2
0
mirror of https://github.com/frappe/books.git synced 2024-09-20 11:29:00 +00:00
books/models/baseModels/InvoiceItem/InvoiceItem.ts
18alantom 591e7b3163 incr: complete typing models
- fix model exports
- add a README for models base
2022-05-23 16:18:22 +05:30

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,
};
},
};
}