/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kuali.kfs.module.cam.document.service; import static org.kuali.kfs.sys.fixture.UserNameFixture.khuntley; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.apache.commons.lang.time.DateUtils; import org.kuali.kfs.module.cam.CamsConstants; import org.kuali.kfs.module.cam.CamsPropertyConstants; import org.kuali.kfs.module.cam.businessobject.Asset; import org.kuali.kfs.module.cam.businessobject.AssetLocation; import org.kuali.kfs.module.cam.businessobject.AssetOrganization; import org.kuali.kfs.module.cam.businessobject.AssetPayment; import org.kuali.kfs.module.cam.document.AssetTransferDocument; import org.kuali.kfs.module.cam.fixture.AssetTransferFixture; import org.kuali.kfs.sys.ConfigureContext; import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntrySourceDetail; import org.kuali.kfs.sys.context.KualiTestBase; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.kfs.sys.fixture.UserNameFixture; import org.kuali.kfs.sys.service.UniversityDateService; import org.kuali.rice.core.api.util.type.KualiDecimal; import org.kuali.rice.krad.service.BusinessObjectService; public class AssetTransferServiceTest extends KualiTestBase { private UniversityDateService universityDateService; private AssetTransferService assetTransferService; @Override @ConfigureContext(session = UserNameFixture.khuntley, shouldCommitTransactions = false) protected void setUp() throws Exception { super.setUp(); universityDateService = SpringContext.getBean(UniversityDateService.class); assetTransferService = SpringContext.getBean(AssetTransferService.class); } /** * Test capital asset with active payments * * @throws Exception */ @ConfigureContext(session = khuntley, shouldCommitTransactions = false) public void testCreateGLPostables_Success() throws Exception { // set up the data AssetTransferDocument document = buildTransferDocument(AssetTransferFixture.ACTIVE_CAPITAL_ASSET.newAsset(), true); this.assetTransferService.createGLPostables(document); // assert gl postables List<GeneralLedgerPendingEntrySourceDetail> generalLedgerPostables = document.getGeneralLedgerPendingEntrySourceDetails(); assertFalse(generalLedgerPostables.isEmpty()); assertEquals(12, generalLedgerPostables.size()); Asset asset = document.getAsset(); // assert source gl postable for first payment AssetPayment payment1 = asset.getAssetPayments().get(0); assertGLPostable(generalLedgerPostables.get(0), asset.getOrganizationOwnerChartOfAccountsCode(), payment1.getAccountChargeAmount(), "9520004", "Reverse asset cost", "8610"); assertGLPostable(generalLedgerPostables.get(1), asset.getOrganizationOwnerChartOfAccountsCode(), payment1.getAccumulatedPrimaryDepreciationAmount(), "9520004", "Reverse accumulated depreciation", "8910"); assertGLPostable(generalLedgerPostables.get(2), asset.getOrganizationOwnerChartOfAccountsCode(), payment1.getAccountChargeAmount().subtract(payment1.getAccumulatedPrimaryDepreciationAmount()), "9520004", "Reverse offset amount", "9899"); // assert source gl postable for second payment AssetPayment payment2 = asset.getAssetPayments().get(1); assertGLPostable(generalLedgerPostables.get(3), asset.getOrganizationOwnerChartOfAccountsCode(), payment2.getAccountChargeAmount(), "9520004", "Reverse asset cost", "8610"); assertGLPostable(generalLedgerPostables.get(4), asset.getOrganizationOwnerChartOfAccountsCode(), payment2.getAccumulatedPrimaryDepreciationAmount(), "9520004", "Reverse accumulated depreciation", "8910"); assertGLPostable(generalLedgerPostables.get(5), asset.getOrganizationOwnerChartOfAccountsCode(), payment2.getAccountChargeAmount().subtract(payment2.getAccumulatedPrimaryDepreciationAmount()), "9520004", "Reverse offset amount", "9899"); // assert target gl postable for first payment assertGLPostable(generalLedgerPostables.get(6), document.getOrganizationOwnerChartOfAccountsCode(), payment1.getAccountChargeAmount(), "9567077", "Transfer asset cost", "8610"); assertGLPostable(generalLedgerPostables.get(7), document.getOrganizationOwnerChartOfAccountsCode(), payment1.getAccumulatedPrimaryDepreciationAmount(), "9567077", "Transfer accumulated depreciation", "8910"); assertGLPostable(generalLedgerPostables.get(8), document.getOrganizationOwnerChartOfAccountsCode(), payment1.getAccountChargeAmount().subtract(payment1.getAccumulatedPrimaryDepreciationAmount()), "9567077", "Transfer offset amount", "9899"); // assert target gl postable for second payment assertGLPostable(generalLedgerPostables.get(9), document.getOrganizationOwnerChartOfAccountsCode(), payment2.getAccountChargeAmount(), "9567077", "Transfer asset cost", "8610"); assertGLPostable(generalLedgerPostables.get(10), document.getOrganizationOwnerChartOfAccountsCode(), payment2.getAccumulatedPrimaryDepreciationAmount(), "9567077", "Transfer accumulated depreciation", "8910"); assertGLPostable(generalLedgerPostables.get(11), document.getOrganizationOwnerChartOfAccountsCode(), payment2.getAccountChargeAmount().subtract(payment2.getAccumulatedPrimaryDepreciationAmount()), "9567077", "Transfer offset amount", "9899"); } /** * Test capital asset with active payments * * @throws Exception */ @ConfigureContext(session = khuntley, shouldCommitTransactions = false) public void testCreateGLPostables_No_Offset() throws Exception { // set up the data AssetTransferDocument document = buildTransferDocumentWithoutOffset(AssetTransferFixture.ACTIVE_CAPITAL_ASSET.newAsset(), true); this.assetTransferService.createGLPostables(document); // assert gl postables List<GeneralLedgerPendingEntrySourceDetail> generalLedgerPostables = document.getGeneralLedgerPendingEntrySourceDetails(); assertFalse(generalLedgerPostables.isEmpty()); assertEquals(8, generalLedgerPostables.size()); Asset asset = document.getAsset(); // assert source gl postable for first payment AssetPayment payment1 = asset.getAssetPayments().get(0); assertGLPostable(generalLedgerPostables.get(0), asset.getOrganizationOwnerChartOfAccountsCode(), payment1.getAccountChargeAmount(), "9520004", "Reverse asset cost", "8610"); assertGLPostable(generalLedgerPostables.get(1), asset.getOrganizationOwnerChartOfAccountsCode(), payment1.getAccumulatedPrimaryDepreciationAmount(), "9520004", "Reverse accumulated depreciation", "8910"); // assert source gl postable for second payment AssetPayment payment2 = asset.getAssetPayments().get(1); assertGLPostable(generalLedgerPostables.get(2), asset.getOrganizationOwnerChartOfAccountsCode(), payment2.getAccountChargeAmount(), "9520004", "Reverse asset cost", "8610"); assertGLPostable(generalLedgerPostables.get(3), asset.getOrganizationOwnerChartOfAccountsCode(), payment2.getAccumulatedPrimaryDepreciationAmount(), "9520004", "Reverse accumulated depreciation", "8910"); // assert target gl postable for first payment assertGLPostable(generalLedgerPostables.get(4), document.getOrganizationOwnerChartOfAccountsCode(), payment1.getAccountChargeAmount(), "9567077", "Transfer asset cost", "8610"); assertGLPostable(generalLedgerPostables.get(5), document.getOrganizationOwnerChartOfAccountsCode(), payment1.getAccumulatedPrimaryDepreciationAmount(), "9567077", "Transfer accumulated depreciation", "8910"); // assert target gl postable for second payment assertGLPostable(generalLedgerPostables.get(6), document.getOrganizationOwnerChartOfAccountsCode(), payment2.getAccountChargeAmount(), "9567077", "Transfer asset cost", "8610"); assertGLPostable(generalLedgerPostables.get(7), document.getOrganizationOwnerChartOfAccountsCode(), payment2.getAccumulatedPrimaryDepreciationAmount(), "9567077", "Transfer accumulated depreciation", "8910"); } /** * test non-capital assets * * @throws Exception */ @ConfigureContext(session = khuntley, shouldCommitTransactions = false) public void testCreateGLPostables_Non_CapitalAsset() throws Exception { // set up the data AssetTransferDocument document = buildTransferDocument(AssetTransferFixture.ACTIVE_NON_CAPITAL_ASSET.newAsset(), true); this.assetTransferService.createGLPostables(document); // assert gl postables List<GeneralLedgerPendingEntrySourceDetail> generalLedgerPostables = document.getGeneralLedgerPendingEntrySourceDetails(); assertTrue(generalLedgerPostables.isEmpty()); } /** * Test active asset with no payments * * @throws Exception */ @ConfigureContext(session = khuntley, shouldCommitTransactions = false) public void testCreateGLPostables_No_Payments() throws Exception { // set up the data AssetTransferDocument document = buildTransferDocument(AssetTransferFixture.ACTIVE_CAPITAL_ASSET.newAsset(), false); this.assetTransferService.createGLPostables(document); // assert gl postables List<GeneralLedgerPendingEntrySourceDetail> generalLedgerPostables = document.getGeneralLedgerPendingEntrySourceDetails(); assertTrue(generalLedgerPostables.isEmpty()); } /** * Assert GL postable entry * * @param glPostable * @param chartOfAccountsCode * @param amount * @param plantAccount * @param financialLineDesc * @param financialObjectCode */ private void assertGLPostable(GeneralLedgerPendingEntrySourceDetail glPostable, String chartOfAccountsCode, KualiDecimal amount, String plantAccount, String financialLineDesc, String financialObjectCode) { assertEquals(plantAccount, glPostable.getAccountNumber()); assertEquals(amount, glPostable.getAmount()); assertEquals(CamsConstants.Postable.GL_BALANCE_TYPE_CODE_AC, glPostable.getBalanceTypeCode()); assertEquals(chartOfAccountsCode, glPostable.getChartOfAccountsCode()); assertEquals(financialLineDesc, glPostable.getFinancialDocumentLineDescription()); assertEquals(financialObjectCode, glPostable.getFinancialObjectCode()); assertEquals(this.universityDateService.getCurrentFiscalYear(), glPostable.getPostingYear()); assertNull(glPostable.getOrganizationReferenceId()); assertNull(glPostable.getProjectCode()); assertNull(glPostable.getReferenceNumber()); assertNull(glPostable.getReferenceOriginCode()); assertNull(glPostable.getReferenceTypeCode()); } private AssetTransferDocument buildTransferDocument(Asset asset, boolean addPayments) { BusinessObjectService boService = SpringContext.getBean(BusinessObjectService.class); AssetTransferDocument document = AssetTransferFixture.ASSET_TRANSFER.newAssetTransferDocument(); asset.setCapitalAssetNumber(null); asset.setCapitalAssetTypeCode("665"); boService.save(asset); if (addPayments) { AssetPayment payment1 = AssetTransferFixture.PAYMENT1_WITH_OFFSET.newAssetPayment(); AssetPayment payment2 = AssetTransferFixture.PAYMENT2_WITH_OFFSET.newAssetPayment(); payment1.setCapitalAssetNumber(asset.getCapitalAssetNumber()); payment1.setPaymentSequenceNumber(1); payment2.setCapitalAssetNumber(asset.getCapitalAssetNumber()); payment2.setPaymentSequenceNumber(2); boService.save(payment1); boService.save(payment2); payment1.refresh(); payment2.refresh(); asset.getAssetPayments().add(payment1); asset.getAssetPayments().add(payment2); } document.setAsset(asset); document.setCapitalAssetNumber(asset.getCapitalAssetNumber()); return document; } private AssetTransferDocument buildTransferDocumentWithoutOffset(Asset asset, boolean addPayments) { BusinessObjectService boService = SpringContext.getBean(BusinessObjectService.class); AssetTransferDocument document = AssetTransferFixture.ASSET_TRANSFER.newAssetTransferDocument(); asset.setCapitalAssetNumber(null); asset.setCapitalAssetTypeCode("665"); boService.save(asset); if (addPayments) { AssetPayment payment1 = AssetTransferFixture.PAYMENT3_WITHOUT_OFFSET.newAssetPayment(); AssetPayment payment2 = AssetTransferFixture.PAYMENT4_WITHOUT_OFFSET.newAssetPayment(); payment1.setCapitalAssetNumber(asset.getCapitalAssetNumber()); payment1.setPaymentSequenceNumber(1); payment2.setCapitalAssetNumber(asset.getCapitalAssetNumber()); payment2.setPaymentSequenceNumber(2); boService.save(payment1); boService.save(payment2); payment1.refresh(); payment2.refresh(); asset.getAssetPayments().add(payment1); asset.getAssetPayments().add(payment2); } document.setAsset(asset); document.setCapitalAssetNumber(asset.getCapitalAssetNumber()); return document; } @ConfigureContext(session = khuntley, shouldCommitTransactions = false) public void testSaveApprovedChanges() throws Exception { AssetTransferDocument document = buildTransferDocument(AssetTransferFixture.ACTIVE_CAPITAL_ASSET.newAsset(), true); this.assetTransferService.saveApprovedChanges(document); BusinessObjectService boService = SpringContext.getBean(BusinessObjectService.class); Asset asset = document.getAsset(); asset = (Asset) boService.retrieve(asset); asset.refreshReferenceObject(CamsPropertyConstants.Asset.ASSET_PAYMENTS); assertNotNull(asset); assertEquals(document.getOrganizationOwnerChartOfAccountsCode(), asset.getOrganizationOwnerChartOfAccountsCode()); assertEquals(document.getOrganizationOwnerAccountNumber(), asset.getOrganizationOwnerAccountNumber()); assertEquals(document.getCampusCode(), asset.getCampusCode()); assertEquals(document.getBuildingCode(), asset.getBuildingCode()); assertEquals(document.getBuildingRoomNumber(), asset.getBuildingRoomNumber()); assertEquals(document.getBuildingSubRoomNumber(), asset.getBuildingSubRoomNumber()); assertTrue(DateUtils.isSameDay(new java.util.Date(), asset.getLastInventoryDate())); List<AssetPayment> assetPayments = asset.getAssetPayments(); // sort the payment Collections.sort(assetPayments, new Comparator<AssetPayment>() { @Override public int compare(AssetPayment o1, AssetPayment o2) { return o1.getPaymentSequenceNumber().compareTo(o2.getPaymentSequenceNumber()); } }); assertEquals(6, assetPayments.size()); // Asset original payment 1 AssetPayment testDataPayment = AssetTransferFixture.PAYMENT1_WITH_OFFSET.newAssetPayment(); AssetPayment assetPayment1 = assetPayments.get(0); assertOriginalPayment(testDataPayment, assetPayment1); // Assert original payment 2 testDataPayment = AssetTransferFixture.PAYMENT2_WITH_OFFSET.newAssetPayment(); AssetPayment assetPayment2 = assetPayments.get(1); assertOriginalPayment(testDataPayment, assetPayment2); // Assert offset payment 1 testDataPayment = AssetTransferFixture.PAYMENT1_WITH_OFFSET.newAssetPayment(); AssetPayment offsetPayment1 = assetPayments.get(2); assertOffsetPayment(testDataPayment, offsetPayment1); // Assert offset payment 2 testDataPayment = AssetTransferFixture.PAYMENT2_WITH_OFFSET.newAssetPayment(); AssetPayment offsetPayment2 = assetPayments.get(3); assertOffsetPayment(testDataPayment, offsetPayment2); // Assert new payment 1 testDataPayment = AssetTransferFixture.PAYMENT1_WITH_OFFSET.newAssetPayment(); AssetPayment newPayment1 = assetPayments.get(4); assertNewPayment(document, testDataPayment, newPayment1); // Assert new payment 2 testDataPayment = AssetTransferFixture.PAYMENT2_WITH_OFFSET.newAssetPayment(); AssetPayment newPayment2 = assetPayments.get(5); assertNewPayment(document, testDataPayment, newPayment2); } @ConfigureContext(session = khuntley, shouldCommitTransactions = false) public void testSaveApprovedChanges_Offcampus() throws Exception { AssetTransferDocument document = buildTransferDocument(AssetTransferFixture.ACTIVE_CAPITAL_ASSET.newAsset(), true); document.setOffCampusAddress("4700 S HAGADORN"); document.setOffCampusCityName("E LANSING"); document.setOffCampusStateCode("MI"); document.setOffCampusZipCode("48823"); // clear fields that conflict with off-campus data document.setCampusCode(null); document.setBuildingCode(null); document.setBuildingRoomNumber(null); document.setBuildingSubRoomNumber(null); this.assetTransferService.saveApprovedChanges(document); BusinessObjectService boService = SpringContext.getBean(BusinessObjectService.class); Asset asset = document.getAsset(); asset = (Asset) boService.retrieve(asset); asset.refreshReferenceObject(CamsPropertyConstants.Asset.ASSET_LOCATIONS); SpringContext.getBean(AssetLocationService.class).setOffCampusLocation(asset); assertNotNull(asset); assertEquals(document.getOrganizationOwnerChartOfAccountsCode(), asset.getOrganizationOwnerChartOfAccountsCode()); assertEquals(document.getOrganizationOwnerAccountNumber(), asset.getOrganizationOwnerAccountNumber()); assertEquals(document.getCampusCode(), asset.getCampusCode()); assertTrue(DateUtils.isSameDay(new java.util.Date(), asset.getLastInventoryDate())); AssetLocation offCampusLocation = asset.getOffCampusLocation(); assertNotNull(offCampusLocation); assertEquals("4700 S HAGADORN", offCampusLocation.getAssetLocationStreetAddress()); assertEquals("E LANSING", offCampusLocation.getAssetLocationCityName()); assertEquals("MI", offCampusLocation.getAssetLocationStateCode()); assertEquals("48823", offCampusLocation.getAssetLocationZipCode()); } @ConfigureContext(session = khuntley, shouldCommitTransactions = false) public void testSaveApprovedChanges_AssetOrgInfo() throws Exception { AssetTransferDocument document = buildTransferDocument(AssetTransferFixture.ACTIVE_CAPITAL_ASSET.newAsset(), true); document.setOrganizationTagNumber("TEL"); document.setOrganizationText("TEXT"); this.assetTransferService.saveApprovedChanges(document); BusinessObjectService boService = SpringContext.getBean(BusinessObjectService.class); Asset asset = document.getAsset(); asset = (Asset) boService.retrieve(asset); asset.refreshReferenceObject(CamsPropertyConstants.AssetOrganization.ASSET_ORGANIZATION); AssetOrganization assetOrganization = asset.getAssetOrganization(); assertNotNull(assetOrganization); assertEquals("TEL", assetOrganization.getOrganizationTagNumber()); assertEquals("TEXT", assetOrganization.getOrganizationText()); } private void assertNewPayment(AssetTransferDocument document, AssetPayment referencePayment, AssetPayment newPayment) { assertEquals(document.getOrganizationOwnerAccountNumber(), newPayment.getAccountNumber()); assertEquals(referencePayment.getAccountChargeAmount(), newPayment.getAccountChargeAmount()); assertEquals(referencePayment.getAccumulatedPrimaryDepreciationAmount(), newPayment.getAccumulatedPrimaryDepreciationAmount()); assertEquals(null, newPayment.getPeriod1Depreciation1Amount()); assertEquals(CamsConstants.AssetPayment.TRANSFER_PAYMENT_CODE_N, newPayment.getTransferPaymentCode()); } private void assertOriginalPayment(AssetPayment referencePayment, AssetPayment assetOriginalPayment) { assertEquals(referencePayment.getAccountNumber(), assetOriginalPayment.getAccountNumber()); assertEquals(referencePayment.getAccountChargeAmount(), assetOriginalPayment.getAccountChargeAmount()); assertEquals(referencePayment.getAccumulatedPrimaryDepreciationAmount(), assetOriginalPayment.getAccumulatedPrimaryDepreciationAmount()); assertEquals(referencePayment.getPeriod1Depreciation1Amount(), assetOriginalPayment.getPeriod1Depreciation1Amount()); assertEquals(CamsConstants.AssetPayment.TRANSFER_PAYMENT_CODE_Y, assetOriginalPayment.getTransferPaymentCode()); } private void assertOffsetPayment(AssetPayment referencePayment, AssetPayment assetOffsetPayment) { assertEquals(referencePayment.getAccountNumber(), assetOffsetPayment.getAccountNumber()); KualiDecimal negative = new KualiDecimal(-1); assertEquals(referencePayment.getAccountChargeAmount().multiply(negative), assetOffsetPayment.getAccountChargeAmount()); assertEquals(referencePayment.getAccumulatedPrimaryDepreciationAmount().multiply(negative), assetOffsetPayment.getAccumulatedPrimaryDepreciationAmount()); assertEquals(null, assetOffsetPayment.getPeriod1Depreciation1Amount()); assertEquals(CamsConstants.AssetPayment.TRANSFER_PAYMENT_CODE_Y, assetOffsetPayment.getTransferPaymentCode()); } }