Subversion Repositories SmartDukaan

Rev

Rev 37260 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 37260 Rev 37641
Line 114... Line 114...
114
    com.spice.profitmandi.web.services.SolrService webSolrService;
114
    com.spice.profitmandi.web.services.SolrService webSolrService;
115
 
115
 
116
    @Autowired
116
    @Autowired
117
    com.spice.profitmandi.web.services.HotDealEnrichmentService hotDealEnrichmentService;
117
    com.spice.profitmandi.web.services.HotDealEnrichmentService hotDealEnrichmentService;
118
 
118
 
119
    @Autowired
-
 
120
    com.spice.profitmandi.dao.repository.catalog.ModelHotDealRepository modelHotDealRepository;
-
 
121
 
119
 
122
    @Autowired
120
    @Autowired
123
    private com.spice.profitmandi.web.services.PartnerSolrClient partnerSolrClient;
121
    private com.spice.profitmandi.web.services.PartnerSolrClient partnerSolrClient;
124
 
122
 
125
    @Autowired
123
    @Autowired
Line 358... Line 356...
358
        params.put("q", StringUtils.join(mandatoryQ, " "));
356
        params.put("q", StringUtils.join(mandatoryQ, " "));
359
        params.put("fl", "*, [child parentFilter=id:catalog* childFilter=active_b:true ]");
357
        params.put("fl", "*, [child parentFilter=id:catalog* childFilter=active_b:true ]");
360
        params.put("wt", "json");
358
        params.put("wt", "json");
361
        params.put("rows", similarCatalogIds.size() + "");
359
        params.put("rows", similarCatalogIds.size() + "");
362
        JSONArray docs = partnerSolrClient.selectDocs(params, userInfo.getRetailerId());
360
        JSONArray docs = partnerSolrClient.selectDocs(params, userInfo.getRetailerId());
363
        return responseSender.ok(this.getCatalogResponse(docs, false, userInfo.getRetailerId()).stream().filter(x -> x.isInStock()).collect(Collectors.toList()));
361
        return responseSender.ok(this.getCatalogResponse(docs, userInfo.getRetailerId()).stream().filter(x -> x.isInStock()).collect(Collectors.toList()));
364
    }
362
    }
365
 
363
 
366
    @ApiImplicitParams({@ApiImplicitParam(name = "Auth-Token", value = "Auth-Token", required = true, dataType = "string", paramType = "header")})
364
    @ApiImplicitParams({@ApiImplicitParam(name = "Auth-Token", value = "Auth-Token", required = true, dataType = "string", paramType = "header")})
367
    /**
365
    /**
368
     * Categories present among today's active hot deals (Solr facet over the curated
366
     * Categories present among today's active hot deals (Solr facet over the curated
369
     * models), for the hot-deals page filter chips: [{"id": 3, "count": 4}, ...].
367
     * models), for the hot-deals page filter chips: [{"id": 3, "count": 4}, ...].
370
     */
368
     */
371
    @RequestMapping(value = "/fofo/hotDeals/categories", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
369
    @RequestMapping(value = "/fofo/hotDeals/categories", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
372
    public ResponseEntity<?> getHotDealCategories(HttpServletRequest request) throws Exception {
370
    public ResponseEntity<?> getHotDealCategories(HttpServletRequest request) throws Exception {
373
        List<Integer> hotDealCatalogIds = modelHotDealRepository.selectAllActive(java.time.LocalDate.now())
-
 
374
                .stream().map(com.spice.profitmandi.dao.entity.catalog.ModelHotDeal::getCatalogItemId)
-
 
375
                .distinct().collect(Collectors.toList());
-
 
376
        List<Map<String, Object>> categories = new ArrayList<>();
371
        List<Map<String, Object>> categories = new ArrayList<>();
-
 
372
        for (Map.Entry<Integer, Integer> entry
377
        for (Map.Entry<Integer, Integer> entry : solrService.getHotDealCategoryFacet(hotDealCatalogIds).entrySet()) {
373
                : solrService.getHotDealCategoryFacet(hotDealCatalogIds()).entrySet()) {
378
            Map<String, Object> category = new HashMap<>();
374
            Map<String, Object> category = new HashMap<>();
379
            category.put("id", entry.getKey());
375
            category.put("id", entry.getKey());
380
            category.put("count", entry.getValue());
376
            category.put("count", entry.getValue());
381
            categories.add(category);
377
            categories.add(category);
382
        }
378
        }
383
        return responseSender.ok(categories);
379
        return responseSender.ok(categories);
384
    }
380
    }
385
 
381
 
-
 
382
    /**
-
 
383
     * Brands present among the hot-deal models, for the hot-deals page brand chips:
-
 
384
     * [{"brand": "Samsung", "count": 4}, ...].
-
 
385
     *
-
 
386
     * <p>These are the ORIGINAL brands, held in Solr's oem_brand_s. Every hot-deal doc
-
 
387
     * reads "Hot Deal" in brand_ss, so that field would facet into one useless bucket.
-
 
388
     * The chip row is labelled simply "Brand" in both apps.
-
 
389
     */
-
 
390
    @RequestMapping(value = "/fofo/hotDeals/brands", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
-
 
391
    public ResponseEntity<?> getHotDealBrands(HttpServletRequest request) throws Exception {
-
 
392
        List<Map<String, Object>> brands = new ArrayList<>();
-
 
393
        for (Map.Entry<String, Integer> entry
-
 
394
                : solrService.getHotDealBrandFacet(hotDealCatalogIds()).entrySet()) {
-
 
395
            Map<String, Object> brand = new HashMap<>();
-
 
396
            brand.put("brand", entry.getKey());
-
 
397
            brand.put("count", entry.getValue());
-
 
398
            brands.add(brand);
-
 
399
        }
-
 
400
        return responseSender.ok(brands);
-
 
401
    }
-
 
402
 
-
 
403
    /**
-
 
404
     * The hot-deal catalog set: membership is brand membership, with no date window.
-
 
405
     * Shared by the two facet endpoints and the hotDeal listing branch.
-
 
406
     */
-
 
407
    private List<Integer> hotDealCatalogIds() {
-
 
408
        return new ArrayList<>(
-
 
409
                catalogRepository.selectCatalogIdsByBrand(ProfitMandiConstants.HOT_DEAL_BRAND));
-
 
410
    }
-
 
411
 
386
    @RequestMapping(value = "/fofo", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
412
    @RequestMapping(value = "/fofo", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
387
    public ResponseEntity<?> getFofo(HttpServletRequest request, @RequestParam(value = "categoryId", required = false, defaultValue = "3") String categoryId, @RequestParam(value = "offset") int offset,
413
    public ResponseEntity<?> getFofo(HttpServletRequest request, @RequestParam(value = "categoryId", required = false, defaultValue = "3") String categoryId, @RequestParam(value = "offset") int offset,
388
         @RequestParam(value = "limit") int limit, @RequestParam(value = "sort", required = false) String sort, @RequestParam(value = "brand", required = false) String brand, @RequestParam(value = "subCategoryId", required = false, defaultValue = "0") int subCategoryId, @RequestParam(value = "q", required = false) String queryTerm, @RequestParam(value = "hotDeal", required = false) boolean hotDeal, @RequestParam(value = "endPoint", required = false) String endPoint,@RequestParam(value = "group", required = false) boolean group) throws Throwable {
414
         @RequestParam(value = "limit") int limit, @RequestParam(value = "sort", required = false) String sort, @RequestParam(value = "brand", required = false) String brand, @RequestParam(value = "subCategoryId", required = false, defaultValue = "0") int subCategoryId, @RequestParam(value = "q", required = false) String queryTerm, @RequestParam(value = "hotDeal", required = false) boolean hotDeal, @RequestParam(value = "endPoint", required = false) String endPoint,@RequestParam(value = "group", required = false) boolean group) throws Throwable {
389
        // Band-aid for URL '+' decode issue on brand names.
415
        // Band-aid for URL '+' decode issue on brand names.
390
        // Front-end sends `brand=Ai+`. Depending on where along the request path the
416
        // Front-end sends `brand=Ai+`. Depending on where along the request path the
Line 421... Line 447...
421
        if (endPoint != null && !endPoint.trim().isEmpty()) {
447
        if (endPoint != null && !endPoint.trim().isEmpty()) {
422
            WebListing webListing = webListingRepository.selectByUrl(endPoint);
448
            WebListing webListing = webListingRepository.selectByUrl(endPoint);
423
            dealResponse = this.getDealResponses(userInfo, fs, webListing, offset, limit);
449
            dealResponse = this.getDealResponses(userInfo, fs, webListing, offset, limit);
424
 
450
 
425
        } else if (hotDeal) {
451
        } else if (hotDeal) {
426
            // Hot deals are sourced from catalog.model_hot_deal (date-windowed, curated);
452
            // Hot deals are the SKUs carrying the Hot Deal brand. Solr's hot_deal_b derives
427
            // Solr's hot_deal_b derives from the same table but is resolved here so the
453
            // from the same brand, but the set is resolved here so the listing does not
428
            // listing does not depend on the last re-index
454
            // depend on the last re-index.
429
            List<Integer> hotDealCatalogIds = modelHotDealRepository.selectAllActive(java.time.LocalDate.now())
455
            List<Integer> hotDealCatalogIds = hotDealCatalogIds();
430
                    .stream().map(com.spice.profitmandi.dao.entity.catalog.ModelHotDeal::getCatalogItemId)
-
 
431
                    .distinct().collect(Collectors.toList());
-
 
432
            if (hotDealCatalogIds.isEmpty()) {
456
            if (hotDealCatalogIds.isEmpty()) {
433
                dealResponse = new ArrayList<>();
457
                dealResponse = new ArrayList<>();
434
            } else {
458
            } else {
435
                // Cross-category by default; a category chip on the page sends categoryId
459
                // Cross-category by default; a category chip on the page sends categoryId
436
                // explicitly, and only then does it narrow the hot-deal listing
460
                // explicitly, and only then does it narrow the hot-deal listing
437
                String explicitCategory = request.getParameter("categoryId") != null ? categoryId : null;
461
                String explicitCategory = request.getParameter("categoryId") != null ? categoryId : null;
438
                dealResponse = this.getCatalogResponse(
462
                dealResponse = this.getCatalogResponse(
439
                        solrService.getSolrDocs(queryTerm, explicitCategory, offset, limit, sort, brand, subCategoryId, false, group, true,
463
                        solrService.getSolrDocs(queryTerm, explicitCategory, offset, limit, sort, brand, subCategoryId, false, group, true,
440
                                brandsService.restrictedBrands(userInfo.getRetailerId()), hotDealCatalogIds), false, userInfo.getRetailerId());
464
                                brandsService.restrictedBrands(userInfo.getRetailerId()), hotDealCatalogIds), userInfo.getRetailerId());
441
            }
465
            }
442
        } else {
466
        } else {
443
 
467
 
444
            dealResponse = this.getCatalogResponse(
468
            dealResponse = this.getCatalogResponse(
445
                    solrService.getSolrDocs(queryTerm, categoryId, offset, limit, sort, brand, subCategoryId, hotDeal, group, true,
469
                    solrService.getSolrDocs(queryTerm, categoryId, offset, limit, sort, brand, subCategoryId, hotDeal, group, true,
446
                            brandsService.restrictedBrands(userInfo.getRetailerId())), hotDeal, userInfo.getRetailerId());
470
                            brandsService.restrictedBrands(userInfo.getRetailerId())), userInfo.getRetailerId());
447
        }
471
        }
448
        hotDealEnrichmentService.enrich(dealResponse);
472
        hotDealEnrichmentService.enrich(dealResponse);
449
 
473
 
450
        Map<Integer, List<Integer>> similarModelMap = dealResponse.stream().filter(x -> x.getSimilarModelIds() != null && x.getSimilarModelIds().size() > 0)
474
        Map<Integer, List<Integer>> similarModelMap = dealResponse.stream().filter(x -> x.getSimilarModelIds() != null && x.getSimilarModelIds().size() > 0)
451
                .collect(Collectors.toMap(x -> x.getCatalogId(), x -> x.getSimilarModelIds()));
475
                .collect(Collectors.toMap(x -> x.getCatalogId(), x -> x.getSimilarModelIds()));
Line 694... Line 718...
694
            params.put("q", StringUtils.join(mandatoryQ, " "));
718
            params.put("q", StringUtils.join(mandatoryQ, " "));
695
            params.put("fl", "*, [child parentFilter=id:catalog*]");
719
            params.put("fl", "*, [child parentFilter=id:catalog*]");
696
            params.put("sort", "rank_i asc, create_s desc");
720
            params.put("sort", "rank_i asc, create_s desc");
697
            params.put("wt", "json");
721
            params.put("wt", "json");
698
            JSONArray docs = partnerSolrClient.selectDocs(params, userInfo.getRetailerId());
722
            JSONArray docs = partnerSolrClient.selectDocs(params, userInfo.getRetailerId());
699
            dealResponse = getCatalogResponse(docs, false, userInfo.getRetailerId());
723
            dealResponse = getCatalogResponse(docs, userInfo.getRetailerId());
700
        } else {
724
        } else {
701
            return responseSender.badRequest(
725
            return responseSender.badRequest(
702
                    new ProfitMandiBusinessException("Retailer id", userInfo.getUserId(), "NOT_FOFO_RETAILER"));
726
                    new ProfitMandiBusinessException("Retailer id", userInfo.getUserId(), "NOT_FOFO_RETAILER"));
703
        }
727
        }
704
        if (dealResponse.isEmpty()) {
728
        if (dealResponse.isEmpty()) {
Line 914... Line 938...
914
            JSONArray docs = docsByListing.get(i);
938
            JSONArray docs = docsByListing.get(i);
915
            List<FofoCatalogResponse> dealResponse;
939
            List<FofoCatalogResponse> dealResponse;
916
            if (docs == null || batch == null) {
940
            if (docs == null || batch == null) {
917
                dealResponse = new ArrayList<>();
941
                dealResponse = new ArrayList<>();
918
            } else {
942
            } else {
919
                dealResponse = buildCatalogResponses(docs, false, fofoId, batch);
943
                dealResponse = buildCatalogResponses(docs, fofoId, batch);
920
                if (query.webProducts != null && query.webListing.getUrl().equals("new-launches")) {
944
                if (query.webProducts != null && query.webListing.getUrl().equals("new-launches")) {
921
                    List<Integer> webProductsFinal = query.webProducts;
945
                    List<Integer> webProductsFinal = query.webProducts;
922
                    dealResponse = dealResponse.stream().sorted(Comparator.comparing(x -> webProductsFinal.indexOf(x.getCatalogId()))).collect(Collectors.toList());
946
                    dealResponse = dealResponse.stream().sorted(Comparator.comparing(x -> webProductsFinal.indexOf(x.getCatalogId()))).collect(Collectors.toList());
923
                }
947
                }
924
            }
948
            }
Line 931... Line 955...
931
        ListingQuery query = buildListingQuery(webListing, fs.getWarehouseId(), offset, limit);
955
        ListingQuery query = buildListingQuery(webListing, fs.getWarehouseId(), offset, limit);
932
        if (query.params == null) {
956
        if (query.params == null) {
933
            return new ArrayList<>();
957
            return new ArrayList<>();
934
        }
958
        }
935
        JSONArray docs = partnerSolrClient.selectDocs(query.params, userInfo.getRetailerId());
959
        JSONArray docs = partnerSolrClient.selectDocs(query.params, userInfo.getRetailerId());
936
        List<FofoCatalogResponse> dealResponse = getCatalogResponse(docs, false, userInfo.getRetailerId());
960
        List<FofoCatalogResponse> dealResponse = getCatalogResponse(docs, userInfo.getRetailerId());
937
 
961
 
938
        if (query.webProducts != null && webListing.getUrl().equals("new-launches")) {
962
        if (query.webProducts != null && webListing.getUrl().equals("new-launches")) {
939
            List<Integer> webProductsFinal = query.webProducts;
963
            List<Integer> webProductsFinal = query.webProducts;
940
            dealResponse = dealResponse.stream().sorted(Comparator.comparing(x -> webProductsFinal.indexOf(x.getCatalogId()))).collect(Collectors.toList());
964
            dealResponse = dealResponse.stream().sorted(Comparator.comparing(x -> webProductsFinal.indexOf(x.getCatalogId()))).collect(Collectors.toList());
941
        }
965
        }
Line 981... Line 1005...
981
    }
1005
    }
982
 
1006
 
983
    @Autowired
1007
    @Autowired
984
    private SaholicCISTableRepository saholicCISTableRepository;
1008
    private SaholicCISTableRepository saholicCISTableRepository;
985
 
1009
 
986
    private List<FofoCatalogResponse> getCatalogResponse(JSONArray docs, boolean hotDeal, int fofoId) throws Exception {
1010
    private List<FofoCatalogResponse> getCatalogResponse(JSONArray docs, int fofoId) throws Exception {
987
        List<Integer> itemIds = extractItemIds(docs);
1011
        List<Integer> itemIds = extractItemIds(docs);
988
        if (itemIds.isEmpty()) {
1012
        if (itemIds.isEmpty()) {
989
            return new ArrayList<>();
1013
            return new ArrayList<>();
990
        }
1014
        }
991
        int warehouseId = fofoStoreRepository.selectByRetailerId(fofoId).getWarehouseId();
1015
        int warehouseId = fofoStoreRepository.selectByRetailerId(fofoId).getWarehouseId();
992
        CatalogBatchData batch = buildCatalogBatchData(fofoId, warehouseId, extractCatalogIds(docs), itemIds);
1016
        CatalogBatchData batch = buildCatalogBatchData(fofoId, warehouseId, extractCatalogIds(docs), itemIds);
993
        return buildCatalogResponses(docs, hotDeal, fofoId, batch);
1017
        return buildCatalogResponses(docs, fofoId, batch);
994
    }
1018
    }
995
 
1019
 
996
    private List<Integer> extractItemIds(JSONArray docs) {
1020
    private List<Integer> extractItemIds(JSONArray docs) {
997
        List<Integer> itemIds = new ArrayList<>();
1021
        List<Integer> itemIds = new ArrayList<>();
998
        for (int i = 0; i < docs.length(); i++) {
1022
        for (int i = 0; i < docs.length(); i++) {
Line 1088... Line 1112...
1088
        batch.comboModelsByCatalogId = comboModelRepository.selectByWarehouseId(warehouseId)
1112
        batch.comboModelsByCatalogId = comboModelRepository.selectByWarehouseId(warehouseId)
1089
                .stream().collect(Collectors.groupingBy(ComboModel::getCatalogId));
1113
                .stream().collect(Collectors.groupingBy(ComboModel::getCatalogId));
1090
        return batch;
1114
        return batch;
1091
    }
1115
    }
1092
 
1116
 
1093
    private List<FofoCatalogResponse> buildCatalogResponses(JSONArray docs, boolean hotDeal, int fofoId, CatalogBatchData batch) throws Exception {
1117
    private List<FofoCatalogResponse> buildCatalogResponses(JSONArray docs, int fofoId, CatalogBatchData batch) throws Exception {
1094
        List<FofoCatalogResponse> dealResponse = new ArrayList<>();
1118
        List<FofoCatalogResponse> dealResponse = new ArrayList<>();
1095
        int warehouseId = batch.warehouseId;
1119
        int warehouseId = batch.warehouseId;
1096
        Map<Integer, List<SaholicPOItem>> poItemAvailabilityMap = batch.poItemAvailabilityMap;
1120
        Map<Integer, List<SaholicPOItem>> poItemAvailabilityMap = batch.poItemAvailabilityMap;
1097
        Map<Integer, Integer> partnerStockAvailabilityMap = batch.partnerStockAvailabilityMap;
1121
        Map<Integer, Integer> partnerStockAvailabilityMap = batch.partnerStockAvailabilityMap;
1098
        Set<Integer> favouriteCatalogIds = batch.favouriteCatalogIds;
1122
        Set<Integer> favouriteCatalogIds = batch.favouriteCatalogIds;
Line 1245... Line 1269...
1245
                        fdi.setCatalog_id(doc.getInt("catalogId_i"));
1269
                        fdi.setCatalog_id(doc.getInt("catalogId_i"));
1246
                        Float cashBack = cashbackMap.get(fofoCatalogResponse.getCatalogId());
1270
                        Float cashBack = cashbackMap.get(fofoCatalogResponse.getCatalogId());
1247
                        cashBack = cashBack == null ? 0 : cashBack;
1271
                        cashBack = cashBack == null ? 0 : cashBack;
1248
                        fdi.setCashback(cashBack);
1272
                        fdi.setCashback(cashBack);
1249
                        fdi.setMinBuyQuantity(1);
1273
                        fdi.setMinBuyQuantity(1);
1250
                        if (hotDeal) {
-
 
1251
                            if (currentAvailability != null) {
1274
                        // Real availability on every listing.
1252
                                fdi.setAvailability(currentAvailability.stream().collect(Collectors.summingInt(SaholicCISTable::getNetAvailability)));
-
 
1253
                            } else {
1275
                        //
1254
                                fdi.setAvailability(0);
1276
                        // This used to branch on the hotDeal flag (r32339, 2023): hot deals
1255
                            }
1277
                        // got real stock, everything else a hardcoded 400. Since 400 is the
1256
                            fdi.setPartnerAvailability(partnerAvailability);
1278
                        // max-quantity cap rather than zero, the effect was the opposite of
1257
                        } else {
1279
                        // the old "out of stock" comment - a partner could order 400 of a SKU
1258
                            // Lets consider that its out of stock
1280
                        // with none in stock, and the app's out-of-stock and over-order
1259
                            fdi.setAvailability(400);
1281
                        // warnings (which test availability == 0 and quantity > availability)
1260
                            Item item = itemMap.get(itemId);
1282
                        // could never fire outside hot deals.
1261
                            // In case its tampered glass moq should be
1283
                        //
1262
                            if (item != null && item.getCategoryId() == 10020) {
1284
                        // The data was always there: cisDataByItemId is built on every call.
1263
                                fdi.setMinBuyQuantity(5);
1285
                        fdi.setAvailability(currentAvailability.stream()
1264
                            }
1286
                                .collect(Collectors.summingInt(SaholicCISTable::getNetAvailability)));
1265
                        }
1287
                        fdi.setPartnerAvailability(partnerAvailability);
1266
                        fdi.setQuantityStep(1);
1288
                        fdi.setQuantityStep(1);
-
 
1289
                        // Partners can always order up to 10, so a zero-stock model can
-
 
1290
                        // still be indented ahead of supply; beyond that the cap follows
-
 
1291
                        // real stock, up to 400.
1267
                        fdi.setMaxQuantity(Math.min(fdi.getAvailability(), 400));
1292
                        fdi.setMaxQuantity(Math.min(Math.max(fdi.getAvailability(), 10), 400));
1268
                        fofoAvailabilityInfoMap.put(itemId, fdi);
1293
                        fofoAvailabilityInfoMap.put(itemId, fdi);
1269
                    }
1294
                    }
1270
                }
1295
                }
1271
                if (fdiAnyColour != null) {
1296
                if (fdiAnyColour != null) {
1272
                    fdiAnyColour.setColorClass(modelColorClass);
1297
                    fdiAnyColour.setColorClass(modelColorClass);