fix: issue in edit payment receive with invoices payment amount chaning.

This commit is contained in:
a.bouhuolia
2020-12-19 17:04:11 +02:00
parent 1a0aad7dc4
commit fb135913bb
8 changed files with 103 additions and 108 deletions

View File

@@ -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);
} }

View File

@@ -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);

View File

@@ -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,

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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,

View File

@@ -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,10 +123,13 @@ 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',
}); });
} }
} }

View File

@@ -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,