Compare commits

...

11 Commits

Author SHA1 Message Date
usama.jameel ffc1a8ac41 Merge pull request 'add pagination in cutting report and count in reporting sidebars' (#37) from add-pagination-cutting-report into main
Reviewed-on: #37
2025-06-30 05:01:17 +00:00
usama.jameel b728efd305 add logic when session expire redirect to login page 2025-06-30 09:58:45 +05:00
usama.jameel 59b572d691 add pagination in cutting report and count in reporting sidebars 2025-06-26 12:20:56 +05:00
usama.jameel b3b5597313 Merge pull request 'add po status flag to the po edit screen and po online status screen' (#36) from add-po-complete-flag into main
Reviewed-on: #36
2025-06-25 04:37:01 +00:00
usama.jameel 9b8d525833 add po status flag to the po edit screen and po online status screen 2025-06-24 12:06:03 +05:00
usama.jameel 77887df4ce Merge pull request 'add date and time in po pdf and remove total stitching' (#35) from add-date-time-po-pdf into main
Reviewed-on: #35
2025-06-23 10:27:30 +00:00
usama.jameel c9a3454bbb add date and time in po pdf and remove total stitching 2025-06-23 15:26:32 +05:00
usama.jameel 2730157de7 Merge pull request 'add-po-items' (#34) from add-po-items into main
Reviewed-on: #34
2025-06-23 09:13:32 +00:00
usama.jameel a8ce116a7c change comment 2025-06-23 12:15:50 +05:00
usama.jameel 06a5adbf93 add po items size, color wise 2025-06-23 12:12:18 +05:00
usama.jameel 7704bbd655 Merge pull request 'add searching field for avs integration' (#33) from integrate-AVS into main
Reviewed-on: #33
2025-06-19 04:51:53 +00:00
22 changed files with 602 additions and 141 deletions

View File

@ -2,10 +2,7 @@ package com.utopiaindustries.controller;
import com.utopiaindustries.auth.PurchaseOrderCTPRole;
import com.utopiaindustries.model.ctp.POsDetails;
import com.utopiaindustries.service.InventoryAccountService;
import com.utopiaindustries.service.PurchaseOrderService;
import com.utopiaindustries.service.ReportingService;
import com.utopiaindustries.service.SummaryInventoryReportService;
import com.utopiaindustries.service.*;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
@ -20,11 +17,13 @@ public class POStatusController {
private final ReportingService reportingService;
private final PurchaseOrderService purchaseOrderService;
private final JobCardItemService jobCardItemService;
public POStatusController(ReportingService reportingService, PurchaseOrderService purchaseOrderService) {
public POStatusController(ReportingService reportingService, PurchaseOrderService purchaseOrderService, JobCardItemService jobCardItemService) {
this.reportingService = reportingService;
this.purchaseOrderService = purchaseOrderService;
this.jobCardItemService = jobCardItemService;
}
@GetMapping
@ -33,12 +32,30 @@ public class POStatusController {
}
@GetMapping( "/all-pos")
public String poReport(@RequestParam(value = "poName", required = false) String poName, Model model){
public String poReport(@RequestParam(value = "poName", required = false) String poName,
@RequestParam(value = "size", required = false) String size,
@RequestParam(value = "color", required = false) String color,
@RequestParam(value = "count", required = false, defaultValue = "100") Long count,
Model model){
model.addAttribute("allPOs", reportingService.getAllPOs(poName));
model.addAttribute("allSize",jobCardItemService.getAllSizesOFItems());
model.addAttribute("allColor",jobCardItemService.getAllColorOFItems());
model.addAttribute("allPOs", reportingService.getAllPOs(poName, size, color, count));
return "/reporting/po-report";
}
@GetMapping( "/po-items")
public String poReport(@RequestParam("poId") long poId,
@RequestParam(value = "size", required = false) String size,
@RequestParam(value = "color", required = false) String color,
Model model){
model.addAttribute("allSize",jobCardItemService.getAllSizesOFItems());
model.addAttribute("allColor",jobCardItemService.getAllColorOFItems());
model.addAttribute("poJobcardItems", reportingService.getPoItemsSizeOrColor(poId, size, color));
return "/reporting/po-jobcard-items-table";
}
@GetMapping( value = "/po-report-view/{poId}" )
public String showJobCardDetail(@PathVariable("poId") long poId, @RequestParam(value = "select-date", required = false) String selectDate ,
Model model ){
@ -46,11 +63,15 @@ public class POStatusController {
return "/reporting/po-job-card-report";
}
@GetMapping(value = "/generate-po-pdf", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<InputStreamResource> sendPoAndReturnPdf(@ModelAttribute POsDetails pOsDetails,
@RequestParam(required = false, defaultValue = "true") boolean includeJobCard,
@RequestParam(required = false, defaultValue = "true") boolean includeItemsDetail,
@RequestParam(required = false, defaultValue = "true") boolean includeStoreDetails,
@RequestParam String color,
@RequestParam String size,
Model model) throws Exception{
return purchaseOrderService.generatePOPdf(pOsDetails, model, includeJobCard, includeStoreDetails);
return purchaseOrderService.generatePOPdf(pOsDetails, model, includeItemsDetail, includeStoreDetails, size, color);
}
}

View File

@ -78,27 +78,27 @@ public class ReportingController {
}
@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 ){
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, @RequestParam(value = "count", required = false) Long count, 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()));
model.addAttribute("cutting",reportingService.getCuttingTableDetails(jobCardId, accountId, startDate1.toString(), endDate1.toString(), count));
return "/reporting/cutting-report";
}
@GetMapping( value = "/stitching-report" )
public String stitchingReport(@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 ){
public String stitchingReport(@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, @RequestParam(value = "count", required = false) Long count, 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.findInventoryAccounts( 2L ) );
model.addAttribute("stitching",reportingService.getStitchingDetails(jobCardId, accountId, startDate1.toString(), endDate1.toString()));
model.addAttribute("stitching",reportingService.getStitchingDetails(jobCardId, accountId, startDate1.toString(), endDate1.toString(), count));
return "/reporting/stitching-report";
}
@ -109,13 +109,14 @@ public class ReportingController {
@RequestParam( value = "sku", required = false) String sku,
@RequestParam( value = "startDate", required = false) String startDate,
@RequestParam( value = "endDate", required = false) String endDate,
@RequestParam(value = "count", required = false) Long count,
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("transactions", reportingService.stitchingItemsTransactions( jobCardId, accountId, sku, startDate1.toString(), endDate1.toString() ));
model.addAttribute("transactions", reportingService.stitchingItemsTransactions( jobCardId, accountId, sku, startDate1.toString(), endDate1.toString(), count ));
return "/reporting/accounts-transaction-table";
}

View File

@ -205,10 +205,6 @@ public class InventoryTransactionLegDAO {
params.addValue("start_date", startDate );
params.addValue("end_date", endDate );
params.addValue("type", type );
System.out.println("Start Date: " + startDate);
System.out.println("End Date: " + endDate);
System.out.println("Params: " + params.getValues());
return namedParameterJdbcTemplate.query( SELECT_JOB_CARD_DATES , params, new InventoryTransactionLegRowMapper() );
}

View File

@ -9,6 +9,7 @@ import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@Repository
@ -26,7 +27,12 @@ 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_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_BY_JOB_CARD_IDS = String.format( "SELECT * FROM %s WHERE job_card_id IN (:job_card_id)", TABLE_NAME );
private final String SELECT_BY_JOB_CARD_IDS_AND_COLOR_SIZE = String.format(
"SELECT * FROM %s WHERE job_card_id IN (:job_card_id) ",
TABLE_NAME
);
private final String SELECT_ALL_SIZE_GROUP_BY = String.format( "SELECT size FROM %s GROUP BY size", TABLE_NAME );
private final String SELECT_ALL_COLOR_GROUP_BY = String.format( "SELECT color FROM %s GROUP BY color", TABLE_NAME );
public JobCardItemDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
@ -133,9 +139,29 @@ public class JobCardItemDAO {
return Boolean.TRUE.equals(allComplete);
}
public List<JobCardItem> findByJobCardIds(List<Long> ids){
//find By jobCard ids, color and size
public List<JobCardItem> findByJobCardIdsAndSizeColor(List<Long> ids, String size, String color){
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("job_card_id", ids);
return namedParameterJdbcTemplate.query( SELECT_BY_JOB_CARD_IDS, params, new JobCardItemRowMapper() );
StringBuilder sql = new StringBuilder(SELECT_BY_JOB_CARD_IDS_AND_COLOR_SIZE);
if (color != null && !color.isEmpty() && !"null".equalsIgnoreCase(color)) {
sql.append(" AND color = :color");
params.addValue("color", color);
}
if (size != null && !size.isEmpty() && !"null".equalsIgnoreCase(size)) {
sql.append(" AND size = :size");
params.addValue("size", size);
}
return namedParameterJdbcTemplate.query( sql.toString(), params, new JobCardItemRowMapper() );
}
public List<String> getAllSize() {
return namedParameterJdbcTemplate.queryForList(SELECT_ALL_SIZE_GROUP_BY, new HashMap<>(), String.class);
}
public List<String> getAllColor() {
return namedParameterJdbcTemplate.queryForList(SELECT_ALL_COLOR_GROUP_BY, new HashMap<>(), String.class);
}
}

View File

@ -23,22 +23,24 @@ public class PurchaseOrderCTPDao {
private final String TABLE_NAME = "cut_to_pack.purchase_order";
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 ", TABLE_NAME );
private final String SELECT_BY_PO_CODE = String.format( "SELECT * FROM %s WHERE purchase_order_code = :purchase_order_code", TABLE_NAME );
private final String SELECT_ALL_QUERY = String.format( "SELECT * FROM %s ORDER BY created_at DESC LIMIT :limit ", TABLE_NAME );
private final String SELECT_BY_PO_CODE = String.format("SELECT * FROM %s WHERE purchase_order_code = :purchase_order_code ORDER BY created_at DESC LIMIT :limit", 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, purchase_order_code, purchase_order_quantity, purchase_order_quantity_required, article_name, created_by, status) " +
"VALUES (:id, :purchase_order_code, :purchase_order_quantity, :purchase_order_quantity_required, :article_name, :created_by, :status) " +
"INSERT INTO %s (id, purchase_order_code, purchase_order_quantity, purchase_order_quantity_required, article_name, created_by, status, po_status) " +
"VALUES (:id, :purchase_order_code, :purchase_order_quantity, :purchase_order_quantity_required, :article_name, :created_by, :status, :po_status) " +
"ON DUPLICATE KEY UPDATE " +
"purchase_order_code = VALUES(purchase_order_code), " +
"purchase_order_quantity = VALUES(purchase_order_quantity), " +
"purchase_order_quantity_required = VALUES(purchase_order_quantity_required), " +
"article_name = VALUES(article_name), " +
"created_by = VALUES(created_by), " +
"status = VALUES(status)",
"status = VALUES(status)," +
"po_status = VALUES(po_status)",
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 );
private final String SELECT_BY_TERM = String.format( "SELECT * FROM %s WHERE purchase_order_code LIKE :term limit 100 offset 0", TABLE_NAME );
private final String SELECT_BY_TERM = String.format( "SELECT * FROM %s WHERE purchase_order_code LIKE :term AND po_status = false limit 100 offset 0", TABLE_NAME );
// prepare query params
@ -50,7 +52,8 @@ public class PurchaseOrderCTPDao {
.addValue("purchase_order_quantity_required", purchaseOrderCTP.getPurchaseOrderQuantityRequired())
.addValue("article_name", purchaseOrderCTP.getArticleName())
.addValue("created_by", purchaseOrderCTP.getCreatedBy())
.addValue("status", purchaseOrderCTP.getStatus());
.addValue("status", purchaseOrderCTP.getStatus())
.addValue("po_status", purchaseOrderCTP.getPoStatus());
return params;
}
@ -67,8 +70,10 @@ public class PurchaseOrderCTPDao {
// find all
public List<PurchaseOrderCTP> findAll() {
return namedParameterJdbcTemplate.query( SELECT_ALL_QUERY, new PurchaseOrderCTPRowMapper() );
public List<PurchaseOrderCTP> findAll(Long limit) {
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("limit", limit);
return namedParameterJdbcTemplate.query( SELECT_ALL_QUERY, params, new PurchaseOrderCTPRowMapper() );
}
// save
@ -96,10 +101,16 @@ public class PurchaseOrderCTPDao {
return namedParameterJdbcTemplate.update( DELETE_QUERY, params ) > 0;
}
/*
* find by query
* */
public List<PurchaseOrderCTP> findByQuery(String query ){
return namedParameterJdbcTemplate.query( query, new PurchaseOrderCTPRowMapper() );
}
/*
* find by created by
* */
public List<PurchaseOrderCTP> findByUserAndLimit(String createdBy, Long limit ){
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("limit", limit.intValue() );
@ -107,9 +118,13 @@ public class PurchaseOrderCTPDao {
return namedParameterJdbcTemplate.query( SELECT_BY_LIMIT, params, new PurchaseOrderCTPRowMapper() );
}
public List<PurchaseOrderCTP> findByPoCode(String poCode){
/*
* find by po code
* */
public List<PurchaseOrderCTP> findByPoCode(String poCode, Long limit ){
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("purchase_order_code", poCode);
params.addValue("limit", limit);
return namedParameterJdbcTemplate.query( SELECT_BY_PO_CODE, params, new PurchaseOrderCTPRowMapper() );
}

View File

@ -19,6 +19,7 @@ public class PurchaseOrderCTPRowMapper implements RowMapper<PurchaseOrderCTP> {
}
PurchaseOrderCTP.setCreatedBy(rs.getString("created_by"));
PurchaseOrderCTP.setStatus(rs.getString("status"));
PurchaseOrderCTP.setPoStatus(rs.getBoolean("po_status"));
return PurchaseOrderCTP;
}
}

View File

@ -0,0 +1,58 @@
package com.utopiaindustries.model.ctp;
public class PoItemsWrapper {
private int totalCutting;
private int totalStitching;
private int totalProduction;
private String size;
private String color;
private String sku;
public int getTotalCutting() {
return totalCutting;
}
public void setTotalCutting(int totalCutting) {
this.totalCutting = totalCutting;
}
public int getTotalStitching() {
return totalStitching;
}
public void setTotalStitching(int totalStitching) {
this.totalStitching = totalStitching;
}
public int getTotalProduction() {
return totalProduction;
}
public void setTotalProduction(int totalProduction) {
this.totalProduction = totalProduction;
}
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getSku() {
return sku;
}
public void setSku(String sku) {
this.sku = sku;
}
}

View File

@ -14,6 +14,7 @@ public class PurchaseOrderCTP {
private long purchaseOrderQuantity;
private long purchaseOrderQuantityRequired;
private String articleName;
private boolean poStatus;
private String createdBy;
private LocalDateTime createdAt;
private String status;
@ -81,4 +82,12 @@ public class PurchaseOrderCTP {
public void setStatus(String status) {
this.status = status;
}
public boolean getPoStatus() {
return poStatus;
}
public void setPoStatus(boolean poStatus) {
this.poStatus = poStatus;
}
}

View File

@ -75,7 +75,7 @@ public class SummaryInventoryReportQueryBuilder {
String startDate,
String endDate,
String type,
String parentDocumentType) {
String parentDocumentType, Long count) {
QueryBuilder qb = new QueryBuilder()
.setTable(TABLE_NAME)
@ -98,6 +98,7 @@ public class SummaryInventoryReportQueryBuilder {
qb.and()
.columnEquals("sku", sku );
}
qb.orderBy("transaction_leg_datetime", "DESC").limit(count);
return qb.build();
}
}

View File

@ -0,0 +1,23 @@
package com.utopiaindustries.service;
import com.utopiaindustries.dao.ctp.JobCardItemDAO;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class JobCardItemService {
private final JobCardItemDAO jobCardItemDAO;
public JobCardItemService(JobCardItemDAO jobCardItemDAO) {
this.jobCardItemDAO = jobCardItemDAO;
}
public List<String> getAllSizesOFItems() {
return jobCardItemDAO.getAllSize();
}
public List<String> getAllColorOFItems() {
return jobCardItemDAO.getAllColor();
}
}

View File

@ -13,6 +13,7 @@ import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@ -23,13 +24,15 @@ public class PurchaseOrderService {
private final PurchaseOrderDAO purchaseOrderDAO;
private final PurchaseOrderCTPService purchaseOrderCTPService;
private final HTMLBuilder htmlBuilder;
private PDFResponseEntityInputStreamResource pdfGenerator;
private final PDFResponseEntityInputStreamResource pdfGenerator;
private final ReportingService reportingService;
public PurchaseOrderService(PurchaseOrderDAO purchaseOrderDAO, PurchaseOrderCTPService purchaseOrderCTPService, HTMLBuilder htmlBuilder, PDFResponseEntityInputStreamResource pdfGenerator) {
public PurchaseOrderService(PurchaseOrderDAO purchaseOrderDAO, PurchaseOrderCTPService purchaseOrderCTPService, HTMLBuilder htmlBuilder, PDFResponseEntityInputStreamResource pdfGenerator, ReportingService reportingService) {
this.purchaseOrderDAO = purchaseOrderDAO;
this.purchaseOrderCTPService = purchaseOrderCTPService;
this.htmlBuilder = htmlBuilder;
this.pdfGenerator = pdfGenerator;
this.reportingService = reportingService;
}
public List<PurchaseOrder> findByTerm( String term ){
@ -37,21 +40,29 @@ public class PurchaseOrderService {
}
/**
* Print Job card *
* Print po pdf *
* **/
public ResponseEntity<InputStreamResource> generatePOPdf(POsDetails pOsDetails, Model model, boolean jobCardDetail, boolean storeDetail ) throws Exception {
public ResponseEntity<InputStreamResource> generatePOPdf(POsDetails pOsDetails, Model model, boolean includeItemsDetail, boolean storeDetail, String size, String color ) throws Exception {
Map<String,Integer> storeItems = purchaseOrderCTPService.getStoreItemsByPoId(pOsDetails.getPoId());
model.addAttribute("poDetail", pOsDetails);
model.addAttribute( "baseUrl", URLUtils.getCurrentBaseUrl() );
model.addAttribute("date", LocalDateTime.now());
if (includeItemsDetail){
model.addAttribute("showItems", true);
model.addAttribute("poItems", reportingService.getPoItemsSizeOrColor(pOsDetails.getPoId(), size, color));
}else {
model.addAttribute("showItems", false);
}
if (storeDetail && !storeItems.isEmpty()){
model.addAttribute("showStore", true);
model.addAttribute("store", storeItems);
}else {
model.addAttribute("showStore", false);
}
String htmlStr = htmlBuilder.buildHTML( "po-status-pdf", model );
// return pdf
return pdfGenerator.generatePdf( htmlStr, "Po-status", "inline" );
}

View File

@ -437,15 +437,18 @@ public class ReportingService {
return barChartData;
}
public List<POsDetails> getAllPOs(String poCode) {
/*
* find all po for po-online-status
* */
public List<POsDetails> getAllPOs(String poCode, String size, String color, Long count) {
List<POsDetails> pOsDetailsList = new ArrayList<>();
List<PurchaseOrderCTP> purchaseOrderCTPList;
if (poCode != null && !poCode.isEmpty()) {
purchaseOrderCTPList = purchaseOrderCTPDao.findByPoCode(poCode);
purchaseOrderCTPList = purchaseOrderCTPDao.findByPoCode(poCode, count);
}else {
purchaseOrderCTPList = purchaseOrderCTPDao.findAll();
purchaseOrderCTPList = purchaseOrderCTPDao.findAll(count);
}
@ -461,67 +464,78 @@ public class ReportingService {
long storeItems = 0L;
long packagingItems = 0L;
POsDetails pOsDetails = new POsDetails();
for (JobCard jobCard : jobCards) {
List<JobCardItem> jobCardItems = jobCardItemDAO.findByCardId(jobCard.getId());
expectedProduction = expectedProduction.add(jobCardItems.stream()
.map(item -> Optional.ofNullable(item.getExpectedProduction()).orElse(BigDecimal.ZERO))
.reduce(BigDecimal.ZERO, BigDecimal::add));
totalProduction = totalProduction.add(jobCardItems.stream()
.map(item -> Optional.ofNullable(item.getTotalProduction()).orElse(BigDecimal.ZERO))
.reduce(BigDecimal.ZERO, BigDecimal::add));
actualProduction = actualProduction.add(jobCardItems.stream()
.map(item -> Optional.ofNullable(item.getActualProduction()).orElse(BigDecimal.ZERO))
.reduce(BigDecimal.ZERO, BigDecimal::add));
//stitching detail
stitchingIn += Optional.of(stitchingOfflineItemDAO.findByJobCardId(jobCard.getId()).size()).orElse(0);
stitchingOut += Optional.ofNullable(stitchingOfflineItemDAO.CalculateTotalQA(jobCard.getId())).orElse(0L);
//finishItems detail
List<FinishedItem> finishedItems = finishedItemDAO.findByJobCardId(jobCard.getId());
finishApprovedItem += finishedItems.stream().filter(e -> e.getQaStatus().equals("APPROVED")).count();
finishRejectItem += finishedItems.stream().filter(e -> e.getQaStatus().equals("REJECT")).count();
//reject store details
storeItems += Optional.ofNullable(storeItemDao.calculateTotalRejectItemByJobCardId(jobCard.getId())).orElse(0L);
//reject packaging details
packagingItems += Optional.of(packagingItemsDAO.findByJobCardId(jobCard.getId()).size()).orElse(0);
List<Long> jobCardIds = jobCards.stream()
.map(JobCard::getId)
.collect(Collectors.toList());
List<JobCardItem> jobCardItems = new ArrayList<>();
if (!jobCardIds.isEmpty()) {
jobCardItems = jobCardItemDAO.findByJobCardIdsAndSizeColor(jobCardIds,size, color);
}else {
jobCardItems = new ArrayList<>();
}
expectedProduction = expectedProduction.add(jobCardItems.stream()
.map(item -> Optional.ofNullable(item.getExpectedProduction()).orElse(BigDecimal.ZERO))
.reduce(BigDecimal.ZERO, BigDecimal::add));
actualProduction = actualProduction.add(jobCardItems.stream()
.map(item -> Optional.ofNullable(item.getActualProduction()).orElse(BigDecimal.ZERO))
.reduce(BigDecimal.ZERO, BigDecimal::add));
if(!jobCardItems.isEmpty() || (StringUtils.isNullOrEmpty(size) || StringUtils.isNullOrEmpty(color))) {
for (JobCardItem jobCardItem : jobCardItems) {
//stitching detail
stitchingIn += Optional.of(stitchingOfflineItemDAO.findByJobCardId(jobCardItem.getJobCardId()).size()).orElse(0);
stitchingOut += Optional.ofNullable(stitchingOfflineItemDAO.CalculateTotalQA(jobCardItem.getJobCardId())).orElse(0L);
//finishItems detail
List<FinishedItem> finishedItems = finishedItemDAO.findByJobCardId(jobCardItem.getJobCardId());
finishApprovedItem += finishedItems.stream().filter(e -> e.getQaStatus().equals("APPROVED")).count();
finishRejectItem += finishedItems.stream().filter(e -> e.getQaStatus().equals("REJECT")).count();
//reject store details
storeItems += Optional.ofNullable(storeItemDao.calculateTotalRejectItemByJobCardId(jobCardItem.getJobCardId())).orElse(0L);
//reject packaging details
packagingItems += Optional.of(packagingItemsDAO.findByJobCardId(jobCardItem.getJobCardId()).size()).orElse(0);
}
pOsDetails.setPoId(pos.getId());
pOsDetails.setPoNumber(pos.getPurchaseOrderCode());
pOsDetails.setArticleTitle(pos.getArticleName());
pOsDetails.setPoQuantity(pos.getPurchaseOrderQuantity());
pOsDetails.setPoRequiredQuantity(pos.getPurchaseOrderQuantityRequired());
pOsDetails.setActualCutting(expectedProduction.longValue());
pOsDetails.setBalanceToCutting(pos.getPurchaseOrderQuantityRequired() - expectedProduction.longValue());
pOsDetails.setCuttingReceived(expectedProduction.longValue());
pOsDetails.setCuttingOki(expectedProduction.intValue());
pOsDetails.setCuttingReject(expectedProduction.subtract(expectedProduction).intValue());
pOsDetails.setStitchingIn(stitchingIn);
pOsDetails.setStitchingOut(stitchingOut);
pOsDetails.setStitchingWips(stitchingIn - stitchingOut);
pOsDetails.setFinishIn(stitchingOut);
pOsDetails.setFinishRej(finishRejectItem);
pOsDetails.setFinishQaApproved(finishApprovedItem);
pOsDetails.setStoreReceived(storeItems);
pOsDetails.setStoreWaiting(finishRejectItem - storeItems);
pOsDetails.setFinishQaApproved(finishApprovedItem);
pOsDetails.setPackagingIn(packagingItems);
pOsDetails.setPackagingOut(packagingItems);
pOsDetails.setPackagingStock(0);
pOsDetails.setShippedScan(packagingItems);
pOsDetails.setShippedNet(packagingItems);
pOsDetails.setPackagingStock(0);
pOsDetails.setPoStatus(pos.getPoStatus());
pOsDetailsList.add(pOsDetails);
}
pOsDetails.setPoId(pos.getId());
pOsDetails.setPoNumber(pos.getPurchaseOrderCode());
pOsDetails.setArticleTitle(pos.getArticleName());
pOsDetails.setPoQuantity(pos.getPurchaseOrderQuantity());
pOsDetails.setPoRequiredQuantity(pos.getPurchaseOrderQuantityRequired());
pOsDetails.setActualCutting(expectedProduction.longValue());
pOsDetails.setBalanceToCutting(pos.getPurchaseOrderQuantityRequired() - actualProduction.longValue());
pOsDetails.setCuttingReceived(expectedProduction.longValue());
pOsDetails.setCuttingOki(actualProduction.intValue());
pOsDetails.setCuttingReject(expectedProduction.subtract(actualProduction).intValue());
pOsDetails.setStitchingIn(stitchingIn);
pOsDetails.setStitchingOut(stitchingOut);
pOsDetails.setStitchingWips(stitchingIn - stitchingOut);
pOsDetails.setFinishIn(stitchingOut);
pOsDetails.setFinishRej(finishRejectItem);
pOsDetails.setFinishQaApproved(finishApprovedItem);
pOsDetails.setStoreReceived(storeItems);
pOsDetails.setStoreWaiting(finishRejectItem - storeItems);
pOsDetails.setFinishQaApproved(finishApprovedItem);
pOsDetails.setPackagingIn(packagingItems);
pOsDetails.setPackagingOut(packagingItems);
pOsDetails.setPackagingStock(0);
pOsDetails.setShippedScan(packagingItems);
pOsDetails.setShippedNet(packagingItems);
pOsDetails.setPackagingStock(0);
pOsDetails.setPoStatus(false);
pOsDetailsList.add(pOsDetails);
}
return pOsDetailsList;
}
/*
* find all job cards of specific po
* */
public HashMap<String, Map<String, Integer>> getAllPoJobCards(long poId, String selectDate) {
String startDate = selectDate != null && !selectDate.isEmpty() ? selectDate + " 00:00:01": null;
String endDate = selectDate != null && !selectDate.isEmpty() ? selectDate + " 23:59:59": null;
@ -590,7 +604,37 @@ public class ReportingService {
return poJobCardItemsProgress;
}
public Map<String, Object> getCuttingTableDetails(String jobCardId, String cuttingTableId, String startDate, String endDate) {
//get po related items size, poId or color
public HashMap<String, PoItemsWrapper> getPoItemsSizeOrColor(long poId, String size, String color) {
List<JobCard> jobCards = jobCardDAO.findByPoId(poId);
List<Long> jobCardIds = jobCards.stream()
.map(JobCard::getId)
.collect(Collectors.toList());
HashMap<String, PoItemsWrapper> poItemsWrapperHashMap = new HashMap<>();
if(!jobCardIds.isEmpty()){
List<JobCardItem> jobCardItems = jobCardItemDAO.findByJobCardIdsAndSizeColor(jobCardIds, size, color);
jobCardItems.forEach(e -> {
String sku = e.getSku();
PoItemsWrapper poItemsWrapper = poItemsWrapperHashMap.getOrDefault(sku, new PoItemsWrapper());
poItemsWrapper.setColor(e.getColor());
poItemsWrapper.setSize(e.getSize());
poItemsWrapper.setSku(e.getSku());
poItemsWrapper.setTotalCutting(
poItemsWrapper.getTotalCutting() + (e.getActualProduction() != null ? e.getActualProduction().intValue() : 0)
);
poItemsWrapper.setTotalProduction(
poItemsWrapper.getTotalProduction() + (e.getExpectedProduction() != null ? e.getExpectedProduction().intValue() : 0)
);
poItemsWrapperHashMap.put(sku, poItemsWrapper);
});
}
return poItemsWrapperHashMap;
}
public Map<String, Object> getCuttingTableDetails(String jobCardId, String cuttingTableId, String startDate, String endDate, Long count) {
Map<String, Object> cuttingDetails = new HashMap<>();
long jobCardIdTemp = 0L;
String startDate1 = null;
@ -615,7 +659,7 @@ public class ReportingService {
inventoryAccountIds = List.of(Long.parseLong(cuttingTableId));
}
String query = SummaryInventoryReportQueryBuilder.cuttingQueryBuild(jobCardIdTemp, inventoryAccountIds, null, startDate1, endDate1, "IN","BUNDLE");
String query = SummaryInventoryReportQueryBuilder.cuttingQueryBuild(jobCardIdTemp, inventoryAccountIds, null, startDate1, endDate1, "IN","BUNDLE", count);
List<InventoryTransactionLeg> inventoryTransactionLegs = inventoryTransactionLegDAO.findByQuery(query);
Map<String, Integer> dateWiseProduction = new TreeMap<>();
@ -631,7 +675,7 @@ public class ReportingService {
for (Map.Entry<LocalDate, List<Long>> entry : dateWiseJobCardIds.entrySet()) {
List<Long> jobCardIds = entry.getValue();
if (!jobCardIds.isEmpty()) {
List<JobCardItem> jobCardItems = jobCardItemDAO.findByJobCardIds(jobCardIds);
List<JobCardItem> jobCardItems = jobCardItemDAO.findByJobCardIdsAndSizeColor(jobCardIds, null, null);
int totalProduction = jobCardItems.stream()
.filter(item -> item.getActualProduction() != null)
.mapToInt(item -> item.getActualProduction().intValue())
@ -688,7 +732,7 @@ public class ReportingService {
return cuttingDetails;
}
public Map<String, Object> getStitchingDetails(String jobCardId, String stitchingLine, String startDate, String endDate) {
public Map<String, Object> getStitchingDetails(String jobCardId, String stitchingLine, String startDate, String endDate, Long count) {
Map<String, Object> stitchingDetails = new HashMap<>();
long jobCardIdTemp = 0L;
String startDate1 = null;
@ -713,7 +757,7 @@ public class ReportingService {
inventoryAccountIds = List.of(Long.parseLong(stitchingLine));
}
String query = SummaryInventoryReportQueryBuilder.cuttingQueryBuild(jobCardIdTemp, inventoryAccountIds,null, startDate1, endDate1, "IN","STITCHING_OFFLINE");
String query = SummaryInventoryReportQueryBuilder.cuttingQueryBuild(jobCardIdTemp, inventoryAccountIds,null, startDate1, endDate1, "IN","STITCHING_OFFLINE", count);
List<InventoryTransactionLeg> inventoryTransactionLegs = inventoryTransactionLegDAO.findByQuery(query);
Map<String, Integer> dateWiseProduction = new TreeMap<>();
@ -787,7 +831,7 @@ public class ReportingService {
return stitchingDetails;
}
public List<StitchingOfflineItem> stitchingItemsTransactions(String jobCardId, String accountId, String sku, String startDate, String endDate) {
public List<StitchingOfflineItem> stitchingItemsTransactions(String jobCardId, String accountId, String sku, String startDate, String endDate, Long count) {
List<Long> accountID = new ArrayList<>();
String startDate1 = null;
String endDate1 = null;
@ -804,7 +848,7 @@ public class ReportingService {
}
String query = SummaryInventoryReportQueryBuilder.cuttingQueryBuild(Long.parseLong(jobCardId), accountID, sku, startDate1, endDate1,"IN","STITCHING_OFFLINE");
String query = SummaryInventoryReportQueryBuilder.cuttingQueryBuild(Long.parseLong(jobCardId), accountID, sku, startDate1, endDate1,"IN","STITCHING_OFFLINE", count);
List<InventoryTransactionLeg> inventoryTransactionLegs = inventoryTransactionLegDAO.findByQuery(query);
List<Long> stitchingItemsList = inventoryTransactionLegs.stream()
.map(InventoryTransactionLeg::getParentDocumentId)

View File

@ -40,10 +40,12 @@
<input type="text" class="form-control" name="lot-number" maxlength="100" th:value="${param['lot-number']}">
</div>
<div class="form-group" data-vue-app th:with="id=${param['purchase-order-id']},title=${param['purchase-order-id']}">
<purchase-order-search th:attr="id=${id},title=${title}"
v-bind:id-field-name="'purchase-order-id'"
v-bind:code-field-name="'purchase-order-code'"
></purchase-order-search>
<search-ctp-po
v-bind:id-field-name="'purchase-order-id'"
v-on:select-po="onPoSelect"
v-bind:required="false"
v-bind:selected="purchaseOrderCode">
</search-ctp-po>
</div>
<div class="form-group" data-vue-app th:with="id=${param['site-id']},title=${param['site-title']}">
<location-site-search th:attr="id=${id},title=${title}"

View File

@ -2,14 +2,15 @@
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:uind="http://www.w3.org/1999/xhtml"
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ctp="http://www.w3.org/1999/xhtml"
xml:lang="en"
lang="en"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Job Card</title>
<link href="https://fonts.googleapis.com/css?family=Open+Sans+Condensed:700|Open+Sans:400,400i&display=swap" rel="stylesheet">
<link rel="stylesheet" type="text/css" th:href="@{|${baseUrl}/css/print.css|}">
<link href="https://fonts.googleapis.com/css?family=Open+Sans+Condensed:700|Open+Sans:400,400i" rel="stylesheet">
<style type="text/css">
@page {
size: landscape;
@ -38,7 +39,7 @@
<td width="50%">
<table class="bordered">
<tr class="tr-header">
<td colspan="2" style="text-align: center" th:text="'PO Online Status'"></td>
<td colspan="2" style="text-align: center" th:text="'PO Online Status'"></td>
</tr>
<tbody>
<tr>
@ -57,10 +58,6 @@
<td class="align-middle"><i>PO Quantity</i></td>
<td><span th:text="${poDetail.getPoQuantity()}"></span></td>
</tr>
<tr>
<td class="align-middle"><i>PO Required Excess+</i></td>
<td><span th:text="${poDetail.getPoRequiredQuantity()}"></span></td>
</tr>
<tr>
<td class="align-middle"><i>PO Status</i></td>
<td>
@ -75,13 +72,15 @@
</table>
<table style="margin-top: 10px;">
<h5 class="no-margin-top no-margin-bottom" style="margin-top: 10px;">PO Details</h5>
<h5 class="no-margin-top no-margin-bottom" style="margin-top: 10px;" ctp:formatdatetime="${date}"></h5>
<thead>
<tr class="tr-header">
<td style="width: 70px; text-align: center"></td>
<td style="width: 90px; text-align: center"></td>
<td style="width: 60px; text-align: center">Cutting Insp.</td>
<td style="width: 150px; text-align: center">Stitching</td>
<td style="width: 60px; text-align: center">Finished</td>
<td style="width: 140px; text-align: center">Stitching</td>
<td style="width: 65px; text-align: center">Finished</td>
<td style="width: 90px; text-align: center; padding-left: 40px">Rej. Store</td>
<td style="width: 100px; text-align: center">Packaging</td>
<td style="width: 80px; text-align: center">Shipped</td>
@ -92,6 +91,7 @@
<table >
<thead>
<tr class="tr-header">
<td style="width: 50px; text-align: center" >Req.+ Excess</td>
<td style="width: 50px; text-align: center" >Actual Cut</td>
<td style="width: 50px; text-align: center; border-right: 1px solid white;">Bal.To Cut</td>
<td style="width: 50px; text-align: center;">Rcvd.</td>
@ -114,6 +114,7 @@
</thead>
<tbody>
<tr >
<td th:text="${poDetail.getPoRequiredQuantity()}" class="td-value"></td>
<td th:text="${poDetail.getActualCutting()}" class="td-value"></td>
<td th:text="${poDetail.getBalanceToCutting()}" class="td-value"></td>
<td th:text="${poDetail.getCuttingReceived()}" class="td-value"></td>
@ -136,20 +137,52 @@
</tbody>
</table>
<table class="bordered" style="width: 50%; margin-top: 20px;" th:if="${showStore}">
<tr class="tr-header">
<td colspan="2" style="text-align: center" th:text="'Reject Items In Store'"></td>
</tr>
<table>
<tbody>
<tr th:each="heading : ${store.keySet()}"
th:if="${store != null and not store.isEmpty()}">
<td style="width: 40%;"><i th:text="${heading}"></i></td>
<td style="width: 60%;">
<a class="text-reset" target="_blank" th:text="${store.get(heading)}"></a>
<tr>
<td style="width: 50%; margin-top: 20px;" th:if="${showStore}">
<table class="bordered" style="margin-top: 10px;">
<tr class="tr-header">
<td colspan="2" style="text-align: center" th:text="'Reject Items In Store'"></td>
</tr>
<tbody>
<tr th:each="heading : ${store.keySet()}"
th:if="${store != null and not store.isEmpty()}">
<td style="width: 40%;"><i th:text="${heading}"></i></td>
<td style="width: 60%;">
<a class="text-reset" target="_blank" th:text="${store.get(heading)}"></a>
</td>
</tr>
</tbody>
</table>
</td>
<td style="width: 50%; margin-top: 20px;" th:if="${showItems && poItems.values() != null and not poItems.values().isEmpty() }">
<table class="bordered" style="margin-top: 10px;">
<thead>
<tr class="tr-header">
<td>Sku</td>
<td>Color</td>
<td>Size</td>
<td>Expected Production</td>
<td>Total Cutting</td>
</tr>
</thead>
<tbody>
<tr th:each="items : ${poItems.values()}" th:object="${items}">
<td th:text="*{sku}"></td>
<td th:text="*{color}"></td>
<td th:text="*{size}"></td>
<td th:text="*{totalProduction}"></td>
<td th:text="*{totalCutting}"></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>

View File

@ -10,7 +10,6 @@
<div th:replace="_notices :: page-notices"></div>
<form th:action="${purchaseOrder.id} != null ? @{/purchase-order/edit/(id=${purchaseOrder.id})} : @{/purchase-order/edit}"
method="POST"
th:object="${purchaseOrder}"
id="jobCardApp">
<div class="bg-light p-3 mb-3">
<h6 class="mb-3">Info</h6>
@ -34,6 +33,12 @@
<label>Article Name</label>
<input type="text" class="form-control" th:field="${purchaseOrder.articleName}" required>
</div>
<div class="col-sm-1 form-group">
<label for="active">Status OPEN/CLOSE</label>
<div class="form-check">
<input class="custom-control-label:" type="checkbox" id="active" th:field="*{purchaseOrder.poStatus}"/>
</div>
</div>
</div>
</div>

View File

@ -28,6 +28,7 @@
<th>Created At</th>
<th>Created By</th>
<th>Status</th>
<th>PO Status</th>
<th>Action</th>
</tr>
@ -44,6 +45,12 @@
<span class="badge font-sm" th:classappend="'badge-' + ${order.status}" th:if="${order.status}" th:text="${order.status}"></span>
<span th:unless="${order.status}">-</span>
</td>
<td>
<span th:if="${!order.poStatus}" class="badge badge-APPROVED">OPEN</span>
<div th:if="${order.poStatus}">
<span class="badge badge-danger" >CLOSE</span>
</div>
</td>
<td>
<th:block >
<a th:href="@{'/purchase-order/edit/' + ${order.id}}" class="btn btn-sm btn-secondary" title="Edit">

View File

@ -32,6 +32,10 @@
</option>
</select>
</div>
<div class="form-group">
<label>Count</label>
<input type="number" class="form-control" name="count" maxlength="100" min="0" th:value="${param['count'] ?: 100}">
</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>

View File

@ -3,6 +3,17 @@
xmlns:ctp="http://www.w3.org/1999/xhtml">
<head th:replace="_fragments :: head('Cutting Report')"></head>
<style>
div.dataTables_wrapper div.dataTables_filter {
text-align: left !important;
}
div.dataTables_wrapper .dt-buttons {
text-align: left !important;
}
div.dataTables_wrapper div.dataTables_info {
text-align: left !important;
}
</style>
<body>
<div class="container-fluid">
@ -33,8 +44,8 @@
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="">
<table class="table table-bordered mt-2 datatable">
<thead>
<tr>
<th>Job Card</th>
<th>PO Number</th>
@ -77,8 +88,37 @@
</div>
</main>
</div>
<!-- Load JavaScript file -->
<!-- Load chart logic -->
<script th:src="@{/js/charts.js}"></script>
<!-- DataTables Initialization -->
<script>
const dataTableConfig = {
pageLength: 5,
searching: true,
lengthChange: false,
processing: false,
info: true,
paging: true,
dom: `
<'row mb-2 mt-2'<'col-sm-6'f><'col-sm-6'B>>
<'row'<'col-sm-12'tr>>
<'row mt-2'<'col-sm-6'i><'col-sm-6 text-end'p>>`
,
buttons: []
};
$(document).ready(function () {
$('table.datatable').each(function () {
const $table = $(this);
if (!$.fn.DataTable.isDataTable($table)) {
$table.DataTable(dataTableConfig);
}
});
});
</script>
</body>
</html>
</html>

View File

@ -0,0 +1,63 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-sm-8">
<table th:if="${#lists != null && #lists.size(poJobcardItems.keySet()) != 0 }" class="table table-bordered font-sm mb-4" data-order="[[ 0, &quot;desc&quot; ]]" data-dropdown-icon-summary >
<thead>
<tr>
<th>Sku</th>
<th>Color</th>
<th>Size</th>
<th>Expected Production</th>
<th>Total Cutting</th>
</tr>
</thead>
<tbody>
<tr th:each="poItems : ${poJobcardItems.values()}" th:object="${poItems}">
<td th:text="*{sku}"></td>
<td th:text="*{color}"></td>
<td th:text="*{size}"></td>
<td th:text="*{totalProduction}"></td>
<td th:text="*{totalCutting}"></td>
</tr>
</tbody>
</table>
<h5 th:if="${#lists.size(poJobcardItems.keySet()) == 0}" class="mt-2">No Items found.</h5>
</div>
</div>
</div>
<div th:replace="_fragments :: page-footer-scripts"></div>
<script th:inline="javascript">
// Initialize DataTables for each individual table
$('table[data-dropdown-icon-summary]').each(function () {
const $table = $(this);
// Prevent reinitializing if already done
if (!$.fn.DataTable.isDataTable($table)) {
$table.DataTable({
paging: false,
searching: false,
lengthChange: false,
info: false,
dom: 't',
buttons: [{
extend: 'excel',
text: '',
className: 'bi bi-file-earmark-spreadsheet btn-sm d-none'
}]
});
}
});
</script>
</body>
</html>

View File

@ -11,6 +11,32 @@
<label>PO Code</label>
<input type="text" class="form-control" name="poName" th:value="${param['poName'] ?: poName}">
</div>
<div class="form-group">
<label>Size</label>
<select class="form-control" name="size">
<option value="">Please Select</option>
<option th:each="size: ${allSize}"
th:value="${size}"
th:text="${size}"
th:selected="${param['size'] == null ? false : #strings.equals(param['size'], size) }">
</option>
</select>
</div>
<div class="form-group">
<label>Color</label>
<select class="form-control" name="color">
<option value="">Please Select</option>
<option th:each="color: ${allColor}"
th:value="${color}"
th:text="${color}"
th:selected="${param['color'] == null ? false : #strings.equals(param['color'], color) }">
</option>
</select>
</div>
<div class="form-group">
<label>Count</label>
<input type="number" class="form-control" name="count" maxlength="100" min="0" th:value="${param['count'] ?: 100}">
</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>

View File

@ -11,7 +11,7 @@
<h3>All PO's</h3>
<div class="table-responsive"> <!-- Bootstrap responsive table wrapper -->
<table th:if="${ #lists != null && #lists.size(allPOs) != 0 }"
class="table table-striped font-sm" style="min-width: 1500px;">
class="table table-striped font-sm" data-order="[[ 0, &quot;desc&quot; ]]" style="min-width: 1500px;">
<thead>
<tr>
<th>PO Number</th>
@ -37,6 +37,7 @@
<th>Shipped Scan</th>
<th>Shipped Net</th>
<th></th>
<th></th>
<th>PO Status</th>
<th>Generate PDF</th>
</tr>
@ -73,6 +74,10 @@
title="Store-Items">
<span data-dropdown-icon-transactions class="bi bi-caret-right-fill"></span>
</td>
<td data-show-dropdown-summary
th:data-po-id="${poDetail.poId}" title="Summary">
<span data-dropdown-icon-summary class="bi bi-caret-right"></span>
</td>
<td>
<span class="badge font-sm badge-danger" th:if="*{poDetail.poStatus}" th:text="'CLOSE'"></span>
<span class="badge font-sm badge-ACTIVE" th:if="*{!poDetail.poStatus}" th:text="'OPEN'"></span>
@ -126,12 +131,12 @@
<h5 class="modal-title">Select PDF Options</h5>
</div>
<div class="modal-body">
<!-- <div class="form-check">-->
<!-- <input class="form-check-input" type="checkbox" id="includeJobCard" name="includeJobCard" value="true" checked>-->
<!-- <label class="form-check-label" for="includeJobCard">-->
<!-- Include Job Card Details-->
<!-- </label>-->
<!-- </div>-->
<div class="form-check">
<input class="form-check-input" type="checkbox" id="includeItemsDetail" name="includeItemsDetail" value="true" checked>
<label class="form-check-label" for="includeItemsDetail">
Include Items Details
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="includeStoreDetails" name="includeStoreDetails" value="true" checked>
<label class="form-check-label" for="includeStoreDetails">
@ -149,6 +154,14 @@
</div>
<div th:replace="_fragments :: page-footer-scripts"></div>
<script>
const params = new URLSearchParams(window.location.search);
// Extract individual parameters
const size = params.get("size");
const color = params.get("color");
// PDF Generation Functions
let currentPoIdForPdf = null;
@ -165,17 +178,40 @@
// Remove existing options if they exist
const existingJobCard = form.querySelector('input[name="includeJobCard"]');
const existingStoreDetails = form.querySelector('input[name="includeStoreDetails"]');
const existingItemsDetail = form.querySelector('input[name="includeItemsDetail"]');
if (existingJobCard) form.removeChild(existingJobCard);
if (existingStoreDetails) form.removeChild(existingStoreDetails);
if (existingItemsDetail) form.removeChild(existingItemsDetail);
// Add params to show store details in pdf
// Add store detail params
const includeStoreDetails = document.createElement('input');
includeStoreDetails.type = 'hidden';
includeStoreDetails.name = 'includeStoreDetails';
includeStoreDetails.value = document.getElementById('includeStoreDetails').checked;
form.appendChild(includeStoreDetails);
// Add item color params
const itemColors = document.createElement('input');
itemColors.type = 'hidden';
itemColors.name = 'color';
itemColors.value = color
form.appendChild(itemColors);
// Add item size params
const itemSize = document.createElement('input');
itemSize.type = 'hidden';
itemSize.name = 'size';
itemSize.value = size;
form.appendChild(itemSize);
// Add add items details checkbox params
const includeItemsDetails = document.createElement('input');
includeItemsDetails.type = 'hidden';
includeItemsDetails.name = 'includeItemsDetail';
includeItemsDetails.value = document.getElementById('includeItemsDetail').checked;
form.appendChild(includeItemsDetails);
form.submit();
$('#pdfOptionsModal').modal('hide');
}
@ -188,7 +224,7 @@
$('table[data-account-table]').each(function () {
$(this).DataTable({
paging: false,
pageLength: 100,
pageLength: 10,
searching: false,
lengthChange: false,
processing: false,
@ -243,6 +279,45 @@
});
}
});
$body.on( 'click', '[data-show-dropdown-summary]', function( e ) {
e.preventDefault();
const $this = $(this);
const $tr = $this.closest('tr');
const $table = $this.closest('table');
const dataTable = $table.DataTable();
const $row = dataTable.row($tr);
const $spanDropdown = $tr.find( '[data-dropdown-icon-summary]' );
const poId = $this.data('po-id');
$spanDropdown.toggleClass( 'bi-caret-right bi-caret-down' );
if( $row.child.isShown() ){
$row.child.hide();
}
else {
$row.child(`<span class="spinner-border text-center spinner-border-md" role="status"></span>`).show();
$.ajax({
url: `/ctp/po-status/po-items?poId=${poId}&size=${size}&color=${color}`,
success: function( data ){
if (data.includes('page-login') ||
data.includes('login__form') ||
data.includes('Sign in')) {
// Redirect to login page
window.location.href = '/ctp/login?logout';
} else {
$row.child(data).show();
}
},
error: function(xhr) {
if (xhr.status === 401) {
window.location.href = '/ctp/login?logout';
} else {
$row.child('<span class="text-danger">Error loading data</span>').show();
}
}
});
}
});
});
</script>

View File

@ -8,7 +8,7 @@
<div class="container">
<div class="row">
<div class="col-sm-8">
<table th:if="${#lists != null && #lists.size(storeItems.keySet()) != 0 }" class="table table-bordered font-sm mb-4" data-account-tables >
<table th:if="${#lists != null && #lists.size(storeItems.keySet()) != 0 }" class="table table-bordered font-sm mb-4" data-order="[[ 0, &quot;desc&quot; ]]" data-account-tables >
<thead>
<tr>
<th th:each="heading : ${storeItems.keySet()}" th:text="${heading}"></th>