{
	"info": {
		"_postman_id": "40babcbe-1e7e-4f80-b93f-9905861a7464",
		"name": "EKKO_ticket_ENG382-90_BIS",
		"description": "Keobiz regroupe un ensemble de services englobant l’expertise comptable, la création d’entreprise, la domiciliation, l’annonce légale, le business plan, le juridique et l’administratif pour les petites entreprises, artisans, professions libérales et commerçants.\r\n\r\nKeobiz a la volonté d’apporter aux chefs d’entreprises un service complet et de qualité avec des tarifs compétitifs pour leur permettre de se concentrer sur leur métier tout en gagnant du temps et en réalisant des économies.",
		"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
	},
	"item": [
		{
			"name": "Scripts",
			"item": [
				{
					"name": "Invoicing",
					"item": [
						{
							"name": "InvoiceXmlScript",
							"event": [
								{
									"listen": "test",
									"script": {
										"exec": [
											"pm.test(\"Successful request\", () => {",
											"  pm.expect(pm.response.code).to.be.oneOf([201,200,202]);",
											"});",
											"",
											""
										],
										"type": "text/javascript"
									}
								}
							],
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "Content-Type",
										"value": "application/xml"
									},
									{
										"key": "Authorization",
										"value": "Basic b3BlbmNlbGwuYWRtaW46b3BlbmNlbGwuYWRtaW4="
									}
								],
								"body": {
									"mode": "raw",
									"raw": "<ScriptInstance code=\"com.opencellsoft.service.ekko.invoicing.InvoiceXmlScript\" description=\"Ekko Invoice Xml Script\">\r\n            <type>JAVA</type>\r\n            <script>\r\n            <![CDATA[ \r\npackage com.opencellsoft.service.ekko.invoicing;\r\n\r\nimport java.io.File;\r\nimport java.math.BigDecimal;\r\nimport java.math.RoundingMode;\r\nimport java.text.SimpleDateFormat;\r\nimport java.util.ArrayList;\r\nimport java.util.Comparator;\r\nimport java.util.Date;\r\nimport java.util.HashMap;\r\nimport java.util.List;\r\nimport java.util.Locale;\r\nimport java.util.Map;\r\nimport java.util.regex.Matcher;\r\nimport java.util.regex.Pattern;\r\n\r\nimport org.meveo.admin.exception.BusinessException;\r\nimport org.meveo.commons.utils.StringUtils;\r\nimport org.meveo.model.billing.Invoice;\r\nimport org.meveo.model.billing.InvoiceAgregate;\r\nimport org.meveo.model.billing.RatedTransaction;\r\nimport org.meveo.model.billing.Subscription;\r\nimport org.meveo.model.billing.TaxInvoiceAgregate;\r\nimport org.meveo.model.payments.PaymentMethodEnum;\r\nimport org.meveo.model.shared.DateUtils;\r\nimport org.meveo.service.billing.impl.EkkoXMLInvoiceCreator;\r\nimport org.meveo.service.billing.impl.InvoiceService;\r\nimport org.meveo.service.billing.impl.RatedTransactionService;\r\nimport org.meveo.service.script.Script;\r\nimport org.w3c.dom.Document;\r\nimport org.w3c.dom.Element;\r\n\r\n/**\r\n * Generate custom Xml Invoice Execute Context Variable :\r\n * <li>CONTEXT_ENTITY : the invoice\r\n * <li>isVirtual : invoicing mode\r\n * <li>XMLInvoiceCreator : XMLInvoiceCreator std service\r\n *\r\n * @author anasseh\r\n */\r\npublic class InvoiceXmlScript extends Script {\r\n\r\n\tprivate static final long serialVersionUID = 1L;\r\n\tprivate EkkoXMLInvoiceCreator xmlInvoiceCreatorScript = (EkkoXMLInvoiceCreator) getServiceInterface(EkkoXMLInvoiceCreator.class.getSimpleName());\r\n\tprivate InvoiceService invoiceService = (InvoiceService) getServiceInterface(InvoiceService.class.getSimpleName());\r\n\tprivate RatedTransactionService ratedTransactionService = (RatedTransactionService) getServiceInterface(RatedTransactionService.class.getSimpleName());\r\n\t\r\n\tprivate SimpleDateFormat dateFormat = new SimpleDateFormat(\"MMMM\", Locale.FRENCH);\r\n\tprivate static final String CF_SUB_PAY_METHOD = \"CF_SUB_PAY_METHOD\";\r\n\tprivate static final String SHIPPING_ADDRESS = \"ShippingAddress\";\r\n\tprivate static final String CF_NbrOfRadiator = \"EK_OPP_NofRadiator__c\";\r\n\tprivate static final String CF_NbrOfRooms = \"EK_OPP_Number_Rooms__c\";\r\n\tprivate Long nbrOfRadiotor = 0L;\r\n\tprivate Long nbrOfRooms = 0L;\r\n\tList<RatedTransaction> rts  = new ArrayList<RatedTransaction>();\r\n\t@Override\r\n\tpublic void execute(Map<String, Object> methodContext) throws BusinessException {\r\n\t\tlog.debug(\"EXECUTE methodContext {}\", methodContext);\r\n\t\ttry {\r\n\r\n\t\t\tInvoice invoice = (Invoice) methodContext.get(Script.CONTEXT_ENTITY);\r\n\t\t\t rts  = ratedTransactionService.getRatedTransactionsByInvoice(invoice, true);\r\n\t\t\tString fullXmlFilePath = invoiceService.getFullXmlFilePath(invoice, true);\r\n\t\t\tBoolean isVirtual = (Boolean) methodContext.get(\"isVirtual\");\r\n\t\t\tDocument document = xmlInvoiceCreatorScript.createDocument(invoice, isVirtual, true);\r\n\t\t\tadditionalInfos(document, invoice, \"CF_SUB_SF_DATA\");\r\n\t\t\tif (\"REC\".equals(invoice.getInvoiceType().getCode())) {\r\n\t\t\t\taddDetailREC(document, invoice);\r\n\t\t\t}\r\n\t\t\tif (\"UPF\".equals(invoice.getInvoiceType().getCode())) {\r\n\t\t\t\taddDetailUPF(document, invoice);\r\n\t\t\t\taddRefsMats(document);\r\n\t\t\t}\r\n\t\t\taddTotalLInes(document, invoice);\r\n\r\n\t\t\tFile file = xmlInvoiceCreatorScript.createFile(document, invoice, fullXmlFilePath);\r\n\t\t\tmethodContext.put(Script.RESULT_VALUE, file);\r\n\t\t} catch (Exception e) {\r\n\t\t\te.printStackTrace();\r\n\t\t\tthrow new BusinessException(e.getMessage());\r\n\t\t}\r\n\t}\r\n\r\n\tprivate void addTotalLInes(Document document, Invoice invoice) {\r\n\t\tElement totauxElement = document.createElement(\"totauxElement\");\r\n\r\n\t\tBigDecimal netToPay = invoice.getAmountWithoutTax();\r\n\r\n\t\tElement totalHTLineElem = document.createElement(\"totalLine\");\r\n\r\n\t\ttotalHTLineElem.setAttribute(\"name\", \"Total HT\");\r\n\t\ttotalHTLineElem.setAttribute(\"amount\", roundFormat(invoice.getAmountWithoutTax()));\r\n\t\ttotauxElement.appendChild(totalHTLineElem);\r\n\r\n\t\tList<TaxInvoiceAgregate> taxInvoiceAgregates = new ArrayList<TaxInvoiceAgregate>();\r\n\t\tfor (InvoiceAgregate invoiceAgregate : invoice.getInvoiceAgregates()) {\r\n\t\t\tif (invoiceAgregate instanceof TaxInvoiceAgregate) {\r\n\t\t\t\ttaxInvoiceAgregates.add((TaxInvoiceAgregate) invoiceAgregate);\r\n\t\t\t}\r\n\t\t}\r\n\t\ttaxInvoiceAgregates.sort(Comparator.comparing(ta -> ta.getTax().getPercent()));\r\n\t\tfor (TaxInvoiceAgregate taxInvoiceAgregate : taxInvoiceAgregates) {\r\n\r\n\t\t\tElement taxElem = document.createElement(\"totalLine\");\r\n\t\t\t\r\n\t\t\tBigDecimal amountTaxInvoiceAgregate = round(computeAmountsForTaxes(rts, taxInvoiceAgregate.getTaxPercent())[1]);\r\n\r\n\t\t\ttaxElem.setAttribute(\"name\", \"TVA (\" + roundFormat(taxInvoiceAgregate.getTaxPercent(), true) + \"%)\");\r\n\t\t\ttaxElem.setAttribute(\"amount\", roundFormat(amountTaxInvoiceAgregate));\r\n\t\t\ttotauxElement.appendChild(taxElem);\r\n\r\n\t\t\tnetToPay = netToPay.add(round(amountTaxInvoiceAgregate));\r\n\r\n\t\t}\r\n\r\n\t\tMap<String, Object> params = new HashMap<String, Object>();\r\n\t\tparams.put(\"dueDateIN\", new Date());\r\n\t\tList<Invoice> unPaidInvoices = (List<Invoice>) invoiceService.executeSelectQuery(\"select inv from Invoice inv where inv.id != \" + invoice.getId()\r\n\t\t\t\t+ \" and inv.recordedInvoice != null and  inv.recordedInvoice.matchingStatus != 'L'  and inv.dueDate <:dueDateIN  and inv.billingAccount.id = \"\r\n\t\t\t\t+ invoice.getBillingAccount().getId() + \" order by inv.id\", params);\r\n\r\n\t\tfor (Invoice inv : unPaidInvoices) {\r\n\t\t\tElement invElem = document.createElement(\"totalLine\");\r\n\r\n\t\t\tinvElem.setAttribute(\"name\", \"Facture impay\\u00E9e N\\u00B0 \" + inv.getInvoiceNumber() + \" du \" + DateUtils.formatDateWithPattern(inv.getInvoiceDate(), \"dd/MM/yyyy\"));\r\n\t\t\tinvElem.setAttribute(\"amount\", roundFormat(inv.getAmountWithTax()));\r\n\t\t\ttotauxElement.appendChild(invElem);\r\n\t\t\tnetToPay = netToPay.add(round(inv.getAmountWithTax()));\r\n\r\n\t\t}\r\n\r\n\t\tElement totalLineElem = document.createElement(\"totalLine\");\r\n\r\n\t\ttotalLineElem.setAttribute(\"name\", \"Total \\u00E0 payer TTC\");\r\n\t\ttotalLineElem.setAttribute(\"amount\", roundFormat(netToPay));\r\n\t\ttotauxElement.appendChild(totalLineElem);\r\n\r\n\t\tdocument.getElementsByTagName(\"invoice\").item(0).appendChild(totauxElement);\r\n\r\n\t}\r\n\r\n//\tprivate void addUnPaidInvoices(Document document, Invoice invoice) {\r\n//\t\tElement unPaidInvElement = document.createElement(\"unPaidInvoices\");\r\n//\r\n//\t\tList<Invoice> unPaidInvoices = (List<Invoice>) invoiceService\r\n//\t\t\t\t.executeSelectQuery(\"select inv from Invoice inv where inv.id != \" + invoice.getId() + \" and inv.recordedInvoice != null and  inv.recordedInvoice.matchingStatus != 'L'  order by inv.id\", null);\r\n//\t\tfor (Invoice inv : unPaidInvoices) {\r\n//\t\t\tElement invElem = document.createElement(\"unPaidInvoice\");\r\n//\r\n//\t\t\tinvElem.setAttribute(\"invoiceNumber\", inv.getInvoiceNumber());\r\n//\t\t\tinvElem.setAttribute(\"invoiceDate\", DateUtils.formatDateWithPattern(inv.getInvoiceDate(), \"dd/MM/yyyy\"));\r\n//\t\t\tinvElem.setAttribute(\"dueDate\", DateUtils.formatDateWithPattern(inv.getDueDate(), \"dd/MM/yyyy\"));\r\n//\t\t\tinvElem.setAttribute(\"amountWithTax\", roundFormat(inv.getAmountWithTax()));\r\n//\t\t\tinvElem.setAttribute(\"amountWithoutTax\", roundFormat(inv.getAmountWithoutTax()));\r\n//\t\t\tinvElem.setAttribute(\"amountTax\", roundFormat(inv.getAmountTax()));\r\n//\t\t\tunPaidInvElement.appendChild(invElem);\r\n//\t\t}\r\n//\r\n//\t\tdocument.getElementsByTagName(\"invoice\").item(0).appendChild(unPaidInvElement);\r\n//\r\n//\t}\r\n\r\n\tprivate void addDetailREC(Document document, Invoice invoice) {\r\n\r\n\t\tElement detailREC = document.createElement(\"detailREC\");\r\n\t\tif (getPaymentMethodType(invoice) != null) {\r\n\t\t\tdetailREC.setAttribute(\"paymentMethod\", getPaymentMethodType(invoice).name());\r\n\t\t}\r\n\t\t\r\n\t\tfor (RatedTransaction rt : rts) {\r\n\t\t\tElement linElem = document.createElement(\"lineREC\");\r\n\t\t\tif (rt.getCode().startsWith(\"CH_REC\")) {\r\n\t\t\t\tlinElem.setAttribute(\"label\",\r\n\t\t\t\t\t\trt.getDescription() + \" du \" + dateFormat.format(rt.getStartDate()) + \" \" + DateUtils.formatDateWithPattern(rt.getStartDate(), \"dd/MM/yyyy\") + \" au \"\r\n\t\t\t\t\t\t\t\t+ DateUtils.formatDateWithPattern(DateUtils.addDaysToDate(rt.getEndDate(), -1), \"dd/MM/yyyy\"));\r\n\t\t\t} else {\r\n\t\t\t\tlinElem.setAttribute(\"label\", rt.getDescription());\r\n\t\t\t}\r\n\t\t\tlinElem.setAttribute(\"unitAmountWithoutTax\", roundFormat(rt.getUnitAmountWithoutTax()));\r\n\t\t\tlinElem.setAttribute(\"taxPercent\", roundFormat(rt.getTaxPercent(), true) + \" %\");\r\n\t\t\tlinElem.setAttribute(\"unitAmountWithTax\", roundFormat(rt.getUnitAmountWithTax()));\r\n\t\t\tlinElem.setAttribute(\"quantity\", roundFormat(rt.getQuantity()));\r\n\t\t\tlinElem.setAttribute(\"amountWithTax\", roundFormat(rt.getAmountWithTax()));\r\n\t\t\tdetailREC.appendChild(linElem);\r\n\t\t}\r\n\r\n\t\tdocument.getElementsByTagName(\"invoice\").item(0).appendChild(detailREC);\r\n\r\n\t}\r\n\r\n\tprivate BigDecimal[] computeAmounts(List<RatedTransaction> rts, String subCatCode) {\r\n\r\n\t\tBigDecimal[] amounts = new BigDecimal[3];\r\n\t\tamounts[0] = BigDecimal.ZERO;\r\n\t\tamounts[1] = BigDecimal.ZERO;\r\n\t\tamounts[2] = BigDecimal.ZERO;\r\n\t\t\t\t\r\n\t\tfor(RatedTransaction rt : rts) {\r\n\t\t\tif(subCatCode.equals(rt.getInvoiceSubCategory().getCode())) {\r\n\t\t\t\tamounts[0] = amounts[0].add(round(rt.getAmountWithoutTax()));\r\n\t\t\t\tamounts[1] = amounts[1].add(round(rt.getAmountTax()));\r\n\t\t\t\tamounts[2] = amounts[2].add(round(rt.getAmountWithTax()));\r\n\t\t\t}\r\n\t\t}\t\t\r\n\r\n\t\treturn amounts;\r\n\t}\r\n\r\n\tprivate BigDecimal[] computeAmountsForTaxes(List<RatedTransaction> rts, BigDecimal taxPercent) {\r\n\r\n\t\tBigDecimal[] amounts = new BigDecimal[3];\r\n\t\tamounts[0] = BigDecimal.ZERO;\r\n\t\tamounts[1] = BigDecimal.ZERO;\r\n\t\tamounts[2] = BigDecimal.ZERO;\r\n\t\t\t\t\r\n\t\tfor(RatedTransaction rt : rts) {\r\n\t\t\tif(taxPercent.compareTo(rt.getTaxPercent()) == 0) {\r\n\t\t\t\tamounts[0] = amounts[0].add(round(rt.getAmountWithoutTax()));\r\n\t\t\t\tamounts[1] = amounts[1].add(round(rt.getAmountTax()));\r\n\t\t\t\tamounts[2] = amounts[2].add(round(rt.getAmountWithTax()));\r\n\t\t\t}\r\n\t\t}\t\t\r\n\r\n\t\treturn amounts;\r\n\t}\r\n\tprivate Element addLineUPF(Document document, String label, String taxPercent, BigDecimal unitHt, BigDecimal unitTtc, BigDecimal quantity, BigDecimal ttc) {\r\n\t\tElement linElem = document.createElement(\"lineUPF\");\r\n\r\n\t\tlinElem.setAttribute(\"label\", label);\r\n\r\n\t\tlinElem.setAttribute(\"unitAmountWithoutTax\", unitHt == null ? \"-\" : roundFormat(unitHt));\r\n\t\tlinElem.setAttribute(\"taxPercent\", taxPercent == null ? \"-\" : (taxPercent + \" %\"));\r\n\t\tlinElem.setAttribute(\"unitAmountWithTax\", unitTtc == null ? \"-\" : roundFormat(unitTtc));\r\n\t\tlinElem.setAttribute(\"quantity\", quantity == null ? \"-\" : roundFormat(quantity));\r\n\t\tlinElem.setAttribute(\"amountWithTax\", ttc == null ? \"-\" : roundFormat(ttc));\r\n\t\treturn linElem;\r\n\r\n\t}\r\n\r\n\tprivate void addDetailUPF(Document document, Invoice invoice) {\r\n\t\tElement detailUPF = document.createElement(\"detailUPF\");\r\n\t\tif (getPaymentMethodType(invoice) != null) {\r\n\t\t\tdetailUPF.setAttribute(\"paymentMethod\", getPaymentMethodType(invoice).name());\r\n\t\t}\r\n\t\t\r\n\r\n\t\tBigDecimal[] amountsInstall = computeAmounts(rts, \"ISCAT_EKKO_INSTALL\");\r\n\t\tBigDecimal[] amountsMat = computeAmounts(rts, \"ISCAT_EKKO_MAT_VENTE\");\r\n\t\tBigDecimal[] amountsDEEE = computeAmounts(rts, \"ISCAT_EKKO_DEEE\");\r\n\t\tBigDecimal[] amountsDEEERemise = computeAmounts(rts, \"ISCAT_EKKO_DEEE_REMISE\");\r\n\t\tBigDecimal[] amountsRemiseInstal = computeAmounts(rts, \"ISCAT_EKKO_INSTALL_REMISE\");\r\n\t\tBigDecimal[] amountsRemiseMat = computeAmounts(rts, \"ISCAT_EKKO_MAT_REMISE\");\r\n\t\tBigDecimal[] amountsGest = computeAmounts(rts, \"ISCAT_EKKO_INSTALL_GEST\");\r\n\r\n\t\tBigDecimal total = round(amountsInstall[2]).add(round(amountsMat[2]).add(round(amountsDEEE[2])));\r\n\t\tif (total.compareTo(BigDecimal.ZERO) != 0) {\r\n\t\t\tdetailUPF.appendChild(addLineUPF(document, \"Fourniture et pose de programmateurs d’intermittence de marque ENGIE sur \" + nbrOfRadiotor + \" radiateurs existants \", null,\r\n\t\t\t\t\tnull, round(total), BigDecimal.ONE, round(total)));\r\n\t\t\tdetailUPF.appendChild(addLineUPF(document, \"\\tdont mat&eacute;riel¹\", \"5,5\", amountsMat[0], amountsMat[2], BigDecimal.ONE, amountsMat[2]));\r\n\t\t\tdetailUPF.appendChild(addLineUPF(document, \"\\tdont &eacute;co-participation \\tDEEE\", \"20\", amountsDEEE[0], amountsDEEE[2], BigDecimal.ONE, amountsDEEE[2]));\r\n\t\t\tdetailUPF.appendChild(addLineUPF(document, \"\\tdont installation\", \"5,5\", amountsInstall[0], amountsInstall[2], BigDecimal.ONE, amountsInstall[2]));\r\n\t\t}\r\n\r\n\t\tBigDecimal totalRemise = round(amountsRemiseInstal[2]).add(round(amountsRemiseMat[2])).add(round(amountsDEEERemise[2]));\r\n\t\tif (totalRemise.compareTo(BigDecimal.ZERO) != 0) {\r\n\t\t\tdetailUPF.appendChild(addLineUPF(document, \"Remise\", null, null, round(totalRemise), BigDecimal.ONE, round(totalRemise)));\r\n\t\t\tdetailUPF.appendChild(addLineUPF(document, \"\\tsur mat&eacute;riel\", \"5,5\", amountsRemiseMat[0], amountsRemiseMat[2], BigDecimal.ONE, amountsRemiseMat[2]));\r\n\t\t\tdetailUPF.appendChild(addLineUPF(document, \"\\tsur installation\", \"5,5\", amountsRemiseInstal[0], amountsRemiseInstal[2], BigDecimal.ONE, amountsRemiseInstal[2]));\r\n\t\t\tdetailUPF.appendChild(addLineUPF(document, \"\\tsur &eacute;co-participation DEEE\", \"20\", amountsDEEERemise[0], amountsDEEERemise[2], BigDecimal.ONE, amountsDEEERemise[2]));\r\n\r\n\t\t}\r\n\r\n\t\tif (amountsGest[0].compareTo(BigDecimal.ZERO) != 0) {\r\n\t\t\tdetailUPF.appendChild(addLineUPF(document, \"Geste commercial\", \"5,5\", amountsGest[0], amountsGest[2], BigDecimal.ONE, amountsGest[2]));\r\n\r\n\t\t}\r\n\r\n\t\tdocument.getElementsByTagName(\"invoice\").item(0).appendChild(detailUPF);\r\n\r\n\t}\r\n\r\n\tpublic Element addMaterielLine(Document document, String name, String reference) {\r\n\t\tElement linElem = document.createElement(\"mat\");\r\n\t\tlinElem.setAttribute(\"name\", name);\r\n\t\tlinElem.setAttribute(\"reference\", reference);\r\n\t\treturn linElem;\r\n\t}\r\n\r\n\tprivate void addRefsMats(Document document) {\r\n\t\tElement refsMats = document.createElement(\"refsMats\");\r\n\t\trefsMats.appendChild(addMaterielLine(document, \"1 prise communicante « Mbox »\", \"(référence K02-GM-01.0013E-C-ETH)\"));\r\n\t\trefsMats.appendChild(addMaterielLine(document, nbrOfRadiotor + \" modules de pilotage « Dbox »\", \"(référence K01-CDK-01.1016-01-P1/TIK)\"));\r\n\t\trefsMats.appendChild(addMaterielLine(document, nbrOfRooms + \" capteurs de température « Sense-3 »\", \"(référence K02-CASTH-01.1004-01/TIK-WH)\"));\r\n\t\trefsMats.appendChild(addMaterielLine(document, \"1 câble Ethernet de longueur 5m\", \"(référence CA-ETHC2)\"));\r\n\r\n\t\tdocument.getElementsByTagName(\"invoice\").item(0).appendChild(refsMats);\r\n\t}\r\n\r\n\tprivate void additionalInfos(Document document, Invoice invoice, String cfName) {\r\n\r\n\t\tElement additionalFields = document.createElement(\"additionalFields\");\r\n\r\n\t\tSubscription sub = invoice.getSubscription();\r\n\t\tMap<String, String> sfDataMap = (Map<String, String>) sub.getCfValue(cfName);\r\n\t\tif (sfDataMap != null) {\r\n\t\t\tfor (Map.Entry<String, String> entry : sfDataMap.entrySet()) {\r\n\t\t\t\tif (SHIPPING_ADDRESS.equals(entry.getKey())) {\r\n\t\t\t\t\textractShippingAddress(document, additionalFields, entry.getValue());\r\n\t\t\t\t} else {\r\n\t\t\t\t\tElement entryElem = document.createElement(entry.getKey());\r\n\t\t\t\t\tentryElem.setTextContent(entry.getValue());\r\n\t\t\t\t\tadditionalFields.appendChild(entryElem);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (sfDataMap.get(CF_NbrOfRadiator) != null) {\r\n\t\t\t\tnbrOfRadiotor = Long.valueOf(sfDataMap.get(CF_NbrOfRadiator));\r\n\t\t\t}\r\n\t\t\tif (sfDataMap.get(CF_NbrOfRooms) != null) {\r\n\t\t\t\tnbrOfRooms = Long.valueOf(sfDataMap.get(CF_NbrOfRooms));\r\n\t\t\t}\r\n\t\t}\r\n\t\tElement dateInsElem = document.createElement(\"CF_SUB_DATE_INSTALL\");\r\n\t\tdateInsElem.setTextContent(DateUtils.formatDateWithPattern((Date) sub.getCfValue(\"CF_SUB_DATE_INSTALL\"), \"dd/MM/yyyy\"));\r\n\t\tadditionalFields.appendChild(dateInsElem);\r\n\r\n\t\tElement nbDaysElem = document.createElement(\"CF_SEL_PAY_NB_BUSI_DAYS\");\r\n\t\tnbDaysElem.setTextContent(\"\" + (Long) sub.getSeller().getCfValue(\"CF_SEL_PAY_NB_BUSI_DAYS\"));\r\n\t\tadditionalFields.appendChild(nbDaysElem);\r\n\r\n\t\tdocument.getElementsByTagName(\"invoice\").item(0).appendChild(additionalFields);\r\n\t}\r\n\r\n\tprivate BigDecimal round(BigDecimal amount) {\r\n\t\treturn round(amount, false);\r\n\t}\r\n\r\n\tprivate BigDecimal round(BigDecimal amount, boolean stripTrailingZeros) {\r\n\t\tif (amount == null) {\r\n\t\t\tamount = BigDecimal.ZERO;\r\n\t\t}\r\n\t\tint scale = 2;\r\n\r\n\t\tamount = amount.setScale(scale, RoundingMode.HALF_UP);\r\n\t\tif (stripTrailingZeros) {\r\n\t\t\tamount = amount.stripTrailingZeros();\r\n\t\t}\r\n\t\treturn amount;\r\n\t}\r\n\r\n\tprivate String roundFormat(BigDecimal amount) {\r\n\t\treturn String.valueOf(round(amount, false).toPlainString()).replaceAll(\"\\\\.\", \",\");\r\n\t}\r\n\r\n\tprivate String roundFormat(BigDecimal amount, boolean stripTrailingZeros) {\r\n\t\treturn String.valueOf(round(amount, stripTrailingZeros).toPlainString()).replaceAll(\"\\\\.\", \",\");\r\n\t}\r\n\r\n\tprivate PaymentMethodEnum getPaymentMethodType(Invoice invoice) {\r\n\t\tString paymentMethod = (String) invoice.getSubscription().getCfValue(CF_SUB_PAY_METHOD);\r\n\t\tPaymentMethodEnum paymentMethodEnumCommande = null;\r\n\t\tif (paymentMethod != null) {\r\n\t\t\tpaymentMethodEnumCommande = PaymentMethodEnum.valueOf(paymentMethod);\r\n\t\t}\r\n\t\tPaymentMethodEnum paymentMethodEnumCustomer = invoice.getBillingAccount().getCustomerAccount().getPreferredPaymentMethodType();\r\n\r\n\t\tif (paymentMethodEnumCommande == PaymentMethodEnum.DIRECTDEBIT && paymentMethodEnumCustomer != PaymentMethodEnum.DIRECTDEBIT) {\r\n\t\t\treturn PaymentMethodEnum.CARD;\r\n\t\t}\r\n\t\treturn paymentMethodEnumCommande;\r\n\r\n\t}\r\n\r\n\tprivate void extractShippingAddress(Document document, Element additionalFields, String shippingAddress) {\r\n\r\n\t\tif (!StringUtils.isBlank(shippingAddress)) {\r\n\t\t\tMatcher m = Pattern.compile(\"\\\\d{5}\\\\S+\").matcher(shippingAddress);\r\n\t\t\tString address = null;\r\n\t\t\tString zipAndCity = null;\r\n\t\t\tif (m.find()) {\r\n\t\t\t\tzipAndCity = m.group(0);\r\n\t\t\t}\r\n\t\t\tif (zipAndCity != null) {\r\n\t\t\t\taddress = shippingAddress.substring(0, (shippingAddress.length() - zipAndCity.length()));\r\n\t\t\t\tElement addressElement = document.createElement(SHIPPING_ADDRESS);\r\n\t\t\t\taddressElement.setTextContent(address);\r\n\t\t\t\tadditionalFields.appendChild(addressElement);\r\n\r\n\t\t\t\tElement zipCodeElement = document.createElement(\"zipcode_and_city\");\r\n\t\t\t\tzipCodeElement.setTextContent(zipAndCity);\r\n\t\t\t\tadditionalFields.appendChild(zipCodeElement);\r\n\t\t\t} else {\r\n\t\t\t\tElement shippingAddressElement = document.createElement(SHIPPING_ADDRESS);\r\n\t\t\t\tshippingAddressElement.setTextContent(shippingAddress);\r\n\t\t\t\tadditionalFields.appendChild(shippingAddressElement);\r\n\t\t\t}\r\n\r\n\t\t}\r\n\t}\r\n\r\n}\r\n\r\n\r\n]]>\r\n            </script>\r\n</ScriptInstance>\r\n\r\n"
								},
								"url": {
									"raw": "{{opencell.url}}/scriptInstance/createOrUpdate",
									"host": [
										"{{opencell.url}}"
									],
									"path": [
										"scriptInstance",
										"createOrUpdate"
									]
								}
							},
							"response": []
						},
						{
							"name": "CheckRoundingAmountsScript",
							"event": [
								{
									"listen": "test",
									"script": {
										"exec": [
											"pm.test(\"Successful request\", () => {",
											"  pm.expect(pm.response.code).to.be.oneOf([201,200,202]);",
											"});",
											"",
											""
										],
										"type": "text/javascript"
									}
								}
							],
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "Content-Type",
										"value": "application/xml"
									},
									{
										"key": "Authorization",
										"value": "Basic b3BlbmNlbGwuYWRtaW46b3BlbmNlbGwuYWRtaW4="
									}
								],
								"body": {
									"mode": "raw",
									"raw": "<ScriptInstance code=\"com.opencellsoft.service.ekko.invoicing.CheckRoundingAmountsScript\" description=\"Check Rounding Amounts Script\">\r\n            <type>JAVA</type>\r\n            <script>\r\n            <![CDATA[ \r\npackage com.opencellsoft.service.ekko.invoicing;\r\n\r\nimport java.math.BigDecimal;\r\nimport java.math.RoundingMode;\r\nimport java.util.List;\r\nimport java.util.Map;\r\n\r\nimport org.meveo.admin.exception.BusinessException;\r\nimport org.meveo.commons.utils.ParamBean;\r\nimport org.meveo.model.billing.Invoice;\r\nimport org.meveo.model.billing.RatedTransaction;\r\nimport org.meveo.service.billing.impl.InvoiceService;\r\nimport org.meveo.service.billing.impl.RatedTransactionService;\r\nimport org.meveo.service.payments.impl.CustomerAccountService;\r\nimport org.meveo.service.script.Script;\r\nimport org.slf4j.Logger;\r\nimport org.slf4j.LoggerFactory;\r\n\r\n/**\r\n\r\n *\r\n * @author anasseh\r\n */\r\npublic class CheckRoundingAmountsScript extends Script {\r\n\r\n\tprivate static final long serialVersionUID = 1L;\r\n\tprivate static final Logger log = LoggerFactory.getLogger(CheckRoundingAmountsScript.class);\r\n\t\r\n\tprivate InvoiceService invoiceService = (InvoiceService) getServiceInterface(InvoiceService.class.getSimpleName());\r\n\tprivate RatedTransactionService ratedTransactionService = (RatedTransactionService) getServiceInterface(RatedTransactionService.class.getSimpleName());\r\n\tprivate CustomerAccountService customerAccountService = (CustomerAccountService) getServiceInterface(CustomerAccountService.class.getSimpleName());\r\n\t\r\n\r\n\r\n\t@Override\r\n\tpublic void execute(Map<String, Object> methodContext) throws BusinessException {\r\n\t\tlog.info(\"EXECUTE methodContext {}\", methodContext);\r\n\t\t\r\n\t\tInvoice invoice = (Invoice) methodContext.get(Script.CONTEXT_ENTITY);\r\n\t\tList<RatedTransaction> rts  = ratedTransactionService.getRatedTransactionsByInvoice(invoice, true);\r\n\t\tBigDecimal[] amounts = computeAmounts(rts);\r\n\t\tinvoice.setAmountWithoutTax(amounts[0]);\r\n\t\tinvoice.setAmountTax(amounts[1]);\r\n\t\tinvoice.setAmountWithTax(amounts[2]);\r\n\t\t\r\n\t\t\r\n\t\tBigDecimal balance = BigDecimal.ZERO;\r\n\t\t\r\n\t\t boolean isBalanceDue = ParamBean.getInstance().getPropertyAsBoolean(\"invoice.balance.limitByDueDate\", true);\r\n         boolean isBalanceLitigation = ParamBean.getInstance().getPropertyAsBoolean(\"invoice.balance.includeLitigation\", false);\r\n         if (isBalanceLitigation) {\r\n             balance = customerAccountService.customerAccountBalanceDue(invoice.getBillingAccount().getCustomerAccount(), isBalanceDue ? invoice.getInvoiceDate() : null);\r\n         } else {\r\n             balance = customerAccountService.customerAccountBalanceDueWithoutLitigation(invoice.getBillingAccount().getCustomerAccount(), isBalanceDue ? invoice.getInvoiceDate() : null);\r\n         }\r\n         \r\n         invoice.setNetToPay(round(round(balance).add(invoice.getAmountWithTax())));\r\n         \r\n         invoiceService.updateNoCheck(invoice);\r\n\t\t\r\n\t}\r\n\r\n\tprivate BigDecimal[] computeAmounts(List<RatedTransaction> rts) {\r\n\r\n\t\tBigDecimal[] amounts = new BigDecimal[3];\r\n\t\tamounts[0] = BigDecimal.ZERO;\r\n\t\tamounts[1] = BigDecimal.ZERO;\r\n\t\tamounts[2] = BigDecimal.ZERO;\r\n\t\t\t\t\r\n\t\tfor(RatedTransaction rt : rts) {\r\n\t\t\t\r\n\t\t\t\tamounts[0] = amounts[0].add(round(rt.getAmountWithoutTax()));\r\n\t\t\t\tamounts[1] = amounts[1].add(round(rt.getAmountTax()));\r\n\t\t\t\tamounts[2] = amounts[2].add(round(rt.getAmountWithTax()));\r\n\t\t\t\r\n\t\t}\t\t\r\n\r\n\t\treturn amounts;\r\n\t}\r\n\t\r\n\tprivate BigDecimal round(BigDecimal amount) {\r\n\t\treturn round(amount, false);\r\n\t}\r\n\r\n\tprivate BigDecimal round(BigDecimal amount, boolean stripTrailingZeros) {\r\n\t\tif (amount == null) {\r\n\t\t\tamount = BigDecimal.ZERO;\r\n\t\t}\r\n\t\tint scale = 2;\r\n\r\n\t\tamount = amount.setScale(scale, RoundingMode.HALF_UP);\r\n\t\tif (stripTrailingZeros) {\r\n\t\t\tamount = amount.stripTrailingZeros();\r\n\t\t}\r\n\t\treturn amount;\r\n\t}\r\n}\r\n\r\n\r\n]]>\r\n            </script>\r\n</ScriptInstance>\r\n\r\n"
								},
								"url": {
									"raw": "{{opencell.url}}/scriptInstance/createOrUpdate",
									"host": [
										"{{opencell.url}}"
									],
									"path": [
										"scriptInstance",
										"createOrUpdate"
									]
								}
							},
							"response": []
						}
					]
				}
			]
		},
		{
			"name": "Notification",
			"item": [
				{
					"name": "CheckRoundingAmountsNotif",
					"event": [
						{
							"listen": "test",
							"script": {
								"exec": [
									""
								],
								"type": "text/javascript"
							}
						}
					],
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "raw",
							"raw": "\r\n        {\r\n        \t\r\n                \"priority\":\"-2\",\r\n\t\t\t    \"code\": \"CheckRoundingAmountsNotif\",\r\n\t\t\t\t\"runAsync\": false,\r\n\t\t\t    \"description\": \"CheckRoundingAmountsNotif\",\r\n\t\t\t    \"classNameFilter\": \"org.meveo.model.billing.Invoice\",\r\n\t\t\t    \"eventTypeFilter\": \"UPDATED\",\r\n\t\t\t    \"elFilter\": \"#{event.invoiceNumber != null}\",\r\n\t\t\t\t\"disabled\": false,\r\n\t\t\t\t\"saveSuccessfulNotifications\": false,\r\n\t\t\t    \"scriptInstanceCode\": \"com.opencellsoft.service.ekko.invoicing.CheckRoundingAmountsScript\"\r\n        \t\r\n        }",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{opencell.url}}/notification/createOrUpdate",
							"host": [
								"{{opencell.url}}"
							],
							"path": [
								"notification",
								"createOrUpdate"
							]
						}
					},
					"response": []
				}
			]
		}
	],
	"auth": {
		"type": "basic",
		"basic": [
			{
				"key": "password",
				"value": "{{opencell.password}}",
				"type": "string"
			},
			{
				"key": "username",
				"value": "{{opencell.username}}",
				"type": "string"
			},
			{
				"key": "saveHelperData",
				"type": "any"
			},
			{
				"key": "showPassword",
				"value": false,
				"type": "boolean"
			}
		]
	},
	"event": [
		{
			"listen": "prerequest",
			"script": {
				"type": "text/javascript",
				"exec": [
					"var now=new Date();",
					"pm.globals.set(\"timestamp.iso\", now.toISOString());",
					"pm.globals.set(\"request.label\", pm.info.requestName);",
					"var parts = pm.info.requestName.split(\"|\");",
					"for(let i=0; i<parts.length; i++) {",
					"    pm.globals.set(\"wait\", 0);",
					"    pm.globals.set(\"request.label.\"+i, parts[i]);",
					"    if(parts[i].indexOf(\"=\") != -1 ){",
					"        propName = parts[i].split(\"=\")[0].trim();",
					"        propValue = parts[i].split(\"=\")[1];",
					"        pm.globals.set(propName, propValue);",
					"    }",
					"}"
				]
			}
		},
		{
			"listen": "test",
			"script": {
				"type": "text/javascript",
				"exec": [
					"let skipTest = pm.environment.get('skipTest');",
					"",
					"(skipTest ? pm.test.skip : pm.test('Status code is ' + pm.response.code, function() {",
					"    pm.expect(pm.response.code).to.be.oneOf([200, 201]);",
					"}));",
					"",
					"(skipTest ? pm.test.skip : pm.test(\"Successful request\", function () {",
					"    var jsonData = pm.response.json();",
					"    if (responseBody.has(\"actionStatus\")) {",
					"        pm.expect(jsonData.actionStatus.status).to.eql(\"SUCCESS\");",
					"    } else {",
					"        pm.expect(jsonData.status).to.eql(\"SUCCESS\");",
					"    }",
					"}));"
				]
			}
		}
	]
}