rework internal order system
This commit is contained in:
@@ -2,28 +2,43 @@ import pool from '../config/database';
|
||||
import logger from '../utils/logger';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Categories (ausruestung_kategorien_katalog)
|
||||
// Categories (ausruestung_kategorien_katalog) — hierarchical with parent_id
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function getKategorien() {
|
||||
const result = await pool.query(
|
||||
'SELECT * FROM ausruestung_kategorien_katalog ORDER BY name',
|
||||
'SELECT * FROM ausruestung_kategorien_katalog ORDER BY parent_id NULLS FIRST, name',
|
||||
);
|
||||
return result.rows;
|
||||
}
|
||||
|
||||
async function createKategorie(name: string) {
|
||||
async function createKategorie(name: string, parentId?: number | null) {
|
||||
const result = await pool.query(
|
||||
'INSERT INTO ausruestung_kategorien_katalog (name) VALUES ($1) RETURNING *',
|
||||
[name],
|
||||
'INSERT INTO ausruestung_kategorien_katalog (name, parent_id) VALUES ($1, $2) RETURNING *',
|
||||
[name, parentId ?? null],
|
||||
);
|
||||
return result.rows[0];
|
||||
}
|
||||
|
||||
async function updateKategorie(id: number, name: string) {
|
||||
async function updateKategorie(id: number, data: { name?: string; parent_id?: number | null }) {
|
||||
const fields: string[] = [];
|
||||
const params: unknown[] = [];
|
||||
|
||||
if (data.name !== undefined) {
|
||||
params.push(data.name);
|
||||
fields.push(`name = $${params.length}`);
|
||||
}
|
||||
if (data.parent_id !== undefined) {
|
||||
params.push(data.parent_id);
|
||||
fields.push(`parent_id = $${params.length}`);
|
||||
}
|
||||
|
||||
if (fields.length === 0) return null;
|
||||
|
||||
params.push(id);
|
||||
const result = await pool.query(
|
||||
'UPDATE ausruestung_kategorien_katalog SET name = $1 WHERE id = $2 RETURNING *',
|
||||
[name, id],
|
||||
`UPDATE ausruestung_kategorien_katalog SET ${fields.join(', ')} WHERE id = $${params.length} RETURNING *`,
|
||||
params,
|
||||
);
|
||||
return result.rows[0] || null;
|
||||
}
|
||||
@@ -279,25 +294,30 @@ async function getRequestById(id: number) {
|
||||
[id],
|
||||
);
|
||||
|
||||
// Load eigenschaft values per position
|
||||
// Load eigenschaft values per position (gracefully handle missing table)
|
||||
const positionIds = positionen.rows.map((p: { id: number }) => p.id);
|
||||
let eigenschaftenMap: Record<number, { eigenschaft_id: number; eigenschaft_name: string; wert: string }[]> = {};
|
||||
if (positionIds.length > 0) {
|
||||
const eigenschaftenResult = await pool.query(
|
||||
`SELECT pe.position_id, pe.eigenschaft_id, ae.name AS eigenschaft_name, pe.wert
|
||||
FROM ausruestung_position_eigenschaften pe
|
||||
JOIN ausruestung_artikel_eigenschaften ae ON ae.id = pe.eigenschaft_id
|
||||
WHERE pe.position_id = ANY($1)
|
||||
ORDER BY ae.sort_order, ae.id`,
|
||||
[positionIds],
|
||||
);
|
||||
for (const row of eigenschaftenResult.rows) {
|
||||
if (!eigenschaftenMap[row.position_id]) eigenschaftenMap[row.position_id] = [];
|
||||
eigenschaftenMap[row.position_id].push({
|
||||
eigenschaft_id: row.eigenschaft_id,
|
||||
eigenschaft_name: row.eigenschaft_name,
|
||||
wert: row.wert,
|
||||
});
|
||||
try {
|
||||
const eigenschaftenResult = await pool.query(
|
||||
`SELECT pe.position_id, pe.eigenschaft_id, ae.name AS eigenschaft_name, pe.wert
|
||||
FROM ausruestung_position_eigenschaften pe
|
||||
JOIN ausruestung_artikel_eigenschaften ae ON ae.id = pe.eigenschaft_id
|
||||
WHERE pe.position_id = ANY($1)
|
||||
ORDER BY ae.sort_order, ae.id`,
|
||||
[positionIds],
|
||||
);
|
||||
for (const row of eigenschaftenResult.rows) {
|
||||
if (!eigenschaftenMap[row.position_id]) eigenschaftenMap[row.position_id] = [];
|
||||
eigenschaftenMap[row.position_id].push({
|
||||
eigenschaft_id: row.eigenschaft_id,
|
||||
eigenschaft_name: row.eigenschaft_name,
|
||||
wert: row.wert,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
// Table may not exist yet if migration hasn't run
|
||||
logger.debug('Position eigenschaften query failed (migration may not have run yet)', { error: err });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,12 +393,16 @@ async function createRequest(
|
||||
// Save eigenschaft values
|
||||
if (item.eigenschaften && item.eigenschaften.length > 0) {
|
||||
for (const e of item.eigenschaften) {
|
||||
await client.query(
|
||||
`INSERT INTO ausruestung_position_eigenschaften (position_id, eigenschaft_id, wert)
|
||||
VALUES ($1, $2, $3)
|
||||
ON CONFLICT (position_id, eigenschaft_id) DO UPDATE SET wert = $3`,
|
||||
[posResult.rows[0].id, e.eigenschaft_id, e.wert],
|
||||
);
|
||||
try {
|
||||
await client.query(
|
||||
`INSERT INTO ausruestung_position_eigenschaften (position_id, eigenschaft_id, wert)
|
||||
VALUES ($1, $2, $3)
|
||||
ON CONFLICT (position_id, eigenschaft_id) DO UPDATE SET wert = $3`,
|
||||
[posResult.rows[0].id, e.eigenschaft_id, e.wert],
|
||||
);
|
||||
} catch (err) {
|
||||
logger.debug('Position eigenschaft insert failed (migration may not have run yet)', { error: err });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -453,12 +477,16 @@ async function updateRequest(
|
||||
// Save eigenschaft values
|
||||
if (item.eigenschaften && item.eigenschaften.length > 0) {
|
||||
for (const e of item.eigenschaften) {
|
||||
await client.query(
|
||||
`INSERT INTO ausruestung_position_eigenschaften (position_id, eigenschaft_id, wert)
|
||||
VALUES ($1, $2, $3)
|
||||
ON CONFLICT (position_id, eigenschaft_id) DO UPDATE SET wert = $3`,
|
||||
[posResult.rows[0].id, e.eigenschaft_id, e.wert],
|
||||
);
|
||||
try {
|
||||
await client.query(
|
||||
`INSERT INTO ausruestung_position_eigenschaften (position_id, eigenschaft_id, wert)
|
||||
VALUES ($1, $2, $3)
|
||||
ON CONFLICT (position_id, eigenschaft_id) DO UPDATE SET wert = $3`,
|
||||
[posResult.rows[0].id, e.eigenschaft_id, e.wert],
|
||||
);
|
||||
} catch (err) {
|
||||
logger.debug('Position eigenschaft insert failed', { error: err });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -566,6 +594,22 @@ async function getOverview() {
|
||||
};
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Widget overview (no permission restriction — counts only)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function getWidgetOverview() {
|
||||
const result = await pool.query(
|
||||
`SELECT
|
||||
COUNT(*)::int AS total_count,
|
||||
COUNT(*) FILTER (WHERE status = 'offen')::int AS pending_count,
|
||||
COUNT(*) FILTER (WHERE status = 'genehmigt')::int AS approved_count,
|
||||
COUNT(*) FILTER (WHERE status = 'offen' AND bearbeitet_von IS NULL)::int AS unhandled_count
|
||||
FROM ausruestung_anfragen`,
|
||||
);
|
||||
return result.rows[0];
|
||||
}
|
||||
|
||||
export default {
|
||||
getKategorien,
|
||||
createKategorie,
|
||||
@@ -591,4 +635,5 @@ export default {
|
||||
unlinkFromOrder,
|
||||
getLinkedOrders,
|
||||
getOverview,
|
||||
getWidgetOverview,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user