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}
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}
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}
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}
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()}
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()}
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()]}
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, }
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}