new features
This commit is contained in:
@@ -35,13 +35,13 @@ async function getVendorById(id: number) {
|
||||
}
|
||||
}
|
||||
|
||||
async function createVendor(data: { name: string; kontakt_person?: string; email?: string; telefon?: string; adresse?: string; notizen?: string }, userId: string) {
|
||||
async function createVendor(data: { name: string; kontakt_name?: string; email?: string; telefon?: string; adresse?: string; website?: string; notizen?: string }, userId: string) {
|
||||
try {
|
||||
const result = await pool.query(
|
||||
`INSERT INTO lieferanten (name, kontakt_person, email, telefon, adresse, notizen, erstellt_von)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
`INSERT INTO lieferanten (name, kontakt_name, email, telefon, adresse, website, notizen, erstellt_von)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
RETURNING *`,
|
||||
[data.name, data.kontakt_person || null, data.email || null, data.telefon || null, data.adresse || null, data.notizen || null, userId]
|
||||
[data.name, data.kontakt_name || null, data.email || null, data.telefon || null, data.adresse || null, data.website || null, data.notizen || null, userId]
|
||||
);
|
||||
return result.rows[0];
|
||||
} catch (error) {
|
||||
@@ -50,20 +50,21 @@ async function createVendor(data: { name: string; kontakt_person?: string; email
|
||||
}
|
||||
}
|
||||
|
||||
async function updateVendor(id: number, data: { name?: string; kontakt_person?: string; email?: string; telefon?: string; adresse?: string; notizen?: string }, userId: string) {
|
||||
async function updateVendor(id: number, data: { name?: string; kontakt_name?: string; email?: string; telefon?: string; adresse?: string; website?: string; notizen?: string }, userId: string) {
|
||||
try {
|
||||
const result = await pool.query(
|
||||
`UPDATE lieferanten
|
||||
SET name = COALESCE($1, name),
|
||||
kontakt_person = COALESCE($2, kontakt_person),
|
||||
kontakt_name = COALESCE($2, kontakt_name),
|
||||
email = COALESCE($3, email),
|
||||
telefon = COALESCE($4, telefon),
|
||||
adresse = COALESCE($5, adresse),
|
||||
notizen = COALESCE($6, notizen),
|
||||
website = COALESCE($6, website),
|
||||
notizen = COALESCE($7, notizen),
|
||||
aktualisiert_am = NOW()
|
||||
WHERE id = $7
|
||||
WHERE id = $8
|
||||
RETURNING *`,
|
||||
[data.name, data.kontakt_person, data.email, data.telefon, data.adresse, data.notizen, id]
|
||||
[data.name, data.kontakt_name, data.email, data.telefon, data.adresse, data.website, data.notizen, id]
|
||||
);
|
||||
if (result.rows.length === 0) return null;
|
||||
|
||||
@@ -157,7 +158,7 @@ async function getOrderById(id: number) {
|
||||
pool.query(`SELECT * FROM bestellpositionen WHERE bestellung_id = $1 ORDER BY id`, [id]),
|
||||
pool.query(`SELECT * FROM bestellung_dateien WHERE bestellung_id = $1 ORDER BY hochgeladen_am DESC`, [id]),
|
||||
pool.query(`SELECT * FROM bestellung_erinnerungen WHERE bestellung_id = $1 ORDER BY faellig_am`, [id]),
|
||||
pool.query(`SELECT h.*, u.display_name AS benutzer_name FROM bestellung_historie h LEFT JOIN users u ON u.id = h.benutzer_id WHERE h.bestellung_id = $1 ORDER BY h.erstellt_am DESC`, [id]),
|
||||
pool.query(`SELECT h.*, u.display_name AS benutzer_name FROM bestellung_historie h LEFT JOIN users u ON u.id = h.erstellt_von WHERE h.bestellung_id = $1 ORDER BY h.erstellt_am DESC`, [id]),
|
||||
]);
|
||||
|
||||
return {
|
||||
@@ -173,16 +174,16 @@ async function getOrderById(id: number) {
|
||||
}
|
||||
}
|
||||
|
||||
async function createOrder(data: { titel: string; lieferant_id?: number; beschreibung?: string; prioritaet?: string }, userId: string) {
|
||||
async function createOrder(data: { bezeichnung: string; lieferant_id?: number; notizen?: string; budget?: number }, userId: string) {
|
||||
try {
|
||||
const result = await pool.query(
|
||||
`INSERT INTO bestellungen (titel, lieferant_id, beschreibung, prioritaet, erstellt_von)
|
||||
`INSERT INTO bestellungen (bezeichnung, lieferant_id, notizen, budget, erstellt_von)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING *`,
|
||||
[data.titel, data.lieferant_id || null, data.beschreibung || null, data.prioritaet || 'normal', userId]
|
||||
[data.bezeichnung, data.lieferant_id || null, data.notizen || null, data.budget || null, userId]
|
||||
);
|
||||
const order = result.rows[0];
|
||||
await logAction(order.id, 'Bestellung erstellt', `Bestellung "${data.titel}" erstellt`, userId);
|
||||
await logAction(order.id, 'Bestellung erstellt', `Bestellung "${data.bezeichnung}" erstellt`, userId);
|
||||
return order;
|
||||
} catch (error) {
|
||||
logger.error('BestellungService.createOrder failed', { error });
|
||||
@@ -190,7 +191,7 @@ async function createOrder(data: { titel: string; lieferant_id?: number; beschre
|
||||
}
|
||||
}
|
||||
|
||||
async function updateOrder(id: number, data: { titel?: string; lieferant_id?: number; beschreibung?: string; prioritaet?: string; status?: string }, userId: string) {
|
||||
async function updateOrder(id: number, data: { bezeichnung?: string; lieferant_id?: number; notizen?: string; budget?: number; status?: string }, userId: string) {
|
||||
try {
|
||||
// Check current order for status change detection
|
||||
const current = await pool.query(`SELECT * FROM bestellungen WHERE id = $1`, [id]);
|
||||
@@ -213,25 +214,25 @@ async function updateOrder(id: number, data: { titel?: string; lieferant_id?: nu
|
||||
|
||||
const result = await pool.query(
|
||||
`UPDATE bestellungen
|
||||
SET titel = COALESCE($1, titel),
|
||||
SET bezeichnung = COALESCE($1, bezeichnung),
|
||||
lieferant_id = COALESCE($2, lieferant_id),
|
||||
beschreibung = COALESCE($3, beschreibung),
|
||||
prioritaet = COALESCE($4, prioritaet),
|
||||
notizen = COALESCE($3, notizen),
|
||||
budget = COALESCE($4, budget),
|
||||
status = COALESCE($5, status),
|
||||
bestellt_am = $6,
|
||||
abgeschlossen_am = $7,
|
||||
aktualisiert_am = NOW()
|
||||
WHERE id = $8
|
||||
RETURNING *`,
|
||||
[data.titel, data.lieferant_id, data.beschreibung, data.prioritaet, data.status, bestellt_am, abgeschlossen_am, id]
|
||||
[data.bezeichnung, data.lieferant_id, data.notizen, data.budget, data.status, bestellt_am, abgeschlossen_am, id]
|
||||
);
|
||||
if (result.rows.length === 0) return null;
|
||||
|
||||
const changes: string[] = [];
|
||||
if (data.titel) changes.push(`Titel geändert`);
|
||||
if (data.bezeichnung) changes.push(`Bezeichnung geändert`);
|
||||
if (data.lieferant_id) changes.push(`Lieferant geändert`);
|
||||
if (data.status && data.status !== oldStatus) changes.push(`Status: ${oldStatus} → ${data.status}`);
|
||||
if (data.prioritaet) changes.push(`Priorität geändert`);
|
||||
if (data.budget) changes.push(`Budget geändert`);
|
||||
|
||||
await logAction(id, 'Bestellung aktualisiert', changes.join(', ') || 'Bestellung bearbeitet', userId);
|
||||
return result.rows[0];
|
||||
@@ -275,12 +276,12 @@ async function deleteOrder(id: number, _userId: string) {
|
||||
}
|
||||
|
||||
const VALID_STATUS_TRANSITIONS: Record<string, string[]> = {
|
||||
entwurf: ['bestellt', 'storniert'],
|
||||
bestellt: ['teillieferung', 'vollstaendig', 'storniert'],
|
||||
teillieferung: ['vollstaendig', 'storniert'],
|
||||
entwurf: ['erstellt', 'bestellt'],
|
||||
erstellt: ['bestellt'],
|
||||
bestellt: ['teillieferung', 'vollstaendig'],
|
||||
teillieferung: ['vollstaendig'],
|
||||
vollstaendig: ['abgeschlossen'],
|
||||
abgeschlossen: [],
|
||||
storniert: ['entwurf'],
|
||||
};
|
||||
|
||||
async function updateOrderStatus(id: number, status: string, userId: string) {
|
||||
@@ -323,15 +324,15 @@ async function updateOrderStatus(id: number, status: string, userId: string) {
|
||||
// Line Items (Bestellpositionen)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function addLineItem(bestellungId: number, data: { artikel: string; menge: number; einheit?: string; einzelpreis?: number; notizen?: string }, userId: string) {
|
||||
async function addLineItem(bestellungId: number, data: { bezeichnung: string; artikelnummer?: string; menge: number; einheit?: string; einzelpreis?: number; notizen?: string }, userId: string) {
|
||||
try {
|
||||
const result = await pool.query(
|
||||
`INSERT INTO bestellpositionen (bestellung_id, artikel, menge, einheit, einzelpreis, notizen)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
`INSERT INTO bestellpositionen (bestellung_id, bezeichnung, artikelnummer, menge, einheit, einzelpreis, notizen)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
RETURNING *`,
|
||||
[bestellungId, data.artikel, data.menge, data.einheit || 'Stück', data.einzelpreis || 0, data.notizen || null]
|
||||
[bestellungId, data.bezeichnung, data.artikelnummer || null, data.menge, data.einheit || 'Stk', data.einzelpreis || 0, data.notizen || null]
|
||||
);
|
||||
await logAction(bestellungId, 'Position hinzugefügt', `"${data.artikel}" x${data.menge}`, userId);
|
||||
await logAction(bestellungId, 'Position hinzugefügt', `"${data.bezeichnung}" x${data.menge}`, userId);
|
||||
return result.rows[0];
|
||||
} catch (error) {
|
||||
logger.error('BestellungService.addLineItem failed', { error, bestellungId });
|
||||
@@ -339,23 +340,24 @@ async function addLineItem(bestellungId: number, data: { artikel: string; menge:
|
||||
}
|
||||
}
|
||||
|
||||
async function updateLineItem(id: number, data: { artikel?: string; menge?: number; einheit?: string; einzelpreis?: number; notizen?: string }, userId: string) {
|
||||
async function updateLineItem(id: number, data: { bezeichnung?: string; artikelnummer?: string; menge?: number; einheit?: string; einzelpreis?: number; notizen?: string }, userId: string) {
|
||||
try {
|
||||
const result = await pool.query(
|
||||
`UPDATE bestellpositionen
|
||||
SET artikel = COALESCE($1, artikel),
|
||||
menge = COALESCE($2, menge),
|
||||
einheit = COALESCE($3, einheit),
|
||||
einzelpreis = COALESCE($4, einzelpreis),
|
||||
notizen = COALESCE($5, notizen)
|
||||
WHERE id = $6
|
||||
SET bezeichnung = COALESCE($1, bezeichnung),
|
||||
artikelnummer = COALESCE($2, artikelnummer),
|
||||
menge = COALESCE($3, menge),
|
||||
einheit = COALESCE($4, einheit),
|
||||
einzelpreis = COALESCE($5, einzelpreis),
|
||||
notizen = COALESCE($6, notizen)
|
||||
WHERE id = $7
|
||||
RETURNING *`,
|
||||
[data.artikel, data.menge, data.einheit, data.einzelpreis, data.notizen, id]
|
||||
[data.bezeichnung, data.artikelnummer, data.menge, data.einheit, data.einzelpreis, data.notizen, id]
|
||||
);
|
||||
if (result.rows.length === 0) return null;
|
||||
|
||||
const item = result.rows[0];
|
||||
await logAction(item.bestellung_id, 'Position aktualisiert', `"${item.artikel}" bearbeitet`, userId);
|
||||
await logAction(item.bestellung_id, 'Position aktualisiert', `"${item.bezeichnung}" bearbeitet`, userId);
|
||||
return item;
|
||||
} catch (error) {
|
||||
logger.error('BestellungService.updateLineItem failed', { error, id });
|
||||
@@ -369,7 +371,7 @@ async function deleteLineItem(id: number, userId: string) {
|
||||
if (item.rows.length === 0) return false;
|
||||
|
||||
await pool.query(`DELETE FROM bestellpositionen WHERE id = $1`, [id]);
|
||||
await logAction(item.rows[0].bestellung_id, 'Position entfernt', `"${item.rows[0].artikel}" entfernt`, userId);
|
||||
await logAction(item.rows[0].bestellung_id, 'Position entfernt', `"${item.rows[0].bezeichnung}" entfernt`, userId);
|
||||
return true;
|
||||
} catch (error) {
|
||||
logger.error('BestellungService.deleteLineItem failed', { error, id });
|
||||
@@ -386,7 +388,7 @@ async function updateReceivedQuantity(id: number, menge: number, userId: string)
|
||||
if (result.rows.length === 0) return null;
|
||||
|
||||
const item = result.rows[0];
|
||||
await logAction(item.bestellung_id, 'Liefermenge aktualisiert', `"${item.artikel}": ${menge} von ${item.menge} erhalten`, userId);
|
||||
await logAction(item.bestellung_id, 'Liefermenge aktualisiert', `"${item.bezeichnung}": ${menge} von ${item.menge} erhalten`, userId);
|
||||
|
||||
// Check if all items for this order are fully received
|
||||
const allItems = await pool.query(
|
||||
@@ -477,15 +479,15 @@ async function getFilesByOrder(bestellungId: number) {
|
||||
// Reminders (Bestellung Erinnerungen)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function addReminder(bestellungId: number, data: { titel: string; faellig_am: string; notizen?: string }, userId: string) {
|
||||
async function addReminder(bestellungId: number, data: { nachricht: string; faellig_am: string }, userId: string) {
|
||||
try {
|
||||
const result = await pool.query(
|
||||
`INSERT INTO bestellung_erinnerungen (bestellung_id, titel, faellig_am, notizen, erstellt_von)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
`INSERT INTO bestellung_erinnerungen (bestellung_id, faellig_am, nachricht, erstellt_von)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
RETURNING *`,
|
||||
[bestellungId, data.titel, data.faellig_am, data.notizen || null, userId]
|
||||
[bestellungId, data.faellig_am, data.nachricht || null, userId]
|
||||
);
|
||||
await logAction(bestellungId, 'Erinnerung erstellt', `"${data.titel}" fällig am ${data.faellig_am}`, userId);
|
||||
await logAction(bestellungId, 'Erinnerung erstellt', `Erinnerung fällig am ${data.faellig_am}`, userId);
|
||||
return result.rows[0];
|
||||
} catch (error) {
|
||||
logger.error('BestellungService.addReminder failed', { error, bestellungId });
|
||||
@@ -502,7 +504,7 @@ async function markReminderDone(id: number, userId: string) {
|
||||
if (result.rows.length === 0) return null;
|
||||
|
||||
const reminder = result.rows[0];
|
||||
await logAction(reminder.bestellung_id, 'Erinnerung erledigt', `"${reminder.titel}"`, userId);
|
||||
await logAction(reminder.bestellung_id, 'Erinnerung erledigt', `Erinnerung #${reminder.id}`, userId);
|
||||
return reminder;
|
||||
} catch (error) {
|
||||
logger.error('BestellungService.markReminderDone failed', { error, id });
|
||||
@@ -526,7 +528,7 @@ async function deleteReminder(id: number) {
|
||||
async function getDueReminders() {
|
||||
try {
|
||||
const result = await pool.query(
|
||||
`SELECT e.*, b.titel AS bestellung_titel, b.erstellt_von AS besteller_id
|
||||
`SELECT e.*, b.bezeichnung AS bestellung_bezeichnung, b.erstellt_von AS besteller_id
|
||||
FROM bestellung_erinnerungen e
|
||||
JOIN bestellungen b ON b.id = e.bestellung_id
|
||||
WHERE e.faellig_am <= NOW() AND e.erledigt = FALSE
|
||||
@@ -546,9 +548,9 @@ async function getDueReminders() {
|
||||
async function logAction(bestellungId: number, aktion: string, details: string, userId: string) {
|
||||
try {
|
||||
await pool.query(
|
||||
`INSERT INTO bestellung_historie (bestellung_id, benutzer_id, aktion, details)
|
||||
VALUES ($1, $2, $3, $4)`,
|
||||
[bestellungId, userId, aktion, details]
|
||||
`INSERT INTO bestellung_historie (bestellung_id, erstellt_von, aktion, details)
|
||||
VALUES ($1, $2, $3, $4::jsonb)`,
|
||||
[bestellungId, userId, aktion, JSON.stringify({ text: details })]
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error('BestellungService.logAction failed', { error, bestellungId, aktion });
|
||||
@@ -561,7 +563,7 @@ async function getHistory(bestellungId: number) {
|
||||
const result = await pool.query(
|
||||
`SELECT h.*, u.display_name AS benutzer_name
|
||||
FROM bestellung_historie h
|
||||
LEFT JOIN users u ON u.id = h.benutzer_id
|
||||
LEFT JOIN users u ON u.id = h.erstellt_von
|
||||
WHERE h.bestellung_id = $1
|
||||
ORDER BY h.erstellt_am DESC`,
|
||||
[bestellungId]
|
||||
|
||||
Reference in New Issue
Block a user