Przeglądaj źródła

Reserve remaining reclamation quantity from stock

Alexander Musikhin 2 dni temu
rodzic
commit
1cd1038028

+ 31 - 21
app/Services/SparePartReservationService.php

@@ -427,7 +427,7 @@ class SparePartReservationService
             ]);
 
             if ($reassignedQty < $requestedQty) {
-                $this->splitPivotRowAfterPartialReassignment(
+                $this->reassignRemainingQuantity(
                     $reservation,
                     $reassignedQty,
                     $requestedQty - $reassignedQty
@@ -476,7 +476,7 @@ class SparePartReservationService
         ]);
     }
 
-    private function splitPivotRowAfterPartialReassignment(
+    private function reassignRemainingQuantity(
         Reservation $reservation,
         int $reservedQty,
         int $remainingQty
@@ -500,26 +500,36 @@ class SparePartReservationService
             'status' => 'reserved',
         ]);
 
-        ReclamationSparePart::query()->create([
-            'reclamation_id' => $row->reclamation_id,
-            'spare_part_id' => $row->spare_part_id,
-            'quantity' => $remainingQty,
-            'with_documents' => $row->with_documents,
-            'status' => 'pending',
-            'reserved_qty' => 0,
-            'issued_qty' => 0,
-        ]);
+        $remainingReservationResult = $this->reserve(
+            $reservation->spare_part_id,
+            $remainingQty,
+            $reservation->with_documents,
+            $reservation->reclamation_id
+        );
+
+        if ($remainingReservationResult->reserved > 0) {
+            ReclamationSparePart::query()->create([
+                'reclamation_id' => $row->reclamation_id,
+                'spare_part_id' => $row->spare_part_id,
+                'quantity' => $remainingReservationResult->reserved,
+                'with_documents' => $row->with_documents,
+                'status' => 'reserved',
+                'reserved_qty' => $remainingReservationResult->reserved,
+                'issued_qty' => 0,
+            ]);
+        }
 
-        Shortage::query()->create([
-            'spare_part_id' => $row->spare_part_id,
-            'reclamation_id' => $row->reclamation_id,
-            'with_documents' => $row->with_documents,
-            'required_qty' => $remainingQty,
-            'reserved_qty' => 0,
-            'missing_qty' => $remainingQty,
-            'status' => Shortage::STATUS_OPEN,
-            'note' => 'Остаток после частичного переноса резерва на выбранный заказ',
-        ]);
+        if ($remainingReservationResult->missing > 0) {
+            ReclamationSparePart::query()->create([
+                'reclamation_id' => $row->reclamation_id,
+                'spare_part_id' => $row->spare_part_id,
+                'quantity' => $remainingReservationResult->missing,
+                'with_documents' => $row->with_documents,
+                'status' => 'pending',
+                'reserved_qty' => 0,
+                'issued_qty' => 0,
+            ]);
+        }
     }
 }
 

+ 78 - 2
tests/Unit/Services/SparePartReservationServiceTest.php

@@ -582,7 +582,7 @@ class SparePartReservationServiceTest extends TestCase
         ]);
     }
 
-    public function test_reassign_reservation_to_selected_order_splits_row_when_selected_order_has_partial_quantity(): void
+    public function test_reassign_reservation_to_selected_order_reserves_remaining_quantity_from_other_stock(): void
     {
         $user = User::factory()->create();
         $this->actingAs($user);
@@ -615,6 +615,12 @@ class SparePartReservationServiceTest extends TestCase
         $newReservation = $this->service->reassignReservationToSelectedOrder($reservation, $selectedOrder->id);
 
         $this->assertSame(2, $newReservation->reserved_qty);
+        $this->assertDatabaseHas('reservations', [
+            'reclamation_id' => $reclamation->id,
+            'spare_part_order_id' => $oldOrder->id,
+            'reserved_qty' => 3,
+            'status' => Reservation::STATUS_ACTIVE,
+        ]);
         $this->assertDatabaseHas('reclamation_spare_part', [
             'reclamation_id' => $reclamation->id,
             'spare_part_id' => $sparePart->id,
@@ -629,6 +635,75 @@ class SparePartReservationServiceTest extends TestCase
             'spare_part_id' => $sparePart->id,
             'quantity' => 3,
             'with_documents' => true,
+            'status' => 'reserved',
+            'reserved_qty' => 3,
+            'issued_qty' => 0,
+        ]);
+        $this->assertDatabaseMissing('shortages', [
+            'reclamation_id' => $reclamation->id,
+            'spare_part_id' => $sparePart->id,
+            'with_documents' => true,
+            'status' => Shortage::STATUS_OPEN,
+        ]);
+    }
+
+    public function test_reassign_reservation_to_selected_order_creates_shortage_only_for_real_missing_quantity(): void
+    {
+        $user = User::factory()->create();
+        $this->actingAs($user);
+
+        $sparePart = SparePart::factory()->create();
+        $reclamation = Reclamation::factory()->create();
+        $oldOrder = SparePartOrder::factory()->inStock()->withDocuments(true)->withQuantity(1)->forSparePart($sparePart)->create([
+            'available_qty' => 1,
+        ]);
+        $selectedOrder = SparePartOrder::factory()->inStock()->withDocuments(true)->withQuantity(2)->forSparePart($sparePart)->create([
+            'available_qty' => 2,
+        ]);
+
+        ReclamationSparePart::query()->create([
+            'reclamation_id' => $reclamation->id,
+            'spare_part_id' => $sparePart->id,
+            'quantity' => 5,
+            'with_documents' => true,
+            'status' => 'reserved',
+            'reserved_qty' => 5,
+            'issued_qty' => 0,
+        ]);
+
+        $reservation = Reservation::factory()
+            ->active()
+            ->withQuantity(5)
+            ->withDocuments(true)
+            ->fromOrder($oldOrder)
+            ->forReclamation($reclamation)
+            ->create([
+                'reserved_qty' => 5,
+            ]);
+
+        $newReservation = $this->service->reassignReservationToSelectedOrder($reservation, $selectedOrder->id);
+
+        $this->assertSame(2, $newReservation->reserved_qty);
+        $this->assertDatabaseHas('reservations', [
+            'reclamation_id' => $reclamation->id,
+            'spare_part_order_id' => $oldOrder->id,
+            'reserved_qty' => 1,
+            'status' => Reservation::STATUS_ACTIVE,
+        ]);
+        $this->assertDatabaseHas('reclamation_spare_part', [
+            'reclamation_id' => $reclamation->id,
+            'spare_part_id' => $sparePart->id,
+            'quantity' => 1,
+            'with_documents' => true,
+            'status' => 'reserved',
+            'reserved_qty' => 1,
+            'issued_qty' => 0,
+        ]);
+        $this->assertDatabaseHas('reclamation_spare_part', [
+            'reclamation_id' => $reclamation->id,
+            'spare_part_id' => $sparePart->id,
+            'quantity' => 2,
+            'with_documents' => true,
             'status' => 'pending',
             'reserved_qty' => 0,
             'issued_qty' => 0,
@@ -636,7 +711,8 @@ class SparePartReservationServiceTest extends TestCase
         $this->assertDatabaseHas('shortages', [
             'reclamation_id' => $reclamation->id,
             'spare_part_id' => $sparePart->id,
-            'missing_qty' => 3,
+            'missing_qty' => 2,
+            'reserved_qty' => 1,
             'with_documents' => true,
             'status' => Shortage::STATUS_OPEN,
         ]);