diff --git a/CLAUDE.md b/CLAUDE.md index 8d7c0ff..5ddcfd3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -41,6 +41,15 @@ docker compose exec web python manage.py createsuperuser docker compose exec web python manage.py setup_groups ``` +## Branching and Release Workflow + +- **`main`** — production branch. Only updated via PR from `develop`. +- **`develop`** — integration branch. All feature work merges here first. +- **Feature branches** — branch from `develop`, PR back to `develop`. +- **Release flow**: `feature-branch → develop (PR) → main (PR)`. Never PR directly to `main` from a feature branch. +- **Hotfixes**: branch from `main`, PR to `main`, then cherry-pick or merge back to `develop`. +- When committing directly to `develop` (e.g. small fixes), no PR is needed for the `develop` commit itself — the PR happens when `develop` merges to `main`. + ## Architecture ### Django Apps diff --git a/src/assets/views.py b/src/assets/views.py index e190652..5c63733 100644 --- a/src/assets/views.py +++ b/src/assets/views.py @@ -2351,12 +2351,23 @@ def location_detail(request, pk): descendant_ids = [loc.pk for loc in location.get_descendants()] all_location_ids = [location.pk] + descendant_ids + # Prefetch primary image to avoid N+1 queries + primary_image_prefetch = Prefetch( + "images", + queryset=AssetImage.objects.filter(is_primary=True), + to_attr="primary_images", + ) + # Base querysets for three tabs - present_qs = Asset.objects.filter( - current_location_id__in=all_location_ids, - status="active", - checked_out_to__isnull=True, - ).select_related("category", "category__department", "checked_out_to") + present_qs = ( + Asset.objects.filter( + current_location_id__in=all_location_ids, + status="active", + checked_out_to__isnull=True, + ) + .select_related("category", "category__department", "checked_out_to") + .prefetch_related(primary_image_prefetch) + ) # Subquery: due_date from most recent checkout transaction latest_checkout_due = ( @@ -2370,13 +2381,18 @@ def location_detail(request, pk): checked_out_to__isnull=False, ) .select_related("category", "category__department", "checked_out_to") + .prefetch_related(primary_image_prefetch) .annotate(checkout_due_date=Subquery(latest_checkout_due)) ) - draft_qs = Asset.objects.filter( - current_location_id__in=all_location_ids, - status="draft", - ).select_related("category", "category__department", "checked_out_to") + draft_qs = ( + Asset.objects.filter( + current_location_id__in=all_location_ids, + status="draft", + ) + .select_related("category", "category__department", "checked_out_to") + .prefetch_related(primary_image_prefetch) + ) # Tab counts present_count = present_qs.count() diff --git a/src/templates/assets/location_detail.html b/src/templates/assets/location_detail.html index 2215218..f745786 100644 --- a/src/templates/assets/location_detail.html +++ b/src/templates/assets/location_detail.html @@ -164,6 +164,7 @@
| Name | Barcode | Category | @@ -175,6 +176,15 @@|
|---|---|---|---|
|
+
+ {% if asset.primary_image %}
+
+ |
{{ asset.name }} | @@ -202,7 +212,15 @@