mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 06:40:31 +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({
|
return res.status(400).send({
|
||||||
errors: [
|
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);
|
next(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,5 +25,6 @@ export interface IItemEntry {
|
|||||||
|
|
||||||
export interface IItemEntryDTO {
|
export interface IItemEntryDTO {
|
||||||
id?: number,
|
id?: number,
|
||||||
|
itemId: number;
|
||||||
landedCost?: boolean;
|
landedCost?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,16 +17,16 @@ const ERRORS = {
|
|||||||
export default class EntriesService {
|
export default class EntriesService {
|
||||||
/**
|
/**
|
||||||
* Validates bill entries that has allocated landed cost amount not deleted.
|
* Validates bill entries that has allocated landed cost amount not deleted.
|
||||||
* @param {IItemEntry[]} oldBillEntries -
|
* @param {IItemEntry[]} oldCommonEntries -
|
||||||
* @param {IItemEntry[]} newBillEntries -
|
* @param {IItemEntry[]} newBillEntries -
|
||||||
*/
|
*/
|
||||||
public getLandedCostEntriesDeleted(
|
public getLandedCostEntriesDeleted(
|
||||||
oldBillEntries: ICommonLandedCostEntry[],
|
oldCommonEntries: ICommonLandedCostEntry[],
|
||||||
newBillEntriesDTO: ICommonLandedCostEntryDTO[]
|
newCommonEntriesDTO: ICommonLandedCostEntryDTO[]
|
||||||
): ICommonLandedCostEntry[] {
|
): 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);
|
const newEntry = newBillEntriesById.get(entry.id);
|
||||||
|
|
||||||
if (entry.allocatedCostAmount > 0 && typeof newEntry === 'undefined') {
|
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.
|
* 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.
|
* @param {IItemEntryDTO[]} newBillEntries - New DTO bill entries.
|
||||||
*/
|
*/
|
||||||
public validateLandedCostEntriesNotDeleted(
|
public validateLandedCostEntriesNotDeleted(
|
||||||
oldBillEntries: ICommonLandedCostEntry[],
|
oldCommonEntries: ICommonLandedCostEntry[],
|
||||||
newBillEntriesDTO: ICommonLandedCostEntryDTO[]
|
newCommonEntriesDTO: ICommonLandedCostEntryDTO[]
|
||||||
): void {
|
): void {
|
||||||
const entriesDeleted = this.getLandedCostEntriesDeleted(
|
const entriesDeleted = this.getLandedCostEntriesDeleted(
|
||||||
oldBillEntries,
|
oldCommonEntries,
|
||||||
newBillEntriesDTO
|
newCommonEntriesDTO
|
||||||
);
|
);
|
||||||
if (entriesDeleted.length > 0) {
|
if (entriesDeleted.length > 0) {
|
||||||
throw new ServiceError(ERRORS.ENTRIES_ALLOCATED_COST_COULD_NOT_DELETED);
|
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.
|
* 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.
|
* @param {IItemEntryDTO[]} newBillEntries - New DTO bill entries.
|
||||||
*/
|
*/
|
||||||
public validateLocatedCostEntriesSmallerThanNewEntries(
|
public validateLocatedCostEntriesSmallerThanNewEntries(
|
||||||
oldBillEntries: ICommonLandedCostEntry[],
|
oldCommonEntries: ICommonLandedCostEntry[],
|
||||||
newBillEntriesDTO: ICommonLandedCostEntryDTO[]
|
newCommonEntriesDTO: ICommonLandedCostEntryDTO[]
|
||||||
): void {
|
): void {
|
||||||
const oldBillEntriesById = transformToMap(oldBillEntries, 'id');
|
const oldBillEntriesById = transformToMap(oldCommonEntries, 'id');
|
||||||
|
|
||||||
newBillEntriesDTO.forEach((entry) => {
|
newCommonEntriesDTO.forEach((entry) => {
|
||||||
const oldEntry = oldBillEntriesById.get(entry.id);
|
const oldEntry = oldBillEntriesById.get(entry.id);
|
||||||
|
|
||||||
if (oldEntry && oldEntry.allocatedCostAmount > entry.amount) {
|
if (oldEntry && oldEntry.allocatedCostAmount > entry.amount) {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import InventoryService from 'services/Inventory/Inventory';
|
|||||||
import SalesInvoicesCost from 'services/Sales/SalesInvoicesCost';
|
import SalesInvoicesCost from 'services/Sales/SalesInvoicesCost';
|
||||||
import TenancyService from 'services/Tenancy/TenancyService';
|
import TenancyService from 'services/Tenancy/TenancyService';
|
||||||
import DynamicListingService from 'services/DynamicListing/DynamicListService';
|
import DynamicListingService from 'services/DynamicListing/DynamicListService';
|
||||||
import { formatDateFields } from 'utils';
|
import { formatDateFields, transformToMap } from 'utils';
|
||||||
import {
|
import {
|
||||||
IBillDTO,
|
IBillDTO,
|
||||||
IBill,
|
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.
|
* Sets the default cost account to the bill entries.
|
||||||
*/
|
*/
|
||||||
@@ -334,6 +364,10 @@ export default class BillsService
|
|||||||
tenantId,
|
tenantId,
|
||||||
billDTO.entries
|
billDTO.entries
|
||||||
);
|
);
|
||||||
|
await this.validateCostEntriesShouldBeInventoryItems(
|
||||||
|
tenantId,
|
||||||
|
billDTO.entries,
|
||||||
|
);
|
||||||
this.logger.info('[bill] trying to create a new bill', {
|
this.logger.info('[bill] trying to create a new bill', {
|
||||||
tenantId,
|
tenantId,
|
||||||
billDTO,
|
billDTO,
|
||||||
@@ -423,7 +457,7 @@ export default class BillsService
|
|||||||
// Validate landed cost entries that have allocated cost could not be deleted.
|
// Validate landed cost entries that have allocated cost could not be deleted.
|
||||||
await this.entriesService.validateLandedCostEntriesNotDeleted(
|
await this.entriesService.validateLandedCostEntriesNotDeleted(
|
||||||
oldBill.entries,
|
oldBill.entries,
|
||||||
billObj.entries,
|
billObj.entries
|
||||||
);
|
);
|
||||||
// Validate new landed cost entries should be bigger than new entries.
|
// Validate new landed cost entries should be bigger than new entries.
|
||||||
await this.entriesService.validateLocatedCostEntriesSmallerThanNewEntries(
|
await this.entriesService.validateLocatedCostEntriesSmallerThanNewEntries(
|
||||||
|
|||||||
@@ -12,5 +12,6 @@ export const ERRORS = {
|
|||||||
VENDOR_HAS_BILLS: 'VENDOR_HAS_BILLS',
|
VENDOR_HAS_BILLS: 'VENDOR_HAS_BILLS',
|
||||||
BILL_HAS_ASSOCIATED_LANDED_COSTS: 'BILL_HAS_ASSOCIATED_LANDED_COSTS',
|
BILL_HAS_ASSOCIATED_LANDED_COSTS: 'BILL_HAS_ASSOCIATED_LANDED_COSTS',
|
||||||
BILL_ENTRIES_ALLOCATED_COST_COULD_DELETED: 'BILL_ENTRIES_ALLOCATED_COST_COULD_DELETED',
|
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