- Implement tests for the internet connections module, covering routes, IP range creation, and connection validation. - Add tests for the Invoice2DataService to validate extraction from GlobalConnect invoices. - Create tests for subscription network provisioning, ensuring proper handling of network items and IP allocations. - Include validation checks for subtotal mismatches and ensure error handling for missing IP selections.
173 lines
7.0 KiB
Python
173 lines
7.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Reset internet connection data and rebuild from latest GlobalConnect extractions."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
from collections import defaultdict
|
|
|
|
from app.billing.backend.supplier_invoices import _sync_globalconnect_extraction_to_internet
|
|
from app.core.database import execute_query, execute_query_single, execute_update, init_db
|
|
|
|
|
|
def latest_globalconnect_extractions() -> list[dict]:
|
|
rows = execute_query(
|
|
"""
|
|
SELECT DISTINCT ON (e.file_id)
|
|
e.extraction_id,
|
|
e.file_id,
|
|
e.vendor_name,
|
|
e.document_id,
|
|
e.document_date,
|
|
e.created_at,
|
|
i.filename
|
|
FROM extractions e
|
|
JOIN incoming_files i ON i.file_id = e.file_id
|
|
WHERE LOWER(COALESCE(e.vendor_name, '')) LIKE '%%globalconnect%%'
|
|
ORDER BY e.file_id, e.created_at DESC, e.extraction_id DESC
|
|
"""
|
|
) or []
|
|
return [dict(row) for row in rows]
|
|
|
|
|
|
def reset_all_internet_data() -> dict:
|
|
summary: dict[str, int] = {}
|
|
counts = execute_query_single(
|
|
"""
|
|
SELECT
|
|
(SELECT COUNT(*) FROM internet_connections_connections WHERE deleted_at IS NULL) AS connections,
|
|
(SELECT COUNT(*) FROM internet_connections_ip_ranges WHERE deleted_at IS NULL) AS ip_ranges,
|
|
(SELECT COUNT(*) FROM internet_connections_ip_addresses WHERE deleted_at IS NULL) AS ip_addresses,
|
|
(SELECT COUNT(*) FROM internet_connections_pricing) AS pricing,
|
|
(SELECT COUNT(*) FROM internet_connections_history) AS history
|
|
"""
|
|
) or {}
|
|
summary["before_connections"] = int(counts.get("connections") or 0)
|
|
summary["before_ip_ranges"] = int(counts.get("ip_ranges") or 0)
|
|
summary["before_ip_addresses"] = int(counts.get("ip_addresses") or 0)
|
|
summary["before_pricing"] = int(counts.get("pricing") or 0)
|
|
summary["before_history"] = int(counts.get("history") or 0)
|
|
|
|
summary["deleted_ip_addresses"] = execute_update(
|
|
"""
|
|
UPDATE internet_connections_ip_addresses
|
|
SET deleted_at = CURRENT_TIMESTAMP,
|
|
updated_at = CURRENT_TIMESTAMP,
|
|
comment = CONCAT(
|
|
COALESCE(comment, ''),
|
|
CASE WHEN COALESCE(comment, '') = '' THEN '' ELSE E'\n' END,
|
|
'Nulstillet før ren genimport af internetforbindelser.'
|
|
)
|
|
WHERE deleted_at IS NULL
|
|
"""
|
|
)
|
|
summary["deleted_ip_ranges"] = execute_update(
|
|
"""
|
|
UPDATE internet_connections_ip_ranges
|
|
SET deleted_at = CURRENT_TIMESTAMP,
|
|
updated_at = CURRENT_TIMESTAMP,
|
|
description = CONCAT(
|
|
COALESCE(description, ''),
|
|
CASE WHEN COALESCE(description, '') = '' THEN '' ELSE E'\n' END,
|
|
'Nulstillet før ren genimport af internetforbindelser.'
|
|
)
|
|
WHERE deleted_at IS NULL
|
|
"""
|
|
)
|
|
summary["deleted_connections"] = execute_update(
|
|
"""
|
|
UPDATE internet_connections_connections
|
|
SET deleted_at = CURRENT_TIMESTAMP,
|
|
updated_at = CURRENT_TIMESTAMP,
|
|
status = 'inactive',
|
|
notes = CONCAT(
|
|
COALESCE(notes, ''),
|
|
CASE WHEN COALESCE(notes, '') = '' THEN '' ELSE E'\n' END,
|
|
'Nulstillet før ren genimport af internetforbindelser.'
|
|
)
|
|
WHERE deleted_at IS NULL
|
|
"""
|
|
)
|
|
summary["deleted_pricing"] = execute_update("DELETE FROM internet_connections_pricing")
|
|
summary["deleted_history"] = execute_update("DELETE FROM internet_connections_history")
|
|
return summary
|
|
|
|
|
|
def rebuild_from_globalconnect() -> dict:
|
|
extractions = latest_globalconnect_extractions()
|
|
results = []
|
|
totals = defaultdict(int)
|
|
|
|
for extraction_stub in extractions:
|
|
extraction = execute_query_single(
|
|
"""
|
|
SELECT *
|
|
FROM extractions
|
|
WHERE extraction_id = %s
|
|
""",
|
|
(extraction_stub["extraction_id"],),
|
|
)
|
|
if not extraction:
|
|
continue
|
|
result = _sync_globalconnect_extraction_to_internet(dict(extraction))
|
|
result_summary = {
|
|
"file_id": extraction_stub["file_id"],
|
|
"extraction_id": extraction_stub["extraction_id"],
|
|
"filename": extraction_stub["filename"],
|
|
"document_id": extraction_stub["document_id"],
|
|
"connections_synced": int(result.get("connections_synced") or 0),
|
|
"connections_created": int(result.get("connections_created") or 0),
|
|
"connections_updated": int(result.get("connections_updated") or 0),
|
|
"ip_ranges_synced": int(result.get("ip_ranges_synced") or 0),
|
|
"skipped_connection_lines": int(result.get("skipped_connection_lines") or 0),
|
|
"skipped_ip_range_lines": int(result.get("skipped_orphan_ip_ranges") or 0),
|
|
"verification": result.get("verification") or {},
|
|
}
|
|
results.append(result_summary)
|
|
totals["files_processed"] += 1
|
|
totals["connections_synced"] += result_summary["connections_synced"]
|
|
totals["connections_created"] += result_summary["connections_created"]
|
|
totals["connections_updated"] += result_summary["connections_updated"]
|
|
totals["ip_ranges_synced"] += result_summary["ip_ranges_synced"]
|
|
totals["skipped_connection_lines"] += result_summary["skipped_connection_lines"]
|
|
totals["skipped_ip_range_lines"] += result_summary["skipped_ip_range_lines"]
|
|
|
|
counts = execute_query_single(
|
|
"""
|
|
SELECT
|
|
(SELECT COUNT(*) FROM internet_connections_connections WHERE deleted_at IS NULL) AS active_connections,
|
|
(SELECT COUNT(*) FROM internet_connections_connections WHERE deleted_at IS NULL AND (address IS NULL OR BTRIM(address) = '')) AS missing_address_connections,
|
|
(SELECT COUNT(*) FROM internet_connections_ip_ranges WHERE deleted_at IS NULL) AS active_ip_ranges,
|
|
(SELECT COUNT(*) FROM internet_connections_ip_addresses WHERE deleted_at IS NULL) AS active_ip_addresses
|
|
"""
|
|
) or {}
|
|
return {
|
|
"totals": dict(totals),
|
|
"results": results,
|
|
"post_counts": {
|
|
"active_connections": int(counts.get("active_connections") or 0),
|
|
"missing_address_connections": int(counts.get("missing_address_connections") or 0),
|
|
"active_ip_ranges": int(counts.get("active_ip_ranges") or 0),
|
|
"active_ip_addresses": int(counts.get("active_ip_addresses") or 0),
|
|
},
|
|
}
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--skip-rebuild", action="store_true", help="Only reset internet data")
|
|
args = parser.parse_args()
|
|
|
|
init_db()
|
|
payload = {
|
|
"reset": reset_all_internet_data(),
|
|
"rebuild": None if args.skip_rebuild else rebuild_from_globalconnect(),
|
|
}
|
|
print(json.dumps(payload, ensure_ascii=False, indent=2, default=str))
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|