From 6b85d4500cc559249d6ed079eeb1381eedcc8a72 Mon Sep 17 00:00:00 2001 From: SONIABHISHEK121 Date: Tue, 28 May 2024 13:35:09 +0530 Subject: [PATCH 1/6] csv-testing : leer function Signed-off-by: SONIABHISHEK121 --- formatos/formato_csv.py | 26 ++--- tests/test_formato_csv.py | 193 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 201 insertions(+), 18 deletions(-) create mode 100644 tests/test_formato_csv.py diff --git a/formatos/formato_csv.py b/formatos/formato_csv.py index b6a1ef809..8bba4a6f8 100644 --- a/formatos/formato_csv.py +++ b/formatos/formato_csv.py @@ -31,29 +31,19 @@ def leer(fn="entrada.csv", delimiter=";"): ext = os.path.splitext(fn)[1].lower() items = [] if ext == ".csv": - csvfile = open(fn, "rb") - # deducir dialecto y delimitador - try: - dialect = csv.Sniffer().sniff(csvfile.read(256), delimiters=[";", ","]) - except csv.Error: - dialect = csv.excel - dialect.delimiter = delimiter - csvfile.seek(0) - csv_reader = csv.reader(csvfile, dialect) - for row in csv_reader: - r = [] - for c in row: - if isinstance(c, basestring): - c = c.strip() - r.append(c) - items.append(r) + with open(fn, "r") as csvfile: + csv_reader = csv.reader(csvfile, delimiter=delimiter) + next(csv_reader) # Skip the header row + for row in csv_reader: + items.append(row) elif ext == ".xlsx": # extraigo los datos de la planilla Excel from openpyxl import load_workbook + wb = load_workbook(filename=fn) - ws1 = wb.get_active_sheet() - for row in ws1.rows: + ws1 = wb.active + for row in ws1.iter_rows(min_row=2): # Start from the second row (skip header) fila = [] for cell in row: fila.append(cell.value) diff --git a/tests/test_formato_csv.py b/tests/test_formato_csv.py new file mode 100644 index 000000000..c91d20164 --- /dev/null +++ b/tests/test_formato_csv.py @@ -0,0 +1,193 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 3, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. + +import os +import sys +import unittest +import importlib.util +import csv +import pytest +import tempfile +from io import StringIO +from openpyxl import Workbook, load_workbook +from unittest.mock import MagicMock, mock_open, patch + + +# Get the absolute path to the formato_csv.py file +formato_csv_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'formatos', 'formato_csv.py')) + + +# Load the formato_csv module +spec = importlib.util.spec_from_file_location("formato_csv", formato_csv_path) +formato_csv = importlib.util.module_from_spec(spec) +spec.loader.exec_module(formato_csv) + + +from pyafipws.formatos.formato_csv import leer + + +@pytest.mark.dontusefix +class TestLeerFunction(unittest.TestCase): + @classmethod + def setUpClass(cls): + # Create sample CSV data + cls.sample_csv_data = "Column1,Column2,Column3\nValue1,Value2,Value3\r\nValue4,Value5,Value6" + + + # Create sample CSV data with pipe delimiter + cls.sample_pipe_csv_data = "Column1|Column2|Column3\r\nValue1|Value2|Value3\r\nValue4|Value5|Value6" + + + # Create empty CSV data + cls.empty_csv_data = "" + + + def test_leer_csv_file(self): + """ + Test that the leer function can read a valid CSV file correctly. + """ + expected_data = [ + ["Column1", "Column2", "Column3"], + ["Value1", "Value2", "Value3"], + ["Value4", "Value5", "Value6"], + ] + with patch('builtins.open', return_value=StringIO(self.sample_csv_data)): + result = leer('data/sample.csv') + self.assertEqual(result, expected_data) + + + def test_leer_xlsx_file(self): + """ + Test that the leer function can read a valid Excel file correctly. + """ + expected_data = [ + ["Column1", "Column2", "Column3"], + ["Value1", "Value2", "Value3"], + ["Value4", "Value5", "Value6"], + ] + + + # Create a temporary Excel file for testing + with tempfile.NamedTemporaryFile(suffix='.xlsx', delete=False) as temp_file: + workbook = Workbook() + worksheet = workbook.active + worksheet['A1'] = 'Column1' + worksheet['B1'] = 'Column2' + worksheet['C1'] = 'Column3' + worksheet['A2'] = 'Value1' + worksheet['B2'] = 'Value2' + worksheet['C2'] = 'Value3' + worksheet['A3'] = 'Value4' + worksheet['B3'] = 'Value5' + worksheet['C3'] = 'Value6' + workbook.save(temp_file.name) + + + result = leer(temp_file.name) + self.assertEqual(result, expected_data) + + + # Clean up the temporary file + os.unlink(temp_file.name) + + + def test_leer_missing_file(self): + """ + Test that the leer function raises an appropriate exception when the file is missing. + """ + filename = os.path.join('data', 'missing.csv') + with self.assertRaises(FileNotFoundError): + leer(filename) + + + def test_leer_empty_file(self): + """ + Test that the leer function handles an empty file correctly. + """ + expected_data = [] + with patch('builtins.open', return_value=StringIO(self.empty_csv_data)): + result = leer('data/empty.csv') + self.assertEqual(result, expected_data) + + + def test_leer_custom_delimiter(self): + """ + Test that the leer function can read a CSV file with a custom delimiter. + """ + expected_data = [ + ["Column1", "Column2", "Column3"], + ["Value1", "Value2", "Value3"], + ["Value4", "Value5", "Value6"], + ] + with patch('builtins.open', return_value=StringIO(self.sample_pipe_csv_data)): + result = leer('data/sample_pipe.csv', delimiter="|") + self.assertEqual(result, expected_data) + + + def test_leer_csv_missing_columns(self): + """ + Test that the leer function handles a CSV file with missing columns correctly. + """ + sample_csv_data = "Column1,Column2\nValue1,Value2\nValue3\nValue4,Value5,Value6" + expected_data = [ + ["Value1", "Value2"], + ["Value3"], + ["Value4", "Value5", "Value6"], + ] + with patch('builtins.open', return_value=StringIO(sample_csv_data)): + result = formato_csv.leer('data/sample_missing_columns.csv', delimiter=',') + self.assertEqual(result, expected_data) + + + def test_leer_csv_extra_columns(self): + """ + Test that the leer function handles a CSV file with extra columns correctly. + """ + sample_csv_data = "Column1,Column2,Column3,Column4,column5,column6\nValue1,Value2,Value3,Value4\nValue5,Value6,Value7,Value8" + expected_data = [ + ["Value1", "Value2", "Value3", "Value4"], + ["Value5", "Value6", "Value7", "Value8"], + ] + with patch('builtins.open', return_value=StringIO(sample_csv_data)): + result = formato_csv.leer('data/sample_extra_columns.csv', delimiter=',') + self.assertEqual(result, expected_data) + + def test_leer_csv_different_column_order(self): + """ + Test that the leer function handles a CSV file with different column order correctly. + """ + sample_csv_data = "Column2,Column1,Column3\nValue2,Value1,Value3\nValue5,Value4,Value6" + expected_data = [ + ["Value2", "Value1", "Value3"], + ["Value5", "Value4", "Value6"], + ] + with patch('builtins.open', return_value=StringIO(sample_csv_data)): + result = formato_csv.leer('data/sample_different_order.csv', delimiter=',') + self.assertEqual(result, expected_data) + + + def test_leer_csv_special_characters(self): + """ + Test that the leer function handles a CSV file with special characters correctly. + """ + sample_csv_data = "Column1,Column2,Column3\nValue1,Válue2,Value3\nValue4,Value5,Válue6" + expected_data = [ + ["Value1", "Válue2", "Value3"], + ["Value4", "Value5", "Válue6"], + ] + with patch('builtins.open', return_value=StringIO(sample_csv_data)): + result = formato_csv.leer('data/sample_special_chars.csv', delimiter=',') + self.assertEqual(result, expected_data) + + +if __name__ == "__main__": + unittest.main() From 523eb0f87a930c583bbc3bfc89d288f0abdfc6f6 Mon Sep 17 00:00:00 2001 From: SONIABHISHEK121 Date: Wed, 29 May 2024 14:17:42 +0530 Subject: [PATCH 2/6] formato_csv : leer tests updated Signed-off-by: SONIABHISHEK121 --- formatos/formato_csv.py | 43 ++++++++++++++++++++------------- tests/test_formato_csv.py | 50 +++++++++++++++++---------------------- 2 files changed, 48 insertions(+), 45 deletions(-) diff --git a/formatos/formato_csv.py b/formatos/formato_csv.py index 8bba4a6f8..4380316c3 100644 --- a/formatos/formato_csv.py +++ b/formatos/formato_csv.py @@ -24,33 +24,42 @@ import csv from decimal import Decimal import os - +from openpyxl import load_workbook def leer(fn="entrada.csv", delimiter=";"): - "Analiza un archivo CSV y devuelve un diccionario (aplanado)" + "Analiza un archivo CSV y devuelve una lista de listas con los datos" ext = os.path.splitext(fn)[1].lower() items = [] + if ext == ".csv": - with open(fn, "r") as csvfile: - csv_reader = csv.reader(csvfile, delimiter=delimiter) - next(csv_reader) # Skip the header row + with open(fn, "r", encoding="utf-8") as csvfile: + try: + dialect = csv.Sniffer().sniff(csvfile.read(256), delimiters=[delimiter, ","]) + except csv.Error: + dialect = csv.excel + dialect.delimiter = delimiter + csvfile.seek(0) + csv_reader = csv.reader(csvfile, dialect) + header_skipped = False for row in csv_reader: - items.append(row) + if not header_skipped: + header_skipped = True + continue + items.append([c.strip() if isinstance(c, str) else c for c in row]) + elif ext == ".xlsx": - # extraigo los datos de la planilla Excel - from openpyxl import load_workbook - - wb = load_workbook(filename=fn) ws1 = wb.active - for row in ws1.iter_rows(min_row=2): # Start from the second row (skip header) - fila = [] - for cell in row: - fila.append(cell.value) - items.append(fila) + header_skipped = False + for row in ws1.iter_rows(values_only=True): + if not header_skipped: + header_skipped = True + continue + items.append([cell for cell in row]) + return items # TODO: return desaplanar(items) - + def aplanar(regs): "Convierte una estructura python en planilla CSV (PyRece)" @@ -365,4 +374,4 @@ def escribir(filas, fn="salida.csv", delimiter=";"): for fila1, fila2 in zip(filas1, filas2): for celda1, celda2 in zip(fila1, fila2): if celda1 != celda2: - print(celda1, celda2) + print(celda1, celda2) \ No newline at end of file diff --git a/tests/test_formato_csv.py b/tests/test_formato_csv.py index c91d20164..d7cb9851e 100644 --- a/tests/test_formato_csv.py +++ b/tests/test_formato_csv.py @@ -10,42 +10,41 @@ # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. +"""Test para formato_csv""" + +__author__ = "Mariano Reingart " +__copyright__ = "Copyright (C) 2010-2019 Mariano Reingart" +__license__ = "GPL 3.0" + import os -import sys import unittest import importlib.util import csv import pytest import tempfile from io import StringIO -from openpyxl import Workbook, load_workbook -from unittest.mock import MagicMock, mock_open, patch - +from openpyxl import Workbook +from unittest.mock import patch # Get the absolute path to the formato_csv.py file formato_csv_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'formatos', 'formato_csv.py')) - # Load the formato_csv module spec = importlib.util.spec_from_file_location("formato_csv", formato_csv_path) formato_csv = importlib.util.module_from_spec(spec) spec.loader.exec_module(formato_csv) - from pyafipws.formatos.formato_csv import leer - @pytest.mark.dontusefix class TestLeerFunction(unittest.TestCase): @classmethod def setUpClass(cls): # Create sample CSV data - cls.sample_csv_data = "Column1,Column2,Column3\nValue1,Value2,Value3\r\nValue4,Value5,Value6" - + cls.sample_csv_data = "Column1,Column2,Column3\nValue1,Value2,Value3\nValue4,Value5,Value6" # Create sample CSV data with pipe delimiter - cls.sample_pipe_csv_data = "Column1|Column2|Column3\r\nValue1|Value2|Value3\r\nValue4|Value5|Value6" - + cls.sample_pipe_csv_data = "Column1|Column2|Column3\nValue1|Value2|Value3\nValue4|Value5|Value6" # Create empty CSV data cls.empty_csv_data = "" @@ -56,12 +55,11 @@ def test_leer_csv_file(self): Test that the leer function can read a valid CSV file correctly. """ expected_data = [ - ["Column1", "Column2", "Column3"], ["Value1", "Value2", "Value3"], ["Value4", "Value5", "Value6"], ] with patch('builtins.open', return_value=StringIO(self.sample_csv_data)): - result = leer('data/sample.csv') + result = formato_csv.leer('data/sample.csv') self.assertEqual(result, expected_data) @@ -70,7 +68,6 @@ def test_leer_xlsx_file(self): Test that the leer function can read a valid Excel file correctly. """ expected_data = [ - ["Column1", "Column2", "Column3"], ["Value1", "Value2", "Value3"], ["Value4", "Value5", "Value6"], ] @@ -91,13 +88,11 @@ def test_leer_xlsx_file(self): worksheet['C3'] = 'Value6' workbook.save(temp_file.name) + result = formato_csv.leer(temp_file.name) + self.assertEqual(result, expected_data) - result = leer(temp_file.name) - self.assertEqual(result, expected_data) - - - # Clean up the temporary file - os.unlink(temp_file.name) + # Clean up the temporary file + os.unlink(temp_file.name) def test_leer_missing_file(self): @@ -106,8 +101,7 @@ def test_leer_missing_file(self): """ filename = os.path.join('data', 'missing.csv') with self.assertRaises(FileNotFoundError): - leer(filename) - + formato_csv.leer(filename) def test_leer_empty_file(self): """ @@ -115,7 +109,7 @@ def test_leer_empty_file(self): """ expected_data = [] with patch('builtins.open', return_value=StringIO(self.empty_csv_data)): - result = leer('data/empty.csv') + result = formato_csv.leer('data/empty.csv') self.assertEqual(result, expected_data) @@ -124,12 +118,11 @@ def test_leer_custom_delimiter(self): Test that the leer function can read a CSV file with a custom delimiter. """ expected_data = [ - ["Column1", "Column2", "Column3"], ["Value1", "Value2", "Value3"], ["Value4", "Value5", "Value6"], ] with patch('builtins.open', return_value=StringIO(self.sample_pipe_csv_data)): - result = leer('data/sample_pipe.csv', delimiter="|") + result = formato_csv.leer('data/sample_pipe.csv', delimiter="|") self.assertEqual(result, expected_data) @@ -147,12 +140,12 @@ def test_leer_csv_missing_columns(self): result = formato_csv.leer('data/sample_missing_columns.csv', delimiter=',') self.assertEqual(result, expected_data) - + def test_leer_csv_extra_columns(self): """ Test that the leer function handles a CSV file with extra columns correctly. """ - sample_csv_data = "Column1,Column2,Column3,Column4,column5,column6\nValue1,Value2,Value3,Value4\nValue5,Value6,Value7,Value8" + sample_csv_data = "Column1,Column2,Column3,Column4\nValue1,Value2,Value3,Value4\nValue5,Value6,Value7,Value8" expected_data = [ ["Value1", "Value2", "Value3", "Value4"], ["Value5", "Value6", "Value7", "Value8"], @@ -161,6 +154,7 @@ def test_leer_csv_extra_columns(self): result = formato_csv.leer('data/sample_extra_columns.csv', delimiter=',') self.assertEqual(result, expected_data) + def test_leer_csv_different_column_order(self): """ Test that the leer function handles a CSV file with different column order correctly. @@ -174,7 +168,7 @@ def test_leer_csv_different_column_order(self): result = formato_csv.leer('data/sample_different_order.csv', delimiter=',') self.assertEqual(result, expected_data) - + def test_leer_csv_special_characters(self): """ Test that the leer function handles a CSV file with special characters correctly. From f7078553b95982dc634edc24528ee89aa52f1525 Mon Sep 17 00:00:00 2001 From: SONIABHISHEK121 Date: Mon, 10 Jun 2024 12:11:36 +0530 Subject: [PATCH 3/6] test_formato_csv : draft Signed-off-by: SONIABHISHEK121 --- .gitignore | 1 + formatos/formato_csv.py | 85 +- tests/conftest.py | 1 + tests/test_formato_csv.py | 1949 ++++++++++++++++++++++++++++++++++++- 4 files changed, 1994 insertions(+), 42 deletions(-) diff --git a/.gitignore b/.gitignore index d2d6f360b..4dc463ca1 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,4 @@ nosetests.xml .mr.developer.cfg .project .pydevproject +env \ No newline at end of file diff --git a/formatos/formato_csv.py b/formatos/formato_csv.py index 4380316c3..71bd75802 100644 --- a/formatos/formato_csv.py +++ b/formatos/formato_csv.py @@ -86,64 +86,63 @@ def aplanar(regs): if reg.get("cbte_nro"): fila["cbt_numero"] = reg["cbte_nro"] - for i, det in enumerate(reg["detalles"]): - li = i + 1 + for i, det in enumerate(reg.get("detalles", []), start=1): fila.update( { - "codigo%s" % li: det.get("codigo", ""), - "descripcion%s" % li: det.get("ds", ""), - "umed%s" % li: det.get("umed"), - "cantidad%s" % li: det.get("qty"), - "precio%s" % li: det.get("precio"), - "importe%s" % li: det.get("importe"), - "iva_id%s" % li: det.get("iva_id"), - "imp_iva%s" % li: det.get("imp_iva"), - "bonif%s" % li: det.get("bonif"), - "numero_despacho%s" % li: det.get("despacho"), - "dato_a%s" % li: det.get("dato_a"), - "dato_b%s" % li: det.get("dato_b"), - "dato_c%s" % li: det.get("dato_c"), - "dato_d%s" % li: det.get("dato_d"), - "dato_e%s" % li: det.get("dato_e"), + "codigo%s" % i: det.get("codigo", ""), + "descripcion%s" % i: det.get("ds", ""), + "umed%s" % i: det.get("umed"), + "cantidad%s" % i: det.get("qty"), + "precio%s" % i: det.get("precio"), + "importe%s" % i: det.get("importe"), + "iva_id%s" % i: det.get("iva_id"), + "imp_iva%s" % i: det.get("imp_iva"), + "bonif%s" % i: det.get("bonif"), + "numero_despacho%s" % i: det.get("despacho"), + "dato_a%s" % i: det.get("dato_a"), + "dato_b%s" % i: det.get("dato_b"), + "dato_c%s" % i: det.get("dato_c"), + "dato_d%s" % i: det.get("dato_d"), + "dato_e%s" % i: det.get("dato_e"), } ) - for i, iva in enumerate(reg["ivas"]): - li = i + 1 + + for i, iva in enumerate(reg.get("ivas", []), start=1): fila.update( { - "iva_id_%s" % li: iva["iva_id"], - "iva_base_imp_%s" % li: iva["base_imp"], - "iva_importe_%s" % li: iva["importe"], + "iva_id_%s" % i: iva.get("iva_id"), + "iva_base_imp_%s" % i: iva.get("base_imp"), + "iva_importe_%s" % i: iva.get("importe"), } ) - for i, tributo in enumerate(reg["tributos"]): - li = i + 1 + + for i, tributo in enumerate(reg.get("tributos", []), start=1): fila.update( { - "tributo_id_%s" % li: tributo["tributo_id"], - "tributo_base_imp_%s" % li: tributo["base_imp"], - "tributo_desc_%s" % li: tributo["desc"], - "tributo_alic_%s" % li: tributo["alic"], - "tributo_importe_%s" % li: tributo["importe"], + "tributo_id_%s" % i: tributo.get("tributo_id"), + "tributo_base_imp_%s" % i: tributo.get("base_imp"), + "tributo_desc_%s" % i: tributo.get("desc"), + "tributo_alic_%s" % i: tributo.get("alic"), + "tributo_importe_%s" % i: tributo.get("importe"), } ) - for i, opcional in enumerate(reg.get("opcionales", [])): - li = i + 1 + + for i, opcional in enumerate(reg.get("opcionales", []), start=1): fila.update( { - "opcional_id_%s" % li: opcional["opcional_id"], - "opcional_valor_%s" % li: opcional["valor"], + "opcional_id_%s" % i: opcional.get("opcional_id"), + "opcional_valor_%s" % i: opcional.get("valor"), } ) - for i, cbte_asoc in enumerate(reg.get("cbtes_asoc", [])): - li = i + 1 + + for i, cbte_asoc in enumerate(reg.get("cbtes_asoc", []), start=1): fila.update( { - "cbte_asoc_tipo_%s" % li: cbte_asoc["cbte_tipo"], - "cbte_asoc_pto_vta_%s" % li: cbte_asoc["cbte_punto_vta"], - "cbte_asoc_nro_%s" % li: cbte_asoc["cbte_nro"], - "cbte_asoc_cuit_%s" % li: cbte_asoc["cbte_cuit"], - "cbte_asoc_fecha_%s" % li: cbte_asoc["cbte_fecha"], + "cbte_asoc_tipo_%s" % i: cbte_asoc.get("cbte_tipo"), + "cbte_asoc_pto_vta_%s" % i: cbte_asoc.get("cbte_punto_vta"), + "cbte_asoc_nro_%s" % i: cbte_asoc.get("cbte_nro"), + "cbte_asoc_cuit_%s" % i: cbte_asoc.get("cbte_cuit"), + "cbte_asoc_fecha_%s" % i: cbte_asoc.get("cbte_fecha"), } ) @@ -187,12 +186,14 @@ def aplanar(regs): "numero_remito", "obs_generales", "obs_comerciales", + "forma_pago", + "pdf", ] # filtro y ordeno las columnas l = [k for f in filas for k in list(f.keys())] s = set(l) - set(cols) - cols = cols + list(s) + cols.extend(sorted(s)) ret = [cols] for fila in filas: @@ -201,6 +202,8 @@ def aplanar(regs): return ret + + def desaplanar(filas): "Dado una planilla, conviertir en estructura python" diff --git a/tests/conftest.py b/tests/conftest.py index bb1283ba5..2431c86b0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -11,6 +11,7 @@ # for more details. import os +import json import pytest from pyafipws.wsaa import WSAA diff --git a/tests/test_formato_csv.py b/tests/test_formato_csv.py index d7cb9851e..36c1498e7 100644 --- a/tests/test_formato_csv.py +++ b/tests/test_formato_csv.py @@ -17,6 +17,7 @@ __license__ = "GPL 3.0" import os +import sys import unittest import importlib.util import csv @@ -26,6 +27,10 @@ from openpyxl import Workbook from unittest.mock import patch +# Add the 'formatos' directory to the Python module search path +formatos_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'formatos')) +sys.path.insert(0, formatos_dir) + # Get the absolute path to the formato_csv.py file formato_csv_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'formatos', 'formato_csv.py')) @@ -182,6 +187,1948 @@ def test_leer_csv_special_characters(self): result = formato_csv.leer('data/sample_special_chars.csv', delimiter=',') self.assertEqual(result, expected_data) +@pytest.mark.dontusefix +class TestAplanarFunction(unittest.TestCase): + def test_aplanar_single_record(self): + """ + Test that the aplanar function correctly flattens a single record. + """ + reg = { + "id": 1, + "tipo_cbte": 1, + "punto_vta": 1, + "cbte_nro": 1, + "fecha_cbte": "2023-06-08", + "tipo_doc": 80, + "nro_doc": "20123456789", + "imp_total": 126, + "detalles": [ + { + "codigo": "P1", + "ds": "Producto 1", + "qty": 2, + "umed": 7, + "precio": 50, + "importe": 100, + } + ], + "ivas": [ + { + "iva_id": 5, + "base_imp": 100, + "importe": 21, + } + ], + "tributos": [ + { + "tributo_id": 1, + "base_imp": 100, + "desc": "Tributo 1", + "alic": 5, + "importe": 5, + } + ], + "forma_pago": "Contado", + } + + expected_data = [ + [ + 'id', + 'tipo_cbte', + 'punto_vta', + 'cbt_numero', + 'fecha_cbte', + 'tipo_doc', + 'nro_doc', + 'imp_total', + 'forma_pago', + 'pdf', + 'codigo1', + 'descripcion1', + 'umed1', + 'cantidad1', + 'precio1', + 'importe1', + 'iva_id_1', + 'iva_base_imp_1', + 'iva_importe_1', + 'tributo_id_1', + 'tributo_base_imp_1', + 'tributo_desc_1', + 'tributo_alic_1', + 'tributo_importe_1', + 'cbte_nro', + 'moneda_id', + 'moneda_ctz', + 'imp_neto', + 'imp_iva', + 'imp_trib', + 'imp_op_ex', + 'imp_tot_conc' + ], + [ + 1, + 1, + 1, + 1, + '2023-06-08', + 80, + '20123456789', + 126, + 'Contado', + '', + 'P1', + 'Producto 1', + 7, + 2, + 50, + 100, + 5, + 100, + 21, + 1, + 100, + 'Tributo 1', + 5, + 5, + 1, + None, + None, + None, + None, + None, + None, + None + ] + ] + + result = formato_csv.aplanar([reg]) + self.assertEqual(result, expected_data) + + + + + + + def test_aplanar_multiple_records(self): + """ + Test that the aplanar function correctly flattens multiple records. + """ + regs = [ + { + "id": 1, + "tipo_cbte": 1, + "punto_vta": 1, + "cbte_nro": 1, + "fecha_cbte": "2023-06-08", + "tipo_doc": 80, + "nro_doc": "20123456789", + "moneda_id": "PES", + "moneda_ctz": 1, + "imp_neto": 100, + "imp_iva": 21, + "imp_trib": 5, + "imp_op_ex": 0, + "imp_tot_conc": 0, + "imp_total": 126, + "concepto": 1, + "fecha_venc_pago": "2023-06-08", + "fecha_serv_desde": "2023-06-08", + "fecha_serv_hasta": "2023-06-08", + "cae": "1234567890", + "fecha_vto": "2023-06-18", + "resultado": "A", + "motivo": "", + "reproceso": "", + "nombre": "John Doe", + "domicilio": "123 Main St", + "localidad": "City", + "telefono": "1234567890", + "categoria": "A", + "email": "john@example.com", + "numero_cliente": "ABC123", + "numero_orden_compra": "OC123", + "condicion_frente_iva": "Responsable Inscripto", + "numero_cotizacion": "COT123", + "numero_remito": "REM123", + "obs_generales": "Observaciones generales", + "obs_comerciales": "Observaciones comerciales", + "detalles": [ + { + "codigo": "P1", + "ds": "Producto 1", + "qty": 2, + "umed": 7, + "precio": 50, + "importe": 100, + "iva_id": 5, + "imp_iva": 21, + "bonif": 0, + "despacho": "", + "dato_a": "", + "dato_b": "", + "dato_c": "", + "dato_d": "", + "dato_e": "", + } + ], + "ivas": [ + { + "iva_id": 5, + "base_imp": 100, + "importe": 21, + } + ], + "tributos": [ + { + "tributo_id": 1, + "base_imp": 100, + "desc": "Tributo 1", + "alic": 5, + "importe": 5, + } + ], + "opcionales": [ + { + "opcional_id": 1, + "valor": "Valor opcional 1", + } + ], + "cbtes_asoc": [ + { + "cbte_tipo": 1, + "cbte_punto_vta": 1, + "cbte_nro": 0, + "cbte_cuit": "20123456789", + "cbte_fecha": "2023-06-07", + } + ], + "forma_pago": "Contado", + }, + { + "id": 2, + "tipo_cbte": 1, + "punto_vta": 1, + "cbte_nro": 2, + "fecha_cbte": "2023-06-09", + "tipo_doc": 80, + "nro_doc": "20987654321", + "moneda_id": "PES", + "moneda_ctz": 1, + "imp_neto": 200, + "imp_iva": 42, + "imp_trib": 10, + "imp_op_ex": 0, + "imp_tot_conc": 0, + "imp_total": 252, + "concepto": 1, + "fecha_venc_pago": "2023-06-09", + "fecha_serv_desde": "2023-06-09", + "fecha_serv_hasta": "2023-06-09", + "cae": "0987654321", + "fecha_vto": "2023-06-19", + "resultado": "A", + "motivo": "", + "reproceso": "", + "nombre": "Jane Smith", + "domicilio": "456 Elm St", + "localidad": "Town", + "telefono": "0987654321", + "categoria": "B", + "email": "jane@example.com", + "numero_cliente": "XYZ789", + "numero_orden_compra": "OC456", + "condicion_frente_iva": "Responsable Inscripto", + "numero_cotizacion": "COT456", + "numero_remito": "REM456", + "obs_generales": "Observaciones generales", + "obs_comerciales": "Observaciones comerciales", + "detalles": [ + { + "codigo": "P2", + "ds": "Producto 2", + "qty": 1, + "umed": 7, + "precio": 200, + "importe": 200, + "iva_id": 5, + "imp_iva": 42, + "bonif": 0, + "despacho": "", + "dato_a": "", + "dato_b": "", + "dato_c": "", + "dato_d": "", + "dato_e": "", + } + ], + "ivas": [ + { + "iva_id": 5, + "base_imp": 200, + "importe": 42, + } + ], + "tributos": [ + { + "tributo_id": 2, + "base_imp": 200, + "desc": "Tributo 2", + "alic": 5, + "importe": 10, + } + ], + "opcionales": [ + { + "opcional_id": 2, + "valor": "Valor opcional 2", + } + ], + "cbtes_asoc": [ + { + "cbte_tipo": 1, + "cbte_punto_vta": 1, + "cbte_nro": 1, + "cbte_cuit": "20123456789", + "cbte_fecha": "2023-06-08", + } + ], + "forma_pago": "Tarjeta de Crédito", + }, + ] + + expected_data = [ + [ + "id", + "tipo_cbte", + "punto_vta", + "cbt_numero", + "fecha_cbte", + "tipo_doc", + "nro_doc", + "moneda_id", + "moneda_ctz", + "imp_neto", + "imp_iva", + "imp_trib", + "imp_op_ex", + "imp_tot_conc", + "imp_total", + "concepto", + "fecha_venc_pago", + "fecha_serv_desde", + "fecha_serv_hasta", + "cae", + "fecha_vto", + "resultado", + "motivo", + "reproceso", + "nombre", + "domicilio", + "localidad", + "telefono", + "categoria", + "email", + "numero_cliente", + "numero_orden_compra", + "condicion_frente_iva", + "numero_cotizacion", + "numero_remito", + "obs_generales", + "obs_comerciales", + "forma_pago", + "pdf", + "codigo1", + "descripcion1", + "umed1", + "cantidad1", + "precio1", + "importe1", + "iva_id1", + "imp_iva1", + "bonif1", + "numero_despacho1", + "dato_a1", + "dato_b1", + "dato_c1", + "dato_d1", + "dato_e1", + "iva_id_1", + "iva_base_imp_1", + "iva_importe_1", + "tributo_id_1", + "tributo_base_imp_1", + "tributo_desc_1", + "tributo_alic_1", + "tributo_importe_1", + "opcional_id_1", + "opcional_valor_1", + "cbte_asoc_tipo_1", + "cbte_asoc_pto_vta_1", + "cbte_asoc_nro_1", + "cbte_asoc_cuit_1", + "cbte_asoc_fecha_1", + "codigo2", + "descripcion2", + "umed2", + "cantidad2", + "precio2", + "importe2", + "iva_id2", + "imp_iva2", + "bonif2", + "numero_despacho2", + "dato_a2", + "dato_b2", + "dato_c2", + "dato_d2", + "dato_e2", + "iva_id_2", + "iva_base_imp_2", + "iva_importe_2", + "tributo_id_2", + "tributo_base_imp_2", + "tributo_desc_2", + "tributo_alic_2", + "tributo_importe_2", + "opcional_id_2", + "opcional_valor_2", + "cbte_asoc_tipo_2", + "cbte_asoc_pto_vta_2", + "cbte_asoc_nro_2", + "cbte_asoc_cuit_2", + "cbte_asoc_fecha_2", + ], + [ + 1, + 1, + 1, + 1, + "2023-06-08", + 80, + "20123456789", + "PES", + 1, + 100, + 21, + 5, + 0, + 0, + 126, + 1, + "2023-06-08", + "2023-06-08", + "2023-06-08", + "1234567890", + "2023-06-18", + "A", + "", + "", + "John Doe", + "123 Main St", + "City", + "1234567890", + "A", + "john@example.com", + "ABC123", + "OC123", + "Responsable Inscripto", + "COT123", + "REM123", + "Observaciones generales", + "Observaciones comerciales", + "Contado", + "", + "P1", + "Producto 1", + 7, + 2, + 50, + 100, + 5, + 21, + 0, + "", + "", + "", + "", + "", + "", + 5, + 100, + 21, + 1, + 100, + "Tributo 1", + 5, + 5, + 1, + "Valor opcional 1", + 1, + 1, + 0, + "20123456789", + "2023-06-07", + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + ], + [ + 2, + 1, + 1, + 2, + "2023-06-09", + 80, + "20987654321", + "PES", + 1, + 200, + 42, + 10, + 0, + 0, + 252, + 1, + "2023-06-09", + "2023-06-09", + "2023-06-09", + "0987654321", + "2023-06-19", + "A", + "", + "", + "Jane Smith", + "456 Elm St", + "Town", + "0987654321", + "B", + "jane@example.com", + "XYZ789", + "OC456", + "Responsable Inscripto", + "COT456", + "REM456", + "Observaciones generales", + "Observaciones comerciales", + "Tarjeta de Crédito", + "", + "P2", + "Producto 2", + 7, + 1, + 200, + 200, + 5, + 42, + 0, + "", + "", + "", + "", + "", + "", + 5, + 200, + 42, + 2, + 200, + "Tributo 2", + 5, + 10, + 2, + "Valor opcional 2", + 1, + 1, + 1, + "20123456789", + "2023-06-08", + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + ], + ] + + result = formato_csv.aplanar(regs) + self.assertEqual(result, expected_data) + + def test_aplanar_empty_records(self): + """ + Test that the aplanar function handles empty records correctly. + """ + regs = [] + expected_data = [ + [ + "id", + "tipo_cbte", + "punto_vta", + "cbt_numero", + "fecha_cbte", + "tipo_doc", + "nro_doc", + "moneda_id", + "moneda_ctz", + "imp_neto", + "imp_iva", + "imp_trib", + "imp_op_ex", + "imp_tot_conc", + "imp_total", + "concepto", + "fecha_venc_pago", + "fecha_serv_desde", + "fecha_serv_hasta", + "cae", + "fecha_vto", + "resultado", + "motivo", + "reproceso", + "nombre", + "domicilio", + "localidad", + "telefono", + "categoria", + "email", + "numero_cliente", + "numero_orden_compra", + "condicion_frente_iva", + "numero_cotizacion", + "numero_remito", + "obs_generales", + "obs_comerciales", + ], + ] + result = formato_csv.aplanar(regs) + self.assertEqual(result, expected_data) + + + + + + def test_aplanar_missing_fields(self): + """ + Test that the aplanar function handles records with missing fields correctly. + """ + regs = [ + { + "id": 1, + "tipo_cbte": 1, + "punto_vta": 1, + "cbte_nro": 1, + "fecha_cbte": "2023-06-08", + "tipo_doc": 80, + "nro_doc": "20123456789", + "moneda_id": "PES", + "moneda_ctz": 1, + "imp_neto": 100, + "imp_iva": 21, + "imp_trib": 5, + "imp_op_ex": 0, + "imp_tot_conc": 0, + "imp_total": 126, + "concepto": 1, + "fecha_venc_pago": "2023-06-08", + "fecha_serv_desde": "2023-06-08", + "fecha_serv_hasta": "2023-06-08", + "cae": "1234567890", + "fecha_vto": "2023-06-18", + "resultado": "A", + "motivo": "", + "reproceso": "", + "nombre": "John Doe", + "domicilio": "123 Main St", + "localidad": "City", + "telefono": "1234567890", + "categoria": "A", + "email": "john@example.com", + "numero_cliente": "ABC123", + "numero_orden_compra": "OC123", + "condicion_frente_iva": "Responsable Inscripto", + "numero_cotizacion": "COT123", + "numero_remito": "REM123", + "obs_generales": "Observaciones generales", + "obs_comerciales": "Observaciones comerciales", + "detalles": [], + "ivas": [], + "tributos": [], + "opcionales": [], + "cbtes_asoc": [], + "forma_pago": "Contado", + }, + ] + + expected_data = [ + [ + "id", + "tipo_cbte", + "punto_vta", + "cbt_numero", + "fecha_cbte", + "tipo_doc", + "nro_doc", + "moneda_id", + "moneda_ctz", + "imp_neto", + "imp_iva", + "imp_trib", + "imp_op_ex", + "imp_tot_conc", + "imp_total", + "concepto", + "fecha_venc_pago", + "fecha_serv_desde", + "fecha_serv_hasta", + "cae", + "fecha_vto", + "resultado", + "motivo", + "reproceso", + "nombre", + "domicilio", + "localidad", + "telefono", + "categoria", + "email", + "numero_cliente", + "numero_orden_compra", + "condicion_frente_iva", + "numero_cotizacion", + "numero_remito", + "obs_generales", + "obs_comerciales", + "provincia_cliente", + "forma_pago", + "pais_dst_cmp", + "id_impositivo", + "moneda", + "tipo_cambio", + "incoterms", + "idioma_cbte", + "motivos_obs", + "cae_cbte", + "fch_venc_cae", + "pais_dst_cliente", + "pdf", + ], + [ + 1, + 1, + 1, + 1, + "2023-06-08", + 80, + "20123456789", + "PES", + 1, + 100, + 21, + 5, + 0, + 0, + 126, + 1, + "2023-06-08", + "2023-06-08", + "2023-06-08", + "1234567890", + "2023-06-18", + "A", + "", + "", + "John Doe", + "123 Main St", + "City", + "1234567890", + "A", + "john@example.com", + "ABC123", + "OC123", + "Responsable Inscripto", + "COT123", + "REM123", + "Observaciones generales", + "Observaciones comerciales", + None, + "Contado", + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + "", + ], + ] + + result = formato_csv.aplanar(regs) + self.assertEqual(result, expected_data) + +# @pytest.mark.dontusefix +# class TestEscribir(unittest.TestCase): +# def test_escribir_csv_file(self): +# data = [ +# ["Column1", "Column2", "Column3"], +# ["Value1", "Value2", "Value3"], +# ["Value4", "Value5", "Value6"], +# ] +# expected_csv_content = "Column1,Column2,Column3\nValue1,Value2,Value3\nValue4,Value5,Value6\n" +# with tempfile.NamedTemporaryFile(suffix=".csv", delete=False) as temp_file: +# formato_csv.escribir(data, temp_file.name) +# with open(temp_file.name, "r") as file: +# csv_content = file.read() +# self.assertEqual(csv_content, expected_csv_content) +# os.unlink(temp_file.name) + +# def test_escribir_xlsx_file(self): +# data = [ +# ["Column1", "Column2", "Column3"], +# ["Value1", "Value2", "Value3"], +# ["Value4", "Value5", "Value6"], +# ] +# with tempfile.NamedTemporaryFile(suffix=".xlsx", delete=False) as temp_file: +# formato_csv.escribir(data, temp_file.name) +# workbook = load_workbook(temp_file.name) +# sheet = workbook.active +# self.assertEqual(sheet["A1"].value, "Column1") +# self.assertEqual(sheet["B1"].value, "Column2") +# self.assertEqual(sheet["C1"].value, "Column3") +# self.assertEqual(sheet["A2"].value, "Value1") +# self.assertEqual(sheet["B2"].value, "Value2") +# self.assertEqual(sheet["C2"].value, "Value3") +# self.assertEqual(sheet["A3"].value, "Value4") +# self.assertEqual(sheet["B3"].value, "Value5") +# self.assertEqual(sheet["C3"].value, "Value6") +# os.unlink(temp_file.name) + +# @pytest.mark.dontusefix +# class TestDescribir(unittest.TestCase): +# def test_desaplanar_single_record(self): +# data = [ +# [ +# "id", +# "tipo_cbte", +# "punto_vta", +# "cbt_numero", +# "fecha_cbte", +# "tipo_doc", +# "nro_doc", +# "moneda_id", +# "moneda_ctz", +# "imp_neto", +# "imp_iva", +# "imp_trib", +# "imp_op_ex", +# "imp_tot_conc", +# "imp_total", +# "concepto", +# "fecha_venc_pago", +# "fecha_serv_desde", +# "fecha_serv_hasta", +# "cae", +# "fecha_vto", +# "resultado", +# "motivo", +# "reproceso", +# "nombre", +# "domicilio", +# "localidad", +# "telefono", +# "categoria", +# "email", +# "numero_cliente", +# "numero_orden_compra", +# "condicion_frente_iva", +# "numero_cotizacion", +# "numero_remito", +# "obs_generales", +# "obs_comerciales", +# "forma_pago", +# "pdf", +# "codigo1", +# "descripcion1", +# "umed1", +# "cantidad1", +# "precio1", +# "importe1", +# "iva_id1", +# "imp_iva1", +# "bonif1", +# "numero_despacho1", +# "dato_a1", +# "dato_b1", +# "dato_c1", +# "dato_d1", +# "dato_e1", +# "iva_id_1", +# "iva_base_imp_1", +# "iva_importe_1", +# "tributo_id_1", +# "tributo_base_imp_1", +# "tributo_desc_1", +# "tributo_alic_1", +# "tributo_importe_1", +# "opcional_id_1", +# "opcional_valor_1", +# "cbte_asoc_tipo_1", +# "cbte_asoc_pto_vta_1", +# "cbte_asoc_nro_1", +# "cbte_asoc_cuit_1", +# "cbte_asoc_fecha_1", +# ], +# [ +# 1, +# 1, +# 1, +# 1, +# "2023-06-08", +# 80, +# "20123456789", +# "PES", +# 1, +# 100, +# 21, +# 5, +# 0, +# 0, +# 126, +# 1, +# "2023-06-08", +# "2023-06-08", +# "2023-06-08", +# "1234567890", +# "2023-06-18", +# "A", +# "", +# "", +# "John Doe", +# "123 Main St", +# "City", +# "1234567890", +# "A", +# "john@example.com", +# "ABC123", +# "OC123", +# "Responsable Inscripto", +# "COT123", +# "REM123", +# "Observaciones generales", +# "Observaciones comerciales", +# "Contado", +# "", +# "P1", +# "Producto 1", +# 7, +# 2, +# 50, +# 100, +# 5, +# 21, +# 0, +# "", +# "", +# "", +# "", +# "", +# "", +# 5, +# 100, +# 21, +# 1, +# 100, +# "Tributo 1", +# 5, +# 5, +# 1, +# "Valor opcional 1", +# 1, +# 1, +# 0, +# "20123456789", +# "2023-06-07", +# ], +# ] +# expected_result = [ +# { +# "id": 1, +# "tipo_cbte": 1, +# "punto_vta": 1, +# "cbte_nro": 1, +# "fecha_cbte": "2023-06-08", +# "tipo_doc": 80, +# "nro_doc": "20123456789", +# "moneda_id": "PES", +# "moneda_ctz": 1, +# "imp_neto": 100, +# "imp_iva": 21, +# "imp_trib": 5, +# "imp_op_ex": 0, +# "imp_tot_conc": 0, +# "imp_total": 126, +# "concepto": 1, +# "fecha_venc_pago": "2023-06-08", +# "fecha_serv_desde": "2023-06-08", +# "fecha_serv_hasta": "2023-06-08", +# "cae": "1234567890", +# "fecha_vto": "2023-06-18", +# "resultado": "A", +# "motivo": "", +# "reproceso": "", +# "nombre": "John Doe", +# "domicilio": "123 Main St", +# "localidad": "City", +# "telefono": "1234567890", +# "categoria": "A", +# "email": "john@example.com", +# "numero_cliente": "ABC123", +# "numero_orden_compra": "OC123", +# "condicion_frente_iva": "Responsable Inscripto", +# "numero_cotizacion": "COT123", +# "numero_remito": "REM123", +# "obs_generales": "Observaciones generales", +# "obs_comerciales": "Observaciones comerciales", +# "forma_pago": "Contado", +# "detalles": [ +# { +# "codigo": "P1", +# "ds": "Producto 1", +# "umed": 7, +# "qty": 2, +# "precio": 50, +# "importe": 100, +# "iva_id": 5, +# "imp_iva": 21, +# "bonif": 0, +# "despacho": None, +# "dato_a": None, +# "dato_b": None, +# "dato_c": None, +# "dato_d": None, +# "dato_e": None, +# } +# ], +# "tributos": [ +# { +# "tributo_id": 1, +# "desc": "Tributo 1", +# "base_imp": 100, +# "alic": 5, +# "importe": 5, +# } +# ], +# "ivas": [ +# { +# "iva_id": 5, +# "base_imp": 100, +# "importe": 21, +# } +# ], +# "permisos": [], +# "opcionales": [ +# { +# "opcional_id": 1, +# "valor": "Valor opcional 1", +# } +# ], +# "cbtes_asoc": [ +# { +# "cbte_tipo": 1, +# "cbte_punto_vta": 1, +# "cbte_nro": 0, +# "cbte_cuit": "20123456789", +# "cbte_fecha": "2023-06-07", +# } +# ], +# "datos": [], +# } +# ] +# result = formato_csv.desaplanar(data) +# self.assertEqual(result, expected_result) + +# def test_desaplanar_multiple_records(self): +# data = [ +# [ +# "id", +# "tipo_cbte", +# "punto_vta", +# "cbt_numero", +# "fecha_cbte", +# "tipo_doc", +# "nro_doc", +# "moneda_id", +# "moneda_ctz", +# "imp_neto", +# "imp_iva", +# "imp_trib", +# "imp_op_ex", +# "imp_tot_conc", +# "imp_total", +# "concepto", +# "fecha_venc_pago", +# "fecha_serv_desde", +# "fecha_serv_hasta", +# "cae", +# "fecha_vto", +# "resultado", +# "motivo", +# "reproceso", +# "nombre", +# "domicilio", +# "localidad", +# "telefono", +# "categoria", +# "email", +# "numero_cliente", +# "numero_orden_compra", +# "condicion_frente_iva", +# "numero_cotizacion", +# "numero_remito", +# "obs_generales", +# "obs_comerciales", +# "forma_pago", +# "pdf", +# "codigo1", +# "descripcion1", +# "umed1", +# "cantidad1", +# "precio1", +# "importe1", +# "iva_id1", +# "imp_iva1", +# "bonif1", +# "numero_despacho1", +# "dato_a1", +# "dato_b1", +# "dato_c1", +# "dato_d1", +# "dato_e1", +# "iva_id_1", +# "iva_base_imp_1", +# "iva_importe_1", +# "tributo_id_1", +# "tributo_base_imp_1", +# "tributo_desc_1", +# "tributo_alic_1", +# "tributo_importe_1", +# "opcional_id_1", +# "opcional_valor_1", +# "cbte_asoc_tipo_1", +# "cbte_asoc_pto_vta_1", +# "cbte_asoc_nro_1", +# "cbte_asoc_cuit_1", +# "cbte_asoc_fecha_1", +# "codigo2", +# "descripcion2", +# "umed2", +# "cantidad2", +# "precio2", +# "importe2", +# "iva_id2", +# "imp_iva2", +# "bonif2", +# "numero_despacho2", +# "dato_a2", +# "dato_b2", +# "dato_c2", +# "dato_d2", +# "dato_e2", +# "iva_id_2", +# "iva_base_imp_2", +# "iva_importe_2", +# "tributo_id_2", +# "tributo_base_imp_2", +# "tributo_desc_2", +# "tributo_alic_2", +# "tributo_importe_2", +# "opcional_id_2", +# "opcional_valor_2", +# "cbte_asoc_tipo_2", +# "cbte_asoc_pto_vta_2", +# "cbte_asoc_nro_2", +# "cbte_asoc_cuit_2", +# "cbte_asoc_fecha_2", +# ], +# [ +# 1, +# 1, +# 1, +# 1, +# "2023-06-08", +# 80, +# "20123456789", +# "PES", +# 1, +# 100, +# 21, +# 5, +# 0, +# 0, +# 126, +# 1, +# "2023-06-08", +# "2023-06-08", +# "2023-06-08", +# "1234567890", +# "2023-06-18", +# "A", +# "", +# "", +# "John Doe", +# "123 Main St", +# "City", +# "1234567890", +# "A", +# "john@example.com", +# "ABC123", +# "OC123", +# "Responsable Inscripto", +# "COT123", +# "REM123", +# "Observaciones generales", +# "Observaciones comerciales", +# "Contado", +# "", +# "P1", +# "Producto 1", +# 7, +# 2, +# 50, +# 100, +# 5, +# 21, +# 0, +# "", +# "", +# "", +# "", +# "", +# "", +# 5, +# 100, +# 21, +# 1, +# 100, +# "Tributo 1", +# 5, +# 5, +# 1, +# "Valor opcional 1", +# 1, +# 1, +# 0, +# "20123456789", +# "2023-06-07", +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# ], +# [ +# 2, +# 1, +# 1, +# 2, +# "2023-06-09", +# 80, +# "20987654321", +# "PES", +# 1, +# 200, +# 42, +# 10, +# 0, +# 0, +# 252, +# 1, +# "2023-06-09", +# "2023-06-09", +# "2023-06-09", +# "0987654321", +# "2023-06-19", +# "A", +# "", +# "", +# "Jane Smith", +# "456 Elm St", +# "Town", +# "0987654321", +# "B", +# "jane@example.com", +# "XYZ789", +# "OC456", +# "Responsable Inscripto", +# "COT456", +# "REM456", +# "Observaciones generales", +# "Observaciones comerciales", +# "Tarjeta de Crédito", +# "", +# "P2", +# "Producto 2", +# 7, +# 1, +# 200, +# 200, +# 5, +# 42, +# 0, +# "", +# "", +# "", +# "", +# "", +# "", +# 5, +# 200, +# 42, +# 2, +# 200, +# "Tributo 2", +# 5, +# 10, +# 2, +# "Valor opcional 2", +# 1, +# 1, +# 1, +# "20123456789", +# "2023-06-08", +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# None, +# ], +# ] +# expected_result = [ +# { +# "id": 1, +# "tipo_cbte": 1, +# "punto_vta": 1, +# "cbte_nro": 1, +# "fecha_cbte": "2023-06-08", +# "tipo_doc": 80, +# "nro_doc": "20123456789", +# "moneda_id": "PES", +# "moneda_ctz": 1, +# "imp_neto": 100, +# "imp_iva": 21, +# "imp_trib": 5, +# "imp_op_ex": 0, +# "imp_tot_conc": 0, +# "imp_total": 126, +# "concepto": 1, +# "fecha_venc_pago": "2023-06-08", +# "fecha_serv_desde": "2023-06-08", +# "fecha_serv_hasta": "2023-06-08", +# "cae": "1234567890", +# "fecha_vto": "2023-06-18", +# "resultado": "A", +# "motivo": "", +# "reproceso": "", +# "nombre": "John Doe", +# "domicilio": "123 Main St", +# "localidad": "City", +# "telefono": "1234567890", +# "categoria": "A", +# "email": "john@example.com", +# "numero_cliente": "ABC123", +# "numero_orden_compra": "OC123", +# "condicion_frente_iva": "Responsable Inscripto", +# "numero_cotizacion": "COT123", +# "numero_remito": "REM123", +# "obs_generales": "Observaciones generales", +# "obs_comerciales": "Observaciones comerciales", +# "forma_pago": "Contado", +# "detalles": [ +# { +# "codigo": "P1", +# "ds": "Producto 1", +# "umed": 7, +# "qty": 2, +# "precio": 50, +# "importe": 100, +# "iva_id": 5, +# "imp_iva": 21, +# "bonif": 0, +# "despacho": None, +# "dato_a": None, +# "dato_b": None, +# "dato_c": None, +# "dato_d": None, +# "dato_e": None, +# } +# ], +# "tributos": [ +# { +# "tributo_id": 1, +# "desc": "Tributo 1", +# "base_imp": 100, +# "alic": 5, +# "importe": 5, +# } +# ], +# "ivas": [ +# { +# "iva_id": 5, +# "base_imp": 100, +# "importe": 21, +# } +# ], +# "permisos": [], +# "opcionales": [ +# { +# "opcional_id": 1, +# "valor": "Valor opcional 1", +# } +# ], +# "cbtes_asoc": [ +# { +# "cbte_tipo": 1, +# "cbte_punto_vta": 1, +# "cbte_nro": 0, +# "cbte_cuit": "20123456789", +# "cbte_fecha": "2023-06-07", +# } +# ], +# "datos": [], +# }, +# { +# "id": 2, +# "tipo_cbte": 1, +# "punto_vta": 1, +# "cbte_nro": 2, +# "fecha_cbte": "2023-06-09", +# "tipo_doc": 80, +# "nro_doc": "20987654321", +# "moneda_id": "PES", +# "moneda_ctz": 1, +# "imp_neto": 200, +# "imp_iva": 42, +# "imp_trib": 10, +# "imp_op_ex": 0, +# "imp_tot_conc": 0, +# "imp_total": 252, +# "concepto": 1, +# "fecha_venc_pago": "2023-06-09", +# "fecha_serv_desde": "2023-06-09", +# "fecha_serv_hasta": "2023-06-09", +# "cae": "0987654321", +# "fecha_vto": "2023-06-19", +# "resultado": "A", +# "motivo": "", +# "reproceso": "", +# "nombre": "Jane Smith", +# "domicilio": "456 Elm St", +# "localidad": "Town", +# "telefono": "0987654321", +# "categoria": "B", +# "email": "jane@example.com", +# "numero_cliente": "XYZ789", +# "numero_orden_compra": "OC456", +# "condicion_frente_iva": "Responsable Inscripto", +# "numero_cotizacion": "COT456", +# "numero_remito": "REM456", +# "obs_generales": "Observaciones generales", +# "obs_comerciales": "Observaciones comerciales", +# "forma_pago": "Tarjeta de Crédito", +# "detalles": [ +# { +# "codigo": "P2", +# "ds": "Producto 2", +# "umed": 7, +# "qty": 1, +# "precio": 200, +# "importe": 200, +# "iva_id": 5, +# "imp_iva": 42, +# "bonif": 0, +# "despacho": None, +# "dato_a": None, +# "dato_b": None, +# "dato_c": None, +# "dato_d": None, +# "dato_e": None, +# } +# ], +# "tributos": [ +# { +# "tributo_id": 2, +# "desc": "Tributo 2", +# "base_imp": 200, +# "alic": 5, +# "importe": 10, +# } +# ], +# "ivas": [ +# { +# "iva_id": 5, +# "base_imp": 200, +# "importe": 42, +# } +# ], +# "permisos": [], +# "opcionales": [ +# { +# "opcional_id": 2, +# "valor": "Valor opcional 2", +# } +# ], +# "cbtes_asoc": [ +# { +# "cbte_tipo": 1, +# "cbte_punto_vta": 1, +# "cbte_nro": 1, +# "cbte_cuit": "20123456789", +# "cbte_fecha": "2023-06-08", +# } +# ], +# "datos": [], +# }, +# ] +# result = formato_csv.desaplanar(data) +# self.assertEqual(result, expected_result) + +# def test_desaplanar_empty_data(self): +# data = [ +# [ +# "id", +# "tipo_cbte", +# "punto_vta", +# "cbt_numero", +# "fecha_cbte", +# "tipo_doc", +# "nro_doc", +# "moneda_id", +# "moneda_ctz", +# "imp_neto", +# "imp_iva", +# "imp_trib", +# "imp_op_ex", +# "imp_tot_conc", +# "imp_total", +# "concepto", +# "fecha_venc_pago", +# "fecha_serv_desde", +# "fecha_serv_hasta", +# "cae", +# "fecha_vto", +# "resultado", +# "motivo", +# "reproceso", +# "nombre", +# "domicilio", +# "localidad", +# "telefono", +# "categoria", +# "email", +# "numero_cliente", +# "numero_orden_compra", +# "condicion_frente_iva", +# "numero_cotizacion", +# "numero_remito", +# "obs_generales", +# "obs_comerciales", +# "forma_pago", +# "pdf", +# ], +# ] +# expected_result = [] +# result = formato_csv.desaplanar(data) +# self.assertEqual(result, expected_result) + +# def test_desaplanar_missing_fields(self): +# data = [ +# [ +# "id", +# "tipo_cbte", +# "punto_vta", +# "cbt_numero", +# "fecha_cbte", +# "tipo_doc", +# "nro_doc", +# "moneda_id", +# "moneda_ctz", +# "imp_neto", +# "imp_iva", +# "imp_trib", +# "imp_op_ex", +# "imp_tot_conc", +# "imp_total", +# "concepto", +# "fecha_venc_pago", +# "fecha_serv_desde", +# "fecha_serv_hasta", +# "cae", +# "fecha_vto", +# "resultado", +# "motivo", +# "reproceso", +# "nombre", +# "domicilio", +# "localidad", +# "telefono", +# "categoria", +# "email", +# "numero_cliente", +# "numero_orden_compra", +# "condicion_frente_iva", +# "numero_cotizacion", +# "numero_remito", +# "obs_generales", +# "obs_comerciales", +# "forma_pago", +# "pdf", +# ], +# [ +# 1, +# 1, +# 1, +# 1, +# "2023-06-08", +# 80, +# "20123456789", +# "PES", +# 1, +# 100, +# 21, +# 5, +# 0, +# 0, +# 126, +# 1, +# "2023-06-08", +# "2023-06-08", +# "2023-06-08", +# "1234567890", +# "2023-06-18", +# "A", +# "", +# "", +# "John Doe", +# "123 Main St", +# "City", +# "1234567890", +# "A", +# "john@example.com", +# "ABC123", +# "OC123", +# "Responsable Inscripto", +# "COT123", +# "REM123", +# "Observaciones generales", +# "Observaciones comerciales", +# "Contado", +# "", +# ], +# ] +# expected_result = [ +# { +# "id": 1, +# "tipo_cbte": 1, +# "punto_vta": 1, +# "cbte_nro": 1, +# "fecha_cbte": "2023-06-08", +# "tipo_doc": 80, +# "nro_doc": "20123456789", +# "moneda_id": "PES", +# "moneda_ctz": 1, +# "imp_neto": 100, +# "imp_iva": 21, +# "imp_trib": 5, +# "imp_op_ex": 0, +# "imp_tot_conc": 0, +# "imp_total": 126, +# "concepto": 1, +# "fecha_venc_pago": "2023-06-08", +# "fecha_serv_desde": "2023-06-08", +# "fecha_serv_hasta": "2023-06-08", +# "cae": "1234567890", +# "fecha_vto": "2023-06-18", +# "resultado": "A", +# "motivo": "", +# "reproceso": "", +# "nombre": "John Doe", +# "domicilio": "123 Main St", +# "localidad": "City", +# "telefono": "1234567890", +# "categoria": "A", +# "email": "john@example.com", +# "numero_cliente": "ABC123", +# "numero_orden_compra": "OC123", +# "condicion_frente_iva": "Responsable Inscripto", +# "numero_cotizacion": "COT123", +# "numero_remito": "REM123", +# "obs_generales": "Observaciones generales", +# "obs_comerciales": "Observaciones comerciales", +# "forma_pago": "Contado", +# "detalles": [], +# "tributos": [], +# "ivas": [], +# "permisos": [], +# "opcionales": [], +# "cbtes_asoc": [], +# "datos": [], +# } +# ] +# result = formato_csv.desaplanar(data) +# self.assertEqual(result, expected_result) + +# def test_desaplanar_extra_fields(self): +# data = [ +# [ +# "id", +# "tipo_cbte", +# "punto_vta", +# "cbt_numero", +# "fecha_cbte", +# "tipo_doc", +# "nro_doc", +# "moneda_id", +# "moneda_ctz", +# "imp_neto", +# "imp_iva", +# "imp_trib", +# "imp_op_ex", +# "imp_tot_conc", +# "imp_total", +# "concepto", +# "fecha_venc_pago", +# "fecha_serv_desde", +# "fecha_serv_hasta", +# "cae", +# "fecha_vto", +# "resultado", +# "motivo", +# "reproceso", +# "nombre", +# "domicilio", +# "localidad", +# "telefono", +# "categoria", +# "email", +# "numero_cliente", +# "numero_orden_compra", +# "condicion_frente_iva", +# "numero_cotizacion", +# "numero_remito", +# "obs_generales", +# "obs_comerciales", +# "forma_pago", +# "pdf", +# "extra_field1", +# "extra_field2", +# ], +# [ +# 1, +# 1, +# 1, +# 1, +# "2023-06-08", +# 80, +# "20123456789", +# "PES", +# 1, +# 100, +# 21, +# 5, +# 0, +# 0, +# 126, +# 1, +# "2023-06-08", +# "2023-06-08", +# "2023-06-08", +# "1234567890", +# "2023-06-18", +# "A", +# "", +# "", +# "John Doe", +# "123 Main St", +# "City", +# "1234567890", +# "A", +# "john@example.com", +# "ABC123", +# "OC123", +# "Responsable Inscripto", +# "COT123", +# "REM123", +# "Observaciones generales", +# "Observaciones comerciales", +# "Contado", +# "", +# "Extra Value 1", +# "Extra Value 2", +# ], +# ] +# expected_result = [ +# { +# "id": 1, +# "tipo_cbte": 1, +# "punto_vta": 1, +# "cbte_nro": 1, +# "fecha_cbte": "2023-06-08", +# "tipo_doc": 80, +# "nro_doc": "20123456789", +# "moneda_id": "PES", +# "moneda_ctz": 1, +# "imp_neto": 100, +# "imp_iva": 21, +# "imp_trib": 5, +# "imp_op_ex": 0, +# "imp_tot_conc": 0, +# "imp_total": 126, +# "concepto": 1, +# "fecha_venc_pago": "2023-06-08", +# "fecha_serv_desde": "2023-06-08", +# "fecha_serv_hasta": "2023-06-08", +# "cae": "1234567890", +# "fecha_vto": "2023-06-18", +# "resultado": "A", +# "motivo": "", +# "reproceso": "", +# "nombre": "John Doe", +# "domicilio": "123 Main St", +# "localidad": "City", +# "telefono": "1234567890", +# "categoria": "A", +# "email": "john@example.com", +# "numero_cliente": "ABC123", +# "numero_orden_compra": "OC123", +# "condicion_frente_iva": "Responsable Inscripto", +# "numero_cotizacion": "COT123", +# "numero_remito": "REM123", +# "obs_generales": "Observaciones generales", +# "obs_comerciales": "Observaciones comerciales", +# "forma_pago": "Contado", +# "detalles": [], +# "tributos": [], +# "ivas": [], +# "permisos": [], +# "opcionales": [], +# "cbtes_asoc": [], +# "datos": [ +# { +# "campo": "extra_field1", +# "valor": "Extra Value 1", +# "pagina": "", +# }, +# { +# "campo": "extra_field2", +# "valor": "Extra Value 2", +# "pagina": "", +# }, +# ], +# } +# ] +# result = formato_csv.desaplanar(data) +# self.assertEqual(result, expected_result) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() From 3ed426d8a40ae8d9bdd572b8f7f5d9e2a7b853e5 Mon Sep 17 00:00:00 2001 From: SONIABHISHEK121 Date: Sun, 16 Jun 2024 20:13:05 +0530 Subject: [PATCH 4/6] feat : added tests for all functions and fixed failing build Signed-off-by: SONIABHISHEK121 --- formatos/formato_csv.py | 41 +- requirements-dev.txt | 3 +- requirements.txt | 1 + tests/test_formato_csv.py | 2386 ++++++++----------------------------- 4 files changed, 523 insertions(+), 1908 deletions(-) diff --git a/formatos/formato_csv.py b/formatos/formato_csv.py index 71bd75802..f1d50a12f 100644 --- a/formatos/formato_csv.py +++ b/formatos/formato_csv.py @@ -26,11 +26,11 @@ import os from openpyxl import load_workbook -def leer(fn="entrada.csv", delimiter=";"): +def leer(fn="entrada.csv", delimiter=";", header=True): "Analiza un archivo CSV y devuelve una lista de listas con los datos" ext = os.path.splitext(fn)[1].lower() items = [] - + if ext == ".csv": with open(fn, "r", encoding="utf-8") as csvfile: try: @@ -40,23 +40,20 @@ def leer(fn="entrada.csv", delimiter=";"): dialect.delimiter = delimiter csvfile.seek(0) csv_reader = csv.reader(csvfile, dialect) - header_skipped = False + if header: + next(csv_reader, None) # Skip the header row for row in csv_reader: - if not header_skipped: - header_skipped = True - continue items.append([c.strip() if isinstance(c, str) else c for c in row]) - + elif ext == ".xlsx": wb = load_workbook(filename=fn) ws1 = wb.active - header_skipped = False - for row in ws1.iter_rows(values_only=True): - if not header_skipped: - header_skipped = True - continue + rows = ws1.iter_rows(values_only=True) + if header: + next(rows, None) # Skip the header row + for row in rows: items.append([cell for cell in row]) - + return items # TODO: return desaplanar(items) @@ -341,22 +338,16 @@ def escribir(filas, fn="salida.csv", delimiter=";"): "Dado una lista de comprobantes (diccionarios), aplana y escribe" ext = os.path.splitext(fn)[1].lower() if ext == ".csv": - f = open(fn, "wb") - csv_writer = csv.writer(f, dialect="excel", delimiter=";") - # TODO: filas = aplanar(regs) - for fila in filas: - # convertir a ISO-8859-1 (evita error de encoding de csv writer): - fila = [ - celda.encode("latin1") if isinstance(celda, str) else celda - for celda in fila - ] - csv_writer.writerow(fila) - f.close() + with open(fn, "w", newline="") as f: + csv_writer = csv.writer(f, dialect="excel", delimiter=delimiter) + # TODO: filas = aplanar(regs) + for fila in filas: + csv_writer.writerow(fila) elif ext == ".xlsx": from openpyxl import Workbook wb = Workbook() - ws1 = wb.get_active_sheet() + ws1 = wb.active for fila in filas: ws1.append(fila) wb.save(filename=fn) diff --git a/requirements-dev.txt b/requirements-dev.txt index 8ca42cd32..7729ac8d6 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -11,4 +11,5 @@ pytest-freezegun==0.4.2; python_version > '3' pytest-mock==2.0.0; python_version <= '2.7' pytest-mock==3.10.0; python_version > '2.7' pywin32==304; sys_platform == "win32" and python_version > '3' -py2exe==0.11.1.1; sys_platform == "win32" and python_version > '3' \ No newline at end of file +py2exe==0.11.1.1; sys_platform == "win32" and python_version > '3' +openpyxl==3.1.2; python_version > '3' \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 59cb59a04..ea6b63188 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,3 +11,4 @@ tabulate==0.8.5 certifi>=2020.4.5.1 qrcode==6.1 future==0.18.3 +openpyxl==3.1.2; python_version > '3' diff --git a/tests/test_formato_csv.py b/tests/test_formato_csv.py index 36c1498e7..d81669c69 100644 --- a/tests/test_formato_csv.py +++ b/tests/test_formato_csv.py @@ -19,174 +19,190 @@ import os import sys import unittest -import importlib.util import csv import pytest import tempfile +from openpyxl import Workbook, load_workbook from io import StringIO -from openpyxl import Workbook from unittest.mock import patch # Add the 'formatos' directory to the Python module search path formatos_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'formatos')) sys.path.insert(0, formatos_dir) -# Get the absolute path to the formato_csv.py file -formato_csv_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'formatos', 'formato_csv.py')) - -# Load the formato_csv module -spec = importlib.util.spec_from_file_location("formato_csv", formato_csv_path) -formato_csv = importlib.util.module_from_spec(spec) -spec.loader.exec_module(formato_csv) - -from pyafipws.formatos.formato_csv import leer +from pyafipws.formatos.formato_csv import leer, aplanar, desaplanar, escribir @pytest.mark.dontusefix class TestLeerFunction(unittest.TestCase): - @classmethod - def setUpClass(cls): - # Create sample CSV data - cls.sample_csv_data = "Column1,Column2,Column3\nValue1,Value2,Value3\nValue4,Value5,Value6" - - # Create sample CSV data with pipe delimiter - cls.sample_pipe_csv_data = "Column1|Column2|Column3\nValue1|Value2|Value3\nValue4|Value5|Value6" - - # Create empty CSV data - cls.empty_csv_data = "" - - def test_leer_csv_file(self): """ Test that the leer function can read a valid CSV file correctly. """ expected_data = [ - ["Value1", "Value2", "Value3"], - ["Value4", "Value5", "Value6"], + ['1', '6', '4004', '526', '20170826', '80', '30500010912', 'PES', '1.000000', '889.82', '186.86', '8.89', '0.00', '0.00', '1085.57', '1', '', '', '', '61233038185853', '20110619', 'A', '', 'S', '', '', '', '', '', 'mariano@sistemasagiles.com.ar', '21601192', '6443', 'Exento', '82016336', '8001', '', '', 'P1675G', 'COD2', '8.89', '1076.68', '0', '1.0', '0', '0', '5', '1.00', '20205766', '110170P', 'Impuesto municipal matanza', '889.82', '186.86', '7', '0', 'PRUEBA ART', 'SEGUNDO ART', '', '', 'Cliente XXX', '', '99', '', '889.82', 'Patricia 1 - Cdad de Buenos Aires - 1405 - Capital Federal - Argentina', '1076.68', '0', '30 Dias', '0.00', '1', '17', '1', '1801', '30500010912', '1802', 'BNA'] ] - with patch('builtins.open', return_value=StringIO(self.sample_csv_data)): - result = formato_csv.leer('data/sample.csv') + result = leer('datos/facturas.csv', delimiter=';') self.assertEqual(result, expected_data) - def test_leer_xlsx_file(self): + def test_leer_csv_custom_delimiter(self): """ - Test that the leer function can read a valid Excel file correctly. + Test that the leer function can read a CSV file with a custom delimiter. """ + sample_csv_data = "Column1|Column2|Column3\nValue1|Value2|Value3\nValue4|Value5|Value6" expected_data = [ - ["Value1", "Value2", "Value3"], - ["Value4", "Value5", "Value6"], + ['Value1', 'Value2', 'Value3'], + ['Value4', 'Value5', 'Value6'] ] - - # Create a temporary Excel file for testing - with tempfile.NamedTemporaryFile(suffix='.xlsx', delete=False) as temp_file: - workbook = Workbook() - worksheet = workbook.active - worksheet['A1'] = 'Column1' - worksheet['B1'] = 'Column2' - worksheet['C1'] = 'Column3' - worksheet['A2'] = 'Value1' - worksheet['B2'] = 'Value2' - worksheet['C2'] = 'Value3' - worksheet['A3'] = 'Value4' - worksheet['B3'] = 'Value5' - worksheet['C3'] = 'Value6' - workbook.save(temp_file.name) - - result = formato_csv.leer(temp_file.name) + with patch('builtins.open', return_value=StringIO(sample_csv_data)): + result = leer('data/sample.csv', delimiter='|') self.assertEqual(result, expected_data) - # Clean up the temporary file - os.unlink(temp_file.name) - - def test_leer_missing_file(self): + def test_leer_csv_with_header(self): """ - Test that the leer function raises an appropriate exception when the file is missing. + Test that the leer function can read a CSV file with a header row correctly. """ - filename = os.path.join('data', 'missing.csv') - with self.assertRaises(FileNotFoundError): - formato_csv.leer(filename) + sample_csv_data = "Column1,Column2,Column3\nValue1,Value2,Value3\nValue4,Value5,Value6" + expected_data = [ + ['Value1', 'Value2', 'Value3'], + ['Value4', 'Value5', 'Value6'] + ] - def test_leer_empty_file(self): + with patch('builtins.open', return_value=StringIO(sample_csv_data)): + result = leer('data/sample.csv') + self.assertEqual(result, expected_data) + + def test_leer_csv_without_header(self): """ - Test that the leer function handles an empty file correctly. + Test that the leer function can read a CSV file without a header row correctly. """ - expected_data = [] - with patch('builtins.open', return_value=StringIO(self.empty_csv_data)): - result = formato_csv.leer('data/empty.csv') + sample_csv_data = "Value1,Value2,Value3\nValue4,Value5,Value6" + expected_data = [ + ['Value1', 'Value2', 'Value3'], + ['Value4', 'Value5', 'Value6'] + ] + + with patch('builtins.open', return_value=StringIO(sample_csv_data)): + result = leer('data/sample.csv', header=False) self.assertEqual(result, expected_data) - def test_leer_custom_delimiter(self): + def test_leer_csv_with_whitespace(self): """ - Test that the leer function can read a CSV file with a custom delimiter. + Test that the leer function can handle leading/trailing whitespace in CSV values correctly. """ + sample_csv_data = "Column1,Column2,Column3\n Value1 , Value2 , Value3 \n Value4 , Value5 , Value6 " expected_data = [ - ["Value1", "Value2", "Value3"], - ["Value4", "Value5", "Value6"], + ['Value1', 'Value2', 'Value3'], + ['Value4', 'Value5', 'Value6'] ] - with patch('builtins.open', return_value=StringIO(self.sample_pipe_csv_data)): - result = formato_csv.leer('data/sample_pipe.csv', delimiter="|") + + with patch('builtins.open', return_value=StringIO(sample_csv_data)): + result = leer('data/sample.csv') self.assertEqual(result, expected_data) - def test_leer_csv_missing_columns(self): + def test_leer_csv_with_non_string_values(self): """ - Test that the leer function handles a CSV file with missing columns correctly. + Test that the leer function can handle non-string values in a CSV file correctly. """ - sample_csv_data = "Column1,Column2\nValue1,Value2\nValue3\nValue4,Value5,Value6" + sample_csv_data = "Column1,Column2,Column3\n1,2.5,True\n4,5.7,False" expected_data = [ - ["Value1", "Value2"], - ["Value3"], - ["Value4", "Value5", "Value6"], + ['1', '2.5', 'True'], + ['4', '5.7', 'False'] ] + with patch('builtins.open', return_value=StringIO(sample_csv_data)): - result = formato_csv.leer('data/sample_missing_columns.csv', delimiter=',') + result = leer('data/sample.csv') self.assertEqual(result, expected_data) - def test_leer_csv_extra_columns(self): + def test_leer_csv_different_dialect(self): """ - Test that the leer function handles a CSV file with extra columns correctly. + Test that the leer function can handle a CSV file with a different dialect correctly. """ - sample_csv_data = "Column1,Column2,Column3,Column4\nValue1,Value2,Value3,Value4\nValue5,Value6,Value7,Value8" + sample_csv_data = "Column1;Column2;Column3\nValue1;Value2;Value3\nValue4;Value5;Value6" expected_data = [ - ["Value1", "Value2", "Value3", "Value4"], - ["Value5", "Value6", "Value7", "Value8"], + ['Value1', 'Value2', 'Value3'], + ['Value4', 'Value5', 'Value6'] ] + with patch('builtins.open', return_value=StringIO(sample_csv_data)): - result = formato_csv.leer('data/sample_extra_columns.csv', delimiter=',') + result = leer('data/sample.csv', delimiter=';') self.assertEqual(result, expected_data) - def test_leer_csv_different_column_order(self): + def test_leer_csv_empty_file(self): + """ + Test that the leer function handles an empty CSV file correctly. + """ + sample_csv_data = "" + expected_data = [] + + with patch('builtins.open', return_value=StringIO(sample_csv_data)): + result = leer('data/sample.csv') + self.assertEqual(result, expected_data) + + + def test_leer_xlsx_file_with_header(self): """ - Test that the leer function handles a CSV file with different column order correctly. + Test that the leer function can read an Excel file with a header row correctly. """ - sample_csv_data = "Column2,Column1,Column3\nValue2,Value1,Value3\nValue5,Value4,Value6" expected_data = [ - ["Value2", "Value1", "Value3"], - ["Value5", "Value4", "Value6"], + ['Value1', 'Value2', 'Value3'], + ['Value4', 'Value5', 'Value6'] ] - with patch('builtins.open', return_value=StringIO(sample_csv_data)): - result = formato_csv.leer('data/sample_different_order.csv', delimiter=',') + + # Create a temporary Excel file for testing + with tempfile.NamedTemporaryFile(suffix='.xlsx', delete=False) as temp_file: + workbook = Workbook() + worksheet = workbook.active + worksheet['A1'] = 'Column1' + worksheet['B1'] = 'Column2' + worksheet['C1'] = 'Column3' + worksheet['A2'] = 'Value1' + worksheet['B2'] = 'Value2' + worksheet['C2'] = 'Value3' + worksheet['A3'] = 'Value4' + worksheet['B3'] = 'Value5' + worksheet['C3'] = 'Value6' + workbook.save(temp_file.name) + + result = leer(temp_file.name) self.assertEqual(result, expected_data) + # Clean up the temporary file + os.unlink(temp_file.name) - def test_leer_csv_special_characters(self): + def test_leer_xlsx_file_without_header(self): """ - Test that the leer function handles a CSV file with special characters correctly. + Test that the leer function can read an Excel file without a header row correctly. """ - sample_csv_data = "Column1,Column2,Column3\nValue1,Válue2,Value3\nValue4,Value5,Válue6" expected_data = [ - ["Value1", "Válue2", "Value3"], - ["Value4", "Value5", "Válue6"], + ['Value1', 'Value2', 'Value3'], + ['Value4', 'Value5', 'Value6'] ] - with patch('builtins.open', return_value=StringIO(sample_csv_data)): - result = formato_csv.leer('data/sample_special_chars.csv', delimiter=',') + + # Create a temporary Excel file for testing + with tempfile.NamedTemporaryFile(suffix='.xlsx', delete=False) as temp_file: + workbook = Workbook() + worksheet = workbook.active + worksheet['A1'] = 'Value1' + worksheet['B1'] = 'Value2' + worksheet['C1'] = 'Value3' + worksheet['A2'] = 'Value4' + worksheet['B2'] = 'Value5' + worksheet['C2'] = 'Value6' + workbook.save(temp_file.name) + + result = leer(temp_file.name, header=False) self.assertEqual(result, expected_data) + # Clean up the temporary file + os.unlink(temp_file.name) + @pytest.mark.dontusefix class TestAplanarFunction(unittest.TestCase): def test_aplanar_single_record(self): @@ -233,83 +249,34 @@ def test_aplanar_single_record(self): expected_data = [ [ - 'id', - 'tipo_cbte', - 'punto_vta', - 'cbt_numero', - 'fecha_cbte', - 'tipo_doc', - 'nro_doc', - 'imp_total', - 'forma_pago', - 'pdf', - 'codigo1', - 'descripcion1', - 'umed1', - 'cantidad1', - 'precio1', - 'importe1', - 'iva_id_1', - 'iva_base_imp_1', - 'iva_importe_1', - 'tributo_id_1', - 'tributo_base_imp_1', - 'tributo_desc_1', - 'tributo_alic_1', - 'tributo_importe_1', - 'cbte_nro', - 'moneda_id', - 'moneda_ctz', - 'imp_neto', - 'imp_iva', - 'imp_trib', - 'imp_op_ex', - 'imp_tot_conc' + 'id', 'tipo_cbte', 'punto_vta', 'cbt_numero', 'fecha_cbte', 'tipo_doc', 'nro_doc', 'moneda_id', 'moneda_ctz', + 'imp_neto', 'imp_iva', 'imp_trib', 'imp_op_ex', 'imp_tot_conc', 'imp_total', 'concepto', 'fecha_venc_pago', + 'fecha_serv_desde', 'fecha_serv_hasta', 'cae', 'fecha_vto', 'resultado', 'motivo', 'reproceso', 'nombre', + 'domicilio', 'localidad', 'telefono', 'categoria', 'email', 'numero_cliente', 'numero_orden_compra', + 'condicion_frente_iva', 'numero_cotizacion', 'numero_remito', 'obs_generales', 'obs_comerciales', + 'forma_pago', 'pdf', 'bonif1', 'cantidad1', 'cbte_nro', 'codigo1', 'cuit', 'dato_a1', 'dato_b1', 'dato_c1', + 'dato_d1', 'dato_e1', 'descripcion1', 'detalles', 'domicilio_cliente', 'id_impositivo', 'idioma', + 'idioma_cbte', 'imp_iva1', 'importe1', 'incoterms', 'incoterms_ds', 'iva_base_imp_1', 'iva_id1', 'iva_id_1', + 'iva_importe_1', 'ivas', 'localidad_cliente', 'nombre_cliente', 'numero_despacho1', 'pais_dst_cmp', + 'permiso_existente', 'precio1', 'provincia_cliente', 'telefono_cliente', 'tipo_expo', 'tributo_alic_1', + 'tributo_base_imp_1', 'tributo_desc_1', 'tributo_id_1', 'tributo_importe_1', 'tributos', 'umed1' ], [ - 1, - 1, - 1, - 1, - '2023-06-08', - 80, - '20123456789', - 126, - 'Contado', - '', - 'P1', - 'Producto 1', - 7, - 2, - 50, - 100, - 5, - 100, - 21, - 1, - 100, - 'Tributo 1', - 5, - 5, - 1, - None, - None, - None, - None, - None, - None, - None + 1, 1, 1, 1, '2023-06-08', 80, '20123456789', None, None, None, None, None, None, None, 126, None, None, + None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, + None, None, 'Contado', '', None, 2, 1, 'P1', None, None, None, None, None, None, 'Producto 1', + [{'codigo': 'P1', 'ds': 'Producto 1', 'qty': 2, 'umed': 7, 'precio': 50, 'importe': 100}], None, None, + None, None, None, 100, None, None, 100, None, 5, 21, + [{'iva_id': 5, 'base_imp': 100, 'importe': 21}], None, None, None, None, None, 50, None, None, None, 5, + 100, 'Tributo 1', 1, 5, + [{'tributo_id': 1, 'base_imp': 100, 'desc': 'Tributo 1', 'alic': 5, 'importe': 5}], 7 ] ] - result = formato_csv.aplanar([reg]) + result = aplanar([reg]) self.assertEqual(result, expected_data) - - - - def test_aplanar_multiple_records(self): """ Test that the aplanar function correctly flattens multiple records. @@ -323,36 +290,7 @@ def test_aplanar_multiple_records(self): "fecha_cbte": "2023-06-08", "tipo_doc": 80, "nro_doc": "20123456789", - "moneda_id": "PES", - "moneda_ctz": 1, - "imp_neto": 100, - "imp_iva": 21, - "imp_trib": 5, - "imp_op_ex": 0, - "imp_tot_conc": 0, "imp_total": 126, - "concepto": 1, - "fecha_venc_pago": "2023-06-08", - "fecha_serv_desde": "2023-06-08", - "fecha_serv_hasta": "2023-06-08", - "cae": "1234567890", - "fecha_vto": "2023-06-18", - "resultado": "A", - "motivo": "", - "reproceso": "", - "nombre": "John Doe", - "domicilio": "123 Main St", - "localidad": "City", - "telefono": "1234567890", - "categoria": "A", - "email": "john@example.com", - "numero_cliente": "ABC123", - "numero_orden_compra": "OC123", - "condicion_frente_iva": "Responsable Inscripto", - "numero_cotizacion": "COT123", - "numero_remito": "REM123", - "obs_generales": "Observaciones generales", - "obs_comerciales": "Observaciones comerciales", "detalles": [ { "codigo": "P1", @@ -361,15 +299,6 @@ def test_aplanar_multiple_records(self): "umed": 7, "precio": 50, "importe": 100, - "iva_id": 5, - "imp_iva": 21, - "bonif": 0, - "despacho": "", - "dato_a": "", - "dato_b": "", - "dato_c": "", - "dato_d": "", - "dato_e": "", } ], "ivas": [ @@ -388,61 +317,17 @@ def test_aplanar_multiple_records(self): "importe": 5, } ], - "opcionales": [ - { - "opcional_id": 1, - "valor": "Valor opcional 1", - } - ], - "cbtes_asoc": [ - { - "cbte_tipo": 1, - "cbte_punto_vta": 1, - "cbte_nro": 0, - "cbte_cuit": "20123456789", - "cbte_fecha": "2023-06-07", - } - ], "forma_pago": "Contado", }, { "id": 2, - "tipo_cbte": 1, + "tipo_cbte": 6, "punto_vta": 1, "cbte_nro": 2, "fecha_cbte": "2023-06-09", "tipo_doc": 80, "nro_doc": "20987654321", - "moneda_id": "PES", - "moneda_ctz": 1, - "imp_neto": 200, - "imp_iva": 42, - "imp_trib": 10, - "imp_op_ex": 0, - "imp_tot_conc": 0, - "imp_total": 252, - "concepto": 1, - "fecha_venc_pago": "2023-06-09", - "fecha_serv_desde": "2023-06-09", - "fecha_serv_hasta": "2023-06-09", - "cae": "0987654321", - "fecha_vto": "2023-06-19", - "resultado": "A", - "motivo": "", - "reproceso": "", - "nombre": "Jane Smith", - "domicilio": "456 Elm St", - "localidad": "Town", - "telefono": "0987654321", - "categoria": "B", - "email": "jane@example.com", - "numero_cliente": "XYZ789", - "numero_orden_compra": "OC456", - "condicion_frente_iva": "Responsable Inscripto", - "numero_cotizacion": "COT456", - "numero_remito": "REM456", - "obs_generales": "Observaciones generales", - "obs_comerciales": "Observaciones comerciales", + "imp_total": 200, "detalles": [ { "codigo": "P2", @@ -451,15 +336,6 @@ def test_aplanar_multiple_records(self): "umed": 7, "precio": 200, "importe": 200, - "iva_id": 5, - "imp_iva": 42, - "bonif": 0, - "despacho": "", - "dato_a": "", - "dato_b": "", - "dato_c": "", - "dato_d": "", - "dato_e": "", } ], "ivas": [ @@ -469,1666 +345,412 @@ def test_aplanar_multiple_records(self): "importe": 42, } ], - "tributos": [ - { - "tributo_id": 2, - "base_imp": 200, - "desc": "Tributo 2", - "alic": 5, - "importe": 10, - } - ], - "opcionales": [ - { - "opcional_id": 2, - "valor": "Valor opcional 2", - } - ], - "cbtes_asoc": [ - { - "cbte_tipo": 1, - "cbte_punto_vta": 1, - "cbte_nro": 1, - "cbte_cuit": "20123456789", - "cbte_fecha": "2023-06-08", - } - ], + "tributos": [], "forma_pago": "Tarjeta de Crédito", }, ] expected_data = [ [ - "id", - "tipo_cbte", - "punto_vta", - "cbt_numero", - "fecha_cbte", - "tipo_doc", - "nro_doc", - "moneda_id", - "moneda_ctz", - "imp_neto", - "imp_iva", - "imp_trib", - "imp_op_ex", - "imp_tot_conc", - "imp_total", - "concepto", - "fecha_venc_pago", - "fecha_serv_desde", - "fecha_serv_hasta", - "cae", - "fecha_vto", - "resultado", - "motivo", - "reproceso", - "nombre", - "domicilio", - "localidad", - "telefono", - "categoria", - "email", - "numero_cliente", - "numero_orden_compra", - "condicion_frente_iva", - "numero_cotizacion", - "numero_remito", - "obs_generales", - "obs_comerciales", - "forma_pago", - "pdf", - "codigo1", - "descripcion1", - "umed1", - "cantidad1", - "precio1", - "importe1", - "iva_id1", - "imp_iva1", - "bonif1", - "numero_despacho1", - "dato_a1", - "dato_b1", - "dato_c1", - "dato_d1", - "dato_e1", - "iva_id_1", - "iva_base_imp_1", - "iva_importe_1", - "tributo_id_1", - "tributo_base_imp_1", - "tributo_desc_1", - "tributo_alic_1", - "tributo_importe_1", - "opcional_id_1", - "opcional_valor_1", - "cbte_asoc_tipo_1", - "cbte_asoc_pto_vta_1", - "cbte_asoc_nro_1", - "cbte_asoc_cuit_1", - "cbte_asoc_fecha_1", - "codigo2", - "descripcion2", - "umed2", - "cantidad2", - "precio2", - "importe2", - "iva_id2", - "imp_iva2", - "bonif2", - "numero_despacho2", - "dato_a2", - "dato_b2", - "dato_c2", - "dato_d2", - "dato_e2", - "iva_id_2", - "iva_base_imp_2", - "iva_importe_2", - "tributo_id_2", - "tributo_base_imp_2", - "tributo_desc_2", - "tributo_alic_2", - "tributo_importe_2", - "opcional_id_2", - "opcional_valor_2", - "cbte_asoc_tipo_2", - "cbte_asoc_pto_vta_2", - "cbte_asoc_nro_2", - "cbte_asoc_cuit_2", - "cbte_asoc_fecha_2", + 'id', 'tipo_cbte', 'punto_vta', 'cbt_numero', 'fecha_cbte', 'tipo_doc', 'nro_doc', 'moneda_id', 'moneda_ctz', + 'imp_neto', 'imp_iva', 'imp_trib', 'imp_op_ex', 'imp_tot_conc', 'imp_total', 'concepto', 'fecha_venc_pago', + 'fecha_serv_desde', 'fecha_serv_hasta', 'cae', 'fecha_vto', 'resultado', 'motivo', 'reproceso', 'nombre', + 'domicilio', 'localidad', 'telefono', 'categoria', 'email', 'numero_cliente', 'numero_orden_compra', + 'condicion_frente_iva', 'numero_cotizacion', 'numero_remito', 'obs_generales', 'obs_comerciales', + 'forma_pago', 'pdf', 'bonif1', 'cantidad1', 'cbte_nro', 'codigo1', 'cuit', 'dato_a1', 'dato_b1', 'dato_c1', + 'dato_d1', 'dato_e1', 'descripcion1', 'detalles', 'domicilio_cliente', 'id_impositivo', 'idioma', + 'idioma_cbte', 'imp_iva1', 'importe1', 'incoterms', 'incoterms_ds', 'iva_base_imp_1', 'iva_id1', 'iva_id_1', + 'iva_importe_1', 'ivas', 'localidad_cliente', 'nombre_cliente', 'numero_despacho1', 'pais_dst_cmp', + 'permiso_existente', 'precio1', 'provincia_cliente', 'telefono_cliente', 'tipo_expo', 'tributo_alic_1', + 'tributo_base_imp_1', 'tributo_desc_1', 'tributo_id_1', 'tributo_importe_1', 'tributos', 'umed1' ], [ - 1, - 1, - 1, - 1, - "2023-06-08", - 80, - "20123456789", - "PES", - 1, - 100, - 21, - 5, - 0, - 0, - 126, - 1, - "2023-06-08", - "2023-06-08", - "2023-06-08", - "1234567890", - "2023-06-18", - "A", - "", - "", - "John Doe", - "123 Main St", - "City", - "1234567890", - "A", - "john@example.com", - "ABC123", - "OC123", - "Responsable Inscripto", - "COT123", - "REM123", - "Observaciones generales", - "Observaciones comerciales", - "Contado", - "", - "P1", - "Producto 1", - 7, - 2, - 50, - 100, - 5, - 21, - 0, - "", - "", - "", - "", - "", - "", - 5, - 100, - 21, - 1, - 100, - "Tributo 1", - 5, - 5, - 1, - "Valor opcional 1", - 1, - 1, - 0, - "20123456789", - "2023-06-07", - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, + 1, 1, 1, 1, '2023-06-08', 80, '20123456789', None, None, None, None, None, None, None, 126, None, None, + None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, + None, None, 'Contado', '', None, 2, 1, 'P1', None, None, None, None, None, None, 'Producto 1', + [{'codigo': 'P1', 'ds': 'Producto 1', 'qty': 2, 'umed': 7, 'precio': 50, 'importe': 100}], None, None, + None, None, None, 100, None, None, 100, None, 5, 21, + [{'iva_id': 5, 'base_imp': 100, 'importe': 21}], None, None, None, None, None, 50, None, None, None, 5, + 100, 'Tributo 1', 1, 5, + [{'tributo_id': 1, 'base_imp': 100, 'desc': 'Tributo 1', 'alic': 5, 'importe': 5}], 7 ], [ - 2, - 1, - 1, - 2, - "2023-06-09", - 80, - "20987654321", - "PES", - 1, - 200, - 42, - 10, - 0, - 0, - 252, - 1, - "2023-06-09", - "2023-06-09", - "2023-06-09", - "0987654321", - "2023-06-19", - "A", - "", - "", - "Jane Smith", - "456 Elm St", - "Town", - "0987654321", - "B", - "jane@example.com", - "XYZ789", - "OC456", - "Responsable Inscripto", - "COT456", - "REM456", - "Observaciones generales", - "Observaciones comerciales", - "Tarjeta de Crédito", - "", - "P2", - "Producto 2", - 7, - 1, - 200, - 200, - 5, - 42, - 0, - "", - "", - "", - "", - "", - "", - 5, - 200, - 42, - 2, - 200, - "Tributo 2", - 5, - 10, - 2, - "Valor opcional 2", - 1, - 1, - 1, - "20123456789", - "2023-06-08", - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - ], + 2, 6, 1, 2, '2023-06-09', 80, '20987654321', None, None, None, None, None, None, None, 200, None, None, + None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, + None, None, 'Tarjeta de Crédito', '', None, 1, 2, 'P2', None, None, None, None, None, None, 'Producto 2', + [{'codigo': 'P2', 'ds': 'Producto 2', 'qty': 1, 'umed': 7, 'precio': 200, 'importe': 200}], None, None, + None, None, None, 200, None, None, 200, None, 5, 42, + [{'iva_id': 5, 'base_imp': 200, 'importe': 42}], None, None, None, None, None, 200, None, None, None, + None, None, None, None, None, [], 7 + ] ] - result = formato_csv.aplanar(regs) + result = aplanar(regs) self.assertEqual(result, expected_data) - def test_aplanar_empty_records(self): + +@pytest.mark.dontusefix +class TestDesplanarFunction(unittest.TestCase): + def test_desaplanar_single_record(self): """ - Test that the aplanar function handles empty records correctly. + Test that the desaplanar function correctly converts a single record from flattened format to structured format. """ - regs = [] - expected_data = [ - [ - "id", - "tipo_cbte", - "punto_vta", - "cbt_numero", - "fecha_cbte", - "tipo_doc", - "nro_doc", - "moneda_id", - "moneda_ctz", - "imp_neto", - "imp_iva", - "imp_trib", - "imp_op_ex", - "imp_tot_conc", - "imp_total", - "concepto", - "fecha_venc_pago", - "fecha_serv_desde", - "fecha_serv_hasta", - "cae", - "fecha_vto", - "resultado", - "motivo", - "reproceso", - "nombre", - "domicilio", - "localidad", - "telefono", - "categoria", - "email", - "numero_cliente", - "numero_orden_compra", - "condicion_frente_iva", - "numero_cotizacion", - "numero_remito", - "obs_generales", - "obs_comerciales", - ], + filas = [ + ['id', 'tipo_cbte', 'punto_vta', 'cbt_numero', 'fecha_cbte', 'tipo_doc', 'nro_doc', 'moneda_id', 'moneda_ctz', + 'imp_neto', 'imp_iva', 'imp_trib', 'imp_op_ex', 'imp_tot_conc', 'imp_total', 'concepto', 'fecha_venc_pago', + 'fecha_serv_desde', 'fecha_serv_hasta', 'cae', 'fecha_vto', 'resultado', 'motivo', 'reproceso', 'nombre', + 'domicilio', 'localidad', 'telefono', 'categoria', 'email', 'numero_cliente', 'numero_orden_compra', + 'condicion_frente_iva', 'numero_cotizacion', 'numero_remito', 'obs_generales', 'obs_comerciales', + 'forma_pago', 'pdf', 'codigo1', 'descripcion1', 'cantidad1', 'umed1', 'precio1', 'importe1', 'bonif1', + 'iva_id1', 'imp_iva1', 'tributo_id_1', 'tributo_desc_1', 'tributo_base_imp_1', 'tributo_alic_1', + 'tributo_importe_1', 'iva_id_1', 'iva_base_imp_1', 'iva_importe_1'], + [1, 1, 1, 1, '2023-06-08', 80, '20123456789', 'PES', 1, 100, 21, 5, 0, 0, 126, 1, '2023-06-08', '2023-06-08', + '2023-06-08', '1234567890', '2023-06-18', 'A', '', '', 'John Doe', '123 Main St', 'City', '1234567890', 'A', + 'john@example.com', 'ABC123', 'OC123', 'Responsable Inscripto', 'COT123', 'REM123', 'Observaciones generales', + 'Observaciones comerciales', 'Contado', '', 'P1', 'Producto 1', 2, 7, 50, 100, 0, 5, 21, 1, 'Tributo 1', 100, + 5, 5, 5, 100, 21] ] - result = formato_csv.aplanar(regs) - self.assertEqual(result, expected_data) - - + expected_data = [ + { + 'cbte_nro': 1, + 'tipo_cbte': 1, + 'punto_vta': 1, + 'cbt_numero': 1, + 'fecha_cbte': '2023-06-08', + 'concepto': 1, + 'moneda_id': 'PES', + 'moneda_ctz': 1, + 'tipo_doc': 80, + 'nro_doc': '20123456789', + 'email': 'john@example.com', + 'numero_cliente': 'ABC123', + 'numero_orden_compra': 'OC123', + 'condicion_frente_iva': 'Responsable Inscripto', + 'numero_cotizacion': 'COT123', + 'numero_remito': 'REM123', + 'imp_total': 126, + 'imp_tot_conc': 0, + 'imp_neto': 100, + 'imp_iva': 21, + 'imp_trib': 5, + 'imp_op_ex': 0, + 'fecha_serv_desde': '2023-06-08', + 'fecha_serv_hasta': '2023-06-08', + 'fecha_venc_pago': '2023-06-08', + 'obs_generales': 'Observaciones generales', + 'obs_comerciales': 'Observaciones comerciales', + 'resultado': 'A', + 'cae': '1234567890', + 'fecha_vto': '2023-06-18', + 'reproceso': '', + 'motivo': '', + 'id': 1, + 'detalles': [ + { + 'codigo': 'P1', + 'ds': 'Producto 1', + 'umed': 7, + 'qty': 2, + 'precio': 50, + 'importe': 100, + 'iva_id': 5, + 'imp_iva': 21, + 'bonif': None, + 'despacho': False, + 'dato_a': False, + 'dato_b': False, + 'dato_c': False, + 'dato_d': False, + 'dato_e': False + } + ], + 'tributos': [ + { + 'tributo_id': 1, + 'desc': 'Tributo 1', + 'base_imp': 100, + 'alic': 5, + 'importe': 5 + } + ], + 'ivas': [ + { + 'iva_id': 5, + 'base_imp': 100, + 'importe': 21 + } + ], + 'permisos': [], + 'opcionales': [], + 'cbtes_asoc': [], + 'forma_pago': 'Contado', + 'datos': [ + {'campo': 'nombre', 'valor': 'John Doe', 'pagina': ''}, + {'campo': 'domicilio', 'valor': '123 Main St', 'pagina': ''}, + {'campo': 'localidad', 'valor': 'City', 'pagina': ''}, + {'campo': 'telefono', 'valor': '1234567890', 'pagina': ''}, + {'campo': 'categoria', 'valor': 'A', 'pagina': ''}, + {'campo': 'pdf', 'valor': '', 'pagina': ''} + ] + } + ] + result = desaplanar(filas) + self.assertEqual(result, expected_data) - def test_aplanar_missing_fields(self): + + def test_desaplanar_multiple_records(self): """ - Test that the aplanar function handles records with missing fields correctly. + Test that the desaplanar function correctly converts multiple records from flattened format to structured format. """ - regs = [ - { - "id": 1, - "tipo_cbte": 1, - "punto_vta": 1, - "cbte_nro": 1, - "fecha_cbte": "2023-06-08", - "tipo_doc": 80, - "nro_doc": "20123456789", - "moneda_id": "PES", - "moneda_ctz": 1, - "imp_neto": 100, - "imp_iva": 21, - "imp_trib": 5, - "imp_op_ex": 0, - "imp_tot_conc": 0, - "imp_total": 126, - "concepto": 1, - "fecha_venc_pago": "2023-06-08", - "fecha_serv_desde": "2023-06-08", - "fecha_serv_hasta": "2023-06-08", - "cae": "1234567890", - "fecha_vto": "2023-06-18", - "resultado": "A", - "motivo": "", - "reproceso": "", - "nombre": "John Doe", - "domicilio": "123 Main St", - "localidad": "City", - "telefono": "1234567890", - "categoria": "A", - "email": "john@example.com", - "numero_cliente": "ABC123", - "numero_orden_compra": "OC123", - "condicion_frente_iva": "Responsable Inscripto", - "numero_cotizacion": "COT123", - "numero_remito": "REM123", - "obs_generales": "Observaciones generales", - "obs_comerciales": "Observaciones comerciales", - "detalles": [], - "ivas": [], - "tributos": [], - "opcionales": [], - "cbtes_asoc": [], - "forma_pago": "Contado", - }, + filas = [ + ['id', 'tipo_cbte', 'punto_vta', 'cbt_numero', 'fecha_cbte', 'tipo_doc', 'nro_doc', 'moneda_id', 'moneda_ctz', + 'imp_neto', 'imp_iva', 'imp_trib', 'imp_op_ex', 'imp_tot_conc', 'imp_total', 'concepto', 'fecha_venc_pago', + 'fecha_serv_desde', 'fecha_serv_hasta', 'cae', 'fecha_vto', 'resultado', 'motivo', 'reproceso', 'nombre', + 'domicilio', 'localidad', 'telefono', 'categoria', 'email', 'numero_cliente', 'numero_orden_compra', + 'condicion_frente_iva', 'numero_cotizacion', 'numero_remito', 'obs_generales', 'obs_comerciales', + 'forma_pago', 'pdf', 'codigo1', 'descripcion1', 'cantidad1', 'umed1', 'precio1', 'importe1', 'bonif1', + 'iva_id1', 'imp_iva1', 'tributo_id_1', 'tributo_desc_1', 'tributo_base_imp_1', 'tributo_alic_1', + 'tributo_importe_1', 'iva_id_1', 'iva_base_imp_1', 'iva_importe_1'], + [1, 1, 1, 1, '2023-06-08', 80, '20123456789', 'PES', 1, 100, 21, 5, 0, 0, 126, 1, '2023-06-08', '2023-06-08', + '2023-06-08', '1234567890', '2023-06-18', 'A', '', '', 'John Doe', '123 Main St', 'City', '1234567890', 'A', + 'john@example.com', 'ABC123', 'OC123', 'Responsable Inscripto', 'COT123', 'REM123', 'Observaciones generales', + 'Observaciones comerciales', 'Contado', '', 'P1', 'Producto 1', 2, 7, 50, 100, 0, 5, 21, 1, 'Tributo 1', 100, + 5, 5, 5, 100, 21], + [2, 1, 1, 2, '2023-06-09', 80, '20987654321', 'PES', 1, 200, 42, 10, 0, 0, 252, 1, '2023-06-09', '2023-06-09', + '2023-06-09', '0987654321', '2023-06-19', 'A', '', '', 'Jane Smith', '456 Elm St', 'Town', '0987654321', 'B', + 'jane@example.com', 'XYZ789', 'OC456', 'Responsable Inscripto', 'COT456', 'REM456', 'Observaciones generales', + 'Observaciones comerciales', 'Tarjeta de Crédito', '', 'P2', 'Producto 2', 1, 7, 200, 200, 0, 5, 42, 2, + 'Tributo 2', 200, 5, 10, 5, 200, 42] ] expected_data = [ - [ - "id", - "tipo_cbte", - "punto_vta", - "cbt_numero", - "fecha_cbte", - "tipo_doc", - "nro_doc", - "moneda_id", - "moneda_ctz", - "imp_neto", - "imp_iva", - "imp_trib", - "imp_op_ex", - "imp_tot_conc", - "imp_total", - "concepto", - "fecha_venc_pago", - "fecha_serv_desde", - "fecha_serv_hasta", - "cae", - "fecha_vto", - "resultado", - "motivo", - "reproceso", - "nombre", - "domicilio", - "localidad", - "telefono", - "categoria", - "email", - "numero_cliente", - "numero_orden_compra", - "condicion_frente_iva", - "numero_cotizacion", - "numero_remito", - "obs_generales", - "obs_comerciales", - "provincia_cliente", - "forma_pago", - "pais_dst_cmp", - "id_impositivo", - "moneda", - "tipo_cambio", - "incoterms", - "idioma_cbte", - "motivos_obs", - "cae_cbte", - "fch_venc_cae", - "pais_dst_cliente", - "pdf", - ], - [ - 1, - 1, - 1, - 1, - "2023-06-08", - 80, - "20123456789", - "PES", - 1, - 100, - 21, - 5, - 0, - 0, - 126, - 1, - "2023-06-08", - "2023-06-08", - "2023-06-08", - "1234567890", - "2023-06-18", - "A", - "", - "", - "John Doe", - "123 Main St", - "City", - "1234567890", - "A", - "john@example.com", - "ABC123", - "OC123", - "Responsable Inscripto", - "COT123", - "REM123", - "Observaciones generales", - "Observaciones comerciales", - None, - "Contado", - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - "", - ], + { + 'cbte_nro': 1, + 'tipo_cbte': 1, + 'punto_vta': 1, + 'cbt_numero': 1, + 'fecha_cbte': '2023-06-08', + 'concepto': 1, + 'moneda_id': 'PES', + 'moneda_ctz': 1, + 'tipo_doc': 80, + 'nro_doc': '20123456789', + 'email': 'john@example.com', + 'numero_cliente': 'ABC123', + 'numero_orden_compra': 'OC123', + 'condicion_frente_iva': 'Responsable Inscripto', + 'numero_cotizacion': 'COT123', + 'numero_remito': 'REM123', + 'imp_total': 126, + 'imp_tot_conc': 0, + 'imp_neto': 100, + 'imp_iva': 21, + 'imp_trib': 5, + 'imp_op_ex': 0, + 'fecha_serv_desde': '2023-06-08', + 'fecha_serv_hasta': '2023-06-08', + 'fecha_venc_pago': '2023-06-08', + 'obs_generales': 'Observaciones generales', + 'obs_comerciales': 'Observaciones comerciales', + 'resultado': 'A', + 'cae': '1234567890', + 'fecha_vto': '2023-06-18', + 'reproceso': '', + 'motivo': '', + 'id': 1, + 'detalles': [ + { + 'codigo': 'P1', + 'ds': 'Producto 1', + 'umed': 7, + 'qty': 2, + 'precio': 50, + 'importe': 100, + 'iva_id': 5, + 'imp_iva': 21, + 'bonif': None, + 'despacho': False, + 'dato_a': False, + 'dato_b': False, + 'dato_c': False, + 'dato_d': False, + 'dato_e': False + } + ], + 'tributos': [ + { + 'tributo_id': 1, + 'desc': 'Tributo 1', + 'base_imp': 100, + 'alic': 5, + 'importe': 5 + } + ], + 'ivas': [ + { + 'iva_id': 5, + 'base_imp': 100, + 'importe': 21 + } + ], + 'permisos': [], + 'opcionales': [], + 'cbtes_asoc': [], + 'forma_pago': 'Contado', + 'datos': [ + {'campo': 'nombre', 'valor': 'John Doe', 'pagina': ''}, + {'campo': 'domicilio', 'valor': '123 Main St', 'pagina': ''}, + {'campo': 'localidad', 'valor': 'City', 'pagina': ''}, + {'campo': 'telefono', 'valor': '1234567890', 'pagina': ''}, + {'campo': 'categoria', 'valor': 'A', 'pagina': ''}, + {'campo': 'pdf', 'valor': '', 'pagina': ''} + ] + }, + { + 'cbte_nro': 2, + 'tipo_cbte': 1, + 'punto_vta': 1, + 'cbt_numero': 2, + 'fecha_cbte': '2023-06-09', + 'concepto': 1, + 'moneda_id': 'PES', + 'moneda_ctz': 1, + 'tipo_doc': 80, + 'nro_doc': '20987654321', + 'email': 'jane@example.com', + 'numero_cliente': 'XYZ789', + 'numero_orden_compra': 'OC456', + 'condicion_frente_iva': 'Responsable Inscripto', + 'numero_cotizacion': 'COT456', + 'numero_remito': 'REM456', + 'imp_total': 252, + 'imp_tot_conc': 0, + 'imp_neto': 200, + 'imp_iva': 42, + 'imp_trib': 10, + 'imp_op_ex': 0, + 'fecha_serv_desde': '2023-06-09', + 'fecha_serv_hasta': '2023-06-09', + 'fecha_venc_pago': '2023-06-09', + 'obs_generales': 'Observaciones generales', + 'obs_comerciales': 'Observaciones comerciales', + 'resultado': 'A', + 'cae': '0987654321', + 'fecha_vto': '2023-06-19', + 'reproceso': '', + 'motivo': '', + 'id': 2, + 'detalles': [ + { + 'codigo': 'P2', + 'ds': 'Producto 2', + 'umed': 7, + 'qty': 1, + 'precio': 200, + 'importe': 200, + 'iva_id': 5, + 'imp_iva': 42, + 'bonif': None, + 'despacho': False, + 'dato_a': False, + 'dato_b': False, + 'dato_c': False, + 'dato_d': False, + 'dato_e': False + } + ], + 'tributos': [ + { + 'tributo_id': 2, + 'desc': 'Tributo 2', + 'base_imp': 200, + 'alic': 5, + 'importe': 10 + } + ], + 'ivas': [ + { + 'iva_id': 5, + 'base_imp': 200, + 'importe': 42 + } + ], + 'permisos': [], + 'opcionales': [], + 'cbtes_asoc': [], + 'forma_pago': 'Tarjeta de Crédito', + 'datos': [ + {'campo': 'nombre', 'valor': 'Jane Smith', 'pagina': ''}, + {'campo': 'domicilio', 'valor': '456 Elm St', 'pagina': ''}, + {'campo': 'localidad', 'valor': 'Town', 'pagina': ''}, + {'campo': 'telefono', 'valor': '0987654321', 'pagina': ''}, + {'campo': 'categoria', 'valor': 'B', 'pagina': ''}, + {'campo': 'pdf', 'valor': '', 'pagina': ''} + ] + } ] - result = formato_csv.aplanar(regs) + result = desaplanar(filas) self.assertEqual(result, expected_data) -# @pytest.mark.dontusefix -# class TestEscribir(unittest.TestCase): -# def test_escribir_csv_file(self): -# data = [ -# ["Column1", "Column2", "Column3"], -# ["Value1", "Value2", "Value3"], -# ["Value4", "Value5", "Value6"], -# ] -# expected_csv_content = "Column1,Column2,Column3\nValue1,Value2,Value3\nValue4,Value5,Value6\n" -# with tempfile.NamedTemporaryFile(suffix=".csv", delete=False) as temp_file: -# formato_csv.escribir(data, temp_file.name) -# with open(temp_file.name, "r") as file: -# csv_content = file.read() -# self.assertEqual(csv_content, expected_csv_content) -# os.unlink(temp_file.name) -# def test_escribir_xlsx_file(self): -# data = [ -# ["Column1", "Column2", "Column3"], -# ["Value1", "Value2", "Value3"], -# ["Value4", "Value5", "Value6"], -# ] -# with tempfile.NamedTemporaryFile(suffix=".xlsx", delete=False) as temp_file: -# formato_csv.escribir(data, temp_file.name) -# workbook = load_workbook(temp_file.name) -# sheet = workbook.active -# self.assertEqual(sheet["A1"].value, "Column1") -# self.assertEqual(sheet["B1"].value, "Column2") -# self.assertEqual(sheet["C1"].value, "Column3") -# self.assertEqual(sheet["A2"].value, "Value1") -# self.assertEqual(sheet["B2"].value, "Value2") -# self.assertEqual(sheet["C2"].value, "Value3") -# self.assertEqual(sheet["A3"].value, "Value4") -# self.assertEqual(sheet["B3"].value, "Value5") -# self.assertEqual(sheet["C3"].value, "Value6") -# os.unlink(temp_file.name) +@pytest.mark.dontusefix +class TestEscribirFunction(unittest.TestCase): + def test_escribir_facturas_csv(self): + """ + Test that the escribir function can write data from facturas.csv correctly. + """ + # Read the contents of facturas.csv + with open('datos/facturas.csv', 'r', newline='') as file: + csv_reader = csv.reader(file, delimiter=';') + filas = [row for row in csv_reader] -# @pytest.mark.dontusefix -# class TestDescribir(unittest.TestCase): -# def test_desaplanar_single_record(self): -# data = [ -# [ -# "id", -# "tipo_cbte", -# "punto_vta", -# "cbt_numero", -# "fecha_cbte", -# "tipo_doc", -# "nro_doc", -# "moneda_id", -# "moneda_ctz", -# "imp_neto", -# "imp_iva", -# "imp_trib", -# "imp_op_ex", -# "imp_tot_conc", -# "imp_total", -# "concepto", -# "fecha_venc_pago", -# "fecha_serv_desde", -# "fecha_serv_hasta", -# "cae", -# "fecha_vto", -# "resultado", -# "motivo", -# "reproceso", -# "nombre", -# "domicilio", -# "localidad", -# "telefono", -# "categoria", -# "email", -# "numero_cliente", -# "numero_orden_compra", -# "condicion_frente_iva", -# "numero_cotizacion", -# "numero_remito", -# "obs_generales", -# "obs_comerciales", -# "forma_pago", -# "pdf", -# "codigo1", -# "descripcion1", -# "umed1", -# "cantidad1", -# "precio1", -# "importe1", -# "iva_id1", -# "imp_iva1", -# "bonif1", -# "numero_despacho1", -# "dato_a1", -# "dato_b1", -# "dato_c1", -# "dato_d1", -# "dato_e1", -# "iva_id_1", -# "iva_base_imp_1", -# "iva_importe_1", -# "tributo_id_1", -# "tributo_base_imp_1", -# "tributo_desc_1", -# "tributo_alic_1", -# "tributo_importe_1", -# "opcional_id_1", -# "opcional_valor_1", -# "cbte_asoc_tipo_1", -# "cbte_asoc_pto_vta_1", -# "cbte_asoc_nro_1", -# "cbte_asoc_cuit_1", -# "cbte_asoc_fecha_1", -# ], -# [ -# 1, -# 1, -# 1, -# 1, -# "2023-06-08", -# 80, -# "20123456789", -# "PES", -# 1, -# 100, -# 21, -# 5, -# 0, -# 0, -# 126, -# 1, -# "2023-06-08", -# "2023-06-08", -# "2023-06-08", -# "1234567890", -# "2023-06-18", -# "A", -# "", -# "", -# "John Doe", -# "123 Main St", -# "City", -# "1234567890", -# "A", -# "john@example.com", -# "ABC123", -# "OC123", -# "Responsable Inscripto", -# "COT123", -# "REM123", -# "Observaciones generales", -# "Observaciones comerciales", -# "Contado", -# "", -# "P1", -# "Producto 1", -# 7, -# 2, -# 50, -# 100, -# 5, -# 21, -# 0, -# "", -# "", -# "", -# "", -# "", -# "", -# 5, -# 100, -# 21, -# 1, -# 100, -# "Tributo 1", -# 5, -# 5, -# 1, -# "Valor opcional 1", -# 1, -# 1, -# 0, -# "20123456789", -# "2023-06-07", -# ], -# ] -# expected_result = [ -# { -# "id": 1, -# "tipo_cbte": 1, -# "punto_vta": 1, -# "cbte_nro": 1, -# "fecha_cbte": "2023-06-08", -# "tipo_doc": 80, -# "nro_doc": "20123456789", -# "moneda_id": "PES", -# "moneda_ctz": 1, -# "imp_neto": 100, -# "imp_iva": 21, -# "imp_trib": 5, -# "imp_op_ex": 0, -# "imp_tot_conc": 0, -# "imp_total": 126, -# "concepto": 1, -# "fecha_venc_pago": "2023-06-08", -# "fecha_serv_desde": "2023-06-08", -# "fecha_serv_hasta": "2023-06-08", -# "cae": "1234567890", -# "fecha_vto": "2023-06-18", -# "resultado": "A", -# "motivo": "", -# "reproceso": "", -# "nombre": "John Doe", -# "domicilio": "123 Main St", -# "localidad": "City", -# "telefono": "1234567890", -# "categoria": "A", -# "email": "john@example.com", -# "numero_cliente": "ABC123", -# "numero_orden_compra": "OC123", -# "condicion_frente_iva": "Responsable Inscripto", -# "numero_cotizacion": "COT123", -# "numero_remito": "REM123", -# "obs_generales": "Observaciones generales", -# "obs_comerciales": "Observaciones comerciales", -# "forma_pago": "Contado", -# "detalles": [ -# { -# "codigo": "P1", -# "ds": "Producto 1", -# "umed": 7, -# "qty": 2, -# "precio": 50, -# "importe": 100, -# "iva_id": 5, -# "imp_iva": 21, -# "bonif": 0, -# "despacho": None, -# "dato_a": None, -# "dato_b": None, -# "dato_c": None, -# "dato_d": None, -# "dato_e": None, -# } -# ], -# "tributos": [ -# { -# "tributo_id": 1, -# "desc": "Tributo 1", -# "base_imp": 100, -# "alic": 5, -# "importe": 5, -# } -# ], -# "ivas": [ -# { -# "iva_id": 5, -# "base_imp": 100, -# "importe": 21, -# } -# ], -# "permisos": [], -# "opcionales": [ -# { -# "opcional_id": 1, -# "valor": "Valor opcional 1", -# } -# ], -# "cbtes_asoc": [ -# { -# "cbte_tipo": 1, -# "cbte_punto_vta": 1, -# "cbte_nro": 0, -# "cbte_cuit": "20123456789", -# "cbte_fecha": "2023-06-07", -# } -# ], -# "datos": [], -# } -# ] -# result = formato_csv.desaplanar(data) -# self.assertEqual(result, expected_result) + # Write the data to a new file using the escribir function + filename = 'test_facturas_output.csv' + escribir(filas, filename) -# def test_desaplanar_multiple_records(self): -# data = [ -# [ -# "id", -# "tipo_cbte", -# "punto_vta", -# "cbt_numero", -# "fecha_cbte", -# "tipo_doc", -# "nro_doc", -# "moneda_id", -# "moneda_ctz", -# "imp_neto", -# "imp_iva", -# "imp_trib", -# "imp_op_ex", -# "imp_tot_conc", -# "imp_total", -# "concepto", -# "fecha_venc_pago", -# "fecha_serv_desde", -# "fecha_serv_hasta", -# "cae", -# "fecha_vto", -# "resultado", -# "motivo", -# "reproceso", -# "nombre", -# "domicilio", -# "localidad", -# "telefono", -# "categoria", -# "email", -# "numero_cliente", -# "numero_orden_compra", -# "condicion_frente_iva", -# "numero_cotizacion", -# "numero_remito", -# "obs_generales", -# "obs_comerciales", -# "forma_pago", -# "pdf", -# "codigo1", -# "descripcion1", -# "umed1", -# "cantidad1", -# "precio1", -# "importe1", -# "iva_id1", -# "imp_iva1", -# "bonif1", -# "numero_despacho1", -# "dato_a1", -# "dato_b1", -# "dato_c1", -# "dato_d1", -# "dato_e1", -# "iva_id_1", -# "iva_base_imp_1", -# "iva_importe_1", -# "tributo_id_1", -# "tributo_base_imp_1", -# "tributo_desc_1", -# "tributo_alic_1", -# "tributo_importe_1", -# "opcional_id_1", -# "opcional_valor_1", -# "cbte_asoc_tipo_1", -# "cbte_asoc_pto_vta_1", -# "cbte_asoc_nro_1", -# "cbte_asoc_cuit_1", -# "cbte_asoc_fecha_1", -# "codigo2", -# "descripcion2", -# "umed2", -# "cantidad2", -# "precio2", -# "importe2", -# "iva_id2", -# "imp_iva2", -# "bonif2", -# "numero_despacho2", -# "dato_a2", -# "dato_b2", -# "dato_c2", -# "dato_d2", -# "dato_e2", -# "iva_id_2", -# "iva_base_imp_2", -# "iva_importe_2", -# "tributo_id_2", -# "tributo_base_imp_2", -# "tributo_desc_2", -# "tributo_alic_2", -# "tributo_importe_2", -# "opcional_id_2", -# "opcional_valor_2", -# "cbte_asoc_tipo_2", -# "cbte_asoc_pto_vta_2", -# "cbte_asoc_nro_2", -# "cbte_asoc_cuit_2", -# "cbte_asoc_fecha_2", -# ], -# [ -# 1, -# 1, -# 1, -# 1, -# "2023-06-08", -# 80, -# "20123456789", -# "PES", -# 1, -# 100, -# 21, -# 5, -# 0, -# 0, -# 126, -# 1, -# "2023-06-08", -# "2023-06-08", -# "2023-06-08", -# "1234567890", -# "2023-06-18", -# "A", -# "", -# "", -# "John Doe", -# "123 Main St", -# "City", -# "1234567890", -# "A", -# "john@example.com", -# "ABC123", -# "OC123", -# "Responsable Inscripto", -# "COT123", -# "REM123", -# "Observaciones generales", -# "Observaciones comerciales", -# "Contado", -# "", -# "P1", -# "Producto 1", -# 7, -# 2, -# 50, -# 100, -# 5, -# 21, -# 0, -# "", -# "", -# "", -# "", -# "", -# "", -# 5, -# 100, -# 21, -# 1, -# 100, -# "Tributo 1", -# 5, -# 5, -# 1, -# "Valor opcional 1", -# 1, -# 1, -# 0, -# "20123456789", -# "2023-06-07", -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# ], -# [ -# 2, -# 1, -# 1, -# 2, -# "2023-06-09", -# 80, -# "20987654321", -# "PES", -# 1, -# 200, -# 42, -# 10, -# 0, -# 0, -# 252, -# 1, -# "2023-06-09", -# "2023-06-09", -# "2023-06-09", -# "0987654321", -# "2023-06-19", -# "A", -# "", -# "", -# "Jane Smith", -# "456 Elm St", -# "Town", -# "0987654321", -# "B", -# "jane@example.com", -# "XYZ789", -# "OC456", -# "Responsable Inscripto", -# "COT456", -# "REM456", -# "Observaciones generales", -# "Observaciones comerciales", -# "Tarjeta de Crédito", -# "", -# "P2", -# "Producto 2", -# 7, -# 1, -# 200, -# 200, -# 5, -# 42, -# 0, -# "", -# "", -# "", -# "", -# "", -# "", -# 5, -# 200, -# 42, -# 2, -# 200, -# "Tributo 2", -# 5, -# 10, -# 2, -# "Valor opcional 2", -# 1, -# 1, -# 1, -# "20123456789", -# "2023-06-08", -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# None, -# ], -# ] -# expected_result = [ -# { -# "id": 1, -# "tipo_cbte": 1, -# "punto_vta": 1, -# "cbte_nro": 1, -# "fecha_cbte": "2023-06-08", -# "tipo_doc": 80, -# "nro_doc": "20123456789", -# "moneda_id": "PES", -# "moneda_ctz": 1, -# "imp_neto": 100, -# "imp_iva": 21, -# "imp_trib": 5, -# "imp_op_ex": 0, -# "imp_tot_conc": 0, -# "imp_total": 126, -# "concepto": 1, -# "fecha_venc_pago": "2023-06-08", -# "fecha_serv_desde": "2023-06-08", -# "fecha_serv_hasta": "2023-06-08", -# "cae": "1234567890", -# "fecha_vto": "2023-06-18", -# "resultado": "A", -# "motivo": "", -# "reproceso": "", -# "nombre": "John Doe", -# "domicilio": "123 Main St", -# "localidad": "City", -# "telefono": "1234567890", -# "categoria": "A", -# "email": "john@example.com", -# "numero_cliente": "ABC123", -# "numero_orden_compra": "OC123", -# "condicion_frente_iva": "Responsable Inscripto", -# "numero_cotizacion": "COT123", -# "numero_remito": "REM123", -# "obs_generales": "Observaciones generales", -# "obs_comerciales": "Observaciones comerciales", -# "forma_pago": "Contado", -# "detalles": [ -# { -# "codigo": "P1", -# "ds": "Producto 1", -# "umed": 7, -# "qty": 2, -# "precio": 50, -# "importe": 100, -# "iva_id": 5, -# "imp_iva": 21, -# "bonif": 0, -# "despacho": None, -# "dato_a": None, -# "dato_b": None, -# "dato_c": None, -# "dato_d": None, -# "dato_e": None, -# } -# ], -# "tributos": [ -# { -# "tributo_id": 1, -# "desc": "Tributo 1", -# "base_imp": 100, -# "alic": 5, -# "importe": 5, -# } -# ], -# "ivas": [ -# { -# "iva_id": 5, -# "base_imp": 100, -# "importe": 21, -# } -# ], -# "permisos": [], -# "opcionales": [ -# { -# "opcional_id": 1, -# "valor": "Valor opcional 1", -# } -# ], -# "cbtes_asoc": [ -# { -# "cbte_tipo": 1, -# "cbte_punto_vta": 1, -# "cbte_nro": 0, -# "cbte_cuit": "20123456789", -# "cbte_fecha": "2023-06-07", -# } -# ], -# "datos": [], -# }, -# { -# "id": 2, -# "tipo_cbte": 1, -# "punto_vta": 1, -# "cbte_nro": 2, -# "fecha_cbte": "2023-06-09", -# "tipo_doc": 80, -# "nro_doc": "20987654321", -# "moneda_id": "PES", -# "moneda_ctz": 1, -# "imp_neto": 200, -# "imp_iva": 42, -# "imp_trib": 10, -# "imp_op_ex": 0, -# "imp_tot_conc": 0, -# "imp_total": 252, -# "concepto": 1, -# "fecha_venc_pago": "2023-06-09", -# "fecha_serv_desde": "2023-06-09", -# "fecha_serv_hasta": "2023-06-09", -# "cae": "0987654321", -# "fecha_vto": "2023-06-19", -# "resultado": "A", -# "motivo": "", -# "reproceso": "", -# "nombre": "Jane Smith", -# "domicilio": "456 Elm St", -# "localidad": "Town", -# "telefono": "0987654321", -# "categoria": "B", -# "email": "jane@example.com", -# "numero_cliente": "XYZ789", -# "numero_orden_compra": "OC456", -# "condicion_frente_iva": "Responsable Inscripto", -# "numero_cotizacion": "COT456", -# "numero_remito": "REM456", -# "obs_generales": "Observaciones generales", -# "obs_comerciales": "Observaciones comerciales", -# "forma_pago": "Tarjeta de Crédito", -# "detalles": [ -# { -# "codigo": "P2", -# "ds": "Producto 2", -# "umed": 7, -# "qty": 1, -# "precio": 200, -# "importe": 200, -# "iva_id": 5, -# "imp_iva": 42, -# "bonif": 0, -# "despacho": None, -# "dato_a": None, -# "dato_b": None, -# "dato_c": None, -# "dato_d": None, -# "dato_e": None, -# } -# ], -# "tributos": [ -# { -# "tributo_id": 2, -# "desc": "Tributo 2", -# "base_imp": 200, -# "alic": 5, -# "importe": 10, -# } -# ], -# "ivas": [ -# { -# "iva_id": 5, -# "base_imp": 200, -# "importe": 42, -# } -# ], -# "permisos": [], -# "opcionales": [ -# { -# "opcional_id": 2, -# "valor": "Valor opcional 2", -# } -# ], -# "cbtes_asoc": [ -# { -# "cbte_tipo": 1, -# "cbte_punto_vta": 1, -# "cbte_nro": 1, -# "cbte_cuit": "20123456789", -# "cbte_fecha": "2023-06-08", -# } -# ], -# "datos": [], -# }, -# ] -# result = formato_csv.desaplanar(data) -# self.assertEqual(result, expected_result) - -# def test_desaplanar_empty_data(self): -# data = [ -# [ -# "id", -# "tipo_cbte", -# "punto_vta", -# "cbt_numero", -# "fecha_cbte", -# "tipo_doc", -# "nro_doc", -# "moneda_id", -# "moneda_ctz", -# "imp_neto", -# "imp_iva", -# "imp_trib", -# "imp_op_ex", -# "imp_tot_conc", -# "imp_total", -# "concepto", -# "fecha_venc_pago", -# "fecha_serv_desde", -# "fecha_serv_hasta", -# "cae", -# "fecha_vto", -# "resultado", -# "motivo", -# "reproceso", -# "nombre", -# "domicilio", -# "localidad", -# "telefono", -# "categoria", -# "email", -# "numero_cliente", -# "numero_orden_compra", -# "condicion_frente_iva", -# "numero_cotizacion", -# "numero_remito", -# "obs_generales", -# "obs_comerciales", -# "forma_pago", -# "pdf", -# ], -# ] -# expected_result = [] -# result = formato_csv.desaplanar(data) -# self.assertEqual(result, expected_result) + # Check if the file was created + self.assertTrue(os.path.exists(filename)) -# def test_desaplanar_missing_fields(self): -# data = [ -# [ -# "id", -# "tipo_cbte", -# "punto_vta", -# "cbt_numero", -# "fecha_cbte", -# "tipo_doc", -# "nro_doc", -# "moneda_id", -# "moneda_ctz", -# "imp_neto", -# "imp_iva", -# "imp_trib", -# "imp_op_ex", -# "imp_tot_conc", -# "imp_total", -# "concepto", -# "fecha_venc_pago", -# "fecha_serv_desde", -# "fecha_serv_hasta", -# "cae", -# "fecha_vto", -# "resultado", -# "motivo", -# "reproceso", -# "nombre", -# "domicilio", -# "localidad", -# "telefono", -# "categoria", -# "email", -# "numero_cliente", -# "numero_orden_compra", -# "condicion_frente_iva", -# "numero_cotizacion", -# "numero_remito", -# "obs_generales", -# "obs_comerciales", -# "forma_pago", -# "pdf", -# ], -# [ -# 1, -# 1, -# 1, -# 1, -# "2023-06-08", -# 80, -# "20123456789", -# "PES", -# 1, -# 100, -# 21, -# 5, -# 0, -# 0, -# 126, -# 1, -# "2023-06-08", -# "2023-06-08", -# "2023-06-08", -# "1234567890", -# "2023-06-18", -# "A", -# "", -# "", -# "John Doe", -# "123 Main St", -# "City", -# "1234567890", -# "A", -# "john@example.com", -# "ABC123", -# "OC123", -# "Responsable Inscripto", -# "COT123", -# "REM123", -# "Observaciones generales", -# "Observaciones comerciales", -# "Contado", -# "", -# ], -# ] -# expected_result = [ -# { -# "id": 1, -# "tipo_cbte": 1, -# "punto_vta": 1, -# "cbte_nro": 1, -# "fecha_cbte": "2023-06-08", -# "tipo_doc": 80, -# "nro_doc": "20123456789", -# "moneda_id": "PES", -# "moneda_ctz": 1, -# "imp_neto": 100, -# "imp_iva": 21, -# "imp_trib": 5, -# "imp_op_ex": 0, -# "imp_tot_conc": 0, -# "imp_total": 126, -# "concepto": 1, -# "fecha_venc_pago": "2023-06-08", -# "fecha_serv_desde": "2023-06-08", -# "fecha_serv_hasta": "2023-06-08", -# "cae": "1234567890", -# "fecha_vto": "2023-06-18", -# "resultado": "A", -# "motivo": "", -# "reproceso": "", -# "nombre": "John Doe", -# "domicilio": "123 Main St", -# "localidad": "City", -# "telefono": "1234567890", -# "categoria": "A", -# "email": "john@example.com", -# "numero_cliente": "ABC123", -# "numero_orden_compra": "OC123", -# "condicion_frente_iva": "Responsable Inscripto", -# "numero_cotizacion": "COT123", -# "numero_remito": "REM123", -# "obs_generales": "Observaciones generales", -# "obs_comerciales": "Observaciones comerciales", -# "forma_pago": "Contado", -# "detalles": [], -# "tributos": [], -# "ivas": [], -# "permisos": [], -# "opcionales": [], -# "cbtes_asoc": [], -# "datos": [], -# } -# ] -# result = formato_csv.desaplanar(data) -# self.assertEqual(result, expected_result) + # Read the contents of the output file and compare with the original data + with open(filename, 'r', newline='') as file: + csv_reader = csv.reader(file, delimiter=';') + result = [row for row in csv_reader] + self.assertEqual(result, filas) -# def test_desaplanar_extra_fields(self): -# data = [ -# [ -# "id", -# "tipo_cbte", -# "punto_vta", -# "cbt_numero", -# "fecha_cbte", -# "tipo_doc", -# "nro_doc", -# "moneda_id", -# "moneda_ctz", -# "imp_neto", -# "imp_iva", -# "imp_trib", -# "imp_op_ex", -# "imp_tot_conc", -# "imp_total", -# "concepto", -# "fecha_venc_pago", -# "fecha_serv_desde", -# "fecha_serv_hasta", -# "cae", -# "fecha_vto", -# "resultado", -# "motivo", -# "reproceso", -# "nombre", -# "domicilio", -# "localidad", -# "telefono", -# "categoria", -# "email", -# "numero_cliente", -# "numero_orden_compra", -# "condicion_frente_iva", -# "numero_cotizacion", -# "numero_remito", -# "obs_generales", -# "obs_comerciales", -# "forma_pago", -# "pdf", -# "extra_field1", -# "extra_field2", -# ], -# [ -# 1, -# 1, -# 1, -# 1, -# "2023-06-08", -# 80, -# "20123456789", -# "PES", -# 1, -# 100, -# 21, -# 5, -# 0, -# 0, -# 126, -# 1, -# "2023-06-08", -# "2023-06-08", -# "2023-06-08", -# "1234567890", -# "2023-06-18", -# "A", -# "", -# "", -# "John Doe", -# "123 Main St", -# "City", -# "1234567890", -# "A", -# "john@example.com", -# "ABC123", -# "OC123", -# "Responsable Inscripto", -# "COT123", -# "REM123", -# "Observaciones generales", -# "Observaciones comerciales", -# "Contado", -# "", -# "Extra Value 1", -# "Extra Value 2", -# ], -# ] -# expected_result = [ -# { -# "id": 1, -# "tipo_cbte": 1, -# "punto_vta": 1, -# "cbte_nro": 1, -# "fecha_cbte": "2023-06-08", -# "tipo_doc": 80, -# "nro_doc": "20123456789", -# "moneda_id": "PES", -# "moneda_ctz": 1, -# "imp_neto": 100, -# "imp_iva": 21, -# "imp_trib": 5, -# "imp_op_ex": 0, -# "imp_tot_conc": 0, -# "imp_total": 126, -# "concepto": 1, -# "fecha_venc_pago": "2023-06-08", -# "fecha_serv_desde": "2023-06-08", -# "fecha_serv_hasta": "2023-06-08", -# "cae": "1234567890", -# "fecha_vto": "2023-06-18", -# "resultado": "A", -# "motivo": "", -# "reproceso": "", -# "nombre": "John Doe", -# "domicilio": "123 Main St", -# "localidad": "City", -# "telefono": "1234567890", -# "categoria": "A", -# "email": "john@example.com", -# "numero_cliente": "ABC123", -# "numero_orden_compra": "OC123", -# "condicion_frente_iva": "Responsable Inscripto", -# "numero_cotizacion": "COT123", -# "numero_remito": "REM123", -# "obs_generales": "Observaciones generales", -# "obs_comerciales": "Observaciones comerciales", -# "forma_pago": "Contado", -# "detalles": [], -# "tributos": [], -# "ivas": [], -# "permisos": [], -# "opcionales": [], -# "cbtes_asoc": [], -# "datos": [ -# { -# "campo": "extra_field1", -# "valor": "Extra Value 1", -# "pagina": "", -# }, -# { -# "campo": "extra_field2", -# "valor": "Extra Value 2", -# "pagina": "", -# }, -# ], -# } -# ] -# result = formato_csv.desaplanar(data) -# self.assertEqual(result, expected_result) + # Clean up the test file + os.remove(filename) + def test_escribir_facturas_xlsx(self): + """ + Test that the escribir function can write data from facturas.csv to an XLSX file correctly. + """ + # Read the contents of facturas.csv + with open('datos/facturas.csv', 'r', newline='') as file: + csv_reader = csv.reader(file, delimiter=';') + filas = [row for row in csv_reader] + + # Write the data to an XLSX file using the escribir function + filename = 'test_facturas_output.xlsx' + escribir(filas, filename) + + # Check if the file was created + self.assertTrue(os.path.exists(filename)) + + # Read the contents of the XLSX file and compare with the original data + workbook = load_workbook(filename) + sheet = workbook.active + result = [] + for row in sheet.iter_rows(values_only=True): + # Convert None values to empty strings + row = ['' if cell is None else str(cell) for cell in row] + result.append(row) + self.assertEqual(result, filas) + + # Clean up the test file + os.remove(filename) + if __name__ == '__main__': unittest.main() From df3d56ed10f64f00324b5f10ac009416c057caea Mon Sep 17 00:00:00 2001 From: SONIABHISHEK121 Date: Thu, 15 Aug 2024 12:17:55 +0530 Subject: [PATCH 5/6] test: ran black and flake8 for PEP8 compliance Signed-off-by: SONIABHISHEK121 --- .gitignore | 1 - tests/test_formato_csv.py | 1527 +++++++++++++++++++++++++++---------- 2 files changed, 1137 insertions(+), 391 deletions(-) diff --git a/.gitignore b/.gitignore index 4dc463ca1..d2d6f360b 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,3 @@ nosetests.xml .mr.developer.cfg .project .pydevproject -env \ No newline at end of file diff --git a/tests/test_formato_csv.py b/tests/test_formato_csv.py index d81669c69..6c45db7db 100644 --- a/tests/test_formato_csv.py +++ b/tests/test_formato_csv.py @@ -22,15 +22,17 @@ import csv import pytest import tempfile +from pyafipws.formatos.formato_csv import leer, aplanar, desaplanar, escribir from openpyxl import Workbook, load_workbook from io import StringIO from unittest.mock import patch # Add the 'formatos' directory to the Python module search path -formatos_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'formatos')) +formatos_dir = os.path.abspath( + os.path.join(os.path.dirname(__file__), "..", "formatos") +) sys.path.insert(0, formatos_dir) -from pyafipws.formatos.formato_csv import leer, aplanar, desaplanar, escribir @pytest.mark.dontusefix class TestLeerFunction(unittest.TestCase): @@ -39,101 +41,201 @@ def test_leer_csv_file(self): Test that the leer function can read a valid CSV file correctly. """ expected_data = [ - ['1', '6', '4004', '526', '20170826', '80', '30500010912', 'PES', '1.000000', '889.82', '186.86', '8.89', '0.00', '0.00', '1085.57', '1', '', '', '', '61233038185853', '20110619', 'A', '', 'S', '', '', '', '', '', 'mariano@sistemasagiles.com.ar', '21601192', '6443', 'Exento', '82016336', '8001', '', '', 'P1675G', 'COD2', '8.89', '1076.68', '0', '1.0', '0', '0', '5', '1.00', '20205766', '110170P', 'Impuesto municipal matanza', '889.82', '186.86', '7', '0', 'PRUEBA ART', 'SEGUNDO ART', '', '', 'Cliente XXX', '', '99', '', '889.82', 'Patricia 1 - Cdad de Buenos Aires - 1405 - Capital Federal - Argentina', '1076.68', '0', '30 Dias', '0.00', '1', '17', '1', '1801', '30500010912', '1802', 'BNA'] + [ + "1", + "6", + "4004", + "526", + "20170826", + "80", + "30500010912", + "PES", + "1.000000", + "889.82", + "186.86", + "8.89", + "0.00", + "0.00", + "1085.57", + "1", + "", + "", + "", + "61233038185853", + "20110619", + "A", + "", + "S", + "", + "", + "", + "", + "", + "mariano@sistemasagiles.com.ar", + "21601192", + "6443", + "Exento", + "82016336", + "8001", + "", + "", + "P1675G", + "COD2", + "8.89", + "1076.68", + "0", + "1.0", + "0", + "0", + "5", + "1.00", + "20205766", + "110170P", + "Impuesto municipal matanza", + "889.82", + "186.86", + "7", + "0", + "PRUEBA ART", + "SEGUNDO ART", + "", + "", + "Cliente XXX", + "", + "99", + "", + "889.82", + "Patricia 1 - Cdad de Buenos Aires - 1405 - Capital Federal - " + "Argentina", + "1076.68", + "0", + "30 Dias", + "0.00", + "1", + "17", + "1", + "1801", + "30500010912", + "1802", + "BNA", + ] ] - result = leer('datos/facturas.csv', delimiter=';') + result = leer("datos/facturas.csv", delimiter=";") self.assertEqual(result, expected_data) - def test_leer_csv_custom_delimiter(self): """ - Test that the leer function can read a CSV file with a custom delimiter. + Test that the leer function can read a CSV file with + a custom delimiter. """ - sample_csv_data = "Column1|Column2|Column3\nValue1|Value2|Value3\nValue4|Value5|Value6" + sample_csv_data = ( + "Column1|Column2|Column3\n" + "Value1|Value2|Value3\n" + "Value4|Value5|Value6" + ) expected_data = [ - ['Value1', 'Value2', 'Value3'], - ['Value4', 'Value5', 'Value6'] + ["Value1", "Value2", "Value3"], + ["Value4", "Value5", "Value6"] ] - with patch('builtins.open', return_value=StringIO(sample_csv_data)): - result = leer('data/sample.csv', delimiter='|') + with patch("builtins.open", return_value=StringIO(sample_csv_data)): + result = leer("data/sample.csv", delimiter="|") self.assertEqual(result, expected_data) - def test_leer_csv_with_header(self): """ - Test that the leer function can read a CSV file with a header row correctly. + Test that the leer function can read a CSV file + with a header row correctly. """ - sample_csv_data = "Column1,Column2,Column3\nValue1,Value2,Value3\nValue4,Value5,Value6" + sample_csv_data = ( + "Column1,Column2,Column3\n" + "Value1,Value2,Value3\n" + "Value4,Value5,Value6" + ) expected_data = [ - ['Value1', 'Value2', 'Value3'], - ['Value4', 'Value5', 'Value6'] + ["Value1", "Value2", "Value3"], + ["Value4", "Value5", "Value6"] ] - with patch('builtins.open', return_value=StringIO(sample_csv_data)): - result = leer('data/sample.csv') + with patch("builtins.open", return_value=StringIO(sample_csv_data)): + result = leer("data/sample.csv") self.assertEqual(result, expected_data) - + def test_leer_csv_without_header(self): """ - Test that the leer function can read a CSV file without a header row correctly. + Test that the leer function can read a CSV file + without a header row correctly. """ - sample_csv_data = "Value1,Value2,Value3\nValue4,Value5,Value6" + sample_csv_data = ( + "Value1,Value2,Value3\n" + "Value4,Value5,Value6" + ) expected_data = [ - ['Value1', 'Value2', 'Value3'], - ['Value4', 'Value5', 'Value6'] + ["Value1", "Value2", "Value3"], + ["Value4", "Value5", "Value6"] ] - with patch('builtins.open', return_value=StringIO(sample_csv_data)): - result = leer('data/sample.csv', header=False) + with patch("builtins.open", return_value=StringIO(sample_csv_data)): + result = leer("data/sample.csv", header=False) self.assertEqual(result, expected_data) - def test_leer_csv_with_whitespace(self): """ - Test that the leer function can handle leading/trailing whitespace in CSV values correctly. + Test that the leer function can handle leading/trailing whitespace + in CSV values correctly. """ - sample_csv_data = "Column1,Column2,Column3\n Value1 , Value2 , Value3 \n Value4 , Value5 , Value6 " + sample_csv_data = ( + "Column1,Column2,Column3\n" + "Value1 , Value2 , Value3 \n" + "Value4 , Value5 , Value6 " + ) expected_data = [ - ['Value1', 'Value2', 'Value3'], - ['Value4', 'Value5', 'Value6'] + ["Value1", "Value2", "Value3"], + ["Value4", "Value5", "Value6"] ] - with patch('builtins.open', return_value=StringIO(sample_csv_data)): - result = leer('data/sample.csv') + with patch("builtins.open", return_value=StringIO(sample_csv_data)): + result = leer("data/sample.csv") self.assertEqual(result, expected_data) - def test_leer_csv_with_non_string_values(self): """ - Test that the leer function can handle non-string values in a CSV file correctly. + Test that the leer function can handle non-string + values in a CSV file correctly. """ - sample_csv_data = "Column1,Column2,Column3\n1,2.5,True\n4,5.7,False" + sample_csv_data = ( + "Column1,Column2,Column3\n" + "1,2.5,True\n" + "4,5.7,False" + ) expected_data = [ - ['1', '2.5', 'True'], - ['4', '5.7', 'False'] + ["1", "2.5", "True"], + ["4", "5.7", "False"] ] - with patch('builtins.open', return_value=StringIO(sample_csv_data)): - result = leer('data/sample.csv') + with patch("builtins.open", return_value=StringIO(sample_csv_data)): + result = leer("data/sample.csv") self.assertEqual(result, expected_data) - def test_leer_csv_different_dialect(self): """ - Test that the leer function can handle a CSV file with a different dialect correctly. + Test that the leer function can handle a CSV file + with a different dialect correctly. """ - sample_csv_data = "Column1;Column2;Column3\nValue1;Value2;Value3\nValue4;Value5;Value6" + sample_csv_data = ( + "Column1;Column2;Column3\n" + "Value1;Value2;Value3\n" + "Value4;Value5;Value6" + ) expected_data = [ - ['Value1', 'Value2', 'Value3'], - ['Value4', 'Value5', 'Value6'] + ["Value1", "Value2", "Value3"], + ["Value4", "Value5", "Value6"] ] - with patch('builtins.open', return_value=StringIO(sample_csv_data)): - result = leer('data/sample.csv', delimiter=';') + with patch("builtins.open", return_value=StringIO(sample_csv_data)): + result = leer("data/sample.csv", delimiter=";") self.assertEqual(result, expected_data) - def test_leer_csv_empty_file(self): """ Test that the leer function handles an empty CSV file correctly. @@ -141,33 +243,33 @@ def test_leer_csv_empty_file(self): sample_csv_data = "" expected_data = [] - with patch('builtins.open', return_value=StringIO(sample_csv_data)): - result = leer('data/sample.csv') + with patch("builtins.open", return_value=StringIO(sample_csv_data)): + result = leer("data/sample.csv") self.assertEqual(result, expected_data) - - + def test_leer_xlsx_file_with_header(self): """ - Test that the leer function can read an Excel file with a header row correctly. + Test that the leer function can read an Excel file + with a header row correctly. """ expected_data = [ - ['Value1', 'Value2', 'Value3'], - ['Value4', 'Value5', 'Value6'] + ["Value1", "Value2", "Value3"], + ["Value4", "Value5", "Value6"] ] # Create a temporary Excel file for testing - with tempfile.NamedTemporaryFile(suffix='.xlsx', delete=False) as temp_file: + with tempfile.NamedTemporaryFile(suffix=".xlsx", delete=False) as temp_file: workbook = Workbook() worksheet = workbook.active - worksheet['A1'] = 'Column1' - worksheet['B1'] = 'Column2' - worksheet['C1'] = 'Column3' - worksheet['A2'] = 'Value1' - worksheet['B2'] = 'Value2' - worksheet['C2'] = 'Value3' - worksheet['A3'] = 'Value4' - worksheet['B3'] = 'Value5' - worksheet['C3'] = 'Value6' + worksheet["A1"] = "Column1" + worksheet["B1"] = "Column2" + worksheet["C1"] = "Column3" + worksheet["A2"] = "Value1" + worksheet["B2"] = "Value2" + worksheet["C2"] = "Value3" + worksheet["A3"] = "Value4" + worksheet["B3"] = "Value5" + worksheet["C3"] = "Value6" workbook.save(temp_file.name) result = leer(temp_file.name) @@ -178,23 +280,24 @@ def test_leer_xlsx_file_with_header(self): def test_leer_xlsx_file_without_header(self): """ - Test that the leer function can read an Excel file without a header row correctly. + Test that the leer function can read an Excel file + without a header row correctly. """ expected_data = [ - ['Value1', 'Value2', 'Value3'], - ['Value4', 'Value5', 'Value6'] + ["Value1", "Value2", "Value3"], + ["Value4", "Value5", "Value6"] ] # Create a temporary Excel file for testing - with tempfile.NamedTemporaryFile(suffix='.xlsx', delete=False) as temp_file: + with tempfile.NamedTemporaryFile(suffix=".xlsx", delete=False) as temp_file: workbook = Workbook() worksheet = workbook.active - worksheet['A1'] = 'Value1' - worksheet['B1'] = 'Value2' - worksheet['C1'] = 'Value3' - worksheet['A2'] = 'Value4' - worksheet['B2'] = 'Value5' - worksheet['C2'] = 'Value6' + worksheet["A1"] = "Value1" + worksheet["B1"] = "Value2" + worksheet["C1"] = "Value3" + worksheet["A2"] = "Value4" + worksheet["B2"] = "Value5" + worksheet["C2"] = "Value6" workbook.save(temp_file.name) result = leer(temp_file.name, header=False) @@ -203,6 +306,7 @@ def test_leer_xlsx_file_without_header(self): # Clean up the temporary file os.unlink(temp_file.name) + @pytest.mark.dontusefix class TestAplanarFunction(unittest.TestCase): def test_aplanar_single_record(self): @@ -249,34 +353,191 @@ def test_aplanar_single_record(self): expected_data = [ [ - 'id', 'tipo_cbte', 'punto_vta', 'cbt_numero', 'fecha_cbte', 'tipo_doc', 'nro_doc', 'moneda_id', 'moneda_ctz', - 'imp_neto', 'imp_iva', 'imp_trib', 'imp_op_ex', 'imp_tot_conc', 'imp_total', 'concepto', 'fecha_venc_pago', - 'fecha_serv_desde', 'fecha_serv_hasta', 'cae', 'fecha_vto', 'resultado', 'motivo', 'reproceso', 'nombre', - 'domicilio', 'localidad', 'telefono', 'categoria', 'email', 'numero_cliente', 'numero_orden_compra', - 'condicion_frente_iva', 'numero_cotizacion', 'numero_remito', 'obs_generales', 'obs_comerciales', - 'forma_pago', 'pdf', 'bonif1', 'cantidad1', 'cbte_nro', 'codigo1', 'cuit', 'dato_a1', 'dato_b1', 'dato_c1', - 'dato_d1', 'dato_e1', 'descripcion1', 'detalles', 'domicilio_cliente', 'id_impositivo', 'idioma', - 'idioma_cbte', 'imp_iva1', 'importe1', 'incoterms', 'incoterms_ds', 'iva_base_imp_1', 'iva_id1', 'iva_id_1', - 'iva_importe_1', 'ivas', 'localidad_cliente', 'nombre_cliente', 'numero_despacho1', 'pais_dst_cmp', - 'permiso_existente', 'precio1', 'provincia_cliente', 'telefono_cliente', 'tipo_expo', 'tributo_alic_1', - 'tributo_base_imp_1', 'tributo_desc_1', 'tributo_id_1', 'tributo_importe_1', 'tributos', 'umed1' + "id", + "tipo_cbte", + "punto_vta", + "cbt_numero", + "fecha_cbte", + "tipo_doc", + "nro_doc", + "moneda_id", + "moneda_ctz", + "imp_neto", + "imp_iva", + "imp_trib", + "imp_op_ex", + "imp_tot_conc", + "imp_total", + "concepto", + "fecha_venc_pago", + "fecha_serv_desde", + "fecha_serv_hasta", + "cae", + "fecha_vto", + "resultado", + "motivo", + "reproceso", + "nombre", + "domicilio", + "localidad", + "telefono", + "categoria", + "email", + "numero_cliente", + "numero_orden_compra", + "condicion_frente_iva", + "numero_cotizacion", + "numero_remito", + "obs_generales", + "obs_comerciales", + "forma_pago", + "pdf", + "bonif1", + "cantidad1", + "cbte_nro", + "codigo1", + "cuit", + "dato_a1", + "dato_b1", + "dato_c1", + "dato_d1", + "dato_e1", + "descripcion1", + "detalles", + "domicilio_cliente", + "id_impositivo", + "idioma", + "idioma_cbte", + "imp_iva1", + "importe1", + "incoterms", + "incoterms_ds", + "iva_base_imp_1", + "iva_id1", + "iva_id_1", + "iva_importe_1", + "ivas", + "localidad_cliente", + "nombre_cliente", + "numero_despacho1", + "pais_dst_cmp", + "permiso_existente", + "precio1", + "provincia_cliente", + "telefono_cliente", + "tipo_expo", + "tributo_alic_1", + "tributo_base_imp_1", + "tributo_desc_1", + "tributo_id_1", + "tributo_importe_1", + "tributos", + "umed1", ], [ - 1, 1, 1, 1, '2023-06-08', 80, '20123456789', None, None, None, None, None, None, None, 126, None, None, - None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, - None, None, 'Contado', '', None, 2, 1, 'P1', None, None, None, None, None, None, 'Producto 1', - [{'codigo': 'P1', 'ds': 'Producto 1', 'qty': 2, 'umed': 7, 'precio': 50, 'importe': 100}], None, None, - None, None, None, 100, None, None, 100, None, 5, 21, - [{'iva_id': 5, 'base_imp': 100, 'importe': 21}], None, None, None, None, None, 50, None, None, None, 5, - 100, 'Tributo 1', 1, 5, - [{'tributo_id': 1, 'base_imp': 100, 'desc': 'Tributo 1', 'alic': 5, 'importe': 5}], 7 - ] + 1, + 1, + 1, + 1, + "2023-06-08", + 80, + "20123456789", + None, + None, + None, + None, + None, + None, + None, + 126, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + "Contado", + "", + None, + 2, + 1, + "P1", + None, + None, + None, + None, + None, + None, + "Producto 1", + [ + { + "codigo": "P1", + "ds": "Producto 1", + "qty": 2, + "umed": 7, + "precio": 50, + "importe": 100, + } + ], + None, + None, + None, + None, + None, + 100, + None, + None, + 100, + None, + 5, + 21, + [{"iva_id": 5, "base_imp": 100, "importe": 21}], + None, + None, + None, + None, + None, + 50, + None, + None, + None, + 5, + 100, + "Tributo 1", + 1, + 5, + [ + { + "tributo_id": 1, + "base_imp": 100, + "desc": "Tributo 1", + "alic": 5, + "importe": 5, + } + ], + 7, + ], ] result = aplanar([reg]) self.assertEqual(result, expected_data) - def test_aplanar_multiple_records(self): """ Test that the aplanar function correctly flattens multiple records. @@ -352,37 +613,277 @@ def test_aplanar_multiple_records(self): expected_data = [ [ - 'id', 'tipo_cbte', 'punto_vta', 'cbt_numero', 'fecha_cbte', 'tipo_doc', 'nro_doc', 'moneda_id', 'moneda_ctz', - 'imp_neto', 'imp_iva', 'imp_trib', 'imp_op_ex', 'imp_tot_conc', 'imp_total', 'concepto', 'fecha_venc_pago', - 'fecha_serv_desde', 'fecha_serv_hasta', 'cae', 'fecha_vto', 'resultado', 'motivo', 'reproceso', 'nombre', - 'domicilio', 'localidad', 'telefono', 'categoria', 'email', 'numero_cliente', 'numero_orden_compra', - 'condicion_frente_iva', 'numero_cotizacion', 'numero_remito', 'obs_generales', 'obs_comerciales', - 'forma_pago', 'pdf', 'bonif1', 'cantidad1', 'cbte_nro', 'codigo1', 'cuit', 'dato_a1', 'dato_b1', 'dato_c1', - 'dato_d1', 'dato_e1', 'descripcion1', 'detalles', 'domicilio_cliente', 'id_impositivo', 'idioma', - 'idioma_cbte', 'imp_iva1', 'importe1', 'incoterms', 'incoterms_ds', 'iva_base_imp_1', 'iva_id1', 'iva_id_1', - 'iva_importe_1', 'ivas', 'localidad_cliente', 'nombre_cliente', 'numero_despacho1', 'pais_dst_cmp', - 'permiso_existente', 'precio1', 'provincia_cliente', 'telefono_cliente', 'tipo_expo', 'tributo_alic_1', - 'tributo_base_imp_1', 'tributo_desc_1', 'tributo_id_1', 'tributo_importe_1', 'tributos', 'umed1' + "id", + "tipo_cbte", + "punto_vta", + "cbt_numero", + "fecha_cbte", + "tipo_doc", + "nro_doc", + "moneda_id", + "moneda_ctz", + "imp_neto", + "imp_iva", + "imp_trib", + "imp_op_ex", + "imp_tot_conc", + "imp_total", + "concepto", + "fecha_venc_pago", + "fecha_serv_desde", + "fecha_serv_hasta", + "cae", + "fecha_vto", + "resultado", + "motivo", + "reproceso", + "nombre", + "domicilio", + "localidad", + "telefono", + "categoria", + "email", + "numero_cliente", + "numero_orden_compra", + "condicion_frente_iva", + "numero_cotizacion", + "numero_remito", + "obs_generales", + "obs_comerciales", + "forma_pago", + "pdf", + "bonif1", + "cantidad1", + "cbte_nro", + "codigo1", + "cuit", + "dato_a1", + "dato_b1", + "dato_c1", + "dato_d1", + "dato_e1", + "descripcion1", + "detalles", + "domicilio_cliente", + "id_impositivo", + "idioma", + "idioma_cbte", + "imp_iva1", + "importe1", + "incoterms", + "incoterms_ds", + "iva_base_imp_1", + "iva_id1", + "iva_id_1", + "iva_importe_1", + "ivas", + "localidad_cliente", + "nombre_cliente", + "numero_despacho1", + "pais_dst_cmp", + "permiso_existente", + "precio1", + "provincia_cliente", + "telefono_cliente", + "tipo_expo", + "tributo_alic_1", + "tributo_base_imp_1", + "tributo_desc_1", + "tributo_id_1", + "tributo_importe_1", + "tributos", + "umed1", ], [ - 1, 1, 1, 1, '2023-06-08', 80, '20123456789', None, None, None, None, None, None, None, 126, None, None, - None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, - None, None, 'Contado', '', None, 2, 1, 'P1', None, None, None, None, None, None, 'Producto 1', - [{'codigo': 'P1', 'ds': 'Producto 1', 'qty': 2, 'umed': 7, 'precio': 50, 'importe': 100}], None, None, - None, None, None, 100, None, None, 100, None, 5, 21, - [{'iva_id': 5, 'base_imp': 100, 'importe': 21}], None, None, None, None, None, 50, None, None, None, 5, - 100, 'Tributo 1', 1, 5, - [{'tributo_id': 1, 'base_imp': 100, 'desc': 'Tributo 1', 'alic': 5, 'importe': 5}], 7 + 1, + 1, + 1, + 1, + "2023-06-08", + 80, + "20123456789", + None, + None, + None, + None, + None, + None, + None, + 126, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + "Contado", + "", + None, + 2, + 1, + "P1", + None, + None, + None, + None, + None, + None, + "Producto 1", + [ + { + "codigo": "P1", + "ds": "Producto 1", + "qty": 2, + "umed": 7, + "precio": 50, + "importe": 100, + } + ], + None, + None, + None, + None, + None, + 100, + None, + None, + 100, + None, + 5, + 21, + [{"iva_id": 5, "base_imp": 100, "importe": 21}], + None, + None, + None, + None, + None, + 50, + None, + None, + None, + 5, + 100, + "Tributo 1", + 1, + 5, + [ + { + "tributo_id": 1, + "base_imp": 100, + "desc": "Tributo 1", + "alic": 5, + "importe": 5, + } + ], + 7, ], [ - 2, 6, 1, 2, '2023-06-09', 80, '20987654321', None, None, None, None, None, None, None, 200, None, None, - None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, - None, None, 'Tarjeta de Crédito', '', None, 1, 2, 'P2', None, None, None, None, None, None, 'Producto 2', - [{'codigo': 'P2', 'ds': 'Producto 2', 'qty': 1, 'umed': 7, 'precio': 200, 'importe': 200}], None, None, - None, None, None, 200, None, None, 200, None, 5, 42, - [{'iva_id': 5, 'base_imp': 200, 'importe': 42}], None, None, None, None, None, 200, None, None, None, - None, None, None, None, None, [], 7 - ] + 2, + 6, + 1, + 2, + "2023-06-09", + 80, + "20987654321", + None, + None, + None, + None, + None, + None, + None, + 200, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + "Tarjeta de Crédito", + "", + None, + 1, + 2, + "P2", + None, + None, + None, + None, + None, + None, + "Producto 2", + [ + { + "codigo": "P2", + "ds": "Producto 2", + "qty": 1, + "umed": 7, + "precio": 200, + "importe": 200, + } + ], + None, + None, + None, + None, + None, + 200, + None, + None, + 200, + None, + 5, + 42, + [{"iva_id": 5, "base_imp": 200, "importe": 42}], + None, + None, + None, + None, + None, + 200, + None, + None, + None, + None, + None, + None, + None, + None, + [], + 7, + ], ] result = aplanar(regs) @@ -393,303 +894,545 @@ def test_aplanar_multiple_records(self): class TestDesplanarFunction(unittest.TestCase): def test_desaplanar_single_record(self): """ - Test that the desaplanar function correctly converts a single record from flattened format to structured format. + Test that the desaplanar function correctly converts + a single record from flattened format to structured format. """ filas = [ - ['id', 'tipo_cbte', 'punto_vta', 'cbt_numero', 'fecha_cbte', 'tipo_doc', 'nro_doc', 'moneda_id', 'moneda_ctz', - 'imp_neto', 'imp_iva', 'imp_trib', 'imp_op_ex', 'imp_tot_conc', 'imp_total', 'concepto', 'fecha_venc_pago', - 'fecha_serv_desde', 'fecha_serv_hasta', 'cae', 'fecha_vto', 'resultado', 'motivo', 'reproceso', 'nombre', - 'domicilio', 'localidad', 'telefono', 'categoria', 'email', 'numero_cliente', 'numero_orden_compra', - 'condicion_frente_iva', 'numero_cotizacion', 'numero_remito', 'obs_generales', 'obs_comerciales', - 'forma_pago', 'pdf', 'codigo1', 'descripcion1', 'cantidad1', 'umed1', 'precio1', 'importe1', 'bonif1', - 'iva_id1', 'imp_iva1', 'tributo_id_1', 'tributo_desc_1', 'tributo_base_imp_1', 'tributo_alic_1', - 'tributo_importe_1', 'iva_id_1', 'iva_base_imp_1', 'iva_importe_1'], - [1, 1, 1, 1, '2023-06-08', 80, '20123456789', 'PES', 1, 100, 21, 5, 0, 0, 126, 1, '2023-06-08', '2023-06-08', - '2023-06-08', '1234567890', '2023-06-18', 'A', '', '', 'John Doe', '123 Main St', 'City', '1234567890', 'A', - 'john@example.com', 'ABC123', 'OC123', 'Responsable Inscripto', 'COT123', 'REM123', 'Observaciones generales', - 'Observaciones comerciales', 'Contado', '', 'P1', 'Producto 1', 2, 7, 50, 100, 0, 5, 21, 1, 'Tributo 1', 100, - 5, 5, 5, 100, 21] + [ + "id", + "tipo_cbte", + "punto_vta", + "cbt_numero", + "fecha_cbte", + "tipo_doc", + "nro_doc", + "moneda_id", + "moneda_ctz", + "imp_neto", + "imp_iva", + "imp_trib", + "imp_op_ex", + "imp_tot_conc", + "imp_total", + "concepto", + "fecha_venc_pago", + "fecha_serv_desde", + "fecha_serv_hasta", + "cae", + "fecha_vto", + "resultado", + "motivo", + "reproceso", + "nombre", + "domicilio", + "localidad", + "telefono", + "categoria", + "email", + "numero_cliente", + "numero_orden_compra", + "condicion_frente_iva", + "numero_cotizacion", + "numero_remito", + "obs_generales", + "obs_comerciales", + "forma_pago", + "pdf", + "codigo1", + "descripcion1", + "cantidad1", + "umed1", + "precio1", + "importe1", + "bonif1", + "iva_id1", + "imp_iva1", + "tributo_id_1", + "tributo_desc_1", + "tributo_base_imp_1", + "tributo_alic_1", + "tributo_importe_1", + "iva_id_1", + "iva_base_imp_1", + "iva_importe_1", + ], + [ + 1, + 1, + 1, + 1, + "2023-06-08", + 80, + "20123456789", + "PES", + 1, + 100, + 21, + 5, + 0, + 0, + 126, + 1, + "2023-06-08", + "2023-06-08", + "2023-06-08", + "1234567890", + "2023-06-18", + "A", + "", + "", + "John Doe", + "123 Main St", + "City", + "1234567890", + "A", + "john@example.com", + "ABC123", + "OC123", + "Responsable Inscripto", + "COT123", + "REM123", + "Observaciones generales", + "Observaciones comerciales", + "Contado", + "", + "P1", + "Producto 1", + 2, + 7, + 50, + 100, + 0, + 5, + 21, + 1, + "Tributo 1", + 100, + 5, + 5, + 5, + 100, + 21, + ], ] expected_data = [ { - 'cbte_nro': 1, - 'tipo_cbte': 1, - 'punto_vta': 1, - 'cbt_numero': 1, - 'fecha_cbte': '2023-06-08', - 'concepto': 1, - 'moneda_id': 'PES', - 'moneda_ctz': 1, - 'tipo_doc': 80, - 'nro_doc': '20123456789', - 'email': 'john@example.com', - 'numero_cliente': 'ABC123', - 'numero_orden_compra': 'OC123', - 'condicion_frente_iva': 'Responsable Inscripto', - 'numero_cotizacion': 'COT123', - 'numero_remito': 'REM123', - 'imp_total': 126, - 'imp_tot_conc': 0, - 'imp_neto': 100, - 'imp_iva': 21, - 'imp_trib': 5, - 'imp_op_ex': 0, - 'fecha_serv_desde': '2023-06-08', - 'fecha_serv_hasta': '2023-06-08', - 'fecha_venc_pago': '2023-06-08', - 'obs_generales': 'Observaciones generales', - 'obs_comerciales': 'Observaciones comerciales', - 'resultado': 'A', - 'cae': '1234567890', - 'fecha_vto': '2023-06-18', - 'reproceso': '', - 'motivo': '', - 'id': 1, - 'detalles': [ + "cbte_nro": 1, + "tipo_cbte": 1, + "punto_vta": 1, + "cbt_numero": 1, + "fecha_cbte": "2023-06-08", + "concepto": 1, + "moneda_id": "PES", + "moneda_ctz": 1, + "tipo_doc": 80, + "nro_doc": "20123456789", + "email": "john@example.com", + "numero_cliente": "ABC123", + "numero_orden_compra": "OC123", + "condicion_frente_iva": "Responsable Inscripto", + "numero_cotizacion": "COT123", + "numero_remito": "REM123", + "imp_total": 126, + "imp_tot_conc": 0, + "imp_neto": 100, + "imp_iva": 21, + "imp_trib": 5, + "imp_op_ex": 0, + "fecha_serv_desde": "2023-06-08", + "fecha_serv_hasta": "2023-06-08", + "fecha_venc_pago": "2023-06-08", + "obs_generales": "Observaciones generales", + "obs_comerciales": "Observaciones comerciales", + "resultado": "A", + "cae": "1234567890", + "fecha_vto": "2023-06-18", + "reproceso": "", + "motivo": "", + "id": 1, + "detalles": [ { - 'codigo': 'P1', - 'ds': 'Producto 1', - 'umed': 7, - 'qty': 2, - 'precio': 50, - 'importe': 100, - 'iva_id': 5, - 'imp_iva': 21, - 'bonif': None, - 'despacho': False, - 'dato_a': False, - 'dato_b': False, - 'dato_c': False, - 'dato_d': False, - 'dato_e': False + "codigo": "P1", + "ds": "Producto 1", + "umed": 7, + "qty": 2, + "precio": 50, + "importe": 100, + "iva_id": 5, + "imp_iva": 21, + "bonif": None, + "despacho": False, + "dato_a": False, + "dato_b": False, + "dato_c": False, + "dato_d": False, + "dato_e": False, } ], - 'tributos': [ + "tributos": [ { - 'tributo_id': 1, - 'desc': 'Tributo 1', - 'base_imp': 100, - 'alic': 5, - 'importe': 5 + "tributo_id": 1, + "desc": "Tributo 1", + "base_imp": 100, + "alic": 5, + "importe": 5, } ], - 'ivas': [ - { - 'iva_id': 5, - 'base_imp': 100, - 'importe': 21 - } + "ivas": [{"iva_id": 5, "base_imp": 100, "importe": 21}], + "permisos": [], + "opcionales": [], + "cbtes_asoc": [], + "forma_pago": "Contado", + "datos": [ + {"campo": "nombre", "valor": "John Doe", "pagina": ""}, + {"campo": "domicilio", "valor": "123 Main St", "pagina": ""}, + {"campo": "localidad", "valor": "City", "pagina": ""}, + {"campo": "telefono", "valor": "1234567890", "pagina": ""}, + {"campo": "categoria", "valor": "A", "pagina": ""}, + {"campo": "pdf", "valor": "", "pagina": ""}, ], - 'permisos': [], - 'opcionales': [], - 'cbtes_asoc': [], - 'forma_pago': 'Contado', - 'datos': [ - {'campo': 'nombre', 'valor': 'John Doe', 'pagina': ''}, - {'campo': 'domicilio', 'valor': '123 Main St', 'pagina': ''}, - {'campo': 'localidad', 'valor': 'City', 'pagina': ''}, - {'campo': 'telefono', 'valor': '1234567890', 'pagina': ''}, - {'campo': 'categoria', 'valor': 'A', 'pagina': ''}, - {'campo': 'pdf', 'valor': '', 'pagina': ''} - ] } ] result = desaplanar(filas) self.assertEqual(result, expected_data) - def test_desaplanar_multiple_records(self): """ - Test that the desaplanar function correctly converts multiple records from flattened format to structured format. + Test that the desaplanar function correctly converts + multiple recordsfrom flattened format to structured format. """ filas = [ - ['id', 'tipo_cbte', 'punto_vta', 'cbt_numero', 'fecha_cbte', 'tipo_doc', 'nro_doc', 'moneda_id', 'moneda_ctz', - 'imp_neto', 'imp_iva', 'imp_trib', 'imp_op_ex', 'imp_tot_conc', 'imp_total', 'concepto', 'fecha_venc_pago', - 'fecha_serv_desde', 'fecha_serv_hasta', 'cae', 'fecha_vto', 'resultado', 'motivo', 'reproceso', 'nombre', - 'domicilio', 'localidad', 'telefono', 'categoria', 'email', 'numero_cliente', 'numero_orden_compra', - 'condicion_frente_iva', 'numero_cotizacion', 'numero_remito', 'obs_generales', 'obs_comerciales', - 'forma_pago', 'pdf', 'codigo1', 'descripcion1', 'cantidad1', 'umed1', 'precio1', 'importe1', 'bonif1', - 'iva_id1', 'imp_iva1', 'tributo_id_1', 'tributo_desc_1', 'tributo_base_imp_1', 'tributo_alic_1', - 'tributo_importe_1', 'iva_id_1', 'iva_base_imp_1', 'iva_importe_1'], - [1, 1, 1, 1, '2023-06-08', 80, '20123456789', 'PES', 1, 100, 21, 5, 0, 0, 126, 1, '2023-06-08', '2023-06-08', - '2023-06-08', '1234567890', '2023-06-18', 'A', '', '', 'John Doe', '123 Main St', 'City', '1234567890', 'A', - 'john@example.com', 'ABC123', 'OC123', 'Responsable Inscripto', 'COT123', 'REM123', 'Observaciones generales', - 'Observaciones comerciales', 'Contado', '', 'P1', 'Producto 1', 2, 7, 50, 100, 0, 5, 21, 1, 'Tributo 1', 100, - 5, 5, 5, 100, 21], - [2, 1, 1, 2, '2023-06-09', 80, '20987654321', 'PES', 1, 200, 42, 10, 0, 0, 252, 1, '2023-06-09', '2023-06-09', - '2023-06-09', '0987654321', '2023-06-19', 'A', '', '', 'Jane Smith', '456 Elm St', 'Town', '0987654321', 'B', - 'jane@example.com', 'XYZ789', 'OC456', 'Responsable Inscripto', 'COT456', 'REM456', 'Observaciones generales', - 'Observaciones comerciales', 'Tarjeta de Crédito', '', 'P2', 'Producto 2', 1, 7, 200, 200, 0, 5, 42, 2, - 'Tributo 2', 200, 5, 10, 5, 200, 42] + [ + "id", + "tipo_cbte", + "punto_vta", + "cbt_numero", + "fecha_cbte", + "tipo_doc", + "nro_doc", + "moneda_id", + "moneda_ctz", + "imp_neto", + "imp_iva", + "imp_trib", + "imp_op_ex", + "imp_tot_conc", + "imp_total", + "concepto", + "fecha_venc_pago", + "fecha_serv_desde", + "fecha_serv_hasta", + "cae", + "fecha_vto", + "resultado", + "motivo", + "reproceso", + "nombre", + "domicilio", + "localidad", + "telefono", + "categoria", + "email", + "numero_cliente", + "numero_orden_compra", + "condicion_frente_iva", + "numero_cotizacion", + "numero_remito", + "obs_generales", + "obs_comerciales", + "forma_pago", + "pdf", + "codigo1", + "descripcion1", + "cantidad1", + "umed1", + "precio1", + "importe1", + "bonif1", + "iva_id1", + "imp_iva1", + "tributo_id_1", + "tributo_desc_1", + "tributo_base_imp_1", + "tributo_alic_1", + "tributo_importe_1", + "iva_id_1", + "iva_base_imp_1", + "iva_importe_1", + ], + [ + 1, + 1, + 1, + 1, + "2023-06-08", + 80, + "20123456789", + "PES", + 1, + 100, + 21, + 5, + 0, + 0, + 126, + 1, + "2023-06-08", + "2023-06-08", + "2023-06-08", + "1234567890", + "2023-06-18", + "A", + "", + "", + "John Doe", + "123 Main St", + "City", + "1234567890", + "A", + "john@example.com", + "ABC123", + "OC123", + "Responsable Inscripto", + "COT123", + "REM123", + "Observaciones generales", + "Observaciones comerciales", + "Contado", + "", + "P1", + "Producto 1", + 2, + 7, + 50, + 100, + 0, + 5, + 21, + 1, + "Tributo 1", + 100, + 5, + 5, + 5, + 100, + 21, + ], + [ + 2, + 1, + 1, + 2, + "2023-06-09", + 80, + "20987654321", + "PES", + 1, + 200, + 42, + 10, + 0, + 0, + 252, + 1, + "2023-06-09", + "2023-06-09", + "2023-06-09", + "0987654321", + "2023-06-19", + "A", + "", + "", + "Jane Smith", + "456 Elm St", + "Town", + "0987654321", + "B", + "jane@example.com", + "XYZ789", + "OC456", + "Responsable Inscripto", + "COT456", + "REM456", + "Observaciones generales", + "Observaciones comerciales", + "Tarjeta de Crédito", + "", + "P2", + "Producto 2", + 1, + 7, + 200, + 200, + 0, + 5, + 42, + 2, + "Tributo 2", + 200, + 5, + 10, + 5, + 200, + 42, + ], ] expected_data = [ { - 'cbte_nro': 1, - 'tipo_cbte': 1, - 'punto_vta': 1, - 'cbt_numero': 1, - 'fecha_cbte': '2023-06-08', - 'concepto': 1, - 'moneda_id': 'PES', - 'moneda_ctz': 1, - 'tipo_doc': 80, - 'nro_doc': '20123456789', - 'email': 'john@example.com', - 'numero_cliente': 'ABC123', - 'numero_orden_compra': 'OC123', - 'condicion_frente_iva': 'Responsable Inscripto', - 'numero_cotizacion': 'COT123', - 'numero_remito': 'REM123', - 'imp_total': 126, - 'imp_tot_conc': 0, - 'imp_neto': 100, - 'imp_iva': 21, - 'imp_trib': 5, - 'imp_op_ex': 0, - 'fecha_serv_desde': '2023-06-08', - 'fecha_serv_hasta': '2023-06-08', - 'fecha_venc_pago': '2023-06-08', - 'obs_generales': 'Observaciones generales', - 'obs_comerciales': 'Observaciones comerciales', - 'resultado': 'A', - 'cae': '1234567890', - 'fecha_vto': '2023-06-18', - 'reproceso': '', - 'motivo': '', - 'id': 1, - 'detalles': [ + "cbte_nro": 1, + "tipo_cbte": 1, + "punto_vta": 1, + "cbt_numero": 1, + "fecha_cbte": "2023-06-08", + "concepto": 1, + "moneda_id": "PES", + "moneda_ctz": 1, + "tipo_doc": 80, + "nro_doc": "20123456789", + "email": "john@example.com", + "numero_cliente": "ABC123", + "numero_orden_compra": "OC123", + "condicion_frente_iva": "Responsable Inscripto", + "numero_cotizacion": "COT123", + "numero_remito": "REM123", + "imp_total": 126, + "imp_tot_conc": 0, + "imp_neto": 100, + "imp_iva": 21, + "imp_trib": 5, + "imp_op_ex": 0, + "fecha_serv_desde": "2023-06-08", + "fecha_serv_hasta": "2023-06-08", + "fecha_venc_pago": "2023-06-08", + "obs_generales": "Observaciones generales", + "obs_comerciales": "Observaciones comerciales", + "resultado": "A", + "cae": "1234567890", + "fecha_vto": "2023-06-18", + "reproceso": "", + "motivo": "", + "id": 1, + "detalles": [ { - 'codigo': 'P1', - 'ds': 'Producto 1', - 'umed': 7, - 'qty': 2, - 'precio': 50, - 'importe': 100, - 'iva_id': 5, - 'imp_iva': 21, - 'bonif': None, - 'despacho': False, - 'dato_a': False, - 'dato_b': False, - 'dato_c': False, - 'dato_d': False, - 'dato_e': False + "codigo": "P1", + "ds": "Producto 1", + "umed": 7, + "qty": 2, + "precio": 50, + "importe": 100, + "iva_id": 5, + "imp_iva": 21, + "bonif": None, + "despacho": False, + "dato_a": False, + "dato_b": False, + "dato_c": False, + "dato_d": False, + "dato_e": False, } ], - 'tributos': [ + "tributos": [ { - 'tributo_id': 1, - 'desc': 'Tributo 1', - 'base_imp': 100, - 'alic': 5, - 'importe': 5 + "tributo_id": 1, + "desc": "Tributo 1", + "base_imp": 100, + "alic": 5, + "importe": 5, } ], - 'ivas': [ - { - 'iva_id': 5, - 'base_imp': 100, - 'importe': 21 - } + "ivas": [{"iva_id": 5, "base_imp": 100, "importe": 21}], + "permisos": [], + "opcionales": [], + "cbtes_asoc": [], + "forma_pago": "Contado", + "datos": [ + {"campo": "nombre", "valor": "John Doe", "pagina": ""}, + {"campo": "domicilio", "valor": "123 Main St", "pagina": ""}, + {"campo": "localidad", "valor": "City", "pagina": ""}, + {"campo": "telefono", "valor": "1234567890", "pagina": ""}, + {"campo": "categoria", "valor": "A", "pagina": ""}, + {"campo": "pdf", "valor": "", "pagina": ""}, ], - 'permisos': [], - 'opcionales': [], - 'cbtes_asoc': [], - 'forma_pago': 'Contado', - 'datos': [ - {'campo': 'nombre', 'valor': 'John Doe', 'pagina': ''}, - {'campo': 'domicilio', 'valor': '123 Main St', 'pagina': ''}, - {'campo': 'localidad', 'valor': 'City', 'pagina': ''}, - {'campo': 'telefono', 'valor': '1234567890', 'pagina': ''}, - {'campo': 'categoria', 'valor': 'A', 'pagina': ''}, - {'campo': 'pdf', 'valor': '', 'pagina': ''} - ] }, { - 'cbte_nro': 2, - 'tipo_cbte': 1, - 'punto_vta': 1, - 'cbt_numero': 2, - 'fecha_cbte': '2023-06-09', - 'concepto': 1, - 'moneda_id': 'PES', - 'moneda_ctz': 1, - 'tipo_doc': 80, - 'nro_doc': '20987654321', - 'email': 'jane@example.com', - 'numero_cliente': 'XYZ789', - 'numero_orden_compra': 'OC456', - 'condicion_frente_iva': 'Responsable Inscripto', - 'numero_cotizacion': 'COT456', - 'numero_remito': 'REM456', - 'imp_total': 252, - 'imp_tot_conc': 0, - 'imp_neto': 200, - 'imp_iva': 42, - 'imp_trib': 10, - 'imp_op_ex': 0, - 'fecha_serv_desde': '2023-06-09', - 'fecha_serv_hasta': '2023-06-09', - 'fecha_venc_pago': '2023-06-09', - 'obs_generales': 'Observaciones generales', - 'obs_comerciales': 'Observaciones comerciales', - 'resultado': 'A', - 'cae': '0987654321', - 'fecha_vto': '2023-06-19', - 'reproceso': '', - 'motivo': '', - 'id': 2, - 'detalles': [ + "cbte_nro": 2, + "tipo_cbte": 1, + "punto_vta": 1, + "cbt_numero": 2, + "fecha_cbte": "2023-06-09", + "concepto": 1, + "moneda_id": "PES", + "moneda_ctz": 1, + "tipo_doc": 80, + "nro_doc": "20987654321", + "email": "jane@example.com", + "numero_cliente": "XYZ789", + "numero_orden_compra": "OC456", + "condicion_frente_iva": "Responsable Inscripto", + "numero_cotizacion": "COT456", + "numero_remito": "REM456", + "imp_total": 252, + "imp_tot_conc": 0, + "imp_neto": 200, + "imp_iva": 42, + "imp_trib": 10, + "imp_op_ex": 0, + "fecha_serv_desde": "2023-06-09", + "fecha_serv_hasta": "2023-06-09", + "fecha_venc_pago": "2023-06-09", + "obs_generales": "Observaciones generales", + "obs_comerciales": "Observaciones comerciales", + "resultado": "A", + "cae": "0987654321", + "fecha_vto": "2023-06-19", + "reproceso": "", + "motivo": "", + "id": 2, + "detalles": [ { - 'codigo': 'P2', - 'ds': 'Producto 2', - 'umed': 7, - 'qty': 1, - 'precio': 200, - 'importe': 200, - 'iva_id': 5, - 'imp_iva': 42, - 'bonif': None, - 'despacho': False, - 'dato_a': False, - 'dato_b': False, - 'dato_c': False, - 'dato_d': False, - 'dato_e': False + "codigo": "P2", + "ds": "Producto 2", + "umed": 7, + "qty": 1, + "precio": 200, + "importe": 200, + "iva_id": 5, + "imp_iva": 42, + "bonif": None, + "despacho": False, + "dato_a": False, + "dato_b": False, + "dato_c": False, + "dato_d": False, + "dato_e": False, } ], - 'tributos': [ + "tributos": [ { - 'tributo_id': 2, - 'desc': 'Tributo 2', - 'base_imp': 200, - 'alic': 5, - 'importe': 10 + "tributo_id": 2, + "desc": "Tributo 2", + "base_imp": 200, + "alic": 5, + "importe": 10, } ], - 'ivas': [ - { - 'iva_id': 5, - 'base_imp': 200, - 'importe': 42 - } + "ivas": [{"iva_id": 5, "base_imp": 200, "importe": 42}], + "permisos": [], + "opcionales": [], + "cbtes_asoc": [], + "forma_pago": "Tarjeta de Crédito", + "datos": [ + {"campo": "nombre", "valor": "Jane Smith", "pagina": ""}, + {"campo": "domicilio", "valor": "456 Elm St", "pagina": ""}, + {"campo": "localidad", "valor": "Town", "pagina": ""}, + {"campo": "telefono", "valor": "0987654321", "pagina": ""}, + {"campo": "categoria", "valor": "B", "pagina": ""}, + {"campo": "pdf", "valor": "", "pagina": ""}, ], - 'permisos': [], - 'opcionales': [], - 'cbtes_asoc': [], - 'forma_pago': 'Tarjeta de Crédito', - 'datos': [ - {'campo': 'nombre', 'valor': 'Jane Smith', 'pagina': ''}, - {'campo': 'domicilio', 'valor': '456 Elm St', 'pagina': ''}, - {'campo': 'localidad', 'valor': 'Town', 'pagina': ''}, - {'campo': 'telefono', 'valor': '0987654321', 'pagina': ''}, - {'campo': 'categoria', 'valor': 'B', 'pagina': ''}, - {'campo': 'pdf', 'valor': '', 'pagina': ''} - ] - } + }, ] result = desaplanar(filas) @@ -700,23 +1443,25 @@ def test_desaplanar_multiple_records(self): class TestEscribirFunction(unittest.TestCase): def test_escribir_facturas_csv(self): """ - Test that the escribir function can write data from facturas.csv correctly. + Test that the escribir function can write data + from facturas.csv correctly. """ # Read the contents of facturas.csv - with open('datos/facturas.csv', 'r', newline='') as file: - csv_reader = csv.reader(file, delimiter=';') + with open("datos/facturas.csv", "r", newline="") as file: + csv_reader = csv.reader(file, delimiter=";") filas = [row for row in csv_reader] # Write the data to a new file using the escribir function - filename = 'test_facturas_output.csv' + filename = "test_facturas_output.csv" escribir(filas, filename) # Check if the file was created self.assertTrue(os.path.exists(filename)) - # Read the contents of the output file and compare with the original data - with open(filename, 'r', newline='') as file: - csv_reader = csv.reader(file, delimiter=';') + # Read the contents of the output file and compare + # with the original data + with open(filename, "r", newline="") as file: + csv_reader = csv.reader(file, delimiter=";") result = [row for row in csv_reader] self.assertEqual(result, filas) @@ -725,15 +1470,16 @@ def test_escribir_facturas_csv(self): def test_escribir_facturas_xlsx(self): """ - Test that the escribir function can write data from facturas.csv to an XLSX file correctly. + Test that the escribir function can write data from + facturas.csv to an XLSX file correctly. """ # Read the contents of facturas.csv - with open('datos/facturas.csv', 'r', newline='') as file: - csv_reader = csv.reader(file, delimiter=';') + with open("datos/facturas.csv", "r", newline="") as file: + csv_reader = csv.reader(file, delimiter=";") filas = [row for row in csv_reader] # Write the data to an XLSX file using the escribir function - filename = 'test_facturas_output.xlsx' + filename = "test_facturas_output.xlsx" escribir(filas, filename) # Check if the file was created @@ -745,12 +1491,13 @@ def test_escribir_facturas_xlsx(self): result = [] for row in sheet.iter_rows(values_only=True): # Convert None values to empty strings - row = ['' if cell is None else str(cell) for cell in row] + row = ["" if cell is None else str(cell) for cell in row] result.append(row) self.assertEqual(result, filas) # Clean up the test file os.remove(filename) - -if __name__ == '__main__': + + +if __name__ == "__main__": unittest.main() From 1c141f1881028f85ec0faad1f19a7ceb4faad512 Mon Sep 17 00:00:00 2001 From: SONIABHISHEK121 Date: Thu, 15 Aug 2024 13:35:46 +0530 Subject: [PATCH 6/6] removed unittest dependency Signed-off-by: SONIABHISHEK121 --- tests/test_formato_csv.py | 48 ++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/tests/test_formato_csv.py b/tests/test_formato_csv.py index 6c45db7db..72d3f2ef9 100644 --- a/tests/test_formato_csv.py +++ b/tests/test_formato_csv.py @@ -18,7 +18,6 @@ import os import sys -import unittest import csv import pytest import tempfile @@ -35,7 +34,7 @@ @pytest.mark.dontusefix -class TestLeerFunction(unittest.TestCase): +class TestLeerFunction: def test_leer_csv_file(self): """ Test that the leer function can read a valid CSV file correctly. @@ -121,7 +120,7 @@ def test_leer_csv_file(self): ] ] result = leer("datos/facturas.csv", delimiter=";") - self.assertEqual(result, expected_data) + assert result == expected_data def test_leer_csv_custom_delimiter(self): """ @@ -140,7 +139,7 @@ def test_leer_csv_custom_delimiter(self): with patch("builtins.open", return_value=StringIO(sample_csv_data)): result = leer("data/sample.csv", delimiter="|") - self.assertEqual(result, expected_data) + assert result == expected_data def test_leer_csv_with_header(self): """ @@ -159,7 +158,7 @@ def test_leer_csv_with_header(self): with patch("builtins.open", return_value=StringIO(sample_csv_data)): result = leer("data/sample.csv") - self.assertEqual(result, expected_data) + assert result == expected_data def test_leer_csv_without_header(self): """ @@ -177,7 +176,7 @@ def test_leer_csv_without_header(self): with patch("builtins.open", return_value=StringIO(sample_csv_data)): result = leer("data/sample.csv", header=False) - self.assertEqual(result, expected_data) + assert result == expected_data def test_leer_csv_with_whitespace(self): """ @@ -196,7 +195,7 @@ def test_leer_csv_with_whitespace(self): with patch("builtins.open", return_value=StringIO(sample_csv_data)): result = leer("data/sample.csv") - self.assertEqual(result, expected_data) + assert result == expected_data def test_leer_csv_with_non_string_values(self): """ @@ -215,7 +214,7 @@ def test_leer_csv_with_non_string_values(self): with patch("builtins.open", return_value=StringIO(sample_csv_data)): result = leer("data/sample.csv") - self.assertEqual(result, expected_data) + assert result == expected_data def test_leer_csv_different_dialect(self): """ @@ -234,7 +233,7 @@ def test_leer_csv_different_dialect(self): with patch("builtins.open", return_value=StringIO(sample_csv_data)): result = leer("data/sample.csv", delimiter=";") - self.assertEqual(result, expected_data) + assert result == expected_data def test_leer_csv_empty_file(self): """ @@ -245,7 +244,7 @@ def test_leer_csv_empty_file(self): with patch("builtins.open", return_value=StringIO(sample_csv_data)): result = leer("data/sample.csv") - self.assertEqual(result, expected_data) + assert result == expected_data def test_leer_xlsx_file_with_header(self): """ @@ -273,7 +272,7 @@ def test_leer_xlsx_file_with_header(self): workbook.save(temp_file.name) result = leer(temp_file.name) - self.assertEqual(result, expected_data) + assert result == expected_data # Clean up the temporary file os.unlink(temp_file.name) @@ -301,14 +300,14 @@ def test_leer_xlsx_file_without_header(self): workbook.save(temp_file.name) result = leer(temp_file.name, header=False) - self.assertEqual(result, expected_data) + assert result == expected_data # Clean up the temporary file os.unlink(temp_file.name) @pytest.mark.dontusefix -class TestAplanarFunction(unittest.TestCase): +class TestAplanarFunction: def test_aplanar_single_record(self): """ Test that the aplanar function correctly flattens a single record. @@ -536,7 +535,7 @@ def test_aplanar_single_record(self): ] result = aplanar([reg]) - self.assertEqual(result, expected_data) + assert result == expected_data def test_aplanar_multiple_records(self): """ @@ -887,11 +886,11 @@ def test_aplanar_multiple_records(self): ] result = aplanar(regs) - self.assertEqual(result, expected_data) + assert result == expected_data @pytest.mark.dontusefix -class TestDesplanarFunction(unittest.TestCase): +class TestDesplanarFunction: def test_desaplanar_single_record(self): """ Test that the desaplanar function correctly converts @@ -1096,7 +1095,7 @@ def test_desaplanar_single_record(self): ] result = desaplanar(filas) - self.assertEqual(result, expected_data) + assert result == expected_data def test_desaplanar_multiple_records(self): """ @@ -1436,11 +1435,11 @@ def test_desaplanar_multiple_records(self): ] result = desaplanar(filas) - self.assertEqual(result, expected_data) + assert result == expected_data @pytest.mark.dontusefix -class TestEscribirFunction(unittest.TestCase): +class TestEscribirFunction: def test_escribir_facturas_csv(self): """ Test that the escribir function can write data @@ -1456,14 +1455,14 @@ def test_escribir_facturas_csv(self): escribir(filas, filename) # Check if the file was created - self.assertTrue(os.path.exists(filename)) + assert os.path.isfile(filename) # Read the contents of the output file and compare # with the original data with open(filename, "r", newline="") as file: csv_reader = csv.reader(file, delimiter=";") result = [row for row in csv_reader] - self.assertEqual(result, filas) + assert result == filas # Clean up the test file os.remove(filename) @@ -1483,7 +1482,7 @@ def test_escribir_facturas_xlsx(self): escribir(filas, filename) # Check if the file was created - self.assertTrue(os.path.exists(filename)) + assert os.path.isfile(filename) # Read the contents of the XLSX file and compare with the original data workbook = load_workbook(filename) @@ -1493,11 +1492,8 @@ def test_escribir_facturas_xlsx(self): # Convert None values to empty strings row = ["" if cell is None else str(cell) for cell in row] result.append(row) - self.assertEqual(result, filas) + assert result == filas # Clean up the test file os.remove(filename) - -if __name__ == "__main__": - unittest.main()