use of de.metas.purchasecandidate.PurchaseCandidatesGroup in project metasfresh-webui-api by metasfresh.
the class PurchaseRow method streamPurchaseCandidatesGroup.
public Stream<PurchaseCandidatesGroup> streamPurchaseCandidatesGroup() {
final Stream<PurchaseCandidatesGroup> includedRowsStream = getIncludedRows().stream().flatMap(PurchaseRow::streamPurchaseCandidatesGroup);
final PurchaseCandidatesGroup candidatesGroup = getPurchaseCandidatesGroup();
if (candidatesGroup == null) {
return includedRowsStream;
} else {
return Stream.concat(Stream.of(candidatesGroup), includedRowsStream);
}
}
use of de.metas.purchasecandidate.PurchaseCandidatesGroup in project metasfresh-webui-api by metasfresh.
the class PurchaseRowsSaver method createOrUpdatePurchaseCandidate.
private List<PurchaseCandidate> createOrUpdatePurchaseCandidate(@NonNull final PurchaseCandidatesGroup candidatesGroup, @NonNull final Map<PurchaseCandidateId, PurchaseCandidate> existingPurchaseCandidatesById) {
Quantity qtyToPurchaseRemainingOfGroup = candidatesGroup.getQtyToPurchase();
if (qtyToPurchaseRemainingOfGroup.signum() <= 0) {
return ImmutableList.of();
}
final PurchaseProfitInfo profitInfo = candidatesGroup.getProfitInfoOrNull();
final ZonedDateTime purchaseDatePromised = candidatesGroup.getPurchaseDatePromised();
final Duration reminderTime = candidatesGroup.getReminderTime();
final List<PurchaseCandidate> allCandidates = getPurchaseCandidates(candidatesGroup, existingPurchaseCandidatesById);
//
// Adjust qtyToPurchaseRemaining: Subtract the qtyToPurchase which was already processed
{
final Optional<Quantity> qtyToPurchaseProcessed = computeQtyToPurchaseAlreadyProcessed(allCandidates);
if (qtyToPurchaseProcessed.isPresent()) {
qtyToPurchaseRemainingOfGroup = qtyToPurchaseRemainingOfGroup.subtract(qtyToPurchaseProcessed.get());
}
if (qtyToPurchaseRemainingOfGroup.signum() < 0) {
// TODO: throw exception?
return ImmutableList.of();
} else if (qtyToPurchaseRemainingOfGroup.signum() == 0) {
return ImmutableList.of();
}
}
//
// Extract all updatable candidates
final ArrayList<PurchaseCandidate> candidatesToUpdate = allCandidates.stream().filter(candidate -> !candidate.isProcessedOrLocked()).collect(Collectors.toCollection(ArrayList::new));
final ArrayList<PurchaseCandidate> candidatesChanged = new ArrayList<>();
// Distribute qtyToPurchase to updatable purchase candidates (FIFO order)
while (qtyToPurchaseRemainingOfGroup.signum() > 0 && !candidatesToUpdate.isEmpty()) {
final PurchaseCandidate candidate = candidatesToUpdate.remove(0);
final Quantity qtyToPurchaseTarget = getQtyToPurchaseTarget(candidate);
final Quantity qtyToPurchase = qtyToPurchaseTarget.min(qtyToPurchaseRemainingOfGroup);
candidate.setQtyToPurchase(qtyToPurchase);
candidate.setPrepared(qtyToPurchase.signum() != 0);
candidate.setPurchaseDatePromised(purchaseDatePromised);
candidate.setProfitInfoOrNull(profitInfo);
candidatesChanged.add(candidate);
qtyToPurchaseRemainingOfGroup = qtyToPurchaseRemainingOfGroup.subtract(qtyToPurchase);
}
// If there is no remaining qty to purchase then ZERO all the remaining purchase candidates lines
if (qtyToPurchaseRemainingOfGroup.signum() <= 0) {
while (!candidatesToUpdate.isEmpty()) {
final PurchaseCandidate candidate = candidatesToUpdate.remove(0);
candidate.setQtyToPurchase(candidate.getQtyToPurchase().toZero());
candidatesChanged.add(candidate);
}
} else // If there is remaining qty to purchase then add it to last changed purchase candidate line
if (!candidatesToUpdate.isEmpty()) {
final PurchaseCandidate lastCandidate = candidatesToUpdate.get(candidatesToUpdate.size() - 1);
lastCandidate.setQtyToPurchase(lastCandidate.getQtyToPurchase().add(qtyToPurchaseRemainingOfGroup));
lastCandidate.setPurchaseDatePromised(purchaseDatePromised);
qtyToPurchaseRemainingOfGroup = qtyToPurchaseRemainingOfGroup.toZero();
} else //
// If there is remaining qty to purchase but no purchase candidate to add to then create a new candidate
{
final DemandGroupReference groupReference;
if (candidatesGroup.getDemandGroupReferences().isEmpty()) {
groupReference = DemandGroupReference.EMPTY;
} else {
groupReference = candidatesGroup.getDemandGroupReferences().get(0);
}
final PurchaseCandidate newCandidate = PurchaseCandidate.builder().groupReference(groupReference).salesOrderAndLineIdOrNull(candidatesGroup.getSingleSalesOrderAndLineIdOrNull()).purchaseDatePromised(purchaseDatePromised).reminderTime(reminderTime).orgId(candidatesGroup.getOrgId()).warehouseId(candidatesGroup.getWarehouseId()).vendorId(candidatesGroup.getVendorId()).vendorProductNo(candidatesGroup.getVendorProductNo()).productId(candidatesGroup.getProductId()).attributeSetInstanceId(candidatesGroup.getAttributeSetInstanceId()).qtyToPurchase(qtyToPurchaseRemainingOfGroup).prepared(true).aggregatePOs(candidatesGroup.isAggregatePOs()).profitInfoOrNull(profitInfo).build();
candidatesChanged.add(newCandidate);
qtyToPurchaseRemainingOfGroup = qtyToPurchaseRemainingOfGroup.toZero();
}
return candidatesChanged;
}
use of de.metas.purchasecandidate.PurchaseCandidatesGroup in project metasfresh-webui-api by metasfresh.
the class PurchaseRowsSaver method save.
public List<PurchaseCandidate> save(@NonNull final List<PurchaseRow> groupingRows) {
final Set<DemandGroupReference> demandIds = extractDemandIds(groupingRows);
final Map<PurchaseCandidateId, PurchaseCandidate> existingPurchaseCandidatesById = getExistingPurchaseCandidatesIndexedById(demandIds);
//
// Create/Update purchase candidates (this used to be stream-based, but it was too hard to debug)
final List<PurchaseCandidate> purchaseCandidatesToSave = new ArrayList<>();
final List<PurchaseCandidatesGroup> purchaseCandidatesGroups = extractPurchaseCandidatesGroups(groupingRows);
for (final PurchaseCandidatesGroup purchaseCandidatesGroup : purchaseCandidatesGroups) {
final List<PurchaseCandidate> purchaseCandidates = createOrUpdatePurchaseCandidate(purchaseCandidatesGroup, existingPurchaseCandidatesById);
purchaseCandidatesToSave.addAll(purchaseCandidates);
}
purchaseCandidatesRepo.saveAll(purchaseCandidatesToSave);
//
// Zerofy remaining candidates:
final Set<PurchaseCandidateId> purchaseCandidateIdsSaved = purchaseCandidatesToSave.stream().map(PurchaseCandidate::getId).filter(Objects::nonNull).collect(ImmutableSet.toImmutableSet());
final List<PurchaseCandidate> purchaseCandidatesToZero = existingPurchaseCandidatesById.values().stream().filter(// don't delete processed/locked candidates
candidate -> !candidate.isProcessedOrLocked()).filter(candidate -> !purchaseCandidateIdsSaved.contains(candidate.getId())).peek(candidate -> {
candidate.setQtyToPurchase(candidate.getQtyToPurchase().toZero());
candidate.setPrepared(false);
}).collect(ImmutableList.toImmutableList());
purchaseCandidatesRepo.saveAll(purchaseCandidatesToZero);
return purchaseCandidatesToSave;
}
use of de.metas.purchasecandidate.PurchaseCandidatesGroup in project metasfresh-webui-api by metasfresh.
the class PurchaseRowsLoader method load.
@VisibleForTesting
PurchaseRowsList load() {
final PurchaseRowsList.PurchaseRowsListBuilder resultBuilder = PurchaseRowsList.builder();
for (final PurchaseDemandWithCandidates demandWithCandidates : purchaseDemandWithCandidatesList) {
final PurchaseDemand demand = demandWithCandidates.getPurchaseDemand();
final List<PurchaseRow> purchaseCandidateRows = new ArrayList<>();
final List<TrackingId> trackingIds = new ArrayList<>();
for (final PurchaseCandidatesGroup purchaseCandidatesGroup : demandWithCandidates.getPurchaseCandidatesGroups()) {
final PurchaseRow purchaseCandidateRow = purchaseRowFactory.lineRowBuilder().purchaseCandidatesGroup(purchaseCandidatesGroup).convertAmountsToCurrencyId(demand.getCurrencyIdOrNull()).build();
purchaseCandidateRows.add(purchaseCandidateRow);
final TrackingId trackingId = TrackingId.random();
trackingIds.add(trackingId);
resultBuilder.purchaseCandidatesGroup(trackingId, purchaseCandidatesGroup);
resultBuilder.purchaseCandidateRow(trackingId, purchaseCandidateRow);
}
final PurchaseRow groupRow = purchaseRowFactory.createGroupRow(demand, purchaseCandidateRows);
resultBuilder.topLevelRow(groupRow);
final PurchaseRowId groupRowId = groupRow.getRowId();
trackingIds.forEach(trackingId -> resultBuilder.trackingIdsByTopLevelRowId(trackingId, groupRowId));
}
return resultBuilder.build();
}
use of de.metas.purchasecandidate.PurchaseCandidatesGroup in project metasfresh-webui-api by metasfresh.
the class PurchaseRow method changeRow.
private void changeRow(@NonNull final PurchaseRowChangeRequest request) {
assertRowType(PurchaseRowType.LINE);
assertRowEditable();
//
final PurchaseCandidatesGroup candidatesGroup = getPurchaseCandidatesGroup();
final PurchaseCandidatesGroupBuilder newCandidatesGroup = candidatesGroup.toBuilder();
boolean hasChanges = false;
//
// QtyToPurchase
final Quantity qtyToPurchase = request.getQtyToPurchase(this::getCurrentUOM);
boolean qtyToPurchaseChanged = false;
if (qtyToPurchase != null && !Objects.equals(candidatesGroup.getQtyToPurchase(), qtyToPurchase)) {
newCandidatesGroup.qtyToPurchase(qtyToPurchase);
qtyToPurchaseChanged = true;
hasChanges = true;
}
//
// PurchaseDatePromised
final ZonedDateTime purchaseDatePromised = request.getPurchaseDatePromised();
if (purchaseDatePromised != null) {
newCandidatesGroup.purchaseDatePromised(purchaseDatePromised);
hasChanges = true;
}
// Recompute Profit Info
if (qtyToPurchaseChanged) {
final PurchaseProfitInfo profitInfo = purchaseProfitInfoService.calculateNoFail(PurchaseProfitInfoRequest.builder().salesOrderAndLineIds(candidatesGroup.getSalesOrderAndLineIds()).qtyToPurchase(qtyToPurchase).vendorProductInfo(candidatesGroup.getVendorProductInfo()).build());
newCandidatesGroup.profitInfoOrNull(profitInfo);
hasChanges = true;
}
// Stop here if there were no changes
if (!hasChanges) {
return;
}
//
setPurchaseCandidatesGroup(newCandidatesGroup.build());
}
Aggregations