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.string.PercentUtils;
036import java.util.ArrayList;
037import java.util.List;
038import javax.enterprise.context.Dependent;
039import javax.inject.Inject;
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    @Inject
067    AssociateControl associateControl;
068
069    @Inject
070    SequenceControl sequenceControl;
071
072    
073    /** Creates a new instance of EditAssociateProgramCommand */
074    public EditAssociateProgramCommand() {
075        super(null, SPEC_FIELD_DEFINITIONS, EDIT_FIELD_DEFINITIONS);
076    }
077    
078    @Override
079    protected BaseResult execute() {
080        var result = AssociateResultFactory.getEditAssociateProgramResult();
081        
082        if(editMode.equals(EditMode.LOCK)) {
083            var associateProgramName = spec.getAssociateProgramName();
084            var associateProgram = associateControl.getAssociateProgramByName(associateProgramName);
085            
086            if(associateProgram != null) {
087                result.setAssociateProgram(associateControl.getAssociateProgramTransfer(getUserVisit(), associateProgram));
088                
089                if(lockEntity(associateProgram)) {
090                    var associateProgramDescription = associateControl.getAssociateProgramDescription(associateProgram, getPreferredLanguage());
091                    var edit = AssociateEditFactory.getAssociateProgramEdit();
092                    var associateProgramDetail = associateProgram.getLastDetail();
093                    var associateSequence = associateProgramDetail.getAssociateSequence();
094                    var associatePartyContactMechanismSequence = associateProgramDetail.getAssociatePartyContactMechanismSequence();
095                    var associateReferralSequence = associateProgramDetail.getAssociateReferralSequence();
096                    
097                    result.setEdit(edit);
098                    edit.setAssociateProgramName(associateProgramDetail.getAssociateProgramName());
099                    edit.setAssociateSequenceName(associateSequence == null? null: associateSequence.getLastDetail().getSequenceName());
100                    edit.setAssociatePartyContactMechanismSequenceName(associatePartyContactMechanismSequence == null? null: associatePartyContactMechanismSequence.getLastDetail().getSequenceName());
101                    edit.setAssociateReferralSequenceName(associateReferralSequence == null? null: associateReferralSequence.getLastDetail().getSequenceName());
102                    edit.setItemIndirectSalePercent(PercentUtils.getInstance().formatFractionalPercent(associateProgramDetail.getItemIndirectSalePercent()));
103                    edit.setItemDirectSalePercent(PercentUtils.getInstance().formatFractionalPercent(associateProgramDetail.getItemDirectSalePercent()));
104                    edit.setIsDefault(associateProgramDetail.getIsDefault().toString());
105                    edit.setSortOrder(associateProgramDetail.getSortOrder().toString());
106                    
107                    if(associateProgramDescription != null)
108                        edit.setDescription(associateProgramDescription.getDescription());
109                } else {
110                    addExecutionError(ExecutionErrors.EntityLockFailed.name());
111                }
112                
113                result.setEntityLock(getEntityLockTransfer(associateProgram));
114            } else {
115                addExecutionError(ExecutionErrors.UnknownAssociateProgramName.name(), associateProgramName);
116            }
117        } else if(editMode.equals(EditMode.UPDATE)) {
118            var associateProgramName = spec.getAssociateProgramName();
119            var associateProgram = associateControl.getAssociateProgramByNameForUpdate(associateProgramName);
120            
121            if(associateProgram != null) {
122                associateProgramName = edit.getAssociateProgramName();
123                var duplicateAssociateProgram = associateControl.getAssociateProgramByName(associateProgramName);
124                
125                if(duplicateAssociateProgram == null || associateProgram.equals(duplicateAssociateProgram)) {
126                    var associateSequenceName = edit.getAssociateSequenceName();
127                    Sequence associateSequence = null;
128                    
129                    if(associateSequenceName != null) {
130                        var sequenceType = sequenceControl.getSequenceTypeByName(SequenceTypes.ASSOCIATE.name());
131                        
132                        if(sequenceType != null) {
133                            associateSequence = sequenceControl.getSequenceByName(sequenceType, associateSequenceName);
134                        } else {
135                            addExecutionError(ExecutionErrors.UnknownSequenceTypeName.name(), SequenceTypes.ASSOCIATE.name());
136                        }
137                    }
138                    
139                    if(associateSequenceName == null || associateSequence != null) {
140                        var associatePartyContactMechanismSequenceName = edit.getAssociatePartyContactMechanismSequenceName();
141                        Sequence associatePartyContactMechanismSequence = null;
142                        
143                        if(associatePartyContactMechanismSequenceName != null) {
144                            var sequenceType = sequenceControl.getSequenceTypeByName(SequenceTypes.ASSOCIATE_PARTY_CONTACT_MECHANISM.name());
145                            
146                            if(sequenceType != null) {
147                                associatePartyContactMechanismSequence = sequenceControl.getSequenceByName(sequenceType, associatePartyContactMechanismSequenceName);
148                            } else {
149                                addExecutionError(ExecutionErrors.UnknownSequenceTypeName.name(), SequenceTypes.ASSOCIATE_PARTY_CONTACT_MECHANISM.name());
150                            }
151                        }
152                        
153                        if(associatePartyContactMechanismSequenceName == null || associatePartyContactMechanismSequence != null) {
154                            var associateReferralSequenceName = edit.getAssociateReferralSequenceName();
155                            Sequence associateReferralSequence = null;
156                            
157                            if(associateReferralSequenceName != null) {
158                                var sequenceType = sequenceControl.getSequenceTypeByName(SequenceTypes.ASSOCIATE_REFERRAL.name());
159                                
160                                if(sequenceType != null) {
161                                    associateReferralSequence = sequenceControl.getSequenceByName(sequenceType, associateReferralSequenceName);
162                                } else {
163                                    addExecutionError(ExecutionErrors.UnknownSequenceTypeName.name(), SequenceTypes.ASSOCIATE_REFERRAL.name());
164                                }
165                            }
166                            
167                            if(associateReferralSequenceName == null || associateReferralSequence != null) {
168                                if(lockEntityForUpdate(associateProgram)) {
169                                    try {
170                                        var partyPK = getPartyPK();
171                                        var strItemIndirectSalePercent = edit.getItemIndirectSalePercent();
172                                        var strItemDirectSalePercent = edit.getItemDirectSalePercent();
173                                        var associateProgramDetailValue = associateControl.getAssociateProgramDetailValueForUpdate(associateProgram);
174                                        var associateProgramDescription = associateControl.getAssociateProgramDescriptionForUpdate(associateProgram, getPreferredLanguage());
175                                        var description = edit.getDescription();
176                                        
177                                        associateProgramDetailValue.setAssociateProgramName(edit.getAssociateProgramName());
178                                        associateProgramDetailValue.setAssociateSequencePK(associateSequence == null? null: associateSequence.getPrimaryKey());
179                                        associateProgramDetailValue.setAssociatePartyContactMechanismSequencePK(associatePartyContactMechanismSequence == null? null: associatePartyContactMechanismSequence.getPrimaryKey());
180                                        associateProgramDetailValue.setAssociateReferralSequencePK(associateReferralSequence == null? null: associateReferralSequence.getPrimaryKey());
181                                        associateProgramDetailValue.setItemIndirectSalePercent(strItemIndirectSalePercent == null? null: Integer.valueOf(strItemIndirectSalePercent));
182                                        associateProgramDetailValue.setItemDirectSalePercent(strItemDirectSalePercent == null? null: Integer.valueOf(strItemDirectSalePercent));
183                                        associateProgramDetailValue.setIsDefault(Boolean.valueOf(edit.getIsDefault()));
184                                        associateProgramDetailValue.setSortOrder(Integer.valueOf(edit.getSortOrder()));
185                                        
186                                        associateControl.updateAssociateProgramFromValue(associateProgramDetailValue, partyPK);
187                                        
188                                        if(associateProgramDescription == null && description != null) {
189                                            associateControl.createAssociateProgramDescription(associateProgram, getPreferredLanguage(), description, partyPK);
190                                        } else if(associateProgramDescription != null && description == null) {
191                                            associateControl.deleteAssociateProgramDescription(associateProgramDescription, partyPK);
192                                        } else if(associateProgramDescription != null && description != null) {
193                                            var associateProgramDescriptionValue = associateControl.getAssociateProgramDescriptionValue(associateProgramDescription);
194                                            
195                                            associateProgramDescriptionValue.setDescription(description);
196                                            associateControl.updateAssociateProgramDescriptionFromValue(associateProgramDescriptionValue, partyPK);
197                                        }
198                                    } finally {
199                                        unlockEntity(associateProgram);
200                                    }
201                                } else {
202                                    addExecutionError(ExecutionErrors.EntityLockStale.name());
203                                }
204                            } else {
205                                addExecutionError(ExecutionErrors.UnknownSequenceName.name(), associateReferralSequenceName);
206                            }
207                        } else {
208                            addExecutionError(ExecutionErrors.UnknownSequenceName.name(), associatePartyContactMechanismSequenceName);
209                        }
210                    } else {
211                        addExecutionError(ExecutionErrors.UnknownSequenceName.name(), associateSequenceName);
212                    }
213                } else {
214                    addExecutionError(ExecutionErrors.DuplicateAssociateProgramName.name(), associateProgramName);
215                }
216            } else {
217                addExecutionError(ExecutionErrors.UnknownAssociateProgramName.name(), associateProgramName);
218            }
219        }
220        
221        return result;
222    }
223    
224}