refactor: inventory adjustments e2e test cases

This commit is contained in:
Ahmed Bouhuolia
2025-01-08 15:43:43 +02:00
parent 52362a43ab
commit ee284196eb
29 changed files with 257 additions and 68 deletions

View File

@@ -152,8 +152,8 @@ import { PostHogModule } from '../EventsTracker/postHog.module';
TransactionsLockingModule,
SettingsModule,
InventoryAdjustmentsModule,
PostHogModule,
EventTrackerModule,
// PostHogModule,
// EventTrackerModule,
],
controllers: [AppController],
providers: [

View File

@@ -1,13 +1,15 @@
import { Inject, Injectable } from '@nestjs/common';
import { PostHog } from 'posthog-node';
import { EventMessage } from 'posthog-node/src/types';
// import { PostHog, EventMessage } from 'posthog-node';
import { POSTHOG } from './postHog.module';
import { TenancyContext } from '../Tenancy/TenancyContext.service';
interface EventMessage {
distinctId
}
@Injectable()
export class EventTrackerService {
constructor(
@Inject(POSTHOG) private readonly posthog: PostHog,
@Inject(POSTHOG) private readonly posthog: any,
private readonly tenancyContext: TenancyContext,
) {}
@@ -15,7 +17,7 @@ export class EventTrackerService {
* Track tenant an event.
* @param event - The event to track.
*/
public async trackEvent(event: Omit<EventMessage, 'distinctId'>) {
public async trackEvent(event: any) {
// Cannot continue if the Posthog not configured.
if (!this.posthog) return;

View File

@@ -1,4 +1,3 @@
import { ITransactionsLockingPartialUnlocked } from '@/interfaces';
import {
SUBSCRIPTION_CANCELLED,
SUBSCRIPTION_PAYMENT_FAILED,

View File

@@ -1,5 +1,5 @@
import { Module } from '@nestjs/common';
import { PostHog } from 'posthog-node';
// import { PostHog } from 'posthog-node';
import { EventTrackerService } from './EventTracker.service';
import { ConfigService } from '@nestjs/config';
@@ -10,10 +10,12 @@ export const POSTHOG = 'PostHog';
EventTrackerService,
{
provide: POSTHOG,
useFactory: (configService: ConfigService) =>
new PostHog(configService.get('posthog.apiKey'), {
host: configService.get('posthog.host'),
}),
useFactory: (configService: ConfigService) => {
},
// new PostHog(configService.get('posthog.apiKey'), {
// host: configService.get('posthog.host'),
// }),
inject: [ConfigService],
},
],

View File

@@ -1,9 +1,19 @@
import { Body, Controller, Delete, Param, Post } from '@nestjs/common';
import {
Body,
Controller,
Delete,
Get,
Param,
Post,
Put,
} from '@nestjs/common';
import { InventoryAdjustmentsApplicationService } from './InventoryAdjustmentsApplication.service';
import { IQuickInventoryAdjustmentDTO } from './types/InventoryAdjustments.types';
import { InventoryAdjustment } from './models/InventoryAdjustment';
import { PublicRoute } from '../Auth/Jwt.guard';
@Controller('inventory-adjustments')
@PublicRoute()
export class InventoryAdjustmentsController {
constructor(
private readonly inventoryAdjustmentsApplicationService: InventoryAdjustmentsApplicationService,
@@ -27,7 +37,16 @@ export class InventoryAdjustmentsController {
);
}
@Post(':id/publish')
@Get(':id')
public async getInventoryAdjustment(
@Param('id') inventoryAdjustmentId: number,
): Promise<InventoryAdjustment> {
return this.inventoryAdjustmentsApplicationService.getInventoryAdjustment(
inventoryAdjustmentId,
);
}
@Put(':id/publish')
public async publishInventoryAdjustment(
@Param('id') inventoryAdjustmentId: number,
): Promise<void> {

View File

@@ -14,6 +14,7 @@ import { WarehousesModule } from '../Warehouses/Warehouses.module';
import { InventoryAdjustmentsGLSubscriber } from './subscribers/InventoryAdjustmentGL.subscriber';
import { InventoryAdjustmentsGLEntries } from './commands/ledger/InventoryAdjustmentsGLEntries';
import { LedgerModule } from '../Ledger/Ledger.module';
import { TenancyContext } from '../Tenancy/TenancyContext.service';
const models = [
RegisterTenancyModel(InventoryAdjustment),
@@ -32,6 +33,7 @@ const models = [
InventoryAdjustmentsApplicationService,
InventoryAdjustmentsGLSubscriber,
InventoryAdjustmentsGLEntries,
TenancyContext,
],
exports: [...models],
})

View File

@@ -1,6 +1,7 @@
import { Knex } from 'knex';
import { Inject } from '@nestjs/common';
import * as R from 'ramda';
import * as moment from 'moment';
import { omit } from 'lodash';
import { events } from '@/common/events/events';
import { InventoryAdjustment } from '../models/InventoryAdjustment';
@@ -17,6 +18,7 @@ import { Account } from '@/modules/Accounts/models/Account.model';
import { BranchTransactionDTOTransformer } from '@/modules/Branches/integrations/BranchTransactionDTOTransform';
import { WarehouseTransactionDTOTransform } from '@/modules/Warehouses/Integrations/WarehouseTransactionDTOTransform';
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
import { ERRORS } from '../constants/InventoryAdjustments.constants';
export class CreateQuickInventoryAdjustmentService {
constructor(
@@ -80,7 +82,6 @@ export class CreateQuickInventoryAdjustmentService {
/**
* Creates a quick inventory adjustment for specific item.
* @param {number} tenantId - Tenant id.
* @param {IQuickInventoryAdjustmentDTO} quickAdjustmentDTO - qucik adjustment DTO.
*/
public async createQuickAdjustment(
@@ -119,7 +120,7 @@ export class CreateQuickInventoryAdjustmentService {
// Saves the inventory adjustment with associated entries to the storage.
const inventoryAdjustment = await this.inventoryAdjustmentModel
.query(trx)
.upsertGraph({
.upsertGraphAndFetch({
...invAdjustmentObject,
});
// Triggers `onInventoryAdjustmentQuickCreated` event.

View File

@@ -1,6 +1,7 @@
import { Knex } from 'knex';
import { Inject } from '@nestjs/common';
import { EventEmitter2 } from '@nestjs/event-emitter';
import * as moment from 'moment';
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
import { InventoryAdjustment } from '../models/InventoryAdjustment';
import {
@@ -9,6 +10,7 @@ import {
} from '../types/InventoryAdjustments.types';
import { events } from '@/common/events/events';
import { ServiceError } from '@/modules/Items/ServiceError';
import { ERRORS } from '../constants/InventoryAdjustments.constants';
export class PublishInventoryAdjustmentService {
constructor(
@@ -47,11 +49,15 @@ export class PublishInventoryAdjustmentService {
);
// Publish the inventory adjustment transaction.
await InventoryAdjustment.query().findById(inventoryAdjustmentId).patch({
publishedAt: moment().toMySqlDateTime(),
});
await this.inventoryAdjustmentModel
.query()
.findById(inventoryAdjustmentId)
.patch({
publishedAt: moment().toMySqlDateTime(),
});
// Retrieve the inventory adjustment after the modification.
const inventoryAdjustment = await InventoryAdjustment.query()
const inventoryAdjustment = await this.inventoryAdjustmentModel
.query()
.findById(inventoryAdjustmentId)
.withGraphFetched('entries');

View File

@@ -1,4 +1,4 @@
const ERRORS = {
export const ERRORS = {
INVENTORY_ADJUSTMENT_NOT_FOUND: 'INVENTORY_ADJUSTMENT_NOT_FOUND',
ITEM_SHOULD_BE_INVENTORY_TYPE: 'ITEM_SHOULD_BE_INVENTORY_TYPE',
INVENTORY_ADJUSTMENT_ALREADY_PUBLISHED:

View File

@@ -1,4 +1,4 @@
import { Model, mixin } from 'objection';
import { Model } from 'objection';
// import TenantModel from 'models/TenantModel';
// import InventoryAdjustmentSettings from './InventoryAdjustment.Settings';
// import ModelSetting from './ModelSetting';

View File

@@ -1,21 +1,24 @@
import { TransformerInjectable } from "@/modules/Transformer/TransformerInjectable.service";
import { InventoryAdjustment } from "../models/InventoryAdjustment";
import { InventoryAdjustmentTransformer } from "../InventoryAdjustmentTransformer";
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
import { InventoryAdjustment } from '../models/InventoryAdjustment';
import { InventoryAdjustmentTransformer } from '../InventoryAdjustmentTransformer';
import { Inject } from '@nestjs/common';
export class GetInventoryAdjustmentService {
constructor(
private readonly transformer: TransformerInjectable,
@Inject(InventoryAdjustment.name)
private readonly inventoryAdjustmentModel: typeof InventoryAdjustment,
) {}
/**
* Retrieve specific inventory adjustment transaction details.
* @param {number} inventoryAdjustmentId - Inventory adjustment id.
*/
async getInventoryAdjustment(
inventoryAdjustmentId: number,
) {
async getInventoryAdjustment(inventoryAdjustmentId: number) {
// Retrieve inventory adjustment transation with associated models.
const inventoryAdjustment = await InventoryAdjustment.query()
const inventoryAdjustment = await this.inventoryAdjustmentModel
.query()
.findById(inventoryAdjustmentId)
.withGraphFetched('entries.item')
.withGraphFetched('adjustmentAccount')

View File

@@ -40,7 +40,7 @@ export class ItemsController extends TenantController {
* @returns The updated item id.
*/
@Put(':id')
@UsePipes(new ZodValidationPipe(createItemSchema))
// @UsePipes(new ZodValidationPipe(createItemSchema))
async editItem(
@Param('id') id: string,
@Body() editItemDto: any,
@@ -55,7 +55,7 @@ export class ItemsController extends TenantController {
* @returns The created item id.
*/
@Post()
@UsePipes(new ZodValidationPipe(createItemSchema))
// @UsePipes(new ZodValidationPipe(createItemSchema))
async createItem(@Body() createItemDto: any): Promise<number> {
return this.createItemService.createItem(createItemDto);
}

View File

@@ -1,7 +1,7 @@
import { Model } from 'objection';
import { omit, isEmpty } from 'lodash';
import { IMetadata, IMetaQuery, IMetableStore } from './types';
import { itemsStartWith } from 'utils';
import { itemsStartWith } from '@/utils/items-start-with';
export class MetableStore implements IMetableStore {
metadata: IMetadata[];
@@ -23,7 +23,7 @@ export class MetableStore implements IMetableStore {
*/
setExtraColumns(columns: string[]): void {
this.extraColumns = columns;
}
}
/**
* Find the given metadata key.
@@ -120,6 +120,7 @@ export class MetableStore implements IMetableStore {
key,
...extraColumns,
_markAsInserted: true,
group: 'default',
});
}
}
@@ -166,11 +167,11 @@ export class MetableStore implements IMetableStore {
* Parse the metadata to the collection.
* @param {Array} collection -
*/
mapMetadataToCollection(metadata: IMetadata[], parseType: string = 'parse') {
return metadata.map((model) =>
this.mapMetadataToCollection(model, parseType)
);
}
// mapMetadataToCollection(metadata: IMetadata[], parseType: string = 'parse') {
// return metadata.map((model) =>
// this.mapMetadataToCollection(model, parseType)
// );
// }
/**
* Load metadata to the metable collection.
@@ -198,12 +199,12 @@ export class MetableStore implements IMetableStore {
* Static method to load metadata to the collection.
* @param {Array} meta
*/
static from(meta) {
const collection = new MetableCollection();
collection.from(meta);
// static from(meta) {
// const collection = new MetableCollection();
// collection.from(meta);
return collection;
}
// return collection;
// }
/**
* Reset the momerized metadata.

View File

@@ -1,8 +1,9 @@
import { IMetadata, IMetableStoreStorage } from './types';
import { MetableStore } from './MetableStore';
import { isBlank, parseBoolean } from 'utils';
import { MetableConfig } from './MetableConfig';
import { EntityRepository } from '@/common/repository/EntityRepository';
import { isBlank } from '@/utils/is-blank';
import { parseBoolean } from '@/utils/parse-boolean';
export class MetableDBStore
extends MetableStore
@@ -72,10 +73,10 @@ export class MetableDBStore
/**
* Saves the modified, deleted and insert metadata.
*/
save() {
async save() {
this.validateStoreIsLoaded();
return Promise.all([
await Promise.all([
this.saveUpdated(this.metadata),
this.saveDeleted(this.metadata),
this.saveInserted(this.metadata),

View File

@@ -15,5 +15,6 @@ export const SETTINGS = 'SETTINGS';
inject: [SettingRepository],
},
],
exports: [SETTINGS]
})
export class SettingsModule {}

View File

@@ -10,7 +10,7 @@ export class SettingsStore extends MetableDBStore {
constructor(repository: EntityRepository, config: any = SettingsOptions) {
super(config);
// this.setExtraColumns(['group']);
this.setExtraColumns(['group']);
this.setRepository(repository);
}
}

View File

@@ -10,8 +10,10 @@ import { PurchasesTransactionLockingGuardSubscriber } from './subscribers/Purcha
import { SalesTransactionLockingGuardSubscriber } from './subscribers/SalesTransactionLockingGuardSubscriber';
import { QueryTransactionsLocking } from './queries/QueryTransactionsLocking';
import { TransactionsLockingController } from './TransactionsLocking.controller';
import { SettingsModule } from '../Settings/Settings.module';
@Module({
imports: [SettingsModule],
providers: [
TransactionsLockingService,
FinancialTransactionLocking,

View File

@@ -4,7 +4,6 @@ import {
TransactionsLockingGroup,
TransactionsLockingType,
} from './types/TransactionsLocking.types';
import { parseDate } from 'utils';
import { Inject, Injectable } from '@nestjs/common';
import { SettingsStore } from '../Settings/SettingsStore';
import { SETTINGS } from '../Settings/Settings.module';
@@ -159,3 +158,7 @@ export class TransactionsLockingRepository {
});
}
}
export const parseDate = (date: string) => {
return date ? moment(date).utcOffset(0).format('YYYY-MM-DD') : '';
};

View File

@@ -1,7 +1,7 @@
import {
ITransactionsLockingSchema,
TransactionsLockingGroup,
} from '@/interfaces';
ITransactionsLockingSchema,
} from './types/TransactionsLocking.types';
export const ERRORS = {
TRANSACTIONS_DATE_LOCKED: 'TRANSACTIONS_DATE_LOCKED',
@@ -30,7 +30,7 @@ export const TRANSACTIONS_LOCKING_SCHEMA = [
] as ITransactionsLockingSchema[];
export function getTransactionsLockingSchemaMeta(
module: TransactionsLockingGroup
module: TransactionsLockingGroup,
): ITransactionsLockingSchema {
return TRANSACTIONS_LOCKING_SCHEMA.find((schema) => schema.module === module);
}

View File

@@ -1,6 +1,7 @@
import { TransactionsLockingGroup } from '../types/TransactionsLocking.types';
import { Injectable } from '@nestjs/common';
import { TransactionsLockingGuard } from './TransactionsLockingGuard';
import { MomentInput } from 'moment';
@Injectable()
export class PurchasesTransactionLockingGuard {
@@ -13,7 +14,7 @@ export class PurchasesTransactionLockingGuard {
* @param {Date} transactionDate - The transaction date.
*/
public transactionLockingGuard = async (
transactionDate: Date
transactionDate: MomentInput
) => {
this.transactionLockingGuardService.transactionsLockingGuard(
transactionDate,

View File

@@ -1,6 +1,7 @@
import { TransactionsLockingGroup } from '../types/TransactionsLocking.types';
import { Injectable } from '@nestjs/common';
import { TransactionsLockingGuard } from './TransactionsLockingGuard';
import { MomentInput } from 'moment';
@Injectable()
export class SalesTransactionLockingGuard {
@@ -13,7 +14,7 @@ export class SalesTransactionLockingGuard {
* @param {Date} transactionDate - The transaction date.
*/
public transactionLockingGuard = async (
transactionDate: Date
transactionDate: MomentInput
) => {
await this.transactionLockingGuardService.transactionsLockingGuard(
transactionDate,

View File

@@ -1,4 +1,4 @@
import moment from 'moment';
import moment, { MomentInput } from 'moment';
import { Injectable } from '@nestjs/common';
import { TransactionsLockingGroup } from '../types/TransactionsLocking.types';
import { TransactionsLockingRepository } from '../TransactionsLockingRepository';
@@ -18,7 +18,7 @@ export class TransactionsLockingGuard {
* @returns {boolean}
*/
public isTransactionsLocking = (
transactionDate: Date,
transactionDate: MomentInput,
lockingGroup: string = TransactionsLockingGroup.All
): boolean => {
const { isEnabled, unlockFromDate, unlockToDate, lockToDate } =
@@ -49,7 +49,7 @@ export class TransactionsLockingGuard {
* @throws {ServiceError}
*/
public validateTransactionsLocking = (
transactionDate: Date,
transactionDate: MomentInput,
lockingGroup: TransactionsLockingGroup
) => {
const isLocked = this.isTransactionsLocking(
@@ -83,7 +83,7 @@ export class TransactionsLockingGuard {
* @param {Date} transactionDate - The transaction date.
*/
public transactionsLockingGuard = (
transactionDate: Date,
transactionDate: MomentInput,
moduleType: TransactionsLockingGroup
) => {
const lockingType =

View File

@@ -16,6 +16,7 @@ export class RefundVendorCredit extends BaseModel {
public depositAccountId!: number;
public description!: string;
public branchId!: number;
public date!: Date;
public vendorCredit!: VendorCredit;
public depositAccount!: Account;