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; public InventoryService( JobCardItemDAO jobCardItemDAO, CutPieceDAO cutPieceDAO, BundleDAO bundleDAO, InventoryTransactionLegDAO inventoryTransactionLegDAO, InventoryTransactionDAO inventoryTransactionDAO, JobCardDAO jobCardDAO, CryptographyService cryptographyService, MasterBundleDAO masterBundleDAO, FinishedItemDAO finishedItemDAO, StitchingOfflineItemDAO stitchingOfflineItemDAO) { 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; } 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 ) { 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 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 ( stitchingOfflineItem.getQaStatus( ).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.setStitchedItemId( stitchingOfflineItem.getId( )); finishedItem.setJobCardId( stitchingOfflineItem.getJobCardId( )); finishedItem.setIsQa( false); 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); // 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, stitchingOfflineItem, fromAccount, InventoryTransactionLeg.Type.OUT.name( ), InventoryArtifactType.FINISHED_ITEM.name( )); } // create IN in finishing Account Finished Item finishedItems.add( preCreatedItem ); } } } for ( FinishedItem finishedItem : finishedItems) { // IN createInventoryTransactionLeg( transaction, finishedItem, wrapper.getFinishedAccountId( ), InventoryTransactionLeg.Type.IN.name( ), InventoryArtifactType.FINISHED_ITEM.name( )); } // save updated stitched items stitchingOfflineItemDAO.saveAll( wrapper.getItems( )); } } /* * segregate finish items * */ @Transactional( rollbackFor = Exception.class, propagation = Propagation.NESTED ) public void segregateFinishedItems( FinishedItemWrapper wrapper) { 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); /* * item is not approved and washed is selected then item remain in Finishing account * */ /* * item is approved and alter is selected then finished item will to stitching account * */ if ( finishedItem.getQaStatus( ).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( )); } } /* * item is approved and grade is selected then fI is move to grade account */ if ( finishedItem.getQaStatus( ).equalsIgnoreCase( "APPROVED") && finishedItem.getAccountId( ) != 0) { // 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 createInventoryTransactionLeg( transaction, finishedItem, finishedItem.getAccountId( ), InventoryTransactionLeg.Type.IN.name( ), InventoryArtifactType.FINISHED_ITEM.name( )); } finishedItem.setIsSegregated( true); } updatedItems.add( finishedItem); } finishedItemDAO.saveAll( updatedItems); // save finish items } } /* * find item summary by account * */ public List findItemSummaryByAccountId( long accountId) { return inventoryTransactionLegDAO.findSummaryByAccountId( accountId); } }