Commit 459ea67c authored by Mahmoud Aglan's avatar Mahmoud Aglan

Fix product creation: auto-generate SKU, catch DB exceptions

- SKU is NOT NULL in the database but was nullable in wizard validation,
  causing a crash when submitted without a SKU value
- Auto-generate SKU (PRD-0001, SRV-0001, DIG-0001) when not provided
- Catch QueryException in both product forms to show friendly error
  instead of crashing on unique constraint violations
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 60ff1e86
...@@ -124,10 +124,12 @@ public function goToStep(int $step): void ...@@ -124,10 +124,12 @@ public function goToStep(int $step): void
public function confirm(): void public function confirm(): void
{ {
try { try {
$sku = $this->sku ?: $this->generateSku();
Product::create([ Product::create([
'name_ar' => $this->nameAr, 'name_ar' => $this->nameAr,
'name' => $this->name ?: null, 'name' => $this->name ?: null,
'sku' => $this->sku ?: null, 'sku' => $sku,
'barcode' => $this->barcode ?: null, 'barcode' => $this->barcode ?: null,
'category_id' => $this->categoryId, 'category_id' => $this->categoryId,
'branch_id' => session('active_branch_id'), 'branch_id' => session('active_branch_id'),
...@@ -147,9 +149,26 @@ public function confirm(): void ...@@ -147,9 +149,26 @@ public function confirm(): void
$this->redirect(route('inventory.products'), navigate: true); $this->redirect(route('inventory.products'), navigate: true);
} catch (DomainException $e) { } catch (DomainException $e) {
session()->flash('error', $e->getMessage()); session()->flash('error', $e->getMessage());
} catch (\Illuminate\Database\QueryException $e) {
if (str_contains($e->getMessage(), 'unique')) {
session()->flash('error', 'رمز المنتج (SKU) مستخدم بالفعل');
} else {
session()->flash('error', 'حدث خطأ أثناء حفظ المنتج: ' . $e->getMessage());
}
} }
} }
private function generateSku(): string
{
$prefix = match ($this->type) {
'service' => 'SRV',
'digital' => 'DIG',
default => 'PRD',
};
$count = Product::withoutGlobalScopes()->count() + 1;
return $prefix . '-' . str_pad($count, 4, '0', STR_PAD_LEFT);
}
public function render() public function render()
{ {
return view('livewire.inventory.create-product-wizard'); return view('livewire.inventory.create-product-wizard');
......
...@@ -67,7 +67,7 @@ public function rules(): array ...@@ -67,7 +67,7 @@ public function rules(): array
return [ return [
'name_ar' => 'required|string|max:255', 'name_ar' => 'required|string|max:255',
'name' => 'nullable|string|max:255', 'name' => 'nullable|string|max:255',
'sku' => ['required', 'string', 'max:50', $uniqueSku], 'sku' => ['nullable', 'string', 'max:50', $uniqueSku],
'barcode' => 'nullable|string|max:50', 'barcode' => 'nullable|string|max:50',
'category_id' => 'nullable|exists:product_categories,id', 'category_id' => 'nullable|exists:product_categories,id',
'type' => 'required|in:physical,digital,service', 'type' => 'required|in:physical,digital,service',
...@@ -113,7 +113,7 @@ public function save(): void ...@@ -113,7 +113,7 @@ public function save(): void
$data = [ $data = [
'name_ar' => $this->name_ar, 'name_ar' => $this->name_ar,
'name' => $this->name ?: null, 'name' => $this->name ?: null,
'sku' => $this->sku, 'sku' => $this->sku ?: $this->generateSku(),
'barcode' => $this->barcode ?: null, 'barcode' => $this->barcode ?: null,
'category_id' => $this->category_id, 'category_id' => $this->category_id,
'type' => $this->type, 'type' => $this->type,
...@@ -140,9 +140,26 @@ public function save(): void ...@@ -140,9 +140,26 @@ public function save(): void
$this->redirect(route('inventory.products'), navigate: true); $this->redirect(route('inventory.products'), navigate: true);
} catch (DomainException $e) { } catch (DomainException $e) {
session()->flash('error', $e->getMessage()); session()->flash('error', $e->getMessage());
} catch (\Illuminate\Database\QueryException $e) {
if (str_contains($e->getMessage(), 'unique')) {
session()->flash('error', __('رمز المنتج (SKU) مستخدم بالفعل'));
} else {
session()->flash('error', __('حدث خطأ أثناء حفظ المنتج'));
}
} }
} }
private function generateSku(): string
{
$prefix = match ($this->type) {
'service' => 'SRV',
'digital' => 'DIG',
default => 'PRD',
};
$count = Product::withoutGlobalScopes()->count() + 1;
return $prefix . '-' . str_pad($count, 4, '0', STR_PAD_LEFT);
}
public function render() public function render()
{ {
return view('livewire.inventory.product-form', [ return view('livewire.inventory.product-form', [
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment