/** * Service Method to create a new current tax lot balance record and copy HoldingTaxLot record to * it * * @param holdingTaxLot * @return currentTaxLotBalance */ public CurrentTaxLotBalance copyHoldingTaxLotToCurrentTaxLotBalance(HoldingTaxLot holdingTaxLot) { CurrentTaxLotBalance currentTaxLotBalance = new CurrentTaxLotBalance(); currentTaxLotBalance.setKemid(holdingTaxLot.getKemid()); currentTaxLotBalance.setSecurityId(holdingTaxLot.getSecurityId()); currentTaxLotBalance.setRegistrationCode(holdingTaxLot.getRegistrationCode()); currentTaxLotBalance.setLotNumber(holdingTaxLot.getLotNumber()); currentTaxLotBalance.setIncomePrincipalIndicator(holdingTaxLot.getIncomePrincipalIndicator()); currentTaxLotBalance.setUnits(holdingTaxLot.getUnits()); currentTaxLotBalance.setCost(holdingTaxLot.getCost()); currentTaxLotBalance.setAcquiredDate(holdingTaxLot.getAcquiredDate()); currentTaxLotBalance.setPriorAccrual(holdingTaxLot.getPriorAccrual()); currentTaxLotBalance.setCurrentAccrual(holdingTaxLot.getCurrentAccrual()); currentTaxLotBalance.setLastTransactionDate(holdingTaxLot.getLastTransactionDate()); return currentTaxLotBalance; }
/** * Updates the tax lots for the transaction line in the case the transaction sub type is non-cash * and the user entered the transaction amount. This method is specific to the Asset Decrease * document. * * @param isSubTypeCash * @param endowmentTransactionSecurity * @param transLine */ private void updateTaxLotsForSubTypeNonCashAndTransAmtNonZero( boolean isUpdate, EndowmentTransactionSecurity endowmentTransactionSecurity, EndowmentTransactionLine transLine) { BigDecimal transactionUnits = transLine.getTransactionUnits().bigDecimalValue(); BigDecimal totalTaxLotsUnits = BigDecimal.ZERO; BigDecimal transactionAmount = transLine.getTransactionAmount().bigDecimalValue(); BigDecimal perUnitValue = BigDecimal.ZERO; List<HoldingTaxLot> holdingTaxLots = new ArrayList<HoldingTaxLot>(); Map<Integer, HoldingTaxLot> lotsMap = new HashMap<Integer, HoldingTaxLot>(); if (!isUpdate) { transLine.getTaxLotLines().clear(); holdingTaxLots = taxLotService.getAllTaxLots( transLine.getKemid(), endowmentTransactionSecurity.getSecurityID(), endowmentTransactionSecurity.getRegistrationCode(), transLine.getTransactionIPIndicatorCode()); } else { List<EndowmentTransactionTaxLotLine> existingTransactionLines = transLine.getTaxLotLines(); for (EndowmentTransactionTaxLotLine endowmentTransactionTaxLotLine : existingTransactionLines) { HoldingTaxLot holdingTaxLot = taxLotService.getByPrimaryKey( transLine.getKemid(), endowmentTransactionSecurity.getSecurityID(), endowmentTransactionSecurity.getRegistrationCode(), endowmentTransactionTaxLotLine.getTransactionHoldingLotNumber(), transLine.getTransactionIPIndicatorCode()); if (ObjectUtils.isNotNull(holdingTaxLot)) { holdingTaxLots.add(holdingTaxLot); } } transLine.getTaxLotLines().clear(); } Map<KualiInteger, EndowmentTransactionTaxLotLine> decreaseHoldingTaxLots = new HashMap<KualiInteger, EndowmentTransactionTaxLotLine>(); if (holdingTaxLots != null && holdingTaxLots.size() > 0) { boolean keepIntegers = true; // compute the total number of units for tax lots for (HoldingTaxLot holdingTaxLot : holdingTaxLots) { totalTaxLotsUnits = totalTaxLotsUnits.add(holdingTaxLot.getUnits()); // 3. Calculate the number of units to be transacted in each lot // check if percentage and tax lot units are integers BigDecimal lotUnits = BigDecimal.ZERO; try { int lotUnitsInt = holdingTaxLot.getUnits().intValueExact(); } catch (ArithmeticException ex) { keepIntegers = false; } } for (HoldingTaxLot holdingTaxLot : holdingTaxLots) { EndowmentTransactionTaxLotLine taxLotLine = new EndowmentTransactionTaxLotLine(); taxLotLine.setDocumentLineNumber(transLine.getTransactionLineNumber()); BigDecimal lotUnits = BigDecimal.ZERO; // 2. Calculate percentage each lot holds out of the total units BigDecimal percentage = KEMCalculationRoundingHelper.divide(holdingTaxLot.getUnits(), totalTaxLotsUnits, 5); lotUnits = KEMCalculationRoundingHelper.multiply( percentage, transLine.getTransactionUnits().bigDecimalValue(), 5); // IF all original units per lot are integers (no decimal values), the result is rounded to // the nearest // integer and stored with the five decimals as zero. If the original units are not all // integers, then the // value is rounded to five decimals and stored as the five decimal values. if (keepIntegers) { lotUnits = lotUnits.setScale(0, BigDecimal.ROUND_HALF_UP); lotUnits = lotUnits.setScale(5); } taxLotLine.setLotUnits(lotUnits); // 6. Calculate holding cost BigDecimal holdingCost = KEMCalculationRoundingHelper.multiply(percentage, transactionAmount, 2); taxLotLine.setLotHoldingCost(holdingCost); // set tax lot line lot number and acquired date taxLotLine.setTransactionHoldingLotNumber(holdingTaxLot.getLotNumber().intValue()); taxLotLine.setKemid(transLine.getKemid()); taxLotLine.setSecurityID(holdingTaxLot.getSecurityId()); taxLotLine.setRegistrationCode(holdingTaxLot.getRegistrationCode()); taxLotLine.setIpIndicator(holdingTaxLot.getIncomePrincipalIndicator()); taxLotLine.setLotAcquiredDate(holdingTaxLot.getAcquiredDate()); // set the new lot indicator taxLotLine.setNewLotIndicator(false); // add the new tax lot line to the transaction line tax lots addTaxLotLine(transLine, taxLotLine); lotsMap.put(taxLotLine.getTransactionHoldingLotNumber(), holdingTaxLot); } adjustUnitsAndAmountsForNonCashAndTransactionAmtNotZero(transLine); } }
/** * Updates the tax lots for the transaction line in the case the accounting method is FIFO or * LIFO. * * @param isSubTypeCash * @param isFIFO * @param endowmentTransactionSecurity * @param transLine */ private void updateTaxLotsForAccountingMethodFIFOorLIFO( boolean isSubTypeCash, boolean isUpdate, boolean isFIFO, EndowmentTransactionSecurity endowmentTransactionSecurity, EndowmentTransactionLine transLine) { BigDecimal transactionUnits = transLine.getTransactionUnits().bigDecimalValue(); BigDecimal transactionAmount = BigDecimal.ZERO; BigDecimal perUnitVal = BigDecimal.ZERO; List<HoldingTaxLot> holdingTaxLots = new ArrayList<HoldingTaxLot>(); if (!isUpdate) { transLine.getTaxLotLines().clear(); holdingTaxLots = taxLotService.getAllTaxLotsOrderByAcquiredDate( transLine.getKemid(), endowmentTransactionSecurity.getSecurityID(), endowmentTransactionSecurity.getRegistrationCode(), transLine.getTransactionIPIndicatorCode(), isFIFO); } else { List<EndowmentTransactionTaxLotLine> existingTransactionLines = transLine.getTaxLotLines(); for (EndowmentTransactionTaxLotLine endowmentTransactionTaxLotLine : existingTransactionLines) { HoldingTaxLot holdingTaxLot = taxLotService.getByPrimaryKey( transLine.getKemid(), endowmentTransactionSecurity.getSecurityID(), endowmentTransactionSecurity.getRegistrationCode(), endowmentTransactionTaxLotLine.getTransactionHoldingLotNumber(), transLine.getTransactionIPIndicatorCode()); if (ObjectUtils.isNotNull(holdingTaxLot)) { holdingTaxLots.add(holdingTaxLot); } } transLine.getTaxLotLines().clear(); } Map<KualiInteger, EndowmentTransactionTaxLotLine> decreaseHoldingTaxLots = new HashMap<KualiInteger, EndowmentTransactionTaxLotLine>(); if (isSubTypeCash) { transactionAmount = transLine.getTransactionAmount().bigDecimalValue(); // 1. Compute per unit value perUnitVal = KEMCalculationRoundingHelper.divide(transactionAmount, transactionUnits, 5); } BigDecimal remainingUnits = transactionUnits; if (holdingTaxLots != null && holdingTaxLots.size() > 0) { // compute the total number of units for tax lots for (HoldingTaxLot holdingTaxLot : holdingTaxLots) { EndowmentTransactionTaxLotLine taxLotLine = new EndowmentTransactionTaxLotLine(); taxLotLine.setDocumentLineNumber(transLine.getTransactionLineNumber()); // 2. Set the lot units // if transaction units is greater than the holding tax lot units then take all the holding // tax lot units if (remainingUnits.compareTo(holdingTaxLot.getUnits()) == 1) { taxLotLine.setLotUnits(holdingTaxLot.getUnits()); remainingUnits = remainingUnits.subtract(holdingTaxLot.getUnits()); } // if transaction units is less than the holding tax lot units then take just the remaining // number of units else { taxLotLine.setLotUnits(remainingUnits); remainingUnits = BigDecimal.ZERO; } // 4. Calculate the original unit value: cost/units BigDecimal originalUnitVal = KEMCalculationRoundingHelper.divide( holdingTaxLot.getCost(), holdingTaxLot.getUnits(), 5); // 5. Calculate original cost BigDecimal originalCost = KEMCalculationRoundingHelper.multiply(originalUnitVal, taxLotLine.getLotUnits(), 2); // set the tax lot holding cost taxLotLine.setLotHoldingCost(originalCost); // if sub type cash then the if (isSubTypeCash) { // 3. Calculate the value received for the units sold and round to 2 decimals BigDecimal receivedValue = KEMCalculationRoundingHelper.multiply(perUnitVal, taxLotLine.getLotUnits(), 2); // 6. Calculate the gain or loss calculateGainLoss(holdingTaxLot, taxLotLine, receivedValue, originalCost); } // set the lot number taxLotLine.setTransactionHoldingLotNumber(holdingTaxLot.getLotNumber().intValue()); taxLotLine.setKemid(transLine.getKemid()); taxLotLine.setSecurityID(holdingTaxLot.getSecurityId()); taxLotLine.setRegistrationCode(holdingTaxLot.getRegistrationCode()); taxLotLine.setIpIndicator(holdingTaxLot.getIncomePrincipalIndicator()); // set the lot acquired date taxLotLine.setLotAcquiredDate(holdingTaxLot.getAcquiredDate()); addTaxLotLine(transLine, taxLotLine); if (remainingUnits.compareTo(BigDecimal.ZERO) == 0) { break; } } } }