package com.utopiaindustries.service; import com.utopiaindustries.dao.ctp.*; import com.utopiaindustries.model.ctp.*; import com.utopiaindustries.model.ctp.BundleWrapper; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @Service public class InventoryService { private final JobCardItemDAO jobCardItemDAO; private final CutPieceDAO cutPieceDAO; private final BundleDAO bundleDAO; private final InventoryTransactionLegDAO inventoryTransactionLegDAO; private final InventoryTransactionDAO inventoryTransactionDAO; private final JobCardDAO jobCardDAO; private final CryptographyService cryptographyService; private final MasterBundleDAO masterBundleDAO; private final FinishedItemDAO finishedItemDAO; private final StitchingOfflineItemDAO stitchingOfflineItemDAO; private final PackagingItemsDAO packagingItemsDAO; public InventoryService(JobCardItemDAO jobCardItemDAO, CutPieceDAO cutPieceDAO, BundleDAO bundleDAO, InventoryTransactionLegDAO inventoryTransactionLegDAO, InventoryTransactionDAO inventoryTransactionDAO, JobCardDAO jobCardDAO, CryptographyService cryptographyService, MasterBundleDAO masterBundleDAO, FinishedItemDAO finishedItemDAO, StitchingOfflineItemDAO stitchingOfflineItemDAO, PackagingItemsDAO packagingItemsDAO) { this.jobCardItemDAO = jobCardItemDAO; this.cutPieceDAO = cutPieceDAO; this.bundleDAO = bundleDAO; this.inventoryTransactionLegDAO = inventoryTransactionLegDAO; this.inventoryTransactionDAO = inventoryTransactionDAO; this.jobCardDAO = jobCardDAO; this.cryptographyService = cryptographyService; this.masterBundleDAO = masterBundleDAO; this.finishedItemDAO = finishedItemDAO; this.stitchingOfflineItemDAO = stitchingOfflineItemDAO; this.packagingItemsDAO = packagingItemsDAO; } private void updateJobCardInventoryStatus(JobCard card) { List items = jobCardItemDAO.findByCardId(card.getId()); for (JobCardItem item : items) { // check if item is received if (item.getActualProduction() == null || item.getActualProduction().compareTo(BigDecimal.ZERO) == 0) { return; } } card.setInventoryStatus(JobCard.InventoryStatus.RECEIVED.name()); jobCardDAO.save(card); } /* * receive inv from job card * */ @Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED) public void receiveJobCardInventory(long jobCardId, JobCardWrapper jobCardWrapper) { if (jobCardId == 0 || jobCardWrapper.getItems() == null || jobCardWrapper.getItems().isEmpty()) { throw new RuntimeException(" JobCard can`t be empty"); } JobCard jobCard = jobCardDAO.find(jobCardId); // get job cad items List jobCardItemWrappers = jobCardWrapper.getItems(); List jobCardItemWrapperIds = jobCardItemWrappers.stream() .map(JobCardItemWrapper::getJobCardItemId) .collect(Collectors.toList()); Map jobCardItemIdToActualProdMap = jobCardItemWrappers.stream() .collect(Collectors.toMap(JobCardItemWrapper::getJobCardItemId, JobCardItemWrapper::getActualProduction)); List items = jobCardItemDAO.findByIds(jobCardItemWrapperIds); if (items != null && !items.isEmpty()) { // get job card item ids List jobCardItemIds = items.stream() .map(JobCardItem::getId) .collect(Collectors.toList()); // save updated cut pieces // List cutPieces = jobCardItemWrappers.stream() // .flatMap(wrapper -> wrapper.getPieces().stream()) // .collect(Collectors.toList()); // cutPieceDAO.saveAll(cutPieces); // Map> piecesMap = cutPieceDAO.findByJobCardItemIds(jobCardItemIds) // .stream() // .collect(Collectors.groupingBy(CutPiece::getJobCardItemId)); for (JobCardItem jobCardItem : items) { 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 bundles = createBundles(jobCardItem, quantity, jobCardItemIdToActualProdMap.getOrDefault(jobCardItem.getId(), BigDecimal.ZERO)); // create transactions createTransactions(bundles, jobCardItem.getAccountId(), InventoryArtifactType.BUNDLE.name()); jobCardItem.setActualProduction(jobCardItemIdToActualProdMap.getOrDefault(jobCardItem.getId(), BigDecimal.ZERO).add(jobCardItem.getActualProduction())); jobCardItem.setComplete(cuttingComplete); } // update items with quantity jobCardItemDAO.saveAll(items); // update job card inv status if (jobCardItemDAO.checkAllItemsComplete(jobCardId, jobCardItemIds)) { updateJobCardInventoryStatus(jobCard); } } else { throw new RuntimeException("Items Not found in Job Card"); } } /* * t create transactions * */ private void createTransactions(List artifacts, long accountId, String parentDocumentType) { if (!artifacts.isEmpty()) { InventoryTransaction transaction = createInventoryTransaction("Transaction Against " + parentDocumentType); for (InventoryArtifact artifact : artifacts) { InventoryTransactionLeg leg = createInventoryTransactionLeg(transaction, artifact, accountId, InventoryTransactionLeg.Type.IN.name(), parentDocumentType); } } } /* * create and save transaction * */ private InventoryTransaction createInventoryTransaction(String notes) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); InventoryTransaction transaction = new InventoryTransaction(); transaction.setGeneratedBy(authentication.getName()); transaction.setTransactionDateTime(LocalDateTime.now()); transaction.setNotes(notes); transaction.setId(inventoryTransactionDAO.save(transaction)); return transaction; } /* * create and save inventory transaction * */ private InventoryTransactionLeg createInventoryTransactionLeg(InventoryTransaction transaction, InventoryArtifact artifact, long accountId, String transactionType, String parentDocumentType) { InventoryTransactionLeg inventoryTransactionLeg = new InventoryTransactionLeg(); inventoryTransactionLeg.setTransactionId(transaction.getId()); inventoryTransactionLeg.setType(transactionType); inventoryTransactionLeg.setQuantity(BigDecimal.valueOf(1L)); inventoryTransactionLeg.setAccountId((int) accountId); inventoryTransactionLeg.setItemId(artifact.getItemId()); inventoryTransactionLeg.setSku(artifact.getSku()); inventoryTransactionLeg.setParentDocumentType(parentDocumentType); inventoryTransactionLeg.setParentDocumentId(artifact.getId()); inventoryTransactionLeg.setParentDocumentPieceType(artifact.getType()); inventoryTransactionLeg.setTransactionLegDateTime(LocalDateTime.now()); inventoryTransactionLeg.setJobCardId(artifact.getJobCardId()); // set balance BigDecimal initialBalance = calculateBalance(accountId, artifact.getItemId(), parentDocumentType, artifact.getType()); if (transactionType.equalsIgnoreCase(InventoryTransactionLeg.Type.IN.name())) { initialBalance = initialBalance.add(inventoryTransactionLeg.getQuantity()); } else if (transactionType.equalsIgnoreCase(InventoryTransactionLeg.Type.OUT.name())) { if (inventoryTransactionLeg.getQuantity().equals(BigDecimal.ZERO)) { initialBalance = BigDecimal.ZERO; } else { initialBalance = initialBalance.subtract(inventoryTransactionLeg.getQuantity()); } } inventoryTransactionLeg.setBalance(initialBalance); inventoryTransactionLeg.setId(inventoryTransactionLegDAO.save(inventoryTransactionLeg)); return inventoryTransactionLeg; } // calculate balance private BigDecimal calculateBalance(long accountId, long itemId, String parentType, String pieceType) { // find the last transaction leg of the current account Id with itemId InventoryTransactionLeg lastTransactionLeg = inventoryTransactionLegDAO.findLastByAccountIdAndItemIdAndParentType(accountId, itemId, parentType, pieceType); if (lastTransactionLeg.getBalance() != null) { return lastTransactionLeg.getBalance(); } return BigDecimal.ZERO; } // create bundles from cut pieces private List createBundles(JobCardItem jobCardItem, int perBundleWrap, BigDecimal value) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (value != null && !value.equals(BigDecimal.ZERO)) { List bundles = new ArrayList<>(); int quantity = value.intValue(); int batchSize = perBundleWrap; int iterations = (int) Math.ceil((double) quantity / batchSize); for (int i = 0; i < iterations; i++) { int start = i * batchSize + 1; // Start index int end = Math.min((i + 1) * batchSize, quantity); // Last index int perBundleQuantity = end - start + 1; Bundle bundle = new Bundle(); bundle.setItemId(jobCardItem.getItemId()); bundle.setSku(jobCardItem.getSku()); bundle.setJobCardId(jobCardItem.getJobCardId()); bundle.setWrapQuantity(BigDecimal.valueOf(perBundleQuantity)); 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)); } // for ( Map.Entry> entry : jobCardItemPieces ) { // JobCardItem key = entry.getKey( ); // List value = entry.getValue( ); // // // } return bundles; } return new ArrayList<>(); } /* * receive inventory from master barcode * */ @Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED) public void receiveInventoryFromMasterBarcode(long masterId, long toAccount) { if (masterId == 0 || toAccount == 0) { throw new RuntimeException("Master Barcode | Account can`t be empty"); } MasterBundle masterBundle = masterBundleDAO.find(masterId); // find bundles from master barcode List bundles = bundleDAO.findByMasterId(masterId); if (bundles != null && !bundles.isEmpty()) { // bundle ids List bundleIds = bundles.stream().map(Bundle::getId).collect(Collectors.toList()); Map lastBundleIdInTransactionMap = inventoryTransactionLegDAO .findLastTransactionByParentIdAndParentType(InventoryTransactionLeg.Type.IN.name(), bundleIds, InventoryArtifactType.BUNDLE.name()) .stream() .collect(Collectors.toMap(InventoryTransactionLeg::getParentDocumentId, Function.identity())); // create Transaction InventoryTransaction transaction = createInventoryTransaction("Against Movement from Cutting to Stitching"); inventoryTransactionDAO.save(transaction); // create transaction legs for (Bundle bundle : bundles) { InventoryTransactionLeg lastInvTransaction = lastBundleIdInTransactionMap.getOrDefault(bundle.getId(), null); if (lastInvTransaction != null) { // OUT long fromAccount = lastInvTransaction.getAccountId(); createInventoryTransactionLeg(transaction, bundle, fromAccount, InventoryTransactionLeg.Type.OUT.name(), InventoryArtifactType.BUNDLE.name()); // IN bundle.setType("BUNDLE"); createInventoryTransactionLeg(transaction, bundle, toAccount, InventoryTransactionLeg.Type.IN.name(), InventoryArtifactType.STITCH_BUNDLE.name()); } } // update status masterBundle.setIsReceived(true); masterBundle.setAccountId(toAccount); masterBundleDAO.save(masterBundle); } } private void validateItems(List cardItems) { if (cardItems == null || cardItems.isEmpty()) { throw new RuntimeException("Item cant be Empty | null"); } for (JobCardItem jobCardItem : cardItems) { if (jobCardItem.getTotalProduction() != null) { int finalQuantity = jobCardItem.getActualProduction().compareTo(jobCardItem.getTotalProduction().add(jobCardItem.getProduction())); if (finalQuantity < 0) { throw new RuntimeException(" Items cant be generated because it exceeds from limit of expected Production"); } } } } private void checkAllBundleAreReceived(long jobCardId, List jobCardItems) { if (jobCardItems != null && !jobCardItems.isEmpty()) { List itemIds = jobCardItems.stream() .filter(JobCardItem::getIsSelected) .map(JobCardItem::getItemId).collect(Collectors.toList()); List bundles = bundleDAO.findByItemIdsAndCardId(itemIds, jobCardId); List masterBundleIds = bundles.stream().map(Bundle::getMasterBundleId).collect(Collectors.toList()); Map idToMasterBundleMap = masterBundleDAO.findByIds(masterBundleIds) .stream() .collect(Collectors.toMap(MasterBundle::getId, Function.identity())); for (Bundle bundle : bundles) { // check all bundles are received MasterBundle masterBundle = idToMasterBundleMap.getOrDefault(bundle.getMasterBundleId(), null); if (masterBundle == null || !masterBundle.getIsReceived()) { throw new RuntimeException("Please Receive Bundles Against Master Bundles First to Create Finished Item"); } } } } /* * create finished items from master bundles * */ @Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED) public void createStitchingOfflineItemsFromJobCard(BundleWrapper wrapper) { List updatedItems = new ArrayList<>(); List updateBundles = new ArrayList<>(); JobCard jobCard = null; //switching table transaction in Transaction Table InventoryTransaction transaction = createInventoryTransaction("Against Movement from Stitching to Stitched Offline Item"); inventoryTransactionDAO.save(transaction); //TransactionLeg Transaction List bundleIds = wrapper.getBundles().stream().map(Bundle::getId).collect(Collectors.toList()); Map lastBundleIdInTransactionMap = inventoryTransactionLegDAO .findLastTransactionByParentIdAndParentType(InventoryTransactionLeg.Type.IN.name(), bundleIds, InventoryArtifactType.STITCH_BUNDLE.name()) .stream() .collect(Collectors.toMap(InventoryTransactionLeg::getParentDocumentId, Function.identity())); for (Bundle subBundle : wrapper.getBundles()) { long accountId = masterBundleDAO.find(subBundle.getMasterBundleId()).getAccountId(); if (subBundle.getCurrentProduction() != null && subBundle.getCurrentProduction().compareTo(BigDecimal.ZERO) != 0) { Bundle bundle = bundleDAO.find(subBundle.getId()); jobCard = jobCardDAO.find(subBundle.getJobCardId()); long production = (bundle.getProduction() == null) ? 0 : bundle.getProduction().longValue(); long wrapQuantity = bundle.getWrapQuantity().longValue(); JobCardItem jobCardItem = jobCardItemDAO.findByCardIdAndItemId(subBundle.getJobCardId(), subBundle.getItemId()); BigDecimal previousTotalProduction = jobCardItem.getTotalProduction() == null ? BigDecimal.ZERO : jobCardItem.getTotalProduction(); InventoryTransactionLeg lastInvTransaction = lastBundleIdInTransactionMap.getOrDefault(subBundle.getId(), null); if (lastInvTransaction != null) { if (wrapQuantity == production + subBundle.getCurrentProduction().longValue()) { // OUT long fromAccount = lastInvTransaction.getAccountId(); createInventoryTransactionLeg(transaction, subBundle, accountId, InventoryTransactionLeg.Type.OUT.name(), InventoryArtifactType.STITCH_BUNDLE.name()); } } // create stitchingOfflineItems items List stitchingOfflineItems = createStitchingOfflineItems(subBundle.getCurrentProduction(), jobCardItem, subBundle.getId()); // create IN Transactions of Finished Items into account createTransactions(stitchingOfflineItems, accountId, InventoryArtifactType.STITCHING_OFFLINE.name()); jobCardItem.setTotalProduction(previousTotalProduction.add(subBundle.getCurrentProduction())); jobCardItem.setJobCardId(jobCard.getId()); updatedItems.add(jobCardItem); BigDecimal pro = BigDecimal.valueOf(production + subBundle.getCurrentProduction().longValue()); bundle.setProduction(pro); bundleDAO.save(bundle); } } jobCardItemDAO.saveAll(updatedItems); } /* * create finished items * */ public List createStitchingOfflineItems(BigDecimal totalItem, JobCardItem jobCardItem, long bundleId) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); List items = new ArrayList<>(); if (jobCardItem != null) { for (int i = 1; i <= totalItem.intValue(); i++) { StitchingOfflineItem stitchingOfflineItem = new StitchingOfflineItem(); stitchingOfflineItem.setCreatedAt(LocalDateTime.now()); stitchingOfflineItem.setCreatedBy(authentication.getName()); stitchingOfflineItem.setItemId(jobCardItem.getItemId()); stitchingOfflineItem.setSku(jobCardItem.getSku()); stitchingOfflineItem.setBundleId(bundleId); stitchingOfflineItem.setJobCardId(jobCardItem.getJobCardId()); stitchingOfflineItem.setIsQa(false); long id = stitchingOfflineItemDAO.save(stitchingOfflineItem); stitchingOfflineItem.setId(id); stitchingOfflineItem.setBarcode(cryptographyService.generateRandomString(15)); stitchingOfflineItemDAO.save(stitchingOfflineItem); items.add(stitchingOfflineItem); } } return items; } /* * find transactions by account id * */ public List findTransactionByAccountId(long accountId) { List legs = inventoryTransactionLegDAO.findByAccountId(accountId); List tIds = legs.stream().map(InventoryTransactionLeg::getTransactionId).collect(Collectors.toList()); Map idToTransactioMap = inventoryTransactionDAO.findByIds(tIds).stream().collect(Collectors.toMap(InventoryTransaction::getId, Function.identity())); legs.forEach(leg -> leg.setTransaction(idToTransactioMap.get(leg.getTransactionId()))); return legs; } /* * * */ @Transactional(rollbackFor = Exception.class) public void markFinishedItemsApproved(List fItemIds, long toAccount) { if (fItemIds.isEmpty() || toAccount == 0) { throw new RuntimeException("Finished Item Ids | Account can`t be empty"); } List finishedItems = finishedItemDAO.findByIds(fItemIds); if (finishedItems != null && !finishedItems.isEmpty()) { // bundle ids List finishedItemIds = finishedItems.stream().map(FinishedItem::getId).collect(Collectors.toList()); Map lastBundleIdInTransactionMap = inventoryTransactionLegDAO .findLastTransactionByParentIdAndParentType(InventoryTransactionLeg.Type.IN.name(), finishedItemIds, InventoryArtifactType.STITCHING_OFFLINE.name()) .stream() .collect(Collectors.toMap(InventoryTransactionLeg::getParentDocumentId, Function.identity())); // create Transaction InventoryTransaction transaction = createInventoryTransaction("Against Movement from Stitching to Packaging After QA"); inventoryTransactionDAO.save(transaction); // create transaction legs for (FinishedItem finishedItem : finishedItems) { InventoryTransactionLeg lastInvTransaction = lastBundleIdInTransactionMap.getOrDefault(finishedItem.getId(), null); if (lastInvTransaction != null) { // OUT long fromAccount = lastInvTransaction.getAccountId(); createInventoryTransactionLeg(transaction, finishedItem, fromAccount, InventoryTransactionLeg.Type.OUT.name(), InventoryArtifactType.STITCHING_OFFLINE.name()); // IN createInventoryTransactionLeg(transaction, finishedItem, toAccount, InventoryTransactionLeg.Type.IN.name(), InventoryArtifactType.STITCHING_OFFLINE.name()); } finishedItem.setIsQa(true); } finishedItemDAO.saveAll(finishedItems); } } /* * generate finished items against stitched items * */ @Transactional(rollbackFor = Exception.class) public void createFinishedItemsAgainstStitchedItems(StitchedItemWrapper wrapper, String qaStatus) { if (wrapper.getItems() != null && wrapper.getFinishedAccountId() != 0) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); List stitchingOfflineItems = wrapper.getItems(); List updatedStitchedItems = new ArrayList<>(); List finishedItems = new ArrayList<>(); List finishedItemsForUlter = new ArrayList<>(); List stitchedItemIds = stitchingOfflineItems.stream() .map(StitchingOfflineItem::getId) .collect(Collectors.toList()); Map lastStitchedIdInTransactionMap = inventoryTransactionLegDAO .findLastTransactionByParentIdAndParentType(InventoryTransactionLeg.Type.IN.name(), stitchedItemIds, InventoryArtifactType.STITCHING_OFFLINE.name()) .stream() .collect(Collectors.toMap(InventoryTransactionLeg::getParentDocumentId, Function.identity())); // get finished items from stitched items if exists List preCreatedFinishedItemIds = finishedItemDAO.findByStitchedItemIds(stitchedItemIds).stream(). map(FinishedItem::getId).collect(Collectors.toList()); Map lastFinishedItemInTransactionMap = inventoryTransactionLegDAO .findLastTransactionByParentIdAndParentType(InventoryTransactionLeg.Type.IN.name(), preCreatedFinishedItemIds, InventoryArtifactType.FINISHED_ITEM.name()) .stream() .collect(Collectors.toMap(InventoryTransactionLeg::getParentDocumentId, Function.identity())); InventoryTransaction transaction = createInventoryTransaction("Against Movement From Stitching Offline to Finished Item"); // generate FI for SI for (StitchingOfflineItem stitchingOfflineItem : stitchingOfflineItems) { if (qaStatus.equalsIgnoreCase("APPROVED")) { // check finished item is already created FinishedItem preCreatedItem = finishedItemDAO.findByStitchedItem(stitchingOfflineItem.getId()); if (preCreatedItem == null) { FinishedItem finishedItem = new FinishedItem(); finishedItem.setItemId(stitchingOfflineItem.getItemId()); finishedItem.setSku(stitchingOfflineItem.getSku()); finishedItem.setBarcode(stitchingOfflineItem.getBarcode()); finishedItem.setCreatedBy(authentication.getName()); finishedItem.setCreatedAt(LocalDateTime.now()); finishedItem.setOperationDate(LocalDateTime.now()); finishedItem.setQaStatus("-"); finishedItem.setStitchedItemId(stitchingOfflineItem.getId()); finishedItem.setJobCardId(stitchingOfflineItem.getJobCardId()); finishedItem.setIsQa(true); finishedItem.setId(finishedItemDAO.save(finishedItem)); finishedItems.add(finishedItem); InventoryTransactionLeg lastInvTransaction = lastStitchedIdInTransactionMap.getOrDefault(stitchingOfflineItem.getId(), null); if (lastInvTransaction != null) { // OUT long fromAccount = lastInvTransaction.getAccountId(); createInventoryTransactionLeg(transaction, stitchingOfflineItem, fromAccount, InventoryTransactionLeg.Type.OUT.name(), InventoryArtifactType.STITCHING_OFFLINE.name()); } // update stitched item stitchingOfflineItem.setIsQa(true); stitchingOfflineItem.setQaStatus(qaStatus); updatedStitchedItems.add(stitchingOfflineItem); // if FI is already created } else { // create OUT from stitching account Finished Item InventoryTransactionLeg lastInvTransaction = lastFinishedItemInTransactionMap.getOrDefault(preCreatedItem.getId(), null); if (lastInvTransaction != null) { // OUT long fromAccount = lastInvTransaction.getAccountId(); createInventoryTransactionLeg(transaction, preCreatedItem, fromAccount, InventoryTransactionLeg.Type.OUT.name(), InventoryArtifactType.FINISHED_ITEM.name()); } stitchingOfflineItem.setIsQa(true); preCreatedItem.setIsQa(true); finishedItemsForUlter.add(preCreatedItem); // create IN in finishing Account Finished Item finishedItems.add(preCreatedItem); } } else { FinishedItem preCreatedItem = finishedItemDAO.findByStitchedItem(stitchingOfflineItem.getId()); if (preCreatedItem != null) { preCreatedItem.setIsQa(false); finishedItemsForUlter.add(preCreatedItem); } stitchingOfflineItem.setIsQa(false); } stitchingOfflineItem.setQaStatus(qaStatus); stitchingOfflineItem.setQcDoneAt(LocalDateTime.now()); updatedStitchedItems.add(stitchingOfflineItem); } for (FinishedItem finishedItem : finishedItems) { // IN createInventoryTransactionLeg(transaction, finishedItem, wrapper.getFinishedAccountId(), InventoryTransactionLeg.Type.IN.name(), InventoryArtifactType.FINISHED_ITEM.name()); } // save updated stitched items finishedItemDAO.saveAll(finishedItemsForUlter); stitchingOfflineItemDAO.saveAll(updatedStitchedItems); } } /* * segregate finish items * */ @Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED) public void segregateFinishedItems(FinishedItemWrapper wrapper, String status) { if (wrapper != null && wrapper.getItems() != null) { List items = wrapper.getItems(); List updatedItems = new ArrayList<>(); // finished ids List finishedItemIds = items.stream().map(FinishedItem::getId) .collect(Collectors.toList()); // stitched ids List stitchedItemIds = items.stream().map(FinishedItem::getStitchedItemId) .collect(Collectors.toList()); // create parent doc type last IN transaction map Map lastFinishedItemIdInTransactionMap = inventoryTransactionLegDAO .findLastTransactionByParentIdAndParentType(InventoryTransactionLeg.Type.IN.name(), finishedItemIds, InventoryArtifactType.FINISHED_ITEM.name()) .stream() .collect(Collectors.toMap(InventoryTransactionLeg::getParentDocumentId, Function.identity())); // create parent doc type last OUT transaction map Map lastStitchedItemOutTransactionMap = inventoryTransactionLegDAO .findLastTransactionByParentIdAndParentType(InventoryTransactionLeg.Type.OUT.name(), stitchedItemIds, InventoryArtifactType.STITCHING_OFFLINE.name()) .stream() .collect(Collectors.toMap(InventoryTransactionLeg::getParentDocumentId, Function.identity())); // create transaction InventoryTransaction transaction = createInventoryTransaction("Against Segregation of Finished Items"); // create IN and OUT for all approved items for (FinishedItem finishedItem : items) { InventoryTransactionLeg lastInvTransaction = lastFinishedItemIdInTransactionMap.getOrDefault(finishedItem.getId(), null); finishedItem.setIsQa(true); finishedItem.setOperationDate(LocalDateTime.now()); /* * item is approved and alter is selected then finished item will to stitching account * */ if (status.equalsIgnoreCase("ALTER")) { // create OUT and IN transactions for FI if (lastInvTransaction != null) { // OUT long fromAccount = lastInvTransaction.getAccountId(); createInventoryTransactionLeg(transaction, finishedItem, fromAccount, InventoryTransactionLeg.Type.OUT.name(), InventoryArtifactType.FINISHED_ITEM.name()); // IN // get the stitching account id long stitchedItemId = finishedItem.getStitchedItemId(); InventoryTransactionLeg lastOutTransaction = lastStitchedItemOutTransactionMap.getOrDefault(stitchedItemId, null); createInventoryTransactionLeg(transaction, finishedItem, lastOutTransaction.getAccountId(), InventoryTransactionLeg.Type.IN.name(), InventoryArtifactType.FINISHED_ITEM.name()); finishedItem.setQaStatus("ALTER"); finishedItem.setIsSegregated(false); } } /* * item is not approved and washed is selected then item remain in Finishing account * */ if (status.equalsIgnoreCase("WASHED")) { finishedItem.setIsSegregated(false); finishedItem.setQaStatus("WASHED"); } /* * item is not approved and B grade is selected then item remain in Finishing account because after * alteration item will be moved to A grade account for segregation * */ if (status.equalsIgnoreCase("B GRADE")) { finishedItem.setIsSegregated(false); finishedItem.setQaStatus("B GRADE"); } /* * item is not approved and C grade is selected then item remain in Finishing account because after * alteration item will be moved to A grade account for segregation * */ if (status.equalsIgnoreCase("REJECT")) { finishedItem.setIsSegregated(false); finishedItem.setQaStatus("REJECT"); } /* * item is approved and grade is selected then fI is move to grade account */ if (status.equalsIgnoreCase("APPROVED")) { finishedItem.setQaStatus("APPROVED"); finishedItem.setIsSegregated(true); } updatedItems.add(finishedItem); } // save finish items finishedItemDAO.saveAll(updatedItems); } } /* * Packaging items * */ @Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED) public void createPackagingItemAndTransaction(FinishedItemWrapper wrapper) { if (wrapper != null && wrapper.getItems() != null) { List items = wrapper.getItems(); List updatedItems = new ArrayList<>(); List packagingItems = new ArrayList<>(); // finished ids List finishedItemIds = items.stream().map(FinishedItem::getId) .collect(Collectors.toList()); // stitched ids List stitchedItemIds = items.stream().map(FinishedItem::getStitchedItemId) .collect(Collectors.toList()); // find parent doc type last IN transaction map Map lastFinishedItemIdInTransactionMap = inventoryTransactionLegDAO .findLastTransactionByParentIdAndParentType(InventoryTransactionLeg.Type.IN.name(), finishedItemIds, InventoryArtifactType.FINISHED_ITEM.name()) .stream() .collect(Collectors.toMap(InventoryTransactionLeg::getParentDocumentId, Function.identity())); // create transaction InventoryTransaction transaction = createInventoryTransaction("Against Segregation of Finished Items"); // create IN and OUT for all approved items for (FinishedItem finishedItem : items) { InventoryTransactionLeg lastInvTransaction = lastFinishedItemIdInTransactionMap.getOrDefault(finishedItem.getId(), null); finishedItem.setIsQa(true); if (finishedItem.getQaStatus().equalsIgnoreCase("APPROVED") && finishedItem.getIsSegregated()) { // create OUT and IN transactions for FI PackagingItems packagingItems1 = (createPackagingItem(finishedItem)); packagingItems1.setId(packagingItemsDAO.save(packagingItems1)); if (lastInvTransaction != null) { // OUT long fromAccount = lastInvTransaction.getAccountId(); createInventoryTransactionLeg(transaction, finishedItem, fromAccount, InventoryTransactionLeg.Type.OUT.name(), InventoryArtifactType.FINISHED_ITEM.name()); // IN createInventoryTransactionLeg(transaction, packagingItems1, 8, InventoryTransactionLeg.Type.IN.name(), InventoryArtifactType.PACKAGING.name()); } finishedItem.setIsSegregated(true); finishedItem.setPackaging(true); packagingItems.add(packagingItems1); } updatedItems.add(finishedItem); } // save finish items finishedItemDAO.saveAll(updatedItems); packagingItemsDAO.saveAll(packagingItems); } } /* * find item summary by account * */ public List findItemSummaryByAccountId(long accountId) { return inventoryTransactionLegDAO.findSummaryByAccountId(accountId); } private PackagingItems createPackagingItem(FinishedItem finishedItem) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); PackagingItems packagingItems = new PackagingItems(); packagingItems.setItemId(finishedItem.getItemId()); packagingItems.setAccountId(finishedItem.getAccountId()); packagingItems.setFinishedItemId(finishedItem.getId()); packagingItems.setJobCardId(finishedItem.getJobCardId()); packagingItems.setJobCard(finishedItem.getJobCard()); packagingItems.setSku(finishedItem.getSku()); packagingItems.setBarcode(finishedItem.getBarcode()); packagingItems.setCreatedAt(LocalDateTime.now()); packagingItems.setCreatedBy(authentication.getName()); packagingItems.setIsQa(finishedItem.getIsQa()); packagingItems.setIsSegregated(finishedItem.getIsSegregated()); packagingItems.setQaStatus(finishedItem.getQaStatus()); return packagingItems; } }