From 93f6b01eceae71a2382e146087d1105d3bdbd768 Mon Sep 17 00:00:00 2001 From: Usama Khan Date: Mon, 7 Apr 2025 17:21:10 -0700 Subject: [PATCH] fixed job card progress --- .../controller/ReportingController.java | 11 +- .../dao/ctp/StitchingOfflineItemDAO.java | 7 ++ .../service/ReportingService.java | 109 +++++++++++++++++ src/main/resources/static/js/charts.js | 115 ++++++++---------- .../resources/static/js/vue-components.js | 38 ++++++ .../reporting/job-card-report-sidebar.html | 40 +----- .../templates/reporting/job-card-report.html | 84 +++++++------ 7 files changed, 265 insertions(+), 139 deletions(-) create mode 100644 src/main/java/com/utopiaindustries/service/ReportingService.java diff --git a/src/main/java/com/utopiaindustries/controller/ReportingController.java b/src/main/java/com/utopiaindustries/controller/ReportingController.java index 01ff8a2..490db07 100644 --- a/src/main/java/com/utopiaindustries/controller/ReportingController.java +++ b/src/main/java/com/utopiaindustries/controller/ReportingController.java @@ -3,6 +3,7 @@ package com.utopiaindustries.controller; import com.utopiaindustries.auth.CuttingRole; import com.utopiaindustries.auth.ReportingRole; import com.utopiaindustries.model.ctp.SummaryInventoryReport; +import com.utopiaindustries.service.ReportingService; import com.utopiaindustries.service.SummaryInventoryReportService; import com.utopiaindustries.util.StringUtils; import org.springframework.stereotype.Controller; @@ -20,10 +21,12 @@ import java.util.Map; @ReportingRole @RequestMapping( "/reporting" ) public class ReportingController { + private final ReportingService reportingService; private final SummaryInventoryReportService summaryInventoryReportService; - public ReportingController(SummaryInventoryReportService summaryInventoryReportService2) { + public ReportingController(SummaryInventoryReportService summaryInventoryReportService2, ReportingService reportingService) { this.summaryInventoryReportService = summaryInventoryReportService2; + this.reportingService = reportingService; } @GetMapping( "/summary") @@ -41,9 +44,9 @@ public class ReportingController { } @GetMapping( "/job-card-report") - public String jobCardReport(@RequestParam(value = "item-id", required = false ) String itemId, @RequestParam(value = "sku" , required = false) String sku, @RequestParam(value = "start-date", required = false) String startDate, @RequestParam(value = "end-date", required = false) String endDate, Model model ){ - int progressValue = 75; - model.addAttribute("progressValue", progressValue); + public String jobCardReport(@RequestParam( value = "job-card-id", required = false ) String jobCardId, + Model model ){ + model.addAttribute("jobCardProgress", reportingService.getJobCardProgress(jobCardId)); return "/reporting/job-card-report"; } diff --git a/src/main/java/com/utopiaindustries/dao/ctp/StitchingOfflineItemDAO.java b/src/main/java/com/utopiaindustries/dao/ctp/StitchingOfflineItemDAO.java index ee5670c..6bc1c08 100644 --- a/src/main/java/com/utopiaindustries/dao/ctp/StitchingOfflineItemDAO.java +++ b/src/main/java/com/utopiaindustries/dao/ctp/StitchingOfflineItemDAO.java @@ -28,6 +28,7 @@ public class StitchingOfflineItemDAO { private final String SELECT_BY_IDS = String.format( "SELECT * FROM %s WHERE id IN (:ids)", TABLE_NAME ); private final String SELECT_BY_TERM = String.format( "SELECT * FROM %s WHERE barcode LIKE :term ORDER BY ID DESC", TABLE_NAME ); private final String SELECT_BY_MASTER_ID = String.format( "SELECT * FROM %s WHERE job_card_id = :job_card_id", TABLE_NAME ); + private final String COUNT_TOTAL_QA_ITEMS= String.format("SELECT COUNT(*) FROM %s WHERE job_card_id = :job_card_id AND qa_remarks IS NOT NULL",TABLE_NAME); public StitchingOfflineItemDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) { this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; @@ -141,4 +142,10 @@ public class StitchingOfflineItemDAO { return totalCounts; } + public Long CalculateTotalQA( long jobCardId ){ + MapSqlParameterSource params = new MapSqlParameterSource(); + params.addValue("job_card_id", jobCardId ); + Long count = namedParameterJdbcTemplate.queryForObject(COUNT_TOTAL_QA_ITEMS, params, Long.class); + return count != null ? count : 0; + } } diff --git a/src/main/java/com/utopiaindustries/service/ReportingService.java b/src/main/java/com/utopiaindustries/service/ReportingService.java new file mode 100644 index 0000000..b687313 --- /dev/null +++ b/src/main/java/com/utopiaindustries/service/ReportingService.java @@ -0,0 +1,109 @@ +package com.utopiaindustries.service; + + +import com.utopiaindustries.dao.ctp.*; +import com.utopiaindustries.model.ctp.JobCardItem; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@Service +public class ReportingService { + + private final JobCardItemDAO jobCardItemDAO; + private final CutPieceDAO cutPieceDAO; + 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; + + public ReportingService( JobCardItemDAO jobCardItemDAO, CutPieceDAO cutPieceDAO, BundleDAO bundleDAO, InventoryTransactionLegDAO inventoryTransactionLegDAO, InventoryTransactionDAO inventoryTransactionDAO, JobCardDAO jobCardDAO, CryptographyService cryptographyService, MasterBundleDAO masterBundleDAO, FinishedItemDAO finishedItemDAO, StitchingOfflineItemDAO stitchingOfflineItemDAO) { + this.jobCardItemDAO = jobCardItemDAO; + this.cutPieceDAO = cutPieceDAO; + this.bundleDAO = bundleDAO; + this.inventoryTransactionLegDAO = inventoryTransactionLegDAO; + this.inventoryTransactionDAO = inventoryTransactionDAO; + this.jobCardDAO = jobCardDAO; + this.cryptographyService = cryptographyService; + this.masterBundleDAO = masterBundleDAO; + this.finishedItemDAO = finishedItemDAO; + this.stitchingOfflineItemDAO = stitchingOfflineItemDAO; + } + + public Map getJobCardProgress(String jobCardID){ + if (jobCardID == null){ + return new HashMap<>(); + }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); + + BigDecimal expectedProduction = jobCardItems.stream() + .map(item -> Optional.ofNullable(item.getExpectedProduction()).orElse(BigDecimal.ZERO)) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + if (totalProduction.compareTo(BigDecimal.ZERO) == 0 && actualProduction.compareTo(BigDecimal.ZERO) == 0 ) { + totalProgress.put("Job Card Progress", BigDecimal.ZERO.intValue()); + } else { + if (actualProduction.compareTo(expectedProduction)>0){ + BigDecimal progressPercentage = actualProduction.add(totalProduction) + .divide(actualProduction.multiply(BigDecimal.valueOf(2)), 4, RoundingMode.HALF_UP) + .multiply(BigDecimal.valueOf(100)); + totalProgress.put("Job Card Progress", progressPercentage.intValue()); + }else { + BigDecimal progressPercentage = actualProduction.add(totalProduction) + .divide(expectedProduction.multiply(BigDecimal.valueOf(2)), 4, RoundingMode.HALF_UP) + .multiply(BigDecimal.valueOf(100)); + totalProgress.put("Job Card Progress", progressPercentage.intValue()); + } + } + + if (actualProduction.compareTo(BigDecimal.ZERO) == 0 ) { + totalProgress.put("Cutting Progress", BigDecimal.ZERO.intValue()); + + } else if (actualProduction.compareTo(expectedProduction) < 0) { + BigDecimal cuttingProgress = expectedProduction + .divide(actualProduction, 4, BigDecimal.ROUND_HALF_UP) + .multiply(BigDecimal.valueOf(100)); + totalProgress.put("Cutting Progress", cuttingProgress.intValue()); + }else if (actualProduction.compareTo(expectedProduction) > 0 || actualProduction.compareTo(expectedProduction) == 0){ + totalProgress.put("Cutting Progress", 100); + } + + if (totalProduction.compareTo(BigDecimal.ZERO) == 0){ + totalProgress.put("Stitching Progress", BigDecimal.ZERO.intValue()); + }else { + BigDecimal stitchingProgress = expectedProduction + .divide(totalProduction, 4, BigDecimal.ROUND_HALF_UP) + .multiply(BigDecimal.valueOf(100)); + totalProgress.put("Stitching Progress", stitchingProgress.intValue()); + } + Long qaProgressItems = stitchingOfflineItemDAO.CalculateTotalQA(Long.parseLong(jobCardID)); + if (qaProgressItems == 0){ + totalProgress.put("QA Progress", 0); + }else { + BigDecimal qaProgress = BigDecimal.valueOf(qaProgressItems) + .divide(actualProduction, 4, BigDecimal.ROUND_HALF_UP) + .multiply(BigDecimal.valueOf(100)); + totalProgress.put("QA Progress", qaProgress.intValue()); + } + return totalProgress; + } + } + +} diff --git a/src/main/resources/static/js/charts.js b/src/main/resources/static/js/charts.js index 9f0bf0b..d716511 100644 --- a/src/main/resources/static/js/charts.js +++ b/src/main/resources/static/js/charts.js @@ -4,58 +4,63 @@ document.addEventListener("DOMContentLoaded", function () { return; } - function createGaugeChart(config) { - Highcharts.chart(config.containerId, { + function createGaugeChart(speed, color, divId, title, height, width , fontSize, fontYAxis, fontXAxis, fontColor, total, actual) { + console.log(fontSize) + Highcharts.chart(divId, { chart: { type: 'solidgauge', - width: config.width, - height: config.height, + width: width, + height: height, backgroundColor: 'transparent', plotBackgroundColor: null, shadow: false }, title: { - text: config.title, + text: title, y: 30 }, pane: { startAngle: 0, endAngle: 360, - y: config.CirclePosition, + y: 0, background: [{ backgroundColor: 'transparent', shape: "arc", borderWidth: 0, - innerRadius: config.innerRadius, - outerRadius: config.outerRadius + innerRadius: '60%', + outerRadius: '100%' }] }, yAxis: { - min: config.minValue, - max: config.maxValue, + min: 0, + max: 100, tickPositions: [], lineWidth: 0, minorTickLength: 0, tickWidth: 0, gridLineWidth: 0, stops: [ - [1, config.color] + [1, color] ] }, series: [{ name: 'Percentage', - data: [config.speed], + data: [speed], dataLabels: { - format: '{y}%
' + config.totalPiece + " | " + config.completedPiece, - y: config.InnerTextYPosition, + format: '{y}% ', +// format: '{y}%
' + "Total: "+ total+ "
Complete: " + actual, + y: fontYAxis, + x: fontXAxis, borderWidth: 0, backgroundColor: 'none', style: { - fontSize: config.fontSize, - fontWeight: 'bold' - } + fontSize: fontSize + 'px', + fontWeight: 'bold', + color:fontColor + }, + zIndex: 10 }, - color: config.color, + color: color, showInLegend: false }], credits: { @@ -63,48 +68,36 @@ document.addEventListener("DOMContentLoaded", function () { } }); } - - function createBarChart(config) { - console.log(`Creating bar chart for '${config.containerId}'`); - - if (!document.getElementById(config.containerId)) { - console.error(`Bar chart container '${config.containerId}' not found!`); - return; - } - - Highcharts.chart(config.containerId, { - chart: { - type: 'column', - height: 400, - width: 1600, // Ensure the chart is wider than the container - marginTop: 60, - spacingTop: 30 - }, - xAxis: { - categories: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", - "Next Monday", "Next Tuesday", "Next Wednesday", "Friday", "Saturday", "Sunday"], - labels: { - rotation: -45 // Optional: Rotate labels if needed - } - }, - scrollbar: { - enabled: true // Ensure Highcharts scrollbar is enabled - }, - series: [ - { name: 'Model A', data: [0.8, 0.75, 0.78, 0.79, 0.77, 0.81, 0.80, 0.76, 0.79, 0.80, 0.76, 0.79, 0.80, 0.76, 0.79, 0.80] }, - { name: 'Model B', data: [0.85, 0.78, 0.82, 0.80, 0.79, 0.84, 0.83, 0.78, 0.82, 0.83, 0.76, 0.79, 0.80, 0.76, 0.79, 0.80] }, - { name: 'Model C', data: [0.88, 0.80, 0.85, 0.82, 0.81, 0.87, 0.85, 0.80, 0.85, 0.86, 0.76, 0.79, 0.80, 0.76, 0.79, 0.80] }, - { name: 'Model D', data: [0.9, 0.83, 0.87, 0.84, 0.83, 0.89, 0.88, 0.83, 0.87, 0.88, 0.76, 0.79, 0.80, 0.76, 0.79, 0.80] } - ] - }); - - console.log(`Bar chart '${config.containerId}' created successfully.`); + initializeGauges(); + function initializeGauges() { + const gaugeDivs2 = document.querySelectorAll('.gauge-chart2'); + gaugeDivs2.forEach(function (div) { + const speed = div.getAttribute('data-speed'); + 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(speed), color, divId, title, height, width, fontSize, -20, 4, fontColor, total, actual); + }); + const gaugeDivs = document.querySelectorAll('.gauge-chart'); + gaugeDivs.forEach(function (div) { + const speed = div.getAttribute('data-speed'); + 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; + console.log(title) + createGaugeChart(parseInt(speed), color, divId, title, height, width, fontSize, -15, 2, fontColor, total, actual); + }); } - - - - - - gaugeConfigs.forEach(createGaugeChart); - createBarChart(barChartConfigs); }); diff --git a/src/main/resources/static/js/vue-components.js b/src/main/resources/static/js/vue-components.js index 22e58c4..5af935d 100644 --- a/src/main/resources/static/js/vue-components.js +++ b/src/main/resources/static/js/vue-components.js @@ -3438,6 +3438,44 @@ if ( typeof Vue !== 'undefined' ) { }) +/* + * job card search for reporting + * */ + Vue.component('job-card-for-reporting',{ + mixins: [searchComponentMixin], + methods : { + getSearchUrl : function () { + let url = `/ctp/rest/job-cards/search?term=${encodeURIComponent(this.list.term)}&filter=false`; + if( ! this.filter ){ + url += '&filter=false' + } + return url; + }, + getEmittedEventName: function() { + return 'job-card-select'; + }, + getTitle: function( card ) { + return `(${card.code}) - ${card.createdBy}`; + } + }, + props: { + labelText: { + default: 'Search Job Card' + }, + titleFieldName: { + default: 'cardTitle' + }, + idFieldName: { + default: 'jobCardId' + }, + codeFieldName : { + default : 'jobCardCode' + }, + filter : { + default : true + } + } + }) /* diff --git a/src/main/resources/templates/reporting/job-card-report-sidebar.html b/src/main/resources/templates/reporting/job-card-report-sidebar.html index c54cccb..9c3e82f 100644 --- a/src/main/resources/templates/reporting/job-card-report-sidebar.html +++ b/src/main/resources/templates/reporting/job-card-report-sidebar.html @@ -7,46 +7,12 @@
Refine Your Search
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
- + >
-
- - -
- Reset diff --git a/src/main/resources/templates/reporting/job-card-report.html b/src/main/resources/templates/reporting/job-card-report.html index 17dd4c6..3398dba 100644 --- a/src/main/resources/templates/reporting/job-card-report.html +++ b/src/main/resources/templates/reporting/job-card-report.html @@ -15,26 +15,38 @@
-

Job Card Report

+

Job Card Report

-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
@@ -110,17 +122,15 @@ - - -
-
-
- - - - + + + + + + +
@@ -226,18 +236,18 @@ completedPiece:100 } ]; - const barChartConfigs = { - containerId: "barChart", - title: "Day-wise Performance Metrics", - max:16, - categories: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", "Next Monday", "Next Tuesday", "Next Wednesday", "Friday", "Saturday", "Sunday", "Next Monday", "Next Tuesday", "Next Wednesday"], - series: [ - { name: "Model A", data: [0.8, 0.75, 0.78, 0.76, 0.74, 0.80, 0.77, 0.79, 0.81, 0.76, 0.80, 0.77, 0.79, 0.81, 0.76], color: "#007bff" }, - { name: "Model B", data: [0.85, 0.7, 0.77, 0.79, 0.72, 0.83, 0.78, 0.80, 0.82, 0.75,0.83, 0.78, 0.80, 0.82, 0.75], color: "#28a745" }, - { name: "Model C", data: [0.82, 0.72, 0.79, 0.80, 0.78, 0.85, 0.81, 0.84, 0.86, 0.79, 0.85, 0.81, 0.84, 0.86, 0.79], color: "#dc3545" }, - { name: "Model D", data: [0.88, 0.78, 0.83, 0.85, 0.82, 0.89, 0.85, 0.87, 0.90, 0.83, 0.89, 0.85, 0.87, 0.90, 0.83], color: "#fd7e14" } - ] -}; + + + + + + + + + + + +