Example #1
0
def post_balances(app, account_id, request_json):
    if account_id == '_all':
        raise InvalidRequest('Invalid account_id')

    account = get_by_id(app, account_id)

    date = request_json.get('date')
    if date is None:
        raise InvalidRequest("Invalid field 'date'")
    try:
        date = datetime.datetime.strptime(date, '%Y-%m-%d')
    except ValueError:
        raise InvalidRequest("Invalid field 'date'")

    balance = request_json.get('balance')
    if balance is None:
        raise InvalidRequest("Invalid field 'balance'")
    try:
        balance = Decimal(balance)
    except InvalidOperation:
        raise InvalidRequest("Invalid field 'balance'")

    with db_transaction(app.session) as session:
        account_balance = AccountBalance(account_id=account_id, date=date, balance=balance)
        session.add(account_balance)
    return {'account_id': account.id, 'id': account_balance.id}
Example #2
0
def delete_balances(app, account_id, id):
    account_balance = AccountBalance.get_by_id(id)
    if account_balance.account_id != int(account_id):
        raise ResourceNotFound()
    with db_transaction(app.session) as session:
        session.delete(account_balance)
    return {'account_id': account_id, 'id': id}
Example #3
0
def delete(app, account_id):
    account = get_by_id(app, account_id)
    with db_transaction(app.session) as session:
        account.deleted = True
        for t in account.transactions:
            t.deleted = True
            session.add(t)
        session.add(account)
    return {'accountId': account_id}
Example #4
0
def delete(app, transaction_id):
    query = app.session.query(Transaction).filter_by(id=transaction_id)
    if query.count() != 1:
        raise exceptions.ResourceNotFound()

    transaction = query.one()
    with db_transaction(app.session) as session:
        transaction.deleted = True
        session.add(transaction)
    return {'transactionId': transaction_id}
Example #5
0
def post(app, request_json):
    try:
        with db_transaction(app.session) as session:
            request_json['account']['id'] = None
            account = Account(**request_json['account'])
            session.add(account)
    except Exception as e:
        raise InvalidRequest(str(e))
    else:
        account_id = account.id
        account = get_by_id(app, account_id)
        return {'account': account.to_dict()}
Example #6
0
def put(app, account_id, request_json):
    account = get_by_id(app, account_id)
    try:
        with db_transaction(app.session) as session:
            for key, value in request_json['account'].items():
                setattr(account, key, value)
            session.add(account)
    except Exception as e:
        raise InvalidRequest(str(e))
    else:
        account_id = account.id
        account = get_by_id(app, account_id)
        return {'account': account.to_dict()}
Example #7
0
def update(app, transaction_id, request_json):
    query = app.session.query(Transaction).filter_by(id=transaction_id)
    if query.count() != 1:
        raise exceptions.ResourceNotFound()

    transaction = query.one()
    for key, value in request_json.items():
        setattr(transaction, key, value)

    with db_transaction(app.session) as session:
        session.add(transaction)
    transaction = app.session.query(Transaction).filter_by(id=transaction_id).one()
    return {'transactions': [transaction.to_dict()]}
Example #8
0
def upload(app, files):
    session = app.session
    file_items = ensure_single_file_uploaded(files)
    filename, file_storage = file_items[0]
    ensure_file_extension(filename)

    parser = OfxParser()
    ofxfile = parser.parse(file_storage)
    account_signature = calculate_account_signature(ofxfile.account)

    file_storage.seek(0)
    file_upload = FileUpload(filename=filename, uploaded_at=datetime.datetime.utcnow(),
                             file_content=base64.b64encode(file_storage.read()),
                             account_signature=account_signature)

    with db_transaction(session):
        session.add(file_upload)

    query = (
        FileUpload.query().with_entities(FileUpload.account_id, func.count(FileUpload.id))
        .filter(FileUpload.account_id != None)  # noqa
        .filter(FileUpload.account_signature == account_signature)
        .group_by(FileUpload.account_id)
        .order_by(func.count(FileUpload.id).desc())
    )
    result = query.all()
    if not result:
        link = {
            'accountId': None,
            'confidenceIndex': None
        }
    else:
        account_id = result[0][0]
        confidence_index = 1.0 * result[0][1] / sum([r[1] for r in result])
        link = {
            'accountId': account_id,
            'confidenceIndex': confidence_index
        }

    return {
        'id': file_upload.id,
        'signature': account_signature,
        'link': link,
    }
Example #9
0
def link(app, file_upload_id, request_json):
    session = app.session
    try:
        file_upload = FileUpload.get_by_id(file_upload_id)
    except NoResultFound:
        raise ResourceNotFound()

    if file_upload.account_id is not None:
        raise InvalidRequest('file_upload {} is already associated with an account'.format(file_upload_id))

    account_id = request_json['accountId']
    if account_id == 'NEW':
        account = Account(
            institution='Unnamed',
            name='Unnamed',
            type='N/A',
        )
        with db_transaction(session):
            session.add(account)
    else:
        try:
            account = Account.get_by_id(account_id)
        except NoResultFound:
            raise InvalidRequest('Invalid account_id: {}'.format(account_id))

    file_content = base64.b64decode(file_upload.file_content)
    parser = OfxParser()
    ofxfile = parser.parse(StringIO(file_content))

    total_imported, total_skipped = 0, 0
    for t in ofxfile.account.statement.transactions:
        transaction = Transaction(date=t.date,
                                  info=t.memo,
                                  payee=t.payee,
                                  memo=t.memo,
                                  amount=t.amount,
                                  transaction_type=t.type,
                                  category_id=TBD_CATEGORY_ID,
                                  account_id=account.id)
        try:
            with db_transaction(session):
                session.add(transaction)
                total_imported += 1
        except IntegrityError:
            total_skipped += 1
            logger.warn('Skip duplicated transaction: {}. checksum: {}'.format(transaction, transaction.checksum))

    file_upload.account_id = account.id
    # record account balance history
    account_balance = AccountBalance(
        account_id=account.id,
        date=ofxfile.account.statement.balance_date,
        balance=ofxfile.account.statement.balance
    )

    try:
        with db_transaction(session):
            session.add(file_upload)
            session.add(account_balance)
    except IntegrityError:
        logger.info('Already a record of account balance for account {} on {}'.format(account_balance.account_id,
                                                                                      account_balance.date))

    return {'account_id': account.id, 'total_imported': total_imported, 'total_skipped': total_skipped}