use std::sync::Arc; use uuid::Uuid; use holzleitner_domain::DeliveryNote; use crate::dto::CreateDeliveryNoteRequest; use crate::error::ApplicationError; use crate::ports::{CarRepository, DeliveryNoteRepository}; /// Legt eine neue Notiz an einer Lieferung an. /// /// Validierung: /// * mindestens eines von `text` (nicht-leer nach trim) und /// `image_attachment` (nicht-leer nach trim) muss gesetzt sein. /// * `author_car_id` muss — falls gesetzt — zum angemeldeten Account gehören. pub struct CreateDeliveryNoteUseCase { repository: Arc, cars: Arc, } impl CreateDeliveryNoteUseCase { pub fn new( repository: Arc, cars: Arc, ) -> Self { Self { repository, cars } } pub async fn execute( &self, delivery_id: Uuid, author_personalnummer: i64, request: CreateDeliveryNoteRequest, ) -> Result { let text = clean(request.text); let image = clean(request.image_attachment); if text.is_none() && image.is_none() { return Err(ApplicationError::Validation( "notiz braucht text oder image_attachment".into(), )); } if let Some(car_id) = request.author_car_id { self.cars .assert_owned_by_account(&[car_id], author_personalnummer) .await?; } self.repository .create( delivery_id, author_personalnummer, request.author_car_id, text, image, request.credit_delivery_item_id, request.is_amount_credit_note, ) .await } } /// Trim + leerer-String → None. fn clean(input: Option) -> Option { input.and_then(|s| { let trimmed = s.trim(); if trimmed.is_empty() { None } else { Some(trimmed.to_owned()) } }) }