add Cutting Report dashboard

add-reporting-dashboard
Usama Khan 2025-04-18 13:12:10 -07:00
parent 91d6fdaa89
commit a2fe57d256
20 changed files with 713 additions and 128 deletions

View File

@ -395,7 +395,7 @@
<jvmArguments>-Xms1024m</jvmArguments> <jvmArguments>-Xms1024m</jvmArguments>
<jvmArguments>-Xmx8g</jvmArguments> <jvmArguments>-Xmx8g</jvmArguments>
</configuration> </configuration>
</plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>8</source><target>8</target></configuration></plugin> </plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>9</source><target>9</target></configuration></plugin>
</plugins> </plugins>
</build> </build>
</project> </project>

View File

@ -1,9 +1,8 @@
package com.utopiaindustries.controller; package com.utopiaindustries.controller;
import com.utopiaindustries.auth.CuttingRole;
import com.utopiaindustries.auth.ReportingRole; import com.utopiaindustries.auth.ReportingRole;
import com.utopiaindustries.model.ctp.JobCardItem;
import com.utopiaindustries.model.ctp.SummaryInventoryReport; import com.utopiaindustries.model.ctp.SummaryInventoryReport;
import com.utopiaindustries.service.InventoryAccountService;
import com.utopiaindustries.service.ReportingService; import com.utopiaindustries.service.ReportingService;
import com.utopiaindustries.service.SummaryInventoryReportService; import com.utopiaindustries.service.SummaryInventoryReportService;
import com.utopiaindustries.util.StringUtils; import com.utopiaindustries.util.StringUtils;
@ -19,7 +18,6 @@ import java.time.LocalDate;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
@Controller @Controller
@ReportingRole @ReportingRole
@ -27,10 +25,13 @@ import java.util.stream.Collectors;
public class ReportingController { public class ReportingController {
private final ReportingService reportingService; private final ReportingService reportingService;
private final SummaryInventoryReportService summaryInventoryReportService; private final SummaryInventoryReportService summaryInventoryReportService;
private final InventoryAccountService inventoryAccountService;
public ReportingController(SummaryInventoryReportService summaryInventoryReportService2, ReportingService reportingService) {
public ReportingController(SummaryInventoryReportService summaryInventoryReportService2, ReportingService reportingService, InventoryAccountService inventoryAccountService) {
this.summaryInventoryReportService = summaryInventoryReportService2; this.summaryInventoryReportService = summaryInventoryReportService2;
this.reportingService = reportingService; this.reportingService = reportingService;
this.inventoryAccountService = inventoryAccountService;
} }
@GetMapping( "/summary") @GetMapping( "/summary")
@ -68,8 +69,9 @@ public class ReportingController {
} }
@GetMapping( "/po-report") @GetMapping( "/po-report")
public String poReport( Model model){ public String poReport(@RequestParam(value = "poName", required = false) String poName, Model model){
model.addAttribute("allPOs", reportingService.getAllPOs());
model.addAttribute("allPOs", reportingService.getAllPOs(poName));
return "/reporting/po-report"; return "/reporting/po-report";
} }
@ -80,6 +82,19 @@ public class ReportingController {
return "/reporting/po-job-card-report"; return "/reporting/po-job-card-report";
} }
@GetMapping( value = "/cutting-report" )
public String cuttingReport(@RequestParam(value = "job-card-id", required = false ) String jobCardId, @RequestParam(value = "accountId" , required = false) String accountId, @RequestParam(value = "start-date", required = false) String startDate, @RequestParam(value = "end-date", required = false) String endDate, Model model ){
LocalDate startDate1 = StringUtils.isNullOrEmpty(startDate) ? LocalDate.now().minusDays(31) : LocalDate.parse(startDate);
LocalDate endDate1 = StringUtils.isNullOrEmpty(endDate) ? LocalDate.now() : LocalDate.parse(endDate);
model.addAttribute("startDate", startDate1);
model.addAttribute("endDate", endDate1);
model.addAttribute("accounts", inventoryAccountService.getAllCuttingAccounts() );
model.addAttribute("cutting",reportingService.getCuttingTableDetails(jobCardId, accountId, startDate1.toString(), endDate1.toString()));
return "/reporting/cutting-report";
}
private ArrayList<LocalDate> generateDateList(LocalDate start, LocalDate end) { private ArrayList<LocalDate> generateDateList(LocalDate start, LocalDate end) {
ArrayList<LocalDate> localDates = new ArrayList<>(); ArrayList<LocalDate> localDates = new ArrayList<>();
while (start.isBefore(end)) { while (start.isBefore(end)) {

View File

@ -1,9 +1,9 @@
package com.utopiaindustries.dao.ctp; package com.utopiaindustries.dao.ctp;
import com.utopiaindustries.model.ctp.Bundle;
import com.utopiaindustries.model.ctp.InventorySummary; import com.utopiaindustries.model.ctp.InventorySummary;
import com.utopiaindustries.model.ctp.InventoryTransactionLeg; import com.utopiaindustries.model.ctp.InventoryTransactionLeg;
import com.utopiaindustries.util.KeyHolderFunctions; import com.utopiaindustries.util.KeyHolderFunctions;
import com.utopiaindustries.util.StringUtils;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.support.GeneratedKeyHolder; import org.springframework.jdbc.support.GeneratedKeyHolder;
@ -55,6 +55,10 @@ public class InventoryTransactionLegDAO {
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
} }
public List<InventoryTransactionLeg> findByQuery(String query ){
return namedParameterJdbcTemplate.query( query, new InventoryTransactionLegRowMapper() );
}
// prepare query params // prepare query params
private MapSqlParameterSource prepareInsertQueryParams( InventoryTransactionLeg inventoryTransactionLeg ) { private MapSqlParameterSource prepareInsertQueryParams( InventoryTransactionLeg inventoryTransactionLeg ) {
MapSqlParameterSource params = new MapSqlParameterSource(); MapSqlParameterSource params = new MapSqlParameterSource();

View File

@ -23,10 +23,10 @@ public class JobCardDAO {
private final String SELECT_ALL_QUERY = String.format( "SELECT * FROM %s ORDER BY id DESC", TABLE_NAME ); private final String SELECT_ALL_QUERY = String.format( "SELECT * FROM %s ORDER BY id DESC", TABLE_NAME );
private final String SELECT_ALL_QUERY_WITH_LIMIT = String.format( "SELECT * FROM %s ORDER BY id DESC limit :limit", TABLE_NAME ); private final String SELECT_ALL_QUERY_WITH_LIMIT = String.format( "SELECT * FROM %s ORDER BY id DESC limit :limit", TABLE_NAME );
private final String DELETE_QUERY = String.format( "DELETE FROM %s WHERE id = :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, code, job_order_id, created_at, created_by, status, inventory_status, customer, lot_number, purchase_order_id, location_site_id, description) VALUES (:id, :code, :job_order_id, :created_at, :created_by, :status, :inventory_status, :customer, :lot_number, :purchase_order_id, :location_site_id, :description) ON DUPLICATE KEY UPDATE code = VALUES(code), job_order_id = VALUES(job_order_id), created_at = VALUES(created_at), created_by = VALUES(created_by), status = VALUES(status), inventory_status = VALUES(inventory_status), customer = VALUES(customer), lot_number = VALUES(lot_number), purchase_order_id = VALUES(purchase_order_id), location_site_id = VALUES(location_site_id), description = VALUES(description)", TABLE_NAME ); private final String INSERT_QUERY = String.format( "INSERT INTO %s (id, code, job_order_id, created_at, created_by, status, inventory_status, customer, lot_number, purchase_order_id, location_site_id, description, poQuantity, articleName) VALUES (:id, :code, :job_order_id, :created_at, :created_by, :status, :inventory_status, :customer, :lot_number, :purchase_order_id, :location_site_id, :description, :poQuantity, :articleName) ON DUPLICATE KEY UPDATE code = VALUES(code), job_order_id = VALUES(job_order_id), created_at = VALUES(created_at), created_by = VALUES(created_by), status = VALUES(status), inventory_status = VALUES(inventory_status), customer = VALUES(customer), lot_number = VALUES(lot_number), purchase_order_id = VALUES(purchase_order_id), location_site_id = VALUES(location_site_id), description = VALUES(description), poQuantity = VALUES(poQuantity), articleName = VALUES(articleName) ", TABLE_NAME );
private final String SELECT_BY_LIKE_CODE_AND_INV_STATUS_AND_STATUS = String.format( "SELECT * FROM %s WHERE code like :code AND status = :status AND inventory_status = :inventory_status", TABLE_NAME ); private final String SELECT_BY_LIKE_CODE_AND_INV_STATUS_AND_STATUS = String.format( "SELECT * FROM %s WHERE code like :code AND status = :status AND inventory_status = :inventory_status", TABLE_NAME );
private final String SELECT_BY_LIKE_CODE = String.format( "SELECT * FROM %s WHERE code like :code", TABLE_NAME ); private final String SELECT_BY_LIKE_CODE = String.format( "SELECT * FROM %s WHERE code like :code", TABLE_NAME );
private final String SELECT_BY_LIMIT = String.format( "SELECT * FROM %s WHERE created_by = :created_by ORDER BY id DESC limit :limit", TABLE_NAME ); private final String SELECT_BY_LIMIT = String.format( "SELECT * FROM %s WHERE created_by = :created_by ORDER BY id ASC limit :limit", TABLE_NAME );
// prepare query params // prepare query params
private MapSqlParameterSource prepareInsertQueryParams( JobCard jobCard ) { private MapSqlParameterSource prepareInsertQueryParams( JobCard jobCard ) {
@ -39,6 +39,8 @@ public class JobCardDAO {
.addValue("status", jobCard.getStatus() ) .addValue("status", jobCard.getStatus() )
.addValue("inventory_status", jobCard.getInventoryStatus() ) .addValue("inventory_status", jobCard.getInventoryStatus() )
.addValue("customer", jobCard.getCustomer() ) .addValue("customer", jobCard.getCustomer() )
.addValue("poQuantity", jobCard.getPoQuantity() )
.addValue("articleName", jobCard.getArticleName() )
.addValue("lot_number", jobCard.getLotNumber() ) .addValue("lot_number", jobCard.getLotNumber() )
.addValue("purchase_order_id", jobCard.getPurchaseOrderId() ) .addValue("purchase_order_id", jobCard.getPurchaseOrderId() )
.addValue("location_site_id", jobCard.getLocationSiteId() ) .addValue("location_site_id", jobCard.getLocationSiteId() )

View File

@ -1,7 +1,6 @@
package com.utopiaindustries.dao.ctp; package com.utopiaindustries.dao.ctp;
import com.utopiaindustries.model.ctp.JobCardItem; import com.utopiaindustries.model.ctp.JobCardItem;
import com.utopiaindustries.model.ctp.MasterBundle;
import com.utopiaindustries.util.KeyHolderFunctions; import com.utopiaindustries.util.KeyHolderFunctions;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
@ -11,7 +10,6 @@ import org.springframework.stereotype.Repository;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
@Repository @Repository
public class JobCardItemDAO { public class JobCardItemDAO {
@ -28,6 +26,7 @@ public class JobCardItemDAO {
private final String SELECT_BY_IDS = String.format( "SELECT * FROM %s WHERE id IN (:ids)", TABLE_NAME ); private final String SELECT_BY_IDS = String.format( "SELECT * FROM %s WHERE id IN (:ids)", TABLE_NAME );
private final String SELECT_BY_JOB_CARD_AND_ACCOUNT_IDS = String.format( "SELECT * FROM %s WHERE job_card_id = :job_card_id AND account_id IN (:account_ids) AND is_complete = FALSE ", TABLE_NAME ); private final String SELECT_BY_JOB_CARD_AND_ACCOUNT_IDS = String.format( "SELECT * FROM %s WHERE job_card_id = :job_card_id AND account_id IN (:account_ids) AND is_complete = FALSE ", TABLE_NAME );
private final String SELECT_ALL_ACTIVE_ITEM = String.format("SELECT CASE WHEN MIN(is_complete) = TRUE THEN TRUE ELSE FALSE END FROM %s WHERE job_card_id = :job_card_id AND id IN (:id)", TABLE_NAME); private final String SELECT_ALL_ACTIVE_ITEM = String.format("SELECT CASE WHEN MIN(is_complete) = TRUE THEN TRUE ELSE FALSE END FROM %s WHERE job_card_id = :job_card_id AND id IN (:id)", TABLE_NAME);
private final String SELECT_BY_JOB_CARD_IDS = String.format( "SELECT * FROM %s WHERE job_card_id IN (:job_card_id)", TABLE_NAME );
public JobCardItemDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) { public JobCardItemDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
@ -131,4 +130,10 @@ public class JobCardItemDAO {
Boolean allComplete = namedParameterJdbcTemplate.queryForObject(SELECT_ALL_ACTIVE_ITEM, params, Boolean.class); Boolean allComplete = namedParameterJdbcTemplate.queryForObject(SELECT_ALL_ACTIVE_ITEM, params, Boolean.class);
return Boolean.TRUE.equals(allComplete); return Boolean.TRUE.equals(allComplete);
} }
public List<JobCardItem> findByJobCardIds(List<Long> ids){
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("job_card_id", ids);
return namedParameterJdbcTemplate.query( SELECT_BY_JOB_CARD_IDS, params, new JobCardItemRowMapper() );
}
} }

View File

@ -22,6 +22,7 @@ public class JobCardItemRowMapper implements RowMapper<JobCardItem> {
jobCardItem.setGsm( rs.getString("gsm" ) ); jobCardItem.setGsm( rs.getString("gsm" ) );
jobCardItem.setWtPly( rs.getString("wt_ply" ) ); jobCardItem.setWtPly( rs.getString("wt_ply" ) );
jobCardItem.setPly( rs.getString("ply" ) ); jobCardItem.setPly( rs.getString("ply" ) );
jobCardItem.setComplete( rs.getBoolean("is_complete" ) );
return jobCardItem; return jobCardItem;
} }
} }

View File

@ -23,6 +23,8 @@ public class JobCardRowMapper implements RowMapper<JobCard> {
jobCard.setPurchaseOrderId( rs.getString("purchase_order_id") ); jobCard.setPurchaseOrderId( rs.getString("purchase_order_id") );
jobCard.setLocationSiteId( rs.getLong("location_site_id" ) ); jobCard.setLocationSiteId( rs.getLong("location_site_id" ) );
jobCard.setDescription( rs.getString("description" ) ); jobCard.setDescription( rs.getString("description" ) );
jobCard.setPoQuantity( rs.getInt("poQuantity" ) );
jobCard.setArticleName( rs.getString("articleName" ) );
return jobCard; return jobCard;
} }
} }

View File

@ -0,0 +1,150 @@
package com.utopiaindustries.model.ctp;
public class CuttingJobCardItemWrapper {
private long jobCardId;
private String poName;
private String sku;
private Long totalCutting;
private String width;
private String length;
private String gsm;
private String wtPly;
private String ply;
private String articleName;
private boolean isComplete;
private String jobCardCode;
private String cuttingOperatorName;
private long cuttingAccountId;
public long getJobCardId() {
return jobCardId;
}
public void setJobCardId(long jobCardId) {
this.jobCardId = jobCardId;
}
public String getPoName() {
return poName;
}
public void setPoName(String poName) {
this.poName = poName;
}
public String getSku() {
return sku;
}
public void setSku(String sku) {
this.sku = sku;
}
public Long getTotalCutting() {
return totalCutting;
}
public void setTotalCutting(Long totalCutting) {
this.totalCutting = totalCutting;
}
public String getWidth() {
return width;
}
public void setWidth(String width) {
this.width = width;
}
public String getGsm() {
return gsm;
}
public void setGsm(String gsm) {
this.gsm = gsm;
}
public String getWtPly() {
return wtPly;
}
public void setWtPly(String wtPly) {
this.wtPly = wtPly;
}
public String getPly() {
return ply;
}
public void setPly(String ply) {
this.ply = ply;
}
public String getArticleName() {
return articleName;
}
public void setArticleName(String articleName) {
this.articleName = articleName;
}
public boolean isComplete() {
return isComplete;
}
public void setComplete(boolean complete) {
isComplete = complete;
}
public String getJobCardCode() {
return jobCardCode;
}
public void setJobCardCode(String jobCardCode) {
this.jobCardCode = jobCardCode;
}
public long getCuttingAccountId() {
return cuttingAccountId;
}
public void setCuttingAccountId(long cuttingAccountId) {
this.cuttingAccountId = cuttingAccountId;
}
public String getLength() {
return length;
}
public void setLength(String length) {
this.length = length;
}
public String getCuttingOperatorName() {
return cuttingOperatorName;
}
public void setCuttingOperatorName(String cuttingOperatorName) {
this.cuttingOperatorName = cuttingOperatorName;
}
@Override
public String toString() {
return "CuttingJobCardItemWrapper{" +
"cuttingAccountId=" + cuttingAccountId +
", cuttingOperatorName='" + cuttingOperatorName + '\'' +
", jobCardCode='" + jobCardCode + '\'' +
", isComplete=" + isComplete +
", articleName='" + articleName + '\'' +
", ply='" + ply + '\'' +
", wtPly='" + wtPly + '\'' +
", gsm='" + gsm + '\'' +
", length='" + length + '\'' +
", width='" + width + '\'' +
", totalCutting=" + totalCutting +
", sku='" + sku + '\'' +
", poName='" + poName + '\'' +
", jobCardId=" + jobCardId +
'}';
}
}

View File

@ -27,6 +27,8 @@ public class JobCard {
private String purchaseOrderId; private String purchaseOrderId;
private long locationSiteId; private long locationSiteId;
private String description; private String description;
private String articleName;
private int poQuantity;
// wrapper // wrapper
private List<JobCardItem> items; private List<JobCardItem> items;
private long toAccountId; private long toAccountId;
@ -162,6 +164,22 @@ public class JobCard {
this.locationTitle = locationTitle; this.locationTitle = locationTitle;
} }
public String getArticleName() {
return articleName;
}
public void setArticleName(String articleName) {
this.articleName = articleName;
}
public int getPoQuantity() {
return poQuantity;
}
public void setPoQuantity(int poQuantity) {
this.poQuantity = poQuantity;
}
@Override @Override
public String toString() { public String toString() {
return "JobCard{" + return "JobCard{" +
@ -174,9 +192,11 @@ public class JobCard {
", inventoryStatus='" + inventoryStatus + '\'' + ", inventoryStatus='" + inventoryStatus + '\'' +
", customer='" + customer + '\'' + ", customer='" + customer + '\'' +
", lotNumber='" + lotNumber + '\'' + ", lotNumber='" + lotNumber + '\'' +
", purchaseOrderId=" + purchaseOrderId + ", purchaseOrderId='" + purchaseOrderId + '\'' +
", locationSiteId=" + locationSiteId + ", locationSiteId=" + locationSiteId +
", description='" + description + '\'' + ", description='" + description + '\'' +
", articleName='" + articleName + '\'' +
", poQuantity=" + poQuantity +
", items=" + items + ", items=" + items +
", toAccountId=" + toAccountId + ", toAccountId=" + toAccountId +
", purchaseOrderTitle='" + purchaseOrderTitle + '\'' + ", purchaseOrderTitle='" + purchaseOrderTitle + '\'' +

View File

@ -62,11 +62,33 @@ public class SummaryInventoryReportQueryBuilder {
.bracketClose() .bracketClose()
.bracketClose() .bracketClose()
.and() .and()
.columnBetween("transaction_leg_date",startDate,endDate) .columnBetween("transaction_leg_datetime",startDate,endDate)
.groupBy("DATE(transaction_leg_datetime), sku, parent_document_type, parent_document_piece_type") .groupBy("DATE(transaction_leg_datetime), sku, parent_document_type, parent_document_piece_type")
.orderBy("transaction_date,", "sku"); .orderBy("transaction_date,", "sku");
return qb.build(); return qb.build();
}
public static String cuttingQueryBuild(long jobCardId,
List<Long> account,
String startDate,
String endDate,String type) {
QueryBuilder qb = new QueryBuilder()
.setTable(TABLE_NAME)
.setColumns("*")
.where()
.columnIn("account_id",account.toArray(new Long[0]))
.and()
.columnEqualToOrGreaterThan("transaction_leg_datetime",startDate)
.and()
.columnEqualToOrLessThan("transaction_leg_datetime",endDate)
.and()
.columnEquals("type",type);
if (jobCardId != 0){
qb.and()
.columnEquals("job_card_id", jobCardId );
}
return qb.build();
} }
} }

View File

@ -3,6 +3,7 @@ package com.utopiaindustries.service;
import com.utopiaindustries.dao.ctp.*; import com.utopiaindustries.dao.ctp.*;
import com.utopiaindustries.model.ctp.*; import com.utopiaindustries.model.ctp.*;
import com.utopiaindustries.querybuilder.ctp.SummaryInventoryReportQueryBuilder;
import com.utopiaindustries.util.CTPDateTimeFormat; import com.utopiaindustries.util.CTPDateTimeFormat;
import com.utopiaindustries.util.StringUtils; import com.utopiaindustries.util.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -21,7 +22,7 @@ import java.util.stream.Collectors;
public class ReportingService { public class ReportingService {
private final JobCardItemDAO jobCardItemDAO; private final JobCardItemDAO jobCardItemDAO;
private final CutPieceDAO cutPieceDAO; private final ProcessDAO processDAO;
private final BundleDAO bundleDAO; private final BundleDAO bundleDAO;
private final InventoryTransactionLegDAO inventoryTransactionLegDAO; private final InventoryTransactionLegDAO inventoryTransactionLegDAO;
private final InventoryTransactionDAO inventoryTransactionDAO; private final InventoryTransactionDAO inventoryTransactionDAO;
@ -32,9 +33,9 @@ public class ReportingService {
private final StitchingOfflineItemDAO stitchingOfflineItemDAO; private final StitchingOfflineItemDAO stitchingOfflineItemDAO;
private final InventoryAccountDAO inventoryAccountDAO; private final InventoryAccountDAO inventoryAccountDAO;
public ReportingService( JobCardItemDAO jobCardItemDAO, CutPieceDAO cutPieceDAO, BundleDAO bundleDAO, InventoryTransactionLegDAO inventoryTransactionLegDAO, InventoryTransactionDAO inventoryTransactionDAO, JobCardDAO jobCardDAO, CryptographyService cryptographyService, MasterBundleDAO masterBundleDAO, FinishedItemDAO finishedItemDAO, StitchingOfflineItemDAO stitchingOfflineItemDAO, InventoryAccountDAO inventoryAccountDAO) { public ReportingService( JobCardItemDAO jobCardItemDAO, ProcessDAO processDAO, BundleDAO bundleDAO, InventoryTransactionLegDAO inventoryTransactionLegDAO, InventoryTransactionDAO inventoryTransactionDAO, JobCardDAO jobCardDAO, CryptographyService cryptographyService, MasterBundleDAO masterBundleDAO, FinishedItemDAO finishedItemDAO, StitchingOfflineItemDAO stitchingOfflineItemDAO, InventoryAccountDAO inventoryAccountDAO) {
this.jobCardItemDAO = jobCardItemDAO; this.jobCardItemDAO = jobCardItemDAO;
this.cutPieceDAO = cutPieceDAO; this.processDAO = processDAO;
this.bundleDAO = bundleDAO; this.bundleDAO = bundleDAO;
this.inventoryTransactionLegDAO = inventoryTransactionLegDAO; this.inventoryTransactionLegDAO = inventoryTransactionLegDAO;
this.inventoryTransactionDAO = inventoryTransactionDAO; this.inventoryTransactionDAO = inventoryTransactionDAO;
@ -442,20 +443,33 @@ public class ReportingService {
return barChartData; return barChartData;
} }
public List<POsDetails> getAllPOs() { public List<POsDetails> getAllPOs(String poName) {
List<POsDetails> pOsDetailsList = new ArrayList<>(); List<POsDetails> pOsDetailsList = new ArrayList<>();
List<JobCard> jobCards = jobCardDAO.findAll() ; List<JobCard> jobCards = jobCardDAO.findAll() ;
HashMap<String, List<JobCard>> filterJobCardsByPos = jobCards.stream() HashMap<String, List<JobCard>> filterJobCardsByPos;
if(poName != null && !poName.isEmpty()) {
filterJobCardsByPos = jobCards.stream()
.filter(jobCard -> jobCard.getPurchaseOrderId().equals(poName))
.collect(Collectors.groupingBy( .collect(Collectors.groupingBy(
JobCard::getPurchaseOrderId, JobCard::getPurchaseOrderId,
HashMap::new, HashMap::new,
Collectors.toList() Collectors.toList()
)); ));
}else {
filterJobCardsByPos = jobCards.stream()
.collect(Collectors.groupingBy(
JobCard::getPurchaseOrderId,
HashMap::new,
Collectors.toList()
));
}
Map<String,Integer> jobCardCompleteItems = new HashMap<>(); Map<String,Integer> jobCardCompleteItems = new HashMap<>();
for (String pos : filterJobCardsByPos.keySet()) { for (String pos : filterJobCardsByPos.keySet()) {
BigDecimal totalProduction = BigDecimal.ZERO; BigDecimal totalProduction = BigDecimal.ZERO;
BigDecimal actualProduction = BigDecimal.ZERO; BigDecimal actualProduction = BigDecimal.ZERO;
int poQuantity = 0;
String articleName = "";
Long qaProgressItems = 0L; Long qaProgressItems = 0L;
Long totalFinishItem = 0L; Long totalFinishItem = 0L;
POsDetails pOsDetails = new POsDetails(); POsDetails pOsDetails = new POsDetails();
@ -468,7 +482,8 @@ public class ReportingService {
actualProduction = actualProduction.add(jobCardItems.stream() actualProduction = actualProduction.add(jobCardItems.stream()
.map(item -> Optional.ofNullable(item.getActualProduction()).orElse(BigDecimal.ZERO)) .map(item -> Optional.ofNullable(item.getActualProduction()).orElse(BigDecimal.ZERO))
.reduce(BigDecimal.ZERO, BigDecimal::add)); .reduce(BigDecimal.ZERO, BigDecimal::add));
poQuantity = jobCard.getPoQuantity();
articleName = jobCard.getArticleName();
qaProgressItems += Optional.ofNullable(stitchingOfflineItemDAO.CalculateTotalQA(jobCard.getId())).orElse(0L); qaProgressItems += Optional.ofNullable(stitchingOfflineItemDAO.CalculateTotalQA(jobCard.getId())).orElse(0L);
totalFinishItem += Optional.ofNullable(finishedItemDAO.calculateTotalFinishItem(jobCard.getId())).orElse(0L); totalFinishItem += Optional.ofNullable(finishedItemDAO.calculateTotalFinishItem(jobCard.getId())).orElse(0L);
@ -479,16 +494,17 @@ public class ReportingService {
} }
pOsDetails.setPoNumber(pos); pOsDetails.setPoNumber(pos);
pOsDetails.setPoQuantity(100); pOsDetails.setArticleTitle(articleName);
pOsDetails.setPoQuantity(poQuantity);
pOsDetails.setTotalCutting(actualProduction.intValue()); pOsDetails.setTotalCutting(actualProduction.intValue());
pOsDetails.setTotalStitching(totalProduction.intValue()); pOsDetails.setTotalStitching(totalProduction.intValue());
pOsDetails.setTotalEndLineQC(qaProgressItems.intValue()); pOsDetails.setTotalEndLineQC(qaProgressItems.intValue());
pOsDetails.setTotalFinishing(totalFinishItem); pOsDetails.setTotalFinishing(totalFinishItem);
pOsDetails.setRemainingCutting(100 - actualProduction.intValue()); pOsDetails.setRemainingCutting(poQuantity - actualProduction.intValue());
pOsDetails.setRemainingStitching(100 - totalProduction.intValue()); pOsDetails.setRemainingStitching(poQuantity - totalProduction.intValue());
pOsDetails.setRemainingEndLineQC(100 - qaProgressItems); pOsDetails.setRemainingEndLineQC(poQuantity - qaProgressItems);
pOsDetails.setRemainingFinishing(100 - totalFinishItem); pOsDetails.setRemainingFinishing(poQuantity - totalFinishItem);
pOsDetails.setTotalAGradeItem(jobCardCompleteItems.getOrDefault("A GRADE", 0)); pOsDetails.setTotalAGradeItem(jobCardCompleteItems.getOrDefault("A GRADE", 0));
pOsDetails.setTotalBGradeItem(jobCardCompleteItems.getOrDefault("B GRADE", 0)); pOsDetails.setTotalBGradeItem(jobCardCompleteItems.getOrDefault("B GRADE", 0));
@ -525,6 +541,7 @@ public class ReportingService {
//stitching day wise //stitching day wise
Integer stitching = stitchingOfflineItems.size(); Integer stitching = stitchingOfflineItems.size();
//total qa
Integer qa = finishedItems.size(); Integer qa = finishedItems.size();
Map<String, Integer> segregateItems = inventoryTransactionLegs.stream() Map<String, Integer> segregateItems = inventoryTransactionLegs.stream()
.filter(leg -> inventoryAccounts.stream() .filter(leg -> inventoryAccounts.stream()
@ -576,6 +593,105 @@ public class ReportingService {
return poJobCardItemsProgress; 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, startDate1, endDate1, "IN");
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.setTotalCutting(item.getActualProduction().longValue());
wrapper.setWidth(item.getWidth());
wrapper.setWtPly(item.getWtPly());
wrapper.setComplete(item.isComplete());
wrapper.setPoName(jobCard.getPurchaseOrderId());
wrapper.setCuttingOperatorName(bundle.getCreatedBy());
wrapper.setJobCardId(item.getJobCardId());
wrapper.setLength(item.getLength());
wrapper.setCuttingAccountId(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;
}
private StringBuilder generateTime(LocalDateTime startDate, LocalDateTime endDate){ private StringBuilder generateTime(LocalDateTime startDate, LocalDateTime endDate){
StringBuilder totalTime = new StringBuilder(); StringBuilder totalTime = new StringBuilder();
if(startDate != null && endDate != null){ if(startDate != null && endDate != null){

View File

@ -137,8 +137,69 @@ document.addEventListener("DOMContentLoaded", function () {
}); });
} }
function createSingleBarChart(divId, height, width, title,Heading, Data, dates, fontSize, maxValue) {
if (!document.getElementById(divId)) {
return;
}
Highcharts.chart(divId, {
chart: {
type: 'column',
height: height,
width: width,
},
title: {
text: title,
align: 'center',
verticalAlign: 'top',
y: 30,
style: {
fontSize: fontSize,
fontWeight: 'bold',
}
},
xAxis: {
categories: dates,
labels: {
rotation: -45,
style: {
fontSize: 10-fontSize,
fontWeight: 'bold'
}
}
},
yAxis: {
min: 0,
max: maxValue,
softMax: maxValue,
softMin: 0,
startOnTick: true,
endOnTick: true,
title: {
text: 'Total Progress',
style: {
fontSize: fontSize,
fontWeight: 'bold',
}
},
labels: {
format: '{value}%'
}
},
scrollbar: {
enabled: true
},
series: [{
name: Heading,
data: Data
}]
});
}
initializeGauges(); initializeGauges();
function initializeGauges() { function initializeGauges() {
const gaugeDivs2 = document.querySelectorAll('.gauge-chart2'); const gaugeDivs2 = document.querySelectorAll('.gauge-chart2');
gaugeDivs2.forEach(function (div) { gaugeDivs2.forEach(function (div) {
const progress = div.getAttribute('data-progress'); const progress = div.getAttribute('data-progress');
@ -154,6 +215,7 @@ document.addEventListener("DOMContentLoaded", function () {
console.log(actual) console.log(actual)
createGaugeChart(parseInt(progress), color, divId, title, height, width, fontSize, -20, 4, fontColor, total, actual); createGaugeChart(parseInt(progress), color, divId, title, height, width, fontSize, -20, 4, fontColor, total, actual);
}); });
const gaugeDivs = document.querySelectorAll('.gauge-chart'); const gaugeDivs = document.querySelectorAll('.gauge-chart');
gaugeDivs.forEach(function (div) { gaugeDivs.forEach(function (div) {
const progress = div.getAttribute('data-progress'); const progress = div.getAttribute('data-progress');
@ -172,6 +234,7 @@ document.addEventListener("DOMContentLoaded", function () {
createGaugeChart(parseInt(progress), color, divId, title, height, width, fontSize, -15, 2, fontColor, total, actual, aGrade, bGrade, cGrade); createGaugeChart(parseInt(progress), color, divId, title, height, width, fontSize, -15, 2, fontColor, total, actual, aGrade, bGrade, cGrade);
}); });
const barChart = document.querySelectorAll('.barChart'); const barChart = document.querySelectorAll('.barChart');
barChart.forEach(function (div) { barChart.forEach(function (div) {
const title = div.getAttribute('data-title'); const title = div.getAttribute('data-title');
@ -190,7 +253,22 @@ document.addEventListener("DOMContentLoaded", function () {
const dates = div.getAttribute('data-dates'); const dates = div.getAttribute('data-dates');
const datesArray = dates.split(','); const datesArray = dates.split(',');
const divId = div.id; const divId = div.id;
createBarChart( divId, height, width, title,aHeading,aData,bHeading,bData,cHeading,cData,dHeading,dData,datesArray,fontSize,maxValue); createBarChart( divId, height, width, title, aHeading, aData, bHeading, bData, cHeading, cData, dHeading, dData, datesArray, fontSize, maxValue);
});
const cuttingBarChart = document.querySelectorAll('.cuttingBarChart');
cuttingBarChart.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 Heading = div.getAttribute('data-barHeading');
const Data = JSON.parse(div.getAttribute('data-barData'));
const dates = div.getAttribute('data-dates');
const datesArray = dates.split(',');
const divId = div.id;
createSingleBarChart( divId, height, width, title, Heading, Data, datesArray, fontSize, maxValue);
}); });
} }
}); });

View File

@ -140,6 +140,10 @@
th:classappend="${#strings.startsWith(#httpServletRequest.getRequestURI(), '/ctp/reporting/job-card-report') ? 'active' : ''}"> th:classappend="${#strings.startsWith(#httpServletRequest.getRequestURI(), '/ctp/reporting/job-card-report') ? 'active' : ''}">
<a th:href="@{/reporting/job-card-report}" class="nav-link">Job Card Report</a> <a th:href="@{/reporting/job-card-report}" class="nav-link">Job Card Report</a>
</li> </li>
<li class="nav-item"
th:classappend="${#strings.startsWith(#httpServletRequest.getRequestURI(), '/ctp/reporting/cutting-report') ? 'active' : ''}">
<a th:href="@{/reporting/cutting-report}" class="nav-link">Cutting Tables Report</a>
</li>
<li class="nav-item" <li class="nav-item"
th:classappend="${#strings.startsWith(#httpServletRequest.getRequestURI(), '/ctp/reporting/summary') ? 'active' : ''}"> th:classappend="${#strings.startsWith(#httpServletRequest.getRequestURI(), '/ctp/reporting/summary') ? 'active' : ''}">
<a th:href="@{/reporting/summary}" class="nav-link">Summary</a> <a th:href="@{/reporting/summary}" class="nav-link">Summary</a>

View File

@ -32,12 +32,20 @@
<label>Lot Number</label> <label>Lot Number</label>
<input class="form-control" th:field="*{lotNumber}" required> <input class="form-control" th:field="*{lotNumber}" required>
</div> </div>
<div class="col-sm-3 form-group">
<label>Article Name</label>
<input class="form-control" th:field="*{articleName}" required>
</div>
</div> </div>
<div class="form-row"> <div class="form-row">
<div class="col-sm-3 form-group"> <div class="col-sm-3 form-group">
<label>Purchase Order</label> <label>Purchase Order</label>
<input type="text" class="form-control" th:field="*{purchaseOrderId}" required> <input type="text" class="form-control" th:field="*{purchaseOrderId}" required>
</div> </div>
<div class="col-sm-3 form-group">
<label>PO Quantity</label>
<input type="number" class="form-control" th:field="*{poQuantity}" required>
</div>
<div class="col-sm-3 form-group" th:with="title=*{locationTitle},id=*{locationSiteId}"> <div class="col-sm-3 form-group" th:with="title=*{locationTitle},id=*{locationSiteId}">
<location-site-search th:attr="id=${id},title=${title}" <location-site-search th:attr="id=${id},title=${title}"
v-bind:id-field-name="'locationSiteId'"> v-bind:id-field-name="'locationSiteId'">

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.w3.org/1999/xhtml">
<head th:replace="_fragments :: head('Home Page')"></head>
<body>
<!-- sidebar starts -->
<aside class="col-sm-2" th:fragment="sidebar">
<div class="page-filters-sidebar">
<form th:action="@{${#strings.replace(#httpServletRequest.requestURI, #request.getContextPath(), '')}}">
<h5 class="mb-4">Refine Your Search</h5>
<div class="form-group" th:with="title=${param['jobCardCode']}" data-vue-app>
<job-card-for-reporting th:attr="title=${title}"
v-bind:id-field-name="'job-card-id'"
v-bind:title-field-name="''"
></job-card-for-reporting>
</div>
<div class="form-group">
<label>Start Date</label>
<input type="date" class="form-control" name="start-date" th:value="${param['start-date'] ?: startDate}">
</div>
<div class="form-group">
<label>End Date</label>
<input type="date" class="form-control" name="end-date" th:value="${param['end-date'] ?: endDate}">
</div>
<div class="form-group">
<label>Cutting Account</label>
<select class="form-control" name="accountId">
<option value="">Please Select</option>
<option th:each="account : ${accounts}"
th:value="${account.id}"
th:selected="${account.id == (param['accountId'] ?: accountId)}"
th:text="${account.title}">
</option>
</select>
</div>
<input type="submit" class="btn btn-secondary btn-block" value="Search">
<a th:href="@{${#strings.replace(#httpServletRequest.requestURI, #request.getContextPath(), '')}}"
class="btn btn-secondary btn-block">Reset</a>
</form>
<div th:replace="_fragments :: page-footer-scripts"></div>
</div>
</aside>
</body>
</html>

View File

@ -0,0 +1,87 @@
<!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('Cutting Report')"></head>
<body>
<div class="container-fluid">
<header class="row page-header" th:replace="_fragments :: page-header"></header>
<main class="row page-main">
<aside class="col-sm-2" th:replace="/reporting/cutting-report-sidebar :: sidebar"></aside>
<div class="col-sm">
<table class="table table-striped" data-account-table data-order="[[ 0, &quot;asc&quot; ]]">
<tbody>
<tr>
<td th:if="${cutting.get('Date Wise Cutting') != null}" style="padding-left: 150px;">
<div style="border: 2px solid #d5d8dc; padding-top: 10px; border-radius: 10px; height: 560px; width: 80%; overflow-x: auto;">
<div id="cuttingBarChart" class="cuttingBarChart" style="height: 500px; width: 1600px;"
th:data-width="1600"
th:data-height="500"
th:data-title="'Days Wise Progress'"
th:data-dates="${cutting.get('Date Wise Cutting').keySet()}"
th:data-barData="${cutting.get('Date Wise Cutting').values()}"
th:data-barHeading="'Cutting'"
th:data-stitching="''"
th:data-quality="''"
th:data-finishing="''"
th:data-totalProduction="'30000'"
th:data-fontSize="30"
></div>
</div>
</td>
</tr>
<tr th:if="${cutting.get('cuttingAccount') != null}" th:each="cuttingAccount, index : ${cutting.get('cuttingAccount')}">
<td th:if="${cutting.get('accountWiseCutting').containsKey(cuttingAccount.id)}" class="p-0 text-center">
<div class="bg-dark text-white py-2 px-3 fs-5 fw-bold text-center" th:text="${cuttingAccount.title}"></div>
<table class="table table-bordered mt-2">
<thead class="">
<tr>
<th>Job Card</th>
<th>PO Number</th>
<th>SKU</th>
<th>Article Name</th>
<th>Total Cutting</th>
<th>Cutting Operator Name</th>
<th>Width</th>
<th>Length</th>
<th>GSM</th>
<th>WT PLY</th>
<th>PLY</th>
<th>Cutting Complete</th>
</tr>
</thead>
<tbody>
<tr th:each="wrap, index : ${cutting.get('accountWiseCutting').get(cuttingAccount.id)}">
<td th:text="${wrap.jobCardCode}"></td>
<td th:text="${wrap.poName}"></td>
<td th:text="${wrap.sku}"></td>
<td th:text="${wrap.articleName}"></td>
<td th:text="${wrap.totalCutting}"></td>
<td th:text="${wrap.cuttingOperatorName}"></td>
<td th:text="${wrap.width}"></td>
<td th:text="${wrap.length}"></td>
<td th:text="${wrap.gsm}"></td>
<td th:text="${wrap.wtPly}"></td>
<td th:text="${wrap.ply}"></td>
<td>
<span th:if="${!wrap.Complete}" class="badge badge-danger" >Not Complete</span>
<div th:if="${wrap.Complete}">
<span class="badge badge-APPROVED">Completed</span>
</div>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</main>
</div>
<!-- Load JavaScript file -->
<script th:src="@{/js/charts.js}"></script>
</body>
</html>

View File

@ -2,7 +2,7 @@
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.w3.org/1999/xhtml" <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"> xmlns:ctp="http://www.w3.org/1999/xhtml">
<head th:replace="_fragments :: head('Summary')"></head> <head th:replace="_fragments :: head('Job Card Report')"></head>
<body> <body>
<div class="container-fluid"> <div class="container-fluid">
@ -11,6 +11,12 @@
<aside class="col-sm-2" th:replace="/reporting/job-card-report-sidebar :: sidebar"></aside> <aside class="col-sm-2" th:replace="/reporting/job-card-report-sidebar :: sidebar"></aside>
<div class="col-sm"> <div class="col-sm">
<table class="table " > <table class="table " >
<thead>
<tr th:if="${jobCardProgress == null}">
<th colspan="5" style="font-size:26px; text-align: center;">Please Select Job card</th>
</tr>
</thead>
<tbody> <tbody>
<tr th:if="${jobCardProgress != null }"> <tr th:if="${jobCardProgress != null }">
<td style="padding:0px;"> <td style="padding:0px;">
@ -65,12 +71,13 @@
</div> </div>
</td> </td>
</tr> </tr>
<tr th:if="${cuttingDetails != null && cuttingDetails.get('accounts') != null}"> <tr>
<td style="padding: 0px; text-align: center;"> <!-- Cutting Details Column -->
<td th:if="${cuttingDetails != null && cuttingDetails.get('accounts') != null}" style="padding: 0px; text-align: center;">
<div style="background-color: black; color: white; padding: 10px; font-size: 18px; font-weight: bold; text-align: center;"> <div style="background-color: black; color: white; padding: 10px; font-size: 18px; font-weight: bold; text-align: center;">
Cutting Detail Cutting Detail
</div> </div>
<table class="table"> <table class="table" style="width: 100%; border-collapse: collapse;">
<thead> <thead>
<tr> <tr>
<th>ID</th> <th>ID</th>
@ -87,22 +94,21 @@
<td th:text="${cuttingDetails.get('personName').get(detail)}"></td> <td th:text="${cuttingDetails.get('personName').get(detail)}"></td>
<td> <td>
<span th:text="${#temporals.format(cuttingDetails.get('date').get(detail), 'E')}"></span> <span th:text="${#temporals.format(cuttingDetails.get('date').get(detail), 'E')}"></span>
<span ctp:formatdate="${cuttingDetails.get('date').get(detail)}" ></span> <span ctp:formatdate="${cuttingDetails.get('date').get(detail)}"></span>
</td> </td>
<td th:text="${cuttingDetails.get('accounts').get(detail).notes}"></td> <td th:text="${cuttingDetails.get('accounts').get(detail).notes}"></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</td> </td>
</tr>
<tr th:if="${stitchingDetails != null && stitchingDetails.get('accounts') != null}"> <!-- Stitching Details Column -->
<td style="padding: 0px; text-align: center; "> <td th:if="${stitchingDetails != null && stitchingDetails.get('accounts') != null}" style="padding: 0px; text-align: center;">
<div style="background-color: black; color: white; padding: 10px; font-size: 18px; font-weight: bold; text-align: center;"> <div style="background-color: black; color: white; padding: 10px; font-size: 18px; font-weight: bold; text-align: center;">
Stitching Detail Stitching Detail
</div> </div>
<table class="table" > <table class="table" style="width: 100%; border-collapse: collapse;">
<thead > <thead>
<tr> <tr>
<th>ID</th> <th>ID</th>
<th>Title</th> <th>Title</th>
@ -123,12 +129,13 @@
<td th:text="${stitchingDetails.get('accounts').get(detail).notes}"></td> <td th:text="${stitchingDetails.get('accounts').get(detail).notes}"></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</td> </td>
</tr> </tr>
<tr th:if="${dailyProgress != null}"> <tr th:if="${dailyProgress != null}">
<td style="padding-left: 150px;"> <td colspan="5" style="padding-left: 150px;">
<div style="border: 2px solid #d5d8dc; padding-top: 10px; border-radius: 10px; height: 560px; width: 80%; overflow-x: auto;"> <div style="border: 2px solid #d5d8dc; padding-top: 10px; border-radius: 10px; height: 560px; width: 80%; overflow-x: auto;">
<div id="barChart" class="barChart" style="height: 500px; width: 1600px;" <div id="barChart" class="barChart" style="height: 500px; width: 1600px;"
th:data-width="1600" th:data-width="1600"
@ -143,8 +150,6 @@
th:data-fontSize="30" th:data-fontSize="30"
></div> ></div>
</div> </div>
</td> </td>
</tr> </tr>
</tbody> </tbody>

View File

@ -1,7 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:uind="http://www.w3.org/1999/xhtml" <html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:uind="http://www.w3.org/1999/xhtml"
xmlns:ctp="http://www.w3.org/1999/xhtml"> xmlns:ctp="http://www.w3.org/1999/xhtml">
<head th:replace="_fragments :: head('Job Card Detail')"></head> <head th:replace="_fragments :: head('POs Job Card Details')"></head>
<body> <body>
<div class="container-fluid"> <div class="container-fluid">
<header class="row page-header" th:replace="_fragments :: page-header"></header> <header class="row page-header" th:replace="_fragments :: page-header"></header>

View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.w3.org/1999/xhtml">
<head th:replace="_fragments :: head('Home Page')"></head>
<body>
<!-- sidebar starts -->
<aside class="col-sm-2" th:fragment="sidebar">
<div class="page-filters-sidebar">
<form th:action="@{${#strings.replace(#httpServletRequest.requestURI, #request.getContextPath(), '')}}">
<h5 class="mb-4">Refine Your Search</h5>
<div class="form-group">
<label>PO Name</label>
<input type="text" class="form-control" name="poName" th:value="${param['poName'] ?: poName}">
</div>
<input type="submit" class="btn btn-secondary btn-block" value="Search">
<a th:href="@{${#strings.replace(#httpServletRequest.requestURI, #request.getContextPath(), '')}}"
class="btn btn-secondary btn-block">Reset</a>
</form>
<div th:replace="_fragments :: page-footer-scripts"></div>
</div>
</aside>
</body>
</html>

View File

@ -2,12 +2,13 @@
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.w3.org/1999/xhtml" <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"> xmlns:ctp="http://www.w3.org/1999/xhtml">
<head th:replace="_fragments :: head('Summary')"></head> <head th:replace="_fragments :: head('PO Report')"></head>
<body> <body>
<div class="container-fluid"> <div class="container-fluid">
<header class="row page-header" th:replace="_fragments :: page-header"></header> <header class="row page-header" th:replace="_fragments :: page-header"></header>
<main class="row page-main"> <main class="row page-main">
<aside class="col-sm-2" th:replace="/reporting/po-report-sidebar :: sidebar"></aside>
<div class="col-sm"> <div class="col-sm">
<h3>PO's Report</h3> <h3>PO's Report</h3>
<div th:replace="_notices :: page-notices"></div> <div th:replace="_notices :: page-notices"></div>
@ -18,14 +19,14 @@
<th>PO Number</th> <th>PO Number</th>
<th>PO Article</th> <th>PO Article</th>
<th>PO Quantity</th> <th>PO Quantity</th>
<th>Total Cutting</th> <th>Cutting</th>
<th>Remaining Cutting</th> <th>Cutting Balance</th>
<th>Total Stitching</th> <th>Stitching</th>
<th>Remaining Stitching</th> <th>Stitching Balance</th>
<th>Total End QC</th> <th>End Line QC</th>
<th>Remaining QC</th> <th>End Line QC Balance</th>
<th>Total Finishing Items</th> <th>Finishing Items</th>
<th>Remaining Finishing Items</th> <th>Finishing Items Balance</th>
<th>A Grade Items</th> <th>A Grade Items</th>
<th>B Grade Items</th> <th>B Grade Items</th>
<th>C Grade Items</th> <th>C Grade Items</th>