1 16 17 package com.opensourcestrategies.financials.ledger; 18 19 import java.sql.Timestamp ; 20 import java.util.*; 21 import java.math.BigDecimal ; 22 23 import org.ofbiz.accounting.invoice.InvoiceWorker; 24 import org.ofbiz.accounting.payment.PaymentWorker; 25 import org.ofbiz.accounting.util.UtilAccounting; 26 import org.ofbiz.accounting.AccountingException; 27 import org.ofbiz.accounting.invoice.InvoiceWorker; 28 import org.ofbiz.base.util.*; 29 import org.ofbiz.entity.GenericDelegator; 30 import org.ofbiz.entity.GenericEntityException; 31 import org.ofbiz.entity.GenericValue; 32 import org.ofbiz.entity.condition.EntityCondition; 33 import org.ofbiz.entity.condition.EntityConditionList; 34 import org.ofbiz.entity.condition.EntityExpr; 35 import org.ofbiz.entity.condition.EntityOperator; 36 import org.ofbiz.entity.util.EntityUtil; 37 import org.ofbiz.service.DispatchContext; 38 import org.ofbiz.service.GenericServiceException; 39 import org.ofbiz.service.LocalDispatcher; 40 import org.ofbiz.service.ModelService; 41 import org.ofbiz.service.ServiceUtil; 42 43 import com.opensourcestrategies.financials.util.UtilCOGS; 44 import com.opensourcestrategies.financials.util.UtilFinancial; 45 46 53 54 55 public class LedgerServices { 56 57 public static final String module = LedgerServices.class.getName(); 58 public static final String INVOICE_PRODUCT_ITEM_TYPE = "INV_FPROD_ITEM"; public static final String PURCHINV_PRODUCT_ITEM_TYPE = "PINV_FPROD_ITEM"; public static final String RETINV_PRODUCT_ITEM_TYPE = "RINV_FPROD_ITEM"; public static final String resource = "FinancialsUiLabels"; 62 63 public static final double epsilon = 0.000001; 66 private static BigDecimal ZERO = new BigDecimal ("0"); 67 private static int decimals = -1; 68 private static int rounding = -1; 69 static { 70 decimals = UtilNumber.getBigDecimalScale("invoice.decimals"); 71 rounding = UtilNumber.getBigDecimalRoundingMode("invoice.rounding"); 72 ZERO.setScale(decimals); 74 } 75 76 public static Map postInvoiceToGl(DispatchContext dctx, Map context) { 77 GenericDelegator delegator = dctx.getDelegator(); 78 LocalDispatcher dispatcher = dctx.getDispatcher(); 79 GenericValue userLogin = (GenericValue) context.get("userLogin"); 80 81 String invoiceId = (String ) context.get("invoiceId"); 82 try { 83 84 GenericValue invoice = delegator.findByPrimaryKeyCache("Invoice", UtilMisc.toMap("invoiceId", invoiceId)); 86 if (invoice == null) { 87 return ServiceUtil.returnError("No invoice found for invoiceId of " + invoiceId); 88 } else if (invoice.get("invoiceTypeId") == null) { 89 return ServiceUtil.returnError("Invoice " + invoiceId + " has a null invoice type and cannot be processed"); 90 } 91 String invoiceTypeId = (String ) invoice.get("invoiceTypeId"); 92 93 String transactionPartyId = null; 95 String transactionPartyRoleTypeId = null; 96 String acctgTransTypeId = null; 97 String organizationPartyId = null; 98 String offsettingGlAccountTypeId = null; 99 String defaultDebitCreditFlag = null; 100 String offsettingDebitCreditFlag = null; 101 String defaultGlAccountTypeId = null; 102 103 if ("SALES_INVOICE".equals(invoiceTypeId)) { 105 acctgTransTypeId = "SALES_ACCTG_TRANS"; 106 offsettingGlAccountTypeId = "ACCOUNTS_RECEIVABLE"; 107 organizationPartyId = invoice.getString("partyIdFrom"); 108 transactionPartyId = invoice.getString("partyId"); 109 transactionPartyRoleTypeId = "BILL_TO_CUSTOMER"; 110 defaultDebitCreditFlag = "C"; 111 offsettingDebitCreditFlag = "D"; 112 defaultGlAccountTypeId = "SALES_ACCOUNT"; 113 } else if ("PURCHASE_INVOICE".equals(invoiceTypeId)) { 114 acctgTransTypeId = "OBLIGATION_ACCTG_TRA"; 115 offsettingGlAccountTypeId = "ACCOUNTS_PAYABLE"; 116 organizationPartyId = invoice.getString("partyId"); 117 transactionPartyId = invoice.getString("partyIdFrom"); 118 transactionPartyRoleTypeId = "BILL_FROM_VENDOR"; 119 defaultDebitCreditFlag = "D"; 120 offsettingDebitCreditFlag = "C"; 121 defaultGlAccountTypeId = "UNINVOICED_SHIP_RCPT"; 122 } else if ("CUST_RTN_INVOICE".equals(invoiceTypeId)) { 123 acctgTransTypeId = "OBLIGATION_ACCTG_TRA"; 124 offsettingGlAccountTypeId = "CUSTOMER_CREDIT"; 125 organizationPartyId = invoice.getString("partyId"); 126 transactionPartyId = invoice.getString("partyIdFrom"); 127 transactionPartyRoleTypeId = "BILL_TO_CUSTOMER"; 128 defaultDebitCreditFlag = "D"; 129 offsettingDebitCreditFlag = "C"; 130 defaultGlAccountTypeId = "SALES_RETURN"; 131 } else { 132 Debug.logWarning("Invoice [" + invoiceId + "] has an unsupported invoice type of [" + invoiceTypeId + "] and was not posted to the ledger", module); 133 return ServiceUtil.returnSuccess(); 134 } 135 136 Map tmpResult = processInvoiceItems( 138 delegator, dispatcher, userLogin, invoice, 139 acctgTransTypeId, offsettingGlAccountTypeId, 140 organizationPartyId, transactionPartyId, transactionPartyRoleTypeId, 141 defaultDebitCreditFlag, defaultGlAccountTypeId 142 ); 143 144 if (ServiceUtil.isError(tmpResult)) return tmpResult; 146 147 int itemSeqId = 1; 149 List acctgTransEntries = new ArrayList(); 150 List acctgTransEntryMaps = (List) tmpResult.get("acctgTransEntries"); 151 for (Iterator iter = acctgTransEntryMaps.iterator(); iter.hasNext(); ) { 152 Map input = (Map) iter.next(); 153 154 if (((Double ) input.get("amount")).doubleValue() == 0.0) { 156 continue; 157 } 158 159 input.put("acctgTransEntrySeqId", Integer.toString(itemSeqId)); 161 acctgTransEntries.add(delegator.makeValue("AcctgTransEntry", input)); 162 itemSeqId++; 163 164 if (Debug.verboseOn()) { 165 Debug.logVerbose(acctgTransEntries.get(acctgTransEntries.size()-1).toString(), module); 166 } 167 } 168 169 Map input = new HashMap(); 171 input.put("glAccountId", tmpResult.get("offsettingGlAccountId")); 172 input.put("acctgTransEntrySeqId", Integer.toString(itemSeqId)); 173 input.put("organizationPartyId", organizationPartyId); 174 input.put("partyId", transactionPartyId); 175 input.put("roleTypeId", transactionPartyRoleTypeId); 176 input.put("debitCreditFlag", offsettingDebitCreditFlag); 177 input.put("amount", tmpResult.get("postingTotal")); 178 input.put("acctgTransEntryTypeId", "_NA_"); 179 Debug.logInfo(input.toString(), module); 180 GenericValue offsettingAcctgTransEntry = delegator.makeValue("AcctgTransEntry", input); 181 acctgTransEntries.add(offsettingAcctgTransEntry); 182 183 input = new HashMap(); 185 input.put("acctgTransEntries", acctgTransEntries); 186 input.put("invoiceId", invoiceId); 187 input.put("partyId", transactionPartyId); 188 input.put("roleTypeId", transactionPartyRoleTypeId); 189 input.put("glFiscalTypeId", "ACTUAL"); 190 input.put("acctgTransTypeId", acctgTransTypeId); 191 input.put("userLogin", userLogin); 192 tmpResult = dispatcher.runSync("createAcctgTransAndEntries", input); 193 194 if (((String ) tmpResult.get(ModelService.RESPONSE_MESSAGE)).equals(ModelService.RESPOND_SUCCESS)) { 196 Map result = ServiceUtil.returnSuccess(); 197 result.put("acctgTransId", tmpResult.get("acctgTransId")); 198 return(result); 199 } 200 201 return tmpResult; 203 } catch (GenericEntityException ee) { 204 return ServiceUtil.returnError(ee.getMessage()); 205 } catch (GenericServiceException se) { 206 return ServiceUtil.returnError(se.getMessage()); 207 } 208 } 209 210 public static Map postInvoiceWriteoffToGl(DispatchContext dctx, Map context) { 211 GenericDelegator delegator = dctx.getDelegator(); 212 LocalDispatcher dispatcher = dctx.getDispatcher(); 213 GenericValue userLogin = (GenericValue) context.get("userLogin"); 214 Map success = ServiceUtil.returnSuccess(); 215 Locale locale = (Locale) context.get("locale"); 216 217 String invoiceId = (String ) context.get("invoiceId"); 218 219 try { 220 221 GenericValue invoice = delegator.findByPrimaryKeyCache("Invoice", UtilMisc.toMap("invoiceId", invoiceId)); 223 if (invoice == null) { 224 return ServiceUtil.returnError("No invoice found for invoiceId of " + invoiceId); 225 } else if (invoice.get("invoiceTypeId") == null) { 226 return ServiceUtil.returnError("Invoice " + invoiceId + " has a null invoice type and cannot be processed"); 227 } 228 String invoiceTypeId = (String ) invoice.get("invoiceTypeId"); 229 BigDecimal invoiceUnappliedAmount = InvoiceWorker.getInvoiceNotApplied(invoice); 230 if (invoiceUnappliedAmount.signum() != 1) { 231 return success; 232 } 233 234 String organizationPartyId = null; 236 String transactionPartyId = null; 237 String creditGlAccountTypeId = null; 238 String debitGlAccountTypeId = null; 239 if ("SALES_INVOICE".equals(invoiceTypeId)) { 240 organizationPartyId = invoice.getString("partyIdFrom"); 241 transactionPartyId = invoice.getString("partyId"); 242 creditGlAccountTypeId = "ACCOUNTS_RECEIVABLE"; 243 debitGlAccountTypeId = "ACCTRECV_WRITEOFF"; 244 } else if ("PURCHASE_INVOICE".equals(invoiceTypeId)) { 245 organizationPartyId = invoice.getString("partyId"); 246 transactionPartyId = invoice.getString("partyIdFrom"); 247 creditGlAccountTypeId = "ACCTPAY_WRITEOFF"; 248 debitGlAccountTypeId = "ACCOUNTS_PAYABLE"; 249 } else if ("COMMISSIONS_INVOICE".equals(invoiceTypeId)) { 250 organizationPartyId = invoice.getString("partyIdFrom"); 251 transactionPartyId = invoice.getString("partyId"); 252 creditGlAccountTypeId = "COMMISSIONS_WRITEOFF"; 253 debitGlAccountTypeId = "COMMISSIONS_PAYABLE"; 254 } else if ("INTEREST_INVOICE".equals(invoiceTypeId)) { 255 organizationPartyId = invoice.getString("partyIdFrom"); 256 transactionPartyId = invoice.getString("partyId"); 257 creditGlAccountTypeId = "INTRSTINC_RECEIVABLE"; 258 debitGlAccountTypeId = "INTRSTINC_WRITEOFF"; 259 } else { 260 Debug.logWarning("Invoice [" + invoiceId + "] has an unsupported invoice type of [" + invoiceTypeId + "], and its write-off transaction was not posted to the ledger", module); 261 return success; 262 } 263 264 List errorMessageList = new ArrayList(); 266 String creditGlAccountId = null; 267 String debitGlAccountId = null; 268 try { 269 creditGlAccountId = UtilAccounting.getProductOrgGlAccountId(null, creditGlAccountTypeId, organizationPartyId, delegator); 270 } catch( AccountingException e ) { 271 errorMessageList.add(UtilProperties.getMessage(resource, "FinancialsServiceErrorNoGlAccountTypeDefaultFound", UtilMisc.toMap("organizationPartyId", organizationPartyId, "glAccountTypeId", creditGlAccountTypeId), locale)); 272 } 273 try { 274 debitGlAccountId = UtilAccounting.getProductOrgGlAccountId(null, debitGlAccountTypeId, organizationPartyId, delegator); 275 } catch( AccountingException e ) { 276 errorMessageList.add(UtilProperties.getMessage(resource, "FinancialsServiceErrorNoGlAccountTypeDefaultFound", UtilMisc.toMap("organizationPartyId", organizationPartyId, "glAccountTypeId", debitGlAccountTypeId), locale)); 277 } 278 if (errorMessageList.size() > 0) { 279 return ServiceUtil.returnError(errorMessageList); 280 } 281 282 List acctgTransEntries = new ArrayList(); 283 284 Map creditAcctgTransEntryItems = new HashMap(); 285 creditAcctgTransEntryItems.put("acctgTransEntrySeqId", "1"); 286 creditAcctgTransEntryItems.put("acctgTransEntryTypeId", "_NA_"); 287 creditAcctgTransEntryItems.put("glAccountId", creditGlAccountId); 288 creditAcctgTransEntryItems.put("organizationPartyId", organizationPartyId); 289 creditAcctgTransEntryItems.put("partyId", transactionPartyId); 290 creditAcctgTransEntryItems.put("debitCreditFlag", "C"); 291 creditAcctgTransEntryItems.put("amount", new Double (invoiceUnappliedAmount.doubleValue())); 292 creditAcctgTransEntryItems.put("currencyUomId", invoice.getString("currencyUomId")); 293 acctgTransEntries.add(delegator.makeValue("AcctgTransEntry", creditAcctgTransEntryItems)); 294 295 Map debitAcctgTransEntryItems = new HashMap(); 296 debitAcctgTransEntryItems.put("acctgTransEntrySeqId", "2"); 297 debitAcctgTransEntryItems.put("acctgTransEntryTypeId", "_NA_"); 298 debitAcctgTransEntryItems.put("glAccountId", debitGlAccountId); 299 debitAcctgTransEntryItems.put("organizationPartyId", organizationPartyId); 300 debitAcctgTransEntryItems.put("partyId", transactionPartyId); 301 debitAcctgTransEntryItems.put("debitCreditFlag", "D"); 302 debitAcctgTransEntryItems.put("amount", new Double (invoiceUnappliedAmount.doubleValue())); 303 debitAcctgTransEntryItems.put("currencyUomId", invoice.getString("currencyUomId")); 304 acctgTransEntries.add(delegator.makeValue("AcctgTransEntry", debitAcctgTransEntryItems)); 305 306 Map acctgTransItems = new HashMap(); 307 acctgTransItems.put("acctgTransEntries", acctgTransEntries); 308 acctgTransItems.put("acctgTransTypeId", "WRITEOFF"); 309 acctgTransItems.put("description", "Invoice written off"); 310 acctgTransItems.put("invoiceId", invoiceId); 311 acctgTransItems.put("glFiscalTypeId", "ACTUAL"); 312 acctgTransItems.put("userLogin", userLogin); 313 Map createAcctgTransAndEntriesResult = dispatcher.runSync("createAcctgTransAndEntries", acctgTransItems); 314 315 if (ServiceUtil.isError(createAcctgTransAndEntriesResult) || ServiceUtil.isFailure(createAcctgTransAndEntriesResult)) { 316 return createAcctgTransAndEntriesResult; 317 } 318 319 } catch (GenericEntityException ee) { 320 return ServiceUtil.returnError(ee.getMessage()); 321 } catch (GenericServiceException se) { 322 return ServiceUtil.returnError(se.getMessage()); 323 } 324 325 return success; 326 } 327 328 337 private static Map processInvoiceItems( 338 GenericDelegator delegator, LocalDispatcher dispatcher, GenericValue userLogin, 339 GenericValue invoice, String acctgTransTypeId, String offsettingGlAccountTypeId, 340 String organizationPartyId, String transactionPartyId, String transactionPartyRoleTypeId, 341 String defaultDebitCreditFlag, String defaultGlAccountTypeId 342 ) 343 throws GenericEntityException, GenericServiceException { 344 345 String offsettingGlAccountId = UtilAccounting.getDefaultAccountId(offsettingGlAccountTypeId, organizationPartyId, delegator); 347 Debug.logInfo("Posting to GL for party " + organizationPartyId + " and offsetting account " + offsettingGlAccountId, module); 348 349 BigDecimal conversionFactor = new BigDecimal (UtilFinancial.determineUomConversionFactor(delegator, dispatcher, organizationPartyId, invoice.getString("currencyUomId"))); 351 352 List acctgTransEntries = new ArrayList(); BigDecimal postingTotal = new BigDecimal ("0.00"); 355 List invoiceItems = invoice.getRelatedCache("InvoiceItem", UtilMisc.toList("invoiceItemSeqId")); 356 357 Iterator invoiceItemIterator = invoiceItems.iterator(); 359 while (invoiceItemIterator.hasNext()) { 360 GenericValue invoiceItem = (GenericValue) invoiceItemIterator.next(); 361 362 if (invoiceItem.getDouble("quantity") == null) { 364 invoiceItem.set("quantity", new Double (1.0)); 365 } 366 367 BigDecimal amount = invoiceItem.getBigDecimal("amount"); 368 BigDecimal quantity = invoiceItem.getBigDecimal("quantity"); 369 370 if ((amount == null) || (amount.signum() == 0) || (quantity.signum() == 0)) { 372 continue; 373 } 374 375 String invoiceItemPostingGlAccountId = invoiceItem.getString("overrideGlAccountId"); 377 378 if (invoiceItemPostingGlAccountId == null) { 379 380 String invoiceItemTypeId = invoiceItem.getString("invoiceItemTypeId"); 383 if ((invoiceItemTypeId.equals(INVOICE_PRODUCT_ITEM_TYPE)) 384 || (invoiceItemTypeId.equals(PURCHINV_PRODUCT_ITEM_TYPE)) 385 || invoiceItemTypeId.equals(RETINV_PRODUCT_ITEM_TYPE)) { 386 invoiceItemPostingGlAccountId = UtilAccounting.getProductOrgGlAccountId(invoiceItem.getString("productId"), 387 defaultGlAccountTypeId, organizationPartyId, delegator); 388 } 389 } 390 391 Map tmpResult = null; 394 if ("SALES_INVOICE".equals(invoice.getString("invoiceTypeId"))) { 395 tmpResult = processSalesInvoiceItem( 396 delegator, dispatcher, userLogin, 397 invoice, invoiceItem, acctgTransEntries, 398 postingTotal, conversionFactor, amount, quantity, 399 invoiceItemPostingGlAccountId, acctgTransTypeId, offsettingGlAccountTypeId, 400 organizationPartyId, transactionPartyId, transactionPartyRoleTypeId, 401 defaultDebitCreditFlag, defaultGlAccountTypeId 402 ); 403 } else { tmpResult = processPurchaseInvoiceItem( 405 delegator, dispatcher, userLogin, 406 invoice, invoiceItem, acctgTransEntries, 407 postingTotal, conversionFactor, amount, quantity, 408 invoiceItemPostingGlAccountId, acctgTransTypeId, offsettingGlAccountTypeId, 409 organizationPartyId, transactionPartyId, transactionPartyRoleTypeId, 410 defaultDebitCreditFlag, defaultGlAccountTypeId 411 ); 412 } 413 if (ServiceUtil.isError(tmpResult)) return tmpResult; 414 415 if (Debug.verboseOn()) { 416 Debug.logVerbose("invoiceItem " + invoiceItem.getString("invoiceId") + ", " + invoiceItem.getString("invoiceItemSeqId") + ": gl account = " 417 + invoiceItemPostingGlAccountId + ", amount = " + invoiceItem.getDouble("amount") + ", quantity = " 418 + invoiceItem.getDouble("quantity") + ", default debit/credit flag = " + defaultDebitCreditFlag, module); 419 } 420 postingTotal = (BigDecimal ) tmpResult.get("postingTotal"); 421 } 422 return UtilMisc.toMap("offsettingGlAccountId", offsettingGlAccountId, "acctgTransEntries", acctgTransEntries, "postingTotal", new Double (postingTotal.doubleValue())); 423 } 424 425 431 private static Map processPurchaseInvoiceItem( 432 GenericDelegator delegator, LocalDispatcher dispatcher, GenericValue userLogin, 433 GenericValue invoice, GenericValue invoiceItem, List acctgTransEntries, 434 BigDecimal postingTotal, BigDecimal conversionFactor, BigDecimal amount, BigDecimal quantity, 435 String invoiceItemPostingGlAccountId, String acctgTransTypeId, String offsettingGlAccountTypeId, 436 String organizationPartyId, String transactionPartyId, String transactionPartyRoleTypeId, 437 String defaultDebitCreditFlag, String defaultGlAccountTypeId 438 ) throws GenericServiceException, GenericEntityException { 439 440 int decimals = UtilNumber.getBigDecimalScale("invoice.decimals"); 441 int rounding = UtilNumber.getBigDecimalRoundingMode("invoice.rounding"); 442 443 BigDecimal postingAmount = conversionFactor.multiply(amount).multiply(quantity).setScale(decimals, rounding); 445 postingTotal = postingTotal.add(postingAmount); 446 447 BigDecimal orderAmount = new BigDecimal ("0.00"); 450 List orderItemBillings = invoiceItem.getRelated("OrderItemBilling"); 451 for (Iterator iter = orderItemBillings.iterator(); iter.hasNext(); ) { 452 GenericValue orderItemBilling = (GenericValue) iter.next(); 453 GenericValue orderItem = orderItemBilling.getRelatedOne("OrderItem"); 454 orderAmount = orderAmount.add(conversionFactor 455 .multiply(orderItem.getBigDecimal("unitPrice")) 456 .multiply(orderItem.getBigDecimal("quantity")) 457 .setScale(decimals, rounding)); 458 } 459 460 if (orderItemBillings.size() == 0) { 462 invoiceItemPostingGlAccountId = getDefaultGlAccount(invoiceItem, organizationPartyId); 463 orderAmount = postingAmount; 464 } 465 466 if ((invoiceItemPostingGlAccountId == null) || (invoiceItemPostingGlAccountId.equals(""))) { 468 return ServiceUtil.returnError("Cannot find posting GL account for invoice item " + invoiceItem); 469 } 470 471 Map acctgTransEntry = new HashMap(); 473 acctgTransEntry.put("glAccountId", invoiceItemPostingGlAccountId); 474 acctgTransEntry.put("debitCreditFlag", defaultDebitCreditFlag); 475 acctgTransEntry.put("organizationPartyId", organizationPartyId); 476 acctgTransEntry.put("partyId", transactionPartyId); 477 acctgTransEntry.put("roleTypeId", transactionPartyRoleTypeId); 478 acctgTransEntry.put("acctgTransEntryTypeId", "_NA_"); 479 acctgTransEntry.put("productId", invoiceItem.getString("productId")); 480 acctgTransEntry.put("amount", new Double (orderAmount.doubleValue())); 481 acctgTransEntries.add(acctgTransEntry); 482 483 BigDecimal varianceAmount = postingAmount.subtract(orderAmount); 485 if (Debug.verboseOn()) { 486 Debug.logVerbose("Purchase InvoiceItem: orderAmount ["+orderAmount+"], postingAmount ["+postingAmount+"], varianceAmount["+varianceAmount+"]", module); 487 } 488 489 if (varianceAmount.signum() != 0) { 491 492 String varianceGlAccountId = UtilAccounting.getDefaultAccountId("PURCHASE_PRICE_VAR", organizationPartyId, delegator); 494 495 acctgTransEntry = new HashMap(acctgTransEntry); 497 acctgTransEntry.put("glAccountId", varianceGlAccountId); 498 acctgTransEntry.put("amount", new Double (varianceAmount.doubleValue())); 499 acctgTransEntries.add(acctgTransEntry); 500 } 501 502 return UtilMisc.toMap("postingTotal", postingTotal); 503 } 504 505 509 private static Map processSalesInvoiceItem( 510 GenericDelegator delegator, LocalDispatcher dispatcher, GenericValue userLogin, 511 GenericValue invoice, GenericValue invoiceItem, List acctgTransEntries, 512 BigDecimal postingTotal, BigDecimal conversionFactor, BigDecimal amount, BigDecimal quantity, 513 String invoiceItemPostingGlAccountId, String acctgTransTypeId, String offsettingGlAccountTypeId, 514 String organizationPartyId, String transactionPartyId, String transactionPartyRoleTypeId, 515 String defaultDebitCreditFlag, String defaultGlAccountTypeId 516 ) throws GenericServiceException, GenericEntityException { 517 518 int decimals = UtilNumber.getBigDecimalScale("invoice.decimals"); 519 int rounding = UtilNumber.getBigDecimalRoundingMode("invoice.rounding"); 520 521 if ((invoiceItemPostingGlAccountId == null) || invoiceItemPostingGlAccountId.equals("")) { 523 invoiceItemPostingGlAccountId = getDefaultGlAccount(invoiceItem, organizationPartyId); 524 } 525 526 if ((invoiceItemPostingGlAccountId == null) || (invoiceItemPostingGlAccountId.equals(""))) { 528 Debug.logError("Canot find GL account to post for this invoice item " + invoiceItem, module); 529 return ServiceUtil.returnError("Cannot find posting GL account for invoice " + invoiceItem.getString("invoiceId") 530 + ", item " + invoiceItem.getString("invoiceItemSeqId")); 531 } 532 533 Map acctgTransEntry = new HashMap(); 536 acctgTransEntry.put("glAccountId", invoiceItemPostingGlAccountId); 537 acctgTransEntry.put("debitCreditFlag", defaultDebitCreditFlag); 538 acctgTransEntry.put("organizationPartyId", organizationPartyId); 539 acctgTransEntry.put("acctgTransEntryTypeId", "_NA_"); 540 acctgTransEntry.put("productId", invoiceItem.getString("productId")); 541 542 BigDecimal postingAmount = amount.multiply(conversionFactor).multiply(quantity).setScale(decimals, rounding); 544 acctgTransEntry.put("amount", new Double (postingAmount.doubleValue())); 545 546 if (invoiceItem.getString("taxAuthPartyId") != null) { 548 acctgTransEntry.put("partyId", invoiceItem.getString("taxAuthPartyId")); 550 acctgTransEntry.put("roleTypeId", "TAX_AUTHORITY"); 551 } else { 552 acctgTransEntry.put("partyId", transactionPartyId); 554 acctgTransEntry.put("roleTypeId", transactionPartyRoleTypeId); 555 } 556 557 acctgTransEntries.add(acctgTransEntry); 559 postingTotal = postingTotal.add(postingAmount); 561 563 if (!(invoiceItem.getString("invoiceItemTypeId").equals("INV_FPROD_ITEM") && (invoiceItem.getString("productId") != null))) { 565 return UtilMisc.toMap("postingTotal", postingTotal); 566 } 567 568 return UtilMisc.toMap("postingTotal", postingTotal); 569 } 570 571 578 private static String getDefaultGlAccount(GenericValue invoiceItem, String organizationPartyId) throws GenericEntityException { 579 if (invoiceItem.getString("overrideGlAccountId") != null) return invoiceItem.getString("overrideGlAccountId"); 580 GenericValue invoiceItemType = invoiceItem.getRelatedOne("InvoiceItemType"); 581 List orgInvoiceItemTypeGlAccounts = invoiceItemType.getRelatedByAnd("InvoiceItemTypeGlAccount", UtilMisc.toMap("organizationPartyId", organizationPartyId)); 582 if ((orgInvoiceItemTypeGlAccounts != null) && (orgInvoiceItemTypeGlAccounts.size() == 1)) { 583 return ((GenericValue) orgInvoiceItemTypeGlAccounts.get(0)).getString("glAccountId"); 584 } else { 585 return invoiceItemType.getString("defaultGlAccountId"); 586 } 587 } 588 589 590 591 592 593 594 595 601 public static Map postPaymentToGl(DispatchContext dctx, Map context) { 602 GenericDelegator delegator = dctx.getDelegator(); 603 LocalDispatcher dispatcher = dctx.getDispatcher(); 604 GenericValue userLogin = (GenericValue) context.get("userLogin"); 605 606 String paymentId = (String ) context.get("paymentId"); 607 try { 608 GenericValue payment = delegator.findByPrimaryKey("Payment", UtilMisc.toMap("paymentId", paymentId)); 609 610 Map results = dispatcher.runSync("getPaymentAccountAndParties", UtilMisc.toMap("paymentId", paymentId)); 612 if (results.get(ModelService.RESPONSE_MESSAGE).equals(ModelService.RESPOND_ERROR)) { 613 return results; 614 } 615 String organizationPartyId = (String ) results.get("organizationPartyId"); 616 String transactionPartyId = (String ) results.get("transactionPartyId"); 617 String paymentGlAccountId = (String ) results.get("glAccountId"); 618 619 double conversionFactor = UtilFinancial.determineUomConversionFactor(delegator, dispatcher, organizationPartyId, payment.getString("currencyUomId")); 621 if (payment.getDouble("amount") == null) { 622 return ServiceUtil.returnError("Cannot post Payment to GL: Payment with paymentId " + paymentId + " has no amount."); 623 } 624 double transactionAmount = conversionFactor * payment.getDouble("amount").doubleValue(); 625 626 Map paymentGlAccountAmounts = UtilMisc.toMap(paymentGlAccountId, new Double (transactionAmount)); 630 Map offsettingGlAccountAmounts = new HashMap(); 631 632 if (UtilAccounting.isTaxPayment(payment)) { 633 List paymentApplications = payment.getRelated("PaymentApplication"); 636 for (Iterator pAi = paymentApplications.iterator(); pAi.hasNext(); ) { 637 GenericValue appl = (GenericValue) pAi.next(); 638 if (appl.getString("taxAuthGeoId") != null) { 639 GenericValue taxAuthGlAccount = delegator.findByPrimaryKeyCache("TaxAuthorityGlAccount", 640 UtilMisc.toMap("organizationPartyId", organizationPartyId, "taxAuthPartyId", transactionPartyId, "taxAuthGeoId", appl.getString("taxAuthGeoId"))); 641 offsettingGlAccountAmounts.put(taxAuthGlAccount.getString("glAccountId"), new Double (appl.getDouble("amountApplied").doubleValue() * conversionFactor)); 642 } 643 } 644 } else { 645 String offsettingGlAccountId = getOffsettingPaymentGlAccount(dispatcher, payment, organizationPartyId, userLogin); 646 offsettingGlAccountAmounts.put(offsettingGlAccountId, new Double (transactionAmount)); 647 } 648 649 Map creditGlAccountAmounts = null; 651 Map debitGlAccountAmounts = null; 652 if (UtilAccounting.isDisbursement(payment)) { 653 creditGlAccountAmounts = paymentGlAccountAmounts; 654 debitGlAccountAmounts = offsettingGlAccountAmounts; 655 } else if (UtilAccounting.isReceipt(payment)) { 656 creditGlAccountAmounts = offsettingGlAccountAmounts; 657 debitGlAccountAmounts = paymentGlAccountAmounts; 658 } else { 659 return ServiceUtil.returnError("Cannot Post Payment to GL: Payment with paymentId " + paymentId 660 + " has unsupported paymentTypeId " + payment.getString("paymentTypeId") + 661 " (Must be or have a parent type of DISBURSEMENT or RECEIPT.)"); 662 } 663 664 if ((creditGlAccountAmounts == null) || (creditGlAccountAmounts.keySet().size() == 0)) { 665 return ServiceUtil.returnError("No credit GL accounts found for payment posting"); 666 } 667 if (debitGlAccountAmounts == null) { 668 return ServiceUtil.returnError("No debit GL accounts found for payment posting"); 669 } 670 671 List acctgTransEntries = makePaymentEntries(creditGlAccountAmounts, debitGlAccountAmounts, 672 organizationPartyId, transactionPartyId, delegator); 673 674 Map tmpMap = UtilMisc.toMap("acctgTransEntries", acctgTransEntries, 676 "glFiscalTypeId", "ACTUAL", "acctgTransTypeId", "PAYMENT_ACCTG_TRANS", 677 "transactionDate", UtilDateTime.nowTimestamp(), "userLogin", userLogin); 678 tmpMap.put("paymentId", paymentId); 679 tmpMap.put("partyId", transactionPartyId); 680 tmpMap = dispatcher.runSync("createAcctgTransAndEntries", tmpMap); 681 682 if (((String ) tmpMap.get(ModelService.RESPONSE_MESSAGE)).equals(ModelService.RESPOND_SUCCESS)) { 683 results = ServiceUtil.returnSuccess(); 684 results.put("acctgTransId", tmpMap.get("acctgTransId")); 685 return(results); 686 } else { 687 return tmpMap; 688 } 689 } catch (GenericEntityException ex) { 690 return(ServiceUtil.returnError(ex.getMessage())); 691 } catch (GenericServiceException ex) { 692 return(ServiceUtil.returnError(ex.getMessage())); 693 } 694 } 695 696 705 public static String getOffsettingPaymentGlAccount(LocalDispatcher dispatcher, GenericValue payment, String organizationPartyId, GenericValue userLogin) 706 throws GenericServiceException, GenericEntityException { 707 List tmpList = payment.getRelatedOne("PaymentType").getRelatedByAnd("PaymentGlAccountTypeMap", UtilMisc.toMap("organizationPartyId", organizationPartyId)); 709 if (tmpList.size() == 0) { 710 throw new AccountingException("Offsetting GL account for payment type " + payment.getString("paymentTypeId") 711 + " of organization " + organizationPartyId + " has not been configured."); 712 } 713 String offsettingGlAccountTypeId = ((GenericValue) tmpList.get(0)).getString("glAccountTypeId"); 714 715 return UtilAccounting.getDefaultAccountId(offsettingGlAccountTypeId, organizationPartyId, userLogin.getDelegator()); 717 } 718 719 727 private static List makePaymentEntries(Map creditGlAccountAmounts, Map debitGlAccountAmounts, 728 String organizationPartyId, String transactionPartyId, GenericDelegator delegator) throws GenericEntityException { 729 List acctgTransEntries = new LinkedList(); 730 int itemSeq = 1; 731 for (Iterator ai = creditGlAccountAmounts.keySet().iterator(); ai.hasNext(); ) { 732 String creditGlAccountId = (String ) ai.next(); 733 Map tmpMap = UtilMisc.toMap("glAccountId", creditGlAccountId, "debitCreditFlag", "C", 734 "amount", creditGlAccountAmounts.get(creditGlAccountId), "acctgTransEntrySeqId", Integer.toString(itemSeq), 735 "organizationPartyId", organizationPartyId, "acctgTransEntryTypeId", "_NA_"); 736 tmpMap.put("partyId", transactionPartyId); 737 GenericValue creditAcctTransEntry = delegator.makeValue("AcctgTransEntry", tmpMap); 738 acctgTransEntries.add(creditAcctTransEntry); 739 itemSeq++; 740 } 741 742 for (Iterator ai = debitGlAccountAmounts.keySet().iterator(); ai.hasNext(); ) { 743 String debitGlAccountId = (String ) ai.next(); 744 Map tmpMap = UtilMisc.toMap("glAccountId", debitGlAccountId, "debitCreditFlag", "D", 745 "amount", debitGlAccountAmounts.get(debitGlAccountId), "acctgTransEntrySeqId", Integer.toString(itemSeq), 746 "organizationPartyId", organizationPartyId, "acctgTransEntryTypeId", "_NA_"); 747 tmpMap.put("partyId", transactionPartyId); 748 GenericValue debitAcctTransEntry = delegator.makeValue("AcctgTransEntry", tmpMap); 749 acctgTransEntries.add(debitAcctTransEntry); 750 itemSeq++; 751 } 752 753 return acctgTransEntries; 754 } 755 756 762 public static Map getPaymentAccountAndParties(DispatchContext dctx, Map context) { 763 GenericDelegator delegator = dctx.getDelegator(); 764 LocalDispatcher dispatcher = dctx.getDispatcher(); 765 GenericValue userLogin = (GenericValue) context.get("userLogin"); 766 767 String paymentId = (String ) context.get("paymentId"); 768 Map result = ServiceUtil.returnSuccess(); 770 String organizationPartyId = null; 771 String transactionPartyId = null; 772 String glAccountId = null; 773 try { 774 GenericValue payment = delegator.findByPrimaryKey("Payment", UtilMisc.toMap("paymentId", paymentId)); 775 if (payment == null) { 776 return ServiceUtil.returnError("Payment " + paymentId + " doesn't exist!"); 777 } 778 779 if (UtilAccounting.isDisbursement(payment)) { 781 organizationPartyId = payment.getString("partyIdFrom"); 782 transactionPartyId = payment.getString("partyIdTo"); 783 } else if (UtilAccounting.isReceipt(payment)) { 784 organizationPartyId = payment.getString("partyIdTo"); 785 transactionPartyId = payment.getString("partyIdFrom"); 786 } else { 787 return ServiceUtil.returnError("Payment with paymentId " + paymentId + " has a type which is not DISBURSEMENT or RECEIPT."); 788 } 789 result.put("organizationPartyId", organizationPartyId); 790 result.put("transactionPartyId", transactionPartyId); 791 792 GenericValue paymentMethod = payment.getRelatedOne("PaymentMethod"); 794 if (paymentMethod != null) { 795 glAccountId = paymentMethod.getString("glAccountId"); 796 if (glAccountId != null) { 797 result.put("glAccountId", glAccountId); 798 return result; 799 } 800 } 801 802 if ("CREDIT_CARD".equals(payment.getString("paymentMethodTypeId"))) { 804 GenericValue cc = payment.getRelatedOne("CreditCard"); 805 if (cc == null) { 806 Debug.logWarning("Cannot find Gl Account from CreditCartTypeGlAccount: Credit Card not found for Payment with paymentId " + payment.getString("paymentId") + ". Trying Gl Account for Credit Cards or default Gl Account instead.", module); 807 } else { 808 GenericValue ccGlAccount = delegator.findByPrimaryKey("CreditCardTypeGlAccount", UtilMisc.toMap("organizationPartyId", organizationPartyId, "cardType", cc.getString("cardType"))); 809 if (ccGlAccount != null) { 810 result.put("glAccountId", ccGlAccount.getString("glAccountId")); 811 return result; 812 } 813 } 814 } 815 816 List tmpList = payment.getRelatedOne("PaymentMethodType").getRelatedByAnd("PaymentMethodTypeGlAccount", 818 UtilMisc.toMap("organizationPartyId", organizationPartyId)); 819 if (tmpList.size() > 0) { 820 GenericValue paymentMethodTypeGlAccount = (GenericValue) tmpList.get(0); 821 glAccountId = paymentMethodTypeGlAccount.getString("glAccountId"); 822 if (glAccountId != null) { 823 result.put("glAccountId", glAccountId); 824 return result; 825 } 826 } 827 828 GenericValue paymentMethodType = payment.getRelatedOne("PaymentMethodType"); 830 if (paymentMethodType != null) { 831 glAccountId = paymentMethodType.getString("defaultGlAccountId"); 832 if (glAccountId != null) { 833 result.put("glAccountId", glAccountId); 834 return result; 835 } 836 } 837 838 return ServiceUtil.returnError("No GL Account found for Payment with paymentId " + paymentId); 839 } catch (GenericEntityException ex) { 840 return(ServiceUtil.returnError(ex.getMessage())); 841 } 842 } 843 844 847 public static Map matchPaymentInvoiceGlPosts(DispatchContext dctx, Map context) { 848 GenericDelegator delegator = dctx.getDelegator(); 849 LocalDispatcher dispatcher = dctx.getDispatcher(); 850 GenericValue userLogin = (GenericValue) context.get("userLogin"); 851 852 String paymentApplicationId = (String ) context.get("paymentApplicationId"); 853 try { 854 GenericValue paymentApplication = delegator.findByPrimaryKey("PaymentApplication", UtilMisc.toMap("paymentApplicationId", paymentApplicationId)); 855 GenericValue payment = paymentApplication.getRelatedOne("Payment"); 856 GenericValue invoice = paymentApplication.getRelatedOne("Invoice"); 857 String paymentId = payment.getString("paymentId"); 858 String invoiceId = invoice.getString("invoiceId"); 859 860 if (invoice == null) { 861 throw new GenericServiceException("Could not find Invoice with ID [" + invoiceId + "]"); 862 } 863 864 String organizationPartyId = null; 866 String paymentOffsetDebitCreditFlag = null; 867 String invoiceOffsetDebitCreditFlag = null; 868 String invoiceOffsettingGlAccountTypeId = null; 869 String transactionPartyId = payment.getString("partyIdTo"); 870 String transactionPartyRoleTypeId = payment.getString("roleTypeIdTo"); 871 String acctgTransTypeId = "OTHER_INTERNAL_ACCTG"; 872 873 if ((UtilAccounting.isDisbursement(payment)) && (invoice.getString("invoiceTypeId").equals("PURCHASE_INVOICE"))) { 876 organizationPartyId = payment.getString("partyIdFrom"); 877 paymentOffsetDebitCreditFlag = "D"; 878 invoiceOffsetDebitCreditFlag = "C"; 879 invoiceOffsettingGlAccountTypeId = "ACCOUNTS_PAYABLE"; 880 } else if ((UtilAccounting.isReceipt(payment)) && (invoice.getString("invoiceTypeId").equals("SALES_INVOICE"))) { organizationPartyId = payment.getString("partyIdTo"); 882 paymentOffsetDebitCreditFlag = "C"; 883 invoiceOffsetDebitCreditFlag = "D"; 884 invoiceOffsettingGlAccountTypeId = "ACCOUNTS_RECEIVABLE"; 885 } else { 886 return ServiceUtil.returnSuccess(); 888 } 889 890 String paymentOffsettingGlAccountId = getOffsettingPaymentGlAccount(dispatcher, payment, organizationPartyId, userLogin); 892 893 String invoiceOffsettingGlAccountId = UtilAccounting.getDefaultAccountId(invoiceOffsettingGlAccountTypeId, organizationPartyId, delegator); 895 896 if (paymentOffsettingGlAccountId == invoiceOffsettingGlAccountId) { 898 if (Debug.verboseOn()) { 899 Debug.logVerbose("Matching payment to invoice: Payment and Invoice offsetting accounts were identical. No need to match.", module); 900 } 901 return ServiceUtil.returnSuccess(); 902 } 903 904 Map input = new HashMap(); 906 input.put("glAccountId", paymentOffsettingGlAccountId); 907 input.put("acctgTransEntrySeqId", "1"); 908 input.put("organizationPartyId", organizationPartyId); 909 input.put("partyId", transactionPartyId); 910 input.put("roleTypeId", transactionPartyRoleTypeId); 911 input.put("debitCreditFlag", invoiceOffsetDebitCreditFlag); input.put("amount", paymentApplication.getDouble("amountApplied")); 913 input.put("acctgTransEntryTypeId", "_NA_"); 914 input.put("description", "Matching GL accounts for invoice " + invoiceId + " and payment " + paymentId); 915 GenericValue paymentEntry = delegator.makeValue("AcctgTransEntry", input); 916 917 input = new HashMap(); 919 input.put("glAccountId", invoiceOffsettingGlAccountId); 920 input.put("acctgTransEntrySeqId", "2"); 921 input.put("organizationPartyId", organizationPartyId); 922 input.put("partyId", transactionPartyId); 923 input.put("roleTypeId", transactionPartyRoleTypeId); 924 input.put("debitCreditFlag", paymentOffsetDebitCreditFlag); input.put("amount", paymentApplication.getDouble("amountApplied")); 926 input.put("acctgTransEntryTypeId", "_NA_"); 927 input.put("description", "Matching GL accounts for invoice " + invoiceId + " and payment " + paymentId); 928 GenericValue invoiceEntry = delegator.makeValue("AcctgTransEntry", input); 929 930 input = new HashMap(); 932 input.put("acctgTransEntries", UtilMisc.toList(paymentEntry, invoiceEntry)); 933 input.put("invoiceId", invoiceId); 934 input.put("partyId", transactionPartyId); 935 input.put("roleTypeId", transactionPartyRoleTypeId); 936 input.put("glFiscalTypeId", "ACTUAL"); 937 input.put("acctgTransTypeId", acctgTransTypeId); 938 input.put("userLogin", userLogin); 939 940 return dispatcher.runSync("createAcctgTransAndEntries", input); 942 943 } catch (GenericEntityException ee) { 944 return ServiceUtil.returnError(ee.getMessage()); 945 } catch (GenericServiceException se) { 946 return ServiceUtil.returnError(se.getMessage()); 947 } 948 } 949 950 957 public static Map postInventoryVarianceToGl(DispatchContext dctx, Map context) { 958 GenericDelegator delegator = dctx.getDelegator(); 959 LocalDispatcher dispatcher = dctx.getDispatcher(); 960 GenericValue userLogin = (GenericValue) context.get("userLogin"); 961 962 String inventoryItemId = (String ) context.get("inventoryItemId"); 963 String physicalInventoryId = (String ) context.get("physicalInventoryId"); 964 try { 965 Map tmpMap = new HashMap(); 966 967 GenericValue inventoryVariance = delegator.findByPrimaryKey("InventoryItemVariance", 968 UtilMisc.toMap("inventoryItemId", inventoryItemId, "physicalInventoryId", physicalInventoryId)); 969 if (inventoryVariance == null) { 970 return ServiceUtil.returnError("No InventoryVariance entity record for inventoryItemId " + inventoryItemId + " and physicalInventoryId " + physicalInventoryId); 971 } 972 973 BigDecimal quantityOnHandVar = inventoryVariance.getBigDecimal("quantityOnHandVar"); 974 if (quantityOnHandVar == null || quantityOnHandVar.compareTo(ZERO) == 0) { 975 return ServiceUtil.returnSuccess(); 977 } 978 979 GenericValue inventoryItem = inventoryVariance.getRelatedOne("InventoryItem"); 980 String productId = inventoryItem.getString("productId"); 981 String ownerPartyId = inventoryItem.getString("ownerPartyId"); 983 BigDecimal unitCost = inventoryItem.getBigDecimal("unitCost"); 985 BigDecimal conversionFactor = new BigDecimal (UtilFinancial.determineUomConversionFactor(delegator, dispatcher, ownerPartyId, inventoryItem.getString("currencyUomId"))); 987 if (unitCost == null) { 989 return ServiceUtil.returnError("Could not determine unitCost of product [" + productId + 990 "] for inventory variance [" + physicalInventoryId + 991 "] and inventory item [" + inventoryItemId + "]"); 992 } 993 unitCost = unitCost.multiply(conversionFactor).setScale(decimals, rounding); 995 BigDecimal transactionAmount = unitCost.multiply(quantityOnHandVar).setScale(decimals, rounding); 997 998 GenericValue acctgPref = delegator.findByPrimaryKeyCache("PartyAcctgPreference", UtilMisc.toMap("partyId", ownerPartyId)); 1000 String cogsMethodId = acctgPref.getString("cogsMethodId"); 1001 1002 BigDecimal inventoryAdjAmount = null; 1004 if ((cogsMethodId != null) && (cogsMethodId.equals("COGS_AVG_COST"))) { 1005 BigDecimal prodAvgCost = UtilCOGS.getProductAverageCost(productId, ownerPartyId, userLogin, delegator, dispatcher); 1006 if (prodAvgCost == null) return ServiceUtil.returnError("Unable to find a product average cost for product ["+productId+"] in organization ["+ownerPartyId+"]"); 1007 inventoryAdjAmount = prodAvgCost.subtract(unitCost).multiply(quantityOnHandVar).setScale(decimals, rounding); 1010 } 1011 1012 String invGlAcctId = UtilAccounting.getProductOrgGlAccountId(productId, "INVENTORY_ACCOUNT", ownerPartyId, delegator); 1014 1015 GenericValue varianceReason = inventoryVariance.getRelatedOne("VarianceReason"); 1022 GenericValue varExpGlAcct = EntityUtil.getFirst(varianceReason.getRelatedByAnd("VarianceReasonGlAccount", UtilMisc.toMap("organizationPartyId", ownerPartyId))); 1023 if (varExpGlAcct == null) { 1024 return ServiceUtil.returnError("Could not find Variance Expense GL Account for variance reason ["+varianceReason.get("description")+"]."); 1025 } 1026 String varExpGlAcctId = (String ) varExpGlAcct.get("glAccountId"); 1027 1028 tmpMap = UtilMisc.toMap("glAccountId", varExpGlAcctId, "debitCreditFlag", "C", 1031 "amount", new Double (transactionAmount.doubleValue()), "acctgTransEntrySeqId", Integer.toString(0), 1032 "organizationPartyId", ownerPartyId, "acctgTransEntryTypeId", "_NA_"); 1033 tmpMap.put("productId", productId); 1034 GenericValue varExpGlAcctTrans = delegator.makeValue("AcctgTransEntry", tmpMap); 1035 1036 tmpMap = UtilMisc.toMap("glAccountId", invGlAcctId, "debitCreditFlag", "D", 1038 "amount", new Double (transactionAmount.doubleValue()), "acctgTransEntrySeqId", Integer.toString(1), 1039 "organizationPartyId", ownerPartyId, "acctgTransEntryTypeId", "_NA_"); 1040 tmpMap.put("productId", productId); 1041 GenericValue invGlAcctTrans = delegator.makeValue("AcctgTransEntry", tmpMap); 1042 1043 List transEntries = UtilMisc.toList(varExpGlAcctTrans, invGlAcctTrans); 1044 1045 if ((inventoryAdjAmount != null) && (inventoryAdjAmount.compareTo(ZERO) != 0)) { 1047 String invGlAcctAdjId = UtilAccounting.getProductOrgGlAccountId(productId, "INV_ADJ_AVG_COST", ownerPartyId, delegator); 1049 tmpMap = UtilMisc.toMap("glAccountId", varExpGlAcctId, "debitCreditFlag", "C", 1054 "amount", new Double (inventoryAdjAmount.doubleValue()), "acctgTransEntrySeqId", Integer.toString(0), 1055 "organizationPartyId", ownerPartyId, "acctgTransEntryTypeId", "_NA_"); 1056 tmpMap.put("productId", productId); 1057 GenericValue varExpGlAcctAdjTrans = delegator.makeValue("AcctgTransEntry", tmpMap); 1058 transEntries.add(varExpGlAcctAdjTrans); 1059 1060 tmpMap = UtilMisc.toMap("glAccountId", invGlAcctAdjId, "debitCreditFlag", "D", 1062 "amount", new Double (inventoryAdjAmount.doubleValue()), "acctgTransEntrySeqId", Integer.toString(1), 1063 "organizationPartyId", ownerPartyId, "acctgTransEntryTypeId", "_NA_"); 1064 tmpMap.put("productId", productId); 1065 GenericValue invGlAcctAdjTrans = delegator.makeValue("AcctgTransEntry", tmpMap); 1066 transEntries.add(invGlAcctAdjTrans); 1067 } 1068 tmpMap = UtilMisc.toMap("acctgTransEntries", transEntries, 1070 "glFiscalTypeId", "ACTUAL", "acctgTransTypeId", "ITEM_VARIANCE_ACCTG_", 1071 "transactionDate", UtilDateTime.nowTimestamp(), 1072 "userLogin", userLogin); 1073 tmpMap.put("inventoryItemId", inventoryItemId); 1074 tmpMap.put("physicalInventoryId", physicalInventoryId); 1075 tmpMap = dispatcher.runSync("createAcctgTransAndEntries", tmpMap); 1076 1077 if (ServiceUtil.isError(tmpMap)) { 1078 return tmpMap; 1079 } 1080 Map result = ServiceUtil.returnSuccess(); 1081 result.put("acctgTransId", tmpMap.get("acctgTransId")); 1082 return result; 1083 } catch (GenericEntityException ex) { 1084 return(ServiceUtil.returnError(ex.getMessage())); 1085 } catch (GenericServiceException ex) { 1086 return(ServiceUtil.returnError(ex.getMessage())); 1087 } 1088 } 1089 1090 1094 public static Map postShipmentToGl(DispatchContext dctx, Map context) { 1095 GenericDelegator delegator = dctx.getDelegator(); 1096 LocalDispatcher dispatcher = dctx.getDispatcher(); 1097 GenericValue userLogin = (GenericValue) context.get("userLogin"); 1098 1099 String shipmentId = (String ) context.get("shipmentId"); 1100 try { 1101 List issuances = delegator.findByAnd("ItemIssuance", UtilMisc.toMap("shipmentId", shipmentId)); 1102 Iterator issuancesIt = issuances.iterator(); 1103 List transEntries = new ArrayList(); 1104 Map input = null; 1105 String partyIdTo = null; 1106 while (issuancesIt.hasNext()) { 1107 GenericValue itemIssuance = (GenericValue)issuancesIt.next(); 1108 GenericValue inventoryItem = itemIssuance.getRelatedOne("InventoryItem"); 1109 1110 GenericValue orderHeader = itemIssuance.getRelatedOne("OrderHeader"); 1111 GenericValue orderRole = EntityUtil.getFirst(orderHeader.getRelatedByAnd("OrderRole", UtilMisc.toMap("roleTypeId", "BILL_TO_CUSTOMER"))); 1112 partyIdTo = orderRole.getString("partyId"); 1113 1114 String productId = inventoryItem.getString("productId"); 1115 BigDecimal quantityIssued = itemIssuance.getBigDecimal("quantity"); 1116 String ownerPartyId = inventoryItem.getString("ownerPartyId"); 1118 BigDecimal unitCost = inventoryItem.getBigDecimal("unitCost"); 1120 BigDecimal conversionFactor = new BigDecimal (UtilFinancial.determineUomConversionFactor(delegator, dispatcher, ownerPartyId, inventoryItem.getString("currencyUomId"))); 1122 if (unitCost == null) { 1124 return ServiceUtil.returnError("Could not determine unitCost of product [" + productId + 1125 "] for item issuance [" + itemIssuance.getString("itemIssuanceId") + "] and inventory item [" + inventoryItem + "]"); 1126 } 1127 unitCost = unitCost.multiply(conversionFactor).setScale(decimals, rounding); 1129 BigDecimal transactionAmount = unitCost.multiply(quantityIssued).setScale(decimals, rounding); 1130 String invGlAcctId = UtilAccounting.getProductOrgGlAccountId(productId, "INVENTORY_ACCOUNT", ownerPartyId, delegator); 1132 String invGlAcctCogsId = UtilAccounting.getProductOrgGlAccountId(productId, "COGS_ACCOUNT", ownerPartyId, delegator); 1133 1134 input = UtilMisc.toMap("glAccountId", invGlAcctId, "organizationPartyId", ownerPartyId, "partyId", partyIdTo); 1136 input.put("productId", productId); 1137 input.put("amount", new Double (transactionAmount.doubleValue())); 1138 input.put("acctgTransEntryTypeId", "_NA_"); 1139 input.put("debitCreditFlag", "C"); 1140 input.put("acctgTransEntrySeqId", Integer.toString(0)); 1141 input.put("roleTypeId", "BILL_TO_CUSTOMER"); 1142 GenericValue creditAcctTrans = delegator.makeValue("AcctgTransEntry", input); 1143 transEntries.add(creditAcctTrans); 1144 1145 input = UtilMisc.toMap("glAccountId", invGlAcctCogsId, "organizationPartyId", ownerPartyId, "partyId", partyIdTo); 1147 input.put("productId", productId); 1148 input.put("amount", new Double (transactionAmount.doubleValue())); 1149 input.put("acctgTransEntryTypeId", "_NA_"); 1150 input.put("debitCreditFlag", "D"); 1151 input.put("acctgTransEntrySeqId", Integer.toString(1)); 1152 input.put("roleTypeId", "BILL_TO_CUSTOMER"); 1153 GenericValue debitAcctTrans = delegator.makeValue("AcctgTransEntry", input); 1154 transEntries.add(debitAcctTrans); 1155 1156 GenericValue acctgPref = delegator.findByPrimaryKeyCache("PartyAcctgPreference", UtilMisc.toMap("partyId", ownerPartyId)); 1158 String cogsMethodId = acctgPref.getString("cogsMethodId"); 1159 BigDecimal inventoryAdjAmount = null; 1160 if ((cogsMethodId != null) && (cogsMethodId.equals("COGS_AVG_COST"))) { 1161 BigDecimal prodAvgCost = UtilCOGS.getProductAverageCost(productId, ownerPartyId, userLogin, delegator, dispatcher); 1162 if (prodAvgCost == null) { 1163 Debug.logWarning("Unable to find a product average cost for product ["+productId+"] in organization ["+ownerPartyId+"], assuming zero", module); 1164 prodAvgCost = ZERO; 1165 } 1166 inventoryAdjAmount = prodAvgCost.subtract(unitCost).multiply(quantityIssued).setScale(decimals, rounding); 1169 } 1170 if ((inventoryAdjAmount != null) && (inventoryAdjAmount.compareTo(ZERO) != 0)) { 1172 String invGlAcctAdjId = UtilAccounting.getProductOrgGlAccountId(productId, "INV_ADJ_AVG_COST", ownerPartyId, delegator); 1174 String invGlAcctAdjCogsId = UtilAccounting.getProductOrgGlAccountId(productId, "COGS_ADJ_AVG_COST", ownerPartyId, delegator); 1175 input = UtilMisc.toMap("glAccountId", invGlAcctAdjId, "debitCreditFlag", "C", 1177 "amount", new Double (inventoryAdjAmount.doubleValue()), "acctgTransEntrySeqId", Integer.toString(0), 1178 "organizationPartyId", ownerPartyId, "acctgTransEntryTypeId", "_NA_"); 1179 input.put("productId", productId); 1180 input.put("partyId", partyIdTo); 1181 input.put("roleTypeId", "BILL_TO_CUSTOMER"); 1182 transEntries.add(delegator.makeValue("AcctgTransEntry", input)); 1183 1184 input = UtilMisc.toMap("glAccountId", invGlAcctAdjCogsId, "debitCreditFlag", "D", 1186 "amount", new Double (inventoryAdjAmount.doubleValue()), "acctgTransEntrySeqId", Integer.toString(1), 1187 "organizationPartyId", ownerPartyId, "acctgTransEntryTypeId", "_NA_"); 1188 input.put("productId", productId); 1189 input.put("partyId", partyIdTo); 1190 input.put("roleTypeId", "BILL_TO_CUSTOMER"); 1191 transEntries.add(delegator.makeValue("AcctgTransEntry", input)); 1192 } 1193 } 1194 input = UtilMisc.toMap("transactionDate", UtilDateTime.nowTimestamp(), "userLogin", userLogin); 1196 input.put("acctgTransEntries", transEntries); 1197 input.put("glFiscalTypeId", "ACTUAL"); 1198 input.put("acctgTransTypeId", "OBLIGATION_ACCTG_TRA"); 1199 input.put("shipmentId", shipmentId); 1200 1201 Map servResult = dispatcher.runSync("createAcctgTransAndEntries", input); 1202 1203 if (ServiceUtil.isError(servResult)) { 1204 return servResult; 1205 } 1206 1207 Map result = ServiceUtil.returnSuccess(); 1208 result.put("acctgTransId", servResult.get("acctgTransId")); 1209 1210 } catch (GenericEntityException ex) { 1211 return(ServiceUtil.returnError(ex.getMessage())); 1212 } catch (GenericServiceException ex) { 1213 return(ServiceUtil.returnError(ex.getMessage())); 1214 } 1215 1216 return ServiceUtil.returnSuccess(); 1217 } 1218 1219 1223 public static Map postShipmentReceiptToGl(DispatchContext dctx, Map context) { 1224 GenericDelegator delegator = dctx.getDelegator(); 1225 LocalDispatcher dispatcher = dctx.getDispatcher(); 1226 GenericValue userLogin = (GenericValue) context.get("userLogin"); 1227 1228 String receiptId = (String ) context.get("receiptId"); 1229 try { 1230 GenericValue receipt = delegator.findByPrimaryKey("ShipmentReceipt", UtilMisc.toMap("receiptId", receiptId)); 1231 String shipmentId = receipt.getString("shipmentId"); 1232 String orderId = receipt.getString("orderId"); 1233 String orderItemSeqId = receipt.getString("orderItemSeqId"); 1234 String productId = receipt.getString("productId"); 1235 BigDecimal quantityReceived = receipt.getBigDecimal("quantityAccepted"); 1236 GenericValue inventoryItem = receipt.getRelatedOne("InventoryItem"); 1237 String organizationPartyId = inventoryItem.getString("ownerPartyId"); 1239 BigDecimal unitCost = inventoryItem.getBigDecimal("unitCost"); 1241 BigDecimal conversionFactor = new BigDecimal (UtilFinancial.determineUomConversionFactor(delegator, dispatcher, organizationPartyId, inventoryItem.getString("currencyUomId"))); 1243 1244 String originPartyId = null; 1246 String offsettingGlAccountTypeId = "UNINVOICED_SHIP_RCPT"; 1247 if (shipmentId != null) { 1248 GenericValue shipment = receipt.getRelatedOne("Shipment"); 1249 originPartyId = shipment.getString("partyIdFrom"); 1250 if ((shipment != null) && (shipment.getString("shipmentTypeId").equals("SALES_RETURN"))) { 1251 offsettingGlAccountTypeId = "COGS_ACCOUNT"; 1252 } 1253 } 1254 if (unitCost == null) { 1256 return ServiceUtil.returnError("Could not determine unitCost of product [" + productId + "] from shipment receipt [" + receiptId + "]"); 1257 } 1258 BigDecimal transactionAmount = unitCost.multiply(quantityReceived).multiply(conversionFactor).setScale(decimals, rounding); 1259 1260 String inventoryGlAccount = UtilAccounting.getProductOrgGlAccountId(productId, "INVENTORY_ACCOUNT", organizationPartyId, delegator); 1262 String uninvoicedGlAccountId = null; 1264 if (offsettingGlAccountTypeId.equals("COGS_ACCOUNT")) { 1265 uninvoicedGlAccountId = UtilAccounting.getProductOrgGlAccountId(productId, offsettingGlAccountTypeId, organizationPartyId, delegator); 1267 } else { 1268 uninvoicedGlAccountId = UtilAccounting.getDefaultAccountId(offsettingGlAccountTypeId, organizationPartyId, delegator); 1269 } 1270 1271 Map input = UtilMisc.toMap("glAccountId", uninvoicedGlAccountId, "organizationPartyId", organizationPartyId, "partyId", originPartyId); 1273 input.put("productId", productId); 1274 input.put("amount", new Double (transactionAmount.doubleValue())); 1275 input.put("acctgTransEntryTypeId", "_NA_"); 1276 input.put("debitCreditFlag", "C"); 1277 input.put("acctgTransEntrySeqId", Integer.toString(0)); 1278 input.put("roleTypeId", "BILL_FROM_VENDOR"); 1279 GenericValue creditAcctTrans = delegator.makeValue("AcctgTransEntry", input); 1280 1281 input = UtilMisc.toMap("glAccountId", inventoryGlAccount, "organizationPartyId", organizationPartyId, "partyId", originPartyId); 1283 input.put("productId", productId); 1284 input.put("amount", new Double (transactionAmount.doubleValue())); 1285 input.put("acctgTransEntryTypeId", "_NA_"); 1286 input.put("debitCreditFlag", "D"); 1287 input.put("acctgTransEntrySeqId", Integer.toString(1)); 1288 input.put("roleTypeId", "BILL_FROM_VENDOR"); 1289 GenericValue debitAcctTrans = delegator.makeValue("AcctgTransEntry", input); 1290 1291 input = UtilMisc.toMap("transactionDate", UtilDateTime.nowTimestamp(), "partyId", originPartyId, "userLogin", userLogin); 1293 input.put("acctgTransEntries", UtilMisc.toList(creditAcctTrans, debitAcctTrans)); 1294 input.put("glFiscalTypeId", "ACTUAL"); 1295 input.put("acctgTransTypeId", "OBLIGATION_ACCTG_TRA"); 1296 input.put("receiptId", receiptId); 1297 if (shipmentId != null) { 1298 input.put("shipmentId", shipmentId); 1299 } 1300 Map servResult = dispatcher.runSync("createAcctgTransAndEntries", input); 1301 1302 if (((String ) servResult.get(ModelService.RESPONSE_MESSAGE)).equals(ModelService.RESPOND_SUCCESS)) { 1303 Map result = ServiceUtil.returnSuccess(); 1304 result.put("acctgTransId", servResult.get("acctgTransId")); 1305 return(result); 1306 } else { 1307 return servResult; 1308 } 1309 } catch (GenericEntityException ex) { 1310 return(ServiceUtil.returnError(ex.getMessage())); 1311 } catch (GenericServiceException ex) { 1312 return(ServiceUtil.returnError(ex.getMessage())); 1313 } 1314 } 1315 1316 1323 public static Map postInventoryItemOwnerChange(DispatchContext dctx, Map context) { 1324 GenericDelegator delegator = dctx.getDelegator(); 1325 LocalDispatcher dispatcher = dctx.getDispatcher(); 1326 GenericValue userLogin = (GenericValue) context.get("userLogin"); 1327 1328 String inventoryItemId = (String ) context.get("inventoryItemId"); 1329 String originOwnerPartyId = (String ) context.get("oldOwnerPartyId"); 1330 try { 1331 Map tmpMap = new HashMap(); 1332 1333 GenericValue inventoryItem = delegator.findByPrimaryKey("InventoryItem", 1334 UtilMisc.toMap("inventoryItemId", inventoryItemId)); 1335 if (inventoryItem == null) { 1336 return ServiceUtil.returnError("No InventoryItem entity record for inventoryItemId " + inventoryItemId); 1337 } 1338 String destinationOwnerPartyId = inventoryItem.getString("ownerPartyId"); 1339 String productId = inventoryItem.getString("productId"); 1340 BigDecimal unitCost = inventoryItem.getBigDecimal("unitCost"); 1342 BigDecimal originConversionFactor = new BigDecimal (UtilFinancial.determineUomConversionFactor(delegator, dispatcher, originOwnerPartyId, inventoryItem.getString("currencyUomId"))); 1344 BigDecimal destinationConversionFactor = new BigDecimal (UtilFinancial.determineUomConversionFactor(delegator, dispatcher, destinationOwnerPartyId, inventoryItem.getString("currencyUomId"))); 1345 BigDecimal quantity = inventoryItem.getBigDecimal("quantityOnHandTotal"); 1347 BigDecimal originTransactionAmount = unitCost.multiply(originConversionFactor).multiply(quantity).setScale(decimals, rounding); 1349 BigDecimal destinationTransactionAmount = unitCost.multiply(destinationConversionFactor).multiply(quantity).setScale(decimals, rounding); 1350 String originInvGlAcctId = UtilAccounting.getProductOrgGlAccountId(productId, "INVENTORY_ACCOUNT", originOwnerPartyId, delegator); 1352 String destinationInvGlAcctId = UtilAccounting.getProductOrgGlAccountId(productId, "INVENTORY_ACCOUNT", destinationOwnerPartyId, delegator); 1353 String originInvXferGlAcctId = UtilAccounting.getProductOrgGlAccountId(productId, "INVENTORY_XFER_OUT", originOwnerPartyId, delegator); 1354 String destinationInvXferGlAcctId = UtilAccounting.getProductOrgGlAccountId(productId, "INVENTORY_XFER_IN", destinationOwnerPartyId, delegator); 1355 1356 List transEntries = new ArrayList(); 1358 tmpMap = UtilMisc.toMap("glAccountId", destinationInvXferGlAcctId, "debitCreditFlag", "C", 1361 "amount", new Double (destinationTransactionAmount.doubleValue()), "acctgTransEntrySeqId", Integer.toString(0), 1362 "organizationPartyId", destinationOwnerPartyId, "acctgTransEntryTypeId", "_NA_"); 1363 tmpMap.put("productId", productId); 1364 transEntries.add(delegator.makeValue("AcctgTransEntry", tmpMap)); 1365 1366 tmpMap = UtilMisc.toMap("glAccountId", destinationInvGlAcctId, "debitCreditFlag", "D", 1368 "amount", new Double (destinationTransactionAmount.doubleValue()), "acctgTransEntrySeqId", Integer.toString(1), 1369 "organizationPartyId", destinationOwnerPartyId, "acctgTransEntryTypeId", "_NA_"); 1370 tmpMap.put("productId", productId); 1371 transEntries.add(delegator.makeValue("AcctgTransEntry", tmpMap)); 1372 1373 tmpMap = UtilMisc.toMap("glAccountId", originInvGlAcctId, "debitCreditFlag", "C", 1376 "amount", new Double (originTransactionAmount.doubleValue()), "acctgTransEntrySeqId", Integer.toString(0), 1377 "organizationPartyId", originOwnerPartyId, "acctgTransEntryTypeId", "_NA_"); 1378 tmpMap.put("productId", productId); 1379 transEntries.add(delegator.makeValue("AcctgTransEntry", tmpMap)); 1380 1381 tmpMap = UtilMisc.toMap("glAccountId", originInvXferGlAcctId, "debitCreditFlag", "D", 1383 "amount", new Double (originTransactionAmount.doubleValue()), "acctgTransEntrySeqId", Integer.toString(1), 1384 "organizationPartyId", originOwnerPartyId, "acctgTransEntryTypeId", "_NA_"); 1385 tmpMap.put("productId", productId); 1386 transEntries.add(delegator.makeValue("AcctgTransEntry", tmpMap)); 1387 1388 GenericValue acctgPref = delegator.findByPrimaryKeyCache("PartyAcctgPreference", UtilMisc.toMap("partyId", originOwnerPartyId)); 1390 String cogsMethodId = acctgPref.getString("cogsMethodId"); 1391 BigDecimal inventoryAdjAmount = null; 1392 if ((cogsMethodId != null) && (cogsMethodId.equals("COGS_AVG_COST"))) { 1393 BigDecimal prodAvgCost = UtilCOGS.getProductAverageCost(productId, originOwnerPartyId, userLogin, delegator, dispatcher); 1394 if (prodAvgCost == null) return ServiceUtil.returnError("Unable to find a product average cost for product ["+productId+"] in organization ["+originOwnerPartyId+"]"); 1395 inventoryAdjAmount = prodAvgCost.subtract(unitCost.multiply(originConversionFactor)).multiply(quantity).setScale(decimals, rounding); 1396 } 1397 if ((inventoryAdjAmount != null) && (inventoryAdjAmount.compareTo(ZERO) != 0)) { 1399 String invGlAcctAdjId = UtilAccounting.getProductOrgGlAccountId(productId, "INV_ADJ_AVG_COST", originOwnerPartyId, delegator); 1401 tmpMap = UtilMisc.toMap("glAccountId", invGlAcctAdjId, "debitCreditFlag", "C", 1403 "amount", new Double (inventoryAdjAmount.doubleValue()), "acctgTransEntrySeqId", Integer.toString(0), 1404 "organizationPartyId", originOwnerPartyId, "acctgTransEntryTypeId", "_NA_"); 1405 tmpMap.put("productId", productId); 1406 transEntries.add(delegator.makeValue("AcctgTransEntry", tmpMap)); 1407 1408 tmpMap = UtilMisc.toMap("glAccountId", originInvXferGlAcctId, "debitCreditFlag", "D", 1410 "amount", new Double (inventoryAdjAmount.doubleValue()), "acctgTransEntrySeqId", Integer.toString(1), 1411 "organizationPartyId", originOwnerPartyId, "acctgTransEntryTypeId", "_NA_"); 1412 tmpMap.put("productId", productId); 1413 transEntries.add(delegator.makeValue("AcctgTransEntry", tmpMap)); 1414 } 1415 1416 tmpMap = UtilMisc.toMap("acctgTransEntries", transEntries, 1418 "glFiscalTypeId", "ACTUAL", "acctgTransTypeId", "ITEM_VARIANCE_ACCTG_", 1419 "transactionDate", UtilDateTime.nowTimestamp(), 1420 "userLogin", userLogin); 1421 tmpMap.put("inventoryItemId", inventoryItemId); 1422 tmpMap = dispatcher.runSync("createAcctgTransAndEntries", tmpMap); 1424 1425 if (ServiceUtil.isError(tmpMap)) { 1426 return tmpMap; 1427 } 1428 1429 tmpMap = dispatcher.runSync("updateProductAverageCost", 1431 UtilMisc.toMap("organizationPartyId", destinationOwnerPartyId, 1432 "productId", productId, 1433 "userLogin", userLogin)); 1434 if (ServiceUtil.isError(tmpMap)) { 1435 return tmpMap; 1436 } 1437 1438 Map result = ServiceUtil.returnSuccess(); 1439 result.put("acctgTransId", tmpMap.get("acctgTransId")); 1440 return result; 1441 1442 } catch (GenericEntityException ex) { 1443 return(ServiceUtil.returnError(ex.getMessage())); 1444 } catch (GenericServiceException ex) { 1445 return(ServiceUtil.returnError(ex.getMessage())); 1446 } 1447 } 1448 1453 public static Map postRawMaterialIssuancesToGl(DispatchContext dctx, Map context) { 1454 GenericDelegator delegator = dctx.getDelegator(); 1455 LocalDispatcher dispatcher = dctx.getDispatcher(); 1456 GenericValue userLogin = (GenericValue) context.get("userLogin"); 1457 1458 String workEffortId = (String ) context.get("workEffortId"); 1459 String finishedProductId = (String ) context.get("finishedProductId"); 1460 try { 1461 GenericValue workEffort = delegator.findByPrimaryKey("WorkEffort", UtilMisc.toMap("workEffortId", workEffortId)); 1462 if (finishedProductId == null) { 1463 GenericValue productionRun = delegator.findByPrimaryKey("WorkEffort", UtilMisc.toMap("workEffortId", workEffort.getString("workEffortParentId"))); 1465 GenericValue finishedProduct = EntityUtil.getFirst(productionRun.getRelated("WorkEffortGoodStandard", UtilMisc.toMap("workEffortGoodStdTypeId", "PRUN_PROD_DELIV"), null)); 1466 finishedProductId = finishedProduct.getString("productId"); 1467 } 1468 GenericValue facility = workEffort.getRelatedOne("Facility"); 1469 if (facility == null) { 1470 return ServiceUtil.returnError("Could not find the facility for work effort [" + workEffortId + "]"); 1471 } 1472 String ownerPartyId = facility.getString("ownerPartyId"); 1473 1474 List issuances = delegator.findByAnd("WorkEffortInventoryAssign", UtilMisc.toMap("workEffortId", workEffortId)); 1475 Iterator issuancesIt = issuances.iterator(); 1476 List transEntries = new ArrayList(); 1477 Map input = null; 1478 while (issuancesIt.hasNext()) { 1479 GenericValue itemIssuance = (GenericValue)issuancesIt.next(); 1480 GenericValue inventoryItem = itemIssuance.getRelatedOne("InventoryItem"); 1481 String productId = inventoryItem.getString("productId"); 1482 BigDecimal quantityIssued = itemIssuance.getBigDecimal("quantity"); 1483 String inventoryOwnerPartyId = inventoryItem.getString("ownerPartyId"); 1485 if (!inventoryOwnerPartyId.equals(ownerPartyId)) { 1486 return ServiceUtil.returnError("The inventory item [" + inventoryOwnerPartyId + 1487 "] is not owned by the owner of the facility [" + facility.getString("facilityId") + "] in item issuance [" + itemIssuance.getString("itemIssuanceId") + "]"); 1488 } 1489 BigDecimal unitCost = inventoryItem.getBigDecimal("unitCost"); 1491 BigDecimal conversionFactor = new BigDecimal (UtilFinancial.determineUomConversionFactor(delegator, dispatcher, ownerPartyId, inventoryItem.getString("currencyUomId"))); 1493 if (unitCost == null) { 1495 return ServiceUtil.returnError("Could not determine unitCost of product [" + productId + 1496 "] for item issuance [" + itemIssuance.getString("itemIssuanceId") + "]"); 1497 } 1498 unitCost = unitCost.multiply(conversionFactor).setScale(decimals, rounding); 1500 BigDecimal transactionAmount = unitCost.multiply(quantityIssued).setScale(decimals, rounding); 1501 String creditAccountId = UtilAccounting.getProductOrgGlAccountId(productId, "RAWMAT_INVENTORY", ownerPartyId, delegator); 1503 String debitAccountId = UtilAccounting.getProductOrgGlAccountId(productId, "WIP_INVENTORY", ownerPartyId, delegator); 1504 1505 input = UtilMisc.toMap("glAccountId", creditAccountId, "organizationPartyId", ownerPartyId); 1507 input.put("productId", productId); 1508 input.put("amount", new Double (transactionAmount.doubleValue())); 1509 input.put("acctgTransEntryTypeId", "_NA_"); 1510 input.put("debitCreditFlag", "C"); 1511 input.put("acctgTransEntrySeqId", Integer.toString(0)); 1512 GenericValue creditAcctTrans = delegator.makeValue("AcctgTransEntry", input); 1513 transEntries.add(creditAcctTrans); 1514 1515 input = UtilMisc.toMap("glAccountId", debitAccountId, "organizationPartyId", ownerPartyId); 1517 input.put("productId", finishedProductId); 1518 input.put("amount", new Double (transactionAmount.doubleValue())); 1519 input.put("acctgTransEntryTypeId", "_NA_"); 1520 input.put("debitCreditFlag", "D"); 1521 input.put("acctgTransEntrySeqId", Integer.toString(1)); 1522 GenericValue debitAcctTrans = delegator.makeValue("AcctgTransEntry", input); 1523 transEntries.add(debitAcctTrans); 1524 1525 GenericValue acctgPref = delegator.findByPrimaryKeyCache("PartyAcctgPreference", UtilMisc.toMap("partyId", ownerPartyId)); 1527 String cogsMethodId = acctgPref.getString("cogsMethodId"); 1528 BigDecimal inventoryAdjAmount = null; 1529 if ((cogsMethodId != null) && (cogsMethodId.equals("COGS_AVG_COST"))) { 1530 BigDecimal prodAvgCost = UtilCOGS.getProductAverageCost(productId, ownerPartyId, userLogin, delegator, dispatcher); 1531 if (prodAvgCost == null) return ServiceUtil.returnError("Unable to find a product average cost for product ["+productId+"] in organization ["+ownerPartyId+"]"); 1532 inventoryAdjAmount = prodAvgCost.subtract(unitCost).multiply(quantityIssued).setScale(decimals, rounding); 1535 } 1536 if ((inventoryAdjAmount != null) && (inventoryAdjAmount.compareTo(ZERO) != 0)) { 1538 String debitGlAcctId = UtilAccounting.getProductOrgGlAccountId(productId, "WIP_INVENTORY", ownerPartyId, delegator); 1539 String creditGlAcctId = UtilAccounting.getProductOrgGlAccountId(productId, "RAWMAT_INVENTORY", ownerPartyId, delegator); 1540 input = UtilMisc.toMap("glAccountId", creditGlAcctId, "debitCreditFlag", "C", 1542 "amount", new Double (inventoryAdjAmount.doubleValue()), "acctgTransEntrySeqId", Integer.toString(0), 1543 "organizationPartyId", ownerPartyId, "acctgTransEntryTypeId", "_NA_"); 1544 input.put("productId", productId); 1545 transEntries.add(delegator.makeValue("AcctgTransEntry", input)); 1546 1547 input = UtilMisc.toMap("glAccountId", debitGlAcctId, "debitCreditFlag", "D", 1549 "amount", new Double (inventoryAdjAmount.doubleValue()), "acctgTransEntrySeqId", Integer.toString(1), 1550 "organizationPartyId", ownerPartyId, "acctgTransEntryTypeId", "_NA_"); 1551 input.put("productId", finishedProductId); 1552 transEntries.add(delegator.makeValue("AcctgTransEntry", input)); 1553 } 1554 1555 } 1556 input = UtilMisc.toMap("transactionDate", UtilDateTime.nowTimestamp(), "userLogin", userLogin); 1558 input.put("acctgTransEntries", transEntries); 1559 input.put("glFiscalTypeId", "ACTUAL"); 1560 input.put("acctgTransTypeId", "OBLIGATION_ACCTG_TRA"); 1561 input.put("workEffortId", workEffortId); 1562 1563 Map servResult = dispatcher.runSync("createAcctgTransAndEntries", input); 1564 1565 if (ServiceUtil.isError(servResult)) { 1566 return servResult; 1567 } 1568 1569 Map result = ServiceUtil.returnSuccess(); 1570 result.put("acctgTransId", servResult.get("acctgTransId")); 1571 1572 } catch (GenericEntityException ex) { 1573 return(ServiceUtil.returnError(ex.getMessage())); 1574 } catch (GenericServiceException ex) { 1575 return(ServiceUtil.returnError(ex.getMessage())); 1576 } 1577 1578 return ServiceUtil.returnSuccess(); 1579 } 1580 1581 1586 public static Map postWorkEffortCostsToGl(DispatchContext dctx, Map context) { 1587 GenericDelegator delegator = dctx.getDelegator(); 1588 LocalDispatcher dispatcher = dctx.getDispatcher(); 1589 GenericValue userLogin = (GenericValue) context.get("userLogin"); 1590 1591 String workEffortId = (String ) context.get("workEffortId"); 1592 try { 1593 GenericValue workEffort = delegator.findByPrimaryKey("WorkEffort", UtilMisc.toMap("workEffortId", workEffortId)); 1594 GenericValue productionRun = delegator.findByPrimaryKey("WorkEffort", UtilMisc.toMap("workEffortId", workEffort.getString("workEffortParentId"))); 1595 GenericValue finishedProduct = EntityUtil.getFirst(productionRun.getRelated("WorkEffortGoodStandard", UtilMisc.toMap("workEffortGoodStdTypeId", "PRUN_PROD_DELIV"), null)); 1596 GenericValue facility = workEffort.getRelatedOne("Facility"); 1597 if (facility == null) { 1598 return ServiceUtil.returnError("Could not find the facility for work effort [" + workEffortId + "]"); 1599 } 1600 String ownerPartyId = facility.getString("ownerPartyId"); 1601 1602 List costComponents = EntityUtil.filterByDate(delegator.findByAnd("CostComponent", UtilMisc.toMap("workEffortId", workEffortId))); 1603 Iterator costComponentsIt = costComponents.iterator(); 1604 List transEntries = new ArrayList(); 1605 Map input = null; 1606 while (costComponentsIt.hasNext()) { 1607 GenericValue costComponent = (GenericValue)costComponentsIt.next(); 1608 if (!"ACTUAL_MAT_COST".equals(costComponent.getString("costComponentTypeId"))) { 1609 GenericValue costComponentCalc = costComponent.getRelatedOne("CostComponentCalc"); 1610 BigDecimal cost = costComponent.getBigDecimal("cost"); 1611 if (cost.compareTo(ZERO) != 0) { 1612 String creditAccountTypeId = costComponentCalc.getString("costGlAccountTypeId"); 1613 String debitAccountTypeId = costComponentCalc.getString("offsettingGlAccountTypeId"); 1614 if (debitAccountTypeId == null) { 1615 debitAccountTypeId = "WIP_INVENTORY"; 1616 } 1617 String creditAccountId = UtilAccounting.getDefaultAccountId(creditAccountTypeId, ownerPartyId, delegator); 1618 String debitAccountId = UtilAccounting.getDefaultAccountId(debitAccountTypeId, ownerPartyId, delegator); 1619 BigDecimal conversionFactor = new BigDecimal (UtilFinancial.determineUomConversionFactor(delegator, dispatcher, ownerPartyId, costComponent.getString("costUomId"))); 1621 BigDecimal transactionAmount = cost.multiply(conversionFactor).setScale(decimals, rounding); 1623 1624 input = UtilMisc.toMap("glAccountId", creditAccountId, "organizationPartyId", ownerPartyId); 1626 input.put("amount", new Double (transactionAmount.doubleValue())); 1627 input.put("acctgTransEntryTypeId", "_NA_"); 1628 input.put("debitCreditFlag", "C"); 1629 input.put("acctgTransEntrySeqId", Integer.toString(0)); 1630 GenericValue creditAcctTrans = delegator.makeValue("AcctgTransEntry", input); 1631 transEntries.add(creditAcctTrans); 1632 1633 input = UtilMisc.toMap("glAccountId", debitAccountId, "organizationPartyId", ownerPartyId); 1635 input.put("amount", new Double (transactionAmount.doubleValue())); 1636 input.put("acctgTransEntryTypeId", "_NA_"); 1637 input.put("debitCreditFlag", "D"); 1638 input.put("productId", finishedProduct.getString("productId")); 1639 input.put("acctgTransEntrySeqId", Integer.toString(1)); 1640 GenericValue debitAcctTrans = delegator.makeValue("AcctgTransEntry", input); 1641 transEntries.add(debitAcctTrans); 1642 } 1643 } 1644 } 1645 input = UtilMisc.toMap("transactionDate", UtilDateTime.nowTimestamp(), "userLogin", userLogin); 1647 input.put("acctgTransEntries", transEntries); 1648 input.put("glFiscalTypeId", "ACTUAL"); 1649 input.put("acctgTransTypeId", "OBLIGATION_ACCTG_TRA"); 1650 input.put("workEffortId", workEffortId); 1651 1652 Map servResult = dispatcher.runSync("createAcctgTransAndEntries", input); 1653 1654 if (ServiceUtil.isError(servResult)) { 1655 return servResult; 1656 } 1657 1658 Map result = ServiceUtil.returnSuccess(); 1659 result.put("acctgTransId", servResult.get("acctgTransId")); 1660 1661 } catch (GenericEntityException ex) { 1662 return(ServiceUtil.returnError(ex.getMessage())); 1663 } catch (GenericServiceException ex) { 1664 return(ServiceUtil.returnError(ex.getMessage())); 1665 } 1666 1667 return ServiceUtil.returnSuccess(); 1668 } 1669 1670 1675 public static Map postInventoryProducedToGl(DispatchContext dctx, Map context) { 1676 GenericDelegator delegator = dctx.getDelegator(); 1677 LocalDispatcher dispatcher = dctx.getDispatcher(); 1678 GenericValue userLogin = (GenericValue) context.get("userLogin"); 1679 1680 String workEffortId = (String )context.get("workEffortId"); 1681 List inventoryItemIds = (List)context.get("inventoryItemIds"); 1682 try { 1683 GenericValue workEffort = delegator.findByPrimaryKey("WorkEffort", UtilMisc.toMap("workEffortId", workEffortId)); 1684 GenericValue facility = workEffort.getRelatedOne("Facility"); 1685 if (facility == null) { 1686 return ServiceUtil.returnError("Could not find the facility for work effort [" + workEffortId + "]"); 1687 } 1688 String ownerPartyId = facility.getString("ownerPartyId"); 1689 1690 Iterator inventoryItemIdsIt = inventoryItemIds.iterator(); 1691 List transEntries = new ArrayList(); 1692 Map input = null; 1693 while (inventoryItemIdsIt.hasNext()) { 1694 String inventoryItemId = (String )inventoryItemIdsIt.next(); 1695 GenericValue inventoryItem = delegator.findByPrimaryKey("InventoryItem", UtilMisc.toMap("inventoryItemId", inventoryItemId)); 1696 BigDecimal unitCost = inventoryItem.getBigDecimal("unitCost"); 1697 String productId = inventoryItem.getString("productId"); 1698 if ((unitCost != null) && (unitCost.compareTo(ZERO) != 0) && (inventoryItem.get("quantityOnHandTotal") != null)) { 1699 String creditAccountId = UtilAccounting.getProductOrgGlAccountId(productId, "WIP_INVENTORY", ownerPartyId, delegator); 1700 String debitAccountId = UtilAccounting.getProductOrgGlAccountId(productId, "INVENTORY_ACCOUNT", ownerPartyId, delegator); 1702 BigDecimal conversionFactor = new BigDecimal (UtilFinancial.determineUomConversionFactor(delegator, dispatcher, ownerPartyId, inventoryItem.getString("currencyUomId"))); 1704 BigDecimal transactionAmount = unitCost.multiply(conversionFactor).multiply(inventoryItem.getBigDecimal("quantityOnHandTotal")).setScale(decimals, rounding); 1706 1707 input = UtilMisc.toMap("glAccountId", creditAccountId, "organizationPartyId", ownerPartyId); 1709 input.put("amount", new Double (transactionAmount.doubleValue())); 1710 input.put("acctgTransEntryTypeId", "_NA_"); 1711 input.put("debitCreditFlag", "C"); 1712 input.put("productId", productId); 1713 input.put("acctgTransEntrySeqId", Integer.toString(0)); 1714 GenericValue creditAcctTrans = delegator.makeValue("AcctgTransEntry", input); 1715 transEntries.add(creditAcctTrans); 1716 1717 input = UtilMisc.toMap("glAccountId", debitAccountId, "organizationPartyId", ownerPartyId); 1719 input.put("amount", new Double (transactionAmount.doubleValue())); 1720 input.put("acctgTransEntryTypeId", "_NA_"); 1721 input.put("debitCreditFlag", "D"); 1722 input.put("productId", productId); 1723 input.put("acctgTransEntrySeqId", Integer.toString(1)); 1724 GenericValue debitAcctTrans = delegator.makeValue("AcctgTransEntry", input); 1725 transEntries.add(debitAcctTrans); 1726 1727 Map tmpResult = dispatcher.runSync("updateProductAverageCost", UtilMisc.toMap("productId", inventoryItem.getString("productId"), 1729 "organizationPartyId", inventoryItem.getString("ownerPartyId"), "userLogin", userLogin)); 1730 } 1731 } 1732 input = UtilMisc.toMap("transactionDate", UtilDateTime.nowTimestamp(), "userLogin", userLogin); 1734 input.put("acctgTransEntries", transEntries); 1735 input.put("glFiscalTypeId", "ACTUAL"); 1736 input.put("acctgTransTypeId", "OBLIGATION_ACCTG_TRA"); 1737 input.put("workEffortId", workEffortId); 1738 1739 Map servResult = dispatcher.runSync("createAcctgTransAndEntries", input); 1740 1741 if (ServiceUtil.isError(servResult)) { 1742 return servResult; 1743 } 1744 1745 Map result = ServiceUtil.returnSuccess(); 1746 result.put("acctgTransId", servResult.get("acctgTransId")); 1747 1748 } catch (GenericEntityException ex) { 1749 return(ServiceUtil.returnError(ex.getMessage())); 1750 } catch (GenericServiceException ex) { 1751 return(ServiceUtil.returnError(ex.getMessage())); 1752 } 1753 1754 return ServiceUtil.returnSuccess(); 1755 } 1756 1757 1763 public static Map closeTimePeriod(DispatchContext dctx, Map context) { 1764 GenericDelegator delegator = dctx.getDelegator(); 1765 LocalDispatcher dispatcher = dctx.getDispatcher(); 1766 GenericValue userLogin = (GenericValue) context.get("userLogin"); 1767 1768 String organizationPartyId = (String ) context.get("organizationPartyId"); 1769 String customTimePeriodId = (String ) context.get("customTimePeriodId"); 1770 1771 try { 1772 GenericValue timePeriod = delegator.findByPrimaryKeyCache("CustomTimePeriod", UtilMisc.toMap("customTimePeriodId", customTimePeriodId)); 1774 if (timePeriod == null) { 1775 return ServiceUtil.returnError("Cannot find a time period for " + organizationPartyId + " and time period id " + customTimePeriodId); 1776 } 1777 String periodTypeId = timePeriod.getString("periodTypeId"); 1778 1779 String retainedEarningsGlAccountId = UtilAccounting.getProductOrgGlAccountId(null, "RETAINED_EARNINGS", organizationPartyId, delegator); 1781 String profitLossGlAccountId = UtilAccounting.getProductOrgGlAccountId(null, "PROFIT_LOSS_ACCOUNT", organizationPartyId, delegator); 1782 1783 double netIncome = 0.0; 1785 Map tmpResult = dispatcher.runSync("getActualNetIncomeSinceLastClosing", UtilMisc.toMap("organizationPartyId", organizationPartyId, "periodTypeId", periodTypeId, 1786 "thruDate", UtilDateTime.toTimestamp(timePeriod.getDate("thruDate")), "userLogin", userLogin)); 1787 if (tmpResult.get("netIncome") != null) { 1788 netIncome = ((Double ) tmpResult.get("netIncome")).doubleValue(); 1789 } else { 1790 return ServiceUtil.returnError("Cannot calculate a net income for" + organizationPartyId + " and time period id " + customTimePeriodId); 1791 } 1792 1793 GenericValue postedNetIncome = delegator.findByPrimaryKey("GlAccountHistory", UtilMisc.toMap("organizationPartyId", organizationPartyId, 1795 "customTimePeriodId", timePeriod.getString("customTimePeriodId"), "glAccountId", profitLossGlAccountId)); 1796 1797 if (postedNetIncome == null) { 1798 GenericValue retainedEarningsTransaction = delegator.makeValue("AcctgTransEntry", UtilMisc.toMap("glAccountId", retainedEarningsGlAccountId, "debitCreditFlag", "C", 1800 "amount", new Double (netIncome), "acctgTransEntrySeqId", Integer.toString(0), "organizationPartyId", organizationPartyId, "acctgTransEntryTypeId", "_NA_")); 1801 GenericValue netIncomeTransaction = delegator.makeValue("AcctgTransEntry", UtilMisc.toMap("glAccountId", profitLossGlAccountId, "debitCreditFlag", "D", 1802 "amount", new Double (netIncome), "acctgTransEntrySeqId", Integer.toString(1), "organizationPartyId", organizationPartyId, "acctgTransEntryTypeId", "_NA_")); 1803 1804 tmpResult = dispatcher.runSync("createAcctgTransAndEntries", UtilMisc.toMap("acctgTransEntries", UtilMisc.toList(retainedEarningsTransaction, netIncomeTransaction), 1806 "glFiscalTypeId", "ACTUAL", "transactionDate", new Timestamp (timePeriod.getDate("thruDate").getTime() - 1000), "acctgTransTypeId", "PERIOD_CLOSING", "userLogin", userLogin)); 1807 } else if (Math.abs(UtilAccounting.getNetBalance(postedNetIncome, module).doubleValue() - netIncome) < epsilon) { 1808 Debug.logInfo("Net income and earnings already posted. Not posting again", module); 1810 } else { 1811 return ServiceUtil.returnError("Calculated a net income of " + netIncome + " but found posted net income of " + UtilAccounting.getNetBalance(postedNetIncome, module)); 1813 } 1814 1815 String lastClosedTimePeriodId = null; 1817 tmpResult = dispatcher.runSync("findLastClosedDate", UtilMisc.toMap("organizationPartyId", organizationPartyId, 1818 "periodTypeId", timePeriod.getString("periodTypeId"), "userLogin", userLogin)); 1819 if (tmpResult.get("lastClosedTimePeriod") != null) { 1820 lastClosedTimePeriodId = ((GenericValue) tmpResult.get("lastClosedTimePeriod")).getString("customTimePeriodId"); 1821 } 1822 1823 1827 1829 List glAccountHistories = delegator.findByAnd("GlAccountHistory", UtilMisc.toMap("organizationPartyId", organizationPartyId, 1830 "customTimePeriodId", timePeriod.getString("customTimePeriodId"))); 1831 1832 Map updatedGlAccountHistories = new HashMap(); 1834 for (Iterator gAHi = glAccountHistories.iterator(); gAHi.hasNext(); ) { 1835 GenericValue glAccountHistory = (GenericValue) gAHi.next(); 1836 double netBalance = UtilAccounting.getNetBalance(glAccountHistory, module).doubleValue(); 1837 glAccountHistory.set("endingBalance", new Double (netBalance)); 1838 updatedGlAccountHistories.put(glAccountHistory.getString("glAccountId"), glAccountHistory); 1839 } 1840 1841 if (lastClosedTimePeriodId != null) { 1843 EntityCondition previousPeriodConditions = new EntityConditionList(UtilMisc.toList(new EntityExpr("organizationPartyId", EntityOperator.EQUALS, organizationPartyId), 1845 new EntityConditionList(UtilMisc.toList( 1846 UtilFinancial.getAssetExpr(delegator), 1847 UtilFinancial.getLiabilityExpr(delegator), 1848 UtilFinancial.getEquityExpr(delegator)), 1849 EntityOperator.OR), 1850 new EntityExpr("customTimePeriodId", EntityOperator.EQUALS, lastClosedTimePeriodId)), EntityOperator.AND); 1851 1852 List previousGlAccountHistories = delegator.findByCondition("GlAccountAndHistory", previousPeriodConditions, 1853 UtilMisc.toList("organizationPartyId", "customTimePeriodId", "glAccountId", "postedDebits", "postedCredits", "endingBalance"), UtilMisc.toList("glAccountId")); 1854 1855 for (Iterator pGAHi = previousGlAccountHistories.iterator(); pGAHi.hasNext(); ) { 1857 GenericValue previousGlAccountAndHistory = (GenericValue) pGAHi.next(); 1858 GenericValue previousGlAccountHistory = previousGlAccountAndHistory.getRelatedOne("GlAccountHistory"); 1859 double previousNetBalance = UtilAccounting.getNetBalance(previousGlAccountHistory, module).doubleValue(); 1860 1861 if (updatedGlAccountHistories.get(previousGlAccountAndHistory.getString("glAccountId")) != null) { 1863 GenericValue updatedGlAccountHistory = (GenericValue) updatedGlAccountHistories.get(previousGlAccountAndHistory.getString("glAccountId")); 1865 double newEndingBalance = updatedGlAccountHistory.getDouble("endingBalance").doubleValue() + previousGlAccountHistory.getDouble("endingBalance").doubleValue(); 1866 updatedGlAccountHistory.set("endingBalance", new Double (newEndingBalance)); 1867 } else { 1868 GenericValue carriedForwardGlAccountHistory = delegator.makeValue("GlAccountHistory", UtilMisc.toMap("glAccountId", previousGlAccountHistory.getString("glAccountId"), 1870 "organizationPartyId", organizationPartyId, "customTimePeriodId", timePeriod.getString("customTimePeriodId"), 1871 "postedDebits", new Double (0.0), "postedCredits", new Double (0.0), "endingBalance", previousGlAccountHistory.getDouble("endingBalance"))); 1872 updatedGlAccountHistories.put(previousGlAccountHistory.getString("glAccountId"), carriedForwardGlAccountHistory); 1873 } 1874 } 1875 } 1876 1877 List toBeStored = new ArrayList(); 1879 for (Iterator vi = updatedGlAccountHistories.values().iterator(); vi.hasNext(); ) { 1880 toBeStored.add(vi.next()); 1881 } 1882 delegator.storeAll(toBeStored); 1883 1884 tmpResult = dispatcher.runSync("updateCustomTimePeriod", UtilMisc.toMap("customTimePeriodId", timePeriod.getString("customTimePeriodId"), "organizationPartyId", organizationPartyId, 1886 "isClosed", "Y", "userLogin", userLogin)); 1887 1888 return(ServiceUtil.returnSuccess()); 1889 1890 } catch (GenericEntityException ex) { 1891 return(ServiceUtil.returnError(ex.getMessage())); 1892 } catch (GenericServiceException ex) { 1893 return(ServiceUtil.returnError(ex.getMessage())); 1894 } 1895 } 1896 1897 1903 public static Map closeAllTimePeriods(DispatchContext dctx, Map context) { 1904 GenericDelegator delegator = dctx.getDelegator(); 1905 LocalDispatcher dispatcher = dctx.getDispatcher(); 1906 GenericValue userLogin = (GenericValue) context.get("userLogin"); 1907 1908 String organizationPartyId = (String ) context.get("organizationPartyId"); 1909 String customTimePeriodId = (String ) context.get("customTimePeriodId"); 1910 1911 try { 1912 GenericValue timePeriod = delegator.findByPrimaryKeyCache("CustomTimePeriod", UtilMisc.toMap("customTimePeriodId", customTimePeriodId)); 1913 if (timePeriod == null) { 1914 return ServiceUtil.returnError("Cannot find a time period for " + organizationPartyId + " and time period id " + customTimePeriodId); 1915 } 1916 1917 closeAllTimePeriodsByType(delegator, dispatcher, organizationPartyId, "FISCAL_WEEK", timePeriod.getDate("thruDate"), userLogin); 1918 closeAllTimePeriodsByType(delegator, dispatcher, organizationPartyId, "FISCAL_BIWEEK", timePeriod.getDate("thruDate"), userLogin); 1919 closeAllTimePeriodsByType(delegator, dispatcher, organizationPartyId, "FISCAL_MONTH", timePeriod.getDate("thruDate"), userLogin); 1920 closeAllTimePeriodsByType(delegator, dispatcher, organizationPartyId, "FISCAL_QUARTER", timePeriod.getDate("thruDate"), userLogin); 1921 closeAllTimePeriodsByType(delegator, dispatcher, organizationPartyId, "FISCAL_YEAR", timePeriod.getDate("thruDate"), userLogin); 1922 1923 return(ServiceUtil.returnSuccess()); 1924 } catch (GenericEntityException ex) { 1925 return(ServiceUtil.returnError(ex.getMessage())); 1926 } catch (GenericServiceException ex) { 1927 return(ServiceUtil.returnError(ex.getMessage())); 1928 } 1929 } 1930 1931 1937 public static Map resetOrgGlAccountBalances(DispatchContext dctx, Map context) { 1938 GenericDelegator delegator = dctx.getDelegator(); 1939 LocalDispatcher dispatcher = dctx.getDispatcher(); 1940 GenericValue userLogin = (GenericValue) context.get("userLogin"); 1941 1942 try { 1943 String organizationPartyId = (String ) context.get("organizationPartyId"); 1944 String customTimePeriodId = (String ) context.get("customTimePeriodId"); 1945 1946 EntityCondition glAccountConditions = new EntityConditionList(UtilMisc.toList(new EntityExpr("organizationPartyId", EntityOperator.EQUALS, organizationPartyId), 1948 new EntityConditionList(UtilMisc.toList(UtilFinancial.getGlAccountClassExpr("REVENUE", delegator), 1949 UtilFinancial.getGlAccountClassExpr("EXPENSE", delegator), 1950 UtilFinancial.getGlAccountClassExpr("INCOME", delegator)), 1951 EntityOperator.OR), 1952 new EntityExpr("postedBalance", EntityOperator.NOT_EQUAL, new Double (0.0))), 1953 EntityOperator.AND); 1954 List glAccounts = delegator.findByCondition("GlAccountOrganizationAndClass", glAccountConditions, 1955 UtilMisc.toList("organizationPartyId", "glAccountId", "postedBalance"), UtilMisc.toList("glAccountId")); 1956 1957 GenericValue timePeriod = delegator.findByPrimaryKeyCache("CustomTimePeriod", UtilMisc.toMap("customTimePeriodId", customTimePeriodId)); 1959 Map tmpResult = dispatcher.runSync("getIncomeStatementAccountSumsByDate", UtilMisc.toMap("organizationPartyId", organizationPartyId, 1960 "fromDate", UtilDateTime.toTimestamp(timePeriod.getDate("thruDate")), "thruDate", UtilDateTime.nowTimestamp(), 1961 "glFiscalTypeId", "ACTUAL", "userLogin", userLogin)); 1962 Map glAccountSums = new HashMap(); if (tmpResult.get("glAccountSums") != null) { 1964 glAccountSums = (Map) tmpResult.get("glAccountSums"); 1965 } 1966 1967 for (Iterator gAi = glAccounts.iterator(); gAi.hasNext(); ) { 1969 GenericValue glAccount = ((GenericValue) gAi.next()).getRelatedOne("GlAccount"); 1970 Double newAmount = null; 1971 if (glAccountSums.get(glAccount) != null) { 1972 newAmount = (Double ) glAccountSums.get(glAccount); 1973 } else { 1974 newAmount = new Double (0.0); 1975 } 1976 Debug.logInfo("now getting ready to reset " + glAccount + " to " + newAmount, module); 1977 tmpResult = dispatcher.runSync("updateGlAccountOrganization", UtilMisc.toMap("organizationPartyId", organizationPartyId, 1978 "glAccountId", glAccount.getString("glAccountId"), "postedBalance", newAmount, "userLogin", userLogin)); 1979 } 1980 1981 return(ServiceUtil.returnSuccess()); 1982 } catch (GenericEntityException ex) { 1983 return(ServiceUtil.returnError(ex.getMessage())); 1984 } catch (GenericServiceException ex) { 1985 return(ServiceUtil.returnError(ex.getMessage())); 1986 } 1987 } 1988 1989 1993 public static Map reconcileGlAccount(DispatchContext dctx, Map context) { 1994 GenericDelegator delegator = dctx.getDelegator(); 1995 LocalDispatcher dispatcher = dctx.getDispatcher(); 1996 GenericValue userLogin = (GenericValue) context.get("userLogin"); 1997 1998 String organizationPartyId = (String ) context.get("organizationPartyId"); 1999 String glAccountId = (String ) context.get("glAccountId"); 2000 String glReconciliationName = (String ) context.get("glReconciliationName"); 2001 String description = (String ) context.get("description"); 2002 Double reconciledBalance = (Double ) context.get("reconciledBalance"); 2003 Timestamp reconciledDate = (Timestamp ) context.get("reconciledDate"); 2004 List acctgTransEntries = (List) context.get("acctgTransEntries"); 2005 try { 2006 if (reconciledBalance == null) { 2007 return ServiceUtil.returnError("Cannot reconcile account " + glAccountId +": No reconciled balance found."); 2008 } 2009 2010 if (reconciledDate == null) { 2011 return ServiceUtil.returnError("Cannot reconcile account " + glAccountId +": No as of date specified."); 2012 } 2013 2014 if ((acctgTransEntries == null) || (acctgTransEntries.size() == 0)) { 2015 return ServiceUtil.returnError("Cannot reconcile account " + glAccountId +": No transactions to be reconciled."); 2016 } 2017 2018 Map params = UtilMisc.toMap("glAccountId", glAccountId, "organizationPartyId", organizationPartyId); 2020 params.put("glReconciliationName", glReconciliationName); 2021 params.put("description", description); 2022 params.put("reconciledBalance", reconciledBalance); 2023 params.put("reconciledDate", reconciledDate); 2024 params.put("userLogin", userLogin); 2025 Debug.logInfo(params.toString(), module); 2026 Map results = dispatcher.runSync("createGlReconciliation", params); 2027 if (ServiceUtil.isError(results)) { 2028 return results; 2029 } 2030 String glReconciliationId = (String ) results.get("glReconciliationId"); 2031 2032 2037 Iterator iter = acctgTransEntries.iterator(); 2038 while (iter.hasNext()) { 2039 String entry = (String ) iter.next(); 2040 if (entry == null) continue; 2041 2042 List tokens = StringUtil.split(entry, "|"); 2044 2045 if ((tokens == null) || (tokens.size() != 2)) continue; 2047 2048 String acctgTransId = (String ) tokens.get(0); 2049 String acctgTransEntrySeqId = (String ) tokens.get(1); 2050 2051 GenericValue acctgTransEntry = delegator.findByPrimaryKey("AcctgTransEntry", UtilMisc.toMap("acctgTransId", acctgTransId, "acctgTransEntrySeqId", acctgTransEntrySeqId)); 2053 2054 if (acctgTransEntry.getString("reconcileStatusId").equals("AES_RECONCILED")) { 2056 return ServiceUtil.returnError("Cannot reconcile account: Submitted transaction entry is already reconciled (acctgTransId=" + acctgTransId 2057 + ", acctgTransEntrySeqId=" + acctgTransEntrySeqId+ ")."); 2058 } 2059 2060 params = UtilMisc.toMap("acctgTransId", acctgTransId, "acctgTransEntrySeqId", acctgTransEntrySeqId); 2062 params.put("userLogin", userLogin); 2063 params.put("reconcileStatusId", "AES_RECONCILED"); 2064 results = dispatcher.runSync("updateAcctgTransEntry", params); 2065 if (ServiceUtil.isError(results)) { 2066 throw new GenericServiceException("Failed to update AcctgTransEntry (acctgTransId=" + acctgTransId 2067 + ", acctgTransEntrySeqId=" + acctgTransEntrySeqId+ ")"); 2068 } 2069 2070 Double amount = acctgTransEntry.getDouble("amount"); 2072 2073 params = UtilMisc.toMap("glReconciliationId", glReconciliationId); 2075 params.put("userLogin", userLogin); 2076 params.put("acctgTransId", acctgTransId); 2077 params.put("acctgTransEntrySeqId", acctgTransEntrySeqId); 2078 params.put("reconciledAmount", amount); 2079 results = dispatcher.runSync("createGlReconciliationEntry", params); 2080 if (ServiceUtil.isError(results)) { 2081 throw new GenericServiceException("Failed to create GlReconciliationEntry (glReconciliationId=" + glReconciliationId 2082 + ", acctgTransId=" + acctgTransId 2083 + ", acctgTransEntrySeqId="+acctgTransEntrySeqId+")"); 2084 } 2085 } 2086 2087 results = ServiceUtil.returnSuccess(); 2088 results.put("glReconciliationId", glReconciliationId); 2089 return results; 2090 2091 } catch (GenericEntityException ex) { 2092 return ServiceUtil.returnError(ex.getMessage()); 2093 } catch (GenericServiceException ex) { 2094 return ServiceUtil.returnError(ex.getMessage()); 2095 } 2096 } 2097 2098 2109 private static void closeAllTimePeriodsByType(GenericDelegator delegator, LocalDispatcher dispatcher, String organizationPartyId, 2110 String periodTypeId, Date asOfDate, GenericValue userLogin) throws GenericEntityException, GenericServiceException { 2111 try { 2112 List timePeriods = delegator.findByAnd("CustomTimePeriod", UtilMisc.toMap("organizationPartyId", organizationPartyId, "periodTypeId", periodTypeId, 2113 "thruDate", asOfDate, "isClosed", "N")); 2114 if ((timePeriods != null) && (timePeriods.size() > 0)) { 2115 for (Iterator tPi = timePeriods.iterator(); tPi.hasNext(); ) { 2116 GenericValue timePeriod = (GenericValue) tPi.next(); 2117 Debug.logInfo("Now trying to close time period " + timePeriod, module); 2118 Map tmpResult = dispatcher.runSync("closeTimePeriod", UtilMisc.toMap("organizationPartyId", organizationPartyId, 2119 "customTimePeriodId", timePeriod.getString("customTimePeriodId"), "userLogin", userLogin)); 2120 if (tmpResult == null) { 2121 throw new GenericServiceException("Failed to close time period for " + organizationPartyId + " and time period " + timePeriod.getString("customTimePeriodId")); 2122 } else if (!tmpResult.get(ModelService.RESPONSE_MESSAGE).equals(ModelService.RESPOND_SUCCESS)) { 2123 throw new GenericServiceException("Failed to close time period for " + organizationPartyId + " and time period " + timePeriod.getString("customTimePeriodId") 2124 + ": " + tmpResult.get(ModelService.ERROR_MESSAGE)); 2125 } 2126 } 2127 } 2128 } catch (GenericEntityException ex) { 2129 Debug.logError(ex.getMessage(), module); 2130 throw new GenericEntityException(ex); 2131 } catch (GenericServiceException ex) { 2132 Debug.logError(ex.getMessage(), module); 2133 throw new GenericServiceException(ex); 2134 } 2135 } 2136 2137 2147 public static Map postForeignExchangeMatchingToGl(DispatchContext dctx, Map context) { 2148 GenericDelegator delegator = dctx.getDelegator(); 2149 LocalDispatcher dispatcher = dctx.getDispatcher(); 2150 GenericValue userLogin = (GenericValue) context.get("userLogin"); 2151 2152 String invoiceId = (String ) context.get("invoiceId"); 2153 try { 2154 GenericValue invoice = delegator.findByPrimaryKeyCache("Invoice", UtilMisc.toMap("invoiceId", invoiceId)); 2156 if (invoice == null) { 2157 return ServiceUtil.returnError("No invoice found for invoiceId of " + invoiceId); 2158 } else if (invoice.get("invoiceTypeId") == null) { 2159 return ServiceUtil.returnError("Invoice " + invoiceId + " has a null invoice type and cannot be processed"); 2160 } 2161 String invoiceTypeId = (String ) invoice.get("invoiceTypeId"); 2162 2163 String transactionPartyId = null; 2165 String transactionPartyRoleTypeId = null; 2166 String organizationPartyId = null; 2167 String offsettingGlAccountTypeId = null; 2168 Map result = null; 2169 2170 if ("SALES_INVOICE".equals(invoiceTypeId)) { 2172 offsettingGlAccountTypeId = "ACCOUNTS_RECEIVABLE"; 2173 organizationPartyId = invoice.getString("partyIdFrom"); 2174 transactionPartyId = invoice.getString("partyId"); 2175 transactionPartyRoleTypeId = "BILL_TO_CUSTOMER"; 2176 } else if ("PURCHASE_INVOICE".equals(invoiceTypeId)) { 2177 offsettingGlAccountTypeId = "ACCOUNTS_PAYABLE"; 2178 organizationPartyId = invoice.getString("partyId"); 2179 transactionPartyId = invoice.getString("partyIdFrom"); 2180 transactionPartyRoleTypeId = "BILL_FROM_VENDOR"; 2181 } else if ("CUST_RTN_INVOICE".equals(invoiceTypeId)) { 2182 result = ServiceUtil.returnSuccess(); 2183 result.put("acctgTransId", null); 2184 return result; 2185 } else { 2186 return ServiceUtil.returnError("Unknown invoiceTypeId '" + invoiceTypeId + "' for Invoice [" + invoiceId + "]"); 2187 } 2188 String invoiceCurrencyId = invoice.getString("currencyUomId"); 2190 GenericValue partyAcctgPreference = delegator.findByPrimaryKey("PartyAcctgPreference", UtilMisc.toMap("partyId", organizationPartyId)); 2192 String companyCurrencyId = partyAcctgPreference.getString("baseCurrencyUomId"); 2193 2194 BigDecimal conversionFactor = new BigDecimal (UtilFinancial.determineUomConversionFactor(delegator, dispatcher, organizationPartyId, invoice.getString("currencyUomId"), invoice.getTimestamp("invoiceDate"))); 2196 BigDecimal invoiceAmount = InvoiceWorker.getInvoiceTotalBd(invoice).multiply(conversionFactor).setScale(decimals, rounding); 2197 2198 BigDecimal paymentAmount = ZERO; 2200 List paymentApplications = delegator.findByAnd("PaymentApplication", UtilMisc.toMap("invoiceId", invoiceId)); 2201 Iterator paymentApplicationIt = paymentApplications.iterator(); 2202 while (paymentApplicationIt.hasNext()) { 2203 GenericValue paymentApplication = (GenericValue)paymentApplicationIt.next(); 2204 GenericValue payment = paymentApplication.getRelatedOne("Payment"); 2205 conversionFactor = new BigDecimal (UtilFinancial.determineUomConversionFactor(delegator, dispatcher, organizationPartyId, payment.getString("currencyUomId"), payment.getTimestamp("effectiveDate"))); 2206 BigDecimal amount = paymentApplication.getBigDecimal("amountApplied"); 2207 paymentAmount = paymentAmount.add(amount.multiply(conversionFactor)).setScale(decimals, rounding); 2208 } 2209 2210 String fxGainLossGlAccountTypeId = null; 2212 String fxGLCreditDebitFlag = null; 2213 String transCreditDebitFlag = null; 2214 2215 BigDecimal transactionAmount = invoiceAmount.subtract(paymentAmount); 2217 if (!invoiceCurrencyId.equals(companyCurrencyId) && (invoiceAmount.compareTo(paymentAmount) != 0)) { 2218 if (invoiceAmount.compareTo(paymentAmount) > 0 ){ 2219 if ("SALES_INVOICE".equals(invoiceTypeId)) { fxGainLossGlAccountTypeId = "FX_LOSS_ACCOUNT"; 2221 fxGLCreditDebitFlag = "D"; 2222 transCreditDebitFlag = "C"; 2223 } else { fxGainLossGlAccountTypeId = "FX_GAIN_ACCOUNT"; 2225 fxGLCreditDebitFlag = "C"; 2226 transCreditDebitFlag = "D"; 2227 } 2228 } else { 2229 transactionAmount = transactionAmount.negate(); 2230 if ("SALES_INVOICE".equals(invoiceTypeId)) { fxGainLossGlAccountTypeId = "FX_GAIN_ACCOUNT"; 2232 fxGLCreditDebitFlag = "C"; 2233 transCreditDebitFlag = "D"; 2234 } else { fxGainLossGlAccountTypeId = "FX_LOSS_ACCOUNT"; 2236 fxGLCreditDebitFlag = "D"; 2237 transCreditDebitFlag = "C"; 2238 } 2239 } 2240 } 2241 else { 2242 result = ServiceUtil.returnSuccess(); 2243 result.put("acctgTransId", null); 2244 return result; 2245 } 2246 2247 String fxGlAccountId = UtilAccounting.getDefaultAccountId(fxGainLossGlAccountTypeId, organizationPartyId, delegator); 2249 String transGlAccountId = UtilAccounting.getDefaultAccountId(offsettingGlAccountTypeId, organizationPartyId, delegator); 2251 2252 Map input = UtilMisc.toMap("glAccountId", fxGlAccountId, "organizationPartyId", organizationPartyId, "partyId", transactionPartyId); 2254 input.put("amount", new Double (transactionAmount.doubleValue())); 2255 input.put("acctgTransEntryTypeId", "_NA_"); 2256 input.put("debitCreditFlag", fxGLCreditDebitFlag); 2257 input.put("acctgTransEntrySeqId", Integer.toString(0)); 2258 input.put("roleTypeId", transactionPartyRoleTypeId); 2259 GenericValue creditAcctTrans = delegator.makeValue("AcctgTransEntry", input); 2260 2261 input = UtilMisc.toMap("glAccountId", transGlAccountId, "organizationPartyId", organizationPartyId, "partyId", transactionPartyId); 2263 input.put("amount", new Double (transactionAmount.doubleValue())); 2264 input.put("acctgTransEntryTypeId", "_NA_"); 2265 input.put("debitCreditFlag", transCreditDebitFlag); 2266 input.put("acctgTransEntrySeqId", Integer.toString(1)); 2267 input.put("roleTypeId", transactionPartyRoleTypeId); 2268 GenericValue debitAcctTrans = delegator.makeValue("AcctgTransEntry", input); 2269 2270 input = UtilMisc.toMap("transactionDate", UtilDateTime.nowTimestamp(), "partyId", transactionPartyId, "userLogin", userLogin); 2272 input.put("acctgTransEntries", UtilMisc.toList(creditAcctTrans, debitAcctTrans)); 2273 input.put("invoiceId", invoiceId); 2274 input.put("roleTypeId", transactionPartyRoleTypeId); 2275 input.put("glFiscalTypeId", "ACTUAL"); 2276 input.put("acctgTransTypeId", "FX_GAINLOSS_ACCTG"); 2277 Map servResult = dispatcher.runSync("createAcctgTransAndEntries", input); 2278 2279 if (((String ) servResult.get(ModelService.RESPONSE_MESSAGE)).equals(ModelService.RESPOND_SUCCESS)) { 2280 result = ServiceUtil.returnSuccess(); 2281 result.put("acctgTransId", servResult.get("acctgTransId")); 2282 return(result); 2283 } else { 2284 return servResult; 2285 } 2286 } catch (GenericEntityException ex) { 2287 return(ServiceUtil.returnError(ex.getMessage())); 2288 } catch (GenericServiceException ex) { 2289 return(ServiceUtil.returnError(ex.getMessage())); 2290 } 2291 } 2292 2293} 2294 | Popular Tags |