From 440be3a36ffaad59f7404aec79742f644d7638fc Mon Sep 17 00:00:00 2001 From: "Fabian @ Blax Software" Date: Sun, 25 Jan 2026 10:40:17 +0100 Subject: [PATCH] I order notes, BF checkout currency --- .../Controllers/StripeWebhookController.php | 16 +++-- src/Models/Cart.php | 1 + src/Models/Order.php | 67 +++++++++++++++++-- tests/Unit/Stripe/StripeWebhookOrderTest.php | 1 - 4 files changed, 71 insertions(+), 14 deletions(-) diff --git a/src/Http/Controllers/StripeWebhookController.php b/src/Http/Controllers/StripeWebhookController.php index 766a869..fddbf7b 100644 --- a/src/Http/Controllers/StripeWebhookController.php +++ b/src/Http/Controllers/StripeWebhookController.php @@ -163,10 +163,11 @@ class StripeWebhookController // recordPayment(int $amount, ?string $reference, ?string $method, ?string $provider) $order->recordPayment($amountPaid, $session->payment_intent, 'stripe', 'stripe'); - // Add a detailed note + // Add a detailed note (customer-visible) $order->addNote( - "Payment of " . Order::formatMoney($amountPaid, $currency) . " received via Stripe checkout (Session: {$session->id})", - OrderNote::TYPE_PAYMENT + "Payment of " . Order::formatMoney($amountPaid, $currency) . " received", + OrderNote::TYPE_PAYMENT, + true ); // Mark order as processing if payment is successful @@ -202,10 +203,11 @@ class StripeWebhookController $order = $cart->order; if ($order && $order->status->canTransitionTo(OrderStatus::FAILED)) { $order->update(['status' => OrderStatus::FAILED]); - // addNote(string $content, string $type, bool $isCustomerNote, ?string $authorType, ?string $authorId) + // Internal note - payment failure details should not be shown to customer $order->addNote( "Payment failed via Stripe checkout (Session: {$session->id})", - OrderNote::TYPE_PAYMENT + OrderNote::TYPE_PAYMENT, + false ); } } @@ -231,9 +233,11 @@ class StripeWebhookController // Add note to order if it exists $order = $cart->order; if ($order) { + // Internal note - session expiry is a technical detail $order->addNote( "Stripe checkout session expired (Session: {$session->id})", - OrderNote::TYPE_SYSTEM + OrderNote::TYPE_SYSTEM, + false ); } } diff --git a/src/Models/Cart.php b/src/Models/Cart.php index 2f4786b..de26bae 100644 --- a/src/Models/Cart.php +++ b/src/Models/Cart.php @@ -2058,6 +2058,7 @@ class Cart extends Model // Prepare session parameters $sessionParams = [ 'payment_method_types' => ['card'], + 'currency' => strtoupper($this->currency), 'line_items' => $lineItems, 'mode' => 'payment', 'success_url' => $success_url, diff --git a/src/Models/Order.php b/src/Models/Order.php index b7285cb..5dc6d13 100644 --- a/src/Models/Order.php +++ b/src/Models/Order.php @@ -147,10 +147,11 @@ class Order extends Model $difference = $newPaid - $oldPaid; if ($difference > 0) { + $currency = $order->currency ?? config('shop.currency', 'USD'); $order->addNote( - "Payment received: " . static::formatMoney($difference, $order->currency), + "Payment received: " . static::formatMoney($difference, $currency), 'payment', - false + true ); // Mark as paid if fully paid @@ -441,10 +442,12 @@ class Order extends Model $this->amount_refunded = ($this->amount_refunded ?? 0) + $amount; $this->save(); + $currency = $this->currency ?? config('shop.currency', 'USD'); $this->addNote( - "Refund processed: " . static::formatMoney($amount, $this->currency) . + "Refund processed: " . static::formatMoney($amount, $currency) . ($reason ? " - Reason: {$reason}" : ''), - 'refund' + 'refund', + true ); // If fully refunded, update status @@ -566,6 +569,56 @@ class Order extends Model ]); } + /** + * Scope to get final/finished orders (completed, cancelled, refunded, failed, delivered). + * Uses OrderStatus::isFinal() to determine which statuses are final. + */ + public function scopeFinal($query) + { + $finalStatuses = array_map( + fn(OrderStatus $status) => $status->value, + array_filter(OrderStatus::cases(), fn(OrderStatus $status) => $status->isFinal()) + ); + + return $query->whereIn('status', $finalStatuses); + } + + /** + * Alias for scopeFinal - get finished orders. + */ + public function scopeFinished($query) + { + return $this->scopeFinal($query); + } + + /** + * Scope to get orders requiring payment (pending status). + * Uses OrderStatus::requiresPayment() to determine which statuses require payment. + */ + public function scopeRequiresPayment($query) + { + $requiresPaymentStatuses = array_map( + fn(OrderStatus $status) => $status->value, + array_filter(OrderStatus::cases(), fn(OrderStatus $status) => $status->requiresPayment()) + ); + + return $query->whereIn('status', $requiresPaymentStatuses); + } + + /** + * Scope to get orders with a paid status (processing, shipped, delivered, etc.). + * Uses OrderStatus::isPaid() - this is different from scopePaid() which checks amounts. + */ + public function scopeStatusPaid($query) + { + $paidStatuses = array_map( + fn(OrderStatus $status) => $status->value, + array_filter(OrderStatus::cases(), fn(OrderStatus $status) => $status->isPaid()) + ); + + return $query->whereIn('status', $paidStatuses); + } + /** * Scope to get completed orders. */ @@ -575,7 +628,7 @@ class Order extends Model } /** - * Scope to get paid orders. + * Scope to get paid orders (by amount). */ public function scopePaid($query) { @@ -583,7 +636,7 @@ class Order extends Model } /** - * Scope to get unpaid orders. + * Scope to get unpaid orders (by amount). */ public function scopeUnpaid($query) { @@ -857,7 +910,7 @@ class Order extends Model 'status' => OrderStatus::PENDING, ]); - $order->addNote('Order created from cart checkout', 'system', false); + $order->addNote('Order created from cart checkout', 'system', true); return $order; } diff --git a/tests/Unit/Stripe/StripeWebhookOrderTest.php b/tests/Unit/Stripe/StripeWebhookOrderTest.php index a11f3de..e30a7fa 100644 --- a/tests/Unit/Stripe/StripeWebhookOrderTest.php +++ b/tests/Unit/Stripe/StripeWebhookOrderTest.php @@ -685,7 +685,6 @@ class StripeWebhookOrderTest extends TestCase $paymentNote = $order->notes()->where('type', OrderNote::TYPE_PAYMENT)->first(); $this->assertNotNull($paymentNote, 'Payment note should be created'); $this->assertStringContainsString('50', $paymentNote->content); - $this->assertStringContainsString('Stripe checkout', $paymentNote->content); } #[Test]