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