# HG changeset patch
# User Gorka Gil <gorka.gil@openbravo.com>
# Date 1550237746 -3600
#      Fri Feb 15 14:35:46 2019 +0100
# Node ID 01361f74e96b77521152aafc05a9005179f0b18a
# Parent  a6452b3b0f6efa5fe8043e5e1044c95c28e860c7
Fixes issue 33973: Cash Vat in sales order and sales invoice

diff -r a6452b3b0f6e -r 01361f74e96b src/org/openbravo/retail/posterminal/OrderGroupingProcessor.java
--- a/src/org/openbravo/retail/posterminal/OrderGroupingProcessor.java	Tue Feb 19 10:57:34 2019 +0100
+++ b/src/org/openbravo/retail/posterminal/OrderGroupingProcessor.java	Fri Feb 15 14:35:46 2019 +0100
@@ -40,6 +40,7 @@
 import org.openbravo.dal.service.OBCriteria;
 import org.openbravo.dal.service.OBDal;
 import org.openbravo.database.ConnectionProvider;
+import org.openbravo.erpCommon.utility.CashVATUtil;
 import org.openbravo.erpCommon.utility.OBMessageUtils;
 import org.openbravo.erpCommon.utility.SequenceIdData;
 import org.openbravo.erpCommon.utility.Utility;
@@ -54,6 +55,7 @@
 import org.openbravo.model.common.order.Order;
 import org.openbravo.model.common.order.OrderLine;
 import org.openbravo.model.common.order.OrderLineOffer;
+import org.openbravo.model.financialmgmt.payment.FIN_PaymentDetail;
 import org.openbravo.model.financialmgmt.payment.FIN_PaymentSchedule;
 import org.openbravo.model.financialmgmt.payment.FIN_PaymentScheduleDetail;
 import org.openbravo.model.materialmgmt.transaction.ShipmentInOutLine;
@@ -276,6 +278,9 @@
       invoice.setDocumentNo(
           getInvoiceDocumentNo(invoice.getTransactionDocument(), invoice.getDocumentType()));
       finishInvoice(invoice, currentDate);
+      if (invoice.isCashVAT()) {
+        createCashVat(invoice);
+      }
       executeHooks(invoice, cashUpId);
     }
 
@@ -393,6 +398,19 @@
         doctype == null ? "" : doctype.getId(), false, true);
   }
 
+  protected void createCashVat(Invoice invoiceObj) {
+    for (FIN_PaymentSchedule scheduleObj : invoiceObj.getFINPaymentScheduleList()) {
+      for (FIN_PaymentScheduleDetail schDetailObj : scheduleObj
+          .getFINPaymentScheduleDetailInvoicePaymentScheduleList()) {
+        FIN_PaymentDetail paymentDetail = schDetailObj.getPaymentDetails();
+        if (paymentDetail != null) {
+          CashVATUtil.createInvoiceTaxCashVAT(paymentDetail, scheduleObj,
+              paymentDetail.getAmount().add(paymentDetail.getWriteoffAmount()));
+        }
+      }
+    }
+  }
+
   private void finishInvoice(Invoice oriInvoice, Date currentDate) throws SQLException {
     if (oriInvoice == null) {
       return;
diff -r a6452b3b0f6e -r 01361f74e96b src/org/openbravo/retail/posterminal/OrderGroupingProcessor_data.xsql
--- a/src/org/openbravo/retail/posterminal/OrderGroupingProcessor_data.xsql	Tue Feb 19 10:57:34 2019 +0100
+++ b/src/org/openbravo/retail/posterminal/OrderGroupingProcessor_data.xsql	Fri Feb 15 14:35:46 2019 +0100
@@ -58,13 +58,13 @@
         (c_invoice_id, ad_client_id, ad_org_id, isactive, created, createdby, updated, updatedby, issotrx,
          documentno, docstatus, docaction, processing, processed, posted, c_doctype_id, c_doctypetarget_id, c_order_id, description, dateordered,
          salesrep_id, dateinvoiced, dateacct, c_bpartner_id, c_bpartner_location_id,  c_currency_id, paymentrule, c_paymentterm_id, totallines,
-         grandtotal, m_pricelist_id, ispaid, totalpaid, outstandingamt, fin_paymentmethod_id, ad_user_id, em_aprm_processinvoice)
+         grandtotal, m_pricelist_id, ispaid, totalpaid, outstandingamt, fin_paymentmethod_id, ad_user_id, em_aprm_processinvoice, iscashvat)
         select get_uuid(), o.ad_client_id, o.ad_org_id, 'Y', now(), ?, now(), ?, 'Y', ?,
         'CO', 'RE', 'N', 'Y', 'N', dt.c_doctypeinvoice_id, dt.c_doctypeinvoice_id,
         null, ?, null, max(o.salesrep_id), to_date(to_char(?), to_char('DD-MM-YYYY')),
         to_date(to_char(?), to_char('DD-MM-YYYY')), o.c_bpartner_id, coalesce(o.billto_id, o.c_bpartner_location_id),
         o.c_currency_id, bp.paymentrule, bp.c_paymentterm_id, sum(o.totallines), sum(o.grandtotal), max(o.m_pricelist_id),
-        'Y', sum(o.grandtotal),  0, bp.fin_paymentmethod_id, o.ad_user_id, 'RE'
+        'Y', sum(o.grandtotal),  0, bp.fin_paymentmethod_id, o.ad_user_id, 'RE', o.iscashvat
         from  c_order o, obpos_applications ap, ad_org org, c_doctype dt, c_bpartner bp
         where o.em_obpos_applications_id = ap.obpos_applications_id
         and ap.ad_org_id = org.ad_org_id
@@ -77,7 +77,7 @@
         and o.em_obpos_notinvoiceoncashup = 'N'
         group by  o.ad_client_id, o.ad_org_id, dt.c_doctypeinvoice_id, dt.c_doctypeinvoice_id,
         o.c_bpartner_id, coalesce(o.billto_id, o.c_bpartner_location_id), o.c_currency_id, bp.paymentrule,
-        bp.c_paymentterm_id, o.m_pricelist_id, bp.fin_paymentmethod_id, o.ad_user_id
+        bp.c_paymentterm_id, o.m_pricelist_id, bp.fin_paymentmethod_id, o.ad_user_id, o.iscashvat
     ]]>
     </Sql>
     <Parameter name="userId"/>
@@ -99,14 +99,14 @@
         (c_invoice_id, ad_client_id, ad_org_id, isactive, created, createdby, updated, updatedby, issotrx,
          documentno, docstatus, docaction, processing, processed, posted, c_doctype_id, c_doctypetarget_id, c_order_id, description, dateordered,
          salesrep_id, dateinvoiced, dateacct, c_bpartner_id, c_bpartner_location_id,  c_currency_id, paymentrule, c_paymentterm_id, totallines,
-         grandtotal, m_pricelist_id, ispaid, totalpaid, outstandingamt, fin_paymentmethod_id, ad_user_id, em_aprm_processinvoice)
+         grandtotal, m_pricelist_id, ispaid, totalpaid, outstandingamt, fin_paymentmethod_id, ad_user_id, em_aprm_processinvoice, iscashvat)
         select get_uuid(), o.ad_client_id, o.ad_org_id, 'Y', now(), ?, now(), ?, 'Y', ?, 'CO', 'RE', 'N', 'Y', 'N',
         dt.c_doctypeinvoice_id, dt.c_doctypeinvoice_id,
         o.c_order_id, ? || '. ' || max(ad_message_get2('OrderDocumentno', ?)) || ' ' || o.documentno, o.dateordered,
         max(o.salesrep_id), to_date(to_char(?), to_char('DD-MM-YYYY')),
         to_date(to_char(?), to_char('DD-MM-YYYY')),
         o.c_bpartner_id, coalesce(o.billto_id, o.c_bpartner_location_id), o.c_currency_id, bp.paymentrule,
-        bp.c_paymentterm_id, sum(o.totallines), sum(o.grandtotal), max(o.m_pricelist_id), 'Y', sum(o.grandtotal),  0, bp.fin_paymentmethod_id, o.ad_user_id, 'RE'
+        bp.c_paymentterm_id, sum(o.totallines), sum(o.grandtotal), max(o.m_pricelist_id), 'Y', sum(o.grandtotal),  0, bp.fin_paymentmethod_id, o.ad_user_id, 'RE', o.iscashvat
         from  c_order o, obpos_applications ap, ad_org org, c_doctype dt, c_bpartner bp
         where o.em_obpos_applications_id = ap.obpos_applications_id
         and ap.ad_org_id = org.ad_org_id
@@ -119,7 +119,7 @@
         group by  o.ad_client_id, o.ad_org_id, dt.c_doctypeinvoice_id, dt.c_doctypeinvoice_id,
         o.c_bpartner_id, coalesce(o.billto_id, o.c_bpartner_location_id), o.c_currency_id, bp.paymentrule,
         bp.c_paymentterm_id, o.m_pricelist_id, bp.fin_paymentmethod_id, o.ad_user_id,
-        o.c_order_id, o.dateOrdered, o.documentno
+        o.c_order_id, o.dateOrdered, o.documentno, o.iscashvat
         order by o.dateOrdered, o.documentno
       ]]>
     </Sql>
@@ -165,6 +165,7 @@
         and o.c_doctype_id in (org.em_obpos_c_doctype_id, org.em_obpos_c_doctyperet_id)
         and not exists (select 1 from c_orderline ol2 where ol2.qtyinvoiced <> 0 and ol2.c_order_id = o.c_order_id)
         and o.em_obpos_notinvoiceoncashup = 'N'
+        and o.iscashvat = i.iscashvat
         and i.documentno = ?
         and i.c_bpartner_id = o.c_bpartner_id and i.c_bpartner_location_id = coalesce(o.billto_id, o.c_bpartner_location_id)
         and coalesce(i.ad_user_id, '1') = coalesce(o.ad_user_id, '1')
@@ -216,6 +217,7 @@
         and o.c_doctype_id in (org.em_obpos_c_doctype_id, org.em_obpos_c_doctyperet_id)
         and not exists (select 1 from c_orderline ol2 where ol2.qtyinvoiced <> 0 and ol2.c_order_id = o.c_order_id)
         and o.em_obpos_notinvoiceoncashup = 'N'
+        and o.iscashvat = i.iscashvat
         and i.documentno = ?
         and i.c_order_id = o.c_order_id
         group by i.ad_client_id, i.ad_org_id, i.createdby, i.updatedby,
diff -r a6452b3b0f6e -r 01361f74e96b src/org/openbravo/retail/posterminal/OrderLoader.java
--- a/src/org/openbravo/retail/posterminal/OrderLoader.java	Tue Feb 19 10:57:34 2019 +0100
+++ b/src/org/openbravo/retail/posterminal/OrderLoader.java	Fri Feb 15 14:35:46 2019 +0100
@@ -1,6 +1,6 @@
 /*
  ************************************************************************************
- * Copyright (C) 2012-2018 Openbravo S.L.U.
+ * Copyright (C) 2012-2019 Openbravo S.L.U.
  * Licensed under the Openbravo Commercial License version 1.0
  * You may obtain a copy of the License at http://www.openbravo.com/legal/obcl.html
  * or in the legal folder of this module distribution.
@@ -968,6 +968,10 @@
       order.set("creationDate", new Date(value));
     }
 
+    if (jsonorder.has("cashVAT")) {
+      order.setCashVAT(jsonorder.getBoolean("cashVAT"));
+    }
+
     int pricePrecision = order.getCurrency().getObposPosprecision() == null
         ? order.getCurrency().getPricePrecision().intValue()
         : order.getCurrency().getObposPosprecision().intValue();
diff -r a6452b3b0f6e -r 01361f74e96b src/org/openbravo/retail/posterminal/term/Terminal.java
--- a/src/org/openbravo/retail/posterminal/term/Terminal.java	Tue Feb 19 10:57:34 2019 +0100
+++ b/src/org/openbravo/retail/posterminal/term/Terminal.java	Fri Feb 15 14:35:46 2019 +0100
@@ -115,13 +115,20 @@
       HQLPropertyList regularTerminalHQLProperties = ModelExtensionUtils
           .getPropertyExtensions(extensions, jsonsent);
 
+      String strOrgId = pOSTerminal.getOrganization().getId();
+
       final OrganizationInformation myOrgInfo = pOSTerminal.getOrganization()
           .getOrganizationInformationList()
           .get(0);
+      final Organization org = OBDal.getInstance().get(Organization.class, strOrgId);
+      final Organization legalEntity = OBContext.getOBContext()
+          .getOrganizationStructureProvider(org.getClient().getId())
+          .getLegalEntity(org);
 
       String storeAddress = "";
       String regionId = "";
       String countryId = "";
+      String orgInfoId = "";
 
       if (myOrgInfo.getLocationAddress() != null
           && myOrgInfo.getLocationAddress().getIdentifier().length() > 0) {
@@ -135,6 +142,12 @@
       if (myOrgInfo.getLocationAddress().getCountry() != null) {
         countryId = myOrgInfo.getLocationAddress().getCountry().getId();
       }
+
+      if (legalEntity != null && legalEntity.getOrganizationInformationList() != null
+          && !legalEntity.getOrganizationInformationList().isEmpty()) {
+        orgInfoId = legalEntity.getId();
+      }
+
       String selectOrgImage = "";
       String fromOrgImage = "";
       String whereOrgImage = "";
@@ -180,12 +193,14 @@
           + lastDocumentNumber + " as lastDocumentNumber, " + lastQuotationDocumentNumber
           + " as lastQuotationDocumentNumber, " + lastReturnDocumentNumber
           + " as lastReturnDocumentNumber, " + "'" + regionId + "'" + " as organizationRegionId, "
-          + "'" + countryId + "'" + " as organizationCountryId, '"
+          + "'" + countryId + "'" + " as organizationCountryId, orginfo.cashVAT as cashVat, '"
           + ProcessHQLQuery.escape(storeAddress) + "' as organizationAddressIdentifier, "
           + sessionTimeout + " as sessionTimeout, " + selectOrgImage
           + regularTerminalHQLProperties.getHqlSelect()
-          + " from OBPOS_Applications AS pos inner join pos.obposTerminaltype as postype inner join pos.organization AS org, "
+          + " from OBPOS_Applications AS pos inner join pos.obposTerminaltype as postype inner join pos.organization AS org, Organization org2, "
           + "PricingPriceList pricelist " + fromOrgImage
+          + " inner join org2.organizationInformationList as orginfo with orginfo.id='" + orgInfoId
+          + "'"
           + " where pos.$readableSimpleCriteria and pos.$activeCriteria and pos.searchKey =:searchKey and pricelist.id =:pricelistId "
           + whereOrgImage;
 
diff -r a6452b3b0f6e -r 01361f74e96b web/org.openbravo.retail.posterminal/js/data/dataordertaxes.js
--- a/web/org.openbravo.retail.posterminal/js/data/dataordertaxes.js	Tue Feb 19 10:57:34 2019 +0100
+++ b/web/org.openbravo.retail.posterminal/js/data/dataordertaxes.js	Fri Feb 15 14:35:46 2019 +0100
@@ -276,7 +276,8 @@
             bpName = receipt.get('bp').get('name') || OB.I18N.getLabel('OBPOS_LblEmptyAddress'),
             bpShipLocName = receipt.get('bp').get('shipLocName') || OB.I18N.getLabel('OBPOS_LblEmptyAddress'),
             bplCountryId = receipt.get('bp').get('shipCountryId') ? receipt.get('bp').get('shipCountryId') : null,
-            bplRegionId = receipt.get('bp').get('shipRegionId') ? receipt.get('bp').get('shipRegionId') : null;
+            bplRegionId = receipt.get('bp').get('shipRegionId') ? receipt.get('bp').get('shipRegionId') : null,
+            isCashVat = OB.MobileApp.model.get('terminal').cashVat;
         // SQL build
         // the query is ordered by countryId desc and regionId desc
         // (so, the first record will be the tax with the same country or
@@ -312,6 +313,9 @@
           sql = sql + " and (c_tax.to_country_id = '" + bplCountryId + "'   or tz.to_country_id = '" + bplCountryId + "'   or (c_tax.to_country_id is null       and (not exists (select 1 from c_tax_zone z where z.c_tax_id = c_tax.c_tax_id)           or exists (select 1 from c_tax_zone z where z.c_tax_id = c_tax.c_tax_id and z.to_country_id = '" + bplCountryId + "')           or exists (select 1 from c_tax_zone z where z.c_tax_id = c_tax.c_tax_id and z.to_country_id is null))))";
           sql = sql + " and (c_tax.to_region_id = '" + bplRegionId + "'   or tz.to_region_id = '" + bplRegionId + "'  or (c_tax.to_region_id is null       and (not exists (select 1 from c_tax_zone z where z.c_tax_id = c_tax.c_tax_id)           or exists (select 1 from c_tax_zone z where z.c_tax_id = c_tax.c_tax_id and z.to_region_id = '" + bplRegionId + "')           or exists (select 1 from c_tax_zone z where z.c_tax_id = c_tax.c_tax_id and z.to_region_id is null))))";
         }
+        if (isCashVat) {
+          sql = sql + " and (c_tax.isCashVAT ='" + isCashVat + "' OR (c_tax.isCashVAT = 'false' and (c_tax.isWithholdingTax = 'true' or c_tax.rate=0))) ";
+        }
         sql = sql + " order by orderRegionTo, orderRegionFrom, orderCountryTo, orderCountryFrom, c_tax.validFrom desc, c_tax.isdefault desc";
 
         OB.UTIL.HookManager.executeHooks('OBPOS_FindTaxRate', {
diff -r a6452b3b0f6e -r 01361f74e96b web/org.openbravo.retail.posterminal/js/model/order.js
--- a/web/org.openbravo.retail.posterminal/js/model/order.js	Tue Feb 19 10:57:34 2019 +0100
+++ b/web/org.openbravo.retail.posterminal/js/model/order.js	Fri Feb 15 14:35:46 2019 +0100
@@ -7354,6 +7354,7 @@
       order.set('isQuotation', false);
       order.set('oldId', null);
       order.set('session', OB.MobileApp.model.get('session'));
+      order.set('cashVAT', OB.MobileApp.model.get('terminal').cashVat);
       order.set('bp', bp);
       if (OB.MobileApp.model.hasPermission('EnableMultiPriceList', true)) {
         // Set price list for order
