Compare commits

..

1 Commits

Author SHA1 Message Date
Ahmed Bouhuolia
3bf2803360 feat(trpc): implement tRPC integration for accounts module
- Add tRPC server setup with NestJS (nestjs-trpc)
- Create AccountsTrpcRouter with CRUD operations
- Add tRPC client configuration in webapp
- Create tRPC React hooks for accounts module
- Replace existing REST hooks with tRPC hooks across 35+ files
- Maintain backward compatibility with existing REST API
- Add proper cache invalidation for mutations

New files:
- packages/server/src/modules/Trpc/*
- packages/webapp/src/trpc.ts
- packages/webapp/src/hooks/trpc/*
- shared/bigcapital-utils/src/trpc.ts

Dependencies added:
- @trpc/server, @trpc/client, @trpc/react-query
- nestjs-trpc, superjson
- @tanstack/react-query

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 04:34:04 +02:00
167 changed files with 833 additions and 648 deletions

View File

@@ -127,7 +127,10 @@
"uuid": "^10.0.0", "uuid": "^10.0.0",
"xlsx": "^0.18.5", "xlsx": "^0.18.5",
"yup": "^0.28.1", "yup": "^0.28.1",
"zod": "^3.23.8" "zod": "^3.23.8",
"@trpc/server": "^11.0.0-rc.648",
"nestjs-trpc": "^1.6.1",
"superjson": "^2.2.2"
}, },
"devDependencies": { "devDependencies": {
"@nestjs/cli": "^10.0.0", "@nestjs/cli": "^10.0.0",

View File

@@ -1,6 +1,5 @@
import { QueryBuilder, Model, mixin } from 'objection'; import { QueryBuilder, Model } from 'objection';
import { ModelHasRelationsError } from '@/common/exceptions/ModelHasRelations.exception'; import { ModelHasRelationsError } from '@/common/exceptions/ModelHasRelations.exception';
import { withDateSessionMixin } from './withDateSessionMixin';
interface PaginationResult<M extends Model> { interface PaginationResult<M extends Model> {
results: M[]; results: M[];
@@ -70,7 +69,6 @@ export class PaginationQueryBuilder<
dependentRelationNames.forEach((relationName: string) => { dependentRelationNames.forEach((relationName: string) => {
recordQuery.withGraphFetched(relationName); recordQuery.withGraphFetched(relationName);
}); });
const record = await recordQuery; const record = await recordQuery;
const hasRelations = dependentRelationNames.some((name) => { const hasRelations = dependentRelationNames.some((name) => {
@@ -99,7 +97,7 @@ export class BaseQueryBuilder<
} }
} }
export class BaseModel extends mixin(Model, [withDateSessionMixin]) { export class BaseModel extends Model {
public readonly id: number; public readonly id: number;
public readonly tableName: string; public readonly tableName: string;

View File

@@ -1,40 +0,0 @@
import * as moment from 'moment';
import { Model } from 'objection';
type Constructor<T = {}> = new (...args: any[]) => T;
export const withDateSessionMixin = <T extends Constructor<Model>>(BaseModel: T) => {
return class DateSession extends BaseModel {
constructor(...args: any[]) {
super(...args);
}
get timestamps() {
return [];
}
$beforeUpdate(opt, context) {
const maybePromise = super.$beforeUpdate(opt, context);
return Promise.resolve(maybePromise).then(() => {
const key = this.timestamps[1];
if (key && !this[key]) {
this[key] = moment().format('YYYY/MM/DD HH:mm:ss');
}
});
}
$beforeInsert(context) {
const maybePromise = super.$beforeInsert(context);
return Promise.resolve(maybePromise).then(() => {
const key = this.timestamps[0];
if (key && !this[key]) {
this[key] = moment().format('YYYY/MM/DD HH:mm:ss');
}
});
}
}
}

View File

@@ -21,7 +21,6 @@ import { AccountsExportable } from './AccountsExportable.service';
import { AccountsImportable } from './AccountsImportable.service'; import { AccountsImportable } from './AccountsImportable.service';
import { BulkDeleteAccountsService } from './BulkDeleteAccounts.service'; import { BulkDeleteAccountsService } from './BulkDeleteAccounts.service';
import { ValidateBulkDeleteAccountsService } from './ValidateBulkDeleteAccounts.service'; import { ValidateBulkDeleteAccountsService } from './ValidateBulkDeleteAccounts.service';
import { AccountsSettingsService } from './AccountsSettings.service';
const models = [RegisterTenancyModel(BankAccount)]; const models = [RegisterTenancyModel(BankAccount)];
@@ -30,7 +29,6 @@ const models = [RegisterTenancyModel(BankAccount)];
controllers: [AccountsController], controllers: [AccountsController],
providers: [ providers: [
AccountsApplication, AccountsApplication,
AccountsSettingsService,
CreateAccountService, CreateAccountService,
TenancyContext, TenancyContext,
CommandAccountValidators, CommandAccountValidators,
@@ -51,10 +49,9 @@ const models = [RegisterTenancyModel(BankAccount)];
exports: [ exports: [
AccountRepository, AccountRepository,
CreateAccountService, CreateAccountService,
AccountsSettingsService,
...models, ...models,
AccountsExportable, AccountsExportable,
AccountsImportable, AccountsImportable
], ],
}) })
export class AccountsModule {} export class AccountsModule {}

View File

@@ -1,33 +0,0 @@
import { Inject, Injectable } from '@nestjs/common';
import { SettingsStore } from '../Settings/SettingsStore';
import { SETTINGS_PROVIDER } from '../Settings/Settings.types';
export interface IAccountsSettings {
accountCodeRequired: boolean;
accountCodeUnique: boolean;
}
@Injectable()
export class AccountsSettingsService {
constructor(
@Inject(SETTINGS_PROVIDER)
private readonly settingsStore: () => SettingsStore,
) {}
/**
* Retrieves account settings (account code required, account code unique).
*/
public async getAccountsSettings(): Promise<IAccountsSettings> {
const settingsStore = await this.settingsStore();
return {
accountCodeRequired: settingsStore.get(
{ group: 'accounts', key: 'account_code_required' },
false,
),
accountCodeUnique: settingsStore.get(
{ group: 'accounts', key: 'account_code_unique' },
true,
),
};
}
}

View File

@@ -106,20 +106,6 @@ export class CommandAccountValidators {
} }
} }
/**
* Throws error if account code is missing or blank when required.
* @param {string|undefined} code - Account code.
*/
public validateAccountCodeRequiredOrThrow(code: string | undefined) {
const trimmed = typeof code === 'string' ? code.trim() : '';
if (!trimmed) {
throw new ServiceError(
ERRORS.ACCOUNT_CODE_REQUIRED,
'Account code is required.',
);
}
}
/** /**
* Validates the account name uniquiness. * Validates the account name uniquiness.
* @param {string} accountName - Account name. * @param {string} accountName - Account name.

View File

@@ -15,7 +15,6 @@ import { events } from '@/common/events/events';
import { CreateAccountDTO } from './CreateAccount.dto'; import { CreateAccountDTO } from './CreateAccount.dto';
import { PartialModelObject } from 'objection'; import { PartialModelObject } from 'objection';
import { TenantModelProxy } from '../System/models/TenantBaseModel'; import { TenantModelProxy } from '../System/models/TenantBaseModel';
import { AccountsSettingsService } from './AccountsSettings.service';
@Injectable() @Injectable()
export class CreateAccountService { export class CreateAccountService {
@@ -33,7 +32,6 @@ export class CreateAccountService {
private readonly uow: UnitOfWork, private readonly uow: UnitOfWork,
private readonly validator: CommandAccountValidators, private readonly validator: CommandAccountValidators,
private readonly tenancyContext: TenancyContext, private readonly tenancyContext: TenancyContext,
private readonly accountsSettings: AccountsSettingsService,
) {} ) {}
/** /**
@@ -45,21 +43,14 @@ export class CreateAccountService {
baseCurrency: string, baseCurrency: string,
params?: CreateAccountParams, params?: CreateAccountParams,
) => { ) => {
const { accountCodeRequired, accountCodeUnique } =
await this.accountsSettings.getAccountsSettings();
// Validate account code required when setting is enabled.
if (accountCodeRequired) {
this.validator.validateAccountCodeRequiredOrThrow(accountDTO.code);
}
// Validate the account code uniquiness when setting is enabled.
if (accountCodeUnique && accountDTO.code?.trim()) {
await this.validator.isAccountCodeUniqueOrThrowError(accountDTO.code);
}
// Validate account name uniquiness. // Validate account name uniquiness.
if (!params.ignoreUniqueName) { if (!params.ignoreUniqueName) {
await this.validator.validateAccountNameUniquiness(accountDTO.name); await this.validator.validateAccountNameUniquiness(accountDTO.name);
} }
// Validate the account code uniquiness.
if (accountDTO.code) {
await this.validator.isAccountCodeUniqueOrThrowError(accountDTO.code);
}
// Retrieve the account type meta or throw service error if not found. // Retrieve the account type meta or throw service error if not found.
this.validator.getAccountTypeOrThrowError(accountDTO.accountType); this.validator.getAccountTypeOrThrowError(accountDTO.accountType);

View File

@@ -7,7 +7,6 @@ import { UnitOfWork } from '../Tenancy/TenancyDB/UnitOfWork.service';
import { events } from '@/common/events/events'; import { events } from '@/common/events/events';
import { EditAccountDTO } from './EditAccount.dto'; import { EditAccountDTO } from './EditAccount.dto';
import { TenantModelProxy } from '../System/models/TenantBaseModel'; import { TenantModelProxy } from '../System/models/TenantBaseModel';
import { AccountsSettingsService } from './AccountsSettings.service';
@Injectable() @Injectable()
export class EditAccount { export class EditAccount {
@@ -18,7 +17,6 @@ export class EditAccount {
@Inject(Account.name) @Inject(Account.name)
private readonly accountModel: TenantModelProxy<typeof Account>, private readonly accountModel: TenantModelProxy<typeof Account>,
private readonly accountsSettings: AccountsSettingsService,
) { } ) { }
/** /**
@@ -32,24 +30,6 @@ export class EditAccount {
accountDTO: EditAccountDTO, accountDTO: EditAccountDTO,
oldAccount: Account, oldAccount: Account,
) => { ) => {
const { accountCodeRequired, accountCodeUnique } =
await this.accountsSettings.getAccountsSettings();
// Validate account code required when setting is enabled.
if (accountCodeRequired) {
this.validator.validateAccountCodeRequiredOrThrow(accountDTO.code);
}
// Validate the account code uniquiness when setting is enabled.
if (
accountCodeUnique &&
accountDTO.code?.trim() &&
accountDTO.code !== oldAccount.code
) {
await this.validator.isAccountCodeUniqueOrThrowError(
accountDTO.code,
oldAccount.id,
);
}
// Validate account name uniquiness. // Validate account name uniquiness.
await this.validator.validateAccountNameUniquiness( await this.validator.validateAccountNameUniquiness(
accountDTO.name, accountDTO.name,
@@ -60,6 +40,13 @@ export class EditAccount {
oldAccount, oldAccount,
accountDTO, accountDTO,
); );
// Validate the account code not exists on the storage.
if (accountDTO.code && accountDTO.code !== oldAccount.code) {
await this.validator.isAccountCodeUniqueOrThrowError(
accountDTO.code,
oldAccount.id,
);
}
// Retrieve the parent account of throw not found service error. // Retrieve the parent account of throw not found service error.
if (accountDTO.parentAccountId) { if (accountDTO.parentAccountId) {
const parentAccount = await this.validator.getParentAccountOrThrowError( const parentAccount = await this.validator.getParentAccountOrThrowError(

View File

@@ -3,7 +3,6 @@ export const ERRORS = {
ACCOUNT_TYPE_NOT_FOUND: 'account_type_not_found', ACCOUNT_TYPE_NOT_FOUND: 'account_type_not_found',
PARENT_ACCOUNT_NOT_FOUND: 'parent_account_not_found', PARENT_ACCOUNT_NOT_FOUND: 'parent_account_not_found',
ACCOUNT_CODE_NOT_UNIQUE: 'account_code_not_unique', ACCOUNT_CODE_NOT_UNIQUE: 'account_code_not_unique',
ACCOUNT_CODE_REQUIRED: 'account_code_required',
ACCOUNT_NAME_NOT_UNIQUE: 'account_name_not_unqiue', ACCOUNT_NAME_NOT_UNIQUE: 'account_name_not_unqiue',
PARENT_ACCOUNT_HAS_DIFFERENT_TYPE: 'parent_has_different_type', PARENT_ACCOUNT_HAS_DIFFERENT_TYPE: 'parent_has_different_type',
ACCOUNT_TYPE_NOT_ALLOWED_TO_CHANGE: 'account_type_not_allowed_to_changed', ACCOUNT_TYPE_NOT_ALLOWED_TO_CHANGE: 'account_type_not_allowed_to_changed',

View File

@@ -104,6 +104,7 @@ import { BillLandedCostsModule } from '../BillLandedCosts/BillLandedCosts.module
import { SocketModule } from '../Socket/Socket.module'; import { SocketModule } from '../Socket/Socket.module';
import { ThrottlerGuard } from '@nestjs/throttler'; import { ThrottlerGuard } from '@nestjs/throttler';
import { AppThrottleModule } from './AppThrottle.module'; import { AppThrottleModule } from './AppThrottle.module';
import { AppTrpcModule } from '../Trpc/Trpc.module';
@Module({ @Module({
imports: [ imports: [
@@ -256,6 +257,7 @@ import { AppThrottleModule } from './AppThrottle.module';
UsersModule, UsersModule,
ContactsModule, ContactsModule,
SocketModule, SocketModule,
AppTrpcModule,
], ],
controllers: [AppController], controllers: [AppController],
providers: [ providers: [

View File

@@ -24,7 +24,6 @@ import { GetBankAccountsService } from './queries/GetBankAccounts.service';
import { DynamicListModule } from '../DynamicListing/DynamicList.module'; import { DynamicListModule } from '../DynamicListing/DynamicList.module';
import { BankAccount } from './models/BankAccount'; import { BankAccount } from './models/BankAccount';
import { LedgerModule } from '../Ledger/Ledger.module'; import { LedgerModule } from '../Ledger/Ledger.module';
import { TenancyModule } from '../Tenancy/Tenancy.module';
import { GetBankAccountTransactionsService } from './queries/GetBankAccountTransactions/GetBankAccountTransactions.service'; import { GetBankAccountTransactionsService } from './queries/GetBankAccountTransactions/GetBankAccountTransactions.service';
import { GetBankAccountTransactionsRepository } from './queries/GetBankAccountTransactions/GetBankAccountTransactionsRepo.service'; import { GetBankAccountTransactionsRepository } from './queries/GetBankAccountTransactions/GetBankAccountTransactionsRepo.service';
import { GetUncategorizedTransactions } from './queries/GetUncategorizedTransactions'; import { GetUncategorizedTransactions } from './queries/GetUncategorizedTransactions';
@@ -47,7 +46,6 @@ const models = [
LedgerModule, LedgerModule,
BranchesModule, BranchesModule,
DynamicListModule, DynamicListModule,
TenancyModule,
...models, ...models,
], ],
controllers: [ controllers: [

View File

@@ -4,14 +4,12 @@ import { GetBankAccountTransactionsRepository } from './GetBankAccountTransactio
import { GetBankAccountTransactions } from './GetBankAccountTransactions'; import { GetBankAccountTransactions } from './GetBankAccountTransactions';
import { GetBankTransactionsQueryDto } from '../../dtos/GetBankTranasctionsQuery.dto'; import { GetBankTransactionsQueryDto } from '../../dtos/GetBankTranasctionsQuery.dto';
import { I18nService } from 'nestjs-i18n'; import { I18nService } from 'nestjs-i18n';
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
@Injectable() @Injectable()
export class GetBankAccountTransactionsService { export class GetBankAccountTransactionsService {
constructor( constructor(
private readonly getBankAccountTransactionsRepository: GetBankAccountTransactionsRepository, private readonly getBankAccountTransactionsRepository: GetBankAccountTransactionsRepository,
private readonly i18nService: I18nService, private readonly i18nService: I18nService
private readonly tenancyContext: TenancyContext,
) {} ) {}
/** /**
@@ -30,16 +28,11 @@ export class GetBankAccountTransactionsService {
await this.getBankAccountTransactionsRepository.asyncInit(); await this.getBankAccountTransactionsRepository.asyncInit();
// Retrieve the tenant metadata to get the date format.
const tenantMetadata = await this.tenancyContext.getTenantMetadata();
const dateFormat = tenantMetadata?.dateFormat;
// Retrieve the computed report. // Retrieve the computed report.
const report = new GetBankAccountTransactions( const report = new GetBankAccountTransactions(
this.getBankAccountTransactionsRepository, this.getBankAccountTransactionsRepository,
parsedQuery, parsedQuery,
this.i18nService, this.i18nService
dateFormat,
); );
const transactions = report.reportData(); const transactions = report.reportData();
const pagination = this.getBankAccountTransactionsRepository.pagination; const pagination = this.getBankAccountTransactionsRepository.pagination;

View File

@@ -24,20 +24,17 @@ export class GetBankAccountTransactions extends FinancialSheet {
* @param {IAccountTransaction[]} transactions - * @param {IAccountTransaction[]} transactions -
* @param {number} openingBalance - * @param {number} openingBalance -
* @param {ICashflowAccountTransactionsQuery} query - * @param {ICashflowAccountTransactionsQuery} query -
* @param {string} dateFormat - The date format from organization settings.
*/ */
constructor( constructor(
repo: GetBankAccountTransactionsRepository, repo: GetBankAccountTransactionsRepository,
query: ICashflowAccountTransactionsQuery, query: ICashflowAccountTransactionsQuery,
i18n: I18nService, i18n: I18nService,
dateFormat?: string,
) { ) {
super(); super();
this.repo = repo; this.repo = repo;
this.query = query; this.query = query;
this.i18n = i18n; this.i18n = i18n;
this.dateFormat = dateFormat || this.dateFormat;
this.runningBalance = runningBalance(this.repo.openingBalance); this.runningBalance = runningBalance(this.repo.openingBalance);
} }
@@ -101,7 +98,7 @@ export class GetBankAccountTransactions extends FinancialSheet {
return { return {
date: transaction.date, date: transaction.date,
formattedDate: this.getDateFormatted(transaction.date), formattedDate: moment(transaction.date).format('YYYY-MM-DD'),
withdrawal: transaction.credit, withdrawal: transaction.credit,
deposit: transaction.debit, deposit: transaction.debit,

View File

@@ -13,13 +13,6 @@ export class BillLandedCostEntry extends BaseModel {
return 'bill_located_cost_entries'; return 'bill_located_cost_entries';
} }
/**
* Timestamps columns.
*/
get timestamps() {
return [];
}
/** /**
* Relationship mapping. * Relationship mapping.
*/ */

View File

@@ -29,7 +29,7 @@ export class Branch extends BaseModel{
* Timestamps columns. * Timestamps columns.
*/ */
get timestamps() { get timestamps() {
return ['createdAt', 'updatedAt']; return ['created_at', 'updated_at'];
} }
/** /**

View File

@@ -10,7 +10,7 @@ export interface IContactAddress {
billingAddressCity: string; billingAddressCity: string;
billingAddressCountry: string; billingAddressCountry: string;
billingAddressEmail: string; billingAddressEmail: string;
billingAddressPostcode: string; billingAddressZipcode: string;
billingAddressPhone: string; billingAddressPhone: string;
billingAddressState: string; billingAddressState: string;
@@ -19,7 +19,7 @@ export interface IContactAddress {
shippingAddressCity: string; shippingAddressCity: string;
shippingAddressCountry: string; shippingAddressCountry: string;
shippingAddressEmail: string; shippingAddressEmail: string;
shippingAddressPostcode: string; shippingAddressZipcode: string;
shippingAddressPhone: string; shippingAddressPhone: string;
shippingAddressState: string; shippingAddressState: string;
} }
@@ -29,7 +29,7 @@ export interface IContactAddressDTO {
billingAddressCity?: string; billingAddressCity?: string;
billingAddressCountry?: string; billingAddressCountry?: string;
billingAddressEmail?: string; billingAddressEmail?: string;
billingAddressPostcode?: string; billingAddressZipcode?: string;
billingAddressPhone?: string; billingAddressPhone?: string;
billingAddressState?: string; billingAddressState?: string;
@@ -38,7 +38,7 @@ export interface IContactAddressDTO {
shippingAddressCity?: string; shippingAddressCity?: string;
shippingAddressCountry?: string; shippingAddressCountry?: string;
shippingAddressEmail?: string; shippingAddressEmail?: string;
shippingAddressPostcode?: string; shippingAddressZipcode?: string;
shippingAddressPhone?: string; shippingAddressPhone?: string;
shippingAddressState?: string; shippingAddressState?: string;
} }

View File

@@ -34,7 +34,7 @@ export class RefundCreditNote extends BaseModel {
* Timestamps columns. * Timestamps columns.
*/ */
get timestamps() { get timestamps() {
return ['createdAt', 'updatedAt']; return ['created_at', 'updated_at'];
} }
/** /**

View File

@@ -56,7 +56,7 @@ export class CreditNote extends TenantBaseModel {
* Timestamps columns. * Timestamps columns.
*/ */
get timestamps() { get timestamps() {
return ['createdAt', 'updatedAt']; return ['created_at', 'updated_at'];
} }
/** /**

View File

@@ -26,7 +26,7 @@ export class CreditNoteAppliedInvoice extends BaseModel {
* Timestamps columns. * Timestamps columns.
*/ */
get timestamps() { get timestamps() {
return ['createdAt', 'updatedAt']; return ['created_at', 'updated_at'];
} }
/** /**

View File

@@ -27,10 +27,10 @@ export class ContactAddressDto {
@IsEmail() @IsEmail()
billingAddressEmail?: string; billingAddressEmail?: string;
@ApiProperty({ required: false, description: 'Billing address postcode' }) @ApiProperty({ required: false, description: 'Billing address zipcode' })
@IsOptional() @IsOptional()
@IsString() @IsString()
billingAddressPostcode?: string; billingAddressZipcode?: string;
@ApiProperty({ required: false, description: 'Billing address phone' }) @ApiProperty({ required: false, description: 'Billing address phone' })
@IsOptional() @IsOptional()
@@ -67,10 +67,10 @@ export class ContactAddressDto {
@IsEmail() @IsEmail()
shippingAddressEmail?: string; shippingAddressEmail?: string;
@ApiProperty({ required: false, description: 'Shipping address postcode' }) @ApiProperty({ required: false, description: 'Shipping address zipcode' })
@IsOptional() @IsOptional()
@IsString() @IsString()
shippingAddressPostcode?: string; shippingAddressZipcode?: string;
@ApiProperty({ required: false, description: 'Shipping address phone' }) @ApiProperty({ required: false, description: 'Shipping address phone' })
@IsOptional() @IsOptional()

View File

@@ -15,7 +15,6 @@ export class FinancialSheet {
negativeFormat: 'mines', negativeFormat: 'mines',
}; };
public baseCurrency: string; public baseCurrency: string;
public dateFormat: string = 'YYYY MMM DD';
/** /**
* Transformes the number format query to settings * Transformes the number format query to settings
@@ -141,19 +140,13 @@ export class FinancialSheet {
* @param {string} format * @param {string} format
* @returns * @returns
*/ */
protected getDateMeta(date: moment.MomentInput, format?: string) { protected getDateMeta(date: moment.MomentInput, format = 'YYYY-MM-DD') {
const dateFormat = format || this.dateFormat || 'YYYY MMM DD';
return { return {
formattedDate: moment(date).format(dateFormat), formattedDate: moment(date).format(format),
date: moment(date).toDate(), date: moment(date).toDate(),
}; };
} }
protected getDateFormatted(date: moment.MomentInput, format?: string) {
const dateFormat = format || this.dateFormat || 'YYYY MMM DD';
return moment(date).format(dateFormat);
}
getPercentageBasis = (base, amount) => { getPercentageBasis = (base, amount) => {
return base ? amount / base : 0; return base ? amount / base : 0;
}; };

View File

@@ -32,19 +32,18 @@ export class APAgingSummaryService {
this.APAgingSummaryRepository.setFilter(filter); this.APAgingSummaryRepository.setFilter(filter);
await this.APAgingSummaryRepository.load(); await this.APAgingSummaryRepository.load();
// Retrieve the aging summary report meta first to get date format.
const meta = await this.APAgingSummaryMeta.meta(filter);
// A/P aging summary report instance. // A/P aging summary report instance.
const APAgingSummaryReport = new APAgingSummarySheet( const APAgingSummaryReport = new APAgingSummarySheet(
filter, filter,
this.APAgingSummaryRepository, this.APAgingSummaryRepository,
{ baseCurrency: meta.baseCurrency, dateFormat: meta.dateFormat },
); );
// A/P aging summary report data and columns. // A/P aging summary report data and columns.
const data = APAgingSummaryReport.reportData(); const data = APAgingSummaryReport.reportData();
const columns = APAgingSummaryReport.reportColumns(); const columns = APAgingSummaryReport.reportColumns();
// Retrieve the aging summary report meta.
const meta = await this.APAgingSummaryMeta.meta(filter);
// Triggers `onPayableAgingViewed` event. // Triggers `onPayableAgingViewed` event.
await this.eventPublisher.emitAsync(events.reports.onPayableAgingViewed, { await this.eventPublisher.emitAsync(events.reports.onPayableAgingViewed, {
query, query,

View File

@@ -14,7 +14,6 @@ import { allPassedConditionsPass } from '@/utils/all-conditions-passed';
import { APAgingSummaryRepository } from './APAgingSummaryRepository'; import { APAgingSummaryRepository } from './APAgingSummaryRepository';
import { Bill } from '@/modules/Bills/models/Bill'; import { Bill } from '@/modules/Bills/models/Bill';
import { APAgingSummaryQueryDto } from './APAgingSummaryQuery.dto'; import { APAgingSummaryQueryDto } from './APAgingSummaryQuery.dto';
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
export class APAgingSummarySheet extends AgingSummaryReport { export class APAgingSummarySheet extends AgingSummaryReport {
readonly repository: APAgingSummaryRepository; readonly repository: APAgingSummaryRepository;
@@ -32,14 +31,12 @@ export class APAgingSummarySheet extends AgingSummaryReport {
constructor( constructor(
query: APAgingSummaryQueryDto, query: APAgingSummaryQueryDto,
repository: APAgingSummaryRepository, repository: APAgingSummaryRepository,
meta: IFinancialReportMeta,
) { ) {
super(); super();
this.query = query; this.query = query;
this.repository = repository; this.repository = repository;
this.numberFormat = this.query.numberFormat; this.numberFormat = this.query.numberFormat;
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
this.overdueInvoicesByContactId = this.repository.overdueBillsByVendorId; this.overdueInvoicesByContactId = this.repository.overdueBillsByVendorId;
this.currentInvoicesByContactId = this.repository.dueBillsByVendorId; this.currentInvoicesByContactId = this.repository.dueBillsByVendorId;

View File

@@ -28,19 +28,18 @@ export class ARAgingSummaryService {
this.ARAgingSummaryRepository.setFilter(filter); this.ARAgingSummaryRepository.setFilter(filter);
await this.ARAgingSummaryRepository.load(); await this.ARAgingSummaryRepository.load();
// Retrieve the aging summary report meta first to get date format.
const meta = await this.ARAgingSummaryMeta.meta(filter);
// A/R aging summary report instance. // A/R aging summary report instance.
const ARAgingSummaryReport = new ARAgingSummarySheet( const ARAgingSummaryReport = new ARAgingSummarySheet(
filter, filter,
this.ARAgingSummaryRepository, this.ARAgingSummaryRepository,
{ baseCurrency: meta.baseCurrency, dateFormat: meta.dateFormat },
); );
// A/R aging summary report data and columns. // A/R aging summary report data and columns.
const data = ARAgingSummaryReport.reportData(); const data = ARAgingSummaryReport.reportData();
const columns = ARAgingSummaryReport.reportColumns(); const columns = ARAgingSummaryReport.reportColumns();
// Retrieve the aging summary report meta.
const meta = await this.ARAgingSummaryMeta.meta(filter);
// Triggers `onReceivableAgingViewed` event. // Triggers `onReceivableAgingViewed` event.
await this.eventPublisher.emitAsync( await this.eventPublisher.emitAsync(
events.reports.onReceivableAgingViewed, events.reports.onReceivableAgingViewed,

View File

@@ -14,7 +14,6 @@ import { ARAgingSummaryRepository } from './ARAgingSummaryRepository';
import { Customer } from '@/modules/Customers/models/Customer'; import { Customer } from '@/modules/Customers/models/Customer';
import { SaleInvoice } from '@/modules/SaleInvoices/models/SaleInvoice'; import { SaleInvoice } from '@/modules/SaleInvoices/models/SaleInvoice';
import { ARAgingSummaryQueryDto } from './ARAgingSummaryQuery.dto'; import { ARAgingSummaryQueryDto } from './ARAgingSummaryQuery.dto';
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
export class ARAgingSummarySheet extends AgingSummaryReport { export class ARAgingSummarySheet extends AgingSummaryReport {
readonly query: ARAgingSummaryQueryDto; readonly query: ARAgingSummaryQueryDto;
@@ -33,19 +32,16 @@ export class ARAgingSummarySheet extends AgingSummaryReport {
* Constructor method. * Constructor method.
* @param {ARAgingSummaryQueryDto} query - Query * @param {ARAgingSummaryQueryDto} query - Query
* @param {ARAgingSummaryRepository} repository - Repository. * @param {ARAgingSummaryRepository} repository - Repository.
* @param {IFinancialReportMeta} meta - Report meta.
*/ */
constructor( constructor(
query: ARAgingSummaryQueryDto, query: ARAgingSummaryQueryDto,
repository: ARAgingSummaryRepository, repository: ARAgingSummaryRepository,
meta: IFinancialReportMeta,
) { ) {
super(); super();
this.query = query; this.query = query;
this.repository = repository; this.repository = repository;
this.numberFormat = this.query.numberFormat; this.numberFormat = this.query.numberFormat;
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
this.overdueInvoicesByContactId = this.overdueInvoicesByContactId =
this.repository.overdueInvoicesByContactId; this.repository.overdueInvoicesByContactId;

View File

@@ -13,7 +13,7 @@ export class AgingSummaryMeta {
*/ */
public async meta(query: IAgingSummaryQuery): Promise<IAgingSummaryMeta> { public async meta(query: IAgingSummaryQuery): Promise<IAgingSummaryMeta> {
const commonMeta = await this.financialSheetMeta.meta(); const commonMeta = await this.financialSheetMeta.meta();
const formattedAsDate = moment(query.asDate).format(commonMeta.dateFormat); const formattedAsDate = moment(query.asDate).format('YYYY/MM/DD');
const formattedDateRange = `As ${formattedAsDate}`; const formattedDateRange = `As ${formattedAsDate}`;
return { return {

View File

@@ -19,7 +19,7 @@ import { BalanceSheetFiltering } from './BalanceSheetFiltering';
import { BalanceSheetNetIncome } from './BalanceSheetNetIncome'; import { BalanceSheetNetIncome } from './BalanceSheetNetIncome';
import { BalanceSheetAggregators } from './BalanceSheetAggregators'; import { BalanceSheetAggregators } from './BalanceSheetAggregators';
import { BalanceSheetAccounts } from './BalanceSheetAccounts'; import { BalanceSheetAccounts } from './BalanceSheetAccounts';
import { INumberFormatQuery, IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types'; import { INumberFormatQuery } from '../../types/Report.types';
import { FinancialSheet } from '../../common/FinancialSheet'; import { FinancialSheet } from '../../common/FinancialSheet';
export class BalanceSheet extends R.pipe( export class BalanceSheet extends R.pipe(
@@ -66,23 +66,21 @@ export class BalanceSheet extends R.pipe(
/** /**
* Constructor method. * Constructor method.
* @param {IBalanceSheetQuery} query - * @param {IBalanceSheetQuery} query -
* @param {BalanceSheetRepository} repository - * @param {IAccount[]} accounts -
* @param {I18nService} i18n - * @param {string} baseCurrency -
* @param {IFinancialReportMeta} meta -
*/ */
constructor( constructor(
query: IBalanceSheetQuery, query: IBalanceSheetQuery,
repository: BalanceSheetRepository, repository: BalanceSheetRepository,
baseCurrency: string,
i18n: I18nService, i18n: I18nService,
meta: IFinancialReportMeta,
) { ) {
super(); super();
this.query = new BalanceSheetQuery(query); this.query = new BalanceSheetQuery(query);
this.repository = repository; this.repository = repository;
this.baseCurrency = meta.baseCurrency; this.baseCurrency = baseCurrency;
this.numberFormat = this.query.query.numberFormat; this.numberFormat = this.query.query.numberFormat;
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
this.i18n = i18n; this.i18n = i18n;
} }

View File

@@ -40,19 +40,19 @@ export class BalanceSheetInjectable {
// Loads all resources. // Loads all resources.
await this.balanceSheetRepository.asyncInitialize(filter); await this.balanceSheetRepository.asyncInitialize(filter);
// Balance sheet meta first to get date format.
const meta = await this.balanceSheetMeta.meta(filter);
// Balance sheet report instance. // Balance sheet report instance.
const balanceSheetInstanace = new BalanceSheet( const balanceSheetInstanace = new BalanceSheet(
filter, filter,
this.balanceSheetRepository, this.balanceSheetRepository,
tenantMetadata.baseCurrency,
this.i18n, this.i18n,
{ baseCurrency: tenantMetadata.baseCurrency, dateFormat: meta.dateFormat },
); );
// Balance sheet data. // Balance sheet data.
const data = balanceSheetInstanace.reportData(); const data = balanceSheetInstanace.reportData();
// Balance sheet meta.
const meta = await this.balanceSheetMeta.meta(filter);
// Triggers `onBalanceSheetViewed` event. // Triggers `onBalanceSheetViewed` event.
await this.eventPublisher.emitAsync(events.reports.onBalanceSheetViewed, { await this.eventPublisher.emitAsync(events.reports.onBalanceSheetViewed, {
query, query,

View File

@@ -13,7 +13,7 @@ export class BalanceSheetMetaInjectable {
*/ */
public async meta(query: IBalanceSheetQuery): Promise<IBalanceSheetMeta> { public async meta(query: IBalanceSheetQuery): Promise<IBalanceSheetMeta> {
const commonMeta = await this.financialSheetMeta.meta(); const commonMeta = await this.financialSheetMeta.meta();
const formattedAsDate = moment(query.toDate).format(commonMeta.dateFormat); const formattedAsDate = moment(query.toDate).format('YYYY/MM/DD');
const formattedDateRange = `As ${formattedAsDate}`; const formattedDateRange = `As ${formattedAsDate}`;
const sheetName = 'Balance Sheet Statement'; const sheetName = 'Balance Sheet Statement';

View File

@@ -27,7 +27,7 @@ import { DISPLAY_COLUMNS_BY } from './constants';
import { FinancialSheetStructure } from '../../common/FinancialSheetStructure'; import { FinancialSheetStructure } from '../../common/FinancialSheetStructure';
import { Account } from '@/modules/Accounts/models/Account.model'; import { Account } from '@/modules/Accounts/models/Account.model';
import { ILedger } from '@/modules/Ledger/types/Ledger.types'; import { ILedger } from '@/modules/Ledger/types/Ledger.types';
import { INumberFormatQuery, IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types'; import { INumberFormatQuery } from '../../types/Report.types';
import { transformToMapBy } from '@/utils/transform-to-map-by'; import { transformToMapBy } from '@/utils/transform-to-map-by';
import { accumSum } from '@/utils/accum-sum'; import { accumSum } from '@/utils/accum-sum';
import { ModelObject } from 'objection'; import { ModelObject } from 'objection';
@@ -62,12 +62,12 @@ export class CashFlowStatement extends R.pipe(
cashLedger: ILedger, cashLedger: ILedger,
netIncomeLedger: ILedger, netIncomeLedger: ILedger,
query: ICashFlowStatementQuery, query: ICashFlowStatementQuery,
baseCurrency: string,
i18n: I18nService, i18n: I18nService,
meta: IFinancialReportMeta,
) { ) {
super(); super();
this.baseCurrency = meta.baseCurrency; this.baseCurrency = baseCurrency;
this.i18n = i18n; this.i18n = i18n;
this.ledger = ledger; this.ledger = ledger;
this.cashLedger = cashLedger; this.cashLedger = cashLedger;
@@ -76,7 +76,6 @@ export class CashFlowStatement extends R.pipe(
this.accountsByRootType = transformToMapBy(accounts, 'accountRootType'); this.accountsByRootType = transformToMapBy(accounts, 'accountRootType');
this.query = query; this.query = query;
this.numberFormat = this.query.numberFormat; this.numberFormat = this.query.numberFormat;
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
this.dateRangeSet = []; this.dateRangeSet = [];
this.comparatorDateType = this.comparatorDateType =
query.displayColumnsType === 'total' ? 'day' : query.displayColumnsBy; query.displayColumnsType === 'total' ? 'day' : query.displayColumnsBy;

View File

@@ -85,9 +85,6 @@ export class CashFlowStatementService {
const cashLedger = Ledger.fromTransactions(cashAtBeginningTransactions); const cashLedger = Ledger.fromTransactions(cashAtBeginningTransactions);
const netIncomeLedger = Ledger.fromTransactions(netIncome); const netIncomeLedger = Ledger.fromTransactions(netIncome);
// Retrieve the cashflow sheet meta first to get date format.
const meta = await this.cashflowSheetMeta.meta(filter);
// Cash flow statement. // Cash flow statement.
const cashFlowInstance = new CashFlowStatement( const cashFlowInstance = new CashFlowStatement(
accounts, accounts,
@@ -95,9 +92,11 @@ export class CashFlowStatementService {
cashLedger, cashLedger,
netIncomeLedger, netIncomeLedger,
filter, filter,
tenant.metadata.baseCurrency,
this.i18n, this.i18n,
{ baseCurrency: tenant.metadata.baseCurrency, dateFormat: meta.dateFormat },
); );
// Retrieve the cashflow sheet meta.
const meta = await this.cashflowSheetMeta.meta(filter);
return { return {
data: cashFlowInstance.reportData(), data: cashFlowInstance.reportData(),

View File

@@ -23,8 +23,8 @@ export class CashflowSheetMeta {
query: ICashFlowStatementQuery, query: ICashFlowStatementQuery,
): Promise<ICashFlowStatementMeta> { ): Promise<ICashFlowStatementMeta> {
const meta = await this.financialSheetMeta.meta(); const meta = await this.financialSheetMeta.meta();
const formattedToDate = moment(query.toDate).format(meta.dateFormat); const formattedToDate = moment(query.toDate).format('YYYY/MM/DD');
const formattedFromDate = moment(query.fromDate).format(meta.dateFormat); const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
const fromLabel = this.i18n.t('cash_flow_statement.from_date'); const fromLabel = this.i18n.t('cash_flow_statement.from_date');
const toLabel = this.i18n.t('cash_flow_statement.to_date'); const toLabel = this.i18n.t('cash_flow_statement.to_date');
const formattedDateRange = `${fromLabel} ${formattedFromDate} | ${toLabel} ${formattedToDate}`; const formattedDateRange = `${fromLabel} ${formattedFromDate} | ${toLabel} ${formattedToDate}`;

View File

@@ -8,7 +8,7 @@ import {
import { ContactBalanceSummaryReport } from '../ContactBalanceSummary/ContactBalanceSummary'; import { ContactBalanceSummaryReport } from '../ContactBalanceSummary/ContactBalanceSummary';
import { ILedger } from '@/modules/Ledger/types/Ledger.types'; import { ILedger } from '@/modules/Ledger/types/Ledger.types';
import { ModelObject } from 'objection'; import { ModelObject } from 'objection';
import { INumberFormatQuery, IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types'; import { INumberFormatQuery } from '../../types/Report.types';
import { Customer } from '@/modules/Customers/models/Customer'; import { Customer } from '@/modules/Customers/models/Customer';
export class CustomerBalanceSummaryReport extends ContactBalanceSummaryReport { export class CustomerBalanceSummaryReport extends ContactBalanceSummaryReport {
@@ -23,22 +23,21 @@ export class CustomerBalanceSummaryReport extends ContactBalanceSummaryReport {
* @param {IJournalPoster} receivableLedger * @param {IJournalPoster} receivableLedger
* @param {ICustomer[]} customers * @param {ICustomer[]} customers
* @param {ICustomerBalanceSummaryQuery} filter * @param {ICustomerBalanceSummaryQuery} filter
* @param {IFinancialReportMeta} meta * @param {string} baseCurrency
*/ */
constructor( constructor(
ledger: ILedger, ledger: ILedger,
customers: ModelObject<Customer>[], customers: ModelObject<Customer>[],
filter: ICustomerBalanceSummaryQuery, filter: ICustomerBalanceSummaryQuery,
meta: IFinancialReportMeta, baseCurrency: string
) { ) {
super(); super();
this.ledger = ledger; this.ledger = ledger;
this.baseCurrency = meta.baseCurrency; this.baseCurrency = baseCurrency;
this.customers = customers; this.customers = customers;
this.filter = filter; this.filter = filter;
this.numberFormat = this.filter.numberFormat; this.numberFormat = this.filter.numberFormat;
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
} }
/** /**

View File

@@ -19,7 +19,7 @@ export class CustomerBalanceSummaryMeta {
query: ICustomerBalanceSummaryQuery, query: ICustomerBalanceSummaryQuery,
): Promise<ICustomerBalanceSummaryMeta> { ): Promise<ICustomerBalanceSummaryMeta> {
const commonMeta = await this.financialSheetMeta.meta(); const commonMeta = await this.financialSheetMeta.meta();
const formattedAsDate = moment(query.asDate).format(commonMeta.dateFormat); const formattedAsDate = moment(query.asDate).format('YYYY/MM/DD');
const formattedDateRange = `As ${formattedAsDate}`; const formattedDateRange = `As ${formattedAsDate}`;
return { return {

View File

@@ -63,16 +63,15 @@ export class CustomerBalanceSummaryService {
// Ledger query. // Ledger query.
const ledger = new Ledger(customersEntries); const ledger = new Ledger(customersEntries);
// Retrieve the customer balance summary meta first to get date format.
const meta = await this.customerBalanceSummaryMeta.meta(filter);
// Report instance. // Report instance.
const report = new CustomerBalanceSummaryReport( const report = new CustomerBalanceSummaryReport(
ledger, ledger,
customers, customers,
filter, filter,
{ baseCurrency: tenantMetadata.baseCurrency, dateFormat: meta.dateFormat }, tenantMetadata.baseCurrency,
); );
// Retrieve the customer balance summary meta.
const meta = await this.customerBalanceSummaryMeta.meta(filter);
// Triggers `onCustomerBalanceSummaryViewed` event. // Triggers `onCustomerBalanceSummaryViewed` event.
await this.eventPublisher.emitAsync( await this.eventPublisher.emitAsync(

View File

@@ -19,7 +19,6 @@ import { Account } from '@/modules/Accounts/models/Account.model';
import { ModelObject } from 'objection'; import { ModelObject } from 'objection';
import { flatToNestedArray } from '@/utils/flat-to-nested-array'; import { flatToNestedArray } from '@/utils/flat-to-nested-array';
import { getTransactionTypeLabel } from '@/modules/BankingTransactions/utils'; import { getTransactionTypeLabel } from '@/modules/BankingTransactions/utils';
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
export class GeneralLedgerSheet extends R.compose(FinancialSheetStructure)( export class GeneralLedgerSheet extends R.compose(FinancialSheetStructure)(
FinancialSheet, FinancialSheet,
@@ -34,21 +33,18 @@ export class GeneralLedgerSheet extends R.compose(FinancialSheetStructure)(
* @param {IGeneralLedgerSheetQuery} query - * @param {IGeneralLedgerSheetQuery} query -
* @param {GeneralLedgerRepository} repository - * @param {GeneralLedgerRepository} repository -
* @param {I18nService} i18n - * @param {I18nService} i18n -
* @param {IFinancialReportMeta} meta -
*/ */
constructor( constructor(
query: IGeneralLedgerSheetQuery, query: IGeneralLedgerSheetQuery,
repository: GeneralLedgerRepository, repository: GeneralLedgerRepository,
i18n: I18nService, i18n: I18nService,
meta: IFinancialReportMeta,
) { ) {
super(); super();
this.query = query; this.query = query;
this.numberFormat = this.query.numberFormat; this.numberFormat = this.query.numberFormat;
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
this.repository = repository; this.repository = repository;
this.baseCurrency = meta.baseCurrency; this.baseCurrency = this.repository.tenant.metadata.baseCurrency;
this.i18n = i18n; this.i18n = i18n;
} }
@@ -91,7 +87,7 @@ export class GeneralLedgerSheet extends R.compose(FinancialSheetStructure)(
return { return {
id: entry.id, id: entry.id,
date: entry.date, date: entry.date,
dateFormatted: moment(entry.date).format(this.dateFormat), dateFormatted: moment(entry.date).format('YYYY MMM DD'),
referenceType: entry.transactionType, referenceType: entry.transactionType,
referenceId: entry.transactionId, referenceId: entry.transactionId,

View File

@@ -6,7 +6,6 @@ export interface IGeneralLedgerSheetQuery {
toDate: Date | string; toDate: Date | string;
basis: string; basis: string;
numberFormat: IGeneralLedgerNumberFormat; numberFormat: IGeneralLedgerNumberFormat;
dateFormat?: string;
noneTransactions: boolean; noneTransactions: boolean;
accountsIds: number[]; accountsIds: number[];
branchesIds?: number[]; branchesIds?: number[];

View File

@@ -19,8 +19,8 @@ export class GeneralLedgerMeta {
): Promise<IGeneralLedgerMeta> { ): Promise<IGeneralLedgerMeta> {
const commonMeta = await this.financialSheetMeta.meta(); const commonMeta = await this.financialSheetMeta.meta();
const formattedToDate = moment(query.toDate).format(commonMeta.dateFormat); const formattedToDate = moment(query.toDate).format('YYYY/MM/DD');
const formattedFromDate = moment(query.fromDate).format(commonMeta.dateFormat); const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`; const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`;
return { return {

View File

@@ -37,19 +37,18 @@ export class GeneralLedgerService {
this.generalLedgerRepository.setFilter(filter); this.generalLedgerRepository.setFilter(filter);
await this.generalLedgerRepository.asyncInitialize(); await this.generalLedgerRepository.asyncInitialize();
// Retrieve general ledger report metadata first to get the date format.
const meta = await this.generalLedgerMeta.meta(filter);
// General ledger report instance. // General ledger report instance.
const generalLedgerInstance = new GeneralLedgerSheet( const generalLedgerInstance = new GeneralLedgerSheet(
filter, filter,
this.generalLedgerRepository, this.generalLedgerRepository,
this.i18n, this.i18n,
{ baseCurrency: meta.baseCurrency, dateFormat: meta.dateFormat },
); );
// Retrieve general ledger report data. // Retrieve general ledger report data.
const reportData = generalLedgerInstance.reportData(); const reportData = generalLedgerInstance.reportData();
// Retrieve general ledger report metadata.
const meta = await this.generalLedgerMeta.meta(filter);
// Triggers `onGeneralLedgerViewed` event. // Triggers `onGeneralLedgerViewed` event.
await this.eventEmitter.emitAsync(events.reports.onGeneralLedgerViewed, {}); await this.eventEmitter.emitAsync(events.reports.onGeneralLedgerViewed, {});

View File

@@ -8,7 +8,6 @@ import { InventoryDetails } from './InventoryItemDetails';
import { InventoryItemDetailsRepository } from './InventoryItemDetailsRepository'; import { InventoryItemDetailsRepository } from './InventoryItemDetailsRepository';
import { InventoryDetailsMetaInjectable } from './InventoryItemDetailsMeta'; import { InventoryDetailsMetaInjectable } from './InventoryItemDetailsMeta';
import { getInventoryItemDetailsDefaultQuery } from './constant'; import { getInventoryItemDetailsDefaultQuery } from './constant';
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
@Injectable() @Injectable()
export class InventoryDetailsService { export class InventoryDetailsService {
@@ -16,7 +15,6 @@ export class InventoryDetailsService {
private readonly inventoryItemDetailsRepository: InventoryItemDetailsRepository, private readonly inventoryItemDetailsRepository: InventoryItemDetailsRepository,
private readonly inventoryDetailsMeta: InventoryDetailsMetaInjectable, private readonly inventoryDetailsMeta: InventoryDetailsMetaInjectable,
private readonly i18n: I18nService, private readonly i18n: I18nService,
private readonly tenancyContext: TenancyContext,
) {} ) {}
/** /**
@@ -36,16 +34,13 @@ export class InventoryDetailsService {
this.inventoryItemDetailsRepository.setFilter(filter); this.inventoryItemDetailsRepository.setFilter(filter);
await this.inventoryItemDetailsRepository.asyncInit(); await this.inventoryItemDetailsRepository.asyncInit();
// Retrieve the meta first to get date format.
const meta = await this.inventoryDetailsMeta.meta(query);
// Inventory details report mapper. // Inventory details report mapper.
const inventoryDetailsInstance = new InventoryDetails( const inventoryDetailsInstance = new InventoryDetails(
filter, filter,
this.inventoryItemDetailsRepository, this.inventoryItemDetailsRepository,
this.i18n, this.i18n,
{ baseCurrency: meta.baseCurrency, dateFormat: meta.dateFormat },
); );
const meta = await this.inventoryDetailsMeta.meta(query);
return { return {
data: inventoryDetailsInstance.reportData(), data: inventoryDetailsInstance.reportData(),

View File

@@ -17,8 +17,6 @@ import { Item } from '@/modules/Items/models/Item';
import { import {
IFormatNumberSettings, IFormatNumberSettings,
INumberFormatQuery, INumberFormatQuery,
IFinancialReportMeta,
DEFAULT_REPORT_META,
} from '../../types/Report.types'; } from '../../types/Report.types';
import { InventoryTransaction } from '@/modules/InventoryCost/models/InventoryTransaction'; import { InventoryTransaction } from '@/modules/InventoryCost/models/InventoryTransaction';
import { InventoryItemDetailsRepository } from './InventoryItemDetailsRepository'; import { InventoryItemDetailsRepository } from './InventoryItemDetailsRepository';
@@ -37,13 +35,11 @@ export class InventoryDetails extends FinancialSheet {
* Constructor method. * Constructor method.
* @param {InventoryItemDetailsRepository} repository - The repository. * @param {InventoryItemDetailsRepository} repository - The repository.
* @param {I18nService} i18n - The i18n service. * @param {I18nService} i18n - The i18n service.
* @param {IFinancialReportMeta} meta - Report meta.
*/ */
constructor( constructor(
filter: IInventoryDetailsQuery, filter: IInventoryDetailsQuery,
repository: InventoryItemDetailsRepository, repository: InventoryItemDetailsRepository,
i18n: I18nService, i18n: I18nService,
meta: IFinancialReportMeta,
) { ) {
super(); super();
@@ -52,7 +48,6 @@ export class InventoryDetails extends FinancialSheet {
this.query = filter; this.query = filter;
this.numberFormat = this.query.numberFormat; this.numberFormat = this.query.numberFormat;
this.i18n = i18n; this.i18n = i18n;
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
} }
/** /**
@@ -94,7 +89,7 @@ export class InventoryDetails extends FinancialSheet {
*/ */
public getDateMeta(date: Date | string): IInventoryDetailsDate { public getDateMeta(date: Date | string): IInventoryDetailsDate {
return { return {
formattedDate: moment(date).format(this.dateFormat), formattedDate: moment(date).format('YYYY-MM-DD'),
date: moment(date).toDate(), date: moment(date).toDate(),
}; };
} }

View File

@@ -19,8 +19,8 @@ export class InventoryDetailsMetaInjectable {
): Promise<IInventoryItemDetailMeta> { ): Promise<IInventoryItemDetailMeta> {
const commonMeta = await this.financialSheetMeta.meta(); const commonMeta = await this.financialSheetMeta.meta();
const formattedFromDate = moment(query.fromDate).format(commonMeta.dateFormat); const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
const formattedToDay = moment(query.toDate).format(commonMeta.dateFormat); const formattedToDay = moment(query.toDate).format('YYYY/MM/DD');
const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDay}`; const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDay}`;
const sheetName = 'Inventory Item Details'; const sheetName = 'Inventory Item Details';

View File

@@ -12,7 +12,6 @@ import { InventoryCostLotTracker } from '@/modules/InventoryCost/models/Inventor
import { FinancialSheet } from '../../common/FinancialSheet'; import { FinancialSheet } from '../../common/FinancialSheet';
import { InventoryValuationSheetRepository } from './InventoryValuationSheetRepository'; import { InventoryValuationSheetRepository } from './InventoryValuationSheetRepository';
import { allPassedConditionsPass } from '@/utils/all-conditions-passed'; import { allPassedConditionsPass } from '@/utils/all-conditions-passed';
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
export class InventoryValuationSheet extends FinancialSheet { export class InventoryValuationSheet extends FinancialSheet {
readonly query: IInventoryValuationReportQuery; readonly query: IInventoryValuationReportQuery;
@@ -22,19 +21,16 @@ export class InventoryValuationSheet extends FinancialSheet {
* Constructor method. * Constructor method.
* @param {IInventoryValuationReportQuery} query - Inventory valuation query. * @param {IInventoryValuationReportQuery} query - Inventory valuation query.
* @param {InventoryValuationSheetRepository} repository - Inventory valuation sheet repository. * @param {InventoryValuationSheetRepository} repository - Inventory valuation sheet repository.
* @param {IFinancialReportMeta} meta - Report meta.
*/ */
constructor( constructor(
query: IInventoryValuationReportQuery, query: IInventoryValuationReportQuery,
repository: InventoryValuationSheetRepository, repository: InventoryValuationSheetRepository,
meta: IFinancialReportMeta,
) { ) {
super(); super();
this.query = query; this.query = query;
this.repository = repository; this.repository = repository;
this.numberFormat = this.query.numberFormat; this.numberFormat = this.query.numberFormat;
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
} }
/** /**

View File

@@ -18,7 +18,7 @@ export class InventoryValuationMetaInjectable {
query: IInventoryValuationReportQuery, query: IInventoryValuationReportQuery,
): Promise<IInventoryValuationSheetMeta> { ): Promise<IInventoryValuationSheetMeta> {
const commonMeta = await this.financialSheetMeta.meta(); const commonMeta = await this.financialSheetMeta.meta();
const formattedAsDate = moment(query.asDate).format(commonMeta.dateFormat); const formattedAsDate = moment(query.asDate).format('YYYY/MM/DD');
const formattedDateRange = `As ${formattedAsDate}`; const formattedDateRange = `As ${formattedAsDate}`;
return { return {

View File

@@ -34,17 +34,16 @@ export class InventoryValuationSheetService {
this.inventoryValuationSheetRepository.setFilter(filter); this.inventoryValuationSheetRepository.setFilter(filter);
await this.inventoryValuationSheetRepository.asyncInit(); await this.inventoryValuationSheetRepository.asyncInit();
// Retrieves the inventorty valuation meta first to get date format.
const meta = await this.inventoryValuationMeta.meta(filter);
const inventoryValuationInstance = new InventoryValuationSheet( const inventoryValuationInstance = new InventoryValuationSheet(
filter, filter,
this.inventoryValuationSheetRepository, this.inventoryValuationSheetRepository,
{ baseCurrency: meta.baseCurrency, dateFormat: meta.dateFormat },
); );
// Retrieve the inventory valuation report data. // Retrieve the inventory valuation report data.
const inventoryValuationData = inventoryValuationInstance.reportData(); const inventoryValuationData = inventoryValuationInstance.reportData();
// Retrieves the inventorty valuation meta.
const meta = await this.inventoryValuationMeta.meta(filter);
// Triggers `onInventoryValuationViewed` event. // Triggers `onInventoryValuationViewed` event.
await this.eventPublisher.emitAsync( await this.eventPublisher.emitAsync(
events.reports.onInventoryValuationViewed, events.reports.onInventoryValuationViewed,

View File

@@ -11,7 +11,6 @@ import { FinancialSheet } from '../../common/FinancialSheet';
import { JournalSheetRepository } from './JournalSheetRepository'; import { JournalSheetRepository } from './JournalSheetRepository';
import { ILedgerEntry } from '@/modules/Ledger/types/Ledger.types'; import { ILedgerEntry } from '@/modules/Ledger/types/Ledger.types';
import { getTransactionTypeLabel } from '@/modules/BankingTransactions/utils'; import { getTransactionTypeLabel } from '@/modules/BankingTransactions/utils';
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
export class JournalSheet extends FinancialSheet { export class JournalSheet extends FinancialSheet {
readonly query: IJournalReportQuery; readonly query: IJournalReportQuery;
@@ -23,24 +22,20 @@ export class JournalSheet extends FinancialSheet {
* @param {IJournalReportQuery} query - * @param {IJournalReportQuery} query -
* @param {JournalSheetRepository} repository - * @param {JournalSheetRepository} repository -
* @param {I18nService} i18n - * @param {I18nService} i18n -
* @param {IFinancialReportMeta} meta -
*/ */
constructor( constructor(
query: IJournalReportQuery, query: IJournalReportQuery,
repository: JournalSheetRepository, repository: JournalSheetRepository,
i18n: I18nService, i18n: I18nService,
meta: IFinancialReportMeta,
) { ) {
super(); super();
this.query = query; this.query = query;
this.repository = repository; this.repository = repository;
this.baseCurrency = meta.baseCurrency;
this.numberFormat = { this.numberFormat = {
...this.numberFormat, ...this.numberFormat,
...this.query.numberFormat, ...this.query.numberFormat,
}; };
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
this.i18n = i18n; this.i18n = i18n;
} }
@@ -99,7 +94,7 @@ export class JournalSheet extends FinancialSheet {
return { return {
date: moment(groupEntry.date).toDate(), date: moment(groupEntry.date).toDate(),
dateFormatted: moment(groupEntry.date).format(this.dateFormat), dateFormatted: moment(groupEntry.date).format('YYYY MMM DD'),
transactionType: groupEntry.transactionType, transactionType: groupEntry.transactionType,
referenceId: groupEntry.transactionId, referenceId: groupEntry.transactionId,

View File

@@ -8,7 +8,6 @@ export interface IJournalReportQuery {
noCents: boolean; noCents: boolean;
divideOn1000: boolean; divideOn1000: boolean;
}; };
dateFormat?: string;
transactionType: string; transactionType: string;
transactionId: string; transactionId: string;

View File

@@ -17,8 +17,8 @@ export class JournalSheetMeta {
): Promise<IJournalSheetMeta> { ): Promise<IJournalSheetMeta> {
const common = await this.financialSheetMeta.meta(); const common = await this.financialSheetMeta.meta();
const formattedToDate = moment(query.toDate).format(common.dateFormat); const formattedToDate = moment(query.toDate).format('YYYY/MM/DD');
const formattedFromDate = moment(query.fromDate).format(common.dateFormat); const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`; const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`;
return { return {

View File

@@ -30,19 +30,18 @@ export class JournalSheetService {
this.journalRepository.setFilter(query); this.journalRepository.setFilter(query);
await this.journalRepository.load(); await this.journalRepository.load();
// Retrieve the journal sheet meta first to get the date format.
const meta = await this.journalSheetMeta.meta(filter);
// Journal report instance. // Journal report instance.
const journalSheetInstance = new JournalSheet( const journalSheetInstance = new JournalSheet(
filter, filter,
this.journalRepository, this.journalRepository,
this.i18n, this.i18n,
{ baseCurrency: meta.baseCurrency, dateFormat: meta.dateFormat },
); );
// Retrieve journal report columns. // Retrieve journal report columns.
const journalSheetData = journalSheetInstance.reportData(); const journalSheetData = journalSheetInstance.reportData();
// Retrieve the journal sheet meta.
const meta = await this.journalSheetMeta.meta(filter);
// Triggers `onJournalViewed` event. // Triggers `onJournalViewed` event.
await this.eventPublisher.emitAsync(events.reports.onJournalViewed, { await this.eventPublisher.emitAsync(events.reports.onJournalViewed, {
query, query,

View File

@@ -28,7 +28,6 @@ import { FinancialSheetStructure } from '../../common/FinancialSheetStructure';
import { FinancialSheet } from '../../common/FinancialSheet'; import { FinancialSheet } from '../../common/FinancialSheet';
import { Account } from '@/modules/Accounts/models/Account.model'; import { Account } from '@/modules/Accounts/models/Account.model';
import { flatToNestedArray } from '@/utils/flat-to-nested-array'; import { flatToNestedArray } from '@/utils/flat-to-nested-array';
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
export default class ProfitLossSheet extends R.pipe( export default class ProfitLossSheet extends R.pipe(
ProfitLossSheetPreviousYear, ProfitLossSheetPreviousYear,
@@ -72,24 +71,20 @@ export default class ProfitLossSheet extends R.pipe(
/** /**
* Constructor method. * Constructor method.
* @param {ProfitLossSheetRepository} repository -
* @param {IProfitLossSheetQuery} query - * @param {IProfitLossSheetQuery} query -
* @param {I18nService} i18n - * @param {IAccount[]} accounts -
* @param {IFinancialReportMeta} meta - * @param {IJournalPoster} transactionsJournal -
*/ */
constructor( constructor(
repository: ProfitLossSheetRepository, repository: ProfitLossSheetRepository,
query: IProfitLossSheetQuery, query: IProfitLossSheetQuery,
i18n: I18nService, i18n: I18nService,
meta: IFinancialReportMeta,
) { ) {
super(); super();
this.query = new ProfitLossSheetQuery(query); this.query = new ProfitLossSheetQuery(query);
this.repository = repository; this.repository = repository;
this.baseCurrency = meta.baseCurrency;
this.numberFormat = this.query.query.numberFormat; this.numberFormat = this.query.query.numberFormat;
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
this.i18n = i18n; this.i18n = i18n;
} }

View File

@@ -19,8 +19,8 @@ export class ProfitLossSheetMeta {
query: IProfitLossSheetQuery, query: IProfitLossSheetQuery,
): Promise<IProfitLossSheetMeta> { ): Promise<IProfitLossSheetMeta> {
const commonMeta = await this.financialSheetMeta.meta(); const commonMeta = await this.financialSheetMeta.meta();
const formattedToDate = moment(query.toDate).format(commonMeta.dateFormat); const formattedToDate = moment(query.toDate).format('YYYY/MM/DD');
const formattedFromDate = moment(query.fromDate).format(commonMeta.dateFormat); const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`; const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`;
const sheetName = 'Cashflow Statement'; const sheetName = 'Cashflow Statement';

View File

@@ -40,19 +40,18 @@ export class ProfitLossSheetService {
this.profitLossRepository.setFilter(filter); this.profitLossRepository.setFilter(filter);
await this.profitLossRepository.asyncInitialize(); await this.profitLossRepository.asyncInitialize();
// Retrieve the profit/loss sheet meta first to get date format.
const meta = await this.profitLossSheetMeta.meta(filter);
// Profit/Loss report instance. // Profit/Loss report instance.
const profitLossInstance = new ProfitLossSheet( const profitLossInstance = new ProfitLossSheet(
this.profitLossRepository, this.profitLossRepository,
filter, filter,
this.i18nService, this.i18nService,
{ baseCurrency: meta.baseCurrency, dateFormat: meta.dateFormat },
); );
// Profit/loss report data and columns. // Profit/loss report data and columns.
const data = profitLossInstance.reportData(); const data = profitLossInstance.reportData();
// Retrieve the profit/loss sheet meta.
const meta = await this.profitLossSheetMeta.meta(filter);
// Triggers `onProfitLossSheetViewed` event. // Triggers `onProfitLossSheetViewed` event.
await this.eventPublisher.emitAsync( await this.eventPublisher.emitAsync(
events.reports.onProfitLossSheetViewed, events.reports.onProfitLossSheetViewed,

View File

@@ -73,17 +73,17 @@ export class PurchasesByItemsService {
// Filter the date range of the sheet. // Filter the date range of the sheet.
builder.modify('filterDateRange', filter.fromDate, filter.toDate); builder.modify('filterDateRange', filter.fromDate, filter.toDate);
}); });
// Retrieve the purchases by items meta first to get date format.
const meta = await this.purchasesByItemsMeta.meta(query);
const purchasesByItemsInstance = new PurchasesByItems( const purchasesByItemsInstance = new PurchasesByItems(
filter, filter,
inventoryItems, inventoryItems,
inventoryTransactions, inventoryTransactions,
{ baseCurrency: tenantMetadata.baseCurrency, dateFormat: meta.dateFormat }, tenantMetadata.baseCurrency,
); );
const purchasesByItemsData = purchasesByItemsInstance.reportData(); const purchasesByItemsData = purchasesByItemsInstance.reportData();
// Retrieve the purchases by items meta.
const meta = await this.purchasesByItemsMeta.meta(query);
// Triggers `onPurchasesByItemViewed` event. // Triggers `onPurchasesByItemViewed` event.
await this.eventPublisher.emitAsync( await this.eventPublisher.emitAsync(
events.reports.onPurchasesByItemViewed, events.reports.onPurchasesByItemViewed,

View File

@@ -11,7 +11,6 @@ import { FinancialSheet } from '../../common/FinancialSheet';
import { transformToMapBy } from '@/utils/transform-to-map-by'; import { transformToMapBy } from '@/utils/transform-to-map-by';
import { Item } from '@/modules/Items/models/Item'; import { Item } from '@/modules/Items/models/Item';
import { InventoryTransaction } from '@/modules/InventoryCost/models/InventoryTransaction'; import { InventoryTransaction } from '@/modules/InventoryCost/models/InventoryTransaction';
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
export class PurchasesByItems extends FinancialSheet{ export class PurchasesByItems extends FinancialSheet{
readonly baseCurrency: string; readonly baseCurrency: string;
@@ -30,15 +29,14 @@ export class PurchasesByItems extends FinancialSheet{
query: IPurchasesByItemsReportQuery, query: IPurchasesByItemsReportQuery,
items: Item[], items: Item[],
itemsTransactions: InventoryTransaction[], itemsTransactions: InventoryTransaction[],
meta: IFinancialReportMeta, baseCurrency: string
) { ) {
super(); super();
this.baseCurrency = meta.baseCurrency; this.baseCurrency = baseCurrency;
this.items = items; this.items = items;
this.itemsTransactions = transformToMapBy(itemsTransactions, 'itemId'); this.itemsTransactions = transformToMapBy(itemsTransactions, 'itemId');
this.query = query; this.query = query;
this.numberFormat = this.query.numberFormat; this.numberFormat = this.query.numberFormat;
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
} }
/** /**

View File

@@ -21,8 +21,8 @@ export class PurchasesByItemsMeta {
query: IPurchasesByItemsReportQuery query: IPurchasesByItemsReportQuery
): Promise<IPurchasesByItemsSheetMeta> { ): Promise<IPurchasesByItemsSheetMeta> {
const commonMeta = await this.financialSheetMetaModel.meta(); const commonMeta = await this.financialSheetMetaModel.meta();
const formattedToDate = moment(query.toDate).format(commonMeta.dateFormat); const formattedToDate = moment(query.toDate).format('YYYY/MM/DD');
const formattedFromDate = moment(query.fromDate).format(commonMeta.dateFormat); const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`; const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`;
return { return {

View File

@@ -12,7 +12,6 @@ import { Item } from '@/modules/Items/models/Item';
import { transformToMap } from '@/utils/transform-to-key'; import { transformToMap } from '@/utils/transform-to-key';
import { allPassedConditionsPass } from '@/utils/all-conditions-passed'; import { allPassedConditionsPass } from '@/utils/all-conditions-passed';
import { InventoryTransaction } from '@/modules/InventoryCost/models/InventoryTransaction'; import { InventoryTransaction } from '@/modules/InventoryCost/models/InventoryTransaction';
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
export class SalesByItemsReport extends FinancialSheet { export class SalesByItemsReport extends FinancialSheet {
readonly baseCurrency: string; readonly baseCurrency: string;
@@ -25,22 +24,21 @@ export class SalesByItemsReport extends FinancialSheet {
* @param {ISalesByItemsReportQuery} query * @param {ISalesByItemsReportQuery} query
* @param {IItem[]} items * @param {IItem[]} items
* @param {IAccountTransaction[]} itemsTransactions * @param {IAccountTransaction[]} itemsTransactions
* @param {IFinancialReportMeta} meta * @param {string} baseCurrency
*/ */
constructor( constructor(
query: ISalesByItemsReportQuery, query: ISalesByItemsReportQuery,
items: Item[], items: Item[],
itemsTransactions: ModelObject<InventoryTransaction>[], itemsTransactions: ModelObject<InventoryTransaction>[],
meta: IFinancialReportMeta, baseCurrency: string,
) { ) {
super(); super();
this.baseCurrency = meta.baseCurrency; this.baseCurrency = baseCurrency;
this.items = items; this.items = items;
this.itemsTransactions = transformToMap(itemsTransactions, 'itemId'); this.itemsTransactions = transformToMap(itemsTransactions, 'itemId');
this.query = query; this.query = query;
this.numberFormat = this.query.numberFormat; this.numberFormat = this.query.numberFormat;
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
} }
/** /**

View File

@@ -18,8 +18,8 @@ export class SalesByItemsMeta {
query: ISalesByItemsReportQuery, query: ISalesByItemsReportQuery,
): Promise<ISalesByItemsSheetMeta> { ): Promise<ISalesByItemsSheetMeta> {
const commonMeta = await this.financialSheetMeta.meta(); const commonMeta = await this.financialSheetMeta.meta();
const formattedToDate = moment(query.toDate).format(commonMeta.dateFormat); const formattedToDate = moment(query.toDate).format('YYYY/MM/DD');
const formattedFromDate = moment(query.fromDate).format(commonMeta.dateFormat); const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`; const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`;
const sheetName = 'Sales By Items'; const sheetName = 'Sales By Items';

View File

@@ -68,17 +68,17 @@ export class SalesByItemsReportService {
// Filter the date range of the sheet. // Filter the date range of the sheet.
builder.modify('filterDateRange', filter.fromDate, filter.toDate); builder.modify('filterDateRange', filter.fromDate, filter.toDate);
}); });
// Retrieve the sales by items meta first to get date format.
const meta = await this.salesByItemsMeta.meta(query);
const sheet = new SalesByItemsReport( const sheet = new SalesByItemsReport(
filter, filter,
inventoryItems, inventoryItems,
inventoryTransactions, inventoryTransactions,
{ baseCurrency: tenantMetadata.baseCurrency, dateFormat: meta.dateFormat }, tenantMetadata.baseCurrency,
); );
const salesByItemsData = sheet.reportData(); const salesByItemsData = sheet.reportData();
// Retrieve the sales by items meta.
const meta = await this.salesByItemsMeta.meta(query);
// Triggers `onSalesByItemViewed` event. // Triggers `onSalesByItemViewed` event.
await this.eventPublisher.emitAsync(events.reports.onSalesByItemViewed, { await this.eventPublisher.emitAsync(events.reports.onSalesByItemViewed, {
query, query,

View File

@@ -8,10 +8,9 @@ import { SalesTaxLiabilitySummaryController } from './SalesTaxLiabilitySummary.c
import { FinancialSheetCommonModule } from '../../common/FinancialSheetCommon.module'; import { FinancialSheetCommonModule } from '../../common/FinancialSheetCommon.module';
import { SalesTaxLiabilitySummaryRepository } from './SalesTaxLiabilitySummaryRepository'; import { SalesTaxLiabilitySummaryRepository } from './SalesTaxLiabilitySummaryRepository';
import { SalesTaxLiabilitySummaryMeta } from './SalesTaxLiabilitySummaryMeta'; import { SalesTaxLiabilitySummaryMeta } from './SalesTaxLiabilitySummaryMeta';
import { TenancyModule } from '@/modules/Tenancy/Tenancy.module';
@Module({ @Module({
imports: [FinancialSheetCommonModule, TenancyModule], imports: [FinancialSheetCommonModule],
providers: [ providers: [
SalesTaxLiabiltiySummaryPdf, SalesTaxLiabiltiySummaryPdf,
SalesTaxLiabilitySummaryTableInjectable, SalesTaxLiabilitySummaryTableInjectable,

View File

@@ -10,7 +10,6 @@ import { FinancialSheet } from '../../common/FinancialSheet';
import { ModelObject } from 'objection'; import { ModelObject } from 'objection';
import { TaxRateModel } from '@/modules/TaxRates/models/TaxRate.model'; import { TaxRateModel } from '@/modules/TaxRates/models/TaxRate.model';
import { SalesTaxLiabilitySummaryRepository } from './SalesTaxLiabilitySummaryRepository'; import { SalesTaxLiabilitySummaryRepository } from './SalesTaxLiabilitySummaryRepository';
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
export class SalesTaxLiabilitySummary extends FinancialSheet { export class SalesTaxLiabilitySummary extends FinancialSheet {
private query: SalesTaxLiabilitySummaryQuery; private query: SalesTaxLiabilitySummaryQuery;
@@ -19,19 +18,18 @@ export class SalesTaxLiabilitySummary extends FinancialSheet {
/** /**
* Sales tax liability summary constructor. * Sales tax liability summary constructor.
* @param {SalesTaxLiabilitySummaryQuery} query * @param {SalesTaxLiabilitySummaryQuery} query
* @param {SalesTaxLiabilitySummaryRepository} repository * @param {ITaxRate[]} taxRates
* @param {IFinancialReportMeta} meta * @param {SalesTaxLiabilitySummaryPayableById} payableTaxesById
* @param {SalesTaxLiabilitySummarySalesById} salesTaxesById
*/ */
constructor( constructor(
query: SalesTaxLiabilitySummaryQuery, query: SalesTaxLiabilitySummaryQuery,
repository: SalesTaxLiabilitySummaryRepository, repository: SalesTaxLiabilitySummaryRepository,
meta: IFinancialReportMeta,
) { ) {
super(); super();
this.query = query; this.query = query;
this.repository = repository; this.repository = repository;
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
} }
/** /**

View File

@@ -14,8 +14,8 @@ export class SalesTaxLiabilitySummaryMeta {
*/ */
public async meta(query: SalesTaxLiabilitySummaryQuery) { public async meta(query: SalesTaxLiabilitySummaryQuery) {
const commonMeta = await this.financialSheetMeta.meta(); const commonMeta = await this.financialSheetMeta.meta();
const formattedToDate = moment(query.toDate).format(commonMeta.dateFormat); const formattedToDate = moment(query.toDate).format('YYYY/MM/DD');
const formattedFromDate = moment(query.fromDate).format(commonMeta.dateFormat); const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`; const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`;
const sheetName = 'Sales Tax Liability Summary'; const sheetName = 'Sales Tax Liability Summary';

View File

@@ -3,14 +3,12 @@ import { SalesTaxLiabilitySummary } from './SalesTaxLiabilitySummary';
import { SalesTaxLiabilitySummaryMeta } from './SalesTaxLiabilitySummaryMeta'; import { SalesTaxLiabilitySummaryMeta } from './SalesTaxLiabilitySummaryMeta';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { SalesTaxLiabilitySummaryQuery } from './SalesTaxLiability.types'; import { SalesTaxLiabilitySummaryQuery } from './SalesTaxLiability.types';
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
@Injectable() @Injectable()
export class SalesTaxLiabilitySummaryService { export class SalesTaxLiabilitySummaryService {
constructor( constructor(
private readonly repository: SalesTaxLiabilitySummaryRepository, private readonly repository: SalesTaxLiabilitySummaryRepository,
private readonly salesTaxLiabilityMeta: SalesTaxLiabilitySummaryMeta, private readonly salesTaxLiabilityMeta: SalesTaxLiabilitySummaryMeta,
private readonly tenancyContext: TenancyContext,
) {} ) {}
/** /**
@@ -21,17 +19,11 @@ export class SalesTaxLiabilitySummaryService {
public async salesTaxLiability(query: SalesTaxLiabilitySummaryQuery) { public async salesTaxLiability(query: SalesTaxLiabilitySummaryQuery) {
await this.repository.load(); await this.repository.load();
// Retrieve the meta first to get date format.
const meta = await this.salesTaxLiabilityMeta.meta(query);
// Get tenant metadata for baseCurrency
const tenantMetadata = await this.tenancyContext.getTenantMetadata();
const taxLiabilitySummary = new SalesTaxLiabilitySummary( const taxLiabilitySummary = new SalesTaxLiabilitySummary(
query, query,
this.repository, this.repository,
{ baseCurrency: tenantMetadata.baseCurrency, dateFormat: meta.dateFormat },
); );
const meta = await this.salesTaxLiabilityMeta.meta(query);
return { return {
data: taxLiabilitySummary.reportData(), data: taxLiabilitySummary.reportData(),

View File

@@ -14,10 +14,9 @@ enum ROW_TYPE {
export class TransactionsByContactsTableRows { export class TransactionsByContactsTableRows {
public i18n: I18nService; public i18n: I18nService;
public dateFormat: string;
public dateAccessor = (value): string => { public dateAccessor = (value): string => {
return moment(value.date).format(this.dateFormat); return moment(value.date).format('YYYY MMM DD');
}; };
/** /**

View File

@@ -12,7 +12,6 @@ import { TransactionsByContact } from '../TransactionsByContact/TransactionsByCo
import { Customer } from '@/modules/Customers/models/Customer'; import { Customer } from '@/modules/Customers/models/Customer';
import { INumberFormatQuery } from '../../types/Report.types'; import { INumberFormatQuery } from '../../types/Report.types';
import { TransactionsByCustomersRepository } from './TransactionsByCustomersRepository'; import { TransactionsByCustomersRepository } from './TransactionsByCustomersRepository';
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
const CUSTOMER_NORMAL = 'debit'; const CUSTOMER_NORMAL = 'debit';
@@ -26,14 +25,12 @@ export class TransactionsByCustomers extends TransactionsByContact {
* Constructor method. * Constructor method.
* @param {ICustomer} customers * @param {ICustomer} customers
* @param {Map<number, IAccountTransaction[]>} transactionsLedger * @param {Map<number, IAccountTransaction[]>} transactionsLedger
* @param {I18nService} i18n * @param {string} baseCurrency
* @param {IFinancialReportMeta} meta
*/ */
constructor( constructor(
filter: ITransactionsByCustomersFilter, filter: ITransactionsByCustomersFilter,
transactionsByCustomersRepository: TransactionsByCustomersRepository, transactionsByCustomersRepository: TransactionsByCustomersRepository,
i18n: I18nService, i18n: I18nService
meta: IFinancialReportMeta,
) { ) {
super(); super();
@@ -41,8 +38,6 @@ export class TransactionsByCustomers extends TransactionsByContact {
this.repository = transactionsByCustomersRepository; this.repository = transactionsByCustomersRepository;
this.numberFormat = this.filter.numberFormat; this.numberFormat = this.filter.numberFormat;
this.i18n = i18n; this.i18n = i18n;
this.baseCurrency = meta.baseCurrency;
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
} }
/** /**

View File

@@ -20,8 +20,8 @@ export class TransactionsByCustomersMeta {
): Promise<ITransactionsByCustomersMeta> { ): Promise<ITransactionsByCustomersMeta> {
const commonMeta = await this.financialSheetMeta.meta(); const commonMeta = await this.financialSheetMeta.meta();
const formattedToDate = moment(query.toDate).format(commonMeta.dateFormat); const formattedToDate = moment(query.toDate).format('YYYY/MM/DD');
const formattedFromDate = moment(query.fromDate).format(commonMeta.dateFormat); const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`; const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`;
return { return {

View File

@@ -36,16 +36,13 @@ export class TransactionsByCustomersSheet {
this.transactionsByCustomersRepository.setFilter(filter); this.transactionsByCustomersRepository.setFilter(filter);
await this.transactionsByCustomersRepository.asyncInit(); await this.transactionsByCustomersRepository.asyncInit();
// Retrieve the meta first to get date format.
const meta = await this.transactionsByCustomersMeta.meta(filter);
// Transactions by customers data mapper. // Transactions by customers data mapper.
const reportInstance = new TransactionsByCustomers( const reportInstance = new TransactionsByCustomers(
filter, filter,
this.transactionsByCustomersRepository, this.transactionsByCustomersRepository,
this.i18n, this.i18n,
{ baseCurrency: meta.baseCurrency, dateFormat: meta.dateFormat },
); );
const meta = await this.transactionsByCustomersMeta.meta(filter);
// Triggers `onCustomerTransactionsViewed` event. // Triggers `onCustomerTransactionsViewed` event.
await this.eventPublisher.emitAsync( await this.eventPublisher.emitAsync(

View File

@@ -22,12 +22,10 @@ export class TransactionsByCustomersTable extends TransactionsByContactsTableRow
constructor( constructor(
customersTransactions: ITransactionsByCustomersCustomer[], customersTransactions: ITransactionsByCustomersCustomer[],
i18n: I18nService, i18n: I18nService,
dateFormat: string,
) { ) {
super(); super();
this.customersTransactions = customersTransactions; this.customersTransactions = customersTransactions;
this.i18n = i18n; this.i18n = i18n;
this.dateFormat = dateFormat;
} }
/** /**

View File

@@ -28,7 +28,6 @@ export class TransactionsByCustomersTableInjectable {
const table = new TransactionsByCustomersTable( const table = new TransactionsByCustomersTable(
customersTransactions.data, customersTransactions.data,
this.i18n, this.i18n,
customersTransactions.meta.dateFormat,
); );
return { return {
table: { table: {

View File

@@ -38,7 +38,7 @@ export class TransactionsByReferenceService {
const report = new TransactionsByReference( const report = new TransactionsByReference(
transactions, transactions,
filter, filter,
{ baseCurrency: tenantMetadata.baseCurrency, dateFormat: tenantMetadata.dateFormat } tenantMetadata.baseCurrency
); );
return { return {

View File

@@ -4,7 +4,7 @@ import {
import { FinancialSheet } from '../../common/FinancialSheet'; import { FinancialSheet } from '../../common/FinancialSheet';
import { ModelObject } from 'objection'; import { ModelObject } from 'objection';
import { AccountTransaction } from '@/modules/Accounts/models/AccountTransaction.model'; import { AccountTransaction } from '@/modules/Accounts/models/AccountTransaction.model';
import { INumberFormatQuery, IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types'; import { INumberFormatQuery } from '../../types/Report.types';
import { TransactionsByReferenceQueryDto } from './TransactionsByReferenceQuery.dto'; import { TransactionsByReferenceQueryDto } from './TransactionsByReferenceQuery.dto';
export class TransactionsByReference extends FinancialSheet { export class TransactionsByReference extends FinancialSheet {
@@ -17,19 +17,18 @@ export class TransactionsByReference extends FinancialSheet {
* Constructor method. * Constructor method.
* @param {ModelObject<AccountTransaction>[]} transactions * @param {ModelObject<AccountTransaction>[]} transactions
* @param {TransactionsByVendorQueryDto} query * @param {TransactionsByVendorQueryDto} query
* @param {IFinancialReportMeta} meta * @param {string} baseCurrency
*/ */
constructor( constructor(
transactions: ModelObject<AccountTransaction>[], transactions: ModelObject<AccountTransaction>[],
query: TransactionsByReferenceQueryDto, query: TransactionsByReferenceQueryDto,
meta: IFinancialReportMeta, baseCurrency: string
) { ) {
super(); super();
this.transactions = transactions; this.transactions = transactions;
this.query = query; this.query = query;
this.baseCurrency = meta.baseCurrency; this.baseCurrency = baseCurrency;
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
// this.numberFormat = this.query.numberFormat; // this.numberFormat = this.query.numberFormat;
} }

View File

@@ -12,7 +12,6 @@ import { TransactionsByContact } from '../TransactionsByContact/TransactionsByCo
import { Vendor } from '@/modules/Vendors/models/Vendor'; import { Vendor } from '@/modules/Vendors/models/Vendor';
import { INumberFormatQuery } from '../../types/Report.types'; import { INumberFormatQuery } from '../../types/Report.types';
import { TransactionsByVendorRepository } from './TransactionsByVendorRepository'; import { TransactionsByVendorRepository } from './TransactionsByVendorRepository';
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
const VENDOR_NORMAL = 'credit'; const VENDOR_NORMAL = 'credit';
@@ -27,13 +26,11 @@ export class TransactionsByVendor extends TransactionsByContact {
* @param {TransactionsByVendorRepository} transactionsByVendorRepository - Transactions by vendor repository. * @param {TransactionsByVendorRepository} transactionsByVendorRepository - Transactions by vendor repository.
* @param {ITransactionsByVendorsFilter} filter - Transactions by vendors filter. * @param {ITransactionsByVendorsFilter} filter - Transactions by vendors filter.
* @param {I18nService} i18n - Internationalization service. * @param {I18nService} i18n - Internationalization service.
* @param {IFinancialReportMeta} meta - Report meta.
*/ */
constructor( constructor(
transactionsByVendorRepository: TransactionsByVendorRepository, transactionsByVendorRepository: TransactionsByVendorRepository,
filter: ITransactionsByVendorsFilter, filter: ITransactionsByVendorsFilter,
i18n: I18nService, i18n: I18nService,
meta: IFinancialReportMeta,
) { ) {
super(); super();
@@ -41,8 +38,6 @@ export class TransactionsByVendor extends TransactionsByContact {
this.filter = filter; this.filter = filter;
this.numberFormat = this.filter.numberFormat; this.numberFormat = this.filter.numberFormat;
this.i18n = i18n; this.i18n = i18n;
this.baseCurrency = meta.baseCurrency;
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
} }
/** /**

View File

@@ -36,16 +36,13 @@ export class TransactionsByVendorsInjectable {
// Initialize the repository. // Initialize the repository.
await this.transactionsByVendorRepository.asyncInit(); await this.transactionsByVendorRepository.asyncInit();
// Retrieve the meta first to get date format. // Transactions by customers data mapper.
const meta = await this.transactionsByVendorMeta.meta(filter);
// Transactions by vendors data mapper.
const reportInstance = new TransactionsByVendor( const reportInstance = new TransactionsByVendor(
this.transactionsByVendorRepository, this.transactionsByVendorRepository,
filter, filter,
this.i18n, this.i18n,
{ baseCurrency: meta.baseCurrency, dateFormat: meta.dateFormat },
); );
const meta = await this.transactionsByVendorMeta.meta(filter);
// Triggers `onVendorTransactionsViewed` event. // Triggers `onVendorTransactionsViewed` event.
await this.eventPublisher.emitAsync( await this.eventPublisher.emitAsync(

View File

@@ -21,8 +21,8 @@ export class TransactionsByVendorMeta {
): Promise<ITransactionsByVendorMeta> { ): Promise<ITransactionsByVendorMeta> {
const commonMeta = await this.financialSheetMeta.meta(); const commonMeta = await this.financialSheetMeta.meta();
const formattedToDate = moment(query.toDate).format(commonMeta.dateFormat); const formattedToDate = moment(query.toDate).format('YYYY/MM/DD');
const formattedFromDate = moment(query.fromDate).format(commonMeta.dateFormat); const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`; const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`;
const sheetName = 'Transactions By Vendor'; const sheetName = 'Transactions By Vendor';

View File

@@ -1,5 +1,4 @@
import * as R from 'ramda'; import * as R from 'ramda';
import { I18nService } from 'nestjs-i18n';
import { ITransactionsByVendorsVendor } from './TransactionsByVendor.types'; import { ITransactionsByVendorsVendor } from './TransactionsByVendor.types';
import { TransactionsByContactsTableRows } from '../TransactionsByContact/TransactionsByContactTableRows'; import { TransactionsByContactsTableRows } from '../TransactionsByContact/TransactionsByContactTableRows';
import { tableRowMapper } from '../../utils/Table.utils'; import { tableRowMapper } from '../../utils/Table.utils';
@@ -20,16 +19,11 @@ export class TransactionsByVendorsTable extends TransactionsByContactsTableRows
* @param {ITransactionsByVendorsVendor[]} vendorsTransactions - * @param {ITransactionsByVendorsVendor[]} vendorsTransactions -
* @param {any} i18n * @param {any} i18n
*/ */
constructor( constructor(vendorsTransactions: ITransactionsByVendorsVendor[], i18n) {
vendorsTransactions: ITransactionsByVendorsVendor[],
i18n: I18nService,
dateFormat: string,
) {
super(); super();
this.vendorsTransactions = vendorsTransactions; this.vendorsTransactions = vendorsTransactions;
this.i18n = i18n; this.i18n = i18n;
this.dateFormat = dateFormat;
} }
/** /**

View File

@@ -25,7 +25,7 @@ export class TransactionsByVendorTableInjectable {
const sheet = await this.transactionsByVendor.transactionsByVendors( const sheet = await this.transactionsByVendor.transactionsByVendors(
query query
); );
const table = new TransactionsByVendorsTable(sheet.data, this.i18n, sheet.meta.dateFormat); const table = new TransactionsByVendorsTable(sheet.data, this.i18n);
return { return {
table: { table: {

View File

@@ -12,7 +12,6 @@ import { Account } from '@/modules/Accounts/models/Account.model';
import { allPassedConditionsPass } from '@/utils/all-conditions-passed'; import { allPassedConditionsPass } from '@/utils/all-conditions-passed';
import { ModelObject } from 'objection'; import { ModelObject } from 'objection';
import { flatToNestedArray } from '@/utils/flat-to-nested-array'; import { flatToNestedArray } from '@/utils/flat-to-nested-array';
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
export class TrialBalanceSheet extends FinancialSheet { export class TrialBalanceSheet extends FinancialSheet {
/** /**
@@ -43,15 +42,14 @@ export class TrialBalanceSheet extends FinancialSheet {
constructor( constructor(
query: ITrialBalanceSheetQuery, query: ITrialBalanceSheetQuery,
repository: TrialBalanceSheetRepository, repository: TrialBalanceSheetRepository,
meta: IFinancialReportMeta, baseCurrency: string
) { ) {
super(); super();
this.query = query; this.query = query;
this.repository = repository; this.repository = repository;
this.numberFormat = this.query.numberFormat; this.numberFormat = this.query.numberFormat;
this.baseCurrency = meta.baseCurrency; this.baseCurrency = baseCurrency;
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
} }
/** /**

View File

@@ -39,18 +39,18 @@ export class TrialBalanceSheetService {
// Loads the resources. // Loads the resources.
await this.trialBalanceSheetRepository.asyncInitialize(); await this.trialBalanceSheetRepository.asyncInitialize();
// Trial balance sheet meta first to get date format.
const meta = await this.trialBalanceSheetMetaService.meta(filter);
// Trial balance report instance. // Trial balance report instance.
const trialBalanceInstance = new TrialBalanceSheet( const trialBalanceInstance = new TrialBalanceSheet(
filter, filter,
this.trialBalanceSheetRepository, this.trialBalanceSheetRepository,
{ baseCurrency: tenantMetadata.baseCurrency, dateFormat: meta.dateFormat }, tenantMetadata.baseCurrency,
); );
// Trial balance sheet data. // Trial balance sheet data.
const trialBalanceSheetData = trialBalanceInstance.reportData(); const trialBalanceSheetData = trialBalanceInstance.reportData();
// Trial balance sheet meta.
const meta = await this.trialBalanceSheetMetaService.meta(filter);
// Triggers `onTrialBalanceSheetViewed` event. // Triggers `onTrialBalanceSheetViewed` event.
await this.eventPublisher.emitAsync( await this.eventPublisher.emitAsync(
events.reports.onTrialBalanceSheetView, events.reports.onTrialBalanceSheetView,

View File

@@ -16,8 +16,8 @@ export class TrialBalanceSheetMeta {
): Promise<ITrialBalanceSheetMeta> { ): Promise<ITrialBalanceSheetMeta> {
const commonMeta = await this.financialSheetMeta.meta(); const commonMeta = await this.financialSheetMeta.meta();
const formattedFromDate = moment(query.fromDate).format(commonMeta.dateFormat); const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
const formattedToDate = moment(query.toDate).format(commonMeta.dateFormat); const formattedToDate = moment(query.toDate).format('YYYY/MM/DD');
const formattedDateRange = `From ${formattedFromDate} to ${formattedToDate}`; const formattedDateRange = `From ${formattedFromDate} to ${formattedToDate}`;
const sheetName = 'Trial Balance Sheet'; const sheetName = 'Trial Balance Sheet';

View File

@@ -8,7 +8,7 @@ import {
} from './VendorBalanceSummary.types'; } from './VendorBalanceSummary.types';
import { ContactBalanceSummaryReport } from '../ContactBalanceSummary/ContactBalanceSummary'; import { ContactBalanceSummaryReport } from '../ContactBalanceSummary/ContactBalanceSummary';
import { Vendor } from '@/modules/Vendors/models/Vendor'; import { Vendor } from '@/modules/Vendors/models/Vendor';
import { INumberFormatQuery, IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types'; import { INumberFormatQuery } from '../../types/Report.types';
import { VendorBalanceSummaryRepository } from './VendorBalanceSummaryRepository'; import { VendorBalanceSummaryRepository } from './VendorBalanceSummaryRepository';
import { Ledger } from '@/modules/Ledger/Ledger'; import { Ledger } from '@/modules/Ledger/Ledger';
@@ -27,17 +27,15 @@ export class VendorBalanceSummaryReport extends ContactBalanceSummaryReport {
constructor( constructor(
repository: VendorBalanceSummaryRepository, repository: VendorBalanceSummaryRepository,
filter: IVendorBalanceSummaryQuery, filter: IVendorBalanceSummaryQuery,
meta: IFinancialReportMeta,
) { ) {
super(); super();
this.repository = repository; this.repository = repository;
this.ledger = this.repository.ledger; this.ledger = this.repository.ledger;
this.baseCurrency = meta.baseCurrency; this.baseCurrency = this.repository.baseCurrency;
this.filter = filter; this.filter = filter;
this.numberFormat = this.filter.numberFormat; this.numberFormat = this.filter.numberFormat;
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
} }

View File

@@ -19,7 +19,7 @@ export class VendorBalanceSummaryMeta {
query: IVendorBalanceSummaryQuery, query: IVendorBalanceSummaryQuery,
): Promise<IVendorBalanceSummaryMeta> { ): Promise<IVendorBalanceSummaryMeta> {
const commonMeta = await this.financialSheetMeta.meta(); const commonMeta = await this.financialSheetMeta.meta();
const formattedAsDate = moment(query.asDate).format(commonMeta.dateFormat); const formattedAsDate = moment(query.asDate).format('YYYY/MM/DD');
return { return {
...commonMeta, ...commonMeta,

View File

@@ -31,15 +31,13 @@ export class VendorBalanceSummaryService {
this.vendorBalanceSummaryRepository.setFilter(filter); this.vendorBalanceSummaryRepository.setFilter(filter);
await this.vendorBalanceSummaryRepository.asyncInit(); await this.vendorBalanceSummaryRepository.asyncInit();
// Retrieve the vendor balance summary meta first to get date format.
const meta = await this.vendorBalanceSummaryMeta.meta(filter);
// Report instance. // Report instance.
const reportInstance = new VendorBalanceSummaryReport( const reportInstance = new VendorBalanceSummaryReport(
this.vendorBalanceSummaryRepository, this.vendorBalanceSummaryRepository,
filter, filter,
{ baseCurrency: this.vendorBalanceSummaryRepository.baseCurrency, dateFormat: meta.dateFormat },
); );
// Retrieve the vendor balance summary meta.
const meta = await this.vendorBalanceSummaryMeta.meta(filter);
// Triggers `onVendorBalanceSummaryViewed` event. // Triggers `onVendorBalanceSummaryViewed` event.
await this.eventEmitter.emitAsync( await this.eventEmitter.emitAsync(

View File

@@ -52,22 +52,6 @@ export interface IFinancialSheetCommonMeta {
sheetName: string; sheetName: string;
} }
/**
* Report meta interface for sheet constructors.
* Combines baseCurrency and dateFormat for a cleaner API.
*/
export interface IFinancialReportMeta {
baseCurrency: string;
dateFormat: string;
}
/**
* Default report meta values.
*/
export const DEFAULT_REPORT_META: Omit<IFinancialReportMeta, 'baseCurrency'> = {
dateFormat: 'YYYY MMM DD',
};
export enum IFinancialDatePeriodsUnit { export enum IFinancialDatePeriodsUnit {
Day = 'day', Day = 'day',
Month = 'month', Month = 'month',

View File

@@ -32,7 +32,7 @@ export class InventoryAdjustment extends TenantBaseModel {
* Timestamps columns. * Timestamps columns.
*/ */
get timestamps(): Array<string> { get timestamps(): Array<string> {
return ['createdAt']; return ['created_at'];
} }
/** /**

View File

@@ -20,13 +20,6 @@ export class InventoryAdjustmentEntry extends BaseModel {
return 'inventory_adjustments_entries'; return 'inventory_adjustments_entries';
} }
/**
* Timestamps columns.
*/
get timestamps() {
return [];
}
/** /**
* Relationship mapping. * Relationship mapping.
*/ */

View File

@@ -13,13 +13,6 @@ export class InventoryTransactionMeta extends BaseModel {
return 'inventory_transaction_meta'; return 'inventory_transaction_meta';
} }
/**
* Timestamps columns.
*/
get timestamps() {
return [];
}
/** /**
* Relationship mapping. * Relationship mapping.
*/ */

View File

@@ -44,13 +44,6 @@ export class Item extends TenantBaseModel {
return 'items'; return 'items';
} }
/**
* Timestamps columns.
*/
get timestamps() {
return ['createdAt', 'updatedAt'];
}
/** /**
* Model modifiers. * Model modifiers.
*/ */

View File

@@ -1,15 +1,18 @@
import currencies from 'js-money/lib/currency'; import currencies from 'js-money/lib/currency';
export const DATE_FORMATS = [ export const DATE_FORMATS = [
'MM/DD/YY', 'MM.dd.yy',
'DD/MM/YY', 'dd.MM.yy',
'YY/MM/DD', 'yy.MM.dd',
'MM/DD/yyyy', 'MM.dd.yyyy',
'DD/MM/yyyy', 'dd.MM.yyyy',
'yyyy/MM/DD', 'yyyy.MM.dd',
'DD MMM YYYY', 'MM/DD/YYYY',
'DD MMMM YYYY', 'M/D/YYYY',
'MMMM DD, YYYY', 'dd MMM YYYY',
'dd MMMM YYYY',
'MMMM dd, YYYY',
'EEE, MMMM dd, YYYY',
]; ];
export const MONTHS = [ export const MONTHS = [
'january', 'january',

View File

@@ -12,6 +12,6 @@ export const transformBuildDto = (
): BuildOrganizationDto => { ): BuildOrganizationDto => {
return { return {
...buildDTO, ...buildDTO,
dateFormat: defaultTo(buildDTO.dateFormat, 'DD MMM YYYY'), dateFormat: defaultTo(buildDTO.dateFormat, 'DD MMM yyyy'),
}; };
}; };

View File

@@ -43,7 +43,7 @@ export class PaymentReceived extends TenantBaseModel {
* Timestamps columns. * Timestamps columns.
*/ */
get timestamps() { get timestamps() {
return ['createdAt', 'updatedAt']; return ['created_at', 'updated_at'];
} }
/** /**

View File

@@ -16,13 +16,6 @@ export class Role extends TenantBaseModel {
return 'roles'; return 'roles';
} }
/**
* Timestamps columns.
*/
get timestamps() {
return [];
}
/** /**
* Relationship mapping. * Relationship mapping.
*/ */

View File

@@ -13,13 +13,6 @@ export class RolePermission extends TenantBaseModel {
return 'role_permissions'; return 'role_permissions';
} }
/**
* Timestamps columns.
*/
get timestamps() {
return [];
}
/** /**
* Relationship mapping. * Relationship mapping.
*/ */

View File

@@ -74,7 +74,7 @@ export class SaleInvoice extends TenantBaseModel {
* Timestamps columns. * Timestamps columns.
*/ */
get timestamps() { get timestamps() {
return ['createdAt', 'updatedAt']; return ['created_at', 'updated_at'];
} }
/** /**

View File

@@ -72,7 +72,7 @@ export class SaleReceipt extends ExtendedModel {
* Timestamps columns. * Timestamps columns.
*/ */
get timestamps() { get timestamps() {
return ['createdAt', 'updatedAt']; return ['created_at', 'updated_at'];
} }
/** /**

View File

@@ -10,10 +10,6 @@ export class Setting extends BaseModel {
return 'settings'; return 'settings';
} }
get timestamps() {
return [];
}
/** /**
* Extra metadata query to query with the current authenticate user. * Extra metadata query to query with the current authenticate user.
* @param {Object} query * @param {Object} query

View File

@@ -50,13 +50,6 @@ export class TenantMetadata extends BaseModel {
*/ */
static tableName = 'tenants_metadata'; static tableName = 'tenants_metadata';
/**
* Timestamps columns.
*/
get timestamps() {
return [];
}
/** /**
* Virtual attributes. * Virtual attributes.
*/ */

View File

@@ -24,7 +24,7 @@ export class TenantUser extends TenantBaseModel {
* Timestamps columns. * Timestamps columns.
*/ */
get timestamps() { get timestamps() {
return ['createdAt', 'updatedAt']; return ['created_at', 'updated_at'];
} }
/** /**

View File

@@ -53,7 +53,7 @@ export class ItemEntry extends BaseModel {
* @returns {string[]} * @returns {string[]}
*/ */
get timestamps() { get timestamps() {
return ['createdAt', 'updatedAt']; return ['created_at', 'updated_at'];
} }
/** /**

View File

@@ -0,0 +1,19 @@
import { Injectable } from '@nestjs/common';
import { TRPCContext, ContextOptions } from 'nestjs-trpc';
@Injectable()
export class TrpcContext implements TRPCContext {
async create(opts: ContextOptions): Promise<Record<string, unknown>> {
const { req } = opts;
// Extract auth token and organization from headers
const token = req.headers['x-access-token'];
const organizationId = req.headers['organization-id'];
return {
token,
organizationId: organizationId ? parseInt(organizationId as string, 10) : null,
req,
};
}
}

View File

@@ -0,0 +1,19 @@
import { Module } from '@nestjs/common';
import { TRPCModule } from 'nestjs-trpc';
import { TrpcService } from './Trpc.service';
import { TrpcContext } from './Trpc.context';
import { AccountsTrpcRouter } from './routers/Accounts.router';
import { AccountsModule } from '@/modules/Accounts/Accounts.module';
@Module({
imports: [
TRPCModule.forRoot({
basePath: '/api/trpc',
context: TrpcContext,
}),
AccountsModule,
],
providers: [TrpcService, TrpcContext, AccountsTrpcRouter],
exports: [TrpcService],
})
export class AppTrpcModule {}

View File

@@ -0,0 +1,13 @@
import { Injectable } from '@nestjs/common';
import { Request, Response } from 'express';
export interface TrpcContext {
req: Request;
res: Response;
user: any;
organizationId: number | null;
}
@Injectable()
export class TrpcService {
}

Some files were not shown because too many files have changed in this diff Show More