diff --git a/app/Http/Requests/SchemaUpdateRequest.php b/app/Http/Requests/SchemaUpdateRequest.php index de6433e81..021ce3eef 100644 --- a/app/Http/Requests/SchemaUpdateRequest.php +++ b/app/Http/Requests/SchemaUpdateRequest.php @@ -27,7 +27,7 @@ public function rules(): array 'hidden' => ['nullable', 'boolean', 'declined_if:required,yes,on,1,true'], 'required' => ['nullable', 'boolean'], - 'default' => ['nullable', 'required_if:required,true', 'integer', 'min:0', 'max:' . count($this->options ?? [])], + 'default' => ['nullable', 'required_if:required,true', 'integer', 'min:0'], 'options' => ['nullable', 'array'], 'options.*.translations' => ['sometimes', new Translations(['name'])], diff --git a/app/Rules/UnlimitedShippingDate.php b/app/Rules/UnlimitedShippingDate.php index 894d92f4e..5f7f4e79a 100644 --- a/app/Rules/UnlimitedShippingDate.php +++ b/app/Rules/UnlimitedShippingDate.php @@ -4,9 +4,9 @@ use App\Models\Item; use App\Services\Contracts\DepositServiceContract; -use Carbon\Carbon; use Illuminate\Contracts\Validation\Rule; use Illuminate\Support\Facades\App; +use Illuminate\Support\Facades\Date; class UnlimitedShippingDate implements Rule { @@ -22,7 +22,7 @@ public function passes($attribute, $value): bool if ($value === null) { return true; } - $shippingDate = Carbon::parse($value); + $shippingDate = Date::parse($value); $depositService = App::make(DepositServiceContract::class); $deposits = $depositService->getDepositsGroupByDateForItem($this->item, 'DESC'); @@ -31,7 +31,7 @@ public function passes($attribute, $value): bool return true; } - $depositsDate = Carbon::parse($deposits[0]['shipping_date']); + $depositsDate = Date::parse($deposits[0]['shipping_date']); return !$shippingDate->isBefore($depositsDate); } diff --git a/app/Services/DepositService.php b/app/Services/DepositService.php index 501e452a1..55cf0d3a9 100644 --- a/app/Services/DepositService.php +++ b/app/Services/DepositService.php @@ -7,7 +7,7 @@ use App\Models\Item; use App\Models\OrderProduct; use App\Services\Contracts\DepositServiceContract; -use Illuminate\Support\Carbon; +use Illuminate\Support\Facades\Date; final class DepositService implements DepositServiceContract { @@ -113,7 +113,7 @@ public function getDepositsGroupByDateForItem(Item $item, string $order = 'ASC') ->whereNotNull('shipping_date') ->where('item_id', '=', $item->getKey()) ->where('from_unlimited', '=', false) - ->where('shipping_date', '>=', Carbon::now()) + ->where('shipping_date', '>=', Date::now()) ->groupBy(['shipping_date']) ->having('quantity', '>', '0') ->orderBy('shipping_date', $order) @@ -242,11 +242,11 @@ private function removeFromShippingTimeAndDate( bool $fromUnlimited, ): bool { if ($shippingTimeAndDate['shipping_date'] !== null) { - $shippingDate = Carbon::parse($shippingTimeAndDate['shipping_date']); + $shippingDate = Date::parse($shippingTimeAndDate['shipping_date']); $groupedDepositsByDate = $this->getDepositsGroupByDateForItem($item, 'DESC'); foreach ($groupedDepositsByDate as $deposit) { - $depositDate = Carbon::parse($deposit['shipping_date']); + $depositDate = Date::parse($deposit['shipping_date']); if (!$depositDate->isAfter($shippingDate) && $quantity > 0) { $quantity -= $deposit['quantity']; @@ -265,7 +265,7 @@ private function removeFromShippingTimeAndDate( $groupedDepositsByTime = $this->getDepositsGroupByTimeForItem($item, 'DESC'); foreach ($groupedDepositsByTime as $deposit) { if (($deposit['shipping_time'] <= $shippingTimeAndDate['shipping_time'] - || $shippingTimeAndDate['shipping_time'] === null) && $quantity > 0) { + || $shippingTimeAndDate['shipping_time'] === null) && $quantity > 0) { $quantity -= $deposit['quantity']; $this->removeFromWarehouse( $orderProduct, diff --git a/app/Services/ProductService.php b/app/Services/ProductService.php index ca5cf2884..4ebb5f386 100644 --- a/app/Services/ProductService.php +++ b/app/Services/ProductService.php @@ -203,8 +203,12 @@ public function getPriceForVariant(Product $product, ProductVariantPriceDto $dto $price_initial = $product->mappedPriceForPriceMap($priceMap); - $sales = $this->discountService->getAllAplicableSalesForProduct($product, $this->discountService->getSalesWithBlockList(), $calculateForCurrentUser); - $price = $this->discountService->calcAllDiscountsOnProductVariant($product, $sales, $salesChannel, $dto->schemas); + if (is_array($dto->schemas) && !empty($dto->schemas)) { + $sales = $this->discountService->getAllAplicableSalesForProduct($product, $this->discountService->getSalesWithBlockList(), $calculateForCurrentUser); + $price = $this->discountService->calcAllDiscountsOnProductVariant($product, $sales, $salesChannel, $dto->schemas); + } else { + $price = ProductCachedPriceDto::from($price_initial, $salesChannel); + } return ProductVariantPriceResource::from([ 'price_initial' => ProductCachedPriceDto::from($price_initial, $salesChannel), diff --git a/database/migrations/2024_08_29_000001_create_sales_channel_for_each_default_price_map.php b/database/migrations/2024_08_29_000001_create_sales_channel_for_each_default_price_map.php index 104d5ff12..9bc5afec2 100644 --- a/database/migrations/2024_08_29_000001_create_sales_channel_for_each_default_price_map.php +++ b/database/migrations/2024_08_29_000001_create_sales_channel_for_each_default_price_map.php @@ -1,6 +1,5 @@ with('options')->chunkById(100, function (Collection $schemas) { + /** @var ProductSchema $schema */ + foreach ($schemas as $schema) { + $default = is_numeric($schema->default) ? intval($schema->default) : null; + + if ($default === null) { + continue; + } + + $default_option = $schema->options->get($default, $schema->options->last()); + $schema->default = $default_option?->getKey(); + $schema->saveQuietly(); + } + }); + } + + public function down(): void {} +}; diff --git a/src/Domain/Price/PriceRepository.php b/src/Domain/Price/PriceRepository.php index 78d3e482e..41ea35e48 100644 --- a/src/Domain/Price/PriceRepository.php +++ b/src/Domain/Price/PriceRepository.php @@ -17,10 +17,10 @@ use Domain\Price\Enums\DiscountConditionPriceType; use Domain\Price\Enums\ProductPriceType; use Domain\SalesChannel\Models\SalesChannel; +use Domain\SalesChannel\SalesChannelService; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; use Illuminate\Support\Arr; -use Illuminate\Support\Facades\Cache; use Ramsey\Uuid\Uuid; use Support\Dtos\ModelIdentityDto; @@ -31,6 +31,7 @@ final class PriceRepository */ public function setCachedProductPrices(ModelIdentityDto|Product $product, array|ProductCachedPricesDtoCollection $priceMatrix): void { + $salesChannels = app(SalesChannelService::class)->getCachedActiveSalesChannels(); $priceMatrix = new ProductCachedPricesDtoCollection(items: $priceMatrix); $rows = []; @@ -39,7 +40,7 @@ public function setCachedProductPrices(ModelIdentityDto|Product $product, array| /** @var ProductCachedPricesDto $pricesCollection */ foreach ($priceMatrix as $pricesCollection) { foreach ($pricesCollection->prices as $price) { - $salesChannel = Cache::driver('array')->rememberForever('sales_channel_' . $price->sales_channel_id, fn () => SalesChannel::with('priceMap')->findOrFail($price->sales_channel_id)); + $salesChannel = $salesChannels->firstOrFail('id', '=', $price->sales_channel_id); $rows[] = [ 'id' => Uuid::uuid4(), @@ -68,6 +69,7 @@ public function setCachedProductPrices(ModelIdentityDto|Product $product, array| ['value', 'net', 'gross', 'is_net'], ); + // Remove prices if priceMap currency changed foreach ($salesChannelsToPreserve as $salesChannelToPreserve) { Price::query() ->where('model_id', $product->getKey()) diff --git a/src/Domain/PriceMap/Resources/PriceMapProductPriceData.php b/src/Domain/PriceMap/Resources/PriceMapProductPriceData.php index 27e361916..e3806cf79 100644 --- a/src/Domain/PriceMap/Resources/PriceMapProductPriceData.php +++ b/src/Domain/PriceMap/Resources/PriceMapProductPriceData.php @@ -20,8 +20,8 @@ public function __construct( public static function fromModel(PriceMapProductPrice $price): static { return new self( - $price->price_map_id, - $price->map?->name ?? '', + $price->map?->id ?? 'MAP_DELETED', + $price->map?->name ?? 'MAP_DELETED', $price->is_net, $price->currency->value, (string) $price->value->getAmount(), diff --git a/src/Domain/PriceMap/Resources/PriceMapSchemaPricesOptionPriceDetailedData.php b/src/Domain/PriceMap/Resources/PriceMapSchemaPricesOptionPriceDetailedData.php index 14203019c..b523ec5fe 100644 --- a/src/Domain/PriceMap/Resources/PriceMapSchemaPricesOptionPriceDetailedData.php +++ b/src/Domain/PriceMap/Resources/PriceMapSchemaPricesOptionPriceDetailedData.php @@ -20,8 +20,8 @@ public function __construct( public static function fromModel(PriceMapSchemaOptionPrice $price): static { return new self( - $price->price_map_id, - $price->map?->name ?? '', + $price->map?->id ?? 'MAP_DELETED', + $price->map?->name ?? 'MAP_DELETED', $price->is_net, $price->currency->value, (string) $price->value->getAmount(), diff --git a/src/Domain/Product/Dtos/ProductVariantPriceDto.php b/src/Domain/Product/Dtos/ProductVariantPriceDto.php index ac81eb648..3de5f0617 100644 --- a/src/Domain/Product/Dtos/ProductVariantPriceDto.php +++ b/src/Domain/Product/Dtos/ProductVariantPriceDto.php @@ -5,13 +5,14 @@ namespace Domain\Product\Dtos; use Spatie\LaravelData\Data; +use Spatie\LaravelData\Optional; final class ProductVariantPriceDto extends Data { /** - * @param array $schemas + * @param array|Optional $schemas */ public function __construct( - public array $schemas, + public array|Optional $schemas, ) {} } diff --git a/src/Domain/ProductSchema/Services/SchemaCrudService.php b/src/Domain/ProductSchema/Services/SchemaCrudService.php index 12985a8a7..29210d5cb 100644 --- a/src/Domain/ProductSchema/Services/SchemaCrudService.php +++ b/src/Domain/ProductSchema/Services/SchemaCrudService.php @@ -85,6 +85,12 @@ public function update(Schema $schema, SchemaDto $dto): Schema $this->availabilityService->calculateSchemaAvailability($schema); + if (is_int($dto->default)) { + $default_option = $schema->options->get($dto->default, $schema->options->last()); + $schema->default = $default_option?->getKey(); + $schema->saveQuietly(); + } + return $schema; } diff --git a/tests/Feature/ItemTest.php b/tests/Feature/ItemTest.php index 7e4fea8cb..d715fbc1b 100644 --- a/tests/Feature/ItemTest.php +++ b/tests/Feature/ItemTest.php @@ -15,9 +15,9 @@ use Domain\Currency\Currency; use Domain\ProductSchema\Services\SchemaCrudService; use Illuminate\Events\CallQueuedListener; -use Illuminate\Support\Carbon; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Bus; +use Illuminate\Support\Facades\Date; use Illuminate\Support\Facades\Event; use Ramsey\Uuid\Uuid; use Spatie\WebhookServer\CallWebhookJob; @@ -37,7 +37,7 @@ public function setUp(): void { parent::setUp(); - Carbon::setTestNow(null); + Date::setTestNow(now()); $this->item = Item::factory()->create(); @@ -202,7 +202,7 @@ public function testIndexFilterBySoldOutAndDay(string $user): void ->actingAs($this->{$user}) ->json('GET', '/items', [ 'sold_out' => 1, - 'day' => Carbon::now(), + 'day' => Date::now(), ]) ->assertStatus(422); } @@ -218,7 +218,7 @@ public function testIndexSortByQuantityAndFilterByDay(string $user): void ->actingAs($this->{$user}) ->json('GET', '/items', [ 'sort' => 'quantity:asc', - 'day' => Carbon::now(), + 'day' => Date::now(), ]) ->assertStatus(422); } @@ -230,7 +230,7 @@ public function testIndexFilterByDay(string $user): void { $this->{$user}->givePermissionTo('items.show'); - $created_at = Carbon::yesterday()->startOfDay()->addHours(12); + $created_at = Date::yesterday()->startOfDay()->addHours(12); $item2 = Item::factory()->create([ 'created_at' => $created_at, @@ -271,11 +271,11 @@ public function testIndexFilterByDayWithHour(string $user): void $this->{$user}->givePermissionTo('items.show'); $item2 = Item::factory()->create([ - 'created_at' => Carbon::yesterday(), + 'created_at' => Date::yesterday(), ]); Deposit::factory([ 'quantity' => 5, - 'created_at' => Carbon::yesterday(), + 'created_at' => Date::yesterday(), ])->create([ 'item_id' => $item2->getKey(), ]); @@ -288,7 +288,7 @@ public function testIndexFilterByDayWithHour(string $user): void $this ->actingAs($this->{$user}) - ->json('GET', '/items', ['day' => Carbon::yesterday()]) + ->json('GET', '/items', ['day' => Date::yesterday()]) ->assertOk() ->assertJsonCount(1, 'data') ->assertJsonFragment([ @@ -787,6 +787,8 @@ public function testUpdateWithInvalidUnlimitedDate($user): void 'shipping_date' => now(), ]); + $this->item->deposits()->delete(); + Deposit::factory()->create([ 'quantity' => 20, 'from_unlimited' => false, @@ -1078,12 +1080,12 @@ public function testUpdateValidationUnlimitedShippingDateLesserThenShippingDate( Deposit::factory()->create([ 'item_id' => $this->item->getKey(), 'quantity' => 2.0, - 'shipping_date' => Carbon::now()->startOfDay()->addDays(4)->toDateTimeString(), + 'shipping_date' => Date::now()->startOfDay()->addDays(4)->toDateTimeString(), ]); $item = [ 'sku' => 'TES/T3', - 'unlimited_stock_shipping_date' => Carbon::now()->startOfDay()->addDay()->toDateTimeString(), + 'unlimited_stock_shipping_date' => Date::now()->startOfDay()->addDay()->toDateTimeString(), ]; $this->actingAs($this->{$user})->patchJson( @@ -1187,7 +1189,7 @@ public function testUpdateUnlimitedShippingTimeNull(string $user): void public function testUpdateUnlimitedShippingDate(string $user): void { $this->{$user}->givePermissionTo('items.edit'); - $date = Carbon::today()->addDays(4); + $date = Date::today()->addDays(4); Deposit::factory()->create([ 'item_id' => $this->item->getKey(), @@ -1223,7 +1225,7 @@ public function testUpdateUnlimitedShippingDate(string $user): void public function testUpdateUnlimitedShippingDateWithSameDateAsDeposit(string $user): void { $this->{$user}->givePermissionTo('items.edit'); - $date = Carbon::today()->addDays(4); + $date = Date::today()->addDays(4); Deposit::factory()->create([ 'item_id' => $this->item->getKey(), @@ -1292,7 +1294,7 @@ public function testCreateUnlimitedShippingDate(string $user): void 'name' => 'Test', 'sku' => 'TES/T1', 'unlimited_stock_shipping_time' => null, - 'unlimited_stock_shipping_date' => Carbon::now()->startOfDay()->addDays(5)->toIso8601String(), + 'unlimited_stock_shipping_date' => Date::now()->startOfDay()->addDays(5)->toIso8601String(), ]; $response = $this->actingAs($this->{$user})->postJson('/items', $item); @@ -1326,7 +1328,7 @@ public function testShowWhitAvailability(string $user): void 'quantity' => 2.0, 'shipping_time' => $time + 5, ]); - $date = Carbon::now()->startOfDay()->addDays(5)->toIso8601String(); + $date = Date::now()->startOfDay()->addDays(5)->toIso8601String(); Deposit::factory()->create([ 'item_id' => $item->getKey(), 'quantity' => 2.0,