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.period.server.graphql; 018 019import com.echothree.control.user.period.common.PeriodUtil; 020import com.echothree.control.user.period.server.command.GetFiscalPeriodsCommand; 021import com.echothree.model.control.graphql.server.graphql.BaseEntityInstanceObject; 022import com.echothree.model.control.graphql.server.graphql.TimeObject; 023import com.echothree.model.control.graphql.server.graphql.count.Connections; 024import com.echothree.model.control.graphql.server.graphql.count.CountedObjects; 025import com.echothree.model.control.graphql.server.graphql.count.CountingDataConnectionFetcher; 026import com.echothree.model.control.graphql.server.graphql.count.CountingPaginatedData; 027import com.echothree.model.control.graphql.server.util.BaseGraphQl; 028import com.echothree.model.control.graphql.server.util.count.ObjectLimiter; 029import com.echothree.model.control.period.server.control.PeriodControl; 030import com.echothree.model.control.user.server.control.UserControl; 031import com.echothree.model.data.period.common.PeriodConstants; 032import com.echothree.model.data.period.server.entity.Period; 033import com.echothree.model.data.period.server.entity.PeriodDetail; 034import com.echothree.util.server.persistence.Session; 035import graphql.annotations.annotationTypes.GraphQLDescription; 036import graphql.annotations.annotationTypes.GraphQLField; 037import graphql.annotations.annotationTypes.GraphQLName; 038import graphql.annotations.annotationTypes.GraphQLNonNull; 039import graphql.annotations.connection.GraphQLConnection; 040import graphql.schema.DataFetchingEnvironment; 041import java.util.ArrayList; 042import javax.enterprise.inject.spi.CDI; 043import javax.naming.NamingException; 044import static com.echothree.model.control.period.common.PeriodConstants.PeriodKind_FISCAL; 045 046public abstract class PeriodObject 047 extends BaseEntityInstanceObject { 048 049 protected final Period period; // Always Present 050 051 protected PeriodObject(Period period) { 052 super(period.getPrimaryKey()); 053 054 this.period = period; 055 } 056 057 private PeriodDetail periodDetail; // Optional, use getPeriodDetail() 058 059 protected PeriodDetail getPeriodDetail() { 060 if(periodDetail == null) { 061 periodDetail = period.getLastDetail(); 062 } 063 064 return periodDetail; 065 } 066 067 public static PeriodInterface toPeriodInterface(Period period) { 068 return period == null ? 069 null : 070 switch(period.getLastDetail().getPeriodKind().getLastDetail().getPeriodKindName()) { 071 case PeriodKind_FISCAL -> new FiscalPeriodObject(period); 072 default -> null; 073 }; 074 } 075 076 @GraphQLField 077 @GraphQLNonNull 078 public String getPeriodName() { 079 return getPeriodDetail().getPeriodName(); 080 } 081 082 @GraphQLField 083 public PeriodKindObject getPeriodKind(final DataFetchingEnvironment env) { 084 return PeriodSecurityUtils.getHasPeriodKindAccess(env) ? new PeriodKindObject(getPeriodDetail().getPeriodKind()) : null; 085 } 086 087 @GraphQLField 088 public PeriodTypeObject getPeriodType(final DataFetchingEnvironment env) { 089 if(PeriodSecurityUtils.getHasPeriodTypeAccess(env)) { 090 var periodType = getPeriodDetail().getPeriodType(); 091 092 return periodType == null ? null : new PeriodTypeObject(periodType); 093 } else { 094 return null; 095 } 096 } 097 098 @GraphQLField 099 public PeriodInterface getParentPeriod(final DataFetchingEnvironment env) { 100 return PeriodSecurityUtils.getHasFiscalPeriodAccess(env) ? toPeriodInterface(getPeriodDetail().getParentPeriod()) : null; 101 } 102 103 @GraphQLField 104 @GraphQLNonNull 105 public TimeObject getStartTime() { 106 return new TimeObject(getPeriodDetail().getStartTime()); 107 } 108 109 @GraphQLField 110 @GraphQLNonNull 111 public TimeObject getEndTime() { 112 return new TimeObject(getPeriodDetail().getEndTime()); 113 } 114 115 @GraphQLField 116 @GraphQLNonNull 117 public String getDescription(final DataFetchingEnvironment env) { 118 var periodControl = Session.getModelController(PeriodControl.class); 119 var userControl = Session.getModelController(UserControl.class); 120 121 return periodControl.getBestPeriodDescription(period, userControl.getPreferredLanguageFromUserVisit(BaseGraphQl.getUserVisit(env))); 122 } 123 124 @GraphQLField 125 @GraphQLDescription("child periods") 126 @GraphQLNonNull 127 @GraphQLConnection(connectionFetcher = CountingDataConnectionFetcher.class) 128 public CountingPaginatedData<PeriodInterface> getPeriods(final DataFetchingEnvironment env) { 129 return getPeriods(env, getPeriodDetail().getPeriodKind().getLastDetail().getPeriodKindName(), 130 getPeriodName(), null); 131 } 132 133 public static CountingPaginatedData<PeriodInterface> getPeriods(final DataFetchingEnvironment env, 134 final String periodKindName, final String parentPeriodName, final String periodTypeName) { 135 if(PeriodKind_FISCAL.equals(periodKindName) && PeriodSecurityUtils.getHasFiscalPeriodsAccess(env)) { 136 try { 137 var form = PeriodUtil.getHome().getGetFiscalPeriodsForm(); 138 var command = CDI.current().select(GetFiscalPeriodsCommand.class).get(); 139 140 form.setParentPeriodName(parentPeriodName); 141 form.setPeriodTypeName(periodTypeName); 142 143 var total = command.getTotalEntitiesForGraphQl(BaseGraphQl.getUserVisitPK(env), form); 144 if(total == null) { 145 return Connections.emptyConnection(); 146 } 147 148 try(var objectLimiter = new ObjectLimiter(env, PeriodConstants.COMPONENT_VENDOR_NAME, 149 PeriodConstants.ENTITY_TYPE_NAME, total)) { 150 var entities = command.getEntitiesForGraphQl(BaseGraphQl.getUserVisitPK(env), form); 151 var objects = new ArrayList<PeriodInterface>(entities.size()); 152 153 for(var entity : entities) { 154 objects.add(toPeriodInterface(entity)); 155 } 156 157 return new CountedObjects<>(objectLimiter, objects); 158 } 159 } catch(NamingException ex) { 160 throw new RuntimeException(ex); 161 } 162 } else { 163 return Connections.emptyConnection(); 164 } 165 } 166 167}