diff --git a/Dockerfile b/Dockerfile index 5efffa9..67cd3e8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,20 @@ FROM python:3.10-slim RUN apt-get update && \ - apt-get install -y unixodbc libfbclient2 + apt-get install -y unixodbc libfbclient2 gnupg curl ca-certificates apt-transport-https software-properties-common + + +COPY install_ms_sql_driver.sh /tmp/install_ms_sql_driver.sh +RUN chmod +x /tmp/install_ms_sql_driver.sh && \ + /tmp/install_ms_sql_driver.sh && \ + rm /tmp/install_ms_sql_driver.sh + WORKDIR /usr/src/app COPY requirements.txt ./ RUN pip install --no-cache-dir -r requirements.txt -COPY . . +COPY ./*.py . ENTRYPOINT ["python", "./sync.py"] \ No newline at end of file diff --git a/config.yaml.example b/config.yaml.example index ebe482e..47ceeb4 100644 --- a/config.yaml.example +++ b/config.yaml.example @@ -1,50 +1,51 @@ firebird: db1: - host: "localhost" + host: localhost port: 3050 - database: "/path/to/database1.fdb" - user: "sysdba" - password: "masterkey" + database: /path/to/database1.fdb + user: sysdba + password: masterkey db2: - host: "localhost" + host: localhost port: 3050 - database: "/path/to/database2.fdb" - user: "sysdba" - password: "masterkey" + database: /path/to/database2.fdb + user: sysdba + password: masterkey mssql: db1: - server: "localhost" - database: "mydatabase1" - user: "sa" - password: "mypassword" + server: localhost + database: mydatabase1 + user: sa + password: mypassword + trust_server_certificate: true db2: - server: "localhost" - database: "mydatabase2" - user: "sa" - password: "mypassword" + server: localhost + database: mydatabase2 + user: sa + password: mypassword frappe_auth: - api_key: "your_api_key" - api_secret: "your_api_secret" + api_key: your_api_key + api_secret: your_api_secret tasks: - - endpoint: "http://frappe.example.com/api/resource/Doctype" - query: "SELECT id, name FROM table" + - endpoint: https://frappe.example.com/api/resource/Doctype + query: SELECT id, name FROM table mapping: - "frappe_field_1": "id" - "frappe_field_2": "name" - db_type: "firebird" - db_name: "db1" - direction: "db_to_frappe" - key_fields: ["frappe_field_1"] + frappe_field_1: id + frappe_field_2: name + db_type: firebird + db_name: db1 + direction: db_to_frappe + key_fields: [frappe_field_1] - - endpoint: "http://frappe.example.com/api/resource/OtherDoctype" - table_name: "my_table" + - endpoint: https://frappe.example.com/api/resource/OtherDoctype + table_name: my_table mapping: - "frappe_field_a": "code" - "frappe_field_b": "description" - db_type: "mssql" - db_name: "db2" - direction: "frappe_to_db" - key_fields: ["code"] + frappe_field_a: code + frappe_field_b: description + db_type: mssql + db_name: db2 + direction: frappe_to_db + key_fields: [code] diff --git a/database.py b/database.py index 0fa97eb..e0df465 100644 --- a/database.py +++ b/database.py @@ -21,11 +21,11 @@ def _connect_firebird(self, config: Dict[str, Dict[str, str | Number]]): for db_name, db_config in config.items(): try: conn = fdb.connect( - host=db_config["host"], - port=db_config["port"], - database=db_config["database"], - user=db_config["user"], - password=db_config["password"], + host=db_config.get("host"), + port=db_config.get("port"), + database=db_config.get("database"), + user=db_config.get("user"), + password=db_config.get("password"), charset="UTF8", ) self.firebird_conns[db_name] = conn @@ -39,11 +39,12 @@ def _connect_mssql(self, config: Dict[str, Dict[str, str | Number]]): for db_name, db_config in config.items(): try: mssql_conn_str = ( - f"DRIVER={{ODBC Driver 17 for SQL Server}};" - f"SERVER={db_config['server']};" - f"DATABASE={db_config['database']};" - f"UID={db_config['user']};" - f"PWD={db_config['password']}" + f"DRIVER={{ODBC Driver 18 for SQL Server}};" + f"SERVER={db_config.get('server')};" + f"DATABASE={db_config.get('database')};" + f"UID={db_config.get('user')};" + f"PWD={db_config.get('password')};" + f"TrustServerCertificate={'yes' if db_config.get('trust_server_certificate') else 'no'}" ) conn = pyodbc.connect(mssql_conn_str) self.mssql_conns[db_name] = conn diff --git a/frappe.py b/frappe.py index 3f02ab8..ad37d09 100644 --- a/frappe.py +++ b/frappe.py @@ -4,6 +4,7 @@ import requests import json from datetime import datetime, date +from decimal import Decimal class FrappeAPI: @@ -23,14 +24,14 @@ def _setup_auth(self, auth_config): ) def send_data(self, method, endpoint, data): - if self.dry_run: - logging.info( - f"""DRY_RUN: {method} {endpoint} - {data}""" - ) - return None try: - json_data = json.dumps(data, cls=DateTimeEncoder) + json_data = json.dumps(data, cls=CustomEncoder) + if self.dry_run: + logging.info( + f"""DRY_RUN: {method} {endpoint} + {json_data}""" + ) + return None headers = self.headers.copy() headers["Content-Type"] = "application/json" if method == "POST": @@ -60,8 +61,10 @@ def get_data(self, endpoint, params=None): return None -class DateTimeEncoder(json.JSONEncoder): +class CustomEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, (datetime, date)): return obj.isoformat() - return super(DateTimeEncoder, self).default(obj) + elif isinstance(obj, Decimal): + return float(obj) # or str(obj) if you prefer + return super(CustomEncoder, self).default(obj) diff --git a/install_ms_sql_driver.sh b/install_ms_sql_driver.sh new file mode 100644 index 0000000..f4f0aae --- /dev/null +++ b/install_ms_sql_driver.sh @@ -0,0 +1,17 @@ +set -e + +apt-get update +apt-get install -y curl + +# Debian 12 +curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg + +#Debian 12 +curl https://packages.microsoft.com/config/debian/12/prod.list | tee /etc/apt/sources.list.d/mssql-release.list + +apt-get update +ACCEPT_EULA=Y apt-get install -y msodbcsql18 +# optional: for bcp and sqlcmd +# ACCEPT_EULA=Y apt-get install -y mssql-tools18 +# echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' >> ~/.bashrc +# source ~/.bashrc \ No newline at end of file