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.control.user.accounting.server.command;
018
019import com.echothree.control.user.accounting.common.edit.AccountingEditFactory;
020import com.echothree.control.user.accounting.common.edit.TransactionGlAccountCategoryEdit;
021import com.echothree.control.user.accounting.common.form.EditTransactionGlAccountCategoryForm;
022import com.echothree.control.user.accounting.common.result.AccountingResultFactory;
023import com.echothree.control.user.accounting.common.result.EditTransactionGlAccountCategoryResult;
024import com.echothree.control.user.accounting.common.spec.TransactionGlAccountCategorySpec;
025import com.echothree.model.control.accounting.server.control.AccountingControl;
026import com.echothree.model.control.core.common.EventTypes;
027import com.echothree.model.control.party.common.PartyTypes;
028import com.echothree.model.control.security.common.SecurityRoleGroups;
029import com.echothree.model.control.security.common.SecurityRoles;
030import com.echothree.model.data.accounting.server.entity.GlAccount;
031import com.echothree.model.data.accounting.server.entity.GlAccountCategory;
032import com.echothree.model.data.accounting.server.entity.TransactionGlAccount;
033import com.echothree.model.data.accounting.server.entity.TransactionGlAccountCategory;
034import com.echothree.model.data.accounting.server.entity.TransactionGlAccountCategoryDescription;
035import com.echothree.model.data.accounting.server.entity.TransactionGlAccountCategoryDetail;
036import com.echothree.model.data.accounting.server.entity.TransactionType;
037import com.echothree.model.data.accounting.server.value.TransactionGlAccountCategoryDescriptionValue;
038import com.echothree.model.data.accounting.server.value.TransactionGlAccountCategoryDetailValue;
039import com.echothree.model.data.accounting.server.value.TransactionGlAccountValue;
040import com.echothree.model.data.user.common.pk.UserVisitPK;
041import com.echothree.util.common.message.ExecutionErrors;
042import com.echothree.util.common.validation.FieldDefinition;
043import com.echothree.util.common.validation.FieldType;
044import com.echothree.util.common.command.BaseResult;
045import com.echothree.util.common.command.EditMode;
046import com.echothree.util.server.control.BaseEditCommand;
047import com.echothree.util.server.control.CommandSecurityDefinition;
048import com.echothree.util.server.control.PartyTypeDefinition;
049import com.echothree.util.server.control.SecurityRoleDefinition;
050import com.echothree.util.server.persistence.Session;
051import java.util.Arrays;
052import java.util.Collections;
053import java.util.List;
054
055public class EditTransactionGlAccountCategoryCommand
056        extends BaseEditCommand<TransactionGlAccountCategorySpec, TransactionGlAccountCategoryEdit> {
057    
058    private final static CommandSecurityDefinition COMMAND_SECURITY_DEFINITION;
059    private final static List<FieldDefinition> SPEC_FIELD_DEFINITIONS;
060    private final static List<FieldDefinition> EDIT_FIELD_DEFINITIONS;
061    
062    static {
063        COMMAND_SECURITY_DEFINITION = new CommandSecurityDefinition(Collections.unmodifiableList(Arrays.asList(
064                new PartyTypeDefinition(PartyTypes.UTILITY.name(), null),
065                new PartyTypeDefinition(PartyTypes.EMPLOYEE.name(), Collections.unmodifiableList(Arrays.asList(
066                        new SecurityRoleDefinition(SecurityRoleGroups.TransactionGlAccountCategory.name(), SecurityRoles.Edit.name())
067                        )))
068                )));
069        
070        SPEC_FIELD_DEFINITIONS = Collections.unmodifiableList(Arrays.asList(
071                new FieldDefinition("TransactionTypeName", FieldType.ENTITY_NAME, true, null, null),
072                new FieldDefinition("TransactionGlAccountCategoryName", FieldType.ENTITY_NAME, true, null, null)
073                ));
074        
075        EDIT_FIELD_DEFINITIONS = Collections.unmodifiableList(Arrays.asList(
076                new FieldDefinition("TransactionGlAccountCategoryName", FieldType.ENTITY_NAME, true, null, null),
077                new FieldDefinition("GlAccountCategoryName", FieldType.ENTITY_NAME, false, null, null),
078                new FieldDefinition("SortOrder", FieldType.SIGNED_INTEGER, true, null, null),
079                new FieldDefinition("GlAccountName", FieldType.ENTITY_NAME, false, null, null),
080                new FieldDefinition("Description", FieldType.STRING, false, 1L, 132L)
081                ));
082    }
083    
084    /** Creates a new instance of EditTransactionGlAccountCategoryCommand */
085    public EditTransactionGlAccountCategoryCommand(UserVisitPK userVisitPK, EditTransactionGlAccountCategoryForm form) {
086        super(userVisitPK, form, COMMAND_SECURITY_DEFINITION, SPEC_FIELD_DEFINITIONS, EDIT_FIELD_DEFINITIONS);
087    }
088    
089    @Override
090    protected BaseResult execute() {
091        var accountingControl = Session.getModelController(AccountingControl.class);
092        EditTransactionGlAccountCategoryResult result = AccountingResultFactory.getEditTransactionGlAccountCategoryResult();
093        String transactionTypeName = spec.getTransactionTypeName();
094        TransactionType transactionType = accountingControl.getTransactionTypeByNameForUpdate(transactionTypeName);
095        
096        if(transactionType != null) {
097            String transactionGlAccountCategoryName = spec.getTransactionGlAccountCategoryName();
098
099            if(editMode.equals(EditMode.LOCK) || editMode.equals(EditMode.ABANDON)) {
100                TransactionGlAccountCategory transactionGlAccountCategory = accountingControl.getTransactionGlAccountCategoryByName(transactionType, transactionGlAccountCategoryName);
101
102                if(transactionGlAccountCategory != null) {
103                    if(editMode.equals(EditMode.LOCK)) {
104                        if(lockEntity(transactionGlAccountCategory)) {
105                            TransactionGlAccountCategoryDescription transactionGlAccountCategoryDescription = accountingControl.getTransactionGlAccountCategoryDescription(transactionGlAccountCategory, getPreferredLanguage());
106                            TransactionGlAccount transactionGlAccount = accountingControl.getTransactionGlAccount(transactionGlAccountCategory);
107                            TransactionGlAccountCategoryEdit edit = AccountingEditFactory.getTransactionGlAccountCategoryEdit();
108                            TransactionGlAccountCategoryDetail transactionGlAccountCategoryDetail = transactionGlAccountCategory.getLastDetail();
109                            GlAccountCategory glAccountCategory = transactionGlAccountCategoryDetail.getGlAccountCategory();
110
111                            result.setTransactionGlAccountCategory(accountingControl.getTransactionGlAccountCategoryTransfer(getUserVisit(), transactionGlAccountCategory));
112
113                            result.setEdit(edit);
114                            edit.setTransactionGlAccountCategoryName(transactionGlAccountCategoryDetail.getTransactionGlAccountCategoryName());
115                            edit.setGlAccountCategoryName(glAccountCategory == null? null: glAccountCategory.getLastDetail().getGlAccountCategoryName());
116                            edit.setSortOrder(transactionGlAccountCategoryDetail.getSortOrder().toString());
117                            edit.setGlAccountName(transactionGlAccount == null? null: transactionGlAccount.getGlAccount().getLastDetail().getGlAccountName());
118
119                            if(transactionGlAccountCategoryDescription != null) {
120                                edit.setDescription(transactionGlAccountCategoryDescription.getDescription());
121                            }
122                        } else {
123                            addExecutionError(ExecutionErrors.EntityLockFailed.name());
124                        }
125
126                        result.setEntityLock(getEntityLockTransfer(transactionGlAccountCategory));
127                    } else { // EditMode.ABANDON
128                        unlockEntity(transactionGlAccountCategory);
129                    }
130                } else {
131                    addExecutionError(ExecutionErrors.UnknownTransactionGlAccountCategoryName.name(), transactionTypeName, transactionGlAccountCategoryName);
132                }
133            } else if(editMode.equals(EditMode.UPDATE)) {
134                TransactionGlAccountCategory transactionGlAccountCategory = accountingControl.getTransactionGlAccountCategoryByNameForUpdate(transactionType, transactionGlAccountCategoryName);
135
136                if(transactionGlAccountCategory != null) {
137                    transactionGlAccountCategoryName = edit.getTransactionGlAccountCategoryName();
138                    TransactionGlAccountCategory duplicateTransactionGlAccountCategory = accountingControl.getTransactionGlAccountCategoryByName(transactionType, transactionGlAccountCategoryName);
139
140                    if(duplicateTransactionGlAccountCategory == null || transactionGlAccountCategory.equals(duplicateTransactionGlAccountCategory)) {
141                        String glAccountCategoryName = edit.getGlAccountCategoryName();
142                        GlAccountCategory glAccountCategory = glAccountCategoryName == null? null: accountingControl.getGlAccountCategoryByName(glAccountCategoryName);
143
144                        if(glAccountCategoryName == null || glAccountCategory != null) {
145                            String glAccountName = edit.getGlAccountName();
146                            GlAccount glAccount = glAccountName == null? null: accountingControl.getGlAccountByName(glAccountName);
147
148                            if(glAccountName == null || glAccount != null) {
149                                if(glAccountCategory == null || glAccount == null? true: glAccountCategory.equals(glAccount.getLastDetail().getGlAccountCategory())) {
150                                    if(lockEntityForUpdate(transactionGlAccountCategory)) {
151                                        try {
152                                            var partyPK = getPartyPK();
153                                            TransactionGlAccountCategoryDetailValue transactionGlAccountCategoryDetailValue = accountingControl.getTransactionGlAccountCategoryDetailValueForUpdate(transactionGlAccountCategory);
154                                            TransactionGlAccountCategoryDescription transactionGlAccountCategoryDescription = accountingControl.getTransactionGlAccountCategoryDescriptionForUpdate(transactionGlAccountCategory, getPreferredLanguage());
155                                            TransactionGlAccount transactionGlAccount = accountingControl.getTransactionGlAccount(transactionGlAccountCategory);
156                                            String description = edit.getDescription();
157
158                                            transactionGlAccountCategoryDetailValue.setTransactionGlAccountCategoryName(edit.getTransactionGlAccountCategoryName());
159                                            transactionGlAccountCategoryDetailValue.setGlAccountCategoryPK(glAccountCategory == null? null: glAccountCategory.getPrimaryKey());
160                                            transactionGlAccountCategoryDetailValue.setSortOrder(Integer.valueOf(edit.getSortOrder()));
161
162                                            accountingControl.updateTransactionGlAccountCategoryFromValue(transactionGlAccountCategoryDetailValue, partyPK);
163
164                                            if(transactionGlAccountCategoryDescription == null && description != null) {
165                                                accountingControl.createTransactionGlAccountCategoryDescription(transactionGlAccountCategory, getPreferredLanguage(), description, partyPK);
166                                            } else if(transactionGlAccountCategoryDescription != null && description == null) {
167                                                accountingControl.deleteTransactionGlAccountCategoryDescription(transactionGlAccountCategoryDescription, partyPK);
168                                            } else if(transactionGlAccountCategoryDescription != null && description != null) {
169                                                TransactionGlAccountCategoryDescriptionValue transactionGlAccountCategoryDescriptionValue = accountingControl.getTransactionGlAccountCategoryDescriptionValue(transactionGlAccountCategoryDescription);
170
171                                                transactionGlAccountCategoryDescriptionValue.setDescription(description);
172                                                accountingControl.updateTransactionGlAccountCategoryDescriptionFromValue(transactionGlAccountCategoryDescriptionValue, partyPK);
173                                            }
174
175                                            if(transactionGlAccount == null && glAccount != null) {
176                                                accountingControl.createTransactionGlAccount(transactionGlAccountCategory, glAccount, partyPK);
177                                            } else if(transactionGlAccount != null && glAccount == null) {
178                                                accountingControl.deleteTransactionGlAccount(transactionGlAccount, partyPK);
179                                            } else if(transactionGlAccount != null && glAccount != null) {
180                                                TransactionGlAccountValue transactionGlAccountValue = accountingControl.getTransactionGlAccountValue(transactionGlAccount);
181
182                                                transactionGlAccountValue.setGlAccountPK(glAccount.getPrimaryKey());
183                                                accountingControl.updateTransactionGlAccountFromValue(transactionGlAccountValue, partyPK);
184                                            }
185                                        } finally {
186                                            unlockEntity(transactionGlAccountCategory);
187                                        }
188                                    } else {
189                                        addExecutionError(ExecutionErrors.EntityLockStale.name());
190                                    }
191                                } else {
192                                    addExecutionError(ExecutionErrors.InvalidGlAccountCategory.name());
193                                }
194                            } else {
195                                addExecutionError(ExecutionErrors.UnknownGlAccountName.name(), glAccountName);
196                            }
197                        } else {
198                            addExecutionError(ExecutionErrors.UnknownGlAccountCategoryName.name(), glAccountCategoryName);
199                        }
200                    } else {
201                        addExecutionError(ExecutionErrors.DuplicateTransactionGlAccountCategoryName.name(), transactionTypeName, transactionGlAccountCategoryName);
202                    }
203
204                    if(hasExecutionErrors()) {
205                        result.setTransactionGlAccountCategory(accountingControl.getTransactionGlAccountCategoryTransfer(getUserVisit(), transactionGlAccountCategory));
206                        result.setEntityLock(getEntityLockTransfer(transactionGlAccountCategory));
207                    }
208                } else {
209                    addExecutionError(ExecutionErrors.UnknownTransactionGlAccountCategoryName.name(), transactionTypeName, transactionGlAccountCategoryName);
210                }
211            }
212        } else {
213            addExecutionError(ExecutionErrors.UnknownTransactionTypeName.name(), transactionTypeName);
214        }
215        
216        return result;
217    }
218    
219}