feat: closed sale receipt status.

feat: approve and reject sale estimate.
feat: initial receipts, invoices, estimates and bills views.
This commit is contained in:
a.bouhuolia
2020-12-14 20:25:38 +02:00
parent 461e18f2a4
commit 27483495cb
23 changed files with 801 additions and 86 deletions

View File

@@ -40,6 +40,24 @@ export default class SalesEstimatesController extends BaseController {
asyncMiddleware(this.deliverSaleEstimate.bind(this)),
this.handleServiceErrors,
);
router.post(
'/:id/approve',
[
this.validateSpecificEstimateSchema,
],
this.validationResult,
asyncMiddleware(this.approveSaleEstimate.bind(this)),
this.handleServiceErrors
);
router.post(
'/:id/reject',
[
this.validateSpecificEstimateSchema,
],
this.validationResult,
asyncMiddleware(this.rejectSaleEstimate.bind(this)),
this.handleServiceErrors,
)
router.post(
'/:id', [
...this.validateSpecificEstimateSchema,
@@ -202,8 +220,55 @@ export default class SalesEstimatesController extends BaseController {
}
}
/**
* Marks the sale estimate as approved.
* @param {Request} req
* @param {Response} res
* @param {NextFunction} next
*/
async approveSaleEstimate(req: Request, res: Response, next: NextFunction) {
const { id: estimateId } = req.params;
const { tenantId } = req;
try {
await this.saleEstimateService.approveSaleEstimate(tenantId, estimateId);
return res.status(200).send({
id: estimateId,
message: 'The sale estimate has been approved successfully.',
});
} catch (error) {
next(error);
}
}
/**
* Marks the sale estimate as rejected.
* @param {Request} req
* @param {Response} res
* @param {NextFunction} next
*/
async rejectSaleEstimate(req: Request, res: Response, next: NextFunction) {
const { id: estimateId } = req.params;
const { tenantId } = req;
try {
await this.saleEstimateService.rejectSaleEstimate(tenantId, estimateId);
return res.status(200).send({
id: estimateId,
message: 'The sale estimate has been rejected successfully.',
});
} catch (error) {
next(error);
}
}
/**
* Retrieve the given estimate with associated entries.
* @param {Request} req
* @param {Response} res
* @param {NextFunction} next
*/
async getEstimate(req: Request, res: Response, next: NextFunction) {
const { id: estimateId } = req.params;
@@ -302,11 +367,31 @@ export default class SalesEstimatesController extends BaseController {
errors: [{ type: 'NOT_SELL_ABLE_ITEMS', code: 800 }],
});
}
if (error.errorType === 'contact_not_found') {
if (error.errorType === 'SALE_ESTIMATE_ALREADY_APPROVED') {
return res.boom.badRequest(null, {
errors: [{ type: 'CUSTOMER_NOT_FOUND', code: 900 }],
});
}
if (error.errorType === 'SALE_ESTIMATE_ALREADY_APPROVED') {
return res.boom.badRequest(null, {
errors: [{ type: 'CUSTOMER_NOT_FOUND', code: 1000 }],
});
}
if (error.errorType === 'SALE_ESTIMATE_NOT_DELIVERED') {
return res.boom.badRequest(null, {
errors: [{ type: 'SALE_ESTIMATE_NOT_DELIVERED', code: 1100 }],
});
}
if (error.errorType === 'SALE_ESTIMATE_ALREADY_REJECTED') {
return res.boom.badRequest(null, {
errors: [{ type: 'SALE_ESTIMATE_ALREADY_REJECTED', code: 1200 }],
});
}
if (error.errorType === 'contact_not_found') {
return res.boom.badRequest(null, {
errors: [{ type: 'CUSTOMER_NOT_FOUND', code: 1300 }],
});
}
}
next(error);
}

View File

@@ -264,7 +264,11 @@ export default class SaleInvoicesController extends BaseController{
}
try {
const { salesInvoices, filterMeta, pagination } = await this.saleInvoiceService.salesInvoicesList(
const {
salesInvoices,
filterMeta,
pagination,
} = await this.saleInvoiceService.salesInvoicesList(
tenantId, filter,
);
return res.status(200).send({

View File

@@ -22,6 +22,16 @@ export default class SalesReceiptsController extends BaseController{
router() {
const router = Router();
router.post(
'/:id/close',
[
...this.specificReceiptValidationSchema,
],
this.validationResult,
asyncMiddleware(this.closeSaleReceipt.bind(this)),
this.handleServiceErrors,
)
router.post(
'/:id', [
...this.specificReceiptValidationSchema,
@@ -75,6 +85,7 @@ export default class SalesReceiptsController extends BaseController{
check('receipt_date').exists().isISO8601(),
check('receipt_number').optional().trim().escape(),
check('reference_no').optional().trim().escape(),
check('closed').default(false).isBoolean().toBoolean(),
check('entries').exists().isArray({ min: 1 }),
@@ -188,6 +199,31 @@ export default class SalesReceiptsController extends BaseController{
}
}
/**
* Marks the given the sale receipt as closed.
* @param {Request} req
* @param {Response} res
* @param {NextFunction} next
*/
async closeSaleReceipt(req: Request, res: Response, next: NextFunction) {
const { tenantId } = req;
const { id: saleReceiptId } = req.params;
try {
// Update the given sale receipt details.
await this.saleReceiptService.closeSaleReceipt(
tenantId,
saleReceiptId,
);
return res.status(200).send({
id: saleReceiptId,
message: 'Sale receipt has been closed successfully.',
});
} catch (error) {
next(error);
}
}
/**
* Listing sales receipts.
* @param {Request} req
@@ -296,6 +332,11 @@ export default class SalesReceiptsController extends BaseController{
errors: [{ type: 'SALE_RECEIPT_NUMBER_NOT_UNIQUE', code: 900 }],
});
}
if (error.errorType === 'SALE_RECEIPT_IS_ALREADY_CLOSED') {
return res.boom.badRequest(null, {
errors: [{ type: 'SALE_RECEIPT_IS_ALREADY_CLOSED', code: 1000 }],
});
}
}
next(error);
}