1 4 package com.nightlabs.ipanema.accounting; 5 6 import java.util.Collection ; 7 import java.util.HashMap ; 8 import java.util.HashSet ; 9 import java.util.Iterator ; 10 import java.util.Map ; 11 12 import javax.jdo.JDOHelper; 13 import javax.jdo.JDOObjectNotFoundException; 14 import javax.jdo.PersistenceManager; 15 16 import com.nightlabs.ModuleException; 17 import com.nightlabs.ipanema.accounting.id.InvoiceID; 18 import com.nightlabs.ipanema.organisation.LocalOrganisation; 19 import com.nightlabs.ipanema.security.User; 20 import com.nightlabs.ipanema.store.Product; 21 import com.nightlabs.ipanema.trade.LegalEntity; 22 import com.nightlabs.ipanema.trade.Offer; 23 import com.nightlabs.ipanema.trade.OfferItem; 24 import com.nightlabs.ipanema.trade.Order; 25 import com.nightlabs.ipanema.trade.OrganisationLegalEntity; 26 import com.nightlabs.ipanema.trade.id.OfferItemID; 27 import com.nightlabs.ipanema.transfer.Transfer; 28 import com.nightlabs.ipanema.transfer.TransferRegistry; 29 import com.nightlabs.ipanema.transfer.id.AnchorID; 30 31 41 public class Accounting 42 implements TransferRegistry 43 { 44 51 public static Accounting getAccounting(PersistenceManager pm) 52 { 53 Iterator it = pm.getExtent(Accounting.class).iterator(); 54 if (it.hasNext()) 55 return (Accounting)it.next(); 56 57 Accounting accounting = new Accounting(); 58 59 it = pm.getExtent(LocalOrganisation.class).iterator(); 61 if (!it.hasNext()) 62 throw new IllegalStateException ("LocalOrganisation undefined in datastore!"); 63 LocalOrganisation localOrganisation = (LocalOrganisation) it.next(); 64 String organisationID = localOrganisation.getOrganisation().getOrganisationID(); 65 accounting.organisationID = organisationID; 66 accounting.mandator = new OrganisationLegalEntity(localOrganisation.getOrganisation()); 67 accounting.accountingPriceConfig = new AccountingPriceConfig(organisationID, accounting.createPriceConfigID()); 68 69 pm.makePersistent(accounting); 70 return accounting; 71 } 72 73 77 private String organisationID; 78 79 82 private OrganisationLegalEntity mandator; 83 84 87 private AccountingPriceConfig accountingPriceConfig; 88 89 92 public String getOrganisationID() 93 { 94 return organisationID; 95 } 96 97 100 protected transient PersistenceManager accountingPM = null; 101 102 protected PersistenceManager getPersistenceManager() { 103 if (accountingPM == null) { 104 accountingPM = JDOHelper.getPersistenceManager(this); 105 if (accountingPM == null) 106 throw new IllegalStateException ("This instance of Accounting is not persistent, can not get a PersistenceManager!"); 107 } 108 return accountingPM; 109 } 110 111 public OrganisationLegalEntity getMandator() { 112 return mandator; 113 } 114 115 130 protected Map productInfos = new HashMap (); 131 132 public ProductInfo getProductInfo(String organisationID, String productID, boolean throwExceptionIfNotExistent) 133 { 134 String pk = ProductInfo.getPrimaryKey(organisationID, productID); 135 ProductInfo res = (ProductInfo) productInfos.get(pk); 136 if (res == null && throwExceptionIfNotExistent) 137 throw new IllegalArgumentException ("No ProductInfo existing with organisationID=\""+organisationID+"\" and productID=\""+productID+"\"!"); 138 return res; 139 } 140 141 public ProductInfo getProductInfo(Product product, boolean throwExceptionIfNotExistent) 142 { 143 String pk = product.getPrimaryKey(); 144 ProductInfo res = (ProductInfo) productInfos.get(pk); 145 if (res == null && throwExceptionIfNotExistent) 146 throw new IllegalArgumentException ("No ProductInfo existing for product \""+pk+"\"!"); 147 return res; 148 } 149 150 public void addProductInfo(ProductInfo productInfo) 151 { 152 productInfos.put(productInfo.getPrimaryKey(), productInfo); 153 } 154 155 167 public ProductInfo createProductInfo(Product product) 168 throws ModuleException 169 { 170 String pk = product.getPrimaryKey(); 171 ProductInfo productInfo = (ProductInfo) productInfos.get(pk); 172 173 if (productInfo == null) { 174 ProductInfo extendedProductInfo = null; 175 ProductInfoFactory productInfoFactory = null; 176 Product extendedProduct = product.getExtendedProduct(); 177 178 if (extendedProduct != null) 179 extendedProductInfo = getProductInfo(extendedProduct, true); 180 181 if (extendedProductInfo != null) 182 productInfoFactory = extendedProductInfo.getProductInfoFactory(); 183 184 if (productInfoFactory != null) 185 productInfo = productInfoFactory.createProductInfo(product, extendedProductInfo); 186 else 187 productInfo = new ProductInfo(product, extendedProductInfo); 188 189 addProductInfo(productInfo); 190 updatePackagedProductInfos(productInfo); 191 } 192 193 return productInfo; 194 } 195 196 199 public AccountingPriceConfig getAccountingPriceConfig() 200 { 201 return accountingPriceConfig; 202 } 203 204 211 public void updatePackagedProductInfos(ProductInfo productInfo) 212 { 213 215 HashSet packagedProductPKs = new HashSet (); 217 for (Iterator it = productInfo.getProduct().getPackagedProducts().iterator(); it.hasNext(); ) { 218 Product packagedProduct = (Product)it.next(); 219 packagedProductPKs.add(packagedProduct.getPrimaryKey()); 220 ProductInfo packagedProductInfo = productInfo.getPackagedProductInfo( 221 packagedProduct.getOrganisationID(), packagedProduct.getProductID(), false); 222 if (packagedProductInfo == null) { 223 packagedProductInfo = getProductInfo(packagedProduct, true); 224 productInfo.addPackagedProductInfo(packagedProductInfo); 225 } 226 } 227 228 229 231 HashSet packagedProductInfosToDelete = new HashSet (); 234 for (Iterator it = productInfo.getPackagedProductInfos().iterator(); it.hasNext(); ) { 235 ProductInfo packagedProductInfo = (ProductInfo)it.next(); 236 if (!packagedProductPKs.contains(packagedProductInfo.getPrimaryKey())) 237 packagedProductInfosToDelete.add(packagedProductInfo); 238 } 239 240 for (Iterator it = packagedProductInfosToDelete.iterator(); it.hasNext(); ) { 241 ProductInfo packagedProductInfo = (ProductInfo)it.next(); 242 productInfo.removePackagedProductInfo( 243 packagedProductInfo.getOrganisationID(), packagedProductInfo.getProductID()); 244 } 245 } 246 247 251 private long nextTransferID = 0; 252 253 268 protected Map transfers = new HashMap (); 269 270 276 public void addTransfer(Transfer transfer) 277 { 278 if (transfer == null) 279 throw new NullPointerException ("transfer is null!"); 280 281 if (transfer.getOrganisationID() == null) 282 throw new NullPointerException ("transfer.organisationID is null!"); 283 284 if (transfer.getTransferID() < 0) 285 throw new NullPointerException ("transfer.transferID < 0!"); 286 287 String key = transfer.getPrimaryKey(); 288 if (transfers.containsKey(key)) 289 throw new IllegalStateException ("Cannot add transfer, because a transfer with the same key already exists!"); 290 291 transfers.put(transfer.getPrimaryKey(), transfer); 292 } 293 294 public synchronized long createTransferID(String organisationID, String transferTypeID) 295 { 296 if (organisationID.equals(getOrganisationID())) 297 throw new IllegalArgumentException ("This instance of Accounting can only create transferIDs for the organisation \""+getOrganisationID()+"\"!"); 298 299 if (!MoneyTransfer.TRANSFERTYPEID.equals(transferTypeID)) 300 throw new IllegalArgumentException ("This implementation of TransferRegistry manages only Transfers with transferTypeID=\""+MoneyTransfer.TRANSFERTYPEID+"\"!"); 301 long res = nextTransferID; 302 nextTransferID = res + 1; 303 return res; 304 } 305 307 310 private long nextPriceConfigID = 0; 311 312 public synchronized long createPriceConfigID() { 313 long res = nextPriceConfigID; 314 nextPriceConfigID = res + 1; 315 return res; 316 } 317 318 321 private long nextInvoiceID = 0; 322 323 protected synchronized long createInvoiceID() { 324 long res = nextInvoiceID; 325 nextInvoiceID = res + 1; 326 return res; 327 } 328 329 330 337 public Invoice createInvoice(User user, Collection offerItems) 338 throws InvoiceEditException 339 { 340 if (offerItems.size() <= 0) 341 throw new InvoiceEditException( 342 InvoiceEditException.REASON_NO_OFFERITEMS, 343 "Can not create an Invoice with no OfferItems!" 344 ); 345 346 String vendorPK = null; 350 String customerPK = null; 351 LegalEntity customerLE = null; 352 Currency invoiceCurrency = null; 353 for (Iterator iter = offerItems.iterator(); iter.hasNext();) { 354 OfferItem offerItem = (OfferItem) iter.next(); 355 356 if (vendorPK == null) 357 vendorPK = offerItem.getOffer().getOrder().getVendor().getPrimaryKey(); 358 if (customerPK == null) { 359 customerLE = offerItem.getOffer().getOrder().getCustomer(); 360 customerPK = customerLE.getPrimaryKey(); 361 } 362 if (invoiceCurrency == null) 363 invoiceCurrency = offerItem.getPrice().getCurrency(); 364 365 OfferItemID offerItemID = OfferItemID.create(offerItem.getOrganisationID(),offerItem.getOfferID(),offerItem.getProductOrganisationID(),offerItem.getProductID()); 366 Offer itemOffer = offerItem.getOffer(); 367 Order itemOrder = itemOffer.getOrder(); 368 369 if (!itemOffer.isConfirmed()) { 370 throw new InvoiceEditException( 371 InvoiceEditException.REASON_OFFER_NOT_CONFIRMED, 372 "At least one involved offer is not confirmed!", 373 offerItemID 374 ); 375 } 376 377 if (!vendorPK.equals(itemOrder.getVendor().getPrimaryKey()) 378 || 379 !customerPK.equals(itemOrder.getCustomer().getPrimaryKey()) 380 ) 381 { 382 throw new InvoiceEditException( 383 InvoiceEditException.REASON_ANCHORS_DONT_MATCH, 384 "Vendor and customer are not equal for all involved orders, can not create Invoice!!" 385 ); 386 } 387 388 if (offerItem.getInvoice() != null) { 389 InvoiceID invoiceID = InvoiceID.create(offerItem.getInvoice().getOrganisationID(), offerItem.getInvoice().getInvoiceID()); 390 throw new InvoiceEditException( 391 InvoiceEditException.REASON_OFFERITEM_ALREADY_IN_INVOICE, 392 "OfferItem already in an invoice. OfferItem "+offerItemID+", Invoice "+invoiceID, 393 offerItemID, 394 invoiceID 395 ); 396 } 397 398 if (!invoiceCurrency.getCurrencyID().equals(offerItem.getPrice().getCurrency().getCurrencyID())) 399 throw new InvoiceEditException( 400 InvoiceEditException.REASON_MULTIPLE_CURRENCIES, 401 "Can not create an Invoice with more than one Currency!" 402 ); 403 } 404 405 if (!vendorPK.equals(getMandator().getPrimaryKey())) 406 throw new InvoiceEditException( 407 InvoiceEditException.REASON_FOREIGN_ORGANISATION, 408 "Attempt to create a Invoice not with the local organisation as vendor. Vendor is "+vendorPK 409 ); 410 411 Invoice invoice = new Invoice(user, getMandator().getOrganisationID(), createInvoiceID()); 412 for (Iterator iter = offerItems.iterator(); iter.hasNext();) { 413 OfferItem offerItem = (OfferItem) iter.next(); 414 invoice.addOfferItem(offerItem); 415 } 416 getPersistenceManager().makePersistent(invoice); 417 418 419 420 return invoice; 421 } 422 423 429 public void bookInvoice(User initiator, Invoice invoice) { 430 431 LegalEntity from = null; 432 LegalEntity to = null; 433 434 if (invoice.getPrice().getAmount() >= 0) { 435 from = invoice.getCustomer(); 436 to = invoice.getVendor(); 437 } 438 else { 439 from = invoice.getVendor(); 440 to = invoice.getCustomer(); 441 } 442 443 InterLegalEntityMoneyTransfer interLegalEntityMoneyTransfer = new InterLegalEntityMoneyTransfer( 445 Accounting.getAccounting(getPersistenceManager()), 446 null, 447 initiator, 448 from, 449 to, 450 invoice, 451 invoice.getPrice().getCurrency(), 452 invoice.getPrice().getAmountAbsoluteValue() 453 ); 455 from.bookTransfer(interLegalEntityMoneyTransfer); 456 to.bookTransfer(interLegalEntityMoneyTransfer); 457 458 invoice.setBooked(initiator, true); 459 } 460 461 468 public void finalizeInvoice(User finalizer, Invoice invoice) { 469 if (!invoice.getVendor().getPrimaryKey().equals(getMandator().getPrimaryKey())) 470 throw new IllegalArgumentException ("Can not finalize an invoice where mandator is not vendor of this invoice!"); 471 invoice.setFinalized(finalizer, true); 472 if (invoice.getCustomer() instanceof OrganisationLegalEntity) { 473 } 475 } 476 477 485 public Account getPartnerAccount(String partnerAccountType, LegalEntity partner, Currency currency) { 486 if (partner == null) 487 throw new IllegalArgumentException ("Parameter partner must not be null!"); 488 if (currency == null) 489 throw new IllegalArgumentException ("Parameter currency must not be null!"); 490 491 String searchAccountID = partner.getAnchorID()+"-"+partnerAccountType+"-"+currency.getCurrencyID(); 492 AnchorID anchorID = AnchorID.create(this.getOrganisationID(), searchAccountID); 493 494 Account account = null; 495 Object o = null; 496 try { 497 o = getPersistenceManager().getObjectById(anchorID); 498 account = (Account)o; 499 } 500 catch (ClassCastException ce) { 501 IllegalStateException ill = new IllegalStateException ("Found persistent object with oid "+anchorID+" but is not of type Account but "+o.getClass().getName()); 502 ill.initCause(ce); 503 throw ill; 504 } 505 catch (JDOObjectNotFoundException je) { 506 account = new Account(this.getOrganisationID(), searchAccountID, currency, false); 508 getPersistenceManager().makePersistent(account); 509 account.setOwner(partner); 510 } 511 512 if (account == null) 513 throw new IllegalStateException ("Account with oid "+anchorID+" could neither be found nor created!"); 514 515 if (!account.getOwner().getPrimaryKey().equals(partner.getPrimaryKey())) 516 throw new IllegalStateException ("A account for oid "+anchorID+" could be found, but its owner is not the partner the search was performed for. Owner: "+account.getOwner().getPrimaryKey()+", Partner: "+partner.getPrimaryKey()); 517 518 return account; 519 } 520 } 521 | Popular Tags |