mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-05-12 13:55:03 +00:00
Merge branch 'develop' into tax-compliance
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -79,7 +79,7 @@ export default class JournalPoster implements IJournalPoster {
|
||||
}
|
||||
|
||||
/**
|
||||
* Async initialize acccounts dependency graph.
|
||||
* Async initialize accounts dependency graph.
|
||||
* @private
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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, {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
|
||||
|
||||
export class AccountsReceivableRepository {
|
||||
|
||||
|
||||
findOrCreateAccount = (currencyCode?: string) => {
|
||||
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
export * from './CashflowBranchesActviateSubscriber';
|
||||
export * from './CashflowBranchesActivateSubscriber';
|
||||
export * from './CreditNoteBranchesActivateSubscriber';
|
||||
export * from './PaymentMadeBranchesActivateSubscriber';
|
||||
export * from './PaymentReceiveBranchesActivateSubscriber';
|
||||
|
||||
@@ -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 -
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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}
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<void>}
|
||||
*/
|
||||
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<void>}
|
||||
*/
|
||||
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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ({
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
|
||||
|
||||
export default class DynamicListAbstract {
|
||||
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
|
||||
|
||||
|
||||
export default class DynamicListAbstruct {
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<void>}
|
||||
|
||||
@@ -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<boolean|null|undefined>}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
};
|
||||
|
||||
@@ -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' };
|
||||
};
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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' };
|
||||
}
|
||||
}
|
||||
@@ -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' },
|
||||
]);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export enum AgingSummaryRowType {
|
||||
Contact = 'contact',
|
||||
Total = 'total',
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<IInvetoryItemDetailDOO>}
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -12,7 +12,7 @@ export const FinancialTable = (Base) =>
|
||||
* @param {ITableColumn[]} columns
|
||||
* @returns {ITableColumn[]}
|
||||
*/
|
||||
protected tableColumnsCellIndexing = (
|
||||
public tableColumnsCellIndexing = (
|
||||
columns: ITableColumn[]
|
||||
): ITableColumn[] => {
|
||||
const cellIndex = increment(-1);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 };
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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: [],
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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 })),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
|
||||
|
||||
export default class ItemsCostService {
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -48,6 +48,7 @@ export class ManualJournalWriteGLSubscriber {
|
||||
/**
|
||||
* Handle manual journal created event.
|
||||
* @param {IManualJournalEventCreatedPayload} payload -
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
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<void>}
|
||||
*/
|
||||
private handleJournalNumberIncrement = async ({
|
||||
tenantId,
|
||||
@@ -77,6 +79,7 @@ export class ManualJournalWriteGLSubscriber {
|
||||
/**
|
||||
* Handle manual journal edited event.
|
||||
* @param {IManualJournalEventEditedPayload}
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
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<void>}
|
||||
*/
|
||||
private handleWriteJournalEntriesOnPublished = async ({
|
||||
tenantId,
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -68,7 +68,7 @@ export default class BillPaymentsPages {
|
||||
): Promise<IBillReceivePageEntry[]> {
|
||||
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')
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ export class BillPaymentsGLEntriesRewriteSubscriber {
|
||||
private billPaymentGLEntriesRewrite: BillPaymentsGLEntriesRewrite;
|
||||
|
||||
/**
|
||||
* Attachs events with handles.
|
||||
* Attaches events with handles.
|
||||
*/
|
||||
public attach(bus) {
|
||||
bus.subscribe(
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 ({
|
||||
|
||||
@@ -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 ({
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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, {
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user