A REST payments API using in memory storage for a psuedo database.
This is the implementation of a technical assesment for [redacted] by Gabriel Kennedy
For this task you’ll create a basic web service that allows a single user to manage and submit payments. The service should comprise of a REST API, running in a technology of your choice. (Express is a popular choice for Node based applications). You can use in-memory storage in a database-like manner for the sake of this test. The service should:
- Allow a user to submit a payment.
- Should perform some basic validation rules on the payment and reject any unusual payments (some example rules are provided below).
- Should allow users to fetch payments information after they’ve been accepted.
- Should allow users to amend payments to change anything about them. Validation Rules At a minimum your API should ensure that:
- Payments for negative amounts cannot be submitted.
- All payments have a beneficiary name associated with them.
- All payments have a payment description associated with them. Feel free to add rules of your own to the list.
The user’s account now starts off with a balance of $1000. Update your service so that:
- Each payment accepted by the system reduces the user’s balance.
- New payments that would push the user into a negative balance are not accepted.
- The user can query the balance at any time and get the correct result.
Payments no longer need be made the same day they’re created. Payments can be scheduled to be up to a month in the future. Update your service so that:
- Users can specify an optional PayDate on their payments in YYYY-MM-DD format
- If a payment is dated for today, or for the next business day, it counts towards the balance
- If a payment is further out, it does not count towards the balance.
- A user can schedule payments in the future (i.e., 2 or more business days out), even if they don’t have the balance right now. To simplify this part of the test, please ignore public holidays when calculating business days
Run npm test
The in memory user DB is automatically populated from a users.json
file, and contains two users.
{
"id": "VQyftQazB",
"name": "Jimbo",
"balance": 1000
},
{
"id": "AwSLfAsEf",
"name": "Jones",
"balance": 0
}
Note: Some endpoints will require userId to be passed in naively as a URL query parameter ?userId=VQyftQazB
POST /payments/create?userId=:userId
Body: {
"amount": 100, //the amount to send
"description": "Some description", //payment description
"beneficiary_name": "Some Name",
"beneficiary_id": "AwSLfAsEf", //the userId of the recipient
}
Additionally you can include the optional Body parameter 'pay_date', with the YYYY-MM-DD format to schedule this payment.
{
"pay_date": "2024-06-10" //OPTIONAL - the future date to schedule this payment
}
If the passed pay_date
is dated for today, or for the next business day, it is immediately deducted from the sender's balance.
If pay_date
is a future date beyond that, no funds will be deducted until the payment is run at 4am on that date. Immediate funds are not required to be in your account balance in order to schedule this type of future payment.
the ID of the created payment.
{
"success": true,
"result": {
"paymentId": "MpJZ9eshR"
}
}
GET /users/:userId
Retrieves the balance for a user
{
"success": true,
"result": {
"balance": 100
}
}
GET /payments/:paymentId
Retrieves the details of a payment record
{
"success": true,
"result": {
"id": "vLajsqxIm",
"amount": 100
}
}
PATCH /payments/:paymentId?userId=:userId
Updates the details of a payment record. At this time only the description field can be updated.
Returns the updated payment record
{
"success": true,
"result": {
"payment": {
"id": "vLajsqxIm",
"amount": 100
}
}
}
GET /payments
Gets a list of all payment records
{
"success": true,
"result": [
{
"id": "VddFbA5Hf",
"amount": 100
}
]
}
GET /payments/future/upcoming
Gets all future payments that will run today
{
"success": true,
"result": [
{
"id": "VddFbA5Hf",
"amount": 100
}
]
}
POST /payments/future/upcoming
Body: null;
Runs all upcoming payments scheduled for today
{
"success": true
}
GET /payments/future/all
Gets all future payments
{
"success": true,
"result": [
{
"id": "VddFbA5Hf",
"amount": 100
}
]
}
POST /payments/future/all
Body: null;
Runs all upcoming payments scheduled, regardless of if they should run today
{
"success": true
}