mirror of
https://github.com/frappe/books.git
synced 2024-11-10 07:40:55 +00:00
107 lines
2.5 KiB
TypeScript
107 lines
2.5 KiB
TypeScript
|
import frappe from 'frappe';
|
||
|
import { DocValue } from 'frappe/core/types';
|
||
|
import Doc from 'frappe/model/doc';
|
||
|
import {
|
||
|
DependsOnMap,
|
||
|
FiltersMap,
|
||
|
FormulaMap,
|
||
|
ValidationMap,
|
||
|
} from 'frappe/model/types';
|
||
|
import Money from 'pesa/dist/types/src/money';
|
||
|
import { Invoice } from '../Invoice/Invoice';
|
||
|
|
||
|
export abstract class InvoiceItem extends Doc {
|
||
|
account?: string;
|
||
|
baseAmount?: Money;
|
||
|
exchangeRate?: number;
|
||
|
parentdoc?: Invoice;
|
||
|
|
||
|
get isSales() {
|
||
|
return this.schemaName === 'SalesInvoiceItem';
|
||
|
}
|
||
|
|
||
|
formulas: FormulaMap = {
|
||
|
description: () =>
|
||
|
this.parentdoc!.getFrom(
|
||
|
'Item',
|
||
|
this.item as string,
|
||
|
'description'
|
||
|
) as string,
|
||
|
rate: async () => {
|
||
|
const baseRate = ((await this.parentdoc!.getFrom(
|
||
|
'Item',
|
||
|
this.item as string,
|
||
|
'rate'
|
||
|
)) || frappe.pesa(0)) as Money;
|
||
|
|
||
|
return baseRate.div(this.exchangeRate!);
|
||
|
},
|
||
|
baseRate: () =>
|
||
|
(this.rate as Money).mul(this.parentdoc!.exchangeRate as number),
|
||
|
account: () => {
|
||
|
let accountType = 'expenseAccount';
|
||
|
if (this.isSales) {
|
||
|
accountType = 'incomeAccount';
|
||
|
}
|
||
|
return this.parentdoc!.getFrom('Item', this.item as string, accountType);
|
||
|
},
|
||
|
tax: () => {
|
||
|
if (this.tax) {
|
||
|
return this.tax as string;
|
||
|
}
|
||
|
|
||
|
return this.parentdoc!.getFrom(
|
||
|
'Item',
|
||
|
this.item as string,
|
||
|
'tax'
|
||
|
) as string;
|
||
|
},
|
||
|
amount: () => (this.rate as Money).mul(this.quantity as number),
|
||
|
baseAmount: () =>
|
||
|
(this.amount as Money).mul(this.parentdoc!.exchangeRate as number),
|
||
|
hsnCode: () =>
|
||
|
this.parentdoc!.getFrom('Item', this.item as string, 'hsnCode'),
|
||
|
};
|
||
|
|
||
|
dependsOn: DependsOnMap = {
|
||
|
hsnCode: ['item'],
|
||
|
};
|
||
|
|
||
|
validations: ValidationMap = {
|
||
|
rate: async (value: DocValue) => {
|
||
|
if ((value as Money).gte(0)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
throw new frappe.errors.ValidationError(
|
||
|
frappe.t`Rate (${frappe.format(
|
||
|
value,
|
||
|
'Currency'
|
||
|
)}) cannot be less zero.`
|
||
|
);
|
||
|
},
|
||
|
};
|
||
|
|
||
|
static filters: FiltersMap = {
|
||
|
item: (doc: Doc) => {
|
||
|
const itemList = doc.parentdoc!.items as Doc[];
|
||
|
const items = itemList.map((d) => d.item as string).filter(Boolean);
|
||
|
|
||
|
let itemNotFor = 'sales';
|
||
|
if (doc.isSales) {
|
||
|
itemNotFor = 'purchases';
|
||
|
}
|
||
|
|
||
|
const baseFilter = { for: ['not in', [itemNotFor]] };
|
||
|
if (items.length <= 0) {
|
||
|
return baseFilter;
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
name: ['not in', items],
|
||
|
...baseFilter,
|
||
|
};
|
||
|
},
|
||
|
};
|
||
|
}
|