fix: implement complete partial payment handling

This commit is contained in:
suhailanzar
2025-06-11 15:12:32 +05:30
parent efd55be1b1
commit 51a2901c9b
5 changed files with 52 additions and 13 deletions
@@ -25,6 +25,7 @@ export class AccountingSettings extends Doc {
enablePricingRule?: boolean;
enableERPNextSync?: boolean;
enablePointOfSaleWithOutInventory?: boolean;
enablePartialPayment?: boolean;
static filters: FiltersMap = {
writeOffAccount: () => ({
+4 -1
View File
@@ -838,7 +838,10 @@ export abstract class Invoice extends Transactional {
if (sinvreturnedDoc.outstandingAmount?.isZero()) {
return this.grandTotal;
} else {
return this.fyo.pesa(0);
const returnAmount = this.grandTotal
?.abs()
.sub(sinvreturnedDoc.outstandingAmount as Money);
return returnAmount;
}
}
+34 -8
View File
@@ -42,6 +42,7 @@ export class Payment extends Transactional {
referenceType?: ModelNameEnum.SalesInvoice | ModelNameEnum.PurchaseInvoice;
for?: PaymentFor[];
_accountsMap?: AccountTypeMap;
initialAmount?: Money;
async paymentMethodDoc() {
return (await this.loadAndGetLink('paymentMethod')) as PaymentMethod;
@@ -112,6 +113,7 @@ export class Payment extends Transactional {
}
await this.validateFor();
this.validatePartialAmount();
this.validateAccounts();
this.validateTotalReferenceAmount();
await this.validateReferences();
@@ -445,6 +447,24 @@ export class Payment extends Transactional {
throw new ValidationError(message);
}
validatePartialAmount() {
if (!this.fyo.singles.AccountingSettings?.enablePartialPayment) {
const amount =
(this.amountPaid as Money)?.isZero?.() === false
? (this.amountPaid as Money)
: (this.amount as Money);
const initialAmount = this.initialAmount as Money;
if (amount.lt(initialAmount) && !amount.eq(initialAmount)) {
if (this.writeoff?.isZero()) {
this.amount = this.initialAmount;
throw new ValidationError(
this.fyo.t`Enable Partial payment to pay partial amount`
);
}
}
}
}
async afterSubmit() {
await super.afterSubmit();
await this.updateReferenceDocOutstanding();
@@ -703,17 +723,23 @@ export class Payment extends Transactional {
return;
}
const amount = (this.getSum('for', 'amount', false) as Money).abs();
if ((value as Money).gt(amount)) {
if (!this.initialAmount) {
this.initialAmount = this.amount as Money;
}
const moneyValue = value as Money;
if (moneyValue.gt(this.initialAmount)) {
throw new ValidationError(
this.fyo.t`Payment amount cannot
exceed ${this.fyo.format(amount, 'Currency')}.`
this.fyo.t`Payment amount cannot exceed ${this.fyo.format(
this.initialAmount,
'Currency'
)}.`
);
} else if ((value as Money).isZero()) {
} else if (moneyValue.isZero()) {
throw new ValidationError(
this.fyo.t`Payment amount cannot
be ${this.fyo.format(value, 'Currency')}.`
this.fyo.t`Payment amount cannot be ${this.fyo.format(
moneyValue,
'Currency'
)}.`
);
}
},
@@ -115,10 +115,12 @@ export class SalesInvoice extends Invoice {
((value as number) || 0) *
((loyaltyProgramDoc?.conversionFactor as number) || 0);
if (this.grandTotal?.lt(loyaltyPoint)) {
throw new ValidationError(
t`no need ${value as number} points to purchase this item`
);
if (!this.isReturn) {
if (this.grandTotal?.lt(loyaltyPoint)) {
throw new ValidationError(
t`no need ${value as number} points to purchase this item`
);
}
}
},
};
+7
View File
@@ -142,6 +142,13 @@
"default": false,
"section": "Features"
},
{
"fieldname": "enablePartialPayment",
"label": "Enable Partial Payment",
"fieldtype": "Check",
"default": false,
"section": "Features"
},
{
"fieldname": "fiscalYearStart",
"label": "Fiscal Year Start Date",