tango-app-api-store-builder 1.0.3-alpha → 1.0.4
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/data/Bitz_Final_Store_List_28.08.25.xlsx +0 -0
- package/data/Coastline 3.0 Tango.xlsx +0 -0
- package/data/Fixture capacity.xlsx +0 -0
- package/data/JJ_OD New Launch_Tango.xlsx +0 -0
- package/data/LKST 98 - Inventory Analysis.xlsx +0 -0
- package/data/OE_Vs_NON_OE_UPDATED.xlsx +0 -0
- package/data/Sale, Non sale stores.xlsx +0 -0
- package/data/Updated IVM New Fixture Flow-v8.xlsx +0 -0
- package/data/VM_logic.xlsx +0 -0
- package/data/euro_center_stores_tentpole.xls +0 -0
- package/data/ivmLogic.json +6058 -0
- package/data/logs.json +3 -0
- package/data/missing_stores.json +3 -0
- package/data/response.json +2119 -0
- package/index.js +7 -1
- package/package.json +15 -4
- package/src/controllers/fixtureTemplate.controller.js +1767 -0
- package/src/controllers/managePlano.controller.js +1986 -0
- package/src/controllers/planoLibrary.controller.js +1487 -0
- package/src/controllers/script.controller.js +14680 -0
- package/src/controllers/storeBuilder.controller.js +7353 -15
- package/src/controllers/task.controller.js +1149 -0
- package/src/dtos/validation.dtos.js +277 -1
- package/src/routes/fixtureTemplate.routes.js +30 -0
- package/src/routes/managePlano.routes.js +29 -0
- package/src/routes/planoLibrary.routes.js +42 -0
- package/src/routes/script.routes.js +44 -0
- package/src/routes/storeBuilder.routes.js +55 -5
- package/src/routes/task.routes.js +20 -0
- package/src/service/assignService.service.js +11 -0
- package/src/service/checklist.service.js +7 -0
- package/src/service/fixtureConfig.service.js +52 -0
- package/src/service/fixtureConfigDuplicate.service.js +52 -0
- package/src/service/fixtureShelf.service.js +53 -0
- package/src/service/fixtureShelfDuplicate.service.js +53 -0
- package/src/service/planoCompliance.service.js +33 -0
- package/src/service/planoDuplicateModel.service.js +41 -0
- package/src/service/planoGlobalComment.service.js +25 -0
- package/src/service/planoLibrary.service.js +45 -0
- package/src/service/planoLibraryDuplicate.service.js +45 -0
- package/src/service/planoMapping.service.js +44 -0
- package/src/service/planoMappingDuplicate.service.js +44 -0
- package/src/service/planoProduct.service.js +42 -0
- package/src/service/planoProductDuplicate.service.js +42 -0
- package/src/service/planoQrConversionRequest.service.js +32 -0
- package/src/service/planoRevision.service.js +15 -0
- package/src/service/planoStaticData.service.js +11 -0
- package/src/service/planoTask.service.js +39 -0
- package/src/service/planoVm.service.js +49 -0
- package/src/service/planoVmDuplicate.service.js +49 -0
- package/src/service/planogram.service.js +8 -0
- package/src/service/planoproductCategory.service.js +47 -0
- package/src/service/processedTaskservice.js +29 -0
- package/src/service/processedchecklist.service.js +17 -0
- package/src/service/storeBuilder.service.js +20 -0
- package/src/service/storeBuilderDuplicate.service.js +53 -0
- package/src/service/storeFixture.service.js +83 -0
- package/src/service/storeFixtureDuplicate.service.js +69 -0
- package/src/service/task.service.js +6 -0
- package/src/service/templateLog.service.js +10 -0
- package/src/service/user.service.js +14 -0
- package/src/service/vmType.service.js +33 -0
|
@@ -0,0 +1,1767 @@
|
|
|
1
|
+
import { logger, download } from 'tango-app-api-middleware';
|
|
2
|
+
import * as fixtureConfigService from '../service/fixtureConfig.service.js';
|
|
3
|
+
import * as fixtureLibService from '../service/planoLibrary.service.js';
|
|
4
|
+
import * as storeFixtureService from '../service/storeFixture.service.js';
|
|
5
|
+
import * as planoService from '../service/planogram.service.js';
|
|
6
|
+
import * as storeService from '../service/store.service.js';
|
|
7
|
+
import * as processedTaskService from '../service/processedTaskservice.js';
|
|
8
|
+
import * as fixtureShelfService from '../service/fixtureShelf.service.js';
|
|
9
|
+
import * as vmService from '../service/planoVm.service.js';
|
|
10
|
+
import * as templateLogService from '../service/templateLog.service.js';
|
|
11
|
+
import * as storeLayoutService from '../service/storeBuilder.service.js';
|
|
12
|
+
import { createTask } from './task.controller.js';
|
|
13
|
+
import mongoose from 'mongoose';
|
|
14
|
+
import dayjs from 'dayjs';
|
|
15
|
+
const ObjectId = mongoose.Types.ObjectId;
|
|
16
|
+
import customParseFormat from 'dayjs/plugin/customParseFormat.js';
|
|
17
|
+
dayjs.extend( customParseFormat );
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
export async function createTemplate( req, res ) {
|
|
21
|
+
try {
|
|
22
|
+
let inputData = req.body;
|
|
23
|
+
const templateType = inputData?.templateType ?? 'sub';
|
|
24
|
+
let getLibDetails = await fixtureLibService.findOne( { _id: inputData.fixtureLibraryId, clientId: inputData.clientId } );
|
|
25
|
+
if ( !getLibDetails ) {
|
|
26
|
+
return res.sendError( 'Fixture library id is wrong', 400 );
|
|
27
|
+
}
|
|
28
|
+
let templateId = await getTemplateId( getLibDetails.fixtureCategory, getLibDetails.fixtureWidth );
|
|
29
|
+
let templateData = {
|
|
30
|
+
clientId: inputData.clientId,
|
|
31
|
+
fixtureLibraryId: inputData.fixtureLibraryId,
|
|
32
|
+
fixtureName: `${templateId}-${getLibDetails.fixtureCategory}`,
|
|
33
|
+
fixtureCategory: getLibDetails.fixtureCategory,
|
|
34
|
+
fixtureType: getLibDetails.fixtureType,
|
|
35
|
+
fixtureHeight: getLibDetails.fixtureHeight,
|
|
36
|
+
fixtureLength: getLibDetails.fixtureLength,
|
|
37
|
+
fixtureWidth: getLibDetails.fixtureWidth,
|
|
38
|
+
shelfConfig: getLibDetails.shelfConfig,
|
|
39
|
+
header: getLibDetails.header,
|
|
40
|
+
footer: getLibDetails.footer,
|
|
41
|
+
isBodyEnabled: getLibDetails.isBodyEnabled,
|
|
42
|
+
fixtureCapacity: getLibDetails.fixtureCapacity,
|
|
43
|
+
fixtureStaticLength: {
|
|
44
|
+
value: 1524,
|
|
45
|
+
unit: 'mm',
|
|
46
|
+
},
|
|
47
|
+
fixtureStaticWidth: {
|
|
48
|
+
value: 1220,
|
|
49
|
+
unit: 'mm',
|
|
50
|
+
},
|
|
51
|
+
templateType: templateType,
|
|
52
|
+
templateIndex: parseInt( templateId.split( '-' )[1] ),
|
|
53
|
+
};
|
|
54
|
+
let fixtureData = await fixtureConfigService.create( templateData );
|
|
55
|
+
return res.sendSuccess( { message: 'Fixture template created successfully', fixtureData } );
|
|
56
|
+
} catch ( e ) {
|
|
57
|
+
logger.error( { functionName: 'createTemplate', error: e } );
|
|
58
|
+
return res.sendError( e, 500 );
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function getTemplateId( name, width ) {
|
|
63
|
+
let templateId = 'Template-1';
|
|
64
|
+
let fixtureTemplateData = await fixtureConfigService.sortAndFindOne( { 'fixtureCategory': name, 'fixtureWidth.unit': width.unit, 'fixtureWidth.value': width.value }, { templateIndex: 1 }, { _id: -1 } );
|
|
65
|
+
if ( fixtureTemplateData.length ) {
|
|
66
|
+
templateId = `Template-${fixtureTemplateData[0].templateIndex + 1}`;
|
|
67
|
+
}
|
|
68
|
+
return templateId;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export async function updateTemplate( req, res ) {
|
|
72
|
+
try {
|
|
73
|
+
let inputData = req.body;
|
|
74
|
+
let templateDetails = await fixtureConfigService.findOne( { _id: req.params.templateId } );
|
|
75
|
+
if ( !templateDetails ) {
|
|
76
|
+
return res.sendError( 'No data found', 204 );
|
|
77
|
+
}
|
|
78
|
+
let checkName = await fixtureConfigService.findOne( { _id: { $ne: req.params.templateId }, fixtureName: inputData.fixtureName } );
|
|
79
|
+
if ( checkName ) {
|
|
80
|
+
return res.sendError( 'Fixture name already exist', 400 );
|
|
81
|
+
}
|
|
82
|
+
let checkstoreMapped = await storeFixtureService.findOne( { fixtureConfigId: req.params.templateId } );
|
|
83
|
+
if ( checkstoreMapped ) {
|
|
84
|
+
inputData.isEdited = true;
|
|
85
|
+
} else {
|
|
86
|
+
inputData.isEdited = false;
|
|
87
|
+
}
|
|
88
|
+
await fixtureConfigService.updateOne( { _id: req.params.templateId }, inputData );
|
|
89
|
+
return res.sendSuccess( 'Fixture template details updated successfully' );
|
|
90
|
+
} catch ( e ) {
|
|
91
|
+
logger.error( { functionName: 'updateTemplate', error: e } );
|
|
92
|
+
return res.sendError( e, 500 );
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export async function deleteTemplate( req, res ) {
|
|
97
|
+
try {
|
|
98
|
+
let templateDetails = await fixtureConfigService.findOne( { _id: req.body.templateId } );
|
|
99
|
+
if ( !templateDetails ) {
|
|
100
|
+
return res.sendError( 'No data found', 204 );
|
|
101
|
+
}
|
|
102
|
+
if ( templateDetails.templateType == 'master' ) {
|
|
103
|
+
return res.sendError( `Can't delete master template`, 400 );
|
|
104
|
+
}
|
|
105
|
+
let getFixtureDetails = await storeFixtureService.find( { fixtureConfigId: req.body.templateId }, { _id: 1, planoId: 1 } );
|
|
106
|
+
if ( getFixtureDetails.length ) {
|
|
107
|
+
let planoDetails = await planoService.find( { _id: getFixtureDetails.map( ( ele ) => ele.planoId ) } );
|
|
108
|
+
return res.sendError( `Fixture template is mapped with ${planoDetails.length}`, 400 );
|
|
109
|
+
}
|
|
110
|
+
await fixtureConfigService.deleteOne( { _id: req.body.templateId } );
|
|
111
|
+
return res.sendSuccess( 'Fixture template is deleted successfully' );
|
|
112
|
+
} catch ( e ) {
|
|
113
|
+
logger.error( { functionName: 'deleteTemplate', error: e } );
|
|
114
|
+
return res.sendError( e, 500 );
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export async function duplicateTemplateOld( req, res ) {
|
|
119
|
+
try {
|
|
120
|
+
let templateDetails = await fixtureConfigService.findOne( { _id: req.body.templateId }, { createdAt: 0, updatedAt: 0 } );
|
|
121
|
+
if ( !templateDetails ) {
|
|
122
|
+
return res.sendError( 'No data found', 204 );
|
|
123
|
+
}
|
|
124
|
+
let getAllTemplate = await fixtureConfigService.findAndSort( { fixtureName: { $regex: templateDetails.fixtureName.replace( /[.*+?^${}()|[\]\\]/g, '\\$&' ), $options: 'i' } }, { fixtureName: 1 }, { fixtureName: -1 } );
|
|
125
|
+
let counter = 1;
|
|
126
|
+
let newFixtureName = templateDetails.fixtureName + ` (${counter})`;
|
|
127
|
+
if ( getAllTemplate?.length ) {
|
|
128
|
+
let fixtureNameList = getAllTemplate.map( ( ele ) => ele.fixtureName );
|
|
129
|
+
while ( fixtureNameList.includes( newFixtureName ) ) {
|
|
130
|
+
newFixtureName = templateDetails.fixtureName + ` (${counter})`;
|
|
131
|
+
counter++;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
templateDetails = templateDetails.toObject();
|
|
135
|
+
delete templateDetails._id;
|
|
136
|
+
templateDetails.fixtureName = newFixtureName;
|
|
137
|
+
templateDetails.status = 'draft';
|
|
138
|
+
let duplicateDetails = await fixtureConfigService.create( templateDetails );
|
|
139
|
+
return res.sendSuccess( { message: 'Fixture template duplicated successfully', id: duplicateDetails._id } );
|
|
140
|
+
} catch ( e ) {
|
|
141
|
+
logger.error( { functionName: 'duplicateFixture', error: e } );
|
|
142
|
+
return res.sendError( e, 500 );
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export async function getTemplateDetails( req, res ) {
|
|
147
|
+
try {
|
|
148
|
+
let templateDetails = await fixtureConfigService.findOne( { _id: req.query.templateId } );
|
|
149
|
+
if ( !templateDetails ) {
|
|
150
|
+
return res.sendError( 'No data found', 204 );
|
|
151
|
+
}
|
|
152
|
+
templateDetails = templateDetails.toObject();
|
|
153
|
+
templateDetails.vmConfig = await Promise.all( templateDetails.vmConfig.map( async ( vm ) => {
|
|
154
|
+
let vmDetails = await vmService.findOne( { _id: vm.vmId } );
|
|
155
|
+
if ( vmDetails ) {
|
|
156
|
+
vm = { ...vm, ...vmDetails.toObject() };
|
|
157
|
+
return vm;
|
|
158
|
+
}
|
|
159
|
+
} ) );
|
|
160
|
+
templateDetails.status = templateDetails.status == 'draft' ? 'draft' : 'inactive';
|
|
161
|
+
let storeFixtureDetails = await storeFixtureService.find( { fixtureConfigId: req.query.templateId } );
|
|
162
|
+
if ( storeFixtureDetails.length ) {
|
|
163
|
+
let fixtureId = storeFixtureDetails.map( ( ele ) => ele.planoId );
|
|
164
|
+
let planoDetails = await planoService.find( { _id: { $in: fixtureId } }, { status: 1 } );
|
|
165
|
+
planoDetails = planoDetails.map( ( ele ) => ele.status );
|
|
166
|
+
templateDetails.status = planoDetails.includes( 'completed' ) ? 'active' : templateDetails.status;
|
|
167
|
+
}
|
|
168
|
+
let data = {
|
|
169
|
+
...templateDetails,
|
|
170
|
+
};
|
|
171
|
+
if ( templateDetails.templateType == 'master' ) {
|
|
172
|
+
let variantCount = await fixtureConfigService.count( { masterTemplateId: templateDetails._id } );
|
|
173
|
+
data = { ...data, variantCount };
|
|
174
|
+
} else {
|
|
175
|
+
let query = [
|
|
176
|
+
{
|
|
177
|
+
$match: {
|
|
178
|
+
fixtureConfigId: new ObjectId( req.query.templateId ),
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
$group: {
|
|
183
|
+
_id: '',
|
|
184
|
+
storeId: { $addToSet: '$storeId' },
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
$project: {
|
|
189
|
+
storeCount: { $size: '$storeId' },
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
];
|
|
193
|
+
|
|
194
|
+
let templateStoreList = await storeFixtureService.aggregate( query );
|
|
195
|
+
data = { ...data, storeCount: templateStoreList?.[0]?.storeCount || 0 };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return res.sendSuccess( data );
|
|
199
|
+
} catch ( e ) {
|
|
200
|
+
logger.error( { functionName: 'getTemplateDetails', error: e } );
|
|
201
|
+
return res.sendError( e, 500 );
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export async function getTemplateList( req, res ) {
|
|
206
|
+
try {
|
|
207
|
+
let limit = req.body?.limit || 10;
|
|
208
|
+
let page = req.body?.offset || 1;
|
|
209
|
+
let skip = limit * ( page - 1 );
|
|
210
|
+
|
|
211
|
+
const matchStage = {
|
|
212
|
+
clientId: req.body.clientId,
|
|
213
|
+
...( req.body?.searchValue ?
|
|
214
|
+
{ fixtureName: { $regex: req.body.searchValue, $options: 'i' } } :
|
|
215
|
+
{} ),
|
|
216
|
+
...( req.body?.filter?.brand?.length ?
|
|
217
|
+
{
|
|
218
|
+
$or: [
|
|
219
|
+
{ 'productBrandName': { $in: req.body.filter.brand } },
|
|
220
|
+
{ 'shelfConfig.productBrandName': { $in: req.body.filter.brand } },
|
|
221
|
+
],
|
|
222
|
+
} :
|
|
223
|
+
{} ),
|
|
224
|
+
...( req.body?.filter?.category?.length ?
|
|
225
|
+
{ fixtureCategory: { $in: req.body.filter.category } } :
|
|
226
|
+
{} ),
|
|
227
|
+
...( req.body?.filter?.subCategory?.length ?
|
|
228
|
+
{ productSubCategory: { $in: req.body.subCategory.category } } :
|
|
229
|
+
{} ),
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
const query = [
|
|
233
|
+
{ $match: matchStage },
|
|
234
|
+
{
|
|
235
|
+
$lookup: {
|
|
236
|
+
from: 'storefixtures',
|
|
237
|
+
let: { templateId: '$_id' },
|
|
238
|
+
pipeline: [
|
|
239
|
+
{
|
|
240
|
+
$match: {
|
|
241
|
+
$expr: {
|
|
242
|
+
$eq: [ '$$templateId', '$fixtureConfigId' ],
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
$group: {
|
|
248
|
+
_id: null,
|
|
249
|
+
planoId: { $addToSet: '$planoId' },
|
|
250
|
+
storeList: { $addToSet: '$storeName' },
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
$project: {
|
|
255
|
+
_id: 0,
|
|
256
|
+
planoId: 1,
|
|
257
|
+
storeList: 1,
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
],
|
|
261
|
+
as: 'storeFixtureDetails',
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
$project: {
|
|
266
|
+
fixtureCategory: 1,
|
|
267
|
+
fixtureName: 1,
|
|
268
|
+
fixtureWidth: 1,
|
|
269
|
+
productBrandName: 1,
|
|
270
|
+
productCategory: 1,
|
|
271
|
+
shelfProduct: {
|
|
272
|
+
$reduce: {
|
|
273
|
+
input: '$shelfConfig',
|
|
274
|
+
initialValue: [],
|
|
275
|
+
in: {
|
|
276
|
+
$concatArrays: [
|
|
277
|
+
'$$value',
|
|
278
|
+
{ $ifNull: [ '$$this.productBrandName', [] ] },
|
|
279
|
+
],
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
shelfProductCategory: {
|
|
284
|
+
$reduce: {
|
|
285
|
+
input: '$shelfConfig',
|
|
286
|
+
initialValue: [],
|
|
287
|
+
in: {
|
|
288
|
+
$concatArrays: [
|
|
289
|
+
'$$value',
|
|
290
|
+
{ $ifNull: [ '$$this.productCategory', [] ] },
|
|
291
|
+
],
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
},
|
|
295
|
+
shelfProductSubCategory: {
|
|
296
|
+
$reduce: {
|
|
297
|
+
input: '$shelfConfig',
|
|
298
|
+
initialValue: [],
|
|
299
|
+
in: {
|
|
300
|
+
$concatArrays: [
|
|
301
|
+
'$$value',
|
|
302
|
+
{ $ifNull: [ '$$this.productSubCategory', [] ] },
|
|
303
|
+
],
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
clientId: 1,
|
|
308
|
+
productSubCategory: 1,
|
|
309
|
+
status: 1,
|
|
310
|
+
fixtureType: 1,
|
|
311
|
+
vmCapacity: { $size: '$vmConfig' },
|
|
312
|
+
productCapacity: {
|
|
313
|
+
$sum: {
|
|
314
|
+
$map: {
|
|
315
|
+
input: '$shelfConfig',
|
|
316
|
+
as: 'shelf',
|
|
317
|
+
in: '$$shelf.productPerShelf',
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
planoId: { $ifNull: [ { $arrayElemAt: [ '$storeFixtureDetails.planoId', 0 ] }, [] ] },
|
|
322
|
+
storeList: { $ifNull: [ { $arrayElemAt: [ '$storeFixtureDetails.storeList', 0 ] }, [] ] },
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
$lookup: {
|
|
327
|
+
from: 'planograms',
|
|
328
|
+
let: { planoIds: '$planoId' },
|
|
329
|
+
pipeline: [
|
|
330
|
+
{
|
|
331
|
+
$match: {
|
|
332
|
+
$expr: {
|
|
333
|
+
$in: [ '$_id', { $ifNull: [ '$$planoIds', [] ] } ],
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
$group: {
|
|
339
|
+
_id: null,
|
|
340
|
+
statusList: { $addToSet: '$status' },
|
|
341
|
+
},
|
|
342
|
+
},
|
|
343
|
+
],
|
|
344
|
+
as: 'planoStatus',
|
|
345
|
+
},
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
$project: {
|
|
349
|
+
fixtureCategory: 1,
|
|
350
|
+
fixtureName: 1,
|
|
351
|
+
fixtureWidth: 1,
|
|
352
|
+
productBrandName: { $concatArrays: [ '$productBrandName', '$shelfProduct' ] },
|
|
353
|
+
productCategory: { $concatArrays: [ '$productCategory', '$shelfProductCategory' ] },
|
|
354
|
+
clientId: 1,
|
|
355
|
+
fixtureType: 1,
|
|
356
|
+
productSubCategory: { $concatArrays: [ '$productSubCategory', '$shelfProductSubCategory' ] },
|
|
357
|
+
status: 1,
|
|
358
|
+
templateId: 1,
|
|
359
|
+
planoId: 1,
|
|
360
|
+
vmCapacity: 1,
|
|
361
|
+
productCapacity: 1,
|
|
362
|
+
storeList: 1,
|
|
363
|
+
storeCount: { $size: '$storeList' },
|
|
364
|
+
planoStatus: { $ifNull: [ { $arrayElemAt: [ '$planoStatus.statusList', 0 ] }, [] ] },
|
|
365
|
+
status: {
|
|
366
|
+
$cond: {
|
|
367
|
+
if: { $in: [ 'completed', { $ifNull: [ { $arrayElemAt: [ '$planoStatus.statusList', 0 ] }, [] ] } ] },
|
|
368
|
+
then: 'active',
|
|
369
|
+
else: {
|
|
370
|
+
$cond: {
|
|
371
|
+
if: {
|
|
372
|
+
$eq: [
|
|
373
|
+
'$status', 'draft',
|
|
374
|
+
],
|
|
375
|
+
},
|
|
376
|
+
then: 'draft',
|
|
377
|
+
else: 'inactive',
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
},
|
|
381
|
+
},
|
|
382
|
+
},
|
|
383
|
+
},
|
|
384
|
+
];
|
|
385
|
+
|
|
386
|
+
if ( req.body.filter.status.length ) {
|
|
387
|
+
query.push( {
|
|
388
|
+
$match: {
|
|
389
|
+
status: { $in: req.body.filter.status },
|
|
390
|
+
},
|
|
391
|
+
} );
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
if ( req.body?.sortColumnName && req.body?.sortBy ) {
|
|
395
|
+
query.push( {
|
|
396
|
+
$sort: {
|
|
397
|
+
[req.body.sortColumnName]: req.body.sortBy,
|
|
398
|
+
},
|
|
399
|
+
},
|
|
400
|
+
);
|
|
401
|
+
} else {
|
|
402
|
+
query.push( {
|
|
403
|
+
$sort: { _id: -1 },
|
|
404
|
+
} );
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
query.push(
|
|
408
|
+
{
|
|
409
|
+
$facet: {
|
|
410
|
+
templateData: [ { $skip: skip }, { $limit: limit } ],
|
|
411
|
+
count: [ { $count: 'total' } ],
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
);
|
|
415
|
+
let fixtureDetails = await fixtureConfigService.aggregate( query );
|
|
416
|
+
if ( !fixtureDetails[0]?.templateData.length ) {
|
|
417
|
+
return res.sendError( 'No data found', 204 );
|
|
418
|
+
}
|
|
419
|
+
if ( req.body.export ) {
|
|
420
|
+
let exportData = [];
|
|
421
|
+
fixtureDetails[0]?.templateData.forEach( ( ele ) => {
|
|
422
|
+
ele.productBrandName = [ ...new Set( ele.productBrandName.map( ( product ) => product ) ) ];
|
|
423
|
+
ele.productCategory = [ ...new Set( ele.productCategory.map( ( product ) => product ) ) ];
|
|
424
|
+
ele.productSubCategory = [ ...new Set( ele.productSubCategory.map( ( product ) => product ) ) ];
|
|
425
|
+
exportData.push( {
|
|
426
|
+
'Fixture Category': ele.fixtureCategory,
|
|
427
|
+
'Fixture Name': ele.fixtureName,
|
|
428
|
+
'Fixture Type': ele.fixtureType,
|
|
429
|
+
'Fixture Width': ele.fixtureWidth.value + ' ' +ele.fixtureWidth.unit,
|
|
430
|
+
'Product BrandName': ele.productBrandName?.toString(),
|
|
431
|
+
'Product Capacity': ele?.productCapacity,
|
|
432
|
+
'Product Category': ele?.productCategory?.toString(),
|
|
433
|
+
'Product SubCategory': ele?.productSubCategory?.toString(),
|
|
434
|
+
'Status': ele.status,
|
|
435
|
+
'Store Count': ele.storeCount,
|
|
436
|
+
'VM Capacity': ele.vmCapacity,
|
|
437
|
+
} );
|
|
438
|
+
} );
|
|
439
|
+
return download( exportData, res );
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
let result = {
|
|
443
|
+
count: fixtureDetails[0].count[0].total,
|
|
444
|
+
data: fixtureDetails[0].templateData,
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
result.data.forEach( ( ele ) => {
|
|
448
|
+
ele.productBrandName = [ ...new Set( ele.productBrandName.map( ( product ) => product ) ) ];
|
|
449
|
+
ele.productCategory = [ ...new Set( ele.productCategory.map( ( product ) => product ) ) ];
|
|
450
|
+
ele.productSubCategory = [ ...new Set( ele.productSubCategory.map( ( product ) => product ) ) ];
|
|
451
|
+
} );
|
|
452
|
+
return res.sendSuccess( result );
|
|
453
|
+
} catch ( e ) {
|
|
454
|
+
console.log( e );
|
|
455
|
+
logger.error( { functionName: 'getTemplateList', error: e } );
|
|
456
|
+
return res.sendError( e, 500 );
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
export async function updateFixtureTask( req, res ) {
|
|
461
|
+
try {
|
|
462
|
+
let storeList = req.body.storeList.map( ( ele ) => ele.toLowerCase() );
|
|
463
|
+
let query = [
|
|
464
|
+
{
|
|
465
|
+
$addFields: {
|
|
466
|
+
storeLower: { $toLower: '$storeName' },
|
|
467
|
+
},
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
$match: {
|
|
471
|
+
clientId: req.body.clientId,
|
|
472
|
+
status: 'active',
|
|
473
|
+
storeLower: { $in: storeList },
|
|
474
|
+
},
|
|
475
|
+
},
|
|
476
|
+
];
|
|
477
|
+
let storeDetails = await storeService.aggregate( query );
|
|
478
|
+
if ( !storeDetails.length ) {
|
|
479
|
+
return res.sendError( 'No date found', 204 );
|
|
480
|
+
}
|
|
481
|
+
storeList = storeDetails.map( ( ele ) => {
|
|
482
|
+
return { store: ele.storeName, email: ele?.spocDetails?.[0]?.email };
|
|
483
|
+
} );
|
|
484
|
+
let fixtureTaskStore = [];
|
|
485
|
+
let layoutTaskStore = [];
|
|
486
|
+
await Promise.all( storeList.map( async ( ele ) => {
|
|
487
|
+
let getTaskDetails = await processedTaskService.findOne( { storeName: ele.store, userEmail: ele.email, isPlano: true, date_iso: new Date( dayjs().format( 'YYYY-MM-DD' ) ), type: 'layout' } );
|
|
488
|
+
if ( getTaskDetails && getTaskDetails.planoType == 'layout' && getTaskDetails.checklistStatus == 'submit' ) {
|
|
489
|
+
fixtureTaskStore.push( ele );
|
|
490
|
+
} else {
|
|
491
|
+
layoutTaskStore.push( ele );
|
|
492
|
+
}
|
|
493
|
+
} ) );
|
|
494
|
+
let currDate = dayjs();
|
|
495
|
+
let endDate = dayjs( req.body.endDate, 'YYYY-MM-DD' );
|
|
496
|
+
let todayDate = currDate.format( 'YYYY-MM-DD' ) == endDate.format( 'YYYY-MM-DD' );
|
|
497
|
+
let data = [
|
|
498
|
+
'Fixture Verification',
|
|
499
|
+
'Layout Verification',
|
|
500
|
+
];
|
|
501
|
+
await Promise.all( data.map( async ( ele ) => {
|
|
502
|
+
req.body = {
|
|
503
|
+
clientId: req.body.clientId,
|
|
504
|
+
stores: ele.includes( 'Fixture' ) ? fixtureTaskStore : layoutTaskStore,
|
|
505
|
+
days: todayDate ? 1 : endDate.diff( currDate, 'day' ) + 2,
|
|
506
|
+
checkListName: ele,
|
|
507
|
+
geoFencing: req.body.geoFencing,
|
|
508
|
+
endTime: req.body.endTime,
|
|
509
|
+
};
|
|
510
|
+
if ( req.body.stores.length ) {
|
|
511
|
+
await createTask( req, res );
|
|
512
|
+
}
|
|
513
|
+
} ) );
|
|
514
|
+
} catch ( e ) {
|
|
515
|
+
logger.error( { functionName: 'updateFixtureTask', error: e } );
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
export async function getAllTemplates( req, res ) {
|
|
520
|
+
try {
|
|
521
|
+
if ( !req.body.clientId ) {
|
|
522
|
+
return res.sendError( 'Client Id is required', 400 );
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
const query = [
|
|
526
|
+
{
|
|
527
|
+
$match: {
|
|
528
|
+
clientId: req.body.clientId,
|
|
529
|
+
templateType: 'sub',
|
|
530
|
+
},
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
$project: {
|
|
534
|
+
'fixtureName': 1,
|
|
535
|
+
'fixtureWidth': 1,
|
|
536
|
+
'productBrandName': {
|
|
537
|
+
$cond: {
|
|
538
|
+
if: { $eq: [ '$productResolutionLevel', 'L1' ] },
|
|
539
|
+
then: '$productBrandName',
|
|
540
|
+
else: {
|
|
541
|
+
$reduce: {
|
|
542
|
+
input: {
|
|
543
|
+
$map: {
|
|
544
|
+
input: '$shelfConfig',
|
|
545
|
+
as: 'shelf',
|
|
546
|
+
in: '$$shelf.productBrandName',
|
|
547
|
+
},
|
|
548
|
+
},
|
|
549
|
+
initialValue: [],
|
|
550
|
+
in: {
|
|
551
|
+
$setUnion: [ '$$value', '$$this' ],
|
|
552
|
+
},
|
|
553
|
+
},
|
|
554
|
+
},
|
|
555
|
+
},
|
|
556
|
+
},
|
|
557
|
+
},
|
|
558
|
+
},
|
|
559
|
+
];
|
|
560
|
+
|
|
561
|
+
const fixtureTemplates = await fixtureConfigService.aggregate( query );
|
|
562
|
+
|
|
563
|
+
res.sendSuccess( fixtureTemplates );
|
|
564
|
+
} catch ( e ) {
|
|
565
|
+
logger.error( { functionName: 'getAllTemplates', error: e } );
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
export async function getFixtureTemplate( req, res ) {
|
|
570
|
+
try {
|
|
571
|
+
let fixtureTemplate = await fixtureConfigService.findOne( { _id: new mongoose.Types.ObjectId( req.query.templateId ) } );
|
|
572
|
+
|
|
573
|
+
if ( !fixtureTemplate ) {
|
|
574
|
+
return res.sendError( 'No data found', 204 );
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
const templateDoc = fixtureTemplate.toObject();
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
if ( templateDoc?.vmConfig?.length ) {
|
|
581
|
+
templateDoc.vmConfig = await Promise.all( templateDoc.vmConfig.map( async ( vm ) => {
|
|
582
|
+
let vmDetails = await vmService.findOne( { _id: vm.vmId } );
|
|
583
|
+
if ( vmDetails ) {
|
|
584
|
+
vm = { ...vm, ...vmDetails.toObject() };
|
|
585
|
+
return vm;
|
|
586
|
+
}
|
|
587
|
+
} ) );
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
res.sendSuccess( templateDoc );
|
|
592
|
+
} catch ( e ) {
|
|
593
|
+
logger.error( { functionName: 'getFixtureTemplate', error: e } );
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
|
|
598
|
+
export async function assigedTemplate( req, res ) {
|
|
599
|
+
try {
|
|
600
|
+
let findFixtureList = await fixtureConfigService.aggregate( [
|
|
601
|
+
{
|
|
602
|
+
$match: {
|
|
603
|
+
templateType: 'sub',
|
|
604
|
+
},
|
|
605
|
+
},
|
|
606
|
+
{
|
|
607
|
+
$project: {
|
|
608
|
+
fixtureCategory: 1,
|
|
609
|
+
fixtureName: 1,
|
|
610
|
+
fixtureWidth: 1,
|
|
611
|
+
productBrandName: 1,
|
|
612
|
+
productCategory: 1,
|
|
613
|
+
},
|
|
614
|
+
},
|
|
615
|
+
{
|
|
616
|
+
$lookup: {
|
|
617
|
+
from: 'storefixtures',
|
|
618
|
+
let: { fixtureConfigId: '$_id' },
|
|
619
|
+
pipeline: [
|
|
620
|
+
{ $match: { $expr: { $eq: [ '$fixtureConfigId', '$$fixtureConfigId' ] } } },
|
|
621
|
+
{
|
|
622
|
+
$project: {
|
|
623
|
+
storeId: 1,
|
|
624
|
+
},
|
|
625
|
+
},
|
|
626
|
+
],
|
|
627
|
+
as: 'storeCount',
|
|
628
|
+
},
|
|
629
|
+
},
|
|
630
|
+
{
|
|
631
|
+
$unwind: {
|
|
632
|
+
path: '$storeCount',
|
|
633
|
+
preserveNullAndEmptyArrays: true,
|
|
634
|
+
},
|
|
635
|
+
},
|
|
636
|
+
{
|
|
637
|
+
$group: {
|
|
638
|
+
_id: '$_id',
|
|
639
|
+
fixtureCategory: { $first: '$fixtureCategory' },
|
|
640
|
+
fixtureName: { $first: '$fixtureName' },
|
|
641
|
+
fixtureWidth: { $first: '$fixtureWidth' },
|
|
642
|
+
productBrandName: { $first: '$productBrandName' },
|
|
643
|
+
productCategory: { $first: '$productCategory' },
|
|
644
|
+
storeCount: { $addToSet: '$storeCount.storeId' },
|
|
645
|
+
},
|
|
646
|
+
},
|
|
647
|
+
{
|
|
648
|
+
$project: {
|
|
649
|
+
fixtureCategory: 1,
|
|
650
|
+
fixtureName: 1,
|
|
651
|
+
fixtureWidth: 1,
|
|
652
|
+
productBrandName: 1,
|
|
653
|
+
productCategory: 1,
|
|
654
|
+
storeCount: { $size: '$storeCount' },
|
|
655
|
+
},
|
|
656
|
+
},
|
|
657
|
+
|
|
658
|
+
] );
|
|
659
|
+
res.sendSuccess( findFixtureList );
|
|
660
|
+
} catch ( e ) {
|
|
661
|
+
logger.error( { functionName: 'assigedTemplate', error: e } );
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
|
|
666
|
+
export async function TemplateStoresList( req, res ) {
|
|
667
|
+
try {
|
|
668
|
+
let query = [];
|
|
669
|
+
let inputData = req.body;
|
|
670
|
+
let limit = inputData?.limit || 10;
|
|
671
|
+
let page = inputData?.offset || 1;
|
|
672
|
+
let skip = limit * ( page - 1 );
|
|
673
|
+
|
|
674
|
+
query.push( {
|
|
675
|
+
$match: {
|
|
676
|
+
clientId: inputData.clientId,
|
|
677
|
+
fixtureConfigId: new mongoose.Types.ObjectId( inputData.fixtureConfigId ),
|
|
678
|
+
},
|
|
679
|
+
},
|
|
680
|
+
{
|
|
681
|
+
$sort: {
|
|
682
|
+
_id: -1,
|
|
683
|
+
},
|
|
684
|
+
},
|
|
685
|
+
{
|
|
686
|
+
$project: {
|
|
687
|
+
storeId: 1,
|
|
688
|
+
storeName: 1,
|
|
689
|
+
planoId: 1,
|
|
690
|
+
floorId: 1,
|
|
691
|
+
},
|
|
692
|
+
},
|
|
693
|
+
{
|
|
694
|
+
$group: {
|
|
695
|
+
_id: { store: '$storeId', floor: '$floorId' },
|
|
696
|
+
storeName: { $first: '$storeName' },
|
|
697
|
+
planoId: { $first: '$planoId' },
|
|
698
|
+
storeId: { $first: '$storeId' },
|
|
699
|
+
floorId: { $first: '$floorId' },
|
|
700
|
+
},
|
|
701
|
+
},
|
|
702
|
+
{
|
|
703
|
+
$lookup: {
|
|
704
|
+
from: 'storelayouts',
|
|
705
|
+
let: { floor: '$floorId' },
|
|
706
|
+
pipeline: [
|
|
707
|
+
{
|
|
708
|
+
$match: {
|
|
709
|
+
$expr: {
|
|
710
|
+
$eq: [ '$_id', '$$floor' ],
|
|
711
|
+
},
|
|
712
|
+
},
|
|
713
|
+
},
|
|
714
|
+
{
|
|
715
|
+
$project: {
|
|
716
|
+
floorName: 1,
|
|
717
|
+
},
|
|
718
|
+
},
|
|
719
|
+
],
|
|
720
|
+
as: 'floorDetails',
|
|
721
|
+
},
|
|
722
|
+
},
|
|
723
|
+
{
|
|
724
|
+
$unwind: {
|
|
725
|
+
path: '$floorDetails',
|
|
726
|
+
preserveNullAndEmptyArrays: true,
|
|
727
|
+
},
|
|
728
|
+
},
|
|
729
|
+
|
|
730
|
+
);
|
|
731
|
+
if ( inputData.showlookup ) {
|
|
732
|
+
query.push(
|
|
733
|
+
{
|
|
734
|
+
$lookup: {
|
|
735
|
+
from: 'stores',
|
|
736
|
+
let: { storeId: '$storeId' },
|
|
737
|
+
pipeline: [
|
|
738
|
+
{ $match: { $expr: { $eq: [ '$storeId', '$$storeId' ] } } },
|
|
739
|
+
{
|
|
740
|
+
$project: {
|
|
741
|
+
spocDetails: { $arrayElemAt: [ '$spocDetails', 0 ] },
|
|
742
|
+
},
|
|
743
|
+
},
|
|
744
|
+
],
|
|
745
|
+
as: 'storeData',
|
|
746
|
+
},
|
|
747
|
+
},
|
|
748
|
+
{ $unwind: { path: '$storeData', preserveNullAndEmptyArrays: true } },
|
|
749
|
+
{
|
|
750
|
+
$project: {
|
|
751
|
+
storeId: 1,
|
|
752
|
+
storeName: 1,
|
|
753
|
+
planoId: 1,
|
|
754
|
+
floorId: 1,
|
|
755
|
+
spocName: { $ifNull: [ '$storeData.spocDetails.name', '' ] },
|
|
756
|
+
spocEmail: { $ifNull: [ '$storeData.spocDetails.email', '' ] },
|
|
757
|
+
floorDetails: 1,
|
|
758
|
+
_id: '$_id.store',
|
|
759
|
+
},
|
|
760
|
+
},
|
|
761
|
+
);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
if ( inputData.sortColumnName && inputData.sortBy ) {
|
|
765
|
+
query.push( { $sort: { [inputData.sortColumnName]: inputData.sortBy } } );
|
|
766
|
+
}
|
|
767
|
+
if ( inputData.searchValue ) {
|
|
768
|
+
query.push( {
|
|
769
|
+
$match: {
|
|
770
|
+
storeName: { $regex: inputData.searchValue, $options: 'i' },
|
|
771
|
+
},
|
|
772
|
+
} );
|
|
773
|
+
}
|
|
774
|
+
let count = await storeFixtureService.aggregate( query );
|
|
775
|
+
if ( !inputData?.export ) {
|
|
776
|
+
query.push( { $skip: skip }, { $limit: limit } );
|
|
777
|
+
}
|
|
778
|
+
if ( inputData.showlookup ) {
|
|
779
|
+
query.push( {
|
|
780
|
+
$lookup: {
|
|
781
|
+
from: 'clusters',
|
|
782
|
+
let: { storeId: '$storeId' },
|
|
783
|
+
pipeline: [
|
|
784
|
+
{
|
|
785
|
+
$match: {
|
|
786
|
+
$expr: {
|
|
787
|
+
$anyElementTrue: {
|
|
788
|
+
$map: {
|
|
789
|
+
input: '$stores',
|
|
790
|
+
as: 'store',
|
|
791
|
+
in: { $eq: [ '$$store.storeId', '$$storeId' ] },
|
|
792
|
+
},
|
|
793
|
+
},
|
|
794
|
+
},
|
|
795
|
+
},
|
|
796
|
+
},
|
|
797
|
+
{
|
|
798
|
+
$project: {
|
|
799
|
+
clusterName: 1,
|
|
800
|
+
},
|
|
801
|
+
},
|
|
802
|
+
],
|
|
803
|
+
as: 'clusterData',
|
|
804
|
+
},
|
|
805
|
+
}, {
|
|
806
|
+
$addFields: {
|
|
807
|
+
clusterData: {
|
|
808
|
+
$map: {
|
|
809
|
+
input: '$clusterData',
|
|
810
|
+
as: 'cd',
|
|
811
|
+
in: '$$cd.clusterName',
|
|
812
|
+
},
|
|
813
|
+
},
|
|
814
|
+
},
|
|
815
|
+
},
|
|
816
|
+
);
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
let floorQuery = [
|
|
820
|
+
{
|
|
821
|
+
$match: {
|
|
822
|
+
clientId: req.body.clientId,
|
|
823
|
+
},
|
|
824
|
+
},
|
|
825
|
+
{
|
|
826
|
+
$group: {
|
|
827
|
+
_id: '$storeId',
|
|
828
|
+
count: { $sum: 1 },
|
|
829
|
+
},
|
|
830
|
+
},
|
|
831
|
+
{
|
|
832
|
+
$match: {
|
|
833
|
+
count: { $gt: 1 },
|
|
834
|
+
},
|
|
835
|
+
},
|
|
836
|
+
{
|
|
837
|
+
$project: {
|
|
838
|
+
_id: 0,
|
|
839
|
+
store: '$_id',
|
|
840
|
+
},
|
|
841
|
+
},
|
|
842
|
+
];
|
|
843
|
+
const [ response, floorDetails ] = await Promise.all( [
|
|
844
|
+
storeFixtureService.aggregate( query ),
|
|
845
|
+
storeLayoutService.aggregate( floorQuery ),
|
|
846
|
+
] );
|
|
847
|
+
|
|
848
|
+
if ( !req.body.export && !response.length ) {
|
|
849
|
+
return res.sendError( 'No data found', 204 );
|
|
850
|
+
}
|
|
851
|
+
let result = {
|
|
852
|
+
count: count.length || 0,
|
|
853
|
+
data: response || [],
|
|
854
|
+
doubleStore: floorDetails?.map( ( ele ) => ele.store ) ?? [],
|
|
855
|
+
};
|
|
856
|
+
if ( !req.body.export ) {
|
|
857
|
+
return res.sendSuccess( result );
|
|
858
|
+
}
|
|
859
|
+
} catch ( e ) {
|
|
860
|
+
logger.error( { functionName: 'TemplateStoresList', error: e } );
|
|
861
|
+
res.sendError( e, 500 );
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
|
|
866
|
+
export async function replaceFixtureDetails( req, res ) {
|
|
867
|
+
try {
|
|
868
|
+
let inputData = req.body;
|
|
869
|
+
let replaceFixtureData = await fixtureConfigService.findOne( { _id: inputData.replaceFixture } );
|
|
870
|
+
|
|
871
|
+
if ( !replaceFixtureData ) {
|
|
872
|
+
return res.sendError( 'No data found', 204 );
|
|
873
|
+
}
|
|
874
|
+
if ( inputData.storeList.length == 0 && inputData.publishAll ) {
|
|
875
|
+
await fixtureConfigService.updateOne( { _id: inputData.replaceFixture }, { isEdited: false } );
|
|
876
|
+
let query = [
|
|
877
|
+
{
|
|
878
|
+
$match: {
|
|
879
|
+
fixtureConfigId: new ObjectId( inputData.findFixture ),
|
|
880
|
+
},
|
|
881
|
+
},
|
|
882
|
+
{
|
|
883
|
+
$group: {
|
|
884
|
+
_id: '$storeId',
|
|
885
|
+
floorDetails: {
|
|
886
|
+
$first: {
|
|
887
|
+
_id: '$floorId',
|
|
888
|
+
},
|
|
889
|
+
},
|
|
890
|
+
},
|
|
891
|
+
},
|
|
892
|
+
{
|
|
893
|
+
$project: {
|
|
894
|
+
storeId: '$_id',
|
|
895
|
+
floorDetails: 1,
|
|
896
|
+
_id: 0,
|
|
897
|
+
},
|
|
898
|
+
},
|
|
899
|
+
];
|
|
900
|
+
|
|
901
|
+
// inputData.storeList = await storeFixtureService.find( { fixtureConfigId: inputData.findFixture }, { storeId: 1 } );
|
|
902
|
+
inputData.storeList = await storeFixtureService.aggregate( query );
|
|
903
|
+
let data = {
|
|
904
|
+
templateId: inputData.replaceFixture,
|
|
905
|
+
data: replaceFixtureData,
|
|
906
|
+
};
|
|
907
|
+
await templateLogService.create( data );
|
|
908
|
+
}
|
|
909
|
+
if ( inputData.storeList.length ) {
|
|
910
|
+
// let storeList = inputData.storeList.map( ( ele ) => ele.storeId );
|
|
911
|
+
// let getDetails = await storeFixtureService.find( { storeId: { $in: storeList }, fixtureConfigId: inputData.findFixture, $or: [ { isMerchEdited: true }, { isVmEdited: true } ] }, { storeId: 1 } );
|
|
912
|
+
// if ( getDetails.length ) {
|
|
913
|
+
// await Promise.all( getDetails.map( async ( ele ) => {
|
|
914
|
+
// let taskDetails = await processedTaskService.findOne( { store_id: ele.storeId, isPlano: true, planoType: [ 'merchRollout', 'vmRollout' ] }, {}, { _id: -1 } );
|
|
915
|
+
// if ( taskDetails ) {
|
|
916
|
+
// await processedTaskService.deleteOne( { _id: taskDetails._id } );
|
|
917
|
+
// }
|
|
918
|
+
// } ) );
|
|
919
|
+
// }
|
|
920
|
+
const updateData = {
|
|
921
|
+
...replaceFixtureData.toObject(),
|
|
922
|
+
fixtureConfigId: replaceFixtureData._id,
|
|
923
|
+
};
|
|
924
|
+
delete updateData._id;
|
|
925
|
+
|
|
926
|
+
await Promise.all(
|
|
927
|
+
inputData.storeList.map( async ( store ) => {
|
|
928
|
+
const replaceFixture = await storeFixtureService.find( {
|
|
929
|
+
fixtureConfigId: inputData.findFixture,
|
|
930
|
+
...( store?.floorDetails?._id ) ? { floorId: store?.floorDetails?._id } : {},
|
|
931
|
+
storeId: store.storeId,
|
|
932
|
+
} );
|
|
933
|
+
|
|
934
|
+
|
|
935
|
+
if ( !replaceFixture.length ) return;
|
|
936
|
+
|
|
937
|
+
const deleteFixShelves = await fixtureShelfService.deleteMany( {
|
|
938
|
+
fixtureId: { $in: replaceFixture.map( ( ele ) => ele._id ) },
|
|
939
|
+
} );
|
|
940
|
+
await storeFixtureService.updateMany(
|
|
941
|
+
{ fixtureConfigId: inputData.findFixture, ...( store?.floorDetails?._id ) ? { floorId: store?.floorDetails?._id } : {}, storeId: store.storeId },
|
|
942
|
+
updateData,
|
|
943
|
+
);
|
|
944
|
+
|
|
945
|
+
if ( replaceFixtureData.shelfConfig?.length ) {
|
|
946
|
+
replaceFixtureData.shelfConfig.forEach( async ( shelf ) => {
|
|
947
|
+
let shelfData = [];
|
|
948
|
+
shelf = { ...shelf.toObject() };
|
|
949
|
+
delete shelf._id;
|
|
950
|
+
replaceFixture.forEach( async ( data ) => {
|
|
951
|
+
shelfData.push( {
|
|
952
|
+
...shelf,
|
|
953
|
+
floorId: data.floorId,
|
|
954
|
+
planoId: data.planoId,
|
|
955
|
+
clientId: data.clientId,
|
|
956
|
+
fixtureId: data._id,
|
|
957
|
+
storeId: data.storeId,
|
|
958
|
+
storeName: data.storeName,
|
|
959
|
+
} );
|
|
960
|
+
} );
|
|
961
|
+
try {
|
|
962
|
+
await fixtureShelfService.insertMany( shelfData );
|
|
963
|
+
} catch ( err ) {
|
|
964
|
+
console.error( 'Insert failed:', err );
|
|
965
|
+
}
|
|
966
|
+
} );
|
|
967
|
+
// const shelfList = replaceFixtureData.shelfConfig.map( ( shelf ) => {
|
|
968
|
+
// const shelfData = {
|
|
969
|
+
// ...shelf.toObject(),
|
|
970
|
+
// floorId: replaceFixture.floorId,
|
|
971
|
+
// planoId: replaceFixture.planoId,
|
|
972
|
+
// clientId: replaceFixture.clientId,
|
|
973
|
+
// // fixtureId: replaceFixture._id,
|
|
974
|
+
// storeId: replaceFixture.storeId,
|
|
975
|
+
// storeName: replaceFixture.storeName,
|
|
976
|
+
// };
|
|
977
|
+
|
|
978
|
+
// delete shelfData._id;
|
|
979
|
+
// return shelfData;
|
|
980
|
+
// } );
|
|
981
|
+
|
|
982
|
+
// try {
|
|
983
|
+
// await fixtureShelfService.insertMany( shelfList );
|
|
984
|
+
// } catch ( err ) {
|
|
985
|
+
// console.error( 'Insert failed:', err );
|
|
986
|
+
// }
|
|
987
|
+
}
|
|
988
|
+
} ),
|
|
989
|
+
);
|
|
990
|
+
} else {
|
|
991
|
+
return res.sendError( 'Store Not found', 500 );
|
|
992
|
+
}
|
|
993
|
+
res.sendSuccess( 'updatedSucessfully' );
|
|
994
|
+
} catch ( e ) {
|
|
995
|
+
logger.error( { functionName: 'replaceFixtureDetails', error: e } );
|
|
996
|
+
res.sendError( e, 500 );
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
export async function getMasterList( req, res ) {
|
|
1001
|
+
try {
|
|
1002
|
+
let limit = req.body?.limit || 10;
|
|
1003
|
+
let page = req.body?.offset || 1;
|
|
1004
|
+
let skip = limit * ( page - 1 );
|
|
1005
|
+
|
|
1006
|
+
let searchMasterList = [];
|
|
1007
|
+
|
|
1008
|
+
if ( req.body?.searchValue ) {
|
|
1009
|
+
let searchQuery = [
|
|
1010
|
+
{
|
|
1011
|
+
$match: {
|
|
1012
|
+
clientId: req.body.clientId,
|
|
1013
|
+
templateType: 'sub',
|
|
1014
|
+
fixtureName: { $regex: req.body.searchValue, $options: 'i' },
|
|
1015
|
+
},
|
|
1016
|
+
},
|
|
1017
|
+
{
|
|
1018
|
+
$group: {
|
|
1019
|
+
_id: '$masterTemplateId',
|
|
1020
|
+
},
|
|
1021
|
+
},
|
|
1022
|
+
];
|
|
1023
|
+
|
|
1024
|
+
let subTemplateDetails = await fixtureConfigService.aggregate( searchQuery );
|
|
1025
|
+
if ( subTemplateDetails.length ) {
|
|
1026
|
+
searchMasterList = subTemplateDetails.map( ( ele ) => ele._id );
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
const matchStage = {
|
|
1031
|
+
clientId: req.body.clientId,
|
|
1032
|
+
templateType: 'master',
|
|
1033
|
+
...( req.body?.searchValue ?
|
|
1034
|
+
{ $or: [ { fixtureName: { $regex: req.body.searchValue, $options: 'i' } }, { _id: { $in: searchMasterList } } ] } :
|
|
1035
|
+
{} ),
|
|
1036
|
+
...( req.body?.filter?.brand?.length ?
|
|
1037
|
+
{
|
|
1038
|
+
$or: [
|
|
1039
|
+
{ 'productBrandName': { $in: req.body.filter.brand } },
|
|
1040
|
+
{ 'shelfConfig.productBrandName': { $in: req.body.filter.brand } },
|
|
1041
|
+
],
|
|
1042
|
+
} :
|
|
1043
|
+
{} ),
|
|
1044
|
+
...( req.body?.filter?.category?.length ?
|
|
1045
|
+
{ fixtureCate: { $in: req.body.filter.category } } :
|
|
1046
|
+
{} ),
|
|
1047
|
+
...( req.body?.filter?.subCategory?.length ?
|
|
1048
|
+
{ productSubCategory: { $in: req.body.subCategory.category } } :
|
|
1049
|
+
{} ),
|
|
1050
|
+
};
|
|
1051
|
+
|
|
1052
|
+
const query = [
|
|
1053
|
+
{
|
|
1054
|
+
$addFields: {
|
|
1055
|
+
fixtureCate: {
|
|
1056
|
+
$concat: [
|
|
1057
|
+
'$fixtureCategory',
|
|
1058
|
+
' - ',
|
|
1059
|
+
{ $toString: '$fixtureWidth.value' },
|
|
1060
|
+
'$fixtureWidth.unit',
|
|
1061
|
+
],
|
|
1062
|
+
},
|
|
1063
|
+
},
|
|
1064
|
+
},
|
|
1065
|
+
{ $match: matchStage },
|
|
1066
|
+
{
|
|
1067
|
+
$lookup: {
|
|
1068
|
+
from: 'fixtureconfigs',
|
|
1069
|
+
let: { mainId: '$_id' },
|
|
1070
|
+
pipeline: [
|
|
1071
|
+
{
|
|
1072
|
+
$match: {
|
|
1073
|
+
$expr: {
|
|
1074
|
+
$eq: [ '$masterTemplateId', '$$mainId' ],
|
|
1075
|
+
},
|
|
1076
|
+
},
|
|
1077
|
+
},
|
|
1078
|
+
{
|
|
1079
|
+
$group: {
|
|
1080
|
+
_id: '$masterTemplateId',
|
|
1081
|
+
count: { $sum: 1 },
|
|
1082
|
+
},
|
|
1083
|
+
},
|
|
1084
|
+
],
|
|
1085
|
+
as: 'childtemplate',
|
|
1086
|
+
},
|
|
1087
|
+
},
|
|
1088
|
+
{ $unwind: { path: '$childtemplate', preserveNullAndEmptyArrays: true } },
|
|
1089
|
+
{
|
|
1090
|
+
$project: {
|
|
1091
|
+
fixtureCategory: 1,
|
|
1092
|
+
fixtureCate: 1,
|
|
1093
|
+
fixtureName: 1,
|
|
1094
|
+
fixtureWidth: 1,
|
|
1095
|
+
clientId: 1,
|
|
1096
|
+
fixtureType: 1,
|
|
1097
|
+
childCount: { $ifNull: [ '$childtemplate.count', 0 ] },
|
|
1098
|
+
productBrandName: {
|
|
1099
|
+
$setUnion: [
|
|
1100
|
+
{ $ifNull: [ '$productBrandName', [] ] },
|
|
1101
|
+
{
|
|
1102
|
+
$reduce: {
|
|
1103
|
+
input: '$shelfConfig',
|
|
1104
|
+
initialValue: [],
|
|
1105
|
+
in: {
|
|
1106
|
+
$concatArrays: [
|
|
1107
|
+
'$$value',
|
|
1108
|
+
{ $ifNull: [ '$$this.productBrandName', [] ] },
|
|
1109
|
+
],
|
|
1110
|
+
},
|
|
1111
|
+
},
|
|
1112
|
+
},
|
|
1113
|
+
],
|
|
1114
|
+
},
|
|
1115
|
+
productCategory: {
|
|
1116
|
+
$setUnion: [
|
|
1117
|
+
{ $ifNull: [ '$productCategory', [] ] },
|
|
1118
|
+
{
|
|
1119
|
+
$reduce: {
|
|
1120
|
+
input: '$shelfConfig',
|
|
1121
|
+
initialValue: [],
|
|
1122
|
+
in: {
|
|
1123
|
+
$concatArrays: [
|
|
1124
|
+
'$$value',
|
|
1125
|
+
{ $ifNull: [ '$$this.productCategory', [] ] },
|
|
1126
|
+
],
|
|
1127
|
+
},
|
|
1128
|
+
},
|
|
1129
|
+
},
|
|
1130
|
+
],
|
|
1131
|
+
},
|
|
1132
|
+
productSubCategory: {
|
|
1133
|
+
$setUnion: [
|
|
1134
|
+
{ $ifNull: [ '$productSubCategory', [] ] },
|
|
1135
|
+
{
|
|
1136
|
+
$reduce: {
|
|
1137
|
+
input: '$shelfConfig',
|
|
1138
|
+
initialValue: [],
|
|
1139
|
+
in: {
|
|
1140
|
+
$concatArrays: [
|
|
1141
|
+
'$$value',
|
|
1142
|
+
{ $ifNull: [ '$$this.productSubCategory', [] ] },
|
|
1143
|
+
],
|
|
1144
|
+
},
|
|
1145
|
+
},
|
|
1146
|
+
},
|
|
1147
|
+
],
|
|
1148
|
+
},
|
|
1149
|
+
},
|
|
1150
|
+
},
|
|
1151
|
+
|
|
1152
|
+
];
|
|
1153
|
+
|
|
1154
|
+
if ( req.body.filter.status.length ) {
|
|
1155
|
+
query.push( {
|
|
1156
|
+
$match: {
|
|
1157
|
+
status: { $in: req.body.filter.status },
|
|
1158
|
+
},
|
|
1159
|
+
} );
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
if ( req.body?.sortColumnName && req.body?.sortBy ) {
|
|
1163
|
+
query.push( {
|
|
1164
|
+
$sort: {
|
|
1165
|
+
[req.body.sortColumnName]: req.body.sortBy,
|
|
1166
|
+
},
|
|
1167
|
+
},
|
|
1168
|
+
);
|
|
1169
|
+
} else {
|
|
1170
|
+
query.push( {
|
|
1171
|
+
$sort: { _id: -1 },
|
|
1172
|
+
} );
|
|
1173
|
+
}
|
|
1174
|
+
query.push(
|
|
1175
|
+
{
|
|
1176
|
+
$facet: {
|
|
1177
|
+
...( !req.body?.export ) ? {
|
|
1178
|
+
templateData: [ { $skip: skip }, { $limit: limit } ],
|
|
1179
|
+
} : { templateData: [ { $skip: skip } ] },
|
|
1180
|
+
count: [ { $count: 'total' } ],
|
|
1181
|
+
},
|
|
1182
|
+
},
|
|
1183
|
+
);
|
|
1184
|
+
let fixtureDetails = await fixtureConfigService.aggregate( query );
|
|
1185
|
+
|
|
1186
|
+
|
|
1187
|
+
if ( !fixtureDetails[0]?.templateData.length ) {
|
|
1188
|
+
return res.sendError( 'No data found', 204 );
|
|
1189
|
+
}
|
|
1190
|
+
let result = {
|
|
1191
|
+
count: fixtureDetails[0].count[0].total,
|
|
1192
|
+
data: fixtureDetails[0].templateData,
|
|
1193
|
+
};
|
|
1194
|
+
|
|
1195
|
+
return res.sendSuccess( result );
|
|
1196
|
+
} catch ( e ) {
|
|
1197
|
+
logger.error( { functionName: 'getMasterList', error: e } );
|
|
1198
|
+
return res.sendError( e, 500 );
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
export async function getChildList( req, res ) {
|
|
1203
|
+
try {
|
|
1204
|
+
let limit = req.body?.limit || 10;
|
|
1205
|
+
let page = req.body?.offset || 1;
|
|
1206
|
+
let skip = limit * ( page - 1 );
|
|
1207
|
+
|
|
1208
|
+
const matchStage = {
|
|
1209
|
+
clientId: req.body.clientId,
|
|
1210
|
+
templateType: 'sub',
|
|
1211
|
+
masterTemplateId: new ObjectId( req.body.masterTemplateId ),
|
|
1212
|
+
...( req.body?.searchValue ?
|
|
1213
|
+
{ fixtureName: { $regex: req.body.searchValue, $options: 'i' } } :
|
|
1214
|
+
{} ),
|
|
1215
|
+
};
|
|
1216
|
+
|
|
1217
|
+
const query = [
|
|
1218
|
+
{ $match: matchStage },
|
|
1219
|
+
{
|
|
1220
|
+
$lookup: {
|
|
1221
|
+
from: 'storefixtures',
|
|
1222
|
+
let: { templateId: '$_id' },
|
|
1223
|
+
pipeline: [
|
|
1224
|
+
{
|
|
1225
|
+
$match: {
|
|
1226
|
+
$expr: {
|
|
1227
|
+
$eq: [ '$$templateId', '$fixtureConfigId' ],
|
|
1228
|
+
},
|
|
1229
|
+
},
|
|
1230
|
+
},
|
|
1231
|
+
{
|
|
1232
|
+
$group: {
|
|
1233
|
+
_id: null,
|
|
1234
|
+
planoId: { $addToSet: '$planoId' },
|
|
1235
|
+
storeList: { $addToSet: '$storeName' },
|
|
1236
|
+
},
|
|
1237
|
+
},
|
|
1238
|
+
{
|
|
1239
|
+
$project: {
|
|
1240
|
+
_id: 0,
|
|
1241
|
+
planoId: 1,
|
|
1242
|
+
storeList: 1,
|
|
1243
|
+
},
|
|
1244
|
+
},
|
|
1245
|
+
],
|
|
1246
|
+
as: 'storeFixtureDetails',
|
|
1247
|
+
},
|
|
1248
|
+
},
|
|
1249
|
+
{
|
|
1250
|
+
$project: {
|
|
1251
|
+
fixtureCategory: 1,
|
|
1252
|
+
fixtureName: 1,
|
|
1253
|
+
fixtureWidth: 1,
|
|
1254
|
+
productBrandName: {
|
|
1255
|
+
$setUnion: [
|
|
1256
|
+
{ $ifNull: [ '$productBrandName', [] ] },
|
|
1257
|
+
{
|
|
1258
|
+
$reduce: {
|
|
1259
|
+
input: '$shelfConfig',
|
|
1260
|
+
initialValue: [],
|
|
1261
|
+
in: {
|
|
1262
|
+
$concatArrays: [
|
|
1263
|
+
'$$value',
|
|
1264
|
+
{ $ifNull: [ '$$this.productBrandName', [] ] },
|
|
1265
|
+
],
|
|
1266
|
+
},
|
|
1267
|
+
},
|
|
1268
|
+
},
|
|
1269
|
+
],
|
|
1270
|
+
},
|
|
1271
|
+
productCategory: {
|
|
1272
|
+
$setUnion: [
|
|
1273
|
+
{ $ifNull: [ '$productCategory', [] ] },
|
|
1274
|
+
{
|
|
1275
|
+
$reduce: {
|
|
1276
|
+
input: '$shelfConfig',
|
|
1277
|
+
initialValue: [],
|
|
1278
|
+
in: {
|
|
1279
|
+
$concatArrays: [
|
|
1280
|
+
'$$value',
|
|
1281
|
+
{ $ifNull: [ '$$this.productCategory', [] ] },
|
|
1282
|
+
],
|
|
1283
|
+
},
|
|
1284
|
+
},
|
|
1285
|
+
},
|
|
1286
|
+
],
|
|
1287
|
+
},
|
|
1288
|
+
productSubCategory: {
|
|
1289
|
+
$setUnion: [
|
|
1290
|
+
{ $ifNull: [ '$productSubCategory', [] ] },
|
|
1291
|
+
{
|
|
1292
|
+
$reduce: {
|
|
1293
|
+
input: '$shelfConfig',
|
|
1294
|
+
initialValue: [],
|
|
1295
|
+
in: {
|
|
1296
|
+
$concatArrays: [
|
|
1297
|
+
'$$value',
|
|
1298
|
+
{ $ifNull: [ '$$this.productSubCategory', [] ] },
|
|
1299
|
+
],
|
|
1300
|
+
},
|
|
1301
|
+
},
|
|
1302
|
+
},
|
|
1303
|
+
],
|
|
1304
|
+
},
|
|
1305
|
+
clientId: 1,
|
|
1306
|
+
status: 1,
|
|
1307
|
+
fixtureType: 1,
|
|
1308
|
+
planoId: { $ifNull: [ { $arrayElemAt: [ '$storeFixtureDetails.planoId', 0 ] }, [] ] },
|
|
1309
|
+
storeList: { $ifNull: [ { $arrayElemAt: [ '$storeFixtureDetails.storeList', 0 ] }, [] ] },
|
|
1310
|
+
updatedAt: 1,
|
|
1311
|
+
},
|
|
1312
|
+
},
|
|
1313
|
+
{
|
|
1314
|
+
$lookup: {
|
|
1315
|
+
from: 'planograms',
|
|
1316
|
+
let: { planoIds: '$planoId' },
|
|
1317
|
+
pipeline: [
|
|
1318
|
+
{
|
|
1319
|
+
$match: {
|
|
1320
|
+
$expr: {
|
|
1321
|
+
$in: [ '$_id', { $ifNull: [ '$$planoIds', [] ] } ],
|
|
1322
|
+
},
|
|
1323
|
+
},
|
|
1324
|
+
},
|
|
1325
|
+
{
|
|
1326
|
+
$group: {
|
|
1327
|
+
_id: null,
|
|
1328
|
+
statusList: { $addToSet: '$status' },
|
|
1329
|
+
},
|
|
1330
|
+
},
|
|
1331
|
+
],
|
|
1332
|
+
as: 'planoStatus',
|
|
1333
|
+
},
|
|
1334
|
+
},
|
|
1335
|
+
{
|
|
1336
|
+
$project: {
|
|
1337
|
+
fixtureCategory: 1,
|
|
1338
|
+
fixtureName: 1,
|
|
1339
|
+
fixtureWidth: 1,
|
|
1340
|
+
productBrandName: 1,
|
|
1341
|
+
productCategory: 1,
|
|
1342
|
+
clientId: 1,
|
|
1343
|
+
fixtureType: 1,
|
|
1344
|
+
productSubCategory: 1,
|
|
1345
|
+
status: 1,
|
|
1346
|
+
templateId: 1,
|
|
1347
|
+
planoId: 1,
|
|
1348
|
+
vmCapacity: 1,
|
|
1349
|
+
productCapacity: 1,
|
|
1350
|
+
storeList: 1,
|
|
1351
|
+
storeCount: { $size: '$storeList' },
|
|
1352
|
+
planoStatus: { $ifNull: [ { $arrayElemAt: [ '$planoStatus.statusList', 0 ] }, [] ] },
|
|
1353
|
+
status: {
|
|
1354
|
+
$cond: {
|
|
1355
|
+
if: { $in: [ 'completed', { $ifNull: [ { $arrayElemAt: [ '$planoStatus.statusList', 0 ] }, [] ] } ] },
|
|
1356
|
+
then: 'active',
|
|
1357
|
+
else: {
|
|
1358
|
+
$cond: {
|
|
1359
|
+
if: {
|
|
1360
|
+
$eq: [
|
|
1361
|
+
'$status', 'draft',
|
|
1362
|
+
],
|
|
1363
|
+
},
|
|
1364
|
+
then: 'draft',
|
|
1365
|
+
else: 'inactive',
|
|
1366
|
+
},
|
|
1367
|
+
},
|
|
1368
|
+
},
|
|
1369
|
+
},
|
|
1370
|
+
updatedAt: 1,
|
|
1371
|
+
},
|
|
1372
|
+
},
|
|
1373
|
+
];
|
|
1374
|
+
|
|
1375
|
+
if ( req.body.searchValue ) {
|
|
1376
|
+
query.push( {
|
|
1377
|
+
$match: {
|
|
1378
|
+
fixtureName: { $regex: req.body.searchValue, $options: 'i' },
|
|
1379
|
+
},
|
|
1380
|
+
} );
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
if ( req.body?.sortColumnName && req.body?.sortBy ) {
|
|
1384
|
+
query.push( {
|
|
1385
|
+
$sort: {
|
|
1386
|
+
[req.body.sortColumnName]: req.body.sortBy,
|
|
1387
|
+
},
|
|
1388
|
+
},
|
|
1389
|
+
);
|
|
1390
|
+
} else {
|
|
1391
|
+
query.push( {
|
|
1392
|
+
$sort: { _id: -1 },
|
|
1393
|
+
} );
|
|
1394
|
+
}
|
|
1395
|
+
query.push(
|
|
1396
|
+
{
|
|
1397
|
+
$facet: {
|
|
1398
|
+
templateData: [ { $skip: skip }, { $limit: limit } ],
|
|
1399
|
+
count: [ { $count: 'total' } ],
|
|
1400
|
+
},
|
|
1401
|
+
},
|
|
1402
|
+
);
|
|
1403
|
+
let fixtureDetails = await fixtureConfigService.aggregate( query );
|
|
1404
|
+
if ( !fixtureDetails[0]?.templateData.length ) {
|
|
1405
|
+
return res.sendError( 'No data found', 204 );
|
|
1406
|
+
}
|
|
1407
|
+
let result = {
|
|
1408
|
+
count: fixtureDetails[0].count[0].total,
|
|
1409
|
+
data: fixtureDetails[0].templateData,
|
|
1410
|
+
};
|
|
1411
|
+
return res.sendSuccess( result );
|
|
1412
|
+
} catch ( e ) {
|
|
1413
|
+
logger.error( { functionName: 'getChildList', error: e } );
|
|
1414
|
+
return res.sendError( e, 500 );
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
export async function getTreeListOld( req, res ) {
|
|
1419
|
+
try {
|
|
1420
|
+
let query = [
|
|
1421
|
+
{
|
|
1422
|
+
$match: {
|
|
1423
|
+
clientId: req.query.clientId,
|
|
1424
|
+
templateType: 'master',
|
|
1425
|
+
...( req.query.masterId && { masterTemplateId: req.query.masterId } ),
|
|
1426
|
+
},
|
|
1427
|
+
},
|
|
1428
|
+
{
|
|
1429
|
+
$group: {
|
|
1430
|
+
_id: '$templateGroupName',
|
|
1431
|
+
},
|
|
1432
|
+
},
|
|
1433
|
+
{
|
|
1434
|
+
$project: {
|
|
1435
|
+
_id: 0,
|
|
1436
|
+
group: '$_id',
|
|
1437
|
+
},
|
|
1438
|
+
},
|
|
1439
|
+
];
|
|
1440
|
+
let getGroupDetails = await fixtureConfigService.aggregate( query );
|
|
1441
|
+
if ( !getGroupDetails.length ) {
|
|
1442
|
+
return res.sendError( 'No data found', 204 );
|
|
1443
|
+
}
|
|
1444
|
+
let treeList = await Promise.all( getGroupDetails.map( async ( ele ) => {
|
|
1445
|
+
let groupDetails = await fixtureConfigService.find( { templateGroupName: ele.group, templateType: 'master' } );
|
|
1446
|
+
let masterDetails = await Promise.all( groupDetails.map( async ( group ) => {
|
|
1447
|
+
let templateDetails = await fixtureConfigService.find( { masterTemplateId: group._id } );
|
|
1448
|
+
let templateList = await Promise.all( templateDetails.map( async ( temp ) => {
|
|
1449
|
+
let storeFixtureCount = await storeFixtureService.count( { fixtureConfigId: ele._id } );
|
|
1450
|
+
return { ...temp.toObject(), storeCount: storeFixtureCount };
|
|
1451
|
+
} ) );
|
|
1452
|
+
return { ...group.toObject(), subTemplateList: templateList };
|
|
1453
|
+
} ) );
|
|
1454
|
+
return { groupName: ele.group, masterTemplate: masterDetails };
|
|
1455
|
+
} ) );
|
|
1456
|
+
return res.sendSuccess( treeList );
|
|
1457
|
+
} catch ( e ) {
|
|
1458
|
+
logger.error( { functionName: 'getTreeList', error: e } );
|
|
1459
|
+
return res.sendError( e, 500 );
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
export async function getTreeList( req, res ) {
|
|
1464
|
+
try {
|
|
1465
|
+
let query = [
|
|
1466
|
+
{
|
|
1467
|
+
$match: {
|
|
1468
|
+
...( req.query?.masterId ) ? { masterTemplateId: new ObjectId( req.query.masterId ) } :{ clientId: req.query.clientId, templateType: 'master' },
|
|
1469
|
+
},
|
|
1470
|
+
},
|
|
1471
|
+
{
|
|
1472
|
+
$sort: {
|
|
1473
|
+
'header.label': 1,
|
|
1474
|
+
},
|
|
1475
|
+
},
|
|
1476
|
+
|
|
1477
|
+
];
|
|
1478
|
+
|
|
1479
|
+
let fixtureDetails = await fixtureConfigService.aggregate( query );
|
|
1480
|
+
if ( req?.query?.masterId ) {
|
|
1481
|
+
fixtureDetails = await Promise.all( fixtureDetails.map( async ( fixt ) => {
|
|
1482
|
+
let query = [
|
|
1483
|
+
{
|
|
1484
|
+
$match: {
|
|
1485
|
+
fixtureConfigId: new ObjectId( fixt._id ),
|
|
1486
|
+
},
|
|
1487
|
+
},
|
|
1488
|
+
{
|
|
1489
|
+
$group: {
|
|
1490
|
+
_id: '',
|
|
1491
|
+
store: { $addToSet: '$storeId' },
|
|
1492
|
+
},
|
|
1493
|
+
},
|
|
1494
|
+
{
|
|
1495
|
+
$project: {
|
|
1496
|
+
_id: 0,
|
|
1497
|
+
storeCount: { $size: '$store' },
|
|
1498
|
+
},
|
|
1499
|
+
},
|
|
1500
|
+
];
|
|
1501
|
+
let storeFixtureCount = await storeFixtureService.aggregate( query );
|
|
1502
|
+
fixt.vmConfig = await Promise.all( fixt.vmConfig.map( async ( vm ) => {
|
|
1503
|
+
let vmDetails = await vmService.findOne( { _id: vm.vmId }, { _id: 0 } );
|
|
1504
|
+
return { ...vm, ...vmDetails?.toObject() };
|
|
1505
|
+
} ) );
|
|
1506
|
+
return { ...fixt, storeCount: storeFixtureCount?.[0]?.storeCount || 0 };
|
|
1507
|
+
} ) );
|
|
1508
|
+
}
|
|
1509
|
+
return res.sendSuccess( fixtureDetails );
|
|
1510
|
+
} catch ( e ) {
|
|
1511
|
+
logger.error( { functionName: 'getTreeList', error: e } );
|
|
1512
|
+
return res.sendError( e, 500 );
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
export async function duplicateTemplate( req, res ) {
|
|
1517
|
+
try {
|
|
1518
|
+
let templateDetails = await fixtureConfigService.findOne( { _id: req.body.templateId }, { createdAt: 0, updatedAt: 0 } );
|
|
1519
|
+
if ( !templateDetails ) {
|
|
1520
|
+
return res.sendError( 'No data found', 204 );
|
|
1521
|
+
}
|
|
1522
|
+
let getAllTemplate;
|
|
1523
|
+
let counter = 1;
|
|
1524
|
+
let newFixtureName;
|
|
1525
|
+
templateDetails = templateDetails.toObject();
|
|
1526
|
+
let type = templateDetails.templateType;
|
|
1527
|
+
if ( templateDetails.templateType == 'master' ) {
|
|
1528
|
+
templateDetails = { ...templateDetails, masterTemplateId: templateDetails._id, templateType: 'sub' };
|
|
1529
|
+
getAllTemplate = await fixtureConfigService.findAndSort( { masterTemplateId: templateDetails.masterTemplateId }, {}, { templateIndex: -1 } );
|
|
1530
|
+
newFixtureName = templateDetails.fixtureName + ` - Variant ${getAllTemplate.length + 1}`;
|
|
1531
|
+
if ( getAllTemplate?.length ) {
|
|
1532
|
+
let fixtureNameList = getAllTemplate.map( ( ele ) => ele.fixtureName );
|
|
1533
|
+
while ( fixtureNameList.includes( newFixtureName ) ) {
|
|
1534
|
+
newFixtureName = templateDetails.fixtureName + ` - Variant ${counter}`;
|
|
1535
|
+
counter++;
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
} else {
|
|
1539
|
+
getAllTemplate = await fixtureConfigService.findAndSort( { fixtureName: { $regex: templateDetails.fixtureName.replace( /[.*+?^${}()|[\]\\]/g, '\\$&' ), $options: 'i' } }, { fixtureName: 1, templateIndex: 1 }, { templateIndex: -1 } );
|
|
1540
|
+
newFixtureName = templateDetails.fixtureName + ` (${counter})`;
|
|
1541
|
+
if ( getAllTemplate?.length ) {
|
|
1542
|
+
let fixtureNameList = getAllTemplate.map( ( ele ) => ele.fixtureName );
|
|
1543
|
+
while ( fixtureNameList.includes( newFixtureName ) ) {
|
|
1544
|
+
newFixtureName = templateDetails.fixtureName + ` (${counter})`;
|
|
1545
|
+
counter++;
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
templateDetails.templateIndex = ( getAllTemplate?.[0]?.templateIndex ?? 0 )+ 1;
|
|
1550
|
+
delete templateDetails._id;
|
|
1551
|
+
delete templateDetails.templateGroupName;
|
|
1552
|
+
templateDetails.fixtureName = newFixtureName;
|
|
1553
|
+
templateDetails.status = 'complete';
|
|
1554
|
+
templateDetails.isEdited = false;
|
|
1555
|
+
let duplicateDetails = await fixtureConfigService.create( templateDetails );
|
|
1556
|
+
return res.sendSuccess( { message: type == 'sub' ? 'Fixture template duplicated successfully' : 'Variant created successfully', id: duplicateDetails?._id } );
|
|
1557
|
+
} catch ( e ) {
|
|
1558
|
+
logger.error( { functionName: 'duplicateFixture', error: e } );
|
|
1559
|
+
return res.sendError( e, 500 );
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
export async function getTemplateStoreList( req, res ) {
|
|
1564
|
+
try {
|
|
1565
|
+
let templateDetails = await fixtureConfigService.findOne( { _id: req.body.templateId } );
|
|
1566
|
+
if ( !templateDetails ) {
|
|
1567
|
+
return res.sendError( 'N0 data found', 204 );
|
|
1568
|
+
}
|
|
1569
|
+
let limit = req.body?.limit || 10;
|
|
1570
|
+
let page = req.body?.offset || 0;
|
|
1571
|
+
let skip = limit * ( page - 1 );
|
|
1572
|
+
let query = [
|
|
1573
|
+
{
|
|
1574
|
+
$match: {
|
|
1575
|
+
fixtureConfigId: new ObjectId( req.body.templateId ),
|
|
1576
|
+
},
|
|
1577
|
+
},
|
|
1578
|
+
{
|
|
1579
|
+
$group: {
|
|
1580
|
+
_id: { store: '$storeName', floor: '$floorId' },
|
|
1581
|
+
storeId: { $first: '$storeId' },
|
|
1582
|
+
updatedAt: { $first: '$updatedAt' },
|
|
1583
|
+
planoId: { $first: '$planoId' },
|
|
1584
|
+
},
|
|
1585
|
+
},
|
|
1586
|
+
{
|
|
1587
|
+
$project: {
|
|
1588
|
+
storeName: '$_id.store',
|
|
1589
|
+
storeId: 1,
|
|
1590
|
+
updatedAt: 1,
|
|
1591
|
+
planoId: 1,
|
|
1592
|
+
floorId: '$_id.floor',
|
|
1593
|
+
},
|
|
1594
|
+
},
|
|
1595
|
+
{
|
|
1596
|
+
$lookup: {
|
|
1597
|
+
from: 'storelayouts',
|
|
1598
|
+
let: { floor: '$floorId' },
|
|
1599
|
+
pipeline: [
|
|
1600
|
+
{
|
|
1601
|
+
$match: {
|
|
1602
|
+
$expr: {
|
|
1603
|
+
$eq: [ '$_id', '$$floor' ],
|
|
1604
|
+
},
|
|
1605
|
+
},
|
|
1606
|
+
},
|
|
1607
|
+
{
|
|
1608
|
+
$project: {
|
|
1609
|
+
floorName: 1,
|
|
1610
|
+
},
|
|
1611
|
+
},
|
|
1612
|
+
],
|
|
1613
|
+
as: 'floorDetails',
|
|
1614
|
+
},
|
|
1615
|
+
},
|
|
1616
|
+
{
|
|
1617
|
+
$unwind: {
|
|
1618
|
+
path: '$floorDetails',
|
|
1619
|
+
preserveNullAndEmptyArrays: true,
|
|
1620
|
+
},
|
|
1621
|
+
},
|
|
1622
|
+
{
|
|
1623
|
+
$lookup: {
|
|
1624
|
+
from: 'stores',
|
|
1625
|
+
let: { store: '$storeId' },
|
|
1626
|
+
pipeline: [
|
|
1627
|
+
{
|
|
1628
|
+
$match: {
|
|
1629
|
+
$expr: {
|
|
1630
|
+
$eq: [ '$storeId', '$$store' ],
|
|
1631
|
+
},
|
|
1632
|
+
},
|
|
1633
|
+
},
|
|
1634
|
+
{
|
|
1635
|
+
$project: {
|
|
1636
|
+
_id: 0,
|
|
1637
|
+
storeProfile: 1,
|
|
1638
|
+
},
|
|
1639
|
+
},
|
|
1640
|
+
],
|
|
1641
|
+
as: 'storeDetails',
|
|
1642
|
+
},
|
|
1643
|
+
},
|
|
1644
|
+
{
|
|
1645
|
+
$lookup: {
|
|
1646
|
+
from: 'clusters',
|
|
1647
|
+
let: { store: '$storeId' },
|
|
1648
|
+
pipeline: [
|
|
1649
|
+
{
|
|
1650
|
+
$match: {
|
|
1651
|
+
$expr: {
|
|
1652
|
+
$in: [ '$$store', '$stores.storeId' ],
|
|
1653
|
+
},
|
|
1654
|
+
},
|
|
1655
|
+
},
|
|
1656
|
+
{
|
|
1657
|
+
$group: {
|
|
1658
|
+
_id: '',
|
|
1659
|
+
clusterName: { $addToSet: '$clusterName' },
|
|
1660
|
+
},
|
|
1661
|
+
},
|
|
1662
|
+
{
|
|
1663
|
+
$project: {
|
|
1664
|
+
_id: 0,
|
|
1665
|
+
clusterName: 1,
|
|
1666
|
+
},
|
|
1667
|
+
},
|
|
1668
|
+
],
|
|
1669
|
+
as: 'clusterDetails',
|
|
1670
|
+
},
|
|
1671
|
+
},
|
|
1672
|
+
{
|
|
1673
|
+
$project: {
|
|
1674
|
+
storeName: 1,
|
|
1675
|
+
storeId: 1,
|
|
1676
|
+
updatedAt: 1,
|
|
1677
|
+
planoId: 1,
|
|
1678
|
+
storeDetails: { $ifNull: [ { $arrayElemAt: [ '$storeDetails.storeProfile', 0 ] }, {} ] },
|
|
1679
|
+
clusterDetails: { $ifNull: [ { $arrayElemAt: [ '$clusterDetails.clusterName', 0 ] }, {} ] },
|
|
1680
|
+
floorId: 1,
|
|
1681
|
+
floorName: { $ifNull: [ '$floorDetails.floorName', '' ] },
|
|
1682
|
+
},
|
|
1683
|
+
},
|
|
1684
|
+
];
|
|
1685
|
+
if ( req.body.searchValue ) {
|
|
1686
|
+
query.push( {
|
|
1687
|
+
$match: {
|
|
1688
|
+
storeName: { $regex: req.body.searchValue, $options: 'i' },
|
|
1689
|
+
},
|
|
1690
|
+
} );
|
|
1691
|
+
}
|
|
1692
|
+
if ( req.body.sortColumnName && req.body.sortBy ) {
|
|
1693
|
+
query.push( { $sort: { [req.body.sortColumnName]: req.body.sortBy } } );
|
|
1694
|
+
} else {
|
|
1695
|
+
query.push( { $sort: { storeName: 1 } } );
|
|
1696
|
+
}
|
|
1697
|
+
query.push(
|
|
1698
|
+
{
|
|
1699
|
+
$facet: {
|
|
1700
|
+
data: [
|
|
1701
|
+
{ $skip: skip }, { $limit: limit },
|
|
1702
|
+
],
|
|
1703
|
+
count: [
|
|
1704
|
+
{ $count: 'total' },
|
|
1705
|
+
],
|
|
1706
|
+
},
|
|
1707
|
+
},
|
|
1708
|
+
);
|
|
1709
|
+
let floorQuery = [
|
|
1710
|
+
{
|
|
1711
|
+
$group: {
|
|
1712
|
+
_id: '$storeId',
|
|
1713
|
+
count: { $sum: 1 },
|
|
1714
|
+
},
|
|
1715
|
+
},
|
|
1716
|
+
{
|
|
1717
|
+
$match: {
|
|
1718
|
+
count: { $gt: 1 },
|
|
1719
|
+
},
|
|
1720
|
+
},
|
|
1721
|
+
{
|
|
1722
|
+
$project: {
|
|
1723
|
+
_id: 0,
|
|
1724
|
+
store: '$_id',
|
|
1725
|
+
},
|
|
1726
|
+
},
|
|
1727
|
+
];
|
|
1728
|
+
const [ getStoreDetails, floorDetails ] = await Promise.all( [
|
|
1729
|
+
storeFixtureService.aggregate( query ),
|
|
1730
|
+
storeLayoutService.aggregate( floorQuery ),
|
|
1731
|
+
] );
|
|
1732
|
+
if ( !getStoreDetails[0].data.length ) {
|
|
1733
|
+
return res.sendError( 'No data found', 204 );
|
|
1734
|
+
}
|
|
1735
|
+
let result = {
|
|
1736
|
+
count: getStoreDetails?.[0]?.count?.[0]?.total || 0,
|
|
1737
|
+
data: getStoreDetails?.[0]?.data || [],
|
|
1738
|
+
doubleFloorStores: floorDetails?.map( ( ele ) => ele.store ) || [],
|
|
1739
|
+
};
|
|
1740
|
+
let status = templateDetails.isEdited ? 'Yet to publish' : 'Published';
|
|
1741
|
+
result.data.forEach( ( ele ) => {
|
|
1742
|
+
ele.status = status;
|
|
1743
|
+
} );
|
|
1744
|
+
return res.sendSuccess( result );
|
|
1745
|
+
} catch ( e ) {
|
|
1746
|
+
logger.error( { functionName: 'getTemplateStoreList', error: e } );
|
|
1747
|
+
return res.sendError( e, 500 );
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
|
|
1751
|
+
export async function templateVersionList( req, res ) {
|
|
1752
|
+
try {
|
|
1753
|
+
if ( !req.query?.templateId ) {
|
|
1754
|
+
return res.sendError( 'Template id is required', 400 );
|
|
1755
|
+
}
|
|
1756
|
+
let configLogDetails = await templateLogService.find( { templateId: req.query.templateId }, {}, { _id: -1 } );
|
|
1757
|
+
if ( !configLogDetails.length ) {
|
|
1758
|
+
return res.sendError( 'NO data found', 204 );
|
|
1759
|
+
}
|
|
1760
|
+
return res.sendSuccess( configLogDetails );
|
|
1761
|
+
} catch ( e ) {
|
|
1762
|
+
logger.error( { functionName: 'templateVersionList', error: e } );
|
|
1763
|
+
return res.sendError( e, 500 );
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
|