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.item.server.graphql;
018
019import com.echothree.model.control.accounting.server.graphql.AccountingSecurityUtils;
020import com.echothree.model.control.accounting.server.graphql.ItemAccountingCategoryObject;
021import com.echothree.model.control.cancellationpolicy.server.graphql.CancellationPolicyObject;
022import com.echothree.model.control.cancellationpolicy.server.graphql.CancellationPolicySecurityUtils;
023import com.echothree.model.control.graphql.server.graphql.BaseEntityInstanceObject;
024import com.echothree.model.control.graphql.server.graphql.TimeObject;
025import com.echothree.model.control.graphql.server.graphql.count.Connections;
026import com.echothree.model.control.graphql.server.graphql.count.CountedObjects;
027import com.echothree.model.control.graphql.server.graphql.count.CountingDataConnectionFetcher;
028import com.echothree.model.control.graphql.server.graphql.count.CountingPaginatedData;
029import com.echothree.model.control.graphql.server.util.BaseGraphQl;
030import com.echothree.model.control.graphql.server.util.count.ObjectLimiter;
031import com.echothree.model.control.item.common.ItemConstants;
032import com.echothree.model.control.item.common.workflow.ItemStatusConstants;
033import com.echothree.model.control.item.server.control.ItemControl;
034import com.echothree.model.control.offer.server.control.OfferItemControl;
035import com.echothree.model.control.offer.server.graphql.OfferItemObject;
036import com.echothree.model.control.offer.server.graphql.OfferSecurityUtils;
037import com.echothree.model.control.party.server.graphql.CompanyObject;
038import com.echothree.model.control.party.server.graphql.PartySecurityUtils;
039import com.echothree.model.control.returnpolicy.server.graphql.ReturnPolicyObject;
040import com.echothree.model.control.returnpolicy.server.graphql.ReturnPolicySecurityUtils;
041import com.echothree.model.control.sequence.server.graphql.SequenceObject;
042import com.echothree.model.control.sequence.server.graphql.SequenceSecurityUtils;
043import com.echothree.model.control.uom.server.graphql.UnitOfMeasureKindObject;
044import com.echothree.model.control.uom.server.graphql.UomSecurityUtils;
045import com.echothree.model.control.vendor.server.control.VendorControl;
046import com.echothree.model.control.vendor.server.graphql.ItemPurchasingCategoryObject;
047import com.echothree.model.control.vendor.server.graphql.VendorItemObject;
048import com.echothree.model.control.vendor.server.graphql.VendorSecurityUtils;
049import com.echothree.model.control.workflow.server.graphql.WorkflowEntityStatusObject;
050import com.echothree.model.data.item.common.ItemAliasConstants;
051import com.echothree.model.data.item.common.ItemPriceConstants;
052import com.echothree.model.data.item.common.ItemUnitOfMeasureTypeConstants;
053import com.echothree.model.data.item.common.RelatedItemTypeConstants;
054import com.echothree.model.data.item.server.entity.Item;
055import com.echothree.model.data.item.server.entity.ItemDetail;
056import com.echothree.model.data.item.server.entity.RelatedItemType;
057import com.echothree.model.data.offer.common.OfferItemConstants;
058import com.echothree.model.data.vendor.common.VendorItemConstants;
059import com.echothree.util.server.persistence.Session;
060import graphql.annotations.annotationTypes.GraphQLDescription;
061import graphql.annotations.annotationTypes.GraphQLField;
062import graphql.annotations.annotationTypes.GraphQLName;
063import graphql.annotations.annotationTypes.GraphQLNonNull;
064import graphql.annotations.connection.GraphQLConnection;
065import graphql.schema.DataFetchingEnvironment;
066import java.util.ArrayList;
067import java.util.stream.Collectors;
068
069@GraphQLDescription("item object")
070@GraphQLName("Item")
071public class ItemObject
072        extends BaseEntityInstanceObject {
073    
074    private final Item item; // Always Present
075    
076    public ItemObject(Item item) {
077        super(item.getPrimaryKey());
078
079        this.item = item;
080    }
081
082    private ItemDetail itemDetail; // Optional, use getItemDetail()
083    
084    private ItemDetail getItemDetail() {
085        if(itemDetail == null) {
086            itemDetail = item.getLastDetail();
087        }
088        
089        return itemDetail;
090    }
091    
092    @GraphQLField
093    @GraphQLDescription("item name")
094    @GraphQLNonNull
095    public String getItemName() {
096        return getItemDetail().getItemName();
097    }
098
099    @GraphQLField
100    @GraphQLDescription("item type")
101    @GraphQLNonNull
102    public ItemTypeObject getItemType(final DataFetchingEnvironment env) {
103        return ItemSecurityUtils.getHasItemTypeAccess(env) ? new ItemTypeObject(getItemDetail().getItemType()) : null;
104    }
105
106    @GraphQLField
107    @GraphQLDescription("item use type")
108    @GraphQLNonNull
109    public ItemUseTypeObject getItemUseType(final DataFetchingEnvironment env) {
110        return ItemSecurityUtils.getHasItemUseTypeAccess(env) ? new ItemUseTypeObject(getItemDetail().getItemUseType()) : null;
111    }
112
113    @GraphQLField
114    @GraphQLDescription("item category")
115    public ItemCategoryObject getItemCategory(final DataFetchingEnvironment env) {
116        return ItemSecurityUtils.getHasItemCategoryAccess(env) ? new ItemCategoryObject(getItemDetail().getItemCategory()) : null;
117    }
118
119    @GraphQLField
120    @GraphQLDescription("item accounting category")
121    public ItemAccountingCategoryObject getItemAccountingCategory(final DataFetchingEnvironment env) {
122        return AccountingSecurityUtils.getHasItemAccountingCategoryAccess(env) ? new ItemAccountingCategoryObject(getItemDetail().getItemAccountingCategory()) : null;
123    }
124
125    @GraphQLField
126    @GraphQLDescription("item purchasing category")
127    public ItemPurchasingCategoryObject getItemPurchasingCategory(final DataFetchingEnvironment env) {
128        return VendorSecurityUtils.getHasItemPurchasingCategoryAccess(env) ? new ItemPurchasingCategoryObject(getItemDetail().getItemPurchasingCategory()) : null;
129    }
130
131    @GraphQLField
132    @GraphQLDescription("company")
133    @GraphQLNonNull
134    public CompanyObject getCompany(final DataFetchingEnvironment env) {
135        var companyParty = getItemDetail().getCompanyParty();
136
137        return PartySecurityUtils.getHasPartyAccess(env, companyParty) ? new CompanyObject(companyParty) : null;
138    }
139
140    @GraphQLField
141    @GraphQLDescription("item delivery type")
142    @GraphQLNonNull
143    public ItemDeliveryTypeObject getItemDeliveryType(final DataFetchingEnvironment env) {
144        return ItemSecurityUtils.getHasItemDeliveryTypeAccess(env) ? new ItemDeliveryTypeObject(getItemDetail().getItemDeliveryType()) : null;
145    }
146
147    @GraphQLField
148    @GraphQLDescription("item inventory type")
149    @GraphQLNonNull
150    public ItemInventoryTypeObject getItemInventoryType(final DataFetchingEnvironment env) {
151        return ItemSecurityUtils.getHasItemInventoryTypeAccess(env) ? new ItemInventoryTypeObject(getItemDetail().getItemInventoryType()) : null;
152    }
153
154    @GraphQLField
155    @GraphQLDescription("inventory serialized")
156    public Boolean getInventorySerialized() {
157        return getItemDetail().getInventorySerialized();
158    }
159
160    @GraphQLField
161    @GraphQLDescription("serial number sequence")
162    public SequenceObject getSalesOrderSequence(final DataFetchingEnvironment env) {
163        var salesOrderSequence = getItemDetail().getSerialNumberSequence();
164
165        return salesOrderSequence == null ? null : (SequenceSecurityUtils.getHasSequenceAccess(env) ? new SequenceObject(salesOrderSequence) : null);
166    }
167
168    @GraphQLField
169    @GraphQLDescription("shipping charge exempt")
170    @GraphQLNonNull
171    public Boolean getShippingChargeExempt() {
172        return getItemDetail().getShippingChargeExempt();
173    }
174
175    @GraphQLField
176    @GraphQLDescription("shipping start time")
177    @GraphQLNonNull
178    public TimeObject getShippingStartTime(final DataFetchingEnvironment env) {
179        return new TimeObject(getItemDetail().getShippingStartTime());
180    }
181    
182    @GraphQLField
183    @GraphQLDescription("shipping end time")
184    public TimeObject getShippingEndTime(final DataFetchingEnvironment env) {
185        var shippingEndTime = getItemDetail().getShippingEndTime();
186
187        return shippingEndTime == null ? null : new TimeObject(shippingEndTime);
188    }
189    
190    @GraphQLField
191    @GraphQLDescription("sales order start time")
192    @GraphQLNonNull
193    public TimeObject getSalesOrderStartTime(final DataFetchingEnvironment env) {
194        return new TimeObject(getItemDetail().getSalesOrderStartTime());
195    }
196
197    @GraphQLField
198    @GraphQLDescription("sales order end time")
199    public TimeObject getSalesOrderEndTime(final DataFetchingEnvironment env) {
200        var salesOrderEndTime = getItemDetail().getSalesOrderEndTime();
201
202        return salesOrderEndTime == null ? null : new TimeObject(salesOrderEndTime);
203    }
204
205    @GraphQLField
206    @GraphQLDescription("purchase order start time")
207    public TimeObject getPurchaseOrderStartTime(final DataFetchingEnvironment env) {
208        var purchaseOrderStartTime = getItemDetail().getPurchaseOrderStartTime();
209
210        return purchaseOrderStartTime == null ? null : new TimeObject(purchaseOrderStartTime);
211    }
212    
213    @GraphQLField
214    @GraphQLDescription("purchase order end time")
215    public TimeObject getPurchaseOrderEndTime(final DataFetchingEnvironment env) {
216        var purchaseOrderEndTime = getItemDetail().getPurchaseOrderEndTime();
217
218        return purchaseOrderEndTime == null ? null : new TimeObject(purchaseOrderEndTime);
219    }
220
221    @GraphQLField
222    @GraphQLDescription("allow club discounts")
223    @GraphQLNonNull
224    public Boolean getAllowClubDiscounts() {
225        return getItemDetail().getAllowClubDiscounts();
226    }
227
228    @GraphQLField
229    @GraphQLDescription("allow coupon discounts")
230    @GraphQLNonNull
231    public Boolean getAllowCouponDiscounts() {
232        return getItemDetail().getAllowCouponDiscounts();
233    }
234
235    @GraphQLField
236    @GraphQLDescription("allow associate payments")
237    @GraphQLNonNull
238    public Boolean getAllowAssociatePayments() {
239        return getItemDetail().getAllowAssociatePayments();
240    }
241
242    @GraphQLField
243    @GraphQLDescription("unit of measure kind")
244    public UnitOfMeasureKindObject getUnitOfMeasureKind(final DataFetchingEnvironment env) {
245        return UomSecurityUtils.getHasUnitOfMeasureKindAccess(env) ? new UnitOfMeasureKindObject(getItemDetail().getUnitOfMeasureKind()) : null;
246    }
247
248    @GraphQLField
249    @GraphQLDescription("item price type")
250    public ItemPriceTypeObject getItemPriceType(final DataFetchingEnvironment env) {
251        return ItemSecurityUtils.getHasItemPriceTypeAccess(env) ? new ItemPriceTypeObject(getItemDetail().getItemPriceType()) : null;
252    }
253
254    @GraphQLField
255    @GraphQLDescription("cancellation policy")
256    public CancellationPolicyObject getCancellationPolicy(final DataFetchingEnvironment env) {
257        var cancellationPolicy = getItemDetail().getCancellationPolicy();
258
259        return cancellationPolicy == null ? null : (CancellationPolicySecurityUtils.getHasCancellationPolicyAccess(env) ? new CancellationPolicyObject(cancellationPolicy) : null);
260    }
261
262    @GraphQLField
263    @GraphQLDescription("return policy")
264    public ReturnPolicyObject getReturnPolicy(final DataFetchingEnvironment env) {
265        var returnPolicy = getItemDetail().getReturnPolicy();
266
267        return returnPolicy == null ? null : (ReturnPolicySecurityUtils.getHasReturnPolicyAccess(env) ? new ReturnPolicyObject(returnPolicy) : null);
268    }
269
270    //| itm_stylpth_stylepathid             | bigint      | YES  |     | NULL    |       |
271
272    @GraphQLField
273    @GraphQLDescription("itemPrices")
274    @GraphQLNonNull
275    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
276    public CountingPaginatedData<ItemPriceObject> getItemPrices(final DataFetchingEnvironment env) {
277        if(ItemSecurityUtils.getHasItemPricesAccess(env)) {
278            var itemControl = Session.getModelController(ItemControl.class);
279            var totalCount = itemControl.countItemPricesByItem(item);
280
281            try(var objectLimiter = new ObjectLimiter(env, ItemPriceConstants.COMPONENT_VENDOR_NAME, ItemPriceConstants.ENTITY_TYPE_NAME, totalCount)) {
282                var entities = itemControl.getItemPricesByItem(item);
283                var itemPrices = entities.stream().map(ItemPriceObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
284
285                return new CountedObjects<>(objectLimiter, itemPrices);
286            }
287        } else {
288            return Connections.emptyConnection();
289        }
290    }
291
292    @GraphQLField
293    @GraphQLDescription("item unit of measure types")
294    @GraphQLNonNull
295    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
296    public CountingPaginatedData<ItemUnitOfMeasureTypeObject> getItemUnitOfMeasureTypes(final DataFetchingEnvironment env) {
297        if(ItemSecurityUtils.getHasItemUnitOfMeasureTypesAccess(env)) {
298            var itemControl = Session.getModelController(ItemControl.class);
299            var totalCount = itemControl.countItemUnitOfMeasureTypesByItem(item);
300
301            try(var objectLimiter = new ObjectLimiter(env, ItemUnitOfMeasureTypeConstants.COMPONENT_VENDOR_NAME, ItemUnitOfMeasureTypeConstants.ENTITY_TYPE_NAME, totalCount)) {
302                var entities = itemControl.getItemUnitOfMeasureTypesByItem(item);
303                var itemAliass = entities.stream().map(ItemUnitOfMeasureTypeObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
304
305                return new CountedObjects<>(objectLimiter, itemAliass);
306            }
307        } else {
308            return Connections.emptyConnection();
309        }
310    }
311
312    @GraphQLField
313    @GraphQLDescription("item aliases")
314    @GraphQLNonNull
315    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
316    public CountingPaginatedData<ItemAliasObject> getItemAliases(final DataFetchingEnvironment env) {
317        if(ItemSecurityUtils.getHasItemAliasesAccess(env)) {
318            var itemControl = Session.getModelController(ItemControl.class);
319            var totalCount = itemControl.countItemAliasesByItem(item);
320
321            try(var objectLimiter = new ObjectLimiter(env, ItemAliasConstants.COMPONENT_VENDOR_NAME, ItemAliasConstants.ENTITY_TYPE_NAME, totalCount)) {
322                var entities = itemControl.getItemAliasesByItem(item);
323                var itemAliases = entities.stream().map(ItemAliasObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
324
325                return new CountedObjects<>(objectLimiter, itemAliases);
326            }
327        } else {
328            return Connections.emptyConnection();
329        }
330    }
331
332    @GraphQLField
333    @GraphQLDescription("description")
334    public String getDescription(final DataFetchingEnvironment env) {
335        var itemControl = Session.getModelController(ItemControl.class);
336        var itemDescriptionType = itemControl.getItemDescriptionTypeByName(ItemConstants.ItemDescriptionType_DEFAULT_DESCRIPTION);
337
338        return itemDescriptionType == null ? null : itemControl.getBestItemStringDescription(itemDescriptionType, item, BaseGraphQl.getLanguageEntity(env));
339    }
340
341    @GraphQLField
342    @GraphQLDescription("item status")
343    public WorkflowEntityStatusObject getItemStatus(final DataFetchingEnvironment env) {
344        return getWorkflowEntityStatusObject(env, ItemStatusConstants.Workflow_ITEM_STATUS);
345    }
346
347    @GraphQLField
348    @GraphQLDescription("offer items")
349    @GraphQLNonNull
350    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
351    public CountingPaginatedData<OfferItemObject> getOfferItems(final DataFetchingEnvironment env) {
352        if(OfferSecurityUtils.getHasOfferItemsAccess(env)) {
353            var offerItemControl = Session.getModelController(OfferItemControl.class);
354            var totalCount = offerItemControl.countOfferItemsByItem(item);
355
356            try(var objectLimiter = new ObjectLimiter(env, OfferItemConstants.COMPONENT_VENDOR_NAME, OfferItemConstants.ENTITY_TYPE_NAME, totalCount)) {
357                var entities = offerItemControl.getOfferItemsByItem(item);
358                var offerItems = entities.stream().map(OfferItemObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
359
360                return new CountedObjects<>(objectLimiter, offerItems);
361            }
362        } else {
363            return Connections.emptyConnection();
364        }
365    }
366
367    @GraphQLField
368    @GraphQLDescription("related item types")
369    @GraphQLNonNull
370    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
371    public CountingPaginatedData<RelatedItemTypeObject> getRelatedItemTypes(final DataFetchingEnvironment env) {
372        if(ItemSecurityUtils.getHasRelatedItemTypesAccess(env)) {
373            var itemControl = Session.getModelController(ItemControl.class);
374            var totalCount = itemControl.countRelatedItemTypes();
375
376            try(var objectLimiter = new ObjectLimiter(env, RelatedItemTypeConstants.COMPONENT_VENDOR_NAME, RelatedItemTypeConstants.ENTITY_TYPE_NAME, totalCount)) {
377                var entities = itemControl.getRelatedItemTypes();
378                var relatedItemTypes = entities.stream()
379                        .map((RelatedItemType relatedItemType) -> new RelatedItemTypeObject(relatedItemType, item))
380                        .collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
381
382                return new CountedObjects<>(objectLimiter, relatedItemTypes);
383            }
384        } else {
385            return Connections.emptyConnection();
386        }
387    }
388
389
390    @GraphQLField
391    @GraphQLDescription("vendor items")
392    @GraphQLNonNull
393    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
394    public CountingPaginatedData<VendorItemObject> getVendorItems(final DataFetchingEnvironment env) {
395        if(VendorSecurityUtils.getHasVendorItemsAccess(env)) {
396            var itemControl = Session.getModelController(VendorControl.class);
397            var totalCount = itemControl.countVendorItemsByItem(item);
398
399            try(var objectLimiter = new ObjectLimiter(env, VendorItemConstants.COMPONENT_VENDOR_NAME, VendorItemConstants.ENTITY_TYPE_NAME, totalCount)) {
400                var entities = itemControl.getVendorItemsByItem(item);
401                var items = entities.stream().map(VendorItemObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
402
403                return new CountedObjects<>(objectLimiter, items);
404            }
405        } else {
406            return Connections.emptyConnection();
407        }
408    }
409
410}