2
0
mirror of https://github.com/frappe/books.git synced 2024-11-08 06:44:06 +00:00

feat: invoice returns

This commit is contained in:
akshayitzme 2023-09-23 16:45:22 +05:30
parent 8cac1ef45f
commit a1fc203e8b
5 changed files with 84 additions and 24 deletions

View File

@ -185,7 +185,7 @@ export class BespokeQueries {
static async getReturnBalanceItemsQty(
db: DatabaseCore,
schemaName: string,
schemaName: ModelNameEnum,
docName: string
): Promise<Record<string, ReturnDocItem> | undefined> {
const returnDocNames = (
@ -200,21 +200,41 @@ export class BespokeQueries {
return;
}
const returnedItems: DocItem[] = await db.knex!(`${schemaName}Item`)
.select('item', 'batch', 'serialNumber')
const returnedItemsQuery = db.knex!(`${schemaName}Item`)
.sum({ quantity: 'quantity' })
.whereIn('parent', returnDocNames)
.groupBy('item', 'batch', 'serialNumber');
.whereIn('parent', returnDocNames);
const docItemsQuery = db.knex!(`${schemaName}Item`)
.where('parent', docName)
.sum({ quantity: 'quantity' });
if (
[ModelNameEnum.SalesInvoice, ModelNameEnum.PurchaseInvoice].includes(
schemaName
)
) {
returnedItemsQuery.select('item', 'batch').groupBy('item', 'batch');
docItemsQuery.select('name', 'item', 'batch').groupBy('item', 'batch');
}
if (
[ModelNameEnum.Shipment, ModelNameEnum.PurchaseReceipt].includes(
schemaName
)
) {
returnedItemsQuery
.select('item', 'batch', 'serialNumber')
.groupBy('item', 'batch', 'serialNumber');
docItemsQuery
.select('name', 'item', 'batch', 'serialNumber')
.groupBy('item', 'batch', 'serialNumber');
}
const returnedItems = (await returnedItemsQuery) as DocItem[];
if (!returnedItems.length) {
return;
}
const docItems: DocItem[] = await db.knex!(`${schemaName}Item`)
.select('name', 'item', 'batch', 'serialNumber')
.where('parent', docName)
.groupBy('item', 'batch', 'serialNumber')
.sum({ quantity: 'quantity' });
const docItems = (await docItemsQuery) as DocItem[];
const docItemsMap = BespokeQueries.#getDocItemMap(docItems);
const returnedItemsMap = BespokeQueries.#getDocItemMap(returnedItems);
@ -223,7 +243,6 @@ export class BespokeQueries {
docItemsMap,
returnedItemsMap
);
return returnBalanceItems;
}

View File

@ -1,2 +1,12 @@
export type PaymentType = 'Receive' | 'Pay';
export type PaymentMethod = 'Cash' | 'Cheque' | 'Transfer';
export enum PaymentTypeEnum{
Receive = 'Receive',
Pay = 'Pay'
}
export enum AccountFieldEnum{
Account = 'account',
PaymentAccount = 'paymentAccount'
}

View File

@ -12,14 +12,26 @@ export class PurchaseInvoice extends Invoice {
async getPosting() {
const exchangeRate = this.exchangeRate ?? 1;
const posting: LedgerPosting = new LedgerPosting(this, this.fyo);
await posting.credit(this.account!, this.baseGrandTotal!);
if (this.isReturn) {
await posting.debit(this.account!, this.baseGrandTotal!);
} else {
await posting.credit(this.account!, this.baseGrandTotal!);
}
for (const item of this.items!) {
if (this.isReturn) {
await posting.credit(item.account!, item.amount!.mul(exchangeRate));
continue;
}
await posting.debit(item.account!, item.amount!.mul(exchangeRate));
}
if (this.taxes) {
for (const tax of this.taxes) {
if (this.isReturn) {
await posting.credit(tax.account!, tax.amount!.mul(exchangeRate));
continue;
}
await posting.debit(tax.account!, tax.amount!.mul(exchangeRate));
}
}
@ -28,7 +40,11 @@ export class PurchaseInvoice extends Invoice {
const discountAccount = this.fyo.singles.AccountingSettings
?.discountAccount as string | undefined;
if (discountAccount && discountAmount.isPositive()) {
await posting.credit(discountAccount, discountAmount.mul(exchangeRate));
if (this.isReturn) {
await posting.debit(discountAccount, discountAmount.mul(exchangeRate));
} else {
await posting.credit(discountAccount, discountAmount.mul(exchangeRate));
}
}
await posting.makeRoundOffEntry();

View File

@ -23,6 +23,7 @@ export function getInvoiceActions(
getMakePaymentAction(fyo),
getMakeStockTransferAction(fyo, schemaName),
getLedgerLinkAction(fyo),
getMakeReturnDocAction(fyo),
];
}
@ -166,11 +167,17 @@ export function getMakeReturnDocAction(fyo: Fyo): Action {
label: fyo.t`Return`,
group: fyo.t`Create`,
condition: (doc: Doc) =>
!!fyo.singles.InventorySettings?.enableStockReturns &&
(!!fyo.singles.AccountingSettings?.enableInvoiceReturns ||
!!fyo.singles.InventorySettings?.enableStockReturns) &&
doc.isSubmitted &&
!doc.isReturn,
action: async (doc: Doc) => {
const returnDoc = await (doc as StockTransfer)?.getReturnDoc();
let returnDoc: Invoice | StockTransfer | undefined;
if (doc instanceof Invoice || doc instanceof StockTransfer) {
returnDoc = await doc.getReturnDoc();
}
if (!returnDoc || !returnDoc.name) {
return;
}
@ -297,6 +304,14 @@ function getSubmittableDocStatus(doc: RenderData | Doc) {
}
export function getInvoiceStatus(doc: RenderData | Doc): InvoiceStatus {
if (doc.submitted && !doc.cancelled && doc.returnAgainst) {
return 'Return';
}
if (doc.submitted && !doc.cancelled && doc.isReturned) {
return 'ReturnIssued';
}
if (
doc.submitted &&
!doc.cancelled &&

View File

@ -92,6 +92,14 @@ function getSubmittableStatus(doc: Doc) {
return 'Cancelled';
}
if (doc.returnAgainst && doc.isSubmitted) {
return 'Return';
}
if (doc.isReturned && doc.isSubmitted) {
return 'ReturnIssued';
}
const isInvoice = doc instanceof Invoice;
if (
doc.isSubmitted &&
@ -113,14 +121,6 @@ function getSubmittableStatus(doc: Doc) {
return 'Paid';
}
if (doc.returnAgainst && doc.isSubmitted) {
return 'Return';
}
if (doc.isReturned && doc.isSubmitted) {
return 'ReturnIssued';
}
if (doc.isSubmitted) {
return 'Submitted';
}