tango-app-api-payment-subscription 3.5.29 → 3.5.31
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 +2 -2
- package/src/controllers/brandsBilling.controller.js +15 -0
- package/src/controllers/invoice.controller.js +341 -56
- package/src/hbs/invoiceBulkEmail.hbs +70 -0
- package/src/hbs/invoicepaymentemail.hbs +817 -856
- package/src/routes/invoice.routes.js +3 -1
- package/src/services/applicationDefault.service.js +29 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
|
-
import { createInvoice, invoiceDownload, invoiceDownloadBulk, clientInvoiceList, creditTransactionlist, pendingInvoices, applyDiscount, migrateInvoice, PaymentStatusChange, checkPaymentStatus, getInvoice, invoiceAnnexure, invoiceBankDetails, updateInvoice, getClientBasePricing, deleteInvoice, approveInvoiceCsm, approveInvoiceFinance, approveInvoiceApproval, recordPayment } from '../controllers/invoice.controller.js';
|
|
2
|
+
import { createInvoice, invoiceDownload, invoiceDownloadBulk, invoiceBulkEmailPreview, invoiceBulkEmailSend, clientInvoiceList, creditTransactionlist, pendingInvoices, applyDiscount, migrateInvoice, PaymentStatusChange, checkPaymentStatus, getInvoice, invoiceAnnexure, invoiceBankDetails, updateInvoice, getClientBasePricing, deleteInvoice, approveInvoiceCsm, approveInvoiceFinance, approveInvoiceApproval, recordPayment } from '../controllers/invoice.controller.js';
|
|
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';
|
|
@@ -24,6 +24,8 @@ function superadminBypass( accessConfig ) {
|
|
|
24
24
|
invoiceRouter.post( '/createInvoice', isAllowedSessionHandler, superadminBypass( { userType: [ 'tango' ], access: [ { featureName: 'Global', name: 'Billing', permissions: [ 'isEdit' ] } ] } ), createInvoice );
|
|
25
25
|
invoiceRouter.post( '/regerateInvoice', isAllowedSessionHandler, superadminBypass( { userType: [ 'tango' ], access: [ { featureName: 'Global', name: 'Billing', permissions: [ 'isEdit' ] } ] } ), createInvoice );
|
|
26
26
|
invoiceRouter.post( '/invoiceDownload/bulk', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'Global', name: 'Billing', permissions: [] } ] } ), invoiceDownloadBulk );
|
|
27
|
+
invoiceRouter.post( '/invoiceEmail/bulk/preview', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'Global', name: 'Billing', permissions: [] } ] } ), invoiceBulkEmailPreview );
|
|
28
|
+
invoiceRouter.post( '/invoiceEmail/bulk/send', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'Global', name: 'Billing', permissions: [] } ] } ), invoiceBulkEmailSend );
|
|
27
29
|
invoiceRouter.post( '/invoiceDownload/:invoiceId', isAllowedSessionHandler, invoiceDownload );
|
|
28
30
|
invoiceRouter.post( '/clientInvoiceList', isAllowedSessionHandler, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'Global', name: 'Billing', permissions: [] } ] } ), clientInvoiceList );
|
|
29
31
|
invoiceRouter.post( '/creditTransactionlist', isAllowedSessionHandler, accessVerification( { userType: [ 'tango' ], access: [ { featureName: 'Global', name: 'Billing', permissions: [] } ] } ), creditTransactionlist );
|
|
@@ -11,3 +11,32 @@ export async function upsertApplicationDefault( query, payload ) {
|
|
|
11
11
|
{ new: true, upsert: true },
|
|
12
12
|
);
|
|
13
13
|
}
|
|
14
|
+
|
|
15
|
+
// Atomically reserve the next value for a named counter and return it.
|
|
16
|
+
// Uses a single findOneAndUpdate($inc) — MongoDB serialises concurrent
|
|
17
|
+
// increments on the same document, so simultaneous callers (e.g. bulk invoice
|
|
18
|
+
// finance-approval) each get a distinct number, eliminating the read-max-then-
|
|
19
|
+
// write race that produced duplicate invoice numbers.
|
|
20
|
+
//
|
|
21
|
+
// `subType` scopes the counter (e.g. 'INV-26-27'). `seedFrom` is the current
|
|
22
|
+
// real-world max (e.g. the highest existing invoiceIndex for that series); it
|
|
23
|
+
// initialises the counter ONLY on first creation via $setOnInsert, so existing
|
|
24
|
+
// numbers are never re-used. Returns the reserved integer.
|
|
25
|
+
export async function nextCounterValue( type, subType, seedFrom = 0 ) {
|
|
26
|
+
// Two-step, both atomic:
|
|
27
|
+
// 1) Ensure the counter doc exists, seeded to the current max WITHOUT
|
|
28
|
+
// incrementing (upsert + $setOnInsert). If it already exists this is a
|
|
29
|
+
// no-op and never lowers a counter that has moved past the seed.
|
|
30
|
+
await model.applicationDefaultModel.updateOne(
|
|
31
|
+
{ type, subType },
|
|
32
|
+
{ $setOnInsert: { type, subType, data: { seq: Number( seedFrom ) || 0 } } },
|
|
33
|
+
{ upsert: true },
|
|
34
|
+
);
|
|
35
|
+
// 2) Atomically claim the next value.
|
|
36
|
+
const doc = await model.applicationDefaultModel.findOneAndUpdate(
|
|
37
|
+
{ type, subType },
|
|
38
|
+
{ $inc: { 'data.seq': 1 } },
|
|
39
|
+
{ new: true },
|
|
40
|
+
);
|
|
41
|
+
return doc?.data?.seq;
|
|
42
|
+
}
|