Skip to content

Enhance profile and pet management features (and add comprehensive test cases) #174

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 56 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
dac7c23
[#173] Simplify left nav links (dashboard)
delano Jun 27, 2024
88ffae9
[#173] Add location and delivery radius fields to Branch
delano Jun 27, 2024
7b344c3
[#173] Add delivery instructions field to request form
delano Jun 27, 2024
902bb92
[#173] Fix for SQL logging
delano Jun 27, 2024
d417296
[#173] Better quality branches fixture
delano Jun 27, 2024
277a694
[#173] Added operational, hidden flags to branch model
delano Jun 27, 2024
b9e486e
[#173] Add branch viewset
delano Jun 27, 2024
eca8204
[#173] Add Branch model management via Django admin and
delano Jun 27, 2024
43a3242
[#173] Add branch viewset tests
delano Jun 28, 2024
8a14683
[#173] Add API request for branches to food form.
delano Jun 28, 2024
ca7f089
[#173] Upgrade to latest nuxt-ui-pro
delano Jun 28, 2024
30a6bac
[#173] Add missing js deps
delano Jun 28, 2024
324885a
[#173] Update build command to use 'nuxi'
delano Jun 28, 2024
9c4ab3a
[#173] Add tailwindcss/typography
delano Jun 28, 2024
e010a71
[#173] Fix (hotfix) for vite wss console error
delano Jun 28, 2024
d89115f
[#173] Enhance pet form with...
delano Jun 28, 2024
c16c9c2
[#173] Add model utilities
delano Jun 28, 2024
a8830c2
[#173] Add Gunicorn config for Django API (prod)
delano Jun 28, 2024
6c9b9e6
[#173] Improve branch selection and GMaps autocomplete
delano Jun 29, 2024
66ee036
[#173] Selecting branch first is required
delano Jun 29, 2024
51925de
[#173] Clean up delivery address step logic
delano Jun 30, 2024
b839e9d
[#173] Add watcher for reference
delano Jun 30, 2024
f2c0df3
[#173] Make sure google address is selected
delano Jun 30, 2024
e308343
[#173] .
delano Jun 30, 2024
53d7b9d
[#173] Add ext_address_details field
delano Jun 30, 2024
125a26f
[#173] Add address_details and ext_address_details to profile
delano Jun 30, 2024
54e955f
[#173] Update branches and autocomplete field for profile
delano Jun 30, 2024
c05c407
[#173] Update delivery info form with new features
delano Jun 30, 2024
f06949b
[#173] Remove unused delivery area modal
delano Jun 30, 2024
c7dcf9e
[#173] Renamed profile viewset file to be consistent
delano Jun 30, 2024
eadc794
[#173] Profile saves the input data
delano Jun 30, 2024
c57e755
[#173] Decrease token exp time; runserver watch settings
delano Jun 30, 2024
e068062
[#173] Add Branch default ordering
delano Jun 30, 2024
c3628ca
[#173] Prepopulate form fields from profile
delano Jun 30, 2024
f03e48d
[#173] Fix for default email
delano Jun 30, 2024
7bdaa5c
[#173] Enhance form behavior for delivery address
delano Jun 30, 2024
ba729b8
[#173] Fix for hitting enter on autocomplete form
delano Jun 30, 2024
67d2402
[#173] Try updating autocomplete boundary when the field is ready
delano Jun 30, 2024
03d4329
[#173] Pets have the association to profile
delano Jun 30, 2024
2063e6a
[#173] Update client pet details form and management
delano Jun 30, 2024
c8aa1af
[#173] Flatten serializer dirs for clarity
delano Jun 30, 2024
0563785
[#173] Ditto for food request view
delano Jun 30, 2024
c298f77
[#173] Ditto again, for user view
delano Jun 30, 2024
0cd7d05
[#173] Add the word view in view files.
delano Jun 30, 2024
e8aa8fd
[#173] Add PetViewSet w/ tests
delano Jul 1, 2024
9c378b5
[#173] Added user+profile boundary tests for pets API
delano Jul 1, 2024
731eb3d
[#173] Add profile viewset tests
delano Jul 1, 2024
4dc9819
[#173] Update Pet and Profile models to improve data handling
delano Jul 1, 2024
5b9fa50
[#173] Add spay/neuter status and animal details to Pet
delano Jul 1, 2024
204a313
[#173] Add logging to reconcile_pets in profile viewset
delano Jul 1, 2024
04aff46
[#173] Update pet form for better UX and data integrity
delano Jul 1, 2024
4c4915c
[#173] Enhance PetsForm and FoodRequestForm with pet details and canc…
delano Jul 1, 2024
de6760a
[#173] Fix up nuxt-auth config
delano Jul 1, 2024
8784c1c
[#173] Add content to summary screen via computed
delano Jul 1, 2024
0f9879e
[#173] Store complete request form data in details
delano Jul 1, 2024
8cfe19a
[#173] Fix performance issue with computed summary
delano Jul 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 56 additions & 8 deletions apps/api/afb/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@
# https://docs.djangoproject.com/en/4.2/ref/csrf/#how-it-works
# CSRF_COOKIE_DOMAIN = ""

TOKEN_EXPIRED_AFTER_WEEKS = 2
TOKEN_EXPIRED_AFTER_WEEKS = 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: For the TOKEN_EXPIRED_AFTER_WEEKS setting, consider documenting the reason for changing the token expiration from 2 weeks to 1 week. This helps maintainers understand the security considerations or business requirements driving this change. [enhancement, importance: 7]

Suggested change
TOKEN_EXPIRED_AFTER_WEEKS = 1
# Reducing token expiration to 1 week for enhanced security posture and to ensure users re-authenticate more frequently.
TOKEN_EXPIRED_AFTER_WEEKS = 1



# Static files (CSS, JavaScript, Images)
Expand Down Expand Up @@ -400,7 +400,15 @@
"PASSWORD": os.getenv("DB_PASSWORD"),
"HOST": os.getenv("DB_HOST"),
"PORT": os.getenv("DB_PORT"),
}
},
"test": {
"ENGINE": os.getenv("DB_ENGINE"),
"NAME": "test_" + (os.getenv("DB_NAME") or ""),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: When defining the test database configuration, ensure that the database name is not empty to avoid potential conflicts or errors during testing. This can be achieved by providing a default name for the test database if DB_NAME is not set in the environment variables. [possible issue, importance: 7]

Suggested change
"NAME": "test_" + (os.getenv("DB_NAME") or ""),
"NAME": "test_" + (os.getenv("DB_NAME") or "default_test_db"),

"USER": os.getenv("DB_USER"),
"PASSWORD": os.getenv("DB_PASSWORD"),
"HOST": os.getenv("DB_HOST"),
"PORT": os.getenv("DB_PORT"),
},
}

# Password validation
Expand Down Expand Up @@ -451,14 +459,40 @@


class QueryFormatter(logging.Formatter):
"""
This formatter class is designed to enhance logging capabilities by
formatting SQL queries to be more readable. It checks for the presence
of an SQL query in the log record and formats it using `sqlparse` for
better readability in the logs.
"""

def format(self, record):
# Implementation remains the same...
record.prettysql = ""
try:
_, rawsql, *_ = record.args
except ValueError:
print("record.args does not contain enough values to unpack")
if hasattr(record, "sql"):
# If record has 'sql' attribute, use it directly
rawsql = record.sql
elif (
hasattr(record, "args")
and isinstance(record.args, tuple)
and len(record.args) > 1
):
# If record has 'args' and it's a tuple with at least 2 elements
rawsql = record.args[1]
else:
# If we can't find SQL, just use an empty string
rawsql = ""

if isinstance(rawsql, str):
try:
record.prettysql = sqlparse.format(rawsql, reindent=True)
except Exception as e:
# If formatting fails, just use the raw SQL
record.prettysql = rawsql
print(f"SQL formatting failed: {e}")
else:
record.prettysql = sqlparse.format(rawsql, reindent=True)
# If rawsql is not a string, convert it to a string
record.prettysql = str(rawsql)

# Call the original formatter class to do the actual formatting
return super().format(record)
Expand Down Expand Up @@ -488,7 +522,7 @@ def format(self, record):
"filters": ["request_id"],
},
"console_db": {
"level": "DEBUG",
"level": "FATAL",
"class": "logging.StreamHandler",
"formatter": "sql",
"filters": ["request_id"],
Expand All @@ -508,3 +542,17 @@ def format(self, record):
},
"root": {"level": LOG_LEVEL, "handlers": ["console"]},
}

if DEBUG:
# RunServerPlus settings
# https://django-extensions.readthedocs.io/en/stable/runserver_plus.html
RUNSERVER_PLUS_PRINT_SQL_TRUNCATE = 1000
RUNSERVERPLUS_POLLER_RELOADER_TYPE = "stat" # or 'watchdog' or 'auto'
RUNSERVER_PLUS_EXCLUDE_PATTERNS = [
"*.sqlite3",
"*.sqlite3-journal",
"#{BASE_DIR}/.local/*",
"#{BASE_DIR}/.git/*",
"**/.pytest_cache/*",
"**/__pycache__/*",
]
14 changes: 9 additions & 5 deletions apps/api/afb/urls/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
"""

from afbcore.views import (
BranchViewSet,
FoodRequestViewSet,
PetViewSet,
ProfileViewSet,
authtoken,
users,
logout_view,
user_view,
)
from django.conf import settings
from django.contrib import admin as afbcore_admin
Expand All @@ -28,17 +30,19 @@
# e.g. /api/v1/requests/abcdef1234/
router.register("requests", FoodRequestViewSet, basename="foodrequest")
router.register("profiles", ProfileViewSet, basename="profile")
router.register("branches", BranchViewSet, basename="branch")
router.register("pets", PetViewSet, basename="pet")

urlpatterns = [
path("afbadmin/", afbcore_admin.site.urls, name="admin"),
path(
"api/<str:version>/register/",
users.RegisterUserAPIView.as_view(),
user_view.RegisterUserAPIView.as_view(),
name="registration",
),
path(
"api/<str:version>/current_user/",
users.CurrentUserAPIView.as_view(),
user_view.CurrentUserAPIView.as_view(),
name="current_user",
),
path("api/<str:version>/", include(router.urls)),
Expand All @@ -50,7 +54,7 @@
),
path(
"api/<str:version>/authtoken/logout/",
authtoken.LogoutView.as_view(),
logout_view.LogoutView.as_view(),
name="api_token_logout",
),
path(
Expand Down
3 changes: 2 additions & 1 deletion apps/api/afbcore/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
Profile,
User,
)
from .views.admin.branch_admin import BranchAdmin


class UserAdmin(BaseUserAdmin):
Expand All @@ -33,7 +34,7 @@ class AuthorAdmin(admin.ModelAdmin):
# Register your models here.
admin.site.register(User, UserAdmin)
admin.site.register(Profile)
admin.site.register(Branch)
# admin.site.register(Branch, BranchAdmin)
admin.site.register(FoodRequest)
admin.site.register(Delivery)
admin.site.register(DeliveryRegion)
Expand Down
164 changes: 137 additions & 27 deletions apps/api/afbcore/fixtures/branches.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,47 @@
[
{
"model": "afbcore.branch",
"pk": "383e8f22-b671-4b94-90e0-df864828ab05",
"pk": "f1b1b1b1-1b1b-1b1b-1b1b-1b1b1b1b1b1b",
"fields": {
"location_name": "Michael's",
"address_line1": "1910 Pembina Hwy",
"location_name": "No branch",
"address_line1": "1234 56th Street",
"address_line2": null,
"city": "Winnipeg",
"state_or_province": "MB",
"postal_code": "R3T 4S5",
"country": null,
"city": "Calgary",
"state_or_province": "AB",
"postal_code": "T2N 1A1",
"country": "Canada",
"ext_id": null,
"display_name": "No branch",
"pickup_locations": null,
"frequency_of_requests": "7",
"spay_neuter_requirement": false,
"pets_per_household_max": 4,
"delivery_deadline_days": 14,
"delivery_type": "drop_off",
"delivery_pickup_details": " ",
"blurb": " ",
"blurb_image": "",
"delivery_regions": [],
"latitude": 51.0447,
"longitude": -114.0719,
"delivery_radius": 10,
"hidden": false,
"operational": true
}
},
{
"model": "afbcore.branch",
"pk": "f684ab06-c155-4b30-b046-80a721879b52",
"fields": {
"location_name": "Medicine Hat",
"address_line1": "375 Kipling Street SE",
"address_line2": null,
"city": "Medicine Hat",
"state_or_province": "AB",
"postal_code": "T1A 1Y9",
"country": "Canada",
"ext_id": null,
"display_name": "Michael's Tots",
"display_name": "Medicine Hat",
"pickup_locations": null,
"frequency_of_requests": "30",
"spay_neuter_requirement": false,
Expand All @@ -21,82 +51,162 @@
"delivery_pickup_details": " ",
"blurb": " ",
"blurb_image": "",
"delivery_regions": []
"delivery_regions": [],
"latitude": 50.0417,
"longitude": -110.6766,
"delivery_radius": 20,
"hidden": true,
"operational": false
}
},
{
"model": "afbcore.branch",
"pk": "5c3549e0-a728-4510-a64a-69bcd26d52d5",
"fields": {
"location_name": "Xanadu's Lot",
"address_line1": "1225 St Mary's Rd",
"location_name": "Osoyoos",
"address_line1": "8702 Main Street",
"address_line2": null,
"city": "Osoyoos",
"state_or_province": "BC",
"postal_code": "V0H 1V0",
"country": "Canada",
"ext_id": null,
"display_name": "Osoyoos",
"pickup_locations": null,
"frequency_of_requests": "14",
"spay_neuter_requirement": false,
"pets_per_household_max": 4,
"delivery_deadline_days": 14,
"delivery_type": "drop_off",
"delivery_pickup_details": " ",
"blurb": " ",
"blurb_image": "",
"delivery_regions": [],
"latitude": 49.0323,
"longitude": -119.4692,
"delivery_radius": 15,
"hidden": false,
"operational": true
}
},
{
"model": "afbcore.branch",
"pk": "383e8f22-b671-4b94-90e0-df864828ab05",
"fields": {
"location_name": "Winnipeg NW",
"address_line1": "1910 Pembina Hwy",
"address_line2": null,
"city": "Winnipeg",
"state_or_province": "MB",
"postal_code": "R2M 5E5",
"country": null,
"postal_code": "R3T 4S5",
"country": "Canada",
"ext_id": null,
"display_name": "Xanadu",
"display_name": "Winnipeg Northwest",
"pickup_locations": null,
"frequency_of_requests": "7",
"spay_neuter_requirement": false,
"pets_per_household_max": 4,
"delivery_deadline_days": 30,
"delivery_deadline_days": 14,
"delivery_type": "drop_off",
"delivery_pickup_details": " ",
"blurb": " ",
"blurb_image": "",
"delivery_regions": []
"delivery_regions": [],
"latitude": 49.9530,
"longitude": -97.2110,
"delivery_radius": 10,
"hidden": true,
"operational": false
}
},
{
"model": "afbcore.branch",
"pk": "8f786370-f10b-11ee-934b-0fdb3c7dc37f",
"fields": {
"location_name": "Martha's",
"location_name": "Winnipeg NE",
"address_line1": "400 North Town Rd",
"address_line2": null,
"city": "Winnipeg",
"state_or_province": "MB",
"postal_code": "R2V 3C4",
"country": null,
"country": "Canada",
"ext_id": null,
"display_name": "Martha's Vines",
"display_name": "Winnipeg Northeast",
"pickup_locations": null,
"frequency_of_requests": "14",
"frequency_of_requests": "7",
"spay_neuter_requirement": false,
"pets_per_household_max": 4,
"delivery_deadline_days": 14,
"delivery_type": "drop_off",
"delivery_pickup_details": " ",
"blurb": " ",
"blurb_image": "",
"delivery_regions": []
"delivery_regions": [],
"latitude": 49.9530,
"longitude": -97.0660,
"delivery_radius": 10,
"hidden": true,
"operational": false
}
},
{
"model": "afbcore.branch",
"pk": "f684ab06-c155-4b30-b046-80a721879b52",
"pk": "b5f7e8d2-f10b-11ee-934b-0fdb3c7dc37f",
"fields": {
"location_name": "Winnipeg SW",
"address_line1": "1225 St Mary's Rd",
"address_line2": null,
"city": "Winnipeg",
"state_or_province": "MB",
"postal_code": "R2M 5E5",
"country": "Canada",
"ext_id": null,
"display_name": "Winnipeg Southwest",
"pickup_locations": null,
"frequency_of_requests": "7",
"spay_neuter_requirement": false,
"pets_per_household_max": 4,
"delivery_deadline_days": 14,
"delivery_type": "drop_off",
"delivery_pickup_details": " ",
"blurb": " ",
"blurb_image": "",
"delivery_regions": [],
"latitude": 49.8370,
"longitude": -97.2110,
"delivery_radius": 10,
"hidden": true,
"operational": false
}
},
{
"model": "afbcore.branch",
"pk": "d1a9f634-f10b-11ee-934b-0fdb3c7dc37f",
"fields": {
"location_name": "The Uni",
"location_name": "Winnipeg SE",
"address_line1": "1555 Regent Ave W",
"address_line2": null,
"city": "Winnipeg",
"state_or_province": "MB",
"postal_code": "R2C 4J2",
"country": null,
"country": "Canada",
"ext_id": null,
"display_name": "University Square ",
"display_name": "Winnipeg Southeast",
"pickup_locations": null,
"frequency_of_requests": "21",
"frequency_of_requests": "7",
"spay_neuter_requirement": false,
"pets_per_household_max": 4,
"delivery_deadline_days": 14,
"delivery_type": "drop_off",
"delivery_pickup_details": " ",
"blurb": " ",
"blurb_image": "",
"delivery_regions": []
"delivery_regions": [],
"latitude": 49.8370,
"longitude": -97.0660,
"delivery_radius": 10,
"hidden": true,
"operational": false
}
}
]
Loading
Loading