Subversion Repositories SmartDukaan

Rev

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

Rev 35458 Rev 35980
Line 17... Line 17...
17
import com.spice.profitmandi.dao.repository.scratch.SeasonalOfferRepository;
17
import com.spice.profitmandi.dao.repository.scratch.SeasonalOfferRepository;
18
import org.apache.logging.log4j.LogManager;
18
import org.apache.logging.log4j.LogManager;
19
import org.apache.logging.log4j.Logger;
19
import org.apache.logging.log4j.Logger;
20
import org.springframework.beans.factory.annotation.Autowired;
20
import org.springframework.beans.factory.annotation.Autowired;
21
import org.springframework.stereotype.Service;
21
import org.springframework.stereotype.Service;
22
import org.springframework.transaction.annotation.Transactional;
-
 
23
 
22
 
24
import java.time.LocalDate;
23
import java.time.LocalDate;
25
import java.time.LocalDateTime;
24
import java.time.LocalDateTime;
26
import java.time.LocalTime;
25
import java.time.LocalTime;
27
import java.util.*;
26
import java.util.*;
Line 44... Line 43...
44
    @Autowired
43
    @Autowired
45
    FofoOrderRepository fofoOrderRepository;
44
    FofoOrderRepository fofoOrderRepository;
46
 
45
 
47
 
46
 
48
    public void processScratchOffer(int fofoOrderId, Set<CustomPaymentOption> paymentOptions, Set<Integer> fofoOrderItemIds) throws ProfitMandiBusinessException {
47
    public void processScratchOffer(int fofoOrderId, Set<CustomPaymentOption> paymentOptions, Set<Integer> fofoOrderItemIds) throws ProfitMandiBusinessException {
49
        FofoOrder fofoOrder = fofoOrderRepository.selectByOrderId(fofoOrderId);
-
 
50
        logger.info("Starting scratchOffer for order: {}", fofoOrder);
-
 
51
        LocalDate today = LocalDate.now();
-
 
52
        for (Integer orderItemId : fofoOrderItemIds) {
-
 
53
            logger.info("Processing order item: {}", orderItemId);
-
 
54
            Item item = this.getItemById(orderItemId);
-
 
55
            Integer itemCategoryId = item.getCategoryId();
-
 
56
            logger.info("Item category ID: {}", itemCategoryId);
-
 
57
            // Find active offer
-
 
58
            List<OfferEntity> activeOffers = seasonalOfferRepository.getOffersByDate(today);
48
        List<OfferEntity> activeOffers = seasonalOfferRepository.getOffersByDate(LocalDate.now());
59
            logger.info("Found Active offer: {}", activeOffers);
-
 
60
            OfferEntity eligibleOffer = FindEligibleOffer(activeOffers, fofoOrder);
-
 
61
//            Set<String> allowedPaymentMethods = Arrays.stream(eligibleOffer.getPaymentMethod().split(","))
-
 
62
//                    .collect(Collectors.toSet());
-
 
63
//
-
 
64
//            boolean isOtherPaymentUsed = paymentOptions.stream()
-
 
65
//                    .map(option -> String.valueOf(option.getPaymentOptionId()))
-
 
66
//                    .anyMatch(paymentId -> !allowedPaymentMethods.contains(paymentId));
-
 
67
//            // proceed with default because user payment method doest not match
-
 
68
//            if (isOtherPaymentUsed) {
49
        if (activeOffers.isEmpty()) {
69
//                logger.info("Customer {} has chosen a different mode of payment.", fofoOrder.getCustomerId());
-
 
70
//                return;
50
            return;
71
//            }
51
        }
72
            if (eligibleOffer != null) {
-
 
73
                logger.info("Found active offer: {}", eligibleOffer.getId());
-
 
74
                Integer activeOfferId = eligibleOffer.getId();
-
 
75
                logger.info
-
 
76
                        ("Active offer ID: {}, Type: {}", activeOfferId, eligibleOffer.getName());
-
 
77
                ScratchOffer availedOffer = scratchOfferRepository.getScractchOfferByCustomerIdAndOfferId(fofoOrder.getCustomerId(), activeOfferId);
-
 
78
 
-
 
79
                if (availedOffer != null) {
-
 
80
                    logger.info("Customer {} has already scratched offer ID {}. No new gift will be allotted.", fofoOrder.getCustomerId(), activeOfferId);
-
 
81
                    return;
-
 
82
                }
-
 
83
 
52
 
84
                if (this.processOffer(eligibleOffer, fofoOrder, itemCategoryId)) {
53
        FofoOrder fofoOrder = fofoOrderRepository.selectByOrderId(fofoOrderId);
85
                    logger.info("Successfully processed offer for item: {}", orderItemId);
54
        OfferEntity eligibleOffer = findEligibleOffer(activeOffers, fofoOrder);
86
                    break;
-
 
87
                } else {
55
        if (eligibleOffer == null) {
88
                    logger.info("Failed to process offer for item: {}", orderItemId);
56
            logger.info("No eligible offer for order {}", fofoOrderId);
89
                }
-
 
90
            } else {
57
            return;
91
                logger.info("No active offers found for today: {}", today);
-
 
92
            }
58
        }
93
 
59
 
-
 
60
        ScratchOffer availedOffer = scratchOfferRepository.getScractchOfferByCustomerIdAndOfferId(fofoOrder.getCustomerId(), eligibleOffer.getId());
-
 
61
        if (availedOffer != null) {
94
            logger.info("No eligible gifts found for any items in order: {}", fofoOrder.getId());
62
            logger.info("Customer {} already availed offer {}", fofoOrder.getCustomerId(), eligibleOffer.getId());
95
            return;
63
            return;
96
        }
64
        }
97
 
65
 
98
        logger.info("No eligible gifts found for any items in order: {}", fofoOrder.getId());
66
        this.processOffer(eligibleOffer, fofoOrder);
99
    }
67
    }
100
 
68
 
101
    private OfferEntity FindEligibleOffer(List<OfferEntity> activeOffers, FofoOrder fofoOrder) {
69
    private OfferEntity findEligibleOffer(List<OfferEntity> activeOffers, FofoOrder fofoOrder) {
102
        int customerFofoId = fofoOrder.getFofoId();
70
        int customerFofoId = fofoOrder.getFofoId();
103
        logger.info("Looking for eligible offer for customer fofoId: {}", customerFofoId);
-
 
104
        logger.info("Total active offers to check: {}", activeOffers.size());
-
 
105
 
71
 
-
 
72
        // Check PartnerWise offers first
106
        for (OfferEntity activeOffer : activeOffers) {
73
        for (OfferEntity activeOffer : activeOffers) {
107
            logger.info("Checking offer ID: {} with classification: {}", activeOffer.getId(), activeOffer.getClassification());
-
 
108
 
-
 
109
            if ("PartnerWise".equals(activeOffer.getClassification())) {
74
            if (!"PartnerWise".equals(activeOffer.getClassification())) {
-
 
75
                continue;
-
 
76
            }
110
                List<GiftEntity> gifts = giftRepository.findByOfferId(activeOffer.getId());
77
            List<GiftEntity> gifts = giftRepository.findByOfferId(activeOffer.getId());
111
                logger.info("Found {} gifts for PartnerWise offer {}", gifts.size(), activeOffer.getId());
-
 
112
 
-
 
113
                if (gifts.isEmpty()) {
78
            for (GiftEntity gift : gifts) {
114
                    logger.warn("No gifts found for PartnerWise offer {}", activeOffer.getId());
79
                if (gift.getFofoStore() == null || gift.getFofoStore().trim().isEmpty()) {
115
                    continue;
80
                    continue;
116
                }
81
                }
117
 
-
 
118
                for (GiftEntity gift : gifts) {
-
 
119
                    logger.info("Checking gift ID: {} with fofoStore: '{}'", gift.getId(), gift.getFofoStore());
-
 
120
 
-
 
121
                    if (gift.getFofoStore() == null || gift.getFofoStore().trim().isEmpty()) {
82
                boolean matches = Arrays.stream(gift.getFofoStore().split(","))
122
                        logger.warn("Gift {} has null/empty fofoStore - skipping", gift.getId());
-
 
123
                        continue;
83
                        .map(String::trim)
124
                    }
-
 
125
 
-
 
126
                    String[] fofoStores = gift.getFofoStore().split(",");
-
 
127
                    logger.info("Gift {} fofoStores array: {}", gift.getId(), Arrays.toString(fofoStores));
-
 
128
 
-
 
129
                    boolean isEligible = Arrays.stream(fofoStores)
-
 
130
                            .filter(store -> !store.trim().isEmpty())
84
                        .filter(s -> !s.isEmpty())
131
                            .map(store -> {
85
                        .anyMatch(store -> {
132
                                try {
86
                            try {
133
                                    int storeId = Integer.parseInt(store.trim());
87
                                return Integer.parseInt(store) == customerFofoId;
134
                                    logger.info("Parsed fofoStore: {} (comparing with customer fofoId: {})", storeId, customerFofoId);
-
 
135
                                    return storeId;
-
 
136
                                } catch (NumberFormatException e) {
88
                            } catch (NumberFormatException e) {
137
                                    logger.warn("Invalid fofoId format in gift {}: '{}' - skipping", gift.getId(), store);
-
 
138
                                    return -1;
89
                                return false;
139
                                }
-
 
140
                            })
90
                            }
141
                            .anyMatch(fofoStore -> {
-
 
142
                                boolean matches = fofoStore == customerFofoId;
-
 
143
                                logger.info("FofoStore {} matches customer fofoId {}: {}", fofoStore, customerFofoId, matches);
-
 
144
                                return matches;
-
 
145
                            });
91
                        });
146
 
-
 
147
                    logger.info("Gift {} is eligible for customer fofoId {}: {}", gift.getId(), customerFofoId, isEligible);
-
 
148
 
-
 
149
                    if (isEligible) {
92
                if (matches) {
150
                        logger.info("Found matching PartnerWise offer: {} for customer fofoId: {}", activeOffer.getId(), customerFofoId);
-
 
151
                        return activeOffer;
93
                    return activeOffer;
152
                    }
-
 
153
                }
94
                }
154
                logger.info("No matching gifts found in PartnerWise offer {} for customer fofoId: {}", activeOffer.getId(), customerFofoId);
-
 
155
            } else {
-
 
156
                logger.info("Offer {} is not PartnerWise (classification: {})", activeOffer.getId(), activeOffer.getClassification());
-
 
157
            }
95
            }
158
        }
96
        }
159
 
97
 
160
        logger.info("No PartnerWise offers matched. Looking for non-PartnerWise offers...");
98
        // Fallback to first non-PartnerWise offer
161
 
-
 
162
        List<OfferEntity> nonPartnerWiseOffers = activeOffers.stream()
99
        return activeOffers.stream()
163
                .filter(offer -> !"PartnerWise".equals(offer.getClassification()))
100
                .filter(offer -> !"PartnerWise".equals(offer.getClassification()))
164
                .collect(Collectors.toList());
101
                .findFirst()
165
 
-
 
166
        logger.info("Found {} non-PartnerWise offers", nonPartnerWiseOffers.size());
-
 
167
 
-
 
168
        OfferEntity selectedOffer = nonPartnerWiseOffers.stream().findFirst().orElse(null);
-
 
169
 
-
 
170
        if (selectedOffer != null) {
102
                .orElse(null);
171
            logger.info("Selected non-PartnerWise offer: {}", selectedOffer.getId());
-
 
172
        } else {
-
 
173
            logger.info("No eligible offers found for customer fofoId: {}", customerFofoId);
-
 
174
        }
-
 
175
 
-
 
176
        return selectedOffer;
-
 
177
    }
103
    }
178
 
104
 
179
 
105
 
180
    private Item getItemById(Integer itemId) throws ProfitMandiBusinessException {
-
 
181
        logger.info("Getting item by ID: {}", itemId);
-
 
182
        Item item = itemRepository.selectById(itemId);
-
 
183
        if (item == null) {
-
 
184
            logger.warn("Item not found with ID: {}", itemId);
-
 
185
        }
-
 
186
        return item;
-
 
187
    }
-
 
188
 
-
 
189
    private boolean checkGiftAvailability(LocalDate date, int perDayMaxQty, OfferEntity offer) {
106
    private boolean checkGiftAvailability(LocalDate date, int perDayMaxQty, OfferEntity offer) {
190
        int defaultGiftId = giftRepository.getDefaultGift(offer.getId()).getId();
107
        GiftEntity defaultGift = giftRepository.getDefaultGift(offer.getId());
-
 
108
        if (defaultGift == null) return false;
191
        Integer giftCounts = scratchOfferRepository.countTodaysGiftDistribution(date.atStartOfDay(), date.atTime(LocalTime.MAX), defaultGiftId);
109
        Integer giftCounts = scratchOfferRepository.countTodaysGiftDistribution(date.atStartOfDay(), date.atTime(LocalTime.MAX), defaultGift.getId());
192
        return giftCounts < perDayMaxQty;
110
        return giftCounts < perDayMaxQty;
193
    }
111
    }
194
 
112
 
195
    private boolean isAppleItem(FofoOrder fofoOrder) {
113
    private boolean isAppleItem(FofoOrder fofoOrder) {
196
        List<FofoOrderItem> fofoOrderItems = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());
114
        List<FofoOrderItem> fofoOrderItems = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());
197
        if (fofoOrderItems == null || fofoOrderItems.isEmpty()) {
115
        if (fofoOrderItems == null || fofoOrderItems.isEmpty()) {
198
            return false;
116
            return false;
199
        }
117
        }
200
        for (FofoOrderItem item : fofoOrderItems) {
118
        return fofoOrderItems.stream()
201
            if (item != null && item.getBrand() != null && item.getBrand().equalsIgnoreCase("apple")) {
119
                .anyMatch(item -> item != null && "apple".equalsIgnoreCase(item.getBrand()));
202
                return true;
-
 
203
            }
-
 
204
        }
-
 
205
        return false;
-
 
206
    }
120
    }
-
 
121
 
207
    private boolean processOffer(OfferEntity offer, FofoOrder fofoOrder, Integer itemCategoryId) {
122
    private boolean processOffer(OfferEntity offer, FofoOrder fofoOrder) {
208
        List<GiftEntity> allGifts = giftRepository.findNonDefaultGIft(offer.getId());
-
 
209
        logger.info("Processing offer {} for order {}", offer.getId(), fofoOrder.getId());
123
        logger.info("Processing offer {} for order {}", offer.getId(), fofoOrder.getId());
-
 
124
 
-
 
125
        List<GiftEntity> allGifts = giftRepository.findNonDefaultGIft(offer.getId());
-
 
126
        GiftEntity defaultGift = giftRepository.getDefaultGift(offer.getId());
-
 
127
 
-
 
128
        if (allGifts.isEmpty()) {
-
 
129
            logger.warn("Offer {} has no gifts", offer.getId());
-
 
130
            return false;
-
 
131
        }
-
 
132
 
-
 
133
        // Apple items always get the last gift
210
        if (isAppleItem(fofoOrder)) {
134
        if (isAppleItem(fofoOrder)) {
211
            GiftEntity lastGift = allGifts.get(allGifts.size() - 1);
135
            GiftEntity lastGift = allGifts.get(allGifts.size() - 1);
212
            if (lastGift.getMaxRedemptions() > 0) {
136
            if (lastGift.getMaxRedemptions() > 0) {
213
                createScratchOffer(fofoOrder, offer, lastGift);
137
                createScratchOffer(fofoOrder, offer, lastGift);
214
                logger.info("Apple item detected, assigned last gift: {}", lastGift.getName());
-
 
215
            } else {
138
            } else {
216
                logger.info("Apple last gift exhausted, assigning Better Luck Next Time");
-
 
217
                createBetterLuckNextTimeScratch(fofoOrder, offer);
139
                createBetterLuckNextTimeScratch(fofoOrder, offer);
218
            }
140
            }
219
            return true;
141
            return true;
220
        }
142
        }
221
        int perDayMaxQty = offer.getUserLimit();
-
 
222
        LocalDate today = LocalDate.now();
-
 
223
        boolean isMoreGiftAvailable = checkGiftAvailability(today, perDayMaxQty, offer);
-
 
224
        logger.info("Gift availability result: {}", isMoreGiftAvailable);
-
 
225
 
143
 
226
        if (allGifts.isEmpty()) {
-
 
227
            logger.warn("Offer {} has no gifts - cannot process scratch offer", offer.getId());
-
 
228
            return false;
144
        // Check daily limit
229
        }
-
 
230
        if (!isMoreGiftAvailable) {
-
 
231
            logger.info("Daily limit reached - assigning default gift");
145
        if (!checkGiftAvailability(LocalDate.now(), offer.getUserLimit(), offer)) {
232
            createDefaultGiftScratch(fofoOrder, offer, giftRepository.getDefaultGift(offer.getId()));
146
            createDefaultGiftScratch(fofoOrder, offer, defaultGift);
233
            return true;
147
            return true;
234
        }
148
        }
-
 
149
 
-
 
150
        // Find eligible gifts by cart value and category
-
 
151
        List<FofoOrderItem> orderItems = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());
-
 
152
        Set<Integer> itemCategoryIds = new HashSet<>();
-
 
153
        for (FofoOrderItem orderItem : orderItems) {
-
 
154
            try {
-
 
155
                Item item = itemRepository.selectById(orderItem.getItemId());
235
        // Get eligible gifts
156
                if (item != null) {
-
 
157
                    itemCategoryIds.add(item.getCategoryId());
-
 
158
                }
-
 
159
            } catch (ProfitMandiBusinessException e) {
-
 
160
                logger.warn("Item {} not found", orderItem.getItemId());
-
 
161
            }
-
 
162
        }
-
 
163
 
-
 
164
        float totalAmount = fofoOrder.getTotalAmount();
-
 
165
        List<GiftEntity> allOfferGifts = giftRepository.findByOfferId(offer.getId());
236
        List<GiftEntity> eligibleGifts = findEligibleGifts(offer, fofoOrder, itemCategoryId);
166
        List<GiftEntity> eligibleGifts = allOfferGifts.stream()
-
 
167
                .filter(gift -> gift.getMaxRedemptions() > 0
-
 
168
                        && totalAmount >= gift.getMinCartValue()
-
 
169
                        && totalAmount <= gift.getMaxCartValue()
-
 
170
                        && itemCategoryIds.stream().anyMatch(catId -> isItemCategoryEligible(gift.getProductCategory(), catId)))
-
 
171
                .collect(Collectors.toList());
-
 
172
 
237
        if (eligibleGifts.isEmpty()) {
173
        if (eligibleGifts.isEmpty()) {
238
            logger.info("No eligible gifts found for offer: {}", offer.getId());
-
 
239
            createDefaultGiftScratch(fofoOrder, offer, giftRepository.getDefaultGift(offer.getId()));
174
            createDefaultGiftScratch(fofoOrder, offer, defaultGift);
240
            return true;
175
            return true;
241
        }
176
        }
242
 
177
 
243
        logger.info("Found {} eligible gifts for offer {}", eligibleGifts.size(), offer.getId());
-
 
244
 
-
 
245
        // Select gift based on classification
-
 
246
        GiftEntity selectedGift = selectGiftByClassification(offer, eligibleGifts, fofoOrder);
178
        GiftEntity selectedGift = selectGiftByClassification(offer, eligibleGifts, fofoOrder);
247
 
-
 
248
        if (selectedGift == null || selectedGift.getMaxRedemptions() <= 0) {
179
        if (selectedGift == null || selectedGift.getMaxRedemptions() <= 0) {
249
            logger.info("No valid gift selected for offer: {}", offer.getId());
-
 
250
            createScratchOffer(fofoOrder, offer, allGifts.get(0));
180
            createDefaultGiftScratch(fofoOrder, offer, defaultGift);
251
            return true;
181
            return true;
252
        }
182
        }
253
 
183
 
254
        logger.info("Selected gift: {} for order: {}", selectedGift.getId(), fofoOrder.getId());
-
 
255
 
-
 
256
        // Create scratch offer
-
 
257
        createScratchOffer(fofoOrder, offer, selectedGift);
184
        createScratchOffer(fofoOrder, offer, selectedGift);
258
        logger.info("Created scratch offer for order: {}", fofoOrder.getId());
-
 
259
        return true;
185
        return true;
260
    }
186
    }
261
 
187
 
262
 
188
 
263
    private List<GiftEntity> findEligibleGifts(OfferEntity offer, FofoOrder fofoOrder, Integer itemCategoryId) {
-
 
264
        logger.info("Finding eligible gifts for offer: {} and category: {}", offer.getId(), itemCategoryId);
-
 
265
        List<GiftEntity> activeOfferGifts = giftRepository.findByOfferId(offer.getId());
-
 
266
        logger.info("Total gifts for offer {}: {}", offer.getId(), activeOfferGifts.size());
-
 
267
 
-
 
268
        float totalAmount = fofoOrder.getTotalAmount();
-
 
269
        logger.info("Order total amount: {}", totalAmount);
-
 
270
 
-
 
271
 
-
 
272
        List<GiftEntity> eligibleGifts = activeOfferGifts.stream().filter(gift -> isGiftEligible(gift, totalAmount, itemCategoryId)).collect(Collectors.toList());
-
 
273
 
-
 
274
        logger.info("Filtered to {} eligible gifts", eligibleGifts.size());
-
 
275
 
-
 
276
        for (GiftEntity gift : activeOfferGifts) {
-
 
277
            boolean isEligible = isGiftEligible(gift, totalAmount, itemCategoryId);
-
 
278
            logger.info("Gift ID: {}, Name: {}, MinCart: {}, MaxCart: {}, Categories: {}, MaxRedemptions: {}, Eligible: {}",
-
 
279
                    gift.getId(), gift.getName(), gift.getMinCartValue(), gift.getMaxCartValue(),
-
 
280
                    gift.getProductCategory(), gift.getMaxRedemptions(), isEligible);
-
 
281
        }
-
 
282
        return eligibleGifts;
-
 
283
    }
-
 
284
 
-
 
285
    private boolean isGiftEligible(GiftEntity gift, float totalAmount, Integer itemCategoryId) {
-
 
286
        logger.info("Checking eligibility for gift: {}", gift.getId());
-
 
287
        // Check cart value condition
-
 
288
        boolean cartValueCondition = totalAmount >= gift.getMinCartValue() && totalAmount <= gift.getMaxCartValue() && gift.getMaxRedemptions() > 0;
-
 
289
        logger.info(
-
 
290
                "Gift {} cart value condition: {} (order amount: {}, min: {}, max: {}, max redemptions: {})",
-
 
291
                gift.getId(), cartValueCondition, totalAmount,
-
 
292
                gift.getMinCartValue(), gift.getMaxCartValue(),
-
 
293
                gift.getMaxRedemptions());
-
 
294
        // Check category condition
-
 
295
        boolean categoryCondition = isItemCategoryEligible(gift.getProductCategory(), itemCategoryId);
-
 
296
        logger.info
-
 
297
                ("Gift {} category condition: {} (item category: {}, gift categories: {})", gift.getId(), categoryCondition, itemCategoryId, gift.getProductCategory());
-
 
298
        boolean isEligible = cartValueCondition && categoryCondition;
-
 
299
        logger.info
-
 
300
                ("Gift {} is eligible: {}", gift.getId(), isEligible);
-
 
301
 
-
 
302
        return isEligible;
-
 
303
    }
-
 
304
 
-
 
305
    private boolean isItemCategoryEligible(String giftCategories, Integer itemCategoryId) {
189
    private boolean isItemCategoryEligible(String giftCategories, Integer itemCategoryId) {
306
        logger.info
-
 
307
                ("Checking if item category {} is in gift categories: {}", itemCategoryId, giftCategories);
-
 
308
 
-
 
309
 
-
 
310
        if (giftCategories == null || giftCategories.trim().isEmpty()) {
190
        if (giftCategories == null || giftCategories.trim().isEmpty()) {
311
            return false;
191
            return false;
312
        }
192
        }
313
 
-
 
314
        return Arrays.stream(giftCategories.split(","))
193
        return Arrays.stream(giftCategories.split(","))
-
 
194
                .map(String::trim)
315
                .filter(category -> !category.trim().isEmpty()) // Filter out empty strings
195
                .filter(s -> !s.isEmpty())
316
                .map(category -> {
196
                .map(category -> {
317
                    try {
197
                    try {
318
                        return Integer.parseInt(category.trim());
198
                        return Integer.parseInt(category);
319
                    } catch (NumberFormatException e) {
199
                    } catch (NumberFormatException e) {
320
                        logger.warn("Invalid category format in gift categories: {}", category);
-
 
321
                        return -1;
200
                        return -1;
322
                    }
201
                    }
323
                })
202
                })
324
                .anyMatch(itemCategoryId::equals);
203
                .anyMatch(itemCategoryId::equals);
325
    }
204
    }
326
 
205
 
327
    private GiftEntity selectGiftByClassification(OfferEntity offer, List<GiftEntity> eligibleGifts, FofoOrder fofoOrder) {
206
    private GiftEntity selectGiftByClassification(OfferEntity offer, List<GiftEntity> eligibleGifts, FofoOrder fofoOrder) {
328
        String classification = offer.getClassification();
-
 
329
        logger.info("Selecting gift by classification: {}", classification);
-
 
330
 
-
 
331
        GiftEntity selectedGift;
-
 
332
        switch (classification) {
207
        switch (offer.getClassification()) {
333
            case "Serial":
208
            case "Serial":
334
                logger.info("Using Serial gift selection strategy");
-
 
335
                selectedGift = handleSerialGifts(eligibleGifts);
209
                return eligibleGifts.get(0);
336
                break;
-
 
337
            case "Random":
210
            case "Random":
338
                logger.info("Using Random gift selection strategy");
211
                List<GiftEntity> shuffled = new ArrayList<>(eligibleGifts);
339
                selectedGift = handleRandomGifts(eligibleGifts);
212
                Collections.shuffle(shuffled);
340
                break;
213
                return shuffled.get(0);
341
            case "PartnerWise":
214
            case "PartnerWise":
-
 
215
                int fofoId = fofoOrder.getFofoId();
-
 
216
                return eligibleGifts.stream()
342
                logger.info("Using PartnerWise gift selection strategy");
217
                        .filter(gift -> gift.getFofoStore() != null
343
                selectedGift = handlePartnerWiseGifts(eligibleGifts, fofoOrder);
218
                                && Arrays.stream(gift.getFofoStore().split(","))
344
                break;
219
                                .map(String::trim)
345
            case "BrandSpecific":
220
                                .anyMatch(s -> {
346
                logger.info("Using BrandSpecific gift selection strategy");
221
                                    try { return Integer.parseInt(s) == fofoId; }
347
                selectedGift = handleBrandSpecificGifts(eligibleGifts, fofoOrder);
222
                                    catch (NumberFormatException e) { return false; }
-
 
223
                                }))
-
 
224
                        .findFirst()
348
                break;
225
                        .orElse(null);
349
            default:
226
            default:
350
                logger.warn("Unknown classification: {}", classification);
227
                logger.warn("Unknown classification: {}", offer.getClassification());
351
                selectedGift = null;
228
                return null;
352
        }
229
        }
353
 
-
 
354
        if (selectedGift != null) {
-
 
355
            logger.info("Selected gift: {}", selectedGift.getId());
-
 
356
        } else {
-
 
357
            logger.warn("No gift selected for classification: {}", classification);
-
 
358
        }
-
 
359
 
-
 
360
        return selectedGift;
-
 
361
    }
-
 
362
 
-
 
363
    private GiftEntity handleSerialGifts(List<GiftEntity> gifts) {
-
 
364
        logger.info("Handling Serial gifts selection from {} gifts", gifts.size());
-
 
365
        return gifts.get(0);
-
 
366
    }
-
 
367
 
-
 
368
    private GiftEntity handleRandomGifts(List<GiftEntity> gifts) {
-
 
369
        logger.info("Handling Random gifts selection from {} gifts", gifts.size());
-
 
370
        List<GiftEntity> giftPool = new ArrayList<>(gifts.subList(0, gifts.size()));
-
 
371
        Collections.shuffle(giftPool);
-
 
372
        return giftPool.get(0);
-
 
373
    }
-
 
374
 
-
 
375
    private GiftEntity handlePartnerWiseGifts(List<GiftEntity> gifts, FofoOrder order) {
-
 
376
        int fofoId = order.getFofoId();
-
 
377
        logger.info("Handling PartnerWise gifts selection from {} gifts for fofoId {}", gifts.size(), fofoId);
-
 
378
        return gifts.stream()
-
 
379
                .filter(gift -> {
-
 
380
                    String[] fofoStores = gift.getFofoStore().split(",");
-
 
381
                    return Arrays.stream(fofoStores)
-
 
382
                            .map(storeId -> {
-
 
383
                                try {
-
 
384
                                    return Integer.parseInt(storeId.trim());
-
 
385
                                } catch (NumberFormatException e) {
-
 
386
                                    logger.warn("Invalid fofoId format in gift {}: {}", gift.getId(), storeId);
-
 
387
                                    return -1;
-
 
388
                                }
-
 
389
                            })
-
 
390
                            .anyMatch(storeId -> storeId == fofoId);
-
 
391
                })
-
 
392
                .findFirst()
-
 
393
                .orElse(null);
-
 
394
    }
-
 
395
 
-
 
396
    private GiftEntity handleBrandSpecificGifts(List<GiftEntity> gifts, FofoOrder order) {
-
 
397
        logger.info("Handling BrandSpecific gifts selection from {} gifts for order {}", gifts.size(), order.getId());
-
 
398
        // TODO: Add brand-specific logic
-
 
399
        logger.warn("BrandSpecific gift selection not implemented yet");
-
 
400
        return null;
-
 
401
    }
230
    }
402
 
231
 
403
    public void createBetterLuckNextTimeScratch(FofoOrder order, OfferEntity offer) {
232
    public void createBetterLuckNextTimeScratch(FofoOrder order, OfferEntity offer) {
404
        try {
-
 
405
            ScratchOffer so = new ScratchOffer();
233
        ScratchOffer so = new ScratchOffer();
406
            so.setCustomerId(order.getCustomerId());
234
        so.setCustomerId(order.getCustomerId());
407
            so.setOfferId(offer.getId());
235
        so.setOfferId(offer.getId());
408
            so.setGiftId(1);
236
        so.setGiftId(1);
409
            so.setInvoiceNumber(order.getInvoiceNumber());
237
        so.setInvoiceNumber(order.getInvoiceNumber());
410
            so.setCreatedTimestamp(LocalDateTime.now());
238
        so.setCreatedTimestamp(LocalDateTime.now());
411
            so.setOfferName(offer.getName());
239
        so.setOfferName(offer.getName());
412
 
-
 
413
            scratchOfferRepository.persist(so);
240
        scratchOfferRepository.persist(so);
414
            logger.info("Created Better Luck Next Time scratch offer: {}", so);
-
 
415
        } catch (Exception e) {
-
 
416
            logger.error("Error creating Better Luck Next Time scratch offer: {}", e.getMessage());
-
 
417
        }
-
 
418
    }
241
    }
419
 
242
 
420
    public void createScratchOffer(FofoOrder order, OfferEntity offer, GiftEntity gift) {
243
    public void createScratchOffer(FofoOrder order, OfferEntity offer, GiftEntity gift) {
421
        try {
-
 
422
            GiftEntity currentGift = giftRepository.findById(gift.getId());
244
        int updated = giftRepository.decrementMaxRedemptions(gift.getId());
423
 
-
 
424
            if (currentGift == null || currentGift.getMaxRedemptions() <= 0) {
245
        if (updated == 0) {
425
                logger.warn("Gift {} has no remaining redemptions", gift.getId());
246
            logger.warn("Gift {} has no remaining redemptions", gift.getId());
426
                return;
247
            return;
427
            }
-
 
428
 
-
 
429
            currentGift.setMaxRedemptions(currentGift.getMaxRedemptions() - 1);
-
 
430
            giftRepository.save(currentGift);
-
 
431
 
-
 
432
            ScratchOffer so = new ScratchOffer();
-
 
433
            so.setCustomerId(order.getCustomerId());
-
 
434
            so.setOfferId(offer.getId());
-
 
435
            so.setGiftId(gift.getId());
-
 
436
            so.setInvoiceNumber(order.getInvoiceNumber());
-
 
437
            so.setCreatedTimestamp(LocalDateTime.now());
-
 
438
            so.setOfferName(gift.getName());
-
 
439
 
-
 
440
            scratchOfferRepository.persist(so);
-
 
441
            logger.info("Created scratch offer: {}", so);
-
 
442
 
-
 
443
        } catch (Exception e) {
-
 
444
            logger.error("Error creating scratch offer: {}", e.getMessage());
-
 
445
 
-
 
446
        }
248
        }
-
 
249
 
-
 
250
        ScratchOffer so = new ScratchOffer();
-
 
251
        so.setCustomerId(order.getCustomerId());
-
 
252
        so.setOfferId(offer.getId());
-
 
253
        so.setGiftId(gift.getId());
-
 
254
        so.setInvoiceNumber(order.getInvoiceNumber());
-
 
255
        so.setCreatedTimestamp(LocalDateTime.now());
-
 
256
        so.setOfferName(gift.getName());
-
 
257
        scratchOfferRepository.persist(so);
-
 
258
        logger.info("Created scratch offer for order {} gift {}", order.getId(), gift.getId());
447
    }
259
    }
448
 
260
 
449
    public void createDefaultGiftScratch(FofoOrder order, OfferEntity offer, GiftEntity gift) {
261
    public void createDefaultGiftScratch(FofoOrder order, OfferEntity offer, GiftEntity gift) {
450
        try {
-
 
451
            ScratchOffer so = new ScratchOffer();
262
        ScratchOffer so = new ScratchOffer();
452
            so.setCustomerId(order.getCustomerId());
263
        so.setCustomerId(order.getCustomerId());
453
            so.setOfferId(offer.getId());
264
        so.setOfferId(offer.getId());
454
            so.setGiftId(gift.getId());
265
        so.setGiftId(gift.getId());
455
            so.setInvoiceNumber(order.getInvoiceNumber());
266
        so.setInvoiceNumber(order.getInvoiceNumber());
456
            so.setCreatedTimestamp(LocalDateTime.now());
267
        so.setCreatedTimestamp(LocalDateTime.now());
457
            so.setOfferName(gift.getName());
268
        so.setOfferName(gift.getName());
458
 
-
 
459
            scratchOfferRepository.persist(so);
269
        scratchOfferRepository.persist(so);
460
            logger.info("Created default (unlimited) scratch offer: {}", so);
-
 
461
        } catch (Exception e) {
-
 
462
            logger.error("Error creating default scratch offer: {}", e.getMessage());
-
 
463
        }
-
 
464
    }
270
    }
465
 
271
 
466
 
272
 
467
    public boolean createOffer(ScratchRequest request) {
273
    public boolean createOffer(ScratchRequest request) {
468
        OfferEntity offer = mapToOfferEntity(request);
274
        OfferEntity offer = mapToOfferEntity(request);