feature: order create endpoint

This commit is contained in:
kusowl 2026-03-18 18:59:45 +05:30
parent a0e5cda432
commit d065ef1db9
23 changed files with 640 additions and 159 deletions

View File

@ -2220,7 +2220,9 @@
'cache.headers','can','guest','password.confirm','precognitive',
'signed','throttle','verified',);
registerArgumentsSet('routes',
'sanctum.csrf-cookie','cart.show','cart.update','cart.store','cart.destroy','products.index','products.store','products.show','products.update',
'sanctum.csrf-cookie','cart.show','cart.update','cart.store','cart.destroy',
'user.addresses.index','user.addresses.store','addresses.show','addresses.update','addresses.destroy',
'users.orders.index','users.orders.store','orders.show','orders.update','orders.destroy','products.index','products.store','products.show','products.update',
'products.destroy',
'storage.local','storage.local.upload',);
registerArgumentsSet('views',

View File

@ -0,0 +1,234 @@
<?php
// @formatter:off
// phpcs:ignoreFile
/**
* A helper file for your Eloquent Models
* Copy the phpDocs from this file to the correct Model,
* And remove them from this file, to prevent double declarations.
*
* @author Barry vd. Heuvel <barryvdh@gmail.com>
*/
namespace App\Models{
/**
* @property int $id
* @property string $first_name
* @property string $last_name
* @property string $street
* @property string $city
* @property string $state
* @property string $pin
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
* @property-read int|null $users_count
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address whereCity($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address whereFirstName($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address whereLastName($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address wherePin($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address whereState($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address whereStreet($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address whereUpdatedAt($value)
* @mixin \Eloquent
*/
#[\AllowDynamicProperties]
class IdeHelperAddress {}
}
namespace App\Models{
/**
* @property int $id
* @property int $user_id
* @property \App\Enums\CartStatus $status
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \App\Models\Order|null $order
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Product> $products
* @property-read int|null $products_count
* @property-read \App\Models\User|null $user
* @method static \Illuminate\Database\Eloquent\Builder<static>|Cart active()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Cart newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Cart newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Cart query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Cart whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Cart whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Cart whereStatus($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Cart whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Cart whereUserId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Cart withProducts()
* @mixin \Eloquent
*/
#[\AllowDynamicProperties]
class IdeHelperCart {}
}
namespace App\Models{
/**
* @property int $id
* @property int $user_id
* @property int $cart_id
* @property string $status
* @property string $shipping_first_name
* @property string $shipping_last_name
* @property string $shipping_street
* @property string $shipping_city
* @property string $shipping_state
* @property string $shipping_pin
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \App\Models\Cart|null $cart
* @property-read \App\Models\User $user
* @method static \Illuminate\Database\Eloquent\Builder<static>|Order newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Order newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Order query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Order whereCartId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Order whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Order whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Order whereShippingCity($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Order whereShippingFirstName($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Order whereShippingLastName($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Order whereShippingPin($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Order whereShippingState($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Order whereShippingStreet($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Order whereStatus($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Order whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Order whereUserId($value)
* @mixin \Eloquent
*/
#[\AllowDynamicProperties]
class IdeHelperOrder {}
}
namespace App\Models{
/**
* @property int $id
* @property string $title
* @property string|null $slug
* @property string $description
* @property numeric $actual_price
* @property numeric $list_price
* @property int $product_category_id
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property bool $is_active
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Cart> $carts
* @property-read int|null $carts_count
* @property-read \App\Models\ProductCategory|null $category
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $favoritedBy
* @property-read int|null $favorited_by_count
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ProductImage> $images
* @property-read int|null $images_count
* @method static \Illuminate\Database\Eloquent\Builder<static>|Product active()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Product newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Product newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Product query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Product whereActualPrice($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Product whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Product whereDescription($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Product whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Product whereIsActive($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Product whereListPrice($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Product whereProductCategoryId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Product whereSlug($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Product whereTitle($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Product whereUpdatedAt($value)
* @mixin \Eloquent
*/
#[\AllowDynamicProperties]
class IdeHelperProduct {}
}
namespace App\Models{
/**
* @property int $id
* @property string $name
* @property string $slug
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductCategory newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductCategory newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductCategory query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductCategory whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductCategory whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductCategory whereName($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductCategory whereSlug($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductCategory whereUpdatedAt($value)
* @mixin \Eloquent
*/
#[\AllowDynamicProperties]
class IdeHelperProductCategory {}
}
namespace App\Models{
/**
* @property int $id
* @property string $path
* @property int $product_id
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \App\Models\Product|null $product
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductImage newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductImage newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductImage query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductImage whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductImage whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductImage wherePath($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductImage whereProductId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductImage whereUpdatedAt($value)
* @mixin \Eloquent
*/
#[\AllowDynamicProperties]
class IdeHelperProductImage {}
}
namespace App\Models{
/**
* @property int $id
* @property string $name
* @property string $email
* @property \Illuminate\Support\Carbon|null $email_verified_at
* @property string $password
* @property string|null $remember_token
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property string $mobile_number
* @property string $city
* @property \App\Enums\UserRoles $role
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Address> $addresses
* @property-read int|null $addresses_count
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Cart> $carts
* @property-read int|null $carts_count
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Product> $favoriteProducts
* @property-read int|null $favorite_products_count
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
* @property-read int|null $notifications_count
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Order> $orders
* @property-read int|null $orders_count
* @method static \Database\Factories\UserFactory factory($count = null, $state = [])
* @method static \Illuminate\Database\Eloquent\Builder<static>|User newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|User newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|User query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereCity($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereEmail($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereEmailVerifiedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereMobileNumber($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereName($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|User wherePassword($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereRememberToken($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereRole($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereUpdatedAt($value)
* @mixin \Eloquent
*/
#[\AllowDynamicProperties]
class IdeHelperUser {}
}

View File

@ -0,0 +1,55 @@
<?php
namespace App\Actions;
use App\Data\OrderRequestDTO;
use App\Enums\CartStatus;
use App\Exceptions\StaleCartException;
use App\Models\Address;
use App\Models\Cart;
use App\Models\Order;
use App\Models\User;
use Illuminate\Http\JsonResponse;
final readonly class CreateOrderAction
{
/**
* Execute the action.
* @throws StaleCartException
*/
public function execute(OrderRequestDTO $dto, User $user): JsonResponse
{
/** @var Cart $cart */
$cart = Cart::query()->where('id', $dto->cartId)->sole();
if ($cart->status !== CartStatus::Active) {
throw new StaleCartException(userId: $user->id, cartId: $cart->id);
}
// check if the user has an order with the same cart id
if ($user->orders()->where('cart_id', $cart->id)->exists()) {
return response()->json([
'message' => 'User already has an order with this cart'
]);
}
/** @var Address $address */
$address = $user->addresses()->where('id', $dto->addressId)->sole();
/** @var Order $order */
$order = $user->orders()->make();
$order->cart_id = $cart->id;
$order->shipping_first_name = $address->first_name;
$order->shipping_last_name = $address->last_name;
$order->shipping_street = $address->street;
$order->shipping_city = $address->city;
$order->shipping_state = $address->state;
$order->shipping_pin = $address->pin;
$order->save();
return response()->json([
'message' => 'Order created successfully'
], 201);
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace App\Data;
use App\Contracts\InputDataTransferObject;
use Illuminate\Foundation\Http\FormRequest;
final readonly class OrderRequestDTO implements InputDataTransferObject
{
public function __construct(
public int $cartId,
public string $addressId,
) {}
/**
* @return array<string, mixed>
*/
public function toArray(): array
{
return [
'cart_id' => $this->cartId,
'address_id' => $this->addressId,
];
}
public static function fromRequest(FormRequest $request): OrderRequestDTO
{
return new self(
cartId: $request->cartId,
addressId: $request->addressId,
);
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace App\Data;
use App\Contracts\OutputDataTransferObject;
use Illuminate\Database\Eloquent\Model;
final readonly class OrderResponeDTO implements OutputDataTransferObject
{
public function __construct(
// TODO: Define your properties here
) {}
/**
* @return array<string, mixed>
*/
public function toArray(): array
{
return [
// TODO: Map properties to array
];
}
public static function fromModel(Model $model): OutputDataTransferObject
{
return new self(
// TODO: Map model data to properties
);
}
}

View File

@ -0,0 +1,15 @@
<?php
namespace App\Enums;
/**
* Open -> The order was placed or created. There is work to do for the order, which can include processing payment, fulfilling, or processing returns.
* Archived -> The order was manually or automatically archived. Usually, this means the order was fulfilled.
* Canceled -> The order was canceled. If a canceled order was not fully refunded, then there might be work remaining for the order.
*/
enum OrderStatus: string
{
case Open = 'open';
case Archived = 'archived';
case Closed = 'closed';
}

View File

@ -0,0 +1,30 @@
<?php
namespace App\Exceptions;
use Exception;
use Illuminate\Http\JsonResponse;
class StaleCartException extends Exception
{
public function __construct(
public readonly int|string $userId,
public readonly int|string $cartId,
public $message = 'Attempt to create a order with a stale cart',
) {
parent::__construct($message);
}
public function context(): array
{
return [
'user_id' => $this->userId,
'cart_id' => $this->cartId,
];
}
public function render(): JsonResponse
{
return response()->json(['message' => 'Cart is stale'], 409);
}
}

View File

@ -0,0 +1,53 @@
<?php
namespace App\Http\Controllers;
use App\Actions\CreateOrderAction;
use App\Data\OrderRequestDTO;
use App\Http\Requests\StoreOrderRequest;
use App\Http\Requests\UpdateOrderRequest;
use App\Http\Resources\OrderResource;
use App\Models\Order;
class OrderController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(StoreOrderRequest $request, CreateOrderAction $action)
{
return $action->execute(OrderRequestDTO::fromRequest($request), $request->user());
}
/**
* Display the specified resource.
*/
public function show(Order $order)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(UpdateOrderRequest $request, Order $order)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(Order $order)
{
//
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace App\Http\Requests;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;
class StoreOrderRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'cartId' => 'required|exists:carts,id',
'addressId' => 'required|exists:addresses,id',
];
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace App\Http\Requests;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;
class UpdateOrderRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return false;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
//
];
}
}

View File

@ -12,6 +12,7 @@
class AddressResource extends JsonResource
{
public static $wrap = null;
/**
* Transform the resource into an array.
*

View File

@ -0,0 +1,19 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class OrderResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return parent::toArray($request);
}
}

View File

@ -8,35 +8,7 @@
use Illuminate\Support\Carbon;
/**
* @property-read User|null $user
*
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address query()
*
* @property-read Collection<int, User> $users
* @property-read int|null $users_count
* @property int $id
* @property string $first_name
* @property string $last_name
* @property string $street
* @property string $city
* @property string $state
* @property string $pin
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
*
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address whereCity($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address whereFirstName($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address whereLastName($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address wherePin($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address whereState($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address whereStreet($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Address whereUpdatedAt($value)
*
* @mixin \Eloquent
* @mixin IdeHelperAddress
*/
class Address extends Model
{

View File

@ -7,54 +7,44 @@
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Support\Carbon;
/**
* @property int $id
* @property int $user_id
* @property CartStatus $status
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property-read Collection<int, Product> $products
* @property-read int|null $products_count
* @property-read User|null $user
*
* @method static Builder<static>|Cart active()
* @method static Builder<static>|Cart newModelQuery()
* @method static Builder<static>|Cart newQuery()
* @method static Builder<static>|Cart query()
* @method static Builder<static>|Cart whereCreatedAt($value)
* @method static Builder<static>|Cart whereId($value)
* @method static Builder<static>|Cart whereStatus($value)
* @method static Builder<static>|Cart whereUpdatedAt($value)
* @method static Builder<static>|Cart whereUserId($value)
* @method static Builder<static>|Cart withProducts()
*
* @mixin \Eloquent
* @mixin IdeHelperCart
*/
class Cart extends Model
{
protected $fillable = ['user_id', 'status'];
protected function casts()
/**
* @return array<string, string>
*/
protected function casts(): array
{
return [
'status' => CartStatus::class,
];
}
public function products()
public function products(): BelongsToMany
{
return $this->belongsToMany(Product::class)
->withPivot('price', 'quantity')
->withTimestamps();
}
public function user()
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function order(): BelongsTo
{
return $this->belongsTo(Order::class);
}
#[Scope]
protected function active(Builder $query)
{

View File

@ -0,0 +1,28 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOne;
/**
* @mixin IdeHelperOrder
*/
class Order extends Model
{
public $fillable = [
'user_id', 'cart_id', 'status', 'shipping_city', 'shipping_street', 'shipping_last_name', 'shipping_first_name',
'shipping_state', 'shipping_pin'
];
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function cart(): HasOne
{
return $this->hasOne(Cart::class);
}
}

View File

@ -13,40 +13,7 @@
use Illuminate\Support\Str;
/**
* @property int $id
* @property string $title
* @property string|null $slug
* @property string $description
* @property numeric $actual_price
* @property numeric $list_price
* @property int $product_category_id
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property bool $is_active
* @property-read Collection<int, Cart> $carts
* @property-read int|null $carts_count
* @property-read ProductCategory|null $category
* @property-read Collection<int, User> $favoritedBy
* @property-read int|null $favorited_by_count
* @property-read Collection<int, ProductImage> $images
* @property-read int|null $images_count
*
* @method static Builder<static>|Product active()
* @method static Builder<static>|Product newModelQuery()
* @method static Builder<static>|Product newQuery()
* @method static Builder<static>|Product query()
* @method static Builder<static>|Product whereActualPrice($value)
* @method static Builder<static>|Product whereCreatedAt($value)
* @method static Builder<static>|Product whereDescription($value)
* @method static Builder<static>|Product whereId($value)
* @method static Builder<static>|Product whereIsActive($value)
* @method static Builder<static>|Product whereListPrice($value)
* @method static Builder<static>|Product whereProductCategoryId($value)
* @method static Builder<static>|Product whereSlug($value)
* @method static Builder<static>|Product whereTitle($value)
* @method static Builder<static>|Product whereUpdatedAt($value)
*
* @mixin \Eloquent
* @mixin IdeHelperProduct
*/
class Product extends Model
{

View File

@ -6,22 +6,7 @@
use Illuminate\Support\Carbon;
/**
* @property int $id
* @property string $name
* @property string $slug
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
*
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductCategory newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductCategory newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductCategory query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductCategory whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductCategory whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductCategory whereName($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductCategory whereSlug($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductCategory whereUpdatedAt($value)
*
* @mixin \Eloquent
* @mixin IdeHelperProductCategory
*/
class ProductCategory extends Model
{

View File

@ -7,23 +7,7 @@
use Illuminate\Support\Carbon;
/**
* @property int $id
* @property string $path
* @property int $product_id
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property-read Product|null $product
*
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductImage newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductImage newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductImage query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductImage whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductImage whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductImage wherePath($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductImage whereProductId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ProductImage whereUpdatedAt($value)
*
* @mixin \Eloquent
* @mixin IdeHelperProductImage
*/
class ProductImage extends Model
{

View File

@ -8,6 +8,7 @@
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\DatabaseNotification;
use Illuminate\Notifications\DatabaseNotificationCollection;
@ -15,41 +16,7 @@
use Illuminate\Support\Carbon;
/**
* @property int $id
* @property string $name
* @property string $email
* @property Carbon|null $email_verified_at
* @property string $password
* @property string|null $remember_token
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property string $mobile_number
* @property string $city
* @property UserRoles $role
* @property-read Collection<int, Cart> $carts
* @property-read int|null $carts_count
* @property-read Collection<int, Product> $favoriteProducts
* @property-read int|null $favorite_products_count
* @property-read DatabaseNotificationCollection<int, DatabaseNotification> $notifications
* @property-read int|null $notifications_count
*
* @method static \Database\Factories\UserFactory factory($count = null, $state = [])
* @method static \Illuminate\Database\Eloquent\Builder<static>|User newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|User newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|User query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereCity($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereEmail($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereEmailVerifiedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereMobileNumber($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereName($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|User wherePassword($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereRememberToken($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereRole($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereUpdatedAt($value)
*
* @mixin \Eloquent
* @mixin IdeHelperUser
*/
class User extends Authenticatable
{
@ -106,13 +73,27 @@ public function hasFavorited(Product $product): bool
return $this->favoriteProducts()->where('product_id', $product->id)->exists();
}
public function carts()
/**
* @return HasMany<Cart>
*/
public function carts():HasMany
{
return $this->hasMany(Cart::class);
}
/**
* @return BelongsToMany<Address>
*/
public function addresses(): BelongsToMany
{
return $this->belongsToMany(Address::class);
}
/**
* @return HasMany<Order>
*/
public function orders(): HasMany
{
return $this->hasMany(Order::class);
}
}

View File

@ -45,6 +45,7 @@
"@php artisan migrate --force"
],
"dev": [
"Composer\\Config::disableProcessTimeout",
"@php artisan serve"
],
"test": [
@ -59,7 +60,8 @@
"@php artisan vendor:publish --tag=laravel-assets --ansi --force",
"@php artisan vendor:publish --tag=laravel-assets --ansi --force",
"@php artisan ide-helper:generate",
"@php artisan ide-helper:meta"
"@php artisan ide-helper:meta",
"@php artisan ide-helper:model --write-mixin"
],
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""

2
backend/composer.lock generated
View File

@ -9716,5 +9716,5 @@
"php": "^8.2"
},
"platform-dev": {},
"plugin-api-version": "2.6.0"
"plugin-api-version": "2.9.0"
}

View File

@ -0,0 +1,39 @@
<?php
use App\Enums\OrderStatus;
use App\Models\Cart;
use App\Models\User;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('orders', function (Blueprint $table) {
$table->id();
$table->foreignIdFor(User::class)->constrained()->cascadeOnDelete();
$table->foreignIdFor(Cart::class)->constrained()->cascadeOnDelete();
$table->enum('status', array_column(OrderStatus::cases(), 'value'));
$table->string('shipping_first_name');
$table->string('shipping_last_name');
$table->string('shipping_street');
$table->string('shipping_city');
$table->string('shipping_state');
$table->string('shipping_pin');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('orders');
}
};

View File

@ -3,6 +3,7 @@
use App\Http\Controllers\AuthenticatedUserController;
use App\Http\Controllers\CartController;
use App\Http\Controllers\FavouriteProductController;
use App\Http\Controllers\OrderController;
use App\Http\Controllers\ProductCategoryController;
use App\Http\Controllers\ProductController;
use App\Http\Controllers\ProductImagesController;
@ -27,6 +28,7 @@
->destroyable();
Route::apiResource('user.addresses', UserAddressController::class)->shallow();
Route::apiResource('users.orders', OrderController::class)->shallow();
});
Route::get('/categories', [ProductCategoryController::class, 'index']);
Route::apiResource('products', ProductController::class);