Files
Krow-workspace/backend/dataconnect/connector/reports/queries.gql
2026-01-19 19:18:11 -05:00

456 lines
9.0 KiB
GraphQL

# ==========================================================
# Reports Connector - For MVP
# ==========================================================
# This file exposes SOURCE-DATA queries for all report screens.
# All aggregation (group by day/week, percentages, averages)
# is intentionally done on the client (Flutter).
#
# Entities used:
# - Shift
# - Application
# - Staff
# - Invoice
# - TimeSheet
#
# NOTE:
# Data Connect does NOT support custom root resolvers.
# These queries return raw rows from @table entities.
# ==========================================================
# ==========================================================
# 1) COVERAGE REPORT (Next 7 days)
# ==========================================================
# Coverage definition:
# - Needed: sum(Shift.workersNeeded) grouped by date
# - Confirmed: count(Application) where status IN (...)
#
# Client groups by Shift.date and calculates:
# coveragePercentage = confirmed / needed * 100
# ==========================================================
query listShiftsForCoverage(
$businessId: UUID!
$startDate: Timestamp!
$endDate: Timestamp!
) @auth(level: USER) {
shifts(
where: {
order: { businessId: { eq: $businessId } }
date: { ge: $startDate, le: $endDate }
}
orderBy: { date: ASC }
) {
id
date
workersNeeded
filled
status
}
}
#I comment here because I have an error en sdk
query listApplicationsForCoverage(
$shiftIds: [UUID!]!
#$statuses: [ApplicationStatus!]!
) @auth(level: USER) {
applications(
where: {
shiftId: { in: $shiftIds }
#status: { in: $statuses }
}
) {
id
shiftId
staffId
status
}
}
# ==========================================================
# 2) DAILY OPS REPORT (Single day)
# ==========================================================
# Metrics derived on client:
# - scheduledShifts = shifts.length
# - workersConfirmed = confirmedApps / totalNeeded
# - inProgressShifts = status == IN_PROGRESS
# - completedShifts = status == COMPLETED
# ==========================================================
query listShiftsForDailyOpsByBusiness(
$businessId: UUID!
$date: Timestamp!
) @auth(level: USER) {
shifts(
where: {
order: { businessId: { eq: $businessId } }
date: { eq: $date }
}
orderBy: { startTime: ASC }
) {
id
title
location
startTime
endTime
workersNeeded
filled
status
}
}
query listShiftsForDailyOpsByVendor(
$vendorId: UUID!
$date: Timestamp!
) @auth(level: USER) {
shifts(
where: {
order: { vendorId: { eq: $vendorId } }
date: { eq: $date }
}
orderBy: { startTime: ASC }
) {
id
title
location
startTime
endTime
workersNeeded
filled
status
}
}
query listApplicationsForDailyOps(
$shiftIds: [UUID!]!
) @auth(level: USER) {
applications(where: { shiftId: { in: $shiftIds } }) {
id
shiftId
staffId
status
checkInTime
checkOutTime
}
}
# ==========================================================
# 3) FORECAST REPORT (Next N weeks)
# ==========================================================
# Projected spend formula (client):
# projectedCost = workersNeeded * hours * hourlyRate
# ==========================================================
query listShiftsForForecastByBusiness(
$businessId: UUID!
$startDate: Timestamp!
$endDate: Timestamp!
) @auth(level: USER) {
shifts(
where: {
order: { businessId: { eq: $businessId } }
date: { ge: $startDate, le: $endDate }
}
orderBy: { date: ASC }
) {
id
date
workersNeeded
hours
cost
status
}
}
query listShiftsForForecastByVendor(
$vendorId: UUID!
$startDate: Timestamp!
$endDate: Timestamp!
) @auth(level: USER) {
shifts(
where: {
order: { vendorId: { eq: $vendorId } }
date: { ge: $startDate, le: $endDate }
}
orderBy: { date: ASC }
) {
id
date
workersNeeded
hours
cost
status
}
}
# ==========================================================
# 4) NO-SHOW REPORT (Historical range)
# ==========================================================
# Now fully supported because ApplicationStatus includes NO_SHOW.
#
# Metrics:
# - totalNoShows = count(status == NO_SHOW)
# - noShowRate = noShows / totalApplications
# - breakdown by staff
# ==========================================================
query listShiftsForNoShowRangeByBusiness(
$businessId: UUID!
$startDate: Timestamp!
$endDate: Timestamp!
) @auth(level: USER) {
shifts(
where: {
order: { businessId: { eq: $businessId } }
date: { ge: $startDate, le: $endDate }
}
) {
id
date
}
}
query listShiftsForNoShowRangeByVendor(
$vendorId: UUID!
$startDate: Timestamp!
$endDate: Timestamp!
) @auth(level: USER) {
shifts(
where: {
order: { vendorId: { eq: $vendorId } }
date: { ge: $startDate, le: $endDate }
}
) {
id
date
}
}
query listApplicationsForNoShowRange(
$shiftIds: [UUID!]!
) @auth(level: USER) {
applications(where: { shiftId: { in: $shiftIds } }) {
id
shiftId
staffId
status
}
}
query listStaffForNoShowReport(
$staffIds: [UUID!]!
) @auth(level: USER) {
staffs(where: { id: { in: $staffIds } }) {
id
fullName
noShowCount
reliabilityScore
}
}
# ==========================================================
# 5) SPEND REPORT (Financial)
# ==========================================================
# Uses Invoice as source of truth for money.
# Filter is now based on:
# - businessId (business dashboard)
# - vendorId (vendor dashboard)
# since Invoice no longer has ownerId.
# ==========================================================
query listInvoicesForSpendByBusiness(
$businessId: UUID!
$startDate: Timestamp!
$endDate: Timestamp!
) @auth(level: USER) {
invoices(
where: {
businessId: { eq: $businessId }
issueDate: { ge: $startDate, le: $endDate }
}
orderBy: { issueDate: ASC }
) {
id
issueDate
dueDate
amount
status
invoiceNumber
vendor { id companyName }
business { id businessName }
order { id eventName }
}
}
query listInvoicesForSpendByVendor(
$vendorId: UUID!
$startDate: Timestamp!
$endDate: Timestamp!
) @auth(level: USER) {
invoices(
where: {
vendorId: { eq: $vendorId }
issueDate: { ge: $startDate, le: $endDate }
}
orderBy: { issueDate: ASC }
) {
id
issueDate
dueDate
amount
status
invoiceNumber
vendor { id companyName }
business { id businessName }
order { id eventName }
}
}
# Optional: Spend by Order (if you need it)
query listInvoicesForSpendByOrder(
$orderId: UUID!
$startDate: Timestamp!
$endDate: Timestamp!
) @auth(level: USER) {
invoices(
where: {
orderId: { eq: $orderId }
issueDate: { ge: $startDate, le: $endDate }
}
orderBy: { issueDate: ASC }
) {
id
issueDate
dueDate
amount
status
invoiceNumber
vendor { id companyName }
business { id businessName }
order { id eventName }
}
}
query listTimesheetsForSpend(
$startTime: Timestamp!
$endTime: Timestamp!
) @auth(level: USER) {
shiftRoles(
where: {
shift: {
date: { ge: $startTime, le: $endTime }
}
}
) {
id
hours
totalValue
shift{
title
location
status
date
order{
business{
businessName
}
}
}
role{
costPerHour
}
}
}
# ==========================================================
# 6) PERFORMANCE REPORT (Historical KPIs)
# ==========================================================
# Metrics derivable:
# - fillRate
# - completionRate
# - onTimeRate
# - avgFillTimeHours (NOW POSSIBLE 🎉)
#
# avgFillTimeHours formula:
# (filledAt - createdAt) averaged across FILLED shifts
# ==========================================================
query listShiftsForPerformanceByBusiness(
$businessId: UUID!
$startDate: Timestamp!
$endDate: Timestamp!
) @auth(level: USER) {
shifts(
where: {
order: { businessId: { eq: $businessId } }
date: { ge: $startDate, le: $endDate }
filledAt: { isNull: false }
}
) {
id
workersNeeded
filled
status
createdAt
filledAt
}
}
query listShiftsForPerformanceByVendor(
$vendorId: UUID!
$startDate: Timestamp!
$endDate: Timestamp!
) @auth(level: USER) {
shifts(
where: {
order: { vendorId: { eq: $vendorId } }
date: { ge: $startDate, le: $endDate }
filledAt: { isNull: false }
}
) {
id
workersNeeded
filled
status
createdAt
filledAt
}
}
query listApplicationsForPerformance(
$shiftIds: [UUID!]!
) @auth(level: USER) {
applications(where: { shiftId: { in: $shiftIds } }) {
id
shiftId
staffId
status
checkInTime
checkOutTime
}
}
query listStaffForPerformance(
$staffIds: [UUID!]!
) @auth(level: USER) {
staffs(where: { id: { in: $staffIds } }) {
id
averageRating
onTimeRate
noShowCount
reliabilityScore
}
}