refactoring: payment made form.

This commit is contained in:
a.bouhuolia
2021-02-21 13:00:06 +02:00
parent 265198103d
commit df2d215071
25 changed files with 542 additions and 145 deletions

View File

@@ -17,14 +17,32 @@ export default class FinancialStatementsService {
router() {
const router = Router();
router.use('/balance_sheet', Container.get(BalanceSheetController).router());
router.use('/profit_loss_sheet', Container.get(ProfitLossController).router());
router.use('/general_ledger', Container.get(GeneralLedgerController).router());
router.use('/trial_balance_sheet', Container.get(TrialBalanceSheetController).router());
router.use(
'/balance_sheet',
Container.get(BalanceSheetController).router()
);
router.use(
'/profit_loss_sheet',
Container.get(ProfitLossController).router()
);
router.use(
'/general_ledger',
Container.get(GeneralLedgerController).router()
);
router.use(
'/trial_balance_sheet',
Container.get(TrialBalanceSheetController).router()
);
router.use('/journal', Container.get(JournalSheetController).router());
router.use('/receivable_aging_summary', Container.get(ARAgingSummary).router());
router.use('/payable_aging_summary', Container.get(APAgingSummary).router());
router.use(
'/receivable_aging_summary',
Container.get(ARAgingSummary).router()
);
router.use(
'/payable_aging_summary',
Container.get(APAgingSummary).router()
);
return router;
}
};
}

View File

@@ -8,6 +8,7 @@ import BillPaymentsService from 'services/Purchases/BillPayments';
import DynamicListingService from 'services/DynamicListing/DynamicListService';
import AccountsService from 'services/Accounts/AccountsService';
import ResourceController from '../Resources';
import { Request } from 'express-validator/src/base';
/**
* Bills payments controller.
@@ -30,6 +31,20 @@ export default class BillsPayments extends BaseController {
router() {
const router = Router();
router.get(
'/new-page/entries',
[query('vendor_id').exists()],
this.validationResult,
asyncMiddleware(this.getBillPaymentNewPageEntries.bind(this)),
this.handleServiceError
);
router.get(
'/:id/edit-page',
this.specificBillPaymentValidateSchema,
this.validationResult,
asyncMiddleware(this.getBillPaymentEditPage.bind(this)),
this.handleServiceError
);
router.post(
'/',
[...this.billPaymentSchemaValidation],
@@ -76,6 +91,7 @@ export default class BillsPayments extends BaseController {
this.handleServiceError,
this.dynamicListService.handlerErrorsToResponse
);
return router;
}
@@ -118,6 +134,53 @@ export default class BillsPayments extends BaseController {
];
}
/**
* Retrieve bill payment new page entries.
* @param {Request} req -
* @param {Response} res -
*/
async getBillPaymentNewPageEntries(req: Request, res: Response) {
const { tenantId } = req;
const { vendorId } = this.matchedQueryData(req);
try {
const entries = await this.billPaymentService.getNewPageEntries(
tenantId,
vendorId
);
return res.status(200).send({
entries: this.transfromToResponse(entries),
});
} catch (error) {}
}
/**
* Retrieve the bill payment edit page details.
* @param {Request} req
* @param {Response} res
*/
async getBillPaymentEditPage(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req;
const { id: paymentReceiveId } = req.params;
try {
const {
billPayment,
entries,
} = await this.billPaymentService.getBillPaymentEditPage(
tenantId,
paymentReceiveId,
);
return res.status(200).send({
bill_payment: this.transfromToResponse(billPayment),
entries: this.transfromToResponse(entries),
});
} catch (error) {
next(error);
}
}
/**
* Creates a bill payment.
* @async

View File

@@ -54,6 +54,15 @@ export default class PaymentReceivesController extends BaseController {
asyncMiddleware(this.getPaymentReceiveEditPage.bind(this)),
this.handleServiceErrors
);
router.get(
'/new-page/entries',
[
query('customer_id').exists().isNumeric().toInt(),
],
this.validationResult,
asyncMiddleware(this.getPaymentReceiveNewPageEntries.bind(this)),
this.getPaymentReceiveNewPageEntries.bind(this)
);
router.get(
'/',
this.validatePaymentReceiveList,
@@ -303,6 +312,26 @@ export default class PaymentReceivesController extends BaseController {
}
}
/**
* Retrieve payment receive new page receivable entries.
* @param {Request} req - Request.
* @param {Response} res - Response.
*/
async getPaymentReceiveNewPageEntries(req, res) {
const { tenantId } = req;
const { customerId } = this.matchedQueryData(req);
try {
const entries = await this.paymentReceiveService.getNewPageEntries(
tenantId,
customerId
);
return res.status(200).send({
entries: this.transfromToResponse(entries),
});
} catch (error) {}
}
/**
* Handles service errors.
* @param error

View File

@@ -32,4 +32,15 @@ export interface IBillPaymentDTO {
description: string,
reference: string,
entries: IBillPaymentEntryDTO[],
};
export interface IBillReceivePageEntry {
billId: number,
entryType: string,
billNo: string,
dueAmount: number,
amount: number,
totalPaymentAmount: number,
paymentAmount: number,
date: Date|string,
};

View File

@@ -52,7 +52,7 @@ export interface IPaymentReceivesFilter extends IDynamicListFilterDTO {
stringifiedFilterRoles?: string,
}
export interface IPaymentReceiveEditPageEntry {
export interface IPaymentReceivePageEntry {
invoiceId: number,
entryType: string,
invoiceNo: string,
@@ -65,5 +65,5 @@ export interface IPaymentReceiveEditPageEntry {
export interface IPaymentReceiveEditPage {
paymentReceive: IPaymentReceive,
entries: IPaymentReceiveEditPageEntry[];
entries: IPaymentReceivePageEntry[];
};

View File

@@ -15,6 +15,7 @@ import {
IPaginationMeta,
IFilterMeta,
IBillPaymentEntry,
IBillReceivePageEntry,
} from 'interfaces';
import AccountsService from 'services/Accounts/AccountsService';
import JournalPoster from 'services/Accounting/JournalPoster';
@@ -26,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 PayableAgingSummaryService from 'services/FinancialStatements/AgingSummary/APAgingSummaryService';
const ERRORS = {
BILL_VENDOR_NOT_FOUND: 'VENDOR_NOT_FOUND',
@@ -598,48 +600,43 @@ export default class BillPaymentsService {
* @param {number} billPaymentId - The bill payment id.
* @return {object}
*/
public async getBillPayment(
public async getBillPaymentEditPage(
tenantId: number,
billPaymentId: number
): Promise<{
billPayment: IBillPayment;
payableBills: IBill[];
paymentMadeBills: IBill[];
billPayment: Omit<IBillPayment, "entries">;
entries: IBillReceivePageEntry[];
}> {
const { BillPayment, Bill } = this.tenancy.models(tenantId);
const billPayment = await BillPayment.query()
.findById(billPaymentId)
.withGraphFetched('entries.bill')
.withGraphFetched('vendor')
.withGraphFetched('paymentAccount');
.withGraphFetched('entries.bill');
// Throw not found the bill payment.
if (!billPayment) {
throw new ServiceError(ERRORS.PAYMENT_MADE_NOT_FOUND);
}
const billsIds = billPayment.entries.map((entry) => entry.billId);
// Retrieve all payable bills that assocaited to the payment made transaction.
const payableBills = await Bill.query()
.modify('dueBills')
.whereNotIn('id', billsIds)
.where('vendor_id', billPayment.vendorId)
.orderBy('bill_date', 'ASC');
// Retrieve all payment made assocaited bills.
const paymentMadeBills = billPayment.entries.map((entry) => ({
...entry.bill,
dueAmount: entry.bill.dueAmount + entry.paymentAmount,
const paymentEntries = billPayment.entries.map((entry) => ({
...this.mapBillToPageEntry(entry.bill),
paymentAmount: entry.paymentAmount,
}));
const resPayableBills = await Bill.query()
.modify('dueBills')
.where('vendor_id', billPayment.vendorId)
.whereNotIn(
'id',
billPayment.entries.map((e) => e.billId),
)
.orderBy('bill_date', 'ASC');
// Mapping the payable bills to entries.
const restPayableEntries = resPayableBills.map(this.mapBillToPageEntry);
const entries = [...paymentEntries, ...restPayableEntries];
return {
billPayment: {
...billPayment,
entries: billPayment.entries.map((entry) => ({
...omit(entry, ['bill']),
})),
},
payableBills,
paymentMadeBills,
billPayment: omit(billPayment, ['entries']),
entries
};
}
@@ -678,4 +675,55 @@ export default class BillPaymentsService {
);
await Promise.all(opers);
}
/**
* Retrive edit page invoices entries from the given sale invoices models.
* @param {ISaleInvoice[]} invoices - Invoices.
* @return {IPaymentReceiveEditPageEntry}
*/
public mapBillToPageEntry(bill: IBill): IBillReceivePageEntry {
return {
entryType: 'invoice',
billId: bill.id,
dueAmount: bill.dueAmount + bill.paymentAmount,
amount: bill.amount,
billNo: bill.billNumber,
totalPaymentAmount: bill.paymentAmount,
paymentAmount: bill.paymentAmount,
date: bill.billDate,
};
}
public mapBillToNewPageEntry(bill: IBill): IBillReceivePageEntry {
return {
entryType: 'invoice',
billId: bill.id,
dueAmount: bill.dueAmount,
amount: bill.amount,
billNo: bill.billNumber,
date: bill.billDate,
totalPaymentAmount: bill.paymentAmount,
paymentAmount: 0,
}
}
/**
* Retrieve the payable entries of the new page once vendor be selected.
* @param {number} tenantId
* @param {number} vendorId
*/
async getNewPageEntries(
tenantId: number,
vendorId: number,
): Promise<IBillReceivePageEntry[]> {
const { Bill } = this.tenancy.models(tenantId);
// Retrieve all payable bills that assocaited to the payment made transaction.
const payableBills = await Bill.query()
.modify('dueBills')
.where('vendor_id', vendorId)
.orderBy('bill_date', 'ASC');
return payableBills.map(this.mapBillToNewPageEntry);
}
}

View File

@@ -18,7 +18,7 @@ import {
ISaleInvoice,
ISystemService,
ISystemUser,
IPaymentReceiveEditPageEntry,
IPaymentReceivePageEntry,
} from 'interfaces';
import AccountsService from 'services/Accounts/AccountsService';
import JournalPoster from 'services/Accounting/JournalPoster';
@@ -471,7 +471,7 @@ export default class PaymentReceiveService {
* @param {ISaleInvoice[]} invoices - Invoices.
* @return {IPaymentReceiveEditPageEntry}
*/
public invoicesToEditPageEntries(
public invoiceToPageEntry(
invoice: ISaleInvoice
): IPaymentReceiveEditPageEntry {
return {
@@ -485,7 +485,7 @@ export default class PaymentReceiveService {
date: invoice.invoiceDate,
};
}
/**
* Retrieve the payment receive details of the given id.
* @param {number} tenantId - Tenant id.
@@ -494,9 +494,10 @@ export default class PaymentReceiveService {
public async getPaymentReceiveEditPage(
tenantId: number,
paymentReceiveId: number,
authorizedUser: ISystemUser
): Promise<{
paymentReceive: IPaymentReceive;
entries: IPaymentReceiveEditPageEntry[];
paymentReceive: Omit<IPaymentReceive, "entries">;
entries: IPaymentReceivePageEntry[];
}> {
const { PaymentReceive, SaleInvoice } = this.tenancy.models(tenantId);
@@ -509,14 +510,8 @@ export default class PaymentReceiveService {
if (!paymentReceive) {
throw new ServiceError(ERRORS.PAYMENT_RECEIVE_NOT_EXISTS);
}
// Mapping the entries invoices.
const entriesInvoicesIds = paymentReceive.entries.map(
(entry) => entry.invoiceId
);
const paymentEntries = paymentReceive.entries.map((entry) => ({
...this.invoicesToEditPageEntries(entry.invoice),
...this.invoiceToPageEntry(entry.invoice),
paymentAmount: entry.paymentAmount,
}));
@@ -524,17 +519,16 @@ export default class PaymentReceiveService {
const restReceivableInvoices = await SaleInvoice.query()
.modify('dueInvoices')
.where('customer_id', paymentReceive.customerId)
.whereNotIn('id', entriesInvoicesIds)
.whereNotIn(
'id',
paymentReceive.entries.map((entry) => entry.invoiceId)
)
.orderBy('invoice_date', 'ASC');
const restReceivableEntries = restReceivableInvoices.map(
this.invoicesToEditPageEntries
this.invoiceToPageEntry
);
const entries = [
...paymentEntries,
...restReceivableEntries,
];
const entries = [...paymentEntries, ...restReceivableEntries];
return {
paymentReceive: omit(paymentReceive, ['entries']),
@@ -616,6 +610,7 @@ export default class PaymentReceiveService {
paymentReceiveId: number
) {
const { PaymentReceive } = this.tenancy.models(tenantId);
return PaymentReceive.query()
.where('id', paymentReceiveId)
.withGraphFetched('invoices')
@@ -739,7 +734,6 @@ export default class PaymentReceiveService {
if (diffEntry.paymentAmount === 0) {
return;
}
const oper = SaleInvoice.changePaymentAmount(
diffEntry.invoiceId,
diffEntry.paymentAmount
@@ -748,4 +742,22 @@ export default class PaymentReceiveService {
});
await Promise.all([...opers]);
}
/**
* Retrieve payment receive new page receivable entries.
* @param {number} tenantId - Tenant id.
* @param {number} vendorId - Vendor id.
* @return {IPaymentReceivePageEntry[]}
*/
async getNewPageEntries(tenantId: number, customerId: number) {
const { SaleInvoice } = this.tenancy.models(tenantId);
// Retrieve due invoices.
const entries = await SaleInvoice.query()
.modify('dueInvoices')
.where('customer_id', customerId)
.orderBy('invoice_date', 'ASC');
return entries.map(this.invoiceToPageEntry);
}
}