Merge branch 'refactor/inventory_stock' of https://gitea.quo.ar/tbianchini/shopit-back into refactor/inventory_stock

This commit is contained in:
2026-09-29 08:23:09 -03:00
parent c5aeb19735
commit 96378a6c2e
596 changed files with 239 additions and 7622 deletions

View File

@@ -39,9 +39,9 @@ class AccommodationService
/**
* @param array<int, array<string, mixed>> $variants
*/
public function upsertMany(Tenant $tenant, array $variants, ?string $stockAdjustmentId = null): CatalogItem
public function upsertMany(Tenant $tenant, array $variants): CatalogItem
{
return DB::transaction(function () use ($tenant, $variants, $stockAdjustmentId): CatalogItem {
return DB::transaction(function () use ($tenant, $variants): CatalogItem {
$attribute = $this->attribute($tenant);
$accommodation = $this->accommodation($tenant, $variants);
$itemAttribute = $accommodation->itemAttributes()->firstOrCreate(
@@ -70,7 +70,7 @@ class AccommodationService
if ($variant === null) {
$this->createVariant($attribute, $accommodation, $itemAttribute, $data);
} else {
$this->updateVariant($attribute, $variant, $itemAttribute, $data, $index, $stockAdjustmentId);
$this->updateVariant($attribute, $variant, $itemAttribute, $data, $index);
}
}
@@ -169,7 +169,7 @@ class AccommodationService
'title' => trim($variant['title']),
'value' => $this->valueCode($variant['title']),
'description' => $variant['description'] ?? null,
...(array_key_exists('stock', $variant) ? ['stock' => (int) $variant['stock']] : []),
'stock' => (int) $variant['stock'],
])->all();
}
@@ -212,7 +212,6 @@ class AccommodationService
$this->createOption($attribute, $data['value'], $data['title']);
$inventory = Inventory::query()->create(['real_stock' => $data['stock']]);
$inventory->recordInitialization();
$variant = $accommodation->variants()->create([
'inventory_id' => $inventory->id,
'descripcion' => $data['description'],
@@ -231,13 +230,20 @@ class AccommodationService
ItemAttribute $itemAttribute,
array $data,
int $index,
?string $stockAdjustmentId,
): void {
$inventory = Inventory::query()
->whereKey($variant->inventory_id)
->lockForUpdate()
->firstOrFail();
if ($data['stock'] < $inventory->reserved_stock) {
throw ValidationException::withMessages([
"variants.{$index}.stock" => [
'El stock no puede ser menor que la cantidad actualmente reservada.',
],
]);
}
$definition = $variant->definitions
->firstWhere('item_attribute_id', $itemAttribute->id);
$option = $definition === null
@@ -257,10 +263,7 @@ class AccommodationService
'descripcion' => $data['description'],
'precio' => $data['price'],
]);
$inventory->adjustAvailableStock(
(int) $data['stock_difference'],
idempotencyKey: $stockAdjustmentId,
);
$inventory->update(['real_stock' => $data['stock']]);
$variant->definitions()->updateOrCreate(
['item_attribute_id' => $itemAttribute->id],
['value' => $data['value']],

View File

@@ -43,18 +43,18 @@ class EntryService
* @param array<int, array<string, mixed>> $entries
* @return Collection<int, CatalogItem>
*/
public function upsertMany(Tenant $tenant, array $entries, ?string $stockAdjustmentId = null): Collection
public function upsertMany(Tenant $tenant, array $entries): Collection
{
return DB::transaction(function () use ($tenant, $entries, $stockAdjustmentId): Collection {
return DB::transaction(function () use ($tenant, $entries): Collection {
$reservedSlugs = [];
$category = Category::query()->firstOrCreate([
'tenant_code' => $tenant->codigo,
'nombre' => 'Entradas',
]);
return collect($entries)->map(function (array $entry, int $index) use ($tenant, $category, $stockAdjustmentId, &$reservedSlugs): CatalogItem {
return collect($entries)->map(function (array $entry, int $index) use ($tenant, $category, &$reservedSlugs): CatalogItem {
if (isset($entry['id'])) {
return $this->update($tenant, $category, $entry, $index, $stockAdjustmentId);
return $this->update($tenant, $category, $entry, $index);
}
$slug = $this->uniqueSlug($tenant, $entry['title'], $reservedSlugs);
@@ -92,7 +92,7 @@ class EntryService
}
/** @param array<string, mixed> $entry */
private function update(Tenant $tenant, Category $category, array $entry, int $index, ?string $stockAdjustmentId): CatalogItem
private function update(Tenant $tenant, Category $category, array $entry, int $index): CatalogItem
{
$catalogItem = CatalogItem::query()
->whereKey($entry['id'])
@@ -121,6 +121,14 @@ class EntryService
->lockForUpdate()
->firstOrFail();
if ((int) $entry['stock'] < $inventory->reserved_stock) {
throw ValidationException::withMessages([
"entries.{$index}.stock" => [
'El stock no puede ser menor que la cantidad actualmente reservada.',
],
]);
}
$eventDateIds = collect($entry['event_date_ids'])
->map(fn ($id): int => (int) $id)
->unique()
@@ -141,10 +149,7 @@ class EntryService
$catalogItem->itemAttributes()
->whereHas('attribute', fn ($query) => $query->where('codigo', 'event_date'))
->update(['allow_multi_select' => true]);
$inventory->adjustAvailableStock(
(int) $entry['stock_difference'],
idempotencyKey: $stockAdjustmentId,
);
$inventory->update(['real_stock' => $entry['stock']]);
return $catalogItem->load([
'variants.inventory',

View File

@@ -11,9 +11,9 @@ use App\Domains\Commerce\Catalog\Models\Inventory;
use App\Domains\Commerce\Catalog\Models\ItemAttribute;
use App\Domains\Commerce\Catalog\Models\Variant;
use App\Domains\Commerce\Catalog\Services\CatalogService;
use App\Domains\Core\Tenant\Models\Tenant;
use App\Domains\Ticketing\Event\Enums\EventDateStatus;
use App\Domains\Ticketing\Event\Models\EventDate;
use App\Domains\Core\Tenant\Models\Tenant;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;
@@ -50,9 +50,9 @@ class FoodService
/**
* @param array<int, array<string, mixed>> $variants
*/
public function upsertMany(Tenant $tenant, array $variants, ?string $stockAdjustmentId = null): CatalogItem
public function upsertMany(Tenant $tenant, array $variants): CatalogItem
{
return DB::transaction(function () use ($tenant, $variants, $stockAdjustmentId): CatalogItem {
return DB::transaction(function () use ($tenant, $variants): CatalogItem {
$attributes = $this->attributes($tenant);
$food = $this->food($tenant, $variants);
$itemAttributes = $this->itemAttributes($food, $attributes);
@@ -85,7 +85,7 @@ class FoodService
if ($variant === null) {
$this->createVariant($food, $itemAttributes, $data);
} else {
$this->updateVariant($variant, $itemAttributes, $data, $index, $stockAdjustmentId);
$this->updateVariant($variant, $itemAttributes, $data, $index);
}
}
@@ -113,11 +113,11 @@ class FoodService
}
/**
* @param array<int, array{id: int, stock_difference: int}> $variants
* @param array<int, array{id: int, stock: int}> $variants
*/
public function updateHistoricalStock(Tenant $tenant, array $variants, ?string $stockAdjustmentId = null): CatalogItem
public function updateHistoricalStock(Tenant $tenant, array $variants): CatalogItem
{
return DB::transaction(function () use ($tenant, $variants, $stockAdjustmentId): CatalogItem {
return DB::transaction(function () use ($tenant, $variants): CatalogItem {
$food = CatalogItem::query()
->forTenantCatalog($tenant)
->where('slug', 'comida')
@@ -142,11 +142,17 @@ class FoodService
]);
}
$stock = (int) $data['stock'];
$inventory = $this->inventoryForHistoricalStockUpdate($variant);
$inventory->adjustAvailableStock(
(int) $data['stock_difference'],
idempotencyKey: $stockAdjustmentId,
);
if ($stock < $inventory->reserved_stock) {
throw ValidationException::withMessages([
"variants.{$index}.stock" => [
'El stock no puede ser menor que la cantidad actualmente reservada.',
],
]);
}
$inventory->update(['real_stock' => $stock]);
}
return $this->current($tenant) ?? $food;
@@ -175,7 +181,6 @@ class FoodService
'reserved_stock' => 0,
'real_stock' => $inventory->real_stock,
]);
$historicalInventory->recordTransferInitialization();
$variant->update(['inventory_id' => $historicalInventory->getKey()]);
return $historicalInventory;
@@ -296,7 +301,7 @@ class FoodService
'schedule' => $schedule->value,
'service' => $service->value,
'description' => (string) ($variant['description'] ?? ''),
...(array_key_exists('stock', $variant) ? ['stock' => (int) $variant['stock']] : []),
'stock' => (int) $variant['stock'],
];
})->all();
}
@@ -379,7 +384,6 @@ class FoodService
private function createVariant(CatalogItem $food, Collection $itemAttributes, array $data): void
{
$inventory = Inventory::query()->create(['real_stock' => $data['stock']]);
$inventory->recordInitialization();
$variant = $food->variants()->create([
'event_date_id' => $data['event_date_id'],
'inventory_id' => $inventory->id,
@@ -396,23 +400,27 @@ class FoodService
Collection $itemAttributes,
array $data,
int $index,
?string $stockAdjustmentId,
): void {
$inventory = Inventory::query()
->whereKey($variant->inventory_id)
->lockForUpdate()
->firstOrFail();
if ($data['stock'] < $inventory->reserved_stock) {
throw ValidationException::withMessages([
"variants.{$index}.stock" => [
'El stock no puede ser menor que la cantidad actualmente reservada.',
],
]);
}
$variant->update([
'event_date_id' => $data['event_date_id'],
'descripcion' => $data['description'],
'precio' => $data['price'],
]);
$variant->eventDates()->sync([$data['event_date_id']]);
$inventory->adjustAvailableStock(
(int) $data['stock_difference'],
idempotencyKey: $stockAdjustmentId,
);
$inventory->update(['real_stock' => $data['stock']]);
$this->syncDefinitions($variant, $itemAttributes, $data);
}

View File

@@ -43,9 +43,9 @@ class MerchandiseService
* @param array<int, array<string, mixed>> $items
* @return Collection<int, CatalogItem>
*/
public function upsertMany(Tenant $tenant, array $items, ?string $stockAdjustmentId = null): Collection
public function upsertMany(Tenant $tenant, array $items): Collection
{
return DB::transaction(function () use ($tenant, $items, $stockAdjustmentId): Collection {
return DB::transaction(function () use ($tenant, $items): Collection {
$attributes = $this->attributes($tenant);
$category = Category::query()->firstOrCreate([
'tenant_code' => $tenant->codigo,
@@ -57,7 +57,6 @@ class MerchandiseService
$tenant,
$attributes,
$category,
$stockAdjustmentId,
&$reservedSlugs,
): CatalogItem {
$item = isset($data['id'])
@@ -102,7 +101,7 @@ class MerchandiseService
if ($variant === null) {
$this->createVariant($item, $itemAttributes, $variantData);
} else {
$this->updateVariant($variant, $itemAttributes, $variantData, $index, $variantIndex, $stockAdjustmentId);
$this->updateVariant($variant, $itemAttributes, $variantData, $index, $variantIndex);
}
}
@@ -245,7 +244,7 @@ class MerchandiseService
...$variant,
'color' => $color->value,
'size' => $size->value,
...(array_key_exists('stock', $variant) ? ['stock' => (int) $variant['stock']] : []),
'stock' => (int) $variant['stock'],
];
})->all();
}
@@ -343,7 +342,6 @@ class MerchandiseService
array $data,
): void {
$inventory = Inventory::query()->create(['real_stock' => $data['stock']]);
$inventory->recordInitialization();
$variant = $item->variants()->create([
'inventory_id' => $inventory->id,
'precio' => $data['price'],
@@ -361,18 +359,22 @@ class MerchandiseService
array $data,
int $itemIndex,
int $variantIndex,
?string $stockAdjustmentId,
): void {
$inventory = Inventory::query()
->whereKey($variant->inventory_id)
->lockForUpdate()
->firstOrFail();
if ($data['stock'] < $inventory->reserved_stock) {
throw ValidationException::withMessages([
"items.{$itemIndex}.variants.{$variantIndex}.stock" => [
'El stock no puede ser menor que la cantidad actualmente reservada.',
],
]);
}
$variant->update(['precio' => $data['price']]);
$inventory->adjustAvailableStock(
(int) $data['stock_difference'],
idempotencyKey: $stockAdjustmentId,
);
$inventory->update(['real_stock' => $data['stock']]);
$this->syncDefinitions($variant, $itemAttributes, $data);
}