Ejemplo n.º 1
0
def enter_transaction(request):
    """ Respond to the "/admin/account/transaction" URL.

        We let the user enter a transaction into the system.
    """
    if request.method == "GET":

        # We're displaying the form for the first time -> set up the default
        # values.

        err_msg                  = None
        type                     = "P"
        user_id                  = ""
        associated_user_id       = ""
        suffix                   = ""
        other_user_id            = ""
        other_associated_user_id = ""
        other_suffix             = ""
        amount                   = ""
        description              = ""

    elif request.method == "POST":

        # Respond to the user submitting our form.

        if request.POST.get("cancel") == "Cancel":
            return HttpResponseRedirect(reverse("tahua.admin_interface." +
                                                "views.main.main"))

        err_msg = None # initially.

        type                     = request.POST['type']
        user_id                  = request.POST['user_id']
        associated_user_id       = request.POST['associated_user_id']
        suffix                   = request.POST['suffix']
        other_user_id            = request.POST['other_user_id']
        other_associated_user_id = request.POST['other_associated_user_id']
        other_suffix             = request.POST['other_suffix']
        amount                   = request.POST['amount']
        description              = request.POST['description']

        account_id = account_helper.make_account_id(user_id,
                                                    associated_user_id,
                                                    suffix)
        if not account_helper.is_valid_account_id(account_id):
            err_msg = "You must enter a valid account identifier."

        if user_id not in ["", None]:
            try:
                user = User.objects.get(user_id=user_id)
            except User.DoesNotExist:
                err_msg = "There is no user with ID " + user_id

        if associated_user_id not in ["", None]:
            try:
                user = User.objects.get(user_id=associated_user_id)
            except User.DoesNotExist:
                err_msg = "There is no user with ID " + associated_user_id

        if err_msg == None:
            try:
                dec_amount = decimal.Decimal(amount)
            except decimal.InvalidOperation:
                err_msg = "Invalid amount."

        if err_msg == None:
            if type not in [Transaction.TYPE_DEPOSIT,
                            Transaction.TYPE_WITHDRAWAL,
                            Transaction.TYPE_PAYMENT,
                            Transaction.TYPE_REVERSAL,
                            Transaction.TYPE_ADJUSTMENT]:
                err_msg = "Please select a valid transaction type."

        if err_msg == None:
            if type == Transaction.TYPE_PAYMENT:
                other_account_id = \
                    account_helper.make_account_id(other_user_id,
                                                   other_associated_user_id,
                                                   other_suffix)
                if not account_helper.is_valid_account_id(other_account_id):
                    err_msg = "You must enter a valid other account identifier."

        # If the entered data was accepted, enter the transaction into the
        # system.

        if err_msg == None:
            account = account_helper.get_or_create_account(account_id)
            if type == Transaction.TYPE_PAYMENT:
                other_account = \
                    account_helper.get_or_create_account(other_account_id)
            else:
                other_account = None

            meta_data = {}
            if description != "":
                meta_data['description'] = description

            if type == Transaction.TYPE_PAYMENT:
                dec_amount = -dec_amount # Deduct amount from source account.

            transaction = Transaction()
            transaction.account       = account
            transaction.other_account = other_account
            transaction.timestamp     = datetime.datetime.now()
            transaction.type          = type
            transaction.amount        = dec_amount
            transaction.metadata      = json.dumps(meta_data)
            transaction.save()

            # If the user is entering a payment, enter the reverse transaction
            # at the same time.

            if type == Transaction.TYPE_PAYMENT:
                transaction = Transaction()
                transaction.account       = other_account
                transaction.other_account = account
                transaction.timestamp     = datetime.datetime.now()
                transaction.type          = type
                transaction.amount        = -dec_amount
                transaction.metadata      = json.dumps(meta_data)
                transaction.save()

            # Finally, tell the user about the entered transaction.

            if type == Transaction.TYPE_PAYMENT:
                msg = utils.formatDecimalAsMoney(-dec_amount) \
                    + " has been transferred from " + account.describe() \
                    + " to " + other_account.describe() + "."
            else:
                msg = 'A transaction of type "' + transaction.type_to_string() \
                    + '" to the value of ' \
                    + utils.formatDecimalAsMoney(dec_amount) \
                    + ' has been entered against the ' \
                    + account.describe()

            return render_to_response("admin_interface/" +
                                      "transaction_entered.html",
                                      {'msg' : msg},
                                      context_instance=RequestContext(request))

    # If we get here, display the form to the user.

    return render_to_response("admin_interface/enter_transaction.html",
                              {'err_msg'                  : err_msg,
                               'type'                     : type,
                               'user_id'                  : user_id,
                               'associated_user_id'       : associated_user_id,
                               'suffix'                   : suffix,
                               'other_user_id'            : other_user_id,
                               'other_associated_user_id' :
                                                       other_associated_user_id,
                               'other_suffix'             : other_suffix,
                               'amount'                   : amount,
                               'description'              : description},
                              context_instance=RequestContext(request))
Ejemplo n.º 2
0
Archivo: pay.py Proyecto: 3taps/Tahua
def pay(request):
    """ Respond to the "/pay" API call.
    """
    try:
        # Extract our payload from the request parameters.

        request_payload = api_helper.process_request(request)
        if "error" in request_payload:
            return request_payload["error"]

        # Check that the required fields have all been supplied.

        error = api_helper.check_fields(
            request_payload,
            required_fields=["session_key", "from_account_id", "to_account_id", "amount"],
            optional_fields=["pin_number", "meta_data"],
        )
        if error != None:
            return error

        # Get the values we need from the payload.

        session = request_payload["session"]
        from_account_id = request_payload["fields"]["from_account_id"]
        to_account_id = request_payload["fields"]["to_account_id"]
        amount = decimal.Decimal(request_payload["fields"]["amount"])
        pin_number = request_payload["fields"].get("pin_number")
        meta_data = request_payload["fields"].get("meta_data")

        # If the "to" account refers to a user alias, call the user alias
        # resolver to translate from the user alias to the underlying user ID.

        if isinstance(to_account_id, dict):
            if "user_alias" in to_account_id:
                user_id = alias_resolver.resolve(to_account_id["user_alias"])
                if user_id == None:
                    return api_helper.error(request_payload, api_errors.UNKNOWN_ACCOUNT_ALIAS)
                to_account_id["user_id"] = user_id
                del to_account_id["user_alias"]

        # Check that the "from" and "to" accounts are both valid.

        if not account_helper.is_valid_account_id(from_account_id):
            return api_helper.error(request_payload, api_errors.INVALID_ACCOUNT_ID)

        if not account_helper.is_valid_account_id(to_account_id):
            return api_helper.error(request_payload, api_errors.INVALID_ACCOUNT_ID)

        # Make sure the user is allowed to access the "from" account.

        if session.user.user_id != from_account_id.get("user_id"):
            return api_helper.error(request_payload, api_errors.UNAUTHORIZED)

        # If this transaction requires a PIN number, ensure that the correct
        # PIN has been supplied.

        max_payment_without_pin = account_helper.get_account_policy(from_account_id, "max_payment_without_pin")
        if max_payment_without_pin != None:
            if amount >= max_payment_without_pin:
                # We need a PIN number for this payment -> check that the
                # correct PIN has been supplied.
                if pin_number == None:
                    return api_helper.error(request_payload, api_errors.PIN_NUMBER_REQUIRED)

                if pin_number != session.user.pin_number:
                    return api_helper.error(request_payload, api_errors.INVALID_PIN_NUMBER)

        # Check that the amount isn't too high, or doesn't exceed the daily
        # transaction limit...eventually.

        # Check that the account has enough funds to cover the desired
        # transaction.

        min_account_balance = account_helper.get_account_policy(from_account_id, "min_account_balance")
        if min_account_balance == None:
            min_account_balance = decimal.Decimal("0.00")

        account_balance = account_helper.get_account_balance(from_account_id)
        if account_balance - amount < min_account_balance:
            return api_helper.error(request_payload, api_errors.INSUFFICIENT_FUNDS)

        # If necessary, create the Account record(s) for the from and to
        # accounts.

        from_account = account_helper.get_or_create_account(from_account_id)
        to_account = account_helper.get_or_create_account(to_account_id)

        # If we get here, we're ready to make this payment.  Create appropriate
        # Transaction records to transfer the funds from one account to the
        # other.

        timestamp = datetime.datetime.now()

        transaction = Transaction()
        transaction.account = from_account
        transaction.other_account = to_account
        transaction.timestamp = timestamp
        transaction.type = Transaction.TYPE_PAYMENT
        transaction.amount = -amount
        transaction.set_metadata(meta_data)
        transaction.save()

        transaction = Transaction()
        transaction.account = to_account
        transaction.other_account = from_account
        transaction.timestamp = timestamp
        transaction.type = Transaction.TYPE_PAYMENT
        transaction.amount = amount
        transaction.set_metadata(meta_data)
        transaction.save()

        # Update the 'update_id' values for both accounts, so that the various
        # clients will know that the accounts have been updated.

        account_helper.increment_update_id(from_account.id)
        account_helper.increment_update_id(to_account.id)

        # Finally, return an empty response payload back to the caller.  We
        # return an empty response (as opposed to an error response) when the
        # payment was successful.

        response_payload = {}
        return api_helper.response(request_payload, response_payload)
    except:
        traceback.print_exc()
        return HttpResponseServerError()