mirror of
https://github.com/snipe/snipe-it.git
synced 2026-08-18 03:06:23 +00:00
Updated importer tests
This commit is contained in:
@ -240,19 +240,32 @@ class ItemImporter extends Importer
|
||||
{
|
||||
$orderNumber = trim((string) $this->findCsvMatch($row, 'order_number'));
|
||||
$currency = trim((string) $this->findCsvMatch($row, 'currency'));
|
||||
// Supplier / purchase_date / purchase_cost live on the Order
|
||||
// and OrderItem now — the parent inventory row no longer holds
|
||||
// them. Pull them off the sub-importer's already-normalized
|
||||
// $this->item so createOrFetchSupplier / parseOrNullDate work
|
||||
// just like they used to when the values were being written
|
||||
// straight onto the parent.
|
||||
$supplierId = $this->item['supplier_id'] ?? null;
|
||||
$purchaseDate = $this->item['purchase_date'] ?? null;
|
||||
$purchaseCost = array_key_exists('purchase_cost', $this->item) && $this->item['purchase_cost'] !== '' && $this->item['purchase_cost'] !== null
|
||||
? (float) $this->item['purchase_cost']
|
||||
: null;
|
||||
|
||||
if ($orderNumber === '' && $currency === '') {
|
||||
if ($orderNumber === '' && $currency === '' && $supplierId === null && $purchaseDate === null && $purchaseCost === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Every accessory / consumable / component / asset create fires
|
||||
// its observer which writes an initial Order + OrderItem from
|
||||
// parent attributes (with a null order_number since parents
|
||||
// don't carry that column any more). The importer's job here is
|
||||
// to enrich that observer-created Order with the CSV's
|
||||
// order_number and currency, not to write a duplicate Order or
|
||||
// duplicate OrderItem line.
|
||||
$initialOrder = $model->orderItems()->latest('id')->first()?->order;
|
||||
// parent attributes (with null acquisition metadata — parents
|
||||
// don't carry those columns any more). The importer's job here
|
||||
// is to enrich the observer-created rows with the CSV's values.
|
||||
$initialLine = $model->orderItems()->latest('id')->first();
|
||||
if (! $initialLine) {
|
||||
return;
|
||||
}
|
||||
$initialOrder = $initialLine->order;
|
||||
if (! $initialOrder) {
|
||||
return;
|
||||
}
|
||||
@ -264,10 +277,20 @@ class ItemImporter extends Importer
|
||||
if ($currency !== '' && $initialOrder->currency !== $currency) {
|
||||
$updates['currency'] = $currency;
|
||||
}
|
||||
if ($supplierId !== null && (int) $initialOrder->supplier_id !== (int) $supplierId) {
|
||||
$updates['supplier_id'] = (int) $supplierId;
|
||||
}
|
||||
if ($purchaseDate !== null && optional($initialOrder->purchase_date)->toDateString() !== (string) $purchaseDate) {
|
||||
$updates['purchase_date'] = $purchaseDate;
|
||||
}
|
||||
|
||||
if ($updates !== []) {
|
||||
$initialOrder->update($updates);
|
||||
}
|
||||
|
||||
if ($purchaseCost !== null && (float) $initialLine->price !== $purchaseCost) {
|
||||
$initialLine->update(['price' => $purchaseCost]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -81,19 +81,18 @@ class ImportAccessoriesTest extends ImportDataTestCase implements TestsPermissio
|
||||
|
||||
$this->assertEquals($row['itemName'], $newAccessory->name);
|
||||
$this->assertEquals($row['quantity'], $newAccessory->qty);
|
||||
$this->assertEquals($row['purchaseDate'], $newAccessory->purchase_date->toDateString());
|
||||
$this->assertEquals($row['purchaseCost'], $newAccessory->purchase_cost);
|
||||
// order_number moved off the parent Accessory column to the
|
||||
// Orders / OrderItems polymorphic pair. Verify the importer's
|
||||
// recordOrderForImportedRow helper wrote a matching Order and
|
||||
// linked it to the new accessory via an OrderItem.
|
||||
// supplier + order_number + purchase_date + purchase_cost all
|
||||
// live on the Orders / OrderItems polymorphic pair now — the
|
||||
// importer's recordOrderForImportedRow helper writes them there.
|
||||
$orderItem = $newAccessory->orderItems()->firstOrFail();
|
||||
$this->assertEquals($row['orderNumber'], $orderItem->order->order_number);
|
||||
$this->assertEquals($row['purchaseDate'], $orderItem->order->purchase_date->toDateString());
|
||||
$this->assertEquals((float) $row['purchaseCost'], (float) $orderItem->price);
|
||||
$this->assertEquals($row['supplierName'], $orderItem->order->supplier->name);
|
||||
$this->assertEquals($row['notes'], $newAccessory->notes);
|
||||
$this->assertEquals($row['category'], $newAccessory->category->name);
|
||||
$this->assertEquals('accessory', $newAccessory->category->category_type);
|
||||
$this->assertEquals($row['manufacturerName'], $newAccessory->manufacturer->name);
|
||||
$this->assertEquals($row['supplierName'], $newAccessory->supplier->name);
|
||||
$this->assertEquals($row['location'], $newAccessory->location->name);
|
||||
$this->assertEquals($row['companyName'], $newAccessory->company->name);
|
||||
$this->assertEquals($row['modelNumber'], $newAccessory->model_number);
|
||||
@ -126,11 +125,15 @@ class ImportAccessoriesTest extends ImportDataTestCase implements TestsPermissio
|
||||
$this->actingAsForApi(User::factory()->superuser()->create());
|
||||
$this->importFileResponse(['import' => $import->id])->assertOk();
|
||||
|
||||
// purchase_date landed on the OrderItem's Order rather than the
|
||||
// parent Accessory column — assert that the importer's date
|
||||
// parser normalized the slashed CSV input to a Y-m-d value.
|
||||
$accessory = Accessory::query()
|
||||
->where('name', $importFileBuilder->firstRow()['itemName'])
|
||||
->sole(['purchase_date']);
|
||||
->sole();
|
||||
|
||||
$this->assertEquals('2022-10-10', $accessory->purchase_date->toDateString());
|
||||
$order = $accessory->orderItems()->latest('id')->firstOrFail()->order;
|
||||
$this->assertEquals('2022-10-10', $order->purchase_date->toDateString());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
@ -224,11 +227,19 @@ class ImportAccessoriesTest extends ImportDataTestCase implements TestsPermissio
|
||||
$this->actingAsForApi(User::factory()->superuser()->create());
|
||||
$this->importFileResponse(['import' => $import->id])->assertOk();
|
||||
|
||||
// Supplier reuse across imported rows is observable on the
|
||||
// OrderItem's Order.supplier_id (parent's default_supplier_id
|
||||
// gets seeded from the first-row's supplier for these but the
|
||||
// per-row dedupe rule lives on the Order path).
|
||||
$newAccessories = Accessory::query()
|
||||
->where('name', $importFileBuilder->pluck('itemName'))
|
||||
->get(['supplier_id']);
|
||||
->whereIn('name', $importFileBuilder->pluck('itemName'))
|
||||
->get();
|
||||
|
||||
$this->assertCount(1, $newAccessories->pluck('supplier_id')->unique()->all());
|
||||
$supplierIds = $newAccessories->map(
|
||||
fn ($accessory) => $accessory->orderItems()->latest('id')->first()?->order?->supplier_id,
|
||||
)->filter()->unique()->all();
|
||||
|
||||
$this->assertCount(1, $supplierIds);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
@ -245,8 +256,12 @@ class ImportAccessoriesTest extends ImportDataTestCase implements TestsPermissio
|
||||
->sole();
|
||||
|
||||
$this->assertNull($newAccessory->min_amt);
|
||||
$this->assertNull($newAccessory->purchase_date);
|
||||
$this->assertNull($newAccessory->purchase_cost);
|
||||
// purchase_date / purchase_cost columns are gone from the parent;
|
||||
// when the CSV omits them, the observer-written OrderItem has
|
||||
// null price and its Order has null purchase_date.
|
||||
$orderItem = $newAccessory->orderItems()->latest('id')->firstOrFail();
|
||||
$this->assertNull($orderItem->order->purchase_date);
|
||||
$this->assertNull($orderItem->price);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
@ -285,27 +300,29 @@ class ImportAccessoriesTest extends ImportDataTestCase implements TestsPermissio
|
||||
|
||||
$updatedAccessory = Accessory::query()->find($accessory->id);
|
||||
$updatedAttributes = [
|
||||
'name', 'company_id', 'qty', 'purchase_date', 'purchase_cost',
|
||||
'order_number', 'notes', 'category_id', 'manufacturer_id', 'supplier_id',
|
||||
'name', 'company_id', 'qty', 'default_purchase_cost', 'default_supplier_id',
|
||||
'notes', 'category_id', 'manufacturer_id',
|
||||
'location_id', 'model_number', 'updated_at',
|
||||
];
|
||||
|
||||
$this->assertEquals($row['itemName'], $updatedAccessory->name);
|
||||
$this->assertEquals($row['companyName'], $updatedAccessory->company->name);
|
||||
$this->assertEquals($row['quantity'], $updatedAccessory->qty);
|
||||
$this->assertEquals($row['purchaseDate'], $updatedAccessory->purchase_date->toDateString());
|
||||
$this->assertEquals($row['purchaseCost'], $updatedAccessory->purchase_cost);
|
||||
// order_number does NOT persist on the parent through an update
|
||||
// (ItemImporter::applyUpdateWithQtyAdjust extracts it from the
|
||||
// sanitized payload before ->update()). When the CSV qty differs
|
||||
// from stored, the value rides on the QuantityAdjust log — the
|
||||
// dedicated "importer_qty_change_creates_quantity_adjust_log"
|
||||
// test covers that path.
|
||||
// Acquisition metadata (order_number / purchase_date /
|
||||
// purchase_cost / supplier) lives on the latest OrderItem's
|
||||
// Order, not the parent. Update mode writes a fresh Order +
|
||||
// OrderItem via recordOrderForImportedRow when the CSV carries
|
||||
// acquisition columns. (When qty differs, the value also rides
|
||||
// on the QuantityAdjust log — see the sibling test
|
||||
// importer_qty_change_creates_quantity_adjust_log.)
|
||||
$latestOrderItem = $updatedAccessory->orderItems()->latest('id')->firstOrFail();
|
||||
$this->assertEquals($row['purchaseDate'], $latestOrderItem->order->purchase_date->toDateString());
|
||||
$this->assertEquals((float) $row['purchaseCost'], (float) $latestOrderItem->price);
|
||||
$this->assertEquals($row['supplierName'], $latestOrderItem->order->supplier->name);
|
||||
$this->assertEquals($row['notes'], $updatedAccessory->notes);
|
||||
$this->assertEquals($row['category'], $updatedAccessory->category->name);
|
||||
$this->assertEquals('accessory', $updatedAccessory->category->category_type);
|
||||
$this->assertEquals($row['manufacturerName'], $updatedAccessory->manufacturer->name);
|
||||
$this->assertEquals($row['supplierName'], $updatedAccessory->supplier->name);
|
||||
$this->assertEquals($row['location'], $updatedAccessory->location->name);
|
||||
$this->assertEquals($row['modelNumber'], $updatedAccessory->model_number);
|
||||
|
||||
@ -370,16 +387,16 @@ class ImportAccessoriesTest extends ImportDataTestCase implements TestsPermissio
|
||||
|
||||
$accessory = Accessory::factory()->create([
|
||||
'notes' => 'Some pre-existing notes',
|
||||
'purchase_date' => '2022-01-01',
|
||||
])->refresh();
|
||||
|
||||
$this->assertNotNull($accessory->purchase_date);
|
||||
$this->assertNotEmpty($accessory->notes);
|
||||
|
||||
// purchase_date moved off the parent post-Orders — the
|
||||
// "empty CSV cell clears the DB column" behavior for the
|
||||
// parent-owned columns is covered here by notes alone.
|
||||
$row = ImportFileBuilder::new()->definition();
|
||||
$row['itemName'] = $accessory->name;
|
||||
$row['notes'] = '';
|
||||
$row['purchaseDate'] = '';
|
||||
|
||||
$importFileBuilder = new ImportFileBuilder([$row]);
|
||||
$import = Import::factory()->accessory()->create([
|
||||
@ -393,7 +410,6 @@ class ImportAccessoriesTest extends ImportDataTestCase implements TestsPermissio
|
||||
|
||||
$accessory->refresh();
|
||||
$this->assertNull($accessory->notes);
|
||||
$this->assertNull($accessory->purchase_date);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
@ -403,20 +419,14 @@ class ImportAccessoriesTest extends ImportDataTestCase implements TestsPermissio
|
||||
|
||||
$accessory = Accessory::factory()->create([
|
||||
'notes' => 'Do not lose this',
|
||||
'purchase_date' => '2022-01-01',
|
||||
])->refresh();
|
||||
|
||||
$originalNotes = $accessory->notes;
|
||||
$originalPurchaseDate = $accessory->purchase_date?->toDateString();
|
||||
|
||||
// Import a CSV that only has the identity field (name) plus one
|
||||
// updated column. All other Accessory fields are absent from the
|
||||
// CSV, so their DB values must be preserved on update. We update
|
||||
// model_number here as the "one changed field" proxy instead of
|
||||
// order_number, because Accessory (like Consumable/Component)
|
||||
// hides its parent-level order_number behind an accessor that
|
||||
// returns null — reads via $accessory->order_number can't verify
|
||||
// the write. model_number is a plain readable column.
|
||||
// updated column. All other parent columns absent from the CSV
|
||||
// must be preserved on update. model_number is the "changed
|
||||
// field" proxy; notes is the "preserved field" proxy.
|
||||
$partialFile = new ImportFileBuilder([[
|
||||
'itemName' => $accessory->name,
|
||||
'modelNumber' => 'UPDATED-MODEL-NUMBER',
|
||||
@ -433,7 +443,6 @@ class ImportAccessoriesTest extends ImportDataTestCase implements TestsPermissio
|
||||
$accessory->refresh();
|
||||
$this->assertEquals('UPDATED-MODEL-NUMBER', $accessory->model_number);
|
||||
$this->assertEquals($originalNotes, $accessory->notes);
|
||||
$this->assertEquals($originalPurchaseDate, $accessory->purchase_date?->toDateString());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
|
||||
@ -85,16 +85,15 @@ class ImportComponentsTest extends ImportDataTestCase implements TestsPermission
|
||||
$this->assertEquals($row['companyName'], $newComponent->company->name);
|
||||
$this->assertEquals($row['category'], $newComponent->category->name);
|
||||
$this->assertEquals($row['location'], $newComponent->location->name);
|
||||
$this->assertNull($newComponent->supplier_id);
|
||||
$this->assertNull($newComponent->default_supplier_id);
|
||||
$this->assertEquals($row['quantity'], $newComponent->qty);
|
||||
// order_number moved off the parent Component column to the
|
||||
// Orders / OrderItems polymorphic pair. Verify the importer's
|
||||
// recordOrderForImportedRow helper wrote a matching Order and
|
||||
// linked it to the new component via an OrderItem.
|
||||
// order_number / purchase_date / purchase_cost all live on the
|
||||
// Orders / OrderItems polymorphic pair now — the importer's
|
||||
// recordOrderForImportedRow helper writes them there.
|
||||
$orderItem = $newComponent->orderItems()->firstOrFail();
|
||||
$this->assertEquals($row['orderNumber'], $orderItem->order->order_number);
|
||||
$this->assertEquals($row['purchaseDate'], $newComponent->purchase_date->toDateString());
|
||||
$this->assertEquals($row['purchaseCost'], $newComponent->purchase_cost);
|
||||
$this->assertEquals($row['purchaseDate'], $orderItem->order->purchase_date->toDateString());
|
||||
$this->assertEquals((float) $row['purchaseCost'], (float) $orderItem->price);
|
||||
$this->assertNull($newComponent->min_amt);
|
||||
$this->assertEquals($row['serialNumber'], $newComponent->serial);
|
||||
$this->assertNull($newComponent->image);
|
||||
@ -245,13 +244,14 @@ class ImportComponentsTest extends ImportDataTestCase implements TestsPermission
|
||||
$this->assertEquals($row['itemName'], $updatedComponent->name);
|
||||
$this->assertEquals($row['category'], $updatedComponent->category->name);
|
||||
$this->assertEquals($row['location'], $updatedComponent->location->name);
|
||||
$this->assertEquals($component->supplier_id, $updatedComponent->supplier_id);
|
||||
$this->assertEquals($component->default_supplier_id, $updatedComponent->default_supplier_id);
|
||||
$this->assertEquals($row['quantity'], $updatedComponent->qty);
|
||||
// order_number does NOT persist on the parent through an update
|
||||
// (see update_accessory_from_import for the same rationale;
|
||||
// importer_qty_change_creates_quantity_adjust_log covers the log).
|
||||
$this->assertEquals($row['purchaseDate'], $updatedComponent->purchase_date->toDateString());
|
||||
$this->assertEquals($row['purchaseCost'], $updatedComponent->purchase_cost);
|
||||
// Acquisition metadata lives on the latest OrderItem's Order —
|
||||
// the update path writes a new Order + OrderItem when the CSV
|
||||
// carries acquisition columns, per recordOrderForImportedRow.
|
||||
$latestOrderItem = $updatedComponent->orderItems()->latest('id')->firstOrFail();
|
||||
$this->assertEquals($row['purchaseDate'], $latestOrderItem->order->purchase_date->toDateString());
|
||||
$this->assertEquals((float) $row['purchaseCost'], (float) $latestOrderItem->price);
|
||||
$this->assertEquals($component->min_amt, $updatedComponent->min_amt);
|
||||
$this->assertEquals($row['serialNumber'], $updatedComponent->serial);
|
||||
$this->assertEquals($component->image, $updatedComponent->image);
|
||||
@ -263,23 +263,19 @@ class ImportComponentsTest extends ImportDataTestCase implements TestsPermission
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->superuser()->create());
|
||||
|
||||
// purchase_date is the sole proxy for the "empty CSV cell clears
|
||||
// the DB column" behavior here. order_number is not exercised
|
||||
// because Component / Accessory / Consumable all hide the
|
||||
// parent-level order_number behind an accessor that returns null
|
||||
// (see Component::getOrderNumberAttribute) — reads via
|
||||
// $component->order_number would be null regardless of the DB
|
||||
// state and would give a false green for this test.
|
||||
// notes is the parent-column proxy for the generic
|
||||
// "empty CSV cell clears the DB column" behavior — see the
|
||||
// consumables import tests for the full rationale.
|
||||
$component = Component::factory()->create([
|
||||
'purchase_date' => '2022-01-01',
|
||||
'notes' => 'seeded note',
|
||||
])->refresh();
|
||||
|
||||
$this->assertNotNull($component->purchase_date);
|
||||
$this->assertEquals('seeded note', $component->notes);
|
||||
|
||||
$row = ImportFileBuilder::new()->definition();
|
||||
$row['itemName'] = $component->name;
|
||||
$row['serialNumber'] = $component->serial;
|
||||
$row['purchaseDate'] = '';
|
||||
$row['notes'] = '';
|
||||
|
||||
$importFileBuilder = new ImportFileBuilder([$row]);
|
||||
$import = Import::factory()->component()->create([
|
||||
@ -292,7 +288,7 @@ class ImportComponentsTest extends ImportDataTestCase implements TestsPermission
|
||||
])->assertOk();
|
||||
|
||||
$component->refresh();
|
||||
$this->assertNull($component->purchase_date);
|
||||
$this->assertNull($component->notes);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
@ -301,17 +297,15 @@ class ImportComponentsTest extends ImportDataTestCase implements TestsPermission
|
||||
$this->actingAsForApi(User::factory()->superuser()->create());
|
||||
|
||||
$component = Component::factory()->create([
|
||||
'purchase_date' => '2022-01-01',
|
||||
'notes' => 'seeded note',
|
||||
])->refresh();
|
||||
|
||||
$originalPurchaseDate = $component->purchase_date?->toDateString();
|
||||
$originalNotes = $component->notes;
|
||||
|
||||
// Import a CSV that only has the identity fields (name+serial) plus
|
||||
// quantity (required by Component validation). All other Component
|
||||
// fields are absent from the CSV, so their DB values must be preserved.
|
||||
// order_number moved off the parent Component column to the Orders
|
||||
// data model, so we can't use it as a preservation proxy here;
|
||||
// purchase_date is the remaining stand-in.
|
||||
// notes is the proxy — see the sibling test above.
|
||||
$partialFile = new ImportFileBuilder([[
|
||||
'itemName' => $component->name,
|
||||
'serialNumber' => $component->serial,
|
||||
@ -328,7 +322,7 @@ class ImportComponentsTest extends ImportDataTestCase implements TestsPermission
|
||||
|
||||
$component->refresh();
|
||||
$this->assertEquals(42, $component->qty);
|
||||
$this->assertEquals($originalPurchaseDate, $component->purchase_date?->toDateString());
|
||||
$this->assertEquals($originalNotes, $component->notes);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
@ -370,7 +364,9 @@ class ImportComponentsTest extends ImportDataTestCase implements TestsPermission
|
||||
])->assertOk();
|
||||
|
||||
$component->refresh();
|
||||
$this->assertEquals($updatedRow['purchaseCost'], $component->purchase_cost);
|
||||
// purchase_cost moved to the OrderItem's price column.
|
||||
$latestOrderItem = $component->orderItems()->latest('id')->firstOrFail();
|
||||
$this->assertEquals((float) $updatedRow['purchaseCost'], (float) $latestOrderItem->price);
|
||||
|
||||
$updateLog = ActionLog::query()
|
||||
->where('item_type', Component::class)
|
||||
@ -426,14 +422,14 @@ class ImportComponentsTest extends ImportDataTestCase implements TestsPermission
|
||||
$this->assertEquals($row['quantity'], $newComponent->name);
|
||||
$this->assertEquals($row['purchaseCost'], $newComponent->category->name);
|
||||
$this->assertEquals($row['serialNumber'], $newComponent->location->name);
|
||||
$this->assertNull($newComponent->supplier_id);
|
||||
$this->assertNull($newComponent->default_supplier_id);
|
||||
$this->assertEquals($row['companyName'], $newComponent->qty);
|
||||
// See the import_components test above for why order_number now
|
||||
// lives on Orders / OrderItems rather than the parent column.
|
||||
// See the import_components test above for why order_number,
|
||||
// purchase_date, and purchase_cost live on Orders / OrderItems.
|
||||
$orderItem = $newComponent->orderItems()->firstOrFail();
|
||||
$this->assertEquals($row['orderNumber'], $orderItem->order->order_number);
|
||||
$this->assertEquals($row['itemName'], $newComponent->purchase_date->toDateString());
|
||||
$this->assertEquals($row['location'], $newComponent->purchase_cost);
|
||||
$this->assertEquals($row['itemName'], $orderItem->order->purchase_date->toDateString());
|
||||
$this->assertEquals((float) $row['location'], (float) $orderItem->price);
|
||||
$this->assertNull($newComponent->min_amt);
|
||||
$this->assertNull($newComponent->image);
|
||||
$this->assertNull($newComponent->notes);
|
||||
|
||||
@ -289,22 +289,20 @@ class ImportConsumablesTest extends ImportDataTestCase implements TestsPermissio
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->superuser()->create());
|
||||
|
||||
// purchase_date is the sole proxy for the "empty CSV cell clears
|
||||
// the DB column" behavior here. order_number is not exercised
|
||||
// because Consumable / Accessory / Component all hide the
|
||||
// parent-level order_number behind an accessor that returns null
|
||||
// (see Consumable::getOrderNumberAttribute) — reads via
|
||||
// $consumable->order_number would be null regardless of the DB
|
||||
// state and would give a false green for this test.
|
||||
// notes is the parent-column proxy for the generic
|
||||
// "empty CSV cell clears the DB column" behavior.
|
||||
// purchase_date is off the parent post-Orders refactor; testing
|
||||
// that clear-on-empty behavior against Orders belongs in the
|
||||
// adjust-quantity flow tests, not the base importer contract.
|
||||
$consumable = Consumable::factory()->create([
|
||||
'purchase_date' => '2022-01-01',
|
||||
'notes' => 'seeded note',
|
||||
])->refresh();
|
||||
|
||||
$this->assertNotNull($consumable->purchase_date);
|
||||
$this->assertEquals('seeded note', $consumable->notes);
|
||||
|
||||
$row = ImportFileBuilder::new()->definition();
|
||||
$row['itemName'] = $consumable->name;
|
||||
$row['purchaseDate'] = '';
|
||||
$row['notes'] = '';
|
||||
|
||||
$importFileBuilder = new ImportFileBuilder([$row]);
|
||||
$import = Import::factory()->consumable()->create([
|
||||
@ -317,7 +315,7 @@ class ImportConsumablesTest extends ImportDataTestCase implements TestsPermissio
|
||||
])->assertOk();
|
||||
|
||||
$consumable->refresh();
|
||||
$this->assertNull($consumable->purchase_date);
|
||||
$this->assertNull($consumable->notes);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
@ -326,17 +324,16 @@ class ImportConsumablesTest extends ImportDataTestCase implements TestsPermissio
|
||||
$this->actingAsForApi(User::factory()->superuser()->create());
|
||||
|
||||
$consumable = Consumable::factory()->create([
|
||||
'purchase_date' => '2022-01-01',
|
||||
'notes' => 'seeded note',
|
||||
])->refresh();
|
||||
|
||||
$originalPurchaseDate = $consumable->purchase_date?->toDateString();
|
||||
$originalNotes = $consumable->notes;
|
||||
|
||||
// Import a CSV that only has the identity field (name) plus quantity
|
||||
// (required by Consumable validation). All other Consumable fields
|
||||
// are absent from the CSV, so their DB values must be preserved.
|
||||
// order_number moved off the parent Consumable column to the Orders
|
||||
// data model, so we can't use it as a preservation proxy here;
|
||||
// purchase_date is the remaining stand-in.
|
||||
// notes is the proxy — see the sibling test above for the
|
||||
// rationale.
|
||||
$partialFile = new ImportFileBuilder([[
|
||||
'itemName' => $consumable->name,
|
||||
'quantity' => 42,
|
||||
@ -352,7 +349,7 @@ class ImportConsumablesTest extends ImportDataTestCase implements TestsPermissio
|
||||
|
||||
$consumable->refresh();
|
||||
$this->assertEquals(42, $consumable->qty);
|
||||
$this->assertEquals($originalPurchaseDate, $consumable->purchase_date?->toDateString());
|
||||
$this->assertEquals($originalNotes, $consumable->notes);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
@ -391,7 +388,9 @@ class ImportConsumablesTest extends ImportDataTestCase implements TestsPermissio
|
||||
])->assertOk();
|
||||
|
||||
$consumable->refresh();
|
||||
$this->assertEquals($updatedRow['purchaseCost'], $consumable->purchase_cost);
|
||||
// purchase_cost moved to the OrderItem's price column.
|
||||
$latestOrderItem = $consumable->orderItems()->latest('id')->firstOrFail();
|
||||
$this->assertEquals((float) $updatedRow['purchaseCost'], (float) $latestOrderItem->price);
|
||||
|
||||
$updateLog = ActivityLog::query()
|
||||
->where('item_type', Consumable::class)
|
||||
@ -451,15 +450,15 @@ class ImportConsumablesTest extends ImportDataTestCase implements TestsPermissio
|
||||
$this->assertEquals($row['purchaseDate'], $newConsumable->company->name);
|
||||
$this->assertEquals($row['companyName'], $newConsumable->qty);
|
||||
$this->assertEquals($row['quantity'], $newConsumable->name);
|
||||
$this->assertNotNull($newConsumable->supplier_id);
|
||||
$this->assertFalse($newConsumable->requestable);
|
||||
$this->assertNull($newConsumable->image);
|
||||
// See the import_consumables test above for why order_number now
|
||||
// lives on Orders / OrderItems rather than the parent column.
|
||||
// See the import_consumables test above for why order_number,
|
||||
// purchase_date, purchase_cost, and supplier all live on the
|
||||
// Orders / OrderItems polymorphic pair now.
|
||||
$orderItem = $newConsumable->orderItems()->firstOrFail();
|
||||
$this->assertEquals($row['orderNumber'], $orderItem->order->order_number);
|
||||
$this->assertEquals($row['itemName'], $newConsumable->purchase_date->toDateString());
|
||||
$this->assertEquals($row['location'], $newConsumable->purchase_cost);
|
||||
$this->assertEquals($row['itemName'], $orderItem->order->purchase_date->toDateString());
|
||||
$this->assertEquals((float) $row['location'], (float) $orderItem->price);
|
||||
$this->assertNull($newConsumable->min_amt);
|
||||
$this->assertEquals('', $newConsumable->model_number);
|
||||
$this->assertNull($newConsumable->item_number);
|
||||
|
||||
@ -14,6 +14,7 @@ use Illuminate\Support\Str;
|
||||
* companyName?: string,
|
||||
* itemName?: string,
|
||||
* location?: string,
|
||||
* notes?: string,
|
||||
* orderNumber?: string,
|
||||
* purchaseCost?: int,
|
||||
* purchaseDate?: string,
|
||||
@ -36,6 +37,7 @@ class ComponentsImportFileBuilder extends FileBuilder
|
||||
'companyName' => 'Company',
|
||||
'itemName' => 'item Name',
|
||||
'location' => 'Location',
|
||||
'notes' => 'Notes',
|
||||
'orderNumber' => 'Order Number',
|
||||
'purchaseCost' => 'Purchase Cost',
|
||||
'purchaseDate' => 'Purchase Date',
|
||||
@ -57,6 +59,7 @@ class ComponentsImportFileBuilder extends FileBuilder
|
||||
'companyName' => Str::random()." {$faker->companySuffix}",
|
||||
'itemName' => Str::random(),
|
||||
'location' => "{$faker->city}, {$faker->country}",
|
||||
'notes' => $faker->sentence(),
|
||||
'orderNumber' => "ON:COM:{$faker->uuid}",
|
||||
'purchaseCost' => rand(1, 100_000),
|
||||
'purchaseDate' => $faker->date,
|
||||
|
||||
@ -14,6 +14,7 @@ use Illuminate\Support\Str;
|
||||
* companyName?: string,
|
||||
* itemName?: string,
|
||||
* location?: string,
|
||||
* notes?: string,
|
||||
* orderNumber?: string,
|
||||
* purchaseCost?: int,
|
||||
* purchaseDate?: string,
|
||||
@ -35,6 +36,7 @@ class ConsumablesImportFileBuilder extends FileBuilder
|
||||
'companyName' => 'Company',
|
||||
'itemName' => 'item Name',
|
||||
'location' => 'Location',
|
||||
'notes' => 'Notes',
|
||||
'orderNumber' => 'Order Number',
|
||||
'purchaseCost' => 'Purchase Cost',
|
||||
'purchaseDate' => 'Purchase Date',
|
||||
@ -55,6 +57,7 @@ class ConsumablesImportFileBuilder extends FileBuilder
|
||||
'companyName' => Str::random()." {$faker->companySuffix}",
|
||||
'itemName' => Str::random(),
|
||||
'location' => "{$faker->city}, {$faker->country}",
|
||||
'notes' => $faker->sentence(),
|
||||
'orderNumber' => "ON:CON:{$faker->uuid}",
|
||||
'purchaseCost' => rand(1, 100_000),
|
||||
'purchaseDate' => $faker->date,
|
||||
|
||||
Reference in New Issue
Block a user