bmc_hub/app/modules/_template/README.md
Christian 0502a7b080 feat: Implement central tagging system with CRUD operations, entity tagging, and workflow management
- Added API endpoints for tag management (create, read, update, delete).
- Implemented entity tagging functionality to associate tags with various entities.
- Created workflow management for tag-triggered actions.
- Developed frontend views for tag administration using FastAPI and Jinja2.
- Designed HTML template for tag management interface with Bootstrap styling.
- Added JavaScript for tag picker component with keyboard shortcuts and dynamic tag filtering.
- Created database migration scripts for tags, entity_tags, and tag_workflows tables.
- Included default tags for initial setup in the database.
2025-12-17 07:56:33 +01:00

4.1 KiB

Template Module

Dette er template strukturen for nye BMC Hub moduler.

Struktur

my_module/
├── module.json          # Metadata og konfiguration
├── README.md            # Dokumentation
├── backend/
│   ├── __init__.py
│   └── router.py        # FastAPI routes (API endpoints)
├── frontend/
│   ├── __init__.py
│   └── views.py         # HTML view routes
├── templates/
│   └── index.html       # Jinja2 templates
└── migrations/
    └── 001_init.sql     # Database migrations

Opret nyt modul

python scripts/create_module.py my_module "My Module Description"

Database Tables

Alle tabeller SKAL bruge table_prefix fra module.json:

-- Hvis table_prefix = "mymod_"
CREATE TABLE mymod_items (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255)
);

Dette sikrer at moduler ikke kolliderer med core eller andre moduler.

Customer Linking (Hvis nødvendigt)

Hvis dit modul skal have sin egen kunde-tabel (f.eks. ved sync fra eksternt system):

SKAL altid linke til core customers:

CREATE TABLE mymod_customers (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    external_id VARCHAR(100),  -- ID fra eksternt system
    hub_customer_id INTEGER REFERENCES customers(id),  -- VIGTIG!
    active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Auto-link trigger (se migrations/001_init.sql for komplet eksempel)
CREATE TRIGGER trigger_auto_link_mymod_customer
    BEFORE INSERT OR UPDATE OF name
    ON mymod_customers
    FOR EACH ROW
    EXECUTE FUNCTION auto_link_mymod_customer();

Hvorfor? Dette sikrer at:

  • E-conomic export virker automatisk
  • Billing integration fungerer
  • Ingen manuel linking nødvendig

Alternativ: Hvis modulet kun har simple kunde-relationer, brug direkte FK:

CREATE TABLE mymod_orders (
    id SERIAL PRIMARY KEY,
    customer_id INTEGER REFERENCES customers(id)  -- Direkte link
);

Konfiguration

Modul-specifikke miljøvariable følger mønsteret:

MODULES__MY_MODULE__API_KEY=secret123
MODULES__MY_MODULE__READ_ONLY=true

Tilgå i kode:

from app.core.config import get_module_config

api_key = get_module_config("my_module", "API_KEY")
read_only = get_module_config("my_module", "READ_ONLY", default="true") == "true"

Database Queries

Brug ALTID helper functions fra app.core.database:

from app.core.database import execute_query, execute_insert

# Fetch
customers = execute_query(
    "SELECT * FROM mymod_customers WHERE active = %s", 
    (True,)
)

# Insert
customer_id = execute_insert(
    "INSERT INTO mymod_customers (name) VALUES (%s)",
    ("Test Customer",)
)

Migrations

Migrations ligger i migrations/ og køres manuelt eller via migration tool:

from app.core.database import execute_module_migration

with open("migrations/001_init.sql") as f:
    migration_sql = f.read()
    
success = execute_module_migration("my_module", migration_sql)

Enable/Disable

# Enable via API
curl -X POST http://localhost:8000/api/v1/modules/my_module/enable

# Eller rediger module.json
{
  "enabled": true
}

# Restart app
docker-compose restart api

Fejlhåndtering

Moduler er isolerede - hvis dit modul crasher ved opstart:

  • Core systemet kører videre
  • Modulet bliver ikke loaded
  • Fejl logges til console og logs/app.log

Runtime fejl i endpoints påvirker ikke andre moduler.

Testing

import pytest
from app.core.database import execute_query

def test_my_module():
    # Test bruger samme database helpers
    result = execute_query("SELECT 1 as test")
    assert result[0]["test"] == 1

Best Practices

  1. Database isolering: Brug ALTID table_prefix fra module.json
  2. Safety switches: Tilføj READ_ONLY og DRY_RUN flags
  3. Error handling: Log fejl, raise HTTPException med status codes
  4. Dependencies: Deklarer i module.json hvis du bruger andre moduler
  5. Migrations: Nummer sekventielt (001, 002, 003...)
  6. Documentation: Opdater README.md med API endpoints og use cases