def calc_first_transfer_amount(user, goal_amount, path, source): """ The first transfer, from the "outest program", is the only one that is not the full balance capacity. """ # Start by transferring from last source product_ratio_balance = [] ratios = [] # We only want to take into account how much could have been transferred thus far node = path.head.next while node.next: # node.data = outgoing_program id # node.next.data = receiving_program id edge_ratio = ratio_instance(node.data, node.next.data).ratio_to() node_balance = calc_balance_ceiling( user.get_balance(node.data).current_balance, edge_ratio) product_ratio_balance.append(edge_ratio * node_balance) node = node.next # We calculate the transfer amount as follows: # Step 1) goal_amount minus what has been transferred thus far, which is the product of edge ratio and balance between two prgograms # Step 2) result of step 1 divide by the cumulative ratios, np.prod((ratios)), yields the amount needed from the last outgoing program # Step 3) result of step 2 divide by the ratio between the last program the one preceding one to get the amount outgoing required ratio = ratio_instance(path.head.data, path.head.next.data).ratio_to() # Minimum, transfer either goal amount or upto balance ceiling transfer_amount = min( ((goal_amount - sum(product_ratio_balance)) / np.prod(ratios)) / ratio, calc_balance_ceiling( user.get_balance(path.head.data).current_balance, ratio)) return transfer_amount
def transfer_json(): if "user" not in session: flash("Please log in before navigating to the dashboard") return redirect('/') user = User.query.get(session["user"]) transfers = user.get_transfers() i = 1 transfer_history = {} for transfer in transfers: ratio = ratio_instance(transfer.outgoing_program, transfer.receiving_program) receiving_amount = int(transfer.outgoing_amount * ratio.ratio_to()) transfer_history["(" + str(transfer.transfer_id) + ")"] = { "transfer_id": i, "outgoing": transfer.outgoing.program_name, "outgoing_amount": "{:,}".format(transfer.outgoing_amount), "receiving": transfer.receiving.program_name, "receiving_amount": "{:,}".format(receiving_amount), "timestamp": transfer.transferred_at, "ratio": str(ratio.numerator) + " : " + str(ratio.denominator), } i += 1 return jsonify(transfer_history)
def balance_capacity(user, current): if current.prev is None: return 0 ratio = ratio_instance(current.prev.data, current.data).ratio_to() balance = user.get_balance(current.prev.data).current_balance current = current.prev return floor((ratio * balance) + balance_capacity(user, current))
def create_path_dictionary(outgoing_id, receiving_id, amount): path = {} transfer = ratio_instance(outgoing_id, receiving_id) path["outgoing"] = Program.query.get(outgoing_id).program_name path["outgoing_url"] = Program.query.get(outgoing_id).vendor.url path["receiving"] = Program.query.get(receiving_id).program_name path["receiving_url"] = Program.query.get(receiving_id).vendor.url path["amount"] = amount path["numerator"] = transfer.numerator path["denominator"] = transfer.denominator return path
def transfer_balance(): """transfer user balance from one program to another.""" if "user" not in session: flash("Please sign in first") return redirect("/login") user = User.query.get(session["user"]) outgoing_id = int(request.form.get("outgoing")) receiving_id = int(request.form.get("receiving")) amount = int(request.form.get("amount")) balance_from = user.get_balance(outgoing_id) # Constraint for positive balance if balance_from.current_balance < amount: return "Not enough outstanding points for this transfer" balance_to = user.get_balance(receiving_id) ratio = ratio_instance(outgoing_id, receiving_id) if amount % ratio.denominator != 0: return "Please enter a transferable amount. See ratio above" user.add_transfer(outgoing_id, receiving_id, amount) db.session.commit() # For updating program balance table via jQuery transferred = {} transferred["outgoing"] = { "program_id": outgoing_id, "program_name": ratio.outgoing.program_name, "current_balance": balance_from.current_balance, "updated_at": balance_from.updated_at, } transferred["receiving"] = { "program_id": receiving_id, "program_name": ratio.receiving.program_name, "current_balance": balance_to.current_balance, "updated_at": balance_to.updated_at, } return jsonify(transferred)
def calc_transfer_amount(user, goal_amount=None, path=None, source=None, outgoing_id=None, receiving_id=None, is_first=False): if is_first: transfer_amount = calc_first_transfer_amount(user, goal_amount, path, source) else: edge_ratio = ratio_instance(outgoing_id, receiving_id).ratio_to() transfer_amount = calc_balance_ceiling( user.get_balance(outgoing_id).current_balance, edge_ratio) return transfer_amount
def return_ratio(): """Return ratio.""" if "user" not in session: flash("Please sign in first") return redirect("/login") user = User.query.get(session["user"]) outgoing = request.args.get("outgoing") receiving = request.args.get("receiving") if receiving: ratio = ratio_instance(outgoing, receiving) ratio = str(ratio.denominator) + " to " + str(ratio.numerator) return jsonify(ratio) else: receiving_programs = user.user_receiving_for(outgoing) program_id = [ program.receiving_program for program in receiving_programs ] vendor_name = [ program.receiving.vendor.vendor_name for program in receiving_programs ] program_name = [ program.receiving.program_name for program in receiving_programs ] receiving = { "program_id": program_id, "vendor_name": vendor_name, "program_name": program_name } return jsonify(receiving)