-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.py
More file actions
381 lines (266 loc) · 13.7 KB
/
Copy pathscript.py
File metadata and controls
381 lines (266 loc) · 13.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
import pandas as pd
from openpyxl import Workbook
from openpyxl.utils.dataframe import dataframe_to_rows
from api.reniec import consultar_persona_por_dni
# Leer el archivo original
df = pd.read_excel('./uploads/data69.xlsx')
# ***Realizar las transformaciones necesarias *** #
# ------------------------------------------------------#
# Crear una columna con 'BV' o 'FT' según el tipo de documento inicio con B0 o F0 se pondra BV o FT respectivamente
df['Tipo_Doc'] = df['DOCUMENTO'].apply(
lambda x: 'BV' if x.startswith('B0') or x.startswith('EB0')
else 'FT')
# ------------------------------------------------------#
# ------------------------------------------------------#
# ------------------------------------------------------#
# si hay numero de documento de identidad en la columna 'NRO.DOC' ponerlo en la columna 'DOCUMENTO' como texto sino poner '00000002'
df['NRO_DOCUMENTO'] = df['NRO.DOC'].apply(lambda x: x if x == '0001' else (
x if pd.notna(x) and x != '-' else '00000000002'))
# ------------------------------------------------------#
df['FECHA'] = pd.to_datetime(df['FECHA'], format='%d/%m/%Y')
df['Col1'] = ''
df['Col2'] = ''
# variables de seguimiento
current_col1 = 5
current_month = None
current_counter = 1
for index, row in df.iterrows():
# Obtener el mes actual de la fecha
month = row['FECHA'].month
# Si cambiamos de mes o superamos el límite de 9999, reseteamos el contador y aumentamos Col1
# Obtener el mes actual de la fecha
month = row['FECHA'].month
# Si cambiamos de mes, reseteamos el contador y actualizamos el mes actual
if month != current_month:
current_month = month
current_counter = 1
# Si superamos el límite de 9999, reseteamos el contador y aumentamos Col1
if current_counter > 9999:
current_counter = 1
current_col1 += 1
# Asignar valores a las columnas
df.at[index, 'Col1'] = f"{current_col1:02d}"
df.at[index, 'Col2'] = f"{current_month:02d}{current_counter:04d}"
# Incrementar el contador
current_counter += 1
# ------------------------------------------------------#
# si el nuemero de documento tiene una longitud de 11 caracteres el tipo_documento_identidad sera 6 pero si tiene un -, esta vacio o tiene un dni se pondra 0
def determinar_tipo_documento(num_documento):
num_documento = str(num_documento)
if pd.isna(num_documento) or num_documento == '-' or len(num_documento) != 11:
return '0'
return '6'
df['Tipo_Doc_identidad'] = df['NRO_DOCUMENTO'].apply(determinar_tipo_documento)
# ------------------------------------------------------#
#!calcular todos los valores númericos para las filas
# calcular la base disponible de la operacion gravada que es la divicion del total entre 1.23
# poner un decimal
df['Base_opreacion_gravada'] = (df['TOTAL'] / 1.23).round(2)
# Calcular IGV_IPM (10% de Base_opreacion_gravada)
df['IGV_IPM'] = (df['Base_opreacion_gravada'] * 0.10).round(2)
# Calcular Otros_tributos (13% de Base_opreacion_gravada)
df['Otros_tributos'] = (df['Base_opreacion_gravada'] * 0.13).round(2)
df['TOTAL_FINAL'] = df['Base_opreacion_gravada'] + \
df['IGV_IPM'] + df['Otros_tributos']
df['TOTAL'] = df['TOTAL_FINAL'].round(2)
df['TOTAL'] = df['TOTAL'].apply(lambda x: f"{x:.2f}")
# Formatear las columnas a cadenas con dos decimales visibles
df['Base_opreacion_gravada'] = df['Base_opreacion_gravada'].apply(lambda x: f"{
x:.2f}")
df['IGV_IPM'] = df['IGV_IPM'].apply(lambda x: f"{x:.2f}")
df['Otros_tributos'] = df['Otros_tributos'].apply(lambda x: f"{x:.2f}")
# ------------------------------------------------------#
df['Serie_documento'] = df['DOCUMENTO'].apply(
lambda x: x.split('-')[0])
df['Numero_documento'] = df['DOCUMENTO'].apply(
lambda x: x.split('-')[1])
# ------------------------------------------------------#
# que la cuenta de ingresos contables sea 701210 pero que el ultimo digito sea el ultimo digito de la serie del documento
def determinar_cuenta_ingresos_contable(numero):
numero = str(numero)
return f'70121{numero[-1]}'
df['Cuenta_ingresos_contable'] = df['Serie_documento'].apply(
determinar_cuenta_ingresos_contable)
# ------------------------------------------------------#
# Crear un nuevo DataFrame con las columnas ordenadas y renombradas según la estructura deseada
df_transformed = pd.DataFrame()
# ? Rellenar las columnas según tus especificaciones (ajusta los nombres y valores según sea necesario)
# que tenga formato Texto para el excel
df_transformed['Tamaño/Formato'] = ''
df_transformed['SubDiario'] = df['Col1'].astype(str) # 2 Caracteres
df_transformed['Comprobante'] = df['Col2'] # 6 Caracteres
df_transformed['Moneda'] = 'MN' # 2 Caracteres (Ejemplo fijo)
df_transformed['Fecha_emision'] = df['FECHA'].dt.strftime(
'%d/%m/%Y') # Campo fecha (dd/mm/aaaa)
df_transformed['Fecha_vencimiento'] = '' # Campo vacío (dd/mm/aaaa)
df_transformed['Tipo_Doc'] = df['Tipo_Doc'] # 2 Caracteres
df_transformed['Serie'] = df['Serie_documento'] # 4 Caracteres
df_transformed['Numero'] = df['Numero_documento'] # 8 Caracteres
# 1 Caracter (Ejemplo fijo)
df_transformed['Tipo_documento_identidad'] = df['Tipo_Doc_identidad']
# 20 Caracteres
df_transformed['Numero_documento_identidad'] = df['NRO_DOCUMENTO']
# Si el numero_documento_identidad es 0001 poner 'FACTURAS ANULADAS' sino porner VENTA DE MERCADERIA
df_transformed['Descripcion'] = df['NRO_DOCUMENTO'].apply(
lambda x: 'FACTURAS ANULADAS' if x == '0001' else 'VENTA DE MERCADERIA')
df_transformed['Valor_factura_exportacion'] = '' # 2 decimales
df_transformed['Base_inponible'] = df['Base_opreacion_gravada'].round(
2) # 2 decimales
df_transformed['Impuesto1'] = '' # 2 decimales
df_transformed['Impuesto2'] = '' # 2 decimales
df_transformed['Impuesto3'] = '' # 2 decimales
df_transformed['IGV Y/O IPM'] = df['IGV_IPM'] # 2 decimales
df_transformed['Impuesto5'] = '' # 2 decimales
df_transformed['Otros tributos'] = df['Otros_tributos'] # 2 decimales
# si tiene un 0 como decimal ponerlo
df_transformed['Importe_total'] = df['TOTAL'] # 2 decimales
df_transformed['Tipo_de_conversion'] = 'V' # 1 Caracter (Ejemplo fijo)
df_transformed['Tipo_de_cambio'] = '' # 3 decimales
df_transformed['Referencia_comprobante_fecha'] = '' # dd/mm/aaaa
# 2 caracteres (Ejemplo fijo)
df_transformed['Referencia_comprobante_tipo'] = ''
# 10 caracteres (Ejemplo fijo)
df_transformed['Referencia_comprobante_serie'] = ''
df_transformed['Referencia_comprobante_numero'] = '' # 20 caracteres
df_transformed['Cuenta_contable'] = '121201' # 12 caracteres
# 12 caracteres
df_transformed['Cuentra_ingresos_contable'] = df['Cuenta_ingresos_contable'].astype(
str)
df_transformed['Area'] = '' # 3 caracteres
df_transformed['Centro_costos'] = '' # 6 caracteres
df_transformed['Anexo_referencia'] = '' # 20 caracteres
# ** ------------------- ** #
# ** ------------------- ** #
# ** ------------------- ** #
# ** ------------------- ** #
# ** ------------------- ** #
# ? TRANSFORMACIONES DE LA SEGUNDA HOJA ** #
# copiar la columna NRO.DOC en la columna DOCUMENTO
df_nro_doc = df[['NRO.DOC']].copy()
# poner la C al tipo a la columna de tipo de anexo
df_nro_doc['Tipo_Anexo'] = 'C'
# Reordenar las columnas
df_nro_doc = df_nro_doc[['Tipo_Anexo', 'NRO.DOC']]
# filtar las columnas que tengan - y eliminarlas
df_nro_doc = df_nro_doc[df_nro_doc['NRO.DOC'] != '-']
# usar la funcion para consultar el dni del cliente y ponerlo en cliente
# poner el tipo de persona N cuando tenga el NRO.DOC una longitudad de 8 caracteres o tenga un RUC que inicie con 10 sino poner J
def determinar_tipo_persona(num_documento):
num_documento = str(num_documento)
if len(num_documento) == 8 or num_documento.startswith('10'):
return 'N'
return 'J'
df_nro_doc['Tipo_persona'] = df['NRO_DOCUMENTO'].apply(determinar_tipo_persona)
def consulta(dni):
try:
if len(str(dni)) == 8:
return consultar_persona_por_dni(dni)
else:
return None
except Exception as e:
print(f"Error al consultar persona: {e}")
return None
# obtener el dni de los ruc que empiezen con 10 osea 10763469498 eliminar el ultimo numero y el 10 y ponerlo en la columna NRO.DOC
def remove_ruc_from_documento(num_documento):
num_documento = str(num_documento)
if num_documento.startswith('10') and len(num_documento) == 11:
return num_documento[:-1][2:]
return num_documento
df_nro_doc['consulta_result'] = df_nro_doc['NRO.DOC'].apply(
remove_ruc_from_documento).apply(consulta)
df_nro_doc['CLIENTE'] = df['CLIENTE']
# funcion para actualizar al cliente segun se haya llamado a la api
def actualizar_cliente(row):
if row['consulta_result']:
return row['consulta_result']['nombre_completo']
return row['CLIENTE']
df_nro_doc['CLIENTE'] = df_nro_doc.apply(actualizar_cliente, axis=1)
# Filtra los registros que tienen el tipo de persona 'N'
df_n = df_nro_doc[df_nro_doc['Tipo_persona'] == 'N'].copy()
# Apellidos_paterno, Apellidos_materno y Nombres serán vacíos
# Separar los nombres completos
df_n['Apellido_paterno'] = df_n['consulta_result'].apply(
lambda x: x['apellido_paterno'] if x else '')
df_n['Apellido_materno'] = df_n['consulta_result'].apply(
lambda x: x['apellido_materno'] if x else '')
df_n['Nombres'] = df_n['consulta_result'].apply(
lambda x: x['nombres'] if x else '')
df_nro_doc = df_nro_doc[df_nro_doc['Tipo_persona']
!= 'N']._append(df_n, ignore_index=True)
# Añadir los clientes que no tengan un guion en su numero de documento
df_nro_doc['Razon_social_o_descripcion'] = df_nro_doc['CLIENTE']
df_nro_doc['Direccion_de_referencia'] = '--'
# RUC mismo que el NRO.DOC
df_nro_doc['RUC'] = df_nro_doc['NRO.DOC']
def determinar_tipo_documento_segunda_hoja(num_documento):
num_documento = str(num_documento)
if pd.isna(num_documento) or num_documento == '-' or len(num_documento) != 11:
return '1'
return '6'
# Tipo de documento de identidad, es 1 cuando en NRO.DOC tiene longitud de 8 si tiene mas se pone 6
df_nro_doc['Tipo_documento_identidad'] = df_nro_doc['NRO.DOC'].apply(
determinar_tipo_documento_segunda_hoja)
# Columna para el número de documento de identidad del cliente
df_nro_doc['Numero_documento_identidad'] = df_nro_doc['NRO.DOC']
# Columna para el tipo siempre es N
df_nro_doc['Tipo'] = 'N'
# Columna Moneda siempre es MN
df_nro_doc['Moneda'] = 'MN'
# Columna nacionalidad sera vacia
df_nro_doc['Nacionalidad'] = ''
# Columna ¿Domiciliado? sera SI
df_nro_doc['Domiciliado'] = 'SI'
# Si es necesario, reordena las columnas para mantener el orden deseado
df_nro_doc = df_nro_doc[['Tipo_Anexo', 'NRO.DOC', 'Razon_social_o_descripcion', 'Direccion_de_referencia',
'Tipo_persona', 'Apellido_paterno', 'Apellido_materno', 'Nombres', 'RUC',
'Tipo_documento_identidad', 'Numero_documento_identidad', 'Tipo', 'Moneda',
'Nacionalidad', 'Domiciliado']]
# CREACION DE LA HOJA DE EXCEL
excel_file = 'Data_transformada.xlsx'
wb = Workbook()
ws = wb.active
ws.title = 'Ventas'
header = [
'VENTAS', 'SubDiario', 'Comprobante', 'Moneda', 'Fecha de emisión de comprobante de pago',
'Fecha de vencimiento o fecha de pago', 'Tipo de documento', 'Serie o Nro Maq Regist de documento',
'Número de documento', 'Tipo de documento de identidad', 'Número de documento de identidad',
'Apellidos y Nombres, denominación o razón social del proveedor', 'Valor facturado de la exportación',
'Base imponible de la operación gravada', 'Importe total de la operación Exonerada',
'Importe total de la operación Inafecta', 'ISC', 'IGV Y/O IPM', 'ICBPER', 'Otros tributos',
'Importe total', 'Tipo de Conversión', 'Tipo de cambio',
'Referencia del comprobante de pago que se modifica Fecha', 'Referencia del comprobante de pago que se modifica Tipo',
'Referencia del comprobante de pago que se modifica Serie', 'Referencia del comprobante de pago que se modifica Numero',
'Cuenta contable por cobrar', 'Cuenta contable de ingresos', 'Area', 'Centro de Costo', 'Anexo de Referencia'
]
restricciones = [
'Restricciones', 'Ver T.G. 02', 'Los dos primeros dígitos son el mes y los otros 4 siguientes un correlativo (MM0001)', 'Ver T.G. 03',
'Solo Fecha', 'Solo Fecha', 'Ver T.G.56 Clave "DOC"', '', '', 'Sólo 0, 1, 4, 6, 7 y A', 'Ingresar solo anexos.', 'Glosa',
'Sólo números', 'Sólo números', 'Sólo números', 'Sólo números', 'Sólo números', 'Sólo números', 'Sólo números',
'Sólo números', 'Sólo números', 'Solo: "C"= Especial, "M"=Compra, "V"=Venta', 'Sólo números. Llenar solo si el tipo de cambio es "C"',
'Fecha documento', 'Tipo de documento', 'Serie de documento', 'Número de documento',
'T.G. 56 Mantenimiento en parámetros de ventas.', 'T.G. 56 Mantenimiento en parámetros de ventas.',
'Si Cuenta Contable tiene habilitado la área, ver T.G. 26', 'Si Cuenta Contable tiene habilitado C. Costo, Ver T.G. 05', 'Ingresar solo anexos.'
]
# Escribir el encabezado
# ws.append(header)
# ws.append(restricciones)
# Escribir el encabezado
ws.append(df_transformed.columns.tolist())
# Escribir los datos del DataFrame
for r in dataframe_to_rows(df_transformed, index=False, header=True):
ws.append(r)
# Crear la segunda hoja
ws2 = wb.create_sheet('Clientes')
# Escribir los datos en la segunda hoja
for r in dataframe_to_rows(df_nro_doc, index=False, header=True):
ws2.append(r)
# Aplicar formato de texto a todas las celdas
# for row in ws.iter_rows():
# for cell in row:
# cell.number_format = '@'
# Aplicar formato de texto a todas las celdas
for row in ws2.iter_rows():
for cell in row:
cell.number_format = '@'
# Guardar el archivo Excel
wb.save(excel_file)