KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > nightlabs > ipanema > accounting > PartnerAccountant


1 /*
2  * Created on Feb 17, 2005
3  * by alex
4  *
5  */

6 package com.nightlabs.ipanema.accounting;
7
8 import java.util.Collections JavaDoc;
9 import java.util.Comparator JavaDoc;
10 import java.util.Iterator JavaDoc;
11 import java.util.LinkedList JavaDoc;
12 import java.util.List JavaDoc;
13
14 import javax.jdo.JDOHelper;
15 import javax.jdo.PersistenceManager;
16
17 import com.nightlabs.ipanema.trade.LegalEntity;
18 import com.nightlabs.ipanema.transfer.Anchor;
19
20 /**
21  * One instance of PartnerAccountant exists per organisation.
22  * It handles Transfers for trade partners that can be other
23  * organisations or customers.
24  *
25  * @author Alexander Bieber <alex[AT]nightlabs[DOT]de>
26  *
27  * @jdo.persistence-capable
28  * identity-type = "application"
29  * persistence-capable-superclass = "com.nightlabs.ipanema.accounting.Accountant"
30  * detachable = "true"
31  *
32  * @jdo.inheritance strategy = "new-table"
33  */

34 // TODO: change inheritence strategy to "no-table"
35
public class PartnerAccountant extends Accountant {
36
37     /**
38      *
39      */

40     public PartnerAccountant() {
41         super();
42     }
43
44     /**
45      * @param organisationID
46      * @param accountantID
47      */

48     public PartnerAccountant(String JavaDoc organisationID, String JavaDoc accountantID) {
49         super(organisationID, accountantID);
50     }
51
52     /**
53      * @see com.nightlabs.ipanema.accounting.Accountant#bookTransfer(com.nightlabs.ipanema.trade.LegalEntity, com.nightlabs.ipanema.accounting.MoneyTransfer)
54      */

55     public void bookTransfer(LegalEntity mandator, MoneyTransfer transfer) {
56         if (transfer instanceof IntraLegalEntityMoneyTransfer) {
57             handleInterLegalEntityMoneyTransfer(mandator, (InterLegalEntityMoneyTransfer)transfer);
58         }
59         else if (transfer instanceof PayMoneyTransfer) {
60             handlePayMoneyTransfer(mandator, (PayMoneyTransfer)transfer);
61         }
62     }
63     
64     /**
65      * Handles MoneyTransfers between LegalEntities by creating one IntraLegalMoneyTransfer for the
66      * given InterLegalEntityMoneyTransfer.
67      *
68      * @param mandator
69      * @param transfer
70      */

71     protected void handleInterLegalEntityMoneyTransfer(LegalEntity mandator, InterLegalEntityMoneyTransfer transfer) {
72         boolean mandatorIsVendor = transfer.getInvoice().getVendor().getPrimaryKey().equals(mandator.getPrimaryKey());
73         boolean mandatorIsCustomer = !mandatorIsVendor;
74         
75         boolean mandatorIsTransferTo = transfer.getTo().getPrimaryKey().equals(mandator.getPrimaryKey());
76         boolean mandatorIsTransferFrom = !mandatorIsTransferTo;
77         
78         Anchor createTransferFrom = null;
79         Anchor createTransferTo = null;
80         Accounting accounting = Accounting.getAccounting(getPersistenceManager());
81         // create IntraLegalEntityMoneyTransfer from PartnerAccount(AsDebitor) to mandator (or <->)
82
// determine the direction
83
if (mandatorIsCustomer) {
84             Account customerPartnerAccount = accounting.getPartnerAccount(Account.PARTNER_ACCOUNT_TYPE_CUSTOMER, mandator, transfer.getInvoice().getCurrency());
85             if (mandatorIsTransferFrom) {
86                 createTransferFrom = customerPartnerAccount;
87                 createTransferTo = mandator;
88             }
89             else {
90                 createTransferFrom = mandator;
91                 createTransferTo = customerPartnerAccount;
92             }
93         }
94         else {
95             // if (mandatorIsCustomer)
96
Account vendorPartnerAccount = accounting.getPartnerAccount(Account.PARTNER_ACCOUNT_TYPE_VENDOR, mandator, transfer.getInvoice().getCurrency());
97             if (mandatorIsTransferFrom) {
98                 createTransferFrom = vendorPartnerAccount;
99                 createTransferTo = mandator;
100             }
101             else {
102                 createTransferFrom = mandator;
103                 createTransferTo = vendorPartnerAccount;
104             }
105         }
106         
107         IntraLegalEntityMoneyTransfer moneyTransfer = new IntraLegalEntityMoneyTransfer(
108             accounting,
109             transfer,
110             createTransferFrom,
111             createTransferTo
112         );
113         
114         createTransferFrom.bookTransfer(moneyTransfer);
115         createTransferTo.bookTransfer(moneyTransfer);
116     }
117     
118     
119     
120     private static class TransferInvoiceEntry {
121         private Invoice invoice;
122         private long invoiceBalance;
123         public TransferInvoiceEntry(Invoice invoice, long invoiceBalance) {
124             this.invoice = invoice;
125             this.invoiceBalance = invoiceBalance;
126         }
127         public Invoice getInvoice() {
128             return invoice;
129         }
130         public long getInvoiceBalance() {
131             return invoiceBalance;
132         }
133     }
134     
135     /**
136      * Handles payments by creating IntraLegalMoneyTransfer.<br/>
137      * Implements the following:
138      * <pre>
139      * * sort invoices (organisationID / invoiceID)
140      * * classify in invoicesPayMoney and invoicesRecieveMoney
141      * * balance invoices
142      * if (balace >= 0)
143      * * clear all invoicesRecieveMoney
144      * * clear all possible invoicesPayMoney following the order
145      * else
146      * if (have invoicesRecieveMoney)
147      * * clear all invoicesPayMoney
148      * * clear all possible invoicesRecieveMoney following the order
149      * else
150      * * not handled yet
151      * </pre>
152      *
153      * @param mandator
154      * @param transfer
155      */

156     protected void handlePayMoneyTransfer(LegalEntity mandator, PayMoneyTransfer transfer) {
157         // Sort Invoices
158
List JavaDoc sortedInvoices = new LinkedList JavaDoc();
159         for (int i = 0; i<transfer.getInvoices().length; i++) {
160             sortedInvoices.add(transfer.getInvoices()[i]);
161         }
162         Comparator JavaDoc comparator = new Comparator JavaDoc() {
163             public int compare(Object JavaDoc arg0, Object JavaDoc arg1) {
164                 if ( (arg0 instanceof Invoice) && (arg1 instanceof Invoice) ) {
165                     Invoice inv0 = (Invoice)arg0;
166                     Invoice inv1 = (Invoice)arg1;
167                     if (inv0.getOrganisationID().equals(inv1.getOrganisationID())) {
168                         if (inv0.getInvoiceID() < inv1.getInvoiceID())
169                             return -1;
170                         else if (inv0.getInvoiceID() > inv1.getInvoiceID())
171                             return 1;
172                         else
173                             return 0;
174                     }
175                     else
176                         return inv0.getOrganisationID().compareTo(inv1.getOrganisationID());
177                 }
178                 else
179                     return 0;
180             }
181         };
182         Collections.sort(sortedInvoices,comparator);
183         
184         
185         
186         // classify Invoices and compute overallBalance
187
boolean mandatorTransferTo = (transfer.getTo() != null) && (transfer.getTo().getPrimaryKey().equals(mandator.getPrimaryKey()));
188         boolean mandatorTransferFrom = !mandatorTransferTo;
189         
190         List JavaDoc invoicesPayMoney = new LinkedList JavaDoc();
191         List JavaDoc invoicesRecieveMoney = new LinkedList JavaDoc();
192         
193         Accounting accounting = Accounting.getAccounting(getPersistenceManager());
194         
195         long overallBalance = 0;
196         
197         for (Iterator JavaDoc iter = sortedInvoices.iterator(); iter.hasNext();) {
198             Invoice invoice = (Invoice) iter.next();
199             long invoiceBalance = 0;
200             boolean mandatorInvoiceCustomer = invoice.getCustomer().getPrimaryKey().equals(mandator.getPrimaryKey());
201             boolean mandatorInvoiceCreditor = !mandatorInvoiceCustomer;
202             long factor = 1;
203             if ( (mandatorTransferTo && mandatorInvoiceCreditor) || (mandatorTransferFrom && mandatorInvoiceCustomer) )
204                 factor = -1;
205             invoiceBalance = invoice.getAmountToPay() * factor;
206             overallBalance += invoiceBalance;
207             if (invoiceBalance >= 0)
208                 invoicesRecieveMoney.add(new TransferInvoiceEntry(invoice,invoiceBalance));
209             else
210                 invoicesRecieveMoney.add(new TransferInvoiceEntry(invoice,invoiceBalance));
211         }
212         
213         // create a IntraLegalEntityMoneyTransfer to transfer the money from LE to Account or vice versa
214
if (mandatorTransferFrom) {
215             // PayMoneyTransfer
216
// Mandator ---------------------> NULL
217
Account fromAccount = accounting.getPartnerAccount(Account.PARTNER_ACCOUNT_TYPE_VENDOR,mandator,transfer.getCurrency());
218             IntraLegalEntityMoneyTransfer moneyTransfer = new IntraLegalEntityMoneyTransfer(
219                 accounting,
220                 transfer,
221                 fromAccount,
222                 mandator,
223                 transfer,
224                 transfer.getCurrency(),
225                 transfer.getAmount()
226             );
227             
228             fromAccount.bookTransfer(moneyTransfer);
229             mandator.bookTransfer(moneyTransfer);
230         }
231         else {
232             // PayMoneyTransfer
233
// NULL ---------------------> Mandator
234
Account toAccount = accounting.getPartnerAccount(Account.PARTNER_ACCOUNT_TYPE_CUSTOMER,mandator,transfer.getCurrency());
235             IntraLegalEntityMoneyTransfer moneyTransfer = new IntraLegalEntityMoneyTransfer(
236                 accounting,
237                 transfer,
238                 mandator,
239                 toAccount,
240                 transfer,
241                 transfer.getCurrency(),
242                 transfer.getAmount()
243             );
244             
245             mandator.bookTransfer(moneyTransfer);
246             toAccount.bookTransfer(moneyTransfer);
247         }
248         
249         if (overallBalance >= 0) {
250             // overall balance positve or zero: underpayment
251
long moneyBalance = transfer.getAmount();
252             // we can safely clear all invoices
253
// where there is money to recieve fist
254
for (Iterator JavaDoc iter = invoicesRecieveMoney.iterator(); iter.hasNext();) {
255                 TransferInvoiceEntry entry = (TransferInvoiceEntry) iter.next();
256                 Invoice invoice = entry.getInvoice();
257                 invoice.setAmountPaid(invoice.getPrice().getAmount());
258                 invoice.setPaid(true);
259                 moneyBalance -= entry.getInvoiceBalance();
260             }
261             // now clear all invoices
262
// where there is money to pay as long as
263
// the moneyBalance allows it
264
for (Iterator JavaDoc iter = invoicesPayMoney.iterator(); iter.hasNext();) {
265                 TransferInvoiceEntry entry = (TransferInvoiceEntry) iter.next();
266                 Invoice invoice = entry.getInvoice();
267                 if (moneyBalance >= entry.getInvoiceBalance()) {
268                     invoice.setAmountPaid(invoice.getPrice().getAmount());
269                     invoice.setPaid(true);
270                     moneyBalance -= entry.getInvoiceBalance();
271                 }
272                 else {
273                     invoice.setAmountPaid(invoice.getAmountPaid() + moneyBalance);
274                     moneyBalance = 0;
275                     break;
276                 }
277             }
278             
279         }
280         else {
281             // overall balance negative: overpayment
282
if (invoicesRecieveMoney.size() > 0) {
283                 // there is at least one invoice where theres money to recieve
284
// we can leave open
285
long moneyBalance = transfer.getAmount();
286                 // we can safely clear all invoices
287
// where there is money to pay first
288
for (Iterator JavaDoc iter = invoicesPayMoney.iterator(); iter.hasNext();) {
289                     TransferInvoiceEntry entry = (TransferInvoiceEntry) iter.next();
290                     Invoice invoice = entry.getInvoice();
291                     invoice.setAmountPaid(invoice.getPrice().getAmount());
292                     invoice.setPaid(true);
293                     moneyBalance -= entry.getInvoiceBalance();
294                 }
295                 // moneyBalance now negative
296
// now clear all invoices
297
// where there is money to recieve as long as
298
// the moneyBalance allows it
299
for (Iterator JavaDoc iter = invoicesRecieveMoney.iterator(); iter.hasNext();) {
300                     TransferInvoiceEntry entry = (TransferInvoiceEntry) iter.next();
301                     Invoice invoice = entry.getInvoice();
302                     if (moneyBalance <= entry.getInvoiceBalance()) {
303                         invoice.setAmountPaid(invoice.getPrice().getAmount());
304                         invoice.setPaid(true);
305                         moneyBalance -= entry.getInvoiceBalance();
306                     }
307                     else {
308                         invoice.setAmountPaid(invoice.getAmountPaid() + moneyBalance);
309                         moneyBalance = 0;
310                         break;
311                     }
312                 }
313             }
314             else {
315                 // if (invoicesRecieveMoney.size() > 0) {
316
// there is no invoice where theres money to recieve
317
// we can leave open
318
// TODO: handle overpayment -> MoneyTransfer to special account
319
}
320         }
321         
322 // List invoicesAsCustomer = new LinkedList();
323
// List invoicesAsVendor = new LinkedList();
324
//
325
// long amountToPayAsCustomer = 0;
326
// long amountToGetAsVendor = 0;
327
// long amountToPayOverAll = 0;
328
//
329
// for (int i = 0; i<transfer.getInvoices().length; i++) {
330
// Invoice invoice = transfer.getInvoices()[i];
331
// if (mandator.getPrimaryKey().equals(invoice.getVendor().getPrimaryKey())) {
332
// // invoice as vendor
333
// amountToGetAsVendor -= invoice.getPrice().getAmount();
334
// amountToPayOverAll -= invoice.getPrice().getAmount();
335
// invoicesAsVendor.add(transfer.getInvoices()[i]);
336
// }
337
// else {
338
// amountToPayAsCustomer += invoice.getPrice().getAmount();
339
// amountToPayOverAll += invoice.getPrice().getAmount();
340
// invoicesAsCustomer.add(transfer.getInvoices()[i]);
341
// }
342
// } // for (int i = 0; i<transfer.getInvoices().length; i++) {
343
//
344
// if (amountToPayOverAll >= 0) {
345
// // balance is greater than 0
346
// }
347
}
348     
349     private PersistenceManager accountantPM = null;
350     
351     protected PersistenceManager getPersistenceManager() {
352         if (accountantPM == null) {
353             accountantPM = JDOHelper.getPersistenceManager(this);
354             if (accountantPM == null)
355                 throw new IllegalStateException JavaDoc("This instance of PartnerAccountant is currently not persistent, can not get a PesistenceManager!!");
356         }
357         return accountantPM;
358     }
359
360 }
361
Popular Tags