hg merge release-4.1 (merge release4.1 into development)

This commit is contained in:
Carlos Ruiz 2017-10-13 16:41:48 +02:00
commit ea5192578b
35 changed files with 1243 additions and 656 deletions

View File

@ -0,0 +1,11 @@
SET SQLBLANKLINES ON
SET DEFINE OFF
-- IDEMPIERE-3488 Improvement to Error Message for Negative Inventory Disallow exception
-- Sep 14, 2017 6:28:55 PM GMT+08:00
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','The {0} warehouse does not allow negative inventory for Product = {1}, ASI = {2}, Locator = {3} (Shortage of {4})',0,0,'Y',TO_DATE('2017-09-14 18:28:54','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2017-09-14 18:28:54','YYYY-MM-DD HH24:MI:SS'),100,200431,'NegativeInventoryDisallowedInfo','D','1a686715-09f5-4437-9885-882719423bd1')
;
SELECT register_migration_script('201709151000_IDEMPIERE-3488.sql') FROM dual
;

View File

@ -0,0 +1,23 @@
SET SQLBLANKLINES ON
SET DEFINE OFF
-- IDEMPIERE-3517 Report Cube - OrgTrx Dimension is not displayed
-- Oct 13, 2017 2:04:42 PM CEST
UPDATE AD_Field SET DisplayLogic='@$Element_OT@=Y', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2017-10-13 14:04:42','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=2344
;
-- Oct 13, 2017 2:05:12 PM CEST
UPDATE AD_Field SET DisplayLogic='@$Element_AY@=Y ', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2017-10-13 14:05:12','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=3886
;
-- Oct 13, 2017 2:05:54 PM CEST
UPDATE AD_Field SET DisplayLogic='@$Element_OT@=Y', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2017-10-13 14:05:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=57023
;
-- Oct 13, 2017 2:06:02 PM CEST
UPDATE AD_Field SET DisplayLogic='@$Element_AY@=Y ', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2017-10-13 14:06:02','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=57013
;
SELECT register_migration_script('201710131406_IDEMPIERE-3517.sql') FROM dual
;

View File

@ -0,0 +1,14 @@
SET SQLBLANKLINES ON
SET DEFINE OFF
-- IDEMPIERE-3519:column updated, created of c_salesregion_trl isn't yet sync so miss default value
-- Oct 13, 2017 12:41:29 PM ICT
ALTER TABLE C_SalesRegion_Trl MODIFY Created DATE DEFAULT SYSDATE
;
-- Oct 13, 2017 12:41:53 PM ICT
ALTER TABLE C_SalesRegion_Trl MODIFY Updated DATE DEFAULT SYSDATE
;
SELECT register_migration_script('201710131604-IDEMPIERE-3519.sql') FROM dual
;

View File

@ -0,0 +1,8 @@
-- IDEMPIERE-3488 Improvement to Error Message for Negative Inventory Disallow exception
-- Sep 14, 2017 6:28:55 PM GMT+08:00
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','The {0} warehouse does not allow negative inventory for Product = {1}, ASI = {2}, Locator = {3} (Shortage of {4})',0,0,'Y',TO_TIMESTAMP('2017-09-14 18:28:54','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2017-09-14 18:28:54','YYYY-MM-DD HH24:MI:SS'),100,200431,'NegativeInventoryDisallowedInfo','D','1a686715-09f5-4437-9885-882719423bd1')
;
SELECT register_migration_script('201709151000_IDEMPIERE-3488.sql') FROM dual
;

View File

@ -0,0 +1,20 @@
-- IDEMPIERE-3517 Report Cube - OrgTrx Dimension is not displayed
-- Oct 13, 2017 2:04:42 PM CEST
UPDATE AD_Field SET DisplayLogic='@$Element_OT@=Y', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2017-10-13 14:04:42','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=2344
;
-- Oct 13, 2017 2:05:12 PM CEST
UPDATE AD_Field SET DisplayLogic='@$Element_AY@=Y ', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2017-10-13 14:05:12','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=3886
;
-- Oct 13, 2017 2:05:54 PM CEST
UPDATE AD_Field SET DisplayLogic='@$Element_OT@=Y', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2017-10-13 14:05:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=57023
;
-- Oct 13, 2017 2:06:02 PM CEST
UPDATE AD_Field SET DisplayLogic='@$Element_AY@=Y ', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2017-10-13 14:06:02','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=57013
;
SELECT register_migration_script('201710131406_IDEMPIERE-3517.sql') FROM dual
;

View File

@ -0,0 +1,11 @@
-- IDEMPIERE-3519:column updated, created of c_salesregion_trl isn't yet sync so miss default value
-- Oct 13, 2017 12:41:29 PM ICT
INSERT INTO t_alter_column values('c_salesregion_trl','Created','TIMESTAMP',null,'statement_timestamp()')
;
-- Oct 13, 2017 12:41:53 PM ICT
INSERT INTO t_alter_column values('c_salesregion_trl','Updated','TIMESTAMP',null,'statement_timestamp()')
;
SELECT register_migration_script('201710131604-IDEMPIERE-3519.sql') FROM dual
;

View File

@ -72,7 +72,7 @@ public class EventManager implements IEventManager {
*/ */
public static IEventManager getInstance() { public static IEventManager getInstance() {
synchronized (mutex) { synchronized (mutex) {
if (instance == null) { while (instance == null) {
try { try {
mutex.wait(10000); mutex.wait(10000);
} catch (InterruptedException e) { } catch (InterruptedException e) {

View File

@ -0,0 +1,88 @@
/*******************************************************************************
* Copyright (C) 2017 Trek Global Inc. *
* Copyright (C) 2017 Low Heng Sin *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. 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, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
*******************************************************************************/
package org.adempiere.exceptions;
import java.math.BigDecimal;
import java.util.Properties;
import org.compiere.model.MAttributeSetInstance;
import org.compiere.model.MLocator;
import org.compiere.model.MProduct;
import org.compiere.model.MSysConfig;
import org.compiere.model.MWarehouse;
import org.compiere.util.Env;
import org.compiere.util.Msg;
/**
*
* @author hengsin
*
*/
public class NegativeInventoryDisallowedException extends AdempiereException
{
/**
*
*/
private static final long serialVersionUID = 253224414462489886L;
private int M_Warehouse_ID;
private int M_Product_ID;
private int M_AttributeSetInstance_ID;
private int M_Locator_ID;
private BigDecimal QtyOnHand;
private BigDecimal MovementQty;
public NegativeInventoryDisallowedException(Properties ctx, int M_Warehouse_ID, int M_Product_ID, int M_AttributeSetInstance_ID, int M_Locator_ID,
BigDecimal QtyOnHand, BigDecimal MovementQty)
{
super(Msg.getMsg(ctx, "NegativeInventoryDisallowedInfo", new Object[] {
MWarehouse.get(ctx, M_Warehouse_ID).getName(),
MProduct.get(ctx, M_Product_ID).getValue() + MSysConfig.getValue(MSysConfig.IDENTIFIER_SEPARATOR, "_", Env.getAD_Client_ID(ctx)) + MProduct.get(ctx, M_Product_ID).getName(),
M_AttributeSetInstance_ID > 0 ? MAttributeSetInstance.get(ctx, M_AttributeSetInstance_ID, M_Product_ID).getDescription() : "0",
M_Locator_ID > 0 ? MLocator.get(ctx, M_Locator_ID).getValue() : "0", MovementQty.subtract(QtyOnHand)
}));
this.M_Warehouse_ID = M_Warehouse_ID;
this.M_Product_ID = M_Product_ID;
this.M_AttributeSetInstance_ID = M_AttributeSetInstance_ID;
this.M_Locator_ID = M_Locator_ID;
this.QtyOnHand = QtyOnHand;
this.MovementQty = MovementQty;
}
public int getM_Warehouse_ID() {
return M_Warehouse_ID;
}
public int getM_Product_ID() {
return M_Product_ID;
}
public int getM_AttributeSetInstance_ID() {
return M_AttributeSetInstance_ID;
}
public int getM_Locator_ID() {
return M_Locator_ID;
}
public BigDecimal getQtyOnHand() {
return QtyOnHand;
}
public BigDecimal getMovementQty() {
return MovementQty;
}
}

View File

@ -1326,6 +1326,8 @@ public class GridTabCSVImporter implements IGridTabImporter
return (new Optional(new ParseBigDecimal(new DecimalFormatSymbols(Language.getLoginLanguage().getLocale())))); return (new Optional(new ParseBigDecimal(new DecimalFormatSymbols(Language.getLoginLanguage().getLocale()))));
} else if (DisplayType.YesNo == field.getDisplayType()) { } else if (DisplayType.YesNo == field.getDisplayType()) {
return (new Optional(new ParseBool("y", "n"))); return (new Optional(new ParseBool("y", "n")));
} else if (DisplayType.TextLong == field.getDisplayType()) {
return (new Optional(new StrMinMax(1, Long.MAX_VALUE)));
} else if (DisplayType.isText(field.getDisplayType())) { } else if (DisplayType.isText(field.getDisplayType())) {
return (new Optional(new StrMinMax(1, field.getFieldLength()))); return (new Optional(new StrMinMax(1, field.getFieldLength())));
} else { // optional lookups and text } else { // optional lookups and text

View File

@ -555,6 +555,12 @@ public abstract class Doc
p_Error = loadDocumentDetails(); p_Error = loadDocumentDetails();
if (p_Error != null) if (p_Error != null)
return p_Error; return p_Error;
if (isDeferPosting())
{
unlock();
p_Status = STATUS_NotPosted;
return null;
}
Trx trx = Trx.get(getTrxName(), true); Trx trx = Trx.get(getTrxName(), true);
// Delete existing Accounting // Delete existing Accounting
@ -2304,4 +2310,11 @@ public abstract class Doc
public ArrayList<Fact> getFacts() { public ArrayList<Fact> getFacts() {
return m_fact; return m_fact;
} }
/**
* Return document whether need to defer posting or not
*/
public boolean isDeferPosting() {
return false;
}
} // Doc } // Doc

View File

@ -77,6 +77,7 @@ public class Doc_MatchPO extends Doc
private ProductCost m_pc; private ProductCost m_pc;
private int m_M_AttributeSetInstance_ID = 0; private int m_M_AttributeSetInstance_ID = 0;
private MMatchPO m_matchPO; private MMatchPO m_matchPO;
private boolean m_deferPosting = false;
/** /**
* Load Specific Document Details * Load Specific Document Details
@ -103,6 +104,24 @@ public class Doc_MatchPO extends Doc
m_pc = new ProductCost (Env.getCtx(), m_pc = new ProductCost (Env.getCtx(),
getM_Product_ID(), m_M_AttributeSetInstance_ID, getTrxName()); getM_Product_ID(), m_M_AttributeSetInstance_ID, getTrxName());
m_pc.setQty(getQty()); m_pc.setQty(getQty());
if (m_M_InOutLine_ID == 0)
{
MMatchPO[] matchPOs = MMatchPO.getOrderLine(getCtx(), m_oLine.getC_OrderLine_ID(), getTrxName());
for (MMatchPO matchPO : matchPOs)
{
if (matchPO.getM_InOutLine_ID() > 0 && matchPO.getC_InvoiceLine_ID() == 0)
{
m_M_InOutLine_ID = matchPO.getM_InOutLine_ID();
break;
}
}
}
if (m_M_InOutLine_ID == 0) // Defer posting if not matched to Shipment
{
m_deferPosting = true;
}
return null; return null;
} // loadDocumentDetails } // loadDocumentDetails
@ -487,4 +506,11 @@ public class Doc_MatchPO extends Doc
return null; return null;
} }
@Override
public boolean isDeferPosting() {
return m_deferPosting;
}
} // Doc_MatchPO } // Doc_MatchPO

View File

@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.logging.Level; import java.util.logging.Level;
import org.compiere.model.MAcctSchema; import org.compiere.model.MAcctSchema;
import org.compiere.model.MCostDetail;
import org.compiere.model.MProduct; import org.compiere.model.MProduct;
import org.compiere.model.MProject; import org.compiere.model.MProject;
import org.compiere.model.MProjectIssue; import org.compiere.model.MProjectIssue;
@ -157,6 +158,20 @@ public class Doc_ProjectIssue extends Doc
cr.setM_Locator_ID(m_line.getM_Locator_ID()); cr.setM_Locator_ID(m_line.getM_Locator_ID());
cr.setLocationFromLocator(m_line.getM_Locator_ID(), true); // from Loc cr.setLocationFromLocator(m_line.getM_Locator_ID(), true); // from Loc
// //
if (product != null && product.get_ID() > 0 && !product.isService() && product.isStocked()) {
BigDecimal costDetailQty = m_line.getQty();
BigDecimal costDetailAmt = cost;
if (!MCostDetail.createProjectIssue(as, m_line.getAD_Org_ID(),
m_line.getM_Product_ID(), m_line.getM_AttributeSetInstance_ID(),
m_line.get_ID(), 0,
costDetailAmt, costDetailQty,
m_line.getDescription(), getTrxName()))
{
p_Error = "Failed to create cost detail record";
return null;
}
}
//
ArrayList<Fact> facts = new ArrayList<Fact>(); ArrayList<Fact> facts = new ArrayList<Fact>();
facts.add(fact); facts.add(fact);
return facts; return facts;
@ -203,6 +218,8 @@ public class Doc_ProjectIssue extends Doc
DB.close(rs, pstmt); DB.close(rs, pstmt);
pstmt = null; rs = null; pstmt = null; rs = null;
} }
if (retValue != null)
retValue = retValue.multiply(m_line.getQty());
return retValue; return retValue;
} // getPOCost(); } // getPOCost();

View File

@ -529,6 +529,70 @@ public class MCostDetail extends X_M_CostDetail
return ok; return ok;
} // createMatchInvoice } // createMatchInvoice
/**
* Create Cost Detail for Project Issue.
* Called from Doc_ProjectIssue
* @param as accounting schema
* @param AD_Org_ID org
* @param M_Product_ID product
* @param M_AttributeSetInstance_ID asi
* @param C_ProjectIssue_ID project issue line
* @param M_CostElement_ID optional cost element
* @param Amt amt total amount
* @param Qty qty
* @param Description optional description
* @param trxName transaction
* @return true if no error
*/
public static boolean createProjectIssue(MAcctSchema as, int AD_Org_ID,
int M_Product_ID, int M_AttributeSetInstance_ID,
int C_ProjectIssue_ID, int M_CostElement_ID,
BigDecimal Amt, BigDecimal Qty,
String Description, String trxName)
{
MCostDetail cd = get (as.getCtx(), "C_ProjectIssue_ID=? AND Coalesce(M_CostElement_ID,0)="+M_CostElement_ID,
C_ProjectIssue_ID, M_AttributeSetInstance_ID, as.getC_AcctSchema_ID(), trxName);
//
if (cd == null) // createNew
{
cd = new MCostDetail (as, AD_Org_ID,
M_Product_ID, M_AttributeSetInstance_ID,
M_CostElement_ID,
Amt, Qty, Description, trxName);
cd.setC_ProjectIssue_ID(C_ProjectIssue_ID);
}
else
{
if (cd.isProcessed())
{
cd.setDeltaAmt(Amt.subtract(cd.getAmt()));
cd.setDeltaQty(Qty.subtract(cd.getQty()));
}
else
{
cd.setDeltaAmt(BigDecimal.ZERO);
cd.setDeltaQty(BigDecimal.ZERO);
cd.setAmt(Amt);
cd.setQty(Qty);
}
if (cd.isDelta())
{
cd.setProcessed(false);
cd.setAmt(Amt);
cd.setQty(Qty);
}
else if (cd.isProcessed())
return true; // nothing to do
}
boolean ok = cd.save();
if (ok && !cd.isProcessed())
{
ok = cd.process();
}
if (s_log.isLoggable(Level.CONFIG)) s_log.config("(" + ok + ") " + cd);
return ok;
} // createProjectIssue
/************************************************************************** /**************************************************************************
* Get Cost Detail * Get Cost Detail
* @param ctx context * @param ctx context
@ -1319,10 +1383,14 @@ public class MCostDetail extends X_M_CostDetail
log.warning("Unknown Type: " + toString()); log.warning("Unknown Type: " + toString());
return false; return false;
} }
setCurrentCostPrice(cost.getCurrentCostPrice());
setCurrentQty(cost.getCurrentQty()); //Should only update cost detail with value from as costing method
setCumulatedAmt(cost.getCumulatedAmt()); if(as.getCostingMethod().equals(ce.getCostingMethod())) {
setCumulatedQty(cost.getCumulatedQty()); setCurrentCostPrice(cost.getCurrentCostPrice());
setCurrentQty(cost.getCurrentQty());
setCumulatedAmt(cost.getCumulatedAmt());
setCumulatedQty(cost.getCumulatedQty());
}
//update history //update history
history.setNewQty(cost.getCurrentQty()); history.setNewQty(cost.getCurrentQty());

View File

@ -26,6 +26,7 @@ import java.util.Properties;
import java.util.logging.Level; import java.util.logging.Level;
import org.adempiere.exceptions.AdempiereException; import org.adempiere.exceptions.AdempiereException;
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
import org.adempiere.exceptions.PeriodClosedException; import org.adempiere.exceptions.PeriodClosedException;
import org.compiere.print.MPrintFormat; import org.compiere.print.MPrintFormat;
import org.compiere.print.ReportEngine; import org.compiere.print.ReportEngine;
@ -1286,6 +1287,7 @@ public class MInOut extends X_M_InOut implements DocAction
if (log.isLoggable(Level.INFO)) log.info(toString()); if (log.isLoggable(Level.INFO)) log.info(toString());
StringBuilder info = new StringBuilder(); StringBuilder info = new StringBuilder();
StringBuilder errors = new StringBuilder();
// For all lines // For all lines
MInOutLine[] lines = getLines(false); MInOutLine[] lines = getLines(false);
for (int lineIndex = 0; lineIndex < lines.length; lineIndex++) for (int lineIndex = 0; lineIndex < lines.length; lineIndex++)
@ -1293,353 +1295,326 @@ public class MInOut extends X_M_InOut implements DocAction
MInOutLine sLine = lines[lineIndex]; MInOutLine sLine = lines[lineIndex];
MProduct product = sLine.getProduct(); MProduct product = sLine.getProduct();
// Qty & Type try
String MovementType = getMovementType();
BigDecimal Qty = sLine.getMovementQty();
if (MovementType.charAt(1) == '-') // C- Customer Shipment - V- Vendor Return
Qty = Qty.negate();
// Update Order Line
MOrderLine oLine = null;
if (sLine.getC_OrderLine_ID() != 0)
{ {
oLine = new MOrderLine (getCtx(), sLine.getC_OrderLine_ID(), get_TrxName()); // Qty & Type
if (log.isLoggable(Level.FINE)) log.fine("OrderLine - Reserved=" + oLine.getQtyReserved() String MovementType = getMovementType();
+ ", Delivered=" + oLine.getQtyDelivered()); BigDecimal Qty = sLine.getMovementQty();
} if (MovementType.charAt(1) == '-') // C- Customer Shipment - V- Vendor Return
Qty = Qty.negate();
// Update Order Line
// Load RMA Line MOrderLine oLine = null;
MRMALine rmaLine = null; if (sLine.getC_OrderLine_ID() != 0)
if (sLine.getM_RMALine_ID() != 0)
{
rmaLine = new MRMALine(getCtx(), sLine.getM_RMALine_ID(), get_TrxName());
}
if (log.isLoggable(Level.INFO)) log.info("Line=" + sLine.getLine() + " - Qty=" + sLine.getMovementQty());
// Stock Movement - Counterpart MOrder.reserveStock
if (product != null
&& product.isStocked() )
{
//Ignore the Material Policy when is Reverse Correction
if(!isReversal())
{ {
BigDecimal movementQty = sLine.getMovementQty(); oLine = new MOrderLine (getCtx(), sLine.getC_OrderLine_ID(), get_TrxName());
BigDecimal qtyOnLineMA = MInOutLineMA.getManualQty(sLine.getM_InOutLine_ID(), get_TrxName()); if (log.isLoggable(Level.FINE)) log.fine("OrderLine - Reserved=" + oLine.getQtyReserved()
+ ", Delivered=" + oLine.getQtyDelivered());
if ( (movementQty.signum() != 0 && qtyOnLineMA.signum() != 0 && movementQty.signum() != qtyOnLineMA.signum()) // must have same sign
|| (qtyOnLineMA.abs().compareTo(movementQty.abs())>0)) { // compare absolute values
// More then line qty on attribute tab for line 10
m_processMsg = "@Over_Qty_On_Attribute_Tab@ " + sLine.getLine();
return DOCSTATUS_Invalid;
}
checkMaterialPolicy(sLine,movementQty.subtract(qtyOnLineMA));
} }
log.fine("Material Transaction");
MTransaction mtrx = null;
// // Load RMA Line
BigDecimal overReceipt = BigDecimal.ZERO; MRMALine rmaLine = null;
if (!isReversal())
if (sLine.getM_RMALine_ID() != 0)
{
rmaLine = new MRMALine(getCtx(), sLine.getM_RMALine_ID(), get_TrxName());
}
if (log.isLoggable(Level.INFO)) log.info("Line=" + sLine.getLine() + " - Qty=" + sLine.getMovementQty());
// Stock Movement - Counterpart MOrder.reserveStock
if (product != null
&& product.isStocked() )
{ {
if (oLine != null) //Ignore the Material Policy when is Reverse Correction
if(!isReversal())
{ {
BigDecimal toDelivered = oLine.getQtyOrdered() BigDecimal movementQty = sLine.getMovementQty();
.subtract(oLine.getQtyDelivered()); BigDecimal qtyOnLineMA = MInOutLineMA.getManualQty(sLine.getM_InOutLine_ID(), get_TrxName());
if (toDelivered.signum() < 0) // IDEMPIERE-2889
toDelivered = Env.ZERO; if ( (movementQty.signum() != 0 && qtyOnLineMA.signum() != 0 && movementQty.signum() != qtyOnLineMA.signum()) // must have same sign
if (sLine.getMovementQty().compareTo(toDelivered) > 0) || (qtyOnLineMA.abs().compareTo(movementQty.abs())>0)) { // compare absolute values
overReceipt = sLine.getMovementQty().subtract( // More then line qty on attribute tab for line 10
toDelivered); m_processMsg = "@Over_Qty_On_Attribute_Tab@ " + sLine.getLine();
if (overReceipt.signum() != 0) return DOCSTATUS_Invalid;
}
checkMaterialPolicy(sLine,movementQty.subtract(qtyOnLineMA));
}
log.fine("Material Transaction");
MTransaction mtrx = null;
//
BigDecimal overReceipt = BigDecimal.ZERO;
if (!isReversal())
{
if (oLine != null)
{ {
sLine.setQtyOverReceipt(overReceipt); BigDecimal toDelivered = oLine.getQtyOrdered()
sLine.saveEx(); .subtract(oLine.getQtyDelivered());
if (toDelivered.signum() < 0) // IDEMPIERE-2889
toDelivered = Env.ZERO;
if (sLine.getMovementQty().compareTo(toDelivered) > 0)
overReceipt = sLine.getMovementQty().subtract(
toDelivered);
if (overReceipt.signum() != 0)
{
sLine.setQtyOverReceipt(overReceipt);
sLine.saveEx();
}
} }
} }
} else
else
{
overReceipt = sLine.getQtyOverReceipt();
}
BigDecimal orderedQtyToUpdate = sLine.getMovementQty().subtract(overReceipt);
//
if (sLine.getM_AttributeSetInstance_ID() == 0)
{
MInOutLineMA mas[] = MInOutLineMA.get(getCtx(),
sLine.getM_InOutLine_ID(), get_TrxName());
for (int j = 0; j < mas.length; j++)
{ {
MInOutLineMA ma = mas[j]; overReceipt = sLine.getQtyOverReceipt();
BigDecimal QtyMA = ma.getMovementQty(); }
if (MovementType.charAt(1) == '-') // C- Customer Shipment - V- Vendor Return BigDecimal orderedQtyToUpdate = sLine.getMovementQty().subtract(overReceipt);
QtyMA = QtyMA.negate(); //
if (sLine.getM_AttributeSetInstance_ID() == 0)
{
MInOutLineMA mas[] = MInOutLineMA.get(getCtx(),
sLine.getM_InOutLine_ID(), get_TrxName());
for (int j = 0; j < mas.length; j++)
{
MInOutLineMA ma = mas[j];
BigDecimal QtyMA = ma.getMovementQty();
if (MovementType.charAt(1) == '-') // C- Customer Shipment - V- Vendor Return
QtyMA = QtyMA.negate();
// Update Storage - see also VMatch.createMatchRecord // Update Storage - see also VMatch.createMatchRecord
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(),
sLine.getM_Locator_ID(),
sLine.getM_Product_ID(),
ma.getM_AttributeSetInstance_ID(),
QtyMA,ma.getDateMaterialPolicy(),
get_TrxName()))
{
String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot correct Inventory OnHand (MA) [" + product.getValue() + "] - " + lastError;
return DocAction.STATUS_Invalid;
}
// Create Transaction
mtrx = new MTransaction (getCtx(), sLine.getAD_Org_ID(),
MovementType, sLine.getM_Locator_ID(),
sLine.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(),
QtyMA, getMovementDate(), get_TrxName());
mtrx.setM_InOutLine_ID(sLine.getM_InOutLine_ID());
if (!mtrx.save())
{
m_processMsg = "Could not create Material Transaction (MA) [" + product.getValue() + "]";
return DocAction.STATUS_Invalid;
}
}
if (oLine!=null && mtrx!=null && oLine.getQtyOrdered().signum() > 0)
{
if (sLine.getC_OrderLine_ID() != 0)
{
if (!MStorageReservation.add(getCtx(), oLine.getM_Warehouse_ID(),
sLine.getM_Product_ID(),
oLine.getM_AttributeSetInstance_ID(),
orderedQtyToUpdate.negate(),
isSOTrx(),
get_TrxName()))
{
String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot correct Inventory " + (isSOTrx()? "Reserved" : "Ordered") + " (MA) - [" + product.getValue() + "] - " + lastError;
return DocAction.STATUS_Invalid;
}
}
}
}
// sLine.getM_AttributeSetInstance_ID() != 0
if (mtrx == null)
{
Timestamp dateMPolicy= null;
MStorageOnHand[] storages = MStorageOnHand.getWarehouse(getCtx(), 0,
sLine.getM_Product_ID(), sLine.getM_AttributeSetInstance_ID(), null,
MClient.MMPOLICY_FiFo.equals(product.getMMPolicy()), false,
sLine.getM_Locator_ID(), get_TrxName());
for (MStorageOnHand storage : storages) {
if (storage.getQtyOnHand().compareTo(sLine.getMovementQty()) >= 0) {
dateMPolicy = storage.getDateMaterialPolicy();
break;
}
}
if (dateMPolicy == null && storages.length > 0)
dateMPolicy = storages[0].getDateMaterialPolicy();
if(dateMPolicy==null)
dateMPolicy = getMovementDate();
// Fallback: Update Storage - see also VMatch.createMatchRecord
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(), if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(),
sLine.getM_Locator_ID(), sLine.getM_Locator_ID(),
sLine.getM_Product_ID(), sLine.getM_Product_ID(),
ma.getM_AttributeSetInstance_ID(), sLine.getM_AttributeSetInstance_ID(),
QtyMA,ma.getDateMaterialPolicy(), Qty,dateMPolicy,get_TrxName()))
get_TrxName()))
{ {
String lastError = CLogger.retrieveErrorString(""); String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot correct Inventory OnHand (MA) [" + product.getValue() + "] - " + lastError; m_processMsg = "Cannot correct Inventory OnHand [" + product.getValue() + "] - " + lastError;
return DocAction.STATUS_Invalid; return DocAction.STATUS_Invalid;
} }
if (oLine!=null && oLine.getQtyOrdered().signum() > 0)
// Create Transaction
mtrx = new MTransaction (getCtx(), sLine.getAD_Org_ID(),
MovementType, sLine.getM_Locator_ID(),
sLine.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(),
QtyMA, getMovementDate(), get_TrxName());
mtrx.setM_InOutLine_ID(sLine.getM_InOutLine_ID());
if (!mtrx.save())
{
m_processMsg = "Could not create Material Transaction (MA) [" + product.getValue() + "]";
return DocAction.STATUS_Invalid;
}
}
if (oLine!=null && mtrx!=null && oLine.getQtyOrdered().signum() > 0)
{
if (sLine.getC_OrderLine_ID() != 0)
{ {
if (!MStorageReservation.add(getCtx(), oLine.getM_Warehouse_ID(), if (!MStorageReservation.add(getCtx(), oLine.getM_Warehouse_ID(),
sLine.getM_Product_ID(), sLine.getM_Product_ID(),
oLine.getM_AttributeSetInstance_ID(), oLine.getM_AttributeSetInstance_ID(),
orderedQtyToUpdate.negate(), orderedQtyToUpdate.negate(), isSOTrx(), get_TrxName()))
isSOTrx(),
get_TrxName()))
{ {
String lastError = CLogger.retrieveErrorString(""); m_processMsg = "Cannot correct Inventory Reserved " + (isSOTrx()? "Reserved [" :"Ordered [") + product.getValue() + "]";
m_processMsg = "Cannot correct Inventory " + (isSOTrx()? "Reserved" : "Ordered") + " (MA) - [" + product.getValue() + "] - " + lastError;
return DocAction.STATUS_Invalid; return DocAction.STATUS_Invalid;
} }
} }
}
} // FallBack: Create Transaction
// sLine.getM_AttributeSetInstance_ID() != 0 mtrx = new MTransaction (getCtx(), sLine.getAD_Org_ID(),
if (mtrx == null) MovementType, sLine.getM_Locator_ID(),
{ sLine.getM_Product_ID(), sLine.getM_AttributeSetInstance_ID(),
Timestamp dateMPolicy= null; Qty, getMovementDate(), get_TrxName());
MStorageOnHand[] storages = MStorageOnHand.getWarehouse(getCtx(), 0, mtrx.setM_InOutLine_ID(sLine.getM_InOutLine_ID());
sLine.getM_Product_ID(), sLine.getM_AttributeSetInstance_ID(), null, if (!mtrx.save())
MClient.MMPOLICY_FiFo.equals(product.getMMPolicy()), false,
sLine.getM_Locator_ID(), get_TrxName());
for (MStorageOnHand storage : storages) {
if (storage.getQtyOnHand().compareTo(sLine.getMovementQty()) >= 0) {
dateMPolicy = storage.getDateMaterialPolicy();
break;
}
}
if (dateMPolicy == null && storages.length > 0)
dateMPolicy = storages[0].getDateMaterialPolicy();
if(dateMPolicy==null)
dateMPolicy = getMovementDate();
// Fallback: Update Storage - see also VMatch.createMatchRecord
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(),
sLine.getM_Locator_ID(),
sLine.getM_Product_ID(),
sLine.getM_AttributeSetInstance_ID(),
Qty,dateMPolicy,get_TrxName()))
{
String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot correct Inventory OnHand [" + product.getValue() + "] - " + lastError;
return DocAction.STATUS_Invalid;
}
if (oLine!=null && oLine.getQtyOrdered().signum() > 0)
{
if (!MStorageReservation.add(getCtx(), oLine.getM_Warehouse_ID(),
sLine.getM_Product_ID(),
oLine.getM_AttributeSetInstance_ID(),
orderedQtyToUpdate.negate(), isSOTrx(), get_TrxName()))
{ {
m_processMsg = "Cannot correct Inventory Reserved " + (isSOTrx()? "Reserved [" :"Ordered [") + product.getValue() + "]"; m_processMsg = CLogger.retrieveErrorString("Could not create Material Transaction [" + product.getValue() + "]");
return DocAction.STATUS_Invalid; return DocAction.STATUS_Invalid;
} }
} }
} // stock movement
// FallBack: Create Transaction // Correct Order Line
mtrx = new MTransaction (getCtx(), sLine.getAD_Org_ID(), if (product != null && oLine != null) // other in VMatch.createMatchRecord
MovementType, sLine.getM_Locator_ID(), {
sLine.getM_Product_ID(), sLine.getM_AttributeSetInstance_ID(), oLine.setQtyReserved(oLine.getQtyReserved().subtract(sLine.getMovementQty().subtract(sLine.getQtyOverReceipt())));
Qty, getMovementDate(), get_TrxName()); }
mtrx.setM_InOutLine_ID(sLine.getM_InOutLine_ID());
if (!mtrx.save()) // Update Sales Order Line
if (oLine != null)
{
if (isSOTrx() // PO is done by Matching
|| sLine.getM_Product_ID() == 0) // PO Charges, empty lines
{ {
m_processMsg = CLogger.retrieveErrorString("Could not create Material Transaction [" + product.getValue() + "]"); if (isSOTrx())
oLine.setQtyDelivered(oLine.getQtyDelivered().subtract(Qty));
else
oLine.setQtyDelivered(oLine.getQtyDelivered().add(Qty));
oLine.setDateDelivered(getMovementDate()); // overwrite=last
}
if (!oLine.save())
{
m_processMsg = "Could not update Order Line";
return DocAction.STATUS_Invalid; return DocAction.STATUS_Invalid;
} }
}
} // stock movement
// Correct Order Line
if (product != null && oLine != null) // other in VMatch.createMatchRecord
{
oLine.setQtyReserved(oLine.getQtyReserved().subtract(sLine.getMovementQty().subtract(sLine.getQtyOverReceipt())));
}
// Update Sales Order Line
if (oLine != null)
{
if (isSOTrx() // PO is done by Matching
|| sLine.getM_Product_ID() == 0) // PO Charges, empty lines
{
if (isSOTrx())
oLine.setQtyDelivered(oLine.getQtyDelivered().subtract(Qty));
else else
oLine.setQtyDelivered(oLine.getQtyDelivered().add(Qty)); if (log.isLoggable(Level.FINE)) log.fine("OrderLine -> Reserved=" + oLine.getQtyReserved()
oLine.setDateDelivered(getMovementDate()); // overwrite=last + ", Delivered=" + oLine.getQtyReserved());
} }
if (!oLine.save()) // Update RMA Line Qty Delivered
{ else if (rmaLine != null)
m_processMsg = "Could not update Order Line"; {
return DocAction.STATUS_Invalid; if (isSOTrx())
} {
else rmaLine.setQtyDelivered(rmaLine.getQtyDelivered().add(Qty));
if (log.isLoggable(Level.FINE)) log.fine("OrderLine -> Reserved=" + oLine.getQtyReserved() }
+ ", Delivered=" + oLine.getQtyReserved()); else
} {
// Update RMA Line Qty Delivered rmaLine.setQtyDelivered(rmaLine.getQtyDelivered().subtract(Qty));
else if (rmaLine != null) }
{ if (!rmaLine.save())
if (isSOTrx()) {
{ m_processMsg = "Could not update RMA Line";
rmaLine.setQtyDelivered(rmaLine.getQtyDelivered().add(Qty)); return DocAction.STATUS_Invalid;
} }
else }
{
rmaLine.setQtyDelivered(rmaLine.getQtyDelivered().subtract(Qty));
}
if (!rmaLine.save())
{
m_processMsg = "Could not update RMA Line";
return DocAction.STATUS_Invalid;
}
}
// Create Asset for SO // Create Asset for SO
if (product != null if (product != null
&& isSOTrx() && isSOTrx()
&& product.isCreateAsset() && product.isCreateAsset()
&& !product.getM_Product_Category().getA_Asset_Group().isFixedAsset() && !product.getM_Product_Category().getA_Asset_Group().isFixedAsset()
&& sLine.getMovementQty().signum() > 0 && sLine.getMovementQty().signum() > 0
&& !isReversal()) && !isReversal())
{
log.fine("Asset");
info.append("@A_Asset_ID@: ");
int noAssets = sLine.getMovementQty().intValue();
if (!product.isOneAssetPerUOM())
noAssets = 1;
for (int i = 0; i < noAssets; i++)
{ {
if (i > 0) log.fine("Asset");
info.append(" - "); info.append("@A_Asset_ID@: ");
int deliveryCount = i+1; int noAssets = sLine.getMovementQty().intValue();
if (!product.isOneAssetPerUOM()) if (!product.isOneAssetPerUOM())
deliveryCount = 0; noAssets = 1;
MAsset asset = new MAsset (this, sLine, deliveryCount); for (int i = 0; i < noAssets; i++)
if (!asset.save(get_TrxName()))
{ {
m_processMsg = "Could not create Asset"; if (i > 0)
return DocAction.STATUS_Invalid; info.append(" - ");
} int deliveryCount = i+1;
info.append(asset.getValue()); if (!product.isOneAssetPerUOM())
} deliveryCount = 0;
} // Asset MAsset asset = new MAsset (this, sLine, deliveryCount);
if (!asset.save(get_TrxName()))
// Matching
if (!isSOTrx()
&& sLine.getM_Product_ID() != 0
&& !isReversal())
{
BigDecimal matchQty = sLine.getMovementQty();
// Invoice - Receipt Match (requires Product)
MInvoiceLine iLine = MInvoiceLine.getOfInOutLine (sLine);
if (iLine != null && iLine.getM_Product_ID() != 0)
{
if (matchQty.compareTo(iLine.getQtyInvoiced())>0)
matchQty = iLine.getQtyInvoiced();
MMatchInv[] matches = MMatchInv.get(getCtx(),
sLine.getM_InOutLine_ID(), iLine.getC_InvoiceLine_ID(), get_TrxName());
if (matches == null || matches.length == 0)
{
MMatchInv inv = new MMatchInv (iLine, getMovementDate(), matchQty);
if (sLine.getM_AttributeSetInstance_ID() != iLine.getM_AttributeSetInstance_ID())
{ {
iLine.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID()); m_processMsg = "Could not create Asset";
iLine.saveEx(); // update matched invoice with ASI
inv.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID());
}
if (!inv.save(get_TrxName()))
{
m_processMsg = CLogger.retrieveErrorString("Could not create Inv Matching");
return DocAction.STATUS_Invalid; return DocAction.STATUS_Invalid;
} }
addDocsPostProcess(inv); info.append(asset.getValue());
} }
} } // Asset
// Link to Order
if (sLine.getC_OrderLine_ID() != 0) // Matching
if (!isSOTrx()
&& sLine.getM_Product_ID() != 0
&& !isReversal())
{ {
log.fine("PO Matching"); BigDecimal matchQty = sLine.getMovementQty();
// Ship - PO // Invoice - Receipt Match (requires Product)
MMatchPO po = MMatchPO.create (null, sLine, getMovementDate(), matchQty); MInvoiceLine iLine = MInvoiceLine.getOfInOutLine (sLine);
if (po != null) { if (iLine != null && iLine.getM_Product_ID() != 0)
if (!po.save(get_TrxName())) {
if (matchQty.compareTo(iLine.getQtyInvoiced())>0)
matchQty = iLine.getQtyInvoiced();
MMatchInv[] matches = MMatchInv.get(getCtx(),
sLine.getM_InOutLine_ID(), iLine.getC_InvoiceLine_ID(), get_TrxName());
if (matches == null || matches.length == 0)
{ {
m_processMsg = "Could not create PO Matching"; MMatchInv inv = new MMatchInv (iLine, getMovementDate(), matchQty);
return DocAction.STATUS_Invalid; if (sLine.getM_AttributeSetInstance_ID() != iLine.getM_AttributeSetInstance_ID())
} {
if (!po.isPosted()) iLine.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID());
addDocsPostProcess(po); iLine.saveEx(); // update matched invoice with ASI
MMatchInv matchInvCreated = po.getMatchInvCreated(); inv.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID());
if (matchInvCreated != null) { }
addDocsPostProcess(matchInvCreated); if (!inv.save(get_TrxName()))
{
m_processMsg = CLogger.retrieveErrorString("Could not create Inv Matching");
return DocAction.STATUS_Invalid;
}
addDocsPostProcess(inv);
} }
} }
// Update PO with ASI
if ( oLine != null && oLine.getM_AttributeSetInstance_ID() == 0 // Link to Order
&& sLine.getMovementQty().compareTo(oLine.getQtyOrdered()) == 0) // just if full match [ 1876965 ] if (sLine.getC_OrderLine_ID() != 0)
{ {
oLine.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID()); log.fine("PO Matching");
oLine.saveEx(get_TrxName()); // Ship - PO
} MMatchPO po = MMatchPO.create (null, sLine, getMovementDate(), matchQty);
}
else // No Order - Try finding links via Invoice
{
// Invoice has an Order Link
if (iLine != null && iLine.getC_OrderLine_ID() != 0)
{
// Invoice is created before Shipment
log.fine("PO(Inv) Matching");
// Ship - Invoice
MMatchPO po = MMatchPO.create (iLine, sLine,
getMovementDate(), matchQty);
if (po != null) { if (po != null) {
if (!po.save(get_TrxName())) if (!po.save(get_TrxName()))
{ {
m_processMsg = "Could not create PO(Inv) Matching"; m_processMsg = "Could not create PO Matching";
return DocAction.STATUS_Invalid; return DocAction.STATUS_Invalid;
} }
if (!po.isPosted()) if (!po.isPosted())
addDocsPostProcess(po); addDocsPostProcess(po);
MMatchInv matchInvCreated = po.getMatchInvCreated();
if (matchInvCreated != null) {
addDocsPostProcess(matchInvCreated);
}
} }
// Update PO with ASI // Update PO with ASI
oLine = new MOrderLine (getCtx(), iLine.getC_OrderLine_ID(), get_TrxName());
if ( oLine != null && oLine.getM_AttributeSetInstance_ID() == 0 if ( oLine != null && oLine.getM_AttributeSetInstance_ID() == 0
&& sLine.getMovementQty().compareTo(oLine.getQtyOrdered()) == 0) // just if full match [ 1876965 ] && sLine.getMovementQty().compareTo(oLine.getQtyOrdered()) == 0) // just if full match [ 1876965 ]
{ {
@ -1647,11 +1622,52 @@ public class MInOut extends X_M_InOut implements DocAction
oLine.saveEx(get_TrxName()); oLine.saveEx(get_TrxName());
} }
} }
} // No Order else // No Order - Try finding links via Invoice
} // PO Matching {
// Invoice has an Order Link
if (iLine != null && iLine.getC_OrderLine_ID() != 0)
{
// Invoice is created before Shipment
log.fine("PO(Inv) Matching");
// Ship - Invoice
MMatchPO po = MMatchPO.create (iLine, sLine,
getMovementDate(), matchQty);
if (po != null) {
if (!po.save(get_TrxName()))
{
m_processMsg = "Could not create PO(Inv) Matching";
return DocAction.STATUS_Invalid;
}
if (!po.isPosted())
addDocsPostProcess(po);
}
// Update PO with ASI
oLine = new MOrderLine (getCtx(), iLine.getC_OrderLine_ID(), get_TrxName());
if ( oLine != null && oLine.getM_AttributeSetInstance_ID() == 0
&& sLine.getMovementQty().compareTo(oLine.getQtyOrdered()) == 0) // just if full match [ 1876965 ]
{
oLine.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID());
oLine.saveEx(get_TrxName());
}
}
} // No Order
} // PO Matching
}
catch (NegativeInventoryDisallowedException e)
{
log.severe(e.getMessage());
errors.append(Msg.getElement(getCtx(), "Line")).append(" ").append(sLine.getLine()).append(": ");
errors.append(e.getMessage()).append("\n");
}
} // for all lines } // for all lines
if (errors.toString().length() > 0)
{
m_processMsg = errors.toString();
return DocAction.STATUS_Invalid;
}
// Counter Documents // Counter Documents
MInOut counter = createCounterDoc(); MInOut counter = createCounterDoc();
if (counter != null) if (counter != null)

View File

@ -24,6 +24,7 @@ import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.logging.Level; import java.util.logging.Level;
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
import org.adempiere.exceptions.PeriodClosedException; import org.adempiere.exceptions.PeriodClosedException;
import org.compiere.process.DocAction; import org.compiere.process.DocAction;
import org.compiere.process.DocumentEngine; import org.compiere.process.DocumentEngine;
@ -435,6 +436,7 @@ public class MInventory extends X_M_Inventory implements DocAction
approveIt(); approveIt();
if (log.isLoggable(Level.INFO)) log.info(toString()); if (log.isLoggable(Level.INFO)) log.info(toString());
StringBuilder errors = new StringBuilder();
MInventoryLine[] lines = getLines(false); MInventoryLine[] lines = getLines(false);
for (MInventoryLine line : lines) for (MInventoryLine line : lines)
{ {
@ -442,90 +444,150 @@ public class MInventory extends X_M_Inventory implements DocAction
continue; continue;
MProduct product = line.getProduct(); MProduct product = line.getProduct();
try
BigDecimal qtyDiff = Env.ZERO;
if (MDocType.DOCSUBTYPEINV_InternalUseInventory.equals(docSubTypeInv))
qtyDiff = line.getQtyInternalUse().negate();
else if (MDocType.DOCSUBTYPEINV_PhysicalInventory.equals(docSubTypeInv))
qtyDiff = line.getQtyCount().subtract(line.getQtyBook());
else if (MDocType.DOCSUBTYPEINV_CostAdjustment.equals(docSubTypeInv))
{ {
if (!isReversal()) BigDecimal qtyDiff = Env.ZERO;
if (MDocType.DOCSUBTYPEINV_InternalUseInventory.equals(docSubTypeInv))
qtyDiff = line.getQtyInternalUse().negate();
else if (MDocType.DOCSUBTYPEINV_PhysicalInventory.equals(docSubTypeInv))
qtyDiff = line.getQtyCount().subtract(line.getQtyBook());
else if (MDocType.DOCSUBTYPEINV_CostAdjustment.equals(docSubTypeInv))
{ {
BigDecimal currentCost = line.getCurrentCostPrice(); if (!isReversal())
MClient client = MClient.get(getCtx(), getAD_Client_ID());
MAcctSchema as = client.getAcctSchema();
MAcctSchema[] ass = MAcctSchema.getClientAcctSchema(getCtx(), client.get_ID());
if (as.getC_Currency_ID() != getC_Currency_ID())
{ {
for (int i = 0; i < ass.length ; i ++) BigDecimal currentCost = line.getCurrentCostPrice();
MClient client = MClient.get(getCtx(), getAD_Client_ID());
MAcctSchema as = client.getAcctSchema();
MAcctSchema[] ass = MAcctSchema.getClientAcctSchema(getCtx(), client.get_ID());
if (as.getC_Currency_ID() != getC_Currency_ID())
{ {
MAcctSchema a = ass[i]; for (int i = 0; i < ass.length ; i ++)
if (a.getC_Currency_ID() == getC_Currency_ID()) {
as = a ; MAcctSchema a = ass[i];
if (a.getC_Currency_ID() == getC_Currency_ID())
as = a ;
}
}
MCost cost = product.getCostingRecord(as, getAD_Org_ID(), line.getM_AttributeSetInstance_ID(), getCostingMethod());
if (cost != null && cost.getCurrentCostPrice().compareTo(currentCost) != 0)
{
m_processMsg = "Current Cost for Line " + line.getLine() + " have changed.";
return DocAction.STATUS_Invalid;
}
}
}
//If Quantity Count minus Quantity Book = Zero, then no change in Inventory
if (qtyDiff.signum() == 0)
continue;
//Ignore the Material Policy when is Reverse Correction
if(!isReversal()){
BigDecimal qtyOnLineMA = MInventoryLineMA.getManualQty(line.getM_InventoryLine_ID(), get_TrxName());
if(qtyDiff.signum()<0){
if(qtyOnLineMA.compareTo(qtyDiff)<0){
m_processMsg = "@Over_Qty_On_Attribute_Tab@ " + line.getLine();
return DOCSTATUS_Invalid;
}
}else{
if(qtyOnLineMA.compareTo(qtyDiff)>0){
m_processMsg = "@Over_Qty_On_Attribute_Tab@ " + line.getLine();
return DOCSTATUS_Invalid;
}
}
checkMaterialPolicy(line, qtyDiff.subtract(qtyOnLineMA));
}
// Stock Movement - Counterpart MOrder.reserveStock
if (product != null
&& product.isStocked() )
{
log.fine("Material Transaction");
MTransaction mtrx = null;
//If AttributeSetInstance = Zero then create new AttributeSetInstance use Inventory Line MA else use current AttributeSetInstance
if (line.getM_AttributeSetInstance_ID() == 0 || qtyDiff.compareTo(Env.ZERO) == 0)
{
MInventoryLineMA mas[] = MInventoryLineMA.get(getCtx(),
line.getM_InventoryLine_ID(), get_TrxName());
for (int j = 0; j < mas.length; j++)
{
MInventoryLineMA ma = mas[j];
BigDecimal QtyMA = ma.getMovementQty();
BigDecimal QtyNew = QtyMA.add(qtyDiff);
if (log.isLoggable(Level.FINE)) log.fine("Diff=" + qtyDiff
+ " - Instance OnHand=" + QtyMA + "->" + QtyNew);
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(),
line.getM_Locator_ID(),
line.getM_Product_ID(),
ma.getM_AttributeSetInstance_ID(),
QtyMA.negate(),ma.getDateMaterialPolicy(), get_TrxName()))
{
String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot correct Inventory (MA) - " + lastError;
return DocAction.STATUS_Invalid;
}
// Only Update Date Last Inventory if is a Physical Inventory
if (MDocType.DOCSUBTYPEINV_PhysicalInventory.equals(docSubTypeInv))
{
MStorageOnHand storage = MStorageOnHand.get(getCtx(), line.getM_Locator_ID(),
line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(),ma.getDateMaterialPolicy(),get_TrxName());
storage.setDateLastInventory(getMovementDate());
if (!storage.save(get_TrxName()))
{
m_processMsg = "Storage not updated(2)";
return DocAction.STATUS_Invalid;
}
}
String m_MovementType =null;
if(QtyMA.negate().compareTo(Env.ZERO) > 0 )
m_MovementType = MTransaction.MOVEMENTTYPE_InventoryIn;
else
m_MovementType = MTransaction.MOVEMENTTYPE_InventoryOut;
// Transaction
mtrx = new MTransaction (getCtx(), line.getAD_Org_ID(), m_MovementType,
line.getM_Locator_ID(), line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(),
QtyMA.negate(), getMovementDate(), get_TrxName());
mtrx.setM_InventoryLine_ID(line.getM_InventoryLine_ID());
if (!mtrx.save())
{
m_processMsg = "Transaction not inserted(2)";
return DocAction.STATUS_Invalid;
}
qtyDiff = QtyNew;
} }
} }
MCost cost = product.getCostingRecord(as, getAD_Org_ID(), line.getM_AttributeSetInstance_ID(), getCostingMethod()); //sLine.getM_AttributeSetInstance_ID() != 0
if (cost != null && cost.getCurrentCostPrice().compareTo(currentCost) != 0) // Fallback
if (mtrx == null)
{ {
m_processMsg = "Current Cost for Line " + line.getLine() + " have changed."; Timestamp dateMPolicy= qtyDiff.signum() > 0 ? getMovementDate() : null;
return DocAction.STATUS_Invalid; if (line.getM_AttributeSetInstance_ID() > 0)
} {
} Timestamp t = MStorageOnHand.getDateMaterialPolicy(line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), line.get_TrxName());
} if (t != null)
dateMPolicy = t;
//If Quantity Count minus Quantity Book = Zero, then no change in Inventory }
if (qtyDiff.signum() == 0)
continue;
//Ignore the Material Policy when is Reverse Correction
if(!isReversal()){
BigDecimal qtyOnLineMA = MInventoryLineMA.getManualQty(line.getM_InventoryLine_ID(), get_TrxName());
if(qtyDiff.signum()<0){
if(qtyOnLineMA.compareTo(qtyDiff)<0){
m_processMsg = "@Over_Qty_On_Attribute_Tab@ " + line.getLine();
return DOCSTATUS_Invalid;
}
}else{
if(qtyOnLineMA.compareTo(qtyDiff)>0){
m_processMsg = "@Over_Qty_On_Attribute_Tab@ " + line.getLine();
return DOCSTATUS_Invalid;
}
}
checkMaterialPolicy(line, qtyDiff.subtract(qtyOnLineMA));
}
// Stock Movement - Counterpart MOrder.reserveStock
if (product != null
&& product.isStocked() )
{
log.fine("Material Transaction");
MTransaction mtrx = null;
//If AttributeSetInstance = Zero then create new AttributeSetInstance use Inventory Line MA else use current AttributeSetInstance
if (line.getM_AttributeSetInstance_ID() == 0 || qtyDiff.compareTo(Env.ZERO) == 0)
{
MInventoryLineMA mas[] = MInventoryLineMA.get(getCtx(),
line.getM_InventoryLine_ID(), get_TrxName());
for (int j = 0; j < mas.length; j++)
{
MInventoryLineMA ma = mas[j];
BigDecimal QtyMA = ma.getMovementQty();
BigDecimal QtyNew = QtyMA.add(qtyDiff);
if (log.isLoggable(Level.FINE)) log.fine("Diff=" + qtyDiff
+ " - Instance OnHand=" + QtyMA + "->" + QtyNew);
//Fallback: Update Storage - see also VMatch.createMatchRecord
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(), if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(),
line.getM_Locator_ID(), line.getM_Locator_ID(),
line.getM_Product_ID(), line.getM_Product_ID(),
ma.getM_AttributeSetInstance_ID(), line.getM_AttributeSetInstance_ID(),
QtyMA.negate(),ma.getDateMaterialPolicy(), get_TrxName())) qtyDiff,dateMPolicy,get_TrxName()))
{ {
String lastError = CLogger.retrieveErrorString(""); String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot correct Inventory (MA) - " + lastError; m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError;
return DocAction.STATUS_Invalid; return DocAction.STATUS_Invalid;
} }
@ -533,7 +595,8 @@ public class MInventory extends X_M_Inventory implements DocAction
if (MDocType.DOCSUBTYPEINV_PhysicalInventory.equals(docSubTypeInv)) if (MDocType.DOCSUBTYPEINV_PhysicalInventory.equals(docSubTypeInv))
{ {
MStorageOnHand storage = MStorageOnHand.get(getCtx(), line.getM_Locator_ID(), MStorageOnHand storage = MStorageOnHand.get(getCtx(), line.getM_Locator_ID(),
line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(),ma.getDateMaterialPolicy(),get_TrxName()); line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),dateMPolicy, get_TrxName());
storage.setDateLastInventory(getMovementDate()); storage.setDateLastInventory(getMovementDate());
if (!storage.save(get_TrxName())) if (!storage.save(get_TrxName()))
{ {
@ -542,86 +605,39 @@ public class MInventory extends X_M_Inventory implements DocAction
} }
} }
String m_MovementType =null; String m_MovementType = null;
if(QtyMA.negate().compareTo(Env.ZERO) > 0 ) if(qtyDiff.compareTo(Env.ZERO) > 0 )
m_MovementType = MTransaction.MOVEMENTTYPE_InventoryIn; m_MovementType = MTransaction.MOVEMENTTYPE_InventoryIn;
else else
m_MovementType = MTransaction.MOVEMENTTYPE_InventoryOut; m_MovementType = MTransaction.MOVEMENTTYPE_InventoryOut;
// Transaction // Transaction
mtrx = new MTransaction (getCtx(), line.getAD_Org_ID(), m_MovementType, mtrx = new MTransaction (getCtx(), line.getAD_Org_ID(), m_MovementType,
line.getM_Locator_ID(), line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), line.getM_Locator_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
QtyMA.negate(), getMovementDate(), get_TrxName()); qtyDiff, getMovementDate(), get_TrxName());
mtrx.setM_InventoryLine_ID(line.getM_InventoryLine_ID());
mtrx.setM_InventoryLine_ID(line.getM_InventoryLine_ID()); if (!mtrx.save())
if (!mtrx.save())
{
m_processMsg = "Transaction not inserted(2)";
return DocAction.STATUS_Invalid;
}
qtyDiff = QtyNew;
}
}
//sLine.getM_AttributeSetInstance_ID() != 0
// Fallback
if (mtrx == null)
{
Timestamp dateMPolicy= qtyDiff.signum() > 0 ? getMovementDate() : null;
if (line.getM_AttributeSetInstance_ID() > 0)
{
Timestamp t = MStorageOnHand.getDateMaterialPolicy(line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), line.get_TrxName());
if (t != null)
dateMPolicy = t;
}
//Fallback: Update Storage - see also VMatch.createMatchRecord
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(),
line.getM_Locator_ID(),
line.getM_Product_ID(),
line.getM_AttributeSetInstance_ID(),
qtyDiff,dateMPolicy,get_TrxName()))
{
String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError;
return DocAction.STATUS_Invalid;
}
// Only Update Date Last Inventory if is a Physical Inventory
if (MDocType.DOCSUBTYPEINV_PhysicalInventory.equals(docSubTypeInv))
{
MStorageOnHand storage = MStorageOnHand.get(getCtx(), line.getM_Locator_ID(),
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),dateMPolicy, get_TrxName());
storage.setDateLastInventory(getMovementDate());
if (!storage.save(get_TrxName()))
{ {
m_processMsg = "Storage not updated(2)"; m_processMsg = "Transaction not inserted(2)";
return DocAction.STATUS_Invalid; return DocAction.STATUS_Invalid;
} }
} } // Fallback
} // stock movement
String m_MovementType = null; }
if(qtyDiff.compareTo(Env.ZERO) > 0 ) catch (NegativeInventoryDisallowedException e)
m_MovementType = MTransaction.MOVEMENTTYPE_InventoryIn; {
else log.severe(e.getMessage());
m_MovementType = MTransaction.MOVEMENTTYPE_InventoryOut; errors.append(Msg.getElement(getCtx(), "Line")).append(" ").append(line.getLine()).append(": ");
// Transaction errors.append(e.getMessage()).append("\n");
mtrx = new MTransaction (getCtx(), line.getAD_Org_ID(), m_MovementType, }
line.getM_Locator_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
qtyDiff, getMovementDate(), get_TrxName());
mtrx.setM_InventoryLine_ID(line.getM_InventoryLine_ID());
if (!mtrx.save())
{
m_processMsg = "Transaction not inserted(2)";
return DocAction.STATUS_Invalid;
}
} // Fallback
} // stock movement
} // for all lines } // for all lines
if (errors.toString().length() > 0)
{
m_processMsg = errors.toString();
return DocAction.STATUS_Invalid;
}
// User Validation // User Validation
String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE); String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE);
if (valid != null) if (valid != null)

View File

@ -24,6 +24,7 @@ import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.logging.Level; import java.util.logging.Level;
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
import org.adempiere.exceptions.PeriodClosedException; import org.adempiere.exceptions.PeriodClosedException;
import org.compiere.process.DocAction; import org.compiere.process.DocAction;
import org.compiere.process.DocumentEngine; import org.compiere.process.DocumentEngine;
@ -416,6 +417,7 @@ public class MMovement extends X_M_Movement implements DocAction
approveIt(); approveIt();
if (log.isLoggable(Level.INFO)) log.info(toString()); if (log.isLoggable(Level.INFO)) log.info(toString());
StringBuilder errors = new StringBuilder();
// //
MMovementLine[] lines = getLines(false); MMovementLine[] lines = getLines(false);
for (int i = 0; i < lines.length; i++) for (int i = 0; i < lines.length; i++)
@ -425,59 +427,145 @@ public class MMovement extends X_M_Movement implements DocAction
//Stock Movement - Counterpart MOrder.reserveStock //Stock Movement - Counterpart MOrder.reserveStock
MProduct product = line.getProduct(); MProduct product = line.getProduct();
if (product != null try
&& product.isStocked() )
{ {
//Ignore the Material Policy when is Reverse Correction if (product != null
if(!isReversal()){ && product.isStocked() )
BigDecimal qtyOnLineMA = MMovementLineMA.getManualQty(line.getM_MovementLine_ID(), get_TrxName()); {
BigDecimal movementQty = line.getMovementQty(); //Ignore the Material Policy when is Reverse Correction
if(!isReversal()){
BigDecimal qtyOnLineMA = MMovementLineMA.getManualQty(line.getM_MovementLine_ID(), get_TrxName());
BigDecimal movementQty = line.getMovementQty();
if(qtyOnLineMA.compareTo(movementQty)>0) if(qtyOnLineMA.compareTo(movementQty)>0)
{ {
// More then line qty on attribute tab for line 10 // More then line qty on attribute tab for line 10
m_processMsg = "@Over_Qty_On_Attribute_Tab@ " + line.getLine(); m_processMsg = "@Over_Qty_On_Attribute_Tab@ " + line.getLine();
return DOCSTATUS_Invalid; return DOCSTATUS_Invalid;
}
checkMaterialPolicy(line,movementQty.subtract(qtyOnLineMA));
} }
checkMaterialPolicy(line,movementQty.subtract(qtyOnLineMA));
}
if (line.getM_AttributeSetInstance_ID() == 0)
if (line.getM_AttributeSetInstance_ID() == 0)
{
MMovementLineMA mas[] = MMovementLineMA.get(getCtx(),
line.getM_MovementLine_ID(), get_TrxName());
for (int j = 0; j < mas.length; j++)
{ {
MMovementLineMA ma = mas[j]; MMovementLineMA mas[] = MMovementLineMA.get(getCtx(),
// line.getM_MovementLine_ID(), get_TrxName());
for (int j = 0; j < mas.length; j++)
{
MMovementLineMA ma = mas[j];
//
MLocator locator = new MLocator (getCtx(), line.getM_Locator_ID(), get_TrxName());
//Update Storage
if (!MStorageOnHand.add(getCtx(),locator.getM_Warehouse_ID(),
line.getM_Locator_ID(),
line.getM_Product_ID(),
ma.getM_AttributeSetInstance_ID(),
ma.getMovementQty().negate(),ma.getDateMaterialPolicy(), get_TrxName()))
{
String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError;
return DocAction.STATUS_Invalid;
}
int M_AttributeSetInstanceTo_ID = line.getM_AttributeSetInstanceTo_ID();
//only can be same asi if locator is different
if (M_AttributeSetInstanceTo_ID == 0 && line.getM_Locator_ID() != line.getM_LocatorTo_ID())
{
M_AttributeSetInstanceTo_ID = ma.getM_AttributeSetInstance_ID();
}
//Update Storage
MLocator locatorTo = new MLocator (getCtx(), line.getM_LocatorTo_ID(), get_TrxName());
if (!MStorageOnHand.add(getCtx(),locatorTo.getM_Warehouse_ID(),
line.getM_LocatorTo_ID(),
line.getM_Product_ID(),
M_AttributeSetInstanceTo_ID,
ma.getMovementQty(),ma.getDateMaterialPolicy(), get_TrxName()))
{
String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError;
return DocAction.STATUS_Invalid;
}
//
trxFrom = new MTransaction (getCtx(), line.getAD_Org_ID(),
MTransaction.MOVEMENTTYPE_MovementFrom,
line.getM_Locator_ID(), line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(),
ma.getMovementQty().negate(), getMovementDate(), get_TrxName());
trxFrom.setM_MovementLine_ID(line.getM_MovementLine_ID());
if (!trxFrom.save())
{
m_processMsg = "Transaction From not inserted (MA)";
return DocAction.STATUS_Invalid;
}
//
MTransaction trxTo = new MTransaction (getCtx(), line.getAD_Org_ID(),
MTransaction.MOVEMENTTYPE_MovementTo,
line.getM_LocatorTo_ID(), line.getM_Product_ID(), M_AttributeSetInstanceTo_ID,
ma.getMovementQty(), getMovementDate(), get_TrxName());
trxTo.setM_MovementLine_ID(line.getM_MovementLine_ID());
if (!trxTo.save())
{
m_processMsg = "Transaction To not inserted (MA)";
return DocAction.STATUS_Invalid;
}
}
}
// Fallback - We have ASI
if (trxFrom == null)
{
Timestamp dateMPolicy= null;
MStorageOnHand[] storages = null;
if (line.getMovementQty().compareTo(Env.ZERO) > 0) {
// Find Date Material Policy bases on ASI
storages = MStorageOnHand.getWarehouse(getCtx(), 0,
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), null,
MClient.MMPOLICY_FiFo.equals(product.getMMPolicy()), false,
line.getM_Locator_ID(), get_TrxName());
} else {
//Case of reversal
storages = MStorageOnHand.getWarehouse(getCtx(), 0,
line.getM_Product_ID(), line.getM_AttributeSetInstanceTo_ID(), null,
MClient.MMPOLICY_FiFo.equals(product.getMMPolicy()), false,
line.getM_LocatorTo_ID(), get_TrxName());
}
for (MStorageOnHand storage : storages) {
if (storage.getQtyOnHand().compareTo(line.getMovementQty()) >= 0) {
dateMPolicy = storage.getDateMaterialPolicy();
break;
}
}
if (dateMPolicy == null && storages.length > 0)
dateMPolicy = storages[0].getDateMaterialPolicy();
MLocator locator = new MLocator (getCtx(), line.getM_Locator_ID(), get_TrxName()); MLocator locator = new MLocator (getCtx(), line.getM_Locator_ID(), get_TrxName());
//Update Storage //Update Storage
Timestamp effDateMPolicy = dateMPolicy;
if (dateMPolicy == null && line.getMovementQty().negate().signum() > 0)
effDateMPolicy = getMovementDate();
if (!MStorageOnHand.add(getCtx(),locator.getM_Warehouse_ID(), if (!MStorageOnHand.add(getCtx(),locator.getM_Warehouse_ID(),
line.getM_Locator_ID(), line.getM_Locator_ID(),
line.getM_Product_ID(), line.getM_Product_ID(),
ma.getM_AttributeSetInstance_ID(), line.getM_AttributeSetInstance_ID(),
ma.getMovementQty().negate(),ma.getDateMaterialPolicy(), get_TrxName())) line.getMovementQty().negate(),effDateMPolicy, get_TrxName()))
{ {
String lastError = CLogger.retrieveErrorString(""); String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError; m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError;
return DocAction.STATUS_Invalid; return DocAction.STATUS_Invalid;
} }
int M_AttributeSetInstanceTo_ID = line.getM_AttributeSetInstanceTo_ID();
//only can be same asi if locator is different
if (M_AttributeSetInstanceTo_ID == 0 && line.getM_Locator_ID() != line.getM_LocatorTo_ID())
{
M_AttributeSetInstanceTo_ID = ma.getM_AttributeSetInstance_ID();
}
//Update Storage //Update Storage
effDateMPolicy = dateMPolicy;
if (dateMPolicy == null && line.getMovementQty().signum() > 0)
effDateMPolicy = getMovementDate();
MLocator locatorTo = new MLocator (getCtx(), line.getM_LocatorTo_ID(), get_TrxName()); MLocator locatorTo = new MLocator (getCtx(), line.getM_LocatorTo_ID(), get_TrxName());
if (!MStorageOnHand.add(getCtx(),locatorTo.getM_Warehouse_ID(), if (!MStorageOnHand.add(getCtx(),locatorTo.getM_Warehouse_ID(),
line.getM_LocatorTo_ID(), line.getM_LocatorTo_ID(),
line.getM_Product_ID(), line.getM_Product_ID(),
M_AttributeSetInstanceTo_ID, line.getM_AttributeSetInstanceTo_ID(),
ma.getMovementQty(),ma.getDateMaterialPolicy(), get_TrxName())) line.getMovementQty(),effDateMPolicy, get_TrxName()))
{ {
String lastError = CLogger.retrieveErrorString(""); String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError; m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError;
@ -487,112 +575,42 @@ public class MMovement extends X_M_Movement implements DocAction
// //
trxFrom = new MTransaction (getCtx(), line.getAD_Org_ID(), trxFrom = new MTransaction (getCtx(), line.getAD_Org_ID(),
MTransaction.MOVEMENTTYPE_MovementFrom, MTransaction.MOVEMENTTYPE_MovementFrom,
line.getM_Locator_ID(), line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), line.getM_Locator_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
ma.getMovementQty().negate(), getMovementDate(), get_TrxName()); line.getMovementQty().negate(), getMovementDate(), get_TrxName());
trxFrom.setM_MovementLine_ID(line.getM_MovementLine_ID()); trxFrom.setM_MovementLine_ID(line.getM_MovementLine_ID());
if (!trxFrom.save()) if (!trxFrom.save())
{ {
m_processMsg = "Transaction From not inserted (MA)"; m_processMsg = "Transaction From not inserted";
return DocAction.STATUS_Invalid; return DocAction.STATUS_Invalid;
} }
// //
MTransaction trxTo = new MTransaction (getCtx(), line.getAD_Org_ID(), MTransaction trxTo = new MTransaction (getCtx(), line.getAD_Org_ID(),
MTransaction.MOVEMENTTYPE_MovementTo, MTransaction.MOVEMENTTYPE_MovementTo,
line.getM_LocatorTo_ID(), line.getM_Product_ID(), M_AttributeSetInstanceTo_ID, line.getM_LocatorTo_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstanceTo_ID(),
ma.getMovementQty(), getMovementDate(), get_TrxName()); line.getMovementQty(), getMovementDate(), get_TrxName());
trxTo.setM_MovementLine_ID(line.getM_MovementLine_ID()); trxTo.setM_MovementLine_ID(line.getM_MovementLine_ID());
if (!trxTo.save()) if (!trxTo.save())
{ {
m_processMsg = "Transaction To not inserted (MA)"; m_processMsg = "Transaction To not inserted";
return DocAction.STATUS_Invalid; return DocAction.STATUS_Invalid;
} }
} } // Fallback
} } // product stock
// Fallback - We have ASI }
if (trxFrom == null) catch (NegativeInventoryDisallowedException e)
{ {
Timestamp dateMPolicy= null; log.severe(e.getMessage());
MStorageOnHand[] storages = null; errors.append(Msg.getElement(getCtx(), "Line")).append(" ").append(line.getLine()).append(": ");
if (line.getMovementQty().compareTo(Env.ZERO) > 0) { errors.append(e.getMessage()).append("\n");
// Find Date Material Policy bases on ASI }
storages = MStorageOnHand.getWarehouse(getCtx(), 0,
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), null,
MClient.MMPOLICY_FiFo.equals(product.getMMPolicy()), false,
line.getM_Locator_ID(), get_TrxName());
} else {
//Case of reversal
storages = MStorageOnHand.getWarehouse(getCtx(), 0,
line.getM_Product_ID(), line.getM_AttributeSetInstanceTo_ID(), null,
MClient.MMPOLICY_FiFo.equals(product.getMMPolicy()), false,
line.getM_LocatorTo_ID(), get_TrxName());
}
for (MStorageOnHand storage : storages) {
if (storage.getQtyOnHand().compareTo(line.getMovementQty()) >= 0) {
dateMPolicy = storage.getDateMaterialPolicy();
break;
}
}
if (dateMPolicy == null && storages.length > 0)
dateMPolicy = storages[0].getDateMaterialPolicy();
MLocator locator = new MLocator (getCtx(), line.getM_Locator_ID(), get_TrxName());
//Update Storage
Timestamp effDateMPolicy = dateMPolicy;
if (dateMPolicy == null && line.getMovementQty().negate().signum() > 0)
effDateMPolicy = getMovementDate();
if (!MStorageOnHand.add(getCtx(),locator.getM_Warehouse_ID(),
line.getM_Locator_ID(),
line.getM_Product_ID(),
line.getM_AttributeSetInstance_ID(),
line.getMovementQty().negate(),effDateMPolicy, get_TrxName()))
{
String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError;
return DocAction.STATUS_Invalid;
}
//Update Storage
effDateMPolicy = dateMPolicy;
if (dateMPolicy == null && line.getMovementQty().signum() > 0)
effDateMPolicy = getMovementDate();
MLocator locatorTo = new MLocator (getCtx(), line.getM_LocatorTo_ID(), get_TrxName());
if (!MStorageOnHand.add(getCtx(),locatorTo.getM_Warehouse_ID(),
line.getM_LocatorTo_ID(),
line.getM_Product_ID(),
line.getM_AttributeSetInstanceTo_ID(),
line.getMovementQty(),effDateMPolicy, get_TrxName()))
{
String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError;
return DocAction.STATUS_Invalid;
}
//
trxFrom = new MTransaction (getCtx(), line.getAD_Org_ID(),
MTransaction.MOVEMENTTYPE_MovementFrom,
line.getM_Locator_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
line.getMovementQty().negate(), getMovementDate(), get_TrxName());
trxFrom.setM_MovementLine_ID(line.getM_MovementLine_ID());
if (!trxFrom.save())
{
m_processMsg = "Transaction From not inserted";
return DocAction.STATUS_Invalid;
}
//
MTransaction trxTo = new MTransaction (getCtx(), line.getAD_Org_ID(),
MTransaction.MOVEMENTTYPE_MovementTo,
line.getM_LocatorTo_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstanceTo_ID(),
line.getMovementQty(), getMovementDate(), get_TrxName());
trxTo.setM_MovementLine_ID(line.getM_MovementLine_ID());
if (!trxTo.save())
{
m_processMsg = "Transaction To not inserted";
return DocAction.STATUS_Invalid;
}
} // Fallback
} // product stock
} // for all lines } // for all lines
if (errors.toString().length() > 0)
{
m_processMsg = errors.toString();
return DocAction.STATUS_Invalid;
}
// User Validation // User Validation
String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE); String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE);
if (valid != null) if (valid != null)

View File

@ -232,4 +232,19 @@ public class MPInstancePara extends X_AD_PInstance_Para
} }
return -1; return -1;
} }
/**
* Get existing AD_PInstance_Para record or create a new one if not found
* @param ctx
* @param AD_PInstance_ID
* @param SeqNo
*/
public static MPInstancePara getOrCreate(Properties ctx, int AD_PInstance_ID, int SeqNo)
{
Query query = new Query(ctx, Table_Name, "AD_PInstance_ID=? AND SeqNo=?", null);
MPInstancePara para = query.setParameters(AD_PInstance_ID, SeqNo).first();
if (para == null)
para = new MPInstancePara(ctx, AD_PInstance_ID, SeqNo);
return para;
}
} // MPInstance_Para } // MPInstance_Para

View File

@ -22,8 +22,11 @@ import java.sql.Timestamp;
import java.util.Properties; import java.util.Properties;
import java.util.logging.Level; import java.util.logging.Level;
import org.adempiere.exceptions.AdempiereException;
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
import org.compiere.util.DB; import org.compiere.util.DB;
import org.compiere.util.Env; import org.compiere.util.Env;
import org.compiere.util.Msg;
/** /**
* Project Issue Model * Project Issue Model
@ -172,9 +175,57 @@ public class MProjectIssue extends X_C_ProjectIssue
dateMPolicy = t; dateMPolicy = t;
} }
if (MStorageOnHand.add(getCtx(), loc.getM_Warehouse_ID(), getM_Locator_ID(), boolean ok = true;
getM_Product_ID(), getM_AttributeSetInstance_ID(), try
getMovementQty().negate(),dateMPolicy, get_TrxName())) {
if (getMovementQty().negate().signum() < 0)
{
String MMPolicy = product.getMMPolicy();
Timestamp minGuaranteeDate = getMovementDate();
int M_Warehouse_ID = getM_Locator_ID() > 0 ? getM_Locator().getM_Warehouse_ID() : getC_Project().getM_Warehouse_ID();
MStorageOnHand[] storages = MStorageOnHand.getWarehouse(getCtx(), M_Warehouse_ID, getM_Product_ID(), getM_AttributeSetInstance_ID(),
minGuaranteeDate, MClient.MMPOLICY_FiFo.equals(MMPolicy), true, getM_Locator_ID(), get_TrxName(), true);
BigDecimal qtyToIssue = getMovementQty();
for (MStorageOnHand storage: storages)
{
if (storage.getQtyOnHand().compareTo(qtyToIssue) >= 0)
{
storage.addQtyOnHand(qtyToIssue.negate());
qtyToIssue = BigDecimal.ZERO;
}
else
{
qtyToIssue = qtyToIssue.subtract(storage.getQtyOnHand());
storage.addQtyOnHand(storage.getQtyOnHand().negate());
}
if (qtyToIssue.signum() == 0)
break;
}
if (qtyToIssue.signum() > 0)
{
ok = MStorageOnHand.add(getCtx(), loc.getM_Warehouse_ID(), getM_Locator_ID(),
getM_Product_ID(), getM_AttributeSetInstance_ID(),
qtyToIssue.negate(),dateMPolicy, get_TrxName());
}
}
else
{
ok = MStorageOnHand.add(getCtx(), loc.getM_Warehouse_ID(), getM_Locator_ID(),
getM_Product_ID(), getM_AttributeSetInstance_ID(),
getMovementQty().negate(),dateMPolicy, get_TrxName());
}
}
catch (NegativeInventoryDisallowedException e)
{
log.severe(e.getMessage());
StringBuilder error = new StringBuilder();
error.append(Msg.getElement(getCtx(), "Line")).append(" ").append(getLine()).append(": ");
error.append(e.getMessage()).append("\n");
throw new AdempiereException(error.toString());
}
if (ok)
{ {
if (mTrx.save(get_TrxName())) if (mTrx.save(get_TrxName()))
{ {

View File

@ -1328,6 +1328,7 @@ public class MSequence extends X_AD_Sequence
"AD_PINSTANCE", "AD_PINSTANCE",
"AD_PINSTANCE_LOG", "AD_PINSTANCE_LOG",
"AD_PINSTANCE_PARA", "AD_PINSTANCE_PARA",
"AD_PREFERENCE",
"AD_RECENTITEM", "AD_RECENTITEM",
"AD_REPLICATION_LOG", "AD_REPLICATION_LOG",
"AD_SCHEDULERLOG", "AD_SCHEDULERLOG",

View File

@ -27,11 +27,10 @@ import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.logging.Level; import java.util.logging.Level;
import org.adempiere.exceptions.AdempiereException; import org.adempiere.exceptions.NegativeInventoryDisallowedException;
import org.compiere.util.CLogger; import org.compiere.util.CLogger;
import org.compiere.util.DB; import org.compiere.util.DB;
import org.compiere.util.Env; import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.compiere.util.Util; import org.compiere.util.Util;
/** /**
@ -735,7 +734,8 @@ public class MStorageOnHand extends X_M_StorageOnHand
if (getQtyOnHand().signum() == -1) { if (getQtyOnHand().signum() == -1) {
MWarehouse wh = MWarehouse.get(Env.getCtx(), getM_Warehouse_ID()); MWarehouse wh = MWarehouse.get(Env.getCtx(), getM_Warehouse_ID());
if (wh.isDisallowNegativeInv()) { if (wh.isDisallowNegativeInv()) {
throw new AdempiereException(Msg.getMsg(Env.getCtx(), "NegativeInventoryDisallowed")); throw new NegativeInventoryDisallowedException(getCtx(), getM_Warehouse_ID(), getM_Product_ID(), getM_AttributeSetInstance_ID(), getM_Locator_ID(),
getQtyOnHand().subtract(addition), addition.negate());
} }
} }
} }
@ -899,13 +899,15 @@ public class MStorageOnHand extends X_M_StorageOnHand
if (getQtyOnHand().compareTo(BigDecimal.ZERO) < 0 || if (getQtyOnHand().compareTo(BigDecimal.ZERO) < 0 ||
QtyOnHand.compareTo(Env.ZERO) < 0) QtyOnHand.compareTo(Env.ZERO) < 0)
{ {
log.saveError("Error", Msg.getMsg(getCtx(), "NegativeInventoryDisallowed")); log.saveError("Error", new NegativeInventoryDisallowedException(getCtx(), getM_Warehouse_ID(), getM_Product_ID(),
getM_AttributeSetInstance_ID(), getM_Locator_ID(), QtyOnHand.subtract(getQtyOnHand()), getQtyOnHand().negate()));
return false; return false;
} }
if (getM_AttributeSetInstance_ID() > 0 && getQtyOnHand().signum() < 0) if (getM_AttributeSetInstance_ID() > 0 && getQtyOnHand().signum() < 0)
{ {
log.saveError("Error", Msg.getMsg(getCtx(), "NegativeInventoryDisallowed")); log.saveError("Error", new NegativeInventoryDisallowedException(getCtx(), getM_Warehouse_ID(), getM_Product_ID(),
getM_AttributeSetInstance_ID(), getM_Locator_ID(), QtyOnHand.subtract(getQtyOnHand()), getQtyOnHand().negate()));
return false; return false;
} }
} }

View File

@ -27,6 +27,7 @@ import java.util.Properties;
import java.util.logging.Level; import java.util.logging.Level;
import org.adempiere.exceptions.AdempiereException; import org.adempiere.exceptions.AdempiereException;
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
import org.compiere.model.MBPartner; import org.compiere.model.MBPartner;
import org.compiere.model.MBPartnerLocation; import org.compiere.model.MBPartnerLocation;
import org.compiere.model.MDocType; import org.compiere.model.MDocType;
@ -847,6 +848,7 @@ public class MDDOrder extends X_DD_Order implements DocAction
BigDecimal Volume = Env.ZERO; BigDecimal Volume = Env.ZERO;
BigDecimal Weight = Env.ZERO; BigDecimal Weight = Env.ZERO;
StringBuilder errors = new StringBuilder();
// Always check and (un) Reserve Inventory // Always check and (un) Reserve Inventory
for (MDDOrderLine line : lines) for (MDDOrderLine line : lines)
{ {
@ -874,35 +876,47 @@ public class MDDOrder extends X_DD_Order implements DocAction
MProduct product = line.getProduct(); MProduct product = line.getProduct();
if (product != null) if (product != null)
{ {
if (product.isStocked()) try
{ {
// Update Storage if (product.isStocked())
if (!MStorageOnHand.add(getCtx(), locator_to.getM_Warehouse_ID(), locator_to.getM_Locator_ID(),
line.getM_Product_ID(),
line.getM_AttributeSetInstance_ID(),
Env.ZERO,null, get_TrxName()))
{ {
throw new AdempiereException(); // Update Storage
} if (!MStorageOnHand.add(getCtx(), locator_to.getM_Warehouse_ID(), locator_to.getM_Locator_ID(),
line.getM_Product_ID(),
line.getM_AttributeSetInstance_ID(),
Env.ZERO,null, get_TrxName()))
{
throw new AdempiereException();
}
if (!MStorageOnHand.add(getCtx(), locator_from.getM_Warehouse_ID(), locator_from.getM_Locator_ID(), if (!MStorageOnHand.add(getCtx(), locator_from.getM_Warehouse_ID(), locator_from.getM_Locator_ID(),
line.getM_Product_ID(), line.getM_Product_ID(),
line.getM_AttributeSetInstanceTo_ID(), line.getM_AttributeSetInstanceTo_ID(),
Env.ZERO,null, get_TrxName())) Env.ZERO,null, get_TrxName()))
{ {
throw new AdempiereException(); throw new AdempiereException();
} }
} // stockec } // stockec
// update line // update line
line.setQtyReserved(line.getQtyReserved().add(reserved_ordered)); line.setQtyReserved(line.getQtyReserved().add(reserved_ordered));
line.saveEx(); line.saveEx();
// //
Volume = Volume.add(product.getVolume().multiply(line.getQtyOrdered())); Volume = Volume.add(product.getVolume().multiply(line.getQtyOrdered()));
Weight = Weight.add(product.getWeight().multiply(line.getQtyOrdered())); Weight = Weight.add(product.getWeight().multiply(line.getQtyOrdered()));
}
catch (NegativeInventoryDisallowedException e)
{
log.severe(e.getMessage());
errors.append(Msg.getElement(getCtx(), "Line")).append(" ").append(line.getLine()).append(": ");
errors.append(e.getMessage()).append("\n");
}
} // product } // product
} // reverse inventory } // reverse inventory
if (errors.toString().length() > 0)
throw new AdempiereException(errors.toString());
setVolume(Volume); setVolume(Volume);
setWeight(Weight); setWeight(Weight);
} // reserveStock } // reserveStock

View File

@ -8,7 +8,7 @@
<cq:property key="target.os" value="*"/> <cq:property key="target.os" value="*"/>
<cq:property key="target.ws" value="*"/> <cq:property key="target.ws" value="*"/>
<cq:advisorNode namePattern="^org\.objectweb\.asm(\..+)?" componentType="osgi.bundle" versionOverride="[5.0.1,6.0.0)"/> <cq:advisorNode namePattern="^org\.objectweb\.asm(\..+)?" componentType="osgi.bundle" versionOverride="[5.0.1,6.0.0)"/>
<cq:advisorNode namePattern="^org\.eclipse\.jetty\.osgi-servlet-api$" useTargetPlatform="false" useWorkspace="false" versionOverride="[0.0.0,9.3.11]"/> <cq:advisorNode namePattern="^org\.eclipse\.jetty\.osgi-servlet-api$" useTargetPlatform="false" useWorkspace="false" versionOverride="[0.0.0,4.0.0)"/>
<cq:advisorNode namePattern="^org\.eclipse\.jetty\.alpn\.api$" versionOverride="[0.0.0,9.3.11)"/> <cq:advisorNode namePattern="^org\.eclipse\.jetty\.alpn\.api$" versionOverride="[0.0.0,9.3.11)"/>
<cq:advisorNode namePattern="^org\.mortbay\.jasper\.apache-jsp$" componentType="osgi.bundle" versionOverride="(8.0.0,8.0.33]"/> <cq:advisorNode namePattern="^org\.mortbay\.jasper\.apache-jsp$" componentType="osgi.bundle" versionOverride="(8.0.0,8.0.33]"/>
<cq:advisorNode namePattern="^org\.eclipse\.jetty(\..+)?" useTargetPlatform="false" useWorkspace="false" versionOverride="[9.2.0,9.3.11)"/> <cq:advisorNode namePattern="^org\.eclipse\.jetty(\..+)?" useTargetPlatform="false" useWorkspace="false" versionOverride="[9.2.0,9.3.11)"/>

View File

@ -1,7 +1,7 @@
<!-- ====================================================== --> <!-- ====================================================== -->
<!-- Adempiere Distribution Setup --> <!-- iDempiere Distribution Setup -->
<!-- ====================================================== --> <!-- ====================================================== -->
<!-- $Header: /cvs/adempiere/install/Adempiere/build.xml,v 1.4 2006/07/03 16:51:31 jjanke Exp $--> <!-- $Header: org.adempiere.server-feature/build.xml $-->
<project name="setup" default="setup" basedir="."> <project name="setup" default="setup" basedir=".">
@ -52,6 +52,8 @@
<copy file="hazelcast-template.xml" <copy file="hazelcast-template.xml"
tofile="hazelcast.xml" filtering="yes" overwrite="yes"/> tofile="hazelcast.xml" filtering="yes" overwrite="yes"/>
<mkdir dir="jettyhome/work"/>
<mkdir dir="log"/>
</target> </target>
<!-- ==================================================== --> <!-- ==================================================== -->
@ -110,6 +112,6 @@
<!-- Setup (Main) --> <!-- Setup (Main) -->
<!-- ==================================================== --> <!-- ==================================================== -->
<target name="setup" depends="setupInit, setupWin, setupNonWin" <target name="setup" depends="setupInit, setupWin, setupNonWin"
description="Setup Adempiere"> description="Setup iDempiere">
</target> </target>
</project> </project>

View File

@ -159,4 +159,5 @@
<Arg>org.eclipse.jetty.server.Request.maxFormContentSize</Arg> <Arg>org.eclipse.jetty.server.Request.maxFormContentSize</Arg>
<Arg>1048576</Arg> <Arg>1048576</Arg>
</Call> </Call>
<Set class="org.eclipse.jetty.util.resource.Resource" name="defaultUseCaches">false</Set>
</Configure> </Configure>

View File

@ -34,6 +34,7 @@ import org.compiere.model.MClient;
import org.compiere.model.MCost; import org.compiere.model.MCost;
import org.compiere.model.MOrgInfo; import org.compiere.model.MOrgInfo;
import org.compiere.model.MRole; import org.compiere.model.MRole;
import org.compiere.model.MTable;
import org.compiere.model.MUser; import org.compiere.model.MUser;
import org.compiere.util.DB; import org.compiere.util.DB;
import org.compiere.util.Env; import org.compiere.util.Env;
@ -224,7 +225,6 @@ public class AcctProcessor extends AdempiereServer
rs = pstmt.executeQuery(); rs = pstmt.executeQuery();
while (!isInterrupted() && rs.next()) while (!isInterrupted() && rs.next())
{ {
count[i]++;
boolean ok = true; boolean ok = true;
try try
{ {
@ -238,6 +238,17 @@ public class AcctProcessor extends AdempiereServer
} }
if (!ok) if (!ok)
countError[i]++; countError[i]++;
else // only count the posted record.
{
MTable table = MTable.get(Env.getCtx(), AD_Table_ID);
int Record_ID = rs.getInt(table.getKeyColumns()[0]);
sql = new StringBuffer("SELECT COUNT(*) FROM ").append(table.getTableName());
sql.append(" WHERE Posted='Y' AND ").append(table.getTableName()).append("_ID=").append(Record_ID);
int no = DB.getSQLValue(null, sql.toString());
if (no > 0 )
count[i]++;
}
} }
} }
catch (Exception e) catch (Exception e)

View File

@ -207,7 +207,7 @@ public class ProcessParameterPanel extends CPanel implements VetoableChangeListe
+ "p.AD_Reference_ID, p.AD_Process_Para_ID, " + "p.AD_Reference_ID, p.AD_Process_Para_ID, "
+ "p.FieldLength, p.IsMandatory, p.IsRange, p.ColumnName, " + "p.FieldLength, p.IsMandatory, p.IsRange, p.ColumnName, "
+ "p.DefaultValue, p.DefaultValue2, p.VFormat, p.ValueMin, p.ValueMax, " + "p.DefaultValue, p.DefaultValue2, p.VFormat, p.ValueMin, p.ValueMax, "
+ "p.SeqNo, p.AD_Reference_Value_ID, vr.Code AS ValidationCode, p.ReadOnlyLogic, p.DisplayLogic, p.IsEncrypted, NULL AS FormatPattern " + "p.SeqNo, p.AD_Reference_Value_ID, vr.Code AS ValidationCode, p.ReadOnlyLogic, p.DisplayLogic, p.IsEncrypted, NULL AS FormatPattern, p.MandatoryLogic "
+ "FROM AD_Process_Para p" + "FROM AD_Process_Para p"
+ " LEFT OUTER JOIN AD_Val_Rule vr ON (p.AD_Val_Rule_ID=vr.AD_Val_Rule_ID) " + " LEFT OUTER JOIN AD_Val_Rule vr ON (p.AD_Val_Rule_ID=vr.AD_Val_Rule_ID) "
+ "WHERE p.AD_Process_ID=?" // 1 + "WHERE p.AD_Process_ID=?" // 1
@ -218,7 +218,7 @@ public class ProcessParameterPanel extends CPanel implements VetoableChangeListe
+ "p.AD_Reference_ID, p.AD_Process_Para_ID, " + "p.AD_Reference_ID, p.AD_Process_Para_ID, "
+ "p.FieldLength, p.IsMandatory, p.IsRange, p.ColumnName, " + "p.FieldLength, p.IsMandatory, p.IsRange, p.ColumnName, "
+ "p.DefaultValue, p.DefaultValue2, p.VFormat, p.ValueMin, p.ValueMax, " + "p.DefaultValue, p.DefaultValue2, p.VFormat, p.ValueMin, p.ValueMax, "
+ "p.SeqNo, p.AD_Reference_Value_ID, vr.Code AS ValidationCode, p.ReadOnlyLogic, p.DisplayLogic, p.IsEncrypted, NULL AS FormatPattern " + "p.SeqNo, p.AD_Reference_Value_ID, vr.Code AS ValidationCode, p.ReadOnlyLogic, p.DisplayLogic, p.IsEncrypted, NULL AS FormatPattern, p.MandatoryLogic "
+ "FROM AD_Process_Para p" + "FROM AD_Process_Para p"
+ " INNER JOIN AD_Process_Para_Trl t ON (p.AD_Process_Para_ID=t.AD_Process_Para_ID)" + " INNER JOIN AD_Process_Para_Trl t ON (p.AD_Process_Para_ID=t.AD_Process_Para_ID)"
+ " LEFT OUTER JOIN AD_Val_Rule vr ON (p.AD_Val_Rule_ID=vr.AD_Val_Rule_ID) " + " LEFT OUTER JOIN AD_Val_Rule vr ON (p.AD_Val_Rule_ID=vr.AD_Val_Rule_ID) "

View File

@ -448,7 +448,7 @@ public class AdempiereWebUI extends Window implements EventListener<Event>, IWeb
String ua = Servlets.getUserAgent((ServletRequest) Executions.getCurrent().getNativeRequest()); String ua = Servlets.getUserAgent((ServletRequest) Executions.getCurrent().getNativeRequest());
clientInfo.userAgent = ua; clientInfo.userAgent = ua;
ua = ua.toLowerCase(); ua = ua.toLowerCase();
clientInfo.tablet = ua.indexOf("ipad") >= 0 || ua.indexOf("iphone") >= 0 || ua.indexOf("android") >= 0; clientInfo.tablet = Executions.getCurrent().getBrowser("mobile") !=null;
if (getDesktop() != null && getDesktop().getSession() != null) { if (getDesktop() != null && getDesktop().getSession() != null) {
getDesktop().getSession().setAttribute(CLIENT_INFO, clientInfo); getDesktop().getSession().setAttribute(CLIENT_INFO, clientInfo);
} }
@ -456,6 +456,7 @@ public class AdempiereWebUI extends Window implements EventListener<Event>, IWeb
Env.setContext(Env.getCtx(), "#clientInfo_desktopWidth", clientInfo.desktopWidth); Env.setContext(Env.getCtx(), "#clientInfo_desktopWidth", clientInfo.desktopWidth);
Env.setContext(Env.getCtx(), "#clientInfo_desktopHeight", clientInfo.desktopHeight); Env.setContext(Env.getCtx(), "#clientInfo_desktopHeight", clientInfo.desktopHeight);
Env.setContext(Env.getCtx(), "#clientInfo_orientation", clientInfo.orientation); Env.setContext(Env.getCtx(), "#clientInfo_orientation", clientInfo.orientation);
Env.setContext(Env.getCtx(), "#clientInfo_mobile", clientInfo.tablet);
} }
} }

View File

@ -17,24 +17,21 @@ package org.adempiere.webui;
import java.util.Locale; import java.util.Locale;
import java.util.Properties; import java.util.Properties;
import javax.servlet.ServletRequest;
import org.adempiere.webui.apps.AEnv; import org.adempiere.webui.apps.AEnv;
import org.adempiere.webui.part.AbstractUIPart; import org.adempiere.webui.part.AbstractUIPart;
import org.adempiere.webui.theme.ThemeManager; import org.adempiere.webui.theme.ThemeManager;
import org.adempiere.webui.util.ZKUpdateUtil; import org.adempiere.webui.util.ZKUpdateUtil;
import org.adempiere.webui.window.LoginWindow; import org.adempiere.webui.window.LoginWindow;
import org.zkoss.web.servlet.Servlets;
import org.zkoss.zhtml.Text; import org.zkoss.zhtml.Text;
import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.metainfo.PageDefinition; import org.zkoss.zk.ui.metainfo.PageDefinition;
import org.zkoss.zul.Borderlayout; import org.zkoss.zul.Borderlayout;
import org.zkoss.zul.Div;
import org.zkoss.zul.East; import org.zkoss.zul.East;
import org.zkoss.zul.North; import org.zkoss.zul.North;
import org.zkoss.zul.South; import org.zkoss.zul.South;
import org.zkoss.zul.West; import org.zkoss.zul.West;
import org.zkoss.zul.Div;
import org.zkoss.zul.Window; import org.zkoss.zul.Window;
/** /**
@ -82,15 +79,13 @@ public class WLogin extends AbstractUIPart
browserWarningWindow.doOverlapped(); browserWarningWindow.doOverlapped();
} }
String ua = Servlets.getUserAgent((ServletRequest) Executions.getCurrent().getNativeRequest()); boolean mobile = Executions.getCurrent().getBrowser("mobile") !=null;
ua = ua.toLowerCase();
boolean mobile = ua.indexOf("ipad") >= 0 || ua.indexOf("iphone") >= 0 || ua.indexOf("android") >= 0;
West west = layout.getWest(); West west = layout.getWest();
if (west.getFirstChild() != null && west.getFirstChild().getFirstChild() != null) { if (west.getFirstChild() != null && west.getFirstChild().getFirstChild() != null) {
west.setCollapsible(true);
west.setSplittable(true);
if (mobile) { if (mobile) {
west.setCollapsible(true);
west.setOpen(false); west.setOpen(false);
} }
} else { } else {

View File

@ -644,6 +644,8 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
saveReportOptionToInstance(savedParams.get(i)); saveReportOptionToInstance(savedParams.get(i));
savedParams.get(i).saveEx(); savedParams.get(i).saveEx();
getProcessInfo().setAD_PInstance_ID(0);
} }
} }
} }

View File

@ -520,7 +520,7 @@ public class ProcessParameterPanel extends Panel implements
result2 = editor2.getValue(); result2 = editor2.getValue();
// Create Parameter // Create Parameter
MPInstancePara para = new MPInstancePara(Env.getCtx(), MPInstancePara para = MPInstancePara.getOrCreate(Env.getCtx(),
m_processInfo.getAD_PInstance_ID(), i); m_processInfo.getAD_PInstance_ID(), i);
GridField mField = (GridField) m_mFields.get(i); GridField mField = (GridField) m_mFields.get(i);
para.setParameterName(mField.getColumnName()); para.setParameterName(mField.getColumnName());

View File

@ -272,9 +272,11 @@ public class WPaySelect extends PaySelect
*/ */
private void loadBankInfo() private void loadBankInfo()
{ {
BankInfo bi = (BankInfo)fieldBankAccount.getSelectedItem().getValue(); if (fieldBankAccount.getItemCount() == 0)
if (bi == null)
return; return;
BankInfo bi = (BankInfo)fieldBankAccount.getSelectedItem().getValue();
labelCurrency.setText(bi.Currency); labelCurrency.setText(bi.Currency);
labelBalance.setText(m_format.format(bi.Balance)); labelBalance.setText(m_format.format(bi.Balance));
@ -301,7 +303,13 @@ public class WPaySelect extends PaySelect
miniTable.setColorCompare(payDate); miniTable.setColorCompare(payDate);
if (log.isLoggable(Level.CONFIG)) log.config("PayDate=" + payDate); if (log.isLoggable(Level.CONFIG)) log.config("PayDate=" + payDate);
BankInfo bi = (BankInfo)fieldBankAccount.getSelectedItem().getValue(); if (fieldBankAccount.getItemCount() == 0) {
FDialog.error(m_WindowNo, form, "VPaySelectNoBank");
return;
}
BankInfo bi = fieldBankAccount.getSelectedItem().getValue();
ValueNamePair paymentRule = (ValueNamePair) fieldPaymentRule.getSelectedItem().getValue(); ValueNamePair paymentRule = (ValueNamePair) fieldPaymentRule.getSelectedItem().getValue();
KeyNamePair bpartner = (KeyNamePair) fieldBPartner.getSelectedItem().getValue(); KeyNamePair bpartner = (KeyNamePair) fieldBPartner.getSelectedItem().getValue();

View File

@ -224,6 +224,13 @@ public class DefaultDesktop extends TabbedDesktop implements MenuListener, Seria
boolean menuCollapsed= pref.isPropertyBool(UserPreference.P_MENU_COLLAPSED); boolean menuCollapsed= pref.isPropertyBool(UserPreference.P_MENU_COLLAPSED);
w.setOpen(!menuCollapsed); w.setOpen(!menuCollapsed);
boolean mobile = Executions.getCurrent().getBrowser("mobile") !=null;
w.setCollapsible(true);
if (mobile) {
w.setOpen(false);
}
East e = layout.getEast(); East e = layout.getEast();
e.addEventListener(Events.ON_OPEN, new EventListener<Event>() { e.addEventListener(Events.ON_OPEN, new EventListener<Event>() {
@Override @Override
@ -293,6 +300,11 @@ public class DefaultDesktop extends TabbedDesktop implements MenuListener, Seria
helpController.render(e, this); helpController.render(e, this);
if (mobile) {
e.setVisible(false);
e.setOpen(false);
}
Center windowArea = layout.getCenter(); Center windowArea = layout.getCenter();
windowContainer.createPart(windowArea); windowContainer.createPart(windowArea);

View File

@ -76,6 +76,7 @@ import org.adempiere.webui.util.ZKUpdateUtil;
import org.compiere.model.GridField; import org.compiere.model.GridField;
import org.compiere.model.GridFieldVO; import org.compiere.model.GridFieldVO;
import org.compiere.model.GridTab; import org.compiere.model.GridTab;
import org.compiere.model.Lookup;
import org.compiere.model.MColumn; import org.compiere.model.MColumn;
import org.compiere.model.MLookup; import org.compiere.model.MLookup;
import org.compiere.model.MLookupFactory; import org.compiere.model.MLookupFactory;
@ -92,9 +93,11 @@ import org.compiere.util.DisplayType;
import org.compiere.util.Env; import org.compiere.util.Env;
import org.compiere.util.Msg; import org.compiere.util.Msg;
import org.compiere.util.SecureEngine; import org.compiere.util.SecureEngine;
import org.compiere.util.Util;
import org.compiere.util.ValueNamePair; import org.compiere.util.ValueNamePair;
import org.zkoss.zk.au.out.AuFocus; import org.zkoss.zk.au.out.AuFocus;
import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Components;
import org.zkoss.zk.ui.HtmlBasedComponent; import org.zkoss.zk.ui.HtmlBasedComponent;
import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.EventListener;
@ -122,10 +125,14 @@ import org.zkoss.zul.Vlayout;
*/ */
public class FindWindow extends Window implements EventListener<Event>, ValueChangeListener, DialogEvents public class FindWindow extends Window implements EventListener<Event>, ValueChangeListener, DialogEvents
{ {
private static final String FIND_ROW_EDITOR = "find.row.editor";
private static final String FIND_ROW_EDITOR_TO = "find.row.editor.to";
/** /**
* *
*/ */
private static final long serialVersionUID = -5747652133096022993L; private static final long serialVersionUID = -4461202150492732658L;
// values and label for history combo // values and label for history combo
private static final String HISTORY_DAY_ALL = "All"; private static final String HISTORY_DAY_ALL = "All";
@ -221,7 +228,8 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
private Combobox historyCombo = new Combobox(); private Combobox historyCombo = new Combobox();
private Properties m_findCtx; private Properties m_simpleCtx;
private Properties m_advanceCtx;
private static final String ON_POST_VISIBLE_ATTR = "onPostVisible.Event.Posted"; private static final String ON_POST_VISIBLE_ATTR = "onPostVisible.Event.Posted";
@ -251,7 +259,8 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
m_minRecords = minRecords; m_minRecords = minRecords;
m_isCancel = true; m_isCancel = true;
// //
m_findCtx = new Properties(Env.getCtx()); m_simpleCtx = new Properties(Env.getCtx());
m_advanceCtx = new Properties(Env.getCtx());
this.setBorder("normal"); this.setBorder("normal");
this.setShadow(false); this.setShadow(false);
@ -634,7 +643,7 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
if (mField.getVO().displayType == DisplayType.YesNo) { if (mField.getVO().displayType == DisplayType.YesNo) {
// Make Yes-No searchable as list // Make Yes-No searchable as list
GridFieldVO vo = mField.getVO(); GridFieldVO vo = mField.getVO();
GridFieldVO ynvo = vo.clone(vo.ctx, vo.WindowNo, vo.TabNo, vo.AD_Window_ID, vo.AD_Tab_ID, vo.tabReadOnly); GridFieldVO ynvo = vo.clone(m_simpleCtx, vo.WindowNo, vo.TabNo, vo.AD_Window_ID, vo.AD_Tab_ID, vo.tabReadOnly);
ynvo.IsDisplayed = true; ynvo.IsDisplayed = true;
ynvo.displayType = DisplayType.List; ynvo.displayType = DisplayType.List;
ynvo.AD_Reference_Value_ID = REFERENCE_YESNO; ynvo.AD_Reference_Value_ID = REFERENCE_YESNO;
@ -642,6 +651,7 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
ynvo.lookupInfo = MLookupFactory.getLookupInfo (ynvo.ctx, ynvo.WindowNo, ynvo.AD_Column_ID, ynvo.displayType, ynvo.lookupInfo = MLookupFactory.getLookupInfo (ynvo.ctx, ynvo.WindowNo, ynvo.AD_Column_ID, ynvo.displayType,
Env.getLanguage(ynvo.ctx), ynvo.ColumnName, ynvo.AD_Reference_Value_ID, Env.getLanguage(ynvo.ctx), ynvo.ColumnName, ynvo.AD_Reference_Value_ID,
ynvo.IsParent, ynvo.ValidationCode); ynvo.IsParent, ynvo.ValidationCode);
ynvo.lookupInfo.tabNo = TABNO;
GridField ynfield = new GridField(ynvo); GridField ynfield = new GridField(ynvo);
@ -653,13 +663,14 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
GridFieldVO vo = mField.getVO(); GridFieldVO vo = mField.getVO();
if ( vo.AD_Reference_Value_ID > 0 ) if ( vo.AD_Reference_Value_ID > 0 )
{ {
GridFieldVO postedvo = vo.clone(vo.ctx, vo.WindowNo, vo.TabNo, vo.AD_Window_ID, vo.AD_Tab_ID, vo.tabReadOnly); GridFieldVO postedvo = vo.clone(m_simpleCtx, vo.WindowNo, vo.TabNo, vo.AD_Window_ID, vo.AD_Tab_ID, vo.tabReadOnly);
postedvo.IsDisplayed = true; postedvo.IsDisplayed = true;
postedvo.displayType = DisplayType.List; postedvo.displayType = DisplayType.List;
postedvo.lookupInfo = MLookupFactory.getLookupInfo (postedvo.ctx, postedvo.WindowNo, postedvo.AD_Column_ID, postedvo.displayType, postedvo.lookupInfo = MLookupFactory.getLookupInfo (postedvo.ctx, postedvo.WindowNo, postedvo.AD_Column_ID, postedvo.displayType,
Env.getLanguage(postedvo.ctx), postedvo.ColumnName, postedvo.AD_Reference_Value_ID, Env.getLanguage(postedvo.ctx), postedvo.ColumnName, postedvo.AD_Reference_Value_ID,
postedvo.IsParent, postedvo.ValidationCode); postedvo.IsParent, postedvo.ValidationCode);
postedvo.lookupInfo.tabNo = TABNO;
GridField postedfield = new GridField(postedvo); GridField postedfield = new GridField(postedvo);
@ -669,7 +680,15 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
} }
} else { } else {
// clone the field and clean gridtab - IDEMPIERE-1105 // clone the field and clean gridtab - IDEMPIERE-1105
GridField findField = (GridField) mField.clone(m_findCtx); GridField findField = (GridField) mField.clone(m_simpleCtx);
if (findField.isLookup()) {
Lookup lookup = findField.getLookup();
if (lookup != null && lookup instanceof MLookup) {
MLookup mLookup = (MLookup) lookup;
mLookup.getLookupInfo().ctx = m_simpleCtx;
mLookup.getLookupInfo().tabNo = TABNO;
}
}
findField.setGridTab(null); findField.setGridTab(null);
m_findFields[i] = findField; m_findFields[i] = findField;
mField = findField; mField = findField;
@ -1058,6 +1077,7 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
editor.setMandatory(false); editor.setMandatory(false);
editor.setReadWrite(true); editor.setReadWrite(true);
editor.dynamicDisplay(); editor.dynamicDisplay();
editor.addValueChangeListener(this);
Label label = editor.getLabel(); Label label = editor.getLabel();
Component fieldEditor = editor.getComponent(); Component fieldEditor = editor.getComponent();
@ -1075,6 +1095,7 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
editorTo.setMandatory(false); editorTo.setMandatory(false);
editorTo.setReadWrite(true); editorTo.setReadWrite(true);
editorTo.dynamicDisplay(); editorTo.dynamicDisplay();
editorTo.addValueChangeListener(this);
// //
if (displayLength > 0) // set it back if (displayLength > 0) // set it back
mField.setDisplayLength(displayLength); mField.setDisplayLength(displayLength);
@ -1916,7 +1937,7 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
GridField field = getTargetMField(columnName); GridField field = getTargetMField(columnName);
if(field == null) return new Label(""); if(field == null) return new Label("");
GridField findField = (GridField) field.clone(m_findCtx); GridField findField = (GridField) field.clone(m_advanceCtx);
findField.setGridTab(null); findField.setGridTab(null);
WEditor editor = null; WEditor editor = null;
if (findField.isKey() if (findField.isKey()
@ -1928,6 +1949,7 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
{ {
if (findField.getAD_Reference_Value_ID() > 0) { if (findField.getAD_Reference_Value_ID() > 0) {
MLookupInfo info = MLookupFactory.getLookup_List(Env.getLanguage(Env.getCtx()), findField.getAD_Reference_Value_ID()); MLookupInfo info = MLookupFactory.getLookup_List(Env.getLanguage(Env.getCtx()), findField.getAD_Reference_Value_ID());
info.tabNo = TABNO;
MLookup mLookup = new MLookup(info, 0); MLookup mLookup = new MLookup(info, 0);
editor = new WTableDirEditor(columnName, false,false, true, mLookup); editor = new WTableDirEditor(columnName, false,false, true, mLookup);
findField.addPropertyChangeListener(editor); findField.addPropertyChangeListener(editor);
@ -1946,6 +1968,12 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
if (DisplayType.isLookup(findField.getDisplayType()) ) if (DisplayType.isLookup(findField.getDisplayType()) )
{ {
findField.loadLookupNoValidate(); findField.loadLookupNoValidate();
Lookup lookup = findField.getLookup();
if (lookup != null && lookup instanceof MLookup)
{
MLookup mLookup = (MLookup) lookup;
mLookup.getLookupInfo().tabNo = TABNO;
}
editor = WebEditorFactory.getEditor(findField, true); editor = WebEditorFactory.getEditor(findField, true);
findField.addPropertyChangeListener(editor); findField.addPropertyChangeListener(editor);
} }
@ -1970,6 +1998,10 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
((WPaymentEditor)editor).getComponent().setEnabled(true, false); ((WPaymentEditor)editor).getComponent().setEnabled(true, false);
} }
// //
if (to)
row.setAttribute(FIND_ROW_EDITOR_TO, editor);
else
row.setAttribute(FIND_ROW_EDITOR, editor);
return editor.getComponent(); return editor.getComponent();
} // getTableCellEditorComponent } // getTableCellEditorComponent
@ -2358,20 +2390,92 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
{ {
WEditor editor = (WEditor)evt.getSource(); WEditor editor = (WEditor)evt.getSource();
// Editor component // Editor component
Component component = editor.getComponent(); ListCell listcell = null;
ListCell listcell = (ListCell)component.getParent(); Properties ctx = null;
listcell.setAttribute("value", evt.getNewValue()); if (winMain.getComponent().getSelectedIndex() == 1)
if (evt.getNewValue() == null) {
Env.setContext(m_findCtx, m_targetWindowNo, editor.getColumnName(), ""); Component component = editor.getComponent();
else if (evt.getNewValue() instanceof Boolean) listcell = (ListCell)component.getParent();
Env.setContext(m_findCtx, m_targetWindowNo, editor.getColumnName(), (Boolean)evt.getNewValue()); listcell.setAttribute("value", evt.getNewValue());
else if (evt.getNewValue() instanceof Timestamp) ctx = m_advanceCtx;
Env.setContext(m_findCtx, m_targetWindowNo, editor.getColumnName(), (Timestamp)evt.getNewValue()); }
else else
Env.setContext(m_findCtx, m_targetWindowNo, editor.getColumnName(), evt.getNewValue().toString()); {
ctx = m_simpleCtx;
}
if (evt.getNewValue() == null)
{
Env.setContext(ctx, m_targetWindowNo, editor.getColumnName(), "");
Env.setContext(ctx, m_targetWindowNo, TABNO, editor.getColumnName(), "");
}
else if (evt.getNewValue() instanceof Boolean)
{
Env.setContext(ctx, m_targetWindowNo, editor.getColumnName(), (Boolean)evt.getNewValue());
Env.setContext(ctx, m_targetWindowNo, TABNO, editor.getColumnName(), (Boolean)evt.getNewValue());
}
else if (evt.getNewValue() instanceof Timestamp)
{
Env.setContext(ctx, m_targetWindowNo, editor.getColumnName(), (Timestamp)evt.getNewValue());
Env.setContext(ctx, m_targetWindowNo, TABNO + "|" + editor.getColumnName(), (Timestamp)evt.getNewValue());
}
else
{
Env.setContext(ctx, m_targetWindowNo, editor.getColumnName(), evt.getNewValue().toString());
Env.setContext(ctx, m_targetWindowNo, TABNO, editor.getColumnName(), evt.getNewValue().toString());
}
dynamicDisplay(editor, listcell);
} }
} }
private void dynamicDisplay(WEditor editor, ListCell listcell) {
if (winMain.getComponent().getSelectedIndex() == 1)
{
List<?> rowList = advancedPanel.getChildren();
for (int rowIndex = 1; rowIndex < rowList.size() ; rowIndex++)
{
// Column
ListItem row = (ListItem)rowList.get(rowIndex);
if (Components.isAncestor(row, listcell))
continue;
WEditor other = (WEditor) row.getAttribute(FIND_ROW_EDITOR);
if (other != null && other.getGridField() != null && other.getGridField().isLookup())
{
Lookup lookup = other.getGridField().getLookup();
if (!Util.isEmpty(lookup.getValidation()))
{
other.dynamicDisplay();
other = (WEditor) row.getAttribute(FIND_ROW_EDITOR_TO);
if (other != null)
other.dynamicDisplay();
}
}
}
}
else
{
for (int i = 0; i < m_sEditors.size(); i++)
{
WEditor wed = (WEditor)m_sEditors.get(i);
if (wed == editor)
continue;
if (wed.getGridField() != null && wed.getGridField().isLookup())
{
Lookup lookup = wed.getGridField().getLookup();
if (!Util.isEmpty(lookup.getValidation()))
{
wed.dynamicDisplay();
wed = m_sEditorsTo.get(i);
if (wed != null && wed != editor)
wed.dynamicDisplay();
}
}
}
}
}
public void OnPostVisible() { public void OnPostVisible() {
removeAttribute(ON_POST_VISIBLE_ATTR); removeAttribute(ON_POST_VISIBLE_ATTR);
if (m_sEditors.size() > 0) if (m_sEditors.size() > 0)
@ -2410,7 +2514,7 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
private boolean isSearchLike(GridField field) private boolean isSearchLike(GridField field)
{ {
return DisplayType.isText(field.getDisplayType()) return DisplayType.isText(field.getDisplayType()) && !field.isVirtualColumn()
&& (field.isSelectionColumn() || MColumn.isSuggestSelectionColumn(field.getColumnName(), true)); && (field.isSelectionColumn() || MColumn.isSuggestSelectionColumn(field.getColumnName(), true));
} }

View File

@ -231,3 +231,25 @@
height: 16px; height: 16px;
padding: 3px 3px; padding: 3px 3px;
} }
@media screen and (min-width: 720px) {
.desktop-header > .z-hlayout-inner {
width: 50%;
height: 100%;
}
}
@media screen and (max-width: 720px) {
.desktop-header {
width: 100%;
height: 100%;
}
.desktop-user-panel {
float: none;
}
.desktop-header > .z-hlayout-inner {
width: 100%;
height: 40%;
display: block;
}
}

View File

@ -1,19 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<zk> <zk>
<div sclass="desktop-header" use="org.adempiere.webui.panel.HeaderPanel" id="header"> <div sclass="desktop-header" use="org.adempiere.webui.panel.HeaderPanel" id="header">
<borderlayout sclass="desktop-header"> <hlayout vflex="1" sclass="desktop-header">
<west width="50%" sclass="desktop-header-left"> <hbox height="100%" pack="center" align="left" sclass="desktop-header-left">
<hbox height="100%" pack="center" align="left">
<image id="logo"/> <image id="logo"/>
<div id="menuLookup"/> <div id="menuLookup"/>
<button id="menuButton" sclass="btn-small"/> <button id="menuButton" sclass="btn-small"/>
</hbox> </hbox>
</west> <vbox apply="org.adempiere.webui.panel.UserPanel" align="right"
<center sclass="desktop-header-right">
<vbox apply="org.adempiere.webui.panel.UserPanel" align="right"
hflex="1" vflex="1"
sclass="desktop-user-panel"> sclass="desktop-user-panel">
<vbox align="right"> <vbox align="right">
<label use="org.adempiere.webui.component.Label" id="loginUserAndRole" <label use="org.adempiere.webui.component.Label" id="loginUserAndRole"
style="cursor: pointer;" style="cursor: pointer;"
sclass="desktop-header-font desktop-header-username"/> sclass="desktop-header-font desktop-header-username"/>
@ -32,7 +28,6 @@
</hbox> </hbox>
</vbox> </vbox>
</vbox> </vbox>
</center> </hlayout>
</borderlayout>
</div> </div>
</zk> </zk>