Skip to content

Commit

Permalink
5511 add apis and view for order history and receipts (#156)
Browse files Browse the repository at this point in the history
* initial hold, api view url

* Fix API

* hold

* add ol django mail

* email task, template, api

* hold

* Fix bug

* merge

* Emails being sent

* Extend base email

* Works with mailjet

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* ruff

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* ruff

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Update lock file

* Update open api

* Remove print

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* PR comments

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Add back param

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* ruff

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix

* fix

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* revert

* try

* fix

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
cp-at-mit and pre-commit-ci[bot] authored Oct 8, 2024
1 parent 85f3dd5 commit 8bb3732
Show file tree
Hide file tree
Showing 18 changed files with 476 additions and 36 deletions.
8 changes: 8 additions & 0 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
"description": "",
"required": false
},
"SITE_NAME": {
"description": "Name of the site.",
"required": false
},
"AWS_ACCESS_KEY_ID": {
"description": "AWS Access Key for S3 storage.",
"required": false
Expand Down Expand Up @@ -357,6 +361,10 @@
"description": "Shared secret for JWT auth tokens",
"required": true
},
"MITOL_MAIL_REPLY_TO_ADDRESS": {
"description": "E-mail to use for reply-to address of emails",
"required": false
},
"MITOPEN_SECURE_SSL_REDIRECT": {
"description": "Application-level SSL redirect setting.",
"value": "True"
Expand Down
22 changes: 11 additions & 11 deletions cart/templates/checkout_interstitial.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@ <h1 class="mt-4">Redirecting to the payment processor...</h1>

<form id="checkout_form" method="post" action="{{ checkout_payload.url }}">
{% if debug_mode %}
{% for key, value in form.items %}
<div><label for="{{ key }}">{{ key }}</label>
<input type="text" readonly="readonly" name="{{ key }}" value="{{ value }}" /></div>
{% endfor %}

<div>
<button class="btn btn-primary" type="submit">Redirect to CyberSource in <span id="countdown-time">5</span></button>
</div>
{% for key, value in form.items %}
<div><label for="{{ key }}">{{ key }}</label>
<input type="text" readonly="readonly" name="{{ key }}" value="{{ value }}" /></div>
{% endfor %}

<div>
<button class="btn btn-primary" type="submit">Redirect to CyberSource in <span id="countdown-time">5</span></button>
</div>
{% else %}
{% for key, value in form.items %}
<input type="hidden" readonly="readonly" name="{{ key }}" value="{{ value }}" />
{% endfor %}
{% for key, value in form.items %}
<input type="hidden" readonly="readonly" name="{{ key }}" value="{{ value }}" />
{% endfor %}
{% endif %}
</form>

Expand Down
9 changes: 9 additions & 0 deletions fixtures/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import pytest
import responses
from pytest_mock import PytestMockWarning
from rest_framework.test import APIClient
from urllib3.exceptions import InsecureRequestWarning


Expand Down Expand Up @@ -83,3 +84,11 @@ def mocked_responses():
"""Mock responses fixture"""
with responses.RequestsMock() as rsps:
yield rsps


@pytest.fixture()
def admin_drf_client(admin_user):
"""DRF API test client with admin user"""
client = APIClient()
client.force_authenticate(user=admin_user)
return client
219 changes: 219 additions & 0 deletions openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,53 @@ paths:
responses:
'200':
description: No response body
/api/v0/payments/orders/history/:
get:
operationId: api_v0_payments_orders_history_list
parameters:
- name: limit
required: false
in: query
description: Number of results to return per page.
schema:
type: integer
- name: offset
required: false
in: query
description: The initial index from which to return the results.
schema:
type: integer
tags:
- api
security:
- cookieAuth: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedOrderHistoryList'
description: ''
/api/v0/payments/orders/history/{id}/:
get:
operationId: api_v0_payments_orders_history_retrieve
parameters:
- in: path
name: id
schema:
type: string
required: true
tags:
- api
security:
- cookieAuth: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/OrderHistory'
description: ''
/integrated_system/:
get:
operationId: integrated_system_list
Expand Down Expand Up @@ -615,6 +662,137 @@ components:
required:
- id
- name
Line:
type: object
description: Serializes a line item for an order.
properties:
id:
type: integer
readOnly: true
quantity:
type: integer
maximum: 2147483647
minimum: 0
item_description:
type: string
readOnly: true
unit_price:
type: string
format: decimal
pattern: ^-?\d{0,7}(?:\.\d{0,2})?$
total_price:
type: string
format: decimal
pattern: ^-?\d{0,7}(?:\.\d{0,2})?$
product:
$ref: '#/components/schemas/Product'
required:
- id
- item_description
- product
- quantity
- total_price
- unit_price
Nested:
type: object
properties:
id:
type: integer
readOnly: true
password:
type: string
maxLength: 128
last_login:
type: string
format: date-time
nullable: true
is_superuser:
type: boolean
title: Superuser status
description: Designates that this user has all permissions without explicitly
assigning them.
username:
type: string
description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_
only.
pattern: ^[\w.@+-]+$
maxLength: 150
first_name:
type: string
maxLength: 150
last_name:
type: string
maxLength: 150
email:
type: string
format: email
title: Email address
maxLength: 254
is_staff:
type: boolean
title: Staff status
description: Designates whether the user can log into this admin site.
is_active:
type: boolean
title: Active
description: Designates whether this user should be treated as active. Unselect
this instead of deleting accounts.
date_joined:
type: string
format: date-time
groups:
type: array
items:
type: integer
description: The groups this user belongs to. A user will get all permissions
granted to each of their groups.
user_permissions:
type: array
items:
type: integer
description: Specific permissions for this user.
required:
- id
- password
- username
OrderHistory:
type: object
properties:
id:
type: integer
readOnly: true
state:
$ref: '#/components/schemas/StateEnum'
reference_number:
type: string
maxLength: 255
purchaser:
allOf:
- $ref: '#/components/schemas/Nested'
readOnly: true
total_price_paid:
type: string
format: decimal
pattern: ^-?\d{0,15}(?:\.\d{0,5})?$
lines:
type: array
items:
$ref: '#/components/schemas/Line'
created_on:
type: string
format: date-time
readOnly: true
updated_on:
type: string
format: date-time
readOnly: true
required:
- created_on
- id
- lines
- purchaser
- total_price_paid
- updated_on
PaginatedBasketItemList:
type: object
required:
Expand Down Expand Up @@ -684,6 +862,29 @@ components:
type: array
items:
$ref: '#/components/schemas/IntegratedSystem'
PaginatedOrderHistoryList:
type: object
required:
- count
- results
properties:
count:
type: integer
example: 123
next:
type: string
nullable: true
format: uri
example: http://api.example.org/accounts/?offset=400&limit=100
previous:
type: string
nullable: true
format: uri
example: http://api.example.org/accounts/?offset=200&limit=100
results:
type: array
items:
$ref: '#/components/schemas/OrderHistory'
PaginatedProductList:
type: object
required:
Expand Down Expand Up @@ -824,6 +1025,24 @@ components:
- sku
- system
- updated_on
StateEnum:
enum:
- pending
- fulfilled
- canceled
- refunded
- declined
- errored
- review
type: string
description: |-
* `pending` - Pending
* `fulfilled` - Fulfilled
* `canceled` - Canceled
* `refunded` - Refunded
* `declined` - Declined
* `errored` - Errored
* `review` - Review
securitySchemes:
cookieAuth:
type: apiKey
Expand Down
15 changes: 6 additions & 9 deletions payments/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,13 @@ def generate_checkout_payload(request):


def fulfill_completed_order(
order, payment_data, basket=None, source=POST_SALE_SOURCE_BACKOFFICE
order,
payment_data,
basket=None,
source=POST_SALE_SOURCE_BACKOFFICE, # noqa: ARG001
):
"""Fulfill the order."""
order.fulfill(payment_data, source)
order.save()
order.fulfill(payment_data)

if basket and basket.compare_to_order(order):
basket.delete()
Expand Down Expand Up @@ -179,14 +181,12 @@ def process_cybersource_payment_response(
msg = f"Transaction declined: {processor_response.message}"
log.debug(msg)
order.decline()
order.save()
return_message = order.state
elif processor_response.state == ProcessorResponse.STATE_ERROR:
# Error - something went wrong with the request
msg = f"Error happened submitting the transaction: {processor_response.message}"
log.debug(msg)
order.error()
order.save()
order.errored()
return_message = order.state
elif processor_response.state in [
ProcessorResponse.STATE_CANCELLED,
Expand All @@ -200,7 +200,6 @@ def process_cybersource_payment_response(
msg = f"Transaction cancelled/reviewed: {processor_response.message}"
log.debug(msg)
order.cancel()
order.save()
return_message = order.state

elif (
Expand Down Expand Up @@ -230,7 +229,6 @@ def process_cybersource_payment_response(
)
log.error(msg)
order.cancel()
order.save()
return_message = order.state

return return_message
Expand Down Expand Up @@ -373,7 +371,6 @@ def check_and_process_pending_orders_for_resolution(refnos=None):
).get()

order.fulfill(payload)
order.save()
fulfilled_count += 1

msg = f"Fulfilled order {order.reference_number}."
Expand Down
Loading

0 comments on commit 8bb3732

Please sign in to comment.