feat: Add farba field and company details to AI Kurzy module

- Add farba (color) field to kurzy schema and Zod validation
- Add company detail fields (firma_ico, firma_dic, firma_ic_dph, firma_sidlo) to ucastnici
- Remove console logs from ai-kurzy service
- Add SQL migration scripts for schema updates and data

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
richardtekula
2026-01-21 14:27:03 +01:00
parent 4089bb4be2
commit 826fd467bc
5 changed files with 197 additions and 2 deletions

View File

@@ -0,0 +1,19 @@
-- ============================================================
-- AI KURZY - Company Details & Course Colors Migration
-- Run this FIRST to add new columns
-- ============================================================
-- Add color field to kurzy table
ALTER TABLE "kurzy" ADD COLUMN IF NOT EXISTS "farba" varchar(20);
-- Add company details fields to ucastnici table
ALTER TABLE "ucastnici" ADD COLUMN IF NOT EXISTS "firma_ico" varchar(20);
ALTER TABLE "ucastnici" ADD COLUMN IF NOT EXISTS "firma_dic" varchar(20);
ALTER TABLE "ucastnici" ADD COLUMN IF NOT EXISTS "firma_ic_dph" varchar(25);
ALTER TABLE "ucastnici" ADD COLUMN IF NOT EXISTS "firma_sidlo" text;
-- ============================================================
-- DONE - Now run 03_ai_kurzy_full_data.sql for complete data
-- ============================================================
SELECT 'AI Kurzy schema migration completed!' as status;
SELECT 'Now run 03_ai_kurzy_full_data.sql for complete data' as next_step;

View File

@@ -0,0 +1,135 @@
-- ============================================================
-- AI KURZY - Complete Data Reset and Import
-- Run this to start fresh with proper data
-- ============================================================
-- First, clear existing data
DELETE FROM prilohy;
DELETE FROM registracie;
DELETE FROM ucastnici;
DELETE FROM kurzy;
-- Reset sequences
ALTER SEQUENCE kurzy_id_seq RESTART WITH 1;
ALTER SEQUENCE ucastnici_id_seq RESTART WITH 1;
ALTER SEQUENCE registracie_id_seq RESTART WITH 1;
-- ============================================================
-- INSERT COURSES (without dates in names, with colors)
-- ============================================================
INSERT INTO kurzy (nazov, typ_kurzu, cena, aktivny, farba) VALUES
('AI 1 (1 deň)', 'AI', 150.00, true, 'blue'),
('AI 2 (1 deň)', 'AI', 150.00, true, 'emerald'),
('AI 1+2 (2 dni)', 'AI', 290.00, true, 'violet'),
('AI v SEO', 'SEO', 150.00, true, 'amber');
-- ============================================================
-- INSERT PARTICIPANTS with company details
-- ============================================================
-- 1. Martin Sovák - energium sro
INSERT INTO ucastnici (titul, meno, priezvisko, email, telefon, firma, firma_ico, firma_dic, firma_ic_dph, firma_sidlo, mesto, ulica, psc)
VALUES (NULL, 'Martin', 'Sovák', 'info@energium.sk', '0918986172', 'energium sro', '47613033', '2024004433', 'SK2024004433', 'Topolcianska 5, 85105 Bratislava', 'Bratislava', 'Topolcianska 5', '85105');
-- 2. Michal Farkaš - SLOVWELD
INSERT INTO ucastnici (titul, meno, priezvisko, email, telefon, firma, firma_ico, firma_dic, firma_ic_dph, firma_sidlo, mesto, ulica, psc)
VALUES (NULL, 'Michal', 'Farkaš', 'michal.farkas83@gmail.com', '0911209122', 'SLOVWELD', NULL, NULL, NULL, NULL, 'Dunajska Lužná', 'Mandlova 30', '90042');
-- 3. Alena Šranková - bez firmy
INSERT INTO ucastnici (titul, meno, priezvisko, email, telefon, firma, firma_ico, firma_dic, firma_ic_dph, firma_sidlo, mesto, ulica, psc)
VALUES (NULL, 'Alena', 'Šranková', 'alena.srankova@gmail.com', '0917352580', NULL, NULL, NULL, NULL, NULL, 'Bratislava', 'Šándorova 1', '82103');
-- 4. Katarina Tomaníková - Classica Shipping Limited
INSERT INTO ucastnici (titul, meno, priezvisko, email, telefon, firma, firma_ico, firma_dic, firma_ic_dph, firma_sidlo, mesto, ulica, psc)
VALUES (NULL, 'Katarina', 'Tomaníková', 'k.tomanikova@riseday.net', '0948070611', 'Classica Shipping Limited', NULL, NULL, NULL, NULL, 'Bratislava', 'Keltska 104', '85110');
-- 5. Róbert Brišák - Spojená škola
INSERT INTO ucastnici (titul, meno, priezvisko, email, telefon, firma, firma_ico, firma_dic, firma_ic_dph, firma_sidlo, mesto, ulica, psc)
VALUES (NULL, 'Róbert', 'Brišák', 'robert.brisak@ss-nizna.sk', '0910583883', 'Spojená škola Nižná', NULL, NULL, NULL, 'Hattalova 471, 02743 Nižná', 'Nižná', 'Hattalova 471', '02743');
-- 6. Marián Bača - bez firmy
INSERT INTO ucastnici (titul, meno, priezvisko, email, telefon, firma, firma_ico, firma_dic, firma_ic_dph, firma_sidlo, mesto, ulica, psc)
VALUES (NULL, 'Marián', 'Bača', 'baca.marian@gmail.com', '0907994126', NULL, NULL, NULL, NULL, NULL, 'Petrovany', '8', '08253');
-- 7. Nikola Horáčková - bez firmy
INSERT INTO ucastnici (titul, meno, priezvisko, email, telefon, firma, firma_ico, firma_dic, firma_ic_dph, firma_sidlo, mesto, ulica, psc)
VALUES ('Mgr. MBA', 'Nikola', 'Horáčková', 'nikolahorackova11@gmail.com', '0918482184', NULL, NULL, NULL, NULL, NULL, 'Zákopčie', 'Zákopčie stred 12', '02311');
-- 8. Tomáš Kupec - Jamajka s.r.o.
INSERT INTO ucastnici (titul, meno, priezvisko, email, telefon, firma, firma_ico, firma_dic, firma_ic_dph, firma_sidlo, mesto, ulica, psc)
VALUES (NULL, 'Tomáš', 'Kupec', 'kupec.tom@gmail.com', '0911030190', 'JAMAJKA, s.r.o.', '36411833', '2020128539', 'SK2020128539', 'Hotel Koliba Gréta 270
032 23 Liptovská Sielnica', 'Liptovská Sielnica', NULL, '03223');
-- 9. Anton Považský - bez firmy (testovací)
INSERT INTO ucastnici (titul, meno, priezvisko, email, telefon, firma, firma_ico, firma_dic, firma_ic_dph, firma_sidlo, mesto, ulica, psc)
VALUES (NULL, 'Anton', 'Považský', 'anton.povazsky@example.com', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
-- ============================================================
-- INSERT REGISTRATIONS
-- ============================================================
-- Martin Sovák -> AI 1+2 (2 dni) - prezenčne, faktúra vystavená, nezaplatené
INSERT INTO registracie (kurz_id, ucastnik_id, datum_od, datum_do, forma_kurzu, pocet_ucastnikov, faktura_vystavena, zaplatene, stav, poznamka)
SELECT k.id, u.id, '2026-02-02', '2026-02-03', 'prezencne', 1, true, false, 'registrovany', 'FA 2026020'
FROM kurzy k, ucastnici u WHERE k.nazov = 'AI 1+2 (2 dni)' AND u.email = 'info@energium.sk';
-- Michal Farkaš -> AI 1 (1 deň) - online, zaplatené
INSERT INTO registracie (kurz_id, ucastnik_id, datum_od, datum_do, forma_kurzu, pocet_ucastnikov, faktura_vystavena, zaplatene, stav, poznamka)
SELECT k.id, u.id, '2026-02-02', '2026-02-02', 'online', 1, true, true, 'registrovany', 'Fa 2025 338, Súhlasil so zmeneným termínom'
FROM kurzy k, ucastnici u WHERE k.nazov = 'AI 1 (1 deň)' AND u.email = 'michal.farkas83@gmail.com';
-- Alena Šranková -> AI 1+2 (2 dni) - online, zaplatené
INSERT INTO registracie (kurz_id, ucastnik_id, datum_od, datum_do, forma_kurzu, pocet_ucastnikov, faktura_vystavena, zaplatene, stav, poznamka)
SELECT k.id, u.id, '2026-02-02', '2026-02-03', 'online', 1, true, true, 'registrovany', NULL
FROM kurzy k, ucastnici u WHERE k.nazov = 'AI 1+2 (2 dni)' AND u.email = 'alena.srankova@gmail.com';
-- Katarina Tomaníková -> AI 1+2 (2 dni) - prezenčne, zaplatené
INSERT INTO registracie (kurz_id, ucastnik_id, datum_od, datum_do, forma_kurzu, pocet_ucastnikov, faktura_vystavena, zaplatene, stav, poznamka)
SELECT k.id, u.id, '2026-02-02', '2026-02-03', 'prezencne', 1, true, true, 'registrovany', 'Presunuta z októbra, chcela až január'
FROM kurzy k, ucastnici u WHERE k.nazov = 'AI 1+2 (2 dni)' AND u.email = 'k.tomanikova@riseday.net';
-- Róbert Brišák -> AI 1+2 (2 dni) - prezenčne, nezaplatené
INSERT INTO registracie (kurz_id, ucastnik_id, datum_od, datum_do, forma_kurzu, pocet_ucastnikov, faktura_vystavena, zaplatene, stav, poznamka)
SELECT k.id, u.id, '2026-02-02', '2026-02-03', 'prezencne', 1, true, false, 'registrovany', 'FA 2026019'
FROM kurzy k, ucastnici u WHERE k.nazov = 'AI 1+2 (2 dni)' AND u.email = 'robert.brisak@ss-nizna.sk';
-- Marián Bača -> AI 2 (1 deň) - prezenčne, nezaplatené
INSERT INTO registracie (kurz_id, ucastnik_id, datum_od, datum_do, forma_kurzu, pocet_ucastnikov, faktura_vystavena, zaplatene, stav, poznamka)
SELECT k.id, u.id, '2026-02-03', '2026-02-03', 'prezencne', 1, true, false, 'registrovany', 'Fa Gablasova'
FROM kurzy k, ucastnici u WHERE k.nazov = 'AI 2 (1 deň)' AND u.email = 'baca.marian@gmail.com';
-- Nikola Horáčková -> AI 1+2 (2 dni) - potenciálny (vzdelávací poukaz)
INSERT INTO registracie (kurz_id, ucastnik_id, datum_od, datum_do, forma_kurzu, pocet_ucastnikov, faktura_vystavena, zaplatene, stav, poznamka)
SELECT k.id, u.id, '2026-02-02', '2026-02-03', 'prezencne', 1, false, false, 'potencialny', 'Vzdelávací poukaz'
FROM kurzy k, ucastnici u WHERE k.nazov = 'AI 1+2 (2 dni)' AND u.email = 'nikolahorackova11@gmail.com';
-- Tomáš Kupec -> AI v SEO - prezenčne, nezaplatené
INSERT INTO registracie (kurz_id, ucastnik_id, datum_od, datum_do, forma_kurzu, pocet_ucastnikov, faktura_vystavena, zaplatene, stav, poznamka)
SELECT k.id, u.id, '2026-02-13', '2026-02-13', 'prezencne', 1, true, false, 'registrovany', 'FA 2026021'
FROM kurzy k, ucastnici u WHERE k.nazov = 'AI v SEO' AND u.email = 'kupec.tom@gmail.com';
-- Anton Považský -> AI v SEO - prezenčne, nezaplatené
INSERT INTO registracie (kurz_id, ucastnik_id, datum_od, datum_do, forma_kurzu, pocet_ucastnikov, faktura_vystavena, zaplatene, stav, poznamka)
SELECT k.id, u.id, '2026-02-13', '2026-02-13', 'prezencne', 1, true, false, 'registrovany', NULL
FROM kurzy k, ucastnici u WHERE k.nazov = 'AI v SEO' AND u.email = 'anton.povazsky@example.com';
-- ============================================================
-- VERIFICATION
-- ============================================================
SELECT 'Kurzy:' as info, COUNT(*) as pocet FROM kurzy;
SELECT 'Účastníci:' as info, COUNT(*) as pocet FROM ucastnici;
SELECT 'Registrácie:' as info, COUNT(*) as pocet FROM registracie;
-- Show sample data with company details
SELECT
u.meno || ' ' || u.priezvisko as ucastnik,
u.firma,
u.firma_ico as ico,
u.firma_dic as dic,
k.nazov as kurz,
k.farba,
r.zaplatene
FROM registracie r
JOIN ucastnici u ON r.ucastnik_id = u.id
JOIN kurzy k ON r.kurz_id = k.id
ORDER BY r.datum_od;

View File

@@ -435,6 +435,7 @@ export const kurzy = pgTable('kurzy', {
cena: numeric('cena', { precision: 10, scale: 2 }).notNull(),
maxKapacita: integer('max_kapacita'),
aktivny: boolean('aktivny').default(true).notNull(),
farba: varchar('farba', { length: 20 }), // Color for visual distinction (e.g., 'primary', 'info', 'warning')
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
});
@@ -448,6 +449,10 @@ export const ucastnici = pgTable('ucastnici', {
email: varchar('email', { length: 255 }).notNull().unique(),
telefon: varchar('telefon', { length: 50 }),
firma: varchar('firma', { length: 255 }),
firmaIco: varchar('firma_ico', { length: 20 }), // IČO spoločnosti
firmaDic: varchar('firma_dic', { length: 20 }), // DIČ spoločnosti
firmaIcDph: varchar('firma_ic_dph', { length: 25 }), // IČ DPH spoločnosti
firmaSidlo: text('firma_sidlo'), // Sídlo firmy (full address)
mesto: varchar('mesto', { length: 100 }),
ulica: varchar('ulica', { length: 255 }),
psc: varchar('psc', { length: 10 }),

View File

@@ -51,6 +51,7 @@ const createKurzSchema = z.object({
cena: z.string().or(z.number()),
maxKapacita: z.number().int().positive().optional().nullable(),
aktivny: z.boolean().optional(),
farba: z.string().max(20).optional().nullable(),
});
const updateKurzSchema = createKurzSchema.partial();
@@ -62,6 +63,10 @@ const createUcastnikSchema = z.object({
email: z.string().email().max(255),
telefon: z.string().max(50).optional().nullable(),
firma: z.string().max(255).optional().nullable(),
firmaIco: z.string().max(20).optional().nullable(),
firmaDic: z.string().max(20).optional().nullable(),
firmaIcDph: z.string().max(25).optional().nullable(),
firmaSidlo: z.string().optional().nullable(),
mesto: z.string().max(100).optional().nullable(),
ulica: z.string().max(255).optional().nullable(),
psc: z.string().max(10).optional().nullable(),

View File

@@ -15,6 +15,7 @@ export const getAllKurzy = async () => {
cena: kurzy.cena,
maxKapacita: kurzy.maxKapacita,
aktivny: kurzy.aktivny,
farba: kurzy.farba,
createdAt: kurzy.createdAt,
registraciiCount: sql`(SELECT COUNT(*) FROM registracie WHERE kurz_id = ${kurzy.id})::int`,
})
@@ -48,6 +49,7 @@ export const createKurz = async (data) => {
cena: data.cena,
maxKapacita: data.maxKapacita || null,
aktivny: data.aktivny !== undefined ? data.aktivny : true,
farba: data.farba || null,
})
.returning();
@@ -57,7 +59,23 @@ export const createKurz = async (data) => {
export const updateKurz = async (id, data) => {
await getKurzById(id);
const updateData = { ...data, updatedAt: new Date() };
const updateData = {
nazov: data.nazov,
typKurzu: data.typKurzu,
popis: data.popis !== undefined ? data.popis : undefined,
cena: data.cena,
maxKapacita: data.maxKapacita !== undefined ? data.maxKapacita : undefined,
aktivny: data.aktivny !== undefined ? data.aktivny : undefined,
farba: data.farba !== undefined ? data.farba : undefined,
updatedAt: new Date(),
};
// Remove undefined values
Object.keys(updateData).forEach(key => {
if (updateData[key] === undefined) {
delete updateData[key];
}
});
const [updated] = await db
.update(kurzy)
@@ -86,6 +104,10 @@ export const getAllUcastnici = async () => {
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,
@@ -122,6 +144,10 @@ export const createUcastnik = async (data) => {
email: data.email,
telefon: data.telefon || null,
firma: data.firma || null,
firmaIco: data.firmaIco || null,
firmaDic: data.firmaDic || null,
firmaIcDph: data.firmaIcDph || null,
firmaSidlo: data.firmaSidlo || null,
mesto: data.mesto || null,
ulica: data.ulica || null,
psc: data.psc || null,
@@ -280,6 +306,10 @@ export const getCombinedTableData = async () => {
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,
@@ -287,6 +317,7 @@ export const getCombinedTableData = async () => {
kurzId: kurzy.id,
kurzNazov: kurzy.nazov,
kurzTyp: kurzy.typKurzu,
kurzFarba: kurzy.farba,
// Registration fields (dates are now here)
datumOd: registracie.datumOd,
datumDo: registracie.datumDo,
@@ -312,7 +343,7 @@ export const getCombinedTableData = async () => {
// Update a single field (for inline editing)
export const updateField = async (registrationId, field, value) => {
// Determine which table to update based on the field
const ucastnikFields = ['titul', 'meno', 'priezvisko', 'email', 'telefon', 'firma', 'mesto', 'ulica', 'psc'];
const ucastnikFields = ['titul', 'meno', 'priezvisko', 'email', 'telefon', 'firma', 'firmaIco', 'firmaDic', 'firmaIcDph', 'firmaSidlo', 'mesto', 'ulica', 'psc'];
const registraciaFields = ['datumOd', 'datumDo', 'formaKurzu', 'pocetUcastnikov', 'fakturaCislo', 'fakturaVystavena', 'zaplatene', 'stav', 'poznamka', 'kurzId'];
const dateFields = ['datumOd', 'datumDo'];