View source
<?php
namespace Drupal\Tests\farm_inventory\Kernel;
use Drupal\asset\Entity\Asset;
use Drupal\asset\Entity\AssetInterface;
use Drupal\fraction\Fraction;
use Drupal\KernelTests\KernelTestBase;
use Drupal\log\Entity\Log;
use Drupal\quantity\Entity\Quantity;
use Drupal\taxonomy\Entity\Term;
use Drupal\Tests\farm_test\Kernel\FarmEntityCacheTestTrait;
class InventoryTest extends KernelTestBase {
use FarmEntityCacheTestTrait;
protected $assetInventory;
protected static $modules = [
'asset',
'entity_reference_revisions',
'farm_field',
'farm_inventory',
'farm_inventory_test',
'farm_log',
'farm_log_quantity',
'farm_quantity_standard',
'farm_unit',
'fraction',
'log',
'options',
'quantity',
'state_machine',
'taxonomy',
'text',
'user',
];
protected function setUp() : void {
parent::setUp();
$this->assetInventory = \Drupal::service('asset.inventory');
$this
->installEntitySchema('asset');
$this
->installEntitySchema('log');
$this
->installEntitySchema('user');
$this
->installEntitySchema('quantity');
$this
->installEntitySchema('taxonomy_term');
$this
->installConfig([
'farm_inventory_test',
'farm_quantity_standard',
]);
}
public function testSimpleAssetInventory() {
$asset = Asset::create([
'type' => 'container',
'name' => $this
->randomMachineName(),
'status' => 'active',
]);
$asset
->save();
$this
->populateEntityTestCache($asset);
$inventory = $this->assetInventory
->getInventory($asset);
$this
->assertEmpty($inventory, 'New assets do not have inventory.');
$this
->assertEntityTestCache($asset, TRUE);
$this
->adjustInventory($asset, 'reset', '1');
$inventory = $this->assetInventory
->getInventory($asset);
$this
->assertNotEmpty($inventory, 'Asset with an inventory adjustment has inventory.');
$this
->assertEquals('1', $inventory[0]['value'], 'Asset inventory is 1.');
$this
->assertEntityTestCache($asset, FALSE);
$this
->populateEntityTestCache($asset);
$this
->adjustInventory($asset, 'increment', '5');
$inventory = $this->assetInventory
->getInventory($asset);
$this
->assertEquals('6', $inventory[0]['value'], 'Asset inventory is 6.');
$this
->assertEntityTestCache($asset, FALSE);
$this
->populateEntityTestCache($asset);
$this
->adjustInventory($asset, 'decrement', '1');
$inventory = $this->assetInventory
->getInventory($asset);
$this
->assertEquals('5', $inventory[0]['value'], 'Asset inventory is 5.');
$this
->assertEntityTestCache($asset, FALSE);
$this
->populateEntityTestCache($asset);
$this
->adjustInventory($asset, 'reset', '0');
$inventory = $this->assetInventory
->getInventory($asset);
$this
->assertEquals('0', $inventory[0]['value'], 'Asset inventory is 0.');
$this
->assertEntityTestCache($asset, FALSE);
$log = $this
->adjustInventory($asset, 'increment', '1');
$log
->set('status', 'pending');
$log
->save();
$this
->populateEntityTestCache($asset);
$log
->save();
$inventory = $this->assetInventory
->getInventory($asset);
$this
->assertEquals('0', $inventory[0]['value'], 'Pending adjustments do not affect inventory.');
$this
->assertEntityTestCache($asset, TRUE);
$log = $this
->adjustInventory($asset, 'increment', '1');
$log
->set('timestamp', \Drupal::time()
->getRequestTime() + 86400);
$log
->save();
$this
->populateEntityTestCache($asset);
$log
->save();
$inventory = $this->assetInventory
->getInventory($asset);
$this
->assertEquals('0', $inventory[0]['value'], 'Future adjustments do not affect inventory.');
$this
->assertEntityTestCache($asset, TRUE);
$this
->adjustInventory($asset, 'reset', '1.1');
$inventory = $this->assetInventory
->getInventory($asset);
$this
->assertEquals('1.1', $inventory[0]['value'], 'Asset inventory is 1.1.');
$this
->assertEntityTestCache($asset, FALSE);
$this
->populateEntityTestCache($asset);
$this
->adjustInventory($asset, 'increment', '1.4');
$inventory = $this->assetInventory
->getInventory($asset);
$this
->assertEquals('2.5', $inventory[0]['value'], 'Asset inventory is 2.5.');
$this
->assertEntityTestCache($asset, FALSE);
$this
->populateEntityTestCache($asset);
$this
->adjustInventory($asset, 'reset', '0.1');
$log = $this
->adjustInventory($asset, 'increment', '0.2');
$inventory = $this->assetInventory
->getInventory($asset);
$this
->assertEquals('0.3', $inventory[0]['value'], 'Inventory calculations handle floating point arithmetic properly.');
$this
->assertEntityTestCache($asset, FALSE);
$this
->populateEntityTestCache($asset);
$log
->delete();
$inventory = $this->assetInventory
->getInventory($asset);
$this
->assertEquals('0.1', $inventory[0]['value'], 'Asset inventory is updated when a log is deleted.');
$this
->assertEntityTestCache($asset, FALSE);
}
public function testMultipleAssetInventory() {
$asset = Asset::create([
'type' => 'container',
'name' => $this
->randomMachineName(),
'status' => 'active',
]);
$asset
->save();
$unit1 = Term::create([
'name' => 'liters',
'vid' => 'unit',
]);
$unit1
->save();
$unit2 = Term::create([
'name' => 'hours',
'vid' => 'unit',
]);
$unit2
->save();
$this
->adjustInventory($asset, 'reset', '1', 'volume', $unit1
->id());
$inventory = $this->assetInventory
->getInventory($asset);
$this
->assertEquals(1, count($inventory), 'Asset has a single inventory.');
$this
->assertEquals('volume', $inventory[0]['measure'], 'Asset inventory has a measure of volume.');
$this
->assertEquals('liters', $inventory[0]['units'], 'Asset inventory has units in liters.');
$this
->assertEquals('1', $inventory[0]['value'], 'Asset inventory is 1.');
$this
->adjustInventory($asset, 'reset', '2', 'time', $unit2
->id());
$inventory = $this->assetInventory
->getInventory($asset);
$this
->assertEquals(2, count($inventory), 'Asset has a single inventory.');
$inventory = $this->assetInventory
->getInventory($asset, 'time', $unit2
->id());
$this
->assertEquals('time', $inventory[0]['measure'], 'Asset inventory has a measure of time.');
$this
->assertEquals('hours', $inventory[0]['units'], 'Asset inventory has units in hours.');
$this
->assertEquals('2', $inventory[0]['value'], 'Asset inventory is 2.');
$inventory = $this->assetInventory
->getInventory($asset, 'volume', $unit1
->id());
$this
->assertEquals('volume', $inventory[0]['measure'], 'Asset inventory has a measure of volume.');
$this
->assertEquals('liters', $inventory[0]['units'], 'Asset inventory has units in liters.');
$this
->assertEquals('1', $inventory[0]['value'], 'Asset inventory is 1.');
$inventory = $this->assetInventory
->getInventory($asset, 'volume', 0);
$this
->assertEquals(1, count($inventory), 'Asset has a single volume inventory.');
$inventory = $this->assetInventory
->getInventory($asset, '', $unit2
->id());
$this
->assertEquals(1, count($inventory), 'Asset has a single liters inventory.');
$this
->adjustInventory($asset, 'increment', '4', 'volume', $unit1
->id());
$inventory = $this->assetInventory
->getInventory($asset, 'volume', $unit1
->id());
$this
->assertEquals('5', $inventory[0]['value'], 'Asset inventory is 5.');
}
protected function adjustInventory(AssetInterface $asset, string $adjustment, string $value, string $measure = '', int $units = 0) {
$fraction = Fraction::createFromDecimal($value);
$quantity = Quantity::create([
'type' => 'standard',
'value' => [
'numerator' => $fraction
->getNumerator(),
'denominator' => $fraction
->getDenominator(),
],
'inventory_adjustment' => $adjustment,
'inventory_asset' => [
'target_id' => $asset
->id(),
],
]);
if (!empty($measure)) {
$quantity
->set('measure', $measure);
}
if (!empty($units)) {
$quantity
->set('units', [
'target_id' => $units,
]);
}
$quantity
->save();
$log = Log::create([
'type' => 'adjustment',
'status' => 'done',
'quantity' => [
'target_id' => $quantity
->id(),
'target_revision_id' => $quantity
->getRevisionId(),
],
]);
$log
->save();
return $log;
}
}