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.model.control.order.server.search;
018
019import static com.echothree.model.jooq.server.keys.order.OrderForeignKeys.ORDERS_ACTIVE_DETAIL_FK;
020import static com.echothree.model.jooq.server.keys.workflow.WorkflowForeignKeys.WORKFLOW_ENTITY_STATUSES_ENTITY_INSTANCE_FK;
021import static com.echothree.model.jooq.server.tables.core.EntityInstances.EntityInstances;
022import static com.echothree.model.jooq.server.tables.order.OrderDetails.OrderDetails;
023import static com.echothree.model.jooq.server.tables.order.Orders.Orders;
024import static com.echothree.model.jooq.server.tables.workflow.WorkflowEntityStatuses.WorkflowEntityStatuses;
025import com.echothree.model.control.core.common.ComponentVendors;
026import com.echothree.model.control.core.common.EntityTypes;
027import com.echothree.model.control.core.server.control.EntityInstanceControl;
028import com.echothree.model.control.order.server.control.OrderAliasControl;
029import com.echothree.model.control.order.server.control.OrderControl;
030import com.echothree.model.control.search.server.search.BaseSearchEvaluator;
031import com.echothree.model.control.search.server.search.EntityInstancePKHolder;
032import com.echothree.model.data.accounting.server.entity.Currency;
033import com.echothree.model.data.cancellationpolicy.server.entity.CancellationPolicy;
034import com.echothree.model.data.order.server.entity.Order;
035import com.echothree.model.data.order.server.entity.OrderAliasType;
036import com.echothree.model.data.order.server.entity.OrderPriority;
037import com.echothree.model.data.order.server.entity.OrderType;
038import com.echothree.model.data.returnpolicy.server.entity.ReturnPolicy;
039import com.echothree.model.data.search.server.entity.SearchDefaultOperator;
040import com.echothree.model.data.search.server.entity.SearchSortDirection;
041import com.echothree.model.data.search.server.entity.SearchSortOrder;
042import com.echothree.model.data.search.server.entity.SearchType;
043import com.echothree.model.data.term.server.entity.Term;
044import com.echothree.model.data.user.server.entity.UserVisit;
045import com.echothree.model.data.workflow.server.entity.WorkflowStep;
046import com.echothree.util.server.message.ExecutionErrorAccumulator;
047import com.echothree.util.server.persistence.Session;
048
049public class OrderSearchEvaluator
050        extends BaseSearchEvaluator {
051    
052    protected OrderType orderType;
053    private WorkflowStep orderStatusWorkflowStep;
054    private String orderName;
055    private OrderAliasType orderAliasType;
056    private String alias;
057    private OrderPriority orderPriority;
058    private Currency currency;
059    private Term term;
060    private String reference;
061    private CancellationPolicy cancellationPolicy;
062    private ReturnPolicy returnPolicy;
063    
064    protected OrderSearchEvaluator(UserVisit userVisit, SearchType searchType, SearchDefaultOperator searchDefaultOperator, SearchSortOrder searchSortOrder,
065            SearchSortDirection searchSortDirection, OrderType orderType) {
066        super(userVisit, searchDefaultOperator, searchType, searchSortOrder, searchSortDirection, null, ComponentVendors.ECHO_THREE.name(),
067                EntityTypes.Order.name(), null, null, null);
068        
069        this.orderType = orderType;
070    }
071    
072    public WorkflowStep getOrderStatusWorkflowStep() {
073        return orderStatusWorkflowStep;
074    }
075
076    public void setOrderStatusWorkflowStep(WorkflowStep orderStatusWorkflowStep) {
077        this.orderStatusWorkflowStep = orderStatusWorkflowStep;
078    }
079    
080    public String getOrderName() {
081        return orderName;
082    }
083
084    public void setOrderName(String orderName) {
085        this.orderName = orderName;
086    }
087
088    public OrderAliasType getOrderAliasType() {
089        return orderAliasType;
090    }
091
092    public void setOrderAliasType(OrderAliasType orderAliasType) {
093        this.orderAliasType = orderAliasType;
094    }
095
096    public String getAlias() {
097        return alias;
098    }
099
100    public void setAlias(String alias) {
101        this.alias = alias;
102    }
103    
104    public OrderPriority getOrderPriority() {
105        return orderPriority;
106    }
107
108    public void setOrderPriority(OrderPriority orderPriority) {
109        this.orderPriority = orderPriority;
110    }
111
112    public Currency getCurrency() {
113        return currency;
114    }
115
116    public void setCurrency(Currency currency) {
117        this.currency = currency;
118    }
119
120    public Term getTerm() {
121        return term;
122    }
123
124    public void setTerm(Term term) {
125        this.term = term;
126    }
127
128    public String getReference() {
129        return reference;
130    }
131
132    public void setReference(String reference) {
133        this.reference = reference;
134    }
135
136    public CancellationPolicy getCancellationPolicy() {
137        return cancellationPolicy;
138    }
139
140    public void setCancellationPolicy(CancellationPolicy cancellationPolicy) {
141        this.cancellationPolicy = cancellationPolicy;
142    }
143
144    public ReturnPolicy getReturnPolicy() {
145        return returnPolicy;
146    }
147
148    public void setReturnPolicy(ReturnPolicy returnPolicy) {
149        this.returnPolicy = returnPolicy;
150    }
151
152    /** Counts the number of search parameters, not including orderType. */
153    @Override
154    protected int countParameters() {
155        return super.countParameters() + (orderStatusWorkflowStep == null ? 0 : 1) + (orderName == null ? 0 : 1) + (orderAliasType == null ? 0 : 1)
156                + (alias == null ? 0 : 1) + (orderPriority == null ? 0 : 1) + (currency == null ? 0 : 1) + (term == null ? 0 : 1) + (reference == null ? 0 : 1)
157                + (cancellationPolicy == null ? 0 : 1) + (returnPolicy == null ? 0 : 1);
158    }
159
160    public EntityInstancePKHolder getEntityInstancePKHolderByOrderType(OrderType orderType) {
161        var query = session.getDslContext()
162                .select(EntityInstances.ENTITY_INSTANCE)
163                .from(EntityInstances)
164                .join(Orders).on(Orders.ORDER.cast(Long.class).eq(EntityInstances.ENTITY_UNIQUE))
165                .join(OrderDetails).onKey(ORDERS_ACTIVE_DETAIL_FK)
166                .where(OrderDetails.ORDER_TYPE.eq(orderType.getPrimaryKey()),
167                        EntityInstances.ENTITY_TYPE.eq(entityType.getPrimaryKey()));
168
169        return getEntityInstancePKHolderFromQuery(query);
170    }
171    
172    public EntityInstancePKHolder getEntityInstancePKHolderByOrderStatusWorkflowStep(WorkflowStep orderStatusWorkflowStep) {
173        var query = session.getDslContext()
174                .select(EntityInstances.ENTITY_INSTANCE)
175                .from(EntityInstances)
176                .join(Orders).on(Orders.ORDER.cast(Long.class).eq(EntityInstances.ENTITY_UNIQUE))
177                .join(OrderDetails).onKey(ORDERS_ACTIVE_DETAIL_FK)
178                .join(WorkflowEntityStatuses).onKey(WORKFLOW_ENTITY_STATUSES_ENTITY_INSTANCE_FK)
179                .where(OrderDetails.ORDER_TYPE.eq(orderType.getPrimaryKey()),
180                        EntityInstances.ENTITY_TYPE.eq(entityType.getPrimaryKey()),
181                        WorkflowEntityStatuses.WORKFLOW_STEP.eq(orderStatusWorkflowStep.getPrimaryKey()),
182                        WorkflowEntityStatuses.THRU_TIME.eq(Session.MAX_TIME));
183
184        return getEntityInstancePKHolderFromQuery(query);
185    }
186 
187    public EntityInstancePKHolder getEntityInstancePKHolderByOrderPriority(OrderPriority orderPriority) {
188        var query = session.getDslContext()
189                .select(EntityInstances.ENTITY_INSTANCE)
190                .from(EntityInstances)
191                .join(Orders).on(Orders.ORDER.cast(Long.class).eq(EntityInstances.ENTITY_UNIQUE))
192                .join(OrderDetails).onKey(ORDERS_ACTIVE_DETAIL_FK)
193                .where(OrderDetails.ORDER_TYPE.eq(orderType.getPrimaryKey()),
194                        OrderDetails.ORDER_PRIORITY.eq(orderPriority.getPrimaryKey()),
195                        EntityInstances.ENTITY_TYPE.eq(entityType.getPrimaryKey()));
196
197        return getEntityInstancePKHolderFromQuery(query);
198    }
199    
200    public EntityInstancePKHolder getEntityInstancePKHolderByCurrency(Currency currency) {
201        var query = session.getDslContext()
202                .select(EntityInstances.ENTITY_INSTANCE)
203                .from(EntityInstances)
204                .join(Orders).on(Orders.ORDER.cast(Long.class).eq(EntityInstances.ENTITY_UNIQUE))
205                .join(OrderDetails).onKey(ORDERS_ACTIVE_DETAIL_FK)
206                .where(OrderDetails.ORDER_TYPE.eq(orderType.getPrimaryKey()),
207                        OrderDetails.CURRENCY.eq(currency.getPrimaryKey()),
208                        EntityInstances.ENTITY_TYPE.eq(entityType.getPrimaryKey()));
209
210        return getEntityInstancePKHolderFromQuery(query);
211    }
212    
213    public EntityInstancePKHolder getEntityInstancePKHolderByTerm(Term term) {
214        var query = session.getDslContext()
215                .select(EntityInstances.ENTITY_INSTANCE)
216                .from(EntityInstances)
217                .join(Orders).on(Orders.ORDER.cast(Long.class).eq(EntityInstances.ENTITY_UNIQUE))
218                .join(OrderDetails).onKey(ORDERS_ACTIVE_DETAIL_FK)
219                .where(OrderDetails.ORDER_TYPE.eq(orderType.getPrimaryKey()),
220                        OrderDetails.TERM.eq(term.getPrimaryKey()),
221                        EntityInstances.ENTITY_TYPE.eq(entityType.getPrimaryKey()));
222
223        return getEntityInstancePKHolderFromQuery(query);
224    }
225    
226    public EntityInstancePKHolder getEntityInstancePKHolderByReference(String reference) {
227        var query = session.getDslContext()
228                .select(EntityInstances.ENTITY_INSTANCE)
229                .from(EntityInstances)
230                .join(Orders).on(Orders.ORDER.cast(Long.class).eq(EntityInstances.ENTITY_UNIQUE))
231                .join(OrderDetails).onKey(ORDERS_ACTIVE_DETAIL_FK)
232                .where(OrderDetails.ORDER_TYPE.eq(orderType.getPrimaryKey()),
233                        OrderDetails.REFERENCE.eq(reference),
234                        EntityInstances.ENTITY_TYPE.eq(entityType.getPrimaryKey()));
235
236        return getEntityInstancePKHolderFromQuery(query);
237    }
238    
239    public EntityInstancePKHolder getEntityInstancePKHolderByCancellationPolicy(CancellationPolicy cancellationPolicy) {
240        var query = session.getDslContext()
241                .select(EntityInstances.ENTITY_INSTANCE)
242                .from(EntityInstances)
243                .join(Orders).on(Orders.ORDER.cast(Long.class).eq(EntityInstances.ENTITY_UNIQUE))
244                .join(OrderDetails).onKey(ORDERS_ACTIVE_DETAIL_FK)
245                .where(OrderDetails.ORDER_TYPE.eq(orderType.getPrimaryKey()),
246                        OrderDetails.CANCELLATION_POLICY.eq(cancellationPolicy.getPrimaryKey()),
247                        EntityInstances.ENTITY_TYPE.eq(entityType.getPrimaryKey()));
248
249        return getEntityInstancePKHolderFromQuery(query);
250    }
251    
252    public EntityInstancePKHolder getEntityInstancePKHolderByReturnPolicy(ReturnPolicy returnPolicy) {
253        var query = session.getDslContext()
254                .select(EntityInstances.ENTITY_INSTANCE)
255                .from(EntityInstances)
256                .join(Orders).on(Orders.ORDER.cast(Long.class).eq(EntityInstances.ENTITY_UNIQUE))
257                .join(OrderDetails).onKey(ORDERS_ACTIVE_DETAIL_FK)
258                .where(OrderDetails.ORDER_TYPE.eq(orderType.getPrimaryKey()),
259                        OrderDetails.RETURN_POLICY.eq(returnPolicy.getPrimaryKey()),
260                        EntityInstances.ENTITY_TYPE.eq(entityType.getPrimaryKey()));
261
262        return getEntityInstancePKHolderFromQuery(query);
263    }
264    
265    /** Subclasses should override and always call their super's executeSearch() */
266    @Override
267    protected EntityInstancePKHolder executeSearch(final ExecutionErrorAccumulator eea) {
268        EntityInstancePKHolder resultSet = null;
269        var parameterCount = (orderName == null ? 0 : 1) + (alias == null ? 0 : 1);
270
271        if(parameterCount == 0) {
272            resultSet = super.executeSearch(eea);
273            
274            if(orderStatusWorkflowStep != null && (resultSet == null || resultSet.size() > 0)) {
275                var entityInstancePKHolder = getEntityInstancePKHolderByOrderStatusWorkflowStep(orderStatusWorkflowStep);
276
277                if(resultSet == null) {
278                    resultSet = entityInstancePKHolder;
279                } else {
280                    resultSet.retainAll(entityInstancePKHolder);
281                }
282            }
283            
284            if(orderPriority != null && (resultSet == null || resultSet.size() > 0)) {
285                var entityInstancePKHolder = getEntityInstancePKHolderByOrderPriority(orderPriority);
286
287                if(resultSet == null) {
288                    resultSet = entityInstancePKHolder;
289                } else {
290                    resultSet.retainAll(entityInstancePKHolder);
291                }
292            }
293            
294            if(currency != null && (resultSet == null || resultSet.size() > 0)) {
295                var entityInstancePKHolder = getEntityInstancePKHolderByCurrency(currency);
296
297                if(resultSet == null) {
298                    resultSet = entityInstancePKHolder;
299                } else {
300                    resultSet.retainAll(entityInstancePKHolder);
301                }
302            }
303            
304            if(term != null && (resultSet == null || resultSet.size() > 0)) {
305                var entityInstancePKHolder = getEntityInstancePKHolderByTerm(term);
306
307                if(resultSet == null) {
308                    resultSet = entityInstancePKHolder;
309                } else {
310                    resultSet.retainAll(entityInstancePKHolder);
311                }
312            }
313            
314            if(reference != null && (resultSet == null || resultSet.size() > 0)) {
315                var entityInstancePKHolder = getEntityInstancePKHolderByReference(reference);
316
317                if(resultSet == null) {
318                    resultSet = entityInstancePKHolder;
319                } else {
320                    resultSet.retainAll(entityInstancePKHolder);
321                }
322            }
323            
324            if(cancellationPolicy != null && (resultSet == null || resultSet.size() > 0)) {
325                var entityInstancePKHolder = getEntityInstancePKHolderByCancellationPolicy(cancellationPolicy);
326
327                if(resultSet == null) {
328                    resultSet = entityInstancePKHolder;
329                } else {
330                    resultSet.retainAll(entityInstancePKHolder);
331                }
332            }
333            
334            if(returnPolicy != null && (resultSet == null || resultSet.size() > 0)) {
335                var entityInstancePKHolder = getEntityInstancePKHolderByReturnPolicy(returnPolicy);
336
337                if(resultSet == null) {
338                    resultSet = entityInstancePKHolder;
339                } else {
340                    resultSet.retainAll(entityInstancePKHolder);
341                }
342            }
343            
344            if(countParameters() == 0 && (resultSet == null || resultSet.size() > 0)) {
345                var entityInstancePKHolder = getEntityInstancePKHolderByOrderType(orderType);
346
347                if(resultSet == null) {
348                    resultSet = entityInstancePKHolder;
349                } else {
350                    resultSet.retainAll(entityInstancePKHolder);
351                }
352            }
353        } else {
354            Order order = null;
355
356            if(parameterCount == 1) {
357                var orderAliasControl = Session.getModelController(OrderAliasControl.class);
358
359                if(orderAliasType == null) {
360                    orderAliasType = orderAliasControl.getDefaultOrderAliasType(orderType);
361                }
362
363                if(orderAliasType != null) {
364                    var orderAlias = orderAliasControl.getOrderAliasByAlias(orderAliasType, alias);
365                    
366                    order = orderAlias == null ? null : orderAlias.getOrder();
367                }
368
369                if(orderName != null) {
370                    var orderControl = Session.getModelController(OrderControl.class);
371
372                    order = orderControl.getOrderByName(orderType, orderName);
373                }
374
375                if(order != null) {
376                    var entityInstanceControl = Session.getModelController(EntityInstanceControl.class);
377
378                    resultSet = new EntityInstancePKHolder(1);
379                    resultSet.add(entityInstanceControl.getEntityInstanceByBasePK(order.getPrimaryKey()).getPrimaryKey(), null);
380                }
381            }
382        }
383        
384        return resultSet;
385    }
386
387}