001// --------------------------------------------------------------------------------
002// Copyright 2002-2025 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.accounting.server.graphql;
018
019import com.echothree.model.control.accounting.common.workflow.TransactionStatusConstants;
020import com.echothree.model.control.accounting.server.control.AccountingControl;
021import com.echothree.model.control.accounting.server.control.TransactionTimeControl;
022import com.echothree.model.control.graphql.server.graphql.BaseEntityInstanceObject;
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.count.ObjectLimiter;
027import com.echothree.model.control.party.server.graphql.PartyObject;
028import com.echothree.model.control.party.server.graphql.PartySecurityUtils;
029import com.echothree.model.control.workflow.server.graphql.WorkflowEntityStatusObject;
030import com.echothree.model.data.accounting.common.TransactionEntityRoleConstants;
031import com.echothree.model.data.accounting.common.TransactionGlEntryConstants;
032import com.echothree.model.data.accounting.common.TransactionTimeConstants;
033import com.echothree.model.data.accounting.server.entity.Transaction;
034import com.echothree.model.data.accounting.server.entity.TransactionDetail;
035import com.echothree.util.server.persistence.Session;
036import graphql.annotations.annotationTypes.GraphQLDescription;
037import graphql.annotations.annotationTypes.GraphQLField;
038import graphql.annotations.annotationTypes.GraphQLName;
039import graphql.annotations.annotationTypes.GraphQLNonNull;
040import graphql.annotations.connection.GraphQLConnection;
041import graphql.schema.DataFetchingEnvironment;
042import java.util.ArrayList;
043import java.util.stream.Collectors;
044
045@GraphQLDescription("transaction object")
046@GraphQLName("Transaction")
047public class TransactionObject
048        extends BaseEntityInstanceObject {
049    
050    private final Transaction transaction; // Always Present
051    
052    public TransactionObject(Transaction transaction) {
053        super(transaction.getPrimaryKey());
054        
055        this.transaction = transaction;
056    }
057
058    private TransactionDetail transactionDetail; // Optional, use getTransactionDetail()
059    
060    private TransactionDetail getTransactionDetail() {
061        if(transactionDetail == null) {
062            transactionDetail = transaction.getLastDetail();
063        }
064        
065        return transactionDetail;
066    }
067    
068    @GraphQLField
069    @GraphQLDescription("transaction group name")
070    @GraphQLNonNull
071    public String getTransactionName() {
072        return getTransactionDetail().getTransactionName();
073    }
074
075    @GraphQLField
076    @GraphQLDescription("group party")
077    public PartyObject getGroupParty(final DataFetchingEnvironment env) {
078        var groupParty = getTransactionDetail().getGroupParty();
079
080        return PartySecurityUtils.getHasPartyAccess(env, groupParty) ? new PartyObject(groupParty) : null;
081    }
082
083    @GraphQLField
084    @GraphQLDescription("transaction group")
085    public TransactionGroupObject getTransactionGroup(final DataFetchingEnvironment env) {
086        var transactionGroup = getTransactionDetail().getTransactionGroup();
087
088        return AccountingSecurityUtils.getHasTransactionGroupAccess(env) ? new TransactionGroupObject(transactionGroup) : null;
089    }
090
091    @GraphQLField
092    @GraphQLDescription("transaction type")
093    public TransactionTypeObject getTransactionType(final DataFetchingEnvironment env) {
094        var transactionType = getTransactionDetail().getTransactionType();
095
096        return AccountingSecurityUtils.getHasTransactionTypeAccess(env) ? new TransactionTypeObject(transactionType) : null;
097    }
098
099    @GraphQLField
100    @GraphQLDescription("transaction status")
101    public WorkflowEntityStatusObject getTransactionStatus(final DataFetchingEnvironment env) {
102        return getWorkflowEntityStatusObject(env, TransactionStatusConstants.Workflow_TRANSACTION_STATUS);
103    }
104
105    @GraphQLField
106    @GraphQLDescription("transaction times")
107    @GraphQLNonNull
108    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
109    public CountingPaginatedData<TransactionTimeObject> getTransactionTimes(final DataFetchingEnvironment env) {
110//        if(AccountingSecurityUtils.getHasTransactionTimesAccess(env)) {
111            var transactionTimeControl = Session.getModelController(TransactionTimeControl.class);
112            var totalCount = transactionTimeControl.countTransactionTimesByTransaction(transaction);
113    
114            try(var objectLimiter = new ObjectLimiter(env, TransactionTimeConstants.COMPONENT_VENDOR_NAME, TransactionTimeConstants.ENTITY_TYPE_NAME, totalCount)) {
115                var entities = transactionTimeControl.getTransactionTimesByTransaction(transaction);
116                var objects = entities.stream().map(TransactionTimeObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
117    
118                return new CountedObjects<>(objectLimiter, objects);
119            }
120//        } else {
121//            return Connections.emptyConnection();
122//        }
123    }
124
125    @GraphQLField
126    @GraphQLDescription("transaction GL entries")
127    @GraphQLNonNull
128    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
129    public CountingPaginatedData<TransactionGlEntryObject> getTransactionGlEntries(final DataFetchingEnvironment env) {
130//        if(AccountingSecurityUtils.getHasTransactionGlEntriesAccess(env)) {
131            var accountingControl = Session.getModelController(AccountingControl.class);
132            var totalCount = accountingControl.countTransactionGlEntryByTransaction(transaction);
133    
134            try(var objectLimiter = new ObjectLimiter(env, TransactionGlEntryConstants.COMPONENT_VENDOR_NAME, TransactionGlEntryConstants.ENTITY_TYPE_NAME, totalCount)) {
135                var entities = accountingControl.getTransactionGlEntriesByTransaction(transaction);
136                var objects = entities.stream().map(TransactionGlEntryObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
137    
138                return new CountedObjects<>(objectLimiter, objects);
139            }
140//        } else {
141//            return Connections.emptyConnection();
142//        }
143    }
144
145    @GraphQLField
146    @GraphQLDescription("transaction entity roles")
147    @GraphQLNonNull
148    @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class)
149    public CountingPaginatedData<TransactionEntityRoleObject> getTransactionEntityRoles(final DataFetchingEnvironment env) {
150//        if(AccountingSecurityUtils.getHasTransactionEntityRolesAccess(env)) {
151            var accountingControl = Session.getModelController(AccountingControl.class);
152            var totalCount = accountingControl.countTransactionEntityRolesByTransaction(transaction);
153
154            try(var objectLimiter = new ObjectLimiter(env, TransactionEntityRoleConstants.COMPONENT_VENDOR_NAME, TransactionEntityRoleConstants.ENTITY_TYPE_NAME, totalCount)) {
155                var entities = accountingControl.getTransactionEntityRolesByTransaction(transaction);
156                var objects = entities.stream().map(TransactionEntityRoleObject::new).collect(Collectors.toCollection(() -> new ArrayList<>(entities.size())));
157
158                return new CountedObjects<>(objectLimiter, objects);
159            }
160//        } else {
161//            return Connections.emptyConnection();
162//        }
163    }
164
165}