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:
@ -36,7 +36,8 @@ use holzleitner_application::usecases::{
|
||||
AssignCarToDeliveryUseCase, CompleteDeliveryUseCase, CreateDeliveryNoteUseCase,
|
||||
CreateMyCarUseCase, CreatePaymentMethodUseCase, CreateServiceUseCase,
|
||||
DeleteDeliveryNoteUseCase, DeleteDeliveryServiceUseCase, DeletePaymentMethodUseCase,
|
||||
DeleteServiceUseCase, DevResyncToursUseCase, GenerateDeliveryReportUseCase, GetAccountUseCase,
|
||||
DeleteServiceUseCase, DevResetDeliveryUseCase, DevResyncToursUseCase,
|
||||
GenerateDeliveryReportUseCase, GetAccountUseCase,
|
||||
GetAttachmentPreviewUseCase, GetTourUseCase,
|
||||
ImportErpToursUseCase, ListDeliveredBelegnummernUseCase, ListMyCarsUseCase,
|
||||
ListMyToursTodayUseCase, ListPaymentMethodsUseCase,
|
||||
@ -345,6 +346,9 @@ pub(crate) async fn run_app(
|
||||
tour_repository.clone(),
|
||||
import_erp_tours.clone(),
|
||||
));
|
||||
// DEV-ONLY: einzelne Lieferung zurücksetzen (per Belegnummer).
|
||||
let dev_reset_delivery =
|
||||
Arc::new(DevResetDeliveryUseCase::new(tour_repository.clone()));
|
||||
// ERP-Rückschreiben beim Lieferabschluss. Der Push-Use-Case wird IMMER
|
||||
// gebaut (Admin-Retry-Endpunkt nutzt ihn manuell). Ob der normale
|
||||
// Abschluss-Pfad automatisch pusht, steuert `ERP_WRITEBACK_ENABLED`.
|
||||
@ -447,6 +451,7 @@ pub(crate) async fn run_app(
|
||||
set_delivery_order,
|
||||
import_erp_tours: import_erp_tours.clone(),
|
||||
dev_resync_tours,
|
||||
dev_reset_delivery,
|
||||
generate_delivery_report,
|
||||
process_delivery_report: process_delivery_report.clone(),
|
||||
report_upload_enabled: cfg.report.upload_enabled,
|
||||
|
||||
@ -24,6 +24,7 @@ use crate::state::AppState;
|
||||
pub fn router() -> Router<AppState> {
|
||||
Router::new()
|
||||
.route("/dev/resync", post(dev_resync))
|
||||
.route("/dev/reset-delivery", post(dev_reset_delivery))
|
||||
.route("/dev/generate-report", post(dev_generate_report))
|
||||
.route("/dev/process-report", post(dev_process_report))
|
||||
.route("/dev/unmark-mail-sent", post(dev_unmark_mail_sent))
|
||||
@ -64,6 +65,43 @@ pub async fn dev_resync(
|
||||
Ok(Json(summary))
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct DevResetDeliveryQuery {
|
||||
/// ERP-Belegnummer der zurückzusetzenden Lieferung.
|
||||
pub belegnummer: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct DevResetDeliveryResponse {
|
||||
pub belegnummer: String,
|
||||
/// Anzahl zurückgesetzter Lieferungen (1 bei Erfolg).
|
||||
pub reset: u64,
|
||||
}
|
||||
|
||||
/// DEV-ONLY, UNAUTHENTIFIZIERT: setzt EINE Lieferung (per Belegnummer) zurück —
|
||||
/// Abschluss, Scan-/Gutschrift-Audit + Report-Job weg, Positionen + Lieferung
|
||||
/// zurück auf `active`. Notizen/Dienstleistungen/Anhänge bleiben. 404, wenn die
|
||||
/// Belegnummer unbekannt ist.
|
||||
pub async fn dev_reset_delivery(
|
||||
State(state): State<AppState>,
|
||||
Query(query): Query<DevResetDeliveryQuery>,
|
||||
) -> Result<Json<DevResetDeliveryResponse>, ApiError> {
|
||||
tracing::warn!(belegnummer = %query.belegnummer, "dev.reset_delivery");
|
||||
let reset = state.dev_reset_delivery.execute(&query.belegnummer).await?;
|
||||
if reset == 0 {
|
||||
return Err(ApiError(ApplicationError::NotFound));
|
||||
}
|
||||
tracing::info!(
|
||||
belegnummer = %query.belegnummer,
|
||||
reset,
|
||||
"dev.reset_delivery.done"
|
||||
);
|
||||
Ok(Json(DevResetDeliveryResponse {
|
||||
belegnummer: query.belegnummer,
|
||||
reset,
|
||||
}))
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct DevReportQuery {
|
||||
/// UUID der Lieferung, für die der Report erzeugt werden soll.
|
||||
|
||||
@ -6,7 +6,8 @@ use holzleitner_application::usecases::{
|
||||
AssignCarToDeliveryUseCase, CompleteDeliveryUseCase, CreateDeliveryNoteUseCase,
|
||||
CreateMyCarUseCase, CreatePaymentMethodUseCase, CreateServiceUseCase,
|
||||
DeleteDeliveryNoteUseCase, DeleteDeliveryServiceUseCase, DeletePaymentMethodUseCase,
|
||||
DeleteServiceUseCase, DevResyncToursUseCase, GenerateDeliveryReportUseCase, GetAccountUseCase,
|
||||
DeleteServiceUseCase, DevResetDeliveryUseCase, DevResyncToursUseCase,
|
||||
GenerateDeliveryReportUseCase, GetAccountUseCase,
|
||||
GetAttachmentPreviewUseCase, GetTourUseCase,
|
||||
ImportErpToursUseCase, ListDeliveredBelegnummernUseCase, ListMyCarsUseCase,
|
||||
ListMyToursTodayUseCase, ListPaymentMethodsUseCase,
|
||||
@ -33,6 +34,8 @@ pub struct AppState {
|
||||
pub import_erp_tours: Arc<ImportErpToursUseCase>,
|
||||
/// DEV-ONLY: überschreibender Resync (löscht Postgres + importiert neu).
|
||||
pub dev_resync_tours: Arc<DevResyncToursUseCase>,
|
||||
/// DEV-ONLY: setzt eine einzelne Lieferung (per Belegnummer) zurück.
|
||||
pub dev_reset_delivery: Arc<DevResetDeliveryUseCase>,
|
||||
/// Erzeugt den PDF-Lieferreport (lokal — Dev-Endpoint + Fallback ohne Upload).
|
||||
pub generate_delivery_report: Arc<GenerateDeliveryReportUseCase>,
|
||||
/// Überträgt den Report an DOCUframe (Upload → Makro → Cleanup) — beim
|
||||
|
||||
Reference in New Issue
Block a user