Example #1
0
def parse_credit_card_transaction(bank_config, account_config, card_config, transaction):

    amount = decode_numeric_value(transaction['importeMovimiento'])
    transaction_code = transaction['claveMovimiento']
    # F**K BANKIA, removed sign from values
    # transaction_direction = TransactionDirection.CHARGE if amount < 0 else TransactionDirection.INCOME
    transaction_direction = infer_transaction_direction(transaction_code)
    if transaction_direction is TransactionDirection.CHARGE:
        amount = amount * -1

    transaction_type = get_type(transaction_code, transaction_direction)

    details = get_card_transaction_details(transaction, transaction_type)
    details['account'] = Account.from_config(account_config)
    details['bank'] = Bank.from_config(bank_config)

    # As we are processing a concrete card, and transaction doesn't have this
    # information, we set it to be able to process all transactions equally
    card_used = Card.from_config(card_config)

    keywords = extract_keywords(
        chain(
            extract_literals(transaction, KEYWORD_FIELDS),
            filter(lambda value: isinstance(value, str), details.values())
        )
    )

    comment = get_comment(details, transaction_type)

    source = get_source(details, transaction_type)
    destination = get_destination(details, transaction_type)
    del details['bank']
    del details['account']

    return ParsedCreditCardTransaction(
        transaction_id=None,
        currency=transaction['importeMovimiento']['nombreMoneda'],
        amount=amount,
        value_date=decode_date(transaction['fechaMovimiento']['valor'], transaction['horaMovimiento']['valor']),
        transaction_date=decode_date(transaction['fechaMovimiento']['valor'], transaction['horaMovimiento']['valor']),
        type=transaction_type,
        source=source,
        destination=destination,
        card=card_used,
        details=details,
        keywords=keywords,
        comment=comment if comment is not None else '',
    )
Example #2
0
def parse_account_transaction(bank_config, account_config, transaction):
    amount = transaction['amount']['amount']
    transaction_code = get_nested_item(transaction, 'scheme.subCategory.id')

    if transaction_code == '0054':  # "Otros ..."
        transaction_code = get_nested_item(transaction, 'concept.id')

    transation_direction = TransactionDirection.CHARGE if amount < 0 else TransactionDirection.INCOME
    transaction_type = get_type(transaction_code, transation_direction)

    details = get_account_transaction_details(transaction, transaction_type)
    details['account'] = Account.from_config(account_config)
    details['bank'] = Bank.from_config(bank_config)

    card_number = details.pop('card_number', None)
    used_card = get_card(account_config, card_number)

    keywords = extract_keywords(
        chain(extract_literals(transaction, KEYWORD_FIELDS),
              filter(lambda value: isinstance(value, str), details.values())))

    comment = get_comment(details, transaction_type)

    source = get_source(details, transaction_type)
    destination = get_destination(details, transaction_type)
    del details['bank']

    return ParsedBankAccountTransaction(
        transaction_id=transaction['id'],
        type=transaction_type,
        currency=transaction['amount']['currency']['code'],
        amount=amount,
        balance=transaction['balance']['availableBalance']['amount'],
        value_date=decode_date(transaction['valueDate']),
        transaction_date=decode_date(transaction['transactionDate']),
        source=source,
        destination=destination,
        account=details.pop('account'),
        card=used_card,
        details=details,
        keywords=keywords,
        comment=comment if comment is not None else '',
    )
Example #3
0
def parse_account_transaction(bank_config, account_config, transaction):
    amount = decode_numeric_value(transaction['importe'])
    transaction_code = transaction['codigoMovimiento']
    transaction['referencias'] = references_by_code(transaction)
    transaction_direction = TransactionDirection.CHARGE if amount < 0 else TransactionDirection.INCOME
    transaction_type = get_type(transaction_code, transaction_direction)

    details = get_account_transaction_details(transaction, transaction_type)
    details['account'] = Account.from_config(account_config)
    details['bank'] = Bank.from_config(bank_config)

    card_number = details.pop('card_number', None)
    card_used = get_card(account_config, card_number)

    keywords = extract_keywords(
        chain(
            extract_literals(transaction, KEYWORD_FIELDS),
            filter(lambda value: isinstance(value, str), details.values())
        )
    )

    comment = get_comment(details, transaction_type)

    source = get_source(details, transaction_type)
    destination = get_destination(details, transaction_type)
    del details['bank']

    return ParsedBankAccountTransaction(
        transaction_id=None,
        currency=transaction['importe']['moneda']['nombreCorto'],
        amount=amount,
        balance=decode_numeric_value(transaction['saldoPosterior']),
        value_date=decode_date(transaction['fechaValor']['valor'], ),
        transaction_date=decode_date(transaction['fechaMovimiento']['valor']),
        type=transaction_type,
        source=source,
        destination=destination,
        account=details.pop('account'),
        card=card_used,
        details=details,
        keywords=keywords,
        comment=comment if comment is not None else '',
    )
Example #4
0
def accounts_root():
    """
        ---
        get:
          summary: Get all accounts this user has access to
          tags:
            - Accounts
          description:
            Returns the list of accounts that this user (person or bot) has permission to access. The list is returned in a single array (no pagination).
          responses:
            200:
              content:
                application/json:
                  schema:
                    type: object
                    properties:
                      list:
                        type: array
                        items:
                          "$ref": '#/definitions/AccountGET'
    """
    user_id = flask.g.grafolean_data['user_id']
    accounts = Account.get_list(user_id)
    return json.dumps({'list': accounts}), 200
Example #5
0
def account_crud(account_id):
    """
        ---
        get:
          summary: Get an account
          tags:
            - Accounts
          description:
            Returns account data.
          parameters:
            - name: account_id
              in: path
              description: "Account id"
              required: true
              schema:
                type: integer
          responses:
            200:
              content:
                application/json:
                  schema:
                    "$ref": '#/definitions/AccountGET'
            404:
              description: No such account
        put:
          summary: Update the account
          tags:
            - Accounts
          description:
            Updates account name.
          parameters:
            - name: account_id
              in: path
              description: "Account id"
              required: true
              schema:
                type: integer
            - name: "body"
              in: body
              description: "Account data"
              required: true
              schema:
                "$ref": '#/definitions/AccountPOST'
          responses:
            204:
              description: Update successful
            404:
              description: No such account

    """
    if flask.request.method in ['GET', 'HEAD']:
        rec = Account.get(account_id)
        if not rec:
            return "No such account", 404
        return json.dumps(rec), 200

    elif flask.request.method == 'PUT':
        rec = Account.forge_from_input(flask.request.get_json(),
                                       force_id=account_id)
        rowcount = rec.update()
        if not rowcount:
            return "No such account", 404
        mqtt_publish_changed([
            'accounts/{account_id}'.format(account_id=account_id),
        ])
        return "", 204
Example #6
0
def parse_credit_card_transaction(bank_config, account_config, card_config,
                                  transaction):
    amount = transaction['amount']['amount']
    transaction_code = get_nested_item(transaction, 'concept.id')
    if transaction_code == '0000':
        # code 0000 seems like an error, as it's really a regular purcharse,
        # so we fake the code
        transaction_code = '0005'

    transation_direction = TransactionDirection.CHARGE if amount < 0 else TransactionDirection.INCOME
    transaction_type = get_type(transaction_code, transation_direction)

    # Transactions have a _PT or _TT termination, that changes once over time and makes id unusable
    # this is an attempt to fix this and still being able to use the id as an unique id
    transaction_id = re.sub(r'_[PT]T$', '', transaction['id'])

    details = get_card_transaction_details(transaction, transaction_type)
    details['account'] = Account.from_config(account_config)
    details['bank'] = Bank.from_config(bank_config)

    # As we are processing a concrete card, and transaction doesn't have this
    # information, we set it to be able to process all transactions equally
    card_used = Card.from_config(card_config)

    keywords = extract_keywords(
        chain(extract_literals(transaction, KEYWORD_FIELDS),
              filter(lambda value: isinstance(value, str), details.values())))

    comment = get_comment(details, transaction_type)

    source = get_source(details, transaction_type)
    destination = get_destination(details, transaction_type)
    del details['bank']
    del details['account']

    is_debit_operation = transaction.get('operationTypeIndicator') == 'D'
    is_consolidated = transaction.get('status', {}).get('id') == '7'

    notify_not_added = False
    status_flags = datatypes.StatusFlags()

    if is_debit_operation:
        if notify_not_added:
            from common.notifications import get_notifier
            import bank
            banking_configuration = bank.load_config(
                bank.env()['main_config_file'])
            notifier = get_notifier(banking_configuration.notifications)
            notifier(
                'Debit transaction found, not adding {bank.name} card transaction: {date} {amount}, {source}->{destination}'
                .format(bank=bank_config,
                        amount=amount,
                        date=transaction['valueDate'],
                        source=str(source),
                        destination=str(destination)))
        status_flags.invalid = True

    if not is_consolidated and notify_not_added:
        if notify_not_added:
            from common.notifications import get_notifier
            import bank
            banking_configuration = bank.load_config(
                bank.env()['main_config_file'])
            notifier = get_notifier(banking_configuration.notifications)
            notifier(
                'Non consolidated transaction found, not adding {bank.name} card transaction: {date} {amount}, {source}->{destination}'
                .format(bank=bank_config,
                        amount=amount,
                        date=transaction['valueDate'],
                        source=str(source),
                        destination=str(destination)))
        return None

    return ParsedCreditCardTransaction(
        transaction_id=transaction_id,
        type=transaction_type,
        currency=transaction['amount']['currency']['code'],
        amount=amount,
        value_date=decode_date(transaction['valueDate']),
        transaction_date=decode_date(transaction['transactionDate']),
        source=source,
        destination=destination,
        card=card_used,
        details=details,
        keywords=keywords,
        comment=comment if comment is not None else '',
        status_flags=status_flags)
Example #7
0
def accounts_crud():
    """
        ---
        get:
          summary: Get accounts
          tags:
            - Admin
          description:
            Returns a list of accounts that this user has the permission to access. The list is returned in a single array (no pagination).
          responses:
            200:
              content:
                application/json:
                  schema:
                    type: object
                    properties:
                      list:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                              description: "Account id"
                            name:
                              type: string
                              description: "Account name"
        post:
          summary: Create an account
          tags:
            - Admin
          description:
            Creates an account.
          parameters:
            - name: "body"
              in: body
              description: "Account data"
              required: true
              schema:
                "$ref": '#/definitions/AccountSchemaInputs'
          responses:
            201:
              content:
                application/json:
                  schema:
                    type: object
                    properties:
                      id:
                        type: integer
                        description: "Account id"
                      name:
                        type: string
                        description: "Account name"
    """
    if flask.request.method in ['GET', 'HEAD']:
        rec = Account.get_list()
        return json.dumps({'list': rec}), 200

    elif flask.request.method == 'POST':
        account = Account.forge_from_input(flask.request.get_json())
        account_id = account.insert()
        return json.dumps({'name': account.name, 'id': account_id}), 201
Example #8
0
def make_test_account():
    return Account('TEST_ACCOUNT', '00000000001')