feature: order create endpoint
This commit is contained in:
parent
a0e5cda432
commit
d065ef1db9
@ -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',
|
||||
|
||||
234
backend/_ide_helper_models.php
Normal file
234
backend/_ide_helper_models.php
Normal 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 {}
|
||||
}
|
||||
|
||||
55
backend/app/Actions/CreateOrderAction.php
Normal file
55
backend/app/Actions/CreateOrderAction.php
Normal 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);
|
||||
}
|
||||
}
|
||||
33
backend/app/Data/OrderRequestDTO.php
Normal file
33
backend/app/Data/OrderRequestDTO.php
Normal 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,
|
||||
);
|
||||
}
|
||||
}
|
||||
30
backend/app/Data/OrderResponeDTO.php
Normal file
30
backend/app/Data/OrderResponeDTO.php
Normal 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
|
||||
);
|
||||
}
|
||||
}
|
||||
15
backend/app/Enums/OrderStatus.php
Normal file
15
backend/app/Enums/OrderStatus.php
Normal 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';
|
||||
}
|
||||
30
backend/app/Exceptions/StaleCartException.php
Normal file
30
backend/app/Exceptions/StaleCartException.php
Normal 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);
|
||||
}
|
||||
}
|
||||
53
backend/app/Http/Controllers/OrderController.php
Normal file
53
backend/app/Http/Controllers/OrderController.php
Normal 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)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
30
backend/app/Http/Requests/StoreOrderRequest.php
Normal file
30
backend/app/Http/Requests/StoreOrderRequest.php
Normal 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',
|
||||
];
|
||||
}
|
||||
}
|
||||
29
backend/app/Http/Requests/UpdateOrderRequest.php
Normal file
29
backend/app/Http/Requests/UpdateOrderRequest.php
Normal 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 [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -12,6 +12,7 @@
|
||||
class AddressResource extends JsonResource
|
||||
{
|
||||
public static $wrap = null;
|
||||
|
||||
/**
|
||||
* Transform the resource into an array.
|
||||
*
|
||||
|
||||
19
backend/app/Http/Resources/OrderResource.php
Normal file
19
backend/app/Http/Resources/OrderResource.php
Normal 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);
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
{
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
28
backend/app/Models/Order.php
Normal file
28
backend/app/Models/Order.php
Normal 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);
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
{
|
||||
|
||||
@ -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
|
||||
{
|
||||
|
||||
@ -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
|
||||
{
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
2
backend/composer.lock
generated
@ -9716,5 +9716,5 @@
|
||||
"php": "^8.2"
|
||||
},
|
||||
"platform-dev": {},
|
||||
"plugin-api-version": "2.6.0"
|
||||
"plugin-api-version": "2.9.0"
|
||||
}
|
||||
|
||||
@ -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');
|
||||
}
|
||||
};
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user