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