refactor(nestjs): e2e test cases

This commit is contained in:
Ahmed Bouhuolia
2025-03-31 00:39:00 +02:00
parent caff6ce47c
commit ab717b96ac
28 changed files with 168 additions and 115 deletions

View File

@@ -2,6 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
import { pick } from 'lodash';
import { Knex } from 'knex';
import * as R from 'ramda';
import * as composeAsync from 'async/compose';
import { CASHFLOW_TRANSACTION_TYPE } from '../constants';
import { transformCashflowTransactionType } from '../utils';
import { CommandBankTransactionValidator } from './CommandCasflowValidator.service';
@@ -104,7 +105,7 @@ export class CreateBankTransactionService {
}
: {}),
};
return R.compose(this.branchDTOTransform.transformDTO<BankTransaction>)(
return composeAsync(this.branchDTOTransform.transformDTO<BankTransaction>)(
initialDTO,
) as BankTransaction;
};

View File

@@ -27,6 +27,7 @@ export class BillDTOTransformer {
@Inject(ItemEntry.name)
private itemEntryModel: TenantModelProxy<typeof ItemEntry>,
@Inject(Item.name) private itemModel: TenantModelProxy<typeof Item>,
) {}
@@ -114,12 +115,16 @@ export class BillDTOTransformer {
}),
userId: authorizedUser.id,
};
const asyncDto = await composeAsync(
this.branchDTOTransform.transformDTO<Bill>,
this.warehouseDTOTransform.transformDTO<Bill>,
)(initialDTO);
return R.compose(
// Associates tax amount withheld to the model.
this.taxDTOTransformer.assocTaxAmountWithheldFromEntries,
this.branchDTOTransform.transformDTO<Bill>,
this.warehouseDTOTransform.transformDTO<Bill>,
)(initialDTO) as Bill;
)(asyncDto) as Bill;
}
/**

View File

@@ -1,23 +1,30 @@
import { Injectable } from '@nestjs/common';
import { Inject, Injectable } from '@nestjs/common';
import { SettingsStore } from '../Settings/SettingsStore';
import { SETTINGS_PROVIDER } from '../Settings/Settings.types';
import { Features } from '@/common/types/Features';
@Injectable()
export class BranchesSettingsService {
constructor(
@Inject(SETTINGS_PROVIDER)
private readonly settingsStore: () => SettingsStore,
) {}
/**
* Marks multi-branches as activated.
*/
public markMultiBranchesAsActivated = () => {
// const settings = this.tenancy.settings(tenantId);
public markMultiBranchesAsActivated = async () => {
const settingsStore = await this.settingsStore();
// settings.set({ group: 'features', key: Features.BRANCHES, value: 1 });
settingsStore.set({ group: 'features', key: Features.BRANCHES, value: 1 });
};
/**
* Retrieves whether multi-branches is active.
*/
public isMultiBranchesActive = () => {
// const settings = this.tenancy.settings(tenantId);
public isMultiBranchesActive = async () => {
const settingsStore = await this.settingsStore();
// return settings.get({ group: 'features', key: Features.BRANCHES });
return false;
return settingsStore.get({ group: 'features', key: Features.BRANCHES });
};
}

View File

@@ -49,8 +49,8 @@ export class ActivateBranches {
* Activate multi-branches feature.
* @returns {Promise<void>}
*/
public activateBranches = (): Promise<void> => {
const isActivated = this.branchesSettings.isMultiBranchesActive();
public activateBranches = async (): Promise<void> => {
const isActivated = await this.branchesSettings.isMultiBranchesActive();
// Throw error if mutli-branches is already activated.
this.throwIfMultiBranchesActivated(isActivated);

View File

@@ -10,22 +10,24 @@ export class BranchTransactionDTOTransformer {
* Excludes DTO branch id when mutli-warehouses feature is inactive.
* @returns {any}
*/
private excludeDTOBranchIdWhenInactive = <T extends { branchId?: number }>(
private excludeDTOBranchIdWhenInactive = async <
T extends { branchId?: number },
>(
DTO: T,
): Omit<T, 'branchId'> | T => {
const isActive = this.branchesSettings.isMultiBranchesActive();
): Promise<Omit<T, 'branchId'> | T> => {
const isActive = await this.branchesSettings.isMultiBranchesActive();
return !isActive ? omit(DTO, ['branchId']) : DTO;
};
/**
* Transformes the input DTO for branches feature.
* Transforms the input DTO for branches feature.
* @param {T} DTO -
* @returns {Omit<T, 'branchId'> | T}
*/
public transformDTO = <T extends { branchId?: number }>(
public transformDTO = async <T extends { branchId?: number }>(
DTO: T,
): Omit<T, 'branchId'> | T => {
): Promise<Omit<T, 'branchId'> | T> => {
return this.excludeDTOBranchIdWhenInactive<T>(DTO);
};
}

View File

@@ -11,17 +11,18 @@ export class ManualJournalBranchesDTOTransformer {
) {}
/**
*
* @param DTO
* @returns
*
* @param DTO
* @returns
*/
private excludeDTOBranchIdWhenInactive = (
private excludeDTOBranchIdWhenInactive = async (
DTO: IManualJournalDTO,
): IManualJournalDTO => {
const isActive = this.branchesSettings.isMultiBranchesActive();
if (isActive) return DTO;
): Promise<IManualJournalDTO> => {
const isActive = await this.branchesSettings.isMultiBranchesActive();
if (isActive) {
return DTO;
}
return {
...DTO,
entries: DTO.entries.map((e) => omit(e, ['branchId'])),
@@ -29,9 +30,11 @@ export class ManualJournalBranchesDTOTransformer {
};
/**
*
*
*/
public transformDTO = (DTO: IManualJournalDTO): IManualJournalDTO => {
return this.excludeDTOBranchIdWhenInactive(DTO);
};
public transformDTO = async (
DTO: IManualJournalDTO,
): Promise<IManualJournalDTO> => {
return this.excludeDTOBranchIdWhenInactive(DTO);
};
}

View File

@@ -17,7 +17,11 @@ import { BrandingTemplateDTOTransformer } from '../../PdfTemplate/BrandingTempla
import { assocItemEntriesDefaultIndex } from '@/utils/associate-item-entries-index';
import { CreditNoteAutoIncrementService } from './CreditNoteAutoIncrement.service';
import { CreditNote } from '../models/CreditNote';
import { CreateCreditNoteDto, CreditNoteEntryDto, EditCreditNoteDto } from '../dtos/CreditNote.dto';
import {
CreateCreditNoteDto,
CreditNoteEntryDto,
EditCreditNoteDto,
} from '../dtos/CreditNote.dto';
@Injectable()
export class CommandCreditNoteDTOTransform {
@@ -33,11 +37,11 @@ export class CommandCreditNoteDTOTransform {
private readonly branchDTOTransform: BranchTransactionDTOTransformer,
private readonly warehouseDTOTransform: WarehouseTransactionDTOTransform,
private readonly brandingTemplatesTransformer: BrandingTemplateDTOTransformer,
private readonly creditNoteAutoIncrement: CreditNoteAutoIncrementService
private readonly creditNoteAutoIncrement: CreditNoteAutoIncrementService,
) {}
/**
* Transformes the credit/edit DTO to model.
* Transforms the credit/edit DTO to model.
* @param {ICreditNoteNewDTO | ICreditNoteEditDTO} creditNoteDTO
* @param {string} customerCurrencyCode -
*/
@@ -61,10 +65,10 @@ export class CommandCreditNoteDTOTransform {
})),
)(creditNoteDTO.entries);
// Retreive the next credit note number.
// Retrieves the next credit note number.
const autoNextNumber = this.creditNoteAutoIncrement.getNextCreditNumber();
// Detarmines the credit note number.
// Determines the credit note number.
const creditNoteNumber =
creditNoteDTO.creditNoteNumber ||
oldCreditNote?.creditNoteNumber ||
@@ -84,17 +88,17 @@ export class CommandCreditNoteDTOTransform {
refundedAmount: 0,
invoicesAmount: 0,
};
const initialAsyncDTO = await composeAsync(
const asyncDto = (await composeAsync(
this.branchDTOTransform.transformDTO<CreditNote>,
this.warehouseDTOTransform.transformDTO<CreditNote>,
// Assigns the default branding template id to the invoice DTO.
this.brandingTemplatesTransformer.assocDefaultBrandingTemplate(
'CreditNote',
),
)(initialDTO);
)(initialDTO)) as CreditNote;
return R.compose(
this.branchDTOTransform.transformDTO<CreditNote>,
this.warehouseDTOTransform.transformDTO<CreditNote>,
)(initialAsyncDTO) as CreditNote;
return asyncDto;
};
/**

View File

@@ -2,6 +2,7 @@ import { ItemEntryDto } from '@/modules/TransactionItemEntry/dto/ItemEntry.dto';
import { ApiProperty } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import {
ArrayMinSize,
IsArray,
IsBoolean,
IsDate,
@@ -88,7 +89,7 @@ export class CommandCreditNoteDto {
@IsArray()
@ValidateNested({ each: true })
@Type(() => CreditNoteEntryDto)
@Min(1)
@ArrayMinSize(1)
@ApiProperty({
example: [
{

View File

@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
import { omit, sumBy } from 'lodash';
import * as moment from 'moment';
import * as R from 'ramda';
import * as composeAsync from 'async/compose';
import { BranchTransactionDTOTransformer } from '@/modules/Branches/integrations/BranchTransactionDTOTransform';
import { Expense } from '../models/Expense.model';
import { assocItemEntriesDefaultIndex } from '@/utils/associate-item-entries-index';
@@ -48,9 +49,9 @@ export class ExpenseDTOTransformer {
* @param {ISystemUser} authorizedUser
* @return {IExpense}
*/
private expenseDTOToModel(
private async expenseDTOToModel(
expenseDTO: CreateExpenseDto | EditExpenseDto,
): Expense {
): Promise<Expense> {
const landedCostAmount = this.getExpenseLandedCostAmount(expenseDTO);
const totalAmount = this.getExpenseCategoriesTotal(expenseDTO.categories);
@@ -71,20 +72,22 @@ export class ExpenseDTOTransformer {
}
: {}),
};
return R.compose(this.branchDTOTransform.transformDTO<Expense>)(
initialDTO,
) as Expense;
const asyncDto = await composeAsync(
this.branchDTOTransform.transformDTO<Expense>,
)(initialDTO);
return asyncDto as Expense;
}
/**
* Transformes the expense create DTO.
* Transforms the expense create DTO.
* @param {IExpenseCreateDTO} expenseDTO
* @returns {Promise<Expense>}
*/
public expenseCreateDTO = async (
expenseDTO: CreateExpenseDto | EditExpenseDto,
): Promise<Partial<Expense>> => {
const initialDTO = this.expenseDTOToModel(expenseDTO);
const initialDTO = await this.expenseDTOToModel(expenseDTO);
const tenant = await this.tenancyContext.getTenant(true);
return {

View File

@@ -1,7 +1,7 @@
import { Knex } from 'knex';
import { Inject, Injectable } from '@nestjs/common';
import * as R from 'ramda';
import * as moment from 'moment';
import * as composeAsync from 'async/compose';
import { omit } from 'lodash';
import { events } from '@/common/events/events';
import { InventoryAdjustment } from '../models/InventoryAdjustment';
@@ -79,7 +79,7 @@ export class CreateQuickInventoryAdjustmentService {
: {}),
entries,
};
return R.compose(
return composeAsync(
this.warehouseDTOTransform.transformDTO<InventoryAdjustment>,
this.branchDTOTransform.transformDTO<InventoryAdjustment>,
)(initialDTO) as InventoryAdjustment;

View File

@@ -3,6 +3,7 @@ import * as moment from 'moment';
import * as R from 'ramda';
import { Knex } from 'knex';
import { Inject, Injectable } from '@nestjs/common';
import * as composeAsync from 'async/compose';
import { EventEmitter2 } from '@nestjs/event-emitter';
import {
IManualJournalDTO,
@@ -73,7 +74,7 @@ export class CreateManualJournalService {
entries,
userId: authorizedUser.id,
};
return R.compose(
return composeAsync(
// Omits the `branchId` from entries if multiply branches feature not active.
this.branchesDTOTransformer.transformDTO,
)(initialDTO) as ManualJournal;

View File

@@ -71,15 +71,15 @@ export class PaymentReceiveDTOTransformer {
exchangeRate: paymentReceiveDTO.exchangeRate || 1,
entries,
};
const initialAsyncDTO = await composeAsync(
const asyncDto = await composeAsync(
this.branchDTOTransform.transformDTO<PaymentReceived>,
// Assigns the default branding template id to the invoice DTO.
this.brandingTemplatesTransformer.assocDefaultBrandingTemplate(
'SaleInvoice',
),
)(initialDTO);
return R.compose(this.branchDTOTransform.transformDTO<PaymentReceived>)(
initialAsyncDTO,
) as PaymentReceived;
return asyncDto;
}
}

View File

@@ -81,17 +81,17 @@ export class SaleEstimateDTOTransformer {
deliveredAt: moment().toMySqlDateTime(),
}),
};
const initialAsyncDTO = await composeAsync(
const asyncDto = await composeAsync(
this.branchDTOTransform.transformDTO<SaleEstimate>,
this.warehouseDTOTransform.transformDTO<SaleEstimate>,
// Assigns the default branding template id to the invoice DTO.
this.brandingTemplatesTransformer.assocDefaultBrandingTemplate(
'SaleEstimate',
),
)(initialDTO);
return R.compose(
this.branchDTOTransform.transformDTO<SaleEstimate>,
this.warehouseDTOTransform.transformDTO<SaleEstimate>,
)(initialAsyncDTO);
return asyncDto;
}
/**

View File

@@ -2,6 +2,7 @@ import { ItemEntryDto } from '@/modules/TransactionItemEntry/dto/ItemEntry.dto';
import { ApiProperty } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import {
ArrayMinSize,
IsArray,
IsBoolean,
IsDate,
@@ -92,7 +93,7 @@ export class CommandSaleEstimateDto {
branchId?: number;
@IsArray()
@MinLength(1)
@ArrayMinSize(1)
@ValidateNested({ each: true })
@Type(() => SaleEstimateEntryDto)
@ApiProperty({

View File

@@ -121,17 +121,18 @@ export class CommandSaleInvoiceDTOTransformer {
} as SaleInvoice;
const initialAsyncDTO = await composeAsync(
this.branchDTOTransform.transformDTO<SaleInvoice>,
this.warehouseDTOTransform.transformDTO<SaleInvoice>,
// Assigns the default branding template id to the invoice DTO.
this.brandingTemplatesTransformer.assocDefaultBrandingTemplate(
'SaleInvoice',
),
)(initialDTO);
return R.compose(
this.taxDTOTransformer.assocTaxAmountWithheldFromEntries,
this.branchDTOTransform.transformDTO<SaleInvoice>,
this.warehouseDTOTransform.transformDTO<SaleInvoice>,
)(initialAsyncDTO);
return R.compose(this.taxDTOTransformer.assocTaxAmountWithheldFromEntries)(
initialAsyncDTO,
);
}
/**

View File

@@ -2,7 +2,6 @@ import { Inject, Injectable } from '@nestjs/common';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { Knex } from 'knex';
import {
ISaleInvoiceCreateDTO,
ISaleInvoiceCreatedPayload,
ISaleInvoiceCreatingPaylaod,
} from '../SaleInvoice.types';

View File

@@ -15,7 +15,10 @@ import { assocItemEntriesDefaultIndex } from '@/utils/associate-item-entries-ind
import { SaleReceipt } from '../models/SaleReceipt';
import { Customer } from '@/modules/Customers/models/Customer';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { CreateSaleReceiptDto, EditSaleReceiptDto } from '../dtos/SaleReceipt.dto';
import {
CreateSaleReceiptDto,
EditSaleReceiptDto,
} from '../dtos/SaleReceipt.dto';
@Injectable()
export class SaleReceiptDTOTransformer {
@@ -96,16 +99,16 @@ export class SaleReceiptDTOTransformer {
}),
entries,
};
const initialAsyncDTO = await composeAsync(
const asyncDto = await composeAsync(
this.branchDTOTransform.transformDTO<SaleReceipt>,
this.warehouseDTOTransform.transformDTO<SaleReceipt>,
// Assigns the default branding template id to the invoice DTO.
this.brandingTemplatesTransformer.assocDefaultBrandingTemplate(
'SaleReceipt',
),
)(initialDTO);
return R.compose(
this.branchDTOTransform.transformDTO<SaleReceipt>,
this.warehouseDTOTransform.transformDTO<SaleReceipt>,
)(initialAsyncDTO) as SaleReceipt;
return asyncDto;
}
}

View File

@@ -24,6 +24,7 @@ import { SaleReceipt } from '../models/SaleReceipt';
import { MailTransporter } from '@/modules/Mail/MailTransporter.service';
import { Mail } from '@/modules/Mail/Mail';
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
@Injectable()
export class SaleReceiptMailNotification {
@@ -43,7 +44,7 @@ export class SaleReceiptMailNotification {
private readonly tenancyContext: TenancyContext,
@Inject(SaleReceipt.name)
private readonly saleReceiptModel: typeof SaleReceipt,
private readonly saleReceiptModel: TenantModelProxy<typeof SaleReceipt>,
@InjectQueue(SendSaleReceiptMailQueue)
private readonly sendSaleReceiptMailProcess: Queue,
@@ -74,7 +75,6 @@ export class SaleReceiptMailNotification {
await this.sendSaleReceiptMailProcess.add(SendSaleReceiptMailJob, {
...payload,
});
// Triggers the event `onSaleReceiptPreMailSend`.
await this.eventEmitter.emitAsync(events.saleReceipt.onPreMailSend, {
saleReceiptId,
@@ -90,7 +90,7 @@ export class SaleReceiptMailNotification {
public async getMailOptions(
saleReceiptId: number,
): Promise<SaleReceiptMailOpts> {
const saleReceipt = await this.saleReceiptModel
const saleReceipt = await this.saleReceiptModel()
.query()
.findById(saleReceiptId)
.throwIfNotFound();

View File

@@ -1,4 +1,5 @@
import knex from 'knex';
import * as LRUCache from 'lru-cache';
import { Global, Module } from '@nestjs/common';
import { knexSnakeCaseMappers } from 'objection';
import { ClsModule, ClsService } from 'nestjs-cls';
@@ -6,6 +7,8 @@ import { ConfigService } from '@nestjs/config';
import { TENANCY_DB_CONNECTION } from './TenancyDB.constants';
import { UnitOfWork } from './UnitOfWork.service';
const lruCache = new LRUCache();
export const TenancyDatabaseProxyProvider = ClsModule.forFeatureAsync({
provide: TENANCY_DB_CONNECTION,
global: true,
@@ -13,14 +16,19 @@ export const TenancyDatabaseProxyProvider = ClsModule.forFeatureAsync({
inject: [ConfigService, ClsService],
useFactory: async (configService: ConfigService, cls: ClsService) => () => {
const organizationId = cls.get('organizationId');
const database = `bigcapital_tenant_${organizationId}`;
const cachedInstance = lruCache.get(database);
return knex({
if (cachedInstance) {
return cachedInstance;
}
const knexInstance = knex({
client: configService.get('tenantDatabase.client'),
connection: {
host: configService.get('tenantDatabase.host'),
user: configService.get('tenantDatabase.user'),
password: configService.get('tenantDatabase.password'),
database: `bigcapital_tenant_${organizationId}`,
database,
charset: 'utf8',
},
migrations: {
@@ -32,6 +40,9 @@ export const TenancyDatabaseProxyProvider = ClsModule.forFeatureAsync({
pool: { min: 0, max: 7 },
...knexSnakeCaseMappers({ upperCase: true }),
});
lruCache.set(database, knexInstance);
return knexInstance;
},
type: 'function',
});

View File

@@ -91,9 +91,10 @@ export function RegisterTenancyModel(model: typeof Model) {
provide: model.name,
inject: [TENANCY_DB_CONNECTION],
global: true,
useFactory: async (tenantKnex: () => Knex) => () => {
useFactory: (tenantKnex: () => Knex) => () => {
return model.bindKnex(tenantKnex());
},
strict: true,
type: 'function',
});
}

View File

@@ -1,6 +1,7 @@
import * as moment from 'moment';
import { omit } from 'lodash';
import * as R from 'ramda';
import * as composeAsync from 'async/compose';
import { ERRORS } from '../constants';
import { ItemsEntriesService } from '@/modules/Items/ItemsEntries.service';
import { BranchTransactionDTOTransformer } from '@/modules/Branches/integrations/BranchTransactionDTOTransform';
@@ -32,7 +33,7 @@ export class VendorCreditDTOTransformService {
) {}
/**
* Transformes the credit/edit vendor credit DTO to model.
* Transforms the credit/edit vendor credit DTO to model.
* @param {IVendorCreditCreateDTO | IVendorCreditEditDTO} vendorCreditDTO
* @param {string} vendorCurrencyCode -
* @param {IVendorCredit} oldVendorCredit -
@@ -80,7 +81,7 @@ export class VendorCreditDTOTransformService {
openedAt: moment().toMySqlDateTime(),
}),
};
return R.compose(
return composeAsync(
this.branchDTOTransform.transformDTO<VendorCredit>,
this.warehouseDTOTransform.transformDTO<VendorCredit>,
)(initialDTO) as VendorCredit;

View File

@@ -1,6 +1,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { Knex } from 'knex';
import * as R from 'ramda';
import * as composeAsync from 'async/compose';
import { EventEmitter2 } from '@nestjs/event-emitter';
import {
IRefundVendorCreditCreatedPayload,
@@ -81,7 +82,7 @@ export class CreateRefundVendorCredit {
refundVendorCreditDTO,
} as IVendorCreditCreatePayload);
const refundCreditObj = this.transformDTOToModel(
const refundCreditObj = await this.transformDTOToModel(
vendorCredit,
refundVendorCreditDTO,
);
@@ -119,7 +120,7 @@ export class CreateRefundVendorCredit {
* @param {RefundVendorCreditDto} vendorCreditDTO
* @returns {IRefundVendorCredit}
*/
public transformDTOToModel = (
public transformDTOToModel = async (
vendorCredit: VendorCredit,
vendorCreditDTO: RefundVendorCreditDto,
) => {
@@ -129,7 +130,7 @@ export class CreateRefundVendorCredit {
currencyCode: vendorCredit.currencyCode,
exchangeRate: vendorCreditDTO.exchangeRate || 1,
};
return R.compose(this.branchDTOTransform.transformDTO)(initialDTO);
return this.branchDTOTransform.transformDTO(initialDTO);
};
/**

View File

@@ -4,34 +4,32 @@ import { WarehousesSettings } from '../WarehousesSettings';
@Injectable()
export class WarehouseTransactionDTOTransform {
constructor(
private readonly warehousesSettings: WarehousesSettings,
) {}
constructor(private readonly warehousesSettings: WarehousesSettings) {}
/**
* Excludes DTO warehouse id when mutli-warehouses feature is inactive.
* @param {number} tenantId
* @returns {Promise<Omit<T, 'warehouseId'> | T>}
*/
private excludeDTOWarehouseIdWhenInactive = <
T extends { warehouseId?: number }
private excludeDTOWarehouseIdWhenInactive = async <
T extends { warehouseId?: number },
>(
DTO: T
): Omit<T, 'warehouseId'> | T => {
const isActive = this.warehousesSettings.isMultiWarehousesActive();
DTO: T,
): Promise<Omit<T, 'warehouseId'> | T> => {
const isActive = await this.warehousesSettings.isMultiWarehousesActive();
return !isActive ? omit(DTO, ['warehouseId']) : DTO;
};
/**
*
*
* @param {number} tenantId
* @param {T} DTO -
* @returns {Omit<T, 'warehouseId'> | T}
*/
public transformDTO =
<T extends { warehouseId?: number }>(DTO: T): Omit<T, 'warehouseId'> | T => {
return this.excludeDTOWarehouseIdWhenInactive<T>(DTO);
};
public transformDTO = async <T extends { warehouseId?: number }>(
DTO: T,
): Promise<Omit<T, 'warehouseId'> | T> => {
return this.excludeDTOWarehouseIdWhenInactive<T>(DTO);
};
}

View File

@@ -19,7 +19,9 @@ export class WarehousesDTOValidators {
* Validates the warehouse existance of sale invoice transaction.
* @param {IWarehouseTransactionDTO} DTO
*/
public validateDTOWarehouseExistance = async (DTO: IWarehouseTransactionDTO) => {
public validateDTOWarehouseExistance = async (
DTO: IWarehouseTransactionDTO,
) => {
// Validates the sale invoice warehouse id existance.
this.validateWarehouseExistanceService.validateWarehouseIdExistance(
DTO,
@@ -47,7 +49,7 @@ export class WarehousesDTOValidators {
public validateDTOWarehouseWhenActive = async (
DTO: IWarehouseTransactionDTO,
): Promise<void> => {
const isActive = this.warehousesSettings.isMultiWarehousesActive();
const isActive = await this.warehousesSettings.isMultiWarehousesActive();
// Can't continue if the multi-warehouses feature is inactive.
if (!isActive) return;

View File

@@ -24,7 +24,7 @@ export class WarehousesItemsQuantitySyncSubscriber {
inventoryTransactions,
trx,
}: IInventoryTransactionsCreatedPayload) {
const isActive = this.warehousesSettings.isMultiWarehousesActive();
const isActive = await this.warehousesSettings.isMultiWarehousesActive();
// Can't continue if the warehouses features is not active.
if (!isActive) return;
@@ -44,7 +44,7 @@ export class WarehousesItemsQuantitySyncSubscriber {
oldInventoryTransactions,
trx,
}: IInventoryTransactionsDeletedPayload) {
const isActive = this.warehousesSettings.isMultiWarehousesActive();
const isActive = await this.warehousesSettings.isMultiWarehousesActive();
// Can't continue if the warehouses feature is not active yet.
if (!isActive) return;

View File

@@ -1,25 +1,32 @@
import { Injectable } from '@nestjs/common';
import { Inject, Injectable } from '@nestjs/common';
import { SettingsStore } from '../Settings/SettingsStore';
import { SETTINGS_PROVIDER } from '../Settings/Settings.types';
import { Features } from '@/common/types/Features';
@Injectable()
export class WarehousesSettings {
constructor(
@Inject(SETTINGS_PROVIDER)
private readonly settingsStore: () => SettingsStore,
) {}
/**
* Marks multi-warehouses as activated.
*/
public markMutliwarehoussAsActivated = () => {
// const settings = this.tenancy.settings(tenantId);
public markMutliwarehoussAsActivated = async () => {
const settings = await this.settingsStore();
// settings.set({ group: 'features', key: Features.WAREHOUSES, value: 1 });
settings.set({ group: 'features', key: Features.WAREHOUSES, value: 1 });
};
/**
* Detarmines multi-warehouses is active.
* Determines multi-warehouses is active.
* @param {number} tenantId
* @returns {boolean}
*/
public isMultiWarehousesActive = () => {
// const settings = this.tenancy.settings(tenantId);
public isMultiWarehousesActive = async () => {
const settings = await this.settingsStore();
// return settings.get({ group: 'features', key: Features.WAREHOUSES });
return true;
return settings.get({ group: 'features', key: Features.WAREHOUSES });
};
}

View File

@@ -40,7 +40,7 @@ export class ActivateWarehousesService {
* - Mutate inventory transactions with the primary warehouse.
*/
public async activateWarehouses(): Promise<void> {
const isActivated = this.settings.isMultiWarehousesActive();
const isActivated = await this.settings.isMultiWarehousesActive();
this.throwIfWarehousesActivated(isActivated);
return this.uow.withTransaction(async (trx: Knex.Transaction) => {

View File

@@ -39,6 +39,7 @@ describe('Sale Estimates (e2e)', () => {
.set('organization-id', orgainzationId)
.send({
name: faker.commerce.productName(),
type: 'inventory',
sellable: true,
purchasable: true,
sellAccountId: 1026,