refactor: branches and warehouses to nestjs

This commit is contained in:
Ahmed Bouhuolia
2024-12-21 00:10:09 +02:00
parent dc52f784b6
commit cb8fd68d46
126 changed files with 5419 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
// import { Service, Inject } from 'typedi';
// import { IWarehouse } from '@/interfaces';
// import HasTenancyService from '@/services/Tenancy/TenancyService';
// @Service()
// export class BillActivateWarehouses {
// @Inject()
// tenancy: HasTenancyService;
// /**
// * Updates all credit note transactions with the primary warehouse.
// * @param {number} tenantId
// * @param {number} primaryWarehouse
// * @returns {Promise<void>}
// */
// public updateBillsWithWarehouse = async (
// tenantId: number,
// primaryWarehouse: IWarehouse
// ): Promise<void> => {
// const { Bill, ItemEntry } = this.tenancy.models(tenantId);
// // Updates the sale estimates with primary warehouse.
// await Bill.query().update({ warehouseId: primaryWarehouse.id });
// // Update the sale estimates entries with primary warehouse.
// await ItemEntry.query().where('referenceType', 'Bill').update({
// warehouseId: primaryWarehouse.id,
// });
// };
// }

View File

@@ -0,0 +1,30 @@
// import { Service, Inject } from 'typedi';
// import { IWarehouse } from '@/interfaces';
// import HasTenancyService from '@/services/Tenancy/TenancyService';
// @Service()
// export class CreditNotesActivateWarehouses {
// @Inject()
// tenancy: HasTenancyService;
// /**
// * Updates all credit note transactions with the primary warehouse.
// * @param {number} tenantId
// * @param {number} primaryWarehouse
// * @returns {Promise<void>}
// */
// public updateCreditsWithWarehouse = async (
// tenantId: number,
// primaryWarehouse: IWarehouse
// ): Promise<void> => {
// const { CreditNote, ItemEntry } = this.tenancy.models(tenantId);
// // Updates the sale estimates with primary warehouse.
// await CreditNote.query().update({ warehouseId: primaryWarehouse.id });
// // Update the sale estimates entries with primary warehouse.
// await ItemEntry.query().where('referenceType', 'CreditNote').update({
// warehouseId: primaryWarehouse.id,
// });
// };
// }

View File

@@ -0,0 +1,30 @@
// import { Service, Inject } from 'typedi';
// import { IWarehouse } from '@/interfaces';
// import HasTenancyService from '@/services/Tenancy/TenancyService';
// @Service()
// export class EstimatesActivateWarehouses {
// @Inject()
// tenancy: HasTenancyService;
// /**
// * Updates all inventory transactions with the primary warehouse.
// * @param {number} tenantId
// * @param {number} primaryWarehouse
// * @returns {Promise<void>}
// */
// public updateEstimatesWithWarehouse = async (
// tenantId: number,
// primaryWarehouse: IWarehouse
// ): Promise<void> => {
// const { SaleEstimate, ItemEntry } = this.tenancy.models(tenantId);
// // Updates the sale estimates with primary warehouse.
// await SaleEstimate.query().update({ warehouseId: primaryWarehouse.id });
// // Update the sale estimates entries with primary warehouse.
// await ItemEntry.query().where('referenceType', 'SaleEstimate').update({
// warehouseId: primaryWarehouse.id,
// });
// };
// }

View File

@@ -0,0 +1,31 @@
// import { Service, Inject } from 'typedi';
// import { IWarehouse } from '@/interfaces';
// import HasTenancyService from '@/services/Tenancy/TenancyService';
// @Service()
// export class InventoryActivateWarehouses {
// @Inject()
// tenancy: HasTenancyService;
// /**
// * Updates all inventory transactions with the primary warehouse.
// * @param {number} tenantId
// * @param {number} primaryWarehouse
// * @returns {Promise<void>}
// */
// public updateInventoryTransactionsWithWarehouse = async (
// tenantId: number,
// primaryWarehouse: IWarehouse
// ): Promise<void> => {
// const { InventoryTransaction, InventoryCostLotTracker } =
// this.tenancy.models(tenantId);
// // Updates the inventory transactions with primary warehouse.
// await InventoryTransaction.query().update({
// warehouseId: primaryWarehouse.id,
// });
// await InventoryCostLotTracker.query().update({
// warehouseId: primaryWarehouse.id,
// });
// };
// }

View File

@@ -0,0 +1,30 @@
// import { Service, Inject } from 'typedi';
// import { IWarehouse } from '@/interfaces';
// import HasTenancyService from '@/services/Tenancy/TenancyService';
// @Service()
// export class InvoicesActivateWarehouses {
// @Inject()
// tenancy: HasTenancyService;
// /**
// * Updates all inventory transactions with the primary warehouse.
// * @param {number} tenantId
// * @param {number} primaryWarehouse
// * @returns {Promise<void>}
// */
// public updateInvoicesWithWarehouse = async (
// tenantId: number,
// primaryWarehouse: IWarehouse
// ): Promise<void> => {
// const { SaleInvoice, ItemEntry } = this.tenancy.models(tenantId);
// // Updates the sale invoices with primary warehouse.
// await SaleInvoice.query().update({ warehouseId: primaryWarehouse.id });
// // Update the sale invoices entries with primary warehouse.
// await ItemEntry.query().where('referenceType', 'SaleInvoice').update({
// warehouseId: primaryWarehouse.id,
// });
// };
// }

View File

@@ -0,0 +1,30 @@
// import { Service, Inject } from 'typedi';
// import { IWarehouse } from '@/interfaces';
// import HasTenancyService from '@/services/Tenancy/TenancyService';
// @Service()
// export class ReceiptActivateWarehouses {
// @Inject()
// tenancy: HasTenancyService;
// /**
// * Updates all sale receipts transactions with the primary warehouse.
// * @param {number} tenantId
// * @param {number} primaryWarehouse
// * @returns {Promise<void>}
// */
// public updateReceiptsWithWarehouse = async (
// tenantId: number,
// primaryWarehouse: IWarehouse
// ): Promise<void> => {
// const { SaleReceipt, ItemEntry } = this.tenancy.models(tenantId);
// // Updates the vendor credits transactions with primary warehouse.
// await SaleReceipt.query().update({ warehouseId: primaryWarehouse.id });
// // Update the sale invoices entries with primary warehouse.
// await ItemEntry.query().where('referenceType', 'SaleReceipt').update({
// warehouseId: primaryWarehouse.id,
// });
// };
// }

View File

@@ -0,0 +1,30 @@
// import { Service, Inject } from 'typedi';
// import { IWarehouse } from '@/interfaces';
// import HasTenancyService from '@/services/Tenancy/TenancyService';
// @Service()
// export class VendorCreditActivateWarehouses {
// @Inject()
// tenancy: HasTenancyService;
// /**
// * Updates all vendor credits transactions with the primary warehouse.
// * @param {number} tenantId
// * @param {number} primaryWarehouse
// * @returns {Promise<void>}
// */
// public updateCreditsWithWarehouse = async (
// tenantId: number,
// primaryWarehouse: IWarehouse
// ): Promise<void> => {
// const { VendorCredit, ItemEntry } = this.tenancy.models(tenantId);
// // Updates the vendor credits transactions with primary warehouse.
// await VendorCredit.query().update({ warehouseId: primaryWarehouse.id });
// // Update the sale invoices entries with primary warehouse.
// await ItemEntry.query().where('referenceType', 'VendorCredit').update({
// warehouseId: primaryWarehouse.id,
// });
// };
// }

View File

@@ -0,0 +1,58 @@
// import { Service, Inject } from 'typedi';
// import events from '@/subscribers/events';
// import { IWarehousesActivatedPayload } from '@/interfaces';
// import { UpdateInventoryTransactionsWithWarehouse } from './UpdateInventoryTransactionsWithWarehouse';
// import { CreateInitialWarehousesItemsQuantity } from './CreateInitialWarehousesitemsQuantity';
// @Service()
// export class ActivateWarehousesSubscriber {
// @Inject()
// private updateInventoryTransactionsWithWarehouse: UpdateInventoryTransactionsWithWarehouse;
// @Inject()
// private createInitialWarehousesItemsQuantity: CreateInitialWarehousesItemsQuantity;
// /**
// * Attaches events with handlers.
// */
// attach(bus) {
// bus.subscribe(
// events.warehouse.onActivated,
// this.updateInventoryTransactionsWithWarehouseOnActivating
// );
// bus.subscribe(
// events.warehouse.onActivated,
// this.createInitialWarehousesItemsQuantityOnActivating
// );
// return bus;
// }
// /**
// * Updates inventory transactiont to primary warehouse once
// * multi-warehouses activated.
// * @param {IWarehousesActivatedPayload}
// */
// private updateInventoryTransactionsWithWarehouseOnActivating = async ({
// tenantId,
// primaryWarehouse,
// }: IWarehousesActivatedPayload) => {
// await this.updateInventoryTransactionsWithWarehouse.run(
// tenantId,
// primaryWarehouse.id
// );
// };
// /**
// * Creates initial warehouses items quantity once the multi-warehouses activated.
// * @param {IWarehousesActivatedPayload}
// */
// private createInitialWarehousesItemsQuantityOnActivating = async ({
// tenantId,
// primaryWarehouse,
// }: IWarehousesActivatedPayload) => {
// await this.createInitialWarehousesItemsQuantity.run(
// tenantId,
// primaryWarehouse.id
// );
// };
// }

View 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);
// }
// }
// }

View File

@@ -0,0 +1,57 @@
// import { Service, Inject } from 'typedi';
// import { Knex } from 'knex';
// import { IItem, IItemWarehouseQuantityChange } from '@/interfaces';
// import { WarehousesItemsQuantitySync } from './Integrations/WarehousesItemsQuantitySync';
// import HasTenancyService from '@/services/Tenancy/TenancyService';
// @Service()
// export class CreateInitialWarehousesItemsQuantity {
// @Inject()
// private warehousesItemsQuantitySync: WarehousesItemsQuantitySync;
// @Inject()
// private tenancy: HasTenancyService;
// /**
// * Retrieves items warehouses quantity changes of the given inventory items.
// * @param {IItem[]} items
// * @param {IWarehouse} primaryWarehouse
// * @returns {IItemWarehouseQuantityChange[]}
// */
// private getWarehousesItemsChanges = (
// items: IItem[],
// primaryWarehouseId: number
// ): IItemWarehouseQuantityChange[] => {
// return items
// .filter((item: IItem) => item.quantityOnHand)
// .map((item: IItem) => ({
// itemId: item.id,
// warehouseId: primaryWarehouseId,
// amount: item.quantityOnHand,
// }));
// };
// /**
// * Creates initial warehouses items quantity.
// * @param {number} tenantId
// */
// public run = async (
// tenantId: number,
// primaryWarehouseId: number,
// trx?: Knex.Transaction
// ): Promise<void> => {
// const { Item } = this.tenancy.models(tenantId);
// const items = await Item.query(trx).where('type', 'Inventory');
// const warehousesChanges = this.getWarehousesItemsChanges(
// items,
// primaryWarehouseId
// );
// await this.warehousesItemsQuantitySync.mutateWarehousesItemsQuantity(
// tenantId,
// warehousesChanges,
// trx
// );
// };
// }

View File

@@ -0,0 +1,39 @@
// import {
// BillsActivateWarehousesSubscriber,
// CreditsActivateWarehousesSubscriber,
// InvoicesActivateWarehousesSubscriber,
// ReceiptsActivateWarehousesSubscriber,
// EstimatesActivateWarehousesSubscriber,
// InventoryActivateWarehousesSubscriber,
// VendorCreditsActivateWarehousesSubscriber,
// } from './Subscribers/Activate';
// import {
// BillWarehousesValidateSubscriber,
// CreditNoteWarehousesValidateSubscriber,
// SaleReceiptWarehousesValidateSubscriber,
// SaleEstimateWarehousesValidateSubscriber,
// SaleInvoicesWarehousesValidateSubscriber,
// VendorCreditWarehousesValidateSubscriber,
// InventoryAdjustmentWarehouseValidatorSubscriber,
// } from './Subscribers/Validators';
// import { DeleteItemWarehousesQuantitySubscriber } from './Subscribers/DeleteItemWarehousesQuantitySubscriber';
// export default () => [
// BillsActivateWarehousesSubscriber,
// CreditsActivateWarehousesSubscriber,
// InvoicesActivateWarehousesSubscriber,
// ReceiptsActivateWarehousesSubscriber,,
// EstimatesActivateWarehousesSubscriber,
// InventoryActivateWarehousesSubscriber,
// VendorCreditsActivateWarehousesSubscriber,
// BillWarehousesValidateSubscriber,
// CreditNoteWarehousesValidateSubscriber,
// SaleReceiptWarehousesValidateSubscriber,
// SaleEstimateWarehousesValidateSubscriber,
// SaleInvoicesWarehousesValidateSubscriber,
// VendorCreditWarehousesValidateSubscriber,
// InventoryAdjustmentWarehouseValidatorSubscriber,
// DeleteItemWarehousesQuantitySubscriber,
// ];

View File

@@ -0,0 +1,79 @@
// import { Inject, Service } from 'typedi';
// import { chain, difference } from 'lodash';
// import { ServiceError } from '@/exceptions';
// import { ERRORS } from './constants';
// import HasTenancyService from '@/services/Tenancy/TenancyService';
// @Service()
// export class ValidateWarehouseExistance {
// @Inject()
// tenancy: HasTenancyService;
// /**
// * 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} tenantId
// * @param {number} warehouseId
// */
// public validateWarehouseExistance = (
// tenantId: number,
// warehouseId: number
// ) => {
// const { Warehouse } = this.tenancy.models(tenantId);
// const warehouse = Warehouse.query().findById(warehouseId);
// if (!warehouse) {
// throw new ServiceError(ERRORS.WAREHOUSE_ID_NOT_FOUND);
// }
// };
// /**
// *
// * @param {number} tenantId
// * @param {{ warehouseId?: number }[]} entries
// */
// public validateItemEntriesWarehousesExistance = async (
// tenantId: number,
// entries: { warehouseId?: number }[]
// ) => {
// const { Warehouse } = this.tenancy.models(tenantId);
// const entriesWarehousesIds = chain(entries)
// .filter((e) => !!e.warehouseId)
// .map((e) => e.warehouseId)
// .uniq()
// .value();
// const warehouses = await Warehouse.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);
// }
// };
// }

View File

@@ -0,0 +1,38 @@
// import { Service, Inject } from 'typedi';
// import { omit } from 'lodash';
// import * as R from 'ramda';
// import { WarehousesSettings } from '../WarehousesSettings';
// @Service()
// export class WarehouseTransactionDTOTransform {
// @Inject()
// private warehousesSettings: WarehousesSettings;
// /**
// * Excludes DTO warehouse id when mutli-warehouses feature is inactive.
// * @param {number} tenantId
// * @returns {Promise<Omit<T, 'warehouseId'> | T>}
// */
// private excludeDTOWarehouseIdWhenInactive = <
// T extends { warehouseId?: number }
// >(
// tenantId: number,
// DTO: T
// ): Omit<T, 'warehouseId'> | T => {
// const isActive = this.warehousesSettings.isMultiWarehousesActive(tenantId);
// return !isActive ? omit(DTO, ['warehouseId']) : DTO;
// };
// /**
// *
// * @param {number} tenantId
// * @param {T} DTO -
// * @returns {Omit<T, 'warehouseId'> | T}
// */
// public transformDTO =
// <T extends { warehouseId?: number }>(tenantId: number) =>
// (DTO: T): Omit<T, 'warehouseId'> | T => {
// return this.excludeDTOWarehouseIdWhenInactive<T>(tenantId, DTO);
// };
// }

View File

@@ -0,0 +1,66 @@
// import { Service, Inject } from 'typedi';
// import { isEmpty } from 'lodash';
// import { ValidateWarehouseExistance } from './ValidateWarehouseExistance';
// import { WarehousesSettings } from '../WarehousesSettings';
// interface IWarehouseTransactionDTO {
// warehouseId?: number|null;
// entries?: { warehouseId?: number|null }[];
// }
// @Service()
// export class WarehousesDTOValidators {
// @Inject()
// private validateWarehouseExistanceService: ValidateWarehouseExistance;
// @Inject()
// private warehousesSettings: WarehousesSettings;
// /**
// * Validates the warehouse existance of sale invoice transaction.
// * @param {number} tenantId
// * @param {ISaleInvoiceCreateDTO | ISaleInvoiceEditDTO} saleInvoiceDTO
// */
// public validateDTOWarehouseExistance = async (
// tenantId: number,
// 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(
// tenantId,
// DTO.warehouseId
// );
// }
// // Validate the sale invoice entries warehouses existance on the storage.
// if (!isEmpty(DTO.entries)) {
// await this.validateWarehouseExistanceService.validateItemEntriesWarehousesExistance(
// tenantId,
// DTO.entries
// );
// }
// };
// /**
// * Validate the warehouse existance of
// * @param {number} tenantId
// * @param {IWarehouseTransactionDTO} saleInvoiceDTO
// * @returns
// */
// public validateDTOWarehouseWhenActive = async (
// tenantId: number,
// DTO: IWarehouseTransactionDTO
// ): Promise<void> => {
// const isActive = this.warehousesSettings.isMultiWarehousesActive(tenantId);
// // Can't continue if the multi-warehouses feature is inactive.
// if (!isActive) return;
// return this.validateDTOWarehouseExistance(tenantId, DTO);
// };
// }

View File

@@ -0,0 +1,117 @@
// import {
// IInventoryTransaction,
// IItemWarehouseQuantityChange,
// } from '@/interfaces';
// import { set, get, chain, toPairs } from 'lodash';
// 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: IInventoryTransaction[]
// ): WarehousesItemsQuantity => {
// const warehouseTransactions = inventoryTransactions.filter(
// (transaction) => transaction.warehouseId
// );
// const warehouseItemsQuantity = new WarehousesItemsQuantity();
// warehouseTransactions.forEach((transaction: IInventoryTransaction) => {
// const change =
// transaction.direction === 'IN'
// ? warehouseItemsQuantity.increment
// : warehouseItemsQuantity.decrement;
// change(transaction.warehouseId, transaction.itemId, transaction.quantity);
// });
// return warehouseItemsQuantity;
// };
// }

View File

@@ -0,0 +1,74 @@
// import events from '@/subscribers/events';
// import { Service, Inject } from 'typedi';
// import { WarehousesItemsQuantitySync } from './WarehousesItemsQuantitySync';
// import {
// IInventoryTransactionsCreatedPayload,
// IInventoryTransactionsDeletedPayload,
// } from '@/interfaces';
// import { WarehousesSettings } from '../WarehousesSettings';
// @Service()
// export class WarehousesItemsQuantitySyncSubscriber {
// @Inject()
// private warehousesItemsQuantitySync: WarehousesItemsQuantitySync;
// @Inject()
// private warehousesSettings: WarehousesSettings;
// /**
// * Attaches events with handlers.
// */
// public attach(bus) {
// bus.subscribe(
// events.inventory.onInventoryTransactionsCreated,
// this.syncWarehousesItemsQuantityOnInventoryTransCreated
// );
// bus.subscribe(
// events.inventory.onInventoryTransactionsDeleted,
// this.syncWarehousesItemsQuantityOnInventoryTransDeleted
// );
// return bus;
// }
// /**
// * Syncs warehouses items quantity once inventory transactions created.
// * @param {IInventoryTransactionsCreatedPayload}
// */
// private syncWarehousesItemsQuantityOnInventoryTransCreated = async ({
// tenantId,
// inventoryTransactions,
// trx,
// }: IInventoryTransactionsCreatedPayload) => {
// const isActive = this.warehousesSettings.isMultiWarehousesActive(tenantId);
// // Can't continue if the warehouses features is not active.
// if (!isActive) return;
// await this.warehousesItemsQuantitySync.mutateWarehousesItemsQuantityFromTransactions(
// tenantId,
// inventoryTransactions,
// trx
// );
// };
// /**
// * Syncs warehouses items quantity once inventory transactions deleted.
// * @param {IInventoryTransactionsDeletedPayload}
// */
// private syncWarehousesItemsQuantityOnInventoryTransDeleted = async ({
// tenantId,
// oldInventoryTransactions,
// trx,
// }: IInventoryTransactionsDeletedPayload) => {
// const isActive = this.warehousesSettings.isMultiWarehousesActive(tenantId);
// // Can't continue if the warehouses feature is not active yet.
// if (!isActive) return;
// await this.warehousesItemsQuantitySync.reverseWarehousesItemsQuantityFromTransactions(
// tenantId,
// oldInventoryTransactions,
// trx
// );
// };
// }

View File

@@ -0,0 +1,131 @@
// import { Knex } from 'knex';
// import { Service, Inject } from 'typedi';
// import { omit } from 'lodash';
// import {
// IInventoryTransaction,
// IItemWarehouseQuantityChange,
// } from '@/interfaces';
// import { WarehousesItemsQuantity } from './WarehousesItemsQuantity';
// import HasTenancyService from '@/services/Tenancy/TenancyService';
// @Service()
// export class WarehousesItemsQuantitySync {
// @Inject()
// tenancy: HasTenancyService;
// /**
// * Retrieves the reversed warehouses items quantity changes.
// * @param {IInventoryTransaction[]} inventoryTransactions
// * @returns {IItemWarehouseQuantityChange[]}
// */
// public getReverseWarehousesItemsQuantityChanges = (
// inventoryTransactions: IInventoryTransaction[]
// ): IItemWarehouseQuantityChange[] => {
// const warehouseItemsQuantity =
// WarehousesItemsQuantity.fromInventoryTransaction(inventoryTransactions);
// return warehouseItemsQuantity.reverse().toArray();
// };
// /**
// * Retrieves the warehouses items changes from the given inventory tranasctions.
// * @param {IInventoryTransaction[]} inventoryTransactions
// * @returns {IItemWarehouseQuantityChange[]}
// */
// public getWarehousesItemsQuantityChange = (
// inventoryTransactions: IInventoryTransaction[]
// ): IItemWarehouseQuantityChange[] => {
// const warehouseItemsQuantity =
// WarehousesItemsQuantity.fromInventoryTransaction(inventoryTransactions);
// return warehouseItemsQuantity.toArray();
// };
// /**
// * Mutates warehouses items quantity on hand on the storage.
// * @param {number} tenantId
// * @param {IItemWarehouseQuantityChange[]} warehousesItemsQuantity
// * @param {Knex.Transaction} trx
// */
// public mutateWarehousesItemsQuantity = async (
// tenantId: number,
// warehousesItemsQuantity: IItemWarehouseQuantityChange[],
// trx?: Knex.Transaction
// ): Promise<void> => {
// const mutationsOpers = warehousesItemsQuantity.map(
// (change: IItemWarehouseQuantityChange) =>
// this.mutateWarehouseItemQuantity(tenantId, change, trx)
// );
// await Promise.all(mutationsOpers);
// };
// /**
// * Mutates the warehouse item quantity.
// * @param {number} tenantId
// * @param {number} warehouseItemQuantity
// * @param {Knex.Transaction} trx
// */
// public mutateWarehouseItemQuantity = async (
// tenantId: number,
// warehouseItemQuantity: IItemWarehouseQuantityChange,
// trx: Knex.Transaction
// ): Promise<void> => {
// const { ItemWarehouseQuantity } = this.tenancy.models(tenantId);
// const itemWarehouseQuantity = await ItemWarehouseQuantity.query(trx)
// .where('itemId', warehouseItemQuantity.itemId)
// .where('warehouseId', warehouseItemQuantity.warehouseId)
// .first();
// if (itemWarehouseQuantity) {
// 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 (
// tenantId: number,
// inventoryTransactions: IInventoryTransaction[],
// trx?: Knex.Transaction
// ) => {
// const changes = this.getWarehousesItemsQuantityChange(
// inventoryTransactions
// );
// await this.mutateWarehousesItemsQuantity(tenantId, changes, trx);
// };
// /**
// * Reverses warehouses items quantity from inventory transactions.
// * @param {number} tenantId
// * @param {IInventoryTransaction[]} inventoryTransactions
// * @param {Knex.Transaction} trx
// */
// public reverseWarehousesItemsQuantityFromTransactions = async (
// tenantId: number,
// inventoryTransactions: IInventoryTransaction[],
// trx?: Knex.Transaction
// ) => {
// const changes = this.getReverseWarehousesItemsQuantityChanges(
// inventoryTransactions
// );
// await this.mutateWarehousesItemsQuantity(tenantId, changes, trx);
// };
// }

View File

@@ -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',
};

View File

@@ -0,0 +1,41 @@
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';
@Injectable()
export class GetItemWarehouses {
constructor(
@Inject(ItemWarehouseQuantity.name)
private readonly itemWarehouseQuantityModel: typeof ItemWarehouseQuantity,
@Inject(Item.name)
private readonly itemModel: 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(),
);
};
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,21 @@
// import HasTenancyService from '@/services/Tenancy/TenancyService';
// import { Service, Inject } from 'typedi';
// @Service()
// export class UpdateInventoryTransactionsWithWarehouse {
// @Inject()
// tenancy: HasTenancyService;
// /**
// * Updates all inventory transactions with primary warehouse.
// * @param {number} tenantId -
// * @param {number} warehouseId -
// */
// public run = async (tenantId: number, primaryWarehouseId: number) => {
// const { InventoryTransaction } = this.tenancy.models(tenantId);
// await InventoryTransaction.query().update({
// warehouseId: primaryWarehouseId,
// });
// };
// }

View File

@@ -0,0 +1,212 @@
import { Knex } from 'knex';
export interface IWarehouse {
id?: number;
}
export interface IWarehouseTransfer {
id?: number;
date: Date;
fromWarehouseId: number;
toWarehouseId: number;
reason?: string;
transactionNumber: string;
entries: IWarehouseTransferEntry[];
transferInitiatedAt?: Date;
transferDeliveredAt?: Date;
isInitiated?: boolean;
isTransferred?: boolean;
}
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 {
// tenantId: number;
warehouseDTO: ICreateWarehouseDTO;
trx: Knex.Transaction;
}
export interface IWarehouseCreatedPayload {
// tenantId: number;
warehouse: IWarehouse;
warehouseDTO: ICreateWarehouseDTO;
trx: Knex.Transaction;
}
export interface IWarehouseTransferCreate {
trx: Knex.Transaction;
warehouseTransferDTO: ICreateWarehouseTransferDTO;
tenantId: number;
}
export interface IWarehouseTransferCreated {
trx: Knex.Transaction;
warehouseTransfer: IWarehouseTransfer;
warehouseTransferDTO: ICreateWarehouseTransferDTO;
// tenantId: number;
}
export interface IWarehouseTransferEditPayload {
// tenantId: number;
editWarehouseDTO: IEditWarehouseTransferDTO;
oldWarehouseTransfer: IWarehouseTransfer;
trx: Knex.Transaction;
}
export interface IWarehouseTransferEditedPayload {
// tenantId: number;
editWarehouseDTO: IEditWarehouseTransferDTO;
oldWarehouseTransfer: IWarehouseTransfer;
warehouseTransfer: IWarehouseTransfer;
trx: Knex.Transaction;
}
export interface IWarehouseTransferDeletePayload {
// tenantId: number;
oldWarehouseTransfer: IWarehouseTransfer;
trx: Knex.Transaction;
}
export interface IWarehouseTransferDeletedPayload {
// tenantId: number;
warehouseTransfer: IWarehouseTransfer;
oldWarehouseTransfer: IWarehouseTransfer;
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: IWarehouse;
}
export interface IWarehouseMarkAsPrimaryPayload {
// tenantId: number;
oldWarehouse: IWarehouse;
trx: Knex.Transaction;
}
export interface IWarehouseMarkedAsPrimaryPayload {
// tenantId: number;
oldWarehouse: IWarehouse;
markedWarehouse: IWarehouse;
trx: Knex.Transaction;
}
export interface IWarehouseTransferInitiatePayload {
// tenantId: number;
oldWarehouseTransfer: IWarehouseTransfer;
trx: Knex.Transaction;
}
export interface IWarehouseTransferInitiatedPayload {
// tenantId: number;
warehouseTransfer: IWarehouseTransfer;
oldWarehouseTransfer: IWarehouseTransfer;
trx: Knex.Transaction;
}
export interface IWarehouseTransferTransferingPayload {
// tenantId: number;
oldWarehouseTransfer: IWarehouseTransfer;
trx: Knex.Transaction;
}
export interface IWarehouseTransferTransferredPayload {
// tenantId: number;
warehouseTransfer: IWarehouseTransfer;
oldWarehouseTransfer: IWarehouseTransfer;
trx: Knex.Transaction;
}

View File

@@ -0,0 +1,111 @@
import {
ICreateWarehouseDTO,
IEditWarehouseDTO,
IWarehouse,
} from './Warehouse.types';
import { ActivateWarehousesService } from './commands/ActivateWarehouses';
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';
@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: ICreateWarehouseDTO) => {
return this.createWarehouseService.createWarehouse(createWarehouseDTO);
};
/**
* Edits the given warehouse.
* @param {number} tenantId
* @param {number} warehouseId
* @param {IEditWarehouseDTO} editWarehouseDTO
* @returns {Promise<void>}
*/
public editWarehouse = (
warehouseId: number,
editWarehouseDTO: IEditWarehouseDTO,
) => {
return this.editWarehouseService.editWarehouse(
warehouseId,
editWarehouseDTO,
);
};
/**
* Deletes the given warehouse.
* @param {number} tenantId
* @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);
};
/**
*
* @param {number} tenantId
* @returns
*/
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 = (
tenantId: number,
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);
};
}

View File

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

View File

@@ -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 = 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,
});
});
}
}

View File

@@ -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,
});
};
}

View File

@@ -0,0 +1,73 @@
import { Inject, Injectable } from '@nestjs/common';
import { Knex } from 'knex';
import {
ICreateWarehouseDTO,
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';
@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: typeof Warehouse,
) {}
/**
* Authorize the warehouse before creating.
* @param {ICreateWarehouseDTO} warehouseDTO -
*/
public authorize = async (warehouseDTO: ICreateWarehouseDTO) => {
if (warehouseDTO.code) {
await this.validator.validateWarehouseCodeUnique(warehouseDTO.code);
}
};
/**
* Creates a new warehouse on the system.
* @param {ICreateWarehouseDTO} warehouseDTO
*/
public createWarehouse = async (
warehouseDTO: ICreateWarehouseDTO
): 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;
});
};
}

View File

@@ -0,0 +1,29 @@
import { Knex } from 'knex';
import { Inject, Injectable } from '@nestjs/common';
import { ItemWarehouseQuantity } from '../models/ItemWarehouseQuantity';
@Injectable()
export class DeleteItemWarehousesQuantity {
/**
* @param {typeof ItemWarehouseQuantity} itemWarehouseQuantityModel - Item warehouse quantity model.
*/
constructor(
@Inject(ItemWarehouseQuantity.name)
private readonly itemWarehouseQuantityModel: 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();
};
}

View File

@@ -0,0 +1,81 @@
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';
@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: 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,
);
});
};
}

View File

@@ -0,0 +1,79 @@
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';
@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: typeof Warehouse,
) {}
/**
* Authorize the warehouse before deleting.
*/
public authorize = async (
warehouseDTO: IEditWarehouseDTO,
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: IEditWarehouseDTO,
): Promise<IWarehouse> => {
// 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;
});
};
}

View File

@@ -0,0 +1,53 @@
import { 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';
@Injectable()
export class WarehouseMarkPrimary {
constructor(
private readonly warehouseModel: 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;
});
}
}

View File

@@ -0,0 +1,51 @@
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';
@Injectable()
export class WarehouseValidator {
constructor(
@Inject(Warehouse.name)
private readonly warehouseModel: 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);
}
};
}

View 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'
};

View File

@@ -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',
},
},
};
}
}

View File

@@ -0,0 +1,178 @@
// import { Model } from 'objection';
import { BaseModel } from '@/models/Model';
export class Warehouse extends BaseModel {
date!: Date;
fromWarehouseId!: number;
toWarehouseId!: number;
reason!: string;
transactionNumber!: string;
transferInitiatedAt!: Date;
transferDeliveredAt!: Date;
isInitiated!: boolean;
isTransferred!: boolean;
primary!: boolean;
/**
* 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',
// },
// },
// };
// }
}

View File

@@ -0,0 +1,23 @@
import { Inject, Injectable } from '@nestjs/common';
import { Warehouse } from '../models/Warehouse.model';
@Injectable()
export class GetWarehouse {
constructor(
@Inject(Warehouse.name)
private readonly warehouseModel: 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;
};
}

View File

@@ -0,0 +1,22 @@
import { Inject, Injectable } from '@nestjs/common';
import { Warehouse } from '../models/Warehouse.model';
@Injectable()
export class GetWarehouses {
constructor(
@Inject(Warehouse.name)
private readonly warehouseModel: typeof Warehouse,
) {}
/**
* Retrieves warehouses list.
* @returns
*/
public getWarehouses = async () => {
const warehouses = await this.warehouseModel
.query()
.orderBy('name', 'DESC');
return warehouses;
};
}

View File

@@ -0,0 +1,36 @@
// import { Service, Inject } from 'typedi';
// import { IWarehousesActivatedPayload } from '@/interfaces';
// import events from '@/subscribers/events';
// import { BillActivateWarehouses } from '../../Activate/BillWarehousesActivate';
// @Service()
// export class BillsActivateWarehousesSubscriber {
// @Inject()
// private billsActivateWarehouses: BillActivateWarehouses;
// /**
// * Attaches events with handlers.
// */
// public attach(bus) {
// bus.subscribe(
// events.warehouse.onActivated,
// this.updateBillsWithWarehouseOnActivated
// );
// return bus;
// }
// /**
// * Updates all inventory transactions with the primary warehouse once
// * multi-warehouses feature is activated.
// * @param {IWarehousesActivatedPayload}
// */
// private updateBillsWithWarehouseOnActivated = async ({
// tenantId,
// primaryWarehouse,
// }: IWarehousesActivatedPayload) => {
// await this.billsActivateWarehouses.updateBillsWithWarehouse(
// tenantId,
// primaryWarehouse
// );
// };
// }

View File

@@ -0,0 +1,36 @@
// import { Service, Inject } from 'typedi';
// import { IWarehousesActivatedPayload } from '@/interfaces';
// import events from '@/subscribers/events';
// import { CreditNotesActivateWarehouses } from '../../Activate/CreditNoteWarehousesActivate';
// @Service()
// export class CreditsActivateWarehousesSubscriber {
// @Inject()
// private creditsActivateWarehouses: CreditNotesActivateWarehouses;
// /**
// * Attaches events with handlers.
// */
// public attach(bus) {
// bus.subscribe(
// events.warehouse.onActivated,
// this.updateInvoicesWithWarehouseOnActivated
// );
// return bus;
// }
// /**
// * Updates all inventory transactions with the primary warehouse once
// * multi-warehouses feature is activated.
// * @param {IWarehousesActivatedPayload}
// */
// private updateInvoicesWithWarehouseOnActivated = async ({
// tenantId,
// primaryWarehouse,
// }: IWarehousesActivatedPayload) => {
// await this.creditsActivateWarehouses.updateCreditsWithWarehouse(
// tenantId,
// primaryWarehouse
// );
// };
// }

View File

@@ -0,0 +1,36 @@
// import { Service, Inject } from 'typedi';
// import { IWarehousesActivatedPayload } from '@/interfaces';
// import events from '@/subscribers/events';
// import { EstimatesActivateWarehouses } from '../../Activate/EstimateWarehousesActivate';
// @Service()
// export class EstimatesActivateWarehousesSubscriber {
// @Inject()
// private estimatesActivateWarehouses: EstimatesActivateWarehouses;
// /**
// * Attaches events with handlers.
// */
// public attach(bus) {
// bus.subscribe(
// events.warehouse.onActivated,
// this.updateEstimatessWithWarehouseOnActivated
// );
// return bus;
// }
// /**
// * Updates all inventory transactions with the primary warehouse once
// * multi-warehouses feature is activated.
// * @param {IWarehousesActivatedPayload}
// */
// private updateEstimatessWithWarehouseOnActivated = async ({
// tenantId,
// primaryWarehouse,
// }: IWarehousesActivatedPayload) => {
// await this.estimatesActivateWarehouses.updateEstimatesWithWarehouse(
// tenantId,
// primaryWarehouse
// );
// };
// }

View File

@@ -0,0 +1,36 @@
// import { Service, Inject } from 'typedi';
// import { IWarehousesActivatedPayload } from '@/interfaces';
// import events from '@/subscribers/events';
// import { InventoryActivateWarehouses } from '../../Activate/InventoryTransactionsWarehousesActivate';
// @Service()
// export class InventoryActivateWarehousesSubscriber {
// @Inject()
// private inventoryActivateWarehouses: InventoryActivateWarehouses;
// /**
// * Attaches events with handlers.
// */
// public attach(bus) {
// bus.subscribe(
// events.warehouse.onActivated,
// this.updateInventoryTransactionsWithWarehouseOnActivated
// );
// return bus;
// }
// /**
// * Updates all inventory transactions with the primary warehouse once
// * multi-warehouses feature is activated.
// * @param {IWarehousesActivatedPayload}
// */
// private updateInventoryTransactionsWithWarehouseOnActivated = async ({
// tenantId,
// primaryWarehouse,
// }: IWarehousesActivatedPayload) => {
// await this.inventoryActivateWarehouses.updateInventoryTransactionsWithWarehouse(
// tenantId,
// primaryWarehouse
// );
// };
// }

View File

@@ -0,0 +1,36 @@
// import { Service, Inject } from 'typedi';
// import { IWarehousesActivatedPayload } from '@/interfaces';
// import events from '@/subscribers/events';
// import { InvoicesActivateWarehouses } from '../../Activate/InvoiceWarehousesActivate';
// @Service()
// export class InvoicesActivateWarehousesSubscriber {
// @Inject()
// private invoicesActivateWarehouses: InvoicesActivateWarehouses;
// /**
// * Attaches events with handlers.
// */
// public attach(bus) {
// bus.subscribe(
// events.warehouse.onActivated,
// this.updateInvoicesWithWarehouseOnActivated
// );
// return bus;
// }
// /**
// * Updates all inventory transactions with the primary warehouse once
// * multi-warehouses feature is activated.
// * @param {IWarehousesActivatedPayload}
// */
// private updateInvoicesWithWarehouseOnActivated = async ({
// tenantId,
// primaryWarehouse,
// }: IWarehousesActivatedPayload) => {
// await this.invoicesActivateWarehouses.updateInvoicesWithWarehouse(
// tenantId,
// primaryWarehouse
// );
// };
// }

View File

@@ -0,0 +1,36 @@
// import { Service, Inject } from 'typedi';
// import { IWarehousesActivatedPayload } from '@/interfaces';
// import events from '@/subscribers/events';
// import { ReceiptActivateWarehouses } from '../../Activate/ReceiptWarehousesActivate';
// @Service()
// export class ReceiptsActivateWarehousesSubscriber {
// @Inject()
// private receiptsActivateWarehouses: ReceiptActivateWarehouses;
// /**
// * Attaches events with handlers.
// */
// public attach(bus) {
// bus.subscribe(
// events.warehouse.onActivated,
// this.updateInventoryTransactionsWithWarehouseOnActivated
// );
// return bus;
// }
// /**
// * Updates all receipts transactions with the primary warehouse once
// * multi-warehouses feature is activated.
// * @param {IWarehousesActivatedPayload}
// */
// private updateInventoryTransactionsWithWarehouseOnActivated = async ({
// tenantId,
// primaryWarehouse,
// }: IWarehousesActivatedPayload) => {
// await this.receiptsActivateWarehouses.updateReceiptsWithWarehouse(
// tenantId,
// primaryWarehouse
// );
// };
// }

View File

@@ -0,0 +1,36 @@
// import { Service, Inject } from 'typedi';
// import { IWarehousesActivatedPayload } from '@/interfaces';
// import events from '@/subscribers/events';
// import { VendorCreditActivateWarehouses } from '../../Activate/VendorCreditWarehousesActivate';
// @Service()
// export class VendorCreditsActivateWarehousesSubscriber {
// @Inject()
// private creditsActivateWarehouses: VendorCreditActivateWarehouses;
// /**
// * Attaches events with handlers.
// */
// public attach(bus) {
// bus.subscribe(
// events.warehouse.onActivated,
// this.updateCreditsWithWarehouseOnActivated
// );
// return bus;
// }
// /**
// * Updates all inventory transactions with the primary warehouse once
// * multi-warehouses feature is activated.
// * @param {IWarehousesActivatedPayload}
// */
// private updateCreditsWithWarehouseOnActivated = async ({
// tenantId,
// primaryWarehouse,
// }: IWarehousesActivatedPayload) => {
// await this.creditsActivateWarehouses.updateCreditsWithWarehouse(
// tenantId,
// primaryWarehouse
// );
// };
// }

View File

@@ -0,0 +1,8 @@
// /* eslint-disable import/extensions */
// export * from './BillWarehousesActivateSubscriber';
// export * from './CreditNoteWarehousesActivateSubscriber';
// export * from './EstimateWarehousesActivateSubscriber';
// export * from './InventoryTransactionsWarehousesActivateSubscriber';
// export * from './VendorCreditWarehousesActivateSubscriber';
// export * from './ReceiptWarehousesActivateSubscriber';
// export * from './InvoiceWarehousesActivateSubscriber';

View File

@@ -0,0 +1,36 @@
// import { Inject, Service } from 'typedi';
// import events from '@/subscribers/events';
// import { DeleteItemWarehousesQuantity } from '../commands/DeleteItemWarehousesQuantity';
// import { IItemEventDeletingPayload } from '@/interfaces';
// @Service()
// export class DeleteItemWarehousesQuantitySubscriber {
// @Inject()
// private deleteItemWarehousesQuantity: DeleteItemWarehousesQuantity;
// /**
// * Attaches events.
// */
// public attach(bus) {
// bus.subscribe(
// events.item.onDeleting,
// this.deleteItemWarehouseQuantitiesOnItemDelete
// );
// }
// /**
// * Deletes the given item warehouses quantities once the item deleting.
// * @param {IItemEventDeletingPayload} payload -
// */
// private deleteItemWarehouseQuantitiesOnItemDelete = async ({
// tenantId,
// oldItem,
// trx,
// }: IItemEventDeletingPayload) => {
// await this.deleteItemWarehousesQuantity.deleteItemWarehousesQuantity(
// tenantId,
// oldItem.id,
// trx
// );
// };
// }

View File

@@ -0,0 +1,35 @@
// import { Inject, Service } from 'typedi';
// import { IInventoryAdjustmentCreatingPayload } from '@/interfaces';
// import events from '@/subscribers/events';
// import { WarehousesDTOValidators } from '../../../Integrations/WarehousesDTOValidators';
// @Service()
// export class InventoryAdjustmentWarehouseValidatorSubscriber {
// @Inject()
// private warehouseDTOValidator: WarehousesDTOValidators;
// /**
// * Attaches events with handlers.
// */
// public attach(bus) {
// bus.subscribe(
// events.inventoryAdjustment.onQuickCreating,
// this.validateAdjustmentWarehouseExistanceOnCreating
// );
// return bus;
// }
// /**
// * Validate warehouse existance of sale invoice once creating.
// * @param {IBillCreatingPayload}
// */
// private validateAdjustmentWarehouseExistanceOnCreating = async ({
// quickAdjustmentDTO,
// tenantId,
// }: IInventoryAdjustmentCreatingPayload) => {
// await this.warehouseDTOValidator.validateDTOWarehouseWhenActive(
// tenantId,
// quickAdjustmentDTO
// );
// };
// }

View File

@@ -0,0 +1,53 @@
// import { Inject, Service } from 'typedi';
// import { IBillCreatingPayload, IBillEditingPayload } from '@/interfaces';
// import events from '@/subscribers/events';
// import { WarehousesDTOValidators } from '../../../Integrations/WarehousesDTOValidators';
// @Service()
// export class BillWarehousesValidateSubscriber {
// @Inject()
// private warehouseDTOValidator: WarehousesDTOValidators;
// /**
// * Attaches events with handlers.
// */
// public attach(bus) {
// bus.subscribe(
// events.bill.onCreating,
// this.validateBillWarehouseExistanceOnCreating
// );
// bus.subscribe(
// events.bill.onEditing,
// this.validateSaleEstimateWarehouseExistanceOnEditing
// );
// return bus;
// }
// /**
// * Validate warehouse existance of sale invoice once creating.
// * @param {IBillCreatingPayload}
// */
// private validateBillWarehouseExistanceOnCreating = async ({
// billDTO,
// tenantId,
// }: IBillCreatingPayload) => {
// await this.warehouseDTOValidator.validateDTOWarehouseWhenActive(
// tenantId,
// billDTO
// );
// };
// /**
// * Validate warehouse existance of sale invoice once editing.
// * @param {IBillEditingPayload}
// */
// private validateSaleEstimateWarehouseExistanceOnEditing = async ({
// tenantId,
// billDTO,
// }: IBillEditingPayload) => {
// await this.warehouseDTOValidator.validateDTOWarehouseWhenActive(
// tenantId,
// billDTO
// );
// };
// }

View File

@@ -0,0 +1,56 @@
// import { Inject, Service } from 'typedi';
// import {
// IVendorCreditCreatingPayload,
// IVendorCreditEditingPayload,
// } from '@/interfaces';
// import events from '@/subscribers/events';
// import { WarehousesDTOValidators } from '../../../Integrations/WarehousesDTOValidators';
// @Service()
// export class VendorCreditWarehousesValidateSubscriber {
// @Inject()
// warehouseDTOValidator: WarehousesDTOValidators;
// /**
// * Attaches events with handlers.
// */
// public attach(bus) {
// bus.subscribe(
// events.vendorCredit.onCreating,
// this.validateVendorCreditWarehouseExistanceOnCreating
// );
// bus.subscribe(
// events.vendorCredit.onEditing,
// this.validateSaleEstimateWarehouseExistanceOnEditing
// );
// return bus;
// }
// /**
// * Validate warehouse existance of sale invoice once creating.
// * @param {IVendorCreditCreatingPayload}
// */
// private validateVendorCreditWarehouseExistanceOnCreating = async ({
// vendorCreditCreateDTO,
// tenantId,
// }: IVendorCreditCreatingPayload) => {
// await this.warehouseDTOValidator.validateDTOWarehouseWhenActive(
// tenantId,
// vendorCreditCreateDTO
// );
// };
// /**
// * Validate warehouse existance of sale invoice once editing.
// * @param {IVendorCreditEditingPayload}
// */
// private validateSaleEstimateWarehouseExistanceOnEditing = async ({
// tenantId,
// vendorCreditDTO,
// }: IVendorCreditEditingPayload) => {
// await this.warehouseDTOValidator.validateDTOWarehouseWhenActive(
// tenantId,
// vendorCreditDTO
// );
// };
// }

View File

@@ -0,0 +1,56 @@
// import { Inject, Service } from 'typedi';
// import {
// ICreditNoteCreatingPayload,
// ICreditNoteEditingPayload,
// } from '@/interfaces';
// import events from '@/subscribers/events';
// import { WarehousesDTOValidators } from '../../../Integrations/WarehousesDTOValidators';
// @Service()
// export class CreditNoteWarehousesValidateSubscriber {
// @Inject()
// warehouseDTOValidator: WarehousesDTOValidators;
// /**
// * Attaches events with handlers.
// */
// public attach(bus) {
// bus.subscribe(
// events.creditNote.onCreating,
// this.validateCreditNoteWarehouseExistanceOnCreating
// );
// bus.subscribe(
// events.creditNote.onEditing,
// this.validateCreditNoteWarehouseExistanceOnEditing
// );
// return bus;
// }
// /**
// * Validate warehouse existance of sale invoice once creating.
// * @param {ICreditNoteCreatingPayload}
// */
// private validateCreditNoteWarehouseExistanceOnCreating = async ({
// creditNoteDTO,
// tenantId,
// }: ICreditNoteCreatingPayload) => {
// await this.warehouseDTOValidator.validateDTOWarehouseWhenActive(
// tenantId,
// creditNoteDTO
// );
// };
// /**
// * Validate warehouse existance of sale invoice once editing.
// * @param {ICreditNoteEditingPayload}
// */
// private validateCreditNoteWarehouseExistanceOnEditing = async ({
// tenantId,
// creditNoteEditDTO,
// }: ICreditNoteEditingPayload) => {
// await this.warehouseDTOValidator.validateDTOWarehouseWhenActive(
// tenantId,
// creditNoteEditDTO
// );
// };
// }

View File

@@ -0,0 +1,56 @@
// import { Inject, Service } from 'typedi';
// import {
// ISaleEstimateCreatingPayload,
// ISaleEstimateEditingPayload,
// } from '@/interfaces';
// import events from '@/subscribers/events';
// import { WarehousesDTOValidators } from '../../../Integrations/WarehousesDTOValidators';
// @Service()
// export class SaleEstimateWarehousesValidateSubscriber {
// @Inject()
// warehouseDTOValidator: WarehousesDTOValidators;
// /**
// * Attaches events with handlers.
// */
// public attach(bus) {
// bus.subscribe(
// events.saleEstimate.onCreating,
// this.validateSaleEstimateWarehouseExistanceOnCreating
// );
// bus.subscribe(
// events.saleEstimate.onEditing,
// this.validateSaleEstimateWarehouseExistanceOnEditing
// );
// return bus;
// }
// /**
// * Validate warehouse existance of sale invoice once creating.
// * @param {ISaleEstimateCreatingPayload}
// */
// private validateSaleEstimateWarehouseExistanceOnCreating = async ({
// estimateDTO,
// tenantId,
// }: ISaleEstimateCreatingPayload) => {
// await this.warehouseDTOValidator.validateDTOWarehouseWhenActive(
// tenantId,
// estimateDTO
// );
// };
// /**
// * Validate warehouse existance of sale invoice once editing.
// * @param {ISaleEstimateEditingPayload}
// */
// private validateSaleEstimateWarehouseExistanceOnEditing = async ({
// tenantId,
// estimateDTO,
// }: ISaleEstimateEditingPayload) => {
// await this.warehouseDTOValidator.validateDTOWarehouseWhenActive(
// tenantId,
// estimateDTO
// );
// };
// }

View File

@@ -0,0 +1,56 @@
// import { Inject, Service } from 'typedi';
// import {
// ISaleInvoiceCreatingPaylaod,
// ISaleInvoiceEditingPayload,
// } from '@/interfaces';
// import events from '@/subscribers/events';
// import { WarehousesDTOValidators } from '../../../Integrations/WarehousesDTOValidators';
// @Service()
// export class SaleInvoicesWarehousesValidateSubscriber {
// @Inject()
// warehousesDTOValidator: WarehousesDTOValidators;
// /**
// * Attaches events with handlers.
// */
// public attach(bus) {
// bus.subscribe(
// events.saleInvoice.onCreating,
// this.validateSaleInvoiceWarehouseExistanceOnCreating
// );
// bus.subscribe(
// events.saleInvoice.onEditing,
// this.validateSaleInvoiceWarehouseExistanceOnEditing
// );
// return bus;
// }
// /**
// * Validate warehouse existance of sale invoice once creating.
// * @param {ISaleInvoiceCreatingPaylaod}
// */
// private validateSaleInvoiceWarehouseExistanceOnCreating = async ({
// saleInvoiceDTO,
// tenantId,
// }: ISaleInvoiceCreatingPaylaod) => {
// await this.warehousesDTOValidator.validateDTOWarehouseWhenActive(
// tenantId,
// saleInvoiceDTO
// );
// };
// /**
// * Validate warehouse existance of sale invoice once editing.
// * @param {ISaleInvoiceEditingPayload}
// */
// private validateSaleInvoiceWarehouseExistanceOnEditing = async ({
// tenantId,
// saleInvoiceDTO,
// }: ISaleInvoiceEditingPayload) => {
// await this.warehousesDTOValidator.validateDTOWarehouseWhenActive(
// tenantId,
// saleInvoiceDTO
// );
// };
// }

View File

@@ -0,0 +1,56 @@
// import { Inject, Service } from 'typedi';
// import {
// ISaleReceiptCreatingPayload,
// ISaleReceiptEditingPayload,
// } from '@/interfaces';
// import events from '@/subscribers/events';
// import { WarehousesDTOValidators } from '../../../Integrations/WarehousesDTOValidators';
// @Service()
// export class SaleReceiptWarehousesValidateSubscriber {
// @Inject()
// private warehousesDTOValidator: WarehousesDTOValidators;
// /**
// * Attaches events with handlers.
// */
// public attach(bus) {
// bus.subscribe(
// events.saleReceipt.onCreating,
// this.validateSaleReceiptWarehouseExistanceOnCreating
// );
// bus.subscribe(
// events.saleReceipt.onEditing,
// this.validateSaleReceiptWarehouseExistanceOnEditing
// );
// return bus;
// }
// /**
// * Validate warehouse existance of sale invoice once creating.
// * @param {ISaleReceiptCreatingPayload}
// */
// private validateSaleReceiptWarehouseExistanceOnCreating = async ({
// saleReceiptDTO,
// tenantId,
// }: ISaleReceiptCreatingPayload) => {
// await this.warehousesDTOValidator.validateDTOWarehouseWhenActive(
// tenantId,
// saleReceiptDTO
// );
// };
// /**
// * Validate warehouse existance of sale invoice once editing.
// * @param {ISaleReceiptEditingPayload}
// */
// private validateSaleReceiptWarehouseExistanceOnEditing = async ({
// tenantId,
// saleReceiptDTO,
// }: ISaleReceiptEditingPayload) => {
// await this.warehousesDTOValidator.validateDTOWarehouseWhenActive(
// tenantId,
// saleReceiptDTO
// );
// };
// }

View File

@@ -0,0 +1,9 @@
// export * from './Purchases/BillWarehousesSubscriber';
// export * from './Purchases/VendorCreditWarehousesSubscriber';
// export * from './Sales/SaleEstimateWarehousesSubscriber';
// export * from './Sales/CreditNoteWarehousesSubscriber';
// export * from './Sales/SaleInvoicesWarehousesSubscriber';
// export * from './Sales/SaleReceiptWarehousesSubscriber';
// export * from './InventoryAdjustment/InventoryAdjustmentWarehouseValidatorSubscriber';