hotfix(server): Unhandled thrown errors of services (#329)

This commit is contained in:
Ahmed Bouhuolia
2024-01-22 21:57:14 +02:00
committed by GitHub
parent e42adcae63
commit 7eb84474a5
8 changed files with 171 additions and 224 deletions

View File

@@ -303,7 +303,7 @@ export default class BillsController extends BaseController {
try { try {
const bill = await this.billsApplication.getBill(tenantId, billId); const bill = await this.billsApplication.getBill(tenantId, billId);
return res.status(200).send(this.transfromToResponse({ bill })); return res.status(200).send({ bill });
} catch (error) { } catch (error) {
next(error); next(error);
} }
@@ -348,14 +348,11 @@ export default class BillsController extends BaseController {
}; };
try { try {
const { bills, pagination, filterMeta } = const billsWithPagination = await this.billsApplication.getBills(
await this.billsApplication.getBills(tenantId, filter); tenantId,
filter
return res.status(200).send({ );
bills: this.transfromToResponse(bills), return res.status(200).send(billsWithPagination);
pagination: this.transfromToResponse(pagination),
filter_meta: this.transfromToResponse(filterMeta),
});
} catch (error) { } catch (error) {
next(error); next(error);
} }

View File

@@ -158,15 +158,11 @@ export default class BillsPayments extends BaseController {
const { tenantId } = req; const { tenantId } = req;
const { vendorId } = this.matchedQueryData(req); const { vendorId } = this.matchedQueryData(req);
try { const entries = await this.billPaymentsPages.getNewPageEntries(
const entries = await this.billPaymentsPages.getNewPageEntries( tenantId,
tenantId, vendorId
vendorId );
); return res.status(200).send({ entries });
return res.status(200).send({
entries: this.transfromToResponse(entries),
});
} catch (error) {}
} }
/** /**
@@ -183,16 +179,12 @@ export default class BillsPayments extends BaseController {
const { id: paymentReceiveId } = req.params; const { id: paymentReceiveId } = req.params;
try { try {
const { billPayment, entries } = const billPaymentsWithEditEntries =
await this.billPaymentsPages.getBillPaymentEditPage( await this.billPaymentsPages.getBillPaymentEditPage(
tenantId, tenantId,
paymentReceiveId paymentReceiveId
); );
return res.status(200).send(billPaymentsWithEditEntries);
return res.status(200).send({
bill_payment: this.transfromToResponse(billPayment),
entries: this.transfromToResponse(entries),
});
} catch (error) { } catch (error) {
next(error); next(error);
} }
@@ -304,9 +296,7 @@ export default class BillsPayments extends BaseController {
tenantId, tenantId,
billPaymentId billPaymentId
); );
return res.status(200).send({ return res.status(200).send({ billPayment });
bill_payment: this.transfromToResponse(billPayment),
});
} catch (error) { } catch (error) {
next(error); next(error);
} }
@@ -359,17 +349,12 @@ export default class BillsPayments extends BaseController {
}; };
try { try {
const { billPayments, pagination, filterMeta } = const billPaymentsWithPagination =
await this.billPaymentsApplication.getBillPayments( await this.billPaymentsApplication.getBillPayments(
tenantId, tenantId,
billPaymentsFilter billPaymentsFilter
); );
return res.status(200).send(billPaymentsWithPagination);
return res.status(200).send({
bill_payments: this.transfromToResponse(billPayments),
pagination: this.transfromToResponse(pagination),
filter_meta: this.transfromToResponse(filterMeta),
});
} catch (error) { } catch (error) {
next(error); next(error);
} }

View File

@@ -26,6 +26,7 @@ import GetCreditNoteAssociatedInvoicesToApply from '@/services/CreditNotes/GetCr
import GetCreditNoteAssociatedAppliedInvoices from '@/services/CreditNotes/GetCreditNoteAssociatedAppliedInvoices'; import GetCreditNoteAssociatedAppliedInvoices from '@/services/CreditNotes/GetCreditNoteAssociatedAppliedInvoices';
import GetRefundCreditTransaction from '@/services/CreditNotes/GetRefundCreditNoteTransaction'; import GetRefundCreditTransaction from '@/services/CreditNotes/GetRefundCreditNoteTransaction';
import GetCreditNotePdf from '../../../services/CreditNotes/GetCreditNotePdf'; import GetCreditNotePdf from '../../../services/CreditNotes/GetCreditNotePdf';
import { ACCEPT_TYPE } from '@/interfaces/Http';
/** /**
* Credit notes controller. * Credit notes controller.
* @service * @service
@@ -438,7 +439,7 @@ export default class PaymentReceivesController extends BaseController {
}; };
/** /**
* Retrieve the payment receive details. * Retrieve the credit note details.
* @param {Request} req * @param {Request} req
* @param {Response} res * @param {Response} res
* @param {NextFunction} next * @param {NextFunction} next
@@ -451,38 +452,28 @@ export default class PaymentReceivesController extends BaseController {
const { tenantId } = req; const { tenantId } = req;
const { id: creditNoteId } = req.params; const { id: creditNoteId } = req.params;
try { const accept = this.accepts(req);
const acceptType = accept.types([
ACCEPT_TYPE.APPLICATION_JSON,
ACCEPT_TYPE.APPLICATION_PDF,
]);
if (ACCEPT_TYPE.APPLICATION_PDF === acceptType) {
const pdfContent = await this.creditNotePdf.getCreditNotePdf(
tenantId,
creditNoteId
);
res.set({
'Content-Type': 'application/pdf',
'Content-Length': pdfContent.length,
});
res.send(pdfContent);
} else {
const creditNote = await this.getCreditNoteService.getCreditNote( const creditNote = await this.getCreditNoteService.getCreditNote(
tenantId, tenantId,
creditNoteId creditNoteId
); );
const ACCEPT_TYPE = { return res.status(200).send({ creditNote });
APPLICATION_PDF: 'application/pdf',
APPLICATION_JSON: 'application/json',
};
// Response formatter.
res.format({
// Json content type.
[ACCEPT_TYPE.APPLICATION_JSON]: () => {
return res
.status(200)
.send({ credit_note: this.transfromToResponse(creditNote) });
},
// Pdf content type.
[ACCEPT_TYPE.APPLICATION_PDF]: async () => {
const pdfContent = await this.creditNotePdf.getCreditNotePdf(
tenantId,
creditNote
);
res.set({
'Content-Type': 'application/pdf',
'Content-Length': pdfContent.length,
});
res.send(pdfContent);
},
});
} catch (error) {
next(error);
} }
}; };

View File

@@ -14,6 +14,7 @@ import DynamicListingService from '@/services/DynamicListing/DynamicListService'
import { PaymentReceivesApplication } from '@/services/Sales/PaymentReceives/PaymentReceivesApplication'; import { PaymentReceivesApplication } from '@/services/Sales/PaymentReceives/PaymentReceivesApplication';
import CheckPolicies from '@/api/middleware/CheckPolicies'; import CheckPolicies from '@/api/middleware/CheckPolicies';
import { ServiceError } from '@/exceptions'; import { ServiceError } from '@/exceptions';
import { ACCEPT_TYPE } from '@/interfaces/Http';
@Service() @Service()
export default class PaymentReceivesController extends BaseController { export default class PaymentReceivesController extends BaseController {
@@ -348,17 +349,12 @@ export default class PaymentReceivesController extends BaseController {
}; };
try { try {
const { paymentReceives, pagination, filterMeta } = const paymentsReceivedWithPagination =
await this.paymentReceiveApplication.getPaymentReceives( await this.paymentReceiveApplication.getPaymentReceives(
tenantId, tenantId,
filter filter
); );
return res.status(200).send(paymentsReceivedWithPagination);
return res.status(200).send({
payment_receives: this.transfromToResponse(paymentReceives),
pagination: this.transfromToResponse(pagination),
filter_meta: this.transfromToResponse(filterMeta),
});
} catch (error) { } catch (error) {
next(error); next(error);
} }
@@ -435,37 +431,34 @@ export default class PaymentReceivesController extends BaseController {
const { tenantId } = req; const { tenantId } = req;
const { id: paymentReceiveId } = req.params; const { id: paymentReceiveId } = req.params;
try { const accept = this.accepts(req);
const ACCEPT_TYPE = {
APPLICATION_PDF: 'application/pdf', const acceptType = accept.types([
APPLICATION_JSON: 'application/json', ACCEPT_TYPE.APPLICATION_JSON,
}; ACCEPT_TYPE.APPLICATION_PDF,
res.format({ ]);
[ACCEPT_TYPE.APPLICATION_JSON]: async () => { // Response in pdf format.
const paymentReceive = if (ACCEPT_TYPE.APPLICATION_PDF === acceptType) {
await this.paymentReceiveApplication.getPaymentReceive( const pdfContent =
tenantId, await this.paymentReceiveApplication.getPaymentReceivePdf(
paymentReceiveId tenantId,
); paymentReceiveId
return res.status(200).send({ );
payment_receive: paymentReceive, res.set({
}); 'Content-Type': 'application/pdf',
}, 'Content-Length': pdfContent.length,
[ACCEPT_TYPE.APPLICATION_PDF]: async () => { });
const pdfContent = res.send(pdfContent);
await this.paymentReceiveApplication.getPaymentReceivePdf( // Response in json format.
tenantId, } else {
paymentReceiveId const paymentReceive =
); await this.paymentReceiveApplication.getPaymentReceive(
res.set({ tenantId,
'Content-Type': 'application/pdf', paymentReceiveId
'Content-Length': pdfContent.length, );
}); return res.status(200).send({
res.send(pdfContent); payment_receive: paymentReceive,
},
}); });
} catch (error) {
next(error);
} }
} }
@@ -499,7 +492,7 @@ export default class PaymentReceivesController extends BaseController {
}; };
/** /**
* * Retrieves the sms details of the given payment receive.
* @param {Request} req * @param {Request} req
* @param {Response} res * @param {Response} res
* @param {NextFunction} next * @param {NextFunction} next
@@ -588,10 +581,10 @@ export default class PaymentReceivesController extends BaseController {
/** /**
* Handles service errors. * Handles service errors.
* @param error * @param {Error} error
* @param req * @param {Request} req
* @param res * @param {Response} res
* @param next * @param {NextFunction} next
*/ */
private handleServiceErrors( private handleServiceErrors(
error: Error, error: Error,

View File

@@ -334,7 +334,6 @@ export default class SalesEstimatesController extends BaseController {
tenantId, tenantId,
estimateId estimateId
); );
return res.status(200).send({ return res.status(200).send({
id: estimateId, id: estimateId,
message: 'The sale estimate has been approved successfully.', message: 'The sale estimate has been approved successfully.',
@@ -363,7 +362,6 @@ export default class SalesEstimatesController extends BaseController {
tenantId, tenantId,
estimateId estimateId
); );
return res.status(200).send({ return res.status(200).send({
id: estimateId, id: estimateId,
message: 'The sale estimate has been rejected successfully.', message: 'The sale estimate has been rejected successfully.',
@@ -383,33 +381,30 @@ export default class SalesEstimatesController extends BaseController {
const { id: estimateId } = req.params; const { id: estimateId } = req.params;
const { tenantId } = req; const { tenantId } = req;
try { const accept = this.accepts(req);
// Response formatter.
res.format({ const acceptType = accept.types([
// JSON content type. ACCEPT_TYPE.APPLICATION_JSON,
[ACCEPT_TYPE.APPLICATION_JSON]: async () => { ACCEPT_TYPE.APPLICATION_PDF,
const estimate = await this.saleEstimatesApplication.getSaleEstimate( ]);
tenantId, // Retrieves estimate in pdf format.
estimateId if (ACCEPT_TYPE.APPLICATION_PDF == acceptType) {
); const pdfContent = await this.saleEstimatesApplication.getSaleEstimatePdf(
return res.status(200).send({ estimate }); tenantId,
}, estimateId
// PDF content type. );
[ACCEPT_TYPE.APPLICATION_PDF]: async () => { res.set({
const pdfContent = 'Content-Type': 'application/pdf',
await this.saleEstimatesApplication.getSaleEstimatePdf( 'Content-Length': pdfContent.length,
tenantId,
estimateId
);
res.set({
'Content-Type': 'application/pdf',
'Content-Length': pdfContent.length,
});
res.send(pdfContent);
},
}); });
} catch (error) { res.send(pdfContent);
next(error); // Retrieves estimates in json format.
} else {
const estimate = await this.saleEstimatesApplication.getSaleEstimate(
tenantId,
estimateId
);
return res.status(200).send({ estimate });
} }
} }
@@ -427,22 +422,11 @@ export default class SalesEstimatesController extends BaseController {
pageSize: 12, pageSize: 12,
...this.matchedQueryData(req), ...this.matchedQueryData(req),
}; };
try { try {
const { salesEstimates, pagination, filterMeta } = const salesEstimatesWithPagination =
await this.saleEstimatesApplication.getSaleEstimates(tenantId, filter); await this.saleEstimatesApplication.getSaleEstimates(tenantId, filter);
res.format({ return res.status(200).send(salesEstimatesWithPagination);
[ACCEPT_TYPE.APPLICATION_JSON]: () => {
return res.status(200).send(
this.transfromToResponse({
salesEstimates,
pagination,
filterMeta,
})
);
},
});
} catch (error) { } catch (error) {
next(error); next(error);
} }

View File

@@ -14,11 +14,8 @@ import {
} from '@/interfaces'; } from '@/interfaces';
import CheckPolicies from '@/api/middleware/CheckPolicies'; import CheckPolicies from '@/api/middleware/CheckPolicies';
import { SaleInvoiceApplication } from '@/services/Sales/Invoices/SaleInvoicesApplication'; import { SaleInvoiceApplication } from '@/services/Sales/Invoices/SaleInvoicesApplication';
import { ACCEPT_TYPE } from '@/interfaces/Http';
const ACCEPT_TYPE = {
APPLICATION_PDF: 'application/pdf',
APPLICATION_JSON: 'application/json',
};
@Service() @Service()
export default class SaleInvoicesController extends BaseController { export default class SaleInvoicesController extends BaseController {
@Inject() @Inject()
@@ -403,7 +400,6 @@ export default class SaleInvoicesController extends BaseController {
saleInvoiceId, saleInvoiceId,
user user
); );
return res.status(200).send({ return res.status(200).send({
id: saleInvoiceId, id: saleInvoiceId,
message: 'The sale invoice has been deleted successfully.', message: 'The sale invoice has been deleted successfully.',
@@ -422,30 +418,32 @@ export default class SaleInvoicesController extends BaseController {
const { id: saleInvoiceId } = req.params; const { id: saleInvoiceId } = req.params;
const { tenantId, user } = req; const { tenantId, user } = req;
// Response formatter. const accept = this.accepts(req);
return res.format({
// JSON content type. const acceptType = accept.types([
[ACCEPT_TYPE.APPLICATION_JSON]: async () => { ACCEPT_TYPE.APPLICATION_JSON,
const saleInvoice = await this.saleInvoiceApplication.getSaleInvoice( ACCEPT_TYPE.APPLICATION_PDF,
tenantId, ]);
saleInvoiceId, // Retrieves invoice in pdf format.
user if (ACCEPT_TYPE.APPLICATION_PDF == acceptType) {
); const pdfContent = await this.saleInvoiceApplication.saleInvoicePdf(
return res.status(200).send(this.transfromToResponse({ saleInvoice })); tenantId,
}, saleInvoiceId
// PDF content type. );
[ACCEPT_TYPE.APPLICATION_PDF]: async () => { res.set({
const pdfContent = await this.saleInvoiceApplication.saleInvoicePdf( 'Content-Type': 'application/pdf',
tenantId, 'Content-Length': pdfContent.length,
saleInvoiceId });
); res.send(pdfContent);
res.set({ // Retrieves invoice in json format.
'Content-Type': 'application/pdf', } else {
'Content-Length': pdfContent.length, const saleInvoice = await this.saleInvoiceApplication.getSaleInvoice(
}); tenantId,
res.send(pdfContent); saleInvoiceId,
}, user
}); );
return res.status(200).send({ saleInvoice });
}
} }
/** /**
* Retrieve paginated sales invoices with custom view metadata. * Retrieve paginated sales invoices with custom view metadata.
@@ -467,14 +465,10 @@ export default class SaleInvoicesController extends BaseController {
...this.matchedQueryData(req), ...this.matchedQueryData(req),
}; };
try { try {
const { salesInvoices, filterMeta, pagination } = const salesInvoicesWithPagination =
await this.saleInvoiceApplication.getSaleInvoices(tenantId, filter); await this.saleInvoiceApplication.getSaleInvoices(tenantId, filter);
return res.status(200).send({ return res.status(200).send(salesInvoicesWithPagination);
sales_invoices: this.transfromToResponse(salesInvoices),
pagination: this.transfromToResponse(pagination),
filter_meta: this.transfromToResponse(filterMeta),
});
} catch (error) { } catch (error) {
next(error); next(error);
} }
@@ -501,9 +495,7 @@ export default class SaleInvoicesController extends BaseController {
tenantId, tenantId,
customerId customerId
); );
return res.status(200).send({ return res.status(200).send({ salesInvoices });
sales_invoices: this.transfromToResponse(salesInvoices),
});
} catch (error) { } catch (error) {
next(error); next(error);
} }
@@ -531,7 +523,6 @@ export default class SaleInvoicesController extends BaseController {
invoiceId, invoiceId,
writeoffDTO writeoffDTO
); );
return res.status(200).send({ return res.status(200).send({
id: saleInvoice.id, id: saleInvoice.id,
message: 'The given sale invoice has been written-off successfully.', message: 'The given sale invoice has been written-off successfully.',

View File

@@ -3,12 +3,17 @@ import { body, check, param, query } from 'express-validator';
import { Inject, Service } from 'typedi'; import { Inject, Service } from 'typedi';
import asyncMiddleware from '@/api/middleware/asyncMiddleware'; import asyncMiddleware from '@/api/middleware/asyncMiddleware';
import BaseController from '../BaseController'; import BaseController from '../BaseController';
import { ISaleReceiptDTO, SaleReceiptMailOpts, SaleReceiptMailOptsDTO } from '@/interfaces/SaleReceipt'; import {
ISaleReceiptDTO,
SaleReceiptMailOpts,
SaleReceiptMailOptsDTO,
} from '@/interfaces/SaleReceipt';
import { ServiceError } from '@/exceptions'; import { ServiceError } from '@/exceptions';
import DynamicListingService from '@/services/DynamicListing/DynamicListService'; import DynamicListingService from '@/services/DynamicListing/DynamicListService';
import CheckPolicies from '@/api/middleware/CheckPolicies'; import CheckPolicies from '@/api/middleware/CheckPolicies';
import { AbilitySubject, SaleReceiptAction } from '@/interfaces'; import { AbilitySubject, SaleReceiptAction } from '@/interfaces';
import { SaleReceiptApplication } from '@/services/Sales/Receipts/SaleReceiptApplication'; import { SaleReceiptApplication } from '@/services/Sales/Receipts/SaleReceiptApplication';
import { ACCEPT_TYPE } from '@/interfaces/Http';
@Service() @Service()
export default class SalesReceiptsController extends BaseController { export default class SalesReceiptsController extends BaseController {
@@ -62,9 +67,7 @@ export default class SalesReceiptsController extends BaseController {
); );
router.get( router.get(
'/:id/mail', '/:id/mail',
[ [...this.specificReceiptValidationSchema],
...this.specificReceiptValidationSchema,
],
this.validationResult, this.validationResult,
asyncMiddleware(this.getSaleReceiptMail.bind(this)), asyncMiddleware(this.getSaleReceiptMail.bind(this)),
this.handleServiceErrors this.handleServiceErrors
@@ -228,7 +231,6 @@ export default class SalesReceiptsController extends BaseController {
tenantId, tenantId,
saleReceiptId saleReceiptId
); );
return res.status(200).send({ return res.status(200).send({
id: saleReceiptId, id: saleReceiptId,
message: 'Sale receipt has been deleted successfully.', message: 'Sale receipt has been deleted successfully.',
@@ -317,15 +319,10 @@ export default class SalesReceiptsController extends BaseController {
...this.matchedQueryData(req), ...this.matchedQueryData(req),
}; };
try { try {
const { data, pagination, filterMeta } = const salesReceiptsWithPagination =
await this.saleReceiptsApplication.getSaleReceipts(tenantId, filter); await this.saleReceiptsApplication.getSaleReceipts(tenantId, filter);
const response = this.transfromToResponse({ return res.status(200).send(salesReceiptsWithPagination);
data,
pagination,
filterMeta,
});
return res.status(200).send(response);
} catch (error) { } catch (error) {
next(error); next(error);
} }
@@ -337,34 +334,34 @@ export default class SalesReceiptsController extends BaseController {
* @param {Response} res * @param {Response} res
* @param {NextFunction} next * @param {NextFunction} next
*/ */
public async getSaleReceipt(req: Request, res: Response, next: NextFunction) { public async getSaleReceipt(req: Request, res: Response) {
const { id: saleReceiptId } = req.params; const { id: saleReceiptId } = req.params;
const { tenantId } = req; const { tenantId } = req;
try { const accept = this.accepts(req);
res.format({
'application/json': async () => { const acceptType = accept.types([
const saleReceipt = await this.saleReceiptsApplication.getSaleReceipt( ACCEPT_TYPE.APPLICATION_JSON,
tenantId, ACCEPT_TYPE.APPLICATION_PDF,
saleReceiptId ]);
); // Retrieves receipt in pdf format.
return res.status(200).send({ saleReceipt }); if (ACCEPT_TYPE.APPLICATION_PDF == acceptType) {
}, const pdfContent = await this.saleReceiptsApplication.getSaleReceiptPdf(
'application/pdf': async () => { tenantId,
const pdfContent = saleReceiptId
await this.saleReceiptsApplication.getSaleReceiptPdf( );
tenantId, res.set({
saleReceiptId 'Content-Type': 'application/pdf',
); 'Content-Length': pdfContent.length,
res.set({
'Content-Type': 'application/pdf',
'Content-Length': pdfContent.length,
});
res.send(pdfContent);
},
}); });
} catch (error) { res.send(pdfContent);
next(error); // Retrieves receipt in json format.
} else {
const saleReceipt = await this.saleReceiptsApplication.getSaleReceipt(
tenantId,
saleReceiptId
);
return res.status(200).send({ saleReceipt });
} }
} }

View File

@@ -1,6 +1,7 @@
import { Inject, Service } from 'typedi'; import { Inject, Service } from 'typedi';
import { ChromiumlyTenancy } from '../ChromiumlyTenancy/ChromiumlyTenancy'; import { ChromiumlyTenancy } from '../ChromiumlyTenancy/ChromiumlyTenancy';
import { TemplateInjectable } from '../TemplateInjectable/TemplateInjectable'; import { TemplateInjectable } from '../TemplateInjectable/TemplateInjectable';
import GetCreditNote from './GetCreditNote';
@Service() @Service()
export default class GetCreditNotePdf { export default class GetCreditNotePdf {
@@ -10,11 +11,19 @@ export default class GetCreditNotePdf {
@Inject() @Inject()
private templateInjectable: TemplateInjectable; private templateInjectable: TemplateInjectable;
@Inject()
private getCreditNoteService: GetCreditNote;
/** /**
* Retrieve sale invoice pdf content. * Retrieve sale invoice pdf content.
* @param {} saleInvoice - * @param {number} tenantId - Tenant id.
* @param {number} creditNoteId - Credit note id.
*/ */
public async getCreditNotePdf(tenantId: number, creditNote) { public async getCreditNotePdf(tenantId: number, creditNoteId: number) {
const creditNote = await this.getCreditNoteService.getCreditNote(
tenantId,
creditNoteId
);
const htmlContent = await this.templateInjectable.render( const htmlContent = await this.templateInjectable.render(
tenantId, tenantId,
'modules/credit-note-standard', 'modules/credit-note-standard',