add dashboard first screen
parent
88cfa11682
commit
a1446670f5
|
@ -0,0 +1,31 @@
|
|||
package com.utopiaindustries.controller;
|
||||
|
||||
import com.utopiaindustries.service.DashboardService;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.ui.Model;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/dashboard")
|
||||
public class DashboardController {
|
||||
|
||||
private final DashboardService dashboardService;
|
||||
|
||||
public DashboardController(DashboardService dashboardService) {
|
||||
this.dashboardService = dashboardService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public String getDashboard(Model model) {
|
||||
model.addAttribute("phases", dashboardService.getPhasesProgressDayWise());
|
||||
model.addAttribute("date", LocalDate.now());
|
||||
model.addAttribute("day", LocalDate.now().getDayOfWeek());
|
||||
model.addAttribute("line", "Line 1" );
|
||||
model.addAttribute("detail", dashboardService.getLineDetails() );
|
||||
|
||||
return "dashboard";
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package com.utopiaindustries.dao.ctp;
|
||||
|
||||
import com.utopiaindustries.model.ctp.FinishedItem;
|
||||
import com.utopiaindustries.model.ctp.JobCard;
|
||||
import com.utopiaindustries.model.ctp.StitchingOfflineItem;
|
||||
import com.utopiaindustries.util.KeyHolderFunctions;
|
||||
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
||||
|
@ -35,6 +34,7 @@ public class FinishedItemDAO {
|
|||
private final String SELECT_BY_STITCHED_ITEM_IDS = String.format("SELECT * FROM %s WHERE stitched_item_id IN (:stitched_item_ids)", TABLE_NAME);
|
||||
private final String COUNT_TOTAL_FINISH_ITEM = String.format("SELECT COUNT(*) FROM %s WHERE job_card_id = :job_card_id AND is_segregated IS TRUE ", TABLE_NAME);
|
||||
private final String SELECT_BY_JOB_CARD_AND_DATE = String.format("SELECT * FROM %s WHERE job_card_id = :job_card_id AND (:start_date IS NULL OR :end_date IS NULL OR created_at BETWEEN :start_date AND :end_date)", TABLE_NAME);
|
||||
private final String SELECT_BY_DATE = String.format( "SELECT * FROM %s WHERE created_at >=:start_date AND created_at <= :end_date", TABLE_NAME );
|
||||
|
||||
public FinishedItemDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
|
||||
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
|
||||
|
@ -195,4 +195,11 @@ public class FinishedItemDAO {
|
|||
return namedParameterJdbcTemplate.query(SELECT_BY_JOB_CARD_AND_DATE, params, new FinishedItemRowMapper());
|
||||
}
|
||||
|
||||
public List<FinishedItem> findByDate(String startDate, String endDate){
|
||||
MapSqlParameterSource params = new MapSqlParameterSource();
|
||||
params.addValue( "start_date", startDate );
|
||||
params.addValue( "end_date", endDate );
|
||||
return namedParameterJdbcTemplate.query( SELECT_BY_DATE , params, new FinishedItemRowMapper() );
|
||||
}
|
||||
|
||||
}
|
|
@ -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_GROUP_By_TRANSACTION_ACCOUNT_IDS_DATE = String.format("SELECT * FROM %s WHERE account_id IN (:account_ids) AND (:start_date IS NULL OR :end_date IS NULL OR transaction_leg_datetime BETWEEN :start_date AND :end_date) GROUP BY parent_document_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);
|
||||
private final String SELECT_JOB_CARD_And_Date_Type_Account_Id = 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 AND account_id IN (:account_ids)", TABLE_NAME);
|
||||
|
||||
|
@ -218,4 +219,12 @@ public class InventoryTransactionLegDAO {
|
|||
params.addValue("account_ids", accountId );
|
||||
return namedParameterJdbcTemplate.query( SELECT_JOB_CARD_And_Date_Type_Account_Id , params, new InventoryTransactionLegRowMapper() );
|
||||
}
|
||||
|
||||
public List<InventoryTransactionLeg> getTransactionByAndDatesAndAccountID(String startDate, String endDate, List<Integer> accountId){
|
||||
MapSqlParameterSource params = new MapSqlParameterSource();
|
||||
params.addValue("start_date", startDate );
|
||||
params.addValue("end_date", endDate );
|
||||
params.addValue("account_ids", accountId );
|
||||
return namedParameterJdbcTemplate.query( SELECT_GROUP_By_TRANSACTION_ACCOUNT_IDS_DATE , params, new InventoryTransactionLegRowMapper() );
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package com.utopiaindustries.dao.ctp;
|
||||
|
||||
import com.utopiaindustries.model.ctp.FinishedItem;
|
||||
import com.utopiaindustries.model.ctp.PackagingItems;
|
||||
import com.utopiaindustries.util.KeyHolderFunctions;
|
||||
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
||||
|
@ -38,6 +39,7 @@ public class PackagingItemsDAO {
|
|||
"qa_status = VALUES(qa_status), bundle_id = VALUES(bundle_id), account_title = VALUES(account_title)",
|
||||
TABLE_NAME
|
||||
);
|
||||
private final String SELECT_BY_DATE = String.format( "SELECT * FROM %s WHERE created_at >=:start_date AND created_at <= :end_date", TABLE_NAME );
|
||||
|
||||
public PackagingItemsDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
|
||||
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
|
||||
|
@ -96,5 +98,11 @@ public class PackagingItemsDAO {
|
|||
return namedParameterJdbcTemplate.query(SELECT_BY_JOB_CARD_ID, params, new PackagingItemsRowMapper());
|
||||
}
|
||||
|
||||
public List<PackagingItems> findByDate(String startDate, String endDate){
|
||||
MapSqlParameterSource params = new MapSqlParameterSource();
|
||||
params.addValue( "start_date", startDate );
|
||||
params.addValue( "end_date", endDate );
|
||||
return namedParameterJdbcTemplate.query( SELECT_BY_DATE , params, new PackagingItemsRowMapper() );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.utopiaindustries.dao.ctp;
|
||||
|
||||
import com.utopiaindustries.model.ctp.FinishedItem;
|
||||
import com.utopiaindustries.model.ctp.InventoryTransactionLeg;
|
||||
import com.utopiaindustries.model.ctp.StitchingOfflineItem;
|
||||
import com.utopiaindustries.util.KeyHolderFunctions;
|
||||
|
@ -23,7 +24,7 @@ public class StitchingOfflineItemDAO {
|
|||
private final String SELECT_ALL_QUERY = String.format( "SELECT * FROM %s ORDER BY id DESC", TABLE_NAME );
|
||||
private final String SELECT_QUERY_BY_JOB_CARD = String.format( "SELECT * FROM %s WHERE job_card_id = :job_card_id", TABLE_NAME );
|
||||
private final String DELETE_QUERY = String.format( "DELETE FROM %s WHERE id = :id", TABLE_NAME );
|
||||
private final String INSERT_QUERY = String.format( "INSERT INTO %s (id, item_id, sku, barcode, created_at, created_by, job_card_id, is_qa, qa_remarks, qa_status,bundle_id) VALUES (:id, :item_id, :sku, :barcode, :created_at, :created_by, :job_card_id, :is_qa, :qa_remarks, :qa_status, :bundle_id) ON DUPLICATE KEY UPDATE item_id = VALUES(item_id), sku = VALUES(sku), barcode = VALUES(barcode), created_at = VALUES(created_at), created_by = VALUES(created_by), job_card_id = VALUES(job_card_id), is_qa = VALUES(is_qa), qa_remarks = VALUES(qa_remarks), qa_status = VALUES(qa_status), bundle_id = VALUES(bundle_id)", TABLE_NAME );
|
||||
private final String INSERT_QUERY = String.format( "INSERT INTO %s (id, item_id, sku, barcode, created_at, created_by, job_card_id, is_qa, qa_remarks, qa_status,bundle_id, qc_done_at) VALUES (:id, :item_id, :sku, :barcode, :created_at, :created_by, :job_card_id, :is_qa, :qa_remarks, :qa_status, :bundle_id, :qc_done_at) ON DUPLICATE KEY UPDATE item_id = VALUES(item_id), sku = VALUES(sku), barcode = VALUES(barcode), created_at = VALUES(created_at), created_by = VALUES(created_by), job_card_id = VALUES(job_card_id), is_qa = VALUES(is_qa), qa_remarks = VALUES(qa_remarks), qa_status = VALUES(qa_status), bundle_id = VALUES(bundle_id), qc_done_at = VALUES(qc_done_at)", TABLE_NAME );
|
||||
private final String SELECT_BY_LIMIT = String.format("SELECT * FROM %s ORDER BY id DESC LIMIT :limit", TABLE_NAME );
|
||||
private final String FIND_TOTAL_COUNT = String.format("SELECT COUNT(*) FROM %s where job_card_id = :job_card_id And item_id = :item_id", TABLE_NAME );
|
||||
private final String SELECT_BY_IDS = String.format( "SELECT * FROM %s WHERE id IN (:ids)", TABLE_NAME );
|
||||
|
@ -32,6 +33,7 @@ public class StitchingOfflineItemDAO {
|
|||
private final String COUNT_TOTAL_QA_ITEMS= String.format("SELECT COUNT(*) FROM %s WHERE job_card_id = :job_card_id AND is_qa IS TRUE",TABLE_NAME);
|
||||
private final String SELECT_BY_TIME_AND_CARD_ID= String.format("SELECT * FROM %s WHERE job_card_id = :job_card_id ORDER BY created_at DESC LIMIT 1;",TABLE_NAME);
|
||||
private final String SELECT_BY_JOB_CARD_AND_DATE = String.format( "SELECT * FROM %s WHERE job_card_id = :job_card_id AND (:start_date IS NULL OR :end_date IS NULL OR created_at BETWEEN :start_date AND :end_date)", TABLE_NAME );
|
||||
private final String SELECT_BY_DATE = String.format( "SELECT * FROM %s WHERE qc_done_at >=:start_date AND qc_done_at <= :end_date", TABLE_NAME );
|
||||
|
||||
public StitchingOfflineItemDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
|
||||
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
|
||||
|
@ -50,6 +52,7 @@ public class StitchingOfflineItemDAO {
|
|||
.addValue("job_card_id", stitchingOfflineItem.getJobCardId() )
|
||||
.addValue("is_qa", stitchingOfflineItem.getIsQa() )
|
||||
.addValue("qa_remarks", stitchingOfflineItem.getQaRemarks() )
|
||||
.addValue("qc_done_at", stitchingOfflineItem.getQcDoneAt() )
|
||||
.addValue("qa_status", stitchingOfflineItem.getQaStatus() );
|
||||
return params;
|
||||
}
|
||||
|
@ -169,4 +172,11 @@ public class StitchingOfflineItemDAO {
|
|||
params.addValue( "end_date", endDate );
|
||||
return namedParameterJdbcTemplate.query( SELECT_BY_JOB_CARD_AND_DATE , params, new StitchingOfflineItemRowMapper() );
|
||||
}
|
||||
|
||||
public List<StitchingOfflineItem> findByQCDoneDate(String startDate, String endDate){
|
||||
MapSqlParameterSource params = new MapSqlParameterSource();
|
||||
params.addValue( "start_date", startDate );
|
||||
params.addValue( "end_date", endDate );
|
||||
return namedParameterJdbcTemplate.query( SELECT_BY_DATE , params, new StitchingOfflineItemRowMapper() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,9 @@ public class StitchingOfflineItemRowMapper implements RowMapper<StitchingOffline
|
|||
if ( rs.getTimestamp( "created_at" ) != null ) {
|
||||
stitchingOfflineItem.setCreatedAt( rs.getTimestamp( "created_at" ).toLocalDateTime() );
|
||||
}
|
||||
if ( rs.getTimestamp( "qc_done_at" ) != null ) {
|
||||
stitchingOfflineItem.setQcDoneAt( rs.getTimestamp( "qc_done_at" ).toLocalDateTime() );
|
||||
}
|
||||
stitchingOfflineItem.setCreatedBy( rs.getString( "created_by" ) );
|
||||
stitchingOfflineItem.setJobCardId( rs.getLong("job_card_id") );
|
||||
stitchingOfflineItem.setIsQa( rs.getBoolean("is_qa"));
|
||||
|
|
|
@ -14,6 +14,10 @@ public class StitchingOfflineItem implements InventoryArtifact {
|
|||
private long jobCardId;
|
||||
@DateTimeFormat( pattern = "yyyy-MM-dd HH:mm:ss" )
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@DateTimeFormat( pattern = "yyyy-MM-dd HH:mm:ss" )
|
||||
private LocalDateTime qcDoneAt;
|
||||
|
||||
private String createdBy;
|
||||
private boolean isQa;
|
||||
private String qaRemarks;
|
||||
|
@ -125,6 +129,14 @@ public class StitchingOfflineItem implements InventoryArtifact {
|
|||
this.bundleId = bundleId;
|
||||
}
|
||||
|
||||
public LocalDateTime getQcDoneAt() {
|
||||
return qcDoneAt;
|
||||
}
|
||||
|
||||
public void setQcDoneAt(LocalDateTime qcDoneAt) {
|
||||
this.qcDoneAt = qcDoneAt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StitchingOfflineItem{" +
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
package com.utopiaindustries.service;
|
||||
|
||||
import com.utopiaindustries.dao.ctp.*;
|
||||
import com.utopiaindustries.model.ctp.*;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class DashboardService {
|
||||
|
||||
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 DashboardService(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, Float> getPhasesProgressDayWise() {
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
String cuttingAccount = "CUTTING ACCOUNT " +1;
|
||||
String stitchingAccount = "STITCHING ACCOUNT " +1;
|
||||
String finishingAccount = "FINISHING ACCOUNT " +1;
|
||||
String packagingAccount = "A GRADE ACCOUNT " +1;
|
||||
|
||||
String startDate1 = LocalDateTime.now().withHour(0).withMinute(0).withSecond(1).format(formatter);
|
||||
String endDate1 = LocalDateTime.now().withHour(23).withMinute(59).withSecond(59).format(formatter);
|
||||
|
||||
|
||||
HashMap<String, Float> progress = new HashMap<>();
|
||||
|
||||
List<InventoryAccount> inventoryAccounts = inventoryAccountDAO.findAll();
|
||||
|
||||
List<Integer> inventoryAccountIds = inventoryAccounts.stream()
|
||||
.filter(e -> cuttingAccount.equals(e.getTitle()) ||
|
||||
stitchingAccount.equals(e.getTitle()) ||
|
||||
finishingAccount.equals(e.getTitle()) ||
|
||||
packagingAccount.equals(e.getTitle()))
|
||||
.map(e -> (int) e.getId())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
||||
List<InventoryTransactionLeg> inventoryTransactionLeg = inventoryTransactionLegDAO.getTransactionByAndDatesAndAccountID(startDate1, endDate1, inventoryAccountIds);
|
||||
|
||||
|
||||
List<StitchingOfflineItem> stitchingOfflineItems =stitchingOfflineItemDAO.findByQCDoneDate(startDate1, endDate1);
|
||||
|
||||
List<FinishedItem> finishedItems = finishedItemDAO.findByDate(startDate1, endDate1);
|
||||
List<PackagingItems> packagingItems = packagingItemsDAO.findByDate(startDate1, endDate1);
|
||||
|
||||
float stitchingDefectedPiece = stitchingOfflineItems.stream()
|
||||
.filter(e -> "REJECT".equals(e.getQaStatus()))
|
||||
.count();
|
||||
|
||||
float finishedItemDefected = finishedItems.stream()
|
||||
.filter(e -> "ALTER".equals(e.getQaStatus()))
|
||||
.count();
|
||||
|
||||
float finishedItem =finishedItems.stream()
|
||||
.filter(e -> "APPROVED".equals(e.getQaStatus()))
|
||||
.count();
|
||||
|
||||
float finishedItemAGrade = packagingItems.size();
|
||||
|
||||
float finishedItemBGrade = finishedItems.stream()
|
||||
.filter(e -> "B GRADE".equals(e.getQaStatus()))
|
||||
.count();
|
||||
|
||||
float finishedItemCGrade = finishedItems.stream()
|
||||
.filter(e -> "C GRADE".equals(e.getQaStatus()))
|
||||
.count();
|
||||
|
||||
float finishDefectedPiece = finishedItemDefected + finishedItemBGrade + finishedItemCGrade;
|
||||
|
||||
progress.put("Stitching", (float) stitchingOfflineItems.size());
|
||||
progress.put("StitchingDefectPiece", stitchingDefectedPiece);
|
||||
progress.put("StitchingDefectPieceRatio", stitchingDefectedPiece / stitchingOfflineItems.size());
|
||||
|
||||
progress.put("finishing", (float) finishedItems.size());
|
||||
progress.put("finishingDefectPiece", finishDefectedPiece);
|
||||
progress.put("finishingDefectPieceRatio", finishDefectedPiece / finishedItems.size());
|
||||
|
||||
|
||||
progress.put("QA", (float) finishedItems.size());
|
||||
progress.put("Finishing", finishedItem);
|
||||
progress.put("A Grade", finishedItemAGrade);
|
||||
progress.put("B Grade", finishedItemBGrade);
|
||||
progress.put("C Grade", finishedItemCGrade);
|
||||
|
||||
return progress;
|
||||
}
|
||||
|
||||
public Map<String, String> getLineDetails() {
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
String startDate1 = LocalDateTime.now().withHour(0).withMinute(0).withSecond(1).format(formatter);
|
||||
String endDate1 = LocalDateTime.now().withHour(23).withMinute(59).withSecond(59).format(formatter);
|
||||
String startDateWithHour = LocalDateTime.now().minusHours(1).format(formatter);
|
||||
String endDateWithHour =LocalDateTime.now().format(formatter);
|
||||
|
||||
|
||||
HashMap<String, String> details = new HashMap<>();
|
||||
List<PackagingItems> packagingItems = packagingItemsDAO.findByDate(startDate1, endDate1);
|
||||
List<PackagingItems> packagingItemsHourly = packagingItemsDAO.findByDate(startDateWithHour, endDateWithHour);
|
||||
|
||||
List<JobCard> jobCards = jobCardDAO.findAll();
|
||||
int target = 1000;
|
||||
int achieved = packagingItems.size();
|
||||
|
||||
|
||||
details.put("Total Target", 1000 + " pc");
|
||||
details.put("Total Achieved", achieved + " pc");
|
||||
details.put("Hourly Target", 1000/24 + " pc");
|
||||
details.put("Hourly Achieved", packagingItemsHourly.size() + " pc");
|
||||
details.put("Efficiency",(float)achieved / target * 100 + " %" );
|
||||
details.put("Total Induction", String.valueOf(jobCards.size()));
|
||||
details.put("Total Machine", String.valueOf(30));
|
||||
details.put("Total Worker", String.valueOf(30));
|
||||
return details;
|
||||
}
|
||||
}
|
|
@ -83,14 +83,14 @@ public class InventoryService {
|
|||
.collect(Collectors.toList());
|
||||
|
||||
// save updated cut pieces
|
||||
List<CutPiece> cutPieces = jobCardItemWrappers.stream()
|
||||
.flatMap(wrapper -> wrapper.getPieces().stream())
|
||||
.collect(Collectors.toList());
|
||||
cutPieceDAO.saveAll(cutPieces);
|
||||
// List<CutPiece> cutPieces = jobCardItemWrappers.stream()
|
||||
// .flatMap(wrapper -> wrapper.getPieces().stream())
|
||||
// .collect(Collectors.toList());
|
||||
// cutPieceDAO.saveAll(cutPieces);
|
||||
|
||||
Map<Long, List<CutPiece>> piecesMap = cutPieceDAO.findByJobCardItemIds(jobCardItemIds)
|
||||
.stream()
|
||||
.collect(Collectors.groupingBy(CutPiece::getJobCardItemId));
|
||||
// Map<Long, List<CutPiece>> piecesMap = cutPieceDAO.findByJobCardItemIds(jobCardItemIds)
|
||||
// .stream()
|
||||
// .collect(Collectors.groupingBy(CutPiece::getJobCardItemId));
|
||||
|
||||
for (JobCardItem jobCardItem : items) {
|
||||
|
||||
|
@ -536,12 +536,16 @@ public class InventoryService {
|
|||
finishedItems.add(preCreatedItem);
|
||||
}
|
||||
} else {
|
||||
|
||||
FinishedItem preCreatedItem = finishedItemDAO.findByStitchedItem(stitchingOfflineItem.getId());
|
||||
preCreatedItem.setIsQa(false);
|
||||
finishedItemsForUlter.add(preCreatedItem);
|
||||
if (preCreatedItem != null) {
|
||||
preCreatedItem.setIsQa(false);
|
||||
finishedItemsForUlter.add(preCreatedItem);
|
||||
}
|
||||
}
|
||||
stitchingOfflineItem.setIsQa(true);
|
||||
stitchingOfflineItem.setQaStatus(qaStatus);
|
||||
stitchingOfflineItem.setQcDoneAt(LocalDateTime.now());
|
||||
updatedStitchedItems.add(stitchingOfflineItem);
|
||||
}
|
||||
for (FinishedItem finishedItem : finishedItems) {
|
||||
|
@ -604,7 +608,7 @@ public class InventoryService {
|
|||
// get the stitching account id
|
||||
long stitchedItemId = finishedItem.getStitchedItemId();
|
||||
InventoryTransactionLeg lastOutTransaction = lastStitchedItemOutTransactionMap.getOrDefault(stitchedItemId, null);
|
||||
createInventoryTransactionLeg(transaction, finishedItem, lastOutTransaction.getAccountId(), InventoryTransactionLeg.Type.IN.name(), InventoryArtifactType.STITCHING_OFFLINE.name());
|
||||
createInventoryTransactionLeg(transaction, finishedItem, lastOutTransaction.getAccountId(), InventoryTransactionLeg.Type.IN.name(), InventoryArtifactType.FINISHED_ITEM.name());
|
||||
finishedItem.setQaStatus("ALTER");
|
||||
finishedItem.setIsSegregated(false);
|
||||
}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 8.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
Binary file not shown.
After Width: | Height: | Size: 9.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
|
@ -136,6 +136,60 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
}]
|
||||
});
|
||||
}
|
||||
function dashboardChart(divId, height, width, title, aHeading, aData, bHeading, bData, cHeading, cData, dHeading, dData, dates, fontSize, maxValue) {
|
||||
if (!document.getElementById(divId)) {
|
||||
return;
|
||||
}
|
||||
Highcharts.chart(divId, {
|
||||
chart: {
|
||||
type: 'bar',
|
||||
width:700,
|
||||
height:280
|
||||
|
||||
},
|
||||
title: {
|
||||
text: title
|
||||
},
|
||||
xAxis: {
|
||||
},
|
||||
yAxis: {
|
||||
max: maxValue,
|
||||
min: 0,
|
||||
title: {
|
||||
align: 'high'
|
||||
},
|
||||
labels: {
|
||||
overflow: 'justify'
|
||||
},
|
||||
gridLineWidth: 0
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: '50%',
|
||||
dataLabels: {
|
||||
enabled: true
|
||||
},
|
||||
groupPadding: 0.1
|
||||
}
|
||||
},
|
||||
credits: {
|
||||
enabled: false
|
||||
},
|
||||
series: [{
|
||||
name: aHeading,
|
||||
data: aData
|
||||
}, {
|
||||
name: bHeading,
|
||||
data: bData
|
||||
}, {
|
||||
name: cHeading,
|
||||
data: cData
|
||||
}, {
|
||||
name: dHeading,
|
||||
data: dData
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
function createSingleBarChart(divId, height, width, title,Heading, Data, dates, fontSize, maxValue) {
|
||||
if (!document.getElementById(divId)) {
|
||||
|
@ -260,6 +314,52 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
createBarChart( divId, height, width, title, aHeading, aData, bHeading, bData, cHeading, cData, dHeading, dData, datesArray, fontSize, maxValue);
|
||||
});
|
||||
|
||||
const dashboardBarChart = document.querySelectorAll('.dashboardBarChart'); // fixed name
|
||||
dashboardBarChart.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 rawValue = div.getAttribute('data-totalProduction') || "0";
|
||||
const cleanValue = rawValue.replace(/[^0-9.-]+/g, '');
|
||||
const maxValue = Number(cleanValue);
|
||||
const aHeading = 'Achieved';
|
||||
const aDataString = div.getAttribute('data-achieved');
|
||||
const cleanValueAchieved = aDataString.replace(/[^0-9.-]+/g, '');
|
||||
const aData = [Number(cleanValueAchieved)];
|
||||
const bHeading = 'Stitching';
|
||||
const bDataString = div.getAttribute('data-stitching');
|
||||
const cleanValueStitch = bDataString.replace(/[^0-9.-]+/g, '');
|
||||
const bData = [Number(cleanValueStitch)];
|
||||
const cHeading = 'End Line Quality Checking';
|
||||
const cDataString =div.getAttribute('data-quality');
|
||||
const cleanValueQuality = cDataString.replace(/[^0-9.-]+/g, '');
|
||||
const cData = [Number(cleanValueQuality)];
|
||||
const dHeading = 'Packaging';
|
||||
const dDataString = div.getAttribute('data-packaging');
|
||||
const cleanValuePackaging = dDataString.replace(/[^0-9.-]+/g, '');
|
||||
const dData = [Number(cleanValuePackaging)];
|
||||
const dates = [div.getAttribute('data-dates')];
|
||||
const divId = div.id;
|
||||
dashboardChart(
|
||||
divId,
|
||||
height,
|
||||
width,
|
||||
title,
|
||||
aHeading,
|
||||
aData,
|
||||
bHeading,
|
||||
bData,
|
||||
cHeading,
|
||||
cData,
|
||||
dHeading,
|
||||
dData,
|
||||
dates,
|
||||
fontSize,
|
||||
maxValue
|
||||
);
|
||||
});
|
||||
|
||||
const cuttingBarChart = document.querySelectorAll('.singleBarChart');
|
||||
cuttingBarChart.forEach(function (div) {
|
||||
const title = div.getAttribute('data-title');
|
||||
|
|
|
@ -0,0 +1,261 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ctp="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head th:replace="_fragments :: head('Production Dashboard')">
|
||||
<style>
|
||||
/* Large screen specific styles */
|
||||
@media (min-width: 1600px) {
|
||||
body {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
.stats-panel h5 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
.card-text {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
.dashboardBarChart {
|
||||
min-height: 400px !important;
|
||||
}
|
||||
|
||||
.card-img-top {
|
||||
width: 200px !important;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
padding: 2rem 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Extra large screens (4K and above) */
|
||||
@media (min-width: 2500px) {
|
||||
body {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.stats-panel h5 {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
|
||||
.card-text {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.dashboardBarChart {
|
||||
min-height: 500px !important;
|
||||
}
|
||||
|
||||
.card-img-top {
|
||||
width: 250px !important;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
padding: 3rem 4rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="m-0 p-0">
|
||||
<div class="container-fluid px-0">
|
||||
<header class="header shadow py-2 bg-black text-white" style="background-color: black !important;">
|
||||
<div class="container-fluid d-flex flex-wrap align-items-center justify-content-between">
|
||||
<img width="200" class="logo img-fluid" th:src="@{/img/utopia-industries-white.png}" alt="Utopia Industries">
|
||||
<div class="d-flex flex-wrap justify-content-end">
|
||||
<h1 class="px-2 fw-bold text-uppercase m-0" th:text="${{day}}"></h1>
|
||||
<h1 class="px-2 fw-bold text-uppercase m-0" th:text="${{date}}"></h1>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="container-fluid main-content">
|
||||
<div class="row page-main g-4 p-3">
|
||||
<!-- Stats Panel -->
|
||||
<div class="col-lg-6 d-flex flex-column align-items-center justify-content-start border border-black-50 stats-panel">
|
||||
<div class="w-100 text-center mb-4">
|
||||
<h1 class="fw-bold text-uppercase m-0" th:text="${{line}}"></h1>
|
||||
</div>
|
||||
|
||||
<div class="row g-4 w-100">
|
||||
<!-- Row 1 -->
|
||||
<div class="col-md-6 d-flex align-items-center justify-content-between px-4 py-3 border-right">
|
||||
<h5 class="fw-bold m-0">Total Target</h5>
|
||||
<h5 class="fw-bold m-0" th:text="${detail.get('Total Target')}"></h5>
|
||||
</div>
|
||||
<div class="col-md-6 d-flex align-items-center justify-content-between px-4 py-3">
|
||||
<h5 class="fw-bold m-0">Total Achieved</h5>
|
||||
<h5 class="fw-bold m-0" th:text="${detail.get('Total Achieved')}"></h5>
|
||||
</div>
|
||||
|
||||
<!-- Row 2 -->
|
||||
<div class="col-md-6 d-flex align-items-center justify-content-between px-4 py-3 border-right">
|
||||
<h5 class="fw-bold m-0">Hourly Target</h5>
|
||||
<h5 class="fw-bold m-0" th:text="${detail.get('Hourly Target')}"></h5>
|
||||
</div>
|
||||
<div class="col-md-6 d-flex align-items-center justify-content-between px-4 py-3">
|
||||
<h5 class="fw-bold m-0">Hourly Achieved</h5>
|
||||
<h5 class="fw-bold m-0" th:text="${detail.get('Hourly Achieved')}"></h5>
|
||||
</div>
|
||||
|
||||
<!-- Row 3 -->
|
||||
<div class="col-md-6 d-flex align-items-center justify-content-between px-4 py-3 border-right">
|
||||
<h5 class="fw-bold m-0">Efficiency</h5>
|
||||
<h5 class="fw-bold m-0" th:text="${detail.get('Efficiency')}"></h5>
|
||||
</div>
|
||||
<div class="col-md-6 d-flex align-items-center justify-content-between px-4 py-3">
|
||||
<h5 class="fw-bold m-0">Total Induction</h5>
|
||||
<h5 class="fw-bold m-0" th:text="${detail.get('Total Induction')}"></h5>
|
||||
</div>
|
||||
|
||||
<!-- Row 4 -->
|
||||
<div class="col-md-6 d-flex align-items-center justify-content-between px-4 py-3 border-right">
|
||||
<h5 class="fw-bold m-0">Total Workers</h5>
|
||||
<h5 class="fw-bold m-0" th:text="${detail.get('Total Worker')}"></h5>
|
||||
</div>
|
||||
<div class="col-md-6 d-flex align-items-center justify-content-between px-4 py-3">
|
||||
<h5 class="fw-bold m-0">Total Machines</h5>
|
||||
<h5 class="fw-bold m-0" th:text="${detail.get('Total Machine')}"></h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Card 1: Stitching -->
|
||||
<div class="col-lg-3 d-flex">
|
||||
<div class="card w-100 h-100">
|
||||
<div class="container-fluid d-flex p-3 align-items-center">
|
||||
<img style="width:200px" th:src="@{/img/stitchingImage.jpg}" class="card-img-top" alt="Stitching">
|
||||
<div class="ps-4 text-center">
|
||||
<h1 class="fw-bold text-uppercase m-0" th:text="${phases.get('Stitching')?.intValue() ?: 0}"></h1>
|
||||
<h4 class="pt-2 fw-bold text-uppercase m-0">Stitching Offline</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body text-center d-flex justify-content-center p-4">
|
||||
<div class="px-4 border-right" style="height: 150px">
|
||||
<h2 class="card-text" th:text="${phases.get('StitchingDefectPiece')?.intValue() ?: 0}"></h2>
|
||||
<h4 class="card-title">Defected QTY</h4>
|
||||
</div>
|
||||
<div class="px-4" style="height: 150px">
|
||||
<h2 class="card-text" th:text="${#numbers.formatDecimal(phases.get('StitchingDefectPieceRatio') ?: 0, 1, 2)} +' %'"></h2>
|
||||
<h4 class="card-title">Defected Ratio</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Card 2: Quality -->
|
||||
<div class="col-lg-3 d-flex">
|
||||
<div class="card w-100 h-100">
|
||||
<div class="container-fluid d-flex align-items-center">
|
||||
<img style="width:200px;height:170px" th:src="@{/img/quality.png}" class="card-img-top" alt="Quality">
|
||||
<div class="ps-4 text-center">
|
||||
<h1 class="fw-bold text-uppercase m-0" th:text="${phases.get('Stitching')?.intValue() ?: 0}"></h1>
|
||||
<h4 class="pt-2 fw-bold text-uppercase m-0">End Line QC</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body text-center d-flex justify-content-center ">
|
||||
<div class="px-4 border-right" style="height: 150px">
|
||||
<h2 class="card-text" th:text="${phases.get('StitchingDefectPiece')?.intValue() ?: 0}"></h2>
|
||||
<h4 class="card-title">Defected QTY</h4>
|
||||
</div>
|
||||
<div class="px-4" style="height: 150px">
|
||||
<h2 class="card-text" th:text="${#numbers.formatDecimal(phases.get('StitchingDefectPieceRatio') ?: 0, 1, 2)} +' %'"></h2>
|
||||
<h4 class="card-title">Defected Ratio</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Second Row -->
|
||||
<div class="row g-4 p-3">
|
||||
<!-- Chart -->
|
||||
<div class="col-lg-6 d-flex border border-black-50">
|
||||
<div id="dashboardBarChart" class="dashboardBarChart w-100"
|
||||
style="min-height: 400px;"
|
||||
th:data-title="'Days Wise Progress'"
|
||||
th:data-dates="${date}"
|
||||
th:data-achieved="${detail.get('Total Achieved')}"
|
||||
th:data-stitching="${phases.get('Stitching')?.intValue() ?: 0}"
|
||||
th:data-quality="${phases.get('Stitching')?.intValue() ?: 0}"
|
||||
th:data-packaging="${phases.get('A Grade')?.intValue() ?: 0}"
|
||||
th:data-totalProduction="${detail.get('Total Target')}"
|
||||
th:data-fontSize="22">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Card 3: Finishing -->
|
||||
<div class="col-lg-3 d-flex">
|
||||
<div class="card w-100 h-100">
|
||||
<div class="container-fluid d-flex p-3 align-items-center">
|
||||
<img style="width:200px" th:src="@{/img/finishing.jfif}" class="card-img-top" alt="Finishing">
|
||||
<div class="ps-4 text-center">
|
||||
<h1 class="fw-bold text-uppercase m-0" th:text="${phases.get('finishing')?.intValue() ?: 0}"></h1>
|
||||
<h4 class="pt-2 fw-bold text-uppercase m-0">Finishing</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body text-center d-flex justify-content-center p-4">
|
||||
<div class="px-4 border-right" style="height: 150px">
|
||||
<h2 class="card-text" th:text="${phases.get('finishingDefectPiece')?.intValue() ?: 0}"></h2>
|
||||
<h4 class="card-title">Defected QTY</h4>
|
||||
</div>
|
||||
<div class="px-4" style="height: 150px">
|
||||
<h2 class="card-text" th:text="${#numbers.formatDecimal(phases.get('finishingDefectPieceRatio') ?: 0, 1, 2)} +' %'"></h2>
|
||||
<h4 class="card-title">Defected Ratio</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Card 4: Packaging -->
|
||||
<div class="col-lg-3 d-flex">
|
||||
<div class="card w-100 h-100">
|
||||
<div class="container-fluid d-flex p-3 align-items-center">
|
||||
<img style="width:200px" th:src="@{/img/packaging.jfif}" class="card-img-top" alt="Packaging">
|
||||
<div class="ps-4 text-center">
|
||||
<h1 class="fw-bold text-uppercase m-0" th:text="${phases.get('A Grade')?.intValue() ?: 0}"></h1>
|
||||
<h4 class="pt-2 fw-bold text-uppercase m-0">Packaging</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body text-center d-flex justify-content-center p-4">
|
||||
<div class="px-4 border-right" style="height: 150px">
|
||||
<h2 class="card-text" th:text="${phases.get('A Grade')?.intValue() ?: 0}"></h2>
|
||||
<h4 class="card-title">A GRADE</h4>
|
||||
</div>
|
||||
<div class="px-4 border-right" style="height: 150px">
|
||||
<h2 class="card-text" th:text="${phases.get('B Grade')?.intValue() ?: 0}"></h2>
|
||||
<h4 class="card-title">B GRADE</h4>
|
||||
</div>
|
||||
<div class="px-4" style="height: 150px">
|
||||
<h2 class="card-text" th:text="${phases.get('C Grade')?.intValue() ?: 0}"></h2>
|
||||
<h4 class="card-title">C GRADE</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script th:src="@{/js/charts.js}"></script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue