package com.utopiaindustries.service; import com.utopiaindustries.dao.ctp.*; import com.utopiaindustries.model.ctp.*; import com.utopiaindustries.querybuilder.ctp.SummaryInventoryReportQueryBuilder; import com.utopiaindustries.util.CTPDateTimeFormat; import com.utopiaindustries.util.StringUtils; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @Service public class ReportingService { private final JobCardItemDAO jobCardItemDAO; private final ProcessDAO processDAO; private final BundleDAO bundleDAO; private final InventoryTransactionLegDAO inventoryTransactionLegDAO; private final InventoryTransactionDAO inventoryTransactionDAO; private final JobCardDAO jobCardDAO; private final CryptographyService cryptographyService; private final MasterBundleDAO masterBundleDAO; private final FinishedItemDAO finishedItemDAO; private final StitchingOfflineItemDAO stitchingOfflineItemDAO; private final InventoryAccountDAO inventoryAccountDAO; private final PackagingItemsDAO packagingItemsDAO; public ReportingService(JobCardItemDAO jobCardItemDAO, ProcessDAO processDAO, BundleDAO bundleDAO, InventoryTransactionLegDAO inventoryTransactionLegDAO, InventoryTransactionDAO inventoryTransactionDAO, JobCardDAO jobCardDAO, CryptographyService cryptographyService, MasterBundleDAO masterBundleDAO, FinishedItemDAO finishedItemDAO, StitchingOfflineItemDAO stitchingOfflineItemDAO, InventoryAccountDAO inventoryAccountDAO, PackagingItemsDAO packagingItemsDAO) { this.jobCardItemDAO = jobCardItemDAO; this.processDAO = processDAO; this.bundleDAO = bundleDAO; this.inventoryTransactionLegDAO = inventoryTransactionLegDAO; this.inventoryTransactionDAO = inventoryTransactionDAO; this.jobCardDAO = jobCardDAO; this.cryptographyService = cryptographyService; this.masterBundleDAO = masterBundleDAO; this.finishedItemDAO = finishedItemDAO; this.stitchingOfflineItemDAO = stitchingOfflineItemDAO; this.inventoryAccountDAO = inventoryAccountDAO; this.packagingItemsDAO = packagingItemsDAO; } public Map getJobCardProgress(String jobCardID) { if (jobCardID == null) { return new LinkedHashMap<>(); } else { Map totalProgress = new HashMap<>(); List jobCardItems = jobCardItemDAO.findByCardId(Long.parseLong(jobCardID)); BigDecimal totalProduction = jobCardItems.stream() .map(item -> Optional.ofNullable(item.getTotalProduction()).orElse(BigDecimal.ZERO)) .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal actualProduction = jobCardItems.stream() .map(item -> Optional.ofNullable(item.getActualProduction()).orElse(BigDecimal.ZERO)) .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal expectedProduction = jobCardItems.stream() .map(item -> Optional.ofNullable(item.getExpectedProduction()).orElse(BigDecimal.ZERO)) .reduce(BigDecimal.ZERO, BigDecimal::add); // Cutting Progress Calculation if (actualProduction.compareTo(BigDecimal.ZERO) == 0) { totalProgress.put("Cutting Progress", 0); } else if (actualProduction.compareTo(expectedProduction) < 0) { BigDecimal cuttingProgress = actualProduction .divide(expectedProduction, 4, RoundingMode.HALF_UP) .multiply(BigDecimal.valueOf(100)); totalProgress.put("Cutting Progress", cuttingProgress.intValue()); } else { totalProgress.put("Cutting Progress", 100); } // Stitching Progress Calculation if (totalProduction.compareTo(BigDecimal.ZERO) == 0) { totalProgress.put("Stitching Progress", 0); } else { BigDecimal stitchingProgress = totalProduction .divide(actualProduction, 4, RoundingMode.HALF_UP) .multiply(BigDecimal.valueOf(100)); totalProgress.put("Stitching Progress", stitchingProgress.intValue()); } // QA Progress Calculation Long qaProgressItems = stitchingOfflineItemDAO.CalculateTotalQA(Long.parseLong(jobCardID)); if (qaProgressItems == 0) { totalProgress.put("QA Progress", 0); } else { BigDecimal qaProgress = BigDecimal.valueOf(qaProgressItems) .divide(actualProduction, 4, RoundingMode.HALF_UP) .multiply(BigDecimal.valueOf(100)); totalProgress.put("QA Progress", qaProgress.intValue()); } // Finishing Progress Calculation Long totalFinishItem = finishedItemDAO.calculateTotalFinishItem(Long.parseLong(jobCardID)); if (totalFinishItem == 0) { totalProgress.put("Finishing Progress", 0); } else { BigDecimal finishItemProgress = BigDecimal.valueOf(totalFinishItem) .divide(actualProduction, 4, RoundingMode.HALF_UP) .multiply(BigDecimal.valueOf(100)); totalProgress.put("Finishing Progress", finishItemProgress.intValue()); } // Job Card Progress Calculation if (totalProduction.compareTo(BigDecimal.ZERO) == 0 && actualProduction.compareTo(BigDecimal.ZERO) == 0) { totalProgress.put("Job Card Progress", 0); } else { BigDecimal progressPercentage; if (actualProduction.compareTo(expectedProduction) > 0) { progressPercentage = actualProduction.add(totalProduction) .add(BigDecimal.valueOf(qaProgressItems)) .add(BigDecimal.valueOf(totalFinishItem)) .divide(actualProduction.multiply(BigDecimal.valueOf(4)), 4, RoundingMode.HALF_UP) .multiply(BigDecimal.valueOf(100)); } else { progressPercentage = actualProduction.add(totalProduction) .add(BigDecimal.valueOf(qaProgressItems)) .add(BigDecimal.valueOf(totalFinishItem)) .divide(expectedProduction.multiply(BigDecimal.valueOf(4)), 4, RoundingMode.HALF_UP) .multiply(BigDecimal.valueOf(100)); } totalProgress.put("Job Card Progress", progressPercentage.intValue()); } // Sorting Map based on Custom Order Map indexMap = new HashMap<>(); indexMap.put("Cutting Progress", 1); indexMap.put("Stitching Progress", 2); indexMap.put("QA Progress", 3); indexMap.put("Finishing Progress", 4); indexMap.put("Job Card Progress", 5); return totalProgress.entrySet() .stream() .sorted(Comparator.comparingInt(entry -> indexMap.get(entry.getKey()))) .collect(LinkedHashMap::new, (m, v) -> m.put(v.getKey(), v.getValue()), Map::putAll); } } public Integer getTotalProduction(String jobCardID){ if (jobCardID == null){ return 0; }else { List jobCardItems = jobCardItemDAO.findByCardId(Long.parseLong(jobCardID)); BigDecimal actualProduction = jobCardItems.stream() .map(item -> Optional.ofNullable(item.getActualProduction()).orElse(BigDecimal.ZERO)) .reduce(BigDecimal.ZERO, BigDecimal::add); return actualProduction.intValue(); } } public Map getCompleteProduction(String jobCardID) { if (jobCardID == null) { return new LinkedHashMap<>(); } else { HashMap totalProgress = new HashMap<>(); List jobCardItems = jobCardItemDAO.findByCardId(Long.parseLong(jobCardID)); BigDecimal totalProduction = jobCardItems.stream() .map(item -> Optional.ofNullable(item.getTotalProduction()).orElse(BigDecimal.ZERO)) .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal actualProduction = jobCardItems.stream() .map(item -> Optional.ofNullable(item.getActualProduction()).orElse(BigDecimal.ZERO)) .reduce(BigDecimal.ZERO, BigDecimal::add); Long qaProgressItems = stitchingOfflineItemDAO.CalculateTotalQA(Long.parseLong(jobCardID)); Long totalFinishItem = finishedItemDAO.calculateTotalFinishItem(Long.parseLong(jobCardID)); // Get Job card Complete Items Map jobCardCompleteItems = getSegregateItems(jobCardID); Integer segregateTotalItems = jobCardCompleteItems.values().stream().mapToInt(Integer::intValue).sum(); // Add values to totalProgress map totalProgress.put("Cutting Progress", actualProduction.intValue()); totalProgress.put("Stitching Progress", totalProduction.intValue()); totalProgress.put("QA Progress", qaProgressItems.intValue()); totalProgress.put("Finishing Progress", totalFinishItem.intValue()); totalProgress.put("Job Card Progress", segregateTotalItems); //custom order Map indexMap = new HashMap<>(); indexMap.put("Job Card Progress", 1); indexMap.put("Cutting Progress", 2); indexMap.put("Stitching Progress", 3); indexMap.put("Finishing Progress", 4); indexMap.put("QA Progress", 5); // Sort the keys based on custom order return totalProgress.entrySet() .stream() .sorted(Comparator.comparingInt(entry -> indexMap.get(entry.getKey()))) .collect(LinkedHashMap::new, (m, v) -> m.put(v.getKey(), v.getValue()), Map::putAll); } } public Map getSegregateItems(String jobCardID){ if (jobCardID == null){ return new HashMap<>(); }else { HashMap gradingItems = new HashMap<>(); List inventoryAccounts = inventoryAccountDAO.getPackagingAccounts(); List finishedItems = finishedItemDAO.findByJobCardId(Long.parseLong(jobCardID)); List packagingItems = packagingItemsDAO.findByJobCardId(Long.parseLong(jobCardID)); List finishItemsIds = finishedItems.stream() .map(FinishedItem::getId).collect(Collectors.toList()); List packagingItemsIds = packagingItems.stream() .map(PackagingItems::getId).collect(Collectors.toList()); if (finishItemsIds.isEmpty()){ gradingItems.put("A GRADE",0); gradingItems.put("B GRADE",0); gradingItems.put("C GRADE",0); return gradingItems; }else { for (InventoryAccount inventoryAccount : inventoryAccounts){ if (inventoryAccount.getIsPackaging()){ long totalGradingItems = inventoryTransactionLegDAO.CalculateTotalGradingItems(packagingItemsIds,(int) inventoryAccount.getId()); gradingItems.put(inventoryAccount.getTitle(), (int) totalGradingItems); }else { long totalGradingItems = inventoryTransactionLegDAO.CalculateTotalGradingItems(finishItemsIds,(int) inventoryAccount.getId()); gradingItems.put(inventoryAccount.getTitle(), (int) totalGradingItems); } } return gradingItems; } } } public HashMap getEachPhaseTotalTime(String jobCardID){ if (jobCardID == null){ return new HashMap<>(); }else { HashMap phasesTimes = new HashMap<>(); JobCard jobCard = jobCardDAO.find(Long.parseLong(jobCardID)); Bundle lastBundle = bundleDAO.findLastBundleByCardId(Long.parseLong(jobCardID)); //Cutting time StringBuilder cuttingTime = generateTime(jobCard.getCreatedAt(),lastBundle.getCreatedAt()); phasesTimes.put("Cutting Total Time",cuttingTime.toString()); //Stitching time List bundlesIds = bundleDAO.findByCardId(Long.parseLong(jobCardID)).stream().map(Bundle::getId).collect(Collectors.toList()); if (!bundlesIds.isEmpty()){ InventoryTransactionLeg inventoryTransactionLeg = inventoryTransactionLegDAO.getFirstStitchBundleTime(bundlesIds,"STITCH_BUNDLE"); StitchingOfflineItem lastStitchItem = stitchingOfflineItemDAO.getLastStitchItemByCardIdAndTime(Long.parseLong(jobCardID)); StringBuilder stitchingTime = generateTime(inventoryTransactionLeg.getTransactionLegDateTime(),lastStitchItem.getCreatedAt()); phasesTimes.put("Stitching Total Time",stitchingTime.toString()); }else { phasesTimes.put("Stitching Total Time",null); } return phasesTimes; } } public HashMap countPendingItemsOnDifferentPhases(String jobCardID){ if (jobCardID == null){ return new HashMap<>(); }else { HashMap phasePending = new HashMap(); List jobCardItems = jobCardItemDAO.findByCardId(Long.parseLong(jobCardID)); BigDecimal totalProduction = jobCardItems.stream() .map(item -> Optional.ofNullable(item.getTotalProduction()).orElse(BigDecimal.ZERO)) .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal actualProduction = jobCardItems.stream() .map(item -> Optional.ofNullable(item.getActualProduction()).orElse(BigDecimal.ZERO)) .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal expectedProduction = jobCardItems.stream() .map(item -> Optional.ofNullable(item.getExpectedProduction()).orElse(BigDecimal.ZERO)) .reduce(BigDecimal.ZERO, BigDecimal::add); if(actualProduction.compareTo(totalProduction) == 0) { phasePending.put("Stitching Total Time", null); }else { phasePending.put("Stitching Total Time", "Pending"); } return phasePending; } } public Map> getCuttingDetails(String jobCardID) { if (jobCardID == null) { return Collections.emptyMap(); } Map> cuttingDetails = new HashMap<>(); Map cuttingAccount = new HashMap<>(); Map cuttingPersonName = new HashMap<>(); Map cuttingDate = new HashMap<>(); List bundles = bundleDAO.findByCardId(Long.parseLong(jobCardID)); if (bundles.isEmpty()) { return cuttingDetails; } Map bundleMap = bundles.stream() .collect(Collectors.toMap(Bundle::getId, Function.identity())); List bundleIds = new ArrayList<>(bundleMap.keySet()); List inventoryTransactionLegs = inventoryTransactionLegDAO .getTransactionByParentIdAndType(bundleIds, "BUNDLE"); for (InventoryTransactionLeg inventoryTransactionLeg : inventoryTransactionLegs) { Integer accountId = inventoryTransactionLeg.getAccountId(); InventoryAccount inventoryAccount = inventoryAccountDAO.find(accountId.longValue()); if (inventoryAccount != null) { String accountTitle = inventoryAccount.getTitle(); cuttingAccount.put(accountTitle, inventoryAccount); Bundle bundle = bundleMap.get(inventoryTransactionLeg.getParentDocumentId()); cuttingPersonName.put(accountTitle, (bundle != null) ? bundle.getCreatedBy() : null); cuttingDate.put(accountTitle,(bundle != null) ? bundle.getCreatedAt().toLocalDate() : null); } } cuttingDetails.put("accounts", new HashMap<>(cuttingAccount)); cuttingDetails.put("personName", new HashMap<>(cuttingPersonName)); cuttingDetails.put("date", new HashMap<>(cuttingDate)); return cuttingDetails; } public Map> getStitchingDetails(String jobCardID) { if (jobCardID == null) { return Collections.emptyMap(); } Map> stitchingDetails = new HashMap<>(); Map stitchingAccount = new HashMap<>(); Map stitchingPersonName = new HashMap<>(); Map stitchingDate = new HashMap<>(); List stitchingOfflineItems = stitchingOfflineItemDAO.findByJobCardId(Long.parseLong(jobCardID)); if (stitchingOfflineItems.isEmpty()) { return stitchingDetails; } Map stitchingOfflineItemMap = stitchingOfflineItems.stream() .collect(Collectors.toMap(StitchingOfflineItem::getId, Function.identity())); List stitchingItemsArray = new ArrayList<>(stitchingOfflineItemMap.keySet()); List inventoryTransactionLegs = inventoryTransactionLegDAO .getTransactionByParentIdAndType(stitchingItemsArray, "STITCHING_OFFLINE"); for (InventoryTransactionLeg inventoryTransactionLeg : inventoryTransactionLegs) { Integer accountId = inventoryTransactionLeg.getAccountId(); InventoryAccount inventoryAccount = inventoryAccountDAO.find(accountId.longValue()); if (inventoryAccount != null) { String accountTitle = inventoryAccount.getTitle(); stitchingAccount.put(accountTitle, inventoryAccount); StitchingOfflineItem stitchingOfflineItem = stitchingOfflineItemMap.get(inventoryTransactionLeg.getParentDocumentId()); stitchingPersonName.put(accountTitle, (stitchingOfflineItem != null) ? stitchingOfflineItem.getCreatedBy() : null); stitchingDate.put(accountTitle,(stitchingOfflineItem != null) ? stitchingOfflineItem.getCreatedAt().toLocalDate() : null); } } stitchingDetails.put("accounts", new HashMap<>(stitchingAccount)); stitchingDetails.put("personName", new HashMap<>(stitchingPersonName)); stitchingDetails.put("date", new HashMap<>(stitchingDate)); return stitchingDetails; } public Map> getPhasesProgressDayWise(String jobCardID) { if (jobCardID == null) { return Collections.emptyMap(); } List inventoryAccounts = inventoryAccountDAO.findByParentEntityTypeAndParentId("PROCESS",6L); List jobCardItems = jobCardItemDAO.findByCardId(Long.parseLong(jobCardID)); BigDecimal actualProduction = jobCardItems.stream() .map(item -> Optional.ofNullable(item.getActualProduction()).orElse(BigDecimal.ZERO)) .reduce(BigDecimal.ZERO, BigDecimal::add); LocalDateTime startDate = jobCardDAO.find(Long.parseLong(jobCardID)).getCreatedAt(); HashMap> barChartData = new HashMap<>(); List inventoryTransactionLegs = inventoryTransactionLegDAO .getTransactionByJobCardAndDatesAndType(Long.parseLong(jobCardID), startDate.toString(), LocalDateTime.now().toString(), "IN"); //remove quality multiple transaction entry approved/rejects List filteredTransactions = inventoryTransactionLegs.stream() .collect(Collectors.toMap( leg -> leg.getAccountId() + "-" + leg.getParentDocumentType() + "-" + leg.getParentDocumentId(), leg -> leg, // Value (existing, replacement) -> existing.getTransactionLegDateTime().isBefore(replacement.getTransactionLegDateTime()) ? existing : replacement // Keep Oldest )) .values() .stream() .collect(Collectors.toList()); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); List uniqueDates = inventoryTransactionLegs.stream() .map(leg -> leg.getTransactionLegDateTime().toLocalDate().format(formatter)) .distinct() .sorted() .collect(Collectors.toList()); Map dateIndexMap = new HashMap<>(); for (int i = 0; i < uniqueDates.size(); i++) { dateIndexMap.put(uniqueDates.get(i), i); } List cuttingList = new ArrayList<>(Collections.nCopies(uniqueDates.size(), 0)); List stitchingList = new ArrayList<>(Collections.nCopies(uniqueDates.size(), 0)); List qualityList = new ArrayList<>(Collections.nCopies(uniqueDates.size(), 0)); List finishItems = new ArrayList<>(Collections.nCopies(uniqueDates.size(), 0)); for (InventoryTransactionLeg leg : filteredTransactions) { String dateKey = leg.getTransactionLegDateTime().format(formatter); int index = dateIndexMap.get(dateKey); if ("BUNDLE".equals(leg.getParentDocumentType())) { Bundle bundle = bundleDAO.find(leg.getParentDocumentId()); cuttingList.set(index, cuttingList.get(index) + bundle.getWrapQuantity().intValue()); } else if ("STITCHING_OFFLINE".equals(leg.getParentDocumentType())) { stitchingList.set(index, stitchingList.get(index) + leg.getQuantity().intValue()); } else if ("FINISHED_ITEM".equals(leg.getParentDocumentType()) && (leg.getAccountId().equals(7) || leg.getAccountId().equals(12))) { if (index == 0 || !dateIndexMap.containsKey(dateKey)) { qualityList.set(index, 0); } qualityList.set(index, qualityList.get(index) + leg.getQuantity().intValue()); } else if ("PACKAGING".equals(leg.getParentDocumentType()) && inventoryAccounts.stream().anyMatch(e -> e.getId() == leg.getAccountId().longValue())) { if (index == 0 || !dateIndexMap.containsKey(dateKey)) { finishItems.set(index, 0); } finishItems.set(index, finishItems.get(index) + leg.getQuantity().intValue()); } } barChartData.put("dates", uniqueDates); barChartData.put("cutting", cuttingList); barChartData.put("stitching", stitchingList); barChartData.put("quality", qualityList); barChartData.put("finishing", finishItems); return barChartData; } public List getAllPOs(String poName) { List pOsDetailsList = new ArrayList<>(); List jobCards = jobCardDAO.findAll() ; HashMap> filterJobCardsByPos; if(poName != null && !poName.isEmpty()) { filterJobCardsByPos = jobCards.stream() .filter(jobCard -> jobCard.getPurchaseOrderId().equals(poName)) .collect(Collectors.groupingBy( JobCard::getPurchaseOrderId, HashMap::new, Collectors.toList() )); }else { filterJobCardsByPos = jobCards.stream() .collect(Collectors.groupingBy( JobCard::getPurchaseOrderId, HashMap::new, Collectors.toList() )); } Map jobCardCompleteItems = new HashMap<>(); for (String pos : filterJobCardsByPos.keySet()) { BigDecimal totalProduction = BigDecimal.ZERO; BigDecimal actualProduction = BigDecimal.ZERO; int poQuantity = 0; String articleName = ""; Long qaProgressItems = 0L; Long totalFinishItem = 0L; POsDetails pOsDetails = new POsDetails(); for (JobCard jobCard : filterJobCardsByPos.get(pos)) { List jobCardItems = jobCardItemDAO.findByCardId(jobCard.getId()); totalProduction = totalProduction.add(jobCardItems.stream() .map(item -> Optional.ofNullable(item.getTotalProduction()).orElse(BigDecimal.ZERO)) .reduce(BigDecimal.ZERO, BigDecimal::add)); actualProduction = actualProduction.add(jobCardItems.stream() .map(item -> Optional.ofNullable(item.getActualProduction()).orElse(BigDecimal.ZERO)) .reduce(BigDecimal.ZERO, BigDecimal::add)); poQuantity = jobCard.getPoQuantity(); articleName = jobCard.getArticleName(); qaProgressItems += Optional.ofNullable(stitchingOfflineItemDAO.CalculateTotalQA(jobCard.getId())).orElse(0L); totalFinishItem += Optional.ofNullable(finishedItemDAO.calculateTotalFinishItem(jobCard.getId())).orElse(0L); jobCardCompleteItems = getSegregateItems(String.valueOf(jobCard.getId())); if (jobCardCompleteItems == null) { jobCardCompleteItems = new HashMap<>(); } } pOsDetails.setPoNumber(pos); pOsDetails.setArticleTitle(articleName); pOsDetails.setPoQuantity(poQuantity); pOsDetails.setTotalCutting(actualProduction.intValue()); pOsDetails.setTotalStitching(totalProduction.intValue()); pOsDetails.setTotalEndLineQC(qaProgressItems.intValue()); pOsDetails.setTotalFinishing(totalFinishItem); pOsDetails.setRemainingCutting(poQuantity - actualProduction.intValue()); pOsDetails.setRemainingStitching(poQuantity - totalProduction.intValue()); pOsDetails.setRemainingEndLineQC(poQuantity - qaProgressItems); pOsDetails.setRemainingFinishing(poQuantity - totalFinishItem); pOsDetails.setTotalAGradeItem(jobCardCompleteItems.getOrDefault("A GRADE", 0)); pOsDetails.setTotalBGradeItem(jobCardCompleteItems.getOrDefault("B GRADE", 0)); pOsDetails.setTotalCGradeItem(jobCardCompleteItems.getOrDefault("C GRADE", 0)); pOsDetailsList.add(pOsDetails); } return pOsDetailsList; } public HashMap> getAllPoJobCards(String PONumber, String selectDate) { String startDate = selectDate != null && !selectDate.isEmpty() ? selectDate + " 00:00:01": null; String endDate = selectDate != null && !selectDate.isEmpty() ? selectDate + " 23:59:59": null; HashMap> poJobCardItemsProgress = new HashMap<>(); List jobCards = jobCardDAO.findAll(); // Filter JobCards by Purchase Order ID List filterJobCardsByPos = jobCards.stream() .filter(e -> e.getPurchaseOrderId().equals(PONumber)) .collect(Collectors.toList()); List inventoryAccounts = inventoryAccountDAO.getPackagingAccounts(); List gradingAccounts = inventoryAccounts.stream().map(e-> (int)(e.getId())).collect(Collectors.toList()); for (JobCard jobCard : filterJobCardsByPos) { List bundles = bundleDAO.findByCardIdAndDATE(jobCard.getId(),startDate,endDate); List stitchingOfflineItems = stitchingOfflineItemDAO.findByJobCardIdAndDate(jobCard.getId(),startDate,endDate); List finishedItems = finishedItemDAO.calculateTotalFinishItem(jobCard.getId(),startDate,endDate); List inventoryTransactionLegs = inventoryTransactionLegDAO.getTransactionByJobCardAndDatesAndTypeAndAccountID(jobCard.getId(),startDate,endDate,"IN", gradingAccounts); //cutting days wise BigDecimal cutting = bundles.stream() .map(bundle -> Optional.ofNullable(bundle.getWrapQuantity()).orElse(BigDecimal.ZERO)) .reduce(BigDecimal.ZERO, BigDecimal::add); //stitching day wise Integer stitching = stitchingOfflineItems.size(); //total qa Integer qa = finishedItems.size(); Map segregateItems = inventoryTransactionLegs.stream() .filter(leg -> inventoryAccounts.stream() .anyMatch(account -> (int) account.getId() == (leg.getAccountId()))) .collect(Collectors.toMap( leg -> inventoryAccounts.stream() .filter(account -> (int) account.getId() == (leg.getAccountId())) .findFirst() .map(InventoryAccount::getTitle) .orElse("Unknown"), leg -> leg.getQuantity().intValue(), Integer::sum, HashMap::new )); Map items = getCompleteProduction(String.valueOf(jobCard.getId())); items.put("Cutting Progress",cutting.intValue()); items.put("Stitching Progress",stitching); items.put("QA Progress",qa); items.put("A Grade",segregateItems.get("A GRADE") != null ? segregateItems.get("A GRADE") : 0); items.put("B Grade",segregateItems.get("B GRADE") != null ? segregateItems.get("B GRADE") : 0); items.put("C Grade",segregateItems.get("C GRADE") != null ? segregateItems.get("C GRADE") : 0); // Define sorting order Map indexMap = new HashMap<>(); indexMap.put("Job Card Progress", 1); indexMap.put("Cutting Progress", 2); indexMap.put("Stitching Progress", 3); indexMap.put("QA Progress", 4); indexMap.put("Finishing Progress", 5); indexMap.put("A GRADE", 6); indexMap.put("B GRADE", 7); indexMap.put("C GRADE", 8); // Sort items based on indexMap order Map sortedItems = items.entrySet() .stream() .sorted(Comparator.comparingInt(entry -> indexMap.getOrDefault(entry.getKey(), Integer.MAX_VALUE))) .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new )); // Add sorted items to the result map poJobCardItemsProgress.put(jobCard.getCode(), sortedItems); } return poJobCardItemsProgress; } public Map getCuttingTableDetails(String jobCardId, String cuttingTableId, String startDate, String endDate) { Map cuttingDetails = new HashMap<>(); long jobCardIdTemp = 0L; String startDate1 = null; String endDate1 = null; if (!StringUtils.isNullOrEmpty(startDate)) { String formattedStart = CTPDateTimeFormat.getMySQLFormattedDateString(startDate, CTPDateTimeFormat.HTML5_DATE_INPUT_FORMAT); String formattedEnd = !StringUtils.isNullOrEmpty(endDate) ? CTPDateTimeFormat.getMySQLFormattedDateString(endDate, CTPDateTimeFormat.HTML5_DATE_INPUT_FORMAT) : LocalDate.now().toString(); startDate1 = String.format("'%s 00:00:01'", formattedStart); endDate1 = String.format("'%s 23:59:59'", formattedEnd); } List inventoryAccounts = inventoryAccountDAO.findByParentEntityTypeAndParentId("PROCESS", 1L); List inventoryAccountIds = inventoryAccounts.stream().map(InventoryAccount::getId).collect(Collectors.toList()); if (!StringUtils.isNullOrEmpty(jobCardId)) { jobCardIdTemp = Long.parseLong(jobCardId); } else if (!StringUtils.isNullOrEmpty(cuttingTableId)) { inventoryAccountIds = List.of(Long.parseLong(cuttingTableId)); } String query = SummaryInventoryReportQueryBuilder.cuttingQueryBuild(jobCardIdTemp, inventoryAccountIds, null, startDate1, endDate1, "IN","BUNDLE"); List inventoryTransactionLegs = inventoryTransactionLegDAO.findByQuery(query); Map dateWiseProduction = new TreeMap<>(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); Map> dateWiseJobCardIds = inventoryTransactionLegs.stream() .filter(e -> e.getTransactionLegDateTime() != null && e.getJobCardId() != 0) .collect(Collectors.groupingBy( e -> e.getTransactionLegDateTime().toLocalDate(), Collectors.mapping(InventoryTransactionLeg::getJobCardId, Collectors.toList()) )); for (Map.Entry> entry : dateWiseJobCardIds.entrySet()) { List jobCardIds = entry.getValue(); if (!jobCardIds.isEmpty()) { List jobCardItems = jobCardItemDAO.findByJobCardIds(jobCardIds); int totalProduction = jobCardItems.stream() .filter(item -> item.getActualProduction() != null) .mapToInt(item -> item.getActualProduction().intValue()) .sum(); dateWiseProduction.put(entry.getKey().format(formatter), totalProduction); } } List distinctJobCardIds = inventoryTransactionLegs.stream() .map(InventoryTransactionLeg::getJobCardId) .filter(id -> id != 0) .distinct() .collect(Collectors.toList()); Map> jobCardItemsCuttingDetailsMap = new HashMap<>(); for (long jobCardIdEntry : distinctJobCardIds) { Long accountId = inventoryTransactionLegs.stream() .filter(e -> e.getJobCardId() == jobCardIdEntry) .map(e -> e.getAccountId().longValue()) .findFirst() .orElse(0L); JobCard jobCard = jobCardDAO.find(jobCardIdEntry); Bundle bundle = bundleDAO.findByCardId(jobCardIdEntry).stream().findFirst().orElse(new Bundle()); List jobCardItems = jobCardItemDAO.findByCardId(jobCardIdEntry); List wrappers = jobCardItems.stream().map(item -> { CuttingJobCardItemWrapper wrapper = new CuttingJobCardItemWrapper(); wrapper.setArticleName(jobCard.getArticleName()); wrapper.setJobCardCode(jobCard.getCode()); wrapper.setGsm(item.getGsm()); wrapper.setPly(item.getPly()); wrapper.setSku(item.getSku()); wrapper.setTotal(item.getActualProduction().longValue()); wrapper.setWidth(item.getWidth()); wrapper.setWtPly(item.getWtPly()); wrapper.setComplete(item.isComplete()); wrapper.setPoName(jobCard.getPurchaseOrderId()); wrapper.setOperatorName(bundle.getCreatedBy()); wrapper.setJobCardId(item.getJobCardId()); wrapper.setLength(item.getLength()); wrapper.setAccountId(accountId); return wrapper; }).collect(Collectors.toList()); jobCardItemsCuttingDetailsMap.computeIfAbsent(accountId, k -> new ArrayList<>()).addAll(wrappers); } cuttingDetails.put("Date Wise Cutting", dateWiseProduction); cuttingDetails.put("accountWiseCutting", jobCardItemsCuttingDetailsMap); cuttingDetails.put("cuttingAccount", inventoryAccounts); return cuttingDetails; } public Map getStitchingDetails(String jobCardId, String stitchingLine, String startDate, String endDate) { Map stitchingDetails = new HashMap<>(); long jobCardIdTemp = 0L; String startDate1 = null; String endDate1 = null; if (!StringUtils.isNullOrEmpty(startDate)) { String formattedStart = CTPDateTimeFormat.getMySQLFormattedDateString(startDate, CTPDateTimeFormat.HTML5_DATE_INPUT_FORMAT); String formattedEnd = !StringUtils.isNullOrEmpty(endDate) ? CTPDateTimeFormat.getMySQLFormattedDateString(endDate, CTPDateTimeFormat.HTML5_DATE_INPUT_FORMAT) : LocalDate.now().toString(); startDate1 = String.format("'%s 00:00:01'", formattedStart); endDate1 = String.format("'%s 23:59:59'", formattedEnd); } List inventoryAccounts = inventoryAccountDAO.findByParentEntityTypeAndParentId("PROCESS", 2L); List inventoryAccountIds = inventoryAccounts.stream().map(InventoryAccount::getId).collect(Collectors.toList()); if (!StringUtils.isNullOrEmpty(jobCardId)) { jobCardIdTemp = Long.parseLong(jobCardId); } else if (!StringUtils.isNullOrEmpty(stitchingLine)) { inventoryAccountIds = List.of(Long.parseLong(stitchingLine)); } String query = SummaryInventoryReportQueryBuilder.cuttingQueryBuild(jobCardIdTemp, inventoryAccountIds,null, startDate1, endDate1, "IN","STITCHING_OFFLINE"); List inventoryTransactionLegs = inventoryTransactionLegDAO.findByQuery(query); Map dateWiseProduction = new TreeMap<>(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); Map> dateWiseJobCardIds = inventoryTransactionLegs.stream() .filter(e -> e.getTransactionLegDateTime() != null && e.getJobCardId() != 0) .collect(Collectors.groupingBy( e -> e.getTransactionLegDateTime().toLocalDate(), Collectors.mapping(InventoryTransactionLeg::getJobCardId, Collectors.toList()) )); for (Map.Entry> entry : dateWiseJobCardIds.entrySet()) { LocalDate date = entry.getKey(); List jobCardIds = entry.getValue(); if (!jobCardIds.isEmpty()) { int totalProduction = inventoryTransactionLegs.stream() .filter(item -> jobCardIds.contains(item.getJobCardId()) && "STITCHING_OFFLINE".equals(item.getParentDocumentType()) && item.getTransactionLegDateTime().toLocalDate().equals(date)) .mapToInt(item -> item.getQuantity().intValue()) .sum(); dateWiseProduction.put(date.format(formatter), totalProduction); } } List distinctJobCardIds = inventoryTransactionLegs.stream() .map(InventoryTransactionLeg::getJobCardId) .filter(id -> id != 0) .distinct() .collect(Collectors.toList()); Map> jobCardItemsStitchingDetailsMap = new HashMap<>(); Map totalStitchingBasedOnAccountID = new HashMap<>(); for (long jobCardIdEntry : distinctJobCardIds) { Long accountId = inventoryTransactionLegs.stream() .filter(e -> e.getJobCardId() == jobCardIdEntry) .map(e -> e.getAccountId().longValue()) .findFirst() .orElse(0L); JobCard jobCard = jobCardDAO.find(jobCardIdEntry); List stitchingOfflineItem = stitchingOfflineItemDAO.findByJobCardId(jobCardIdEntry); List jobCardItems = jobCardItemDAO.findByCardId(jobCardIdEntry); List wrappers = jobCardItems.stream().map(item -> { CuttingJobCardItemWrapper wrapper = new CuttingJobCardItemWrapper(); wrapper.setArticleName(jobCard.getArticleName()); wrapper.setJobCardId(jobCard.getId()); wrapper.setJobCardCode(jobCard.getCode()); wrapper.setSku(item.getSku()); wrapper.setPoName(jobCard.getPurchaseOrderId()); wrapper.setJobCardId(item.getJobCardId()); wrapper.setOperatorName(stitchingOfflineItem.get(0).getCreatedBy()); wrapper.setAccountId(accountId); return wrapper; }).collect(Collectors.toList()); totalStitchingBasedOnAccountID.put(jobCard.getId()+stitchingOfflineItem.get(0).getSku(), stitchingOfflineItem.size()); jobCardItemsStitchingDetailsMap.computeIfAbsent(accountId, k -> new ArrayList<>()).addAll(wrappers); } stitchingDetails.put("totalStitchingBasedOnAccountID", totalStitchingBasedOnAccountID); stitchingDetails.put("jobCardItemsStitchingDetailsMap", jobCardItemsStitchingDetailsMap); stitchingDetails.put("Date Wise Stitching", dateWiseProduction); stitchingDetails.put("stitchingAccount", inventoryAccounts); return stitchingDetails; } public List stitchingItemsTransactions(String jobCardId, String accountId, String sku, String startDate, String endDate) { List accountID = new ArrayList<>(); String startDate1 = null; String endDate1 = null; if (!StringUtils.isNullOrEmpty(startDate) && !StringUtils.isNullOrEmpty(accountId) && !StringUtils.isNullOrEmpty(jobCardId)) { String formattedStart = CTPDateTimeFormat.getMySQLFormattedDateString(startDate, CTPDateTimeFormat.HTML5_DATE_INPUT_FORMAT); String formattedEnd = !StringUtils.isNullOrEmpty(endDate) ? CTPDateTimeFormat.getMySQLFormattedDateString(endDate, CTPDateTimeFormat.HTML5_DATE_INPUT_FORMAT) : LocalDate.now().toString(); startDate1 = String.format("'%s 00:00:01'", formattedStart); endDate1 = String.format("'%s 23:59:59'", formattedEnd); accountID.add(Long.parseLong(accountId)); } String query = SummaryInventoryReportQueryBuilder.cuttingQueryBuild(Long.parseLong(jobCardId), accountID, sku, startDate1, endDate1,"IN","STITCHING_OFFLINE"); List inventoryTransactionLegs = inventoryTransactionLegDAO.findByQuery(query); List stitchingItemsList = inventoryTransactionLegs.stream() .map(InventoryTransactionLeg::getParentDocumentId) .collect(Collectors.toList()); return stitchingOfflineItemDAO.findByIds(stitchingItemsList); } private StringBuilder generateTime(LocalDateTime startDate, LocalDateTime endDate){ StringBuilder totalTime = new StringBuilder(); if(startDate != null && endDate != null){ Duration duration = Duration.between(startDate, endDate); if (duration.toDays() > 0) { totalTime.append(String.format("%d days, ", duration.toDays())); } if (duration.toHours() % 24 > 0) { totalTime.append(String.format("%d hours, ", duration.toHours() % 24)); } if (duration.toMinutes() % 60 > 0) { totalTime.append(String.format("%d minutes ", duration.toMinutes() % 60)); } return totalTime; }else return totalTime.append(""); } }