hg merge release-4.1 (merge release4.1 into development)
This commit is contained in:
commit
ea5192578b
|
@ -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
|
||||
;
|
||||
|
|
@ -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
|
||||
;
|
||||
|
|
@ -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
|
||||
;
|
|
@ -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
|
||||
;
|
||||
|
|
@ -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
|
||||
;
|
||||
|
|
@ -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
|
||||
;
|
|
@ -72,7 +72,7 @@ public class EventManager implements IEventManager {
|
|||
*/
|
||||
public static IEventManager getInstance() {
|
||||
synchronized (mutex) {
|
||||
if (instance == null) {
|
||||
while (instance == null) {
|
||||
try {
|
||||
mutex.wait(10000);
|
||||
} catch (InterruptedException e) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -1326,6 +1326,8 @@ public class GridTabCSVImporter implements IGridTabImporter
|
|||
return (new Optional(new ParseBigDecimal(new DecimalFormatSymbols(Language.getLoginLanguage().getLocale()))));
|
||||
} else if (DisplayType.YesNo == field.getDisplayType()) {
|
||||
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())) {
|
||||
return (new Optional(new StrMinMax(1, field.getFieldLength())));
|
||||
} else { // optional lookups and text
|
||||
|
|
|
@ -555,6 +555,12 @@ public abstract class Doc
|
|||
p_Error = loadDocumentDetails();
|
||||
if (p_Error != null)
|
||||
return p_Error;
|
||||
if (isDeferPosting())
|
||||
{
|
||||
unlock();
|
||||
p_Status = STATUS_NotPosted;
|
||||
return null;
|
||||
}
|
||||
|
||||
Trx trx = Trx.get(getTrxName(), true);
|
||||
// Delete existing Accounting
|
||||
|
@ -2304,4 +2310,11 @@ public abstract class Doc
|
|||
public ArrayList<Fact> getFacts() {
|
||||
return m_fact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return document whether need to defer posting or not
|
||||
*/
|
||||
public boolean isDeferPosting() {
|
||||
return false;
|
||||
}
|
||||
} // Doc
|
||||
|
|
|
@ -77,6 +77,7 @@ public class Doc_MatchPO extends Doc
|
|||
private ProductCost m_pc;
|
||||
private int m_M_AttributeSetInstance_ID = 0;
|
||||
private MMatchPO m_matchPO;
|
||||
private boolean m_deferPosting = false;
|
||||
|
||||
/**
|
||||
* Load Specific Document Details
|
||||
|
@ -103,6 +104,24 @@ public class Doc_MatchPO extends Doc
|
|||
m_pc = new ProductCost (Env.getCtx(),
|
||||
getM_Product_ID(), m_M_AttributeSetInstance_ID, getTrxName());
|
||||
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;
|
||||
} // loadDocumentDetails
|
||||
|
||||
|
@ -487,4 +506,11 @@ public class Doc_MatchPO extends Doc
|
|||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isDeferPosting() {
|
||||
return m_deferPosting;
|
||||
}
|
||||
|
||||
|
||||
} // Doc_MatchPO
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.util.ArrayList;
|
|||
import java.util.logging.Level;
|
||||
|
||||
import org.compiere.model.MAcctSchema;
|
||||
import org.compiere.model.MCostDetail;
|
||||
import org.compiere.model.MProduct;
|
||||
import org.compiere.model.MProject;
|
||||
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.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>();
|
||||
facts.add(fact);
|
||||
return facts;
|
||||
|
@ -203,6 +218,8 @@ public class Doc_ProjectIssue extends Doc
|
|||
DB.close(rs, pstmt);
|
||||
pstmt = null; rs = null;
|
||||
}
|
||||
if (retValue != null)
|
||||
retValue = retValue.multiply(m_line.getQty());
|
||||
return retValue;
|
||||
} // getPOCost();
|
||||
|
||||
|
|
|
@ -529,6 +529,70 @@ public class MCostDetail extends X_M_CostDetail
|
|||
return ok;
|
||||
} // 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
|
||||
* @param ctx context
|
||||
|
@ -1319,10 +1383,14 @@ public class MCostDetail extends X_M_CostDetail
|
|||
log.warning("Unknown Type: " + toString());
|
||||
return false;
|
||||
}
|
||||
|
||||
//Should only update cost detail with value from as costing method
|
||||
if(as.getCostingMethod().equals(ce.getCostingMethod())) {
|
||||
setCurrentCostPrice(cost.getCurrentCostPrice());
|
||||
setCurrentQty(cost.getCurrentQty());
|
||||
setCumulatedAmt(cost.getCumulatedAmt());
|
||||
setCumulatedQty(cost.getCumulatedQty());
|
||||
}
|
||||
|
||||
//update history
|
||||
history.setNewQty(cost.getCurrentQty());
|
||||
|
|
|
@ -26,6 +26,7 @@ import java.util.Properties;
|
|||
import java.util.logging.Level;
|
||||
|
||||
import org.adempiere.exceptions.AdempiereException;
|
||||
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
|
||||
import org.adempiere.exceptions.PeriodClosedException;
|
||||
import org.compiere.print.MPrintFormat;
|
||||
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());
|
||||
StringBuilder info = new StringBuilder();
|
||||
|
||||
StringBuilder errors = new StringBuilder();
|
||||
// For all lines
|
||||
MInOutLine[] lines = getLines(false);
|
||||
for (int lineIndex = 0; lineIndex < lines.length; lineIndex++)
|
||||
|
@ -1293,6 +1295,8 @@ public class MInOut extends X_M_InOut implements DocAction
|
|||
MInOutLine sLine = lines[lineIndex];
|
||||
MProduct product = sLine.getProduct();
|
||||
|
||||
try
|
||||
{
|
||||
// Qty & Type
|
||||
String MovementType = getMovementType();
|
||||
BigDecimal Qty = sLine.getMovementQty();
|
||||
|
@ -1649,9 +1653,21 @@ public class MInOut extends X_M_InOut implements DocAction
|
|||
}
|
||||
} // 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
|
||||
|
||||
if (errors.toString().length() > 0)
|
||||
{
|
||||
m_processMsg = errors.toString();
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
|
||||
// Counter Documents
|
||||
MInOut counter = createCounterDoc();
|
||||
if (counter != null)
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.List;
|
|||
import java.util.Properties;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
|
||||
import org.adempiere.exceptions.PeriodClosedException;
|
||||
import org.compiere.process.DocAction;
|
||||
import org.compiere.process.DocumentEngine;
|
||||
|
@ -435,6 +436,7 @@ public class MInventory extends X_M_Inventory implements DocAction
|
|||
approveIt();
|
||||
if (log.isLoggable(Level.INFO)) log.info(toString());
|
||||
|
||||
StringBuilder errors = new StringBuilder();
|
||||
MInventoryLine[] lines = getLines(false);
|
||||
for (MInventoryLine line : lines)
|
||||
{
|
||||
|
@ -442,7 +444,8 @@ public class MInventory extends X_M_Inventory implements DocAction
|
|||
continue;
|
||||
|
||||
MProduct product = line.getProduct();
|
||||
|
||||
try
|
||||
{
|
||||
BigDecimal qtyDiff = Env.ZERO;
|
||||
if (MDocType.DOCSUBTYPEINV_InternalUseInventory.equals(docSubTypeInv))
|
||||
qtyDiff = line.getQtyInternalUse().negate();
|
||||
|
@ -619,9 +622,22 @@ public class MInventory extends X_M_Inventory implements DocAction
|
|||
}
|
||||
} // Fallback
|
||||
} // stock movement
|
||||
}
|
||||
catch (NegativeInventoryDisallowedException e)
|
||||
{
|
||||
log.severe(e.getMessage());
|
||||
errors.append(Msg.getElement(getCtx(), "Line")).append(" ").append(line.getLine()).append(": ");
|
||||
errors.append(e.getMessage()).append("\n");
|
||||
}
|
||||
|
||||
} // for all lines
|
||||
|
||||
if (errors.toString().length() > 0)
|
||||
{
|
||||
m_processMsg = errors.toString();
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
|
||||
// User Validation
|
||||
String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE);
|
||||
if (valid != null)
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.List;
|
|||
import java.util.Properties;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
|
||||
import org.adempiere.exceptions.PeriodClosedException;
|
||||
import org.compiere.process.DocAction;
|
||||
import org.compiere.process.DocumentEngine;
|
||||
|
@ -416,6 +417,7 @@ public class MMovement extends X_M_Movement implements DocAction
|
|||
approveIt();
|
||||
if (log.isLoggable(Level.INFO)) log.info(toString());
|
||||
|
||||
StringBuilder errors = new StringBuilder();
|
||||
//
|
||||
MMovementLine[] lines = getLines(false);
|
||||
for (int i = 0; i < lines.length; i++)
|
||||
|
@ -425,6 +427,8 @@ public class MMovement extends X_M_Movement implements DocAction
|
|||
|
||||
//Stock Movement - Counterpart MOrder.reserveStock
|
||||
MProduct product = line.getProduct();
|
||||
try
|
||||
{
|
||||
if (product != null
|
||||
&& product.isStocked() )
|
||||
{
|
||||
|
@ -592,7 +596,21 @@ public class MMovement extends X_M_Movement implements DocAction
|
|||
}
|
||||
} // Fallback
|
||||
} // product stock
|
||||
}
|
||||
catch (NegativeInventoryDisallowedException e)
|
||||
{
|
||||
log.severe(e.getMessage());
|
||||
errors.append(Msg.getElement(getCtx(), "Line")).append(" ").append(line.getLine()).append(": ");
|
||||
errors.append(e.getMessage()).append("\n");
|
||||
}
|
||||
} // for all lines
|
||||
|
||||
if (errors.toString().length() > 0)
|
||||
{
|
||||
m_processMsg = errors.toString();
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
|
||||
// User Validation
|
||||
String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE);
|
||||
if (valid != null)
|
||||
|
|
|
@ -232,4 +232,19 @@ public class MPInstancePara extends X_AD_PInstance_Para
|
|||
}
|
||||
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
|
||||
|
|
|
@ -22,8 +22,11 @@ import java.sql.Timestamp;
|
|||
import java.util.Properties;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.adempiere.exceptions.AdempiereException;
|
||||
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
|
||||
import org.compiere.util.DB;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Msg;
|
||||
|
||||
/**
|
||||
* Project Issue Model
|
||||
|
@ -172,9 +175,57 @@ public class MProjectIssue extends X_C_ProjectIssue
|
|||
dateMPolicy = t;
|
||||
}
|
||||
|
||||
if (MStorageOnHand.add(getCtx(), loc.getM_Warehouse_ID(), getM_Locator_ID(),
|
||||
boolean ok = true;
|
||||
try
|
||||
{
|
||||
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(),
|
||||
getMovementQty().negate(),dateMPolicy, get_TrxName()))
|
||||
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()))
|
||||
{
|
||||
|
|
|
@ -1328,6 +1328,7 @@ public class MSequence extends X_AD_Sequence
|
|||
"AD_PINSTANCE",
|
||||
"AD_PINSTANCE_LOG",
|
||||
"AD_PINSTANCE_PARA",
|
||||
"AD_PREFERENCE",
|
||||
"AD_RECENTITEM",
|
||||
"AD_REPLICATION_LOG",
|
||||
"AD_SCHEDULERLOG",
|
||||
|
|
|
@ -27,11 +27,10 @@ import java.util.List;
|
|||
import java.util.Properties;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.adempiere.exceptions.AdempiereException;
|
||||
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
|
||||
import org.compiere.util.CLogger;
|
||||
import org.compiere.util.DB;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Msg;
|
||||
import org.compiere.util.Util;
|
||||
|
||||
/**
|
||||
|
@ -735,7 +734,8 @@ public class MStorageOnHand extends X_M_StorageOnHand
|
|||
if (getQtyOnHand().signum() == -1) {
|
||||
MWarehouse wh = MWarehouse.get(Env.getCtx(), getM_Warehouse_ID());
|
||||
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 ||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.Properties;
|
|||
import java.util.logging.Level;
|
||||
|
||||
import org.adempiere.exceptions.AdempiereException;
|
||||
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
|
||||
import org.compiere.model.MBPartner;
|
||||
import org.compiere.model.MBPartnerLocation;
|
||||
import org.compiere.model.MDocType;
|
||||
|
@ -847,6 +848,7 @@ public class MDDOrder extends X_DD_Order implements DocAction
|
|||
BigDecimal Volume = Env.ZERO;
|
||||
BigDecimal Weight = Env.ZERO;
|
||||
|
||||
StringBuilder errors = new StringBuilder();
|
||||
// Always check and (un) Reserve Inventory
|
||||
for (MDDOrderLine line : lines)
|
||||
{
|
||||
|
@ -873,6 +875,8 @@ public class MDDOrder extends X_DD_Order implements DocAction
|
|||
// Check Product - Stocked and Item
|
||||
MProduct product = line.getProduct();
|
||||
if (product != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (product.isStocked())
|
||||
{
|
||||
|
@ -900,9 +904,19 @@ public class MDDOrder extends X_DD_Order implements DocAction
|
|||
//
|
||||
Volume = Volume.add(product.getVolume().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
|
||||
} // reverse inventory
|
||||
|
||||
if (errors.toString().length() > 0)
|
||||
throw new AdempiereException(errors.toString());
|
||||
|
||||
setVolume(Volume);
|
||||
setWeight(Weight);
|
||||
} // reserveStock
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<cq:property key="target.os" 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\.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\.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)"/>
|
||||
|
|
|
@ -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=".">
|
||||
|
||||
|
@ -52,6 +52,8 @@
|
|||
<copy file="hazelcast-template.xml"
|
||||
tofile="hazelcast.xml" filtering="yes" overwrite="yes"/>
|
||||
|
||||
<mkdir dir="jettyhome/work"/>
|
||||
<mkdir dir="log"/>
|
||||
</target>
|
||||
|
||||
<!-- ==================================================== -->
|
||||
|
@ -110,6 +112,6 @@
|
|||
<!-- Setup (Main) -->
|
||||
<!-- ==================================================== -->
|
||||
<target name="setup" depends="setupInit, setupWin, setupNonWin"
|
||||
description="Setup Adempiere">
|
||||
description="Setup iDempiere">
|
||||
</target>
|
||||
</project>
|
|
@ -159,4 +159,5 @@
|
|||
<Arg>org.eclipse.jetty.server.Request.maxFormContentSize</Arg>
|
||||
<Arg>1048576</Arg>
|
||||
</Call>
|
||||
<Set class="org.eclipse.jetty.util.resource.Resource" name="defaultUseCaches">false</Set>
|
||||
</Configure>
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.compiere.model.MClient;
|
|||
import org.compiere.model.MCost;
|
||||
import org.compiere.model.MOrgInfo;
|
||||
import org.compiere.model.MRole;
|
||||
import org.compiere.model.MTable;
|
||||
import org.compiere.model.MUser;
|
||||
import org.compiere.util.DB;
|
||||
import org.compiere.util.Env;
|
||||
|
@ -224,7 +225,6 @@ public class AcctProcessor extends AdempiereServer
|
|||
rs = pstmt.executeQuery();
|
||||
while (!isInterrupted() && rs.next())
|
||||
{
|
||||
count[i]++;
|
||||
boolean ok = true;
|
||||
try
|
||||
{
|
||||
|
@ -238,6 +238,17 @@ public class AcctProcessor extends AdempiereServer
|
|||
}
|
||||
if (!ok)
|
||||
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)
|
||||
|
|
|
@ -207,7 +207,7 @@ public class ProcessParameterPanel extends CPanel implements VetoableChangeListe
|
|||
+ "p.AD_Reference_ID, p.AD_Process_Para_ID, "
|
||||
+ "p.FieldLength, p.IsMandatory, p.IsRange, p.ColumnName, "
|
||||
+ "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"
|
||||
+ " LEFT OUTER JOIN AD_Val_Rule vr ON (p.AD_Val_Rule_ID=vr.AD_Val_Rule_ID) "
|
||||
+ "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.FieldLength, p.IsMandatory, p.IsRange, p.ColumnName, "
|
||||
+ "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"
|
||||
+ " 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) "
|
||||
|
|
|
@ -448,7 +448,7 @@ public class AdempiereWebUI extends Window implements EventListener<Event>, IWeb
|
|||
String ua = Servlets.getUserAgent((ServletRequest) Executions.getCurrent().getNativeRequest());
|
||||
clientInfo.userAgent = ua;
|
||||
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) {
|
||||
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_desktopHeight", clientInfo.desktopHeight);
|
||||
Env.setContext(Env.getCtx(), "#clientInfo_orientation", clientInfo.orientation);
|
||||
Env.setContext(Env.getCtx(), "#clientInfo_mobile", clientInfo.tablet);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,24 +17,21 @@ package org.adempiere.webui;
|
|||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
import org.adempiere.webui.apps.AEnv;
|
||||
import org.adempiere.webui.part.AbstractUIPart;
|
||||
import org.adempiere.webui.theme.ThemeManager;
|
||||
import org.adempiere.webui.util.ZKUpdateUtil;
|
||||
import org.adempiere.webui.window.LoginWindow;
|
||||
import org.zkoss.web.servlet.Servlets;
|
||||
import org.zkoss.zhtml.Text;
|
||||
import org.zkoss.zk.ui.Component;
|
||||
import org.zkoss.zk.ui.Executions;
|
||||
import org.zkoss.zk.ui.metainfo.PageDefinition;
|
||||
import org.zkoss.zul.Borderlayout;
|
||||
import org.zkoss.zul.Div;
|
||||
import org.zkoss.zul.East;
|
||||
import org.zkoss.zul.North;
|
||||
import org.zkoss.zul.South;
|
||||
import org.zkoss.zul.West;
|
||||
import org.zkoss.zul.Div;
|
||||
import org.zkoss.zul.Window;
|
||||
|
||||
/**
|
||||
|
@ -82,15 +79,13 @@ public class WLogin extends AbstractUIPart
|
|||
browserWarningWindow.doOverlapped();
|
||||
}
|
||||
|
||||
String ua = Servlets.getUserAgent((ServletRequest) Executions.getCurrent().getNativeRequest());
|
||||
ua = ua.toLowerCase();
|
||||
boolean mobile = ua.indexOf("ipad") >= 0 || ua.indexOf("iphone") >= 0 || ua.indexOf("android") >= 0;
|
||||
|
||||
boolean mobile = Executions.getCurrent().getBrowser("mobile") !=null;
|
||||
|
||||
West west = layout.getWest();
|
||||
if (west.getFirstChild() != null && west.getFirstChild().getFirstChild() != null) {
|
||||
if (mobile) {
|
||||
west.setCollapsible(true);
|
||||
west.setSplittable(true);
|
||||
if (mobile) {
|
||||
west.setOpen(false);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -644,6 +644,8 @@ public abstract class AbstractProcessDialog extends Window implements IProcessUI
|
|||
saveReportOptionToInstance(savedParams.get(i));
|
||||
|
||||
savedParams.get(i).saveEx();
|
||||
|
||||
getProcessInfo().setAD_PInstance_ID(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -520,7 +520,7 @@ public class ProcessParameterPanel extends Panel implements
|
|||
result2 = editor2.getValue();
|
||||
|
||||
// Create Parameter
|
||||
MPInstancePara para = new MPInstancePara(Env.getCtx(),
|
||||
MPInstancePara para = MPInstancePara.getOrCreate(Env.getCtx(),
|
||||
m_processInfo.getAD_PInstance_ID(), i);
|
||||
GridField mField = (GridField) m_mFields.get(i);
|
||||
para.setParameterName(mField.getColumnName());
|
||||
|
|
|
@ -272,9 +272,11 @@ public class WPaySelect extends PaySelect
|
|||
*/
|
||||
private void loadBankInfo()
|
||||
{
|
||||
BankInfo bi = (BankInfo)fieldBankAccount.getSelectedItem().getValue();
|
||||
if (bi == null)
|
||||
if (fieldBankAccount.getItemCount() == 0)
|
||||
return;
|
||||
|
||||
BankInfo bi = (BankInfo)fieldBankAccount.getSelectedItem().getValue();
|
||||
|
||||
labelCurrency.setText(bi.Currency);
|
||||
labelBalance.setText(m_format.format(bi.Balance));
|
||||
|
||||
|
@ -301,7 +303,13 @@ public class WPaySelect extends PaySelect
|
|||
miniTable.setColorCompare(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();
|
||||
KeyNamePair bpartner = (KeyNamePair) fieldBPartner.getSelectedItem().getValue();
|
||||
|
|
|
@ -224,6 +224,13 @@ public class DefaultDesktop extends TabbedDesktop implements MenuListener, Seria
|
|||
boolean menuCollapsed= pref.isPropertyBool(UserPreference.P_MENU_COLLAPSED);
|
||||
w.setOpen(!menuCollapsed);
|
||||
|
||||
boolean mobile = Executions.getCurrent().getBrowser("mobile") !=null;
|
||||
w.setCollapsible(true);
|
||||
|
||||
if (mobile) {
|
||||
w.setOpen(false);
|
||||
}
|
||||
|
||||
East e = layout.getEast();
|
||||
e.addEventListener(Events.ON_OPEN, new EventListener<Event>() {
|
||||
@Override
|
||||
|
@ -293,6 +300,11 @@ public class DefaultDesktop extends TabbedDesktop implements MenuListener, Seria
|
|||
|
||||
helpController.render(e, this);
|
||||
|
||||
if (mobile) {
|
||||
e.setVisible(false);
|
||||
e.setOpen(false);
|
||||
}
|
||||
|
||||
Center windowArea = layout.getCenter();
|
||||
|
||||
windowContainer.createPart(windowArea);
|
||||
|
|
|
@ -76,6 +76,7 @@ import org.adempiere.webui.util.ZKUpdateUtil;
|
|||
import org.compiere.model.GridField;
|
||||
import org.compiere.model.GridFieldVO;
|
||||
import org.compiere.model.GridTab;
|
||||
import org.compiere.model.Lookup;
|
||||
import org.compiere.model.MColumn;
|
||||
import org.compiere.model.MLookup;
|
||||
import org.compiere.model.MLookupFactory;
|
||||
|
@ -92,9 +93,11 @@ import org.compiere.util.DisplayType;
|
|||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Msg;
|
||||
import org.compiere.util.SecureEngine;
|
||||
import org.compiere.util.Util;
|
||||
import org.compiere.util.ValueNamePair;
|
||||
import org.zkoss.zk.au.out.AuFocus;
|
||||
import org.zkoss.zk.ui.Component;
|
||||
import org.zkoss.zk.ui.Components;
|
||||
import org.zkoss.zk.ui.HtmlBasedComponent;
|
||||
import org.zkoss.zk.ui.event.Event;
|
||||
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
|
||||
{
|
||||
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
|
||||
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 Properties m_findCtx;
|
||||
private Properties m_simpleCtx;
|
||||
private Properties m_advanceCtx;
|
||||
|
||||
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_isCancel = true;
|
||||
//
|
||||
m_findCtx = new Properties(Env.getCtx());
|
||||
m_simpleCtx = new Properties(Env.getCtx());
|
||||
m_advanceCtx = new Properties(Env.getCtx());
|
||||
|
||||
this.setBorder("normal");
|
||||
this.setShadow(false);
|
||||
|
@ -634,7 +643,7 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
|
|||
if (mField.getVO().displayType == DisplayType.YesNo) {
|
||||
// Make Yes-No searchable as list
|
||||
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.displayType = DisplayType.List;
|
||||
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,
|
||||
Env.getLanguage(ynvo.ctx), ynvo.ColumnName, ynvo.AD_Reference_Value_ID,
|
||||
ynvo.IsParent, ynvo.ValidationCode);
|
||||
ynvo.lookupInfo.tabNo = TABNO;
|
||||
|
||||
GridField ynfield = new GridField(ynvo);
|
||||
|
||||
|
@ -653,13 +663,14 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
|
|||
GridFieldVO vo = mField.getVO();
|
||||
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.displayType = DisplayType.List;
|
||||
|
||||
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,
|
||||
postedvo.IsParent, postedvo.ValidationCode);
|
||||
postedvo.lookupInfo.tabNo = TABNO;
|
||||
|
||||
GridField postedfield = new GridField(postedvo);
|
||||
|
||||
|
@ -669,7 +680,15 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
|
|||
}
|
||||
} else {
|
||||
// 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);
|
||||
m_findFields[i] = findField;
|
||||
mField = findField;
|
||||
|
@ -1058,6 +1077,7 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
|
|||
editor.setMandatory(false);
|
||||
editor.setReadWrite(true);
|
||||
editor.dynamicDisplay();
|
||||
editor.addValueChangeListener(this);
|
||||
Label label = editor.getLabel();
|
||||
Component fieldEditor = editor.getComponent();
|
||||
|
||||
|
@ -1075,6 +1095,7 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
|
|||
editorTo.setMandatory(false);
|
||||
editorTo.setReadWrite(true);
|
||||
editorTo.dynamicDisplay();
|
||||
editorTo.addValueChangeListener(this);
|
||||
//
|
||||
if (displayLength > 0) // set it back
|
||||
mField.setDisplayLength(displayLength);
|
||||
|
@ -1916,7 +1937,7 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
|
|||
GridField field = getTargetMField(columnName);
|
||||
if(field == null) return new Label("");
|
||||
|
||||
GridField findField = (GridField) field.clone(m_findCtx);
|
||||
GridField findField = (GridField) field.clone(m_advanceCtx);
|
||||
findField.setGridTab(null);
|
||||
WEditor editor = null;
|
||||
if (findField.isKey()
|
||||
|
@ -1928,6 +1949,7 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
|
|||
{
|
||||
if (findField.getAD_Reference_Value_ID() > 0) {
|
||||
MLookupInfo info = MLookupFactory.getLookup_List(Env.getLanguage(Env.getCtx()), findField.getAD_Reference_Value_ID());
|
||||
info.tabNo = TABNO;
|
||||
MLookup mLookup = new MLookup(info, 0);
|
||||
editor = new WTableDirEditor(columnName, false,false, true, mLookup);
|
||||
findField.addPropertyChangeListener(editor);
|
||||
|
@ -1946,6 +1968,12 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
|
|||
if (DisplayType.isLookup(findField.getDisplayType()) )
|
||||
{
|
||||
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);
|
||||
findField.addPropertyChangeListener(editor);
|
||||
}
|
||||
|
@ -1970,6 +1998,10 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
|
|||
((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();
|
||||
|
||||
} // getTableCellEditorComponent
|
||||
|
@ -2358,17 +2390,89 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
|
|||
{
|
||||
WEditor editor = (WEditor)evt.getSource();
|
||||
// Editor component
|
||||
ListCell listcell = null;
|
||||
Properties ctx = null;
|
||||
if (winMain.getComponent().getSelectedIndex() == 1)
|
||||
{
|
||||
Component component = editor.getComponent();
|
||||
ListCell listcell = (ListCell)component.getParent();
|
||||
listcell = (ListCell)component.getParent();
|
||||
listcell.setAttribute("value", evt.getNewValue());
|
||||
if (evt.getNewValue() == null)
|
||||
Env.setContext(m_findCtx, m_targetWindowNo, editor.getColumnName(), "");
|
||||
else if (evt.getNewValue() instanceof Boolean)
|
||||
Env.setContext(m_findCtx, m_targetWindowNo, editor.getColumnName(), (Boolean)evt.getNewValue());
|
||||
else if (evt.getNewValue() instanceof Timestamp)
|
||||
Env.setContext(m_findCtx, m_targetWindowNo, editor.getColumnName(), (Timestamp)evt.getNewValue());
|
||||
ctx = m_advanceCtx;
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2410,7 +2514,7 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
|
|||
|
||||
private boolean isSearchLike(GridField field)
|
||||
{
|
||||
return DisplayType.isText(field.getDisplayType())
|
||||
return DisplayType.isText(field.getDisplayType()) && !field.isVirtualColumn()
|
||||
&& (field.isSelectionColumn() || MColumn.isSuggestSelectionColumn(field.getColumnName(), true));
|
||||
}
|
||||
|
||||
|
|
|
@ -231,3 +231,25 @@
|
|||
height: 16px;
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,17 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<zk>
|
||||
<div sclass="desktop-header" use="org.adempiere.webui.panel.HeaderPanel" id="header">
|
||||
<borderlayout sclass="desktop-header">
|
||||
<west width="50%" sclass="desktop-header-left">
|
||||
<hbox height="100%" pack="center" align="left">
|
||||
<hlayout vflex="1" sclass="desktop-header">
|
||||
<hbox height="100%" pack="center" align="left" sclass="desktop-header-left">
|
||||
<image id="logo"/>
|
||||
<div id="menuLookup"/>
|
||||
<button id="menuButton" sclass="btn-small"/>
|
||||
</hbox>
|
||||
</west>
|
||||
<center sclass="desktop-header-right">
|
||||
<vbox apply="org.adempiere.webui.panel.UserPanel" align="right"
|
||||
hflex="1" vflex="1"
|
||||
sclass="desktop-user-panel">
|
||||
<vbox align="right">
|
||||
<label use="org.adempiere.webui.component.Label" id="loginUserAndRole"
|
||||
|
@ -32,7 +28,6 @@
|
|||
</hbox>
|
||||
</vbox>
|
||||
</vbox>
|
||||
</center>
|
||||
</borderlayout>
|
||||
</hlayout>
|
||||
</div>
|
||||
</zk>
|
Loading…
Reference in New Issue