You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
classConta(Base):
''' Conta de cliente Parametros ---------- numero : Integer Numero da conta do cliente cliente : String Nome do cliente Atributos --------- id : Integer Código gerado pelo banco de dados operacoes : lista-relacional<OperacaoConta> Operações da conta '''classContaErro(LookupError):
''' Exceção para quando a conta não é valida! '''pass__tablename__='contas'#### Atributos da tabela contas##id=Column(Integer, primary_key=True)
numero=Column(Integer, nullable=False)
cliente=Column(String, nullable=False)
#### Relacionamento com a tabela operacoes_conta - muitas-para-uma##operacoes=relationship("OperacaoConta", back_populates="conta")
def__ultima_operacao(self):
''' Retorna a ultima operação realizada '''op=self.operacoes[-1:]
returnop[0] iflen(op) ==1elseNone@propertydefsaldo_atual(self):
''' Saldo da ultima operação '''op=self.__ultima_operacao()
returnop.saldo_atualifopelse0@propertydefsequencia_atual(self):
''' Sequencia da ultima operação '''op=self.__ultima_operacao()
returnop.sequenciaifopelse0@staticmethoddefcreate(numero=None, cliente=None):
''' Construtor de Conta com validações dos parametros '''c=Conta(numero=numero, cliente=cliente)
ifnotc.numero:
raiseConta.ContaErro('A conta deve conter um numero')
ifnotc.cliente:
raiseConta.ContaErro('A conta deve pertencer a um cliente')
returncdef__repr__(self):
''' Representação do objeto '''return"<Conta(id='%s', numero='%s', cliente='%s')>"% (
self.id, self.numero, self.cliente)
classOperacaoConta(Base):
''' Operações que são realizadas nas contas Parametros ---------- tipo : String caracter indicando o tipo de operação (C = Credito, D = Debito) para : Conta conta que sera afetada pela operação valor : Integer valor da operação, 100,00 = 10000 Atributos --------- saldo_atual : Integer saldo após efetuar a operação operacao_referente : OperacaoConta indica se a operação tem vinculo com outra operação ex: transferencia = faz debito na conta1 e faz credito na conta2 '''__tablename__='operacoes_conta'classOperacaoContaErro(LookupError):
'''Exceção para quando a operação da conta não é valida! '''pass#### Atributos da tabela operacoes_conta##id=Column(Integer, primary_key=True)
tipo=Column(String, nullable=False)
valor=Column(Integer, nullable=False)
saldo_atual=Column(Integer)
#### O atributo sequencia é determinado pelo valor da sequencia da## ultima operação +1##sequencia=Column(Integer, nullable=False)
#### Relacionamento com a tabela contas - uma-para-muitas##conta_id=Column(Integer, ForeignKey('contas.id'), nullable=False)
conta=relationship("Conta", back_populates="operacoes")
#### Auto referenciamento para operações que foram realizadas devido a outra operação - uma-para-uma##operacao_referente_filho_id=Column(Integer, ForeignKey('operacoes_conta.id'))
operacao_referente_filho=relationship("OperacaoConta", uselist=False,
backref=backref('operacao_referente_pai', remote_side=[id], uselist=False))
#### Restrição de (conta_id|sequencia) para ajudar a previnir condicação de corrida com outra## instancia concorrente. Ex: Um celery worker pode capturar a exceção gerada por _operacao_conta_sequencia_uc## e coloca a requisição devolta na fila para ser reprocessado##__table_args__= (UniqueConstraint('conta_id', 'sequencia', name='_operacao_conta_sequencia_uc'),
)
@staticmethoddef__create(tipo=None, para=None, valor=None):
''' Builder de OperacaoConta "generico" com validações dos parametros '''iftiponotin ('D', 'C'):
raiseOperacaoConta.OperacaoContaErro('Operação invalida!')
ifnotpara:
raiseOperacaoConta.OperacaoContaErro('É necessário informar a conta!')
ifnotvalororvalor<=0:
raiseOperacaoConta.OperacaoContaErro('O valor deve ser maior que zero!')
sequencia=para.sequencia_atual+1returnOperacaoConta(tipo=tipo, conta=para, valor=valor, sequencia=sequencia)
@staticmethoddefdebito(para=None, valor=None):
'''Builder de operação de debito, com validações especificas '''saldo_anterior=para.saldo_atualop=OperacaoConta.__create(tipo='D', para=para, valor=valor)
op.saldo_atual=saldo_anterior-valorifop.saldo_atual<0:
raiseOperacaoConta.OperacaoContaErro('Saldo insuficiente!')
returnop@staticmethoddefcredito(para=None, valor=None):
'''Builder de operação de credito, com validações especificas '''saldo_anterior=para.saldo_atualop=OperacaoConta.__create(tipo='C', para=para, valor=valor)
op.saldo_atual=saldo_anterior+valorreturnop@staticmethoddeftransferencia(de=None, para=None, valor=None):
'''Builder de operações de transferencia, uma de credito e outra de debito e referencia elas entre si Retorno ------- Tupla <OperacaoConta> : com duas operações referenciadas (Débito , Crédito) '''d=OperacaoConta.debito(de, valor)
c=OperacaoConta.credito(para, valor)
d.operacao_referente_filho=cc.operacao_referente_pai=dreturnd, cdef__repr__(self):
''' Representação do objeto '''return"<OperacaoConta(id='%s', tipo='%s', valor='%s', saldo_atual='%s', conta_id='%s', operacao_referente_id='%s')>"% (
self.id, self.tipo, self.valor, self.saldo_atual, self.conta_id, self.operacao_referente_filho_id)
opd= {'D':'Debito', 'C': 'Credito'}
print('-'*60)
print(c1.cliente, 'está com saldo atual de', c1.saldo_atual)
print(c2.cliente, 'está com saldo atual de', c2.saldo_atual)
print('*'*60)
operacoes= []
operacoes.append(OperacaoConta.credito(para=c1, valor=99999))
operacoes=operacoes+ [wforwinOperacaoConta.transferencia(de=c1, para=c2, valor=10000)]
operacoes=operacoes+ [wforwinOperacaoConta.transferencia(de=c1, para=c2, valor=10000)]
session.add_all(operacoes)
session.flush()
session.commit()
forwinsession.query(OperacaoConta).all():
print("*{} {} na conta de {} no valor de {}{}{}\n----> Novo saldo {}".format(w.id,
opd[w.tipo],
w.conta.cliente,
w.valor,
' referente *{}'.format(w.operacao_referente_filho.id) ifw.operacao_referente_filhoelse'',
' referente *{}'.format(w.operacao_referente_pai.id) ifw.operacao_referente_paielse'',
w.saldo_atual))
print('*'*60)
print(c1.cliente, 'está com saldo atual de', c1.saldo_atual)
print(c2.cliente, 'está com saldo atual de', c2.saldo_atual)
print('-'*60)
------------------------------------------------------------
Rodrigo está com saldo atual de 0
André está com saldo atual de 0
************************************************************
*1 Credito na conta de Rodrigo no valor de 99999
----> Novo saldo 99999
*2 Debito na conta de Rodrigo no valor de 10000 referente *4
----> Novo saldo 89999
*3 Debito na conta de Rodrigo no valor de 10000 referente *5
----> Novo saldo 79999
*4 Credito na conta de André no valor de 10000 referente *2
----> Novo saldo 10000
*5 Credito na conta de André no valor de 10000 referente *3
----> Novo saldo 20000
************************************************************
Rodrigo está com saldo atual de 79999
André está com saldo atual de 20000
------------------------------------------------------------