mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-23 08:10:32 +00:00
add server to monorepo.
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
import { Service, Inject } from 'typedi';
|
||||
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import { ServiceError } from '@/exceptions';
|
||||
import { ERRORS } from './constants';
|
||||
|
||||
@Service()
|
||||
export class CRUDWarehouseTransfer {
|
||||
@Inject()
|
||||
tenancy: HasTenancyService;
|
||||
|
||||
|
||||
throwIfTransferNotFound = (warehouseTransfer) => {
|
||||
if (!warehouseTransfer) {
|
||||
throw new ServiceError(ERRORS.WAREHOUSE_TRANSFER_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
public getWarehouseTransferOrThrowNotFound = async (
|
||||
tenantId: number,
|
||||
branchId: number
|
||||
) => {
|
||||
const { WarehouseTransfer } = this.tenancy.models(tenantId);
|
||||
|
||||
const foundTransfer = await WarehouseTransfer.query().findById(branchId);
|
||||
|
||||
if (!foundTransfer) {
|
||||
throw new ServiceError(ERRORS.WAREHOUSE_TRANSFER_NOT_FOUND);
|
||||
}
|
||||
return foundTransfer;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
import { Inject } from 'typedi';
|
||||
import {
|
||||
ICreateWarehouseTransferDTO,
|
||||
IEditWarehouseTransferDTO,
|
||||
IItem,
|
||||
} from '@/interfaces';
|
||||
import { ServiceError } from '@/exceptions';
|
||||
import { ERRORS } from './constants';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import ItemsEntriesService from '@/services/Items/ItemsEntriesService';
|
||||
import { CRUDWarehouseTransfer } from './CRUDWarehouseTransfer';
|
||||
|
||||
export class CommandWarehouseTransfer extends CRUDWarehouseTransfer {
|
||||
@Inject()
|
||||
tenancy: HasTenancyService;
|
||||
|
||||
@Inject()
|
||||
itemsEntries: ItemsEntriesService;
|
||||
|
||||
/**
|
||||
* Validate the from/to warehouses should not be the same.
|
||||
* @param {ICreateWarehouseTransferDTO|IEditWarehouseTransferDTO} warehouseTransferDTO
|
||||
*/
|
||||
protected validateWarehouseFromToNotSame = (
|
||||
warehouseTransferDTO:
|
||||
| ICreateWarehouseTransferDTO
|
||||
| IEditWarehouseTransferDTO
|
||||
) => {
|
||||
if (
|
||||
warehouseTransferDTO.fromWarehouseId ===
|
||||
warehouseTransferDTO.toWarehouseId
|
||||
) {
|
||||
throw new ServiceError(ERRORS.WAREHOUSES_TRANSFER_SHOULD_NOT_BE_SAME);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validates entries items should be inventory.
|
||||
* @param {IItem[]} items
|
||||
* @returns {void}
|
||||
*/
|
||||
protected validateItemsShouldBeInventory = (items: IItem[]): void => {
|
||||
const nonInventoryItems = items.filter((item) => item.type !== 'inventory');
|
||||
|
||||
if (nonInventoryItems.length > 0) {
|
||||
throw new ServiceError(
|
||||
ERRORS.WAREHOUSE_TRANSFER_ITEMS_SHOULD_BE_INVENTORY
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
protected getToWarehouseOrThrow = async (
|
||||
tenantId: number,
|
||||
fromWarehouseId: number
|
||||
) => {
|
||||
const { Warehouse } = this.tenancy.models(tenantId);
|
||||
|
||||
const warehouse = await Warehouse.query().findById(fromWarehouseId);
|
||||
|
||||
if (!warehouse) {
|
||||
throw new ServiceError(ERRORS.TO_WAREHOUSE_NOT_FOUND);
|
||||
}
|
||||
return warehouse;
|
||||
};
|
||||
|
||||
protected getFromWarehouseOrThrow = async (
|
||||
tenantId: number,
|
||||
fromWarehouseId: number
|
||||
) => {
|
||||
const { Warehouse } = this.tenancy.models(tenantId);
|
||||
|
||||
const warehouse = await Warehouse.query().findById(fromWarehouseId);
|
||||
|
||||
if (!warehouse) {
|
||||
throw new ServiceError(ERRORS.FROM_WAREHOUSE_NOT_FOUND);
|
||||
}
|
||||
return warehouse;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
import { Knex } from 'knex';
|
||||
import { omit, get, isNumber } from 'lodash';
|
||||
import * as R from 'ramda';
|
||||
import {
|
||||
ICreateWarehouseTransferDTO,
|
||||
IWarehouseTransfer,
|
||||
IWarehouseTransferCreate,
|
||||
IWarehouseTransferCreated,
|
||||
IWarehouseTransferEntryDTO,
|
||||
IInventoryItemCostMeta,
|
||||
} from '@/interfaces';
|
||||
import { Service, Inject } from 'typedi';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||
import UnitOfWork from '@/services/UnitOfWork';
|
||||
import events from '@/subscribers/events';
|
||||
import ItemsEntriesService from '@/services/Items/ItemsEntriesService';
|
||||
import { CommandWarehouseTransfer } from './CommandWarehouseTransfer';
|
||||
import { InventoryItemCostService } from '@/services/Inventory/InventoryCostsService';
|
||||
import { WarehouseTransferAutoIncrement } from './WarehouseTransferAutoIncrement';
|
||||
|
||||
@Service()
|
||||
export class CreateWarehouseTransfer extends CommandWarehouseTransfer {
|
||||
@Inject()
|
||||
private tenancy: HasTenancyService;
|
||||
|
||||
@Inject()
|
||||
private uow: UnitOfWork;
|
||||
|
||||
@Inject()
|
||||
private eventPublisher: EventPublisher;
|
||||
|
||||
@Inject()
|
||||
private itemsEntries: ItemsEntriesService;
|
||||
|
||||
@Inject()
|
||||
private inventoryItemCost: InventoryItemCostService;
|
||||
|
||||
@Inject()
|
||||
private autoIncrementOrders: WarehouseTransferAutoIncrement;
|
||||
|
||||
/**
|
||||
* Transformes the givne new warehouse transfer DTO to model.
|
||||
* @param {ICreateWarehouseTransferDTO} warehouseTransferDTO
|
||||
* @returns {IWarehouseTransfer}
|
||||
*/
|
||||
private transformDTOToModel = async (
|
||||
tenantId: number,
|
||||
warehouseTransferDTO: ICreateWarehouseTransferDTO
|
||||
): Promise<IWarehouseTransfer> => {
|
||||
const entries = await this.transformEntries(
|
||||
tenantId,
|
||||
warehouseTransferDTO,
|
||||
warehouseTransferDTO.entries
|
||||
);
|
||||
// Retrieves the auto-increment the warehouse transfer number.
|
||||
const autoNextNumber =
|
||||
this.autoIncrementOrders.getNextTransferNumber(tenantId);
|
||||
|
||||
// Warehouse transfer order transaction number.
|
||||
const transactionNumber =
|
||||
warehouseTransferDTO.transactionNumber || autoNextNumber;
|
||||
|
||||
return {
|
||||
...omit(warehouseTransferDTO, ['transferDelivered', 'transferInitiated']),
|
||||
transactionNumber,
|
||||
...(warehouseTransferDTO.transferDelivered
|
||||
? {
|
||||
transferDeliveredAt: new Date(),
|
||||
}
|
||||
: {}),
|
||||
...(warehouseTransferDTO.transferDelivered ||
|
||||
warehouseTransferDTO.transferInitiated
|
||||
? {
|
||||
transferInitiatedAt: new Date(),
|
||||
}
|
||||
: {}),
|
||||
entries,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Assoc average cost to the entry that has no cost.
|
||||
* @param {Promise<Map<number, IInventoryItemCostMeta>} inventoryItemsCostMap -
|
||||
* @param {IWarehouseTransferEntryDTO} entry -
|
||||
*/
|
||||
private transformEntryAssocAverageCost = R.curry(
|
||||
(
|
||||
inventoryItemsCostMap: Map<number, IInventoryItemCostMeta>,
|
||||
entry: IWarehouseTransferEntryDTO
|
||||
): IWarehouseTransferEntryDTO => {
|
||||
const itemValuation = inventoryItemsCostMap.get(entry.itemId);
|
||||
const itemCost = get(itemValuation, 'average', 0);
|
||||
|
||||
return isNumber(entry.cost) ? entry : R.assoc('cost', itemCost, entry);
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Transformes warehouse transfer entries.
|
||||
* @param {number} tenantId
|
||||
* @param {ICreateWarehouseTransferDTO} warehouseTransferDTO
|
||||
* @param {IWarehouseTransferEntryDTO[]} entries
|
||||
* @returns {Promise<IWarehouseTransferEntryDTO[]>}
|
||||
*/
|
||||
public transformEntries = async (
|
||||
tenantId: number,
|
||||
warehouseTransferDTO: ICreateWarehouseTransferDTO,
|
||||
entries: IWarehouseTransferEntryDTO[]
|
||||
): Promise<IWarehouseTransferEntryDTO[]> => {
|
||||
const inventoryItemsIds = warehouseTransferDTO.entries.map((e) => e.itemId);
|
||||
|
||||
// Retrieves the inventory items valuation map.
|
||||
const inventoryItemsCostMap =
|
||||
await this.inventoryItemCost.getItemsInventoryValuation(
|
||||
tenantId,
|
||||
inventoryItemsIds,
|
||||
warehouseTransferDTO.date
|
||||
);
|
||||
// Assoc average cost to the entry.
|
||||
const assocAverageCost = this.transformEntryAssocAverageCost(
|
||||
inventoryItemsCostMap
|
||||
);
|
||||
return R.map(assocAverageCost)(entries);
|
||||
};
|
||||
|
||||
/**
|
||||
* Authorize warehouse transfer before creating.
|
||||
* @param {number} tenantId
|
||||
* @param {ICreateWarehouseTransferDTO} warehouseTransferDTO
|
||||
*/
|
||||
public authorize = async (
|
||||
tenantId: number,
|
||||
warehouseTransferDTO: ICreateWarehouseTransferDTO
|
||||
) => {
|
||||
// Validate warehouse from and to should not be the same.
|
||||
this.validateWarehouseFromToNotSame(warehouseTransferDTO);
|
||||
|
||||
// Retrieves the from warehouse or throw not found service error.
|
||||
const fromWarehouse = await this.getFromWarehouseOrThrow(
|
||||
tenantId,
|
||||
warehouseTransferDTO.fromWarehouseId
|
||||
);
|
||||
// Retrieves the to warehouse or throw not found service error.
|
||||
const toWarehouse = await this.getToWarehouseOrThrow(
|
||||
tenantId,
|
||||
warehouseTransferDTO.toWarehouseId
|
||||
);
|
||||
// Validates the not found entries items ids.
|
||||
const items = await this.itemsEntries.validateItemsIdsExistance(
|
||||
tenantId,
|
||||
warehouseTransferDTO.entries
|
||||
);
|
||||
// Validate the items entries should be inventory type.
|
||||
this.validateItemsShouldBeInventory(items);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new warehouse transfer transaction.
|
||||
* @param {number} tenantId -
|
||||
* @param {ICreateWarehouseTransferDTO} warehouseDTO -
|
||||
* @returns {Promise<IWarehouseTransferCreate>}
|
||||
*/
|
||||
public createWarehouseTransfer = async (
|
||||
tenantId: number,
|
||||
warehouseTransferDTO: ICreateWarehouseTransferDTO
|
||||
): Promise<IWarehouseTransfer> => {
|
||||
const { WarehouseTransfer } = this.tenancy.models(tenantId);
|
||||
|
||||
// Authorize warehouse transfer before creating.
|
||||
await this.authorize(tenantId, warehouseTransferDTO);
|
||||
|
||||
// Transformes the warehouse transfer DTO to model.
|
||||
const warehouseTransferModel = await this.transformDTOToModel(
|
||||
tenantId,
|
||||
warehouseTransferDTO
|
||||
);
|
||||
// Create warehouse transfer under unit-of-work.
|
||||
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => {
|
||||
// Triggers `onWarehouseTransferCreate` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouseTransfer.onCreate, {
|
||||
trx,
|
||||
warehouseTransferDTO,
|
||||
tenantId,
|
||||
} as IWarehouseTransferCreate);
|
||||
|
||||
// Stores the warehouse transfer transaction graph to the storage.
|
||||
const warehouseTransfer = await WarehouseTransfer.query(
|
||||
trx
|
||||
).upsertGraphAndFetch({
|
||||
...warehouseTransferModel,
|
||||
});
|
||||
// Triggers `onWarehouseTransferCreated` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouseTransfer.onCreated, {
|
||||
trx,
|
||||
warehouseTransfer,
|
||||
warehouseTransferDTO,
|
||||
tenantId,
|
||||
} as IWarehouseTransferCreated);
|
||||
|
||||
return warehouseTransfer;
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import { Service, Inject } from 'typedi';
|
||||
import { Knex } from 'knex';
|
||||
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import UnitOfWork from '@/services/UnitOfWork';
|
||||
import events from '@/subscribers/events';
|
||||
import {
|
||||
IWarehouseTransferDeletedPayload,
|
||||
IWarehouseTransferDeletePayload,
|
||||
} from '@/interfaces';
|
||||
import { CRUDWarehouseTransfer } from './CRUDWarehouseTransfer';
|
||||
|
||||
@Service()
|
||||
export class DeleteWarehouseTransfer extends CRUDWarehouseTransfer {
|
||||
@Inject()
|
||||
private tenancy: HasTenancyService;
|
||||
|
||||
@Inject()
|
||||
private uow: UnitOfWork;
|
||||
|
||||
@Inject()
|
||||
private eventPublisher: EventPublisher;
|
||||
|
||||
/**
|
||||
* Deletes warehouse transfer transaction.
|
||||
* @param {number} tenantId
|
||||
* @param {number} warehouseTransferId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public deleteWarehouseTransfer = async (
|
||||
tenantId: number,
|
||||
warehouseTransferId: number
|
||||
): Promise<void> => {
|
||||
const { WarehouseTransfer, WarehouseTransferEntry } =
|
||||
this.tenancy.models(tenantId);
|
||||
|
||||
// Retrieve the old warehouse transfer or throw not found service error.
|
||||
const oldWarehouseTransfer = await WarehouseTransfer.query()
|
||||
.findById(warehouseTransferId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// Deletes the warehouse transfer under unit-of-work envirement.
|
||||
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => {
|
||||
// Triggers `onWarehouseTransferCreate` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouseTransfer.onDelete, {
|
||||
tenantId,
|
||||
oldWarehouseTransfer,
|
||||
trx,
|
||||
} as IWarehouseTransferDeletePayload);
|
||||
|
||||
// Delete warehouse transfer entries.
|
||||
await WarehouseTransferEntry.query(trx)
|
||||
.where('warehouseTransferId', warehouseTransferId)
|
||||
.delete();
|
||||
|
||||
// Delete warehouse transfer.
|
||||
await WarehouseTransfer.query(trx).findById(warehouseTransferId).delete();
|
||||
|
||||
// Triggers `onWarehouseTransferDeleted` event
|
||||
await this.eventPublisher.emitAsync(events.warehouseTransfer.onDeleted, {
|
||||
tenantId,
|
||||
oldWarehouseTransfer,
|
||||
trx,
|
||||
} as IWarehouseTransferDeletedPayload);
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import { Service, Inject } from 'typedi';
|
||||
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import UnitOfWork from '@/services/UnitOfWork';
|
||||
import { Knex } from 'knex';
|
||||
import events from '@/subscribers/events';
|
||||
import {
|
||||
IEditWarehouseTransferDTO,
|
||||
IWarehouseTransfer,
|
||||
IWarehouseTransferEditPayload,
|
||||
IWarehouseTransferEditedPayload,
|
||||
} from '@/interfaces';
|
||||
import { CommandWarehouseTransfer } from './CommandWarehouseTransfer';
|
||||
|
||||
@Service()
|
||||
export class EditWarehouseTransfer extends CommandWarehouseTransfer {
|
||||
@Inject()
|
||||
tenancy: HasTenancyService;
|
||||
|
||||
@Inject()
|
||||
uow: UnitOfWork;
|
||||
|
||||
@Inject()
|
||||
eventPublisher: EventPublisher;
|
||||
|
||||
/**
|
||||
* Edits warehouse transfer.
|
||||
* @param {number} tenantId
|
||||
* @param {number} warehouseTransferId
|
||||
* @param {IEditWarehouseTransferDTO} editWarehouseDTO
|
||||
* @returns {Promise<IWarehouseTransfer>}
|
||||
*/
|
||||
public editWarehouseTransfer = async (
|
||||
tenantId: number,
|
||||
warehouseTransferId: number,
|
||||
editWarehouseDTO: IEditWarehouseTransferDTO
|
||||
): Promise<IWarehouseTransfer> => {
|
||||
const { WarehouseTransfer } = this.tenancy.models(tenantId);
|
||||
|
||||
// Retrieves the old warehouse transfer transaction.
|
||||
const oldWarehouseTransfer = await WarehouseTransfer.query()
|
||||
.findById(warehouseTransferId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// Validate warehouse from and to should not be the same.
|
||||
this.validateWarehouseFromToNotSame(editWarehouseDTO);
|
||||
|
||||
// Retrieves the from warehouse or throw not found service error.
|
||||
const fromWarehouse = await this.getFromWarehouseOrThrow(
|
||||
tenantId,
|
||||
editWarehouseDTO.fromWarehouseId
|
||||
);
|
||||
// Retrieves the to warehouse or throw not found service error.
|
||||
const toWarehouse = await this.getToWarehouseOrThrow(
|
||||
tenantId,
|
||||
editWarehouseDTO.toWarehouseId
|
||||
);
|
||||
// Validates the not found entries items ids.
|
||||
const items = await this.itemsEntries.validateItemsIdsExistance(
|
||||
tenantId,
|
||||
editWarehouseDTO.entries
|
||||
);
|
||||
// Validate the items entries should be inventory type.
|
||||
this.validateItemsShouldBeInventory(items);
|
||||
|
||||
// Edits warehouse transfer transaction under unit-of-work envirement.
|
||||
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => {
|
||||
// Triggers `onWarehouseTransferEdit` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouseTransfer.onEdit, {
|
||||
tenantId,
|
||||
editWarehouseDTO,
|
||||
oldWarehouseTransfer,
|
||||
trx,
|
||||
} as IWarehouseTransferEditPayload);
|
||||
|
||||
// Updates warehouse transfer graph on the storage.
|
||||
const warehouseTransfer = await WarehouseTransfer.query(
|
||||
trx
|
||||
).upsertGraphAndFetch({
|
||||
id: warehouseTransferId,
|
||||
...editWarehouseDTO,
|
||||
});
|
||||
// Triggers `onWarehouseTransferEdit` event
|
||||
await this.eventPublisher.emitAsync(events.warehouseTransfer.onEdited, {
|
||||
tenantId,
|
||||
editWarehouseDTO,
|
||||
warehouseTransfer,
|
||||
oldWarehouseTransfer,
|
||||
trx,
|
||||
} as IWarehouseTransferEditedPayload);
|
||||
|
||||
return warehouseTransfer;
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import { Service, Inject } from 'typedi';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import { IWarehouseTransfer } from '@/interfaces';
|
||||
import { CRUDWarehouseTransfer } from './CRUDWarehouseTransfer';
|
||||
import { WarehouseTransferTransformer } from './WarehouseTransferTransfomer';
|
||||
import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
|
||||
|
||||
@Service()
|
||||
export class GetWarehouseTransfer extends CRUDWarehouseTransfer {
|
||||
@Inject()
|
||||
private tenancy: HasTenancyService;
|
||||
|
||||
@Inject()
|
||||
private transformer: TransformerInjectable;
|
||||
|
||||
/**
|
||||
* Retrieves the specific warehouse transfer transaction.
|
||||
* @param {number} tenantId
|
||||
* @param {number} warehouseTransferId
|
||||
* @param {IEditWarehouseTransferDTO} editWarehouseDTO
|
||||
* @returns {Promise<IWarehouseTransfer>}
|
||||
*/
|
||||
public getWarehouseTransfer = async (
|
||||
tenantId: number,
|
||||
warehouseTransferId: number
|
||||
): Promise<IWarehouseTransfer> => {
|
||||
const { WarehouseTransfer } = this.tenancy.models(tenantId);
|
||||
|
||||
// Retrieves the old warehouse transfer transaction.
|
||||
const warehouseTransfer = await WarehouseTransfer.query()
|
||||
.findById(warehouseTransferId)
|
||||
.withGraphFetched('entries.item')
|
||||
.withGraphFetched('fromWarehouse')
|
||||
.withGraphFetched('toWarehouse');
|
||||
|
||||
this.throwIfTransferNotFound(warehouseTransfer);
|
||||
|
||||
// Retrieves the transfromed warehouse transfers.
|
||||
return this.transformer.transform(
|
||||
tenantId,
|
||||
warehouseTransfer,
|
||||
new WarehouseTransferTransformer()
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
import * as R from 'ramda';
|
||||
import { Service, Inject } from 'typedi';
|
||||
import DynamicListingService from '@/services/DynamicListing/DynamicListService';
|
||||
import { IGetWarehousesTransfersFilterDTO } from '@/interfaces';
|
||||
import { WarehouseTransferTransformer } from './WarehouseTransferTransfomer';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
|
||||
|
||||
@Service()
|
||||
export class GetWarehouseTransfers {
|
||||
@Inject()
|
||||
private dynamicListService: DynamicListingService;
|
||||
|
||||
@Inject()
|
||||
private tenancy: HasTenancyService;
|
||||
|
||||
@Inject()
|
||||
private transformer: TransformerInjectable;
|
||||
|
||||
/**
|
||||
* Parses the sale invoice list filter DTO.
|
||||
* @param filterDTO
|
||||
* @returns
|
||||
*/
|
||||
private parseListFilterDTO(filterDTO) {
|
||||
return R.compose(this.dynamicListService.parseStringifiedFilter)(filterDTO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves warehouse transfers paginated list.
|
||||
* @param {number} tenantId
|
||||
* @param {IGetWarehousesTransfersFilterDTO} filterDTO
|
||||
* @returns {}
|
||||
*/
|
||||
public getWarehouseTransfers = async (
|
||||
tenantId: number,
|
||||
filterDTO: IGetWarehousesTransfersFilterDTO
|
||||
) => {
|
||||
const { WarehouseTransfer } = this.tenancy.models(tenantId);
|
||||
|
||||
// Parses stringified filter roles.
|
||||
const filter = this.parseListFilterDTO(filterDTO);
|
||||
|
||||
// Dynamic list service.
|
||||
const dynamicFilter = await this.dynamicListService.dynamicList(
|
||||
tenantId,
|
||||
WarehouseTransfer,
|
||||
filter
|
||||
);
|
||||
const { results, pagination } = await WarehouseTransfer.query()
|
||||
.onBuild((query) => {
|
||||
query.withGraphFetched('entries.item');
|
||||
query.withGraphFetched('fromWarehouse');
|
||||
query.withGraphFetched('toWarehouse');
|
||||
|
||||
dynamicFilter.buildQuery()(query);
|
||||
})
|
||||
.pagination(filter.page - 1, filter.pageSize);
|
||||
|
||||
// Retrieves the transformed warehouse transfers
|
||||
const warehousesTransfers = await this.transformer.transform(
|
||||
tenantId,
|
||||
results,
|
||||
new WarehouseTransferTransformer()
|
||||
);
|
||||
return {
|
||||
warehousesTransfers,
|
||||
pagination,
|
||||
filter,
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
import { Service, Inject } from 'typedi';
|
||||
import { Knex } from 'knex';
|
||||
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import UnitOfWork from '@/services/UnitOfWork';
|
||||
import events from '@/subscribers/events';
|
||||
import {
|
||||
IWarehouseTransfer,
|
||||
IWarehouseTransferEditedPayload,
|
||||
IWarehouseTransferInitiatePayload,
|
||||
} from '@/interfaces';
|
||||
import { CommandWarehouseTransfer } from './CommandWarehouseTransfer';
|
||||
import { ServiceError } from '@/exceptions';
|
||||
import { ERRORS } from './constants';
|
||||
|
||||
@Service()
|
||||
export class InitiateWarehouseTransfer extends CommandWarehouseTransfer {
|
||||
@Inject()
|
||||
private tenancy: HasTenancyService;
|
||||
|
||||
@Inject()
|
||||
private uow: UnitOfWork;
|
||||
|
||||
@Inject()
|
||||
private eventPublisher: EventPublisher;
|
||||
|
||||
/**
|
||||
* Validate the given warehouse transfer not already initiated.
|
||||
* @param {IWarehouseTransfer} warehouseTransfer
|
||||
*/
|
||||
private validateWarehouseTransferNotAlreadyInitiated = (
|
||||
warehouseTransfer: IWarehouseTransfer
|
||||
) => {
|
||||
if (warehouseTransfer.transferInitiatedAt) {
|
||||
throw new ServiceError(ERRORS.WAREHOUSE_TRANSFER_ALREADY_INITIATED);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Initiate warehouse transfer.
|
||||
* @param {number} tenantId
|
||||
* @param {number} warehouseTransferId
|
||||
* @returns {Promise<IWarehouseTransfer>}
|
||||
*/
|
||||
public initiateWarehouseTransfer = async (
|
||||
tenantId: number,
|
||||
warehouseTransferId: number
|
||||
): Promise<IWarehouseTransfer> => {
|
||||
const { WarehouseTransfer } = this.tenancy.models(tenantId);
|
||||
|
||||
// Retrieves the old warehouse transfer transaction.
|
||||
const oldWarehouseTransfer = await WarehouseTransfer.query()
|
||||
.findById(warehouseTransferId)
|
||||
.throwIfNotFound(warehouseTransferId);
|
||||
|
||||
// Validate the given warehouse transfer not already initiated.
|
||||
this.validateWarehouseTransferNotAlreadyInitiated(oldWarehouseTransfer);
|
||||
|
||||
// Edits warehouse transfer transaction under unit-of-work envirement.
|
||||
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => {
|
||||
// Triggers `onWarehouseTransferInitiate` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouseTransfer.onInitiate, {
|
||||
tenantId,
|
||||
oldWarehouseTransfer,
|
||||
trx,
|
||||
} as IWarehouseTransferInitiatePayload);
|
||||
|
||||
// Updates warehouse transfer graph on the storage.
|
||||
const warehouseTransferUpdated = await WarehouseTransfer.query(trx)
|
||||
.findById(warehouseTransferId)
|
||||
.patch({
|
||||
transferInitiatedAt: new Date(),
|
||||
});
|
||||
// Fetches the warehouse transfer with entries.
|
||||
const warehouseTransfer = await WarehouseTransfer.query(trx)
|
||||
.findById(warehouseTransferId)
|
||||
.withGraphFetched('entries');
|
||||
|
||||
// Triggers `onWarehouseTransferEdit` event
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.warehouseTransfer.onInitiated,
|
||||
{
|
||||
tenantId,
|
||||
warehouseTransfer,
|
||||
oldWarehouseTransfer,
|
||||
trx,
|
||||
} as IWarehouseTransferEditedPayload
|
||||
);
|
||||
return warehouseTransfer;
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
import { Service, Inject } from 'typedi';
|
||||
import { Knex } from 'knex';
|
||||
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import UnitOfWork from '@/services/UnitOfWork';
|
||||
import events from '@/subscribers/events';
|
||||
import {
|
||||
IWarehouseTransfer,
|
||||
IWarehouseTransferTransferingPayload,
|
||||
IWarehouseTransferTransferredPayload,
|
||||
} from '@/interfaces';
|
||||
import { CommandWarehouseTransfer } from './CommandWarehouseTransfer';
|
||||
import { ERRORS } from './constants';
|
||||
import { ServiceError } from '@/exceptions';
|
||||
|
||||
@Service()
|
||||
export class TransferredWarehouseTransfer extends CommandWarehouseTransfer {
|
||||
@Inject()
|
||||
tenancy: HasTenancyService;
|
||||
|
||||
@Inject()
|
||||
uow: UnitOfWork;
|
||||
|
||||
@Inject()
|
||||
eventPublisher: EventPublisher;
|
||||
|
||||
/**
|
||||
* Validate the warehouse transfer not already transferred.
|
||||
* @param {IWarehouseTransfer} warehouseTransfer
|
||||
*/
|
||||
private validateWarehouseTransferNotTransferred = (
|
||||
warehouseTransfer: IWarehouseTransfer
|
||||
) => {
|
||||
if (warehouseTransfer.transferDeliveredAt) {
|
||||
throw new ServiceError(ERRORS.WAREHOUSE_TRANSFER_ALREAD_TRANSFERRED);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate the warehouse transfer should be initiated.
|
||||
* @param {IWarehouseTransfer} warehouseTransfer
|
||||
*/
|
||||
private validateWarehouseTranbsferShouldInitiated = (
|
||||
warehouseTransfer: IWarehouseTransfer
|
||||
) => {
|
||||
if (!warehouseTransfer.transferInitiatedAt) {
|
||||
throw new ServiceError(ERRORS.WAREHOUSE_TRANSFER_NOT_INITIATED);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Transferred warehouse transfer.
|
||||
* @param {number} tenantId
|
||||
* @param {number} warehouseTransferId
|
||||
* @returns {Promise<IWarehouseTransfer>}
|
||||
*/
|
||||
public transferredWarehouseTransfer = async (
|
||||
tenantId: number,
|
||||
warehouseTransferId: number
|
||||
): Promise<IWarehouseTransfer> => {
|
||||
const { WarehouseTransfer } = this.tenancy.models(tenantId);
|
||||
|
||||
// Retrieves the old warehouse transfer transaction.
|
||||
const oldWarehouseTransfer = await WarehouseTransfer.query()
|
||||
.findById(warehouseTransferId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// Validate the warehouse transfer not already transferred.
|
||||
this.validateWarehouseTransferNotTransferred(oldWarehouseTransfer);
|
||||
|
||||
// Validate the warehouse transfer should be initiated.
|
||||
this.validateWarehouseTranbsferShouldInitiated(oldWarehouseTransfer);
|
||||
|
||||
// Edits warehouse transfer transaction under unit-of-work envirement.
|
||||
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => {
|
||||
// Triggers `onWarehouseTransferInitiate` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouseTransfer.onTransfer, {
|
||||
tenantId,
|
||||
oldWarehouseTransfer,
|
||||
trx,
|
||||
} as IWarehouseTransferTransferingPayload);
|
||||
|
||||
// Updates warehouse transfer graph on the storage.
|
||||
const warehouseTransferUpdated = await WarehouseTransfer.query(trx)
|
||||
.findById(warehouseTransferId)
|
||||
.patch({
|
||||
transferDeliveredAt: new Date(),
|
||||
});
|
||||
// Fetches the warehouse transfer with entries.
|
||||
const warehouseTransfer = await WarehouseTransfer.query(trx)
|
||||
.findById(warehouseTransferId)
|
||||
.withGraphFetched('entries');
|
||||
|
||||
// Triggers `onWarehouseTransferEdit` event
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.warehouseTransfer.onTransferred,
|
||||
{
|
||||
tenantId,
|
||||
warehouseTransfer,
|
||||
oldWarehouseTransfer,
|
||||
trx,
|
||||
} as IWarehouseTransferTransferredPayload
|
||||
);
|
||||
return warehouseTransfer;
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
import {
|
||||
ICreateWarehouseTransferDTO,
|
||||
IEditWarehouseTransferDTO,
|
||||
IGetWarehousesTransfersFilterDTO,
|
||||
IWarehouseTransfer,
|
||||
} from '@/interfaces';
|
||||
import { Service, Inject } from 'typedi';
|
||||
import { CreateWarehouseTransfer } from './CreateWarehouseTransfer';
|
||||
import { DeleteWarehouseTransfer } from './DeleteWarehouseTransfer';
|
||||
import { EditWarehouseTransfer } from './EditWarehouseTransfer';
|
||||
import { GetWarehouseTransfer } from './GetWarehouseTransfer';
|
||||
import { GetWarehouseTransfers } from './GetWarehouseTransfers';
|
||||
import { InitiateWarehouseTransfer } from './InitiateWarehouseTransfer';
|
||||
import { TransferredWarehouseTransfer } from './TransferredWarehouseTransfer';
|
||||
|
||||
@Service()
|
||||
export class WarehouseTransferApplication {
|
||||
@Inject()
|
||||
private createWarehouseTransferService: CreateWarehouseTransfer;
|
||||
|
||||
@Inject()
|
||||
private editWarehouseTransferService: EditWarehouseTransfer;
|
||||
|
||||
@Inject()
|
||||
private deleteWarehouseTransferService: DeleteWarehouseTransfer;
|
||||
|
||||
@Inject()
|
||||
private getWarehouseTransferService: GetWarehouseTransfer;
|
||||
|
||||
@Inject()
|
||||
private getWarehousesTransfersService: GetWarehouseTransfers;
|
||||
|
||||
@Inject()
|
||||
private initiateWarehouseTransferService: InitiateWarehouseTransfer;
|
||||
|
||||
@Inject()
|
||||
private transferredWarehouseTransferService: TransferredWarehouseTransfer;
|
||||
|
||||
/**
|
||||
* Creates a warehouse transfer transaction.
|
||||
* @param {number} tenantId
|
||||
* @param {ICreateWarehouseTransferDTO} createWarehouseTransferDTO
|
||||
* @returns {}
|
||||
*/
|
||||
public createWarehouseTransfer = (
|
||||
tenantId: number,
|
||||
createWarehouseTransferDTO: ICreateWarehouseTransferDTO
|
||||
): Promise<IWarehouseTransfer> => {
|
||||
return this.createWarehouseTransferService.createWarehouseTransfer(
|
||||
tenantId,
|
||||
createWarehouseTransferDTO
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Edits warehouse transfer transaction.
|
||||
* @param {number} tenantId -
|
||||
* @param {number} warehouseTransferId - number
|
||||
* @param {IEditWarehouseTransferDTO} editWarehouseTransferDTO
|
||||
*/
|
||||
public editWarehouseTransfer = (
|
||||
tenantId: number,
|
||||
warehouseTransferId: number,
|
||||
editWarehouseTransferDTO: IEditWarehouseTransferDTO
|
||||
): Promise<IWarehouseTransfer> => {
|
||||
return this.editWarehouseTransferService.editWarehouseTransfer(
|
||||
tenantId,
|
||||
warehouseTransferId,
|
||||
editWarehouseTransferDTO
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes warehouse transfer transaction.
|
||||
* @param {number} tenantId
|
||||
* @param {number} warehouseTransferId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public deleteWarehouseTransfer = (
|
||||
tenantId: number,
|
||||
warehouseTransferId: number
|
||||
): Promise<void> => {
|
||||
return this.deleteWarehouseTransferService.deleteWarehouseTransfer(
|
||||
tenantId,
|
||||
warehouseTransferId
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves warehouse transfer transaction.
|
||||
* @param {number} tenantId
|
||||
* @param {number} warehouseTransferId
|
||||
* @returns {Promise<IWarehouseTransfer>}
|
||||
*/
|
||||
public getWarehouseTransfer = (
|
||||
tenantId: number,
|
||||
warehouseTransferId: number
|
||||
): Promise<IWarehouseTransfer> => {
|
||||
return this.getWarehouseTransferService.getWarehouseTransfer(
|
||||
tenantId,
|
||||
warehouseTransferId
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves warehouses trans
|
||||
* @param {number} tenantId
|
||||
* @param {IGetWarehousesTransfersFilterDTO} filterDTO
|
||||
* @returns {Promise<IWarehouseTransfer>}
|
||||
*/
|
||||
public getWarehousesTransfers = (
|
||||
tenantId: number,
|
||||
filterDTO: IGetWarehousesTransfersFilterDTO
|
||||
) => {
|
||||
return this.getWarehousesTransfersService.getWarehouseTransfers(
|
||||
tenantId,
|
||||
filterDTO
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Marks the warehouse transfer order as transfered.
|
||||
* @param {number} tenantId
|
||||
* @param {number} warehouseTransferId
|
||||
* @returns {Promise<IWarehouseTransfer>}
|
||||
*/
|
||||
public transferredWarehouseTransfer = (
|
||||
tenantId: number,
|
||||
warehouseTransferId: number
|
||||
): Promise<IWarehouseTransfer> => {
|
||||
return this.transferredWarehouseTransferService.transferredWarehouseTransfer(
|
||||
tenantId,
|
||||
warehouseTransferId
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Marks the warehouse transfer order as initiated.
|
||||
* @param {number} tenantId
|
||||
* @param {number} warehouseTransferId
|
||||
* @returns {Promise<IWarehouseTransfer>}
|
||||
*/
|
||||
public initiateWarehouseTransfer = (
|
||||
tenantId: number,
|
||||
warehouseTransferId: number
|
||||
): Promise<IWarehouseTransfer> => {
|
||||
return this.initiateWarehouseTransferService.initiateWarehouseTransfer(
|
||||
tenantId,
|
||||
warehouseTransferId
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { Inject, Service } from 'typedi';
|
||||
import AutoIncrementOrdersService from '../../Sales/AutoIncrementOrdersService';
|
||||
|
||||
@Service()
|
||||
export class WarehouseTransferAutoIncrement {
|
||||
@Inject()
|
||||
private autoIncrementOrdersService: AutoIncrementOrdersService;
|
||||
|
||||
/**
|
||||
* Retrieve the next unique invoice number.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @return {string}
|
||||
*/
|
||||
public getNextTransferNumber(tenantId: number): string {
|
||||
return this.autoIncrementOrdersService.getNextTransactionNumber(
|
||||
tenantId,
|
||||
'warehouse_transfers'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the invoice next number.
|
||||
* @param {number} tenantId -
|
||||
*/
|
||||
public incrementNextTransferNumber(tenantId: number) {
|
||||
return this.autoIncrementOrdersService.incrementSettingsNextNumber(
|
||||
tenantId,
|
||||
'warehouse_transfers'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Service, Inject } from 'typedi';
|
||||
import events from '@/subscribers/events';
|
||||
import { IWarehouseTransferCreated } from '@/interfaces';
|
||||
import { WarehouseTransferAutoIncrement } from './WarehouseTransferAutoIncrement';
|
||||
|
||||
@Service()
|
||||
export class WarehouseTransferAutoIncrementSubscriber {
|
||||
@Inject()
|
||||
private warehouseTransferAutoIncrement: WarehouseTransferAutoIncrement;
|
||||
|
||||
/**
|
||||
* Attaches events with handlers.
|
||||
*/
|
||||
public attach = (bus) => {
|
||||
bus.subscribe(
|
||||
events.warehouseTransfer.onCreated,
|
||||
this.incrementTransferAutoIncrementOnCreated
|
||||
);
|
||||
return bus;
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes inventory transactions once warehouse transfer created.
|
||||
* @param {IInventoryTransactionsCreatedPayload} -
|
||||
*/
|
||||
private incrementTransferAutoIncrementOnCreated = async ({
|
||||
tenantId,
|
||||
}: IWarehouseTransferCreated) => {
|
||||
await this.warehouseTransferAutoIncrement.incrementNextTransferNumber(
|
||||
tenantId
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
import { Service, Inject } from 'typedi';
|
||||
import events from '@/subscribers/events';
|
||||
import {
|
||||
IWarehouseTransferEditedPayload,
|
||||
IWarehouseTransferDeletedPayload,
|
||||
IWarehouseTransferCreated,
|
||||
IWarehouseTransferInitiatedPayload,
|
||||
IWarehouseTransferTransferredPayload,
|
||||
} from '@/interfaces';
|
||||
import { WarehouseTransferInventoryTransactions } from './WriteInventoryTransactions';
|
||||
|
||||
@Service()
|
||||
export class WarehouseTransferInventoryTransactionsSubscriber {
|
||||
@Inject()
|
||||
private warehouseTransferInventoryTransactions: WarehouseTransferInventoryTransactions;
|
||||
|
||||
/**
|
||||
* Attaches events with handlers.
|
||||
*/
|
||||
public attach = (bus) => {
|
||||
bus.subscribe(
|
||||
events.warehouseTransfer.onCreated,
|
||||
this.writeInventoryTransactionsOnWarehouseTransferCreated
|
||||
);
|
||||
bus.subscribe(
|
||||
events.warehouseTransfer.onEdited,
|
||||
this.rewriteInventoryTransactionsOnWarehouseTransferEdited
|
||||
);
|
||||
bus.subscribe(
|
||||
events.warehouseTransfer.onDeleted,
|
||||
this.revertInventoryTransactionsOnWarehouseTransferDeleted
|
||||
);
|
||||
bus.subscribe(
|
||||
events.warehouseTransfer.onInitiated,
|
||||
this.writeInventoryTransactionsOnTransferInitiated
|
||||
);
|
||||
bus.subscribe(
|
||||
events.warehouseTransfer.onTransferred,
|
||||
this.writeInventoryTransactionsOnTransferred
|
||||
);
|
||||
return bus;
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes inventory transactions once warehouse transfer created.
|
||||
* @param {IInventoryTransactionsCreatedPayload} -
|
||||
*/
|
||||
private writeInventoryTransactionsOnWarehouseTransferCreated = async ({
|
||||
warehouseTransfer,
|
||||
tenantId,
|
||||
trx,
|
||||
}: IWarehouseTransferCreated) => {
|
||||
// Can't continue if the warehouse transfer is not initiated yet.
|
||||
if (!warehouseTransfer.isInitiated) return;
|
||||
|
||||
// Write all inventory transaction if warehouse transfer initiated and transferred.
|
||||
if (warehouseTransfer.isInitiated && warehouseTransfer.isTransferred) {
|
||||
await this.warehouseTransferInventoryTransactions.writeAllInventoryTransactions(
|
||||
tenantId,
|
||||
warehouseTransfer,
|
||||
false,
|
||||
trx
|
||||
);
|
||||
// Write initiate inventory transaction if warehouse transfer initited and transferred yet.
|
||||
} else if (warehouseTransfer.isInitiated) {
|
||||
await this.warehouseTransferInventoryTransactions.writeInitiateInventoryTransactions(
|
||||
tenantId,
|
||||
warehouseTransfer,
|
||||
false,
|
||||
trx
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Rewrite inventory transactions once warehouse transfer edited.
|
||||
* @param {IWarehouseTransferEditedPayload} -
|
||||
*/
|
||||
private rewriteInventoryTransactionsOnWarehouseTransferEdited = async ({
|
||||
tenantId,
|
||||
warehouseTransfer,
|
||||
trx,
|
||||
}: IWarehouseTransferEditedPayload) => {
|
||||
// Can't continue if the warehouse transfer is not initiated yet.
|
||||
if (!warehouseTransfer.isInitiated) return;
|
||||
|
||||
// Write all inventory transaction if warehouse transfer initiated and transferred.
|
||||
if (warehouseTransfer.isInitiated && warehouseTransfer.isTransferred) {
|
||||
await this.warehouseTransferInventoryTransactions.writeAllInventoryTransactions(
|
||||
tenantId,
|
||||
warehouseTransfer,
|
||||
true,
|
||||
trx
|
||||
);
|
||||
// Write initiate inventory transaction if warehouse transfer initited and transferred yet.
|
||||
} else if (warehouseTransfer.isInitiated) {
|
||||
await this.warehouseTransferInventoryTransactions.writeInitiateInventoryTransactions(
|
||||
tenantId,
|
||||
warehouseTransfer,
|
||||
true,
|
||||
trx
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Reverts inventory transactions once warehouse transfer deleted.
|
||||
* @parma {IWarehouseTransferDeletedPayload} -
|
||||
*/
|
||||
private revertInventoryTransactionsOnWarehouseTransferDeleted = async ({
|
||||
tenantId,
|
||||
oldWarehouseTransfer,
|
||||
trx,
|
||||
}: IWarehouseTransferDeletedPayload) => {
|
||||
await this.warehouseTransferInventoryTransactions.revertInventoryTransactions(
|
||||
tenantId,
|
||||
oldWarehouseTransfer.id,
|
||||
trx
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Write inventory transactions of warehouse transfer once the transfer initiated.
|
||||
* @param {IWarehouseTransferInitiatedPayload}
|
||||
*/
|
||||
private writeInventoryTransactionsOnTransferInitiated = async ({
|
||||
trx,
|
||||
warehouseTransfer,
|
||||
tenantId,
|
||||
}: IWarehouseTransferInitiatedPayload) => {
|
||||
await this.warehouseTransferInventoryTransactions.writeInitiateInventoryTransactions(
|
||||
tenantId,
|
||||
warehouseTransfer,
|
||||
false,
|
||||
trx
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Write inventory transactions of warehouse transfer once the transfer completed.
|
||||
* @param {IWarehouseTransferTransferredPayload}
|
||||
*/
|
||||
private writeInventoryTransactionsOnTransferred = async ({
|
||||
trx,
|
||||
warehouseTransfer,
|
||||
tenantId,
|
||||
}: IWarehouseTransferTransferredPayload) => {
|
||||
await this.warehouseTransferInventoryTransactions.writeTransferredInventoryTransactions(
|
||||
tenantId,
|
||||
warehouseTransfer,
|
||||
false,
|
||||
trx
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { Transformer } from '@/lib/Transformer/Transformer';
|
||||
|
||||
export class WarehouseTransferItemTransformer extends Transformer {
|
||||
/**
|
||||
* Include these attributes to sale invoice object.
|
||||
* @returns {Array}
|
||||
*/
|
||||
public includeAttributes = (): string[] => {
|
||||
return ['formattedQuantity', 'formattedCost', 'formattedTotal'];
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param entry
|
||||
* @returns
|
||||
*/
|
||||
public formattedTotal = (entry) => {
|
||||
return this.formatMoney(entry.total);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param entry
|
||||
* @returns
|
||||
*/
|
||||
public formattedQuantity = (entry) => {
|
||||
return this.formatNumber(entry.quantity);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param entry
|
||||
* @returns
|
||||
*/
|
||||
public formattedCost = (entry) => {
|
||||
return this.formatMoney(entry.cost);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { Transformer } from '@/lib/Transformer/Transformer';
|
||||
import { WarehouseTransferItemTransformer } from './WarehouseTransferItemTransformer';
|
||||
|
||||
export class WarehouseTransferTransformer extends Transformer {
|
||||
/**
|
||||
* Include these attributes to sale invoice object.
|
||||
* @returns {Array}
|
||||
*/
|
||||
public includeAttributes = (): string[] => {
|
||||
return ['formattedDate', 'entries'];
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param transfer
|
||||
* @returns
|
||||
*/
|
||||
protected formattedDate = (transfer) => {
|
||||
return this.formatDate(transfer.date);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
protected entries = (transfer) => {
|
||||
return this.item(transfer.entries, new WarehouseTransferItemTransformer());
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
import { Knex } from 'knex';
|
||||
import {
|
||||
IWarehouseTransfer,
|
||||
IInventoryTransaction,
|
||||
IWarehouseTransferEntry,
|
||||
} from '@/interfaces';
|
||||
import { Inject, Service } from 'typedi';
|
||||
import InventoryService from '@/services/Inventory/Inventory';
|
||||
|
||||
@Service()
|
||||
export class WarehouseTransferInventoryTransactions {
|
||||
@Inject()
|
||||
private inventory: InventoryService;
|
||||
|
||||
/**
|
||||
* Writes all (initiate and transfer) inventory transactions.
|
||||
* @param {number} tenantId
|
||||
* @param {IWarehouseTransfer} warehouseTransfer
|
||||
* @param {Boolean} override
|
||||
* @param {Knex.Transaction} trx - Knex transcation.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public writeAllInventoryTransactions = async (
|
||||
tenantId: number,
|
||||
warehouseTransfer: IWarehouseTransfer,
|
||||
override?: boolean,
|
||||
trx?: Knex.Transaction
|
||||
): Promise<void> => {
|
||||
const inventoryTransactions =
|
||||
this.getWarehouseTransferInventoryTransactions(warehouseTransfer);
|
||||
|
||||
await this.inventory.recordInventoryTransactions(
|
||||
tenantId,
|
||||
inventoryTransactions,
|
||||
override,
|
||||
trx
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes initiate inventory transactions of warehouse transfer transaction.
|
||||
* @param {number} tenantId
|
||||
* @param {IWarehouseTransfer} warehouseTransfer
|
||||
* @param {boolean} override
|
||||
* @param {Knex.Transaction} trx - Knex transaction.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public writeInitiateInventoryTransactions = async (
|
||||
tenantId: number,
|
||||
warehouseTransfer: IWarehouseTransfer,
|
||||
override?: boolean,
|
||||
trx?: Knex.Transaction
|
||||
): Promise<void> => {
|
||||
const inventoryTransactions =
|
||||
this.getWarehouseFromTransferInventoryTransactions(warehouseTransfer);
|
||||
|
||||
await this.inventory.recordInventoryTransactions(
|
||||
tenantId,
|
||||
inventoryTransactions,
|
||||
override,
|
||||
trx
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes transferred inventory transaction of warehouse transfer transaction.
|
||||
* @param {number} tenantId
|
||||
* @param {IWarehouseTransfer} warehouseTransfer
|
||||
* @param {boolean} override
|
||||
* @param {Knex.Transaction} trx - Knex transaction.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public writeTransferredInventoryTransactions = async (
|
||||
tenantId: number,
|
||||
warehouseTransfer: IWarehouseTransfer,
|
||||
override?: boolean,
|
||||
trx?: Knex.Transaction
|
||||
): Promise<void> => {
|
||||
const inventoryTransactions =
|
||||
this.getWarehouseToTransferInventoryTransactions(warehouseTransfer);
|
||||
|
||||
await this.inventory.recordInventoryTransactions(
|
||||
tenantId,
|
||||
inventoryTransactions,
|
||||
override,
|
||||
trx
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Reverts warehouse transfer inventory transactions.
|
||||
* @param {number} tenatnId
|
||||
* @param {number} warehouseTransferId
|
||||
* @param {Knex.Transaction} trx
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public revertInventoryTransactions = async (
|
||||
tenantId: number,
|
||||
warehouseTransferId: number,
|
||||
trx?: Knex.Transaction
|
||||
): Promise<void> => {
|
||||
await this.inventory.deleteInventoryTransactions(
|
||||
tenantId,
|
||||
warehouseTransferId,
|
||||
'WarehouseTransfer',
|
||||
trx
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the inventory transactions of the given warehouse transfer.
|
||||
* @param {IWarehouseTransfer} warehouseTransfer
|
||||
* @returns {IInventoryTransaction[]}
|
||||
*/
|
||||
private getWarehouseFromTransferInventoryTransactions = (
|
||||
warehouseTransfer: IWarehouseTransfer
|
||||
): IInventoryTransaction[] => {
|
||||
const commonEntry = {
|
||||
date: warehouseTransfer.date,
|
||||
transactionType: 'WarehouseTransfer',
|
||||
transactionId: warehouseTransfer.id,
|
||||
};
|
||||
return warehouseTransfer.entries.map((entry: IWarehouseTransferEntry) => ({
|
||||
...commonEntry,
|
||||
entryId: entry.id,
|
||||
itemId: entry.itemId,
|
||||
quantity: entry.quantity,
|
||||
rate: entry.cost,
|
||||
direction: 'OUT',
|
||||
warehouseId: warehouseTransfer.fromWarehouseId,
|
||||
}));
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {IWarehouseTransfer} warehouseTransfer
|
||||
* @returns {IInventoryTransaction[]}
|
||||
*/
|
||||
private getWarehouseToTransferInventoryTransactions = (
|
||||
warehouseTransfer: IWarehouseTransfer
|
||||
): IInventoryTransaction[] => {
|
||||
const commonEntry = {
|
||||
date: warehouseTransfer.date,
|
||||
transactionType: 'WarehouseTransfer',
|
||||
transactionId: warehouseTransfer.id,
|
||||
};
|
||||
return warehouseTransfer.entries.map((entry: IWarehouseTransferEntry) => ({
|
||||
...commonEntry,
|
||||
entryId: entry.id,
|
||||
itemId: entry.itemId,
|
||||
quantity: entry.quantity,
|
||||
rate: entry.cost,
|
||||
direction: 'IN',
|
||||
warehouseId: warehouseTransfer.toWarehouseId,
|
||||
}));
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {IWarehouseTransfer} warehouseTransfer
|
||||
* @returns {IInventoryTransaction[]}
|
||||
*/
|
||||
private getWarehouseTransferInventoryTransactions = (
|
||||
warehouseTransfer: IWarehouseTransfer
|
||||
): IInventoryTransaction[] => {
|
||||
// Retrieve the to inventory transactions of warehouse transfer.
|
||||
const toTransactions =
|
||||
this.getWarehouseToTransferInventoryTransactions(warehouseTransfer);
|
||||
|
||||
// Retrieve the from inventory transactions of warehouse transfer.
|
||||
const fromTransactions =
|
||||
this.getWarehouseFromTransferInventoryTransactions(warehouseTransfer);
|
||||
|
||||
return [...toTransactions, ...fromTransactions];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
export const ERRORS = {
|
||||
WAREHOUSE_TRANSFER_NOT_FOUND: 'WAREHOUSE_TRANSFER_NOT_FOUND',
|
||||
WAREHOUSES_TRANSFER_SHOULD_NOT_BE_SAME:
|
||||
'WAREHOUSES_TRANSFER_SHOULD_NOT_BE_SAME',
|
||||
|
||||
FROM_WAREHOUSE_NOT_FOUND: 'FROM_WAREHOUSE_NOT_FOUND',
|
||||
TO_WAREHOUSE_NOT_FOUND: 'TO_WAREHOUSE_NOT_FOUND',
|
||||
WAREHOUSE_TRANSFER_ITEMS_SHOULD_BE_INVENTORY:
|
||||
'WAREHOUSE_TRANSFER_ITEMS_SHOULD_BE_INVENTORY',
|
||||
|
||||
WAREHOUSE_TRANSFER_ALREAD_TRANSFERRED:
|
||||
'WAREHOUSE_TRANSFER_ALREADY_TRANSFERRED',
|
||||
|
||||
WAREHOUSE_TRANSFER_ALREADY_INITIATED: 'WAREHOUSE_TRANSFER_ALREADY_INITIATED',
|
||||
WAREHOUSE_TRANSFER_NOT_INITIATED: 'WAREHOUSE_TRANSFER_NOT_INITIATED',
|
||||
};
|
||||
|
||||
// Warehouse transfers default views.
|
||||
export const DEFAULT_VIEWS = [
|
||||
{
|
||||
name: 'warehouse_transfer.view.draft.name',
|
||||
slug: 'draft',
|
||||
rolesLogicExpression: '1',
|
||||
roles: [
|
||||
{ index: 1, fieldKey: 'status', comparator: 'equals', value: 'draft' },
|
||||
],
|
||||
columns: [],
|
||||
},
|
||||
{
|
||||
name: 'warehouse_transfer.view.in_transit.name',
|
||||
slug: 'in-transit',
|
||||
rolesLogicExpression: '1',
|
||||
roles: [
|
||||
{
|
||||
index: 1,
|
||||
fieldKey: 'status',
|
||||
comparator: 'equals',
|
||||
value: 'in-transit',
|
||||
},
|
||||
],
|
||||
columns: [],
|
||||
},
|
||||
{
|
||||
name: 'warehouse_transfer.view.transferred.name',
|
||||
slug: 'transferred',
|
||||
rolesLogicExpression: '1',
|
||||
roles: [
|
||||
{
|
||||
index: 1,
|
||||
fieldKey: 'status',
|
||||
comparator: 'equals',
|
||||
value: 'tansferred',
|
||||
},
|
||||
],
|
||||
columns: [],
|
||||
},
|
||||
];
|
||||
Reference in New Issue
Block a user