001 /*
002 * Copyright 2011 The Kuali Foundation.
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.kfs.module.ar.document;
017
018 import java.sql.Date;
019 import java.util.ArrayList;
020 import java.util.List;
021
022 import org.apache.commons.lang.StringUtils;
023 import org.kuali.kfs.coa.businessobject.Account;
024 import org.kuali.kfs.coa.businessobject.Chart;
025 import org.kuali.kfs.coa.businessobject.ObjectCode;
026 import org.kuali.kfs.coa.businessobject.ProjectCode;
027 import org.kuali.kfs.coa.businessobject.SubAccount;
028 import org.kuali.kfs.coa.businessobject.SubObjectCode;
029 import org.kuali.kfs.module.ar.ArConstants;
030 import org.kuali.kfs.module.ar.businessobject.AccountsReceivableDocumentHeader;
031 import org.kuali.kfs.module.ar.businessobject.CustomerInvoiceDetail;
032 import org.kuali.kfs.module.ar.businessobject.ReceivableCustomerInvoiceDetail;
033 import org.kuali.kfs.module.ar.businessobject.SalesTaxCustomerInvoiceDetail;
034 import org.kuali.kfs.module.ar.businessobject.WriteoffCustomerInvoiceDetail;
035 import org.kuali.kfs.module.ar.businessobject.WriteoffTaxCustomerInvoiceDetail;
036 import org.kuali.kfs.module.ar.document.service.AccountsReceivableTaxService;
037 import org.kuali.kfs.module.ar.document.service.CustomerInvoiceGLPEService;
038 import org.kuali.kfs.module.ar.document.service.CustomerInvoiceWriteoffDocumentService;
039 import org.kuali.kfs.sys.KFSConstants;
040 import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper;
041 import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail;
042 import org.kuali.kfs.sys.businessobject.TaxDetail;
043 import org.kuali.kfs.sys.context.SpringContext;
044 import org.kuali.kfs.sys.document.AmountTotaling;
045 import org.kuali.kfs.sys.document.GeneralLedgerPendingEntrySource;
046 import org.kuali.kfs.sys.document.GeneralLedgerPostingDocumentBase;
047 import org.kuali.kfs.sys.service.GeneralLedgerPendingEntryService;
048 import org.kuali.kfs.sys.service.TaxService;
049 import org.kuali.rice.kew.dto.DocumentRouteStatusChangeDTO;
050 import org.kuali.rice.kns.bo.Note;
051 import org.kuali.rice.kns.exception.ValidationException;
052 import org.kuali.rice.kns.rule.event.KualiDocumentEvent;
053 import org.kuali.rice.kns.service.ParameterService;
054 import org.kuali.rice.kns.util.KualiDecimal;
055 import org.kuali.rice.kns.util.ObjectUtils;
056 import org.kuali.rice.kns.util.TypedArrayList;
057
058 public class CustomerInvoiceWriteoffDocument extends GeneralLedgerPostingDocumentBase implements GeneralLedgerPendingEntrySource, AmountTotaling {
059
060 protected static final String REQUIRES_APPROVAL_NODE = "RequiresApproval";
061 protected String chartOfAccountsCode;
062 protected String accountNumber;
063 protected String subAccountNumber;
064 protected String financialObjectCode;
065 protected String financialSubObjectCode;
066 protected String projectCode;
067 protected String organizationReferenceIdentifier;
068 protected String financialDocumentReferenceInvoiceNumber;
069 protected String statusCode;
070
071 protected String customerNote;
072
073 protected Account account;
074 protected Chart chartOfAccounts;
075 protected SubAccount subAccount;
076 protected ObjectCode financialObject;
077 protected SubObjectCode financialSubObject;
078 protected ProjectCode project;
079 protected CustomerInvoiceDocument customerInvoiceDocument;
080 protected AccountsReceivableDocumentHeader accountsReceivableDocumentHeader;
081 protected KualiDecimal invoiceWriteoffAmount;
082
083 public AccountsReceivableDocumentHeader getAccountsReceivableDocumentHeader() {
084 return accountsReceivableDocumentHeader;
085 }
086
087 public void setAccountsReceivableDocumentHeader(AccountsReceivableDocumentHeader accountsReceivableDocumentHeader) {
088 this.accountsReceivableDocumentHeader = accountsReceivableDocumentHeader;
089 }
090
091 public String getChartOfAccountsCode() {
092 return chartOfAccountsCode;
093 }
094
095 public void setChartOfAccountsCode(String chartOfAccountsCode) {
096 this.chartOfAccountsCode = chartOfAccountsCode;
097 }
098
099 public String getAccountNumber() {
100 return accountNumber;
101 }
102
103 public void setAccountNumber(String accountNumber) {
104 this.accountNumber = accountNumber;
105 }
106
107 public String getSubAccountNumber() {
108 return subAccountNumber;
109 }
110
111 public void setSubAccountNumber(String subAccountNumber) {
112 this.subAccountNumber = subAccountNumber;
113 }
114
115 public String getFinancialObjectCode() {
116 return financialObjectCode;
117 }
118
119 public void setFinancialObjectCode(String financialObjectCode) {
120 this.financialObjectCode = financialObjectCode;
121 }
122
123 public String getFinancialSubObjectCode() {
124 return financialSubObjectCode;
125 }
126
127 public void setFinancialSubObjectCode(String financialSubObjectCode) {
128 this.financialSubObjectCode = financialSubObjectCode;
129 }
130
131 public String getProjectCode() {
132 return projectCode;
133 }
134
135 public void setProjectCode(String projectCode) {
136 this.projectCode = projectCode;
137 }
138
139 public String getOrganizationReferenceIdentifier() {
140 return organizationReferenceIdentifier;
141 }
142
143 public void setOrganizationReferenceIdentifier(String organizationReferenceIdentifier) {
144 this.organizationReferenceIdentifier = organizationReferenceIdentifier;
145 }
146
147 public String getFinancialDocumentReferenceInvoiceNumber() {
148 return financialDocumentReferenceInvoiceNumber;
149 }
150
151 public void setFinancialDocumentReferenceInvoiceNumber(String financialDocumentReferenceInvoiceNumber) {
152 this.financialDocumentReferenceInvoiceNumber = financialDocumentReferenceInvoiceNumber;
153 }
154
155 public Account getAccount() {
156 return account;
157 }
158
159 public void setAccount(Account account) {
160 this.account = account;
161 }
162
163 public Chart getChartOfAccounts() {
164 return chartOfAccounts;
165 }
166
167 public void setChartOfAccounts(Chart chartOfAccounts) {
168 this.chartOfAccounts = chartOfAccounts;
169 }
170
171 public SubAccount getSubAccount() {
172 return subAccount;
173 }
174
175 public void setSubAccount(SubAccount subAccount) {
176 this.subAccount = subAccount;
177 }
178
179 public ObjectCode getFinancialObject() {
180 return financialObject;
181 }
182
183 public void setFinancialObject(ObjectCode financialObject) {
184 this.financialObject = financialObject;
185 }
186
187 public SubObjectCode getFinancialSubObject() {
188 return financialSubObject;
189 }
190
191 public void setFinancialSubObject(SubObjectCode financialSubObject) {
192 this.financialSubObject = financialSubObject;
193 }
194
195 public ProjectCode getProject() {
196 return project;
197 }
198
199 public void setProject(ProjectCode project) {
200 this.project = project;
201 }
202
203 public CustomerInvoiceDocument getCustomerInvoiceDocument() {
204 if (ObjectUtils.isNull(customerInvoiceDocument) && StringUtils.isNotEmpty(financialDocumentReferenceInvoiceNumber)) {
205 refreshReferenceObject("customerInvoiceDocument");
206 }
207
208 return customerInvoiceDocument;
209 }
210
211 public void setCustomerInvoiceDocument(CustomerInvoiceDocument customerInvoiceDocument) {
212 this.customerInvoiceDocument = customerInvoiceDocument;
213 }
214
215 /**
216 * This method returns all the applicable invoice details for writeoff. This method also sets the writeoff document number on
217 * each of the invoice details for making retrieval of the actual writeoff amount easier.
218 *
219 * @return
220 */
221 public List<CustomerInvoiceDetail> getCustomerInvoiceDetailsForWriteoff() {
222 List<CustomerInvoiceDetail> customerInvoiceDetailsForWriteoff = new TypedArrayList(CustomerInvoiceDetail.class);
223 for (CustomerInvoiceDetail customerInvoiceDetail : getCustomerInvoiceDocument().getCustomerInvoiceDetailsWithoutDiscounts()) {
224 customerInvoiceDetail.setCustomerInvoiceWriteoffDocumentNumber(this.documentNumber);
225 customerInvoiceDetailsForWriteoff.add(customerInvoiceDetail);
226 }
227
228 return customerInvoiceDetailsForWriteoff;
229 }
230
231 /**
232 * This method returns the total amount to be written off
233 *
234 * @return
235 */
236 public KualiDecimal getInvoiceWriteoffAmount() {
237 // only pull the invoice open amount as the invoice writeoff amount while the doc
238 // is in play. once its been approved, rely on the amount stored in the db.
239 if (!KFSConstants.DocumentStatusCodes.APPROVED.equals(getDocumentHeader().getFinancialDocumentStatusCode())) {
240 invoiceWriteoffAmount = customerInvoiceDocument.getOpenAmount();
241 }
242 return invoiceWriteoffAmount;
243 }
244
245 public void setInvoiceWriteoffAmount(KualiDecimal invoiceWriteoffAmount) {
246 this.invoiceWriteoffAmount = invoiceWriteoffAmount;
247 }
248
249 public String getStatusCode() {
250 return statusCode;
251 }
252
253 public void setStatusCode(String statusCode) {
254 this.statusCode = statusCode;
255 }
256
257 /**
258 * Initializes the values for a new document.
259 */
260 public void initiateDocument() {
261 setStatusCode(ArConstants.CustomerInvoiceWriteoffStatuses.INITIATE);
262 }
263
264 /**
265 * Clear out the initially populated fields.
266 */
267 public void clearInitFields() {
268 setFinancialDocumentReferenceInvoiceNumber(null);
269 }
270
271 @Override
272 public List<Long> getWorkflowEngineDocumentIdsToLock() {
273 if (StringUtils.isNotBlank(getFinancialDocumentReferenceInvoiceNumber())) {
274 List<Long> documentIds = new ArrayList<Long>();
275 documentIds.add(new Long(getFinancialDocumentReferenceInvoiceNumber()));
276 return documentIds;
277 }
278 return null;
279
280 }
281
282 /**
283 * When document is processed do the following: 1) Apply amounts to writeoff invoice 2) Mark off invoice indiciator
284 *
285 * @see org.kuali.kfs.sys.document.GeneralLedgerPostingDocumentBase#doRouteStatusChange()
286 */
287 @Override
288 public void doRouteStatusChange(DocumentRouteStatusChangeDTO statusChangeEvent) {
289 super.doRouteStatusChange(statusChangeEvent);
290 if (getDocumentHeader().getWorkflowDocument().stateIsProcessed()) {
291 CustomerInvoiceWriteoffDocumentService writeoffService = SpringContext.getBean(CustomerInvoiceWriteoffDocumentService.class);
292 writeoffService.completeWriteoffProcess(this);
293 }
294 }
295
296 /**
297 * do all the calculations before the document gets saved gets called for 'Submit', 'Save', and 'Blanket Approved'
298 *
299 * @see org.kuali.rice.kns.document.Document#prepareForSave(org.kuali.rice.kns.rule.event.KualiDocumentEvent)
300 */
301 public void prepareForSave(KualiDocumentEvent event) {
302 // generate GLPEs
303 if (!SpringContext.getBean(GeneralLedgerPendingEntryService.class).generateGeneralLedgerPendingEntries(this)) {
304 logErrors();
305 throw new ValidationException("general ledger GLPE generation failed");
306 }
307 super.prepareForSave(event);
308 }
309
310 public boolean generateDocumentGeneralLedgerPendingEntries(GeneralLedgerPendingEntrySequenceHelper sequenceHelper) {
311 return true;
312 }
313
314 protected KualiDecimal getCustomerInvoiceDetailOpenPretaxAmount(CustomerInvoiceDetail customerInvoiceDetail) {
315 String postalCode = SpringContext.getBean(AccountsReceivableTaxService.class).getPostalCodeForTaxation(getCustomerInvoiceDocument());
316 Date dateOfTransaction = getCustomerInvoiceDocument().getBillingDate();
317 KualiDecimal pretaxAmount = SpringContext.getBean(TaxService.class).getPretaxAmount(dateOfTransaction, postalCode, customerInvoiceDetail.getAmountOpen());
318
319 return pretaxAmount;
320 }
321
322 /**
323 * This method creates the following GLPE's for the customer invoice writeoff 1. C Receivable object code with remaining amount
324 * 2. D Writeoff object code (or Writeoff FAU) with remaining amount 3. C Receivable object code for tax on state tax account 4.
325 * D Sales Tax object code for tax on the state tax account 5. C Receivable object code for tax on district tax account 6. D
326 * District tax object code for $1.00 on the district tax account
327 *
328 * @see org.kuali.kfs.service.impl.GenericGeneralLedgerPendingEntryGenerationProcessImpl#processGenerateGeneralLedgerPendingEntries(org.kuali.kfs.sys.document.GeneralLedgerPendingEntrySource,
329 * org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail,
330 * org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper)
331 */
332
333 public boolean generateGeneralLedgerPendingEntries(GeneralLedgerPendingEntrySourceDetail glpeSourceDetail, GeneralLedgerPendingEntrySequenceHelper sequenceHelper) {
334 CustomerInvoiceDetail customerInvoiceDetail = (CustomerInvoiceDetail) glpeSourceDetail;
335
336 // if invoice item open amount <= 0 -> do not generate GLPEs for this glpeSourceDetail
337 if (!customerInvoiceDetail.getAmountOpen().isPositive())
338 return true;
339
340 KualiDecimal amount;
341
342 String receivableOffsetOption = SpringContext.getBean(ParameterService.class).getParameterValue(CustomerInvoiceDocument.class, ArConstants.GLPE_RECEIVABLE_OFFSET_GENERATION_METHOD);
343 boolean hasReceivableClaimOnCashOffset = ArConstants.GLPE_RECEIVABLE_OFFSET_GENERATION_METHOD_FAU.equals(receivableOffsetOption);
344
345 String writeoffOffsetOption = SpringContext.getBean(ParameterService.class).getParameterValue(CustomerInvoiceWriteoffDocument.class, ArConstants.GLPE_WRITEOFF_GENERATION_METHOD);
346 boolean hasWriteoffClaimOnCashOffset = ArConstants.GLPE_WRITEOFF_GENERATION_METHOD_ORG_ACCT_DEFAULT.equals(writeoffOffsetOption);
347
348 String writeoffTaxGenerationOption = SpringContext.getBean(ParameterService.class).getParameterValue(CustomerInvoiceWriteoffDocument.class, ArConstants.ALLOW_SALES_TAX_LIABILITY_ADJUSTMENT_IND);
349 boolean hasWriteoffTaxClaimOnCashOffset = ArConstants.ALLOW_SALES_TAX_LIABILITY_ADJUSTMENT_IND_NO.equals( writeoffTaxGenerationOption );
350
351 boolean hasClaimOnCashOffset = hasReceivableClaimOnCashOffset || hasWriteoffClaimOnCashOffset;
352
353 // if sales tax is enabled generate tax GLPEs
354 if (SpringContext.getBean(AccountsReceivableTaxService.class).isCustomerInvoiceDetailTaxable(getCustomerInvoiceDocument(), customerInvoiceDetail)) {
355 amount = getCustomerInvoiceDetailOpenPretaxAmount(customerInvoiceDetail);
356 addReceivableGLPEs(sequenceHelper, glpeSourceDetail, hasClaimOnCashOffset, amount);
357 sequenceHelper.increment();
358 addWriteoffGLPEs(sequenceHelper, glpeSourceDetail, hasClaimOnCashOffset, amount);
359 addSalesTaxGLPEs( sequenceHelper, glpeSourceDetail, hasWriteoffTaxClaimOnCashOffset, amount);
360 }
361 else {
362 amount = customerInvoiceDetail.getAmountOpen();
363 addReceivableGLPEs(sequenceHelper, glpeSourceDetail, hasClaimOnCashOffset, amount);
364 sequenceHelper.increment();
365 addWriteoffGLPEs(sequenceHelper, glpeSourceDetail, hasClaimOnCashOffset, amount);
366 }
367 return true;
368 }
369
370 /**
371 * This method creates the receivable GLPEs for customer invoice details using the remaining amount
372 *
373 * @param poster
374 * @param sequenceHelper
375 * @param postable
376 * @param explicitEntry
377 */
378 protected void addReceivableGLPEs(GeneralLedgerPendingEntrySequenceHelper sequenceHelper, GeneralLedgerPendingEntrySourceDetail glpeSourceDetail, boolean hasClaimOnCashOffset, KualiDecimal amount) {
379
380 CustomerInvoiceDetail customerInvoiceDetail = (CustomerInvoiceDetail) glpeSourceDetail;
381 ReceivableCustomerInvoiceDetail receivableCustomerInvoiceDetail = new ReceivableCustomerInvoiceDetail(customerInvoiceDetail, getCustomerInvoiceDocument());
382 boolean isDebit = false;
383
384 CustomerInvoiceGLPEService service = SpringContext.getBean(CustomerInvoiceGLPEService.class);
385 service.createAndAddGenericInvoiceRelatedGLPEs(this, receivableCustomerInvoiceDetail, sequenceHelper, isDebit, hasClaimOnCashOffset, amount);
386 }
387
388 /**
389 * This method adds writeoff GLPE's for the customer invoice details using the remaining amount.
390 *
391 * @param poster
392 * @param sequenceHelper
393 * @param postable
394 * @param explicitEntry
395 */
396 protected void addWriteoffGLPEs(GeneralLedgerPendingEntrySequenceHelper sequenceHelper, GeneralLedgerPendingEntrySourceDetail glpeSourceDetail, boolean hasClaimOnCashOffset, KualiDecimal amount) {
397
398 CustomerInvoiceDetail customerInvoiceDetail = (CustomerInvoiceDetail) glpeSourceDetail;
399 WriteoffCustomerInvoiceDetail writeoffCustomerInvoiceDetail = new WriteoffCustomerInvoiceDetail(customerInvoiceDetail, this);
400 boolean isDebit = true;
401
402 CustomerInvoiceGLPEService service = SpringContext.getBean(CustomerInvoiceGLPEService.class);
403 service.createAndAddGenericInvoiceRelatedGLPEs(this, writeoffCustomerInvoiceDetail, sequenceHelper, isDebit, hasClaimOnCashOffset, amount);
404 }
405
406 protected void addSalesTaxGLPEs(GeneralLedgerPendingEntrySequenceHelper sequenceHelper, GeneralLedgerPendingEntrySourceDetail glpeSourceDetail, boolean hasWriteoffTaxClaimOnCashOffset, KualiDecimal amount){
407 CustomerInvoiceDetail customerInvoiceDetail = (CustomerInvoiceDetail) glpeSourceDetail;
408 WriteoffCustomerInvoiceDetail writeoffCustomerInvoiceDetail = new WriteoffCustomerInvoiceDetail(customerInvoiceDetail, this);
409
410 boolean isDebit = true;
411
412 String postalCode = SpringContext.getBean(AccountsReceivableTaxService.class).getPostalCodeForTaxation(getCustomerInvoiceDocument());
413 Date dateOfTransaction = getCustomerInvoiceDocument().getBillingDate();
414
415 List<TaxDetail> salesTaxDetails = SpringContext.getBean(TaxService.class).getSalesTaxDetails(dateOfTransaction, postalCode, amount);
416
417 CustomerInvoiceGLPEService service = SpringContext.getBean(CustomerInvoiceGLPEService.class);
418 SalesTaxCustomerInvoiceDetail salesTaxCustomerInvoiceDetail;
419 ReceivableCustomerInvoiceDetail receivableCustomerInvoiceDetail;
420 WriteoffTaxCustomerInvoiceDetail writeoffTaxCustomerInvoiceDetail;
421 for (TaxDetail salesTaxDetail : salesTaxDetails) {
422
423 salesTaxCustomerInvoiceDetail = new SalesTaxCustomerInvoiceDetail(salesTaxDetail, customerInvoiceDetail);
424 receivableCustomerInvoiceDetail = new ReceivableCustomerInvoiceDetail(salesTaxCustomerInvoiceDetail, getCustomerInvoiceDocument());
425 writeoffTaxCustomerInvoiceDetail = new WriteoffTaxCustomerInvoiceDetail(salesTaxCustomerInvoiceDetail, this);
426
427 sequenceHelper.increment();
428 service.createAndAddGenericInvoiceRelatedGLPEs(this, receivableCustomerInvoiceDetail, sequenceHelper, !isDebit, hasWriteoffTaxClaimOnCashOffset, salesTaxDetail.getTaxAmount());
429
430 sequenceHelper.increment();
431 service.createAndAddGenericInvoiceRelatedGLPEs(this, writeoffTaxCustomerInvoiceDetail, sequenceHelper, isDebit, hasWriteoffTaxClaimOnCashOffset, salesTaxDetail.getTaxAmount());
432 }
433 }
434
435 public KualiDecimal getGeneralLedgerPendingEntryAmountForDetail(GeneralLedgerPendingEntrySourceDetail glpeSourceDetail) {
436 // TODO Auto-generated method stub
437 return null;
438 }
439
440 public List<GeneralLedgerPendingEntrySourceDetail> getGeneralLedgerPendingEntrySourceDetails() {
441 List<GeneralLedgerPendingEntrySourceDetail> generalLedgerPendingEntrySourceDetails = new ArrayList<GeneralLedgerPendingEntrySourceDetail>();
442 generalLedgerPendingEntrySourceDetails.addAll(getCustomerInvoiceDocument().getCustomerInvoiceDetailsWithoutDiscounts());
443 return generalLedgerPendingEntrySourceDetails;
444
445 }
446
447 public boolean isDebit(GeneralLedgerPendingEntrySourceDetail postable) {
448 // TODO Auto-generated method stub
449 return false;
450 }
451
452 public KualiDecimal getTotalDollarAmount() {
453 return getInvoiceWriteoffAmount();
454 }
455
456 /**
457 * Gets the customerNote attribute.
458 *
459 * @return Returns the customerNote.
460 */
461 public String getCustomerNote() {
462 /*
463 * ArrayList boNotes = (ArrayList) this.getCustomerInvoiceDocument().getCustomer().getBoNotes(); if (boNotes.size() > 0)
464 * customerNote = boNotes.toString(); else customerNote = "";
465 */
466 return customerNote;
467 }
468
469 /**
470 * Sets the customerNote attribute value.
471 *
472 * @param customerNote The customerNote to set.
473 */
474 public void setCustomerNote(String customerNote) {
475 this.customerNote = customerNote;
476 }
477
478 public void populateCustomerNote() {
479 customerNote = "";
480 ArrayList boNotes = (ArrayList) this.getCustomerInvoiceDocument().getCustomer().getBoNotes();
481 if (boNotes.size() > 0) {
482 for (int i = 0; i < boNotes.size(); i++)
483 customerNote += ((Note) boNotes.get(i)).getNoteText() + " ";
484 customerNote.trim();
485 }
486 }
487
488 /**
489 * Answers true when invoice write off amount is greater than default approved amount ($50???)
490 *
491 * @see org.kuali.kfs.sys.document.FinancialSystemTransactionalDocumentBase#answerSplitNodeQuestion(java.lang.String)
492 */
493 @Override
494 public boolean answerSplitNodeQuestion(String nodeName) throws UnsupportedOperationException {
495 if (REQUIRES_APPROVAL_NODE.equals(nodeName)) {
496
497 // grab the approval threshold from the param service
498 ParameterService paramService = SpringContext.getBean(ParameterService.class);
499 KualiDecimal approvalThreshold = new KualiDecimal(paramService.getParameterValue(CustomerInvoiceWriteoffDocument.class, ArConstants.WRITEOFF_APPROVAL_THRESHOLD));
500
501 return (approvalThreshold.isLessThan(getInvoiceWriteoffAmount()));
502 }
503 throw new UnsupportedOperationException("answerSplitNode('" + nodeName + "') called but no handler for this nodeName present.");
504 }
505
506
507 }