mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-06-01 15:39:00 +00:00
Fix 20+ pre-existing TypeScript errors in the server package using proper type-safe solutions — no `as any`, `as unknown`, or `any` types. Key changes: - Replace R.curry with regular curried arrow functions for proper inference - Add return types to abstract methods (DynamicFilterRoleAbstractor) - Add field declarations to empty models (ItemWarehouseQuantity) - Add index signature to IMetadata for dynamic extra columns - Use explicit field construction instead of pick()+cast patterns - Convert moment format strings to Date objects where Date type expected - Make interface properties optional where payloads don't include them - Use native Array.reduce with proper typing instead of lodash chain Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
124 lines
4.0 KiB
TypeScript
124 lines
4.0 KiB
TypeScript
import { Knex } from 'knex';
|
|
import { defaultTo } from 'lodash';
|
|
import { EventEmitter2 } from '@nestjs/event-emitter';
|
|
import { Inject, Injectable, Scope } from '@nestjs/common';
|
|
import { IItemDTO, IItemEventCreatedPayload } from '@/interfaces/Item';
|
|
import { events } from '@/common/events/events';
|
|
import { ItemsValidators } from './ItemValidator.service';
|
|
import { Item } from './models/Item';
|
|
import { UnitOfWork } from '../Tenancy/TenancyDB/UnitOfWork.service';
|
|
import { TenantModelProxy } from '../System/models/TenantBaseModel';
|
|
import { CreateItemDto } from './dtos/Item.dto';
|
|
|
|
@Injectable({ scope: Scope.REQUEST })
|
|
export class CreateItemService {
|
|
/**
|
|
* Constructor for the CreateItemService class.
|
|
* @param {EventEmitter2} eventEmitter - Event emitter for publishing item creation events.
|
|
* @param {UnitOfWork} uow - Unit of Work for tenant database transactions.
|
|
* @param {ItemsValidators} validators - Service for validating item data.
|
|
* @param {typeof Item} itemModel - The Item model class for database operations.
|
|
*/
|
|
constructor(
|
|
private readonly eventEmitter: EventEmitter2,
|
|
private readonly uow: UnitOfWork,
|
|
private readonly validators: ItemsValidators,
|
|
|
|
@Inject(Item.name)
|
|
private readonly itemModel: TenantModelProxy<typeof Item>,
|
|
) {}
|
|
|
|
/**
|
|
* Authorize the creating item.
|
|
* @param {number} tenantId
|
|
* @param {IItemDTO} itemDTO
|
|
*/
|
|
async authorize(itemDTO: CreateItemDto) {
|
|
// Validate whether the given item name already exists on the storage.
|
|
await this.validators.validateItemNameUniquiness(itemDTO.name);
|
|
|
|
if (itemDTO.categoryId) {
|
|
await this.validators.validateItemCategoryExistance(itemDTO.categoryId);
|
|
}
|
|
if (itemDTO.sellAccountId) {
|
|
await this.validators.validateItemSellAccountExistance(
|
|
itemDTO.sellAccountId,
|
|
);
|
|
}
|
|
// Validate the income account id existance if the item is sellable.
|
|
this.validators.validateIncomeAccountExistance(
|
|
itemDTO.sellable,
|
|
itemDTO.sellAccountId,
|
|
);
|
|
if (itemDTO.costAccountId) {
|
|
await this.validators.validateItemCostAccountExistance(
|
|
itemDTO.costAccountId,
|
|
);
|
|
}
|
|
// Validate the cost account id existance if the item is purchasable.
|
|
this.validators.validateCostAccountExistance(
|
|
itemDTO.purchasable,
|
|
itemDTO.costAccountId,
|
|
);
|
|
if (itemDTO.inventoryAccountId) {
|
|
await this.validators.validateItemInventoryAccountExistance(
|
|
itemDTO.inventoryAccountId,
|
|
);
|
|
}
|
|
if (itemDTO.purchaseTaxRateId) {
|
|
await this.validators.validatePurchaseTaxRateExistance(
|
|
itemDTO.purchaseTaxRateId,
|
|
);
|
|
}
|
|
if (itemDTO.sellTaxRateId) {
|
|
await this.validators.validateSellTaxRateExistance(itemDTO.sellTaxRateId);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Transforms the item DTO to model.
|
|
* @param {CreateItemDto} itemDTO - Item DTO.
|
|
* @return {IItem}
|
|
*/
|
|
private transformNewItemDTOToModel(itemDTO: CreateItemDto) {
|
|
return {
|
|
...itemDTO,
|
|
active: Boolean(defaultTo(itemDTO.active, true)),
|
|
quantityOnHand: itemDTO.type === 'inventory' ? 0 : null,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a new item.
|
|
* @param {IItemDTO} itemDTO
|
|
* @return {Promise<number>} - The created item id.
|
|
*/
|
|
public async createItem(
|
|
itemDTO: CreateItemDto,
|
|
trx?: Knex.Transaction,
|
|
): Promise<number> {
|
|
// Authorize the item before creating.
|
|
await this.authorize(itemDTO);
|
|
|
|
// Creates a new item with associated transactions under unit-of-work envirement.
|
|
return this.uow.withTransaction<number>(async (trx: Knex.Transaction) => {
|
|
const itemInsert = this.transformNewItemDTOToModel(itemDTO);
|
|
|
|
// Inserts a new item and fetch the created item.
|
|
const item = await this.itemModel()
|
|
.query(trx)
|
|
.insertAndFetch({
|
|
...itemInsert,
|
|
});
|
|
// Triggers `onItemCreated` event.
|
|
await this.eventEmitter.emitAsync(events.item.onCreated, {
|
|
item,
|
|
itemId: item.id,
|
|
trx,
|
|
} as IItemEventCreatedPayload);
|
|
|
|
return item.id;
|
|
}, trx);
|
|
}
|
|
}
|