Example #1
0
class BoletoBanrisul(Boleto):
    conta_cedente = CustomProperty('conta_cedente', 6)
    nosso_numero = CustomProperty('nosso_numero', 8)

    def __init__(self):
        Boleto.__init__(self)
        self.codigo_banco = "041"
        self.logo_image = "logo_banrisul.jpg"

    @property
    def campo_livre(self):
        content = '21%04d%07d%08d40' % (int(
            self.agencia_cedente), int(
                self.conta_cedente), int(self.nosso_numero))
        return '%s%s' % (content, self._dv_campo_livre(content))

    # From http://jrimum.org/bopepo/browser/trunk/src/br/com/nordestefomento/
    # jrimum/bopepo/campolivre/AbstractCLBanrisul.java
    def _dv_campo_livre(self, campo_livre):
        dv = self.modulo10(campo_livre)
        while True:
            rest_mod_11 = self.modulo11(campo_livre + str(dv), 7, 1)
            if rest_mod_11 != 1:
                break
            dv += 1
            dv %= 10

        return str(dv) + str(11 - rest_mod_11)
class BoletoCaixaSigcb(Boleto):
    '''
        Gera Dados necessários para criação de boleto para o banco Caixa
        Economica Federal
    '''

    agencia_cedente = CustomProperty('agencia_cedente', 4)
    conta_cedente = CustomProperty('conta_cedente', 6)
    nosso_numero = CustomProperty('nosso_numero', 17)

    def __init__(self):
        super(BoletoCaixaSigcb, self).__init__()

        self.codigo_banco = "104"
        self.local_pagamento = ("Preferencialmente nas Casas Lotéricas e "
                                "Agências da Caixa")
        self.logo_image = "logo_bancocaixa.jpg"

    @property
    def campo_livre(self):  # 24 digits
        content = "%6s%1s%3s%1s%3s%1s%9s" % (
            self.conta_cedente.split('-')[0],
            self.modulo11(self.conta_cedente.split('-')[0]),
            self.nosso_numero[2:5],
            self.nosso_numero[0:1],
            self.nosso_numero[5:8],
            self.nosso_numero[1:2],
            self.nosso_numero[8:17]
        )
        dv_content = self.modulo11(content)

        return "%24s%1s" % (content, dv_content)

    def format_nosso_numero(self):
        return self.nosso_numero
Example #3
0
class BoletoItau(Boleto):
    '''Implementa Boleto Itaú

        Gera Dados necessários para criação de boleto para o banco Itau
        Todas as carteiras com excessão das que utilizam 15 dígitos: (106,107,
        195,196,198)
    '''

    # Nosso numero (sem dv) com 8 digitos
    nosso_numero = CustomProperty('nosso_numero', 8)
    # Conta (sem dv) com 5 digitos
    conta_cedente = CustomProperty('conta_cedente', 5)
    #  Agência (sem dv) com 4 digitos
    agencia_cedente = CustomProperty('agencia_cedente', 4)
    carteira = CustomProperty('carteira', 3)

    def __init__(self):
        super(BoletoItau, self).__init__()

        self.codigo_banco = "341"
        self.logo_image = "logo_itau.jpg"
        self.especie_documento = 'DM'

    @property
    def dv_nosso_numero(self):
        composto = "%4s%5s%3s%8s" % (self.agencia_cedente, self.conta_cedente,
                                     self.carteira, self.nosso_numero)
        return self.modulo10(composto)

    @property
    def dv_agencia_conta_cedente(self):
        agencia_conta = "%s%s" % (self.agencia_cedente, self.conta_cedente)
        return self.modulo10(agencia_conta)

    @property
    def agencia_conta_cedente(self):
        return "%s/%s-%s" % (self.agencia_cedente, self.conta_cedente,
                             self.dv_agencia_conta_cedente)

    def format_nosso_numero(self):
        return "%3s/%8s-%1s" % (self.carteira, self.nosso_numero,
                                self.dv_nosso_numero)

    @property
    def campo_livre(self):
        content = "%3s%8s%1s%4s%5s%1s%3s" % (self.carteira,
                                             self.nosso_numero,
                                             self.dv_nosso_numero,
                                             self.agencia_cedente,
                                             self.conta_cedente,
                                             self.dv_agencia_conta_cedente,
                                             '000'
                                             )
        return content
Example #4
0
class BoletoHsbcComRegistro(Boleto):
    '''
        Gera Dados necessários para criação de boleto para o banco HSBC
        com registro
    '''
    # Nosso numero (sem dv) sao 10 digitos
    nosso_numero = CustomProperty('nosso_numero', 10)

    def __init__(self):
        super(BoletoHsbcComRegistro, self).__init__()

        self.codigo_banco = "399"
        self.logo_image = "logo_bancohsbc.jpg"
        self.carteira = 'CSB'
        self.especie_documento = 'PD'

    @property
    def dv_nosso_numero(self):
        resto = self.modulo11(self.nosso_numero, 7, 1)
        if resto == 0 or resto == 1:
            return 0
        else:
            return 11 - resto

    @property
    def campo_livre(self):
        content = "%10s%1s%4s%7s001" % (self.nosso_numero,
                                        self.dv_nosso_numero,
                                        self.agencia_cedente.split('-')[0],
                                        self.conta_cedente.split('-')[0])
        return content
Example #5
0
class BoletoCaixa(Boleto):
    '''
        Gera Dados necessários para criação de boleto para o banco Caixa
        Economica Federal

    '''

    conta_cedente = CustomProperty('conta_cedente', 11)
    '''
        Este numero tem o inicio fixo
        Carteira SR: 80, 81 ou 82
        Carteira CR: 90 (Confirmar com gerente qual usar)

    '''
    nosso_numero = CustomProperty('nosso_numero', 10)

    def __init__(self):
        super(BoletoCaixa, self).__init__()

        self.codigo_banco = "104"
        self.local_pagamento = "Preferencialmente nas Casas Lotéricas e \
Agências da Caixa"

        self.logo_image = "logo_bancocaixa.jpg"

    @property
    def dv_nosso_numero(self):
        resto2 = self.modulo11(self.nosso_numero.split('-')[0], 9, 1)
        digito = 11 - resto2
        if digito == 10 or digito == 11:
            dv = 0
        else:
            dv = digito
        return dv

    @property
    def campo_livre(self):
        content = "%10s%4s%11s" % (self.nosso_numero, self.agencia_cedente,
                                   self.conta_cedente.split('-')[0])
        return content

    def format_nosso_numero(self):
        return self.nosso_numero + '-' + str(self.dv_nosso_numero)
class BoletoSantander(Boleto):
    '''
        Gera Dados necessários para criação de boleto para o banco Santander
    '''

    nosso_numero = CustomProperty('nosso_numero', 12)

    #: Também chamado de "ponto de venda"
    agencia_cedente = CustomProperty('agencia_cedente', 4)

    #: Também chamdo de código do cedente, se for uma conta de 9 dígitos
    #: ignorar os 2 primeiros
    conta_cedente = CustomProperty('conta_cedente', 7)

    def __init__(self):
        super(BoletoSantander, self).__init__()

        self.codigo_banco = "033"
        self.logo_image = "logo_santander.jpg"
        self.carteira = '102'
        # IOS - somente para Seguradoras (Se 7% informar 7, limitado 9%)
        # Demais clientes usar 0 (zero)
        self.ios = "0"

    def format_nosso_numero(self):
        return "%s-%s" % (self.nosso_numero, self._dv_nosso_numero())

    def _dv_nosso_numero(self):
        return str(self.modulo11(self.nosso_numero, 9, 0))

    @property
    def campo_livre(self):
        content = "".join([
            '9',
            self.conta_cedente,
            self.nosso_numero,
            self._dv_nosso_numero(),
            self.ios,
            self.carteira,
        ])
        return content
Example #7
0
class BoletoBradesco(Boleto):
    '''
        Gera Dados necessários para criação de boleto para o banco Bradesco
    '''

    nosso_numero = CustomProperty('nosso_numero', 11)
    agencia_cedente = CustomProperty('agencia_cedente', 4)
    conta_cedente = CustomProperty('conta_cedente', 7)

    def __init__(self):
        super(BoletoBradesco, self).__init__()

        self.codigo_banco = "237"
        self.logo_image = "logo_bancobradesco.jpg"
        self.carteira = '06'

    def format_nosso_numero(self):
        return "%s/%s-%s" % (self.carteira, self.nosso_numero,
                             self.dv_nosso_numero)

    @property
    def dv_nosso_numero(self):
        resto2 = self.modulo11(self.nosso_numero, 7, 1)
        digito = 11 - resto2
        if digito == 10:
            dv = 'P'
        elif digito == 11:
            dv = 0
        else:
            dv = digito
        return dv

    @property
    def campo_livre(self):
        content = "%4s%2s%11s%7s%1s" % (self.agencia_cedente.split('-')[0],
                                        self.carteira, self.nosso_numero,
                                        self.conta_cedente.split('-')[0], '0')
        return content
Example #8
0
class BoletoHsbc(Boleto):
    '''
        Gera Dados necessários para criação de boleto para o banco HSBC
    '''

    numero_documento = CustomProperty('numero_documento', 13)

    def __init__(self):
        super(BoletoHsbc, self).__init__()

        self.codigo_banco = "399"
        self.logo_image = "logo_bancohsbc.jpg"
        self.carteira = 'CNR'

    def format_nosso_numero(self):
        nosso_numero = self.nosso_numero
        # Primeiro DV
        nosso_numero += str(self.modulo11(nosso_numero))
        # Cobrança com vencimento = 4
        nosso_numero += "4"
        # Segundo DV
        sum_params = int(nosso_numero) + int(self.conta_cedente)
        sum_params += int(self.data_vencimento.strftime('%d%m%y'))
        sum_params = str(sum_params)
        nosso_numero += str(self.modulo11(sum_params))
        return nosso_numero

    @property
    def data_vencimento_juliano(self):
        data_vencimento = str(self.data_vencimento.timetuple().tm_yday)
        data_vencimento += str(self.data_vencimento.year)[-1:]
        return data_vencimento.zfill(4)

    @property
    def campo_livre(self):
        content = "%7s%13s%4s2" % (self.conta_cedente, self.nosso_numero,
                                   self.data_vencimento_juliano)
        return content
Example #9
0
class BoletoBB(Boleto):
    '''
        Gera Dados necessários para criação de boleto para o Banco do Brasil
    '''

    agencia_cedente = CustomProperty('agencia_cedente', 4)
    conta_cedente = CustomProperty('conta_cedente', 8)

    def __init__(self, format_convenio, format_nnumero):
        '''
            Construtor para boleto do Banco deo Brasil

            Args:
                format_convenio Formato do convenio 4, 6, 7 ou 8
                format_nnumero Formato nosso numero 1 ou 2
                    (apenas para convenio 6)
        '''
        super(BoletoBB, self).__init__()

        self.codigo_banco = "001"
        self.carteira = 18
        self.logo_image = "logo_bb.jpg"

        # Size of convenio 4, 6, 7 or 8
        self.format_convenio = format_convenio

        #  Nosso Numero format. 1 or 2
        #  Used only for convenio=6
        #  1: Nosso Numero with 5 positions
        #  2: Nosso Numero with 17 positions
        self.format_nnumero = format_nnumero

        self._convenio = ""
        self._nosso_numero = ""

    def format_nosso_numero(self):
        if self.format_convenio == 7:
            return "%7s%10s" % (self.convenio, self.nosso_numero)
        else:
            return "%s%s-%s" % (self.convenio, self.nosso_numero,
                                self.dv_nosso_numero)

    # Nosso numero (sem dv) sao 11 digitos
    def _get_nosso_numero(self):
        return self._nosso_numero

    def _set_nosso_numero(self, val):
        val = str(val)
        if self.format_convenio == 4:
            nn = val.zfill(7)
        elif self.format_convenio == 6:
            if self.format_nnumero == 1:
                nn = val.zfill(5)
            elif self.format_nnumero == 2:
                nn = val.zfill(17)
        elif self.format_convenio == 7:
            nn = val.zfill(10)
        elif self.format_convenio == 8:
            nn = val.zfill(9)
        self._nosso_numero = nn

    nosso_numero = property(_get_nosso_numero, _set_nosso_numero)

    def _get_convenio(self):
        return self._convenio

    def _set_convenio(self, val):
        self._convenio = str(val).ljust(self.format_convenio, '0')

    convenio = property(_get_convenio, _set_convenio)

    @property
    def agencia_conta_cedente(self):
        return "%s-%s / %s-%s" % (
            self.agencia_cedente, self.modulo11(self.agencia_cedente),
            self.conta_cedente, self.modulo11(self.conta_cedente))

    @property
    def dv_nosso_numero(self):
        '''
            This function uses a modified version of modulo11
        '''
        num = self.convenio + self.nosso_numero
        base = 2
        fator = 9
        soma = 0
        for c in reversed(num):
            soma += int(c) * fator
            if fator == base:
                fator = 10
            fator -= 1
        r = soma % 11
        if r == 10:
            return 'X'
        return r

    @property
    def campo_livre(self):
        if self.format_convenio == 4:
            content = "%s%s%s%s%s" % (self.convenio, self.nosso_numero,
                                      self.agencia_cedente, self.conta_cedente,
                                      self.carteira)
        elif self.format_convenio in (7, 8):
            content = "000000%s%s%s" % (self.convenio, self.nosso_numero,
                                        self.carteira)
        elif self.format_convenio == 6:
            if self.format_nnumero == 1:
                content = "%s%s%s%s%s" % (self.convenio, self.nosso_numero,
                                          self.agencia_cedente,
                                          self.conta_cedente, self.carteira)
            if self.format_nnumero == 2:
                content = "%s%s%s" % (self.convenio, self.nosso_numero, '21'
                                      )  # numero do serviço

        return content
Example #10
0
class BancoInter(Boleto):
    """ Implementa a Api do BancoInter """

    seu_numero = CustomProperty('seu_numero', 15)
    nosso_numero = CustomProperty('nosso_numero', 11)
    linha_digitavel = None
    barcode = None
    _gera_pdf = False

    @classmethod
    def convert_to(cls, obj, **kwargs):
        obj.__class__ = cls
        obj.__special_init__()
        for key, value in kwargs.items():
            if hasattr(obj, key):
                obj.__dict__[key] = value

    def __init__(self, **kwargs):
        super(BancoInter, self).__init__(**kwargs)
        self.codigo_banco = "077"
        self.sacado_complemento = kwargs.pop('sacado_complemento', "")
        self.sacado_numero = kwargs.pop('sacado_numero', "")
        self.sacado_ddd = kwargs.pop('sacado_ddd', "")
        self.sacado_telefone = kwargs.pop('sacado_telefone', "")
        self.sacado_bairro = kwargs.pop('sacado_bairro', "")
        self.sacado_email = kwargs.pop('sacado_email', "")
        self.mora = dict(codigoMora="ISENTO", valor=0, taxa=0)
        self.multa = dict(codigoMulta="NAOTEMMULTA", valor=0, taxa=0)

    def _emissao_data(self):
        pagador = dict(
            cnpjCpf=self.sacado_documento,
            nome=self.sacado_nome,
            email=self.sacado_email,
            telefone=self.sacado_telefone,
            cep=self.sacado_cep,
            numero=self.sacado_numero,
            complemento=self.sacado_complemento,
            bairro=self.sacado_bairro,
            cidade=self.sacado_cidade,
            uf=self.sacado_uf,
            endereco=self.sacado_endereco,
            ddd=self.sacado_ddd,
            tipoPessoa=self.sacado_tipo_pessoa,
        )
        mensagem1 = dict({
            'linha{}'.format(k + 1): v
            for (k, v) in enumerate(self._instrucoes)
        })
        desconto1 = dict(codigoDesconto="NAOTEMDESCONTO",
                         taxa=0,
                         valor=0,
                         data="")
        desconto2 = dict(codigoDesconto="NAOTEMDESCONTO",
                         taxa=0,
                         valor=0,
                         data="")
        desconto3 = dict(codigoDesconto="NAOTEMDESCONTO",
                         taxa=0,
                         valor=0,
                         data="")
        data = dict(pagador=pagador,
                    dataEmissao=self.data_documento,
                    seuNumero=self.numero_documento,
                    dataLimite="SESSENTA",
                    dataVencimento=self.data_documento,
                    mensagem=mensagem1,
                    desconto1=desconto1,
                    desconto2=desconto2,
                    desconto3=desconto3,
                    valorNominal=self.valor_documento,
                    valorAbatimento=0,
                    multa=self.multa,
                    mora=self.mora,
                    cnpjCPFBeneficiario=self.cedente_documento,
                    numDiasAgenda="SESSENTA")
        return data
Example #11
0
class BoletoSicredi(Boleto):
    '''
        Gera Dados necessários para criação de boleto para o Banco Sicredi
    '''
    agencia_cedente = CustomProperty('agencia_cedente', 4)
    conta_cedente = CustomProperty('conta_cedente', 8)
    posto = CustomProperty('posto', 2)
    convenio = CustomProperty('convenio', 4)
    # Nosso numero (sem dv) com 8 digitos
    nosso_numero = CustomProperty('nosso_numero', 8)

    def __init__(self):
        '''
            Construtor para boleto do Banco Sicredi

            Args:
                format_convenio Formato do convenio 6, 7 ou 8
                format_nnumero Formato nosso numero 1 ou 2
        '''
        super(BoletoSicredi, self).__init__()

        self.codigo_banco = "748"
        self.carteira = 3
        self.posto = "05"
        self.logo_image = "logo_sicredi.jpg"

        # Size of convenio 6, 7 or 8
        self.format_convenio = 5

        #  Nosso Numero format. 1 or 2
        #  1: Nosso Numero with 5 positions
        #  2: Nosso Numero with 17 positions
        self.format_nnumero = 1  # self.nosso_numero

    def format_ano(self):
        ano = str(self.data_vencimento.strftime('%y'))
        ano = ano.zfill(2)
        return ano

    def format_nosso_numero(self):

        # 14 ano + 2 : Nosso Número deve ser apresentado no formato
        # AA/BXXXXX-D, onde:
        return "%s/2%s-%s" % (self.format_ano(), self.nosso_numero,
                              self.dv_nosso_numero)

    # Nosso numero (sem dv) sao 11 digitos
    def _get_nosso_numero(self):
        return self._nosso_numero

    def _set_nosso_numero(self, val):
        val = str(val)
        if self.format_convenio == 5:
            if self.format_nnumero == 1:
                nn = val.zfill(5)
            elif self.format_nnumero == 2:
                nn = val.zfill(17)
        elif self.format_convenio == 7:
            nn = val.zfill(10)
        elif self.format_convenio == 8:
            nn = val.zfill(9)
        self._nosso_numero = nn

    nosso_numero = property(_get_nosso_numero, _set_nosso_numero)

    def _get_convenio(self):
        return self._convenio

    def _set_convenio(self, val):
        self._convenio = str(val).rjust(self.format_convenio, '0')

    convenio = property(_get_convenio, _set_convenio)

    @property
    def agencia_conta_cedente(self):
        return "%s.%s.%s" % (self.agencia_cedente, self.posto, self.convenio)

    @property
    def dv_nosso_numero(self):
        dv = "%s%s%s%s2%s" % (self.agencia_cedente, self.posto, self.convenio,
                              self.format_ano(), self.nosso_numero)
        dv = self.modulo11(dv)
        return dv

    @property
    def campo_livre(self):
        content = str("")
        if self.format_nnumero == 1:
            #        "3027050000414205586")
            # 14 ano + 2 : Nosso Número deve ser apresentado no formato
            # AA/BXXXXX-D, onde:
            content = "%s1%s2%s%s%s%s%s10" % (self.carteira, self.format_ano(
            ), self.nosso_numero, self.dv_nosso_numero, self.agencia_cedente,
                                              self.posto, self.convenio)
            n = self.modulo11(content)
            if n > 9:
                n = 1
            content += str(n)
        return str(content)

    @property
    def codigo_dv_banco(self):
        cod = "%s-X" % self.codigo_banco
        return cod
Example #12
0
class Boleto(object):
    """Interface para implementações específicas de bancos

    Esta classe geralmente nunca será usada diretamente. Geralmente o usuário
    irá usar uma das subclasses com a implementação específica de cada banco.

    As classes dentro do pacote :mod:`pyboleto.bank` extendem essa classe
    para implementar as especificações de cada banco.
    Portanto as especificações dentro desta classe são genéricas seguindo as
    normas da FEBRABAN.

    Todos os parâmetros devem ser passados como ``**kwargs`` para o construtor
    ou então devem ser passados depois, porém antes de imprimir o boleto.

    eg::

        bData = Boleto(agencia='123', valor='650')
        bData.cedente = u'João Ninguém'
        bData.cedente_cidade = u'Rio de Janeiro'
        bData.cedente_uf = u'RJ'
        # Assim por diante até preencher todos os campos obrigatórios.

    **Parâmetros obrigatórios**:

    :param aceite: 'N' para o caixa não acetitar o boleto após a
        validade ou 'A' para aceitar. *(default: 'N')*
    :param agencia_cedente: Tamanho pode variar com o banco.
    :param carteira: Depende do Banco.
    :param cedente: Nome do Cedente
    :param cedente_cidade:
    :param cedente_uf:
    :param cedente_logradouro: Endereço do Cedente
    :param cedente_bairro:
    :param cedente_cep:
    :param cedente_documento: CPF ou CNPJ do Cedente.
    :param conta_cedente: Conta do Cedente sem o dígito verificador.
    :param data_documento:
    :type data_documento: `datetime.date`
    :param data_processamento:
    :type data_processamento: `datetime.date`
    :param data_vencimento:
    :type data_vencimento: `datetime.date`
    :param numero_documento: Número Customizado para controle. Pode ter até 13
        caracteres dependendo do banco.
    :param sacado_nome: Nome do Sacado
    :param sacado_documento: CPF ou CNPJ do Sacado
    :param sacado_cidade:
    :param sacado_uf:
    :param sacado_endereco: Endereco do Sacado
    :param sacado_bairro:
    :param sacado_cep:

    **Parâmetros não obrigatórios**:

    :param quantidade:
    :param especie: Nunca precisa mudar essa opção *(default: 'R$')*
    :param especie_documento:
    :param local_pagamento: *(default: 'Pagável em qualquer banco
        até o vencimento')*
    :param moeda: Nunca precisa mudar essa opção *(default: '9')*

    """

    nosso_numero = CustomProperty('nosso_numero', 13)
    """Nosso Número geralmente tem 13 posições

    Algumas subclasses podem alterar isso dependendo das normas do banco

    """

    agencia_cedente = CustomProperty('agencia_cedente', 4)
    """Agência do Cedente geralmente tem 4 posições

    Algumas subclasses podem alterar isso dependendo das normas do banco

    """

    conta_cedente = CustomProperty('conta_cedente', 7)
    """Conta do Cedente geralmente tem 7 posições

    Algumas subclasses podem alterar isso dependendo das normas do banco

    """
    def __init__(self, **kwargs):
        #        otherwise the printed value might diffent from the value in
        #        the barcode.
        self.aceite = kwargs.pop('aceite', "N")
        self.agencia_cedente = kwargs.pop('agencia_cedente', "")
        self.carteira = kwargs.pop('carteira', "")
        self.cedente = kwargs.pop('cedente', "")
        self.cedente_cidade = kwargs.pop('cedente_cidade', "")
        self.cedente_uf = kwargs.pop('cedente_uf', "")
        self.cedente_logradouro = kwargs.pop('cedente_logradouro', "")
        self.cedente_bairro = kwargs.pop('cedente_bairro', "")
        self.cedente_cep = kwargs.pop('cedente_cep', "")
        self.cedente_documento = kwargs.pop('cedente_documento', "")
        self.codigo_banco = kwargs.pop('codigo_banco', "")
        self.conta_cedente = kwargs.pop('conta_cedente', "")
        self.data_documento = kwargs.pop('data_documento', "")
        self.data_processamento = kwargs.pop('data_processamento',
                                             datetime.date.today())
        self.data_vencimento = kwargs.pop('data_vencimento', "")
        self.especie = kwargs.pop('especie', "R$")
        self.especie_documento = kwargs.pop('especie_documento', "")
        self.local_pagamento = kwargs.pop(
            'local_pagamento', "Pagável em qualquer banco até o vencimento")
        self.logo_image = kwargs.pop('logo_image', "")
        self.moeda = kwargs.pop('moeda', "9")
        self.numero_documento = kwargs.pop('numero_do_documento', "")
        self.quantidade = kwargs.pop('quantidade', "")
        self.sacado_nome = kwargs.pop('sacado_nome', "")
        self.sacado_documento = kwargs.pop('sacado_documento', "")
        self.sacado_cidade = kwargs.pop('sacado_cidade', "")
        self.sacado_uf = kwargs.pop('sacado_uf', "")
        self.sacado_endereco = kwargs.pop('sacado_endereco', "")
        self.sacado_bairro = kwargs.pop('sacado_bairro', "")
        self.sacado_cep = kwargs.pop('sacado_cep', 0)
        if kwargs:
            raise TypeError("Paramêtro(s) desconhecido: %r" % (kwargs, ))
        self._cedente_endereco = None
        self._demonstrativo = []
        self._instrucoes = []
        self._sacado = None
        self._valor = None
        self._valor_documento = None
        self._gera_pdf = True

    @property
    def barcode(self):
        """Essa função sempre é a mesma para todos os bancos. Então basta
        implementar o método :func:`barcode` para o pyboleto calcular a linha
        digitável.

        Posição  #   Conteúdo
        01 a 03  03  Número do banco
        04       01  Código da Moeda - 9 para Real
        05       01  Digito verificador do Código de Barras
        06 a 09  04  Data de vencimento em dias partis de 07/10/1997
        10 a 19  10  Valor do boleto (8 inteiros e 2 decimais)
        20 a 44  25  Campo Livre definido por cada banco
        Total    44
        """

        for attr, length, data_type in [
            ('codigo_banco', 3, str),
            ('moeda', 1, str),
            ('data_vencimento', None, datetime.date),
            ('valor_documento', -1, str),
            ('campo_livre', 25, str),
        ]:
            value = getattr(self, attr)
            if not isinstance(value, data_type):
                raise TypeError(
                    "%s.%s must be a %s, got %r (type %s)" %
                    (self.__class__.__name__, attr, data_type.__name__, value,
                     type(value).__name__))
            if (data_type == str and length != -1 and len(value) != length):
                raise ValueError(
                    "%s.%s must have a length of %d, not %r (len: %d)" %
                    (self.__class__.__name__, attr, length, value, len(value)))

        due_date_days = (self.data_vencimento - _EPOCH).days
        if not (9999 >= due_date_days >= 0):
            raise TypeError("Invalid date, must be between 1997/07/01 and "
                            "2024/11/15")
        num = "%s%1s%04d%010d%24s" % (
            self.codigo_banco, self.moeda, due_date_days,
            Decimal(self.valor_documento) * 100, self.campo_livre)
        dv = self.calculate_dv_barcode(num)

        barcode = num[:4] + str(dv) + num[4:]
        if len(barcode) != 44:
            raise BoletoException(
                'The barcode must have 44 characteres, found %d' %
                len(barcode))
        return barcode

    @property
    def campo_livre(self):
        """Must be overriden by child class property

        :exception NotImplementedError: Needs to be implemented by derived
            class
        """
        raise NotImplementedError(
            'This method has not been implemented by this class')

    def calculate_dv_barcode(self, line):
        """Calcula DV para código de barras

        Está é uma implementação genérica mas pode ser reimplementada pela
        classe derivada dependendo das definições de cada bancoGeralmente
        é implementado pela classe derivada.

        """
        resto2 = self.modulo11(line, 9, 1)
        if resto2 in [0, 1, 10]:
            dv = 1
        else:
            dv = 11 - resto2
        return dv

    def format_nosso_numero(self):
        """
            Geralmente é implementado pela classe derivada. Usada para formatar
            como o noso número será impresso no boleto. Às vezes é o mesmo
            do `numero_documento` e às vezes contém outros campos
            juntos.
        """
        return self.nosso_numero

    def _cedente_endereco_get(self):
        if self._cedente_endereco is None:
            self._cedente_endereco = '%s - %s - %s - %s - %s' % (
                self.cedente_logradouro, self.cedente_bairro,
                self.cedente_cidade, self.cedente_uf, self.cedente_cep)
        return self._cedente_endereco

    def _cedente_endereco_set(self, endereco):
        if len(endereco) > 80:
            raise BoletoException(
                u'Linha de endereço possui mais que 80 caracteres')
        self._cedente_endereco = endereco

    cedente_endereco = property(_cedente_endereco_get, _cedente_endereco_set)
    """Endereço do Cedente com no máximo 80 caracteres"""

    def _get_valor(self):
        if self._valor is not None:
            return "%.2f" % self._valor

    def _set_valor(self, val):
        if type(val) is Decimal:
            self._valor = val
        else:
            self._valor = Decimal(str(val))

    valor = property(_get_valor, _set_valor)
    """Valor convertido para :class:`Decimal`.

    Geralmente valor e valor_documento são o mesmo número.

    :type: Decimal

    """

    def _get_valor_documento(self):
        if self._valor_documento is not None:
            return "%.2f" % self._valor_documento

    def _set_valor_documento(self, val):
        if type(val) is Decimal:
            self._valor_documento = val
        else:
            self._valor_documento = Decimal(str(val))

    valor_documento = property(_get_valor_documento, _set_valor_documento)
    """Valor do Documento convertido para :class:`Decimal`.

    De preferência para passar um valor em :class:`Decimal`, se não for passado
    outro tipo será feito um cast para :class:`Decimal`.

    """

    def _instrucoes_get(self):
        return self._instrucoes

    def _instrucoes_set(self, list_inst):
        if isinstance(list_inst, str):
            list_inst = list_inst.splitlines()

        if len(list_inst) > 7:
            raise BoletoException(
                u'Número de linhas de instruções maior que 7')
        for line in list_inst:
            if len(line) > 90:
                raise BoletoException(
                    u'Linha de instruções possui mais que 90 caracteres')
        self._instrucoes = list_inst

    instrucoes = property(_instrucoes_get, _instrucoes_set)
    """Instruções para o caixa do banco que recebe o bilhete

    Máximo de 7 linhas com 90 caracteres cada.
    Geralmente contém instruções para aplicar multa ou não aceitar caso tenha
    passado a data de validade.

    """

    def _demonstrativo_get(self):
        return self._demonstrativo

    def _demonstrativo_set(self, list_dem):
        if isinstance(list_dem, str):
            list_dem = list_dem.splitlines()

        if len(list_dem) > 12:
            raise BoletoException(
                u'Número de linhas de demonstrativo maior que 12')
        for line in list_dem:
            if len(line) > 90:
                raise BoletoException(
                    u'Linha de demonstrativo possui mais que 90 caracteres')
        self._demonstrativo = list_dem

    demonstrativo = property(_demonstrativo_get, _demonstrativo_set)
    """Texto que vai impresso no corpo do Recibo do Sacado

    Máximo de 12 linhas com 90 caracteres cada.

    """

    def _sacado_get(self):
        """Tenta usar o sacado que foi setado ou constroi um

        Se você não especificar um sacado o boleto tentará construir um sacado
        a partir de outras proriedades setadas.

        Para facilitar você deve sempre setar essa propriedade.

        """
        if self._sacado is None:
            self.sacado = [
                '%s - CPF/CNPJ: %s' %
                (self.sacado_nome, self.sacado_documento),
                self.sacado_endereco,
                '%s - %s - %s - %s' % (self.sacado_bairro, self.sacado_cidade,
                                       self.sacado_uf, self.sacado_cep)
            ]
        return self._sacado

    def _sacado_set(self, list_sacado):
        if len(list_sacado) > 3:
            raise BoletoException(u'Número de linhas do sacado maior que 3')
        self._sacado = list_sacado

    sacado = property(_sacado_get, _sacado_set)
    """Campo sacado composto por até 3 linhas.

    A primeira linha precisa ser o nome do sacado.
    As outras duas linhas devem ser usadas para o endereço do sacado.

    """

    @property
    def agencia_conta_cedente(self):
        return "%s/%s" % (self.agencia_cedente, self.conta_cedente)

    @property
    def codigo_dv_banco(self):
        cod = "%s-%s" % (self.codigo_banco, self.modulo11(self.codigo_banco))
        return cod

    @property
    def linha_digitavel(self):
        """Monta a linha digitável a partir do barcode

        Esta é a linha que o cliente pode utilizar para digitar se o código
        de barras não estiver legível.
        """
        linha = self.barcode
        if not linha:
            raise BoletoException("Boleto doesn't have a barcode")

        def monta_campo(campo):
            campo_dv = "%s%s" % (campo, self.modulo10(campo))
            return "%s.%s" % (campo_dv[0:5], campo_dv[5:])

        return ' '.join([
            monta_campo(linha[0:4] + linha[19:24]),
            monta_campo(linha[24:34]),
            monta_campo(linha[34:44]), linha[4], linha[5:19]
        ])

    @staticmethod
    def modulo11(num, base=9, r=0):
        return modulo11(num, base, r)

    @staticmethod
    def modulo10(num):
        return modulo10(num)