tango-app-api-client 3.1.14 → 3.1.15

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tango-app-api-client",
3
- "version": "3.1.14",
3
+ "version": "3.1.15",
4
4
  "description": "client",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -25,8 +25,8 @@
25
25
  "mongodb": "^6.3.0",
26
26
  "nodemon": "^3.0.3",
27
27
  "swagger-ui-express": "^5.0.0",
28
- "tango-api-schema": "^2.0.93",
29
- "tango-app-api-middleware": "^3.1.9",
28
+ "tango-api-schema": "^2.0.104",
29
+ "tango-app-api-middleware": "^3.1.11",
30
30
  "winston": "^3.11.0",
31
31
  "winston-daily-rotate-file": "^5.0.0"
32
32
  },
@@ -1,11 +1,11 @@
1
- import { billingDetailsUpdate, brandInfoUpdate, domainDetailsConfigurationUpdate, featureConfigurationUpdate, getClientData, signatoryDetailsUpdate, ticketConfigurationUpdate, documentsUpdate, getUserData, auditConfigurationUpdate, auditConfigurationGet, CsmUsersGet, OpsUsersGet, userConfigurationUpdate, findClient, aggregateClient, createAuditQueue, findOne, insert, update, findOneClient } from '../service/client.service.js';
1
+ import { billingDetailsUpdate, brandInfoUpdate, domainDetailsConfigurationUpdate, featureConfigurationUpdate, getClientData, signatoryDetailsUpdate, ticketConfigurationUpdate, documentsUpdate, getUserData, auditConfigurationUpdate, auditConfigurationGet, CsmUsersGet, OpsUsersGet, userConfigurationUpdate, findClient, aggregateClient, createAuditQueue, findOne, insert, update, findOneClient, updateOneClient } from '../service/client.service.js';
2
2
  import { checkFileExist, fileUpload, signedUrl, chunkArray, download, logger, getOpenSearchData, insertOpenSearchData, appConfig, sendEmailWithSES } from 'tango-app-api-middleware';
3
3
  import { countDocumentsUser, findOneAndUpdateUser, findOneUser, getUserNameEmailById, updateManyUser } from '../service/user.service.js';
4
- import { aggregateStore, countDocumentsStore, updateManyStore } from '../service/store.service.js';
4
+ import { aggregateStore, countDocumentsStore, findOneStore, updateManyStore } from '../service/store.service.js';
5
5
  import { aggregateCamera, countDocumentsCamera, updateManyCamera } from '../service/camera.service.js';
6
6
  import _ from 'lodash';
7
7
  import { findOneStandaredRole } from '../service/standaredRole.service.js';
8
- import { aggregateUserAssignedStore } from '../service/userAssignedStore.service.js';
8
+ import { aggregateUserAssignedStore, deleteOneAssignedStore, updateOneUserAssignedStore } from '../service/userAssignedStore.service.js';
9
9
  import { aggregateTickets } from '../service/tangoticket.service.js';
10
10
  import { join } from 'path';
11
11
  import { readFileSync } from 'fs';
@@ -180,6 +180,44 @@ export async function create( req, res ) {
180
180
 
181
181
  await postApi( `${appConfig.url.oldapidomain}/oldDefaultRoleInsert`, oldDefaultRolesInsertData );
182
182
 
183
+ const logObj = {
184
+ clientId: insertedClientRecord.clientId,
185
+ userName: req.user?.userName,
186
+ email: req.user?.email,
187
+ date: new Date(),
188
+ logType: 'brandDetails',
189
+ logSubType: 'brandApproval',
190
+ changes: [ insertedClientRecord.clientName ],
191
+ showTo: [],
192
+ eventType: 'approve',
193
+ showTo: [ 'client', 'tango' ],
194
+ };
195
+
196
+ await insertOpenSearchData( appConfig.opensearch.activityLog, logObj );
197
+
198
+ for ( let index = 0; index < leadRecord?.planDetails?.product?.length; index++ ) {
199
+ const logObj = {
200
+ userName: req.user?.userName,
201
+ email: req.user?.email,
202
+ clientId: insertedClientRecord.clientId,
203
+ clientNotification: false,
204
+ adminNotification: true,
205
+ logSubType: 'startTrial',
206
+ description: 'Subscription - Your 14 Days free trial has been started',
207
+ title: 'Subscription',
208
+ alertCta: [],
209
+ markasRead: false,
210
+ logType: 'subscription',
211
+ showPushNotification: true,
212
+ date: new Date(),
213
+ changes: [ `${convertTitleCase( leadRecord?.planDetails?.product[index] )} trial started` ],
214
+ eventType: '',
215
+ showTo: [ 'client', 'tango' ],
216
+ };
217
+
218
+ await insertOpenSearchData( appConfig.opensearch.activityLog, logObj );
219
+ }
220
+
183
221
 
184
222
  if ( insertClient ) {
185
223
  const userRecord = {
@@ -200,6 +238,13 @@ export async function create( req, res ) {
200
238
  }
201
239
  }
202
240
 
241
+ function convertTitleCase( data ) {
242
+ let [ firstWord, secondWord ] = data.replace( /([a-z])([A-Z])/g, '$1 $2' ).split( ' ' );
243
+ firstWord = firstWord.charAt( 0 ).toUpperCase() + firstWord.slice( 1 );
244
+ data = firstWord + ' ' + secondWord;
245
+ return data;
246
+ }
247
+
203
248
  export const sendEmail = ( data ) => {
204
249
  try {
205
250
  const attachments = null;
@@ -249,6 +294,16 @@ export async function getClients( req, res ) {
249
294
  $match: {
250
295
  userEmail: req?.user?.email,
251
296
  assignedType: { $eq: 'client' },
297
+ $expr: {
298
+ $cond: {
299
+ if: { $and: [
300
+ { $eq: [ '$userType', 'tango' ] },
301
+ { $eq: [ '$tangoUserType', 'csm' ] },
302
+ ] },
303
+ then: { $eq: [ '$isClientApproved', true ] },
304
+ else: true,
305
+ },
306
+ },
252
307
  },
253
308
  },
254
309
  {
@@ -413,11 +468,30 @@ export async function detailedAllClientCount( req, res ) {
413
468
 
414
469
  },
415
470
  },
471
+ {
472
+ $project: {
473
+ _id: 0,
474
+ totalCount: 1,
475
+ activeClient: 1,
476
+ paidClient: 1,
477
+ trialClient: 1,
478
+ freeClient: 1,
479
+ holdClient: 1,
480
+ suspendClient: 1,
481
+ deactiveClient: 1,
482
+ activeStoresCount: { $ifNull: [ 0, 0 ] },
483
+ activeCameraCount: { $ifNull: [ 0, 0 ] },
484
+ },
485
+ },
416
486
  ];
417
487
  const result = await aggregateClient( query );
418
- if ( result == 0 ) {
488
+ const activeStores = await countDocumentsStore( { 'status': 'active', 'edge.firstFile': true } );
489
+ const activeCameras = await countDocumentsCamera( { isUp: true, isActivated: true } );
490
+ if ( result.length == 0 ) {
419
491
  return res.sendError( 'No Data Found', 204 );
420
492
  }
493
+ result[0].activeStoresCount = activeStores;
494
+ result[0].activeCameraCount = activeCameras;
421
495
  return res.sendSuccess( { result: result } );
422
496
  } catch ( error ) {
423
497
  logger.error( { error: error, function: 'detailedAllClientCount' } );
@@ -465,9 +539,12 @@ export async function updateBrandInfo( req, res ) {
465
539
  logSubType: 'brandInfo',
466
540
  changes: updateKeys,
467
541
  eventType: 'update',
542
+ showTo: [ 'client', 'tango' ],
468
543
  };
469
544
 
470
- await insertOpenSearchData( 'tango-retail-activity-logs', logObj );
545
+ if ( updateKeys.length ) {
546
+ await insertOpenSearchData( appConfig.opensearch.activityLog, logObj );
547
+ }
471
548
 
472
549
 
473
550
  const updateAck = await brandInfoUpdate( {
@@ -559,9 +636,13 @@ export async function updateBillingDetails( req, res ) {
559
636
  logSubType: 'billingDetails',
560
637
  changes: updateKeys,
561
638
  eventType: 'update',
639
+ showTo: [ 'client', 'tango' ],
562
640
  };
563
641
 
564
- await insertOpenSearchData( 'tango-retail-activity-logs', logObj );
642
+ if ( updateKeys.length ) {
643
+ await insertOpenSearchData( appConfig.opensearch.activityLog, logObj );
644
+ }
645
+
565
646
 
566
647
  const updateAck = await billingDetailsUpdate( {
567
648
  clientId: req.params?.id, tradeName: req.body?.tradeName, gstNumber: req.body?.gstNumber,
@@ -597,9 +678,13 @@ export async function updateSignatoryDetails( req, res ) {
597
678
  logSubType: 'signatoryDetails',
598
679
  changes: updateKeys,
599
680
  eventType: 'update',
681
+ showTo: [ 'client', 'tango' ],
600
682
  };
601
683
 
602
- await insertOpenSearchData( 'tango-retail-activity-logs', logObj );
684
+ if ( updateKeys.length ) {
685
+ await insertOpenSearchData( appConfig.opensearch.activityLog, logObj );
686
+ }
687
+
603
688
  const updateAck = await signatoryDetailsUpdate( {
604
689
  clientId: req.params?.id, name: req.body?.name, email: req.body?.email,
605
690
  number: req.body?.number, designation: req.body?.designation,
@@ -640,8 +725,12 @@ export async function updateTicketConfiguration( req, res ) {
640
725
  logSubType: 'ticketConfig',
641
726
  changes: updateKeys,
642
727
  eventType: 'update',
728
+ showTo: [ 'tango' ],
643
729
  };
644
- await insertOpenSearchData( 'tango-retail-activity-logs', logObj );
730
+
731
+ if ( updateKeys.length ) {
732
+ await insertOpenSearchData( appConfig.opensearch.activityLog, logObj );
733
+ }
645
734
 
646
735
  if ( updateAck ) {
647
736
  res.sendSuccess( { result: 'Updated Successfully' } );
@@ -725,8 +814,11 @@ export async function updateFeatureConfiguration( req, res ) {
725
814
  logSubType: 'featureConfig',
726
815
  changes: updateKeys,
727
816
  eventType: 'update',
817
+ showTo: [ 'client', 'tango' ],
728
818
  };
729
- await insertOpenSearchData( 'tango-retail-activity-logs', logObj );
819
+ if ( updateKeys.length ) {
820
+ await insertOpenSearchData( appConfig.opensearch.activityLog, logObj );
821
+ }
730
822
 
731
823
  if ( updateAck ) {
732
824
  res.sendSuccess( { result: 'Updated Successfully' } );
@@ -764,9 +856,13 @@ export async function domainDetailsConfiguration( req, res ) {
764
856
  logSubType: 'domainDetails',
765
857
  changes: updateKeys,
766
858
  eventType: 'update',
859
+ showTo: [ 'client', 'tango' ],
767
860
  };
768
861
 
769
- await insertOpenSearchData( 'tango-retail-activity-logs', logObj );
862
+ if ( updateKeys.length ) {
863
+ await insertOpenSearchData( appConfig.opensearch.activityLog, logObj );
864
+ }
865
+
770
866
  if ( updateAck ) {
771
867
  res.sendSuccess( { result: 'Updated Successfully' } );
772
868
  }
@@ -874,9 +970,12 @@ export async function updateDocuments( req, res ) {
874
970
  logSubType: 'documentUpload',
875
971
  changes: updateKeys,
876
972
  eventType: 'update',
973
+ showTo: [ 'client', 'tango' ],
877
974
  };
878
975
 
879
- await insertOpenSearchData( 'tango-retail-activity-logs', logObj );
976
+ if ( updateKeys.length ) {
977
+ await insertOpenSearchData( appConfig.opensearch.activityLog, logObj );
978
+ }
880
979
 
881
980
  if ( updateAck ) {
882
981
  res.sendSuccess( { result: 'Updated Successfully' } );
@@ -912,35 +1011,37 @@ export async function getAuditConfiguration( req, res ) {
912
1011
  export async function auditConfiguration( req, res ) {
913
1012
  try {
914
1013
  for ( let i = 0; i < req.body?.length; i++ ) {
1014
+ const previousStore = await findOneStore( { storeId: req.body[i].storeId }, { auditConfigs: 1, _id: 0 } );
915
1015
  await auditConfigurationUpdate( {
916
1016
  storeId: req.body[i].storeId,
917
1017
  count: req.body[i].count,
918
1018
  iteration: req.body[i].iteration,
919
1019
  ratio: normalizeNumber( req.body[i].ratio, 0, 100 ),
920
1020
  } );
921
- }
922
-
923
- const user = await getUserNameEmailById( req.userId );
924
-
925
- const logObj = {
926
- clientId: req.params?.id,
927
- userName: user.userName,
928
- email: user.email,
929
- date: new Date(),
930
- logType: 'configuration',
931
- logSubType: 'auditConfig',
932
- eventType: 'update',
933
- };
934
1021
 
935
- if ( req.body?.length === 1 ) {
936
- logObj.changes = [ `Audit config for store id ${req.body[0].storeId}` ];
937
- }
1022
+ const logObj = {
1023
+ clientId: req.params?.id,
1024
+ userName: req.user?.userName,
1025
+ email: req.user?.email,
1026
+ date: new Date(),
1027
+ logType: 'configuration',
1028
+ logSubType: 'auditConfig',
1029
+ eventType: 'update',
1030
+ showTo: [ 'tango' ],
1031
+ changes: [ `Audit config for store id ${req.body[i].storeId}` ],
1032
+ storeId: req.body[i].storeId,
1033
+ previous: previousStore,
1034
+ current: {
1035
+ storeId: req.body[i].storeId,
1036
+ count: req.body[i].count,
1037
+ iteration: req.body[i].iteration,
1038
+ ratio: normalizeNumber( req.body[i].ratio, 0, 100 ),
1039
+ },
1040
+ };
938
1041
 
939
- if ( req.body?.length > 1 ) {
940
- logObj.changes = [ `Audit config bulk` ];
1042
+ await insertOpenSearchData( appConfig.opensearch.activityLog, logObj );
941
1043
  }
942
1044
 
943
- await insertOpenSearchData( 'tango-retail-activity-logs', logObj );
944
1045
 
945
1046
  res.sendSuccess( { result: 'Updated Successfully' } );
946
1047
  } catch ( error ) {
@@ -978,6 +1079,15 @@ export async function clientList( req, res ) {
978
1079
  $match: {
979
1080
  userEmail: { $eq: req?.user?.email },
980
1081
  userType: 'tango',
1082
+ $expr: {
1083
+ $cond: {
1084
+ if: { $and: [
1085
+ { $eq: [ '$tangoUserType', 'csm' ] },
1086
+ ] },
1087
+ then: { $eq: [ '$isClientApproved', true ] },
1088
+ else: true,
1089
+ },
1090
+ },
981
1091
 
982
1092
  },
983
1093
  }, {
@@ -1003,6 +1113,10 @@ export async function clientList( req, res ) {
1003
1113
  );
1004
1114
  }
1005
1115
  if ( inputData.filterByPaymentStatus ) {
1116
+ if ( inputData.filterByPaymentStatus.includes( 'paid' ) ) {
1117
+ inputData.filterByPaymentStatus.push( ...[ 'unbilled', 'due' ] );
1118
+ }
1119
+
1006
1120
  clientQuery.push(
1007
1121
  {
1008
1122
  $match: {
@@ -1253,8 +1367,13 @@ export async function clientList( req, res ) {
1253
1367
  list.push( {
1254
1368
  'client Name': chunk[i]?.clientName,
1255
1369
  'client Id': chunk[i]?.clientId,
1370
+ 'Installation Stores Count': chunk[i]?.installedStores || 0,
1371
+ 'Onboarded Stores Count': chunk[i]?.totalStores,
1372
+ 'Store Progress': chunk[i]?.installedStores? `${ ( ( chunk[i]?.installedStores/ chunk[i]?.totalStores )* 100 ).toFixed( 0 )}%`: '0%',
1256
1373
  'Active Store': chunk[i]?.activeStoreCount || 0,
1257
1374
  'Active Camera': chunk[i]?.activeCameraCount && chunk[i]?.activeCameraCount != undefined ? chunk[i]?.activeCameraCount : 0,
1375
+ 'Pending Stores': chunk[i]?.pendingStores || 0,
1376
+ 'Failed Stores': chunk[i]?.failedStores || 0,
1258
1377
  'Payment Status': chunk[i]?.paymentStatus,
1259
1378
  'Subs Plan': chunk[i]?.subscriptionType,
1260
1379
  'Status': chunk[i]?.status,
@@ -1326,7 +1445,10 @@ export async function detailedClientCount( req, res ) {
1326
1445
  export async function getActivityLogs( req, res ) {
1327
1446
  try {
1328
1447
  const query = {
1329
- '_source': [ 'userId', 'userName', 'email', 'date', 'logType', 'logSubType', 'changes', 'eventType' ],
1448
+ '_source': [
1449
+ 'userId', 'userName', 'email', 'date', 'logType', 'logSubType',
1450
+ 'changes', 'eventType',
1451
+ ],
1330
1452
  'query': {
1331
1453
  'bool': {
1332
1454
  'must': [
@@ -1340,6 +1462,13 @@ export async function getActivityLogs( req, res ) {
1340
1462
  },
1341
1463
  'from': ( req.body.offset - 1 ) * req.body.limit,
1342
1464
  'size': req.body.limit,
1465
+ 'sort': [
1466
+ {
1467
+ 'date': {
1468
+ 'order': 'desc',
1469
+ },
1470
+ },
1471
+ ],
1343
1472
  };
1344
1473
 
1345
1474
  if ( req.body?.logTypeFilters?.length ) {
@@ -1363,7 +1492,15 @@ export async function getActivityLogs( req, res ) {
1363
1492
  } );
1364
1493
  }
1365
1494
 
1366
- const logs = await getOpenSearchData( 'tango-retail-activity-logs', query );
1495
+ query.query.bool.must.push(
1496
+ {
1497
+ 'terms': {
1498
+ 'showTo.keyword': [ req.user.userType ],
1499
+ },
1500
+ },
1501
+ );
1502
+
1503
+ const logs = await getOpenSearchData( appConfig.opensearch.activityLog, query );
1367
1504
 
1368
1505
  const hits = logs?.body?.hits?.hits;
1369
1506
  const totalDocuments = logs?.body?.hits?.total?.value;
@@ -1379,6 +1516,7 @@ export async function getActivityLogs( req, res ) {
1379
1516
  }
1380
1517
  }
1381
1518
 
1519
+
1382
1520
  async function postApi( url, data ) {
1383
1521
  const requestOptions = {
1384
1522
  method: 'POST',
@@ -1415,3 +1553,34 @@ async function getApi( url ) {
1415
1553
  }
1416
1554
  }
1417
1555
 
1556
+
1557
+ export async function csmAssignConfirmation( req, res ) {
1558
+ try {
1559
+ const client = await findOneClient( { clientId: req.query.clientId }, { notifyCsmAssign: 1, _id: 0 } );
1560
+ if ( !client ) {
1561
+ res.sendError( 'No data found', 204 );
1562
+ }
1563
+ res.sendSuccess( client );
1564
+ } catch ( error ) {
1565
+ logger.error( { error: error, message: req.params, function: 'csmAssignConfirmation' } );
1566
+ return res.sendError( 'Internal Server Error', 500 );
1567
+ }
1568
+ }
1569
+
1570
+ export async function clientCsmAssignAction( req, res ) {
1571
+ try {
1572
+ await updateOneClient( { clientId: req.query.clientId }, { notifyCsmAssign: false } );
1573
+ if ( req.body.action === 'approve' ) {
1574
+ await updateOneUserAssignedStore( { clientId: req.query.clientId, tangoUserType: 'csm', assignedType: 'client' }, { isClientApproved: true } );
1575
+ }
1576
+
1577
+ if ( req.body.action === 'decline' ) {
1578
+ await deleteOneAssignedStore( { clientId: req.query.clientId, tangoUserType: 'csm', assignedType: 'client' } );
1579
+ }
1580
+
1581
+ res.sendSuccess( 'Updated Succesfully' );
1582
+ } catch ( error ) {
1583
+ logger.error( { error: error, message: req.params, function: 'csmAssignConfirmation' } );
1584
+ return res.sendError( 'Internal Server Error', 500 );
1585
+ }
1586
+ }
@@ -40,14 +40,6 @@ export const clientDocs = {
40
40
  description: 'Get list of clients',
41
41
  operationId: 'get-clients',
42
42
  parameters: [
43
- {
44
- in: 'path',
45
- name: 'id',
46
- required: true,
47
- schema: {
48
- type: 'string',
49
- },
50
- },
51
43
  ],
52
44
  responses: {
53
45
  200: { description: 'Success' },
@@ -455,14 +447,6 @@ export const clientDocs = {
455
447
  description: 'Get toatal info about overall clients',
456
448
  operationId: 'detailed-all-client-count',
457
449
  parameters: [
458
- {
459
- in: 'path',
460
- name: 'id',
461
- required: true,
462
- schema: {
463
- type: 'string',
464
- },
465
- },
466
450
  ],
467
451
  responses: {
468
452
  200: { description: 'Success' },
@@ -261,3 +261,24 @@ export const activityLogSchema = joi.object( {
261
261
  export const activityLogValid = {
262
262
  body: activityLogSchema,
263
263
  };
264
+
265
+ export const getAssignedClientSchama = joi.object( {
266
+ clientId: joi.string().required(),
267
+ } );
268
+
269
+ export const getAssignedClientValid = {
270
+ query: getAssignedClientSchama,
271
+ };
272
+
273
+ export const postClientCamApprovalSchamaQuery = joi.object( {
274
+ clientId: joi.string().required(),
275
+ } );
276
+
277
+ export const postClientCamApprovalSchamaBody = joi.object( {
278
+ action: joi.string().required(),
279
+ } );
280
+
281
+ export const postClientCamApprovalValid = {
282
+ query: postClientCamApprovalSchamaQuery,
283
+ body: postClientCamApprovalSchamaBody,
284
+ };
@@ -1,7 +1,7 @@
1
1
 
2
2
  import express from 'express';
3
- import { activityLogValid, auditConfigValid, billingDetailsValid, brandInfoValid, clientCreationValid, clientDetailsValid, documentsValid, domainDetailsValid, featureConfigurationValid, getAuditConfigValid, signatoryDetailsValid, ticketConfigurationValid, userConfigurationValid } from '../dtos/client.dtos.js';
4
- import { auditConfiguration, changeStatus, clientDetails, create, domainDetailsConfiguration, getActivityLogs, getAuditConfiguration, getClients, getCsmUsers, getOpsUsers, updateBillingDetails, updateBrandInfo, updateDocuments, updateFeatureConfiguration, updateSignatoryDetails, updateTicketConfiguration, userConfiguration } from '../controllers/client.controllers.js';
3
+ import { activityLogValid, auditConfigValid, billingDetailsValid, brandInfoValid, clientCreationValid, clientDetailsValid, documentsValid, domainDetailsValid, featureConfigurationValid, getAssignedClientValid, getAuditConfigValid, postClientCamApprovalValid, signatoryDetailsValid, ticketConfigurationValid, userConfigurationValid } from '../dtos/client.dtos.js';
4
+ import { auditConfiguration, changeStatus, clientCsmAssignAction, clientDetails, create, csmAssignConfirmation, domainDetailsConfiguration, getActivityLogs, getAuditConfiguration, getClients, getCsmUsers, getOpsUsers, updateBillingDetails, updateBrandInfo, updateDocuments, updateFeatureConfiguration, updateSignatoryDetails, updateTicketConfiguration, userConfiguration } from '../controllers/client.controllers.js';
5
5
  import { authorize, isAllowedSessionHandler, validate } from 'tango-app-api-middleware';
6
6
  import { clientListValid, detailedClientCountValid } from '../dtos/client.dtos.js';
7
7
  import { isclientIdExists, isclientNameExists } from '../validations/client.validations.js';
@@ -93,4 +93,10 @@ clientRouter.post( '/activity-log', isAllowedSessionHandler, authorize(
93
93
  { featureName: 'settings', name: 'activityLog', permissions: [ 'isView' ] } ] } ),
94
94
  validate( activityLogValid ), getActivityLogs );
95
95
 
96
+ clientRouter.get( '/show-csm-assign-confirmation', isAllowedSessionHandler,
97
+ validate( getAssignedClientValid ), csmAssignConfirmation );
98
+
99
+ clientRouter.post( '/client-csm-assign-action', isAllowedSessionHandler,
100
+ validate( postClientCamApprovalValid ), clientCsmAssignAction );
101
+
96
102
 
@@ -285,3 +285,12 @@ export function findOneClient( query, field ) {
285
285
  return clientModel.findOne( query, field );
286
286
  }
287
287
 
288
+ export async function updateOneClient( query, record ) {
289
+ return clientModel.updateOne(
290
+ query,
291
+ {
292
+ $set: record,
293
+ },
294
+ );
295
+ }
296
+
@@ -11,3 +11,7 @@ export function aggregateStore( query ) {
11
11
  export function updateManyStore( query, record ) {
12
12
  return storeModel.updateMany( query, { $set: record } );
13
13
  }
14
+
15
+ export function findOneStore( query, field ) {
16
+ return storeModel.findOne( query, field );
17
+ }
@@ -4,3 +4,16 @@ import userAssignedStoreModel from 'tango-api-schema/schema/userAssignedStore.mo
4
4
  export async function aggregateUserAssignedStore( query ) {
5
5
  return await userAssignedStoreModel.aggregate( query );
6
6
  };
7
+
8
+ export async function updateOneUserAssignedStore( query, record ) {
9
+ return userAssignedStoreModel.updateOne(
10
+ query,
11
+ {
12
+ $set: record,
13
+ },
14
+ );
15
+ }
16
+
17
+ export async function deleteOneAssignedStore( query ) {
18
+ return userAssignedStoreModel.deleteOne( query );
19
+ }