detall post - Resum per importar fitxers CSV de comptabilitat a la base de dades autonomo_contabilidad amb Python

Creado en: 2025-07-19 16:12:17

Actualizado en: 2025-07-19 16:15:43

eines

bbdd essential

Aquest script en Python importa dades d'un fitxer CSV (com `compartit 3tr-2025 - VENDA.csv`) a la base de dades MySQL `autonomo_contabilidad`, utilitzant l'esquema de taules `wp_contabilidad_clientes`, `wp_contabilidad_empleados`, `wp_contabilidad_productos`, `wp_contabilidad_ventas` i `wp_contabilidad_detalles_venta`.

Resum per importar fitxers CSV de comptabilitat a la base de dades `autonomo_contabilidad` amb Python

Aquest script en Python importa dades d'un fitxer CSV (com `compartit 3tr-2025 - VENDA.csv`) a la base de dades MySQL `autonomo_contabilidad`, utilitzant l'esquema de taules `wp_contabilidad_clientes`, `wp_contabilidad_empleados`, `wp_contabilidad_productos`, `wp_contabilidad_ventas` i `wp_contabilidad_detalles_venta`.

**Passos clau**:
1. **Configuració**:
   - Instal·lar llibreries: `pip install pandas mysql-connector-python`.
   - Configurar credencials a `db_config` (usuari, contrasenya, host, port).
   - Especificar el camí del CSV (ex.: `C:\\Users\\joanp\\Documents\\compartit 3tr-2025 - VENDA.csv`).

2. **Processament del CSV**:
   - Llegir el CSV amb `pandas`.
   - Netejar columnes: convertir `import total` a float (eliminant ' €' i canviant ',' per '.'), i `data` a format `YYYY-MM-DD`.
   - Assumir IVA del 21% per calcular `subtotal` i `iva_monto`.

3. **Inserció a la base de dades**:
   - **Clients**: Inserir clients únics (`client`) a `wp_contabilidad_clientes`.
   - **Empleats**: Inserir empleats únics (`empleat`) a `wp_contabilidad_empleados` amb NIF provisional (UUID).
   - **Productes**: Inserir productes únics (`producte`) a `wp_contabilidad_productos` amb `protocol=''` (ajustar segons esquema).
   - **Vendes**: Inserir vendes a `wp_contabilidad_ventas` amb `fecha`, `cliente_id`, `subtotal`, `iva_porcentaje`, `iva_monto`, `total`, i `metode pagament` a `notas`.
   - **Detalls de vendes**: Inserir a `wp_contabilidad_detalles_venta` amb `venta_id`, `producto_id`, `cantidad=1`, `precio_unitario`, i `subtotal`.

4. **Gestió d'errors**:
   - Utilitzar `try-except` per capturar errors de connexió, CSV o SQL.
   - Afegir `cursor.fetchall()` i `buffered=True` per evitar errors com `Unread result found`.
   - Comprovar l'existència de taules abans d'inserir.

import pandas as pd
import mysql.connector
from datetime import datetime
import uuid
import logging

# Configurar logging per rastrejar errors i progrés
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# Configuració de la connexió a la base de dades
db_config = {
    'host': 'localhost',  # Canvia si el teu host és diferent
    'user': 'joan',  # Substitueix amb el teu usuari de MySQL
    'password': 'queMm88/g62123',  # Substitueix amb la teva contrasenya de MySQL
    'database': 'autonomo_contabilidad',
    'port': 3306  # Canvia si utilitzes un port diferent
}

# Llegir el fitxer CSV
csv_file = 'C:\\Users\\joanp\\Documents\\compartit 3tr-2025 - VENDA.csv'
try:
    df = pd.read_csv(csv_file)
    logging.info(f"Fitxer CSV '{csv_file}' llegit correctament.")
except Exception as e:
    logging.error(f"Error en llegir el fitxer CSV: {e}")
    exit(1)

# Netejar i preprocessar les dades
def clean_currency(value):
    try:
        if isinstance(value, str):
            return float(value.replace(' €', '').replace(',', '.'))
        return float(value)
    except Exception as e:
        logging.error(f"Error en netejar valor monetari '{value}': {e}")
        return 0.0

def clean_date(date_str):
    try:
        return datetime.strptime(date_str, '%d/%m/%Y').strftime('%Y-%m-%d')
    except Exception as e:
        logging.error(f"Error en netejar data '{date_str}': {e}")
        return None

df['import total'] = df['import total'].apply(clean_currency)
df['data'] = df['data'].apply(clean_date)

# Eliminar files amb dates invàlides
df = df.dropna(subset=['data'])
logging.info(f"Total de files després de netejar dates: {len(df)}")

# Connectar a la base de dades
try:
    conn = mysql.connector.connect(**db_config)
    cursor = conn.cursor(buffered=True)  # Afegim buffered=True per gestionar resultats
    logging.info("Connexió a la base de dades establerta correctament.")
except mysql.connector.Error as e:
    logging.error(f"Error en connectar a la base de dades: {e}")
    exit(1)

# Comprovar si les taules existeixen
try:
    cursor.execute("SHOW TABLES LIKE 'wp_contabilidad_productos'")
    if not cursor.fetchone():
        logging.error("La taula wp_contabilidad_productos no existeix. Assegura't que l'esquema està creat.")
        cursor.close()
        conn.close()
        exit(1)
    cursor.fetchall()  # Consumir resultats pendents
except mysql.connector.Error as e:
    logging.error(f"Error en comprovar taules: {e}")
    cursor.close()
    conn.close()
    exit(1)

# Inserir clients únics
clients = df['client'].unique()
client_ids = {}
try:
    for client in clients:
        cursor.execute("SELECT id FROM wp_contabilidad_clientes WHERE nombre = %s", (client,))
        result = cursor.fetchone()
        cursor.fetchall()  # Consumir qualsevol resultat pendent
        if not result:
            cursor.execute(
                "INSERT INTO wp_contabilidad_clientes (nombre, fecha_creacion) VALUES (%s, NOW())",
                (client,)
            )
            client_ids[client] = cursor.lastrowid
            logging.info(f"Client '{client}' inserit amb ID {client_ids[client]}.")
        else:
            client_ids[client] = result[0]
except mysql.connector.Error as e:
    logging.error(f"Error en inserir clients: {e}")
    conn.rollback()
    cursor.close()
    conn.close()
    exit(1)

# Inserir empleats únics
employees = df['empleat'].unique()
employee_ids = {}
try:
    for employee in employees:
        cursor.execute("SELECT id FROM wp_contabilidad_empleados WHERE nombre = %s", (employee,))
        result = cursor.fetchone()
        cursor.fetchall()  # Consumir qualsevol resultat pendent
        if not result:
            cursor.execute(
                "INSERT INTO wp_contabilidad_empleados (nombre, nif, fecha_creacion) VALUES (%s, %s, NOW())",
                (employee, str(uuid.uuid4())[:20])  # Generar un NIF provisional
            )
            employee_ids[employee] = cursor.lastrowid
            logging.info(f"Empleat '{employee}' inserit amb ID {employee_ids[employee]}.")
        else:
            employee_ids[employee] = result[0]
except mysql.connector.Error as e:
    logging.error(f"Error en inserir empleats: {e}")
    conn.rollback()
    cursor.close()
    conn.close()
    exit(1)

# Inserir productes únics
products = df['producte'].unique()
product_ids = {}
default_category_id = 7  # ID de categoria per defecte segons l'esquema
try:
    for product in products:
        cursor.execute("SELECT id FROM wp_contabilidad_productos WHERE nombre = %s", (product,))
        result = cursor.fetchone()
        cursor.fetchall()  # Consumir qualsevol resultat pendent
        if not result:
            cursor.execute(
                """
                INSERT INTO wp_contabilidad_productos 
                (nombre, id_categoria_producto, precio, stock, protocol, created_at, updated_at) 
                VALUES (%s, %s, %s, %s, %s, NOW(), NOW())
                """,
                (product, default_category_id, 0.00, 0, '')  # Afegim protocol com cadena buida
            )
            product_ids[product] = cursor.lastrowid
            logging.info(f"Producte '{product}' inserit amb ID {product_ids[product]}.")
        else:
            product_ids[product] = result[0]
except mysql.connector.Error as e:
    logging.error(f"Error en inserir productes: {e}")
    conn.rollback()
    cursor.close()
    conn.close()
    exit(1)

# Inserir vendes i detalls de vendes
try:
    for index, row in df.iterrows():
        # Calcular subtotal i IVA (assumim IVA del 21%)
        total = row['import total']
        iva_porcentaje = 21.00
        subtotal = round(total / 1.21, 2)
        iva_monto = round(total - subtotal, 2)

        # Inserir a wp_contabilidad_ventas
        cursor.execute(
            """
            INSERT INTO wp_contabilidad_ventas 
            (fecha, cliente_id, subtotal, iva_porcentaje, iva_monto, total, notas, fecha_creacion, empleado_id)
            VALUES (%s, %s, %s, %s, %s, %s, %s, NOW(), %s)
            """,
            (
                row['data'],
                client_ids[row['client']],
                subtotal,
                iva_porcentaje,
                iva_monto,
                total,
                f"Metode de pagament: {row['metode pagament']}",
                employee_ids[row['empleat']]
            )
        )
        venta_id = cursor.lastrowid
        logging.info(f"Venda inserida amb ID {venta_id} per al client {row['client']}.")

        # Inserir a wp_contabilidad_detalles_venta
        cursor.execute(
            """
            INSERT INTO wp_contabilidad_detalles_venta 
            (venta_id, producto_id, cantidad, precio_unitario, subtotal)
            VALUES (%s, %s, %s, %s, %s)
            """,
            (
                venta_id,
                product_ids[row['producte']],
                1,  # Assumim quantitat 1
                subtotal,
                subtotal
            )
        )
        logging.info(f"Detall de venda inserit per al producte {row['producte']}.")
except mysql.connector.Error as e:
    logging.error(f"Error en inserir vendes o detalls: {e}")
    conn.rollback()
    cursor.close()
    conn.close()
    exit(1)

# Confirmar canvis i tancar connexió
try:
    conn.commit()
    logging.info("Totes les dades s'han importat correctament a la base de dades.")
except mysql.connector.Error as e:
    logging.error(f"Error en confirmar canvis: {e}")
    conn.rollback()
finally:
    cursor.close()
    conn.close()

print("Importació completada amb èxit.")


**Notes**:
- Assegura't que l'esquema (`ESTRUCTURA.sql`) està aplicat.
- Ajusta `protocol` a `wp_contabilidad_productos` segons el tipus de dades requerit.
- Per a futurs fitxers, actualitza `csv_file` i verifica l'IVA o quantitats si varien.

Aquest resum és ideal per enganxar a un formulari amb camp Trix per documentar el procés. Si necessites més detalls o ajustos, pots ampliar el codi o consultar l'esquema complet!

Resum per importar fitxers CSV de comptabilitat a la base de dades autonomo_contabilidad amb Python