mirror of
https://github.com/frappe/books.git
synced 2026-08-24 02:24:17 -05:00
Merge pull request #1251 from frappe/fix-returned-invoices
fix: filter returned invoices
This commit is contained in:
@@ -26,6 +26,7 @@ export class AccountingSettings extends Doc {
|
||||
enableERPNextSync?: boolean;
|
||||
enablePointOfSaleWithOutInventory?: boolean;
|
||||
enablePartialPayment?: boolean;
|
||||
enableitemGroup?: boolean;
|
||||
|
||||
static filters: FiltersMap = {
|
||||
writeOffAccount: () => ({
|
||||
|
||||
@@ -339,6 +339,10 @@ export abstract class Invoice extends Transactional {
|
||||
for (const details of (tax.details ?? []) as TaxDetail[]) {
|
||||
let amount = item.amount!;
|
||||
|
||||
if (this.isReturn && amount.isPositive()) {
|
||||
amount = amount.neg();
|
||||
}
|
||||
|
||||
if (!this.discountAfterTax) {
|
||||
let itemDiscountAmount = this.getDiscountAmount(item);
|
||||
|
||||
@@ -895,11 +899,21 @@ export abstract class Invoice extends Transactional {
|
||||
this.returnAgainst
|
||||
)) as Invoice;
|
||||
if (sinvreturnedDoc.outstandingAmount?.isZero()) {
|
||||
return this.grandTotal;
|
||||
return this.grandTotal?.abs();
|
||||
} else {
|
||||
return this.grandTotal
|
||||
const totalPaid = this.grandTotal
|
||||
?.abs()
|
||||
.sub(sinvreturnedDoc.outstandingAmount as Money);
|
||||
|
||||
if (!sinvreturnedDoc.isReturn) {
|
||||
return totalPaid?.abs();
|
||||
}
|
||||
|
||||
if (!this.grandTotal?.isNegative()) {
|
||||
this.grandTotal = this.grandTotal?.neg();
|
||||
}
|
||||
|
||||
return this.grandTotal?.add(totalPaid as Money).abs();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -459,6 +459,16 @@ export class Payment extends Transactional {
|
||||
row.referenceName
|
||||
);
|
||||
|
||||
const previousOutstandingAmount = referenceDoc.outstandingAmount as Money;
|
||||
const outstandingAmount = previousOutstandingAmount.sub(row.amount!);
|
||||
await referenceDoc.setAndSync({ outstandingAmount });
|
||||
}
|
||||
}
|
||||
|
||||
async beforeSync(): Promise<void> {
|
||||
await super.beforeSync();
|
||||
|
||||
for (const row of this.for ?? []) {
|
||||
if (!this.fyo.singles.AccountingSettings?.enablePartialPayment) {
|
||||
const amount = !(this.amountPaid as Money).isZero()
|
||||
? (this.amountPaid as Money)
|
||||
@@ -466,7 +476,7 @@ export class Payment extends Transactional {
|
||||
const initialAmount = this.initialAmount as Money;
|
||||
if (amount.lt(initialAmount) && !amount.eq(initialAmount)) {
|
||||
if (this.writeoff?.isZero()) {
|
||||
row.amount = this.initialAmount;
|
||||
this.amount = this.initialAmount;
|
||||
row.amountPaid = this.fyo.pesa(0);
|
||||
throw new ValidationError(
|
||||
this.fyo.t`Enable Partial payment to pay partial amount`
|
||||
@@ -474,10 +484,6 @@ export class Payment extends Transactional {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const previousOutstandingAmount = referenceDoc.outstandingAmount as Money;
|
||||
const outstandingAmount = previousOutstandingAmount.sub(row.amount!);
|
||||
await referenceDoc.setAndSync({ outstandingAmount });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -648,23 +654,13 @@ export class Payment extends Transactional {
|
||||
}
|
||||
|
||||
const reference = this?.for?.[0];
|
||||
if (!reference) {
|
||||
return null;
|
||||
}
|
||||
const refDoc = (await reference.loadAndGetLink(
|
||||
const refDoc = (await reference?.loadAndGetLink(
|
||||
'referenceName'
|
||||
)) as Invoice | null;
|
||||
|
||||
const partyDoc = (await this.loadAndGetLink('party')) as Party;
|
||||
const outstanding = partyDoc.outstandingAmount as Money;
|
||||
|
||||
if (outstanding.isNegative()) {
|
||||
if (this.referenceType === ModelNameEnum.PurchaseInvoice) {
|
||||
return 'Pay';
|
||||
}
|
||||
return 'Receive';
|
||||
}
|
||||
|
||||
if (partyDoc.role === 'Supplier') {
|
||||
if (refDoc?.isReturn) {
|
||||
return 'Receive';
|
||||
|
||||
@@ -180,7 +180,7 @@ test('create SINV return for balance qty', async (t) => {
|
||||
|
||||
t.equals(
|
||||
returnDoc.outstandingAmount?.float,
|
||||
-itemData.rate,
|
||||
itemData.rate,
|
||||
'return doc outstanding amount matches'
|
||||
);
|
||||
});
|
||||
|
||||
@@ -57,13 +57,6 @@
|
||||
"fieldtype": "Check",
|
||||
"section": "Features"
|
||||
},
|
||||
{
|
||||
"fieldname": "enableStockReturns",
|
||||
"label": "Enable Stock Returns",
|
||||
"fieldtype": "Check",
|
||||
"default": false,
|
||||
"section": "Features"
|
||||
},
|
||||
{
|
||||
"fieldname": "enablePointOfSale",
|
||||
"label": "Enable Point of Sale",
|
||||
|
||||
@@ -105,6 +105,7 @@
|
||||
/>
|
||||
|
||||
<Link
|
||||
v-if="fyo.singles.AccountingSettings?.enableitemGroup"
|
||||
:df="{
|
||||
label: t`Filter by Group`,
|
||||
fieldtype: 'Link',
|
||||
|
||||
@@ -466,7 +466,7 @@ export default defineComponent({
|
||||
await this.setItems();
|
||||
},
|
||||
async setItems() {
|
||||
const filters: Record<string, boolean> = {};
|
||||
const filters: Record<string, boolean | string> = {};
|
||||
const itemVisibility = this.fyo.singles.POSSettings?.itemVisibility;
|
||||
const hideUnavailable =
|
||||
this.fyo.singles.POSSettings?.hideUnavailableItems;
|
||||
@@ -477,13 +477,13 @@ export default defineComponent({
|
||||
filters.trackItem = false;
|
||||
}
|
||||
|
||||
const itemGroupfilter = this.selectedItemGroup
|
||||
? { itemGroup: this.selectedItemGroup }
|
||||
: undefined;
|
||||
if (this.selectedItemGroup) {
|
||||
filters.itemGroup = this.selectedItemGroup;
|
||||
}
|
||||
|
||||
const items = (await fyo.db.getAll(ModelNameEnum.Item, {
|
||||
fields: [],
|
||||
filters: itemGroupfilter,
|
||||
filters: filters,
|
||||
})) as Item[];
|
||||
|
||||
this.items = [] as POSItem[];
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
:show-label="true"
|
||||
:border="true"
|
||||
:required="!transferAmount.isZero()"
|
||||
:read-only="false"
|
||||
:value="transferRefNo"
|
||||
@change="(value:string) => $emit('setTransferRefNo', value)"
|
||||
/>
|
||||
@@ -41,6 +42,7 @@
|
||||
:show-label="true"
|
||||
:border="true"
|
||||
:required="!transferAmount.isZero()"
|
||||
:read-only="false"
|
||||
:value="transferClearanceDate"
|
||||
@change="(value:Date) => $emit('setTransferClearanceDate', value)"
|
||||
/>
|
||||
@@ -306,6 +308,10 @@ export default defineComponent({
|
||||
return true;
|
||||
},
|
||||
showPaidChange(): boolean {
|
||||
if (this.sinvDoc.isReturn) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
this.fyo.pesa(this.paidAmount.float).eq(fyo.pesa(0)) &&
|
||||
this.transferAmount.eq(fyo.pesa(0))
|
||||
|
||||
@@ -108,6 +108,7 @@ import { SalesInvoice } from 'models/baseModels/SalesInvoice/SalesInvoice';
|
||||
import { defineComponent, inject } from 'vue';
|
||||
import { ModelNameEnum } from 'models/types';
|
||||
import { Field } from 'schemas/types';
|
||||
import { Money } from 'pesa';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ReturnSalesInvoice',
|
||||
@@ -169,7 +170,7 @@ export default defineComponent({
|
||||
},
|
||||
filteredInvoices() {
|
||||
return this.returnedInvoices.filter((invoice) =>
|
||||
invoice.name
|
||||
(invoice.name as string)
|
||||
.toLowerCase()
|
||||
.includes(this.invoiceSearchTerm.toLowerCase())
|
||||
);
|
||||
@@ -210,11 +211,28 @@ export default defineComponent({
|
||||
});
|
||||
|
||||
const returnedInvoiceNames = allInvoices
|
||||
.filter((inv) => inv.returnAgainst)
|
||||
.map((inv) => inv.returnAgainst);
|
||||
.filter((inv) => {
|
||||
if (inv.isReturned) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.returnedInvoices = allInvoices.filter(
|
||||
(inv) => !inv.returnAgainst && !returnedInvoiceNames.includes(inv.name)
|
||||
if (inv.isReturned && !(inv.outstandingAmount as Money).isZero()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!inv.isReturned && !inv.returnAgainst) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!inv.isReturned && !(inv.outstandingAmount as Money).isZero()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
})
|
||||
.map((inv) => inv.name);
|
||||
this.returnedInvoices = allInvoices.filter((inv) =>
|
||||
returnedInvoiceNames.includes(inv.name)
|
||||
) as SalesInvoice[];
|
||||
},
|
||||
},
|
||||
|
||||
@@ -186,7 +186,7 @@ export async function syncDocumentsFromERPNext(fyo: Fyo) {
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
return await fyo.doc
|
||||
await fyo.doc
|
||||
.getNewDoc(ErrorLogEnum.IntegrationErrorLog, {
|
||||
error: error as string,
|
||||
data: JSON.stringify({ instance: deviceID, records: docsToSync }),
|
||||
@@ -220,9 +220,7 @@ export async function syncDocumentsFromERPNext(fyo: Fyo) {
|
||||
(doc.erpnextDocName as string) || (doc.name as string),
|
||||
newDoc.name as string
|
||||
);
|
||||
} catch (error) {
|
||||
return error;
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user