diff --git a/org.adempiere.base/src/org/compiere/model/MPaySelectionCheck.java b/org.adempiere.base/src/org/compiere/model/MPaySelectionCheck.java index 82466c7da7..202b63cd00 100644 --- a/org.adempiere.base/src/org/compiere/model/MPaySelectionCheck.java +++ b/org.adempiere.base/src/org/compiere/model/MPaySelectionCheck.java @@ -676,7 +676,7 @@ public class MPaySelectionCheck extends X_C_PaySelectionCheck StringBuilder sb = new StringBuilder("MPaymentCheck["); sb.append(get_ID()).append("-").append(getDocumentNo()) .append("-").append(getPayAmt()) - .append(",PaymetRule=").append(getPaymentRule()) + .append(",PaymentRule=").append(getPaymentRule()) .append(",Qty=").append(getQty()) .append("]"); return sb.toString(); diff --git a/org.adempiere.base/src/org/compiere/model/PO.java b/org.adempiere.base/src/org/compiere/model/PO.java index 581f33eb1f..690093ad0d 100644 --- a/org.adempiere.base/src/org/compiere/model/PO.java +++ b/org.adempiere.base/src/org/compiere/model/PO.java @@ -374,7 +374,6 @@ public abstract class PO public int hashCode() { - assert false : "hashCode not designed"; return 42; // any arbitrary constant will do } diff --git a/org.adempiere.base/src/org/compiere/wf/MWorkflow.java b/org.adempiere.base/src/org/compiere/wf/MWorkflow.java index 5a61993c23..3bf578eccb 100644 --- a/org.adempiere.base/src/org/compiere/wf/MWorkflow.java +++ b/org.adempiere.base/src/org/compiere/wf/MWorkflow.java @@ -1088,7 +1088,7 @@ public class MWorkflow extends X_AD_Workflow implements ImmutablePOSupport ProcessInfo processInfo = new ProcessInfo (((DocAction)po).getDocumentInfo(),column.getAD_Process_ID(),po.get_Table_ID(),po.get_ID()); processInfo.setTransactionName(po.get_TrxName()); processInfo.setPO(po); - ServerProcessCtl.process(processInfo, Trx.get(processInfo.getTransactionName(), false)); + ServerProcessCtl.process(processInfo, !Util.isEmpty(processInfo.getTransactionName(), true) ? Trx.get(processInfo.getTransactionName(), false) : null); return processInfo; } } // MWorkflow_ID diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/form/WPayPrint.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/form/WPayPrint.java index fcd0f33267..f80b40acdc 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/form/WPayPrint.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/form/WPayPrint.java @@ -22,6 +22,7 @@ import java.io.File; import java.io.FileInputStream; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Level; import org.adempiere.util.Callback; @@ -57,12 +58,6 @@ import org.compiere.apps.form.PayPrint; import org.compiere.model.MLookup; import org.compiere.model.MLookupFactory; import org.compiere.model.MPaySelectionCheck; -import org.compiere.model.MPaymentBatch; -import org.compiere.print.MPrintFormat; -import org.compiere.print.ReportEngine; -import org.compiere.process.ProcessInfo; -import org.compiere.process.ServerProcessCtl; -import org.compiere.util.DB; import org.compiere.util.DisplayType; import org.compiere.util.Env; import org.compiere.util.Msg; @@ -74,8 +69,6 @@ import org.zkoss.zul.Center; import org.zkoss.zul.Filedownload; import org.zkoss.zul.South; -import com.lowagie.text.pdf.PdfReader; - /** * Payment Print and Export * @@ -121,7 +114,7 @@ public class WPayPrint extends PayPrint implements IFormController, EventListene } } // WPayPrint - // Static Variables + // Instance Variables protected Panel centerPanel = new Panel(); protected ConfirmPanel southPanel = new ConfirmPanel(true, false, false, false, false, false, false); protected Grid centerLayout = GridFactory.newGridLayout(); @@ -277,9 +270,9 @@ public class WPayPrint extends PayPrint implements IFormController, EventListene * Action Listener * @param e event */ + @Override public void onEvent(Event e) { - // log.config( "VPayPrint.actionPerformed" + e.toString()); if (e.getTarget() == bCancel) dispose(); else if (m_C_PaySelection_ID <= 0) @@ -293,18 +286,17 @@ public class WPayPrint extends PayPrint implements IFormController, EventListene cmd_EFT(); else if (e.getTarget() == bPrint) confirm_cmd_print(); - } // actionPerformed + } /** - * PaySelect changed - load Bank + * load pay selection details */ protected void loadPaySelectInfo() { - log.info( "VPayPrint.loadPaySelectInfo"); if (m_C_PaySelection_ID <= 0) return; - // load Banks from PaySelectLine + // load details from PaySelectLine loadPaySelectInfo(m_C_PaySelection_ID); fBank.setText(bank); @@ -319,7 +311,6 @@ public class WPayPrint extends PayPrint implements IFormController, EventListene */ protected void loadPaymentRule() { - log.info(""); if (m_C_BankAccount_ID == -1) return; @@ -370,7 +361,9 @@ public class WPayPrint extends PayPrint implements IFormController, EventListene getPluginFeatures(); } // loadPaymentRuleInfo - + /** + * load payment export class + */ protected void getPluginFeatures() { if (m_C_PaySelection_ID!=0) @@ -473,7 +466,6 @@ public class WPayPrint extends PayPrint implements IFormController, EventListene protected void cmd_EFT() { String PaymentRule = fPaymentRule.getSelectedItem().toValueNamePair().getValue(); - log.info(PaymentRule); if (!getChecks(PaymentRule)) return; dispose(); @@ -504,7 +496,6 @@ public class WPayPrint extends PayPrint implements IFormController, EventListene protected void cmd_print() { String PaymentRule = fPaymentRule.getSelectedItem().toValueNamePair().getValue(); - log.info(PaymentRule); if (!getChecks(PaymentRule)) return; @@ -513,53 +504,15 @@ public class WPayPrint extends PayPrint implements IFormController, EventListene if (log.isLoggable(Level.CONFIG)) log.config("DocumentNo=" + startDocumentNo); // for all checks - List pdfList = new ArrayList(); - int lastDocumentNo = startDocumentNo; - for (int i = 0; i < m_checks.length; i++) + List pdfList = null; + try { - MPaySelectionCheck check = m_checks[i]; - - // Set new Check Document No - check.setDocumentNo(String.valueOf(lastDocumentNo)); - check.saveEx(); - - // Update BankAccountDoc - MPaySelectionCheck.confirmPrint(m_checks[i], m_batch); - - // ReportCtrl will check BankAccountDoc for PrintFormat - ReportEngine re = ReportEngine.get(Env.getCtx(), ReportEngine.CHECK, check.get_ID(), m_WindowNo); - try - { - MPrintFormat format = re.getPrintFormat(); - File pdfFile = null; - if (format.getJasperProcess_ID() > 0) - { - ProcessInfo pi = new ProcessInfo("", format.getJasperProcess_ID()); - pi.setRecord_ID(check.get_ID()); - pi.setIsBatch(true); - - ServerProcessCtl.process(pi, null); - pdfFile = pi.getPDFReport(); - } - else - { - pdfFile = File.createTempFile("WPayPrint", null); - re.getPDF(pdfFile); - } - - if (pdfFile != null) - { - // increase the check document no by the number of pages of the generated pdf file - PdfReader document = new PdfReader(pdfFile.getAbsolutePath()); - lastDocumentNo += document.getNumberOfPages(); - pdfList.add(pdfFile); - } - } - catch (Exception e) - { - log.log(Level.SEVERE, e.getLocalizedMessage(), e); - return; - } + pdfList = createCheckDocuments(startDocumentNo, PaymentRule); + } + catch (Exception e) + { + log.log(Level.SEVERE, e.getLocalizedMessage(), e); + return; } SimplePDFViewer chequeViewer = null; @@ -578,16 +531,6 @@ public class WPayPrint extends PayPrint implements IFormController, EventListene } final SimplePDFViewer chequeViewerRef = chequeViewer; - // Update Check Next Document No - if (startDocumentNo != lastDocumentNo) - { - StringBuilder sb = new StringBuilder(); - sb.append("UPDATE C_BankAccountDoc SET CurrentNext=").append(lastDocumentNo) - .append(" WHERE C_BankAccount_ID=").append(m_C_BankAccount_ID) - .append(" AND PaymentRule='").append(PaymentRule).append("'"); - DB.executeUpdate(sb.toString(), null); - } - Dialog.ask(m_WindowNo, "VPayPrintPrintRemittance", new Callback() { @Override @@ -596,35 +539,7 @@ public class WPayPrint extends PayPrint implements IFormController, EventListene SimplePDFViewer remitViewer = null; if (result) { - List pdfList = new ArrayList(); - for (int i = 0; i < m_checks.length; i++) - { - MPaySelectionCheck check = m_checks[i]; - ReportEngine re = ReportEngine.get(Env.getCtx(), ReportEngine.REMITTANCE, check.get_ID(), m_WindowNo); - try - { - MPrintFormat format = re.getPrintFormat(); - if (format.getJasperProcess_ID() > 0) - { - ProcessInfo pi = new ProcessInfo("", format.getJasperProcess_ID()); - pi.setRecord_ID(check.get_ID()); - pi.setIsBatch(true); - - ServerProcessCtl.process(pi, null); - pdfList.add(pi.getPDFReport()); - } - else - { - File file = File.createTempFile("WPayPrint", null); - re.getPDF(file); - pdfList.add(file); - } - } - catch (Exception e) - { - log.log(Level.SEVERE, e.getLocalizedMessage(), e); - } - } + List pdfList = createRemittanceDocuments(); try { @@ -660,31 +575,18 @@ public class WPayPrint extends PayPrint implements IFormController, EventListene */ protected boolean getChecks(String PaymentRule) { - // do we have values - if (m_C_PaySelection_ID <= 0 || m_C_BankAccount_ID == -1 - || fPaymentRule.getSelectedIndex() == -1 || fDocumentNo.getValue() == null) - { - Dialog.error(m_WindowNo, "VPayPrintNoRecords", - "(" + Msg.translate(Env.getCtx(), "C_PaySelectionLine_ID") + "=0)"); - return false; - } - - if (log.isLoggable(Level.CONFIG)) log.config("C_PaySelection_ID=" + m_C_PaySelection_ID + ", PaymentRule=" + PaymentRule); + AtomicReference error = new AtomicReference<>(); - // get payment selection checks without check no assignment - m_checks = MPaySelectionCheck.get(m_C_PaySelection_ID, PaymentRule, null); - - // - if (m_checks == null || m_checks.length == 0) + boolean ok = getChecks(PaymentRule, fDocumentNo.getValue(), error, null); + if (!ok) { - Dialog.error(m_WindowNo, "VPayPrintNoRecords", - "(" + Msg.translate(Env.getCtx(), "C_PaySelectionLine_ID") + " #0"); - return false; + if (error.get() != null) + Dialog.error(m_WindowNo, error.get().getValue(), error.get().getName()); } - m_batch = MPaymentBatch.getForPaySelection (Env.getCtx(), m_C_PaySelection_ID, null); - return true; + return ok; } // getChecks + @Override public ADForm getForm() { return form; } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/form/WPaySelect.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/form/WPaySelect.java index 6903d7664d..b0a5a16aa7 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/form/WPaySelect.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/form/WPaySelect.java @@ -21,13 +21,11 @@ package org.adempiere.webui.apps.form; import static org.compiere.model.SystemIDs.FORM_PAYMENT_PRINT_EXPORT; import static org.compiere.model.SystemIDs.PROCESS_C_PAYSELECTION_CREATEPAYMENT; -import java.io.File; import java.sql.Timestamp; import java.util.ArrayList; import java.util.logging.Level; import org.adempiere.util.Callback; -import org.adempiere.util.IProcessUI; import org.adempiere.webui.ClientInfo; import org.adempiere.webui.LayoutUtils; import org.adempiere.webui.apps.AEnv; @@ -69,7 +67,6 @@ import org.compiere.util.KeyNamePair; import org.compiere.util.Msg; import org.compiere.util.ValueNamePair; import org.zkoss.zk.ui.Component; -import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.SuspendNotAllowedException; import org.zkoss.zk.ui.WrongValueException; import org.zkoss.zk.ui.event.Event; @@ -96,12 +93,9 @@ import org.zkoss.zul.Space; */ @org.idempiere.ui.zk.annotation.Form(name = "org.compiere.apps.form.VPaySelect") public class WPaySelect extends PaySelect - implements IFormController, EventListener, WTableModelListener, IProcessUI, ValueChangeListener + implements IFormController, EventListener, WTableModelListener, ValueChangeListener { - /** @todo withholding */ - protected CustomForm form = new CustomForm(); - // private Panel mainPanel = new Panel(); private Borderlayout mainLayout = new Borderlayout(); @@ -130,7 +124,6 @@ public class WPaySelect extends PaySelect private Listbox fieldDtype = ListboxFactory.newDropdownListbox(); private Panel southPanel; private Checkbox chkOnePaymentPerInv = new Checkbox(); - @SuppressWarnings("unused") private ProcessInfo m_pi; private boolean m_isLock; private Hlayout statusBar = new Hlayout(); @@ -155,10 +148,10 @@ public class WPaySelect extends PaySelect { log.log(Level.SEVERE, "", e); } - } // init + } /** - * Static Init + * Init UI component and layout * @throws Exception */ private void zkInit() throws Exception @@ -371,7 +364,7 @@ public class WPaySelect extends PaySelect } // loadBankInfo /** - * Query and create TableInfo + * Load open documents */ protected void loadTableInfo() { @@ -424,6 +417,7 @@ public class WPaySelect extends PaySelect * ActionListener * @param e event */ + @Override public void onEvent (Event e) { // Update Bank Info @@ -497,7 +491,7 @@ public class WPaySelect extends PaySelect { m_isOnePaymentPerInvoice = chkOnePaymentPerInv.isChecked(); } - } // actionPerformed + } @Override public void valueChange(ValueChangeEvent e) { @@ -513,7 +507,7 @@ public class WPaySelect extends PaySelect { if (e.getColumn() == 0) calculateSelection(); - } // valueChanged + } /** * Calculate selected rows. @@ -572,7 +566,6 @@ public class WPaySelect extends PaySelect AD_Proces_ID, X_C_PaySelection.Table_ID, m_ps.getC_PaySelection_ID(), false); if (dialog.isValid()) { try { - //dialog.setWidth("500px"); dialog.setVisible(true); dialog.setPage(form.getPage()); dialog.doHighlighted(); @@ -634,54 +627,24 @@ public class WPaySelect extends PaySelect this.dispose(); } - public void executeASync(ProcessInfo pi) { - } - + /** + * + * @return true if UI is lock + */ public boolean isUILocked() { return m_isLock; } + @Override public ADForm getForm() { return form; } - - @Override - public void statusUpdate(String message) { - } - - @Override - public void ask(final String message, final Callback callback) { - Executions.schedule(form.getDesktop(), new EventListener() { - @Override - public void onEvent(Event event) throws Exception { - Dialog.ask(m_WindowNo, message, callback); - } - }, new Event("onAsk")); - } - - @Override - public void download(File file) { - // TODO Auto-generated method stub - - } - - @Override - public void askForInput(final String message, final Callback callback) { - Executions.schedule(form.getDesktop(), new EventListener() { - @Override - public void onEvent(Event event) throws Exception { - Dialog.askForInput(m_WindowNo, message, callback); - } - }, new Event("onAskForInput")); - } - @Override - public void askForSecretInput(final String message, final Callback callback) { - Executions.schedule(form.getDesktop(), new EventListener() { - @Override - public void onEvent(Event event) throws Exception { - Dialog.askForSecretInput(m_WindowNo, message, callback); - } - }, new Event("onAskForInput")); + /** + * + * @return {@link ProcessInfo} + */ + public ProcessInfo getProcessInfo() { + return m_pi; } -} // VPaySelect +} diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/WListbox.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/WListbox.java index f387a77d6b..4578fc57ba 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/WListbox.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/component/WListbox.java @@ -459,7 +459,7 @@ public class WListbox extends Listbox implements IMiniTable, TableValueChangeLis MRole.SQL_FULLYQUALIFIED, MRole.SQL_RO); - logger.finest(finalSQL); + if (logger.isLoggable(Level.FINEST)) logger.finest(finalSQL); return finalSQL; } diff --git a/org.adempiere.ui/META-INF/MANIFEST.MF b/org.adempiere.ui/META-INF/MANIFEST.MF index cddef6ee4c..8d0c54da5c 100644 --- a/org.adempiere.ui/META-INF/MANIFEST.MF +++ b/org.adempiere.ui/META-INF/MANIFEST.MF @@ -33,3 +33,4 @@ Bundle-ClassPath: ., lib/org-openide-util-lookup.jar Automatic-Module-Name: org.adempiere.ui Bundle-Vendor: iDempiere Community +Import-Package: com.lowagie.text.pdf diff --git a/org.adempiere.ui/src/org/compiere/apps/form/PayPrint.java b/org.adempiere.ui/src/org/compiere/apps/form/PayPrint.java index 078c6b3afa..58aebdcee0 100644 --- a/org.adempiere.ui/src/org/compiere/apps/form/PayPrint.java +++ b/org.adempiere.ui/src/org/compiere/apps/form/PayPrint.java @@ -20,11 +20,14 @@ package org.compiere.apps.form; import static org.compiere.model.SystemIDs.REFERENCE_PAYMENTRULE; +import java.io.File; import java.math.BigDecimal; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; import java.util.logging.Level; import org.adempiere.base.Core; @@ -32,38 +35,47 @@ import org.compiere.model.MLookupFactory; import org.compiere.model.MLookupInfo; import org.compiere.model.MPaySelectionCheck; import org.compiere.model.MPaymentBatch; +import org.compiere.print.MPrintFormat; +import org.compiere.print.ReportEngine; +import org.compiere.process.ProcessInfo; +import org.compiere.process.ServerProcessCtl; import org.compiere.util.CLogger; import org.compiere.util.DB; import org.compiere.util.Env; import org.compiere.util.Language; +import org.compiere.util.Msg; import org.compiere.util.PaymentExport; +import org.compiere.util.Util; import org.compiere.util.ValueNamePair; +import com.lowagie.text.pdf.PdfReader; + public class PayPrint { /** Window No */ - public int m_WindowNo = 0; + protected int m_WindowNo = 0; /** Used Bank Account */ - public int m_C_BankAccount_ID = -1; + protected int m_C_BankAccount_ID = -1; /** Export Class for Bank Account */ - public String m_PaymentExportClass = null; + protected String m_PaymentExportClass = null; /** Payment Selection */ - public int m_C_PaySelection_ID = 0; + protected int m_C_PaySelection_ID = 0; /** Payment Information */ - public MPaySelectionCheck[] m_checks = null; + protected MPaySelectionCheck[] m_checks = null; /** Payment Batch */ - public MPaymentBatch m_batch = null; + protected MPaymentBatch m_batch = null; /** Logger */ - public static final CLogger log = CLogger.getCLogger(PayPrint.class); + protected static final CLogger log = CLogger.getCLogger(PayPrint.class); - public String bank; - public String currency; - public BigDecimal balance; + protected String bank; + protected String currency; + protected BigDecimal balance; protected PaymentExport m_PaymentExport; /** - * PaySelect changed - load Bank + * load pay selection details (bank info, balance and payment export class) + * @param C_PaySelection_ID */ public void loadPaySelectInfo(int C_PaySelection_ID) { @@ -114,7 +126,9 @@ public class PayPrint { } // loadPaySelectInfo /** - * Bank changed - load PaymentRule + * load payment rules that's applicable to pay selection + * @param C_PaySelection_ID + * @return list of applicable payment rules */ public ArrayList loadPaymentRule(int C_PaySelection_ID) { @@ -159,14 +173,17 @@ public class PayPrint { return data; } // loadPaymentRule - public String noPayments; - public Integer documentNo; - public Double sumPayments; - public Integer printFormatId; + protected String noPayments; + protected Integer documentNo; + protected Double sumPayments; + protected Integer printFormatId; /** * PaymentRule changed - load DocumentNo, NoPayments, * enable/disable EFT, Print + * @param C_PaySelection_ID + * @param PaymentRule + * @return error message (if any) */ public String loadPaymentRuleInfo(int C_PaySelection_ID, String PaymentRule) { @@ -241,6 +258,11 @@ public class PayPrint { return msg; } // loadPaymentRuleInfo + /** + * + * @param err error message buffer + * @return 0 if loaded fine, -1 if failed to load + */ protected int loadPaymentExportClass (StringBuffer err) { m_PaymentExport = null ; @@ -278,4 +300,136 @@ public class PayPrint { } return 0 ; } // loadPaymentExportClass + + /** + * Create PDF documents from pay selection check records + * @param startDocumentNo + * @param paymentRule + * @return list of PDF documents + * @throws Exception + */ + protected List createCheckDocuments(int startDocumentNo, String paymentRule) throws Exception + { + // for all checks + List pdfList = new ArrayList(); + int lastDocumentNo = startDocumentNo; + for (int i = 0; i < m_checks.length; i++) + { + MPaySelectionCheck check = m_checks[i]; + + // Set new Check Document No + check.setDocumentNo(String.valueOf(lastDocumentNo)); + check.saveEx(); + + // Update BankAccountDoc + MPaySelectionCheck.confirmPrint(m_checks[i], m_batch); + + // ReportCtrl will check BankAccountDoc for PrintFormat + ReportEngine re = ReportEngine.get(Env.getCtx(), ReportEngine.CHECK, check.get_ID(), m_WindowNo); + MPrintFormat format = re.getPrintFormat(); + File pdfFile = null; + if (format.getJasperProcess_ID() > 0) + { + ProcessInfo pi = new ProcessInfo("", format.getJasperProcess_ID()); + pi.setRecord_ID(check.get_ID()); + pi.setIsBatch(true); + + ServerProcessCtl.process(pi, null); + pdfFile = pi.getPDFReport(); + } + else + { + pdfFile = File.createTempFile("WPayPrint", null); + re.getPDF(pdfFile); + } + + if (pdfFile != null) + { + // increase the check document no by the number of pages of the generated pdf file + PdfReader document = new PdfReader(pdfFile.getAbsolutePath()); + lastDocumentNo += document.getNumberOfPages(); + pdfList.add(pdfFile); + } + } + + // Update Check Next Document No + if (startDocumentNo != lastDocumentNo) + { + StringBuilder sb = new StringBuilder(); + sb.append("UPDATE C_BankAccountDoc SET CurrentNext=").append(lastDocumentNo) + .append(" WHERE C_BankAccount_ID=").append(m_C_BankAccount_ID) + .append(" AND PaymentRule='").append(paymentRule).append("'"); + DB.executeUpdate(sb.toString(), null); + } + + return pdfList; + } + + /** + * Create Remittance Documents (PDF) from pay selection check records + * @return list of Remittance documents + */ + protected List createRemittanceDocuments() + { + + List pdfList = new ArrayList(); + for (int i = 0; i < m_checks.length; i++) + { + MPaySelectionCheck check = m_checks[i]; + ReportEngine re = ReportEngine.get(Env.getCtx(), ReportEngine.REMITTANCE, check.get_ID(), m_WindowNo); + try + { + MPrintFormat format = re.getPrintFormat(); + if (format.getJasperProcess_ID() > 0) + { + ProcessInfo pi = new ProcessInfo("", format.getJasperProcess_ID()); + pi.setRecord_ID(check.get_ID()); + pi.setIsBatch(true); + + ServerProcessCtl.process(pi, null); + pdfList.add(pi.getPDFReport()); + } + else + { + File file = File.createTempFile("WPayPrint", null); + re.getPDF(file); + pdfList.add(file); + } + } + catch (Exception e) + { + log.log(Level.SEVERE, e.getLocalizedMessage(), e); + } + } + return pdfList; + } + /************************************************************************** + * Get Checks + * @param PaymentRule Payment Rule + * @return true if payments were created + */ + protected boolean getChecks(String PaymentRule, BigDecimal startDocumentNo, AtomicReference error, String trxName) + { + // do we have values + if (m_C_PaySelection_ID <= 0 || m_C_BankAccount_ID == -1 + || Util.isEmpty(PaymentRule, true) || startDocumentNo == null) + { + error.set(new ValueNamePair("VPayPrintNoRecords", "(" + Msg.translate(Env.getCtx(), "C_PaySelectionLine_ID") + " #0")); + return false; + } + + if (log.isLoggable(Level.CONFIG)) log.config("C_PaySelection_ID=" + m_C_PaySelection_ID + ", PaymentRule=" + PaymentRule); + + // get payment selection checks without check no assignment + m_checks = MPaySelectionCheck.get(m_C_PaySelection_ID, PaymentRule, trxName); + + // + if (m_checks == null || m_checks.length == 0) + { + error.set(new ValueNamePair("VPayPrintNoRecords", "(" + Msg.translate(Env.getCtx(), "C_PaySelectionLine_ID") + " #0")); + return false; + } + m_batch = MPaymentBatch.getForPaySelection (Env.getCtx(), m_C_PaySelection_ID, null); + return true; + } // getChecks } diff --git a/org.adempiere.ui/src/org/compiere/apps/form/PaySelect.java b/org.adempiere.ui/src/org/compiere/apps/form/PaySelect.java index 11796184a4..f5ec5aebd8 100644 --- a/org.adempiere.ui/src/org/compiere/apps/form/PaySelect.java +++ b/org.adempiere.ui/src/org/compiere/apps/form/PaySelect.java @@ -49,30 +49,32 @@ import org.compiere.util.ValueNamePair; public class PaySelect { - /** @todo withholding */ - /** Window No */ - public int m_WindowNo = 0; + protected int m_WindowNo = 0; /** Format */ - public DecimalFormat m_format = DisplayType.getNumberFormat(DisplayType.Amount); + protected DecimalFormat m_format = DisplayType.getNumberFormat(DisplayType.Amount); /** Bank Balance */ private BigDecimal m_bankBalance = Env.ZERO; /** SQL for Query */ private String m_sql; /** Number of selected rows */ - public int m_noSelected = 0; + protected int m_noSelected = 0; /** Client ID */ private int m_AD_Client_ID = 0; /**/ - public boolean m_isLocked = false; + protected boolean m_isLocked = false; /** Payment Selection */ - public MPaySelection m_ps = null; + protected MPaySelection m_ps = null; /** one-To-one payment per invoice */ - public boolean m_isOnePaymentPerInvoice = false; + protected boolean m_isOnePaymentPerInvoice = false; /** Logger */ - public static final CLogger log = CLogger.getCLogger(PaySelect.class); + protected static final CLogger log = CLogger.getCLogger(PaySelect.class); + /** + * Get list of active bank account with active C_BankAccountDoc records + * @return list of {@link BankInfo} + */ public ArrayList getBankAccountData() { ArrayList data = new ArrayList(); @@ -119,6 +121,10 @@ public class PaySelect return data; } + /** + * Get list of business partners with open vendor invoice + * @return list of business partners + */ public ArrayList getBPartnerData() { ArrayList data = new ArrayList(); @@ -161,6 +167,10 @@ public class PaySelect return data; } + /** + * Get document types for invoice and credit memo + * @return list of document types + */ public ArrayList getDocTypeData() { ArrayList data = new ArrayList(); @@ -200,6 +210,10 @@ public class PaySelect return data; } + /** + * Setup {@link ColumnInfo}, From and Where clause + * @param miniTable + */ public void prepareTable(IMiniTable miniTable) { Properties ctx = Env.getCtx(); @@ -253,10 +267,12 @@ public class PaySelect + " AND i.DocStatus IN ('CO','CL')" + " AND i.AD_Client_ID=?", // additional where & order in loadTableInfo() true, "i"); - } // dynInit + } // prepareTable /** - * Load Bank Info - Load Info from Bank Account and valid Documents (PaymentRule) + * Get payment rules that's applicable to bank account + * @param bi + * @return list of applicable payment rules */ public ArrayList getPaymentRuleData(BankInfo bi) { @@ -301,12 +317,19 @@ public class PaySelect } /** - * Query and create TableInfo + * Load open documents into miniTable + * @param bi + * @param payDate + * @param paymentRule + * @param onlyDue + * @param onlyPositiveBalance + * @param bpartner + * @param docType + * @param miniTable */ public void loadTableInfo(BankInfo bi, Timestamp payDate, ValueNamePair paymentRule, boolean onlyDue, boolean onlyPositiveBalance, KeyNamePair bpartner, KeyNamePair docType, IMiniTable miniTable) { - log.config(""); // not yet initialized if (m_sql == null) return; @@ -414,6 +437,8 @@ public class PaySelect /** * Calculate selected rows. * - add up selected rows + * @param miniTable + * @return info message */ public String calculateSelection(IMiniTable miniTable) { @@ -441,16 +466,17 @@ public class PaySelect info.append(Msg.getMsg(Env.getCtx(), "Remaining")).append(" ").append(m_format.format(remaining)); return info.toString(); } // calculateSelection - - public Trx trx = null; /** - * Generate PaySelection + * Generate PaySelection + * @param miniTable + * @param paymentRule + * @param payDate + * @param bi + * @return error message (if any) */ public String generatePaySelect(IMiniTable miniTable, ValueNamePair paymentRule, Timestamp payDate, BankInfo bi) { - log.info(""); - String trxName = null; Trx trx = null; try { @@ -510,11 +536,21 @@ public class PaySelect trx.commit(); trx.close(); } + if (m_ps != null) + m_ps.set_TrxName(null); } return null; } // generatePaySelect + /** + * Get balance of selected bank record (after call to {@link #getPaymentRuleData(BankInfo)}) + * @return bank balance + */ + protected BigDecimal getBankBalance() { + return m_bankBalance; + } + /************************************************************************** * Bank Account Info */ @@ -538,12 +574,13 @@ public class PaySelect Currency = newCurrency; Balance = newBalance; } - int C_BankAccount_ID; - int C_Currency_ID; - String Name; + + public int C_BankAccount_ID; + public int C_Currency_ID; + public String Name; public String Currency; public BigDecimal Balance; - boolean Transfers; + public boolean Transfers; /** * to String diff --git a/org.idempiere.test/src/org/idempiere/test/form/PaySelectFormTest.java b/org.idempiere.test/src/org/idempiere/test/form/PaySelectFormTest.java new file mode 100644 index 0000000000..6912d5b4ce --- /dev/null +++ b/org.idempiere.test/src/org/idempiere/test/form/PaySelectFormTest.java @@ -0,0 +1,334 @@ +/*********************************************************************** + * This file is part of iDempiere ERP Open Source * + * http://www.idempiere.org * + * * + * Copyright (C) Contributors * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301, USA. * + * * + * Contributors: * + * - hengsin * + **********************************************************************/ +package org.idempiere.test.form; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.File; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; + +import org.compiere.apps.form.PayPrint; +import org.compiere.apps.form.PaySelect; +import org.compiere.apps.form.PaySelect.BankInfo; +import org.compiere.minigrid.IDColumn; +import org.compiere.model.MAllocationHdr; +import org.compiere.model.MAllocationLine; +import org.compiere.model.MBPartner; +import org.compiere.model.MInvoice; +import org.compiere.model.MInvoiceLine; +import org.compiere.model.MPInstance; +import org.compiere.model.MPInstancePara; +import org.compiere.model.MPaySelection; +import org.compiere.model.MPaySelectionCheck; +import org.compiere.model.MPaySelectionLine; +import org.compiere.model.MPayment; +import org.compiere.model.Query; +import org.compiere.model.SystemIDs; +import org.compiere.process.DocAction; +import org.compiere.process.ProcessInfo; +import org.compiere.process.ServerProcessCtl; +import org.compiere.util.DB; +import org.compiere.util.DisplayType; +import org.compiere.util.Env; +import org.compiere.util.KeyNamePair; +import org.compiere.util.TimeUtil; +import org.compiere.util.Util; +import org.compiere.util.ValueNamePair; +import org.compiere.wf.MWorkflow; +import org.idempiere.test.AbstractTestCase; +import org.idempiere.test.DictionaryIDs; +import org.idempiere.test.ui.MiniTableImpl; +import org.junit.jupiter.api.Test; + +public class PaySelectFormTest extends AbstractTestCase { + + public PaySelectFormTest() { + } + + @Test + public void testPaySelect() { + MInvoice invoice = null; + MInvoiceLine line = null; + MPaySelection paySelection = null; + Optional optionalPR = null; + try { + //create vendor invoice + invoice = new MInvoice(Env.getCtx(), 0, null); + MBPartner bp = MBPartner.get(Env.getCtx(), DictionaryIDs.C_BPartner.PATIO.id); + invoice.setBPartner(bp); + invoice.setIsSOTrx(false); + invoice.setC_DocTypeTarget_ID(); + invoice.setC_Currency_ID(DictionaryIDs.C_Currency.USD.id); + invoice.setPaymentRule(MInvoice.PAYMENTRULE_Check); + invoice.setC_PaymentTerm_ID(DictionaryIDs.C_PaymentTerm.IMMEDIATE.id); + invoice.setDateAcct(TimeUtil.getDay(System.currentTimeMillis())); + invoice.setDateOrdered(invoice.getDateAcct()); + invoice.saveEx(); + + line = new MInvoiceLine(invoice); + line.setC_Charge_ID(DictionaryIDs.C_Charge.COMMISSIONS.id); + line.setQty(new BigDecimal("1")); + line.setPrice(new BigDecimal("10")); + line.saveEx(); + + ProcessInfo info = MWorkflow.runDocumentActionWorkflow(invoice, DocAction.ACTION_Complete); + assertFalse(info.isError(), info.getSummary()); + invoice.load(null); + assertEquals(DocAction.STATUS_Completed, invoice.getDocStatus()); + + PaySelectImpl form = new PaySelectImpl(); + + MInvoice finalInvoice = invoice; + ArrayList bis = form.getBankAccountData(); + assertTrue(bis.size() > 0, "Failed to retrieve bank account info"); + Optional optionalBI = bis.stream().filter(e -> e.C_Currency_ID == finalInvoice.getC_Currency_ID()).findFirst(); + assertTrue(optionalBI.isPresent(), "Failed to locate bank account record for currency " + invoice.getC_Currency_ID()); + + ArrayList bps = form.getBPartnerData(); + assertTrue(bps.size() > 0, "Failed to retrieve business partner records with open invoice"); + Optional optionalBP = bps.stream().filter(e -> e.getKey() == finalInvoice.getC_BPartner_ID()).findFirst(); + assertTrue(optionalBP.isPresent(), "Failed to find business partner for invoice"); + + ArrayList docTypes = form.getDocTypeData(); + assertTrue(docTypes.size() > 0, "Failed to retrieve document type records"); + Optional optionalDocType = docTypes.stream().filter(e -> e.getKey() == finalInvoice.getC_DocType_ID()).findFirst(); + assertTrue(optionalDocType.isPresent(), "Failed to retrieve document type for invoice"); + + ArrayList paymentRules = form.getPaymentRuleData(optionalBI.get()); + assertTrue(paymentRules.size() > 0, "Failed to retrieve payment rule records"); + optionalPR = paymentRules.stream().filter(e -> e.getValue().equals(finalInvoice.getPaymentRule())).findFirst(); + assertTrue(optionalPR.isPresent(), "Failed to retrieve payment rule for invoice"); + assertEquals(optionalBI.get().Balance.setScale(2, RoundingMode.HALF_EVEN), form.getBankBalance().setScale(2, RoundingMode.HALF_EVEN), "Unexpected bank balance"); + + form.loadTableInfo(optionalBI.get(), invoice.getDateInvoiced(), optionalPR.get(), true, true, optionalBP.get(), optionalDocType.get(), form.miniTable); + assertTrue(form.miniTable.getRowCount() > 0, "Failed to load open invoice documents"); + + BigDecimal balance = optionalBI.get().Balance; + for(int i = 0; i < form.miniTable.getRowCount(); i++) { + IDColumn id = (IDColumn) form.miniTable.getValueAt(i, 0); + if (id.getRecord_ID().intValue() == invoice.get_ID()) { + id.setSelected(true); + form.miniTable.setSelectedRow(i); + BigDecimal amt = (BigDecimal)form.miniTable.getValueAt(i, 9); + balance = balance.subtract(amt); + break; + } + } + + assertEquals(0, form.miniTable.getSelectedRow(), "Invoice not in loaded open list"); + + DecimalFormat format = DisplayType.getNumberFormat(DisplayType.Amount); + String status = form.calculateSelection(form.miniTable); + BigDecimal expected = optionalBI.get().Balance.subtract(invoice.getGrandTotal()); + String remaining = format.format(expected); + assertTrue(status.contains(remaining), "Unexpected status text"); + assertEquals(expected.setScale(2, RoundingMode.HALF_EVEN), balance.setScale(2, RoundingMode.HALF_EVEN), "Unexpected balance after selection and calculation"); + + //create pay selection + String error = form.generatePaySelect(form.miniTable, optionalPR.get(), invoice.getDateInvoiced(), optionalBI.get()); + assertTrue(Util.isEmpty(error, true), error); + assertNotNull(form.getPaySelection(), "Pay Selection Not Generated"); + paySelection = form.getPaySelection(); + + //create pay selection check + int AD_Process_ID = SystemIDs.PROCESS_C_PAYSELECTION_CREATEPAYMENT; + MPInstance mpi = new MPInstance(Env.getCtx(), AD_Process_ID, 0); + mpi.setRecord_ID(paySelection.get_ID()); + mpi.saveEx(); + MPInstancePara para = new MPInstancePara(mpi, 10); + para.setParameter(MPaySelection.COLUMNNAME_IsOnePaymentPerInvoice, false); + para.saveEx(); + + ProcessInfo pi = new ProcessInfo("PROCESS_C_PAYSELECTION_CREATEPAYMENT", AD_Process_ID); + pi.setAD_PInstance_ID(mpi.get_ID()); + pi.setAD_Client_ID(getAD_Client_ID()); + pi.setAD_User_ID(getAD_User_ID()); + pi.setTable_ID(MPaySelection.Table_ID); + pi.setRecord_ID(paySelection.get_ID()); + ServerProcessCtl.process(pi, null); + assertFalse(pi.isError(), pi.getSummary()); + + MPaySelectionCheck[] pscs = MPaySelectionCheck.get(paySelection.get_ID(), optionalPR.get().getValue(), null); + assertTrue(pscs.length > 0, "MPaySelectionCheck not created"); + + //create payment + PayPrintImpl payPrint = new PayPrintImpl(); + payPrint.loadPaySelectInfo(paySelection.getC_PaySelection_ID()); + paymentRules = payPrint.loadPaymentRule(paySelection.getC_PaySelection_ID()); + assertTrue(paymentRules.size() > 0, "Failed to load applicable payment rules for payment selection"); + payPrint.loadPaymentRuleInfo(paySelection.get_ID(), optionalPR.get().getValue()); + assertTrue(payPrint.getNextDocumentNo() > 0, "Unexpected next check/document number"); + assertTrue(payPrint.getNumberOfPreparePayment() > 0, "Unexpected number of C_PaySelectionCheck record: " + payPrint.getNumberOfPreparePayment()); + assertTrue(payPrint.getPayAmtSum() > 0, "Unexpected sum of pay amount: " + payPrint.getPayAmtSum()); + assertTrue(payPrint.getPrintFormatId() > 0, "No print format"); + + try { + AtomicReference errorRef = new AtomicReference<>(); + errorRef.set(new ValueNamePair(null, null)); + boolean loaded = payPrint.getChecks(optionalPR.get().getValue(), new BigDecimal(payPrint.getNextDocumentNo()), errorRef, null); + assertTrue(loaded, "Failed to load check selection records"); + assertTrue(Util.isEmpty(errorRef.get().getValue()), errorRef.get().getValue() + " " + errorRef.get().getName() != null ? errorRef.get().getName() : ""); + MPaySelectionCheck[] checks = payPrint.getSelectionChecks(); + assertTrue(checks.length > 0, "Unexpected number of C_PaySelectionCheck records : " + checks.length); + + //create payments + List pdfs = payPrint.createCheckDocuments(payPrint.getNextDocumentNo(), optionalPR.get().getValue()); + assertTrue(pdfs.size() > 0, "Failed to create check document"); + for(MPaySelectionCheck psc : checks) { + psc.load(null); + assertTrue(psc.getC_Payment_ID() > 0, "Payment not created"); + } + + pdfs = payPrint.createRemittanceDocuments(); + assertTrue(pdfs.size() > 0, "Failed to create remittance documents"); + } catch (Exception e1) { + fail(e1); + } + } finally { + if (paySelection != null && paySelection.get_ID() > 0) { + MPaySelectionLine[] lines = paySelection.getLines(true); + for(MPaySelectionLine l : lines) + l.deleteEx(true); + if (optionalPR.get() != null) { + MPaySelectionCheck[] pscs = MPaySelectionCheck.get(paySelection.get_ID(), optionalPR.get().getValue(), null); + for(MPaySelectionCheck psc : pscs) { + int C_Payment_ID = psc.getC_Payment_ID(); + psc.deleteEx(true); + if (C_Payment_ID > 0) { + MPayment payment = new MPayment(Env.getCtx(), C_Payment_ID, null); + if (payment.get_ID() != C_Payment_ID) continue; + Query query = new Query(Env.getCtx(), MAllocationLine.Table_Name, "C_Payment_ID=?", null); + List list = query.setParameters(payment.get_ID()).list(); + List headers = new ArrayList<>(); + for(MAllocationLine al : list) { + if (!headers.contains(al.getC_AllocationHdr_ID())) + headers.add(al.getC_AllocationHdr_ID()); + al.deleteEx(true); + } + for(Integer i : headers) { + MAllocationHdr hdr = new MAllocationHdr(Env.getCtx(), i, null); + hdr.deleteEx(true); + } + DB.executeUpdateEx("UPDATE C_Invoice SET C_Payment_ID=NULL WHERE C_Payment_ID=?", new Object[] {payment.get_ID()}, null); + payment.deleteEx(true); + } + } + } + paySelection.deleteEx(true); + } + if (line != null && line.get_ID() > 0) { + line.deleteEx(true); + } + if (invoice != null && invoice.get_ID() > 0) { + Query query = new Query(Env.getCtx(), MAllocationLine.Table_Name, "C_Invoice_ID=?", null); + List list = query.setParameters(invoice.get_ID()).list(); + List headers = new ArrayList<>(); + for(MAllocationLine al : list) { + if (!headers.contains(al.getC_AllocationHdr_ID())) + headers.add(al.getC_AllocationHdr_ID()); + al.deleteEx(true); + } + for(Integer i : headers) { + MAllocationHdr hdr = new MAllocationHdr(Env.getCtx(), i, null); + hdr.deleteEx(true); + } + invoice.deleteEx(true); + } + } + + } + + private class PaySelectImpl extends PaySelect { + MiniTableImpl miniTable = null; + + protected PaySelectImpl() { + miniTable = new MiniTableImpl(); + prepareTable(miniTable); + } + + protected BigDecimal getBankBalance() { + return super.getBankBalance(); + } + + protected MPaySelection getPaySelection() { + return m_ps; + } + } + + private class PayPrintImpl extends PayPrint { + protected int getNextDocumentNo() { + return documentNo != null ? documentNo.intValue() : 0; + } + + protected int getNumberOfPreparePayment() { + return !Util.isEmpty(noPayments, true) ? Integer.parseInt(noPayments) : 0; + } + + protected Double getPayAmtSum() { + return sumPayments; + } + + protected int getPrintFormatId() { + return printFormatId; + } + + + @Override + protected List createCheckDocuments(int startDocumentNo, String paymentRule) throws Exception { + return super.createCheckDocuments(startDocumentNo, paymentRule); + } + + @Override + protected List createRemittanceDocuments() { + return super.createRemittanceDocuments(); + } + + @Override + protected boolean getChecks(String PaymentRule, BigDecimal startDocumentNo, + AtomicReference error, String trxName) { + return super.getChecks(PaymentRule, startDocumentNo, error, trxName); + } + + protected MPaySelectionCheck[] getSelectionChecks() { + return m_checks; + } + + @Override + public void loadPaySelectInfo(int C_PaySelection_ID) { + m_C_PaySelection_ID = C_PaySelection_ID; + super.loadPaySelectInfo(C_PaySelection_ID); + } + } +} diff --git a/org.idempiere.test/src/org/idempiere/test/ui/MiniTableImpl.java b/org.idempiere.test/src/org/idempiere/test/ui/MiniTableImpl.java index 3fc70c8604..244574db54 100644 --- a/org.idempiere.test/src/org/idempiere/test/ui/MiniTableImpl.java +++ b/org.idempiere.test/src/org/idempiere/test/ui/MiniTableImpl.java @@ -36,6 +36,7 @@ import java.util.Map; import org.compiere.minigrid.ColumnInfo; import org.compiere.minigrid.IDColumn; import org.compiere.minigrid.IMiniTable; +import org.compiere.model.MRole; import org.compiere.model.PO; import org.compiere.util.KeyNamePair; @@ -101,14 +102,36 @@ public class MiniTableImpl implements IMiniTable { m_layout = layout; m_tableColumns.clear(); model.clear(); + StringBuilder sql = new StringBuilder ("SELECT "); for (int columnIndex = 0; columnIndex < layout.length; columnIndex++) { + // create sql + if (columnIndex > 0) + { + sql.append(", "); + } + sql.append(layout[columnIndex].getColSQL()); + + // adding ID column + if (layout[columnIndex].isKeyPairCol()) + { + sql.append(",").append(layout[columnIndex].getKeyPairColSQL()); + } + addColumn(layout[columnIndex].getColHeader(), layout[columnIndex].getColDescription(), layout[columnIndex].getAD_Reference_ID(), layout[columnIndex].getColClass()); if (layout[columnIndex].getColClass() == IDColumn.class) { m_keyColumnIndex = columnIndex; } } - return null; + + sql.append( " FROM ").append(from); + sql.append(" WHERE ").append(where); + + String finalSQL = MRole.getDefault().addAccessSQL(sql.toString(), + tableName, + MRole.SQL_FULLYQUALIFIED, + MRole.SQL_RO); + return finalSQL; } @Override