mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-26 09:39:49 +00:00
Compare commits
13 Commits
feat/trpc-
...
fix/accoun
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca68918caa | ||
|
|
fa1acc9773 | ||
|
|
558fc29962 | ||
|
|
8a32e13a79 | ||
|
|
d35915b16b | ||
|
|
b5d1a2c9d0 | ||
|
|
f5e74f3e88 | ||
|
|
c83132b867 | ||
|
|
88ff5db0f3 | ||
|
|
f35e85c3d2 | ||
|
|
29decf9c5a | ||
|
|
f149ff43b4 | ||
|
|
fb05af8c00 |
@@ -21,6 +21,7 @@ import { AccountsExportable } from './AccountsExportable.service';
|
||||
import { AccountsImportable } from './AccountsImportable.service';
|
||||
import { BulkDeleteAccountsService } from './BulkDeleteAccounts.service';
|
||||
import { ValidateBulkDeleteAccountsService } from './ValidateBulkDeleteAccounts.service';
|
||||
import { AccountsSettingsService } from './AccountsSettings.service';
|
||||
|
||||
const models = [RegisterTenancyModel(BankAccount)];
|
||||
|
||||
@@ -29,6 +30,7 @@ const models = [RegisterTenancyModel(BankAccount)];
|
||||
controllers: [AccountsController],
|
||||
providers: [
|
||||
AccountsApplication,
|
||||
AccountsSettingsService,
|
||||
CreateAccountService,
|
||||
TenancyContext,
|
||||
CommandAccountValidators,
|
||||
@@ -49,9 +51,10 @@ const models = [RegisterTenancyModel(BankAccount)];
|
||||
exports: [
|
||||
AccountRepository,
|
||||
CreateAccountService,
|
||||
AccountsSettingsService,
|
||||
...models,
|
||||
AccountsExportable,
|
||||
AccountsImportable
|
||||
AccountsImportable,
|
||||
],
|
||||
})
|
||||
export class AccountsModule {}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
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,
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -106,6 +106,20 @@ 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.
|
||||
* @param {string} accountName - Account name.
|
||||
|
||||
@@ -15,6 +15,7 @@ import { events } from '@/common/events/events';
|
||||
import { CreateAccountDTO } from './CreateAccount.dto';
|
||||
import { PartialModelObject } from 'objection';
|
||||
import { TenantModelProxy } from '../System/models/TenantBaseModel';
|
||||
import { AccountsSettingsService } from './AccountsSettings.service';
|
||||
|
||||
@Injectable()
|
||||
export class CreateAccountService {
|
||||
@@ -32,6 +33,7 @@ export class CreateAccountService {
|
||||
private readonly uow: UnitOfWork,
|
||||
private readonly validator: CommandAccountValidators,
|
||||
private readonly tenancyContext: TenancyContext,
|
||||
private readonly accountsSettings: AccountsSettingsService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -43,14 +45,21 @@ export class CreateAccountService {
|
||||
baseCurrency: string,
|
||||
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.
|
||||
if (!params.ignoreUniqueName) {
|
||||
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.
|
||||
this.validator.getAccountTypeOrThrowError(accountDTO.accountType);
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import { UnitOfWork } from '../Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { events } from '@/common/events/events';
|
||||
import { EditAccountDTO } from './EditAccount.dto';
|
||||
import { TenantModelProxy } from '../System/models/TenantBaseModel';
|
||||
import { AccountsSettingsService } from './AccountsSettings.service';
|
||||
|
||||
@Injectable()
|
||||
export class EditAccount {
|
||||
@@ -17,7 +18,8 @@ export class EditAccount {
|
||||
|
||||
@Inject(Account.name)
|
||||
private readonly accountModel: TenantModelProxy<typeof Account>,
|
||||
) { }
|
||||
private readonly accountsSettings: AccountsSettingsService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Authorize the account editing.
|
||||
@@ -30,6 +32,24 @@ export class EditAccount {
|
||||
accountDTO: EditAccountDTO,
|
||||
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.
|
||||
await this.validator.validateAccountNameUniquiness(
|
||||
accountDTO.name,
|
||||
@@ -40,13 +60,6 @@ export class EditAccount {
|
||||
oldAccount,
|
||||
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.
|
||||
if (accountDTO.parentAccountId) {
|
||||
const parentAccount = await this.validator.getParentAccountOrThrowError(
|
||||
|
||||
@@ -3,6 +3,7 @@ export const ERRORS = {
|
||||
ACCOUNT_TYPE_NOT_FOUND: 'account_type_not_found',
|
||||
PARENT_ACCOUNT_NOT_FOUND: 'parent_account_not_found',
|
||||
ACCOUNT_CODE_NOT_UNIQUE: 'account_code_not_unique',
|
||||
ACCOUNT_CODE_REQUIRED: 'account_code_required',
|
||||
ACCOUNT_NAME_NOT_UNIQUE: 'account_name_not_unqiue',
|
||||
PARENT_ACCOUNT_HAS_DIFFERENT_TYPE: 'parent_has_different_type',
|
||||
ACCOUNT_TYPE_NOT_ALLOWED_TO_CHANGE: 'account_type_not_allowed_to_changed',
|
||||
|
||||
@@ -24,6 +24,7 @@ import { GetBankAccountsService } from './queries/GetBankAccounts.service';
|
||||
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
||||
import { BankAccount } from './models/BankAccount';
|
||||
import { LedgerModule } from '../Ledger/Ledger.module';
|
||||
import { TenancyModule } from '../Tenancy/Tenancy.module';
|
||||
import { GetBankAccountTransactionsService } from './queries/GetBankAccountTransactions/GetBankAccountTransactions.service';
|
||||
import { GetBankAccountTransactionsRepository } from './queries/GetBankAccountTransactions/GetBankAccountTransactionsRepo.service';
|
||||
import { GetUncategorizedTransactions } from './queries/GetUncategorizedTransactions';
|
||||
@@ -46,6 +47,7 @@ const models = [
|
||||
LedgerModule,
|
||||
BranchesModule,
|
||||
DynamicListModule,
|
||||
TenancyModule,
|
||||
...models,
|
||||
],
|
||||
controllers: [
|
||||
|
||||
@@ -4,12 +4,14 @@ import { GetBankAccountTransactionsRepository } from './GetBankAccountTransactio
|
||||
import { GetBankAccountTransactions } from './GetBankAccountTransactions';
|
||||
import { GetBankTransactionsQueryDto } from '../../dtos/GetBankTranasctionsQuery.dto';
|
||||
import { I18nService } from 'nestjs-i18n';
|
||||
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
|
||||
|
||||
@Injectable()
|
||||
export class GetBankAccountTransactionsService {
|
||||
constructor(
|
||||
private readonly getBankAccountTransactionsRepository: GetBankAccountTransactionsRepository,
|
||||
private readonly i18nService: I18nService
|
||||
private readonly i18nService: I18nService,
|
||||
private readonly tenancyContext: TenancyContext,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -28,11 +30,16 @@ export class GetBankAccountTransactionsService {
|
||||
|
||||
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.
|
||||
const report = new GetBankAccountTransactions(
|
||||
this.getBankAccountTransactionsRepository,
|
||||
parsedQuery,
|
||||
this.i18nService
|
||||
this.i18nService,
|
||||
dateFormat,
|
||||
);
|
||||
const transactions = report.reportData();
|
||||
const pagination = this.getBankAccountTransactionsRepository.pagination;
|
||||
|
||||
@@ -24,17 +24,20 @@ export class GetBankAccountTransactions extends FinancialSheet {
|
||||
* @param {IAccountTransaction[]} transactions -
|
||||
* @param {number} openingBalance -
|
||||
* @param {ICashflowAccountTransactionsQuery} query -
|
||||
* @param {string} dateFormat - The date format from organization settings.
|
||||
*/
|
||||
constructor(
|
||||
repo: GetBankAccountTransactionsRepository,
|
||||
query: ICashflowAccountTransactionsQuery,
|
||||
i18n: I18nService,
|
||||
dateFormat?: string,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.repo = repo;
|
||||
this.query = query;
|
||||
this.i18n = i18n;
|
||||
this.dateFormat = dateFormat || this.dateFormat;
|
||||
|
||||
this.runningBalance = runningBalance(this.repo.openingBalance);
|
||||
}
|
||||
@@ -98,7 +101,7 @@ export class GetBankAccountTransactions extends FinancialSheet {
|
||||
|
||||
return {
|
||||
date: transaction.date,
|
||||
formattedDate: moment(transaction.date).format('YYYY-MM-DD'),
|
||||
formattedDate: this.getDateFormatted(transaction.date),
|
||||
|
||||
withdrawal: transaction.credit,
|
||||
deposit: transaction.debit,
|
||||
|
||||
@@ -10,7 +10,7 @@ export interface IContactAddress {
|
||||
billingAddressCity: string;
|
||||
billingAddressCountry: string;
|
||||
billingAddressEmail: string;
|
||||
billingAddressZipcode: string;
|
||||
billingAddressPostcode: string;
|
||||
billingAddressPhone: string;
|
||||
billingAddressState: string;
|
||||
|
||||
@@ -19,7 +19,7 @@ export interface IContactAddress {
|
||||
shippingAddressCity: string;
|
||||
shippingAddressCountry: string;
|
||||
shippingAddressEmail: string;
|
||||
shippingAddressZipcode: string;
|
||||
shippingAddressPostcode: string;
|
||||
shippingAddressPhone: string;
|
||||
shippingAddressState: string;
|
||||
}
|
||||
@@ -29,7 +29,7 @@ export interface IContactAddressDTO {
|
||||
billingAddressCity?: string;
|
||||
billingAddressCountry?: string;
|
||||
billingAddressEmail?: string;
|
||||
billingAddressZipcode?: string;
|
||||
billingAddressPostcode?: string;
|
||||
billingAddressPhone?: string;
|
||||
billingAddressState?: string;
|
||||
|
||||
@@ -38,7 +38,7 @@ export interface IContactAddressDTO {
|
||||
shippingAddressCity?: string;
|
||||
shippingAddressCountry?: string;
|
||||
shippingAddressEmail?: string;
|
||||
shippingAddressZipcode?: string;
|
||||
shippingAddressPostcode?: string;
|
||||
shippingAddressPhone?: string;
|
||||
shippingAddressState?: string;
|
||||
}
|
||||
|
||||
@@ -27,10 +27,10 @@ export class ContactAddressDto {
|
||||
@IsEmail()
|
||||
billingAddressEmail?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Billing address zipcode' })
|
||||
@ApiProperty({ required: false, description: 'Billing address postcode' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
billingAddressZipcode?: string;
|
||||
billingAddressPostcode?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Billing address phone' })
|
||||
@IsOptional()
|
||||
@@ -67,10 +67,10 @@ export class ContactAddressDto {
|
||||
@IsEmail()
|
||||
shippingAddressEmail?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Shipping address zipcode' })
|
||||
@ApiProperty({ required: false, description: 'Shipping address postcode' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
shippingAddressZipcode?: string;
|
||||
shippingAddressPostcode?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Shipping address phone' })
|
||||
@IsOptional()
|
||||
|
||||
@@ -15,6 +15,7 @@ export class FinancialSheet {
|
||||
negativeFormat: 'mines',
|
||||
};
|
||||
public baseCurrency: string;
|
||||
public dateFormat: string = 'YYYY MMM DD';
|
||||
|
||||
/**
|
||||
* Transformes the number format query to settings
|
||||
@@ -140,13 +141,19 @@ export class FinancialSheet {
|
||||
* @param {string} format
|
||||
* @returns
|
||||
*/
|
||||
protected getDateMeta(date: moment.MomentInput, format = 'YYYY-MM-DD') {
|
||||
protected getDateMeta(date: moment.MomentInput, format?: string) {
|
||||
const dateFormat = format || this.dateFormat || 'YYYY MMM DD';
|
||||
return {
|
||||
formattedDate: moment(date).format(format),
|
||||
formattedDate: moment(date).format(dateFormat),
|
||||
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) => {
|
||||
return base ? amount / base : 0;
|
||||
};
|
||||
|
||||
@@ -32,18 +32,19 @@ export class APAgingSummaryService {
|
||||
this.APAgingSummaryRepository.setFilter(filter);
|
||||
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.
|
||||
const APAgingSummaryReport = new APAgingSummarySheet(
|
||||
filter,
|
||||
this.APAgingSummaryRepository,
|
||||
{ baseCurrency: meta.baseCurrency, dateFormat: meta.dateFormat },
|
||||
);
|
||||
// A/P aging summary report data and columns.
|
||||
const data = APAgingSummaryReport.reportData();
|
||||
const columns = APAgingSummaryReport.reportColumns();
|
||||
|
||||
// Retrieve the aging summary report meta.
|
||||
const meta = await this.APAgingSummaryMeta.meta(filter);
|
||||
|
||||
// Triggers `onPayableAgingViewed` event.
|
||||
await this.eventPublisher.emitAsync(events.reports.onPayableAgingViewed, {
|
||||
query,
|
||||
|
||||
@@ -14,6 +14,7 @@ import { allPassedConditionsPass } from '@/utils/all-conditions-passed';
|
||||
import { APAgingSummaryRepository } from './APAgingSummaryRepository';
|
||||
import { Bill } from '@/modules/Bills/models/Bill';
|
||||
import { APAgingSummaryQueryDto } from './APAgingSummaryQuery.dto';
|
||||
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
|
||||
|
||||
export class APAgingSummarySheet extends AgingSummaryReport {
|
||||
readonly repository: APAgingSummaryRepository;
|
||||
@@ -31,12 +32,14 @@ export class APAgingSummarySheet extends AgingSummaryReport {
|
||||
constructor(
|
||||
query: APAgingSummaryQueryDto,
|
||||
repository: APAgingSummaryRepository,
|
||||
meta: IFinancialReportMeta,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.query = query;
|
||||
this.repository = repository;
|
||||
this.numberFormat = this.query.numberFormat;
|
||||
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
|
||||
|
||||
this.overdueInvoicesByContactId = this.repository.overdueBillsByVendorId;
|
||||
this.currentInvoicesByContactId = this.repository.dueBillsByVendorId;
|
||||
|
||||
@@ -28,18 +28,19 @@ export class ARAgingSummaryService {
|
||||
this.ARAgingSummaryRepository.setFilter(filter);
|
||||
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.
|
||||
const ARAgingSummaryReport = new ARAgingSummarySheet(
|
||||
filter,
|
||||
this.ARAgingSummaryRepository,
|
||||
{ baseCurrency: meta.baseCurrency, dateFormat: meta.dateFormat },
|
||||
);
|
||||
// A/R aging summary report data and columns.
|
||||
const data = ARAgingSummaryReport.reportData();
|
||||
const columns = ARAgingSummaryReport.reportColumns();
|
||||
|
||||
// Retrieve the aging summary report meta.
|
||||
const meta = await this.ARAgingSummaryMeta.meta(filter);
|
||||
|
||||
// Triggers `onReceivableAgingViewed` event.
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.reports.onReceivableAgingViewed,
|
||||
|
||||
@@ -14,6 +14,7 @@ import { ARAgingSummaryRepository } from './ARAgingSummaryRepository';
|
||||
import { Customer } from '@/modules/Customers/models/Customer';
|
||||
import { SaleInvoice } from '@/modules/SaleInvoices/models/SaleInvoice';
|
||||
import { ARAgingSummaryQueryDto } from './ARAgingSummaryQuery.dto';
|
||||
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
|
||||
|
||||
export class ARAgingSummarySheet extends AgingSummaryReport {
|
||||
readonly query: ARAgingSummaryQueryDto;
|
||||
@@ -32,16 +33,19 @@ export class ARAgingSummarySheet extends AgingSummaryReport {
|
||||
* Constructor method.
|
||||
* @param {ARAgingSummaryQueryDto} query - Query
|
||||
* @param {ARAgingSummaryRepository} repository - Repository.
|
||||
* @param {IFinancialReportMeta} meta - Report meta.
|
||||
*/
|
||||
constructor(
|
||||
query: ARAgingSummaryQueryDto,
|
||||
repository: ARAgingSummaryRepository,
|
||||
meta: IFinancialReportMeta,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.query = query;
|
||||
this.repository = repository;
|
||||
this.numberFormat = this.query.numberFormat;
|
||||
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
|
||||
|
||||
this.overdueInvoicesByContactId =
|
||||
this.repository.overdueInvoicesByContactId;
|
||||
|
||||
@@ -13,7 +13,7 @@ export class AgingSummaryMeta {
|
||||
*/
|
||||
public async meta(query: IAgingSummaryQuery): Promise<IAgingSummaryMeta> {
|
||||
const commonMeta = await this.financialSheetMeta.meta();
|
||||
const formattedAsDate = moment(query.asDate).format('YYYY/MM/DD');
|
||||
const formattedAsDate = moment(query.asDate).format(commonMeta.dateFormat);
|
||||
const formattedDateRange = `As ${formattedAsDate}`;
|
||||
|
||||
return {
|
||||
|
||||
@@ -19,7 +19,7 @@ import { BalanceSheetFiltering } from './BalanceSheetFiltering';
|
||||
import { BalanceSheetNetIncome } from './BalanceSheetNetIncome';
|
||||
import { BalanceSheetAggregators } from './BalanceSheetAggregators';
|
||||
import { BalanceSheetAccounts } from './BalanceSheetAccounts';
|
||||
import { INumberFormatQuery } from '../../types/Report.types';
|
||||
import { INumberFormatQuery, IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
|
||||
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||
|
||||
export class BalanceSheet extends R.pipe(
|
||||
@@ -66,21 +66,23 @@ export class BalanceSheet extends R.pipe(
|
||||
/**
|
||||
* Constructor method.
|
||||
* @param {IBalanceSheetQuery} query -
|
||||
* @param {IAccount[]} accounts -
|
||||
* @param {string} baseCurrency -
|
||||
* @param {BalanceSheetRepository} repository -
|
||||
* @param {I18nService} i18n -
|
||||
* @param {IFinancialReportMeta} meta -
|
||||
*/
|
||||
constructor(
|
||||
query: IBalanceSheetQuery,
|
||||
repository: BalanceSheetRepository,
|
||||
baseCurrency: string,
|
||||
i18n: I18nService,
|
||||
meta: IFinancialReportMeta,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.query = new BalanceSheetQuery(query);
|
||||
this.repository = repository;
|
||||
this.baseCurrency = baseCurrency;
|
||||
this.baseCurrency = meta.baseCurrency;
|
||||
this.numberFormat = this.query.query.numberFormat;
|
||||
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
|
||||
this.i18n = i18n;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,19 +40,19 @@ export class BalanceSheetInjectable {
|
||||
// Loads all resources.
|
||||
await this.balanceSheetRepository.asyncInitialize(filter);
|
||||
|
||||
// Balance sheet meta first to get date format.
|
||||
const meta = await this.balanceSheetMeta.meta(filter);
|
||||
|
||||
// Balance sheet report instance.
|
||||
const balanceSheetInstanace = new BalanceSheet(
|
||||
filter,
|
||||
this.balanceSheetRepository,
|
||||
tenantMetadata.baseCurrency,
|
||||
this.i18n,
|
||||
{ baseCurrency: tenantMetadata.baseCurrency, dateFormat: meta.dateFormat },
|
||||
);
|
||||
// Balance sheet data.
|
||||
const data = balanceSheetInstanace.reportData();
|
||||
|
||||
// Balance sheet meta.
|
||||
const meta = await this.balanceSheetMeta.meta(filter);
|
||||
|
||||
// Triggers `onBalanceSheetViewed` event.
|
||||
await this.eventPublisher.emitAsync(events.reports.onBalanceSheetViewed, {
|
||||
query,
|
||||
|
||||
@@ -13,7 +13,7 @@ export class BalanceSheetMetaInjectable {
|
||||
*/
|
||||
public async meta(query: IBalanceSheetQuery): Promise<IBalanceSheetMeta> {
|
||||
const commonMeta = await this.financialSheetMeta.meta();
|
||||
const formattedAsDate = moment(query.toDate).format('YYYY/MM/DD');
|
||||
const formattedAsDate = moment(query.toDate).format(commonMeta.dateFormat);
|
||||
const formattedDateRange = `As ${formattedAsDate}`;
|
||||
const sheetName = 'Balance Sheet Statement';
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ import { DISPLAY_COLUMNS_BY } from './constants';
|
||||
import { FinancialSheetStructure } from '../../common/FinancialSheetStructure';
|
||||
import { Account } from '@/modules/Accounts/models/Account.model';
|
||||
import { ILedger } from '@/modules/Ledger/types/Ledger.types';
|
||||
import { INumberFormatQuery } from '../../types/Report.types';
|
||||
import { INumberFormatQuery, IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
|
||||
import { transformToMapBy } from '@/utils/transform-to-map-by';
|
||||
import { accumSum } from '@/utils/accum-sum';
|
||||
import { ModelObject } from 'objection';
|
||||
@@ -62,12 +62,12 @@ export class CashFlowStatement extends R.pipe(
|
||||
cashLedger: ILedger,
|
||||
netIncomeLedger: ILedger,
|
||||
query: ICashFlowStatementQuery,
|
||||
baseCurrency: string,
|
||||
i18n: I18nService,
|
||||
meta: IFinancialReportMeta,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.baseCurrency = baseCurrency;
|
||||
this.baseCurrency = meta.baseCurrency;
|
||||
this.i18n = i18n;
|
||||
this.ledger = ledger;
|
||||
this.cashLedger = cashLedger;
|
||||
@@ -76,6 +76,7 @@ export class CashFlowStatement extends R.pipe(
|
||||
this.accountsByRootType = transformToMapBy(accounts, 'accountRootType');
|
||||
this.query = query;
|
||||
this.numberFormat = this.query.numberFormat;
|
||||
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
|
||||
this.dateRangeSet = [];
|
||||
this.comparatorDateType =
|
||||
query.displayColumnsType === 'total' ? 'day' : query.displayColumnsBy;
|
||||
|
||||
@@ -85,6 +85,9 @@ export class CashFlowStatementService {
|
||||
const cashLedger = Ledger.fromTransactions(cashAtBeginningTransactions);
|
||||
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.
|
||||
const cashFlowInstance = new CashFlowStatement(
|
||||
accounts,
|
||||
@@ -92,11 +95,9 @@ export class CashFlowStatementService {
|
||||
cashLedger,
|
||||
netIncomeLedger,
|
||||
filter,
|
||||
tenant.metadata.baseCurrency,
|
||||
this.i18n,
|
||||
{ baseCurrency: tenant.metadata.baseCurrency, dateFormat: meta.dateFormat },
|
||||
);
|
||||
// Retrieve the cashflow sheet meta.
|
||||
const meta = await this.cashflowSheetMeta.meta(filter);
|
||||
|
||||
return {
|
||||
data: cashFlowInstance.reportData(),
|
||||
|
||||
@@ -23,8 +23,8 @@ export class CashflowSheetMeta {
|
||||
query: ICashFlowStatementQuery,
|
||||
): Promise<ICashFlowStatementMeta> {
|
||||
const meta = await this.financialSheetMeta.meta();
|
||||
const formattedToDate = moment(query.toDate).format('YYYY/MM/DD');
|
||||
const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
|
||||
const formattedToDate = moment(query.toDate).format(meta.dateFormat);
|
||||
const formattedFromDate = moment(query.fromDate).format(meta.dateFormat);
|
||||
const fromLabel = this.i18n.t('cash_flow_statement.from_date');
|
||||
const toLabel = this.i18n.t('cash_flow_statement.to_date');
|
||||
const formattedDateRange = `${fromLabel} ${formattedFromDate} | ${toLabel} ${formattedToDate}`;
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
import { ContactBalanceSummaryReport } from '../ContactBalanceSummary/ContactBalanceSummary';
|
||||
import { ILedger } from '@/modules/Ledger/types/Ledger.types';
|
||||
import { ModelObject } from 'objection';
|
||||
import { INumberFormatQuery } from '../../types/Report.types';
|
||||
import { INumberFormatQuery, IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
|
||||
import { Customer } from '@/modules/Customers/models/Customer';
|
||||
|
||||
export class CustomerBalanceSummaryReport extends ContactBalanceSummaryReport {
|
||||
@@ -23,21 +23,22 @@ export class CustomerBalanceSummaryReport extends ContactBalanceSummaryReport {
|
||||
* @param {IJournalPoster} receivableLedger
|
||||
* @param {ICustomer[]} customers
|
||||
* @param {ICustomerBalanceSummaryQuery} filter
|
||||
* @param {string} baseCurrency
|
||||
* @param {IFinancialReportMeta} meta
|
||||
*/
|
||||
constructor(
|
||||
ledger: ILedger,
|
||||
customers: ModelObject<Customer>[],
|
||||
filter: ICustomerBalanceSummaryQuery,
|
||||
baseCurrency: string
|
||||
meta: IFinancialReportMeta,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.ledger = ledger;
|
||||
this.baseCurrency = baseCurrency;
|
||||
this.baseCurrency = meta.baseCurrency;
|
||||
this.customers = customers;
|
||||
this.filter = filter;
|
||||
this.numberFormat = this.filter.numberFormat;
|
||||
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,7 +19,7 @@ export class CustomerBalanceSummaryMeta {
|
||||
query: ICustomerBalanceSummaryQuery,
|
||||
): Promise<ICustomerBalanceSummaryMeta> {
|
||||
const commonMeta = await this.financialSheetMeta.meta();
|
||||
const formattedAsDate = moment(query.asDate).format('YYYY/MM/DD');
|
||||
const formattedAsDate = moment(query.asDate).format(commonMeta.dateFormat);
|
||||
const formattedDateRange = `As ${formattedAsDate}`;
|
||||
|
||||
return {
|
||||
|
||||
@@ -63,15 +63,16 @@ export class CustomerBalanceSummaryService {
|
||||
// Ledger query.
|
||||
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.
|
||||
const report = new CustomerBalanceSummaryReport(
|
||||
ledger,
|
||||
customers,
|
||||
filter,
|
||||
tenantMetadata.baseCurrency,
|
||||
{ baseCurrency: tenantMetadata.baseCurrency, dateFormat: meta.dateFormat },
|
||||
);
|
||||
// Retrieve the customer balance summary meta.
|
||||
const meta = await this.customerBalanceSummaryMeta.meta(filter);
|
||||
|
||||
// Triggers `onCustomerBalanceSummaryViewed` event.
|
||||
await this.eventPublisher.emitAsync(
|
||||
|
||||
@@ -19,6 +19,7 @@ import { Account } from '@/modules/Accounts/models/Account.model';
|
||||
import { ModelObject } from 'objection';
|
||||
import { flatToNestedArray } from '@/utils/flat-to-nested-array';
|
||||
import { getTransactionTypeLabel } from '@/modules/BankingTransactions/utils';
|
||||
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
|
||||
|
||||
export class GeneralLedgerSheet extends R.compose(FinancialSheetStructure)(
|
||||
FinancialSheet,
|
||||
@@ -33,18 +34,21 @@ export class GeneralLedgerSheet extends R.compose(FinancialSheetStructure)(
|
||||
* @param {IGeneralLedgerSheetQuery} query -
|
||||
* @param {GeneralLedgerRepository} repository -
|
||||
* @param {I18nService} i18n -
|
||||
* @param {IFinancialReportMeta} meta -
|
||||
*/
|
||||
constructor(
|
||||
query: IGeneralLedgerSheetQuery,
|
||||
repository: GeneralLedgerRepository,
|
||||
i18n: I18nService,
|
||||
meta: IFinancialReportMeta,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.query = query;
|
||||
this.numberFormat = this.query.numberFormat;
|
||||
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
|
||||
this.repository = repository;
|
||||
this.baseCurrency = this.repository.tenant.metadata.baseCurrency;
|
||||
this.baseCurrency = meta.baseCurrency;
|
||||
this.i18n = i18n;
|
||||
}
|
||||
|
||||
@@ -87,7 +91,7 @@ export class GeneralLedgerSheet extends R.compose(FinancialSheetStructure)(
|
||||
return {
|
||||
id: entry.id,
|
||||
date: entry.date,
|
||||
dateFormatted: moment(entry.date).format('YYYY MMM DD'),
|
||||
dateFormatted: moment(entry.date).format(this.dateFormat),
|
||||
|
||||
referenceType: entry.transactionType,
|
||||
referenceId: entry.transactionId,
|
||||
|
||||
@@ -6,6 +6,7 @@ export interface IGeneralLedgerSheetQuery {
|
||||
toDate: Date | string;
|
||||
basis: string;
|
||||
numberFormat: IGeneralLedgerNumberFormat;
|
||||
dateFormat?: string;
|
||||
noneTransactions: boolean;
|
||||
accountsIds: number[];
|
||||
branchesIds?: number[];
|
||||
|
||||
@@ -19,8 +19,8 @@ export class GeneralLedgerMeta {
|
||||
): Promise<IGeneralLedgerMeta> {
|
||||
const commonMeta = await this.financialSheetMeta.meta();
|
||||
|
||||
const formattedToDate = moment(query.toDate).format('YYYY/MM/DD');
|
||||
const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
|
||||
const formattedToDate = moment(query.toDate).format(commonMeta.dateFormat);
|
||||
const formattedFromDate = moment(query.fromDate).format(commonMeta.dateFormat);
|
||||
const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`;
|
||||
|
||||
return {
|
||||
|
||||
@@ -37,18 +37,19 @@ export class GeneralLedgerService {
|
||||
this.generalLedgerRepository.setFilter(filter);
|
||||
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.
|
||||
const generalLedgerInstance = new GeneralLedgerSheet(
|
||||
filter,
|
||||
this.generalLedgerRepository,
|
||||
this.i18n,
|
||||
{ baseCurrency: meta.baseCurrency, dateFormat: meta.dateFormat },
|
||||
);
|
||||
// Retrieve general ledger report data.
|
||||
const reportData = generalLedgerInstance.reportData();
|
||||
|
||||
// Retrieve general ledger report metadata.
|
||||
const meta = await this.generalLedgerMeta.meta(filter);
|
||||
|
||||
// Triggers `onGeneralLedgerViewed` event.
|
||||
await this.eventEmitter.emitAsync(events.reports.onGeneralLedgerViewed, {});
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import { InventoryDetails } from './InventoryItemDetails';
|
||||
import { InventoryItemDetailsRepository } from './InventoryItemDetailsRepository';
|
||||
import { InventoryDetailsMetaInjectable } from './InventoryItemDetailsMeta';
|
||||
import { getInventoryItemDetailsDefaultQuery } from './constant';
|
||||
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
|
||||
|
||||
@Injectable()
|
||||
export class InventoryDetailsService {
|
||||
@@ -15,6 +16,7 @@ export class InventoryDetailsService {
|
||||
private readonly inventoryItemDetailsRepository: InventoryItemDetailsRepository,
|
||||
private readonly inventoryDetailsMeta: InventoryDetailsMetaInjectable,
|
||||
private readonly i18n: I18nService,
|
||||
private readonly tenancyContext: TenancyContext,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -34,13 +36,16 @@ export class InventoryDetailsService {
|
||||
this.inventoryItemDetailsRepository.setFilter(filter);
|
||||
await this.inventoryItemDetailsRepository.asyncInit();
|
||||
|
||||
// Retrieve the meta first to get date format.
|
||||
const meta = await this.inventoryDetailsMeta.meta(query);
|
||||
|
||||
// Inventory details report mapper.
|
||||
const inventoryDetailsInstance = new InventoryDetails(
|
||||
filter,
|
||||
this.inventoryItemDetailsRepository,
|
||||
this.i18n,
|
||||
{ baseCurrency: meta.baseCurrency, dateFormat: meta.dateFormat },
|
||||
);
|
||||
const meta = await this.inventoryDetailsMeta.meta(query);
|
||||
|
||||
return {
|
||||
data: inventoryDetailsInstance.reportData(),
|
||||
|
||||
@@ -17,6 +17,8 @@ import { Item } from '@/modules/Items/models/Item';
|
||||
import {
|
||||
IFormatNumberSettings,
|
||||
INumberFormatQuery,
|
||||
IFinancialReportMeta,
|
||||
DEFAULT_REPORT_META,
|
||||
} from '../../types/Report.types';
|
||||
import { InventoryTransaction } from '@/modules/InventoryCost/models/InventoryTransaction';
|
||||
import { InventoryItemDetailsRepository } from './InventoryItemDetailsRepository';
|
||||
@@ -35,11 +37,13 @@ export class InventoryDetails extends FinancialSheet {
|
||||
* Constructor method.
|
||||
* @param {InventoryItemDetailsRepository} repository - The repository.
|
||||
* @param {I18nService} i18n - The i18n service.
|
||||
* @param {IFinancialReportMeta} meta - Report meta.
|
||||
*/
|
||||
constructor(
|
||||
filter: IInventoryDetailsQuery,
|
||||
repository: InventoryItemDetailsRepository,
|
||||
i18n: I18nService,
|
||||
meta: IFinancialReportMeta,
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -48,6 +52,7 @@ export class InventoryDetails extends FinancialSheet {
|
||||
this.query = filter;
|
||||
this.numberFormat = this.query.numberFormat;
|
||||
this.i18n = i18n;
|
||||
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,7 +94,7 @@ export class InventoryDetails extends FinancialSheet {
|
||||
*/
|
||||
public getDateMeta(date: Date | string): IInventoryDetailsDate {
|
||||
return {
|
||||
formattedDate: moment(date).format('YYYY-MM-DD'),
|
||||
formattedDate: moment(date).format(this.dateFormat),
|
||||
date: moment(date).toDate(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ export class InventoryDetailsMetaInjectable {
|
||||
): Promise<IInventoryItemDetailMeta> {
|
||||
const commonMeta = await this.financialSheetMeta.meta();
|
||||
|
||||
const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
|
||||
const formattedToDay = moment(query.toDate).format('YYYY/MM/DD');
|
||||
const formattedFromDate = moment(query.fromDate).format(commonMeta.dateFormat);
|
||||
const formattedToDay = moment(query.toDate).format(commonMeta.dateFormat);
|
||||
const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDay}`;
|
||||
|
||||
const sheetName = 'Inventory Item Details';
|
||||
|
||||
@@ -12,6 +12,7 @@ import { InventoryCostLotTracker } from '@/modules/InventoryCost/models/Inventor
|
||||
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||
import { InventoryValuationSheetRepository } from './InventoryValuationSheetRepository';
|
||||
import { allPassedConditionsPass } from '@/utils/all-conditions-passed';
|
||||
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
|
||||
|
||||
export class InventoryValuationSheet extends FinancialSheet {
|
||||
readonly query: IInventoryValuationReportQuery;
|
||||
@@ -21,16 +22,19 @@ export class InventoryValuationSheet extends FinancialSheet {
|
||||
* Constructor method.
|
||||
* @param {IInventoryValuationReportQuery} query - Inventory valuation query.
|
||||
* @param {InventoryValuationSheetRepository} repository - Inventory valuation sheet repository.
|
||||
* @param {IFinancialReportMeta} meta - Report meta.
|
||||
*/
|
||||
constructor(
|
||||
query: IInventoryValuationReportQuery,
|
||||
repository: InventoryValuationSheetRepository,
|
||||
meta: IFinancialReportMeta,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.query = query;
|
||||
this.repository = repository;
|
||||
this.numberFormat = this.query.numberFormat;
|
||||
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,7 +18,7 @@ export class InventoryValuationMetaInjectable {
|
||||
query: IInventoryValuationReportQuery,
|
||||
): Promise<IInventoryValuationSheetMeta> {
|
||||
const commonMeta = await this.financialSheetMeta.meta();
|
||||
const formattedAsDate = moment(query.asDate).format('YYYY/MM/DD');
|
||||
const formattedAsDate = moment(query.asDate).format(commonMeta.dateFormat);
|
||||
const formattedDateRange = `As ${formattedAsDate}`;
|
||||
|
||||
return {
|
||||
|
||||
@@ -34,16 +34,17 @@ export class InventoryValuationSheetService {
|
||||
this.inventoryValuationSheetRepository.setFilter(filter);
|
||||
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(
|
||||
filter,
|
||||
this.inventoryValuationSheetRepository,
|
||||
{ baseCurrency: meta.baseCurrency, dateFormat: meta.dateFormat },
|
||||
);
|
||||
// Retrieve the inventory valuation report data.
|
||||
const inventoryValuationData = inventoryValuationInstance.reportData();
|
||||
|
||||
// Retrieves the inventorty valuation meta.
|
||||
const meta = await this.inventoryValuationMeta.meta(filter);
|
||||
|
||||
// Triggers `onInventoryValuationViewed` event.
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.reports.onInventoryValuationViewed,
|
||||
|
||||
@@ -11,6 +11,7 @@ import { FinancialSheet } from '../../common/FinancialSheet';
|
||||
import { JournalSheetRepository } from './JournalSheetRepository';
|
||||
import { ILedgerEntry } from '@/modules/Ledger/types/Ledger.types';
|
||||
import { getTransactionTypeLabel } from '@/modules/BankingTransactions/utils';
|
||||
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
|
||||
|
||||
export class JournalSheet extends FinancialSheet {
|
||||
readonly query: IJournalReportQuery;
|
||||
@@ -22,20 +23,24 @@ export class JournalSheet extends FinancialSheet {
|
||||
* @param {IJournalReportQuery} query -
|
||||
* @param {JournalSheetRepository} repository -
|
||||
* @param {I18nService} i18n -
|
||||
* @param {IFinancialReportMeta} meta -
|
||||
*/
|
||||
constructor(
|
||||
query: IJournalReportQuery,
|
||||
repository: JournalSheetRepository,
|
||||
i18n: I18nService,
|
||||
meta: IFinancialReportMeta,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.query = query;
|
||||
this.repository = repository;
|
||||
this.baseCurrency = meta.baseCurrency;
|
||||
this.numberFormat = {
|
||||
...this.numberFormat,
|
||||
...this.query.numberFormat,
|
||||
};
|
||||
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
|
||||
this.i18n = i18n;
|
||||
}
|
||||
|
||||
@@ -94,7 +99,7 @@ export class JournalSheet extends FinancialSheet {
|
||||
|
||||
return {
|
||||
date: moment(groupEntry.date).toDate(),
|
||||
dateFormatted: moment(groupEntry.date).format('YYYY MMM DD'),
|
||||
dateFormatted: moment(groupEntry.date).format(this.dateFormat),
|
||||
|
||||
transactionType: groupEntry.transactionType,
|
||||
referenceId: groupEntry.transactionId,
|
||||
|
||||
@@ -8,6 +8,7 @@ export interface IJournalReportQuery {
|
||||
noCents: boolean;
|
||||
divideOn1000: boolean;
|
||||
};
|
||||
dateFormat?: string;
|
||||
transactionType: string;
|
||||
transactionId: string;
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ export class JournalSheetMeta {
|
||||
): Promise<IJournalSheetMeta> {
|
||||
const common = await this.financialSheetMeta.meta();
|
||||
|
||||
const formattedToDate = moment(query.toDate).format('YYYY/MM/DD');
|
||||
const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
|
||||
const formattedToDate = moment(query.toDate).format(common.dateFormat);
|
||||
const formattedFromDate = moment(query.fromDate).format(common.dateFormat);
|
||||
const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`;
|
||||
|
||||
return {
|
||||
|
||||
@@ -30,18 +30,19 @@ export class JournalSheetService {
|
||||
this.journalRepository.setFilter(query);
|
||||
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.
|
||||
const journalSheetInstance = new JournalSheet(
|
||||
filter,
|
||||
this.journalRepository,
|
||||
this.i18n,
|
||||
{ baseCurrency: meta.baseCurrency, dateFormat: meta.dateFormat },
|
||||
);
|
||||
// Retrieve journal report columns.
|
||||
const journalSheetData = journalSheetInstance.reportData();
|
||||
|
||||
// Retrieve the journal sheet meta.
|
||||
const meta = await this.journalSheetMeta.meta(filter);
|
||||
|
||||
// Triggers `onJournalViewed` event.
|
||||
await this.eventPublisher.emitAsync(events.reports.onJournalViewed, {
|
||||
query,
|
||||
|
||||
@@ -28,6 +28,7 @@ import { FinancialSheetStructure } from '../../common/FinancialSheetStructure';
|
||||
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||
import { Account } from '@/modules/Accounts/models/Account.model';
|
||||
import { flatToNestedArray } from '@/utils/flat-to-nested-array';
|
||||
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
|
||||
|
||||
export default class ProfitLossSheet extends R.pipe(
|
||||
ProfitLossSheetPreviousYear,
|
||||
@@ -71,20 +72,24 @@ export default class ProfitLossSheet extends R.pipe(
|
||||
|
||||
/**
|
||||
* Constructor method.
|
||||
* @param {ProfitLossSheetRepository} repository -
|
||||
* @param {IProfitLossSheetQuery} query -
|
||||
* @param {IAccount[]} accounts -
|
||||
* @param {IJournalPoster} transactionsJournal -
|
||||
* @param {I18nService} i18n -
|
||||
* @param {IFinancialReportMeta} meta -
|
||||
*/
|
||||
constructor(
|
||||
repository: ProfitLossSheetRepository,
|
||||
query: IProfitLossSheetQuery,
|
||||
i18n: I18nService,
|
||||
meta: IFinancialReportMeta,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.query = new ProfitLossSheetQuery(query);
|
||||
this.repository = repository;
|
||||
this.baseCurrency = meta.baseCurrency;
|
||||
this.numberFormat = this.query.query.numberFormat;
|
||||
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
|
||||
this.i18n = i18n;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ export class ProfitLossSheetMeta {
|
||||
query: IProfitLossSheetQuery,
|
||||
): Promise<IProfitLossSheetMeta> {
|
||||
const commonMeta = await this.financialSheetMeta.meta();
|
||||
const formattedToDate = moment(query.toDate).format('YYYY/MM/DD');
|
||||
const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
|
||||
const formattedToDate = moment(query.toDate).format(commonMeta.dateFormat);
|
||||
const formattedFromDate = moment(query.fromDate).format(commonMeta.dateFormat);
|
||||
const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`;
|
||||
|
||||
const sheetName = 'Cashflow Statement';
|
||||
|
||||
@@ -40,18 +40,19 @@ export class ProfitLossSheetService {
|
||||
this.profitLossRepository.setFilter(filter);
|
||||
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.
|
||||
const profitLossInstance = new ProfitLossSheet(
|
||||
this.profitLossRepository,
|
||||
filter,
|
||||
this.i18nService,
|
||||
{ baseCurrency: meta.baseCurrency, dateFormat: meta.dateFormat },
|
||||
);
|
||||
// Profit/loss report data and columns.
|
||||
const data = profitLossInstance.reportData();
|
||||
|
||||
// Retrieve the profit/loss sheet meta.
|
||||
const meta = await this.profitLossSheetMeta.meta(filter);
|
||||
|
||||
// Triggers `onProfitLossSheetViewed` event.
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.reports.onProfitLossSheetViewed,
|
||||
|
||||
@@ -73,17 +73,17 @@ export class PurchasesByItemsService {
|
||||
// Filter the date range of the sheet.
|
||||
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(
|
||||
filter,
|
||||
inventoryItems,
|
||||
inventoryTransactions,
|
||||
tenantMetadata.baseCurrency,
|
||||
{ baseCurrency: tenantMetadata.baseCurrency, dateFormat: meta.dateFormat },
|
||||
);
|
||||
const purchasesByItemsData = purchasesByItemsInstance.reportData();
|
||||
|
||||
// Retrieve the purchases by items meta.
|
||||
const meta = await this.purchasesByItemsMeta.meta(query);
|
||||
|
||||
// Triggers `onPurchasesByItemViewed` event.
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.reports.onPurchasesByItemViewed,
|
||||
|
||||
@@ -11,6 +11,7 @@ import { FinancialSheet } from '../../common/FinancialSheet';
|
||||
import { transformToMapBy } from '@/utils/transform-to-map-by';
|
||||
import { Item } from '@/modules/Items/models/Item';
|
||||
import { InventoryTransaction } from '@/modules/InventoryCost/models/InventoryTransaction';
|
||||
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
|
||||
|
||||
export class PurchasesByItems extends FinancialSheet{
|
||||
readonly baseCurrency: string;
|
||||
@@ -29,14 +30,15 @@ export class PurchasesByItems extends FinancialSheet{
|
||||
query: IPurchasesByItemsReportQuery,
|
||||
items: Item[],
|
||||
itemsTransactions: InventoryTransaction[],
|
||||
baseCurrency: string
|
||||
meta: IFinancialReportMeta,
|
||||
) {
|
||||
super();
|
||||
this.baseCurrency = baseCurrency;
|
||||
this.baseCurrency = meta.baseCurrency;
|
||||
this.items = items;
|
||||
this.itemsTransactions = transformToMapBy(itemsTransactions, 'itemId');
|
||||
this.query = query;
|
||||
this.numberFormat = this.query.numberFormat;
|
||||
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,8 +21,8 @@ export class PurchasesByItemsMeta {
|
||||
query: IPurchasesByItemsReportQuery
|
||||
): Promise<IPurchasesByItemsSheetMeta> {
|
||||
const commonMeta = await this.financialSheetMetaModel.meta();
|
||||
const formattedToDate = moment(query.toDate).format('YYYY/MM/DD');
|
||||
const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
|
||||
const formattedToDate = moment(query.toDate).format(commonMeta.dateFormat);
|
||||
const formattedFromDate = moment(query.fromDate).format(commonMeta.dateFormat);
|
||||
const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`;
|
||||
|
||||
return {
|
||||
|
||||
@@ -12,6 +12,7 @@ import { Item } from '@/modules/Items/models/Item';
|
||||
import { transformToMap } from '@/utils/transform-to-key';
|
||||
import { allPassedConditionsPass } from '@/utils/all-conditions-passed';
|
||||
import { InventoryTransaction } from '@/modules/InventoryCost/models/InventoryTransaction';
|
||||
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
|
||||
|
||||
export class SalesByItemsReport extends FinancialSheet {
|
||||
readonly baseCurrency: string;
|
||||
@@ -24,21 +25,22 @@ export class SalesByItemsReport extends FinancialSheet {
|
||||
* @param {ISalesByItemsReportQuery} query
|
||||
* @param {IItem[]} items
|
||||
* @param {IAccountTransaction[]} itemsTransactions
|
||||
* @param {string} baseCurrency
|
||||
* @param {IFinancialReportMeta} meta
|
||||
*/
|
||||
constructor(
|
||||
query: ISalesByItemsReportQuery,
|
||||
items: Item[],
|
||||
itemsTransactions: ModelObject<InventoryTransaction>[],
|
||||
baseCurrency: string,
|
||||
meta: IFinancialReportMeta,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.baseCurrency = baseCurrency;
|
||||
this.baseCurrency = meta.baseCurrency;
|
||||
this.items = items;
|
||||
this.itemsTransactions = transformToMap(itemsTransactions, 'itemId');
|
||||
this.query = query;
|
||||
this.numberFormat = this.query.numberFormat;
|
||||
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,8 +18,8 @@ export class SalesByItemsMeta {
|
||||
query: ISalesByItemsReportQuery,
|
||||
): Promise<ISalesByItemsSheetMeta> {
|
||||
const commonMeta = await this.financialSheetMeta.meta();
|
||||
const formattedToDate = moment(query.toDate).format('YYYY/MM/DD');
|
||||
const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
|
||||
const formattedToDate = moment(query.toDate).format(commonMeta.dateFormat);
|
||||
const formattedFromDate = moment(query.fromDate).format(commonMeta.dateFormat);
|
||||
const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`;
|
||||
|
||||
const sheetName = 'Sales By Items';
|
||||
|
||||
@@ -68,17 +68,17 @@ export class SalesByItemsReportService {
|
||||
// Filter the date range of the sheet.
|
||||
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(
|
||||
filter,
|
||||
inventoryItems,
|
||||
inventoryTransactions,
|
||||
tenantMetadata.baseCurrency,
|
||||
{ baseCurrency: tenantMetadata.baseCurrency, dateFormat: meta.dateFormat },
|
||||
);
|
||||
const salesByItemsData = sheet.reportData();
|
||||
|
||||
// Retrieve the sales by items meta.
|
||||
const meta = await this.salesByItemsMeta.meta(query);
|
||||
|
||||
// Triggers `onSalesByItemViewed` event.
|
||||
await this.eventPublisher.emitAsync(events.reports.onSalesByItemViewed, {
|
||||
query,
|
||||
|
||||
@@ -8,9 +8,10 @@ import { SalesTaxLiabilitySummaryController } from './SalesTaxLiabilitySummary.c
|
||||
import { FinancialSheetCommonModule } from '../../common/FinancialSheetCommon.module';
|
||||
import { SalesTaxLiabilitySummaryRepository } from './SalesTaxLiabilitySummaryRepository';
|
||||
import { SalesTaxLiabilitySummaryMeta } from './SalesTaxLiabilitySummaryMeta';
|
||||
import { TenancyModule } from '@/modules/Tenancy/Tenancy.module';
|
||||
|
||||
@Module({
|
||||
imports: [FinancialSheetCommonModule],
|
||||
imports: [FinancialSheetCommonModule, TenancyModule],
|
||||
providers: [
|
||||
SalesTaxLiabiltiySummaryPdf,
|
||||
SalesTaxLiabilitySummaryTableInjectable,
|
||||
|
||||
@@ -10,6 +10,7 @@ import { FinancialSheet } from '../../common/FinancialSheet';
|
||||
import { ModelObject } from 'objection';
|
||||
import { TaxRateModel } from '@/modules/TaxRates/models/TaxRate.model';
|
||||
import { SalesTaxLiabilitySummaryRepository } from './SalesTaxLiabilitySummaryRepository';
|
||||
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
|
||||
|
||||
export class SalesTaxLiabilitySummary extends FinancialSheet {
|
||||
private query: SalesTaxLiabilitySummaryQuery;
|
||||
@@ -18,18 +19,19 @@ export class SalesTaxLiabilitySummary extends FinancialSheet {
|
||||
/**
|
||||
* Sales tax liability summary constructor.
|
||||
* @param {SalesTaxLiabilitySummaryQuery} query
|
||||
* @param {ITaxRate[]} taxRates
|
||||
* @param {SalesTaxLiabilitySummaryPayableById} payableTaxesById
|
||||
* @param {SalesTaxLiabilitySummarySalesById} salesTaxesById
|
||||
* @param {SalesTaxLiabilitySummaryRepository} repository
|
||||
* @param {IFinancialReportMeta} meta
|
||||
*/
|
||||
constructor(
|
||||
query: SalesTaxLiabilitySummaryQuery,
|
||||
repository: SalesTaxLiabilitySummaryRepository,
|
||||
meta: IFinancialReportMeta,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.query = query;
|
||||
this.repository = repository;
|
||||
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,8 +14,8 @@ export class SalesTaxLiabilitySummaryMeta {
|
||||
*/
|
||||
public async meta(query: SalesTaxLiabilitySummaryQuery) {
|
||||
const commonMeta = await this.financialSheetMeta.meta();
|
||||
const formattedToDate = moment(query.toDate).format('YYYY/MM/DD');
|
||||
const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
|
||||
const formattedToDate = moment(query.toDate).format(commonMeta.dateFormat);
|
||||
const formattedFromDate = moment(query.fromDate).format(commonMeta.dateFormat);
|
||||
const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`;
|
||||
|
||||
const sheetName = 'Sales Tax Liability Summary';
|
||||
|
||||
@@ -3,12 +3,14 @@ import { SalesTaxLiabilitySummary } from './SalesTaxLiabilitySummary';
|
||||
import { SalesTaxLiabilitySummaryMeta } from './SalesTaxLiabilitySummaryMeta';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { SalesTaxLiabilitySummaryQuery } from './SalesTaxLiability.types';
|
||||
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
|
||||
|
||||
@Injectable()
|
||||
export class SalesTaxLiabilitySummaryService {
|
||||
constructor(
|
||||
private readonly repository: SalesTaxLiabilitySummaryRepository,
|
||||
private readonly salesTaxLiabilityMeta: SalesTaxLiabilitySummaryMeta,
|
||||
private readonly tenancyContext: TenancyContext,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -19,11 +21,17 @@ export class SalesTaxLiabilitySummaryService {
|
||||
public async salesTaxLiability(query: SalesTaxLiabilitySummaryQuery) {
|
||||
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(
|
||||
query,
|
||||
this.repository,
|
||||
{ baseCurrency: tenantMetadata.baseCurrency, dateFormat: meta.dateFormat },
|
||||
);
|
||||
const meta = await this.salesTaxLiabilityMeta.meta(query);
|
||||
|
||||
return {
|
||||
data: taxLiabilitySummary.reportData(),
|
||||
|
||||
@@ -14,9 +14,10 @@ enum ROW_TYPE {
|
||||
|
||||
export class TransactionsByContactsTableRows {
|
||||
public i18n: I18nService;
|
||||
public dateFormat: string;
|
||||
|
||||
public dateAccessor = (value): string => {
|
||||
return moment(value.date).format('YYYY MMM DD');
|
||||
return moment(value.date).format(this.dateFormat);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,6 +12,7 @@ import { TransactionsByContact } from '../TransactionsByContact/TransactionsByCo
|
||||
import { Customer } from '@/modules/Customers/models/Customer';
|
||||
import { INumberFormatQuery } from '../../types/Report.types';
|
||||
import { TransactionsByCustomersRepository } from './TransactionsByCustomersRepository';
|
||||
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
|
||||
|
||||
const CUSTOMER_NORMAL = 'debit';
|
||||
|
||||
@@ -25,12 +26,14 @@ export class TransactionsByCustomers extends TransactionsByContact {
|
||||
* Constructor method.
|
||||
* @param {ICustomer} customers
|
||||
* @param {Map<number, IAccountTransaction[]>} transactionsLedger
|
||||
* @param {string} baseCurrency
|
||||
* @param {I18nService} i18n
|
||||
* @param {IFinancialReportMeta} meta
|
||||
*/
|
||||
constructor(
|
||||
filter: ITransactionsByCustomersFilter,
|
||||
transactionsByCustomersRepository: TransactionsByCustomersRepository,
|
||||
i18n: I18nService
|
||||
i18n: I18nService,
|
||||
meta: IFinancialReportMeta,
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -38,6 +41,8 @@ export class TransactionsByCustomers extends TransactionsByContact {
|
||||
this.repository = transactionsByCustomersRepository;
|
||||
this.numberFormat = this.filter.numberFormat;
|
||||
this.i18n = i18n;
|
||||
this.baseCurrency = meta.baseCurrency;
|
||||
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,8 +20,8 @@ export class TransactionsByCustomersMeta {
|
||||
): Promise<ITransactionsByCustomersMeta> {
|
||||
const commonMeta = await this.financialSheetMeta.meta();
|
||||
|
||||
const formattedToDate = moment(query.toDate).format('YYYY/MM/DD');
|
||||
const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
|
||||
const formattedToDate = moment(query.toDate).format(commonMeta.dateFormat);
|
||||
const formattedFromDate = moment(query.fromDate).format(commonMeta.dateFormat);
|
||||
const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`;
|
||||
|
||||
return {
|
||||
|
||||
@@ -36,13 +36,16 @@ export class TransactionsByCustomersSheet {
|
||||
this.transactionsByCustomersRepository.setFilter(filter);
|
||||
await this.transactionsByCustomersRepository.asyncInit();
|
||||
|
||||
// Retrieve the meta first to get date format.
|
||||
const meta = await this.transactionsByCustomersMeta.meta(filter);
|
||||
|
||||
// Transactions by customers data mapper.
|
||||
const reportInstance = new TransactionsByCustomers(
|
||||
filter,
|
||||
this.transactionsByCustomersRepository,
|
||||
this.i18n,
|
||||
{ baseCurrency: meta.baseCurrency, dateFormat: meta.dateFormat },
|
||||
);
|
||||
const meta = await this.transactionsByCustomersMeta.meta(filter);
|
||||
|
||||
// Triggers `onCustomerTransactionsViewed` event.
|
||||
await this.eventPublisher.emitAsync(
|
||||
|
||||
@@ -22,10 +22,12 @@ export class TransactionsByCustomersTable extends TransactionsByContactsTableRow
|
||||
constructor(
|
||||
customersTransactions: ITransactionsByCustomersCustomer[],
|
||||
i18n: I18nService,
|
||||
dateFormat: string,
|
||||
) {
|
||||
super();
|
||||
this.customersTransactions = customersTransactions;
|
||||
this.i18n = i18n;
|
||||
this.dateFormat = dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,6 +28,7 @@ export class TransactionsByCustomersTableInjectable {
|
||||
const table = new TransactionsByCustomersTable(
|
||||
customersTransactions.data,
|
||||
this.i18n,
|
||||
customersTransactions.meta.dateFormat,
|
||||
);
|
||||
return {
|
||||
table: {
|
||||
|
||||
@@ -38,7 +38,7 @@ export class TransactionsByReferenceService {
|
||||
const report = new TransactionsByReference(
|
||||
transactions,
|
||||
filter,
|
||||
tenantMetadata.baseCurrency
|
||||
{ baseCurrency: tenantMetadata.baseCurrency, dateFormat: tenantMetadata.dateFormat }
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||
import { ModelObject } from 'objection';
|
||||
import { AccountTransaction } from '@/modules/Accounts/models/AccountTransaction.model';
|
||||
import { INumberFormatQuery } from '../../types/Report.types';
|
||||
import { INumberFormatQuery, IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
|
||||
import { TransactionsByReferenceQueryDto } from './TransactionsByReferenceQuery.dto';
|
||||
|
||||
export class TransactionsByReference extends FinancialSheet {
|
||||
@@ -17,18 +17,19 @@ export class TransactionsByReference extends FinancialSheet {
|
||||
* Constructor method.
|
||||
* @param {ModelObject<AccountTransaction>[]} transactions
|
||||
* @param {TransactionsByVendorQueryDto} query
|
||||
* @param {string} baseCurrency
|
||||
* @param {IFinancialReportMeta} meta
|
||||
*/
|
||||
constructor(
|
||||
transactions: ModelObject<AccountTransaction>[],
|
||||
query: TransactionsByReferenceQueryDto,
|
||||
baseCurrency: string
|
||||
meta: IFinancialReportMeta,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.transactions = transactions;
|
||||
this.query = query;
|
||||
this.baseCurrency = baseCurrency;
|
||||
this.baseCurrency = meta.baseCurrency;
|
||||
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
|
||||
// this.numberFormat = this.query.numberFormat;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import { TransactionsByContact } from '../TransactionsByContact/TransactionsByCo
|
||||
import { Vendor } from '@/modules/Vendors/models/Vendor';
|
||||
import { INumberFormatQuery } from '../../types/Report.types';
|
||||
import { TransactionsByVendorRepository } from './TransactionsByVendorRepository';
|
||||
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
|
||||
|
||||
const VENDOR_NORMAL = 'credit';
|
||||
|
||||
@@ -26,11 +27,13 @@ export class TransactionsByVendor extends TransactionsByContact {
|
||||
* @param {TransactionsByVendorRepository} transactionsByVendorRepository - Transactions by vendor repository.
|
||||
* @param {ITransactionsByVendorsFilter} filter - Transactions by vendors filter.
|
||||
* @param {I18nService} i18n - Internationalization service.
|
||||
* @param {IFinancialReportMeta} meta - Report meta.
|
||||
*/
|
||||
constructor(
|
||||
transactionsByVendorRepository: TransactionsByVendorRepository,
|
||||
filter: ITransactionsByVendorsFilter,
|
||||
i18n: I18nService,
|
||||
meta: IFinancialReportMeta,
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -38,6 +41,8 @@ export class TransactionsByVendor extends TransactionsByContact {
|
||||
this.filter = filter;
|
||||
this.numberFormat = this.filter.numberFormat;
|
||||
this.i18n = i18n;
|
||||
this.baseCurrency = meta.baseCurrency;
|
||||
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -36,13 +36,16 @@ export class TransactionsByVendorsInjectable {
|
||||
// Initialize the repository.
|
||||
await this.transactionsByVendorRepository.asyncInit();
|
||||
|
||||
// Transactions by customers data mapper.
|
||||
// Retrieve the meta first to get date format.
|
||||
const meta = await this.transactionsByVendorMeta.meta(filter);
|
||||
|
||||
// Transactions by vendors data mapper.
|
||||
const reportInstance = new TransactionsByVendor(
|
||||
this.transactionsByVendorRepository,
|
||||
filter,
|
||||
this.i18n,
|
||||
{ baseCurrency: meta.baseCurrency, dateFormat: meta.dateFormat },
|
||||
);
|
||||
const meta = await this.transactionsByVendorMeta.meta(filter);
|
||||
|
||||
// Triggers `onVendorTransactionsViewed` event.
|
||||
await this.eventPublisher.emitAsync(
|
||||
|
||||
@@ -21,8 +21,8 @@ export class TransactionsByVendorMeta {
|
||||
): Promise<ITransactionsByVendorMeta> {
|
||||
const commonMeta = await this.financialSheetMeta.meta();
|
||||
|
||||
const formattedToDate = moment(query.toDate).format('YYYY/MM/DD');
|
||||
const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
|
||||
const formattedToDate = moment(query.toDate).format(commonMeta.dateFormat);
|
||||
const formattedFromDate = moment(query.fromDate).format(commonMeta.dateFormat);
|
||||
const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`;
|
||||
|
||||
const sheetName = 'Transactions By Vendor';
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as R from 'ramda';
|
||||
import { I18nService } from 'nestjs-i18n';
|
||||
import { ITransactionsByVendorsVendor } from './TransactionsByVendor.types';
|
||||
import { TransactionsByContactsTableRows } from '../TransactionsByContact/TransactionsByContactTableRows';
|
||||
import { tableRowMapper } from '../../utils/Table.utils';
|
||||
@@ -19,11 +20,16 @@ export class TransactionsByVendorsTable extends TransactionsByContactsTableRows
|
||||
* @param {ITransactionsByVendorsVendor[]} vendorsTransactions -
|
||||
* @param {any} i18n
|
||||
*/
|
||||
constructor(vendorsTransactions: ITransactionsByVendorsVendor[], i18n) {
|
||||
constructor(
|
||||
vendorsTransactions: ITransactionsByVendorsVendor[],
|
||||
i18n: I18nService,
|
||||
dateFormat: string,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.vendorsTransactions = vendorsTransactions;
|
||||
this.i18n = i18n;
|
||||
this.dateFormat = dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,7 +25,7 @@ export class TransactionsByVendorTableInjectable {
|
||||
const sheet = await this.transactionsByVendor.transactionsByVendors(
|
||||
query
|
||||
);
|
||||
const table = new TransactionsByVendorsTable(sheet.data, this.i18n);
|
||||
const table = new TransactionsByVendorsTable(sheet.data, this.i18n, sheet.meta.dateFormat);
|
||||
|
||||
return {
|
||||
table: {
|
||||
|
||||
@@ -12,6 +12,7 @@ import { Account } from '@/modules/Accounts/models/Account.model';
|
||||
import { allPassedConditionsPass } from '@/utils/all-conditions-passed';
|
||||
import { ModelObject } from 'objection';
|
||||
import { flatToNestedArray } from '@/utils/flat-to-nested-array';
|
||||
import { IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
|
||||
|
||||
export class TrialBalanceSheet extends FinancialSheet {
|
||||
/**
|
||||
@@ -42,14 +43,15 @@ export class TrialBalanceSheet extends FinancialSheet {
|
||||
constructor(
|
||||
query: ITrialBalanceSheetQuery,
|
||||
repository: TrialBalanceSheetRepository,
|
||||
baseCurrency: string
|
||||
meta: IFinancialReportMeta,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.query = query;
|
||||
this.repository = repository;
|
||||
this.numberFormat = this.query.numberFormat;
|
||||
this.baseCurrency = baseCurrency;
|
||||
this.baseCurrency = meta.baseCurrency;
|
||||
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -39,18 +39,18 @@ export class TrialBalanceSheetService {
|
||||
// Loads the resources.
|
||||
await this.trialBalanceSheetRepository.asyncInitialize();
|
||||
|
||||
// Trial balance sheet meta first to get date format.
|
||||
const meta = await this.trialBalanceSheetMetaService.meta(filter);
|
||||
|
||||
// Trial balance report instance.
|
||||
const trialBalanceInstance = new TrialBalanceSheet(
|
||||
filter,
|
||||
this.trialBalanceSheetRepository,
|
||||
tenantMetadata.baseCurrency,
|
||||
{ baseCurrency: tenantMetadata.baseCurrency, dateFormat: meta.dateFormat },
|
||||
);
|
||||
// Trial balance sheet data.
|
||||
const trialBalanceSheetData = trialBalanceInstance.reportData();
|
||||
|
||||
// Trial balance sheet meta.
|
||||
const meta = await this.trialBalanceSheetMetaService.meta(filter);
|
||||
|
||||
// Triggers `onTrialBalanceSheetViewed` event.
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.reports.onTrialBalanceSheetView,
|
||||
|
||||
@@ -16,8 +16,8 @@ export class TrialBalanceSheetMeta {
|
||||
): Promise<ITrialBalanceSheetMeta> {
|
||||
const commonMeta = await this.financialSheetMeta.meta();
|
||||
|
||||
const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
|
||||
const formattedToDate = moment(query.toDate).format('YYYY/MM/DD');
|
||||
const formattedFromDate = moment(query.fromDate).format(commonMeta.dateFormat);
|
||||
const formattedToDate = moment(query.toDate).format(commonMeta.dateFormat);
|
||||
const formattedDateRange = `From ${formattedFromDate} to ${formattedToDate}`;
|
||||
|
||||
const sheetName = 'Trial Balance Sheet';
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
} from './VendorBalanceSummary.types';
|
||||
import { ContactBalanceSummaryReport } from '../ContactBalanceSummary/ContactBalanceSummary';
|
||||
import { Vendor } from '@/modules/Vendors/models/Vendor';
|
||||
import { INumberFormatQuery } from '../../types/Report.types';
|
||||
import { INumberFormatQuery, IFinancialReportMeta, DEFAULT_REPORT_META } from '../../types/Report.types';
|
||||
import { VendorBalanceSummaryRepository } from './VendorBalanceSummaryRepository';
|
||||
import { Ledger } from '@/modules/Ledger/Ledger';
|
||||
|
||||
@@ -27,15 +27,17 @@ export class VendorBalanceSummaryReport extends ContactBalanceSummaryReport {
|
||||
constructor(
|
||||
repository: VendorBalanceSummaryRepository,
|
||||
filter: IVendorBalanceSummaryQuery,
|
||||
meta: IFinancialReportMeta,
|
||||
) {
|
||||
super();
|
||||
|
||||
|
||||
this.repository = repository;
|
||||
this.ledger = this.repository.ledger;
|
||||
this.baseCurrency = this.repository.baseCurrency;
|
||||
this.baseCurrency = meta.baseCurrency;
|
||||
|
||||
this.filter = filter;
|
||||
this.numberFormat = this.filter.numberFormat;
|
||||
this.dateFormat = meta.dateFormat || DEFAULT_REPORT_META.dateFormat;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ export class VendorBalanceSummaryMeta {
|
||||
query: IVendorBalanceSummaryQuery,
|
||||
): Promise<IVendorBalanceSummaryMeta> {
|
||||
const commonMeta = await this.financialSheetMeta.meta();
|
||||
const formattedAsDate = moment(query.asDate).format('YYYY/MM/DD');
|
||||
const formattedAsDate = moment(query.asDate).format(commonMeta.dateFormat);
|
||||
|
||||
return {
|
||||
...commonMeta,
|
||||
|
||||
@@ -31,13 +31,15 @@ export class VendorBalanceSummaryService {
|
||||
this.vendorBalanceSummaryRepository.setFilter(filter);
|
||||
await this.vendorBalanceSummaryRepository.asyncInit();
|
||||
|
||||
// Retrieve the vendor balance summary meta first to get date format.
|
||||
const meta = await this.vendorBalanceSummaryMeta.meta(filter);
|
||||
|
||||
// Report instance.
|
||||
const reportInstance = new VendorBalanceSummaryReport(
|
||||
this.vendorBalanceSummaryRepository,
|
||||
filter,
|
||||
{ baseCurrency: this.vendorBalanceSummaryRepository.baseCurrency, dateFormat: meta.dateFormat },
|
||||
);
|
||||
// Retrieve the vendor balance summary meta.
|
||||
const meta = await this.vendorBalanceSummaryMeta.meta(filter);
|
||||
|
||||
// Triggers `onVendorBalanceSummaryViewed` event.
|
||||
await this.eventEmitter.emitAsync(
|
||||
|
||||
@@ -52,6 +52,22 @@ export interface IFinancialSheetCommonMeta {
|
||||
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 {
|
||||
Day = 'day',
|
||||
Month = 'month',
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
import currencies from 'js-money/lib/currency';
|
||||
|
||||
export const DATE_FORMATS = [
|
||||
'MM.dd.yy',
|
||||
'dd.MM.yy',
|
||||
'yy.MM.dd',
|
||||
'MM.dd.yyyy',
|
||||
'dd.MM.yyyy',
|
||||
'yyyy.MM.dd',
|
||||
'MM/DD/YYYY',
|
||||
'M/D/YYYY',
|
||||
'dd MMM YYYY',
|
||||
'dd MMMM YYYY',
|
||||
'MMMM dd, YYYY',
|
||||
'EEE, MMMM dd, YYYY',
|
||||
'MM/DD/YY',
|
||||
'DD/MM/YY',
|
||||
'YY/MM/DD',
|
||||
'MM/DD/yyyy',
|
||||
'DD/MM/yyyy',
|
||||
'yyyy/MM/DD',
|
||||
'DD MMM YYYY',
|
||||
'DD MMMM YYYY',
|
||||
'MMMM DD, YYYY',
|
||||
];
|
||||
export const MONTHS = [
|
||||
'january',
|
||||
|
||||
@@ -12,6 +12,6 @@ export const transformBuildDto = (
|
||||
): BuildOrganizationDto => {
|
||||
return {
|
||||
...buildDTO,
|
||||
dateFormat: defaultTo(buildDTO.dateFormat, 'DD MMM yyyy'),
|
||||
dateFormat: defaultTo(buildDTO.dateFormat, 'DD MMM YYYY'),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -48,7 +48,10 @@ export class EditVendorDto extends ContactAddressDto {
|
||||
@IsString()
|
||||
personalPhone?: string;
|
||||
|
||||
@ApiProperty({ required: false, description: 'Additional notes about the vendor' })
|
||||
@ApiProperty({
|
||||
required: false,
|
||||
description: 'Additional notes about the vendor',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
note?: string;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import React from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
import { Intent, Menu, MenuItem, Tag } from '@blueprintjs/core';
|
||||
import { FormatDateCell, Icon } from '@/components';
|
||||
import { Icon } from '@/components';
|
||||
import { safeCallback } from '@/utils';
|
||||
import { useAccountTransactionsContext } from './AccountTransactionsProvider';
|
||||
import FinancialLoadingBar from '@/containers/FinancialStatements/FinancialLoadingBar';
|
||||
@@ -75,8 +75,7 @@ export function useAccountTransactionsColumns() {
|
||||
{
|
||||
id: 'date',
|
||||
Header: intl.get('date'),
|
||||
accessor: 'date',
|
||||
Cell: FormatDateCell,
|
||||
accessor: 'formatted_date',
|
||||
width: 110,
|
||||
className: 'date',
|
||||
clickable: true,
|
||||
|
||||
@@ -82,7 +82,7 @@ function CashflowBankAccount({
|
||||
const handleEditAccount = () => {
|
||||
openDialog(DialogsName.AccountForm, {
|
||||
action: AccountDialogAction.Edit,
|
||||
id: account.id,
|
||||
accountId: account.id,
|
||||
});
|
||||
};
|
||||
// Handle money in menu item actions.
|
||||
|
||||
@@ -27,20 +27,20 @@ const CustomerBillingAddress = ({}) => {
|
||||
|
||||
{/*------------ Billing Address 1 -----------*/}
|
||||
<FFormGroup
|
||||
name={'billing_address_1'}
|
||||
name={'billing_address1'}
|
||||
label={<T id={'address_line_1'} />}
|
||||
inline={true}
|
||||
>
|
||||
<FTextArea name={'billing_address_1'} />
|
||||
<FTextArea name={'billing_address1'} />
|
||||
</FFormGroup>
|
||||
|
||||
{/*------------ Billing Address 2 -----------*/}
|
||||
<FFormGroup
|
||||
name={'billing_address_2'}
|
||||
name={'billing_address2'}
|
||||
label={<T id={'address_line_2'} />}
|
||||
inline={true}
|
||||
>
|
||||
<FTextArea name={'billing_address_2'} />
|
||||
<FTextArea name={'billing_address2'} />
|
||||
</FFormGroup>
|
||||
{/*------------ Billing Address city -----------*/}
|
||||
<FFormGroup
|
||||
@@ -93,20 +93,20 @@ const CustomerBillingAddress = ({}) => {
|
||||
|
||||
{/*------------ Shipping Address 1 -----------*/}
|
||||
<FFormGroup
|
||||
name={'shipping_address_1'}
|
||||
name={'shipping_address1'}
|
||||
label={<T id={'address_line_1'} />}
|
||||
inline={true}
|
||||
>
|
||||
<FTextArea name={'shipping_address_1'} />
|
||||
<FTextArea name={'shipping_address1'} />
|
||||
</FFormGroup>
|
||||
|
||||
{/*------------ Shipping Address 2 -----------*/}
|
||||
<FFormGroup
|
||||
name={'shipping_address_2'}
|
||||
name={'shipping_address2'}
|
||||
label={<T id={'address_line_2'} />}
|
||||
inline={true}
|
||||
>
|
||||
<FTextArea name={'shipping_address_2'} />
|
||||
<FTextArea name={'shipping_address2'} />
|
||||
</FFormGroup>
|
||||
|
||||
{/*------------ Shipping Address city -----------*/}
|
||||
|
||||
@@ -25,16 +25,16 @@ const Schema = Yup.object().shape({
|
||||
note: Yup.string().trim(),
|
||||
|
||||
billing_address_country: Yup.string().trim(),
|
||||
billing_address_1: Yup.string().trim(),
|
||||
billing_address_2: Yup.string().trim(),
|
||||
billing_address1: Yup.string().trim(),
|
||||
billing_address2: Yup.string().trim(),
|
||||
billing_address_city: Yup.string().trim(),
|
||||
billing_address_state: Yup.string().trim(),
|
||||
billing_address_postcode: Yup.string().nullable(),
|
||||
billing_address_phone: Yup.string().nullable(),
|
||||
|
||||
shipping_address_country: Yup.string().trim(),
|
||||
shipping_address_1: Yup.string().trim(),
|
||||
shipping_address_2: Yup.string().trim(),
|
||||
shipping_address1: Yup.string().trim(),
|
||||
shipping_address2: Yup.string().trim(),
|
||||
shipping_address_city: Yup.string().trim(),
|
||||
shipping_address_state: Yup.string().trim(),
|
||||
shipping_address_postcode: Yup.string().nullable(),
|
||||
|
||||
@@ -8,7 +8,7 @@ import styled from 'styled-components';
|
||||
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { CreateCustomerForm, EditCustomerForm } from './CustomerForm.schema';
|
||||
import { compose, transformToForm, saveInvoke } from '@/utils';
|
||||
import { compose, transformToForm, saveInvoke, parseBoolean } from '@/utils';
|
||||
import { useCustomerFormContext } from './CustomerFormProvider';
|
||||
import { defaultInitialValues } from './utils';
|
||||
|
||||
@@ -60,7 +60,10 @@ function CustomerFormFormik({
|
||||
// Handles the form submit.
|
||||
const handleFormSubmit = (values, formArgs) => {
|
||||
const { setSubmitting, resetForm } = formArgs;
|
||||
const formValues = { ...values };
|
||||
const formValues = {
|
||||
...values,
|
||||
active: parseBoolean(values.active, true),
|
||||
};
|
||||
|
||||
const onSuccess = (res) => {
|
||||
AppToaster.show({
|
||||
|
||||
@@ -55,7 +55,7 @@ export default function CustomerFormPrimarySection({}) {
|
||||
label={<T id={'company_name'} />}
|
||||
inline={true}
|
||||
>
|
||||
<InputGroup name={'company_name'} />
|
||||
<FInputGroup name={'company_name'} />
|
||||
</FFormGroup>
|
||||
|
||||
{/*----------- Display Name -----------*/}
|
||||
|
||||
@@ -23,16 +23,16 @@ export const defaultInitialValues = {
|
||||
active: true,
|
||||
|
||||
billing_address_country: '',
|
||||
billing_address_1: '',
|
||||
billing_address_2: '',
|
||||
billing_address1: '',
|
||||
billing_address2: '',
|
||||
billing_address_city: '',
|
||||
billing_address_state: '',
|
||||
billing_address_postcode: '',
|
||||
billing_address_phone: '',
|
||||
|
||||
shipping_address_country: '',
|
||||
shipping_address_1: '',
|
||||
shipping_address_2: '',
|
||||
shipping_address1: '',
|
||||
shipping_address2: '',
|
||||
shipping_address_city: '',
|
||||
shipping_address_state: '',
|
||||
shipping_address_postcode: '',
|
||||
|
||||
@@ -15,10 +15,16 @@ export const AccountDialogAction = {
|
||||
*/
|
||||
export const transformApiErrors = (errors) => {
|
||||
const fields = {};
|
||||
if (errors.find((e) => e.type === 'account_code_required')) {
|
||||
fields.code = intl.get('account_code_is_required');
|
||||
}
|
||||
if (errors.find((e) => e.type === 'NOT_UNIQUE_CODE')) {
|
||||
fields.code = intl.get('account_code_is_not_unique');
|
||||
}
|
||||
if (errors.find((e) => e.type === 'ACCOUNT.NAME.NOT.UNIQUE')) {
|
||||
if (errors.find((e) => e.type === 'account_code_not_unique')) {
|
||||
fields.code = intl.get('account_code_is_not_unique');
|
||||
}
|
||||
if (errors.find((e) => e.type === 'account_name_not_unqiue')) {
|
||||
fields.name = intl.get('account_name_is_already_used');
|
||||
}
|
||||
if (
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import intl from 'react-intl-universal';
|
||||
import React from 'react';
|
||||
|
||||
import { FormatDateCell } from '@/components';
|
||||
import { useAccountDrawerTableOptionsContext } from './AccountDrawerTableOptionsProvider';
|
||||
|
||||
/**
|
||||
@@ -15,8 +14,7 @@ export const useAccountReadEntriesColumns = () => {
|
||||
() => [
|
||||
{
|
||||
Header: intl.get('transaction_date'),
|
||||
accessor: 'date',
|
||||
Cell: FormatDateCell,
|
||||
accessor: 'formatted_date',
|
||||
width: 110,
|
||||
textOverview: true,
|
||||
},
|
||||
|
||||
@@ -111,12 +111,12 @@ export default function PreferencesGeneralForm({ isSubmitting }) {
|
||||
>
|
||||
<Stack>
|
||||
<FInputGroup
|
||||
name={'address.address_1'}
|
||||
name={'address.address1'}
|
||||
placeholder={'Address 1'}
|
||||
fastField
|
||||
/>
|
||||
<FInputGroup
|
||||
name={'address.address_2'}
|
||||
name={'address.address2'}
|
||||
placeholder={'Address 2'}
|
||||
fastField
|
||||
/>
|
||||
|
||||
@@ -18,16 +18,16 @@ const Schema = Yup.object().shape({
|
||||
note: Yup.string().trim(),
|
||||
|
||||
billing_address_country: Yup.string().trim(),
|
||||
billing_address_1: Yup.string().trim(),
|
||||
billing_address_2: Yup.string().trim(),
|
||||
billing_address1: Yup.string().trim(),
|
||||
billing_address2: Yup.string().trim(),
|
||||
billing_address_city: Yup.string().trim(),
|
||||
billing_address_state: Yup.string().trim(),
|
||||
billing_address_postcode: Yup.string().nullable(),
|
||||
billing_address_phone: Yup.string().nullable(),
|
||||
|
||||
shipping_address_country: Yup.string().trim(),
|
||||
shipping_address_1: Yup.string().trim(),
|
||||
shipping_address_2: Yup.string().trim(),
|
||||
shipping_address1: Yup.string().trim(),
|
||||
shipping_address2: Yup.string().trim(),
|
||||
shipping_address_city: Yup.string().trim(),
|
||||
shipping_address_state: Yup.string().trim(),
|
||||
shipping_address_postcode: Yup.string().nullable(),
|
||||
|
||||
@@ -21,7 +21,7 @@ import VendorFloatingActions from './VendorFloatingActions';
|
||||
import { withCurrentOrganization } from '@/containers/Organization/withCurrentOrganization';
|
||||
|
||||
import { useVendorFormContext } from './VendorFormProvider';
|
||||
import { compose, transformToForm, safeInvoke } from '@/utils';
|
||||
import { compose, transformToForm, safeInvoke, parseBoolean } from '@/utils';
|
||||
import { defaultInitialValues } from './utils';
|
||||
|
||||
import '@/style/pages/Vendors/Form.scss';
|
||||
@@ -69,7 +69,10 @@ function VendorFormFormik({
|
||||
// Handles the form submit.
|
||||
const handleFormSubmit = (values, form) => {
|
||||
const { setSubmitting, resetForm } = form;
|
||||
const requestForm = { ...values };
|
||||
const requestForm = {
|
||||
...values,
|
||||
active: parseBoolean(values.active, true),
|
||||
};
|
||||
|
||||
setSubmitting(true);
|
||||
|
||||
|
||||
@@ -22,16 +22,16 @@ export const defaultInitialValues = {
|
||||
active: true,
|
||||
|
||||
billing_address_country: '',
|
||||
billing_address_1: '',
|
||||
billing_address_2: '',
|
||||
billing_address1: '',
|
||||
billing_address2: '',
|
||||
billing_address_city: '',
|
||||
billing_address_state: '',
|
||||
billing_address_postcode: '',
|
||||
billing_address_phone: '',
|
||||
|
||||
shipping_address_country: '',
|
||||
shipping_address_1: '',
|
||||
shipping_address_2: '',
|
||||
shipping_address1: '',
|
||||
shipping_address2: '',
|
||||
shipping_address_city: '',
|
||||
shipping_address_state: '',
|
||||
shipping_address_postcode: '',
|
||||
|
||||
@@ -462,6 +462,7 @@
|
||||
"should_total_of_credit_and_debit_be_equal": "Should total of credit and debit be equal.",
|
||||
"no_accounts": "No Accounts",
|
||||
"the_accounts_have_been_successfully_inactivated": "The accounts have been successfully inactivated.",
|
||||
"account_code_is_required": "Account code is required.",
|
||||
"account_code_is_not_unique": "Account code is not unique.",
|
||||
"are_sure_to_publish_this_expense": "Are you sure you want to publish this expense?",
|
||||
"once_delete_these_journals_you_will_not_able_restore_them": "Once you delete these journals, you won't be able to retrieve them later. Are you sure you want to delete them?",
|
||||
|
||||
@@ -84,6 +84,20 @@ export const handleBooleanChange = (handler) => {
|
||||
return (event) => handler(event.target.checked);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses a value to boolean (handles 1, 0, '1', '0', true, false).
|
||||
* @param {*} value
|
||||
* @param {boolean} defaultValue - value when empty/unknown
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const parseBoolean = (value, defaultValue = false) => {
|
||||
if (typeof value === 'boolean') return value;
|
||||
if (value === 1 || value === '1') return true;
|
||||
if (value === 0 || value === '0') return false;
|
||||
if (value == null || value === '') return defaultValue;
|
||||
return Boolean(value);
|
||||
};
|
||||
|
||||
/** Event handler that exposes the target element's value as a string. */
|
||||
export const handleStringChange = (handler) => {
|
||||
return (event) => handler(event.target.value);
|
||||
|
||||
Reference in New Issue
Block a user