- Added a new column `subscriptions_locked` to the `customers` table to manage subscription access. - Implemented a script to create new modules from a template, including updates to various files (module.json, README.md, router.py, views.py, and migration SQL). - Developed a script to import BMC Office subscriptions from an Excel file into the database, including error handling and statistics reporting. - Created a script to lookup and update missing CVR numbers using the CVR.dk API. - Implemented a script to relink Hub customers to e-conomic customer numbers based on name matching. - Developed scripts to sync CVR numbers from Simply-CRM and vTiger to the local customers database.
190 lines
6.7 KiB
Python
Executable File
190 lines
6.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Create Module Script
|
|
Generer et nyt BMC Hub modul fra template
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import json
|
|
import shutil
|
|
from pathlib import Path
|
|
|
|
|
|
def create_module(module_name: str, description: str = ""):
|
|
"""
|
|
Opret nyt modul baseret på _template
|
|
|
|
Args:
|
|
module_name: Navn på nyt modul (fx "my_module")
|
|
description: Beskrivelse af modul
|
|
"""
|
|
|
|
# Validate module name
|
|
if not module_name.replace("_", "").isalnum():
|
|
print(f"❌ Ugyldigt modul navn: {module_name}")
|
|
print(" Brug kun bogstaver, tal og underscore")
|
|
sys.exit(1)
|
|
|
|
# Paths
|
|
project_root = Path(__file__).parent.parent
|
|
modules_dir = project_root / "app" / "modules"
|
|
template_dir = modules_dir / "_template"
|
|
new_module_dir = modules_dir / module_name
|
|
|
|
# Check if template exists
|
|
if not template_dir.exists():
|
|
print(f"❌ Template directory ikke fundet: {template_dir}")
|
|
sys.exit(1)
|
|
|
|
# Check if module already exists
|
|
if new_module_dir.exists():
|
|
print(f"❌ Modul '{module_name}' eksisterer allerede")
|
|
sys.exit(1)
|
|
|
|
print(f"📦 Opretter modul: {module_name}")
|
|
print(f" Placering: {new_module_dir}")
|
|
|
|
# Copy template
|
|
try:
|
|
shutil.copytree(template_dir, new_module_dir)
|
|
print(f"✅ Kopieret template struktur")
|
|
except Exception as e:
|
|
print(f"❌ Kunne ikke kopiere template: {e}")
|
|
sys.exit(1)
|
|
|
|
# Update module.json
|
|
manifest_path = new_module_dir / "module.json"
|
|
try:
|
|
with open(manifest_path, 'r', encoding='utf-8') as f:
|
|
manifest = json.load(f)
|
|
|
|
manifest["name"] = module_name
|
|
manifest["description"] = description or f"BMC Hub module: {module_name}"
|
|
manifest["table_prefix"] = f"{module_name}_"
|
|
manifest["api_prefix"] = f"/api/v1/{module_name}"
|
|
manifest["tags"] = [module_name.replace("_", " ").title()]
|
|
|
|
with open(manifest_path, 'w', encoding='utf-8') as f:
|
|
json.dump(manifest, f, indent=2, ensure_ascii=False)
|
|
|
|
print(f"✅ Opdateret module.json")
|
|
except Exception as e:
|
|
print(f"❌ Kunne ikke opdatere module.json: {e}")
|
|
sys.exit(1)
|
|
|
|
# Update README.md
|
|
readme_path = new_module_dir / "README.md"
|
|
try:
|
|
with open(readme_path, 'r', encoding='utf-8') as f:
|
|
readme = f.read()
|
|
|
|
# Replace template references
|
|
readme = readme.replace("Template Module", f"{module_name.replace('_', ' ').title()} Module")
|
|
readme = readme.replace("template_module", module_name)
|
|
readme = readme.replace("my_module", module_name)
|
|
readme = readme.replace("mymod_", f"{module_name}_")
|
|
readme = readme.replace("template_", f"{module_name}_")
|
|
|
|
with open(readme_path, 'w', encoding='utf-8') as f:
|
|
f.write(readme)
|
|
|
|
print(f"✅ Opdateret README.md")
|
|
except Exception as e:
|
|
print(f"⚠️ Kunne ikke opdatere README: {e}")
|
|
|
|
# Update backend/router.py
|
|
router_path = new_module_dir / "backend" / "router.py"
|
|
try:
|
|
with open(router_path, 'r', encoding='utf-8') as f:
|
|
router_code = f.read()
|
|
|
|
router_code = router_code.replace("Template Module", f"{module_name.replace('_', ' ').title()} Module")
|
|
router_code = router_code.replace("template_module", module_name)
|
|
router_code = router_code.replace("template_items", f"{module_name}_items")
|
|
router_code = router_code.replace("/template/", f"/{module_name}/")
|
|
|
|
with open(router_path, 'w', encoding='utf-8') as f:
|
|
f.write(router_code)
|
|
|
|
print(f"✅ Opdateret backend/router.py")
|
|
except Exception as e:
|
|
print(f"⚠️ Kunne ikke opdatere router: {e}")
|
|
|
|
# Update frontend/views.py
|
|
views_path = new_module_dir / "frontend" / "views.py"
|
|
try:
|
|
with open(views_path, 'r', encoding='utf-8') as f:
|
|
views_code = f.read()
|
|
|
|
views_code = views_code.replace("Template Module", f"{module_name.replace('_', ' ').title()} Module")
|
|
views_code = views_code.replace("template_module", module_name)
|
|
views_code = views_code.replace("template_items", f"{module_name}_items")
|
|
views_code = views_code.replace("/template", f"/{module_name}")
|
|
views_code = views_code.replace("_template", module_name)
|
|
|
|
with open(views_path, 'w', encoding='utf-8') as f:
|
|
f.write(views_code)
|
|
|
|
print(f"✅ Opdateret frontend/views.py")
|
|
except Exception as e:
|
|
print(f"⚠️ Kunne ikke opdatere views: {e}")
|
|
|
|
# Update migration SQL
|
|
migration_path = new_module_dir / "migrations" / "001_init.sql"
|
|
try:
|
|
with open(migration_path, 'r', encoding='utf-8') as f:
|
|
migration_sql = f.read()
|
|
|
|
migration_sql = migration_sql.replace("Template Module", f"{module_name.replace('_', ' ').title()} Module")
|
|
migration_sql = migration_sql.replace("template_items", f"{module_name}_items")
|
|
migration_sql = migration_sql.replace("template_module", module_name)
|
|
|
|
with open(migration_path, 'w', encoding='utf-8') as f:
|
|
f.write(migration_sql)
|
|
|
|
print(f"✅ Opdateret migrations/001_init.sql")
|
|
except Exception as e:
|
|
print(f"⚠️ Kunne ikke opdatere migration: {e}")
|
|
|
|
print()
|
|
print("🎉 Modul oprettet successfully!")
|
|
print()
|
|
print("Næste steps:")
|
|
print(f"1. Kør database migration:")
|
|
print(f" psql -U bmc_hub -d bmc_hub -f app/modules/{module_name}/migrations/001_init.sql")
|
|
print()
|
|
print(f"2. Enable modulet:")
|
|
print(f" Rediger app/modules/{module_name}/module.json og sæt 'enabled': true")
|
|
print()
|
|
print(f"3. Restart API:")
|
|
print(f" docker-compose restart api")
|
|
print()
|
|
print(f"4. Test endpoints:")
|
|
print(f" http://localhost:8000/api/docs#{module_name.replace('_', '-').title()}")
|
|
print(f" http://localhost:8000/{module_name}")
|
|
print()
|
|
print(f"5. Tilføj modul-specifik konfiguration til .env:")
|
|
print(f" MODULES__{module_name.upper()}__READ_ONLY=false")
|
|
print(f" MODULES__{module_name.upper()}__DRY_RUN=false")
|
|
print()
|
|
|
|
|
|
def main():
|
|
"""Main entry point"""
|
|
if len(sys.argv) < 2:
|
|
print("Usage: python scripts/create_module.py <module_name> [description]")
|
|
print()
|
|
print("Eksempel:")
|
|
print(' python scripts/create_module.py my_feature "My awesome feature"')
|
|
sys.exit(1)
|
|
|
|
module_name = sys.argv[1]
|
|
description = sys.argv[2] if len(sys.argv) > 2 else ""
|
|
|
|
create_module(module_name, description)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|