cut-to-pack-service/src/main/java/com/utopiaindustries/service/InventoryService.java

626 lines
34 KiB
Java

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<JobCardItem> 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<JobCardItemWrapper> jobCardItemWrappers = jobCardWrapper.getItems( );
List<Long> jobCardItemWrapperIds = jobCardItemWrappers.stream( )
.map( JobCardItemWrapper::getJobCardItemId )
.collect( Collectors.toList( ) );
Map<Long,BigDecimal> jobCardItemIdToActualProdMap = jobCardItemWrappers.stream( )
.collect( Collectors.toMap( JobCardItemWrapper::getJobCardItemId, JobCardItemWrapper::getActualProduction ) );
List<JobCardItem> items = jobCardItemDAO.findByIds( jobCardItemWrapperIds );
if ( items != null && !items.isEmpty( ) ) {
// get job card item ids
List<Long> jobCardItemIds = items.stream( )
.map( JobCardItem::getId)
.collect( Collectors.toList( ));
// save updated cut pieces
List<CutPiece> cutPieces = jobCardItemWrappers.stream( )
.flatMap( wrapper -> wrapper.getPieces( ).stream( ) )
.collect( Collectors.toList( ) );
cutPieceDAO.saveAll( cutPieces );
Map<Long, List<CutPiece>> 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::getFinalReceived)
.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
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<? extends InventoryArtifact> 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( ));
// 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<Bundle> createBundles( JobCardItem jobCardItem,
int perBundleWrap, BigDecimal value ) {
Authentication authentication = SecurityContextHolder.getContext( ).getAuthentication( );
if ( value != null && !value.equals(BigDecimal.ZERO)) {
List<Bundle> 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<JobCardItem, List<CutPiece>> entry : jobCardItemPieces ) {
// JobCardItem key = entry.getKey( );
// List<CutPiece> 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<Bundle> bundles = bundleDAO.findByMasterId( masterId);
if ( bundles != null && !bundles.isEmpty( )) {
// bundle ids
List<Long> bundleIds = bundles.stream( ).map( Bundle::getId).collect( Collectors.toList( ));
Map<Long, InventoryTransactionLeg> 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<JobCardItem> 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<JobCardItem> jobCardItems) {
if ( jobCardItems != null && !jobCardItems.isEmpty( ) ) {
List<Long> itemIds = jobCardItems.stream( )
.filter( JobCardItem::getIsSelected )
.map( JobCardItem::getItemId).collect( Collectors.toList( ));
List<Bundle> bundles = bundleDAO.findByItemIdsAndCardId( itemIds, jobCardId);
List<Long> masterBundleIds = bundles.stream( ).map( Bundle::getMasterBundleId).collect( Collectors.toList( ));
Map<Long, MasterBundle> 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<JobCardItem> updatedItems = new ArrayList<>();
List<Bundle> 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<Long> bundleIds = wrapper.getBundles().stream().map(Bundle::getId).collect(Collectors.toList());
Map<Long, InventoryTransactionLeg> 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().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());
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<StitchingOfflineItem> stitchingOfflineItems = createStitchingOfflineItems(subBundle.getCurrentProduction(),jobCardItem,subBundle.getId());
// create IN Transactions of Finished Items into account
createTransactions(stitchingOfflineItems, accountId, InventoryArtifactType.STITCHING_OFFLINE.name());
jobCardItem.setTotalProduction(jobCardItem.getTotalProduction().add(subBundle.getCurrentProduction()));
jobCardItem.setJobCardId(jobCard.getId());
updatedItems.add(jobCardItem);
BigDecimal pro = subBundle.getCurrentProduction();
bundle.setProduction(pro);
bundleDAO.save(bundle);
}
}
jobCardItemDAO.saveAll(updatedItems);
}
/*
* create finished items
* */
public List<StitchingOfflineItem> createStitchingOfflineItems( BigDecimal totalItem, JobCardItem jobCardItem,long bundleId) {
Authentication authentication = SecurityContextHolder.getContext( ).getAuthentication( );
List<StitchingOfflineItem> 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<InventoryTransactionLeg> findTransactionByAccountId( long accountId) {
List<InventoryTransactionLeg> legs = inventoryTransactionLegDAO.findByAccountId( accountId);
List<Long> tIds = legs.stream( ).map( InventoryTransactionLeg::getTransactionId).collect( Collectors.toList( ));
Map<Long, InventoryTransaction> 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<Long> fItemIds, long toAccount) {
if ( fItemIds.isEmpty( ) || toAccount == 0) {
throw new RuntimeException( "Finished Item Ids | Account can`t be empty");
}
List<FinishedItem> finishedItems = finishedItemDAO.findByIds( fItemIds);
if ( finishedItems != null && !finishedItems.isEmpty( )) {
// bundle ids
List<Long> finishedItemIds = finishedItems.stream( ).map( FinishedItem::getId).collect( Collectors.toList( ));
Map<Long, InventoryTransactionLeg> 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<StitchingOfflineItem> stitchingOfflineItems = wrapper.getItems( );
List<StitchingOfflineItem> updatedStitchedItems = new ArrayList<>( );
List<FinishedItem> finishedItems = new ArrayList<>( );
List<Long> stitchedItemIds = stitchingOfflineItems.stream( )
.map( StitchingOfflineItem::getId)
.collect( Collectors.toList( ));
Map<Long, InventoryTransactionLeg> 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<Long> preCreatedFinishedItemIds = finishedItemDAO.findByStitchedItemIds( stitchedItemIds ).stream( ).
map( FinishedItem::getId ).collect( Collectors.toList( ));
Map<Long, InventoryTransactionLeg> 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<FinishedItem> items = wrapper.getItems( );
List<FinishedItem> updatedItems = new ArrayList<>( );
// finished ids
List<Long> finishedItemIds = items.stream( ).map( FinishedItem::getId)
.collect( Collectors.toList( ));
// stitched ids
List<Long> stitchedItemIds = items.stream( ).map( FinishedItem::getStitchedItemId)
.collect( Collectors.toList( ));
// create parent doc type last IN transaction map
Map<Long, InventoryTransactionLeg> 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<Long, InventoryTransactionLeg> 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<InventorySummary> findItemSummaryByAccountId( long accountId) {
return inventoryTransactionLegDAO.findSummaryByAccountId( accountId);
}
}