def get(self, disbursement_id): accounts = db.session.query(TransferAccount)\ .filter(TransferAccount.disbursements.any(id=disbursement_id))\ .options(joinedload(TransferAccount.disbursements)) accounts, total_items, total_pages, new_last_fetched = paginate_query( accounts) if accounts is None: response_object = { 'message': 'No transfer accounts', } return make_response(jsonify(response_object)), 400 transfer_accounts = transfer_accounts_schema.dump(accounts).data d = db.session.query(Disbursement).filter_by( id=disbursement_id).first() disbursement = disbursement_schema.dump(d).data response_object = { 'status': 'success', 'message': 'Successfully Loaded.', 'data': { 'transfer_accounts': transfer_accounts, 'disbursement': disbursement } } return make_response(jsonify(response_object)), 200
def get(self, disbursement_id): transfers = db.session.query(CreditTransfer)\ .filter(CreditTransfer.disbursement.has(id=disbursement_id))\ .options(joinedload(CreditTransfer.disbursement)) transfers, total_items, total_pages, new_last_fetched = paginate_query( transfers) if transfers is None: response_object = { 'message': 'No credit transfers', } return make_response(jsonify(response_object)), 400 transfer_list = credit_transfers_schema.dump(transfers).data d = db.session.query(Disbursement).filter_by( id=disbursement_id).first() disbursement = disbursement_schema.dump(d).data response_object = { 'status': 'success', 'message': 'Successfully Loaded.', 'items': total_items, 'pages': total_pages, 'last_fetched': new_last_fetched, 'data': { 'credit_transfers': transfer_list, 'disbursement': disbursement } } return make_response(jsonify(response_object)), 200
def put(self, disbursement_id): put_data = request.get_json() action = put_data.get('action', '').upper() notes = put_data.get('notes') or '' if not disbursement_id: return {'message': 'Please provide a disbursement_id'}, 400 if not action: return {'message': 'Please provide an action'}, 400 if action not in ['APPROVE', 'REJECT']: # We might want more actions later! return {'message': f'{action} not a valid action'}, 400 # Ensure it's impossible to have two threads operating on the same disbursement with red.lock(name=f'Disbursemnt{disbursement_id}', timeout=10, blocking_timeout=20): disbursement = Disbursement.query.filter(Disbursement.id == disbursement_id)\ .options(joinedload(Disbursement.credit_transfers))\ .first() disbursement.notes = notes if not disbursement: return { 'message': f'Disbursement with ID \'{disbursement_id}\' not found' }, 400 if disbursement.state in ['APPROVED', 'REJECTED']: return { 'message': f'Disbursement with ID \'{disbursement_id}\' has already been set to {disbursement.state.lower()}!' }, 400 if action == 'APPROVE': disbursement.approve() db.session.commit() auto_resolve = False if current_app.config[ 'REQUIRE_MULTIPLE_APPROVALS'] or AccessControl.has_sufficient_tier( g.user.roles, 'ADMIN', 'superadmin'): auto_resolve = True # A disbursement isn't necessarily approved after approve() is called, since we can require multiple approvers task_uuid = None if disbursement.state == 'APPROVED': task_uuid = add_after_request_checkable_executor_job( make_transfers, kwargs={ 'disbursement_id': disbursement.id, 'auto_resolve': auto_resolve }) data = disbursement_schema.dump(disbursement).data return { 'status': 'success', 'data': { 'disbursement': data }, 'task_uuid': task_uuid }, 200 if action == 'REJECT': disbursement.reject() db.session.commit() data = disbursement_schema.dump(disbursement).data return { 'status': 'success', 'data': { 'disbursement': data }, }, 200
def post(self): post_data = request.get_json() # --- Handle Parameters --- # HANDLE PARAM : label - Name for the disbursement label = post_data.get('label') or '' # HANDLE PARAM : search_string - Any search string. An empty string (or None) will just return everything! search_string = post_data.get('search_string') or '' # HANDLE PARAM : params - Standard filter object. Exact same as the ones Metrics uses! encoded_filters = post_data.get('params') filters = process_transfer_filters(encoded_filters) # HANDLE PARAM : include_accounts - Explicitly include these users include_accounts = post_data.get('include_accounts', []) # HANDLE PARAM : include_accounts - Explicitly exclude these users exclude_accounts = post_data.get('exclude_accounts', []) disbursement_amount = abs( round(Decimal(post_data.get('disbursement_amount') or 0), 6)) if include_accounts and exclude_accounts: return { 'message': 'Please either include or exclude users (include is additive from the whole search, while exclude is subtractive)' } # HANDLE PARAM : transfer_type - Transfer type-- either DISBURSEMENT, RECLAMATION, or BALANCE transfer_type = post_data.get('transfer_type', 'DISBURSEMENT') if transfer_type not in ['DISBURSEMENT', 'RECLAMATION', 'BALANCE']: return { 'message': f'{transfer_type} not a valid transfer type. Please choose one of DISBURSEMENT, RECLAMATION, or BALANCE' } order_arg = request.args.get('order') or 'DESC' if order_arg.upper() not in ['ASC', 'DESC']: return { 'message': 'Invalid order value \'{}\'. Please use \'ASC\' or \'DESC\''. format(order_arg) } order = asc if order_arg.upper() == 'ASC' else desc sort_by_arg = request.args.get('sort_by') or 'rank' # --- Build Disbursement Object --- d = Disbursement(creator_user=g.user, label=label, search_string=search_string, search_filter_params=encoded_filters, include_accounts=include_accounts, exclude_accounts=exclude_accounts, disbursement_amount=disbursement_amount, transfer_type=transfer_type) if include_accounts: transfer_accounts = db.session.query(TransferAccount).filter( TransferAccount.id.in_(include_accounts)).all() else: search_query = generate_search_query(search_string, filters, order, sort_by_arg, include_user=True) search_query = search_query.filter( TransferAccount.id.notin_(exclude_accounts)) results = search_query.all() transfer_accounts = [ r[0] for r in results ] # Get TransferAccount (TransferAccount, searchRank, User) d.transfer_accounts.extend(transfer_accounts) db.session.flush() disbursement = disbursement_schema.dump(d).data response_object = { 'data': { 'status': 'success', 'disbursement': disbursement } } return make_response(jsonify(response_object)), 201