// Evidence Dossier
3DFAB Inventory System
Inventory for the 3DFAB workshop: components by location, stock movements, work-order materials and replenishment alerts. Full in-house development and active operation; this case study separates production use from local verification.
- Who it serves
3DFAB workshop: physical components, storage locations and materials used in manufacturing jobs.
- My responsibility
Complete development: data model, Django backend, interface, QR labels, reports, tests and documentation. Fully designed and built by me.
- Current status
Operational in active production. Verified in an isolated local copy with SQLite and synthetic data; production was not inspected.
- What it enables
Look up stock, record material use and identify replenishment needs. No verified savings, performance or availability metrics.
Context
3DFAB works with physical components and manufacturing materials. Inventory links each part to its category, primary location, available quantity and replenishment threshold. Work orders associate material use with a specific job.
I built the complete system and it is currently operational. No confirmed user count or real-use measurements are available; execution described here took place in a local laboratory.
Problem
A quantity alone does not explain where a component is stored or which operation changed it. The domain problem is to bring together catalog, location, movements and job consumption, while highlighting stock needing replenishment.
Consistency requires distinguishing pending from applied movements and checking repeated or simultaneous operations. An available history does not establish that every physical balance has a documented opening movement.
My role
I designed and developed the complete Django solution: models and relationships, forms, views, stock rules, interface, QR labels, alerts, reports, tests and documentation. Attribution comes from my confirmation, not from inferring responsibilities through Git.
This case-study review inspects and tests a product copy. It does not incorporate functional repairs into the source repository.
Constraints
Validation had to run locally without touching workshop data or services. Credentials, the existing database, uploaded files and logs were excluded; only necessary code, documentation and configuration files were copied.
There is no Python lockfile and some dependencies are not pinned. The installed environment was reused with its versions recorded, without updating packages to obtain passing tests. PostgreSQL, external email, physical readers and backup restoration were not executed.
Solution
The catalog combines components, categories, locations, photographs and specifications. Searches combine name, code, category, location and stock state; lists use pagination and preloaded relationships.
Movements support entries, withdrawals, transfers and count adjustments. Work-order consumption generates withdrawals. Signals create alerts and QR labels; reports produce PDF, Excel and CSV. QR content is an informational snapshot of the component and does not establish integrated mobile scanning. Indicators are calculated when the page is requested; continuous updates were not established.
Architecture and data model
Django 5 monolith: authentication and sessions → views and forms → domain models → persistence. Pages render on the server, with HTMX for queries and Alpine.js for interaction. Tailwind and Chart.js load from external services in the reviewed templates.
The model covers categories, locations, components, movement history, orders, component usage and alerts. QR labels and images are files outside database transactions.
SQLite is the default engine. DATABASE_URL contemplates PostgreSQL, with additional packages described in the guide and absent from the main dependency manifest. That engine was not run. The presence of select_for_update() does not provide row locking in SQLite.
Read the diagram and its limits
How to read the flow: The workshop user accesses the web interface (Django with HTMX and Alpine.js) to consult catalog items and record stock adjustments. In parallel, the administrator manages users and model instances directly via the native Django Admin panel. Work orders initiate material consumption workflows directed to the inventory domain.
Components and persistence: The core layer brings together Django models and inventory business rules for components, locations, and movements. This layer interacts with local SQLite via the Django ORM. Post_save signals execute alert evaluation and attempt QR label generation, persisting image files to disk.
Diagram simplifications: In the mobile view, actors and interfaces are grouped into consolidated stages to preserve clear visual relationships without horizontal scrolling or label crowding.
Tested scope: Core domain logic, movements and catalogs were executed and validated locally on SQLite (32/37 tests passing). CSV data export was verified. PostgreSQL is contemplated in the application configuration, but was neither executed nor verified in a live production environment.
System boundaries: File and QR label persistence operates outside the database transaction (disk failures do not roll back the DB record). Resaving work orders generated duplicate withdrawal effects in validation tests. The architecture lacks asynchronous task queues, and concurrent multi-user load was not evaluated under real operating conditions.
Technical implementation and evidence map. Unit and stock tests executed locally on SQLite; PostgreSQL engine and production concurrency were not validated in a live environment.
Main inventory workflow
Workflow checked using Django’s HTTP client with CSRF enforcement: start a test session, create a component with no stock, register a ten-unit entry, apply it and consult the detail page and stock response. Persisted quantity, applied state and server-assigned user were verified.
The domain test covered withdrawal, replenishment, transfer and adjustment: it checked balances, location change and alert creation/resolution. The browser confirmed sign-in and presentation of the synthetic catalog. These are local workflows, not evidence of continuous operation or physical reader tests.
Concurrency and stock integrity
Applying a movement places the stock update and movement state inside a transaction. An excessive withdrawal was rejected without changes. Simulating failure after the stock write rolled back balance, movement and alert; reloading allowed a successful retry.
Two overlapping withdrawals against ten units used threads and real SQLite connections, synchronized during reads: one applied and the other received a lock error; two units and one applied movement remained. This demonstrates contention, not satisfactory concurrency handling or a result transferable to PostgreSQL.
Tests found repeated effects with stale objects and when resaving work-order consumption. A directly entered initial balance also lacked an automatic opening movement. Complete idempotency and exhaustive reconciliation therefore require reinforcement.
Architectural decisions
Django brings forms, ORM, authentication and administration into one maintainable application. HTMX enriches queries without duplicating the entire interface in a separate client; this is a choice consistent with the product, not a performance comparison between frameworks.
Atomic transactions limit partial movement writes. ORM locking depends on the engine: PostgreSQL supports row locking while SQLite does not implement that operation. Changing engines requires dedicated tests.
Signals automate QR labels and alerts. QR storage avoids another signal chain, but file failure preserves the component without a label and does not establish automatic recovery.
Documentation describes earlier fixes to QR, stock, forms and queries. No numbered ADRs were found to support the case study’s previous references.
Security and access control
Implemented: Django authentication, PBKDF2 password hashing, HttpOnly session cookies, CSRF middleware and HTTPS configuration controls. Checked locally: redirecting visitors without sessions, rejecting POST without CSRF and access with a synthetic account.
Role separation in the general interface did not pass validation. Groups and administration permissions do not establish enforcement in every view. This is shared inventory and is not presented as tenant isolation.
Rate limiting exists and a clean-cache test observed the expected block; original cases share cache state and one additional run varied across limiter windows. Overall abuse resistance was not established. Local settings retain five deployment warnings; production was not audited. Operational routes, secrets and workshop records are not published.
Testing and validation scope
Real modules ran in an isolated copy: Python 3.12.10, Django 5.0.1 and file-based SQLite, without copying the operational environment. Local startup, migrations, syntax analysis and dependency checks completed. The source project has no dedicated lint or type task.
The first original run passed 30 cases with seven errors. After collectstatic, without changing assertions or code, 32 passed, four failed and one errored. The four failures concern the limiter and its presentation; the error combines a client without CSRF enforcement with missing-price validation.
The 15 additional checks finished with nine passing and six failing. The table separates verified behavior from unmet expectations: reproducing a defect does not make it a passing guarantee. Coverage, maximum load and production latency were not measured.
| Verification / Check | Result | Scope & Evidence |
|---|---|---|
| Original suite | 32/37; 4 failures, 1 error | Static assets prepared. Shared cache in limiter tests; missing-price form error. |
| Additional tests | 9/15; 6 failures | Real modules: HTTP workflow, domain, access controls, integrity, concurrency and files. |
| Create → entry → lookup | Passed locally | CSRF enforced; balance 0 → 10, applied movement and rendered response. |
| Withdrawal, transfer, adjustment | Passed locally | Balances and location checked; alerts created and resolved. |
| Partial failures | Rollback verified | Injected save failure. Simulated QR failure: component retained without label. |
| SQLite concurrency | Contention reproduced | 2 overlapping withdrawals: 1 applied, 1 lock error. PostgreSQL not run. |
| Integrity and permissions | Reinforcement needed | Role isolation, stale-state resend, consumption re-save and opening history checks failed. |
| Exports | Partial result | CSV retains code and quantity; PDF generated with valid header. Excel retains values as text: numeric assertion failed. |
| Configuration and startup | Completed locally | check clean; migrations, syntax and dependencies passed. 5 deployment warnings. |
Deployment and environment
Operational in the 3DFAB workshop. The guide outlines Gunicorn and WhiteNoise, Nginx/Apache proxy, HTTPS, PostgreSQL and backups. These are deployment instructions, not evidence that this topology describes the current instance.
Only the development server was started on loopback with the synthetic database. Required static assets were generated and browser access checked. Production infrastructure, email, restoration, availability and workshop devices were not inspected.
Outcome and current status
The delivered application combines part lookup, locations, movements, alerts and reports. I developed the entire system and it remains in active operation. Execution supports the basic inventory workflow and provides concrete limits for prioritizing improvements.
There is insufficient evidence to quantify savings, search speed, error reduction or availability. Absolute equivalence between physical stock and history is not claimed. Demonstrated value lies in centralizing work and making its rules and states visible.
Evidence and limits
Implemented: inspected models, forms, views, signals and exports. Verified locally: original suite, additional checks, startup, HTTP workflow and browser presentation. Simulated: movement-save failure and QR-generation failure. Scope: complete in-house development and operational status. Unverified: production, PostgreSQL, physical QR reading, email and restoration.
The review included local numeric-format and dashboard changes. Copies were checked using SHA-256 and the source repository was preserved intact. The sanitized record and reproducible environment remain internal; this page explains methods and results without downloads.
Synthetic database checks
The database was created exclusively with synthetic data. The workshop database was not opened. Balances, movement states, alerts and recovery effects were checked. Direct creation with positive stock lacks automatic opening history; this result is not extrapolated to real records.
Concurrency and repeated operations
Two real SQLite connections overlapped reads of the same component before writing. Final stock was consistent in that scenario, but the second operation received a lock error. This does not measure maximum capacity or simulate PostgreSQL. Resend and repeated-consumption tests found separate limits.
Software quality and workshop UX
The catalog and forms bring together workshop operations; messages, pending states and alerts help staff interpret what was recorded. Search and pagination bound the displayed volume; select_related reduces repeated queries in lists.
Software quality means checking inventory rules and their failures, not accumulating passing tests. Review adds resend, concurrency, rollback and export scenarios missing from the happy path.
Product UX depends on external resources for styling and interaction; full offline operation was not established. This case study offers an index, project navigation, readable diagram and mobile code wrapping. No accessibility score or benchmark is claimed.
Code sample and engineering test
Public, standalone adaptation of a withdrawal rule: validate quantity, reject overdraft and calculate whether the threshold is reached. Requires Python 3 and its standard library only. Both displayed blocks were concatenated and executed exactly. It imports no reserved code and does not replace the system’s real transactions.
def plan_dispatch(stock, quantity, minimum): |
"""Pure stock rule: no database, network or reserved code.""" |
values = (stock, quantity, minimum) |
if any(type(value) is not int for value in values): |
raise ValueError("Integer values required") |
if stock < 0 or minimum < 0 or quantity <= 0: |
raise ValueError("Invalid stock or quantity") |
if quantity > stock: |
raise ValueError("Insufficient stock") |
remaining = stock - quantity |
return remaining, remaining <= minimum |
Isolated engineering test
import unittest |
|
class StockRuleTest(unittest.TestCase): |
def test_dispatch_and_threshold(self): |
self.assertEqual(plan_dispatch(10, 8, 3), (2, True)) |
|
def test_threshold_boundary(self): |
self.assertEqual(plan_dispatch(10, 7, 3), (3, True)) |
|
def test_above_threshold(self): |
self.assertEqual(plan_dispatch(10, 2, 3), (8, False)) |
|
def test_exact_stock(self): |
self.assertEqual(plan_dispatch(10, 10, 0), (0, True)) |
|
def test_reject_invalid_inputs(self): |
for values in [(10, 11, 3), (10, 0, 3), (-1, 1, 0), |
(10, 1, -1), (10, True, 3), (10, 1.5, 3)]: |
with self.subTest(values=values): |
with self.assertRaises(ValueError): |
plan_dispatch(*values) |
|
unittest.main() |
5 tests passed; the invalid-input test includes 6 subcases. This checks the pure rule only: it does not establish concurrency, permissions, persistence or production operation.