From f92070e3be7c56778c1aa73ed377a6bafddffb9b Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 8 Jun 2022 20:40:26 +1000 Subject: [PATCH] Inventory Management Tests --- app/Http/Controllers/InvoiceController.php | 10 +- app/Http/Livewire/BillingPortalPurchase.php | 1 + app/Jobs/Inventory/AdjustProductInventory.php | 29 +++-- app/Jobs/RecurringInvoice/SendRecurring.php | 1 + .../Admin/InventoryNotificationObject.php | 2 +- app/Services/Invoice/InvoiceService.php | 5 +- app/Services/Quote/ConvertQuote.php | 1 + .../Inventory/InventoryManagementTest.php | 111 ++++++++++++++++++ tests/MockAccountData.php | 1 + 9 files changed, 146 insertions(+), 15 deletions(-) create mode 100644 tests/Feature/Inventory/InventoryManagementTest.php diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php index 0ebfcbafda..168a6bbc05 100644 --- a/app/Http/Controllers/InvoiceController.php +++ b/app/Http/Controllers/InvoiceController.php @@ -225,6 +225,7 @@ class InvoiceController extends BaseController $invoice = $invoice->service() ->fillDefaults() ->triggeredActions($request) + ->adjustInventory() ->save(); event(new InvoiceWasCreated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); @@ -414,9 +415,14 @@ class InvoiceController extends BaseController return response()->json(['message' => ctrans('texts.locked_invoice')], 403); } + $old_invoice = $invoice->line_items; + $invoice = $this->invoice_repo->save($request->all(), $invoice); - - $invoice->service()->triggeredActions($request)->touchPdf(); + + $invoice->service() + ->triggeredActions($request) + ->touchPdf() + ->adjustInventory($old_invoice); event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); diff --git a/app/Http/Livewire/BillingPortalPurchase.php b/app/Http/Livewire/BillingPortalPurchase.php index 4a5fd2f714..d383ee5522 100644 --- a/app/Http/Livewire/BillingPortalPurchase.php +++ b/app/Http/Livewire/BillingPortalPurchase.php @@ -362,6 +362,7 @@ class BillingPortalPurchase extends Component ->service() ->markSent() ->fillDefaults() + ->adjustInventory() ->save(); Cache::put($this->hash, [ diff --git a/app/Jobs/Inventory/AdjustProductInventory.php b/app/Jobs/Inventory/AdjustProductInventory.php index 0c8468e19e..7af22ce891 100644 --- a/app/Jobs/Inventory/AdjustProductInventory.php +++ b/app/Jobs/Inventory/AdjustProductInventory.php @@ -37,9 +37,8 @@ class AdjustProductInventory implements ShouldQueue public array $old_invoice; - public function __construct(Company $company, Invoice $invoice, array $old_invoice = []) + public function __construct(Company $company, Invoice $invoice, ?array $old_invoice = []) { - $this->company = $company; $this->invoice = $invoice; $this->old_invoice = $old_invoice; @@ -55,8 +54,10 @@ class AdjustProductInventory implements ShouldQueue { MultiDB::setDb($this->company->db); +nlog("old invoice count = " . count($this->old_invoice)); + if(count($this->old_invoice) > 0) - return $this->existingInventoryAdjustment(); + $this->existingInventoryAdjustment(); return $this->newInventoryAdjustment(); @@ -73,6 +74,8 @@ class AdjustProductInventory implements ShouldQueue $line_items = $this->invoice->line_items; +nlog($line_items); + foreach($line_items as $item) { @@ -81,10 +84,14 @@ class AdjustProductInventory implements ShouldQueue if(!$p) continue; - $p->in_stock_quantity -= $item->quantity; - $p->save(); - //check thresholds and notify user +nlog("subtracting back " . $item->quantity); + + $p->in_stock_quantity -= $item->quantity; + $p->saveQuietly(); + +nlog($p->toArray()); + if($p->stock_notification_threshold && $p->in_stock_quantity <= $p->stock_notification_threshold) $this->notifyStockLevels($p, 'product'); @@ -98,16 +105,18 @@ class AdjustProductInventory implements ShouldQueue private function existingInventoryAdjustment() { - foreach($this->old_invoice['line_items'] as $item) + foreach($this->old_invoice as $item) { - $p = Product::where('product_key', $item->product_key)->where('company_id', $this->company->id)->where('in_stock_quantity', '>', 0)->first(); + $p = Product::where('product_key', $item->product_key)->where('company_id', $this->company->id)->first(); if(!$p) continue; - $p->in_stock_quantity += $item->quantity; - $p->save(); +nlog("adding back " . $item->quantity); + $p->in_stock_quantity += $item->quantity; + $p->saveQuietly(); +nlog($p->toArray()); } } diff --git a/app/Jobs/RecurringInvoice/SendRecurring.php b/app/Jobs/RecurringInvoice/SendRecurring.php index b5ef1d7d20..b3bf0a53dd 100644 --- a/app/Jobs/RecurringInvoice/SendRecurring.php +++ b/app/Jobs/RecurringInvoice/SendRecurring.php @@ -87,6 +87,7 @@ class SendRecurring implements ShouldQueue ->applyNumber() //->createInvitations() //need to only link invitations to those in the recurring invoice ->fillDefaults() + ->adjustInventory() ->save(); } diff --git a/app/Mail/Admin/InventoryNotificationObject.php b/app/Mail/Admin/InventoryNotificationObject.php index d7217b5ecd..e752c5acf9 100644 --- a/app/Mail/Admin/InventoryNotificationObject.php +++ b/app/Mail/Admin/InventoryNotificationObject.php @@ -33,7 +33,7 @@ class InventoryNotificationObject public function __construct(Product $product, string $notification_level) { - $this->payment = $product; + $this->product = $product; $this->company = $product->company; $this->settings = $this->company->settings; } diff --git a/app/Services/Invoice/InvoiceService.php b/app/Services/Invoice/InvoiceService.php index c13673df2d..a0a90deb03 100644 --- a/app/Services/Invoice/InvoiceService.php +++ b/app/Services/Invoice/InvoiceService.php @@ -565,10 +565,11 @@ class InvoiceService return $this; } - public function adjustInventory() + public function adjustInventory($old_invoice = []) { + if($this->invoice->company->track_inventory) - AdjustProductInventory::dispatch($this->invoice->company, $this->invoice, null)->delay(rand(1,2)); + AdjustProductInventory::dispatchNow($this->invoice->company, $this->invoice, $old_invoice); return $this; } diff --git a/app/Services/Quote/ConvertQuote.php b/app/Services/Quote/ConvertQuote.php index 5f9d6fccac..eedb94bc71 100644 --- a/app/Services/Quote/ConvertQuote.php +++ b/app/Services/Quote/ConvertQuote.php @@ -70,6 +70,7 @@ class ConvertQuote $invoice->service() ->fillDefaults() + ->adjustInventory() ->save(); $quote->invoice_id = $invoice->id; diff --git a/tests/Feature/Inventory/InventoryManagementTest.php b/tests/Feature/Inventory/InventoryManagementTest.php new file mode 100644 index 0000000000..8415e6cdc2 --- /dev/null +++ b/tests/Feature/Inventory/InventoryManagementTest.php @@ -0,0 +1,111 @@ +makeTestData(); + + $this->withoutMiddleware( + ThrottleRequests::class + ); + } + + public function testInventoryMovements() + { + + $product = Product::factory()->create([ + 'user_id' => $this->user->id, + 'company_id' => $this->company->id, + 'in_stock_quantity' => 100, + 'stock_notification' => true, + 'stock_notification_threshold' => 99 + ]); + + $invoice = Invoice::factory()->create([ + 'user_id' => $this->user->id, + 'company_id' => $this->company->id, + 'client_id' => $this->client->id + ]); + + $invoice->company->track_inventory = true; + $invoice->push(); + + + $invoice_item = new InvoiceItem; + $invoice_item->type_id = 1; + $invoice_item->product_key = $product->product_key; + $invoice_item->notes = $product->notes; + $invoice_item->quantity = 10; + $invoice_item->cost = 100; + + $line_items[] = $invoice_item; + $invoice->line_items = $line_items; + $invoice->number = Str::random(16); + + $invoice->client_id = $this->client->hashed_id; + + $invoice_array = $invoice->toArray(); + $invoice_array['client_id'] = $this->client->hashed_id; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/invoices/', $invoice_array) + ->assertStatus(200); + + $product = $product->refresh(); + + $this->assertEquals(90, $product->in_stock_quantity); + + + $arr = $response->json(); + $invoice_hashed_id = $arr['data']['id']; + + $invoice_item = new InvoiceItem; + $invoice_item->type_id = 1; + $invoice_item->product_key = $product->product_key; + $invoice_item->notes = $product->notes; + $invoice_item->quantity = 5; + $invoice_item->cost = 100; + + $line_items2[] = $invoice_item; + $invoice->line_items = $line_items2; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/invoices/'.$invoice_hashed_id, $invoice->toArray()) + ->assertStatus(200); + + $product = $product->refresh(); + + $this->assertEquals(95, $product->in_stock_quantity); + } +} diff --git a/tests/MockAccountData.php b/tests/MockAccountData.php index 1e8cf07e92..1cb37e7273 100644 --- a/tests/MockAccountData.php +++ b/tests/MockAccountData.php @@ -217,6 +217,7 @@ trait MockAccountData $settings->timezone_id = '1'; $settings->entity_send_time = 0; + $this->company->track_inventory = true; $this->company->settings = $settings; $this->company->save();