mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-01 03:04:35 -04:00
Inventory Management Tests
This commit is contained in:
parent
e153a0a06a
commit
f92070e3be
@ -225,6 +225,7 @@ class InvoiceController extends BaseController
|
|||||||
$invoice = $invoice->service()
|
$invoice = $invoice->service()
|
||||||
->fillDefaults()
|
->fillDefaults()
|
||||||
->triggeredActions($request)
|
->triggeredActions($request)
|
||||||
|
->adjustInventory()
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
event(new InvoiceWasCreated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
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);
|
return response()->json(['message' => ctrans('texts.locked_invoice')], 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$old_invoice = $invoice->line_items;
|
||||||
|
|
||||||
$invoice = $this->invoice_repo->save($request->all(), $invoice);
|
$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)));
|
event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||||
|
|
||||||
|
@ -362,6 +362,7 @@ class BillingPortalPurchase extends Component
|
|||||||
->service()
|
->service()
|
||||||
->markSent()
|
->markSent()
|
||||||
->fillDefaults()
|
->fillDefaults()
|
||||||
|
->adjustInventory()
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
Cache::put($this->hash, [
|
Cache::put($this->hash, [
|
||||||
|
@ -37,9 +37,8 @@ class AdjustProductInventory implements ShouldQueue
|
|||||||
|
|
||||||
public array $old_invoice;
|
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->company = $company;
|
||||||
$this->invoice = $invoice;
|
$this->invoice = $invoice;
|
||||||
$this->old_invoice = $old_invoice;
|
$this->old_invoice = $old_invoice;
|
||||||
@ -55,8 +54,10 @@ class AdjustProductInventory implements ShouldQueue
|
|||||||
{
|
{
|
||||||
MultiDB::setDb($this->company->db);
|
MultiDB::setDb($this->company->db);
|
||||||
|
|
||||||
|
nlog("old invoice count = " . count($this->old_invoice));
|
||||||
|
|
||||||
if(count($this->old_invoice) > 0)
|
if(count($this->old_invoice) > 0)
|
||||||
return $this->existingInventoryAdjustment();
|
$this->existingInventoryAdjustment();
|
||||||
|
|
||||||
return $this->newInventoryAdjustment();
|
return $this->newInventoryAdjustment();
|
||||||
|
|
||||||
@ -73,6 +74,8 @@ class AdjustProductInventory implements ShouldQueue
|
|||||||
|
|
||||||
$line_items = $this->invoice->line_items;
|
$line_items = $this->invoice->line_items;
|
||||||
|
|
||||||
|
nlog($line_items);
|
||||||
|
|
||||||
foreach($line_items as $item)
|
foreach($line_items as $item)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -81,10 +84,14 @@ class AdjustProductInventory implements ShouldQueue
|
|||||||
if(!$p)
|
if(!$p)
|
||||||
continue;
|
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)
|
if($p->stock_notification_threshold && $p->in_stock_quantity <= $p->stock_notification_threshold)
|
||||||
$this->notifyStockLevels($p, 'product');
|
$this->notifyStockLevels($p, 'product');
|
||||||
@ -98,16 +105,18 @@ class AdjustProductInventory implements ShouldQueue
|
|||||||
private function existingInventoryAdjustment()
|
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)
|
if(!$p)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
$p->in_stock_quantity += $item->quantity;
|
nlog("adding back " . $item->quantity);
|
||||||
$p->save();
|
|
||||||
|
|
||||||
|
$p->in_stock_quantity += $item->quantity;
|
||||||
|
$p->saveQuietly();
|
||||||
|
nlog($p->toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -87,6 +87,7 @@ class SendRecurring implements ShouldQueue
|
|||||||
->applyNumber()
|
->applyNumber()
|
||||||
//->createInvitations() //need to only link invitations to those in the recurring invoice
|
//->createInvitations() //need to only link invitations to those in the recurring invoice
|
||||||
->fillDefaults()
|
->fillDefaults()
|
||||||
|
->adjustInventory()
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ class InventoryNotificationObject
|
|||||||
|
|
||||||
public function __construct(Product $product, string $notification_level)
|
public function __construct(Product $product, string $notification_level)
|
||||||
{
|
{
|
||||||
$this->payment = $product;
|
$this->product = $product;
|
||||||
$this->company = $product->company;
|
$this->company = $product->company;
|
||||||
$this->settings = $this->company->settings;
|
$this->settings = $this->company->settings;
|
||||||
}
|
}
|
||||||
|
@ -565,10 +565,11 @@ class InvoiceService
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function adjustInventory()
|
public function adjustInventory($old_invoice = [])
|
||||||
{
|
{
|
||||||
|
|
||||||
if($this->invoice->company->track_inventory)
|
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;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,7 @@ class ConvertQuote
|
|||||||
|
|
||||||
$invoice->service()
|
$invoice->service()
|
||||||
->fillDefaults()
|
->fillDefaults()
|
||||||
|
->adjustInventory()
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
$quote->invoice_id = $invoice->id;
|
$quote->invoice_id = $invoice->id;
|
||||||
|
111
tests/Feature/Inventory/InventoryManagementTest.php
Normal file
111
tests/Feature/Inventory/InventoryManagementTest.php
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -217,6 +217,7 @@ trait MockAccountData
|
|||||||
$settings->timezone_id = '1';
|
$settings->timezone_id = '1';
|
||||||
$settings->entity_send_time = 0;
|
$settings->entity_send_time = 0;
|
||||||
|
|
||||||
|
$this->company->track_inventory = true;
|
||||||
$this->company->settings = $settings;
|
$this->company->settings = $settings;
|
||||||
$this->company->save();
|
$this->company->save();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user