@accounter/server
Version:
Accounter GraphQL server
454 lines (423 loc) • 16.5 kB
text/typescript
import z from 'zod';
const invoiceSchema = z
.object({
id: z.string().describe('Unique identifier of this resource as a UUID.'), // example: "rhCTiRd9Mad41RwjsFWw-",
amount: z
.string() // NOTE: by docs, optional
.describe('Billed amount of the invoice.'),
contract_id: z
.string()
.nullable() // NOTE: by docs, not nullable
.describe('Unique identifier of the related contract.'), // example: "string"
created_at: z.iso
.datetime() // NOTE: by docs, nullable
.describe('Date and time when the invoice was created (ISO-8601 format).'), // example: "2022-05-24T09:38:46.235Z",
currency: z.string().length(3).describe('Three-letter currency code for the invoice.'), // example: "GBP",
deel_fee: z
.literal('0.00') // NOTE: by docs, nullable & optional
.describe('Fee charged by Deel.'),
due_date: z
.union([z.literal(''), z.iso.datetime()]) // NOTE: by docs, nullable
.describe('Date and time when the invoice is due (ISO-8601 format).'), // example: "2022-05-24T09:38:46.235Z",
// early_payout_fee: z
// .string()
// .nullable()
// .optional()
// .describe('Fee charged for early payout of the invoice.'),
// exchange_fee: z
// .string()
// .nullable()
// .optional()
// .describe('Fee related to currency exchange for the invoice.'),
// fee: z.string().nullable().optional().describe('Fee added to the invoice amount.'),
// has_breakdown: z
// .boolean()
// .nullable()
// .optional()
// .describe('Indicates whether the invoice includes a breakdown of items.'),
// is_early_paid: z
// .boolean()
// .nullable()
// .optional()
// .describe('Indicates whether the invoice was paid early.'),
// is_offcycle: z
// .boolean()
// .nullable()
// .optional()
// .describe('Indicates whether the invoice is off-cycle.'),
is_overdue: z
.boolean() // NOTE: by docs, nullable
.describe('Indicates whether the invoice is overdue.'), // example: true,
// is_paid_to_contractor: z
// .boolean()
// .nullable()
// .optional()
// .describe('Indicates whether the invoice was paid to the contractor.'),
// is_sealed: z
// .boolean()
// .nullable()
// .optional()
// .describe('Indicates whether the invoice is sealed.'),
issued_at: z.iso
.datetime() // NOTE: by docs, nullable
.describe('Date and time when the invoice was issued (ISO-8601 format).'), // example: "2022-05-24T09:38:46.235Z",
label: z.string().describe('Label or reference number of the invoice.'), // example: "INV-2023-4",
// money_received_at: z
// .iso
// .datetime()
// .nullable()
// .optional()
// .describe('Date and time when the payment was received (ISO-8601 format).'),
paid_at: z
.union([z.literal(''), z.iso.datetime()]) // NOTE: by docs, nullable
.describe('Date and time when the invoice was paid (ISO-8601 format).'), // example: "2022-05-24T09:38:46.235Z",
// payment_currency: z.string().optional().describe('Currency in which the invoice was paid.'),
// payment_method: z.string().nullable().optional().describe('Method used to pay the invoice.'),
// payment_processed_at: z
// .iso
// .datetime()
// .nullable()
// .optional()
// .describe('Date and time when the payment was processed (ISO-8601 format).'),
// processed_at: z
// .iso
// .datetime()
// .nullable()
// .optional()
// .describe('Date and time when the invoice was processed (ISO-8601 format).'),
status: z
.enum([
'pending',
'paid',
'processing',
'canceled',
'skipped',
'failed',
'refunded',
'processed',
])
.describe('Current status of the invoice.'), // example: "paid",
total: z.string().describe('Total invoice amount, including fees and VAT.'), // example: "1000",
// type: z.string().nullable().optional().describe('Type of the invoice.'),
vat_id: z.literal('').describe('VAT identification number related to the invoice.'), // example: "string",
vat_percentage: z.literal('').describe('Percentage of VAT charged on the invoice.'), // example: "21",
vat_total: z.literal('0.00').describe('Total amount of VAT charged on the invoice.'), // example: "210",
recipient_legal_entity_id: z.literal('1dee10b1-105b-4dc7-bcdb-5ed5c52ba868'), // TODO: replace with DB variable instead of hardcoding
})
.strict();
export type Invoice = z.infer<typeof invoiceSchema>;
export const retrieveInvoicesSchema = z
.object({
data: z.array(invoiceSchema),
page: z
.object({
total_rows: z.number().int().positive(),
items_per_page: z.number().int().min(1).max(99),
offset: z.number().int().min(0),
})
.strict(),
})
.strict();
export type RetrieveInvoices = z.infer<typeof retrieveInvoicesSchema>;
export const downloadInvoicePdfSchema = z
.object({
data: z
.object({
id: z
.string()
.optional() // NOTE: by docs, not optional
.describe('Unique identifier of the invoice.'),
url: z
.string()
.nullable()
.describe(
'URL to the requested invoice for download. This URL may expire after a certain duration.',
),
expires_at: z.iso
.datetime()
.optional() // NOTE: by docs, not optional
.describe(
'The expiration date and time of the download URL, after which the URL will no longer be accessible.',
),
})
.strict(),
})
.strict();
export type DownloadInvoicePdf = z.infer<typeof downloadInvoicePdfSchema>;
export const workerSchema = z
.object({
id: z.string().describe('Unique identifier for the worker.'),
contract_id: z.string().nullable().optional().describe("The worker's Deel contract ID."),
name: z.string().optional().describe('Full name of the worker.'),
picUrl: z.string().nullable().describe("URL to the worker's Deel avatar."),
public_id: z.string().optional(), // NOTE: by docs, not existing
})
.strict();
export type DeelWorker = z.infer<typeof workerSchema>;
export const paymentReceiptsSchema = z
.object({
id: z
.string() // NOTE: by docs, optional
.describe('Unique identifier of the payment.'),
created_at: z.iso
.datetime() // NOTE: by docs, optional
.describe('Date and time when the payment was created, in ISO-8601 format.'),
label: z
.string() // NOTE: by docs, optional
.describe('A descriptive label for the payment.'),
paid_at: z.iso
.datetime()
.nullable()
.describe('Date and time when the payment was completed, in ISO-8601 format.'),
payment_currency: z
.string()
.length(3) // NOTE: by docs, optional
.describe('Three-letter currency code for the payment, following ISO 4217.'),
payment_method: z.object({}).optional().describe('payment_method object'), // TODO: define
total: z.string(), // NOTE: by docs, not existing
status: z
.enum(['paid']) // NOTE: by docs, optional
.describe("Status of the payment. Either 'paid' or 'processing'."),
workers: z.array(workerSchema).optional(),
invoices: z.array(
z
.object({
id: z.string().describe('Unique identifier for the invoice.'),
})
.strict(),
),
timezone: z
.string()
.nullable()
.describe('Timezone offset in ISO 8601 format (e.g., +02:00, -05:00).'),
deel_reference: z.string().nullable().describe('Deel reference identifier for the payment.'),
})
.strict();
export type PaymentReceipts = z.infer<typeof paymentReceiptsSchema>;
export const retrievePaymentReceiptsSchema = z
.object({
data: z
.object({
rows: z.array(paymentReceiptsSchema),
total: z.number().int().min(0),
next_cursor: z
.string()
.nullable()
.describe(
'A cursor for pagination. Use the value returned in the ‘next_cursor’ field to get the next page of results. If there are no more results, this will be null.',
),
has_more: z
.boolean()
.nullable()
.describe('Inform if there are more entries to be fetched using next cursor.'),
total_count: z
.number()
.nullable()
.describe('The total number of payments matching the query'),
})
.strict(),
})
.strict();
export type RetrievePaymentReceipts = z.infer<typeof retrievePaymentReceiptsSchema>;
const paymentBreakdownRecordSchema = z
.object({
adjustment: z.literal('0.00').describe('Adjustment amount for the payment.'),
approve_date: z
.union([z.literal(''), z.iso.datetime()])
.describe('The date when the payment was approved.'),
approvers: z.string().describe('Approvers of the payment breakdown.'),
bonus: z.literal('0.00').describe('Bonus payment amount.'),
commissions: z.literal('0.00').describe('Commissions included in the payment.'),
contract_country: z
.union([z.literal(''), z.string().length(2)])
.describe('Country where the contract is associated.'),
contract_start_date: z
.union([z.iso.datetime(), z.literal('')])
.describe('Start date of the contract.'),
contract_type: z.string(),
contractor_email: z.union([z.literal(''), z.email()]).describe("Worker's email address."),
contractor_employee_name: z.string().describe("Worker's name."),
contractor_unique_identifier: z
.union([z.literal(''), z.uuid()])
.describe("Worker's unique identifier as a UUID."),
currency: z.string().describe('Currency code used for this payment.'),
date: z.iso.datetime().describe('The date associated with the payment breakdown.'),
deductions: z.literal('0.00').describe('Deductions from the payment.'),
expenses: z.string().describe('Expenses related to the payment.'),
frequency: z
.enum(['', 'hourly', 'daily', 'monthly', 'custom'])
.describe('Frequency of payment (e.g., monthly, weekly).'),
general_ledger_account: z.literal('').describe('General ledger account for the payment.'),
group_id: z.string(),
invoice_id: z.string().describe('Invoice number associated with the payment.'),
// invoice_number: z
// .string()
// .optional()
// .describe('Invoice number associated with the payment.'),
others: z.string().describe('Other payment amounts.'),
overtime: z.literal('0.00').describe('Overtime payment amount.'),
payment_currency: z.string().describe('Currency in which the payment was made.'),
payment_date: z.iso.datetime().describe('The date the payment was made.'),
pro_rata: z.string().describe('Pro-rated payment amount.'),
processing_fee: z.string().describe('Processing fee applied to the payment.'),
// receipt_number: z.string().optional().describe('Receipt number for the payment.'),
// team: z
// .string()
// .optional()
// .describe('The name of the team or company associated with the payment.'),
work: z.string().describe('Amount associated with work payment.'),
total: z.string().describe('Total payment due for this breakdown item.'),
total_payment_currency: z.string().describe('Total payment in the payment currency.'),
})
.strict();
export type PaymentBreakdownRecord = z.infer<typeof paymentBreakdownRecordSchema>;
export const retrievePaymentBreakdownSchema = z
.object({
data: z.array(paymentBreakdownRecordSchema),
})
.strict();
export type RetrievePaymentBreakdown = z.infer<typeof retrievePaymentBreakdownSchema>;
/* contracts schemas */
const TeamSchema = z
.object({
id: z.uuid(),
name: z.string(),
})
.strict();
const LegalEntitySchema = z
.object({
email: z.literal(''),
id: z.uuid(),
name: z.string(),
registration_number: z.string(),
subtype: z.literal('private-liability-company'),
type: z.literal('company'),
vat_number: z.string(),
})
.strict();
const ClientSchema = z
.object({
email: z.email(),
full_name: z.string(),
id: z.uuid(),
legal_entity: LegalEntitySchema,
team: TeamSchema,
})
.strict();
const WorkerSchema = z
.object({
alternate_email: z.array(z.never()),
country: z.string().length(2),
date_of_birth: z.iso.date(),
email: z.email(),
expected_email: z.email(),
first_name: z.string(),
full_name: z.string(),
id: z.uuid(),
last_name: z.string(),
nationality: z.string().length(2).nullable(),
})
.strict();
const InvitationsSchema = z
.object({
client_email: z.email(),
worker_email: z.email().or(z.literal('')),
})
.strict();
const SignaturesSchema = z
.object({
client_signature: z.string(),
client_signed_at: z.iso.datetime(),
signed_at: z.iso.datetime(),
worker_signature: z.string(),
worker_signed_at: z.iso.datetime(),
})
.strict();
const CompensationDetailsSchema = z
.object({
amount: z.string().nullable(),
currency_code: z.string().length(3),
cycle_end: z.number().int().nullable(),
cycle_end_type: z.enum(['DAY_OF_MONTH', 'DAY_OF_WEEK', 'DAY_OF_LAST_WEEK']).nullable(),
first_payment: z.preprocess(val => (val === '' ? null : val), z.coerce.number().nullable()),
first_payment_date: z.iso.datetime({ offset: true }).or(z.literal('')),
frequency: z.enum(['', 'weekly', 'biweekly', 'semimonthly', 'monthly', 'calendar-month']),
gross_annual_salary: z.number().or(z.literal('')),
gross_signing_bonus: z.literal(''),
gross_variable_bonus: z.literal(''),
scale: z.enum(['', 'monthly', 'hourly', 'daily', 'custom']),
variable_compensations: z.array(z.never()),
})
.strict();
const EmploymentProbationPeriodMetadataSchema = z
.object({
display_value: z.literal(90),
time_unit: z.literal('DAY'),
})
.strict();
const EmploymentDetailsSchema = z
.object({
days_per_week: z.literal(0),
hours_per_day: z.literal(0),
paid_vacation_days: z.literal(0),
probation_period: z.number().int(),
probation_period_metadata: EmploymentProbationPeriodMetadataSchema.nullable(),
type: z.enum(['ongoing_time_based', 'eor', 'pay_as_you_go_time_based']),
})
.strict();
const EmploymentTypeSchema = z.enum(['FULL_TIME']);
const WorkDaySchema = z
.object({
day: z.enum(['MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 'SATURDAY', 'SUNDAY']),
end: z.iso.time(),
start: z.iso.time(),
work_hours: z.number().int(),
})
.strict();
const WorkScheduleSchema = z
.object({
country: z.string().length(2),
days: z.array(WorkDaySchema),
employment_type: EmploymentTypeSchema,
name: z.string(),
work_hours_per_week: z.number().int(),
work_schedule_type: z.string(),
worker_types: z.array(z.enum(['HOURLY_EOR_EMPLOYEE', 'SALARIED_EOR_EMPLOYEE'])),
})
.strict();
export const ContractSchema = z
.object({
data: z
.object({
client: ClientSchema,
compensation_details: CompensationDetailsSchema,
contract_template: z.null(),
created_at: z.iso.datetime(),
custom_fields: z.array(z.never()),
employment_details: EmploymentDetailsSchema,
employment_type: EmploymentTypeSchema.nullable(),
external_id: z.null(),
id: z.string(),
invitations: InvitationsSchema,
is_archived: z.boolean(),
job_title: z.string().optional(),
notice_period: z.number().int(),
scope_of_work: z.string().optional(),
seniority: z.null(),
signatures: SignaturesSchema,
special_clause: z.literal(''),
start_date: z.iso.datetime({ offset: true }),
status: z.enum(['in_progress', 'completed', 'cancelled', 'user_cancelled']),
termination_date: z.iso.datetime().or(z.literal('')),
title: z.string(),
type: z.enum(['ongoing_time_based', 'eor', 'pay_as_you_go_time_based']),
updated_at: z.iso.datetime(),
who_reports: z.enum(['both']).optional(),
work_schedule: WorkScheduleSchema.nullable(),
work_statement_id: z.uuid().optional(),
worker: WorkerSchema,
})
.strict(),
})
.strict();
export type Contract = z.infer<typeof ContractSchema>;