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.model.control.shipment.server;
018
019import com.echothree.model.control.core.common.EventTypes;
020import com.echothree.model.control.shipment.common.choice.ShipmentAliasTypeChoicesBean;
021import com.echothree.model.control.shipment.common.choice.ShipmentTimeTypeChoicesBean;
022import com.echothree.model.control.shipment.common.choice.ShipmentTypeChoicesBean;
023import com.echothree.model.control.shipment.common.transfer.ShipmentAliasTransfer;
024import com.echothree.model.control.shipment.common.transfer.ShipmentAliasTypeDescriptionTransfer;
025import com.echothree.model.control.shipment.common.transfer.ShipmentAliasTypeTransfer;
026import com.echothree.model.control.shipment.common.transfer.ShipmentTimeTransfer;
027import com.echothree.model.control.shipment.common.transfer.ShipmentTimeTypeDescriptionTransfer;
028import com.echothree.model.control.shipment.common.transfer.ShipmentTimeTypeTransfer;
029import com.echothree.model.control.shipment.common.transfer.ShipmentTransfer;
030import com.echothree.model.control.shipment.common.transfer.ShipmentTypeDescriptionTransfer;
031import com.echothree.model.control.shipment.common.transfer.ShipmentTypeShippingMethodTransfer;
032import com.echothree.model.control.shipment.common.transfer.ShipmentTypeTransfer;
033import com.echothree.model.control.shipment.server.control.BaseShipmentControl;
034import com.echothree.model.control.shipment.server.transfer.ShipmentAliasTransferCache;
035import com.echothree.model.control.shipment.server.transfer.ShipmentAliasTypeDescriptionTransferCache;
036import com.echothree.model.control.shipment.server.transfer.ShipmentAliasTypeTransferCache;
037import com.echothree.model.control.shipment.server.transfer.ShipmentTimeTransferCache;
038import com.echothree.model.control.shipment.server.transfer.ShipmentTimeTypeDescriptionTransferCache;
039import com.echothree.model.control.shipment.server.transfer.ShipmentTimeTypeTransferCache;
040import com.echothree.model.control.shipment.server.transfer.ShipmentTypeDescriptionTransferCache;
041import com.echothree.model.control.shipment.server.transfer.ShipmentTypeShippingMethodTransferCache;
042import com.echothree.model.control.shipment.server.transfer.ShipmentTypeTransferCache;
043import com.echothree.model.data.contact.server.entity.PartyContactMechanism;
044import com.echothree.model.data.party.server.entity.Language;
045import com.echothree.model.data.sequence.common.pk.SequenceTypePK;
046import com.echothree.model.data.sequence.server.entity.SequenceType;
047import com.echothree.model.data.shipment.common.pk.ShipmentAliasTypePK;
048import com.echothree.model.data.shipment.common.pk.ShipmentPK;
049import com.echothree.model.data.shipment.common.pk.ShipmentTimeTypePK;
050import com.echothree.model.data.shipment.common.pk.ShipmentTypePK;
051import com.echothree.model.data.shipment.server.entity.Shipment;
052import com.echothree.model.data.shipment.server.entity.ShipmentAlias;
053import com.echothree.model.data.shipment.server.entity.ShipmentAliasType;
054import com.echothree.model.data.shipment.server.entity.ShipmentAliasTypeDescription;
055import com.echothree.model.data.shipment.server.entity.ShipmentAliasTypeDetail;
056import com.echothree.model.data.shipment.server.entity.ShipmentTime;
057import com.echothree.model.data.shipment.server.entity.ShipmentTimeType;
058import com.echothree.model.data.shipment.server.entity.ShipmentTimeTypeDescription;
059import com.echothree.model.data.shipment.server.entity.ShipmentTimeTypeDetail;
060import com.echothree.model.data.shipment.server.entity.ShipmentType;
061import com.echothree.model.data.shipment.server.entity.ShipmentTypeDescription;
062import com.echothree.model.data.shipment.server.entity.ShipmentTypeDetail;
063import com.echothree.model.data.shipment.server.entity.ShipmentTypeShippingMethod;
064import com.echothree.model.data.shipment.server.factory.ShipmentAliasFactory;
065import com.echothree.model.data.shipment.server.factory.ShipmentAliasTypeDescriptionFactory;
066import com.echothree.model.data.shipment.server.factory.ShipmentAliasTypeDetailFactory;
067import com.echothree.model.data.shipment.server.factory.ShipmentAliasTypeFactory;
068import com.echothree.model.data.shipment.server.factory.ShipmentTimeFactory;
069import com.echothree.model.data.shipment.server.factory.ShipmentTimeTypeDescriptionFactory;
070import com.echothree.model.data.shipment.server.factory.ShipmentTimeTypeDetailFactory;
071import com.echothree.model.data.shipment.server.factory.ShipmentTimeTypeFactory;
072import com.echothree.model.data.shipment.server.factory.ShipmentTypeDescriptionFactory;
073import com.echothree.model.data.shipment.server.factory.ShipmentTypeDetailFactory;
074import com.echothree.model.data.shipment.server.factory.ShipmentTypeFactory;
075import com.echothree.model.data.shipment.server.factory.ShipmentTypeShippingMethodFactory;
076import com.echothree.model.data.shipment.server.value.ShipmentAliasTypeDescriptionValue;
077import com.echothree.model.data.shipment.server.value.ShipmentAliasTypeDetailValue;
078import com.echothree.model.data.shipment.server.value.ShipmentAliasValue;
079import com.echothree.model.data.shipment.server.value.ShipmentTimeTypeDescriptionValue;
080import com.echothree.model.data.shipment.server.value.ShipmentTimeTypeDetailValue;
081import com.echothree.model.data.shipment.server.value.ShipmentTimeValue;
082import com.echothree.model.data.shipment.server.value.ShipmentTypeDescriptionValue;
083import com.echothree.model.data.shipment.server.value.ShipmentTypeDetailValue;
084import com.echothree.model.data.shipment.server.value.ShipmentTypeShippingMethodValue;
085import com.echothree.model.data.shipping.common.pk.ShippingMethodPK;
086import com.echothree.model.data.shipping.server.entity.ShippingMethod;
087import com.echothree.model.data.user.server.entity.UserVisit;
088import com.echothree.model.data.workflow.common.pk.WorkflowEntrancePK;
089import com.echothree.model.data.workflow.common.pk.WorkflowPK;
090import com.echothree.model.data.workflow.server.entity.Workflow;
091import com.echothree.model.data.workflow.server.entity.WorkflowEntrance;
092import com.echothree.util.common.exception.PersistenceDatabaseException;
093import com.echothree.util.common.persistence.BasePK;
094import com.echothree.util.server.persistence.EntityPermission;
095import com.echothree.util.server.persistence.Session;
096import java.sql.PreparedStatement;
097import java.sql.SQLException;
098import java.util.ArrayList;
099import java.util.Collection;
100import java.util.Collections;
101import java.util.HashMap;
102import java.util.HashSet;
103import java.util.Iterator;
104import java.util.List;
105import java.util.Map;
106import java.util.Objects;
107import java.util.Set;
108
109public class ShipmentControl
110        extends BaseShipmentControl {
111    
112    /** Creates a new instance of ShipmentControl */
113    public ShipmentControl() {
114        super();
115    }
116    
117    // --------------------------------------------------------------------------------
118    //   Shipment Types
119    // --------------------------------------------------------------------------------
120
121    public ShipmentType createShipmentType(String shipmentTypeName, ShipmentType parentShipmentType, SequenceType shipmentSequenceType,
122            SequenceType shipmentPackageSequenceType, Workflow shipmentWorkflow, WorkflowEntrance shipmentWorkflowEntrance, Boolean isDefault, Integer sortOrder,
123            BasePK createdBy) {
124        ShipmentType defaultShipmentType = getDefaultShipmentType();
125        boolean defaultFound = defaultShipmentType != null;
126
127        if(defaultFound && isDefault) {
128            ShipmentTypeDetailValue defaultShipmentTypeDetailValue = getDefaultShipmentTypeDetailValueForUpdate();
129
130            defaultShipmentTypeDetailValue.setIsDefault(Boolean.FALSE);
131            updateShipmentTypeFromValue(defaultShipmentTypeDetailValue, false, createdBy);
132        } else if(!defaultFound) {
133            isDefault = Boolean.TRUE;
134        }
135
136        ShipmentType shipmentType = ShipmentTypeFactory.getInstance().create();
137        ShipmentTypeDetail shipmentTypeDetail = ShipmentTypeDetailFactory.getInstance().create(shipmentType, shipmentTypeName, parentShipmentType,
138                shipmentSequenceType, shipmentPackageSequenceType, shipmentWorkflow, shipmentWorkflowEntrance, isDefault, sortOrder, session.START_TIME_LONG,
139                Session.MAX_TIME_LONG);
140
141        // Convert to R/W
142        shipmentType = ShipmentTypeFactory.getInstance().getEntityFromPK(EntityPermission.READ_WRITE,
143                shipmentType.getPrimaryKey());
144        shipmentType.setActiveDetail(shipmentTypeDetail);
145        shipmentType.setLastDetail(shipmentTypeDetail);
146        shipmentType.store();
147
148        sendEvent(shipmentType.getPrimaryKey(), EventTypes.CREATE, null, null, createdBy);
149
150        return shipmentType;
151    }
152
153    private static final Map<EntityPermission, String> getShipmentTypeByNameQueries;
154
155    static {
156        Map<EntityPermission, String> queryMap = new HashMap<>(2);
157
158        queryMap.put(EntityPermission.READ_ONLY,
159                "SELECT _ALL_ " +
160                "FROM shipmenttypes, shipmenttypedetails " +
161                "WHERE shptyp_activedetailid = shptypdt_shipmenttypedetailid " +
162                "AND shptypdt_shipmenttypename = ?");
163        queryMap.put(EntityPermission.READ_WRITE,
164                "SELECT _ALL_ " +
165                "FROM shipmenttypes, shipmenttypedetails " +
166                "WHERE shptyp_activedetailid = shptypdt_shipmenttypedetailid " +
167                "AND shptypdt_shipmenttypename = ? " +
168                "FOR UPDATE");
169        getShipmentTypeByNameQueries = Collections.unmodifiableMap(queryMap);
170    }
171
172    private ShipmentType getShipmentTypeByName(String shipmentTypeName, EntityPermission entityPermission) {
173        return ShipmentTypeFactory.getInstance().getEntityFromQuery(entityPermission, getShipmentTypeByNameQueries, shipmentTypeName);
174    }
175
176    public ShipmentType getShipmentTypeByName(String shipmentTypeName) {
177        return getShipmentTypeByName(shipmentTypeName, EntityPermission.READ_ONLY);
178    }
179
180    public ShipmentType getShipmentTypeByNameForUpdate(String shipmentTypeName) {
181        return getShipmentTypeByName(shipmentTypeName, EntityPermission.READ_WRITE);
182    }
183
184    public ShipmentTypeDetailValue getShipmentTypeDetailValueForUpdate(ShipmentType shipmentType) {
185        return shipmentType == null? null: shipmentType.getLastDetailForUpdate().getShipmentTypeDetailValue().clone();
186    }
187
188    public ShipmentTypeDetailValue getShipmentTypeDetailValueByNameForUpdate(String shipmentTypeName) {
189        return getShipmentTypeDetailValueForUpdate(getShipmentTypeByNameForUpdate(shipmentTypeName));
190    }
191
192    private static final Map<EntityPermission, String> getDefaultShipmentTypeQueries;
193
194    static {
195        Map<EntityPermission, String> queryMap = new HashMap<>(2);
196
197        queryMap.put(EntityPermission.READ_ONLY,
198                "SELECT _ALL_ " +
199                "FROM shipmenttypes, shipmenttypedetails " +
200                "WHERE shptyp_activedetailid = shptypdt_shipmenttypedetailid " +
201                "AND shptypdt_isdefault = 1");
202        queryMap.put(EntityPermission.READ_WRITE,
203                "SELECT _ALL_ " +
204                "FROM shipmenttypes, shipmenttypedetails " +
205                "WHERE shptyp_activedetailid = shptypdt_shipmenttypedetailid " +
206                "AND shptypdt_isdefault = 1 " +
207                "FOR UPDATE");
208        getDefaultShipmentTypeQueries = Collections.unmodifiableMap(queryMap);
209    }
210
211    private ShipmentType getDefaultShipmentType(EntityPermission entityPermission) {
212        return ShipmentTypeFactory.getInstance().getEntityFromQuery(entityPermission, getDefaultShipmentTypeQueries);
213    }
214
215    public ShipmentType getDefaultShipmentType() {
216        return getDefaultShipmentType(EntityPermission.READ_ONLY);
217    }
218
219    public ShipmentType getDefaultShipmentTypeForUpdate() {
220        return getDefaultShipmentType(EntityPermission.READ_WRITE);
221    }
222
223    public ShipmentTypeDetailValue getDefaultShipmentTypeDetailValueForUpdate() {
224        return getDefaultShipmentTypeForUpdate().getLastDetailForUpdate().getShipmentTypeDetailValue().clone();
225    }
226
227    private static final Map<EntityPermission, String> getShipmentTypesQueries;
228
229    static {
230        Map<EntityPermission, String> queryMap = new HashMap<>(2);
231
232        queryMap.put(EntityPermission.READ_ONLY,
233                "SELECT _ALL_ " +
234                "FROM shipmenttypes, shipmenttypedetails " +
235                "WHERE shptyp_activedetailid = shptypdt_shipmenttypedetailid " +
236                "ORDER BY shptypdt_sortorder, shptypdt_shipmenttypename " +
237                "_LIMIT_");
238        queryMap.put(EntityPermission.READ_WRITE,
239                "SELECT _ALL_ " +
240                "FROM shipmenttypes, shipmenttypedetails " +
241                "WHERE shptyp_activedetailid = shptypdt_shipmenttypedetailid " +
242                "FOR UPDATE");
243        getShipmentTypesQueries = Collections.unmodifiableMap(queryMap);
244    }
245
246    private List<ShipmentType> getShipmentTypes(EntityPermission entityPermission) {
247        return ShipmentTypeFactory.getInstance().getEntitiesFromQuery(entityPermission, getShipmentTypesQueries);
248    }
249
250    public List<ShipmentType> getShipmentTypes() {
251        return getShipmentTypes(EntityPermission.READ_ONLY);
252    }
253
254    public List<ShipmentType> getShipmentTypesForUpdate() {
255        return getShipmentTypes(EntityPermission.READ_WRITE);
256    }
257
258    private static final Map<EntityPermission, String> getShipmentTypesByParentShipmentTypeQueries;
259
260    static {
261        Map<EntityPermission, String> queryMap = new HashMap<>(2);
262
263        queryMap.put(EntityPermission.READ_ONLY,
264                "SELECT _ALL_ " +
265                "FROM shipmenttypes, shipmenttypedetails " +
266                "WHERE shptyp_activedetailid = shptypdt_shipmenttypedetailid AND shptypdt_parentshipmenttypeid = ? " +
267                "ORDER BY shptypdt_sortorder, shptypdt_shipmenttypename " +
268                "_LIMIT_");
269        queryMap.put(EntityPermission.READ_WRITE,
270                "SELECT _ALL_ " +
271                "FROM shipmenttypes, shipmenttypedetails " +
272                "WHERE shptyp_activedetailid = shptypdt_shipmenttypedetailid AND shptypdt_parentshipmenttypeid = ? " +
273                "FOR UPDATE");
274        getShipmentTypesByParentShipmentTypeQueries = Collections.unmodifiableMap(queryMap);
275    }
276
277    private List<ShipmentType> getShipmentTypesByParentShipmentType(ShipmentType parentShipmentType,
278            EntityPermission entityPermission) {
279        return ShipmentTypeFactory.getInstance().getEntitiesFromQuery(entityPermission, getShipmentTypesByParentShipmentTypeQueries,
280                parentShipmentType);
281    }
282
283    public List<ShipmentType> getShipmentTypesByParentShipmentType(ShipmentType parentShipmentType) {
284        return getShipmentTypesByParentShipmentType(parentShipmentType, EntityPermission.READ_ONLY);
285    }
286
287    public List<ShipmentType> getShipmentTypesByParentShipmentTypeForUpdate(ShipmentType parentShipmentType) {
288        return getShipmentTypesByParentShipmentType(parentShipmentType, EntityPermission.READ_WRITE);
289    }
290
291    public ShipmentTypeTransfer getShipmentTypeTransfer(UserVisit userVisit, ShipmentType shipmentType) {
292        return getShipmentTransferCaches(userVisit).getShipmentTypeTransferCache().getTransfer(shipmentType);
293    }
294
295    public List<ShipmentTypeTransfer> getShipmentTypeTransfers(UserVisit userVisit) {
296        List<ShipmentType> shipmentTypes = getShipmentTypes();
297        List<ShipmentTypeTransfer> shipmentTypeTransfers = new ArrayList<>(shipmentTypes.size());
298        ShipmentTypeTransferCache shipmentTypeTransferCache = getShipmentTransferCaches(userVisit).getShipmentTypeTransferCache();
299
300        shipmentTypes.forEach((shipmentType) ->
301                shipmentTypeTransfers.add(shipmentTypeTransferCache.getTransfer(shipmentType))
302        );
303
304        return shipmentTypeTransfers;
305    }
306
307    public ShipmentTypeChoicesBean getShipmentTypeChoices(String defaultShipmentTypeChoice,
308            Language language, boolean allowNullChoice) {
309        List<ShipmentType> shipmentTypes = getShipmentTypes();
310        var size = shipmentTypes.size();
311        var labels = new ArrayList<String>(size);
312        var values = new ArrayList<String>(size);
313        String defaultValue = null;
314
315        if(allowNullChoice) {
316            labels.add("");
317            values.add("");
318
319            if(defaultShipmentTypeChoice == null) {
320                defaultValue = "";
321            }
322        }
323
324        for(var shipmentType : shipmentTypes) {
325            ShipmentTypeDetail shipmentTypeDetail = shipmentType.getLastDetail();
326
327            var label = getBestShipmentTypeDescription(shipmentType, language);
328            var value = shipmentTypeDetail.getShipmentTypeName();
329
330            labels.add(label == null? value: label);
331            values.add(value);
332
333            var usingDefaultChoice = defaultShipmentTypeChoice != null && defaultShipmentTypeChoice.equals(value);
334            if(usingDefaultChoice || (defaultValue == null && shipmentTypeDetail.getIsDefault())) {
335                defaultValue = value;
336            }
337        }
338
339        return new ShipmentTypeChoicesBean(labels, values, defaultValue);
340    }
341
342    public boolean isParentShipmentTypeSafe(ShipmentType shipmentType,
343            ShipmentType parentShipmentType) {
344        boolean safe = true;
345
346        if(parentShipmentType != null) {
347            Set<ShipmentType> parentShipmentTypes = new HashSet<>();
348
349            parentShipmentTypes.add(shipmentType);
350            do {
351                if(parentShipmentTypes.contains(parentShipmentType)) {
352                    safe = false;
353                    break;
354                }
355
356                parentShipmentTypes.add(parentShipmentType);
357                parentShipmentType = parentShipmentType.getLastDetail().getParentShipmentType();
358            } while(parentShipmentType != null);
359        }
360
361        return safe;
362    }
363
364    private void updateShipmentTypeFromValue(ShipmentTypeDetailValue shipmentTypeDetailValue, boolean checkDefault,
365            BasePK updatedBy) {
366        if(shipmentTypeDetailValue.hasBeenModified()) {
367            ShipmentType shipmentType = ShipmentTypeFactory.getInstance().getEntityFromPK(EntityPermission.READ_WRITE,
368                     shipmentTypeDetailValue.getShipmentTypePK());
369            ShipmentTypeDetail shipmentTypeDetail = shipmentType.getActiveDetailForUpdate();
370
371            shipmentTypeDetail.setThruTime(session.START_TIME_LONG);
372            shipmentTypeDetail.store();
373
374            ShipmentTypePK shipmentTypePK = shipmentTypeDetail.getShipmentTypePK(); // Not updated
375            String shipmentTypeName = shipmentTypeDetailValue.getShipmentTypeName();
376            ShipmentTypePK parentShipmentTypePK = shipmentTypeDetailValue.getParentShipmentTypePK();
377            SequenceTypePK shipmentSequenceTypePK = shipmentTypeDetailValue.getShipmentSequenceTypePK();
378            SequenceTypePK shipmentPackageSequenceTypePK = shipmentTypeDetailValue.getShipmentPackageSequenceTypePK();
379            WorkflowPK shipmentWorkflowPK = shipmentTypeDetailValue.getShipmentWorkflowPK();
380            WorkflowEntrancePK shipmentWorkflowEntrancePK = shipmentTypeDetailValue.getShipmentWorkflowEntrancePK();
381            Boolean isDefault = shipmentTypeDetailValue.getIsDefault();
382            Integer sortOrder = shipmentTypeDetailValue.getSortOrder();
383
384            if(checkDefault) {
385                ShipmentType defaultShipmentType = getDefaultShipmentType();
386                boolean defaultFound = defaultShipmentType != null && !defaultShipmentType.equals(shipmentType);
387
388                if(isDefault && defaultFound) {
389                    // If I'm the default, and a default already existed...
390                    ShipmentTypeDetailValue defaultShipmentTypeDetailValue = getDefaultShipmentTypeDetailValueForUpdate();
391
392                    defaultShipmentTypeDetailValue.setIsDefault(Boolean.FALSE);
393                    updateShipmentTypeFromValue(defaultShipmentTypeDetailValue, false, updatedBy);
394                } else if(!isDefault && !defaultFound) {
395                    // If I'm not the default, and no other default exists...
396                    isDefault = Boolean.TRUE;
397                }
398            }
399
400            shipmentTypeDetail = ShipmentTypeDetailFactory.getInstance().create(shipmentTypePK, shipmentTypeName, parentShipmentTypePK, shipmentSequenceTypePK,
401                    shipmentPackageSequenceTypePK, shipmentWorkflowPK, shipmentWorkflowEntrancePK, isDefault, sortOrder, session.START_TIME_LONG,
402                    Session.MAX_TIME_LONG);
403
404            shipmentType.setActiveDetail(shipmentTypeDetail);
405            shipmentType.setLastDetail(shipmentTypeDetail);
406
407            sendEvent(shipmentTypePK, EventTypes.MODIFY, null, null, updatedBy);
408        }
409    }
410
411    public void updateShipmentTypeFromValue(ShipmentTypeDetailValue shipmentTypeDetailValue, BasePK updatedBy) {
412        updateShipmentTypeFromValue(shipmentTypeDetailValue, true, updatedBy);
413    }
414
415    private void deleteShipmentType(ShipmentType shipmentType, boolean checkDefault, BasePK deletedBy) {
416        ShipmentTypeDetail shipmentTypeDetail = shipmentType.getLastDetailForUpdate();
417
418        deleteShipmentTypesByParentShipmentType(shipmentType, deletedBy);
419        deleteShipmentTypeDescriptionsByShipmentType(shipmentType, deletedBy);
420        deleteShipmentAliasTypesByShipmentType(shipmentType, deletedBy);
421        // TODO: deleteShipmentsByShipmentType(shipmentType, deletedBy);
422
423        shipmentTypeDetail.setThruTime(session.START_TIME_LONG);
424        shipmentType.setActiveDetail(null);
425        shipmentType.store();
426
427        if(checkDefault) {
428            // Check for default, and pick one if necessary
429            ShipmentType defaultShipmentType = getDefaultShipmentType();
430
431            if(defaultShipmentType == null) {
432                List<ShipmentType> shipmentTypes = getShipmentTypesForUpdate();
433
434                if(!shipmentTypes.isEmpty()) {
435                    Iterator<ShipmentType> iter = shipmentTypes.iterator();
436                    if(iter.hasNext()) {
437                        defaultShipmentType = iter.next();
438                    }
439                    ShipmentTypeDetailValue shipmentTypeDetailValue = Objects.requireNonNull(defaultShipmentType).getLastDetailForUpdate().getShipmentTypeDetailValue().clone();
440
441                    shipmentTypeDetailValue.setIsDefault(Boolean.TRUE);
442                    updateShipmentTypeFromValue(shipmentTypeDetailValue, false, deletedBy);
443                }
444            }
445        }
446
447        sendEvent(shipmentType.getPrimaryKey(), EventTypes.DELETE, null, null, deletedBy);
448    }
449
450    public void deleteShipmentType(ShipmentType shipmentType, BasePK deletedBy) {
451        deleteShipmentType(shipmentType, true, deletedBy);
452    }
453
454    private void deleteShipmentTypes(List<ShipmentType> shipmentTypes, boolean checkDefault, BasePK deletedBy) {
455        shipmentTypes.forEach((shipmentType) -> deleteShipmentType(shipmentType, checkDefault, deletedBy));
456    }
457
458    public void deleteShipmentTypes(List<ShipmentType> shipmentTypes, BasePK deletedBy) {
459        deleteShipmentTypes(shipmentTypes, true, deletedBy);
460    }
461
462    private void deleteShipmentTypesByParentShipmentType(ShipmentType parentShipmentType, BasePK deletedBy) {
463        deleteShipmentTypes(getShipmentTypesByParentShipmentTypeForUpdate(parentShipmentType), false, deletedBy);
464    }
465
466    // --------------------------------------------------------------------------------
467    //   Shipment Type Descriptions
468    // --------------------------------------------------------------------------------
469
470    public ShipmentTypeDescription createShipmentTypeDescription(ShipmentType shipmentType, Language language, String description, BasePK createdBy) {
471        ShipmentTypeDescription shipmentTypeDescription = ShipmentTypeDescriptionFactory.getInstance().create(shipmentType, language, description,
472                session.START_TIME_LONG, Session.MAX_TIME_LONG);
473
474        sendEvent(shipmentType.getPrimaryKey(), EventTypes.MODIFY, shipmentTypeDescription.getPrimaryKey(), EventTypes.CREATE, createdBy);
475
476        return shipmentTypeDescription;
477    }
478
479    private static final Map<EntityPermission, String> getShipmentTypeDescriptionQueries;
480
481    static {
482        Map<EntityPermission, String> queryMap = new HashMap<>(2);
483
484        queryMap.put(EntityPermission.READ_ONLY,
485                "SELECT _ALL_ " +
486                "FROM shipmenttypedescriptions " +
487                "WHERE shptypd_shptyp_shipmenttypeid = ? AND shptypd_lang_languageid = ? AND shptypd_thrutime = ?");
488        queryMap.put(EntityPermission.READ_WRITE,
489                "SELECT _ALL_ " +
490                "FROM shipmenttypedescriptions " +
491                "WHERE shptypd_shptyp_shipmenttypeid = ? AND shptypd_lang_languageid = ? AND shptypd_thrutime = ? " +
492                "FOR UPDATE");
493        getShipmentTypeDescriptionQueries = Collections.unmodifiableMap(queryMap);
494    }
495
496    private ShipmentTypeDescription getShipmentTypeDescription(ShipmentType shipmentType, Language language, EntityPermission entityPermission) {
497        return ShipmentTypeDescriptionFactory.getInstance().getEntityFromQuery(entityPermission, getShipmentTypeDescriptionQueries,
498                shipmentType, language, Session.MAX_TIME);
499    }
500
501    public ShipmentTypeDescription getShipmentTypeDescription(ShipmentType shipmentType, Language language) {
502        return getShipmentTypeDescription(shipmentType, language, EntityPermission.READ_ONLY);
503    }
504
505    public ShipmentTypeDescription getShipmentTypeDescriptionForUpdate(ShipmentType shipmentType, Language language) {
506        return getShipmentTypeDescription(shipmentType, language, EntityPermission.READ_WRITE);
507    }
508
509    public ShipmentTypeDescriptionValue getShipmentTypeDescriptionValue(ShipmentTypeDescription shipmentTypeDescription) {
510        return shipmentTypeDescription == null? null: shipmentTypeDescription.getShipmentTypeDescriptionValue().clone();
511    }
512
513    public ShipmentTypeDescriptionValue getShipmentTypeDescriptionValueForUpdate(ShipmentType shipmentType, Language language) {
514        return getShipmentTypeDescriptionValue(getShipmentTypeDescriptionForUpdate(shipmentType, language));
515    }
516
517    private static final Map<EntityPermission, String> getShipmentTypeDescriptionsByShipmentTypeQueries;
518
519    static {
520        Map<EntityPermission, String> queryMap = new HashMap<>(2);
521
522        queryMap.put(EntityPermission.READ_ONLY,
523                "SELECT _ALL_ " +
524                "FROM shipmenttypedescriptions, languages " +
525                "WHERE shptypd_shptyp_shipmenttypeid = ? AND shptypd_thrutime = ? AND shptypd_lang_languageid = lang_languageid " +
526                "ORDER BY lang_sortorder, lang_languageisoname");
527        queryMap.put(EntityPermission.READ_WRITE,
528                "SELECT _ALL_ " +
529                "FROM shipmenttypedescriptions " +
530                "WHERE shptypd_shptyp_shipmenttypeid = ? AND shptypd_thrutime = ? " +
531                "FOR UPDATE");
532        getShipmentTypeDescriptionsByShipmentTypeQueries = Collections.unmodifiableMap(queryMap);
533    }
534
535    private List<ShipmentTypeDescription> getShipmentTypeDescriptionsByShipmentType(ShipmentType shipmentType, EntityPermission entityPermission) {
536        return ShipmentTypeDescriptionFactory.getInstance().getEntitiesFromQuery(entityPermission, getShipmentTypeDescriptionsByShipmentTypeQueries,
537                shipmentType, Session.MAX_TIME);
538    }
539
540    public List<ShipmentTypeDescription> getShipmentTypeDescriptionsByShipmentType(ShipmentType shipmentType) {
541        return getShipmentTypeDescriptionsByShipmentType(shipmentType, EntityPermission.READ_ONLY);
542    }
543
544    public List<ShipmentTypeDescription> getShipmentTypeDescriptionsByShipmentTypeForUpdate(ShipmentType shipmentType) {
545        return getShipmentTypeDescriptionsByShipmentType(shipmentType, EntityPermission.READ_WRITE);
546    }
547
548    public String getBestShipmentTypeDescription(ShipmentType shipmentType, Language language) {
549        String description;
550        ShipmentTypeDescription shipmentTypeDescription = getShipmentTypeDescription(shipmentType, language);
551
552        if(shipmentTypeDescription == null && !language.getIsDefault()) {
553            shipmentTypeDescription = getShipmentTypeDescription(shipmentType, getPartyControl().getDefaultLanguage());
554        }
555
556        if(shipmentTypeDescription == null) {
557            description = shipmentType.getLastDetail().getShipmentTypeName();
558        } else {
559            description = shipmentTypeDescription.getDescription();
560        }
561
562        return description;
563    }
564
565    public ShipmentTypeDescriptionTransfer getShipmentTypeDescriptionTransfer(UserVisit userVisit, ShipmentTypeDescription shipmentTypeDescription) {
566        return getShipmentTransferCaches(userVisit).getShipmentTypeDescriptionTransferCache().getTransfer(shipmentTypeDescription);
567    }
568
569    public List<ShipmentTypeDescriptionTransfer> getShipmentTypeDescriptionTransfersByShipmentType(UserVisit userVisit, ShipmentType shipmentType) {
570        List<ShipmentTypeDescription> shipmentTypeDescriptions = getShipmentTypeDescriptionsByShipmentType(shipmentType);
571        List<ShipmentTypeDescriptionTransfer> shipmentTypeDescriptionTransfers = new ArrayList<>(shipmentTypeDescriptions.size());
572        ShipmentTypeDescriptionTransferCache shipmentTypeDescriptionTransferCache = getShipmentTransferCaches(userVisit).getShipmentTypeDescriptionTransferCache();
573
574        shipmentTypeDescriptions.forEach((shipmentTypeDescription) ->
575                shipmentTypeDescriptionTransfers.add(shipmentTypeDescriptionTransferCache.getTransfer(shipmentTypeDescription))
576        );
577
578        return shipmentTypeDescriptionTransfers;
579    }
580
581    public void updateShipmentTypeDescriptionFromValue(ShipmentTypeDescriptionValue shipmentTypeDescriptionValue, BasePK updatedBy) {
582        if(shipmentTypeDescriptionValue.hasBeenModified()) {
583            ShipmentTypeDescription shipmentTypeDescription = ShipmentTypeDescriptionFactory.getInstance().getEntityFromPK(EntityPermission.READ_WRITE,
584                    shipmentTypeDescriptionValue.getPrimaryKey());
585
586            shipmentTypeDescription.setThruTime(session.START_TIME_LONG);
587            shipmentTypeDescription.store();
588
589            ShipmentType shipmentType = shipmentTypeDescription.getShipmentType();
590            Language language = shipmentTypeDescription.getLanguage();
591            String description = shipmentTypeDescriptionValue.getDescription();
592
593            shipmentTypeDescription = ShipmentTypeDescriptionFactory.getInstance().create(shipmentType, language, description,
594                    session.START_TIME_LONG, Session.MAX_TIME_LONG);
595
596            sendEvent(shipmentType.getPrimaryKey(), EventTypes.MODIFY, shipmentTypeDescription.getPrimaryKey(), EventTypes.MODIFY, updatedBy);
597        }
598    }
599
600    public void deleteShipmentTypeDescription(ShipmentTypeDescription shipmentTypeDescription, BasePK deletedBy) {
601        shipmentTypeDescription.setThruTime(session.START_TIME_LONG);
602
603        sendEvent(shipmentTypeDescription.getShipmentTypePK(), EventTypes.MODIFY, shipmentTypeDescription.getPrimaryKey(), EventTypes.DELETE, deletedBy);
604
605    }
606
607    public void deleteShipmentTypeDescriptionsByShipmentType(ShipmentType shipmentType, BasePK deletedBy) {
608        List<ShipmentTypeDescription> shipmentTypeDescriptions = getShipmentTypeDescriptionsByShipmentTypeForUpdate(shipmentType);
609
610        shipmentTypeDescriptions.forEach((shipmentTypeDescription) -> 
611                deleteShipmentTypeDescription(shipmentTypeDescription, deletedBy)
612        );
613    }
614
615    // --------------------------------------------------------------------------------
616    //   Shipment Time Types
617    // --------------------------------------------------------------------------------
618
619    public ShipmentTimeType createShipmentTimeType(ShipmentType shipmentType, String shipmentTimeTypeName, Boolean isDefault, Integer sortOrder, BasePK createdBy) {
620        ShipmentTimeType defaultShipmentTimeType = getDefaultShipmentTimeType(shipmentType);
621        boolean defaultFound = defaultShipmentTimeType != null;
622
623        if(defaultFound && isDefault) {
624            ShipmentTimeTypeDetailValue defaultShipmentTimeTypeDetailValue = getDefaultShipmentTimeTypeDetailValueForUpdate(shipmentType);
625
626            defaultShipmentTimeTypeDetailValue.setIsDefault(Boolean.FALSE);
627            updateShipmentTimeTypeFromValue(defaultShipmentTimeTypeDetailValue, false, createdBy);
628        } else if(!defaultFound) {
629            isDefault = Boolean.TRUE;
630        }
631
632        ShipmentTimeType shipmentTimeType = ShipmentTimeTypeFactory.getInstance().create();
633        ShipmentTimeTypeDetail shipmentTimeTypeDetail = ShipmentTimeTypeDetailFactory.getInstance().create(shipmentTimeType, shipmentType, shipmentTimeTypeName, isDefault,
634                sortOrder, session.START_TIME_LONG, Session.MAX_TIME_LONG);
635
636        // Convert to R/W
637        shipmentTimeType = ShipmentTimeTypeFactory.getInstance().getEntityFromPK(EntityPermission.READ_WRITE,
638                shipmentTimeType.getPrimaryKey());
639        shipmentTimeType.setActiveDetail(shipmentTimeTypeDetail);
640        shipmentTimeType.setLastDetail(shipmentTimeTypeDetail);
641        shipmentTimeType.store();
642
643        sendEvent(shipmentTimeType.getPrimaryKey(), EventTypes.CREATE, null, null, createdBy);
644
645        return shipmentTimeType;
646    }
647
648    private static final Map<EntityPermission, String> getShipmentTimeTypeByNameQueries;
649
650    static {
651        Map<EntityPermission, String> queryMap = new HashMap<>(2);
652
653        queryMap.put(EntityPermission.READ_ONLY,
654                "SELECT _ALL_ " +
655                "FROM shipmenttimetypes, shipmenttimetypedetails " +
656                "WHERE shptimtyp_activedetailid = shptimtypdt_shipmenttimetypedetailid " +
657                "AND shptimtypdt_shptyp_shipmenttypeid = ? AND shptimtypdt_shipmenttimetypename = ?");
658        queryMap.put(EntityPermission.READ_WRITE,
659                "SELECT _ALL_ " +
660                "FROM shipmenttimetypes, shipmenttimetypedetails " +
661                "WHERE shptimtyp_activedetailid = shptimtypdt_shipmenttimetypedetailid " +
662                "AND shptimtypdt_shptyp_shipmenttypeid = ? AND shptimtypdt_shipmenttimetypename = ? " +
663                "FOR UPDATE");
664        getShipmentTimeTypeByNameQueries = Collections.unmodifiableMap(queryMap);
665    }
666
667    private ShipmentTimeType getShipmentTimeTypeByName(ShipmentType shipmentType, String shipmentTimeTypeName, EntityPermission entityPermission) {
668        return ShipmentTimeTypeFactory.getInstance().getEntityFromQuery(entityPermission, getShipmentTimeTypeByNameQueries,
669                shipmentType, shipmentTimeTypeName);
670    }
671
672    public ShipmentTimeType getShipmentTimeTypeByName(ShipmentType shipmentType, String shipmentTimeTypeName) {
673        return getShipmentTimeTypeByName(shipmentType, shipmentTimeTypeName, EntityPermission.READ_ONLY);
674    }
675
676    public ShipmentTimeType getShipmentTimeTypeByNameForUpdate(ShipmentType shipmentType, String shipmentTimeTypeName) {
677        return getShipmentTimeTypeByName(shipmentType, shipmentTimeTypeName, EntityPermission.READ_WRITE);
678    }
679
680    public ShipmentTimeTypeDetailValue getShipmentTimeTypeDetailValueForUpdate(ShipmentTimeType shipmentTimeType) {
681        return shipmentTimeType == null? null: shipmentTimeType.getLastDetailForUpdate().getShipmentTimeTypeDetailValue().clone();
682    }
683
684    public ShipmentTimeTypeDetailValue getShipmentTimeTypeDetailValueByNameForUpdate(ShipmentType shipmentType, String shipmentTimeTypeName) {
685        return getShipmentTimeTypeDetailValueForUpdate(getShipmentTimeTypeByNameForUpdate(shipmentType, shipmentTimeTypeName));
686    }
687
688    private static final Map<EntityPermission, String> getDefaultShipmentTimeTypeQueries;
689
690    static {
691        Map<EntityPermission, String> queryMap = new HashMap<>(2);
692
693        queryMap.put(EntityPermission.READ_ONLY,
694                "SELECT _ALL_ " +
695                "FROM shipmenttimetypes, shipmenttimetypedetails " +
696                "WHERE shptimtyp_activedetailid = shptimtypdt_shipmenttimetypedetailid " +
697                "AND shptimtypdt_shptyp_shipmenttypeid = ? AND shptimtypdt_isdefault = 1");
698        queryMap.put(EntityPermission.READ_WRITE,
699                "SELECT _ALL_ " +
700                "FROM shipmenttimetypes, shipmenttimetypedetails " +
701                "WHERE shptimtyp_activedetailid = shptimtypdt_shipmenttimetypedetailid " +
702                "AND shptimtypdt_shptyp_shipmenttypeid = ? AND shptimtypdt_isdefault = 1 " +
703                "FOR UPDATE");
704        getDefaultShipmentTimeTypeQueries = Collections.unmodifiableMap(queryMap);
705    }
706
707    private ShipmentTimeType getDefaultShipmentTimeType(ShipmentType shipmentType, EntityPermission entityPermission) {
708        return ShipmentTimeTypeFactory.getInstance().getEntityFromQuery(entityPermission, getDefaultShipmentTimeTypeQueries,
709                shipmentType);
710    }
711
712    public ShipmentTimeType getDefaultShipmentTimeType(ShipmentType shipmentType) {
713        return getDefaultShipmentTimeType(shipmentType, EntityPermission.READ_ONLY);
714    }
715
716    public ShipmentTimeType getDefaultShipmentTimeTypeForUpdate(ShipmentType shipmentType) {
717        return getDefaultShipmentTimeType(shipmentType, EntityPermission.READ_WRITE);
718    }
719
720    public ShipmentTimeTypeDetailValue getDefaultShipmentTimeTypeDetailValueForUpdate(ShipmentType shipmentType) {
721        return getDefaultShipmentTimeTypeForUpdate(shipmentType).getLastDetailForUpdate().getShipmentTimeTypeDetailValue().clone();
722    }
723
724    private static final Map<EntityPermission, String> getShipmentTimeTypesQueries;
725
726    static {
727        Map<EntityPermission, String> queryMap = new HashMap<>(2);
728
729        queryMap.put(EntityPermission.READ_ONLY,
730                "SELECT _ALL_ " +
731                "FROM shipmenttimetypes, shipmenttimetypedetails " +
732                "WHERE shptimtyp_activedetailid = shptimtypdt_shipmenttimetypedetailid " +
733                "AND shptimtypdt_shptyp_shipmenttypeid = ? " +
734                "ORDER BY shptimtypdt_sortorder, shptimtypdt_shipmenttimetypename");
735        queryMap.put(EntityPermission.READ_WRITE,
736                "SELECT _ALL_ " +
737                "FROM shipmenttimetypes, shipmenttimetypedetails " +
738                "WHERE shptimtyp_activedetailid = shptimtypdt_shipmenttimetypedetailid " +
739                "AND shptimtypdt_shptyp_shipmenttypeid = ? " +
740                "FOR UPDATE");
741        getShipmentTimeTypesQueries = Collections.unmodifiableMap(queryMap);
742    }
743
744    private List<ShipmentTimeType> getShipmentTimeTypes(ShipmentType shipmentType, EntityPermission entityPermission) {
745        return ShipmentTimeTypeFactory.getInstance().getEntitiesFromQuery(entityPermission, getShipmentTimeTypesQueries,
746                shipmentType);
747    }
748
749    public List<ShipmentTimeType> getShipmentTimeTypes(ShipmentType shipmentType) {
750        return getShipmentTimeTypes(shipmentType, EntityPermission.READ_ONLY);
751    }
752
753    public List<ShipmentTimeType> getShipmentTimeTypesForUpdate(ShipmentType shipmentType) {
754        return getShipmentTimeTypes(shipmentType, EntityPermission.READ_WRITE);
755    }
756
757    public ShipmentTimeTypeTransfer getShipmentTimeTypeTransfer(UserVisit userVisit, ShipmentTimeType shipmentTimeType) {
758        return getShipmentTransferCaches(userVisit).getShipmentTimeTypeTransferCache().getTransfer(shipmentTimeType);
759    }
760
761    public List<ShipmentTimeTypeTransfer> getShipmentTimeTypeTransfers(UserVisit userVisit, ShipmentType shipmentType) {
762        List<ShipmentTimeType> shipmentTimeTypes = getShipmentTimeTypes(shipmentType);
763        List<ShipmentTimeTypeTransfer> shipmentTimeTypeTransfers = new ArrayList<>(shipmentTimeTypes.size());
764        ShipmentTimeTypeTransferCache shipmentTimeTypeTransferCache = getShipmentTransferCaches(userVisit).getShipmentTimeTypeTransferCache();
765
766        shipmentTimeTypes.forEach((shipmentTimeType) ->
767                shipmentTimeTypeTransfers.add(shipmentTimeTypeTransferCache.getTransfer(shipmentTimeType))
768        );
769
770        return shipmentTimeTypeTransfers;
771    }
772
773    public ShipmentTimeTypeChoicesBean getShipmentTimeTypeChoices(String defaultShipmentTimeTypeChoice, Language language, boolean allowNullChoice,
774            ShipmentType shipmentType) {
775        List<ShipmentTimeType> shipmentTimeTypes = getShipmentTimeTypes(shipmentType);
776        var size = shipmentTimeTypes.size();
777        var labels = new ArrayList<String>(size);
778        var values = new ArrayList<String>(size);
779        String defaultValue = null;
780
781        if(allowNullChoice) {
782            labels.add("");
783            values.add("");
784
785            if(defaultShipmentTimeTypeChoice == null) {
786                defaultValue = "";
787            }
788        }
789
790        for(var shipmentTimeType : shipmentTimeTypes) {
791            ShipmentTimeTypeDetail shipmentTimeTypeDetail = shipmentTimeType.getLastDetail();
792
793            var label = getBestShipmentTimeTypeDescription(shipmentTimeType, language);
794            var value = shipmentTimeTypeDetail.getShipmentTimeTypeName();
795
796            labels.add(label == null? value: label);
797            values.add(value);
798
799            var usingDefaultChoice = defaultShipmentTimeTypeChoice != null && defaultShipmentTimeTypeChoice.equals(value);
800            if(usingDefaultChoice || (defaultValue == null && shipmentTimeTypeDetail.getIsDefault())) {
801                defaultValue = value;
802            }
803        }
804
805        return new ShipmentTimeTypeChoicesBean(labels, values, defaultValue);
806    }
807
808    private void updateShipmentTimeTypeFromValue(ShipmentTimeTypeDetailValue shipmentTimeTypeDetailValue, boolean checkDefault,
809            BasePK updatedBy) {
810        if(shipmentTimeTypeDetailValue.hasBeenModified()) {
811            ShipmentTimeType shipmentTimeType = ShipmentTimeTypeFactory.getInstance().getEntityFromPK(EntityPermission.READ_WRITE,
812                     shipmentTimeTypeDetailValue.getShipmentTimeTypePK());
813            ShipmentTimeTypeDetail shipmentTimeTypeDetail = shipmentTimeType.getActiveDetailForUpdate();
814
815            shipmentTimeTypeDetail.setThruTime(session.START_TIME_LONG);
816            shipmentTimeTypeDetail.store();
817
818            ShipmentType shipmentType = shipmentTimeTypeDetail.getShipmentType(); // Not updated
819            ShipmentTypePK shipmentTypePK = shipmentType.getPrimaryKey(); // Not updated
820            ShipmentTimeTypePK shipmentTimeTypePK = shipmentTimeTypeDetail.getShipmentTimeTypePK(); // Not updated
821            String shipmentTimeTypeName = shipmentTimeTypeDetailValue.getShipmentTimeTypeName();
822            Boolean isDefault = shipmentTimeTypeDetailValue.getIsDefault();
823            Integer sortOrder = shipmentTimeTypeDetailValue.getSortOrder();
824
825            if(checkDefault) {
826                ShipmentTimeType defaultShipmentTimeType = getDefaultShipmentTimeType(shipmentType);
827                boolean defaultFound = defaultShipmentTimeType != null && !defaultShipmentTimeType.equals(shipmentTimeType);
828
829                if(isDefault && defaultFound) {
830                    // If I'm the default, and a default already existed...
831                    ShipmentTimeTypeDetailValue defaultShipmentTimeTypeDetailValue = getDefaultShipmentTimeTypeDetailValueForUpdate(shipmentType);
832
833                    defaultShipmentTimeTypeDetailValue.setIsDefault(Boolean.FALSE);
834                    updateShipmentTimeTypeFromValue(defaultShipmentTimeTypeDetailValue, false, updatedBy);
835                } else if(!isDefault && !defaultFound) {
836                    // If I'm not the default, and no other default exists...
837                    isDefault = Boolean.TRUE;
838                }
839            }
840
841            shipmentTimeTypeDetail = ShipmentTimeTypeDetailFactory.getInstance().create(shipmentTimeTypePK, shipmentTypePK, shipmentTimeTypeName, isDefault, sortOrder,
842                    session.START_TIME_LONG, Session.MAX_TIME_LONG);
843
844            shipmentTimeType.setActiveDetail(shipmentTimeTypeDetail);
845            shipmentTimeType.setLastDetail(shipmentTimeTypeDetail);
846
847            sendEvent(shipmentTimeTypePK, EventTypes.MODIFY, null, null, updatedBy);
848        }
849    }
850
851    public void updateShipmentTimeTypeFromValue(ShipmentTimeTypeDetailValue shipmentTimeTypeDetailValue, BasePK updatedBy) {
852        updateShipmentTimeTypeFromValue(shipmentTimeTypeDetailValue, true, updatedBy);
853    }
854
855    public void deleteShipmentTimeType(ShipmentTimeType shipmentTimeType, BasePK deletedBy) {
856        deleteShipmentTimesByShipmentTimeType(shipmentTimeType, deletedBy);
857        deleteShipmentTimeTypeDescriptionsByShipmentTimeType(shipmentTimeType, deletedBy);
858
859        ShipmentTimeTypeDetail shipmentTimeTypeDetail = shipmentTimeType.getLastDetailForUpdate();
860        shipmentTimeTypeDetail.setThruTime(session.START_TIME_LONG);
861        shipmentTimeType.setActiveDetail(null);
862        shipmentTimeType.store();
863
864        // Check for default, and pick one if necessary
865        ShipmentType shipmentType = shipmentTimeTypeDetail.getShipmentType();
866        ShipmentTimeType defaultShipmentTimeType = getDefaultShipmentTimeType(shipmentType);
867        if(defaultShipmentTimeType == null) {
868            List<ShipmentTimeType> shipmentTimeTypes = getShipmentTimeTypesForUpdate(shipmentType);
869
870            if(!shipmentTimeTypes.isEmpty()) {
871                Iterator<ShipmentTimeType> iter = shipmentTimeTypes.iterator();
872                if(iter.hasNext()) {
873                    defaultShipmentTimeType = iter.next();
874                }
875                ShipmentTimeTypeDetailValue shipmentTimeTypeDetailValue = Objects.requireNonNull(defaultShipmentTimeType).getLastDetailForUpdate().getShipmentTimeTypeDetailValue().clone();
876
877                shipmentTimeTypeDetailValue.setIsDefault(Boolean.TRUE);
878                updateShipmentTimeTypeFromValue(shipmentTimeTypeDetailValue, false, deletedBy);
879            }
880        }
881
882        sendEvent(shipmentTimeType.getPrimaryKey(), EventTypes.DELETE, null, null, deletedBy);
883    }
884
885    // --------------------------------------------------------------------------------
886    //   Shipment Time Type Descriptions
887    // --------------------------------------------------------------------------------
888
889    public ShipmentTimeTypeDescription createShipmentTimeTypeDescription(ShipmentTimeType shipmentTimeType, Language language, String description, BasePK createdBy) {
890        ShipmentTimeTypeDescription shipmentTimeTypeDescription = ShipmentTimeTypeDescriptionFactory.getInstance().create(shipmentTimeType, language, description,
891                session.START_TIME_LONG, Session.MAX_TIME_LONG);
892
893        sendEvent(shipmentTimeType.getPrimaryKey(), EventTypes.MODIFY, shipmentTimeTypeDescription.getPrimaryKey(), EventTypes.CREATE, createdBy);
894
895        return shipmentTimeTypeDescription;
896    }
897
898    private static final Map<EntityPermission, String> getShipmentTimeTypeDescriptionQueries;
899
900    static {
901        Map<EntityPermission, String> queryMap = new HashMap<>(2);
902
903        queryMap.put(EntityPermission.READ_ONLY,
904                "SELECT _ALL_ " +
905                "FROM shipmenttimetypedescriptions " +
906                "WHERE shptimtypd_shptimtyp_shipmenttimetypeid = ? AND shptimtypd_lang_languageid = ? AND shptimtypd_thrutime = ?");
907        queryMap.put(EntityPermission.READ_WRITE,
908                "SELECT _ALL_ " +
909                "FROM shipmenttimetypedescriptions " +
910                "WHERE shptimtypd_shptimtyp_shipmenttimetypeid = ? AND shptimtypd_lang_languageid = ? AND shptimtypd_thrutime = ? " +
911                "FOR UPDATE");
912        getShipmentTimeTypeDescriptionQueries = Collections.unmodifiableMap(queryMap);
913    }
914
915    private ShipmentTimeTypeDescription getShipmentTimeTypeDescription(ShipmentTimeType shipmentTimeType, Language language, EntityPermission entityPermission) {
916        return ShipmentTimeTypeDescriptionFactory.getInstance().getEntityFromQuery(entityPermission, getShipmentTimeTypeDescriptionQueries,
917                shipmentTimeType, language, Session.MAX_TIME);
918    }
919
920    public ShipmentTimeTypeDescription getShipmentTimeTypeDescription(ShipmentTimeType shipmentTimeType, Language language) {
921        return getShipmentTimeTypeDescription(shipmentTimeType, language, EntityPermission.READ_ONLY);
922    }
923
924    public ShipmentTimeTypeDescription getShipmentTimeTypeDescriptionForUpdate(ShipmentTimeType shipmentTimeType, Language language) {
925        return getShipmentTimeTypeDescription(shipmentTimeType, language, EntityPermission.READ_WRITE);
926    }
927
928    public ShipmentTimeTypeDescriptionValue getShipmentTimeTypeDescriptionValue(ShipmentTimeTypeDescription shipmentTimeTypeDescription) {
929        return shipmentTimeTypeDescription == null? null: shipmentTimeTypeDescription.getShipmentTimeTypeDescriptionValue().clone();
930    }
931
932    public ShipmentTimeTypeDescriptionValue getShipmentTimeTypeDescriptionValueForUpdate(ShipmentTimeType shipmentTimeType, Language language) {
933        return getShipmentTimeTypeDescriptionValue(getShipmentTimeTypeDescriptionForUpdate(shipmentTimeType, language));
934    }
935
936    private static final Map<EntityPermission, String> getShipmentTimeTypeDescriptionsByShipmentTimeTypeQueries;
937
938    static {
939        Map<EntityPermission, String> queryMap = new HashMap<>(2);
940
941        queryMap.put(EntityPermission.READ_ONLY,
942                "SELECT _ALL_ " +
943                "FROM shipmenttimetypedescriptions, languages " +
944                "WHERE shptimtypd_shptimtyp_shipmenttimetypeid = ? AND shptimtypd_thrutime = ? AND shptimtypd_lang_languageid = lang_languageid " +
945                "ORDER BY lang_sortorder, lang_languageisoname");
946        queryMap.put(EntityPermission.READ_WRITE,
947                "SELECT _ALL_ " +
948                "FROM shipmenttimetypedescriptions " +
949                "WHERE shptimtypd_shptimtyp_shipmenttimetypeid = ? AND shptimtypd_thrutime = ? " +
950                "FOR UPDATE");
951        getShipmentTimeTypeDescriptionsByShipmentTimeTypeQueries = Collections.unmodifiableMap(queryMap);
952    }
953
954    private List<ShipmentTimeTypeDescription> getShipmentTimeTypeDescriptionsByShipmentTimeType(ShipmentTimeType shipmentTimeType, EntityPermission entityPermission) {
955        return ShipmentTimeTypeDescriptionFactory.getInstance().getEntitiesFromQuery(entityPermission, getShipmentTimeTypeDescriptionsByShipmentTimeTypeQueries,
956                shipmentTimeType, Session.MAX_TIME);
957    }
958
959    public List<ShipmentTimeTypeDescription> getShipmentTimeTypeDescriptionsByShipmentTimeType(ShipmentTimeType shipmentTimeType) {
960        return getShipmentTimeTypeDescriptionsByShipmentTimeType(shipmentTimeType, EntityPermission.READ_ONLY);
961    }
962
963    public List<ShipmentTimeTypeDescription> getShipmentTimeTypeDescriptionsByShipmentTimeTypeForUpdate(ShipmentTimeType shipmentTimeType) {
964        return getShipmentTimeTypeDescriptionsByShipmentTimeType(shipmentTimeType, EntityPermission.READ_WRITE);
965    }
966
967    public String getBestShipmentTimeTypeDescription(ShipmentTimeType shipmentTimeType, Language language) {
968        String description;
969        ShipmentTimeTypeDescription shipmentTimeTypeDescription = getShipmentTimeTypeDescription(shipmentTimeType, language);
970
971        if(shipmentTimeTypeDescription == null && !language.getIsDefault()) {
972            shipmentTimeTypeDescription = getShipmentTimeTypeDescription(shipmentTimeType, getPartyControl().getDefaultLanguage());
973        }
974
975        if(shipmentTimeTypeDescription == null) {
976            description = shipmentTimeType.getLastDetail().getShipmentTimeTypeName();
977        } else {
978            description = shipmentTimeTypeDescription.getDescription();
979        }
980
981        return description;
982    }
983
984    public ShipmentTimeTypeDescriptionTransfer getShipmentTimeTypeDescriptionTransfer(UserVisit userVisit, ShipmentTimeTypeDescription shipmentTimeTypeDescription) {
985        return getShipmentTransferCaches(userVisit).getShipmentTimeTypeDescriptionTransferCache().getTransfer(shipmentTimeTypeDescription);
986    }
987
988    public List<ShipmentTimeTypeDescriptionTransfer> getShipmentTimeTypeDescriptionTransfersByShipmentTimeType(UserVisit userVisit, ShipmentTimeType shipmentTimeType) {
989        List<ShipmentTimeTypeDescription> shipmentTimeTypeDescriptions = getShipmentTimeTypeDescriptionsByShipmentTimeType(shipmentTimeType);
990        List<ShipmentTimeTypeDescriptionTransfer> shipmentTimeTypeDescriptionTransfers = new ArrayList<>(shipmentTimeTypeDescriptions.size());
991        ShipmentTimeTypeDescriptionTransferCache shipmentTimeTypeDescriptionTransferCache = getShipmentTransferCaches(userVisit).getShipmentTimeTypeDescriptionTransferCache();
992
993        shipmentTimeTypeDescriptions.forEach((shipmentTimeTypeDescription) ->
994                shipmentTimeTypeDescriptionTransfers.add(shipmentTimeTypeDescriptionTransferCache.getTransfer(shipmentTimeTypeDescription))
995        );
996
997        return shipmentTimeTypeDescriptionTransfers;
998    }
999
1000    public void updateShipmentTimeTypeDescriptionFromValue(ShipmentTimeTypeDescriptionValue shipmentTimeTypeDescriptionValue, BasePK updatedBy) {
1001        if(shipmentTimeTypeDescriptionValue.hasBeenModified()) {
1002            ShipmentTimeTypeDescription shipmentTimeTypeDescription = ShipmentTimeTypeDescriptionFactory.getInstance().getEntityFromPK(EntityPermission.READ_WRITE,
1003                    shipmentTimeTypeDescriptionValue.getPrimaryKey());
1004
1005            shipmentTimeTypeDescription.setThruTime(session.START_TIME_LONG);
1006            shipmentTimeTypeDescription.store();
1007
1008            ShipmentTimeType shipmentTimeType = shipmentTimeTypeDescription.getShipmentTimeType();
1009            Language language = shipmentTimeTypeDescription.getLanguage();
1010            String description = shipmentTimeTypeDescriptionValue.getDescription();
1011
1012            shipmentTimeTypeDescription = ShipmentTimeTypeDescriptionFactory.getInstance().create(shipmentTimeType, language, description,
1013                    session.START_TIME_LONG, Session.MAX_TIME_LONG);
1014
1015            sendEvent(shipmentTimeType.getPrimaryKey(), EventTypes.MODIFY, shipmentTimeTypeDescription.getPrimaryKey(), EventTypes.MODIFY, updatedBy);
1016        }
1017    }
1018
1019    public void deleteShipmentTimeTypeDescription(ShipmentTimeTypeDescription shipmentTimeTypeDescription, BasePK deletedBy) {
1020        shipmentTimeTypeDescription.setThruTime(session.START_TIME_LONG);
1021
1022        sendEvent(shipmentTimeTypeDescription.getShipmentTimeTypePK(), EventTypes.MODIFY, shipmentTimeTypeDescription.getPrimaryKey(), EventTypes.DELETE, deletedBy);
1023
1024    }
1025
1026    public void deleteShipmentTimeTypeDescriptionsByShipmentTimeType(ShipmentTimeType shipmentTimeType, BasePK deletedBy) {
1027        List<ShipmentTimeTypeDescription> shipmentTimeTypeDescriptions = getShipmentTimeTypeDescriptionsByShipmentTimeTypeForUpdate(shipmentTimeType);
1028
1029        shipmentTimeTypeDescriptions.forEach((shipmentTimeTypeDescription) -> 
1030                deleteShipmentTimeTypeDescription(shipmentTimeTypeDescription, deletedBy)
1031        );
1032    }
1033
1034    // --------------------------------------------------------------------------------
1035    //   Shipment Type Shipping Methods
1036    // --------------------------------------------------------------------------------
1037    
1038    public ShipmentTypeShippingMethod createShipmentTypeShippingMethod(ShipmentType shipmentType, ShippingMethod shippingMethod, Boolean isDefault,
1039            Integer sortOrder, BasePK createdBy) {
1040        ShipmentTypeShippingMethod defaultShipmentTypeShippingMethod = getDefaultShipmentTypeShippingMethod(shipmentType);
1041        boolean defaultFound = defaultShipmentTypeShippingMethod != null;
1042        
1043        if(defaultFound && isDefault) {
1044            ShipmentTypeShippingMethodValue defaultShipmentTypeShippingMethodValue = getDefaultShipmentTypeShippingMethodValueForUpdate(shipmentType);
1045            
1046            defaultShipmentTypeShippingMethodValue.setIsDefault(Boolean.FALSE);
1047            updateShipmentTypeShippingMethodFromValue(defaultShipmentTypeShippingMethodValue, false, createdBy);
1048        } else if(!defaultFound) {
1049            isDefault = Boolean.TRUE;
1050        }
1051        
1052        ShipmentTypeShippingMethod shipmentTypeShippingMethod = ShipmentTypeShippingMethodFactory.getInstance().create(shipmentType, shippingMethod,
1053                isDefault, sortOrder, session.START_TIME_LONG, Session.MAX_TIME_LONG);
1054        
1055        sendEvent(shippingMethod.getPrimaryKey(), EventTypes.MODIFY, shipmentTypeShippingMethod.getPrimaryKey(), EventTypes.CREATE, createdBy);
1056        
1057        return shipmentTypeShippingMethod;
1058    }
1059    
1060    private ShipmentTypeShippingMethod getShipmentTypeShippingMethod(ShipmentType shipmentType, ShippingMethod shippingMethod, EntityPermission entityPermission) {
1061        ShipmentTypeShippingMethod shipmentTypeShippingMethod;
1062        
1063        try {
1064            String query = null;
1065            
1066            if(entityPermission.equals(EntityPermission.READ_ONLY)) {
1067                query = "SELECT _ALL_ " +
1068                        "FROM shipmenttypeshippingmethods " +
1069                        "WHERE shptypshm_shptyp_shipmenttypeid = ? AND shptypshm_shm_shippingmethodid = ? AND shptypshm_thrutime = ?";
1070            } else if(entityPermission.equals(EntityPermission.READ_WRITE)) {
1071                query = "SELECT _ALL_ " +
1072                        "FROM shipmenttypeshippingmethods " +
1073                        "WHERE shptypshm_shptyp_shipmenttypeid = ? AND shptypshm_shm_shippingmethodid = ? AND shptypshm_thrutime = ? " +
1074                        "FOR UPDATE";
1075            }
1076            
1077            PreparedStatement ps = ShipmentTypeShippingMethodFactory.getInstance().prepareStatement(query);
1078            
1079            ps.setLong(1, shipmentType.getPrimaryKey().getEntityId());
1080            ps.setLong(2, shippingMethod.getPrimaryKey().getEntityId());
1081            ps.setLong(3, Session.MAX_TIME);
1082            
1083            shipmentTypeShippingMethod = ShipmentTypeShippingMethodFactory.getInstance().getEntityFromQuery(entityPermission, ps);
1084        } catch (SQLException se) {
1085            throw new PersistenceDatabaseException(se);
1086        }
1087        
1088        return shipmentTypeShippingMethod;
1089    }
1090    
1091    public ShipmentTypeShippingMethod getShipmentTypeShippingMethod(ShipmentType shipmentType, ShippingMethod shippingMethod) {
1092        return getShipmentTypeShippingMethod(shipmentType, shippingMethod, EntityPermission.READ_ONLY);
1093    }
1094    
1095    public ShipmentTypeShippingMethod getShipmentTypeShippingMethodForUpdate(ShipmentType shipmentType, ShippingMethod shippingMethod) {
1096        return getShipmentTypeShippingMethod(shipmentType, shippingMethod, EntityPermission.READ_WRITE);
1097    }
1098    
1099    public ShipmentTypeShippingMethodValue getShipmentTypeShippingMethodValueForUpdate(ShipmentType shipmentType, ShippingMethod shippingMethod) {
1100        ShipmentTypeShippingMethod shipmentTypeShippingMethod = getShipmentTypeShippingMethodForUpdate(shipmentType, shippingMethod);
1101        
1102        return shipmentTypeShippingMethod == null? null: shipmentTypeShippingMethod.getShipmentTypeShippingMethodValue().clone();
1103    }
1104    
1105    private ShipmentTypeShippingMethod getDefaultShipmentTypeShippingMethod(ShipmentType shipmentType, EntityPermission entityPermission) {
1106        ShipmentTypeShippingMethod shipmentTypeShippingMethod;
1107        
1108        try {
1109            String query = null;
1110            
1111            if(entityPermission.equals(EntityPermission.READ_ONLY)) {
1112                query = "SELECT _ALL_ " +
1113                        "FROM shipmenttypeshippingmethods " +
1114                        "WHERE shptypshm_shptyp_shipmenttypeid = ? AND shptypshm_isdefault = 1 AND shptypshm_thrutime = ?";
1115            } else if(entityPermission.equals(EntityPermission.READ_WRITE)) {
1116                query = "SELECT _ALL_ " +
1117                        "FROM shipmenttypeshippingmethods " +
1118                        "WHERE shptypshm_shptyp_shipmenttypeid = ? AND shptypshm_isdefault = 1 AND shptypshm_thrutime = ? " +
1119                        "FOR UPDATE";
1120            }
1121            
1122            PreparedStatement ps = ShipmentTypeShippingMethodFactory.getInstance().prepareStatement(query);
1123            
1124            ps.setLong(1, shipmentType.getPrimaryKey().getEntityId());
1125            ps.setLong(2, Session.MAX_TIME);
1126            
1127            shipmentTypeShippingMethod = ShipmentTypeShippingMethodFactory.getInstance().getEntityFromQuery(entityPermission, ps);
1128        } catch (SQLException se) {
1129            throw new PersistenceDatabaseException(se);
1130        }
1131        
1132        return shipmentTypeShippingMethod;
1133    }
1134    
1135    public ShipmentTypeShippingMethod getDefaultShipmentTypeShippingMethod(ShipmentType shipmentType) {
1136        return getDefaultShipmentTypeShippingMethod(shipmentType, EntityPermission.READ_ONLY);
1137    }
1138    
1139    public ShipmentTypeShippingMethod getDefaultShipmentTypeShippingMethodForUpdate(ShipmentType shipmentType) {
1140        return getDefaultShipmentTypeShippingMethod(shipmentType, EntityPermission.READ_WRITE);
1141    }
1142    
1143    public ShipmentTypeShippingMethodValue getDefaultShipmentTypeShippingMethodValueForUpdate(ShipmentType shipmentType) {
1144        ShipmentTypeShippingMethod shipmentTypeShippingMethod = getDefaultShipmentTypeShippingMethodForUpdate(shipmentType);
1145        
1146        return shipmentTypeShippingMethod == null? null: shipmentTypeShippingMethod.getShipmentTypeShippingMethodValue().clone();
1147    }
1148    
1149    private List<ShipmentTypeShippingMethod> getShipmentTypeShippingMethodsByShipmentType(ShipmentType shipmentType, EntityPermission entityPermission) {
1150        List<ShipmentTypeShippingMethod> shipmentTypeShippingMethods;
1151        
1152        try {
1153            String query = null;
1154            
1155            if(entityPermission.equals(EntityPermission.READ_ONLY)) {
1156                query = "SELECT _ALL_ " +
1157                        "FROM shipmenttypeshippingmethods, shippingmethods, shippingmethoddetails " +
1158                        "WHERE shptypshm_shptyp_shipmenttypeid = ? AND shptypshm_thrutime = ? " +
1159                        "AND shptypshm_shm_shippingmethodid = shm_shippingmethodid AND shm_lastdetailid = shmdt_shippingmethoddetailid " +
1160                        "ORDER BY shmdt_sortorder, shmdt_shippingmethodname";
1161            } else if(entityPermission.equals(EntityPermission.READ_WRITE)) {
1162                query = "SELECT _ALL_ " +
1163                        "FROM shipmenttypeshippingmethods " +
1164                        "WHERE shptypshm_shptyp_shipmenttypeid = ? AND shptypshm_thrutime = ? " +
1165                        "FOR UPDATE";
1166            }
1167            
1168            PreparedStatement ps = ShipmentTypeShippingMethodFactory.getInstance().prepareStatement(query);
1169            
1170            ps.setLong(1, shipmentType.getPrimaryKey().getEntityId());
1171            ps.setLong(2, Session.MAX_TIME);
1172            
1173            shipmentTypeShippingMethods = ShipmentTypeShippingMethodFactory.getInstance().getEntitiesFromQuery(entityPermission, ps);
1174        } catch (SQLException se) {
1175            throw new PersistenceDatabaseException(se);
1176        }
1177        
1178        return shipmentTypeShippingMethods;
1179    }
1180    
1181    public List<ShipmentTypeShippingMethod> getShipmentTypeShippingMethodsByShipmentType(ShipmentType shipmentType) {
1182        return getShipmentTypeShippingMethodsByShipmentType(shipmentType, EntityPermission.READ_ONLY);
1183    }
1184    
1185    public List<ShipmentTypeShippingMethod> getShipmentTypeShippingMethodsByShipmentTypeForUpdate(ShipmentType shipmentType) {
1186        return getShipmentTypeShippingMethodsByShipmentType(shipmentType, EntityPermission.READ_WRITE);
1187    }
1188    
1189    private List<ShipmentTypeShippingMethod> getShipmentTypeShippingMethodsByShippingMethod(ShippingMethod shippingMethod, EntityPermission entityPermission) {
1190        List<ShipmentTypeShippingMethod> shipmentTypeShippingMethods;
1191        
1192        try {
1193            String query = null;
1194            
1195            if(entityPermission.equals(EntityPermission.READ_ONLY)) {
1196                query = "SELECT _ALL_ " +
1197                        "FROM shipmenttypeshippingmethods, shipmenttypes, shipmenttypedetails, returnkinds, returnkinddetails " +
1198                        "WHERE shptypshm_shm_shippingmethodid = ? AND shptypshm_thrutime = ? " +
1199                        "AND shptypshm_shptyp_shipmenttypeid = shptyp_shipmenttypeid AND shptyp_lastdetailid = shptypdt_shipmenttypedetailid " +
1200                        "AND shptypdt_rtnk_returnkindid = rtnk_returnkindid AND rtnk_lastdetailid = rtnkdt_returnkinddetailid " +
1201                        "ORDER BY shptypdt_sortorder, shptypdt_shipmenttypename, rtnkdt_sortorder, rtnkdt_returnkindname";
1202            } else if(entityPermission.equals(EntityPermission.READ_WRITE)) {
1203                query = "SELECT _ALL_ " +
1204                        "FROM shipmenttypeshippingmethods " +
1205                        "WHERE shptypshm_shm_shippingmethodid = ? AND shptypshm_thrutime = ? " +
1206                        "FOR UPDATE";
1207            }
1208            
1209            PreparedStatement ps = ShipmentTypeShippingMethodFactory.getInstance().prepareStatement(query);
1210            
1211            ps.setLong(1, shippingMethod.getPrimaryKey().getEntityId());
1212            ps.setLong(2, Session.MAX_TIME);
1213            
1214            shipmentTypeShippingMethods = ShipmentTypeShippingMethodFactory.getInstance().getEntitiesFromQuery(entityPermission, ps);
1215        } catch (SQLException se) {
1216            throw new PersistenceDatabaseException(se);
1217        }
1218        
1219        return shipmentTypeShippingMethods;
1220    }
1221    
1222    public List<ShipmentTypeShippingMethod> getShipmentTypeShippingMethodsByShippingMethod(ShippingMethod shippingMethod) {
1223        return getShipmentTypeShippingMethodsByShippingMethod(shippingMethod, EntityPermission.READ_ONLY);
1224    }
1225    
1226    public List<ShipmentTypeShippingMethod> getShipmentTypeShippingMethodsByShippingMethodForUpdate(ShippingMethod shippingMethod) {
1227        return getShipmentTypeShippingMethodsByShippingMethod(shippingMethod, EntityPermission.READ_WRITE);
1228    }
1229    
1230    public List<ShipmentTypeShippingMethodTransfer> getShipmentTypeShippingMethodTransfers(UserVisit userVisit, Collection<ShipmentTypeShippingMethod> shipmentTypeShippingMethods) {
1231        List<ShipmentTypeShippingMethodTransfer> shipmentTypeShippingMethodTransfers = new ArrayList<>(shipmentTypeShippingMethods.size());
1232        ShipmentTypeShippingMethodTransferCache shipmentTypeShippingMethodTransferCache = getShipmentTransferCaches(userVisit).getShipmentTypeShippingMethodTransferCache();
1233        
1234        shipmentTypeShippingMethods.forEach((shipmentTypeShippingMethod) ->
1235                shipmentTypeShippingMethodTransfers.add(shipmentTypeShippingMethodTransferCache.getTransfer(shipmentTypeShippingMethod))
1236        );
1237        
1238        return shipmentTypeShippingMethodTransfers;
1239    }
1240    
1241    public List<ShipmentTypeShippingMethodTransfer> getShipmentTypeShippingMethodTransfersByShipmentType(UserVisit userVisit, ShipmentType shipmentType) {
1242        return getShipmentTypeShippingMethodTransfers(userVisit, getShipmentTypeShippingMethodsByShipmentType(shipmentType));
1243    }
1244    
1245    public List<ShipmentTypeShippingMethodTransfer> getShipmentTypeShippingMethodTransfersByShippingMethod(UserVisit userVisit, ShippingMethod shippingMethod) {
1246        return getShipmentTypeShippingMethodTransfers(userVisit, getShipmentTypeShippingMethodsByShippingMethod(shippingMethod));
1247    }
1248    
1249    public ShipmentTypeShippingMethodTransfer getShipmentTypeShippingMethodTransfer(UserVisit userVisit, ShipmentTypeShippingMethod shipmentTypeShippingMethod) {
1250        return getShipmentTransferCaches(userVisit).getShipmentTypeShippingMethodTransferCache().getTransfer(shipmentTypeShippingMethod);
1251    }
1252    
1253    private void updateShipmentTypeShippingMethodFromValue(ShipmentTypeShippingMethodValue shipmentTypeShippingMethodValue, boolean checkDefault, BasePK updatedBy) {
1254        if(shipmentTypeShippingMethodValue.hasBeenModified()) {
1255            ShipmentTypeShippingMethod shipmentTypeShippingMethod = ShipmentTypeShippingMethodFactory.getInstance().getEntityFromPK(EntityPermission.READ_WRITE,
1256                     shipmentTypeShippingMethodValue.getPrimaryKey());
1257            
1258            shipmentTypeShippingMethod.setThruTime(session.START_TIME_LONG);
1259            shipmentTypeShippingMethod.store();
1260            
1261            ShipmentType shipmentType = shipmentTypeShippingMethod.getShipmentType(); // Not Updated
1262            ShipmentTypePK shipmentTypePK = shipmentType.getPrimaryKey(); // Not Updated
1263            ShippingMethodPK shippingMethodPK = shipmentTypeShippingMethod.getShippingMethodPK(); // Not Updated
1264            Boolean isDefault = shipmentTypeShippingMethodValue.getIsDefault();
1265            Integer sortOrder = shipmentTypeShippingMethodValue.getSortOrder();
1266            
1267            if(checkDefault) {
1268                ShipmentTypeShippingMethod defaultShipmentTypeShippingMethod = getDefaultShipmentTypeShippingMethod(shipmentType);
1269                boolean defaultFound = defaultShipmentTypeShippingMethod != null && !defaultShipmentTypeShippingMethod.equals(shipmentTypeShippingMethod);
1270                
1271                if(isDefault && defaultFound) {
1272                    // If I'm the default, and a default already existed...
1273                    ShipmentTypeShippingMethodValue defaultShipmentTypeShippingMethodValue = getDefaultShipmentTypeShippingMethodValueForUpdate(shipmentType);
1274                    
1275                    defaultShipmentTypeShippingMethodValue.setIsDefault(Boolean.FALSE);
1276                    updateShipmentTypeShippingMethodFromValue(defaultShipmentTypeShippingMethodValue, false, updatedBy);
1277                } else if(!isDefault && !defaultFound) {
1278                    // If I'm not the default, and no other default exists...
1279                    isDefault = Boolean.TRUE;
1280                }
1281            }
1282            
1283            shipmentTypeShippingMethod = ShipmentTypeShippingMethodFactory.getInstance().create(shipmentTypePK, shippingMethodPK,
1284                    isDefault, sortOrder, session.START_TIME_LONG, Session.MAX_TIME_LONG);
1285            
1286            sendEvent(shippingMethodPK, EventTypes.MODIFY, shipmentTypeShippingMethod.getPrimaryKey(), EventTypes.MODIFY, updatedBy);
1287        }
1288    }
1289    
1290    public void updateShipmentTypeShippingMethodFromValue(ShipmentTypeShippingMethodValue shipmentTypeShippingMethodValue, BasePK updatedBy) {
1291        updateShipmentTypeShippingMethodFromValue(shipmentTypeShippingMethodValue, true, updatedBy);
1292    }
1293    
1294    public void deleteShipmentTypeShippingMethod(ShipmentTypeShippingMethod shipmentTypeShippingMethod, BasePK deletedBy) {
1295        shipmentTypeShippingMethod.setThruTime(session.START_TIME_LONG);
1296        shipmentTypeShippingMethod.store();
1297        
1298        // Check for default, and pick one if necessary
1299        ShipmentType shipmentType = shipmentTypeShippingMethod.getShipmentType();
1300        ShipmentTypeShippingMethod defaultShipmentTypeShippingMethod = getDefaultShipmentTypeShippingMethod(shipmentType);
1301        if(defaultShipmentTypeShippingMethod == null) {
1302            List<ShipmentTypeShippingMethod> shipmentTypeShippingMethods = getShipmentTypeShippingMethodsByShipmentTypeForUpdate(shipmentType);
1303            
1304            if(!shipmentTypeShippingMethods.isEmpty()) {
1305                Iterator<ShipmentTypeShippingMethod> iter = shipmentTypeShippingMethods.iterator();
1306                if(iter.hasNext()) {
1307                    defaultShipmentTypeShippingMethod = iter.next();
1308                }
1309                ShipmentTypeShippingMethodValue shipmentTypeShippingMethodValue = defaultShipmentTypeShippingMethod.getShipmentTypeShippingMethodValue().clone();
1310                
1311                shipmentTypeShippingMethodValue.setIsDefault(Boolean.TRUE);
1312                updateShipmentTypeShippingMethodFromValue(shipmentTypeShippingMethodValue, false, deletedBy);
1313            }
1314        }
1315        
1316        sendEvent(shipmentTypeShippingMethod.getShippingMethodPK(), EventTypes.MODIFY, shipmentTypeShippingMethod.getPrimaryKey(), EventTypes.DELETE, deletedBy);
1317    }
1318    
1319    public void deleteShipmentTypeShippingMethods(List<ShipmentTypeShippingMethod> shipmentTypeShippingMethods, BasePK deletedBy) {
1320        shipmentTypeShippingMethods.forEach((shipmentTypeShippingMethod) -> 
1321                deleteShipmentTypeShippingMethod(shipmentTypeShippingMethod, deletedBy)
1322        );
1323    }
1324    
1325    public void deleteShipmentTypeShippingMethodsByShipmentType(ShipmentType shipmentType, BasePK deletedBy) {
1326        deleteShipmentTypeShippingMethods(getShipmentTypeShippingMethodsByShipmentTypeForUpdate(shipmentType), deletedBy);
1327    }
1328    
1329    public void deleteShipmentTypeShippingMethodsByShippingMethod(ShippingMethod shippingMethod, BasePK deletedBy) {
1330        deleteShipmentTypeShippingMethods(getShipmentTypeShippingMethodsByShippingMethodForUpdate(shippingMethod), deletedBy);
1331    }
1332    
1333    // --------------------------------------------------------------------------------
1334    //   Shipment Times
1335    // --------------------------------------------------------------------------------
1336
1337    public ShipmentTime createShipmentTime(Shipment shipment, ShipmentTimeType shipmentTimeType, Long time, BasePK createdBy) {
1338        ShipmentTime shipmentTime = ShipmentTimeFactory.getInstance().create(shipment, shipmentTimeType, time, session.START_TIME_LONG, Session.MAX_TIME_LONG);
1339
1340        sendEvent(shipment.getPrimaryKey(), EventTypes.MODIFY, shipmentTime.getPrimaryKey(), EventTypes.CREATE, createdBy);
1341
1342        return shipmentTime;
1343    }
1344
1345    public long countShipmentTimesByShipment(Shipment shipment) {
1346        return session.queryForLong(
1347                "SELECT COUNT(*) " +
1348                "FROM shipmenttimes " +
1349                "WHERE shptim_shp_shipmentid = ? AND shptim_thrutime = ?",
1350                shipment, Session.MAX_TIME_LONG);
1351    }
1352
1353    public long countShipmentTimesByShipmentTimeType(ShipmentTimeType shipmentTimeType) {
1354        return session.queryForLong(
1355                "SELECT COUNT(*) " +
1356                "FROM shipmenttimes " +
1357                "WHERE shptim_shptimtyp_shipmenttimetypeid = ? AND shptim_thrutime = ?",
1358                shipmentTimeType, Session.MAX_TIME_LONG);
1359    }
1360
1361    private static final Map<EntityPermission, String> getShipmentTimeQueries;
1362
1363    static {
1364        Map<EntityPermission, String> queryMap = new HashMap<>(2);
1365
1366        queryMap.put(EntityPermission.READ_ONLY,
1367                "SELECT _ALL_ " +
1368                "FROM shipmenttimes " +
1369                "WHERE shptim_shp_shipmentid = ? AND shptim_shptimtyp_shipmenttimetypeid = ? AND shptim_thrutime = ?");
1370        queryMap.put(EntityPermission.READ_WRITE,
1371                "SELECT _ALL_ " +
1372                "FROM shipmenttimes " +
1373                "WHERE shptim_shp_shipmentid = ? AND shptim_shptimtyp_shipmenttimetypeid = ? AND shptim_thrutime = ? " +
1374                "FOR UPDATE");
1375        getShipmentTimeQueries = Collections.unmodifiableMap(queryMap);
1376    }
1377
1378    private ShipmentTime getShipmentTime(Shipment shipment, ShipmentTimeType shipmentTimeType, EntityPermission entityPermission) {
1379        return ShipmentTimeFactory.getInstance().getEntityFromQuery(entityPermission, getShipmentTimeQueries, shipment, shipmentTimeType, Session.MAX_TIME);
1380    }
1381
1382    public ShipmentTime getShipmentTime(Shipment shipment, ShipmentTimeType shipmentTimeType) {
1383        return getShipmentTime(shipment, shipmentTimeType, EntityPermission.READ_ONLY);
1384    }
1385
1386    public ShipmentTime getShipmentTimeForUpdate(Shipment shipment, ShipmentTimeType shipmentTimeType) {
1387        return getShipmentTime(shipment, shipmentTimeType, EntityPermission.READ_WRITE);
1388    }
1389
1390    public ShipmentTimeValue getShipmentTimeValue(ShipmentTime shipmentTime) {
1391        return shipmentTime == null? null: shipmentTime.getShipmentTimeValue().clone();
1392    }
1393
1394    public ShipmentTimeValue getShipmentTimeValueForUpdate(Shipment shipment, ShipmentTimeType shipmentTimeType) {
1395        return getShipmentTimeValue(getShipmentTimeForUpdate(shipment, shipmentTimeType));
1396    }
1397
1398    private static final Map<EntityPermission, String> getShipmentTimesByShipmentQueries;
1399
1400    static {
1401        Map<EntityPermission, String> queryMap = new HashMap<>(2);
1402
1403        queryMap.put(EntityPermission.READ_ONLY,
1404                "SELECT _ALL_ " +
1405                "FROM shipmenttimes, shipmenttimetypes, shipmenttimetypedetails " +
1406                "WHERE shptim_shp_shipmentid = ? AND shptim_thrutime = ? " +
1407                "AND shptim_shptimtyp_shipmenttimetypeid = shptimtyp_shipmenttimetypeid AND shptimtyp_activedetailid = shptimtypdt_shipmenttimetypedetailid " +
1408                "ORDER BY shptimtypdt_sortorder, shptimtypdt_shipmenttimetypename");
1409        queryMap.put(EntityPermission.READ_WRITE,
1410                "SELECT _ALL_ " +
1411                "FROM shipmenttimes " +
1412                "WHERE shptim_shp_shipmentid = ? AND shptim_thrutime = ? " +
1413                "FOR UPDATE");
1414        getShipmentTimesByShipmentQueries = Collections.unmodifiableMap(queryMap);
1415    }
1416
1417    private List<ShipmentTime> getShipmentTimesByShipment(Shipment shipment, EntityPermission entityPermission) {
1418        return ShipmentTimeFactory.getInstance().getEntitiesFromQuery(entityPermission, getShipmentTimesByShipmentQueries, shipment, Session.MAX_TIME);
1419    }
1420
1421    public List<ShipmentTime> getShipmentTimesByShipment(Shipment shipment) {
1422        return getShipmentTimesByShipment(shipment, EntityPermission.READ_ONLY);
1423    }
1424
1425    public List<ShipmentTime> getShipmentTimesByShipmentForUpdate(Shipment shipment) {
1426        return getShipmentTimesByShipment(shipment, EntityPermission.READ_WRITE);
1427    }
1428
1429    private static final Map<EntityPermission, String> getShipmentTimesByShipmentTimeTypeQueries;
1430
1431    static {
1432        Map<EntityPermission, String> queryMap = new HashMap<>(2);
1433
1434        queryMap.put(EntityPermission.READ_ONLY,
1435                "SELECT _ALL_ " +
1436                "FROM shipmenttimes, shipments, shipmentdetails " +
1437                "WHERE shptim_shptimtyp_shipmenttimetypeid = ? AND shptim_thrutime = ? " +
1438                "AND shptim_shp_shipmentid = shptim_shp_shipmentid AND shp_activedetailid = shpdt_shipmentdetailid " +
1439                "ORDER BY shpdt_shipmentname");
1440        queryMap.put(EntityPermission.READ_WRITE,
1441                "SELECT _ALL_ " +
1442                "FROM shipmenttimes " +
1443                "WHERE shptim_shptimtyp_shipmenttimetypeid = ? AND shptim_thrutime = ? " +
1444                "FOR UPDATE");
1445        getShipmentTimesByShipmentTimeTypeQueries = Collections.unmodifiableMap(queryMap);
1446    }
1447
1448    private List<ShipmentTime> getShipmentTimesByShipmentTimeType(ShipmentTimeType shipmentTimeType, EntityPermission entityPermission) {
1449        return ShipmentTimeFactory.getInstance().getEntitiesFromQuery(entityPermission, getShipmentTimesByShipmentTimeTypeQueries, shipmentTimeType, Session.MAX_TIME);
1450    }
1451
1452    public List<ShipmentTime> getShipmentTimesByShipmentTimeType(ShipmentTimeType shipmentTimeType) {
1453        return getShipmentTimesByShipmentTimeType(shipmentTimeType, EntityPermission.READ_ONLY);
1454    }
1455
1456    public List<ShipmentTime> getShipmentTimesByShipmentTimeTypeForUpdate(ShipmentTimeType shipmentTimeType) {
1457        return getShipmentTimesByShipmentTimeType(shipmentTimeType, EntityPermission.READ_WRITE);
1458    }
1459
1460    public ShipmentTimeTransfer getShipmentTimeTransfer(UserVisit userVisit, ShipmentTime shipmentTime) {
1461        return getShipmentTransferCaches(userVisit).getShipmentTimeTransferCache().getTransfer(shipmentTime);
1462    }
1463
1464    public List<ShipmentTimeTransfer> getShipmentTimeTransfers(UserVisit userVisit, Collection<ShipmentTime> shipmentTimes) {
1465        List<ShipmentTimeTransfer> shipmentTimeTransfers = new ArrayList<>(shipmentTimes.size());
1466        ShipmentTimeTransferCache shipmentTimeTransferCache = getShipmentTransferCaches(userVisit).getShipmentTimeTransferCache();
1467
1468        shipmentTimes.forEach((shipmentTime) ->
1469                shipmentTimeTransfers.add(shipmentTimeTransferCache.getTransfer(shipmentTime))
1470        );
1471
1472        return shipmentTimeTransfers;
1473    }
1474
1475    public List<ShipmentTimeTransfer> getShipmentTimeTransfersByShipment(UserVisit userVisit, Shipment shipment) {
1476        return getShipmentTimeTransfers(userVisit, getShipmentTimesByShipment(shipment));
1477    }
1478
1479    public List<ShipmentTimeTransfer> getShipmentTimeTransfersByShipmentTimeType(UserVisit userVisit, ShipmentTimeType shipmentTimeType) {
1480        return getShipmentTimeTransfers(userVisit, getShipmentTimesByShipmentTimeType(shipmentTimeType));
1481    }
1482
1483    public void updateShipmentTimeFromValue(ShipmentTimeValue shipmentTimeValue, BasePK updatedBy) {
1484        if(shipmentTimeValue.hasBeenModified()) {
1485            ShipmentTime shipmentTime = ShipmentTimeFactory.getInstance().getEntityFromPK(EntityPermission.READ_WRITE,
1486                    shipmentTimeValue.getPrimaryKey());
1487
1488            shipmentTime.setThruTime(session.START_TIME_LONG);
1489            shipmentTime.store();
1490
1491            ShipmentPK shipmentPK = shipmentTime.getShipmentPK(); // Not updated
1492            ShipmentTimeTypePK shipmentTimeTypePK = shipmentTime.getShipmentTimeTypePK(); // Not updated
1493            Long time = shipmentTimeValue.getTime();
1494
1495            shipmentTime = ShipmentTimeFactory.getInstance().create(shipmentPK, shipmentTimeTypePK, time, session.START_TIME_LONG, Session.MAX_TIME_LONG);
1496
1497            sendEvent(shipmentPK, EventTypes.MODIFY, shipmentTime.getPrimaryKey(), EventTypes.MODIFY, updatedBy);
1498        }
1499    }
1500
1501    public void deleteShipmentTime(ShipmentTime shipmentTime, BasePK deletedBy) {
1502        shipmentTime.setThruTime(session.START_TIME_LONG);
1503
1504        sendEvent(shipmentTime.getShipmentTimeTypePK(), EventTypes.MODIFY, shipmentTime.getPrimaryKey(), EventTypes.DELETE, deletedBy);
1505
1506    }
1507
1508    public void deleteShipmentTimes(List<ShipmentTime> shipmentTimes, BasePK deletedBy) {
1509        shipmentTimes.forEach((shipmentTime) -> 
1510                deleteShipmentTime(shipmentTime, deletedBy)
1511        );
1512    }
1513
1514    public void deleteShipmentTimesByShipment(Shipment shipment, BasePK deletedBy) {
1515        deleteShipmentTimes(getShipmentTimesByShipmentForUpdate(shipment), deletedBy);
1516    }
1517
1518    public void deleteShipmentTimesByShipmentTimeType(ShipmentTimeType shipmentTimeType, BasePK deletedBy) {
1519        deleteShipmentTimes(getShipmentTimesByShipmentTimeTypeForUpdate(shipmentTimeType), deletedBy);
1520    }
1521
1522    // --------------------------------------------------------------------------------
1523    //   Shipment Alias Types
1524    // --------------------------------------------------------------------------------
1525
1526    public ShipmentAliasType createShipmentAliasType(ShipmentType shipmentType, String shipmentAliasTypeName, String validationPattern, Boolean isDefault, Integer sortOrder,
1527            BasePK createdBy) {
1528        ShipmentAliasType defaultShipmentAliasType = getDefaultShipmentAliasType(shipmentType);
1529        boolean defaultFound = defaultShipmentAliasType != null;
1530
1531        if(defaultFound && isDefault) {
1532            ShipmentAliasTypeDetailValue defaultShipmentAliasTypeDetailValue = getDefaultShipmentAliasTypeDetailValueForUpdate(shipmentType);
1533
1534            defaultShipmentAliasTypeDetailValue.setIsDefault(Boolean.FALSE);
1535            updateShipmentAliasTypeFromValue(defaultShipmentAliasTypeDetailValue, false, createdBy);
1536        } else if(!defaultFound) {
1537            isDefault = Boolean.TRUE;
1538        }
1539
1540        ShipmentAliasType shipmentAliasType = ShipmentAliasTypeFactory.getInstance().create();
1541        ShipmentAliasTypeDetail shipmentAliasTypeDetail = ShipmentAliasTypeDetailFactory.getInstance().create(shipmentAliasType, shipmentType, shipmentAliasTypeName,
1542                validationPattern, isDefault, sortOrder, session.START_TIME_LONG, Session.MAX_TIME_LONG);
1543
1544        // Convert to R/W
1545        shipmentAliasType = ShipmentAliasTypeFactory.getInstance().getEntityFromPK(EntityPermission.READ_WRITE, shipmentAliasType.getPrimaryKey());
1546        shipmentAliasType.setActiveDetail(shipmentAliasTypeDetail);
1547        shipmentAliasType.setLastDetail(shipmentAliasTypeDetail);
1548        shipmentAliasType.store();
1549
1550        sendEvent(shipmentAliasType.getPrimaryKey(), EventTypes.CREATE, null, null, createdBy);
1551
1552        return shipmentAliasType;
1553    }
1554
1555    private static final Map<EntityPermission, String> getShipmentAliasTypeByNameQueries;
1556
1557    static {
1558        Map<EntityPermission, String> queryMap = new HashMap<>(2);
1559
1560        queryMap.put(EntityPermission.READ_ONLY,
1561                "SELECT _ALL_ " +
1562                "FROM shipmentaliastypes, shipmentaliastypedetails " +
1563                "WHERE shpaltyp_activedetailid = shpaltypdt_shipmentaliastypedetailid AND shpaltypdt_shptyp_shipmenttypeid = ? " +
1564                "AND shpaltypdt_shipmentaliastypename = ?");
1565        queryMap.put(EntityPermission.READ_WRITE,
1566                "SELECT _ALL_ " +
1567                "FROM shipmentaliastypes, shipmentaliastypedetails " +
1568                "WHERE shpaltyp_activedetailid = shpaltypdt_shipmentaliastypedetailid AND shpaltypdt_shptyp_shipmenttypeid = ? " +
1569                "AND shpaltypdt_shipmentaliastypename = ? " +
1570                "FOR UPDATE");
1571        getShipmentAliasTypeByNameQueries = Collections.unmodifiableMap(queryMap);
1572    }
1573
1574    private ShipmentAliasType getShipmentAliasTypeByName(ShipmentType shipmentType, String shipmentAliasTypeName, EntityPermission entityPermission) {
1575        return ShipmentAliasTypeFactory.getInstance().getEntityFromQuery(entityPermission, getShipmentAliasTypeByNameQueries,
1576                shipmentType, shipmentAliasTypeName);
1577    }
1578
1579    public ShipmentAliasType getShipmentAliasTypeByName(ShipmentType shipmentType, String shipmentAliasTypeName) {
1580        return getShipmentAliasTypeByName(shipmentType, shipmentAliasTypeName, EntityPermission.READ_ONLY);
1581    }
1582
1583    public ShipmentAliasType getShipmentAliasTypeByNameForUpdate(ShipmentType shipmentType, String shipmentAliasTypeName) {
1584        return getShipmentAliasTypeByName(shipmentType, shipmentAliasTypeName, EntityPermission.READ_WRITE);
1585    }
1586
1587    public ShipmentAliasTypeDetailValue getShipmentAliasTypeDetailValueForUpdate(ShipmentAliasType shipmentAliasType) {
1588        return shipmentAliasType == null? null: shipmentAliasType.getLastDetailForUpdate().getShipmentAliasTypeDetailValue().clone();
1589    }
1590
1591    public ShipmentAliasTypeDetailValue getShipmentAliasTypeDetailValueByNameForUpdate(ShipmentType shipmentType,
1592            String shipmentAliasTypeName) {
1593        return getShipmentAliasTypeDetailValueForUpdate(getShipmentAliasTypeByNameForUpdate(shipmentType, shipmentAliasTypeName));
1594    }
1595
1596    private static final Map<EntityPermission, String> getDefaultShipmentAliasTypeQueries;
1597
1598    static {
1599        Map<EntityPermission, String> queryMap = new HashMap<>(2);
1600
1601        queryMap.put(EntityPermission.READ_ONLY,
1602                "SELECT _ALL_ " +
1603                "FROM shipmentaliastypes, shipmentaliastypedetails " +
1604                "WHERE shpaltyp_activedetailid = shpaltypdt_shipmentaliastypedetailid AND shpaltypdt_shptyp_shipmenttypeid = ? " +
1605                "AND shpaltypdt_isdefault = 1");
1606        queryMap.put(EntityPermission.READ_WRITE,
1607                "SELECT _ALL_ " +
1608                "FROM shipmentaliastypes, shipmentaliastypedetails " +
1609                "WHERE shpaltyp_activedetailid = shpaltypdt_shipmentaliastypedetailid AND shpaltypdt_shptyp_shipmenttypeid = ? " +
1610                "AND shpaltypdt_isdefault = 1 " +
1611                "FOR UPDATE");
1612        getDefaultShipmentAliasTypeQueries = Collections.unmodifiableMap(queryMap);
1613    }
1614
1615    private ShipmentAliasType getDefaultShipmentAliasType(ShipmentType shipmentType, EntityPermission entityPermission) {
1616        return ShipmentAliasTypeFactory.getInstance().getEntityFromQuery(entityPermission, getDefaultShipmentAliasTypeQueries, shipmentType);
1617    }
1618
1619    public ShipmentAliasType getDefaultShipmentAliasType(ShipmentType shipmentType) {
1620        return getDefaultShipmentAliasType(shipmentType, EntityPermission.READ_ONLY);
1621    }
1622
1623    public ShipmentAliasType getDefaultShipmentAliasTypeForUpdate(ShipmentType shipmentType) {
1624        return getDefaultShipmentAliasType(shipmentType, EntityPermission.READ_WRITE);
1625    }
1626
1627    public ShipmentAliasTypeDetailValue getDefaultShipmentAliasTypeDetailValueForUpdate(ShipmentType shipmentType) {
1628        return getDefaultShipmentAliasTypeForUpdate(shipmentType).getLastDetailForUpdate().getShipmentAliasTypeDetailValue().clone();
1629    }
1630
1631    private static final Map<EntityPermission, String> getShipmentAliasTypesQueries;
1632
1633    static {
1634        Map<EntityPermission, String> queryMap = new HashMap<>(2);
1635
1636        queryMap.put(EntityPermission.READ_ONLY,
1637                "SELECT _ALL_ " +
1638                "FROM shipmentaliastypes, shipmentaliastypedetails " +
1639                "WHERE shpaltyp_activedetailid = shpaltypdt_shipmentaliastypedetailid AND shpaltypdt_shptyp_shipmenttypeid = ? " +
1640                "ORDER BY shpaltypdt_sortorder, shpaltypdt_shipmentaliastypename");
1641        queryMap.put(EntityPermission.READ_WRITE,
1642                "SELECT _ALL_ " +
1643                "FROM shipmentaliastypes, shipmentaliastypedetails " +
1644                "WHERE shpaltyp_activedetailid = shpaltypdt_shipmentaliastypedetailid AND shpaltypdt_shptyp_shipmenttypeid = ? " +
1645                "FOR UPDATE");
1646        getShipmentAliasTypesQueries = Collections.unmodifiableMap(queryMap);
1647    }
1648
1649    private List<ShipmentAliasType> getShipmentAliasTypes(ShipmentType shipmentType, EntityPermission entityPermission) {
1650        return ShipmentAliasTypeFactory.getInstance().getEntitiesFromQuery(entityPermission, getShipmentAliasTypesQueries, shipmentType);
1651    }
1652
1653    public List<ShipmentAliasType> getShipmentAliasTypes(ShipmentType shipmentType) {
1654        return getShipmentAliasTypes(shipmentType, EntityPermission.READ_ONLY);
1655    }
1656
1657    public List<ShipmentAliasType> getShipmentAliasTypesForUpdate(ShipmentType shipmentType) {
1658        return getShipmentAliasTypes(shipmentType, EntityPermission.READ_WRITE);
1659    }
1660
1661    public ShipmentAliasTypeTransfer getShipmentAliasTypeTransfer(UserVisit userVisit, ShipmentAliasType shipmentAliasType) {
1662        return getShipmentTransferCaches(userVisit).getShipmentAliasTypeTransferCache().getTransfer(shipmentAliasType);
1663    }
1664
1665    public List<ShipmentAliasTypeTransfer> getShipmentAliasTypeTransfers(UserVisit userVisit, ShipmentType shipmentType) {
1666        List<ShipmentAliasType> shipmentAliasTypes = getShipmentAliasTypes(shipmentType);
1667        List<ShipmentAliasTypeTransfer> shipmentAliasTypeTransfers = new ArrayList<>(shipmentAliasTypes.size());
1668        ShipmentAliasTypeTransferCache shipmentAliasTypeTransferCache = getShipmentTransferCaches(userVisit).getShipmentAliasTypeTransferCache();
1669
1670        shipmentAliasTypes.forEach((shipmentAliasType) ->
1671                shipmentAliasTypeTransfers.add(shipmentAliasTypeTransferCache.getTransfer(shipmentAliasType))
1672        );
1673
1674        return shipmentAliasTypeTransfers;
1675    }
1676
1677    public ShipmentAliasTypeChoicesBean getShipmentAliasTypeChoices(String defaultShipmentAliasTypeChoice, Language language,
1678            boolean allowNullChoice, ShipmentType shipmentType) {
1679        List<ShipmentAliasType> shipmentAliasTypes = getShipmentAliasTypes(shipmentType);
1680        var size = shipmentAliasTypes.size();
1681        var labels = new ArrayList<String>(size);
1682        var values = new ArrayList<String>(size);
1683        String defaultValue = null;
1684
1685        if(allowNullChoice) {
1686            labels.add("");
1687            values.add("");
1688
1689            if(defaultShipmentAliasTypeChoice == null) {
1690                defaultValue = "";
1691            }
1692        }
1693
1694        for(var shipmentAliasType : shipmentAliasTypes) {
1695            ShipmentAliasTypeDetail shipmentAliasTypeDetail = shipmentAliasType.getLastDetail();
1696
1697            var label = getBestShipmentAliasTypeDescription(shipmentAliasType, language);
1698            var value = shipmentAliasTypeDetail.getShipmentAliasTypeName();
1699
1700            labels.add(label == null? value: label);
1701            values.add(value);
1702
1703            var usingDefaultChoice = defaultShipmentAliasTypeChoice != null && defaultShipmentAliasTypeChoice.equals(value);
1704            if(usingDefaultChoice || (defaultValue == null && shipmentAliasTypeDetail.getIsDefault())) {
1705                defaultValue = value;
1706            }
1707        }
1708
1709        return new ShipmentAliasTypeChoicesBean(labels, values, defaultValue);
1710    }
1711
1712    private void updateShipmentAliasTypeFromValue(ShipmentAliasTypeDetailValue shipmentAliasTypeDetailValue, boolean checkDefault,
1713            BasePK updatedBy) {
1714        if(shipmentAliasTypeDetailValue.hasBeenModified()) {
1715            ShipmentAliasType shipmentAliasType = ShipmentAliasTypeFactory.getInstance().getEntityFromPK(EntityPermission.READ_WRITE,
1716                    shipmentAliasTypeDetailValue.getShipmentAliasTypePK());
1717            ShipmentAliasTypeDetail shipmentAliasTypeDetail = shipmentAliasType.getActiveDetailForUpdate();
1718
1719            shipmentAliasTypeDetail.setThruTime(session.START_TIME_LONG);
1720            shipmentAliasTypeDetail.store();
1721
1722            ShipmentAliasTypePK shipmentAliasTypePK = shipmentAliasTypeDetail.getShipmentAliasTypePK();
1723            ShipmentType shipmentType = shipmentAliasTypeDetail.getShipmentType();
1724            ShipmentTypePK shipmentTypePK = shipmentType.getPrimaryKey();
1725            String shipmentAliasTypeName = shipmentAliasTypeDetailValue.getShipmentAliasTypeName();
1726            String validationPattern = shipmentAliasTypeDetailValue.getValidationPattern();
1727            Boolean isDefault = shipmentAliasTypeDetailValue.getIsDefault();
1728            Integer sortOrder = shipmentAliasTypeDetailValue.getSortOrder();
1729
1730            if(checkDefault) {
1731                ShipmentAliasType defaultShipmentAliasType = getDefaultShipmentAliasType(shipmentType);
1732                boolean defaultFound = defaultShipmentAliasType != null && !defaultShipmentAliasType.equals(shipmentAliasType);
1733
1734                if(isDefault && defaultFound) {
1735                    // If I'm the default, and a default already existed...
1736                    ShipmentAliasTypeDetailValue defaultShipmentAliasTypeDetailValue = getDefaultShipmentAliasTypeDetailValueForUpdate(shipmentType);
1737
1738                    defaultShipmentAliasTypeDetailValue.setIsDefault(Boolean.FALSE);
1739                    updateShipmentAliasTypeFromValue(defaultShipmentAliasTypeDetailValue, false, updatedBy);
1740                } else if(!isDefault && !defaultFound) {
1741                    // If I'm not the default, and no other default exists...
1742                    isDefault = Boolean.TRUE;
1743                }
1744            }
1745
1746            shipmentAliasTypeDetail = ShipmentAliasTypeDetailFactory.getInstance().create(shipmentAliasTypePK, shipmentTypePK, shipmentAliasTypeName,
1747                    validationPattern, isDefault, sortOrder, session.START_TIME_LONG, Session.MAX_TIME_LONG);
1748
1749            shipmentAliasType.setActiveDetail(shipmentAliasTypeDetail);
1750            shipmentAliasType.setLastDetail(shipmentAliasTypeDetail);
1751
1752            sendEvent(shipmentAliasTypePK, EventTypes.MODIFY, null, null, updatedBy);
1753        }
1754    }
1755
1756    public void updateShipmentAliasTypeFromValue(ShipmentAliasTypeDetailValue shipmentAliasTypeDetailValue, BasePK updatedBy) {
1757        updateShipmentAliasTypeFromValue(shipmentAliasTypeDetailValue, true, updatedBy);
1758    }
1759
1760    public void deleteShipmentAliasType(ShipmentAliasType shipmentAliasType, BasePK deletedBy) {
1761        deleteShipmentAliasesByShipmentAliasType(shipmentAliasType, deletedBy);
1762        deleteShipmentAliasTypeDescriptionsByShipmentAliasType(shipmentAliasType, deletedBy);
1763
1764        ShipmentAliasTypeDetail shipmentAliasTypeDetail = shipmentAliasType.getLastDetailForUpdate();
1765        shipmentAliasTypeDetail.setThruTime(session.START_TIME_LONG);
1766        shipmentAliasType.setActiveDetail(null);
1767        shipmentAliasType.store();
1768
1769        // Check for default, and pick one if necessary
1770        ShipmentType shipmentType = shipmentAliasTypeDetail.getShipmentType();
1771        ShipmentAliasType defaultShipmentAliasType = getDefaultShipmentAliasType(shipmentType);
1772        if(defaultShipmentAliasType == null) {
1773            List<ShipmentAliasType> shipmentAliasTypes = getShipmentAliasTypesForUpdate(shipmentType);
1774
1775            if(!shipmentAliasTypes.isEmpty()) {
1776                Iterator<ShipmentAliasType> iter = shipmentAliasTypes.iterator();
1777                if(iter.hasNext()) {
1778                    defaultShipmentAliasType = iter.next();
1779                }
1780                ShipmentAliasTypeDetailValue shipmentAliasTypeDetailValue = Objects.requireNonNull(defaultShipmentAliasType).getLastDetailForUpdate().getShipmentAliasTypeDetailValue().clone();
1781
1782                shipmentAliasTypeDetailValue.setIsDefault(Boolean.TRUE);
1783                updateShipmentAliasTypeFromValue(shipmentAliasTypeDetailValue, false, deletedBy);
1784            }
1785        }
1786
1787        sendEvent(shipmentAliasType.getPrimaryKey(), EventTypes.DELETE, null, null, deletedBy);
1788    }
1789
1790    public void deleteShipmentAliasTypes(List<ShipmentAliasType> shipmentAliasTypes, BasePK deletedBy) {
1791        shipmentAliasTypes.forEach((shipmentAliasType) -> 
1792                deleteShipmentAliasType(shipmentAliasType, deletedBy)
1793        );
1794    }
1795
1796    public void deleteShipmentAliasTypesByShipmentType(ShipmentType shipmentType, BasePK deletedBy) {
1797        deleteShipmentAliasTypes(getShipmentAliasTypesForUpdate(shipmentType), deletedBy);
1798    }
1799
1800    // --------------------------------------------------------------------------------
1801    //   Shipment Alias Type Descriptions
1802    // --------------------------------------------------------------------------------
1803
1804    public ShipmentAliasTypeDescription createShipmentAliasTypeDescription(ShipmentAliasType shipmentAliasType, Language language, String description, BasePK createdBy) {
1805        ShipmentAliasTypeDescription shipmentAliasTypeDescription = ShipmentAliasTypeDescriptionFactory.getInstance().create(shipmentAliasType, language,
1806                description, session.START_TIME_LONG, Session.MAX_TIME_LONG);
1807
1808        sendEvent(shipmentAliasType.getPrimaryKey(), EventTypes.MODIFY, shipmentAliasTypeDescription.getPrimaryKey(), EventTypes.CREATE, createdBy);
1809
1810        return shipmentAliasTypeDescription;
1811    }
1812
1813    private static final Map<EntityPermission, String> getShipmentAliasTypeDescriptionQueries;
1814
1815    static {
1816        Map<EntityPermission, String> queryMap = new HashMap<>(2);
1817
1818        queryMap.put(EntityPermission.READ_ONLY,
1819                "SELECT _ALL_ " +
1820                "FROM shipmentaliastypedescriptions " +
1821                "WHERE shpaltypd_shpaltyp_shipmentaliastypeid = ? AND shpaltypd_lang_languageid = ? AND shpaltypd_thrutime = ?");
1822        queryMap.put(EntityPermission.READ_WRITE,
1823                "SELECT _ALL_ " +
1824                "FROM shipmentaliastypedescriptions " +
1825                "WHERE shpaltypd_shpaltyp_shipmentaliastypeid = ? AND shpaltypd_lang_languageid = ? AND shpaltypd_thrutime = ? " +
1826                "FOR UPDATE");
1827        getShipmentAliasTypeDescriptionQueries = Collections.unmodifiableMap(queryMap);
1828    }
1829
1830    private ShipmentAliasTypeDescription getShipmentAliasTypeDescription(ShipmentAliasType shipmentAliasType, Language language, EntityPermission entityPermission) {
1831        return ShipmentAliasTypeDescriptionFactory.getInstance().getEntityFromQuery(entityPermission, getShipmentAliasTypeDescriptionQueries,
1832                shipmentAliasType, language, Session.MAX_TIME);
1833    }
1834
1835    public ShipmentAliasTypeDescription getShipmentAliasTypeDescription(ShipmentAliasType shipmentAliasType, Language language) {
1836        return getShipmentAliasTypeDescription(shipmentAliasType, language, EntityPermission.READ_ONLY);
1837    }
1838
1839    public ShipmentAliasTypeDescription getShipmentAliasTypeDescriptionForUpdate(ShipmentAliasType shipmentAliasType, Language language) {
1840        return getShipmentAliasTypeDescription(shipmentAliasType, language, EntityPermission.READ_WRITE);
1841    }
1842
1843    public ShipmentAliasTypeDescriptionValue getShipmentAliasTypeDescriptionValue(ShipmentAliasTypeDescription shipmentAliasTypeDescription) {
1844        return shipmentAliasTypeDescription == null? null: shipmentAliasTypeDescription.getShipmentAliasTypeDescriptionValue().clone();
1845    }
1846
1847    public ShipmentAliasTypeDescriptionValue getShipmentAliasTypeDescriptionValueForUpdate(ShipmentAliasType shipmentAliasType, Language language) {
1848        return getShipmentAliasTypeDescriptionValue(getShipmentAliasTypeDescriptionForUpdate(shipmentAliasType, language));
1849    }
1850
1851    private static final Map<EntityPermission, String> getShipmentAliasTypeDescriptionsByShipmentAliasTypeQueries;
1852
1853    static {
1854        Map<EntityPermission, String> queryMap = new HashMap<>(2);
1855
1856        queryMap.put(EntityPermission.READ_ONLY,
1857                "SELECT _ALL_ " +
1858                "FROM shipmentaliastypedescriptions, languages " +
1859                "WHERE shpaltypd_shpaltyp_shipmentaliastypeid = ? AND shpaltypd_thrutime = ? AND shpaltypd_lang_languageid = lang_languageid " +
1860                "ORDER BY lang_sortorder, lang_languageisoname");
1861        queryMap.put(EntityPermission.READ_WRITE,
1862                "SELECT _ALL_ " +
1863                "FROM shipmentaliastypedescriptions " +
1864                "WHERE shpaltypd_shpaltyp_shipmentaliastypeid = ? AND shpaltypd_thrutime = ? " +
1865                "FOR UPDATE");
1866        getShipmentAliasTypeDescriptionsByShipmentAliasTypeQueries = Collections.unmodifiableMap(queryMap);
1867    }
1868
1869    private List<ShipmentAliasTypeDescription> getShipmentAliasTypeDescriptionsByShipmentAliasType(ShipmentAliasType shipmentAliasType, EntityPermission entityPermission) {
1870        return ShipmentAliasTypeDescriptionFactory.getInstance().getEntitiesFromQuery(entityPermission, getShipmentAliasTypeDescriptionsByShipmentAliasTypeQueries,
1871                shipmentAliasType, Session.MAX_TIME);
1872    }
1873
1874    public List<ShipmentAliasTypeDescription> getShipmentAliasTypeDescriptionsByShipmentAliasType(ShipmentAliasType shipmentAliasType) {
1875        return getShipmentAliasTypeDescriptionsByShipmentAliasType(shipmentAliasType, EntityPermission.READ_ONLY);
1876    }
1877
1878    public List<ShipmentAliasTypeDescription> getShipmentAliasTypeDescriptionsByShipmentAliasTypeForUpdate(ShipmentAliasType shipmentAliasType) {
1879        return getShipmentAliasTypeDescriptionsByShipmentAliasType(shipmentAliasType, EntityPermission.READ_WRITE);
1880    }
1881
1882    public String getBestShipmentAliasTypeDescription(ShipmentAliasType shipmentAliasType, Language language) {
1883        String description;
1884        ShipmentAliasTypeDescription shipmentAliasTypeDescription = getShipmentAliasTypeDescription(shipmentAliasType, language);
1885
1886        if(shipmentAliasTypeDescription == null && !language.getIsDefault()) {
1887            shipmentAliasTypeDescription = getShipmentAliasTypeDescription(shipmentAliasType, getPartyControl().getDefaultLanguage());
1888        }
1889
1890        if(shipmentAliasTypeDescription == null) {
1891            description = shipmentAliasType.getLastDetail().getShipmentAliasTypeName();
1892        } else {
1893            description = shipmentAliasTypeDescription.getDescription();
1894        }
1895
1896        return description;
1897    }
1898
1899    public ShipmentAliasTypeDescriptionTransfer getShipmentAliasTypeDescriptionTransfer(UserVisit userVisit, ShipmentAliasTypeDescription shipmentAliasTypeDescription) {
1900        return getShipmentTransferCaches(userVisit).getShipmentAliasTypeDescriptionTransferCache().getTransfer(shipmentAliasTypeDescription);
1901    }
1902
1903    public List<ShipmentAliasTypeDescriptionTransfer> getShipmentAliasTypeDescriptionTransfersByShipmentAliasType(UserVisit userVisit, ShipmentAliasType shipmentAliasType) {
1904        List<ShipmentAliasTypeDescription> shipmentAliasTypeDescriptions = getShipmentAliasTypeDescriptionsByShipmentAliasType(shipmentAliasType);
1905        List<ShipmentAliasTypeDescriptionTransfer> shipmentAliasTypeDescriptionTransfers = new ArrayList<>(shipmentAliasTypeDescriptions.size());
1906        ShipmentAliasTypeDescriptionTransferCache shipmentAliasTypeDescriptionTransferCache = getShipmentTransferCaches(userVisit).getShipmentAliasTypeDescriptionTransferCache();
1907
1908        shipmentAliasTypeDescriptions.forEach((shipmentAliasTypeDescription) ->
1909                shipmentAliasTypeDescriptionTransfers.add(shipmentAliasTypeDescriptionTransferCache.getTransfer(shipmentAliasTypeDescription))
1910        );
1911
1912        return shipmentAliasTypeDescriptionTransfers;
1913    }
1914
1915    public void updateShipmentAliasTypeDescriptionFromValue(ShipmentAliasTypeDescriptionValue shipmentAliasTypeDescriptionValue, BasePK updatedBy) {
1916        if(shipmentAliasTypeDescriptionValue.hasBeenModified()) {
1917            ShipmentAliasTypeDescription shipmentAliasTypeDescription = ShipmentAliasTypeDescriptionFactory.getInstance().getEntityFromPK(EntityPermission.READ_WRITE,
1918                     shipmentAliasTypeDescriptionValue.getPrimaryKey());
1919
1920            shipmentAliasTypeDescription.setThruTime(session.START_TIME_LONG);
1921            shipmentAliasTypeDescription.store();
1922
1923            ShipmentAliasType shipmentAliasType = shipmentAliasTypeDescription.getShipmentAliasType();
1924            Language language = shipmentAliasTypeDescription.getLanguage();
1925            String description = shipmentAliasTypeDescriptionValue.getDescription();
1926
1927            shipmentAliasTypeDescription = ShipmentAliasTypeDescriptionFactory.getInstance().create(shipmentAliasType, language, description,
1928                    session.START_TIME_LONG, Session.MAX_TIME_LONG);
1929
1930            sendEvent(shipmentAliasType.getPrimaryKey(), EventTypes.MODIFY, shipmentAliasTypeDescription.getPrimaryKey(), EventTypes.MODIFY, updatedBy);
1931        }
1932    }
1933
1934    public void deleteShipmentAliasTypeDescription(ShipmentAliasTypeDescription shipmentAliasTypeDescription, BasePK deletedBy) {
1935        shipmentAliasTypeDescription.setThruTime(session.START_TIME_LONG);
1936
1937        sendEvent(shipmentAliasTypeDescription.getShipmentAliasTypePK(), EventTypes.MODIFY, shipmentAliasTypeDescription.getPrimaryKey(), EventTypes.DELETE, deletedBy);
1938
1939    }
1940
1941    public void deleteShipmentAliasTypeDescriptionsByShipmentAliasType(ShipmentAliasType shipmentAliasType, BasePK deletedBy) {
1942        List<ShipmentAliasTypeDescription> shipmentAliasTypeDescriptions = getShipmentAliasTypeDescriptionsByShipmentAliasTypeForUpdate(shipmentAliasType);
1943
1944        shipmentAliasTypeDescriptions.forEach((shipmentAliasTypeDescription) -> 
1945                deleteShipmentAliasTypeDescription(shipmentAliasTypeDescription, deletedBy)
1946        );
1947    }
1948
1949    // --------------------------------------------------------------------------------
1950    //   Shipment Aliases
1951    // --------------------------------------------------------------------------------
1952
1953    public ShipmentAlias createShipmentAlias(Shipment shipment, ShipmentAliasType shipmentAliasType, String alias, BasePK createdBy) {
1954        ShipmentAlias shipmentAlias = ShipmentAliasFactory.getInstance().create(shipment, shipmentAliasType, alias, session.START_TIME_LONG, Session.MAX_TIME_LONG);
1955
1956        sendEvent(shipment.getPrimaryKey(), EventTypes.MODIFY, shipmentAlias.getPrimaryKey(), EventTypes.CREATE, createdBy);
1957
1958        return shipmentAlias;
1959    }
1960
1961    private static final Map<EntityPermission, String> getShipmentAliasQueries;
1962
1963    static {
1964        Map<EntityPermission, String> queryMap = new HashMap<>(2);
1965
1966        queryMap.put(EntityPermission.READ_ONLY,
1967                "SELECT _ALL_ " +
1968                "FROM shipmentaliases " +
1969                "WHERE shpal_shp_shipmentid = ? AND shpal_shpaltyp_shipmentaliastypeid = ? AND shpal_thrutime = ?");
1970        queryMap.put(EntityPermission.READ_WRITE,
1971                "SELECT _ALL_ " +
1972                "FROM shipmentaliases " +
1973                "WHERE shpal_shp_shipmentid = ? AND shpal_shpaltyp_shipmentaliastypeid = ? AND shpal_thrutime = ? " +
1974                "FOR UPDATE");
1975        getShipmentAliasQueries = Collections.unmodifiableMap(queryMap);
1976    }
1977
1978    private ShipmentAlias getShipmentAlias(Shipment shipment, ShipmentAliasType shipmentAliasType, EntityPermission entityPermission) {
1979        return ShipmentAliasFactory.getInstance().getEntityFromQuery(entityPermission, getShipmentAliasQueries,
1980                shipment, shipmentAliasType, Session.MAX_TIME);
1981    }
1982
1983    public ShipmentAlias getShipmentAlias(Shipment shipment, ShipmentAliasType shipmentAliasType) {
1984        return getShipmentAlias(shipment, shipmentAliasType, EntityPermission.READ_ONLY);
1985    }
1986
1987    public ShipmentAlias getShipmentAliasForUpdate(Shipment shipment, ShipmentAliasType shipmentAliasType) {
1988        return getShipmentAlias(shipment, shipmentAliasType, EntityPermission.READ_WRITE);
1989    }
1990
1991    public ShipmentAliasValue getShipmentAliasValue(ShipmentAlias shipmentAlias) {
1992        return shipmentAlias == null? null: shipmentAlias.getShipmentAliasValue().clone();
1993    }
1994
1995    public ShipmentAliasValue getShipmentAliasValueForUpdate(Shipment shipment, ShipmentAliasType shipmentAliasType) {
1996        return getShipmentAliasValue(getShipmentAliasForUpdate(shipment, shipmentAliasType));
1997    }
1998
1999    private static final Map<EntityPermission, String> getShipmentAliasByAliasQueries;
2000
2001    static {
2002        Map<EntityPermission, String> queryMap = new HashMap<>(2);
2003
2004        queryMap.put(EntityPermission.READ_ONLY,
2005                "SELECT _ALL_ " +
2006                "FROM shipmentaliases " +
2007                "WHERE shpal_shpaltyp_shipmentaliastypeid = ? AND shpal_alias = ? AND shpal_thrutime = ?");
2008        queryMap.put(EntityPermission.READ_WRITE,
2009                "SELECT _ALL_ " +
2010                "FROM shipmentaliases " +
2011                "WHERE shpal_shpaltyp_shipmentaliastypeid = ? AND shpal_alias = ? AND shpal_thrutime = ? " +
2012                "FOR UPDATE");
2013        getShipmentAliasByAliasQueries = Collections.unmodifiableMap(queryMap);
2014    }
2015
2016    private ShipmentAlias getShipmentAliasByAlias(ShipmentAliasType shipmentAliasType, String alias, EntityPermission entityPermission) {
2017        return ShipmentAliasFactory.getInstance().getEntityFromQuery(entityPermission, getShipmentAliasByAliasQueries, shipmentAliasType, alias, Session.MAX_TIME);
2018    }
2019
2020    public ShipmentAlias getShipmentAliasByAlias(ShipmentAliasType shipmentAliasType, String alias) {
2021        return getShipmentAliasByAlias(shipmentAliasType, alias, EntityPermission.READ_ONLY);
2022    }
2023
2024    public ShipmentAlias getShipmentAliasByAliasForUpdate(ShipmentAliasType shipmentAliasType, String alias) {
2025        return getShipmentAliasByAlias(shipmentAliasType, alias, EntityPermission.READ_WRITE);
2026    }
2027
2028    private static final Map<EntityPermission, String> getShipmentAliasesByShipmentQueries;
2029
2030    static {
2031        Map<EntityPermission, String> queryMap = new HashMap<>(2);
2032
2033        queryMap.put(EntityPermission.READ_ONLY,
2034                "SELECT _ALL_ " +
2035                "FROM shipmentaliases, shipmentaliastypes, shipmentaliastypedetails " +
2036                "WHERE shpal_shp_shipmentid = ? AND shpal_thrutime = ? " +
2037                "AND shpal_shpaltyp_shipmentaliastypeid = shpaltyp_shipmentaliastypeid AND shpaltyp_lastdetailid = shpaltypdt_shipmentaliastypedetailid" +
2038                "ORDER BY shpaltypdt_sortorder, shpaltypdt_shipmentaliastypename");
2039        queryMap.put(EntityPermission.READ_WRITE,
2040                "SELECT _ALL_ " +
2041                "FROM shipmentaliases " +
2042                "WHERE shpal_shp_shipmentid = ? AND shpal_thrutime = ? " +
2043                "FOR UPDATE");
2044        getShipmentAliasesByShipmentQueries = Collections.unmodifiableMap(queryMap);
2045    }
2046
2047    private List<ShipmentAlias> getShipmentAliasesByShipment(Shipment shipment, EntityPermission entityPermission) {
2048        return ShipmentAliasFactory.getInstance().getEntitiesFromQuery(entityPermission, getShipmentAliasesByShipmentQueries,
2049                shipment, Session.MAX_TIME);
2050    }
2051
2052    public List<ShipmentAlias> getShipmentAliasesByShipment(Shipment shipment) {
2053        return getShipmentAliasesByShipment(shipment, EntityPermission.READ_ONLY);
2054    }
2055
2056    public List<ShipmentAlias> getShipmentAliasesByShipmentForUpdate(Shipment shipment) {
2057        return getShipmentAliasesByShipment(shipment, EntityPermission.READ_WRITE);
2058    }
2059
2060    private static final Map<EntityPermission, String> getShipmentAliasesByShipmentAliasTypeQueries;
2061
2062    static {
2063        Map<EntityPermission, String> queryMap = new HashMap<>(2);
2064
2065        queryMap.put(EntityPermission.READ_ONLY,
2066                "SELECT _ALL_ " +
2067                "FROM shipmentaliases, shipmentes, shipmentdetails " +
2068                "WHERE shpal_shpaltyp_shipmentaliastypeid = ? AND shpal_thrutime = ? " +
2069                "AND shpal_shp_shipmentid = shp_shipmentid AND shp_lastdetailid = shpdt_shipmentdetailid " +
2070                "ORDER BY lang_sortorder, lang_languageisoname");
2071        queryMap.put(EntityPermission.READ_WRITE,
2072                "SELECT _ALL_ " +
2073                "FROM shipmentaliases " +
2074                "WHERE shpal_shpaltyp_shipmentaliastypeid = ? AND shpal_thrutime = ? " +
2075                "FOR UPDATE");
2076        getShipmentAliasesByShipmentAliasTypeQueries = Collections.unmodifiableMap(queryMap);
2077    }
2078
2079    private List<ShipmentAlias> getShipmentAliasesByShipmentAliasType(ShipmentAliasType shipmentAliasType, EntityPermission entityPermission) {
2080        return ShipmentAliasFactory.getInstance().getEntitiesFromQuery(entityPermission, getShipmentAliasesByShipmentAliasTypeQueries,
2081                shipmentAliasType, Session.MAX_TIME);
2082    }
2083
2084    public List<ShipmentAlias> getShipmentAliasesByShipmentAliasType(ShipmentAliasType shipmentAliasType) {
2085        return getShipmentAliasesByShipmentAliasType(shipmentAliasType, EntityPermission.READ_ONLY);
2086    }
2087
2088    public List<ShipmentAlias> getShipmentAliasesByShipmentAliasTypeForUpdate(ShipmentAliasType shipmentAliasType) {
2089        return getShipmentAliasesByShipmentAliasType(shipmentAliasType, EntityPermission.READ_WRITE);
2090    }
2091
2092    public ShipmentAliasTransfer getShipmentAliasTransfer(UserVisit userVisit, ShipmentAlias shipmentAlias) {
2093        return getShipmentTransferCaches(userVisit).getShipmentAliasTransferCache().getTransfer(shipmentAlias);
2094    }
2095
2096    public List<ShipmentAliasTransfer> getShipmentAliasTransfersByShipment(UserVisit userVisit, Shipment shipment) {
2097        List<ShipmentAlias> shipmentaliases = getShipmentAliasesByShipment(shipment);
2098        List<ShipmentAliasTransfer> shipmentAliasTransfers = new ArrayList<>(shipmentaliases.size());
2099        ShipmentAliasTransferCache shipmentAliasTransferCache = getShipmentTransferCaches(userVisit).getShipmentAliasTransferCache();
2100
2101        shipmentaliases.forEach((shipmentAlias) ->
2102                shipmentAliasTransfers.add(shipmentAliasTransferCache.getTransfer(shipmentAlias))
2103        );
2104
2105        return shipmentAliasTransfers;
2106    }
2107
2108    public void updateShipmentAliasFromValue(ShipmentAliasValue shipmentAliasValue, BasePK updatedBy) {
2109        if(shipmentAliasValue.hasBeenModified()) {
2110            ShipmentAlias shipmentAlias = ShipmentAliasFactory.getInstance().getEntityFromPK(EntityPermission.READ_WRITE, shipmentAliasValue.getPrimaryKey());
2111
2112            shipmentAlias.setThruTime(session.START_TIME_LONG);
2113            shipmentAlias.store();
2114
2115            ShipmentPK shipmentPK = shipmentAlias.getShipmentPK();
2116            ShipmentAliasTypePK shipmentAliasTypePK = shipmentAlias.getShipmentAliasTypePK();
2117            String alias  = shipmentAliasValue.getAlias();
2118
2119            shipmentAlias = ShipmentAliasFactory.getInstance().create(shipmentPK, shipmentAliasTypePK, alias, session.START_TIME_LONG, Session.MAX_TIME_LONG);
2120
2121            sendEvent(shipmentPK, EventTypes.MODIFY, shipmentAlias.getPrimaryKey(), EventTypes.MODIFY, updatedBy);
2122        }
2123    }
2124
2125    public void deleteShipmentAlias(ShipmentAlias shipmentAlias, BasePK deletedBy) {
2126        shipmentAlias.setThruTime(session.START_TIME_LONG);
2127
2128        sendEvent(shipmentAlias.getShipmentPK(), EventTypes.MODIFY, shipmentAlias.getPrimaryKey(), EventTypes.DELETE, deletedBy);
2129
2130    }
2131
2132    public void deleteShipmentAliasesByShipmentAliasType(ShipmentAliasType shipmentAliasType, BasePK deletedBy) {
2133        List<ShipmentAlias> shipmentaliases = getShipmentAliasesByShipmentAliasTypeForUpdate(shipmentAliasType);
2134
2135        shipmentaliases.forEach((shipmentAlias) -> 
2136                deleteShipmentAlias(shipmentAlias, deletedBy)
2137        );
2138    }
2139
2140    public void deleteShipmentAliasesByShipment(Shipment shipment, BasePK deletedBy) {
2141        List<ShipmentAlias> shipmentaliases = getShipmentAliasesByShipmentForUpdate(shipment);
2142
2143        shipmentaliases.forEach((shipmentAlias) -> 
2144                deleteShipmentAlias(shipmentAlias, deletedBy)
2145        );
2146    }
2147
2148    // --------------------------------------------------------------------------------
2149    //   Shipments
2150    // --------------------------------------------------------------------------------
2151
2152    public Shipment getShipmentByName(ShipmentType shipmentType, String shipmentName) {
2153        // TODO
2154        return null;
2155    }
2156
2157    public ShipmentTransfer getShipmentTransfer(UserVisit userVisit, Shipment shipment) {
2158        // TODO
2159        return null;
2160    }
2161
2162    public void deleteShipmentsByPartyContactMechanism(PartyContactMechanism partyContactMechanism, BasePK deletedBy) {
2163        // TODO
2164    }
2165    
2166}