1 18 package org.ofbiz.accounting.invoice; 19 20 import java.math.BigDecimal ; 21 import java.sql.Timestamp ; 22 import java.util.*; 23 24 import javolution.util.FastMap; 25 26 import org.ofbiz.accounting.payment.BillingAccountWorker; 27 import org.ofbiz.accounting.payment.PaymentWorker; 28 import org.ofbiz.accounting.payment.PaymentGatewayServices; 29 import org.ofbiz.base.util.Debug; 30 import org.ofbiz.base.util.UtilDateTime; 31 import org.ofbiz.base.util.UtilFormatOut; 32 import org.ofbiz.base.util.UtilMisc; 33 import org.ofbiz.base.util.UtilNumber; 34 import org.ofbiz.base.util.UtilProperties; 35 import org.ofbiz.base.util.UtilValidate; 36 import org.ofbiz.entity.GenericDelegator; 37 import org.ofbiz.entity.GenericEntityException; 38 import org.ofbiz.entity.GenericValue; 39 import org.ofbiz.entity.util.EntityUtil; 40 import org.ofbiz.entity.condition.EntityCondition; 41 import org.ofbiz.entity.condition.EntityOperator; 42 import org.ofbiz.entity.condition.EntityExpr; 43 import org.ofbiz.order.order.OrderReadHelper; 44 import org.ofbiz.product.product.ProductWorker; 45 import org.ofbiz.service.DispatchContext; 46 import org.ofbiz.service.GenericServiceException; 47 import org.ofbiz.service.LocalDispatcher; 48 import org.ofbiz.service.ServiceUtil; 49 50 93 public class InvoiceServices { 94 95 public static String module = InvoiceServices.class.getName(); 96 97 private static BigDecimal ZERO = new BigDecimal ("0"); 99 private static int decimals = UtilNumber.getBigDecimalScale("invoice.decimals"); 100 private static int rounding = UtilNumber.getBigDecimalRoundingMode("invoice.rounding"); 101 private static int taxDecimals = UtilNumber.getBigDecimalScale("salestax.calc.decimals"); 102 private static int taxRounding = UtilNumber.getBigDecimalScale("salestax.rounding"); 103 104 public static final String resource = "AccountingUiLabels"; 105 106 107 public static Map createInvoiceForOrder(DispatchContext dctx, Map context) { 108 GenericDelegator delegator = dctx.getDelegator(); 109 LocalDispatcher dispatcher = dctx.getDispatcher(); 110 GenericValue userLogin = (GenericValue) context.get("userLogin"); 111 Locale locale = (Locale) context.get("locale"); 112 113 if (decimals == -1 || rounding == -1) { 114 return ServiceUtil.returnError("Arithmetic properties for Invoice services not configured properly. Cannot proceed."); 115 } 116 117 String orderId = (String ) context.get("orderId"); 118 List billItems = (List) context.get("billItems"); 119 boolean previousInvoiceFound = false; 120 121 if (billItems == null || billItems.size() == 0) { 122 Debug.logVerbose("No order items to invoice; not creating invoice; returning success", module); 123 return ServiceUtil.returnSuccess("No order items to invoice, not creating invoice."); 124 } 125 126 try { 127 GenericValue orderHeader = delegator.findByPrimaryKey("OrderHeader", UtilMisc.toMap("orderId", orderId)); 128 if (orderHeader == null) { 129 return ServiceUtil.returnError("No OrderHeader, cannot create invoice"); 130 } 131 132 List billedItems = delegator.findByAnd("OrderItemBilling", UtilMisc.toMap("orderId", orderId)); 134 if (billedItems != null && billedItems.size() > 0) { 135 boolean nonDigitalInvoice = false; 136 Iterator bii = billedItems.iterator(); 137 while (bii.hasNext() && !nonDigitalInvoice) { 138 GenericValue orderItemBilling = (GenericValue) bii.next(); 139 GenericValue invoiceItem = orderItemBilling.getRelatedOne("InvoiceItem"); 140 if (invoiceItem != null) { 141 String invoiceItemType = invoiceItem.getString("invoiceItemTypeId"); 142 if (invoiceItemType != null) { 143 if ("INV_FPROD_ITEM".equals(invoiceItemType) || "INV_PROD_FEATR_ITEM".equals(invoiceItemType)) { 144 nonDigitalInvoice = true; 145 } 146 } 147 } 148 } 149 if (nonDigitalInvoice) { 150 previousInvoiceFound = true; 151 } 152 } 153 154 String invoiceType = null; 156 157 String orderType = orderHeader.getString("orderTypeId"); 158 if (orderType.equals("SALES_ORDER")) { 159 invoiceType = "SALES_INVOICE"; 160 } else if (orderType.equals("PURCHASE_ORDER")) { 161 invoiceType = "PURCHASE_INVOICE"; 162 } 163 164 OrderReadHelper orh = new OrderReadHelper(orderHeader); 166 167 GenericValue productStore = delegator.findByPrimaryKey("ProductStore", UtilMisc.toMap("productStoreId", orh.getProductStoreId())); 169 170 String prorateShipping = productStore.getString("prorateShipping"); 172 if (prorateShipping == null) { 173 prorateShipping = "Y"; 174 } 175 176 String billToCustomerPartyId = orh.getBillToParty().getString("partyId"); 178 String billFromVendorPartyId = orh.getBillFromParty().getString("partyId"); 179 180 BigDecimal totalItemsInOrder = orh.getTotalOrderItemsQuantityBd(); 182 183 BigDecimal shippableAmount = orh.getShippableTotalBd(null); 185 BigDecimal orderSubTotal = orh.getOrderItemsSubTotalBd(); 186 187 BigDecimal invoiceShipProRateAmount = ZERO; 189 BigDecimal invoiceSubTotal = ZERO; 190 BigDecimal invoiceQuantity = ZERO; 191 192 GenericValue billingAccount = orderHeader.getRelatedOne("BillingAccount"); 193 String billingAccountId = billingAccount != null ? billingAccount.getString("billingAccountId") : null; 194 195 Timestamp invoiceDate = UtilDateTime.nowTimestamp(); 197 Long orderTermNetDays = orh.getOrderTermNetDays(); 199 Timestamp dueDate = null; 200 if (orderTermNetDays != null) { 201 dueDate = UtilDateTime.getDayEnd(invoiceDate, orderTermNetDays.intValue()); 202 } 203 204 Map createInvoiceContext = FastMap.newInstance(); 206 createInvoiceContext.put("partyId", billToCustomerPartyId); 207 createInvoiceContext.put("partyIdFrom", billFromVendorPartyId); 208 createInvoiceContext.put("billingAccountId", billingAccountId); 209 createInvoiceContext.put("invoiceDate", invoiceDate); 210 createInvoiceContext.put("dueDate", dueDate); 211 createInvoiceContext.put("invoiceTypeId", invoiceType); 212 createInvoiceContext.put("statusId", "INVOICE_IN_PROCESS"); 214 createInvoiceContext.put("currencyUomId", orderHeader.getString("currencyUom")); 215 createInvoiceContext.put("userLogin", userLogin); 216 217 Map createInvoiceResult = dispatcher.runSync("createInvoice", createInvoiceContext); 219 if (ServiceUtil.isError(createInvoiceResult)) { 220 return ServiceUtil.returnError("Error creating invoice from order", null, null, createInvoiceResult); 221 } 222 223 String invoiceId = (String ) createInvoiceResult.get("invoiceId"); 225 226 List orderRoles = orderHeader.getRelated("OrderRole"); 228 if (orderRoles != null) { 229 Iterator orderRolesIt = orderRoles.iterator(); 230 Map createInvoiceRoleContext = FastMap.newInstance(); 231 createInvoiceRoleContext.put("invoiceId", invoiceId); 232 createInvoiceRoleContext.put("userLogin", userLogin); 233 while (orderRolesIt.hasNext()) { 234 GenericValue orderRole = (GenericValue)orderRolesIt.next(); 235 createInvoiceRoleContext.put("partyId", orderRole.getString("partyId")); 236 createInvoiceRoleContext.put("roleTypeId", orderRole.getString("roleTypeId")); 237 Map createInvoiceRoleResult = dispatcher.runSync("createInvoiceRole", createInvoiceRoleContext); 238 if (ServiceUtil.isError(createInvoiceRoleResult)) { 239 return ServiceUtil.returnError("Error creating invoice role from order", null, null, createInvoiceRoleResult); 240 } 241 } 242 } 243 244 List orderTerms = orh.getOrderTerms(); 247 createInvoiceTerms(delegator, dispatcher, invoiceId, orderTerms, userLogin); 248 249 List billingAccountTerms = null; 251 if (billingAccount != null) { 253 billingAccountTerms = billingAccount.getRelated("BillingAccountTerm"); 255 256 createInvoiceTerms(delegator, dispatcher, invoiceId, billingAccountTerms, userLogin); 258 259 List billToRoles = billingAccount.getRelated("BillingAccountRole", UtilMisc.toMap("roleTypeId", "BILL_TO_CUSTOMER"), null); 261 Iterator billToIter = billToRoles.iterator(); 262 while (billToIter.hasNext()) { 263 GenericValue billToRole = (GenericValue) billToIter.next(); 264 if (!(billToRole.getString("partyId").equals(billToCustomerPartyId))) { 265 Map createInvoiceRoleContext = UtilMisc.toMap("invoiceId", invoiceId, "partyId", billToRole.get("partyId"), 266 "roleTypeId", "BILL_TO_CUSTOMER", "userLogin", userLogin); 267 Map createInvoiceRoleResult = dispatcher.runSync("createInvoiceRole", createInvoiceRoleContext); 268 if (ServiceUtil.isError(createInvoiceRoleResult)) { 269 return ServiceUtil.returnError("Error creating InvoiceRole from order", null, null, createInvoiceRoleResult); 270 } 271 } 272 } 273 274 if (UtilValidate.isNotEmpty(billingAccount.getString("contactMechId"))) { 276 Map createBillToContactMechContext = UtilMisc.toMap("invoiceId", invoiceId, "contactMechId", billingAccount.getString("contactMechId"), 277 "contactMechPurposeTypeId", "BILLING_LOCATION", "userLogin", userLogin); 278 Map createBillToContactMechResult = dispatcher.runSync("createInvoiceContactMech", createBillToContactMechContext); 279 if (ServiceUtil.isError(createBillToContactMechResult)) { 280 return ServiceUtil.returnError("Error creating BILLING_LOCATION InvoiceContactMech from order", null, null, createBillToContactMechResult); 281 } 282 } 283 } else { 284 List billingLocations = orh.getBillingLocations(); 285 if (billingLocations != null) { 286 Iterator bli = billingLocations.iterator(); 287 while (bli.hasNext()) { 288 GenericValue ocm = (GenericValue) bli.next(); 289 Map createBillToContactMechContext = UtilMisc.toMap("invoiceId", invoiceId, "contactMechId", ocm.getString("contactMechId"), 290 "contactMechPurposeTypeId", "BILLING_LOCATION", "userLogin", userLogin); 291 Map createBillToContactMechResult = dispatcher.runSync("createInvoiceContactMech", createBillToContactMechContext); 292 if (ServiceUtil.isError(createBillToContactMechResult)) { 293 return ServiceUtil.returnError("Error creating BILLING_LOCATION InvoiceContactMech from order", null, null, createBillToContactMechResult); 294 } 295 } 296 } 297 } 298 299 302 GenericValue payToAddress = null; 304 if (invoiceType.equals("PURCHASE_INVOICE")) { 305 GenericValue billFromVendor = orh.getPartyFromRole("BILL_FROM_VENDOR"); 307 if (billFromVendor != null) { 308 List billingContactMechs = billFromVendor.getRelatedOne("Party").getRelatedByAnd("PartyContactMechPurpose", 309 UtilMisc.toMap("contactMechPurposeTypeId", "BILLING_LOCATION")); 310 if ((billingContactMechs != null) && (billingContactMechs.size() > 0)) { 311 payToAddress = (GenericValue) billingContactMechs.get(0); 312 } 313 } 314 } else { 315 payToAddress = PaymentWorker.getPaymentAddress(delegator, productStore.getString("payToPartyId")); 317 } 318 if (payToAddress != null) { 319 320 Map createPayToContactMechContext = UtilMisc.toMap("invoiceId", invoiceId, "contactMechId", payToAddress.getString("contactMechId"), 321 "contactMechPurposeTypeId", "PAYMENT_LOCATION", "userLogin", userLogin); 322 Map createPayToContactMechResult = dispatcher.runSync("createInvoiceContactMech", createPayToContactMechContext); 323 if (ServiceUtil.isError(createPayToContactMechResult)) { 324 return ServiceUtil.returnError("Error creating PAYMENT_LOCATION InvoiceContactMech from order", null, null, createPayToContactMechResult); 325 } 326 } 327 328 int invoiceItemSeqNum = 1; 330 String invoiceItemSeqId = UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum, 2); 331 332 if (billItems != null) { 334 Iterator itemIter = billItems.iterator(); 335 while (itemIter.hasNext()) { 336 GenericValue itemIssuance = null; 337 GenericValue orderItem = null; 338 GenericValue shipmentReceipt = null; 339 GenericValue currentValue = (GenericValue) itemIter.next(); 340 if ("ItemIssuance".equals(currentValue.getEntityName())) { 341 itemIssuance = currentValue; 342 } else if ("OrderItem".equals(currentValue.getEntityName())) { 343 orderItem = currentValue; 344 } else if ("ShipmentReceipt".equals(currentValue.getEntityName())) { 345 shipmentReceipt = currentValue; 346 } else { 347 Debug.logError("Unexpected entity " + currentValue + " of type " + currentValue.getEntityName(), module); 348 } 349 350 if (orderItem == null && itemIssuance != null) { 351 orderItem = itemIssuance.getRelatedOne("OrderItem"); 352 } else if ((orderItem == null) && (shipmentReceipt != null)) { 353 orderItem = shipmentReceipt.getRelatedOne("OrderItem"); 354 } else if ((orderItem == null) && (itemIssuance == null) && (shipmentReceipt == null)) { 355 Debug.logError("Cannot create invoice when orderItem, itemIssuance, and shipmentReceipt are all null", module); 356 return ServiceUtil.returnError("Illegal values passed to create invoice service"); 357 } 358 GenericValue product = null; 359 if (orderItem.get("productId") != null) { 360 product = orderItem.getRelatedOne("Product"); 361 } 362 363 BigDecimal orderedQuantity = orderItem.getBigDecimal("quantity"); 365 BigDecimal billingQuantity = null; 366 if (itemIssuance != null) { 367 billingQuantity = itemIssuance.getBigDecimal("quantity"); 368 } else if (shipmentReceipt != null) { 369 billingQuantity = shipmentReceipt.getBigDecimal("quantityAccepted"); 370 } else { 371 billingQuantity = orderedQuantity; 372 } 373 if (orderedQuantity == null) orderedQuantity = ZERO; 374 if (billingQuantity == null) billingQuantity = ZERO; 375 376 String lookupType = "FINISHED_GOOD"; if (product != null) { 378 lookupType = product.getString("productTypeId"); 379 } else if (orderItem != null) { 380 lookupType = orderItem.getString("orderItemTypeId"); 381 } 382 383 boolean shippingApplies = false; 385 if ((product != null) && (ProductWorker.shippingApplies(product)) && (invoiceType.equals("SALES_INVOICE"))) { 386 shippingApplies = true; 387 } 388 389 BigDecimal billingAmount = orderItem.getBigDecimal("unitPrice").setScale(decimals, rounding); 390 391 Map createInvoiceItemContext = FastMap.newInstance(); 392 createInvoiceItemContext.put("invoiceId", invoiceId); 393 createInvoiceItemContext.put("invoiceItemSeqId", invoiceItemSeqId); 394 createInvoiceItemContext.put("invoiceItemTypeId", getInvoiceItemType(delegator, lookupType, invoiceType, "INV_FPROD_ITEM")); 395 createInvoiceItemContext.put("description", orderItem.get("itemDescription")); 396 createInvoiceItemContext.put("quantity", new Double (billingQuantity.doubleValue())); 397 createInvoiceItemContext.put("amount", new Double (billingAmount.doubleValue())); 398 createInvoiceItemContext.put("productId", orderItem.get("productId")); 399 createInvoiceItemContext.put("productFeatureId", orderItem.get("productFeatureId")); 400 createInvoiceItemContext.put("overrideGlAccountId", orderItem.get("overrideGlAccountId")); 401 createInvoiceItemContext.put("userLogin", userLogin); 403 404 String itemIssuanceId = null; 405 if (itemIssuance != null && itemIssuance.get("inventoryItemId") != null) { 406 itemIssuanceId = itemIssuance.getString("itemIssuanceId"); 407 createInvoiceItemContext.put("inventoryItemId", itemIssuance.get("inventoryItemId")); 408 } 409 if ((product != null) && (invoiceType.equals("SALES_INVOICE"))) { 411 createInvoiceItemContext.put("taxableFlag", product.get("taxable")); 412 } 413 414 Map createInvoiceItemResult = dispatcher.runSync("createInvoiceItem", createInvoiceItemContext); 415 if (ServiceUtil.isError(createInvoiceItemResult)) { 416 return ServiceUtil.returnError("Error creating InvoiceItem from order", null, null, createInvoiceItemResult); 417 } 418 419 BigDecimal thisAmount = billingAmount.multiply(billingQuantity).setScale(decimals, rounding); 421 422 if (shippingApplies) { 424 invoiceShipProRateAmount = invoiceShipProRateAmount.add(thisAmount).setScale(decimals, rounding); 425 } 426 427 invoiceSubTotal = invoiceSubTotal.add(thisAmount).setScale(100, rounding); 429 430 invoiceQuantity = invoiceQuantity.add(billingQuantity).setScale(decimals, rounding); 432 433 Map createOrderItemBillingContext = FastMap.newInstance(); 435 createOrderItemBillingContext.put("invoiceId", invoiceId); 436 createOrderItemBillingContext.put("invoiceItemSeqId", invoiceItemSeqId); 437 createOrderItemBillingContext.put("orderId", orderItem.get("orderId")); 438 createOrderItemBillingContext.put("orderItemSeqId", orderItem.get("orderItemSeqId")); 439 createOrderItemBillingContext.put("itemIssuanceId", itemIssuanceId); 440 createOrderItemBillingContext.put("quantity", new Double (billingQuantity.doubleValue())); 441 createOrderItemBillingContext.put("amount", new Double (billingAmount.doubleValue())); 442 createOrderItemBillingContext.put("userLogin", userLogin); 443 if ((shipmentReceipt != null) && (shipmentReceipt.getString("receiptId") != null)) { 444 createOrderItemBillingContext.put("shipmentReceiptId", shipmentReceipt.getString("receiptId")); 445 } 446 447 Map createOrderItemBillingResult = dispatcher.runSync("createOrderItemBilling", createOrderItemBillingContext); 448 if (ServiceUtil.isError(createOrderItemBillingResult)) { 449 return ServiceUtil.returnError("Error creating OrderItemBilling from order", null, null, createOrderItemBillingResult); 450 } 451 452 invoiceItemSeqNum++; 454 invoiceItemSeqId = UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum, 2); 455 456 List itemAdjustments = OrderReadHelper.getOrderItemAdjustmentList(orderItem, orh.getAdjustments()); 458 Iterator itemAdjIter = itemAdjustments.iterator(); 459 while (itemAdjIter.hasNext()) { 460 GenericValue adj = (GenericValue) itemAdjIter.next(); 461 462 BigDecimal adjAlreadyInvoicedAmount = null; 464 try { 465 Map checkResult = dispatcher.runSync("calculateInvoicedAdjustmentTotal", UtilMisc.toMap("orderAdjustment", adj)); 466 adjAlreadyInvoicedAmount = (BigDecimal ) checkResult.get("invoicedTotal"); 467 } catch (GenericServiceException e) { 468 String errMsg = UtilProperties.getMessage(resource, "AccountingTroubleCallingCalculateInvoicedAdjustmentTotalService", locale); 469 Debug.logError(e, errMsg, module); 470 return ServiceUtil.returnError(errMsg); 471 } 472 473 if (adjAlreadyInvoicedAmount.abs().compareTo(adj.getBigDecimal("amount").setScale(decimals, rounding).abs()) > 0) { 476 continue; 477 } 478 479 if (adj.get("amount") != null) { 480 482 BigDecimal amount = adj.getBigDecimal("amount").divide(orderItem.getBigDecimal("quantity"), 100, rounding); 484 amount = amount.multiply(billingQuantity); 485 amount = amount.setScale(decimals, rounding); 486 487 Map createInvoiceItemAdjContext = FastMap.newInstance(); 488 createInvoiceItemAdjContext.put("invoiceId", invoiceId); 489 createInvoiceItemAdjContext.put("invoiceItemSeqId", invoiceItemSeqId); 490 createInvoiceItemAdjContext.put("invoiceItemTypeId", getInvoiceItemType(delegator, adj.getString("orderAdjustmentTypeId"), invoiceType, "INVOICE_ITM_ADJ")); 491 createInvoiceItemAdjContext.put("description", adj.get("description")); 492 createInvoiceItemAdjContext.put("quantity", new Double (1)); 493 createInvoiceItemAdjContext.put("amount", new Double (amount.doubleValue())); 494 createInvoiceItemAdjContext.put("productId", orderItem.get("productId")); 495 createInvoiceItemAdjContext.put("productFeatureId", orderItem.get("productFeatureId")); 496 createInvoiceItemAdjContext.put("overrideGlAccountId", adj.get("overrideGlAccountId")); 497 createInvoiceItemAdjContext.put("userLogin", userLogin); 499 createInvoiceItemAdjContext.put("taxAuthPartyId", adj.get("taxAuthPartyId")); 500 createInvoiceItemAdjContext.put("taxAuthGeoId", adj.get("taxAuthGeoId")); 501 createInvoiceItemAdjContext.put("taxAuthorityRateSeqId", adj.get("taxAuthorityRateSeqId")); 502 503 if (!(adj.getString("orderAdjustmentTypeId").equals("SALES_TAX"))) { 506 createInvoiceItemAdjContext.put("taxableFlag", product.get("taxable")); 507 } 508 509 Map createInvoiceItemAdjResult = dispatcher.runSync("createInvoiceItem", createInvoiceItemAdjContext); 510 if (ServiceUtil.isError(createInvoiceItemAdjResult)) { 511 return ServiceUtil.returnError("Error creating InvoiceItem from order item adjustment", null, null, createInvoiceItemAdjResult); 512 } 513 514 Map createOrderAdjustmentBillingContext = FastMap.newInstance(); 516 createOrderAdjustmentBillingContext.put("orderAdjustmentId", adj.getString("orderAdjustmentId")); 517 createOrderAdjustmentBillingContext.put("invoiceId", invoiceId); 518 createOrderAdjustmentBillingContext.put("invoiceItemSeqId", invoiceItemSeqId); 519 createOrderAdjustmentBillingContext.put("amount", new Double (amount.doubleValue())); 520 createOrderAdjustmentBillingContext.put("userLogin", userLogin); 521 522 Map createOrderAdjustmentBillingResult = dispatcher.runSync("createOrderAdjustmentBilling", createOrderAdjustmentBillingContext); 523 if (ServiceUtil.isError(createOrderAdjustmentBillingResult)) { 524 return ServiceUtil.returnError(UtilProperties.getMessage(resource,"AccountingErrorCreatingOrderAdjustmentBillingFromOrder",locale), null, null, createOrderAdjustmentBillingContext); 525 } 526 527 BigDecimal thisAdjAmount = new BigDecimal (amount.doubleValue()).setScale(decimals, rounding); 529 530 if (!"SALES_TAX".equals(adj.getString("orderAdjustmentTypeId")) && 532 !"SHIPPING_ADJUSTMENT".equals(adj.getString("orderAdjustmentTypeId"))) { 533 invoiceSubTotal = invoiceSubTotal.add(thisAdjAmount).setScale(100, rounding); 535 536 if (shippingApplies) { 538 invoiceShipProRateAmount = invoiceShipProRateAmount.add(thisAdjAmount).setScale(decimals, rounding); 539 } 540 } 541 542 invoiceItemSeqNum++; 544 invoiceItemSeqId = UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum, 2); 545 } 546 } 547 } 548 } 549 550 Map shipAdjustments = new HashMap(); 552 Map taxAdjustments = new HashMap(); 553 554 List headerAdjustments = orh.getOrderHeaderAdjustments(); 555 Iterator headerAdjIter = headerAdjustments.iterator(); 556 while (headerAdjIter.hasNext()) { 557 GenericValue adj = (GenericValue) headerAdjIter.next(); 558 559 BigDecimal adjAlreadyInvoicedAmount = null; 561 try { 562 Map checkResult = dispatcher.runSync("calculateInvoicedAdjustmentTotal", UtilMisc.toMap("orderAdjustment", adj)); 563 adjAlreadyInvoicedAmount = ((BigDecimal ) checkResult.get("invoicedTotal")).setScale(decimals, rounding); 564 } catch (GenericServiceException e) { 565 String errMsg = UtilProperties.getMessage(resource, "AccountingTroubleCallingCalculateInvoicedAdjustmentTotalService", locale); 566 Debug.logError(e, errMsg, module); 567 return ServiceUtil.returnError(errMsg); 568 } 569 570 if (adjAlreadyInvoicedAmount.abs().compareTo(adj.getBigDecimal("amount").setScale(decimals, rounding).abs()) > 0) { 573 continue; 574 } 575 576 if ("SHIPPING_CHARGES".equals(adj.getString("orderAdjustmentTypeId"))) { 577 shipAdjustments.put(adj, adjAlreadyInvoicedAmount); 578 } else if ("SALES_TAX".equals(adj.getString("orderAdjustmentTypeId"))) { 579 taxAdjustments.put(adj, adjAlreadyInvoicedAmount); 580 } else { 581 BigDecimal adjAmount = calcHeaderAdj(delegator, adj, invoiceType, invoiceId, invoiceItemSeqId, 584 orderSubTotal, invoiceSubTotal, adj.getBigDecimal("amount").setScale(decimals, rounding), decimals, rounding, userLogin, dispatcher, locale); 585 589 invoiceItemSeqNum++; 591 invoiceItemSeqId = UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum, 2); 592 } 593 } 594 595 Iterator shipAdjIter = shipAdjustments.keySet().iterator(); 598 while (shipAdjIter.hasNext()) { 599 GenericValue adj = (GenericValue) shipAdjIter.next(); 600 BigDecimal adjAlreadyInvoicedAmount = (BigDecimal ) shipAdjustments.get(adj); 601 602 if ("N".equalsIgnoreCase(prorateShipping)) { 603 BigDecimal divisor = new BigDecimal ("1"); 605 BigDecimal multiplier = new BigDecimal ("1"); 606 607 BigDecimal baseAmount = adj.getBigDecimal("amount").setScale(decimals, rounding).subtract(adjAlreadyInvoicedAmount); 610 BigDecimal adjAmount = calcHeaderAdj(delegator, adj, invoiceType, invoiceId, invoiceItemSeqId, 611 divisor, multiplier, baseAmount, decimals, rounding, userLogin, dispatcher, locale); 612 } else { 613 BigDecimal divisor = shippableAmount; 615 BigDecimal multiplier = invoiceShipProRateAmount; 616 617 BigDecimal baseAmount = adj.getBigDecimal("amount").setScale(decimals, rounding); 619 BigDecimal adjAmount = calcHeaderAdj(delegator, adj, invoiceType, invoiceId, invoiceItemSeqId, 620 divisor, multiplier, baseAmount, decimals, rounding, userLogin, dispatcher, locale); 621 } 622 623 invoiceItemSeqNum++; 625 invoiceItemSeqId = UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum, 2); 626 } 627 628 String prorateTaxes = productStore.getString("prorateTaxes"); 630 if (prorateTaxes == null) { 631 prorateTaxes = "Y"; 632 } 633 Iterator taxAdjIter = taxAdjustments.keySet().iterator(); 634 while (taxAdjIter.hasNext()) { 635 GenericValue adj = (GenericValue) taxAdjIter.next(); 636 BigDecimal adjAlreadyInvoicedAmount = (BigDecimal ) taxAdjustments.get(adj); 637 BigDecimal adjAmount = null; 638 639 if ("N".equalsIgnoreCase(prorateTaxes)) { 640 641 BigDecimal divisor = new BigDecimal ("1"); 643 BigDecimal multiplier = new BigDecimal ("1"); 644 645 BigDecimal baseAmount = adj.getBigDecimal("amount").setScale(decimals, rounding).subtract(adjAlreadyInvoicedAmount); 649 adjAmount = calcHeaderAdj(delegator, adj, invoiceType, invoiceId, invoiceItemSeqId, 650 divisor, multiplier, baseAmount, decimals, rounding, userLogin, dispatcher, locale); 651 } else { 652 653 BigDecimal divisor = orderSubTotal; 655 BigDecimal multiplier = invoiceSubTotal; 656 657 BigDecimal baseAmount = adj.getBigDecimal("amount").setScale(decimals, rounding); 660 adjAmount = calcHeaderAdj(delegator, adj, invoiceType, invoiceId, invoiceItemSeqId, 661 divisor, multiplier, baseAmount, decimals, rounding, userLogin, dispatcher, locale); 662 } 663 invoiceSubTotal = invoiceSubTotal.add(adjAmount).setScale(decimals, rounding); 664 665 invoiceItemSeqNum++; 667 invoiceItemSeqId = UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum, 2); 668 } 669 670 List orderPaymentPrefs = delegator.findByAnd("OrderPaymentPreference", UtilMisc.toMap("orderId", orderId)); 672 if (orderPaymentPrefs != null) { 673 List currentPayments = new ArrayList(); 674 Iterator opi = orderPaymentPrefs.iterator(); 675 while (opi.hasNext()) { 676 GenericValue paymentPref = (GenericValue) opi.next(); 677 List payments = paymentPref.getRelated("Payment"); 678 currentPayments.addAll(payments); 679 } 680 if (currentPayments.size() > 0) { 681 Iterator cpi = currentPayments.iterator(); 683 while (cpi.hasNext()) { 684 GenericValue payment = (GenericValue) cpi.next(); 685 List currentApplications = null; 686 currentApplications = payment.getRelated("PaymentApplication"); 687 if (currentApplications == null || currentApplications.size() == 0) { 688 Map appl = new HashMap(); 690 appl.put("paymentId", payment.get("paymentId")); 691 appl.put("invoiceId", invoiceId); 692 appl.put("billingAccountId", billingAccountId); 693 appl.put("amountApplied", payment.get("amount")); 694 appl.put("userLogin", userLogin); 695 Map createPayApplResult = dispatcher.runSync("createPaymentApplication", appl); 696 if (ServiceUtil.isError(createPayApplResult)) { 697 return ServiceUtil.returnError("Error creating invoice from order", null, null, createPayApplResult); 698 } 699 } 700 } 701 } 702 } 703 704 String nextStatusId = "INVOICE_READY"; 706 if (invoiceType.equals("PURCHASE_INVOICE")) { 707 nextStatusId = "INVOICE_IN_PROCESS"; 708 } 709 Map setInvoiceStatusResult = dispatcher.runSync("setInvoiceStatus", UtilMisc.toMap("invoiceId", invoiceId, "statusId", nextStatusId, "userLogin", userLogin)); 710 if (ServiceUtil.isError(setInvoiceStatusResult)) { 711 return ServiceUtil.returnError("Error creating invoice from order", null, null, setInvoiceStatusResult); 712 } 713 714 Map checkResp = dispatcher.runSync("checkInvoicePaymentApplications", UtilMisc.toMap("invoiceId", invoiceId, "userLogin", userLogin)); 716 if (ServiceUtil.isError(checkResp)) { 717 return ServiceUtil.returnError("Error creating invoice from order while checking payment applications", null, null, checkResp); 718 } 719 720 Map resp = ServiceUtil.returnSuccess(); 721 resp.put("invoiceId", invoiceId); 722 return resp; 723 } catch (GenericEntityException e) { 724 String errMsg = "Entity/data problem creating invoice from order items: " + e.toString(); 725 Debug.logError(e, errMsg, module); 726 return ServiceUtil.returnError(errMsg); 727 } catch (GenericServiceException e) { 728 String errMsg = "Service/other problem creating invoice from order items: " + e.toString(); 729 Debug.logError(e, errMsg, module); 730 return ServiceUtil.returnError(errMsg); 731 } 732 } 733 734 public static Map createInvoicesFromShipment(DispatchContext dctx, Map context) { 735 GenericDelegator delegator = dctx.getDelegator(); 736 LocalDispatcher dispatcher = dctx.getDispatcher(); 737 String shipmentId = (String ) context.get("shipmentId"); 738 List invoicesCreated = new ArrayList(); 739 Locale locale = (Locale) context.get("locale"); 740 741 Map serviceContext = UtilMisc.toMap("shipmentIds", UtilMisc.toList(shipmentId), "userLogin", context.get("userLogin")); 742 try { 743 Map result = dispatcher.runSync("createInvoicesFromShipments", serviceContext); 744 invoicesCreated = (List)result.get("invoicesCreated"); 745 } catch (GenericServiceException e) { 746 Debug.logError(e, "Trouble calling createInvoicesFromShipment service; invoice not created for shipment [" + shipmentId + "]", module); 747 return ServiceUtil.returnError(UtilProperties.getMessage(resource,"AccountingTroubleCallingCreateInvoicesFromShipmentService",UtilMisc.toMap("shipmentId",shipmentId),locale)); 748 } 749 Map response = ServiceUtil.returnSuccess(); 750 response.put("invoicesCreated", invoicesCreated); 751 return response; 752 } 753 754 public static Map createInvoicesFromShipments(DispatchContext dctx, Map context) { 755 GenericDelegator delegator = dctx.getDelegator(); 756 LocalDispatcher dispatcher = dctx.getDispatcher(); 757 List shipmentIds = (List) context.get("shipmentIds"); 758 Locale locale = (Locale) context.get("locale"); 759 760 boolean salesShipmentFound = false; 761 boolean purchaseShipmentFound = false; 762 763 List invoicesCreated = new ArrayList(); 764 765 List shipmentIdList = new LinkedList(); 766 for (int i = 0; i < shipmentIds.size(); i++) { 767 String tmpShipmentId = (String )shipmentIds.get(i); 768 try { 769 GenericValue shipment = delegator.findByPrimaryKey("Shipment", UtilMisc.toMap("shipmentId", tmpShipmentId)); 770 if ((shipment.getString("shipmentTypeId") != null) && (shipment.getString("shipmentTypeId").equals("PURCHASE_SHIPMENT"))) { 771 purchaseShipmentFound = true; 772 } else { 773 salesShipmentFound = true; 774 } 775 if (purchaseShipmentFound && salesShipmentFound) { 776 return ServiceUtil.returnError("Shipments of different types found; shipment [" + tmpShipmentId + "] of type [" + shipment.getString("shipmentTypeId") + "] is of different type from the previous ones."); 777 } 778 } catch (GenericEntityException e) { 779 Debug.logError(e, "Trouble getting Shipment entity for shipment [" + tmpShipmentId + "]", module); 780 return ServiceUtil.returnError("Trouble getting Shipment entity for shipment [" + tmpShipmentId + "]"); 781 } 782 } 783 EntityCondition shipmentIdsCond = new EntityExpr("shipmentId", EntityOperator.IN, shipmentIds); 784 786 List items = null; 789 try { 790 if (purchaseShipmentFound) { 791 items = delegator.findByCondition("ShipmentReceipt", shipmentIdsCond, null, UtilMisc.toList("shipmentId")); 792 } else { 793 items = delegator.findByCondition("ItemIssuance", shipmentIdsCond, null, UtilMisc.toList("shipmentId")); 794 } 795 } catch (GenericEntityException e) { 796 Debug.logError(e, "Problem getting issued items from shipments", module); 797 return ServiceUtil.returnError("Problem getting issued items from shipments"); 798 } 799 if (items == null) { 800 Debug.logInfo("No items issued for shipments", module); 801 return ServiceUtil.returnSuccess(); 802 } 803 804 Map shippedOrderItems = new HashMap(); 806 Iterator itemsIter = items.iterator(); 807 while (itemsIter.hasNext()) { 808 GenericValue item = (GenericValue) itemsIter.next(); 809 String orderId = item.getString("orderId"); 810 String orderItemSeqId = item.getString("orderItemSeqId"); 811 List itemsByOrder = (List) shippedOrderItems.get(orderId); 812 if (itemsByOrder == null) { 813 itemsByOrder = new ArrayList(); 814 } 815 816 Map billFields = UtilMisc.toMap("orderId", orderId, "orderItemSeqId", orderItemSeqId); 818 if (item.getEntityName().equals("ItemIssuance")) { 819 billFields.put("itemIssuanceId", item.get("itemIssuanceId")); 820 } else if (item.getEntityName().equals("ShipmentReceipt")) { 821 billFields.put("shipmentReceiptId", item.getString("receiptId")); 822 } 823 List itemBillings = null; 824 try { 825 itemBillings = delegator.findByAnd("OrderItemBilling", billFields); 826 } catch (GenericEntityException e) { 827 Debug.logError(e, "Problem looking up OrderItemBilling records for : " + billFields, module); 828 return ServiceUtil.returnError("Problem getting OrderItemBilling records"); 829 } 830 831 if (itemBillings == null || itemBillings.size() == 0) { 833 itemsByOrder.add(item); 834 } 835 836 shippedOrderItems.put(orderId, itemsByOrder); 838 } 839 840 Set orders = shippedOrderItems.keySet(); 842 Iterator ordersIter = orders.iterator(); 843 while (ordersIter.hasNext()) { 844 String orderId = (String ) ordersIter.next(); 845 846 List billItems = (List) shippedOrderItems.get(orderId); 848 849 List toBillItems = new ArrayList(); 851 852 Map itemQtyAvail = new HashMap(); 854 855 Iterator billIt = billItems.iterator(); 857 while (billIt.hasNext()) { 858 GenericValue issue = (GenericValue) billIt.next(); 859 BigDecimal issueQty = ZERO; 860 if (issue.getEntityName().equals("ShipmentReceipt")) { 861 issueQty = issue.getBigDecimal("quantityAccepted"); 862 } else { 863 issueQty = issue.getBigDecimal("quantity"); 864 } 865 866 BigDecimal billAvail = (BigDecimal ) itemQtyAvail.get(issue.getString("orderItemSeqId")); 867 if (billAvail == null) { 868 Map lookup = UtilMisc.toMap("orderId", orderId, "orderItemSeqId", issue.get("orderItemSeqId")); 869 GenericValue orderItem = null; 870 List billed = null; 871 try { 872 orderItem = issue.getRelatedOne("OrderItem"); 873 billed = delegator.findByAnd("OrderItemBilling", lookup); 874 } catch (GenericEntityException e) { 875 Debug.logError(e, "Problem looking up OrderItem/OrderItemBilling records for : " + lookup, module); 876 return ServiceUtil.returnError("Problem getting OrderItem/OrderItemBilling records"); 877 } 878 879 BigDecimal orderedQty = orderItem.getBigDecimal("quantity"); 881 882 if (billed != null && billed.size() > 0) { 884 BigDecimal billedQuantity = ZERO; 885 Iterator bi = billed.iterator(); 886 while (bi.hasNext()) { 887 GenericValue oib = (GenericValue) bi.next(); 888 BigDecimal qty = oib.getBigDecimal("quantity"); 889 if (qty != null) { 890 billedQuantity = billedQuantity.add(qty).setScale(decimals, rounding); 891 } 892 } 893 BigDecimal leftToBill = orderedQty.subtract(billedQuantity).setScale(decimals, rounding); 894 billAvail = leftToBill; 895 } else { 896 billAvail = orderedQty; 897 } 898 } 899 900 if (billAvail != null && billAvail.signum() == 1) { if (issueQty != null && issueQty.doubleValue() > billAvail.doubleValue()) { 903 issue.set("quantity", new Double (billAvail.doubleValue())); 905 billAvail = ZERO; 906 } else { 907 billAvail = billAvail.subtract(issueQty).setScale(decimals, rounding); 909 } 910 911 toBillItems.add(issue); 913 } 914 915 itemQtyAvail.put(issue.getString("orderItemSeqId"), billAvail); 917 } 918 919 OrderReadHelper orh = new OrderReadHelper(delegator, orderId); 920 GenericValue productStore = orh.getProductStore(); 921 922 if (productStore.getString("prorateShipping").equals("N")) { 924 925 List invoiceableShipmentIds = EntityUtil.getFieldListFromEntityList(toBillItems, "shipmentId", true); 927 List invoiceableShipments = null; 928 try { 929 invoiceableShipments = delegator.findByCondition("Shipment", new EntityExpr("shipmentId", EntityOperator.IN, invoiceableShipmentIds), null, null); 930 } catch( GenericEntityException e ) { 931 String errMsg = UtilProperties.getMessage(resource, "AccountingTroubleCallingCreateInvoicesFromShipmentsService", locale); 932 Debug.logError(e, errMsg, module); 933 return ServiceUtil.returnError(errMsg); 934 } 935 936 Map additionalShippingCharges = new HashMap(); 938 BigDecimal totalAdditionalShippingCharges = ZERO; 939 Iterator isit = invoiceableShipments.iterator(); 940 while(isit.hasNext()) { 941 GenericValue shipment = (GenericValue) isit.next(); 942 if (shipment.get("additionalShippingCharge") == null) continue; 943 BigDecimal shipmentAdditionalShippingCharges = shipment.getBigDecimal("additionalShippingCharge").setScale(decimals, rounding); 944 additionalShippingCharges.put(shipment, shipmentAdditionalShippingCharges); 945 totalAdditionalShippingCharges = totalAdditionalShippingCharges.add(shipmentAdditionalShippingCharges); 946 } 947 948 if (totalAdditionalShippingCharges.signum() == 1) { 950 951 Iterator ascit = additionalShippingCharges.keySet().iterator(); 953 while (ascit.hasNext()) { 954 GenericValue shipment = (GenericValue) ascit.next(); 955 String shipmentId = shipment.getString("shipmentId"); 956 BigDecimal additionalShippingCharge = (BigDecimal ) additionalShippingCharges.get(shipment); 957 Map createOrderAdjustmentContext = new HashMap(); 958 createOrderAdjustmentContext.put("orderId", orderId); 959 createOrderAdjustmentContext.put("orderAdjustmentTypeId", "SHIPPING_CHARGES"); 960 createOrderAdjustmentContext.put("description", UtilProperties.getMessage(resource, "AccountingAdditionalShippingChargeForShipment", locale) + " #" + shipmentId); 961 createOrderAdjustmentContext.put("sourceReferenceId", shipmentId); 962 createOrderAdjustmentContext.put("amount", new Double (additionalShippingCharge.doubleValue())); 963 createOrderAdjustmentContext.put("userLogin", context.get("userLogin")); 964 String shippingOrderAdjustmentId = null; 965 try { 966 Map createOrderAdjustmentResult = dispatcher.runSync("createOrderAdjustment", createOrderAdjustmentContext); 967 shippingOrderAdjustmentId = (String ) createOrderAdjustmentResult.get("orderAdjustmentId"); 968 } catch (GenericServiceException e) { 969 String errMsg = UtilProperties.getMessage(resource, "AccountingTroubleCallingCreateOrderAdjustmentService", locale); 970 Debug.logError(e, errMsg, module); 971 return ServiceUtil.returnError(errMsg); 972 } 973 974 GenericValue billToParty = orh.getBillToParty(); 976 GenericValue destinationContactMech = null; 977 try { 978 destinationContactMech = shipment.getRelatedOne("DestinationPostalAddress"); 979 } catch( GenericEntityException e ) { 980 String errMsg = UtilProperties.getMessage(resource, "AccountingTroubleCallingCreateInvoicesFromShipmentService", locale); 981 Debug.logError(e, errMsg, module); 982 return ServiceUtil.returnError(errMsg); 983 } 984 985 List emptyList = new ArrayList(); 986 Map calcTaxContext = new HashMap(); 987 calcTaxContext.put("productStoreId", orh.getProductStoreId()); 988 calcTaxContext.put("billToPartyId", billToParty.getString("partyId")); 989 calcTaxContext.put("orderShippingAmount", totalAdditionalShippingCharges); 990 calcTaxContext.put("shippingAddress", destinationContactMech); 991 992 calcTaxContext.put("itemProductList", emptyList); 994 calcTaxContext.put("itemAmountList", emptyList); 995 calcTaxContext.put("itemPriceList", emptyList); 996 calcTaxContext.put("itemShippingList", emptyList); 997 998 List orderAdjustments = null; 999 Map calcTaxResult = null; 1000 try { 1001 calcTaxResult = dispatcher.runSync("calcTax", calcTaxContext); 1002 } catch (GenericServiceException e) { 1003 String errMsg = UtilProperties.getMessage(resource, "AccountingTroubleCallingCalcTaxService", locale); 1004 Debug.logError(e, errMsg, module); 1005 return ServiceUtil.returnError(errMsg); 1006 } 1007 orderAdjustments = (List) calcTaxResult.get("orderAdjustments"); 1008 1009 if (calcTaxResult != null && orderAdjustments != null) { 1011 Iterator oait = orderAdjustments.iterator(); 1012 while (oait.hasNext()) { 1013 GenericValue orderAdjustment = (GenericValue) oait.next(); 1014 totalAdditionalShippingCharges = totalAdditionalShippingCharges.add(orderAdjustment.getBigDecimal("amount").setScale(decimals, rounding)); 1015 orderAdjustment.set("orderAdjustmentId", delegator.getNextSeqId("OrderAdjustment")); 1016 orderAdjustment.set("orderId", orderId); 1017 orderAdjustment.set("orderItemSeqId", "_NA_"); 1018 orderAdjustment.set("shipGroupSeqId", shipment.getString("primaryShipGroupSeqId")); 1019 orderAdjustment.set("originalAdjustmentId", shippingOrderAdjustmentId); 1020 } 1021 try { 1022 delegator.storeAll(orderAdjustments); 1023 } catch( GenericEntityException e ) { 1024 String errMsg = UtilProperties.getMessage(resource, "AccountingProblemStoringOrderAdjustments", UtilMisc.toMap("orderAdjustments", orderAdjustments), locale); 1025 Debug.logError(e, errMsg, module); 1026 return ServiceUtil.returnError(errMsg); 1027 } 1028 } 1029 1030 List orderPaymentPreferences = new ArrayList(); 1032 try { 1033 orderPaymentPreferences = delegator.findByAnd("OrderPaymentPreference", UtilMisc.toMap("orderId", orderId, "paymentMethodTypeId", "CREDIT_CARD")); 1034 } catch( GenericEntityException e ) { 1035 String errMsg = UtilProperties.getMessage(resource, "AccountingProblemGettingOrderPaymentPreferences", locale); 1036 Debug.logError(e, errMsg, module); 1037 return ServiceUtil.returnError(errMsg); 1038 } 1039 1040 String paymentMethodId = null; 1042 GenericValue cardOrderPaymentPref = EntityUtil.getFirst(orderPaymentPreferences); 1043 if (cardOrderPaymentPref != null) { 1044 paymentMethodId = cardOrderPaymentPref.getString("paymentMethodId"); 1045 } 1046 1047 if (paymentMethodId != null ) { 1048 1049 BigDecimal totalNewAuthAmount = new BigDecimal (totalAdditionalShippingCharges.doubleValue()).setScale(decimals, rounding); 1053 Iterator oppit = orderPaymentPreferences.iterator(); 1054 while (oppit.hasNext()) { 1055 GenericValue orderPaymentPreference = (GenericValue) oppit.next(); 1056 if (! (orderPaymentPreference.getString("statusId").equals("PAYMENT_SETTLED") || orderPaymentPreference.getString("statusId").equals("PAYMENT_CANCELLED"))) { 1057 GenericValue authTransaction = PaymentGatewayServices.getAuthTransaction(orderPaymentPreference); 1058 if (authTransaction != null && authTransaction.get("amount") != null) { 1059 1060 totalNewAuthAmount = totalNewAuthAmount.add(authTransaction.getBigDecimal("amount").setScale(decimals, rounding)); 1062 1063 Map prefReleaseResult = null; 1065 try { 1066 prefReleaseResult = dispatcher.runSync("releaseOrderPaymentPreference", UtilMisc.toMap("orderPaymentPreferenceId", orderPaymentPreference.getString("orderPaymentPreferenceId"), "userLogin", context.get("userLogin"))); 1067 } catch( GenericServiceException e ) { 1068 String errMsg = UtilProperties.getMessage(resource, "AccountingTroubleCallingReleaseOrderPaymentPreferenceService", locale); 1069 Debug.logError(e, errMsg, module); 1070 return ServiceUtil.returnError(errMsg); 1071 } 1072 if (ServiceUtil.isError(prefReleaseResult) || ServiceUtil.isFailure(prefReleaseResult)) { 1073 String errMsg = ServiceUtil.getErrorMessage(prefReleaseResult); 1074 Debug.logError(errMsg, module); 1075 return ServiceUtil.returnError(errMsg); 1076 } 1077 } 1078 } 1079 } 1080 1081 Map serviceContext = UtilMisc.toMap("orderId", orderId, "paymentMethodId", paymentMethodId, "paymentMethodTypeId", "CREDIT_CARD", "userLogin", context.get("userLogin")); 1084 String orderPaymentPreferenceId = null; 1085 try { 1086 Map result = dispatcher.runSync("createOrderPaymentPreference", serviceContext); 1087 orderPaymentPreferenceId = (String ) result.get("orderPaymentPreferenceId"); 1088 } catch (GenericServiceException e) { 1089 String errMsg = UtilProperties.getMessage(resource, "AccountingTroubleCallingCreateOrderPaymentPreferenceService", locale); 1090 Debug.logError(e, errMsg, module); 1091 return ServiceUtil.returnError(errMsg); 1092 } 1093 1094 Map authResult = null; 1096 try { 1097 1098 authResult = dispatcher.runSync("authOrderPaymentPreference", UtilMisc.toMap("orderPaymentPreferenceId", orderPaymentPreferenceId, "overrideAmount", new Double (totalNewAuthAmount.doubleValue()), "userLogin", context.get("userLogin"))); 1100 } catch (GenericServiceException e) { 1101 String errMsg = UtilProperties.getMessage(resource, "AccountingTroubleCallingAuthOrderPaymentPreferenceService", locale); 1102 Debug.logError(e, errMsg, module); 1103 return ServiceUtil.returnError(errMsg); 1104 } 1105 1106 boolean authFinished = ( (Boolean ) authResult.get("finished") ).booleanValue(); 1108 boolean authErrors = ( (Boolean ) authResult.get("errors") ).booleanValue(); 1109 if (authErrors || ! authFinished) { 1110 String errMsg = UtilProperties.getMessage(resource, "AccountingUnableToAuthAdditionalShipCharges", UtilMisc.toMap("shipmentId", shipmentId, "paymentMethodId", paymentMethodId, "orderPaymentPreferenceId", orderPaymentPreferenceId), locale); 1111 Debug.logError(errMsg, module); 1112 } 1113 1114 } 1115 } 1116 } 1117 } 1118 1119 Map serviceContext = UtilMisc.toMap("orderId", orderId, "billItems", toBillItems, "userLogin", context.get("userLogin")); 1121 try { 1122 Map result = dispatcher.runSync("createInvoiceForOrder", serviceContext); 1123 invoicesCreated.add(result.get("invoiceId")); 1124 } catch (GenericServiceException e) { 1125 Debug.logError(e, "Trouble calling createInvoiceForOrder service; invoice not created for shipment", module); 1126 return ServiceUtil.returnError("Trouble calling createInvoiceForOrder service; invoice not created for shipment"); 1127 } 1128 } 1129 1130 Map response = ServiceUtil.returnSuccess(); 1131 response.put("invoicesCreated", invoicesCreated); 1132 return response; 1133 } 1134 1135 private static String getInvoiceItemType(GenericDelegator delegator, String key, String invoiceTypeId, String defaultValue) { 1136 GenericValue itemMap = null; 1137 try { 1138 itemMap = delegator.findByPrimaryKey("InvoiceItemTypeMap", UtilMisc.toMap("invoiceItemMapKey", key, "invoiceTypeId", invoiceTypeId)); 1139 } catch (GenericEntityException e) { 1140 Debug.logError(e, "Trouble getting InvoiceItemTypeMap entity", module); 1141 return defaultValue; 1142 } 1143 if (itemMap != null) { 1144 return itemMap.getString("invoiceItemTypeId"); 1145 } else { 1146 return defaultValue; 1147 } 1148 } 1149 1150 public static Map createInvoicesFromReturnShipment(DispatchContext dctx, Map context) { 1151 GenericDelegator delegator = dctx.getDelegator(); 1152 LocalDispatcher dispatcher = dctx.getDispatcher(); 1153 1154 String shipmentId = (String ) context.get("shipmentId"); 1155 String errorMsg = "Error creating invoice for shipment [" + shipmentId + "]. "; 1156 List invoicesCreated = new ArrayList(); 1157 try { 1158 1159 GenericValue shipment = delegator.findByPrimaryKey("Shipment", UtilMisc.toMap("shipmentId", shipmentId)); 1161 if (shipment == null) { 1162 return ServiceUtil.returnError(errorMsg + "Shipment not found."); 1163 } 1164 if (!shipment.getString("shipmentTypeId").equals("SALES_RETURN")) { 1165 return ServiceUtil.returnError(errorMsg + "Shipment is not of type SALES_RETURN."); 1166 } 1167 1168 List shipmentReceipts = shipment.getRelated("ShipmentReceipt"); 1170 1171 Map receiptsGroupedByReturn = new HashMap(); 1173 for (Iterator iter = shipmentReceipts.iterator(); iter.hasNext(); ) { 1174 GenericValue receipt = (GenericValue) iter.next(); 1175 String returnId = receipt.getString("returnId"); 1176 1177 List billings = delegator.findByAnd("ReturnItemBilling", UtilMisc.toMap("shipmentReceiptId", receipt.getString("receiptId"), "returnId", returnId, 1179 "returnItemSeqId", receipt.get("returnItemSeqId"))); 1180 1181 if (billings.size() > 0) continue; 1183 1184 List receipts = (List) receiptsGroupedByReturn.get(returnId); 1186 if (receipts == null) { 1187 receipts = new ArrayList(); 1188 } 1189 1190 receipts.add(receipt); 1192 receiptsGroupedByReturn.put(returnId, receipts); 1193 } 1194 1195 for (Iterator iter = receiptsGroupedByReturn.keySet().iterator(); iter.hasNext(); ) { 1197 String returnId = (String ) iter.next(); 1198 List receipts = (List) receiptsGroupedByReturn.get(returnId); 1199 if (Debug.verboseOn()) { 1200 Debug.logVerbose("Creating invoice for return [" + returnId + "] with receipts: " + receipts.toString(), module); 1201 } 1202 Map input = UtilMisc.toMap("returnId", returnId, "shipmentReceiptsToBill", receipts, "userLogin", context.get("userLogin")); 1203 Map serviceResults = dispatcher.runSync("createInvoiceFromReturn", input); 1204 if (ServiceUtil.isError(serviceResults)) { 1205 return ServiceUtil.returnError(errorMsg, null, null, serviceResults); 1206 } 1207 1208 invoicesCreated.add(serviceResults.get("invoiceId")); 1210 } 1211 } catch (GenericServiceException e) { 1212 Debug.logError(e, errorMsg + e.getMessage(), module); 1213 return ServiceUtil.returnError(errorMsg + e.getMessage()); 1214 } catch (GenericEntityException e) { 1215 Debug.logError(e, errorMsg + e.getMessage(), module); 1216 return ServiceUtil.returnError(errorMsg + e.getMessage()); 1217 } 1218 1219 Map result = ServiceUtil.returnSuccess(); 1220 result.put("invoicesCreated", invoicesCreated); 1221 return result; 1222 } 1223 1224 public static Map createInvoiceFromReturn(DispatchContext dctx, Map context) { 1225 GenericDelegator delegator = dctx.getDelegator(); 1226 LocalDispatcher dispatcher = dctx.getDispatcher(); 1227 GenericValue userLogin = (GenericValue) context.get("userLogin"); 1228 1229 String returnId= (String ) context.get("returnId"); 1230 List receipts = (List) context.get("shipmentReceiptsToBill"); 1231 String errorMsg = "Error creating invoice for return [" + returnId + "]. "; 1232 List invoicesCreated = new ArrayList(); 1233 try { 1234 GenericValue returnHeader = delegator.findByPrimaryKey("ReturnHeader", UtilMisc.toMap("returnId", returnId)); 1236 1237 Map input = UtilMisc.toMap("invoiceTypeId", "CUST_RTN_INVOICE", "statusId", "INVOICE_IN_PROCESS"); 1239 input.put("partyId", returnHeader.get("toPartyId")); 1240 input.put("partyIdFrom", returnHeader.get("fromPartyId")); 1241 input.put("currencyUomId", returnHeader.get("currencyUomId")); 1242 input.put("invoiceDate", UtilDateTime.nowTimestamp()); 1243 input.put("billingAccountId", returnHeader.get("billingAccountId")); 1244 input.put("userLogin", userLogin); 1245 1246 Map serviceResults = dispatcher.runSync("createInvoice", input); 1248 if (ServiceUtil.isError(serviceResults)) { 1249 return ServiceUtil.returnError(errorMsg, null, null, serviceResults); 1250 } 1251 String invoiceId = (String ) serviceResults.get("invoiceId"); 1252 1253 BigDecimal invoiceTotal = ZERO; 1255 BigDecimal promisedTotal = ZERO; 1256 1257 int invoiceItemSeqNum = 1; 1259 String invoiceItemSeqId = UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum, 2); 1260 for (Iterator iter = receipts.iterator(); iter.hasNext(); ) { 1261 GenericValue receipt = (GenericValue) iter.next(); 1262 1263 GenericValue returnItem = receipt.getRelatedOneCache("ReturnItem"); 1265 GenericValue product = returnItem.getRelatedOneCache("Product"); 1266 1267 BigDecimal returnPrice = returnItem.getBigDecimal("returnPrice"); 1269 1270 String invoiceItemTypeId = getInvoiceItemType(delegator, returnItem.getString("returnItemTypeId"), "CUST_RTN_INVOICE", null); 1272 if (invoiceItemTypeId == null) { 1273 return ServiceUtil.returnError(errorMsg + "No known invoice item type for the return item type [" 1274 + returnItem.getString("returnItemTypeId") + "]"); 1275 } 1276 1277 input = UtilMisc.toMap("invoiceId", invoiceId, "invoiceItemTypeId", invoiceItemTypeId, "quantity", receipt.get("quantityAccepted")); 1279 input.put("invoiceItemSeqId", "" + invoiceItemSeqId); input.put("amount", returnItem.get("returnPrice")); input.put("productId", returnItem.get("productId")); 1282 input.put("taxableFlag", product.get("taxable")); 1283 input.put("description", returnItem.get("description")); 1284 input.put("userLogin", userLogin); 1286 serviceResults = dispatcher.runSync("createInvoiceItem", input); 1287 if (ServiceUtil.isError(serviceResults)) { 1288 return ServiceUtil.returnError(errorMsg, null, null, serviceResults); 1289 } 1290 1291 input = UtilMisc.toMap("returnId", returnId, "returnItemSeqId", returnItem.get("returnItemSeqId"), 1293 "invoiceId", invoiceId); 1294 input.put("invoiceItemSeqId", "" + invoiceItemSeqId); input.put("shipmentReceiptId", receipt.get("receiptId")); 1296 input.put("quantity", receipt.get("quantityAccepted")); 1297 input.put("amount", returnItem.get("returnPrice")); input.put("userLogin", userLogin); 1299 serviceResults = dispatcher.runSync("createReturnItemBilling", input); 1300 if (ServiceUtil.isError(serviceResults)) { 1301 return ServiceUtil.returnError(errorMsg, null, null, serviceResults); 1302 } 1303 if (Debug.verboseOn()) { 1304 Debug.logVerbose("Creating Invoice Item with amount " + returnPrice + " and quantity " + receipt.getBigDecimal("quantityAccepted") 1305 + " for shipment receipt [" + receipt.getString("receiptId") + "]", module); 1306 } 1307 1308 invoiceItemSeqNum += 1; 1310 invoiceItemSeqId = UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum, 2); 1311 1312 BigDecimal actualAmount = returnPrice.multiply(receipt.getBigDecimal("quantityAccepted")).setScale(decimals, rounding); 1314 BigDecimal promisedAmount = returnPrice.multiply(receipt.getBigDecimal("quantityAccepted").add(receipt.getBigDecimal("quantityRejected"))).setScale(decimals, rounding); 1315 invoiceTotal = invoiceTotal.add(actualAmount).setScale(decimals, rounding); 1316 promisedTotal = promisedTotal.add(promisedAmount).setScale(decimals, rounding); 1317 1318 List adjustments = returnItem.getRelatedCache("ReturnAdjustment"); 1320 for (Iterator adjIter = adjustments.iterator(); adjIter.hasNext(); ) { 1321 GenericValue adjustment = (GenericValue) adjIter.next(); 1322 1323 invoiceItemTypeId = getInvoiceItemType(delegator, adjustment.getString("returnAdjustmentTypeId"), "CUST_RTN_INVOICE", null); 1325 if (invoiceItemTypeId == null) { 1326 return ServiceUtil.returnError(errorMsg + "No known invoice item type for the return adjustment type [" 1327 + adjustment.getString("returnAdjustmentTypeId") + "]"); 1328 } 1329 1330 BigDecimal ratio = receipt.getBigDecimal("quantityAccepted").divide(returnItem.getBigDecimal("returnQuantity"), 100, rounding); 1332 BigDecimal amount = adjustment.getBigDecimal("amount"); 1333 amount = amount.multiply(ratio).setScale(decimals, rounding); 1334 if (Debug.verboseOn()) { 1335 Debug.logVerbose("Creating Invoice Item with amount " + adjustment.getBigDecimal("amount") + " prorated to " + amount 1336 + " for return adjustment [" + adjustment.getString("returnAdjustmentId") + "]", module); 1337 } 1338 1339 input = UtilMisc.toMap("invoiceId", invoiceId, "invoiceItemTypeId", invoiceItemTypeId, "quantity", new Double (1.0)); 1341 input.put("amount", new Double (amount.doubleValue())); 1342 input.put("invoiceItemSeqId", "" + invoiceItemSeqId); input.put("productId", returnItem.get("productId")); 1344 input.put("description", adjustment.get("description")); 1345 input.put("overrideGlAccountId", adjustment.get("overrideGlAccountId")); 1346 input.put("taxAuthPartyId", adjustment.get("taxAuthPartyId")); 1347 input.put("taxAuthGeoId", adjustment.get("taxAuthGeoId")); 1348 input.put("userLogin", userLogin); 1349 1350 if (adjustment.get("returnAdjustmentTypeId").equals("RET_SALES_TAX_ADJ")) { 1353 input.put("taxableFlag", "N"); 1354 } 1355 1356 serviceResults = dispatcher.runSync("createInvoiceItem", input); 1358 if (ServiceUtil.isError(serviceResults)) { 1359 return ServiceUtil.returnError(errorMsg, null, null, serviceResults); 1360 } 1361 1362 invoiceItemSeqNum += 1; 1364 invoiceItemSeqId = UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum, 2); 1365 1366 invoiceTotal = invoiceTotal.add(amount).setScale(decimals, rounding); 1368 promisedTotal = promisedTotal.add(amount).setScale(decimals, rounding); 1369 } 1370 } 1371 1372 BigDecimal actualToPromisedRatio = ZERO; 1374 if (invoiceTotal.signum() != 0) { 1375 actualToPromisedRatio = invoiceTotal.divide(promisedTotal, 100, rounding); } 1377 1378 List adjustments = returnHeader.getRelatedByAndCache("ReturnAdjustment", UtilMisc.toMap("returnItemSeqId", "_NA_")); 1380 for (Iterator iter = adjustments.iterator(); iter.hasNext(); ) { 1381 GenericValue adjustment = (GenericValue) iter.next(); 1382 1383 String invoiceItemTypeId = getInvoiceItemType(delegator, adjustment.getString("returnAdjustmentTypeId"), "CUST_RTN_INVOICE", null); 1385 if (invoiceItemTypeId == null) { 1386 return ServiceUtil.returnError(errorMsg + "No known invoice item type for the return adjustment type [" 1387 + adjustment.getString("returnAdjustmentTypeId") + "]"); 1388 } 1389 1390 BigDecimal amount = adjustment.getBigDecimal("amount").multiply(actualToPromisedRatio).setScale(decimals, rounding); 1392 if (Debug.verboseOn()) { 1393 Debug.logVerbose("Creating Invoice Item with amount " + adjustment.getBigDecimal("amount") + " prorated to " + amount 1394 + " for return adjustment [" + adjustment.getString("returnAdjustmentId") + "]", module); 1395 } 1396 1397 input = UtilMisc.toMap("invoiceId", invoiceId, "invoiceItemTypeId", invoiceItemTypeId, "quantity", new Double (1.0)); 1399 input.put("amount", new Double (amount.doubleValue())); 1400 input.put("invoiceItemSeqId", "" + invoiceItemSeqId); input.put("description", adjustment.get("description")); 1402 input.put("overrideGlAccountId", adjustment.get("overrideGlAccountId")); 1403 input.put("taxAuthPartyId", adjustment.get("taxAuthPartyId")); 1404 input.put("taxAuthGeoId", adjustment.get("taxAuthGeoId")); 1405 input.put("userLogin", userLogin); 1406 1407 input.put("taxableFlag", adjustment.get("includeInTax")); 1409 1410 serviceResults = dispatcher.runSync("createInvoiceItem", input); 1412 if (ServiceUtil.isError(serviceResults)) { 1413 return ServiceUtil.returnError(errorMsg, null, null, serviceResults); 1414 } 1415 1416 invoiceItemSeqNum += 1; 1418 invoiceItemSeqId = UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum, 2); 1419 } 1420 1421 serviceResults = dispatcher.runSync("setInvoiceStatus", UtilMisc.toMap("invoiceId", invoiceId, "statusId", "INVOICE_READY", "userLogin", userLogin)); 1423 if (ServiceUtil.isError(serviceResults)) { 1424 return ServiceUtil.returnError(errorMsg, null, null, serviceResults); 1425 } 1426 1427 Map results = ServiceUtil.returnSuccess(); 1429 results.put("invoiceId", invoiceId); 1430 return results; 1431 } catch (GenericServiceException e) { 1432 Debug.logError(e, errorMsg + e.getMessage(), module); 1433 return ServiceUtil.returnError(errorMsg + e.getMessage()); 1434 } catch (GenericEntityException e) { 1435 Debug.logError(e, errorMsg + e.getMessage(), module); 1436 return ServiceUtil.returnError(errorMsg + e.getMessage()); 1437 } 1438 } 1439 1440 public static Map checkInvoicePaymentApplications(DispatchContext ctx, Map context) { 1441 GenericDelegator delegator = ctx.getDelegator(); 1442 LocalDispatcher dispatcher = ctx.getDispatcher(); 1443 GenericValue userLogin = (GenericValue) context.get("userLogin"); 1444 1445 if (decimals == -1 || rounding == -1) { 1446 return ServiceUtil.returnError("Arithmetic properties for Invoice services not configured properly. Cannot proceed."); 1447 } 1448 1449 String invoiceId = (String ) context.get("invoiceId"); 1450 GenericValue invoice = null ; 1451 try { 1452 invoice = delegator.findByPrimaryKey("Invoice", UtilMisc.toMap("invoiceId", invoiceId)); 1453 } catch( GenericEntityException e ) { 1454 Debug.logError(e, "Problem getting Invoice for Invoice ID" + invoiceId, module); 1455 return ServiceUtil.returnError("Problem getting Invoice for Invoice ID" + invoiceId); 1456 } 1457 1458 if (! invoice.getString("statusId").equals("INVOICE_READY")) { 1460 return ServiceUtil.returnSuccess(); 1461 } 1462 1463 List paymentAppl = null; 1464 try { 1465 paymentAppl = delegator.findByAnd("PaymentApplication", UtilMisc.toMap("invoiceId", invoiceId)); 1466 } catch (GenericEntityException e) { 1467 Debug.logError(e, "Problem getting PaymentApplication(s) for Invoice #" + invoiceId, module); 1468 return ServiceUtil.returnError("Problem getting PaymentApplication(s) for Invoice #" + invoiceId); 1469 } 1470 1471 Map payments = new HashMap(); 1472 Timestamp paidDate = null; 1473 if (paymentAppl != null) { 1474 Iterator pai = paymentAppl.iterator(); 1475 while (pai.hasNext()) { 1476 GenericValue payAppl = (GenericValue) pai.next(); 1477 payments.put(payAppl.getString("paymentId"), payAppl.getBigDecimal("amountApplied")); 1478 1479 try { 1481 GenericValue Payment = payAppl.getRelatedOne("Payment"); 1482 Timestamp paymentDate = Payment.getTimestamp("effectiveDate"); 1483 if (paymentDate != null) { 1484 if ((paidDate == null) || (paidDate.before(paymentDate))) { 1485 paidDate = paymentDate; 1486 } 1487 } 1488 } catch (GenericEntityException ex) { 1489 Debug.logError(ex, "Cannot get payment for application [" + payAppl + "]", module); 1490 return ServiceUtil.returnError("Cannot get payment for application [" + payAppl + "] due to " + ex.getMessage()); 1491 } 1492 1493 } 1494 } 1495 1496 BigDecimal totalPayments = ZERO; 1497 Iterator pi = payments.keySet().iterator(); 1498 while (pi.hasNext()) { 1499 String paymentId = (String ) pi.next(); 1500 BigDecimal amount = (BigDecimal ) payments.get(paymentId); 1501 if (amount == null) amount = ZERO; 1502 totalPayments = totalPayments.add(amount).setScale(decimals, rounding); 1503 } 1504 1505 if (totalPayments.signum() == 1) { 1506 BigDecimal invoiceTotal = InvoiceWorker.getInvoiceTotalBd(delegator, invoiceId); 1507 if (Debug.verboseOn()) { 1508 Debug.logVerbose("Invoice #" + invoiceId + " total: " + invoiceTotal, module); 1509 Debug.logVerbose("Total payments : " + totalPayments, module); 1510 } 1511 if (totalPayments.compareTo(invoiceTotal) >= 0) { Map svcCtx = UtilMisc.toMap("statusId", "INVOICE_PAID", "invoiceId", invoiceId, 1514 "paidDate", paidDate, "userLogin", userLogin); 1515 try { 1516 dispatcher.runSync("setInvoiceStatus", svcCtx); 1517 } catch (GenericServiceException e) { 1518 Debug.logError(e, "Problem changing invoice status : " + svcCtx, module); 1519 return ServiceUtil.returnError("Problem changing invoice status"); 1520 } 1521 } 1522 } else { 1523 Debug.log("No payments found for Invoice #" + invoiceId, module); 1524 } 1525 1526 return ServiceUtil.returnSuccess(); 1527 } 1528 1529 private static BigDecimal calcHeaderAdj(GenericDelegator delegator, GenericValue adj, String invoiceTypeId, String invoiceId, String invoiceItemSeqId, 1530 BigDecimal divisor, BigDecimal multiplier, BigDecimal baseAmount, int decimals, int rounding, GenericValue userLogin, LocalDispatcher dispatcher, Locale locale) { 1531 BigDecimal adjAmount = ZERO; 1532 if (adj.get("amount") != null) { 1533 1534 BigDecimal baseAdjAmount = adj.getBigDecimal("amount"); 1536 BigDecimal amount = ZERO; 1537 if (divisor.signum() != 0) { 1539 amount = baseAmount.multiply(multiplier).divide(divisor, decimals, rounding); 1541 } 1542 if (amount.signum() != 0) { 1543 Map createInvoiceItemContext = FastMap.newInstance(); 1544 createInvoiceItemContext.put("invoiceId", invoiceId); 1545 createInvoiceItemContext.put("invoiceItemSeqId", invoiceItemSeqId); 1546 createInvoiceItemContext.put("invoiceItemTypeId", getInvoiceItemType(delegator, adj.getString("orderAdjustmentTypeId"), invoiceTypeId, "INVOICE_ADJ")); 1547 createInvoiceItemContext.put("description", adj.get("description")); 1548 createInvoiceItemContext.put("quantity", new Double (1)); 1549 createInvoiceItemContext.put("amount", new Double (amount.doubleValue())); 1550 createInvoiceItemContext.put("overrideGlAccountId", adj.get("overrideGlAccountId")); 1551 createInvoiceItemContext.put("taxAuthPartyId", adj.get("taxAuthPartyId")); 1556 createInvoiceItemContext.put("taxAuthGeoId", adj.get("taxAuthGeoId")); 1557 createInvoiceItemContext.put("taxAuthorityRateSeqId", adj.get("taxAuthorityRateSeqId")); 1558 createInvoiceItemContext.put("userLogin", userLogin); 1559 1560 Map createInvoiceItemResult = null; 1561 try { 1562 createInvoiceItemResult = dispatcher.runSync("createInvoiceItem", createInvoiceItemContext); 1563 } catch( GenericServiceException e ) { 1564 String errMsg = "Service/other problem creating InvoiceItem from order header adjustment: " + e.toString(); 1565 Debug.logError(e, errMsg, module); 1566 ServiceUtil.returnError(errMsg); 1567 } 1568 if (ServiceUtil.isError(createInvoiceItemResult)) { 1569 ServiceUtil.returnError("Error creating InvoiceItem from order header adjustment", null, null, createInvoiceItemResult); 1570 } 1571 1572 Map createOrderAdjustmentBillingContext = FastMap.newInstance(); 1574 createOrderAdjustmentBillingContext.put("orderAdjustmentId", adj.getString("orderAdjustmentId")); 1575 createOrderAdjustmentBillingContext.put("invoiceId", invoiceId); 1576 createOrderAdjustmentBillingContext.put("invoiceItemSeqId", invoiceItemSeqId); 1577 createOrderAdjustmentBillingContext.put("amount", new Double (amount.doubleValue())); 1578 createOrderAdjustmentBillingContext.put("userLogin", userLogin); 1579 1580 try { 1581 Map createOrderAdjustmentBillingResult = dispatcher.runSync("createOrderAdjustmentBilling", createOrderAdjustmentBillingContext); 1582 } catch( GenericServiceException e ) { 1583 ServiceUtil.returnError(UtilProperties.getMessage(resource,"AccountingErrorCreatingOrderAdjustmentBillingFromOrder",locale), null, null, createOrderAdjustmentBillingContext); 1584 } 1585 1586 } 1587 amount.setScale(decimals, rounding); 1588 adjAmount = amount; 1589 } 1590 1591 Debug.logInfo("adjAmount: " + adjAmount + ", divisor: " + divisor + ", multiplier: " + multiplier + 1592 ", invoiceTypeId: " + invoiceTypeId + ", invoiceId: " + invoiceId + ", itemSeqId: " + invoiceItemSeqId + 1593 ", decimals: " + decimals + ", rounding: " + rounding + ", adj: " + adj, module); 1594 return adjAmount; 1595 } 1596 1597 1598 private static void createInvoiceTerms(GenericDelegator delegator, LocalDispatcher dispatcher, String invoiceId, List terms, GenericValue userLogin) { 1599 if ((terms != null) && (terms.size() > 0)) { 1600 for (Iterator termsIter = terms.iterator(); termsIter.hasNext(); ) { 1601 GenericValue term = (GenericValue) termsIter.next(); 1602 1603 Map createInvoiceTermContext = FastMap.newInstance(); 1604 createInvoiceTermContext.put("invoiceId", invoiceId); 1605 createInvoiceTermContext.put("invoiceItemSeqId", "_NA_"); 1606 createInvoiceTermContext.put("termTypeId", term.get("termTypeId")); 1607 createInvoiceTermContext.put("termValue", term.get("termValue")); 1608 createInvoiceTermContext.put("termDays", term.get("termDays")); 1609 createInvoiceTermContext.put("uomId", term.get("uomId")); 1610 createInvoiceTermContext.put("userLogin", userLogin); 1611 1612 Map createInvoiceTermResult = null; 1613 try { 1614 createInvoiceTermResult = dispatcher.runSync("createInvoiceTerm", createInvoiceTermContext); 1615 } catch( GenericServiceException e ) { 1616 String errMsg = "Service/other problem creating InvoiceTerm from order: " + e.toString(); 1617 Debug.logError(e, errMsg, module); 1618 ServiceUtil.returnError(errMsg); 1619 } 1620 if (ServiceUtil.isError(createInvoiceTermResult)) { 1621 ServiceUtil.returnError("Error creating InvoiceTerm from order", null, null, createInvoiceTermResult); 1622 } 1623 } 1624 } 1625 } 1626 1627 1635 public static Map updatePaymentApplication(DispatchContext dctx, Map context) { 1636 Double amountApplied = (Double ) context.get("amountApplied"); 1637 if (amountApplied != null) { 1638 BigDecimal amountAppliedBd = new BigDecimal (amountApplied.toString()); 1639 context.put("amountApplied", amountAppliedBd); 1640 } else { 1641 BigDecimal amountAppliedBd = ZERO; 1642 context.put("amountApplied", amountAppliedBd); 1643 } 1644 1645 return updatePaymentApplicationBd(dctx, context); 1646 } 1647 1648 public static Map updatePaymentApplicationBd(DispatchContext dctx, Map context) { 1649 GenericDelegator delegator = dctx.getDelegator(); 1650 LocalDispatcher dispatcher = dctx.getDispatcher(); 1651 1652 if (decimals == -1 || rounding == -1) { 1653 return ServiceUtil.returnError("Arithmetic properties for Invoice services not configured properly. Cannot proceed."); 1654 } 1655 1656 String defaultInvoiceProcessing = UtilProperties.getPropertyValue("AccountingConfig","invoiceProcessing").toString(); 1657 1658 boolean debug = true; 1661 String changeProcessing = (String ) context.get("invoiceProcessing"); 1663 String invoiceId = (String ) context.get("invoiceId"); 1664 String invoiceItemSeqId = (String ) context.get("invoiceItemSeqId"); 1665 String paymentId = (String ) context.get("paymentId"); 1666 String toPaymentId = (String ) context.get("toPaymentId"); 1667 String paymentApplicationId = (String ) context.get("paymentApplicationId"); 1668 BigDecimal amountApplied = (BigDecimal ) context.get("amountApplied"); 1669 String billingAccountId = (String ) context.get("billingAccountId"); 1670 String taxAuthGeoId = (String ) context.get("taxAuthGeoId"); 1671 1672 List errorMessageList = new LinkedList(); 1673 String successMessage = null; 1674 if (debug) Debug.logInfo("Input parameters..." + 1675 " defaultInvoiceProcessing: " + defaultInvoiceProcessing + 1676 " changeDefaultInvoiceProcessing: " + changeProcessing + 1677 " paymentApplicationId: " + paymentApplicationId + 1678 " PaymentId: " + paymentId + 1679 " InvoiceId: " + invoiceId + 1680 " InvoiceItemSeqId: " + invoiceItemSeqId + 1681 " BillingAccountId: " + billingAccountId + 1682 " toPaymentId: " + toPaymentId + 1683 " amountApplied: " + amountApplied.toString() + 1684 " TaxAuthGeoId: " + taxAuthGeoId, module); 1685 1686 if (changeProcessing == null) changeProcessing = new String ("N"); 1688 boolean invoiceProcessing = true; 1689 if (defaultInvoiceProcessing.equals("YY")) invoiceProcessing = true; 1690 1691 else if (defaultInvoiceProcessing.equals("NN")) invoiceProcessing = false; 1692 1693 else if (defaultInvoiceProcessing.equals("Y")) { 1694 if (changeProcessing.equals("Y")) invoiceProcessing = false; 1695 else invoiceProcessing = true; 1696 } 1697 1698 else if (defaultInvoiceProcessing.equals("N")) { 1699 if (changeProcessing.equals("Y")) invoiceProcessing = true; 1700 else invoiceProcessing = false; 1701 } 1702 1703 if (paymentApplicationId == null) { 1707 int count = 0; 1708 if (invoiceId != null) count++; 1709 if (toPaymentId != null) count++; 1710 if (billingAccountId != null) count++; 1711 if (taxAuthGeoId != null) count++; 1712 if ((billingAccountId != null) && (invoiceId != null)) count--; 1713 if (count != 1) { 1714 errorMessageList.add("- Specify either Invoice or toPayment or billing account or taxGeoId....\n"); 1715 } 1716 } 1717 1718 if (amountApplied == null) amountApplied = new BigDecimal ("0"); 1720 if (invoiceId == null) invoiceItemSeqId = null; 1722 1723 1725 BigDecimal paymentApplyAvailable = new BigDecimal ("0"); 1727 BigDecimal amountAppliedMax = new BigDecimal ("0"); 1729 GenericValue payment = null; 1732 if (paymentId == null || paymentId.equals("")) { 1733 errorMessageList.add("- PaymentId blank or not supplied.... .....\n"); 1734 } else { 1735 try { 1736 payment = delegator.findByPrimaryKey("Payment", UtilMisc.toMap("paymentId", paymentId)); 1737 } catch (GenericEntityException e) { 1738 ServiceUtil.returnError(e.getMessage()); 1739 } 1740 if (payment == null) { 1741 errorMessageList.add("- Payment record not found, ID: " + paymentId + "\n"); 1742 } 1743 paymentApplyAvailable = payment.getBigDecimal("amount").subtract(PaymentWorker.getPaymentAppliedBd(payment)).setScale(decimals,rounding); 1744 1745 if (payment.getString("statusId").equals("PMNT_CANCELLED")) { 1746 errorMessageList.add("- Payment(" + paymentId + ") is cancelled and cannot be applied\n"); 1747 } 1748 1749 if (amountApplied.signum() == 0) { 1752 amountAppliedMax = paymentApplyAvailable; 1753 } 1754 1755 if (paymentApplicationId == null) { 1756 if (paymentApplyAvailable.signum() == 0) { 1758 errorMessageList.add("- Payment(" + paymentId + ") is already fully applied\n"); 1759 } else { 1760 if (amountApplied.compareTo(paymentApplyAvailable) > 0) { 1763 errorMessageList.add("- Payment(" + paymentId + ") has " + paymentApplyAvailable + " to apply but " + amountApplied + " is requested\n"); 1764 } 1765 } 1766 } 1767 1768 if (debug) Debug.logInfo("Payment info retrieved and checked...", module); 1769 } 1770 1771 BigDecimal toPaymentApplyAvailable = new BigDecimal ("0"); 1773 GenericValue toPayment = null; 1774 if (toPaymentId != null && !toPaymentId.equals("")) { 1775 try { 1776 toPayment = delegator.findByPrimaryKey("Payment", UtilMisc.toMap("paymentId", toPaymentId)); 1777 } catch (GenericEntityException e) { 1778 ServiceUtil.returnError(e.getMessage()); 1779 } 1780 if (toPayment == null) { 1781 errorMessageList.add("- toPayment record not found, ID: " + toPaymentId + "\n"); 1782 } 1783 toPaymentApplyAvailable = toPayment.getBigDecimal("amount").subtract(PaymentWorker.getPaymentAppliedBd(toPayment)).setScale(decimals,rounding); 1784 1785 if (toPayment.getString("statusId").equals("PMNT_CANCELLED")) { 1786 errorMessageList.add("- toPayment(" + toPaymentId + ") is cancelled and cannot be applied\n"); 1787 } 1788 1789 if (amountAppliedMax.compareTo(toPaymentApplyAvailable) > 0) { 1791 amountAppliedMax = toPaymentApplyAvailable; 1792 } 1793 1794 if (paymentApplicationId == null) { 1795 if (toPaymentApplyAvailable.signum() == 0) { 1797 errorMessageList.add("- toPayment(" + toPaymentId + ") is already fully applied\n"); 1798 } else { 1799 if (amountApplied.compareTo(toPaymentApplyAvailable) > 0) { 1802 errorMessageList.add("- toPayment(" + toPaymentId + ") has " + toPaymentApplyAvailable + " to apply but " + amountApplied + " is requested\n"); 1803 } 1804 } 1805 } 1806 1807 if (!payment.getString("partyIdFrom").equals(toPayment.getString("partyIdTo")) && 1809 !payment.getString("partyIdFrom").equals(toPayment.getString("partyIdTo"))) { 1810 errorMessageList.add("- At least the 'from' party should be the same as the 'to' party of the other payment\n"); 1811 } 1812 1813 if (debug) Debug.logInfo("toPayment info retrieved and checked...", module); 1814 } 1815 1816 GenericValue billingAccount = null; 1818 BigDecimal billingAccountApplyAvailable = new BigDecimal ("0"); 1819 if (billingAccountId != null && !billingAccountId.equals("")) { 1820 try { 1821 billingAccount = delegator.findByPrimaryKey("BillingAccount", UtilMisc.toMap("billingAccountId", billingAccountId)); 1822 } catch (GenericEntityException e) { 1823 ServiceUtil.returnError(e.getMessage()); 1824 } 1825 if (billingAccount == null) { 1826 errorMessageList.add("- Billing Account record not found, ID: " + billingAccountId + "\n"); 1827 } 1828 1829 try { 1831 billingAccountApplyAvailable = BillingAccountWorker.availableToCapture(billingAccount); 1832 } catch (GenericEntityException e) { 1833 ServiceUtil.returnError(e.getMessage()); 1834 errorMessageList.add("- Billing Account(" + billingAccountId + ") balance could not be retrieved, see log for more info...(\n"); 1835 } 1836 1837 if (paymentApplicationId == null) { 1838 if (invoiceId != null) { 1844 if (billingAccountApplyAvailable.signum() <= 0) { 1845 errorMessageList.add("- Billing Account(" + billingAccountId + " doesn't have a positive balance: " + billingAccountApplyAvailable + "\n"); 1846 } else { 1847 if (amountApplied.compareTo(billingAccountApplyAvailable) == 1) { 1850 errorMessageList.add("- Billing Account(" + billingAccountId + ") has " + paymentApplyAvailable + " to apply but " + amountApplied + " is requested\n"); 1851 } 1852 } 1853 } 1854 } 1855 1856 if (billingAccount.get("accountCurrencyUomId") != null && payment.get("currencyUomId") != null && 1858 !billingAccount.getString("accountCurrencyUomId").equals(payment.getString("currencyUomId"))) { 1859 errorMessageList.add("- Currencies are not the same, Billing Account(" + billingAccountId + ") has currency " + billingAccount.getString("accountCurrencyUomId") + " and Payment(" + paymentId + ") has a currency of: " + payment.getString("currencyUomId") + "\n"); 1860 } 1861 1862 if (debug) Debug.logInfo("Billing Account info retrieved and checked...", module); 1863 } 1864 1865 BigDecimal invoiceApplyAvailable = new BigDecimal ("0"); 1867 BigDecimal invoiceItemApplyAvailable = new BigDecimal ("0"); 1869 GenericValue invoice = null; 1871 GenericValue invoiceItem = null; 1872 if (invoiceId != null) { 1873 try { 1874 invoice = delegator.findByPrimaryKey("Invoice", UtilMisc.toMap("invoiceId", invoiceId)); 1875 } catch (GenericEntityException e) { 1876 ServiceUtil.returnError(e.getMessage()); 1877 } 1878 1879 if (invoice == null) { 1880 errorMessageList.add("- Invoice record not found, ID: " + invoiceId + "\n"); 1881 } 1882 else { 1884 if (invoice.getString("statusId").equals("INVOICE_CANCELLED")) { 1885 errorMessageList.add("- Invoice is cancelled, cannot be applied to, ID: " + invoiceId + "\n"); 1886 } 1887 1888 BigDecimal invoiceTotal = InvoiceWorker.getInvoiceTotalBd(invoice); 1890 invoiceApplyAvailable = invoiceTotal.subtract(InvoiceWorker.getInvoiceAppliedBd(invoice)).setScale(decimals, rounding); 1891 1892 if (invoiceApplyAvailable.compareTo(amountAppliedMax) < 0) { 1894 amountAppliedMax = invoiceApplyAvailable; 1895 } 1896 1897 if (invoiceTotal.signum() == 0) { 1898 errorMessageList.add("- Invoice (" + invoiceId + ") has a total value of zero....cannot apply anything...\n"); 1899 } else if (paymentApplicationId == null) { 1900 if (invoiceApplyAvailable.signum() == 0) { 1902 errorMessageList.add("- Invoice (" + invoiceId + ") is already completely covered by payments... \n"); 1903 } 1904 else if (amountApplied.compareTo(invoiceApplyAvailable) > 0) { 1907 errorMessageList.add("- Invoice(" + invoiceId + ") has " + invoiceApplyAvailable + " to apply but " + amountApplied + " is requested\n"); 1908 } 1909 } 1910 1911 if (!payment.getString("partyIdFrom").equals(invoice.getString("partyId")) && 1913 !payment.getString("partyIdTo").equals(invoice.getString("partyIdFrom"))) { 1914 errorMessageList.add("- At least the 'from' party should be the same as the 'to' party of the payment/invoice\n"); 1915 } 1916 1917 if (debug) Debug.logInfo("Invoice info retrieved and checked ...", module); 1918 } 1919 1920 if (invoiceItemSeqId != null) { 1922 try { 1924 invoiceItem = delegator.findByPrimaryKey("InvoiceItem", UtilMisc.toMap("invoiceId", invoiceId, "invoiceItemSeqId", invoiceItemSeqId)); 1925 } catch (GenericEntityException e) { 1926 ServiceUtil.returnError(e.getMessage()); 1927 } 1928 1929 if (invoiceItem == null) { 1930 errorMessageList.add("- InvoiceItem record not found, ID: " + invoiceId + " " + invoiceItemSeqId + "\n"); 1931 } else { 1932 if (invoiceItem.get("uomId") != null && payment.get("currencyUomId") != null && !invoiceItem.getString("uomId").equals(payment.getString("currencyUomId"))) { 1933 errorMessageList.add("- Payment currency(" + payment.getString("currencyUomId") + ") and invoice Item currency(" + invoiceItem.getString("uomId") + ") not the same\n"); 1934 } else if (invoice.get("currencyUomId") != null && payment.get("currencyUomId") != null && !invoice.getString("currencyUomId").equals(payment.getString("currencyUomId"))) { 1935 errorMessageList.add("- Payment currency(" + payment.getString("currencyUomId") + ") and invoice currency(" + invoice.getString("currencyUomId") + ") not the same\n"); 1936 } 1937 1938 BigDecimal quantity = null; 1940 if (invoiceItem.get("quantity") == null) { 1941 quantity = new BigDecimal ("1"); 1942 } else { 1943 quantity = invoiceItem.getBigDecimal("quantity").setScale(decimals,rounding); 1944 } 1945 invoiceItemApplyAvailable = invoiceItem.getBigDecimal("amount").multiply(quantity).subtract(InvoiceWorker.getInvoiceItemAppliedBd(invoiceItem)); 1946 if (paymentApplicationId == null && amountApplied.compareTo(invoiceItemApplyAvailable) > 0) { 1949 errorMessageList.add("- Invoice(" + invoiceId + ") item(" + invoiceItemSeqId + ") has " + invoiceItemApplyAvailable + " to apply but " + amountApplied + " is requested\n"); 1951 } 1952 1953 } 1954 if (debug) Debug.logInfo("InvoiceItem info retrieved and checked against the Invoice (currency and amounts) ...", module); 1955 } 1956 } 1957 1958 BigDecimal newInvoiceApplyAvailable = invoiceApplyAvailable; 1961 BigDecimal newInvoiceItemApplyAvailable = invoiceItemApplyAvailable; 1963 BigDecimal newToPaymentApplyAvailable = toPaymentApplyAvailable; 1965 BigDecimal newBillingAccountApplyAvailable = billingAccountApplyAvailable; 1967 BigDecimal newPaymentApplyAvailable = paymentApplyAvailable; 1969 GenericValue paymentApplication = null; 1970 if (paymentApplicationId == null) { 1971 paymentApplication = delegator.makeValue("PaymentApplication", null); 1972 } else { try { 1975 paymentApplication = delegator.findByPrimaryKey("PaymentApplication", UtilMisc.toMap("paymentApplicationId", paymentApplicationId)); 1976 } catch (GenericEntityException e) { 1977 ServiceUtil.returnError(e.getMessage()); 1978 } 1979 1980 if (paymentApplication == null) { 1981 errorMessageList.add("- PaymentApplication record not found, ID: " + paymentApplicationId + "\n"); 1982 paymentApplicationId = null; 1983 } else { 1984 1985 if (paymentApplication.get("invoiceId") == null && invoiceId != null) { 1989 billingAccountId = null; 1990 taxAuthGeoId = null; 1991 toPaymentId = null; 1992 } else if (paymentApplication.get("toPaymentId") == null && toPaymentId != null) { 1993 invoiceId = null; 1994 invoiceItemSeqId = null; 1995 taxAuthGeoId = null; 1996 billingAccountId = null; 1997 } else if (paymentApplication.get("billingAccountId") == null && billingAccountId != null) { 1998 invoiceId = null; 1999 invoiceItemSeqId = null; 2000 toPaymentId = null; 2001 taxAuthGeoId = null; 2002 } else if (paymentApplication.get("taxAuthGeoId") == null && taxAuthGeoId != null) { 2003 invoiceId = null; 2004 invoiceItemSeqId = null; 2005 toPaymentId = null; 2006 billingAccountId = null; 2007 } 2008 2009 newPaymentApplyAvailable = paymentApplyAvailable.add(paymentApplication.getBigDecimal("amountApplied")).subtract(amountApplied).setScale(decimals, rounding); 2012 if (newPaymentApplyAvailable.compareTo(ZERO) < 0) { 2013 errorMessageList.add("- Payment(" + paymentId + ") has an amount(" + paymentApplyAvailable.add(paymentApplication.getBigDecimal("amountApplied")) + ") to apply and the " + amountApplied + " specified is too much\n"); 2014 } 2015 2016 if (invoiceId != null) { 2017 if (invoiceId.equals(paymentApplication .getString("invoiceId"))) { 2020 if (invoiceItemSeqId == null && paymentApplication.get("invoiceItemSeqId") == null) { 2023 newInvoiceApplyAvailable = invoiceApplyAvailable.add(paymentApplication.getBigDecimal("amountApplied")).subtract(amountApplied).setScale(decimals, rounding); 2024 if (invoiceApplyAvailable.compareTo(ZERO) < 0) { 2025 errorMessageList.add("- Update would apply " + newInvoiceApplyAvailable.negate() + " to much on this Invoice(" + invoiceId + ")\n"); 2026 } 2027 } else if (invoiceItemSeqId == null && paymentApplication.get("invoiceItemSeqId") != null) { 2028 newInvoiceApplyAvailable = invoiceApplyAvailable.add(paymentApplication.getBigDecimal("amountApplied")).subtract(amountApplied).setScale(decimals, rounding); 2030 if (invoiceApplyAvailable.compareTo(ZERO) < 0) { 2031 errorMessageList.add("- Update would apply " + newInvoiceApplyAvailable.negate() + " to much on this Invoice(" + invoiceId + ")\n"); 2032 } 2033 } else if (invoiceItemSeqId != null && paymentApplication.get("invoiceItemSeqId") == null) { 2034 newInvoiceItemApplyAvailable = invoiceItemApplyAvailable.subtract(amountApplied).setScale(decimals, rounding); 2037 if (newInvoiceItemApplyAvailable.compareTo(ZERO) < 0) { 2038 errorMessageList.add("- Update would apply " + newInvoiceItemApplyAvailable.negate() + " to much on this Invoice item(" + invoiceId + "/" + invoiceItemSeqId + "\n"); 2039 } 2040 } else if (invoiceItemSeqId.equals(paymentApplication.getString("invoiceItemSeqId"))) { 2041 newInvoiceItemApplyAvailable = invoiceItemApplyAvailable.add(paymentApplication.getBigDecimal("amountApplied")).subtract(amountApplied).setScale(decimals, rounding); 2044 if (newInvoiceItemApplyAvailable.compareTo(ZERO) < 0) { 2045 errorMessageList.add("- Update would apply " + newInvoiceItemApplyAvailable.negate() + " to much on this Invoice item(" + invoiceId + "/" + invoiceItemSeqId + "\n"); 2046 } 2047 } else { 2048 newInvoiceItemApplyAvailable = invoiceItemApplyAvailable.add(amountApplied).setScale(decimals, rounding); 2050 if (newInvoiceItemApplyAvailable.compareTo(ZERO) < 0) { 2051 errorMessageList.add("- Update would apply " + newInvoiceItemApplyAvailable.negate() + " to much on this Invoice item\n"); 2052 } 2053 } 2054 2055 if (amountApplied.signum() == 0) { 2058 if (newInvoiceItemApplyAvailable.compareTo(newPaymentApplyAvailable) < 0) { 2059 amountApplied = newInvoiceItemApplyAvailable; 2060 } else { 2062 amountApplied = newPaymentApplyAvailable; 2063 } 2065 } 2066 2067 newInvoiceApplyAvailable = invoiceApplyAvailable.add(paymentApplication.getBigDecimal("amountApplied").subtract(amountApplied)).setScale(decimals, rounding); 2069 if (newInvoiceApplyAvailable.compareTo(ZERO) < 0) { 2070 errorMessageList.add("- Invoice (" + invoiceId + ") has only " + invoiceApplyAvailable.add(paymentApplication.getBigDecimal("amountApplied")) + " left which it not applied, so " + amountApplied + " is too much\n"); 2071 } 2072 } 2073 } 2074 2075 if (toPaymentId != null && toPaymentId.equals(paymentApplication.getString("toPaymentId"))) { 2078 newToPaymentApplyAvailable = toPaymentApplyAvailable.subtract(paymentApplication.getBigDecimal("amountApplied")).add(amountApplied).setScale(decimals, rounding); 2079 if (newToPaymentApplyAvailable.compareTo(ZERO) < 0) { 2080 errorMessageList.add("- toPaymentId(" + toPaymentId + ") has only " + newToPaymentApplyAvailable + " available so " + amountApplied + " is too much\n"); 2081 } 2082 } else if (toPaymentId != null) { 2083 newToPaymentApplyAvailable = toPaymentApplyAvailable.add(amountApplied).setScale(decimals, rounding); 2086 if (newToPaymentApplyAvailable.compareTo(ZERO) < 0) { 2087 errorMessageList.add("- toPaymentId(" + toPaymentId + ") has only "+ newToPaymentApplyAvailable + " available so " + amountApplied + " is too much\n"); 2088 } 2089 2090 } 2091 if (billingAccountId != null && billingAccountId.equals(paymentApplication.getString("billingAccountId"))) { 2096 newBillingAccountApplyAvailable = billingAccountApplyAvailable.subtract(paymentApplication.getBigDecimal("amountApplied")).add(amountApplied).setScale(decimals, rounding); 2097 if (newBillingAccountApplyAvailable.compareTo(ZERO) < 0) { 2098 errorMessageList.add("- Billing Account(" + billingAccountId + ") has only " + newBillingAccountApplyAvailable + " available so " + amountApplied + " is too much\n"); 2099 } 2100 } else if (billingAccountId != null) { 2101 newBillingAccountApplyAvailable = billingAccountApplyAvailable.add(amountApplied).setScale(decimals, rounding); 2104 if (newBillingAccountApplyAvailable.compareTo(ZERO) < 0) { 2105 errorMessageList.add("- Billing Account(" + billingAccountId + ") has only "+ newBillingAccountApplyAvailable + " available so " + amountApplied + " is too much\n"); 2106 } 2107 2108 } 2109 } 2110 if (debug) Debug.logInfo("paymentApplication record info retrieved and checked...", module); 2111 } 2112 2113 if (debug) { 2115 String extra = new String (""); 2116 if (invoiceItemSeqId != null) { 2117 extra = new String (" Invoice item(" + invoiceItemSeqId + ") amount not yet applied: " + newInvoiceItemApplyAvailable); 2118 } 2119 Debug.logInfo("checking finished, start processing withe the following data... ", module); 2120 if (invoiceId != null) { 2121 Debug.logInfo(" Invoice(" + invoiceId + ") amount not yet applied: " + newInvoiceApplyAvailable + extra + " Payment(" + paymentId + ") amount not yet applied: " + newPaymentApplyAvailable + " Requested amount to apply:" + amountApplied, module); 2122 } 2123 if (toPaymentId != null) { 2124 Debug.logInfo(" toPayment(" + toPaymentId + ") amount not yet applied: " + newToPaymentApplyAvailable + " Payment(" + paymentId + ") amount not yet applied: " + newPaymentApplyAvailable + " Requested amount to apply:" + amountApplied, module); 2125 } 2126 if (billingAccountId != null) { 2127 Debug.logInfo(" billingAccount(" + billingAccountId + ") amount not yet applied: " + newBillingAccountApplyAvailable + " Payment(" + paymentId + ") amount not yet applied: " + newPaymentApplyAvailable + " Requested amount to apply:" + amountApplied, module); 2128 } 2129 if (taxAuthGeoId != null) { 2130 Debug.logInfo(" taxAuthGeoId(" + taxAuthGeoId + ") Payment(" + paymentId + ") amount not yet applied: " + newPaymentApplyAvailable + " Requested amount to apply:" + amountApplied, module); 2131 } 2132 } 2133 2134 if (errorMessageList.size() > 0) { 2136 return ServiceUtil.returnError(errorMessageList); 2137 } 2138 2139 if (paymentApplicationId != null) { 2141 if (debug) Debug.logInfo("Process an existing paymentApplication record: " + paymentApplicationId, module); 2143 paymentApplication.set("invoiceId", invoiceId); 2145 paymentApplication.set("invoiceItemSeqId", invoiceItemSeqId); 2146 paymentApplication.set("paymentId", paymentId); 2147 paymentApplication.set("toPaymentId", toPaymentId); 2148 paymentApplication.set("amountApplied", new Double (amountApplied.doubleValue())); 2149 paymentApplication.set("billingAccountId", billingAccountId); 2150 paymentApplication.set("taxAuthGeoId", taxAuthGeoId); 2151 return storePaymentApplication(delegator, paymentApplication); 2152 } 2153 2154 if (invoiceId != null && paymentId != null && (invoiceItemSeqId == null)) { 2158 if (invoiceProcessing) { 2159 if (debug) Debug.logInfo("Try to allocate the payment to the invoice as a whole", module); 2161 paymentApplication.set("paymentId", paymentId); 2162 paymentApplication.set("toPaymentId",toPaymentId); 2163 paymentApplication.set("invoiceId", invoiceId); 2164 paymentApplication.set("invoiceItemSeqId", null); 2165 paymentApplication.set("toPaymentId", null); 2166 if (amountApplied.compareTo(ZERO) > 0) { 2167 paymentApplication.set("amountApplied", new Double (amountApplied.doubleValue())); 2168 } else { 2169 paymentApplication.set("amountApplied", new Double (amountAppliedMax.doubleValue())); 2170 } 2171 paymentApplication.set("billingAccountId", null); 2172 paymentApplication.set("taxAuthGeoId", null); 2173 if (debug) Debug.logInfo("NEW paymentapplication ID:" + paymentApplicationId + " created", module); 2174 return storePaymentApplication(delegator, paymentApplication); 2175 } else { if (debug) Debug.logInfo("Try to allocate the payment to the itemnumbers of the invoice", module); 2177 List invoiceItems = null; 2179 try { 2180 invoiceItems = delegator.findByAnd("InvoiceItem", UtilMisc.toMap("invoiceId", invoiceId)); 2181 } catch (GenericEntityException e) { 2182 ServiceUtil.returnError(e.getMessage()); 2183 } 2184 if (invoiceItems == null || invoiceItems.size() == 0) { 2185 errorMessageList.add("- No invoice items found for invoice " + invoiceId + " to match payment against...\n"); 2186 return ServiceUtil.returnError(errorMessageList); 2187 } else { Iterator i = invoiceItems.iterator(); 2189 if (amountApplied.signum() != 0 && amountApplied.compareTo(paymentApplyAvailable) < 0) { 2191 paymentApplyAvailable = amountApplied; 2192 } 2193 while (i.hasNext() && paymentApplyAvailable.compareTo(ZERO) > 0) { 2194 invoiceItem = (GenericValue) i.next(); 2196 if (debug) Debug.logInfo("Start processing item: " + invoiceItem.getString("invoiceItemSeqId"), module); 2197 BigDecimal itemQuantity = new BigDecimal ("1"); 2198 if (invoiceItem.get("quantity") != null && invoiceItem.getBigDecimal("quantity").signum() != 0) { 2199 itemQuantity = new BigDecimal (invoiceItem.getString("quantity")).setScale(decimals,rounding); 2200 } 2201 BigDecimal itemAmount = invoiceItem.getBigDecimal("amount").setScale(decimals,rounding); 2202 BigDecimal itemTotal = itemAmount.multiply(itemQuantity).setScale(decimals,rounding); 2203 2204 List paymentApplications = null; 2207 try { 2208 paymentApplications = invoiceItem.getRelated("PaymentApplication"); 2209 } catch (GenericEntityException e) { 2210 ServiceUtil.returnError(e.getMessage()); 2211 } 2212 BigDecimal tobeApplied = new BigDecimal ("0"); 2213 BigDecimal alreadyApplied = new BigDecimal ("0"); 2215 if (paymentApplications != null && paymentApplications.size() > 0) { 2216 Iterator p = paymentApplications.iterator(); 2218 while (p.hasNext()) { 2219 paymentApplication = (GenericValue) p.next(); 2220 alreadyApplied = alreadyApplied.add(paymentApplication.getBigDecimal("amountApplied").setScale(decimals,rounding)); 2221 } 2222 tobeApplied = itemTotal.subtract(alreadyApplied).setScale(decimals,rounding); 2223 } else { 2224 tobeApplied = itemTotal; 2226 } 2227 if (debug) Debug.logInfo("tobeApplied:(" + tobeApplied + ") = " + "itemTotal(" + itemTotal + ") - alreadyApplied(" + alreadyApplied + ") but not more then (nonapplied) paymentAmount(" + paymentApplyAvailable + ")", module); 2228 2229 if (tobeApplied.signum() == 0) { 2230 continue; 2232 } 2233 2234 if (paymentApplyAvailable.compareTo(tobeApplied) > 0) { 2235 paymentApplyAvailable = paymentApplyAvailable.subtract(tobeApplied); 2236 } else { 2237 tobeApplied = paymentApplyAvailable; 2238 paymentApplyAvailable = new BigDecimal ("0"); 2239 } 2240 2241 if (invoiceItem.get("uomId") != null && payment.get("currencyUomId") != null && !invoiceItem.getString("uomId").equals(payment.getString("currencyUomId"))) { 2244 errorMessageList.add("- Payment currency (" + payment.getString("currencyUomId") + ") and invoice Item(" + invoiceItem.getString("invoiceItemSeqId") + ") currency(" + invoiceItem.getString("uomId") + ") not the same\n"); 2245 } else if (invoice.get("currencyUomId") != null && payment.get("currencyUomId") != null && !invoice.getString("currencyUomId").equals( payment.getString("currencyUomId"))) { 2246 errorMessageList.add("- Payment currency (" + payment.getString("currencyUomId") + ") and invoice currency(" + invoice.getString("currencyUomId") + ") not the same\n"); 2247 } else { 2248 paymentApplication.set("paymentApplicationId", null); 2249 paymentApplication.set("invoiceId", invoiceId); 2251 paymentApplication.set("invoiceItemSeqId", invoiceItem.getString("invoiceItemSeqId")); 2252 paymentApplication.set("paymentId", paymentId); 2253 paymentApplication.set("toPaymentId", toPaymentId); 2254 paymentApplication.set("amountApplied", new Double ( tobeApplied.doubleValue())); 2255 paymentApplication.set("billingAccountId", billingAccountId); 2256 paymentApplication.set("taxAuthGeoId", taxAuthGeoId); 2257 storePaymentApplication(delegator, paymentApplication); 2258 } 2259 2260 2281 } 2282 2283 if (errorMessageList.size() > 0) { 2284 return ServiceUtil.returnError(errorMessageList); 2285 } else { 2286 if (successMessage != null) { 2287 return ServiceUtil.returnSuccess(successMessage); 2288 } 2289 else { 2290 return ServiceUtil.returnSuccess(); 2291 } 2292 } 2293 } 2294 } 2295 } 2296 2297 if (paymentApplicationId == null && amountApplied != null) { 2300 paymentApplication.set("paymentApplicationId", paymentApplicationId); 2301 paymentApplication.set("invoiceId", invoiceId); 2302 paymentApplication.set("invoiceItemSeqId", invoiceItemSeqId); 2303 paymentApplication.set("paymentId", paymentId); 2304 paymentApplication.set("toPaymentId", toPaymentId); 2305 paymentApplication.set("amountApplied", new Double (amountApplied.doubleValue())); 2306 paymentApplication.set("billingAccountId", billingAccountId); 2307 paymentApplication.set("taxAuthGeoId", taxAuthGeoId); 2308 return storePaymentApplication(delegator, paymentApplication); 2309 } 2310 2311 errorMessageList.add("??unsuitable parameters passed...?? This message.... should never be shown\n"); 2313 errorMessageList.add("--Input parameters...InvoiceId:" + invoiceId + " invoiceItemSeqId:" + invoiceItemSeqId + " PaymentId:" + paymentId + " toPaymentId:" + toPaymentId + "\n paymentApplicationId:" + paymentApplicationId + " amountApplied:" + amountApplied); 2314 return ServiceUtil.returnError(errorMessageList); 2315 } 2316 2317 public static Map calculateInvoicedAdjustmentTotalBd(DispatchContext dctx, Map context) { 2318 GenericDelegator delegator = dctx.getDelegator(); 2319 Locale locale = (Locale) context.get("locale"); 2320 GenericValue orderAdjustment = (GenericValue) context.get("orderAdjustment"); 2321 Map result = ServiceUtil.returnSuccess(); 2322 2323 BigDecimal invoicedTotal = ZERO; 2324 List invoicedAdjustments = null; 2325 try { 2326 invoicedAdjustments = delegator.findByAnd("OrderAdjustmentBilling", UtilMisc.toMap("orderAdjustmentId", orderAdjustment.getString("orderAdjustmentId"))); 2327 } catch( GenericEntityException e ) { 2328 String errMsg = UtilProperties.getMessage(resource, "AccountingTroubleCallingCalculateInvoicedAdjustmentTotalService" + ": " + e.getMessage(), locale); 2329 Debug.logError(e, errMsg, module); 2330 return ServiceUtil.returnError(errMsg); 2331 } 2332 Iterator iait = invoicedAdjustments.iterator(); 2333 while (iait.hasNext()) { 2334 GenericValue invoicedAdjustment = (GenericValue) iait.next(); 2335 invoicedTotal = invoicedTotal.add(invoicedAdjustment.getBigDecimal("amount").setScale(decimals, rounding)); 2336 } 2337 result.put("invoicedTotal", invoicedTotal); 2338 return result; 2339 } 2340 2341 2349 private static Map storePaymentApplication(GenericDelegator delegator, GenericValue paymentApplication) { 2350 Map results = ServiceUtil.returnSuccess(); 2351 boolean debug = true; 2352 if (debug) Debug.logInfo("===============Start updating the paymentApplication table ", module); 2353 2354 if (decimals == -1 || rounding == -1) { 2355 return ServiceUtil.returnError("Arithmetic properties for Invoice services not configured properly. Cannot proceed."); 2356 } 2357 2358 List checkAppls = null; 2360 try { 2361 checkAppls = delegator.findByAnd("PaymentApplication", UtilMisc.toMap( 2362 "invoiceId", paymentApplication.get("invoiceId"), 2363 "invoiceItemSeqId", paymentApplication.get("invoiceItemSeqId"), 2364 "billingAccountId", paymentApplication.get("billingAccountId"), 2365 "paymentId", paymentApplication.get("paymentId"), 2366 "toPaymentId", paymentApplication.get("toPaymentId"), 2367 "taxAuthGeoId", paymentApplication.get("taxAuthGeoId"))); 2368 } catch (GenericEntityException e) { 2369 ServiceUtil.returnError(e.getMessage()); 2370 } 2371 if (checkAppls != null && checkAppls.size() > 0) { 2372 if (debug) Debug.logInfo("===============" + checkAppls.size() + " records already exist", module); 2373 GenericValue checkAppl = (GenericValue) checkAppls.get(0); 2375 if ( paymentApplication.get("paymentApplicationId") == null) { 2377 checkAppl.set("amountApplied", new Double (paymentApplication.getBigDecimal("amountApplied"). 2379 add(checkAppl.getBigDecimal("amountApplied")).setScale(decimals,rounding).doubleValue())); 2380 if (debug) Debug.logInfo("==============Update paymentApplication record: " + checkAppl.getString("paymentApplicationId") + " with appliedAmount:" + checkAppl.getBigDecimal("amountApplied"), module); 2381 try { 2382 checkAppl.store(); 2383 } catch (GenericEntityException e) { 2384 ServiceUtil.returnError(e.getMessage()); 2385 } 2386 } else if (paymentApplication.getString("paymentApplicationId").equals(checkAppl.getString("paymentApplicationId"))) { 2387 checkAppl.set("amountApplied", new Double (paymentApplication.getBigDecimal("amountApplied").doubleValue())); 2389 if (debug) Debug.logInfo("==============Update paymentApplication record: " + checkAppl.getString("paymentApplicationId") + " with appliedAmount:" + checkAppl.getBigDecimal("amountApplied"), module); 2390 try { 2391 checkAppl.store(); 2392 } catch (GenericEntityException e) { 2393 ServiceUtil.returnError(e.getMessage()); 2394 } 2395 } else { checkAppl.set("amountApplied", new Double (paymentApplication.getBigDecimal("amountApplied"). 2398 add(checkAppl.getBigDecimal("amountApplied")).setScale(decimals,rounding).doubleValue())); 2399 if (debug) Debug.logInfo("============Delete paymentApplication record: " + paymentApplication.getString("paymentApplicationId") + " with appliedAmount:" + paymentApplication.getBigDecimal("amountApplied"), module); 2401 try { 2402 paymentApplication.remove(); 2403 } catch (GenericEntityException e) { 2404 ServiceUtil.returnError(e.getMessage()); 2405 } 2406 if (debug) Debug.logInfo("==============Update paymentApplication record: " + checkAppl.getString("paymentApplicationId") + " with appliedAmount:" + checkAppl.getBigDecimal("amountApplied"), module); 2408 try { 2409 checkAppl.store(); 2410 } catch (GenericEntityException e) { 2411 ServiceUtil.returnError(e.getMessage()); 2412 } 2413 } 2414 } else { 2415 if (debug) Debug.logInfo("No records found with paymentId,invoiceid..etc probaly changed one of them...", module); 2416 if (paymentApplication.get("paymentApplicationId") == null) { 2418 paymentApplication.set("paymentApplicationId", delegator.getNextSeqId("PaymentApplication")); 2419 if (debug) Debug.logInfo("=============Create new paymentAppication record: " + paymentApplication.getString("paymentApplicationId") + " with appliedAmount:" + paymentApplication.getBigDecimal("amountApplied"), module); 2420 try { 2421 paymentApplication.create(); 2422 } catch (GenericEntityException e) { 2423 ServiceUtil.returnError(e.getMessage()); 2424 } 2425 } else { 2426 if (debug) Debug.logInfo("===========Update existing paymentApplication record: " + paymentApplication.getString("paymentApplicationId") + " with appliedAmount:" + paymentApplication.getBigDecimal("amountApplied"), module); 2428 try { 2429 paymentApplication.store(); 2430 } catch (GenericEntityException e) { 2431 ServiceUtil.returnError(e.getMessage()); 2432 } 2433 } 2434 } 2435 return results; 2436 } 2437 2438 public static Map checkPaymentInvoices(DispatchContext dctx, Map context) { 2439 GenericDelegator delegator = dctx.getDelegator(); 2440 LocalDispatcher dispatcher = dctx.getDispatcher(); 2441 GenericValue userLogin = (GenericValue) context.get("userLogin"); 2442 2443 String paymentId = (String ) context.get("paymentId"); 2444 try { 2445 GenericValue payment = delegator.findByPrimaryKey("Payment", UtilMisc.toMap("paymentId", paymentId)); 2446 if (payment == null) throw new GenericServiceException("Payment with ID [" + paymentId + "] not found!"); 2447 2448 List paymentApplications = payment.getRelated("PaymentApplication"); 2449 if (UtilValidate.isEmpty(paymentApplications)) return ServiceUtil.returnSuccess(); 2450 2451 Iterator iter = paymentApplications.iterator(); 2452 while (iter.hasNext()) { 2453 GenericValue paymentApplication = (GenericValue) iter.next(); 2454 String invoiceId = paymentApplication.getString("invoiceId"); 2455 if (invoiceId != null) { 2456 Map serviceResult = dispatcher.runSync("checkInvoicePaymentApplications", UtilMisc.toMap("invoiceId", invoiceId, "userLogin", userLogin)); 2457 if (ServiceUtil.isError(serviceResult)) return serviceResult; 2458 } 2459 } 2460 return ServiceUtil.returnSuccess(); 2461 } catch (GenericServiceException se) { 2462 Debug.logError(se, se.getMessage(), module); 2463 return ServiceUtil.returnError(se.getMessage()); 2464 } catch (GenericEntityException ee) { 2465 Debug.logError(ee, ee.getMessage(), module); 2466 return ServiceUtil.returnError(ee.getMessage()); 2467 } 2468 } 2469 2470} 2471 | Popular Tags |