Skip to content

Commit 579333f

Browse files
authored
Merge pull request #59 from diging/develop
Prepare next release
2 parents 0339b2d + fcf4ed5 commit 579333f

File tree

13 files changed

+127
-31
lines changed

13 files changed

+127
-31
lines changed

.env_app_example

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@
66
export APP_ROOT="edrop/"
77
# adjust this property to the host edrop is running on
88
export ALLOWED_HOSTS="localhost,127.0.0.1"
9-
# add hostname of server here: https://myhost.org/
9+
# add hostname of server here: https://myhost.org
1010
export CSRF_TRUSTED_ORIGINS=""
1111

1212
export DATA_PATH=/data/files/
1313
export MEDIA_URL_PATH=/dashboard/files/
1414
export MEDIA_ROOT_PATH=files
15+
export LOGLEVEL='INFO' # WARNING, ERROR, INFO, DEBUG
16+
1517
# the following variables also need to be in .docker_env (ugly but not sure how else to get it to work)
1618
export POSTGRES_DB=postgres
1719
export POSTGRES_NAME=postgres
@@ -27,4 +29,4 @@ export REDCAP_URL=""
2729
export GBF_TEST_FLAG='true' # should be true or false
2830
export GBF_TOKEN="XXX" # token for GBF
2931
export GBF_URL="" # set to host of GBF api endpoints ending in /
30-
export GBF_ITEM_NR = "XXX" # the item nr of the kit that should be ordered
32+
export GBF_ITEM_NR="XXX" # the item nr of the kit that should be ordered

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,5 +101,11 @@ supervisorctl -c /etc/supervisor/supervisord.conf restart edrop
101101
6. If that works, stop and start through systemd.
102102
7. Edit webserver to proxy eDROP Django app.
103103

104+
## Processing Flow
105+
106+
Below is a diagram that describes the process flow of eDROP Connector.
107+
108+
![eDROP Connector Process Flow](eDROPConnectorFlow.png)
109+
104110
## Copyright
105111
By committing code to this repository, you agree to transfer or license your copyright to the project under its current terms.

eDROPConnectorFlow.png

51.1 KB
Loading

edrop-cron.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ echo "Starting $NAME as `whoami`"
1212
cd $DJANGODIR
1313
source .env_app
1414
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
15-
15+
export PYTHONPATH=$DJANGODIR:$PYTHONPATH
1616
mkdir -p /edrop/logs
1717

1818
# start the cron job

edrop/settings.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
import os, logging
1515

1616
logger = logging.getLogger(__name__)
17-
logging.basicConfig(format="%(levelname)s: %(name)s: %(message)s")
17+
LOGLEVEL = os.environ.get('LOGLEVEL', 'INFO').upper()
18+
logging.basicConfig(format="%(levelname)s: %(name)s: %(message)s", level=LOGLEVEL)
1819

1920

2021
# Build paths inside the project like this: BASE_DIR / 'subdir'.
@@ -141,6 +142,9 @@
141142

142143
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
143144

145+
# set the timezone in which dates should be displayed when writing to REDCap
146+
REQUEST_TIMEZONE = os.environ.get('REQUEST_TIMEZONE', "MST")
147+
144148
# REDCap configurations
145149
REDCAP_INSTRUMENT_ID = "contact"
146150
REDCAP_FIELD_TO_BE_COMPLETE = "contact_complete"

mockoon/gbf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@
7979
"responses": [
8080
{
8181
"uuid": "2fdaec13-6d2a-4066-aca5-999dc5b09f1a",
82-
"body": "{\n \"ShippingConfirmations\": [\n {\n \"OrderNumber\": \"EDROP-00001\",\n \"Shipper\": \"gbf shipping document\",\n \"ShipVia\": \"customer ship method\",\n \"ShipDate\": \"2023-01-12\",\n \"ClientID\": \"XXXX\",\n \"Tracking\": [\n \"outbound tracking 1\",\n\t\t\"outbound tracking 2\"\n ],\n \"Items\": [\n {\n \"ItemNumber\": \"customer item number (serialized example)\",\n \"LotNumber\": \"gbf lot number\",\n\t\t \"ExpireDate\": \"kit expire date\",\n \"SerialNumber\": \"gbf kit serial\",\n \"ShippedQty\": 1,\n\t\t \"TubeSerials\" : [\n\t\t\t\"child 1\",\n\t\t\t\"child 1\"\n\t\t ],\n \"ReturnTracking\": [\n \"inbound tracking\"\n ]\n },\n\t\t{\n\t\t \"ItemNumber\": \"customer item number (non serialized example)\",\n \"LotNumber\": \"gbf lot number\",\n\t\t \"ExpireDate\": \"kit expire date\",\n \"ShippedQty\": 5\n\t\t}\n ]\n }\n ]\n}",
82+
"body": "{\n \"success\": true,\n \"dataArray\": [\n {\n \"format\": \"json\",\n \"data\": \"{\\r\\n \\\"ShippingConfirmations\\\": [\\r\\n {\\r\\n \\\"OrderNumber\\\": \\\"EDROP-00014\\\",\\r\\n \\\"Shipper\\\": \\\"\\\",\\r\\n \\\"ShipVia\\\": \\\"FedEx Ground\\\",\\r\\n \\\"ShipDate\\\": \\\"2025-01-23\\\",\\r\\n \\\"ClientID\\\": \\\"\\\",\\r\\n \\\"Tracking\\\": [\\r\\n \\\"270000004830\\\"\\r\\n ],\\r\\n \\\"Items\\\": [\\r\\n {\\r\\n \\\"ItemNumber\\\": \\\"K-BAN-001\\\",\\r\\n \\\"SerialNumber\\\": \\\"EV-05FCSG\\\",\\r\\n \\\"ShippedQty\\\": 1,\\r\\n \\\"ReturnTracking\\\": [\\r\\n \\\"XXXXXXXXXXXX\\\"\\r\\n ],\\r\\n \\\"TubeSerial\\\": [\\r\\n \\\"SIHIRJT5786\\\"\\r\\n ]\\r\\n }\\r\\n ]\\r\\n }\\r\\n ]\\r\\n}\"\n }\n ]\n}",
8383
"latency": 0,
8484
"statusCode": 200,
8585
"label": "",

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ gunicorn==22.0.0
33
psycopg2==2.9.10
44
dj-static==0.0.6
55
requests==2.32.3
6-
django-apscheduler==0.7.0
6+
django-apscheduler==0.7.0
7+
pytz==2024.2

track/admin.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
# Register your models here.
55
class OrderAdmin(admin.ModelAdmin):
6-
list_display = ["record_id", "order_number", "tracking_nrs", "order_status", "ship_date"]
6+
list_display = ["record_id", "order_number", "tracking_nrs", "return_tracking_nrs", "tube_serials", "order_status", "ship_date"]
77

88

99
admin.site.register(Order, OrderAdmin)

track/gbf.py

Lines changed: 67 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -33,25 +33,29 @@ def _generate_order_number(order):
3333
def _generate_order_json(order, address_data):
3434
order_json = {
3535
"test": settings.GBF_TEST_FLAG,
36-
"orderNumber": order.order_number,
37-
"shippingInfo": {
38-
"address": {
39-
"company": f"{address_data['first_name'] if 'first_name' in address_data else ''} {address_data['last_name'] if 'last_name' in address_data else ''}",
40-
"addressLine1": address_data['street_1'] if 'street_1' in address_data else '',
41-
"addressLine2": address_data['street_2'] if 'street_2' in address_data else '', # in case we add this to redcap, we need to add
42-
"city": address_data['city'] if 'city' in address_data else '',
43-
"state": address_data['state'] if 'state' in address_data else '',
44-
"zipCode": address_data['zip'] if 'zip' in address_data else '',
45-
"country": settings.GBF_SHIPPING_COUNTRY,
46-
"phone": address_data['phone'] if 'phone' in address_data else '',
47-
"residential": True # see GitHub discussion #19 (shipping address)
48-
},
49-
"shipMethod": settings.GBF_SHIPPING_METHOD,
50-
},
51-
"lineItems": [
36+
"orders": [
5237
{
53-
"itemNumber": settings.GBF_ITEM_NR,
54-
"itemQuantity": settings.GBF_ITEM_QUANTITY,
38+
"orderNumber": order.order_number,
39+
"shippingInfo": {
40+
"address": {
41+
"company": f"{address_data['first_name'] if 'first_name' in address_data else ''} {address_data['last_name'] if 'last_name' in address_data else ''}",
42+
"addressLine1": address_data['street_1'] if 'street_1' in address_data else '',
43+
"addressLine2": address_data['street_2'] if 'street_2' in address_data else '', # in case we add this to redcap, we need to add
44+
"city": address_data['city'] if 'city' in address_data else '',
45+
"state": address_data['state'] if 'state' in address_data else '',
46+
"zipCode": address_data['zip'] if 'zip' in address_data else '',
47+
"country": settings.GBF_SHIPPING_COUNTRY,
48+
"phone": address_data['phone'] if 'phone' in address_data else '',
49+
"residential": True # see GitHub discussion #19 (shipping address)
50+
},
51+
"shipMethod": settings.GBF_SHIPPING_METHOD,
52+
},
53+
"lineItems": [
54+
{
55+
"itemNumber": settings.GBF_ITEM_NR,
56+
"itemQuantity": settings.GBF_ITEM_QUANTITY,
57+
}
58+
]
5559
}
5660
]
5761
}
@@ -79,9 +83,16 @@ def _place_order_with_GBF(order_json):
7983
logger.error("Response from GBF:")
8084
logger.error(response)
8185

86+
response_body = response.json()
8287
if response.status_code != HTTPStatus.OK:
8388
logger.error("Could not submit order to GBF.")
8489
logger.error(response)
90+
logger.error(response_body)
91+
return False
92+
93+
if "success" not in response_body or response_body["success"] != True:
94+
logger.error("Could not submit order to GBF.")
95+
logger.error(response_body)
8596
return False
8697

8798
return True
@@ -93,13 +104,25 @@ def get_order_confirmations(order_numbers):
93104
- tracking numbers
94105
- return tracking numbers
95106
107+
GBF sends json like this:
108+
{
109+
"success": true,
110+
"dataArray": [
111+
{
112+
"format": "json",
113+
"data": "{\r\n \"ShippingConfirmations\": [\r\n {\r\n \"OrderNumber\": \"EDROP-00014\",\r\n \"Shipper\": \"\",\r\n \"ShipVia\": \"FedEx Ground\",\r\n \"ShipDate\": \"2025-01-23\",\r\n \"ClientID\": \"\",\r\n \"Tracking\": [\r\n \"270000004830\"\r\n ],\r\n \"Items\": [\r\n {\r\n \"ItemNumber\": \"K-BAN-001\",\r\n \"SerialNumber\": \"EV-05FCSG\",\r\n \"ShippedQty\": 1,\r\n \"ReturnTracking\": [\r\n \"XXXXXXXXXXXX\"\r\n ],\r\n \"TubeSerial\": [\r\n \"SIHIRJT5786\"\r\n ]\r\n }\r\n ]\r\n }\r\n ]\r\n}"
114+
}
115+
]
116+
}
117+
96118
Returns:
97119
- a dictionary of the form:
98120
{
99121
'EDROP-001': {
100122
'date_kit_shipped': '2023-01-12',
101123
'kit_tracking_n': ['outbound tracking 1', 'outbound tracking 2'],
102-
'return_tracking_n': ['inbound tracking', 'inbound tracking2']
124+
'return_tracking_n': ['inbound tracking', 'inbound tracking2'],
125+
'tube_serial_n': [tube serial1', 'tube serial2']
103126
}
104127
}
105128
"""
@@ -108,20 +131,43 @@ def get_order_confirmations(order_numbers):
108131
try:
109132
response = requests.post(f"{settings.GBF_URL}oap/api/confirm2", data=content, headers=headers)
110133
response.raise_for_status() # Raises an exception for bad status codes
134+
logger.debug(response.json())
111135
except requests.exceptions.HTTPError as err:
112136
logger.error(f"Could not get order confirmation from GBF.")
113137
logger.error(err)
114138
return None
115139

116-
confirmations = response.json()
140+
response_body = response.json()
141+
# if for some reason GBF does not return a success response
142+
if response_body['success'] != True:
143+
logger.error("GBF returned success is false.")
144+
logger.error(response_body)
145+
146+
if "dataArray" not in response_body or not response_body["dataArray"]:
147+
logger.info("No GBF confirmations available.")
148+
return None
149+
150+
# GBF sends one object in a list in 'dataArray', so we'll use the first one
151+
data_object = response_body["dataArray"][0]
152+
if 'format' not in data_object or data_object["format"] != "json":
153+
logger.error("GBF did not send json back.")
154+
return None
155+
156+
if 'data' not in data_object or not data_object["data"]:
157+
logger.info("No GBF confirmations available.")
158+
return None
159+
160+
confirmations = json.loads(data_object["data"])
117161
tracking_info = {}
118162
if "ShippingConfirmations" in confirmations:
119163
for shipping_confirmation in confirmations['ShippingConfirmations']:
120164
tracking_info[shipping_confirmation['OrderNumber']] = {
121165
'date_kit_shipped': shipping_confirmation['ShipDate'],
122166
'kit_tracking_n': shipping_confirmation['Tracking'],
123167
#filter for items with return tracking numbers and returns tracking numbers
124-
'return_tracking_n': [return_track for item in shipping_confirmation['Items'] if 'ReturnTracking' in item for return_track in item['ReturnTracking']]
168+
'return_tracking_n': [return_track for item in shipping_confirmation['Items'] if 'ReturnTracking' in item for return_track in item['ReturnTracking']],
169+
#filter for items with return tracking numbers and returns tracking numbers
170+
'tube_serial_n': [tube_serial for item in shipping_confirmation['Items'] if 'TubeSerial' in item for tube_serial in item['TubeSerial']]
125171
}
126172
return tracking_info
127173

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Generated by Django 5.1.4 on 2025-01-31 04:31
2+
3+
import django.contrib.postgres.fields
4+
from django.db import migrations, models
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('track', '0008_remove_order_return_tracking_nr_and_more'),
11+
]
12+
13+
operations = [
14+
migrations.AddField(
15+
model_name='order',
16+
name='tube_serials',
17+
field=django.contrib.postgres.fields.ArrayField(base_field=models.CharField(), blank=True, null=True, size=None),
18+
),
19+
]

0 commit comments

Comments
 (0)