2021-09-29 17:17:52 +00:00
|
|
|
|
import logging
|
|
|
|
|
|
2020-10-17 16:34:05 +00:00
|
|
|
|
import tagulous
|
2022-12-22 07:07:29 +00:00
|
|
|
|
from adminsortable2.admin import SortableAdminMixin, SortableInlineAdminMixin
|
2022-07-21 19:34:21 +00:00
|
|
|
|
from django.conf import settings
|
2020-10-16 15:54:34 +00:00
|
|
|
|
from django.contrib import admin
|
2022-09-30 18:24:57 +00:00
|
|
|
|
from django.template.loader import render_to_string
|
2022-07-21 19:34:21 +00:00
|
|
|
|
from django.urls import reverse
|
|
|
|
|
from django.utils.html import format_html
|
2021-10-09 08:54:07 +00:00
|
|
|
|
from django.utils.translation import gettext_lazy as _
|
2020-10-24 14:33:02 +00:00
|
|
|
|
from import_export.admin import ImportExportMixin
|
|
|
|
|
from import_export.resources import ModelResource
|
2020-10-16 15:54:34 +00:00
|
|
|
|
|
2022-02-05 11:18:09 +00:00
|
|
|
|
from inventory.admin.base import (
|
|
|
|
|
BaseFileModelInline,
|
|
|
|
|
BaseImageModelInline,
|
|
|
|
|
BaseUserAdmin,
|
2022-07-21 19:34:21 +00:00
|
|
|
|
LimitTreeDepthListFilter,
|
2022-02-05 11:18:09 +00:00
|
|
|
|
UserInlineMixin,
|
|
|
|
|
)
|
2022-12-22 08:55:42 +00:00
|
|
|
|
from inventory.admin.tagulous_fix import TagulousModelAdminFix
|
2020-10-17 16:34:05 +00:00
|
|
|
|
from inventory.models import ItemLinkModel, ItemModel
|
2021-04-28 15:03:24 +00:00
|
|
|
|
from inventory.models.item import ItemFileModel, ItemImageModel
|
2022-07-21 19:34:21 +00:00
|
|
|
|
from inventory.string_utils import ltruncatechars
|
2020-10-17 16:34:05 +00:00
|
|
|
|
|
|
|
|
|
|
2021-09-29 17:17:52 +00:00
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
2020-11-15 11:53:05 +00:00
|
|
|
|
class ItemLinkModelInline(UserInlineMixin, SortableInlineAdminMixin, admin.TabularInline):
|
|
|
|
|
model = ItemLinkModel
|
|
|
|
|
extra = 0
|
|
|
|
|
|
|
|
|
|
|
2021-10-09 18:10:14 +00:00
|
|
|
|
class ItemImageModelInline(BaseImageModelInline):
|
2020-11-15 11:53:05 +00:00
|
|
|
|
model = ItemImageModel
|
2020-10-24 14:33:02 +00:00
|
|
|
|
|
2020-11-15 11:53:05 +00:00
|
|
|
|
|
2021-10-09 18:10:14 +00:00
|
|
|
|
class ItemFileModelInline(BaseFileModelInline):
|
2021-04-28 15:03:24 +00:00
|
|
|
|
model = ItemFileModel
|
|
|
|
|
|
|
|
|
|
|
2020-11-15 11:53:05 +00:00
|
|
|
|
class ItemModelResource(ModelResource):
|
2020-10-24 14:33:02 +00:00
|
|
|
|
class Meta:
|
|
|
|
|
model = ItemModel
|
|
|
|
|
|
|
|
|
|
|
2020-10-16 15:54:34 +00:00
|
|
|
|
@admin.register(ItemModel)
|
2022-12-22 08:55:42 +00:00
|
|
|
|
class ItemModelAdmin(TagulousModelAdminFix, ImportExportMixin, SortableAdminMixin, BaseUserAdmin):
|
2022-09-30 18:24:57 +00:00
|
|
|
|
@admin.display(description=_('Related items'))
|
|
|
|
|
def related_items(self, obj):
|
|
|
|
|
if obj.pk is None:
|
|
|
|
|
# Add a new item -> there are no related items ;)
|
|
|
|
|
return '-'
|
|
|
|
|
|
|
|
|
|
related_qs = ItemModel.tree_objects.related_objects(instance=obj)
|
|
|
|
|
context = {
|
|
|
|
|
'items': related_qs,
|
|
|
|
|
'opts': self.opts,
|
|
|
|
|
}
|
|
|
|
|
return render_to_string('admin/item/related_items.html', context)
|
|
|
|
|
|
2022-07-21 19:34:21 +00:00
|
|
|
|
@admin.display(ordering='path_str', description=_('ItemModel.verbose_name'))
|
|
|
|
|
def item(self, obj):
|
|
|
|
|
path = obj.path
|
|
|
|
|
if len(path) > 1:
|
|
|
|
|
prefixes = ' › '.join(path[:-1] + [''])
|
|
|
|
|
prefixes = ltruncatechars(prefixes, max_length=settings.TREE_PATH_STR_MAX_LENGTH)
|
|
|
|
|
else:
|
|
|
|
|
prefixes = ''
|
|
|
|
|
item = path[-1]
|
|
|
|
|
url = reverse('admin:inventory_itemmodel_change', args=[obj.pk])
|
|
|
|
|
return format_html(
|
2025-09-20 19:09:12 +00:00
|
|
|
|
format_string='<a href="{url}">{prefixes}<strong>{item}</strong></a>',
|
|
|
|
|
url=url,
|
|
|
|
|
prefixes=prefixes,
|
|
|
|
|
item=item,
|
2022-07-21 19:34:21 +00:00
|
|
|
|
)
|
|
|
|
|
|
2021-09-15 17:42:49 +00:00
|
|
|
|
def get_queryset(self, request):
|
|
|
|
|
qs = super().get_queryset(request)
|
|
|
|
|
qs = qs.prefetch_related(
|
2022-07-28 19:06:56 +00:00
|
|
|
|
'location',
|
2021-09-15 17:42:49 +00:00
|
|
|
|
'kind',
|
|
|
|
|
'producer',
|
|
|
|
|
)
|
|
|
|
|
return qs
|
|
|
|
|
|
2022-12-22 07:07:29 +00:00
|
|
|
|
def get_max_order(self, request, obj=None):
|
|
|
|
|
# Work-a-round for: https://github.com/jrief/django-admin-sortable2/issues/341
|
|
|
|
|
return 0
|
|
|
|
|
|
2020-10-17 16:34:05 +00:00
|
|
|
|
date_hierarchy = 'create_dt'
|
2023-07-20 18:15:44 +00:00
|
|
|
|
list_display = ('producer', 'item', 'kind', 'location', 'received_date', 'update_dt')
|
2022-07-21 19:34:21 +00:00
|
|
|
|
ordering = ('path_str',)
|
2022-12-22 07:07:29 +00:00
|
|
|
|
list_display_links = ()
|
2025-09-21 11:18:13 +00:00
|
|
|
|
list_filter = (
|
|
|
|
|
LimitTreeDepthListFilter,
|
|
|
|
|
('kind', admin.RelatedOnlyFieldListFilter),
|
|
|
|
|
('location', admin.RelatedOnlyFieldListFilter),
|
|
|
|
|
('producer', admin.RelatedOnlyFieldListFilter),
|
|
|
|
|
('tags', admin.RelatedOnlyFieldListFilter),
|
|
|
|
|
)
|
2021-01-19 18:02:40 +00:00
|
|
|
|
search_fields = ('name', 'description', 'kind__name', 'tags__name')
|
2020-10-17 16:34:05 +00:00
|
|
|
|
fieldsets = (
|
2022-09-30 18:24:57 +00:00
|
|
|
|
(
|
|
|
|
|
_('Internals'),
|
|
|
|
|
{
|
|
|
|
|
'classes': ('collapse',),
|
|
|
|
|
'fields': (
|
|
|
|
|
('id', 'version'),
|
|
|
|
|
'user',
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
(_('Meta'), {'classes': ('collapse',), 'fields': ('create_dt', 'update_dt')}),
|
|
|
|
|
(
|
|
|
|
|
_('Basic'),
|
|
|
|
|
{
|
|
|
|
|
'fields': (
|
|
|
|
|
'kind',
|
|
|
|
|
('producer', 'name'),
|
|
|
|
|
'description',
|
|
|
|
|
'tags',
|
|
|
|
|
'fcc_id',
|
|
|
|
|
'parent',
|
|
|
|
|
'location',
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
(_('Related items'), {'classes': ('collapse',), 'fields': ('related_items',)}),
|
|
|
|
|
(
|
|
|
|
|
_('Lent'),
|
|
|
|
|
{
|
|
|
|
|
'classes': ('collapse',),
|
|
|
|
|
'fields': (
|
|
|
|
|
'lent_to',
|
|
|
|
|
(
|
|
|
|
|
'lent_from_date',
|
|
|
|
|
'lent_until_date',
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
(
|
|
|
|
|
_('Received'),
|
|
|
|
|
{
|
|
|
|
|
'classes': ('collapse',),
|
|
|
|
|
'fields': (('received_from', 'received_date', 'received_price'),),
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
(
|
|
|
|
|
_('Handed over'),
|
|
|
|
|
{
|
|
|
|
|
'classes': ('collapse',),
|
|
|
|
|
'fields': (('handed_over_to', 'handed_over_date', 'handed_over_price'),),
|
|
|
|
|
},
|
|
|
|
|
),
|
2020-10-17 16:34:05 +00:00
|
|
|
|
)
|
2022-09-30 17:20:07 +00:00
|
|
|
|
autocomplete_fields = ('parent', 'location')
|
2022-09-30 18:24:57 +00:00
|
|
|
|
readonly_fields = ('id', 'create_dt', 'update_dt', 'user', 'related_items')
|
2021-04-28 15:03:24 +00:00
|
|
|
|
inlines = (ItemImageModelInline, ItemFileModelInline, ItemLinkModelInline)
|
2020-10-17 16:34:05 +00:00
|
|
|
|
|
2023-07-21 04:06:04 +00:00
|
|
|
|
def get_list_display(self, request):
|
|
|
|
|
list_display = list(super().get_list_display(request))
|
|
|
|
|
|
|
|
|
|
# FIXME: SortableAdminMixin.get_list_display() adds this, we didn't need here:
|
|
|
|
|
# See: https://github.com/jrief/django-admin-sortable2/issues/363
|
|
|
|
|
if '_reorder_' in list_display:
|
|
|
|
|
list_display.remove('_reorder_')
|
|
|
|
|
|
|
|
|
|
return list_display
|
|
|
|
|
|
2020-10-17 16:34:05 +00:00
|
|
|
|
|
|
|
|
|
tagulous.admin.enhance(ItemModel, ItemModelAdmin)
|