1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-20 00:11:35 +02:00

Inventory Management Tests

This commit is contained in:
David Bomba 2022-06-08 20:40:26 +10:00
parent e153a0a06a
commit f92070e3be
9 changed files with 146 additions and 15 deletions

View File

@ -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)));

View File

@ -362,6 +362,7 @@ class BillingPortalPurchase extends Component
->service()
->markSent()
->fillDefaults()
->adjustInventory()
->save();
Cache::put($this->hash, [

View File

@ -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());
}
}

View File

@ -87,6 +87,7 @@ class SendRecurring implements ShouldQueue
->applyNumber()
//->createInvitations() //need to only link invitations to those in the recurring invoice
->fillDefaults()
->adjustInventory()
->save();
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -70,6 +70,7 @@ class ConvertQuote
$invoice->service()
->fillDefaults()
->adjustInventory()
->save();
$quote->invoice_id = $invoice->id;

View File

@ -0,0 +1,111 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace Tests\Feature\Inventory;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Tests\MockAccountData;
use Tests\TestCase;
use App\Models\Product;
use App\Models\Invoice;
use App\DataMapper\InvoiceItem;
use Illuminate\Support\Str;
/**
* @test
*/
class InventoryManagementTest extends TestCase
{
use DatabaseTransactions;
use MockAccountData;
public function setUp() :void
{
parent::setUp();
$this->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);
}
}

View File

@ -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();