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:
parent
8cac1ef45f
commit
a1fc203e8b
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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'
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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 &&
|
||||
|
@ -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';
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user