2
0
mirror of https://github.com/frappe/books.git synced 2024-12-27 20:45:04 +00:00
books/reports/AccountsReceivablePayable/AccountsReceivablePayable.js
2022-01-21 02:27:29 +05:30

171 lines
3.7 KiB
JavaScript

import frappe from 'frappe';
export default class AccountsReceivablePayable {
async run(reportType, { date }) {
const rows = await getReceivablePayable({
reportType,
date,
});
return { rows };
}
}
async function getReceivablePayable({ reportType = 'Receivable', date }) {
let entries = [];
const debitOrCredit = reportType === 'Receivable' ? 'debit' : 'credit';
const referenceType =
reportType === 'Receivable' ? 'SalesInvoice' : 'PurchaseInvoice';
entries = await getLedgerEntries();
const vouchers = await getVouchers();
const futureEntries = getFutureEntries();
const returnEntries = getReturnEntries();
const pdc = getPDC();
const validEntries = getValidEntries();
let data = [];
for (let entry of validEntries) {
const { outStandingAmount, creditNoteAmount } = getOutstandingAmount(entry);
if (outStandingAmount > 0.1 / 10) {
const row = {
date: entry.date,
party: entry.party,
};
// due date / bill date
row.voucherType = entry.referenceType;
row.voucherNo = entry.referenceName;
// bill details
const invoicedAmount = entry[debitOrCredit] || 0;
const paidAmount = invoicedAmount - outStandingAmount - creditNoteAmount;
Object.assign(row, {
invoicedAmount,
paidAmount,
outStandingAmount,
creditNoteAmount,
});
// ageing
data.push(row);
}
}
return data;
// helpers
async function getVouchers() {
return await frappe.db.getAll({
doctype: referenceType,
fields: ['name', 'date'],
filters: {
submitted: 1,
},
});
}
function getValidEntries() {
return entries.filter((entry) => {
return (
entry.date <= date &&
entry.referenceType === referenceType &&
entry[debitOrCredit] > 0
);
});
}
function getOutstandingAmount(entry) {
let paymentAmount = 0.0,
creditNoteAmount = 0.0;
let reverseDebitOrCredit = debitOrCredit === 'debit' ? 'credit' : 'debit';
for (let e of getEntriesFor(
entry.party,
entry.referenceType,
entry.referenceName
)) {
if (e.date <= date) {
const amount = e[reverseDebitOrCredit] - e[debitOrCredit];
if (!Object.keys(returnEntries).includes(e.referenceName)) {
paymentAmount += amount;
} else {
creditNoteAmount += amount;
}
}
}
return {
outStandingAmount:
entry[debitOrCredit] -
entry[reverseDebitOrCredit] -
paymentAmount -
creditNoteAmount,
creditNoteAmount,
};
}
function getEntriesFor(party, againstVoucherType, againstVoucher) {
// TODO
return [];
}
function getFutureEntries() {
return entries.filter((entry) => entry.date > date);
}
function getReturnEntries() {
// TODO
return {};
}
function getPDC() {
return [];
}
async function getLedgerEntries() {
if (entries.length) {
return entries;
}
const partyType = reportType === 'Receivable' ? 'customer' : 'supplier';
const partyList = (
await frappe.db.getAll({
doctype: 'Party',
filters: {
[partyType]: 1,
},
})
).map((d) => d.name);
return await frappe.db.getAll({
doctype: 'AccountingLedgerEntry',
fields: [
'name',
'date',
'account',
'party',
'referenceType',
'referenceName',
'sum(debit) as debit',
'sum(credit) as credit',
],
filters: {
party: ['in', partyList],
},
groupBy: ['referenceType', 'referenceName', 'party'],
orderBy: 'date',
});
}
}