tango-app-api-client 3.3.3-beta.8 → 3.4.0-beta.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/package.json +42 -43
- package/src/controllers/client.controllers.js +712 -121
- package/src/docs/client.docs.js +2 -10
package/package.json
CHANGED
|
@@ -1,43 +1,42 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "tango-app-api-client",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"description": "client",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"scripts": {
|
|
8
|
-
"start": "nodemon --exec \"eslint --fix . && node index.js\""
|
|
9
|
-
},
|
|
10
|
-
"engines": {
|
|
11
|
-
"node": ">=18.10.0"
|
|
12
|
-
},
|
|
13
|
-
"author": "praveenraj",
|
|
14
|
-
"license": "ISC",
|
|
15
|
-
"dependencies": {
|
|
16
|
-
"aws-sdk": "^2.1560.0",
|
|
17
|
-
"cors": "^2.8.5",
|
|
18
|
-
"dotenv": "^16.4.4",
|
|
19
|
-
"express": "^4.18.2",
|
|
20
|
-
"express-fileupload": "^1.4.3",
|
|
21
|
-
"handlebars": "^4.7.8",
|
|
22
|
-
"
|
|
23
|
-
"joi": "^
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"tango-api-
|
|
31
|
-
"
|
|
32
|
-
"winston": "^
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"eslint": "^
|
|
37
|
-
"eslint-config-
|
|
38
|
-
"eslint-config-
|
|
39
|
-
"eslint-
|
|
40
|
-
"eslint-plugin-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "tango-app-api-client",
|
|
3
|
+
"version": "3.4.0-beta.0",
|
|
4
|
+
"description": "client",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"start": "nodemon --exec \"eslint --fix . && node index.js\""
|
|
9
|
+
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=18.10.0"
|
|
12
|
+
},
|
|
13
|
+
"author": "praveenraj",
|
|
14
|
+
"license": "ISC",
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"aws-sdk": "^2.1560.0",
|
|
17
|
+
"cors": "^2.8.5",
|
|
18
|
+
"dotenv": "^16.4.4",
|
|
19
|
+
"express": "^4.18.2",
|
|
20
|
+
"express-fileupload": "^1.4.3",
|
|
21
|
+
"handlebars": "^4.7.8",
|
|
22
|
+
"joi": "^17.12.1",
|
|
23
|
+
"joi-to-swagger": "^6.2.0",
|
|
24
|
+
"lodash": "^4.17.21",
|
|
25
|
+
"mongodb": "^6.7.0",
|
|
26
|
+
"nodemon": "^3.0.3",
|
|
27
|
+
"npm": "^10.9.1",
|
|
28
|
+
"swagger-ui-express": "^5.0.0",
|
|
29
|
+
"tango-api-schema": "^2.2.59",
|
|
30
|
+
"tango-app-api-middleware": "^3.1.60",
|
|
31
|
+
"winston": "^3.11.0",
|
|
32
|
+
"winston-daily-rotate-file": "^5.0.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"eslint": "^8.56.0",
|
|
36
|
+
"eslint-config-google": "^0.14.0",
|
|
37
|
+
"eslint-config-semistandard": "^17.0.0",
|
|
38
|
+
"eslint-config-standard": "^17.1.0",
|
|
39
|
+
"eslint-plugin-import": "^2.29.1",
|
|
40
|
+
"eslint-plugin-promise": "^6.1.1"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -142,7 +142,23 @@ export async function create( req, res ) {
|
|
|
142
142
|
'isDefaults': true,
|
|
143
143
|
};
|
|
144
144
|
|
|
145
|
-
await createclusterModel( defaultcluster );
|
|
145
|
+
const cluster = await createclusterModel( defaultcluster );
|
|
146
|
+
|
|
147
|
+
const logClusterObj = {
|
|
148
|
+
clientId: insertedClientRecord.clientId,
|
|
149
|
+
userName: req.user?.userName,
|
|
150
|
+
userId: req?.user?._id,
|
|
151
|
+
email: req.user?.email,
|
|
152
|
+
clusterId: cluster._id,
|
|
153
|
+
date: new Date(),
|
|
154
|
+
logType: 'cluster',
|
|
155
|
+
logSubType: 'clusterCreated',
|
|
156
|
+
changes: [ 'All stores' ],
|
|
157
|
+
eventType: 'create',
|
|
158
|
+
showTo: [ 'client', 'tango' ],
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
await insertOpenSearchData( openSearch.activityLog, logClusterObj );
|
|
146
162
|
|
|
147
163
|
|
|
148
164
|
const defaultGroup = {
|
|
@@ -284,6 +300,7 @@ export async function create( req, res ) {
|
|
|
284
300
|
const logObj = {
|
|
285
301
|
clientId: insertedClientRecord.clientId,
|
|
286
302
|
userName: req.user?.userName,
|
|
303
|
+
userId: req?.user?._id,
|
|
287
304
|
email: req.user?.email,
|
|
288
305
|
date: new Date(),
|
|
289
306
|
logType: 'brandDetails',
|
|
@@ -691,7 +708,7 @@ export async function updateBrandInfo( req, res ) {
|
|
|
691
708
|
ContentType: req.files.logo.mimetype,
|
|
692
709
|
body: req.files.logo.data,
|
|
693
710
|
};
|
|
694
|
-
updateKeys.push( 'Logo' );
|
|
711
|
+
updateKeys.push( 'Brand Logo' );
|
|
695
712
|
await fileUpload( uploadDataParams );
|
|
696
713
|
}
|
|
697
714
|
|
|
@@ -701,32 +718,93 @@ export async function updateBrandInfo( req, res ) {
|
|
|
701
718
|
} );
|
|
702
719
|
}
|
|
703
720
|
|
|
704
|
-
|
|
721
|
+
// Get updated client information before the update operation (fetch selected fields only)
|
|
722
|
+
const getPreCientInfo = await findOneClient(
|
|
723
|
+
{ clientId: req.params.id }, // Filter by clientId
|
|
724
|
+
{
|
|
725
|
+
'_id': 0,
|
|
726
|
+
'profileDetails.registeredCompanyName': 1,
|
|
727
|
+
'profileDetails.industry': 1,
|
|
728
|
+
'profileDetails.clientType': 1,
|
|
729
|
+
'profileDetails.registeredAddress': 1,
|
|
730
|
+
'profileDetails.headQuarters': 1,
|
|
731
|
+
'profileDetails.website': 1,
|
|
732
|
+
'status': 1,
|
|
733
|
+
'averageTransactionValue': 1,
|
|
734
|
+
},
|
|
735
|
+
);
|
|
736
|
+
|
|
705
737
|
|
|
738
|
+
const updateAck = await brandInfoUpdate( {
|
|
739
|
+
clientId: req.params?.id, registeredCompanyName: req.body?.registeredCompanyName, industry: req.body?.industry,
|
|
740
|
+
clientType: req.body?.clientType, registeredAddress: req.body?.registeredAddress, headQuarters: req.body?.headQuarters,
|
|
741
|
+
website: req.body?.website, status: req.body?.status, logo: req.files?.logo ? `brandLogo.${req.files.logo.name.split( '.' )[1]}` : undefined, averageTransactionValue: req.body?.averageTransactionValue,
|
|
742
|
+
} );
|
|
706
743
|
|
|
744
|
+
// Get updated client information after the update operation (fetch selected fields only)
|
|
745
|
+
const getPosCientInfo = await findOneClient(
|
|
746
|
+
{ clientId: req.params.id }, // Filter by clientId
|
|
747
|
+
{
|
|
748
|
+
'_id': 0,
|
|
749
|
+
'profileDetails.registeredCompanyName': 1,
|
|
750
|
+
'profileDetails.industry': 1,
|
|
751
|
+
'profileDetails.clientType': 1,
|
|
752
|
+
'profileDetails.registeredAddress': 1,
|
|
753
|
+
'profileDetails.headQuarters': 1,
|
|
754
|
+
'profileDetails.website': 1,
|
|
755
|
+
'status': 1,
|
|
756
|
+
'averageTransactionValue': 1,
|
|
757
|
+
},
|
|
758
|
+
);
|
|
759
|
+
// Map and rename keys from previous client info for UI display and logging
|
|
760
|
+
const oldData = {
|
|
761
|
+
RegisteredCompanyName: getPreCientInfo?.profileDetails?.registeredCompanyName,
|
|
762
|
+
IndustryType: getPreCientInfo?.profileDetails?.industry,
|
|
763
|
+
FirmType: getPreCientInfo?.profileDetails?.clientType,
|
|
764
|
+
RegisteredAddress: getPreCientInfo?.profileDetails?.registeredAddress,
|
|
765
|
+
HeadQuarters: getPreCientInfo?.profileDetails?.headQuarters,
|
|
766
|
+
CompanyWebsite: getPreCientInfo?.profileDetails?.website,
|
|
767
|
+
ProcessingStatus: getPreCientInfo?.status,
|
|
768
|
+
AverageTransactionValue: getPreCientInfo?.averageTransactionValue,
|
|
769
|
+
};
|
|
770
|
+
|
|
771
|
+
// Map and rename keys from current client info for UI display and logging
|
|
772
|
+
const newData ={
|
|
773
|
+
RegisteredCompanyName: getPosCientInfo?.profileDetails?.registeredCompanyName,
|
|
774
|
+
IndustryType: getPosCientInfo?.profileDetails?.industry,
|
|
775
|
+
FirmType: getPosCientInfo?.profileDetails?.clientType,
|
|
776
|
+
RegisteredAddress: getPosCientInfo?.profileDetails?.registeredAddress,
|
|
777
|
+
HeadQuarters: getPosCientInfo?.profileDetails?.headQuarters,
|
|
778
|
+
CompanyWebsite: getPosCientInfo?.profileDetails?.website,
|
|
779
|
+
ProcessingStatus: getPosCientInfo?.status,
|
|
780
|
+
AverageTransactionValue: getPosCientInfo?.averageTransactionValue,
|
|
781
|
+
|
|
782
|
+
};
|
|
783
|
+
|
|
784
|
+
// Prepare activity log object with all relevant details for OpenSearch logging
|
|
707
785
|
const logObj = {
|
|
708
|
-
clientId: req.params?.id,
|
|
709
|
-
userName: user?.userName,
|
|
710
|
-
email: user?.email,
|
|
711
|
-
date: new Date(),
|
|
712
|
-
logType: 'brandDetails',
|
|
713
|
-
logSubType: 'brandInfo',
|
|
714
|
-
changes: updateKeys,
|
|
715
|
-
eventType: 'update',
|
|
716
|
-
showTo: [ 'client', 'tango' ],
|
|
786
|
+
clientId: req.params?.id, // ID of the client whose data was updated
|
|
787
|
+
userName: req?.user?.userName, // Name of the user performing the update
|
|
788
|
+
email: req?.user?.email, // Email of the user performing the update
|
|
789
|
+
date: new Date(), // Timestamp of the update event
|
|
790
|
+
logType: 'brandDetails', // Type of log (e.g., related to brand details)
|
|
791
|
+
logSubType: 'brandInfo', // Subtype for more specific categorization
|
|
792
|
+
changes: updateKeys, // List of fields that were updated.these will shown in the UI as part of activity log
|
|
793
|
+
eventType: 'update', // Type of event (update operation)
|
|
794
|
+
showTo: [ 'client', 'tango' ], // Visibility of the log (who can see this log)
|
|
795
|
+
previous: getPreCientInfo, // Previous (old) client information before update based on DB keys (for internal reference and comparison).
|
|
796
|
+
current: getPosCientInfo, // Current (new) client information after update based on DB keys (for internal reference and comparison).
|
|
797
|
+
oldData: oldData, // Previous (old) client information before update (used for showing detailed changes in the UI).
|
|
798
|
+
newData: newData, // Current (new) client information after update (used for showing detailed changes in the UI).
|
|
717
799
|
};
|
|
800
|
+
logger.info( { logObj: logObj, updateKeys: updateKeys, length: updateKeys?.length } );
|
|
718
801
|
|
|
802
|
+
// Insert activity log into OpenSearch if there are fields that were updated
|
|
719
803
|
if ( updateKeys.length ) {
|
|
720
|
-
await insertOpenSearchData( openSearch.activityLog, logObj );
|
|
804
|
+
await insertOpenSearchData( openSearch.activityLog, logObj ); // Insert activity log
|
|
721
805
|
}
|
|
722
806
|
|
|
723
807
|
|
|
724
|
-
const updateAck = await brandInfoUpdate( {
|
|
725
|
-
clientId: req.params?.id, registeredCompanyName: req.body?.registeredCompanyName, industry: req.body?.industry,
|
|
726
|
-
clientType: req.body?.clientType, registeredAddress: req.body?.registeredAddress, headQuarters: req.body?.headQuarters,
|
|
727
|
-
website: req.body?.website, status: req.body?.status, logo: req.files?.logo ? `brandLogo.${req.files.logo.name.split( '.' )[1]}` : undefined, averageTransactionValue: req.body?.averageTransactionValue,
|
|
728
|
-
} );
|
|
729
|
-
|
|
730
808
|
if ( req.body?.status === 'active' ) {
|
|
731
809
|
await updateManyStore( { clientId: req.params?.id }, { status: 'active' } );
|
|
732
810
|
await updateManyUser( { clientId: req.params?.id }, { isActive: true } );
|
|
@@ -743,7 +821,6 @@ export async function updateBrandInfo( req, res ) {
|
|
|
743
821
|
|
|
744
822
|
if ( req.body?.status === 'deactive' ) {
|
|
745
823
|
await updateManyStore( { clientId: req.params?.id }, { status: 'deactive' } );
|
|
746
|
-
// await updateManyCamera( { clientId: req.params?.id }, { isUp: false, isActivated: false } );
|
|
747
824
|
await updateManyUser( { clientId: req.params?.id }, { isActive: false } );
|
|
748
825
|
}
|
|
749
826
|
|
|
@@ -769,7 +846,7 @@ export async function updateBrandInfo( req, res ) {
|
|
|
769
846
|
await postApi( `${url.oldapidomain}/oldBrandUpdate/${data?._id}`, { clientStatus: data.clientStatus } );
|
|
770
847
|
|
|
771
848
|
if ( updateAck ) {
|
|
772
|
-
res.sendSuccess( { result: 'Updated Successfully' } );
|
|
849
|
+
return res.sendSuccess( { result: 'Updated Successfully' } );
|
|
773
850
|
}
|
|
774
851
|
} catch ( error ) {
|
|
775
852
|
logger.error( { error: error, message: req.params, function: 'updateBrandInfo' } );
|
|
@@ -878,6 +955,25 @@ export async function updateSignatoryDetails( req, res ) {
|
|
|
878
955
|
export async function updateTicketConfiguration( req, res ) {
|
|
879
956
|
try {
|
|
880
957
|
const openSearch = JSON.parse( process.env.OPENSEARCH );
|
|
958
|
+
const fields ={
|
|
959
|
+
'ticketConfigs.downTimeType': 1,
|
|
960
|
+
'ticketConfigs.installationReAssign': 1,
|
|
961
|
+
'ticketConfigs.infraDownTime': 1,
|
|
962
|
+
'ticketConfigs.MinFilesCount': 1,
|
|
963
|
+
'ticketConfigs.rcaTicketAssign': 1,
|
|
964
|
+
'ticketConfigs.refreshAlert': 1,
|
|
965
|
+
'ticketConfigs.statusCheckAlert': 1,
|
|
966
|
+
'ticketConfigs.accuracyPercentage': 1,
|
|
967
|
+
'ticketConfigs.reTrain': 1,
|
|
968
|
+
};
|
|
969
|
+
|
|
970
|
+
// Get updated client ticket configuration before the update operation (fetch selected fields only)
|
|
971
|
+
let findClient = await findOneClient(
|
|
972
|
+
{ clientId: req.params?.id }, // Filter by clientId
|
|
973
|
+
fields,
|
|
974
|
+
);
|
|
975
|
+
|
|
976
|
+
// update the requested values in Mongo DB
|
|
881
977
|
const updateAck = await ticketConfigurationUpdate( {
|
|
882
978
|
clientId: req.params?.id, MinFilesCount: req.body?.MinFilesCount, accuracyPercentage: req.body?.accuracyPercentage, downTimeType: req.body?.downTimeType,
|
|
883
979
|
infraDownTime: req.body?.infraDownTime, installationReAssign: req.body?.installationReAssign, isRcaTicketAssign: req.body?.isRcaTicketAssign,
|
|
@@ -885,37 +981,75 @@ export async function updateTicketConfiguration( req, res ) {
|
|
|
885
981
|
refreshAlert: req.body?.refreshAlert, sendToAdmin: req.body?.sendToAdmin, sendToUser: req.body?.sendToUser, statusCheckAlert: req.body?.statusCheckAlert,
|
|
886
982
|
} );
|
|
887
983
|
|
|
888
|
-
let updateKeys = [];
|
|
984
|
+
let updateKeys = []; // List of updated field names in readable format
|
|
985
|
+
|
|
986
|
+
// Check if request body has any fields to update
|
|
889
987
|
if ( Object.keys( req.body ).length > 0 ) {
|
|
890
988
|
Object.keys( req.body ).forEach( ( element ) => {
|
|
891
|
-
updateKeys.push( camelCaseToWords( element ) );
|
|
989
|
+
updateKeys.push( camelCaseToWords( element ) ); // Convert camelCase field name to readable format and add to updateKeys
|
|
892
990
|
} );
|
|
893
991
|
}
|
|
894
992
|
|
|
895
|
-
const user = await getUserNameEmailById( req.userId );
|
|
896
993
|
|
|
994
|
+
// Get updated client ticket configuration after the update operation (fetch selected fields only)
|
|
995
|
+
let updatedClient = await findOneClient( { clientId: req.params?.id }, fields );
|
|
996
|
+
|
|
997
|
+
// Map and rename keys from previous client info for UI display and logging
|
|
998
|
+
const oldData = {
|
|
999
|
+
InfraDowntimeType: findClient?.ticketConfigs?.downTimeType,
|
|
1000
|
+
AutoReAssignInstallation: findClient?.ticketConfigs?.installationReAssign,
|
|
1001
|
+
InfraDowntime: findClient?.ticketConfigs?.infraDownTime,
|
|
1002
|
+
InfraFiles: findClient?.ticketConfigs?.MinFilesCount,
|
|
1003
|
+
RcaTicket: findClient?.ticketConfigs?.rcaTicketAssign,
|
|
1004
|
+
RefreshTicketAlert: findClient?.ticketConfigs?.refreshAlert,
|
|
1005
|
+
StatusCheckAlert: findClient?.ticketConfigs?.statusCheckAlert,
|
|
1006
|
+
DataMismatchAccuracyPercentage: findClient?.ticketConfigs?.accuracyPercentage,
|
|
1007
|
+
DataMismatchReTraining: findClient?.ticketConfigs?.reTrain,
|
|
1008
|
+
};
|
|
1009
|
+
|
|
1010
|
+
// Map and rename keys from current client info for UI display and logging
|
|
1011
|
+
const newData ={
|
|
1012
|
+
InfraDowntimeType: updatedClient?.ticketConfigs?.downTimeType,
|
|
1013
|
+
AutoReAssignInstallation: updatedClient?.ticketConfigs?.installationReAssign,
|
|
1014
|
+
InfraDowntime: updatedClient?.ticketConfigs?.infraDownTime,
|
|
1015
|
+
InfraFiles: updatedClient?.ticketConfigs?.MinFilesCount,
|
|
1016
|
+
RcaTicket: updatedClient?.ticketConfigs?.rcaTicketAssign,
|
|
1017
|
+
RefreshTicketAlert: updatedClient?.ticketConfigs?.refreshAlert,
|
|
1018
|
+
StatusCheckAlert: updatedClient?.ticketConfigs?.statusCheckAlert,
|
|
1019
|
+
DataMismatchAccuracyPercentage: updatedClient?.ticketConfigs?.accuracyPercentage,
|
|
1020
|
+
DataMismatchReTraining: updatedClient?.ticketConfigs?.reTrain,
|
|
1021
|
+
|
|
1022
|
+
};
|
|
1023
|
+
|
|
1024
|
+
// Prepare activity log object with all relevant details for OpenSearch logging
|
|
897
1025
|
const logObj = {
|
|
898
|
-
clientId: req.params?.id,
|
|
899
|
-
userName: user
|
|
900
|
-
email: user
|
|
901
|
-
date: new Date(),
|
|
902
|
-
logType: 'configuration',
|
|
903
|
-
logSubType: 'ticketConfig',
|
|
904
|
-
changes: updateKeys,
|
|
905
|
-
eventType: 'update',
|
|
906
|
-
showTo: [ 'tango' ],
|
|
1026
|
+
clientId: req.params?.id, // ID of the client whose data was updated
|
|
1027
|
+
userName: req?.user?.userName, // Name of the user performing the update
|
|
1028
|
+
email: req?.user?.email, // Email of the user performing the update
|
|
1029
|
+
date: new Date(), // Timestamp of the update event
|
|
1030
|
+
logType: 'configuration', // Type of log (e.g., related to brand details)
|
|
1031
|
+
logSubType: 'ticketConfig', // Subtype for more specific categorization
|
|
1032
|
+
changes: updateKeys, // List of fields that were updated.these will shown in the UI as part of activity log
|
|
1033
|
+
eventType: 'update', // Type of event (update operation)
|
|
1034
|
+
showTo: [ 'tango' ], // Visibility of the log (who can see this log)
|
|
1035
|
+
current: updatedClient.ticketConfigs, // Previous (old) client information before update based on DB keys (for internal reference and comparison).
|
|
1036
|
+
previous: findClient.ticketConfigs, // Current (new) client information after update based on DB keys (for internal reference and comparison).
|
|
1037
|
+
oldData: oldData, // Previous (old) client information before update (used for showing detailed changes in the UI).
|
|
1038
|
+
newData: newData, // Current (new) client information after update (used for showing detailed changes in the UI).
|
|
907
1039
|
};
|
|
908
1040
|
|
|
1041
|
+
// Insert activity log into OpenSearch if there are fields that were updated
|
|
909
1042
|
if ( updateKeys.length ) {
|
|
910
|
-
await insertOpenSearchData( openSearch.activityLog, logObj );
|
|
1043
|
+
await insertOpenSearchData( openSearch.activityLog, logObj ); // Insert activity log
|
|
911
1044
|
}
|
|
912
1045
|
|
|
913
1046
|
if ( updateAck ) {
|
|
914
1047
|
res.sendSuccess( { result: 'Updated Successfully' } );
|
|
915
1048
|
}
|
|
916
1049
|
} catch ( error ) {
|
|
1050
|
+
const err = error.message || 'Internal Server Error';
|
|
917
1051
|
logger.error( { error: error, message: req.params, function: 'updateTicketConfiguration' } );
|
|
918
|
-
return res.sendError(
|
|
1052
|
+
return res.sendError( err, 500 );
|
|
919
1053
|
}
|
|
920
1054
|
}
|
|
921
1055
|
|
|
@@ -923,6 +1057,9 @@ export async function updateFeatureConfiguration( req, res ) {
|
|
|
923
1057
|
try {
|
|
924
1058
|
const openSearch = JSON.parse( process.env.OPENSEARCH );
|
|
925
1059
|
const url = JSON.parse( process.env.URL );
|
|
1060
|
+
|
|
1061
|
+
// Get updated client Feature configuration before the update operation (fetch selected fields only)
|
|
1062
|
+
const previousData = await findOneClient( { clientId: req.params?.id }, { featureConfigs: 1 } );
|
|
926
1063
|
const inputData = req.body;
|
|
927
1064
|
if ( inputData?.bouncedLimitValue ) {
|
|
928
1065
|
inputData.missedOpportunityFromValue = inputData?.bouncedLimitValue;
|
|
@@ -933,11 +1070,15 @@ export async function updateFeatureConfiguration( req, res ) {
|
|
|
933
1070
|
}
|
|
934
1071
|
const updateAck = await featureConfigurationUpdate( { clientId: req.params?.id }, inputData );
|
|
935
1072
|
|
|
936
|
-
|
|
1073
|
+
// Get updated client Feature configuration after the update operation (fetch selected fields only)
|
|
1074
|
+
const postData = await findOneClient( { clientId: req.params?.id }, { featureConfigs: 1 } );
|
|
1075
|
+
let updateKeys = []; // List of updated field names in readable format
|
|
937
1076
|
|
|
1077
|
+
// Check if request body has any fields to update
|
|
938
1078
|
if ( Object.keys( inputData ).length > 0 ) {
|
|
939
1079
|
Object.keys( inputData ).forEach( ( element ) => {
|
|
940
|
-
|
|
1080
|
+
element === 'billableCalculation'? 'potentialCalculation': element; // Replace 'billableCalculation' with 'potentialCalculation' if present
|
|
1081
|
+
updateKeys.push( camelCaseToWords( element ) ); // Convert camelCase field name to readable format and add to updateKeys
|
|
941
1082
|
} );
|
|
942
1083
|
}
|
|
943
1084
|
|
|
@@ -986,21 +1127,105 @@ export async function updateFeatureConfiguration( req, res ) {
|
|
|
986
1127
|
}
|
|
987
1128
|
|
|
988
1129
|
await postApi( `${url.oldapidomain}/oldBrandUpdate/${data?._id}`, { brandConfigs: data.brandConfigs } );
|
|
1130
|
+
const keysArray = [
|
|
1131
|
+
'isExcludedArea', 'isPasserByData', 'isNormalized', 'isbillingDisabled',
|
|
1132
|
+
'isCameraDisabled', 'isFootfallDirectory', 'isNOB', 'isNewTraffic',
|
|
1133
|
+
'isTrax', 'isNewZone', 'isNewReports', 'isNewDashboard', 'streamBy',
|
|
1134
|
+
];
|
|
1135
|
+
// Map and rename keys from previous client info for UI display and logging
|
|
1136
|
+
const oldData = {
|
|
1137
|
+
StoreOpenTime: previousData?.featureConfigs?.open,
|
|
1138
|
+
StoreCloseTime: previousData?.featureConfigs?.close,
|
|
1139
|
+
ConversionCalculations: previousData?.featureConfigs?.conversionCalculation,
|
|
1140
|
+
MissedOpportunityCalculation: previousData?.featureConfigs?.missedOpportunityCalculation,
|
|
1141
|
+
PotentialCalculations: previousData?.featureConfigs?.billableCalculation,
|
|
1142
|
+
ConversionCondition: previousData?.featureConfigs?.conversion.condition,
|
|
1143
|
+
ConversionValue: previousData?.featureConfigs?.conversion.value,
|
|
1144
|
+
MissedOpportunityFromCondition: previousData?.featureConfigs?.missedOpportunityFrom?.condition,
|
|
1145
|
+
MissedOpportunityToCondition: previousData?.featureConfigs?.missedOpportunityTo?.condition,
|
|
1146
|
+
MissedOpportunityFromValue: previousData?.featureConfigs?.missedOpportunityFrom?.value,
|
|
1147
|
+
MissedOpportunityToValue: previousData?.featureConfigs?.missedOpportunityTo?.value,
|
|
1148
|
+
BouncedLimitCondition: previousData?.featureConfigs?.bouncedLimit?.condition,
|
|
1149
|
+
BouncedLimitValue: previousData?.featureConfigs?.bouncedLimit?.value,
|
|
1150
|
+
InfraAlertValue: previousData?.featureConfigs?.infraAlert?.value,
|
|
1151
|
+
InfraAlertCondition: previousData?.featureConfigs?.infraAlert?.condition,
|
|
1152
|
+
ConversionCalculations: previousData?.featureConfigs?.conversionCalculation,
|
|
1153
|
+
ExcludedArea: previousData?.featureConfigs?.isExcludedArea ==true ? 'Enable': 'Disable',
|
|
1154
|
+
PasserBydata: previousData?.featureConfigs?.isPasserByData ==true ? 'Enable': 'Disable',
|
|
1155
|
+
NormalizedDataDuringDowntime: previousData?.featureConfigs?.isNormalized ==true ? 'Enable': 'Disable',
|
|
1156
|
+
Billing: previousData?.featureConfigs?.isbillingDisabled ==true ? 'Enable': 'Disable',
|
|
1157
|
+
CameraBlurring: previousData?.featureConfigs?.isCameraDisabled ==true ? 'Enable': 'Disable',
|
|
1158
|
+
FootfallDirectory: previousData?.featureConfigs?.isFootfallDirectory ==true ? 'Enable': 'Disable',
|
|
1159
|
+
NOBStatus: previousData?.featureConfigs?.isNOB ==true ? 'Enable': 'Disable',
|
|
1160
|
+
EnableAnalyze: previousData?.featureConfigs?.isNewDashboard ==true ? 'Enable': 'Disable',
|
|
1161
|
+
Traffic: previousData?.featureConfigs?.isNewTraffic==true ? 'Enable': 'Disable',
|
|
1162
|
+
Zone: previousData?.featureConfigs?.isNewZone ==true ? 'Enable': 'Disable',
|
|
1163
|
+
Zonev2: previousData?.featureConfigs?.isNewZoneV2 ==true ? 'Enable': 'Disable',
|
|
1164
|
+
Reports: previousData?.featureConfigs?.isNewReports ==true ? 'Enable': 'Disable',
|
|
1165
|
+
Trax: previousData?.featureConfigs?.isTrax ==true ? 'Enable': 'Disable',
|
|
1166
|
+
StreamType: previousData?.featureConfigs?.streamBy =='Edge' ? 'Edge App': 'RTSP',
|
|
1167
|
+
FootfallDirectoryOnlyAudit: previousData?.featureConfigs?.isFootfallDirectoryAudit ==true ? 'Enable': 'Disable',
|
|
1168
|
+
FootfallDirectoryOnlyFew: previousData?.featureConfigs?.isFootfallDirectoryLimit ==true ? 'Enable': 'Disable',
|
|
1169
|
+
|
|
1170
|
+
};
|
|
989
1171
|
|
|
1172
|
+
// Map and rename keys from current client info for UI display and logging
|
|
1173
|
+
const newData ={
|
|
1174
|
+
StoreOpenTime: postData?.featureConfigs?.open,
|
|
1175
|
+
StoreCloseTime: postData?.featureConfigs?.close,
|
|
1176
|
+
ConversionCalculations: postData?.featureConfigs?.conversionCalculation,
|
|
1177
|
+
MissedOpportunityCalculation: postData?.featureConfigs?.missedOpportunityCalculation,
|
|
1178
|
+
PotentialCalculations: postData?.featureConfigs?.billableCalculation,
|
|
1179
|
+
ConversionCondition: postData?.featureConfigs?.conversion.condition,
|
|
1180
|
+
ConversionValue: postData?.featureConfigs?.conversion.value,
|
|
1181
|
+
MissedOpportunityFromCondition: postData?.featureConfigs?.missedOpportunityFrom?.condition,
|
|
1182
|
+
MissedOpportunityToCondition: postData?.featureConfigs?.missedOpportunityTo?.condition,
|
|
1183
|
+
MissedOpportunityFromValue: postData?.featureConfigs?.missedOpportunityFrom?.value,
|
|
1184
|
+
MissedOpportunityToValue: postData?.featureConfigs?.missedOpportunityTo?.value,
|
|
1185
|
+
BouncedLimitCondition: postData?.featureConfigs?.bouncedLimit?.condition,
|
|
1186
|
+
BouncedLimitValue: postData?.featureConfigs?.bouncedLimit?.value,
|
|
1187
|
+
InfraAlertValue: postData?.featureConfigs?.infraAlert?.value,
|
|
1188
|
+
InfraAlertCondition: postData?.featureConfigs?.infraAlert?.condition,
|
|
1189
|
+
ConversionCalculations: postData?.featureConfigs?.conversionCalculation,
|
|
1190
|
+
ExcludedArea: postData?.featureConfigs?.isExcludedArea ==true ? 'Enable': 'Disable',
|
|
1191
|
+
PasserBydata: postData?.featureConfigs?.isPasserByData ==true ? 'Enable': 'Disable',
|
|
1192
|
+
NormalizedDataDuringDowntime: postData?.featureConfigs?.isNormalized ==true ? 'Enable': 'Disable',
|
|
1193
|
+
Billing: postData?.featureConfigs?.isbillingDisabled ==true ? 'Enable': 'Disable',
|
|
1194
|
+
CameraBlurring: postData?.featureConfigs?.isCameraDisabled ==true ? 'Enable': 'Disable',
|
|
1195
|
+
FootfallDirectory: postData?.featureConfigs?.isFootfallDirectory ==true ? 'Enable': 'Disable',
|
|
1196
|
+
NOBStatus: postData?.featureConfigs?.isNOB ==true ? 'Enable': 'Disable',
|
|
1197
|
+
EnableAnalyze: postData?.featureConfigs?.isNewDashboard ==true ? 'Enable': 'Disable',
|
|
1198
|
+
Traffic: postData?.featureConfigs?.isNewTraffic==true ? 'Enable': 'Disable',
|
|
1199
|
+
Zone: postData?.featureConfigs?.isNewZone ==true ? 'Enable': 'Disable',
|
|
1200
|
+
Zonev2: postData?.featureConfigs?.isNewZoneV2 ==true ? 'Enable': 'Disable',
|
|
1201
|
+
Reports: postData?.featureConfigs?.isNewReports ==true ? 'Enable': 'Disable',
|
|
1202
|
+
Trax: postData?.featureConfigs?.isTrax ==true ? 'Enable': 'Disable',
|
|
1203
|
+
StreamType: postData?.featureConfigs?.streamBy =='Edge' ? 'Edge App': 'RTSP',
|
|
1204
|
+
FootfallDirectoryOnlyAudit: postData?.featureConfigs?.isFootfallDirectoryAudit ==true ? 'Enable': 'Disable',
|
|
1205
|
+
FootfallDirectoryOnlyFew: postData?.featureConfigs?.isFootfallDirectoryLimit ==true ? 'Enable': 'Disable',
|
|
990
1206
|
|
|
1207
|
+
};
|
|
1208
|
+
|
|
1209
|
+
// Prepare activity log object with all relevant details for OpenSearch logging
|
|
991
1210
|
const logObj = {
|
|
992
|
-
clientId: req.params?.id,
|
|
993
|
-
userName: user?.userName,
|
|
994
|
-
email: user?.email,
|
|
995
|
-
date: new Date(),
|
|
996
|
-
logType: 'configuration',
|
|
997
|
-
logSubType: 'featureConfig',
|
|
998
|
-
changes: updateKeys,
|
|
999
|
-
eventType: 'update',
|
|
1000
|
-
showTo: [ 'client', 'tango' ],
|
|
1211
|
+
clientId: req.params?.id, // ID of the client whose data was updated
|
|
1212
|
+
userName: user?.userName, // Name of the user performing the update
|
|
1213
|
+
email: user?.email, // Email of the user performing the update
|
|
1214
|
+
date: new Date(), // Timestamp of the update event
|
|
1215
|
+
logType: 'configuration', // Type of log (e.g., related to brand details)
|
|
1216
|
+
logSubType: Object.keys( inputData ).some( ( key ) => keysArray.includes( key ) ) ? 'dashboardConfig' : 'featureConfig', // Subtype for more specific categorization
|
|
1217
|
+
changes: updateKeys, // List of fields that were updated.these will shown in the UI as part of activity log
|
|
1218
|
+
eventType: 'update', // Type of event (update operation)
|
|
1219
|
+
showTo: [ 'client', 'tango' ], // Visibility of the log (who can see this log)
|
|
1220
|
+
previous: previousData.featureConfigs, // Previous (old) client information before update based on DB keys (for internal reference and comparison).
|
|
1221
|
+
current: postData.featureConfigs, // Current (new) client information after update based on DB keys (for internal reference and comparison).
|
|
1222
|
+
oldData: oldData, // Previous (old) client information before update (used for showing detailed changes in the UI).
|
|
1223
|
+
newData: newData, // Current (new) client information after update (used for showing detailed changes in the UI).
|
|
1001
1224
|
};
|
|
1225
|
+
|
|
1226
|
+
// Insert activity log into OpenSearch if there are fields that were updated
|
|
1002
1227
|
if ( updateKeys.length ) {
|
|
1003
|
-
await insertOpenSearchData( openSearch.activityLog, logObj );
|
|
1228
|
+
await insertOpenSearchData( openSearch.activityLog, logObj ); // Insert activity log
|
|
1004
1229
|
}
|
|
1005
1230
|
|
|
1006
1231
|
if ( updateAck ) {
|
|
@@ -1016,6 +1241,18 @@ export async function updateFeatureConfiguration( req, res ) {
|
|
|
1016
1241
|
export async function domainDetailsConfiguration( req, res ) {
|
|
1017
1242
|
try {
|
|
1018
1243
|
const openSearch = JSON.parse( process.env.OPENSEARCH );
|
|
1244
|
+
|
|
1245
|
+
// Get updated client domain configuration before the update operation (fetch selected fields only)
|
|
1246
|
+
const getPreData = await findOneClient(
|
|
1247
|
+
{ clientId: req.params?.id }, // filter by clientId
|
|
1248
|
+
{
|
|
1249
|
+
domainName: '$domainConfig.ssoLogin.domainName',
|
|
1250
|
+
isEnable: '$domainConfig.ssoLogin.isEnable',
|
|
1251
|
+
ipWhitelist: '$domainConfig.ipWhitelisting.enableWhitelisting',
|
|
1252
|
+
WhitelistedIps: '$domainConfig.ipWhitelisting.allowedIps',
|
|
1253
|
+
TwoFactorAuthentication: '$domainConfig.enableOtp',
|
|
1254
|
+
},
|
|
1255
|
+
);
|
|
1019
1256
|
const updateAck = await domainDetailsConfigurationUpdate( {
|
|
1020
1257
|
clientId: req.params?.id, domainName: req.body?.domainName, isEnable: req.body?.isEnable,
|
|
1021
1258
|
enableWhitelisting: req.body?.enableWhitelisting, allowedIps: req.body?.allowedIps, enableOtp: req.body?.enableOtp,
|
|
@@ -1023,30 +1260,66 @@ export async function domainDetailsConfiguration( req, res ) {
|
|
|
1023
1260
|
|
|
1024
1261
|
let updateKeys = [];
|
|
1025
1262
|
|
|
1026
|
-
|
|
1263
|
+
// Check if request body has any fields to update
|
|
1027
1264
|
if ( Object.keys( req.body ).length > 0 ) {
|
|
1028
1265
|
Object.keys( req.body ).forEach( ( element ) => {
|
|
1029
1266
|
updateKeys.push( camelCaseToWords( element ) );
|
|
1030
1267
|
} );
|
|
1031
1268
|
}
|
|
1032
1269
|
|
|
1033
|
-
|
|
1270
|
+
// Get updated client domain configuration after the update operation (fetch selected fields only)
|
|
1271
|
+
const getPostData = await findOneClient(
|
|
1272
|
+
{ clientId: req.params?.id }, // Filter by clientId
|
|
1273
|
+
{
|
|
1274
|
+
domainName: '$domainConfig.ssoLogin.domainName',
|
|
1275
|
+
isEnable: '$domainConfig.ssoLogin.isEnable',
|
|
1276
|
+
ipWhitelist: '$domainConfig.ipWhitelisting.enableWhitelisting',
|
|
1277
|
+
WhitelistedIps: '$domainConfig.ipWhitelisting.allowedIps',
|
|
1278
|
+
TwoFactorAuthentication: '$domainConfig.enableOtp',
|
|
1279
|
+
},
|
|
1280
|
+
);
|
|
1281
|
+
|
|
1034
1282
|
|
|
1283
|
+
// Map and rename keys from previous client info for UI display and logging
|
|
1284
|
+
const oldData = {
|
|
1285
|
+
DomainName: getPreData?.domainConfig?.ssoLogin?.domainName,
|
|
1286
|
+
IsEnable: getPreData?.domainConfig?.ssoLogin?.isEnable ==true ? 'Enable': 'Disable',
|
|
1287
|
+
IPWhitelist: getPreData?.domainConfig?.ipWhitelisting?.enableWhitelisting ==true ? 'Enable': 'Disable',
|
|
1288
|
+
WhitelistedIps: ( getPreData?.domainConfig?.ipWhitelisting?.allowedIps ).join( ', ' ),
|
|
1289
|
+
TwoFactorAuthentication: getPreData?.domainConfig?.enableOtp ==true ? 'Enable': 'Disable',
|
|
1290
|
+
|
|
1291
|
+
};
|
|
1035
1292
|
|
|
1293
|
+
// Map and rename keys from current client info for UI display and logging
|
|
1294
|
+
const newData ={
|
|
1295
|
+
DomainName: getPostData?.domainConfig?.ssoLogin?.domainName,
|
|
1296
|
+
IsEnable: getPostData?.domainConfig?.ssoLogin?.isEnable ==true ? 'Enable': 'Disable',
|
|
1297
|
+
IPWhitelist: getPostData?.domainConfig?.ipWhitelisting?.enableWhitelisting ==true ? 'Enable': 'Disable',
|
|
1298
|
+
WhitelistedIps: ( getPostData?.domainConfig?.ipWhitelisting?.allowedIps ).join( ', ' ),
|
|
1299
|
+
TwoFactorAuthentication: getPostData?.domainConfig?.enableOtp ==true ? 'Enable': 'Disable',
|
|
1300
|
+
};
|
|
1301
|
+
|
|
1302
|
+
|
|
1303
|
+
// Prepare activity log object with all relevant details for OpenSearch logging
|
|
1036
1304
|
const logObj = {
|
|
1037
|
-
clientId: req.params?.id,
|
|
1038
|
-
userName: user?.userName,
|
|
1039
|
-
email: user?.email,
|
|
1040
|
-
date: new Date(),
|
|
1041
|
-
logType: 'configuration',
|
|
1042
|
-
logSubType: 'domainDetails',
|
|
1043
|
-
changes: updateKeys,
|
|
1044
|
-
eventType: 'update',
|
|
1045
|
-
showTo: [ 'client', 'tango' ],
|
|
1305
|
+
clientId: req.params?.id, // ID of the client whose data was updated
|
|
1306
|
+
userName: req?.user?.userName, // Name of the user performing the update
|
|
1307
|
+
email: req?.user?.email, // Email of the user performing the update
|
|
1308
|
+
date: new Date(), // Timestamp of the update event
|
|
1309
|
+
logType: 'configuration', // Type of log (e.g., related to brand details)
|
|
1310
|
+
logSubType: 'domainDetails', // Subtype for more specific categorization
|
|
1311
|
+
changes: updateKeys, // List of fields that were updated.these will shown in the UI as part of activity log
|
|
1312
|
+
eventType: 'update', // Type of event (update operation)
|
|
1313
|
+
showTo: [ 'client', 'tango' ], // Visibility of the log (who can see this log)
|
|
1314
|
+
previous: getPreData, // Previous (old) client information before update based on DB keys (for internal reference and comparison).
|
|
1315
|
+
current: getPostData, // Current (new) client information after update based on DB keys (for internal reference and comparison).
|
|
1316
|
+
oldData: oldData, // Previous (old) client information before update (used for showing detailed changes in the UI).
|
|
1317
|
+
newData: newData, // Current (new) client information after update (used for showing detailed changes in the UI).
|
|
1046
1318
|
};
|
|
1047
1319
|
|
|
1320
|
+
// Insert activity log into OpenSearch if there are fields that were updated
|
|
1048
1321
|
if ( updateKeys.length ) {
|
|
1049
|
-
await insertOpenSearchData( openSearch.activityLog, logObj );
|
|
1322
|
+
await insertOpenSearchData( openSearch.activityLog, logObj ); // Insert activity log
|
|
1050
1323
|
}
|
|
1051
1324
|
|
|
1052
1325
|
if ( updateAck ) {
|
|
@@ -1148,7 +1421,6 @@ export async function updateDocuments( req, res ) {
|
|
|
1148
1421
|
|
|
1149
1422
|
const user = await getUserNameEmailById( req.userId );
|
|
1150
1423
|
|
|
1151
|
-
|
|
1152
1424
|
const logObj = {
|
|
1153
1425
|
clientId: req.params?.id,
|
|
1154
1426
|
userName: user?.userName,
|
|
@@ -1210,14 +1482,29 @@ export async function auditConfiguration( req, res ) {
|
|
|
1210
1482
|
auditConfigs: 1, _id: 0,
|
|
1211
1483
|
};
|
|
1212
1484
|
const previousClient = await findOneClient( query, fields );
|
|
1485
|
+
previousClient.auditConfigs.ratio = previousClient?.auditConfigs?.ratio? ( previousClient.auditConfigs.ratio )*100 : null;
|
|
1213
1486
|
const record = {
|
|
1214
1487
|
'auditConfigs.count': inputData.count,
|
|
1215
1488
|
'auditConfigs.audit': inputData.audit,
|
|
1216
1489
|
'auditConfigs.ratio': Number( normalizeNumber( inputData.ratio, 0, 100 ) ),
|
|
1217
1490
|
};
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1491
|
+
await updateOneClient( query, record );
|
|
1492
|
+
|
|
1493
|
+
|
|
1494
|
+
// Map and rename keys from previous client info for UI display and logging
|
|
1495
|
+
const oldData = {
|
|
1496
|
+
AuditStatus: inputData?.audit ==true ? 'Enable': 'Disable',
|
|
1497
|
+
MappingPercentage: inputData?.ratio,
|
|
1498
|
+
AuditCount: inputData?.count,
|
|
1499
|
+
|
|
1500
|
+
};
|
|
1501
|
+
|
|
1502
|
+
// Map and rename keys from current client info for UI display and logging
|
|
1503
|
+
const newData ={
|
|
1504
|
+
AuditStatus: previousClient.auditConfigs?.audit ==true ? 'Enable': 'Disable',
|
|
1505
|
+
MappingPercentage: previousClient.auditConfigs?.ratio,
|
|
1506
|
+
AuditCount: previousClient.auditConfigs?.count,
|
|
1507
|
+
};
|
|
1221
1508
|
const logObj = {
|
|
1222
1509
|
clientId: req.params?.id,
|
|
1223
1510
|
userName: req.user?.userName,
|
|
@@ -1228,13 +1515,15 @@ export async function auditConfiguration( req, res ) {
|
|
|
1228
1515
|
eventType: 'update',
|
|
1229
1516
|
showTo: [ 'tango' ],
|
|
1230
1517
|
changes: [ `Audit config for client id ${req.params?.id}` ],
|
|
1231
|
-
previous: previousClient,
|
|
1518
|
+
previous: previousClient.auditConfigs,
|
|
1232
1519
|
current: {
|
|
1233
1520
|
clientId: req.params?.id,
|
|
1234
1521
|
count: inputData.count,
|
|
1235
1522
|
audit: inputData.audit,
|
|
1236
|
-
ratio:
|
|
1523
|
+
ratio: inputData.ratio,
|
|
1237
1524
|
},
|
|
1525
|
+
oldData: oldData,
|
|
1526
|
+
newData: newData,
|
|
1238
1527
|
};
|
|
1239
1528
|
|
|
1240
1529
|
await insertOpenSearchData( openSearch.activityLog, logObj );
|
|
@@ -1277,17 +1566,6 @@ export async function clientList( req, res ) {
|
|
|
1277
1566
|
$match: {
|
|
1278
1567
|
userEmail: { $eq: req?.user?.email },
|
|
1279
1568
|
userType: 'tango',
|
|
1280
|
-
// $expr: {
|
|
1281
|
-
// $cond: {
|
|
1282
|
-
// if: {
|
|
1283
|
-
// $and: [
|
|
1284
|
-
// { $eq: [ '$tangoUserType', 'csm' ] },
|
|
1285
|
-
// ],
|
|
1286
|
-
// },
|
|
1287
|
-
// then: { $eq: [ '$isClientApproved', true ] },
|
|
1288
|
-
// else: true,
|
|
1289
|
-
// },
|
|
1290
|
-
// },
|
|
1291
1569
|
|
|
1292
1570
|
},
|
|
1293
1571
|
}, {
|
|
@@ -1603,17 +1881,6 @@ export async function clientListV1( req, res ) {
|
|
|
1603
1881
|
$match: {
|
|
1604
1882
|
userEmail: { $eq: req?.user?.email },
|
|
1605
1883
|
userType: 'tango',
|
|
1606
|
-
// $expr: {
|
|
1607
|
-
// $cond: {
|
|
1608
|
-
// if: {
|
|
1609
|
-
// $and: [
|
|
1610
|
-
// { $eq: [ '$tangoUserType', 'csm' ] },
|
|
1611
|
-
// ],
|
|
1612
|
-
// },
|
|
1613
|
-
// then: { $eq: [ '$isClientApproved', true ] },
|
|
1614
|
-
// else: true,
|
|
1615
|
-
// },
|
|
1616
|
-
// },
|
|
1617
1884
|
|
|
1618
1885
|
},
|
|
1619
1886
|
},
|
|
@@ -2009,9 +2276,37 @@ export async function detailedClientCount( req, res ) {
|
|
|
2009
2276
|
}
|
|
2010
2277
|
}
|
|
2011
2278
|
|
|
2012
|
-
export async function
|
|
2279
|
+
export async function getActivityLogs1( req, res ) {
|
|
2013
2280
|
try {
|
|
2281
|
+
const inputData = req.body;
|
|
2014
2282
|
const openSearch = JSON.parse( process.env.OPENSEARCH );
|
|
2283
|
+
const clientQuery =[
|
|
2284
|
+
{
|
|
2285
|
+
$match: {
|
|
2286
|
+
$and: [
|
|
2287
|
+
{
|
|
2288
|
+
clientId: { $in: inputData },
|
|
2289
|
+
},
|
|
2290
|
+
],
|
|
2291
|
+
},
|
|
2292
|
+
},
|
|
2293
|
+
{
|
|
2294
|
+
$group: {
|
|
2295
|
+
_id: null,
|
|
2296
|
+
clientName: { $push: '$clientName' },
|
|
2297
|
+
},
|
|
2298
|
+
},
|
|
2299
|
+
{
|
|
2300
|
+
$project: {
|
|
2301
|
+
_id: 0,
|
|
2302
|
+
clientName: 1,
|
|
2303
|
+
},
|
|
2304
|
+
},
|
|
2305
|
+
];
|
|
2306
|
+
const getClientName = await aggregateClient( clientQuery );
|
|
2307
|
+
if ( getClientName?.length == 0 || getClientName[0]?.clientName?.length ===0 ) {
|
|
2308
|
+
return res.sendError( 'No Data Found', 204 );
|
|
2309
|
+
}
|
|
2015
2310
|
const query = {
|
|
2016
2311
|
'_source': [
|
|
2017
2312
|
'userId', 'userName', 'email', 'date', 'logType', 'logSubType',
|
|
@@ -2019,13 +2314,27 @@ export async function getActivityLogs( req, res ) {
|
|
|
2019
2314
|
],
|
|
2020
2315
|
'query': {
|
|
2021
2316
|
'bool': {
|
|
2022
|
-
'must': [
|
|
2317
|
+
// 'must': [
|
|
2318
|
+
// {
|
|
2319
|
+
// 'terms': {
|
|
2320
|
+
// 'clientId.keyword': [ req.body.clientId ],
|
|
2321
|
+
// },
|
|
2322
|
+
// },
|
|
2323
|
+
// ],
|
|
2324
|
+
|
|
2325
|
+
'should': [
|
|
2326
|
+
{
|
|
2327
|
+
'terms': {
|
|
2328
|
+
'clientId.keyword': [ inputData.clientId ],
|
|
2329
|
+
},
|
|
2330
|
+
},
|
|
2023
2331
|
{
|
|
2024
2332
|
'terms': {
|
|
2025
|
-
'
|
|
2333
|
+
'clientName.keyword': [ getClientName[0].clientName ], // Add clientName condition
|
|
2026
2334
|
},
|
|
2027
2335
|
},
|
|
2028
2336
|
],
|
|
2337
|
+
'minimum_should_match': 1, // Ensures at least one condition must match
|
|
2029
2338
|
},
|
|
2030
2339
|
},
|
|
2031
2340
|
'from': ( req.body.offset - 1 ) * req.body.limit,
|
|
@@ -2072,30 +2381,22 @@ export async function getActivityLogs( req, res ) {
|
|
|
2072
2381
|
|
|
2073
2382
|
const hits = logs?.body?.hits?.hits;
|
|
2074
2383
|
const totalDocuments = logs?.body?.hits?.total?.value;
|
|
2384
|
+
|
|
2075
2385
|
let temp = [];
|
|
2076
2386
|
if ( totalDocuments ) {
|
|
2077
2387
|
hits.map( ( hit, i ) => {
|
|
2078
|
-
|
|
2388
|
+
let respo ={};
|
|
2389
|
+
hit._source.logSubType = hit._source.logSubType === 'documentUpload'? 'documentsUpload': hit._source.logSubType === 'domainDetails'? 'securityFeatures': hit?._source?.logSubType;
|
|
2079
2390
|
if ( ( ( hit?._source?.eventType ).match( /update/ ) || ( hit?._source?.eventType ).match( /edit/ ) )&& hit?._source?.previous ) {
|
|
2080
|
-
const previous =
|
|
2081
|
-
const current=
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
const diff = Object.entries( current )
|
|
2090
|
-
.reduce( ( acc, [ key, value ] ) => {
|
|
2091
|
-
if ( value !== previous[key] & typeof previous[key] === 'string' ) {
|
|
2092
|
-
acc[key] = { previous: previous[key], current: value };
|
|
2093
|
-
}
|
|
2094
|
-
|
|
2095
|
-
return acc;
|
|
2096
|
-
}, {} );
|
|
2097
|
-
logger.info( { diff: diff } );
|
|
2098
|
-
temp[i].updatedValue = diff;
|
|
2391
|
+
const previous = hit?._source?.previous;
|
|
2392
|
+
const current=hit?._source?.current;
|
|
2393
|
+
const logType =hit?._source?.logType;
|
|
2394
|
+
|
|
2395
|
+
const logSubType =hit?._source?.logSubType;
|
|
2396
|
+
respo = findDifferences1( previous, current, logType, logSubType );
|
|
2397
|
+
hit._source.updatedValue = respo;
|
|
2398
|
+
temp.push( hit?._source );
|
|
2399
|
+
hit._source.changes =logSubType === 'ticketConfig'? Object.keys( respo ).map( ( item ) => item ) : hit._source.changes;
|
|
2099
2400
|
} else {
|
|
2100
2401
|
temp.push( hit?._source );
|
|
2101
2402
|
}
|
|
@@ -2110,25 +2411,284 @@ export async function getActivityLogs( req, res ) {
|
|
|
2110
2411
|
return res.sendError( 'Internal Server Error', 500 );
|
|
2111
2412
|
}
|
|
2112
2413
|
}
|
|
2113
|
-
function removeIndexedKeysAndFlatten( obj ) {
|
|
2114
|
-
const result = {};
|
|
2115
2414
|
|
|
2116
|
-
for ( const [ key, value ] of Object.entries( obj ) ) {
|
|
2117
|
-
// Skip numeric keys and preserve arrays intact
|
|
2118
|
-
if ( /^\d+$/.test( key ) ) continue;
|
|
2119
2415
|
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2416
|
+
function findDifferences1( previous, current, logType, logSubType, path = '' ) {
|
|
2417
|
+
const dbKeys = JSON.parse( process.env.DB_KEYS );
|
|
2418
|
+
const ignoredKeys = new Set( [
|
|
2419
|
+
'_id', 'updatedAt', 'createdAt', 'password', 'clientId',
|
|
2420
|
+
'storeId', 'refreshToken', 'employeeId', 'fcmToken', 'permission', 'updateFeatureConfig',
|
|
2421
|
+
] );
|
|
2422
|
+
const documents = dbKeys.DOCUMENTS;
|
|
2423
|
+
// Get correct key mapping based on logType
|
|
2424
|
+
const keyMapping = logType == 'stores' ?documents.stores: logType == 'users' ?documents.users :logSubType=='reportConfig'?documents.reports: logType=='brandInfo'?documents.client:documents.client;
|
|
2425
|
+
|
|
2426
|
+
|
|
2427
|
+
let differences = {};
|
|
2428
|
+
|
|
2429
|
+
for ( const key in current ) {
|
|
2430
|
+
if ( !Object.prototype.hasOwnProperty.call( current, key ) || ignoredKeys.has( key ) ) continue;
|
|
2431
|
+
|
|
2432
|
+
const prevValue = previous[key];
|
|
2433
|
+
const currValue = current[key];
|
|
2434
|
+
|
|
2435
|
+
if ( typeof prevValue === 'object' && typeof currValue === 'object' && prevValue !== null && currValue !== null ) {
|
|
2436
|
+
if ( logSubType!== 'userUpdated' ) {
|
|
2437
|
+
if ( key == 'spocDetails' ) {
|
|
2438
|
+
if ( _.isEqual( prevValue, currValue ) ) {
|
|
2439
|
+
continue;
|
|
2440
|
+
} else {
|
|
2441
|
+
let result = compareArrayObjects( prevValue, currValue );
|
|
2442
|
+
differences = { ...differences, ...result };
|
|
2443
|
+
}
|
|
2444
|
+
} else if ( Array.isArray( prevValue ) && prevValue.every( ( item ) => typeof item === 'string' ) ||Array.isArray( currValue ) && currValue.every( ( item ) => typeof item === 'string' ) ) {
|
|
2445
|
+
JSON.stringify( prevValue ) !== JSON.stringify( currValue )?
|
|
2446
|
+
differences[`${path}${key}`] = { previous: prevValue.length> 0 ? prevValue.join( ',' ): null, current: currValue.length > 0? currValue.join( ',' ): null } : null;
|
|
2447
|
+
|
|
2448
|
+
// differences[`${path}${key}`] = { previous: removed.length> 0 ? prevValue.join( ',' ): prevValue.join( ', ' ) :, current: added.length > 0? addedUsers.join( ', ' ) : currValue.join( ',' ) } : null;
|
|
2449
|
+
} else {
|
|
2450
|
+
const nestedDiffs = findDifferences1( prevValue, currValue, logType, logSubType, `${path}${key}.` );
|
|
2451
|
+
Object.assign( differences, nestedDiffs );
|
|
2452
|
+
}
|
|
2453
|
+
} else {
|
|
2454
|
+
const nestedDiffs = findDifferences1( prevValue, currValue, logType, logSubType, `${path}${key}.` );
|
|
2455
|
+
Object.assign( differences, nestedDiffs );
|
|
2456
|
+
}
|
|
2457
|
+
} else if ( prevValue !== currValue ) {
|
|
2458
|
+
if (
|
|
2459
|
+
( prevValue === '' && currValue === '' ) ||
|
|
2460
|
+
( Array.isArray( prevValue ) && Array.isArray( currValue ) && prevValue.length === 0 && currValue.length === 0 )
|
|
2461
|
+
) {
|
|
2462
|
+
continue;
|
|
2463
|
+
}
|
|
2464
|
+
differences[`${path}${key}`] = { previous: prevValue, current: currValue };
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
|
|
2468
|
+
// **Transform & Filter Differences**
|
|
2469
|
+
let updatedDifferences = {};
|
|
2470
|
+
Object.keys( differences ).forEach( ( key ) => {
|
|
2471
|
+
let newKey = key.replace( /spocDetails\.\d+\./, 'spocDetails.' ).replace( /WhitelistedIps\.\d+/, 'Whitelisted Ips' );
|
|
2472
|
+
let diff = differences[key];
|
|
2473
|
+
if ( newKey.toLowerCase().includes( 'isactive' ) ) {
|
|
2474
|
+
diff = {
|
|
2475
|
+
previous: diff.previous ? 'Active' : 'Deactive',
|
|
2476
|
+
current: diff.current ? 'Active' : 'Deactive',
|
|
2477
|
+
};
|
|
2478
|
+
}
|
|
2479
|
+
|
|
2480
|
+
const userFriendlyKey = getUserFriendlyKey( newKey, keyMapping );
|
|
2481
|
+
if ( userFriendlyKey ) {
|
|
2482
|
+
newKey = userFriendlyKey;
|
|
2483
|
+
}
|
|
2484
|
+
const binaryKeys = [ 'Two Factor Authentication', 'Mat Enabled', 'Audit Status', 'Infra Email Alert', 'Ip Whitelist', 'Excluded Area', 'Passer-by data', 'Normalized data during downtime', 'Billing', 'Camera Blurring', 'Footfall Directory', 'Footfall Directory Audit', 'Footfall Directory Limit', 'NOB Status', 'Traffic', 'Trax', 'Zone V1', 'Zone V2', 'Reports', 'Analyze' ];
|
|
2485
|
+
if ( binaryKeys.includes( newKey ) ) {
|
|
2486
|
+
diff.previous = ( diff.previous == true || diff.previous == 'Enabled' ) ? 'Enabled' : 'Disabled';
|
|
2487
|
+
diff.current = ( diff.current == true || diff.current == 'Enabled' ) ? 'Enabled' : 'Disabled';
|
|
2488
|
+
}
|
|
2489
|
+
if ( newKey === 'Server Type' ) {
|
|
2490
|
+
diff.previous = ( diff.previous == true || diff.previous == 'Server' ) ? 'Server' : 'Serverless';
|
|
2491
|
+
diff.current = ( diff.current == true || diff.current == 'Server' ) ? 'Server' : 'Serverless';
|
|
2492
|
+
}
|
|
2493
|
+
|
|
2494
|
+
if ( newKey === 'Stream Type' ) {
|
|
2495
|
+
diff.previous = ( diff.previous == 'Edge' || diff.previous == 'Edge App' ) ? 'Edge App' : 'RTSP';
|
|
2496
|
+
diff.current = ( diff.current == 'Edge' || diff.current == 'Edge App' ) ? 'Edge App' : 'RTSP';
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2499
|
+
// **Transform Roles Permission Keys**
|
|
2500
|
+
const rolesPermissionMatch = newKey.match( /rolespermission\.(\d+)\.modules\.(\d+)\.(isAdd|isEdit)/ );
|
|
2501
|
+
if ( rolesPermissionMatch ) {
|
|
2502
|
+
const [ , roleIndex, moduleIndex, action ] = rolesPermissionMatch;
|
|
2503
|
+
const role = previous.rolespermission?.[roleIndex];
|
|
2504
|
+
const module = role?.modules?.[moduleIndex];
|
|
2505
|
+
|
|
2506
|
+
if ( module ) {
|
|
2507
|
+
newKey = `User's ${module.name} Module ${action === 'isAdd' ? 'Add' : 'Edit'}`;
|
|
2508
|
+
diff.previous = diff.previous ? 'Enabled' : 'Disabled';
|
|
2509
|
+
diff.current = diff.current ? 'Enabled' : 'Disabled';
|
|
2510
|
+
}
|
|
2511
|
+
}
|
|
2512
|
+
|
|
2513
|
+
if ( !newKey || ( diff.previous === '' && !diff.current ) ) return;
|
|
2514
|
+
|
|
2515
|
+
if (
|
|
2516
|
+
( diff.previous === '' || diff.previous === null || ( Array.isArray( diff.previous ) && diff.previous.length === 0 ) ) &&
|
|
2517
|
+
diff.current === undefined
|
|
2518
|
+
) {
|
|
2519
|
+
return;
|
|
2520
|
+
}
|
|
2521
|
+
if (
|
|
2522
|
+
( diff.current === '' || diff.current === null || ( Array.isArray( diff.current ) && diff.current.length === 0 ) ) &&
|
|
2523
|
+
diff.previous === undefined
|
|
2524
|
+
) {
|
|
2525
|
+
return;
|
|
2526
|
+
}
|
|
2527
|
+
|
|
2528
|
+
updatedDifferences[newKey] = diff;
|
|
2529
|
+
} );
|
|
2530
|
+
|
|
2531
|
+
return updatedDifferences;
|
|
2532
|
+
}
|
|
2533
|
+
|
|
2534
|
+
|
|
2535
|
+
function getUserFriendlyKey( keyPath, mapping ) {
|
|
2536
|
+
const keys = keyPath.split( '.' ); // Split the key path (e.g., storeProfile.pincode → ['storeProfile', 'pincode'])
|
|
2537
|
+
let value = mapping;
|
|
2538
|
+
|
|
2539
|
+
for ( const key of keys ) {
|
|
2540
|
+
if ( value && typeof value === 'object' && key in value ) {
|
|
2541
|
+
value = value[key]; // Traverse down the object
|
|
2124
2542
|
} else {
|
|
2125
|
-
|
|
2543
|
+
return null; // Return original if not found
|
|
2126
2544
|
}
|
|
2127
2545
|
}
|
|
2128
2546
|
|
|
2129
|
-
return
|
|
2547
|
+
return typeof value === 'string' ? value : keyPath; // Return mapped value or original key
|
|
2130
2548
|
}
|
|
2131
2549
|
|
|
2550
|
+
export async function getActivityLogs( req, res ) {
|
|
2551
|
+
try {
|
|
2552
|
+
const inputData = req.body;
|
|
2553
|
+
const openSearch = JSON.parse( process.env.OPENSEARCH );
|
|
2554
|
+
const clientQuery =[
|
|
2555
|
+
{
|
|
2556
|
+
$match: {
|
|
2557
|
+
$and: [
|
|
2558
|
+
{
|
|
2559
|
+
clientId: { $eq: inputData.clientId },
|
|
2560
|
+
},
|
|
2561
|
+
],
|
|
2562
|
+
},
|
|
2563
|
+
},
|
|
2564
|
+
{
|
|
2565
|
+
$group: {
|
|
2566
|
+
_id: null,
|
|
2567
|
+
clientName: { $push: '$clientName' },
|
|
2568
|
+
},
|
|
2569
|
+
},
|
|
2570
|
+
{
|
|
2571
|
+
$project: {
|
|
2572
|
+
_id: 0,
|
|
2573
|
+
clientName: 1,
|
|
2574
|
+
},
|
|
2575
|
+
},
|
|
2576
|
+
];
|
|
2577
|
+
const getClientName = await aggregateClient( clientQuery );
|
|
2578
|
+
if ( getClientName?.length == 0 || getClientName[0]?.clientName?.length ===0 ) {
|
|
2579
|
+
return res.sendError( 'No Data Found', 204 );
|
|
2580
|
+
}
|
|
2581
|
+
const query = {
|
|
2582
|
+
'_source': [
|
|
2583
|
+
'userId', 'userName', 'email', 'date', 'logType', 'logSubType',
|
|
2584
|
+
'changes', 'eventType', 'previous', 'current', 'oldData', 'newData',
|
|
2585
|
+
],
|
|
2586
|
+
'query': {
|
|
2587
|
+
'bool': {
|
|
2588
|
+
'must': [
|
|
2589
|
+
{
|
|
2590
|
+
'terms': {
|
|
2591
|
+
'clientId.keyword': [ inputData.clientId ],
|
|
2592
|
+
},
|
|
2593
|
+
},
|
|
2594
|
+
|
|
2595
|
+
],
|
|
2596
|
+
'should': [
|
|
2597
|
+
{
|
|
2598
|
+
'terms': {
|
|
2599
|
+
'clientName.keyword': getClientName[0].clientName, // Add clientName condition
|
|
2600
|
+
},
|
|
2601
|
+
},
|
|
2602
|
+
],
|
|
2603
|
+
},
|
|
2604
|
+
},
|
|
2605
|
+
'from': ( req.body.offset - 1 ) * req.body.limit,
|
|
2606
|
+
'size': req.body.limit,
|
|
2607
|
+
'sort': [
|
|
2608
|
+
{
|
|
2609
|
+
'date': {
|
|
2610
|
+
'order': 'desc',
|
|
2611
|
+
},
|
|
2612
|
+
},
|
|
2613
|
+
],
|
|
2614
|
+
};
|
|
2615
|
+
|
|
2616
|
+
if ( req.body?.logTypeFilters?.length ) {
|
|
2617
|
+
query.query.bool.must.push(
|
|
2618
|
+
{
|
|
2619
|
+
'terms': {
|
|
2620
|
+
'logType.keyword': req.body.logTypeFilters,
|
|
2621
|
+
},
|
|
2622
|
+
},
|
|
2623
|
+
);
|
|
2624
|
+
}
|
|
2625
|
+
|
|
2626
|
+
if ( req.body?.startDate || req.body?.endDate ) {
|
|
2627
|
+
query.query.bool.must.push( {
|
|
2628
|
+
'range': {
|
|
2629
|
+
'date': {
|
|
2630
|
+
'gte': req.body?.startDate ? req.body.startDate : '',
|
|
2631
|
+
'lte': req.body?.endDate ? req.body.endDate : '',
|
|
2632
|
+
},
|
|
2633
|
+
},
|
|
2634
|
+
} );
|
|
2635
|
+
}
|
|
2636
|
+
|
|
2637
|
+
query.query.bool.must.push(
|
|
2638
|
+
{
|
|
2639
|
+
'terms': {
|
|
2640
|
+
'showTo.keyword': [ req.user.userType ],
|
|
2641
|
+
},
|
|
2642
|
+
},
|
|
2643
|
+
);
|
|
2644
|
+
|
|
2645
|
+
const logs = await getOpenSearchData( openSearch.activityLog, query );
|
|
2646
|
+
|
|
2647
|
+
const hits = logs?.body?.hits?.hits;
|
|
2648
|
+
const totalDocuments = logs?.body?.hits?.total?.value;
|
|
2649
|
+
|
|
2650
|
+
let temp = [];
|
|
2651
|
+
if ( totalDocuments ) {
|
|
2652
|
+
hits.map( ( hit, i ) => {
|
|
2653
|
+
let respo ={};
|
|
2654
|
+
hit._source.logSubType = hit._source.logSubType === 'documentUpload'? 'documentsUpload': hit._source.logSubType === 'domainDetails'? 'securityFeatures': hit?._source?.logSubType;
|
|
2655
|
+
if ( ( ( hit?._source?.eventType ).match( /update/ ) || ( hit?._source?.eventType ).match( /edit/ ) )&& hit?._source?.previous ) {
|
|
2656
|
+
const previous = hit?._source?.oldData;
|
|
2657
|
+
const current=hit?._source?.newData;
|
|
2658
|
+
respo = findDifferences( previous, current );
|
|
2659
|
+
hit._source.updatedValue = respo;
|
|
2660
|
+
temp.push( hit?._source );
|
|
2661
|
+
// hit._source.changes =logSubType === 'ticketConfig'? Object.keys( respo ).map( ( item ) => item ) : hit._source.changes;
|
|
2662
|
+
} else {
|
|
2663
|
+
temp.push( hit?._source );
|
|
2664
|
+
}
|
|
2665
|
+
},
|
|
2666
|
+
);
|
|
2667
|
+
res.sendSuccess( { data: temp, count: totalDocuments } );
|
|
2668
|
+
} else {
|
|
2669
|
+
res.sendError( 'No data found', 204 );
|
|
2670
|
+
}
|
|
2671
|
+
} catch ( error ) {
|
|
2672
|
+
logger.error( { error: error, message: req.body, function: 'getActivityLogs' } );
|
|
2673
|
+
return res.sendError( 'Internal Server Error', 500 );
|
|
2674
|
+
}
|
|
2675
|
+
}
|
|
2676
|
+
|
|
2677
|
+
function findDifferences( obj1, obj2 ) {
|
|
2678
|
+
let differences = {};
|
|
2679
|
+
|
|
2680
|
+
for ( let key in obj1 ) {
|
|
2681
|
+
if ( obj1[key] !== obj2[key] ) {
|
|
2682
|
+
differences[splitCamelCase( key )] = { previous: obj1[key], current: obj2[key] };
|
|
2683
|
+
}
|
|
2684
|
+
}
|
|
2685
|
+
|
|
2686
|
+
return differences;
|
|
2687
|
+
}
|
|
2688
|
+
|
|
2689
|
+
function splitCamelCase( text ) {
|
|
2690
|
+
return text.replace( /([a-z])([A-Z])/g, '$1 $2' );
|
|
2691
|
+
}
|
|
2132
2692
|
|
|
2133
2693
|
async function postApi( url, data ) {
|
|
2134
2694
|
const requestOptions = {
|
|
@@ -2197,3 +2757,34 @@ export async function clientCsmAssignAction( req, res ) {
|
|
|
2197
2757
|
return res.sendError( 'Internal Server Error', 500 );
|
|
2198
2758
|
}
|
|
2199
2759
|
}
|
|
2760
|
+
|
|
2761
|
+
function compareArrayObjects( prevArray, currArray ) {
|
|
2762
|
+
let changes = {};
|
|
2763
|
+
// logger.info( { prevArray: prevArray, currArray: currArray } );
|
|
2764
|
+
// Find the longest array length to avoid index mismatch
|
|
2765
|
+
let maxLength = Math.max( prevArray.length, currArray.length );
|
|
2766
|
+
|
|
2767
|
+
for ( let i = 0; i < maxLength; i++ ) {
|
|
2768
|
+
let prevObj = prevArray[i] || {}; // Default to empty object if missing
|
|
2769
|
+
let currObj = currArray[i] || {};
|
|
2770
|
+
let diff = {};
|
|
2771
|
+
|
|
2772
|
+
Object.keys( { ...prevObj, ...currObj } ).forEach( ( key ) => {
|
|
2773
|
+
if ( prevObj[key] !== currObj[key] && key !== '_id' ) {
|
|
2774
|
+
const key1 = key == 'contact'? 'Contact Number': key == 'email'? 'Email ID':key == 'name'?'Name': key == 'designation'?'Designation':key;
|
|
2775
|
+
const name = i ==0? 'Primary Spoc': `Alternate Spoc ${i+1}`;
|
|
2776
|
+
diff[`${name} ${key1}`] = {
|
|
2777
|
+
previous: prevObj[key] || 'null',
|
|
2778
|
+
current: currObj[key] || 'null',
|
|
2779
|
+
};
|
|
2780
|
+
}
|
|
2781
|
+
} );
|
|
2782
|
+
|
|
2783
|
+
if ( Object.keys( diff ).length > 0 ) {
|
|
2784
|
+
// changes.push( { index: i, changes: diff } );
|
|
2785
|
+
changes = { ...changes, ...diff };
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2788
|
+
|
|
2789
|
+
return changes;
|
|
2790
|
+
}
|
package/src/docs/client.docs.js
CHANGED
|
@@ -400,20 +400,12 @@ export const clientDocs = {
|
|
|
400
400
|
},
|
|
401
401
|
},
|
|
402
402
|
|
|
403
|
-
'/v3/client/activity-log
|
|
403
|
+
'/v3/client/activity-log': {
|
|
404
404
|
post: {
|
|
405
405
|
tags: [ 'Client' ],
|
|
406
406
|
description: 'Activity log',
|
|
407
407
|
operationId: 'activity-log',
|
|
408
|
-
parameters: [
|
|
409
|
-
in: 'path',
|
|
410
|
-
name: 'id',
|
|
411
|
-
required: true,
|
|
412
|
-
description: 'The ID of the client.',
|
|
413
|
-
schema: {
|
|
414
|
-
type: 'string',
|
|
415
|
-
},
|
|
416
|
-
} ],
|
|
408
|
+
parameters: [],
|
|
417
409
|
requestBody: {
|
|
418
410
|
content: {
|
|
419
411
|
'application/json': {
|