Exemplo n.º 1
0
class LancamentoAddCommand(object):
    def __init__(self):
        self._conta_dao = Inject('conta dao')
        self._lancamento_dao = Inject('lancamento dao')

    def lancamento_parser_created_handler(self, lancamento_parser):
        parser = lancamento_parser.add_parser(
            'add', aliases=['a'], help='Adiciona um novo lançamento')
        parser.set_defaults(event='lancamento_add_command')

        parser.add_argument('origem')
        parser.add_argument('destino')
        parser.add_argument('valor', type=currency.parse)
        parser.add_argument('--data',
                            '-d',
                            type=date_converter.parse,
                            default=date.today())
        parser.add_argument('--observacao', '-o', required=False)

    def lancamento_add_command_handler(self, args):
        contas_not_found = []

        origem = self._conta_dao.by_name(args.origem)
        if not origem:
            contas_not_found += ['origem']

        destino = self._conta_dao.by_name(args.destino)
        if not destino:
            contas_not_found += ['destino']

        if len(contas_not_found) > 0:
            return 'conta_not_found', {'contas': contas_not_found}
        else:
            lancamento = Lancamento()

            lancamento.data = args.data
            lancamento.origem = origem
            lancamento.destino = destino
            lancamento.valor = args.valor
            lancamento.observacao = args.observacao

            self._lancamento_dao.insert(lancamento)

            return 'ok', {'lancamento': lancamento}

    def lancamento_add_command_ok_handler(self, lancamento):
        observacao = lancamento.observacao if lancamento.observacao else ''

        print('Lançamento criado: {} {} {} {} {}'.format(
            lancamento.data, lancamento.origem.nome, lancamento.destino.nome,
            lancamento.valor, observacao))

    def lancamento_add_command_conta_not_found_handler(self, contas):
        plural_suffix = 's' if len(contas) > 0 else ''

        contas_str = ', '.join(contas)

        print('Conta{} não encontrada{0}: {}'.format(plural_suffix,
                                                     contas_str))
Exemplo n.º 2
0
class ContaAddCommand(object):

    def __init__(self):
        self._dao = Inject('conta dao')

    @staticmethod
    def conta_parser_created_handler(conta_parser):
        conta_add_parser = conta_parser.add_parser('add', aliases=['a'], help='Adiciona uma nova conta')
        conta_add_parser.set_defaults(event='conta_add_command')

        conta_add_parser.add_argument("-c", "--contabilizavel", default=False, action="store_true",
                                      help="Marca a nova conta como contabilizável (o saldo é calculado nas listagens)")
        conta_add_parser.add_argument("--df", "--fechamento", help="Data de fechamento da conta")

        conta_add_parser.add_argument("nome", help="Nome da conta a ser criada")

    def conta_add_command_handler(self, args):
        conta = Conta()

        conta.nome = args.nome
        if args.contabilizavel:
            conta.propriedades += 'contabilizável'

        if hasattr(args, "fechamento"):
            conta.fechamento = args.fechamento

        self._dao.insert(conta)

        return 'ok', conta

    def conta_add_command_ok_handler(self, conta):
        message = 'Conta "{}"'.format(conta.nome)

        if conta.propriedades != '':
            message += ' com as propriedades "{}"'.format(conta.propriedades)

        message += " criada."

        print(message)
Exemplo n.º 3
0
class ImportCSVCommand(object):

    def __init__(self):
        self._connection = Inject('database connection')
        self._conta_dao = Inject('conta dao')
        self._produto_dao = Inject('produto dao')
        self._fornecedor_dao = Inject('fornecedor dao')
        self._lancamento_dao = Inject('lancamento dao')

        self._unknown_contas = None
        self._unknown_produtos = None
        self._unknown_fornecedores = None

    @staticmethod
    def import_parser_created_handler(import_parser):
        import_csv_parser = import_parser.add_parser('csv', help='Importa um arquivo .csv')
        import_csv_parser.set_defaults(event='import_csv_command')

        import_csv_parser.add_argument('-c', '--confirm', action='store_true',
                                       help='Confirma a importação, caso contrário apenas mostra em tela o que será importado')
        import_csv_parser.add_argument("filename", help="Nome do arquivo que será importado")

    def import_csv_command_handler(self, args):
        source = open(args.filename, 'r')

        self._unknown_contas = set()
        self._unknown_produtos = set()
        self._unknown_fornecedores = set()

        ok = True

        lancamentos = []

        try:
            for self._i, self._line in enumerate(source):
                fields_array = self._get_fields_array()

                if not self._validate(fields_array, lambda f: len(f) >= 4, None,
                                      'every line must have at least 4 fields'):
                    continue

                fields = self._get_fields(fields_array)

                ok &= self._validate_fields(*fields)

                if ok:
                    lancamento = self._make_lancamento(*fields)

                    if args.confirm:
                        self._lancamento_dao.insert(lancamento)
                    else:
                        lancamentos.append(lancamento)

        except Exception:
            self._connection.rollback()
            raise

        if ok:
            if args.confirm:
                self._connection.commit()

                return 'imported', {'filename': args.filename}
            else:
                return 'simulated', {'filename': args.filename, 'lancamentos': lancamentos}

        else:
            if args.confirm:
                self._connection.rollback()

            return 'error', {'filename': args.filename, 'unknown_contas': self._unknown_contas,
                             'unknown_produtos': self._unknown_produtos,
                             'unknown_fornecedores': self._unknown_fornecedores}

    def _get_fields_array(self):
        if self._line.endswith('\n'):
            self._line = self._line[:-1]

        fields = self._line.split(';')

        return fields

    def _validate(self, data, validator, validation_fail_callback, message):
        if not validator(data):
            print('[ERROR] Line {}: {}'.format(self._i + 1, message.format(data)))

            if validation_fail_callback:
                validation_fail_callback()

            return False

        return True

    def _get_fields(self, fields_array):
        data = fields_array[0]
        origem = fields_array[1]
        destino = fields_array[2]
        valor = fields_array[3]

        observacoes = self._get(fields_array, 4)
        produto = self._get(fields_array, 5)
        quantidade = self._get(fields_array, 6)
        fornecedor = self._get(fields_array, 7)

        return data, origem, destino, valor, observacoes, produto, quantidade, fornecedor

    def _validate_fields(self, data, origem, destino, valor, observacoes, produto, quantidade, fornecedor):
        ok = self._validate(data, self._data_ok, None, 'date "{{}}" is not in format "{}"'.format(_CSV_DATE_FORMAT))

        ok &= self._validate(origem, self._conta_dao.by_name, lambda: self._unknown_contas.add(origem),
                             'origem "{}" doesnt exists')

        ok &= self._validate(destino, self._conta_dao.by_name, lambda: self._unknown_contas.add(destino),
                             'destino "{}" doesnt exists')

        ok &= self._validate(valor, self._valor_ok, None, 'valor "{}" is not in valid format')

        if produto:
            ok &= self._validate(produto, self._produto_dao.by_name, lambda: self._unknown_produtos.add(produto),
                                 'produto "{}" not found')

        if quantidade:
            ok &= self._validate(quantidade, self._is_float, None, 'quantidade "{}" is not a float value')

        if fornecedor:
            ok &= self._validate(fornecedor, self._fornecedor_dao.by_name,
                                 lambda: self._unknown_fornecedores.add(fornecedor), 'fornecedor "{}" not found')

        return ok

    def _make_lancamento(self, data, origem, destino, valor, observacoes, produto, quantidade, fornecedor):
        lancamento = Lancamento()

        # TODO Extract a formatter from the following two lines
        lancamento.data = datetime.strftime(datetime.strptime(data, _CSV_DATE_FORMAT), _SQLITE_DATE_FORMAT)
        lancamento.valor = int(valor.replace('.', ''))
        lancamento.origem = self._conta_dao.by_name(origem)
        lancamento.destino = self._conta_dao.by_name(destino)
        lancamento.observacoes = observacoes
        lancamento.produto = self._produto_dao.by_name(produto) if produto else None
        lancamento.quantidade = quantidade
        lancamento.fornecedor = self._fornecedor_dao.by_name(fornecedor) if fornecedor else None

        return lancamento

    @staticmethod
    def _get(fields, index, default=None):
        return fields[index] if len(fields) >= index + 1 else default

    @staticmethod
    def _data_ok(value):
        try:
            datetime.strptime(value, _CSV_DATE_FORMAT)

            return True
        except ValueError:
            return False

    @staticmethod
    def _valor_ok(valor):
        try:
            # TODO Internacionalize this to work with , for decimal point!
            Decimal(valor)
            return True
        except InvalidOperation:
            return False

    @staticmethod
    def _is_float(value):
        try:
            float(value)
            return True
        except ValueError:
            return False

    @staticmethod
    def import_csv_command_imported_handler(filename):
        print('Arquivo "{}" importado com sucesso!'.format(filename))

    @staticmethod
    def import_csv_command_simulated_handler(filename, lancamentos):
        print('Simulated import for file "{}" (use --confirm to actually import), would create lancamentos:'.format(
            filename))

        for lancamento in lancamentos:
            print(ImportCSVCommand._make_lancamento_string(lancamento))

    @staticmethod
    def _make_lancamento_string(lancamento):
        values = list()

        values.append(str(lancamento.data))
        values.append(str(lancamento.origem))
        values.append(str(lancamento.destino))
        values.append(str(lancamento.valor))
        values.append(str(lancamento.observacoes)) if lancamento.observacoes else None
        values.append(str(lancamento.produto)) if lancamento.produto else None
        values.append(str(lancamento.quantidade)) if lancamento.quantidade else None
        values.append(str(lancamento.fornecedor)) if lancamento.fornecedor else None

        return '; '.join(values)

    @staticmethod
    def import_csv_command_error_handler(filename, unknown_contas, unknown_produtos, unknown_fornecedores):
        print('Erros importando arquivo "{}"!'.format(filename))
        print()

        ImportCSVCommand._print_array('Contas desconhecidas:', unknown_contas)
        ImportCSVCommand._print_array('Produtos desconhecidos:', unknown_produtos)
        ImportCSVCommand._print_array('Fornecedores desconhecidos:', unknown_fornecedores)

    @staticmethod
    def _print_array(message, array):
        if len(array) == 0:
            return

        print(message)

        for conta in array:
            print(conta)

        print()