fix(persoenliche-ausruestung): save characteristics on create/edit and add editable eigenschaft fields to assignment page

This commit is contained in:
Matthias Hochmeister
2026-04-15 20:06:02 +02:00
parent 260b71baf8
commit 3f8c4d151d
6 changed files with 141 additions and 51 deletions

View File

@@ -572,6 +572,7 @@ class AusruestungsanfrageController {
benutzerName?: string;
groesse?: string;
kategorie?: string;
eigenschaften?: Array<{ eigenschaft_id?: number; name: string; wert: string }>;
}>;
};

View File

@@ -15,6 +15,12 @@ const isoDate = z.string().regex(
const ZustandEnum = z.enum(['gut', 'beschaedigt', 'abgaengig', 'verloren']);
const EigenschaftInput = z.object({
eigenschaft_id: z.number().int().positive().nullable().optional(),
name: z.string().min(1).max(200),
wert: z.string().max(500),
});
const CreateSchema = z.object({
bezeichnung: z.string().min(1).max(200),
kategorie: z.string().max(100).optional(),
@@ -27,6 +33,7 @@ const CreateSchema = z.object({
anschaffung_datum: isoDate.optional(),
zustand: ZustandEnum.optional(),
notizen: z.string().max(2000).optional(),
eigenschaften: z.array(EigenschaftInput).optional(),
});
const UpdateSchema = z.object({
@@ -41,6 +48,7 @@ const UpdateSchema = z.object({
anschaffung_datum: isoDate.nullable().optional(),
zustand: ZustandEnum.optional(),
notizen: z.string().max(2000).nullable().optional(),
eigenschaften: z.array(EigenschaftInput).nullable().optional(),
});
function isValidUUID(s: string): boolean {

View File

@@ -959,6 +959,7 @@ interface AssignmentInput {
benutzerName?: string;
groesse?: string;
kategorie?: string;
eigenschaften?: { eigenschaft_id?: number; name: string; wert: string }[];
}
async function assignDeliveredItems(
@@ -1057,20 +1058,31 @@ async function assignDeliveredItems(
);
const newId = insertResult.rows[0].id;
// Copy position eigenschaften to persoenliche_ausruestung_eigenschaften
const posEigResult = await client.query(
`SELECT poe.eigenschaft_id, aae.name, poe.wert
FROM ausruestung_position_eigenschaften poe
JOIN ausruestung_artikel_eigenschaften aae ON aae.id = poe.eigenschaft_id
WHERE poe.position_id = $1`,
[a.positionId],
);
for (const row of posEigResult.rows) {
await client.query(
`INSERT INTO persoenliche_ausruestung_eigenschaften (persoenlich_id, eigenschaft_id, name, wert)
VALUES ($1, $2, $3, $4) ON CONFLICT DO NOTHING`,
[newId, row.eigenschaft_id, row.name, row.wert],
// Copy eigenschaften: use frontend-provided values if any, otherwise copy from position
const providedEig = a.eigenschaften && a.eigenschaften.length > 0;
if (providedEig) {
for (const e of a.eigenschaften!) {
await client.query(
`INSERT INTO persoenliche_ausruestung_eigenschaften (persoenlich_id, eigenschaft_id, name, wert)
VALUES ($1, $2, $3, $4) ON CONFLICT DO NOTHING`,
[newId, e.eigenschaft_id ?? null, e.name, e.wert],
);
}
} else {
const posEigResult = await client.query(
`SELECT poe.eigenschaft_id, aae.name, poe.wert
FROM ausruestung_position_eigenschaften poe
JOIN ausruestung_artikel_eigenschaften aae ON aae.id = poe.eigenschaft_id
WHERE poe.position_id = $1`,
[a.positionId],
);
for (const row of posEigResult.rows) {
await client.query(
`INSERT INTO persoenliche_ausruestung_eigenschaften (persoenlich_id, eigenschaft_id, name, wert)
VALUES ($1, $2, $3, $4) ON CONFLICT DO NOTHING`,
[newId, row.eigenschaft_id, row.name, row.wert],
);
}
}
await client.query(

View File

@@ -19,7 +19,7 @@ interface CreatePersonalEquipmentData {
anschaffung_datum?: string;
zustand?: string;
notizen?: string;
eigenschaften?: { eigenschaft_id?: number; name: string; wert: string }[];
eigenschaften?: { eigenschaft_id?: number | null; name: string; wert: string }[];
}
interface UpdatePersonalEquipmentData {