From dd5c88e3bb58483a90e280c6dfd947035e5db2ae Mon Sep 17 00:00:00 2001 From: alzyras Date: Fri, 30 Jan 2026 17:03:32 +0200 Subject: [PATCH] Client script working --- uv_app/core/mssql.py | 7 ++- uv_app/core/pgsql.py | 7 ++- uv_app/user/insert_clients.py | 81 +++++++++++++++++++++------------ uv_app/user/routeriai_query.sql | 2 +- 4 files changed, 64 insertions(+), 33 deletions(-) diff --git a/uv_app/core/mssql.py b/uv_app/core/mssql.py index 4d9521f..e109838 100644 --- a/uv_app/core/mssql.py +++ b/uv_app/core/mssql.py @@ -2,10 +2,13 @@ import os from typing import Optional import pyodbc -from dotenv import find_dotenv, load_dotenv +from pathlib import Path +from dotenv import load_dotenv + +DOTENV_PATH = Path(__file__).resolve().parents[2] / ".env" # Force reload environment variables from repo .env, ignoring system vars. -load_dotenv(find_dotenv(), override=True) +load_dotenv(DOTENV_PATH, override=True) def _get_required_env(name: str) -> str: diff --git a/uv_app/core/pgsql.py b/uv_app/core/pgsql.py index 251316f..1134ac0 100644 --- a/uv_app/core/pgsql.py +++ b/uv_app/core/pgsql.py @@ -2,10 +2,13 @@ import os from typing import Optional import psycopg2 -from dotenv import find_dotenv, load_dotenv +from pathlib import Path +from dotenv import load_dotenv + +DOTENV_PATH = Path(__file__).resolve().parents[2] / ".env" # Force reload environment variables from repo .env, ignoring system vars. -load_dotenv(find_dotenv(), override=True) +load_dotenv(DOTENV_PATH, override=True) DB_HOST = os.getenv("DB_HOST") DB_PORT = os.getenv("DB_PORT") diff --git a/uv_app/user/insert_clients.py b/uv_app/user/insert_clients.py index 2978e7b..2bd4f63 100644 --- a/uv_app/user/insert_clients.py +++ b/uv_app/user/insert_clients.py @@ -8,7 +8,7 @@ from typing import Dict, Iterable, Optional, Tuple import psycopg2 import psycopg2.extras import requests -from dotenv import find_dotenv, load_dotenv +from dotenv import load_dotenv from uv_app.core.mssql import connect_to_mssql from uv_app.core.pgsql import connect_to_pgsql @@ -17,11 +17,13 @@ BASE_URL = "https://api.manorivile.lt/client/v2" TIMEOUT = 30 QUERY_PATH = Path(__file__).with_name("routeriai_query.sql") +DOTENV_PATH = Path(__file__).resolve().parents[2] / ".env" # Force reload environment variables from repo .env, ignoring system vars. -load_dotenv(find_dotenv(), override=True) +load_dotenv(DOTENV_PATH, override=True) -def _post(api_key: str, payload: dict) -> dict: + +def _post(api_key: str, payload: dict) -> tuple[dict, int]: headers = { "ApiKey": api_key, "Content-Type": "application/json", @@ -35,14 +37,15 @@ def _post(api_key: str, payload: dict) -> dict: timeout=TIMEOUT, ) - if response.status_code != 200: - raise RuntimeError(f"Rivile HTTP {response.status_code}: {response.text}") + status_code = response.status_code + if status_code != 200: + raise RuntimeError(f"Rivile HTTP {status_code}: {response.text}") data = response.json() if "errorMessage" in data: raise RuntimeError(f"Rivile API error: {data}") - return data + return data, status_code def _get_api_key() -> str: @@ -62,11 +65,10 @@ def _fetch_mssql_client( ) -> Optional[Dict[str, object]]: query = """ SELECT - N08_KODAS, N08_KODAS_KS, N08_PAV, - N08_ADDR, - N08_E_EMAIL, + N08_ADR, + N08_E_MAIL, N08_ADD_DATE, N08_MOB_TEL, N08_IM_KODAS, @@ -95,8 +97,10 @@ def _fetch_mssql_client( return dict(zip(columns, row)) -def _normalize_person_type(value: Optional[str]) -> str: - cleaned = (value or "").strip() +def _normalize_person_type(value: Optional[object]) -> str: + if value is None: + return "1" + cleaned = str(value).strip() if cleaned == "1": return "1" if cleaned == "0": @@ -109,21 +113,32 @@ def _build_n08_payload(row: Dict[str, object]) -> Dict[str, object]: phone = (row.get("phone") or "").strip() contact_phone = mobile or phone + company_code = row.get("company_code") + if company_code is None or str(company_code).strip() == "": + company_code = "ND" + else: + company_code = str(company_code).strip() + + vat_code = row.get("vat_code") + if vat_code is None or str(vat_code).strip() == "": + vat_code = "ND" + else: + vat_code = str(vat_code).strip() + creation_date = row.get("creation_date") if isinstance(creation_date, (date, datetime)): creation_date = creation_date.isoformat() return { - "N08_KODAS": row.get("client_code"), "N08_KODAS_KS": row.get("client_code"), - "N08_PAV": row.get("name") or "", - "N08_ADDR": row.get("address") or "", - "N08_E_EMAIL": row.get("email") or "", - "N08_ADD_DATE": creation_date or "", + "N08_PAV": row.get("name"), + "N08_ADR": row.get("address"), + "N08_E_MAIL": row.get("email"), + "N08_ADD_DATE": creation_date, "N08_MOB_TEL": contact_phone, - "N08_IM_KODAS": row.get("company_code") or "", - "N08_PVM_KODAS": row.get("vat_code") or "", - "N08_ADDUSR": row.get("ucreated") or "", + "N08_IM_KODAS": company_code, + "N08_PVM_KODAS": vat_code, + "N08_ADDUSR": row.get("ucreated"), "N08_TIPAS": _normalize_person_type(row.get("person_type")), "N08_KODAS_DS": "PT001", "N08_BUSENA": "1", @@ -134,7 +149,7 @@ def _build_n08_payload(row: Dict[str, object]) -> Dict[str, object]: "N08_KODAS_XS_T": "NEPVM", "N08_KODAS_XS_P": "NEPVM", "N08_RUSIS": "1", - "N08_R_DATE": date.today().isoformat(), + "N08_R_DATE": datetime.now().isoformat(timespec="seconds"), } @@ -164,10 +179,14 @@ def _diff_fields( return changes + + def _upsert_client( api_key: str, mssql_conn: "pyodbc.Connection", row: Dict[str, object], + index: int, + total: int, ) -> None: client_code = str(row.get("client_code") or "").strip() if not client_code: @@ -176,13 +195,17 @@ def _upsert_client( n08 = _build_n08_payload(row) user = _get_user_from_key(api_key) existing = _fetch_mssql_client(mssql_conn, client_code) + if existing: + existing_web = _normalize_value(existing.get("N08_WEB_POZT")) + if existing_web: + n08["N08_WEB_POZT"] = existing_web changes = _diff_fields(existing, n08) if existing: - if not changes: - print(f"No changes for client: {client_code}") + if not changes or set(changes.keys()) == {"N08_R_DATE"}: + print(f"No changes for client: {client_code} ({index}/{total})") return - print(f"Updating client: {client_code}") + print(f"Updating client: {client_code} ({index}/{total})") for field, (old, new) in changes.items(): print(f" {field}: '{old}' -> '{new}'") payload = { @@ -196,7 +219,7 @@ def _upsert_client( "data": {"N08": n08}, } else: - print(f"Creating client: {client_code}") + print(f"Creating client: {client_code} ({index}/{total})") for field, (_, new) in changes.items(): print(f" {field}: '' -> '{new}'") payload = { @@ -205,7 +228,8 @@ def _upsert_client( "data": {"N08": n08}, } - _post(api_key, payload) + _, status_code = _post(api_key, payload) + print(f" Rivile response status: {status_code}") def _read_query() -> str: @@ -226,13 +250,14 @@ def _fetch_clients() -> Iterable[Dict[str, object]]: def main() -> None: api_key = _get_api_key() - rows = _fetch_clients() + rows = list(_fetch_clients()) mssql_conn = connect_to_mssql() if mssql_conn is None: raise RuntimeError("Failed to connect to MSSQL.") try: - for row in rows: - _upsert_client(api_key, mssql_conn, row) + total = len(rows) + for index, row in enumerate(rows, start=1): + _upsert_client(api_key, mssql_conn, row, index, total) finally: mssql_conn.close() diff --git a/uv_app/user/routeriai_query.sql b/uv_app/user/routeriai_query.sql index 83afa65..779b8fc 100644 --- a/uv_app/user/routeriai_query.sql +++ b/uv_app/user/routeriai_query.sql @@ -2,7 +2,7 @@ SELECT k.kodas AS client_code, trim(concat_ws(' ', k.vardas, k.pavarde)) AS name, trim(concat_ws(', ', - concat_ws(' ', g.pav, k.namas, k.butas), + concat_ws(' ', g.pav, k.namas, NULLIF(NULLIF(k.butas::text, '0'), '')), m.pav, r.pav )) AS address,