11import {
22 Company ,
3+ User ,
34} from "@generated/type-graphql" ;
45import {
6+ Arg ,
57 Authorized ,
68 Ctx ,
9+ Field ,
710 Info ,
11+ Int ,
12+ ObjectType ,
813 Query ,
914 Resolver ,
1015} from "type-graphql" ;
@@ -21,25 +26,62 @@ import {
2126 toSelect ,
2227} from "../helpers/resolver" ;
2328import {
29+ listQuestApplicants ,
2430 listQuestCompanies ,
2531} from "../../services/quest-service" ;
2632import {
2733 getCurrentSeasonId ,
2834 scopeCompanyApplicationsToSeason ,
2935} from "../../services/season-service" ;
36+ import {
37+ Role ,
38+ } from "../../helpers/auth" ;
3039import {
3140 transformSelect as transformSelectCompanies ,
3241} from "./company" ;
3342
43+ @ObjectType ( )
44+ export class QuestApplicantEntry {
45+ @Field ( ( ) => User )
46+ user ! : User ;
47+
48+ @Field ( ( ) => Int )
49+ points ! : number ;
50+
51+ @Field ( ( ) => Date )
52+ scannedAt ! : Date ;
53+ }
54+
55+ @ObjectType ( )
56+ export class QuestCompanyStats {
57+ @Field ( ( ) => Company )
58+ company ! : Company ;
59+
60+ @Field ( ( ) => Int )
61+ applicantCount ! : number ;
62+ }
63+
3464@Resolver ( ( ) => Company )
3565export class QuestResolver {
3666 @Authorized ( )
3767 @Query ( ( ) => [ Company ] )
3868 async questCompanies (
3969 @Ctx ( ) ctx : Context ,
4070 @Info ( ) info : GraphQLResolveInfo ,
71+ @Arg ( "seasonUid" , ( ) => String , { nullable : true } )
72+ seasonUid : string | null = null ,
4173 ) : Promise < Company [ ] > {
42- const seasonId = await getCurrentSeasonId ( ctx . prisma ) ;
74+ let seasonId : number | null ;
75+
76+ if ( seasonUid ) {
77+ const season = await ctx . prisma . season . findUnique ( {
78+ where : { uid : seasonUid } ,
79+ select : { id : true } ,
80+ } ) ;
81+ seasonId = season ?. id ?? null ;
82+ } else {
83+ seasonId = await getCurrentSeasonId ( ctx . prisma ) ;
84+ }
4385
4486 if ( null === seasonId ) {
4587 return [ ] ;
@@ -53,4 +95,117 @@ export class QuestResolver {
5395
5496 return listQuestCompanies ( ctx . prisma , seasonId , select ) as unknown as Promise < Company [ ] > ;
5597 }
98+
99+ @Authorized ( Role . Admin )
100+ @Query ( ( ) => [ QuestApplicantEntry ] )
101+ async questApplicants (
102+ @Ctx ( ) ctx : Context ,
103+ @Arg ( "seasonUid" , ( ) => String )
104+ seasonUid : string ,
105+ @Arg ( "companyUid" , ( ) => String )
106+ companyUid : string ,
107+ ) : Promise < QuestApplicantEntry [ ] > {
108+ const season = await ctx . prisma . season . findUnique ( {
109+ where : { uid : seasonUid } ,
110+ select : { id : true } ,
111+ } ) ;
112+
113+ if ( ! season ) {
114+ return [ ] ;
115+ }
116+
117+ const company = await ctx . prisma . company . findUnique ( {
118+ where : { uid : companyUid } ,
119+ select : { id : true } ,
120+ } ) ;
121+
122+ if ( ! company ) {
123+ return [ ] ;
124+ }
125+
126+ const applicants = await listQuestApplicants ( ctx . prisma , company . id , season . id ) ;
127+
128+ if ( 0 === applicants . length ) {
129+ return [ ] ;
130+ }
131+
132+ const applicantUserIds = applicants . map ( ( a ) => a . userId ) ;
133+
134+ const users = await ctx . prisma . user . findMany ( {
135+ where : { id : { in : applicantUserIds } } ,
136+ select : {
137+ id : true ,
138+ uid : true ,
139+ firstName : true ,
140+ lastName : true ,
141+ email : true ,
142+ phone : true ,
143+ } ,
144+ } ) ;
145+
146+ const usersById = new Map ( users . map ( ( u ) => [ u . id , u ] ) ) ;
147+
148+ return applicants
149+ . map ( ( a ) => {
150+ const user = usersById . get ( a . userId ) ;
151+ if ( ! user ) {
152+ return null ;
153+ }
154+ return {
155+ user : user as unknown as User ,
156+ points : a . points ,
157+ scannedAt : a . scannedAt ,
158+ } ;
159+ } )
160+ . filter ( ( entry ) : entry is QuestApplicantEntry => null !== entry )
161+ ;
162+ }
163+
164+ @Authorized ( Role . Admin )
165+ @Query ( ( ) => [ QuestCompanyStats ] )
166+ async questCompaniesWithStats (
167+ @Ctx ( ) ctx : Context ,
168+ @Arg ( "seasonUid" , ( ) => String )
169+ seasonUid : string ,
170+ ) : Promise < QuestCompanyStats [ ] > {
171+ const season = await ctx . prisma . season . findUnique ( {
172+ where : { uid : seasonUid } ,
173+ select : { id : true } ,
174+ } ) ;
175+
176+ if ( ! season ) {
177+ return [ ] ;
178+ }
179+
180+ const companies = await listQuestCompanies ( ctx . prisma , season . id , {
181+ id : true ,
182+ uid : true ,
183+ brandName : true ,
184+ } ) ;
185+
186+ if ( 0 === companies . length ) {
187+ return [ ] ;
188+ }
189+
190+ const companyIds = companies . map ( ( c ) => c . id as number ) ;
191+
192+ const counts = await ctx . prisma . companyScannedUser . groupBy ( {
193+ by : [ "companyId" ] ,
194+ where : {
195+ seasonId : season . id ,
196+ questEntered : true ,
197+ companyId : { in : companyIds } ,
198+ } ,
199+ _count : { userId : true } ,
200+ } ) ;
201+
202+ const countByCompanyId = new Map (
203+ counts . map ( ( row ) => [ row . companyId , row . _count . userId ] ) ,
204+ ) ;
205+
206+ return companies . map ( ( c ) => ( {
207+ company : c as unknown as Company ,
208+ applicantCount : countByCompanyId . get ( c . id as number ) ?? 0 ,
209+ } ) ) ;
210+ }
56211}
0 commit comments