diff --git a/de.metas.contracts/src/main/java/de/metas/contracts/IFlatrateBL.java b/de.metas.contracts/src/main/java/de/metas/contracts/IFlatrateBL.java index da5af3af4c9..66c99a281be 100644 --- a/de.metas.contracts/src/main/java/de/metas/contracts/IFlatrateBL.java +++ b/de.metas.contracts/src/main/java/de/metas/contracts/IFlatrateBL.java @@ -198,11 +198,21 @@ I_C_Flatrate_Term createTerm(IContextAware context, void voidIt(I_C_Flatrate_Term term); /** - * Check if there are terms for the same that have a time period overlapping with the given term and match with the same product or product category. + * Return {@code true} if the given term (by virtue of its conditions-type) does not define a set of invoice candidates that "belong" to it. + * Examples for ICs that belong to a contract in this sense are e.g. ICs that shall trigger a refund, a commission payment or are empties (e.g. empty pallets). + * In all this cases, a completed term matches a set of ICs and for every given ICs, we need to make sure that max. one term matches it. * + * Also see {@link #hasOverlappingTerms(I_C_Flatrate_Term)}. + */ + boolean isAllowedToOverlapWithOtherTerms(I_C_Flatrate_Term term); + + /** + * Check if there are terms for the same bPartner that have a time period overlapping with the given term and match with the same product or product category. + *
+ * Note that overlapping need to be prevented for those types of terms (like refund contracts or refundable contracts) to which newly created invoice candidates need to be mapped.
+ * Overlapping is no problem for subscription contracts.
*
- * @param term
- * @return
+ * Also see {@link #isAllowedToOverlapWithOtherTerms(I_C_Flatrate_Term)}.
*/
boolean hasOverlappingTerms(final I_C_Flatrate_Term term);
diff --git a/de.metas.contracts/src/main/java/de/metas/contracts/IFlatrateDAO.java b/de.metas.contracts/src/main/java/de/metas/contracts/IFlatrateDAO.java
index 90387d2fe1a..6c436dc50ab 100644
--- a/de.metas.contracts/src/main/java/de/metas/contracts/IFlatrateDAO.java
+++ b/de.metas.contracts/src/main/java/de/metas/contracts/IFlatrateDAO.java
@@ -155,7 +155,7 @@ public interface IFlatrateDAO extends ISingletonService
void updateQtyActualFromDataEntry(I_C_Flatrate_DataEntry dataEntry);
/**
- * Retrieves the flatrate term matching the given invoice candidate or null
.
+ * Retrieves the flatrate term matching the given invoice candidate (or {@code code>}) by using {@link I_C_Flatrate_Matching} Records.
* Basically calls {@link #retrieveTerms(Properties, int, Timestamp, int, int, int, String)}, but discards all terms that have IsSimulation=Y
.
*
* @return the term or null
diff --git a/de.metas.contracts/src/main/java/de/metas/contracts/impl/FlatrateBL.java b/de.metas.contracts/src/main/java/de/metas/contracts/impl/FlatrateBL.java
index 543af1d31c3..423a49a3d1b 100644
--- a/de.metas.contracts/src/main/java/de/metas/contracts/impl/FlatrateBL.java
+++ b/de.metas.contracts/src/main/java/de/metas/contracts/impl/FlatrateBL.java
@@ -1553,17 +1553,19 @@ public void complete(final I_C_Flatrate_Term term)
@Override
public void completeIfValid(final I_C_Flatrate_Term term)
{
- final boolean hasOverlappingTerms = hasOverlappingTerms(term);
- if (hasOverlappingTerms)
+ if (!isAllowedToOverlapWithOtherTerms(term))
{
+ final boolean hasOverlappingTerms = hasOverlappingTerms(term);
+ if (hasOverlappingTerms)
+ {
- Loggables.get().addLog(Services.get(IMsgBL.class).getMsg(
- Env.getCtx(),
- MSG_HasOverlapping_Term,
- new Object[] { term.getC_Flatrate_Term_ID(), term.getBill_BPartner().getValue() }));
- return;
+ Loggables.get().addLog(Services.get(IMsgBL.class).getMsg(
+ Env.getCtx(),
+ MSG_HasOverlapping_Term,
+ new Object[] { term.getC_Flatrate_Term_ID(), term.getBill_BPartner().getValue() }));
+ return;
+ }
}
-
complete(term);
}
@@ -1575,6 +1577,18 @@ public void voidIt(final I_C_Flatrate_Term term)
}
+ @Override
+ public boolean isAllowedToOverlapWithOtherTerms(@NonNull final I_C_Flatrate_Term term)
+ {
+ final String typeConditions = term.getType_Conditions();
+
+ // These contract types do not match "other" ICs such as ICs that trigger a commission, or IC that belong to a vendor's empty package (pallette/TU).
+ // Therefore they can overlap without causing us any problems.
+ final boolean allowedToOverlapWithOtherTerms = X_C_Flatrate_Term.TYPE_CONDITIONS_Subscription.equals(typeConditions)
+ || X_C_Flatrate_Term.TYPE_CONDITIONS_Procurement.equals(typeConditions);
+ return allowedToOverlapWithOtherTerms;
+ }
+
@Override
public boolean hasOverlappingTerms(final I_C_Flatrate_Term newTerm)
{
diff --git a/de.metas.contracts/src/main/java/de/metas/contracts/interceptor/C_Flatrate_Term.java b/de.metas.contracts/src/main/java/de/metas/contracts/interceptor/C_Flatrate_Term.java
index 92642f05353..e024003f95c 100644
--- a/de.metas.contracts/src/main/java/de/metas/contracts/interceptor/C_Flatrate_Term.java
+++ b/de.metas.contracts/src/main/java/de/metas/contracts/interceptor/C_Flatrate_Term.java
@@ -493,6 +493,10 @@ public void preventOverlappingTerms_OnComplete(final I_C_Flatrate_Term term)
// services
final IFlatrateBL flatrateBL = Services.get(IFlatrateBL.class);
+ if (flatrateBL.isAllowedToOverlapWithOtherTerms(term))
+ {
+ return;
+ }
final boolean hasOverlappingTerms = flatrateBL.hasOverlappingTerms(term);
if (hasOverlappingTerms)
{
@@ -518,7 +522,7 @@ private void setMasterEndDate(final I_C_Flatrate_Term term)
term.setMasterEndDate(masterEndDate);
}
-
+
private Timestamp computeMasterEndDateIfC_FlatrateTerm_Next_IDChanged(@NonNull final I_C_Flatrate_Term term, Timestamp masterEndDate)
{
if (InterfaceWrapperHelper.isValueChanged(term, I_C_Flatrate_Term.COLUMNNAME_C_FlatrateTerm_Next_ID) && !term.isAutoRenew())
@@ -532,7 +536,7 @@ private Timestamp computeMasterEndDateIfC_FlatrateTerm_Next_IDChanged(@NonNull f
masterEndDate = term.getEndDate();
}
}
-
+
return masterEndDate;
}
}