Rev 36306 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
package com.smartdukaan.cron.scheduled;import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;import com.spice.profitmandi.dao.entity.transaction.CronBatch;import com.spice.profitmandi.dao.enumuration.catalog.OfferSchemeType;import com.spice.profitmandi.dao.model.CreateOfferRequest;import com.spice.profitmandi.service.cron.CronBatchService;import com.spice.profitmandi.service.offers.OfferPartnerPayoutData;import com.spice.profitmandi.service.offers.OfferProcessingHelper;import com.spice.profitmandi.service.offers.OfferService;import com.spice.profitmandi.service.offers.SellinPartnerPayoutData;import com.spice.profitmandi.service.transaction.PartnerLimitUpdateData;import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.util.LinkedHashMap;import java.util.List;/*** Batch-aware scheduled tasks with per-partner transaction isolation.* NO @Transactional at class level — each partner gets its own transaction* via REQUIRES_NEW in the helper beans.** Tracks every run in cron_batch / cron_batch_item tables.* Sends failure summary email to technology on partial failures.*/@Componentpublic class BatchScheduledTasks {private static final Logger LOGGER = LogManager.getLogger(BatchScheduledTasks.class);@Autowiredprivate CronBatchService cronBatchService;@Autowiredprivate OfferProcessingHelper offerProcessingHelper;@Autowiredprivate OfferService offerService;@Autowiredprivate PartnerLimitHelper partnerLimitHelper;/*** Processes a single offer with per-partner transaction isolation and batch tracking.* Routes to activation or sellin based on scheme type.** Flow:* 1. Load offer (read-only transaction)* 2. Calculate payouts per partner (read-only transaction)* 3. Create batch record with all eligible partners* 4. Per-partner: call helper with REQUIRES_NEW — commits/rolls back independently* 5. Finalize batch: update counts, send failure email if any*/public void processOfferWithBatch(int offerId) throws Exception {CreateOfferRequest createOfferRequest = offerProcessingHelper.loadOfferRequest(offerId);if (createOfferRequest == null) {return;}LOGGER.info("Processing offer {} (type={}) with batch tracking", offerId, createOfferRequest.getSchemeType());if (createOfferRequest.getSchemeType().equals(OfferSchemeType.ACTIVATION)) {processActivationOfferWithBatch(offerId, createOfferRequest);} else if (createOfferRequest.getSchemeType().equals(OfferSchemeType.SELLIN)) {processSellinOfferWithBatch(offerId, createOfferRequest);} else {LOGGER.warn("Offer {} has unsupported scheme type: {}", offerId, createOfferRequest.getSchemeType());}}private void processActivationOfferWithBatch(int offerId, CreateOfferRequest createOfferRequest) throws Exception {List<OfferPartnerPayoutData> partnerPayouts;try {partnerPayouts = offerService.calculateOfferPayouts(createOfferRequest);} catch (Exception e) {LOGGER.error("Failed to calculate activation payouts for offer {}: {}", offerId, e.getMessage());return;}if (partnerPayouts.isEmpty()) {LOGGER.info("No eligible partners for activation offer {}", offerId);return;}LinkedHashMap<Integer, String> fofoIdPartnerNameMap = new LinkedHashMap<>();for (OfferPartnerPayoutData data : partnerPayouts) {fofoIdPartnerNameMap.put(data.getFofoId(), "fofo-" + data.getFofoId());}CronBatch batch = cronBatchService.createBatch("processActivationOffer-" + offerId, fofoIdPartnerNameMap);for (OfferPartnerPayoutData data : partnerPayouts) {try {offerProcessingHelper.processPartnerOfferPayout(batch.getId(), data.getFofoId(), offerId, createOfferRequest.getDescription(),data.getLineItemValueMap(), data.getItemCriteriaPayout(), data.getCriteriaId(),data.getSerialNumberPaid(), data.getAgeingSummaryModelsMap(),data.getEligiblePayoutValue(), data.isDiscount());} catch (Exception e) {LOGGER.error("Activation offer {} failed for fofoId={}: {}", offerId, data.getFofoId(), e.getMessage());cronBatchService.markItemFailed(batch.getId(), data.getFofoId(), e.getMessage());}}cronBatchService.finalizeBatch(batch.getId());}private void processSellinOfferWithBatch(int offerId, CreateOfferRequest createOfferRequest) throws Exception {List<SellinPartnerPayoutData> partnerPayouts;try {partnerPayouts = offerService.calculateSellinPayouts(createOfferRequest);} catch (Exception e) {LOGGER.error("Failed to calculate sellin payouts for offer {}: {}", offerId, e.getMessage());return;}if (partnerPayouts.isEmpty()) {LOGGER.info("No eligible partners for sellin offer {}", offerId);return;}LinkedHashMap<Integer, String> fofoIdPartnerNameMap = new LinkedHashMap<>();for (SellinPartnerPayoutData data : partnerPayouts) {fofoIdPartnerNameMap.put(data.getFofoId(), "fofo-" + data.getFofoId());}CronBatch batch = cronBatchService.createBatch("processSellinOffer-" + offerId, fofoIdPartnerNameMap);for (SellinPartnerPayoutData data : partnerPayouts) {try {offerProcessingHelper.processPartnerSellinPayout(batch.getId(), data.getFofoId(), offerId, createOfferRequest.getDescription(),data.getSerialNumberInventoryItemMap(), data.getItemCriteriaPayout(), data.getCriteriaId(),data.getSerialNumberPaid(), data.getEligiblePayoutValue(), data.isDiscount());} catch (Exception e) {LOGGER.error("Sellin offer {} failed for fofoId={}: {}", offerId, data.getFofoId(), e.getMessage());cronBatchService.markItemFailed(batch.getId(), data.getFofoId(), e.getMessage());}}cronBatchService.finalizeBatch(batch.getId());}/*** Recalculates partner credit limits. Only writes to partners where values actually changed.** Flow:* 1. Read phase: calculate limits for all 1,500 partners, compare with current values* 2. Create batch with only changed partners (~50-100 typically)* 3. Per-partner: update in REQUIRES_NEW transaction* 4. Finalize: counts + failure email*/public void updatePartnerLimitWithBatch() throws Exception {List<PartnerLimitUpdateData> changedPartners;try {changedPartners = partnerLimitHelper.calculateChangedPartnerLimits();} catch (Exception e) {LOGGER.error("Failed to calculate partner limits: {}", e.getMessage());return;}if (changedPartners.isEmpty()) {LOGGER.info("No partner limits changed, skipping");return;}LinkedHashMap<Integer, String> fofoIdPartnerNameMap = new LinkedHashMap<>();for (PartnerLimitUpdateData data : changedPartners) {fofoIdPartnerNameMap.put(data.getFofoId(), "fofo-" + data.getFofoId());}CronBatch batch = cronBatchService.createBatch("updatePartnerLimit", fofoIdPartnerNameMap);for (PartnerLimitUpdateData data : changedPartners) {try {partnerLimitHelper.updateSinglePartnerLimit(batch.getId(), data);} catch (Exception e) {LOGGER.error("updatePartnerLimit failed for fofoId={}: {}", data.getFofoId(), e.getMessage());cronBatchService.markItemFailed(batch.getId(), data.getFofoId(), e.getMessage());}}cronBatchService.finalizeBatch(batch.getId());}}