mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-15 20:30:33 +00:00
WIP: allocate landed cost.
This commit is contained in:
@@ -446,7 +446,9 @@ export default class BillsController extends BaseController {
|
||||
],
|
||||
});
|
||||
}
|
||||
if (error.errorType === 'LOCATED_COST_ENTRIES_SHOULD_BIGGE_THAN_NEW_ENTRIES') {
|
||||
if (
|
||||
error.errorType === 'LOCATED_COST_ENTRIES_SHOULD_BIGGE_THAN_NEW_ENTRIES'
|
||||
) {
|
||||
return res.status(400).send({
|
||||
errors: [
|
||||
{
|
||||
@@ -456,6 +458,18 @@ export default class BillsController extends BaseController {
|
||||
],
|
||||
});
|
||||
}
|
||||
if (error.errorType === 'LANDED_COST_ENTRIES_SHOULD_BE_INVENTORY_ITEMS') {
|
||||
return res.status(400).send({
|
||||
errors: [
|
||||
{
|
||||
type: 'LANDED_COST_ENTRIES_SHOULD_BE_INVENTORY_ITEMS',
|
||||
message:
|
||||
'Landed cost entries should be only with inventory items.',
|
||||
code: 1600,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
next(error);
|
||||
}
|
||||
|
||||
@@ -25,5 +25,6 @@ export interface IItemEntry {
|
||||
|
||||
export interface IItemEntryDTO {
|
||||
id?: number,
|
||||
itemId: number;
|
||||
landedCost?: boolean;
|
||||
}
|
||||
|
||||
@@ -17,16 +17,16 @@ const ERRORS = {
|
||||
export default class EntriesService {
|
||||
/**
|
||||
* Validates bill entries that has allocated landed cost amount not deleted.
|
||||
* @param {IItemEntry[]} oldBillEntries -
|
||||
* @param {IItemEntry[]} oldCommonEntries -
|
||||
* @param {IItemEntry[]} newBillEntries -
|
||||
*/
|
||||
public getLandedCostEntriesDeleted(
|
||||
oldBillEntries: ICommonLandedCostEntry[],
|
||||
newBillEntriesDTO: ICommonLandedCostEntryDTO[]
|
||||
oldCommonEntries: ICommonLandedCostEntry[],
|
||||
newCommonEntriesDTO: ICommonLandedCostEntryDTO[]
|
||||
): ICommonLandedCostEntry[] {
|
||||
const newBillEntriesById = transformToMap(newBillEntriesDTO, 'id');
|
||||
const newBillEntriesById = transformToMap(newCommonEntriesDTO, 'id');
|
||||
|
||||
return oldBillEntries.filter((entry) => {
|
||||
return oldCommonEntries.filter((entry) => {
|
||||
const newEntry = newBillEntriesById.get(entry.id);
|
||||
|
||||
if (entry.allocatedCostAmount > 0 && typeof newEntry === 'undefined') {
|
||||
@@ -38,16 +38,16 @@ export default class EntriesService {
|
||||
|
||||
/**
|
||||
* Validates the bill entries that have located cost amount should not be deleted.
|
||||
* @param {IItemEntry[]} oldBillEntries - Old bill entries.
|
||||
* @param {IItemEntry[]} oldCommonEntries - Old bill entries.
|
||||
* @param {IItemEntryDTO[]} newBillEntries - New DTO bill entries.
|
||||
*/
|
||||
public validateLandedCostEntriesNotDeleted(
|
||||
oldBillEntries: ICommonLandedCostEntry[],
|
||||
newBillEntriesDTO: ICommonLandedCostEntryDTO[]
|
||||
oldCommonEntries: ICommonLandedCostEntry[],
|
||||
newCommonEntriesDTO: ICommonLandedCostEntryDTO[]
|
||||
): void {
|
||||
const entriesDeleted = this.getLandedCostEntriesDeleted(
|
||||
oldBillEntries,
|
||||
newBillEntriesDTO
|
||||
oldCommonEntries,
|
||||
newCommonEntriesDTO
|
||||
);
|
||||
if (entriesDeleted.length > 0) {
|
||||
throw new ServiceError(ERRORS.ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED);
|
||||
@@ -56,16 +56,16 @@ export default class EntriesService {
|
||||
|
||||
/**
|
||||
* Validate allocated cost amount entries should be smaller than new entries amount.
|
||||
* @param {IItemEntry[]} oldBillEntries - Old bill entries.
|
||||
* @param {IItemEntry[]} oldCommonEntries - Old bill entries.
|
||||
* @param {IItemEntryDTO[]} newBillEntries - New DTO bill entries.
|
||||
*/
|
||||
public validateLocatedCostEntriesSmallerThanNewEntries(
|
||||
oldBillEntries: ICommonLandedCostEntry[],
|
||||
newBillEntriesDTO: ICommonLandedCostEntryDTO[]
|
||||
oldCommonEntries: ICommonLandedCostEntry[],
|
||||
newCommonEntriesDTO: ICommonLandedCostEntryDTO[]
|
||||
): void {
|
||||
const oldBillEntriesById = transformToMap(oldBillEntries, 'id');
|
||||
const oldBillEntriesById = transformToMap(oldCommonEntries, 'id');
|
||||
|
||||
newBillEntriesDTO.forEach((entry) => {
|
||||
newCommonEntriesDTO.forEach((entry) => {
|
||||
const oldEntry = oldBillEntriesById.get(entry.id);
|
||||
|
||||
if (oldEntry && oldEntry.allocatedCostAmount > entry.amount) {
|
||||
|
||||
@@ -13,7 +13,7 @@ import InventoryService from 'services/Inventory/Inventory';
|
||||
import SalesInvoicesCost from 'services/Sales/SalesInvoicesCost';
|
||||
import TenancyService from 'services/Tenancy/TenancyService';
|
||||
import DynamicListingService from 'services/DynamicListing/DynamicListService';
|
||||
import { formatDateFields } from 'utils';
|
||||
import { formatDateFields, transformToMap } from 'utils';
|
||||
import {
|
||||
IBillDTO,
|
||||
IBill,
|
||||
@@ -194,6 +194,36 @@ export default class BillsService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate transaction entries that have landed cost type should not be
|
||||
* inventory items.
|
||||
* @param {number} tenantId -
|
||||
* @param {IItemEntryDTO[]} newEntriesDTO -
|
||||
*/
|
||||
public async validateCostEntriesShouldBeInventoryItems(
|
||||
tenantId: number,
|
||||
newEntriesDTO: IItemEntryDTO[]
|
||||
) {
|
||||
const { Item } = this.tenancy.models(tenantId);
|
||||
|
||||
const entriesItemsIds = newEntriesDTO.map((e) => e.itemId);
|
||||
const entriesItems = await Item.query().whereIn('id', entriesItemsIds);
|
||||
|
||||
const entriesItemsById = transformToMap(entriesItems, 'id');
|
||||
|
||||
// Filter the landed cost entries that not associated with inventory item.
|
||||
const nonInventoryHasCost = newEntriesDTO.filter((entry) => {
|
||||
const item = entriesItemsById.get(entry.itemId);
|
||||
|
||||
return entry.landedCost && item.type !== 'inventory';
|
||||
});
|
||||
if (nonInventoryHasCost.length > 0) {
|
||||
throw new ServiceError(
|
||||
ERRORS.LANDED_COST_ENTRIES_SHOULD_BE_INVENTORY_ITEMS
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default cost account to the bill entries.
|
||||
*/
|
||||
@@ -334,6 +364,10 @@ export default class BillsService
|
||||
tenantId,
|
||||
billDTO.entries
|
||||
);
|
||||
await this.validateCostEntriesShouldBeInventoryItems(
|
||||
tenantId,
|
||||
billDTO.entries,
|
||||
);
|
||||
this.logger.info('[bill] trying to create a new bill', {
|
||||
tenantId,
|
||||
billDTO,
|
||||
@@ -423,7 +457,7 @@ export default class BillsService
|
||||
// Validate landed cost entries that have allocated cost could not be deleted.
|
||||
await this.entriesService.validateLandedCostEntriesNotDeleted(
|
||||
oldBill.entries,
|
||||
billObj.entries,
|
||||
billObj.entries
|
||||
);
|
||||
// Validate new landed cost entries should be bigger than new entries.
|
||||
await this.entriesService.validateLocatedCostEntriesSmallerThanNewEntries(
|
||||
|
||||
@@ -12,5 +12,6 @@ export const ERRORS = {
|
||||
VENDOR_HAS_BILLS: 'VENDOR_HAS_BILLS',
|
||||
BILL_HAS_ASSOCIATED_LANDED_COSTS: 'BILL_HAS_ASSOCIATED_LANDED_COSTS',
|
||||
BILL_ENTRIES_ALLOCATED_COST_COULD_DELETED: 'BILL_ENTRIES_ALLOCATED_COST_COULD_DELETED',
|
||||
LOCATED_COST_ENTRIES_SHOULD_BIGGE_THAN_NEW_ENTRIES: 'LOCATED_COST_ENTRIES_SHOULD_BIGGE_THAN_NEW_ENTRIES'
|
||||
LOCATED_COST_ENTRIES_SHOULD_BIGGE_THAN_NEW_ENTRIES: 'LOCATED_COST_ENTRIES_SHOULD_BIGGE_THAN_NEW_ENTRIES',
|
||||
LANDED_COST_ENTRIES_SHOULD_BE_INVENTORY_ITEMS: 'LANDED_COST_ENTRIES_SHOULD_BE_INVENTORY_ITEMS'
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user