- Add datumOd and datumDo columns to kurzy table - Remove datumOd, datumDo, pocetUcastnikov from registracie table - Update schema, validators, and services accordingly - Certificate generation now uses course dates - Migration preserves existing data by copying most recent dates Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
235 lines
7.1 KiB
JavaScript
235 lines
7.1 KiB
JavaScript
import { db } from '../../config/database.js';
|
|
import { kurzy, ucastnici, registracie, prilohy } from '../../db/schema.js';
|
|
import { and, desc, eq, sql } from 'drizzle-orm';
|
|
import { NotFoundError } from '../../utils/errors.js';
|
|
|
|
export const getAllRegistracie = async (kurzId = null) => {
|
|
const conditions = kurzId ? [eq(registracie.kurzId, kurzId)] : [];
|
|
|
|
const result = await db
|
|
.select({
|
|
id: registracie.id,
|
|
kurzId: registracie.kurzId,
|
|
ucastnikId: registracie.ucastnikId,
|
|
formaKurzu: registracie.formaKurzu,
|
|
fakturaCislo: registracie.fakturaCislo,
|
|
fakturaVystavena: registracie.fakturaVystavena,
|
|
zaplatene: registracie.zaplatene,
|
|
stav: registracie.stav,
|
|
poznamka: registracie.poznamka,
|
|
createdAt: registracie.createdAt,
|
|
kurzNazov: kurzy.nazov,
|
|
kurzTyp: kurzy.typKurzu,
|
|
kurzDatumOd: kurzy.datumOd,
|
|
kurzDatumDo: kurzy.datumDo,
|
|
ucastnikMeno: ucastnici.meno,
|
|
ucastnikPriezvisko: ucastnici.priezvisko,
|
|
ucastnikEmail: ucastnici.email,
|
|
ucastnikFirma: ucastnici.firma,
|
|
})
|
|
.from(registracie)
|
|
.leftJoin(kurzy, eq(registracie.kurzId, kurzy.id))
|
|
.leftJoin(ucastnici, eq(registracie.ucastnikId, ucastnici.id))
|
|
.where(conditions.length > 0 ? and(...conditions) : undefined)
|
|
.orderBy(desc(kurzy.datumOd), desc(registracie.createdAt));
|
|
|
|
return result;
|
|
};
|
|
|
|
export const getRegistraciaById = async (id) => {
|
|
const [reg] = await db
|
|
.select({
|
|
id: registracie.id,
|
|
kurzId: registracie.kurzId,
|
|
ucastnikId: registracie.ucastnikId,
|
|
formaKurzu: registracie.formaKurzu,
|
|
fakturaCislo: registracie.fakturaCislo,
|
|
fakturaVystavena: registracie.fakturaVystavena,
|
|
zaplatene: registracie.zaplatene,
|
|
stav: registracie.stav,
|
|
poznamka: registracie.poznamka,
|
|
createdAt: registracie.createdAt,
|
|
kurzNazov: kurzy.nazov,
|
|
kurzTyp: kurzy.typKurzu,
|
|
ucastnikMeno: ucastnici.meno,
|
|
ucastnikPriezvisko: ucastnici.priezvisko,
|
|
ucastnikEmail: ucastnici.email,
|
|
})
|
|
.from(registracie)
|
|
.leftJoin(kurzy, eq(registracie.kurzId, kurzy.id))
|
|
.leftJoin(ucastnici, eq(registracie.ucastnikId, ucastnici.id))
|
|
.where(eq(registracie.id, id))
|
|
.limit(1);
|
|
|
|
if (!reg) {
|
|
throw new NotFoundError('Registrácia nenájdená');
|
|
}
|
|
|
|
return reg;
|
|
};
|
|
|
|
export const createRegistracia = async (data) => {
|
|
const [newReg] = await db
|
|
.insert(registracie)
|
|
.values({
|
|
kurzId: data.kurzId,
|
|
ucastnikId: data.ucastnikId,
|
|
formaKurzu: data.formaKurzu || 'prezencne',
|
|
fakturaCislo: data.fakturaCislo || null,
|
|
fakturaVystavena: data.fakturaVystavena || false,
|
|
zaplatene: data.zaplatene || false,
|
|
stav: data.stav || 'registrovany',
|
|
poznamka: data.poznamka || null,
|
|
})
|
|
.returning();
|
|
|
|
return newReg;
|
|
};
|
|
|
|
export const updateRegistracia = async (id, data) => {
|
|
await getRegistraciaById(id);
|
|
|
|
const [updated] = await db
|
|
.update(registracie)
|
|
.set({
|
|
...data,
|
|
updatedAt: new Date(),
|
|
})
|
|
.where(eq(registracie.id, id))
|
|
.returning();
|
|
|
|
return updated;
|
|
};
|
|
|
|
export const deleteRegistracia = async (id) => {
|
|
await getRegistraciaById(id);
|
|
await db.delete(registracie).where(eq(registracie.id, id));
|
|
return { success: true, message: 'Registrácia bola odstránená' };
|
|
};
|
|
|
|
export const getCombinedTableData = async () => {
|
|
const result = await db
|
|
.select({
|
|
id: registracie.id,
|
|
ucastnikId: ucastnici.id,
|
|
titul: ucastnici.titul,
|
|
meno: ucastnici.meno,
|
|
priezvisko: ucastnici.priezvisko,
|
|
email: ucastnici.email,
|
|
telefon: ucastnici.telefon,
|
|
firma: ucastnici.firma,
|
|
firmaIco: ucastnici.firmaIco,
|
|
firmaDic: ucastnici.firmaDic,
|
|
firmaIcDph: ucastnici.firmaIcDph,
|
|
firmaSidlo: ucastnici.firmaSidlo,
|
|
mesto: ucastnici.mesto,
|
|
ulica: ucastnici.ulica,
|
|
psc: ucastnici.psc,
|
|
needsFollowup: ucastnici.needsFollowup,
|
|
kurzId: kurzy.id,
|
|
kurzNazov: kurzy.nazov,
|
|
kurzTyp: kurzy.typKurzu,
|
|
kurzFarba: kurzy.farba,
|
|
datumOd: kurzy.datumOd,
|
|
datumDo: kurzy.datumDo,
|
|
formaKurzu: registracie.formaKurzu,
|
|
fakturaCislo: registracie.fakturaCislo,
|
|
fakturaVystavena: registracie.fakturaVystavena,
|
|
zaplatene: registracie.zaplatene,
|
|
stav: registracie.stav,
|
|
poznamka: registracie.poznamka,
|
|
createdAt: registracie.createdAt,
|
|
dokumentyCount: sql`(SELECT COUNT(*) FROM prilohy WHERE registracia_id = ${registracie.id})::int`,
|
|
hasCertificate: sql`(SELECT COUNT(*) > 0 FROM prilohy WHERE registracia_id = ${registracie.id} AND typ_prilohy = 'certifikat')::boolean`,
|
|
})
|
|
.from(registracie)
|
|
.innerJoin(ucastnici, eq(registracie.ucastnikId, ucastnici.id))
|
|
.innerJoin(kurzy, eq(registracie.kurzId, kurzy.id))
|
|
.orderBy(desc(kurzy.datumOd), desc(registracie.createdAt));
|
|
|
|
return result;
|
|
};
|
|
|
|
export const updateField = async (registrationId, field, value) => {
|
|
const ucastnikFields = ['titul', 'meno', 'priezvisko', 'email', 'telefon', 'firma', 'firmaIco', 'firmaDic', 'firmaIcDph', 'firmaSidlo', 'mesto', 'ulica', 'psc', 'needsFollowup'];
|
|
const registraciaFields = ['formaKurzu', 'fakturaCislo', 'fakturaVystavena', 'zaplatene', 'stav', 'poznamka', 'kurzId'];
|
|
|
|
const [reg] = await db
|
|
.select({ ucastnikId: registracie.ucastnikId })
|
|
.from(registracie)
|
|
.where(eq(registracie.id, registrationId))
|
|
.limit(1);
|
|
|
|
if (!reg) {
|
|
throw new NotFoundError('Registrácia nenájdená');
|
|
}
|
|
|
|
if (ucastnikFields.includes(field)) {
|
|
await db
|
|
.update(ucastnici)
|
|
.set({ [field]: value, updatedAt: new Date() })
|
|
.where(eq(ucastnici.id, reg.ucastnikId));
|
|
} else if (registraciaFields.includes(field)) {
|
|
await db
|
|
.update(registracie)
|
|
.set({ [field]: value, updatedAt: new Date() })
|
|
.where(eq(registracie.id, registrationId));
|
|
} else {
|
|
throw new Error(`Unknown field: ${field}`);
|
|
}
|
|
|
|
return { success: true };
|
|
};
|
|
|
|
export const getPrilohyByRegistracia = async (registraciaId) => {
|
|
const result = await db
|
|
.select()
|
|
.from(prilohy)
|
|
.where(eq(prilohy.registraciaId, registraciaId))
|
|
.orderBy(desc(prilohy.createdAt));
|
|
|
|
return result;
|
|
};
|
|
|
|
export const createPriloha = async (data) => {
|
|
const [newPriloha] = await db
|
|
.insert(prilohy)
|
|
.values({
|
|
registraciaId: data.registraciaId,
|
|
nazovSuboru: data.nazovSuboru,
|
|
typPrilohy: data.typPrilohy || 'ine',
|
|
cestaKSuboru: data.cestaKSuboru,
|
|
mimeType: data.mimeType || null,
|
|
velkostSuboru: data.velkostSuboru || null,
|
|
popis: data.popis || null,
|
|
})
|
|
.returning();
|
|
|
|
return newPriloha;
|
|
};
|
|
|
|
export const deletePriloha = async (id) => {
|
|
const [priloha] = await db
|
|
.select()
|
|
.from(prilohy)
|
|
.where(eq(prilohy.id, id))
|
|
.limit(1);
|
|
|
|
if (!priloha) {
|
|
throw new NotFoundError('Príloha nenájdená');
|
|
}
|
|
|
|
await db.delete(prilohy).where(eq(prilohy.id, id));
|
|
return { success: true, filePath: priloha.cestaKSuboru };
|
|
};
|
|
|
|
export const getPrilohaById = async (id) => {
|
|
const [priloha] = await db
|
|
.select()
|
|
.from(prilohy)
|
|
.where(eq(prilohy.id, id))
|
|
.limit(1);
|
|
|
|
return priloha || null;
|
|
};
|