diff --git a/.all-contributorsrc b/.all-contributorsrc index d69d4da6f..16d16eb97 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -51,6 +51,15 @@ "contributions": [ "code" ] + }, + { + "login": "KalliopiPliogka", + "name": "Kalliopi Pliogka", + "avatar_url": "https://avatars.githubusercontent.com/u/81677549?v=4", + "profile": "https://github.com/KalliopiPliogka", + "contributions": [ + "bug" + ] } ], "contributorsPerLine": 7, diff --git a/.gitignore b/.gitignore index 8e489a403..83973c22d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,9 @@ node_modules/ -data + +# Docker volumes data directory +/data + +# Production env file .env + test-results/ \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index b8f1759f7..003fd26da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,20 @@ All notable changes to Bigcapital server-side will be in this file. +# [0.9.12] - 29-08-2023 + +* Refactor: split the services to multiple service classes. (by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/202) +* Fix: create quick customer/vendor by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/206 +* Fix: typo in bill success message without bill number by @KalliopiPliogka in https://github.com/bigcapitalhq/bigcapital/pull/219 +* Fix: AP/AR aging summary issue by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/229 +* Fix: shouldn't write GL entries when save transaction as draft. by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/221 +* Fix: Transaction type of credit note and vendor credit are not defined on account transactions by @abouolia in +* Fix: date format of filtering transactions by date range by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/231 +* Fix: change the default from/date date value of reports by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/230 +* Fix: typos in words start with `A` letter by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/227 +* Fix: filter by customers, vendors and items in reports do not work by @abouolia in https://github.com/bigcapitalhq/bigcapital/pull/224 +https://github.com/bigcapitalhq/bigcapital/pull/225 + # [0.9.11] - 23-07-2023 * added: Restart policy to docker compose files. by @suhaibaffan in https://github.com/bigcapitalhq/bigcapital/pull/198 @@ -97,7 +111,7 @@ All notable changes to Bigcapital server-side will be in this file. - fix: delete invoice transaction issue. `@bigcapital/webapp` -- fix: general, accoutant and items preferences. +- fix: general, accountant and items preferences. - fix: auto-increment sale invoices, estiamtes, credit notes, payments and manual journals. - refactor: the setup organization form to use binded Formik components. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a70008750..aa9093c25 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,6 +7,7 @@ Please read through this document before submitting any issues or pull requests ## Sections - [General Instructions](#general-instructions) +- [Local Setup Prerequisites](#local-setup-prerequisites) - [Contribute to Backend](#contribute-to-backend) - [Contribute to Frontend](#contribute-to-frontend) - [Other Ways to Contribute](#other-ways-to-contribute) @@ -31,9 +32,18 @@ Contributions via pull requests are much appreciated. Once the approach is agree --- +## Local Setup Prerequisites + - The application currently supports **Node.js v14.x**. Please ensure that you are using this version of Node.js when developing. (use [nvm](https://github.com/nvm-sh/nvm#installing-and-updating) to switch between node versions) + ## Contribute to Backend - Clone the `bigcapital` repository and `cd` into `bigcapital` directory. +- Create `.env` file by copying `.env.example` file to `.env`. (The ``.env.example`` file has all the necessary values of variables to start development directly). + +``` +cp .env.example .env +``` + - Install all npm dependencies of the monorepo, you don't have to change directory to the `backend` package. just hit these command on root directory and it will install dependencies of all packages. ``` diff --git a/README.md b/README.md index 208d39aab..99f1d3cc2 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d ElforJani13
ElforJani13

💻 Lars Scheibling
Lars Scheibling

🐛 Suhaib Affan
Suhaib Affan

💻 + Kalliopi Pliogka
Kalliopi Pliogka

🐛 diff --git a/packages/server/resources/locales/ar.json b/packages/server/resources/locales/ar.json index f7bed4726..a52b13d51 100644 --- a/packages/server/resources/locales/ar.json +++ b/packages/server/resources/locales/ar.json @@ -152,7 +152,7 @@ "Opening Balance Liabilities": "رصيد الالتزامات الافتتاحي", "Loan": "اقراض", "Owner A Drawings": "مسحوبات المالك", - "An account that holds valuation of products or goods that availiable for sale.": "حساب يحمل قيم مخزون البضاعة أو السلع المتاحة للبيع.", + "An account that holds valuation of products or goods that available for sale.": "حساب يحمل قيم مخزون البضاعة أو السلع المتاحة للبيع.", "Tracks the gain and losses of the exchange differences.": "يسجل مكاسب وخسائر فروق الصرف.", "Any bank fees levied is recorded into the bank fees and charges account. A bank account maintenance fee, transaction charges, a late payment fee are some examples.": "يتم تسجيل أي رسوم مصرفية يتم فرضها في حساب الرسوم والمصروفات البنكية. ومن الأمثلة على ذلك رسوم صيانة الحساب المصرفي ورسوم المعاملات ورسوم الدفع المتأخر.", "The income activities are not associated to the core business.": "لا ترتبط انشطة الدخل إلى الأعمال الأساسية.", diff --git a/packages/server/resources/locales/en.json b/packages/server/resources/locales/en.json index 811db19e7..b021c2347 100644 --- a/packages/server/resources/locales/en.json +++ b/packages/server/resources/locales/en.json @@ -151,7 +151,7 @@ "Opening Balance Liabilities": "Opening Balance Liabilities", "Loan": "Loan", "Owner A Drawings": "Owner A Drawings", - "An account that holds valuation of products or goods that availiable for sale.": "An account that holds valuation of products or goods that availiable for sale.", + "An account that holds valuation of products or goods that available for sale.": "An account that holds valuation of products or goods that available for sale.", "Tracks the gain and losses of the exchange differences.": "Tracks the gain and losses of the exchange differences.", "Any bank fees levied is recorded into the bank fees and charges account. A bank account maintenance fee, transaction charges, a late payment fee are some examples.": "Any bank fees levied is recorded into the bank fees and charges account. A bank account maintenance fee, transaction charges, a late payment fee are some examples.", "The income activities are not associated to the core business.": "The income activities are not associated to the core business.", diff --git a/packages/server/src/api/controllers/FinancialStatements/APAgingSummary.ts b/packages/server/src/api/controllers/FinancialStatements/APAgingSummary.ts index 8bd6c1014..b0dc28841 100644 --- a/packages/server/src/api/controllers/FinancialStatements/APAgingSummary.ts +++ b/packages/server/src/api/controllers/FinancialStatements/APAgingSummary.ts @@ -33,10 +33,13 @@ export default class APAgingSummaryReportController extends BaseFinancialReportC return [ ...this.sheetNumberFormatValidationSchema, query('as_date').optional().isISO8601(), - query('aging_days_before').optional().isNumeric().toInt(), - query('aging_periods').optional().isNumeric().toInt(), + + query('aging_days_before').default(30).isInt({ max: 500 }).toInt(), + query('aging_periods').default(3).isInt({ max: 12 }).toInt(), + query('vendors_ids').optional().isArray({ min: 1 }), query('vendors_ids.*').isInt({ min: 1 }).toInt(), + query('none_zero').default(true).isBoolean().toBoolean(), // Filtering by branches. @@ -53,15 +56,36 @@ export default class APAgingSummaryReportController extends BaseFinancialReportC const filter = this.matchedQueryData(req); try { - const { data, columns, query, meta } = - await this.APAgingSummaryService.APAgingSummary(tenantId, filter); + const accept = this.accepts(req); + const acceptType = accept.types(['json', 'application/json+table']); - return res.status(200).send({ - data: this.transfromToResponse(data), - columns: this.transfromToResponse(columns), - query: this.transfromToResponse(query), - meta: this.transfromToResponse(meta), - }); + switch (acceptType) { + case 'application/json+table': + const table = await this.APAgingSummaryService.APAgingSummaryTable( + tenantId, + filter + ); + return res.status(200).send({ + table: { + rows: table.rows, + columns: table.columns, + }, + meta: table.meta, + query: table.query, + }); + break; + default: + const { data, columns, query, meta } = + await this.APAgingSummaryService.APAgingSummary(tenantId, filter); + + return res.status(200).send({ + data: this.transfromToResponse(data), + columns: this.transfromToResponse(columns), + query: this.transfromToResponse(query), + meta: this.transfromToResponse(meta), + }); + break; + } } catch (error) { next(error); } diff --git a/packages/server/src/api/controllers/FinancialStatements/ARAgingSummary.ts b/packages/server/src/api/controllers/FinancialStatements/ARAgingSummary.ts index deb69a172..489eb04ae 100644 --- a/packages/server/src/api/controllers/FinancialStatements/ARAgingSummary.ts +++ b/packages/server/src/api/controllers/FinancialStatements/ARAgingSummary.ts @@ -36,8 +36,8 @@ export default class ARAgingSummaryReportController extends BaseFinancialReportC query('as_date').optional().isISO8601(), - query('aging_days_before').optional().isInt({ max: 500 }).toInt(), - query('aging_periods').optional().isInt({ max: 12 }).toInt(), + query('aging_days_before').default(30).isInt({ max: 500 }).toInt(), + query('aging_periods').default(3).isInt({ max: 12 }).toInt(), query('customers_ids').optional().isArray({ min: 1 }), query('customers_ids.*').isInt({ min: 1 }).toInt(), @@ -58,15 +58,36 @@ export default class ARAgingSummaryReportController extends BaseFinancialReportC const filter = this.matchedQueryData(req); try { - const { data, columns, query, meta } = - await this.ARAgingSummaryService.ARAgingSummary(tenantId, filter); + const accept = this.accepts(req); + const acceptType = accept.types(['json', 'application/json+table']); - return res.status(200).send({ - data: this.transfromToResponse(data), - columns: this.transfromToResponse(columns), - query: this.transfromToResponse(query), - meta: this.transfromToResponse(meta), - }); + switch (acceptType) { + case 'application/json+table': + const table = await this.ARAgingSummaryService.ARAgingSummaryTable( + tenantId, + filter + ); + return res.status(200).send({ + table: { + rows: table.rows, + columns: table.columns, + }, + meta: table.meta, + query: table.query, + }); + break; + default: + const { data, columns, query, meta } = + await this.ARAgingSummaryService.ARAgingSummary(tenantId, filter); + + return res.status(200).send({ + data: this.transfromToResponse(data), + columns: this.transfromToResponse(columns), + query: this.transfromToResponse(query), + meta: this.transfromToResponse(meta), + }); + break; + } } catch (error) { console.log(error); } diff --git a/packages/server/src/api/controllers/ManualJournals.ts b/packages/server/src/api/controllers/ManualJournals.ts index 682ef64ce..8af8c13b5 100644 --- a/packages/server/src/api/controllers/ManualJournals.ts +++ b/packages/server/src/api/controllers/ManualJournals.ts @@ -387,7 +387,7 @@ export default class ManualJournalsController extends BaseController { errors: [{ type: 'CREDIT.DEBIT.NOT.EQUALS', code: 300 }], }); } - if (error.errorType === 'acccounts_ids_not_found') { + if (error.errorType === 'accounts_ids_not_found') { return res.boom.badRequest( 'Journal entries some of accounts ids not exists.', { errors: [{ type: 'ACCOUNTS.IDS.NOT.FOUND', code: 400 }] } diff --git a/packages/server/src/api/controllers/Sales/PaymentReceives.ts b/packages/server/src/api/controllers/Sales/PaymentReceives.ts index 4e1f69720..ec210ad23 100644 --- a/packages/server/src/api/controllers/Sales/PaymentReceives.ts +++ b/packages/server/src/api/controllers/Sales/PaymentReceives.ts @@ -372,7 +372,7 @@ export default class PaymentReceivesController extends BaseController { /** * Retrieve the given payment receive details. - * @asycn + * @async * @param {Request} req - * @param {Response} res - */ diff --git a/packages/server/src/data/TransactionTypes.ts b/packages/server/src/data/TransactionTypes.ts new file mode 100755 index 000000000..9815ab183 --- /dev/null +++ b/packages/server/src/data/TransactionTypes.ts @@ -0,0 +1,28 @@ +export const TransactionTypes = { + SaleInvoice: 'Sale invoice', + SaleReceipt: 'Sale receipt', + PaymentReceive: 'Payment receive', + Bill: 'Bill', + BillPayment: 'Payment made', + VendorOpeningBalance: 'Vendor opening balance', + CustomerOpeningBalance: 'Customer opening balance', + InventoryAdjustment: 'Inventory adjustment', + ManualJournal: 'Manual journal', + Journal: 'Manual journal', + Expense: 'Expense', + OwnerContribution: 'Owner contribution', + TransferToAccount: 'Transfer to account', + TransferFromAccount: 'Transfer from account', + OtherIncome: 'Other income', + OtherExpense: 'Other expense', + OwnerDrawing: 'Owner drawing', + InvoiceWriteOff: 'Invoice write-off', + + CreditNote: 'transaction_type.credit_note', + VendorCredit: 'transaction_type.vendor_credit', + + RefundCreditNote: 'transaction_type.refund_credit_note', + RefundVendorCredit: 'transaction_type.refund_vendor_credit', + + LandedCost: 'transaction_type.landed_cost', +}; diff --git a/packages/server/src/database/seeds/data/accounts.js b/packages/server/src/database/seeds/data/accounts.js index fa9ee0d0c..e8f68b208 100644 --- a/packages/server/src/database/seeds/data/accounts.js +++ b/packages/server/src/database/seeds/data/accounts.js @@ -92,7 +92,7 @@ export default [ index: 1, active: 1, description: - 'An account that holds valuation of products or goods that availiable for sale.', + 'An account that holds valuation of products or goods that available for sale.', }, // Libilities diff --git a/packages/server/src/interfaces/APAgingSummaryReport.ts b/packages/server/src/interfaces/APAgingSummaryReport.ts index 788892112..db6626167 100644 --- a/packages/server/src/interfaces/APAgingSummaryReport.ts +++ b/packages/server/src/interfaces/APAgingSummaryReport.ts @@ -1,51 +1,36 @@ import { IAgingPeriod, IAgingPeriodTotal, - IAgingAmount + IAgingAmount, + IAgingSummaryQuery, + IAgingSummaryTotal, + IAgingSummaryContact, + IAgingSummaryData, } from './AgingReport'; -import { - INumberFormatQuery -} from './FinancialStatements'; +import { INumberFormatQuery } from './FinancialStatements'; -export interface IAPAgingSummaryQuery { - asDate: Date | string; - agingDaysBefore: number; - agingPeriods: number; - numberFormat: INumberFormatQuery; +export interface IAPAgingSummaryQuery extends IAgingSummaryQuery { vendorsIds: number[]; - noneZero: boolean; - - branchesIds?: number[] } -export interface IAPAgingSummaryVendor { - vendorName: string, - current: IAgingAmount, - aging: IAgingPeriodTotal[], - total: IAgingAmount, -}; +export interface IAPAgingSummaryVendor extends IAgingSummaryContact { + vendorName: string; +} -export interface IAPAgingSummaryTotal { - current: IAgingAmount, - aging: IAgingPeriodTotal[], - total: IAgingAmount, -}; +export interface IAPAgingSummaryTotal extends IAgingSummaryTotal {} -export interface IAPAgingSummaryData { - vendors: IAPAgingSummaryVendor[], - total: IAPAgingSummaryTotal, -}; +export interface IAPAgingSummaryData extends IAgingSummaryData { + vendors: IAPAgingSummaryVendor[]; +} export type IAPAgingSummaryColumns = IAgingPeriod[]; - export interface IARAgingSummaryMeta { - baseCurrency: string, - organizationName: string, + baseCurrency: string; + organizationName: string; } - export interface IAPAgingSummaryMeta { - baseCurrency: string, - organizationName: string, -} \ No newline at end of file + baseCurrency: string; + organizationName: string; +} diff --git a/packages/server/src/interfaces/ARAgingSummaryReport.ts b/packages/server/src/interfaces/ARAgingSummaryReport.ts index a9d6ff3f5..7d25e2b2c 100644 --- a/packages/server/src/interfaces/ARAgingSummaryReport.ts +++ b/packages/server/src/interfaces/ARAgingSummaryReport.ts @@ -1,37 +1,28 @@ -import { IAgingPeriod, IAgingPeriodTotal, IAgingAmount } from './AgingReport'; -import { INumberFormatQuery } from './FinancialStatements'; +import { + IAgingPeriod, + IAgingSummaryQuery, + IAgingSummaryTotal, + IAgingSummaryContact, + IAgingSummaryData, +} from './AgingReport'; -export interface IARAgingSummaryQuery { - asDate: Date | string; - agingDaysBefore: number; - agingPeriods: number; - numberFormat: INumberFormatQuery; +export interface IARAgingSummaryQuery extends IAgingSummaryQuery { customersIds: number[]; - branchesIds: number[]; - noneZero: boolean; } -export interface IARAgingSummaryCustomer { +export interface IARAgingSummaryCustomer extends IAgingSummaryContact { customerName: string; - current: IAgingAmount; - aging: IAgingPeriodTotal[]; - total: IAgingAmount; } -export interface IARAgingSummaryTotal { - current: IAgingAmount; - aging: IAgingPeriodTotal[]; - total: IAgingAmount; -} +export interface IARAgingSummaryTotal extends IAgingSummaryTotal {} -export interface IARAgingSummaryData { +export interface IARAgingSummaryData extends IAgingSummaryData { customers: IARAgingSummaryCustomer[]; - total: IARAgingSummaryTotal; } export type IARAgingSummaryColumns = IAgingPeriod[]; export interface IARAgingSummaryMeta { - organizationName: string, - baseCurrency: string, -} \ No newline at end of file + organizationName: string; + baseCurrency: string; +} diff --git a/packages/server/src/interfaces/Account.ts b/packages/server/src/interfaces/Account.ts index de8a2332c..3d3ce47a7 100644 --- a/packages/server/src/interfaces/Account.ts +++ b/packages/server/src/interfaces/Account.ts @@ -58,6 +58,7 @@ export interface IAccountTransaction { date: string | Date; referenceType: string; + referenceTypeFormatted: string; referenceId: number; referenceNumber?: string; diff --git a/packages/server/src/interfaces/AgingReport.ts b/packages/server/src/interfaces/AgingReport.ts index 65983d44f..c68b6b389 100644 --- a/packages/server/src/interfaces/AgingReport.ts +++ b/packages/server/src/interfaces/AgingReport.ts @@ -1,6 +1,9 @@ + +import { INumberFormatQuery } from './FinancialStatements'; + export interface IAgingPeriodTotal extends IAgingPeriod { total: IAgingAmount; -}; +} export interface IAgingAmount { amount: number; @@ -20,3 +23,22 @@ export interface IAgingSummaryContact { aging: IAgingPeriodTotal[]; total: IAgingAmount; } + +export interface IAgingSummaryQuery { + asDate: Date | string; + agingDaysBefore: number; + agingPeriods: number; + numberFormat: INumberFormatQuery; + branchesIds: number[]; + noneZero: boolean; +} + +export interface IAgingSummaryTotal { + current: IAgingAmount; + aging: IAgingPeriodTotal[]; + total: IAgingAmount; +} + +export interface IAgingSummaryData { + total: IAgingSummaryTotal; +} diff --git a/packages/server/src/interfaces/Bill.ts b/packages/server/src/interfaces/Bill.ts index fcf89dbda..fa94c3e41 100644 --- a/packages/server/src/interfaces/Bill.ts +++ b/packages/server/src/interfaces/Bill.ts @@ -1,7 +1,7 @@ import { Knex } from 'knex'; import { IDynamicListFilterDTO } from './DynamicFilter'; import { IItemEntry, IItemEntryDTO } from './ItemEntry'; -import { IBillLandedCost } from './LandedCost'; +import { IBillLandedCost } from './LandedCost'; export interface IBillDTO { vendorId: number; billNumber: string; @@ -99,17 +99,17 @@ export interface IBillCreatedPayload { trx: Knex.Transaction; } -export interface IBillCreatingPayload{ +export interface IBillCreatingPayload { tenantId: number; billDTO: IBillDTO; - trx: Knex.Transaction; + trx: Knex.Transaction; } export interface IBillEditingPayload { tenantId: number; oldBill: IBill; billDTO: IBillEditDTO; - trx: Knex.Transaction; + trx: Knex.Transaction; } export interface IBillEditedPayload { tenantId: number; @@ -129,7 +129,7 @@ export interface IBIllEventDeletedPayload { export interface IBillEventDeletingPayload { tenantId: number; oldBill: IBill; - trx: Knex.Transaction; + trx: Knex.Transaction; } export enum BillAction { Create = 'Create', @@ -138,3 +138,16 @@ export enum BillAction { View = 'View', NotifyBySms = 'NotifyBySms', } + +export interface IBillOpeningPayload { + trx: Knex.Transaction; + tenantId: number; + oldBill: IBill; +} + +export interface IBillOpenedPayload { + trx: Knex.Transaction; + bill: IBill; + oldBill: IBill; + tenantId: number; +} diff --git a/packages/server/src/interfaces/CashFlow.ts b/packages/server/src/interfaces/CashFlow.ts index 289159727..e9a2dc8cd 100644 --- a/packages/server/src/interfaces/CashFlow.ts +++ b/packages/server/src/interfaces/CashFlow.ts @@ -41,7 +41,7 @@ export interface ICashFlowStatementAccountMeta { code: string; total: ICashFlowStatementTotal; accountType: string; - adjusmentType: string; + adjustmentType: string; sectionType: ICashFlowStatementSectionType.ACCOUNT; } diff --git a/packages/server/src/interfaces/PaymentReceive.ts b/packages/server/src/interfaces/PaymentReceive.ts index 658113fb3..6f8d8552a 100644 --- a/packages/server/src/interfaces/PaymentReceive.ts +++ b/packages/server/src/interfaces/PaymentReceive.ts @@ -1,6 +1,5 @@ -import { ISystemUser } from '@/interfaces'; import { Knex } from 'knex'; -import { pick } from 'lodash'; +import { ISystemUser } from '@/interfaces'; import { ILedgerEntry } from './Ledger'; import { ISaleInvoice } from './SaleInvoice'; diff --git a/packages/server/src/interfaces/SaleInvoice.ts b/packages/server/src/interfaces/SaleInvoice.ts index 874d1b6c9..4aa072655 100644 --- a/packages/server/src/interfaces/SaleInvoice.ts +++ b/packages/server/src/interfaces/SaleInvoice.ts @@ -160,6 +160,7 @@ export interface ISaleInvoiceEventDeliveredPayload { tenantId: number; saleInvoiceId: number; saleInvoice: ISaleInvoice; + trx: Knex.Transaction; } export interface ISaleInvoiceDeliveringPayload { diff --git a/packages/server/src/lib/DynamicFilter/DynamicFilter.ts b/packages/server/src/lib/DynamicFilter/DynamicFilter.ts index 2af4d7c4f..b50391dc2 100644 --- a/packages/server/src/lib/DynamicFilter/DynamicFilter.ts +++ b/packages/server/src/lib/DynamicFilter/DynamicFilter.ts @@ -1,8 +1,8 @@ import { forEach, uniqBy } from 'lodash'; -import DynamicFilterAbstructor from './DynamicFilterAbstructor'; +import DynamicFilterAbstractor from './DynamicFilterAbstractor'; import { IDynamicFilter, IFilterRole, IModel } from '@/interfaces'; -export default class DynamicFilter extends DynamicFilterAbstructor{ +export default class DynamicFilter extends DynamicFilterAbstractor{ private model: IModel; private tableName: string; private dynamicFilters: IDynamicFilter[]; diff --git a/packages/server/src/lib/DynamicFilter/DynamicFilterAbstructor.ts b/packages/server/src/lib/DynamicFilter/DynamicFilterAbstractor.ts similarity index 96% rename from packages/server/src/lib/DynamicFilter/DynamicFilterAbstructor.ts rename to packages/server/src/lib/DynamicFilter/DynamicFilterAbstractor.ts index 3b3f6dee1..256333c68 100644 --- a/packages/server/src/lib/DynamicFilter/DynamicFilterAbstructor.ts +++ b/packages/server/src/lib/DynamicFilter/DynamicFilterAbstractor.ts @@ -1,5 +1,5 @@ -export default class DynamicFilterAbstructor { +export default class DynamicFilterAbstractor { /** * Extract relation table name from relation. * @param {String} column - diff --git a/packages/server/src/lib/DynamicFilter/DynamicFilterFilterRoles.ts b/packages/server/src/lib/DynamicFilter/DynamicFilterFilterRoles.ts index ae0502e7e..0bacf4d80 100644 --- a/packages/server/src/lib/DynamicFilter/DynamicFilterFilterRoles.ts +++ b/packages/server/src/lib/DynamicFilter/DynamicFilterFilterRoles.ts @@ -1,7 +1,7 @@ -import DynamicFilterRoleAbstructor from './DynamicFilterRoleAbstructor'; +import DynamicFilterRoleAbstractor from './DynamicFilterRoleAbstractor'; import { IFilterRole } from '@/interfaces'; -export default class FilterRoles extends DynamicFilterRoleAbstructor { +export default class FilterRoles extends DynamicFilterRoleAbstractor { private filterRoles: IFilterRole[]; /** diff --git a/packages/server/src/lib/DynamicFilter/DynamicFilterRoleAbstructor.ts b/packages/server/src/lib/DynamicFilter/DynamicFilterRoleAbstractor.ts similarity index 99% rename from packages/server/src/lib/DynamicFilter/DynamicFilterRoleAbstructor.ts rename to packages/server/src/lib/DynamicFilter/DynamicFilterRoleAbstractor.ts index 1dbc4f889..488f48919 100644 --- a/packages/server/src/lib/DynamicFilter/DynamicFilterRoleAbstructor.ts +++ b/packages/server/src/lib/DynamicFilter/DynamicFilterRoleAbstractor.ts @@ -6,7 +6,7 @@ import DynamicFilterQueryParser from './DynamicFilterQueryParser'; import { Lexer } from '../LogicEvaluation/Lexer'; import { COMPARATOR_TYPE, FIELD_TYPE } from './constants'; -export default abstract class DynamicFilterAbstructor +export default abstract class DynamicFilterAbstractor implements IDynamicFilter { protected filterRoles: IFilterRole[] = []; diff --git a/packages/server/src/lib/DynamicFilter/DynamicFilterSortBy.ts b/packages/server/src/lib/DynamicFilter/DynamicFilterSortBy.ts index f1ab6c7fc..d70ff3603 100644 --- a/packages/server/src/lib/DynamicFilter/DynamicFilterSortBy.ts +++ b/packages/server/src/lib/DynamicFilter/DynamicFilterSortBy.ts @@ -1,4 +1,4 @@ -import DynamicFilterRoleAbstructor from '@/lib/DynamicFilter/DynamicFilterRoleAbstructor'; +import DynamicFilterRoleAbstractor from '@/lib/DynamicFilter/DynamicFilterRoleAbstractor'; import { FIELD_TYPE } from './constants'; interface ISortRole { @@ -6,7 +6,7 @@ interface ISortRole { order: string; } -export default class DynamicFilterSortBy extends DynamicFilterRoleAbstructor { +export default class DynamicFilterSortBy extends DynamicFilterRoleAbstractor { private sortRole: ISortRole = {}; /** diff --git a/packages/server/src/lib/DynamicFilter/DynamicFilterViews.ts b/packages/server/src/lib/DynamicFilter/DynamicFilterViews.ts index 40e95c5b4..289e616ab 100644 --- a/packages/server/src/lib/DynamicFilter/DynamicFilterViews.ts +++ b/packages/server/src/lib/DynamicFilter/DynamicFilterViews.ts @@ -1,8 +1,8 @@ import { omit } from 'lodash'; import { IView, IViewRole } from '@/interfaces'; -import DynamicFilterRoleAbstructor from './DynamicFilterRoleAbstructor'; +import DynamicFilterRoleAbstractor from './DynamicFilterRoleAbstractor'; -export default class DynamicFilterViews extends DynamicFilterRoleAbstructor { +export default class DynamicFilterViews extends DynamicFilterRoleAbstractor { private viewSlug: string; private logicExpression: string; private filterRoles: IViewRole[]; diff --git a/packages/server/src/lib/ViewRolesBuilder/FilterRolesDynamicFilter.js b/packages/server/src/lib/ViewRolesBuilder/FilterRolesDynamicFilter.js index 978abb53d..c07af232b 100644 --- a/packages/server/src/lib/ViewRolesBuilder/FilterRolesDynamicFilter.js +++ b/packages/server/src/lib/ViewRolesBuilder/FilterRolesDynamicFilter.js @@ -1,10 +1,10 @@ -import DynamicFilterRoleAbstructor from '@/lib/DynamicFilter/DynamicFilterRoleAbstructor'; +import DynamicFilterRoleAbstractor from '@/lib/DynamicFilter/DynamicFilterRoleAbstractor'; import { validateViewRoles, buildFilterQuery, } from '@/lib/ViewRolesBuilder'; -export default class ViewRolesDynamicFilter extends DynamicFilterRoleAbstructor { +export default class ViewRolesDynamicFilter extends DynamicFilterRoleAbstractor { /** * Constructor method. * @param {*} filterRoles - diff --git a/packages/server/src/loaders/eventEmitter.ts b/packages/server/src/loaders/eventEmitter.ts index ea2b97677..52f8c489d 100644 --- a/packages/server/src/loaders/eventEmitter.ts +++ b/packages/server/src/loaders/eventEmitter.ts @@ -1,6 +1,5 @@ import { EventPublisher } from '@/lib/EventPublisher/EventPublisher'; -import ItemSubscriber from '@/subscribers/Items/ItemSubscriber'; import InventoryAdjustmentsSubscriber from '@/subscribers/Inventory/InventoryAdjustment'; import BillWriteInventoryTransactionsSubscriber from '@/subscribers/Bills/WriteInventoryTransactions'; import PaymentSyncBillBalance from '@/subscribers/PaymentMades/PaymentSyncBillBalance'; @@ -91,7 +90,6 @@ export default () => { export const susbcribers = () => { return [ - ItemSubscriber, InventoryAdjustmentsSubscriber, BillWriteInventoryTransactionsSubscriber, PaymentSyncBillBalance, diff --git a/packages/server/src/locales/ar.json b/packages/server/src/locales/ar.json index f7bed4726..a52b13d51 100644 --- a/packages/server/src/locales/ar.json +++ b/packages/server/src/locales/ar.json @@ -152,7 +152,7 @@ "Opening Balance Liabilities": "رصيد الالتزامات الافتتاحي", "Loan": "اقراض", "Owner A Drawings": "مسحوبات المالك", - "An account that holds valuation of products or goods that availiable for sale.": "حساب يحمل قيم مخزون البضاعة أو السلع المتاحة للبيع.", + "An account that holds valuation of products or goods that available for sale.": "حساب يحمل قيم مخزون البضاعة أو السلع المتاحة للبيع.", "Tracks the gain and losses of the exchange differences.": "يسجل مكاسب وخسائر فروق الصرف.", "Any bank fees levied is recorded into the bank fees and charges account. A bank account maintenance fee, transaction charges, a late payment fee are some examples.": "يتم تسجيل أي رسوم مصرفية يتم فرضها في حساب الرسوم والمصروفات البنكية. ومن الأمثلة على ذلك رسوم صيانة الحساب المصرفي ورسوم المعاملات ورسوم الدفع المتأخر.", "The income activities are not associated to the core business.": "لا ترتبط انشطة الدخل إلى الأعمال الأساسية.", diff --git a/packages/server/src/locales/en.json b/packages/server/src/locales/en.json index 811db19e7..b021c2347 100644 --- a/packages/server/src/locales/en.json +++ b/packages/server/src/locales/en.json @@ -151,7 +151,7 @@ "Opening Balance Liabilities": "Opening Balance Liabilities", "Loan": "Loan", "Owner A Drawings": "Owner A Drawings", - "An account that holds valuation of products or goods that availiable for sale.": "An account that holds valuation of products or goods that availiable for sale.", + "An account that holds valuation of products or goods that available for sale.": "An account that holds valuation of products or goods that available for sale.", "Tracks the gain and losses of the exchange differences.": "Tracks the gain and losses of the exchange differences.", "Any bank fees levied is recorded into the bank fees and charges account. A bank account maintenance fee, transaction charges, a late payment fee are some examples.": "Any bank fees levied is recorded into the bank fees and charges account. A bank account maintenance fee, transaction charges, a late payment fee are some examples.", "The income activities are not associated to the core business.": "The income activities are not associated to the core business.", diff --git a/packages/server/src/models/Account.ts b/packages/server/src/models/Account.ts index a3d9f74f3..9d4fb053e 100644 --- a/packages/server/src/models/Account.ts +++ b/packages/server/src/models/Account.ts @@ -127,7 +127,7 @@ export default class Account extends mixin(TenantModel, [ }, filterAccountTypes(query, typesIds) { if (typesIds.length > 0) { - query.whereIn('account_types.accoun_type_id', typesIds); + query.whereIn('account_types.account_type_id', typesIds); } }, viewRolesBuilder(query, conditionals, expression) { diff --git a/packages/server/src/models/AccountTransaction.ts b/packages/server/src/models/AccountTransaction.ts index 2aa70aa75..a8ad848f7 100644 --- a/packages/server/src/models/AccountTransaction.ts +++ b/packages/server/src/models/AccountTransaction.ts @@ -2,8 +2,11 @@ import { Model, raw } from 'objection'; import moment from 'moment'; import { isEmpty, castArray } from 'lodash'; import TenantModel from 'models/TenantModel'; +import { getTransactionTypeLabel } from '@/utils/transactions-types'; export default class AccountTransaction extends TenantModel { + referenceType: string; + /** * Table name */ @@ -30,40 +33,7 @@ export default class AccountTransaction extends TenantModel { * @return {string} */ get referenceTypeFormatted() { - return AccountTransaction.getReferenceTypeFormatted(this.referenceType); - } - - /** - * Reference type formatted. - */ - static getReferenceTypeFormatted(referenceType) { - const mapped = { - SaleInvoice: 'Sale invoice', - SaleReceipt: 'Sale receipt', - PaymentReceive: 'Payment receive', - Bill: 'Bill', - BillPayment: 'Payment made', - VendorOpeningBalance: 'Vendor opening balance', - CustomerOpeningBalance: 'Customer opening balance', - InventoryAdjustment: 'Inventory adjustment', - ManualJournal: 'Manual journal', - Journal: 'Manual journal', - Expense: 'Expense', - OwnerContribution: 'Owner contribution', - TransferToAccount: 'Transfer to account', - TransferFromAccount: 'Transfer from account', - OtherIncome: 'Other income', - OtherExpense: 'Other expense', - OwnerDrawing: 'Owner drawing', - InvoiceWriteOff: 'Invoice write-off', - - CreditNote: 'transaction_type.credit_note', - VendorCredit: 'transaction_type.vendor_credit', - - RefundCreditNote: 'transaction_type.refund_credit_note', - RefundVendorCredit: 'transaction_type.refund_vendor_credit', - }; - return mapped[referenceType] || ''; + return getTransactionTypeLabel(this.referenceType); } /** @@ -89,15 +59,9 @@ export default class AccountTransaction extends TenantModel { } }, filterDateRange(query, startDate, endDate, type = 'day') { - const dateFormat = 'YYYY-MM-DD HH:mm:ss'; - const fromDate = moment(startDate) - .utcOffset(0) - .startOf(type) - .format(dateFormat); - const toDate = moment(endDate) - .utcOffset(0) - .endOf(type) - .format(dateFormat); + const dateFormat = 'YYYY-MM-DD'; + const fromDate = moment(startDate).startOf(type).format(dateFormat); + const toDate = moment(endDate).endOf(type).format(dateFormat); if (startDate) { query.where('date', '>=', fromDate); @@ -141,7 +105,6 @@ export default class AccountTransaction extends TenantModel { query.modify('filterDateRange', null, toDate); query.modify('sumationCreditDebit'); }, - contactsOpeningBalance( query, openingDate, diff --git a/packages/server/src/models/Branch.ts b/packages/server/src/models/Branch.ts index d8097a45d..bf2c4bfa3 100644 --- a/packages/server/src/models/Branch.ts +++ b/packages/server/src/models/Branch.ts @@ -97,7 +97,7 @@ export default class Branch extends TenantModel { }, /** - * Branch may belongs to assocaited bills. + * Branch may belongs to associated bills. */ bills: { relation: Model.HasManyRelation, diff --git a/packages/server/src/models/CashflowTransaction.ts b/packages/server/src/models/CashflowTransaction.ts index 6d6ffcc9b..2184d1434 100644 --- a/packages/server/src/models/CashflowTransaction.ts +++ b/packages/server/src/models/CashflowTransaction.ts @@ -121,7 +121,7 @@ export default class CashflowTransaction extends TenantModel { }, /** - * Cashflow transaction may has assocaited cashflow account. + * Cashflow transaction may has associated cashflow account. */ cashflowAccount: { relation: Model.BelongsToOneRelation, diff --git a/packages/server/src/models/InventoryCostLotTracker.ts b/packages/server/src/models/InventoryCostLotTracker.ts index fd9b13475..7b644f9a5 100644 --- a/packages/server/src/models/InventoryCostLotTracker.ts +++ b/packages/server/src/models/InventoryCostLotTracker.ts @@ -33,7 +33,7 @@ export default class InventoryCostLotTracker extends TenantModel { query.groupBy('item_id'); }, filterDateRange(query, startDate, endDate, type = 'day') { - const dateFormat = 'YYYY-MM-DD HH:mm:ss'; + const dateFormat = 'YYYY-MM-DD'; const fromDate = moment(startDate).startOf(type).format(dateFormat); const toDate = moment(endDate).endOf(type).format(dateFormat); diff --git a/packages/server/src/models/InventoryTransaction.ts b/packages/server/src/models/InventoryTransaction.ts index 16db33993..ffdf2471d 100644 --- a/packages/server/src/models/InventoryTransaction.ts +++ b/packages/server/src/models/InventoryTransaction.ts @@ -1,9 +1,13 @@ import { Model, raw } from 'objection'; -import { castArray, isEmpty } from 'lodash'; +import { castArray } from 'lodash'; import moment from 'moment'; import TenantModel from 'models/TenantModel'; +import { getTransactionTypeLabel } from '@/utils/transactions-types'; export default class InventoryTransaction extends TenantModel { + transactionId: number; + transactionType: string; + /** * Table name */ @@ -23,27 +27,7 @@ export default class InventoryTransaction extends TenantModel { * @return {string} */ get transcationTypeFormatted() { - return InventoryTransaction.getReferenceTypeFormatted(this.transactionType); - } - - /** - * Reference type formatted. - */ - static getReferenceTypeFormatted(referenceType) { - const mapped = { - SaleInvoice: 'Sale invoice', - SaleReceipt: 'Sale receipt', - PaymentReceive: 'Payment receive', - Bill: 'Bill', - BillPayment: 'Payment made', - VendorOpeningBalance: 'Vendor opening balance', - CustomerOpeningBalance: 'Customer opening balance', - InventoryAdjustment: 'Inventory adjustment', - ManualJournal: 'Manual journal', - Journal: 'Manual journal', - LandedCost: 'transaction_type.landed_cost', - }; - return mapped[referenceType] || ''; + return getTransactionTypeLabel(this.transactionType); } /** @@ -52,7 +36,7 @@ export default class InventoryTransaction extends TenantModel { static get modifiers() { return { filterDateRange(query, startDate, endDate, type = 'day') { - const dateFormat = 'YYYY-MM-DD HH:mm:ss'; + const dateFormat = 'YYYY-MM-DD'; const fromDate = moment(startDate).startOf(type).format(dateFormat); const toDate = moment(endDate).endOf(type).format(dateFormat); diff --git a/packages/server/src/models/SaleInvoice.ts b/packages/server/src/models/SaleInvoice.ts index ca2612397..5bbeb51fc 100644 --- a/packages/server/src/models/SaleInvoice.ts +++ b/packages/server/src/models/SaleInvoice.ts @@ -284,7 +284,7 @@ export default class SaleInvoice extends mixin(TenantModel, [ * Filters the invoices between the given date range. */ filterDateRange(query, startDate, endDate, type = 'day') { - const dateFormat = 'YYYY-MM-DD HH:mm:ss'; + const dateFormat = 'YYYY-MM-DD'; const fromDate = moment(startDate).startOf(type).format(dateFormat); const toDate = moment(endDate).endOf(type).format(dateFormat); diff --git a/packages/server/src/models/Warehouse.ts b/packages/server/src/models/Warehouse.ts index 12058d396..6657c9a15 100644 --- a/packages/server/src/models/Warehouse.ts +++ b/packages/server/src/models/Warehouse.ts @@ -84,7 +84,7 @@ export default class Warehouse extends TenantModel { }, /** - * Warehouse may belongs to assocaited bills. + * Warehouse may belongs to associated bills. */ bills: { relation: Model.HasManyRelation, diff --git a/packages/server/src/services/Accounting/AcountsTransactionsWarehouses.ts b/packages/server/src/services/Accounting/AccountsTransactionsWarehouses.ts similarity index 100% rename from packages/server/src/services/Accounting/AcountsTransactionsWarehouses.ts rename to packages/server/src/services/Accounting/AccountsTransactionsWarehouses.ts diff --git a/packages/server/src/services/Accounting/AccountsTransactionsWarehousesSubscribe.ts b/packages/server/src/services/Accounting/AccountsTransactionsWarehousesSubscribe.ts index dd6486e91..b109d1237 100644 --- a/packages/server/src/services/Accounting/AccountsTransactionsWarehousesSubscribe.ts +++ b/packages/server/src/services/Accounting/AccountsTransactionsWarehousesSubscribe.ts @@ -1,6 +1,6 @@ import { Service, Inject } from 'typedi'; import events from '@/subscribers/events'; -import { InventoryTransactionsWarehouses } from './AcountsTransactionsWarehouses'; +import { InventoryTransactionsWarehouses } from './AccountsTransactionsWarehouses'; import { IBranchesActivatedPayload } from '@/interfaces'; @Service() diff --git a/packages/server/src/services/Accounting/JournalPoster.ts b/packages/server/src/services/Accounting/JournalPoster.ts index d3400396d..1a2787488 100644 --- a/packages/server/src/services/Accounting/JournalPoster.ts +++ b/packages/server/src/services/Accounting/JournalPoster.ts @@ -79,7 +79,7 @@ export default class JournalPoster implements IJournalPoster { } /** - * Async initialize acccounts dependency graph. + * Async initialize accounts dependency graph. * @private * @returns {Promise} */ diff --git a/packages/server/src/services/Accounting/LedgerContactStorage.ts b/packages/server/src/services/Accounting/LedgerContactStorage.ts index f8a484122..11825db8f 100644 --- a/packages/server/src/services/Accounting/LedgerContactStorage.ts +++ b/packages/server/src/services/Accounting/LedgerContactStorage.ts @@ -66,14 +66,14 @@ export class LedgerContactsBalanceStorage { ): Promise<(entry: ILedgerEntry) => boolean> => { const { Account } = this.tenancy.models(tenantId); - const ARAPAcounts = await Account.query(trx).whereIn('accountType', [ + const ARAPAccounts = await Account.query(trx).whereIn('accountType', [ ACCOUNT_TYPE.ACCOUNTS_RECEIVABLE, ACCOUNT_TYPE.ACCOUNTS_PAYABLE, ]); - const ARAPAcountsIds = ARAPAcounts.map((a) => a.id); + const ARAPAccountsIds = ARAPAccounts.map((a) => a.id); return (entry: ILedgerEntry) => { - return ARAPAcountsIds.indexOf(entry.accountId) !== -1; + return ARAPAccountsIds.indexOf(entry.accountId) !== -1; }; }; diff --git a/packages/server/src/services/Accounting/LedgerStorageService.ts b/packages/server/src/services/Accounting/LedgerStorageService.ts index 2ab78d8fb..616ae6230 100644 --- a/packages/server/src/services/Accounting/LedgerStorageService.ts +++ b/packages/server/src/services/Accounting/LedgerStorageService.ts @@ -35,7 +35,7 @@ export default class LedgerStorageService { // Saves the ledger entries. this.ledgerEntriesService.saveEntries(tenantId, ledger, trx), - // Mutates the assocaited accounts balances. + // Mutates the associated accounts balances. this.ledgerAccountsBalance.saveAccountsBalance(tenantId, ledger, trx), // Mutates the associated contacts balances. @@ -60,7 +60,7 @@ export default class LedgerStorageService { // Deletes the ledger entries. this.ledgerEntriesService.deleteEntries(tenantId, ledger, trx), - // Mutates the assocaited accounts balances. + // Mutates the associated accounts balances. this.ledgerAccountsBalance.saveAccountsBalance(tenantId, ledger, trx), // Mutates the associated contacts balances. diff --git a/packages/server/src/services/Accounting/LedgetAccountStorage.ts b/packages/server/src/services/Accounting/LedgetAccountStorage.ts index 0bb5ae8fb..92d02c07e 100644 --- a/packages/server/src/services/Accounting/LedgetAccountStorage.ts +++ b/packages/server/src/services/Accounting/LedgetAccountStorage.ts @@ -108,7 +108,7 @@ export class LedegrAccountsStorage { const { Account } = this.tenancy.models(tenantId); const account = await Account.query(trx).findById(accountId); - // Filters the ledger entries by the current acount. + // Filters the ledger entries by the current account. const accountLedger = ledger.whereAccountId(accountId); // Retrieves the given tenant metadata. diff --git a/packages/server/src/services/Accounts/AccountTransactionTransformer.ts b/packages/server/src/services/Accounts/AccountTransactionTransformer.ts index e239b4da9..857fe5ccc 100644 --- a/packages/server/src/services/Accounts/AccountTransactionTransformer.ts +++ b/packages/server/src/services/Accounts/AccountTransactionTransformer.ts @@ -46,7 +46,7 @@ export default class AccountTransactionTransformer extends Transformer { * @returns {string} */ public transactionTypeFormatted(transaction: IAccountTransaction) { - return transaction.referenceTypeFormatted; + return this.context.i18n.__(transaction.referenceTypeFormatted); } /** diff --git a/packages/server/src/services/Accounts/DeleteAccount.ts b/packages/server/src/services/Accounts/DeleteAccount.ts index 4534d5fdd..d8d499c58 100644 --- a/packages/server/src/services/Accounts/DeleteAccount.ts +++ b/packages/server/src/services/Accounts/DeleteAccount.ts @@ -77,7 +77,7 @@ export class DeleteAccount { // Authorize before delete account. await this.authorize(tenantId, accountId, oldAccount); - // Deletes the account and assocaited transactions under UOW envirement. + // Deletes the account and associated transactions under UOW envirement. return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => { // Triggers `onAccountDelete` event. await this.eventPublisher.emitAsync(events.accounts.onDelete, { diff --git a/packages/server/src/services/Accounts/GetAccounts.ts b/packages/server/src/services/Accounts/GetAccounts.ts index c9f1b1d5f..17d19bad2 100644 --- a/packages/server/src/services/Accounts/GetAccounts.ts +++ b/packages/server/src/services/Accounts/GetAccounts.ts @@ -23,15 +23,6 @@ export class GetAccounts { @Inject() private transformer: TransformerInjectable; - /** - * Parsees accounts list filter DTO. - * @param filterDTO - * @returns - */ - private parseListFilterDTO(filterDTO) { - return R.compose(this.dynamicListService.parseStringifiedFilter)(filterDTO); - } - /** * Retrieve accounts datatable list. * @param {number} tenantId @@ -75,4 +66,13 @@ export class GetAccounts { filterMeta: dynamicList.getResponseMeta(), }; }; + + /** + * Parsees accounts list filter DTO. + * @param filterDTO + * @returns + */ + private parseListFilterDTO(filterDTO) { + return R.compose(this.dynamicListService.parseStringifiedFilter)(filterDTO); + } } diff --git a/packages/server/src/services/AccountsReceivable/AccountsReceivableRepository.ts b/packages/server/src/services/AccountsReceivable/AccountsReceivableRepository.ts deleted file mode 100644 index 17bd1f154..000000000 --- a/packages/server/src/services/AccountsReceivable/AccountsReceivableRepository.ts +++ /dev/null @@ -1,9 +0,0 @@ - - -export class AccountsReceivableRepository { - - - findOrCreateAccount = (currencyCode?: string) => { - - }; -} \ No newline at end of file diff --git a/packages/server/src/services/Branches/Subscribers/Activate/CashflowBranchesActviateSubscriber.ts b/packages/server/src/services/Branches/Subscribers/Activate/CashflowBranchesActivateSubscriber.ts similarity index 100% rename from packages/server/src/services/Branches/Subscribers/Activate/CashflowBranchesActviateSubscriber.ts rename to packages/server/src/services/Branches/Subscribers/Activate/CashflowBranchesActivateSubscriber.ts diff --git a/packages/server/src/services/Branches/Subscribers/Activate/index.ts b/packages/server/src/services/Branches/Subscribers/Activate/index.ts index fa691a069..97aeadcee 100644 --- a/packages/server/src/services/Branches/Subscribers/Activate/index.ts +++ b/packages/server/src/services/Branches/Subscribers/Activate/index.ts @@ -1,4 +1,4 @@ -export * from './CashflowBranchesActviateSubscriber'; +export * from './CashflowBranchesActivateSubscriber'; export * from './CreditNoteBranchesActivateSubscriber'; export * from './PaymentMadeBranchesActivateSubscriber'; export * from './PaymentReceiveBranchesActivateSubscriber'; diff --git a/packages/server/src/services/Cashflow/CommandCasflowValidator.ts b/packages/server/src/services/Cashflow/CommandCasflowValidator.ts index 81c0aaffb..07722e50e 100644 --- a/packages/server/src/services/Cashflow/CommandCasflowValidator.ts +++ b/packages/server/src/services/Cashflow/CommandCasflowValidator.ts @@ -1,17 +1,12 @@ -import { Service, Inject } from 'typedi'; -import { includes, difference, camelCase, upperFirst } from 'lodash'; -import { ACCOUNT_TYPE } from '@/data/AccountTypes'; -import { IAccount, ICashflowTransactionLine } from '@/interfaces'; +import { Service } from 'typedi'; +import { includes, camelCase, upperFirst } from 'lodash'; +import { IAccount } from '@/interfaces'; import { getCashflowTransactionType } from './utils'; import { ServiceError } from '@/exceptions'; import { CASHFLOW_TRANSACTION_TYPE, ERRORS } from './constants'; -import HasTenancyService from '@/services/Tenancy/TenancyService'; @Service() export class CommandCashflowValidator { - @Inject() - private tenancy: HasTenancyService; - /** * Validates the lines accounts type should be cash or bank account. * @param {IAccount} accounts - diff --git a/packages/server/src/services/Cashflow/CommandCashflowTransaction.ts b/packages/server/src/services/Cashflow/CommandCashflowTransaction.ts deleted file mode 100644 index 9a562e404..000000000 --- a/packages/server/src/services/Cashflow/CommandCashflowTransaction.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { difference, includes } from 'lodash'; -import { ICashflowTransactionLine } from '@/interfaces'; -import { ServiceError } from '@/exceptions'; -import { Inject, Service } from 'typedi'; -import { CASHFLOW_TRANSACTION_TYPE, ERRORS } from './constants'; -import { IAccount } from '@/interfaces'; -import HasTenancyService from '@/services/Tenancy/TenancyService'; - -@Service() -export default class CommandCashflowTransaction { - @Inject() - private tenancy: HasTenancyService; - -} diff --git a/packages/server/src/services/Cashflow/utils.ts b/packages/server/src/services/Cashflow/utils.ts index f9cb1ad6b..31af4b1bc 100644 --- a/packages/server/src/services/Cashflow/utils.ts +++ b/packages/server/src/services/Cashflow/utils.ts @@ -6,7 +6,7 @@ import { } from './constants'; /** - * Ensures the given transaction type to transformed to properiate format. + * Ensures the given transaction type to transformed to appropriate format. * @param {string} type * @returns {string} */ diff --git a/packages/server/src/services/CreditNotes/CreateCreditNote.ts b/packages/server/src/services/CreditNotes/CreateCreditNote.ts index 2c4c0d58f..641d1034e 100644 --- a/packages/server/src/services/CreditNotes/CreateCreditNote.ts +++ b/packages/server/src/services/CreditNotes/CreateCreditNote.ts @@ -16,16 +16,16 @@ import BaseCreditNotes from './CreditNotes'; @Service() export default class CreateCreditNote extends BaseCreditNotes { @Inject() - uow: UnitOfWork; + private uow: UnitOfWork; @Inject() - itemsEntriesService: ItemsEntriesService; + private itemsEntriesService: ItemsEntriesService; @Inject() - tenancy: HasTenancyService; + private tenancy: HasTenancyService; @Inject() - eventPublisher: EventPublisher; + private eventPublisher: EventPublisher; /** * Creates a new credit note. diff --git a/packages/server/src/services/CreditNotes/CreditNoteApplySyncInvoicesSubscriber.ts b/packages/server/src/services/CreditNotes/CreditNoteApplySyncInvoicesSubscriber.ts index 3a4e7f59b..f22a6c03e 100644 --- a/packages/server/src/services/CreditNotes/CreditNoteApplySyncInvoicesSubscriber.ts +++ b/packages/server/src/services/CreditNotes/CreditNoteApplySyncInvoicesSubscriber.ts @@ -1,5 +1,4 @@ import { Service, Inject } from 'typedi'; -import HasTenancyService from '@/services/Tenancy/TenancyService'; import events from '@/subscribers/events'; import { IApplyCreditToInvoicesCreatedPayload, @@ -10,15 +9,12 @@ import CreditNoteApplySyncInvoicesCreditedAmount from './CreditNoteApplySyncInvo @Service() export default class CreditNoteApplySyncInvoicesCreditedAmountSubscriber { @Inject() - tenancy: HasTenancyService; - - @Inject() - syncInvoicesWithCreditNote: CreditNoteApplySyncInvoicesCreditedAmount; + private syncInvoicesWithCreditNote: CreditNoteApplySyncInvoicesCreditedAmount; /** * Attaches events with handlers. */ - attach(bus) { + public attach(bus) { bus.subscribe( events.creditNote.onApplyToInvoicesCreated, this.incrementAppliedInvoicesOnceCreditCreated diff --git a/packages/server/src/services/CreditNotes/CreditNoteInventoryTransactionsSubscriber.ts b/packages/server/src/services/CreditNotes/CreditNoteInventoryTransactionsSubscriber.ts index 7b23d079d..54b702bea 100644 --- a/packages/server/src/services/CreditNotes/CreditNoteInventoryTransactionsSubscriber.ts +++ b/packages/server/src/services/CreditNotes/CreditNoteInventoryTransactionsSubscriber.ts @@ -15,7 +15,7 @@ export default class CreditNoteInventoryTransactionsSubscriber { /** * Attaches events with publisher. */ - attach(bus) { + public attach(bus) { bus.subscribe( events.creditNote.onCreated, this.writeInventoryTranscationsOnceCreated @@ -37,6 +37,7 @@ export default class CreditNoteInventoryTransactionsSubscriber { /** * Writes inventory transactions once credit note created. * @param {ICreditNoteCreatedPayload} payload - + * @returns {Promise} */ public writeInventoryTranscationsOnceCreated = async ({ tenantId, @@ -44,9 +45,8 @@ export default class CreditNoteInventoryTransactionsSubscriber { trx, }: ICreditNoteCreatedPayload) => { // Can't continue if the credit note is open yet. - if (!creditNote.isOpen) { - return; - } + if (!creditNote.isOpen) return; + await this.inventoryTransactions.createInventoryTransactions( tenantId, creditNote, @@ -57,6 +57,7 @@ export default class CreditNoteInventoryTransactionsSubscriber { /** * Rewrites inventory transactions once credit note edited. * @param {ICreditNoteEditedPayload} payload - + * @returns {Promise} */ public rewriteInventoryTransactionsOnceEdited = async ({ tenantId, @@ -65,9 +66,8 @@ export default class CreditNoteInventoryTransactionsSubscriber { trx, }: ICreditNoteEditedPayload) => { // Can't continue if the credit note is open yet. - if (!creditNote.isOpen) { - return; - } + if (!creditNote.isOpen) return; + await this.inventoryTransactions.editInventoryTransactions( tenantId, creditNoteId, @@ -87,9 +87,8 @@ export default class CreditNoteInventoryTransactionsSubscriber { trx, }: ICreditNoteDeletedPayload) => { // Can't continue if the credit note is open yet. - if (!oldCreditNote.isOpen) { - return; - } + if (!oldCreditNote.isOpen) return; + await this.inventoryTransactions.deleteInventoryTransactions( tenantId, creditNoteId, diff --git a/packages/server/src/services/CreditNotes/CreditNotesInventoryTransactions.ts b/packages/server/src/services/CreditNotes/CreditNotesInventoryTransactions.ts index 175b640b6..857f5fc89 100644 --- a/packages/server/src/services/CreditNotes/CreditNotesInventoryTransactions.ts +++ b/packages/server/src/services/CreditNotes/CreditNotesInventoryTransactions.ts @@ -49,7 +49,7 @@ export default class CreditNoteInventoryTransactions { }; /** - * Edits vendor credit assocaited inventory transactions. + * Edits vendor credit associated inventory transactions. * @param {number} tenantId * @param {number} creditNoteId * @param {ICreditNote} creditNote diff --git a/packages/server/src/services/CreditNotes/DeleteCustomerLinkedCreditSubscriber.ts b/packages/server/src/services/CreditNotes/DeleteCustomerLinkedCreditSubscriber.ts index 4f1727c5c..4f1fb3e9d 100644 --- a/packages/server/src/services/CreditNotes/DeleteCustomerLinkedCreditSubscriber.ts +++ b/packages/server/src/services/CreditNotes/DeleteCustomerLinkedCreditSubscriber.ts @@ -29,7 +29,7 @@ export default class DeleteCustomerLinkedCreditSubscriber { }; /** - * Validate vendor has no assocaited credit transaction once the vendor deleting. + * Validate vendor has no associated credit transaction once the vendor deleting. * @param {IVendorEventDeletingPayload} payload - */ public validateCustomerHasNoLinkedCreditsOnDeleting = async ({ diff --git a/packages/server/src/services/DynamicListing/DynamicListAbstract.ts b/packages/server/src/services/DynamicListing/DynamicListAbstract.ts new file mode 100644 index 000000000..216ace346 --- /dev/null +++ b/packages/server/src/services/DynamicListing/DynamicListAbstract.ts @@ -0,0 +1,6 @@ + + + +export default class DynamicListAbstract { + +} \ No newline at end of file diff --git a/packages/server/src/services/DynamicListing/DynamicListAbstruct.ts b/packages/server/src/services/DynamicListing/DynamicListAbstruct.ts deleted file mode 100644 index d7997966b..000000000 --- a/packages/server/src/services/DynamicListing/DynamicListAbstruct.ts +++ /dev/null @@ -1,6 +0,0 @@ - - - -export default class DynamicListAbstruct { - -} \ No newline at end of file diff --git a/packages/server/src/services/DynamicListing/DynamicListCustomView.ts b/packages/server/src/services/DynamicListing/DynamicListCustomView.ts index 7642bd4c4..a46f6ee98 100644 --- a/packages/server/src/services/DynamicListing/DynamicListCustomView.ts +++ b/packages/server/src/services/DynamicListing/DynamicListCustomView.ts @@ -1,5 +1,5 @@ import { Inject, Service } from 'typedi'; -import DynamicListAbstruct from './DynamicListAbstruct'; +import DynamicListAbstract from './DynamicListAbstract'; import DynamicFilterViews from '@/lib/DynamicFilter/DynamicFilterViews'; import { ServiceError } from '@/exceptions'; import HasTenancyService from '@/services/Tenancy/TenancyService'; @@ -7,7 +7,7 @@ import { ERRORS } from './constants'; import { IModel } from '@/interfaces'; @Service() -export default class DynamicListCustomView extends DynamicListAbstruct { +export default class DynamicListCustomView extends DynamicListAbstract { @Inject() tenancy: HasTenancyService; diff --git a/packages/server/src/services/DynamicListing/DynamicListFilterRoles.ts b/packages/server/src/services/DynamicListing/DynamicListFilterRoles.ts index 688b05b09..8f8485036 100644 --- a/packages/server/src/services/DynamicListing/DynamicListFilterRoles.ts +++ b/packages/server/src/services/DynamicListing/DynamicListFilterRoles.ts @@ -2,13 +2,13 @@ import { Service } from 'typedi'; import * as R from 'ramda'; import validator from 'is-my-json-valid'; import { IFilterRole, IModel } from '@/interfaces'; -import DynamicListAbstruct from './DynamicListAbstruct'; +import DynamicListAbstract from './DynamicListAbstract'; import DynamicFilterAdvancedFilter from '@/lib/DynamicFilter/DynamicFilterAdvancedFilter'; import { ERRORS } from './constants'; import { ServiceError } from '@/exceptions'; @Service() -export default class DynamicListFilterRoles extends DynamicListAbstruct { +export default class DynamicListFilterRoles extends DynamicListAbstract { /** * Validates filter roles schema. * @param {IFilterRole[]} filterRoles - Filter roles. diff --git a/packages/server/src/services/DynamicListing/DynamicListSearch.ts b/packages/server/src/services/DynamicListing/DynamicListSearch.ts index 517a15460..7dadaa897 100644 --- a/packages/server/src/services/DynamicListing/DynamicListSearch.ts +++ b/packages/server/src/services/DynamicListing/DynamicListSearch.ts @@ -1,11 +1,11 @@ import { Service } from 'typedi'; import { IFilterRole, IModel } from '@/interfaces'; -import DynamicListAbstruct from './DynamicListAbstruct'; +import DynamicListAbstract from './DynamicListAbstract'; import DynamicFilterFilterRoles from '@/lib/DynamicFilter/DynamicFilterFilterRoles'; import DynamicFilterSearch from '@/lib/DynamicFilter/DynamicFilterSearch'; @Service() -export default class DynamicListSearch extends DynamicListAbstruct { +export default class DynamicListSearch extends DynamicListAbstract { /** * Dynamic list filter roles. * @param {IModel} model diff --git a/packages/server/src/services/DynamicListing/DynamicListSortBy.ts b/packages/server/src/services/DynamicListing/DynamicListSortBy.ts index 594e1c141..0e236edb0 100644 --- a/packages/server/src/services/DynamicListing/DynamicListSortBy.ts +++ b/packages/server/src/services/DynamicListing/DynamicListSortBy.ts @@ -1,12 +1,12 @@ import { Service } from 'typedi'; -import DynamicListAbstruct from './DynamicListAbstruct'; +import DynamicListAbstract from './DynamicListAbstract'; import DynamicFilterSortBy from '@/lib/DynamicFilter/DynamicFilterSortBy'; import { IModel, ISortOrder } from '@/interfaces'; import { ServiceError } from '@/exceptions'; import { ERRORS } from './constants'; @Service() -export default class DynamicListSortBy extends DynamicListAbstruct { +export default class DynamicListSortBy extends DynamicListAbstract { /** * Dynamic list sort by. * @param {IModel} model diff --git a/packages/server/src/services/Expenses/ExpenseGLEntriesSubscriber.ts b/packages/server/src/services/Expenses/ExpenseGLEntriesSubscriber.ts index 56d37a7db..1a177876e 100644 --- a/packages/server/src/services/Expenses/ExpenseGLEntriesSubscriber.ts +++ b/packages/server/src/services/Expenses/ExpenseGLEntriesSubscriber.ts @@ -21,7 +21,7 @@ export class ExpensesWriteGLSubscriber { * Attaches events with handlers. * @param bus */ - attach(bus) { + public attach(bus) { bus.subscribe( events.expenses.onCreated, this.handleWriteGLEntriesOnceCreated diff --git a/packages/server/src/services/Features/FeaturesManager.ts b/packages/server/src/services/Features/FeaturesManager.ts index c57f3663e..2ee0265be 100644 --- a/packages/server/src/services/Features/FeaturesManager.ts +++ b/packages/server/src/services/Features/FeaturesManager.ts @@ -34,7 +34,7 @@ export class FeaturesManager { } /** - * Detarmines the given feature name is accessiable. + * Detarmines the given feature name is accessible. * @param {number} tenantId * @param {string} feature * @returns {Promise} diff --git a/packages/server/src/services/Features/FeaturesSettingsDriver.ts b/packages/server/src/services/Features/FeaturesSettingsDriver.ts index 6e3827951..dd0c98022 100644 --- a/packages/server/src/services/Features/FeaturesSettingsDriver.ts +++ b/packages/server/src/services/Features/FeaturesSettingsDriver.ts @@ -33,7 +33,7 @@ export class FeaturesSettingsDriver { } /** - * Detarmines the given feature name is accessiable. + * Detarmines the given feature name is accessible. * @param {number} tenantId * @param {string} feature * @returns {Promise} diff --git a/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummaryService.ts b/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummaryService.ts index ad85b1688..73860c9a5 100644 --- a/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummaryService.ts +++ b/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummaryService.ts @@ -5,6 +5,7 @@ import TenancyService from '@/services/Tenancy/TenancyService'; import APAgingSummarySheet from './APAgingSummarySheet'; import { Tenant } from '@/system/models'; import { isEmpty } from 'lodash'; +import APAgingSummaryTable from './APAgingSummaryTable'; @Service() export default class PayableAgingSummaryService { @@ -84,7 +85,7 @@ export default class PayableAgingSummaryService { // Common query. const commonQuery = (query) => { - if (isEmpty(filter.branchesIds)) { + if (!isEmpty(filter.branchesIds)) { query.modify('filterByBranches', filter.branchesIds); } }; @@ -118,4 +119,21 @@ export default class PayableAgingSummaryService { meta: this.reportMetadata(tenantId), }; } + + /** + * Retrieves A/P aging summary in table format. + * @param {number} tenantId + * @param {IAPAgingSummaryQuery} query + */ + async APAgingSummaryTable(tenantId: number, query: IAPAgingSummaryQuery) { + const report = await this.APAgingSummary(tenantId, query); + const table = new APAgingSummaryTable(report.data, query, {}); + + return { + columns: table.tableColumns(), + rows: table.tableRows(), + meta: report.meta, + query: report.query, + }; + } } diff --git a/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummarySheet.ts b/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummarySheet.ts index dff23c4b6..ba42812ac 100644 --- a/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummarySheet.ts +++ b/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummarySheet.ts @@ -91,7 +91,7 @@ export default class APAgingSummarySheet extends AgingSummaryReport { return { vendorName: vendor.displayName, - current: this.formatTotalAmount(currentTotal), + current: this.formatAmount(currentTotal), aging: agingPeriods, total: this.formatTotalAmount(amount), }; diff --git a/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummaryTable.ts b/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummaryTable.ts new file mode 100644 index 000000000..b74e748d7 --- /dev/null +++ b/packages/server/src/services/FinancialStatements/AgingSummary/APAgingSummaryTable.ts @@ -0,0 +1,46 @@ +import { + IAPAgingSummaryData, + IAgingSummaryQuery, + ITableColumn, + ITableColumnAccessor, + ITableRow, +} from '@/interfaces'; +import AgingSummaryTable from './AgingSummaryTable'; + +export default class APAgingSummaryTable extends AgingSummaryTable { + readonly report: IAPAgingSummaryData; + + /** + * Constructor method. + * @param {IARAgingSummaryData} data + * @param {IAgingSummaryQuery} query + * @param {any} i18n + */ + constructor(data: IAPAgingSummaryData, query: IAgingSummaryQuery, i18n: any) { + super(data, query, i18n); + } + + /** + * Retrieves the contacts table rows. + * @returns {ITableRow[]} + */ + get contactsRows(): ITableRow[] { + return this.contactsNodes(this.report.vendors); + } + + /** + * Contact name node accessor. + * @returns {ITableColumnAccessor} + */ + get contactNameNodeAccessor(): ITableColumnAccessor { + return { key: 'vendor_name', accessor: 'vendorName' }; + } + + /** + * Retrieves the contact name table column. + * @returns {ITableColumn} + */ + contactNameTableColumn = (): ITableColumn => { + return { label: 'Vendor name', key: 'vendor_name' }; + }; +} diff --git a/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryService.ts b/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryService.ts index b1a5764af..60bdb8675 100644 --- a/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryService.ts +++ b/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryService.ts @@ -5,6 +5,7 @@ import { IARAgingSummaryQuery, IARAgingSummaryMeta } from '@/interfaces'; import TenancyService from '@/services/Tenancy/TenancyService'; import ARAgingSummarySheet from './ARAgingSummarySheet'; import { Tenant } from '@/system/models'; +import ARAgingSummaryTable from './ARAgingSummaryTable'; @Service() export default class ARAgingSummaryService { @@ -89,12 +90,12 @@ export default class ARAgingSummaryService { }; // Retrieve all overdue sale invoices. const overdueSaleInvoices = await SaleInvoice.query() - .modify('dueInvoicesFromDate', filter.asDate) + .modify('overdueInvoicesFromDate', filter.asDate) .onBuild(commonQuery); // Retrieve all due sale invoices. const currentInvoices = await SaleInvoice.query() - .modify('overdueInvoicesFromDate', filter.asDate) + .modify('dueInvoicesFromDate', filter.asDate) .onBuild(commonQuery); // AR aging summary report instance. @@ -117,4 +118,21 @@ export default class ARAgingSummaryService { meta: this.reportMetadata(tenantId), }; } + + /** + * Retrieves A/R aging summary in table format. + * @param {number} tenantId + * @param {IARAgingSummaryQuery} query + */ + async ARAgingSummaryTable(tenantId: number, query: IARAgingSummaryQuery) { + const report = await this.ARAgingSummary(tenantId, query); + const table = new ARAgingSummaryTable(report.data, query, {}); + + return { + columns: table.tableColumns(), + rows: table.tableRows(), + meta: report.meta, + query, + }; + } } diff --git a/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummarySheet.ts b/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummarySheet.ts index 0dba17a1e..a9f1856c2 100644 --- a/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummarySheet.ts +++ b/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummarySheet.ts @@ -1,4 +1,4 @@ -import { groupBy, isEmpty, sum } from 'lodash'; +import { Dictionary, groupBy, isEmpty, sum } from 'lodash'; import * as R from 'ramda'; import { ICustomer, @@ -54,7 +54,6 @@ export default class ARAgingSummarySheet extends AgingSummaryReport { currentSaleInvoices, 'customerId' ); - // Initializes the aging periods. this.agingPeriods = this.agingRangePeriods( this.query.asDate, @@ -189,7 +188,7 @@ export default class ARAgingSummarySheet extends AgingSummaryReport { }; /** - * Retrieve AR aging summary report columns. + * Retrieve A/R aging summary report columns. * @return {IARAgingSummaryColumns} */ public reportColumns(): IARAgingSummaryColumns { diff --git a/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryTable.ts b/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryTable.ts new file mode 100644 index 000000000..5e0ad88b3 --- /dev/null +++ b/packages/server/src/services/FinancialStatements/AgingSummary/ARAgingSummaryTable.ts @@ -0,0 +1,38 @@ +import { + IARAgingSummaryData, + IAgingSummaryData, + IAgingSummaryQuery, + ITableColumnAccessor, + ITableRow, +} from '@/interfaces'; +import AgingSummaryTable from './AgingSummaryTable'; + +export default class ARAgingSummaryTable extends AgingSummaryTable { + readonly report: IARAgingSummaryData; + + /** + * Constructor method. + * @param {IARAgingSummaryData} data + * @param {IAgingSummaryQuery} query + * @param {any} i18n + */ + constructor(data: IARAgingSummaryData, query: IAgingSummaryQuery, i18n: any) { + super(data, query, i18n); + } + + /** + * Retrieves the contacts table rows. + * @returns {ITableRow[]} + */ + get contactsRows(): ITableRow[] { + return this.contactsNodes(this.report.customers); + } + + /** + * Contact name node accessor. + * @returns {ITableColumnAccessor} + */ + get contactNameNodeAccessor(): ITableColumnAccessor { + return { key: 'customer_name', accessor: 'customerName' }; + } +} diff --git a/packages/server/src/services/FinancialStatements/AgingSummary/AgingSummaryTable.ts b/packages/server/src/services/FinancialStatements/AgingSummary/AgingSummaryTable.ts new file mode 100644 index 000000000..3b74c76ac --- /dev/null +++ b/packages/server/src/services/FinancialStatements/AgingSummary/AgingSummaryTable.ts @@ -0,0 +1,211 @@ +import * as R from 'ramda'; +import { + IAgingPeriod, + IAgingSummaryContact, + IAgingSummaryData, + IAgingSummaryQuery, + IAgingSummaryTotal, + ITableColumn, + ITableColumnAccessor, + ITableRow, +} from '@/interfaces'; +import { tableRowMapper } from '@/utils'; +import AgingReport from './AgingReport'; +import { AgingSummaryRowType } from './_constants'; +import { FinancialTable } from '../FinancialTable'; +import { FinancialSheetStructure } from '../FinancialSheetStructure'; + +export default abstract class AgingSummaryTable extends R.compose( + FinancialSheetStructure, + FinancialTable +)(AgingReport) { + protected readonly report: IAgingSummaryData; + protected readonly query: IAgingSummaryQuery; + protected readonly agingPeriods: IAgingPeriod[]; + protected readonly i18n: any; + + /** + * Constructor method. + * @param {IARAgingSummaryData} data + * @param {IAgingSummaryQuery} query + * @param {any} i18n + */ + constructor(data: IAgingSummaryData, query: IAgingSummaryQuery, i18n: any) { + super(); + + this.report = data; + this.i18n = i18n; + this.query = query; + + this.agingPeriods = this.agingRangePeriods( + this.query.asDate, + this.query.agingDaysBefore, + this.query.agingPeriods + ); + } + + // ------------------------- + // # Accessors. + // ------------------------- + /** + * Aging accessors of contact and total nodes. + * @param {IAgingSummaryContact | IAgingSummaryTotal} node + * @returns {ITableColumnAccessor[]} + */ + protected agingNodeAccessors = ( + node: IAgingSummaryContact | IAgingSummaryTotal + ): ITableColumnAccessor[] => { + return node.aging.map((aging, index) => ({ + key: 'aging', + accessor: `aging[${index}].total.formattedAmount`, + })); + }; + + /** + * Contact name node accessor. + * @returns {ITableColumnAccessor} + */ + protected get contactNameNodeAccessor(): ITableColumnAccessor { + return { key: 'customer_name', accessor: 'customerName' }; + } + + /** + * Retrieves the common columns for all report nodes. + * @param {IAgingSummaryContact} + * @returns {ITableColumnAccessor[]} + */ + protected contactNodeAccessors = ( + node: IAgingSummaryContact + ): ITableColumnAccessor[] => { + return R.compose( + R.concat([ + this.contactNameNodeAccessor, + { key: 'current', accessor: 'current.formattedAmount' }, + ...this.agingNodeAccessors(node), + { key: 'total', accessor: 'total.formattedAmount' }, + ]) + )([]); + }; + + /** + * Retrieves the contact name table row. + * @param {IAgingSummaryContact} node - + * @return {ITableRow} + */ + protected contactNameNode = (node: IAgingSummaryContact): ITableRow => { + const columns = this.contactNodeAccessors(node); + const meta = { + rowTypes: [AgingSummaryRowType.Contact], + }; + return tableRowMapper(node, columns, meta); + }; + + /** + * Maps the customers nodes to table rows. + * @param {IAgingSummaryContact[]} nodes + * @returns {ITableRow[]} + */ + protected contactsNodes = (nodes: IAgingSummaryContact[]): ITableRow[] => { + return nodes.map(this.contactNameNode); + }; + + /** + * Retrieves the common columns for all report nodes. + * @param {IAgingSummaryTotal} + * @returns {ITableColumnAccessor[]} + */ + protected totalNodeAccessors = ( + node: IAgingSummaryTotal + ): ITableColumnAccessor[] => { + return R.compose( + R.concat([ + { key: 'blank', value: '' }, + { key: 'current', accessor: 'current.formattedAmount' }, + ...this.agingNodeAccessors(node), + { key: 'total', accessor: 'total.formattedAmount' }, + ]) + )([]); + }; + + /** + * Retrieves the total row of the given report total node. + * @param {IAgingSummaryTotal} node + * @returns {ITableRow} + */ + protected totalNode = (node: IAgingSummaryTotal): ITableRow => { + const columns = this.totalNodeAccessors(node); + const meta = { + rowTypes: [AgingSummaryRowType.Total], + }; + return tableRowMapper(node, columns, meta); + }; + + // ------------------------- + // # Computed Rows. + // ------------------------- + /** + * Retrieves the contacts table rows. + * @returns {ITableRow[]} + */ + protected get contactsRows(): ITableRow[] { + return []; + } + + /** + * Table total row. + * @returns {ITableRow} + */ + protected get totalRow(): ITableRow { + return this.totalNode(this.report.total); + } + + /** + * Retrieves the table rows. + * @returns {ITableRow[]} + */ + public tableRows = (): ITableRow[] => { + return R.compose( + R.unless(R.isEmpty, R.append(this.totalRow)), + R.concat(this.contactsRows) + )([]); + }; + + // ------------------------- + // # Columns. + // ------------------------- + /** + * Retrieves the aging table columns. + * @returns {ITableColumn[]} + */ + protected agingTableColumns = (): ITableColumn[] => { + return this.agingPeriods.map((agingPeriod) => { + return { + label: `${agingPeriod.beforeDays} - ${ + agingPeriod.toDays || 'And Over' + }`, + key: 'aging_period', + }; + }); + }; + + /** + * Retrieves the contact name table column. + * @returns {ITableColumn} + */ + protected contactNameTableColumn = (): ITableColumn => { + return { label: 'Customer name', key: 'customer_name' }; + }; + + /** + * Retrieves the report columns. + * @returns {ITableColumn} + */ + public tableColumns = (): ITableColumn[] => { + return R.compose(this.tableColumnsCellIndexing)([ + this.contactNameTableColumn(), + { label: 'Current', key: 'current' }, + ...this.agingTableColumns(), + { label: 'Total', key: 'total' }, + ]); + }; +} diff --git a/packages/server/src/services/FinancialStatements/AgingSummary/_constants.ts b/packages/server/src/services/FinancialStatements/AgingSummary/_constants.ts new file mode 100644 index 000000000..961f0b7ed --- /dev/null +++ b/packages/server/src/services/FinancialStatements/AgingSummary/_constants.ts @@ -0,0 +1,4 @@ +export enum AgingSummaryRowType { + Contact = 'contact', + Total = 'total', +} diff --git a/packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetService.ts b/packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetService.ts index f674048bc..b0470c745 100644 --- a/packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetService.ts +++ b/packages/server/src/services/FinancialStatements/BalanceSheet/BalanceSheetService.ts @@ -37,7 +37,7 @@ export default class BalanceSheetStatementService displayColumnsBy: 'month', fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), + toDate: moment().format('YYYY-MM-DD'), numberFormat: { precision: 2, diff --git a/packages/server/src/services/FinancialStatements/CashFlow/CashFlow.ts b/packages/server/src/services/FinancialStatements/CashFlow/CashFlow.ts index fe2717fea..019b252ba 100644 --- a/packages/server/src/services/FinancialStatements/CashFlow/CashFlow.ts +++ b/packages/server/src/services/FinancialStatements/CashFlow/CashFlow.ts @@ -197,7 +197,7 @@ export default class CashFlowStatement extends compose( code: account.code, label: account.name, accountType: account.accountType, - adjusmentType: relation.direction, + adjustmentType: relation.direction, total: this.getAmountMeta(closingBalance), sectionType: ICashFlowStatementSectionType.ACCOUNT, }; @@ -362,14 +362,14 @@ export default class CashFlowStatement extends compose( /** * Retrieve the total section from the eqauation parser. * @param {ICashFlowSchemaTotalSection} sectionSchema - * @param {ICashFlowSchemaSection[]} accumlatedSections + * @param {ICashFlowSchemaSection[]} accumulatedSections * @returns {ICashFlowStatementTotalSection} */ private totalEquationSectionParser = ( - accumlatedSections: ICashFlowSchemaSection[], + accumulatedSections: ICashFlowSchemaSection[], sectionSchema: ICashFlowSchemaTotalSection ): ICashFlowStatementTotalSection => { - const mappedSectionsById = this.transformSectionsToMap(accumlatedSections); + const mappedSectionsById = this.transformSectionsToMap(accumulatedSections); const nodesTotalById = this.sectionsMapToTotal(mappedSectionsById); const total = this.evaluateEquation(sectionSchema.equation, nodesTotalById); @@ -421,7 +421,7 @@ export default class CashFlowStatement extends compose( code: account.code, label: account.name, accountType: account.accountType, - adjusmentType: relation.direction, + adjustmentType: relation.direction, total: this.getAmountMeta(closingBalance), sectionType: ICashFlowStatementSectionType.ACCOUNT, }; @@ -524,7 +524,7 @@ export default class CashFlowStatement extends compose( * @param {ICashFlowSchemaSection | ICashFlowStatementSection} section * @param {number} key * @param {ICashFlowSchemaSection[]} parentValue - * @param {(ICashFlowSchemaSection | ICashFlowStatementSection)[]} accumlatedSections + * @param {(ICashFlowSchemaSection | ICashFlowStatementSection)[]} accumulatedSections * @returns {ICashFlowSchemaSection} */ private schemaSectionTotalParser = ( @@ -532,13 +532,13 @@ export default class CashFlowStatement extends compose( key: number, parentValue: ICashFlowSchemaSection[], context, - accumlatedSections: (ICashFlowSchemaSection | ICashFlowStatementSection)[] + accumulatedSections: (ICashFlowSchemaSection | ICashFlowStatementSection)[] ): ICashFlowSchemaSection | ICashFlowStatementSection => { return R.compose( // Total equation section. R.when( this.isSchemaSectionType(ICashFlowStatementSectionType.TOTAL), - R.curry(this.totalEquationSectionParser)(accumlatedSections) + R.curry(this.totalEquationSectionParser)(accumulatedSections) ) )(section); }; diff --git a/packages/server/src/services/FinancialStatements/CashFlow/CashFlowDatePeriods.ts b/packages/server/src/services/FinancialStatements/CashFlow/CashFlowDatePeriods.ts index 864180b26..7d493cc5d 100644 --- a/packages/server/src/services/FinancialStatements/CashFlow/CashFlowDatePeriods.ts +++ b/packages/server/src/services/FinancialStatements/CashFlow/CashFlowDatePeriods.ts @@ -165,7 +165,7 @@ export const CashFlowStatementDatePeriods = (Base) => .whereAccountId(node.id) .getClosingBalance(); - return this.amountAdjustment(node.adjusmentType, closingBalance); + return this.amountAdjustment(node.adjustmentType, closingBalance); }; /** @@ -322,7 +322,7 @@ export const CashFlowStatementDatePeriods = (Base) => // Cash at beginning ---------------------- /** - * Retrieve the date preioods of the given node and accumlated function. + * Retrieve the date preioods of the given node and accumulated function. * @param {} node * @param {} * @return {} diff --git a/packages/server/src/services/FinancialStatements/CashFlow/CashFlowService.ts b/packages/server/src/services/FinancialStatements/CashFlow/CashFlowService.ts index 58fd5d2ad..09fdf91ca 100644 --- a/packages/server/src/services/FinancialStatements/CashFlow/CashFlowService.ts +++ b/packages/server/src/services/FinancialStatements/CashFlow/CashFlowService.ts @@ -40,7 +40,7 @@ export default class CashFlowStatementService displayColumnsType: 'total', displayColumnsBy: 'day', fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), + toDate: moment().format('YYYY-MM-DD'), numberFormat: { precision: 2, divideOn1000: false, diff --git a/packages/server/src/services/FinancialStatements/CashflowAccountTransactions/CashflowAccountTransactionsService.ts b/packages/server/src/services/FinancialStatements/CashflowAccountTransactions/CashflowAccountTransactionsService.ts index 7a41cef41..f3035a148 100644 --- a/packages/server/src/services/FinancialStatements/CashflowAccountTransactions/CashflowAccountTransactionsService.ts +++ b/packages/server/src/services/FinancialStatements/CashflowAccountTransactions/CashflowAccountTransactionsService.ts @@ -41,7 +41,7 @@ export default class CashflowAccountTransactionsService extends FinancialSheet { } /** - * Retrieve the cashflow accouynt transactions report data. + * Retrieve the cashflow account transactions report data. * @param {number} tenantId - * @param {ICashflowAccountTransactionsQuery} query - * @return {Promise} diff --git a/packages/server/src/services/FinancialStatements/FinancialDatePeriods.ts b/packages/server/src/services/FinancialStatements/FinancialDatePeriods.ts index e1c05e64e..cc79aa74d 100644 --- a/packages/server/src/services/FinancialStatements/FinancialDatePeriods.ts +++ b/packages/server/src/services/FinancialStatements/FinancialDatePeriods.ts @@ -64,7 +64,7 @@ export const FinancialDatePeriods = (Base) => }; /** - * Retrieve the date preioods of the given node and accumlated function. + * Retrieve the date preioods of the given node and accumulated function. * @param {IBalanceSheetAccountNode} node * @param {(fromDate: Date, toDate: Date, index: number) => any} * @return {} diff --git a/packages/server/src/services/FinancialStatements/FinancialTable.ts b/packages/server/src/services/FinancialStatements/FinancialTable.ts index 20ae528a2..0a7eafd01 100644 --- a/packages/server/src/services/FinancialStatements/FinancialTable.ts +++ b/packages/server/src/services/FinancialStatements/FinancialTable.ts @@ -12,7 +12,7 @@ export const FinancialTable = (Base) => * @param {ITableColumn[]} columns * @returns {ITableColumn[]} */ - protected tableColumnsCellIndexing = ( + public tableColumnsCellIndexing = ( columns: ITableColumn[] ): ITableColumn[] => { const cellIndex = increment(-1); diff --git a/packages/server/src/services/FinancialStatements/GeneralLedger/GeneralLedgerService.ts b/packages/server/src/services/FinancialStatements/GeneralLedger/GeneralLedgerService.ts index 74633d81e..012a05b94 100644 --- a/packages/server/src/services/FinancialStatements/GeneralLedger/GeneralLedgerService.ts +++ b/packages/server/src/services/FinancialStatements/GeneralLedger/GeneralLedgerService.ts @@ -31,8 +31,8 @@ export default class GeneralLedgerService { */ get defaultQuery() { return { - fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), + fromDate: moment().startOf('month').format('YYYY-MM-DD'), + toDate: moment().format('YYYY-MM-DD'), basis: 'cash', numberFormat: { noCents: false, diff --git a/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetails.ts b/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetails.ts index c626441e3..d09cf19cd 100644 --- a/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetails.ts +++ b/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetails.ts @@ -126,7 +126,7 @@ export default class InventoryDetails extends FinancialSheet { ); /** - * Accumlate and mapping running quantity on transactions. + * Accumulate and mapping running quantity on transactions. * @param {IInventoryDetailsItemTransaction[]} transactions * @returns {IInventoryDetailsItemTransaction[]} */ @@ -150,7 +150,7 @@ export default class InventoryDetails extends FinancialSheet { } /** - * Accumlate and mapping running valuation on transactions. + * Accumulate and mapping running valuation on transactions. * @param {IInventoryDetailsItemTransaction[]} transactions * @returns {IInventoryDetailsItemTransaction} */ @@ -160,8 +160,8 @@ export default class InventoryDetails extends FinancialSheet { const initial = this.getNumberMeta(0); const mapAccumAppender = (a, b) => { - const adjusmtent = b.direction === 'OUT' ? -1 : 1; - const total = a.runningValuation.number + b.cost.number * adjusmtent; + const adjustment = b.direction === 'OUT' ? -1 : 1; + const total = a.runningValuation.number + b.cost.number * adjustment; const totalMeta = this.getNumberMeta(total, { excerptZero: false }); const accum = { ...b, runningValuation: totalMeta }; diff --git a/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsService.ts b/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsService.ts index 7cc1d0667..cdeca4f39 100644 --- a/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsService.ts +++ b/packages/server/src/services/FinancialStatements/InventoryDetails/InventoryDetailsService.ts @@ -16,13 +16,13 @@ import { Tenant } from '@/system/models'; @Service() export default class InventoryDetailsService extends FinancialSheet { @Inject() - tenancy: TenancyService; + private tenancy: TenancyService; @Inject() - reportRepo: InventoryDetailsRepository; + private reportRepo: InventoryDetailsRepository; @Inject() - inventoryService: InventoryService; + private inventoryService: InventoryService; /** * Defaults balance sheet filter query. @@ -30,8 +30,8 @@ export default class InventoryDetailsService extends FinancialSheet { */ private get defaultQuery(): IInventoryDetailsQuery { return { - fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), + fromDate: moment().startOf('month').format('YYYY-MM-DD'), + toDate: moment().format('YYYY-MM-DD'), itemsIds: [], numberFormat: { precision: 2, diff --git a/packages/server/src/services/FinancialStatements/InventoryValuationSheet/InventoryValuationSheetService.ts b/packages/server/src/services/FinancialStatements/InventoryValuationSheet/InventoryValuationSheetService.ts index 41650ccde..75c871ce8 100644 --- a/packages/server/src/services/FinancialStatements/InventoryValuationSheet/InventoryValuationSheetService.ts +++ b/packages/server/src/services/FinancialStatements/InventoryValuationSheet/InventoryValuationSheetService.ts @@ -27,7 +27,7 @@ export default class InventoryValuationSheetService { */ get defaultQuery(): IInventoryValuationReportQuery { return { - asDate: moment().endOf('year').format('YYYY-MM-DD'), + asDate: moment().format('YYYY-MM-DD'), itemsIds: [], numberFormat: { precision: 2, diff --git a/packages/server/src/services/FinancialStatements/JournalSheet/JournalSheetService.ts b/packages/server/src/services/FinancialStatements/JournalSheet/JournalSheetService.ts index f932efd8c..fe0a071ff 100644 --- a/packages/server/src/services/FinancialStatements/JournalSheet/JournalSheetService.ts +++ b/packages/server/src/services/FinancialStatements/JournalSheet/JournalSheetService.ts @@ -25,8 +25,8 @@ export default class JournalSheetService { */ get defaultQuery() { return { - fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), + fromDate: moment().startOf('month').format('YYYY-MM-DD'), + toDate: moment().format('YYYY-MM-DD'), fromRange: null, toRange: null, accountsIds: [], diff --git a/packages/server/src/services/FinancialStatements/ProfitLossSheet/utils.ts b/packages/server/src/services/FinancialStatements/ProfitLossSheet/utils.ts index 8f17be584..85663a0b8 100644 --- a/packages/server/src/services/FinancialStatements/ProfitLossSheet/utils.ts +++ b/packages/server/src/services/FinancialStatements/ProfitLossSheet/utils.ts @@ -8,7 +8,7 @@ import { IProfitLossSheetQuery } from '@/interfaces'; */ export const getDefaultPLQuery = (): IProfitLossSheetQuery => ({ fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), + toDate: moment().format('YYYY-MM-DD'), numberFormat: { divideOn1000: false, diff --git a/packages/server/src/services/FinancialStatements/ProjectProfitabilitySummary/ProjectProfitabilitySummaryRepository.ts b/packages/server/src/services/FinancialStatements/ProjectProfitabilitySummary/ProjectProfitabilitySummaryRepository.ts index 9ba59cc74..463574a27 100644 --- a/packages/server/src/services/FinancialStatements/ProjectProfitabilitySummary/ProjectProfitabilitySummaryRepository.ts +++ b/packages/server/src/services/FinancialStatements/ProjectProfitabilitySummary/ProjectProfitabilitySummaryRepository.ts @@ -129,9 +129,9 @@ export class ProjectProfitabilitySummaryRespository { */ public getIncomeAccountsGroupedEntries = async () => { const incomeAccounts = await this.getIncomeAccounts(); - const incomeAcountssIds = map(incomeAccounts, 'id'); + const incomeAccountsIds = map(incomeAccounts, 'id'); - return this.getAccountsGroupedEntries(incomeAcountssIds); + return this.getAccountsGroupedEntries(incomeAccountsIds); }; /** diff --git a/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsService.ts b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsService.ts index 4c226e48a..df4aee1ad 100644 --- a/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsService.ts +++ b/packages/server/src/services/FinancialStatements/PurchasesByItems/PurchasesByItemsService.ts @@ -12,10 +12,7 @@ import { Tenant } from '@/system/models'; @Service() export default class InventoryValuationReportService { @Inject() - tenancy: TenancyService; - - @Inject('logger') - logger: any; + private tenancy: TenancyService; /** * Defaults balance sheet filter query. @@ -23,8 +20,8 @@ export default class InventoryValuationReportService { */ get defaultQuery(): IInventoryValuationReportQuery { return { - fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), + fromDate: moment().startOf('month').format('YYYY-MM-DD'), + toDate: moment().format('YYYY-MM-DD'), itemsIds: [], numberFormat: { precision: 2, @@ -73,9 +70,9 @@ export default class InventoryValuationReportService { tenantId: number, query: IInventoryValuationReportQuery ): Promise<{ - data: IInventoryValuationStatement, - query: IInventoryValuationReportQuery, - meta: IInventoryValuationSheetMeta, + data: IInventoryValuationStatement; + query: IInventoryValuationReportQuery; + meta: IInventoryValuationSheetMeta; }> { const { Item, InventoryTransaction } = this.tenancy.models(tenantId); @@ -87,7 +84,7 @@ export default class InventoryValuationReportService { ...this.defaultQuery, ...query, }; - const inventoryItems = await Item.query().onBuild(q => { + const inventoryItems = await Item.query().onBuild((q) => { q.where('type', 'inventory'); if (filter.itemsIds.length > 0) { @@ -106,7 +103,7 @@ export default class InventoryValuationReportService { builder.whereIn('itemId', inventoryItemsIds); // Filter the date range of the sheet. - builder.modify('filterDateRange', filter.fromDate, filter.toDate) + builder.modify('filterDateRange', filter.fromDate, filter.toDate); } ); diff --git a/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsService.ts b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsService.ts index 8d0032f7a..7570ef572 100644 --- a/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsService.ts +++ b/packages/server/src/services/FinancialStatements/SalesByItems/SalesByItemsService.ts @@ -23,8 +23,8 @@ export default class SalesByItemsReportService { */ get defaultQuery(): ISalesByItemsReportQuery { return { - fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), + fromDate: moment().startOf('month').format('YYYY-MM-DD'), + toDate: moment().format('YYYY-MM-DD'), itemsIds: [], numberFormat: { precision: 2, diff --git a/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersService.ts b/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersService.ts index 24723caaa..a6f56d9fe 100644 --- a/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersService.ts +++ b/packages/server/src/services/FinancialStatements/TransactionsByCustomer/TransactionsByCustomersService.ts @@ -31,8 +31,8 @@ export default class TransactionsByCustomersService */ get defaultQuery(): ITransactionsByCustomersFilter { return { - fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), + fromDate: moment().startOf('month').format('YYYY-MM-DD'), + toDate: moment().format('YYYY-MM-DD'), numberFormat: { precision: 2, divideOn1000: false, diff --git a/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorService.ts b/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorService.ts index 18be5b7ed..c112a059a 100644 --- a/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorService.ts +++ b/packages/server/src/services/FinancialStatements/TransactionsByVendor/TransactionsByVendorService.ts @@ -32,7 +32,7 @@ export default class TransactionsByVendorsService */ get defaultQuery(): ITransactionsByVendorsFilter { return { - fromDate: moment().format('YYYY-MM-DD'), + fromDate: moment().startOf('month').format('YYYY-MM-DD'), toDate: moment().format('YYYY-MM-DD'), numberFormat: { precision: 2, diff --git a/packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetService.ts b/packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetService.ts index e06ed6b02..f22624a3e 100644 --- a/packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetService.ts +++ b/packages/server/src/services/FinancialStatements/TrialBalanceSheet/TrialBalanceSheetService.ts @@ -27,7 +27,7 @@ export default class TrialBalanceSheetService extends FinancialSheet { get defaultQuery(): ITrialBalanceSheetQuery { return { fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), + toDate: moment().format('YYYY-MM-DD'), numberFormat: { divideOn1000: false, negativeFormat: 'mines', diff --git a/packages/server/src/services/Inventory/Inventory.ts b/packages/server/src/services/Inventory/Inventory.ts index c5ec78dee..33394bfe7 100644 --- a/packages/server/src/services/Inventory/Inventory.ts +++ b/packages/server/src/services/Inventory/Inventory.ts @@ -95,7 +95,7 @@ export default class InventoryService { ) { const { Item } = this.tenancy.models(tenantId); - // Fetches the item with assocaited item category. + // Fetches the item with associated item category. const item = await Item.query().findById(itemId); // Cannot continue if the given item was not inventory item. diff --git a/packages/server/src/services/Inventory/InventoryAdjustmentService.ts b/packages/server/src/services/Inventory/InventoryAdjustmentService.ts index 44df986e1..48b94d149 100644 --- a/packages/server/src/services/Inventory/InventoryAdjustmentService.ts +++ b/packages/server/src/services/Inventory/InventoryAdjustmentService.ts @@ -180,7 +180,7 @@ export default class InventoryAdjustmentService { quickAdjustmentDTO, } as IInventoryAdjustmentCreatingPayload ); - // Saves the inventory adjustment with assocaited entries to the storage. + // Saves the inventory adjustment with associated entries to the storage. const inventoryAdjustment = await InventoryAdjustment.query( trx ).upsertGraph({ diff --git a/packages/server/src/services/Inventory/InventoryAverageCost.ts b/packages/server/src/services/Inventory/InventoryAverageCost.ts index 0108cab16..84c2bdd85 100644 --- a/packages/server/src/services/Inventory/InventoryAverageCost.ts +++ b/packages/server/src/services/Inventory/InventoryAverageCost.ts @@ -49,7 +49,7 @@ export default class InventoryAverageCostMethod public async computeItemCost() { const { InventoryTransaction } = this.tenantModels; const { averageCost, openingQuantity, openingCost } = - await this.getOpeningAvaregeCost(this.startingDate, this.itemId); + await this.getOpeningAverageCost(this.startingDate, this.itemId); const afterInvTransactions: IInventoryTransaction[] = await InventoryTransaction.query() @@ -75,12 +75,12 @@ export default class InventoryAverageCostMethod } /** - * Get items Avarege cost from specific date from inventory transactions. + * Get items Average cost from specific date from inventory transactions. * @async * @param {Date} closingDate * @return {number} */ - public async getOpeningAvaregeCost(closingDate: Date, itemId: number) { + public async getOpeningAverageCost(closingDate: Date, itemId: number) { const { InventoryCostLotTracker } = this.tenantModels; const commonBuilder = (builder: any) => { diff --git a/packages/server/src/services/Inventory/InventoryCostLotTracker.ts b/packages/server/src/services/Inventory/InventoryCostLotTracker.ts index 9ce03880a..aa317674c 100644 --- a/packages/server/src/services/Inventory/InventoryCostLotTracker.ts +++ b/packages/server/src/services/Inventory/InventoryCostLotTracker.ts @@ -79,7 +79,7 @@ export default class InventoryCostLotTracker extends InventoryCostMethod impleme /** * Fetched inventory transactions that has date from the starting date and - * fetches availiable IN LOTs transactions that has remaining bigger than zero. + * fetches available IN LOTs transactions that has remaining bigger than zero. * @private */ private async fetchInvINTransactions() { @@ -97,7 +97,7 @@ export default class InventoryCostLotTracker extends InventoryCostMethod impleme .orderBy('lot_number', (this.costMethod === 'LIFO') ? 'DESC' : 'ASC') .withGraphFetched('item'); - const availiableINLots: IInventoryLotCost[] = + const availableINLots: IInventoryLotCost[] = await InventoryLotCostTracker.query() .modify('filterDateRange', null, this.startingDate) .orderBy('date', 'ASC') @@ -107,7 +107,7 @@ export default class InventoryCostLotTracker extends InventoryCostMethod impleme .whereNot('remaining', 0); this.inTransactions = [ - ...availiableINLots.map((trans) => ({ lotTransId: trans.id, ...trans })), + ...availableINLots.map((trans) => ({ lotTransId: trans.id, ...trans })), ...afterInvTransactions.map((trans) => ({ invTransId: trans.id, ...trans })), ]; } diff --git a/packages/server/src/services/ItemCategories/ItemCategoriesService.ts b/packages/server/src/services/ItemCategories/ItemCategoriesService.ts index 76a6f1c18..f1ba27621 100644 --- a/packages/server/src/services/ItemCategories/ItemCategoriesService.ts +++ b/packages/server/src/services/ItemCategories/ItemCategoriesService.ts @@ -344,7 +344,7 @@ export default class ItemCategoriesService implements IItemCategoriesService { ); // Items categories. const itemCategories = await ItemCategory.query().onBuild((query) => { - // Subquery to calculate sumation of assocaited items to the item category. + // Subquery to calculate sumation of associated items to the item category. query.select('*', ItemCategory.relatedQuery('items').count().as('count')); dynamicList.buildQuery()(query); diff --git a/packages/server/src/services/Items/DeleteItem.ts b/packages/server/src/services/Items/DeleteItem.ts index dd27a80e5..900faca03 100644 --- a/packages/server/src/services/Items/DeleteItem.ts +++ b/packages/server/src/services/Items/DeleteItem.ts @@ -9,13 +9,9 @@ import HasTenancyService from '@/services/Tenancy/TenancyService'; import UnitOfWork from '@/services/UnitOfWork'; import events from '@/subscribers/events'; import { ERRORS } from './constants'; -import { ItemsValidators } from './ItemValidators'; @Service() export class DeleteItem { - @Inject() - private validators: ItemsValidators; - @Inject() private tenancy: HasTenancyService; diff --git a/packages/server/src/services/Items/ItemValidators.ts b/packages/server/src/services/Items/ItemValidators.ts index d902c3872..486c08a8d 100644 --- a/packages/server/src/services/Items/ItemValidators.ts +++ b/packages/server/src/services/Items/ItemValidators.ts @@ -198,7 +198,7 @@ export class ItemsValidators { /** * Validate the item inventory account whether modified and item - * has assocaited inventory transactions. + * has associated inventory transactions. * @param {numnber} tenantId * @param {IItem} oldItem * @param {IItemDTO} newItemDTO diff --git a/packages/server/src/services/Items/ItemsCostService.ts b/packages/server/src/services/Items/ItemsCostService.ts deleted file mode 100644 index 6f028f808..000000000 --- a/packages/server/src/services/Items/ItemsCostService.ts +++ /dev/null @@ -1,5 +0,0 @@ - - -export default class ItemsCostService { - -} \ No newline at end of file diff --git a/packages/server/src/services/ManualJournals/CommandManualJournalValidators.ts b/packages/server/src/services/ManualJournals/CommandManualJournalValidators.ts index d6bbe0a8c..5cc3e94c4 100644 --- a/packages/server/src/services/ManualJournals/CommandManualJournalValidators.ts +++ b/packages/server/src/services/ManualJournals/CommandManualJournalValidators.ts @@ -59,7 +59,7 @@ export class CommandManualJournalValidators { const storedAccountsIds = accounts.map((account) => account.id); if (difference(manualAccountsIds, storedAccountsIds).length > 0) { - throw new ServiceError(ERRORS.ACCCOUNTS_IDS_NOT_FOUND); + throw new ServiceError(ERRORS.ACCOUNTS_IDS_NOT_FOUND); } } diff --git a/packages/server/src/services/ManualJournals/GetManualJournal.ts b/packages/server/src/services/ManualJournals/GetManualJournal.ts index 9f4f5c530..97142a494 100644 --- a/packages/server/src/services/ManualJournals/GetManualJournal.ts +++ b/packages/server/src/services/ManualJournals/GetManualJournal.ts @@ -12,7 +12,7 @@ export class GetManualJournal { private transformer: TransformerInjectable; /** - * Retrieve manual journal details with assocaited journal transactions. + * Retrieve manual journal details with associated journal transactions. * @param {number} tenantId * @param {number} manualJournalId */ diff --git a/packages/server/src/services/ManualJournals/ManualJournalGLEntriesSubscriber.ts b/packages/server/src/services/ManualJournals/ManualJournalGLEntriesSubscriber.ts index c5efa8f12..21f921d22 100644 --- a/packages/server/src/services/ManualJournals/ManualJournalGLEntriesSubscriber.ts +++ b/packages/server/src/services/ManualJournals/ManualJournalGLEntriesSubscriber.ts @@ -48,6 +48,7 @@ export class ManualJournalWriteGLSubscriber { /** * Handle manual journal created event. * @param {IManualJournalEventCreatedPayload} payload - + * @returns {Promise} */ private handleWriteJournalEntriesOnCreated = async ({ tenantId, @@ -55,18 +56,19 @@ export class ManualJournalWriteGLSubscriber { trx, }: IManualJournalEventCreatedPayload) => { // Ingore writing manual journal journal entries in case was not published. - if (manualJournal.publishedAt) { - await this.manualJournalGLEntries.createManualJournalGLEntries( - tenantId, - manualJournal.id, - trx - ); - } + if (!manualJournal.publishedAt) return; + + await this.manualJournalGLEntries.createManualJournalGLEntries( + tenantId, + manualJournal.id, + trx + ); }; /** * Handles the manual journal next number increment once the journal be created. * @param {IManualJournalEventCreatedPayload} payload - + * @return {Promise} */ private handleJournalNumberIncrement = async ({ tenantId, @@ -77,6 +79,7 @@ export class ManualJournalWriteGLSubscriber { /** * Handle manual journal edited event. * @param {IManualJournalEventEditedPayload} + * @return {Promise} */ private handleRewriteJournalEntriesOnEdited = async ({ tenantId, @@ -96,6 +99,7 @@ export class ManualJournalWriteGLSubscriber { /** * Handles writing journal entries once the manula journal publish. * @param {IManualJournalEventPublishedPayload} payload - + * @return {Promise} */ private handleWriteJournalEntriesOnPublished = async ({ tenantId, diff --git a/packages/server/src/services/ManualJournals/constants.ts b/packages/server/src/services/ManualJournals/constants.ts index ed085f2fc..6f6379be2 100644 --- a/packages/server/src/services/ManualJournals/constants.ts +++ b/packages/server/src/services/ManualJournals/constants.ts @@ -2,7 +2,7 @@ export const ERRORS = { NOT_FOUND: 'manual_journal_not_found', CREDIT_DEBIT_NOT_EQUAL_ZERO: 'credit_debit_not_equal_zero', CREDIT_DEBIT_NOT_EQUAL: 'credit_debit_not_equal', - ACCCOUNTS_IDS_NOT_FOUND: 'acccounts_ids_not_found', + ACCOUNTS_IDS_NOT_FOUND: 'accounts_ids_not_found', JOURNAL_NUMBER_EXISTS: 'journal_number_exists', ENTRIES_SHOULD_ASSIGN_WITH_CONTACT: 'ENTRIES_SHOULD_ASSIGN_WITH_CONTACT', CONTACTS_NOT_FOUND: 'contacts_not_found', diff --git a/packages/server/src/services/Projects/Times/SyncActualTimeTaskSubscriber.ts b/packages/server/src/services/Projects/Times/SyncActualTimeTaskSubscriber.ts index 45f64f52c..82b24b31b 100644 --- a/packages/server/src/services/Projects/Times/SyncActualTimeTaskSubscriber.ts +++ b/packages/server/src/services/Projects/Times/SyncActualTimeTaskSubscriber.ts @@ -23,7 +23,7 @@ export class SyncActualTimeTaskSubscriber { ); bus.subscribe( events.projectTime.onDeleted, - this.handleDecreaseActaulTimeOnTimeDelete + this.handleDecreaseActualTimeOnTimeDelete ); bus.subscribe( events.projectTime.onEdited, @@ -52,7 +52,7 @@ export class SyncActualTimeTaskSubscriber { * Handle decreasing the actual time of the tsak once time entry be deleted. * @param {IProjectTimeDeletedEventPayload} payload */ - private handleDecreaseActaulTimeOnTimeDelete = async ({ + private handleDecreaseActualTimeOnTimeDelete = async ({ tenantId, oldTime, trx, diff --git a/packages/server/src/services/Purchases/BillPayments/BillPaymentGLEntriesSubscriber.ts b/packages/server/src/services/Purchases/BillPayments/BillPaymentGLEntriesSubscriber.ts index 6a7cc983e..cdfb456d5 100644 --- a/packages/server/src/services/Purchases/BillPayments/BillPaymentGLEntriesSubscriber.ts +++ b/packages/server/src/services/Purchases/BillPayments/BillPaymentGLEntriesSubscriber.ts @@ -36,7 +36,7 @@ export class PaymentWriteGLEntriesSubscriber { trx, }: IBillPaymentEventCreatedPayload) => { // Records the journal transactions after bills payment - // and change diff acoount balance. + // and change diff account balance. await this.billPaymentGLEntries.writePaymentGLEntries( tenantId, billPayment.id, diff --git a/packages/server/src/services/Purchases/BillPayments/BillPaymentsPages.ts b/packages/server/src/services/Purchases/BillPayments/BillPaymentsPages.ts index 7b4e0d8fe..0eb20b856 100644 --- a/packages/server/src/services/Purchases/BillPayments/BillPaymentsPages.ts +++ b/packages/server/src/services/Purchases/BillPayments/BillPaymentsPages.ts @@ -68,7 +68,7 @@ export default class BillPaymentsPages { ): Promise { const { Bill } = this.tenancy.models(tenantId); - // Retrieve all payable bills that assocaited to the payment made transaction. + // Retrieve all payable bills that associated to the payment made transaction. const payableBills = await Bill.query() .modify('opened') .modify('dueBills') diff --git a/packages/server/src/services/Purchases/Bills/BillGLEntriesSubscriber.ts b/packages/server/src/services/Purchases/Bills/BillGLEntriesSubscriber.ts index c38e65cb7..231b3cedd 100644 --- a/packages/server/src/services/Purchases/Bills/BillGLEntriesSubscriber.ts +++ b/packages/server/src/services/Purchases/Bills/BillGLEntriesSubscriber.ts @@ -4,6 +4,7 @@ import { IBillCreatedPayload, IBillEditedPayload, IBIllEventDeletedPayload, + IBillOpenedPayload, } from '@/interfaces'; import { BillGLEntries } from './BillGLEntries'; @@ -13,13 +14,17 @@ export class BillGLEntriesSubscriber { private billGLEntries: BillGLEntries; /** - * Attachs events with handles. + * Attaches events with handles. */ public attach(bus) { bus.subscribe( events.bill.onCreated, this.handlerWriteJournalEntriesOnCreate ); + bus.subscribe( + events.bill.onOpened, + this.handlerWriteJournalEntriesOnCreate + ); bus.subscribe( events.bill.onEdited, this.handleOverwriteJournalEntriesOnEdit @@ -33,10 +38,12 @@ export class BillGLEntriesSubscriber { */ private handlerWriteJournalEntriesOnCreate = async ({ tenantId, - billId, + bill, trx, - }: IBillCreatedPayload) => { - await this.billGLEntries.writeBillGLEntries(tenantId, billId, trx); + }: IBillCreatedPayload | IBillOpenedPayload) => { + if (!bill.openedAt) return null; + + await this.billGLEntries.writeBillGLEntries(tenantId, bill.id, trx); }; /** @@ -46,8 +53,11 @@ export class BillGLEntriesSubscriber { private handleOverwriteJournalEntriesOnEdit = async ({ tenantId, billId, + bill, trx, }: IBillEditedPayload) => { + if (!bill.openedAt) return null; + await this.billGLEntries.rewriteBillGLEntries(tenantId, billId, trx); }; diff --git a/packages/server/src/services/Purchases/Bills/BillPaymentsGLEntriesRewriteSubscriber.ts b/packages/server/src/services/Purchases/Bills/BillPaymentsGLEntriesRewriteSubscriber.ts index b2571fef3..4e193fe2f 100644 --- a/packages/server/src/services/Purchases/Bills/BillPaymentsGLEntriesRewriteSubscriber.ts +++ b/packages/server/src/services/Purchases/Bills/BillPaymentsGLEntriesRewriteSubscriber.ts @@ -9,7 +9,7 @@ export class BillPaymentsGLEntriesRewriteSubscriber { private billPaymentGLEntriesRewrite: BillPaymentsGLEntriesRewrite; /** - * Attachs events with handles. + * Attaches events with handles. */ public attach(bus) { bus.subscribe( diff --git a/packages/server/src/services/Purchases/Bills/DeleteBill.ts b/packages/server/src/services/Purchases/Bills/DeleteBill.ts index 51f58ddfc..6cb47e9d5 100644 --- a/packages/server/src/services/Purchases/Bills/DeleteBill.ts +++ b/packages/server/src/services/Purchases/Bills/DeleteBill.ts @@ -43,7 +43,7 @@ export class DeleteBill { // Validate the givne bill has no associated landed cost transactions. await this.validators.validateBillHasNoLandedCost(tenantId, billId); - // Validate the purchase bill has no assocaited payments transactions. + // Validate the purchase bill has no associated payments transactions. await this.validators.validateBillHasNoEntries(tenantId, billId); // Validate the given bill has no associated reconciled with vendor credits. diff --git a/packages/server/src/services/Purchases/Bills/EditBill.ts b/packages/server/src/services/Purchases/Bills/EditBill.ts index a7259c730..26121c120 100644 --- a/packages/server/src/services/Purchases/Bills/EditBill.ts +++ b/packages/server/src/services/Purchases/Bills/EditBill.ts @@ -132,7 +132,7 @@ export class EditBill { } as IBillEditingPayload); // Update the bill transaction. - const bill = await Bill.query(trx).upsertGraph({ + const bill = await Bill.query(trx).upsertGraphAndFetch({ id: billId, ...billObj, }); diff --git a/packages/server/src/services/Purchases/Bills/OpenBill.ts b/packages/server/src/services/Purchases/Bills/OpenBill.ts index a2c2039b3..25a0da22e 100644 --- a/packages/server/src/services/Purchases/Bills/OpenBill.ts +++ b/packages/server/src/services/Purchases/Bills/OpenBill.ts @@ -5,6 +5,9 @@ import { ERRORS } from './constants'; import HasTenancyService from '@/services/Tenancy/TenancyService'; import UnitOfWork from '@/services/UnitOfWork'; import { BillsValidators } from './BillsValidators'; +import { EventPublisher } from '@/lib/EventPublisher/EventPublisher'; +import events from '@/subscribers/events'; +import { IBillOpenedPayload, IBillOpeningPayload } from '@/interfaces'; @Service() export class OpenBill { @@ -17,6 +20,9 @@ export class OpenBill { @Inject() private validators: BillsValidators; + @Inject() + private eventPublisher: EventPublisher; + /** * Mark the bill as open. * @param {number} tenantId @@ -37,10 +43,27 @@ export class OpenBill { throw new ServiceError(ERRORS.BILL_ALREADY_OPEN); } return this.uow.withTransaction(tenantId, async (trx) => { - // Record the bill opened at on the storage. - await Bill.query(trx).findById(billId).patch({ - openedAt: moment().toMySqlDateTime(), - }); + // Triggers `onBillCreating` event. + await this.eventPublisher.emitAsync(events.bill.onOpening, { + trx, + tenantId, + oldBill, + } as IBillOpeningPayload); + + // Save the bill opened at on the storage. + const bill = await Bill.query(trx) + .patchAndFetchById(billId, { + openedAt: moment().toMySqlDateTime(), + }) + .withGraphFetched('entries'); + + // Triggers `onBillCreating` event. + await this.eventPublisher.emitAsync(events.bill.onOpened, { + trx, + bill, + oldBill, + tenantId, + } as IBillOpenedPayload); }); } } diff --git a/packages/server/src/services/Purchases/LandedCost/RevertAllocatedLandedCost.ts b/packages/server/src/services/Purchases/LandedCost/RevertAllocatedLandedCost.ts index 75d4a4399..df18b6065 100644 --- a/packages/server/src/services/Purchases/LandedCost/RevertAllocatedLandedCost.ts +++ b/packages/server/src/services/Purchases/LandedCost/RevertAllocatedLandedCost.ts @@ -39,7 +39,7 @@ export default class RevertAllocatedLandedCost extends BaseLandedCost { ); // Deletes landed cost with associated transactions. return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => { - // Delete landed cost transaction with assocaited locate entries. + // Delete landed cost transaction with associated locate entries. await this.deleteLandedCost(tenantId, landedCostId, trx); // Triggers the event `onBillLandedCostCreated`. @@ -55,7 +55,7 @@ export default class RevertAllocatedLandedCost extends BaseLandedCost { }; /** - * Deletes the landed cost transaction with assocaited allocate entries. + * Deletes the landed cost transaction with associated allocate entries. * @param {number} tenantId - Tenant id. * @param {number} landedCostId - Landed cost id. */ diff --git a/packages/server/src/services/Purchases/VendorCredits/ApplyVendorCreditToBills/ApplyVendorCreditSyncBills.ts b/packages/server/src/services/Purchases/VendorCredits/ApplyVendorCreditToBills/ApplyVendorCreditSyncBills.ts index f9a86c663..c6f617c60 100644 --- a/packages/server/src/services/Purchases/VendorCredits/ApplyVendorCreditToBills/ApplyVendorCreditSyncBills.ts +++ b/packages/server/src/services/Purchases/VendorCredits/ApplyVendorCreditToBills/ApplyVendorCreditSyncBills.ts @@ -1,13 +1,13 @@ import { Service, Inject } from 'typedi'; -import Knex from 'knex'; +import { Knex } from 'knex'; +import Bluebird from 'bluebird'; import { IVendorCreditAppliedBill } from '@/interfaces'; import HasTenancyService from '@/services/Tenancy/TenancyService'; -import Bluebird from 'bluebird'; @Service() export default class ApplyVendorCreditSyncBills { @Inject() - tenancy: HasTenancyService; + private tenancy: HasTenancyService; /** * Increment bills credited amount. @@ -49,4 +49,4 @@ export default class ApplyVendorCreditSyncBills { .findById(vendorCreditAppliedBill.billId) .decrement('creditedAmount', vendorCreditAppliedBill.amount); }; -} \ No newline at end of file +} diff --git a/packages/server/src/services/Purchases/VendorCredits/DeleteVendorAssociatedVendorCredit.ts b/packages/server/src/services/Purchases/VendorCredits/DeleteVendorAssociatedVendorCredit.ts index 63ad79d8d..ac974cee9 100644 --- a/packages/server/src/services/Purchases/VendorCredits/DeleteVendorAssociatedVendorCredit.ts +++ b/packages/server/src/services/Purchases/VendorCredits/DeleteVendorAssociatedVendorCredit.ts @@ -25,7 +25,7 @@ export default class DeleteVendorAssociatedVendorCredit { }; /** - * Validate vendor has no assocaited credit transaction once the vendor deleting. + * Validate vendor has no associated credit transaction once the vendor deleting. * @param {IVendorEventDeletingPayload} payload - */ public validateVendorHasNoCreditsTransactionsOnceDeleting = async ({ diff --git a/packages/server/src/services/Purchases/VendorCredits/VendorCreditGLEntriesSubscriber.ts b/packages/server/src/services/Purchases/VendorCredits/VendorCreditGLEntriesSubscriber.ts index 5bfccf190..0c7761701 100644 --- a/packages/server/src/services/Purchases/VendorCredits/VendorCreditGLEntriesSubscriber.ts +++ b/packages/server/src/services/Purchases/VendorCredits/VendorCreditGLEntriesSubscriber.ts @@ -71,7 +71,7 @@ export default class VendorCreditGlEntriesSubscriber { }; /** - * Edits assocaited GL entries once vendor credit edited. + * Edits associated GL entries once vendor credit edited. * @param {IVendorCreditEditedPayload} payload */ private editGLEntriesOnceVendorCreditEdited = async ({ diff --git a/packages/server/src/services/Purchases/VendorCredits/VendorCreditInventoryTransactions.ts b/packages/server/src/services/Purchases/VendorCredits/VendorCreditInventoryTransactions.ts index ed58daa1b..258bfe8d9 100644 --- a/packages/server/src/services/Purchases/VendorCredits/VendorCreditInventoryTransactions.ts +++ b/packages/server/src/services/Purchases/VendorCredits/VendorCreditInventoryTransactions.ts @@ -51,7 +51,7 @@ export default class VendorCreditInventoryTransactions { }; /** - * Edits vendor credit assocaited inventory transactions. + * Edits vendor credit associated inventory transactions. * @param {number} tenantId * @param {number} creditNoteId * @param {ICreditNote} creditNote diff --git a/packages/server/src/services/Purchases/VendorCredits/VendorCreditInventoryTransactionsSusbcriber.ts b/packages/server/src/services/Purchases/VendorCredits/VendorCreditInventoryTransactionsSusbcriber.ts index c9b24a4f7..bae3adc23 100644 --- a/packages/server/src/services/Purchases/VendorCredits/VendorCreditInventoryTransactionsSusbcriber.ts +++ b/packages/server/src/services/Purchases/VendorCredits/VendorCreditInventoryTransactionsSusbcriber.ts @@ -10,7 +10,7 @@ import VendorCreditInventoryTransactions from './VendorCreditInventoryTransactio @Service() export default class VendorCreditInventoryTransactionsSubscriber { @Inject() - inventoryTransactions: VendorCreditInventoryTransactions; + private inventoryTransactions: VendorCreditInventoryTransactions; /** * Attaches events with handlers. @@ -21,6 +21,10 @@ export default class VendorCreditInventoryTransactionsSubscriber { events.vendorCredit.onCreated, this.writeInventoryTransactionsOnceCreated ); + bus.subscribe( + events.vendorCredit.onOpened, + this.writeInventoryTransactionsOnceCreated + ); bus.subscribe( events.vendorCredit.onEdited, this.rewriteInventroyTransactionsOnceEdited @@ -40,6 +44,9 @@ export default class VendorCreditInventoryTransactionsSubscriber { vendorCredit, trx, }: IVendorCreditCreatedPayload) => { + // Can't continue if vendor credit is not opened. + if (!vendorCredit.openedAt) return null; + await this.inventoryTransactions.createInventoryTransactions( tenantId, vendorCredit, @@ -57,6 +64,9 @@ export default class VendorCreditInventoryTransactionsSubscriber { vendorCredit, trx, }: IVendorCreditEditedPayload) => { + // Can't continue if vendor credit is not opened. + if (!vendorCredit.openedAt) return null; + await this.inventoryTransactions.editInventoryTransactions( tenantId, vendorCreditId, diff --git a/packages/server/src/services/Sales/Estimates/DeleteSaleEstimate.ts b/packages/server/src/services/Sales/Estimates/DeleteSaleEstimate.ts index 4975b58f3..4cc17e926 100644 --- a/packages/server/src/services/Sales/Estimates/DeleteSaleEstimate.ts +++ b/packages/server/src/services/Sales/Estimates/DeleteSaleEstimate.ts @@ -44,7 +44,7 @@ export class DeleteSaleEstimate { if (oldSaleEstimate.convertedToInvoiceId) { throw new ServiceError(ERRORS.SALE_ESTIMATE_CONVERTED_TO_INVOICE); } - // Deletes the estimate with associated transactions under UOW enivrement. + // Updates the estimate with associated transactions under UOW enivrement. return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => { // Triggers `onSaleEstimatedDeleting` event. await this.eventPublisher.emitAsync(events.saleEstimate.onDeleting, { diff --git a/packages/server/src/services/Sales/Invoices/DeliverSaleInvoice.ts b/packages/server/src/services/Sales/Invoices/DeliverSaleInvoice.ts index 77511af84..30ba635a6 100644 --- a/packages/server/src/services/Sales/Invoices/DeliverSaleInvoice.ts +++ b/packages/server/src/services/Sales/Invoices/DeliverSaleInvoice.ts @@ -63,14 +63,17 @@ export class DeliverSaleInvoice { // Record the delivered at on the storage. const saleInvoice = await SaleInvoice.query(trx) - .where({ id: saleInvoiceId }) - .update({ deliveredAt: moment().toMySqlDateTime() }); + .patchAndFetchById(saleInvoiceId, { + deliveredAt: moment().toMySqlDateTime(), + }) + .withGraphFetched('entries'); // Triggers `onSaleInvoiceDelivered` event. await this.eventPublisher.emitAsync(events.saleInvoice.onDelivered, { tenantId, saleInvoiceId, saleInvoice, + trx, } as ISaleInvoiceEventDeliveredPayload); }); } diff --git a/packages/server/src/services/Sales/Invoices/GetInvoicePaymentsService.ts b/packages/server/src/services/Sales/Invoices/GetInvoicePaymentsService.ts index 2bdb874f1..05b3b7f9e 100644 --- a/packages/server/src/services/Sales/Invoices/GetInvoicePaymentsService.ts +++ b/packages/server/src/services/Sales/Invoices/GetInvoicePaymentsService.ts @@ -12,7 +12,7 @@ export class GetInvoicePaymentsService { private transformer: TransformerInjectable; /** - * Retrieve the invoice assocaited payments transactions. + * Retrieve the invoice associated payments transactions. * @param {number} tenantId - Tenant id. * @param {number} invoiceId - Invoice id. */ diff --git a/packages/server/src/services/Sales/Receipts/CloseSaleReceipt.ts b/packages/server/src/services/Sales/Receipts/CloseSaleReceipt.ts index 0566d4733..b678884e3 100644 --- a/packages/server/src/services/Sales/Receipts/CloseSaleReceipt.ts +++ b/packages/server/src/services/Sales/Receipts/CloseSaleReceipt.ts @@ -58,12 +58,12 @@ export class CloseSaleReceipt { } as ISaleReceiptEventClosingPayload); // Mark the sale receipt as closed on the storage. - const saleReceipt = await SaleReceipt.query(trx) - .findById(saleReceiptId) - .patch({ + const saleReceipt = await SaleReceipt.query(trx).patchAndFetchById( + saleReceiptId, + { closedAt: moment().toMySqlDateTime(), - }); - + } + ); // Triggers `onSaleReceiptClosed` event. await this.eventPublisher.emitAsync(events.saleReceipt.onClosed, { saleReceiptId, diff --git a/packages/server/src/services/Warehouses/Integrations/ValidateItemEntriesWarehouseExistance.ts b/packages/server/src/services/Warehouses/Integrations/ValidateItemEntriesWarehouseExistance.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/server/src/services/Warehouses/WarehousesTransfers/TransferredWarehouseTransfer.ts b/packages/server/src/services/Warehouses/WarehousesTransfers/TransferredWarehouseTransfer.ts index 6e5f52722..9ce618990 100644 --- a/packages/server/src/services/Warehouses/WarehousesTransfers/TransferredWarehouseTransfer.ts +++ b/packages/server/src/services/Warehouses/WarehousesTransfers/TransferredWarehouseTransfer.ts @@ -32,7 +32,7 @@ export class TransferredWarehouseTransfer extends CommandWarehouseTransfer { warehouseTransfer: IWarehouseTransfer ) => { if (warehouseTransfer.transferDeliveredAt) { - throw new ServiceError(ERRORS.WAREHOUSE_TRANSFER_ALREAD_TRANSFERRED); + throw new ServiceError(ERRORS.WAREHOUSE_TRANSFER_ALREADY_TRANSFERRED); } }; diff --git a/packages/server/src/services/Warehouses/WarehousesTransfers/constants.ts b/packages/server/src/services/Warehouses/WarehousesTransfers/constants.ts index b147c1f08..790061627 100644 --- a/packages/server/src/services/Warehouses/WarehousesTransfers/constants.ts +++ b/packages/server/src/services/Warehouses/WarehousesTransfers/constants.ts @@ -8,7 +8,7 @@ export const ERRORS = { WAREHOUSE_TRANSFER_ITEMS_SHOULD_BE_INVENTORY: 'WAREHOUSE_TRANSFER_ITEMS_SHOULD_BE_INVENTORY', - WAREHOUSE_TRANSFER_ALREAD_TRANSFERRED: + WAREHOUSE_TRANSFER_ALREADY_TRANSFERRED: 'WAREHOUSE_TRANSFER_ALREADY_TRANSFERRED', WAREHOUSE_TRANSFER_ALREADY_INITIATED: 'WAREHOUSE_TRANSFER_ALREADY_INITIATED', diff --git a/packages/server/src/subscribers/Bills/WriteInventoryTransactions.ts b/packages/server/src/subscribers/Bills/WriteInventoryTransactions.ts index ee04c98a1..6af4e8551 100644 --- a/packages/server/src/subscribers/Bills/WriteInventoryTransactions.ts +++ b/packages/server/src/subscribers/Bills/WriteInventoryTransactions.ts @@ -4,6 +4,7 @@ import { IBillCreatedPayload, IBillEditedPayload, IBIllEventDeletedPayload, + IBillOpenedPayload, } from '@/interfaces'; import { BillInventoryTransactions } from '@/services/Purchases/Bills/BillInventoryTransactions'; @@ -20,6 +21,10 @@ export default class BillWriteInventoryTransactionsSubscriber { events.bill.onCreated, this.handleWritingInventoryTransactions ); + bus.subscribe( + events.bill.onOpened, + this.handleWritingInventoryTransactions + ); bus.subscribe( events.bill.onEdited, this.handleOverwritingInventoryTransactions @@ -32,15 +37,19 @@ export default class BillWriteInventoryTransactionsSubscriber { /** * Handles writing the inventory transactions once bill created. + * @param {IBillCreatedPayload | IBillOpenedPayload} payload - */ private handleWritingInventoryTransactions = async ({ tenantId, - billId, + bill, trx, - }: IBillCreatedPayload) => { + }: IBillCreatedPayload | IBillOpenedPayload) => { + // Can't continue if the bill is not opened yet. + if (!bill.openedAt) return null; + await this.billsInventory.recordInventoryTransactions( tenantId, - billId, + bill.id, false, trx ); @@ -48,12 +57,17 @@ export default class BillWriteInventoryTransactionsSubscriber { /** * Handles the overwriting the inventory transactions once bill edited. + * @param {IBillEditedPayload} payload - */ private handleOverwritingInventoryTransactions = async ({ tenantId, billId, + bill, trx, }: IBillEditedPayload) => { + // Can't continue if the bill is not opened yet. + if (!bill.openedAt) return null; + await this.billsInventory.recordInventoryTransactions( tenantId, billId, @@ -64,6 +78,7 @@ export default class BillWriteInventoryTransactionsSubscriber { /** * Handles the reverting the inventory transactions once the bill deleted. + * @param {IBIllEventDeletedPayload} payload - */ private handleRevertInventoryTransactions = async ({ tenantId, diff --git a/packages/server/src/subscribers/Bills/WriteJournalEntries.ts b/packages/server/src/subscribers/Bills/WriteJournalEntries.ts index bb9589f54..50e4ea155 100644 --- a/packages/server/src/subscribers/Bills/WriteJournalEntries.ts +++ b/packages/server/src/subscribers/Bills/WriteJournalEntries.ts @@ -17,9 +17,9 @@ export default class BillWriteGLEntriesSubscriber { billsService: BillsService; /** - * Attachs events with handles. + * Attaches events with handles. */ - attach(bus) { + public attach(bus) { bus.subscribe( events.bill.onCreated, this.handlerWriteJournalEntriesOnCreate @@ -38,8 +38,12 @@ export default class BillWriteGLEntriesSubscriber { private handlerWriteJournalEntriesOnCreate = async ({ tenantId, billId, + bill, trx, }: IBillCreatedPayload) => { + // Can't continue if the bill is not opened yet. + if (!bill.openedAt) return null; + await this.billsService.recordJournalTransactions( tenantId, billId, @@ -55,8 +59,12 @@ export default class BillWriteGLEntriesSubscriber { private handleOverwriteJournalEntriesOnEdit = async ({ tenantId, billId, + bill, trx, }: IBillEditedPayload) => { + // Can't continue if the bill is not opened yet. + if (!bill.openedAt) return null; + await this.billsService.recordJournalTransactions( tenantId, billId, diff --git a/packages/server/src/subscribers/Cashflow/OwnerContributionCashflow.ts b/packages/server/src/subscribers/Cashflow/OwnerContributionCashflow.ts deleted file mode 100644 index 6a2fb8379..000000000 --- a/packages/server/src/subscribers/Cashflow/OwnerContributionCashflow.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Container } from 'typedi'; -import { EventSubscriber, On } from 'event-dispatch'; -import { map, head } from 'lodash'; -import events from '@/subscribers/events'; -import TenancyService from '@/services/Tenancy/TenancyService'; -import SaleInvoicesCost from '@/services/Sales/SalesInvoicesCost'; -import InventoryItemsQuantitySync from '@/services/Inventory/InventoryItemsQuantitySync'; -import InventoryService from '@/services/Inventory/Inventory'; - -@EventSubscriber() -export class OwnerContributionCashflowSubscriber { - depends: number = 0; - startingDate: Date; - saleInvoicesCost: SaleInvoicesCost; - tenancy: TenancyService; - itemsQuantitySync: InventoryItemsQuantitySync; - inventoryService: InventoryService; - agenda: any; - - /** - * Constructor method. - */ - constructor() { - this.tenancy = Container.get(TenancyService); - } - - /** - * Marks items cost compute running state. - */ - @On(events.cashflow.onOwnerContributionCreate) - async writeOwnerContributionJournalEntries({ - - }) { - - } - -} diff --git a/packages/server/src/subscribers/Items/ItemSubscriber.ts b/packages/server/src/subscribers/Items/ItemSubscriber.ts deleted file mode 100644 index 728da6888..000000000 --- a/packages/server/src/subscribers/Items/ItemSubscriber.ts +++ /dev/null @@ -1,18 +0,0 @@ -import events from '@/subscribers/events'; -import { EventSubscriber } from '@/lib/EventPublisher/EventPublisher'; -import { Service } from 'typedi'; - -@Service() -export default class ItemSubscriber extends EventSubscriber { - /** - * Attaches the events with handles. - * @param bus - */ - attach(bus) { - bus.subscribe(events.item.onCreated, this.handleItemCreated); - } - - handleItemCreated() { - - } -} diff --git a/packages/server/src/subscribers/Organization/SyncTenantAdminUser.ts b/packages/server/src/subscribers/Organization/SyncTenantAdminUser.ts index d09a621da..f0d88fcf6 100644 --- a/packages/server/src/subscribers/Organization/SyncTenantAdminUser.ts +++ b/packages/server/src/subscribers/Organization/SyncTenantAdminUser.ts @@ -16,7 +16,7 @@ export default class OrgSyncTenantAdminUserSubscriber { } /** - * Assign the autorized system user as admin role. + * Assign the authorized system user as admin role. */ public assignSystemUserAsAdminRole = async ({ tenantId, diff --git a/packages/server/src/subscribers/PaymentReceive/PaymentReceiveSyncInvoices.ts b/packages/server/src/subscribers/PaymentReceive/PaymentReceiveSyncInvoices.ts index 26ac16e14..d257de18c 100644 --- a/packages/server/src/subscribers/PaymentReceive/PaymentReceiveSyncInvoices.ts +++ b/packages/server/src/subscribers/PaymentReceive/PaymentReceiveSyncInvoices.ts @@ -37,7 +37,6 @@ export default class PaymentReceiveSyncInvoicesSubscriber { */ private handleInvoiceIncrementPaymentOnceCreated = async ({ tenantId, - paymentReceiveId, paymentReceive, trx, }: IPaymentReceiveCreatedPayload) => { diff --git a/packages/server/src/subscribers/SaleInvoices/WriteInventoryTransactions.ts b/packages/server/src/subscribers/SaleInvoices/WriteInventoryTransactions.ts index b4f620b20..ec3d920a5 100644 --- a/packages/server/src/subscribers/SaleInvoices/WriteInventoryTransactions.ts +++ b/packages/server/src/subscribers/SaleInvoices/WriteInventoryTransactions.ts @@ -4,6 +4,7 @@ import { ISaleInvoiceCreatedPayload, ISaleInvoiceDeletedPayload, ISaleInvoiceEditedPayload, + ISaleInvoiceEventDeliveredPayload, } from '@/interfaces'; import { InvoiceInventoryTransactions } from '@/services/Sales/Invoices/InvoiceInventoryTransactions'; @@ -20,6 +21,10 @@ export default class WriteInventoryTransactions { events.saleInvoice.onCreated, this.handleWritingInventoryTransactions ); + bus.subscribe( + events.saleInvoice.onDelivered, + this.handleWritingInventoryTransactions + ); bus.subscribe( events.saleInvoice.onEdited, this.handleRewritingInventoryTransactions @@ -38,7 +43,10 @@ export default class WriteInventoryTransactions { tenantId, saleInvoice, trx, - }: ISaleInvoiceCreatedPayload) => { + }: ISaleInvoiceCreatedPayload | ISaleInvoiceEventDeliveredPayload) => { + // Can't continue if the sale invoice is not delivered yet. + if (!saleInvoice.deliveredAt) return null; + await this.saleInvoiceInventory.recordInventoryTranscactions( tenantId, saleInvoice, diff --git a/packages/server/src/subscribers/SaleInvoices/WriteJournalEntries.ts b/packages/server/src/subscribers/SaleInvoices/WriteJournalEntries.ts index fc5d9411b..4b1eab698 100644 --- a/packages/server/src/subscribers/SaleInvoices/WriteJournalEntries.ts +++ b/packages/server/src/subscribers/SaleInvoices/WriteJournalEntries.ts @@ -15,11 +15,15 @@ export default class SaleInvoiceWriteGLEntriesSubscriber { /** * Constructor method. */ - attach(bus) { + public attach(bus) { bus.subscribe( events.saleInvoice.onCreated, this.handleWriteJournalEntriesOnInvoiceCreated ); + bus.subscribe( + events.saleInvoice.onDelivered, + this.handleWriteJournalEntriesOnInvoiceCreated + ); bus.subscribe( events.saleInvoice.onEdited, this.handleRewriteJournalEntriesOnceInvoiceEdit @@ -32,12 +36,18 @@ export default class SaleInvoiceWriteGLEntriesSubscriber { /** * Records journal entries of the non-inventory invoice. + * @param {ISaleInvoiceCreatedPayload} payload - + * @returns {Promise} */ private handleWriteJournalEntriesOnInvoiceCreated = async ({ tenantId, saleInvoiceId, + saleInvoice, trx, }: ISaleInvoiceCreatedPayload) => { + // Can't continue if the sale invoice is not delivered yet. + if (!saleInvoice.deliveredAt) return null; + await this.saleInvoiceGLEntries.writeInvoiceGLEntries( tenantId, saleInvoiceId, @@ -47,12 +57,17 @@ export default class SaleInvoiceWriteGLEntriesSubscriber { /** * Records journal entries of the non-inventory invoice. + * @param {ISaleInvoiceEditedPayload} payload - + * @returns {Promise} */ private handleRewriteJournalEntriesOnceInvoiceEdit = async ({ tenantId, saleInvoice, trx, }: ISaleInvoiceEditedPayload) => { + // Can't continue if the sale invoice is not delivered yet. + if (!saleInvoice.deliveredAt) return null; + await this.saleInvoiceGLEntries.rewritesInvoiceGLEntries( tenantId, saleInvoice.id, @@ -62,6 +77,8 @@ export default class SaleInvoiceWriteGLEntriesSubscriber { /** * Handle reverting journal entries once sale invoice delete. + * @param {ISaleInvoiceDeletePayload} payload - + * @returns {Promise} */ private handleRevertingInvoiceJournalEntriesOnDelete = async ({ tenantId, diff --git a/packages/server/src/subscribers/SaleReceipt/WriteInventoryTransactions.ts b/packages/server/src/subscribers/SaleReceipt/WriteInventoryTransactions.ts index 57da23747..bf4fd007a 100644 --- a/packages/server/src/subscribers/SaleReceipt/WriteInventoryTransactions.ts +++ b/packages/server/src/subscribers/SaleReceipt/WriteInventoryTransactions.ts @@ -40,6 +40,9 @@ export default class SaleReceiptInventoryTransactionsSubscriber { saleReceipt, trx, }: ISaleReceiptCreatedPayload) => { + // Can't continue if the sale receipt is not closed yet. + if (!saleReceipt.closedAt) return null; + await this.saleReceiptInventory.recordInventoryTransactions( tenantId, saleReceipt, @@ -57,6 +60,9 @@ export default class SaleReceiptInventoryTransactionsSubscriber { saleReceipt, trx, }: ISaleReceiptEditedPayload) => { + // Can't continue if the sale receipt is not closed yet. + if (!saleReceipt.closedAt) return null; + await this.saleReceiptInventory.recordInventoryTransactions( tenantId, saleReceipt, diff --git a/packages/server/src/subscribers/SaleReceipt/WriteJournalEntries.ts b/packages/server/src/subscribers/SaleReceipt/WriteJournalEntries.ts index 8a14bfcad..32c9c363b 100644 --- a/packages/server/src/subscribers/SaleReceipt/WriteJournalEntries.ts +++ b/packages/server/src/subscribers/SaleReceipt/WriteJournalEntries.ts @@ -21,6 +21,10 @@ export default class SaleReceiptWriteGLEntriesSubscriber { events.saleReceipt.onCreated, this.handleWriteReceiptIncomeJournalEntrieOnCreate ); + bus.subscribe( + events.saleReceipt.onClosed, + this.handleWriteReceiptIncomeJournalEntrieOnCreate + ); bus.subscribe( events.saleReceipt.onEdited, this.handleWriteReceiptIncomeJournalEntrieOnEdited @@ -38,8 +42,12 @@ export default class SaleReceiptWriteGLEntriesSubscriber { public handleWriteReceiptIncomeJournalEntrieOnCreate = async ({ tenantId, saleReceiptId, + saleReceipt, trx, }: ISaleReceiptCreatedPayload) => { + // Can't continue if the sale receipt is not closed yet. + if (!saleReceipt.closedAt) return null; + // Writes the sale receipt income journal entries. await this.saleReceiptGLEntries.writeIncomeGLEntries( tenantId, @@ -71,8 +79,12 @@ export default class SaleReceiptWriteGLEntriesSubscriber { private handleWriteReceiptIncomeJournalEntrieOnEdited = async ({ tenantId, saleReceiptId, + saleReceipt, trx, }: ISaleReceiptEditedPayload) => { + // Can't continue if the sale receipt is not closed yet. + if (!saleReceipt.closedAt) return null; + // Writes the sale receipt income journal entries. await this.saleReceiptGLEntries.rewriteReceiptGLEntries( tenantId, diff --git a/packages/server/src/subscribers/events.ts b/packages/server/src/subscribers/events.ts index f8653238a..df91245b6 100644 --- a/packages/server/src/subscribers/events.ts +++ b/packages/server/src/subscribers/events.ts @@ -220,6 +220,9 @@ export default { onPublishing: 'onBillPublishing', onPublished: 'onBillPublished', + + onOpening: 'onBillOpening', + onOpened: 'onBillOpened', }, /** diff --git a/packages/server/src/utils/transactions-types.ts b/packages/server/src/utils/transactions-types.ts new file mode 100644 index 000000000..ab5981115 --- /dev/null +++ b/packages/server/src/utils/transactions-types.ts @@ -0,0 +1,5 @@ +import { TransactionTypes } from '@/data/TransactionTypes'; + +export const getTransactionTypeLabel = (transactionType: string) => { + return TransactionTypes[transactionType]; +}; diff --git a/packages/server/tests/routes/auth.test.js b/packages/server/tests/routes/auth.test.js index 69226bad8..0f9da2b34 100644 --- a/packages/server/tests/routes/auth.test.js +++ b/packages/server/tests/routes/auth.test.js @@ -95,7 +95,7 @@ describe('routes: /auth/', () => { expect(res.status).equals(200); }); - it('Should autheticate success with correct phone number and password.', async () => { + it('Should authenticate success with correct phone number and password.', async () => { const password = await hashPassword('admin'); const user = await createUser(tenantWebsite, { phone_number: '0920000000', diff --git a/packages/server/tests/routes/sales_invoices.test.js b/packages/server/tests/routes/sales_invoices.test.js index 8e759fbdc..f0441dd5a 100644 --- a/packages/server/tests/routes/sales_invoices.test.js +++ b/packages/server/tests/routes/sales_invoices.test.js @@ -471,7 +471,7 @@ describe('route: `/sales/invoices`', () => { }); }); - it('Should delete the given sale invoice with assocaited entries.', async () => { + it('Should delete the given sale invoice with associated entries.', async () => { const saleInvoice = await tenantFactory.create('sale_invoice'); const saleInvoiceEntey = await tenantFactory.create('sale_invoice_entry', { sale_invoice_id: saleInvoice.id, diff --git a/packages/webapp/package-lock.json b/packages/webapp/package-lock.json index 86134863b..d9c359fbc 100644 --- a/packages/webapp/package-lock.json +++ b/packages/webapp/package-lock.json @@ -1227,9 +1227,9 @@ } }, "@blueprintjs-formik/select": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@blueprintjs-formik/select/-/select-0.2.5.tgz", - "integrity": "sha512-Sztf5dOemedUBfEjnDWD8ryfMU/x95hyhIgJT5/ywC/jQfX+d/K2OhujklTrCDzQilUeAJLoVkSdV+w77n8ckQ==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@blueprintjs-formik/select/-/select-0.3.1.tgz", + "integrity": "sha512-gEoXne1kOPSq8hoQmJ3OyE1HMQAFYsSKnddN59dmkWTgobKxA+hH7mcdhbbkVSx93r3wg/oyWw4CHxOaZspGOQ==", "requires": { "lodash.get": "^4.4.2", "lodash.keyby": "^4.6.0", @@ -17751,4 +17751,4 @@ "integrity": "sha512-7UlRWU4Q3uCMCeDVMOm7eBrIu145OqsIJ3p6zq58l8UsSYwKWxc6zEapC5YA9tIeh0oheb4cT9Kk2Wq353loFg==" } } -} \ No newline at end of file +} diff --git a/packages/webapp/package.json b/packages/webapp/package.json index 96ac5d16f..7e3c9a47c 100644 --- a/packages/webapp/package.json +++ b/packages/webapp/package.json @@ -5,7 +5,7 @@ "dependencies": { "@blueprintjs-formik/core": "^0.3.4", "@blueprintjs-formik/datetime": "^0.3.4", - "@blueprintjs-formik/select": "^0.2.5", + "@blueprintjs-formik/select": "^0.3.1", "@blueprintjs/core": "^3.50.2", "@blueprintjs/datetime": "^3.23.12", "@blueprintjs/popover2": "^0.11.1", diff --git a/packages/webapp/src/components/AvaterCell.tsx b/packages/webapp/src/components/AvatarCell.tsx similarity index 100% rename from packages/webapp/src/components/AvaterCell.tsx rename to packages/webapp/src/components/AvatarCell.tsx diff --git a/packages/webapp/src/components/Contacts/ContactsMultiSelect.tsx b/packages/webapp/src/components/Contacts/ContactsMultiSelect.tsx index 2eb3536a4..02de5b22d 100644 --- a/packages/webapp/src/components/Contacts/ContactsMultiSelect.tsx +++ b/packages/webapp/src/components/Contacts/ContactsMultiSelect.tsx @@ -1,43 +1,78 @@ // @ts-nocheck import React, { useCallback } from 'react'; -import { MenuItem } from '@blueprintjs/core'; -import { MultiSelect } from '../MultiSelectTaggable'; +import * as R from 'ramda'; +import { FMultiSelect } from '../Forms'; +import withDrawerActions from '@/containers/Drawer/withDrawerActions'; +import { DRAWERS } from '@/constants/drawers'; /** * Contacts multi-select component. */ -export function ContactsMultiSelect({ ...multiSelectProps }) { - // Filters accounts items. - const filterContactsPredicater = useCallback( - (query, contact, _index, exactMatch) => { - const normalizedTitle = contact.display_name.toLowerCase(); - const normalizedQuery = query.toLowerCase(); - - if (exactMatch) { - return normalizedTitle === normalizedQuery; - } else { - return normalizedTitle.indexOf(normalizedQuery) >= 0; - } - }, - [], - ); +export function ContactsMultiSelect({ allowCreate, ...multiSelectProps }) { + // Maybe inject new item props to select component. + const maybeCreateNewItemRenderer = allowCreate ? createNewItemRenderer : null; + const maybeCreateNewItemFromQuery = allowCreate + ? createNewItemFromQuery + : null; return ( - ( - - )} + item.display_name} + createNewItemRenderer={maybeCreateNewItemRenderer} + createNewItemFromQuery={maybeCreateNewItemFromQuery} {...multiSelectProps} /> ); } + +/** + * Customers multi-select component. + */ +function CustomersMultiSelectRoot({ + // #withDrawerAction + openDrawer, + closeDrawer, + ...props +}) { + const handleCreateItemClick = () => { + openDrawer(DRAWERS.QUICK_CREATE_CUSTOMER); + }; + return ( + + ); +} + +/** + * Vendors multi-select component. + */ +function VendorsMultiSelectRoot({ + // #withDrawerAction + openDrawer, + closeDrawer, + ...props +}) { + const handleCreateItemClick = () => { + openDrawer(DRAWERS.QUICK_WRITE_VENDOR); + }; + return ( + + ); +} + +export const CustomersMultiSelect = R.compose(withDrawerActions)( + CustomersMultiSelectRoot, +); + +export const VendorsMultiSelect = R.compose(withDrawerActions)( + VendorsMultiSelectRoot, +); diff --git a/packages/webapp/src/components/Dashboard/DashboardBoot.tsx b/packages/webapp/src/components/Dashboard/DashboardBoot.tsx index 2389cc4a7..bae18273e 100644 --- a/packages/webapp/src/components/Dashboard/DashboardBoot.tsx +++ b/packages/webapp/src/components/Dashboard/DashboardBoot.tsx @@ -86,7 +86,7 @@ export function useApplicationBoot() { const [startLoading, stopLoading] = useSplashLoading(); // Splash loading when organization request loading and - // applicaiton still not booted. + // application still not booted. useWatchImmediate((value) => { value && !isBooted.current && startLoading(); }, isOrgLoading); diff --git a/packages/webapp/src/components/Items/ItemsMultiSelect.tsx b/packages/webapp/src/components/Items/ItemsMultiSelect.tsx index 31c2a18cb..aed937376 100644 --- a/packages/webapp/src/components/Items/ItemsMultiSelect.tsx +++ b/packages/webapp/src/components/Items/ItemsMultiSelect.tsx @@ -1,49 +1,48 @@ // @ts-nocheck -import React, { useCallback } from 'react'; -import { MenuItem } from '@blueprintjs/core'; -import { MultiSelect } from '@/components'; +import React from 'react'; +import * as R from 'ramda'; +import { FMultiSelect } from '@/components/Forms'; +import withDialogActions from '@/containers/Dialog/withDialogActions'; /** * Items multi-select. */ -export function ItemsMultiSelect({ ...multiSelectProps }) { - // Filters accounts items. - const filterItemsPredicater = useCallback( - (query, item, _index, exactMatch) => { - const normalizedTitle = item.name.toLowerCase(); - const normalizedQuery = query.toLowerCase(); +function ItemsMultiSelectRoot({ + // #withDialogAction + openDialog, + closeDialog, - if (exactMatch) { - return normalizedTitle === normalizedQuery; - } else { - return `${normalizedTitle} ${item.code}`.indexOf(normalizedQuery) >= 0; - } - }, - [], - ); + // #props + allowCreate, + ...multiSelectProps +}) { + // Maybe inject new item props to select component. + const maybeCreateNewItemRenderer = allowCreate ? createNewItemRenderer : null; + const maybeCreateNewItemFromQuery = allowCreate + ? createNewItemFromQuery + : null; + + // Handles the create item click. + const handleCreateItemClick = () => { + openDialog(DialogsName.AccountForm); + }; return ( - ( - - )} - popoverProps={{ minimal: true, usePortal: false, targetTagName: 'div ' }} + item.name} + popoverProps={{ minimal: true }} resetOnSelect={true} + createNewItemRenderer={maybeCreateNewItemRenderer} + createNewItemFromQuery={maybeCreateNewItemFromQuery} + onCreateItemSelect={handleCreateItemClick} {...multiSelectProps} /> ); } -ItemsMultiSelect.defaultProps = { - initialSelectedItems: [], -}; +export const ItemsMultiSelect = + R.compose(withDialogActions)(ItemsMultiSelectRoot); diff --git a/packages/webapp/src/components/index.tsx b/packages/webapp/src/components/index.tsx index 79efd3148..4a8478e3d 100644 --- a/packages/webapp/src/components/index.tsx +++ b/packages/webapp/src/components/index.tsx @@ -1,7 +1,7 @@ // @ts-nocheck import MODIFIER from './modifiers'; import ContextMenu from './ContextMenu'; -import AvaterCell from './AvaterCell'; +import AvatarCell from './AvatarCell'; export * from './Money/Money'; export * from './Dialog'; @@ -65,4 +65,4 @@ export * from './Postbox'; export * from './AppToaster'; export * from './Layout'; -export { MODIFIER, ContextMenu, AvaterCell }; +export { MODIFIER, ContextMenu, AvatarCell }; diff --git a/packages/webapp/src/containers/Customers/CustomerForm/CustomerForm.tsx b/packages/webapp/src/containers/Customers/CustomerForm/CustomerForm.tsx index ceca8de2c..bcc7df75b 100644 --- a/packages/webapp/src/containers/Customers/CustomerForm/CustomerForm.tsx +++ b/packages/webapp/src/containers/Customers/CustomerForm/CustomerForm.tsx @@ -4,7 +4,7 @@ import { CustomerFormProvider } from './CustomerFormProvider'; import CustomerFormFormik from './CustomerFormFormik'; /** - * Abstructed customer form. + * Abstracted customer form. */ export default function CustomerForm({ customerId }) { return ( diff --git a/packages/webapp/src/containers/Customers/CustomersLanding/components.tsx b/packages/webapp/src/containers/Customers/CustomersLanding/components.tsx index c93bcb31f..0de0a69b5 100644 --- a/packages/webapp/src/containers/Customers/CustomersLanding/components.tsx +++ b/packages/webapp/src/containers/Customers/CustomersLanding/components.tsx @@ -11,7 +11,7 @@ import { Classes, } from '@blueprintjs/core'; -import { Can, Icon, Money, If, AvaterCell } from '@/components'; +import { Can, Icon, Money, If, AvatarCell } from '@/components'; import { CustomerAction, AbilitySubject } from '@/constants/abilityOption'; import { safeCallback } from '@/utils'; @@ -121,7 +121,7 @@ export function useCustomersTableColumns() { { id: 'avatar', Header: '', - Cell: AvaterCell, + Cell: AvatarCell, className: 'avatar', width: 45, disableResizing: true, diff --git a/packages/webapp/src/containers/Dialogs/WarehouseActivateDialog/index.tsx b/packages/webapp/src/containers/Dialogs/WarehouseActivateDialog/index.tsx index 1537c0c0d..ea0ac1272 100644 --- a/packages/webapp/src/containers/Dialogs/WarehouseActivateDialog/index.tsx +++ b/packages/webapp/src/containers/Dialogs/WarehouseActivateDialog/index.tsx @@ -16,7 +16,7 @@ function WarehouseActivateDialog({ dialogName, payload: {}, isOpen }) { return ( } + title={} isOpen={isOpen} canEscapeJeyClose={true} autoFocus={true} diff --git a/packages/webapp/src/containers/Drawers/BillDrawer/BillDetailTableFooter.tsx b/packages/webapp/src/containers/Drawers/BillDrawer/BillDetailTableFooter.tsx index 6ad6d62d5..e3b44c1ce 100644 --- a/packages/webapp/src/containers/Drawers/BillDrawer/BillDetailTableFooter.tsx +++ b/packages/webapp/src/containers/Drawers/BillDrawer/BillDetailTableFooter.tsx @@ -23,7 +23,7 @@ export function BillDetailTableFooter() { } - value={} + value={} borderStyle={TotalLineBorderStyle.SingleDark} /> { - const _filter = { - ...filter, - asDate: moment(filter.asDate).format('YYYY-MM-DD'), - }; - setFilter(_filter); - }, []); - + const handleFilterSubmit = useCallback( + (filter) => { + const _filter = { + ...filter, + asDate: moment(filter.asDate).format('YYYY-MM-DD'), + }; + setLocationQuery(_filter); + }, + [setLocationQuery], + ); // Handle number format submit. const handleNumberFormatSubmit = (numberFormat) => { - setFilter({ - ...filter, - numberFormat, - }); + setLocationQuery({ ...filter, numberFormat }); }; // Hide the report filter drawer once the page unmount. useEffect( @@ -55,9 +52,9 @@ function APAgingSummary({ ); return ( - + @@ -65,7 +62,7 @@ function APAgingSummary({ diff --git a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryBody.tsx b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryBody.tsx index c49642106..366404561 100644 --- a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryBody.tsx +++ b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryBody.tsx @@ -18,11 +18,11 @@ function APAgingSummaryBodyJSX({ // #withCurrentOrganization organizationName, }) { - const { isLoading } = useAPAgingSummaryContext(); + const { isAPAgingLoading } = useAPAgingSummaryContext(); return ( - {isLoading ? ( + {isAPAgingLoading ? ( ) : ( diff --git a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryHeader.tsx b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryHeader.tsx index 1eeecb772..f935a39ee 100644 --- a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryHeader.tsx @@ -1,7 +1,5 @@ // @ts-nocheck import React from 'react'; -import moment from 'moment'; -import * as Yup from 'yup'; import styled from 'styled-components'; import { FormattedMessage as T } from '@/components'; import { Formik, Form } from 'formik'; @@ -17,6 +15,10 @@ import withAPAgingSummaryActions from './withAPAgingSummaryActions'; import { transformToForm, compose } from '@/utils'; import { useFeatureCan } from '@/hooks/state'; import { Features } from '@/constants'; +import { + getAPAgingSummaryQuerySchema, + getDefaultAPAgingSummaryQuery, +} from './common'; /** * AP Aging Summary Report - Drawer Header. @@ -33,39 +35,22 @@ function APAgingSummaryHeader({ isFilterDrawerOpen, }) { // Validation schema. - const validationSchema = Yup.object({ - asDate: Yup.date().required().label('asDate'), - agingDaysBefore: Yup.number() - .required() - .integer() - .positive() - .label('agingBeforeDays'), - agingPeriods: Yup.number() - .required() - .integer() - .positive() - .label('agingPeriods'), - }); + const validationSchema = getAPAgingSummaryQuerySchema(); // Initial values. - const defaultValues = { - asDate: moment(pageFilter.asDate).toDate(), - agingDaysBefore: 30, - agingPeriods: 3, - vendorsIds: [], - branchesIds: [], - filterByOption: 'without-zero-balance', - }; - // Formik initial values. - const initialValues = transformToForm({ ...pageFilter }, defaultValues); + const defaultValues = getDefaultAPAgingSummaryQuery(); + // Formik initial values. + const initialValues = transformToForm( + { ...defaultValues, ...pageFilter }, + defaultValues, + ); // Handle form submit. const handleSubmit = (values, { setSubmitting }) => { onSubmitFilter(values); toggleFilterDrawerDisplay(false); setSubmitting(false); }; - // Handle cancel button click. const handleCancelClick = () => { toggleFilterDrawerDisplay(false); @@ -74,9 +59,8 @@ function APAgingSummaryHeader({ const handleDrawerClose = () => { toggleFilterDrawerDisplay(false); }; - // Detarmines the feature whether is enabled. + // Detarmines whether the feature is enabled. const { featureCan } = useFeatureCan(); - const isBranchesFeatureCan = featureCan(Features.Branches); return ( diff --git a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryHeaderGeneralContent.tsx b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryHeaderGeneralContent.tsx index d1fd8de43..c079f39df 100644 --- a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryHeaderGeneralContent.tsx +++ b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryHeaderGeneralContent.tsx @@ -1,21 +1,15 @@ // @ts-nocheck import React from 'react'; -import { FastField, Field } from 'formik'; +import { FastField } from 'formik'; +import { Intent, FormGroup, InputGroup, Position } from '@blueprintjs/core'; import { DateInput } from '@blueprintjs/datetime'; -import { - Intent, - FormGroup, - InputGroup, - Position, - Classes, -} from '@blueprintjs/core'; -import classNames from 'classnames'; import { FormattedMessage as T, - ContactsMultiSelect, Row, Col, FieldHint, + FFormGroup, + VendorsMultiSelect, } from '@/components'; import { useAPAgingSummaryGeneralContext } from './APAgingSummaryGeneralProvider'; import FinancialStatementsFilter from '../FinancialStatementsFilter'; @@ -104,22 +98,9 @@ export default function APAgingSummaryHeaderGeneralContent() { - - {({ form: { setFieldValue }, field: { value } }) => ( - } - className={classNames('form-group--select-list', Classes.FILL)} - > - { - const vendorsIds = vendors.map((customer) => customer.id); - setFieldValue('vendorsIds', vendorsIds); - }} - /> - - )} - + } name={'vendorsIds'}> + + diff --git a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryTable.tsx b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryTable.tsx index a54f25a09..115a8a887 100644 --- a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryTable.tsx +++ b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/APAgingSummaryTable.tsx @@ -20,7 +20,7 @@ export default function APAgingSummaryTable({ }) { // AP aging summary report content. const { - APAgingSummary: { tableRows }, + APAgingSummary: { table, query }, isAPAgingLoading, } = useAPAgingSummaryContext(); @@ -31,12 +31,12 @@ export default function APAgingSummaryTable({ { return flatObject(transformToCamelCase(form)); }; +/** + * The default query of AP aging summary. + * @returns + */ export const getDefaultAPAgingSummaryQuery = () => { return { asDate: moment().endOf('day').format('YYYY-MM-DD'), agingDaysBefore: 30, agingPeriods: 3, + filterByOption: 'without-zero-balance', vendorsIds: [], branchesIds: [], - filterByOption: 'without-zero-balance', - } -} \ No newline at end of file + }; +}; + +/** + * Retrieves the query validation schema. + * @returns {Yup} + */ +export const getAPAgingSummaryQuerySchema = () => { + return Yup.object({ + asDate: Yup.date().required().label('asDate'), + agingDaysBefore: Yup.number() + .required() + .integer() + .positive() + .label('Aging days before') + .min(1) + .max(500), + agingPeriods: Yup.number() + .required() + .integer() + .positive() + .max(12) + .min(1) + .label('Aging periods'), + }); +}; + +/** + * Parses the AP aging summary query state. + * @param locationQuery + * @returns + */ +const parseAPAgingSummaryQuery = (locationQuery) => { + const defaultQuery = getDefaultAPAgingSummaryQuery(); + + const transformed = { + ...defaultQuery, + ...transformToForm(locationQuery, defaultQuery), + }; + return { + ...transformed, + vendorsIds: castArray(transformed.vendorsIds), + branchesIds: castArray(transformed.branchesIds), + }; +}; + +/** + * AP aging summary query state. + */ +export const useAPAgingSummaryQuery = () => { + // Retrieves location query. + const [locationQuery, setLocationQuery] = useAppQueryString(); + + // Merges the default filter query with location URL query. + const query = useMemo( + () => parseAPAgingSummaryQuery(locationQuery), + [locationQuery], + ); + return { query, locationQuery, setLocationQuery }; +}; diff --git a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/components.tsx b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/components.tsx index b67c7c7ce..f6af9931a 100644 --- a/packages/webapp/src/containers/FinancialStatements/APAgingSummary/components.tsx +++ b/packages/webapp/src/containers/FinancialStatements/APAgingSummary/components.tsx @@ -1,57 +1,20 @@ // @ts-nocheck import React, { useMemo } from 'react'; -import intl from 'react-intl-universal'; -import { If, FormattedMessage as T } from '@/components'; -import { useAPAgingSummaryContext } from './APAgingSummaryProvider'; -import { getColumnWidth } from '@/utils'; + +import { If } from '@/components'; import FinancialLoadingBar from '../FinancialLoadingBar'; +import { useAPAgingSummaryContext } from './APAgingSummaryProvider'; +import { agingSummaryDynamicColumns } from '../AgingSummary/dynamicColumns'; /** * Retrieve AP aging summary columns. */ export const useAPAgingSummaryColumns = () => { const { - APAgingSummary: { tableRows, columns }, + APAgingSummary: { table }, } = useAPAgingSummaryContext(); - const agingColumns = React.useMemo(() => { - return columns.map( - (agingColumn) => - `${agingColumn.before_days} - ${ - agingColumn.to_days || intl.get('and_over') - }`, - ); - }, [columns]); - - return useMemo( - () => [ - { - Header: , - accessor: 'name', - className: 'vendor_name', - width: 240, - sticky: 'left', - textOverview: true, - }, - { - Header: , - accessor: 'current', - className: 'current', - width: getColumnWidth(tableRows, `current`, { minWidth: 120 }), - }, - ...agingColumns.map((agingColumn, index) => ({ - Header: agingColumn, - accessor: `aging-${index}`, - width: getColumnWidth(tableRows, `aging-${index}`, { minWidth: 120 }), - })), - { - Header: , - accessor: 'total', - width: getColumnWidth(tableRows, 'total', { minWidth: 120 }), - }, - ], - [tableRows, agingColumns], - ); + return agingSummaryDynamicColumns(table.columns, table.rows); }; /** diff --git a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummary.tsx b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummary.tsx index 99456ae26..2ff0550bb 100644 --- a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummary.tsx +++ b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummary.tsx @@ -2,7 +2,6 @@ import React, { useState, useCallback, useEffect } from 'react'; import moment from 'moment'; - import ARAgingSummaryHeader from './ARAgingSummaryHeader'; import ARAgingSummaryActionsBar from './ARAgingSummaryActionsBar'; @@ -13,7 +12,7 @@ import { ARAgingSummaryBody } from './ARAgingSummaryBody'; import withARAgingSummaryActions from './withARAgingSummaryActions'; -import { getDefaultARAgingSummaryQuery } from './common'; +import { useARAgingSummaryQuery } from './common'; import { compose } from '@/utils'; /** @@ -23,9 +22,7 @@ function ReceivableAgingSummarySheet({ // #withARAgingSummaryActions toggleARAgingSummaryFilterDrawer: toggleDisplayFilterDrawer, }) { - const [filter, setFilter] = useState({ - ...getDefaultARAgingSummaryQuery(), - }); + const { query, setLocationQuery } = useARAgingSummaryQuery(); // Handle filter submit. const handleFilterSubmit = useCallback((filter) => { @@ -33,25 +30,23 @@ function ReceivableAgingSummarySheet({ ...filter, asDate: moment(filter.asDate).format('YYYY-MM-DD'), }; - setFilter(_filter); - }, []); + setLocationQuery(_filter); + }, [setLocationQuery]); // Handle number format submit. const handleNumberFormatSubmit = (numberFormat) => { - setFilter({ ...filter, numberFormat }); + setLocationQuery({ ...query, numberFormat }); }; // Hide the filter drawer once the page unmount. useEffect( - () => () => { - toggleDisplayFilterDrawer(false); - }, + () => () => toggleDisplayFilterDrawer(false), [toggleDisplayFilterDrawer], ); return ( - + @@ -59,7 +54,7 @@ function ReceivableAgingSummarySheet({ diff --git a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeader.tsx b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeader.tsx index 5e0c8e471..2dcb33c32 100644 --- a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeader.tsx @@ -2,7 +2,6 @@ import React from 'react'; import styled from 'styled-components'; import moment from 'moment'; -import * as Yup from 'yup'; import { FormattedMessage as T } from '@/components'; import { Formik, Form } from 'formik'; import { Tabs, Tab, Button, Intent } from '@blueprintjs/core'; @@ -17,6 +16,10 @@ import withARAgingSummaryActions from './withARAgingSummaryActions'; import { compose, transformToForm } from '@/utils'; import { useFeatureCan } from '@/hooks/state'; import { Features } from '@/constants'; +import { + getARAgingSummaryQuerySchema, + getDefaultARAgingSummaryQuery, +} from './common'; /** * AR Aging Summary Report - Drawer Header. @@ -33,32 +36,15 @@ function ARAgingSummaryHeader({ isFilterDrawerOpen, }) { // Validation schema. - const validationSchema = Yup.object().shape({ - asDate: Yup.date().required().label('asDate'), - agingDaysBefore: Yup.number() - .required() - .integer() - .positive() - .label('agingDaysBefore'), - agingPeriods: Yup.number() - .required() - .integer() - .positive() - .label('agingPeriods'), - }); + const validationSchema = getARAgingSummaryQuerySchema(); + // Initial values. - const defaultValues = { - asDate: moment().toDate(), - agingDaysBefore: 30, - agingPeriods: 3, - customersIds: [], - branchesIds: [], - filterByOption: 'without-zero-balance', - }; + const defaultValues = getDefaultARAgingSummaryQuery(); // Initial values. const initialValues = transformToForm( { + ...defaultValues, ...pageFilter, asDate: moment(pageFilter.asDate).toDate(), }, @@ -80,7 +66,6 @@ function ARAgingSummaryHeader({ }; // Detarmines the feature whether is enabled. const { featureCan } = useFeatureCan(); - const isBranchesFeatureCan = featureCan(Features.Branches); return ( diff --git a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeaderGeneralContent.tsx b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeaderGeneralContent.tsx index 64dc309fe..9d7ded2dc 100644 --- a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeaderGeneralContent.tsx +++ b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryHeaderGeneralContent.tsx @@ -2,22 +2,16 @@ import React from 'react'; import { FastField, Field } from 'formik'; import { DateInput } from '@blueprintjs/datetime'; -import { - Intent, - FormGroup, - InputGroup, - Position, - Classes, -} from '@blueprintjs/core'; -import classNames from 'classnames'; - +import { Intent, FormGroup, InputGroup, Position } from '@blueprintjs/core'; import FinancialStatementsFilter from '../FinancialStatementsFilter'; import { FormattedMessage as T, - ContactsMultiSelect, Row, Col, FieldHint, + FInputGroup, + FFormGroup, + CustomersMultiSelect, } from '@/components'; import { momentFormatter } from '@/utils'; import { useARAgingSummaryGeneralContext } from './ARAgingSummaryGeneralProvider'; @@ -81,22 +75,13 @@ export default function ARAgingSummaryHeaderGeneralContent() { - - {({ field, meta: { error, touched } }) => ( - } - labelInfo={} - className={'form-group--aging-periods'} - intent={error && Intent.DANGER} - > - - - )} - + } + labelInfo={} + > + + @@ -111,24 +96,12 @@ export default function ARAgingSummaryHeaderGeneralContent() { - - {({ form: { setFieldValue }, field: { value } }) => ( - } - className={classNames('form-group--select-list', Classes.FILL)} - > - { - const customersIds = customers.map( - (customer) => customer.id, - ); - setFieldValue('customersIds', customersIds); - }} - /> - - )} - + } + > + + diff --git a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryProvider.tsx b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryProvider.tsx index c29e2a43d..1b9577900 100644 --- a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryProvider.tsx +++ b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryProvider.tsx @@ -11,7 +11,10 @@ const ARAgingSummaryContext = createContext(); */ function ARAgingSummaryProvider({ filter, ...props }) { // Transformes the filter from to the url query. - const query = useMemo(() => transformFilterFormToQuery(filter), [filter]); + const requestQuery = useMemo( + () => transformFilterFormToQuery(filter), + [filter], + ); // A/R aging summary sheet context. const { @@ -19,11 +22,10 @@ function ARAgingSummaryProvider({ filter, ...props }) { isLoading: isARAgingLoading, isFetching: isARAgingFetching, refetch, - } = useARAgingSummaryReport(query, { keepPreviousData: true }); + } = useARAgingSummaryReport(requestQuery, { keepPreviousData: true }); const provider = { ARAgingSummary, - isARAgingLoading, isARAgingFetching, refetch, diff --git a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryTable.tsx b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryTable.tsx index 11f1dfa19..2cde74a37 100644 --- a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryTable.tsx +++ b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/ARAgingSummaryTable.tsx @@ -19,7 +19,10 @@ export default function ReceivableAgingSummaryTable({ organizationName, }) { // AR aging summary report context. - const { ARAgingSummary, isARAgingLoading } = useARAgingSummaryContext(); + const { + ARAgingSummary: { table, query }, + isARAgingLoading, + } = useARAgingSummaryContext(); // AR aging summary columns. const columns = useARAgingSummaryColumns(); @@ -28,12 +31,12 @@ export default function ReceivableAgingSummaryTable({ { return flatObject(transformToCamelCase(form)); @@ -14,8 +18,61 @@ export const getDefaultARAgingSummaryQuery = () => { asDate: moment().endOf('day').format('YYYY-MM-DD'), agingDaysBefore: 30, agingPeriods: 3, - customersIds: [], filterByOption: 'without-zero-balance', + customersIds: [], branchesIds: [], }; }; + +/** + * Retrieves the AR aging summary query schema. + * @returns {Yup} + */ +export const getARAgingSummaryQuerySchema = () => { + return Yup.object().shape({ + asDate: Yup.date().required().label('asDate'), + agingDaysBefore: Yup.number() + .required() + .integer() + .positive() + .label('Aging days before') + .min(1) + .max(500), + agingPeriods: Yup.number() + .required() + .integer() + .positive() + .max(12) + .min(1) + .label('Aging periods'), + }); +}; + +/** + * Parses the AR aging summary state. + */ +const parseARAgingSummaryQuery = (locationQuery) => { + const defaultQuery = getDefaultARAgingSummaryQuery(); + const transformed = { + ...defaultQuery, + ...transformToForm(locationQuery, defaultQuery), + }; + return { + ...transformed, + branchesIds: castArray(transformed.branchesIds), + customersIds: castArray(transformed.customersIds), + }; +}; + +/** + * AR aging summary query state. + */ +export const useARAgingSummaryQuery = () => { + const [locationQuery, setLocationQuery] = useAppQueryString(); + + const query = useMemo( + () => parseARAgingSummaryQuery(locationQuery), + [locationQuery], + ); + return { query, locationQuery, setLocationQuery }; +}; diff --git a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/components.tsx b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/components.tsx index 1cbea1c17..e2e89a8db 100644 --- a/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/components.tsx +++ b/packages/webapp/src/containers/FinancialStatements/ARAgingSummary/components.tsx @@ -1,71 +1,20 @@ // @ts-nocheck import React from 'react'; -import intl from 'react-intl-universal'; import { useARAgingSummaryContext } from './ARAgingSummaryProvider'; import { If, FormattedMessage as T } from '@/components'; -import { getColumnWidth } from '@/utils'; -import { Align } from '@/constants'; - import FinancialLoadingBar from '../FinancialLoadingBar'; +import { agingSummaryDynamicColumns } from '../AgingSummary/dynamicColumns'; /** * Retrieve AR aging summary columns. */ export const useARAgingSummaryColumns = () => { const { - ARAgingSummary: { tableRows, columns }, + ARAgingSummary: { table }, } = useARAgingSummaryContext(); - const agingColumns = React.useMemo(() => { - return columns.map( - (agingColumn) => - `${agingColumn.before_days} - ${ - agingColumn.to_days || intl.get('and_over') - }`, - ); - }, [columns]); - - return React.useMemo( - () => [ - { - Header: , - accessor: 'name', - className: 'customer_name', - sticky: 'left', - width: 240, - textOverview: true, - }, - { - Header: , - accessor: 'current', - className: 'current', - width: getColumnWidth(tableRows, `current`, { - minWidth: 120, - }), - align: Align.Right - }, - ...agingColumns.map((agingColumn, index) => ({ - Header: agingColumn, - accessor: `aging-${index}`, - width: getColumnWidth(tableRows, `aging-${index}`, { - minWidth: 120, - }), - align: Align.Right - })), - { - Header: , - id: 'total', - accessor: 'total', - className: 'total', - width: getColumnWidth(tableRows, 'total', { - minWidth: 120, - }), - align: Align.Right - }, - ], - [tableRows, agingColumns], - ); + return agingSummaryDynamicColumns(table.columns, table.rows); }; /** diff --git a/packages/webapp/src/containers/FinancialStatements/AgingSummary/dynamicColumns.ts b/packages/webapp/src/containers/FinancialStatements/AgingSummary/dynamicColumns.ts new file mode 100644 index 000000000..971bdadb7 --- /dev/null +++ b/packages/webapp/src/containers/FinancialStatements/AgingSummary/dynamicColumns.ts @@ -0,0 +1,74 @@ +// @ts-nocheck +import React, { useMemo } from 'react'; +import * as R from 'ramda'; +import { getColumnWidth } from '@/utils'; +import { Align } from '@/constants'; + +const getTableCellValueAccessor = (index) => `cells[${index}].value`; + +const contactNameAccessor = R.curry((data, column) => ({ + key: column.key, + Header: column.label, + accessor: getTableCellValueAccessor(column.cell_index), + sticky: 'left', + width: 240, + textOverview: true, +})); + +const currentAccessor = R.curry((data, column) => { + const accessor = getTableCellValueAccessor(column.cell_index); + + return { + key: column.key, + Header: column.label, + accessor, + className: column.id, + width: getColumnWidth(data, accessor, { minWidth: 120 }), + align: Align.Right, + }; +}); + +const totalAccessor = R.curry((data, column) => { + const accessor = getTableCellValueAccessor(column.cell_index); + + return { + Header: column.label, + id: column.key, + accessor: getTableCellValueAccessor(column.cell_index), + className: column.key, + width: getColumnWidth(data, accessor, { minWidth: 120 }), + align: Align.Right, + }; +}); + +const agingPeriodAccessor = R.curry((data, column) => { + const accessor = getTableCellValueAccessor(column.cell_index); + + return { + Header: column.label, + id: `${column.key}-${column.cell_index}`, + accessor, + className: column.key, + width: getColumnWidth(data, accessor, { minWidth: 120 }), + align: Align.Right, + }; +}); + +const dynamicColumnMapper = R.curry((data, column) => { + const totalAccessorColumn = totalAccessor(data); + const currentAccessorColumn = currentAccessor(data); + const customerNameAccessorColumn = contactNameAccessor(data); + const agingPeriodAccessorColumn = agingPeriodAccessor(data); + + return R.compose( + R.when(R.pathEq(['key'], 'total'), totalAccessorColumn), + R.when(R.pathEq(['key'], 'current'), currentAccessorColumn), + R.when(R.pathEq(['key'], 'customer_name'), customerNameAccessorColumn), + R.when(R.pathEq(['key'], 'vendor_name'), customerNameAccessorColumn), + R.when(R.pathEq(['key'], 'aging_period'), agingPeriodAccessorColumn), + )(column); +}); + +export const agingSummaryDynamicColumns = (columns, data) => { + return R.map(dynamicColumnMapper(data), columns); +}; diff --git a/packages/webapp/src/containers/FinancialStatements/BalanceSheet/BalanceSheetHeader.tsx b/packages/webapp/src/containers/FinancialStatements/BalanceSheet/BalanceSheetHeader.tsx index f90c9d980..310a3c059 100644 --- a/packages/webapp/src/containers/FinancialStatements/BalanceSheet/BalanceSheetHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/BalanceSheet/BalanceSheetHeader.tsx @@ -68,7 +68,6 @@ function BalanceSheetHeader({ }; // Detarmines the given feature whether is enabled. const { featureCan } = useFeatureCan(); - const isBranchesFeatureCan = featureCan(Features.Branches); return ( diff --git a/packages/webapp/src/containers/FinancialStatements/BalanceSheet/utils.tsx b/packages/webapp/src/containers/FinancialStatements/BalanceSheet/utils.tsx index 937178490..2b9a2facd 100644 --- a/packages/webapp/src/containers/FinancialStatements/BalanceSheet/utils.tsx +++ b/packages/webapp/src/containers/FinancialStatements/BalanceSheet/utils.tsx @@ -15,7 +15,7 @@ import { useAppQueryString } from '@/hooks'; */ export const getDefaultBalanceSheetQuery = () => ({ fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), + toDate: moment().format('YYYY-MM-DD'), basis: 'cash', displayColumnsType: 'total', filterByOption: 'without-zero-balance', diff --git a/packages/webapp/src/containers/FinancialStatements/CashFlowStatement/utils.tsx b/packages/webapp/src/containers/FinancialStatements/CashFlowStatement/utils.tsx index ecad0760e..6606ce259 100644 --- a/packages/webapp/src/containers/FinancialStatements/CashFlowStatement/utils.tsx +++ b/packages/webapp/src/containers/FinancialStatements/CashFlowStatement/utils.tsx @@ -12,7 +12,7 @@ import { useAppQueryString } from '@/hooks'; export const getDefaultCashFlowSheetQuery = () => { return { fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), + toDate: moment().format('YYYY-MM-DD'), basis: 'cash', displayColumnsType: 'total', filterByOption: 'with-transactions', diff --git a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummary.tsx b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummary.tsx index ab4fa5b54..84d93e75d 100644 --- a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummary.tsx +++ b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummary.tsx @@ -1,5 +1,5 @@ // @ts-nocheck -import React, { useEffect, useState } from 'react'; +import React, { useEffect } from 'react'; import moment from 'moment'; import * as R from 'ramda'; @@ -10,11 +10,10 @@ import CustomersBalanceSummaryHeader from './CustomersBalanceSummaryHeader'; import { CustomerBalanceSummaryBody } from './CustomerBalanceSummaryBody'; import { CustomersBalanceSummaryProvider } from './CustomersBalanceSummaryProvider'; -import { getDefaultCustomersBalanceQuery } from './utils'; +import { useCustomerBalanceSummaryQuery } from './utils'; import { CustomersBalanceLoadingBar } from './components'; import withCustomersBalanceSummaryActions from './withCustomersBalanceSummaryActions'; - /** * Customers Balance summary. */ @@ -22,36 +21,33 @@ function CustomersBalanceSummary({ // #withCustomersBalanceSummaryActions toggleCustomerBalanceFilterDrawer, }) { - const [filter, setFilter] = useState({ - ...getDefaultCustomersBalanceQuery(), - }); + const { query, setLocationQuery } = useCustomerBalanceSummaryQuery(); + // Handle re-fetch customers balance summary after filter change. const handleFilterSubmit = (filter) => { const _filter = { ...filter, asDate: moment(filter.asDate).format('YYYY-MM-DD'), }; - setFilter({ ..._filter }); + setLocationQuery({ ..._filter }); }; // Handle number format. const handleNumberFormat = (values) => { - setFilter({ + setLocationQuery({ ...filter, numberFormat: values, }); }; useEffect( - () => () => { - toggleCustomerBalanceFilterDrawer(false); - }, + () => () => toggleCustomerBalanceFilterDrawer(false), [toggleCustomerBalanceFilterDrawer], ); return ( - + @@ -59,7 +55,7 @@ function CustomersBalanceSummary({ diff --git a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryGeneralPanelContent.tsx b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryGeneralPanelContent.tsx index fbd81fa24..227929af3 100644 --- a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryGeneralPanelContent.tsx +++ b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryGeneralPanelContent.tsx @@ -1,17 +1,16 @@ // @ts-nocheck import React from 'react'; -import { FastField, Field } from 'formik'; +import { FastField } from 'formik'; import { DateInput } from '@blueprintjs/datetime'; -import { Classes, FormGroup, Position, Checkbox } from '@blueprintjs/core'; +import { FormGroup, Position, Checkbox } from '@blueprintjs/core'; import { - ContactsMultiSelect, FormattedMessage as T, Row, Col, FieldHint, + CustomersMultiSelect, + FFormGroup, } from '@/components'; -import classNames from 'classnames'; - import { momentFormatter, tansformDateValue, @@ -86,26 +85,12 @@ export default function CustomersBalanceSummaryGeneralPanelContent() { - - {({ - form: { setFieldValue }, - field: { value }, - meta: { error, touched }, - }) => ( - } - className={classNames('form-group--select-list', Classes.FILL)} - > - { - const customersIds = contacts.map((contact) => contact.id); - setFieldValue('customersIds', customersIds); - }} - /> - - )} - + } + > + + diff --git a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryHeader.tsx b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryHeader.tsx index 131668761..2ceaf1c1d 100644 --- a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryHeader.tsx @@ -1,6 +1,6 @@ // @ts-nocheck import React from 'react'; -import * as Yup from 'yup'; + import styled from 'styled-components'; import moment from 'moment'; import { Formik, Form } from 'formik'; @@ -13,6 +13,7 @@ import withCustomersBalanceSummaryActions from './withCustomersBalanceSummaryAct import CustomersBalanceSummaryGeneralPanel from './CustomersBalanceSummaryGeneralPanel'; import { compose, transformToForm } from '@/utils'; +import { getCustomersBalanceQuerySchema } from './utils'; /** * Customers balance summary. @@ -29,9 +30,8 @@ function CustomersBalanceSummaryHeader({ toggleCustomerBalanceFilterDrawer, }) { // validation schema. - const validationSchema = Yup.object().shape({ - asDate: Yup.date().required().label('asDate'), - }); + const validationSchema = getCustomersBalanceQuerySchema(); + // Default form values. const defaultValues = { ...pageFilter, diff --git a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryTable.tsx b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryTable.tsx index 729b04617..6957483bc 100644 --- a/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryTable.tsx +++ b/packages/webapp/src/containers/FinancialStatements/CustomersBalanceSummary/CustomersBalanceSummaryTable.tsx @@ -18,7 +18,7 @@ export default function CustomersBalanceSummaryTable({ companyName, }) { const { - CustomerBalanceSummary: { table }, + CustomerBalanceSummary: { table, query }, } = useCustomersBalanceSummaryContext(); // Retrieves the customers summary columns. @@ -28,7 +28,7 @@ export default function CustomersBalanceSummaryTable({ { return { asDate: moment().endOf('day').format('YYYY-MM-DD'), filterByOption: 'with-transactions', + customersIds: [], }; }; + +/** + * Retrieves the customers balance query schema. + * @returns {Yup} + */ +export const getCustomersBalanceQuerySchema = () => { + return Yup.object().shape({ + asDate: Yup.date().required().label('asDate'), + }); +}; + +/** + * Parses the customer balance summary query. + */ +const parseCustomersBalanceSummaryQuery = (locationQuery) => { + const defaultQuery = getDefaultARAgingSummaryQuery(); + + const transformed = { + ...defaultQuery, + ...transformToForm(locationQuery, defaultQuery), + }; + return { + ...transformed, + customersIds: castArray(transformed.customersIds), + }; +}; + +/** + * Getter/setter query state of customers balance summary. + */ +export const useCustomerBalanceSummaryQuery = () => { + const [locationQuery, setLocationQuery] = useAppQueryString(); + + const query = useMemo( + () => parseCustomersBalanceSummaryQuery(locationQuery), + [locationQuery], + ); + return { query, locationQuery, setLocationQuery }; +}; diff --git a/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactions.tsx b/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactions.tsx index b170cabe2..bd2d5bc52 100644 --- a/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactions.tsx +++ b/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactions.tsx @@ -13,6 +13,7 @@ import { CustomersTransactionsBody } from './CustomersTransactionsBody'; import { CustomersTransactionsProvider } from './CustomersTransactionsProvider'; import { compose } from '@/utils'; +import { useCustomersTransactionsQuery } from './_utils'; /** * Customers transactions. @@ -22,11 +23,7 @@ function CustomersTransactions({ toggleCustomersTransactionsFilterDrawer, }) { // filter - const [filter, setFilter] = useState({ - fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), - filterByOption: 'with-transactions', - }); + const [filter, setFilter] = useCustomersTransactionsQuery(); const handleFilterSubmit = (filter) => { const _filter = { diff --git a/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsHeader.tsx b/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsHeader.tsx index a96527b4f..3f9104d73 100644 --- a/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsHeader.tsx @@ -1,7 +1,5 @@ // @ts-nocheck import React from 'react'; -import * as Yup from 'yup'; -import intl from 'react-intl-universal'; import moment from 'moment'; import styled from 'styled-components'; import { Tabs, Tab, Button, Intent } from '@blueprintjs/core'; @@ -15,6 +13,10 @@ import withCustomersTransactions from './withCustomersTransactions'; import withCustomersTransactionsActions from './withCustomersTransactionsActions'; import { compose, transformToForm } from '@/utils'; +import { + getCustomersTransactionsDefaultQuery, + getCustomersTransactionsQuerySchema, +} from './_utils'; /** * Customers transactions header. @@ -31,12 +33,8 @@ function CustomersTransactionsHeader({ toggleCustomersTransactionsFilterDrawer: toggleFilterDrawer, }) { // Default form values. - const defaultValues = { - ...pageFilter, - fromDate: moment().toDate(), - toDate: moment().toDate(), - customersIds: [], - }; + const defaultValues = getCustomersTransactionsDefaultQuery(); + // Initial form values. const initialValues = transformToForm( { @@ -49,13 +47,7 @@ function CustomersTransactionsHeader({ ); // Validation schema. - const validationSchema = Yup.object().shape({ - fromDate: Yup.date().required().label(intl.get('fromDate')), - toDate: Yup.date() - .min(Yup.ref('fromDate')) - .required() - .label(intl.get('toDate')), - }); + const validationSchema = getCustomersTransactionsQuerySchema(); // Handle form submit. const handleSubmit = (values, { setSubmitting }) => { diff --git a/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsHeaderGeneralPanel.tsx b/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsHeaderGeneralPanel.tsx index 40394e175..509a70cc1 100644 --- a/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsHeaderGeneralPanel.tsx +++ b/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsHeaderGeneralPanel.tsx @@ -1,15 +1,13 @@ // @ts-nocheck import React from 'react'; -import classNames from 'classnames'; -import { Field } from 'formik'; -import { Classes, FormGroup } from '@blueprintjs/core'; import FinancialStatementDateRange from '../FinancialStatementDateRange'; import FinancialStatementsFilter from '../FinancialStatementsFilter'; import { Row, Col, - ContactsMultiSelect, FormattedMessage as T, + CustomersMultiSelect, + FFormGroup, } from '@/components'; import { filterCustomersOptions } from '../constants'; @@ -51,24 +49,12 @@ function CustomersTransactionsHeaderGeneralPanelContent() { - - {({ form: { setFieldValue }, field: { value } }) => ( - } - className={classNames('form-group--select-list', Classes.FILL)} - > - { - const customersIds = customers.map( - (customer) => customer.id, - ); - setFieldValue('customersIds', customersIds); - }} - /> - - )} - + } + name={'customersIds'} + > + + diff --git a/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsProvider.tsx b/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsProvider.tsx index 59079c1ef..ef7d69954 100644 --- a/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsProvider.tsx +++ b/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/CustomersTransactionsProvider.tsx @@ -14,7 +14,7 @@ function CustomersTransactionsProvider({ filter, ...props }) { filter, ]); - // fetches the customers transactions. + // Fetches the customers transactions. const { data: customersTransactions, isFetching: isCustomersTransactionsFetching, diff --git a/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/_utils.ts b/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/_utils.ts new file mode 100644 index 000000000..ba9e02a8f --- /dev/null +++ b/packages/webapp/src/containers/FinancialStatements/CustomersTransactions/_utils.ts @@ -0,0 +1,48 @@ +// @ts-nocheck +import * as Yup from 'yup'; +import intl from 'react-intl-universal'; +import moment from 'moment'; +import { transformToForm } from '@/utils'; +import { castArray } from 'lodash'; +import { useMemo } from 'react'; +import { useAppQueryString } from '@/hooks'; + +export const getCustomersTransactionsQuerySchema = () => { + return Yup.object().shape({ + fromDate: Yup.date().required().label(intl.get('fromDate')), + toDate: Yup.date() + .min(Yup.ref('fromDate')) + .required() + .label(intl.get('toDate')), + }); +}; + +export const getCustomersTransactionsDefaultQuery = () => ({ + fromDate: moment().startOf('month').format('YYYY-MM-DD'), + toDate: moment().format('YYYY-MM-DD'), + customersIds: [], + filterByOption: 'with-transactions', +}); + +const parseCustomersTransactionsQuery = (query) => { + const defaultQuery = getCustomersTransactionsDefaultQuery(); + + const transformedQuery = { + ...defaultQuery, + ...transformToForm(query, defaultQuery), + }; + return { + ...transformedQuery, + customersIds: castArray(transformedQuery.customersIds), + }; +}; + +export const useCustomersTransactionsQuery = () => { + const [locationQuery, setLocationQuery] = useAppQueryString(); + + const query = useMemo( + () => parseCustomersTransactionsQuery(locationQuery), + [locationQuery], + ); + return [query, setLocationQuery]; +}; diff --git a/packages/webapp/src/containers/FinancialStatements/GeneralLedger/GeneralLedger.tsx b/packages/webapp/src/containers/FinancialStatements/GeneralLedger/GeneralLedger.tsx index 934f5c628..6f6047c9f 100644 --- a/packages/webapp/src/containers/FinancialStatements/GeneralLedger/GeneralLedger.tsx +++ b/packages/webapp/src/containers/FinancialStatements/GeneralLedger/GeneralLedger.tsx @@ -1,5 +1,5 @@ // @ts-nocheck -import React, { useCallback } from 'react'; +import React, { useCallback, useEffect } from 'react'; import moment from 'moment'; import GeneralLedgerHeader from './GeneralLedgerHeader'; @@ -41,10 +41,8 @@ function GeneralLedger({ ); // Hide the filter drawer once the page unmount. - React.useEffect( - () => () => { - toggleGeneralLedgerFilterDrawer(false); - }, + useEffect( + () => () => toggleGeneralLedgerFilterDrawer(false), [toggleGeneralLedgerFilterDrawer], ); diff --git a/packages/webapp/src/containers/FinancialStatements/GeneralLedger/GeneralLedgerHeader.tsx b/packages/webapp/src/containers/FinancialStatements/GeneralLedger/GeneralLedgerHeader.tsx index 8728bfa22..831c24f5f 100644 --- a/packages/webapp/src/containers/FinancialStatements/GeneralLedger/GeneralLedgerHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/GeneralLedger/GeneralLedgerHeader.tsx @@ -2,12 +2,14 @@ import React from 'react'; import moment from 'moment'; import styled from 'styled-components'; -import * as Yup from 'yup'; import { Formik, Form } from 'formik'; import { Tabs, Tab, Button, Intent } from '@blueprintjs/core'; import { FormattedMessage as T } from '@/components'; -import { getDefaultGeneralLedgerQuery } from './common'; +import { + getDefaultGeneralLedgerQuery, + getGeneralLedgerQuerySchema, +} from './common'; import { compose, transformToForm, saveInvoke } from '@/utils'; import FinancialStatementHeader from '../FinancialStatementHeader'; @@ -39,6 +41,7 @@ function GeneralLedgerHeader({ // Initial values. const initialValues = transformToForm( { + ...defaultValues, ...pageFilter, fromDate: moment(pageFilter.fromDate).toDate(), toDate: moment(pageFilter.toDate).toDate(), @@ -46,11 +49,8 @@ function GeneralLedgerHeader({ defaultValues, ); // Validation schema. - const validationSchema = Yup.object().shape({ - dateRange: Yup.string().optional(), - fromDate: Yup.date().required(), - toDate: Yup.date().min(Yup.ref('fromDate')).required(), - }); + const validationSchema = getGeneralLedgerQuerySchema(); + // Handle form submit. const handleSubmit = (values, { setSubmitting }) => { saveInvoke(onSubmitFilter, values); @@ -68,6 +68,7 @@ function GeneralLedgerHeader({ // Detarmines the feature whether is enabled. const { featureCan } = useFeatureCan(); + // Detarmine if the feature is enabled. const isBranchesFeatureCan = featureCan(Features.Branches); return ( diff --git a/packages/webapp/src/containers/FinancialStatements/GeneralLedger/common.tsx b/packages/webapp/src/containers/FinancialStatements/GeneralLedger/common.tsx index 491e7bffd..4f6c5a65c 100644 --- a/packages/webapp/src/containers/FinancialStatements/GeneralLedger/common.tsx +++ b/packages/webapp/src/containers/FinancialStatements/GeneralLedger/common.tsx @@ -2,6 +2,7 @@ import React from 'react'; import intl from 'react-intl-universal'; import moment from 'moment'; +import * as Yup from 'yup'; import { castArray } from 'lodash'; import { useAppQueryString } from '@/hooks'; @@ -26,15 +27,25 @@ export const filterAccountsOptions = [ /** * Retrieves the default general ledger query. */ -export const getDefaultGeneralLedgerQuery = () => { - return { - fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), - basis: 'accrual', - filterByOption: 'with-transactions', - branchesIds: [], - accountsIds: [], - }; +export const getDefaultGeneralLedgerQuery = () => ({ + fromDate: moment().startOf('month').format('YYYY-MM-DD'), + toDate: moment().format('YYYY-MM-DD'), + basis: 'accrual', + filterByOption: 'with-transactions', + branchesIds: [], + accountsIds: [], +}); + +/** + * Retrieves the validation schema of general ledger. + * @returns {Yup} + */ +export const getGeneralLedgerQuerySchema = () => { + return Yup.object().shape({ + dateRange: Yup.string().optional(), + fromDate: Yup.date().required(), + toDate: Yup.date().min(Yup.ref('fromDate')).required(), + }); }; /** diff --git a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsHeader.tsx b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsHeader.tsx index 1af6bc2a9..31821760c 100644 --- a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsHeader.tsx @@ -1,10 +1,9 @@ // @ts-nocheck import React from 'react'; -import * as Yup from 'yup'; + import moment from 'moment'; import { Formik, Form } from 'formik'; import { Tabs, Tab, Button, Intent } from '@blueprintjs/core'; -import intl from 'react-intl-universal'; import styled from 'styled-components'; import { FormattedMessage as T } from '@/components'; @@ -16,7 +15,10 @@ import InventoryItemDetailsHeaderDimensionsPanel from './InventoryItemDetailsHea import withInventoryItemDetails from './withInventoryItemDetails'; import withInventoryItemDetailsActions from './withInventoryItemDetailsActions'; -import { getInventoryItemDetailsDefaultQuery } from './utils2'; +import { + getInventoryItemDetailsDefaultQuery, + getInventoryItemDetailsQuerySchema, +} from './utils2'; import { compose, transformToForm } from '@/utils'; import { useFeatureCan } from '@/hooks/state'; import { Features } from '@/constants'; @@ -28,6 +30,7 @@ function InventoryItemDetailsHeader({ // #ownProps onSubmitFilter, pageFilter, + // #withInventoryItemDetails isFilterDrawerOpen, @@ -40,30 +43,29 @@ function InventoryItemDetailsHeader({ // Filter form initial values. const initialValues = transformToForm( { + ...defaultValues, ...pageFilter, fromDate: moment(pageFilter.fromDate).toDate(), toDate: moment(pageFilter.toDate).toDate(), }, defaultValues, ); + // Validation schema. - const validationSchema = Yup.object().shape({ - fromDate: Yup.date().required().label(intl.get('fromDate')), - toDate: Yup.date() - .min(Yup.ref('fromDate')) - .required() - .label(intl.get('toDate')), - }); + const validationSchema = getInventoryItemDetailsQuerySchema(); + // Handle form submit. const handleSubmit = (values, { setSubmitting }) => { onSubmitFilter(values); toggleFilterDrawer(false); setSubmitting(false); }; + // Handle drawer close action. const handleDrawerClose = () => { toggleFilterDrawer(false); }; + // Detarmines the given feature whether is enabled. const { featureCan } = useFeatureCan(); diff --git a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsHeaderDimensionsPanelProvider.tsx b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsHeaderDimensionsPanelProvider.tsx index d183f0b25..ef7bf3f2f 100644 --- a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsHeaderDimensionsPanelProvider.tsx +++ b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsHeaderDimensionsPanelProvider.tsx @@ -16,10 +16,10 @@ function InventoryItemDetailsHeaderDimensionsProvider({ ...props }) { // Features guard. const { featureCan } = useFeatureCan(); - // Detarmines whether the warehouses feature is accessiable. + // Detarmines whether the warehouses feature is accessible. const isWarehouseFeatureCan = featureCan(Features.Warehouses); - // Detarmines whether the branches feature is accessiable. + // Detarmines whether the branches feature is accessible. const isBranchesFeatureCan = featureCan(Features.Branches); // Fetches the warehouses list. diff --git a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsHeaderGeneralPanel.tsx b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsHeaderGeneralPanel.tsx index 9335ab79c..74edcbfa8 100644 --- a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsHeaderGeneralPanel.tsx +++ b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsHeaderGeneralPanel.tsx @@ -1,14 +1,12 @@ // @ts-nocheck import React from 'react'; -import { FormGroup, Classes } from '@blueprintjs/core'; -import { Field } from 'formik'; import { ItemsMultiSelect, Row, Col, FormattedMessage as T, + FFormGroup, } from '@/components'; -import classNames from 'classnames'; import FinancialStatementDateRange from '../FinancialStatementDateRange'; import { @@ -39,26 +37,9 @@ function InventoryItemDetailsHeaderGeneralPanelContent() { - - {({ - form: { setFieldValue }, - field: { value }, - meta: { error, touched }, - }) => ( - } - className={classNames('form-group--select-list', Classes.FILL)} - > - { - const itemsIds = items.map((item) => item.id); - setFieldValue('itemsIds', itemsIds); - }} - /> - - )} - + } name={'itemsIds'}> + + diff --git a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsTable.tsx b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsTable.tsx index 8171862f7..f8cd204cd 100644 --- a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsTable.tsx +++ b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/InventoryItemDetailsTable.tsx @@ -35,8 +35,8 @@ export function InventoryItemDetailsTable({ companyName={companyName} sheetType={intl.get('inventory_item_details')} loading={isInventoryItemDetailsLoading} - fromDate={query.from_date} - toDate={query.to_date} + fromDate={query.fromDate} + toDate={query.toDate} fullWidth={true} > ({ align: Align.Right, })); -/** - * columns mapper. - */ const columnsMapper = R.curry((data, index, column) => ({ id: column.key, key: column.key, diff --git a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/utils2.tsx b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/utils2.tsx index 345e84a95..4293cf610 100644 --- a/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/utils2.tsx +++ b/packages/webapp/src/containers/FinancialStatements/InventoryItemDetails/utils2.tsx @@ -2,6 +2,8 @@ import React from 'react'; import moment from 'moment'; import { castArray } from 'lodash'; +import * as Yup from 'yup'; +import intl from 'react-intl-universal'; import { useAppQueryString } from '@/hooks'; import { transformToForm } from '@/utils'; @@ -9,13 +11,26 @@ import { transformToForm } from '@/utils'; /** * Retrieves inventory item details default query. */ -export const getInventoryItemDetailsDefaultQuery = () => { - return { - fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), - warehousesIds: [], - branchesIds: [], - }; +export const getInventoryItemDetailsDefaultQuery = () => ({ + fromDate: moment().startOf('month').format('YYYY-MM-DD'), + toDate: moment().format('YYYY-MM-DD'), + itemsIds: [], + warehousesIds: [], + branchesIds: [], +}); + +/** + * Retrieves inventory item details query schema. + * @returns {Yup} + */ +export const getInventoryItemDetailsQuerySchema = () => { + return Yup.object().shape({ + fromDate: Yup.date().required().label(intl.get('fromDate')), + toDate: Yup.date() + .min(Yup.ref('fromDate')) + .required() + .label(intl.get('toDate')), + }); }; /** @@ -32,7 +47,8 @@ const parseInventoryItemDetailsQuery = (locationQuery) => { return { ...transformed, - // Ensures the branches/warehouses ids is always array. + // Ensure the branches, warehouses and items ids is always array. + itemsIds: castArray(transformed.itemsIds), branchesIds: castArray(transformed.branchesIds), warehousesIds: castArray(transformed.warehousesIds), }; diff --git a/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationHeader.tsx b/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationHeader.tsx index 09d29c7d9..1dd9d86c4 100644 --- a/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationHeader.tsx @@ -1,6 +1,5 @@ // @ts-nocheck import React from 'react'; -import * as Yup from 'yup'; import moment from 'moment'; import styled from 'styled-components'; import { Formik, Form } from 'formik'; @@ -17,6 +16,10 @@ import withInventoryValuationActions from './withInventoryValuationActions'; import { compose, transformToForm } from '@/utils'; import { useFeatureCan } from '@/hooks/state'; import { Features } from '@/constants'; +import { + getInventoryValuationQuery, + getInventoryValuationQuerySchema, +} from './utils'; /** * inventory valuation header. @@ -33,25 +36,17 @@ function InventoryValuationHeader({ toggleInventoryValuationFilterDrawer, }) { // Form validation schema. - const validationSchema = Yup.object().shape({ - asDate: Yup.date().required().label('asDate'), - }); + const validationSchema = getInventoryValuationQuerySchema(); + const defaultQuery = getInventoryValuationQuery(); - // Default values. - const defaultValues = { - ...pageFilter, - asDate: moment().toDate(), - itemsIds: [], - warehousesIds: [], - }; // Initial values. const initialValues = transformToForm( { - ...defaultValues, + ...defaultQuery, ...pageFilter, asDate: moment(pageFilter.asDate).toDate(), }, - defaultValues, + defaultQuery, ); // Handle the form of header submit. @@ -71,6 +66,7 @@ function InventoryValuationHeader({ // Detarmines the given feature whether is enabled. const { featureCan } = useFeatureCan(); + // Detarmine if these feature are enabled. const isBranchesFeatureCan = featureCan(Features.Branches); const isWarehousesFeatureCan = featureCan(Features.Warehouses); diff --git a/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationHeaderDimensionsPanelProvider.tsx b/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationHeaderDimensionsPanelProvider.tsx index b42623ab8..b39557749 100644 --- a/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationHeaderDimensionsPanelProvider.tsx +++ b/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationHeaderDimensionsPanelProvider.tsx @@ -16,10 +16,10 @@ function InventoryValuationHeaderDimensionsProvider({ ...props }) { // Features guard. const { featureCan } = useFeatureCan(); - // Detarmines whether the warehouses feature is accessiable. + // Detarmines whether the warehouses feature is accessible. const isWarehouseFeatureCan = featureCan(Features.Warehouses); - // Detarmines whether the branches feature is accessiable. + // Detarmines whether the branches feature is accessible. const isBranchFeatureCan = featureCan(Features.Branches); // Fetches the warehouses list. diff --git a/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationHeaderGeneralPanel.tsx b/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationHeaderGeneralPanel.tsx index ef343192e..3981a5577 100644 --- a/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationHeaderGeneralPanel.tsx +++ b/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationHeaderGeneralPanel.tsx @@ -2,8 +2,7 @@ import React from 'react'; import { FastField, Field } from 'formik'; import { DateInput } from '@blueprintjs/datetime'; -import { FormGroup, Position, Classes } from '@blueprintjs/core'; -import classNames from 'classnames'; +import { FormGroup, Position } from '@blueprintjs/core'; import { FormattedMessage as T, @@ -11,9 +10,9 @@ import { Row, Col, FieldHint, + FFormGroup, } from '@/components'; import { filterInventoryValuationOptions } from '../constants'; - import { momentFormatter, tansformDateValue, @@ -83,22 +82,9 @@ function InventoryValuationHeaderGeneralPanelContent() { - - {({ form: { setFieldValue } }) => ( - } - className={classNames('form-group--select-list', Classes.FILL)} - > - { - const itemsIds = items.map((item) => item.id); - setFieldValue('itemsIds', itemsIds); - }} - /> - - )} - + }> + + diff --git a/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationTable.tsx b/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationTable.tsx index 009832ebb..bada2a466 100644 --- a/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationTable.tsx +++ b/packages/webapp/src/containers/FinancialStatements/InventoryValuation/InventoryValuationTable.tsx @@ -19,7 +19,7 @@ export default function InventoryValuationTable({ }) { // inventory valuation context. const { - inventoryValuation: { tableRows }, + inventoryValuation: { tableRows, query }, isLoading, } = useInventoryValuationContext(); @@ -30,7 +30,7 @@ export default function InventoryValuationTable({ { - return { - asDate: moment().endOf('day').format('YYYY-MM-DD'), - filterByOption: 'with-transactions', - - branchesIds: [], - warehousesIds: [], - }; +export const getInventoryValuationQuerySchema = () => { + return Yup.object().shape({ + asDate: Yup.date().required().label('asDate'), + }); }; /** - * Parses inventory valiation location query to report query. + * Retrieves the inventory valuation sheet default query. + */ +export const getInventoryValuationQuery = () => ({ + asDate: moment().format('YYYY-MM-DD'), + filterByOption: 'with-transactions', + itemsIds: [], + branchesIds: [], + warehousesIds: [], +}); + +/** + * Parses inventory valuation location query to report query. */ const parseInventoryValuationQuery = (locationQuery) => { const defaultQuery = getInventoryValuationQuery(); @@ -33,6 +41,7 @@ const parseInventoryValuationQuery = (locationQuery) => { ...transformed, // Ensures the branches/warehouses ids is always array. + itemsIds: castArray(transformed.itemsIds), branchesIds: castArray(transformed.branchesIds), warehousesIds: castArray(transformed.warehousesIds), }; diff --git a/packages/webapp/src/containers/FinancialStatements/Journal/utils.tsx b/packages/webapp/src/containers/FinancialStatements/Journal/utils.tsx index bafa46384..f65f027ed 100644 --- a/packages/webapp/src/containers/FinancialStatements/Journal/utils.tsx +++ b/packages/webapp/src/containers/FinancialStatements/Journal/utils.tsx @@ -11,17 +11,16 @@ import { transformToForm } from '@/utils'; */ export const getDefaultJournalQuery = () => { return { - fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), + fromDate: moment().startOf('month').format('YYYY-MM-DD'), + toDate: moment().format('YYYY-MM-DD'), basis: 'accrual', }; }; - /** * Parses balance sheet query. */ - const parseJournalQuery = (locationQuery) => { +const parseJournalQuery = (locationQuery) => { const defaultQuery = getDefaultJournalQuery(); return { diff --git a/packages/webapp/src/containers/FinancialStatements/ProfitLossSheet/ProfitLossSheetTable.tsx b/packages/webapp/src/containers/FinancialStatements/ProfitLossSheet/ProfitLossSheetTable.tsx index 0573e8e1a..933408534 100644 --- a/packages/webapp/src/containers/FinancialStatements/ProfitLossSheet/ProfitLossSheetTable.tsx +++ b/packages/webapp/src/containers/FinancialStatements/ProfitLossSheet/ProfitLossSheetTable.tsx @@ -23,7 +23,7 @@ export default function ProfitLossSheetTable({ } = useProfitLossSheetContext(); // Retrieves the profit/loss table columns. - const tableColumns = useProfitLossSheetColumns(); + const columns = useProfitLossSheetColumns(); // Retrieve default expanded rows of balance sheet. const expandedRows = React.useMemo( @@ -40,7 +40,7 @@ export default function ProfitLossSheetTable({ basis={query.basis} > ({ basis: 'cash', fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), + toDate: moment().format('YYYY-MM-DD'), displayColumnsType: 'total', filterByOption: 'with-transactions', @@ -146,7 +146,7 @@ export const handlePreviousYearPercentageCheckboxChange = R.curry( ); /** - * Handles previous period change amout checkbox change. + * Handles previous period change amount checkbox change. */ export const handlePreviousPeriodChangeCheckboxChange = R.curry( (form, event) => { diff --git a/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItems.tsx b/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItems.tsx index 485922d87..7fa14d85d 100644 --- a/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItems.tsx +++ b/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItems.tsx @@ -1,5 +1,5 @@ // @ts-nocheck -import React, { useEffect, useState, useCallback } from 'react'; +import React, { useEffect, useCallback } from 'react'; import moment from 'moment'; import PurchasesByItemsActionsBar from './PurchasesByItemsActionsBar'; @@ -9,7 +9,7 @@ import { FinancialStatement, DashboardPageContent } from '@/components'; import { PurchasesByItemsLoadingBar } from './components'; import { PurchasesByItemsProvider } from './PurchasesByItemsProvider'; import { PurchasesByItemsBody } from './PurchasesByItemsBody'; -import { getDefaultPurchasesByItemsQuery } from './utils'; +import { usePurchasesByItemsQuery } from './utils'; import { compose } from '@/utils'; import withPurchasesByItemsActions from './withPurchasesByItemsActions'; @@ -21,9 +21,7 @@ function PurchasesByItems({ // #withPurchasesByItemsActions togglePurchasesByItemsFilterDrawer, }) { - const [filter, setFilter] = useState({ - ...getDefaultPurchasesByItemsQuery(), - }); + const { query, setLocationQuery } = usePurchasesByItemsQuery(); // Handle filter form submit. const handleFilterSubmit = useCallback( @@ -33,11 +31,10 @@ function PurchasesByItems({ fromDate: moment(filter.fromDate).format('YYYY-MM-DD'), toDate: moment(filter.toDate).format('YYYY-MM-DD'), }; - setFilter(parsedFilter); + setLocationQuery(parsedFilter); }, - [setFilter], + [setLocationQuery], ); - // Handle number format form submit. const handleNumberFormatSubmit = (numberFormat) => { setFilter({ @@ -45,7 +42,6 @@ function PurchasesByItems({ numberFormat, }); }; - // Hide the filter drawer once the page unmount. useEffect( () => () => { @@ -55,9 +51,9 @@ function PurchasesByItems({ ); return ( - + @@ -65,7 +61,7 @@ function PurchasesByItems({ diff --git a/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsGeneralPanel.tsx b/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsGeneralPanel.tsx index c9bd572b3..859f4a3dd 100644 --- a/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsGeneralPanel.tsx +++ b/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsGeneralPanel.tsx @@ -1,14 +1,12 @@ // @ts-nocheck import React from 'react'; -import { FormGroup, Classes } from '@blueprintjs/core'; -import { Field } from 'formik'; import { Row, Col, FormattedMessage as T, ItemsMultiSelect, + FFormGroup, } from '@/components'; -import classNames from 'classnames'; import FinancialStatementDateRange from '../FinancialStatementDateRange'; import FinancialStatementsFilter from '../FinancialStatementsFilter'; import { filterItemsOptions } from '../constants'; @@ -51,22 +49,9 @@ function PurchasesByItemsGeneralPanelContent() { - - {({ form: { setFieldValue } }) => ( - } - className={classNames('form-group--select-list', Classes.FILL)} - > - { - const itemsIds = items.map((item) => item.id); - setFieldValue('itemsIds', itemsIds); - }} - /> - - )} - + }> + + diff --git a/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsHeader.tsx b/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsHeader.tsx index 5ea0f6da8..935a6eaa6 100644 --- a/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/PurchasesByItemsHeader.tsx @@ -1,14 +1,11 @@ // @ts-nocheck import React from 'react'; -import * as Yup from 'yup'; import moment from 'moment'; -import intl from 'react-intl-universal'; -import styled from 'styled-components'; +import styled from 'styled-components'; import { Formik, Form } from 'formik'; import { Tabs, Tab, Button, Intent } from '@blueprintjs/core'; import { FormattedMessage as T } from '@/components'; - import FinancialStatementHeader from '@/containers/FinancialStatements/FinancialStatementHeader'; import PurchasesByItemsGeneralPanel from './PurchasesByItemsGeneralPanel'; @@ -16,6 +13,10 @@ import withPurchasesByItems from './withPurchasesByItems'; import withPurchasesByItemsActions from './withPurchasesByItemsActions'; import { compose, transformToForm } from '@/utils'; +import { + getDefaultPurchasesByItemsQuery, + getPurchasesByItemsQuerySchema, +} from './utils'; /** * Purchases by items header. @@ -32,38 +33,26 @@ function PurchasesByItemsHeader({ togglePurchasesByItemsFilterDrawer, }) { // Form validation schema. - const validationSchema = Yup.object().shape({ - fromDate: Yup.date().required().label(intl.get('from_date')), - toDate: Yup.date() - .min(Yup.ref('fromDate')) - .required() - .label(intl.get('to_date')), - }); - // Default form values. - const defaultValues = { - ...pageFilter, - fromDate: moment().toDate(), - toDate: moment().toDate(), - itemsIds: [], - }; + const validationSchema = getPurchasesByItemsQuerySchema(); + + const defaultQuery = getDefaultPurchasesByItemsQuery(); + // Initial form values. const initialValues = transformToForm( { - ...defaultValues, + ...defaultQuery, ...pageFilter, fromDate: moment(pageFilter.fromDate).toDate(), toDate: moment(pageFilter.toDate).toDate(), }, - defaultValues, + defaultQuery, ); - // Handle form submit. const handleSubmit = (values, { setSubmitting }) => { onSubmitFilter(values); setSubmitting(false); togglePurchasesByItemsFilterDrawer(false); }; - // Handle drawer close & cancel action. const handleDrawerClose = () => { togglePurchasesByItemsFilterDrawer(false); diff --git a/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/utils.tsx b/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/utils.tsx index b4309f30c..51a2684c3 100644 --- a/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/utils.tsx +++ b/packages/webapp/src/containers/FinancialStatements/PurchasesByItems/utils.tsx @@ -1,11 +1,62 @@ // @ts-nocheck +import React from 'react'; import moment from 'moment'; +import * as Yup from 'yup'; +import intl from 'react-intl-universal'; +import { useAppQueryString } from '@/hooks'; +import { transformToForm } from '@/utils'; +import { castArray } from 'lodash'; +/** + * Retrieves the purchases by items query. + */ +export const getDefaultPurchasesByItemsQuery = () => ({ + fromDate: moment().startOf('month').format('YYYY-MM-DD'), + toDate: moment().format('YYYY-MM-DD'), + filterByOption: 'with-transactions', + itemsIds: [], +}); -export const getDefaultPurchasesByItemsQuery = () => { +/** + * Retrieves the purchases by items query validation schema. + * @returns {Yup} + */ +export const getPurchasesByItemsQuerySchema = () => { + return Yup.object().shape({ + fromDate: Yup.date().required().label(intl.get('from_date')), + toDate: Yup.date() + .min(Yup.ref('fromDate')) + .required() + .label(intl.get('to_date')), + }); +}; + +/** + * Parses the purchases by items query. + */ +const parsePurchasesByItemsQuery = (locationQuery) => { + const defaultQuery = getDefaultPurchasesByItemsQuery(); + + const transformed = { + ...defaultQuery, + ...transformToForm(locationQuery, defaultQuery), + }; return { - fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), - filterByOption: 'with-transactions', - } -} \ No newline at end of file + ...transformed, + itemsIds: castArray(transformed.itemsIds), + }; +}; + +/** + * Purchases by items query state. + */ +export const usePurchasesByItemsQuery = () => { + // Retrieves location query. + const [locationQuery, setLocationQuery] = useAppQueryString(); + + const query = React.useMemo( + () => parsePurchasesByItemsQuery(locationQuery), + [locationQuery], + ); + return { query, locationQuery, setLocationQuery }; +}; diff --git a/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItems.tsx b/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItems.tsx index b094d1b69..3382b3072 100644 --- a/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItems.tsx +++ b/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItems.tsx @@ -1,5 +1,5 @@ // @ts-nocheck -import React, { useEffect, useState, useCallback } from 'react'; +import React, { useEffect, useCallback } from 'react'; import moment from 'moment'; import { SalesByItemsBody } from './SalesByItemsBody'; @@ -11,7 +11,7 @@ import SalesByItemsHeader from './SalesByItemsHeader'; import withSalesByItemsActions from './withSalesByItemsActions'; -import { getDefaultSalesByItemsQuery } from './utils'; +import { useSalesByItemsQuery } from './utils'; import { compose } from '@/utils'; /** @@ -21,9 +21,7 @@ function SalesByItems({ // #withSellsByItemsActions toggleSalesByItemsFilterDrawer, }) { - const [filter, setFilter] = useState({ - ...getDefaultSalesByItemsQuery(), - }); + const { query, setLocationQuery } = useSalesByItemsQuery(); // Handle filter form submit. const handleFilterSubmit = useCallback( @@ -33,30 +31,28 @@ function SalesByItems({ fromDate: moment(filter.fromDate).format('YYYY-MM-DD'), toDate: moment(filter.toDate).format('YYYY-MM-DD'), }; - setFilter(parsedFilter); + setLocationQuery(parsedFilter); }, - [setFilter], + [setLocationQuery], ); // Handle number format form submit. const handleNumberFormatSubmit = (numberFormat) => { - setFilter({ + setLocationQuery({ ...filter, numberFormat, }); }; // Hide the filter drawer once the page unmount. useEffect( - () => () => { - toggleSalesByItemsFilterDrawer(false); - }, + () => () => toggleSalesByItemsFilterDrawer(false), [toggleSalesByItemsFilterDrawer], ); return ( - + @@ -64,7 +60,7 @@ function SalesByItems({ diff --git a/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemsHeader.tsx b/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemsHeader.tsx index 0fc4fa1f6..f0c024b04 100644 --- a/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemsHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemsHeader.tsx @@ -1,8 +1,6 @@ // @ts-nocheck import React from 'react'; -import * as Yup from 'yup'; import moment from 'moment'; -import intl from 'react-intl-universal'; import styled from 'styled-components'; import { Formik, Form } from 'formik'; import { Tabs, Tab, Button, Intent } from '@blueprintjs/core'; @@ -14,7 +12,11 @@ import SalesByItemsHeaderGeneralPanel from './SalesByItemsHeaderGeneralPanel'; import withSalesByItems from './withSalesByItems'; import withSalesByItemsActions from './withSalesByItemsActions'; -import { compose } from '@/utils'; +import { compose, transformToForm } from '@/utils'; +import { + getDefaultSalesByItemsQuery, + getSalesByItemsQueryShema, +} from './utils'; /** * Sales by items header. @@ -31,21 +33,22 @@ function SalesByItemsHeader({ toggleSalesByItemsFilterDrawer, }) { // Form validation schema. - const validationSchema = Yup.object().shape({ - fromDate: Yup.date().required().label(intl.get('from_date')), - toDate: Yup.date() - .min(Yup.ref('fromDate')) - .required() - .label(intl.get('to_date')), - }); + const validationSchema = getSalesByItemsQueryShema(); + + const defaultQuery = getDefaultSalesByItemsQuery(); // Initial values. - const initialValues = { - ...pageFilter, - fromDate: moment(pageFilter.fromDate).toDate(), - toDate: moment(pageFilter.toDate).toDate(), - }; + const initialValues = transformToForm( + { + ...defaultQuery, + ...pageFilter, + fromDate: moment(pageFilter.fromDate).toDate(), + toDate: moment(pageFilter.toDate).toDate(), + }, + defaultQuery, + ); + // Handle the form submitting. const handleSubmit = (values, { setSubmitting }) => { onSubmitFilter(values); setSubmitting(false); diff --git a/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemsHeaderGeneralPanel.tsx b/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemsHeaderGeneralPanel.tsx index 46f2f6416..01d267fbd 100644 --- a/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemsHeaderGeneralPanel.tsx +++ b/packages/webapp/src/containers/FinancialStatements/SalesByItems/SalesByItemsHeaderGeneralPanel.tsx @@ -1,13 +1,15 @@ // @ts-nocheck import React from 'react'; -import { FormGroup, Classes } from '@blueprintjs/core'; -import { Field } from 'formik'; -import classNames from 'classnames'; - -import { filterItemsOptions } from '../constants'; -import { Row, Col, ItemsMultiSelect, FormattedMessage as T } from '@/components'; +import { + Row, + Col, + ItemsMultiSelect, + FormattedMessage as T, + FFormGroup, +} from '@/components'; import FinancialStatementDateRange from '../FinancialStatementDateRange'; import FinancialStatementsFilter from '../FinancialStatementsFilter'; +import { filterItemsOptions } from '../constants'; import { SalesByItemGeneralPanelProvider, useSalesByItemsGeneralPanelContext, @@ -46,22 +48,9 @@ function SalesByItemsHeaderGeneralPanelContent() { - - {({ form: { setFieldValue }, field: { value } }) => ( - } - className={classNames('form-group--select-list', Classes.FILL)} - > - { - const itemsIds = items.map((item) => item.id); - setFieldValue('itemsIds', itemsIds); - }} - /> - - )} - + } name={'itemsIds'}> + + diff --git a/packages/webapp/src/containers/FinancialStatements/SalesByItems/utils.tsx b/packages/webapp/src/containers/FinancialStatements/SalesByItems/utils.tsx index 102b157b9..b56536f33 100644 --- a/packages/webapp/src/containers/FinancialStatements/SalesByItems/utils.tsx +++ b/packages/webapp/src/containers/FinancialStatements/SalesByItems/utils.tsx @@ -1,10 +1,63 @@ // @ts-nocheck +import React from 'react'; import moment from 'moment'; +import * as Yup from 'yup'; +import intl from 'react-intl-universal'; +import { castArray } from 'lodash'; +import { useAppQueryString } from '@/hooks'; +import { transformToForm } from '@/utils'; -export const getDefaultSalesByItemsQuery = () => { +/** + * Retrieves the validation schema. + * @returns {Yup} + */ +export const getSalesByItemsQueryShema = () => { + return Yup.object().shape({ + fromDate: Yup.date().required().label(intl.get('from_date')), + toDate: Yup.date() + .min(Yup.ref('fromDate')) + .required() + .label(intl.get('to_date')), + }); +}; + +/** + * Retrieves the default query. + */ +export const getDefaultSalesByItemsQuery = () => ({ + fromDate: moment().startOf('month').format('YYYY-MM-DD'), + toDate: moment().format('YYYY-MM-DD'), + filterByOption: 'with-transactions', + itemsIds: [], +}); + +/** + * Parses sales by items query of browser location. + */ +const parseSalesByItemsQuery = (locationQuery) => { + const defaultQuery = getDefaultSalesByItemsQuery(); + + const transformed = { + ...defaultQuery, + ...transformToForm(locationQuery, defaultQuery), + }; return { - fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), - filterByOption: 'with-transactions', + ...transformed, + itemsIds: castArray(transformed.itemsIds), }; }; + +/** + * Sales by items query state. + */ +export const useSalesByItemsQuery = () => { + // Retrieves location query. + const [locationQuery, setLocationQuery] = useAppQueryString(); + + // Merges the default filter query with location URL query. + const query = React.useMemo( + () => parseSalesByItemsQuery(locationQuery), + [locationQuery], + ); + return { query, locationQuery, setLocationQuery }; +}; diff --git a/packages/webapp/src/containers/FinancialStatements/TrialBalanceSheet/utils.tsx b/packages/webapp/src/containers/FinancialStatements/TrialBalanceSheet/utils.tsx index 6bbec6db7..62be9afa8 100644 --- a/packages/webapp/src/containers/FinancialStatements/TrialBalanceSheet/utils.tsx +++ b/packages/webapp/src/containers/FinancialStatements/TrialBalanceSheet/utils.tsx @@ -12,7 +12,7 @@ import { transformToForm } from '@/utils'; export function getDefaultTrialBalanceQuery() { return { fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), + toDate: moment().format('YYYY-MM-DD'), basis: 'accrual', filterByOption: 'with-transactions', branchesIds: [], diff --git a/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummary.tsx b/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummary.tsx index 85ee52a96..dcf4e2486 100644 --- a/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummary.tsx +++ b/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummary.tsx @@ -13,7 +13,7 @@ import { VendorBalanceSummaryBody } from './VendorsBalanceSummaryBody'; import withVendorsBalanceSummaryActions from './withVendorsBalanceSummaryActions'; -import { getDefaultVendorsBalanceQuery } from './utils'; +import { useVendorsBalanceSummaryQuery } from './utils'; import { compose } from '@/utils'; /** @@ -23,9 +23,7 @@ function VendorsBalanceSummary({ // #withVendorsBalanceSummaryActions toggleVendorSummaryFilterDrawer, }) { - const [filter, setFilter] = useState({ - ...getDefaultVendorsBalanceQuery(), - }); + const { query, setLocationQuery } = useVendorsBalanceSummaryQuery(); // Handle refetch vendors balance summary. const handleFilterSubmit = (filter) => { @@ -33,28 +31,26 @@ function VendorsBalanceSummary({ ...filter, asDate: moment(filter.asDate).format('YYYY-MM-DD'), }; - setFilter(_filter); + setLocationQuery(_filter); }; // Handle number format submit. const handleNumberFormatSubmit = (format) => { - setFilter({ + setLocationQuery({ ...filter, numberFormat: format, }); }; useEffect( - () => () => { - toggleVendorSummaryFilterDrawer(false); - }, + () => () => toggleVendorSummaryFilterDrawer(false), [toggleVendorSummaryFilterDrawer], ); return ( - + @@ -62,7 +58,7 @@ function VendorsBalanceSummary({ diff --git a/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryHeader.tsx b/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryHeader.tsx index c102596e8..c5aef9f42 100644 --- a/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryHeader.tsx @@ -1,6 +1,6 @@ // @ts-nocheck import React from 'react'; -import * as Yup from 'yup'; + import moment from 'moment'; import styled from 'styled-components'; import { Formik, Form } from 'formik'; @@ -13,6 +13,7 @@ import FinancialStatementHeader from '../FinancialStatementHeader'; import VendorsBalanceSummaryHeaderGeneral from './VendorsBalanceSummaryHeaderGeneral'; import withVendorsBalanceSummary from './withVendorsBalanceSummary'; import withVendorsBalanceSummaryActions from './withVendorsBalanceSummaryActions'; +import { getVendorsBalanceQuerySchema } from './utils'; /** * Vendors balance summary drawer header. @@ -28,10 +29,8 @@ function VendorsBalanceSummaryHeader({ //#withVendorsBalanceSummaryActions toggleVendorSummaryFilterDrawer, }) { - // validation schema. - const validationSchema = Yup.object().shape({ - asDate: Yup.date().required().label('asDate'), - }); + // Validation schema. + const validationSchema = getVendorsBalanceQuerySchema(); // filter form initial values. const defaultValues = { @@ -80,6 +79,7 @@ function VendorsBalanceSummaryHeader({ panel={} /> +
diff --git a/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryTable.tsx b/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryTable.tsx index 9a57d5d40..6f7362449 100644 --- a/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryTable.tsx +++ b/packages/webapp/src/containers/FinancialStatements/VendorsBalanceSummary/VendorsBalanceSummaryTable.tsx @@ -9,7 +9,6 @@ import { tableRowTypesToClassnames } from '@/utils'; import { useVendorsBalanceColumns } from './components'; import { useVendorsBalanceSummaryContext } from './VendorsBalanceSummaryProvider'; - /** * Vendors balance summary table. */ @@ -18,7 +17,7 @@ export default function VendorsBalanceSummaryTable({ organizationName, }) { const { - VendorBalanceSummary: { table }, + VendorBalanceSummary: { table, query }, } = useVendorsBalanceSummaryContext(); // vendors balance summary columns. @@ -28,7 +27,7 @@ export default function VendorsBalanceSummaryTable({ { return { asDate: moment().endOf('day').format('YYYY-MM-DD'), filterByOption: 'with-transactions', + vendorsIds: [], }; -} \ No newline at end of file +}; + +export const getVendorsBalanceQuerySchema = () => { + return Yup.object().shape({ + asDate: Yup.date().required().label('asDate'), + }); +}; + +export const parseVendorsBalanceSummaryQuery = (locationQuery) => { + const defaultQuery = getDefaultVendorsBalanceQuery(); + + const transformed = { + ...defaultQuery, + ...transformToForm(locationQuery, defaultQuery), + }; + return { + ...transformed, + vendorsIds: castArray(transformed.vendorsIds), + }; +}; + +export const useVendorsBalanceSummaryQuery = () => { + const [locationQuery, setLocationQuery] = useAppQueryString(); + + const query = useMemo( + () => parseVendorsBalanceSummaryQuery(locationQuery), + [locationQuery], + ); + return { query, locationQuery, setLocationQuery }; +}; diff --git a/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactions.tsx b/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactions.tsx index c55a2e8fe..69cb6d506 100644 --- a/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactions.tsx +++ b/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactions.tsx @@ -13,6 +13,7 @@ import VendorsTransactionsActionsBar from './VendorsTransactionsActionsBar'; import withVendorsTransactionsActions from './withVendorsTransactionsActions'; import { compose } from '@/utils'; +import { useVendorsTransactionsQuery } from './_utils'; /** * Vendors transactions. @@ -22,11 +23,7 @@ function VendorsTransactions({ toggleVendorsTransactionsFilterDrawer, }) { // filter - const [filter, setFilter] = useState({ - fromDate: moment().startOf('year').format('YYYY-MM-DD'), - toDate: moment().endOf('year').format('YYYY-MM-DD'), - filterByOption: 'with-transactions', - }); + const [filter, setFilter] = useVendorsTransactionsQuery(); const handleFilterSubmit = (filter) => { const _filter = { diff --git a/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsHeader.tsx b/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsHeader.tsx index a61c5119e..df32211c0 100644 --- a/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsHeader.tsx +++ b/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsHeader.tsx @@ -1,8 +1,7 @@ // @ts-nocheck import React from 'react'; -import * as Yup from 'yup'; + import moment from 'moment'; -import intl from 'react-intl-universal'; import { Formik, Form } from 'formik'; import { Tabs, Tab, Button, Intent } from '@blueprintjs/core'; import { FormattedMessage as T } from '@/components'; @@ -14,11 +13,14 @@ import withVendorsTransaction from './withVendorsTransaction'; import withVendorsTransactionsActions from './withVendorsTransactionsActions'; import { compose, transformToForm } from '@/utils'; +import { + getVendorTransactionsQuerySchema, + getVendorsTransactionsDefaultQuery, +} from './_utils'; /** * Vendors transactions header. */ - function VendorsTransactionsHeader({ // #ownProps onSubmitFilter, @@ -31,12 +33,7 @@ function VendorsTransactionsHeader({ toggleVendorsTransactionsFilterDrawer: toggleFilterDrawer, }) { // Default form values. - const defaultValues = { - ...pageFilter, - fromDate: moment().toDate(), - toDate: moment().toDate(), - vendorsIds: [], - }; + const defaultValues = getVendorsTransactionsDefaultQuery(); // Initial form values. const initialValues = transformToForm( @@ -48,15 +45,8 @@ function VendorsTransactionsHeader({ }, defaultValues, ); - // Validation schema. - const validationSchema = Yup.object().shape({ - fromDate: Yup.date().required().label(intl.get('fromDate')), - toDate: Yup.date() - .min(Yup.ref('fromDate')) - .required() - .label(intl.get('toDate')), - }); + const validationSchema = getVendorTransactionsQuerySchema(); // Handle form submit. const handleSubmit = (values, { setSubmitting }) => { @@ -64,7 +54,6 @@ function VendorsTransactionsHeader({ toggleFilterDrawer(false); setSubmitting(false); }; - // Handle drawer close action. const handleDrawerClose = () => { toggleFilterDrawer(false); diff --git a/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsHeaderGeneralPanel.tsx b/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsHeaderGeneralPanel.tsx index ab4db23ab..c6ef6eb51 100644 --- a/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsHeaderGeneralPanel.tsx +++ b/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/VendorsTransactionsHeaderGeneralPanel.tsx @@ -1,8 +1,5 @@ // @ts-nocheck import React from 'react'; -import { Field } from 'formik'; -import { Classes, FormGroup } from '@blueprintjs/core'; -import classNames from 'classnames'; import FinancialStatementDateRange from '../FinancialStatementDateRange'; import FinancialStatementsFilter from '../FinancialStatementsFilter'; @@ -10,8 +7,9 @@ import FinancialStatementsFilter from '../FinancialStatementsFilter'; import { Row, Col, - ContactsMultiSelect, FormattedMessage as T, + FFormGroup, + VendorsMultiSelect, } from '@/components'; import { filterVendorsOptions } from '../constants'; @@ -53,22 +51,9 @@ function VendorsTransactionsHeaderGeneralPanelContent() { - - {({ form: { setFieldValue }, field: { value } }) => ( - } - className={classNames('form-group--select-list', Classes.FILL)} - > - { - const vendorsIds = vendors.map((customer) => customer.id); - setFieldValue('vendorsIds', vendorsIds); - }} - /> - - )} - + } name={'vendorsIds'}> + + diff --git a/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/_utils.ts b/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/_utils.ts new file mode 100644 index 000000000..fc2cd02d8 --- /dev/null +++ b/packages/webapp/src/containers/FinancialStatements/VendorsTransactions/_utils.ts @@ -0,0 +1,57 @@ +// @ts-nocheck +import * as Yup from 'yup'; +import intl from 'react-intl-universal'; +import moment from 'moment'; +import { useMemo } from 'react'; +import { transformToForm } from '@/utils'; +import { useAppQueryString } from '@/hooks'; + +/** + * The validation schema of vendors transactions. + */ +export const getVendorTransactionsQuerySchema = () => { + return Yup.object().shape({ + fromDate: Yup.date().required().label(intl.get('fromDate')), + toDate: Yup.date() + .min(Yup.ref('fromDate')) + .required() + .label(intl.get('toDate')), + }); +}; + +/** + * Retrieves the default query of vendors transactions. + */ +export const getVendorsTransactionsDefaultQuery = () => ({ + fromDate: moment().startOf('month').format('YYYY-MM-DD'), + toDate: moment().format('YYYY-MM-DD'), + vendorsIds: [], +}); + +/** + * Parses the query of vendors transactions. + */ +const parseVendorsTransactionsQuery = (query) => { + const defaultQuery = getVendorsTransactionsDefaultQuery(); + const transformed = { + ...defaultQuery, + ...transformToForm(query, defaultQuery), + }; + return { + ...transformed, + vendorsIds: transformed.vendorsIds ? transformed.vendorsIds : [], + }; +}; + +/** + * Retrieves the query of vendors transactions. + */ +export const useVendorsTransactionsQuery = () => { + const [locationQuery, setLocationQuery] = useAppQueryString(); + + const query = useMemo( + () => parseVendorsTransactionsQuery(locationQuery), + [locationQuery], + ); + return [query, setLocationQuery]; +}; diff --git a/packages/webapp/src/containers/Projects/components/ProjectSuggestField.tsx b/packages/webapp/src/containers/Projects/components/ProjectSuggestField.tsx index 216606a5f..071e0ac41 100644 --- a/packages/webapp/src/containers/Projects/components/ProjectSuggestField.tsx +++ b/packages/webapp/src/containers/Projects/components/ProjectSuggestField.tsx @@ -128,10 +128,10 @@ export function ProjectSuggestField({ } const AvatarSelect = ({ text }) => { - return {firstLettersArgs(text?.name)}; + return {firstLettersArgs(text?.name)}; }; -const AvaterContent = styled.div` +const AvatarContent = styled.div` display: inline-block; background: #adbcc9; text-align: center; diff --git a/packages/webapp/src/containers/Purchases/Bills/BillForm/BillFloatingActions.tsx b/packages/webapp/src/containers/Purchases/Bills/BillForm/BillFloatingActions.tsx index e326102f0..f0e1fda04 100644 --- a/packages/webapp/src/containers/Purchases/Bills/BillForm/BillFloatingActions.tsx +++ b/packages/webapp/src/containers/Purchases/Bills/BillForm/BillFloatingActions.tsx @@ -36,7 +36,7 @@ export default function BillFloatingActions() { submitForm(); }; - // Handle submit, open and anothe new button click. + // Handle submit, open and another new button click. const handleSubmitOpenAndNewBtnClick = (event) => { setSubmitPayload({ redirect: false, status: true, resetForm: true }); submitForm(); diff --git a/packages/webapp/src/containers/Purchases/Bills/BillForm/BillForm.tsx b/packages/webapp/src/containers/Purchases/Bills/BillForm/BillForm.tsx index 90d5a5583..38aa0fb5e 100644 --- a/packages/webapp/src/containers/Purchases/Bills/BillForm/BillForm.tsx +++ b/packages/webapp/src/containers/Purchases/Bills/BillForm/BillForm.tsx @@ -82,7 +82,6 @@ function BillForm({ isNewMode ? 'the_bill_has_been_created_successfully' : 'the_bill_has_been_edited_successfully', - { number: values.bill_number }, ), intent: Intent.SUCCESS, }); diff --git a/packages/webapp/src/containers/Purchases/Bills/BillForm/BillFormHeaderFields.tsx b/packages/webapp/src/containers/Purchases/Bills/BillForm/BillFormHeaderFields.tsx index 8e4fb0d88..0b797c2e5 100644 --- a/packages/webapp/src/containers/Purchases/Bills/BillForm/BillFormHeaderFields.tsx +++ b/packages/webapp/src/containers/Purchases/Bills/BillForm/BillFormHeaderFields.tsx @@ -176,7 +176,7 @@ function BillFormVendorField() { name={'vendor_id'} items={vendors} placeholder={} - onItemSelect={(contact) => { + onItemChange={(contact) => { setFieldValue('vendor_id', contact.id); setFieldValue('currency_code', contact?.currency_code); }} diff --git a/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFloatingActions.tsx b/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFloatingActions.tsx index db0c3111c..dd56835a7 100644 --- a/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFloatingActions.tsx +++ b/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFloatingActions.tsx @@ -35,7 +35,7 @@ export default function VendorCreditNoteFloatingActions() { submitForm(); }; - // Handle submit, open and anothe new button click. + // Handle submit, open and another new button click. const handleSubmitOpenAndNewBtnClick = (event) => { setSubmitPayload({ redirect: false, open: true, resetForm: true }); submitForm(); diff --git a/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormHeaderFields.tsx b/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormHeaderFields.tsx index 81de5cac9..aff4cada7 100644 --- a/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormHeaderFields.tsx +++ b/packages/webapp/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormHeaderFields.tsx @@ -193,7 +193,7 @@ function VendorCreditFormVendorSelect() { name={'vendor_id'} items={vendors} placeholder={} - onItemSelect={(contact) => { + onItemChange={(contact) => { setFieldValue('vendor_id', contact.id); setFieldValue('currency_code', contact?.currency_code); }} diff --git a/packages/webapp/src/containers/Purchases/PaymentMades/PaymentForm/PaymentMadeEntriesTable.tsx b/packages/webapp/src/containers/Purchases/PaymentMades/PaymentForm/PaymentMadeEntriesTable.tsx index 89f2c786c..cd0228799 100644 --- a/packages/webapp/src/containers/Purchases/PaymentMades/PaymentForm/PaymentMadeEntriesTable.tsx +++ b/packages/webapp/src/containers/Purchases/PaymentMades/PaymentForm/PaymentMadeEntriesTable.tsx @@ -42,7 +42,7 @@ export default function PaymentMadeEntriesTable({ }, [onUpdateData, entries], ); - // Detarmines the right no results message before selecting vendor and aftering + // Detarmines the right no results message before selecting vendor and after // selecting vendor id. const noResultsMessage = vendor_id ? ( } - onItemSelect={(contact) => { + onItemChange={(contact) => { setFieldValue('vendor_id', contact.id); setFieldValue('currency_code', contact?.currency_code); setPaymentVendorId(contact.id); diff --git a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFloatingActions.tsx b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFloatingActions.tsx index 1a837de22..71dd18325 100644 --- a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFloatingActions.tsx +++ b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFloatingActions.tsx @@ -35,7 +35,7 @@ export default function CreditNoteFloatingActions() { submitForm(); }; - // Handle submit, open and anothe new button click. + // Handle submit, open and another new button click. const handleSubmitOpenAndNewBtnClick = (event) => { setSubmitPayload({ redirect: false, open: true, resetForm: true }); submitForm(); diff --git a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormHeaderFields.tsx b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormHeaderFields.tsx index 5b2a31758..cd2fc1d1a 100644 --- a/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormHeaderFields.tsx +++ b/packages/webapp/src/containers/Sales/CreditNotes/CreditNoteForm/CreditNoteFormHeaderFields.tsx @@ -110,7 +110,7 @@ function CreditNoteCustomersSelect() { name={'customer_id'} items={customers} placeholder={} - onItemSelect={(customer) => { + onItemChange={(customer) => { setFieldValue('customer_id', customer.id); setFieldValue('currency_code', customer?.currency_code); }} diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormHeaderFields.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormHeaderFields.tsx index a5b94c750..e3bfabb9a 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormHeaderFields.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateForm/EstimateFormHeaderFields.tsx @@ -165,7 +165,7 @@ function EstimateFormCustomerSelect() { name={'customer_id'} items={customers} placeholder={} - onItemSelect={(customer) => { + onItemChange={(customer) => { setFieldValue('customer_id', customer.id); setFieldValue('currency_code', customer?.currency_code); }} diff --git a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormHeaderFields.tsx b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormHeaderFields.tsx index b22f744b5..8697e52bc 100644 --- a/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormHeaderFields.tsx +++ b/packages/webapp/src/containers/Sales/Invoices/InvoiceForm/InvoiceFormHeaderFields.tsx @@ -178,7 +178,7 @@ function InvoiceFormCustomerSelect() { name={'customer_id'} items={customers} placeholder={} - onItemSelect={(customer) => { + onItemChange={(customer) => { setFieldValue('customer_id', customer.id); setFieldValue('currency_code', customer?.currency_code); }} diff --git a/packages/webapp/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveHeaderFields.tsx b/packages/webapp/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveHeaderFields.tsx index d25290ab7..9ed1e5503 100644 --- a/packages/webapp/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveHeaderFields.tsx +++ b/packages/webapp/src/containers/Sales/PaymentReceives/PaymentReceiveForm/PaymentReceiveHeaderFields.tsx @@ -263,7 +263,7 @@ function PaymentReceiveCustomerSelect() { name={'customer_id'} items={customers} placeholder={} - onItemSelect={(customer) => { + onItemChange={(customer) => { setFieldValue('customer_id', customer.id); setFieldValue('full_amount', ''); setFieldValue('currency_code', customer?.currency_code); diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormHeaderFields.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormHeaderFields.tsx index f1f37378b..92ef297cb 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormHeaderFields.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptForm/ReceiptFormHeaderFields.tsx @@ -162,7 +162,7 @@ function ReceiptFormCustomerSelect() { name={'customer_id'} items={customers} placeholder={} - onItemSelect={(customer) => { + onItemChange={(customer) => { setFieldValue('customer_id', customer.id); setFieldValue('currency_code', customer?.currency_code); }} diff --git a/packages/webapp/src/containers/Vendors/VendorForm/VendorAttahmentTab.tsx b/packages/webapp/src/containers/Vendors/VendorForm/VendorAttachmentTab.tsx similarity index 76% rename from packages/webapp/src/containers/Vendors/VendorForm/VendorAttahmentTab.tsx rename to packages/webapp/src/containers/Vendors/VendorForm/VendorAttachmentTab.tsx index 5d80112fe..7cbb5735f 100644 --- a/packages/webapp/src/containers/Vendors/VendorForm/VendorAttahmentTab.tsx +++ b/packages/webapp/src/containers/Vendors/VendorForm/VendorAttachmentTab.tsx @@ -3,9 +3,9 @@ import React from 'react'; import { Dragzone, FormattedMessage as T } from '@/components'; /** - * Vendor Attahment Tab. + * Vendor Attachment Tab. */ -function VendorAttahmentTab() { +function VendorAttachmentTab() { return (
({ - columns: res.data.columns, - data: res.data.data, - query: res.data.query, - tableRows: ARAgingSummaryTableRowsMapper({ - customers: res.data.data.customers, - total: res.data.data.total, - columns: res.data.columns, - }), - }), - defaultData: { - data: { - customers: [], - total: {}, - }, - columns: [], - tableRows: [], - }, + select: (res) => res.data, ...props, }, ); @@ -173,26 +159,12 @@ export function useAPAgingSummaryReport(query, props) { method: 'get', url: '/financial_statements/payable_aging_summary', params: query, + headers: { + Accept: 'application/json+table', + }, }, { - select: (res) => ({ - columns: res.data.columns, - data: res.data.data, - query: res.data.query, - tableRows: APAgingSummaryTableRowsMapper({ - vendors: res.data.data.vendors, - total: res.data.data.total, - columns: res.data.columns, - }), - }), - defaultData: { - data: { - vendors: [], - total: {}, - }, - columns: [], - tableRows: [], - }, + select: (res) => res.data, ...props, }, ); diff --git a/packages/webapp/src/lang/ar/index.json b/packages/webapp/src/lang/ar/index.json index 23144174c..b2325c53f 100644 --- a/packages/webapp/src/lang/ar/index.json +++ b/packages/webapp/src/lang/ar/index.json @@ -423,7 +423,7 @@ "company_name": "اسم الشركة", "other": "آخر", "address": "عنوان", - "attachement": "التعلق", + "attachment": "التعلق", "country": "دولة", "city_town": "المدينة / البلدة", "state": "ولاية", @@ -1906,7 +1906,7 @@ "branch.alert.mark_primary_message": "تم تحديد الفرع على أنه أساسي.", "branch.error.could_not_delete_only_branch": "لا يمكنك حذف الفرع الاخير.", "warehouse_activate.dialog_success_message": "تم تفعيل خاصية تعدد المخازن بنجاح.", - "warehouse_actviate.dialog.label": "تفعيل المخازن", + "warehouse_activate.dialog.label": "تفعيل المخازن", "warehouse_activate.dialog_paragraph": "بمجرد تفعيل خاصية تعدد المخازن, لن تتمكن من تعطيلها. ومع ذلك ، يمكنك حذف المخزن أو وضع علامة على أنه غير نشط.", "warehouse_activate.dialog_paragraph.line_1": "سيتم اعتبار المنشأة الحالية بمثابة المكتب الرئيسي أو الفرع الرئيسي.", "warehouse_activate.dialog_paragraph.line_2": "سيتم اعتبار جميع معاملات الحسابات بمثابة المكتب الرئيسي. ", diff --git a/packages/webapp/src/lang/en/index.json b/packages/webapp/src/lang/en/index.json index 6fb394354..68cb44364 100644 --- a/packages/webapp/src/lang/en/index.json +++ b/packages/webapp/src/lang/en/index.json @@ -420,7 +420,7 @@ "company_name": "Company Name", "other": "Other", "address": "Address", - "attachement": "Attachement", + "attachment": "Attachment", "country": "Country", "city_town": "City/Town", "state": "State", @@ -558,8 +558,8 @@ "bill_date_": "Bill date", "bill_number_": "Bill number", "delete_bill": "Delete Bill", - "the_bill_has_been_edited_successfully": "The bill #{number} has been edited successfully.", - "the_bill_has_been_created_successfully": "The bill #{number} has been created successfully.", + "the_bill_has_been_edited_successfully": "The bill has been edited successfully.", + "the_bill_has_been_created_successfully": "The bill has been created successfully.", "the_bill_has_been_deleted_successfully": "The bill has been deleted successfully.", "once_delete_this_bill_you_will_able_to_restore_it": "Once you delete this bill, you won't be able to restore it later. Are you sure you want to delete this bill?", "deposit_to": "Deposit to", @@ -1930,7 +1930,7 @@ "branch.alert.mark_primary_message": "The branch has been marked as primary.", "branch.alert.are_you_sure_you_want_to_make": "Are you sure you want to make a primary branch?", "branch.error.could_not_delete_only_branch": "You could not delete the only branch.", - "warehouse_actviate.dialog.label": "Warehouses Activation", + "warehouse_activate.dialog.label": "Warehouses Activation", "warehouse_activate.dialog_success_message": "Multi-branches feature has been activated successfully.", "warehouse_activate.dialog_paragraph": "Once you enable Multiple Warehouses, you will not be able to disable it. However, you can delete the warehouse or mark it inactive.", "warehouse_activate.dialog_paragraph.line_1": "The current organization will be considered as the Head Office or Primary warehouse.", @@ -2294,4 +2294,4 @@ "sidebar.new_time_entry": "New Time Entry", "sidebar.project_profitability_summary": "Project Profitability Summary", "global_error.too_many_requests": "Too many requests" -} \ No newline at end of file +}