Compare commits

..

32 Commits

Author SHA1 Message Date
saif.haq 6ac6a42a60 Merge pull request 'add stitching report dashboard' (#19) from add-stitching-dashboard into main
Reviewed-on: #19
2025-04-24 05:23:36 +00:00
Usama Khan 4a94cac214 fix table searching issues 2025-04-24 10:21:16 -07:00
Usama Khan 4c01a5ee1a add stitching report dashboard 2025-04-24 09:05:05 -07:00
saif.haq eb9c4cce02 Merge pull request 'add-reporting-dashboard' (#18) from add-reporting-dashboard into main
Reviewed-on: http://git.utopiadeals.com:8080/UIND/cut-to-pack-service/pulls/18
2025-04-22 05:10:09 +00:00
Usama Khan a2fe57d256 add Cutting Report dashboard 2025-04-18 13:12:10 -07:00
Usama Khan 91d6fdaa89 add PO's based job Card dashboard 2025-04-11 16:56:33 -07:00
Usama Khan 9a541b8389 fix redirect and null exceptioin on dashboard screen 2025-04-10 12:19:54 -07:00
Usama Khan 2cd71d3828 barchart and cutting details and stitching detail 2025-04-10 10:51:45 -07:00
Usama Khan 6da953ad69 add barchart and add jobcard id in transactionleg table 2025-04-09 12:09:01 -07:00
Usama Khan 93f6b01ece fixed job card progress 2025-04-07 17:21:10 -07:00
saif 05c14e0940 - bug fixed 2025-03-27 13:10:36 +05:00
Usama Khan 7014d0bfcb fixed bar chart 2025-03-27 12:56:54 -07:00
saif.haq 9e25a4f2de Merge pull request 'update-job-card-print' (#17) from update-job-card-print into main
Reviewed-on: http://git.utopiadeals.com:8080/UIND/cut-to-pack-service/pulls/17
2025-03-13 07:38:18 +00:00
Usama Khan 7596eb05f1 fixed comments 2025-03-13 01:35:59 -07:00
Usama Khan 760a667adb fixed comments 2025-03-13 01:33:59 -07:00
Usama Khan 9a6514c724 fixed comments 2025-03-13 01:32:16 -07:00
Usama Khan f7f8cf8df3 set min value and remove max in stitching side bar 2025-03-12 23:53:28 -07:00
Usama Khan be08c72056 fixed job card print and add bundle id in stitching offline item and make table dsc order 2025-03-12 23:42:39 -07:00
saif.haq 229be993d5 Merge pull request 'fixed null pointer Exception' (#16) from print-job-card into main
Reviewed-on: http://git.utopiadeals.com:8080/UIND/cut-to-pack-service/pulls/16
2025-03-07 05:21:23 +00:00
Usama Khan c39d5c0805 fixed null pointer Exception 2025-03-06 22:19:14 -08:00
Usama Khan fae2e12c84 fixed Items Search By SKu 2025-03-05 00:09:56 -08:00
saif.haq 98b6cae284 Merge pull request 'fixed Items Search By SKu' (#15) from print-job-card into main
Reviewed-on: http://git.utopiadeals.com:8080/UIND/cut-to-pack-service/pulls/15
2025-03-05 07:53:18 +00:00
Usama Khan 79d47a66b0 fixed comments 2025-03-04 22:02:24 -08:00
Usama Khan 78c1d7682f change pdf name 2025-03-04 21:47:27 -08:00
saif.haq be680eb413 Merge pull request 'print-job-card' (#14) from print-job-card into main
Reviewed-on: http://git.utopiadeals.com:8080/UIND/cut-to-pack-service/pulls/14
2025-03-05 05:05:33 +00:00
Usama Khan 18c92a362f add job card print 2025-03-04 04:03:41 -08:00
saif.haq f70ddecfa6 Merge pull request 'fixed-serach-item' (#12) from fixed-serach-item into main
Reviewed-on: http://git.utopiadeals.com:8080/UIND/cut-to-pack-service/pulls/12
2025-03-03 05:11:24 +00:00
Usama Khan a21d0d07f9 change Field name 2025-03-02 21:29:56 -08:00
Usama Khan 4ad26f4fa6 fixed manually enter bundle Quantity and Total production and Qr field scan autofocus and Barcode scan Field autofocus 2025-03-01 05:55:45 -08:00
saif.haq f619001e5f Merge pull request 'add_QRCode' (#11) from add_QRCode into main
Reviewed-on: http://git.utopiadeals.com:8080/UIND/cut-to-pack-service/pulls/11
2025-02-28 07:11:00 +00:00
saif.haq 9869e3c9c0 Merge pull request 'fix path' (#9) from add_QRCode into main
Reviewed-on: http://git.utopiadeals.com:8080/UIND/cut-to-pack-service/pulls/9
2025-02-27 06:08:56 +00:00
saif.haq b3bc4c5e6d Merge pull request 'add_QRCode' (#8) from add_QRCode into main
Reviewed-on: http://git.utopiadeals.com:8080/UIND/cut-to-pack-service/pulls/8
2025-02-27 05:06:04 +00:00
70 changed files with 7213 additions and 137 deletions

View File

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

View File

@ -8,6 +8,9 @@ import com.utopiaindustries.service.InventoryAccountService;
import com.utopiaindustries.service.JobCardService; import com.utopiaindustries.service.JobCardService;
import com.utopiaindustries.service.LocationService; import com.utopiaindustries.service.LocationService;
import com.utopiaindustries.util.StringUtils; import com.utopiaindustries.util.StringUtils;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -173,6 +176,11 @@ public class JobCardController {
return "job-card-view"; return "job-card-view";
} }
@GetMapping( value = "/pdf/{id}", produces = MediaType.APPLICATION_PDF_VALUE )
public ResponseEntity<InputStreamResource> generateJobCardPdf(@PathVariable long id, Model model ) throws Exception {
return jobCardService.getJobCardReceivingPdf(id,model);
}
private ArrayList<LocalDate> generateDateList(LocalDate start, LocalDate end) { private ArrayList<LocalDate> generateDateList(LocalDate start, LocalDate end) {
ArrayList<LocalDate> localDates = new ArrayList<>(); ArrayList<LocalDate> localDates = new ArrayList<>();
while (start.isBefore(end)) { while (start.isBefore(end)) {

View File

@ -1,15 +1,18 @@
package com.utopiaindustries.controller; package com.utopiaindustries.controller;
import com.utopiaindustries.auth.CuttingRole;
import com.utopiaindustries.auth.ReportingRole; import com.utopiaindustries.auth.ReportingRole;
import com.utopiaindustries.model.ctp.SummaryInventoryReport; import com.utopiaindustries.model.ctp.SummaryInventoryReport;
import com.utopiaindustries.service.InventoryAccountService;
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;
import org.springframework.ui.Model; 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.PathVariable;
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,14 +23,19 @@ 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;
private final InventoryAccountService inventoryAccountService;
public ReportingController(SummaryInventoryReportService summaryInventoryReportService2) {
public ReportingController(SummaryInventoryReportService summaryInventoryReportService2, ReportingService reportingService, InventoryAccountService inventoryAccountService) {
this.summaryInventoryReportService = summaryInventoryReportService2; this.summaryInventoryReportService = summaryInventoryReportService2;
this.reportingService = reportingService;
this.inventoryAccountService = inventoryAccountService;
} }
@GetMapping( "/summary") @GetMapping( "/summary")
public String showMasterBundles(@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 summary(@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 ){
LocalDate startDate1 = StringUtils.isNullOrEmpty(startDate) ? LocalDate.now().minusDays(6) : LocalDate.parse(startDate); LocalDate startDate1 = StringUtils.isNullOrEmpty(startDate) ? LocalDate.now().minusDays(6) : LocalDate.parse(startDate);
LocalDate endDate1 = StringUtils.isNullOrEmpty(endDate) ? LocalDate.now().plusDays(1) : LocalDate.parse(endDate); LocalDate endDate1 = StringUtils.isNullOrEmpty(endDate) ? LocalDate.now().plusDays(1) : LocalDate.parse(endDate);
@ -40,6 +48,83 @@ public class ReportingController {
return "/reporting/inventory-summary"; return "/reporting/inventory-summary";
} }
@GetMapping( "/job-card-report")
public String jobCardReport(@RequestParam( value = "job-card-id", required = false ) String jobCardId,
Model model, RedirectAttributes redirectAttributes ){
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";
}
@GetMapping( "/po-report")
public String poReport(@RequestParam(value = "poName", required = false) String poName, Model model){
model.addAttribute("allPOs", reportingService.getAllPOs(poName));
return "/reporting/po-report";
}
@GetMapping( value = "/po-report-view/{poNo}" )
public String showJobCardDetail( @PathVariable("poNo") String poNo, @RequestParam(value = "select-date", required = false) String selectDate ,
Model model ){
model.addAttribute("allJobCard", reportingService.getAllPoJobCards(poNo, selectDate));
return "/reporting/po-job-card-report";
}
@GetMapping( value = "/cutting-report" )
public String cuttingReport(@RequestParam(value = "job-card-id", required = false ) String jobCardId, @RequestParam(value = "accountId" , required = false) String accountId, @RequestParam(value = "start-date", required = false) String startDate, @RequestParam(value = "end-date", required = false) String endDate, Model model ){
LocalDate startDate1 = StringUtils.isNullOrEmpty(startDate) ? LocalDate.now().minusDays(31) : LocalDate.parse(startDate);
LocalDate endDate1 = StringUtils.isNullOrEmpty(endDate) ? LocalDate.now() : LocalDate.parse(endDate);
model.addAttribute("startDate", startDate1);
model.addAttribute("endDate", endDate1);
model.addAttribute("accounts", inventoryAccountService.getAllCuttingAccounts() );
model.addAttribute("cutting",reportingService.getCuttingTableDetails(jobCardId, accountId, startDate1.toString(), endDate1.toString()));
return "/reporting/cutting-report";
}
@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 ){
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()));
return "/reporting/stitching-report";
}
@GetMapping( "/inventory-transactions" )
public String getInventoryTransactionsByAccount( @RequestParam( value = "account-id", required = false) String accountId,
@RequestParam( value = "jobCard-id", required = false) String jobCardId,
@RequestParam( value = "sku", required = false) String sku,
@RequestParam( value = "startDate", required = false) String startDate,
@RequestParam( value = "endDate", required = false) String endDate,
Model model ){
LocalDate startDate1 = StringUtils.isNullOrEmpty(startDate) ? LocalDate.now().minusDays(31) : LocalDate.parse(startDate);
LocalDate endDate1 = StringUtils.isNullOrEmpty(endDate) ? LocalDate.now() : LocalDate.parse(endDate);
model.addAttribute("startDate", startDate1);
model.addAttribute("endDate", endDate1);
model.addAttribute("transactions", reportingService.stitchingItemsTransactions( jobCardId, accountId, sku, startDate1.toString(), endDate1.toString() ));
return "/reporting/accounts-transaction-table";
}
private ArrayList<LocalDate> generateDateList(LocalDate start, LocalDate end) { private ArrayList<LocalDate> generateDateList(LocalDate start, LocalDate end) {
ArrayList<LocalDate> localDates = new ArrayList<>(); ArrayList<LocalDate> localDates = new ArrayList<>();
while (start.isBefore(end)) { while (start.isBefore(end)) {

View File

@ -93,13 +93,13 @@ public class StitchingController {
@RequestParam( value = "sku", required = false ) String sku, @RequestParam( value = "sku", required = false ) String sku,
@RequestParam( value = "start-date", required = false) String startDate, @RequestParam( value = "start-date", required = false) String startDate,
@RequestParam( value = "end-date", required = false ) String endDate, @RequestParam( value = "end-date", required = false ) String endDate,
@RequestParam( value = "job-card-id", required = false ) String jobCardId, @RequestParam(value = "bundle-id", required = false) Long bundleId,
@RequestParam( value = "count", required = false, defaultValue = "100") Long count, @RequestParam( value = "count", required = false, defaultValue = "100") Long count,
Model model Model model
,RedirectAttributes redirect){ ,RedirectAttributes redirect){
LocalDate startDate1 = StringUtils.isNullOrEmpty(startDate) ? LocalDate.now().minusDays(30) : LocalDate.parse(startDate); LocalDate startDate1 = StringUtils.isNullOrEmpty(startDate) ? LocalDate.now().minusDays(30) : LocalDate.parse(startDate);
LocalDate endDate1 = StringUtils.isNullOrEmpty(endDate) ? LocalDate.now() : LocalDate.parse(endDate); LocalDate endDate1 = StringUtils.isNullOrEmpty(endDate) ? LocalDate.now() : LocalDate.parse(endDate);
List<StitchingOfflineItem> itemList = bundleService.getStitchedOfflineItems( id, itemId, sku, startDate, endDate, jobCardId ,count ); List<StitchingOfflineItem> itemList = bundleService.getStitchedOfflineItems( id, itemId, sku, startDate, endDate, bundleId ,count );
model.addAttribute("items", itemList ) ; model.addAttribute("items", itemList ) ;
model.addAttribute("startDate", startDate1); model.addAttribute("startDate", startDate1);
model.addAttribute("endDate", endDate1); model.addAttribute("endDate", endDate1);

View File

@ -26,10 +26,12 @@ 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);
private final String SELECT_BY_JOB_CARD_AND_DATE = String.format( "SELECT * FROM %s WHERE job_card_id = :job_card_id AND (:start_date IS NULL OR :end_date IS NULL OR created_at BETWEEN :start_date AND :end_date)", TABLE_NAME );
public BundleDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) { public BundleDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
@ -132,11 +134,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 +147,27 @@ 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());
}
public List<Bundle> findByCardIdAndDATE( long cardId, String startDate, String endDate){
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("job_card_id", cardId );
params.addValue( "start_date", startDate );
params.addValue( "end_date", endDate );
return namedParameterJdbcTemplate.query( SELECT_BY_JOB_CARD_AND_DATE, params, new BundleRowMapper() );
}
} }

View File

@ -32,6 +32,8 @@ 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);
private final String SELECT_BY_JOB_CARD_AND_DATE = String.format( "SELECT * FROM %s WHERE job_card_id = :job_card_id AND (:start_date IS NULL OR :end_date IS NULL OR created_at BETWEEN :start_date AND :end_date)", TABLE_NAME );
public FinishedItemDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) { public FinishedItemDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
@ -168,4 +170,20 @@ 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;
}
public List<FinishedItem> calculateTotalFinishItem( long jobCardId, String startDate, String endDate ){
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("job_card_id", jobCardId );
params.addValue( "start_date", startDate );
params.addValue( "end_date", endDate );
return namedParameterJdbcTemplate.query( SELECT_BY_JOB_CARD_AND_DATE, params, new FinishedItemRowMapper() );
}
} }

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

@ -3,6 +3,7 @@ package com.utopiaindustries.dao.ctp;
import com.utopiaindustries.model.ctp.InventorySummary; import com.utopiaindustries.model.ctp.InventorySummary;
import com.utopiaindustries.model.ctp.InventoryTransactionLeg; import com.utopiaindustries.model.ctp.InventoryTransactionLeg;
import com.utopiaindustries.util.KeyHolderFunctions; import com.utopiaindustries.util.KeyHolderFunctions;
import com.utopiaindustries.util.StringUtils;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.support.GeneratedKeyHolder; import org.springframework.jdbc.support.GeneratedKeyHolder;
@ -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,11 +45,20 @@ 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);
private final String SELECT_JOB_CARD_And_Date_Type_Account_Id = String.format("SELECT * FROM %s WHERE job_card_id = :job_card_id AND (:start_date IS NULL OR :end_date IS NULL OR transaction_leg_datetime BETWEEN :start_date AND :end_date) AND type = :type AND account_id IN (:account_ids)", TABLE_NAME);
public InventoryTransactionLegDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) { public InventoryTransactionLegDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
} }
public List<InventoryTransactionLeg> findByQuery(String query ){
return namedParameterJdbcTemplate.query( query, new InventoryTransactionLegRowMapper() );
}
// prepare query params // prepare query params
private MapSqlParameterSource prepareInsertQueryParams( InventoryTransactionLeg inventoryTransactionLeg ) { private MapSqlParameterSource prepareInsertQueryParams( InventoryTransactionLeg inventoryTransactionLeg ) {
MapSqlParameterSource params = new MapSqlParameterSource(); MapSqlParameterSource params = new MapSqlParameterSource();
@ -63,7 +73,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 +165,57 @@ 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 );
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() );
}
public List<InventoryTransactionLeg> getTransactionByJobCardAndDatesAndTypeAndAccountID(long jobCardID, String startDate, String endDate, String type, List<Integer> accountId){
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("job_card_id", jobCardID );
params.addValue("start_date", startDate );
params.addValue("end_date", endDate );
params.addValue("type", type );
params.addValue("account_ids", accountId );
return namedParameterJdbcTemplate.query( SELECT_JOB_CARD_And_Date_Type_Account_Id , 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

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

View File

@ -1,7 +1,6 @@
package com.utopiaindustries.dao.ctp; package com.utopiaindustries.dao.ctp;
import com.utopiaindustries.model.ctp.JobCardItem; import com.utopiaindustries.model.ctp.JobCardItem;
import com.utopiaindustries.model.ctp.MasterBundle;
import com.utopiaindustries.util.KeyHolderFunctions; import com.utopiaindustries.util.KeyHolderFunctions;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
@ -11,7 +10,6 @@ import org.springframework.stereotype.Repository;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
@Repository @Repository
public class JobCardItemDAO { public class JobCardItemDAO {
@ -24,9 +22,11 @@ public class JobCardItemDAO {
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 SELECT_BY_CARD_ID = String.format( "SELECT * FROM %s WHERE job_card_id = :card_id", TABLE_NAME ); private final String SELECT_BY_CARD_ID = String.format( "SELECT * FROM %s WHERE job_card_id = :card_id", TABLE_NAME );
private final String SELECT_BY_CARD_ID_AND_ITEM_ID = String.format( "SELECT * FROM %s WHERE job_card_id = :card_id AND item_id = :item_id ", TABLE_NAME ); private final String SELECT_BY_CARD_ID_AND_ITEM_ID = String.format( "SELECT * FROM %s WHERE job_card_id = :card_id AND item_id = :item_id ", TABLE_NAME );
private final String INSERT_QUERY = String.format( "INSERT INTO %s (id, job_card_id, item_id, sku, expected_production, actual_production, total_production, account_id, length, width, gsm, wt_ply, ply) VALUES (:id, :job_card_id, :item_id, :sku, :expected_production, :actual_production, :total_production, :account_id, :length, :width, :gsm, :wt_ply, :ply) ON DUPLICATE KEY UPDATE job_card_id = VALUES(job_card_id), item_id = VALUES(item_id), sku = VALUES(sku), expected_production = VALUES(expected_production), actual_production = VALUES(actual_production), total_production = VALUES(total_production), account_id = VALUES(account_id), length = VALUES(length), width = VALUES(width), gsm = VALUES(gsm), wt_ply = VALUES(wt_ply), ply = VALUES(ply) ", TABLE_NAME ); private final String INSERT_QUERY = String.format( "INSERT INTO %s (id, job_card_id, item_id, sku, expected_production, actual_production, total_production, account_id, length, width, gsm, wt_ply, ply, is_complete) VALUES (:id, :job_card_id, :item_id, :sku, :expected_production, :actual_production, :total_production, :account_id, :length, :width, :gsm, :wt_ply, :ply, :is_complete) ON DUPLICATE KEY UPDATE job_card_id = VALUES(job_card_id), item_id = VALUES(item_id), sku = VALUES(sku), expected_production = VALUES(expected_production), actual_production = VALUES(actual_production), total_production = VALUES(total_production), account_id = VALUES(account_id), length = VALUES(length), width = VALUES(width), gsm = VALUES(gsm), wt_ply = VALUES(wt_ply), ply = VALUES(ply), is_complete =VALUES(is_complete) ", 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_JOB_CARD_AND_ACCOUNT_IDS = String.format( "SELECT * FROM %s WHERE job_card_id = :job_card_id AND actual_production = :actual_production AND account_id IN (:account_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 );
public JobCardItemDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) { public JobCardItemDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
@ -47,7 +47,9 @@ public class JobCardItemDAO {
.addValue("width", jobCardItem.getWidth() ) .addValue("width", jobCardItem.getWidth() )
.addValue("gsm", jobCardItem.getGsm() ) .addValue("gsm", jobCardItem.getGsm() )
.addValue("wt_ply", jobCardItem.getWtPly() ) .addValue("wt_ply", jobCardItem.getWtPly() )
.addValue("ply", jobCardItem.getPly() ); .addValue("ply", jobCardItem.getPly() )
.addValue("is_complete", jobCardItem.isComplete() );
return params; return params;
} }
@ -112,12 +114,26 @@ public class JobCardItemDAO {
return namedParameterJdbcTemplate.query( SELECT_BY_IDS, params, new JobCardItemRowMapper() ); return namedParameterJdbcTemplate.query( SELECT_BY_IDS, params, new JobCardItemRowMapper() );
} }
public List<JobCardItem> findByJobCardAndAccountIdsAndIsReceived( Long jobCardId, Long actualProduction, List<Long> accountIds ){ public List<JobCardItem> findByJobCardAndAccountIdsAndIsReceived( Long jobCardId, List<Long> accountIds ){
if( accountIds == null || accountIds.isEmpty() ) return new ArrayList<>(); if( accountIds == null || accountIds.isEmpty() ) return new ArrayList<>();
MapSqlParameterSource params = new MapSqlParameterSource(); MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue( "account_ids", accountIds ); params.addValue( "account_ids", accountIds );
params.addValue("job_card_id", jobCardId ); params.addValue("job_card_id", jobCardId );
params.addValue("actual_production", actualProduction );
return namedParameterJdbcTemplate.query( SELECT_BY_JOB_CARD_AND_ACCOUNT_IDS , params, new JobCardItemRowMapper() ); return namedParameterJdbcTemplate.query( SELECT_BY_JOB_CARD_AND_ACCOUNT_IDS , params, new JobCardItemRowMapper() );
} }
public boolean checkAllItemsComplete( Long jobCardId, List<Long> itemsId ){
if( itemsId == null || itemsId.isEmpty() ) return false;
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue( "id", itemsId );
params.addValue("job_card_id", jobCardId );
Boolean allComplete = namedParameterJdbcTemplate.queryForObject(SELECT_ALL_ACTIVE_ITEM, params, Boolean.class);
return Boolean.TRUE.equals(allComplete);
}
public List<JobCardItem> findByJobCardIds(List<Long> ids){
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("job_card_id", ids);
return namedParameterJdbcTemplate.query( SELECT_BY_JOB_CARD_IDS, params, new JobCardItemRowMapper() );
}
} }

View File

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

View File

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

View File

@ -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,9 @@ 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);
private final String SELECT_BY_JOB_CARD_AND_DATE = String.format( "SELECT * FROM %s WHERE job_card_id = :job_card_id AND (:start_date IS NULL OR :end_date IS NULL OR created_at BETWEEN :start_date AND :end_date)", TABLE_NAME );
public StitchingOfflineItemDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) { public StitchingOfflineItemDAO(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate; this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
@ -141,4 +145,28 @@ 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() );
}
public List<StitchingOfflineItem> findByJobCardIdAndDate(long jobCardId, String startDate, String endDate){
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue( "job_card_id", jobCardId );
params.addValue( "start_date", startDate );
params.addValue( "end_date", endDate );
return namedParameterJdbcTemplate.query( SELECT_BY_JOB_CARD_AND_DATE , params, new StitchingOfflineItemRowMapper() );
}
} }

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

@ -42,7 +42,7 @@ public class ItemDAO {
TABLE_NAME); 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_IDS_AND_ACTIVE = String.format("SELECT * FROM %s WHERE id IN (:ids) AND is_active = 1 ", TABLE_NAME); private final String SELECT_BY_IDS_AND_ACTIVE = String.format("SELECT * FROM %s WHERE id IN (:ids) AND is_active = 1 ", TABLE_NAME);
private final String SELECT_LIKE_TITLE_AND_STATUS_QUERY = String.format("SELECT * FROM %s WHERE is_active = :is_active AND title LIKE :title ORDER BY title ASC limit 100 offset 0", TABLE_NAME); private final String SELECT_LIKE_TITLE_AND_STATUS_QUERY_OR_SKU = String.format("SELECT * FROM %s WHERE is_active = :is_active AND title LIKE :title OR sku LIKE :sku ORDER BY title ASC limit 100 offset 0", TABLE_NAME);
private final String SELECT_LIKE_TITLE_BY_DEPARTMENT_QUERY = private final String SELECT_LIKE_TITLE_BY_DEPARTMENT_QUERY =
String.format("SELECT * FROM %s WHERE department_id = :department_id AND title LIKE :title ORDER BY title ASC", TABLE_NAME); String.format("SELECT * FROM %s WHERE department_id = :department_id AND title LIKE :title ORDER BY title ASC", TABLE_NAME);
private final String SELECT_LIKE_TITLE = String.format("SELECT * FROM %s WHERE title LIKE :item_title", TABLE_NAME); private final String SELECT_LIKE_TITLE = String.format("SELECT * FROM %s WHERE title LIKE :item_title", TABLE_NAME);
@ -232,11 +232,12 @@ public class ItemDAO {
} }
// find all like title (active only) // find all like title (active only)
public List<Item> findLikeTitleAndStatus(String title, boolean active) { public List<Item> findLikeTitleAndStatusORSKU(String title, boolean active) {
MapSqlParameterSource params = new MapSqlParameterSource(); MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("title", "%" + title + "%"); params.addValue("title", "%" + title + "%");
params.addValue("is_active", active); params.addValue("is_active", active);
return namedParameterJdbcTemplate.query(SELECT_LIKE_TITLE_AND_STATUS_QUERY, params, new ItemRowMapper()); params.addValue("sku", "%" + title + "%");
return namedParameterJdbcTemplate.query(SELECT_LIKE_TITLE_AND_STATUS_QUERY_OR_SKU, params, new ItemRowMapper());
} }
// find all like title and department // find all like title and department

View File

@ -0,0 +1,151 @@
package com.utopiaindustries.model.ctp;
public class CuttingJobCardItemWrapper {
private long jobCardId;
private String poName;
private String sku;
private Long total;
private String width;
private String length;
private String gsm;
private String wtPly;
private String ply;
private String articleName;
private boolean isComplete;
private String jobCardCode;
private String operatorName;
private long accountId;
public long getJobCardId() {
return jobCardId;
}
public void setJobCardId(long jobCardId) {
this.jobCardId = jobCardId;
}
public String getPoName() {
return poName;
}
public void setPoName(String poName) {
this.poName = poName;
}
public String getSku() {
return sku;
}
public void setSku(String sku) {
this.sku = sku;
}
public String getWidth() {
return width;
}
public void setWidth(String width) {
this.width = width;
}
public String getGsm() {
return gsm;
}
public void setGsm(String gsm) {
this.gsm = gsm;
}
public String getWtPly() {
return wtPly;
}
public void setWtPly(String wtPly) {
this.wtPly = wtPly;
}
public String getPly() {
return ply;
}
public void setPly(String ply) {
this.ply = ply;
}
public String getArticleName() {
return articleName;
}
public void setArticleName(String articleName) {
this.articleName = articleName;
}
public boolean isComplete() {
return isComplete;
}
public void setComplete(boolean complete) {
isComplete = complete;
}
public String getJobCardCode() {
return jobCardCode;
}
public void setJobCardCode(String jobCardCode) {
this.jobCardCode = jobCardCode;
}
public String getLength() {
return length;
}
public void setLength(String length) {
this.length = length;
}
public String getOperatorName() {
return operatorName;
}
public void setOperatorName(String operatorName) {
this.operatorName = operatorName;
}
public long getAccountId() {
return accountId;
}
public void setAccountId(long accountId) {
this.accountId = accountId;
}
public Long getTotal() {
return total;
}
public void setTotal(Long total) {
this.total = total;
}
@Override
public String toString() {
return "CuttingJobCardItemWrapper{" +
"jobCardId=" + jobCardId +
", poName='" + poName + '\'' +
", sku='" + sku + '\'' +
", total=" + total +
", width='" + width + '\'' +
", length='" + length + '\'' +
", gsm='" + gsm + '\'' +
", wtPly='" + wtPly + '\'' +
", ply='" + ply + '\'' +
", articleName='" + articleName + '\'' +
", isComplete=" + isComplete +
", jobCardCode='" + jobCardCode + '\'' +
", operatorName='" + operatorName + '\'' +
", accountId=" + accountId +
'}';
}
}

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

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

View File

@ -23,6 +23,7 @@ public class JobCardItem {
private List<CutPiece> cutPieces; private List<CutPiece> cutPieces;
private String title; private String title;
private boolean isSelected; private boolean isSelected;
private boolean isComplete;
public JobCardItem() { public JobCardItem() {
this.expectedProduction = BigDecimal.ZERO; this.expectedProduction = BigDecimal.ZERO;
@ -167,6 +168,14 @@ public class JobCardItem {
isSelected = selected; isSelected = selected;
} }
public boolean isComplete() {
return isComplete;
}
public void setComplete(boolean complete) {
isComplete = complete;
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;

View File

@ -9,6 +9,8 @@ public class JobCardItemWrapper {
private long jobCardItemId; private long jobCardItemId;
private List<CutPiece> pieces; private List<CutPiece> pieces;
private BigDecimal actualProduction; private BigDecimal actualProduction;
private int perBundleQuantity;
private boolean cuttingComplete;
public long getJobCardId() { public long getJobCardId() {
return jobCardId; return jobCardId;
@ -42,6 +44,22 @@ public class JobCardItemWrapper {
this.actualProduction = actualProduction; this.actualProduction = actualProduction;
} }
public int getPerBundleQuantity() {
return perBundleQuantity;
}
public void setPerBundleQuantity(int perBundleQuantity) {
this.perBundleQuantity = perBundleQuantity;
}
public boolean getCuttingComplete() {
return cuttingComplete;
}
public void setCuttingComplete(boolean finalReceived) {
this.cuttingComplete = finalReceived;
}
@Override @Override
public String toString() { public String toString() {
return "JobCardItemWrapper{" + return "JobCardItemWrapper{" +

View File

@ -0,0 +1,147 @@
package com.utopiaindustries.model.ctp;
public class POsDetails {
private String poNumber;
private String articleTitle;
private long poQuantity;
private long totalCutting;
private long remainingCutting;
private long totalStitching;
private long remainingStitching;
private long totalEndLineQC;
private long remainingEndLineQC;
private long totalFinishing;
private long remainingFinishing;
private long totalAGradeItem;
private long totalBGradeItem;
private long totalCGradeItem;
public long getPoQuantity() {
return poQuantity;
}
public void setPoQuantity(long poQuantity) {
this.poQuantity = poQuantity;
}
public String getPoNumber() {
return poNumber;
}
public void setPoNumber(String poNumber) {
this.poNumber = poNumber;
}
public String getArticleTitle() {
return articleTitle;
}
public void setArticleTitle(String articleTitle) {
this.articleTitle = articleTitle;
}
public long getTotalCutting() {
return totalCutting;
}
public void setTotalCutting(long totalCutting) {
this.totalCutting = totalCutting;
}
public long getRemainingCutting() {
return remainingCutting;
}
public void setRemainingCutting(long remainingCutting) {
this.remainingCutting = remainingCutting;
}
public long getTotalStitching() {
return totalStitching;
}
public void setTotalStitching(long totalStitching) {
this.totalStitching = totalStitching;
}
public long getRemainingStitching() {
return remainingStitching;
}
public void setRemainingStitching(long remainingStitching) {
this.remainingStitching = remainingStitching;
}
public long getTotalEndLineQC() {
return totalEndLineQC;
}
public void setTotalEndLineQC(long totalEndLineQC) {
this.totalEndLineQC = totalEndLineQC;
}
public long getRemainingEndLineQC() {
return remainingEndLineQC;
}
public void setRemainingEndLineQC(long remainingEndLineQC) {
this.remainingEndLineQC = remainingEndLineQC;
}
public long getTotalFinishing() {
return totalFinishing;
}
public void setTotalFinishing(long totalFinishing) {
this.totalFinishing = totalFinishing;
}
public long getRemainingFinishing() {
return remainingFinishing;
}
public void setRemainingFinishing(long remainingFinishing) {
this.remainingFinishing = remainingFinishing;
}
public long getTotalAGradeItem() {
return totalAGradeItem;
}
public void setTotalAGradeItem(long totalAGradeItem) {
this.totalAGradeItem = totalAGradeItem;
}
public long getTotalBGradeItem() {
return totalBGradeItem;
}
public void setTotalBGradeItem(long totalBGradeItem) {
this.totalBGradeItem = totalBGradeItem;
}
public long getTotalCGradeItem() {
return totalCGradeItem;
}
public void setTotalCGradeItem(long totalCGradeItem) {
this.totalCGradeItem = totalCGradeItem;
}
@Override
public String toString() {
return "POsDetails{" +
"totalCutting=" + totalCutting +
", remainingCutting=" + remainingCutting +
", totalStitching=" + totalStitching +
", remainingStitching=" + remainingStitching +
", totalEndLineQC=" + totalEndLineQC +
", remainingEndLineQC=" + remainingEndLineQC +
", totalFinishing=" + totalFinishing +
", remainingFinishing=" + remainingFinishing +
", totalAGradeItem=" + totalAGradeItem +
", totalBGradeItem=" + totalBGradeItem +
", totalCGradeItem=" + totalCGradeItem +
'}';
}
}

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

@ -8,7 +8,7 @@ import java.time.LocalDate;
public class StichedOfflineItemQueryBuilder { public class StichedOfflineItemQueryBuilder {
public static String buildQuery(String id, String itemId, String sku, String createdStartDate, String createdEndDate, String jobCardId, Long count) { public static String buildQuery(String id, String itemId, String sku, String createdStartDate, String createdEndDate, Long bundleId, Long count) {
// format date // format date
String formattedDate; String formattedDate;
String formattedEndDate; String formattedEndDate;
@ -35,7 +35,7 @@ public class StichedOfflineItemQueryBuilder {
.and() .and()
.columnEquals("item_id", itemId ) .columnEquals("item_id", itemId )
.and() .and()
.columnEquals("job_card_id", jobCardId ) .columnEquals("bundle_id", bundleId )
.and() .and()
.columnEqualToOrGreaterThan("created_at", startDate1) .columnEqualToOrGreaterThan("created_at", startDate1)
.and() .and()

View File

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

View File

@ -31,7 +31,7 @@ public class ItemRestController {
items = itemDAO.findBySkuOrTitleAndTypeIdAndActive(term, Arrays.stream(typeIds).collect(Collectors.toList()), "1" ); items = itemDAO.findBySkuOrTitleAndTypeIdAndActive(term, Arrays.stream(typeIds).collect(Collectors.toList()), "1" );
} else { } else {
// else return all results // else return all results
items = itemDAO.findLikeTitleAndStatus(term, true ); items = itemDAO.findLikeTitleAndStatusORSKU(term, true );
} }
return items; return items;
} }

View File

@ -351,13 +351,18 @@ public class BarcodeService {
PdfFont font = PdfFontFactory.createFont(StandardFonts.COURIER_OBLIQUE); PdfFont font = PdfFontFactory.createFont(StandardFonts.COURIER_OBLIQUE);
String id = String.valueOf(artifact.getId()); String id = String.valueOf(artifact.getId());
float textSize = stickerSize.getTextSize() + 8;
float charWidth = textSize * 0.6f;
float idWidth = id.length() * charWidth;
float xCentered = (labelWidth / 2f) - (idWidth / 2f);
document.add(new Paragraph(id) document.add(new Paragraph(id)
.setFont(font) .setFont(font)
.setBold() .setBold()
.setFontColor(ColorConstants.BLACK) .setFontColor(ColorConstants.BLACK)
.setFontSize(stickerSize.getTextSize() + 8) .setFontSize(textSize)
.setTextAlignment(TextAlignment.LEFT) .setFixedPosition(xCentered, textY + 13, 100));
.setFixedPosition(textX - 25, textY + 13, 100));
float dottedLine = textY - 65; float dottedLine = textY - 65;
for(int i= 0 ;i<16;i++){ for(int i= 0 ;i<16;i++){

View File

@ -125,13 +125,13 @@ public class BundleService {
/* /*
* find finished Items by params * find finished Items by params
* */ * */
public List<StitchingOfflineItem> getStitchedOfflineItems(String id, String itemId, String sku, String createdStartDate, String createdEndDate, String jobCardId, Long count ){ public List<StitchingOfflineItem> getStitchedOfflineItems(String id, String itemId, String sku, String createdStartDate, String createdEndDate, Long bundleId, Long count ){
List<StitchingOfflineItem> stitchingOfflineItems = new ArrayList<>(); List<StitchingOfflineItem> stitchingOfflineItems = new ArrayList<>();
if( count == null ){ if( count == null ){
count = 100L; count = 100L;
} }
if( StringUtils.isAnyNotNullOrEmpty(id, itemId, sku, createdStartDate, createdEndDate, jobCardId ) ){ if( StringUtils.isAnyNotNullOrEmpty(id, itemId, sku, createdStartDate, createdEndDate, String.valueOf(bundleId) ) ){
String query = StichedOfflineItemQueryBuilder.buildQuery( id, itemId, sku, createdStartDate, createdEndDate, jobCardId , count ); String query = StichedOfflineItemQueryBuilder.buildQuery( id, itemId, sku, createdStartDate, createdEndDate, bundleId , count );
System.out.println( query ); System.out.println( query );
stitchingOfflineItems = stitchingOfflineItemDAO.findByQuery( query ); stitchingOfflineItems = stitchingOfflineItemDAO.findByQuery( query );
} else { } else {

View File

@ -73,6 +73,7 @@ public class InventoryService {
.collect( Collectors.toMap( JobCardItemWrapper::getJobCardItemId, JobCardItemWrapper::getActualProduction ) ); .collect( Collectors.toMap( JobCardItemWrapper::getJobCardItemId, JobCardItemWrapper::getActualProduction ) );
List<JobCardItem> items = jobCardItemDAO.findByIds( jobCardItemWrapperIds ); List<JobCardItem> items = jobCardItemDAO.findByIds( jobCardItemWrapperIds );
if ( items != null && !items.isEmpty( ) ) { if ( items != null && !items.isEmpty( ) ) {
// get job card item ids // get job card item ids
List<Long> jobCardItemIds = items.stream( ) List<Long> jobCardItemIds = items.stream( )
@ -90,16 +91,38 @@ public class InventoryService {
.collect( Collectors.groupingBy( CutPiece::getJobCardItemId)); .collect( Collectors.groupingBy( CutPiece::getJobCardItemId));
for ( JobCardItem jobCardItem : items) { for ( JobCardItem jobCardItem : items) {
// create + save bundles
List<Bundle> bundles = createBundles( jobCardItem, piecesMap.get( jobCardItem.getId( ) ),jobCardItemIdToActualProdMap.getOrDefault( jobCardItem.getId( ) , BigDecimal.ZERO ) ); int quantity = jobCardItemWrappers.stream()
.filter(e -> e.getJobCardItemId() == jobCardItem.getId())
.mapToInt(JobCardItemWrapper::getPerBundleQuantity)
.findFirst()
.orElse(0);
boolean cuttingComplete = jobCardItemWrappers.stream()
.filter(e -> e.getJobCardItemId() == jobCardItem.getId())
.map(JobCardItemWrapper::getCuttingComplete)
.findFirst()
.orElse(false);
BigDecimal production = jobCardItemWrappers.stream()
.filter(e -> e.getJobCardItemId() == jobCardItem.getId())
.map(JobCardItemWrapper::getActualProduction)
.findFirst()
.orElse(BigDecimal.ZERO);
List<Bundle> bundles = createBundles( jobCardItem,quantity,jobCardItemIdToActualProdMap.getOrDefault( jobCardItem.getId( ) , BigDecimal.ZERO ) );
// create transactions // create transactions
createTransactions( bundles, jobCardItem.getAccountId( ), InventoryArtifactType.BUNDLE.name( )); createTransactions( bundles, jobCardItem.getAccountId( ), InventoryArtifactType.BUNDLE.name( ));
jobCardItem.setActualProduction( jobCardItemIdToActualProdMap.getOrDefault( jobCardItem.getId( ) , BigDecimal.ZERO ) ); jobCardItem.setActualProduction( jobCardItemIdToActualProdMap.getOrDefault( jobCardItem.getId( ), BigDecimal.ZERO ).add(jobCardItem.getActualProduction()) );
jobCardItem.setComplete(cuttingComplete);
} }
// update items with quantity // update items with quantity
jobCardItemDAO.saveAll( items ); jobCardItemDAO.saveAll( items );
// update job card inv status // update job card inv status
updateJobCardInventoryStatus( jobCard ); if(jobCardItemDAO.checkAllItemsComplete(jobCardId,jobCardItemIds)) {
updateJobCardInventoryStatus(jobCard);
}
} else { } else {
throw new RuntimeException( "Items Not found in Job Card"); throw new RuntimeException( "Items Not found in Job Card");
} }
@ -151,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( ));
@ -182,29 +206,12 @@ public class InventoryService {
// create bundles from cut pieces // create bundles from cut pieces
private List<Bundle> createBundles( JobCardItem jobCardItem, private List<Bundle> createBundles( JobCardItem jobCardItem,
List<CutPiece> jobCardItemPieces, BigDecimal value ) { int perBundleWrap, BigDecimal value ) {
Authentication authentication = SecurityContextHolder.getContext( ).getAuthentication( ); Authentication authentication = SecurityContextHolder.getContext( ).getAuthentication( );
if ( value != null && !value.equals(BigDecimal.ZERO)) { if ( value != null && !value.equals(BigDecimal.ZERO)) {
List<Bundle> bundles = new ArrayList<>( ); List<Bundle> bundles = new ArrayList<>( );
// create bundle against every cut piece
if(value.intValue()<=20){
Bundle bundle = new Bundle( );
bundle.setItemId( jobCardItem.getItemId( ));
bundle.setSku( jobCardItem.getSku( ));
bundle.setJobCardId( jobCardItem.getJobCardId( ) );
bundle.setWrapQuantity(value);
bundle.setType( "BUNDLE");
bundle.setCreatedAt( LocalDateTime.now( ));
bundle.setCreatedBy( authentication.getName( ));
bundles.add( bundle);
bundle.setId( bundleDAO.save( bundle));
bundle.setBarcode( cryptographyService.generateRandomString( 15));
// save again after barcode generation
bundle.setId( bundleDAO.save( bundle));
}else{
int quantity = value.intValue(); int quantity = value.intValue();
int batchSize = 20; int batchSize = perBundleWrap;
int iterations = (int) Math.ceil((double) quantity / batchSize); int iterations = (int) Math.ceil((double) quantity / batchSize);
for (int i = 0; i < iterations; i++) { for (int i = 0; i < iterations; i++) {
@ -225,8 +232,6 @@ public class InventoryService {
// save again after barcode generation // save again after barcode generation
bundle.setId( bundleDAO.save( bundle)); bundle.setId( bundleDAO.save( bundle));
} }
}
// for ( Map.Entry<JobCardItem, List<CutPiece>> entry : jobCardItemPieces ) { // for ( Map.Entry<JobCardItem, List<CutPiece>> entry : jobCardItemPieces ) {
// JobCardItem key = entry.getKey( ); // JobCardItem key = entry.getKey( );
// List<CutPiece> value = entry.getValue( ); // List<CutPiece> value = entry.getValue( );
@ -342,12 +347,13 @@ public class InventoryService {
.collect(Collectors.toMap(InventoryTransactionLeg::getParentDocumentId, Function.identity())); .collect(Collectors.toMap(InventoryTransactionLeg::getParentDocumentId, Function.identity()));
for (Bundle subBundle : wrapper.getBundles()) { for (Bundle subBundle : wrapper.getBundles()) {
long accountId = masterBundleDAO.find(subBundle.getMasterBundleId()).getAccountId(); long accountId = masterBundleDAO.find(subBundle.getMasterBundleId()).getAccountId();
if(subBundle.getCurrentProduction().compareTo(BigDecimal.ZERO) != 0){ if(subBundle.getCurrentProduction() != null && subBundle.getCurrentProduction().compareTo(BigDecimal.ZERO) != 0){
Bundle bundle = bundleDAO.find(subBundle.getId()); Bundle bundle = bundleDAO.find(subBundle.getId());
jobCard = jobCardDAO.find(subBundle.getJobCardId()); jobCard = jobCardDAO.find(subBundle.getJobCardId());
long production = (bundle.getProduction() == null) ? 0 : bundle.getProduction().longValue() ; long production = (bundle.getProduction() == null) ? 0 : bundle.getProduction().longValue() ;
long wrapQuantity = bundle.getWrapQuantity().longValue(); long wrapQuantity = bundle.getWrapQuantity().longValue();
JobCardItem jobCardItem = jobCardItemDAO.findByCardIdAndItemId(subBundle.getJobCardId(),subBundle.getItemId()); JobCardItem jobCardItem = jobCardItemDAO.findByCardIdAndItemId(subBundle.getJobCardId(),subBundle.getItemId());
BigDecimal previousTotalProduction = jobCardItem.getTotalProduction() == null ? BigDecimal.ZERO : jobCardItem.getTotalProduction();
InventoryTransactionLeg lastInvTransaction = lastBundleIdInTransactionMap.getOrDefault(subBundle.getId(), null); InventoryTransactionLeg lastInvTransaction = lastBundleIdInTransactionMap.getOrDefault(subBundle.getId(), null);
@ -363,10 +369,10 @@ public class InventoryService {
// create IN Transactions of Finished Items into account // create IN Transactions of Finished Items into account
createTransactions(stitchingOfflineItems, accountId, InventoryArtifactType.STITCHING_OFFLINE.name()); createTransactions(stitchingOfflineItems, accountId, InventoryArtifactType.STITCHING_OFFLINE.name());
jobCardItem.setTotalProduction(jobCardItem.getTotalProduction().add(subBundle.getCurrentProduction())); jobCardItem.setTotalProduction(previousTotalProduction.add(subBundle.getCurrentProduction()));
jobCardItem.setJobCardId(jobCard.getId()); jobCardItem.setJobCardId(jobCard.getId());
updatedItems.add(jobCardItem); updatedItems.add(jobCardItem);
BigDecimal pro = subBundle.getCurrentProduction(); BigDecimal pro = BigDecimal.valueOf(production + subBundle.getCurrentProduction().longValue());
bundle.setProduction(pro); bundle.setProduction(pro);
bundleDAO.save(bundle); bundleDAO.save(bundle);
} }

View File

@ -7,14 +7,21 @@ import com.utopiaindustries.dao.uind.PurchaseOrderDAO;
import com.utopiaindustries.model.ctp.*; import com.utopiaindustries.model.ctp.*;
import com.utopiaindustries.model.uind.Item; import com.utopiaindustries.model.uind.Item;
import com.utopiaindustries.querybuilder.ctp.JobCardQueryBuilder; import com.utopiaindustries.querybuilder.ctp.JobCardQueryBuilder;
import com.utopiaindustries.util.HTMLBuilder;
import com.utopiaindustries.util.PDFResponseEntityInputStreamResource;
import com.utopiaindustries.util.StringUtils; import com.utopiaindustries.util.StringUtils;
import com.utopiaindustries.util.URLUtils;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -36,8 +43,10 @@ public class JobCardService {
private final FinishedItemDAO finishedItemDAO; private final FinishedItemDAO finishedItemDAO;
private final StitchingOfflineItemDAO stitchingOfflineItemDAO; private final StitchingOfflineItemDAO stitchingOfflineItemDAO;
private final SkuCutPiecesDAO skuCutPiecesDAO; private final SkuCutPiecesDAO skuCutPiecesDAO;
private final HTMLBuilder htmlBuilder;
private PDFResponseEntityInputStreamResource pdfGenerator;
public JobCardService(JobCardDAO jobCardDAO, CutPieceTypeDAO cutPieceTypeDAO, JobCardItemDAO jobCardItemDAO, CutPieceDAO cutPieceDAO, ItemDAO itemDAO, LocationSiteDAO locationSiteDAO, PurchaseOrderDAO purchaseOrderDAO, UserInventoryAccountDAO userInventoryAccountDAO, FinishedItemDAO finishedItemDAO, StitchingOfflineItemDAO stitchingOfflineItemDAO, SkuCutPiecesDAO skuCutPiecesDAO) { public JobCardService(JobCardDAO jobCardDAO, CutPieceTypeDAO cutPieceTypeDAO, JobCardItemDAO jobCardItemDAO, CutPieceDAO cutPieceDAO, ItemDAO itemDAO, LocationSiteDAO locationSiteDAO, PurchaseOrderDAO purchaseOrderDAO, UserInventoryAccountDAO userInventoryAccountDAO, FinishedItemDAO finishedItemDAO, StitchingOfflineItemDAO stitchingOfflineItemDAO, SkuCutPiecesDAO skuCutPiecesDAO, HTMLBuilder htmlBuilder, PDFResponseEntityInputStreamResource pdfGenerator) {
this.skuCutPiecesDAO = skuCutPiecesDAO; this.skuCutPiecesDAO = skuCutPiecesDAO;
this.jobCardDAO = jobCardDAO; this.jobCardDAO = jobCardDAO;
this.cutPieceTypeDAO = cutPieceTypeDAO; this.cutPieceTypeDAO = cutPieceTypeDAO;
@ -49,6 +58,8 @@ public class JobCardService {
this.userInventoryAccountDAO = userInventoryAccountDAO; this.userInventoryAccountDAO = userInventoryAccountDAO;
this.finishedItemDAO = finishedItemDAO; this.finishedItemDAO = finishedItemDAO;
this.stitchingOfflineItemDAO = stitchingOfflineItemDAO; this.stitchingOfflineItemDAO = stitchingOfflineItemDAO;
this.htmlBuilder = htmlBuilder;
this.pdfGenerator = pdfGenerator;
} }
/* /*
@ -184,7 +195,7 @@ public class JobCardService {
.collect( Collectors.toList() ); .collect( Collectors.toList() );
// get items has account ids and has actual production not filled // get items has account ids and has actual production not filled
List<JobCardItem> items = jobCardItemDAO.findByJobCardAndAccountIdsAndIsReceived( id, 0L ,accountIds ); List<JobCardItem> items = jobCardItemDAO.findByJobCardAndAccountIdsAndIsReceived( id ,accountIds );
if (items != null && !items.isEmpty()) { if (items != null && !items.isEmpty()) {
// get job card ite ids // get job card ite ids
List<Long> jobCardItemIds = items.stream() List<Long> jobCardItemIds = items.stream()
@ -300,4 +311,29 @@ public class JobCardService {
public Map<Long, Long> totalFinishItem(List<Long> itemIds, long jobCardId ){ public Map<Long, Long> totalFinishItem(List<Long> itemIds, long jobCardId ){
return finishedItemDAO.findTotalFinishedItems( itemIds, jobCardId ); return finishedItemDAO.findTotalFinishedItems( itemIds, jobCardId );
} }
/**
* Print Job card *
* **/
public ResponseEntity<InputStreamResource> getJobCardReceivingPdf(long id, Model model ) throws Exception {
List<JobCardItem> jobCardItems = findJobCardItemByJobCardId(id);
List<Long> jobCardItemIds = jobCardItems.stream()
.map(JobCardItem::getItemId)
.collect(Collectors.toList());
List<Long> itemIds = jobCardItems.stream()
.map(JobCardItem::getId)
.collect(Collectors.toList());
model.addAttribute( "baseUrl", URLUtils.getCurrentBaseUrl() );
model.addAttribute( "card", findByID(id));
model.addAttribute("jobCardItems", jobCardItems);
model.addAttribute("cutPiece", findCutPieceByJobCardItemIds(itemIds));
model.addAttribute("totalFinishItem", totalFinishItem(jobCardItemIds, id));
model.addAttribute("totalStitchingItem", totalStitchingItem(jobCardItemIds, id));
// html str
String htmlStr = htmlBuilder.buildHTML( "job-card-view-pdf", model );
// return pdf
return pdfGenerator.generatePdf( htmlStr, "Job-Card", "inline" );
}
} }

View File

@ -0,0 +1,837 @@
package com.utopiaindustries.service;
import com.utopiaindustries.dao.ctp.*;
import com.utopiaindustries.model.ctp.*;
import com.utopiaindustries.querybuilder.ctp.SummaryInventoryReportQueryBuilder;
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 ProcessDAO processDAO;
private final BundleDAO bundleDAO;
private final InventoryTransactionLegDAO inventoryTransactionLegDAO;
private final InventoryTransactionDAO inventoryTransactionDAO;
private final JobCardDAO jobCardDAO;
private final CryptographyService cryptographyService;
private final MasterBundleDAO masterBundleDAO;
private final FinishedItemDAO finishedItemDAO;
private final StitchingOfflineItemDAO stitchingOfflineItemDAO;
private final InventoryAccountDAO inventoryAccountDAO;
public ReportingService( JobCardItemDAO jobCardItemDAO, ProcessDAO processDAO, BundleDAO bundleDAO, InventoryTransactionLegDAO inventoryTransactionLegDAO, InventoryTransactionDAO inventoryTransactionDAO, JobCardDAO jobCardDAO, CryptographyService cryptographyService, MasterBundleDAO masterBundleDAO, FinishedItemDAO finishedItemDAO, StitchingOfflineItemDAO stitchingOfflineItemDAO, InventoryAccountDAO inventoryAccountDAO) {
this.jobCardItemDAO = jobCardItemDAO;
this.processDAO = processDAO;
this.bundleDAO = bundleDAO;
this.inventoryTransactionLegDAO = inventoryTransactionLegDAO;
this.inventoryTransactionDAO = inventoryTransactionDAO;
this.jobCardDAO = jobCardDAO;
this.cryptographyService = cryptographyService;
this.masterBundleDAO = masterBundleDAO;
this.finishedItemDAO = finishedItemDAO;
this.stitchingOfflineItemDAO = stitchingOfflineItemDAO;
this.inventoryAccountDAO = inventoryAccountDAO;
}
public Map<String, Integer> getJobCardProgress(String jobCardID) {
if (jobCardID == null) {
return new LinkedHashMap<>();
} else {
Map<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);
// Cutting Progress Calculation
if (actualProduction.compareTo(BigDecimal.ZERO) == 0) {
totalProgress.put("Cutting Progress", 0);
} else if (actualProduction.compareTo(expectedProduction) < 0) {
BigDecimal cuttingProgress = actualProduction
.divide(expectedProduction, 4, RoundingMode.HALF_UP)
.multiply(BigDecimal.valueOf(100));
totalProgress.put("Cutting Progress", cuttingProgress.intValue());
} else {
totalProgress.put("Cutting Progress", 100);
}
// Stitching Progress Calculation
if (totalProduction.compareTo(BigDecimal.ZERO) == 0) {
totalProgress.put("Stitching Progress", 0);
} else {
BigDecimal stitchingProgress = totalProduction
.divide(actualProduction, 4, RoundingMode.HALF_UP)
.multiply(BigDecimal.valueOf(100));
totalProgress.put("Stitching Progress", stitchingProgress.intValue());
}
// QA Progress Calculation
Long qaProgressItems = stitchingOfflineItemDAO.CalculateTotalQA(Long.parseLong(jobCardID));
if (qaProgressItems == 0) {
totalProgress.put("QA Progress", 0);
} else {
BigDecimal qaProgress = BigDecimal.valueOf(qaProgressItems)
.divide(actualProduction, 4, RoundingMode.HALF_UP)
.multiply(BigDecimal.valueOf(100));
totalProgress.put("QA Progress", qaProgress.intValue());
}
// Finishing Progress Calculation
Long totalFinishItem = finishedItemDAO.calculateTotalFinishItem(Long.parseLong(jobCardID));
if (totalFinishItem == 0) {
totalProgress.put("Finishing Progress", 0);
} else {
BigDecimal finishItemProgress = BigDecimal.valueOf(totalFinishItem)
.divide(actualProduction, 4, RoundingMode.HALF_UP)
.multiply(BigDecimal.valueOf(100));
totalProgress.put("Finishing Progress", finishItemProgress.intValue());
}
// Job Card Progress Calculation
if (totalProduction.compareTo(BigDecimal.ZERO) == 0 && actualProduction.compareTo(BigDecimal.ZERO) == 0) {
totalProgress.put("Job Card Progress", 0);
} else {
BigDecimal progressPercentage;
if (actualProduction.compareTo(expectedProduction) > 0) {
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));
} else {
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());
}
// Sorting Map based on Custom Order
Map<String, Integer> indexMap = new HashMap<>();
indexMap.put("Cutting Progress", 1);
indexMap.put("Stitching Progress", 2);
indexMap.put("QA Progress", 3);
indexMap.put("Finishing Progress", 4);
indexMap.put("Job Card Progress", 5);
return totalProgress.entrySet()
.stream()
.sorted(Comparator.comparingInt(entry -> indexMap.get(entry.getKey())))
.collect(LinkedHashMap::new, (m, v) -> m.put(v.getKey(), v.getValue()), Map::putAll);
}
}
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 LinkedHashMap<>();
} 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);
Long qaProgressItems = stitchingOfflineItemDAO.CalculateTotalQA(Long.parseLong(jobCardID));
Long totalFinishItem = finishedItemDAO.calculateTotalFinishItem(Long.parseLong(jobCardID));
// Get Job card Complete Items
Map<String, Integer> jobCardCompleteItems = getSegregateItems(jobCardID);
Integer segregateTotalItems = jobCardCompleteItems.values().stream().mapToInt(Integer::intValue).sum();
// Add values to totalProgress map
totalProgress.put("Cutting Progress", actualProduction.intValue());
totalProgress.put("Stitching Progress", totalProduction.intValue());
totalProgress.put("QA Progress", qaProgressItems.intValue());
totalProgress.put("Finishing Progress", totalFinishItem.intValue());
totalProgress.put("Job Card Progress", segregateTotalItems);
//custom order
Map<String, Integer> indexMap = new HashMap<>();
indexMap.put("Job Card Progress", 1);
indexMap.put("Cutting Progress", 2);
indexMap.put("Stitching Progress", 3);
indexMap.put("Finishing Progress", 4);
indexMap.put("QA Progress", 5);
// Sort the keys based on custom order
return totalProgress.entrySet()
.stream()
.sorted(Comparator.comparingInt(entry -> indexMap.get(entry.getKey())))
.collect(LinkedHashMap::new, (m, v) -> m.put(v.getKey(), v.getValue()), Map::putAll);
}
}
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()){
gradingItems.put("A GRADE",0);
gradingItems.put("B GRADE",0);
gradingItems.put("C GRADE",0);
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;
}
public List<POsDetails> getAllPOs(String poName) {
List<POsDetails> pOsDetailsList = new ArrayList<>();
List<JobCard> jobCards = jobCardDAO.findAll() ;
HashMap<String, List<JobCard>> filterJobCardsByPos;
if(poName != null && !poName.isEmpty()) {
filterJobCardsByPos = jobCards.stream()
.filter(jobCard -> jobCard.getPurchaseOrderId().equals(poName))
.collect(Collectors.groupingBy(
JobCard::getPurchaseOrderId,
HashMap::new,
Collectors.toList()
));
}else {
filterJobCardsByPos = jobCards.stream()
.collect(Collectors.groupingBy(
JobCard::getPurchaseOrderId,
HashMap::new,
Collectors.toList()
));
}
Map<String,Integer> jobCardCompleteItems = new HashMap<>();
for (String pos : filterJobCardsByPos.keySet()) {
BigDecimal totalProduction = BigDecimal.ZERO;
BigDecimal actualProduction = BigDecimal.ZERO;
int poQuantity = 0;
String articleName = "";
Long qaProgressItems = 0L;
Long totalFinishItem = 0L;
POsDetails pOsDetails = new POsDetails();
for (JobCard jobCard : filterJobCardsByPos.get(pos)) {
List<JobCardItem> jobCardItems = jobCardItemDAO.findByCardId(jobCard.getId());
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));
poQuantity = jobCard.getPoQuantity();
articleName = jobCard.getArticleName();
qaProgressItems += Optional.ofNullable(stitchingOfflineItemDAO.CalculateTotalQA(jobCard.getId())).orElse(0L);
totalFinishItem += Optional.ofNullable(finishedItemDAO.calculateTotalFinishItem(jobCard.getId())).orElse(0L);
jobCardCompleteItems = getSegregateItems(String.valueOf(jobCard.getId()));
if (jobCardCompleteItems == null) {
jobCardCompleteItems = new HashMap<>();
}
}
pOsDetails.setPoNumber(pos);
pOsDetails.setArticleTitle(articleName);
pOsDetails.setPoQuantity(poQuantity);
pOsDetails.setTotalCutting(actualProduction.intValue());
pOsDetails.setTotalStitching(totalProduction.intValue());
pOsDetails.setTotalEndLineQC(qaProgressItems.intValue());
pOsDetails.setTotalFinishing(totalFinishItem);
pOsDetails.setRemainingCutting(poQuantity - actualProduction.intValue());
pOsDetails.setRemainingStitching(poQuantity - totalProduction.intValue());
pOsDetails.setRemainingEndLineQC(poQuantity - qaProgressItems);
pOsDetails.setRemainingFinishing(poQuantity - totalFinishItem);
pOsDetails.setTotalAGradeItem(jobCardCompleteItems.getOrDefault("A GRADE", 0));
pOsDetails.setTotalBGradeItem(jobCardCompleteItems.getOrDefault("B GRADE", 0));
pOsDetails.setTotalCGradeItem(jobCardCompleteItems.getOrDefault("C GRADE", 0));
pOsDetailsList.add(pOsDetails);
}
return pOsDetailsList;
}
public HashMap<String, Map<String, Integer>> getAllPoJobCards(String PONumber, String selectDate) {
String startDate = selectDate != null && !selectDate.isEmpty() ? selectDate + " 00:00:01": null;
String endDate = selectDate != null && !selectDate.isEmpty() ? selectDate + " 23:59:59": null;
HashMap<String, Map<String, Integer>> poJobCardItemsProgress = new HashMap<>();
List<JobCard> jobCards = jobCardDAO.findAll();
// Filter JobCards by Purchase Order ID
List<JobCard> filterJobCardsByPos = jobCards.stream()
.filter(e -> e.getPurchaseOrderId().equals(PONumber))
.collect(Collectors.toList());
List<InventoryAccount> inventoryAccounts = inventoryAccountDAO.getPackagingAccounts();
List<Integer> gradingAccounts = inventoryAccounts.stream().map(e-> (int)(e.getId())).collect(Collectors.toList());
for (JobCard jobCard : filterJobCardsByPos) {
List<Bundle> bundles = bundleDAO.findByCardIdAndDATE(jobCard.getId(),startDate,endDate);
List<StitchingOfflineItem> stitchingOfflineItems = stitchingOfflineItemDAO.findByJobCardIdAndDate(jobCard.getId(),startDate,endDate);
List<FinishedItem> finishedItems = finishedItemDAO.calculateTotalFinishItem(jobCard.getId(),startDate,endDate);
List<InventoryTransactionLeg> inventoryTransactionLegs = inventoryTransactionLegDAO.getTransactionByJobCardAndDatesAndTypeAndAccountID(jobCard.getId(),startDate,endDate,"IN", gradingAccounts);
//cutting days wise
BigDecimal cutting = bundles.stream()
.map(bundle -> Optional.ofNullable(bundle.getWrapQuantity()).orElse(BigDecimal.ZERO))
.reduce(BigDecimal.ZERO, BigDecimal::add);
//stitching day wise
Integer stitching = stitchingOfflineItems.size();
//total qa
Integer qa = finishedItems.size();
Map<String, Integer> segregateItems = inventoryTransactionLegs.stream()
.filter(leg -> inventoryAccounts.stream()
.anyMatch(account -> (int) account.getId() == (leg.getAccountId())))
.collect(Collectors.toMap(
leg -> inventoryAccounts.stream()
.filter(account -> (int) account.getId() == (leg.getAccountId()))
.findFirst()
.map(InventoryAccount::getTitle)
.orElse("Unknown"),
leg -> leg.getQuantity().intValue(),
Integer::sum,
HashMap::new
));
Map<String, Integer> items = getCompleteProduction(String.valueOf(jobCard.getId()));
items.put("Cutting Progress",cutting.intValue());
items.put("Stitching Progress",stitching);
items.put("QA Progress",qa);
items.put("A Grade",segregateItems.get("A GRADE") != null ? segregateItems.get("A GRADE") : 0);
items.put("B Grade",segregateItems.get("B GRADE") != null ? segregateItems.get("B GRADE") : 0);
items.put("C Grade",segregateItems.get("C GRADE") != null ? segregateItems.get("C GRADE") : 0);
// Define sorting order
Map<String, Integer> indexMap = new HashMap<>();
indexMap.put("Job Card Progress", 1);
indexMap.put("Cutting Progress", 2);
indexMap.put("Stitching Progress", 3);
indexMap.put("QA Progress", 4);
indexMap.put("Finishing Progress", 5);
indexMap.put("A GRADE", 6);
indexMap.put("B GRADE", 7);
indexMap.put("C GRADE", 8);
// Sort items based on indexMap order
Map<String, Integer> sortedItems = items.entrySet()
.stream()
.sorted(Comparator.comparingInt(entry -> indexMap.getOrDefault(entry.getKey(), Integer.MAX_VALUE)))
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(oldValue, newValue) -> oldValue,
LinkedHashMap::new
));
// Add sorted items to the result map
poJobCardItemsProgress.put(jobCard.getCode(), sortedItems);
}
return poJobCardItemsProgress;
}
public Map<String, Object> getCuttingTableDetails(String jobCardId, String cuttingTableId, String startDate, String endDate) {
Map<String, Object> cuttingDetails = new HashMap<>();
long jobCardIdTemp = 0L;
String startDate1 = null;
String endDate1 = null;
if (!StringUtils.isNullOrEmpty(startDate)) {
String formattedStart = CTPDateTimeFormat.getMySQLFormattedDateString(startDate, CTPDateTimeFormat.HTML5_DATE_INPUT_FORMAT);
String formattedEnd = !StringUtils.isNullOrEmpty(endDate)
? CTPDateTimeFormat.getMySQLFormattedDateString(endDate, CTPDateTimeFormat.HTML5_DATE_INPUT_FORMAT)
: LocalDate.now().toString();
startDate1 = String.format("'%s 00:00:01'", formattedStart);
endDate1 = String.format("'%s 23:59:59'", formattedEnd);
}
List<InventoryAccount> inventoryAccounts = inventoryAccountDAO.findByParentEntityTypeAndParentId("PROCESS", 1L);
List<Long> inventoryAccountIds = inventoryAccounts.stream().map(InventoryAccount::getId).collect(Collectors.toList());
if (!StringUtils.isNullOrEmpty(jobCardId)) {
jobCardIdTemp = Long.parseLong(jobCardId);
} else if (!StringUtils.isNullOrEmpty(cuttingTableId)) {
inventoryAccountIds = List.of(Long.parseLong(cuttingTableId));
}
String query = SummaryInventoryReportQueryBuilder.cuttingQueryBuild(jobCardIdTemp, inventoryAccountIds, null, startDate1, endDate1, "IN","BUNDLE");
List<InventoryTransactionLeg> inventoryTransactionLegs = inventoryTransactionLegDAO.findByQuery(query);
Map<String, Integer> dateWiseProduction = new TreeMap<>();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
Map<LocalDate, List<Long>> dateWiseJobCardIds = inventoryTransactionLegs.stream()
.filter(e -> e.getTransactionLegDateTime() != null && e.getJobCardId() != 0)
.collect(Collectors.groupingBy(
e -> e.getTransactionLegDateTime().toLocalDate(),
Collectors.mapping(InventoryTransactionLeg::getJobCardId, Collectors.toList())
));
for (Map.Entry<LocalDate, List<Long>> entry : dateWiseJobCardIds.entrySet()) {
List<Long> jobCardIds = entry.getValue();
if (!jobCardIds.isEmpty()) {
List<JobCardItem> jobCardItems = jobCardItemDAO.findByJobCardIds(jobCardIds);
int totalProduction = jobCardItems.stream()
.filter(item -> item.getActualProduction() != null)
.mapToInt(item -> item.getActualProduction().intValue())
.sum();
dateWiseProduction.put(entry.getKey().format(formatter), totalProduction);
}
}
List<Long> distinctJobCardIds = inventoryTransactionLegs.stream()
.map(InventoryTransactionLeg::getJobCardId)
.filter(id -> id != 0)
.distinct()
.collect(Collectors.toList());
Map<Long, List<CuttingJobCardItemWrapper>> jobCardItemsCuttingDetailsMap = new HashMap<>();
for (long jobCardIdEntry : distinctJobCardIds) {
Long accountId = inventoryTransactionLegs.stream()
.filter(e -> e.getJobCardId() == jobCardIdEntry)
.map(e -> e.getAccountId().longValue())
.findFirst()
.orElse(0L);
JobCard jobCard = jobCardDAO.find(jobCardIdEntry);
Bundle bundle = bundleDAO.findByCardId(jobCardIdEntry).stream().findFirst().orElse(new Bundle());
List<JobCardItem> jobCardItems = jobCardItemDAO.findByCardId(jobCardIdEntry);
List<CuttingJobCardItemWrapper> wrappers = jobCardItems.stream().map(item -> {
CuttingJobCardItemWrapper wrapper = new CuttingJobCardItemWrapper();
wrapper.setArticleName(jobCard.getArticleName());
wrapper.setJobCardCode(jobCard.getCode());
wrapper.setGsm(item.getGsm());
wrapper.setPly(item.getPly());
wrapper.setSku(item.getSku());
wrapper.setTotal(item.getActualProduction().longValue());
wrapper.setWidth(item.getWidth());
wrapper.setWtPly(item.getWtPly());
wrapper.setComplete(item.isComplete());
wrapper.setPoName(jobCard.getPurchaseOrderId());
wrapper.setOperatorName(bundle.getCreatedBy());
wrapper.setJobCardId(item.getJobCardId());
wrapper.setLength(item.getLength());
wrapper.setAccountId(accountId);
return wrapper;
}).collect(Collectors.toList());
jobCardItemsCuttingDetailsMap.computeIfAbsent(accountId, k -> new ArrayList<>()).addAll(wrappers);
}
cuttingDetails.put("Date Wise Cutting", dateWiseProduction);
cuttingDetails.put("accountWiseCutting", jobCardItemsCuttingDetailsMap);
cuttingDetails.put("cuttingAccount", inventoryAccounts);
return cuttingDetails;
}
public Map<String, Object> getStitchingDetails(String jobCardId, String stitchingLine, String startDate, String endDate) {
Map<String, Object> stitchingDetails = new HashMap<>();
long jobCardIdTemp = 0L;
String startDate1 = null;
String endDate1 = null;
if (!StringUtils.isNullOrEmpty(startDate)) {
String formattedStart = CTPDateTimeFormat.getMySQLFormattedDateString(startDate, CTPDateTimeFormat.HTML5_DATE_INPUT_FORMAT);
String formattedEnd = !StringUtils.isNullOrEmpty(endDate)
? CTPDateTimeFormat.getMySQLFormattedDateString(endDate, CTPDateTimeFormat.HTML5_DATE_INPUT_FORMAT)
: LocalDate.now().toString();
startDate1 = String.format("'%s 00:00:01'", formattedStart);
endDate1 = String.format("'%s 23:59:59'", formattedEnd);
}
List<InventoryAccount> inventoryAccounts = inventoryAccountDAO.findByParentEntityTypeAndParentId("PROCESS", 2L);
List<Long> inventoryAccountIds = inventoryAccounts.stream().map(InventoryAccount::getId).collect(Collectors.toList());
if (!StringUtils.isNullOrEmpty(jobCardId)) {
jobCardIdTemp = Long.parseLong(jobCardId);
} else if (!StringUtils.isNullOrEmpty(stitchingLine)) {
inventoryAccountIds = List.of(Long.parseLong(stitchingLine));
}
String query = SummaryInventoryReportQueryBuilder.cuttingQueryBuild(jobCardIdTemp, inventoryAccountIds,null, startDate1, endDate1, "IN","STITCHING_OFFLINE");
List<InventoryTransactionLeg> inventoryTransactionLegs = inventoryTransactionLegDAO.findByQuery(query);
Map<String, Integer> dateWiseProduction = new TreeMap<>();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
Map<LocalDate, List<Long>> dateWiseJobCardIds = inventoryTransactionLegs.stream()
.filter(e -> e.getTransactionLegDateTime() != null && e.getJobCardId() != 0)
.collect(Collectors.groupingBy(
e -> e.getTransactionLegDateTime().toLocalDate(),
Collectors.mapping(InventoryTransactionLeg::getJobCardId, Collectors.toList())
));
for (Map.Entry<LocalDate, List<Long>> entry : dateWiseJobCardIds.entrySet()) {
LocalDate date = entry.getKey();
List<Long> jobCardIds = entry.getValue();
if (!jobCardIds.isEmpty()) {
int totalProduction = inventoryTransactionLegs.stream()
.filter(item -> jobCardIds.contains(item.getJobCardId()) &&
"STITCHING_OFFLINE".equals(item.getParentDocumentType()) && item.getTransactionLegDateTime().toLocalDate().equals(date))
.mapToInt(item -> item.getQuantity().intValue())
.sum();
dateWiseProduction.put(date.format(formatter), totalProduction);
}
}
List<Long> distinctJobCardIds = inventoryTransactionLegs.stream()
.map(InventoryTransactionLeg::getJobCardId)
.filter(id -> id != 0)
.distinct()
.collect(Collectors.toList());
Map<Long, List<CuttingJobCardItemWrapper>> jobCardItemsStitchingDetailsMap = new HashMap<>();
Map<String, Integer> totalStitchingBasedOnAccountID = new HashMap<>();
for (long jobCardIdEntry : distinctJobCardIds) {
Long accountId = inventoryTransactionLegs.stream()
.filter(e -> e.getJobCardId() == jobCardIdEntry)
.map(e -> e.getAccountId().longValue())
.findFirst()
.orElse(0L);
JobCard jobCard = jobCardDAO.find(jobCardIdEntry);
List<StitchingOfflineItem> stitchingOfflineItem = stitchingOfflineItemDAO.findByJobCardId(jobCardIdEntry);
List<JobCardItem> jobCardItems = jobCardItemDAO.findByCardId(jobCardIdEntry);
List<CuttingJobCardItemWrapper> wrappers = jobCardItems.stream().map(item -> {
CuttingJobCardItemWrapper wrapper = new CuttingJobCardItemWrapper();
wrapper.setArticleName(jobCard.getArticleName());
wrapper.setJobCardId(jobCard.getId());
wrapper.setJobCardCode(jobCard.getCode());
wrapper.setSku(item.getSku());
wrapper.setPoName(jobCard.getPurchaseOrderId());
wrapper.setJobCardId(item.getJobCardId());
wrapper.setOperatorName(stitchingOfflineItem.get(0).getCreatedBy());
wrapper.setAccountId(accountId);
return wrapper;
}).collect(Collectors.toList());
totalStitchingBasedOnAccountID.put(jobCard.getId()+stitchingOfflineItem.get(0).getSku(), stitchingOfflineItem.size());
jobCardItemsStitchingDetailsMap.computeIfAbsent(accountId, k -> new ArrayList<>()).addAll(wrappers);
}
stitchingDetails.put("totalStitchingBasedOnAccountID", totalStitchingBasedOnAccountID);
stitchingDetails.put("jobCardItemsStitchingDetailsMap", jobCardItemsStitchingDetailsMap);
stitchingDetails.put("Date Wise Stitching", dateWiseProduction);
stitchingDetails.put("stitchingAccount", inventoryAccounts);
return stitchingDetails;
}
public List<StitchingOfflineItem> stitchingItemsTransactions(String jobCardId, String accountId, String sku, String startDate, String endDate) {
List<Long> accountID = new ArrayList<>();
String startDate1 = null;
String endDate1 = null;
if (!StringUtils.isNullOrEmpty(startDate) && !StringUtils.isNullOrEmpty(accountId) && !StringUtils.isNullOrEmpty(jobCardId)) {
String formattedStart = CTPDateTimeFormat.getMySQLFormattedDateString(startDate, CTPDateTimeFormat.HTML5_DATE_INPUT_FORMAT);
String formattedEnd = !StringUtils.isNullOrEmpty(endDate)
? CTPDateTimeFormat.getMySQLFormattedDateString(endDate, CTPDateTimeFormat.HTML5_DATE_INPUT_FORMAT)
: LocalDate.now().toString();
startDate1 = String.format("'%s 00:00:01'", formattedStart);
endDate1 = String.format("'%s 23:59:59'", formattedEnd);
accountID.add(Long.parseLong(accountId));
}
String query = SummaryInventoryReportQueryBuilder.cuttingQueryBuild(Long.parseLong(jobCardId), accountID, sku, startDate1, endDate1,"IN","STITCHING_OFFLINE");
List<InventoryTransactionLeg> inventoryTransactionLegs = inventoryTransactionLegDAO.findByQuery(query);
List<Long> stitchingItemsList = inventoryTransactionLegs.stream()
.map(InventoryTransactionLeg::getParentDocumentId)
.collect(Collectors.toList());
return stitchingOfflineItemDAO.findByIds(stitchingItemsList);
}
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

@ -0,0 +1,16 @@
package com.utopiaindustries.util;
import com.itextpdf.html2pdf.attach.ITagWorker;
import com.itextpdf.html2pdf.attach.ProcessorContext;
import com.itextpdf.html2pdf.attach.impl.DefaultTagWorkerFactory;
import com.itextpdf.html2pdf.html.TagConstants;
import com.itextpdf.styledxmlparser.node.IElementNode;
public class CustomTagWorkerFactory extends DefaultTagWorkerFactory {
public ITagWorker getCustomTagWorker( IElementNode tag, ProcessorContext context) {
if ( TagConstants.HTML.equals(tag.name())) {
return new ZeroMarginHtmlTagWorker(tag, context);
}
return null;
}
}

View File

@ -0,0 +1,90 @@
package com.utopiaindustries.util;
import com.utopiaindustries.dialect.CTPDialect;
import org.springframework.stereotype.Component;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.w3c.tidy.Tidy;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
@Component
public class HTMLBuilder {
private final String UTF_8 = StandardCharsets.UTF_8.displayName();
public String buildHTML( String templateName, Model model ) throws Exception {
// template resolver
ClassLoaderTemplateResolver pdfTemplateResolver = createPDFTemplateResolver();
// template engine
TemplateEngine templateEngine = new TemplateEngine();
templateEngine.setTemplateResolver( pdfTemplateResolver );
templateEngine.addDialect( new CTPDialect() );
// context
Context ctx = configureContext( model );
// render the template
String renderedHTMLContent = templateEngine.process( templateName, ctx );
return convertToXhtml( renderedHTMLContent );
}
public String buildHTMLMap( String templateName, ModelMap model ) throws Exception {
// template resolver
ClassLoaderTemplateResolver pdfTemplateResolver = createPDFTemplateResolver();
// template engine
TemplateEngine templateEngine = new TemplateEngine();
templateEngine.setTemplateResolver( pdfTemplateResolver );
templateEngine.addDialect( new CTPDialect() );
// context
Context ctx = configureContextMap( model );
// render the template
String renderedHTMLContent = templateEngine.process( templateName, ctx );
return convertToXhtml( renderedHTMLContent );
}
private String convertToXhtml( String html ) throws UnsupportedEncodingException {
Tidy tidy = new Tidy();
tidy.setInputEncoding( UTF_8 );
tidy.setOutputEncoding( UTF_8 );
tidy.setXHTML( true );
ByteArrayInputStream inputStream = new ByteArrayInputStream( html.getBytes( UTF_8 ) );
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
tidy.parseDOM( inputStream, outputStream );
return outputStream.toString( UTF_8 );
}
private ClassLoaderTemplateResolver createPDFTemplateResolver() {
ClassLoaderTemplateResolver pdfTemplateResolver = new ClassLoaderTemplateResolver();
pdfTemplateResolver.setPrefix( "/templates/" );
pdfTemplateResolver.setTemplateMode( TemplateMode.HTML );
pdfTemplateResolver.setSuffix( ".html" );
pdfTemplateResolver.setCharacterEncoding( UTF_8 );
pdfTemplateResolver.setOrder( 1 );
return pdfTemplateResolver;
}
private Context configureContext( Model model ) {
Context ctx = new Context();
// adding model attributes to context
for ( Map.Entry<String, Object> entry: model.asMap().entrySet() ) {
ctx.setVariable( entry.getKey(), entry.getValue() );
}
return ctx;
}
private Context configureContextMap( ModelMap model ) {
Context ctx = new Context();
// adding model attributes to context
for ( Map.Entry<String, Object> entry: model.entrySet() ) {
ctx.setVariable( entry.getKey(), entry.getValue() );
}
return ctx;
}
}

View File

@ -0,0 +1,110 @@
package com.utopiaindustries.util;
import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.html2pdf.resolver.font.DefaultFontProvider;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@Component
public class PDFResponseEntityInputStreamResource {
/**
* prepare pdf document from html string
*/
private ResponseEntity<InputStreamResource> createPDFResponseEntityInputStreamResource( String htmlStr, String filename, String method ) throws IOException {
// output stream
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// converter properties
ConverterProperties properties = new ConverterProperties();
properties.setFontProvider( new DefaultFontProvider( false, false, true ) );
// pdf document
PdfWriter writer = new PdfWriter( outputStream );
//temp Code
/* PdfDocument temp = new PdfDocument(writer);
Rectangle rectangle3x5 = new Rectangle(216, 360);
PageSize pageSize =new PageSize( rectangle3x5 );
temp.setDefaultPageSize( pageSize);
properties.setTagWorkerFactory( new CustomTagWorkerFactory() );*/
//temp code end
Document document = HtmlConverter.convertToDocument( htmlStr, writer, properties );
document.close();
// input stream
ByteArrayInputStream inputStream = new ByteArrayInputStream( outputStream.toByteArray() );
// content disposition header
String headerContentDispositionStr = String.format( "%s; filename=%s.pdf", method, filename.replaceAll( ",", "-" ) );
// return response
return ResponseEntity
.ok()
.header( HttpHeaders.CONTENT_DISPOSITION, headerContentDispositionStr )
.contentType( MediaType.APPLICATION_PDF )
.body( new InputStreamResource( inputStream ) );
}
/**
* prepare pdf document from html string
*/
private ResponseEntity<InputStreamResource> createPDFResponseEntityInvoiceInputStreamResource( String htmlStr, String filename, String method, long height, long width )
throws IOException {
// output stream
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// converter properties
ConverterProperties properties = new ConverterProperties();
properties.setFontProvider( new DefaultFontProvider( false, true, false ) );
// pdf document
PdfWriter writer = new PdfWriter( outputStream );
//Code for invoice slips
PdfDocument temp = new PdfDocument( writer );
Rectangle rectangle3x5 = new Rectangle( width, height );
PageSize pageSize = new PageSize( rectangle3x5 );
temp.setDefaultPageSize( pageSize );
properties.setTagWorkerFactory( new CustomTagWorkerFactory() );
//temp code end
Document document = HtmlConverter.convertToDocument( htmlStr, temp, properties );
//document.setFontSize( 200.0f );
document.close();
// input stream
ByteArrayInputStream inputStream = new ByteArrayInputStream( outputStream.toByteArray() );
// content disposition header
String headerContentDispositionStr = String.format( "%s; filename=%s.pdf", method, filename.replaceAll( ",", "-" ) );
// return response
return ResponseEntity
.ok()
.header( HttpHeaders.CONTENT_DISPOSITION, headerContentDispositionStr )
.contentType( MediaType.APPLICATION_PDF )
.body( new InputStreamResource( inputStream ) );
}
/**
* with inline as default content disposition "inline"
*/
public ResponseEntity<InputStreamResource> generatePdf( String htmlStr, String filename ) throws IOException {
return this.createPDFResponseEntityInputStreamResource( htmlStr, filename, "inline" );
}
/**
* manual content disposition
*/
public ResponseEntity<InputStreamResource> generatePdf( String htmlStr, String filename, String method ) throws IOException {
return this.createPDFResponseEntityInputStreamResource( htmlStr, filename, method );
}
/**
* manual content disposition
*/
public ResponseEntity<InputStreamResource> generateInvoicePdf( String htmlStr, String filename, String method, long height, long width ) throws IOException {
return this.createPDFResponseEntityInvoiceInputStreamResource( htmlStr, filename, method, height, width );
}
}

View File

@ -0,0 +1,16 @@
package com.utopiaindustries.util;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
public class URLUtils {
public static String getCurrentBaseUrl() {
ServletRequestAttributes sra = ( ServletRequestAttributes ) RequestContextHolder.getRequestAttributes();
HttpServletRequest req = sra.getRequest();
return req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + req.getContextPath();
}
}

View File

@ -0,0 +1,15 @@
package com.utopiaindustries.util;
import com.itextpdf.html2pdf.attach.ProcessorContext;
import com.itextpdf.html2pdf.attach.impl.tags.HtmlTagWorker;
import com.itextpdf.layout.Document;
import com.itextpdf.styledxmlparser.node.IElementNode;
public class ZeroMarginHtmlTagWorker extends HtmlTagWorker {
public ZeroMarginHtmlTagWorker( IElementNode element, ProcessorContext context) {
super(element, context);
Document doc = (Document) getElementResult();
doc.setMargins(0, 0, 0, 0);
}
}

View File

@ -0,0 +1 @@
*,*:before,*:after{padding:0;margin:0;box-sizing:border-box}body{font-family:"Open Sans",sans-serif;font-size:7pt;font-weight:400;line-height:1.2em;background:#fff !important;color:#111;position:relative;background:rgba(0,0,0,0) !important}body.draft:before,body.draft:after,body.terminated:before,body.terminated:after,body.not-approved:before,body.not-approved:after,body.duplicate:before,body.duplicate:after,body.cancel:before,body.cancel:after{font-size:70pt;font-weight:bold;color:red;text-align:center;display:block;opacity:.6;position:absolute;top:250pt;left:0;transform:rotate(-45deg)}body.duplicate:before,body.duplicate:after{content:"DUPLICATE"}body.cancel:before,body.cancel:after{content:"CANCEL"}body.draft:before,body.draft:after{content:"DRAFT"}body.terminated:before,body.terminated:after{content:"TERMINATED"}body.not-approved:before,body.not-approved:after{content:"NOT APPROVED"}@page{font-family:"Open Sans",sans-serif;font-size:6.65pt;font-style:italic;margin:1.25cm 1.25cm;@bottom-left{content:"Utopia Industries Pvt. Limited"}@bottom-center{content:"Page " counter(page) " of " counter(pages)}@bottom-right{width:126px;height:122px;margin-top:-130px}}h1{font-size:2em}h2{font-size:2.2857142857em}h3{font-size:1.8571428571em}h4{font-size:1.7142857143em}h5{font-size:1.5714285714em}h6{font-size:1.4285714286em}h1,h2,h3,h4,h5,h6{font-family:"Open Sans Condensed",sans-serif;font-weight:700;page-break-after:avoid;page-break-inside:avoid;text-transform:uppercase;margin:1.5em 0 1em}h1.no-margin-top,h2.no-margin-top,h3.no-margin-top,h4.no-margin-top,h5.no-margin-top,h6.no-margin-top{margin-top:0}h1.no-margin-bottom,h2.no-margin-bottom,h3.no-margin-bottom,h4.no-margin-bottom,h5.no-margin-bottom,h6.no-margin-bottom{margin-bottom:0}.text-right{text-align:right}.text-uppercase{text-transform:uppercase}.text-center{text-align:center}.font-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}b{font-weight:700}img{page-break-inside:avoid;page-break-after:avoid}ul,ol,dl{page-break-before:avoid}table{width:100%;border-collapse:collapse;border:none}table td{border:none}table.bordered,table.bordered td{border:1px solid #111}table.borderless,table.borderless td{border:none;padding:0}.tr-footer{text-transform:uppercase}td{padding:.4285714286em .8571428571em;vertical-align:top}td.spacer{padding:1em 0}.tr-header td{font-family:"Open Sans Condensed",sans-serif;font-size:1em;font-weight:bold;text-transform:uppercase;color:#fff;background:#111}td.pd-0{padding:0}ul,ol{padding:0 1.4285714286em;margin:0}ul{list-style-type:disc}.spacer{width:100%;height:1px;margin:2em 0 1em}.row{overflow:hidden;width:100%}.col{float:left}.col.col-half{width:49.96%}.col.col-half.col-padded:first-child{padding-right:3.5pt}.col.col-half.col-padded:last-child{padding-left:3.5pt}.col.col-two-third{width:66.6666%}.col.col-one-third{width:33.3333%}.col.col-one-third.col-padded{padding-left:3.5pt;padding-right:3.5pt}.col.col-one-third.col-padded:first-child{padding-left:0}.col.col-one-third.col-padded:last-child{padding-right:0}.visitor-photo{text-align:center;width:23%;height:77pt;line-height:77pt;margin-left:5pt;border:1px solid #111}.visitor-photo img{display:inline-block;width:90%;height:auto}/*# sourceMappingURL=print.css.map */

View File

@ -0,0 +1,43 @@
( async function(){
Vue.prototype.$types = window.ctp.types;
Vue.prototype.$accounts = window.ctp.accounts;
let app = new Vue({
el : '#dashboard',
data :{
jobCard : {}
},
computed: {
getStatus: function() {
return `badge-${this.jobCard.status}`;
},
getInvStatus: function() {
return `badge-${this.jobCard.inventoryStatus}`;
}
},
methods : {
onCardSelect : function ( id, card ) {
// $.ajax({
// url: `/ctp/rest/job-cards/find/${id}`,
// method: 'GET',
// contentType: 'application/json',
// dataType: 'json',
// success: ( data ) => {
// this.jobCard = data;
// },
// error : function ( err ){
// alert( err );
// }
// })
console.log("hello")
}
},
mounted : function () {
}
})
})(jQuery);

View File

@ -0,0 +1,278 @@
document.addEventListener("DOMContentLoaded", function () {
if (typeof Highcharts === "undefined") {
console.error("Highcharts library not loaded!");
return;
}
function createGaugeChart(progress, color, divId, title, height, width , fontSize, fontYAxis, fontXAxis, fontColor, total, actual, aGrade, bGrade, cGrade) {
Highcharts.chart(divId, {
chart: {
type: 'solidgauge',
width: width,
height: height,
backgroundColor: 'transparent',
plotBackgroundColor: null,
shadow: false
},
title: {
text: title,
y: 30
},
pane: {
startAngle: 0,
endAngle: 360,
y: 0,
background: [{
backgroundColor: 'transparent',
shape: "arc",
borderWidth: 0,
innerRadius: '60%',
outerRadius: '100%'
}]
},
yAxis: {
min: 0,
max: 100,
tickPositions: [],
lineWidth: 0,
minorTickLength: 0,
tickWidth: 0,
gridLineWidth: 0,
stops: [
[1, color]
]
},
series: [{
name: 'Percentage',
data: [progress],
dataLabels: {
format: '{y}% ',
y: fontYAxis,
x: fontXAxis,
borderWidth: 0,
backgroundColor: 'none',
style: {
fontSize: fontSize + 'px',
fontWeight: 'bold',
color:fontColor
},
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
}],
credits: {
enabled: false
}
});
}
function createBarChart(divId, height, width, title, aHeading, aData, bHeading, bData, cHeading, cData, dHeading, dData, dates, fontSize, maxValue) {
if (!document.getElementById(divId)) {
return;
}
Highcharts.chart(divId, {
chart: {
type: 'column',
height: height,
width: width,
},
title: {
text: title,
align: 'center',
verticalAlign: 'top',
y: 30,
style: {
fontSize: fontSize,
fontWeight: 'bold',
}
},
xAxis: {
categories: dates,
labels: {
rotation: -45,
style: {
fontSize: 10-fontSize,
fontWeight: 'bold'
}
}
},
yAxis: {
min: 0,
max: maxValue,
softMax: maxValue,
softMin: 0,
startOnTick: true,
endOnTick: true,
title: {
text: 'Total Progress',
style: {
fontSize: fontSize,
fontWeight: 'bold',
}
},
labels: {
format: '{value}%'
}
},
scrollbar: {
enabled: true
},
series: [{
name: aHeading,
data: aData
}, {
name: bHeading,
data: bData
}, {
name: cHeading,
data: cData
}, {
name: dHeading,
data: dData
}]
});
}
function createSingleBarChart(divId, height, width, title,Heading, Data, dates, fontSize, maxValue) {
if (!document.getElementById(divId)) {
return;
}
Highcharts.chart(divId, {
chart: {
type: 'column',
height: height,
width: width,
},
title: {
text: title,
align: 'center',
verticalAlign: 'top',
y: 30,
style: {
fontSize: fontSize,
fontWeight: 'bold',
}
},
xAxis: {
categories: dates,
labels: {
rotation: -45,
style: {
fontSize: 10-fontSize,
fontWeight: 'bold'
}
}
},
yAxis: {
min: 0,
max: maxValue,
softMax: maxValue,
softMin: 0,
startOnTick: true,
endOnTick: true,
title: {
text: 'Total Progress',
style: {
fontSize: fontSize,
fontWeight: 'bold',
}
},
labels: {
format: '{value}%'
}
},
legend: {
itemStyle: {
fontSize: 10-fontSize,
fontWeight: 'bold'
}
},
scrollbar: {
enabled: true
},
series: [{
name: Heading,
data: Data
}]
});
}
initializeGauges();
function initializeGauges() {
const gaugeDivs2 = document.querySelectorAll('.gauge-chart2');
gaugeDivs2.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 divId = div.id;
console.log(actual)
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;
createBarChart( divId, height, width, title, aHeading, aData, bHeading, bData, cHeading, cData, dHeading, dData, datesArray, fontSize, maxValue);
});
const cuttingBarChart = document.querySelectorAll('.singleBarChart');
cuttingBarChart.forEach(function (div) {
const title = div.getAttribute('data-title');
const height = div.getAttribute('data-height');
const width = div.getAttribute('data-width');
const fontSize = div.getAttribute('data-fontSize');
const maxValue = Number(div.getAttribute('data-totalProduction'));
const Heading = div.getAttribute('data-barHeading');
const Data = JSON.parse(div.getAttribute('data-barData'));
const dates = div.getAttribute('data-dates');
const datesArray = dates.split(',');
const divId = div.id;
createSingleBarChart( divId, height, width, title, Heading, Data, datesArray, fontSize, maxValue);
});
}
});

View File

@ -0,0 +1,91 @@
(async function () {
Vue.component('bundle-table', {
props: ['bundles'],
methods: {
removeBundle: function (idx) {
this.$emit('bundle-remove', idx)
},
getFormattedDateTime: function (bundle) {
if (!!bundle.createdAt) {
return bundle.createdAt.split('T')[0] + ' ' + bundle.createdAt.split('T')[1];
}
return luxon.DateTime.now().toFormat('yyyy-MM-dd HH:mm:ss');
},
},
template: `
<table class="table table-bordered bg-white col-sm-8">
<thead>
<tr>
<th>ID</th>
<th>Item ID</th>
<th>Sku</th>
<th>Job Card ID</th>
<th>Wrap Quantity</th>
<th>Type</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr v-for="(bundle,index) in bundles">
<input hidden="hidden" v-bind:name="'bundles[' + index + '].id'" v-bind:value="bundle.id" >
<input hidden="hidden" v-bind:name="'bundles[' + index + '].itemId'" v-bind:value="bundle.itemId" >
<input hidden="hidden" v-bind:name="'bundles[' + index + '].sku'" v-bind:value="bundle.sku" >
<input hidden="hidden" v-bind:name="'bundles[' + index + '].masterBundleId'" v-bind:value="bundle.masterBundleId" >
<input hidden="hidden" v-bind:name="'bundles[' + index + '].jobCardId'" v-bind:value="bundle.jobCardId" >
<input hidden="hidden" v-bind:name="'bundles[' + index + '].wrapQuantity'" v-bind:value="bundle.wrapQuantity" >
<input hidden="hidden" v-bind:name="'bundles[' + index + '].type'" v-bind:value="bundle.type" >
<input hidden="hidden" v-bind:name="'bundles[' + index + '].barcode'" v-bind:value="bundle.barcode" >
<input hidden="hidden" v-bind:name="'bundles[' + index + '].createdAt'" v-bind:value="getFormattedDateTime(bundle.createdAt)" >
<input hidden="hidden" v-bind:name="'bundles[' + index + '].createdBy'" v-bind:value="bundle.createdBy" >
<td><span>{{bundle.id}}</span></td>
<td><span>{{bundle.itemId}}</span></td>
<td><span>{{bundle.sku}}</span></td>
<td><span>{{bundle.jobCardId}}</span></td>
<td><span>{{bundle.wrapQuantity}}</span></td>
<td><span>{{bundle.type}}</span></td>
<td>
<button type="button" title="Remove" class="btn btn-light text-left" v-on:click="removeBundle(index)">
<i class="bi bi-trash"></i>
</button>
</td>
</tr>
</tbody>
</table>
`
})
let app = new Vue({
el: "#jobcardsidebar",
data: {
bundles: [],
},
methods: {
removeBundle: function (idx) {
this.bundles.splice(idx, 1)
},
onBundleSelect: function (id, bundle) {
this.bundles.push(
bundle
)
},
hasMultipleItemSelect : function () {
const ids = this.bundles.map(item => item.itemId);
const uniqueIds = new Set(ids);
return uniqueIds.size > 1;
},
hasDuplicates: function () {
const ids = this.bundles.map(item => item.id);
const uniqueIds = new Set(ids);
return ids.length !== uniqueIds.size;
}
},
mounted: function () {
this.bundles = window.ctp.wrapper.bundles;
}
});
})(jQuery);

View File

@ -90,6 +90,7 @@
}, },
methods : { methods : {
onItemSelect: function (id, item) { onItemSelect: function (id, item) {
console.log("wdwawdwwadwwdwda",item.id)
this.items.push(item); this.items.push(item);
}, },
removeItem: function (index) { removeItem: function (index) {

File diff suppressed because one or more lines are too long

View File

@ -4,23 +4,27 @@
Vue.prototype.$accounts = window.ctp.accounts; Vue.prototype.$accounts = window.ctp.accounts;
Vue.component('item-rows', { Vue.component('item-rows', {
data() {
return {
wrapQuantity: 0
};
},
props: ['index', 'item'], props: ['index', 'item'],
methods : { methods : {
populateCuttingAccount : function (){ populateCuttingAccount : function (){
return this.$accounts.find(account => account.id === this.item.accountId).title; return this.$accounts.find(account => account.id === this.item.accountId).title;
}, },
handleValueChange : function(value){
this.wrapQuantity = value
}
}, },
template: ` template: `
<tr> <tr>
<td width="400"> <td width="120">
<input hidden="hidden" v-bind:name="'items[' + index + '].jobCardId'" v-bind:value="item.jobCardId" > <input hidden="hidden" v-bind:name="'items[' + index + '].jobCardId'" v-bind:value="item.jobCardId" >
<input hidden="hidden" v-bind:name="'items[' + index + '].jobCardItemId'" v-bind:value="item.id" > <input hidden="hidden" v-bind:name="'items[' + index + '].jobCardItemId'" v-bind:value="item.id" >
<item-search <span class="form-control" readonly>{{item.id}}</span>
v-bind:id-field-name="'items[' + index + '].itemId'"
v-bind:id="item.itemId"
v-bind:type="item.type"
v-bind:show-label="false"
v-bind:disabled="true"></item-search>
</td> </td>
<td width="400"> <td width="400">
<span class="form-control" readonly >{{item.sku}}</span> <span class="form-control" readonly >{{item.sku}}</span>
@ -36,8 +40,17 @@
<td width="200"> <td width="200">
<span class="form-control" readonly>{{item.expectedProduction}}</span> <span class="form-control" readonly>{{item.expectedProduction}}</span>
</td> </td>
<td width="100">
<span class="form-control" readonly>{{item.actualProduction}}</span>
</td>
<td width="200"> <td width="200">
<input class="form-control" min="0" type="number" v-bind:name="'items[' + index + '].actualProduction'" required> <input class="form-control" @input="handleValueChange($event.target.value)" :min="0" type="number" v-bind:name="'items[' + index + '].actualProduction'" required>
</td>
<td width="200">
<input class="form-control" min="1" :max="wrapQuantity" type="number" v-bind:name="'items[' + index + '].perBundleQuantity'" required>
</td>
<td width="10" style="text-align: center;" >
<input type="checkbox" v-bind:name="'items[' + index + '].cuttingComplete'">
</td> </td>
<td> <td>
{{ populateCuttingAccount() }} {{ populateCuttingAccount() }}
@ -84,11 +97,14 @@
<table class="table table-bordered bg-white w-100"> <table class="table table-bordered bg-white w-100">
<thead> <thead>
<tr> <tr>
<th>Item</th> <th>ID</th>
<th>Item Sku/Title</th> <th>Item Sku/Title</th>
<th>Cut Pieces</th> <th>Cut Pieces</th>
<th>Expected Production</th> <th>Expected Production</th>
<th>Current Production</th>
<th>Actual Production</th> <th>Actual Production</th>
<th>Per Bundle Quantity</th>
<th>Cutting Complete</th>
<th style="width: 312px" >Account</th> <th style="width: 312px" >Account</th>
</tr> </tr>
</tr> </tr>

View File

@ -216,6 +216,7 @@ if ( typeof Vue !== 'undefined' ) {
v-bind:disabled="disabled" v-bind:disabled="disabled"
v-bind:readonly="readOnly" v-bind:readonly="readOnly"
v-bind:inputmode="inputMode" v-bind:inputmode="inputMode"
autofocus
v-bind:class="{ 'is-invalid': ( showInputErrorOnZeroId && ( entityId === 0 || entityId == null ) ) }" v-bind:class="{ 'is-invalid': ( showInputErrorOnZeroId && ( entityId === 0 || entityId == null ) ) }"
autocomplete="off"> autocomplete="off">
<!-- autocomplete list --> <!-- autocomplete list -->
@ -1049,6 +1050,35 @@ if ( typeof Vue !== 'undefined' ) {
} }
}); });
/**
* location site search component
*/
Vue.component( 'search-job-card-dashBoard', {
mixins: [searchComponentMixin],
methods: {
getSearchUrl: function() {
return `/ctp/rest/locations/sites/search?term=${encodeURIComponent( this.list.term )}`;
},
getEmittedEventName: function() {
return 'location-site-select';
}
},
props: {
labelText: {
default: 'Search Site'
},
titleFieldName: {
default: 'siteTitle'
},
idFieldName: {
default: 'siteId'
},
codeFieldName: {
default: ''
}
}
});
/** /**
* location site search component * location site search component
@ -1150,7 +1180,7 @@ if ( typeof Vue !== 'undefined' ) {
} }
// else format item title with code // else format item title with code
if ( typeof item.code !== 'undefined' ) { if ( typeof item.code !== 'undefined' ) {
return `${item.title} (${item.code})`; return `${item.title} (${item.sku}) (${item.code})`;
} }
// item title only // item title only
return item.title; return item.title;
@ -3408,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
}
}
})
/* /*
@ -3525,43 +3593,75 @@ if ( typeof Vue !== 'undefined' ) {
}); });
/* Vue.component('search-item', {
* finished item search
* */
Vue.component('finished-item-search',{
mixins: [searchComponentMixin],
methods : {
getSearchUrl : function () {
return `/ctp/rest/finished-items/search?term=${encodeURIComponent( this.list.term )}&is-segregated=${this.isSegregated}`
},
getEmittedEventName: function() {
return 'finished-item-select';
},
getTitle: function( item ) {
return `${item.id} - ( ${item.barcode} )`;
}
},
props: { props: {
labelText: { label: {
type: String,
default: 'Search Finished Item' default: 'Search Finished Item'
}, },
titleFieldName: { url: {
default: 'title' type: String,
default: ''
}, },
idFieldName: { isSegregated: {
default: 'id' type: Boolean,
default: false
}, },
codeFieldName : { debounceTime: {
default : 'code' type: Number,
default: 500
}
}, },
isSegregated : { data() {
default : false return {
searchTerm: '',
timeout: null
};
}, },
inputMode: { methods: {
default : 'none' handleInput() {
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
this.fetchData();
}, this.debounceTime);
},
async fetchData() {
if (this.searchTerm.trim() === '') return;
try {
const response = await fetch(`${this.url}?term=${encodeURIComponent(this.searchTerm)}&is-segregated=${this.isSegregated}`);
const data = await response.json();
if (data.length > 0) {
const selectedItem = data[0];
this.$emit('finished-item-select', selectedItem.id, selectedItem);
this.searchTerm = `${selectedItem.id} - (${selectedItem.barcode})`;
setTimeout(() => {
this.searchTerm = '';
}, 500);
} else {
setTimeout(() => {
this.searchTerm = '';
}, 500);
}
} catch (error) {
console.error('Error fetching search results:', error);
} }
} }
}) },
template: `
<div class="search-container">
<label>{{ label }}</label>
<input type="text" class="form-control"
v-model="searchTerm"
@input="handleInput"
placeholder="Scan QR"
autocomplete="off"
inputmode="none"
autofocus>
</div>
`
});
/* /*
* bundle search component * bundle search component

View File

@ -16,6 +16,9 @@
<script th:src="@{/js/vendor/bignumber.min.js}"></script> <script th:src="@{/js/vendor/bignumber.min.js}"></script>
<script th:src="@{/js/vue-components.js}"></script> <script th:src="@{/js/vue-components.js}"></script>
<script th:src="@{/js/utils.js}"></script> <script th:src="@{/js/utils.js}"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<script src="https://code.highcharts.com/modules/solid-gauge.js"></script>
<title th:text="${#strings.concat(title, ' - CTP')}"></title> <title th:text="${#strings.concat(title, ' - CTP')}"></title>
</head> </head>
<body> <body>
@ -125,6 +128,32 @@
</li> </li>
</ul> </ul>
</nav> </nav>
<!--Second level of reporting-->
<nav class="navbar navbar-light bg-light navbar-expand-lg justify-content-between"
th:if="${#strings.startsWith(#httpServletRequest.getRequestURI(), '/ctp/reporting')}">
<ul class="navbar-nav">
<li class="nav-item"
th:classappend="${#strings.startsWith(#httpServletRequest.getRequestURI(), '/ctp/reporting/po-report') ? 'active' : ''}">
<a th:href="@{/reporting/po-report}" class="nav-link">PO Report</a>
</li>
<li class="nav-item"
th:classappend="${#strings.startsWith(#httpServletRequest.getRequestURI(), '/ctp/reporting/job-card-report') ? 'active' : ''}">
<a th:href="@{/reporting/job-card-report}" class="nav-link">Job Card Report</a>
</li>
<li class="nav-item"
th:classappend="${#strings.startsWith(#httpServletRequest.getRequestURI(), '/ctp/reporting/cutting-report') ? 'active' : ''}">
<a th:href="@{/reporting/cutting-report}" class="nav-link">Cutting Tables Report</a>
</li>
<li class="nav-item"
th:classappend="${#strings.startsWith(#httpServletRequest.getRequestURI(), '/ctp/reporting/stitching-report') ? 'active' : ''}">
<a th:href="@{/reporting/stitching-report}" class="nav-link">Stitching Line Report</a>
</li>
<li class="nav-item"
th:classappend="${#strings.startsWith(#httpServletRequest.getRequestURI(), '/ctp/reporting/summary') ? 'active' : ''}">
<a th:href="@{/reporting/summary}" class="nav-link">Summary</a>
</li>
</ul>
</nav>
<!-- second level stitching --> <!-- second level stitching -->
<nav class="navbar navbar-light bg-light navbar-expand-lg justify-content-between" <nav class="navbar navbar-light bg-light navbar-expand-lg justify-content-between"
th:if="${#strings.startsWith(#httpServletRequest.getRequestURI(), '/ctp/stitching')}"> th:if="${#strings.startsWith(#httpServletRequest.getRequestURI(), '/ctp/stitching')}">

View File

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

View File

@ -18,7 +18,7 @@
<div th:replace="_fragments :: table-loading-skeleton"></div> <div th:replace="_fragments :: table-loading-skeleton"></div>
<form th:action="@{/cutting/generate-bundle-barcodes}" method="post"> <form th:action="@{/cutting/generate-bundle-barcodes}" method="post">
<input hidden="hidden" name="artifactType" value="Bundle"> <input hidden="hidden" name="artifactType" value="Bundle">
<table class="table table-striped" data-table data-order="[[ 0, &quot;asc&quot; ]]"> <table class="table table-striped" data-table data-order="[[ 0, &quot;desc&quot; ]]">
<thead> <thead>
<tr> <tr>
<th>ID</th> <th>ID</th>

View File

@ -17,9 +17,11 @@
<div class="bg-light p-3 mb-3"> <div class="bg-light p-3 mb-3">
<div class="form-row"> <div class="form-row">
<div class="col-sm-3"> <div class="col-sm-3">
<bundle-search <search-item
v-on:bundle-select="onBundleSelect" label="Search Bundle"
></bundle-search> url="/ctp/rest/bundles/search"
v-on:finished-item-select="onBundleSelect">
</search-item>
</div> </div>
</div> </div>
</div> </div>

View File

@ -19,7 +19,7 @@
<form th:action="@{/cutting/generate-master-barcodes}" method="post"> <form th:action="@{/cutting/generate-master-barcodes}" method="post">
<input hidden="hidden" name="artifactType" value="MasterBundle"> <input hidden="hidden" name="artifactType" value="MasterBundle">
<table class="table table-striped table-bordered" data-bundle-table <table class="table table-striped table-bordered" data-bundle-table
data-order="[[ 0, &quot;asc&quot; ]]"> data-order="[[ 0, &quot;desc&quot; ]]">
<thead> <thead>
<tr> <tr>
<th></th> <th></th>

View File

@ -22,6 +22,7 @@
v-on:job-card-select="onCardSelect" v-on:job-card-select="onCardSelect"
v-bind:required="true" v-bind:required="true"
></job-card-search> ></job-card-search>
</div> </div>
<!-- <div class="col-sm-3">--> <!-- <div class="col-sm-3">-->
<!-- <label>Cutting Account</label>--> <!-- <label>Cutting Account</label>-->

View File

@ -19,7 +19,7 @@
<div th:replace="_fragments :: table-loading-skeleton"></div> <div th:replace="_fragments :: table-loading-skeleton"></div>
<form th:action="@{/cutting/generate-barcodes}" method="post"> <form th:action="@{/cutting/generate-barcodes}" method="post">
<input hidden="hidden" name="artifactType" value="Bundle"> <input hidden="hidden" name="artifactType" value="Bundle">
<table class="table table-striped" data-table data-order="[[ 0, &quot;asc&quot; ]]"> <table class="table table-striped" data-table data-order="[[ 0, &quot;desc&quot; ]]">
<thead> <thead>
<tr> <tr>
<th>ID</th> <th>ID</th>

View File

@ -14,11 +14,10 @@
<div class="bg-light p-3 mb-3"> <div class="bg-light p-3 mb-3">
<div class="form-row"> <div class="form-row">
<div class="col-sm-3 form-group"> <div class="col-sm-3 form-group">
<finished-item-search <search-item
v-bind:is-segregated="false" url="/ctp/rest/finished-items/search"
v-on:finished-item-select="onItemSelect" v-on:finished-item-select="onItemSelect">
> </search-item>
</finished-item-search>
</div> </div>
<div class="col-sm-3 form-group"> <div class="col-sm-3 form-group">
<!-- <label>Packaging Account</label>--> <!-- <label>Packaging Account</label>-->

View File

@ -1,5 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.w3.org/1999/xhtml" xmlns:uind="http://www.w3.org/1999/xhtml"> <html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.w3.org/1999/xhtml"
xmlns:uind="http://www.w3.org/1999/xhtml" xmlns:ctp="http://www.w3.org/1999/xhtml">
<head th:replace="_fragments :: head('Job Cards')"></head> <head th:replace="_fragments :: head('Job Cards')"></head>
<body> <body>
<div class="container-fluid"> <div class="container-fluid">
@ -60,6 +61,9 @@
<i class="bi bi-pencil"></i> <i class="bi bi-pencil"></i>
</a> </a>
</th:block> </th:block>
<a th:href="@{'/job-cards/pdf/' + *{id}}" target="_blank" class="btn btn-sm btn-secondary" title="View PDF">
<i class="bi bi-filetype-pdf"></i>
</a>
</td> </td>
</tr> </tr>
</tbody> </tbody>

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8"?>
<!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"
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|}">
</head>
<body>
<div class="container-fluid">
<table>
<tr>
<td width="400">
<img width="200" th:src="@{|${baseUrl}/img/utopia-industries.png|}" alt="Utopia Industries">
</td>
<td >
<table class="bordered">
<tr class="tr-header">
<td colspan="2" th:text="'JOB CARD DETAIL'"></td>
</tr>
<tbody>
<tr>
<td style="width: 40%; border: 1px solid black;"><i>Job Card ID</i></td>
<td style="width: 60%; border: 1px solid black;">
<a class="text-reset" target="_blank" th:text="${card.getCode()}"></a>
</td>
</tr>
<tr>
<td style="width: 40%; border: 1px solid black;"><i>Job Order ID</i></td>
<td style="width: 60%; border: 1px solid black;">
<a class="text-reset" target="_blank" th:text="${card.getJobOrderId()}"></a>
</td>
</tr>
<tr>
<td class="align-middle" style="border: 1px solid black;"><i>Card Status</i></td>
<td style="border: 1px solid black;"><span th:text="${card.getStatus()}"></span></td>
</tr>
<tr>
<td class="align-middle" style="border: 1px solid black;"><i>Inventory Status</i></td>
<td style="border: 1px solid black;"><span th:text="${card.getInventoryStatus()}"></span></td>
</tr>
<tr>
<td class="align-middle" style="border: 1px solid black;"><i>Customer</i></td>
<td style="border: 1px solid black;"><span th:text="${card.getCustomer()}"></span></td>
</tr>
<tr>
<td class="align-middle" style="border: 1px solid black;"><i>Lot Number</i></td>
<td style="border: 1px solid black;"><span th:text="${card.getLotNumber()}"></span></td>
</tr>
<tr>
<td class="align-middle" style="border: 1px solid black;"><i>Purchase Order ID</i></td>
<td style="border: 1px solid black;"><span th:text="${card.getPurchaseOrderId()}"></span></td>
</tr>
</tbody>
</table>
</td>
</tr>
</table>
<table class="bordered" style="width: 100%; margin-top: 20px; border-collapse: collapse; ">
<h5 class="no-margin-top no-margin-bottom" style="margin-top: 20px;">CUTTING DETAILS</h5>
<thead >
<tr class="tr-header">
<td th:text="'Sku'"></td>
<td th:text="'Length'"></td>
<td th:text="'Width'"></td>
<td th:text="'Gsm'"></td>
<td th:text="'WT_Ply'"></td>
<td th:text="'Ply'"></td>
</tr>
</thead>
<tbody>
<tr th:each="cardItem : ${jobCardItems}">
<td style="border: 1px solid black;" th:text="${cardItem.getSku()}"></td>
<td style="border: 1px solid black;" th:text="${cardItem.getLength()}"></td>
<td style="border: 1px solid black;" th:text="${cardItem.getWidth()}"></td>
<td style="border: 1px solid black;" th:text="${cardItem.getGsm()}"></td>
<td style="border: 1px solid black;" th:text="${cardItem.getWtPly()}"></td>
<td style="border: 1px solid black;" th:text="${cardItem.getPly()}"></td>
</tr>
</tbody>
</table>
<table class="bordered" style="width: 100%; margin-top: 20px; border-collapse: collapse; ">
<h5 class="no-margin-top no-margin-bottom" style="margin-top: 20px;">ITEMS</h5>
<thead >
<tr class="tr-header">
<td th:text="'ID'"></td>
<td th:text="'Item ID'"></td>
<td th:text="'Sku'"></td>
<td th:text="'Expected Production'"></td>
<td th:text="'Actual Production'"></td>
<td th:text="'Total Production'"></td>
<td th:text="'Cut Piece Items'"></td>
</tr>
</thead>
<!-- Table Body -->
<tbody>
<tr th:each="cardItem : ${jobCardItems}">
<td style="border: 1px solid black;" th:text="${cardItem.getId()}"></td>
<td style="border: 1px solid black;" th:text="${cardItem.getItemId()}"></td>
<td style="border: 1px solid black;" th:text="${cardItem.getSku()}"></td>
<td style="border: 1px solid black;" th:text="${cardItem.getExpectedProduction()}"></td>
<td style="border: 1px solid black;" th:text="${cardItem.getActualProduction()}"></td>
<td style="border: 1px solid black;" th:text="${cardItem.getTotalProduction()}"></td>
<td style="border: 1px solid black;" th:text="${totalStitchingItem.get(cardItem.getItemId())}"></td>
<td style="border: 1px solid black;" th:text="${totalFinishItem.get(cardItem.getItemId())}"></td>
<td style="margin:0px; padding:0px">
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>

View File

@ -16,7 +16,7 @@
<h3>Packaging Inventory Accounts</h3> <h3>Packaging Inventory Accounts</h3>
</div> </div>
<div th:replace="_fragments :: table-loading-skeleton"></div> <div th:replace="_fragments :: table-loading-skeleton"></div>
<table class="table table-striped" data-account-table data-order="[[ 0, &quot;asc&quot; ]]"> <table class="table table-striped" data-account-table data-order="[[ 0, &quot;desc&quot; ]]">
<thead> <thead>
<tr> <tr>
<th></th> <th></th>

View File

@ -13,12 +13,13 @@
<form th:action="'/ctp/quality-control/qc-finished-item'" method="post" id="qcForm" <form th:action="'/ctp/quality-control/qc-finished-item'" method="post" id="qcForm"
th:object="${wrapper}"> th:object="${wrapper}">
<div class="bg-light p-3 mb-3"> <div class="bg-light p-3 mb-3">
<h6 class="mb-3">Search Stitched Item</h6>
<div class="form-row"> <div class="form-row">
<div class="col-sm-3 form-group"> <div class="col-sm-3 form-group">
<stitching-offline-item <search-item
v-on:stitching-offline-item-select="onItemSelect" label="Search Stitch Item"
></stitching-offline-item> url="/ctp/rest/stitching-offline-items/search"
v-on:finished-item-select="onItemSelect">
</search-item>
</div> </div>
<div class="col-sm-3 form-group"> <div class="col-sm-3 form-group">
<label>Finishing Account</label> <label>Finishing Account</label>

View File

@ -19,7 +19,7 @@
<div th:replace="_fragments :: table-loading-skeleton"></div> <div th:replace="_fragments :: table-loading-skeleton"></div>
<form th:action="@{/cutting/generate-barcodes}" method="post"> <form th:action="@{/cutting/generate-barcodes}" method="post">
<input hidden="hidden" name="artifactType" value="Bundle"> <input hidden="hidden" name="artifactType" value="Bundle">
<table class="table table-striped" data-table data-order="[[ 0, &quot;asc&quot; ]]"> <table class="table table-striped" data-table data-order="[[ 0, &quot;desc&quot; ]]">
<thead> <thead>
<tr> <tr>
<th>ID</th> <th>ID</th>

View File

@ -0,0 +1,113 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
/* Custom CSS for full height and center alignment of span */
.vertical-divider {
display: flex;
justify-content: center; /* Center horizontally */
align-items: center; /* Center vertically */
}
.vertical-divider span {
display: inline-block;
width: 1px;
background-color: #dee2e6;
height: 100%; /* Take full height of the parent div */
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-sm-12">
<table th:if="${#lists.size(transactions) != 0 && #lists != null }" class="table table-bordered font-sm mb-4" data-account-tables>
<thead>
<tr>
<th>ID</th>
<th>Item ID</th>
<th>SKU</th>
<th>QR Code</th>
<th>Created By</th>
<th>Created At</th>
<th>Bundle Id</th>
<th>QA Status</th>
</tr>
</thead>
<tbody>
<tr th:each="transaction : ${transactions}" th:object="${transaction}">
<td th:text="*{id}"></td>
<td th:text="*{itemId}"></td>
<td th:text="*{sku}"></td>
<td th:text="*{barcode}"></td>
<td th:text="*{createdBy}"></td>
<td th:text="*{createdAt}"></td>
<td th:text="*{bundleId}"></td>
<td>
<span th:if="*{ not isQa}" class="badge badge-danger">NOT PERFORMED</span>
<div th:if="*{isQa}">
<span class="badge badge-APPROVED">PERFORMED</span>
</div>
</td>
</tr>
<!-- More rows as needed -->
</tbody>
</table>
<h5 th:if="${#lists.size(transactions) == 0}" class="mt-2">No Inventory Transactions 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-account-tables]').each(function () {
const $table = $(this);
// Prevent reinitializing if already done
if (!$.fn.DataTable.isDataTable($table)) {
$table.DataTable({
pageLength: 5,
searching: true,
lengthChange: false,
processing: false,
dom: `
<'row'<'col-sm-5'B><'col-sm-7'f>>
<'row'<'col-sm-12't>>
<'row'<'col-sm-5'i><'col-sm-7'p>>`,
buttons: [{
extend: 'excel',
text: '',
className: 'bi bi-file-earmark-spreadsheet btn-sm d-none' // Keep it hidden
}]
});
}
});
(async function () {
const $selectAllCheckBox = $('[data-checkbox-all]');
$selectAllCheckBox.change(function () {
if ($selectAllCheckBox.prop('checked')) {
// When parent checkbox is checked, check all child checkboxes
$('[name="parent-doc-type-ids"]').each(function () {
let $this = $(this);
$this.prop('checked', true);
});
} else {
// When parent checkbox is unchecked, uncheck all child checkboxes
$('[name="parent-doc-type-ids"]').each(function () {
let $this = $(this);
$this.prop('checked', false);
});
}
});
})(jQuery)
</script>
</body>
</html>

View File

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

View File

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

View File

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.w3.org/1999/xhtml">
<head th:replace="_fragments :: head('Home Page')"></head>
<body>
<!-- sidebar starts -->
<aside class="col-sm-2" th:fragment="sidebar">
<div class="page-filters-sidebar">
<form th:action="@{${#strings.replace(#httpServletRequest.requestURI, #request.getContextPath(), '')}}">
<h5 class="mb-4">Refine Your Search</h5>
<div class="form-group" th:with="id=${param['site-id']},title=${param['site-title']}" data-vue-app>
<job-card-for-reporting th:attr="id=${id},title=${title}"
v-bind:id-field-name="'job-card-id'"
v-bind:title-field-name="'site-title'"
></job-card-for-reporting>
</div>
<input type="submit" class="btn btn-secondary btn-block" value="Search">
<a th:href="@{${#strings.replace(#httpServletRequest.requestURI, #request.getContextPath(), '')}}"
class="btn btn-secondary btn-block">Reset</a>
</form>
<div th:replace="_fragments :: page-footer-scripts"></div>
</div>
</aside>
</body>
</html>

View File

@ -0,0 +1,164 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.w3.org/1999/xhtml"
xmlns:ctp="http://www.w3.org/1999/xhtml">
<head th:replace="_fragments :: head('Job Card Report')"></head>
<body>
<div class="container-fluid">
<header class="row page-header" th:replace="_fragments :: page-header"></header>
<main class="row page-main">
<aside class="col-sm-2" th:replace="/reporting/job-card-report-sidebar :: sidebar"></aside>
<div class="col-sm">
<table class="table " >
<thead>
<tr th:if="${jobCardProgress == null}">
<th colspan="5" style="font-size:26px; text-align: center;">Please Select Job card</th>
</tr>
</thead>
<tbody>
<tr th:if="${jobCardProgress != null }">
<td style="padding:0px;">
<div style="border: 2px solid #d5d8dc; padding: 10px; border-radius: 10px; height: 370px;">
<h1 style="text-align: center;">Job Card Report</h1>
<div style="display: flex; align-items: center;">
<div style="text-align: center;margin-top: -45px">
<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="${completeProduction.get('Job Card Progress')}"
th:data-fontSize="30"
th:data-fontColor="'#17202a'"
th:data-color="'#566573'"></div>
</div>
<div style="display: flex; ">
<div th:each="title, index : ${jobCardProgress.keySet()}" style="text-align: center; margin-top: 40px;">
<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>
</div>
</div>
</td>
</tr>
<tr th:if="${phasesTimes != null }">
<td style="display: flex; flex-direction: column; align-items: center; border: none !important; outline: none;">
<div style="display: flex; gap: 10px;">
<div th:each="phase, index : ${phasesTimes.keySet()}" style="border: 2px solid #d5d8dc; border-radius: 10px; text-align: center; padding:20px;">
<H6 th:text="${phase}"></H6>
<H6 th:text="${phasesTimes.get(phase)}"></H6>
<H6 th:if="${pendingStatus.get(phase) != null}" th:text="${pendingStatus.get(phase)}"></H6>
</div>
</div>
</td>
</tr>
<tr>
<!-- Cutting Details Column -->
<td th:if="${cuttingDetails != null && cuttingDetails.get('accounts') != null}" style="padding: 0px; text-align: center;">
<div style="background-color: black; color: white; padding: 10px; font-size: 18px; font-weight: bold; text-align: center;">
Cutting Detail
</div>
<table class="table" style="width: 100%; border-collapse: collapse;">
<thead>
<tr>
<th>ID</th>
<th>Title</th>
<th>Cutting</th>
<th>Cutting Date</th>
<th>Cutting Table Descriptions</th>
</tr>
</thead>
<tbody>
<tr th:if="${cuttingDetails != null}" th:each="detail, index : ${cuttingDetails.get('accounts').keySet()}">
<td th:text="${cuttingDetails.get('accounts').get(detail).id}"></td>
<td th:text="${cuttingDetails.get('accounts').get(detail).title}"></td>
<td th:text="${cuttingDetails.get('personName').get(detail)}"></td>
<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>
</tbody>
</table>
</td>
<!-- Stitching Details Column -->
<td th:if="${stitchingDetails != null && stitchingDetails.get('accounts') != null}" style="padding: 0px; text-align: center;">
<div style="background-color: black; color: white; padding: 10px; font-size: 18px; font-weight: bold; text-align: center;">
Stitching Detail
</div>
<table class="table" style="width: 100%; border-collapse: collapse;">
<thead>
<tr>
<th>ID</th>
<th>Title</th>
<th>Stitching</th>
<th>Stitching Day</th>
<th>Stitching Table Descriptions</th>
</tr>
</thead>
<tbody th:if="${stitchingDetails != null and stitchingDetails.get('accounts') != null}">
<tr th:each="detail : ${stitchingDetails.get('accounts').keySet()}">
<td th:text="${stitchingDetails.get('accounts').get(detail).id}"></td>
<td th:text="${stitchingDetails.get('accounts').get(detail).title}"></td>
<td th:text="${stitchingDetails.get('personName') != null ? stitchingDetails.get('personName').get(detail) : ''}"></td>
<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>
</tbody>
</table>
</td>
</tr>
<tr th:if="${dailyProgress != null}">
<td colspan="5" style="padding-left: 150px;">
<div style="border: 2px solid #d5d8dc; padding-top: 10px; border-radius: 10px; height: 560px; width: 80%; overflow-x: auto;">
<div 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>
</td>
</tr>
</tbody>
</table>
</div>
</main>
</div>
<!-- Load JavaScript file -->
<script th:src="@{/js/charts.js}"></script>
</body>
</html>

View File

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

View File

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:uind="http://www.w3.org/1999/xhtml"
xmlns:ctp="http://www.w3.org/1999/xhtml">
<head th:replace="_fragments :: head('POs Job Card Details')"></head>
<body>
<div class="container-fluid">
<header class="row page-header" th:replace="_fragments :: page-header"></header>
<main class="row page-main">
<aside class="col-sm-2" th:replace="/reporting/po-job-card-report-sidebar :: sidebar"></aside>
<div class="col-sm">
<table class="table">
<tbody>
<tr th:if="${allJobCard != null}" th:each="jobCard : ${allJobCard.keySet()}" style="padding-bottom:10px">
<td class="m-0 pb-3">
<table class="table mb-0 table-bordered text-center">
<thead>
<tr>
<th colspan="10" class="text-center bg-dark text-white">
<span th:text="${jobCard}"></span>
</th>
</tr>
<tr>
<th th:each="headings : ${allJobCard.get(jobCard).keySet()}" th:text="${headings}"></th>
</tr>
</thead>
<tbody>
<tr>
<td >
<span style="font-size: 14px; font-weight: bold;" th:text="'Total : ' + ${allJobCard.get(jobCard).get('Cutting Progress')}"></span>
<br>
<span style="font-size: 14px; font-weight: bold;" th:text="'Complete Products : ' + ${allJobCard.get(jobCard).get('Job Card Progress')}"></span>
</td>
<td style="font-size: 14px;" th:if="${values != 'Job Card Progress'}" th:each="values : ${allJobCard.get(jobCard).keySet()}" th:text="${allJobCard.get(jobCard).get(values)}"></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</main>
</div>
<div th:replace="_fragments :: page-footer-scripts"></div>
</body>
</html>

View File

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

View File

@ -0,0 +1,65 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.w3.org/1999/xhtml"
xmlns:ctp="http://www.w3.org/1999/xhtml">
<head th:replace="_fragments :: head('PO Report')"></head>
<body>
<div class="container-fluid">
<header class="row page-header" th:replace="_fragments :: page-header"></header>
<main class="row page-main">
<aside class="col-sm-2" th:replace="/reporting/po-report-sidebar :: sidebar"></aside>
<div class="col-sm">
<h3>PO's Report</h3>
<div th:replace="_notices :: page-notices"></div>
<div th:replace="_fragments :: table-loading-skeleton"></div>
<table class="table table-striped font-sm" data-table data-order="[[ 0, &quot;asc&quot; ]]">
<thead>
<tr>
<th>PO Number</th>
<th>PO Article</th>
<th>PO Quantity</th>
<th>Cutting</th>
<th>Cutting Balance</th>
<th>Stitching</th>
<th>Stitching Balance</th>
<th>End Line QC</th>
<th>End Line QC Balance</th>
<th>Finishing Items</th>
<th>Finishing Items Balance</th>
<th>A Grade Items</th>
<th>B Grade Items</th>
<th>C Grade Items</th>
</tr>
</thead>
<tbody>
<!-- Dummy data for testing purposes -->
<tr th:each="poDetail : ${allPOs}">
<td><a class="text-reset" th:href="@{'/reporting/po-report-view/' + ${poDetail.poNumber}}" th:text="${poDetail.poNumber}"></a></td>
<td th:text="${poDetail.articleTitle}"></td>
<td th:text="${poDetail.poQuantity}"></td>
<td th:text="${poDetail.totalCutting}"></td>
<td th:text="${poDetail.remainingCutting}"></td>
<td th:text="${poDetail.totalStitching}"></td>
<td th:text="${poDetail.remainingStitching}"></td>
<td th:text="${poDetail.totalEndLineQC}"></td>
<td th:text="${poDetail.remainingEndLineQC}"></td>
<td th:text="${poDetail.totalFinishing}"></td>
<td th:text="${poDetail.remainingFinishing}"></td>
<td th:text="${poDetail.totalAGradeItem}"></td>
<td th:text="${poDetail.totalBGradeItem}"></td>
<td th:text="${poDetail.totalCGradeItem}"></td>
</tr>
</tbody>
</table>
<!-- <h4 th:if="${#lists.size(cards) == 0 }">No cards found.</h4>-->
</div>
</main>
</div>
<div th:replace="_fragments :: page-footer-scripts"></div>
<script th:src="@{/js/summary.js}"></script>
</body>
</html>

View File

@ -0,0 +1,132 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.w3.org/1999/xhtml"
xmlns:ctp="http://www.w3.org/1999/xhtml">
<head th:replace="_fragments :: head('Stitching Report')"></head>
<body>
<div class="container-fluid">
<header class="row page-header" th:replace="_fragments :: page-header"></header>
<main class="row page-main">
<aside class="col-sm-2" th:replace="/reporting/cutting-report-sidebar :: sidebar"></aside>
<div class="col-lg-10">
<div th:if="${stitching.get('Date Wise Stitching') != null}" style="padding-left: 150px;">
<div style="border: 2px solid #d5d8dc; padding-top: 10px; border-radius: 10px; height: 560px; width: 80%; overflow-x: auto;">
<div id="singleBarChart" class="singleBarChart" style="height: 500px; width: 1600px;"
th:data-width="1600"
th:data-height="500"
th:data-title="'Days Wise Progress'"
th:data-dates="${stitching.get('Date Wise Stitching').keySet()}"
th:data-barData="${stitching.get('Date Wise Stitching').values()}"
th:data-barHeading="'Stitching'"
th:data-stitching="''"
th:data-quality="''"
th:data-finishing="''"
th:data-totalProduction="'500'"
th:data-fontSize="30"
></div>
</div>
</div>
<div class="mt-3" th:if="${stitching.get('stitchingAccount') != null && stitching.get('jobCardItemsStitchingDetailsMap').get(stitchingAccount.id) != null}"
th:each="stitchingAccount, index : ${stitching.get('stitchingAccount')}">
<div class="bg-dark text-white py-2 px-3 fs-5 fw-bold text-center mb-2"
th:text="${stitchingAccount.title}"></div>
<table class="table table-striped " data-account-table th:data-account-id="${stitchingAccount.id}">
<thead>
<tr>
<th></th>
<th>Job Card</th>
<th>PO Number</th>
<th>SKU</th>
<th>Article Name</th>
<th>Stitching Operator Name</th>
<th>Total Stitching</th>
</tr>
</thead>
<tbody>
<tr th:each="wrap, index : ${stitching.get('jobCardItemsStitchingDetailsMap').get(stitchingAccount.id)}">
<td data-show-dropdown-transactions
th:data-account-id="${stitchingAccount.id}"
th:data-jobcardid="${wrap.jobCardId}"
th:data-sku="${wrap.sku}"
th:data-start-date="${param['start-date'] ?: startDate}"
th:data-end-date="${param['end-date'] ?: endDate}"
title="Transactions">
<span data-dropdown-icon-transactions class="bi bi-caret-right-fill"></span>
</td>
<td th:text="${wrap.jobCardCode}"></td>
<td th:text="${wrap.poName}"></td>
<td th:text="${wrap.sku}"></td>
<td th:text="${wrap.articleName}"></td>
<td th:text="${wrap.operatorName}"></td>
<td th:text="${stitching.get('totalStitchingBasedOnAccountID').get(wrap.jobCardId+wrap.sku)}"></td>
</tr>
</tbody>
</table>
</div>
</div>
</main>
</div>
<script>
const $body = $('body');
// Initialize DataTables for each individual table
$('table[data-account-table]').each(function () {
$(this).DataTable({
paging: false,
pageLength: 100,
searching: false,
lengthChange: false,
processing: false,
dom: `
<'row'<'col-sm-5'B><'col-sm-7'f>>
<'row'<'col-sm-12't>>
<'row'<'col-sm-5'i><'col-sm-7'p>>`,
buttons: [{
extend: 'excel',
text: '',
className: 'bi bi-file-earmark-spreadsheet btn-sm d-none'
}]
});
});
// Dropdown transactions toggle
$body.on('click', '[data-show-dropdown-transactions]', 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 = $this.find('[data-dropdown-icon-transactions]');
const accountId = $this.data('account-id');
const jobCardId = $this.data('jobcardid');
const sku = $this.data('sku');
const startDate = $this.data('start-date');
const endDate = $this.data('end-date');
$spanDropdown.toggleClass('bi-caret-right-fill bi-caret-down-fill');
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/reporting/inventory-transactions?account-id=${accountId}&jobCard-id=${jobCardId}&sku=${sku}&startDate=${startDate}&endDate=${endDate}`,
success: function (data) {
$row.child(data).show();
}
});
}
});
</script>
<!-- Load JavaScript file -->
<script th:src="@{/js/charts.js}"></script>
</body>
</html>

View File

@ -20,8 +20,8 @@
<input type="text" class="form-control" name="sku" maxlength="100" th:value="${param['sku']}"> <input type="text" class="form-control" name="sku" maxlength="100" th:value="${param['sku']}">
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Master Bundle ID</label> <label>Bundle ID</label>
<input type="text" class="form-control" name="job-card-id" maxlength="100" th:value="${param['job-card-id']}"> <input type="number" class="form-control" min="0" name="bundle-id" th:value="${param['bundle-id']}">
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Start Date</label> <label>Start Date</label>

View File

@ -20,11 +20,12 @@
<form th:action="@{/stitching/generate-barcodes}" method="post"> <form th:action="@{/stitching/generate-barcodes}" method="post">
<input hidden="hidden" name="artifactType" value="FinishedItem"> <input hidden="hidden" name="artifactType" value="FinishedItem">
<table th:if="${ #lists != null && #lists.size(items) != 0 }" class="table table-striped table-bordered" data-table <table th:if="${ #lists != null && #lists.size(items) != 0 }" class="table table-striped table-bordered" data-table
data-order="[[ 0, &quot;asc&quot; ]]"> data-order="[[ 0, &quot;desc&quot; ]]">
<thead> <thead>
<tr> <tr>
<th>ID</th> <th>ID</th>
<th>Item ID</th> <th>Item ID</th>
<th>Bundle ID</th>
<th>Sku</th> <th>Sku</th>
<th>Created At</th> <th>Created At</th>
<th>Created By</th> <th>Created By</th>
@ -41,6 +42,7 @@
<tr th:each="item : ${items}" th:object="${item}"> <tr th:each="item : ${items}" th:object="${item}">
<td th:text="*{id}"></td> <td th:text="*{id}"></td>
<td th:text="*{itemId}"></td> <td th:text="*{itemId}"></td>
<td th:text="*{bundleId}"></td>
<td th:text="*{sku}"></td> <td th:text="*{sku}"></td>
<td ctp:formatdatetime="*{createdAt}"></td> <td ctp:formatdatetime="*{createdAt}"></td>
<td th:text="*{createdBy}"></td> <td th:text="*{createdBy}"></td>