diff --git a/src/main/java/com/utopiaindustries/controller/ReportingController.java b/src/main/java/com/utopiaindustries/controller/ReportingController.java index 9da4f1c..54ea0a3 100644 --- a/src/main/java/com/utopiaindustries/controller/ReportingController.java +++ b/src/main/java/com/utopiaindustries/controller/ReportingController.java @@ -54,6 +54,7 @@ public class ReportingController { model.addAttribute("jobCardProgress", reportingService.getJobCardProgress(jobCardId)); model.addAttribute("cuttingDetails", reportingService.getCuttingDetails(jobCardId)); model.addAttribute("stitchingDetails", reportingService.getStitchingDetails(jobCardId)); + model.addAttribute("dailyProgress", reportingService.getPhasesProgressDayWise(jobCardId)); return "/reporting/job-card-report"; } diff --git a/src/main/java/com/utopiaindustries/dao/ctp/InventoryTransactionLegDAO.java b/src/main/java/com/utopiaindustries/dao/ctp/InventoryTransactionLegDAO.java index e29293a..9b3667c 100644 --- a/src/main/java/com/utopiaindustries/dao/ctp/InventoryTransactionLegDAO.java +++ b/src/main/java/com/utopiaindustries/dao/ctp/InventoryTransactionLegDAO.java @@ -48,6 +48,7 @@ public class InventoryTransactionLegDAO { private final String COUNT_TOTAL_SEGREGATE_ITEMS = String.format("SELECT COUNT(*) FROM %s WHERE parent_document_id IN (:parent_document_id) AND account_id = :account_id", TABLE_NAME); private final String SELECT_FIRST_TRANSACTION_PARENT_TYPE_PARENT_ID = String.format("SELECT * FROM %s WHERE parent_document_id IN (:parent_document_id) AND parent_document_type = :parent_document_type ORDER BY transaction_leg_datetime ASC LIMIT 1", TABLE_NAME); private final String SELECT_GROUP_By_TRANSACTION_PARENT_TYPE_PARENT_ID = String.format("SELECT * FROM %s WHERE parent_document_id IN (:parent_document_id) AND parent_document_type = :parent_document_type GROUP BY account_id", TABLE_NAME); + private final String SELECT_JOB_CARD_DATES = String.format("SELECT * FROM %s WHERE job_card_id = :job_card_id AND (:start_date IS NULL OR :end_date IS NULL OR transaction_leg_datetime BETWEEN :start_date AND :end_date) AND type = :type ", TABLE_NAME); public InventoryTransactionLegDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) { this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; @@ -189,4 +190,13 @@ public class InventoryTransactionLegDAO { params.addValue("parent_document_type", parentType ); return namedParameterJdbcTemplate.query( SELECT_GROUP_By_TRANSACTION_PARENT_TYPE_PARENT_ID , params, new InventoryTransactionLegRowMapper() ); } + + public List getTransactionByJobCardAndDatesAndType(long jobCardID, String startDate, String endDate, String type){ + MapSqlParameterSource params = new MapSqlParameterSource(); + params.addValue("job_card_id", jobCardID ); + params.addValue("start_date", startDate ); + params.addValue("end_date", endDate ); + params.addValue("type", type ); + return namedParameterJdbcTemplate.query( SELECT_JOB_CARD_DATES , params, new InventoryTransactionLegRowMapper() ); + } } \ No newline at end of file diff --git a/src/main/java/com/utopiaindustries/dao/ctp/SummaryInventoryReportDao.java b/src/main/java/com/utopiaindustries/dao/ctp/SummaryInventoryReportDao.java index d834950..d84f3fe 100644 --- a/src/main/java/com/utopiaindustries/dao/ctp/SummaryInventoryReportDao.java +++ b/src/main/java/com/utopiaindustries/dao/ctp/SummaryInventoryReportDao.java @@ -13,7 +13,7 @@ public class SummaryInventoryReportDao { private final NamedParameterJdbcTemplate namedParameterJdbcTemplate; private final String TABLE_NAME = "cut_to_pack.inventory_transaction_leg "; - String SELECT_QUERY = "SELECT item_id, account_id, parent_document_id, DATE(transaction_leg_datetime) AS transaction_date, " + String SELECT_QUERY = "SELECT job_card_id, item_id, account_id, parent_document_id, DATE(transaction_leg_datetime) AS transaction_date, " + "sku, parent_document_type, parent_document_piece_type, " + "SUM(CASE WHEN type = 'IN' THEN 1 ELSE 0 END) AS total_in, " + "SUM(CASE WHEN type = 'OUT' THEN 1 ELSE 0 END) AS total_out " diff --git a/src/main/java/com/utopiaindustries/dao/ctp/SummaryInventoryReportRowMapper.java b/src/main/java/com/utopiaindustries/dao/ctp/SummaryInventoryReportRowMapper.java index aceb783..eca6a64 100644 --- a/src/main/java/com/utopiaindustries/dao/ctp/SummaryInventoryReportRowMapper.java +++ b/src/main/java/com/utopiaindustries/dao/ctp/SummaryInventoryReportRowMapper.java @@ -15,6 +15,7 @@ public class SummaryInventoryReportRowMapper implements RowMapper> getPhasesProgressDayWise(String jobCardID) { + if (jobCardID == null) { + return Collections.emptyMap(); + } + 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 ("FINISHED_ITEM".equals(leg.getParentDocumentType()) && (leg.getAccountId().equals(8) || leg.getAccountId().equals(9) || leg.getAccountId().equals(10))) { + 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; + } + + + private StringBuilder generateTime(LocalDateTime startDate, LocalDateTime endDate){ StringBuilder totalTime = new StringBuilder(); if(startDate != null && endDate != null){ diff --git a/src/main/resources/static/js/charts.js b/src/main/resources/static/js/charts.js index 8ec6c0f..88d82b8 100644 --- a/src/main/resources/static/js/charts.js +++ b/src/main/resources/static/js/charts.js @@ -69,12 +69,13 @@ document.addEventListener("DOMContentLoaded", function () { } }); } - function createBarChart(config, height, width, title) { - if (!document.getElementById(config.containerId)) { + function createBarChart(divId, height, width, title, aHeading, aData, bHeading, bData, cHeading, cData, dHeading, dData, dates, fontSize, maxValue) { + if (!document.getElementById(divId)) { return; } + console.log(maxValue); - Highcharts.chart(config.containerId, { + Highcharts.chart(divId, { chart: { type: 'column', height: height, @@ -82,44 +83,58 @@ document.addEventListener("DOMContentLoaded", function () { }, title: { text: title, - align: 'center', // Optionally align title in center + align: 'center', verticalAlign: 'top', - y: 30 // Offset from top + y: 30, + style: { + fontSize: fontSize, + fontWeight: 'bold', + } }, xAxis: { - categories: [ - "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", - "Next Monday", "Next Tuesday", "Next Wednesday", "Next Friday", "Next Saturday", "Next Sunday" - ], + categories: dates, labels: { - rotation: -45 // Optional: Rotate labels if needed + rotation: -45, + style: { + fontSize: 10-fontSize, + fontWeight: 'bold' + } } }, yAxis: { min: 0, - max: 100, + max: maxValue, + softMax: maxValue, + softMin: 0, + startOnTick: true, + endOnTick: true, title: { - text: 'Total Progress' + text: 'Total Progress', + style: { + fontSize: fontSize, + fontWeight: 'bold', + } }, labels: { format: '{value}%' } }, + scrollbar: { - enabled: true // Ensure Highcharts scrollbar is enabled + enabled: true }, series: [{ - name: 'Model A', - data: [100, 75, 78, 79, 77, 81, 80, 76, 79, 80, 76, 79, 80, 76, 79, 80, 80] + name: aHeading, + data: aData }, { - name: 'Model B', - data: [85, 78, 82, 80, 79, 84, 83, 78, 82, 83, 76, 79, 80, 76, 79, 80, 85] + name: bHeading, + data: bData }, { - name: 'Model C', - data: [88, 80, 85, 82, 81, 87, 85, 80, 85, 86, 76, 79, 80, 76, 79, 80, 88] + name: cHeading, + data: cData }, { - name: 'Model D', - data: [90, 83, 87, 84, 83, 89, 88, 83, 87, 88, 76, 79, 80, 76, 79, 80, 90] + name: dHeading, + data: dData }] }); } @@ -127,19 +142,19 @@ document.addEventListener("DOMContentLoaded", function () { initializeGauges(); function initializeGauges() { const gaugeDivs2 = document.querySelectorAll('.gauge-chart2'); - gaugeDivs2.forEach(function (div) { - const progress = div.getAttribute('data-progress'); - const color = div.getAttribute('data-color'); - const title = div.getAttribute('data-title'); - const height = div.getAttribute('data-height'); - const width = div.getAttribute('data-width'); - const fontSize = div.getAttribute('data-fontSize'); - const fontColor = div.getAttribute('data-fontColor'); - const total = div.getAttribute('data-totalProduction'); - const actual = div.getAttribute('data-actualProduction'); - const divId = div.id; - createGaugeChart(parseInt(progress), color, divId, title, height, width, fontSize, -20, 4, fontColor, total, actual); - }); + gaugeDivs2.forEach(function (div) { + const progress = div.getAttribute('data-progress'); + const color = div.getAttribute('data-color'); + const title = div.getAttribute('data-title'); + const height = div.getAttribute('data-height'); + const width = div.getAttribute('data-width'); + const fontSize = div.getAttribute('data-fontSize'); + const fontColor = div.getAttribute('data-fontColor'); + const total = div.getAttribute('data-totalProduction'); + const actual = div.getAttribute('data-actualProduction'); + const divId = div.id; + createGaugeChart(parseInt(progress), color, divId, title, height, width, fontSize, -20, 4, fontColor, total, actual); + }); const gaugeDivs = document.querySelectorAll('.gauge-chart'); gaugeDivs.forEach(function (div) { const progress = div.getAttribute('data-progress'); @@ -157,26 +172,27 @@ document.addEventListener("DOMContentLoaded", function () { const divId = div.id; createGaugeChart(parseInt(progress), color, divId, title, height, width, fontSize, -15, 2, fontColor, total, actual, aGrade, bGrade, cGrade); + }); + const barChart = document.querySelectorAll('.barChart'); + barChart.forEach(function (div) { + const title = div.getAttribute('data-title'); + const height = div.getAttribute('data-height'); + const width = div.getAttribute('data-width'); + const fontSize = div.getAttribute('data-fontSize'); + const maxValue = Number(div.getAttribute('data-totalProduction')); + const aHeading = 'Cutting'; + const aData = JSON.parse(div.getAttribute('data-cutting')); + const bHeading='Stitching'; + const bData =JSON.parse(div.getAttribute('data-stitching')); + const cHeading='End Line Quality Checking'; + const cData =JSON.parse(div.getAttribute('data-quality')); + const dHeading="Finish Items"; + const dData =JSON.parse(div.getAttribute('data-finishing')); + const dates = div.getAttribute('data-dates'); + const datesArray = dates.split(','); + const divId = div.id; + console.log(maxValue, typeof maxValue) + createBarChart( divId, height, width, title,aHeading,aData,bHeading,bData,cHeading,cData,dHeading,dData,datesArray,fontSize,maxValue); }); - - const barChart = document.querySelectorAll('.barChart'); - barChart.forEach(function (div) { - const progress = div.getAttribute('data-progress'); - const color = div.getAttribute('data-color'); - const title = div.getAttribute('data-title'); - const height = div.getAttribute('data-height'); - const width = div.getAttribute('data-width'); - const fontSize = div.getAttribute('data-fontSize'); - const fontColor = div.getAttribute('data-fontColor'); - const total = div.getAttribute('data-totalProduction'); - const actual = div.getAttribute('data-actualProduction'); - const aGrade = div.getAttribute('data-aGrade'); - const bGrade = div.getAttribute('data-bGrade'); - const cGrade = div.getAttribute('data-cGrade'); - const divId = div.id; - createBarChart(barChartConfigs, height, width, title,); - - }); - } }); diff --git a/src/main/resources/templates/reporting/job-card-report.html b/src/main/resources/templates/reporting/job-card-report.html index 5f0d6f4..285a116 100644 --- a/src/main/resources/templates/reporting/job-card-report.html +++ b/src/main/resources/templates/reporting/job-card-report.html @@ -127,14 +127,21 @@ - + -
-
+
+ th:data-dates="${dailyProgress.get('dates')}" + th:data-cutting="${dailyProgress.get('cutting')}" + th:data-stitching="${dailyProgress.get('stitching')}" + th:data-quality="${dailyProgress.get('quality')}" + th:data-finishing="${dailyProgress.get('finishing')}" + th:data-totalProduction="${completeProduction.get('Cutting Progress')}" + th:data-fontSize="30" + >
@@ -146,120 +153,6 @@ - -