tango-app-api-payment-subscription 3.5.22 → 3.5.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/src/controllers/billing.controllers.js +88 -55
- package/src/controllers/brandsBilling.controller.js +430 -69
- package/src/controllers/estimate.controller.js +111 -17
- package/src/controllers/invoice.controller.js +53 -8
- package/src/controllers/paymentSubscription.controllers.js +82 -2
- package/src/controllers/purchaseOrder.controller.js +112 -4
- package/src/hbs/estimatePdf.hbs +12 -0
- package/src/hbs/invoicepaymentemail.hbs +4 -0
- package/src/routes/billing.routes.js +7 -8
- package/src/routes/brandsBilling.routes.js +12 -12
- package/src/routes/invoice.routes.js +4 -3
- package/src/routes/paymentSubscription.routes.js +5 -7
- package/src/services/clientPayment.services.js +21 -0
- package/src/services/purchaseOrder.service.js +4 -0
|
@@ -5,16 +5,16 @@ import { isAllowedSessionHandler, accessVerification } from 'tango-app-api-middl
|
|
|
5
5
|
|
|
6
6
|
export const brandsBillingRouter = express.Router();
|
|
7
7
|
|
|
8
|
-
brandsBillingRouter.post( '/brandsBillingList', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: '
|
|
8
|
+
brandsBillingRouter.post( '/brandsBillingList', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'EditBilling', permissions: [] } ] } ), brandsBillingList );
|
|
9
9
|
brandsBillingRouter.post( '/brandInvoiceList', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ ] } ), brandInvoiceList );
|
|
10
|
-
brandsBillingRouter.post( '/latestDailyPricing', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: '
|
|
11
|
-
brandsBillingRouter.post( '/brandBillingGroups', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: '
|
|
12
|
-
brandsBillingRouter.put( '/updateDailyPricingWorkingDays', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: '
|
|
13
|
-
brandsBillingRouter.put( '/updateDailyPricingStoreField', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: '
|
|
14
|
-
brandsBillingRouter.post( '/getClientBillingInfo', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoAdmin', name: '
|
|
15
|
-
brandsBillingRouter.get( '/bulk-download-billing-groups', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: '
|
|
16
|
-
brandsBillingRouter.post( '/bulk-update-billing-groups', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: '
|
|
17
|
-
brandsBillingRouter.post( '/billingSummary', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: '
|
|
18
|
-
brandsBillingRouter.get( '/billingSummary', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: '
|
|
19
|
-
brandsBillingRouter.get( '/additionalProducts', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: '
|
|
20
|
-
brandsBillingRouter.get( '/additionalProductExport', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: '
|
|
10
|
+
brandsBillingRouter.post( '/latestDailyPricing', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'EditBilling', permissions: [] } ] } ), latestDailyPricing );
|
|
11
|
+
brandsBillingRouter.post( '/brandBillingGroups', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'EditBilling', permissions: [] } ] } ), brandBillingGroups );
|
|
12
|
+
brandsBillingRouter.put( '/updateDailyPricingWorkingDays', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'EditBilling', permissions: [ 'isEdit' ] } ] } ), updateDailyPricingWorkingDays );
|
|
13
|
+
brandsBillingRouter.put( '/updateDailyPricingStoreField', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'EditBilling', permissions: [ 'isEdit' ] } ] } ), updateDailyPricingStoreField );
|
|
14
|
+
brandsBillingRouter.post( '/getClientBillingInfo', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoAdmin', name: 'EditBilling', permissions: [] } ] } ), getClientBillingInfo );
|
|
15
|
+
brandsBillingRouter.get( '/bulk-download-billing-groups', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'EditBilling', permissions: [ 'isEdit' ] } ] } ), bulkDownloadBillingGroups );
|
|
16
|
+
brandsBillingRouter.post( '/bulk-update-billing-groups', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'EditBilling', permissions: [ 'isEdit' ] } ] } ), bulkUpdateBillingGroups );
|
|
17
|
+
brandsBillingRouter.post( '/billingSummary', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'EditBilling', permissions: [] } ] } ), billingSummary );
|
|
18
|
+
brandsBillingRouter.get( '/billingSummary', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'EditBilling', permissions: [] } ] } ), billingSummary );
|
|
19
|
+
brandsBillingRouter.get( '/additionalProducts', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'EditBilling', permissions: [] } ] } ), additionalProducts );
|
|
20
|
+
brandsBillingRouter.get( '/additionalProductExport', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'EditBilling', permissions: [] } ] } ), additionalProductExport );
|
|
@@ -3,7 +3,7 @@ import { createInvoice, invoiceDownload, invoiceDownloadBulk, clientInvoiceList,
|
|
|
3
3
|
import { isAllowedSessionHandler, accessVerification, validate } from 'tango-app-api-middleware';
|
|
4
4
|
import { getInvoiceHeads, updateInvoiceHeads } from '../controllers/applicationDefault.controllers.js';
|
|
5
5
|
import { uploadBankStatement, bankTransactionList, resolveOptions, resolveBankTransaction } from '../controllers/bankTransaction.controller.js';
|
|
6
|
-
import { estimateList, createEstimate, updateEstimate, getEstimate,
|
|
6
|
+
import { estimateList, createEstimate, updateEstimate, getEstimate, deleteEstimate, downloadEstimate, approveEstimateCsm, approveEstimateFinance, approveEstimateApproval } from '../controllers/estimate.controller.js';
|
|
7
7
|
import { updateInvoiceHeadsSchema } from '../dtos/validation.dtos.js';
|
|
8
8
|
export const invoiceRouter = express.Router();
|
|
9
9
|
|
|
@@ -58,9 +58,10 @@ invoiceRouter.post( '/bankStatement/resolve', isAllowedSessionHandler, superadmi
|
|
|
58
58
|
// lifecycle. List/get are read; create/status/delete need edit rights.
|
|
59
59
|
invoiceRouter.post( '/estimate/list', isAllowedSessionHandler, superadminBypass( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'invoiceApproval', permissions: [] } ] } ), estimateList );
|
|
60
60
|
invoiceRouter.post( '/estimate/create', isAllowedSessionHandler, superadminBypass( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'invoiceApproval', permissions: [ 'isEdit' ] } ] } ), createEstimate );
|
|
61
|
+
invoiceRouter.post( '/estimate/approveCsm', isAllowedSessionHandler, superadminBypass( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'csmApproval', permissions: [ 'isEdit' ] } ] } ), approveEstimateCsm );
|
|
62
|
+
invoiceRouter.post( '/estimate/approveFinance', isAllowedSessionHandler, superadminBypass( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'financeApproval', permissions: [ 'isEdit' ] } ] } ), approveEstimateFinance );
|
|
63
|
+
invoiceRouter.post( '/estimate/approveApproval', isAllowedSessionHandler, superadminBypass( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'invoiceApproval', permissions: [ 'isEdit' ] } ] } ), approveEstimateApproval );
|
|
61
64
|
invoiceRouter.post( '/estimate/update', isAllowedSessionHandler, superadminBypass( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'invoiceApproval', permissions: [ 'isEdit' ] } ] } ), updateEstimate );
|
|
62
|
-
invoiceRouter.post( '/estimate/send', isAllowedSessionHandler, superadminBypass( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'invoiceApproval', permissions: [ 'isEdit' ] } ] } ), sendEstimate );
|
|
63
65
|
invoiceRouter.post( '/estimate/download/:estimateId', isAllowedSessionHandler, superadminBypass( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'invoiceApproval', permissions: [] } ] } ), downloadEstimate );
|
|
64
66
|
invoiceRouter.get( '/estimate/:estimateId', isAllowedSessionHandler, superadminBypass( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'invoiceApproval', permissions: [] } ] } ), getEstimate );
|
|
65
|
-
invoiceRouter.post( '/estimate/statusUpdate', isAllowedSessionHandler, superadminBypass( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'invoiceApproval', permissions: [ 'isEdit' ] } ] } ), estimateStatusUpdate );
|
|
66
67
|
invoiceRouter.delete( '/estimate/:estimateId', isAllowedSessionHandler, superadminBypass( { userType: [ 'tango' ], access: [ { featureName: 'TangoAdmin', name: 'invoiceApproval', permissions: [ 'isEdit' ] } ] } ), deleteEstimate );
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
|
|
2
2
|
import express from 'express';
|
|
3
|
-
import multer from 'multer';
|
|
4
3
|
import * as paymentController from '../controllers/paymentSubscription.controllers.js';
|
|
5
4
|
import { validate, isAllowedSessionHandler, accessVerification } from 'tango-app-api-middleware';
|
|
6
5
|
import * as validationDtos from '../dtos/validation.dtos.js';
|
|
7
6
|
import { validateClient } from '../utils/validations/client.validation.js';
|
|
8
7
|
export const paymentSubscriptionRouter = express.Router();
|
|
9
8
|
|
|
10
|
-
// PDF document upload (Plans & Subscription > Documents). In-memory storage,
|
|
11
|
-
// 10MB cap; the controller streams the buffer to the assets S3 bucket.
|
|
12
|
-
const documentUpload = multer( { storage: multer.memoryStorage(), limits: { fileSize: 10 * 1024 * 1024 } } );
|
|
13
|
-
|
|
14
9
|
paymentSubscriptionRouter.post( '/addBilling', isAllowedSessionHandler, accessVerification( {
|
|
15
10
|
userType: [ 'tango', 'client' ], access: [
|
|
16
11
|
{ featureName: 'Global', name: 'Subscription', permissions: [ 'isAdd' ] },
|
|
@@ -151,9 +146,12 @@ paymentSubscriptionRouter.put( '/pushNotification/update/:notificationId', isAll
|
|
|
151
146
|
paymentSubscriptionRouter.post( '/updateRemind/:notificationId', isAllowedSessionHandler, validate( validationDtos.validateId ), paymentController.updateRemind );
|
|
152
147
|
paymentSubscriptionRouter.post( '/createDefaultbillings', paymentController.createDefaultbillings );
|
|
153
148
|
|
|
154
|
-
// Brand documents (Plans & Subscription > Documents accordion).
|
|
155
|
-
|
|
149
|
+
// Brand documents (Plans & Subscription > Documents accordion). The multipart
|
|
150
|
+
// body is parsed app-wide by express-fileupload (see app.js) → req.files.file.
|
|
151
|
+
paymentSubscriptionRouter.post( '/client-document/upload', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'Global', name: 'Subscription', permissions: [ 'isEdit' ] } ] } ), paymentController.uploadClientDocument );
|
|
156
152
|
paymentSubscriptionRouter.get( '/client-document/list', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'Global', name: 'Subscription', permissions: [] } ] } ), paymentController.getClientDocuments );
|
|
153
|
+
paymentSubscriptionRouter.put( '/client-document/update', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'Global', name: 'Subscription', permissions: [ 'isEdit' ] } ] } ), paymentController.updateClientDocument );
|
|
154
|
+
paymentSubscriptionRouter.delete( '/client-document/:documentId', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'Global', name: 'Subscription', permissions: [ 'isEdit' ] } ] } ), paymentController.deleteClientDocument );
|
|
157
155
|
|
|
158
156
|
// Toggle billing-group-wise pricing for a client (tango only, edit perm).
|
|
159
157
|
paymentSubscriptionRouter.post( '/billingGroupWisePricing', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'Global', name: 'Subscription', permissions: [ 'isEdit' ] } ] } ), paymentController.setBillingGroupWisePricing );
|
|
@@ -21,6 +21,27 @@ export const pushAdditionalDocument = ( query = {}, document = {} ) => {
|
|
|
21
21
|
return model.clientModel.updateOne( query, { $push: { additionalDocuments: document } } );
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
+
// Update fields of a single additionalDocuments subdoc (matched by _id). `fields`
|
|
25
|
+
// keys are the subdoc field names, e.g. { documentName, expiryDate, path }.
|
|
26
|
+
export const updateAdditionalDocument = ( clientId, documentId, fields = {} ) => {
|
|
27
|
+
const set = {};
|
|
28
|
+
for ( const [ k, v ] of Object.entries( fields ) ) {
|
|
29
|
+
set[`additionalDocuments.$.${k}`] = v;
|
|
30
|
+
}
|
|
31
|
+
return model.clientModel.updateOne(
|
|
32
|
+
{ clientId, 'additionalDocuments._id': documentId },
|
|
33
|
+
{ $set: set },
|
|
34
|
+
);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Remove a single additionalDocuments subdoc (matched by _id).
|
|
38
|
+
export const pullAdditionalDocument = ( clientId, documentId ) => {
|
|
39
|
+
return model.clientModel.updateOne(
|
|
40
|
+
{ clientId },
|
|
41
|
+
{ $pull: { additionalDocuments: { _id: documentId } } },
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
24
45
|
export const aggregate = ( query = [] ) => {
|
|
25
46
|
return model.clientModel.aggregate( query );
|
|
26
47
|
};
|
|
@@ -16,6 +16,10 @@ export const updateOne = ( query, record ) => {
|
|
|
16
16
|
return model.purchaseOrderModel.updateOne( query, { $set: record } );
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
+
export const deleteRecord = ( query ) => {
|
|
20
|
+
return model.purchaseOrderModel.deleteOne( query );
|
|
21
|
+
};
|
|
22
|
+
|
|
19
23
|
export const aggregate = ( query = [] ) => {
|
|
20
24
|
return model.purchaseOrderModel.aggregate( query );
|
|
21
25
|
};
|