tango-app-api-payment-subscription 3.0.0
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/.eslintrc.cjs +41 -0
- package/README.md +29 -0
- package/index.js +7 -0
- package/package.json +35 -0
- package/script-new.js +376 -0
- package/src/controllers/paymentSubscription.controllers.js +125 -0
- package/src/dtos/validation.dtos.js +32 -0
- package/src/routes/paymentSubscription.routes.js +15 -0
- package/src/services/paymentSubscription.services.js +46 -0
package/.eslintrc.cjs
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
|
|
2
|
+
module.exports = {
|
|
3
|
+
'env': {
|
|
4
|
+
'es2021': true,
|
|
5
|
+
'node': true,
|
|
6
|
+
},
|
|
7
|
+
'extends': 'google',
|
|
8
|
+
'overrides': [
|
|
9
|
+
{
|
|
10
|
+
'env': {
|
|
11
|
+
'node': true,
|
|
12
|
+
},
|
|
13
|
+
'files': [
|
|
14
|
+
'.eslintrc.{js,cjs}',
|
|
15
|
+
],
|
|
16
|
+
'parserOptions': {
|
|
17
|
+
'sourceType': 'script',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
'parserOptions': {
|
|
22
|
+
'ecmaVersion': 'latest',
|
|
23
|
+
'sourceType': 'module',
|
|
24
|
+
},
|
|
25
|
+
'rules': {
|
|
26
|
+
'linebreak-style': [ 'error', 'windows' ],
|
|
27
|
+
'require-jsdoc': 'off',
|
|
28
|
+
'arrow-spacing': 'error',
|
|
29
|
+
'key-spacing': [ 'error', { 'beforeColon': false, 'afterColon': true } ],
|
|
30
|
+
'object-curly-spacing': [ 'error', 'always' ],
|
|
31
|
+
'space-in-parens': [ 'error', 'always' ],
|
|
32
|
+
'keyword-spacing': 'error',
|
|
33
|
+
'array-bracket-spacing': [ 'error', 'always' ],
|
|
34
|
+
'spaced-comment': [ 'error', 'always' ],
|
|
35
|
+
'max-len': [ 'error', { 'code': 700 } ],
|
|
36
|
+
'no-unused-vars': 'error',
|
|
37
|
+
'new-cap': [ 'error', { 'newIsCap': true, 'capIsNew': false } ],
|
|
38
|
+
'prefer-const': 'off',
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# README #
|
|
2
|
+
|
|
3
|
+
This README would normally document whatever steps are necessary to get your application up and running.
|
|
4
|
+
|
|
5
|
+
### What is this repository for? ###
|
|
6
|
+
|
|
7
|
+
* Quick summary
|
|
8
|
+
* Version
|
|
9
|
+
* [Learn Markdown](https://bitbucket.org/tutorials/markdowndemo)
|
|
10
|
+
|
|
11
|
+
### How do I get set up? ###
|
|
12
|
+
|
|
13
|
+
* Summary of set up
|
|
14
|
+
* Configuration
|
|
15
|
+
* Dependencies
|
|
16
|
+
* Database configuration
|
|
17
|
+
* How to run tests
|
|
18
|
+
* Deployment instructions
|
|
19
|
+
|
|
20
|
+
### Contribution guidelines ###
|
|
21
|
+
|
|
22
|
+
* Writing tests
|
|
23
|
+
* Code review
|
|
24
|
+
* Other guidelines
|
|
25
|
+
|
|
26
|
+
### Who do I talk to? ###
|
|
27
|
+
|
|
28
|
+
* Repo owner or admin
|
|
29
|
+
* Other community or team contact
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tango-app-api-payment-subscription",
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"description": "paymentSubscription",
|
|
5
|
+
"main": "app.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"start": "nodemon --exec \"eslint --fix . && node app.js\""
|
|
9
|
+
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=18.10.0"
|
|
12
|
+
},
|
|
13
|
+
"author": "praveenraj",
|
|
14
|
+
"license": "ISC",
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"aws-sdk": "^2.1572.0",
|
|
17
|
+
"dotenv": "^16.4.5",
|
|
18
|
+
"express": "^4.18.3",
|
|
19
|
+
"handlebars": "^4.7.8",
|
|
20
|
+
"mongodb": "^6.4.0",
|
|
21
|
+
"nodemon": "^3.1.0",
|
|
22
|
+
"tango-api-schema": "^2.0.4",
|
|
23
|
+
"tango-app-api-middleware": "^1.0.15",
|
|
24
|
+
"winston": "^3.12.0",
|
|
25
|
+
"winston-daily-rotate-file": "^5.0.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"eslint": "^8.57.0",
|
|
29
|
+
"eslint-config-google": "^0.14.0",
|
|
30
|
+
"eslint-config-semistandard": "^17.0.0",
|
|
31
|
+
"eslint-config-standard": "^17.1.0",
|
|
32
|
+
"eslint-plugin-import": "^2.29.1",
|
|
33
|
+
"eslint-plugin-promise": "^6.1.1"
|
|
34
|
+
}
|
|
35
|
+
}
|
package/script-new.js
ADDED
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
const fs = require( 'fs' );
|
|
2
|
+
const path = require( 'path' );
|
|
3
|
+
const { execSync } = require( 'child_process' );
|
|
4
|
+
// Define folder structure
|
|
5
|
+
const createProjectStructure = async ( folderName ) => {
|
|
6
|
+
const folders = [
|
|
7
|
+
`src`,
|
|
8
|
+
`src/controllers`,
|
|
9
|
+
`src/routes`,
|
|
10
|
+
`config`,
|
|
11
|
+
`config/database`,
|
|
12
|
+
`config/logger`,
|
|
13
|
+
`config/env`,
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
// Create folders
|
|
17
|
+
folders.forEach( ( folder ) => {
|
|
18
|
+
const folderPath = path.join( __dirname, folder );
|
|
19
|
+
fs.mkdirSync( folderPath, { recursive: true } );
|
|
20
|
+
} );
|
|
21
|
+
|
|
22
|
+
// Create index.js file
|
|
23
|
+
const indexjsContent = `
|
|
24
|
+
|
|
25
|
+
import { ${folderName}router } from './src/routes/${folderName}.routes.js';
|
|
26
|
+
|
|
27
|
+
export { ${folderName}router };
|
|
28
|
+
|
|
29
|
+
`;
|
|
30
|
+
fs.writeFileSync(
|
|
31
|
+
path.join( __dirname, `/`, 'index.js' ),
|
|
32
|
+
indexjsContent,
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
// Create app.js file
|
|
36
|
+
const appContent = `
|
|
37
|
+
import express from 'express';
|
|
38
|
+
import { ${folderName}router } from './index.js';
|
|
39
|
+
|
|
40
|
+
import dotenv from 'dotenv';
|
|
41
|
+
import { logger } from 'tango-app-api-middleware';
|
|
42
|
+
import { connectdb } from './config/database/database.js';
|
|
43
|
+
|
|
44
|
+
const env=dotenv.config();
|
|
45
|
+
|
|
46
|
+
const app = express();
|
|
47
|
+
const PORT = process.env.PORT || 3000;
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
if ( env.error ) {
|
|
53
|
+
logger.error( '.env not found' );
|
|
54
|
+
process.exit( 1 );
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
app.use('/api', ${folderName}Router);
|
|
59
|
+
|
|
60
|
+
app.listen(PORT, () => {
|
|
61
|
+
console.log(\`server is running on port= \${PORT} \`);
|
|
62
|
+
connectdb();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
`;
|
|
66
|
+
fs.writeFileSync(
|
|
67
|
+
path.join( __dirname, `/`, 'app.js' ),
|
|
68
|
+
appContent,
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
// Create route.js file
|
|
72
|
+
const appJsContent = `
|
|
73
|
+
import express from 'express';
|
|
74
|
+
|
|
75
|
+
export const ${folderName}router = express.Router();
|
|
76
|
+
|
|
77
|
+
${folderName}router.get('/', (req, res) => {
|
|
78
|
+
res.send('Hello, world!');
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
`;
|
|
83
|
+
fs.writeFileSync(
|
|
84
|
+
path.join( __dirname, `/src/routes`, `${folderName}.routes.js` ),
|
|
85
|
+
appJsContent,
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
// Create package.json file
|
|
89
|
+
const packageJsonContent = `
|
|
90
|
+
{
|
|
91
|
+
"name": "${folderName}",
|
|
92
|
+
"version": "1.0.0",
|
|
93
|
+
"description": "${folderName}",
|
|
94
|
+
"main": "app.js",
|
|
95
|
+
"type": "module",
|
|
96
|
+
"scripts": {
|
|
97
|
+
"start": "nodemon --exec \\"eslint --fix . && node app.js\\""
|
|
98
|
+
},
|
|
99
|
+
"engines": {
|
|
100
|
+
"node": ">=18.10.0"
|
|
101
|
+
},
|
|
102
|
+
"author": "praveenraj",
|
|
103
|
+
"license": "ISC"
|
|
104
|
+
|
|
105
|
+
}
|
|
106
|
+
`;
|
|
107
|
+
fs.writeFileSync(
|
|
108
|
+
path.join( __dirname, 'package.json' ),
|
|
109
|
+
packageJsonContent,
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
// Create .eslintrc.js file
|
|
113
|
+
const eslintrcContent = `
|
|
114
|
+
module.exports = {
|
|
115
|
+
'env': {
|
|
116
|
+
'es2021': true,
|
|
117
|
+
'node': true,
|
|
118
|
+
},
|
|
119
|
+
'extends': 'google',
|
|
120
|
+
'overrides': [
|
|
121
|
+
{
|
|
122
|
+
'env': {
|
|
123
|
+
'node': true,
|
|
124
|
+
},
|
|
125
|
+
'files': [
|
|
126
|
+
'.eslintrc.{js,cjs}',
|
|
127
|
+
],
|
|
128
|
+
'parserOptions': {
|
|
129
|
+
'sourceType': 'script',
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
'parserOptions': {
|
|
134
|
+
'ecmaVersion': 'latest',
|
|
135
|
+
'sourceType': 'module',
|
|
136
|
+
},
|
|
137
|
+
'rules': {
|
|
138
|
+
'linebreak-style': [ 'error', 'windows' ],
|
|
139
|
+
'require-jsdoc': 'off',
|
|
140
|
+
'arrow-spacing': 'error',
|
|
141
|
+
'key-spacing': [ 'error', { 'beforeColon': false, 'afterColon': true } ],
|
|
142
|
+
'object-curly-spacing': [ 'error', 'always' ],
|
|
143
|
+
'space-in-parens': [ 'error', 'always' ],
|
|
144
|
+
'keyword-spacing': 'error',
|
|
145
|
+
'array-bracket-spacing': [ 'error', 'always' ],
|
|
146
|
+
'spaced-comment': [ 'error', 'always' ],
|
|
147
|
+
'max-len': [ 'error', { 'code': 700 } ],
|
|
148
|
+
'no-unused-vars': 'error',
|
|
149
|
+
'new-cap': [ 'error', { 'newIsCap': true, 'capIsNew': false } ],
|
|
150
|
+
'prefer-const': 'off',
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
`;
|
|
155
|
+
fs.writeFileSync(
|
|
156
|
+
path.join( __dirname, '.eslintrc.cjs' ),
|
|
157
|
+
eslintrcContent,
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
// Create .env file
|
|
161
|
+
const envContent = `
|
|
162
|
+
PORT=3005
|
|
163
|
+
AWS_ACCESS_KEY_ID=AKIAQSSPN5BZSDAZHWB2
|
|
164
|
+
AWS_SECRET_ACCESS_KEY=WkkH2+s4mPbaM48EEHP+ZZHGdkixvNsHHAgS8rMT
|
|
165
|
+
|
|
166
|
+
mongo_username= tangoeye
|
|
167
|
+
mongo_password= SUTONQosEUijJKWC
|
|
168
|
+
|
|
169
|
+
ELASTIC_CLOUD_ID=
|
|
170
|
+
ELASTIC_USERNAME=
|
|
171
|
+
ELASTIC_PASSWORD=
|
|
172
|
+
ELASTIC_NODE=
|
|
173
|
+
|
|
174
|
+
`;
|
|
175
|
+
fs.writeFileSync( path.join( __dirname, '.env' ), envContent );
|
|
176
|
+
|
|
177
|
+
// Create database.js file
|
|
178
|
+
const databaseContent = `
|
|
179
|
+
import appConfig from '../../config/env/env.js';
|
|
180
|
+
import mongoose from 'mongoose';
|
|
181
|
+
import { logger } from 'tango-app-api-middleware';
|
|
182
|
+
|
|
183
|
+
export function getConnection() {
|
|
184
|
+
appConfig.database.mongo.username = process.env.mongo_username;
|
|
185
|
+
appConfig.database.mongo.password = process.env.mongo_password;
|
|
186
|
+
|
|
187
|
+
const options = {
|
|
188
|
+
useNewUrlParser: true,
|
|
189
|
+
useUnifiedTopology: true,
|
|
190
|
+
};
|
|
191
|
+
let connectionString;
|
|
192
|
+
|
|
193
|
+
if (appConfig.database.mongo.authSource) {
|
|
194
|
+
connectionString = \`\${appConfig.database.mongo.hostname}/\${appConfig.database.mongo.name}?\${appConfig.database.mongo.authSource}\`;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (appConfig.database.mongo.username && appConfig.database.mongo.password) {
|
|
198
|
+
connectionString = \`\${appConfig.database.mongo.username}:\${appConfig.database.mongo.password}@\${appConfig.database.mongo.hostname}/\${appConfig.database.mongo.name}\`;
|
|
199
|
+
} else {
|
|
200
|
+
connectionString = \`\${appConfig.database.mongo.hostname}/\${appConfig.database.mongo.name}\`;
|
|
201
|
+
}
|
|
202
|
+
if (appConfig.database.mongo.authSource) {
|
|
203
|
+
connectionString = \`mongodb+srv://\${connectionString}\`;
|
|
204
|
+
} else {
|
|
205
|
+
connectionString = \`mongodb://\${connectionString}\`;
|
|
206
|
+
}
|
|
207
|
+
return { uri: \`\${connectionString}\`, options };
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function connectdb() {
|
|
211
|
+
const db = getConnection();
|
|
212
|
+
// Establish Connection
|
|
213
|
+
mongoose.connect(db.uri, db.options);
|
|
214
|
+
|
|
215
|
+
// Mongoose Events
|
|
216
|
+
mongoose.connection.on('connected', () => {
|
|
217
|
+
logger.info('Mongoose connected with MongoDB: ' + new Date().toISOString());
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// Event: Disconnected
|
|
221
|
+
mongoose.connection.on('disconnected', () => {
|
|
222
|
+
logger.log('MongoDB Connection Closed: ' + new Date().toISOString());
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
// Event: Error
|
|
226
|
+
mongoose.connection.on('error', (error) => {
|
|
227
|
+
logger.error(error);
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
`;
|
|
231
|
+
|
|
232
|
+
fs.writeFileSync(
|
|
233
|
+
path.join( __dirname, `/config/database`, `database.js` ),
|
|
234
|
+
|
|
235
|
+
databaseContent,
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
// Create logger.js file
|
|
239
|
+
const loggerContent = `
|
|
240
|
+
import winston from 'winston';
|
|
241
|
+
import DailyRotateFile from 'winston-daily-rotate-file';
|
|
242
|
+
|
|
243
|
+
export const logger = winston.createLogger( {
|
|
244
|
+
level: 'info',
|
|
245
|
+
format: winston.format.combine(
|
|
246
|
+
winston.format.errors( { stack: true } ),
|
|
247
|
+
winston.format.timestamp(),
|
|
248
|
+
winston.format.prettyPrint(),
|
|
249
|
+
winston.format.colorize(),
|
|
250
|
+
),
|
|
251
|
+
transports: [
|
|
252
|
+
new DailyRotateFile( {
|
|
253
|
+
filename: \`error-%DATE%.log\`,
|
|
254
|
+
dirname: \`storage/logs/\`,
|
|
255
|
+
datePattern: 'YYYY-MM-DD',
|
|
256
|
+
zippedArchive: true,
|
|
257
|
+
maxFiles: '2d',
|
|
258
|
+
maxSize: '2g',
|
|
259
|
+
level: 'error',
|
|
260
|
+
} ),
|
|
261
|
+
new DailyRotateFile( {
|
|
262
|
+
filename: \`application-%DATE%.log\`,
|
|
263
|
+
dirname: \`storage/logs/\`,
|
|
264
|
+
datePattern: 'YYYY-MM-DD',
|
|
265
|
+
zippedArchive: true,
|
|
266
|
+
maxFiles: '2d',
|
|
267
|
+
maxSize: '2g',
|
|
268
|
+
} ),
|
|
269
|
+
],
|
|
270
|
+
} );
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
`;
|
|
274
|
+
fs.writeFileSync(
|
|
275
|
+
path.join( __dirname, `/config/logger`, `logger.js` ),
|
|
276
|
+
|
|
277
|
+
loggerContent,
|
|
278
|
+
);
|
|
279
|
+
console.log( `Folder structure for ${folderName} created successfully.` );
|
|
280
|
+
|
|
281
|
+
// Create database.js file
|
|
282
|
+
const envjsContent = `
|
|
283
|
+
const appConfig = {
|
|
284
|
+
app: {
|
|
285
|
+
environment: 'development',
|
|
286
|
+
},
|
|
287
|
+
api: {
|
|
288
|
+
version: [ 'v3' ],
|
|
289
|
+
},
|
|
290
|
+
url: {
|
|
291
|
+
admin: '',
|
|
292
|
+
audit: '',
|
|
293
|
+
},
|
|
294
|
+
database: {
|
|
295
|
+
mongo: {
|
|
296
|
+
hostname: 'serverlessinstance-1.o0iqto1.mongodb.net',
|
|
297
|
+
name: 'tango-api-uat',
|
|
298
|
+
},
|
|
299
|
+
postgre: {},
|
|
300
|
+
},
|
|
301
|
+
cloud: {
|
|
302
|
+
aws: {
|
|
303
|
+
region: 'ap-south-1',
|
|
304
|
+
secertManager: 'tango-api-dev',
|
|
305
|
+
sqs: {
|
|
306
|
+
url: '',
|
|
307
|
+
},
|
|
308
|
+
bucket: {
|
|
309
|
+
name: '',
|
|
310
|
+
},
|
|
311
|
+
version: 'v4',
|
|
312
|
+
},
|
|
313
|
+
elasticSearch: {
|
|
314
|
+
cloud: {
|
|
315
|
+
id: process.env.ELASTIC_CLOUD_ID,
|
|
316
|
+
},
|
|
317
|
+
auth: {
|
|
318
|
+
username: process.env.ELASTIC_USERNAME,
|
|
319
|
+
password: process.env.ELASTIC_PASSWORD,
|
|
320
|
+
},
|
|
321
|
+
// node: process.env.ELASTIC_NODE,
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
export default appConfig;
|
|
328
|
+
|
|
329
|
+
`;
|
|
330
|
+
|
|
331
|
+
fs.writeFileSync(
|
|
332
|
+
path.join( __dirname, `/config/env`, `env.js` ),
|
|
333
|
+
envjsContent,
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
// Install specific dependencies
|
|
337
|
+
console.log( 'Installing dependencies...', {
|
|
338
|
+
cwd: path.join( __dirname ),
|
|
339
|
+
} );
|
|
340
|
+
try {
|
|
341
|
+
const gitignoreContent = [
|
|
342
|
+
'node_modules/',
|
|
343
|
+
'package-lock.json',
|
|
344
|
+
'storage/',
|
|
345
|
+
'config/',
|
|
346
|
+
'app.js',
|
|
347
|
+
'.env',
|
|
348
|
+
].join( '\r\n' ); // Use Windows-style line endings
|
|
349
|
+
|
|
350
|
+
// Write content to .gitignore
|
|
351
|
+
fs.writeFileSync( path.join( __dirname, '.gitignore' ), gitignoreContent );
|
|
352
|
+
|
|
353
|
+
// Install npm dependencies
|
|
354
|
+
const npmCommand = 'npm install express mongodb aws-sdk nodemon tango-api-schema winston winston-daily-rotate-file dotenv';
|
|
355
|
+
execSync( npmCommand, { cwd: path.join( __dirname ), stdio: 'inherit' } );
|
|
356
|
+
|
|
357
|
+
console.log( 'Dependencies installed successfully.' );
|
|
358
|
+
} catch ( error ) {
|
|
359
|
+
console.error( 'Error occurred while installing dependencies:', error );
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Install specific dependencies as devDependencies
|
|
363
|
+
console.log( 'Installing devDependencies...' );
|
|
364
|
+
try {
|
|
365
|
+
await execSync(
|
|
366
|
+
' npm install --save-dev eslint eslint-config-google eslint-config-semistandard eslint-config-standard eslint-plugin-import eslint-plugin-promise',
|
|
367
|
+
{ cwd: path.join( __dirname ) },
|
|
368
|
+
);
|
|
369
|
+
console.log( 'devDependencies installed successfully.' );
|
|
370
|
+
} catch ( error ) {
|
|
371
|
+
console.error( 'Error occurred while installing devDependencies:', error );
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
// Usage: node createProjectStructure.js myapi
|
|
376
|
+
createProjectStructure( process.argv[2] );
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { logger } from 'tango-app-api-middleware';
|
|
2
|
+
import paymentService from '../services/paymentSubscription.services.js';
|
|
3
|
+
// import mongoose from 'mongoose';
|
|
4
|
+
// const ObjectId = mongoose.Types.ObjectId;
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
export const addBilling = async ( req, res ) => {
|
|
8
|
+
try {
|
|
9
|
+
let details = await paymentService.findOne( { _id: req.body.brand }, { _id: 1 } );
|
|
10
|
+
if ( !details ) {
|
|
11
|
+
return res.sendNoContent( 'Brand Not Found' );
|
|
12
|
+
}
|
|
13
|
+
let params = {
|
|
14
|
+
'billingDetails.gstNumber': req.body.gstNo,
|
|
15
|
+
'billingDetails.billingAddress': req.body.billingAddress,
|
|
16
|
+
};
|
|
17
|
+
let result = await paymentService.updateOne( { _id: req.body.brand }, params );
|
|
18
|
+
if ( result.modifiedCount ) {
|
|
19
|
+
logger.info( 'Billing Details Added Successfully' );
|
|
20
|
+
return res.sendSuccess( { message: 'Bank Details Added Successfully' } );
|
|
21
|
+
} else {
|
|
22
|
+
logger.error( 'Error Occurs WHile updating billing Detaisls' );
|
|
23
|
+
return res.sendError( 'Something Went Wrong', 500 );
|
|
24
|
+
}
|
|
25
|
+
} catch ( e ) {
|
|
26
|
+
console.log( e );
|
|
27
|
+
logger.error( e );
|
|
28
|
+
return res.sendError( e, 500 );
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
export const billingInfo = async ( req, res, next ) => {
|
|
34
|
+
try {
|
|
35
|
+
let brandInfo;
|
|
36
|
+
brandInfo = await paymentService.findOne( { _id: req.params.brandId } );
|
|
37
|
+
if ( !brandInfo ) {
|
|
38
|
+
return res.sendNoContent( 'Client is not Found' );
|
|
39
|
+
}
|
|
40
|
+
let storeCount = await paymentService.storeCount( { clientId: brandInfo.clientId } );
|
|
41
|
+
|
|
42
|
+
let virtualBankInfo = await paymentService.VirtualAccFind( {}, { _id: 0, createdAt: 0, updatedAt: 0 } );
|
|
43
|
+
let description;
|
|
44
|
+
if ( brandInfo?.planDetails?.subscriptionType && brandInfo?.planDetails?.subscriptionType == 'free' ) {
|
|
45
|
+
description = 'You will not be billed during your free subscription. To explore other products, upgrade to a paid subscription.';
|
|
46
|
+
} else if ( brandInfo?.planDetails?.subscriptionType && brandInfo.planDetails.subscriptionType == 'premium' ) {
|
|
47
|
+
description = 'You will not be billed during your free trial.To keep your dashboard running after the trial end, upgrade to a paid subscription.';
|
|
48
|
+
} else if ( brandInfo?.planDetails?.subscriptionType && brandInfo.planDetails.subscriptionType == 'enterprice' ) {
|
|
49
|
+
description = 'You will not be billed during your free trial.To keep your dashboard running after the trial end, upgrade to a paid subscription.';
|
|
50
|
+
}
|
|
51
|
+
let data = {
|
|
52
|
+
brandDetails: brandInfo,
|
|
53
|
+
bankDetails: virtualBankInfo,
|
|
54
|
+
storeCount: storeCount,
|
|
55
|
+
description: description,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
return res.sendSuccess( data );
|
|
59
|
+
} catch ( e ) {
|
|
60
|
+
console.log( e );
|
|
61
|
+
logger.error( e );
|
|
62
|
+
return res.sendError( e, 500 );
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const getStoreList = async ( req, res ) => {
|
|
67
|
+
try {
|
|
68
|
+
let storeList = await paymentService.storeFind( { clientId: req.query.clientId }, { _id: 1, storeId: 1, storeName: 1 } );
|
|
69
|
+
|
|
70
|
+
if ( !storeList.length ) {
|
|
71
|
+
return res.sendNoContent( 'No Stores Found' );
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return res.sendSuccess( storeList );
|
|
75
|
+
} catch ( e ) {
|
|
76
|
+
logger.error( e );
|
|
77
|
+
return res.sendError( e, 500 );
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export const getClientList = async ( req, res ) => {
|
|
82
|
+
try {
|
|
83
|
+
let storeList = await paymentService.find( {}, { clientId: 1, _id: 1, clientName: 1 } );
|
|
84
|
+
|
|
85
|
+
if ( !storeList.length ) {
|
|
86
|
+
return res.sendNoContent( 'No Stores Found' );
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return res.sendSuccess( storeList );
|
|
90
|
+
} catch ( e ) {
|
|
91
|
+
logger.error( e );
|
|
92
|
+
return res.sendError( e, 500 );
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export const pricingInfo = async ( req, res ) => {
|
|
97
|
+
try {
|
|
98
|
+
let query = [
|
|
99
|
+
{
|
|
100
|
+
$match: {
|
|
101
|
+
product_name: { $in: req.body.products },
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
$group: {
|
|
106
|
+
_id: '',
|
|
107
|
+
price: { $sum: '$base_price' },
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
$project: {
|
|
112
|
+
_id: 0,
|
|
113
|
+
price: 1,
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
];
|
|
117
|
+
let pricingDetails = await paymentService.getprice( query );
|
|
118
|
+
|
|
119
|
+
return res.sendSuccess( { price: pricingDetails } );
|
|
120
|
+
} catch ( e ) {
|
|
121
|
+
logger.error( e );
|
|
122
|
+
return res.sendError( e, 500 );
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import joi from 'joi';
|
|
2
|
+
|
|
3
|
+
export const validateBillingParams = {
|
|
4
|
+
body: joi.object( {
|
|
5
|
+
brand: joi.string().required(),
|
|
6
|
+
gstNo: joi.string().required(),
|
|
7
|
+
billingAddress: joi.string().required(),
|
|
8
|
+
} ),
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const validateBrandParams = {
|
|
12
|
+
params: joi.object( {
|
|
13
|
+
brandId: joi.string().required(),
|
|
14
|
+
} ),
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const validateStoreParams = {
|
|
18
|
+
query: joi.object( {
|
|
19
|
+
clientId: joi.string().required(),
|
|
20
|
+
} ),
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
export const validateProducts = {
|
|
25
|
+
post: joi.object( {
|
|
26
|
+
camara_per_sqft: joi.string().required(),
|
|
27
|
+
currency_type: joi.string().required(),
|
|
28
|
+
plan_name: joi.string().required(),
|
|
29
|
+
products: joi.array().required(),
|
|
30
|
+
stores_count: joi.string().required(),
|
|
31
|
+
} ),
|
|
32
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
import express from 'express';
|
|
3
|
+
import { addBilling, billingInfo, getStoreList, getClientList, pricingInfo } from '../controllers/paymentSubscription.controllers.js';
|
|
4
|
+
import { validate } from 'tango-app-api-middleware';
|
|
5
|
+
import { validateBillingParams, validateBrandParams, validateStoreParams, validateProducts } from '../dtos/validation.dtos.js';
|
|
6
|
+
|
|
7
|
+
export const paymentSubscriptionRouter = express.Router();
|
|
8
|
+
|
|
9
|
+
paymentSubscriptionRouter.post( '/addBilling', validate( validateBillingParams ), addBilling );
|
|
10
|
+
paymentSubscriptionRouter.get( '/brandBillingInfo/:brandId', validate( validateBrandParams ), billingInfo );
|
|
11
|
+
paymentSubscriptionRouter.get( '/storeList', validate( validateStoreParams ), getStoreList );
|
|
12
|
+
paymentSubscriptionRouter.get( '/clientList', getClientList );
|
|
13
|
+
paymentSubscriptionRouter.post( '/basePricing', validate( validateProducts ), pricingInfo );
|
|
14
|
+
|
|
15
|
+
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import model from 'tango-api-schema';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
const findOne = ( query = {}, record = {} ) => {
|
|
5
|
+
return model.clientModel.findOne( query, record ).sort( { updatedAt: -1 } );
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const updateOne = ( query = {}, record = {} ) => {
|
|
9
|
+
return model.clientModel.updateOne( query, { $set: record } );
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const VirtualAccFind = ( query = {}, record ={} ) => {
|
|
13
|
+
return model.vitualModel.findOne( query, record );
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const storeFind = ( query = {}, record = {} ) => {
|
|
17
|
+
return model.storeModel.find( query, record );
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const aggregate = ( query = [] ) => {
|
|
21
|
+
return model.clientModel.aggregate( query );
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const find = ( query = {}, record = {} ) => {
|
|
25
|
+
return model.clientModel.find( query, record );
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const storeCount = ( query= {} ) => {
|
|
29
|
+
return model.storeModel.count( query );
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const getprice = ( query= {} ) => {
|
|
33
|
+
return model.basePricingModel.aggregate( query );
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
export default {
|
|
38
|
+
findOne,
|
|
39
|
+
updateOne,
|
|
40
|
+
VirtualAccFind,
|
|
41
|
+
storeFind,
|
|
42
|
+
aggregate,
|
|
43
|
+
find,
|
|
44
|
+
storeCount,
|
|
45
|
+
getprice,
|
|
46
|
+
};
|