Skip to content

Commit

Permalink
#7012 Can no longer reactivate or void sales orders with exported shi… (
Browse files Browse the repository at this point in the history
#7037)

* extending the json-pojos; about to add tables and stuff

* implement big part of shipment schedule exporting

TODO
* unit tests for ShipmentCandidateExporter and ShipmentScheduleAuditRepository
* MIs, ErrorMessages etc to prevent fiddling with exported shipment schedules
* dev-test;
* also see & coordinante what's missing

#7012

* add "Export" fields to shipment schedule window

TODO
* unit tests for ShipmentCandidateExporter and ShipmentScheduleAuditRepository
* MIs, ErrorMessages etc to prevent fiddling with exported shipment schedules
* dev-test;
* also see & coordinante what's missing

#7012

* work on ShipmentCandidateExporterTest

TODO
* unit tests for ShipmentCandidateExporter
* MIs, ErrorMessages etc to prevent fiddling with exported shipment schedules
* dev-test;
* also see & coordinate what's missing

#7012

* #7012 New Shipment Disposition Window.

* #7012 Removed script belonging to private repo.

* finish ShipmentCandidateExporterTest and add another export status

TODO
* MIs, ErrorMessages etc to prevent fiddling with exported shipment schedules
* dev-test;
* also see & coordinate what's missing

#7012

* create filemaker-pojos so we can read&write XML

TODO
* MIs, ErrorMessages etc to prevent fiddling with exported shipment schedules
* dev-test;
* also see & coordinate what's missing

#7012

* minor fixes

TODO
* MIs, ErrorMessages etc to prevent fiddling with exported shipment schedules
* dev-test;
* also see & coordinate what's missing

#7012

* minor fixes

TODO
* MIs, ErrorMessages etc to prevent fiddling with exported shipment schedules
* dev-test;
* also see & coordinate what's missing

#7012

* add additional exportstatus "don't export"

TODO
* MIs, ErrorMessages etc to prevent fiddling with exported shipment schedules
* dev-test;
* also see & coordinate what's missing

#7012

* add additional exportstatus "don't export"

TODO
* MIs, ErrorMessages etc to prevent fiddling with exported shipment schedules
* dev-test;
* also see & coordinate what's missing

#7012

* go at another enforcer dependency convergence error

TODO
* MIs, ErrorMessages etc to prevent fiddling with exported shipment schedules
* dev-test;
* also see & coordinate what's missing

#7012

* `Picking Terminal V2`: Add process for picking and packing in 1 step (#6950)

(cherry picked from commit c03f7d2)

* ProductsToPickViewFactory: Inject the constructor via Spring instead of SpringContextHolder (#6970)

#6949
(cherry picked from commit 9d6fda6)

* Picking Terminal V2: Pick&Pack: Skip rows with qty 0 (#7022)

(cherry picked from commit fd95e03)

* Fixes after cherrypicks

#7021

* work on camel testing

TODO
* MIs, ErrorMessages etc to prevent fiddling with exported shipment schedules
* dev-test;
* also see & coordinate what's missing

#7012

* Updated ReleaseNotes.md

added issues

* minor fix: don't export scheds with qtyToDeliver<=0

TODO
* MIs, ErrorMessages etc to prevent fiddling with exported shipment schedules
* dev-test;
* also see & coordinate what's missing

#7012

* Update WEBUI_M_HU_ReturnFromCustomer.java (#7028)

* div. improvements

* Use jackson-stuff in our camel route
* Send feedback to metasfresh
* Update audit records using feedback
* convert JSON to XML
* simplify audit records in metasfresh
* Also
  * CacheInvalidateMultiRequest with better support for RepoIdAwares

  #7012

* fixes

  #7012

* fixes

#7012

* attempt to fix criculary error handling + dependency conversion errors

#7012

* minor

#7012

* minor

#7012

* work on fixing tests

#7012

* attempt to fix dependency conversion errors
#7012

* rename/more classes and modules; meekly start with receipt-candidates

#7012

* attempt to fix dependency conversion errors

#7012

* Add ExportStatus and CanBeExportedFrom for M_ReceiptSchedule

#7012

* Starting with Receipt Candidate API

* move ShipmentScheduleId class
* extract common APIExportAudit and APIExportAuditRepository
* start receipt candidate code (similar to shipment candidate, but e.g. different classes)

#7012

* fix module name

#7012

* Starting with Receipt Candidate API

* pom.xml fix typo in exclusion
* start implementing the camel part as well

#7012

* Upgrade lodash due to security advisory (#7031)

Co-authored-by: Petrica Nanca <petrica.nanca@metasfresh.com>

* Add extra checks for clearing the filter (#7032)

Co-authored-by: Petrica Nanca <petrica.nanca@metasfresh.com>

* solve another depdendency conversion error

#7012

* solve after-refactor-error

#7012

* attempt to solve dependency convergence error

#7012

* work on json-XML-mapping for receipt schedules

#7012

* fix docker image name in build descr

#7012

* #7012 Can no longer reactivate or void sales orders with exported shipment schedules.

* different improvements

* sql
  * fix typo in the DE-text i provided
  * remove "webui." prefix..not sure what it's point was
* ShipmentSchedulePA
  * deduplicate "read-only" enum values
  * no need to order
* C_Order: don't go to the DB for a purchase order

#7012

* #7012 Small Improvements.
 - added filter for unprocessed shipment schedules
 - changed name of function in ShipmentSchedulePA

* #7012 Small Improvements.
 - Added new process and new error message
 - Created new java process that changes status of unprocessed lines.

* #7012 Small Improvements.
 - Moved script setting readonly logic in m_shipmentschedule from private to public repo.
 - Small code adjustments.

* solve after-merge-conflicts

* minor comment-fix

Co-authored-by: Tobias Schöneberg <tobias.schoeneberg@metasfresh.com>
Co-authored-by: TheBestPessimist <cristian@tbp.land>
Co-authored-by: Kay <kay.kostelnik@metasfresh.com>
Co-authored-by: Teo Sarca <teo.sarca@metasfresh.com>
Co-authored-by: Petrica Nanca <petrica_nanca@yahoo.com>
Co-authored-by: Petrica Nanca <petrica.nanca@metasfresh.com>
  • Loading branch information
7 people committed Jul 23, 2020
1 parent 1c7c727 commit 2b85d67
Show file tree
Hide file tree
Showing 12 changed files with 412 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ public interface IQueryBuilder<T>
/**
* Filters those rows for whom the columnName's value is in given array.
* If no values were provided the record is rejected.
*
* Note that "InArray*Filters" also support {@link RepoIdAware} and {@link de.metas.util.lang.ReferenceListAwareEnum}
*/
@SuppressWarnings("unchecked")
<V> IQueryBuilder<T> addInArrayFilter(String columnName, V... values);
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
UPDATE AD_Column
SET ReadOnlyLogic='@ExportStatus/''X''@ = ''EXPORTED'' | @ExportStatus/''X''@ = ''EXPORTED_AND_FORWARDED'' | @ExportStatus/''X''@ = ''EXPORTED_FORWARD_ERROR''',
Updated=now(),UpdatedBy=100
WHERE AD_Table_ID=500221
;
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
public class X_M_Packageable_V extends org.compiere.model.PO implements I_M_Packageable_V, org.compiere.model.I_Persistent
{

private static final long serialVersionUID = -1822918291L;
private static final long serialVersionUID = -521904266L;

/** Standard Constructor */
public X_M_Packageable_V (Properties ctx, int M_Packageable_V_ID, String trxName)
Expand Down Expand Up @@ -580,7 +580,7 @@ public void setPOReference (java.lang.String POReference)
}

@Override
public java.lang.String getPOReference()
public java.lang.String getPOReference()
{
return (java.lang.String)get_Value(COLUMNNAME_POReference);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,8 @@
package de.metas.inoutcandidate.api;

import java.sql.Timestamp;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Stream;

import javax.annotation.Nullable;

import de.metas.inoutcandidate.ShipmentScheduleId;
import org.adempiere.ad.dao.IQueryBuilder;
import org.adempiere.ad.dao.IQueryFilter;
import org.adempiere.util.lang.impl.TableRecordReference;
import org.compiere.model.I_M_InOutLine;
import org.compiere.model.MOrderLine;

import com.google.common.collect.ImmutableList;

import de.metas.bpartner.BPartnerId;
import de.metas.inoutcandidate.ShipmentScheduleId;
import de.metas.inoutcandidate.model.I_M_ShipmentSchedule;
import de.metas.interfaces.I_C_OrderLine;
import de.metas.invoicecandidate.model.I_C_Invoice_Candidate;
Expand All @@ -28,12 +11,26 @@
import de.metas.process.PInstanceId;
import de.metas.product.ProductId;
import de.metas.util.ISingletonService;
import lombok.NonNull;
import org.adempiere.ad.dao.IQueryBuilder;
import org.adempiere.ad.dao.IQueryFilter;
import org.adempiere.util.lang.impl.TableRecordReference;
import org.compiere.model.I_M_InOutLine;
import org.compiere.model.MOrderLine;

import javax.annotation.Nullable;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Stream;

/**
* Implementers give database access to {@link I_M_ShipmentSchedule} instances (DAO).
*
* @author ts
*
*/
public interface IShipmentSchedulePA extends ISingletonService
{
Expand All @@ -53,6 +50,8 @@ public interface IShipmentSchedulePA extends ISingletonService
@Nullable
ShipmentScheduleId getShipmentScheduleIdByOrderLineId(OrderLineId orderLineId);

boolean existsExportedShipmentScheduleForOrder(@NonNull final OrderId orderId);

Set<ShipmentScheduleId> retrieveUnprocessedIdsByOrderId(OrderId orderId);

/**
Expand Down Expand Up @@ -96,6 +95,9 @@ public interface IShipmentSchedulePA extends ISingletonService
* <li>The selection will be created out of transaction
* </ul>
*/

void updateExportStatus(final String exportStatus, final PInstanceId pinstanceId);

IQueryBuilder<I_M_ShipmentSchedule> createQueryForShipmentScheduleSelection(Properties ctx, IQueryFilter<I_M_ShipmentSchedule> userSelectionFilter);

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,47 +1,17 @@
package de.metas.inoutcandidate.api.impl;

import static org.adempiere.model.InterfaceWrapperHelper.load;
import static org.adempiere.model.InterfaceWrapperHelper.loadByRepoIdAwares;
import static org.adempiere.model.InterfaceWrapperHelper.loadByRepoIdAwaresOutOfTrx;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Stream;

import javax.annotation.Nullable;

import org.adempiere.ad.dao.ICompositeQueryFilter;
import org.adempiere.ad.dao.IQueryBL;
import org.adempiere.ad.dao.IQueryBuilder;
import org.adempiere.ad.dao.IQueryFilter;
import org.adempiere.ad.dao.impl.ModelColumnNameValue;
import org.adempiere.ad.trx.api.ITrx;
import org.adempiere.exceptions.AdempiereException;
import org.adempiere.model.InterfaceWrapperHelper;
import org.adempiere.model.PlainContextAware;
import org.adempiere.util.lang.impl.TableRecordReference;
import org.compiere.model.IQuery;
import org.compiere.model.MOrderLine;
import org.slf4j.Logger;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;

import de.metas.bpartner.BPartnerId;
import de.metas.cache.CacheMgt;
import de.metas.cache.model.CacheInvalidateMultiRequest;
import de.metas.inout.model.I_M_InOutLine;
import de.metas.inoutcandidate.ShipmentScheduleId;
import de.metas.inoutcandidate.api.IShipmentScheduleAllocDAO;
import de.metas.inoutcandidate.api.IShipmentSchedulePA;
import de.metas.inoutcandidate.api.OlAndSched;
import de.metas.inoutcandidate.exportaudit.APIExportStatus;
import de.metas.inoutcandidate.ShipmentScheduleId;
import de.metas.inoutcandidate.invalidation.IShipmentScheduleInvalidateRepository;
import de.metas.inoutcandidate.model.I_M_ShipmentSchedule;
Expand All @@ -57,18 +27,49 @@
import de.metas.util.Check;
import de.metas.util.Services;
import lombok.NonNull;
import org.adempiere.ad.dao.ICompositeQueryFilter;
import org.adempiere.ad.dao.IQueryBL;
import org.adempiere.ad.dao.IQueryBuilder;
import org.adempiere.ad.dao.IQueryFilter;
import org.adempiere.ad.dao.impl.ModelColumnNameValue;
import org.adempiere.ad.trx.api.ITrx;
import org.adempiere.exceptions.AdempiereException;
import org.adempiere.model.InterfaceWrapperHelper;
import org.adempiere.model.PlainContextAware;
import org.adempiere.util.lang.impl.TableRecordReference;
import org.compiere.model.IQuery;
import org.compiere.model.MOrderLine;
import org.slf4j.Logger;

import javax.annotation.Nullable;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Stream;

import static org.adempiere.model.InterfaceWrapperHelper.load;
import static org.adempiere.model.InterfaceWrapperHelper.loadByRepoIdAwares;
import static org.adempiere.model.InterfaceWrapperHelper.loadByRepoIdAwaresOutOfTrx;

public class ShipmentSchedulePA implements IShipmentSchedulePA
{
private final static Logger logger = LogManager.getLogger(ShipmentSchedulePA.class);
private final IQueryBL queryBL = Services.get(IQueryBL.class);

/** When mass cache invalidation, above this threshold we will invalidate ALL shipment schedule records instead of particular IDS */
/**
* When mass cache invalidation, above this threshold we will invalidate ALL shipment schedule records instead of particular IDS
*/
private static final int CACHE_INVALIDATE_ALL_THRESHOLD = 200;

/**
* Order by clause used to fetch {@link I_M_ShipmentSchedule}s.
*
* <p>
* NOTE: this ordering is VERY important because that's the order in which QtyOnHand will be allocated too.
*/
private static final String ORDER_CLAUSE = "\n ORDER BY " //
Expand Down Expand Up @@ -148,6 +149,19 @@ public ShipmentScheduleId getShipmentScheduleIdByOrderLineId(@NonNull final Orde
.firstIdOnly(ShipmentScheduleId::ofRepoIdOrNull);
}

@Override
public boolean existsExportedShipmentScheduleForOrder(@NonNull final OrderId orderId)
{
return queryBL
.createQueryBuilder(I_M_ShipmentSchedule.class)
.addOnlyActiveRecordsFilter()
.addEqualsFilter(I_M_ShipmentSchedule.COLUMNNAME_C_Order_ID, orderId)
.addEqualsFilter(I_M_ShipmentSchedule.COLUMNNAME_Processed, false)
.addInArrayFilter(I_M_ShipmentSchedule.COLUMNNAME_ExportStatus, APIExportStatus.EXPORTED_STATES)
.create()
.anyMatch();
}

private IQueryBuilder<I_M_ShipmentSchedule> getByOrderLineIdQuery(@NonNull final OrderLineId orderLineId)
{
return queryBL
Expand Down Expand Up @@ -287,14 +301,13 @@ public Stream<I_M_ShipmentSchedule> streamUnprocessedByPartnerIdAndAllowConsolid

/**
* Mass-update a given shipment schedule column.
*
* <p>
* If there were any changes and the invalidate parameter is on true, those shipment schedules will be invalidated.
*
* @param inoutCandidateColumnName {@link I_M_ShipmentSchedule}'s column to update
* @param value value to set (you can also use {@link ModelColumnNameValue})
* @param updateOnlyIfNull if true then it will update only if column value is null (not set)
* @param selectionId ShipmentSchedule selection (AD_PInstance_ID)
* @param trxName
* @param value value to set (you can also use {@link ModelColumnNameValue})
* @param updateOnlyIfNull if true then it will update only if column value is null (not set)
* @param selectionId ShipmentSchedule selection (AD_PInstance_ID)
*/
private final <ValueType> void updateColumnForSelection(
final String inoutCandidateColumnName,
Expand All @@ -309,7 +322,7 @@ private final <ValueType> void updateColumnForSelection(
.createQueryBuilder(I_M_ShipmentSchedule.class)
.setOnlySelection(selectionId)
.addEqualsFilter(I_M_ShipmentSchedule.COLUMNNAME_Processed, false) // do not touch the processed shipment schedules
;
;

if (updateOnlyIfNull)
{
Expand Down Expand Up @@ -433,6 +446,18 @@ public void updatePreparationDate_Override(final Timestamp preparationDate, fina
);
}

@Override
public void updateExportStatus(final String exportStatus, final PInstanceId pinstanceId)
{
updateColumnForSelection(
I_M_ShipmentSchedule.COLUMNNAME_ExportStatus,
exportStatus,
false /* updateOnlyIfNull */,
pinstanceId,
false /* invalidate */
);
}

@Override
public IQueryBuilder<I_M_ShipmentSchedule> createQueryForShipmentScheduleSelection(final Properties ctx, final IQueryFilter<I_M_ShipmentSchedule> userSelectionFilter)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ void updateSchedules(final Properties ctx, final List<OlAndSched> olsAndScheds)
}
}


ShipmentSchedulesDuringUpdate generate_FirstRun(
@NonNull final Properties ctx,
@NonNull final List<OlAndSched> lines)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
* <http://www.gnu.org/licenses/gpl-2.0.html>.
* #L%
*/

package de.metas.inoutcandidate.exportaudit;

import lombok.NonNull;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
package de.metas.inoutcandidate.exportaudit;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import de.metas.inoutcandidate.model.X_M_ShipmentSchedule;
import de.metas.order.InvoiceRule;
Expand All @@ -32,7 +33,6 @@
import org.adempiere.exceptions.AdempiereException;

import javax.annotation.Nullable;
import java.sql.Timestamp;
import java.util.Arrays;

public enum APIExportStatus implements ReferenceListAwareEnum
Expand All @@ -44,6 +44,8 @@ public enum APIExportStatus implements ReferenceListAwareEnum
ExportedAndForwarded(X_M_ShipmentSchedule.EXPORTSTATUS_EXPORTED_AND_FORWARDED),
ExportedAndError(X_M_ShipmentSchedule.EXPORTSTATUS_EXPORTED_FORWARD_ERROR);

public static final ImmutableSet<APIExportStatus> EXPORTED_STATES = ImmutableSet.of(Exported, ExportedAndError, ExportedAndForwarded);

@Getter
private final String code;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package de.metas.inoutcandidate.modelvalidator;

import de.metas.i18n.AdMessageKey;
import de.metas.inoutcandidate.api.IShipmentConstraintsBL;
import de.metas.inoutcandidate.api.IShipmentSchedulePA;
import de.metas.order.OrderId;
import de.metas.util.Services;
import org.adempiere.ad.modelvalidator.annotations.DocValidate;
import org.adempiere.ad.modelvalidator.annotations.Interceptor;
import org.adempiere.exceptions.AdempiereException;
import org.compiere.model.I_C_Order;
import org.compiere.model.ModelValidator;

import de.metas.i18n.AdMessageKey;
import de.metas.inoutcandidate.api.IShipmentConstraintsBL;
import de.metas.util.Services;

/*
* #%L
* de.metas.swat.base
Expand All @@ -20,12 +21,12 @@
* 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>.
Expand All @@ -35,17 +36,18 @@
@Interceptor(I_C_Order.class)
public class C_Order
{
private final IShipmentSchedulePA shipmentSchedulePA = Services.get(IShipmentSchedulePA.class);
private static final AdMessageKey MSG_CannotCompleteOrder_DeliveryStop = AdMessageKey.of("CannotCompleteOrder_DeliveryStop");
private static final AdMessageKey MSG_REACTIVATION_VOID_NOT_ALLOWED = AdMessageKey.of("salesorder.shipmentschedule.exported");

@DocValidate(timings = ModelValidator.TIMING_BEFORE_PREPARE)
public void assertNotDeliveryStopped(final I_C_Order order)
{
// Makes sense only for sales orders
if(!order.isSOTrx())
if (!order.isSOTrx())
{
return;
}

final int billPartnerId = order.getBill_BPartner_ID();
final int deliveryStopShipmentConstraintId = Services.get(IShipmentConstraintsBL.class).getDeliveryStopShipmentConstraintId(billPartnerId);
final boolean isDeliveryStop = deliveryStopShipmentConstraintId > 0;
Expand All @@ -55,4 +57,21 @@ public void assertNotDeliveryStopped(final I_C_Order order)
.markAsUserValidationError();
}
}

@DocValidate(timings = { ModelValidator.TIMING_BEFORE_REACTIVATE,
ModelValidator.TIMING_BEFORE_REVERSEACCRUAL,
ModelValidator.TIMING_BEFORE_REVERSECORRECT,
ModelValidator.TIMING_BEFORE_VOID })
public void assertReActivationAllowed(final I_C_Order order)
{
if (!order.isSOTrx())
{
return; // we can spare us the effort
}
if (shipmentSchedulePA.existsExportedShipmentScheduleForOrder(OrderId.ofRepoId(order.getC_Order_ID())))
{
throw new AdempiereException(MSG_REACTIVATION_VOID_NOT_ALLOWED)
.markAsUserValidationError();
}
}
}
Loading

0 comments on commit 2b85d67

Please sign in to comment.