196 lines
6.3 KiB
Markdown
196 lines
6.3 KiB
Markdown
# Laravel Shop - Repository Context
|
|
|
|
This document provides context for AI agents and developers working on this repository.
|
|
|
|
## Project Overview
|
|
|
|
- **Package Name**: `blax-software/laravel-shop`
|
|
- **Type**: Composer package (Laravel library)
|
|
- **Purpose**: A comprehensive headless e-commerce package for Laravel
|
|
- **License**: MIT
|
|
- **PHP Version**: 8.2+
|
|
- **Laravel Version**: 9.0 - 12.0
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
├── config/ # Configuration files
|
|
│ └── shop.php # Main shop configuration
|
|
├── database/
|
|
│ ├── factories/ # Model factories for testing
|
|
│ └── migrations/ # Database migration stubs
|
|
├── docs/ # Documentation
|
|
├── routes/
|
|
│ └── api.php # API routes (webhooks, etc.)
|
|
├── src/
|
|
│ ├── Console/Commands/ # Artisan commands
|
|
│ ├── Contracts/ # Interfaces (Cartable, Chargable, Purchasable)
|
|
│ ├── Enums/ # PHP Enums (ProductType, OrderStatus, etc.)
|
|
│ ├── Events/ # Laravel events
|
|
│ ├── Exceptions/ # Custom exceptions
|
|
│ ├── Facades/ # Shop, Cart facades
|
|
│ ├── Http/ # Controllers (webhooks)
|
|
│ ├── Models/ # Eloquent models
|
|
│ ├── Services/ # Service classes
|
|
│ ├── Traits/ # Reusable traits
|
|
│ └── ShopServiceProvider.php
|
|
├── tests/
|
|
│ ├── Feature/ # Feature/integration tests
|
|
│ ├── Unit/ # Unit tests
|
|
│ ├── TestCase.php # Base test case
|
|
│ └── bootstrap.php # PHPUnit bootstrap
|
|
└── workbench/ # Orchestra Testbench workbench
|
|
```
|
|
|
|
## Key Concepts
|
|
|
|
### Product Types
|
|
- **SIMPLE**: Standalone product with no variations
|
|
- E.g., "T-shirt", "Mug", "E-book"
|
|
- **VARIABLE**: Product with variations/options
|
|
- E.g., "T-shirt" with sizes S, M, L
|
|
- **GROUPED**: Collection of related products sold together
|
|
- E.g., "Gift Set" with multiple items
|
|
- **EXTERNAL**: Product linking to external purchase site
|
|
- E.g., "Third-party course"
|
|
- **BOOKING**: Time-based bookable product
|
|
- E.g., "Hotel Room", "Consultation Slot"
|
|
- **POOL**: Dynamic pricing based on availability and grouped stocks
|
|
- E.g., "Parking Space", "Event Ticket"
|
|
|
|
### Pool Products
|
|
Pool products are complex - they consist of:
|
|
- A **pool parent** (e.g., "Parking Spaces")
|
|
- Multiple **single items** (e.g., individual parking spots)
|
|
- **Pricing strategy**: LOWEST, HIGHEST, or AVERAGE
|
|
- **Fallback pricing**: Pool can have a default price if singles don't have prices
|
|
|
|
Key pool concepts:
|
|
- `product_id` column on cart_items tracks which single is allocated
|
|
- `reallocatePoolItems()` reassigns singles when dates change
|
|
- Singles can use pool's price as fallback
|
|
|
|
### Cart System
|
|
- Authenticated users: Cart stored in database
|
|
- Guest users: Session-based cart with session ID
|
|
- Cart items track: `purchasable_id`, `purchasable_type`, `product_id`, `price_id`, `from`, `until`
|
|
- Booking items require date ranges
|
|
|
|
### Stripe Integration
|
|
- Syncs products/prices to Stripe
|
|
- Handles webhooks for checkout.session.completed
|
|
- Creates orders from completed checkout sessions
|
|
- Uses Laravel Cashier
|
|
|
|
## Commands
|
|
|
|
### Running Tests
|
|
```bash|fish
|
|
./vendor/bin/phpunit
|
|
```
|
|
|
|
## Testing
|
|
|
|
- **Framework**: PHPUnit 10+
|
|
- **Database**: SQLite in-memory for tests
|
|
- **Base Class**: `Blax\Shop\Tests\TestCase` (extends Orchestra Testbench)
|
|
- **Factories**: Located in `database/factories/`
|
|
|
|
### Writing Tests
|
|
```php
|
|
<?php
|
|
|
|
namespace Blax\Shop\Tests\Feature\Pool;
|
|
|
|
use Blax\Shop\Tests\TestCase;
|
|
use PHPUnit\Framework\Attributes\Test;
|
|
|
|
class MyPoolTest extends TestCase
|
|
{
|
|
#[Test]
|
|
public function it_does_something()
|
|
{
|
|
// Test code
|
|
}
|
|
}
|
|
```
|
|
|
|
## Key Models
|
|
|
|
| Model | Description |
|
|
|-------------------|---------------------------------------------------|
|
|
| `Product` | Main product model with types, stock, pricing |
|
|
| `ProductPrice` | Prices for products (multi-currency, sale prices) |
|
|
| `ProductCategory` | Product categorization |
|
|
| `Cart` | Shopping cart (user or guest) |
|
|
| `CartItem` | Items in cart with quantities, dates, prices |
|
|
| `Order` | Completed orders |
|
|
| `Purchase` | Individual purchase records |
|
|
|
|
## Key Traits
|
|
|
|
| Trait | Purpose |
|
|
|---------------------------|------------------------------------------|
|
|
| `HasShoppingCapabilities` | Add to User model for purchasing ability |
|
|
| `MayBePoolProduct` | Pool product functionality |
|
|
| `HasStock` | Stock management methods |
|
|
| `Purchasable` | Make models purchasable |
|
|
|
|
## Configuration
|
|
|
|
Main config file: `config/shop.php`
|
|
|
|
Key settings:
|
|
- `shop.tables.*` - Database table names
|
|
- `shop.cache.*` - Caching configuration
|
|
- `shop.stripe.*` - Stripe integration settings
|
|
|
|
## Dependencies
|
|
|
|
### Required
|
|
- `illuminate/support` & `illuminate/database` (Laravel)
|
|
- `blax-software/laravel-workkit` (Base utilities)
|
|
- `laravel/cashier` (Stripe integration)
|
|
|
|
### Dev
|
|
- `orchestra/testbench` (Laravel package testing)
|
|
- `phpunit/phpunit` (Testing)
|
|
- `mockery/mockery` (Mocking)
|
|
|
|
## Common Patterns
|
|
|
|
### Creating a Pool Product
|
|
```php
|
|
$pool = Product::create([
|
|
'type' => ProductType::POOL,
|
|
'name' => 'Parking Spaces',
|
|
// ...
|
|
]);
|
|
|
|
$single1 = Product::create([
|
|
'type' => ProductType::BOOKING,
|
|
'name' => 'Spot A1',
|
|
// ...
|
|
]);
|
|
|
|
$pool->attachSingleItems([$single1->id]);
|
|
```
|
|
|
|
### Adding to Cart with Dates
|
|
```php
|
|
$cart->addToCart($product, 1, [], $from, $until);
|
|
```
|
|
|
|
### Checking Out
|
|
```php
|
|
$cart->checkout(); // Creates purchases, claims stock
|
|
```
|
|
|
|
## Recent Architecture Decisions
|
|
|
|
1. **`product_id` column on cart_items**: Replaced `allocated_single_item_id` in meta with a proper foreign key column to track which pool single is allocated to a cart item.
|
|
|
|
2. **Order creation in webhooks**: Stripe checkout flow creates orders in the webhook handler when the cart doesn't have a pre-existing order.
|
|
|
|
3. **Price fallback for pool singles**: Singles without prices use the pool's price as fallback.
|