mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 22:00:31 +00:00
feat(nestjs): migrate to NestJS
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ModelObject } from 'objection';
|
||||
import { IGetWarehousesTransfersFilterDTO } from '@/modules/Warehouses/Warehouse.types';
|
||||
import { CreateWarehouseTransfer } from './commands/CreateWarehouseTransfer';
|
||||
import { DeleteWarehouseTransfer } from './commands/DeleteWarehouseTransfer';
|
||||
import { EditWarehouseTransfer } from './commands/EditWarehouseTransfer';
|
||||
import { GetWarehouseTransfer } from './queries/GetWarehouseTransfer';
|
||||
import { GetWarehouseTransfers } from './queries/GetWarehouseTransfers';
|
||||
import { InitiateWarehouseTransfer } from './commands/InitiateWarehouseTransfer';
|
||||
import { TransferredWarehouseTransfer } from './commands/TransferredWarehouseTransfer';
|
||||
import { WarehouseTransfer } from './models/WarehouseTransfer';
|
||||
import {
|
||||
CreateWarehouseTransferDto,
|
||||
EditWarehouseTransferDto,
|
||||
} from './dtos/WarehouseTransfer.dto';
|
||||
|
||||
@Injectable()
|
||||
export class WarehouseTransferApplication {
|
||||
constructor(
|
||||
private readonly createWarehouseTransferService: CreateWarehouseTransfer,
|
||||
private readonly editWarehouseTransferService: EditWarehouseTransfer,
|
||||
private readonly deleteWarehouseTransferService: DeleteWarehouseTransfer,
|
||||
private readonly getWarehouseTransferService: GetWarehouseTransfer,
|
||||
private readonly getWarehousesTransfersService: GetWarehouseTransfers,
|
||||
private readonly initiateWarehouseTransferService: InitiateWarehouseTransfer,
|
||||
private readonly transferredWarehouseTransferService: TransferredWarehouseTransfer,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Creates a warehouse transfer transaction.
|
||||
* @param {ICreateWarehouseTransferDTO} createWarehouseTransferDTO
|
||||
* @returns {Promise<ModelObject<WarehouseTransfer>>}
|
||||
*/
|
||||
public createWarehouseTransfer = (
|
||||
createWarehouseTransferDTO: CreateWarehouseTransferDto,
|
||||
): Promise<ModelObject<WarehouseTransfer>> => {
|
||||
return this.createWarehouseTransferService.createWarehouseTransfer(
|
||||
createWarehouseTransferDTO,
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Edits warehouse transfer transaction.
|
||||
* @param {number} warehouseTransferId - number
|
||||
* @param {IEditWarehouseTransferDTO} editWarehouseTransferDTO
|
||||
*/
|
||||
public editWarehouseTransfer = (
|
||||
warehouseTransferId: number,
|
||||
editWarehouseTransferDTO: EditWarehouseTransferDto,
|
||||
): Promise<ModelObject<WarehouseTransfer>> => {
|
||||
return this.editWarehouseTransferService.editWarehouseTransfer(
|
||||
warehouseTransferId,
|
||||
editWarehouseTransferDTO,
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes warehouse transfer transaction.
|
||||
* @param {number} warehouseTransferId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public deleteWarehouseTransfer = (
|
||||
warehouseTransferId: number,
|
||||
): Promise<void> => {
|
||||
return this.deleteWarehouseTransferService.deleteWarehouseTransfer(
|
||||
warehouseTransferId,
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves warehouse transfer transaction.
|
||||
* @param {number} warehouseTransferId - Warehouse transfer id.
|
||||
* @returns {Promise<ModelObject<WarehouseTransfer>>}
|
||||
*/
|
||||
public getWarehouseTransfer = (
|
||||
warehouseTransferId: number,
|
||||
): Promise<ModelObject<WarehouseTransfer>> => {
|
||||
return this.getWarehouseTransferService.getWarehouseTransfer(
|
||||
warehouseTransferId,
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves warehouses trans
|
||||
* @param {IGetWarehousesTransfersFilterDTO} filterDTO
|
||||
* @returns {Promise<IWarehouseTransfer>}
|
||||
*/
|
||||
public getWarehousesTransfers = (
|
||||
filterDTO: IGetWarehousesTransfersFilterDTO,
|
||||
) => {
|
||||
return this.getWarehousesTransfersService.getWarehouseTransfers(filterDTO);
|
||||
};
|
||||
|
||||
/**
|
||||
* Marks the warehouse transfer order as transfered.
|
||||
* @param {number} warehouseTransferId
|
||||
* @returns {Promise<IWarehouseTransfer>}
|
||||
*/
|
||||
public transferredWarehouseTransfer = (
|
||||
warehouseTransferId: number,
|
||||
): Promise<ModelObject<WarehouseTransfer>> => {
|
||||
return this.transferredWarehouseTransferService.transferredWarehouseTransfer(
|
||||
warehouseTransferId,
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Marks the warehouse transfer order as initiated.
|
||||
* @param {number} warehouseTransferId
|
||||
* @returns {Promise<ModelObject<WarehouseTransfer>>}
|
||||
*/
|
||||
public initiateWarehouseTransfer = (
|
||||
warehouseTransferId: number,
|
||||
): Promise<ModelObject<WarehouseTransfer>> => {
|
||||
return this.initiateWarehouseTransferService.initiateWarehouseTransfer(
|
||||
warehouseTransferId,
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
import {
|
||||
Controller,
|
||||
Post,
|
||||
Put,
|
||||
Get,
|
||||
Delete,
|
||||
Body,
|
||||
Param,
|
||||
Query,
|
||||
Inject,
|
||||
} from '@nestjs/common';
|
||||
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
|
||||
import { WarehouseTransferApplication } from './WarehouseTransferApplication';
|
||||
import {
|
||||
CreateWarehouseTransferDto,
|
||||
EditWarehouseTransferDto,
|
||||
} from './dtos/WarehouseTransfer.dto';
|
||||
|
||||
@Controller('warehouse-transfers')
|
||||
@ApiTags('warehouse-transfers')
|
||||
export class WarehouseTransfersController {
|
||||
/**
|
||||
* @param {WarehouseTransferApplication} warehouseTransferApplication - Warehouse transfer application.
|
||||
*/
|
||||
constructor(
|
||||
@Inject(WarehouseTransferApplication)
|
||||
private readonly warehouseTransferApplication: WarehouseTransferApplication,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Creates a new warehouse transfer transaction.
|
||||
*/
|
||||
@Post()
|
||||
@ApiOperation({ summary: 'Create a new warehouse transfer transaction.' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description:
|
||||
'The warehouse transfer transaction has been created successfully.',
|
||||
})
|
||||
async createWarehouseTransfer(
|
||||
@Body() createWarehouseTransferDTO: CreateWarehouseTransferDto,
|
||||
) {
|
||||
const warehouse =
|
||||
await this.warehouseTransferApplication.createWarehouseTransfer(
|
||||
createWarehouseTransferDTO,
|
||||
);
|
||||
|
||||
return {
|
||||
id: warehouse.id,
|
||||
message:
|
||||
'The warehouse transfer transaction has been created successfully.',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits warehouse transfer transaction.
|
||||
*/
|
||||
@Post(':id')
|
||||
@ApiOperation({ summary: 'Edit the given warehouse transfer transaction.' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description:
|
||||
'The warehouse transfer transaction has been edited successfully.',
|
||||
})
|
||||
async editWarehouseTransfer(
|
||||
@Param('id') id: number,
|
||||
@Body() editWarehouseTransferDTO: EditWarehouseTransferDto,
|
||||
) {
|
||||
const warehouseTransfer =
|
||||
await this.warehouseTransferApplication.editWarehouseTransfer(
|
||||
id,
|
||||
editWarehouseTransferDTO,
|
||||
);
|
||||
return {
|
||||
id: warehouseTransfer.id,
|
||||
message:
|
||||
'The warehouse transfer transaction has been edited successfully.',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates the warehouse transfer.
|
||||
*/
|
||||
@Put(':id/initiate')
|
||||
@ApiOperation({ summary: 'Initiate the given warehouse transfer.' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'The warehouse transfer has been initiated successfully.',
|
||||
})
|
||||
async initiateTransfer(@Param('id') id: number) {
|
||||
await this.warehouseTransferApplication.initiateWarehouseTransfer(id);
|
||||
|
||||
return {
|
||||
id,
|
||||
message: 'The given warehouse transfer has been initialized.',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the given warehouse transfer as transferred.
|
||||
*/
|
||||
@Put(':id/transferred')
|
||||
@ApiOperation({
|
||||
summary: 'Mark the given warehouse transfer as transferred.',
|
||||
})
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description:
|
||||
'The warehouse transfer has been marked as transferred successfully.',
|
||||
})
|
||||
async deliverTransfer(@Param('id') id: number) {
|
||||
await this.warehouseTransferApplication.transferredWarehouseTransfer(id);
|
||||
|
||||
return {
|
||||
id,
|
||||
message: 'The given warehouse transfer has been delivered.',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves warehouse transfer transactions with pagination.
|
||||
*/
|
||||
@Get()
|
||||
@ApiOperation({
|
||||
summary: 'Retrieve warehouse transfer transactions with pagination.',
|
||||
})
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description:
|
||||
'The warehouse transfer transactions have been retrieved successfully.',
|
||||
})
|
||||
async getWarehousesTransfers(@Query() query: any) {
|
||||
const { warehousesTransfers, pagination, filter } =
|
||||
await this.warehouseTransferApplication.getWarehousesTransfers(query);
|
||||
|
||||
return {
|
||||
data: warehousesTransfers,
|
||||
pagination,
|
||||
filter,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves warehouse transfer transaction details.
|
||||
*/
|
||||
@Get(':id')
|
||||
@ApiOperation({ summary: 'Retrieve warehouse transfer transaction details.' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description:
|
||||
'The warehouse transfer transaction details have been retrieved successfully.',
|
||||
})
|
||||
async getWarehouseTransfer(@Param('id') id: number) {
|
||||
const warehouseTransfer =
|
||||
await this.warehouseTransferApplication.getWarehouseTransfer(id);
|
||||
|
||||
return { data: warehouseTransfer };
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the given warehouse transfer transaction.
|
||||
*/
|
||||
@Delete(':id')
|
||||
@ApiOperation({ summary: 'Delete the given warehouse transfer transaction.' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description:
|
||||
'The warehouse transfer transaction has been deleted successfully.',
|
||||
})
|
||||
async deleteWarehouseTransfer(@Param('id') id: number) {
|
||||
await this.warehouseTransferApplication.deleteWarehouseTransfer(id);
|
||||
|
||||
return {
|
||||
message:
|
||||
'The warehouse transfer transaction has been deleted successfully.',
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { CreateWarehouseTransfer } from './commands/CreateWarehouseTransfer';
|
||||
import { EditWarehouseTransfer } from './commands/EditWarehouseTransfer';
|
||||
import { DeleteWarehouseTransfer } from './commands/DeleteWarehouseTransfer';
|
||||
import { GetWarehouseTransfer } from './queries/GetWarehouseTransfer';
|
||||
import { GetWarehouseTransfers } from './queries/GetWarehouseTransfers';
|
||||
import { WarehouseTransferApplication } from './WarehouseTransferApplication';
|
||||
import { WarehouseTransfersController } from './WarehouseTransfers.controller';
|
||||
import { WarehouseTransferInventoryTransactions } from './commands/WarehouseTransferWriteInventoryTransactions';
|
||||
import { WarehouseTransferAutoIncrement } from './commands/WarehouseTransferAutoIncrement';
|
||||
import { WarehouseTransferAutoIncrementSubscriber } from './susbcribers/WarehouseTransferAutoIncrementSubscriber';
|
||||
import { WarehouseTransferInventoryTransactionsSubscriber } from './susbcribers/WarehouseTransferInventoryTransactionsSubscriber';
|
||||
import { InitiateWarehouseTransfer } from './commands/InitiateWarehouseTransfer';
|
||||
import { TransferredWarehouseTransfer } from './commands/TransferredWarehouseTransfer';
|
||||
import { CommandWarehouseTransfer } from './commands/CommandWarehouseTransfer';
|
||||
import { ItemsModule } from '../Items/items.module';
|
||||
import { InventoryCostModule } from '../InventoryCost/InventoryCost.module';
|
||||
import { RegisterTenancyModel } from '../Tenancy/TenancyModels/Tenancy.module';
|
||||
import { WarehouseTransfer } from './models/WarehouseTransfer';
|
||||
import { WarehouseTransferEntry } from './models/WarehouseTransferEntry';
|
||||
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
||||
import { AutoIncrementOrdersModule } from '../AutoIncrementOrders/AutoIncrementOrders.module';
|
||||
|
||||
const models = [
|
||||
RegisterTenancyModel(WarehouseTransfer),
|
||||
RegisterTenancyModel(WarehouseTransferEntry),
|
||||
];
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ItemsModule,
|
||||
InventoryCostModule,
|
||||
DynamicListModule,
|
||||
AutoIncrementOrdersModule,
|
||||
...models,
|
||||
],
|
||||
providers: [
|
||||
WarehouseTransferApplication,
|
||||
CreateWarehouseTransfer,
|
||||
EditWarehouseTransfer,
|
||||
DeleteWarehouseTransfer,
|
||||
GetWarehouseTransfer,
|
||||
GetWarehouseTransfers,
|
||||
WarehouseTransferInventoryTransactions,
|
||||
WarehouseTransferAutoIncrement,
|
||||
WarehouseTransferAutoIncrementSubscriber,
|
||||
WarehouseTransferInventoryTransactionsSubscriber,
|
||||
TransferredWarehouseTransfer,
|
||||
InitiateWarehouseTransfer,
|
||||
CommandWarehouseTransfer,
|
||||
],
|
||||
exports: [...models],
|
||||
controllers: [WarehouseTransfersController],
|
||||
})
|
||||
export class WarehousesTransfersModule {}
|
||||
@@ -0,0 +1,113 @@
|
||||
import { ModelObject } from 'objection';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { ERRORS } from '../constants';
|
||||
import { WarehouseTransfer } from '../models/WarehouseTransfer';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||
import { Item } from '@/modules/Items/models/Item';
|
||||
import { Warehouse } from '@/modules/Warehouses/models/Warehouse.model';
|
||||
import {
|
||||
CreateWarehouseTransferDto,
|
||||
EditWarehouseTransferDto,
|
||||
} from '../dtos/WarehouseTransfer.dto';
|
||||
|
||||
@Injectable()
|
||||
export class CommandWarehouseTransfer {
|
||||
constructor(
|
||||
@Inject(Warehouse.name)
|
||||
private readonly warehouseModel: TenantModelProxy<typeof Warehouse>,
|
||||
|
||||
@Inject(WarehouseTransfer.name)
|
||||
private readonly warehouseTransferModel: TenantModelProxy<
|
||||
typeof WarehouseTransfer
|
||||
>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Throws error if warehouse transfer not found.
|
||||
* @param {WarehouseTransfer} warehouseTransfer
|
||||
*/
|
||||
throwIfTransferNotFound = (warehouseTransfer: WarehouseTransfer) => {
|
||||
if (!warehouseTransfer) {
|
||||
throw new ServiceError(ERRORS.WAREHOUSE_TRANSFER_NOT_FOUND);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the warehouse transfer or throw not found service error.
|
||||
* @param {number} branchId
|
||||
* @returns {Promise<WarehouseTransfer>}
|
||||
*/
|
||||
async getWarehouseTransferOrThrowNotFound(branchId: number) {
|
||||
const foundTransfer = await this.warehouseTransferModel()
|
||||
.query()
|
||||
.findById(branchId);
|
||||
|
||||
if (!foundTransfer) {
|
||||
throw new ServiceError(ERRORS.WAREHOUSE_TRANSFER_NOT_FOUND);
|
||||
}
|
||||
return foundTransfer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the from/to warehouses should not be the same.
|
||||
* @param {ICreateWarehouseTransferDTO|IEditWarehouseTransferDTO} warehouseTransferDTO
|
||||
*/
|
||||
validateWarehouseFromToNotSame(
|
||||
warehouseTransferDTO: CreateWarehouseTransferDto | EditWarehouseTransferDto,
|
||||
) {
|
||||
if (
|
||||
warehouseTransferDTO.fromWarehouseId ===
|
||||
warehouseTransferDTO.toWarehouseId
|
||||
) {
|
||||
throw new ServiceError(ERRORS.WAREHOUSES_TRANSFER_SHOULD_NOT_BE_SAME);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates entries items should be inventory.
|
||||
* @param {ModelObject<Item>[]} items - Items.
|
||||
* @returns {void}
|
||||
*/
|
||||
validateItemsShouldBeInventory = (items: ModelObject<Item>[]): void => {
|
||||
const nonInventoryItems = items.filter((item) => item.type !== 'inventory');
|
||||
|
||||
if (nonInventoryItems.length > 0) {
|
||||
throw new ServiceError(
|
||||
ERRORS.WAREHOUSE_TRANSFER_ITEMS_SHOULD_BE_INVENTORY,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the to warehouse or throw not found service error.
|
||||
* @param {number} fromWarehouseId - From warehouse id.
|
||||
* @returns {Promise<Warehouse>}
|
||||
*/
|
||||
getToWarehouseOrThrow = async (fromWarehouseId: number) => {
|
||||
const warehouse = await this.warehouseModel()
|
||||
.query()
|
||||
.findById(fromWarehouseId);
|
||||
|
||||
if (!warehouse) {
|
||||
throw new ServiceError(ERRORS.TO_WAREHOUSE_NOT_FOUND);
|
||||
}
|
||||
return warehouse;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number} fromWarehouseId
|
||||
* @returns
|
||||
*/
|
||||
getFromWarehouseOrThrow = async (fromWarehouseId: number) => {
|
||||
const warehouse = await this.warehouseModel()
|
||||
.query()
|
||||
.findById(fromWarehouseId);
|
||||
|
||||
if (!warehouse) {
|
||||
throw new ServiceError(ERRORS.FROM_WAREHOUSE_NOT_FOUND);
|
||||
}
|
||||
return warehouse;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
import { Knex } from 'knex';
|
||||
import { omit, get, isNumber } from 'lodash';
|
||||
import * as R from 'ramda';
|
||||
import {
|
||||
ICreateWarehouseTransferDTO,
|
||||
IWarehouseTransferCreate,
|
||||
IWarehouseTransferCreated,
|
||||
IWarehouseTransferEntryDTO,
|
||||
} from '@/modules/Warehouses/Warehouse.types';
|
||||
import { CommandWarehouseTransfer } from './CommandWarehouseTransfer';
|
||||
import { WarehouseTransferAutoIncrement } from './WarehouseTransferAutoIncrement';
|
||||
import { WarehouseTransfer } from '../models/WarehouseTransfer';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { ItemsEntriesService } from '@/modules/Items/ItemsEntries.service';
|
||||
import { InventoryItemCostService } from '@/modules/InventoryCost/commands/InventoryCosts.service';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { events } from '@/common/events/events';
|
||||
import { IInventoryItemCostMeta } from '@/modules/InventoryCost/types/InventoryCost.types';
|
||||
import { ModelObject } from 'objection';
|
||||
import { WarehouseTransferEntry } from '../models/WarehouseTransferEntry';
|
||||
import {
|
||||
CreateWarehouseTransferDto,
|
||||
WarehouseTransferEntryDto,
|
||||
} from '../dtos/WarehouseTransfer.dto';
|
||||
|
||||
@Injectable()
|
||||
export class CreateWarehouseTransfer {
|
||||
/**
|
||||
* @param {UnitOfWork} uow - Unit of work.
|
||||
* @param {EventEmitter2} eventPublisher - Event publisher.
|
||||
* @param {ItemsEntriesService} itemsEntries - Items entries service.
|
||||
* @param {InventoryItemCostService} inventoryItemCost - Inventory item cost service.
|
||||
* @param {WarehouseTransferAutoIncrement} autoIncrementOrders - Warehouse transfer auto increment.
|
||||
* @param {CommandWarehouseTransfer} commandWarehouseTransfer - Command warehouse transfer.
|
||||
* @param {TenantModelProxy<typeof WarehouseTransfer>} warehouseTransferModel - Warehouse transfer model.
|
||||
*/
|
||||
constructor(
|
||||
private readonly uow: UnitOfWork,
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
private readonly itemsEntries: ItemsEntriesService,
|
||||
private readonly inventoryItemCost: InventoryItemCostService,
|
||||
private readonly autoIncrementOrders: WarehouseTransferAutoIncrement,
|
||||
private readonly commandWarehouseTransfer: CommandWarehouseTransfer,
|
||||
|
||||
@Inject(WarehouseTransfer.name)
|
||||
private readonly warehouseTransferModel: TenantModelProxy<
|
||||
typeof WarehouseTransfer
|
||||
>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Transformes the givne new warehouse transfer DTO to model.
|
||||
* @param {ICreateWarehouseTransferDTO} warehouseTransferDTO
|
||||
* @returns {IWarehouseTransfer}
|
||||
*/
|
||||
private transformDTOToModel = async (
|
||||
warehouseTransferDTO: CreateWarehouseTransferDto,
|
||||
): Promise<ModelObject<WarehouseTransfer>> => {
|
||||
const entries = await this.transformEntries(
|
||||
warehouseTransferDTO,
|
||||
warehouseTransferDTO.entries,
|
||||
);
|
||||
// Retrieves the auto-increment the warehouse transfer number.
|
||||
const autoNextNumber = this.autoIncrementOrders.getNextTransferNumber();
|
||||
|
||||
// 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: WarehouseTransferEntryDto,
|
||||
): WarehouseTransferEntryDto => {
|
||||
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 {ICreateWarehouseTransferDTO} warehouseTransferDTO
|
||||
* @param {IWarehouseTransferEntryDTO[]} entries
|
||||
* @returns {Promise<IWarehouseTransferEntryDTO[]>}
|
||||
*/
|
||||
public transformEntries = async (
|
||||
warehouseTransferDTO: CreateWarehouseTransferDto,
|
||||
entries: WarehouseTransferEntryDto[],
|
||||
): Promise<ModelObject<WarehouseTransferEntry>[]> => {
|
||||
const inventoryItemsIds = warehouseTransferDTO.entries.map((e) => e.itemId);
|
||||
|
||||
// Retrieves the inventory items valuation map.
|
||||
const inventoryItemsCostMap =
|
||||
await this.inventoryItemCost.getItemsInventoryValuation(
|
||||
inventoryItemsIds,
|
||||
warehouseTransferDTO.date,
|
||||
);
|
||||
// Assoc average cost to the entry.
|
||||
const assocAverageCost = this.transformEntryAssocAverageCost(
|
||||
inventoryItemsCostMap,
|
||||
);
|
||||
return entries.map((entry) => assocAverageCost(entry));
|
||||
};
|
||||
|
||||
/**
|
||||
* Authorize warehouse transfer before creating.
|
||||
* @param {CreateWarehouseTransferDto} warehouseTransferDTO - Warehouse transfer DTO.
|
||||
*/
|
||||
public authorize = async (
|
||||
warehouseTransferDTO: CreateWarehouseTransferDto,
|
||||
) => {
|
||||
// Validate warehouse from and to should not be the same.
|
||||
this.commandWarehouseTransfer.validateWarehouseFromToNotSame(
|
||||
warehouseTransferDTO,
|
||||
);
|
||||
// Retrieves the from warehouse or throw not found service error.
|
||||
const fromWarehouse =
|
||||
await this.commandWarehouseTransfer.getFromWarehouseOrThrow(
|
||||
warehouseTransferDTO.fromWarehouseId,
|
||||
);
|
||||
// Retrieves the to warehouse or throw not found service error.
|
||||
const toWarehouse =
|
||||
await this.commandWarehouseTransfer.getToWarehouseOrThrow(
|
||||
warehouseTransferDTO.toWarehouseId,
|
||||
);
|
||||
// Validates the not found entries items ids.
|
||||
const items = await this.itemsEntries.validateItemsIdsExistance(
|
||||
warehouseTransferDTO.entries,
|
||||
);
|
||||
// Validate the items entries should be inventory type.
|
||||
this.commandWarehouseTransfer.validateItemsShouldBeInventory(items);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new warehouse transfer transaction.
|
||||
* @param {ICreateWarehouseTransferDTO} warehouseDTO -
|
||||
* @returns {Promise<ModelObject<WarehouseTransfer>>}
|
||||
*/
|
||||
public createWarehouseTransfer = async (
|
||||
warehouseTransferDTO: CreateWarehouseTransferDto,
|
||||
): Promise<ModelObject<WarehouseTransfer>> => {
|
||||
// Authorize warehouse transfer before creating.
|
||||
await this.authorize(warehouseTransferDTO);
|
||||
|
||||
// Transformes the warehouse transfer DTO to model.
|
||||
const warehouseTransferModel =
|
||||
await this.transformDTOToModel(warehouseTransferDTO);
|
||||
|
||||
// Create warehouse transfer under unit-of-work.
|
||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||
// Triggers `onWarehouseTransferCreate` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouseTransfer.onCreate, {
|
||||
trx,
|
||||
warehouseTransferDTO,
|
||||
} as IWarehouseTransferCreate);
|
||||
|
||||
// Stores the warehouse transfer transaction graph to the storage.
|
||||
const warehouseTransfer = await this.warehouseTransferModel()
|
||||
.query(trx)
|
||||
.upsertGraphAndFetch({
|
||||
...warehouseTransferModel,
|
||||
});
|
||||
// Triggers `onWarehouseTransferCreated` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouseTransfer.onCreated, {
|
||||
trx,
|
||||
warehouseTransfer,
|
||||
warehouseTransferDTO,
|
||||
} as IWarehouseTransferCreated);
|
||||
|
||||
return warehouseTransfer;
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import { Knex } from 'knex';
|
||||
import {
|
||||
IWarehouseTransferDeletedPayload,
|
||||
IWarehouseTransferDeletePayload,
|
||||
} from '@/modules/Warehouses/Warehouse.types';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { events } from '@/common/events/events';
|
||||
import { WarehouseTransfer } from '../models/WarehouseTransfer';
|
||||
import { WarehouseTransferEntry } from '../models/WarehouseTransferEntry';
|
||||
|
||||
@Injectable()
|
||||
export class DeleteWarehouseTransfer {
|
||||
/**
|
||||
* @param {UnitOfWork} uow - Unit of work service.
|
||||
* @param {EventEmitter2} eventPublisher - Event emitter service.
|
||||
* @param {TenantModelProxy<WarehouseTransfer>} warehouseTransferModel - Warehouse transfer model.
|
||||
* @param {TenantModelProxy<WarehouseTransferEntry>} warehouseTransferEntryModel - Warehouse transfer entry model.
|
||||
*/
|
||||
constructor(
|
||||
private readonly uow: UnitOfWork,
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
|
||||
@Inject(WarehouseTransfer.name)
|
||||
private readonly warehouseTransferModel: TenantModelProxy<
|
||||
typeof WarehouseTransfer
|
||||
>,
|
||||
@Inject(WarehouseTransferEntry.name)
|
||||
private readonly warehouseTransferEntryModel: TenantModelProxy<
|
||||
typeof WarehouseTransferEntry
|
||||
>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Deletes warehouse transfer transaction.
|
||||
* @param {number} warehouseTransferId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public deleteWarehouseTransfer = async (
|
||||
warehouseTransferId: number,
|
||||
): Promise<void> => {
|
||||
// Retrieve the old warehouse transfer or throw not found service error.
|
||||
const oldWarehouseTransfer = await this.warehouseTransferModel()
|
||||
.query()
|
||||
.findById(warehouseTransferId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// Deletes the warehouse transfer under unit-of-work envirement.
|
||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||
// Triggers `onWarehouseTransferCreate` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouseTransfer.onDelete, {
|
||||
oldWarehouseTransfer,
|
||||
trx,
|
||||
} as IWarehouseTransferDeletePayload);
|
||||
|
||||
// Delete warehouse transfer entries.
|
||||
await this.warehouseTransferEntryModel()
|
||||
.query(trx)
|
||||
.where('warehouseTransferId', warehouseTransferId)
|
||||
.delete();
|
||||
|
||||
// Delete warehouse transfer.
|
||||
await this.warehouseTransferModel()
|
||||
.query(trx)
|
||||
.findById(warehouseTransferId)
|
||||
.delete();
|
||||
|
||||
// Triggers `onWarehouseTransferDeleted` event
|
||||
await this.eventPublisher.emitAsync(events.warehouseTransfer.onDeleted, {
|
||||
oldWarehouseTransfer,
|
||||
trx,
|
||||
} as IWarehouseTransferDeletedPayload);
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
import { Knex } from 'knex';
|
||||
import {
|
||||
IEditWarehouseTransferDTO,
|
||||
IWarehouseTransferEditPayload,
|
||||
IWarehouseTransferEditedPayload,
|
||||
} from '@/modules/Warehouses/Warehouse.types';
|
||||
import { CommandWarehouseTransfer } from './CommandWarehouseTransfer';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { TenantModelProxy } from '../../System/models/TenantBaseModel';
|
||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { WarehouseTransfer } from '../models/WarehouseTransfer';
|
||||
import { ItemsEntriesService } from '@/modules/Items/ItemsEntries.service';
|
||||
import { ModelObject } from 'objection';
|
||||
import { EditWarehouseTransferDto } from '../dtos/WarehouseTransfer.dto';
|
||||
|
||||
@Injectable()
|
||||
export class EditWarehouseTransfer {
|
||||
/**
|
||||
* @param {UnitOfWork} uow - Unit of work service.
|
||||
* @param {EventEmitter2} eventPublisher - Event emitter service.
|
||||
* @param {CommandWarehouseTransfer} commandWarehouseTransfer - Command warehouse transfer service.
|
||||
* @param {ItemsEntriesService} itemsEntries - Items entries service.
|
||||
* @param {TenantModelProxy<WarehouseTransfer>} warehouseTransferModel - Warehouse transfer model.
|
||||
*/
|
||||
constructor(
|
||||
private readonly uow: UnitOfWork,
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
private readonly commandWarehouseTransfer: CommandWarehouseTransfer,
|
||||
private readonly itemsEntries: ItemsEntriesService,
|
||||
|
||||
@Inject(WarehouseTransfer.name)
|
||||
private readonly warehouseTransferModel: TenantModelProxy<
|
||||
typeof WarehouseTransfer
|
||||
>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Edits warehouse transfer.
|
||||
* @param {number} warehouseTransferId - Warehouse transfer id.
|
||||
* @param {IEditWarehouseTransferDTO} editWarehouseDTO -
|
||||
* @returns {Promise<ModelObject<WarehouseTransfer>>}
|
||||
*/
|
||||
public editWarehouseTransfer = async (
|
||||
warehouseTransferId: number,
|
||||
editWarehouseDTO: EditWarehouseTransferDto,
|
||||
): Promise<ModelObject<WarehouseTransfer>> => {
|
||||
// Retrieves the old warehouse transfer transaction.
|
||||
const oldWarehouseTransfer = await this.warehouseTransferModel()
|
||||
.query()
|
||||
.findById(warehouseTransferId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// Validate warehouse from and to should not be the same.
|
||||
this.commandWarehouseTransfer.validateWarehouseFromToNotSame(
|
||||
editWarehouseDTO,
|
||||
);
|
||||
// Retrieves the from warehouse or throw not found service error.
|
||||
const fromWarehouse =
|
||||
await this.commandWarehouseTransfer.getFromWarehouseOrThrow(
|
||||
editWarehouseDTO.fromWarehouseId,
|
||||
);
|
||||
// Retrieves the to warehouse or throw not found service error.
|
||||
const toWarehouse =
|
||||
await this.commandWarehouseTransfer.getToWarehouseOrThrow(
|
||||
editWarehouseDTO.toWarehouseId,
|
||||
);
|
||||
// Validates the not found entries items ids.
|
||||
const items = await this.itemsEntries.validateItemsIdsExistance(
|
||||
editWarehouseDTO.entries,
|
||||
);
|
||||
// Validate the items entries should be inventory type.
|
||||
this.commandWarehouseTransfer.validateItemsShouldBeInventory(items);
|
||||
|
||||
// Edits warehouse transfer transaction under unit-of-work envirement.
|
||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||
// Triggers `onWarehouseTransferEdit` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouseTransfer.onEdit, {
|
||||
editWarehouseDTO,
|
||||
oldWarehouseTransfer,
|
||||
trx,
|
||||
} as IWarehouseTransferEditPayload);
|
||||
|
||||
// Updates warehouse transfer graph on the storage.
|
||||
const warehouseTransfer = await this.warehouseTransferModel()
|
||||
.query(trx)
|
||||
.upsertGraphAndFetch({
|
||||
id: warehouseTransferId,
|
||||
...editWarehouseDTO,
|
||||
});
|
||||
// Triggers `onWarehouseTransferEdit` event
|
||||
await this.eventPublisher.emitAsync(events.warehouseTransfer.onEdited, {
|
||||
editWarehouseDTO,
|
||||
warehouseTransfer,
|
||||
oldWarehouseTransfer,
|
||||
trx,
|
||||
} as IWarehouseTransferEditedPayload);
|
||||
|
||||
return warehouseTransfer;
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
import { Knex } from 'knex';
|
||||
import {
|
||||
IWarehouseTransferEditedPayload,
|
||||
IWarehouseTransferInitiatedPayload,
|
||||
IWarehouseTransferInitiatePayload,
|
||||
} from '@/modules/Warehouses/Warehouse.types';
|
||||
import { ERRORS } from '../constants';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { WarehouseTransfer } from '../models/WarehouseTransfer';
|
||||
import { Inject } from '@nestjs/common';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||
import { events } from '@/common/events/events';
|
||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { ModelObject } from 'objection';
|
||||
|
||||
@Injectable()
|
||||
export class InitiateWarehouseTransfer {
|
||||
constructor(
|
||||
private readonly uow: UnitOfWork,
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
|
||||
@Inject(WarehouseTransfer.name)
|
||||
private readonly warehouseTransferModel: TenantModelProxy<
|
||||
typeof WarehouseTransfer
|
||||
>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate the given warehouse transfer not already initiated.
|
||||
* @param {IWarehouseTransfer} warehouseTransfer
|
||||
*/
|
||||
private validateWarehouseTransferNotAlreadyInitiated = (
|
||||
warehouseTransfer: ModelObject<WarehouseTransfer>,
|
||||
) => {
|
||||
if (warehouseTransfer.transferInitiatedAt) {
|
||||
throw new ServiceError(ERRORS.WAREHOUSE_TRANSFER_ALREADY_INITIATED);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Initiate warehouse transfer.
|
||||
* @param {number} warehouseTransferId
|
||||
* @returns {Promise<IWarehouseTransfer>}
|
||||
*/
|
||||
public initiateWarehouseTransfer = async (
|
||||
warehouseTransferId: number,
|
||||
): Promise<ModelObject<WarehouseTransfer>> => {
|
||||
// Retrieves the old warehouse transfer transaction.
|
||||
const oldWarehouseTransfer = await this.warehouseTransferModel()
|
||||
.query()
|
||||
.findById(warehouseTransferId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// Validate the given warehouse transfer not already initiated.
|
||||
this.validateWarehouseTransferNotAlreadyInitiated(oldWarehouseTransfer);
|
||||
|
||||
// Edits warehouse transfer transaction under unit-of-work envirement.
|
||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||
// Triggers `onWarehouseTransferInitiate` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouseTransfer.onInitiate, {
|
||||
oldWarehouseTransfer,
|
||||
trx,
|
||||
} as IWarehouseTransferInitiatePayload);
|
||||
|
||||
// Updates warehouse transfer graph on the storage.
|
||||
const warehouseTransferUpdated = await this.warehouseTransferModel()
|
||||
.query(trx)
|
||||
.findById(warehouseTransferId)
|
||||
.patch({
|
||||
transferInitiatedAt: new Date(),
|
||||
});
|
||||
// Fetches the warehouse transfer with entries.
|
||||
const warehouseTransfer = await this.warehouseTransferModel()
|
||||
.query(trx)
|
||||
.findById(warehouseTransferId)
|
||||
.withGraphFetched('entries');
|
||||
|
||||
// Triggers `onWarehouseTransferEdit` event
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.warehouseTransfer.onInitiated,
|
||||
{
|
||||
warehouseTransfer,
|
||||
oldWarehouseTransfer,
|
||||
trx,
|
||||
} as IWarehouseTransferInitiatedPayload,
|
||||
);
|
||||
return warehouseTransfer;
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
import { Knex } from 'knex';
|
||||
import {
|
||||
IWarehouseTransferTransferingPayload,
|
||||
IWarehouseTransferTransferredPayload,
|
||||
} from '@/modules/Warehouses/Warehouse.types';
|
||||
import { CommandWarehouseTransfer } from './CommandWarehouseTransfer';
|
||||
import { ERRORS } from '../constants';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { UnitOfWork } from '../../Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { TenantModelProxy } from '../../System/models/TenantBaseModel';
|
||||
import { WarehouseTransfer } from '../models/WarehouseTransfer';
|
||||
import { ServiceError } from '../../Items/ServiceError';
|
||||
import { events } from '@/common/events/events';
|
||||
import { ModelObject } from 'objection';
|
||||
|
||||
@Injectable()
|
||||
export class TransferredWarehouseTransfer {
|
||||
constructor(
|
||||
private readonly uow: UnitOfWork,
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
|
||||
@Inject(WarehouseTransfer.name)
|
||||
private readonly warehouseTransferModel: TenantModelProxy<
|
||||
typeof WarehouseTransfer
|
||||
>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Validate the warehouse transfer not already transferred.
|
||||
* @param {IWarehouseTransfer} warehouseTransfer
|
||||
*/
|
||||
private validateWarehouseTransferNotTransferred = (
|
||||
warehouseTransfer: ModelObject<WarehouseTransfer>,
|
||||
) => {
|
||||
if (warehouseTransfer.transferDeliveredAt) {
|
||||
throw new ServiceError(ERRORS.WAREHOUSE_TRANSFER_ALREADY_TRANSFERRED);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate the warehouse transfer should be initiated.
|
||||
* @param {IWarehouseTransfer} warehouseTransfer
|
||||
*/
|
||||
private validateWarehouseTranbsferShouldInitiated = (
|
||||
warehouseTransfer: ModelObject<WarehouseTransfer>,
|
||||
) => {
|
||||
if (!warehouseTransfer.transferInitiatedAt) {
|
||||
throw new ServiceError(ERRORS.WAREHOUSE_TRANSFER_NOT_INITIATED);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Transferred warehouse transfer.
|
||||
* @param {number} warehouseTransferId
|
||||
* @returns {Promise<IWarehouseTransfer>}
|
||||
*/
|
||||
public transferredWarehouseTransfer = async (
|
||||
warehouseTransferId: number,
|
||||
): Promise<ModelObject<WarehouseTransfer>> => {
|
||||
// Retrieves the old warehouse transfer transaction.
|
||||
const oldWarehouseTransfer = await this.warehouseTransferModel()
|
||||
.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(async (trx: Knex.Transaction) => {
|
||||
// Triggers `onWarehouseTransferInitiate` event.
|
||||
await this.eventPublisher.emitAsync(events.warehouseTransfer.onTransfer, {
|
||||
oldWarehouseTransfer,
|
||||
trx,
|
||||
} as IWarehouseTransferTransferingPayload);
|
||||
|
||||
// Updates warehouse transfer graph on the storage.
|
||||
const warehouseTransferUpdated = await this.warehouseTransferModel()
|
||||
.query(trx)
|
||||
.findById(warehouseTransferId)
|
||||
.patch({
|
||||
transferDeliveredAt: new Date(),
|
||||
});
|
||||
// Fetches the warehouse transfer with entries.
|
||||
const warehouseTransfer = await this.warehouseTransferModel()
|
||||
.query(trx)
|
||||
.findById(warehouseTransferId)
|
||||
.withGraphFetched('entries');
|
||||
|
||||
// Triggers `onWarehouseTransferEdit` event
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.warehouseTransfer.onTransferred,
|
||||
{
|
||||
warehouseTransfer,
|
||||
oldWarehouseTransfer,
|
||||
trx,
|
||||
} as IWarehouseTransferTransferredPayload,
|
||||
);
|
||||
return warehouseTransfer;
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { AutoIncrementOrdersService } from '@/modules/AutoIncrementOrders/AutoIncrementOrders.service';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class WarehouseTransferAutoIncrement {
|
||||
constructor(
|
||||
private readonly autoIncrementOrdersService: AutoIncrementOrdersService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieve the next unique invoice number.
|
||||
* @return {Promise<string>}
|
||||
*/
|
||||
public getNextTransferNumber(): Promise<string> {
|
||||
return this.autoIncrementOrdersService.getNextTransactionNumber(
|
||||
'warehouse_transfers',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the invoice next number.
|
||||
*/
|
||||
public incrementNextTransferNumber() {
|
||||
return this.autoIncrementOrdersService.incrementSettingsNextNumber(
|
||||
'warehouse_transfers',
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
import { Knex } from 'knex';
|
||||
import { IWarehouseTransferEntry } from '@/modules/Warehouses/Warehouse.types';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InventoryTransactionsService } from '../../InventoryCost/commands/InventoryTransactions.service';
|
||||
import { ModelObject } from 'objection';
|
||||
import { WarehouseTransfer } from '../models/WarehouseTransfer';
|
||||
import { InventoryTransaction } from '../../InventoryCost/models/InventoryTransaction';
|
||||
import { WarehouseTransferEntry } from '../models/WarehouseTransferEntry';
|
||||
|
||||
@Injectable()
|
||||
export class WarehouseTransferInventoryTransactions {
|
||||
constructor(private readonly inventory: InventoryTransactionsService) {}
|
||||
|
||||
/**
|
||||
* Writes all (initiate and transfer) inventory transactions.
|
||||
* @param {ModelObject<WarehouseTransfer>} warehouseTransfer - Warehouse transfer.
|
||||
* @param {Boolean} override - Override the inventory transactions.
|
||||
* @param {Knex.Transaction} trx - Knex transcation.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public writeAllInventoryTransactions = async (
|
||||
warehouseTransfer: ModelObject<WarehouseTransfer>,
|
||||
override?: boolean,
|
||||
trx?: Knex.Transaction,
|
||||
): Promise<void> => {
|
||||
const inventoryTransactions =
|
||||
this.getWarehouseTransferInventoryTransactions(warehouseTransfer);
|
||||
|
||||
await this.inventory.recordInventoryTransactions(
|
||||
inventoryTransactions,
|
||||
override,
|
||||
trx,
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes initiate inventory transactions of warehouse transfer transaction.
|
||||
* @param {ModelObject<WarehouseTransfer>} warehouseTransfer - Warehouse transfer.
|
||||
* @param {boolean} override - Override the inventory transactions.
|
||||
* @param {Knex.Transaction} trx - Knex transaction.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public writeInitiateInventoryTransactions = async (
|
||||
warehouseTransfer: ModelObject<WarehouseTransfer>,
|
||||
override?: boolean,
|
||||
trx?: Knex.Transaction,
|
||||
): Promise<void> => {
|
||||
const inventoryTransactions =
|
||||
this.getWarehouseFromTransferInventoryTransactions(warehouseTransfer);
|
||||
|
||||
await this.inventory.recordInventoryTransactions(
|
||||
inventoryTransactions,
|
||||
override,
|
||||
trx,
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes transferred inventory transaction of warehouse transfer transaction.
|
||||
* @param {ModelObject<WarehouseTransfer>} warehouseTransfer - Warehouse transfer.
|
||||
* @param {boolean} override - Override the inventory transactions.
|
||||
* @param {Knex.Transaction} trx - Knex transaction.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public writeTransferredInventoryTransactions = async (
|
||||
warehouseTransfer: ModelObject<WarehouseTransfer>,
|
||||
override?: boolean,
|
||||
trx?: Knex.Transaction,
|
||||
): Promise<void> => {
|
||||
const inventoryTransactions =
|
||||
this.getWarehouseToTransferInventoryTransactions(warehouseTransfer);
|
||||
|
||||
await this.inventory.recordInventoryTransactions(
|
||||
inventoryTransactions,
|
||||
override,
|
||||
trx,
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Reverts warehouse transfer inventory transactions.
|
||||
* @param {number} warehouseTransferId - Warehouse transfer id.
|
||||
* @param {Knex.Transaction} trx - Knex transaction.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public revertInventoryTransactions = async (
|
||||
warehouseTransferId: number,
|
||||
trx?: Knex.Transaction,
|
||||
): Promise<void> => {
|
||||
await this.inventory.deleteInventoryTransactions(
|
||||
warehouseTransferId,
|
||||
'WarehouseTransfer',
|
||||
trx,
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the inventory transactions of the given warehouse transfer.
|
||||
* @param {IWarehouseTransfer} warehouseTransfer
|
||||
* @returns {IInventoryTransaction[]}
|
||||
*/
|
||||
private getWarehouseFromTransferInventoryTransactions = (
|
||||
warehouseTransfer: ModelObject<WarehouseTransfer>,
|
||||
) => {
|
||||
const commonEntry = {
|
||||
date: warehouseTransfer.date,
|
||||
transactionType: 'WarehouseTransfer',
|
||||
transactionId: warehouseTransfer.id,
|
||||
};
|
||||
return warehouseTransfer.entries.map(
|
||||
(entry: ModelObject<WarehouseTransferEntry>) => ({
|
||||
...commonEntry,
|
||||
entryId: entry.id,
|
||||
itemId: entry.itemId,
|
||||
quantity: entry.quantity,
|
||||
rate: entry.cost,
|
||||
direction: 'OUT',
|
||||
warehouseId: warehouseTransfer.fromWarehouseId,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the inventory transactions of the given warehouse transfer.
|
||||
* @param {ModelObject<WarehouseTransfer>} warehouseTransfer - Warehouse transfer.
|
||||
* @returns {IInventoryTransaction[]}
|
||||
*/
|
||||
private getWarehouseToTransferInventoryTransactions = (
|
||||
warehouseTransfer: ModelObject<WarehouseTransfer>,
|
||||
) => {
|
||||
const commonEntry = {
|
||||
date: warehouseTransfer.date,
|
||||
transactionType: 'WarehouseTransfer',
|
||||
transactionId: warehouseTransfer.id,
|
||||
};
|
||||
return warehouseTransfer.entries.map(
|
||||
(entry: ModelObject<WarehouseTransferEntry>) => ({
|
||||
...commonEntry,
|
||||
entryId: entry.id,
|
||||
itemId: entry.itemId,
|
||||
quantity: entry.quantity,
|
||||
rate: entry.cost,
|
||||
direction: 'IN',
|
||||
warehouseId: warehouseTransfer.toWarehouseId,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the inventory transactions of the given warehouse transfer.
|
||||
* @param {ModelObject<WarehouseTransfer>} warehouseTransfer - Warehouse transfer.
|
||||
* @returns {IInventoryTransaction[]}
|
||||
*/
|
||||
private getWarehouseTransferInventoryTransactions = (
|
||||
warehouseTransfer: ModelObject<WarehouseTransfer>,
|
||||
) => {
|
||||
// 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];
|
||||
};
|
||||
}
|
||||
57
packages/server/src/modules/WarehousesTransfers/constants.ts
Normal file
57
packages/server/src/modules/WarehousesTransfers/constants.ts
Normal file
@@ -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_ALREADY_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: [],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,109 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { Type } from 'class-transformer';
|
||||
import {
|
||||
IsArray,
|
||||
IsBoolean,
|
||||
IsDate,
|
||||
IsDecimal,
|
||||
IsInt,
|
||||
IsNotEmpty,
|
||||
IsNumber,
|
||||
IsOptional,
|
||||
IsPositive,
|
||||
IsString,
|
||||
ValidateNested,
|
||||
ArrayMinSize,
|
||||
} from 'class-validator';
|
||||
|
||||
export class WarehouseTransferEntryDto {
|
||||
@IsNotEmpty()
|
||||
index: number;
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsInt()
|
||||
itemId: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
description?: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsInt()
|
||||
@IsPositive()
|
||||
quantity: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsDecimal()
|
||||
cost?: number;
|
||||
}
|
||||
|
||||
export class CommandWarehouseTransferDto {
|
||||
@IsNotEmpty()
|
||||
@IsInt()
|
||||
@ApiProperty({
|
||||
description: 'The id of the warehouse to transfer from',
|
||||
example: 1,
|
||||
})
|
||||
fromWarehouseId: number;
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsInt()
|
||||
@ApiProperty({
|
||||
description: 'The id of the warehouse to transfer to',
|
||||
example: 2,
|
||||
})
|
||||
toWarehouseId: number;
|
||||
|
||||
@IsNotEmpty()
|
||||
@IsDate()
|
||||
@ApiProperty({
|
||||
description: 'The date of the warehouse transfer',
|
||||
example: '2021-01-01',
|
||||
})
|
||||
date: Date;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@ApiProperty({
|
||||
description: 'The transaction number of the warehouse transfer',
|
||||
example: '123456',
|
||||
})
|
||||
transactionNumber?: string;
|
||||
|
||||
@IsBoolean()
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'Whether the warehouse transfer has been initiated',
|
||||
example: false,
|
||||
})
|
||||
transferInitiated: boolean = false;
|
||||
|
||||
@IsBoolean()
|
||||
@IsOptional()
|
||||
@ApiProperty({
|
||||
description: 'Whether the warehouse transfer has been delivered',
|
||||
example: false,
|
||||
})
|
||||
transferDelivered: boolean = false;
|
||||
|
||||
@IsArray()
|
||||
@ArrayMinSize(1)
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => WarehouseTransferEntryDto)
|
||||
@ApiProperty({
|
||||
description: 'The entries of the warehouse transfer',
|
||||
example: [
|
||||
{
|
||||
index: 1,
|
||||
itemId: 1,
|
||||
description: 'This is a description',
|
||||
quantity: 100,
|
||||
cost: 100,
|
||||
},
|
||||
],
|
||||
})
|
||||
entries: WarehouseTransferEntryDto[];
|
||||
}
|
||||
|
||||
export class CreateWarehouseTransferDto extends CommandWarehouseTransferDto {}
|
||||
export class EditWarehouseTransferDto extends CommandWarehouseTransferDto {}
|
||||
@@ -0,0 +1,152 @@
|
||||
import { Model, mixin } from 'objection';
|
||||
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
||||
import { Warehouse } from '@/modules/Warehouses/models/Warehouse.model';
|
||||
import { WarehouseTransferEntry } from './WarehouseTransferEntry';
|
||||
|
||||
export class WarehouseTransfer extends TenantBaseModel {
|
||||
public date!: Date;
|
||||
public transferInitiatedAt!: Date;
|
||||
public transferDeliveredAt!: Date;
|
||||
public fromWarehouseId!: number;
|
||||
public toWarehouseId!: number;
|
||||
|
||||
public entries!: WarehouseTransferEntry[];
|
||||
public fromWarehouse!: Warehouse;
|
||||
public toWarehouse!: Warehouse;
|
||||
|
||||
|
||||
/**
|
||||
* Table name.
|
||||
*/
|
||||
static get tableName() {
|
||||
return 'warehouses_transfers';
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamps columns.
|
||||
*/
|
||||
get timestamps() {
|
||||
return ['created_at', 'updated_at'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Virtual attributes.
|
||||
*/
|
||||
static get virtualAttributes() {
|
||||
return ['isInitiated', 'isTransferred'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Detarmines whether the warehouse transfer initiated.
|
||||
* @retruns {boolean}
|
||||
*/
|
||||
get isInitiated() {
|
||||
return !!this.transferInitiatedAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detarmines whether the warehouse transfer transferred.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
get isTransferred() {
|
||||
return !!this.transferDeliveredAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Model modifiers.
|
||||
*/
|
||||
static get modifiers() {
|
||||
return {
|
||||
filterByDraft(query) {
|
||||
query.whereNull('transferInitiatedAt');
|
||||
query.whereNull('transferDeliveredAt');
|
||||
},
|
||||
filterByInTransit(query) {
|
||||
query.whereNotNull('transferInitiatedAt');
|
||||
query.whereNull('transferDeliveredAt');
|
||||
},
|
||||
filterByTransferred(query) {
|
||||
query.whereNotNull('transferInitiatedAt');
|
||||
query.whereNotNull('transferDeliveredAt');
|
||||
},
|
||||
filterByStatus(query, status) {
|
||||
switch (status) {
|
||||
case 'draft':
|
||||
default:
|
||||
return query.modify('filterByDraft');
|
||||
case 'in-transit':
|
||||
return query.modify('filterByInTransit');
|
||||
case 'transferred':
|
||||
return query.modify('filterByTransferred');
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Relationship mapping.
|
||||
*/
|
||||
static get relationMappings() {
|
||||
const { WarehouseTransferEntry } = require('./WarehouseTransferEntry');
|
||||
const { Warehouse } = require('../../Warehouses/models/Warehouse.model');
|
||||
|
||||
return {
|
||||
/**
|
||||
* View model may has many columns.
|
||||
*/
|
||||
entries: {
|
||||
relation: Model.HasManyRelation,
|
||||
modelClass: WarehouseTransferEntry,
|
||||
join: {
|
||||
from: 'warehouses_transfers.id',
|
||||
to: 'warehouses_transfers_entries.warehouseTransferId',
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
fromWarehouse: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: Warehouse,
|
||||
join: {
|
||||
from: 'warehouses_transfers.fromWarehouseId',
|
||||
to: 'warehouses.id',
|
||||
},
|
||||
},
|
||||
|
||||
toWarehouse: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: Warehouse,
|
||||
join: {
|
||||
from: 'warehouses_transfers.toWarehouseId',
|
||||
to: 'warehouses.id',
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Model settings.
|
||||
*/
|
||||
// static get meta() {
|
||||
// return WarehouseTransferSettings;
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * Retrieve the default custom views, roles and columns.
|
||||
// */
|
||||
// static get defaultViews() {
|
||||
// return DEFAULT_VIEWS;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Model search roles.
|
||||
*/
|
||||
static get searchRoles() {
|
||||
return [
|
||||
// { fieldKey: 'name', comparator: 'contains' },
|
||||
// { condition: 'or', fieldKey: 'code', comparator: 'like' },
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import { Model } from 'objection';
|
||||
import { TenantBaseModel } from '@/modules/System/models/TenantBaseModel';
|
||||
import { WarehouseTransfer } from './WarehouseTransfer';
|
||||
import { Item } from '@/modules/Items/models/Item';
|
||||
|
||||
export class WarehouseTransferEntry extends TenantBaseModel {
|
||||
public warehouseTransferId!: number;
|
||||
public itemId!: number;
|
||||
public quantity!: number;
|
||||
public cost!: number;
|
||||
|
||||
public warehouseTransfer!: WarehouseTransfer;
|
||||
public item!: Item;
|
||||
|
||||
/**
|
||||
* Table name.
|
||||
*/
|
||||
static get tableName() {
|
||||
return 'warehouses_transfers_entries';
|
||||
}
|
||||
|
||||
/**
|
||||
* Virtual attributes.
|
||||
*/
|
||||
static get virtualAttributes() {
|
||||
return ['total'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoice amount in local currency.
|
||||
* @returns {number}
|
||||
*/
|
||||
get total() {
|
||||
return this.cost * this.quantity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Relationship mapping.
|
||||
*/
|
||||
static get relationMappings() {
|
||||
const { Item } = require('../../Items/models/Item');
|
||||
|
||||
return {
|
||||
item: {
|
||||
relation: Model.BelongsToOneRelation,
|
||||
modelClass: Item,
|
||||
join: {
|
||||
from: 'warehouses_transfers_entries.itemId',
|
||||
to: 'items.id',
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { WarehouseTransferTransformer } from './WarehouseTransferTransfomer';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
import { WarehouseTransfer } from '../models/WarehouseTransfer';
|
||||
import { ModelObject } from 'objection';
|
||||
|
||||
@Injectable()
|
||||
export class GetWarehouseTransfer {
|
||||
constructor(
|
||||
private readonly transformer: TransformerInjectable,
|
||||
|
||||
@Inject(WarehouseTransfer.name)
|
||||
private readonly warehouseTransferModel: TenantModelProxy<
|
||||
typeof WarehouseTransfer
|
||||
>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieves the specific warehouse transfer transaction.
|
||||
* @param {number} warehouseTransferId
|
||||
* @param {IEditWarehouseTransferDTO} editWarehouseDTO
|
||||
* @returns {Promise<IWarehouseTransfer>}
|
||||
*/
|
||||
public getWarehouseTransfer = async (
|
||||
warehouseTransferId: number,
|
||||
): Promise<ModelObject<WarehouseTransfer>> => {
|
||||
// Retrieves the old warehouse transfer transaction.
|
||||
const warehouseTransfer = await this.warehouseTransferModel()
|
||||
.query()
|
||||
.findById(warehouseTransferId)
|
||||
.withGraphFetched('entries.item')
|
||||
.withGraphFetched('fromWarehouse')
|
||||
.withGraphFetched('toWarehouse')
|
||||
.throwIfNotFound();
|
||||
|
||||
// Retrieves the transfromed warehouse transfers.
|
||||
return this.transformer.transform(
|
||||
warehouseTransfer,
|
||||
new WarehouseTransferTransformer(),
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
import * as R from 'ramda';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { WarehouseTransferTransformer } from './WarehouseTransferTransfomer';
|
||||
import { IGetWarehousesTransfersFilterDTO } from '../../Warehouses/Warehouse.types';
|
||||
import { TransformerInjectable } from '../../Transformer/TransformerInjectable.service';
|
||||
import { DynamicListService } from '../../DynamicListing/DynamicList.service';
|
||||
import { TenantModelProxy } from '../../System/models/TenantBaseModel';
|
||||
import { WarehouseTransfer } from '../models/WarehouseTransfer';
|
||||
|
||||
@Injectable()
|
||||
export class GetWarehouseTransfers {
|
||||
constructor(
|
||||
private readonly dynamicListService: DynamicListService,
|
||||
private readonly transformer: TransformerInjectable,
|
||||
|
||||
@Inject(WarehouseTransfer.name)
|
||||
private readonly warehouseTransferModel: TenantModelProxy<
|
||||
typeof WarehouseTransfer
|
||||
>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* 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 (
|
||||
filterDTO: IGetWarehousesTransfersFilterDTO,
|
||||
) => {
|
||||
// Parses stringified filter roles.
|
||||
const filter = this.parseListFilterDTO(filterDTO);
|
||||
|
||||
// Dynamic list service.
|
||||
const dynamicFilter = await this.dynamicListService.dynamicList(
|
||||
this.warehouseTransferModel(),
|
||||
filter,
|
||||
);
|
||||
const { results, pagination } = await this.warehouseTransferModel()
|
||||
.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(
|
||||
results,
|
||||
new WarehouseTransferTransformer(),
|
||||
);
|
||||
return {
|
||||
warehousesTransfers,
|
||||
pagination,
|
||||
filter,
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { Transformer } from "../../Transformer/Transformer";
|
||||
|
||||
export class WarehouseTransferItemTransformer extends Transformer {
|
||||
/**
|
||||
* Include these attributes to sale invoice object.
|
||||
* @returns {Array}
|
||||
*/
|
||||
public includeAttributes = (): string[] => {
|
||||
return ['formattedQuantity', 'formattedCost', 'formattedTotal'];
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats the total.
|
||||
* @param {IWarehouseTransferEntry} entry
|
||||
* @returns {string}
|
||||
*/
|
||||
public formattedTotal = (entry) => {
|
||||
return this.formatMoney(entry.total);
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats the quantity.
|
||||
* @param {IWarehouseTransferEntry} entry
|
||||
* @returns {string}
|
||||
*/
|
||||
public formattedQuantity = (entry) => {
|
||||
return this.formatNumber(entry.quantity);
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats the cost.
|
||||
* @param {IWarehouseTransferEntry} entry
|
||||
* @returns {string}
|
||||
*/
|
||||
public formattedCost = (entry) => {
|
||||
return this.formatMoney(entry.cost);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { WarehouseTransferItemTransformer } from './WarehouseTransferItemTransformer';
|
||||
import { Transformer } from '@/modules/Transformer/Transformer';
|
||||
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,21 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { events } from '@/common/events/events';
|
||||
import { IWarehouseTransferCreated } from '../../Warehouses/Warehouse.types';
|
||||
import { WarehouseTransferAutoIncrement } from '../commands/WarehouseTransferAutoIncrement';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
|
||||
@Injectable()
|
||||
export class WarehouseTransferAutoIncrementSubscriber {
|
||||
constructor(
|
||||
private readonly warehouseTransferAutoIncrement: WarehouseTransferAutoIncrement,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Writes inventory transactions once warehouse transfer created.
|
||||
* @param {IInventoryTransactionsCreatedPayload} -
|
||||
*/
|
||||
@OnEvent(events.warehouseTransfer.onCreated)
|
||||
async incrementTransferAutoIncrementOnCreated({}: IWarehouseTransferCreated) {
|
||||
await this.warehouseTransferAutoIncrement.incrementNextTransferNumber();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
import {
|
||||
IWarehouseTransferEditedPayload,
|
||||
IWarehouseTransferDeletedPayload,
|
||||
IWarehouseTransferCreated,
|
||||
IWarehouseTransferInitiatedPayload,
|
||||
IWarehouseTransferTransferredPayload,
|
||||
} from '@/modules/Warehouses/Warehouse.types';
|
||||
import { WarehouseTransferInventoryTransactions } from '../commands/WarehouseTransferWriteInventoryTransactions';
|
||||
import { OnEvent } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class WarehouseTransferInventoryTransactionsSubscriber {
|
||||
constructor(
|
||||
private readonly warehouseTransferInventoryTransactions: WarehouseTransferInventoryTransactions,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Writes inventory transactions once warehouse transfer created.
|
||||
* @param {IInventoryTransactionsCreatedPayload} -
|
||||
*/
|
||||
@OnEvent(events.warehouseTransfer.onCreated)
|
||||
async writeInventoryTransactionsOnWarehouseTransferCreated({
|
||||
warehouseTransfer,
|
||||
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(
|
||||
warehouseTransfer,
|
||||
false,
|
||||
trx,
|
||||
);
|
||||
// Write initiate inventory transaction if warehouse transfer initited and transferred yet.
|
||||
} else if (warehouseTransfer.isInitiated) {
|
||||
await this.warehouseTransferInventoryTransactions.writeInitiateInventoryTransactions(
|
||||
warehouseTransfer,
|
||||
false,
|
||||
trx,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrite inventory transactions once warehouse transfer edited.
|
||||
* @param {IWarehouseTransferEditedPayload} -
|
||||
*/
|
||||
@OnEvent(events.warehouseTransfer.onEdited)
|
||||
async rewriteInventoryTransactionsOnWarehouseTransferEdited({
|
||||
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(
|
||||
warehouseTransfer,
|
||||
true,
|
||||
trx,
|
||||
);
|
||||
// Write initiate inventory transaction if warehouse transfer initited and transferred yet.
|
||||
} else if (warehouseTransfer.isInitiated) {
|
||||
await this.warehouseTransferInventoryTransactions.writeInitiateInventoryTransactions(
|
||||
warehouseTransfer,
|
||||
true,
|
||||
trx,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverts inventory transactions once warehouse transfer deleted.
|
||||
* @parma {IWarehouseTransferDeletedPayload} -
|
||||
*/
|
||||
@OnEvent(events.warehouseTransfer.onDeleted)
|
||||
async revertInventoryTransactionsOnWarehouseTransferDeleted({
|
||||
oldWarehouseTransfer,
|
||||
trx,
|
||||
}: IWarehouseTransferDeletedPayload) {
|
||||
await this.warehouseTransferInventoryTransactions.revertInventoryTransactions(
|
||||
oldWarehouseTransfer.id,
|
||||
trx,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write inventory transactions of warehouse transfer once the transfer initiated.
|
||||
* @param {IWarehouseTransferInitiatedPayload}
|
||||
*/
|
||||
@OnEvent(events.warehouseTransfer.onInitiated)
|
||||
async writeInventoryTransactionsOnTransferInitiated({
|
||||
trx,
|
||||
warehouseTransfer,
|
||||
}: IWarehouseTransferInitiatedPayload) {
|
||||
await this.warehouseTransferInventoryTransactions.writeInitiateInventoryTransactions(
|
||||
warehouseTransfer,
|
||||
false,
|
||||
trx,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write inventory transactions of warehouse transfer once the transfer completed.
|
||||
* @param {IWarehouseTransferTransferredPayload}
|
||||
*/
|
||||
@OnEvent(events.warehouseTransfer.onTransferred)
|
||||
async writeInventoryTransactionsOnTransferred({
|
||||
trx,
|
||||
warehouseTransfer,
|
||||
}: IWarehouseTransferTransferredPayload) {
|
||||
await this.warehouseTransferInventoryTransactions.writeTransferredInventoryTransactions(
|
||||
warehouseTransfer,
|
||||
false,
|
||||
trx,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user