IM product purchase process

This commit is contained in:
a6a2f5842 2025-11-22 15:13:30 +01:00
parent afe7359ea4
commit 2c31b6ea98
4 changed files with 26 additions and 21 deletions

View File

@ -179,7 +179,7 @@ return new class extends Migration
// Product stock logs table // Product stock logs table
if (!Schema::hasTable(config('shop.tables.product_stock_logs', 'product_stock_logs'))) { if (!Schema::hasTable(config('shop.tables.product_stock_logs', 'product_stock_logs'))) {
Schema::create(config('shop.tables.product_stock_logs', 'product_stock_logs'), function (Blueprint $table) { Schema::create(config('shop.tables.product_stock_logs', 'product_stock_logs'), function (Blueprint $table) {
$table->uuid('id')->primary(); $table->id();
$table->uuid('product_id'); $table->uuid('product_id');
$table->integer('quantity_change'); $table->integer('quantity_change');
$table->integer('quantity_after'); $table->integer('quantity_after');

View File

@ -13,6 +13,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
class Product extends Model implements Purchasable class Product extends Model implements Purchasable
{ {
@ -25,15 +26,11 @@ class Product extends Model implements Purchasable
'description', 'description',
'type', 'type',
'stripe_product_id', 'stripe_product_id',
'price',
'regular_price',
'sale_price',
'sale_start', 'sale_start',
'sale_end', 'sale_end',
'manage_stock', 'manage_stock',
'stock_quantity', 'stock_quantity',
'low_stock_threshold', 'low_stock_threshold',
'in_stock',
'stock_status', 'stock_status',
'weight', 'weight',
'length', 'length',
@ -298,7 +295,7 @@ class Product extends Model implements Purchasable
protected function logStockChange(int $quantityChange, string $type): void protected function logStockChange(int $quantityChange, string $type): void
{ {
\DB::table('product_stock_logs')->insert([ DB::table('product_stock_logs')->insert([
'product_id' => $this->id, 'product_id' => $this->id,
'quantity_change' => $quantityChange, 'quantity_change' => $quantityChange,
'quantity_after' => $this->stock_quantity, 'quantity_after' => $this->stock_quantity,

View File

@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace Rapidez\Shop\Services; namespace Blax\Shop\Services;
use Blax\Shop\Models\Product; use Blax\Shop\Models\Product;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;

View File

@ -4,6 +4,7 @@ namespace Blax\Shop\Traits;
use Blax\Shop\Models\ProductPurchase; use Blax\Shop\Models\ProductPurchase;
use Blax\Shop\Models\Product; use Blax\Shop\Models\Product;
use Blax\Shop\Models\ProductPrice;
use Illuminate\Database\Eloquent\Relations\MorphMany; use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -41,12 +42,25 @@ trait HasShoppingCapabilities
* *
* @param Product $product * @param Product $product
* @param int $quantity * @param int $quantity
* @param array $options Additional options (price_id, meta, etc.) *
* @return ProductPurchase * @return ProductPurchase
* @throws \Exception * @throws \Exception
*/ */
public function purchase(Product $product, int $quantity = 1, array $options = []): ProductPurchase public function purchase(
{ ProductPrice|string $productPrice,
int $quantity = 1,
): ProductPurchase {
if ($productPrice instanceof ProductPrice) {
} else {
$productPrice = ProductPrice::findOrFail($productPrice);
}
if (!$productPrice?->product?->id) {
throw new \Exception("Price does not belong to the specified product");
}
$product = $productPrice->product;
// Validate stock availability // Validate stock availability
if ($product->manage_stock) { if ($product->manage_stock) {
$available = $product->getAvailableStock(); $available = $product->getAvailableStock();
@ -65,27 +79,21 @@ trait HasShoppingCapabilities
throw new \Exception("Unable to decrease stock"); throw new \Exception("Unable to decrease stock");
} }
// Determine price
$priceId = $options['price_id'] ?? null;
$price = $this->determinePurchasePrice($product, $priceId);
// Create purchase record // Create purchase record
$purchase = $this->purchases()->create([ $purchase = $this->purchases()->create([
'product_id' => $product->id, 'product_id' => $product->id,
'quantity' => $quantity, 'quantity' => $quantity,
'status' => $options['status'] ?? 'completed', 'status' => 'unpaid',
'meta' => array_merge([ 'meta' => array_merge([
'price_id' => $priceId, 'price_id' => $productPrice->id,
'price' => $price, 'price' => $productPrice->price,
'amount' => $price * $quantity, 'amount' => $productPrice->price * $quantity,
'charge_id' => $options['charge_id'] ?? null, ]),
], $options['meta'] ?? []),
]); ]);
// Trigger product actions // Trigger product actions
$product->callActions('purchased', $purchase, [ $product->callActions('purchased', $purchase, [
'purchaser' => $this, 'purchaser' => $this,
...$options,
]); ]);
return $purchase; return $purchase;