create results page and routes
This commit is contained in:
parent
e7f70b9295
commit
60bdd909a7
16
.bruno/BRF/Financial Years.bru
Normal file
16
.bruno/BRF/Financial Years.bru
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
meta {
|
||||||
|
name: Financial Years
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{base_url}}/api/financial-years
|
||||||
|
body: none
|
||||||
|
auth: inherit
|
||||||
|
}
|
||||||
|
|
||||||
|
settings {
|
||||||
|
encodeUrl: true
|
||||||
|
timeout: 0
|
||||||
|
}
|
||||||
16
.bruno/BRF/Result.bru
Normal file
16
.bruno/BRF/Result.bru
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
meta {
|
||||||
|
name: Result
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{base_url}}/api/results/2018
|
||||||
|
body: none
|
||||||
|
auth: inherit
|
||||||
|
}
|
||||||
|
|
||||||
|
settings {
|
||||||
|
encodeUrl: true
|
||||||
|
timeout: 0
|
||||||
|
}
|
||||||
16
.bruno/BRF/Results.bru
Normal file
16
.bruno/BRF/Results.bru
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
meta {
|
||||||
|
name: Results
|
||||||
|
type: http
|
||||||
|
seq: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{base_url}}/api/results
|
||||||
|
body: none
|
||||||
|
auth: inherit
|
||||||
|
}
|
||||||
|
|
||||||
|
settings {
|
||||||
|
encodeUrl: true
|
||||||
|
timeout: 0
|
||||||
|
}
|
||||||
15
.bruno/BRF/bruno.json
Normal file
15
.bruno/BRF/bruno.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"version": "1",
|
||||||
|
"name": "BRF",
|
||||||
|
"type": "collection",
|
||||||
|
"ignore": [
|
||||||
|
"node_modules",
|
||||||
|
".git"
|
||||||
|
],
|
||||||
|
"size": 0,
|
||||||
|
"filesCount": 0,
|
||||||
|
"presets": {
|
||||||
|
"requestType": "http",
|
||||||
|
"requestUrl": "{{base_url}}/"
|
||||||
|
}
|
||||||
|
}
|
||||||
3
.bruno/BRF/collection.bru
Normal file
3
.bruno/BRF/collection.bru
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
vars:pre-request {
|
||||||
|
base_url: https://brf.local
|
||||||
|
}
|
||||||
@ -1,15 +0,0 @@
|
|||||||
import { h } from 'preact'
|
|
||||||
import Head from './head.ts'
|
|
||||||
|
|
||||||
const OtherPage = () => (
|
|
||||||
<section>
|
|
||||||
<Head>
|
|
||||||
<title> : Other</title>
|
|
||||||
</Head>
|
|
||||||
|
|
||||||
<h1>Other Page</h1>
|
|
||||||
<p>Not the page where it begins</p>
|
|
||||||
</section>
|
|
||||||
)
|
|
||||||
|
|
||||||
export default OtherPage
|
|
||||||
31
client/public/components/result.tsx
Normal file
31
client/public/components/result.tsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { h, type FunctionalComponent } from 'preact'
|
||||||
|
import { useEffect, useState } from 'preact/hooks'
|
||||||
|
import rek from 'rek'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
year: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const Result: FunctionalComponent<Props> = ({ year }) => {
|
||||||
|
const [result, setResults] = useState([])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
rek(`/api/results/${year}`).then(setResults)
|
||||||
|
}, [year])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
{result.map((result) => (
|
||||||
|
<tr>
|
||||||
|
<td>{result.accountNumber}</td>
|
||||||
|
<td>{result.description}</td>
|
||||||
|
<td>{result.amount}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Result
|
||||||
5
client/public/components/results_page.module.scss
Normal file
5
client/public/components/results_page.module.scss
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.years {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
justify-content: start;
|
||||||
|
}
|
||||||
41
client/public/components/results_page.tsx
Normal file
41
client/public/components/results_page.tsx
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { h } from 'preact'
|
||||||
|
import { useEffect, useState } from 'preact/hooks'
|
||||||
|
import rek from 'rek'
|
||||||
|
import Head from './head.ts'
|
||||||
|
import Result from './result.tsx'
|
||||||
|
import s from './results_page.module.scss'
|
||||||
|
|
||||||
|
const ResultsPage = () => {
|
||||||
|
const [financialYears, setFinancialYears] = useState([])
|
||||||
|
const [currentYear, setCurrentYear] = useState<number>(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
rek('/api/financial-years').then((financialYears) => {
|
||||||
|
setFinancialYears(financialYears)
|
||||||
|
setCurrentYear(financialYears[financialYears.length - 1].year)
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section>
|
||||||
|
<Head>
|
||||||
|
<title> : Results</title>
|
||||||
|
</Head>
|
||||||
|
|
||||||
|
<h1>Results</h1>
|
||||||
|
<div className={s.years}>
|
||||||
|
{financialYears.map((financialYear) => (
|
||||||
|
<button onClick={() => setCurrentYear(financialYear.year)}>{financialYear.year}</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
{currentYear ? (
|
||||||
|
<div>
|
||||||
|
<h2>{currentYear}</h2>
|
||||||
|
<Result year={currentYear} />
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ResultsPage
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import Start from './components/start_page.tsx'
|
import Start from './components/start_page.tsx'
|
||||||
import Other from './components/other_page.tsx'
|
import Results from './components/results_page.tsx'
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
@ -9,9 +9,9 @@ export default [
|
|||||||
component: Start,
|
component: Start,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/other',
|
path: '/results',
|
||||||
name: 'other',
|
name: 'results',
|
||||||
title: 'Other',
|
title: 'Results',
|
||||||
component: Other,
|
component: Results,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
-- PostgreSQL database dump
|
-- PostgreSQL database dump
|
||||||
--
|
--
|
||||||
|
|
||||||
\restrict EQkcX1mt4Oqej8UZL2Z1qyvnzIAf3O4TYefngsqIN91Lr6JLNTawzD4OIRSJr2s
|
\restrict H2xBPQq6I6IQHZkAgiuKoY9lao4r4KAPtiyNvDE9oc0DN75cJ1gNbkoGFqutWDp
|
||||||
|
|
||||||
-- Dumped from database version 18.1
|
-- Dumped from database version 18.1
|
||||||
-- Dumped by pg_dump version 18.1
|
-- Dumped by pg_dump version 18.1
|
||||||
@ -162,6 +162,7 @@ ALTER SEQUENCE public.entry_id_seq OWNED BY public.entry.id;
|
|||||||
|
|
||||||
CREATE TABLE public.financial_year (
|
CREATE TABLE public.financial_year (
|
||||||
id integer NOT NULL,
|
id integer NOT NULL,
|
||||||
|
year integer NOT NULL,
|
||||||
start_date date NOT NULL,
|
start_date date NOT NULL,
|
||||||
end_date date NOT NULL
|
end_date date NOT NULL
|
||||||
);
|
);
|
||||||
@ -402,6 +403,14 @@ ALTER TABLE ONLY public.financial_year
|
|||||||
ADD CONSTRAINT financial_year_start_date_end_date_key UNIQUE (start_date, end_date);
|
ADD CONSTRAINT financial_year_start_date_end_date_key UNIQUE (start_date, end_date);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: financial_year financial_year_year_key; Type: CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.financial_year
|
||||||
|
ADD CONSTRAINT financial_year_year_key UNIQUE (year);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: journal journal_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
-- Name: journal journal_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
@ -486,5 +495,5 @@ ALTER TABLE ONLY public.transactions_to_objects
|
|||||||
-- PostgreSQL database dump complete
|
-- PostgreSQL database dump complete
|
||||||
--
|
--
|
||||||
|
|
||||||
\unrestrict EQkcX1mt4Oqej8UZL2Z1qyvnzIAf3O4TYefngsqIN91Lr6JLNTawzD4OIRSJr2s
|
\unrestrict H2xBPQq6I6IQHZkAgiuKoY9lao4r4KAPtiyNvDE9oc0DN75cJ1gNbkoGFqutWDp
|
||||||
|
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
"@bmp/highlight-stack": "^0.1.2",
|
"@bmp/highlight-stack": "^0.1.2",
|
||||||
"@fastify/middie": "^9.0.3",
|
"@fastify/middie": "^9.0.3",
|
||||||
"@fastify/static": "^8.3.0",
|
"@fastify/static": "^8.3.0",
|
||||||
|
"@fastify/type-provider-typebox": "^6.1.0",
|
||||||
"chalk": "^5.6.2",
|
"chalk": "^5.6.2",
|
||||||
"fastify": "^5.6.2",
|
"fastify": "^5.6.2",
|
||||||
"fastify-plugin": "^5.1.0",
|
"fastify-plugin": "^5.1.0",
|
||||||
@ -37,7 +38,8 @@
|
|||||||
"pg-protocol": "^1.10.3",
|
"pg-protocol": "^1.10.3",
|
||||||
"pino-abstract-transport": "^3.0.0",
|
"pino-abstract-transport": "^3.0.0",
|
||||||
"preact": "^10.27.2",
|
"preact": "^10.27.2",
|
||||||
"preact-router": "^4.1.2"
|
"preact-router": "^4.1.2",
|
||||||
|
"rek": "^0.8.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.26.10",
|
"@babel/core": "^7.26.10",
|
||||||
@ -53,6 +55,7 @@
|
|||||||
"oxlint": "^1.29.0",
|
"oxlint": "^1.29.0",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"sass": "^1.85.1",
|
"sass": "^1.85.1",
|
||||||
|
"typebox": "^1.0.55",
|
||||||
"typescript": "^5.8.2",
|
"typescript": "^5.8.2",
|
||||||
"vite": "^7.2.4"
|
"vite": "^7.2.4"
|
||||||
}
|
}
|
||||||
|
|||||||
28
pnpm-lock.yaml
generated
28
pnpm-lock.yaml
generated
@ -20,6 +20,9 @@ importers:
|
|||||||
'@fastify/static':
|
'@fastify/static':
|
||||||
specifier: ^8.3.0
|
specifier: ^8.3.0
|
||||||
version: 8.3.0
|
version: 8.3.0
|
||||||
|
'@fastify/type-provider-typebox':
|
||||||
|
specifier: ^6.1.0
|
||||||
|
version: 6.1.0(typebox@1.0.55)
|
||||||
chalk:
|
chalk:
|
||||||
specifier: ^5.6.2
|
specifier: ^5.6.2
|
||||||
version: 5.6.2
|
version: 5.6.2
|
||||||
@ -53,6 +56,9 @@ importers:
|
|||||||
preact-router:
|
preact-router:
|
||||||
specifier: ^4.1.2
|
specifier: ^4.1.2
|
||||||
version: 4.1.2(preact@10.27.2)
|
version: 4.1.2(preact@10.27.2)
|
||||||
|
rek:
|
||||||
|
specifier: ^0.8.1
|
||||||
|
version: 0.8.1
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@babel/core':
|
'@babel/core':
|
||||||
specifier: ^7.26.10
|
specifier: ^7.26.10
|
||||||
@ -93,6 +99,9 @@ importers:
|
|||||||
sass:
|
sass:
|
||||||
specifier: ^1.85.1
|
specifier: ^1.85.1
|
||||||
version: 1.94.2
|
version: 1.94.2
|
||||||
|
typebox:
|
||||||
|
specifier: ^1.0.55
|
||||||
|
version: 1.0.55
|
||||||
typescript:
|
typescript:
|
||||||
specifier: ^5.8.2
|
specifier: ^5.8.2
|
||||||
version: 5.9.3
|
version: 5.9.3
|
||||||
@ -591,6 +600,11 @@ packages:
|
|||||||
'@fastify/static@8.3.0':
|
'@fastify/static@8.3.0':
|
||||||
resolution: {integrity: sha512-yKxviR5PH1OKNnisIzZKmgZSus0r2OZb8qCSbqmw34aolT4g3UlzYfeBRym+HJ1J471CR8e2ldNub4PubD1coA==}
|
resolution: {integrity: sha512-yKxviR5PH1OKNnisIzZKmgZSus0r2OZb8qCSbqmw34aolT4g3UlzYfeBRym+HJ1J471CR8e2ldNub4PubD1coA==}
|
||||||
|
|
||||||
|
'@fastify/type-provider-typebox@6.1.0':
|
||||||
|
resolution: {integrity: sha512-k29cOitDRcZhMXVjtRq0+caKxdWoArz7su+dQWGzGWnFG+fSKhevgiZ7nexHWuXOEEQzgJlh6cptIMu69beaTA==}
|
||||||
|
peerDependencies:
|
||||||
|
typebox: ^1.0.13
|
||||||
|
|
||||||
'@isaacs/balanced-match@4.0.1':
|
'@isaacs/balanced-match@4.0.1':
|
||||||
resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==}
|
resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==}
|
||||||
engines: {node: 20 || >=22}
|
engines: {node: 20 || >=22}
|
||||||
@ -1844,6 +1858,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
|
resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
rek@0.8.1:
|
||||||
|
resolution: {integrity: sha512-DXklCeA33/W9oaKjn/Upiwpdt7ZYqGJE2+1/l5v9iXwRzlfTEDtG7wMJLSWXftXgQz7/IlOjmLgOY/5OwbFPOA==}
|
||||||
|
|
||||||
require-from-string@2.0.2:
|
require-from-string@2.0.2:
|
||||||
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
|
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@ -2076,6 +2093,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==}
|
resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==}
|
||||||
engines: {node: '>=20'}
|
engines: {node: '>=20'}
|
||||||
|
|
||||||
|
typebox@1.0.55:
|
||||||
|
resolution: {integrity: sha512-TP02wN0B6tDZngprrGVu/Z9s/QUyVEmR7VIg1yEOtsqyDdXXEoQPSfWdkD2PsA2lGLxu6GgwOTtGZVS9CAoERg==}
|
||||||
|
|
||||||
typescript@5.9.3:
|
typescript@5.9.3:
|
||||||
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
|
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
|
||||||
engines: {node: '>=14.17'}
|
engines: {node: '>=14.17'}
|
||||||
@ -2604,6 +2624,10 @@ snapshots:
|
|||||||
fastq: 1.19.1
|
fastq: 1.19.1
|
||||||
glob: 11.1.0
|
glob: 11.1.0
|
||||||
|
|
||||||
|
'@fastify/type-provider-typebox@6.1.0(typebox@1.0.55)':
|
||||||
|
dependencies:
|
||||||
|
typebox: 1.0.55
|
||||||
|
|
||||||
'@isaacs/balanced-match@4.0.1': {}
|
'@isaacs/balanced-match@4.0.1': {}
|
||||||
|
|
||||||
'@isaacs/brace-expansion@5.0.0':
|
'@isaacs/brace-expansion@5.0.0':
|
||||||
@ -3833,6 +3857,8 @@ snapshots:
|
|||||||
gopd: 1.2.0
|
gopd: 1.2.0
|
||||||
set-function-name: 2.0.2
|
set-function-name: 2.0.2
|
||||||
|
|
||||||
|
rek@0.8.1: {}
|
||||||
|
|
||||||
require-from-string@2.0.2: {}
|
require-from-string@2.0.2: {}
|
||||||
|
|
||||||
resolve-from@5.0.0: {}
|
resolve-from@5.0.0: {}
|
||||||
@ -4080,6 +4106,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
punycode: 2.3.1
|
punycode: 2.3.1
|
||||||
|
|
||||||
|
typebox@1.0.55: {}
|
||||||
|
|
||||||
typescript@5.9.3: {}
|
typescript@5.9.3: {}
|
||||||
|
|
||||||
undici-types@7.16.0: {}
|
undici-types@7.16.0: {}
|
||||||
|
|||||||
@ -158,7 +158,11 @@ export default async function parseStream(stream: ReadableStream, decoder: Decod
|
|||||||
|
|
||||||
if (yearNumber !== 0) continue
|
if (yearNumber !== 0) continue
|
||||||
|
|
||||||
currentYear = (await trx('financial_year').insert({ startDate, endDate }).returning('*'))[0]
|
currentYear = (
|
||||||
|
await trx('financial_year')
|
||||||
|
.insert({ year: startDate.slice(0, 4), startDate, endDate })
|
||||||
|
.returning('*')
|
||||||
|
)[0]
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,59 +1,85 @@
|
|||||||
import { type FastifyPluginCallback } from 'fastify'
|
import { Type, type Static, type FastifyPluginCallbackTypebox } from '@fastify/type-provider-typebox'
|
||||||
import knex from '../lib/knex.ts'
|
import knex from '../lib/knex.ts'
|
||||||
|
|
||||||
const apiRoutes: FastifyPluginCallback = (fastify, _, done) => {
|
export const FinancialYear = Type.Object({
|
||||||
|
year: Type.Number(),
|
||||||
|
startDate: Type.String(),
|
||||||
|
endDate: Type.String(),
|
||||||
|
})
|
||||||
|
|
||||||
|
export type FinancialYearType = Static<typeof FinancialYear>
|
||||||
|
|
||||||
|
const apiRoutes: FastifyPluginCallbackTypebox = (fastify, _, done) => {
|
||||||
fastify.route({
|
fastify.route({
|
||||||
url: '/result',
|
url: '/financial-years',
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
async handler(req, res) {
|
handler() {
|
||||||
|
return knex('financialYear').select('*')
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
fastify.route({
|
||||||
|
url: '/results',
|
||||||
|
method: 'GET',
|
||||||
|
async handler() {
|
||||||
const years = await knex('financialYear').select('*')
|
const years = await knex('financialYear').select('*')
|
||||||
|
|
||||||
|
const accounts = await knex('account').select('*')
|
||||||
|
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
years.map((year) =>
|
years.map((year) =>
|
||||||
knex('account')
|
knex('account AS a')
|
||||||
.select('account.number', 'account.description')
|
.select('a.number', 'a.description')
|
||||||
.sum('transaction.amount as amount')
|
.sum('t.amount as amount')
|
||||||
.innerJoin('transaction', function () {
|
.innerJoin('transaction AS t', function () {
|
||||||
this.on('transaction.accountNumber', '=', 'account.number')
|
this.on('t.accountNumber', '=', 'a.number')
|
||||||
})
|
})
|
||||||
.innerJoin('entry', function () {
|
.innerJoin('entry AS e', function () {
|
||||||
this.on('transaction.entryId', '=', 'entry.id')
|
this.on('t.entryId', '=', 'e.id')
|
||||||
})
|
})
|
||||||
.groupBy('account.number', 'account.description')
|
.groupBy('a.number', 'a.description')
|
||||||
.where('account.number', '>=', 3000)
|
.where('a.number', '>=', 3000)
|
||||||
.where('entry.financialYearId', year.id)
|
.where('e.financialYearId', year.id)
|
||||||
.orderBy('account.number')
|
.orderBy('a.number')
|
||||||
.then((result) => ({
|
.then((result) => ({
|
||||||
startDate: year.startDate,
|
startDate: year.startDate,
|
||||||
endDate: year.endDate,
|
endDate: year.endDate,
|
||||||
result,
|
result,
|
||||||
})),
|
})),
|
||||||
),
|
),
|
||||||
)
|
).then((years) => ({
|
||||||
|
accounts,
|
||||||
|
years,
|
||||||
|
}))
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
fastify.route({
|
fastify.route({
|
||||||
url: '/result/:year',
|
url: '/results/:year',
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
async handler(req, res) {
|
schema: {
|
||||||
const year = await knex('financialYear').first('*').where('startDate', `${req.params.year}0101`)
|
params: Type.Object({
|
||||||
|
year: Type.Number(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
async handler(req) {
|
||||||
|
const year = await knex('financialYear').first('*').where('year', req.params.year)
|
||||||
|
|
||||||
const result = await knex('account')
|
if (!year) return null
|
||||||
.select('account.number', 'account.description')
|
|
||||||
.sum('transaction.amount as amount')
|
|
||||||
.innerJoin('transaction', function () {
|
|
||||||
this.on('transaction.accountNumber', '=', 'account.number')
|
|
||||||
})
|
|
||||||
.innerJoin('entry', function () {
|
|
||||||
this.on('transaction.entryId', '=', 'entry.id')
|
|
||||||
})
|
|
||||||
.groupBy('account.number', 'account.description')
|
|
||||||
.where('account.number', '>=', 3000)
|
|
||||||
.where('entry.financialYearId', year.id)
|
|
||||||
.orderBy('account.number')
|
|
||||||
|
|
||||||
return result
|
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')
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import fastify from 'fastify'
|
import fastify, { type FastifyServerOptions } from 'fastify'
|
||||||
import StatusError from './lib/status_error.ts'
|
import StatusError from './lib/status_error.ts'
|
||||||
import env from './env.ts'
|
import env from './env.ts'
|
||||||
import ErrorHandler from './handlers/error.ts'
|
import ErrorHandler from './handlers/error.ts'
|
||||||
@ -6,7 +6,7 @@ import vitePlugin from './plugins/vite.ts'
|
|||||||
import apiRoutes from './routes/api.ts'
|
import apiRoutes from './routes/api.ts'
|
||||||
import templatePublic from './templates/public.ts'
|
import templatePublic from './templates/public.ts'
|
||||||
|
|
||||||
export default async (options) => {
|
export default async (options: FastifyServerOptions) => {
|
||||||
const server = fastify(options)
|
const server = fastify(options)
|
||||||
|
|
||||||
server.setNotFoundHandler(() => {
|
server.setNotFoundHandler(() => {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user