Skip to content

Commit

Permalink
feat: add test
Browse files Browse the repository at this point in the history
  • Loading branch information
kaioken committed Sep 18, 2024
1 parent 9ab100d commit 7cb2d27
Show file tree
Hide file tree
Showing 9 changed files with 344 additions and 28 deletions.
48 changes: 23 additions & 25 deletions app/GraphQL/Souk/Mutations/Orders/DraftOrderManagementMutation.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,35 @@
namespace App\GraphQL\Souk\Mutations\Orders;

use Kanvas\Apps\Models\Apps;
use Kanvas\Guild\Customers\Enums\ContactTypeEnum;
use Kanvas\Inventory\Variants\Models\Variants;
use Kanvas\Social\Interactions\Actions\CreateInteraction;
use Kanvas\Social\Interactions\Actions\CreateUserInteractionAction;
use Kanvas\Social\Interactions\DataTransferObject\Interaction;
use Kanvas\Social\Interactions\DataTransferObject\UserInteraction;
use Kanvas\Souk\Orders\DataTransferObject\DirectOrder;
use Kanvas\Souk\Payments\DataTransferObject\CreditCard;
use Kanvas\Souk\Payments\Providers\AuthorizeNetPaymentProcessor;
use Kanvas\Companies\Models\CompaniesBranches;
use Kanvas\Exceptions\ValidationException;
use Kanvas\Inventory\Regions\Models\Regions;
use Kanvas\Souk\Orders\Actions\CreateDraftOrderAction;
use Kanvas\Souk\Orders\DataTransferObject\DraftOrder;
use Kanvas\Souk\Orders\Models\Order;

class DraftOrderManagementMutation
{
public function create(mixed $root, array $request): array
public function create(mixed $root, array $request): Order
{
$user = auth()->user();
$app = app(Apps::class);
$branch = app(CompaniesBranches::class);

print_R($request);
$customer = $request['input']['customer'];
$customer['contacts'] = [
[
'contact' => $request['input']['email'],
'contacts_types_id' => ContactTypeEnum::EMAIL->value,
'weight' => 0
]
];

print_r($customer); die();


return [];
}
if ($branch->id === null) {
throw new ValidationException('Missing Location Header');
}

$region = Regions::getByIdFromCompanyApp($request['input']['region_id'], $branch->company, $app);

$draftOrder = DraftOrder::viaRequest(
$app,
$branch,
$user,
$region,
$request
);

return (new CreateDraftOrderAction($draftOrder))->execute();
}
}
8 changes: 5 additions & 3 deletions graphql/schemas/Souk/order.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,11 @@ input OrderInput {

input DraftOrderInput {
email: String!
phone: String
customer: PeopleInput!
billing: CreditCardBillingInput
address: AddressInput
region_id: ID!
billing_address: CreditCardBillingInput
shipping_address: AddressInput
items: [OrderLineItemInput!]!
note: String
metadata: Mixed
Expand All @@ -119,7 +121,7 @@ extend type Mutation @guard {
@field(
resolver: "App\\GraphQL\\Souk\\Mutations\\Orders\\OrderManagementMutation@create"
)
createDraftOrder(input: DraftOrderInput!): Mixed!
createDraftOrder(input: DraftOrderInput!): Order!
@field(
resolver: "App\\GraphQL\\Souk\\Mutations\\Orders\\DraftOrderManagementMutation@create"
)
Expand Down
5 changes: 5 additions & 0 deletions src/Domains/Inventory/Regions/Models/Regions.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ public function currencies(): BelongsTo
return $this->belongsTo(Currencies::class, 'currency_id');
}

public function currency(): BelongsTo
{
return $this->belongsTo(Currencies::class, 'currency_id');
}

public function warehouses(): HasMany
{
return $this->hasMany(Warehouses::class, 'regions_id');
Expand Down
50 changes: 50 additions & 0 deletions src/Domains/Souk/Orders/Actions/CreateDraftOrderAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace Kanvas\Souk\Orders\Actions;

use Illuminate\Support\Facades\DB;
use Kanvas\Souk\Orders\DataTransferObject\DraftOrder;
use Kanvas\Souk\Orders\Models\Order as ModelsOrder;

class CreateDraftOrderAction
{
public function __construct(
protected DraftOrder $orderData
) {
}

public function execute(): ModelsOrder
{
return DB::connection('commerce')->transaction(function () {
$order = new ModelsOrder();
$order->apps_id = $this->orderData->app->getId();
$order->region_id = $this->orderData->region->getId();
$order->companies_id = $this->orderData->branch->company->getId();
$order->people_id = $this->orderData->people->getId();
$order->users_id = $this->orderData->user->getId();
$order->user_email = $this->orderData->email;
$order->user_phone = $this->orderData->phone;
$order->token = null;
$order->shipping_address_id = $this->orderData?->shippingAddress?->getId() ?? null;
$order->billing_address_id = $this->orderData?->billingAddress?->getId() ?? null;
$order->total_gross_amount = $this->orderData->total;
$order->total_net_amount = $this->orderData->total - $this->orderData->taxes;
$order->shipping_price_gross_amount = $this->orderData->totalShipping;
$order->shipping_price_net_amount = $this->orderData->totalShipping;
$order->discount_amount = $this->orderData->totalDiscount;
$order->status = $this->orderData->status;
$order->fulfillment_status = 'pending';
$order->currency = $this->orderData->currency->code;
$order->metadata = $this->orderData->metadata;
$order->payment_gateway_names = $this->orderData->paymentGatewayName;
//$order->language_code = $this->orderData->languageCode;
$order->saveOrFail();

$order->addItems($this->orderData->items);

return $order;
});
}
}
139 changes: 139 additions & 0 deletions src/Domains/Souk/Orders/DataTransferObject/DraftOrder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<?php

declare(strict_types=1);

namespace Kanvas\Souk\Orders\DataTransferObject;

use Baka\Contracts\AppInterface;
use Baka\Users\Contracts\UserInterface;
use Kanvas\Apps\Models\Apps;
use Kanvas\Companies\Models\CompaniesBranches;
use Kanvas\Currencies\Models\Currencies;
use Kanvas\Guild\Customers\Actions\CreatePeopleAction;
use Kanvas\Guild\Customers\DataTransferObject\Address;
use Kanvas\Guild\Customers\DataTransferObject\Contact;
use Kanvas\Guild\Customers\DataTransferObject\People;
use Kanvas\Guild\Customers\Enums\ContactTypeEnum;
use Kanvas\Guild\Customers\Models\Address as ModelsAddress;
use Kanvas\Guild\Customers\Models\People as ModelsPeople;
use Kanvas\Inventory\Regions\Models\Regions;
use Kanvas\Users\Models\Users;
use Spatie\LaravelData\Attributes\DataCollectionOf;
use Spatie\LaravelData\Data;
use Spatie\LaravelData\DataCollection;

class DraftOrder extends Data
{
public function __construct(
public readonly Apps $app,
public readonly CompaniesBranches $branch,
public readonly Regions $region,
public readonly Users $user,
public readonly string $email,
public readonly ModelsPeople $people,
public readonly float $total,
public readonly float $taxes,
public readonly float $totalDiscount,
public readonly float $totalShipping,
public readonly string $status, //enums
public readonly Currencies $currency,
#[DataCollectionOf(OrderItem::class)]
public readonly DataCollection $items,
public readonly array $paymentGatewayName = [],
public readonly ?ModelsAddress $billingAddress = null,
public readonly ?ModelsAddress $shippingAddress = null,
public readonly ?string $phone = null,
public readonly ?string $notes = null,
public readonly ?string $metadata = null,
) {
}

public static function viaRequest(AppInterface $app, CompaniesBranches $branch, UserInterface $user, Regions $region, array $request): self
{
$customer = $request['input']['customer'];
$customer['contacts'] = [
[
'value' => $request['input']['email'],
'contacts_types_id' => ContactTypeEnum::EMAIL->value,
'weight' => 0,
],
];

$people = People::from([
'app' => $app,
'branch' => $branch,
'user' => $user,
'firstname' => $customer['firstname'],
'middlename' => $customer['middlename'] ?? null,
'lastname' => $customer['lastname'] ?? null,
'contacts' => Contact::collect($customer['contacts'] ?? [], DataCollection::class),
'address' => Address::collect([], DataCollection::class),
'id' => $data['id'] ?? 0,
'dob' => $data['dob'] ?? null,
'facebook_contact_id' => $data['facebook_contact_id'] ?? null,
'google_contact_id' => $data['google_contact_id'] ?? null,
'apple_contact_id' => $data['apple_contact_id'] ?? null,
'linkedin_contact_id' => $data['linkedin_contact_id'] ?? null,
'tags' => $data['tags'] ?? [],
'custom_fields' => $data['custom_fields'] ?? [],
]);

$people = (new CreatePeopleAction($people))->execute();

$shippingAddress = ! empty($request['input']['shipping_address']['address1']) ?
$customer->addAddress(new Address(
address: $request['input']['shipping_address']['address1'] ?? '',
address_2: $request['input']['shipping_address']['address2'] ?? '',
city: $request['input']['shipping_address']['city'] ?? '',
state: $request['input']['shipping_address']['province'] ?? '',
country: $request['input']['shipping_address']['country'] ?? '',
zipcode: $request['input']['shipping_address']['zip'] ?? ''
))
: null;

$billingAddress = ! empty($request['input']['billing_address']['address1']) ?
$customer->addAddress(new Address(
address: $request['input']['billing_address']['address1'],
address_2: $request['input']['billing_address']['address2'],
city: $request['input']['billing_address']['city'],
state: $request['input']['billing_address']['province'],
country: $request['input']['billing_address']['country'],
zipcode: $request['input']['billing_address']['zip']
))
: null;

$total = 0;
$totalTax = 0;
$totalDiscount = 0;
$totalShipping = 0;
$lineItems = [];
foreach ($request['input']['items'] as $key => $lineItem) {
$lineItems[$key] = OrderItem::viaRequest($app, $branch->company, $region, $lineItem);
$total += $lineItems[$key]->getTotal();
$totalTax = $lineItems[$key]->getTotalTax();
$totalDiscount = $lineItems[$key]->getTotalDiscount();
}

return new self(
$app,
$branch,
$region,
$user,
$request['input']['email'],
$people,
$total,
$totalTax,
$totalDiscount,
$totalShipping,
'draft',
$region->currency,
OrderItem::collect($lineItems, DataCollection::class),
['manual'],
$shippingAddress,
$billingAddress,
$request['input']['phone'] ?? null,
$request['input']['notes'] ?? null,
$request['input']['metadata'] ?? null,
);
}
}
38 changes: 38 additions & 0 deletions src/Domains/Souk/Orders/DataTransferObject/OrderItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@

namespace Kanvas\Souk\Orders\DataTransferObject;

use Baka\Contracts\AppInterface;
use Baka\Contracts\CompanyInterface;
use Kanvas\Apps\Models\Apps;
use Kanvas\Currencies\Models\Currencies;
use Kanvas\Inventory\Regions\Models\Regions;
use Kanvas\Inventory\Variants\Models\Variants;
use Spatie\LaravelData\Data;

Expand All @@ -24,4 +27,39 @@ public function __construct(
public readonly int $quantityShipped = 0,
) {
}

public static function viaRequest(AppInterface $app, CompanyInterface $company, Regions $region, array $request): self
{
$variant = Variants::getByIdFromCompanyApp($request['variant_id'], $company, $app);
$warehouse = $region->warehouses()->firstOrFail(); //@todo get product warehouse with stock
$price = $variant->getPrice($warehouse);

return new self(
app: $app,
variant: $variant,
name: $variant->name,
sku: $variant->sku,
quantity: $request['quantity'],
price: $price,
tax: 0, //@todo get from region
discount: 0,
currency: $region->currency,
quantityShipped: $request['quantity_shipped'] ?? 0
);
}

public function getTotal(): float
{
return $this->price * $this->quantity;
}

public function getTotalDiscount(): float
{
return $this->discount * $this->quantity;
}

public function getTotalTax(): float
{
return $this->tax * $this->quantity;
}
}
18 changes: 18 additions & 0 deletions src/Domains/Souk/Orders/Models/Order.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Baka\Casts\Json;
use Baka\Traits\UuidTrait;
use Baka\Users\Contracts\UserInterface;
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
Expand All @@ -15,6 +16,7 @@
use Kanvas\Inventory\Regions\Models\Regions;
use Kanvas\Souk\Models\BaseModel;
use Kanvas\Souk\Orders\DataTransferObject\OrderItem as OrderItemDto;
use Kanvas\Souk\Orders\Observers\OrderObserver;
use Kanvas\Users\Models\Users;
use Kanvas\Workflow\Traits\CanUseWorkflow;
use Laravel\Scout\Searchable;
Expand Down Expand Up @@ -65,6 +67,7 @@
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
*/
#[ObservedBy(OrderObserver::class)]
class Order extends BaseModel
{
use UuidTrait;
Expand Down Expand Up @@ -172,4 +175,19 @@ public function cancel(): void
$this->status = 'cancelled';
$this->saveOrFail();
}

public function generateOrderNumber(): int
{
// Lock the orders table while retrieving the last order
$lastOrder = Order::where('companies_id', $this->companies_id)
->where('apps_id', $this->apps_id)
->lockForUpdate() // Ensure no race conditions
->latest('id')
->first();

$lastOrderNumber = $lastOrder ? intval($lastOrder->order_number) : 0;
$newOrderNumber = $lastOrderNumber + 1;

return $newOrderNumber;
}
}
15 changes: 15 additions & 0 deletions src/Domains/Souk/Orders/Observers/OrderObserver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Kanvas\Souk\Orders\Observers;

use Kanvas\Souk\Orders\Models\Order;

class OrderObserver
{
public function creating(Order $order)
{
$order->order_number = $order->generateOrderNumber();
}
}
Loading

0 comments on commit 7cb2d27

Please sign in to comment.