feat(dev): /dev/reset-delivery — einzelne Lieferung per Belegnummer zurücksetzen
Setzt EINE Lieferung zurück, ohne die Tour zu löschen (Alternative zum destruktiven /dev/resync): Abschluss (delivery_completions), Scan-/ Gutschrift-Audit + offener Report-Job weg, Positionen zurück (scanned/ credited = 0, Status in_progress), Lieferung wieder active (state_reason/ assigned_car/review_* geleert). Notizen/Dienstleistungen/Anhänge bleiben. Vervollständigt den bisher nur als Port-Stub vorhandenen reset_delivery_by_belegnummer (Build war dadurch kaputt) + Use Case + DEV-Route (nur bei dev.sync_enabled gemountet, unauthentifiziert). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -912,6 +912,82 @@ impl TourRepository for PgTourRepository {
|
||||
.map_err(db)?;
|
||||
Ok(res.rows_affected())
|
||||
}
|
||||
|
||||
async fn reset_delivery_by_belegnummer(
|
||||
&self,
|
||||
belegnummer: &str,
|
||||
) -> Result<u64, ApplicationError> {
|
||||
let mut tx = self.pool.begin().await.map_err(db)?;
|
||||
|
||||
// Subquery-Filter überall identisch: Lieferung(en) mit dieser Belegnr.
|
||||
const BY_BELEG: &str =
|
||||
"SELECT id FROM deliveries WHERE erp_belegnummer = $1";
|
||||
|
||||
// Abschluss + (evtl.) offener Report-Job + Scan-/Gutschrift-Audit löschen.
|
||||
sqlx::query(&format!(
|
||||
"DELETE FROM delivery_report_jobs WHERE delivery_id IN ({BY_BELEG})"
|
||||
))
|
||||
.bind(belegnummer)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
.map_err(db)?;
|
||||
|
||||
sqlx::query(&format!(
|
||||
"DELETE FROM delivery_completions WHERE delivery_id IN ({BY_BELEG})"
|
||||
))
|
||||
.bind(belegnummer)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
.map_err(db)?;
|
||||
|
||||
sqlx::query(
|
||||
"DELETE FROM scan_audit WHERE delivery_item_id IN (\
|
||||
SELECT di.id FROM delivery_items di \
|
||||
JOIN deliveries d ON d.id = di.delivery_id \
|
||||
WHERE d.erp_belegnummer = $1)",
|
||||
)
|
||||
.bind(belegnummer)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
.map_err(db)?;
|
||||
|
||||
sqlx::query(&format!(
|
||||
"DELETE FROM delivery_credit_audit WHERE delivery_id IN ({BY_BELEG})"
|
||||
))
|
||||
.bind(belegnummer)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
.map_err(db)?;
|
||||
|
||||
// Positionen zurück (verladen + gutgeschrieben = 0, Status offen).
|
||||
sqlx::query(&format!(
|
||||
"UPDATE delivery_items \
|
||||
SET scanned_quantity = 0, scan_status = 'in_progress', \
|
||||
held_reason = NULL, credited_quantity = 0, \
|
||||
scan_last_updated_at = now() \
|
||||
WHERE delivery_id IN ({BY_BELEG})"
|
||||
))
|
||||
.bind(belegnummer)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
.map_err(db)?;
|
||||
|
||||
// Lieferung wieder aktiv; Status-/Auto-/Review-Felder leeren.
|
||||
let res = sqlx::query(
|
||||
"UPDATE deliveries \
|
||||
SET state = 'active', state_reason = NULL, assigned_car_id = NULL, \
|
||||
review_resolved_at = NULL, review_resolved_by = NULL, \
|
||||
review_note = NULL \
|
||||
WHERE erp_belegnummer = $1",
|
||||
)
|
||||
.bind(belegnummer)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
.map_err(db)?;
|
||||
|
||||
tx.commit().await.map_err(db)?;
|
||||
Ok(res.rows_affected())
|
||||
}
|
||||
}
|
||||
|
||||
// ===== Upsert-Helfer =====================================================
|
||||
|
||||
Reference in New Issue
Block a user