#!/usr/bin/env python3 """ Script pour recréer toutes les relations Hasura avec les noms camelCase. Utilise l'API metadata Hasura pour créer les relations manquantes. """ import json import subprocess import sys ADMIN_SECRET = 'Digitribe972' METADATA_URL = 'http://localhost:8082/v1/metadata' GRAPHQL_URL = 'http://localhost:8082/v1/graphql' def graphql_query(query): """Execute a GraphQL query and return the result.""" r = subprocess.run( ['curl', '-s', '-X', 'POST', GRAPHQL_URL, '-H', f'x-hasura-admin-secret: {ADMIN_SECRET}', '-H', 'Content-Type: application/json', '-d', json.dumps({"query": query})], capture_output=True, text=True, timeout=15 ) return json.loads(r.stdout) def metadata_command(payload): """Execute a metadata command and return the result.""" r = subprocess.run( ['curl', '-s', '-X', 'POST', METADATA_URL, '-H', f'x-hasura-admin-secret: {ADMIN_SECRET}', '-H', 'Content-Type: application/json', '-d', json.dumps(payload)], capture_output=True, text=True, timeout=15 ) return json.loads(r.stdout) def test_relation(table, relation, fields='{ id }'): """Test if a relation works by querying it.""" query = f'{{ {table}(where: {{id: {{_eq: "CP001"}}}}) {{ id {relation} {fields} }} }}' result = graphql_query(query) if 'errors' in result: return False, result['errors'][0]['message'][:100] return True, "OK" def create_relation(table, name, rel_type, remote_table, col_map): """Create a relationship in Hasura.""" if rel_type == 'object': payload = { "type": "pg_create_object_relationship", "args": { "source": "default", "table": {"schema": "public", "name": table}, "name": name, "using": { "manual_configuration": { "remote_table": {"schema": "public", "name": remote_table}, "column_mapping": col_map } } } } else: payload = { "type": "pg_create_array_relationship", "args": { "source": "default", "table": {"schema": "public", "name": table}, "name": name, "using": { "manual_configuration": { "remote_table": {"schema": "public", "name": remote_table}, "column_mapping": col_map } } } } result = metadata_command(payload) if 'message' in result and result['message'] == 'success': return True elif 'error' in result: if 'already exists' in result['error']: return True # Already exists, that's OK print(f" ERROR: {result['error'][:200]}") return False return False def main(): print("=== Diagnostic des relations Hasura ===\n") # Test critical relations critical_relations = [ ("ChargingStations", "location", "{ id name }"), ("ChargingStations", "evses", "{ id evseId }"), ("ChargingStations", "connectors", "{ id status }"), ("ChargingStations", "transactions", "{ id }"), ("ChargingStations", "latestStatusNotifications", "{ statusNotification { connectorStatus } }"), ("ChargingStations", "tenant", "{ id name }"), ("Evses", "connectors", "{ id status }"), ("Transactions", "chargingStation", "{ id }"), ("Transactions", "evse", "{ id }"), ("Transactions", "connector", "{ id }"), ("Transactions", "location", "{ id name }"), ("LatestStatusNotifications", "statusNotification", "{ connectorStatus }"), ] print("Test des relations critiques:") all_ok = True for table, relation, fields in critical_relations: ok, msg = test_relation(table, relation, fields) status = "OK" if ok else "FAIL" print(f" {status}: {table}.{relation}") if not ok: all_ok = False print(f" -> {msg}") if all_ok: print("\n=== Toutes les relations fonctionnent ! ===") return print("\n=== Recréation des relations manquantes ===\n") # Define all relations to create relations = [ # ChargingStations ("ChargingStations", "location", "object", "Locations", {"locationId": "id"}), ("ChargingStations", "tenant", "object", "Tenants", {"tenantId": "id"}), ("ChargingStations", "evses", "array", "Evses", {"id": "stationId"}), ("ChargingStations", "connectors", "array", "Connectors", {"id": "stationId"}), ("ChargingStations", "transactions", "array", "Transactions", {"id": "stationId"}), ("ChargingStations", "latestStatusNotifications", "array", "LatestStatusNotifications", {"id": "stationId"}), ("ChargingStations", "variableAttributes", "array", "VariableAttributes", {"id": "stationPkId"}), # Evses ("Evses", "connectors", "array", "Connectors", {"evseId": "evseId"}), ("Evses", "transactions", "array", "Transactions", {"evseId": "evseId"}), ("Evses", "chargingStation", "object", "ChargingStations", {"stationId": "id"}), # Connectors ("Connectors", "evse", "object", "Evses", {"evseId": "id"}), ("Connectors", "chargingStation", "object", "ChargingStations", {"stationId": "id"}), # Transactions ("Transactions", "chargingStation", "object", "ChargingStations", {"stationId": "id"}), ("Transactions", "evse", "object", "Evses", {"evseId": "id"}), ("Transactions", "connector", "object", "Connectors", {"connectorId": "id"}), ("Transactions", "authorization", "object", "Authorizations", {"authorizationId": "id"}), ("Transactions", "location", "object", "Locations", {"locationId": "id"}), # LatestStatusNotifications ("LatestStatusNotifications", "statusNotification", "object", "StatusNotifications", {"statusNotificationId": "id"}), ("LatestStatusNotifications", "chargingStation", "object", "ChargingStations", {"stationId": "id"}), # Locations ("Locations", "chargingStations", "array", "ChargingStations", {"locationId": "id"}), # StatusNotifications ("StatusNotifications", "chargingStation", "object", "ChargingStations", {"stationId": "id"}), ("StatusNotifications", "evse", "object", "Evses", {"evseId": "id"}), ("StatusNotifications", "connector", "object", "Connectors", {"connectorId": "id"}), # Authorizations ("Authorizations", "transactions", "array", "Transactions", {"authorizationId": "id"}), ("Authorizations", "chargingStation", "object", "ChargingStations", {"stationId": "id"}), # Tenants ("Tenants", "chargingStations", "array", "ChargingStations", {"tenantId": "id"}), ("Tenants", "evses", "array", "Evses", {"tenantId": "id"}), ("Tenants", "connectors", "array", "Connectors", {"tenantId": "id"}), ("Tenants", "transactions", "array", "Transactions", {"tenantId": "id"}), ("Tenants", "locations", "array", "Locations", {"tenantId": "id"}), ("Tenants", "authorizations", "array", "Authorizations", {"tenantId": "id"}), ("Tenants", "tenantPartners", "array", "TenantPartners", {"tenantId": "id"}), ("Tenants", "statusNotifications", "array", "StatusNotifications", {"tenantId": "id"}), ("Tenants", "latestStatusNotifications", "array", "LatestStatusNotifications", {"tenantId": "id"}), ("Tenants", "variableAttributes", "array", "VariableAttributes", {"tenantId": "id"}), ("Tenants", "chargingProfiles", "array", "ChargingProfiles", {"tenantId": "id"}), ("Tenants", "chargingSchedules", "array", "ChargingSchedules", {"tenantId": "id"}), ("Tenants", "salesTariffs", "array", "SalesTariffs", {"tenantId": "id"}), ("Tenants", "messageInfos", "array", "MessageInfos", {"tenantId": "id"}), ("Tenants", "securityEvents", "array", "SecurityEvents", {"tenantId": "id"}), ("Tenants", "certificates", "array", "Certificates", {"tenantId": "id"}), ("Tenants", "boots", "array", "Boots", {"tenantId": "id"}), ("Tenants", "asyncJobStatuses", "array", "AsyncJobStatuses", {"tenantId": "id"}), ("Tenants", "eventData", "array", "EventData", {"tenantId": "id"}), ("Tenants", "subscriptions", "array", "Subscriptions", {"tenantId": "id"}), ("Tenants", "reservations", "array", "Reservations", {"tenantId": "id"}), ("Tenants", "transactionEvents", "array", "TransactionEvents", {"tenantId": "id"}), ("Tenants", "startTransactions", "array", "StartTransactions", {"tenantId": "id"}), ("Tenants", "stopTransactions", "array", "StopTransactions", {"tenantId": "id"}), ("Tenants", "meterValues", "array", "MeterValues", {"tenantId": "id"}), ("Tenants", "chargingStationNetworkProfiles", "array", "ChargingStationNetworkProfiles", {"tenantId": "id"}), ("Tenants", "serverNetworkProfiles", "array", "ServerNetworkProfiles", {"tenantId": "id"}), ("Tenants", "componentVariables", "array", "ComponentVariables", {"tenantId": "id"}), ("Tenants", "components", "array", "Components", {"tenantId": "id"}), ("Tenants", "variables", "array", "Variables", {"tenantId": "id"}), ("Tenants", "evseTypes", "array", "EvseTypes", {"tenantId": "id"}), ("Tenants", "compositeSchedules", "array", "CompositeSchedules", {"tenantId": "id"}), ("Tenants", "changeConfigurations", "array", "ChangeConfigurations", {"tenantId": "id"}), ("Tenants", "chargingStationSequences", "array", "ChargingStationSequences", {"tenantId": "id"}), ("Tenants", "chargingStationSecurityInfos", "array", "ChargingStationSecurityInfos", {"tenantId": "id"}), ("Tenants", "localListAuthorizations", "array", "LocalListAuthorizations", {"tenantId": "id"}), ("Tenants", "localListVersionAuthorizations", "array", "LocalListVersionAuthorizations", {"tenantId": "id"}), ("Tenants", "localListVersions", "array", "LocalListVersions", {"tenantId": "id"}), ("Tenants", "sendLocalListAuthorizations", "array", "SendLocalListAuthorizations", {"tenantId": "id"}), ("Tenants", "sendLocalLists", "array", "SendLocalLists", {"tenantId": "id"}), ("Tenants", "deleteCertificateAttempts", "array", "DeleteCertificateAttempts", {"tenantId": "id"}), ("Tenants", "installCertificateAttempts", "array", "InstallCertificateAttempts", {"tenantId": "id"}), ("Tenants", "installedCertificates", "array", "InstalledCertificates", {"tenantId": "id"}), ] created = 0 failed = 0 for table, name, rel_type, remote_table, col_map in relations: print(f"Creating {table}.{name}...", end=" ") if create_relation(table, name, rel_type, remote_table, col_map): print("OK") created += 1 else: print("FAIL") failed += 1 print(f"\n=== Résultat: {created} créées, {failed} échouées ===") # Retest critical relations print("\n=== Vérification finale ===\n") all_ok = True for table, relation, fields in critical_relations: ok, msg = test_relation(table, relation, fields) status = "OK" if ok else "FAIL" print(f" {status}: {table}.{relation}") if not ok: all_ok = False if all_ok: print("\n🎉 Toutes les relations fonctionnent !") else: print("\n❌ Certaines relations ne fonctionnent pas encore.") if __name__ == '__main__': main()