001// --------------------------------------------------------------------------------
002// Copyright 2002-2026 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.associate.server.command;
018
019import com.echothree.control.user.associate.common.edit.AssociateEditFactory;
020import com.echothree.control.user.associate.common.edit.AssociateProgramEdit;
021import com.echothree.control.user.associate.common.form.EditAssociateProgramForm;
022import com.echothree.control.user.associate.common.result.AssociateResultFactory;
023import com.echothree.control.user.associate.common.spec.AssociateProgramSpec;
024import com.echothree.model.control.associate.server.control.AssociateControl;
025import com.echothree.model.control.sequence.common.SequenceTypes;
026import com.echothree.model.control.sequence.server.control.SequenceControl;
027import com.echothree.model.data.sequence.server.entity.Sequence;
028import com.echothree.model.data.user.common.pk.UserVisitPK;
029import com.echothree.util.common.command.BaseResult;
030import com.echothree.util.common.command.EditMode;
031import com.echothree.util.common.message.ExecutionErrors;
032import com.echothree.util.common.validation.FieldDefinition;
033import com.echothree.util.common.validation.FieldType;
034import com.echothree.util.server.control.BaseEditCommand;
035import com.echothree.util.server.persistence.Session;
036import com.echothree.util.server.string.PercentUtils;
037import java.util.ArrayList;
038import java.util.List;
039import javax.enterprise.context.Dependent;
040
041@Dependent
042public class EditAssociateProgramCommand
043        extends BaseEditCommand<AssociateProgramSpec, AssociateProgramEdit> {
044    
045    private final static List<FieldDefinition> SPEC_FIELD_DEFINITIONS;
046    private final static List<FieldDefinition> EDIT_FIELD_DEFINITIONS;
047    
048    static {
049        SPEC_FIELD_DEFINITIONS = List.of(
050                new FieldDefinition("AssociateProgramName", FieldType.ENTITY_NAME, true, null, null)
051                );
052        
053        EDIT_FIELD_DEFINITIONS = List.of(
054                new FieldDefinition("AssociateProgramName", FieldType.ENTITY_NAME, true, null, null),
055                new FieldDefinition("AssociateSequenceName", FieldType.ENTITY_NAME, false, null, null),
056                new FieldDefinition("AssociatePartyContactMechanismSequenceName", FieldType.ENTITY_NAME, false, null, null),
057                new FieldDefinition("AssociateReferralSequenceName", FieldType.ENTITY_NAME, false, null, null),
058                new FieldDefinition("ItemIndirectSalePercent", FieldType.FRACTIONAL_PERCENT, false, null, null),
059                new FieldDefinition("ItemDirectSalePercent", FieldType.FRACTIONAL_PERCENT, false, null, null),
060                new FieldDefinition("IsDefault", FieldType.BOOLEAN, true, null, null),
061                new FieldDefinition("SortOrder", FieldType.SIGNED_INTEGER, true, null, null),
062                new FieldDefinition("Description", FieldType.STRING, false, 1L, 132L)
063                );
064    }
065    
066    /** Creates a new instance of EditAssociateProgramCommand */
067    public EditAssociateProgramCommand() {
068        super(null, SPEC_FIELD_DEFINITIONS, EDIT_FIELD_DEFINITIONS);
069    }
070    
071    @Override
072    protected BaseResult execute() {
073        var associateControl = Session.getModelController(AssociateControl.class);
074        var result = AssociateResultFactory.getEditAssociateProgramResult();
075        
076        if(editMode.equals(EditMode.LOCK)) {
077            var associateProgramName = spec.getAssociateProgramName();
078            var associateProgram = associateControl.getAssociateProgramByName(associateProgramName);
079            
080            if(associateProgram != null) {
081                result.setAssociateProgram(associateControl.getAssociateProgramTransfer(getUserVisit(), associateProgram));
082                
083                if(lockEntity(associateProgram)) {
084                    var associateProgramDescription = associateControl.getAssociateProgramDescription(associateProgram, getPreferredLanguage());
085                    var edit = AssociateEditFactory.getAssociateProgramEdit();
086                    var associateProgramDetail = associateProgram.getLastDetail();
087                    var associateSequence = associateProgramDetail.getAssociateSequence();
088                    var associatePartyContactMechanismSequence = associateProgramDetail.getAssociatePartyContactMechanismSequence();
089                    var associateReferralSequence = associateProgramDetail.getAssociateReferralSequence();
090                    
091                    result.setEdit(edit);
092                    edit.setAssociateProgramName(associateProgramDetail.getAssociateProgramName());
093                    edit.setAssociateSequenceName(associateSequence == null? null: associateSequence.getLastDetail().getSequenceName());
094                    edit.setAssociatePartyContactMechanismSequenceName(associatePartyContactMechanismSequence == null? null: associatePartyContactMechanismSequence.getLastDetail().getSequenceName());
095                    edit.setAssociateReferralSequenceName(associateReferralSequence == null? null: associateReferralSequence.getLastDetail().getSequenceName());
096                    edit.setItemIndirectSalePercent(PercentUtils.getInstance().formatFractionalPercent(associateProgramDetail.getItemIndirectSalePercent()));
097                    edit.setItemDirectSalePercent(PercentUtils.getInstance().formatFractionalPercent(associateProgramDetail.getItemDirectSalePercent()));
098                    edit.setIsDefault(associateProgramDetail.getIsDefault().toString());
099                    edit.setSortOrder(associateProgramDetail.getSortOrder().toString());
100                    
101                    if(associateProgramDescription != null)
102                        edit.setDescription(associateProgramDescription.getDescription());
103                } else {
104                    addExecutionError(ExecutionErrors.EntityLockFailed.name());
105                }
106                
107                result.setEntityLock(getEntityLockTransfer(associateProgram));
108            } else {
109                addExecutionError(ExecutionErrors.UnknownAssociateProgramName.name(), associateProgramName);
110            }
111        } else if(editMode.equals(EditMode.UPDATE)) {
112            var associateProgramName = spec.getAssociateProgramName();
113            var associateProgram = associateControl.getAssociateProgramByNameForUpdate(associateProgramName);
114            
115            if(associateProgram != null) {
116                associateProgramName = edit.getAssociateProgramName();
117                var duplicateAssociateProgram = associateControl.getAssociateProgramByName(associateProgramName);
118                
119                if(duplicateAssociateProgram == null || associateProgram.equals(duplicateAssociateProgram)) {
120                    var sequenceControl = Session.getModelController(SequenceControl.class);
121                    var associateSequenceName = edit.getAssociateSequenceName();
122                    Sequence associateSequence = null;
123                    
124                    if(associateSequenceName != null) {
125                        var sequenceType = sequenceControl.getSequenceTypeByName(SequenceTypes.ASSOCIATE.name());
126                        
127                        if(sequenceType != null) {
128                            associateSequence = sequenceControl.getSequenceByName(sequenceType, associateSequenceName);
129                        } else {
130                            addExecutionError(ExecutionErrors.UnknownSequenceTypeName.name(), SequenceTypes.ASSOCIATE.name());
131                        }
132                    }
133                    
134                    if(associateSequenceName == null || associateSequence != null) {
135                        var associatePartyContactMechanismSequenceName = edit.getAssociatePartyContactMechanismSequenceName();
136                        Sequence associatePartyContactMechanismSequence = null;
137                        
138                        if(associatePartyContactMechanismSequenceName != null) {
139                            var sequenceType = sequenceControl.getSequenceTypeByName(SequenceTypes.ASSOCIATE_PARTY_CONTACT_MECHANISM.name());
140                            
141                            if(sequenceType != null) {
142                                associatePartyContactMechanismSequence = sequenceControl.getSequenceByName(sequenceType, associatePartyContactMechanismSequenceName);
143                            } else {
144                                addExecutionError(ExecutionErrors.UnknownSequenceTypeName.name(), SequenceTypes.ASSOCIATE_PARTY_CONTACT_MECHANISM.name());
145                            }
146                        }
147                        
148                        if(associatePartyContactMechanismSequenceName == null || associatePartyContactMechanismSequence != null) {
149                            var associateReferralSequenceName = edit.getAssociateReferralSequenceName();
150                            Sequence associateReferralSequence = null;
151                            
152                            if(associateReferralSequenceName != null) {
153                                var sequenceType = sequenceControl.getSequenceTypeByName(SequenceTypes.ASSOCIATE_REFERRAL.name());
154                                
155                                if(sequenceType != null) {
156                                    associateReferralSequence = sequenceControl.getSequenceByName(sequenceType, associateReferralSequenceName);
157                                } else {
158                                    addExecutionError(ExecutionErrors.UnknownSequenceTypeName.name(), SequenceTypes.ASSOCIATE_REFERRAL.name());
159                                }
160                            }
161                            
162                            if(associateReferralSequenceName == null || associateReferralSequence != null) {
163                                if(lockEntityForUpdate(associateProgram)) {
164                                    try {
165                                        var partyPK = getPartyPK();
166                                        var strItemIndirectSalePercent = edit.getItemIndirectSalePercent();
167                                        var strItemDirectSalePercent = edit.getItemDirectSalePercent();
168                                        var associateProgramDetailValue = associateControl.getAssociateProgramDetailValueForUpdate(associateProgram);
169                                        var associateProgramDescription = associateControl.getAssociateProgramDescriptionForUpdate(associateProgram, getPreferredLanguage());
170                                        var description = edit.getDescription();
171                                        
172                                        associateProgramDetailValue.setAssociateProgramName(edit.getAssociateProgramName());
173                                        associateProgramDetailValue.setAssociateSequencePK(associateSequence == null? null: associateSequence.getPrimaryKey());
174                                        associateProgramDetailValue.setAssociatePartyContactMechanismSequencePK(associatePartyContactMechanismSequence == null? null: associatePartyContactMechanismSequence.getPrimaryKey());
175                                        associateProgramDetailValue.setAssociateReferralSequencePK(associateReferralSequence == null? null: associateReferralSequence.getPrimaryKey());
176                                        associateProgramDetailValue.setItemIndirectSalePercent(strItemIndirectSalePercent == null? null: Integer.valueOf(strItemIndirectSalePercent));
177                                        associateProgramDetailValue.setItemDirectSalePercent(strItemDirectSalePercent == null? null: Integer.valueOf(strItemDirectSalePercent));
178                                        associateProgramDetailValue.setIsDefault(Boolean.valueOf(edit.getIsDefault()));
179                                        associateProgramDetailValue.setSortOrder(Integer.valueOf(edit.getSortOrder()));
180                                        
181                                        associateControl.updateAssociateProgramFromValue(associateProgramDetailValue, partyPK);
182                                        
183                                        if(associateProgramDescription == null && description != null) {
184                                            associateControl.createAssociateProgramDescription(associateProgram, getPreferredLanguage(), description, partyPK);
185                                        } else if(associateProgramDescription != null && description == null) {
186                                            associateControl.deleteAssociateProgramDescription(associateProgramDescription, partyPK);
187                                        } else if(associateProgramDescription != null && description != null) {
188                                            var associateProgramDescriptionValue = associateControl.getAssociateProgramDescriptionValue(associateProgramDescription);
189                                            
190                                            associateProgramDescriptionValue.setDescription(description);
191                                            associateControl.updateAssociateProgramDescriptionFromValue(associateProgramDescriptionValue, partyPK);
192                                        }
193                                    } finally {
194                                        unlockEntity(associateProgram);
195                                    }
196                                } else {
197                                    addExecutionError(ExecutionErrors.EntityLockStale.name());
198                                }
199                            } else {
200                                addExecutionError(ExecutionErrors.UnknownSequenceName.name(), associateReferralSequenceName);
201                            }
202                        } else {
203                            addExecutionError(ExecutionErrors.UnknownSequenceName.name(), associatePartyContactMechanismSequenceName);
204                        }
205                    } else {
206                        addExecutionError(ExecutionErrors.UnknownSequenceName.name(), associateSequenceName);
207                    }
208                } else {
209                    addExecutionError(ExecutionErrors.DuplicateAssociateProgramName.name(), associateProgramName);
210                }
211            } else {
212                addExecutionError(ExecutionErrors.UnknownAssociateProgramName.name(), associateProgramName);
213            }
214        }
215        
216        return result;
217    }
218    
219}