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