mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 05:10:31 +00:00
WIP: Allocate landed cost.
This commit is contained in:
@@ -17,11 +17,12 @@ import {
|
||||
IExpensesService,
|
||||
ISystemUser,
|
||||
IPaginationMeta,
|
||||
IExpenseCategory,
|
||||
} from 'interfaces';
|
||||
import DynamicListingService from 'services/DynamicListing/DynamicListService';
|
||||
import events from 'subscribers/events';
|
||||
import ContactsService from 'services/Contacts/ContactsService';
|
||||
import { ACCOUNT_PARENT_TYPE, ACCOUNT_ROOT_TYPE } from 'data/AccountTypes'
|
||||
import { ACCOUNT_PARENT_TYPE, ACCOUNT_ROOT_TYPE } from 'data/AccountTypes';
|
||||
|
||||
const ERRORS = {
|
||||
EXPENSE_NOT_FOUND: 'expense_not_found',
|
||||
@@ -32,6 +33,7 @@ const ERRORS = {
|
||||
PAYMENT_ACCOUNT_HAS_INVALID_TYPE: 'payment_account_has_invalid_type',
|
||||
EXPENSES_ACCOUNT_HAS_INVALID_TYPE: 'expenses_account_has_invalid_type',
|
||||
EXPENSE_ALREADY_PUBLISHED: 'expense_already_published',
|
||||
EXPENSE_HAS_ASSOCIATED_LANDED_COST: 'EXPENSE_HAS_ASSOCIATED_LANDED_COST',
|
||||
};
|
||||
|
||||
@Service()
|
||||
@@ -308,6 +310,27 @@ export default class ExpensesService implements IExpensesService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the expense landed cost amount.
|
||||
* @param {IExpenseDTO} expenseDTO
|
||||
* @return {number}
|
||||
*/
|
||||
private getExpenseLandedCostAmount(expenseDTO: IExpenseDTO): number {
|
||||
const landedCostEntries = expenseDTO.categories.filter((entry) => {
|
||||
return entry.landedCost === true;
|
||||
});
|
||||
return this.getExpenseCategoriesTotal(landedCostEntries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the given expense categories total.
|
||||
* @param {IExpenseCategory} categories
|
||||
* @returns {number}
|
||||
*/
|
||||
private getExpenseCategoriesTotal(categories): number {
|
||||
return sumBy(categories, 'amount');
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapping expense DTO to model.
|
||||
* @param {IExpenseDTO} expenseDTO
|
||||
@@ -315,12 +338,14 @@ export default class ExpensesService implements IExpensesService {
|
||||
* @return {IExpense}
|
||||
*/
|
||||
private expenseDTOToModel(expenseDTO: IExpenseDTO, user?: ISystemUser) {
|
||||
const totalAmount = sumBy(expenseDTO.categories, 'amount');
|
||||
const landedCostAmount = this.getExpenseLandedCostAmount(expenseDTO);
|
||||
const totalAmount = this.getExpenseCategoriesTotal(expenseDTO.categories);
|
||||
|
||||
return {
|
||||
categories: [],
|
||||
...omit(expenseDTO, ['publish']),
|
||||
totalAmount,
|
||||
landedCostAmount,
|
||||
paymentDate: moment(expenseDTO.paymentDate).toMySqlDateTime(),
|
||||
...(user
|
||||
? {
|
||||
@@ -340,7 +365,7 @@ export default class ExpensesService implements IExpensesService {
|
||||
* @param {IExpenseDTO} expenseDTO
|
||||
* @return {number[]}
|
||||
*/
|
||||
mapExpensesAccountsIdsFromDTO(expenseDTO: IExpenseDTO) {
|
||||
private mapExpensesAccountsIdsFromDTO(expenseDTO: IExpenseDTO) {
|
||||
return expenseDTO.categories.map((category) => category.expenseAccountId);
|
||||
}
|
||||
|
||||
@@ -544,15 +569,16 @@ export default class ExpensesService implements IExpensesService {
|
||||
authorizedUser: ISystemUser
|
||||
): Promise<void> {
|
||||
const oldExpense = await this.getExpenseOrThrowError(tenantId, expenseId);
|
||||
const {
|
||||
expenseRepository,
|
||||
expenseEntryRepository,
|
||||
} = this.tenancy.repositories(tenantId);
|
||||
const { expenseRepository, expenseEntryRepository } =
|
||||
this.tenancy.repositories(tenantId);
|
||||
|
||||
this.logger.info('[expense] trying to delete the expense.', {
|
||||
tenantId,
|
||||
expenseId,
|
||||
});
|
||||
// Validates the expense has no associated landed cost.
|
||||
await this.validateNoAssociatedLandedCost(tenantId, expenseId);
|
||||
|
||||
await expenseEntryRepository.deleteBy({ expenseId });
|
||||
await expenseRepository.deleteById(expenseId);
|
||||
|
||||
@@ -572,7 +598,7 @@ export default class ExpensesService implements IExpensesService {
|
||||
|
||||
/**
|
||||
* Filters the not published expenses.
|
||||
* @param {IExpense[]} expenses -
|
||||
* @param {IExpense[]} expenses -
|
||||
*/
|
||||
public getNonePublishedExpenses(expenses: IExpense[]): IExpense[] {
|
||||
return expenses.filter((expense) => !expense.publishedAt);
|
||||
@@ -648,4 +674,25 @@ export default class ExpensesService implements IExpensesService {
|
||||
}
|
||||
return expense;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the expense has not associated landed cost
|
||||
* references to the given expense.
|
||||
* @param {number} tenantId
|
||||
* @param {number} expenseId
|
||||
*/
|
||||
public async validateNoAssociatedLandedCost(
|
||||
tenantId: number,
|
||||
expenseId: number
|
||||
) {
|
||||
const { BillLandedCost } = this.tenancy.models(tenantId);
|
||||
|
||||
const associatedLandedCosts = await BillLandedCost.query()
|
||||
.where('fromTransactionType', 'Expense')
|
||||
.where('fromTransactionId', expenseId);
|
||||
|
||||
if (associatedLandedCosts.length > 0) {
|
||||
throw new ServiceError(ERRORS.EXPENSE_HAS_ASSOCIATED_LANDED_COST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user