diff --git a/src/main/java/com/utopiaindustries/auth/InventoryAccountRole.java b/src/main/java/com/utopiaindustries/auth/InventoryAccountRole.java new file mode 100644 index 0000000..bb55e8f --- /dev/null +++ b/src/main/java/com/utopiaindustries/auth/InventoryAccountRole.java @@ -0,0 +1,14 @@ +package com.utopiaindustries.auth; + +import org.springframework.security.access.prepost.PreAuthorize; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.TYPE}) +@PreAuthorize("hasAnyRole('ROLE_INVENTORY_ACCOUNT','ROLE_ADMIN')") +public @interface InventoryAccountRole { +} diff --git a/src/main/java/com/utopiaindustries/controller/InventoryAccountController.java b/src/main/java/com/utopiaindustries/controller/InventoryAccountController.java index 30f0400..6f3057d 100644 --- a/src/main/java/com/utopiaindustries/controller/InventoryAccountController.java +++ b/src/main/java/com/utopiaindustries/controller/InventoryAccountController.java @@ -1,16 +1,15 @@ package com.utopiaindustries.controller; -import com.utopiaindustries.auth.AdminRole; +import com.utopiaindustries.auth.InventoryAccountRole; import com.utopiaindustries.model.ctp.InventoryAccount; import com.utopiaindustries.service.InventoryAccountService; -import com.utopiaindustries.util.StringUtils; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.mvc.support.RedirectAttributes; @Controller -@AdminRole +@InventoryAccountRole @RequestMapping( "/inventory-accounts" ) public class InventoryAccountController { diff --git a/src/main/java/com/utopiaindustries/dao/ctp/FinishedItemDAO.java b/src/main/java/com/utopiaindustries/dao/ctp/FinishedItemDAO.java index 3977c18..fc4ff9a 100644 --- a/src/main/java/com/utopiaindustries/dao/ctp/FinishedItemDAO.java +++ b/src/main/java/com/utopiaindustries/dao/ctp/FinishedItemDAO.java @@ -196,7 +196,7 @@ public class FinishedItemDAO { return namedParameterJdbcTemplate.query(SELECT_BY_JOB_CARD_AND_DATE, params, new FinishedItemRowMapper()); } - public Long findByOperationDoneDate(String startDate, String endDate, String qaStatus, List ids){ + public Long findByOperationDateAndIdsAndQaStatus(String startDate, String endDate, String qaStatus, List ids){ MapSqlParameterSource params = new MapSqlParameterSource(); params.addValue( "start_date", startDate ); params.addValue( "end_date", endDate ); diff --git a/src/main/java/com/utopiaindustries/dao/ctp/InventoryAccountDAO.java b/src/main/java/com/utopiaindustries/dao/ctp/InventoryAccountDAO.java index 1719428..95b0aee 100644 --- a/src/main/java/com/utopiaindustries/dao/ctp/InventoryAccountDAO.java +++ b/src/main/java/com/utopiaindustries/dao/ctp/InventoryAccountDAO.java @@ -20,7 +20,26 @@ public class InventoryAccountDAO { private final String SELECT_QUERY = String.format( "SELECT * FROM %s WHERE id = :id", TABLE_NAME ); private final String SELECT_ALL_QUERY = String.format( "SELECT * FROM %s ORDER BY title DESC", 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, title, parent_entity_type, parent_entity_id, active, created_by, created_at, location_site_id, notes, is_packaging) VALUES (:id, :title, :parent_entity_type, :parent_entity_id, :active, :created_by, :created_at, :location_site_id, :notes, :is_packaging) ON DUPLICATE KEY UPDATE title = VALUES(title), parent_entity_type = VALUES(parent_entity_type), parent_entity_id = VALUES(parent_entity_id), active = VALUES(active), created_by = VALUES(created_by), created_at = VALUES(created_at), location_site_id = VALUES(location_site_id), notes = VALUES(notes), is_packaging = VALUES(is_packaging)", TABLE_NAME ); + private final String INSERT_QUERY = String.format( + "INSERT INTO %s (id, title, parent_entity_type, parent_entity_id, active, created_by, created_at, location_site_id, notes, is_packaging, article_name, shift_minutes, total_machines, efficiency, sam) " + + "VALUES (:id, :title, :parent_entity_type, :parent_entity_id, :active, :created_by, :created_at, :location_site_id, :notes, :is_packaging, :article_name, :shift_minutes, :total_machines, :efficiency, :sam) " + + "ON DUPLICATE KEY UPDATE " + + "title = VALUES(title), " + + "parent_entity_type = VALUES(parent_entity_type), " + + "parent_entity_id = VALUES(parent_entity_id), " + + "active = VALUES(active), " + + "created_by = VALUES(created_by), " + + "created_at = VALUES(created_at), " + + "location_site_id = VALUES(location_site_id), " + + "notes = VALUES(notes), " + + "is_packaging = VALUES(is_packaging), " + + "article_name = VALUES(article_name), " + + "shift_minutes = VALUES(shift_minutes), " + + "efficiency = VALUES(efficiency), " + + "sam = VALUES(sam), " + + "total_machines = VALUES(total_machines)", + TABLE_NAME + ); private final String SELECT_BY_IDS = String.format( "SELECT * FROM %s WHERE id IN (:ids)", TABLE_NAME ); private final String SELECT_BY_IDS_AND_PARENT_ID = String.format( "SELECT * FROM %s WHERE active = TRUE AND id IN (:ids) AND parent_entity_id = :parent_entity_id", TABLE_NAME ); private final String SELECT_BY_IDS_AND_PARENT_IDS = String.format( "SELECT * FROM %s WHERE active = TRUE AND id IN (:ids) AND parent_entity_id IN (:parent_entity_ids)", TABLE_NAME ); @@ -45,6 +64,11 @@ public class InventoryAccountDAO { .addValue( "created_at", inventoryAccount.getCreatedAt() ) .addValue( "location_site_id", inventoryAccount.getLocationSiteId() ) .addValue( "notes", inventoryAccount.getNotes() ) + .addValue( "article_name", inventoryAccount.getArticleName() ) + .addValue( "total_machines", inventoryAccount.getTotalMachines() ) + .addValue( "shift_minutes", inventoryAccount.getShiftMinutes() ) + .addValue( "efficiency", inventoryAccount.getEfficiency() ) + .addValue( "sam", inventoryAccount.getSam() ) .addValue("is_packaging", inventoryAccount.getIsPackaging() ); return params; } diff --git a/src/main/java/com/utopiaindustries/dao/ctp/InventoryAccountRowMapper.java b/src/main/java/com/utopiaindustries/dao/ctp/InventoryAccountRowMapper.java index 1442d83..d015aea 100644 --- a/src/main/java/com/utopiaindustries/dao/ctp/InventoryAccountRowMapper.java +++ b/src/main/java/com/utopiaindustries/dao/ctp/InventoryAccountRowMapper.java @@ -20,6 +20,11 @@ public class InventoryAccountRowMapper implements RowMapper { } inventoryAccount.setLocationSiteId( rs.getInt( "location_site_id" ) ); inventoryAccount.setNotes( rs.getString( "notes" ) ); + inventoryAccount.setArticleName( rs.getString( "article_name" ) ); + inventoryAccount.setShiftMinutes( rs.getLong( "shift_minutes" ) ); + inventoryAccount.setTotalMachines( rs.getLong( "total_machines" ) ); + inventoryAccount.setEfficiency( rs.getBigDecimal( "efficiency" ) ); + inventoryAccount.setSam( rs.getBigDecimal( "sam" ) ); inventoryAccount.setIsPackaging( rs.getBoolean("is_packaging" ) ); return inventoryAccount; } diff --git a/src/main/java/com/utopiaindustries/dao/ctp/InventoryTransactionLegDAO.java b/src/main/java/com/utopiaindustries/dao/ctp/InventoryTransactionLegDAO.java index 6a5d757..839781d 100644 --- a/src/main/java/com/utopiaindustries/dao/ctp/InventoryTransactionLegDAO.java +++ b/src/main/java/com/utopiaindustries/dao/ctp/InventoryTransactionLegDAO.java @@ -221,7 +221,7 @@ public class InventoryTransactionLegDAO { return namedParameterJdbcTemplate.query( SELECT_JOB_CARD_And_Date_Type_Account_Id , params, new InventoryTransactionLegRowMapper() ); } - public List getParentIDsOFRemainingINVENTORY(String parentType, Integer accountId){ + public List findRemainingByParentTypeAndAccountID(String parentType, Integer accountId){ MapSqlParameterSource params = new MapSqlParameterSource(); params.addValue("account_id", accountId ); params.addValue("parent_document_type", parentType ); diff --git a/src/main/java/com/utopiaindustries/dao/ctp/PackagingItemsDAO.java b/src/main/java/com/utopiaindustries/dao/ctp/PackagingItemsDAO.java index 4d83629..8ddefbe 100644 --- a/src/main/java/com/utopiaindustries/dao/ctp/PackagingItemsDAO.java +++ b/src/main/java/com/utopiaindustries/dao/ctp/PackagingItemsDAO.java @@ -98,7 +98,7 @@ public class PackagingItemsDAO { return namedParameterJdbcTemplate.query(SELECT_BY_JOB_CARD_ID, params, new PackagingItemsRowMapper()); } - public Long findByDateANDIDs(String startDate, String endDate,List ids){ + public Long findByDateAndIds(String startDate, String endDate,List ids){ MapSqlParameterSource params = new MapSqlParameterSource(); params.addValue( "start_date", startDate ); params.addValue( "end_date", endDate ); diff --git a/src/main/java/com/utopiaindustries/dao/ctp/StitchingOfflineItemDAO.java b/src/main/java/com/utopiaindustries/dao/ctp/StitchingOfflineItemDAO.java index ff8b5f8..53c5d31 100644 --- a/src/main/java/com/utopiaindustries/dao/ctp/StitchingOfflineItemDAO.java +++ b/src/main/java/com/utopiaindustries/dao/ctp/StitchingOfflineItemDAO.java @@ -174,7 +174,7 @@ public class StitchingOfflineItemDAO { return namedParameterJdbcTemplate.query( SELECT_BY_JOB_CARD_AND_DATE , params, new StitchingOfflineItemRowMapper() ); } - public Long findByQCDoneDate(String startDate, String endDate, String qaStatus, List ids){ + public Long findByQCOperationDateAndIds(String startDate, String endDate, String qaStatus, List ids){ MapSqlParameterSource params = new MapSqlParameterSource(); params.addValue( "start_date", startDate ); params.addValue( "end_date", endDate ); @@ -183,7 +183,7 @@ public class StitchingOfflineItemDAO { Long count = namedParameterJdbcTemplate.queryForObject(SELECT_BY_DATE_QA_STATUS, params, Long.class); return count != null ? count : 0; } - public Long findByQCDoneDateApproved(String startDate, String endDate, String qaStatus){ + public Long findByQCOperationDateAndApproved(String startDate, String endDate, String qaStatus){ MapSqlParameterSource params = new MapSqlParameterSource(); params.addValue( "start_date", startDate ); params.addValue( "end_date", endDate ); diff --git a/src/main/java/com/utopiaindustries/model/Roles.java b/src/main/java/com/utopiaindustries/model/Roles.java index 7a8abbd..864dca6 100644 --- a/src/main/java/com/utopiaindustries/model/Roles.java +++ b/src/main/java/com/utopiaindustries/model/Roles.java @@ -10,5 +10,6 @@ public enum Roles { ROLE_FINISHING, ROLE_PACKAGING, ROLE_REPORTING, - ROLE_PURCHASE_ORDER + ROLE_PURCHASE_ORDER, + ROLE_INVENTORY_ACCOUNT } diff --git a/src/main/java/com/utopiaindustries/model/ctp/InventoryAccount.java b/src/main/java/com/utopiaindustries/model/ctp/InventoryAccount.java index 5b3ff7e..331f528 100644 --- a/src/main/java/com/utopiaindustries/model/ctp/InventoryAccount.java +++ b/src/main/java/com/utopiaindustries/model/ctp/InventoryAccount.java @@ -1,5 +1,6 @@ package com.utopiaindustries.model.ctp; +import java.math.BigDecimal; import java.time.LocalDateTime; public class InventoryAccount { @@ -14,6 +15,12 @@ public class InventoryAccount { private Integer locationSiteId; private String notes; private Boolean isPackaging; + private String articleName; + private long shiftMinutes; + private long totalMachines; + private BigDecimal efficiency; + private BigDecimal sam; + //wrapper private String locationTitle; @@ -105,6 +112,45 @@ public class InventoryAccount { this.locationTitle = locationTitle; } + public String getArticleName() { + return articleName; + } + + public void setArticleName(String articleName) { + this.articleName = articleName; + } + + public long getShiftMinutes() { + return shiftMinutes; + } + + public void setShiftMinutes(long shiftMinutes) { + this.shiftMinutes = shiftMinutes; + } + + public long getTotalMachines() { + return totalMachines; + } + + public void setTotalMachines(long totalMachines) { + this.totalMachines = totalMachines; + } + + public BigDecimal getEfficiency() { + return efficiency; + } + + public void setEfficiency(BigDecimal efficiency) { + this.efficiency = efficiency; + } + + public BigDecimal getSam() { + return sam; + } + + public void setSam(BigDecimal sam) { + this.sam = sam; + } @Override public String toString() { @@ -119,6 +165,10 @@ public class InventoryAccount { ", locationSiteId=" + locationSiteId + ", notes='" + notes + '\'' + ", isPackaging=" + isPackaging + + ", articleName='" + articleName + '\'' + + ", shiftMinutes=" + shiftMinutes + + ", totalMachines=" + totalMachines + + ", efficiency=" + efficiency + ", locationTitle='" + locationTitle + '\'' + '}'; } diff --git a/src/main/java/com/utopiaindustries/service/DashboardService.java b/src/main/java/com/utopiaindustries/service/DashboardService.java index 62b6eee..b2da69c 100644 --- a/src/main/java/com/utopiaindustries/service/DashboardService.java +++ b/src/main/java/com/utopiaindustries/service/DashboardService.java @@ -4,7 +4,11 @@ import com.utopiaindustries.dao.ctp.*; import com.utopiaindustries.model.ctp.*; import org.springframework.stereotype.Service; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.Duration; import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; @@ -37,7 +41,9 @@ public class DashboardService { String finishingAccount = "FINISHING ACCOUNT " + lineNo; String packagingAccount = "A GRADE ACCOUNT " + lineNo; - String startDate1 = LocalDateTime.now().withHour(0).withMinute(0).withSecond(1).format(formatter); + LocalDateTime today = LocalDateTime.now().withHour(0).withMinute(0).withSecond(1); + + String startDate1 = today.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); @@ -47,6 +53,9 @@ public class DashboardService { List inventoryAccounts = inventoryAccountDAO.findAll(); + InventoryAccount inventoryAccount = inventoryAccounts.stream() + .filter(e -> cuttingAccount.equals(e.getTitle())).findFirst().orElse(new InventoryAccount()); + Map inventoryAccountMap = inventoryAccounts.stream() .filter(e -> cuttingAccount.equals(e.getTitle()) || stitchingAccount.equals(e.getTitle()) || @@ -55,16 +64,17 @@ public class DashboardService { .collect(Collectors.toMap(InventoryAccount::getTitle, e -> (int) e.getId())); - List stitchingItemIds = inventoryTransactionLegDAO.getParentIDsOFRemainingINVENTORY("STITCHING_OFFLINE", inventoryAccountMap.get(stitchingAccount)); + List stitchingItemIds = inventoryTransactionLegDAO.findRemainingByParentTypeAndAccountID("STITCHING_OFFLINE", inventoryAccountMap.get(stitchingAccount)); + List finishing = inventoryTransactionLegDAO.getInParentIdIdByDate("FINISHED_ITEM", inventoryAccountMap.get(finishingAccount)); - List packagingItemIDs = inventoryTransactionLegDAO.getParentIDsOFRemainingINVENTORY("PACKAGING", inventoryAccountMap.get(packagingAccount)); + List packagingItemIDs = inventoryTransactionLegDAO.findRemainingByParentTypeAndAccountID("PACKAGING", inventoryAccountMap.get(packagingAccount)); Long approvedStitchingOfflineItems = 0L; - Long qcReject = 0L; + long qcReject = 0L; if (stitchingItemIds != null && !stitchingItemIds.isEmpty()) { - approvedStitchingOfflineItems = stitchingOfflineItemDAO.findByQCDoneDateApproved(startDate1, endDate1, "APPROVED"); - qcReject = stitchingOfflineItemDAO.findByQCDoneDate(null, endDate1, "REJECT", stitchingItemIds); + approvedStitchingOfflineItems = stitchingOfflineItemDAO.findByQCOperationDateAndApproved(startDate1, endDate1, "APPROVED"); + qcReject = stitchingOfflineItemDAO.findByQCOperationDateAndIds(null, endDate1, "REJECT", stitchingItemIds); } Long alterationPieceFinish = 0L; @@ -74,21 +84,35 @@ public class DashboardService { Long operationNotPerformed = 0L; if (finishing != null && !finishing.isEmpty()) { - approved = finishedItemDAO.findByOperationDoneDate(startDate1, endDate1, "APPROVED", finishing); - operationNotPerformed = finishedItemDAO.findByOperationDoneDate(null, endDate1, "-", finishing); - rejectFinishedItem = finishedItemDAO.findByOperationDoneDate(null, endDate1, "REJECT", finishing); - washFinishedItem = finishedItemDAO.findByOperationDoneDate(startDate1, endDate1, "WASHED", finishing); - alterationPieceFinish = finishedItemDAO.findByOperationDoneDate(null, endDate1, "ALTER", finishing); + approved = finishedItemDAO.findByOperationDateAndIdsAndQaStatus(startDate1, endDate1, "APPROVED", finishing); + operationNotPerformed = finishedItemDAO.findByOperationDateAndIdsAndQaStatus(null, endDate1, "-", finishing); + rejectFinishedItem = finishedItemDAO.findByOperationDateAndIdsAndQaStatus(null, endDate1, "REJECT", finishing); + washFinishedItem = finishedItemDAO.findByOperationDateAndIdsAndQaStatus(startDate1, endDate1, "WASHED", finishing); + alterationPieceFinish = finishedItemDAO.findByOperationDateAndIdsAndQaStatus(null, endDate1, "ALTER", finishing); } Long packagingItems = 0L; - Long packagingItemsHourly = 0L; if (packagingItemIDs != null && !packagingItemIDs.isEmpty()) { - packagingItems = packagingItemsDAO.findByDateANDIDs(startDate1, endDate1, packagingItemIDs); - packagingItemsHourly = packagingItemsDAO.findByDateANDIDs(startDateWithHour, endDateWithHour, packagingItemIDs); + packagingItems = packagingItemsDAO.findByDateAndIds(startDate1, endDate1, packagingItemIDs); } + LocalDateTime statTime = LocalDateTime.now().withHour(9).withMinute(0).withSecond(0).withNano(0); + LocalDateTime endTime = statTime.plusMinutes(inventoryAccount.getShiftMinutes()); + + long minutesPassed = 0; + + if (statTime.isBefore(LocalDateTime.now()) && LocalDateTime.now().isBefore(endTime)) { + minutesPassed = Duration.between(statTime, LocalDateTime.now()).toMinutes(); + } + + long shiftTargetMinutesWise = getTargetShiftWiseOrHourlyWise(Math.max(0, minutesPassed), inventoryAccount); + float efficiency; + if (shiftTargetMinutesWise == 0) { + efficiency = 0f; + } else { + efficiency = (float) approvedStitchingOfflineItems / shiftTargetMinutesWise; + } progress.put("Stitching", (float) approvedStitchingOfflineItems + qcReject); progress.put("totalWips", (float) stitchingItemIds.size() - qcReject); progress.put("Alteration", (float) qcReject); @@ -97,32 +121,50 @@ public class DashboardService { progress.put("ALTER", (float) alterationPieceFinish); progress.put("Reject", (float) rejectFinishedItem); progress.put("wash", (float) washFinishedItem); + progress.put("packaging", (float) packagingItems); - progress.put("Shift Achieved", (float) packagingItems); - progress.put("Efficiency", (float) packagingItems / 1000 * 100); - progress.put("Hourly Achieved", Float.valueOf(packagingItemsHourly)); - - + progress.put("Efficiency",efficiency); return progress; } public Map getLineDetails(String lineNo) { String cuttingAccount = "CUTTING ACCOUNT " + lineNo; List inventoryAccounts = inventoryAccountDAO.findAll(); - String articleNote = inventoryAccounts.stream() - .filter(e -> cuttingAccount.equals(e.getTitle())) - .map(InventoryAccount::getNotes).findFirst().orElse(null); + InventoryAccount inventoryAccount = inventoryAccounts.stream() + .filter(e -> cuttingAccount.equals(e.getTitle())).findFirst().orElse(new InventoryAccount()); + + int shiftTarget = getTargetShiftWiseOrHourlyWise(inventoryAccount.getShiftMinutes(), inventoryAccount); + int shiftHourlyTarget = getTargetShiftWiseOrHourlyWise(60, inventoryAccount); HashMap details = new HashMap<>(); - List jobCards = jobCardDAO.findAll(); - details.put("Shift Target", 1000 + " Pcs"); - details.put("articleNote", articleNote); - details.put("Hourly Target", 1000 / 24 + " Pcs"); - details.put("Total Induction", String.valueOf(jobCards.size())); - details.put("Total Machine", String.valueOf(30)); + details.put("Shift Target", shiftTarget + " Pcs"); + details.put("articleName", inventoryAccount.getArticleName()); + details.put("Hourly Target", shiftHourlyTarget + " Pcs"); + details.put("Total Machine", String.valueOf(inventoryAccount.getTotalMachines())); details.put("Total Worker", String.valueOf(30)); details.put("line", "Line " + lineNo); return details; } + + //formula for calculating targets --> machine * shiftTime * Efficiency / SAM + private int getTargetShiftWiseOrHourlyWise(long minutes, InventoryAccount inventoryAccount) { + if (inventoryAccount == null || + inventoryAccount.getTotalMachines() == 0 || + inventoryAccount.getEfficiency() == null || + inventoryAccount.getSam() == null) { + return 0; + } + BigDecimal totalMachines = BigDecimal.valueOf(inventoryAccount.getTotalMachines()); + BigDecimal efficiency = inventoryAccount.getEfficiency(); + BigDecimal sam = inventoryAccount.getSam(); + BigDecimal totalShiftProductiveTime = totalMachines + .multiply(BigDecimal.valueOf(minutes)) + .multiply(efficiency); + if (sam.longValue() != 0) { + return totalShiftProductiveTime.divide(sam, 0, RoundingMode.HALF_UP).intValueExact(); + } + return 0; + } + } diff --git a/src/main/resources/templates/_fragments.html b/src/main/resources/templates/_fragments.html index f6924ac..3ffc86f 100644 --- a/src/main/resources/templates/_fragments.html +++ b/src/main/resources/templates/_fragments.html @@ -94,6 +94,15 @@ class="dropdown-item">User And Roles + @@ -44,7 +44,7 @@

+ th:text="${phases.get('packaging')?.intValue() ?: 0}">

Achieved

@@ -87,7 +87,7 @@

0%

+ th:text="${#numbers.formatDecimal(phases.get('Efficiency'), 1, 2) + ' %'}">0%

Efficiency

@@ -100,7 +100,6 @@ -