diff --git a/packages/api/src/ApiServiceProvider.php b/packages/api/src/ApiServiceProvider.php index 49c326749..f94cf3c37 100644 --- a/packages/api/src/ApiServiceProvider.php +++ b/packages/api/src/ApiServiceProvider.php @@ -17,7 +17,6 @@ use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Gate; use Illuminate\Support\ServiceProvider; -use Lunar\Base\CartSessionInterface; use Lunar\Facades\ModelManifest; class ApiServiceProvider extends ServiceProvider @@ -202,6 +201,14 @@ protected function setPaymentOptionsConfig(): void Config::set('lunar.cart.pipelines.cart', $cartPipelines); + Config::set( + 'lunar.cart.pipelines.cart_lines', + array_merge( + Config::get('lunar.cart.pipelines.cart_lines'), + [Domain\CartLines\Pipelines\GetUnitPriceExTax::class] + ) + ); + Config::set( 'lunar.cart.validators.set_payment_option', [Domain\Carts\Validation\PaymentOptionValidator::class], @@ -449,7 +456,7 @@ protected function bindModels(): void Domain\Carts\Contracts\CurrentSessionCart::class, function (Application $app): ?\Lunar\Models\Contracts\Cart { /** @var \Lunar\Managers\CartSessionManager $cartSession */ - $cartSession = $this->app->make(CartSessionInterface::class); + $cartSession = $this->app->make(\Lunar\Base\CartSessionInterface::class); return $cartSession->current(); } diff --git a/packages/api/src/Domain/CartLines/JsonApi/V1/CartLineResource.php b/packages/api/src/Domain/CartLines/JsonApi/V1/CartLineResource.php index 20ccc58e4..b135b10ff 100644 --- a/packages/api/src/Domain/CartLines/JsonApi/V1/CartLineResource.php +++ b/packages/api/src/Domain/CartLines/JsonApi/V1/CartLineResource.php @@ -5,6 +5,9 @@ use Dystore\Api\Domain\JsonApi\Resources\JsonApiResource; use Illuminate\Http\Request; +/** + * @param \Dystore\Api\Domain\CartLines\Models\CartLine $resource + */ class CartLineResource extends JsonApiResource { /** diff --git a/packages/api/src/Domain/CartLines/JsonApi/V1/CartLineSchema.php b/packages/api/src/Domain/CartLines/JsonApi/V1/CartLineSchema.php index ac3713e0b..06a4fea8c 100644 --- a/packages/api/src/Domain/CartLines/JsonApi/V1/CartLineSchema.php +++ b/packages/api/src/Domain/CartLines/JsonApi/V1/CartLineSchema.php @@ -2,10 +2,10 @@ namespace Dystore\Api\Domain\CartLines\JsonApi\V1; +use Dystore\Api\Domain\JsonApi\Eloquent\Fields\CartLinePricing; use Dystore\Api\Domain\JsonApi\Eloquent\Schema; use Dystore\Api\Support\Models\Actions\SchemaType; use LaravelJsonApi\Eloquent\Fields\ArrayHash; -use LaravelJsonApi\Eloquent\Fields\Map; use LaravelJsonApi\Eloquent\Fields\Number; use LaravelJsonApi\Eloquent\Fields\Relations\BelongsTo; use LaravelJsonApi\Eloquent\Fields\Relations\MorphTo; @@ -55,24 +55,13 @@ public function fields(): array $this->idField(), Number::make('purchasable_id'), - Str::make('purchasable_type'), - Map::make('prices', [ - Number::make('unit_price', 'unitPrice') - ->serializeUsing(static fn ($value) => $value?->decimal()), - Number::make('quantity', 'quantity'), - Number::make('sub_total', 'subTotal')->serializeUsing(static fn ($value) => $value?->decimal()), - Number::make('sub_total_discounted', 'subTotalDiscounted') - ->serializeUsing(static fn ($value) => $value?->decimal()), - Number::make('total', 'total') - ->serializeUsing(static fn ($value) => $value?->decimal()), - Number::make('tax_amount', 'taxAmount') - ->serializeUsing(static fn ($value) => $value?->decimal()), - Number::make('discount_total', 'discounTotal') - ->serializeUsing(static fn ($value) => $value?->decimal()), - ]), + Str::make('purchasable_type'), Number::make('quantity'), + + CartLinePricing::make('pricing'), + ArrayHash::make('meta'), BelongsTo::make('cart') diff --git a/packages/api/src/Domain/CartLines/Models/CartLine.php b/packages/api/src/Domain/CartLines/Models/CartLine.php index dbec64b7a..da14d8ad0 100644 --- a/packages/api/src/Domain/CartLines/Models/CartLine.php +++ b/packages/api/src/Domain/CartLines/Models/CartLine.php @@ -4,9 +4,24 @@ use Dystore\Api\Domain\CartLines\Concerns\InteractsWithDystoreApi; use Dystore\Api\Domain\CartLines\Contracts\CartLine as CartLineContract; +use Lunar\DataTypes\Price; use Lunar\Models\CartLine as LunarCartLine; +/** + * @property ?Price $unitPriceExTax + * @property ?Price $unitTax + */ class CartLine extends LunarCartLine implements CartLineContract { use InteractsWithDystoreApi; + + /** + * Unit price excluding tax. + */ + public ?Price $unitPriceExTax = null; + + /** + * Unit tax. + */ + public ?Price $unitTax = null; } diff --git a/packages/api/src/Domain/CartLines/Pipelines/GetUnitPriceExTax.php b/packages/api/src/Domain/CartLines/Pipelines/GetUnitPriceExTax.php new file mode 100644 index 000000000..aef29579a --- /dev/null +++ b/packages/api/src/Domain/CartLines/Pipelines/GetUnitPriceExTax.php @@ -0,0 +1,57 @@ +purchasable; + $cart = $cartLine->cart; + + if ($customer = $cart->customer) { + $customerGroups = $customer->customerGroups; + } else { + $customerGroups = $cart->user?->customers->pluck('customerGroups')->flatten(); + } + + $currency = Blink::once('currency_'.$cart->currency_id, function () use ($cart) { + return $cart->currency; + }); + + $priceResponse = Pricing::currency($currency) + ->qty($cartLine->quantity) + ->currency($cart->currency) + ->customerGroups($customerGroups) + ->for($purchasable) + ->get(); + + $cartLine->unitPriceExTax = new Price( + $priceResponse->matched->priceExTax()->value, + $cart->currency, + $purchasable->getUnitQuantity() + ); + + $cartLine->unitTax = new Price( + $cartLine->unitPriceInclTax->value - $cartLine->unitPriceExTax->value, + $cart->currency, + $purchasable->getUnitQuantity() + ); + + return $next($cartLine); + } +} diff --git a/packages/api/src/Domain/Carts/JsonApi/V1/CartSchema.php b/packages/api/src/Domain/Carts/JsonApi/V1/CartSchema.php index 1db1ceed3..ea8051d07 100644 --- a/packages/api/src/Domain/Carts/JsonApi/V1/CartSchema.php +++ b/packages/api/src/Domain/Carts/JsonApi/V1/CartSchema.php @@ -2,19 +2,16 @@ namespace Dystore\Api\Domain\Carts\JsonApi\V1; -use Dystore\Api\Domain\Discounts\Data\DiscountBreakdown; +use Dystore\Api\Domain\JsonApi\Eloquent\Fields\CartPricing; use Dystore\Api\Domain\JsonApi\Eloquent\Schema; use Dystore\Api\Support\Models\Actions\SchemaType; use LaravelJsonApi\Eloquent\Fields\ArrayHash; use LaravelJsonApi\Eloquent\Fields\Boolean; -use LaravelJsonApi\Eloquent\Fields\Map; -use LaravelJsonApi\Eloquent\Fields\Number; use LaravelJsonApi\Eloquent\Fields\Relations\BelongsTo; use LaravelJsonApi\Eloquent\Fields\Relations\HasMany; use LaravelJsonApi\Eloquent\Fields\Relations\HasOne; use LaravelJsonApi\Eloquent\Fields\Str; use LaravelJsonApi\Eloquent\Resources\Relation; -use Lunar\Base\ValueObjects\Cart\DiscountBreakdown as LunarDiscountBreakdown; use Lunar\Models\Contracts\Cart; use Lunar\Models\Contracts\CartAddress; use Lunar\Models\Contracts\CartLine; @@ -93,54 +90,17 @@ public function fields(): array return [ $this->idField(), - Map::make('prices', [ - Number::make('sub_total', 'subTotal') - ->serializeUsing(static fn ($value) => $value?->decimal), - - Number::make('sub_total_discounted', 'subTotalDiscounted') - ->serializeUsing(static fn ($value) => $value?->decimal), - - Number::make('total', 'total') - ->serializeUsing(static fn ($value) => $value?->decimal), - - Number::make('shipping_sub_total', 'shippingSubTotal') - ->serializeUsing(static fn ($value) => $value?->decimal), - - Number::make('shipping_total', 'shippingTotal') - ->serializeUsing(static fn ($value) => $value?->decimal), - - Number::make('payment_sub_total', 'paymentSubTotal') - ->serializeUsing(static fn ($value) => $value?->decimal), - - Number::make('payment_total', 'paymentTotal') - ->serializeUsing(static fn ($value) => $value?->decimal), - - Number::make('tax_total', 'taxTotal') - ->serializeUsing(static fn ($value) => $value?->decimal), - - Number::make('discount_total', 'discountTotal') - ->serializeUsing(static fn ($value) => $value?->decimal), - - ArrayHash::make('tax_breakdown', 'taxBreakdown') - ->serializeUsing(static fn ($value) => $value?->amounts), - - ArrayHash::make('discount_breakdown', 'discountBreakdown') - ->serializeUsing(static fn ($value) => $value?->map( - fn (LunarDiscountBreakdown $discountBreakdown) => (new DiscountBreakdown($discountBreakdown))->toArray(), - )), - ]), + CartPricing::make('pricing'), Str::make('coupon_code'), Str::make('payment_option'), - // NOTE: Attributes used for setting shipping options to current session cart - Str::make('shipping_option')->hidden(), + Str::make('shipping_option')->hidden(), // NOTE: Attributes used for setting shipping options to current session cart Str::make('address_type')->hidden(), - // NOTE: Attributes used for determining if user should be created during checkout - Boolean::make('create_user')->hidden(), + Boolean::make('create_user')->hidden(), // NOTE: Attributes used for determining if user should be created during checkout Boolean::make('agree')->hidden(), diff --git a/packages/api/src/Domain/JsonApi/Eloquent/Fields/CartLinePricing.php b/packages/api/src/Domain/JsonApi/Eloquent/Fields/CartLinePricing.php new file mode 100644 index 000000000..d50753ba6 --- /dev/null +++ b/packages/api/src/Domain/JsonApi/Eloquent/Fields/CartLinePricing.php @@ -0,0 +1,61 @@ +related ? $model->{$this->related} : $model; + $values = []; + + $fields = [ + Boolean::make('incl_tax')->extractUsing(fn () => prices_inc_tax()), + Price::make(fieldName: 'unit_price', price: $owner->unitPrice), + Price::make(fieldName: 'unit_price_incl_tax', price: $owner->unitPriceInclTax), + Price::make(fieldName: 'sub_total', price: $owner->subTotal), + Price::make(fieldName: 'sub_total_discounted', price: $owner->subTotalDiscounted), + Price::make(fieldName: 'total', price: $owner->total), + Price::make(fieldName: 'tax_total', price: $owner->taxAmount), + Price::make(fieldName: 'discount_total', price: $owner->discountTotal), + Number::make('quantity'), + Number::make('unit_quantity'), + ]; + + if ($owner) { + foreach ($fields as $attr) { + if ($attr instanceof SerializableContract) { + $values[$attr->serializedFieldName()] = $attr->serialize($owner); + } + } + } + + ksort($values); + + return $values ?: null; + } +} diff --git a/packages/api/src/Domain/JsonApi/Eloquent/Fields/CartPricing.php b/packages/api/src/Domain/JsonApi/Eloquent/Fields/CartPricing.php new file mode 100644 index 000000000..f85dcfe49 --- /dev/null +++ b/packages/api/src/Domain/JsonApi/Eloquent/Fields/CartPricing.php @@ -0,0 +1,77 @@ +related ? $model->{$this->related} : $model; + $values = []; + + $fields = [ + Boolean::make('incl_tax')->extractUsing(fn () => prices_inc_tax()), + Price::make(fieldName: 'shipping_sub_total', price: $owner->shippingSubTotal), + Price::make(fieldName: 'shipping_tax_total', price: $owner->shippingTaxTotal), + Price::make(fieldName: 'shipping_total', price: $owner->shippingTotal), + Price::make(fieldName: 'payment_sub_total', price: $owner->paymentSubTotal), + Price::make(fieldName: 'payment_tax_total', price: $owner->paymentTaxTotal), + Price::make(fieldName: 'payment_total', price: $owner->paymentTotal), + Price::make(fieldName: 'sub_total', price: $owner->subTotal), + Price::make(fieldName: 'sub_total_discounted', price: $owner->subTotalDiscounted), + Price::make(fieldName: 'total', price: $owner->total), + Price::make(fieldName: 'tax_total', price: $owner->taxTotal), + Price::make(fieldName: 'discount_total', price: $owner->discountTotal), + + ArrayHash::make('tax_breakdown', 'taxBreakdown') + ->serializeUsing( + static fn ($value) => $value?->amounts + ), + + ArrayHash::make('discount_breakdown', 'discountBreakdown') + ->serializeUsing( + static fn ($value) => $value?->map( + fn (LunarDiscountBreakdown $discountBreakdown) => (new DiscountBreakdown($discountBreakdown))->toArray(), + ) + ), + ]; + + if ($owner) { + foreach ($fields as $attr) { + if ($attr instanceof SerializableContract) { + $values[$attr->serializedFieldName()] = $attr->serialize($owner); + } + } + } + + ksort($values); + + return $values ?: null; + } +} diff --git a/packages/api/src/Domain/JsonApi/Eloquent/Fields/OrderLinePricing.php b/packages/api/src/Domain/JsonApi/Eloquent/Fields/OrderLinePricing.php new file mode 100644 index 000000000..89e77e673 --- /dev/null +++ b/packages/api/src/Domain/JsonApi/Eloquent/Fields/OrderLinePricing.php @@ -0,0 +1,65 @@ +related ? $model->{$this->related} : $model; + $values = []; + + $subTotalDiscounted = new PriceData( + value: $owner->sub_total->value - $owner->discount_total->value, + currency: $owner->sub_total->currency + ); + + $fields = [ + Boolean::make('incl_tax')->extractUsing(fn () => prices_inc_tax()), + Price::make(fieldName: 'unit_price', price: $owner->unit_price), + Price::make(fieldName: 'sub_total', price: $owner->sub_total), + Price::make(fieldName: 'sub_total_discounted', price: $subTotalDiscounted), + Price::make(fieldName: 'total', price: $owner->total), + Price::make(fieldName: 'tax_total', price: $owner->tax_total), + Price::make(fieldName: 'discount_total', price: $owner->discount_total), + Number::make('quantity'), + ]; + + if ($owner) { + foreach ($fields as $attr) { + if ($attr instanceof SerializableContract) { + $values[$attr->serializedFieldName()] = $attr->serialize($owner); + } + } + } + + ksort($values); + + return $values ?: null; + } +} diff --git a/packages/api/src/Domain/JsonApi/Eloquent/Fields/OrderPricing.php b/packages/api/src/Domain/JsonApi/Eloquent/Fields/OrderPricing.php new file mode 100644 index 000000000..e4468ab0c --- /dev/null +++ b/packages/api/src/Domain/JsonApi/Eloquent/Fields/OrderPricing.php @@ -0,0 +1,65 @@ +related ? $model->{$this->related} : $model; + $values = []; + + $fields = [ + Boolean::make('incl_tax')->extractUsing(fn () => prices_inc_tax()), + Price::make(fieldName: 'shipping_total', price: $owner->shipping_total), + Price::make(fieldName: 'payment_total', price: $owner->payment_total), + Price::make(fieldName: 'tax_total', price: $owner->tax_total), + Price::make(fieldName: 'sub_total', price: $owner->sub_total), + Price::make(fieldName: 'discount_total', price: $owner->discount_total), + Price::make(fieldName: 'total', price: $owner->total), + + ArrayHash::make('tax_breakdown', 'taxBreakdown')->serializeUsing(static fn ($value) => $value?->amounts), + ArrayHash::make('shipping_breakdown')->serializeUsing(static fn ($value) => $value?->items), + ArrayHash::make('payment_breakdown')->serializeUsing(static fn ($value) => $value?->items), + ArrayHash::make('discount_breakdown', 'discountBreakdown')->serializeUsing(static fn ($value) => $value), + Number::make('exchange_rate'), + ]; + + if ($owner) { + foreach ($fields as $attr) { + if ($attr instanceof SerializableContract) { + $values[$attr->serializedFieldName()] = $attr->serialize($owner); + } + } + } + + ksort($values); + + return $values ?: null; + } +} diff --git a/packages/api/src/Domain/JsonApi/Eloquent/Fields/Price.php b/packages/api/src/Domain/JsonApi/Eloquent/Fields/Price.php new file mode 100644 index 000000000..b71421c5a --- /dev/null +++ b/packages/api/src/Domain/JsonApi/Eloquent/Fields/Price.php @@ -0,0 +1,100 @@ +extractor = static function (Model $model, string $column, ?PriceData $price): array { + return [ + 'value' => $price?->value, + 'decimal' => $price?->unitDecimal(), + 'formatted' => $price?->unitFormatted(), + ]; + }; + } + + public static function make( + string $fieldName, + ?string $column = null, + ?PriceData $price = null + ): static { + return new static($fieldName, $column, $price); + } + + /** + * {@inheritDoc} + */ + public function serialize(object $model): array + { + $column = $this->column(); + $owner = $this->related ? $model->{$this->related} : $model; + $value = $this->price ?? $owner?->{$column} ?? null; + + if ($this->serializer) { + $value = ($this->serializer)($value); + } + + if ($this->extractor) { + return ($this->extractor)($model, $column, $value); + } + + return $value; + } + + /** + * {@inheritDoc} + */ + protected function deserialize($value): ?array + { + $value = parent::deserialize($value); + + if (is_null($value)) { + return null; + } + + if (is_null($value)) { + return null; + } + + return Hash::cast($value)->all(); + } + + /** + * {@inheritDoc} + */ + protected function assertValue($value): void + { + if (! $value instanceof PriceData) { + throw new UnexpectedValueException(sprintf( + 'Expecting the value of attribute %s to be of Lunar\DataTypes\Price type.', + $this->name() + )); + } + } +} diff --git a/packages/api/src/Domain/OrderLines/JsonApi/V1/OrderLineSchema.php b/packages/api/src/Domain/OrderLines/JsonApi/V1/OrderLineSchema.php index 0724ec859..4bbe45ac7 100644 --- a/packages/api/src/Domain/OrderLines/JsonApi/V1/OrderLineSchema.php +++ b/packages/api/src/Domain/OrderLines/JsonApi/V1/OrderLineSchema.php @@ -2,11 +2,11 @@ namespace Dystore\Api\Domain\OrderLines\JsonApi\V1; +use Dystore\Api\Domain\JsonApi\Eloquent\Fields\OrderLinePricing; use Dystore\Api\Domain\JsonApi\Eloquent\Schema; use Dystore\Api\Domain\ShippingOptions\Entities\ShippingOption; use Dystore\Api\Support\Models\Actions\SchemaType; use LaravelJsonApi\Eloquent\Fields\ArrayHash; -use LaravelJsonApi\Eloquent\Fields\Map; use LaravelJsonApi\Eloquent\Fields\Number; use LaravelJsonApi\Eloquent\Fields\Relations\BelongsTo; use LaravelJsonApi\Eloquent\Fields\Relations\MorphTo; @@ -68,22 +68,7 @@ public function fields(): array Str::make('identifier'), Str::make('notes'), - Map::make('prices', [ - Number::make('unit_price', 'unit_price') - ->serializeUsing(static fn ($value) => $value?->decimal()), - Number::make('unit_quantity', 'unit_quantity'), - Number::make('quantity', 'quantity'), - Number::make('sub_total', 'sub_total') - ->serializeUsing(static fn ($value) => $value?->decimal()), - Number::make('total', 'total') - ->serializeUsing(static fn ($value) => $value?->decimal()), - Number::make('tax_total', 'tax_total') - ->serializeUsing(static fn ($value) => $value?->decimal()), - Number::make('discount_total', 'discount_total') - ->serializeUsing(static fn ($value) => $value?->decimal()), - ArrayHash::make('tax_breakdown', 'tax_breakdown') - ->serializeUsing(static fn ($value) => $value?->amounts), - ]), + OrderLinePricing::make('pricing'), ArrayHash::make('meta'), diff --git a/packages/api/src/Domain/Orders/JsonApi/V1/OrderSchema.php b/packages/api/src/Domain/Orders/JsonApi/V1/OrderSchema.php index 5890f7abb..cb28f1a0d 100644 --- a/packages/api/src/Domain/Orders/JsonApi/V1/OrderSchema.php +++ b/packages/api/src/Domain/Orders/JsonApi/V1/OrderSchema.php @@ -2,13 +2,12 @@ namespace Dystore\Api\Domain\Orders\JsonApi\V1; +use Dystore\Api\Domain\JsonApi\Eloquent\Fields\OrderPricing; use Dystore\Api\Domain\JsonApi\Eloquent\Schema; use Dystore\Api\Support\Models\Actions\SchemaType; use LaravelJsonApi\Eloquent\Fields\ArrayHash; use LaravelJsonApi\Eloquent\Fields\Boolean; use LaravelJsonApi\Eloquent\Fields\DateTime; -use LaravelJsonApi\Eloquent\Fields\Map; -use LaravelJsonApi\Eloquent\Fields\Number; use LaravelJsonApi\Eloquent\Fields\Relations\BelongsTo; use LaravelJsonApi\Eloquent\Fields\Relations\HasMany; use LaravelJsonApi\Eloquent\Fields\Relations\HasOne; @@ -135,49 +134,9 @@ public function fields(): array Str::make('notes'), Str::make('currency_code'), Str::make('compare_currency_code'), - Map::make('prices', [ - Number::make('sub_total') - ->serializeUsing( - static fn ($value) => $value?->decimal, - ), - Number::make('total', 'total') - ->serializeUsing( - static fn ($value) => $value?->decimal, - ), - Number::make('tax_total', 'tax_total') - ->serializeUsing( - static fn ($value) => $value?->decimal, - ), - Number::make('discount_total', 'discount_total') - ->serializeUsing( - static fn ($value) => $value?->decimal, - ), - Number::make('shipping_total', 'shipping_total') - ->serializeUsing( - static fn ($value) => $value?->decimal, - ), - Number::make('payment_total', 'payment_total') - ->serializeUsing( - static fn ($value) => $value?->decimal, - ), - ArrayHash::make('tax_breakdown', 'taxBreakdown') - ->serializeUsing( - static fn ($value) => $value?->amounts, - ), - ArrayHash::make('shipping_breakdown') - ->serializeUsing( - static fn ($value) => $value?->items, - ), - ArrayHash::make('payment_breakdown') - ->serializeUsing( - static fn ($value) => $value?->items, - ), - ArrayHash::make('discount_breakdown', 'discountBreakdown') - ->serializeUsing( - static fn ($value) => $value, - ), - Number::make('exchange_rate'), - ]), + + OrderPricing::make('pricing'), + DateTime::make('placed_at') ->sortable(), diff --git a/packages/api/src/Domain/Products/JsonApi/V1/ProductResource.php b/packages/api/src/Domain/Products/JsonApi/V1/ProductResource.php index 357cc8cbb..ff1926982 100644 --- a/packages/api/src/Domain/Products/JsonApi/V1/ProductResource.php +++ b/packages/api/src/Domain/Products/JsonApi/V1/ProductResource.php @@ -3,11 +3,16 @@ namespace Dystore\Api\Domain\Products\JsonApi\V1; use Dystore\Api\Domain\JsonApi\Resources\JsonApiResource; -use Dystore\Api\Domain\Products\Models\Product; use Dystore\Api\Domain\ProductVariants\Models\ProductVariant; use Illuminate\Http\Request; +use Lunar\Facades\CartSession; +use Lunar\Facades\Pricing; +use Lunar\Facades\StorefrontSession; use Lunar\Models\Contracts\ProductVariant as ProductVariantContract; +/** + * @param \Dystore\Api\Domain\Products\Models\Product $resource + */ class ProductResource extends JsonApiResource { /** @@ -17,9 +22,19 @@ class ProductResource extends JsonApiResource */ public function attributes($request): iterable { - /** @var Product $model */ $model = $this->resource; + // $variant = $this->variants->firstWhere('id', 2099); + + // ray(CartSession::current()->lines->first()->total); + + // $pricing = Pricing::for($variant) + // ->currency(StorefrontSession::getCurrency()) + // ->customerGroups(StorefrontSession::getCustomerGroups()) + // ->get(); + // + // ray($pricing); + if ($model->relationLoaded('variants')) { /** @var ProductVariant $variant */ $model->variants->each( diff --git a/tests/api/Feature/Domain/Orders/JsonApi/V1/OrderOrderLinesRelationshipTest.php b/tests/api/Feature/Domain/Orders/JsonApi/V1/OrderOrderLinesRelationshipTest.php index 3df91a54c..548c49fb5 100644 --- a/tests/api/Feature/Domain/Orders/JsonApi/V1/OrderOrderLinesRelationshipTest.php +++ b/tests/api/Feature/Domain/Orders/JsonApi/V1/OrderOrderLinesRelationshipTest.php @@ -3,17 +3,18 @@ use Dystore\Api\Domain\Carts\Models\Cart; use Dystore\Api\Domain\Customers\Models\Customer; use Dystore\Api\Domain\OrderLines\Models\OrderLine; -use Dystore\Api\Domain\Orders\Models\Order; use Dystore\Api\Domain\Users\Models\User; use Dystore\Tests\Api\TestCase; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Support\Facades\App; +use Illuminate\Support\Facades\Config; use Lunar\Base\CartSessionInterface; uses(TestCase::class, RefreshDatabase::class) ->group('orders', 'order_lines'); beforeEach(function () { + Config::set('lunar.pricing.stored_inclusive_of_tax', true); /** @var TestCase $this */ $this->user = User::factory() ->has(Customer::factory()) @@ -22,7 +23,7 @@ $this->cart = Cart::factory() ->for($this->user) ->withAddresses() - ->withLines(2) + ->withLines() ->create(); /** @property CartSessionManager $cartSession */ @@ -33,24 +34,9 @@ it('can list related product lines', function () { /** @var TestCase $this */ - $response = $this - ->jsonApi() - ->expects('orders') - ->withData([ - 'type' => 'carts', - 'attributes' => [ - 'agree' => true, - 'create_user' => false, - ], - ]) - ->post(serverUrl('/carts/-actions/checkout')); - - $signedUrl = $response->json('data.links')['self.signed']; - - $order = Order::query() - ->where('cart_id', $this->cart->getKey()) - ->with(['lines']) - ->first(); + $order = $this->cart->createOrder(); + + $order->load(['lines']); $expected = $order->productLines->map(fn (OrderLine $line) => [ 'id' => (string) $line->getRouteKey(), @@ -73,6 +59,22 @@ ->assertFetchedMany($expected); }); +it('returns correct product line pricing', function () { + /** @var TestCase $this */ + $order = $this->cart->createOrder(); + + $response = $this + ->actingAs($this->user) + ->jsonApi() + ->expects('orders') + ->get(serverUrl("/orders/{$order->getRouteKey()}/product_lines")); + + $response + ->assertSuccessful(); + + ray($response->json('data')[0]['attributes']['pricing']); +}); + it('cannot list order lines relationships without url signature', function () { /** @var TestCase $this */ $order = $this->cart->createOrder(); diff --git a/tests/api/Feature/Domain/Orders/JsonApi/V1/ReadOrderTest.php b/tests/api/Feature/Domain/Orders/JsonApi/V1/ReadOrderTest.php index 3abbbaa6c..0c1ec4408 100644 --- a/tests/api/Feature/Domain/Orders/JsonApi/V1/ReadOrderTest.php +++ b/tests/api/Feature/Domain/Orders/JsonApi/V1/ReadOrderTest.php @@ -1,81 +1,69 @@ group('orders'); -it('can read order details without signature when user is logged in and owns the order', function () { +beforeEach(function () { /** @var TestCase $this */ + $this->user = User::factory() + ->has(Customer::factory()) + ->create(); - /** @var User $user */ - $user = User::factory()->create(); - - /** @var CartFactory $factory */ - $factory = Cart::factory(); - - /** @var Cart $cart */ - $cart = $factory + $this->cart = Cart::factory() + ->for($this->user) ->withAddresses() - ->withLines() - ->for($user) + ->withLines(2) ->create(); - CartSession::use($cart); + /** @property CartSessionManager $cartSession */ + $this->cartSession = App::make(CartSessionInterface::class); + + $this->cartSession->use($this->cart); +}); - $order = $cart->createOrder(); +it('can show order details without signature when user is logged in and owns the order', function () { + /** @var TestCase $this */ + $order = $this->cart->createOrder(); $order = Order::query() ->where($order->getKeyName(), $order->getKey()) ->first(); $response = $this - ->actingAs($user) + ->actingAs($this->user) ->jsonApi() ->includePaths( 'product_lines.purchasable.product', - 'product_lines.purchasable.prices', + 'product_lines.purchasable.price', 'product_lines.purchasable.images', 'product_lines.currency', 'customer', 'order_addresses', ) ->expects('orders') - ->get('/api/v1/orders/'.$order->getRouteKey()); + ->get(serverUrl('/orders/'.$order->getRouteKey())); $response + ->assertSuccessful() ->assertFetchedOne($order) ->assertIsIncluded('order_lines', $order->lines->first()); - }); -it('can read order details when accessing order with valid signature', function () { +it('can show order details when accessing order with valid signature', function () { /** @var TestCase $this */ Config::set('dystore.general.checkout.checkout_protection_strategy', CheckoutProtectionStrategy::SIGNATURE); - /** @var User $user */ - $user = User::factory()->create(); - - /** @var CartFactory $factory */ - $factory = Cart::factory(); - - /** @var Cart $cart */ - $cart = $factory - ->withAddresses() - ->withLines() - ->for($user) - ->create(); - - CartSession::use($cart); - $response = $this ->jsonApi() ->expects('orders') @@ -91,7 +79,7 @@ $signedUrl = $response->json('data.links')['self.signed']; $order = Order::query() - ->where('cart_id', $cart->getKey()) + ->where('cart_id', $this->cart->getKey()) ->first(); $response = $this @@ -119,18 +107,30 @@ ]); }); -it('returns unauthorized if the user does not own the order', function () { +it('can show order pricing correctly', function () { /** @var TestCase $this */ + $order = $this->cart->createOrder(); - /** @var CartFactory $factory */ - $factory = Cart::factory(); + $order = Order::query() + ->where($order->getKeyName(), $order->getKey()) + ->first(); - /** @var Cart $cart */ - $cart = $factory->withAddresses() - ->withLines() - ->create(); + $response = $this + ->actingAs($this->user) + ->jsonApi() + ->expects('orders') + ->get(serverUrl('/orders/'.$order->getRouteKey())); - $order = $cart->createOrder(); + ray($response->json('data.attributes.prices.sub_total')); + + $response + ->assertSuccessful() + ->assertFetchedOne($order); +}); + +it('returns unauthorized if the user does not own the order', function () { + /** @var TestCase $this */ + $order = $this->cart->createOrder(); $order = Order::query() ->where($order->getKeyName(), $order->getKey())