mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 22:00:31 +00:00
162 lines
4.5 KiB
TypeScript
162 lines
4.5 KiB
TypeScript
import { Knex } from 'knex';
|
|
import { Service, Inject } from 'typedi';
|
|
import {
|
|
IItem,
|
|
IItemDTO,
|
|
IItemEditDTO,
|
|
IItemEventEditedPayload,
|
|
} from '@/interfaces';
|
|
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
|
import UnitOfWork from '@/services/UnitOfWork';
|
|
import { ItemsValidators } from './ItemValidators';
|
|
import events from '@/subscribers/events';
|
|
|
|
@Service()
|
|
export class EditItem {
|
|
@Inject()
|
|
private validators: ItemsValidators;
|
|
|
|
@Inject()
|
|
private tenancy: HasTenancyService;
|
|
|
|
@Inject()
|
|
private eventPublisher: EventPublisher;
|
|
|
|
@Inject()
|
|
private uow: UnitOfWork;
|
|
|
|
/**
|
|
* Authorize the editing item.
|
|
* @param {number} tenantId
|
|
* @param {IItemEditDTO} itemDTO
|
|
* @param {IItem} oldItem
|
|
*/
|
|
async authorize(tenantId: number, itemDTO: IItemEditDTO, oldItem: IItem) {
|
|
// Validate edit item type from inventory type.
|
|
this.validators.validateEditItemFromInventory(itemDTO, oldItem);
|
|
|
|
// Validate edit item type to inventory type.
|
|
await this.validators.validateEditItemTypeToInventory(
|
|
tenantId,
|
|
oldItem,
|
|
itemDTO
|
|
);
|
|
// Validate whether the given item name already exists on the storage.
|
|
await this.validators.validateItemNameUniquiness(
|
|
tenantId,
|
|
itemDTO.name,
|
|
oldItem.id
|
|
);
|
|
// Validate the item category existance on the storage,
|
|
if (itemDTO.categoryId) {
|
|
await this.validators.validateItemCategoryExistance(
|
|
tenantId,
|
|
itemDTO.categoryId
|
|
);
|
|
}
|
|
// Validate the sell account existance on the storage.
|
|
if (itemDTO.sellAccountId) {
|
|
await this.validators.validateItemSellAccountExistance(
|
|
tenantId,
|
|
itemDTO.sellAccountId
|
|
);
|
|
}
|
|
// Validate the cost account existance on the storage.
|
|
if (itemDTO.costAccountId) {
|
|
await this.validators.validateItemCostAccountExistance(
|
|
tenantId,
|
|
itemDTO.costAccountId
|
|
);
|
|
}
|
|
// Validate the inventory account existance onthe storage.
|
|
if (itemDTO.inventoryAccountId) {
|
|
await this.validators.validateItemInventoryAccountExistance(
|
|
tenantId,
|
|
itemDTO.inventoryAccountId
|
|
);
|
|
}
|
|
// Validate the purchase tax rate id existance.
|
|
if (itemDTO.purchaseTaxRateId) {
|
|
await this.validators.validatePurchaseTaxRateExistance(
|
|
tenantId,
|
|
itemDTO.purchaseTaxRateId
|
|
);
|
|
}
|
|
// Validate the sell tax rate id existance.
|
|
if (itemDTO.sellTaxRateId) {
|
|
await this.validators.validateSellTaxRateExistance(
|
|
tenantId,
|
|
itemDTO.sellTaxRateId
|
|
);
|
|
}
|
|
// Validate inventory account should be modified in inventory item
|
|
// has inventory transactions.
|
|
await this.validators.validateItemInvnetoryAccountModified(
|
|
tenantId,
|
|
oldItem,
|
|
itemDTO
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Transformes edit item DTO to model.
|
|
* @param {IItemDTO} itemDTO - Item DTO.
|
|
* @param {IItem} oldItem -
|
|
*/
|
|
private transformEditItemDTOToModel(itemDTO: IItemDTO, oldItem: IItem) {
|
|
return {
|
|
...itemDTO,
|
|
...(itemDTO.type === 'inventory' && oldItem.type !== 'inventory'
|
|
? {
|
|
quantityOnHand: 0,
|
|
}
|
|
: {}),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Edits the item metadata.
|
|
* @param {number} tenantId
|
|
* @param {number} itemId
|
|
* @param {IItemDTO} itemDTO
|
|
*/
|
|
public async editItem(tenantId: number, itemId: number, itemDTO: IItemDTO) {
|
|
const { Item } = this.tenancy.models(tenantId);
|
|
|
|
// Validates the given item existance on the storage.
|
|
const oldItem = await Item.query().findById(itemId).throwIfNotFound();
|
|
|
|
// Authorize before editing item.
|
|
await this.authorize(tenantId, itemDTO, oldItem);
|
|
|
|
// Transform the edit item DTO to model.
|
|
const itemModel = this.transformEditItemDTOToModel(itemDTO, oldItem);
|
|
|
|
// Edits the item with associated transactions under unit-of-work envirement.
|
|
const newItem = this.uow.withTransaction(
|
|
tenantId,
|
|
async (trx: Knex.Transaction) => {
|
|
// Updates the item on the storage and fetches the updated once.
|
|
const newItem = await Item.query(trx).patchAndFetchById(itemId, {
|
|
...itemModel,
|
|
});
|
|
// Edit event payload.
|
|
const eventPayload: IItemEventEditedPayload = {
|
|
tenantId,
|
|
item: newItem,
|
|
oldItem,
|
|
itemId: newItem.id,
|
|
trx,
|
|
};
|
|
// Triggers `onItemEdited` event.
|
|
await this.eventPublisher.emitAsync(events.item.onEdited, eventPayload);
|
|
|
|
return newItem;
|
|
}
|
|
);
|
|
|
|
return newItem;
|
|
}
|
|
}
|