diff --git a/backend/database/bespoke.ts b/backend/database/bespoke.ts index 92315508..bd5cc50d 100644 --- a/backend/database/bespoke.ts +++ b/backend/database/bespoke.ts @@ -75,10 +75,50 @@ export class BespokeQueries { outflow: 'credit', }) .select({ - 'month-year': dateAsMonthYear, + yearmonth: dateAsMonthYear, }) .where('account', 'in', cashAndBankAccounts) .whereBetween('date', [fromDate, toDate]) .groupBy(dateAsMonthYear); } + + static async getIncomeAndExpenses( + db: DatabaseCore, + fromDate: string, + toDate: string + ) { + const income = await db.knex!.raw( + ` + select sum(credit - debit) as balance, strftime('%Y-%m', date) as yearmonth + from AccountingLedgerEntry + where + reverted = false and + date between date(?) and date(?) and + account in ( + select name + from Account + where rootType = 'Income' + ) + group by yearmonth`, + [fromDate, toDate] + ); + + const expense = await db.knex!.raw( + ` + select sum(debit - credit) as balance, strftime('%Y-%m', date) as yearmonth + from AccountingLedgerEntry + where + reverted = false and + date between date(?) and date(?) and + account in ( + select name + from Account + where rootType = 'Expense' + ) + group by yearmonth`, + [fromDate, toDate] + ); + + return { income, expense }; + } } diff --git a/fyo/core/dbHandler.ts b/fyo/core/dbHandler.ts index 9a725684..65e5a5e1 100644 --- a/fyo/core/dbHandler.ts +++ b/fyo/core/dbHandler.ts @@ -17,7 +17,9 @@ import { // Return types of Bespoke Queries type TopExpenses = { account: string; total: number }[]; type TotalOutstanding = { total: number; outstanding: number }; -type Cashflow = { inflow: number; outflow: number; 'month-year': string }[]; +type Cashflow = { inflow: number; outflow: number; yearmonth: string }[]; +type Balance = { balance: number; yearmonth: string }[]; +type IncomeExpense = { income: Balance; expense: Balance }; export class DatabaseHandler extends DatabaseBase { #fyo: Fyo; @@ -252,6 +254,17 @@ export class DatabaseHandler extends DatabaseBase { )) as Cashflow; } + async getIncomeAndExpenses( + fromDate: string, + toDate: string + ): Promise { + return (await this.#demux.callBespoke( + 'getIncomeAndExpenses', + fromDate, + toDate + )) as IncomeExpense; + } + /** * Internal methods */ diff --git a/reports/AccountsReceivablePayable/AccountsReceivablePayable.js b/reports/AccountsReceivablePayable/AccountsReceivablePayable.js deleted file mode 100644 index 614c0c84..00000000 --- a/reports/AccountsReceivablePayable/AccountsReceivablePayable.js +++ /dev/null @@ -1,170 +0,0 @@ -import fyo from 'fyo'; - -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 fyo.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 fyo.db.getAll({ - doctype: 'Party', - filters: { - [partyType]: 1, - }, - }) - ).map((d) => d.name); - - return await fyo.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', - }); - } -} diff --git a/reports/BankReconciliation/BankReconciliation.js b/reports/BankReconciliation/BankReconciliation.js deleted file mode 100644 index 4540f16b..00000000 --- a/reports/BankReconciliation/BankReconciliation.js +++ /dev/null @@ -1,54 +0,0 @@ -import { fyo } from 'src/initFyo' - -class BankReconciliation { - async run(params) { - if (!Object.keys(params).length) return []; - - const filters = {}; - if (params.paymentAccount) filters.paymentAccount = params.paymentAccount; - if (params.party) filters.party = params.party; - if (params.toDate || params.fromDate) { - filters.date = []; - if (params.toDate) filters.date.push('<=', params.toDate); - if (params.fromDate) filters.date.push('>=', params.fromDate); - } - - filters.paymentMethod = ['in', ['Cheque', 'Transfer']]; - - let data = await fyo.db.getAll({ - doctype: 'Payment', - fields: [ - 'date', - 'account', - 'paymentAccount', - 'party', - 'name', - 'referenceDate', - 'referenceId', - 'clearanceDate', - ], - filters: filters, - }); - - for (var i = 0; i < data.length; i++) { - let ledger = await fyo.db.getAll({ - doctype: 'AccountingLedgerEntry', - fields: ['date', 'referenceType', 'referenceName', 'debit', 'credit'], - filters: { - referenceType: 'Payment', - account: data[i].paymentAccount, - referenceName: data[i].name, - }, - }); - data[i].credit = ledger[0].credit; - data[i].debit = ledger[0].debit; - data[i].debit = ledger[0].debit; - data[i].referenceName = ledger[0].referenceName; - data[i].referenceType = ledger[0].referenceType; - } - - return data; - } -} - -export default BankReconciliation; diff --git a/reports/BankReconciliation/BankReconciliationImport.js b/reports/BankReconciliation/BankReconciliationImport.js deleted file mode 100644 index b407f713..00000000 --- a/reports/BankReconciliation/BankReconciliationImport.js +++ /dev/null @@ -1,89 +0,0 @@ -import csv2json from 'csvjson-csv2json'; -import { fyo } from 'src/initFyo'; -import ReconciliationValidation from '../../src/components/ReconciliationValidation'; - -export const fileImportHandler = (file, report) => { - const reader = new FileReader(); - reader.onload = () => { - const csv = reader.result; - const json = csvToJsonHandler(csv); - findMatchingReferences(json, report); - }; - reader.readAsBinaryString(file); -}; - -export const csvToJsonHandler = (csv) => { - const json = csv2json(csv, { parseNumbers: true }); - return json; -}; - -export const findMatchingReferences = async (json, report) => { - const referenceField = Object.keys(json[0]).filter((field) => { - return field.toLowerCase().indexOf('ref') > -1 ? true : false; - }); - const clearanceDateField = Object.keys(json[0]).filter((field) => { - return field.toLowerCase().indexOf('date') > -1 ? true : false; - }); - const debitField = Object.keys(json[0]).filter((field) => { - return field.toLowerCase().indexOf('debit') > -1 || - field.toLowerCase().indexOf('deposit') > -1 - ? true - : false; - }); - const creditField = Object.keys(json[0]).filter((field) => { - return field.toLowerCase().indexOf('credit') > -1 || - field.toLowerCase().indexOf('withdraw') > -1 - ? true - : false; - }); - const balanceField = Object.keys(json[0]).filter((field) => { - return field.toLowerCase().indexOf('balance') > -1 ? true : false; - }); - const references = json.map((row) => { - return row[referenceField]; - }); - const payments = await fyo.db.getAll({ - doctype: 'Payment', - fields: ['*'], - filters: { - referenceId: ['in', references], - paymentAccount: report.currentFilters.paymentAccount, - clearanceDate: ['in', [null, undefined, '']], - }, - }); - if (payments.length) { - const entries = payments.map((payment) => { - const jsonEntry = json.filter((row) => { - return row[referenceField] === payment.referenceId; - }); - return Object.assign(payment, jsonEntry[0]); - }); - const normalizedEntries = entries.map((entry) => { - return { - 'Posting Date': fyo.format(entry.date, 'Date'), - 'Payment Entry': entry.name, - 'Ref/Cheq. ID': entry[referenceField], - 'Cr/Dr': - fyo.parseNumber(entry[debitField]) > 0 - ? entry[debitField] + ' Dr.' - : entry[creditField] + ' Cr.', - 'Clearance Date': entry[clearanceDateField], - }; - }); - report.$modal.show({ - modalProps: { - title: `Validate Matching Entries`, - noFooter: true, - }, - component: ReconciliationValidation, - props: { - entries: normalizedEntries, - afterReconcile: async () => { - await report.getReportData(report.currentFilters); - }, - }, - }); - } else { - // 'No entries found with matching Ref / Cheque ID' - } -}; diff --git a/reports/BankReconciliation/viewConfig.js b/reports/BankReconciliation/viewConfig.js deleted file mode 100644 index 9524cc66..00000000 --- a/reports/BankReconciliation/viewConfig.js +++ /dev/null @@ -1,122 +0,0 @@ -const title = 'Bank Reconciliation'; -import { t } from 'fyo'; -import ImportWizard from '../../src/components/ImportWizart'; -import BankReconciliationImport from './BankReconciliationImport'; - -export default { - title: title, - method: 'bank-reconciliation', - filterFields: [ - { - fieldtype: 'Link', - target: 'Account', - size: 'small', - placeholder: t`Payment Account`, - label: t`Payment Account`, - fieldname: 'paymentAccount', - getFilters: () => { - return { - accountType: 'Bank', - isGroup: 0, - }; - }, - }, - { - fieldtype: 'Link', - target: 'Party', - size: 'small', - label: t`Party`, - placeholder: t`Party`, - fieldname: 'party', - }, - { - fieldtype: 'Date', - size: 'small', - placeholder: t`From Date`, - label: t`From Date`, - fieldname: 'fromDate', - }, - { - fieldtype: 'Date', - size: 'small', - placeholder: t`To Date`, - label: t`To Date`, - fieldname: 'toDate', - }, - ], - actions: [ - { - label: t`Reconcile`, - type: 'secondary', - condition: (report) => report.currentFilters.paymentAccount, - action: async (report) => { - report.$modal.show({ - modalProps: { - title: `Import Bank Account Statement`, - noFooter: true, - }, - component: ImportWizard, - props: { - importHandler: BankReconciliationImport.fileImportHandler, - report, - }, - }); - }, - }, - ], - getColumns() { - return [ - { - label: t`Posting Date`, - fieldtype: 'Date', - fieldname: 'date', - }, - { - label: t`Payment Account`, - fieldtype: 'Link', - }, - { - label: t`Debit`, - fieldtype: 'Currency', - }, - { - label: t`Credit`, - fieldtype: 'Currency', - }, - { - label: t`Balance`, - fieldtype: 'Currency', - }, - { - label: t`Ref/Cheque ID`, - fieldtype: 'Data', - fieldname: 'referenceId', - }, - { - label: t`Clearance Date`, - fieldtype: 'Date', - fieldname: 'clearanceDate', - }, - { - label: t`Ref. Type`, - fieldtype: 'Data', - fieldname: 'referenceType', - }, - { - label: t`Ref. Name`, - fieldtype: 'Data', - fieldname: 'referenceName', - }, - { - label: t`Ref. Date`, - fieldtype: 'Date', - fieldname: 'referenceDate', - }, - - { - label: t`Party`, - fieldtype: 'Link', - }, - ]; - }, -}; diff --git a/reports/FinancialStatements/financialStatements.ts b/reports/FinancialStatements/financialStatements.ts deleted file mode 100644 index 24185928..00000000 --- a/reports/FinancialStatements/financialStatements.ts +++ /dev/null @@ -1,426 +0,0 @@ -import { Fyo } from 'fyo'; -import { DocValueMap } from 'fyo/core/types'; -import { DateTime } from 'luxon'; -import { AccountRootType } from 'models/baseModels/Account/types'; -import Money from 'pesa/dist/types/src/money'; -import { - BalanceType, - FinancialStatementOptions, - Periodicity, -} from 'reports/types'; -import { convertPesaValuesToFloat } from 'src/utils'; - -interface FiscalYear { - start: string; - end: string; - quarters: number[]; - isSplit: number; -} - -interface AccountInfo extends DocValueMap { - name: string; - parentAccount: string; - isGroup: boolean; - account?: string; - indent?: number; -} - -interface LedgerInfo extends DocValueMap { - account: string; - debit: Money; - credit: Money; - date: string; -} - -export class FinancialStatements { - fyo: Fyo; - constructor(fyo: Fyo) { - this.fyo = fyo; - } - - async getData(options: FinancialStatementOptions) { - const rootType = options.rootType; - const balanceMustBe = options.balanceMustBe ?? 'Debit'; - const fromDate = options.fromDate; - const toDate = options.toDate; - const periodicity = options.periodicity ?? 'Monthly'; - const accumulateValues = options.accumulateValues ?? false; - - const accounts = await this.getAccounts(rootType); - const fiscalYear = await getFiscalYear(this.fyo); - const ledgerEntries = await this.getLedgerEntries( - fromDate, - toDate, - accounts - ); - const periodList = getPeriodList(fromDate, toDate, periodicity, fiscalYear); - this.setPeriodAmounts( - accounts, - ledgerEntries, - periodicity, - fiscalYear, - balanceMustBe - ); - - if (accumulateValues) { - this.accumulateValues(accounts, periodList); - } - - const totalRow = this.getTotalRow( - rootType, - balanceMustBe, - periodList, - accounts - ); - accounts.forEach(convertPesaValuesToFloat); - - return { accounts, totalRow, periodList }; - } - - setPeriodAmounts( - accounts: AccountInfo[], - ledgerEntries: LedgerInfo[], - periodicity: Periodicity, - fiscalYear: FiscalYear, - balanceMustBe: BalanceType - ) { - for (const account of accounts) { - const entries = ledgerEntries.filter( - (entry) => entry.account === account.name - ); - - for (const entry of entries) { - const periodKey = getPeriodKey(entry.date, periodicity, fiscalYear); - - if (account[periodKey] === undefined) { - account[periodKey] = this.fyo.pesa(0.0); - } - - const multiplier = balanceMustBe === 'Debit' ? 1 : -1; - const value = entry.debit.sub(entry.credit).mul(multiplier); - account[periodKey] = value.add(account[periodKey] as Money); - } - } - } - - getTotalRow( - rootType: AccountRootType, - balanceMustBe: BalanceType, - periodList: string[], - accounts: AccountInfo[] - ) { - const totalRow: DocValueMap = { - account: `Total ${rootType} (${balanceMustBe})`, - }; - - periodList.forEach((periodKey) => { - if (totalRow[periodKey] === undefined) { - totalRow[periodKey] = this.fyo.pesa(0.0); - } - - for (const account of accounts) { - totalRow[periodKey] = (totalRow[periodKey] as Money).add( - (account[periodKey] as Money) ?? 0.0 - ); - } - }); - - convertPesaValuesToFloat(totalRow); - return totalRow; - } - - async accumulateValues(accounts: AccountInfo[], periodList: string[]) { - periodList.forEach((periodKey, i) => { - if (i === 0) { - return; - } - - const previousPeriodKey = periodList[i - 1]; - - for (const account of accounts) { - if (!account[periodKey]) { - account[periodKey] = this.fyo.pesa(0.0); - } - - account[periodKey] = (account[periodKey] as Money).add( - (account[previousPeriodKey] as Money | undefined) ?? 0 - ); - } - }); - } - - async getAccounts(rootType: AccountRootType) { - let accounts = (await this.fyo.db.getAll('Account', { - fields: ['name', 'parentAccount', 'isGroup'], - filters: { - rootType, - }, - })) as AccountInfo[]; - - accounts = setIndentLevel(accounts); - accounts = sortAccounts(accounts); - - accounts.forEach((account) => { - account.account = account.name; - }); - - return accounts; - } - - async getLedgerEntries( - fromDate: string | null, - toDate: string, - accounts: AccountInfo[] - ) { - const accountFilter = ['in', accounts.map((d) => d.name)]; - let dateFilter: string[] = ['<=', toDate]; - if (fromDate) { - dateFilter = ['>=', fromDate, '<=', toDate]; - } - - const ledgerEntries = (await this.fyo.db.getAll('AccountingLedgerEntry', { - fields: ['account', 'debit', 'credit', 'date'], - filters: { - account: accountFilter, - date: dateFilter, - }, - })) as LedgerInfo[]; - - return ledgerEntries; - } - - async getTrialBalance(options: FinancialStatementOptions) { - const { rootType, fromDate, toDate } = options; - const accounts = await this.getAccounts(rootType); - const ledgerEntries = await this.getLedgerEntries(null, toDate, accounts); - - for (const account of accounts) { - const accountEntries = ledgerEntries.filter( - (entry) => entry.account === account.name - ); - // opening - const beforePeriodEntries = accountEntries.filter( - (entry) => entry.date < fromDate - ); - - account.opening = beforePeriodEntries.reduce( - (acc, entry) => acc.add(entry.debit).sub(entry.credit), - this.fyo.pesa(0) - ); - - if (account.opening.gte(0)) { - account.openingDebit = account.opening; - account.openingCredit = this.fyo.pesa(0); - } else { - account.openingCredit = account.opening.neg(); - account.openingDebit = this.fyo.pesa(0); - } - - // debit / credit - const periodEntries = accountEntries.filter( - (entry) => entry.date >= fromDate && entry.date < toDate - ); - account.debit = periodEntries.reduce( - (acc, entry) => acc.add(entry.debit), - this.fyo.pesa(0) - ); - account.credit = periodEntries.reduce( - (acc, entry) => acc.add(entry.credit), - this.fyo.pesa(0) - ); - - // closing - account.closing = account.opening.add(account.debit).sub(account.credit); - - if (account.closing.gte(0)) { - account.closingDebit = account.closing; - account.closingCredit = this.fyo.pesa(0); - } else { - account.closingCredit = account.closing.neg(); - account.closingDebit = this.fyo.pesa(0); - } - - if (account.debit.neq(0) || account.credit.neq(0)) { - setParentEntry(account, account.parentAccount); - } - } - - function setParentEntry(leafAccount: AccountInfo, parentName: string) { - for (const acc of accounts) { - if (acc.name === parentName) { - acc.debit = (acc.debit as Money).add(leafAccount.debit as Money); - acc.credit = (acc.credit as Money).add(leafAccount.credit as Money); - acc.closing = (acc.opening as Money).add(acc.debit).sub(acc.credit); - - if (acc.closing.gte(0)) { - acc.closingDebit = acc.closing; - } else { - acc.closingCredit = acc.closing.neg(); - } - - if (acc.parentAccount) { - setParentEntry(leafAccount, acc.parentAccount); - } else { - return; - } - } - } - } - - accounts.forEach(convertPesaValuesToFloat); - return accounts; - } -} - -function setIndentLevel( - accounts: AccountInfo[], - parentAccount?: string | null, - level?: number -): AccountInfo[] { - if (parentAccount === undefined) { - parentAccount = null; - level = 0; - } - - accounts.forEach((account) => { - if ( - account.parentAccount === parentAccount && - account.indent === undefined - ) { - account.indent = level; - setIndentLevel(accounts, account.name, (level ?? 0) + 1); - } - }); - - return accounts; -} - -function sortAccounts(accounts: AccountInfo[]) { - const out: AccountInfo[] = []; - const pushed: Record = {}; - - pushToOut(null); - - function pushToOut(parentAccount: string | null) { - accounts.forEach((account) => { - if (pushed[account.name] && account.parentAccount !== parentAccount) { - return; - } - - out.push(account); - pushed[account.name] = true; - - pushToOut(account.name); - }); - } - - return out; -} - -export function getPeriodList( - fromDate: string, - toDate: string, - periodicity: Periodicity, - fiscalYear: FiscalYear -) { - if (!fromDate) { - fromDate = fiscalYear.start; - } - - const monthsToAdd = { - Monthly: 1, - Quarterly: 3, - 'Half Yearly': 6, - Yearly: 12, - }[periodicity]; - - const startDate = DateTime.fromISO(fromDate).startOf('month'); - const endDate = DateTime.fromISO(toDate).endOf('month'); - let curDate = startDate; - const periodKeyList: string[] = []; - - while (curDate <= endDate) { - const periodKey = getPeriodKey(curDate, periodicity, fiscalYear); - periodKeyList.push(periodKey); - curDate = curDate.plus({ months: monthsToAdd }); - } - - return periodKeyList; -} - -function getPeriodKey( - dateObj: DateTime | string, - periodicity: Periodicity, - fiscalYear: FiscalYear -) { - if (typeof dateObj === 'string') { - dateObj = DateTime.fromISO(dateObj); - } - - const { start, quarters, isSplit } = fiscalYear; - const { month, year } = dateObj; - const fisacalStart = DateTime.fromISO(start); - - if (periodicity === 'Monthly') { - return `${dateObj.monthShort} ${year}`; - } - - if (periodicity === 'Quarterly') { - const key = - month < fisacalStart.month - ? `${year - 1} - ${year}` - : `${year} - ${year + 1}`; - const strYear = isSplit ? key : `${year}`; - return { - 1: `Q1 ${strYear}`, - 2: `Q2 ${strYear}`, - 3: `Q3 ${strYear}`, - 4: `Q4 ${strYear}`, - }[quarters[month - 1]] as string; - } - - if (periodicity === 'Half Yearly') { - const key = - month < fisacalStart.month - ? `${year - 1} - ${year}` - : `${year} - ${year + 1}`; - const strYear = isSplit ? key : `${year}`; - return { - 1: `1st Half ${strYear}`, - 2: `1st Half ${strYear}`, - 3: `2nd Half ${strYear}`, - 4: `2nd Half ${strYear}`, - }[quarters[month - 1]] as string; - } - - const key = - month < fisacalStart.month - ? `${year - 1} - ${year}` - : `${year} - ${year + 1}`; - const strYear = isSplit ? key : `${year}`; - return `FY ${strYear}`; -} - -export async function getFiscalYear(fyo: Fyo): Promise { - const accountingSettings = await fyo.doc.getSingle('AccountingSettings'); - - const fiscalYearStart = accountingSettings.fiscalYearStart as string; - const fiscalYearEnd = accountingSettings.fiscalYearEnd as string; - - //right now quaters received from luxon lib is fixed to Jan as starting quarter - //moving the financial quarters, according to of start of fiscal year month - const quarters = [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4]; - const start = DateTime.fromISO(fiscalYearStart); - quarters.unshift(...quarters.splice(13 - start.month, 11)); - - //check if fiscal year ends in next year - const end = DateTime.fromISO(fiscalYearEnd); - const isFiscalSplit = start.year - end.year; - - return { - start: fiscalYearStart, - end: fiscalYearEnd, - quarters: quarters, - isSplit: isFiscalSplit, - }; -} diff --git a/reports/PurchaseRegister/PurchaseRegister.js b/reports/PurchaseRegister/PurchaseRegister.js deleted file mode 100644 index 8210d8cc..00000000 --- a/reports/PurchaseRegister/PurchaseRegister.js +++ /dev/null @@ -1,56 +0,0 @@ -import { fyo } from 'src/initFyo'; - -class PurchaseRegister { - async run({ fromDate, toDate, supplier }) { - if (!fromDate && !toDate && !supplier) return { rows: [] }; - - let filters = {}; - if (supplier) { - filters.supplier = supplier; - } - - if (fromDate && toDate) { - filters.date = ['>=', fromDate, '<=', toDate]; - } else if (fromDate) { - filters.date = ['>=', fromDate]; - } else if (toDate) { - filters.date = ['<=', toDate]; - } - filters.submitted = 1; - - const bills = await fyo.db.getAll({ - doctype: 'PurchaseInvoice', - fields: ['name', 'date', 'supplier', 'account', 'netTotal', 'grandTotal'], - filters, - orderBy: 'date', - order: 'desc', - }); - - const billNames = bills.map((d) => d.name); - - const taxes = await fyo.db.getAll({ - doctype: 'TaxSummary', - fields: ['parent', 'amount'], - filters: { - parenttype: 'PurchaseInvoice', - parent: ['in', billNames], - }, - orderBy: 'name', - }); - - for (let bill of bills) { - bill.totalTax = taxes - .filter((tax) => tax.parent === bill.name) - .reduce((acc, tax) => { - if (tax.amount) { - acc = acc + tax.amount; - } - return acc; - }, 0); - } - - return { rows: bills }; - } -} - -export default PurchaseRegister; diff --git a/reports/PurchaseRegister/viewConfig.js b/reports/PurchaseRegister/viewConfig.js deleted file mode 100644 index 2434667e..00000000 --- a/reports/PurchaseRegister/viewConfig.js +++ /dev/null @@ -1,56 +0,0 @@ -const title = 'Purchase Register'; -import { t } from 'fyo'; - -export default { - title: title, - method: 'purchase-register', - filterFields: [ - { - fieldtype: 'Link', - target: 'Party', - label: t`Supplier Name`, - fieldname: 'supplier', - size: 'small', - placeholder: t`Supplier Name`, - getFilters: (query) => { - if (query) - return { - keywords: ['like', query], - supplier: 1, - }; - - return { - supplier: 1, - }; - }, - }, - { - fieldtype: 'Date', - fieldname: 'fromDate', - size: 'small', - placeholder: t`From Date`, - label: t`From Date`, - required: 1, - }, - { - fieldtype: 'Date', - size: 'small', - placeholder: t`To Date`, - fieldname: 'toDate', - label: t`To Date`, - required: 1, - }, - ], - actions: [], - getColumns() { - return [ - { label: t`PurchaseInvoice`, fieldname: 'name' }, - { label: t`Posting Date`, fieldname: 'date' }, - { label: t`Supplier`, fieldname: 'supplier' }, - { label: t`Payable Account`, fieldname: 'account' }, - { label: t`Net Total`, fieldname: 'netTotal', fieldtype: 'Currency' }, - { label: t`Total Tax`, fieldname: 'totalTax', fieldtype: 'Currency' }, - { label: t`Grand Total`, fieldname: 'grandTotal', fieldtype: 'Currency' }, - ]; - }, -}; diff --git a/reports/SalesRegister/SalesRegister.js b/reports/SalesRegister/SalesRegister.js deleted file mode 100644 index d0d23bef..00000000 --- a/reports/SalesRegister/SalesRegister.js +++ /dev/null @@ -1,55 +0,0 @@ -import { fyo } from 'src/initFyo'; - -class SalesRegister { - async run({ fromDate, toDate, customer }) { - if (!fromDate && !toDate && !customer) return { rows: [] }; - - let filters = {}; - if (customer) { - filters.customer = customer; - } - - if (fromDate && toDate) { - filters.date = ['>=', fromDate, '<=', toDate]; - } else if (fromDate) { - filters.date = ['>=', fromDate]; - } else if (toDate) { - filters.date = ['<=', toDate]; - } - - const invoices = await fyo.db.getAll({ - doctype: 'SalesInvoice', - fields: ['name', 'date', 'customer', 'account', 'netTotal', 'grandTotal'], - filters: filters, - orderBy: 'date', - order: 'desc', - }); - - const invoiceNames = invoices.map((d) => d.name); - - const taxes = await fyo.db.getAll({ - doctype: 'TaxSummary', - fields: ['parent', 'amount'], - filters: { - parenttype: 'Invoice', - parent: ['in', invoiceNames], - }, - orderBy: 'name', - }); - - for (let invoice of invoices) { - invoice.totalTax = taxes - .filter((tax) => tax.parent === invoice.name) - .reduce((acc, tax) => { - if (tax.amount) { - acc = acc + tax.amount; - } - return acc; - }, 0); - } - - return { rows: invoices }; - } -} - -export default SalesRegister; diff --git a/reports/SalesRegister/viewConfig.js b/reports/SalesRegister/viewConfig.js deleted file mode 100644 index 2036ff8b..00000000 --- a/reports/SalesRegister/viewConfig.js +++ /dev/null @@ -1,56 +0,0 @@ -const title = 'Sales Register'; -import { t } from 'fyo'; - -export default { - title: title, - method: 'sales-register', - filterFields: [ - { - fieldtype: 'Link', - target: 'Party', - label: t`Customer Name`, - size: 'small', - placeholder: t`Customer Name`, - fieldname: 'customer', - getFilters: (query) => { - if (query) - return { - keywords: ['like', query], - customer: 1, - }; - - return { - customer: 1, - }; - }, - }, - { - fieldtype: 'Date', - fieldname: 'fromDate', - size: 'small', - placeholder: t`From Date`, - label: t`From Date`, - required: 1, - }, - { - fieldtype: 'Date', - size: 'small', - placeholder: t`To Date`, - fieldname: 'toDate', - label: t`To Date`, - required: 1, - }, - ], - actions: [], - getColumns() { - return [ - { label: t`SalesInvoice`, fieldname: 'name' }, - { label: t`Posting Date`, fieldname: 'date', fieldtype: 'Date' }, - { label: t`Customer`, fieldname: 'customer' }, - { label: t`Receivable Account`, fieldname: 'account' }, - { label: t`Net Total`, fieldname: 'netTotal', fieldtype: 'Currency' }, - { label: t`Total Tax`, fieldname: 'totalTax', fieldtype: 'Currency' }, - { label: t`Grand Total`, fieldname: 'grandTotal', fieldtype: 'Currency' }, - ]; - }, -}; diff --git a/reports/view.ts b/reports/view.ts deleted file mode 100644 index b75ebf9b..00000000 --- a/reports/view.ts +++ /dev/null @@ -1,26 +0,0 @@ -// import BalanceSheetViewConfig from './BalanceSheet/viewConfig'; -// import GeneralLedgerViewConfig from './GeneralLedger/viewConfig'; -// import GoodsAndServiceTaxGSTR1View from './GoodsAndServiceTax/GSTR1View'; -// import GoodsAndServiceTaxGSTR2View from './GoodsAndServiceTax/GSTR2View'; -// import ProfitAndLossViewConfig from './ProfitAndLoss/viewConfig'; -// import PurchaseRegisterViewConfig from './PurchaseRegister/viewConfig'; -// import SalesRegisterViewConfig from './SalesRegister/viewConfig'; -// import TrialBalanceViewConfig from './TrialBalance/viewConfig'; - -// export default { -// 'general-ledger': GeneralLedgerViewConfig, -// 'sales-register': SalesRegisterViewConfig, -// 'purchase-register': PurchaseRegisterViewConfig, -// 'balance-sheet': BalanceSheetViewConfig, -// 'profit-and-loss': ProfitAndLossViewConfig, -// 'trial-balance': TrialBalanceViewConfig, -// 'gstr-1': GoodsAndServiceTaxGSTR1View, -// 'gstr-2': GoodsAndServiceTaxGSTR2View, -// }; - -interface ReportView { - title: string; - method: string; -} - -export default {} as Record; diff --git a/src/components/Charts/BarChart.vue b/src/components/Charts/BarChart.vue index 25412809..f0c32f69 100644 --- a/src/components/Charts/BarChart.vue +++ b/src/components/Charts/BarChart.vue @@ -123,7 +123,7 @@ >

- {{ xi > -1 ? xLabels[xi] : '' }} + {{ xi > -1 ? formatX(xLabels[xi]) : '' }}

{{ yi > -1 ? format(points[yi][xi]) : '' }} @@ -133,8 +133,8 @@

diff --git a/src/pages/Dashboard/Dashboard.vue b/src/pages/Dashboard/Dashboard.vue index 4226616a..ff95573f 100644 --- a/src/pages/Dashboard/Dashboard.vue +++ b/src/pages/Dashboard/Dashboard.vue @@ -7,12 +7,12 @@

- + @@ -21,7 +21,7 @@ import PageHeader from 'src/components/PageHeader'; import Cashflow from './Cashflow'; // import Expenses from './Expenses'; -// import ProfitAndLoss from './ProfitAndLoss'; +import ProfitAndLoss from './ProfitAndLoss'; import UnpaidInvoices from './UnpaidInvoices'; export default { @@ -30,8 +30,8 @@ export default { PageHeader, UnpaidInvoices, Cashflow, - /* ProfitAndLoss, + /* Expenses, */ }, diff --git a/src/pages/Dashboard/ProfitAndLoss.vue b/src/pages/Dashboard/ProfitAndLoss.vue index 574ba504..a1bb05da 100644 --- a/src/pages/Dashboard/ProfitAndLoss.vue +++ b/src/pages/Dashboard/ProfitAndLoss.vue @@ -28,11 +28,11 @@