104 lines
3.3 KiB
PHP
104 lines
3.3 KiB
PHP
<?php
|
|
|
|
namespace App\Repositories;
|
|
|
|
use App\Models\OfferItem;
|
|
use App\Models\OfferTemplate;
|
|
use App\Models\OfferVersion;
|
|
use Illuminate\Support\Collection;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
/**
|
|
* Repository für Angebots-Vorlagen.
|
|
*
|
|
* Vorlagen bestehen aus Default-Texten (Headline/Intro/Itinerary/Closing)
|
|
* und einer Default-Positionsliste (JSON in `default_items`). Über
|
|
* {@see applyTo()} wird eine Vorlage in eine existierende Draft-Version
|
|
* hineinkopiert (Texte + Positionen).
|
|
*/
|
|
class OfferTemplateRepository extends BaseRepository
|
|
{
|
|
public function __construct(OfferTemplate $model)
|
|
{
|
|
$this->model = $model;
|
|
}
|
|
|
|
/**
|
|
* @param array<string,mixed> $data
|
|
*/
|
|
public function create(array $data): OfferTemplate
|
|
{
|
|
return OfferTemplate::create($data);
|
|
}
|
|
|
|
/**
|
|
* @param array<string,mixed> $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<int, OfferTemplate>
|
|
*/
|
|
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']);
|
|
});
|
|
}
|
|
}
|