mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 22:00:31 +00:00
feat(sales): currency code associated from invoice customer.
feat(purchases): currency code associated from vendor customer.
This commit is contained in:
@@ -27,6 +27,7 @@ import DynamicListingService from 'services/DynamicListing/DynamicListService';
|
||||
import { entriesAmountDiff, formatDateFields } from 'utils';
|
||||
import { ServiceError } from 'exceptions';
|
||||
import { ACCOUNT_PARENT_TYPE } from 'data/AccountTypes';
|
||||
import VendorsService from 'services/Contacts/VendorsService';
|
||||
|
||||
const ERRORS = {
|
||||
BILL_VENDOR_NOT_FOUND: 'VENDOR_NOT_FOUND',
|
||||
@@ -38,6 +39,7 @@ const ERRORS = {
|
||||
BILL_ENTRIES_IDS_NOT_FOUND: 'BILL_ENTRIES_IDS_NOT_FOUND',
|
||||
BILL_PAYMENT_ENTRIES_NOT_FOUND: 'BILL_PAYMENT_ENTRIES_NOT_FOUND',
|
||||
INVALID_BILL_PAYMENT_AMOUNT: 'INVALID_BILL_PAYMENT_AMOUNT',
|
||||
PAYMENT_NUMBER_SHOULD_NOT_MODIFY: 'PAYMENT_NUMBER_SHOULD_NOT_MODIFY',
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -58,6 +60,9 @@ export default class BillPaymentsService {
|
||||
@Inject()
|
||||
dynamicListService: DynamicListingService;
|
||||
|
||||
@Inject()
|
||||
vendorsService: VendorsService;
|
||||
|
||||
@EventDispatcher()
|
||||
eventDispatcher: EventDispatcherInterface;
|
||||
|
||||
@@ -118,7 +123,6 @@ export default class BillPaymentsService {
|
||||
const paymentAccount = await accountRepository.findOneById(
|
||||
paymentAccountId
|
||||
);
|
||||
|
||||
if (!paymentAccount) {
|
||||
throw new ServiceError(ERRORS.PAYMENT_ACCOUNT_NOT_FOUND);
|
||||
}
|
||||
@@ -263,6 +267,45 @@ export default class BillPaymentsService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* * Validate the payment vendor whether modified.
|
||||
* @param {string} billPaymentNo
|
||||
*/
|
||||
validateVendorNotModified(
|
||||
billPaymentDTO: IBillPaymentDTO,
|
||||
oldBillPayment: IBillPayment
|
||||
) {
|
||||
if (billPaymentDTO.vendorId !== oldBillPayment.vendorId) {
|
||||
throw new ServiceError(ERRORS.PAYMENT_NUMBER_SHOULD_NOT_MODIFY);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms create/edit DTO to model.
|
||||
* @param {number} tenantId
|
||||
* @param {IBillPaymentDTO} billPaymentDTO - Bill payment.
|
||||
* @param {IBillPayment} oldBillPayment - Old bill payment.
|
||||
* @return {Promise<IBillPayment>}
|
||||
*/
|
||||
async transformDTOToModel(
|
||||
tenantId: number,
|
||||
billPaymentDTO: IBillPaymentDTO,
|
||||
oldBillPayment?: IBillPayment
|
||||
): Promise<IBillPayment> {
|
||||
// Retrieve vendor details by the given vendor id.
|
||||
const vendor = await this.vendorsService.getVendorByIdOrThrowError(
|
||||
tenantId,
|
||||
billPaymentDTO.vendorId
|
||||
);
|
||||
|
||||
return {
|
||||
amount: sumBy(billPaymentDTO.entries, 'paymentAmount'),
|
||||
currencyCode: vendor.currencyCode,
|
||||
...formatDateFields(billPaymentDTO, ['paymentDate']),
|
||||
entries: billPaymentDTO.entries,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new bill payment transcations and store it to the storage
|
||||
* with associated bills entries and journal transactions.
|
||||
@@ -288,11 +331,11 @@ export default class BillPaymentsService {
|
||||
});
|
||||
const { BillPayment } = this.tenancy.models(tenantId);
|
||||
|
||||
const billPaymentObj = {
|
||||
amount: sumBy(billPaymentDTO.entries, 'paymentAmount'),
|
||||
...formatDateFields(billPaymentDTO, ['paymentDate']),
|
||||
};
|
||||
|
||||
// Transform create DTO to model object.
|
||||
const billPaymentObj = await this.transformDTOToModel(
|
||||
tenantId,
|
||||
billPaymentDTO
|
||||
);
|
||||
// Validate vendor existance on the storage.
|
||||
await this.getVendorOrThrowError(tenantId, billPaymentObj.vendorId);
|
||||
|
||||
@@ -301,7 +344,6 @@ export default class BillPaymentsService {
|
||||
tenantId,
|
||||
billPaymentObj.paymentAccountId
|
||||
);
|
||||
|
||||
// Validate the payment number uniquiness.
|
||||
if (billPaymentObj.paymentNumber) {
|
||||
await this.validatePaymentNumber(tenantId, billPaymentObj.paymentNumber);
|
||||
@@ -312,15 +354,13 @@ export default class BillPaymentsService {
|
||||
billPaymentObj.entries,
|
||||
billPaymentDTO.vendorId
|
||||
);
|
||||
|
||||
// Validates the bills due payment amount.
|
||||
await this.validateBillsDueAmount(tenantId, billPaymentObj.entries);
|
||||
|
||||
const billPayment = await BillPayment.query().insertGraphAndFetch({
|
||||
...omit(billPaymentObj, ['entries']),
|
||||
entries: billPaymentDTO.entries,
|
||||
...billPaymentObj,
|
||||
});
|
||||
|
||||
// Triggers `onBillPaymentCreated` event.
|
||||
await this.eventDispatcher.dispatch(events.billPayment.onCreated, {
|
||||
tenantId,
|
||||
billPayment,
|
||||
@@ -363,11 +403,14 @@ export default class BillPaymentsService {
|
||||
tenantId,
|
||||
billPaymentId
|
||||
);
|
||||
|
||||
const billPaymentObj = {
|
||||
amount: sumBy(billPaymentDTO.entries, 'paymentAmount'),
|
||||
...formatDateFields(billPaymentDTO, ['paymentDate']),
|
||||
};
|
||||
// Transform bill payment DTO to model object.
|
||||
const billPaymentObj = await this.transformDTOToModel(
|
||||
tenantId,
|
||||
billPaymentDTO,
|
||||
oldBillPayment
|
||||
);
|
||||
// Validate vendor not modified.
|
||||
this.validateVendorNotModified(billPaymentDTO, oldBillPayment);
|
||||
|
||||
// Validate vendor existance on the storage.
|
||||
await this.getVendorOrThrowError(tenantId, billPaymentObj.vendorId);
|
||||
@@ -377,28 +420,24 @@ export default class BillPaymentsService {
|
||||
tenantId,
|
||||
billPaymentObj.paymentAccountId
|
||||
);
|
||||
|
||||
// Validate the items entries IDs existance on the storage.
|
||||
await this.validateEntriesIdsExistance(
|
||||
tenantId,
|
||||
billPaymentId,
|
||||
billPaymentObj.entries
|
||||
);
|
||||
|
||||
// Validate the bills existance and associated to the given vendor.
|
||||
await this.validateBillsExistance(
|
||||
tenantId,
|
||||
billPaymentObj.entries,
|
||||
billPaymentDTO.vendorId
|
||||
);
|
||||
|
||||
// Validates the bills due payment amount.
|
||||
await this.validateBillsDueAmount(
|
||||
tenantId,
|
||||
billPaymentObj.entries,
|
||||
oldBillPayment.entries
|
||||
);
|
||||
|
||||
// Validate the payment number uniquiness.
|
||||
if (billPaymentObj.paymentNumber) {
|
||||
await this.validatePaymentNumber(
|
||||
@@ -409,8 +448,7 @@ export default class BillPaymentsService {
|
||||
}
|
||||
const billPayment = await BillPayment.query().upsertGraphAndFetch({
|
||||
id: billPaymentId,
|
||||
...omit(billPaymentObj, ['entries']),
|
||||
entries: billPaymentDTO.entries,
|
||||
...billPaymentObj,
|
||||
});
|
||||
await this.eventDispatcher.dispatch(events.billPayment.onEdited, {
|
||||
tenantId,
|
||||
|
||||
@@ -27,6 +27,7 @@ import ItemsService from 'services/Items/ItemsService';
|
||||
import ItemsEntriesService from 'services/Items/ItemsEntriesService';
|
||||
import JournalCommands from 'services/Accounting/JournalCommands';
|
||||
import JournalPosterService from 'services/Sales/JournalPosterService';
|
||||
import VendorsService from 'services/Contacts/VendorsService';
|
||||
import { ERRORS } from './constants';
|
||||
|
||||
/**
|
||||
@@ -46,7 +47,7 @@ export default class BillsService extends SalesInvoicesCost {
|
||||
|
||||
@Inject()
|
||||
tenancy: TenancyService;
|
||||
|
||||
|
||||
@EventDispatcher()
|
||||
eventDispatcher: EventDispatcherInterface;
|
||||
|
||||
@@ -62,6 +63,9 @@ export default class BillsService extends SalesInvoicesCost {
|
||||
@Inject()
|
||||
journalPosterService: JournalPosterService;
|
||||
|
||||
@Inject()
|
||||
vendorsService: VendorsService;
|
||||
|
||||
/**
|
||||
* Validates whether the vendor is exist.
|
||||
* @async
|
||||
@@ -136,16 +140,25 @@ export default class BillsService extends SalesInvoicesCost {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts bill DTO to model.
|
||||
* Validate the bill number require.
|
||||
* @param {string} billNo -
|
||||
*/
|
||||
validateBillNoRequire(billNo: string) {
|
||||
if (!billNo) {
|
||||
throw new ServiceError(ERRORS.BILL_NO_IS_REQUIRED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts create bill DTO to model.
|
||||
* @param {number} tenantId
|
||||
* @param {IBillDTO} billDTO
|
||||
* @param {IBill} oldBill
|
||||
*
|
||||
* @returns {IBill}
|
||||
*/
|
||||
private async billDTOToModel(
|
||||
tenantId: number,
|
||||
billDTO: IBillDTO | IBillEditDTO,
|
||||
billDTO: IBillDTO,
|
||||
authorizedUser: ISystemUser,
|
||||
oldBill?: IBill
|
||||
) {
|
||||
@@ -157,15 +170,25 @@ export default class BillsService extends SalesInvoicesCost {
|
||||
}));
|
||||
const amount = sumBy(entries, 'amount');
|
||||
|
||||
// Bill number from DTO or from auto-increment.
|
||||
const billNumber = billDTO.billNumber || oldBill?.billNumber;
|
||||
|
||||
// Retrieve vendor details by the given vendor id.
|
||||
const vendor = await this.vendorsService.getVendorByIdOrThrowError(
|
||||
tenantId,
|
||||
billDTO.vendorId
|
||||
);
|
||||
return {
|
||||
...formatDateFields(omit(billDTO, ['open', 'entries']), [
|
||||
'billDate',
|
||||
'dueDate',
|
||||
]),
|
||||
amount,
|
||||
currencyCode: vendor.currencyCode,
|
||||
billNumber,
|
||||
entries: entries.map((entry) => ({
|
||||
reference_type: 'Bill',
|
||||
...omit(entry, ['amount', 'id']),
|
||||
...omit(entry, ['amount']),
|
||||
})),
|
||||
// Avoid rewrite the open date in edit mode when already opened.
|
||||
...(billDTO.open &&
|
||||
@@ -205,16 +228,14 @@ export default class BillsService extends SalesInvoicesCost {
|
||||
const billObj = await this.billDTOToModel(
|
||||
tenantId,
|
||||
billDTO,
|
||||
authorizedUser,
|
||||
null
|
||||
authorizedUser
|
||||
);
|
||||
// Retrieve vendor or throw not found service error.
|
||||
await this.getVendorOrThrowError(tenantId, billDTO.vendorId);
|
||||
|
||||
// Validate the bill number uniqiness on the storage.
|
||||
if (billDTO.billNumber) {
|
||||
await this.validateBillNumberExists(tenantId, billDTO.billNumber);
|
||||
}
|
||||
await this.validateBillNumberExists(tenantId, billDTO.billNumber);
|
||||
|
||||
// Validate items IDs existance.
|
||||
await this.itemsEntriesService.validateItemsIdsExistance(
|
||||
tenantId,
|
||||
@@ -277,7 +298,6 @@ export default class BillsService extends SalesInvoicesCost {
|
||||
authorizedUser,
|
||||
oldBill
|
||||
);
|
||||
|
||||
// Retrieve vendor details or throw not found service error.
|
||||
await this.getVendorOrThrowError(tenantId, billDTO.vendorId);
|
||||
|
||||
@@ -292,7 +312,6 @@ export default class BillsService extends SalesInvoicesCost {
|
||||
'Bill',
|
||||
billDTO.entries
|
||||
);
|
||||
|
||||
// Validate the items ids existance on the storage.
|
||||
await this.itemsEntriesService.validateItemsIdsExistance(
|
||||
tenantId,
|
||||
|
||||
@@ -7,4 +7,5 @@ export const ERRORS = {
|
||||
BILL_ENTRIES_IDS_NOT_FOUND: 'BILL_ENTRIES_IDS_NOT_FOUND',
|
||||
NOT_PURCHASE_ABLE_ITEMS: 'NOT_PURCHASE_ABLE_ITEMS',
|
||||
BILL_ALREADY_OPEN: 'BILL_ALREADY_OPEN',
|
||||
BILL_NO_IS_REQUIRED: 'BILL_NO_IS_REQUIRED'
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user