mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 05:40:31 +00:00
feat(nestjs): migrate to NestJS
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { AccountTransaction } from '../Accounts/models/AccountTransaction.model';
|
||||
import { TenantModelProxy } from '../System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class InventoryTransactionsWarehouses {
|
||||
constructor(
|
||||
@Inject(AccountTransaction.name)
|
||||
private readonly accountTransactionModel: TenantModelProxy<
|
||||
typeof AccountTransaction
|
||||
>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all accounts transctions with the priamry branch.
|
||||
* @param {number} primaryBranchId - The primary branch id.
|
||||
*/
|
||||
public updateTransactionsWithWarehouse = async (
|
||||
primaryBranchId: number,
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
await this.accountTransactionModel().query(trx).update({
|
||||
branchId: primaryBranchId,
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InventoryTransactionsWarehouses } from './AccountsTransactionsWarehouses';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { IBranchesActivatedPayload } from '../Branches/Branches.types';
|
||||
import { events } from '@/common/events/events';
|
||||
|
||||
@Injectable()
|
||||
export class AccountsTransactionsWarehousesSubscribe {
|
||||
constructor(
|
||||
private readonly accountsTransactionsWarehouses: InventoryTransactionsWarehouses,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all GL transactions to primary branch once
|
||||
* the multi-branches activated.
|
||||
* @param {IBranchesActivatedPayload}
|
||||
*/
|
||||
@OnEvent(events.branch.onActivated)
|
||||
async updateGLTransactionsToPrimaryBranchOnActivated({
|
||||
primaryBranch,
|
||||
trx,
|
||||
}: IBranchesActivatedPayload) {
|
||||
await this.accountsTransactionsWarehouses.updateTransactionsWithWarehouse(
|
||||
primaryBranch.id,
|
||||
trx,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Warehouse } from '../models/Warehouse.model';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { Bill } from '@/modules/Bills/models/Bill';
|
||||
import { ItemEntry } from '@/modules/TransactionItemEntry/models/ItemEntry';
|
||||
|
||||
@Injectable()
|
||||
export class BillActivateWarehouses {
|
||||
constructor(
|
||||
@Inject(Bill.name)
|
||||
private readonly billModel: TenantModelProxy<typeof Bill>,
|
||||
|
||||
@Inject(ItemEntry.name)
|
||||
private readonly itemEntryModel: TenantModelProxy<typeof ItemEntry>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all credit note transactions with the primary warehouse.
|
||||
* @param {Warehouse} primaryWarehouse
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public updateBillsWithWarehouse = async (
|
||||
primaryWarehouse: Warehouse,
|
||||
): Promise<void> => {
|
||||
// Updates the sale estimates with primary warehouse.
|
||||
await this.billModel().query().update({
|
||||
warehouseId: primaryWarehouse.id,
|
||||
});
|
||||
// Update the sale estimates entries with primary warehouse.
|
||||
await this.itemEntryModel().query().where('referenceType', 'Bill').update({
|
||||
warehouseId: primaryWarehouse.id,
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { ItemEntry } from '@/modules/TransactionItemEntry/models/ItemEntry';
|
||||
import { CreditNote } from '@/modules/CreditNotes/models/CreditNote';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Warehouse } from '../models/Warehouse.model';
|
||||
|
||||
@Injectable()
|
||||
export class CreditNotesActivateWarehouses {
|
||||
constructor(
|
||||
@Inject(CreditNote.name)
|
||||
private readonly creditNoteModel: TenantModelProxy<typeof CreditNote>,
|
||||
|
||||
@Inject(ItemEntry.name)
|
||||
private readonly itemEntryModel: TenantModelProxy<typeof ItemEntry>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all credit note transactions with the primary warehouse.
|
||||
* @param {Warehouse} primaryWarehouse
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public updateCreditsWithWarehouse = async (
|
||||
primaryWarehouse: Warehouse
|
||||
): Promise<void> => {
|
||||
// Updates the sale estimates with primary warehouse.
|
||||
await this.creditNoteModel().query().update({
|
||||
warehouseId: primaryWarehouse.id,
|
||||
});
|
||||
// Update the sale estimates entries with primary warehouse.
|
||||
await this.itemEntryModel()
|
||||
.query()
|
||||
.where('referenceType', 'CreditNote')
|
||||
.update({
|
||||
warehouseId: primaryWarehouse.id,
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { ItemEntry } from '@/modules/TransactionItemEntry/models/ItemEntry';
|
||||
import { SaleEstimate } from '@/modules/SaleEstimates/models/SaleEstimate';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Warehouse } from '../models/Warehouse.model';
|
||||
|
||||
@Injectable()
|
||||
export class EstimatesActivateWarehouses {
|
||||
constructor(
|
||||
private readonly saleEstimateModel: TenantModelProxy<typeof SaleEstimate>,
|
||||
private readonly itemEntryModel: TenantModelProxy<typeof ItemEntry>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all inventory transactions with the primary warehouse.
|
||||
* @param {Warehouse} primaryWarehouse
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public updateEstimatesWithWarehouse = async (
|
||||
primaryWarehouse: Warehouse,
|
||||
): Promise<void> => {
|
||||
// Updates the sale estimates with primary warehouse.
|
||||
await this.saleEstimateModel()
|
||||
.query()
|
||||
.update({ warehouseId: primaryWarehouse.id });
|
||||
|
||||
// Update the sale estimates entries with primary warehouse.
|
||||
await this.itemEntryModel()
|
||||
.query()
|
||||
.where('referenceType', 'SaleEstimate')
|
||||
.update({
|
||||
warehouseId: primaryWarehouse.id,
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { InventoryTransaction } from "@/modules/InventoryCost/models/InventoryTransaction";
|
||||
import { TenantModelProxy } from "@/modules/System/models/TenantBaseModel";
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { Warehouse } from "../models/Warehouse.model";
|
||||
import { InventoryCostLotTracker } from "@/modules/InventoryCost/models/InventoryCostLotTracker";
|
||||
|
||||
@Injectable()
|
||||
export class InventoryActivateWarehouses {
|
||||
constructor(
|
||||
private readonly inventoryTransactionModel: TenantModelProxy<typeof InventoryTransaction>,
|
||||
private readonly inventoryCostLotTrackerModel: TenantModelProxy<typeof InventoryCostLotTracker>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all inventory transactions with the primary warehouse.
|
||||
* @param {number} tenantId
|
||||
* @param {number} primaryWarehouse
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public updateInventoryTransactionsWithWarehouse = async (
|
||||
primaryWarehouse: Warehouse
|
||||
): Promise<void> => {
|
||||
// Updates the inventory transactions with primary warehouse.
|
||||
await this.inventoryTransactionModel().query().update({
|
||||
warehouseId: primaryWarehouse.id,
|
||||
});
|
||||
await this.inventoryCostLotTrackerModel().query().update({
|
||||
warehouseId: primaryWarehouse.id,
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Warehouse } from '../models/Warehouse.model';
|
||||
import { SaleInvoice } from '@/modules/SaleInvoices/models/SaleInvoice';
|
||||
import { ItemEntry } from '@/modules/TransactionItemEntry/models/ItemEntry';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class InvoicesActivateWarehouses {
|
||||
constructor(
|
||||
@Inject(SaleInvoice.name)
|
||||
private readonly saleInvoiceModel: TenantModelProxy<typeof SaleInvoice>,
|
||||
|
||||
@Inject(ItemEntry.name)
|
||||
private readonly itemEntryModel: TenantModelProxy<typeof ItemEntry>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all inventory transactions with the primary warehouse.
|
||||
* @param {Warehouse} primaryWarehouse
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
updateInvoicesWithWarehouse = async (
|
||||
primaryWarehouse: Warehouse,
|
||||
): Promise<void> => {
|
||||
// Updates the sale invoices with primary warehouse.
|
||||
await this.saleInvoiceModel().query().update({
|
||||
warehouseId: primaryWarehouse.id,
|
||||
});
|
||||
|
||||
// Update the sale invoices entries with primary warehouse.
|
||||
await this.itemEntryModel()
|
||||
.query()
|
||||
.where('referenceType', 'SaleInvoice')
|
||||
.update({
|
||||
warehouseId: primaryWarehouse.id,
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { ItemEntry } from '@/modules/TransactionItemEntry/models/ItemEntry';
|
||||
import { Warehouse } from '../models/Warehouse.model';
|
||||
import { SaleReceipt } from '@/modules/SaleReceipts/models/SaleReceipt';
|
||||
|
||||
@Injectable()
|
||||
export class ReceiptActivateWarehouses {
|
||||
constructor(
|
||||
@Inject(SaleReceipt.name)
|
||||
private readonly saleReceiptModel: TenantModelProxy<typeof SaleReceipt>,
|
||||
|
||||
@Inject(ItemEntry.name)
|
||||
private readonly itemEntryModel: TenantModelProxy<typeof ItemEntry>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all sale receipts transactions with the primary warehouse.
|
||||
* @param {Warehouse} primaryWarehouse
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public updateReceiptsWithWarehouse = async (
|
||||
primaryWarehouse: Warehouse,
|
||||
): Promise<void> => {
|
||||
// Updates the vendor credits transactions with primary warehouse.
|
||||
await this.saleReceiptModel().query().update({
|
||||
warehouseId: primaryWarehouse.id,
|
||||
});
|
||||
// Update the sale invoices entries with primary warehouse.
|
||||
await this.itemEntryModel()
|
||||
.query()
|
||||
.where('referenceType', 'SaleReceipt')
|
||||
.update({
|
||||
warehouseId: primaryWarehouse.id,
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { VendorCredit } from '@/modules/VendorCredit/models/VendorCredit';
|
||||
import { ItemEntry } from '@/modules/TransactionItemEntry/models/ItemEntry';
|
||||
import { Warehouse } from '../models/Warehouse.model';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class VendorCreditActivateWarehouses {
|
||||
constructor(
|
||||
@Inject(VendorCredit.name)
|
||||
private readonly vendorCreditModel: TenantModelProxy<typeof VendorCredit>,
|
||||
|
||||
@Inject(ItemEntry.name)
|
||||
private readonly itemEntryModel: TenantModelProxy<typeof ItemEntry>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all vendor credits transactions with the primary warehouse.
|
||||
* @param {Warehouse} primaryWarehouse
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public updateCreditsWithWarehouse = async (
|
||||
primaryWarehouse: Warehouse,
|
||||
): Promise<void> => {
|
||||
// Updates the vendor credits transactions with primary warehouse.
|
||||
await this.vendorCreditModel().query().update({
|
||||
warehouseId: primaryWarehouse.id,
|
||||
});
|
||||
|
||||
// Update the sale invoices entries with primary warehouse.
|
||||
await this.itemEntryModel()
|
||||
.query()
|
||||
.where('referenceType', 'VendorCredit')
|
||||
.update({
|
||||
warehouseId: primaryWarehouse.id,
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { UpdateInventoryTransactionsWithWarehouse } from './UpdateInventoryTransactionsWithWarehouse';
|
||||
import { CreateInitialWarehousesItemsQuantity } from './CreateInitialWarehousesitemsQuantity';
|
||||
import { IWarehousesActivatedPayload } from './Warehouse.types';
|
||||
|
||||
@Injectable()
|
||||
export class ActivateWarehousesSubscriber {
|
||||
constructor(
|
||||
private readonly updateInventoryTransactionsWithWarehouse: UpdateInventoryTransactionsWithWarehouse,
|
||||
private readonly createInitialWarehousesItemsQuantity: CreateInitialWarehousesItemsQuantity,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates inventory transactiont to primary warehouse once
|
||||
* multi-warehouses activated.
|
||||
* @param {IWarehousesActivatedPayload}
|
||||
*/
|
||||
@OnEvent(events.warehouse.onActivated)
|
||||
async updateInventoryTransactionsWithWarehouseOnActivating({
|
||||
primaryWarehouse,
|
||||
}: IWarehousesActivatedPayload) {
|
||||
await this.updateInventoryTransactionsWithWarehouse.run(
|
||||
primaryWarehouse.id,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates initial warehouses items quantity once the multi-warehouses activated.
|
||||
* @param {IWarehousesActivatedPayload}
|
||||
*/
|
||||
@OnEvent(events.warehouse.onActivated)
|
||||
async createInitialWarehousesItemsQuantityOnActivating({
|
||||
primaryWarehouse,
|
||||
}: IWarehousesActivatedPayload) {
|
||||
await this.createInitialWarehousesItemsQuantity.run(primaryWarehouse.id);
|
||||
}
|
||||
}
|
||||
26
packages/server/src/modules/Warehouses/CRUDWarehouse.ts
Normal file
26
packages/server/src/modules/Warehouses/CRUDWarehouse.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
// import { Inject, Service } from 'typedi';
|
||||
// import { ServiceError } from '@/exceptions';
|
||||
// import { ERRORS } from './contants';
|
||||
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
|
||||
// export class CRUDWarehouse {
|
||||
// @Inject()
|
||||
// tenancy: HasTenancyService;
|
||||
|
||||
// getWarehouseOrThrowNotFound = async (tenantId: number, warehouseId: number) => {
|
||||
// const { Warehouse } = this.tenancy.models(tenantId);
|
||||
|
||||
// const foundWarehouse = await Warehouse.query().findById(warehouseId);
|
||||
|
||||
// if (!foundWarehouse) {
|
||||
// throw new ServiceError(ERRORS.WAREHOUSE_NOT_FOUND);
|
||||
// }
|
||||
// return foundWarehouse;
|
||||
// };
|
||||
|
||||
// throwIfWarehouseNotFound = (warehouse) => {
|
||||
// if (!warehouse) {
|
||||
// throw new ServiceError(ERRORS.WAREHOUSE_NOT_FOUND);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,55 @@
|
||||
import { Knex } from 'knex';
|
||||
import { WarehousesItemsQuantitySync } from './Integrations/WarehousesItemsQuantitySync';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { IItemWarehouseQuantityChange } from './Warehouse.types';
|
||||
import { Item } from '../Items/models/Item';
|
||||
import { TenantModelProxy } from '../System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class CreateInitialWarehousesItemsQuantity {
|
||||
constructor(
|
||||
private readonly warehousesItemsQuantitySync: WarehousesItemsQuantitySync,
|
||||
|
||||
@Inject(Item.name)
|
||||
private readonly itemModel: TenantModelProxy<typeof Item>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieves items warehouses quantity changes of the given inventory items.
|
||||
* @param {IItem[]} items
|
||||
* @param {IWarehouse} primaryWarehouse
|
||||
* @returns {IItemWarehouseQuantityChange[]}
|
||||
*/
|
||||
private getWarehousesItemsChanges = (
|
||||
items: Item[],
|
||||
primaryWarehouseId: number,
|
||||
): IItemWarehouseQuantityChange[] => {
|
||||
return items
|
||||
.filter((item: Item) => item.quantityOnHand)
|
||||
.map((item: Item) => ({
|
||||
itemId: item.id,
|
||||
warehouseId: primaryWarehouseId,
|
||||
amount: item.quantityOnHand,
|
||||
}));
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates initial warehouses items quantity.
|
||||
* @param {number} tenantId
|
||||
*/
|
||||
public run = async (
|
||||
primaryWarehouseId: number,
|
||||
trx?: Knex.Transaction,
|
||||
): Promise<void> => {
|
||||
const items = await this.itemModel().query(trx).where('type', 'Inventory');
|
||||
|
||||
const warehousesChanges = this.getWarehousesItemsChanges(
|
||||
items,
|
||||
primaryWarehouseId,
|
||||
);
|
||||
await this.warehousesItemsQuantitySync.mutateWarehousesItemsQuantity(
|
||||
warehousesChanges,
|
||||
trx,
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import { chain, difference } from 'lodash';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { ERRORS } from './constants';
|
||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { Warehouse } from '../models/Warehouse.model';
|
||||
|
||||
@Injectable()
|
||||
export class ValidateWarehouseExistance {
|
||||
/**
|
||||
* @param {TenantModelProxy<typeof Warehouse>} warehouseModel - Warehouse model.
|
||||
*/
|
||||
constructor(
|
||||
@Inject(Warehouse.name)
|
||||
private readonly warehouseModel: TenantModelProxy<typeof Warehouse>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate transaction warehouse id existance.
|
||||
* @param transDTO
|
||||
* @param entries
|
||||
*/
|
||||
public validateWarehouseIdExistance = (
|
||||
transDTO: { warehouseId?: number },
|
||||
entries: { warehouseId?: number }[] = [],
|
||||
) => {
|
||||
const notAssignedWarehouseEntries = entries.filter((e) => !e.warehouseId);
|
||||
|
||||
if (notAssignedWarehouseEntries.length > 0 && !transDTO.warehouseId) {
|
||||
throw new ServiceError(ERRORS.WAREHOUSE_ID_NOT_FOUND);
|
||||
}
|
||||
if (entries.length === 0 && !transDTO.warehouseId) {
|
||||
throw new ServiceError(ERRORS.WAREHOUSE_ID_NOT_FOUND);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate warehouse existance.
|
||||
* @param {number} warehouseId - Warehouse id.
|
||||
*/
|
||||
public validateWarehouseExistance = (warehouseId: number) => {
|
||||
const warehouse = this.warehouseModel().query().findById(warehouseId);
|
||||
|
||||
if (!warehouse) {
|
||||
throw new ServiceError(ERRORS.WAREHOUSE_ID_NOT_FOUND);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate item entries warehouses existance.
|
||||
* @param {{ warehouseId?: number }[]} entries
|
||||
*/
|
||||
public validateItemEntriesWarehousesExistance = async (
|
||||
entries: { warehouseId?: number }[],
|
||||
) => {
|
||||
const entriesWarehousesIds = chain(entries)
|
||||
.filter((e) => !!e.warehouseId)
|
||||
.map((e) => e.warehouseId)
|
||||
.uniq()
|
||||
.value();
|
||||
|
||||
const warehouses = await this.warehouseModel()
|
||||
.query()
|
||||
.whereIn('id', entriesWarehousesIds);
|
||||
const warehousesIds = warehouses.map((e) => e.id);
|
||||
const notFoundWarehousesIds = difference(
|
||||
entriesWarehousesIds,
|
||||
warehousesIds,
|
||||
);
|
||||
if (notFoundWarehousesIds.length > 0) {
|
||||
throw new ServiceError(ERRORS.WAREHOUSE_ID_NOT_FOUND);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { omit } from 'lodash';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { WarehousesSettings } from '../WarehousesSettings';
|
||||
|
||||
@Injectable()
|
||||
export class WarehouseTransactionDTOTransform {
|
||||
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 = async <
|
||||
T extends { warehouseId?: number },
|
||||
>(
|
||||
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 = async <T extends { warehouseId?: number }>(
|
||||
DTO: T,
|
||||
): Promise<Omit<T, 'warehouseId'> | T> => {
|
||||
return this.excludeDTOWarehouseIdWhenInactive<T>(DTO);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { ValidateWarehouseExistance } from './ValidateWarehouseExistance';
|
||||
import { WarehousesSettings } from '../WarehousesSettings';
|
||||
|
||||
interface IWarehouseTransactionDTO {
|
||||
warehouseId?: number | null;
|
||||
entries?: { warehouseId?: number | null }[];
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class WarehousesDTOValidators {
|
||||
constructor(
|
||||
private readonly validateWarehouseExistanceService: ValidateWarehouseExistance,
|
||||
private readonly warehousesSettings: WarehousesSettings,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validates the warehouse existance of sale invoice transaction.
|
||||
* @param {IWarehouseTransactionDTO} DTO
|
||||
*/
|
||||
public validateDTOWarehouseExistance = async (
|
||||
DTO: IWarehouseTransactionDTO,
|
||||
) => {
|
||||
// Validates the sale invoice warehouse id existance.
|
||||
this.validateWarehouseExistanceService.validateWarehouseIdExistance(
|
||||
DTO,
|
||||
DTO.entries,
|
||||
);
|
||||
// Validate the sale invoice warehouse existance on the storage.
|
||||
if (DTO.warehouseId) {
|
||||
this.validateWarehouseExistanceService.validateWarehouseExistance(
|
||||
DTO.warehouseId,
|
||||
);
|
||||
}
|
||||
// Validate the sale invoice entries warehouses existance on the storage.
|
||||
if (!isEmpty(DTO.entries)) {
|
||||
await this.validateWarehouseExistanceService.validateItemEntriesWarehousesExistance(
|
||||
DTO.entries,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate the warehouse existance of
|
||||
* @param {IWarehouseTransactionDTO} saleInvoiceDTO
|
||||
* @returns
|
||||
*/
|
||||
public validateDTOWarehouseWhenActive = async (
|
||||
DTO: IWarehouseTransactionDTO,
|
||||
): Promise<void> => {
|
||||
const isActive = await this.warehousesSettings.isMultiWarehousesActive();
|
||||
|
||||
// Can't continue if the multi-warehouses feature is inactive.
|
||||
if (!isActive) return;
|
||||
|
||||
return this.validateDTOWarehouseExistance(DTO);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
import { IItemWarehouseQuantityChange } from '@/modules/Warehouses/Warehouse.types';
|
||||
import { set, get, chain, toPairs } from 'lodash';
|
||||
import { InventoryTransaction } from '@/modules/InventoryCost/models/InventoryTransaction';
|
||||
|
||||
export class WarehousesItemsQuantity {
|
||||
balanceMap: { [warehouseId: number]: { [itemId: number]: number } } = {};
|
||||
/**
|
||||
*
|
||||
* @param {number} warehouseId
|
||||
* @param {number} itemId
|
||||
* @returns {number}
|
||||
*/
|
||||
public get = (warehouseId: number, itemId: number): number => {
|
||||
return get(this.balanceMap, `${warehouseId}.${itemId}`, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number} warehouseId
|
||||
* @param {number} itemId
|
||||
* @param {number} amount
|
||||
* @returns {WarehousesItemsQuantity}
|
||||
*/
|
||||
public set = (warehouseId: number, itemId: number, amount: number) => {
|
||||
if (!get(this.balanceMap, warehouseId)) {
|
||||
set(this.balanceMap, warehouseId, {});
|
||||
}
|
||||
set(this.balanceMap, `${warehouseId}.${itemId}`, amount);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number} warehouseId
|
||||
* @param {number} itemId
|
||||
* @param {number} amount
|
||||
* @returns {WarehousesItemsQuantity}
|
||||
*/
|
||||
public increment = (warehouseId: number, itemId: number, amount: number) => {
|
||||
const oldAmount = this.get(warehouseId, itemId);
|
||||
|
||||
return this.set(warehouseId, itemId, oldAmount + amount);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number} warehouseId
|
||||
* @param {number} itemId
|
||||
* @param {number} amount
|
||||
* @returns {WarehousesItemsQuantity}
|
||||
*/
|
||||
public decrement = (warehouseId: number, itemId: number, amount: number) => {
|
||||
const oldAmount = this.get(warehouseId, itemId);
|
||||
|
||||
return this.set(warehouseId, itemId, oldAmount - amount);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {WarehousesItemsQuantity}
|
||||
*/
|
||||
public reverse = () => {
|
||||
const collection = this.toArray();
|
||||
|
||||
collection.forEach((change) => {
|
||||
this.set(change.warehouseId, change.itemId, change.amount * -1);
|
||||
});
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {IItemWarehouseQuantityChange[]}
|
||||
*/
|
||||
public toArray = (): IItemWarehouseQuantityChange[] => {
|
||||
return chain(this.balanceMap)
|
||||
.toPairs()
|
||||
.map(([warehouseId, item]) => {
|
||||
const pairs = toPairs(item);
|
||||
|
||||
return pairs.map(([itemId, amount]) => ({
|
||||
itemId: parseInt(itemId),
|
||||
warehouseId: parseInt(warehouseId),
|
||||
amount,
|
||||
}));
|
||||
})
|
||||
.flatten()
|
||||
.value();
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {IInventoryTransaction[]} inventoryTransactions
|
||||
* @returns {WarehousesItemsQuantity}
|
||||
*/
|
||||
static fromInventoryTransaction = (
|
||||
inventoryTransactions: InventoryTransaction[],
|
||||
): WarehousesItemsQuantity => {
|
||||
const warehouseTransactions = inventoryTransactions.filter(
|
||||
(transaction) => transaction.warehouseId,
|
||||
);
|
||||
const warehouseItemsQuantity = new WarehousesItemsQuantity();
|
||||
|
||||
warehouseTransactions.forEach((transaction: InventoryTransaction) => {
|
||||
const change =
|
||||
transaction.direction === 'IN'
|
||||
? warehouseItemsQuantity.increment
|
||||
: warehouseItemsQuantity.decrement;
|
||||
|
||||
change(transaction.warehouseId, transaction.itemId, transaction.quantity);
|
||||
});
|
||||
return warehouseItemsQuantity;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import { WarehousesItemsQuantitySync } from './WarehousesItemsQuantitySync';
|
||||
import { WarehousesSettings } from '../WarehousesSettings';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { events } from '@/common/events/events';
|
||||
import {
|
||||
IInventoryTransactionsCreatedPayload,
|
||||
IInventoryTransactionsDeletedPayload,
|
||||
} from '@/modules/InventoryCost/types/InventoryCost.types';
|
||||
|
||||
@Injectable()
|
||||
export class WarehousesItemsQuantitySyncSubscriber {
|
||||
constructor(
|
||||
private readonly warehousesItemsQuantitySync: WarehousesItemsQuantitySync,
|
||||
private readonly warehousesSettings: WarehousesSettings,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Syncs warehouses items quantity once inventory transactions created.
|
||||
* @param {IInventoryTransactionsCreatedPayload}
|
||||
*/
|
||||
@OnEvent(events.inventory.onInventoryTransactionsCreated)
|
||||
async syncWarehousesItemsQuantityOnInventoryTransCreated({
|
||||
inventoryTransactions,
|
||||
trx,
|
||||
}: IInventoryTransactionsCreatedPayload) {
|
||||
const isActive = await this.warehousesSettings.isMultiWarehousesActive();
|
||||
|
||||
// Can't continue if the warehouses features is not active.
|
||||
if (!isActive) return;
|
||||
|
||||
await this.warehousesItemsQuantitySync.mutateWarehousesItemsQuantityFromTransactions(
|
||||
inventoryTransactions,
|
||||
trx,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncs warehouses items quantity once inventory transactions deleted.
|
||||
* @param {IInventoryTransactionsDeletedPayload}
|
||||
*/
|
||||
@OnEvent(events.inventory.onInventoryTransactionsDeleted)
|
||||
async syncWarehousesItemsQuantityOnInventoryTransDeleted({
|
||||
oldInventoryTransactions,
|
||||
trx,
|
||||
}: IInventoryTransactionsDeletedPayload) {
|
||||
const isActive = await this.warehousesSettings.isMultiWarehousesActive();
|
||||
|
||||
// Can't continue if the warehouses feature is not active yet.
|
||||
if (!isActive) return;
|
||||
|
||||
await this.warehousesItemsQuantitySync.reverseWarehousesItemsQuantityFromTransactions(
|
||||
oldInventoryTransactions,
|
||||
trx,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
import { InventoryTransaction } from '@/modules/InventoryCost/models/InventoryTransaction';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import { omit } from 'lodash';
|
||||
import { IItemWarehouseQuantityChange } from '../Warehouse.types';
|
||||
import { WarehousesItemsQuantity } from './WarehousesItemsQuantity';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { ItemWarehouseQuantity } from '../models/ItemWarehouseQuantity';
|
||||
|
||||
@Injectable()
|
||||
export class WarehousesItemsQuantitySync {
|
||||
constructor(
|
||||
private readonly warehouseItemsQuantityModel: WarehousesItemsQuantity,
|
||||
private readonly itemWarehouseQuantityModel: TenantModelProxy<
|
||||
typeof ItemWarehouseQuantity
|
||||
>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieves the reversed warehouses items quantity changes.
|
||||
* @param {InventoryTransaction[]} inventoryTransactions
|
||||
* @returns {IItemWarehouseQuantityChange[]}
|
||||
*/
|
||||
public getReverseWarehousesItemsQuantityChanges = (
|
||||
inventoryTransactions: InventoryTransaction[],
|
||||
): IItemWarehouseQuantityChange[] => {
|
||||
const warehouseItemsQuantity =
|
||||
WarehousesItemsQuantity.fromInventoryTransaction(inventoryTransactions);
|
||||
|
||||
return warehouseItemsQuantity.reverse().toArray();
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the warehouses items changes from the given inventory tranasctions.
|
||||
* @param {InventoryTransaction[]} inventoryTransactions
|
||||
* @returns {IItemWarehouseQuantityChange[]}
|
||||
*/
|
||||
public getWarehousesItemsQuantityChange = (
|
||||
inventoryTransactions: InventoryTransaction[],
|
||||
): IItemWarehouseQuantityChange[] => {
|
||||
const warehouseItemsQuantity =
|
||||
WarehousesItemsQuantity.fromInventoryTransaction(inventoryTransactions);
|
||||
|
||||
return warehouseItemsQuantity.toArray();
|
||||
};
|
||||
|
||||
/**
|
||||
* Mutates warehouses items quantity on hand on the storage.
|
||||
* @param {IItemWarehouseQuantityChange[]} warehousesItemsQuantity
|
||||
* @param {Knex.Transaction} trx
|
||||
*/
|
||||
public mutateWarehousesItemsQuantity = async (
|
||||
warehousesItemsQuantity: IItemWarehouseQuantityChange[],
|
||||
trx?: Knex.Transaction,
|
||||
): Promise<void> => {
|
||||
const mutationsOpers = warehousesItemsQuantity.map(
|
||||
(change: IItemWarehouseQuantityChange) =>
|
||||
this.mutateWarehouseItemQuantity(change, trx),
|
||||
);
|
||||
await Promise.all(mutationsOpers);
|
||||
};
|
||||
|
||||
/**
|
||||
* Mutates the warehouse item quantity.
|
||||
* @param {number} warehouseItemQuantity
|
||||
* @param {Knex.Transaction} trx
|
||||
*/
|
||||
public mutateWarehouseItemQuantity = async (
|
||||
warehouseItemQuantity: IItemWarehouseQuantityChange,
|
||||
trx: Knex.Transaction,
|
||||
): Promise<void> => {
|
||||
const itemWarehouseQuantity = await this.itemWarehouseQuantityModel()
|
||||
.query(trx)
|
||||
.where('itemId', warehouseItemQuantity.itemId)
|
||||
.where('warehouseId', warehouseItemQuantity.warehouseId)
|
||||
.first();
|
||||
|
||||
if (itemWarehouseQuantity) {
|
||||
// @ts-ignore
|
||||
await ItemWarehouseQuantity.changeAmount(
|
||||
{
|
||||
itemId: warehouseItemQuantity.itemId,
|
||||
warehouseId: warehouseItemQuantity.warehouseId,
|
||||
},
|
||||
'quantityOnHand',
|
||||
warehouseItemQuantity.amount,
|
||||
trx,
|
||||
);
|
||||
} else {
|
||||
await ItemWarehouseQuantity.query(trx).insert({
|
||||
...omit(warehouseItemQuantity, ['amount']),
|
||||
quantityOnHand: warehouseItemQuantity.amount,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Mutates warehouses items quantity from inventory transactions.
|
||||
* @param {number} tenantId -
|
||||
* @param {IInventoryTransaction[]} inventoryTransactions -
|
||||
* @param {Knex.Transaction}
|
||||
*/
|
||||
public mutateWarehousesItemsQuantityFromTransactions = async (
|
||||
inventoryTransactions: InventoryTransaction[],
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
const changes = this.getWarehousesItemsQuantityChange(
|
||||
inventoryTransactions,
|
||||
);
|
||||
await this.mutateWarehousesItemsQuantity(changes, trx);
|
||||
};
|
||||
|
||||
/**
|
||||
* Reverses warehouses items quantity from inventory transactions.
|
||||
* @param {number} tenantId
|
||||
* @param {IInventoryTransaction[]} inventoryTransactions
|
||||
* @param {Knex.Transaction} trx
|
||||
*/
|
||||
public reverseWarehousesItemsQuantityFromTransactions = async (
|
||||
inventoryTransactions: InventoryTransaction[],
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
const changes = this.getReverseWarehousesItemsQuantityChanges(
|
||||
inventoryTransactions,
|
||||
);
|
||||
await this.mutateWarehousesItemsQuantity(changes, trx);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export const ERRORS = {
|
||||
WAREHOUSE_ID_NOT_FOUND: 'WAREHOUSE_ID_NOT_FOUND',
|
||||
ITEM_ENTRY_WAREHOUSE_ID_NOT_FOUND: 'ITEM_ENTRY_WAREHOUSE_ID_NOT_FOUND',
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
import { GetItemWarehouseTransformer } from './GettItemWarehouseTransformer';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { ItemWarehouseQuantity } from '../models/ItemWarehouseQuantity';
|
||||
import { Item } from '@/modules/Items/models/Item';
|
||||
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class GetItemWarehouses {
|
||||
constructor(
|
||||
@Inject(ItemWarehouseQuantity.name)
|
||||
private readonly itemWarehouseQuantityModel: TenantModelProxy<
|
||||
typeof ItemWarehouseQuantity
|
||||
>,
|
||||
|
||||
@Inject(Item.name)
|
||||
private readonly itemModel: TenantModelProxy<typeof Item>,
|
||||
private readonly transformer: TransformerInjectable,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieves the item warehouses.
|
||||
* @param {number} itemId
|
||||
* @returns
|
||||
*/
|
||||
public getItemWarehouses = async (itemId: number) => {
|
||||
// Retrieves specific item or throw not found service error.
|
||||
const item = await this.itemModel()
|
||||
.query()
|
||||
.findById(itemId)
|
||||
.throwIfNotFound();
|
||||
|
||||
const itemWarehouses = await this.itemWarehouseQuantityModel()
|
||||
.query()
|
||||
.where('itemId', itemId)
|
||||
.withGraphFetched('warehouse');
|
||||
|
||||
// Retrieves the transformed items warehouses.
|
||||
return this.transformer.transform(
|
||||
itemWarehouses,
|
||||
new GetItemWarehouseTransformer(),
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { Transformer } from '@/modules/Transformer/Transformer';
|
||||
import { Item } from '@/modules/Items/models/Item';
|
||||
|
||||
export class GetItemWarehouseTransformer extends Transformer {
|
||||
/**
|
||||
* Include these attributes to sale invoice object.
|
||||
* @returns {Array}
|
||||
*/
|
||||
public includeAttributes = (): string[] => {
|
||||
return [
|
||||
'warehouseId',
|
||||
'warehouseName',
|
||||
'warehouseCode',
|
||||
'quantityOnHandFormatted',
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* Exclude the warehouse attribute.
|
||||
* @returns {Array}
|
||||
*/
|
||||
public excludeAttributes = (): string[] => {
|
||||
return ['warehouse'];
|
||||
};
|
||||
|
||||
/**
|
||||
* Formatted sell price.
|
||||
* @param item
|
||||
* @returns {string}
|
||||
*/
|
||||
public quantityOnHandFormatted(item: Item): string {
|
||||
return this.formatNumber(item.quantityOnHand, { money: false });
|
||||
}
|
||||
|
||||
public warehouseCode(item: Item): string {
|
||||
return item.warehouse.code;
|
||||
}
|
||||
|
||||
public warehouseName(item: Item): string {
|
||||
return item.warehouse.name;
|
||||
}
|
||||
|
||||
public warehouseId(item: Item): number {
|
||||
return item.warehouse.id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { TenantModelProxy } from '../System/models/TenantBaseModel';
|
||||
import { InventoryTransaction } from '../InventoryCost/models/InventoryTransaction';
|
||||
|
||||
@Injectable()
|
||||
export class UpdateInventoryTransactionsWithWarehouse {
|
||||
constructor(
|
||||
@Inject(InventoryTransaction.name)
|
||||
private readonly inventoryTransactionModel: TenantModelProxy<
|
||||
typeof InventoryTransaction
|
||||
>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all inventory transactions with primary warehouse.
|
||||
* @param {number} warehouseId - Warehouse ID.
|
||||
*/
|
||||
public run = async (primaryWarehouseId: number) => {
|
||||
await this.inventoryTransactionModel().query().update({
|
||||
warehouseId: primaryWarehouseId,
|
||||
});
|
||||
};
|
||||
}
|
||||
186
packages/server/src/modules/Warehouses/Warehouse.types.ts
Normal file
186
packages/server/src/modules/Warehouses/Warehouse.types.ts
Normal file
@@ -0,0 +1,186 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Warehouse } from './models/Warehouse.model';
|
||||
import { WarehouseTransfer } from '../WarehousesTransfers/models/WarehouseTransfer';
|
||||
import { ModelObject } from 'objection';
|
||||
|
||||
export interface IWarehouse {
|
||||
id?: number;
|
||||
}
|
||||
|
||||
export interface IWarehouseTransferEntry {
|
||||
id?: number;
|
||||
index?: number;
|
||||
itemId: number;
|
||||
description: string;
|
||||
quantity: number;
|
||||
cost: number;
|
||||
}
|
||||
export interface ICreateWarehouseDTO {
|
||||
name: string;
|
||||
code: string;
|
||||
|
||||
city?: string;
|
||||
country?: string;
|
||||
address?: string;
|
||||
|
||||
primary?: boolean;
|
||||
}
|
||||
export interface IEditWarehouseDTO {
|
||||
name: string;
|
||||
code: string;
|
||||
city: string;
|
||||
country: string;
|
||||
address: string;
|
||||
}
|
||||
|
||||
export interface IWarehouseTransferEntryDTO {
|
||||
index?: number;
|
||||
itemId: number;
|
||||
description: string;
|
||||
quantity: number;
|
||||
cost?: number;
|
||||
}
|
||||
|
||||
export interface ICreateWarehouseTransferDTO {
|
||||
fromWarehouseId: number;
|
||||
toWarehouseId: number;
|
||||
transactionNumber: string;
|
||||
date: Date;
|
||||
transferInitiated: boolean;
|
||||
transferDelivered: boolean;
|
||||
entries: IWarehouseTransferEntryDTO[];
|
||||
}
|
||||
export interface IEditWarehouseTransferDTO {
|
||||
fromWarehouseId: number;
|
||||
toWarehouseId: number;
|
||||
transactionNumber: string;
|
||||
date: Date;
|
||||
entries: {
|
||||
id?: number;
|
||||
itemId: number;
|
||||
description: string;
|
||||
quantity: number;
|
||||
}[];
|
||||
}
|
||||
|
||||
export interface IWarehouseEditPayload {
|
||||
tenantId: number;
|
||||
warehouseId: number;
|
||||
warehouseDTO: IEditWarehouseDTO;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IWarehouseEditedPayload {
|
||||
tenantId: number;
|
||||
warehouse: IWarehouse;
|
||||
warehouseDTO: IEditWarehouseDTO;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IWarehouseDeletePayload {
|
||||
// tenantId: number;
|
||||
warehouseId: number;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
export interface IWarehouseDeletedPayload {
|
||||
tenantId: number;
|
||||
warehouseId: number;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
export interface IWarehouseCreatePayload {
|
||||
warehouseDTO: ICreateWarehouseDTO;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IWarehouseCreatedPayload {
|
||||
warehouse: IWarehouse;
|
||||
warehouseDTO: ICreateWarehouseDTO;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IWarehouseTransferCreate {
|
||||
trx: Knex.Transaction;
|
||||
warehouseTransferDTO: ICreateWarehouseTransferDTO;
|
||||
tenantId: number;
|
||||
}
|
||||
|
||||
export interface IWarehouseTransferCreated {
|
||||
trx?: Knex.Transaction;
|
||||
warehouseTransfer: ModelObject<WarehouseTransfer>;
|
||||
warehouseTransferDTO: ICreateWarehouseTransferDTO;
|
||||
}
|
||||
|
||||
export interface IWarehouseTransferEditPayload {
|
||||
editWarehouseDTO: IEditWarehouseTransferDTO;
|
||||
oldWarehouseTransfer: ModelObject<WarehouseTransfer>;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IWarehouseTransferEditedPayload {
|
||||
editWarehouseDTO: IEditWarehouseTransferDTO;
|
||||
oldWarehouseTransfer: ModelObject<WarehouseTransfer>;
|
||||
warehouseTransfer: ModelObject<WarehouseTransfer>;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IWarehouseTransferDeletePayload {
|
||||
oldWarehouseTransfer: ModelObject<WarehouseTransfer>;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IWarehouseTransferDeletedPayload {
|
||||
oldWarehouseTransfer: ModelObject<WarehouseTransfer>;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IGetWarehousesTransfersFilterDTO {
|
||||
page: number;
|
||||
pageSize: number;
|
||||
searchKeyword: string;
|
||||
}
|
||||
|
||||
export interface IItemWarehouseQuantityChange {
|
||||
itemId: number;
|
||||
warehouseId: number;
|
||||
amount: number;
|
||||
}
|
||||
|
||||
export interface IWarehousesActivatePayload {
|
||||
// tenantId: number;
|
||||
}
|
||||
export interface IWarehousesActivatedPayload {
|
||||
// tenantId: number;
|
||||
primaryWarehouse: Warehouse;
|
||||
}
|
||||
|
||||
export interface IWarehouseMarkAsPrimaryPayload {
|
||||
oldWarehouse: Warehouse;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
export interface IWarehouseMarkedAsPrimaryPayload {
|
||||
oldWarehouse: Warehouse;
|
||||
markedWarehouse: Warehouse;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IWarehouseTransferInitiatePayload {
|
||||
oldWarehouseTransfer: ModelObject<WarehouseTransfer>;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IWarehouseTransferInitiatedPayload {
|
||||
warehouseTransfer: ModelObject<WarehouseTransfer>;
|
||||
oldWarehouseTransfer: ModelObject<WarehouseTransfer>;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IWarehouseTransferTransferingPayload {
|
||||
oldWarehouseTransfer: ModelObject<WarehouseTransfer>;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IWarehouseTransferTransferredPayload {
|
||||
warehouseTransfer: ModelObject<WarehouseTransfer>;
|
||||
oldWarehouseTransfer: ModelObject<WarehouseTransfer>;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Param,
|
||||
Post,
|
||||
Put,
|
||||
} from '@nestjs/common';
|
||||
import { WarehousesApplication } from './WarehousesApplication.service';
|
||||
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
import { CreateWarehouseDto, EditWarehouseDto } from './dtos/Warehouse.dto';
|
||||
|
||||
@Controller('warehouses')
|
||||
@ApiTags('warehouses')
|
||||
export class WarehousesController {
|
||||
constructor(private warehousesApplication: WarehousesApplication) {}
|
||||
|
||||
@Post()
|
||||
@ApiOperation({ summary: 'Create a warehouse' })
|
||||
createWarehouse(@Body() createWarehouseDTO: CreateWarehouseDto) {
|
||||
return this.warehousesApplication.createWarehouse(createWarehouseDTO);
|
||||
}
|
||||
|
||||
@Put(':id')
|
||||
editWarehouse(
|
||||
@Param('id') warehouseId: string,
|
||||
@Body() editWarehouseDTO: EditWarehouseDto,
|
||||
) {
|
||||
return this.warehousesApplication.editWarehouse(
|
||||
Number(warehouseId),
|
||||
editWarehouseDTO,
|
||||
);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
@ApiOperation({ summary: 'Delete a warehouse' })
|
||||
deleteWarehouse(@Param('id') warehouseId: string) {
|
||||
return this.warehousesApplication.deleteWarehouse(Number(warehouseId));
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@ApiOperation({ summary: 'Get a warehouse' })
|
||||
getWarehouse(@Param('id') warehouseId: string) {
|
||||
return this.warehousesApplication.getWarehouse(Number(warehouseId));
|
||||
}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: 'Get all warehouses' })
|
||||
getWarehouses() {
|
||||
return this.warehousesApplication.getWarehouses();
|
||||
}
|
||||
|
||||
@Post('activate')
|
||||
@ApiOperation({ summary: 'Activate a warehouse' })
|
||||
activateWarehouses() {
|
||||
return this.warehousesApplication.activateWarehouses();
|
||||
}
|
||||
|
||||
@Post(':id/mark-primary')
|
||||
@ApiOperation({ summary: 'Mark a warehouse as primary' })
|
||||
markWarehousePrimary(@Param('id') warehouseId: string) {
|
||||
return this.warehousesApplication.markWarehousePrimary(Number(warehouseId));
|
||||
}
|
||||
|
||||
@Get('items/:itemId')
|
||||
@ApiOperation({ summary: 'Get item warehouses' })
|
||||
getItemWarehouses(@Param('itemId') itemId: string) {
|
||||
return this.warehousesApplication.getItemWarehouses(Number(itemId));
|
||||
}
|
||||
}
|
||||
95
packages/server/src/modules/Warehouses/Warehouses.module.ts
Normal file
95
packages/server/src/modules/Warehouses/Warehouses.module.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { I18nContext } from 'nestjs-i18n';
|
||||
import { TenancyDatabaseModule } from '../Tenancy/TenancyDB/TenancyDB.module';
|
||||
import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
||||
import { TransformerInjectable } from '../Transformer/TransformerInjectable.service';
|
||||
import { CreateWarehouse } from './commands/CreateWarehouse.service';
|
||||
import { EditWarehouse } from './commands/EditWarehouse.service';
|
||||
import { DeleteWarehouseService } from './commands/DeleteWarehouse.service';
|
||||
import { WarehousesController } from './Warehouses.controller';
|
||||
import { GetWarehouse } from './queries/GetWarehouse';
|
||||
import { WarehouseMarkPrimary } from './commands/WarehouseMarkPrimary.service';
|
||||
import { GetWarehouses } from './queries/GetWarehouses';
|
||||
import { GetItemWarehouses } from './Items/GetItemWarehouses';
|
||||
import { WarehouseValidator } from './commands/WarehouseValidator.service';
|
||||
import { WarehousesApplication } from './WarehousesApplication.service';
|
||||
import { ActivateWarehousesService } from './commands/ActivateWarehouses.service';
|
||||
import { CreateInitialWarehouse } from './commands/CreateInitialWarehouse.service';
|
||||
import { WarehousesSettings } from './WarehousesSettings';
|
||||
import { WarehouseTransactionDTOTransform } from './Integrations/WarehouseTransactionDTOTransform';
|
||||
import { BillsActivateWarehousesSubscriber } from './subscribers/Activate/BillWarehousesActivateSubscriber';
|
||||
import { VendorCreditsActivateWarehousesSubscriber } from './subscribers/Activate/VendorCreditWarehousesActivateSubscriber';
|
||||
import { ReceiptsActivateWarehousesSubscriber } from './subscribers/Activate/ReceiptWarehousesActivateSubscriber';
|
||||
import { InvoicesActivateWarehousesSubscriber } from './subscribers/Activate/InvoiceWarehousesActivateSubscriber';
|
||||
import { CreditsActivateWarehousesSubscriber } from './subscribers/Activate/CreditNoteWarehousesActivateSubscriber';
|
||||
import { InventoryAdjustmentWarehouseValidatorSubscriber } from './subscribers/Validators/InventoryAdjustment/InventoryAdjustmentWarehouseValidatorSubscriber';
|
||||
import { DeleteItemWarehousesQuantitySubscriber } from './subscribers/DeleteItemWarehousesQuantitySubscriber';
|
||||
import { VendorCreditWarehousesValidateSubscriber } from './subscribers/Validators/Purchases/VendorCreditWarehousesSubscriber';
|
||||
import { SaleInvoicesWarehousesValidateSubscriber } from './subscribers/Validators/Sales/SaleInvoicesWarehousesSubscriber';
|
||||
import { SaleEstimateWarehousesValidateSubscriber } from './subscribers/Validators/Sales/SaleEstimateWarehousesSubscriber';
|
||||
import { SaleReceiptWarehousesValidateSubscriber } from './subscribers/Validators/Sales/SaleReceiptWarehousesSubscriber';
|
||||
import { CreditNoteWarehousesValidateSubscriber } from './subscribers/Validators/Sales/CreditNoteWarehousesSubscriber';
|
||||
import { BillWarehousesValidateSubscriber } from './subscribers/Validators/Purchases/BillWarehousesSubscriber';
|
||||
import { AccountsTransactionsWarehousesSubscribe } from './AccountsTransactionsWarehousesSubscribe';
|
||||
import { BillActivateWarehouses } from './Activate/BillWarehousesActivate';
|
||||
import { CreditNotesActivateWarehouses } from './Activate/CreditNoteWarehousesActivate';
|
||||
import { VendorCreditActivateWarehouses } from './Activate/VendorCreditWarehousesActivate';
|
||||
import { InvoicesActivateWarehouses } from './Activate/InvoiceWarehousesActivate';
|
||||
import { ReceiptActivateWarehouses } from './Activate/ReceiptWarehousesActivate';
|
||||
import { WarehousesDTOValidators } from './Integrations/WarehousesDTOValidators';
|
||||
import { DeleteItemWarehousesQuantity } from './commands/DeleteItemWarehousesQuantity';
|
||||
import { InventoryTransactionsWarehouses } from './AccountsTransactionsWarehouses';
|
||||
import { RegisterTenancyModel } from '../Tenancy/TenancyModels/Tenancy.module';
|
||||
import { Warehouse } from './models/Warehouse.model';
|
||||
import { ValidateWarehouseExistance } from './Integrations/ValidateWarehouseExistance';
|
||||
|
||||
const models = [RegisterTenancyModel(Warehouse)];
|
||||
|
||||
@Module({
|
||||
imports: [TenancyDatabaseModule, ...models],
|
||||
controllers: [WarehousesController],
|
||||
providers: [
|
||||
CreateWarehouse,
|
||||
EditWarehouse,
|
||||
DeleteWarehouseService,
|
||||
GetWarehouse,
|
||||
GetWarehouses,
|
||||
GetItemWarehouses,
|
||||
WarehouseMarkPrimary,
|
||||
WarehouseValidator,
|
||||
WarehousesApplication,
|
||||
ActivateWarehousesService,
|
||||
CreateInitialWarehouse,
|
||||
WarehousesSettings,
|
||||
I18nContext,
|
||||
TenancyContext,
|
||||
TransformerInjectable,
|
||||
WarehouseTransactionDTOTransform,
|
||||
BillsActivateWarehousesSubscriber,
|
||||
CreditsActivateWarehousesSubscriber,
|
||||
InvoicesActivateWarehousesSubscriber,
|
||||
ReceiptsActivateWarehousesSubscriber,
|
||||
VendorCreditsActivateWarehousesSubscriber,
|
||||
InventoryAdjustmentWarehouseValidatorSubscriber,
|
||||
DeleteItemWarehousesQuantitySubscriber,
|
||||
BillWarehousesValidateSubscriber,
|
||||
CreditNoteWarehousesValidateSubscriber,
|
||||
SaleReceiptWarehousesValidateSubscriber,
|
||||
SaleEstimateWarehousesValidateSubscriber,
|
||||
SaleInvoicesWarehousesValidateSubscriber,
|
||||
VendorCreditWarehousesValidateSubscriber,
|
||||
AccountsTransactionsWarehousesSubscribe,
|
||||
BillActivateWarehouses,
|
||||
CreditNotesActivateWarehouses,
|
||||
VendorCreditActivateWarehouses,
|
||||
CreditNotesActivateWarehouses,
|
||||
InvoicesActivateWarehouses,
|
||||
ReceiptActivateWarehouses,
|
||||
WarehousesDTOValidators,
|
||||
DeleteItemWarehousesQuantity,
|
||||
InventoryTransactionsWarehouses,
|
||||
ValidateWarehouseExistance
|
||||
],
|
||||
exports: [WarehouseTransactionDTOTransform, ...models],
|
||||
})
|
||||
export class WarehousesModule {}
|
||||
@@ -0,0 +1,104 @@
|
||||
import {
|
||||
IWarehouse,
|
||||
} from './Warehouse.types';
|
||||
import { ActivateWarehousesService } from './commands/ActivateWarehouses.service';
|
||||
import { CreateWarehouse } from './commands/CreateWarehouse.service';
|
||||
import { DeleteWarehouseService } from './commands/DeleteWarehouse.service';
|
||||
import { EditWarehouse } from './commands/EditWarehouse.service';
|
||||
import { GetWarehouse } from './queries/GetWarehouse';
|
||||
import { GetWarehouses } from './queries/GetWarehouses';
|
||||
import { GetItemWarehouses } from './Items/GetItemWarehouses';
|
||||
import { WarehouseMarkPrimary } from './commands/WarehouseMarkPrimary.service';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { CreateWarehouseDto, EditWarehouseDto } from './dtos/Warehouse.dto';
|
||||
|
||||
@Injectable()
|
||||
export class WarehousesApplication {
|
||||
constructor(
|
||||
private createWarehouseService: CreateWarehouse,
|
||||
private editWarehouseService: EditWarehouse,
|
||||
private deleteWarehouseService: DeleteWarehouseService,
|
||||
private getWarehouseService: GetWarehouse,
|
||||
private getWarehousesService: GetWarehouses,
|
||||
private activateWarehousesService: ActivateWarehousesService,
|
||||
private markWarehousePrimaryService: WarehouseMarkPrimary,
|
||||
private getItemWarehousesService: GetItemWarehouses,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Creates a new warehouse.
|
||||
* @param {ICreateWarehouseDTO} createWarehouseDTO
|
||||
* @returns {Promise<IWarehouse>}
|
||||
*/
|
||||
public createWarehouse = (createWarehouseDTO: CreateWarehouseDto) => {
|
||||
return this.createWarehouseService.createWarehouse(createWarehouseDTO);
|
||||
};
|
||||
|
||||
/**
|
||||
* Edits the given warehouse.
|
||||
* @param {number} warehouseId
|
||||
* @param {EditWarehouseDto} editWarehouseDTO
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public editWarehouse = (
|
||||
warehouseId: number,
|
||||
editWarehouseDTO: EditWarehouseDto,
|
||||
) => {
|
||||
return this.editWarehouseService.editWarehouse(
|
||||
warehouseId,
|
||||
editWarehouseDTO,
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes the given warehouse.
|
||||
* @param {number} warehouseId
|
||||
*/
|
||||
public deleteWarehouse = (warehouseId: number) => {
|
||||
return this.deleteWarehouseService.deleteWarehouse(warehouseId);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the specific warehouse.
|
||||
* @param {number} warehouseId
|
||||
* @returns
|
||||
*/
|
||||
public getWarehouse = (warehouseId: number) => {
|
||||
return this.getWarehouseService.getWarehouse(warehouseId);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the warehouses list.
|
||||
* @returns {Promise<IWarehouse[]>}
|
||||
*/
|
||||
public getWarehouses = () => {
|
||||
return this.getWarehousesService.getWarehouses();
|
||||
};
|
||||
|
||||
/**
|
||||
* Activates the warehouses feature.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public activateWarehouses = () => {
|
||||
return this.activateWarehousesService.activateWarehouses();
|
||||
};
|
||||
|
||||
/**
|
||||
* Mark the given warehouse as primary.
|
||||
* @param {number} tenantId -
|
||||
* @returns {Promise<IWarehouse>}
|
||||
*/
|
||||
public markWarehousePrimary = (warehouseId: number): Promise<IWarehouse> => {
|
||||
return this.markWarehousePrimaryService.markAsPrimary(warehouseId);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the specific item warehouses quantity.
|
||||
* @param {number} tenantId
|
||||
* @param {number} itemId
|
||||
* @returns
|
||||
*/
|
||||
public getItemWarehouses = (itemId: number): Promise<any> => {
|
||||
return this.getItemWarehousesService.getItemWarehouses(itemId);
|
||||
};
|
||||
}
|
||||
32
packages/server/src/modules/Warehouses/WarehousesSettings.ts
Normal file
32
packages/server/src/modules/Warehouses/WarehousesSettings.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
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 = async () => {
|
||||
const settings = await this.settingsStore();
|
||||
|
||||
settings.set({ group: 'features', key: Features.WAREHOUSES, value: 1 });
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines multi-warehouses is active.
|
||||
* @param {number} tenantId
|
||||
* @returns {boolean}
|
||||
*/
|
||||
public isMultiWarehousesActive = async () => {
|
||||
const settings = await this.settingsStore();
|
||||
|
||||
return settings.get({ group: 'features', key: Features.WAREHOUSES });
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { CreateInitialWarehouse } from './CreateInitialWarehouse.service';
|
||||
import { WarehousesSettings } from '../WarehousesSettings';
|
||||
import { ERRORS } from '../contants';
|
||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||
import { events } from '@/common/events/events';
|
||||
|
||||
@Injectable()
|
||||
export class ActivateWarehousesService {
|
||||
/**
|
||||
* @param {UnitOfWork} uow - Unit of work.
|
||||
* @param {EventEmitter2} eventEmitter - Event emitter.
|
||||
* @param {CreateInitialWarehouse} createInitialWarehouse - Create initial warehouse service.
|
||||
* @param {WarehousesSettings} settings - Warehouses settings.
|
||||
*/
|
||||
constructor(
|
||||
private readonly uow: UnitOfWork,
|
||||
private readonly eventEmitter: EventEmitter2,
|
||||
private readonly createInitialWarehouse: CreateInitialWarehouse,
|
||||
private readonly settings: WarehousesSettings,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Throws error if the multi-warehouses is already activated.
|
||||
*/
|
||||
private throwIfWarehousesActivated(isActivated: boolean): void {
|
||||
if (isActivated) {
|
||||
throw new ServiceError(ERRORS.MUTLI_WAREHOUSES_ALREADY_ACTIVATED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates the multi-warehouses.
|
||||
*
|
||||
* - Creates a new warehouses and mark it as primary.
|
||||
* - Seed warehouses items quantity.
|
||||
* - Mutate inventory transactions with the primary warehouse.
|
||||
*/
|
||||
public async activateWarehouses(): Promise<void> {
|
||||
const isActivated = await this.settings.isMultiWarehousesActive();
|
||||
this.throwIfWarehousesActivated(isActivated);
|
||||
|
||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||
await this.eventEmitter.emitAsync(events.warehouse.onActivate, { trx });
|
||||
|
||||
const primaryWarehouse =
|
||||
await this.createInitialWarehouse.createInitialWarehouse();
|
||||
|
||||
this.settings.markMutliwarehoussAsActivated();
|
||||
|
||||
await this.eventEmitter.emitAsync(events.warehouse.onActivated, {
|
||||
primaryWarehouse,
|
||||
trx,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { CreateWarehouse } from './CreateWarehouse.service';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { I18nContext } from 'nestjs-i18n';
|
||||
|
||||
@Injectable()
|
||||
export class CreateInitialWarehouse {
|
||||
/**
|
||||
* @param {CreateWarehouse} createWarehouse - Create warehouse service.
|
||||
* @param {I18nContext} i18n - I18n context.
|
||||
*/
|
||||
constructor(
|
||||
private readonly createWarehouse: CreateWarehouse,
|
||||
private readonly i18n: I18nContext,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Creates a initial warehouse.
|
||||
* @param {number} tenantId
|
||||
*/
|
||||
public createInitialWarehouse = async () => {
|
||||
return this.createWarehouse.createWarehouse({
|
||||
name: this.i18n.t('warehouses.primary_warehouse'),
|
||||
code: '10001',
|
||||
primary: true,
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import {
|
||||
IWarehouseCreatedPayload,
|
||||
IWarehouseCreatePayload,
|
||||
} from '../Warehouse.types';
|
||||
import { WarehouseValidator } from './WarehouseValidator.service';
|
||||
import { Warehouse } from '../models/Warehouse.model';
|
||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { CreateWarehouseDto } from '../dtos/Warehouse.dto';
|
||||
|
||||
@Injectable()
|
||||
export class CreateWarehouse {
|
||||
/**
|
||||
* @param {UnitOfWork} uow - Unit of work.
|
||||
* @param {EventEmitter2} eventEmitter - Event emitter.
|
||||
* @param {WarehouseValidator} validator - Warehouse command validator.
|
||||
* @param {typeof Warehouse} warehouseModel - Warehouse model.
|
||||
*/
|
||||
constructor(
|
||||
private readonly uow: UnitOfWork,
|
||||
private readonly eventEmitter: EventEmitter2,
|
||||
private readonly validator: WarehouseValidator,
|
||||
|
||||
@Inject(Warehouse.name)
|
||||
private readonly warehouseModel: TenantModelProxy<typeof Warehouse>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Authorize the warehouse before creating.
|
||||
* @param {ICreateWarehouseDTO} warehouseDTO -
|
||||
*/
|
||||
public authorize = async (warehouseDTO: CreateWarehouseDto) => {
|
||||
if (warehouseDTO.code) {
|
||||
await this.validator.validateWarehouseCodeUnique(warehouseDTO.code);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new warehouse on the system.
|
||||
* @param {ICreateWarehouseDTO} warehouseDTO
|
||||
*/
|
||||
public createWarehouse = async (
|
||||
warehouseDTO: CreateWarehouseDto,
|
||||
): Promise<Warehouse> => {
|
||||
// Authorize warehouse before creating.
|
||||
await this.authorize(warehouseDTO);
|
||||
|
||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||
// Triggers `onWarehouseCreate` event.
|
||||
await this.eventEmitter.emitAsync(events.warehouse.onEdit, {
|
||||
warehouseDTO,
|
||||
trx,
|
||||
} as IWarehouseCreatePayload);
|
||||
|
||||
// Creates a new warehouse on the storage.
|
||||
const warehouse = await this.warehouseModel()
|
||||
.query(trx)
|
||||
.insertAndFetch({
|
||||
...warehouseDTO,
|
||||
});
|
||||
|
||||
// Triggers `onWarehouseCreated` event.
|
||||
await this.eventEmitter.emitAsync(events.warehouse.onCreated, {
|
||||
warehouseDTO,
|
||||
warehouse,
|
||||
trx,
|
||||
} as IWarehouseCreatedPayload);
|
||||
|
||||
return warehouse;
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { ItemWarehouseQuantity } from '../models/ItemWarehouseQuantity';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class DeleteItemWarehousesQuantity {
|
||||
/**
|
||||
* @param {typeof ItemWarehouseQuantity} itemWarehouseQuantityModel - Item warehouse quantity model.
|
||||
*/
|
||||
constructor(
|
||||
@Inject(ItemWarehouseQuantity.name)
|
||||
private readonly itemWarehouseQuantityModel: TenantModelProxy<
|
||||
typeof ItemWarehouseQuantity
|
||||
>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Deletes the given item warehouses quantities.
|
||||
* @param {number} itemId
|
||||
* @param {Knex.Transaction} trx -
|
||||
*/
|
||||
public deleteItemWarehousesQuantity = async (
|
||||
itemId: number,
|
||||
trx?: Knex.Transaction,
|
||||
): Promise<void> => {
|
||||
await this.itemWarehouseQuantityModel()
|
||||
.query(trx)
|
||||
.where('itemId', itemId)
|
||||
.delete();
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import {
|
||||
IWarehouseDeletedPayload,
|
||||
IWarehouseDeletePayload,
|
||||
} from '../Warehouse.types';
|
||||
import { WarehouseValidator } from './WarehouseValidator.service';
|
||||
import { ERRORS } from '../contants';
|
||||
import { Warehouse } from '../models/Warehouse.model';
|
||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { events } from '@/common/events/events';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class DeleteWarehouseService {
|
||||
/**
|
||||
* @param {UnitOfWork} uow - Unit of work.
|
||||
* @param {EventEmitter2} eventPublisher - Event emitter.
|
||||
* @param {WarehouseValidator} validator - Warehouse command validator.
|
||||
* @param {typeof Warehouse} warehouseModel - Warehouse model.
|
||||
*/
|
||||
constructor(
|
||||
private readonly uow: UnitOfWork,
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
private readonly validator: WarehouseValidator,
|
||||
|
||||
@Inject(Warehouse.name)
|
||||
private readonly warehouseModel: TenantModelProxy<typeof Warehouse>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validates the given warehouse before deleting.
|
||||
* @param {number} warehouseId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public authorize = async (warehouseId: number): Promise<void> => {
|
||||
await this.validator.validateWarehouseNotOnlyWarehouse(warehouseId);
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes specific warehouse.
|
||||
* @param {number} warehouseId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public deleteWarehouse = async (warehouseId: number): Promise<void> => {
|
||||
// Retrieves the old warehouse or throw not found service error.
|
||||
const oldWarehouse = await this.warehouseModel()
|
||||
.query()
|
||||
.findById(warehouseId)
|
||||
.throwIfNotFound();
|
||||
// .queryAndThrowIfHasRelations({
|
||||
// type: ERRORS.WAREHOUSE_HAS_ASSOCIATED_TRANSACTIONS,
|
||||
// });
|
||||
|
||||
// Validates the given warehouse before deleting.
|
||||
await this.authorize(warehouseId);
|
||||
|
||||
// Creates a new warehouse under unit-of-work.
|
||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||
const eventPayload = {
|
||||
warehouseId,
|
||||
oldWarehouse,
|
||||
trx,
|
||||
} as IWarehouseDeletePayload | IWarehouseDeletedPayload;
|
||||
|
||||
// Triggers `onWarehouseCreate`.
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.warehouse.onDelete,
|
||||
eventPayload,
|
||||
);
|
||||
// Deletes the given warehouse from the storage.
|
||||
await this.warehouseModel().query().findById(warehouseId).delete();
|
||||
|
||||
// Triggers `onWarehouseCreated`.
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.warehouse.onDeleted,
|
||||
eventPayload as IWarehouseDeletedPayload,
|
||||
);
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import { IEditWarehouseDTO, IWarehouse } from '../Warehouse.types';
|
||||
import { WarehouseValidator } from './WarehouseValidator.service';
|
||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { Warehouse } from '../models/Warehouse.model';
|
||||
import { events } from '@/common/events/events';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { EditWarehouseDto } from '../dtos/Warehouse.dto';
|
||||
|
||||
@Injectable()
|
||||
export class EditWarehouse {
|
||||
/**
|
||||
* @param {UnitOfWork} uow - Unit of work.
|
||||
* @param {EventEmitter2} eventPublisher - Event emitter.
|
||||
* @param {WarehouseValidator} validator - Warehouse command validator.
|
||||
* @param {typeof Warehouse} warehouseModel - Warehouse model.
|
||||
*/
|
||||
constructor(
|
||||
private readonly uow: UnitOfWork,
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
private readonly validator: WarehouseValidator,
|
||||
|
||||
@Inject(Warehouse.name)
|
||||
private readonly warehouseModel: TenantModelProxy<typeof Warehouse>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Authorize the warehouse before deleting.
|
||||
*/
|
||||
public authorize = async (
|
||||
warehouseDTO: EditWarehouseDto,
|
||||
warehouseId: number,
|
||||
) => {
|
||||
if (warehouseDTO.code) {
|
||||
await this.validator.validateWarehouseCodeUnique(
|
||||
warehouseDTO.code,
|
||||
warehouseId,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Edits a new warehouse on the system.
|
||||
* @param {ICreateWarehouseDTO} warehouseDTO
|
||||
* @returns {Promise<IWarehouse>}
|
||||
*/
|
||||
public editWarehouse = async (
|
||||
warehouseId: number,
|
||||
warehouseDTO: EditWarehouseDto,
|
||||
): Promise<Warehouse> => {
|
||||
// Authorize the warehouse DTO before editing.
|
||||
await this.authorize(warehouseDTO, warehouseId);
|
||||
|
||||
// Edits warehouse under unit-of-work.
|
||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||
// Triggers `onWarehouseEdit` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouse.onEdit, {
|
||||
warehouseId,
|
||||
warehouseDTO,
|
||||
trx,
|
||||
});
|
||||
// Updates the given branch on the storage.
|
||||
const warehouse = await this.warehouseModel()
|
||||
.query()
|
||||
.patchAndFetchById(warehouseId, {
|
||||
...warehouseDTO,
|
||||
});
|
||||
|
||||
// Triggers `onWarehouseEdited` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouse.onEdited, {
|
||||
warehouse,
|
||||
warehouseDTO,
|
||||
trx,
|
||||
});
|
||||
|
||||
return warehouse;
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import {
|
||||
IWarehouseMarkAsPrimaryPayload,
|
||||
IWarehouseMarkedAsPrimaryPayload,
|
||||
} from '../Warehouse.types';
|
||||
import { Warehouse } from '../models/Warehouse.model';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { events } from '@/common/events/events';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class WarehouseMarkPrimary {
|
||||
constructor(
|
||||
@Inject(Warehouse.name)
|
||||
private readonly warehouseModel: TenantModelProxy<typeof Warehouse>,
|
||||
|
||||
private readonly uow: UnitOfWork,
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Marks the given warehouse as primary.
|
||||
* @param {number} warehouseId
|
||||
* @returns {Promise<IWarehouse>}
|
||||
*/
|
||||
public async markAsPrimary(warehouseId: number) {
|
||||
const oldWarehouse = await this.warehouseModel()
|
||||
.query()
|
||||
.findById(warehouseId)
|
||||
.throwIfNotFound();
|
||||
|
||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||
await this.eventPublisher.emitAsync(events.warehouse.onMarkPrimary, {
|
||||
oldWarehouse,
|
||||
trx,
|
||||
} as IWarehouseMarkAsPrimaryPayload);
|
||||
|
||||
await this.warehouseModel().query(trx).update({ primary: false });
|
||||
|
||||
const markedWarehouse = await this.warehouseModel()
|
||||
.query(trx)
|
||||
.patchAndFetchById(warehouseId, { primary: true });
|
||||
|
||||
await this.eventPublisher.emitAsync(events.warehouse.onMarkedPrimary, {
|
||||
oldWarehouse,
|
||||
markedWarehouse,
|
||||
trx,
|
||||
} as IWarehouseMarkedAsPrimaryPayload);
|
||||
|
||||
return markedWarehouse;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||
import { Inject } from '@nestjs/common';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ERRORS } from '../contants';
|
||||
import { Warehouse } from '../models/Warehouse.model';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class WarehouseValidator {
|
||||
constructor(
|
||||
@Inject(Warehouse.name)
|
||||
private readonly warehouseModel: TenantModelProxy<typeof Warehouse>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validates the warehouse not only warehouse.
|
||||
* @param {number} warehouseId
|
||||
*/
|
||||
public validateWarehouseNotOnlyWarehouse = async (warehouseId: number) => {
|
||||
const warehouses = await this.warehouseModel()
|
||||
.query()
|
||||
.whereNot('id', warehouseId);
|
||||
|
||||
if (warehouses.length === 0) {
|
||||
throw new ServiceError(ERRORS.COULD_NOT_DELETE_ONLY_WAERHOUSE);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validates the warehouse code uniqueness.
|
||||
* @param {string} code
|
||||
* @param {number} exceptWarehouseId
|
||||
*/
|
||||
public validateWarehouseCodeUnique = async (
|
||||
code: string,
|
||||
exceptWarehouseId?: number,
|
||||
) => {
|
||||
const warehouse = await this.warehouseModel()
|
||||
.query()
|
||||
.onBuild((query) => {
|
||||
query.select(['id']);
|
||||
query.where('code', code);
|
||||
|
||||
if (exceptWarehouseId) {
|
||||
query.whereNot('id', exceptWarehouseId);
|
||||
}
|
||||
})
|
||||
.first();
|
||||
|
||||
if (warehouse) {
|
||||
throw new ServiceError(ERRORS.WAREHOUSE_CODE_NOT_UNIQUE);
|
||||
}
|
||||
};
|
||||
}
|
||||
7
packages/server/src/modules/Warehouses/contants.ts
Normal file
7
packages/server/src/modules/Warehouses/contants.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export const ERRORS = {
|
||||
WAREHOUSE_NOT_FOUND: 'WAREHOUSE_NOT_FOUND',
|
||||
MUTLI_WAREHOUSES_ALREADY_ACTIVATED: 'MUTLI_WAREHOUSES_ALREADY_ACTIVATED',
|
||||
COULD_NOT_DELETE_ONLY_WAERHOUSE: 'COULD_NOT_DELETE_ONLY_WAERHOUSE',
|
||||
WAREHOUSE_CODE_NOT_UNIQUE: 'WAREHOUSE_CODE_NOT_UNIQUE',
|
||||
WAREHOUSE_HAS_ASSOCIATED_TRANSACTIONS: 'WAREHOUSE_HAS_ASSOCIATED_TRANSACTIONS'
|
||||
};
|
||||
55
packages/server/src/modules/Warehouses/dtos/Warehouse.dto.ts
Normal file
55
packages/server/src/modules/Warehouses/dtos/Warehouse.dto.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
import { IsBoolean, IsEmail, IsOptional, IsUrl } from "class-validator";
|
||||
import { IsNotEmpty } from "class-validator";
|
||||
import { IsString } from "class-validator";
|
||||
|
||||
|
||||
export class CommandWarehouseDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({ description: 'The name of the warehouse' })
|
||||
name: string;
|
||||
|
||||
@IsBoolean()
|
||||
@IsOptional()
|
||||
@ApiProperty({ description: 'Whether the warehouse is primary' })
|
||||
primary?: boolean;
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@ApiProperty({ description: 'The code of the warehouse' })
|
||||
code?: string;
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@ApiProperty({ description: 'The address of the warehouse' })
|
||||
address?: string;
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@ApiProperty({ description: 'The city of the warehouse' })
|
||||
city?: string;
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@ApiProperty({ description: 'The country of the warehouse' })
|
||||
country?: string;
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@ApiProperty({ description: 'The phone number of the warehouse' })
|
||||
phoneNumber?: string;
|
||||
|
||||
@IsEmail()
|
||||
@IsOptional()
|
||||
@ApiProperty({ description: 'The email of the warehouse' })
|
||||
email?: string;
|
||||
|
||||
@IsUrl()
|
||||
@IsOptional()
|
||||
@ApiProperty({ description: 'The website of the warehouse' })
|
||||
website?: string;
|
||||
}
|
||||
|
||||
export class CreateWarehouseDto extends CommandWarehouseDto {}
|
||||
export class EditWarehouseDto extends CommandWarehouseDto {}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { BaseModel } from '@/models/Model';
|
||||
import { Model } from 'objection';
|
||||
|
||||
export class ItemWarehouseQuantity extends BaseModel{
|
||||
/**
|
||||
* Table name.
|
||||
*/
|
||||
static get tableName() {
|
||||
return 'items_warehouses_quantity';
|
||||
}
|
||||
|
||||
/**
|
||||
* Relation mappings.
|
||||
*/
|
||||
static get relationMappings() {
|
||||
const { Item } = require('../../Items/models/Item');
|
||||
const { Warehouse } = require('./Warehouse.model');
|
||||
|
||||
return {
|
||||
item: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: Item,
|
||||
join: {
|
||||
from: 'items_warehouses_quantity.itemId',
|
||||
to: 'items.id',
|
||||
},
|
||||
},
|
||||
warehouse: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: Warehouse,
|
||||
join: {
|
||||
from: 'items_warehouses_quantity.warehouseId',
|
||||
to: 'warehouses.id',
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
172
packages/server/src/modules/Warehouses/models/Warehouse.model.ts
Normal file
172
packages/server/src/modules/Warehouses/models/Warehouse.model.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
// import { Model } from 'objection';
|
||||
import { BaseModel } from '@/models/Model';
|
||||
import { Item } from '@/modules/Items/models/Item';
|
||||
|
||||
export class Warehouse extends BaseModel {
|
||||
name!: string;
|
||||
code!: string;
|
||||
city!: string;
|
||||
country!: string;
|
||||
address!: string;
|
||||
primary!: boolean;
|
||||
|
||||
items!: Item[];
|
||||
|
||||
/**
|
||||
* Table name.
|
||||
*/
|
||||
static get tableName() {
|
||||
return 'warehouses';
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamps columns.
|
||||
*/
|
||||
get timestamps() {
|
||||
return ['created_at', 'updated_at'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Model modifiers.
|
||||
*/
|
||||
static get modifiers() {
|
||||
return {
|
||||
/**
|
||||
* Filters accounts by the given ids.
|
||||
* @param {Query} query
|
||||
* @param {number[]} accountsIds
|
||||
*/
|
||||
isPrimary(query) {
|
||||
query.where('primary', true);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Relationship mapping.
|
||||
*/
|
||||
// static get relationMappings() {
|
||||
// const SaleInvoice = require('models/SaleInvoice');
|
||||
// const SaleEstimate = require('models/SaleEstimate');
|
||||
// const SaleReceipt = require('models/SaleReceipt');
|
||||
// const Bill = require('models/Bill');
|
||||
// const VendorCredit = require('models/VendorCredit');
|
||||
// const CreditNote = require('models/CreditNote');
|
||||
// const InventoryTransaction = require('models/InventoryTransaction');
|
||||
// const WarehouseTransfer = require('models/WarehouseTransfer');
|
||||
// const InventoryAdjustment = require('models/InventoryAdjustment');
|
||||
|
||||
// return {
|
||||
// /**
|
||||
// * Warehouse may belongs to associated sale invoices.
|
||||
// */
|
||||
// invoices: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: SaleInvoice.default,
|
||||
// join: {
|
||||
// from: 'warehouses.id',
|
||||
// to: 'sales_invoices.warehouseId',
|
||||
// },
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * Warehouse may belongs to associated sale estimates.
|
||||
// */
|
||||
// estimates: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: SaleEstimate.default,
|
||||
// join: {
|
||||
// from: 'warehouses.id',
|
||||
// to: 'sales_estimates.warehouseId',
|
||||
// },
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * Warehouse may belongs to associated sale receipts.
|
||||
// */
|
||||
// receipts: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: SaleReceipt.default,
|
||||
// join: {
|
||||
// from: 'warehouses.id',
|
||||
// to: 'sales_receipts.warehouseId',
|
||||
// },
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * Warehouse may belongs to associated bills.
|
||||
// */
|
||||
// bills: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: Bill.default,
|
||||
// join: {
|
||||
// from: 'warehouses.id',
|
||||
// to: 'bills.warehouseId',
|
||||
// },
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * Warehouse may belongs to associated credit notes.
|
||||
// */
|
||||
// creditNotes: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: CreditNote.default,
|
||||
// join: {
|
||||
// from: 'warehouses.id',
|
||||
// to: 'credit_notes.warehouseId',
|
||||
// },
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * Warehouse may belongs to associated to vendor credits.
|
||||
// */
|
||||
// vendorCredit: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: VendorCredit.default,
|
||||
// join: {
|
||||
// from: 'warehouses.id',
|
||||
// to: 'vendor_credits.warehouseId',
|
||||
// },
|
||||
// },
|
||||
|
||||
// /**
|
||||
// * Warehouse may belongs to associated to inventory transactions.
|
||||
// */
|
||||
// inventoryTransactions: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: InventoryTransaction.default,
|
||||
// join: {
|
||||
// from: 'warehouses.id',
|
||||
// to: 'inventory_transactions.warehouseId',
|
||||
// },
|
||||
// },
|
||||
|
||||
// warehouseTransferTo: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: WarehouseTransfer.default,
|
||||
// join: {
|
||||
// from: 'warehouses.id',
|
||||
// to: 'warehouses_transfers.toWarehouseId',
|
||||
// },
|
||||
// },
|
||||
|
||||
// warehouseTransferFrom: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: WarehouseTransfer.default,
|
||||
// join: {
|
||||
// from: 'warehouses.id',
|
||||
// to: 'warehouses_transfers.fromWarehouseId',
|
||||
// },
|
||||
// },
|
||||
|
||||
// inventoryAdjustment: {
|
||||
// relation: Model.HasManyRelation,
|
||||
// modelClass: InventoryAdjustment.default,
|
||||
// join: {
|
||||
// from: 'warehouses.id',
|
||||
// to: 'inventory_adjustments.warehouseId',
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Warehouse } from '../models/Warehouse.model';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class GetWarehouse {
|
||||
constructor(
|
||||
@Inject(Warehouse.name)
|
||||
private readonly warehouseModel: TenantModelProxy<typeof Warehouse>,
|
||||
) {}
|
||||
/**
|
||||
* Retrieves warehouse details.
|
||||
* @param {number} warehouseId
|
||||
* @returns {Promise<IWarehouse>}
|
||||
*/
|
||||
public getWarehouse = async (warehouseId: number) => {
|
||||
const warehouse = await this.warehouseModel()
|
||||
.query()
|
||||
.findById(warehouseId)
|
||||
.throwIfNotFound();
|
||||
|
||||
return warehouse;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Warehouse } from '../models/Warehouse.model';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class GetWarehouses {
|
||||
constructor(
|
||||
@Inject(Warehouse.name)
|
||||
private readonly warehouseModel: TenantModelProxy<typeof Warehouse>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieves warehouses list.
|
||||
* @returns
|
||||
*/
|
||||
public getWarehouses = async () => {
|
||||
const warehouses = await this.warehouseModel()
|
||||
.query()
|
||||
.orderBy('name', 'DESC');
|
||||
|
||||
return warehouses;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { BillActivateWarehouses } from '../../Activate/BillWarehousesActivate';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { events } from '@/common/events/events';
|
||||
import { IWarehousesActivatedPayload } from '../../Warehouse.types';
|
||||
|
||||
@Injectable()
|
||||
export class BillsActivateWarehousesSubscriber {
|
||||
constructor(
|
||||
private readonly billsActivateWarehouses: BillActivateWarehouses,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all inventory transactions with the primary warehouse once
|
||||
* multi-warehouses feature is activated.
|
||||
* @param {IWarehousesActivatedPayload}
|
||||
*/
|
||||
@OnEvent(events.warehouse.onActivated)
|
||||
async updateBillsWithWarehouseOnActivated ({
|
||||
primaryWarehouse,
|
||||
}: IWarehousesActivatedPayload) {
|
||||
await this.billsActivateWarehouses.updateBillsWithWarehouse(
|
||||
primaryWarehouse
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { CreditNotesActivateWarehouses } from '../../Activate/CreditNoteWarehousesActivate';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { IWarehousesActivatedPayload } from '../../Warehouse.types';
|
||||
import { events } from '@/common/events/events';
|
||||
|
||||
@Injectable()
|
||||
export class CreditsActivateWarehousesSubscriber {
|
||||
constructor(
|
||||
private readonly creditsActivateWarehouses: CreditNotesActivateWarehouses,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all inventory transactions with the primary warehouse once
|
||||
* multi-warehouses feature is activated.
|
||||
* @param {IWarehousesActivatedPayload}
|
||||
*/
|
||||
@OnEvent(events.warehouse.onActivated)
|
||||
async updateInvoicesWithWarehouseOnActivated({
|
||||
primaryWarehouse,
|
||||
}: IWarehousesActivatedPayload) {
|
||||
await this.creditsActivateWarehouses.updateCreditsWithWarehouse(
|
||||
primaryWarehouse,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { EstimatesActivateWarehouses } from '../../Activate/EstimateWarehousesActivate';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { IWarehousesActivatedPayload } from '../../Warehouse.types';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class EstimatesActivateWarehousesSubscriber {
|
||||
constructor(
|
||||
private readonly estimatesActivateWarehouses: EstimatesActivateWarehouses,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all inventory transactions with the primary warehouse once
|
||||
* multi-warehouses feature is activated.
|
||||
* @param {IWarehousesActivatedPayload}
|
||||
*/
|
||||
@OnEvent(events.warehouse.onActivated)
|
||||
async updateEstimatessWithWarehouseOnActivated({
|
||||
primaryWarehouse,
|
||||
}: IWarehousesActivatedPayload) {
|
||||
await this.estimatesActivateWarehouses.updateEstimatesWithWarehouse(
|
||||
primaryWarehouse,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { InventoryActivateWarehouses } from '../../Activate/InventoryTransactionsWarehousesActivate';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { events } from '@/common/events/events';
|
||||
import { IWarehousesActivatedPayload } from '../../Warehouse.types';
|
||||
|
||||
@Injectable()
|
||||
export class InventoryActivateWarehousesSubscriber {
|
||||
constructor(
|
||||
private readonly inventoryActivateWarehouses: InventoryActivateWarehouses,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all inventory transactions with the primary warehouse once
|
||||
* multi-warehouses feature is activated.
|
||||
* @param {IWarehousesActivatedPayload}
|
||||
*/
|
||||
@OnEvent(events.warehouse.onActivated)
|
||||
async updateInventoryTransactionsWithWarehouseOnActivated({
|
||||
primaryWarehouse,
|
||||
}: IWarehousesActivatedPayload) {
|
||||
await this.inventoryActivateWarehouses.updateInventoryTransactionsWithWarehouse(
|
||||
primaryWarehouse,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InvoicesActivateWarehouses } from '../../Activate/InvoiceWarehousesActivate';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { IWarehousesActivatedPayload } from '../../Warehouse.types';
|
||||
import { events } from '@/common/events/events';
|
||||
|
||||
@Injectable()
|
||||
export class InvoicesActivateWarehousesSubscriber {
|
||||
constructor(
|
||||
private readonly invoicesActivateWarehouses: InvoicesActivateWarehouses,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all inventory transactions with the primary warehouse once
|
||||
* multi-warehouses feature is activated.
|
||||
* @param {IWarehousesActivatedPayload}
|
||||
*/
|
||||
@OnEvent(events.warehouse.onActivated)
|
||||
async updateInvoicesWithWarehouseOnActivated({
|
||||
primaryWarehouse,
|
||||
}: IWarehousesActivatedPayload) {
|
||||
await this.invoicesActivateWarehouses.updateInvoicesWithWarehouse(
|
||||
primaryWarehouse,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ReceiptActivateWarehouses } from '../../Activate/ReceiptWarehousesActivate';
|
||||
import { events } from '@/common/events/events';
|
||||
import { IWarehousesActivatedPayload } from '../../Warehouse.types';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class ReceiptsActivateWarehousesSubscriber {
|
||||
constructor(
|
||||
private readonly receiptsActivateWarehouses: ReceiptActivateWarehouses,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all receipts transactions with the primary warehouse once
|
||||
* multi-warehouses feature is activated.
|
||||
* @param {IWarehousesActivatedPayload}
|
||||
*/
|
||||
@OnEvent(events.warehouse.onActivated)
|
||||
async updateInventoryTransactionsWithWarehouseOnActivated({
|
||||
primaryWarehouse,
|
||||
}: IWarehousesActivatedPayload) {
|
||||
await this.receiptsActivateWarehouses.updateReceiptsWithWarehouse(
|
||||
primaryWarehouse
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { VendorCreditActivateWarehouses } from '../../Activate/VendorCreditWarehousesActivate';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { IWarehousesActivatedPayload } from '../../Warehouse.types';
|
||||
import { events } from '@/common/events/events';
|
||||
|
||||
@Injectable()
|
||||
export class VendorCreditsActivateWarehousesSubscriber {
|
||||
constructor(
|
||||
private readonly creditsActivateWarehouses: VendorCreditActivateWarehouses,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Updates all inventory transactions with the primary warehouse once
|
||||
* multi-warehouses feature is activated.
|
||||
* @param {IWarehousesActivatedPayload}
|
||||
*/
|
||||
@OnEvent(events.warehouse.onActivated)
|
||||
async updateCreditsWithWarehouseOnActivated({
|
||||
primaryWarehouse,
|
||||
}: IWarehousesActivatedPayload) {
|
||||
await this.creditsActivateWarehouses.updateCreditsWithWarehouse(
|
||||
primaryWarehouse,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { DeleteItemWarehousesQuantity } from '../commands/DeleteItemWarehousesQuantity';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { IItemEventDeletingPayload } from '@/interfaces/Item';
|
||||
|
||||
@Injectable()
|
||||
export class DeleteItemWarehousesQuantitySubscriber {
|
||||
constructor(
|
||||
private readonly deleteItemWarehousesQuantity: DeleteItemWarehousesQuantity,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Deletes the given item warehouses quantities once the item deleting.
|
||||
* @param {IItemEventDeletingPayload} payload -
|
||||
*/
|
||||
@OnEvent(events.item.onDeleting)
|
||||
async deleteItemWarehouseQuantitiesOnItemDelete({
|
||||
oldItem,
|
||||
trx,
|
||||
}: IItemEventDeletingPayload) {
|
||||
await this.deleteItemWarehousesQuantity.deleteItemWarehousesQuantity(
|
||||
oldItem.id,
|
||||
trx,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { WarehousesDTOValidators } from '../../../Integrations/WarehousesDTOValidators';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { IInventoryAdjustmentCreatingPayload } from '@/modules/InventoryAdjutments/types/InventoryAdjustments.types';
|
||||
import { events } from '@/common/events/events';
|
||||
|
||||
@Injectable()
|
||||
export class InventoryAdjustmentWarehouseValidatorSubscriber {
|
||||
constructor(
|
||||
private readonly warehouseDTOValidator: WarehousesDTOValidators,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate warehouse existance of sale invoice once creating.
|
||||
* @param {IBillCreatingPayload}
|
||||
*/
|
||||
@OnEvent(events.inventoryAdjustment.onQuickCreating)
|
||||
async validateAdjustmentWarehouseExistanceOnCreating({
|
||||
quickAdjustmentDTO,
|
||||
}: IInventoryAdjustmentCreatingPayload) {
|
||||
await this.warehouseDTOValidator.validateDTOWarehouseWhenActive(
|
||||
quickAdjustmentDTO,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { WarehousesDTOValidators } from '../../../Integrations/WarehousesDTOValidators';
|
||||
import { IBillEditingPayload } from '@/modules/Bills/Bills.types';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { IBillCreatingPayload } from '@/modules/Bills/Bills.types';
|
||||
|
||||
@Injectable()
|
||||
export class BillWarehousesValidateSubscriber {
|
||||
constructor(
|
||||
private readonly warehouseDTOValidator: WarehousesDTOValidators,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate warehouse existance of sale invoice once creating.
|
||||
* @param {IBillCreatingPayload}
|
||||
*/
|
||||
@OnEvent(events.bill.onCreating)
|
||||
async validateBillWarehouseExistanceOnCreating({
|
||||
billDTO,
|
||||
}: IBillCreatingPayload) {
|
||||
await this.warehouseDTOValidator.validateDTOWarehouseWhenActive(billDTO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate warehouse existance of sale invoice once editing.
|
||||
* @param {IBillEditingPayload}
|
||||
*/
|
||||
|
||||
@OnEvent(events.bill.onEditing)
|
||||
async validateSaleEstimateWarehouseExistanceOnEditing({
|
||||
billDTO,
|
||||
}: IBillEditingPayload) {
|
||||
await this.warehouseDTOValidator.validateDTOWarehouseWhenActive(billDTO);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { WarehousesDTOValidators } from '../../../Integrations/WarehousesDTOValidators';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { IVendorCreditEditingPayload } from '@/modules/VendorCredit/types/VendorCredit.types';
|
||||
import { events } from '@/common/events/events';
|
||||
import { IVendorCreditCreatingPayload } from '@/modules/VendorCredit/types/VendorCredit.types';
|
||||
|
||||
@Injectable()
|
||||
export class VendorCreditWarehousesValidateSubscriber {
|
||||
constructor(
|
||||
private readonly warehouseDTOValidator: WarehousesDTOValidators,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate warehouse existance of sale invoice once creating.
|
||||
* @param {IVendorCreditCreatingPayload}
|
||||
*/
|
||||
@OnEvent(events.vendorCredit.onCreating)
|
||||
async validateVendorCreditWarehouseExistanceOnCreating({
|
||||
vendorCreditCreateDTO,
|
||||
}: IVendorCreditCreatingPayload) {
|
||||
await this.warehouseDTOValidator.validateDTOWarehouseWhenActive(
|
||||
vendorCreditCreateDTO,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate warehouse existance of sale invoice once editing.
|
||||
* @param {IVendorCreditEditingPayload}
|
||||
*/
|
||||
@OnEvent(events.vendorCredit.onEditing)
|
||||
async validateSaleEstimateWarehouseExistanceOnEditing({
|
||||
vendorCreditDTO,
|
||||
}: IVendorCreditEditingPayload) {
|
||||
await this.warehouseDTOValidator.validateDTOWarehouseWhenActive(
|
||||
vendorCreditDTO,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { WarehousesDTOValidators } from '../../../Integrations/WarehousesDTOValidators';
|
||||
import {
|
||||
ICreditNoteEditingPayload,
|
||||
ICreditNoteCreatingPayload,
|
||||
} from '@/modules/CreditNotes/types/CreditNotes.types';
|
||||
import { events } from '@/common/events/events';
|
||||
|
||||
@Injectable()
|
||||
export class CreditNoteWarehousesValidateSubscriber {
|
||||
constructor(
|
||||
private readonly warehouseDTOValidator: WarehousesDTOValidators,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate warehouse existance of sale invoice once creating.
|
||||
* @param {ICreditNoteCreatingPayload}
|
||||
*/
|
||||
@OnEvent(events.creditNote.onCreating)
|
||||
async validateCreditNoteWarehouseExistanceOnCreating({
|
||||
creditNoteDTO,
|
||||
}: ICreditNoteCreatingPayload) {
|
||||
await this.warehouseDTOValidator.validateDTOWarehouseWhenActive(
|
||||
creditNoteDTO,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate warehouse existance of sale invoice once editing.
|
||||
* @param {ICreditNoteEditingPayload}
|
||||
*/
|
||||
@OnEvent(events.creditNote.onEditing)
|
||||
async validateCreditNoteWarehouseExistanceOnEditing({
|
||||
creditNoteEditDTO,
|
||||
}: ICreditNoteEditingPayload) {
|
||||
await this.warehouseDTOValidator.validateDTOWarehouseWhenActive(
|
||||
creditNoteEditDTO,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { WarehousesDTOValidators } from '../../../Integrations/WarehousesDTOValidators';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { events } from '@/common/events/events';
|
||||
import { ISaleEstimateEditingPayload } from '@/modules/SaleEstimates/types/SaleEstimates.types';
|
||||
import { ISaleEstimateCreatingPayload } from '@/modules/SaleEstimates/types/SaleEstimates.types';
|
||||
|
||||
@Injectable()
|
||||
export class SaleEstimateWarehousesValidateSubscriber {
|
||||
constructor(
|
||||
private readonly warehouseDTOValidator: WarehousesDTOValidators,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate warehouse existance of sale invoice once creating.
|
||||
* @param {ISaleEstimateCreatingPayload}
|
||||
*/
|
||||
@OnEvent(events.saleEstimate.onCreating)
|
||||
async validateSaleEstimateWarehouseExistanceOnCreating({
|
||||
estimateDTO,
|
||||
}: ISaleEstimateCreatingPayload) {
|
||||
await this.warehouseDTOValidator.validateDTOWarehouseWhenActive(
|
||||
estimateDTO,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate warehouse existance of sale invoice once editing.
|
||||
* @param {ISaleEstimateEditingPayload}
|
||||
*/
|
||||
@OnEvent(events.saleEstimate.onEditing)
|
||||
async validateSaleEstimateWarehouseExistanceOnEditing({
|
||||
estimateDTO,
|
||||
}: ISaleEstimateEditingPayload) {
|
||||
await this.warehouseDTOValidator.validateDTOWarehouseWhenActive(
|
||||
estimateDTO,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { WarehousesDTOValidators } from '../../../Integrations/WarehousesDTOValidators';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import {
|
||||
ISaleInvoiceCreatingPaylaod,
|
||||
ISaleInvoiceEditingPayload,
|
||||
} from '@/modules/SaleInvoices/SaleInvoice.types';
|
||||
import { events } from '@/common/events/events';
|
||||
|
||||
@Injectable()
|
||||
export class SaleInvoicesWarehousesValidateSubscriber {
|
||||
constructor(
|
||||
private readonly warehousesDTOValidator: WarehousesDTOValidators,
|
||||
) {}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Validate warehouse existance of sale invoice once creating.
|
||||
* @param {ISaleInvoiceCreatingPaylaod}
|
||||
*/
|
||||
@OnEvent(events.saleInvoice.onCreating)
|
||||
async validateSaleInvoiceWarehouseExistanceOnCreating({
|
||||
saleInvoiceDTO,
|
||||
}: ISaleInvoiceCreatingPaylaod) {
|
||||
await this.warehousesDTOValidator.validateDTOWarehouseWhenActive(
|
||||
saleInvoiceDTO,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate warehouse existance of sale invoice once editing.
|
||||
* @param {ISaleInvoiceEditingPayload}
|
||||
*/
|
||||
@OnEvent(events.saleInvoice.onEditing)
|
||||
async validateSaleInvoiceWarehouseExistanceOnEditing({
|
||||
saleInvoiceDTO,
|
||||
}: ISaleInvoiceEditingPayload) {
|
||||
await this.warehousesDTOValidator.validateDTOWarehouseWhenActive(
|
||||
saleInvoiceDTO,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import {
|
||||
ISaleReceiptCreatingPayload,
|
||||
ISaleReceiptEditingPayload,
|
||||
} from '@/modules/SaleReceipts/types/SaleReceipts.types';
|
||||
import { events } from '@/common/events/events';
|
||||
import { WarehousesDTOValidators } from '../../../Integrations/WarehousesDTOValidators';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class SaleReceiptWarehousesValidateSubscriber {
|
||||
constructor(
|
||||
private readonly warehousesDTOValidator: WarehousesDTOValidators,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate warehouse existance of sale invoice once creating.
|
||||
* @param {ISaleReceiptCreatingPayload}
|
||||
*/
|
||||
@OnEvent(events.saleReceipt.onCreating)
|
||||
async validateSaleReceiptWarehouseExistanceOnCreating({
|
||||
saleReceiptDTO,
|
||||
}: ISaleReceiptCreatingPayload) {
|
||||
await this.warehousesDTOValidator.validateDTOWarehouseWhenActive(
|
||||
saleReceiptDTO,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate warehouse existance of sale invoice once editing.
|
||||
* @param {ISaleReceiptEditingPayload}
|
||||
*/
|
||||
@OnEvent(events.saleReceipt.onEditing)
|
||||
async validateSaleReceiptWarehouseExistanceOnEditing({
|
||||
saleReceiptDTO,
|
||||
}: ISaleReceiptEditingPayload) {
|
||||
await this.warehousesDTOValidator.validateDTOWarehouseWhenActive(
|
||||
saleReceiptDTO,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user