Inicio > Contabilidad, Programing > Administrar la recepción de CFD/CFDI – Script que lee XML de un Comprobante Fistal Digital

Administrar la recepción de CFD/CFDI – Script que lee XML de un Comprobante Fistal Digital


Esta nota surge de una idea orginal AdanGQ y su nota original se puede consulta en El Arte de Programar, Administrar la recepción de CFD/CFDi y que a petición de el en un twit de crear una versión usando Python, no he logrando no participar… esto era casi irresistible… el código en python claro!

Y el resultado es el que muestro a continuación y lo he creado usando funciones estandar para que funcione en la mayoría de las plataforma!

#!/usr/bin/env python
# -*- coding: utf-8 -*-

###############################################################################
# ADMINCFD - Administra archivos de CFD
# Autor: Ricardo Torres
# email: rictor@cuhrt.com
# blog: htpp://rctorr.wordpress.com
# twitter: @rctorr
#
# Descripción
# Este script ayuda a leer un CFD para despues formatear el nombre del archivo
# de la siguiente manera:
#    Fecha_RFCemisor_serie_folio_subtotal_iva_total.xml
#
# Fecha: Fecha en que se generó el comprobante
# RFCemisor: RFC de quien emite el cfd/cfdi
# Serie y Folio: Numero de Serie y folio de la factura
# Subtotal, iva, total: Importes de la factura.
#
# El nombre del xml se proporciona desde la línea de comandos, de tal forma que
# se puede usar en algún otro script para automatizar el proceso.
#
###############################################################################

# Ver 1.0
# - Se lee el nombre del archivo desde la línea de comando
# - Se leer los atributos del archivo xml
# - Genera el nombre con la sintaxis solicitada
# - Renombra el archivo xml al nuevo nombre
#

import sys
import os.path
import datetime
import os
from optparse import OptionParser
import ConfigParser
from xml.dom import minidom

class XmlCFD(object):
    """
       Esta clase se encarga de realizar todas las operaciones relacionadas
       con la manipulación del archivo xml de facturación electrónica
    """
    nomFileXml = ''

    def __init__(self, nomFileXml):
        """ Initialize instance. """
        self.nomFileXml = nomFileXml
        self.atributos = dict()

    def getAtributos(self):
        """ Regresa los atributos necesario para formar el nombre del archivo. """

        if os.path.isfile(self.nomFileXml):
            xmlDoc = minidom.parse(self.nomFileXml)
            nodes = xmlDoc.childNodes
            comprobante = nodes[0]

            compAtrib = dict(comprobante.attributes.items())
            self.atributos['serie'] = compAtrib['serie']
            self.atributos['folio'] = compAtrib['folio']
            # Se trunca la parte de la hora de emisión
            self.atributos['fecha'] = compAtrib['fecha'][:10]
            self.atributos['total'] = compAtrib['total'].rjust(10,'0')
            self.atributos['subTotal'] = compAtrib['subTotal'].rjust(10,'0')

            emisor = comprobante.getElementsByTagName('Emisor')
            self.atributos['rfc'] = emisor[0].getAttribute('rfc')
            self.atributos['nombre'] = emisor[0].getAttribute('nombre')

            impuestos = comprobante.getElementsByTagName('Impuestos')
            self.atributos['iva'] = impuestos[0].getAttribute('totalImpuestosTrasladados').rjust(10,'0')

        return self.atributos

    def rename(self):
        """ Renombra el archivo xml de la forma:
                Fecha_RFCemisor_serie_folio_subtotal_iva_total.xml

            Regresa el nuevo nombre del archivo
        """

        self.getAtributos()

        nomFileXmlNew = self.atributos['fecha']
        nomFileXmlNew = '_'+self.atributos['rfc']
        nomFileXmlNew += '_'+self.atributos['serie']
        nomFileXmlNew += '_'+self.atributos['folio']
        nomFileXmlNew += '_'+self.atributos['subTotal']
        nomFileXmlNew += '_'+self.atributos['iva']
        nomFileXmlNew += '_'+self.atributos['total']
        nomFileXmlNew += '.xml'

        os.rename(self.nomFileXml, nomFileXmlNew)

        return nomFileXmlNew

def main(argv):

    usage = "%prog [opciones] archivocfd.xml"
    add_help_option = False
    parser = OptionParser(usage=usage, add_help_option,add_help_option)
    parser.add_option("-h", "--help", action="help",
         help=u"muestra este mensaje de ayuda y termina")
    (options, args) = parser.parse_args()

    if len(args) == 0:
        parser.error("Se tiene que indicar el nombre del archivo xml")
    else:
        nomFileXml = args[0]

    print
    print
    print
    print """
    _       _           _          ____ _____ ____  _
   / \   __| |_ __ ___ (_)_ __    / ___|  ___|  _ \( )___
  / _ \ / _` | '_ ` _ \| | '_ \  | |   | |_  | | | |// __|
 / ___ \ (_| | | | | | | | | | | | |___|  _| | |_| | \__ \\
/_/   \_\__,_|_| |_| |_|_|_| |_|  \____|_|   |____/  |___/

            """
    print '13-08-2012'
    print 'rictor@cuhrt.com'
    print
    print
    print

    if not os.path.isfile(nomFileXml):
        print "El archivo "+nomFileXml+" no existe, vuelve a intentarlo!"
        sys.exit(1)

    xmlcfd = XmlCFD(nomFileXml)
    nomFileXmlNew = xmlcfd.rename()

    print "Renombrando: "+ nomFileXml + " a: "+nomFileXmlNew
    print

if __name__ == "__main__":
  main(sys.argv[1:])

Y bueno solucionado de momento, pero interesante para seguir complementándolo!

¿Algún comentario o sugerencia?

¿En realidad es útil de esta manera? o ¿De que manera se puede mejorar aún más?

Salu2+

Anuncios
  1. Fidel Macias H.
    3 mayo, 2017 en 23:55

    Buenas Noches, respecto a tu programa esta muy bueno te felicito

    Tengo un problema al ejecutarlo cuando el nombre del archivo trae Ñ o ñ , ya que manda un error y se traba la conversion, estuve leyendo y creo que el problema viene por : -*- coding: utf-8 -*-
    pero el windows 7 pro donde lo corro lo tiene activado y me da el problema , mas sin embargo lo he corrido en otros equipos con el mismo windows 7 profesional y lo hace bien, la verdad estoyconfundido con esto.

    Me puedes sugerir como resolver este problema.

    de Antemano agradesco tus atenciones

    Fidel Macias H.

    • 4 mayo, 2017 en 00:30

      Hola Fidel

      Que gusto que te sea de utilidad y muchas gracias por el comentario!

      El -*- coding:utf-8 -*- es para que dentro del código del programa se puedan usar acetos y ñ’s y no afecta para la parte de ejecución.

      Tengo una duda ¿cómo es que el win7 donde lo corres lo tiene activado? ¿cómo es eso? ¿cómo es que está activado?

      Ya somos dos confundidos por que funciona bien en otros equipos y en ese en particular no.

      otra pregunta más ¿estás usando el programa desde el código fuente y lo ejecutas con algo como python archivo.py?

      Porque también he liberado una versión exe, no se si ya la estés usando.

      Salu2+ y gracias!

  1. 14 enero, 2014 en 19:32

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

PiKon

3D Printing + Raspberry Pi Camera = PiKon Telescope

gvSIG blog

gvSIG project blog

Python Adventures

Welcome to the Jungle!

A %d blogueros les gusta esto: