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.offer.server.graphql;
018
019import com.echothree.model.control.filter.server.graphql.FilterObject;
020import com.echothree.model.control.filter.server.graphql.FilterSecurityUtils;
021import com.echothree.model.control.graphql.server.graphql.BaseEntityInstanceObject;
022import com.echothree.model.control.graphql.server.graphql.count.Connections;
023import com.echothree.model.control.graphql.server.graphql.count.CountedObjects;
024import com.echothree.model.control.graphql.server.graphql.count.CountingDataConnectionFetcher;
025import com.echothree.model.control.graphql.server.graphql.count.CountingPaginatedData;
026import com.echothree.model.control.graphql.server.util.BaseGraphQl;
027import com.echothree.model.control.graphql.server.util.count.ObjectLimiter;
028import com.echothree.model.control.offer.server.control.OfferControl;
029import com.echothree.model.control.offer.server.control.OfferItemControl;
030import com.echothree.model.control.offer.server.control.OfferUseControl;
031import com.echothree.model.control.party.server.graphql.DepartmentObject;
032import com.echothree.model.control.party.server.graphql.PartySecurityUtils;
033import com.echothree.model.control.selector.server.graphql.SelectorObject;
034import com.echothree.model.control.selector.server.graphql.SelectorSecurityUtils;
035import com.echothree.model.control.sequence.server.graphql.SequenceObject;
036import com.echothree.model.control.sequence.server.graphql.SequenceSecurityUtils;
037import com.echothree.model.control.user.server.control.UserControl;
038import com.echothree.model.data.offer.common.OfferCustomerTypeConstants;
039import com.echothree.model.data.offer.common.OfferItemConstants;
040import com.echothree.model.data.offer.common.OfferUseConstants;
041import com.echothree.model.data.offer.server.entity.Offer;
042import com.echothree.model.data.offer.server.entity.OfferDetail;
043import com.echothree.util.server.persistence.Session;
044import graphql.annotations.annotationTypes.GraphQLDescription;
045import graphql.annotations.annotationTypes.GraphQLField;
046import graphql.annotations.annotationTypes.GraphQLName;
047import graphql.annotations.annotationTypes.GraphQLNonNull;
048import graphql.annotations.connection.GraphQLConnection;
049import graphql.schema.DataFetchingEnvironment;
050import java.util.ArrayList;
051import java.util.stream.Collectors;
052
053@GraphQLDescription("offer object")
054@GraphQLName("Offer")
055public class OfferObject
056        extends BaseEntityInstanceObject {
057    
058    private final Offer offer; // Always Present
059    
060    public OfferObject(Offer offer) {
061        super(offer.getPrimaryKey());
062        
063        this.offer = offer;
064    }
065
066    private OfferDetail offerDetail; // Optional, offer getOfferDetail()
067    
068    private OfferDetail getOfferDetail() {
069        if(offerDetail == null) {
070            offerDetail = offer.getLastDetail();
071        }
072        
073        return offerDetail;
074    }
075    
076    @GraphQLField
077    @GraphQLDescription("offer name")
078    @GraphQLNonNull
079    public String getOfferName() {
080        return getOfferDetail().getOfferName();
081    }
082
083    @GraphQLField
084    @GraphQLDescription("sales order sequence")
085    public SequenceObject getSalesOrderSequence(final DataFetchingEnvironment env) {
086        if(SequenceSecurityUtils.getHasSequenceAccess(env)) {
087            var salesOrderSequence = getOfferDetail().getSalesOrderSequence();
088
089            return salesOrderSequence == null ? null : new SequenceObject(salesOrderSequence);
090        } else {
091            return null;
092        }
093    }
094
095    @GraphQLField
096    @GraphQLDescription("department")
097    public DepartmentObject getDepartment(final DataFetchingEnvironment env) {
098        var departmentParty = getOfferDetail().getDepartmentParty();
099
100        return PartySecurityUtils.getHasPartyAccess(env, departmentParty) ? new DepartmentObject(departmentParty) : null;
101    }
102
103    @GraphQLField
104    @GraphQLDescription("offer item selector")
105    public SelectorObject getOfferItemSelector(final DataFetchingEnvironment env) {
106        if(SelectorSecurityUtils.getHasSelectorAccess(env)) {
107            var offerItemSelector = getOfferDetail().getOfferItemSelector();
108
109            return offerItemSelector == null ? null : new SelectorObject(offerItemSelector);
110        } else {
111            return null;
112        }
113    }
114
115    @GraphQLField
116    @GraphQLDescription("offer item price filter")
117    public FilterObject getOfferItemPriceFilter(final DataFetchingEnvironment env) {
118        if(FilterSecurityUtils.getHasFilterAccess(env)) {
119            var offerItemPriceFilter = getOfferDetail().getOfferItemPriceFilter();
120
121            return offerItemPriceFilter == null ? null : new FilterObject(offerItemPriceFilter);
122        } else {
123            return null;
124        }
125    }
126
127    @GraphQLField
128    @GraphQLDescription("is default")
129    @GraphQLNonNull
130    public boolean getIsDefault() {
131        return getOfferDetail().getIsDefault();
132    }
133    
134    @GraphQLField
135    @GraphQLDescription("sort order")
136    @GraphQLNonNull
137    public int getSortOrder() {
138        return getOfferDetail().getSortOrder();
139    }
140    
141    @GraphQLField
142    @GraphQLDescription("description")
143    @GraphQLNonNull
144    public String getDescription(final DataFetchingEnvironment env) {
145        var offerControl = Session.getModelController(OfferControl.class);
146        var userControl = Session.getModelController(UserControl.class);
147
148        return offerControl.getBestOfferDescription(offer, userControl.getPreferredLanguageFromUserVisit(BaseGraphQl.getUserVisit(env)));
149    }
150
151    @GraphQLField
152    @GraphQLDescription("offer uses")
153    @GraphQLNonNull
154    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
155    public CountingPaginatedData<OfferUseObject> getOfferUses(final DataFetchingEnvironment env) {
156        if(OfferSecurityUtils.getHasOfferUsesAccess(env)) {
157            var offerUseControl = Session.getModelController(OfferUseControl.class);
158            var totalCount = offerUseControl.countOfferUsesByOffer(offer);
159
160            try(var objectLimiter = new ObjectLimiter(env, OfferUseConstants.COMPONENT_VENDOR_NAME, OfferUseConstants.ENTITY_TYPE_NAME, totalCount)) {
161                var entities = offerUseControl.getOfferUsesByOffer(offer);
162                var offerUses = entities.stream().map(OfferUseObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
163
164                return new CountedObjects<>(objectLimiter, offerUses);
165            }
166        } else {
167            return Connections.emptyConnection();
168        }
169    }
170
171    @GraphQLField
172    @GraphQLDescription("offer items")
173    @GraphQLNonNull
174    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
175    public CountingPaginatedData<OfferItemObject> getOfferItems(final DataFetchingEnvironment env) {
176        if(OfferSecurityUtils.getHasOfferItemsAccess(env)) {
177            var offerItemControl = Session.getModelController(OfferItemControl.class);
178            var totalCount = offerItemControl.countOfferItemsByOffer(offer);
179
180            try(var objectLimiter = new ObjectLimiter(env, OfferItemConstants.COMPONENT_VENDOR_NAME, OfferItemConstants.ENTITY_TYPE_NAME, totalCount)) {
181                var entities = offerItemControl.getOfferItemsByOffer(offer);
182                var offerItems = entities.stream().map(OfferItemObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
183
184                return new CountedObjects<>(objectLimiter, offerItems);
185            }
186        } else {
187            return Connections.emptyConnection();
188        }
189    }
190
191    @GraphQLField
192    @GraphQLDescription("offer customer types")
193    @GraphQLNonNull
194    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
195    public CountingPaginatedData<OfferCustomerTypeObject> getOfferCustomerTypes(final DataFetchingEnvironment env) {
196        if(OfferSecurityUtils.getHasOfferCustomerTypesAccess(env)) {
197            var offerCustomerTypeControl = Session.getModelController(OfferControl.class);
198            var totalCount = offerCustomerTypeControl.countOfferCustomerTypesByOffer(offer);
199
200            try(var objectLimiter = new ObjectLimiter(env, OfferCustomerTypeConstants.COMPONENT_VENDOR_NAME, OfferCustomerTypeConstants.ENTITY_TYPE_NAME, totalCount)) {
201                var entities = offerCustomerTypeControl.getOfferCustomerTypesByOffer(offer);
202                var offerCustomerTypes = entities.stream().map(OfferCustomerTypeObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
203
204                return new CountedObjects<>(objectLimiter, offerCustomerTypes);
205            }
206        } else {
207            return Connections.emptyConnection();
208        }
209    }
210
211}