Compare commits

...

4 Commits

17 changed files with 827 additions and 269 deletions

View File

@ -3,6 +3,7 @@ package com.utopiaindustries.controller;
import com.utopiaindustries.auth.CuttingRole; import com.utopiaindustries.auth.CuttingRole;
import com.utopiaindustries.auth.ReportingRole; import com.utopiaindustries.auth.ReportingRole;
import com.utopiaindustries.model.ctp.SummaryInventoryReport; import com.utopiaindustries.model.ctp.SummaryInventoryReport;
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;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
@ -10,6 +11,7 @@ import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.ArrayList; import java.util.ArrayList;
@ -20,10 +22,12 @@ import java.util.Map;
@ReportingRole @ReportingRole
@RequestMapping( "/reporting" ) @RequestMapping( "/reporting" )
public class ReportingController { public class ReportingController {
private final ReportingService reportingService;
private final SummaryInventoryReportService summaryInventoryReportService; private final SummaryInventoryReportService summaryInventoryReportService;
public ReportingController(SummaryInventoryReportService summaryInventoryReportService2) { public ReportingController(SummaryInventoryReportService summaryInventoryReportService2, ReportingService reportingService) {
this.summaryInventoryReportService = summaryInventoryReportService2; this.summaryInventoryReportService = summaryInventoryReportService2;
this.reportingService = reportingService;
} }
@GetMapping( "/summary") @GetMapping( "/summary")
@ -41,9 +45,22 @@ public class ReportingController {
} }
@GetMapping( "/job-card-report") @GetMapping( "/job-card-report")
public String jobCardReport(@RequestParam(value = "item-id", required = false ) String itemId, @RequestParam(value = "sku" , required = false) String sku, @RequestParam(value = "start-date", required = false) String startDate, @RequestParam(value = "end-date", required = false) String endDate, Model model ){ public String jobCardReport(@RequestParam( value = "job-card-id", required = false ) String jobCardId,
int progressValue = 75; Model model, RedirectAttributes redirectAttributes ){
model.addAttribute("progressValue", progressValue); if( jobCardId == null || jobCardId.isEmpty()) {
redirectAttributes.addFlashAttribute("error", "Please Re-Select Job Card" );
return "/reporting/job-card-report";
}
model.addAttribute("totalProduction", reportingService.getTotalProduction(jobCardId));
model.addAttribute("phasesTimes", reportingService.getEachPhaseTotalTime(jobCardId));
model.addAttribute("segregateItems", reportingService.getSegregateItems(jobCardId));
model.addAttribute("pendingStatus", reportingService.countPendingItemsOnDifferentPhases(jobCardId));
model.addAttribute("completeProduction", reportingService.getCompleteProduction(jobCardId));
model.addAttribute("jobCardProgress", reportingService.getJobCardProgress(jobCardId));
model.addAttribute("cuttingDetails", reportingService.getCuttingDetails(jobCardId));
model.addAttribute("stitchingDetails", reportingService.getStitchingDetails(jobCardId));
model.addAttribute("dailyProgress", reportingService.getPhasesProgressDayWise(jobCardId));
return "/reporting/job-card-report"; return "/reporting/job-card-report";
} }

View File

@ -26,10 +26,11 @@ public class BundleDAO {
private final String SELECT_BY_LIMIT = String.format( "SELECT * FROM %s ORDER BY id DESC LIMIT :limit", TABLE_NAME ); private final String SELECT_BY_LIMIT = String.format( "SELECT * FROM %s ORDER BY id DESC LIMIT :limit", TABLE_NAME );
private final String SELECT_BY_MASTER_ID = String.format( "SELECT * FROM %s WHERE master_bundle_id = :master_bundle_id ORDER BY id DESC", TABLE_NAME ); private final String SELECT_BY_MASTER_ID = String.format( "SELECT * FROM %s WHERE master_bundle_id = :master_bundle_id ORDER BY id DESC", TABLE_NAME );
private final String SELECT_BY_IDS = String.format( "SELECT * FROM %s WHERE id IN (:ids)", TABLE_NAME ); private final String SELECT_BY_IDS = String.format( "SELECT * FROM %s WHERE id IN (:ids)", TABLE_NAME );
private final String SELECT_BY_ITEM_ID_AND_JOB_CARD = String.format( "SELECT * FROM %s WHERE item_id = :item_id AND job_card_id = :job_card_id", TABLE_NAME ); private final String SELECT_BY_JOB_CARD = String.format( "SELECT * FROM %s WHERE job_card_id = :job_card_id", TABLE_NAME );
private final String SELECT_BY_ITEM_IDS_AND_JOB_CARD = String.format( "SELECT * FROM %s WHERE item_id IN (:item_ids) AND job_card_id = :job_card_id", TABLE_NAME ); private final String SELECT_BY_ITEM_IDS_AND_JOB_CARD = String.format( "SELECT * FROM %s WHERE item_id IN (:item_ids) AND job_card_id = :job_card_id", TABLE_NAME );
private final String SELECT_LIKE_BARCODE = String.format("SELECT * FROM %s WHERE barcode LIKE :barcode", TABLE_NAME); private final String SELECT_LIKE_BARCODE = String.format("SELECT * FROM %s WHERE barcode LIKE :barcode", TABLE_NAME);
private final String SELECT_FIRST_BUNDLE_BY_JOB_CARD = String.format("SELECT * FROM %s WHERE job_card_id = :job_card_id ORDER BY created_at ASC LIMIT 1", TABLE_NAME);
private final String SELECT_LAST_BUNDLE_BY_JOB_CARD = String.format("SELECT * FROM %s WHERE job_card_id = :job_card_id ORDER BY created_at DESC LIMIT 1", TABLE_NAME);
public BundleDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) { public BundleDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
@ -132,11 +133,10 @@ public class BundleDAO {
return namedParameterJdbcTemplate.query( SELECT_BY_IDS , params, new BundleRowMapper() ); return namedParameterJdbcTemplate.query( SELECT_BY_IDS , params, new BundleRowMapper() );
} }
public List<Bundle> findByItemIdAndCardId( long itemId, long cardId ){ public List<Bundle> findByCardId( long cardId ){
MapSqlParameterSource params = new MapSqlParameterSource(); MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("item_id", itemId );
params.addValue("job_card_id", cardId ); params.addValue("job_card_id", cardId );
return namedParameterJdbcTemplate.query( SELECT_BY_ITEM_ID_AND_JOB_CARD, params, new BundleRowMapper() ); return namedParameterJdbcTemplate.query( SELECT_BY_JOB_CARD, params, new BundleRowMapper() );
} }
public List<Bundle> findByItemIdsAndCardId( List<Long> itemIds, long cardId ){ public List<Bundle> findByItemIdsAndCardId( List<Long> itemIds, long cardId ){
@ -146,4 +146,19 @@ public class BundleDAO {
params.addValue("job_card_id", cardId ); params.addValue("job_card_id", cardId );
return namedParameterJdbcTemplate.query( SELECT_BY_ITEM_IDS_AND_JOB_CARD, params, new BundleRowMapper() ); return namedParameterJdbcTemplate.query( SELECT_BY_ITEM_IDS_AND_JOB_CARD, params, new BundleRowMapper() );
} }
public Bundle findFirstBundleByCardId(long cardId) {
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("job_card_id", cardId);
return namedParameterJdbcTemplate.queryForObject(SELECT_FIRST_BUNDLE_BY_JOB_CARD, params, new BundleRowMapper());
}
public Bundle findLastBundleByCardId(long cardId) {
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("job_card_id", cardId);
return namedParameterJdbcTemplate.query(SELECT_LAST_BUNDLE_BY_JOB_CARD, params, new BundleRowMapper())
.stream()
.findFirst().orElse(new Bundle());
}
} }

View File

@ -32,6 +32,7 @@ public class FinishedItemDAO {
private final String SELECT_BY_TERM = String.format( "SELECT * FROM %s WHERE barcode LIKE :term AND is_segregated = :is_segregated ORDER BY ID DESC", TABLE_NAME ); private final String SELECT_BY_TERM = String.format( "SELECT * FROM %s WHERE barcode LIKE :term AND is_segregated = :is_segregated ORDER BY ID DESC", TABLE_NAME );
private final String SELECT_BY_STITCHED_ITEM_ID = String.format( "SELECT * FROM %s WHERE stitched_item_id = :stitched_item_id", TABLE_NAME ); private final String SELECT_BY_STITCHED_ITEM_ID = String.format( "SELECT * FROM %s WHERE stitched_item_id = :stitched_item_id", TABLE_NAME );
private final String SELECT_BY_STITCHED_ITEM_IDS = String.format( "SELECT * FROM %s WHERE stitched_item_id IN (:stitched_item_ids)", TABLE_NAME ); private final String SELECT_BY_STITCHED_ITEM_IDS = String.format( "SELECT * FROM %s WHERE stitched_item_id IN (:stitched_item_ids)", TABLE_NAME );
private final String COUNT_TOTAL_FINISH_ITEM= String.format("SELECT COUNT(*) FROM %s WHERE job_card_id = :job_card_id AND is_segregated IS TRUE ",TABLE_NAME);
public FinishedItemDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) { public FinishedItemDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
@ -168,4 +169,11 @@ public class FinishedItemDAO {
} }
return items; return items;
} }
public Long calculateTotalFinishItem( long jobCardId ){
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("job_card_id", jobCardId );
Long count = namedParameterJdbcTemplate.queryForObject(COUNT_TOTAL_FINISH_ITEM, params, Long.class);
return count != null ? count : 0;
}
} }

View File

@ -27,6 +27,7 @@ public class InventoryAccountDAO {
private final String SELECT_BY_IDS_AND_PARENT_ENTITY_TYPE_AND_PARENT_ID_AND_COUNT = String.format( "SELECT * FROM %s WHERE id IN (:ids) AND parent_entity_id = :parent_entity_id AND parent_entity_type = :parent_entity_type LIMIT :limit", TABLE_NAME ); private final String SELECT_BY_IDS_AND_PARENT_ENTITY_TYPE_AND_PARENT_ID_AND_COUNT = String.format( "SELECT * FROM %s WHERE id IN (:ids) AND parent_entity_id = :parent_entity_id AND parent_entity_type = :parent_entity_type LIMIT :limit", TABLE_NAME );
private final String SELECT_BY_IDS_PACKAGING_AND_COUNT = String.format( "SELECT * FROM %s WHERE id IN (:ids) AND is_packaging = :is_packaging LIMIT :limit", TABLE_NAME ); private final String SELECT_BY_IDS_PACKAGING_AND_COUNT = String.format( "SELECT * FROM %s WHERE id IN (:ids) AND is_packaging = :is_packaging LIMIT :limit", TABLE_NAME );
private final String SELECT_BY_PARENT_TYPE_AND_PARENT_ID = String.format( "SELECT * FROM %s WHERE active = TRUE AND parent_entity_type = :parent_entity_type AND parent_entity_id = :parent_entity_id" , TABLE_NAME ); private final String SELECT_BY_PARENT_TYPE_AND_PARENT_ID = String.format( "SELECT * FROM %s WHERE active = TRUE AND parent_entity_type = :parent_entity_type AND parent_entity_id = :parent_entity_id" , TABLE_NAME );
private final String SELECT_BY_IS_PACKAGING_TRUE = String.format( "SELECT * FROM %s WHERE is_packaging IS TRUE", TABLE_NAME );
public InventoryAccountDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) { public InventoryAccountDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
@ -144,4 +145,9 @@ public class InventoryAccountDAO {
params.addValue("parent_entity_id", parentEntityId ); params.addValue("parent_entity_id", parentEntityId );
return namedParameterJdbcTemplate.query( SELECT_BY_PARENT_TYPE_AND_PARENT_ID, params, new InventoryAccountRowMapper() ); return namedParameterJdbcTemplate.query( SELECT_BY_PARENT_TYPE_AND_PARENT_ID, params, new InventoryAccountRowMapper() );
} }
public List<InventoryAccount> getPackagingAccounts(){
MapSqlParameterSource params = new MapSqlParameterSource();
return namedParameterJdbcTemplate.query( SELECT_BY_IS_PACKAGING_TRUE, params, new InventoryAccountRowMapper() );
}
} }

View File

@ -1,5 +1,6 @@
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;
@ -21,7 +22,7 @@ public class InventoryTransactionLegDAO {
private final String SELECT_QUERY = String.format( "SELECT * FROM %s WHERE id = :id", TABLE_NAME ); private final String SELECT_QUERY = String.format( "SELECT * FROM %s WHERE id = :id", TABLE_NAME );
private final String SELECT_ALL_QUERY = String.format( "SELECT * FROM %s ORDER BY id DESC", TABLE_NAME ); private final String SELECT_ALL_QUERY = String.format( "SELECT * FROM %s ORDER BY id DESC", 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, transaction_id, item_id, sku, type, quantity, account_id, balance, transaction_leg_datetime, parent_document_type, parent_document_id, parent_document_piece_type) VALUES (:id, :transaction_id, :item_id, :sku, :type, :quantity, :account_id, :balance, :transaction_leg_datetime, :parent_document_type, :parent_document_id, :parent_document_piece_type) ON DUPLICATE KEY UPDATE transaction_id = VALUES(transaction_id), item_id = VALUES(item_id), sku = VALUES(sku), type = VALUES(type), quantity = VALUES(quantity), account_id = VALUES(account_id), balance = VALUES(balance), transaction_leg_datetime = VALUES(transaction_leg_datetime), parent_document_type = VALUES(parent_document_type), parent_document_id = VALUES(parent_document_id), parent_document_piece_type = VALUES(parent_document_piece_type)", TABLE_NAME ); private final String INSERT_QUERY = String.format( "INSERT INTO %s (id, transaction_id, item_id, sku, type, quantity, account_id, balance, transaction_leg_datetime, parent_document_type, parent_document_id, parent_document_piece_type, job_card_id) VALUES (:id, :transaction_id, :item_id, :sku, :type, :quantity, :account_id, :balance, :transaction_leg_datetime, :parent_document_type, :parent_document_id, :parent_document_piece_type, :job_card_id) ON DUPLICATE KEY UPDATE transaction_id = VALUES(transaction_id), item_id = VALUES(item_id), sku = VALUES(sku), type = VALUES(type), quantity = VALUES(quantity), account_id = VALUES(account_id), balance = VALUES(balance), transaction_leg_datetime = VALUES(transaction_leg_datetime), parent_document_type = VALUES(parent_document_type), parent_document_id = VALUES(parent_document_id), parent_document_piece_type = VALUES(parent_document_piece_type), job_card_id = VALUES(job_card_id)", TABLE_NAME );
private final String SELECT_LAST_ACCOUNT_ID_AND_ITEM_ID = String.format( "SELECT * FROM %s WHERE account_id = :account_id AND item_id = :item_id AND parent_document_type= :parent_document_type AND parent_document_piece_type = :parent_document_piece_type ORDER BY id DESC LIMIT 1", TABLE_NAME ); private final String SELECT_LAST_ACCOUNT_ID_AND_ITEM_ID = String.format( "SELECT * FROM %s WHERE account_id = :account_id AND item_id = :item_id AND parent_document_type= :parent_document_type AND parent_document_piece_type = :parent_document_piece_type ORDER BY id DESC LIMIT 1", TABLE_NAME );
private final String SELECT_BY_ACCOUNT_ID = String.format( "SELECT * FROM %s WHERE account_id = :account_id ORDER BY id DESC" , TABLE_NAME ); private final String SELECT_BY_ACCOUNT_ID = String.format( "SELECT * FROM %s WHERE account_id = :account_id ORDER BY id DESC" , TABLE_NAME );
private final String SELECT_SUMMARY_BY_ACCOUNT_ID = String.format( "SELECT item_id, sku, parent_document_type,parent_document_piece_type," + private final String SELECT_SUMMARY_BY_ACCOUNT_ID = String.format( "SELECT item_id, sku, parent_document_type,parent_document_piece_type," +
@ -44,6 +45,10 @@ public class InventoryTransactionLegDAO {
" WHERE itl.type = :type" + " WHERE itl.type = :type" +
" AND itl.parent_document_type = :parent_document_type" " AND itl.parent_document_type = :parent_document_type"
, TABLE_NAME, TABLE_NAME ); , TABLE_NAME, TABLE_NAME );
private final String COUNT_TOTAL_SEGREGATE_ITEMS = String.format("SELECT COUNT(*) FROM %s WHERE parent_document_id IN (:parent_document_id) AND account_id = :account_id", TABLE_NAME);
private final String SELECT_FIRST_TRANSACTION_PARENT_TYPE_PARENT_ID = String.format("SELECT * FROM %s WHERE parent_document_id IN (:parent_document_id) AND parent_document_type = :parent_document_type ORDER BY transaction_leg_datetime ASC LIMIT 1", TABLE_NAME);
private final String SELECT_GROUP_By_TRANSACTION_PARENT_TYPE_PARENT_ID = String.format("SELECT * FROM %s WHERE parent_document_id IN (:parent_document_id) AND parent_document_type = :parent_document_type GROUP BY account_id", TABLE_NAME);
private final String SELECT_JOB_CARD_DATES = String.format("SELECT * FROM %s WHERE job_card_id = :job_card_id AND (:start_date IS NULL OR :end_date IS NULL OR transaction_leg_datetime BETWEEN :start_date AND :end_date) AND type = :type ", TABLE_NAME);
public InventoryTransactionLegDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) { public InventoryTransactionLegDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
@ -63,7 +68,9 @@ public class InventoryTransactionLegDAO {
.addValue( "transaction_leg_datetime", inventoryTransactionLeg.getTransactionLegDateTime() ) .addValue( "transaction_leg_datetime", inventoryTransactionLeg.getTransactionLegDateTime() )
.addValue( "parent_document_type", inventoryTransactionLeg.getParentDocumentType() ) .addValue( "parent_document_type", inventoryTransactionLeg.getParentDocumentType() )
.addValue( "parent_document_id", inventoryTransactionLeg.getParentDocumentId() ) .addValue( "parent_document_id", inventoryTransactionLeg.getParentDocumentId() )
.addValue("parent_document_piece_type", inventoryTransactionLeg.getParentDocumentPieceType() ); .addValue("parent_document_piece_type", inventoryTransactionLeg.getParentDocumentPieceType() )
.addValue("job_card_id", inventoryTransactionLeg.getJobCardId() );
return params; return params;
} }
@ -153,4 +160,43 @@ public class InventoryTransactionLegDAO {
params.addValue("parent_document_type", parentType ); params.addValue("parent_document_type", parentType );
return namedParameterJdbcTemplate.query( SELECT_LAST_LEG_BY_TYPE_AND_PARENT_ID , params, new InventoryTransactionLegRowMapper() ); return namedParameterJdbcTemplate.query( SELECT_LAST_LEG_BY_TYPE_AND_PARENT_ID , params, new InventoryTransactionLegRowMapper() );
} }
public Long CalculateTotalGradingItems(List<Long> finishItemIds, Integer accountId) {
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("parent_document_id", finishItemIds);
params.addValue("account_id", accountId);
Long count = namedParameterJdbcTemplate.queryForObject(COUNT_TOTAL_SEGREGATE_ITEMS, params, Long.class);
return count != null ? count : 0;
}
public InventoryTransactionLeg getFirstStitchBundleTime(List<Long> parentsIds, String parentType) {
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("parent_document_id", parentsIds);
params.addValue("parent_document_type", parentType);
return namedParameterJdbcTemplate.query(SELECT_FIRST_TRANSACTION_PARENT_TYPE_PARENT_ID, params,new InventoryTransactionLegRowMapper())
.stream()
.findFirst()
.orElse( new InventoryTransactionLeg() );
}
public List<InventoryTransactionLeg> getTransactionByParentIdAndType(List<Long> parentIds , String parentType){
if ( parentIds == null || parentIds.isEmpty() ){
return new ArrayList<>();
}
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("parent_document_id", parentIds );
params.addValue("parent_document_type", parentType );
return namedParameterJdbcTemplate.query( SELECT_GROUP_By_TRANSACTION_PARENT_TYPE_PARENT_ID , params, new InventoryTransactionLegRowMapper() );
}
public List<InventoryTransactionLeg> getTransactionByJobCardAndDatesAndType(long jobCardID, String startDate, String endDate, String type){
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("job_card_id", jobCardID );
params.addValue("start_date", startDate );
params.addValue("end_date", endDate );
params.addValue("type", type );
return namedParameterJdbcTemplate.query( SELECT_JOB_CARD_DATES , params, new InventoryTransactionLegRowMapper() );
}
} }

View File

@ -23,6 +23,7 @@ public class InventoryTransactionLegRowMapper implements RowMapper<InventoryTran
inventoryTransactionLeg.setParentDocumentType( rs.getString( "parent_document_type" ) ); inventoryTransactionLeg.setParentDocumentType( rs.getString( "parent_document_type" ) );
inventoryTransactionLeg.setParentDocumentId( rs.getLong( "parent_document_id" ) ); inventoryTransactionLeg.setParentDocumentId( rs.getLong( "parent_document_id" ) );
inventoryTransactionLeg.setParentDocumentPieceType( rs.getString("parent_document_piece_type")); inventoryTransactionLeg.setParentDocumentPieceType( rs.getString("parent_document_piece_type"));
inventoryTransactionLeg.setJobCardId( rs.getLong("job_card_id"));
return inventoryTransactionLeg; return inventoryTransactionLeg;
} }
} }

View File

@ -1,5 +1,6 @@
package com.utopiaindustries.dao.ctp; package com.utopiaindustries.dao.ctp;
import com.utopiaindustries.model.ctp.InventoryTransactionLeg;
import com.utopiaindustries.model.ctp.StitchingOfflineItem; import com.utopiaindustries.model.ctp.StitchingOfflineItem;
import com.utopiaindustries.util.KeyHolderFunctions; import com.utopiaindustries.util.KeyHolderFunctions;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
@ -28,6 +29,8 @@ public class StitchingOfflineItemDAO {
private final String SELECT_BY_IDS = String.format( "SELECT * FROM %s WHERE id IN (:ids)", TABLE_NAME ); private final String SELECT_BY_IDS = String.format( "SELECT * FROM %s WHERE id IN (:ids)", TABLE_NAME );
private final String SELECT_BY_TERM = String.format( "SELECT * FROM %s WHERE barcode LIKE :term ORDER BY ID DESC", TABLE_NAME ); private final String SELECT_BY_TERM = String.format( "SELECT * FROM %s WHERE barcode LIKE :term ORDER BY ID DESC", TABLE_NAME );
private final String SELECT_BY_MASTER_ID = String.format( "SELECT * FROM %s WHERE job_card_id = :job_card_id", TABLE_NAME ); private final String SELECT_BY_MASTER_ID = String.format( "SELECT * FROM %s WHERE job_card_id = :job_card_id", TABLE_NAME );
private final String COUNT_TOTAL_QA_ITEMS= String.format("SELECT COUNT(*) FROM %s WHERE job_card_id = :job_card_id AND is_qa IS TRUE",TABLE_NAME);
private final String SELECT_BY_TIME_AND_CARD_ID= String.format("SELECT * FROM %s WHERE job_card_id = :job_card_id ORDER BY created_at DESC LIMIT 1;",TABLE_NAME);
public StitchingOfflineItemDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) { public StitchingOfflineItemDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
@ -141,4 +144,20 @@ public class StitchingOfflineItemDAO {
return totalCounts; return totalCounts;
} }
public Long CalculateTotalQA( long jobCardId ){
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("job_card_id", jobCardId );
Long count = namedParameterJdbcTemplate.queryForObject(COUNT_TOTAL_QA_ITEMS, params, Long.class);
return count != null ? count : 0;
}
public StitchingOfflineItem getLastStitchItemByCardIdAndTime(long jobCardId) {
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("job_card_id", jobCardId);
return namedParameterJdbcTemplate.query(SELECT_BY_TIME_AND_CARD_ID, params,new StitchingOfflineItemRowMapper())
.stream()
.findFirst()
.orElse( new StitchingOfflineItem() );
}
} }

View File

@ -13,7 +13,7 @@ public class SummaryInventoryReportDao {
private final NamedParameterJdbcTemplate namedParameterJdbcTemplate; private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
private final String TABLE_NAME = "cut_to_pack.inventory_transaction_leg "; private final String TABLE_NAME = "cut_to_pack.inventory_transaction_leg ";
String SELECT_QUERY = "SELECT item_id, account_id, parent_document_id, DATE(transaction_leg_datetime) AS transaction_date, " String SELECT_QUERY = "SELECT job_card_id, item_id, account_id, parent_document_id, DATE(transaction_leg_datetime) AS transaction_date, "
+ "sku, parent_document_type, parent_document_piece_type, " + "sku, parent_document_type, parent_document_piece_type, "
+ "SUM(CASE WHEN type = 'IN' THEN 1 ELSE 0 END) AS total_in, " + "SUM(CASE WHEN type = 'IN' THEN 1 ELSE 0 END) AS total_in, "
+ "SUM(CASE WHEN type = 'OUT' THEN 1 ELSE 0 END) AS total_out " + "SUM(CASE WHEN type = 'OUT' THEN 1 ELSE 0 END) AS total_out "

View File

@ -15,6 +15,7 @@ public class SummaryInventoryReportRowMapper implements RowMapper<SummaryInvento
summaryInventoryReport.setAccountId(rs.getString("account_id")); summaryInventoryReport.setAccountId(rs.getString("account_id"));
summaryInventoryReport.setDate(rs.getString("transaction_date")); summaryInventoryReport.setDate(rs.getString("transaction_date"));
summaryInventoryReport.setTotalIn(rs.getLong("total_in")); summaryInventoryReport.setTotalIn(rs.getLong("total_in"));
summaryInventoryReport.setJobCardID(rs.getLong("job_card_id"));
summaryInventoryReport.setTotalOut(rs.getLong("total_out")); summaryInventoryReport.setTotalOut(rs.getLong("total_out"));
summaryInventoryReport.setParentDocumentType(rs.getString("parent_document_type")); summaryInventoryReport.setParentDocumentType(rs.getString("parent_document_type"));
summaryInventoryReport.setParentDocumentPieceType(rs.getString("parent_document_piece_type")); summaryInventoryReport.setParentDocumentPieceType(rs.getString("parent_document_piece_type"));

View File

@ -22,7 +22,7 @@ public class InventoryTransactionLeg {
private String parentDocumentType; private String parentDocumentType;
private long parentDocumentId; private long parentDocumentId;
private String parentDocumentPieceType; private String parentDocumentPieceType;
private long jobCardId;
//wrapper //wrapper
private InventoryTransaction transaction; private InventoryTransaction transaction;
@ -122,6 +122,14 @@ public class InventoryTransactionLeg {
this.parentDocumentPieceType = parentDocumentPieceType; this.parentDocumentPieceType = parentDocumentPieceType;
} }
public long getJobCardId() {
return jobCardId;
}
public void setJobCardId(long jobCardId) {
this.jobCardId = jobCardId;
}
public InventoryTransaction getTransaction() { public InventoryTransaction getTransaction() {
return transaction; return transaction;
} }

View File

@ -7,6 +7,7 @@ public class SummaryInventoryReport {
private String Date; private String Date;
private long totalIn; private long totalIn;
private long totalOut; private long totalOut;
private long jobCardID;
private String parentDocumentType; private String parentDocumentType;
private String parentDocumentId; private String parentDocumentId;
private String accountId; private String accountId;
@ -91,4 +92,12 @@ public class SummaryInventoryReport {
public void setAccountId(String accountId) { public void setAccountId(String accountId) {
this.accountId = accountId; this.accountId = accountId;
} }
public long getJobCardID() {
return jobCardID;
}
public void setJobCardID(long jobCardID) {
this.jobCardID = jobCardID;
}
} }

View File

@ -174,6 +174,7 @@ public class InventoryService {
inventoryTransactionLeg.setParentDocumentId( artifact.getId( )); inventoryTransactionLeg.setParentDocumentId( artifact.getId( ));
inventoryTransactionLeg.setParentDocumentPieceType( artifact.getType( )); inventoryTransactionLeg.setParentDocumentPieceType( artifact.getType( ));
inventoryTransactionLeg.setTransactionLegDateTime( LocalDateTime.now( )); inventoryTransactionLeg.setTransactionLegDateTime( LocalDateTime.now( ));
inventoryTransactionLeg.setJobCardId(artifact.getJobCardId());
// set balance // set balance
BigDecimal initialBalance = calculateBalance( accountId, artifact.getItemId( ), parentDocumentType, artifact.getType( )); BigDecimal initialBalance = calculateBalance( accountId, artifact.getItemId( ), parentDocumentType, artifact.getType( ));

View File

@ -0,0 +1,423 @@
package com.utopiaindustries.service;
import com.utopiaindustries.dao.ctp.*;
import com.utopiaindustries.model.ctp.*;
import com.utopiaindustries.util.CTPDateTimeFormat;
import com.utopiaindustries.util.StringUtils;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@Service
public class ReportingService {
private final JobCardItemDAO jobCardItemDAO;
private final CutPieceDAO cutPieceDAO;
private final BundleDAO bundleDAO;
private final InventoryTransactionLegDAO inventoryTransactionLegDAO;
private final InventoryTransactionDAO inventoryTransactionDAO;
private final JobCardDAO jobCardDAO;
private final CryptographyService cryptographyService;
private final MasterBundleDAO masterBundleDAO;
private final FinishedItemDAO finishedItemDAO;
private final StitchingOfflineItemDAO stitchingOfflineItemDAO;
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) {
this.jobCardItemDAO = jobCardItemDAO;
this.cutPieceDAO = cutPieceDAO;
this.bundleDAO = bundleDAO;
this.inventoryTransactionLegDAO = inventoryTransactionLegDAO;
this.inventoryTransactionDAO = inventoryTransactionDAO;
this.jobCardDAO = jobCardDAO;
this.cryptographyService = cryptographyService;
this.masterBundleDAO = masterBundleDAO;
this.finishedItemDAO = finishedItemDAO;
this.stitchingOfflineItemDAO = stitchingOfflineItemDAO;
this.inventoryAccountDAO = inventoryAccountDAO;
}
public Map<String,Integer> getJobCardProgress(String jobCardID){
if (jobCardID == null){
return new HashMap<>();
}else {
HashMap<String,Integer> totalProgress = new HashMap<>();
List<JobCardItem> jobCardItems = jobCardItemDAO.findByCardId(Long.parseLong(jobCardID));
BigDecimal totalProduction = jobCardItems.stream()
.map(item -> Optional.ofNullable(item.getTotalProduction()).orElse(BigDecimal.ZERO))
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal actualProduction = jobCardItems.stream()
.map(item -> Optional.ofNullable(item.getActualProduction()).orElse(BigDecimal.ZERO))
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal expectedProduction = jobCardItems.stream()
.map(item -> Optional.ofNullable(item.getExpectedProduction()).orElse(BigDecimal.ZERO))
.reduce(BigDecimal.ZERO, BigDecimal::add);
if (actualProduction.compareTo(BigDecimal.ZERO) == 0 ) {
totalProgress.put("Cutting Progress", BigDecimal.ZERO.intValue());
} else if (actualProduction.compareTo(expectedProduction) < 0) {
BigDecimal cuttingProgress = expectedProduction
.divide(actualProduction, 4, BigDecimal.ROUND_HALF_UP)
.multiply(BigDecimal.valueOf(100));
totalProgress.put("Cutting Progress", cuttingProgress.intValue());
}else if (actualProduction.compareTo(expectedProduction) > 0 || actualProduction.compareTo(expectedProduction) == 0){
totalProgress.put("Cutting Progress", 100);
}
if (totalProduction.compareTo(BigDecimal.ZERO) == 0){
totalProgress.put("Stitching Progress", BigDecimal.ZERO.intValue());
}else {
BigDecimal stitchingProgress = totalProduction
.divide(actualProduction, 4, BigDecimal.ROUND_HALF_UP)
.multiply(BigDecimal.valueOf(100));
totalProgress.put("Stitching Progress", stitchingProgress.intValue());
}
Long qaProgressItems = stitchingOfflineItemDAO.CalculateTotalQA(Long.parseLong(jobCardID));
if (qaProgressItems == 0){
totalProgress.put("QA Progress", 0);
}else {
BigDecimal qaProgress = BigDecimal.valueOf(qaProgressItems)
.divide(actualProduction, 4, BigDecimal.ROUND_HALF_UP)
.multiply(BigDecimal.valueOf(100));
totalProgress.put("QA Progress", qaProgress.intValue());
}
Long totalFinishItem = finishedItemDAO.calculateTotalFinishItem(Long.parseLong(jobCardID));
if (totalFinishItem == 0){
totalProgress.put("Finishing Progress", BigDecimal.ZERO.intValue());
}else {
BigDecimal finishItemProgress = BigDecimal.valueOf(totalFinishItem)
.divide(actualProduction, 4, BigDecimal.ROUND_HALF_UP)
.multiply(BigDecimal.valueOf(100));
totalProgress.put("Finishing Progress", finishItemProgress.intValue());
}
if (totalProduction.compareTo(BigDecimal.ZERO) == 0 && actualProduction.compareTo(BigDecimal.ZERO) == 0 ) {
totalProgress.put("Job Card Progress", BigDecimal.ZERO.intValue());
} else {
if (actualProduction.compareTo(expectedProduction)>0){
BigDecimal progressPercentage = actualProduction.add(totalProduction).add(BigDecimal.valueOf(qaProgressItems)).add(BigDecimal.valueOf(totalFinishItem))
.divide(actualProduction.multiply(BigDecimal.valueOf(4)), 4, RoundingMode.HALF_UP)
.multiply(BigDecimal.valueOf(100));
totalProgress.put("Job Card Progress", progressPercentage.intValue());
}else {
BigDecimal progressPercentage = actualProduction.add(totalProduction).add(BigDecimal.valueOf(qaProgressItems)).add(BigDecimal.valueOf(totalFinishItem))
.divide(expectedProduction.multiply(BigDecimal.valueOf(4)), 4, RoundingMode.HALF_UP)
.multiply(BigDecimal.valueOf(100));
totalProgress.put("Job Card Progress", progressPercentage.intValue());
}
}
return totalProgress;
}
}
public Integer getTotalProduction(String jobCardID){
if (jobCardID == null){
return 0;
}else {
List<JobCardItem> jobCardItems = jobCardItemDAO.findByCardId(Long.parseLong(jobCardID));
BigDecimal actualProduction = jobCardItems.stream()
.map(item -> Optional.ofNullable(item.getActualProduction()).orElse(BigDecimal.ZERO))
.reduce(BigDecimal.ZERO, BigDecimal::add);
return actualProduction.intValue();
}
}
public Map<String,Integer> getCompleteProduction(String jobCardID){
if (jobCardID == null){
return new HashMap<>();
}else {
HashMap<String,Integer> totalProgress = new HashMap<>();
List<JobCardItem> jobCardItems = jobCardItemDAO.findByCardId(Long.parseLong(jobCardID));
BigDecimal totalProduction = jobCardItems.stream()
.map(item -> Optional.ofNullable(item.getTotalProduction()).orElse(BigDecimal.ZERO))
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal actualProduction = jobCardItems.stream()
.map(item -> Optional.ofNullable(item.getActualProduction()).orElse(BigDecimal.ZERO))
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal expectedProduction = jobCardItems.stream()
.map(item -> Optional.ofNullable(item.getExpectedProduction()).orElse(BigDecimal.ZERO))
.reduce(BigDecimal.ZERO, BigDecimal::add);
Long qaProgressItems = stitchingOfflineItemDAO.CalculateTotalQA(Long.parseLong(jobCardID));
Long totalFinishItem = finishedItemDAO.calculateTotalFinishItem(Long.parseLong(jobCardID));
totalProgress.put("Cutting Progress", actualProduction.intValue());
totalProgress.put("Stitching Progress", totalProduction.intValue());
totalProgress.put("QA Progress", qaProgressItems.intValue());
totalProgress.put("Finishing Progress", totalFinishItem.intValue());
return totalProgress;
}
}
public Map<String,Integer> getSegregateItems(String jobCardID){
if (jobCardID == null){
return new HashMap<>();
}else {
HashMap<String,Integer> gradingItems = new HashMap<>();
List<InventoryAccount> inventoryAccounts = inventoryAccountDAO.getPackagingAccounts();
List<FinishedItem> finishedItems = finishedItemDAO.findByJobCardId(Long.parseLong(jobCardID));
List<Long> finishItemsIds = finishedItems.stream()
.map(FinishedItem::getId).collect(Collectors.toList());
if (finishItemsIds.isEmpty()){
return gradingItems;
}else {
for (InventoryAccount inventoryAccount : inventoryAccounts){
long totalGradingItems = inventoryTransactionLegDAO.CalculateTotalGradingItems(finishItemsIds,(int) inventoryAccount.getId());
gradingItems.put(inventoryAccount.getTitle(), (int) totalGradingItems);
}
return gradingItems;
}
}
}
public HashMap<String,String> getEachPhaseTotalTime(String jobCardID){
if (jobCardID == null){
return new HashMap<>();
}else {
HashMap<String,String> phasesTimes = new HashMap<>();
JobCard jobCard = jobCardDAO.find(Long.parseLong(jobCardID));
Bundle lastBundle = bundleDAO.findLastBundleByCardId(Long.parseLong(jobCardID));
//Cutting time
StringBuilder cuttingTime = generateTime(jobCard.getCreatedAt(),lastBundle.getCreatedAt());
phasesTimes.put("Cutting Total Time",cuttingTime.toString());
//Stitching time
List<Long> bundlesIds = bundleDAO.findByCardId(Long.parseLong(jobCardID)).stream().map(Bundle::getId).collect(Collectors.toList());
if (!bundlesIds.isEmpty()){
InventoryTransactionLeg inventoryTransactionLeg = inventoryTransactionLegDAO.getFirstStitchBundleTime(bundlesIds,"STITCH_BUNDLE");
StitchingOfflineItem lastStitchItem = stitchingOfflineItemDAO.getLastStitchItemByCardIdAndTime(Long.parseLong(jobCardID));
StringBuilder stitchingTime = generateTime(inventoryTransactionLeg.getTransactionLegDateTime(),lastStitchItem.getCreatedAt());
phasesTimes.put("Stitching Total Time",stitchingTime.toString());
}else {
phasesTimes.put("Stitching Total Time",null);
}
return phasesTimes;
}
}
public HashMap<String,String> countPendingItemsOnDifferentPhases(String jobCardID){
if (jobCardID == null){
return new HashMap<>();
}else {
HashMap<String,String> phasePending = new HashMap<String,String>();
List<JobCardItem> jobCardItems = jobCardItemDAO.findByCardId(Long.parseLong(jobCardID));
BigDecimal totalProduction = jobCardItems.stream()
.map(item -> Optional.ofNullable(item.getTotalProduction()).orElse(BigDecimal.ZERO))
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal actualProduction = jobCardItems.stream()
.map(item -> Optional.ofNullable(item.getActualProduction()).orElse(BigDecimal.ZERO))
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal expectedProduction = jobCardItems.stream()
.map(item -> Optional.ofNullable(item.getExpectedProduction()).orElse(BigDecimal.ZERO))
.reduce(BigDecimal.ZERO, BigDecimal::add);
if(actualProduction.compareTo(totalProduction) == 0) {
phasePending.put("Stitching Total Time", null);
}else {
phasePending.put("Stitching Total Time", "Pending");
}
return phasePending;
}
}
public Map<String, Map<String, Object>> getCuttingDetails(String jobCardID) {
if (jobCardID == null) {
return Collections.emptyMap();
}
Map<String, Map<String, Object>> cuttingDetails = new HashMap<>();
Map<String, InventoryAccount> cuttingAccount = new HashMap<>();
Map<String, String> cuttingPersonName = new HashMap<>();
Map<String, LocalDate> cuttingDate = new HashMap<>();
List<Bundle> bundles = bundleDAO.findByCardId(Long.parseLong(jobCardID));
if (bundles.isEmpty()) {
return cuttingDetails;
}
Map<Long, Bundle> bundleMap = bundles.stream()
.collect(Collectors.toMap(Bundle::getId, Function.identity()));
List<Long> bundleIds = new ArrayList<>(bundleMap.keySet());
List<InventoryTransactionLeg> inventoryTransactionLegs = inventoryTransactionLegDAO
.getTransactionByParentIdAndType(bundleIds, "BUNDLE");
for (InventoryTransactionLeg inventoryTransactionLeg : inventoryTransactionLegs) {
Integer accountId = inventoryTransactionLeg.getAccountId();
InventoryAccount inventoryAccount = inventoryAccountDAO.find(accountId.longValue());
if (inventoryAccount != null) {
String accountTitle = inventoryAccount.getTitle();
cuttingAccount.put(accountTitle, inventoryAccount);
Bundle bundle = bundleMap.get(inventoryTransactionLeg.getParentDocumentId());
cuttingPersonName.put(accountTitle, (bundle != null) ? bundle.getCreatedBy() : null);
cuttingDate.put(accountTitle,(bundle != null) ? bundle.getCreatedAt().toLocalDate() : null);
}
}
cuttingDetails.put("accounts", new HashMap<>(cuttingAccount));
cuttingDetails.put("personName", new HashMap<>(cuttingPersonName));
cuttingDetails.put("date", new HashMap<>(cuttingDate));
return cuttingDetails;
}
public Map<String, Map<String, Object>> getStitchingDetails(String jobCardID) {
if (jobCardID == null) {
return Collections.emptyMap();
}
Map<String, Map<String, Object>> stitchingDetails = new HashMap<>();
Map<String, InventoryAccount> stitchingAccount = new HashMap<>();
Map<String, String> stitchingPersonName = new HashMap<>();
Map<String, LocalDate> stitchingDate = new HashMap<>();
List<StitchingOfflineItem> stitchingOfflineItems = stitchingOfflineItemDAO.findByJobCardId(Long.parseLong(jobCardID));
if (stitchingOfflineItems.isEmpty()) {
return stitchingDetails;
}
Map<Long, StitchingOfflineItem> stitchingOfflineItemMap = stitchingOfflineItems.stream()
.collect(Collectors.toMap(StitchingOfflineItem::getId, Function.identity()));
List<Long> stitchingItemsArray = new ArrayList<>(stitchingOfflineItemMap.keySet());
List<InventoryTransactionLeg> inventoryTransactionLegs = inventoryTransactionLegDAO
.getTransactionByParentIdAndType(stitchingItemsArray, "STITCHING_OFFLINE");
for (InventoryTransactionLeg inventoryTransactionLeg : inventoryTransactionLegs) {
Integer accountId = inventoryTransactionLeg.getAccountId();
InventoryAccount inventoryAccount = inventoryAccountDAO.find(accountId.longValue());
if (inventoryAccount != null) {
String accountTitle = inventoryAccount.getTitle();
stitchingAccount.put(accountTitle, inventoryAccount);
StitchingOfflineItem stitchingOfflineItem = stitchingOfflineItemMap.get(inventoryTransactionLeg.getParentDocumentId());
stitchingPersonName.put(accountTitle, (stitchingOfflineItem != null) ? stitchingOfflineItem.getCreatedBy() : null);
stitchingDate.put(accountTitle,(stitchingOfflineItem != null) ? stitchingOfflineItem.getCreatedAt().toLocalDate() : null);
}
}
stitchingDetails.put("accounts", new HashMap<>(stitchingAccount));
stitchingDetails.put("personName", new HashMap<>(stitchingPersonName));
stitchingDetails.put("date", new HashMap<>(stitchingDate));
return stitchingDetails;
}
public Map<String, List<?>> getPhasesProgressDayWise(String jobCardID) {
if (jobCardID == null) {
return Collections.emptyMap();
}
List<JobCardItem> jobCardItems = jobCardItemDAO.findByCardId(Long.parseLong(jobCardID));
BigDecimal actualProduction = jobCardItems.stream()
.map(item -> Optional.ofNullable(item.getActualProduction()).orElse(BigDecimal.ZERO))
.reduce(BigDecimal.ZERO, BigDecimal::add);
LocalDateTime startDate = jobCardDAO.find(Long.parseLong(jobCardID)).getCreatedAt();
HashMap<String, List<?>> barChartData = new HashMap<>();
List<InventoryTransactionLeg> inventoryTransactionLegs = inventoryTransactionLegDAO
.getTransactionByJobCardAndDatesAndType(Long.parseLong(jobCardID), startDate.toString(), LocalDateTime.now().toString(), "IN");
//remove quality multiple transaction entry approved/rejects
List<InventoryTransactionLeg> filteredTransactions = inventoryTransactionLegs.stream()
.collect(Collectors.toMap(
leg -> leg.getAccountId() + "-" + leg.getParentDocumentType() + "-" + leg.getParentDocumentId(),
leg -> leg, // Value
(existing, replacement) -> existing.getTransactionLegDateTime().isBefore(replacement.getTransactionLegDateTime()) ? existing : replacement // Keep Oldest
))
.values()
.stream()
.collect(Collectors.toList());
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
List<String> uniqueDates = inventoryTransactionLegs.stream()
.map(leg -> leg.getTransactionLegDateTime().toLocalDate().format(formatter))
.distinct()
.sorted()
.collect(Collectors.toList());
Map<String, Integer> dateIndexMap = new HashMap<>();
for (int i = 0; i < uniqueDates.size(); i++) {
dateIndexMap.put(uniqueDates.get(i), i);
}
List<Integer> cuttingList = new ArrayList<>(Collections.nCopies(uniqueDates.size(), 0));
List<Integer> stitchingList = new ArrayList<>(Collections.nCopies(uniqueDates.size(), 0));
List<Integer> qualityList = new ArrayList<>(Collections.nCopies(uniqueDates.size(), 0));
List<Integer> finishItems = new ArrayList<>(Collections.nCopies(uniqueDates.size(), 0));
for (InventoryTransactionLeg leg : filteredTransactions) {
String dateKey = leg.getTransactionLegDateTime().format(formatter);
int index = dateIndexMap.get(dateKey);
if ("BUNDLE".equals(leg.getParentDocumentType())) {
Bundle bundle = bundleDAO.find(leg.getParentDocumentId());
cuttingList.set(index, cuttingList.get(index) + bundle.getWrapQuantity().intValue());
}
else if ("STITCHING_OFFLINE".equals(leg.getParentDocumentType())) {
stitchingList.set(index, stitchingList.get(index) + leg.getQuantity().intValue());
}
else if ("FINISHED_ITEM".equals(leg.getParentDocumentType()) && (leg.getAccountId().equals(7) || leg.getAccountId().equals(12))) {
if (index == 0 || !dateIndexMap.containsKey(dateKey)) {
qualityList.set(index, 0);
}
qualityList.set(index, qualityList.get(index) + leg.getQuantity().intValue());
}else if ("FINISHED_ITEM".equals(leg.getParentDocumentType()) && (leg.getAccountId().equals(8) || leg.getAccountId().equals(9) || leg.getAccountId().equals(10))) {
if (index == 0 || !dateIndexMap.containsKey(dateKey)) {
finishItems.set(index, 0);
}
finishItems.set(index, finishItems.get(index) + leg.getQuantity().intValue());
}
}
barChartData.put("dates", uniqueDates);
barChartData.put("cutting", cuttingList);
barChartData.put("stitching", stitchingList);
barChartData.put("quality", qualityList);
barChartData.put("finishing", finishItems);
return barChartData;
}
private StringBuilder generateTime(LocalDateTime startDate, LocalDateTime endDate){
StringBuilder totalTime = new StringBuilder();
if(startDate != null && endDate != null){
Duration duration = Duration.between(startDate, endDate);
if (duration.toDays() > 0) {
totalTime.append(String.format("%d days, ", duration.toDays()));
}
if (duration.toHours() % 24 > 0) {
totalTime.append(String.format("%d hours, ", duration.toHours() % 24));
}
if (duration.toMinutes() % 60 > 0) {
totalTime.append(String.format("%d minutes ", duration.toMinutes() % 60));
}
return totalTime;
}else return totalTime.append("");
}
}

View File

@ -4,58 +4,64 @@ document.addEventListener("DOMContentLoaded", function () {
return; return;
} }
function createGaugeChart(config) { function createGaugeChart(progress, color, divId, title, height, width , fontSize, fontYAxis, fontXAxis, fontColor, total, actual, aGrade, bGrade, cGrade) {
Highcharts.chart(config.containerId, { Highcharts.chart(divId, {
chart: { chart: {
type: 'solidgauge', type: 'solidgauge',
width: config.width, width: width,
height: config.height, height: height,
backgroundColor: 'transparent', backgroundColor: 'transparent',
plotBackgroundColor: null, plotBackgroundColor: null,
shadow: false shadow: false
}, },
title: { title: {
text: config.title, text: title,
y: 30 y: 30
}, },
pane: { pane: {
startAngle: 0, startAngle: 0,
endAngle: 360, endAngle: 360,
y: config.CirclePosition, y: 0,
background: [{ background: [{
backgroundColor: 'transparent', backgroundColor: 'transparent',
shape: "arc", shape: "arc",
borderWidth: 0, borderWidth: 0,
innerRadius: config.innerRadius, innerRadius: '60%',
outerRadius: config.outerRadius outerRadius: '100%'
}] }]
}, },
yAxis: { yAxis: {
min: config.minValue, min: 0,
max: config.maxValue, max: 100,
tickPositions: [], tickPositions: [],
lineWidth: 0, lineWidth: 0,
minorTickLength: 0, minorTickLength: 0,
tickWidth: 0, tickWidth: 0,
gridLineWidth: 0, gridLineWidth: 0,
stops: [ stops: [
[1, config.color] [1, color]
] ]
}, },
series: [{ series: [{
name: 'Percentage', name: 'Percentage',
data: [config.speed], data: [progress],
dataLabels: { dataLabels: {
format: '{y}% <br>' + config.totalPiece + " | " + config.completedPiece, format: '{y}% ',
y: config.InnerTextYPosition, y: fontYAxis,
x: fontXAxis,
borderWidth: 0, borderWidth: 0,
backgroundColor: 'none', backgroundColor: 'none',
style: { style: {
fontSize: config.fontSize, fontSize: fontSize + 'px',
fontWeight: 'bold' fontWeight: 'bold',
} color:fontColor
}, },
color: config.color, zIndex: 10
},
tooltip: {
pointFormat: title == 'Finishing Progress' ? 'Percentage: ' + progress + '%<br>Total: ' + total + '<br>Completed: ' + actual + '<br>A Grade: ' + aGrade + '<br>B Grade: ' + bGrade + '<br>C Grade: ' + cGrade : 'Percentage: ' + progress + '%<br>Total: ' + total + '<br>Completed:'+actual
},
color: color,
showInLegend: false showInLegend: false
}], }],
credits: { credits: {
@ -63,48 +69,130 @@ document.addEventListener("DOMContentLoaded", function () {
} }
}); });
} }
function createBarChart(divId, height, width, title, aHeading, aData, bHeading, bData, cHeading, cData, dHeading, dData, dates, fontSize, maxValue) {
function createBarChart(config) { if (!document.getElementById(divId)) {
console.log(`Creating bar chart for '${config.containerId}'`);
if (!document.getElementById(config.containerId)) {
console.error(`Bar chart container '${config.containerId}' not found!`);
return; return;
} }
console.log(maxValue);
Highcharts.chart(config.containerId, { Highcharts.chart(divId, {
chart: { chart: {
type: 'column', type: 'column',
height: 400, height: height,
width: 1600, // Ensure the chart is wider than the container width: width,
marginTop: 60, },
spacingTop: 30 title: {
text: title,
align: 'center',
verticalAlign: 'top',
y: 30,
style: {
fontSize: fontSize,
fontWeight: 'bold',
}
}, },
xAxis: { xAxis: {
categories: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", categories: dates,
"Next Monday", "Next Tuesday", "Next Wednesday", "Friday", "Saturday", "Sunday"],
labels: { labels: {
rotation: -45 // Optional: Rotate labels if needed 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: { scrollbar: {
enabled: true // Ensure Highcharts scrollbar is enabled enabled: true
}, },
series: [ series: [{
{ name: 'Model A', data: [0.8, 0.75, 0.78, 0.79, 0.77, 0.81, 0.80, 0.76, 0.79, 0.80, 0.76, 0.79, 0.80, 0.76, 0.79, 0.80] }, name: aHeading,
{ name: 'Model B', data: [0.85, 0.78, 0.82, 0.80, 0.79, 0.84, 0.83, 0.78, 0.82, 0.83, 0.76, 0.79, 0.80, 0.76, 0.79, 0.80] }, data: aData
{ name: 'Model C', data: [0.88, 0.80, 0.85, 0.82, 0.81, 0.87, 0.85, 0.80, 0.85, 0.86, 0.76, 0.79, 0.80, 0.76, 0.79, 0.80] }, }, {
{ name: 'Model D', data: [0.9, 0.83, 0.87, 0.84, 0.83, 0.89, 0.88, 0.83, 0.87, 0.88, 0.76, 0.79, 0.80, 0.76, 0.79, 0.80] } name: bHeading,
] data: bData
}, {
name: cHeading,
data: cData
}, {
name: dHeading,
data: dData
}]
}); });
console.log(`Bar chart '${config.containerId}' created successfully.`);
} }
initializeGauges();
function initializeGauges() {
const gaugeDivs2 = document.querySelectorAll('.gauge-chart2');
gaugeDivs2.forEach(function (div) {
gaugeConfigs.forEach(createGaugeChart); const progress = div.getAttribute('data-progress');
createBarChart(barChartConfigs); const color = div.getAttribute('data-color');
const title = div.getAttribute('data-title');
const height = div.getAttribute('data-height');
const width = div.getAttribute('data-width');
const fontSize = div.getAttribute('data-fontSize');
const fontColor = div.getAttribute('data-fontColor');
const total = div.getAttribute('data-totalProduction');
const actual = div.getAttribute('data-actualProduction');
const divId = div.id;
createGaugeChart(parseInt(progress), color, divId, title, height, width, fontSize, -20, 4, fontColor, total, actual);
});
const gaugeDivs = document.querySelectorAll('.gauge-chart');
gaugeDivs.forEach(function (div) {
const progress = div.getAttribute('data-progress');
const color = div.getAttribute('data-color');
const title = div.getAttribute('data-title');
const height = div.getAttribute('data-height');
const width = div.getAttribute('data-width');
const fontSize = div.getAttribute('data-fontSize');
const fontColor = div.getAttribute('data-fontColor');
const total = div.getAttribute('data-totalProduction');
const actual = div.getAttribute('data-actualProduction');
const aGrade = div.getAttribute('data-aGrade');
const bGrade = div.getAttribute('data-bGrade');
const cGrade = div.getAttribute('data-cGrade');
const divId = div.id;
createGaugeChart(parseInt(progress), color, divId, title, height, width, fontSize, -15, 2, fontColor, total, actual, aGrade, bGrade, cGrade);
});
const barChart = document.querySelectorAll('.barChart');
barChart.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 aHeading = 'Cutting';
const aData = JSON.parse(div.getAttribute('data-cutting'));
const bHeading='Stitching';
const bData =JSON.parse(div.getAttribute('data-stitching'));
const cHeading='End Line Quality Checking';
const cData =JSON.parse(div.getAttribute('data-quality'));
const dHeading="Finish Items";
const dData =JSON.parse(div.getAttribute('data-finishing'));
const dates = div.getAttribute('data-dates');
const datesArray = dates.split(',');
const divId = div.id;
console.log(maxValue, typeof maxValue)
createBarChart( divId, height, width, title,aHeading,aData,bHeading,bData,cHeading,cData,dHeading,dData,datesArray,fontSize,maxValue);
});
}
}); });

View File

@ -3438,6 +3438,44 @@ if ( typeof Vue !== 'undefined' ) {
}) })
/*
* job card search for reporting
* */
Vue.component('job-card-for-reporting',{
mixins: [searchComponentMixin],
methods : {
getSearchUrl : function () {
let url = `/ctp/rest/job-cards/search?term=${encodeURIComponent(this.list.term)}&filter=false`;
if( ! this.filter ){
url += '&filter=false'
}
return url;
},
getEmittedEventName: function() {
return 'job-card-select';
},
getTitle: function( card ) {
return `(${card.code}) - ${card.createdBy}`;
}
},
props: {
labelText: {
default: 'Search Job Card'
},
titleFieldName: {
default: 'cardTitle'
},
idFieldName: {
default: 'jobCardId'
},
codeFieldName : {
default : 'jobCardCode'
},
filter : {
default : true
}
}
})
/* /*

View File

@ -7,46 +7,12 @@
<div class="page-filters-sidebar"> <div class="page-filters-sidebar">
<form th:action="@{${#strings.replace(#httpServletRequest.requestURI, #request.getContextPath(), '')}}"> <form th:action="@{${#strings.replace(#httpServletRequest.requestURI, #request.getContextPath(), '')}}">
<h5 class="mb-4">Refine Your Search</h5> <h5 class="mb-4">Refine Your Search</h5>
<div class="form-group">
<label>ID</label>
<input type="text" class="form-control" name="id" maxlength="100" th:value="${param['id']}">
</div>
<div class="form-group">
<label>Title</label>
<input type="text" class="form-control" name="title" maxlength="100"
th:value="${param['title']}">
</div>
<div class="form-group">
<label>Active</label>
<select name="active" class="form-control" >
<option value="">Please select</option>
<option value="1" th:selected="${#strings.equals(param['active'], #strings.toString(1))}">Active</option>
<option value="0" th:selected="${#strings.equals(param['active'], #strings.toString(0))}">Inactive</option>
</select>
</div>
<div class="form-group">
<label>Created By</label>
<input type="text" class="form-control" name="created-by" maxlength="50" th:value="${param['created-by']}">
</div>
<div class="form-group">
<label>Created Start Date</label>
<input type="date" class="form-control" name="start-date" th:value="${param['start-date']}">
</div>
<div class="form-group">
<label>Created End Date</label>
<input type="date" class="form-control" name="end-date" th:value="${param['end-date']}">
</div>
<div class="form-group" th:with="id=${param['site-id']},title=${param['site-title']}" data-vue-app> <div class="form-group" th:with="id=${param['site-id']},title=${param['site-title']}" data-vue-app>
<location-site-search th:attr="id=${id},title=${title}" <job-card-for-reporting th:attr="id=${id},title=${title}"
v-bind:id-field-name="'site-id'" v-bind:id-field-name="'job-card-id'"
v-bind:title-field-name="'site-title'" v-bind:title-field-name="'site-title'"
></location-site-search> ></job-card-for-reporting>
</div> </div>
<div class="form-group">
<label>Count</label>
<input type="number" class="form-control" name="count" th:value="${param['count'] ?: 100}" min="0" step="1" />
</div>
<input type="submit" class="btn btn-secondary btn-block" value="Search"> <input type="submit" class="btn btn-secondary btn-block" value="Search">
<a th:href="@{${#strings.replace(#httpServletRequest.requestURI, #request.getContextPath(), '')}}" <a th:href="@{${#strings.replace(#httpServletRequest.requestURI, #request.getContextPath(), '')}}"
class="btn btn-secondary btn-block">Reset</a> class="btn btn-secondary btn-block">Reset</a>

View File

@ -12,50 +12,60 @@
<div class="col-sm"> <div class="col-sm">
<table class="table " > <table class="table " >
<tbody> <tbody>
<tr> <tr th:if="${jobCardProgress != null }">
<td style="padding:0px;"> <td style="padding:0px;">
<div style="border: 2px solid #d5d8dc; padding: 10px; border-radius: 10px; height: 370px;"> <div style="border: 2px solid #d5d8dc; padding: 10px; border-radius: 10px; height: 370px;">
<h1 style="text-align: center; margin-left: 300px">Job Card Report</h1> <h1 style="text-align: center;">Job Card Report</h1>
<div style="display: flex; align-items: center;"> <div style="display: flex; align-items: center;">
<div style="text-align: center;margin-top: -45px"> <div style="text-align: center;margin-top: -45px">
<div id="jobCard" style="width: 300px; height: 330px;"></div> <div style="width: 300px; height: 330px;"
th:id="'gauge-chart2'"
class="gauge-chart2"
th:data-progress="${jobCardProgress.get('Job Card Progress')}"
th:data-title="${'Job Card Progress'}"
th:data-width="350"
th:data-height="350"
th:data-totalProduction="${totalProduction}"
th:data-actualProduction="${jobCardProgress.get('actualProduction')}"
th:data-fontSize="30"
th:data-fontColor="'#17202a'"
th:data-color="'#566573'"></div>
</div> </div>
<div style="display: flex; "> <div style="display: flex; ">
<div style="text-align: center; margin-top: 40px;"> <div th:each="title, index : ${jobCardProgress.keySet()}" style="text-align: center; margin-top: 40px;">
<div id="cutting" style="width: 200px; height: 200px;"></div> <div th:if ="${ title != 'Job Card Progress' }"
th:id="'gauge-chart-' + ${index}" class="gauge-chart" style="width: 200px; height: 230px;"
th:data-progress="${jobCardProgress.get(title)}"
th:data-totalProduction="${totalProduction}"
th:data-actualProduction="${completeProduction.get(title)}"
th:data-title="${title}"
th:data-width="230"
th:data-height="230"
th:data-fontSize="20"
th:data-aGrade="${segregateItems.get('A GRADE') == null ? 0 : segregateItems.get('A GRADE')}"
th:data-bGrade="${segregateItems.get('B GRADE') == null ? 0 : segregateItems.get('B GRADE')}"
th:data-cGrade="${segregateItems.get('C GRADE') == null ? 0 : segregateItems.get('C GRADE')}"
th:data-fontColor="'#17202a'"
th:data-color="'#95a5a6'">
</div> </div>
<div style="text-align: center; margin-top: 40px;">
<div id="stitching" style="width: 200px; height: 200px;"></div>
</div>
<div style="text-align: center; margin-top: 40px;">
<div id="quality" style="width: 200px; height: 200px;"></div>
</div>
<div style="text-align: center; margin-top: 40px;">
<div id="finishing" style="width: 200px; height: 200px;"></div>
</div>
<div style="text-align: center; margin-top: 40px;">
<div id="Packaging" style="width: 200px; height: 200px;"></div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</td> </td>
</tr> </tr>
<tr> <tr th:if="${phasesTimes != null }">
<td style="display: flex; flex-direction: column; align-items: center; border: none !important; outline: none;"> <td style="display: flex; flex-direction: column; align-items: center; border: none !important; outline: none;">
<div style="display: flex; gap: 10px;"> <div style="display: flex; gap: 10px;">
<div style="border: 2px solid #d5d8dc; border-radius: 10px; text-align: center; padding:20px;"> <div th:each="phase, index : ${phasesTimes.keySet()}" style="border: 2px solid #d5d8dc; border-radius: 10px; text-align: center; padding:20px;">
<H6>Cutting Total Time</H6> <H6 th:text="${phase}"></H6>
<H6>10</H6> <H6 th:text="${phasesTimes.get(phase)}"></H6>
<H6 th:if="${pendingStatus.get(phase) != null}" th:text="${pendingStatus.get(phase)}"></H6>
</div> </div>
<div style="border: 2px solid #d5d8dc; border-radius: 10px; text-align: center; padding:20px;"><H6>Stitching Total Time</H6></div>
<div style="border: 2px solid #d5d8dc; border-radius: 10px; text-align: center; padding:20px;"><H6>Quality Checking Total Time</H6></div>
<div style="border: 2px solid #d5d8dc; border-radius: 10px; text-align: center; padding:20px;"><H6>Finishing Total Time</H6></div>
<div style="border: 2px solid #d5d8dc; border-radius: 10px; text-align: center; padding:20px;"><H6>Packaging Total Time</H6></div>
</div> </div>
</td> </td>
</tr> </tr>
<tr> <tr th:if="${cuttingDetails != null && cuttingDetails.get('accounts') != null}">
<td style="padding: 0px; text-align: center;"> <td 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
@ -66,24 +76,27 @@
<th>ID</th> <th>ID</th>
<th>Title</th> <th>Title</th>
<th>Cutting</th> <th>Cutting</th>
<th>Cutting Day</th> <th>Cutting Date</th>
<th>Cutting Table Descriptions</th> <th>Cutting Table Descriptions</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr> <tr th:if="${cuttingDetails != null}" th:each="detail, index : ${cuttingDetails.get('accounts').keySet()}">
<td th:text="1"></td> <td th:text="${cuttingDetails.get('accounts').get(detail).id}"></td>
<td th:text="'Cutting Account 1'"></td> <td th:text="${cuttingDetails.get('accounts').get(detail).title}"></td>
<td th:text="Usama"></td> <td th:text="${cuttingDetails.get('personName').get(detail)}"></td>
<td th:text="Friday"></td> <td>
<td th:text="'Cutting Table'"></td> <span th:text="${#temporals.format(cuttingDetails.get('date').get(detail), 'E')}"></span>
<span ctp:formatdate="${cuttingDetails.get('date').get(detail)}" ></span>
</td>
<td th:text="${cuttingDetails.get('accounts').get(detail).notes}"></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</td> </td>
</tr> </tr>
<tr> <tr th:if="${stitchingDetails != null && stitchingDetails.get('accounts') != null}">
<td style="padding: 0px; text-align: center; "> <td 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
@ -98,149 +111,48 @@
<th>Stitching Table Descriptions</th> <th>Stitching Table Descriptions</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody th:if="${stitchingDetails != null and stitchingDetails.get('accounts') != null}">
<tr> <tr th:each="detail : ${stitchingDetails.get('accounts').keySet()}">
<td th:text="1"></td> <td th:text="${stitchingDetails.get('accounts').get(detail).id}"></td>
<td th:text="'Stitching Account 1'"></td> <td th:text="${stitchingDetails.get('accounts').get(detail).title}"></td>
<td th:text="Usama"></td> <td th:text="${stitchingDetails.get('personName') != null ? stitchingDetails.get('personName').get(detail) : ''}"></td>
<td th:text="Friday"></td> <td>
<td th:text="'Stitching Table'"></td> <span th:if="${stitchingDetails.get('date') != null and stitchingDetails.get('date').get(detail) != null}" th:text="${#temporals.format(stitchingDetails.get('date').get(detail), 'E')}"></span>
<span th:if="${stitchingDetails.get('date') != null and stitchingDetails.get('date').get(detail) != null}" ctp:formatdate="${stitchingDetails.get('date').get(detail)}"></span>
</td>
<td th:text="${stitchingDetails.get('accounts').get(detail).notes}"></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</td> </td>
</tr> </tr>
<tr> <tr th:if="${dailyProgress != null}">
<td style="padding-left: 150px;"> <td style="padding-left: 150px;">
<div style="border: 2px solid #d5d8dc; padding-top: 10px; border-radius: 10px; height: 460px; 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" style="height: 400px; width: 1600px;"></div> <!-- 100% width for responsiveness --> <div id="barChart" class="barChart" style="height: 500px; width: 1600px;"
th:data-width="1600"
th:data-height="500"
th:data-title="'Days Wise Progress'"
th:data-dates="${dailyProgress.get('dates')}"
th:data-cutting="${dailyProgress.get('cutting')}"
th:data-stitching="${dailyProgress.get('stitching')}"
th:data-quality="${dailyProgress.get('quality')}"
th:data-finishing="${dailyProgress.get('finishing')}"
th:data-totalProduction="${completeProduction.get('Cutting Progress')}"
th:data-fontSize="30"
></div>
</div> </div>
</td> </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
</main> </main>
</div> </div>
<script>
var gaugeConfigs = [
{
containerId: "jobCard",
width: 350,
height: 350,
minValue: 0,
maxValue: 100,
speed: 10,
innerRadius: "80%",
outerRadius: "20%",
color: "#566573",
title: "Job Card Report",
fontSize:10,
InnerTextYPosition:-20,
totalPiece:200,
completedPiece:100,
CirclePosition:-20
},
{
containerId: "cutting",
width: 200,
height: 200,
minValue: 0,
maxValue: 300,
speed: 250,
innerRadius: "60%",
outerRadius: "100%",
color: "#5dade2",
title: "Cutting Report",
fontSize:10,
InnerTextYPosition:-20,
totalPiece:200,
completedPiece:100
},
{
containerId: "stitching",
width: 200,
height: 200,
minValue: 0,
maxValue: 300,
speed: 250,
innerRadius: "60%",
outerRadius: "100%",
color: "#76d7c4",
title: "Stitching Report",
fontSize:10,
InnerTextYPosition:-20,
totalPiece:200,
completedPiece:100
},
{
containerId: "quality",
width: 200,
height: 200,
minValue: 0,
maxValue: 300,
speed: 250,
innerRadius: "60%",
outerRadius: "100%",
color: "#73c6b6",
title: "Quality Report",
fontSize:10,
InnerTextYPosition:-20,
totalPiece:200,
completedPiece:100
},{
containerId: "finishing",
width: 200,
height: 200,
minValue: 0,
maxValue: 300,
speed: 250,
innerRadius: "60%",
outerRadius: "100%",
color: "#58d68d",
title: "Finishing Report",
fontSize:10,
InnerTextYPosition:-20,
totalPiece:200,
completedPiece:100
},
{
containerId: "Packaging",
width: 200,
height: 200,
minValue: 0,
maxValue: 300,
speed: 250,
innerRadius: "60%",
outerRadius: "100%",
color: "#f5cba7",
title: "Finishing Report",
fontSize:10,
InnerTextYPosition:-20,
totalPiece:200,
completedPiece:100
}
];
const barChartConfigs = {
containerId: "barChart",
title: "Day-wise Performance Metrics",
max:16,
categories: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", "Next Monday", "Next Tuesday", "Next Wednesday", "Friday", "Saturday", "Sunday", "Next Monday", "Next Tuesday", "Next Wednesday"],
series: [
{ name: "Model A", data: [0.8, 0.75, 0.78, 0.76, 0.74, 0.80, 0.77, 0.79, 0.81, 0.76, 0.80, 0.77, 0.79, 0.81, 0.76], color: "#007bff" },
{ name: "Model B", data: [0.85, 0.7, 0.77, 0.79, 0.72, 0.83, 0.78, 0.80, 0.82, 0.75,0.83, 0.78, 0.80, 0.82, 0.75], color: "#28a745" },
{ name: "Model C", data: [0.82, 0.72, 0.79, 0.80, 0.78, 0.85, 0.81, 0.84, 0.86, 0.79, 0.85, 0.81, 0.84, 0.86, 0.79], color: "#dc3545" },
{ name: "Model D", data: [0.88, 0.78, 0.83, 0.85, 0.82, 0.89, 0.85, 0.87, 0.90, 0.83, 0.89, 0.85, 0.87, 0.90, 0.83], color: "#fd7e14" }
]
};
</script>
<!-- Load JavaScript file --> <!-- Load JavaScript file -->
<script th:src="@{/js/charts.js}"></script> <script th:src="@{/js/charts.js}"></script>
</body> </body>