mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-20 14:50:32 +00:00
fix: issue in edit payment receive with invoices payment amount chaning.
This commit is contained in:
@@ -80,7 +80,6 @@ export default class PaymentReceivesController extends BaseController {
|
|||||||
*/
|
*/
|
||||||
get paymentReceiveSchema(): ValidationChain[] {
|
get paymentReceiveSchema(): ValidationChain[] {
|
||||||
return [
|
return [
|
||||||
check('customer_id').exists().isNumeric().toInt(),
|
|
||||||
check('payment_date').exists(),
|
check('payment_date').exists(),
|
||||||
check('reference_no').optional(),
|
check('reference_no').optional(),
|
||||||
check('deposit_account_id').exists().isNumeric().toInt(),
|
check('deposit_account_id').exists().isNumeric().toInt(),
|
||||||
@@ -121,7 +120,10 @@ export default class PaymentReceivesController extends BaseController {
|
|||||||
* @return {Array}
|
* @return {Array}
|
||||||
*/
|
*/
|
||||||
get newPaymentReceiveValidation() {
|
get newPaymentReceiveValidation() {
|
||||||
return [...this.paymentReceiveSchema];
|
return [
|
||||||
|
check('customer_id').exists().isNumeric().toInt(),
|
||||||
|
...this.paymentReceiveSchema,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -172,7 +174,10 @@ export default class PaymentReceivesController extends BaseController {
|
|||||||
await this.paymentReceiveService.editPaymentReceive(
|
await this.paymentReceiveService.editPaymentReceive(
|
||||||
tenantId, paymentReceiveId, paymentReceive,
|
tenantId, paymentReceiveId, paymentReceive,
|
||||||
);
|
);
|
||||||
return res.status(200).send({ id: paymentReceiveId });
|
return res.status(200).send({
|
||||||
|
id: paymentReceiveId,
|
||||||
|
message: 'The payment receive has been edited successfully.'
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ export default class SaleInvoicesController extends BaseController {
|
|||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
id: saleInvoiceId,
|
id: saleInvoiceId,
|
||||||
message: 'The given sale invoice has been published successfully',
|
message: 'The given sale invoice has been delivered successfully',
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
next(error);
|
next(error);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export interface IPaymentReceive {
|
|||||||
entries: IPaymentReceiveEntry[],
|
entries: IPaymentReceiveEntry[],
|
||||||
userId: number,
|
userId: number,
|
||||||
};
|
};
|
||||||
export interface IPaymentReceiveDTO {
|
export interface IPaymentReceiveCreateDTO {
|
||||||
customerId: number,
|
customerId: number,
|
||||||
paymentDate: Date,
|
paymentDate: Date,
|
||||||
amount: number,
|
amount: number,
|
||||||
@@ -24,6 +24,16 @@ export interface IPaymentReceiveDTO {
|
|||||||
entries: IPaymentReceiveEntryDTO[],
|
entries: IPaymentReceiveEntryDTO[],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface IPaymentReceiveEditDTO {
|
||||||
|
paymentDate: Date,
|
||||||
|
amount: number,
|
||||||
|
referenceNo: string,
|
||||||
|
depositAccountId: number,
|
||||||
|
paymentReceiveNo?: string,
|
||||||
|
description: string,
|
||||||
|
entries: IPaymentReceiveEntryDTO[],
|
||||||
|
};
|
||||||
|
|
||||||
export interface IPaymentReceiveEntry {
|
export interface IPaymentReceiveEntry {
|
||||||
id?: number,
|
id?: number,
|
||||||
paymentReceiveId: number,
|
paymentReceiveId: number,
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export interface ISaleInvoiceDTO {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ISaleInvoiceCreateDTO extends ISaleInvoiceDTO {
|
export interface ISaleInvoiceCreateDTO extends ISaleInvoiceDTO {
|
||||||
fromEstiamteId: number,
|
fromEstimateId: number,
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface ISaleInvoiceEditDTO extends ISaleInvoiceDTO {
|
export interface ISaleInvoiceEditDTO extends ISaleInvoiceDTO {
|
||||||
|
|||||||
@@ -8,62 +8,6 @@ export default class HasItemEntries {
|
|||||||
@Inject()
|
@Inject()
|
||||||
tenancy: TenancyService;
|
tenancy: TenancyService;
|
||||||
|
|
||||||
/**
|
|
||||||
* Patch items entries to the storage.
|
|
||||||
*
|
|
||||||
* @param {Array} newEntries -
|
|
||||||
* @param {Array} oldEntries -
|
|
||||||
* @param {String} referenceType -
|
|
||||||
* @param {String|Number} referenceId -
|
|
||||||
* @return {Promise}
|
|
||||||
*/
|
|
||||||
async patchItemsEntries(
|
|
||||||
tenantId: number,
|
|
||||||
newEntries: Array<any>,
|
|
||||||
oldEntries: Array<any>,
|
|
||||||
referenceType: string,
|
|
||||||
referenceId: string|number
|
|
||||||
) {
|
|
||||||
const { ItemEntry } = this.tenancy.models(tenantId);
|
|
||||||
|
|
||||||
const entriesHasIds = newEntries.filter((entry) => entry.id);
|
|
||||||
const entriesHasNoIds = newEntries.filter((entry) => !entry.id);
|
|
||||||
const entriesIds = entriesHasIds.map(entry => entry.id);
|
|
||||||
|
|
||||||
const oldEntriesIds = oldEntries.map((e) => e.id);
|
|
||||||
const excludeAttrs = ['id', 'amount'];
|
|
||||||
const opers = [];
|
|
||||||
|
|
||||||
const entriesIdsShouldDelete = difference(
|
|
||||||
oldEntriesIds,
|
|
||||||
entriesIds,
|
|
||||||
);
|
|
||||||
if (entriesIdsShouldDelete.length > 0) {
|
|
||||||
const deleteOper = ItemEntry.query()
|
|
||||||
.whereIn('id', entriesIdsShouldDelete)
|
|
||||||
.delete();
|
|
||||||
opers.push(deleteOper);
|
|
||||||
}
|
|
||||||
entriesHasIds.forEach((entry) => {
|
|
||||||
const updateOper = ItemEntry.query()
|
|
||||||
.where('id', entry.id)
|
|
||||||
.update({
|
|
||||||
...omit(entry, excludeAttrs),
|
|
||||||
});
|
|
||||||
opers.push(updateOper);
|
|
||||||
});
|
|
||||||
entriesHasNoIds.forEach((entry) => {
|
|
||||||
const insertOper = ItemEntry.query()
|
|
||||||
.insert({
|
|
||||||
reference_id: referenceId,
|
|
||||||
reference_type: referenceType,
|
|
||||||
...omit(entry, excludeAttrs),
|
|
||||||
});
|
|
||||||
opers.push(insertOper);
|
|
||||||
});
|
|
||||||
return Promise.all([...opers]);
|
|
||||||
}
|
|
||||||
|
|
||||||
filterNonInventoryEntries(entries: [], items: []) {
|
filterNonInventoryEntries(entries: [], items: []) {
|
||||||
const nonInventoryItems = items.filter((item: any) => item.type !== 'inventory');
|
const nonInventoryItems = items.filter((item: any) => item.type !== 'inventory');
|
||||||
const nonInventoryItemsIds = nonInventoryItems.map((i: any) => i.id);
|
const nonInventoryItemsIds = nonInventoryItems.map((i: any) => i.id);
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import {
|
|||||||
IPaginationMeta,
|
IPaginationMeta,
|
||||||
IPaymentReceive,
|
IPaymentReceive,
|
||||||
IPaymentReceiveDTO,
|
IPaymentReceiveDTO,
|
||||||
|
IPaymentReceiveCreateDTO,
|
||||||
|
IPaymentReceiveEditDTO,
|
||||||
IPaymentReceiveEntry,
|
IPaymentReceiveEntry,
|
||||||
IPaymentReceiveEntryDTO,
|
IPaymentReceiveEntryDTO,
|
||||||
IPaymentReceivesFilter,
|
IPaymentReceivesFilter,
|
||||||
@@ -236,7 +238,7 @@ export default class PaymentReceiveService {
|
|||||||
* @param {number} tenantId - Tenant id.
|
* @param {number} tenantId - Tenant id.
|
||||||
* @param {IPaymentReceive} paymentReceive
|
* @param {IPaymentReceive} paymentReceive
|
||||||
*/
|
*/
|
||||||
public async createPaymentReceive(tenantId: number, paymentReceiveDTO: IPaymentReceiveDTO) {
|
public async createPaymentReceive(tenantId: number, paymentReceiveDTO: IPaymentReceiveCreateDTO) {
|
||||||
const { PaymentReceive } = this.tenancy.models(tenantId);
|
const { PaymentReceive } = this.tenancy.models(tenantId);
|
||||||
const paymentAmount = sumBy(paymentReceiveDTO.entries, 'paymentAmount');
|
const paymentAmount = sumBy(paymentReceiveDTO.entries, 'paymentAmount');
|
||||||
|
|
||||||
@@ -293,7 +295,7 @@ export default class PaymentReceiveService {
|
|||||||
public async editPaymentReceive(
|
public async editPaymentReceive(
|
||||||
tenantId: number,
|
tenantId: number,
|
||||||
paymentReceiveId: number,
|
paymentReceiveId: number,
|
||||||
paymentReceiveDTO: any,
|
paymentReceiveDTO: IPaymentReceiveEditDTO,
|
||||||
) {
|
) {
|
||||||
const { PaymentReceive } = this.tenancy.models(tenantId);
|
const { PaymentReceive } = this.tenancy.models(tenantId);
|
||||||
const paymentAmount = sumBy(paymentReceiveDTO.entries, 'paymentAmount');
|
const paymentAmount = sumBy(paymentReceiveDTO.entries, 'paymentAmount');
|
||||||
@@ -310,14 +312,11 @@ export default class PaymentReceiveService {
|
|||||||
// Validate the deposit account existance and type.
|
// Validate the deposit account existance and type.
|
||||||
this.getDepositAccountOrThrowError(tenantId, paymentReceiveDTO.depositAccountId);
|
this.getDepositAccountOrThrowError(tenantId, paymentReceiveDTO.depositAccountId);
|
||||||
|
|
||||||
// Validate customer existance.
|
|
||||||
await this.customersService.getCustomerByIdOrThrowError(tenantId, paymentReceiveDTO.customerId);
|
|
||||||
|
|
||||||
// Validate the entries ids existance on payment receive type.
|
// Validate the entries ids existance on payment receive type.
|
||||||
await this.validateEntriesIdsExistance(tenantId, paymentReceiveId, paymentReceiveDTO.entries);
|
await this.validateEntriesIdsExistance(tenantId, paymentReceiveId, paymentReceiveDTO.entries);
|
||||||
|
|
||||||
// Validate payment receive invoices IDs existance and associated to the given customer id.
|
// Validate payment receive invoices IDs existance and associated to the given customer id.
|
||||||
await this.validateInvoicesIDsExistance(tenantId, paymentReceiveDTO.customerId, paymentReceiveDTO.entries);
|
await this.validateInvoicesIDsExistance(tenantId, oldPaymentReceive.customerId, paymentReceiveDTO.entries);
|
||||||
|
|
||||||
// Validate invoice payment amount.
|
// Validate invoice payment amount.
|
||||||
await this.validateInvoicesPaymentsAmount(tenantId, paymentReceiveDTO.entries, oldPaymentReceive.entries);
|
await this.validateInvoicesPaymentsAmount(tenantId, paymentReceiveDTO.entries, oldPaymentReceive.entries);
|
||||||
@@ -536,7 +535,7 @@ export default class PaymentReceiveService {
|
|||||||
* @param {number} tenantId - Tenant id.
|
* @param {number} tenantId - Tenant id.
|
||||||
* @param {Array} paymentReceiveEntries
|
* @param {Array} paymentReceiveEntries
|
||||||
* @param {Array} newPaymentReceiveEntries
|
* @param {Array} newPaymentReceiveEntries
|
||||||
* @return
|
* @return {Promise<void>}
|
||||||
*/
|
*/
|
||||||
public async saveChangeInvoicePaymentAmount(
|
public async saveChangeInvoicePaymentAmount(
|
||||||
tenantId: number,
|
tenantId: number,
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ export default class PaymentReceivesSubscriber {
|
|||||||
this.tenancy = Container.get(TenancyService);
|
this.tenancy = Container.get(TenancyService);
|
||||||
this.logger = Container.get('logger');
|
this.logger = Container.get('logger');
|
||||||
this.paymentReceivesService = Container.get(PaymentReceiveService);
|
this.paymentReceivesService = Container.get(PaymentReceiveService);
|
||||||
|
|
||||||
this.settingsService = Container.get(SettingsService);
|
this.settingsService = Container.get(SettingsService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,39 +24,17 @@ export default class PaymentReceivesSubscriber {
|
|||||||
* Handle customer balance decrement once payment receive created.
|
* Handle customer balance decrement once payment receive created.
|
||||||
*/
|
*/
|
||||||
@On(events.paymentReceive.onCreated)
|
@On(events.paymentReceive.onCreated)
|
||||||
async handleCustomerBalanceDecrement({ tenantId, paymentReceiveId, paymentReceive }) {
|
async handleCustomerBalanceDecrement({
|
||||||
|
tenantId,
|
||||||
|
paymentReceiveId,
|
||||||
|
paymentReceive,
|
||||||
|
}) {
|
||||||
const { customerRepository } = this.tenancy.repositories(tenantId);
|
const { customerRepository } = this.tenancy.repositories(tenantId);
|
||||||
|
|
||||||
this.logger.info('[payment_receive] trying to decrement customer balance.');
|
this.logger.info('[payment_receive] trying to decrement customer balance.');
|
||||||
await customerRepository.changeBalance(paymentReceive.customerId, paymentReceive.amount * -1);
|
await customerRepository.changeBalance(
|
||||||
}
|
paymentReceive.customerId,
|
||||||
|
paymentReceive.amount * -1
|
||||||
/**
|
|
||||||
* Handle sale invoice increment/decrement payment amount once created, edited or deleted.
|
|
||||||
*/
|
|
||||||
@On(events.paymentReceive.onCreated)
|
|
||||||
@On(events.paymentReceive.onEdited)
|
|
||||||
async handleInvoiceIncrementPaymentAmount({ tenantId, paymentReceiveId, paymentReceive, oldPaymentReceive }) {
|
|
||||||
|
|
||||||
this.logger.info('[payment_receive] trying to change sale invoice payment amount.', { tenantId });
|
|
||||||
await this.paymentReceivesService.saveChangeInvoicePaymentAmount(
|
|
||||||
tenantId,
|
|
||||||
paymentReceive.entries,
|
|
||||||
oldPaymentReceive?.entries || null,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle revert invoices payment amount once payment receive deleted.
|
|
||||||
*/
|
|
||||||
@On(events.paymentReceive.onDeleted)
|
|
||||||
async handleInvoiceDecrementPaymentAmount({ tenantId, paymentReceiveId, oldPaymentReceive }) {
|
|
||||||
this.logger.info('[payment_receive] trying to decrement sale invoice payment amount.');
|
|
||||||
|
|
||||||
await this.paymentReceivesService.saveChangeInvoicePaymentAmount(
|
|
||||||
tenantId,
|
|
||||||
oldPaymentReceive.entries.map((entry) => ({ ...entry, paymentAmount: 0 })),
|
|
||||||
oldPaymentReceive.entries,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,13 +42,17 @@ export default class PaymentReceivesSubscriber {
|
|||||||
* Handle customer balance increment once payment receive deleted.
|
* Handle customer balance increment once payment receive deleted.
|
||||||
*/
|
*/
|
||||||
@On(events.paymentReceive.onDeleted)
|
@On(events.paymentReceive.onDeleted)
|
||||||
async handleCustomerBalanceIncrement({ tenantId, paymentReceiveId, oldPaymentReceive }) {
|
async handleCustomerBalanceIncrement({
|
||||||
|
tenantId,
|
||||||
|
paymentReceiveId,
|
||||||
|
oldPaymentReceive,
|
||||||
|
}) {
|
||||||
const { customerRepository } = this.tenancy.repositories(tenantId);
|
const { customerRepository } = this.tenancy.repositories(tenantId);
|
||||||
|
|
||||||
this.logger.info('[payment_receive] trying to increment customer balance.');
|
this.logger.info('[payment_receive] trying to increment customer balance.');
|
||||||
await customerRepository.changeBalance(
|
await customerRepository.changeBalance(
|
||||||
oldPaymentReceive.customerId,
|
oldPaymentReceive.customerId,
|
||||||
oldPaymentReceive.amount,
|
oldPaymentReceive.amount
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,14 +60,62 @@ export default class PaymentReceivesSubscriber {
|
|||||||
* Handles customer balance diff balance change once payment receive edited.
|
* Handles customer balance diff balance change once payment receive edited.
|
||||||
*/
|
*/
|
||||||
@On(events.paymentReceive.onEdited)
|
@On(events.paymentReceive.onEdited)
|
||||||
async handleCustomerBalanceDiffChange({ tenantId, paymentReceiveId, paymentReceive, oldPaymentReceive }) {
|
async handleCustomerBalanceDiffChange({
|
||||||
|
tenantId,
|
||||||
|
paymentReceiveId,
|
||||||
|
paymentReceive,
|
||||||
|
oldPaymentReceive,
|
||||||
|
}) {
|
||||||
const { customerRepository } = this.tenancy.repositories(tenantId);
|
const { customerRepository } = this.tenancy.repositories(tenantId);
|
||||||
|
|
||||||
await customerRepository.changeDiffBalance(
|
await customerRepository.changeDiffBalance(
|
||||||
paymentReceive.customerId,
|
paymentReceive.customerId,
|
||||||
paymentReceive.amount * -1,
|
paymentReceive.amount * -1,
|
||||||
oldPaymentReceive.amount * -1,
|
oldPaymentReceive.amount * -1,
|
||||||
oldPaymentReceive.customerId,
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle sale invoice increment/decrement payment amount once created, edited or deleted.
|
||||||
|
*/
|
||||||
|
@On(events.paymentReceive.onCreated)
|
||||||
|
@On(events.paymentReceive.onEdited)
|
||||||
|
async handleInvoiceIncrementPaymentAmount({
|
||||||
|
tenantId,
|
||||||
|
paymentReceiveId,
|
||||||
|
paymentReceive,
|
||||||
|
oldPaymentReceive,
|
||||||
|
}) {
|
||||||
|
this.logger.info(
|
||||||
|
'[payment_receive] trying to change sale invoice payment amount.',
|
||||||
|
{ tenantId }
|
||||||
|
);
|
||||||
|
await this.paymentReceivesService.saveChangeInvoicePaymentAmount(
|
||||||
|
tenantId,
|
||||||
|
paymentReceive.entries,
|
||||||
|
oldPaymentReceive?.entries || null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle revert invoices payment amount once payment receive deleted.
|
||||||
|
*/
|
||||||
|
@On(events.paymentReceive.onDeleted)
|
||||||
|
async handleInvoiceDecrementPaymentAmount({
|
||||||
|
tenantId,
|
||||||
|
paymentReceiveId,
|
||||||
|
oldPaymentReceive,
|
||||||
|
}) {
|
||||||
|
this.logger.info(
|
||||||
|
'[payment_receive] trying to decrement sale invoice payment amount.'
|
||||||
|
);
|
||||||
|
await this.paymentReceivesService.saveChangeInvoicePaymentAmount(
|
||||||
|
tenantId,
|
||||||
|
oldPaymentReceive.entries.map((entry) => ({
|
||||||
|
...entry,
|
||||||
|
paymentAmount: 0,
|
||||||
|
})),
|
||||||
|
oldPaymentReceive.entries
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +123,10 @@ export default class PaymentReceivesSubscriber {
|
|||||||
* Handles increment next number of payment receive once be created.
|
* Handles increment next number of payment receive once be created.
|
||||||
*/
|
*/
|
||||||
@On(events.paymentReceive.onCreated)
|
@On(events.paymentReceive.onCreated)
|
||||||
public async handlePaymentNextNumberIncrement({ tenantId, paymentReceiveId }) {
|
public async handlePaymentNextNumberIncrement({
|
||||||
|
tenantId,
|
||||||
|
paymentReceiveId,
|
||||||
|
}) {
|
||||||
await this.settingsService.incrementNextNumber(tenantId, {
|
await this.settingsService.incrementNextNumber(tenantId, {
|
||||||
key: 'next_number',
|
key: 'next_number',
|
||||||
group: 'payment_receives',
|
group: 'payment_receives',
|
||||||
|
|||||||
@@ -190,10 +190,15 @@ const entriesAmountDiff = (
|
|||||||
.mapValues((group) => _.sumBy(group, amountAttribute) || 0)
|
.mapValues((group) => _.sumBy(group, amountAttribute) || 0)
|
||||||
.value();
|
.value();
|
||||||
|
|
||||||
return _.chain(newEntries)
|
const newEntriesTable = _.chain(newEntries)
|
||||||
.groupBy(idAttribute)
|
.groupBy(idAttribute)
|
||||||
.mapValues((group) => _.sumBy(group, amountAttribute) || 0)
|
.mapValues((group) => _.sumBy(group, amountAttribute) || 0)
|
||||||
.mapValues((value, key) => value - (oldEntriesTable[key] || 0))
|
.mergeWith(oldEntriesTable, (objValue, srcValue) => {
|
||||||
|
return (_.isNumber(objValue) ? objValue - srcValue : srcValue * -1);
|
||||||
|
})
|
||||||
|
.value();
|
||||||
|
|
||||||
|
return _.chain(newEntriesTable)
|
||||||
.mapValues((value, key) => ({
|
.mapValues((value, key) => ({
|
||||||
[idAttribute]: key,
|
[idAttribute]: key,
|
||||||
[amountAttribute]: value,
|
[amountAttribute]: value,
|
||||||
|
|||||||
Reference in New Issue
Block a user