cut-to-pack-service/src/main/java/com/utopiaindustries/service/ReportingService.java

854 lines
44 KiB
Java

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<String, Integer> getJobCardProgress(String jobCardID) {
if (jobCardID == null) {
return new LinkedHashMap<>();
} else {
Map<String, Integer> totalProgress = new HashMap<>();
List<JobCardItem> 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<String, Integer> 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<JobCardItem> 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<String, Integer> getCompleteProduction(String jobCardID) {
if (jobCardID == null) {
return new LinkedHashMap<>();
} else {
HashMap<String, Integer> totalProgress = new HashMap<>();
List<JobCardItem> 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<String, Integer> 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<String, Integer> 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<String,Integer> getSegregateItems(String jobCardID){
if (jobCardID == null){
return new HashMap<>();
}else {
HashMap<String,Integer> gradingItems = new HashMap<>();
List<InventoryAccount> inventoryAccounts = inventoryAccountDAO.getPackagingAccounts();
List<FinishedItem> finishedItems = finishedItemDAO.findByJobCardId(Long.parseLong(jobCardID));
List<PackagingItems> packagingItems = packagingItemsDAO.findByJobCardId(Long.parseLong(jobCardID));
List<Long> finishItemsIds = finishedItems.stream()
.map(FinishedItem::getId).collect(Collectors.toList());
List<Long> 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<String,String> getEachPhaseTotalTime(String jobCardID){
if (jobCardID == null){
return new HashMap<>();
}else {
HashMap<String,String> 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<Long> 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<String,String> countPendingItemsOnDifferentPhases(String jobCardID){
if (jobCardID == null){
return new HashMap<>();
}else {
HashMap<String,String> phasePending = new HashMap<String,String>();
List<JobCardItem> 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<String, Map<String, Object>> getCuttingDetails(String jobCardID) {
if (jobCardID == null) {
return Collections.emptyMap();
}
Map<String, Map<String, Object>> cuttingDetails = new HashMap<>();
Map<String, InventoryAccount> cuttingAccount = new HashMap<>();
Map<String, String> cuttingPersonName = new HashMap<>();
Map<String, LocalDate> cuttingDate = new HashMap<>();
List<Bundle> bundles = bundleDAO.findByCardId(Long.parseLong(jobCardID));
if (bundles.isEmpty()) {
return cuttingDetails;
}
Map<Long, Bundle> bundleMap = bundles.stream()
.collect(Collectors.toMap(Bundle::getId, Function.identity()));
List<Long> bundleIds = new ArrayList<>(bundleMap.keySet());
List<InventoryTransactionLeg> 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<String, Map<String, Object>> getStitchingDetails(String jobCardID) {
if (jobCardID == null) {
return Collections.emptyMap();
}
Map<String, Map<String, Object>> stitchingDetails = new HashMap<>();
Map<String, InventoryAccount> stitchingAccount = new HashMap<>();
Map<String, String> stitchingPersonName = new HashMap<>();
Map<String, LocalDate> stitchingDate = new HashMap<>();
List<StitchingOfflineItem> stitchingOfflineItems = stitchingOfflineItemDAO.findByJobCardId(Long.parseLong(jobCardID));
if (stitchingOfflineItems.isEmpty()) {
return stitchingDetails;
}
Map<Long, StitchingOfflineItem> stitchingOfflineItemMap = stitchingOfflineItems.stream()
.collect(Collectors.toMap(StitchingOfflineItem::getId, Function.identity()));
List<Long> stitchingItemsArray = new ArrayList<>(stitchingOfflineItemMap.keySet());
List<InventoryTransactionLeg> 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<String, List<?>> getPhasesProgressDayWise(String jobCardID) {
if (jobCardID == null) {
return Collections.emptyMap();
}
List<InventoryAccount> inventoryAccounts = inventoryAccountDAO.findByParentEntityTypeAndParentId("PROCESS",6L);
List<JobCardItem> 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<String, List<?>> barChartData = new HashMap<>();
List<InventoryTransactionLeg> inventoryTransactionLegs = inventoryTransactionLegDAO
.getTransactionByJobCardAndDatesAndType(Long.parseLong(jobCardID), startDate.toString(), LocalDateTime.now().toString(), "IN");
//remove quality multiple transaction entry approved/rejects
List<InventoryTransactionLeg> 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<String> uniqueDates = inventoryTransactionLegs.stream()
.map(leg -> leg.getTransactionLegDateTime().toLocalDate().format(formatter))
.distinct()
.sorted()
.collect(Collectors.toList());
Map<String, Integer> dateIndexMap = new HashMap<>();
for (int i = 0; i < uniqueDates.size(); i++) {
dateIndexMap.put(uniqueDates.get(i), i);
}
List<Integer> cuttingList = new ArrayList<>(Collections.nCopies(uniqueDates.size(), 0));
List<Integer> stitchingList = new ArrayList<>(Collections.nCopies(uniqueDates.size(), 0));
List<Integer> qualityList = new ArrayList<>(Collections.nCopies(uniqueDates.size(), 0));
List<Integer> 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<POsDetails> getAllPOs(String poName) {
List<POsDetails> pOsDetailsList = new ArrayList<>();
List<JobCard> jobCards = jobCardDAO.findAll() ;
HashMap<String, List<JobCard>> 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<String,Integer> 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<JobCardItem> 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<String, Map<String, Integer>> 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<String, Map<String, Integer>> poJobCardItemsProgress = new HashMap<>();
List<JobCard> jobCards = jobCardDAO.findAll();
// Filter JobCards by Purchase Order ID
List<JobCard> filterJobCardsByPos = jobCards.stream()
.filter(e -> e.getPurchaseOrderId().equals(PONumber))
.collect(Collectors.toList());
List<InventoryAccount> inventoryAccounts = inventoryAccountDAO.getPackagingAccounts();
List<Integer> gradingAccounts = inventoryAccounts.stream().map(e-> (int)(e.getId())).collect(Collectors.toList());
for (JobCard jobCard : filterJobCardsByPos) {
List<Bundle> bundles = bundleDAO.findByCardIdAndDATE(jobCard.getId(),startDate,endDate);
List<StitchingOfflineItem> stitchingOfflineItems = stitchingOfflineItemDAO.findByJobCardIdAndDate(jobCard.getId(),startDate,endDate);
List<FinishedItem> finishedItems = finishedItemDAO.calculateTotalFinishItem(jobCard.getId(),startDate,endDate);
List<InventoryTransactionLeg> 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<String, Integer> 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<String, Integer> 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<String, Integer> 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<String, Integer> 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<String, Object> getCuttingTableDetails(String jobCardId, String cuttingTableId, String startDate, String endDate) {
Map<String, Object> 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<InventoryAccount> inventoryAccounts = inventoryAccountDAO.findByParentEntityTypeAndParentId("PROCESS", 1L);
List<Long> 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<InventoryTransactionLeg> inventoryTransactionLegs = inventoryTransactionLegDAO.findByQuery(query);
Map<String, Integer> dateWiseProduction = new TreeMap<>();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
Map<LocalDate, List<Long>> 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<LocalDate, List<Long>> entry : dateWiseJobCardIds.entrySet()) {
List<Long> jobCardIds = entry.getValue();
if (!jobCardIds.isEmpty()) {
List<JobCardItem> 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<Long> distinctJobCardIds = inventoryTransactionLegs.stream()
.map(InventoryTransactionLeg::getJobCardId)
.filter(id -> id != 0)
.distinct()
.collect(Collectors.toList());
Map<Long, List<CuttingJobCardItemWrapper>> 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<JobCardItem> jobCardItems = jobCardItemDAO.findByCardId(jobCardIdEntry);
List<CuttingJobCardItemWrapper> 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<String, Object> getStitchingDetails(String jobCardId, String stitchingLine, String startDate, String endDate) {
Map<String, Object> 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<InventoryAccount> inventoryAccounts = inventoryAccountDAO.findByParentEntityTypeAndParentId("PROCESS", 2L);
List<Long> 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<InventoryTransactionLeg> inventoryTransactionLegs = inventoryTransactionLegDAO.findByQuery(query);
Map<String, Integer> dateWiseProduction = new TreeMap<>();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
Map<LocalDate, List<Long>> 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<LocalDate, List<Long>> entry : dateWiseJobCardIds.entrySet()) {
LocalDate date = entry.getKey();
List<Long> 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<Long> distinctJobCardIds = inventoryTransactionLegs.stream()
.map(InventoryTransactionLeg::getJobCardId)
.filter(id -> id != 0)
.distinct()
.collect(Collectors.toList());
Map<Long, List<CuttingJobCardItemWrapper>> jobCardItemsStitchingDetailsMap = new HashMap<>();
Map<String, Integer> 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> stitchingOfflineItem = stitchingOfflineItemDAO.findByJobCardId(jobCardIdEntry);
List<JobCardItem> jobCardItems = jobCardItemDAO.findByCardId(jobCardIdEntry);
List<CuttingJobCardItemWrapper> 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<StitchingOfflineItem> stitchingItemsTransactions(String jobCardId, String accountId, String sku, String startDate, String endDate) {
List<Long> 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<InventoryTransactionLeg> inventoryTransactionLegs = inventoryTransactionLegDAO.findByQuery(query);
List<Long> 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("");
}
}