Files
WitShop/app/Services/OrderService.php
T
marcoandClaude Sonnet 4.6 41078fdc08 Initial commit: WitShop Laravel Online-Shop
- Laravel 11, Blade, Alpine.js, Tailwind CSS
- Produkt- & Kategorieverwaltung mit Varianten
- Checkout (Vorkasse + Rechnung), Session-Warenkorb
- Admin-Backend (Dashboard, Bestellungen, Kunden, CMS)
- DSGVO-konform: Cookie-Consent, Impressum, Widerruf, AGB
- PDF-Rechnung via dompdf, SMTP-Mailversand
- Kundenverwaltung mit manueller Freischaltung

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 00:34:09 +02:00

94 lines
3.1 KiB
PHP

<?php
namespace App\Services;
use App\Mail\OrderConfirmationMail;
use App\Mail\OrderShippedMail;
use App\Models\Order;
use App\Models\OrderAddress;
use App\Models\OrderItem;
use App\Models\ProductVariant;
use App\Models\ShippingRate;
use Illuminate\Support\Facades\Mail;
class OrderService
{
public function __construct(private CartService $cart) {}
public function createFromSession(array $addressData, string $paymentMethod): Order
{
$items = $this->cart->get();
$subtotal = $this->cart->subtotal();
$shippingRate = ShippingRate::forCart($subtotal);
$shippingCost = $shippingRate ? $shippingRate->getCostForTotal($subtotal) : 0;
$taxTotal = array_sum(array_map(function ($item) {
$net = $item['price'] / (1 + $item['tax_rate'] / 100);
return round(($item['price'] - $net) * $item['qty'], 2);
}, $items));
$order = Order::create([
'order_number' => Order::generateOrderNumber(),
'user_id' => auth()->id(),
'guest_email' => auth()->check() ? null : ($addressData['email'] ?? null),
'status' => 'new',
'payment_method' => $paymentMethod,
'subtotal' => $subtotal,
'tax_total' => $taxTotal,
'shipping_cost' => $shippingCost,
'total' => $subtotal + $shippingCost,
]);
foreach ($items as $item) {
OrderItem::create([
'order_id' => $order->id,
'product_variant_id'=> $item['variant_id'],
'product_name' => $item['product_name'],
'variant_label' => $item['variant_label'],
'quantity' => $item['qty'],
'unit_price' => $item['price'],
'tax_rate' => $item['tax_rate'],
]);
// Bestand reduzieren — nur wenn track_stock aktiv
$variant = ProductVariant::with('product')->find($item['variant_id']);
if ($variant && $variant->product->track_stock) {
$variant->decrement('stock', $item['qty']);
}
}
foreach (['billing', 'shipping'] as $type) {
$src = $addressData[$type] ?? $addressData['billing'];
OrderAddress::create(array_merge($src, ['order_id' => $order->id, 'type' => $type]));
}
$this->cart->clear();
Mail::to($order->guest_email ?? $order->user?->email)->send(new OrderConfirmationMail($order));
return $order;
}
public function updateStatus(Order $order, string $newStatus, ?string $trackingCode = null): void
{
$order->status = $newStatus;
if ($newStatus === 'payment_received' && !$order->paid_at) {
$order->paid_at = now();
}
if ($trackingCode) {
$order->tracking_code = $trackingCode;
}
$order->save();
if ($newStatus === 'shipped') {
$email = $order->guest_email ?? $order->user?->email;
if ($email) {
Mail::to($email)->send(new OrderShippedMail($order));
}
}
}
}