Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add WeekStatus GraphQL Endpoint for User Week Confirmation Status #1180

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 61 additions & 9 deletions server/graphql/resolvers/timesheet/TimesheetResolver.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
/* eslint-disable unicorn/empty-brace-spaces */
/* eslint-disable unicorn/prevent-abbreviations */
import 'reflect-metadata'
import { Arg, Authorized, Ctx, Mutation, Query, Resolver } from 'type-graphql'
import { Service } from 'typedi'
import { TimesheetService } from '../../../services'
import { DateObject } from '../../../../shared/utils/date'
import { ConfirmedPeriodsService, TimesheetService, UserService } from '../../../services'
import { IAuthOptions } from '../../authChecker'
import { RequestContext } from '../../requestContext'
import { BaseResult } from '../types'
Expand All @@ -10,8 +13,10 @@ import {
TimesheetPeriodInput,
TimesheetPeriodObject,
TimesheetQuery,
VacationSummary
VacationSummary,
WeekStatusObject
} from './types'
import { PermissionScope } from '../../../../shared/config/security'

/**
* Resolver for `TimesheetPeriodObject`.
Expand All @@ -29,10 +34,14 @@ export class TimesheetResolver {
/**
* Constructor for TimesheetResolver
*
* @param _timesheet - Timesheet service
* @param _timesheetSvc - Timesheet service
* @param _userSvc - User service
*/
// eslint-disable-next-line unicorn/empty-brace-spaces
constructor(private readonly _timesheet: TimesheetService) {}
constructor(
private readonly _timesheetSvc: TimesheetService,
private readonly _userSvc: UserService,
private readonly _cpSvc: ConfirmedPeriodsService
) { }

/**
* Get timesheet
Expand All @@ -50,7 +59,7 @@ export class TimesheetResolver {
@Arg('options') options: TimesheetOptions
) {
try {
return await this._timesheet.getTimesheet({
return await this._timesheetSvc.getTimesheet({
...query,
...options,
configuration: context.userConfiguration?.timesheet || {}
Expand All @@ -72,7 +81,7 @@ export class TimesheetResolver {
})
async vacation(@Ctx() context: RequestContext) {
try {
return await this._timesheet.getVacation(
return await this._timesheetSvc.getVacation(
context.subscription.settings.vacation
)
} catch (error) {
Expand All @@ -96,7 +105,7 @@ export class TimesheetResolver {
@Arg('options') options: TimesheetOptions
): Promise<BaseResult> {
try {
await this._timesheet.submitPeriod({ ...options, period })
await this._timesheetSvc.submitPeriod({ ...options, period })
return {
success: false,
error: null
Expand Down Expand Up @@ -125,7 +134,7 @@ export class TimesheetResolver {
@Arg('options') options: TimesheetOptions
): Promise<BaseResult> {
try {
await this._timesheet.unsubmitPeriod({ ...options, period })
await this._timesheetSvc.unsubmitPeriod({ ...options, period })
return {
success: true,
error: null
Expand All @@ -137,4 +146,47 @@ export class TimesheetResolver {
}
}
}

/**
* Get status for the provided week and user (and year if provided).
*
* @remarks For now, this is using the `ACCESS_REPORTS` scope, but this
* could be changed in the future.
*
* @param email - User email
* @param week - Week number
* @param year - Year (optional, defaults to current year)
*
* @returns An object containing the user's ID, submit status and total hours for the week
*/
@Authorized<IAuthOptions>({ scope: PermissionScope.ACCESS_REPORTS })
@Query(() => WeekStatusObject, {
description: 'Get status of the current week'
})
public async weekStatus(
@Arg('email') email: string,
@Arg('week') week: number,
@Arg('year', { nullable: true }) year?: number
): Promise<WeekStatusObject> {
const user = await this._userSvc.getById(email)
if (!user) throw new Error(`No user found with email ${email}`)
const confirmedPeriods = await this._cpSvc.find({
userId: user._id,
week,
year: year ?? new Date().getFullYear()
})
const {isWeekSplit} = new DateObject().fromObject({
week,
year: year ?? new Date().getFullYear()
})
const submitStatus = isWeekSplit && confirmedPeriods.length === 2 ? 2 : (confirmedPeriods.length === 1 && !isWeekSplit ? 1 : 0)
const hours = confirmedPeriods.reduce((sum, { hours }) => sum + hours, 0)

return {
userId: user._id,
submitStatus,
hours,
isWeekSplit
}
}
}
40 changes: 40 additions & 0 deletions server/graphql/resolvers/timesheet/types/WeekStatusObject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import 'reflect-metadata'
import { Field, Float, Int, ObjectType } from 'type-graphql'

/**
* Return object for the `weekStatus` query
*
* @category GraphQL ObjectType
*/
@ObjectType({
description: 'Return object for the weekStatus query'
})
export class WeekStatusObject {
/**
* User ID
*/
@Field()
userId: string

/**
* Submit status
*
* `0` - Not submitted
* `1` - Partially submitted (the week is split between months and one of the months is submitted)
* `2` - Fully submitted
*/
@Field(() => Int)
submitStatus: number

/**
* Total hours for the week
*/
@Field(() => Float)
hours: number

/**
* Is the week split between months?
*/
@Field()
isWeekSplit: boolean
}
2 changes: 2 additions & 0 deletions server/graphql/resolvers/timesheet/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ export * from './TimesheetPeriodInput'
export * from './TimesheetPeriodObject'
export * from './TimesheetQuery'
export * from './VacationSummaryObject'
export * from './WeekStatusObject'

7 changes: 7 additions & 0 deletions shared/utils/DateObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,13 @@ export class DateObject {
return DateUtils.isCurrentMonth(this)
}

/**
* Is week split between two months
*/
public get isWeekSplit() {
return DateUtils.isWeekSplit(this)
}

/**
* Get the formatted date according to the string of tokens passed in.
*
Expand Down
9 changes: 9 additions & 0 deletions shared/utils/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,15 @@ export class DateUtils {
return (year || date.$.year()) === $dayjs().year()
}

/**
* Is the week split between two months
*
* @param date - Date
*/
public isWeekSplit(date: DateObject): boolean {
return date.startOfWeek.isSameMonth(date.endOfWeek) === false
}

/**
* Is current year
*
Expand Down
Loading