diff --git a/models/baseModels/Invoice/Invoice.ts b/models/baseModels/Invoice/Invoice.ts index b03d9929..2aa675f2 100644 --- a/models/baseModels/Invoice/Invoice.ts +++ b/models/baseModels/Invoice/Invoice.ts @@ -337,7 +337,17 @@ export abstract class Invoice extends Transactional { const tax = await this.getTax(item.tax); for (const details of (tax.details ?? []) as TaxDetail[]) { - const amount = item.amount!; + let amount = item.amount!; + + if (!this.discountAfterTax) { + const itemDiscountAmount = this.getItemDiscountAmount(); + + if (this.isReturn) { + amount = amount.add(itemDiscountAmount); + } else { + amount = amount.sub(itemDiscountAmount); + } + } const taxItem: InvoiceTaxItem = { details, @@ -416,6 +426,11 @@ export abstract class Invoice extends Transactional { const itemDiscountAmount = this.getItemDiscountAmount(); const invoiceDiscountAmount = this.getInvoiceDiscountAmount(); + + if (this.isReturn) { + return itemDiscountAmount.add(invoiceDiscountAmount).neg(); + } + return itemDiscountAmount.add(invoiceDiscountAmount); } @@ -430,7 +445,7 @@ export abstract class Invoice extends Transactional { .map((doc) => doc.amount as Money) .reduce((a, b) => { if (this.isReturn) { - return a.add(b.abs()).neg(); + return a.abs().add(b.abs()).neg(); } return a.add(b.abs()); @@ -473,7 +488,9 @@ export abstract class Invoice extends Transactional { for (const item of this.items) { if (item.setItemDiscountAmount) { discountAmount = discountAmount.add( - item.itemDiscountAmount ?? this.fyo.pesa(0) + (item.itemDiscountAmount ?? this.fyo.pesa(0)).mul( + item.quantity as number + ) ); } else if (!this.discountAfterTax) { if (this.isReturn) { @@ -566,6 +583,7 @@ export abstract class Invoice extends Transactional { } const docData = this.getValidDict(true, true); + docData.pricingRuleDetail = []; const docItems = docData.items as DocValueMap[]; if (!docItems) { diff --git a/src/utils/erpnextSync.ts b/src/utils/erpnextSync.ts index 1934df79..d22e6ef2 100644 --- a/src/utils/erpnextSync.ts +++ b/src/utils/erpnextSync.ts @@ -10,6 +10,8 @@ import { StockMovementItem } from 'models/inventory/StockMovementItem'; import { getRandomString } from '../../utils'; import { ErrorLogEnum } from 'fyo/telemetry/types'; import { ValidationError } from 'fyo/utils/errors'; +import { PricingRule } from 'models/baseModels/PricingRule/PricingRule'; +import { PricingRuleItem } from 'models/baseModels/PricingRuleItem/PricingRuleItem'; export async function registerInstanceToERPNext(fyo: Fyo) { if (!navigator.onLine) { @@ -153,10 +155,12 @@ export async function syncDocumentsFromERPNext(fyo: Fyo) { (doc.fbooksDocName as string) || (doc.name as string) ); + doc.name = doc.fbooksDocName ?? doc.name; doc = checkDocDataTypes(fyo, doc) as DocValueMap; await existingDoc.setMultiple(doc); await performPreSync(fyo, doc); + await appendDocValues(existingDoc as DocValueMap, doc); existingDoc._addDocToSyncQueue = false; await existingDoc.sync(); @@ -175,7 +179,7 @@ export async function syncDocumentsFromERPNext(fyo: Fyo) { token, deviceID, doc, - doc.name as string, + (doc.erpnextDocName as string) || (doc.name as string), doc.name as string ); continue; @@ -213,7 +217,7 @@ export async function syncDocumentsFromERPNext(fyo: Fyo) { token, deviceID, doc, - doc.name as string, + (doc.erpnextDocName as string) || (doc.name as string), newDoc.name as string ); } catch (error) { @@ -231,6 +235,36 @@ async function appendDocValues(newDoc: DocValueMap, doc: DocValueMap) { conversionFactor: uomDoc.conversionFactor, }); } + + case ModelNameEnum.PricingRule: + const itemSet = new Set(); + + (newDoc as Doc).appliedItems = ( + newDoc as PricingRule + ).appliedItems?.filter((row: PricingRuleItem) => { + const key = `${row.item as string}::${row.unit as string}`; + + if (itemSet.has(key)) { + return false; + } + + itemSet.add(key); + return true; + }); + + const docItemSet = new Set( + (doc as PricingRule).appliedItems?.map( + (row: PricingRuleItem) => + `${row.item as string}::${row.unit as string}` + ) || [] + ); + + (newDoc as PricingRule).appliedItems = ( + newDoc as PricingRule + ).appliedItems?.filter((row: PricingRuleItem) => + docItemSet.has(`${row.item as string}::${row.unit as string}`) + ); + break; } } @@ -573,8 +607,28 @@ function checkDocDataTypes( doc: DocValueMap | Doc ): DocValueMap | Doc { switch (doc.doctype) { - case ModelNameEnum.Item: + case ModelNameEnum.Item: { const fields = ['rate']; + + const updatedDoc = changeDocDataType( + fyo, + doc, + fields, + ModelNameEnum.Currency + ); + + return updatedDoc; + } + + case ModelNameEnum.PricingRule: { + const fields = [ + 'minAmount', + 'maxAmount', + 'discountAmount', + 'discountRate', + 'freeItemRate', + ]; + const updatedDoc = changeDocDataType( fyo, doc, @@ -582,6 +636,8 @@ function checkDocDataTypes( ModelNameEnum.Currency ); return updatedDoc; + } + default: return doc; } @@ -591,6 +647,7 @@ function isValidSyncableDocName(doctype: string): boolean { const syncableDocNames = [ ModelNameEnum.Item, ModelNameEnum.Batch, + ModelNameEnum.PricingRule, ] as string[]; if (syncableDocNames.includes(doctype)) { diff --git a/src/utils/pos.ts b/src/utils/pos.ts index bdad43d1..20dec8e4 100644 --- a/src/utils/pos.ts +++ b/src/utils/pos.ts @@ -56,7 +56,9 @@ export function getItemDiscounts(items: SalesInvoiceItem[]): Money { for (const item of items) { if (item.setItemDiscountAmount) { if (!item.itemDiscountAmount?.isZero()) { - itemDiscounts = itemDiscounts.add(item.itemDiscountAmount as Money); + itemDiscounts = itemDiscounts.add( + (item.itemDiscountAmount as Money).mul(item.quantity as number) + ); } } else { if (item.amount && (item.itemDiscountPercent as number) > 1) {