Add coupons, newsletter, country-based shipping, sale prices, USP bar
Deploy to Production (witstore.wende.it) / deploy (push) Successful in 8s
Deploy to Production (witstore.wende.it) / deploy (push) Successful in 8s
- Gutscheincodes: DB-Verwaltung (%, €-Rabatt, Mindestbestellwert, Ablauf), Eingabefeld im Checkout, Admin unter Marketing → Gutscheine - Newsletter: Double-Opt-In per E-Mail, Formular im Footer, Admin-Liste mit CSV-Export - Länderzonen-Versand: DE / DACH / EU / WORLD, Versandkosten nach Lieferland dynamisch berechnet, Coupon-Rabatt in Bestellung gespeichert - Sale-Preise: sale_price auf Produkten, durchgestrichener UVP auf Produktkarte, Sonderangebote-Sektion auf Startseite - USP-Leiste auf Startseite: Versand, Zahlung, Rückgabe, Service Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ namespace App\Services;
|
||||
|
||||
use App\Mail\OrderConfirmationMail;
|
||||
use App\Mail\OrderShippedMail;
|
||||
use App\Models\Coupon;
|
||||
use App\Models\Order;
|
||||
use App\Models\OrderAddress;
|
||||
use App\Models\OrderItem;
|
||||
@@ -17,40 +18,58 @@ class OrderService
|
||||
|
||||
public function createFromSession(array $addressData, string $paymentMethod): Order
|
||||
{
|
||||
$items = $this->cart->get();
|
||||
$items = $this->cart->get();
|
||||
$subtotal = $this->cart->subtotal();
|
||||
|
||||
$shippingRate = ShippingRate::forCart($subtotal);
|
||||
$country = $addressData['shipping']['country'] ?? $addressData['billing']['country'] ?? 'DE';
|
||||
$shippingRate = ShippingRate::forCart($subtotal, $country);
|
||||
$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);
|
||||
// Gutschein aus Session
|
||||
$couponCode = null;
|
||||
$discountAmount = 0;
|
||||
if ($code = session('coupon_code')) {
|
||||
$coupon = Coupon::findValid($code);
|
||||
if ($coupon) {
|
||||
$discountAmount = $coupon->calcDiscount($subtotal);
|
||||
$couponCode = $coupon->code;
|
||||
$coupon->increment('used_count');
|
||||
}
|
||||
}
|
||||
|
||||
$taxable = max(0, $subtotal - $discountAmount);
|
||||
$taxTotal = array_sum(array_map(function ($item) use ($subtotal, $discountAmount) {
|
||||
$ratio = $subtotal > 0 ? ($item['price'] * $item['qty']) / $subtotal : 0;
|
||||
$itemNet = ($item['price'] * $item['qty'] - $discountAmount * $ratio) / (1 + $item['tax_rate'] / 100);
|
||||
return round(($item['price'] * $item['qty'] - $discountAmount * $ratio) - $itemNet, 2);
|
||||
}, $items));
|
||||
|
||||
$total = max(0, $subtotal - $discountAmount) + $shippingCost;
|
||||
|
||||
$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,
|
||||
'order_number' => Order::generateOrderNumber(),
|
||||
'user_id' => auth()->id(),
|
||||
'guest_email' => auth()->check() ? null : ($addressData['email'] ?? null),
|
||||
'status' => 'new',
|
||||
'payment_method' => $paymentMethod,
|
||||
'coupon_code' => $couponCode,
|
||||
'discount_amount' => $discountAmount,
|
||||
'subtotal' => $subtotal,
|
||||
'tax_total' => $taxTotal,
|
||||
'shipping_cost' => $shippingCost,
|
||||
'total' => $total,
|
||||
]);
|
||||
|
||||
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'],
|
||||
'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']);
|
||||
@@ -63,6 +82,7 @@ class OrderService
|
||||
}
|
||||
|
||||
$this->cart->clear();
|
||||
session()->forget('coupon_code');
|
||||
|
||||
Mail::to($order->guest_email ?? $order->user?->email)->send(new OrderConfirmationMail($order));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user