Subversion Repositories SmartDukaan

Rev

Rev 35971 | Rev 36024 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
33172 tejus.loha 1
package com.spice.profitmandi.service.order;
2
 
3
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
4
import com.spice.profitmandi.common.model.BulkOrderModel;
33341 tejus.loha 5
import com.spice.profitmandi.common.model.LineItemModel;
33547 tejus.loha 6
import com.spice.profitmandi.common.model.ProfitMandiConstants;
33341 tejus.loha 7
import com.spice.profitmandi.common.model.TransactionApprovalModel;
33172 tejus.loha 8
import com.spice.profitmandi.common.util.ExcelUtils;
35971 aman 9
import com.spice.profitmandi.common.util.Utils;
33172 tejus.loha 10
import com.spice.profitmandi.dao.cart.CartService;
33341 tejus.loha 11
import com.spice.profitmandi.dao.entity.auth.AuthUser;
34443 vikas.jang 12
import com.spice.profitmandi.dao.entity.catalog.Bid;
34832 ranu 13
import com.spice.profitmandi.dao.entity.catalog.Item;
33172 tejus.loha 14
import com.spice.profitmandi.dao.entity.catalog.TagListing;
34856 ranu 15
import com.spice.profitmandi.dao.entity.fofo.FofoStore;
34566 ranu 16
import com.spice.profitmandi.dao.entity.fofo.LoanTransaction;
34674 aman.kumar 17
import com.spice.profitmandi.dao.entity.transaction.LineItem;
18
import com.spice.profitmandi.dao.entity.transaction.Order;
19
import com.spice.profitmandi.dao.entity.transaction.Transaction;
20
import com.spice.profitmandi.dao.entity.transaction.TransactionApproval;
35971 aman 21
import com.spice.profitmandi.dao.entity.user.StoreTimelinetb;
22
import com.spice.profitmandi.dao.enumuration.cs.EscalationType;
23
import com.spice.profitmandi.dao.enumuration.dtr.StoreTimeline;
33213 tejus.loha 24
import com.spice.profitmandi.dao.enumuration.transaction.TransactionApprovalStatus;
33172 tejus.loha 25
import com.spice.profitmandi.dao.model.CartItem;
26
import com.spice.profitmandi.dao.model.UserCart;
33341 tejus.loha 27
import com.spice.profitmandi.dao.repository.auth.AuthRepository;
34468 vikas.jang 28
import com.spice.profitmandi.dao.repository.catalog.BidRepository;
34832 ranu 29
import com.spice.profitmandi.dao.repository.catalog.ItemRepository;
34468 vikas.jang 30
import com.spice.profitmandi.dao.repository.catalog.LiquidationRepository;
33172 tejus.loha 31
import com.spice.profitmandi.dao.repository.catalog.TagListingRepository;
34443 vikas.jang 32
import com.spice.profitmandi.dao.repository.cs.CsService;
34856 ranu 33
import com.spice.profitmandi.dao.repository.dtr.FofoStoreRepository;
33172 tejus.loha 34
import com.spice.profitmandi.dao.repository.dtr.UserRepository;
34566 ranu 35
import com.spice.profitmandi.dao.repository.fofo.LoanTransactionRepository;
33341 tejus.loha 36
import com.spice.profitmandi.dao.repository.transaction.OrderRepository;
33338 amit.gupta 37
import com.spice.profitmandi.dao.repository.transaction.SDCreditRequirementRepository;
33213 tejus.loha 38
import com.spice.profitmandi.dao.repository.transaction.TransactionApprovalRepository;
39
import com.spice.profitmandi.dao.repository.transaction.TransactionRepository;
40
import com.spice.profitmandi.dao.repository.user.AddressRepository;
34468 vikas.jang 41
import com.spice.profitmandi.dao.service.BidService;
34832 ranu 42
import com.spice.profitmandi.service.catalog.BrandsService;
34661 ranu 43
import com.spice.profitmandi.service.transaction.BlockLoanIdSanctionId;
33338 amit.gupta 44
import com.spice.profitmandi.service.transaction.SDCreditService;
33172 tejus.loha 45
import com.spice.profitmandi.service.transaction.TransactionService;
46
import com.spice.profitmandi.service.wallet.CommonPaymentService;
47
import com.spice.profitmandi.service.wallet.WalletService;
48
import org.apache.logging.log4j.LogManager;
49
import org.apache.logging.log4j.Logger;
33213 tejus.loha 50
import org.apache.poi.ss.usermodel.Cell;
33172 tejus.loha 51
import org.apache.poi.ss.usermodel.Row;
52
import org.apache.poi.xssf.usermodel.XSSFRow;
53
import org.apache.poi.xssf.usermodel.XSSFSheet;
54
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
55
import org.springframework.beans.factory.annotation.Autowired;
35971 aman 56
import org.springframework.mail.javamail.JavaMailSender;
33213 tejus.loha 57
import org.springframework.stereotype.Service;
33172 tejus.loha 58
import org.springframework.web.multipart.MultipartFile;
59
 
33338 amit.gupta 60
import java.math.BigDecimal;
35956 amit 61
import java.time.LocalDateTime;
35995 aman 62
import java.util.*;
33172 tejus.loha 63
import java.util.stream.Collectors;
64
 
33213 tejus.loha 65
@Service
33172 tejus.loha 66
public class BulkOrderService {
67
    private static final Logger LOGGER = LogManager.getLogger(BulkOrderService.class);
68
    @Autowired
69
    CartService cartService;
70
    @Autowired
71
    TransactionService transactionService;
72
    @Autowired
73
    CommonPaymentService commonPaymentService;
74
    @Autowired
75
    TagListingRepository tagListingRepository;
76
    @Autowired
77
    WalletService walletService;
78
    @Autowired
79
    UserRepository userRepository;
33213 tejus.loha 80
    @Autowired
81
    TransactionRepository transactionRepository;
82
    @Autowired
83
    TransactionApprovalRepository transactionApprovalRepository;
84
    @Autowired
85
    AddressRepository addressRepository;
33341 tejus.loha 86
    @Autowired
87
    OrderRepository orderRepository;
34443 vikas.jang 88
    //TODO:Tejus need to check
33341 tejus.loha 89
    @Autowired
90
    SDCreditRequirementRepository sdCreditRequirementRepository;
33338 amit.gupta 91
    @Autowired
92
    SDCreditService sdCreditService;
34443 vikas.jang 93
    @Autowired
94
    private CsService csService;
95
    @Autowired
34468 vikas.jang 96
    private AuthRepository authRepository;
34443 vikas.jang 97
    @Autowired
34468 vikas.jang 98
    private BidRepository bidRepository;
99
    @Autowired
100
    private BidService bidService;
101
    @Autowired
34832 ranu 102
    ItemRepository itemRepository;
103
    @Autowired
104
    private BrandsService brandsService;
105
    @Autowired
34566 ranu 106
    private LoanTransactionRepository loanTransactionRepository;
107
 
108
    @Autowired
34468 vikas.jang 109
    private LiquidationRepository liquidationRepository;
33338 amit.gupta 110
 
34674 aman.kumar 111
    @Autowired
112
    com.spice.profitmandi.dao.repository.user.UserRepository user_userRepository;
33338 amit.gupta 113
 
34856 ranu 114
    @Autowired
115
    FofoStoreRepository fofoStoreRepository;
34674 aman.kumar 116
 
35971 aman 117
    @Autowired
118
    JavaMailSender mailSender;
34856 ranu 119
 
35971 aman 120
    @Autowired
121
    com.spice.profitmandi.service.user.StoreTimelineTatService storeTimelineTatService;
122
 
123
    @Autowired
124
    com.spice.profitmandi.dao.repository.dtr.PartnerOnBoardingPanelRepository partnerOnBoardingPanelRepository;
125
 
126
    @Autowired
127
    com.spice.profitmandi.dao.repository.user.StoreTimelinetbRepository storeTimelinetbRepository;
128
 
129
 
34468 vikas.jang 130
    public void parseBulkOrders(MultipartFile file, int creatorId) throws Exception {
33172 tejus.loha 131
        XSSFWorkbook myWorkBook = new XSSFWorkbook(file.getInputStream());
132
 
133
        myWorkBook.setMissingCellPolicy(Row.MissingCellPolicy.RETURN_BLANK_AS_NULL);
134
        // Return first sheet from the XLSX workbook
135
        XSSFSheet mySheet = myWorkBook.getSheetAt(0);
136
        LOGGER.info("rowCellNum {}", mySheet.getLastRowNum());
137
        List<BulkOrderModel> bulkOrderModels = new ArrayList<>();
33547 tejus.loha 138
        LOGGER.info("mySheet.getLastRowNum() - {}", mySheet.getLastRowNum());
33172 tejus.loha 139
        for (int rowNumber = 1; rowNumber <= mySheet.getLastRowNum(); rowNumber++) {
140
            XSSFRow row = mySheet.getRow(rowNumber);
33547 tejus.loha 141
            LOGGER.info("Row - {}", row);
142
            if (row != null) {
143
                BulkOrderModel bulkOrderModel = this.createBulkModel(row);
144
                bulkOrderModels.add(bulkOrderModel);
145
            } else {
146
                break;
147
            }
33172 tejus.loha 148
        }
34468 vikas.jang 149
        this.generatePurchaseOrder(bulkOrderModels, creatorId, ProfitMandiConstants.PO_TYPE.MANUAL, ProfitMandiConstants.BID_CRON_ENUM.TODAY);
34443 vikas.jang 150
    }
151
 
34592 vikas.jang 152
    public ProfitMandiConstants.BID_ENUM generatePurchaseOrder(List<BulkOrderModel> bulkOrderModels, int creatorId, ProfitMandiConstants.PO_TYPE type, ProfitMandiConstants.BID_CRON_ENUM scheduleType) throws Exception {
33172 tejus.loha 153
        Map<Integer, List<BulkOrderModel>> fofoBulkOrdersMap = bulkOrderModels.stream().collect(Collectors.groupingBy(x -> x.getFofoId()));
34443 vikas.jang 154
        boolean approvalRequired = false;
34592 vikas.jang 155
        ProfitMandiConstants.BID_ENUM finalBidStatus = ProfitMandiConstants.BID_ENUM.CLOSED;
33172 tejus.loha 156
        for (Map.Entry<Integer, List<BulkOrderModel>> fofoBulkOrderEntry : fofoBulkOrdersMap.entrySet()) {
157
            int fofoId = fofoBulkOrderEntry.getKey();
158
            List<BulkOrderModel> fofoBulkOrderModels = fofoBulkOrderEntry.getValue();
159
            Map<Integer, Long> orderItemCountMap = fofoBulkOrderModels.stream().collect(Collectors.groupingBy(x -> x.getItemId(), Collectors.counting()));
160
 
161
            if (orderItemCountMap.entrySet().stream().filter(x -> x.getValue() > 1).count() > 0) {
162
                throw new ProfitMandiBusinessException("Fofo ID", fofoId, "Duplicate in items");
163
            }
164
 
165
            boolean hasZeroQuantity = fofoBulkOrderModels.stream().filter(x -> x.getQuantity() <= 0).count() > 0;
166
            if (hasZeroQuantity) {
167
                throw new ProfitMandiBusinessException("Item Quantity", "", "Should be greater than 0");
168
            }
169
 
35690 amit 170
            // Batch-fetch per-fofo data once (instead of per-item)
171
            FofoStore fofoStore = fofoStoreRepository.selectByRetailerId(fofoId);
172
            List<String> partnerIneligibleBrands = brandsService.partnerIneligibleBrands(fofoId);
173
 
174
            // Batch-fetch items and tag listings for all items in this fofo's order (2 queries instead of 2N)
175
            Set<Integer> allItemIds = fofoBulkOrderModels.stream().map(BulkOrderModel::getItemId).collect(Collectors.toSet());
176
            Map<Integer, TagListing> tagListingMap = tagListingRepository.selectByItemIds(allItemIds);
177
            Map<Integer, Item> itemMap = itemRepository.selectByIds(allItemIds).stream()
178
                    .collect(Collectors.toMap(Item::getId, item -> item));
179
 
33172 tejus.loha 180
            List<CartItem> cartItems = new ArrayList<>();
33338 amit.gupta 181
            double totalPayableAmount = 0;
34957 amit 182
            BigDecimal totalPayableAmountBD = new BigDecimal(0);
33172 tejus.loha 183
            for (BulkOrderModel fofoBulkOrderModel : fofoBulkOrderModels) {
184
                CartItem cartItem = new CartItem();
185
                cartItem.setQuantity(fofoBulkOrderModel.getQuantity());
186
                cartItem.setItemId(fofoBulkOrderModel.getItemId());
35690 amit 187
                TagListing tagListing = tagListingMap.get(fofoBulkOrderModel.getItemId());
33556 amit.gupta 188
                if (tagListing == null) {
189
                    String message = "Pricing Does not exist for " + fofoBulkOrderModel.getItemId() + "(" + fofoBulkOrderModel.getDescription() + ")";
190
                    throw new ProfitMandiBusinessException(message, message, message);
191
                }
35690 amit 192
                Item item = itemMap.get(fofoBulkOrderModel.getItemId());
193
                if (item == null) {
194
                    throw new ProfitMandiBusinessException("Item not found", fofoBulkOrderModel.getItemId(), "Item does not exist: " + fofoBulkOrderModel.getItemId());
195
                }
34856 ranu 196
                if (!fofoStore.isInternal()) {
197
                    if (partnerIneligibleBrands.contains(item.getBrand())) {
198
                        throw new ProfitMandiBusinessException("Brand is not allowed", "Brand ( " + item.getBrand() + ") is not allowed for this partner", "");
199
                    }
34832 ranu 200
                }
201
 
33213 tejus.loha 202
                double itemSellingPrice = tagListing.getSellingPrice();
33597 tejus.loha 203
                boolean isActualPrice = fofoBulkOrderModel.getItemPrice() == itemSellingPrice;
204
                boolean isPriceZero = fofoBulkOrderModel.getItemPrice() == 0d;
33213 tejus.loha 205
                double customSellingPrice = fofoBulkOrderModel.getItemPrice();
206
                int itemId = cartItem.getItemId();
33597 tejus.loha 207
                if (isPriceZero || isActualPrice) {
33213 tejus.loha 208
                    cartItem.setSellingPrice(itemSellingPrice);
209
                } else {
33216 tejus.loha 210
                    if (customSellingPrice <= tagListing.getMrp() || customSellingPrice <= tagListing.getMop()) {
33213 tejus.loha 211
                        cartItem.setSellingPrice(customSellingPrice);
34443 vikas.jang 212
                        approvalRequired = true;
33213 tejus.loha 213
 
214
                    } else {
215
                        throw new ProfitMandiBusinessException("Given price is greater than selling price for item Id - ", itemId, " it should be less or equal of DP");
216
                    }
217
 
218
                }
34958 amit 219
                totalPayableAmountBD = totalPayableAmountBD.add(new BigDecimal(String.valueOf(cartItem.getSellingPrice())).multiply(new BigDecimal(cartItem.getQuantity())));
33172 tejus.loha 220
                cartItems.add(cartItem);
221
            }
34957 amit 222
            totalPayableAmount = totalPayableAmountBD.doubleValue();
34501 vikas.jang 223
            Bid bid = null;
224
            if (type.equals(ProfitMandiConstants.PO_TYPE.AUTO)) {
225
                bid = bidRepository.selectById(fofoBulkOrderModels.get(0).getRowIndex());
34592 vikas.jang 226
                approvalRequired = false;
34957 amit 227
                totalPayableAmount = totalPayableAmountBD.doubleValue() - ProfitMandiConstants.BID_CHARGES;
34501 vikas.jang 228
            }
33338 amit.gupta 229
            LOGGER.info("totalAmount of item " + totalPayableAmount);
33172 tejus.loha 230
            double walletAmount = walletService.getWalletAmount(fofoId);
33338 amit.gupta 231
 
232
            BigDecimal creditAvailability = sdCreditService.getAvailableAmount(fofoId);
233
 
234
            double netAmountInHand = creditAvailability.doubleValue() + walletAmount;
33442 tejus.loha 235
            LOGGER.info("netAmountInHand - " + netAmountInHand);
33547 tejus.loha 236
            if (totalPayableAmount > ProfitMandiConstants.MAX_NEGATIVE_WALLET_VALUE && netAmountInHand < totalPayableAmount) {
34468 vikas.jang 237
                if (type.equals(ProfitMandiConstants.PO_TYPE.MANUAL)) {
34695 aman.kumar 238
                    throw new ProfitMandiBusinessException("Skipping order due to insufficient balance for id - ", fofoId, String.valueOf(fofoId));
34443 vikas.jang 239
                } else {
34468 vikas.jang 240
                    if (scheduleType.equals(ProfitMandiConstants.BID_CRON_ENUM.TODAY)) {
34592 vikas.jang 241
                        finalBidStatus = bidService.sendMailToRBM(netAmountInHand, totalPayableAmount, fofoId);
34572 vikas.jang 242
                        LOGGER.info("Skipping order due to insufficient balance for id - "+ fofoId+ " Sending mail to RBM");
243
                        //throw new ProfitMandiBusinessException("Skipping order due to insufficient balance for id - ", fofoId, " ,Sending mail to RBM");
34468 vikas.jang 244
                    } else {
34592 vikas.jang 245
                        finalBidStatus = bidService.cancelYesterdayProcessBid(bid);
34572 vikas.jang 246
                        LOGGER.info("Skipping order due to insufficient balance for id - "+ fofoId+ " Cancelling the BID");
247
                        //throw new ProfitMandiBusinessException("Skipping order due to insufficient balance for id - ", fofoId, " ,Cancelling the BID");
34468 vikas.jang 248
                    }
34443 vikas.jang 249
                }
33172 tejus.loha 250
            }
251
            UserCart userCart = cartService.setCartItems(fofoId, cartItems);
33213 tejus.loha 252
            // createtransactionInternally set the value in transaction table
33338 amit.gupta 253
 
33351 amit.gupta 254
            double creditAmountRequired = totalPayableAmount - walletAmount;
34312 ranu 255
            int loanId = 0;
34492 vikas.jang 256
            try {
257
                if (creditAmountRequired > ProfitMandiConstants.MAX_NEGATIVE_WALLET_VALUE) {
34576 vikas.jang 258
                    LOGGER.info("Creating new loan for: {}",userCart.getUserId());
34675 aman.kumar 259
                    BlockLoanIdSanctionId loan = sdCreditService.createSDDirectOrder(userCart.getUserId(), totalPayableAmount, 0);
34661 ranu 260
                    loanId = loan.getLoanId();
34492 vikas.jang 261
                }
262
            } catch (Exception exception){
34501 vikas.jang 263
                if (type.equals(ProfitMandiConstants.PO_TYPE.AUTO)) {
34592 vikas.jang 264
                    finalBidStatus = bidService.sendMailToRBM(netAmountInHand, totalPayableAmount, fofoId);
34572 vikas.jang 265
                    LOGGER.info("Skipping order due to insufficient balance for id - "+ fofoId+ " Cancelling the BID");
266
                    //throw new ProfitMandiBusinessException("Skipping order unable to create load for id - ", fofoId, " ,Sending mail to RBM");
34501 vikas.jang 267
                }
33338 amit.gupta 268
            }
34443 vikas.jang 269
 
34576 vikas.jang 270
            LOGGER.info("finalBidStatus: {}",finalBidStatus);
34573 vikas.jang 271
            if (finalBidStatus.equals(ProfitMandiConstants.BID_ENUM.CLOSED)) {
35971 aman 272
                // Check if this is the first PO for this partner (before creating the new transaction)
273
                List<Transaction> existingTransactions = transactionRepository.selectByRetailerId(fofoId);
274
                boolean isFirstPO = (existingTransactions == null || existingTransactions.isEmpty());
275
 
276
                // Block first PO if FULL_STOCK_PAYMENT is not done (for LOI-flow partners only)
277
                if (isFirstPO && fofoStore != null && !fofoStore.isInternal() && fofoStore.getCode() != null) {
278
                    com.spice.profitmandi.dao.entity.fofo.PartnerOnBoardingPanel pob =
279
                            partnerOnBoardingPanelRepository.selectByCode(fofoStore.getCode());
280
                    if (pob != null) {
281
                        StoreTimelinetb fspEntry = storeTimelinetbRepository.selectByOnboardingIdAndEvent(
282
                                pob.getId(), StoreTimeline.FULL_STOCK_PAYMENT);
283
                        if (fspEntry == null) {
284
                            LOGGER.warn("PO creation blocked for fofoId={}, onboardingId={}: FULL_STOCK_PAYMENT not done", fofoId, pob.getId());
285
                            throw new ProfitMandiBusinessException(
286
                                    "Full Stock Payment is required before creating PO",
287
                                    fofoStore.getCode(),
288
                                    "Full Stock Payment must be completed before first PO can be created");
289
                        }
290
                    }
291
                }
292
 
34959 amit 293
                LOGGER.info("totalPayableAmount - {}", totalPayableAmount);
34573 vikas.jang 294
                int transactionId = transactionService.createTransactionInternally(userCart, totalPayableAmount, 0);
295
                //Set here created by
296
                Transaction transaction = transactionRepository.selectById(transactionId);
297
                transaction.setCreatedBy(creatorId);
34637 vikas.jang 298
                LOGGER.info("transaction created by {}", transaction.getCreatedBy());
34573 vikas.jang 299
                commonPaymentService.payThroughWallet(transactionId);
35995 aman 300
 
301
                // First PO always requires approval
302
                if (isFirstPO) {
303
                    approvalRequired = true;
304
                }
305
 
34573 vikas.jang 306
                if (approvalRequired) {
35995 aman 307
                    this.createApproval(transactionId, isFirstPO);
34573 vikas.jang 308
                    if (loanId > 0) {
309
                        LoanTransaction loanTransaction = new LoanTransaction();
310
                        loanTransaction.setLoanId(loanId);
311
                        loanTransaction.setTransactionId(transactionId);
312
                        loanTransactionRepository.persist(loanTransaction);
313
                    }
314
                } else {
315
                    transactionService.processTransaction(transactionId, loanId);
316
                }
35971 aman 317
 
35995 aman 318
                // Send approval email and track timeline for first PO
35971 aman 319
                if (isFirstPO) {
320
                    try {
321
                        sendFirstPOApprovalEmail(fofoStore, transactionId, totalPayableAmount, creatorId);
322
                    } catch (Exception e) {
323
                        LOGGER.error("Failed to send first PO approval email for fofoId: " + fofoId, e);
324
                    }
325
                    // Track PO_CREATION on timeline for first PO
326
                    try {
327
                        if (fofoStore != null && fofoStore.getCode() != null) {
328
                            com.spice.profitmandi.dao.entity.fofo.PartnerOnBoardingPanel pob =
329
                                    partnerOnBoardingPanelRepository.selectByCode(fofoStore.getCode());
330
                            if (pob != null) {
331
                                storeTimelineTatService.onPoCreationComplete(pob.getId());
332
                            }
333
                        }
334
                    } catch (Exception e) {
335
                        LOGGER.error("Failed to track PO_CREATION timeline for fofoId: " + fofoId, e);
336
                    }
337
                }
33213 tejus.loha 338
            }
339
 
33172 tejus.loha 340
        }
34592 vikas.jang 341
        return finalBidStatus;
33172 tejus.loha 342
    }
343
 
35995 aman 344
    public void createApproval(int transactionId, boolean firstPo) {
33213 tejus.loha 345
        TransactionApproval transactionApproval = new TransactionApproval();
346
        transactionApproval.setId(transactionId);
347
        transactionApproval.setStatus(TransactionApprovalStatus.PENDING);
35995 aman 348
        transactionApproval.setFirstPo(firstPo);
33213 tejus.loha 349
        transactionApprovalRepository.persist(transactionApproval);
350
    }
351
 
33172 tejus.loha 352
    private BulkOrderModel createBulkModel(XSSFRow row) throws ProfitMandiBusinessException {
353
        BulkOrderModel bulkOrderModel = new BulkOrderModel();
354
        int i = 0;
355
        bulkOrderModel.setRowIndex(row.getRowNum());
356
        try {
33696 amit.gupta 357
            Cell partnerName = row.getCell(i++);
358
            if (partnerName == null)
33213 tejus.loha 359
                bulkOrderModel.setPartnerName("");
360
            else
33696 amit.gupta 361
                bulkOrderModel.setPartnerName(partnerName.getStringCellValue().trim());
33213 tejus.loha 362
            Cell description = row.getCell(i++);
363
            if (description == null)
364
                bulkOrderModel.setDescription("");
365
            else
366
                bulkOrderModel.setDescription(description.getStringCellValue().trim());
367
 
33172 tejus.loha 368
            bulkOrderModel.setFofoId((int) row.getCell(i++).getNumericCellValue());
369
            bulkOrderModel.setItemId((int) row.getCell(i++).getNumericCellValue());
33213 tejus.loha 370
            bulkOrderModel.setItemPrice(row.getCell(i++).getNumericCellValue());
33172 tejus.loha 371
            bulkOrderModel.setQuantity((int) row.getCell(i++).getNumericCellValue());
372
        } catch (Throwable e) {
373
            LOGGER.info(e.getCause());
33213 tejus.loha 374
            throw new ProfitMandiBusinessException("Field", "Field at row - " + row.getRowNum() + ", column - " + (i - 1), "Invalid field value at - " + ExcelUtils.toAlphabet(i - 1) + (row.getRowNum() + 1) + ", " + ExcelUtils.getCellValue(row.getCell(i - 1)));
33172 tejus.loha 375
        }
376
        LOGGER.info(bulkOrderModel);
377
        return bulkOrderModel;
378
    }
379
 
33341 tejus.loha 380
    // create model for transaction Approval so that finance team see all order and approve
381
    public List<TransactionApprovalModel> getAllPendingTransactionApproval() throws ProfitMandiBusinessException {
382
        List<TransactionApproval> transactionApprovals = transactionApprovalRepository.selectAllPending();
383
        LOGGER.info("list of Approval transaction Id " + transactionApprovals);
384
        List<TransactionApprovalModel> approvalModelList = new ArrayList<>();
385
        for (TransactionApproval transactionApproval : transactionApprovals) {
386
            List<Order> orderList = orderRepository.selectAllByTransactionId(transactionApproval.getId());
387
            Transaction transaction = transactionRepository.selectById(transactionApproval.getId());
388
            List<LineItemModel> lineItemModelList = new ArrayList<>();
35995 aman 389
 
390
            // Fetch stock availability for all items in this order
391
            Map<Integer, List<com.spice.profitmandi.model.WarehouseItemQtyModel>> stockMap = Collections.emptyMap();
392
            try {
393
                int retailerId = transaction.getRetailerId();
394
                FofoStore fofoStore = fofoStoreRepository.selectByRetailerId(retailerId);
395
                if (fofoStore != null) {
396
                    List<Integer> itemIds = orderList.stream()
397
                            .map(o -> o.getLineItem().getItemId())
398
                            .collect(java.util.stream.Collectors.toList());
399
                    stockMap = orderRepository.getItemAvailability(fofoStore.getWarehouseId(), itemIds);
400
                }
401
            } catch (Exception e) {
402
                LOGGER.error("Failed to fetch stock availability for transactionId: {}", transactionApproval.getId(), e);
403
            }
404
 
33341 tejus.loha 405
            for (Order order : orderList) {
406
                LineItem lineItem = order.getLineItem();
407
                LineItemModel lineItemModel = new LineItemModel();
408
                lineItemModel.setItemId(lineItem.getItemId());
409
                lineItemModel.setItemName(lineItem.getItem().getItemDescription());
410
                lineItemModel.setItemQuantity(lineItem.getQuantity());
411
                lineItemModel.setSellingPrice(lineItem.getUnitPrice());
412
                lineItemModel.setDp(tagListingRepository.selectByItemId(lineItem.getItemId()).getSellingPrice());
35995 aman 413
                // Set available stock (show 0 if negative — negative means over-committed)
414
                List<com.spice.profitmandi.model.WarehouseItemQtyModel> itemStock = stockMap.get(lineItem.getItemId());
415
                if (itemStock != null && !itemStock.isEmpty()) {
416
                    int totalAvailable = itemStock.stream().mapToInt(s -> s.getNetAvailability()).sum();
417
                    lineItemModel.setAvailableStock(Math.max(0, totalAvailable));
418
                }
33341 tejus.loha 419
                lineItemModelList.add(lineItemModel);
420
            }
421
            AuthUser authUser = authRepository.selectById(transaction.getCreatedBy());
422
            TransactionApprovalModel transactionApprovalModel = new TransactionApprovalModel();
423
            String retailerName = " ";
424
            retailerName = orderList.get(0).getRetailerName();
425
            transactionApprovalModel.setRetailerName(retailerName);
34573 vikas.jang 426
            if (authUser == null) {
427
                transactionApprovalModel.setCreatedBy(retailerName);
428
            } else {
429
                transactionApprovalModel.setCreatedBy(authUser.getFullName());
430
            }
33341 tejus.loha 431
            transactionApprovalModel.setCreatedOn(transaction.getCreateTimestamp());
432
            transactionApprovalModel.setTransactionId(transactionApproval.getId());
433
            transactionApprovalModel.setLineItemModels(lineItemModelList);
35995 aman 434
            transactionApprovalModel.setFirstPo(transactionApproval.isFirstPo());
33341 tejus.loha 435
            approvalModelList.add(transactionApprovalModel);
33172 tejus.loha 436
 
33341 tejus.loha 437
        }
438
        return approvalModelList;
439
    }
440
 
35956 amit 441
    public List<TransactionApprovalModel> getBulkOrderApprovalReport(LocalDateTime startDate, LocalDateTime endDate) throws ProfitMandiBusinessException {
442
        List<TransactionApproval> transactionApprovals = transactionApprovalRepository.selectAllByDateRange(startDate, endDate);
443
        LOGGER.info("Approval report: found {} records", transactionApprovals.size());
444
        List<TransactionApprovalModel> approvalModelList = new ArrayList<>();
445
        for (TransactionApproval transactionApproval : transactionApprovals) {
446
            List<Order> orderList = orderRepository.selectAllByTransactionId(transactionApproval.getId());
447
            Transaction transaction = transactionRepository.selectById(transactionApproval.getId());
448
            List<LineItemModel> lineItemModelList = new ArrayList<>();
449
            for (Order order : orderList) {
450
                LineItem lineItem = order.getLineItem();
451
                LineItemModel lineItemModel = new LineItemModel();
452
                lineItemModel.setItemId(lineItem.getItemId());
453
                lineItemModel.setItemName(lineItem.getItem().getItemDescription());
454
                lineItemModel.setItemQuantity(lineItem.getQuantity());
455
                lineItemModel.setSellingPrice(lineItem.getUnitPrice());
456
                lineItemModel.setDp(tagListingRepository.selectByItemId(lineItem.getItemId()).getSellingPrice());
457
                lineItemModelList.add(lineItemModel);
458
            }
459
            AuthUser authUser = authRepository.selectById(transaction.getCreatedBy());
460
            TransactionApprovalModel model = new TransactionApprovalModel();
461
            String retailerName = orderList.isEmpty() ? "" : orderList.get(0).getRetailerName();
462
            model.setRetailerName(retailerName);
463
            if (authUser == null) {
464
                model.setCreatedBy(retailerName);
465
            } else {
466
                model.setCreatedBy(authUser.getFullName());
467
            }
468
            model.setCreatedOn(transaction.getCreateTimestamp());
469
            model.setTransactionId(transactionApproval.getId());
470
            model.setLineItemModels(lineItemModelList);
471
            model.setStatus(transactionApproval.getStatus().name());
472
            model.setApprovedBy(transactionApproval.getApprovedBy());
473
            model.setApprovedOn(transactionApproval.getApprovedOn());
474
            model.setRemark(transactionApproval.getRemark());
35995 aman 475
            model.setFirstPo(transactionApproval.isFirstPo());
35956 amit 476
            approvalModelList.add(model);
477
        }
478
        return approvalModelList;
479
    }
480
 
35971 aman 481
    private void sendFirstPOApprovalEmail(FofoStore fofoStore, int transactionId, double totalAmount, int creatorId) throws Exception {
482
        String partnerName = "Partner";
483
        if (fofoStore.getUserAddress() != null && fofoStore.getUserAddress().getName() != null) {
484
            partnerName = fofoStore.getUserAddress().getName();
485
        }
486
        String storeCode = fofoStore.getCode() != null ? fofoStore.getCode() : "";
487
 
488
        String createdByName = "";
489
        if (creatorId > 0) {
490
            AuthUser creator = authRepository.selectById(creatorId);
491
            if (creator != null) {
492
                createdByName = creator.getFullName();
493
            }
494
        }
495
 
496
        String subject = "First PO Created - Approval Required - " + partnerName + " (" + storeCode + ")";
497
 
498
        StringBuilder sb = new StringBuilder();
499
        sb.append("<html><body>");
500
        sb.append("<p>Dear Team,</p>");
501
        sb.append("<p>The <strong>first Purchase Order</strong> has been created for the below partner. Please review and approve.</p><br/>");
502
        sb.append("<table style='border:1px solid black; border-collapse: collapse;'>");
503
        sb.append("<tbody>");
504
        sb.append("<tr>");
505
        sb.append("<th style='border:1px solid black; padding: 5px;'>Partner Name</th>");
506
        sb.append("<th style='border:1px solid black; padding: 5px;'>Store Code</th>");
507
        sb.append("<th style='border:1px solid black; padding: 5px;'>Transaction ID</th>");
508
        sb.append("<th style='border:1px solid black; padding: 5px;'>Total Amount</th>");
509
        sb.append("<th style='border:1px solid black; padding: 5px;'>Created By</th>");
510
        sb.append("</tr>");
511
        sb.append("<tr>");
512
        sb.append("<td style='border:1px solid black; padding: 5px;'>").append(partnerName).append("</td>");
513
        sb.append("<td style='border:1px solid black; padding: 5px;'>").append(storeCode).append("</td>");
514
        sb.append("<td style='border:1px solid black; padding: 5px;'>").append(transactionId).append("</td>");
515
        sb.append("<td style='border:1px solid black; padding: 5px;'>").append(String.format("%.2f", totalAmount)).append("</td>");
516
        sb.append("<td style='border:1px solid black; padding: 5px;'>").append(createdByName).append("</td>");
517
        sb.append("</tr>");
518
        sb.append("</tbody></table>");
519
        sb.append("<br/><p>Please approve this order from the <strong>Transaction Approvals</strong> panel.</p>");
520
        sb.append("<br/><p>Regards,<br/>Smart Dukaan</p>");
521
        sb.append("</body></html>");
522
 
523
        // Send to Sales L3
524
        List<AuthUser> salesL3Users = csService.getAuthUserByCategoryId(
525
                ProfitMandiConstants.TICKET_CATEGORY_SALES, EscalationType.L3);
526
 
527
        List<String> sendTo = new ArrayList<>();
528
        if (!salesL3Users.isEmpty()) {
529
            sendTo.addAll(salesL3Users.stream().map(AuthUser::getEmailId).collect(Collectors.toList()));
530
        }
531
 
532
        if (!sendTo.isEmpty()) {
533
            String[] emailArray = sendTo.toArray(new String[0]);
534
            Utils.sendMailWithAttachments(mailSender, emailArray, null, subject, sb.toString());
535
            LOGGER.info("First PO approval email sent for fofoId: {} transactionId: {}", fofoStore.getId(), transactionId);
536
        }
537
    }
538
 
33172 tejus.loha 539
}