Skip to content

Commit

Permalink
fixes for receipt&issue; also:
Browse files Browse the repository at this point in the history
* improve MD_Candidate type naming #10327
* fix the processing of M_Inventory #10422
  • Loading branch information
metas-ts committed Dec 14, 2020
1 parent 80d1578 commit a13098c
Show file tree
Hide file tree
Showing 27 changed files with 825 additions and 432 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,6 @@ public interface IHUAssignmentDAO extends ISingletonService
{
/**
* Retrieve single top-level handling unit assignment. "Top-level" means that both {@code M_LU_HU_ID} and {@code M_TU_HU_ID} are null. If no such record is found, return null.
*
* @param ctx
* @param huId
* @param adTableId
* @param recordId
* @param trxName
* @return assignment
*/
I_M_HU_Assignment retrieveHUAssignmentOrNull(Properties ctx, int huId, int adTableId, int recordId, String trxName);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,13 @@ public interface IHUAttributePropagator
* Sets {@link IHUAttributePropagatorFactory}.
*
* NOTE: don't call it directly. It's called by API.
*
* @param factory
*/
void setHUAttributePropagatorFactory(IHUAttributePropagatorFactory factory);

/**
* Check if this {@link IHUAttributePropagator} is compatible with it's parent. See the implementing subclasses' javadocs for implementation details.
*
* @param otherPropagator the propagator to compare with
* @return
*/
boolean isCompatible(IHUAttributePropagator otherPropagator);

Expand All @@ -67,9 +64,7 @@ public interface IHUAttributePropagator
* Set and propagate attribute value.
* Note that propagation only happens if the respective attribute exists in the propagation target. If it doesn't exists, it is <b>not</b> created on the fly
*
* @param propagationContext
* @param attributeSet the attributeset to which the given <code>value</code> shall be set.
* @param value
*/
void propagateValue(IHUAttributePropagationContext propagationContext, IAttributeStorage attributeSet, Object value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ public DocBaseAndSubType extractDocBaseAndSubTypeOrNull(@Nullable final I_M_Inve
return docTypeDAO.getDocBaseAndSubTypeById(docTypeId);
}

/**
* The method might not belong here, but we often need this from outside the repo
*/
public InventoryLine toInventoryLine(@NonNull final I_M_InventoryLine inventoryLineRecord)
{
final InventoryLineId inventoryLineId = extractInventoryLineIdOrNull(inventoryLineRecord);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package de.metas.handlingunits.material.interceptor;

import de.metas.handlingunits.material.interceptor.transactionevent.TransactionEventFactory;
import de.metas.handlingunits.material.interceptor.transactionevent.TransactionDescriptor;
import de.metas.handlingunits.material.interceptor.transactionevent.TransactionDescriptorFactory;
import de.metas.material.event.MaterialEvent;
import de.metas.material.event.PostMaterialEventService;
import de.metas.util.Services;
Expand Down Expand Up @@ -38,24 +41,26 @@
*/
@Interceptor(I_M_Transaction.class)
@Component
public class M_Transaction_PostMaterialEvent
public class M_Transaction_PostTransactionEvent
{
private final ITrxManager trxManager = Services.get(ITrxManager.class);
private final PostMaterialEventService materialEventService;
private final M_Transaction_TransactionEventCreator mtransactionEventCreator;
private final TransactionEventFactory transactionEventCreator;
private final TransactionDescriptorFactory transactionDescriptorFactory;

public M_Transaction_PostMaterialEvent(@NonNull final PostMaterialEventService materialEventService)
public M_Transaction_PostTransactionEvent(
@NonNull final PostMaterialEventService materialEventService,
@NonNull final TransactionEventFactory transactionEventCreator)
{
this.materialEventService = materialEventService;
this.mtransactionEventCreator = new M_Transaction_TransactionEventCreator();
this.transactionEventCreator = transactionEventCreator;
this.transactionDescriptorFactory = new TransactionDescriptorFactory();
}

/**
* Note: it's important to enqueue the transaction after it was saved and before it is deleted, because we need its ID.
*
* @task https://github.com/metasfresh/metasfresh/issues/710
* task https://github.com/metasfresh/metasfresh/issues/710
*/
@ModelChange(timings = {
ModelValidator.TYPE_AFTER_NEW,
Expand All @@ -72,9 +77,9 @@ public void fireTransactionEvent(
trxManager.runAfterCommit(() -> createAndPostEventsNow(transaction, deleted));
}

private void createAndPostEventsNow(final TransactionDescriptor transaction, final boolean deleted)
private void createAndPostEventsNow(@NonNull final TransactionDescriptor transaction, final boolean deleted)
{
final List<MaterialEvent> events = mtransactionEventCreator.createEventsForTransaction(transaction, deleted);
final List<MaterialEvent> events = transactionEventCreator.createEventsForTransaction(transaction, deleted);
for (final MaterialEvent event : events)
{
materialEventService.postEventNow(event);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* #%L
* de.metas.handlingunits.base
* %%
* Copyright (C) 2020 metas GmbH
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-2.0.html>.
* #L%
*/

package de.metas.handlingunits.material.interceptor.transactionevent;

import com.google.common.collect.ImmutableList;
import de.metas.handlingunits.HuId;
import de.metas.handlingunits.IHandlingUnitsDAO;
import de.metas.handlingunits.inventory.InventoryLine;
import de.metas.handlingunits.inventory.InventoryLineHU;
import de.metas.handlingunits.inventory.InventoryRepository;
import de.metas.material.event.commons.HUDescriptor;
import de.metas.util.Services;
import de.metas.util.collections.CollectionUtils;
import lombok.NonNull;
import org.adempiere.model.InterfaceWrapperHelper;
import org.compiere.model.I_M_InventoryLine;
import org.springframework.stereotype.Component;

@Component // not calling it service, because right now it's intended to be used only from the M_Transaction model interceptor
public class HUDescriptorFromInventoryLineService
{
private final InventoryRepository inventoryRepository;
private final HUDescriptorService huDescriptorService;
private final IHandlingUnitsDAO handlingUnitsDAO = Services.get(IHandlingUnitsDAO.class);

public HUDescriptorFromInventoryLineService(
@NonNull final InventoryRepository inventoryRepository,
@NonNull final HUDescriptorService huDescriptorService)
{
this.inventoryRepository = inventoryRepository;
this.huDescriptorService = huDescriptorService;
}

public ImmutableList<HUDescriptor> createHuDescriptorsForInventoryLine(
@NonNull final I_M_InventoryLine inventoryLineRecord,
final boolean deleted)
{
final InventoryLine inventoryLine = inventoryRepository.toInventoryLine(
InterfaceWrapperHelper.create(inventoryLineRecord, de.metas.handlingunits.model.I_M_InventoryLine.class));

final ImmutableList<InventoryLineHU> inventoryLineHUs = inventoryLine.getInventoryLineHUs();
final ImmutableList<HuId> huIds = CollectionUtils.extractDistinctElements(inventoryLineHUs, InventoryLineHU::getHuId);

return handlingUnitsDAO
.getByIds(huIds)
.stream()
.flatMap(huRecord -> huDescriptorService.createHuDescriptors(huRecord, deleted).stream())
.collect(ImmutableList.toImmutableList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* #%L
* de.metas.handlingunits.base
* %%
* Copyright (C) 2020 metas GmbH
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-2.0.html>.
* #L%
*/

package de.metas.handlingunits.material.interceptor.transactionevent;

import com.google.common.collect.ImmutableList;
import de.metas.handlingunits.IHUContext;
import de.metas.handlingunits.IHUContextFactory;
import de.metas.handlingunits.IMutableHUContext;
import de.metas.handlingunits.model.I_M_HU;
import de.metas.handlingunits.storage.IHUProductStorage;
import de.metas.handlingunits.storage.IHUStorage;
import de.metas.material.event.commons.AttributesKey;
import de.metas.material.event.commons.HUDescriptor;
import de.metas.material.event.commons.ProductDescriptor;
import de.metas.util.Services;
import lombok.NonNull;
import org.adempiere.mm.attributes.AttributeSetInstanceId;
import org.adempiere.mm.attributes.api.AttributesKeys;
import org.adempiere.mm.attributes.api.IAttributeSet;
import org.adempiere.mm.attributes.api.IAttributeSetInstanceBL;
import org.adempiere.mm.attributes.api.ImmutableAttributeSet;
import org.adempiere.util.lang.IPair;
import org.adempiere.util.lang.ImmutablePair;
import org.compiere.model.I_M_Attribute;
import org.compiere.model.I_M_AttributeSetInstance;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

@Service
public class HUDescriptorService
{
private final IHUContextFactory huContextFactory = Services.get(IHUContextFactory.class);
private final IAttributeSetInstanceBL attributeSetInstanceBL = Services.get(IAttributeSetInstanceBL.class);

public ImmutableList<HUDescriptor> createHuDescriptors(
@NonNull final I_M_HU huRecord,
final boolean deleted)
{
final IMutableHUContext huContext = huContextFactory.createMutableHUContext();
final IHUStorage storage = huContext.getHUStorageFactory().getStorage(huRecord);

// Important note: we could have the AttributesKey without making an ASI, but we need the ASI-ID for display reasons in the material dispo window.
final IPair<AttributesKey, AttributeSetInstanceId> attributesKeyAndAsiId = createAttributesKeyAndAsiId(huContext, huRecord);
final AttributesKey attributesKey = attributesKeyAndAsiId.getLeft();
final AttributeSetInstanceId asiId = attributesKeyAndAsiId.getRight();

final ImmutableList.Builder<HUDescriptor> descriptors = ImmutableList.builder();
for (final IHUProductStorage productStorage : storage.getProductStorages())
{
final ProductDescriptor productDescriptor = ProductDescriptor.forProductAndAttributes(
productStorage.getProductId().getRepoId(),
attributesKey,
asiId.getRepoId());

final BigDecimal quantity = productStorage.getQtyInStockingUOM().toBigDecimal();

final HUDescriptor descriptor = HUDescriptor.builder()
.huId(huRecord.getM_HU_ID())
.productDescriptor(productDescriptor)
.quantity(deleted ? BigDecimal.ZERO : quantity)
.quantityDelta(deleted ? quantity.negate() : quantity)
.build();
descriptors.add(descriptor);
}
return descriptors.build();
}

private IPair<AttributesKey, AttributeSetInstanceId> createAttributesKeyAndAsiId(
@NonNull final IHUContext huContext,
@NonNull final I_M_HU hu)
{
final IAttributeSet attributeStorage = huContext.getHUAttributeStorageFactory().getAttributeStorage(hu);

// we don't want all the non-storage-relevant attributes to pollute the ASI we will display in the material disposition window
final IAttributeSet storageRelevantSubSet = ImmutableAttributeSet.createSubSet(attributeStorage, I_M_Attribute::isStorageRelevant);

final I_M_AttributeSetInstance asi = attributeSetInstanceBL.createASIFromAttributeSet(storageRelevantSubSet);
final AttributeSetInstanceId asiId = AttributeSetInstanceId.ofRepoIdOrNone(asi.getM_AttributeSetInstance_ID());

final AttributesKey attributesKey = AttributesKeys
.createAttributesKeyFromASIStorageAttributes(asiId)
.orElse(AttributesKey.NONE);

return ImmutablePair.of(attributesKey, asiId);
}
}

0 comments on commit a13098c

Please sign in to comment.