import _ from 'lodash' import { Type, type Static, type FastifyPluginCallbackTypebox } from '@fastify/type-provider-typebox' import knex from '../lib/knex.ts' import StatusError from '../lib/status_error.ts' export const FinancialYear = Type.Object({ year: Type.Number(), startDate: Type.String(), endDate: Type.String(), }) export type FinancialYearType = Static const apiRoutes: FastifyPluginCallbackTypebox = (fastify, _, done) => { fastify.route({ url: '/financial-years', method: 'GET', handler() { return knex('financialYear').select('*') }, }) fastify.route({ url: '/invoices', method: 'GET', schema: { querystring: Type.Object({ year: Type.Optional(Type.Number()), supplier: Type.Optional(Type.Number()), }), }, async handler(req) { let query: { financialYearId?: number; supplierId?: number } = {} if (req.query.year) { const year = await knex('financialYear').first('*').where('year', req.query.year) if (!year) throw new StatusError(404, `Year ${req.query.year} not found.`) query.financialYearId = year.id } if (req.query.supplier) { query.supplierId = req.query.supplier } return knex('invoice AS i') .select('*', { files: knex .select(knex.raw('json_agg(files)')) .from( knex .select('id', 'filename') .from('file AS f') .innerJoin('filesToInvoice AS fi', 'f.id', 'fi.fileId') .where('fi.invoiceId', knex.ref('i.id')) .as('files'), ), }) .where(query) }, }) fastify.route({ url: '/invoices/:id', method: 'GET', schema: { params: Type.Object({ id: Type.Number(), }), }, handler(req) { return knex('invoice').first('*').where('id', req.params.id) }, }) fastify.route({ url: '/invoices/by-supplier/:supplier', method: 'GET', schema: { params: Type.Object({ supplier: Type.Number(), }), }, handler(req) { return knex('invoice AS i') .select('*', { files: knex .select(knex.raw('json_agg(files)')) .from( knex .select('id', 'filename') .from('file AS f') .innerJoin('filesToInvoice AS fi', 'f.id', 'fi.fileId') .where('fi.invoiceId', knex.ref('i.id')) .as('files'), ), }) .where('supplierId', req.params.supplier) }, }) fastify.route({ url: '/invoices/by-year/:year', method: 'GET', schema: { params: Type.Object({ year: Type.Number(), }), }, async handler(req) { const year = await knex('financialYear').first('*').where('year', req.params.year) if (!year) throw new StatusError(404, `Year ${req.params.year} not found.`) return knex('invoice').select('*').where('financialYearId', year.id) }, }) fastify.route({ url: '/objects', method: 'GET', handler() { return knex('object AS o') .select('o.id', 'o.number', 'o.name', 'd.number AS dimensionNumber', 'd.name AS dimensionName') .innerJoin('dimension AS d', function () { this.on('o.dimensionId', '=', 'd.id') }) }, }) fastify.route({ url: '/objects/:id', method: 'GET', schema: { params: Type.Object({ id: Type.Number(), }), }, async handler(req) { // const object = knex('object').first('*').where('id', req.params.id) // if (!object) throw new StatusError(404) console.log(req.params.id) return knex('transaction AS t') .select('e.transactionDate', 't.accountNumber', 't.amount') .innerJoin('transactions_to_objects AS to', function () { this.on('t.id', 'to.transactionId') }) .innerJoin('entry AS e', function () { this.on('e.id', '=', 't.entryId') }) .where('to.objectId', req.params.id) }, }) fastify.route({ url: '/results', method: 'GET', async handler() { const years = await knex('financialYear').select('*') const accounts = await knex('account').select('*') return Promise.all( years.map((year) => knex('account AS a') .select('a.number', 'a.description') .sum('t.amount as amount') .innerJoin('transaction AS t', function () { this.on('t.accountNumber', '=', 'a.number') }) .innerJoin('entry AS e', function () { this.on('t.entryId', '=', 'e.id') }) .groupBy('a.number', 'a.description') .where('a.number', '>=', 3000) .where('e.financialYearId', year.id) .orderBy('a.number') .then((result) => ({ startDate: year.startDate, endDate: year.endDate, result, })), ), ).then((years) => ({ accounts, years, })) }, }) fastify.route({ url: '/results/:year', method: 'GET', schema: { params: Type.Object({ year: Type.Number(), }), }, async handler(req) { const year = await knex('financialYear').first('*').where('year', req.params.year) if (!year) return null return knex('transaction AS t') .select('t.accountNumber', 'a.description') .sum('t.amount as amount') .innerJoin('account AS a', function () { this.on('t.accountNumber', '=', 'a.number') }) .innerJoin('entry AS e', function () { this.on('t.entryId', '=', 'e.id') }) .groupBy('t.accountNumber', 'a.description') .where('t.accountNumber', '>=', 3000) .where('e.financialYearId', year.id) .orderBy('t.accountNumber') }, }) fastify.route({ url: '/suppliers', method: 'GET', async handler(req) { return knex('supplier').select('*').orderBy('name') }, }) fastify.route({ url: '/suppliers/:id', method: 'GET', schema: { params: Type.Object({ id: Type.Number(), }), }, async handler(req) { return knex('supplier').first('*').where('id', req.params.id) }, }) done() } export default apiRoutes