model = $model; } /** * @param array $data */ public function create(array $data): OfferTemplate { return OfferTemplate::create($data); } /** * @param array $data */ public function update(OfferTemplate $template, array $data): OfferTemplate { $template->fill($data); $template->save(); return $template->fresh(); } /** * Aktive Vorlagen, optional gefiltert nach Branch (inkl. global = branch_id NULL). * * @return Collection */ public function listActive(?int $branchId = null): Collection { return OfferTemplate::query() ->active() ->forBranch($branchId) ->orderBy('name') ->get(); } /** * Wendet eine Vorlage auf eine Draft-Version an: * - kopiert Default-Texte (nur in leere Felder, bestehender Text wird nicht überschrieben) * - legt Positionen aus `default_items` an (ersetzt bestehende Items komplett) * - merkt sich die Vorlage in `offer_version.template_id` * * @return OfferVersion fresh, inkl. items */ public function applyTo(OfferTemplate $template, OfferVersion $version): OfferVersion { if (! $version->isEditable()) { throw new \DomainException( "OfferVersion #{$version->id} ist eingefroren (status={$version->status}); " . 'Vorlage kann nicht mehr angewendet werden.' ); } return DB::transaction(function () use ($template, $version) { $version->template_id = $template->id; $version->headline = $version->headline ?: $template->default_headline; $version->intro_text = $version->intro_text ?: $template->default_intro; $version->itinerary_text = $version->itinerary_text ?: $template->default_itinerary; $version->closing_text = $version->closing_text ?: $template->default_closing; $version->save(); OfferItem::where('offer_version_id', $version->id)->delete(); $position = 0; $sum = 0.0; foreach ((array) $template->default_items as $itemData) { $item = new OfferItem(array_merge($itemData, [ 'offer_version_id' => $version->id, 'position' => $position++, ])); $item->recomputeTotal(); $item->save(); $sum += (float) $item->total_price; } $version->total_price = $sum; $version->save(); return $version->fresh(['items']); }); } }