Initial commit: Inventory Barcode System

This commit is contained in:
2025-07-22 20:24:51 -04:00
commit 511b01748d
63 changed files with 26932 additions and 0 deletions

View File

@ -0,0 +1,165 @@
const Inventory = require('../models/Inventory');
describe('Inventory Model - Basic Tests', () => {
test('should create inventory instance', () => {
const inventory = new Inventory({
product_id: 1,
current_level: 50,
minimum_level: 10,
updated_by: 'testuser'
});
expect(inventory.product_id).toBe(1);
expect(inventory.current_level).toBe(50);
expect(inventory.minimum_level).toBe(10);
expect(inventory.updated_by).toBe('testuser');
});
test('should validate required product_id', () => {
const inventory = new Inventory({
current_level: 50,
minimum_level: 10
});
const validation = inventory.validate();
expect(validation.isValid).toBe(false);
expect(validation.errors).toContain('Product ID is required and must be a number');
});
test('should validate current_level is non-negative', () => {
const inventory = new Inventory({
product_id: 1,
current_level: -5,
minimum_level: 10
});
const validation = inventory.validate();
expect(validation.isValid).toBe(false);
expect(validation.errors).toContain('Current level must be a non-negative number');
});
test('should pass validation with valid data', () => {
const inventory = new Inventory({
product_id: 1,
current_level: 50,
minimum_level: 10,
maximum_level: 100,
updated_by: 'testuser'
});
const validation = inventory.validate();
expect(validation.isValid).toBe(true);
expect(validation.errors).toHaveLength(0);
});
test('should convert to JSON', () => {
const inventoryData = {
id: 1,
product_id: 1,
current_level: 50,
minimum_level: 10,
maximum_level: 100,
last_updated: '2023-01-01 00:00:00',
updated_by: 'testuser',
version: 1
};
const inventory = new Inventory(inventoryData);
const json = inventory.toJSON();
expect(json).toEqual(inventoryData);
});
});
describe('Inventory Model - Database Tests', () => {
const database = require('../models/database');
let testProduct;
beforeAll(async () => {
// Initialize database for testing
database.initialize();
});
afterAll(() => {
// Close database connection
database.close();
});
beforeEach(() => {
// Clear tables before each test
const db = database.getDatabase();
db.exec('DELETE FROM inventory_history');
db.exec('DELETE FROM inventory');
db.exec('DELETE FROM products');
// Create a test product
const insertStmt = db.prepare(`
INSERT INTO products (product_code, description, category, unit_of_measure)
VALUES (?, ?, ?, ?)
`);
const result = insertStmt.run('TEST001', 'Test Product', 'Electronics', 'pieces');
testProduct = { id: result.lastInsertRowid, product_code: 'TEST001' };
});
test('should create inventory record for a product', async () => {
const inventory = await Inventory.createForProduct(
testProduct.id,
100,
10,
200,
'testuser'
);
expect(inventory.product_id).toBe(testProduct.id);
expect(inventory.current_level).toBe(100);
expect(inventory.minimum_level).toBe(10);
expect(inventory.maximum_level).toBe(200);
expect(inventory.updated_by).toBe('testuser');
expect(inventory.id).toBeDefined();
});
test('should update inventory level and create audit record', async () => {
// Create initial inventory
await Inventory.createForProduct(testProduct.id, 100, 10, 200, 'system');
const updatedInventory = await Inventory.updateInventoryLevel(
testProduct.id,
150,
'Restocking from supplier',
'testuser'
);
expect(updatedInventory.product_id).toBe(testProduct.id);
expect(updatedInventory.current_level).toBe(150);
expect(updatedInventory.updated_by).toBe('testuser');
expect(updatedInventory.version).toBe(2); // Version should increment
// Verify audit trail was created
const history = await Inventory.getInventoryHistory(testProduct.id);
expect(history).toHaveLength(2); // Initial creation + update
expect(history[0].old_level).toBe(100);
expect(history[0].new_level).toBe(150);
expect(history[0].change_reason).toBe('Restocking from supplier');
expect(history[0].updated_by).toBe('testuser');
});
test('should handle concurrent updates with optimistic locking', async () => {
// Create initial inventory
await Inventory.createForProduct(testProduct.id, 100, 10, 200, 'system');
// Simulate concurrent access by getting the same record twice
const inventory1 = await Inventory.getByProductId(testProduct.id);
const inventory2 = await Inventory.getByProductId(testProduct.id);
// First update should succeed
inventory1.current_level = 120;
inventory1.updated_by = 'user1';
await inventory1.save();
// Second update should fail due to version mismatch
inventory2.current_level = 110;
inventory2.updated_by = 'user2';
await expect(inventory2.save()).rejects.toThrow('Concurrent update detected');
});
});