Subversion Repositories SmartDukaan

Rev

Rev 36338 | Go to most recent revision | Details | Last modification | View Log | RSS feed

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