'''
Nombre:         app.py
Autor(es):      Angel Soto
Fecha Creación: 2022-08-02
Descripción:    Archivo de prueba de conocimiento sobre Python y Flask
Observaciones:  Sin observaciones.
Python Ver.  :  3.10.5
Modificaciones: 
----------------------------------------
    *2022-08-02*
    Los JSON generados muestran correctamente los acentos

CONSIDERACIONES: el return de cada Funcion debería ser un 404 indicándole al usuario que hay un error pero no decirle cual
'''

#Importación de las Librerías necesarias
#Importación del framework Flask y sus métodos Flask para las conexiones y jsonify para el envió de respuestas en formato json
from ipaddress import ip_address
import json
from lib2to3.pytree import type_repr
from re import A
from flask import Flask, jsonify, request
#from flask_cors import CORS
#Importación de la Librería para conectar con MySQL
import mysql.connector
from werkzeug.middleware.proxy_fix import ProxyFix
import time



#Funcion constructora de la conexión con la base de datos
def mydb():
    aux = False
    while aux == False:
        try:
            con = mysql.connector.connect(
            host = '104.218.48.215',
            user = 'cloccide_pablo',
            password = 'clo2020*',
            database = 'cloccide_prueba'
            )
            aux = True
        except mysql.connector.Error as err:
            print(err)
            aux = False
    return con

def mydbDespacho():
    aux = False
    while aux == False:
        try:
            con = mysql.connector.connect(
            host = '104.218.48.215',
            user = 'cloccidental_despachos',
            password = 'sNVfu=4]ajOt',
            database = 'cloccidental_clo_dp'
            )
            aux = True
        except mysql.connector.Error as err:
            print(err)
            aux = False
    return con

#Inicialización de la aplicación
app = Flask(__name__)
#CORS(app)

 

#Ruta para la ejecución de la Función que bajara la información de los artículos de acuerdo a la fecha
@app.route('/articulos/<fechamodifi>', methods = ['GET'])
def solicitar_articulo(fechamodifi):
    #Try para la captura de errores en la bajada de los datos de los artículos
    try:
        #Petición y captura de los datos solicitados de acuerdo al parámetro fecha solicitado
        con         = mydb()
        mi_cursor   = con.cursor()
        sql         = f"SELECT * FROM articulo WHERE fechamodifi >= '{fechamodifi}';"
        mi_cursor.execute(sql)
        array       = mi_cursor.fetchall()
        
        #Creación de la tupla que contendrá los datos
        articulos   = []

        #For que recorrerá el array de datos traído por la base de datos
        for celda in array:
            #Diccionario que guardara los datos traídos
            #La Funcion STRIP() elimina espacios en blanco
            #La Funcion STRFTIME() da formato a la fecha
            data = {
            'codigo'      : celda[0].strip(),
            'grupo'       : celda[1].strip(),
            'subgrupo'    : celda[2].strip(),
            'nombre'      : celda[3].strip(),
            'referencia'  : celda[4].strip(),
            'marca'       : celda[5].strip(),
            'unidad'      : celda[6].strip(),
            'existencia'  : celda[7],
            'precio1'     : celda[8],
            'precio2'     : celda[9],
            'precio3'     : celda[10],
            'precio4'     : celda[11],
            'precio5'     : celda[12],
            'precio6'     : celda[13],
            'precio7'     : celda[14],
            'fechamodifi' : celda[15].strftime("%Y-%m-%d %H:%M:%S"),
            'discont'     : celda[16],
            'vta_max'     : celda[17],
            'vta_min'     : celda[18],
            'dctotope'    : celda[19],
            'empreapp'    : celda[20]
            #Preventa fue anulada
            }
            #Guardado del Diccionario en la tupla previamente creada
            articulos.append(data)

        #Cierre de la conexión
        con.close()
        #Retorno de la información obtenida en formato JSON
        return jsonify(articulos)

    #Excepción que captura los Errores en la solicitud de los datos
    except Exception as error:
        #Muestra en consola del error presentado
        print(error)
        #Cierre de conexión con la base de datos
        con.close()
        #Retorno del Error presentado como respuesta
        return jsonify(status = '404')


#Ruta para la ejecución de la Función que bajara la información de los artículos de acuerdo a la fecha
@app.route('/articulo', methods = ['GET'])
@app.route('/articulo/', methods = ['GET'])
@app.route('/articulo/<dato>', methods = ['GET'])
def pedir_articulo(dato = ' '):
    #Try para la captura de errores en la bajada de los datos de los artículos
    try:
        #Petición y captura de los datos solicitados de acuerdo al parámetro fecha solicitado
        con = mydb()
        mi_cursor = con.cursor()
        sql = f"SELECT * FROM `articulo` WHERE `precio1` != 0 AND `existencia` != 0 AND `discont` = 0 AND nombre REGEXP '{dato}';"
        mi_cursor.execute(sql)
        array = mi_cursor.fetchall()
        
        #Creación de la tupla que contendrá los datos
        articulos   = []

        #For que recorrerá el array de datos traído por la base de datos
        for celda in array:
            #Diccionario que guardara los datos traídos
            #La Funcion STRIP() elimina espacios en blanco
            #La Funcion STRFTIME() da formato a la fecha
            data = {
            'codigo'      : celda[0].strip(),
            'grupo'       : celda[1].strip(),
            'nombre'      : celda[3].strip(),
            'referencia'  : celda[4].strip(),
            'marca'       : celda[5].strip(),
            'unidad'      : celda[6].strip(),
            'existencia'  : celda[7],
            'precio1'     : celda[8],
            'fechamodifi' : celda[15].strftime("%Y-%m-%d %H:%M:%S"),
            'vta_max'     : celda[17],
            'vta_min'     : celda[18],
            'dctotope'    : celda[19],
            #Preventa fue anulada
            }
            #Guardado del Diccionario en la tupla previamente creada
            articulos.append(data)

        #Cierre de la conexión
        con.close()
        #Retorno de la información obtenida en formato JSON
        return jsonify(articulos)

    #Excepción que captura los Errores en la solicitud de los datos
    except Exception as error:
        #Muestra en consola del error presentado
        print(error)
        print (time.strftime("%d/%m/%y %H:%M:%S"))
        #Cierre de conexión con la base de datos
        con.close()
        #Retorno del Error presentado como respuesta
        return jsonify(status = '404')


#Ruta para la ejecución de la Función que bajara la información de los clientes de acuerdo a la fecha
@app.route('/clientes/<fechamodifi>', methods = ['GET'])
def info_cliente(fechamodifi):
    try:
        #Petición y captura de los datos solicitados de acuerdo al parámetro fecha solicitado
        con         = mydb()
        mi_cursor   = con.cursor()
        sql         = f"SELECT * FROM cliempre WHERE fechamodifi >= '{fechamodifi}';"
        mi_cursor.execute(sql)
        array       = mi_cursor.fetchall()

        #Creación de la tupla que contendrá los datos
        clientes   = []

        #For que recorrerá el array de datos traído por la base de datos
        for celda in array:
            #Diccionario que guardara los datos traídos
            #La Funcion STRIP() elimina espacios en blanco
            #La Funcion STRFTIME() da formato a la fecha
            data = {
            'codigo'          : celda[0].strip(),
            'nombre'          : celda[1],
            'direccion'       : celda[2].strip(),
            'telefonos'       : celda[3].strip(),
            'perscont'        : celda[4].strip(),
            'vendedor'        : celda[5].strip(),
            'contribespecial' : celda[6],
            'status'          : celda[7],
            'sector'          : celda[8].strip(),
            'subcodigo'       : celda[9].strip(),
            'fechamodifi'     : celda[10].strftime("%Y-%m-%d %H:%M:%S"),
            'precio'          : celda[11],
            'email'           : celda[12].strip(),
            'kne_activa'      : celda[13],
            'kne_mtomin'      : celda[14]
            }
            #Guardado del Diccionario en la tupla previamente creada
            clientes.append(data)

        #Cierre de la conexión
        con.close()
        #Retorno de la información obtenida en formato JSON
        return jsonify(clientes)

    except Exception as error:
        print(error)
        #Cierre de conexión con la base de datos
        con.close()
        #Retorno del Error presentado como respuesta
        return jsonify(status = '404')


#Ruta para la ejecución de la Función que bajara la información de los estadísticas de acuerdo a la fecha
@app.route('/estadisticas/<fecha_estad>', methods = ['GET'])
def estadisticas(fecha_estad):
    try:
        #Petición y captura de los datos solicitados de acuerdo al parámetro fecha solicitado
        con         = mydb()
        mi_cursor   = con.cursor()
        sql         = f"SELECT * FROM ke_estadc01 WHERE fecha_estad >= '{fecha_estad}';"
        mi_cursor.execute(sql)
        array       = mi_cursor.fetchall()

        #Creación de la tupla que contendrá los datos
        estadisticas   = []

        #For que recorrerá el array de datos traído por la base de datos
        for celda in array:
            #Diccionario que guardara los datos traídos
            #La Funcion STRIP() elimina espacios en blanco
            #La Funcion STRFTIME() da formato a la fecha
            data = {
            'codcoord'       : celda[0].strip(),
            'nomcoord'       : celda[1].strip(),
            'vendedor'       : celda[2].strip(),
            'nombrevend'     : celda[3].strip(),
            'cntpedidos'     : celda[4],
            'mtopedidos'     : celda[5],
            'cntfacturas'    : celda[6],
            'mtofacturas'    : celda[7],
            'metavend'       : celda[8],
            'prcmeta'        : celda[9],
            'cntclientes'    : celda[10],
            'clivisit'       : celda[11],
            'prcvisitas'     : celda[12],
            'lom_montovtas'  : celda[13],
            'lom_prcvtas'    : celda[14],
            'lom_prcvisit'   : celda[15],
            'rlom_montovtas' : celda[16],
            'rlom_prcvtas'   : celda[17],
            'rlom_prcvisit'  : celda[18],
            'fecha_estad'    : celda[19].strftime("%Y-%m-%d")
            }
            #Guardado del Diccionario en la tupla previamente creada
            estadisticas.append(data)

        #Cierre de la conexión
        con.close()
        #Retorno de la información obtenida en formato JSON
        return jsonify(estadisticas)

    except Exception as error:
        print(error)
        #Cierre de conexión con la base de datos
        con.close()
        #Retorno del Error presentado como respuesta
        return jsonify(status = '404')

#Funcion para la comunicacion del URL del Usuario
@app.route('/usuario/<ked_codigo>' , methods = ['GET'])
def bajar_usuario(ked_codigo):
    #TRY para la ejecución del programa
    try:
        #Conexión con la base de datos
        con = mydb()
        mi_cursor = con.cursor()
        #SQL para la búsqueda del enlace de acuerdo al código proporcionado
        sql = f"SELECT ked_enlace FROM ke_dataconex WHERE ked_codigo = '{ked_codigo}' AND ked_status = '1';"
        mi_cursor.execute(sql)
        array = mi_cursor.fetchone()
        #Creación de la tupla que guardara los datos
        url = []
        #Recorrido y guardado del resultado en un diccionario
        for celda in array:
            data = {
                'respuesta': celda
            }
            #Insercion del diccionario dentro de la tupla previamente creada
            url.append(data)
        #Cerrado de la conexión
        con.close()
        #Retorno de la tupla con los resultados
        return jsonify(url)
    #Capturador de errores al intentar ejecutar el programa
    except Exception as error:
        #Muestra del error en consola
        print(error)
        #Cierre de conexión con la base de datos
        con.close()
        #Retorno del Error presentado como respuesta 404
        return jsonify(respuesta = '404')


@app.route('/pedido', methods = ['POST'])
def guardar_pedido():
    #Conexión con la base de datos
    conn = mydb()
    # Cancelar enviado automático
    conn.autocommit = False
    #Inicialización de la variable que cuenta errores
    estado = []

    
    #Inicio del Try Except
    try:
        #Llamado de los datos del JSON
        Pedidos = request.json['Pedido']

        with open('data.json', 'a') as file:
            json.dump(Pedidos, file, indent=4)
        #For para desencapsular el JSON
        
        for Pedido in Pedidos:
            errores_line = 0
            errores_head = 0
            #Diccionario de la cabecera
            Cabecera = Pedido['Cabecera']
            

            #Asignación de variable para cada dato del diccionario
            kti_ndoc      = Cabecera["kti_ndoc"]
            kti_tdoc      = Cabecera["kti_tdoc"]
            kti_codcli    = Cabecera["kti_codcli"]
            kti_nombrecli = Cabecera["kti_nombrecli"]
            kti_codven    = Cabecera["kti_codven"]
            kti_docsol    = Cabecera["kti_docsol"]
            kti_condicion = Cabecera["kti_condicion"]
            kti_tipprec   = Cabecera["kti_tipprec"]
            kti_totneto   = Cabecera["kti_totneto"]
            kti_status    = Cabecera["kti_status"]
            kti_fchdoc    = Cabecera["kti_fchdoc"]
            fechamodifi   = Cabecera["fechamodifi"]
            kti_negesp    = Cabecera["kti_negesp"]

            #Inicializacion del cursor y SQL para la validacion de la existencia
            cursor = conn.cursor()
            queryVal = f"SELECT COUNT(kti_ndoc) FROM ke_opti WHERE kti_ndoc = '{kti_ndoc}';"
            cursor.execute(queryVal)

            pedConteo = cursor.fetchone()
            print(f"Valor retornado en cabeceras: {pedConteo[0]}")
        #     #Validacion de la existencia
            if pedConteo[0] > 0:
                #Conteo de errores, rollback de los datos y continuacion del ciclo; omicion de datos erroneos
                estado.append(
                    {
                        "correlativo": kti_ndoc,
                        "status": "111"
                    }
                )
                errores_head = 1
                print(f"Rollback Cabecera {kti_ndoc} Por repeticion de correlativo")
                conn.rollback()
                continue
            else:
                #Envio de datos a la base de datos
                queryIn = f"INSERT INTO ke_opti(kti_ndoc, kti_tdoc, kti_codcli, kti_nombrecli, kti_codven, kti_docsol, kti_condicion, kti_tipprec, kti_totneto, kti_status, kti_fchdoc, fechamodifi, kti_negesp) VALUES('{kti_ndoc}', '{kti_tdoc}', '{kti_codcli}', '{kti_nombrecli}', '{kti_codven}', '{kti_docsol}', '{kti_condicion}', '{kti_tipprec}', '{kti_totneto}', '{kti_status}', '{kti_fchdoc}', '{fechamodifi}', '{kti_negesp}');"

                cursor.execute(queryIn)

                #print(f"Cabecera ejecutada adecuadamente {kti_ndoc}")

                #Inicializacion de la Tupla de las lineas
                Lineas = Cabecera['Lineas']

                #Descompocicion de la Tupla
                for Linea in Lineas:
                    if errores_line > 0:
                        continue
                    else:
                        #If para validar que el numero de documento tanto en la cabecera como en las lineas sea el correcto
                        if Linea["kti_ndoc"] != Cabecera["kti_ndoc"]:
                            print(f"Rollbak linea: {Linea['kti_ndoc']} cabecera: {Cabecera['kti_ndoc']}")
                            #Conteo de errores, rollback de los datos y continuacion del ciclo; omicion de datos erroneos
                            estado.append(
                                {
                                    "correlativo": Cabecera["kti_ndoc"],
                                    "status": "403"
                                }
                            )
                            errores_line = 1
                            conn.rollback()
                            continue
                        else:

                            #Asignacion de variables de los datos del diccionario de Linea
                            kti_tdoc    = Linea["kti_tdoc"]
                            kti_ndoc    = Linea["kti_ndoc"]
                            kti_tipprec = Linea["kti_tipprec"]
                            kmv_codart  = Linea["kmv_codart"]
                            kmv_nombre  = Linea["kmv_nombre"]
                            kmv_cant    = Linea["kmv_cant"]
                            kmv_artprec = Linea["kmv_artprec"]
                            kmv_stot    = Linea["kmv_stot"]

                            #Inicializacion del cursor y SQL para la validacion de la existencia
                            cursorl = conn.cursor()
                            queryValL = f"SELECT COUNT(kmv_codart) FROM ke_opmv WHERE kti_ndoc = '{kti_ndoc}' AND kmv_codart = '{kmv_codart}';"
                            cursorl.execute(queryValL)
                            #print("cursor ejecutado en: " + kti_ndoc)
                            
                            linConteo = cursorl.fetchone()
                            #print(f"Valor retornado en lineas: {linConteo[0]}")

                            #Validacion de la existencia
                            if linConteo[0] > 0:
                                #Conteo de errores, rollback de los datos y continuacion del ciclo; omicion de datos erroneos
                                estado.append(
                                    {
                                        "correlativo": kti_ndoc,
                                        "status": "112"
                                    }
                                )
                                errores_line += 1
                                print(f"Rollback linea ya esxitente, linea: {kti_ndoc}")
                                #Se desactivo porque al detectar una linea arriba repetida sustendia todo el proceso, ahora en cambio si hay una repetida la omite
                                conn.rollback()
                                continue
                            else:
                                #Envio de datos a la base de datos
                                queryInl = f"INSERT INTO ke_opmv(kti_tdoc, kti_ndoc, kti_tipprec, kmv_codart, kmv_nombre, kmv_cant, kmv_artprec, kmv_stot) VALUES('{kti_tdoc}', '{kti_ndoc}', '{kti_tipprec}', '{kmv_codart}', '{kmv_nombre}', '{kmv_cant}', '{kmv_artprec}', '{kmv_stot}');"

                                cursor.execute(queryInl)

                                #print(f"Linea ejecutada adecuadamente {kti_ndoc}")
            #Autorizacion para el envio de datos anterior
            if (errores_line == 0) and (errores_head == 0):
                conn.commit()
                print(f"Pedido ejecutado adecuadamente {kti_ndoc}")
                estado.append(
                        {
                            "correlativo": kti_ndoc,
                            "status": "200"
                        }
                    )

        #Cerrado de la conexion
        conn.close()
        #Respuesta del servidor
        return jsonify(estado = estado)
    #Except del Try
    except Exception as ex:
        #Muestra de errores por consola
        print(ex)
        #Rollback y descarte de los datos
        conn.rollback()
        estado.append(
            {
                "correlativo": "0",
                "status": "400"
            }
        )
        #Respuesta del servidor
        return jsonify(estado = estado)

## inserción de Pedidos
# @app.route('/pedido', methods = ['POST'])
# def guardar_pedido():
#     #Conexión con la base de datos
#     conn = mydb()
#     # Cancelar enviado automático
#     conn.autocommit = False
#     #Inicialización de la variable que cuenta errores
#     estado = []

    
#     #Inicio del Try Except
#     try:
#         #Llamado de los datos del JSON
#         if request.json['Pedido'] == None or request.json['Pedido'] == [] or request.json['Pedido'] == [{}]:
#             estado.append(
#                 {
#                     "correlativo": "0",
#                     "status": "405"
#                 }
#             )
#             return jsonify(estado = estado)
#         Pedidos = request.json['Pedido']
#         #For para desencapsular el JSON
#         for Pedido in Pedidos:
#             errores_line = 0
#             errores_head = 0
#             #Diccionario de la cabecera
#             if Pedido['Cabecera'] == None or Pedido['Cabecera'] == {}:
#                 estado.append(
#                     {
#                         "correlativo": "0",
#                         "status": "406"
#                     }
#                 )
#                 errores_head = 1
#                 print(f"Rollback cabecera inexistente")
#                 conn.rollback()
#                 continue
#             Cabecera = Pedido['Cabecera']

#             if Cabecera["kti_ndoc"] == None or Cabecera["kti_ndoc"] == '' or Cabecera["kti_tdoc"] == None or Cabecera["kti_tdoc"] == '' or Cabecera["kti_codcli"] == None or Cabecera["kti_codcli"] == '' or Cabecera["kti_nombrecli"] == None or Cabecera["kti_nombrecli"] == '' or Cabecera["kti_codven"] == None or Cabecera["kti_codven"] == '' or Cabecera["kti_docsol"] == None or Cabecera["kti_docsol"] == '' or Cabecera["kti_condicion"] == None or Cabecera["kti_condicion"] == '' or Cabecera["kti_tipprec"] == None or Cabecera["kti_tipprec"] == '' or Cabecera["kti_totneto"] == None or Cabecera["kti_totneto"] == '' or Cabecera["kti_status"] == None or Cabecera["kti_status"] == '' or Cabecera["kti_fchdoc"] == None or Cabecera["kti_fchdoc"] == '' or Cabecera["fechamodifi"] == None or Cabecera["fechamodifi"] == '' or Cabecera["kti_negesp"] == None or Cabecera["kti_negesp"] == '':
#                 kti_ndoc = Cabecera["kti_ndoc"]
#                 estado.append(
#                     {
#                         "correlativo": kti_ndoc,
#                         "status": "407"
#                     }
#                 )
#                 errores_head = 1
#                 print(f"Rollback cabecera por tener un campo vacio")
#                 conn.rollback()
#                 continue
#             #Asignación de variable para cada dato del diccionario
#             kti_ndoc      = Cabecera["kti_ndoc"]
#             kti_tdoc      = Cabecera["kti_tdoc"]
#             kti_codcli    = Cabecera["kti_codcli"]
#             kti_nombrecli = Cabecera["kti_nombrecli"]
#             kti_codven    = Cabecera["kti_codven"]
#             kti_docsol    = Cabecera["kti_docsol"]
#             kti_condicion = Cabecera["kti_condicion"]
#             kti_tipprec   = Cabecera["kti_tipprec"]
#             kti_totneto   = Cabecera["kti_totneto"]
#             kti_status    = Cabecera["kti_status"]
#             kti_fchdoc    = Cabecera["kti_fchdoc"]
#             fechamodifi   = Cabecera["fechamodifi"]
#             kti_negesp    = Cabecera["kti_negesp"]

#             #Inicializacion del cursor y SQL para la validacion de la existencia
#             cursor = conn.cursor()
#             queryVal = f"SELECT COUNT(kti_ndoc) FROM ke_opti WHERE kti_ndoc = '{kti_ndoc}';"
#             cursor.execute(queryVal)

#             pedConteo = cursor.fetchone()
#             #print(f"Valor retornado en cabeceras: {pedConteo[0]}")
#             #Validacion de la existencia
#             if pedConteo[0] > 0:
#                 #Conteo de errores, rollback de los datos y continuacion del ciclo; omicion de datos erroneos
#                 estado.append(
#                     {
#                         "correlativo": kti_ndoc,
#                         "status": "111"
#                     }
#                 )
#                 errores_head = 1
#                 print(f"Rollback Cabecera {kti_ndoc} Por repeticion de correlativo")
#                 conn.rollback()
#                 continue
#             else:
#                 #Envio de datos a la base de datos
#                 queryIn = f"INSERT INTO ke_opti(kti_ndoc, kti_tdoc, kti_codcli, kti_nombrecli, kti_codven, kti_docsol, kti_condicion, kti_tipprec, kti_totneto, kti_status, kti_fchdoc, fechamodifi, kti_negesp) VALUES('{kti_ndoc}', '{kti_tdoc}', '{kti_codcli}', '{kti_nombrecli}', '{kti_codven}', '{kti_docsol}', '{kti_condicion}', '{kti_tipprec}', '{kti_totneto}', '{kti_status}', '{kti_fchdoc}', '{fechamodifi}', '{kti_negesp}');"

#                 cursor.execute(queryIn)

#                 # print(queryIn)
#                 print("Cabecera ejecutada adecuadamente")

#                 if Cabecera['Lineas'] == None or Cabecera['Lineas'] == [] or Cabecera['Lineas'] == [{}]:
#                     estado.append(
#                         {
#                             "correlativo": kti_ndoc,
#                             "status": "408"
#                         }
#                     )
#                     errores_line = 1
#                     print(f"Rollback linea {Cabecera['kti_ndoc']} por no tener lineas")
#                     conn.rollback()
#                     continue
#                 #Inicializacion de la Tupla de las lineas
#                 Lineas = Cabecera['Lineas']

#                 #Descompocicion de la Tupla
#                 for Linea in Lineas:
#                     if errores_line > 0:
#                         continue
#                     else:
#                         #If para validar que el numero de documento tanto en la cabecera como en las lineas sea el correcto
#                         if Linea["kti_ndoc"] != Cabecera["kti_ndoc"]:
#                             print(Linea["kti_ndoc"])
#                             print(Cabecera["kti_ndoc"])
#                             #Conteo de errores, rollback de los datos y continuacion del ciclo; omicion de datos erroneos
#                             estado.append(
#                                 {
#                                     "correlativo": Cabecera["kti_ndoc"],
#                                     "status": "403"
#                                 }
#                             )
#                             errores_line = 1
#                             print(f"Rollback linea {kti_ndoc} 1")
#                             conn.rollback()
#                             continue
#                         else:
#                             if Linea["kti_tdoc"] == None or Linea["kti_tdoc"] == '' or Linea["kti_ndoc"] == None or Linea["kti_ndoc"] == '' or Linea["kti_tipprec"] == None or Linea["kti_tipprec"] == '' or Linea["kmv_codart"] == None or Linea["kmv_codart"] == '' or Linea["kmv_nombre"] == None or Linea["kmv_nombre"] == '' or Linea["kmv_cant"] == None or Linea["kmv_cant"] == '' or Linea["kmv_artprec"] == None or Linea["kmv_artprec"] == '' or Linea["kmv_stot"] == None or Linea["kmv_stot"] == '':
#                                 estado.append(
#                                     {
#                                         "correlativo": Cabecera["kti_ndoc"],
#                                         "status": "409"
#                                     }
#                                 )
#                                 errores_line = 1
#                                 print(f"Rollback linea {Cabecera['kti_ndoc']} por tener un campo vacio")
#                                 conn.rollback()
#                                 continue
#                             #Asignacion de variables de los datos del diccionario de Linea
#                             kti_tdoc    = Linea["kti_tdoc"]
#                             kti_ndoc    = Linea["kti_ndoc"]
#                             kti_tipprec = Linea["kti_tipprec"]
#                             kmv_codart  = Linea["kmv_codart"]
#                             kmv_nombre  = Linea["kmv_nombre"]
#                             kmv_cant    = Linea["kmv_cant"]
#                             kmv_artprec = Linea["kmv_artprec"]
#                             kmv_stot    = Linea["kmv_stot"]

#                             #Inicializacion del cursor y SQL para la validacion de la existencia
#                             cursorl = conn.cursor()
#                             queryValL = f"SELECT COUNT(kmv_codart) FROM ke_opmv WHERE kti_ndoc = '{kti_ndoc}' AND kmv_codart = '{kmv_codart}';"
#                             cursorl.execute(queryValL)
#                             #print("cursor ejecutado en: " + kti_ndoc)
                            
#                             linConteo = cursorl.fetchone()
#                             #print(f"Valor retornado en lineas: {linConteo[0]}")

#                             #Validacion de la existencia
#                             if linConteo[0] > 0:
#                                 #Conteo de errores, rollback de los datos y continuacion del ciclo; omicion de datos erroneos
#                                 estado.append(
#                                     {
#                                         "correlativo": kti_ndoc,
#                                         "status": "112"
#                                     }
#                                 )
#                                 errores_line += 1
#                                 print(f"Rollback linea {kti_ndoc}")
#                                 #Se desactivo porque al detectar una linea arriba repetida sustendia todo el proceso, ahora en cambio si hay una repetida la omite
#                                 #conn.rollback()
#                                 continue
#                             else:
#                                 #Envio de datos a la base de datos
#                                 queryInl = f"INSERT INTO ke_opmv(kti_tdoc, kti_ndoc, kti_tipprec, kmv_codart, kmv_nombre, kmv_cant, kmv_artprec, kmv_stot) VALUES('{kti_tdoc}', '{kti_ndoc}', '{kti_tipprec}', '{kmv_codart}', '{kmv_nombre}', '{kmv_cant}', '{kmv_artprec}', '{kmv_stot}');"

#                                 cursor.execute(queryInl)

#                                 # print(queryInl)
#                                 print("Linea ejecutada adecuadamente")
#             #Autorizacion para el envio de datos anterior
#             if (errores_line == 0) and (errores_head == 0):
#                 estado.append(
#                         {
#                             "correlativo": kti_ndoc,
#                             "status": "200"
#                         }
#                     )

#             #conn.commit()
#         #Cerrado de la conexion
#         conn.close()
#         #Respuesta del servidor
#         with open('data.json', 'w') as file:
#             json.dump(estado, file, indent=4)
#         return jsonify(estado = estado)
#     #Except del Try
#     except Exception as ex:
#         #Muestra de errores por consola
#         print(ex)
#         #Rollback y descarte de los datos
#         conn.rollback()
#         estado.append(
#             {
#                 "correlativo": "0",
#                 "status": "400"
#             }
#         )
#         #Respuesta del servidor
#         with open('data.json', 'w') as file:
#             json.dump(estado, file, indent=4)
#         return jsonify(estado = estado)

@app.route('/pedidos', methods = ['POST'])
def guardar_pedidos():
    conn   = mydb()
    conn.autocommit = False
    
    try:
        
        headers = request.json['Cabecera']
        lines   = request.json['Lineas']
        
           
        for fila in headers:
            kti_ndoc        =  fila["kti_ndoc"]
            kti_codcli      =  fila["kti_codcli"]
            kti_codven      =  fila["kti_codven"]
            kti_docsol      =  fila["kti_docsol"]
            kti_tdoc        =  fila["kti_tdoc"]
            kti_tipprec     =  fila["kti_tipprec"]
            kti_nombrecli   =  fila["kti_nombrecli"]
            kti_totneto     =  fila["kti_totneto"]
            kti_fchdoc      =  fila["kti_fchdoc"]
            kti_status      =  fila["kti_status"]
            kti_fechamodifi =  fila["fechamodifi"]
            kti_negesp      =  fila["kti_negesp"]
            kti_condicion   =  fila["kti_condicion"]

            ## valido que el pedido ya este creado en la bdd
            cursor = conn.cursor()
            queryVal = "SELECT COUNT(kti_ndoc) FROM ke_opti WHERE kti_ndoc = '" + kti_ndoc + "'"
            cursor.execute(queryVal)

            isCreado = 0
            pedConteo = cursor.fetchall()
            for exist in pedConteo:
                isCreado = exist[0]
                print("valor retornado en cabeceras: " + str(isCreado))

                if isCreado > 0:
                    return jsonify( status = "111")
                else:
                    queryIn = """INSERT INTO ke_opti(kti_codcli, kti_codven, kti_docsol, kti_condicion, kti_tdoc, kti_ndoc, kti_tipprec, 
                    kti_nombrecli, kti_totneto, kti_fchdoc, kti_status, fechamodifi, kti_negesp) VALUES('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}',{8},'{9}','{10}','{11}','{12}')""" .format(kti_codcli, kti_codven, kti_docsol,
                    kti_condicion, kti_tdoc,kti_ndoc,kti_tipprec, kti_nombrecli, kti_totneto, kti_fchdoc, kti_status, kti_fechamodifi, kti_negesp)

                    cursor.execute(queryIn) 
        
        for linea in lines:
            
            kti_ndoc   = linea["kti_ndoc"]
            kmv_codart = linea["kmv_codart"]
            kmv_nombre = linea["kmv_nombre"]
            kmv_cant   = linea["kmv_cant"]
            kmv_stot   = linea["kmv_stot"]
            kmv_artprec = linea["kmv_artprec"]
            kti_tdoc = linea["kti_tdoc"]
            kti_tipprec = linea["kti_tipprec"]

            cursorl = conn.cursor()
            queryValL = "SELECT count(kmv_codart) FROM ke_opmv WHERE kti_ndoc =  '" + kti_ndoc + "' AND kmv_codart = '" + kmv_codart + "'"
            cursorl.execute(queryValL)
            print("cursor ejecutado en: " + kti_ndoc)
            
            isCreado = 0
            
            linConteo = cursorl.fetchall()
            for reg in linConteo:
                isCreado = reg[0]
                print("valor retornado en lineas: " + str(isCreado))

                if isCreado > 0:
                     return jsonify(status = "112")
                else:
                    queryInl = """INSERT INTO ke_opmv (kmv_codart, kmv_nombre, kti_tipprec, kmv_cant, kti_tdoc, kti_ndoc, kmv_stot, kmv_artprec) 
                    VALUES ('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}')""" .format(kmv_codart, kmv_nombre, kti_tipprec, kmv_cant, kti_tdoc, kti_ndoc,
                    kmv_stot,kmv_artprec)
                    cursor.execute(queryInl) 
        
      
        conn.commit()
        
        return jsonify(status = "200")
       
    except Exception as ex:
        print(ex)
        conn.rollback()
        
        return jsonify(status = "404")


@app.route('/articulos/<fechamodifi>', methods = ['GET'])
def bajar_articulos(fechamodifi):
    
    try:
        ## query de los articulos simplificado 
        conn   = mydb()
        cursor = conn.cursor()
        sql    = f"SELECT codigo, grupo, subgrupo, nombre, referencia, marca, unidad, existencia, precio1, precio2, precio3, precio4, precio5, precio6, comprometido FROM articulo WHERE fechamodifi > '{fechamodifi}';"
        cursor.execute(sql)
        datos  = cursor.fetchall()
        articulos = []
        for fila in datos:
            articulo = {
            'codigo': fila[0].strip(), 
            'grupo': fila[1].strip(),
            'subgrupo': fila[2].strip(),
            'nombre': fila[3].strip(),
            'referencia': fila[4].strip(),
            'marca': fila[5].strip(),
            'unidad': fila[6].strip(),   
            'existencia': fila[7],
            'precio1': fila[8],
            'precio2': fila[9],
            'precio3': fila[10],
            'precio4': fila[11],
            'precio5': fila[12],
            'precio6': fila[13],
            'comprometido': fila[14]
            }
            
            articulos.append(articulo)
        
        return jsonify(articulos)
        
    except Exception as ex:
        print(ex)
        return jsonify(str(ex))


@app.route('/precobranzas', methods = ['POST'])
def guardar_precobranzas():
        #Conexión con la base de datos
    conn = mydb()
    # Cancelar enviado automático
    conn.autocommit = False
    #Inicialización de la variable que cuenta errores
    estado = []

    
    #Inicio del Try Except
    try:
        #Llamado de los datos del JSON
        Pedidos = request.json['Cobranza']

        with open('cobranza.json', 'a') as file:
            json.dump(Pedidos, file, indent=4)
        #For para desencapsular el JSON
        
        for Pedido in Pedidos:
            errores_line = 0
            errores_head = 0
            #Diccionario de la cabecera
            Cabecera = Pedido['Cabecera']
            

            #Asignación de variable para cada dato del diccionario
            cxcndoc     = Cabecera["cxcndoc"]
            tiporecibo  = Cabecera["tiporecibo"]
            codvend     = Cabecera["codvend"]
            nro_recibo  = Cabecera["nro_recibo"]
            kecxc_id    = Cabecera["kecxc_id"]
            tasadia     = Cabecera["tasadia"]
            fchrecibo   = Cabecera["fchrecibo"]
            clicontesp  = Cabecera["clicontesp"]
            bsneto      = Cabecera["bsneto"]
            bsiva       = Cabecera["bsiva"]
            bsretiva    = Cabecera["bsretiva"]
            bsflete     = Cabecera["bsflete"]
            bstotal     = Cabecera["bstotal"]
            dolneto     = Cabecera["dolneto"]
            doliva      = Cabecera["doliva"]
            dolretiva   = Cabecera["dolretiva"]
            dolflete    = Cabecera["dolflete"]
            doltotal    = Cabecera["doltotal"]
            moneda      = Cabecera["moneda"]
            dctoaplic   = Cabecera["dctoaplic"]
            netocob     = Cabecera["netocob"]
            efectivo    = Cabecera["efectivo"]
            bcoecod     = Cabecera["bcoecod"]
            bcocod      = Cabecera["bcocod"]
            bconombre   = Cabecera["bconombre"]
            fchr_dep    = Cabecera["fchr_dep"]
            bcomonto    = Cabecera["bcomonto"]
            bcoref      = Cabecera["bcoref"]
            edorec      = Cabecera["edorec"]
            fchhr       = Cabecera["fchhr"]
            fchvigen    = Cabecera["fchvigen"]
            bsretflete  = Cabecera["bsretflete"]
            diasvigen   = Cabecera["diasvigen"]
            retmun_sbi  = Cabecera["retmun_sbi"]
            retmun_sbs  = Cabecera["retmun_sbs"]

            

            #Inicializacion del cursor y SQL para la validacion de la existencia
            cursor = conn.cursor()
            queryVal = f"SELECT COUNT(cxcndoc) FROM ke_precobranza WHERE cxcndoc = '{cxcndoc}';"
            cursor.execute(queryVal)

            preConteo = cursor.fetchone()
            print(f"Valor retornado en cabeceras: {preConteo[0]}")
        #     #Validacion de la existencia
            if preConteo[0] > 0:
                #Conteo de errores, rollback de los datos y continuacion del ciclo; omicion de datos erroneos
                estado.append(
                    {
                        "correlativo": cxcndoc,
                        "status": "111"
                    }
                )
                errores_head = 1
                print(f"Rollback Cabecera {cxcndoc} Por repeticion de correlativo")
                conn.rollback()
                continue
            else:
                #Envio de datos a la base de datos
                queryIn = f"INSERT INTO `ke_precobranza`(`cxcndoc`, `tiporecibo`, `codvend`, `nro_recibo`, `kecxc_id`, `tasadia`, `fchrecibo`, `clicontesp`, `bsneto`, `bsiva`, `bsretiva`, `bsflete`, `bstotal`, `dolneto`, `doliva`, `dolretiva`, `dolflete`, `doltotal`, `moneda`, `dctoaplic`, `netocob`, `efectivo`, `bcoecod`, `bcocod`, `bconombre`, `fchr_dep`, `bcomonto`, `bcoref`, `edorec`, `fchhr`, `fchvigen`, `bsretflete`, `diasvigen`, `retmun_sbi`, `retmun_sbs`) VALUES ('{cxcndoc}', '{tiporecibo}', '{codvend}', '{nro_recibo}', '{kecxc_id}', '{tasadia}', '{fchrecibo}', '{clicontesp}', '{bsneto}', '{bsiva}', '{bsretiva}', '{bsflete}', '{bstotal}', '{dolneto}', '{doliva}', '{dolretiva}', '{dolflete}', '{doltotal}', '{moneda}', '{dctoaplic}', '{netocob}', '{efectivo}', '{bcoecod}', '{bcocod}', '{bconombre}', '{fchr_dep}', '{bcomonto}', '{bcoref}', '{edorec}', '{fchhr}', '{fchvigen}', '{bsretflete}', '{diasvigen}', '{retmun_sbi}', '{retmun_sbs}');"

                cursor.execute(queryIn)

                #print(f"Cabecera ejecutada adecuadamente {kti_ndoc}")

                #Inicializacion de la Tupla de las lineas
                Lineas = Cabecera['Lineas']

                #Descompocicion de la Tupla
                for Linea in Lineas:
                    if errores_line > 0:
                        continue
                    else:
                        #If para validar que el numero de documento tanto en la cabecera como en las lineas sea el correcto
                        if Linea["cxcndoc"] != Cabecera["cxcndoc"]:
                            print(f"Rollbak linea: {Linea['cxcndoc']} cabecera: {Cabecera['cxcndoc']}")
                            #Conteo de errores, rollback de los datos y continuacion del ciclo; omicion de datos erroneos
                            estado.append(
                                {
                                    "correlativo": Cabecera["cxcndoc"],
                                    "status": "403"
                                }
                            )
                            errores_line = 1
                            conn.rollback()
                            continue
                        else:

                            #Asignacion de variables de los datos del diccionario de Linea
                            cxcndoc    = Linea["cxcndoc"]
                            agencia    = Linea["agencia"]
                            tipodoc    = Linea["tipodoc"]
                            documento    = Linea["documento"]
                            bscobro    = Linea["bscobro"]
                            prcdsctopp    = Linea["prcdsctopp"]
                            nroret    = Linea["nroret"]
                            fchemiret    = Linea["fchemiret"]
                            bsretiva    = Linea["bsretiva"]
                            refret    = Linea["refret"]
                            nroretfte    = Linea["nroretfte"]
                            fchemirfte    = Linea["fchemirfte"]
                            bsmtofte    = Linea["bsmtofte"]
                            bsretfte    = Linea["bsretfte"]
                            refretfte    = Linea["refretfte"]
                            bsmtoiva    = Linea["bsmtoiva"]
                            retmun_bi    = Linea["retmun_bi"]
                            retmun_cod    = Linea["retmun_cod"]
                            retmun_nro    = Linea["retmun_nro"]
                            retmun_mto    = Linea["retmun_mto"]
                            retmun_fch    = Linea["retmun_fch"]
                            retmun_ref    = Linea["retmun_ref"]
                            diascalc    = Linea["diascalc"]


                            #Inicializacion del cursor y SQL para la validacion de la existencia
                            cursorl = conn.cursor()
                            queryValL = f"SELECT COUNT(documento) FROM ke_precobradocs WHERE cxcndoc = '{cxcndoc}' AND documento = '{documento}';"
                            cursorl.execute(queryValL)
                            
                            #print("cursor ejecutado en: " + kti_ndoc)
                            
                            linConteo = cursorl.fetchone()
                            #print(f"Valor retornado en lineas: {linConteo[0]}")
                            #Validacion de la existencia
                            if linConteo[0] > 0:
                                #Conteo de errores, rollback de los datos y continuacion del ciclo; omicion de datos erroneos
                                estado.append(
                                    {
                                        "correlativo": cxcndoc,
                                        "status": "112"
                                    }
                                )
                                errores_line += 1
                                print(f"Rollback linea ya esxitente, linea: {cxcndoc}")
                                #Se desactivo porque al detectar una linea arriba repetida sustendia todo el proceso, ahora en cambio si hay una repetida la omite
                                conn.rollback()
                                continue
                            else:
                                #Envio de datos a la base de datos
                                queryInl = f"INSERT INTO `ke_precobradocs`(`cxcndoc`, `agencia`, `tipodoc`, `documento`, `bscobro`, `prcdsctopp`, `nroret`, `fchemiret`, `bsretiva`, `refret`, `nroretfte`, `fchemirfte`, `bsmtofte`, `bsretfte`, `refretfte`, `bsmtoiva`, `retmun_bi`, `retmun_cod`, `retmun_nro`, `retmun_mto`, `retmun_fch`, `retmun_ref`, `diascalc`) VALUES ('{cxcndoc}', '{agencia}', '{tipodoc}', '{documento}', '{bscobro}', '{prcdsctopp}', '{nroret}', '{fchemiret}', '{bsretiva}', '{refret}', '{nroretfte}', '{fchemirfte}', '{bsmtofte}', '{bsretfte}', '{refretfte}', '{bsmtoiva}', '{retmun_bi}', '{retmun_cod}', '{retmun_nro}', '{retmun_mto}', '{retmun_fch}', '{retmun_ref}', '{diascalc}');"

                                cursor.execute(queryInl)

                                #print(f"Linea ejecutada adecuadamente {kti_ndoc}")
            #Autorizacion para el envio de datos anterior
            if (errores_line == 0) and (errores_head == 0):
                conn.commit()
                print(f"Cobranza ejecutado adecuadamente {cxcndoc}")
                estado.append(
                        {
                            "correlativo": cxcndoc,
                            "status": "200"
                        }
                    )

        #Cerrado de la conexion
        conn.close()
        #Respuesta del servidor
        return jsonify(estado = estado)
    #Except del Try
    except Exception as ex:
        #Muestra de errores por consola
        print(ex)
        #Rollback y descarte de los datos
        conn.rollback()
        estado.append(
            {
                "correlativo": "0",
                "status": "400"
            }
        )
        #Respuesta del servidor
        return jsonify(estado = estado)


@app.route('/precobranzas2', methods = ['POST'])
def guardar_precobranzas2():
        #Conexión con la base de datos
    conn = mydb()
    # Cancelar enviado automático
    conn.autocommit = False
    #Inicialización de la variable que cuenta errores
    estado = []

    
    #Inicio del Try Except
    try:
        #Llamado de los datos del JSON
        Pedidos = request.json['Cobranza']

        with open('cobranza.json', 'a') as file:
            json.dump(Pedidos, file, indent=4)
        #For para desencapsular el JSON
        
        for Pedido in Pedidos:
            errores_line = 0
            errores_head = 0
            #Diccionario de la cabecera
            Cabecera = Pedido['Cabecera']
            

            #Asignación de variable para cada dato del diccionario
            cxcndoc     = Cabecera["cxcndoc"]
            tiporecibo  = Cabecera["tiporecibo"]
            codvend     = Cabecera["codvend"]
            nro_recibo  = Cabecera["nro_recibo"]
            kecxc_id    = Cabecera["kecxc_id"]
            tasadia     = Cabecera["tasadia"]
            fchrecibo   = Cabecera["fchrecibo"]
            clicontesp  = Cabecera["clicontesp"]
            bsneto      = Cabecera["bsneto"]
            bsiva       = Cabecera["bsiva"]
            bsretiva    = Cabecera["bsretiva"]
            bsflete     = Cabecera["bsflete"]
            bstotal     = Cabecera["bstotal"]
            dolneto     = Cabecera["dolneto"]
            doliva      = Cabecera["doliva"]
            dolretiva   = Cabecera["dolretiva"]
            dolflete    = Cabecera["dolflete"]
            doltotal    = Cabecera["doltotal"]
            moneda      = Cabecera["moneda"]
            docdifcamb  = Cabecera["docdifcamb"]
            ddc_age     = Cabecera["ddc_age"]
            ddc_tipo    = Cabecera["ddc_tipo"]
            ddc_montobs = Cabecera["ddc_montobs"]
            ddc_doc     = Cabecera["ddc_doc"]
            dctoaplic   = Cabecera["dctoaplic"]
            netocob     = Cabecera["netocob"]
            concepto    = Cabecera["concepto"]
            efectivo    = Cabecera["efectivo"]
            bcoecod     = Cabecera["bcoecod"]
            bcocod      = Cabecera["bcocod"]
            bconombre   = Cabecera["bconombre"]
            fchr_dep    = Cabecera["fchr_dep"]
            bcomonto    = Cabecera["bcomonto"]
            bcoref      = Cabecera["bcoref"]
            pidvalid    = Cabecera["pidvalid"]
            edorec      = Cabecera["edorec"]
            edocomiv    = Cabecera["edocomiv"]
            prccomiv    = Cabecera["prccomiv"]
            mtocomiv    = Cabecera["mtocomiv"]
            fchr_pcomv  = Cabecera["fchr_pcomv"]
            codcoord    = Cabecera["codcoord"]
            edocomic    = Cabecera["edocomic"]
            prccomic    = Cabecera["prccomic"]
            mtocomic    = Cabecera["mtocomic"]
            fchr_pcomc  = Cabecera["fchr_pcomc"]
            fchhr       = Cabecera["fchhr"]
            fchvigen    = Cabecera["fchvigen"]
            bsretflete  = Cabecera["bsretflete"]
            diasvigen   = Cabecera["diasvigen"]
            retmun_sbi  = Cabecera["retmun_sbi"]
            retmun_sbs  = Cabecera["retmun_sbs"]
            comiaut     = Cabecera["comiaut"]
            comiautpor  = Cabecera["comiautpor"]
            comiautfch  = Cabecera["comiautfch"]
            reci_age    = Cabecera["reci_age"]
            reci_doc    = Cabecera["reci_doc"]
            status      = Cabecera["status"]
            fechamodifi = Cabecera["fechamodifi"]
            cxcndoc_aux = Cabecera["cxcndoc_aux"]

            print(bsretiva + "1")

            #Inicializacion del cursor y SQL para la validacion de la existencia
            cursor = conn.cursor()
            queryVal = f"SELECT COUNT(cxcndoc) FROM ke_precobranza WHERE cxcndoc = '{cxcndoc}';"
            cursor.execute(queryVal)

            preConteo = cursor.fetchone()
            print(f"Valor retornado en cabeceras: {preConteo[0]}")
        #     #Validacion de la existencia
            if preConteo[0] > 0:
                #Conteo de errores, rollback de los datos y continuacion del ciclo; omicion de datos erroneos

                cursor = conn.cursor()
                queryVal = f"SELECT fechamodifi FROM ke_precobranza WHERE cxcndoc = '{cxcndoc}';"
                cursor.execute(queryVal)

                fch = cursor.fetchone()

                if fch[0] != fechamodifi:
                    mycursor = conn.cursor()
                    queryVal = f"UPDATE ke_precobranza SET reci_doc = '{reci_doc}', fechamodifi = '{fechamodifi}', edorec = {edorec}, status = {0} WHERE cxcndoc = '{cxcndoc}';"
                    mycursor.execute(queryVal)
                    print(f"Actualizada correctamente {cxcndoc}")

                else :
                    estado.append(
                        {
                            "correlativo": cxcndoc,
                            "status": "111"
                        }
                    )
                    errores_head = 1
                    print(f"Rollback Cabecera {cxcndoc} Por repeticion de correlativo")
                    conn.rollback()
                    continue

            else:
                #Envio de datos a la base de datos
                queryIn = f"INSERT INTO `ke_precobranza`(`cxcndoc`, `tiporecibo`, `codvend`, `nro_recibo`, `kecxc_id`, `tasadia`, `fchrecibo`, `clicontesp`, `bsneto`, `bsiva`, `bsretiva`, `bsflete`, `bstotal`, `dolneto`, `doliva`, `dolretiva`, `dolflete`, `doltotal`, `moneda`, `docdifcamb`, `ddc_age`, `ddc_tipo`, `ddc_montobs`, `ddc_doc`, `dctoaplic`, `netocob`, `concepto`, `efectivo`, `bcoecod`, `bcocod`, `bconombre`, `fchr_dep`, `bcomonto`, `bcoref`, `pidvalid`, `edorec`, `edocomiv`, `prccomiv`, `mtocomiv`, `fchr_pcomv`, `codcoord`, `edocomic`, `prccomic`, `mtocomic`, `fchr_pcomc`, `fchhr`, `fchvigen`, `bsretflete`, `diasvigen`, `retmun_sbi`, `retmun_sbs`, `comiaut`, `comiautpor`, `comiautfch`, `reci_age`, `reci_doc`, `status`, `fechamodifi`, `cxcndoc_aux`) VALUES ('{cxcndoc}', '{tiporecibo}', '{codvend}', '{nro_recibo}', '{kecxc_id}', '{tasadia}', '{fchrecibo}', '{clicontesp}', '{bsneto}', '{bsiva}', '{bsretiva}', '{bsflete}', '{bstotal}', '{dolneto}', '{doliva}', '{dolretiva}', '{dolflete}', '{doltotal}', '{moneda}', '{docdifcamb}', '{ddc_age}', '{ddc_tipo}', '{ddc_montobs}', '{ddc_doc}', '{dctoaplic}', '{netocob}', '{concepto}', '{efectivo}', '{bcoecod}', '{bcocod}', '{bconombre}', '{fchr_dep}', '{bcomonto}', '{bcoref}', '{pidvalid}', '{edorec}', '{edocomiv}', '{prccomiv}', '{mtocomiv}', '{fchr_pcomv}', '{codcoord}', '{edocomic}', '{prccomic}', '{mtocomic}', '{fchr_pcomc}', '{fchhr}', '{fchvigen}', '{bsretflete}', '{diasvigen}', '{retmun_sbi}', '{retmun_sbs}', '{comiaut}', '{comiautpor}', '{comiautfch}', '{reci_age}', '{reci_doc}', '{status}', '{fechamodifi}', '{cxcndoc_aux}');"

                cursor.execute(queryIn)

                #print(f"Cabecera ejecutada adecuadamente {kti_ndoc}")

                #Inicializacion de la Tupla de las lineas
                Lineas = Cabecera['Lineas']

                #Descompocicion de la Tupla
                for Linea in Lineas:
                    if errores_line > 0:
                        continue
                    else:
                        #If para validar que el numero de documento tanto en la cabecera como en las lineas sea el correcto
                        if Linea["cxcndoc"] != Cabecera["cxcndoc"]:
                            print(f"Rollbak linea: {Linea['cxcndoc']} cabecera: {Cabecera['cxcndoc']}")
                            #Conteo de errores, rollback de los datos y continuacion del ciclo; omicion de datos erroneos
                            estado.append(
                                {
                                    "correlativo": Cabecera["cxcndoc"],
                                    "status": "403"
                                }
                            )
                            errores_line = 1
                            conn.rollback()
                            continue
                        else:

                            #Asignacion de variables de los datos del diccionario de Linea
                            cxcndoc     = Linea["cxcndoc"]
                            agencia     = Linea["agencia"]
                            tipodoc     = Linea["tipodoc"]
                            documento   = Linea["documento"]
                            bscobro     = Linea["bscobro"]
                            prccobro    = Linea["prccobro"]
                            prcdsctopp  = Linea["prcdsctopp"]
                            nroret      = Linea["nroret"]
                            fchemiret   = Linea["fchemiret"]
                            bsretiva    = Linea["bsretiva"]
                            refret      = Linea["refret"]
                            nroretfte   = Linea["nroretfte"]
                            fchemirfte  = Linea["fchemirfte"]
                            bsmtofte    = Linea["bsmtofte"]
                            bsretfte    = Linea["bsretfte"]
                            refretfte   = Linea["refretfte"]
                            pidvalid    = Linea["pidvalid"]
                            bsmtoiva    = Linea["bsmtoiva"]
                            retmun_bi   = Linea["retmun_bi"]
                            retmun_cod  = Linea["retmun_cod"]
                            retmun_nro  = Linea["retmun_nro"]
                            retmun_mto  = Linea["retmun_mto"]
                            retmun_fch  = Linea["retmun_fch"]
                            retmun_ref  = Linea["retmun_ref"]
                            diascalc    = Linea["diascalc"]
                            prccomiv    = Linea["prccomiv"]
                            prccomic    = Linea["prccomic"]
                            cxcndoc_aux = Linea["cxcndoc_aux"]
                            tnetodbs    = Linea["tnetodbs"]
                            tnetoddol   = Linea["tnetoddol"]
                            fchrecibod  = Linea["fchrecibod"]
                            kecxc_idd   = Linea["kecxc_idd"]
                            tasadiad    = Linea["tasadiad"]
                            afavor      = Linea["afavor"]

                            #Inicializacion del cursor y SQL para la validacion de la existencia
                            cursorl = conn.cursor()
                            queryValL = f"SELECT COUNT(documento) FROM ke_precobradocs WHERE cxcndoc = '{cxcndoc}' AND documento = '{documento}';"
                            #print(f"SELECT COUNT(documento) FROM ke_precobradocs WHERE cxcndoc = '{cxcndoc}' AND documento = '{documento}';")
                            cursorl.execute(queryValL)
                            
                            #print("cursor ejecutado en: " + kti_ndoc)
                            
                            linConteo = cursorl.fetchone()
                            #print(f"Valor retornado en lineas: {linConteo[0]}")
                            #Validacion de la existencia
                            #Si existe en una cobranzas dentro de sus lineas el mismo documento y es un tipo W es malo, pero de ser un D es bueno
                            if (linConteo[0] > 0) and (tiporecibo == "W"):
                                #Conteo de errores, rollback de los datos y continuacion del ciclo; omicion de datos erroneos
                                estado.append(
                                    {
                                        "correlativo": cxcndoc,
                                        "status": "112"
                                    }
                                )
                                errores_line += 1
                                print(f"Rollback linea ya esxitente, linea: {cxcndoc}")
                                #Se desactivo porque al detectar una linea arriba repetida sustendia todo el proceso, ahora en cambio si hay una repetida la omite
                                conn.rollback()
                                continue
                            else:
                                #Envio de datos a la base de datos
                                queryInl = f"INSERT INTO `ke_precobradocs`(`cxcndoc`, `agencia`, `tipodoc`, `documento`, `bscobro`, `prccobro`, `prcdsctopp`, `nroret`, `fchemiret`, `bsretiva`, `refret`, `nroretfte`, `fchemirfte`, `bsmtofte`, `bsretfte`, `refretfte`, `pidvalid`, `bsmtoiva`, `retmun_bi`, `retmun_cod`, `retmun_nro`, `retmun_mto`, `retmun_fch`, `retmun_ref`, `diascalc`, `prccomiv`, `prccomic`, `cxcndoc_aux`, `tnetodbs`, `tnetoddol`, `fchrecibod`, `kecxc_idd`, `tasadiad`, `afavor`) VALUE ('{cxcndoc}', '{agencia}', '{tipodoc}', '{documento}', '{bscobro}', '{prccobro}', '{prcdsctopp}', '{nroret}', '{fchemiret}', '{bsretiva}', '{refret}', '{nroretfte}', '{fchemirfte}', '{bsmtofte}', '{bsretfte}', '{refretfte}', '{pidvalid}', '{bsmtoiva}', '{retmun_bi}', '{retmun_cod}', '{retmun_nro}', '{retmun_mto}', '{retmun_fch}', '{retmun_ref}', '{diascalc}', '{prccomiv}', '{prccomic}', '{cxcndoc_aux}', '{tnetodbs}', '{tnetoddol}', '{fchrecibod}', '{kecxc_idd}', '{tasadiad}', '{afavor}');"

                                cursor.execute(queryInl)

                                #print(f"Linea ejecutada adecuadamente {kti_ndoc}")
            #Autorizacion para el envio de datos anterior
            if (errores_line == 0) and (errores_head == 0):
                conn.commit()
                print(f"Cobranza ejecutado adecuadamente {cxcndoc}")
                estado.append(
                        {
                            "correlativo": cxcndoc,
                            "status": "200"
                        }
                    )

        #Cerrado de la conexion
        conn.close()
        #Respuesta del servidor
        return jsonify(estado = estado)
    #Except del Try
    except Exception as ex:
        #Muestra de errores por consola
        print(ex)
        #Rollback y descarte de los datos
        conn.rollback()
        estado.append(
            {
                "correlativo": "0",
                "status": "400"
            }
        )
        #Respuesta del servidor
        return jsonify(estado = estado)

@app.route('/precobranza', methods = ['POST'])
def guardar_precobranza():
        
        conn   = mydb()    
        conn.autocommit = False
        try:
            ## obtengo el json completo
            datos   = request.data
            headers = request.json['Cabecera']
            lines   = request.json['Lineas']

           

            for fila in headers:
                cxcndoc     =  fila["cxcndoc"]
                tiporecibo  =  fila["tiporecibo"]
                codvend     =  fila["codvend"]
                nro_recibo  =  fila["nro_recibo"]
                kecxc_id    =  fila["kecxc_id"]
                tasadia     =  fila["tasadia"]
                fchrecibo   =  fila["fchrecibo"]
                clicontesp  =  fila["clicontesp"]
                bsneto      =  fila["bsneto"]
                bsiva       =  fila["bsiva"]
                bsretiva    =  fila["bsretiva"]
                bsflete     =  fila["bsflete"]
                bstotal     =  fila["bstotal"]
                dolneto     =  fila["dolneto"]
                doliva      =  fila["doliva"]
                dolretiva   =  fila["dolretiva"]
                dolflete    =  fila["dolflete"]
                doltotal    =  fila["doltotal"]
                moneda      =  fila["moneda"]
                dctoaplic   =  fila["dctoaplic"]
                netocob     =  fila["netocob"]
                efectivo    =  fila["efectivo"]
                bcoecod     =  fila["bcoecod"]
                bcocod      =  fila["bcocod"]
                bconombre   =  fila["bconombre"]
                fchr_dep    =  fila["fchr_dep"]
                bcomonto    =  fila["bcomonto"]	
                bcoref      =  fila["bcoref"]
                edorec      =  fila["edorec"]
                fchhr	    =  fila["fchhr"]
                fchvigen    =  fila["fchvigen"]
                bsretflete  =  fila["bsretflete"]
                diasvigen   =  fila["diasvigen"]
                retmun_sbi  =  fila["retmun_sbi"]	
                retmun_sbs  =  fila["retmun_sbs"]


                ## valido que el recibo ya se encuentra creado
                cursor = conn.cursor()
                queryVal = "SELECT COUNT(cxcndoc) FROM ke_precobranza WHERE cxcndoc = '" + cxcndoc + "'"
                cursor.execute(queryVal)     

                isCreado = 0
                recCreado = cursor.fetchall()      
                
                for reg in recCreado:
                    isCreado = reg[0]
                    if isCreado > 0:
                        return jsonify(status = "111")
                    else:
                        queryIn = f"INSERT INTO ke_precobranza(cxcndoc, tiporecibo, codvend, nro_recibo, kecxc_id, tasadia, fchrecibo, clicontesp, bsneto, bsiva, bsretiva, bsflete, bstotal, dolneto, doliva, dolretiva, dolflete, doltotal, moneda, dctoaplic, netocob, efectivo, bcoecod, bcocod, bconombre, fchr_dep, bcomonto, bcoref, edorec, fchhr, fchvigen, bsretflete, diasvigen, retmun_sbi, retmun_sbs) VALUES('{cxcndoc}', '{tiporecibo}', '{codvend}', '{nro_recibo}', '{kecxc_id}', '{tasadia}', '{fchrecibo}', '{clicontesp}', '{bsneto}', '{bsiva}', '{bsretiva}', '{bsflete}', '{bstotal}', '{dolneto}', '{doliva}', '{dolretiva}', '{dolflete}', '{doltotal}', '{moneda}', '{dctoaplic}', '{netocob}', '{efectivo}', '{bcoecod}', '{bcocod}', '{bconombre}', '{fchr_dep}', '{bcomonto}', '{bcoref}', '{edorec}', '{fchhr}', '{fchvigen}', '{bsretflete}', '{diasvigen}', '{retmun_sbi}', '{retmun_sbs}');"
                        # {34} coma de mas
                        cursor.execute(queryIn)

            for linea in lines:
                ## cargo los elementos que vienen de las lineas  
                cxcndoc     = linea["cxcndoc"]
                agencia     = linea["agencia"]
                tipodoc     = linea["tipodoc"]
                documento   = linea["documento"]
                bscobro     = linea["bscobro"]
                prcdsctopp  = linea["prcdsctopp"]
                nroret      = linea["nroret"]
                fchemiret   = linea["fchemiret"]
                bsretiva    = linea["bsretiva"]
                refret      = linea["refret"]
                nroretfte   = linea["nroretfte"]
                fchemirfte  = linea["fchemirfte"]
                bsmtofte    = linea["bsmtofte"]
                bsretfte    = linea["bsretfte"]
                refretfte   = linea["refretfte"]
                bsmtoiva    = linea["bsmtoiva"]
                retmun_bi   = linea["retmun_bi"]
                retmun_cod  = linea["retmun_cod"]
                retmun_nro  = linea["retmun_nro"]
                retmun_mto  = linea["retmun_mto"]
                retmun_fch	= linea["retmun_fch"]
                retmun_ref  = linea["retmun_ref"]	
                diascalc	= linea["diascalc"]
                
                ## valido que el documento en el recibo no se repita con los mismos datos
                cursor = conn.cursor()
                queryVal = "SELECT COUNT(documento) FROM ke_precobradocs WHERE cxcndoc = '" + cxcndoc + "' AND documento ='" + documento + "'"
                cursor.execute(queryVal)     

                isCreado = 0
                recdocCreado = cursor.fetchall()

                for reg in recdocCreado:
                    isCreado = reg[0]
                    if isCreado > 0:
                        return jsonify(status = "112")
                    else:
                        queryIn = f"INSERT INTO ke_precobradocs(cxcndoc, agencia, tipodoc, documento, bscobro, prcdsctopp, nroret, fchemiret, bsretiva, refret, nroretfte, fchemirfte, bsmtofte, bsretfte, refretfte, bsmtoiva, retmun_bi, retmun_cod, retmun_nro, retmun_mto, retmun_fch, retmun_ref, diascalc) VALUES('{cxcndoc}', '{agencia}', '{tipodoc}', '{documento}', '{bscobro}', '{prcdsctopp}', '{nroret}', '{fchemiret}', '{bsretiva}', '{refret}', '{nroretfte}', '{fchemirfte}', '{bsmtofte}', '{bsretfte}', '{refretfte}', '{bsmtoiva}', '{retmun_bi}', '{retmun_cod}', '{retmun_nro}', '{retmun_mto}', '{retmun_fch}', '{retmun_ref}', '{diascalc}');"

                        cursor.execute(queryIn)

                    
            conn.commit()
            return jsonify(status = "200")

        except Exception as ex:
            print(str(ex))
            conn.rollback()
            return jsonify(status = "404")


@app.route('/coordinadores', methods = ['GET'])
def bajar_coordinadores():
        try:
        ## query de los articulos simplificado 
            conn   = mydb()
            cursor = conn.cursor()
            sql    = f"SELECT `ke_estadc01`.* FROM `ke_estadc01` INNER JOIN `listvend` ON `ke_estadc01`.`vendedor` = `listvend`.`codigo` WHERE `listvend`.`status` = '1';"
            cursor.execute(sql)
            datos  = cursor.fetchall()
            estadisticas = []
            for fila in datos:
                estadistica = {
                'codcoord': fila[0].strip(), 
                'nomcoord': fila[1].strip(), 
                'vendedor': fila[2].strip(), 
                'nombrevend': fila[3].strip(), 
                'cntpedidos': fila[4], 
                'mtopedidos': round(fila[5]*100)/100, 
                'cntfacturas': fila[6], 
                'mtofacturas': round(fila[7]*100)/100, 
                'metavend': fila[8], 
                'prcmeta': fila[9], 
                'cntclientes': fila[10], 
                'clivisit': fila[11], 
                'prcvisitas': round(fila[12]*100)/100, 
                'lom_montovtas': fila[13], 
                'lom_prcvtas': fila[14], 
                'lom_prcvisit': fila[15], 
                'rlom_montovtas': fila[16], 
                'rlom_prcvtas': fila[17], 
                'rlom_prcvisit': fila[18], 
                'fecha_estad': fila[19].strftime("%d/%m/%Y"), 
                'ppgdol_totneto': round(fila[20]*100)/100, 
                'devdol_totneto': round(fila[21]*100)/100, 
                'defdol_totneto':round(fila[22]*100)/100, 
                'totdolcob': fila[23]
                }
                
                estadisticas.append(estadistica)
            
            return jsonify(estadisticas)

            return datos
        
        except Exception as ex:
            print(ex)
            return jsonify(str(ex))
            
@app.route('/tasas', methods = ['GET'])
def bajar_tasas():
    try:
        conn   = mydb()
        cursor = conn.cursor()
        sql    = f"SELECT * FROM `kecxc_tasas` ORDER BY `kecxc_tasas`.`kecxc_fecha` DESC LIMIT 1;"
        cursor.execute(sql)
        datos  = cursor.fetchall()
        tasas = []
        for fila in datos:
            tasa = {
            'kecxc_id': fila[0].strip(), 
            'kecxc_fecha': fila[1].strftime("%d/%m/%y"),
            'kecxc_tasa': fila[2],
            'kecxc_usuario': fila[3].strip(),
            'kecxc_ip': fila[4].strip(),
            'kecxc_fchyhora': fila[5].strftime("%d/%m/%y %H:%M:%S"),
            'fechamodifi': fila[6].strftime("%d/%m/%y %H:%M:%S"),
            'kecxc_tasaib': fila[7]
            }
            
            tasas.append(tasa)
        
        return jsonify(tasas)

    except Exception as ex:
        print(ex)
        return jsonify(str(ex))

        
@app.route('/sincroonizacion', methods = ['POST'])
def guardar_sincroonizacion():
    #Conexión con la base de datos
    conn = mydb()
    # Cancelar enviado automático
    conn.autocommit = False
    #Inicialización de la variable que cuenta errores
    estado = []

    
    #Inicio del Try Except
    try:
        #Llamado de los datos del JSON
        Sincroonizacion = request.json['sincroonizacion']

        Usuario = Sincroonizacion['usuario']
        Fecha = Sincroonizacion['fecha']
        Version = Sincroonizacion['version']

        cursor = conn.cursor()
        sql = f"UPDATE usuarios SET ult_sinc = '{Fecha}', version = '{Version}' WHERE vendedor = '{Usuario}';"
        print(sql)
        cursor.execute(sql)

        conn.commit()
        #Cerrado de la conexion
        conn.close()

        estado = {
            "status": 200,
            "usuario": Usuario,
        }
            
        
        #Respuesta del servidor
        return jsonify(estado = estado)
    #Except del Try
    except Exception as ex:
        print(ex)
        estado = {
            "status": 404,
            "usuario": 0,
        }
        return jsonify(estado = estado)
    


@app.route("/login",  methods = ['POST'])
def login():
    #Conexión con la base de datos
    conn = mydb()
    # Cancelar enviado automático
    conn.autocommit = False
    #Inicialización de la variable que cuenta errores
    estado = []

    #Inicio del Try Except
    try:
        #Llamado de los datos del JSON
        Login = request.json['Login']

        vendedor = Login['vendedor']
        sesion = Login['sesion']

        cursor = conn.cursor()

        queryIn = f"UPDATE `usuarios` SET `sesion`='{sesion}' WHERE `vendedor` = '{vendedor}';"

        cursor.execute(queryIn)

        conn.commit()
        #Cerrado de la conexion
        conn.close()

        estado = {
            "status": 200,
            "usuario": vendedor,
        }
            
        
        #Respuesta del servidor
        return jsonify(estado = estado)

    except Exception as ex:
        print(ex)
        estado = {
            "status": 404,
            "usuario": 0,
        }
        return jsonify(estado = estado)




######################################################### DESPACHO#########################################################################################
@app.route("/despacho_fecha", methods = ['POST'])
def despachoFecha():
    #Conexión con la base de datos
    conn = mydbDespacho()
    # Cancelar enviado automático
    conn.autocommit = False
    #Inicialización de la variable que cuenta errores
    estado = []

    #Inicio del Try Except
    try:
        #Llamado de los datos del JSON
        Despachos = request.json['Despacho']

        
        
        
        for Despacho in Despachos:
            errores = 0
            #Diccionario de la cabecera
            Datos = Despacho['Datos']
            print(Datos)
            

            #Asignación de variable para cada dato del diccionario
            print(Datos["DPFA_agencia"])
            DPFA_agencia         = Datos["DPFA_agencia"]
            DPFA_tipodoc         = Datos["DPFA_tipodoc"]
            DPFA_documento       = Datos["DPFA_documento"]
            DPFA_FchEntrega      = Datos["DPFA_FchEntrega"]
            DPFA_geolocalizacion = Datos["DPFA_geolocalizacion"]
            DPFA_Latitud         = Datos["DPFA_Latitud"]
            DPFA_Longitud        = Datos["DPFA_Longitud"]
            DPFA_notas           = Datos["DPFA_notas"]
            DPFA_Status          = Datos["DPFA_Status"]
            

            #Inicializacion del cursor y SQL para la validacion de la existencia
            cursor = conn.cursor()
            queryVal = f"SELECT COUNT(DPFA_documento) FROM DP_FechasActualizadas WHERE DPFA_documento = '{DPFA_documento}';"
            cursor.execute(queryVal)

            preConteo = cursor.fetchone()
            print(f"Valor retornado en cabeceras: {preConteo[0]}")
        #     #Validacion de la existencia
            if preConteo[0] > 0:
                #Conteo de errores, rollback de los datos y continuacion del ciclo; omicion de datos erroneos

                estado.append(
                    {
                        "documento": DPFA_documento,
                        "status": "111"
                    }
                )
                errores = 1
                print(f"Rollback documento {DPFA_documento} por repeticion")
                conn.rollback()
                continue

            else:
                #Envio de datos a la base de datos
                queryIn = f"INSERT INTO `DP_FechasActualizadas`(`DPFA_agencia`, `DPFA_tipodoc`, `DPFA_documento`, `DPFA_FchEntrega`, `DPFA_geolocalizacion`, `DPFA_Latitud`, `DPFA_Longitud`, `DPFA_notas`, `DPFA_Status`) VALUES ('{DPFA_agencia}', '{DPFA_tipodoc}', '{DPFA_documento}', '{DPFA_FchEntrega}', '{DPFA_geolocalizacion}', '{DPFA_Latitud}', '{DPFA_Longitud}', '{DPFA_notas}', '{DPFA_Status}');"

                cursor.execute(queryIn)
            #Autorizacion para el envio de datos anterior
            if (errores == 0):
                conn.commit()
                print(f"Cobranza ejecutado adecuadamente {DPFA_documento}")
                estado.append(
                        {
                            "correlativo": DPFA_documento,
                            "status": "200"
                        }
                    )

        #Cerrado de la conexion
        conn.close()
        #Respuesta del servidor
        return jsonify(estado = estado)
    #Except del Try
    except Exception as ex:
        #Muestra de errores por consola
        print(ex)
        #Rollback y descarte de los datos
        conn.rollback()
        estado.append(
            {
                "correlativo": "0",
                "status": "400"
            }
        )
        #Respuesta del servidor
        return jsonify(estado = estado)




def pagina_no_encontrada(error):
    return "<h1>Esta página no existe</h1>"

#Corrido de la Aplicación
if __name__ == '__main__':
    app.register_error_handler(404, pagina_no_encontrada)
    app.config['JSON_AS_ASCII'] = False
    app.run(debug=True, port=5001)
