Subversion Repositories SmartDukaan

Rev

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

Rev 36338 Rev 36343
Line 1... Line 1...
1
package com.smartdukaan.cron.scheduled;
1
package com.smartdukaan.cron.scheduled;
2
 
2
 
3
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
-
 
4
import com.spice.profitmandi.dao.entity.transaction.CronBatch;
3
import com.spice.profitmandi.dao.entity.transaction.CronBatch;
5
import com.spice.profitmandi.dao.enumuration.catalog.OfferSchemeType;
-
 
6
import com.spice.profitmandi.dao.model.CreateOfferRequest;
-
 
7
import com.spice.profitmandi.service.cron.CronBatchService;
4
import com.spice.profitmandi.service.cron.CronBatchService;
8
import com.spice.profitmandi.service.offers.OfferPartnerPayoutData;
-
 
9
import com.spice.profitmandi.service.offers.OfferProcessingHelper;
-
 
10
import com.spice.profitmandi.service.offers.OfferService;
5
import com.spice.profitmandi.service.offers.OfferBatchService;
11
import com.spice.profitmandi.service.offers.SellinPartnerPayoutData;
-
 
12
import com.spice.profitmandi.service.transaction.PartnerLimitUpdateData;
6
import com.spice.profitmandi.service.transaction.PartnerLimitUpdateData;
13
import org.apache.logging.log4j.LogManager;
7
import org.apache.logging.log4j.LogManager;
14
import org.apache.logging.log4j.Logger;
8
import org.apache.logging.log4j.Logger;
15
import org.springframework.beans.factory.annotation.Autowired;
9
import org.springframework.beans.factory.annotation.Autowired;
16
import org.springframework.stereotype.Component;
10
import org.springframework.stereotype.Component;
Line 22... Line 16...
22
 * Batch-aware scheduled tasks with per-partner transaction isolation.
16
 * Batch-aware scheduled tasks with per-partner transaction isolation.
23
 * NO @Transactional at class level — each partner gets its own transaction
17
 * NO @Transactional at class level — each partner gets its own transaction
24
 * via REQUIRES_NEW in the helper beans.
18
 * via REQUIRES_NEW in the helper beans.
25
 *
19
 *
26
 * Tracks every run in cron_batch / cron_batch_item tables.
20
 * Tracks every run in cron_batch / cron_batch_item tables.
27
 * Sends failure summary email to technology on partial failures.
21
 * Sends failure summary email on partial failures.
28
 */
22
 */
29
@Component
23
@Component
30
public class BatchScheduledTasks {
24
public class BatchScheduledTasks {
31
 
25
 
32
    private static final Logger LOGGER = LogManager.getLogger(BatchScheduledTasks.class);
26
    private static final Logger LOGGER = LogManager.getLogger(BatchScheduledTasks.class);
33
 
27
 
34
    @Autowired
28
    @Autowired
35
    private CronBatchService cronBatchService;
29
    private CronBatchService cronBatchService;
36
 
30
 
37
    @Autowired
31
    @Autowired
38
    private OfferProcessingHelper offerProcessingHelper;
-
 
39
 
-
 
40
    @Autowired
-
 
41
    private OfferService offerService;
32
    private OfferBatchService offerBatchService;
42
 
33
 
43
    @Autowired
34
    @Autowired
44
    private PartnerLimitHelper partnerLimitHelper;
35
    private PartnerLimitHelper partnerLimitHelper;
45
 
36
 
46
    /**
37
    /**
47
     * Processes a single offer with per-partner transaction isolation and batch tracking.
38
     * CLI entrypoint for cron: delegates to shared OfferBatchService (also used by web/fofo controllers).
48
     * Routes to activation or sellin based on scheme type.
-
 
49
     *
-
 
50
     * Flow:
-
 
51
     * 1. Load offer (read-only transaction)
-
 
52
     * 2. Calculate payouts per partner (read-only transaction)
-
 
53
     * 3. Create batch record with all eligible partners
-
 
54
     * 4. Per-partner: call helper with REQUIRES_NEW — commits/rolls back independently
-
 
55
     * 5. Finalize batch: update counts, send failure email if any
-
 
56
     */
39
     */
57
    public void processOfferWithBatch(int offerId) throws Exception {
40
    public void processOfferWithBatch(int offerId) throws Exception {
58
        CreateOfferRequest createOfferRequest = offerProcessingHelper.loadOfferRequest(offerId);
-
 
59
        if (createOfferRequest == null) {
-
 
60
            return;
-
 
61
        }
-
 
62
        LOGGER.info("Processing offer {} (type={}) with batch tracking", offerId, createOfferRequest.getSchemeType());
-
 
63
 
-
 
64
        if (createOfferRequest.getSchemeType().equals(OfferSchemeType.ACTIVATION)) {
-
 
65
            processActivationOfferWithBatch(offerId, createOfferRequest);
-
 
66
        } else if (createOfferRequest.getSchemeType().equals(OfferSchemeType.SELLIN)) {
-
 
67
            processSellinOfferWithBatch(offerId, createOfferRequest);
-
 
68
        } else {
-
 
69
            LOGGER.warn("Offer {} has unsupported scheme type: {}", offerId, createOfferRequest.getSchemeType());
-
 
70
        }
-
 
71
    }
-
 
72
 
-
 
73
    private void processActivationOfferWithBatch(int offerId, CreateOfferRequest createOfferRequest) throws Exception {
-
 
74
        List<OfferPartnerPayoutData> partnerPayouts;
-
 
75
        try {
-
 
76
            partnerPayouts = offerService.calculateOfferPayouts(createOfferRequest);
-
 
77
        } catch (Exception e) {
-
 
78
            LOGGER.error("Failed to calculate activation payouts for offer {}: {}", offerId, e.getMessage());
-
 
79
            return;
-
 
80
        }
-
 
81
 
-
 
82
        if (partnerPayouts.isEmpty()) {
-
 
83
            LOGGER.info("No eligible partners for activation offer {}", offerId);
-
 
84
            return;
-
 
85
        }
-
 
86
 
-
 
87
        LinkedHashMap<Integer, String> fofoIdPartnerNameMap = new LinkedHashMap<>();
-
 
88
        for (OfferPartnerPayoutData data : partnerPayouts) {
-
 
89
            fofoIdPartnerNameMap.put(data.getFofoId(), "fofo-" + data.getFofoId());
-
 
90
        }
-
 
91
 
-
 
92
        CronBatch batch = cronBatchService.createBatch("processActivationOffer-" + offerId, fofoIdPartnerNameMap);
-
 
93
 
-
 
94
        for (OfferPartnerPayoutData data : partnerPayouts) {
-
 
95
            try {
-
 
96
                offerProcessingHelper.processPartnerOfferPayout(
-
 
97
                        batch.getId(), data.getFofoId(), offerId, createOfferRequest.getDescription(),
-
 
98
                        data.getLineItemValueMap(), data.getItemCriteriaPayout(), data.getCriteriaId(),
-
 
99
                        data.getSerialNumberPaid(), data.getAgeingSummaryModelsMap(),
-
 
100
                        data.getEligiblePayoutValue(), data.isDiscount());
-
 
101
            } catch (Exception e) {
-
 
102
                LOGGER.error("Activation offer {} failed for fofoId={}: {}", offerId, data.getFofoId(), e.getMessage());
-
 
103
                cronBatchService.markItemFailed(batch.getId(), data.getFofoId(), e.getMessage());
-
 
104
            }
-
 
105
        }
-
 
106
 
-
 
107
        cronBatchService.finalizeBatch(batch.getId());
-
 
108
    }
-
 
109
 
-
 
110
    private void processSellinOfferWithBatch(int offerId, CreateOfferRequest createOfferRequest) throws Exception {
-
 
111
        List<SellinPartnerPayoutData> partnerPayouts;
-
 
112
        try {
-
 
113
            partnerPayouts = offerService.calculateSellinPayouts(createOfferRequest);
-
 
114
        } catch (Exception e) {
-
 
115
            LOGGER.error("Failed to calculate sellin payouts for offer {}: {}", offerId, e.getMessage());
-
 
116
            return;
-
 
117
        }
-
 
118
 
-
 
119
        if (partnerPayouts.isEmpty()) {
-
 
120
            LOGGER.info("No eligible partners for sellin offer {}", offerId);
-
 
121
            return;
-
 
122
        }
-
 
123
 
-
 
124
        LinkedHashMap<Integer, String> fofoIdPartnerNameMap = new LinkedHashMap<>();
-
 
125
        for (SellinPartnerPayoutData data : partnerPayouts) {
-
 
126
            fofoIdPartnerNameMap.put(data.getFofoId(), "fofo-" + data.getFofoId());
-
 
127
        }
-
 
128
 
-
 
129
        CronBatch batch = cronBatchService.createBatch("processSellinOffer-" + offerId, fofoIdPartnerNameMap);
-
 
130
 
-
 
131
        for (SellinPartnerPayoutData data : partnerPayouts) {
-
 
132
            try {
-
 
133
                offerProcessingHelper.processPartnerSellinPayout(
-
 
134
                        batch.getId(), data.getFofoId(), offerId, createOfferRequest.getDescription(),
-
 
135
                        data.getSerialNumberInventoryItemMap(), data.getItemCriteriaPayout(), data.getCriteriaId(),
-
 
136
                        data.getSerialNumberPaid(), data.getEligiblePayoutValue(), data.isDiscount());
-
 
137
            } catch (Exception e) {
-
 
138
                LOGGER.error("Sellin offer {} failed for fofoId={}: {}", offerId, data.getFofoId(), e.getMessage());
-
 
139
                cronBatchService.markItemFailed(batch.getId(), data.getFofoId(), e.getMessage());
-
 
140
            }
-
 
141
        }
-
 
142
 
-
 
143
        cronBatchService.finalizeBatch(batch.getId());
41
        offerBatchService.processOfferWithBatch(offerId);
144
    }
42
    }
145
 
43
 
146
    /**
44
    /**
147
     * Recalculates partner credit limits. Only writes to partners where values actually changed.
45
     * Recalculates partner credit limits. Only writes to partners where values actually changed.
148
     *
46
     *