001// -------------------------------------------------------------------------------- 002// Copyright 2002-2024 Echo Three, LLC 003// 004// Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0 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 017package com.echothree.model.control.accounting.server.logic; 018 019import com.echothree.model.control.accounting.server.control.AccountingControl; 020import com.echothree.model.control.core.server.control.CoreControl; 021import com.echothree.model.control.party.server.control.PartyControl; 022import com.echothree.model.data.accounting.server.entity.Currency; 023import com.echothree.model.data.accounting.server.entity.GlAccount; 024import com.echothree.model.data.accounting.server.entity.Transaction; 025import com.echothree.model.data.accounting.server.entity.TransactionDetail; 026import com.echothree.model.data.accounting.server.entity.TransactionEntityRole; 027import com.echothree.model.data.accounting.server.entity.TransactionEntityRoleType; 028import com.echothree.model.data.accounting.server.entity.TransactionGlAccount; 029import com.echothree.model.data.accounting.server.entity.TransactionGlAccountCategory; 030import com.echothree.model.data.accounting.server.entity.TransactionGlEntry; 031import com.echothree.model.data.accounting.server.entity.TransactionStatus; 032import com.echothree.model.data.accounting.server.entity.TransactionType; 033import com.echothree.model.data.core.server.entity.EntityInstance; 034import com.echothree.model.data.party.server.entity.Party; 035import com.echothree.util.common.persistence.BasePK; 036import com.echothree.util.server.persistence.Session; 037 038public class TransactionLogic { 039 040 private TransactionLogic() { 041 super(); 042 } 043 044 private static class TransactionLogicHolder { 045 static TransactionLogic instance = new TransactionLogic(); 046 } 047 048 public static TransactionLogic getInstance() { 049 return TransactionLogicHolder.instance; 050 } 051 052 public Transaction createTransactionUsingNames(final Session session, final Party groupParty, final String transactionTypeName, final Long postingTime, final BasePK createdBy) { 053 var accountingControl = Session.getModelController(AccountingControl.class); 054 055 return createTransaction(session, groupParty, accountingControl.getTransactionTypeByName(transactionTypeName), postingTime, createdBy); 056 } 057 058 public Transaction createTransaction(final Session session, final Party groupParty, final TransactionType transactionType, final Long postingTime, final BasePK createdBy) { 059 var accountingControl = Session.getModelController(AccountingControl.class); 060 061 return accountingControl.createTransaction(groupParty, transactionType, postingTime == null? session.START_TIME_LONG: postingTime, createdBy); 062 } 063 064 public TransactionGlEntry createTransactionGlEntryUsingNames(final Transaction transaction, final Party groupParty, final String transactionGlAccountCategoryName, 065 final GlAccount glAccount, final Currency originalCurrency, final Long originalAmount, final BasePK createdBy) { 066 var accountingControl = Session.getModelController(AccountingControl.class); 067 TransactionDetail transactionDetail = transaction.getLastDetail(); 068 069 return createTransactionGlEntry(transaction, groupParty == null? transactionDetail.getGroupParty(): groupParty, 070 accountingControl.getTransactionGlAccountCategoryByName(transactionDetail.getTransactionType(), transactionGlAccountCategoryName), glAccount, originalCurrency, originalAmount, 071 createdBy); 072 } 073 074 private GlAccount getGlAccount(final AccountingControl accountingControl, final TransactionGlAccountCategory transactionGlAccountCategory, GlAccount glAccount) { 075 if(glAccount == null) { 076 TransactionGlAccount transactionGlAccount = accountingControl.getTransactionGlAccount(transactionGlAccountCategory); 077 078 if(transactionGlAccount == null) { 079 throw new IllegalArgumentException("glAccount is a required parameter"); 080 } else { 081 glAccount = transactionGlAccount.getGlAccount(); 082 } 083 } 084 085 return glAccount; 086 } 087 088 private Integer getTransactionGlEntrySequence(final AccountingControl accountingControl, final Transaction transaction) { 089 TransactionStatus transactionStatus = accountingControl.getTransactionStatusForUpdate(transaction); 090 Integer transactionGlEntrySequence = transactionStatus.getTransactionGlEntrySequence() + 1; 091 092 transactionStatus.setTransactionGlEntrySequence(transactionGlEntrySequence); 093 094 return transactionGlEntrySequence; 095 } 096 097 private Long getAmount(final GlAccount glAccount, final Currency originalCurrency, final Long originalAmount) { 098 Currency currency = glAccount.getLastDetail().getCurrency(); 099 100 Long amount = null; 101 if(originalCurrency.equals(currency)) { 102 amount = originalAmount; 103 } else { 104 throw new IllegalArgumentException("Currency conversion is not available"); 105 } 106 107 return amount; 108 } 109 110 public TransactionGlEntry createTransactionGlEntry(final Transaction transaction, final Party groupParty, final TransactionGlAccountCategory transactionGlAccountCategory, 111 GlAccount glAccount, final Currency originalCurrency, final Long originalAmount, final BasePK createdBy) { 112 var accountingControl = Session.getModelController(AccountingControl.class); 113 114 glAccount = getGlAccount(accountingControl, transactionGlAccountCategory, glAccount); 115 116 Long amount = getAmount(glAccount, originalCurrency, originalAmount); 117 118 return accountingControl.createTransactionGlEntry(transaction, getTransactionGlEntrySequence(accountingControl, transaction), null, groupParty, transactionGlAccountCategory, glAccount, 119 originalCurrency, originalAmount, amount, createdBy); 120 } 121 122 public TransactionEntityRole createTransactionEntityRoleUsingNames(final Transaction transaction, final String transactionEntityRoleTypeName, final BasePK pk, 123 final BasePK createdBy) { 124 var accountingControl = Session.getModelController(AccountingControl.class); 125 TransactionEntityRoleType transactionEntityRoleType = accountingControl.getTransactionEntityRoleTypeByName(transaction.getLastDetail().getTransactionType(), 126 transactionEntityRoleTypeName); 127 128 return createTransactionEntityRole(transaction, transactionEntityRoleType, pk, createdBy); 129 } 130 131 public TransactionEntityRole createTransactionEntityRole(final Transaction transaction, final TransactionEntityRoleType transactionEntityRoleType, final BasePK pk, 132 final BasePK createdBy) { 133 var accountingControl = Session.getModelController(AccountingControl.class); 134 var coreControl = Session.getModelController(CoreControl.class); 135 EntityInstance entityInstance = coreControl.getEntityInstanceByBasePK(pk); 136 137 if(!transactionEntityRoleType.getLastDetail().getEntityType().equals(entityInstance.getEntityType())) { 138 throw new IllegalArgumentException("entityInstance is not of the required EntityType"); 139 } 140 141 return accountingControl.createTransactionEntityRole(transaction, transactionEntityRoleType, entityInstance, createdBy); 142 } 143 144 public void finishTransaction(final Transaction transaction) { 145 var accountingControl = Session.getModelController(AccountingControl.class); 146 147 accountingControl.removeTransactionStatusByTransaction(transaction); 148 149 PostingLogic.getInstance().postTransaction(transaction); 150 } 151 152 public void testTransaction(final Session session, final BasePK testedBy) { 153 var accountingControl = Session.getModelController(AccountingControl.class); 154 var partyControl = Session.getModelController(PartyControl.class); 155 Party companyParty = partyControl.getDefaultPartyCompany().getParty(); 156 Party divisionParty = partyControl.getDefaultPartyDivision(companyParty).getParty(); 157 Party departmentParty = partyControl.getDefaultPartyDepartment(divisionParty).getParty(); 158 Currency originalCurrency = accountingControl.getDefaultCurrency(); 159 160 Transaction transaction = createTransactionUsingNames(session, departmentParty, "TEST", null, testedBy); 161 createTransactionGlEntryUsingNames(transaction, null, "TEST_ACCOUNT_A", null, originalCurrency, 1999L, testedBy); 162 createTransactionGlEntryUsingNames(transaction, null, "TEST_ACCOUNT_B", null, originalCurrency, -1999L, testedBy); 163 createTransactionEntityRoleUsingNames(transaction, "TEST_ENTITY_INSTANCE_ROLE_TYPE", testedBy, testedBy); 164 finishTransaction(transaction); 165 } 166 167}