diff --git a/companies/admin.py b/companies/admin.py index 93c1e9d..82e7dd9 100644 --- a/companies/admin.py +++ b/companies/admin.py @@ -33,7 +33,6 @@ def import_categories_view(self, request): return HttpResponseRedirect(reverse('admin:companies_productcategory_changelist')) - # Step 1: Add PoliticalDataInline for editing political data within a business class PoliticalDataInline(admin.StackedInline): model = PoliticalData @@ -49,6 +48,27 @@ class EditRequestInline(admin.TabularInline): fields = ('submitted_by', 'status', 'justification', 'created_at', 'reviewed_at') readonly_fields = ('created_at', 'reviewed_at') +@admin.register(ServiceCategory) +class ServiceCategoryAdmin(CategoryImportMixin, admin.ModelAdmin): + list_display = ('name', 'parent', 'slug') + search_fields = ('name',) + list_filter = ('parent',) + prepopulated_fields = {'slug': ('name',)} + raw_id_fields = ('parent',) + + def get_queryset(self, request): + return super().get_queryset(request).select_related('parent') + +@admin.register(ProductCategory) +class ProductCategoryAdmin(CategoryImportMixin, admin.ModelAdmin): + list_display = ('name', 'parent', 'slug') + search_fields = ('name',) + list_filter = ('parent',) + prepopulated_fields = {'slug': ('name',)} + raw_id_fields = ('parent',) + + def get_queryset(self, request): + return super().get_queryset(request).select_related('parent') # Step 3: Updated BusinessAdmin to include inlines @admin.register(Business) diff --git a/companies/templates/companies/business_detail.html b/companies/templates/companies/business_detail.html index 6559a33..0f5c6d7 100644 --- a/companies/templates/companies/business_detail.html +++ b/companies/templates/companies/business_detail.html @@ -210,16 +210,72 @@

{{ product.name }}

{% if alternatives %}

Alternative Businesses

+
{% for alt in alternatives %}
-

- - {{ alt.business.name }} - -

-

{{ alt.business.description|truncatewords:30 }}

-

Matches {{ alt.overlap_count }} product{{ alt.overlap_count|pluralize:",s" }}/service{{ alt.overlap_count|pluralize:",s" }}

+
+
+

+ + {{ alt.business.name }} + +

+ + {{ alt.business.description|truncatewords:30 }} + +
+ Matches {{ alt.overlap_count }} product{{ alt.overlap_count|pluralize:",s" }}/service{{ alt.overlap_count|pluralize:",s" }} +
+ + {% if alt.business.politicaldata %} +
+
+ + [ {{ alt.business.politicaldata.overall_conservative_percentage|default:"0" }}% Conservative ] + + / + + [ {{ alt.business.politicaldata.overall_liberal_percentage|default:"0" }}% Liberal ] + + {% if alt.business.inherited_from %} + *inherited from {{ alt.business.inherited_from.name }} + {% endif %} +
+ +
+ {% if alt.business.politicaldata.direct_america_pac_donor or alt.business.politicaldata.affiliated_pac_america_pac_donor %} +
⚠️ America PAC Donor
+ {% endif %} + + {% if alt.business.politicaldata.direct_save_america_pac_donor or alt.business.politicaldata.affiliated_pac_save_america_pac_donor %} +
⚠️ Save America PAC Donor
+ {% endif %} + + {% if alt.business.politicaldata.direct_maga_inc_donor or alt.business.politicaldata.affiliated_pac_maga_inc_donor %} +
⚠️ MAGA Inc Donor
+ {% endif %} + + {% if alt.business.politicaldata.senior_employee_trump_donor %} +
⚠️ Senior Employee Trump Donor
+ {% endif %} + + {% if alt.business.politicaldata.senior_employee_america_pac_donor %} +
⚠️ Senior Employee America Pac Donor
+ {% endif %} + + {% if alt.business.politicaldata.senior_employee_save_america_pac_donor %} +
⚠️ Senior Employee Save America Pac Donor
+ {% endif %} + + {% if alt.business.politicaldata.senior_employee_maga_inc_donor %} +
⚠️ Senior Employee MAGA Inc Donor
+ {% endif %} +
+
+ {% endif %} +
+
{% endfor %}
diff --git a/pack_planner/admin.py b/pack_planner/admin.py index 7a1e56c..aeed542 100644 --- a/pack_planner/admin.py +++ b/pack_planner/admin.py @@ -8,16 +8,34 @@ class ProductInline(admin.TabularInline): model = Product extra = 1 - fields = ('name', 'description', 'url', 'is_available', 'last_verified') + fields = ('name', 'description', 'url', 'notes', 'is_available', 'go_bag', 'seventy_two_hr_bag', 'last_verified') readonly_fields = ('last_verified',) @admin.register(Category) class CategoryAdmin(admin.ModelAdmin): - list_display = ('name', 'importance', 'order', 'item_count') - list_filter = ('importance',) + list_display = ('name', 'importance', 'order', 'go_bag', 'seventy_two_hr_bag', 'item_count') + list_filter = ('importance', 'go_bag', 'seventy_two_hr_bag') search_fields = ('name', 'description') ordering = ('order', 'name') + fieldsets = ( + (None, { + 'fields': ( + 'name', + 'description', + 'importance', + 'order', + ) + }), + ('Pack Type Applicability', { + 'fields': ( + 'go_bag', + 'seventy_two_hr_bag', + ), + 'classes': ('collapse',) + }) + ) + def item_count(self, obj): count = obj.items.count() return format_html( @@ -37,11 +55,27 @@ class ItemAdmin(admin.ModelAdmin): 'weight_note', 'product_count', 'has_special_considerations', + 'go_bag', + 'seventy_two_hr_bag' + ) + list_filter = ( + 'importance', + 'category', + 'go_bag', + 'seventy_two_hr_bag', 'for_adults', 'for_children', 'for_pets', + 'for_cats', + 'for_dogs', + 'for_small_animals', + 'for_disabled', + 'for_elderly', + 'for_on_foot', + 'for_bicycle', + 'for_vehicle', + 'for_public_transit' ) - list_filter = ('importance', 'category', 'for_adults', 'for_children', 'for_pets', 'for_disabled', 'for_elderly') search_fields = ('name', 'description', 'uses', 'special_considerations') ordering = ('category', 'order', 'name') inlines = [ProductInline] @@ -58,21 +92,35 @@ class ItemAdmin(admin.ModelAdmin): 'order' ) }), - ('Details', { + ('Pack Type Applicability', { + 'fields': ( + 'go_bag', + 'seventy_two_hr_bag', + ), + 'classes': ('collapse',) + }), + ('Item Details', { 'fields': ( 'weight_note', 'special_considerations', 'alternatives', 'conditional_applicability', - 'for_adults', - 'for_children', - 'for_pets', - 'for_disabled', - 'for_elderly', - 'for_on_foot', - 'for_bicycle', - 'for_vehicle', - 'for_public_transit' + ), + 'classes': ('collapse',) + }), + ('User Applicability', { + 'fields': ( + ('for_adults', 'for_elderly'), + ('for_children', 'for_disabled'), + 'for_pets', + ('for_cats', 'for_dogs', 'for_small_animals'), + ), + 'classes': ('collapse',) + }), + ('Transportation Methods', { + 'fields': ( + ('for_on_foot', 'for_bicycle'), + ('for_vehicle', 'for_public_transit'), ), 'classes': ('collapse',) }) @@ -102,11 +150,15 @@ class ProductAdmin(admin.ModelAdmin): 'item', 'category_name', 'is_available', + 'go_bag', + 'seventy_two_hr_bag', 'last_verified', 'url_link' ) list_filter = ( - 'is_available', + 'is_available', + 'go_bag', + 'seventy_two_hr_bag', 'item__category', 'last_verified' ) @@ -117,6 +169,31 @@ class ProductAdmin(admin.ModelAdmin): 'item__name' ) readonly_fields = ('last_verified',) + + fieldsets = ( + (None, { + 'fields': ( + 'name', + 'description', + 'item', + 'url', + 'notes', + ) + }), + ('Availability', { + 'fields': ( + 'is_available', + 'last_verified', + ) + }), + ('Pack Type Applicability', { + 'fields': ( + 'go_bag', + 'seventy_two_hr_bag', + ), + 'classes': ('collapse',) + }) + ) def category_name(self, obj): return obj.item.category.name diff --git a/pack_planner/models.py b/pack_planner/models.py index f9bd98e..61e9444 100644 --- a/pack_planner/models.py +++ b/pack_planner/models.py @@ -25,6 +25,7 @@ class Category(models.Model): ('optional', 'Optional') ] ) + go_bag = models.BooleanField(default=True) seventy_two_hr_bag = models.BooleanField(default=True) order = models.IntegerField(default=0) @@ -63,12 +64,16 @@ class Item(models.Model): for_adults = models.BooleanField(default=True) for_children = models.BooleanField(default=False) for_pets = models.BooleanField(default=False) + for_cats = models.BooleanField(default=False) + for_dogs = models.BooleanField(default=False) + for_small_animals = models.BooleanField(default=False) for_disabled = models.BooleanField(default=False) for_elderly = models.BooleanField(default=False) for_on_foot = models.BooleanField(default=True) for_bicycle = models.BooleanField(default=True) for_vehicle = models.BooleanField(default=True) for_public_transit = models.BooleanField(default=True) + go_bag = models.BooleanField(default=True) seventy_two_hr_bag = models.BooleanField(default=True) class Meta: @@ -82,5 +87,6 @@ class Product(models.Model): notes = models.TextField(blank=True) is_available = models.BooleanField(default=True) last_verified = models.DateTimeField(auto_now=True) - + + go_bag = models.BooleanField(default=True) seventy_two_hr_bag = models.BooleanField(default=True) \ No newline at end of file diff --git a/pack_planner/services/data_processor.py b/pack_planner/services/data_processor.py index 780391d..a160b53 100644 --- a/pack_planner/services/data_processor.py +++ b/pack_planner/services/data_processor.py @@ -30,7 +30,9 @@ def _process_categories(self, categories): defaults={ 'description': cat_data['description'], 'importance': cat_data['importance'], - 'order': cat_data.get('order', 0) + 'order': cat_data.get('order', 0), + 'go_bag': cat_data.get('go_bag', True), + 'seventy_two_hr_bag': cat_data.get('seventy_two_hr_bag', True) } ) if created: @@ -50,15 +52,22 @@ def _process_items(self, items): 'weight_note': item_data.get('weight_note', ''), 'special_considerations': item_data.get('special_considerations', ''), 'order': item_data.get('order', 0), + # All boolean fields with their defaults + 'conditional_applicability': item_data.get('conditional_applicability', False), 'for_adults': item_data.get('for_adults', True), 'for_children': item_data.get('for_children', False), 'for_pets': item_data.get('for_pets', False), + 'for_cats': item_data.get('for_cats', False), + 'for_dogs': item_data.get('for_dogs', False), + 'for_small_animals': item_data.get('for_small_animals', False), 'for_disabled': item_data.get('for_disabled', False), 'for_elderly': item_data.get('for_elderly', False), 'for_on_foot': item_data.get('for_on_foot', True), 'for_bicycle': item_data.get('for_bicycle', True), 'for_vehicle': item_data.get('for_vehicle', True), 'for_public_transit': item_data.get('for_public_transit', True), + 'go_bag': item_data.get('go_bag', True), + 'seventy_two_hr_bag': item_data.get('seventy_two_hr_bag', True) } ) @@ -84,7 +93,9 @@ def _process_products(self, products): 'description': prod_data['description'], 'url': prod_data.get('url', ''), 'notes': prod_data.get('notes', ''), - 'is_available': prod_data.get('is_available', True) + 'is_available': prod_data.get('is_available', True), + 'go_bag': prod_data.get('go_bag', True), + 'seventy_two_hr_bag': prod_data.get('seventy_two_hr_bag', True) } ) if created: diff --git a/pack_planner/templates/pack_planner/assessment_results.html b/pack_planner/templates/pack_planner/assessment_results.html index f95ff85..731234a 100644 --- a/pack_planner/templates/pack_planner/assessment_results.html +++ b/pack_planner/templates/pack_planner/assessment_results.html @@ -65,6 +65,89 @@

Quick Navigation

+ +
+
+
+
+

Pack Type

+ +
+

+ Currently showing Go-Bag items only +

+
+
+ +
+
+
+ + + + {% csrf_token %} @@ -103,19 +186,39 @@

{{ category.name }}