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.endow.document.service.impl; 017 018 import java.math.BigDecimal; 019 import java.util.List; 020 021 import org.kuali.kfs.module.endow.businessobject.EndowmentSourceTransactionLine; 022 import org.kuali.kfs.module.endow.businessobject.EndowmentTransactionLine; 023 import org.kuali.kfs.module.endow.businessobject.EndowmentTransactionSecurity; 024 import org.kuali.kfs.module.endow.businessobject.EndowmentTransactionTaxLotLine; 025 import org.kuali.kfs.module.endow.businessobject.HoldingTaxLot; 026 import org.kuali.kfs.module.endow.businessobject.Security; 027 import org.kuali.kfs.module.endow.document.CorporateReorganizationDocument; 028 import org.kuali.kfs.module.endow.document.SecurityTransferDocument; 029 import org.kuali.kfs.module.endow.document.service.HoldingTaxLotService; 030 import org.kuali.kfs.module.endow.document.service.KEMService; 031 import org.kuali.kfs.module.endow.document.service.SecurityService; 032 import org.kuali.kfs.module.endow.document.service.UpdateSecurityTransferTargetTaxLotsService; 033 import org.kuali.kfs.module.endow.util.KEMCalculationRoundingHelper; 034 import org.kuali.rice.kns.util.KualiDecimal; 035 import org.kuali.rice.kns.util.ObjectUtils; 036 037 public class UpdateSecurityTransferTargetTaxLotsServiceImpl implements UpdateSecurityTransferTargetTaxLotsService { 038 039 private HoldingTaxLotService taxLotService; 040 private SecurityService securityService; 041 private KEMService kemService; 042 043 public void updateTransactionLineTaxLots(CorporateReorganizationDocument document, EndowmentTransactionLine transLine) { 044 // calculate the transaction line amount 045 046 //if there are no source transaction lines, do not process anything. 047 if (document.getSourceTransactionLines().size() > 0) { 048 // get the source transaction line and compute the unit value by dividing the source amount by the source number of units 049 EndowmentSourceTransactionLine sourceTransactionLine = (EndowmentSourceTransactionLine) document.getSourceTransactionLines().get(0); 050 EndowmentTransactionSecurity endowmentTransactionSecurity = document.getSourceTransactionSecurity(); 051 052 if (ObjectUtils.isNotNull(sourceTransactionLine)) { 053 BigDecimal sourceAmount = BigDecimal.ZERO; 054 if (sourceTransactionLine.getTransactionAmount() != null) { 055 sourceAmount = sourceTransactionLine.getTransactionAmount().bigDecimalValue(); 056 } 057 BigDecimal sourceUnits = BigDecimal.ZERO; 058 if (sourceTransactionLine.getTransactionUnits() != null) { 059 sourceUnits = sourceTransactionLine.getTransactionUnits().bigDecimalValue(); 060 } 061 062 BigDecimal unitValue = BigDecimal.ZERO; 063 if (sourceUnits != null && sourceUnits.compareTo(BigDecimal.ZERO) != 0) { 064 unitValue = KEMCalculationRoundingHelper.divide(sourceAmount, sourceUnits, 5); 065 } 066 067 BigDecimal targetAmount = KEMCalculationRoundingHelper.multiply(transLine.getTransactionUnits().bigDecimalValue(), unitValue, 2); 068 transLine.setTransactionAmount(new KualiDecimal(sourceAmount)); 069 070 EndowmentTransactionTaxLotLine taxLotLine = null; 071 boolean newLine = false; 072 073 if (transLine.getTaxLotLines() != null && transLine.getTaxLotLines().size() > 0) { 074 // there is only one tax lot line per each transaction line 075 taxLotLine = transLine.getTaxLotLines().get(0); 076 } 077 else { 078 // create and set a new tax lot line 079 newLine = true; 080 taxLotLine = new EndowmentTransactionTaxLotLine(); 081 taxLotLine.setDocumentNumber(document.getDocumentNumber()); 082 taxLotLine.setDocumentLineNumber(transLine.getTransactionLineNumber()); 083 } 084 085 Security security = endowmentTransactionSecurity.getSecurity(); 086 String securityId = endowmentTransactionSecurity.getSecurityID(); 087 String regCode = endowmentTransactionSecurity.getRegistrationCode(); 088 String ipIndicator = transLine.getTransactionIPIndicatorCode(); 089 String kemid = transLine.getKemid(); 090 091 // Step 6. 092 if (!security.getClassCode().isTaxLotIndicator()) { 093 taxLotLine.setTransactionHoldingLotNumber(1); 094 HoldingTaxLot taxLot = taxLotService.getByPrimaryKey(kemid, securityId, regCode, 1, ipIndicator); 095 if (taxLot != null) { 096 if (taxLot.getUnits().compareTo(BigDecimal.ZERO) == 0 && taxLot.getCost().compareTo(BigDecimal.ZERO) == 0) { 097 taxLotLine.setLotAcquiredDate(kemService.getCurrentProcessDate()); 098 } 099 else { 100 taxLotLine.setLotAcquiredDate(taxLot.getAcquiredDate()); 101 } 102 } 103 else { 104 taxLotLine.setLotAcquiredDate(kemService.getCurrentProcessDate()); 105 } 106 // Step 7. 107 } 108 else { 109 List<HoldingTaxLot> taxLots = taxLotService.getAllTaxLots(kemid, securityId, regCode, ipIndicator); 110 int lotNumber = 1; 111 for (HoldingTaxLot taxLot : taxLots) { 112 if (lotNumber < taxLot.getLotNumber().intValue()) { 113 lotNumber = taxLot.getLotNumber().intValue(); 114 } 115 } 116 taxLotLine.setTransactionHoldingLotNumber(Integer.valueOf(lotNumber)); 117 taxLotLine.setLotAcquiredDate(kemService.getCurrentProcessDate()); 118 } 119 120 taxLotLine.setLotUnits(transLine.getTransactionUnits().bigDecimalValue()); 121 taxLotLine.setLotHoldingCost(sourceAmount); 122 taxLotLine.setKemid(kemid); 123 taxLotLine.setSecurityID(securityId); 124 taxLotLine.setRegistrationCode(regCode); 125 taxLotLine.setIpIndicator(ipIndicator); 126 127 // set the tax lot acquired date 128 setTaxLotAcquiredDate(taxLotLine, document, transLine); 129 130 // set the new tax lot indicator 131 setNewLotIndicator(taxLotLine, document); 132 133 if (newLine) { 134 transLine.getTaxLotLines().add(taxLotLine); 135 } 136 } 137 } 138 } 139 140 /** 141 * @see org.kuali.kfs.module.endow.document.service.UpdateSecurityTransferTargetTaxLotsService#updateTransactionLineTaxLots(org.kuali.kfs.module.endow.document.SecurityTransferDocument, 142 * org.kuali.kfs.module.endow.businessobject.EndowmentTransactionLine) 143 */ 144 public void updateTransactionLineTaxLots(SecurityTransferDocument document, EndowmentTransactionLine transLine) { 145 // calculate the transaction line amount 146 147 //if there are no source transaction lines, do not process anything. 148 if (document.getSourceTransactionLines().size() > 0) { 149 // get the source transaction line and compute the unit value by dividing the source amount by the source number of units 150 EndowmentSourceTransactionLine sourceTransactionLine = (EndowmentSourceTransactionLine) document.getSourceTransactionLines().get(0); 151 EndowmentTransactionSecurity endowmentTransactionSecurity = document.getSourceTransactionSecurity(); 152 153 if (ObjectUtils.isNotNull(sourceTransactionLine)) { 154 BigDecimal sourceAmount = BigDecimal.ZERO; 155 if (sourceTransactionLine.getTransactionAmount() != null) { 156 sourceAmount = sourceTransactionLine.getTransactionAmount().bigDecimalValue(); 157 } 158 BigDecimal sourceUnits = BigDecimal.ZERO; 159 if (sourceTransactionLine.getTransactionUnits() != null) { 160 sourceUnits = sourceTransactionLine.getTransactionUnits().bigDecimalValue(); 161 } 162 163 BigDecimal unitValue = BigDecimal.ZERO; 164 if (sourceUnits != null && sourceUnits.compareTo(BigDecimal.ZERO) != 0) { 165 unitValue = KEMCalculationRoundingHelper.divide(sourceAmount, sourceUnits, 5); 166 } 167 168 BigDecimal targetAmount = KEMCalculationRoundingHelper.multiply(transLine.getTransactionUnits().bigDecimalValue(), unitValue, 2); 169 // set transaction line target amount 170 transLine.setTransactionAmount(new KualiDecimal(targetAmount)); 171 172 EndowmentTransactionTaxLotLine taxLotLine = null; 173 boolean newLine = false; 174 175 if (transLine.getTaxLotLines() != null && transLine.getTaxLotLines().size() > 0) { 176 // there is only one tax lot line per each transaction line 177 taxLotLine = transLine.getTaxLotLines().get(0); 178 } 179 else { 180 // create and set a new tax lot line 181 newLine = true; 182 taxLotLine = new EndowmentTransactionTaxLotLine(); 183 taxLotLine.setDocumentNumber(document.getDocumentNumber()); 184 taxLotLine.setDocumentLineNumber(transLine.getTransactionLineNumber()); 185 taxLotLine.setTransactionHoldingLotNumber(1); 186 } 187 188 taxLotLine.setKemid(transLine.getKemid()); 189 taxLotLine.setSecurityID(endowmentTransactionSecurity.getSecurityID()); 190 taxLotLine.setRegistrationCode(endowmentTransactionSecurity.getRegistrationCode()); 191 taxLotLine.setIpIndicator(transLine.getTransactionIPIndicatorCode()); 192 taxLotLine.setLotUnits(transLine.getTransactionUnits().bigDecimalValue()); 193 taxLotLine.setLotHoldingCost(targetAmount); 194 195 // set the tax lot acquired date 196 setTaxLotAcquiredDate(taxLotLine, document, transLine); 197 198 // set the new tax lot indicator 199 setNewLotIndicator(taxLotLine, document); 200 201 if (newLine) { 202 transLine.getTaxLotLines().add(taxLotLine); 203 } 204 205 } 206 } 207 208 } 209 210 /** 211 * Sets the Acquired date for the given tax lot line. If the tax lot indicator for the security (END_TRAN_SEC_T: 212 * SEC_TAX_LOT_IND) is No then for the lot acquired date - LOT_AQ_DATE - Search the END_HLDG_TAX_LOT_T records by KEMID by 213 * SEC_ID by REGIS_CD by HLDG_IP_IND [where HLDG_IP_IND is equal to END_TRAN_LN_T: TRAN_IP_IND_CD] by HLDG_LOT_NBR where 214 * HLDG_LOT_NBR is equal to 1 and return the HLDG_ACQD_DT: - If a lot exists for the security in END_HLDG_TAX_LOT_T, but the 215 * HLDG_UNITS and HLDG_COST are zero, insert the current date (System or Process) in LOT_ACQD_DT. - IF no lot exists for the 216 * security, then insert the current date (System or Process) in LOT_ACQD_DT. If the tax lot indicator for the security 217 * (END_TRAN_SEC_T: SEC_TAX_LOT_IND) is Yes: - LOT_AQ_DATE - insert the current date (System or Process) in this field 218 * 219 * @param taxLotLine the tax lot line for which to set the acquired date 220 * @param aiDocument the Asset Increase Document the tax lot line belongs to 221 * @param transLine the transaction line the tax lot is related to 222 */ 223 private void setTaxLotAcquiredDate(EndowmentTransactionTaxLotLine taxLotLine, SecurityTransferDocument document, EndowmentTransactionLine transLine) { 224 EndowmentTransactionSecurity endowmentTransactionSecurity = document.getSourceTransactionSecurity(); 225 226 Security security = securityService.getByPrimaryKey(endowmentTransactionSecurity.getSecurityID()); 227 228 // if security tax lot indicator is 'No' and a tax lot exists for the kemid, security, registration code and income 229 // principal indicator - set the lot acquired date to be the tax lot holding acquired date if units and cost is not zero; 230 // otherwise set the date to be the current date 231 if (ObjectUtils.isNotNull(security) && !security.getClassCode().isTaxLotIndicator()) { 232 HoldingTaxLot holdingTaxLot = taxLotService.getByPrimaryKey(transLine.getKemid(), endowmentTransactionSecurity.getSecurityID(), endowmentTransactionSecurity.getRegistrationCode(), 1, transLine.getTransactionIPIndicatorCode()); 233 if (ObjectUtils.isNotNull(holdingTaxLot)) { 234 if (holdingTaxLot.getUnits().equals(KualiDecimal.ZERO) && holdingTaxLot.getCost().equals(KualiDecimal.ZERO)) { 235 taxLotLine.setLotAcquiredDate(kemService.getCurrentDate()); 236 } 237 else { 238 taxLotLine.setLotAcquiredDate(holdingTaxLot.getAcquiredDate()); 239 } 240 } 241 else { 242 taxLotLine.setLotAcquiredDate(kemService.getCurrentDate()); 243 } 244 245 } 246 // if security tax lot indicator is 'Yes' set the lot acquired date to be the current date 247 else { 248 taxLotLine.setLotAcquiredDate(kemService.getCurrentDate()); 249 } 250 } 251 252 /** 253 * Sets the new lot indicator for the tax lot: -- if the security tax lot indicator is No then I think we should set the field 254 * to 'N'. When the batch process runs we might need to create a new entry on the holding tax lot table in case no entry is 255 * found for the given KEMID, security ID, registration code, holding ip indicator, and holding lot number = 1. In case there is 256 * an entry we will just update that one; -- if the security tax lot is Yes then the field should be set to 'Y'.We are always 257 * creating a new field with the lot number being the next sequential lot number. 258 * 259 * @param taxLotLine 260 * @param document 261 */ 262 private void setNewLotIndicator(EndowmentTransactionTaxLotLine taxLotLine, SecurityTransferDocument document) { 263 EndowmentTransactionSecurity endowmentTransactionSecurity = document.getSourceTransactionSecurity(); 264 Security security = securityService.getByPrimaryKey(endowmentTransactionSecurity.getSecurityID()); 265 266 if (ObjectUtils.isNotNull(security)) { 267 // if the security tax lot indicator is No then I think we should set the field to 'N'. When the batch process runs we 268 // might need to create a new entry on the holding tax lot table in case no entry is found for the given KEMID, security 269 // ID, registration code, holding ip indicator, and holding lot number = 1. In case there is an entry we will just 270 // update that one 271 if (!security.getClassCode().isTaxLotIndicator()) { 272 273 taxLotLine.setNewLotIndicator(false); 274 } 275 // if the security tax lot is Yes then the field should be set to 'Y'.We are always creating a new field with the lot 276 // number being the next sequential lot number. 277 else { 278 taxLotLine.setNewLotIndicator(true); 279 } 280 } 281 } 282 283 private void setTaxLotAcquiredDate(EndowmentTransactionTaxLotLine taxLotLine, CorporateReorganizationDocument document, EndowmentTransactionLine transLine) { 284 EndowmentTransactionSecurity endowmentTransactionSecurity = document.getSourceTransactionSecurity(); 285 286 Security security = securityService.getByPrimaryKey(endowmentTransactionSecurity.getSecurityID()); 287 288 // if security tax lot indicator is 'No' and a tax lot exists for the kemid, security, registration code and income 289 // principal indicator - set the lot acquired date to be the tax lot holding acquired date if units and cost is not zero; 290 // otherwise set the date to be the current date 291 if (ObjectUtils.isNotNull(security) && !security.getClassCode().isTaxLotIndicator()) { 292 HoldingTaxLot holdingTaxLot = taxLotService.getByPrimaryKey(transLine.getKemid(), endowmentTransactionSecurity.getSecurityID(), endowmentTransactionSecurity.getRegistrationCode(), 1, transLine.getTransactionIPIndicatorCode()); 293 if (ObjectUtils.isNotNull(holdingTaxLot)) { 294 if (holdingTaxLot.getUnits().equals(KualiDecimal.ZERO) && holdingTaxLot.getCost().equals(KualiDecimal.ZERO)) { 295 taxLotLine.setLotAcquiredDate(kemService.getCurrentDate()); 296 } 297 else { 298 taxLotLine.setLotAcquiredDate(holdingTaxLot.getAcquiredDate()); 299 } 300 } 301 else { 302 taxLotLine.setLotAcquiredDate(kemService.getCurrentDate()); 303 } 304 305 } 306 // if security tax lot indicator is 'Yes' set the lot acquired date to be the current date 307 else { 308 taxLotLine.setLotAcquiredDate(kemService.getCurrentDate()); 309 } 310 } 311 312 private void setNewLotIndicator(EndowmentTransactionTaxLotLine taxLotLine, CorporateReorganizationDocument document) { 313 EndowmentTransactionSecurity endowmentTransactionSecurity = document.getSourceTransactionSecurity(); 314 Security security = securityService.getByPrimaryKey(endowmentTransactionSecurity.getSecurityID()); 315 316 if (ObjectUtils.isNotNull(security)) { 317 // if the security tax lot indicator is No then I think we should set the field to 'N'. When the batch process runs we 318 // might need to create a new entry on the holding tax lot table in case no entry is found for the given KEMID, security 319 // ID, registration code, holding ip indicator, and holding lot number = 1. In case there is an entry we will just 320 // update that one 321 if (!security.getClassCode().isTaxLotIndicator()) { 322 323 taxLotLine.setNewLotIndicator(false); 324 } 325 // if the security tax lot is Yes then the field should be set to 'Y'.We are always creating a new field with the lot 326 // number being the next sequential lot number. 327 else { 328 taxLotLine.setNewLotIndicator(true); 329 } 330 } 331 } 332 333 /** 334 * Gets the taxLotService. 335 * 336 * @return taxLotService 337 */ 338 protected HoldingTaxLotService getTaxLotService() { 339 return taxLotService; 340 } 341 342 /** 343 * Sets the taxLotService. 344 * 345 * @param taxLotService 346 */ 347 public void setTaxLotService(HoldingTaxLotService taxLotService) { 348 this.taxLotService = taxLotService; 349 } 350 351 /** 352 * Gets the securityService. 353 * 354 * @return securityService 355 */ 356 protected SecurityService getSecurityService() { 357 return securityService; 358 } 359 360 /** 361 * Sets the securityService. 362 * 363 * @param securityService 364 */ 365 public void setSecurityService(SecurityService securityService) { 366 this.securityService = securityService; 367 } 368 369 /** 370 * Gets the kemService. 371 * 372 * @return kemService 373 */ 374 protected KEMService getKemService() { 375 return kemService; 376 } 377 378 /** 379 * Sets the kemService. 380 * 381 * @param kemService 382 */ 383 public void setKemService(KEMService kemService) { 384 this.kemService = kemService; 385 } 386 }