Compare commits
10 Commits
96fe655f72
...
v1.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb9df1d73f | ||
|
|
fe18fe01c6 | ||
|
|
91bdd791d2 | ||
|
|
ed06f0b56e | ||
|
|
df9468344d | ||
|
|
d87067e88c | ||
|
|
2e5ce8d153 | ||
|
|
c71a815792 | ||
|
|
0a9ea0f575 | ||
|
|
432cd28ca5 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -4,3 +4,7 @@ __pycache__/
|
||||
*.pyc
|
||||
.env
|
||||
.DS_Store
|
||||
aInventory-PROD*
|
||||
aInventory-PROD*.zip
|
||||
logs/
|
||||
backend/logs/
|
||||
|
||||
78
AI_RULES.md
78
AI_RULES.md
@@ -1,43 +1,51 @@
|
||||
# AI AGENT RULES - SINGLE SOURCE OF TRUTH
|
||||
# AI AGENT RULES - MANDATORY ENTRY POINT
|
||||
|
||||
This file is the single source of truth for ALL Artificial Intelligence agents working on this project (Claude, Gemini, etc.).
|
||||
Any AI or session MUST respect these mandatory rules.
|
||||
**READ THIS ENTIRE FILE BEFORE EXECUTING ANY TASK.**
|
||||
This is the **Single Source of Truth** for ALL Artificial Intelligence agents (Claude, Gemini, etc.) working on this project.
|
||||
(Automatic IDE entry points like `GEMINI.md` and `CLAUDE.md` exist solely to redirect agents to this main file).
|
||||
For technical architecture, data models, and stack details, refer to [PROJECT_ARCHITECTURE.md](PROJECT_ARCHITECTURE.md).
|
||||
|
||||
## General Rules
|
||||
- **UI & Code Language**: All web interfaces, functions, variables, and any text inside the application MUST BE DIRECTLY AND ONLY IN ENGLISH.
|
||||
- **Communication Language**: Conversation with the user will be in Romanian or English, preferably Romanian.
|
||||
|
||||
## Multi-AI Coordination & Handover
|
||||
## 1. Multi-AI Coordination & Memory
|
||||
- **MANDATORY STARTUP**: Every AI session MUST first read `dev_docs/SESSION_STATE.md` to understand current context.
|
||||
- **MANDATORY HANDOVER**: At the end of every task/session, create or update a handover note in `dev_docs/SESSION_STATE.md`. Specify: **Active AI**, **Current Status**, **Technical Context** (details not in code), and **Next Steps**.
|
||||
- **ARCHIVAL RULE**: To prevent `SESSION_STATE.md` from bloating, incoming AI agents MUST move all content of the *previous* session handover into the top of `dev_docs/SESSION_HISTORY.md` before writing their own new state. This keeps `SESSION_STATE.md` focused only on the *active* session.
|
||||
- **NO INTERACTION OVERLAP**: Never modify a file if another AI session is explicitly working on it according to `SESSION_STATE.md`.
|
||||
- **MANDATORY HANDOVER**: At the end of every task/session, update the handover note in `dev_docs/SESSION_STATE.md`. Specify: **Active AI**, **Current Status**, **Technical Context**, and **Next Steps**.
|
||||
- **ARCHIVAL RULE**: Before writing new state, move all content of the *previous* session handover into the top of `dev_docs/SESSION_HISTORY.md` to prevent bloat.
|
||||
- **NO INTERACTION OVERLAP**: Never modify a file if another AI session is explicitly working on it.
|
||||
|
||||
## Implementation Completion
|
||||
- All code modifications MUST be committed in git before the task is considered finished. `VERSION.json` must be updated on EACH commit.
|
||||
- **MANDATORY GIT RULE:** Never push to remote unless explicitly requested by the user. Only commit locally with proper messages. Always assume the user will handle all `git push` operations. If a task requires pushing, ask for explicit permission first.
|
||||
- **GIT BINARY PATH**: On this macOS environment, the system `git` (in `/usr/bin/git`) is often broken due to `xcode-select` issues. ALWAYS use the binary path stored in `.git_path` at the project root for all Git operations.
|
||||
- **GIT BRANCHING STRUCTURE**:
|
||||
- The main stable branch is `master`.
|
||||
- All active development MUST occur in the `dev` branch.
|
||||
- Every major version MUST have its own dedicated archival branch named `vX` (e.g., `v1`, `v2`) which copies the state of the major release.
|
||||
- **MANDATORY GIT RULE**: NO AI is allowed to write in git commits that it is the author or co-author (e.g., DO NOT add texts like `Co-Authored-By: AI...`). Commits should only contain technical messages.
|
||||
- **MANDATORY LOGGING**: Any modification of code, architecture, or logic MUST be documented in `dev_docs/ARCHIVE_LOGS.md` at the end of the task. The log must include modified files, purpose of modification, and (if applicable) test results.
|
||||
- **MANDATORY PLAN ARCHIVING**: Once a phase or task is confirmed as completed and verified, the Architect (Gemini/AI) MUST move these entries from `PLAN.md` into `dev_docs/PLAN_HISTORY.md`. This maintains the active plan's focus and prevents document bloat.
|
||||
- After finishing an entire job, end your final response on a separate line exactly with:
|
||||
## 2. Global Operational Laws
|
||||
- **STRICT ENGLISH POLICY**: All web interfaces, code, variables, scripts, and documentation MUST BE DIRECTLY AND ONLY IN ENGLISH. If you find Romanian text in code, translate it immediately.
|
||||
- **COMMUNICATION LANGUAGE**: Conversation with the user will be in Romanian or English (preferably Romanian).
|
||||
- **GIT BINARY PATH**: On this macOS environment, the system `git` is often broken. ALWAYS use the binary path stored in `.git_path` at the project root for all Git operations.
|
||||
- **COMMIT & PUSH STRICT RULE**:
|
||||
- Never push to remote (`git push`) or use force flags (`--hard`, `--force`) unless explicitly requested.
|
||||
- Always update `VERSION.json` on every commit.
|
||||
- Do NOT add AI co-author signatures (e.g., `Co-Authored-By: AI...`) to commit messages.
|
||||
- Branching: `master` (stable), `dev` (active development), `vX` (archival releases).
|
||||
- **MANDATORY LOGGING**: Document coding/architecture changes in `dev_docs/ARCHIVE_LOGS.md` at the end of the task.
|
||||
- **TRIPLE CONFIRMATION (Safe Forget)**: You cannot delete a physical location, item, or critical entity without explicit user permission three times.
|
||||
|
||||
## 3. UI/UX Fidelity Specifications
|
||||
- **Fidelity First**: Never simplify the UI unless asked. Density and aesthetics must remain "Premium".
|
||||
- **Styling**: Tailwind CSS. Font weights/spacing must be consistent (Inter/Roboto).
|
||||
- **Readability**: NO `uppercase` or `tracking-widest` styles. Use standard camel/Title case.
|
||||
- **Icons**: Use **Lucide Icons** exclusively. NO emojis.
|
||||
- **Interactive Affordance**: All select/dropdown boxes MUST have a `ChevronDown` icon. Masked passwords should have reduced opacity (`text-white/50`).
|
||||
- **Iconography Standardization**:
|
||||
- **Categories**: ALWAYS use `Layers` (Color: `text-primary`).
|
||||
- **Item Types**: ALWAYS use `Package` (Color: `text-green-500`).
|
||||
|
||||
## 4. Documentation Maintenance
|
||||
- **SSOT INTEGRITY**: Whenever a feature is added, modified, or removed, you MUST update all corresponding documentation files:
|
||||
- `README.md` (General usage & technical modes).
|
||||
- `USER_GUIDE.md` (End-user instructions).
|
||||
- `PROJECT_ARCHITECTURE.md` (Technical logic & data models).
|
||||
- `export_prod.sh` (If new scripts or files must be included in the production bundle).
|
||||
- **REAL-TIME UPDATES**: Documentation updates are NOT optional and must be performed within the same session as the code changes.
|
||||
|
||||
## 5. End of Session Protocol
|
||||
- Once a phase/task from `PLAN.md` is completed and verified, move that entry into `dev_docs/PLAN_HISTORY.md`.
|
||||
- After finishing an entire job (including updating session state, architecture logs, and versioning), end your final response on a separate line exactly with:
|
||||
```
|
||||
---
|
||||
✓ Done.
|
||||
```
|
||||
- Do not provide unnecessary summaries of the code.
|
||||
|
||||
## Triple Confirmation & Safety Limits
|
||||
- **Safe Forget**: You cannot delete a physical location, item, or critical entity without a triple confirmation mechanism.
|
||||
- **No Force Operations**: Never use destructive flags (e.g., `git reset --hard`, `git push --force`, `rm -rf`) without explicit user permission.
|
||||
|
||||
## UI/UX & Documentation Rules
|
||||
- **STRICT ENGLISH POLICY**: ANY TEXT within the application (documentation, scripts, CLI, UI, internal comments, logs, etc.) MUST be strictly in English. NO Romanian characters (ăâîșț) or words are allowed in the repository.
|
||||
- **MANDATORY TRANSLATION**: Any Romanian text found during an AI session (in any file) MUST be translated to English immediately.
|
||||
- Use Bootstrap Icons (`<i class="bi bi-something"></i>`); never use emojis.
|
||||
- The UI must remain fully functional offline (no external CDNs).
|
||||
- **MANDATORY UI FIDELITY**: Any modification to UI components (headers, banners, cards, buttons) MUST comply with the specifications in `dev_docs/UI_FIDELITY_SPEC.md` to prevent regressions. All agents MUST read that document before modifying frontend code.
|
||||
- Do not provide unnecessary verbatim summaries of the code.
|
||||
|
||||
11
CLAUDE.md
Normal file
11
CLAUDE.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# CLAUDE ENTRY POINT
|
||||
|
||||
You are Claude, operating on the TFM aInventory project.
|
||||
|
||||
**IMMEDIATE MANDATORY ACTION:**
|
||||
Before taking any action or writing code, you MUST read the following Single Source of Truth files:
|
||||
1. `AI_RULES.md` (Contains your operational constraints, Git rules, and UI fidelity laws).
|
||||
2. `PROJECT_ARCHITECTURE.md` (Contains the tech stack, data models, and system logic).
|
||||
3. `dev_docs/SESSION_STATE.md` (Contains the current handover status from the previous AI).
|
||||
|
||||
Do not proceed with any task until you have analyzed these three files.
|
||||
12
Caddyfile
Normal file
12
Caddyfile
Normal file
@@ -0,0 +1,12 @@
|
||||
# TFM aInventory - Caddy Self-Signed Internal Proxy
|
||||
# This replaces the need for `local-ssl-proxy` in Node.
|
||||
|
||||
:3003 {
|
||||
tls internal
|
||||
reverse_proxy frontend:3000
|
||||
}
|
||||
|
||||
:3002 {
|
||||
tls internal
|
||||
reverse_proxy backend:8000
|
||||
}
|
||||
11
GEMINI.md
Normal file
11
GEMINI.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# GEMINI ENTRY POINT
|
||||
|
||||
You are Gemini (Antigravity), operating on the TFM aInventory project.
|
||||
|
||||
**IMMEDIATE MANDATORY ACTION:**
|
||||
Before taking any action or writing code, you MUST read the following Single Source of Truth files:
|
||||
1. `AI_RULES.md` (Contains your operational constraints, Git rules, and UI fidelity laws).
|
||||
2. `PROJECT_ARCHITECTURE.md` (Contains the tech stack, data models, and system logic).
|
||||
3. `dev_docs/SESSION_STATE.md` (Contains the current handover status from the previous AI).
|
||||
|
||||
Do not proceed with any task until you have analyzed these three files.
|
||||
54
PLAN.md
54
PLAN.md
@@ -1,55 +1,13 @@
|
||||
# Inventory PWA System Architecture & Implementation Plan
|
||||
# Active Development Plan
|
||||
|
||||
This document defines the technical architecture and rules for the InventoryAI System (2026 Edition).
|
||||
|
||||
## 1. Core Architecture
|
||||
|
||||
### 1.1 Backend (Python 3.14+)
|
||||
- **Framework:** FastAPI
|
||||
- **Database:** SQLite (SQLAlchemy) - chosen for local performance and simplicity.
|
||||
- **Organization:** Modular design with separate routers for Items and Operations.
|
||||
|
||||
### 1.2 Frontend (Next.js 15+ PWA)
|
||||
- **State Management:** React Hooks + Dexie.js (IndexedDB wrapper).
|
||||
- **Offline Engine:**
|
||||
- Service Workers for asset caching.
|
||||
- IndexedDB for local data persistence.
|
||||
- Sync mechanism: Local changes are buffered and pushed to backend when online.
|
||||
- **Scanner:** `html5-qrcode` for standard barcode/QR detection (Local-only).
|
||||
|
||||
## 2. AI Intelligence Strategy (Critical)
|
||||
|
||||
### 2.1 AI Usage Policy
|
||||
- **New Item Onboarding:** AI-OCR is permitted. It analyzes complex label photos (SFP, hardware specs) and maps them to JSON fields.
|
||||
- **Routine Operations (Check-in/Out/Audit):** **AI IS STRICTLY FORBIDDEN.**
|
||||
- Use local barcode/QR scanning only.
|
||||
- If a label is not recognized locally, the user is prompted to start the "AI Onboarding Assistant".
|
||||
- Goal: $0 cost for 99% of daily operations.
|
||||
|
||||
### 2.2 Modular AI Providers Architecture
|
||||
Located in `backend/ai/`, the system supports multiple providers through a managed orchestrator:
|
||||
- **Provider Modules:** `gemini.py`, `claude.py`, etc.
|
||||
- **SDK Update (v2):** Switched to `google-genai` (v2) for improved stability and response parsing.
|
||||
- **Model Hardcoding Power:** Switched from dynamic discovery to fixed high-speed models (`gemini-2.0-flash`) for sub-second responses on cellular networks.
|
||||
|
||||
### 2.3 Hybrid Sync & Deduplication (New)
|
||||
To ensure zero data loss during unstable mobile sessions:
|
||||
- **UUID Labeling:** Every sync operation generated on a mobile device is tagged with a client-side UUID.
|
||||
- **Idempotent Backend:** The `bulk_sync` endpoint checks UUIDs against `AuditLog` before applying increments, preventing double-counts.
|
||||
|
||||
## 3. Data Integrity & Audit
|
||||
- **Immutable Audit Log:** Every change (Add, Remove, Edit) is logged with a timestamp, action, and previous/new state.
|
||||
- **Validation Mask:** AI-extracted data is NEVER saved directly. It is presented to a human user in a validation UI for final confirmation.
|
||||
|
||||
## 4. Implementation Status
|
||||
This document tracks the immediate implementation checklist. For overarching design and constraints, see [PROJECT_ARCHITECTURE.md](PROJECT_ARCHITECTURE.md).
|
||||
|
||||
## Implementation Status
|
||||
- [x] **Phase 1: Backend Foundation** (FastAPI, SQLite, Models).
|
||||
- [x] **Phase 2: Modular AI Integration** (Gemini & Claude support, v2 SDK).
|
||||
- [x] **Phase 3: AI Onboarding UI** (Validation Mask, Camera/Upload integration).
|
||||
- [x] **Phase 2: Modular AI Integration** (Gemini support, v2 SDK).
|
||||
- [x] **Phase 3: AI Onboarding UI** (Validation Mask, Camera integration).
|
||||
- [x] **Phase 4: Offline Synchronization** (Deduplicated Dexie -> SQL sync logic).
|
||||
- [x] **Phase 5: Inventory Trash Management** (Waste/Discard/Damage workflow).
|
||||
- [ ] **Phase 6: Audit Log Dashboard UI** (Visual historical interventions).
|
||||
|
||||
## 5. Security & Infrastructure
|
||||
- **Unified SSL Proxy:** Integrated `local-ssl-proxy` for HTTPS access (Camera/Mic) on port 3003.
|
||||
- **VENV Isolation:** Automated `.venv` management in `start_server.sh`.
|
||||
*(Note: Completed phases are periodically moved to `dev_docs/PLAN_HISTORY.md` according to AI_RULES)*
|
||||
|
||||
54
PROJECT_ARCHITECTURE.md
Normal file
54
PROJECT_ARCHITECTURE.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# TFM aInventory - Project Architecture & Requirements
|
||||
|
||||
This document is the **Single Source of Truth** for the project's technical architecture, business requirements, and core logic.
|
||||
|
||||
## 1. Application Overview
|
||||
A unified system to maintain an inventory of "items" and their quantities, inclusive of a web administration interface, offline field operations, audit logging, and AI-powered label extraction functionalities.
|
||||
|
||||
## 2. Technical Stack
|
||||
### 2.1 Backend (API & Data)
|
||||
- **Language:** Python 3.12+ (Optimized for performance and type safety)
|
||||
- **Framework:** FastAPI (Async ASGI)
|
||||
- **Database:** SQLite (SQLAlchemy) - Local file-based persistence
|
||||
- **Validation:** Pydantic v2
|
||||
- **Auth:** Hybrid LDAP (python-ldap) + PBKDF2 local password hash caching
|
||||
- **AI Engine:** Google GenAI SDK (Gemini 2.0 Flash) - Location: `backend/ai/`
|
||||
|
||||
### 2.2 Frontend (Web & PWA)
|
||||
- **Architecture:** Next.js 15+ (App Router)
|
||||
- **Styling:** Tailwind CSS (Readability-first config)
|
||||
- **Icons:** Lucide Icons (React components)
|
||||
- **Offline persistence:** Dexie.js (IndexedDB wrapper)
|
||||
- **Scanner:** `html5-qrcode` (Client-side, offline-only)
|
||||
- **Sync:** Axios with bulk-sync idempotency (UUID-based)
|
||||
|
||||
### 2.3 Operations & Tooling
|
||||
- **PWA Deployment:** `next-pwa` (Service Workers + Manifest.json)
|
||||
- **HTTPS Proxy:** `local-ssl-proxy` (Required for mobile camera access, Port 3003)
|
||||
- **Servers:** Frontend (`npm run dev` on 3000), Backend (`./start_server.sh` on 8000)
|
||||
|
||||
## 3. Data Models & Entities
|
||||
- **Item:** Name, Category Group (Structured), Item Type (Specific), Quantity, Barcode, Part Number.
|
||||
- **Category:** Predefined groups for organizational structure.
|
||||
- **Intervention:** Linked to a required items list.
|
||||
- **Audit Log:** Immutable ledger detailing CRUD operations and stock fluctuations.
|
||||
|
||||
## 4. Scanning & Optimization Strategy (Crucial)
|
||||
### 4.1 AI Usage Policy
|
||||
- **Routine Operations (Check-in/Out):** Executes entirely on the local device unconditionally using `html5-qrcode` ($0 cost). No AI is allowed here.
|
||||
- **New Item Onboarding (AI Label OCR):** Uses cloud AI (`gemini-2.0-flash`). The user takes a photo, AI extracts data based on strict templates.
|
||||
- **Validation Mask:** AI-extracted data is NEVER saved directly. It is presented in a validation UI for human confirmation.
|
||||
|
||||
### 4.2 Scanner Technical Specs (FROZEN)
|
||||
- **Hardware Access:** Direct `MediaStreamTrack` access. Zoom cycle: 1x -> 2x -> Max/2 -> Max.
|
||||
- **Image Pre-processing:** Rescaling (1200px), 60% Center Crop, Grayscale/Contrast filters, JPEG (`0.85` quality).
|
||||
- **OCR Matching Engine (`page.tsx`):**
|
||||
- Noise Filtering: Ignores `< 3` chars, decimals, and dates.
|
||||
- Scoring: Exact S/N (+500), Exact P/N (+200), Token match (+50), Category match (+20).
|
||||
- Threshold: Minimum **40 points** for auto-match without user intervention.
|
||||
|
||||
## 5. Offline Sync Protocol
|
||||
To prevent data loss in basements or unstable networks:
|
||||
- **Offline Engine:** Service Workers cache assets. IndexedDB saves data.
|
||||
- **UUID Labeling:** Every sync operation generated offline is tagged with a client-side UUID.
|
||||
- **Idempotent Backend:** The `bulk_sync` endpoint checks UUIDs against `AuditLog` before applying increments, preventing double-counts.
|
||||
53
README.md
Normal file
53
README.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# TFM aInventory (2026 Edition)
|
||||
|
||||
A unified, offline-first Inventory Management System built as a Progressive Web App (PWA). Features include AI-powered label extraction (OCR), local barcode/QR scanning, and multi-user authentication with LDAP support.
|
||||
|
||||
---
|
||||
|
||||
## 🛠 Project Modes
|
||||
|
||||
This project supports three distinct operational modes:
|
||||
|
||||
### 1. 🚀 Development Mode (Bare-Metal)
|
||||
Ideal for local development on macOS/Linux.
|
||||
* **Command:** `./start_server.sh`
|
||||
* **Details:** Runs FastAPI (backend) and Next.js (frontend) in development mode. Uses `local-ssl-proxy` for HTTPS.
|
||||
* **Backend:** http://localhost:8000
|
||||
* **Frontend:** https://localhost:3003
|
||||
|
||||
### 2. 🐳 Docker Mode (Recommended for Production)
|
||||
Isolated and portable container stack.
|
||||
* **Command:** `docker-compose up -d --build`
|
||||
* **Details:** Uses Caddy as a reverse proxy for HTTPS. Persistent data and logs are mapped to `./data` and `./logs`.
|
||||
* **Access:** https://localhost:3003
|
||||
|
||||
### 3. 🐧 Standalone Linux Mode (Systemd)
|
||||
Native Linux installation (Alma/Debian/Ubuntu) without Docker dependencies.
|
||||
* **Installation:** `sudo ./install_service.sh`
|
||||
* **Execution:** `sudo systemctl start inventory`
|
||||
* **Details:** Compiles the frontend for production and manages the entire stack as a system service.
|
||||
* **Access:** https://<SERVER-IP>:3003
|
||||
|
||||
---
|
||||
|
||||
## 📦 Production Distribution
|
||||
To generate a clean production package without AI-agent metadata or development artifacts:
|
||||
1. Run `./export_prod.sh`
|
||||
2. A `.zip` archive will be created (e.g., `aInventory-PROD-v1.3.2.zip`).
|
||||
3. This archive contains a specialized `README.txt` with deployment-only instructions.
|
||||
|
||||
---
|
||||
|
||||
## 🏗 Technical Overview
|
||||
* **Backend:** FastAPI (Python 3.12+)
|
||||
* **Frontend:** Next.js 15+ (React PWA)
|
||||
* **Database:** SQLite (SQLAlchemy) with Dexie.js (IndexedDB) for client-side sync.
|
||||
* **Proxy:** Caddy (Docker) or local-ssl-proxy (Standalone/Dev).
|
||||
* **AI Engine:** Google Gemini (Generative AI SDK).
|
||||
|
||||
For more details, see [PROJECT_ARCHITECTURE.md](PROJECT_ARCHITECTURE.md).
|
||||
|
||||
---
|
||||
|
||||
## 📜 AI Operational Rules
|
||||
AI agents working on this project MUST follow the guidelines in [AI_RULES.md](AI_RULES.md).
|
||||
50
USER_GUIDE.md
Normal file
50
USER_GUIDE.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# TFM aInventory - User Guide (Ghid de Utilizare)
|
||||
|
||||
Bun venit în sistemul **TFM aInventory**. Acest document explică modul de utilizare a aplicației pentru gestionarea inventarului.
|
||||
|
||||
---
|
||||
|
||||
## 📱 Instalarea pe Telefon (PWA)
|
||||
Aplicația este un **Progressive Web App**, ceea ce înseamnă că nu trebuie descărcată din App Store/Google Play.
|
||||
1. Deschideți URL-ul aplicației în browser (ex: Safari pe iOS sau Chrome pe Android).
|
||||
2. Apăsați butonul de **Share** (iOS) sau cele **trei puncte** (Android).
|
||||
3. Selectați **"Add to Home Screen"** (Adaugă pe ecranul principal).
|
||||
4. Aplicația va apărea acum ca o iconiță pe ecranul dvs. și va funcționa într-un mod imersiv (fără barele browserului).
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Autentificarea
|
||||
* **Utilizator Implicit:** La prima instalare, folosiți `Admin` / `admin`.
|
||||
* **Vă recomandăm schimbarea parolei imediat din secțiunea de Admin.**
|
||||
* **LDAP:** Dacă administratorul a configurat integrarea, vă puteți loga cu contul de domeniu/companie. Aplicația vă va reține hash-ul parolei pentru a permite logarea în zone fără semnal (ex: subsoluri).
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Scanarea și Adăugarea de Obiecte
|
||||
Aplicația suportă două moduri de scanare:
|
||||
1. **Manual / Barcode:** Scanați un cod de bare existent pentru a găsi sau adăuga un obiect.
|
||||
2. **AI Label Extraction (OCR):** Folosiți camera pentru a fotografia eticheta unui produs nou. AI-ul va încerca să extragă automat:
|
||||
* Denumirea produsului (Model/Series)
|
||||
* Producătorul (Brand)
|
||||
* Specificațiile tehnice
|
||||
* Codul de bare
|
||||
|
||||
---
|
||||
|
||||
## 📂 Organizarea Inventarului
|
||||
* **Category Groups:** Grupează categoriile (ex: IT, Papetărie, Mobilier).
|
||||
* **Categories:** Subdiviziuni ale grupurilor.
|
||||
* **Item Types:** Definește template-uri pentru obiecte (ex: Laptop, Scaun, Tonner).
|
||||
|
||||
---
|
||||
|
||||
## 📜 Jurnalul de Activitate (Audit Log)
|
||||
Toate acțiunile (adăugări, modificări, ștergeri) sunt înregistrate în timp real. Puteți consulta istoricul în secțiunea **Logs** pentru a vedea cine și când a operat modificări în stoc.
|
||||
|
||||
---
|
||||
|
||||
## 📶 Modul Offline
|
||||
Aplicația este concepută să funcționeze chiar și atunci când nu aveți conexiune la internet în depozit. Datele sunt sincronizate automat când reveniți în zona de acoperire.
|
||||
|
||||
---
|
||||
*Pentru asistență tehnică, contactați administratorul de sistem.*
|
||||
18
VERSION.json
18
VERSION.json
@@ -1,16 +1,10 @@
|
||||
{
|
||||
"version": "1.2.6",
|
||||
"last_build": "2026-04-11-1206",
|
||||
"commit": "d9e2a",
|
||||
"version": "1.3.5",
|
||||
"last_build": "2026-04-11-1250",
|
||||
"commit": "PENDING",
|
||||
"changelog": [
|
||||
"v1.2.6: Hotfix - Added missing icon imports (Layers, ChevronDown)",
|
||||
"v1.2.5: Synchronized icons across UI (Layers for Categories, Package for Item Types)",
|
||||
"v1.2.4: Offline LDAP auth support and UI affordance improvements (Dropdown chevrons, soft password dots)",
|
||||
"v1.2.3: System-wide UI consistency (standardized font sizes, removed uppercase)",
|
||||
"v1.2.2: UI Readability refactor (Removed uppercase/tracking, increased font sizes)",
|
||||
"v1.2.1: Git path persistence, master/dev/vX branching, and UI case-sensitivity fix",
|
||||
"v1.2.0: Structured category management with grouping support",
|
||||
"v1.1.0: Multi-user auth & LDAP framework integration",
|
||||
"v1.0.0: Initial PWA inventory launch"
|
||||
"v1.3.5: Updated AI_RULES.md with mandatory documentation maintenance requirements for all agents",
|
||||
"v1.3.4: Created USER_GUIDE.md (Romanian) for end-users and integrated into export bundle",
|
||||
"v1.3.3: Added comprehensive project README.md documenting all operational modes"
|
||||
]
|
||||
}
|
||||
|
||||
35
backend/Dockerfile
Normal file
35
backend/Dockerfile
Normal file
@@ -0,0 +1,35 @@
|
||||
FROM python:3.12-slim
|
||||
|
||||
# Install system dependencies required for python-ldap (needed by backend)
|
||||
RUN apt-get update && apt-get install -y \
|
||||
build-essential \
|
||||
libldap2-dev \
|
||||
libsasl2-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy requirements and install
|
||||
COPY backend/requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Create non-root user
|
||||
RUN adduser --system --group appuser
|
||||
|
||||
# Copy application files
|
||||
COPY backend ./backend
|
||||
|
||||
# We define the data dir explicitly for Docker
|
||||
ENV DATA_DIR="/app/data"
|
||||
ENV LOGS_DIR="/app/logs"
|
||||
|
||||
# Ensure the appuser can write to data and logs if we pre-create them,
|
||||
# although Docker volumes will handle ownership context.
|
||||
RUN mkdir -p /app/data /app/logs && chown -R appuser:appuser /app
|
||||
|
||||
USER appuser
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
# Start Uvicorn pointing to the backend module
|
||||
CMD ["python", "-m", "uvicorn", "backend.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||
@@ -4,9 +4,11 @@ import os
|
||||
|
||||
# Get absolute path for the backend directory
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
DATA_DIR = os.path.join(BASE_DIR, "data")
|
||||
|
||||
# Create data directory if it doesn't exist in the backend folder
|
||||
# Use DATA_DIR from environment if running in Docker, otherwise fallback to local 'data' folder
|
||||
DATA_DIR = os.environ.get("DATA_DIR", os.path.join(BASE_DIR, "data"))
|
||||
|
||||
# Create data directory if it doesn't exist
|
||||
os.makedirs(DATA_DIR, exist_ok=True)
|
||||
|
||||
# Handle absolute path for SQLite (needs 4 slashes on Unix)
|
||||
|
||||
51
backend/logger.py
Normal file
51
backend/logger.py
Normal file
@@ -0,0 +1,51 @@
|
||||
import logging
|
||||
import os
|
||||
from logging.handlers import RotatingFileHandler
|
||||
|
||||
# Define paths
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
# Fallback to local 'logs' dir if not overridden in Docker
|
||||
LOGS_DIR = os.environ.get("LOGS_DIR", os.path.join(BASE_DIR, "logs"))
|
||||
|
||||
# Ensure directory exists
|
||||
os.makedirs(LOGS_DIR, exist_ok=True)
|
||||
|
||||
LOG_FILE_PATH = os.path.join(LOGS_DIR, "backend.log")
|
||||
|
||||
def setup_logger():
|
||||
logger = logging.getLogger("ainventory")
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
# Avoid duplicate handlers if setup multiple times
|
||||
if logger.handlers:
|
||||
return logger
|
||||
|
||||
formatter = logging.Formatter(
|
||||
"[%(asctime)s] [%(levelname)s] [%(name)s] %(message)s",
|
||||
datefmt="%Y-%m-%d %H:%M:%S"
|
||||
)
|
||||
|
||||
# Console Handler
|
||||
console_handler = logging.StreamHandler()
|
||||
console_handler.setFormatter(formatter)
|
||||
|
||||
# File Handler (10MB max, keep 5 backups)
|
||||
file_handler = RotatingFileHandler(
|
||||
LOG_FILE_PATH, maxBytes=10*1024*1024, backupCount=5
|
||||
)
|
||||
file_handler.setFormatter(formatter)
|
||||
|
||||
# Attach handlers
|
||||
logger.addHandler(console_handler)
|
||||
logger.addHandler(file_handler)
|
||||
|
||||
# Special redirect for uvicorn logs to also go to file
|
||||
uvicorn_logger = logging.getLogger("uvicorn")
|
||||
uvicorn_logger.addHandler(file_handler)
|
||||
|
||||
uvicorn_access_logger = logging.getLogger("uvicorn.access")
|
||||
uvicorn_access_logger.addHandler(file_handler)
|
||||
|
||||
return logger
|
||||
|
||||
log = setup_logger()
|
||||
@@ -3,11 +3,14 @@ from fastapi.middleware.cors import CORSMiddleware
|
||||
from . import models
|
||||
from .database import engine
|
||||
from .routers import items, operations, users, categories
|
||||
from .logger import log
|
||||
|
||||
# Create the database tables
|
||||
models.Base.metadata.create_all(bind=engine)
|
||||
log.info("Database tables verified.")
|
||||
|
||||
app = FastAPI(title="TFM aInventory API", version="1.1.0")
|
||||
log.info("TFM aInventory API process started.")
|
||||
|
||||
# Setup Cross-Origin for Client interaction (PWA)
|
||||
app.add_middleware(
|
||||
|
||||
@@ -11,7 +11,7 @@ router = APIRouter(prefix="/users", tags=["users"])
|
||||
pwd_context = CryptContext(schemes=["pbkdf2_sha256"], deprecated="auto")
|
||||
|
||||
def get_ldap_config():
|
||||
config_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "ldap_config.json")
|
||||
config_path = os.path.join(database.DATA_DIR, "ldap_config.json")
|
||||
if os.path.exists(config_path):
|
||||
with open(config_path, "r") as f:
|
||||
return json.load(f)
|
||||
@@ -209,7 +209,7 @@ def get_ldap_settings():
|
||||
|
||||
@router.post("/ldap-config")
|
||||
def update_ldap_settings(config: dict):
|
||||
config_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "ldap_config.json")
|
||||
config_path = os.path.join(database.DATA_DIR, "ldap_config.json")
|
||||
with open(config_path, "w") as f:
|
||||
json.dump(config, f)
|
||||
return {"message": "Config saved"}
|
||||
|
||||
@@ -1,10 +1,58 @@
|
||||
### [2026-04-11 12:05] v1.2.6: Hotfix - Missing Icon Imports
|
||||
**Purpose:** Fixed `ReferenceError: Layers is not defined` and `ChevronDown is not defined` errors by adding missing imports in `admin/page.tsx` and `app/page.tsx`.
|
||||
### [2026-04-11 12:45] v1.3.0: Dockerization & Export Script
|
||||
**Purpose:** Upgraded the system architecture to support seamless dual-mode execution (Dockerized or Bare-Metal/Local). Extracted data and logic persistence layers to external volumes (`/data`, `/logs`). Added a dedicated production compiler.
|
||||
**Actions:**
|
||||
- `backend/database.py` and `users.py` now support `DATA_DIR` environment overrides.
|
||||
- Implemented `backend/logger.py` for standard Python rotating logs mapped to `/app/logs`.
|
||||
- Next.js configured for `standalone` output mode to strictly optimize containerized PWA size.
|
||||
- Orchestrated full environment with `docker-compose.yml`, using Caddy for local self-signed HTTPS termination.
|
||||
- Created `export_prod.sh` to extract a clean release bundle without AI/Dev files (using optimized `rsync`).
|
||||
**Modified Files:**
|
||||
- `frontend/app/admin/page.tsx`
|
||||
- `frontend/app/page.tsx`
|
||||
- `backend/database.py`
|
||||
- `backend/routers/users.py`
|
||||
- `backend/logger.py` (New)
|
||||
- `backend/main.py`
|
||||
- `frontend/next.config.mjs`
|
||||
- `frontend/Dockerfile` (New)
|
||||
- `backend/Dockerfile` (New)
|
||||
- `docker-compose.yml` (New)
|
||||
- `Caddyfile` (New)
|
||||
- `export_prod.sh` (New)
|
||||
- `VERSION.json`
|
||||
|
||||
### [2026-04-11 12:35] v1.2.9: Automatic IDE Entry Points
|
||||
**Purpose:** Restored specific ID-based entry points (`GEMINI.md` and `CLAUDE.md`) as "Proxy Pointers" to ensure modern AI extensions (Cursor, Windsurf, Gemini IDE) naturally pick them up as system prompt injections.
|
||||
**Modified Files:**
|
||||
- `GEMINI.md` (Recreated as proxy)
|
||||
- `CLAUDE.md` (Created as proxy)
|
||||
- `AI_RULES.md`
|
||||
- `VERSION.json`
|
||||
|
||||
### [2026-04-11 12:25] v1.2.8: Absolute Documentation Consolidation
|
||||
**Purpose:** Restructured all project documentation to completely eliminate redundancy and establish clear "Single Source of Truth" boundaries for humans and AI agents.
|
||||
**Actions:**
|
||||
- Created `PROJECT_ARCHITECTURE.md` uniting business requirements, tech stack, data models, and specific OCR algorithms.
|
||||
- Unified all AI operational rules, constraints, and UI fidelities strictly inside `AI_RULES.md`.
|
||||
- Removed redundant, overlapping files (`GEMINI.md`, `requirements.md`, `TECH_STACK.md`, `UI_FIDELITY_SPEC.md`, `SCANNER_LOGIC_SPEC.md`).
|
||||
- Stripped `PLAN.md` down to just the active checklist.
|
||||
**Modified Files:**
|
||||
- `PROJECT_ARCHITECTURE.md` (New)
|
||||
- `AI_RULES.md`
|
||||
- `PLAN.md`
|
||||
- `VERSION.json`
|
||||
|
||||
### [2026-04-11 12:15] v1.2.7: Documentation Refactor & Portability
|
||||
**Purpose:** Consolidated technical stack information into a single source of truth (`dev_docs/TECH_STACK.md`) and removed absolute paths from all AI-facing documents to ensure the project can be moved across environments without breaking references.
|
||||
**Modified Files:**
|
||||
- `dev_docs/TECH_STACK.md` (New)
|
||||
- `GEMINI.md` (Refined)
|
||||
- `AI_RULES.md` (Cleaned)
|
||||
- `PLAN.md` (Referenced tech stack)
|
||||
- `requirements.md` (Referenced tech stack)
|
||||
- `dev_docs/SESSION_STATE.md` (Path cleanup)
|
||||
- `VERSION.json`
|
||||
|
||||
### [2026-04-11 12:05] v1.2.6: Hotfix - Missing Icon Imports
|
||||
|
||||
### [2026-04-11 11:58] v1.2.5: UI Icon Synchronization
|
||||
|
||||
### [2026-04-11 11:45] v1.2.4: Offline Auth & UX Polish
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
# TFM aInventory - Scanner Technical Specification (v1.2)
|
||||
|
||||
This document defines the "Frozen" parameters for the scanner component. Do NOT modify these values without explicit user approval.
|
||||
|
||||
## 1. Hardware Access
|
||||
- **API**: Direct `MediaStreamTrack` access for high-performance camera control.
|
||||
- **Zoom**: Dynamic detection of `capabilities.zoom.max`.
|
||||
- **Zoom Cycle**: 1x -> 2x -> Max/2 -> Max.
|
||||
|
||||
## 2. Image Pre-processing (The OCR "Secret Sauce")
|
||||
Before being sent to Tesseract.js, every frame undergoes these transformations:
|
||||
- **Rescaling**: Fixed canvas width of **1200px** (Optimal for Mobile RAM/Accuracy).
|
||||
- **Cropping**: **60% Center Crop** of the video stream (forces focus & removes peripheral noise).
|
||||
- **Filters**: `grayscale(100%) contrast(180%) brightness(105%)`.
|
||||
- **Format**: High-quality JPEG (`0.85` quality) via `toDataURL`.
|
||||
|
||||
## 3. OCR Matching Engine (page.tsx)
|
||||
- **Sanitization**: Text normalized to UPPERCASE, non-alphanumeric replaced with spaces.
|
||||
- **Noise Filtering**:
|
||||
- Tokens < 3 chars ignored.
|
||||
- Decimals (e.g., `0.11`, `0.18`) ignored via regex: `/^\d+\.\d+$/`.
|
||||
- Dates (e.g., `2024-07-25`) ignored via regex: `/^\d{2,4}-\d{2}-\d{2}$/`.
|
||||
- **Scoring System**:
|
||||
- **Exact Serial Number Match**: +500 points (Instant Match).
|
||||
- **Exact Part Number Match**: +200 points.
|
||||
- **Token match (e.g., "LC" in "LC/UPC")**: +50 points.
|
||||
- **Category Match**: +20 points.
|
||||
- **Threshold**: Minimum **40 points** required for automatic match without user intervention.
|
||||
|
||||
## 4. UI/UX Flow
|
||||
1. **Auto-Match**: Attempt to identify item immediately from raw text.
|
||||
2. **Interactive Selection (Fallback)**: If match confidence is low, freeze frame and show clickable bounding boxes for manual word selection.
|
||||
|
||||
---
|
||||
*Created: 2026-04-10*
|
||||
*Status: FROZEN*
|
||||
@@ -5,6 +5,21 @@ Entries are added here when a new AI session starts.
|
||||
|
||||
---
|
||||
|
||||
**[Archived: 2026-04-11]**
|
||||
**Status**: UI Readability Refactor Completed (v1.2.2). Ready for Phase 6.
|
||||
**Current AI Agent**: Gemini (Antigravity)
|
||||
**Context**:
|
||||
- **UI Readability**: System-wide removal of `uppercase` and `tracking-*`. Font sizes increased from 9px/10px to xs/sm. Title Case applied to major buttons.
|
||||
- **Rules Compliance**: All changes logged in `ARCHIVE_LOGS.md` and `VERSION.json`.
|
||||
- **Git**: Working on branch `dev`. Path persisted in `.git_path`.
|
||||
|
||||
**Next Steps**:
|
||||
1. **Proceed to Phase 6: Audit Log Dashboard UI**. The backend already has `Log` models, but the frontend needs a more comprehensive view beyond the current "Audit History" modal if requested, OR finalize the existing ones.
|
||||
2. Enable LDAP and test with real server (from v1.2.1 goals).
|
||||
3. Deploy v1.2.2 to stable branch if user confirms.
|
||||
|
||||
---
|
||||
|
||||
### Handover Archive (Auto-Archived)
|
||||
**Status**: v1.2.1 Infrastructure Stable.
|
||||
**Current AI Agent**: Gemini (Antigravity)
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
# AI Session State - HANDOVER
|
||||
# CURRENT AI WORKING SESSION
|
||||
|
||||
**Status**: UI Readability Refactor Completed (v1.2.2). Ready for Phase 6.
|
||||
**Current AI Agent**: Gemini (Antigravity)
|
||||
**Context**:
|
||||
- **UI Readability**: System-wide removal of `uppercase` and `tracking-*`. Font sizes increased from 9px/10px to xs/sm. Title Case applied to major buttons.
|
||||
- **Rules Compliance**: All changes logged in `ARCHIVE_LOGS.md` and `VERSION.json`.
|
||||
- **Git**: Working on branch `dev`. Path persisted in `.git_path`.
|
||||
**Active AI:** Antigravity (Gemini)
|
||||
**Last Updated:** 2026-04-11
|
||||
**Current Version:** v1.3.0
|
||||
**Branch:** dev
|
||||
|
||||
**Next Steps**:
|
||||
1. **Proceed to Phase 6: Audit Log Dashboard UI**. The backend already has `Log` models, but the frontend needs a more comprehensive view beyond the current "Audit History" modal if requested, OR finalize the existing ones.
|
||||
2. Enable LDAP and test with real server (from v1.2.1 goals).
|
||||
3. Deploy v1.2.2 to stable branch if user confirms.
|
||||
### Current Status
|
||||
Finalized the system refactoring by implementing a complete, portable **Dockerization Architecture**. Introduced the `export_prod.sh` bundle compiler, centralized technical documentation into a Single Source Of Truth (`PROJECT_ARCHITECTURE.md`), and ensured exact reverse compatibility so that bare-metal development using `./start_server.sh` operates identically to previous versions.
|
||||
|
||||
### Technical Context
|
||||
- **Persistence Mapping:** Local database (`inventory.db`) and `ldap_config.json` now persist through the environmental variable `DATA_DIR` (mapped to local `/data` volume).
|
||||
- **Log System:** Created `backend/logger.py` with Python's RotatingFileHandler. Streamed locally into `/logs`.
|
||||
- **Standalone:** Next.js uses `output: standalone` configuration specifically to support the Node alpine dockerfile. Caddy replaces `local-ssl-proxy` only inside the Docker environment.
|
||||
|
||||
### Next Steps / Blockers
|
||||
1. Testing actual AI flow in production mode (using the exported Production Bundle zip).
|
||||
2. Implementing the Advanced Audit log Dashboard inside the UI.
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
# UI Fidelity Specification
|
||||
|
||||
This document details the mandatory visual and structural specifications for UI components (headers, banners, cards, buttons) in the unified PWA interface.
|
||||
|
||||
## 1. General Principles
|
||||
- Use TailwindCSS (or equivalent local vanilla CSS framework established).
|
||||
- No emojis; strictly Bootstrap Icons.
|
||||
- Standard spacing, consistent font weight (Inter or Roboto).
|
||||
- Responsive: Viewport scaling for both Desktop dashboard and Mobile full-screen scanning modes.
|
||||
|
||||
## 2. Specific Components
|
||||
*(To be populated as components are developed)*
|
||||
53
docker-compose.yml
Normal file
53
docker-compose.yml
Normal file
@@ -0,0 +1,53 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
backend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: backend/Dockerfile
|
||||
networks:
|
||||
- inventory_net
|
||||
ports:
|
||||
- "8000:8000"
|
||||
volumes:
|
||||
- ./data:/app/data
|
||||
- ./logs:/app/logs
|
||||
environment:
|
||||
- DATA_DIR=/app/data
|
||||
- LOGS_DIR=/app/logs
|
||||
restart: unless-stopped
|
||||
|
||||
frontend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: frontend/Dockerfile
|
||||
networks:
|
||||
- inventory_net
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
- ./logs:/app/logs
|
||||
# Write Next.js logs to both stdout (docker logs) and file (mapped volume)
|
||||
command: sh -c "mkdir -p /app/logs && node server.js 2>&1 | tee -a /app/logs/frontend.log"
|
||||
restart: unless-stopped
|
||||
|
||||
proxy:
|
||||
image: caddy:alpine
|
||||
networks:
|
||||
- inventory_net
|
||||
ports:
|
||||
- "3002:3002"
|
||||
- "3003:3003"
|
||||
volumes:
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile
|
||||
# Persist the internal Caddy certificates so users don't get new certificate warnings constantly
|
||||
- ./data/caddy_data:/data
|
||||
- ./data/caddy_config:/config
|
||||
depends_on:
|
||||
- frontend
|
||||
- backend
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
inventory_net:
|
||||
driver: bridge
|
||||
68
export_prod.sh
Executable file
68
export_prod.sh
Executable file
@@ -0,0 +1,68 @@
|
||||
#!/bin/bash
|
||||
# export_prod.sh - Generates a clean production bundle for distribution
|
||||
|
||||
echo "📦 Preparing TFM aInventory Production Bundle..."
|
||||
|
||||
# Extract version from VERSION.json using grep to avoid macOS python/xcode stubs
|
||||
VERSION=$(grep '"version"' VERSION.json | head -n 1 | awk -F '"' '{print $4}')
|
||||
PROD_DIR="aInventory-PROD-v${VERSION}"
|
||||
|
||||
# Clean previous run if it exists
|
||||
rm -rf "$PROD_DIR"
|
||||
rm -f "${PROD_DIR}.zip"
|
||||
|
||||
mkdir -p "$PROD_DIR"
|
||||
|
||||
echo "📂 Copying application components (excluding dev artifacts)..."
|
||||
# Core application
|
||||
rsync -a --exclude 'node_modules' --exclude '.next' frontend/ "$PROD_DIR/frontend/"
|
||||
rsync -a --exclude '__pycache__' --exclude '.pytest_cache' --exclude '.venv' backend/ "$PROD_DIR/backend/"
|
||||
|
||||
# Orchestration & Scripts
|
||||
cp docker-compose.yml "$PROD_DIR/"
|
||||
cp Caddyfile "$PROD_DIR/"
|
||||
cp start_server.sh "$PROD_DIR/"
|
||||
cp run_standalone.sh "$PROD_DIR/"
|
||||
cp install_service.sh "$PROD_DIR/"
|
||||
cp inventory.service.template "$PROD_DIR/"
|
||||
cp USER_GUIDE.md "$PROD_DIR/"
|
||||
cp README.md "$PROD_DIR/INSTALLATION_GUIDE.md"
|
||||
cp .git_path "$PROD_DIR/" 2>/dev/null || true
|
||||
cp VERSION.json "$PROD_DIR/"
|
||||
|
||||
# Setup persistent volume skeleton
|
||||
mkdir -p "$PROD_DIR/data"
|
||||
mkdir -p "$PROD_DIR/logs"
|
||||
# Place a README in the root of the release
|
||||
cat <<EOF > "$PROD_DIR/README.txt"
|
||||
TFM aInventory - v${VERSION}
|
||||
=============================
|
||||
|
||||
This is a clean production build, free of development or AI-agent constraints.
|
||||
|
||||
TO RUN VIA DOCKER (Recommended):
|
||||
1. Install Docker Desktop or Docker Engine.
|
||||
2. Run: docker-compose build
|
||||
3. Run: docker-compose up -d
|
||||
4. Access via https://<YOUR-IP>:3003 (Accept the internal security warning).
|
||||
|
||||
TO INSTALL AS A LINUX SYSTEM SERVICE (Optional):
|
||||
1. sudo ./install_service.sh
|
||||
2. sudo systemctl start inventory
|
||||
|
||||
TO RUN BARE-METAL (No Docker):
|
||||
1. Install Python 3.12+ and Node.js 20+.
|
||||
2. Ensure you have network access for npm installs.
|
||||
3. Run: ./start_server.sh
|
||||
4. Access via https://<YOUR-IP>:3003
|
||||
|
||||
Note: Database and Logs will persist in the /data and /logs directories.
|
||||
EOF
|
||||
|
||||
echo "🗜️ Zipping the final bundle..."
|
||||
zip -r -q "${PROD_DIR}.zip" "$PROD_DIR"
|
||||
|
||||
# Optional: cleanup the directory to leave just the zip
|
||||
# rm -rf "$PROD_DIR"
|
||||
|
||||
echo "✅ SUCCESS: The clean production archive is ready: ${PROD_DIR}.zip"
|
||||
48
frontend/Dockerfile
Normal file
48
frontend/Dockerfile
Normal file
@@ -0,0 +1,48 @@
|
||||
FROM node:20-alpine AS base
|
||||
|
||||
# Step 1: Install dependencies
|
||||
FROM base AS deps
|
||||
RUN apk add --no-cache libc6-compat
|
||||
WORKDIR /app
|
||||
# We run this from the frontend folder context
|
||||
COPY package.json package-lock.json* ./
|
||||
RUN npm ci
|
||||
|
||||
# Step 2: Build the source code
|
||||
FROM base AS builder
|
||||
WORKDIR /app
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
# Disable telemetry during build
|
||||
ENV NEXT_TELEMETRY_DISABLED 1
|
||||
RUN npm run build
|
||||
|
||||
# Step 3: Production image
|
||||
FROM base AS runner
|
||||
WORKDIR /app
|
||||
|
||||
ENV NODE_ENV production
|
||||
ENV NEXT_TELEMETRY_DISABLED 1
|
||||
|
||||
# Add nextjs user
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 nextjs
|
||||
|
||||
# Copy standalone output
|
||||
COPY --from=builder /app/public ./public
|
||||
# Set proper permissions for the Next.js cache
|
||||
RUN mkdir .next
|
||||
RUN chown nextjs:nodejs .next
|
||||
|
||||
# Automatically leverage output traces to reduce image size
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||
|
||||
USER nextjs
|
||||
|
||||
EXPOSE 3000
|
||||
ENV PORT 3000
|
||||
ENV HOSTNAME "0.0.0.0"
|
||||
|
||||
# Note: The server.js is created by next build from the standalone output
|
||||
CMD ["node", "server.js"]
|
||||
@@ -9,7 +9,7 @@ const withPWA = withPWAInit({
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
// Config options here
|
||||
output: "standalone",
|
||||
};
|
||||
|
||||
export default withPWA(nextConfig);
|
||||
|
||||
69
install_service.sh
Executable file
69
install_service.sh
Executable file
@@ -0,0 +1,69 @@
|
||||
#!/bin/bash
|
||||
# install_service.sh - Installs the inventory system as a standalone systemd service
|
||||
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo "🚫 This script must be run as root (use sudo)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "⚙️ Installing TFM aInventory as a Standalone Linux service..."
|
||||
|
||||
# Detect working directory
|
||||
WORKING_DIR="$(pwd)"
|
||||
|
||||
# 1. Dependency Checks
|
||||
echo "🔍 Checking dependencies..."
|
||||
for cmd in python3 node npm; do
|
||||
if ! command -v $cmd &> /dev/null; then
|
||||
echo "❌ $cmd not found! Please install it before proceeding."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# 2. Setup Backend Environment
|
||||
echo "🐍 Setting up Python Virtual Environment..."
|
||||
if [ ! -d ".venv" ]; then
|
||||
python3 -m venv .venv
|
||||
fi
|
||||
source .venv/bin/activate
|
||||
pip install -q --upgrade pip
|
||||
pip install -q -r backend/requirements.txt
|
||||
|
||||
# 3. Setup Frontend Environment
|
||||
echo "📦 Installing Node dependencies (this may take a minute)..."
|
||||
cd frontend
|
||||
npm install --quiet
|
||||
echo "🏗️ Building Frontend for Production (Next.js build)..."
|
||||
npm run build
|
||||
cd ..
|
||||
|
||||
# 4. Create the final service file from template
|
||||
TEMPLATE="inventory.service.template"
|
||||
TARGET="/etc/systemd/system/inventory.service"
|
||||
|
||||
if [ ! -f "$TEMPLATE" ]; then
|
||||
echo "❌ Template file $TEMPLATE not found in current directory!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sed "s|__WORKING_DIR__|$WORKING_DIR|g" "$TEMPLATE" > "$TARGET"
|
||||
|
||||
echo "📝 Service file created at $TARGET"
|
||||
|
||||
# 5. Reload and enable
|
||||
systemctl daemon-reload
|
||||
systemctl enable inventory.service
|
||||
|
||||
# 6. Ensure scripts are executable
|
||||
chmod +x run_standalone.sh
|
||||
chmod +x start_server.sh
|
||||
|
||||
echo ""
|
||||
echo "🚀 TFM aInventory Standalone service installed and enabled!"
|
||||
echo " Commands:"
|
||||
echo " 👉 sudo systemctl start inventory"
|
||||
echo " 👉 sudo systemctl status inventory"
|
||||
echo " 👉 sudo systemctl stop inventory"
|
||||
echo ""
|
||||
echo "Note: The service is currently ENABLED to start on boot, but NOT started."
|
||||
echo " Run 'sudo systemctl start inventory' to launch it now."
|
||||
17
inventory.service.template
Normal file
17
inventory.service.template
Normal file
@@ -0,0 +1,17 @@
|
||||
[Unit]
|
||||
Description=TFM aInventory Docker Stack
|
||||
After=docker.service
|
||||
Requires=docker.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=__WORKING_DIR__
|
||||
ExecStart=/bin/bash __WORKING_DIR__/run_standalone.sh
|
||||
# No explicit ExecStop needed as kill 0 in run_standalone handles it,
|
||||
# but systemd handles SIGTERM by default anyway.
|
||||
Restart=always
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,35 +0,0 @@
|
||||
# Inventory Application Requirements
|
||||
|
||||
## 1. Description
|
||||
A unified system to maintain an inventory of "items" and their quantities, inclusive of a web administration interface, offline field operations, audit logging, and AI-powered label extraction functionalities.
|
||||
|
||||
## 2. Core Constraints & System Elements
|
||||
|
||||
### 2.1 Main Application Server (Linux Backend)
|
||||
* **Target Environment:** Dockerized Linux Environment.
|
||||
* **Framework:** Python (FastAPI) + SQLite database.
|
||||
* **Users & Security:** Support multiple authenticated users (PBKDF2 local + optional LDAP).
|
||||
* **Audit Compliance:** All operations maintain a strict audit log (unique UUIDs, details).
|
||||
|
||||
### 2.2 Client Interface (PWA - Progressive Web App)
|
||||
* **Unified Interface:** A single Web Application (Next.js or similar) that is fully responsive. It functions as the administration dashboard on desktop and as a mobile application on phones/tablets.
|
||||
* **Installation:** Installed on mobile devices directly via the browser ("Add to Home Screen") to bypass App Stores. Completely managed by the main Linux Server.
|
||||
* **Offline Mode:** Service Workers and local browser storage (IndexedDB) must cache the inventory catalog, allowing offline check-ins/check-outs. Modifications are synced to the Linux server upon network reconnection.
|
||||
* **Hardware Access:** Must natively tap into the device's camera via HTML5 APIs to capture barcode data or full images.
|
||||
|
||||
### 2.3 Scanning & AI processing Cost-Optimization Strategy (Crucial)
|
||||
* **Routine Operations (Check-in / Check-out):** Utilize client-side, offline Javascript libraries (e.g., `html5-qrcode`) to read 1D/2D barcodes directly in the browser's camera. This executes entirely on the local device unconditionally and uses no AI cloud credits.
|
||||
* **New Item Onboarding (AI Label OCR):** When an unknown label is encountered or a specific new item is being created, the user takes a high-res photo. This photo is sent to the backend, which proxies a minimal request to a Cloud AI API (e.g., OpenAI / GPT-4 Vision).
|
||||
* **Template Extraction:** The AI performs standard OCR & structure extraction based on strict prompting templates. The parsed elements are transmitted back to the client interface.
|
||||
* **Validation Mask:** The client interface explicitly presents a selection mask. The user selects which parsed strings/fields map to specific Item properties (e.g., identifying the actual serial number while discarding vendor identifiers) before committing the Item to the database.
|
||||
|
||||
### 2.4 Data Models & Entities
|
||||
* **Item:** Name, Category Group (Structured), Item Type (Specific), Quantity, Barcode, Part Number.
|
||||
* **Category:** Predefined groups for organizational structure (e.g., Connectors, Tools).
|
||||
* **Intervention:** Linked to a required items list.
|
||||
* **Audit Log:** Immutable ledger detailing CRUD operations and stock fluctuations.
|
||||
|
||||
### 2.5 Workflows & Reporting
|
||||
* **Reports:** Quantity aggregates across all items/categories, with historical tracking of item usage intervals (last month, last 6 months, last year).
|
||||
* **Notifications:** Alert generation when stock drops below minimum quantities.
|
||||
* **Intervention Planning:** Loading intervention lists (Text/Scanning). Check-outs must fulfill matching lists incrementally, while Check-ins reconcile unused stock.
|
||||
49
run_standalone.sh
Executable file
49
run_standalone.sh
Executable file
@@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
# run_standalone.sh - Headless production launcher for TFM aInventory
|
||||
# manages Backend, Frontend, and SSL Proxies in a single process group.
|
||||
|
||||
echo "🚀 Starting TFM aInventory in Standalone Mode..."
|
||||
|
||||
# Trapping termination signals to clean up child processes
|
||||
trap "echo 'Stopping all processes...'; kill 0" SIGINT SIGTERM EXIT
|
||||
|
||||
# --- CONFIGURATION (Match start_server.sh) ---
|
||||
BACKEND_PORT=8000
|
||||
FRONTEND_PORT=3001
|
||||
BACKEND_SSL_PORT=3002
|
||||
FRONTEND_SSL_PORT=3003
|
||||
|
||||
# 1. Activate Environment
|
||||
if [ -d ".venv" ]; then
|
||||
source .venv/bin/activate
|
||||
fi
|
||||
|
||||
# 2. Start Backend (No Reload for Prod)
|
||||
echo "🔥 Starting Backend (Uvicorn)..."
|
||||
python3 -m uvicorn backend.main:app --host 0.0.0.0 --port $BACKEND_PORT &
|
||||
|
||||
# 3. Start Frontend (Production Start)
|
||||
echo "💻 Starting Frontend (Next.js Prod)..."
|
||||
cd frontend
|
||||
npm run start -- -p $FRONTEND_PORT &
|
||||
cd ..
|
||||
|
||||
# 4. Start Proxies (via npx)
|
||||
echo "🛡️ Starting HTTPS Proxies..."
|
||||
npx local-ssl-proxy --source $BACKEND_SSL_PORT --target $BACKEND_PORT --hostname 0.0.0.0 > /dev/null 2>&1 &
|
||||
npx local-ssl-proxy --source $FRONTEND_SSL_PORT --target $FRONTEND_PORT --hostname 0.0.0.0 > /dev/null 2>&1 &
|
||||
|
||||
# 5. Detection of IP for logs
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
LOCAL_IP=$(ipconfig getifaddr en0 || ipconfig getifaddr en1 || echo "localhost")
|
||||
else
|
||||
LOCAL_IP=$(hostname -I | awk '{print $1}')
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "✅ TFM aInventory is active at https://$LOCAL_IP:$FRONTEND_SSL_PORT"
|
||||
echo " Processes are running in background. Monitoring logs..."
|
||||
echo ""
|
||||
|
||||
# Wait for children
|
||||
wait
|
||||
Reference in New Issue
Block a user