Search in sources :

Example 1 with PurchaseCandidatesGroup

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);
    }
}
Also used : PurchaseCandidatesGroup(de.metas.purchasecandidate.PurchaseCandidatesGroup)

Example 2 with PurchaseCandidatesGroup

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;
}
Also used : ZonedDateTime(java.time.ZonedDateTime) Function(java.util.function.Function) OrderAndLineId(de.metas.order.OrderAndLineId) ArrayList(java.util.ArrayList) IOrderLineBL(de.metas.order.IOrderLineBL) ImmutableList(com.google.common.collect.ImmutableList) PurchaseCandidateRepository(de.metas.purchasecandidate.PurchaseCandidateRepository) Quantity(de.metas.quantity.Quantity) Duration(java.time.Duration) Map(java.util.Map) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableMap(com.google.common.collect.ImmutableMap) NonNull(lombok.NonNull) Collection(java.util.Collection) PurchaseCandidate(de.metas.purchasecandidate.PurchaseCandidate) Set(java.util.Set) PurchaseCandidateId(de.metas.purchasecandidate.PurchaseCandidateId) Collectors(java.util.stream.Collectors) Services(de.metas.util.Services) Objects(java.util.Objects) List(java.util.List) Builder(lombok.Builder) DemandGroupReference(de.metas.purchasecandidate.DemandGroupReference) PurchaseProfitInfo(de.metas.purchasecandidate.grossprofit.PurchaseProfitInfo) Optional(java.util.Optional) Comparator(java.util.Comparator) PurchaseCandidatesGroup(de.metas.purchasecandidate.PurchaseCandidatesGroup) Optional(java.util.Optional) ZonedDateTime(java.time.ZonedDateTime) ArrayList(java.util.ArrayList) Quantity(de.metas.quantity.Quantity) Duration(java.time.Duration) PurchaseCandidate(de.metas.purchasecandidate.PurchaseCandidate) DemandGroupReference(de.metas.purchasecandidate.DemandGroupReference) PurchaseProfitInfo(de.metas.purchasecandidate.grossprofit.PurchaseProfitInfo)

Example 3 with PurchaseCandidatesGroup

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;
}
Also used : ZonedDateTime(java.time.ZonedDateTime) Function(java.util.function.Function) OrderAndLineId(de.metas.order.OrderAndLineId) ArrayList(java.util.ArrayList) IOrderLineBL(de.metas.order.IOrderLineBL) ImmutableList(com.google.common.collect.ImmutableList) PurchaseCandidateRepository(de.metas.purchasecandidate.PurchaseCandidateRepository) Quantity(de.metas.quantity.Quantity) Duration(java.time.Duration) Map(java.util.Map) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableMap(com.google.common.collect.ImmutableMap) NonNull(lombok.NonNull) Collection(java.util.Collection) PurchaseCandidate(de.metas.purchasecandidate.PurchaseCandidate) Set(java.util.Set) PurchaseCandidateId(de.metas.purchasecandidate.PurchaseCandidateId) Collectors(java.util.stream.Collectors) Services(de.metas.util.Services) Objects(java.util.Objects) List(java.util.List) Builder(lombok.Builder) DemandGroupReference(de.metas.purchasecandidate.DemandGroupReference) PurchaseProfitInfo(de.metas.purchasecandidate.grossprofit.PurchaseProfitInfo) Optional(java.util.Optional) Comparator(java.util.Comparator) PurchaseCandidatesGroup(de.metas.purchasecandidate.PurchaseCandidatesGroup) ArrayList(java.util.ArrayList) PurchaseCandidatesGroup(de.metas.purchasecandidate.PurchaseCandidatesGroup) PurchaseCandidate(de.metas.purchasecandidate.PurchaseCandidate) DemandGroupReference(de.metas.purchasecandidate.DemandGroupReference) PurchaseCandidateId(de.metas.purchasecandidate.PurchaseCandidateId)

Example 4 with PurchaseCandidatesGroup

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();
}
Also used : PurchaseDemandWithCandidates(de.metas.purchasecandidate.PurchaseDemandWithCandidates) PurchaseDemand(de.metas.purchasecandidate.PurchaseDemand) ArrayList(java.util.ArrayList) PurchaseCandidatesGroup(de.metas.purchasecandidate.PurchaseCandidatesGroup) TrackingId(de.metas.vendor.gateway.api.availability.TrackingId) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 5 with PurchaseCandidatesGroup

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());
}
Also used : ZonedDateTime(java.time.ZonedDateTime) PurchaseCandidatesGroupBuilder(de.metas.purchasecandidate.PurchaseCandidatesGroup.PurchaseCandidatesGroupBuilder) PurchaseCandidatesGroup(de.metas.purchasecandidate.PurchaseCandidatesGroup) Quantity(de.metas.quantity.Quantity) PurchaseProfitInfo(de.metas.purchasecandidate.grossprofit.PurchaseProfitInfo)

Aggregations

PurchaseCandidatesGroup (de.metas.purchasecandidate.PurchaseCandidatesGroup)5 PurchaseProfitInfo (de.metas.purchasecandidate.grossprofit.PurchaseProfitInfo)3 Quantity (de.metas.quantity.Quantity)3 ZonedDateTime (java.time.ZonedDateTime)3 ArrayList (java.util.ArrayList)3 ImmutableList (com.google.common.collect.ImmutableList)2 ImmutableMap (com.google.common.collect.ImmutableMap)2 ImmutableSet (com.google.common.collect.ImmutableSet)2 IOrderLineBL (de.metas.order.IOrderLineBL)2 OrderAndLineId (de.metas.order.OrderAndLineId)2 DemandGroupReference (de.metas.purchasecandidate.DemandGroupReference)2 PurchaseCandidate (de.metas.purchasecandidate.PurchaseCandidate)2 PurchaseCandidateId (de.metas.purchasecandidate.PurchaseCandidateId)2 PurchaseCandidateRepository (de.metas.purchasecandidate.PurchaseCandidateRepository)2 Services (de.metas.util.Services)2 Duration (java.time.Duration)2 Collection (java.util.Collection)2 Comparator (java.util.Comparator)2 List (java.util.List)2 Map (java.util.Map)2