feat(abschluss): interne Notiz des Fahrers beim Abschluss
- CompleteDeliveryAcknowledgements.internalNote (optional, getrimmt, max. 2000 Zeichen) wird atomar mit dem Abschluss gespeichert (delivery_completions.internal_note) - Bewusst keine delivery_notes-Zeile: loest weder die Kunden-Bestaetigung der Notizen aus noch erscheint sie im Notizen-Step der App - Lieferbericht: eigener Abschnitt "Interne Notiz" mit Zeitpunkt und Fahrer - Bericht: Betrag in "Betrag erhalten" ans Zeilenende (Helvetica setzt nach dem Euro-Zeichen zu eng) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@ -295,8 +295,8 @@ impl DeliveryCompletionRepository for PgDeliveryCompletionRepository {
|
||||
delivery_id, customer_signature_path, driver_signature_path,
|
||||
receipt_confirmed, notes_acknowledged, acknowledged_note_ids,
|
||||
completed_by_personalnummer, completed_by_car_id,
|
||||
payment_collected, collected_amount_cents, payment_id
|
||||
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
|
||||
payment_collected, collected_amount_cents, payment_id, internal_note
|
||||
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
||||
"#,
|
||||
)
|
||||
.bind(delivery_id)
|
||||
@ -310,6 +310,7 @@ impl DeliveryCompletionRepository for PgDeliveryCompletionRepository {
|
||||
.bind(requires_collection && collected)
|
||||
.bind(collected_amount_cents)
|
||||
.bind(logged_payment_id)
|
||||
.bind(input.internal_note.as_deref())
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
.map_err(db)?;
|
||||
|
||||
@ -568,7 +568,7 @@ impl DeliveryReportRenderer for PdfDeliveryReportRenderer {
|
||||
if let Some(collected) = c.collected_amount_cents {
|
||||
p.kv(
|
||||
"Betrag erhalten",
|
||||
&format!("Ja — {} (am {})", cents(collected), dt(self.tz, &c.completed_at)),
|
||||
&format!("Ja, am {} — {}", dt(self.tz, &c.completed_at), cents(collected)),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -620,6 +620,30 @@ impl DeliveryReportRenderer for PdfDeliveryReportRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
// 6b. Interne Notiz des Fahrers (nach den Unterschriften erfasst,
|
||||
// nicht Teil der Kunden-Bestätigung).
|
||||
p.heading("Interne Notiz");
|
||||
match d
|
||||
.completion
|
||||
.as_ref()
|
||||
.and_then(|c| c.internal_note.as_deref().map(|n| (c, n)))
|
||||
{
|
||||
Some((c, note)) => {
|
||||
p.text(
|
||||
&format!(
|
||||
"{} · Fahrer {}",
|
||||
dt(self.tz, &c.completed_at),
|
||||
c.completed_by_personalnummer
|
||||
),
|
||||
8.0,
|
||||
true,
|
||||
0.0,
|
||||
);
|
||||
p.text(note, 9.0, false, 4.0);
|
||||
}
|
||||
None => p.text("— keine —", 9.0, false, 0.0),
|
||||
}
|
||||
|
||||
// 7. Unterschriften
|
||||
p.heading("Unterschriften");
|
||||
match &d.completion {
|
||||
|
||||
@ -104,6 +104,7 @@ struct CompletionRow {
|
||||
payment_collected: bool,
|
||||
collected_amount_cents: Option<i64>,
|
||||
payment_id: Option<Uuid>,
|
||||
internal_note: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(sqlx::FromRow)]
|
||||
@ -289,7 +290,7 @@ impl DeliveryReportRepository for PgDeliveryReportRepository {
|
||||
r#"
|
||||
SELECT completed_at, completed_by_personalnummer, receipt_confirmed,
|
||||
notes_acknowledged, customer_signature_path, driver_signature_path,
|
||||
payment_collected, collected_amount_cents, payment_id
|
||||
payment_collected, collected_amount_cents, payment_id, internal_note
|
||||
FROM delivery_completions
|
||||
WHERE delivery_id = $1
|
||||
"#,
|
||||
@ -466,6 +467,7 @@ impl DeliveryReportRepository for PgDeliveryReportRepository {
|
||||
payment_collected: c.payment_collected,
|
||||
collected_amount_cents: c.collected_amount_cents,
|
||||
payment_id: c.payment_id,
|
||||
internal_note: c.internal_note,
|
||||
}),
|
||||
scan_audit: scan_audit
|
||||
.into_iter()
|
||||
|
||||
@ -81,6 +81,7 @@ fn input(delivery_id: Uuid, payment_collected: bool) -> CompleteDeliveryInput {
|
||||
payment_method_id: None,
|
||||
completed_by_personalnummer: 1,
|
||||
completed_by_car_id: None,
|
||||
internal_note: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,8 +157,15 @@ async fn payment_protocol_and_completion_gate() {
|
||||
assert_eq!(payment_id, Some(inv.id));
|
||||
|
||||
// 8) Alte App: Flag ohne Protokoll funktioniert weiterhin.
|
||||
// Dazu interne Notiz: wird am Abschluss gespeichert.
|
||||
let d4 = seed(&pool, CASH).await;
|
||||
completions.complete(input(d4, true)).await.unwrap();
|
||||
let mut with_note = input(d4, true);
|
||||
with_note.internal_note = Some("Kunde wünscht Rückruf wegen Montage".into());
|
||||
completions.complete(with_note).await.unwrap();
|
||||
let note: Option<String> =
|
||||
sqlx::query_scalar("SELECT internal_note FROM delivery_completions WHERE delivery_id = $1")
|
||||
.bind(d4).fetch_one(&pool).await.unwrap();
|
||||
assert_eq!(note.as_deref(), Some("Kunde wünscht Rückruf wegen Montage"));
|
||||
|
||||
// 9) Tour-Aggregat liefert die jüngste Zahlung; Einzel-Reset löscht sie.
|
||||
let tours = PgTourRepository::new(pool.clone());
|
||||
|
||||
Reference in New Issue
Block a user