import logging from pathlib import Path import tagulous.models from bx_django_utils.filename import clean_filename from django.db import models from django.urls import reverse from django.utils.translation import gettext_lazy as _ from django_tools.model_version_protect.models import VersionProtectBaseModel from django_tools.serve_media_app.models import user_directory_path from tinymce.models import HTMLField from inventory.models.base import BaseItemAttachmentModel, BaseParentTreeModel from inventory.models.links import BaseLink logger = logging.getLogger(__name__) class ItemQuerySet(models.QuerySet): def sort(self): return self.order_by('kind', 'producer', 'name') class ItemModel(BaseParentTreeModel, VersionProtectBaseModel): """ A Item that can be described and store somewhere ;) """ objects = ItemQuerySet.as_manager() kind = tagulous.models.TagField( case_sensitive=False, force_lowercase=False, space_delimiter=False, max_count=3, verbose_name=_('ItemModel.kind.verbose_name'), help_text=_('ItemModel.kind.help_text'), ) producer = tagulous.models.TagField( blank=True, case_sensitive=False, force_lowercase=False, space_delimiter=False, max_count=1, verbose_name=_('ItemModel.producer.verbose_name'), help_text=_('ItemModel.producer.help_text'), ) description = HTMLField( blank=True, null=True, verbose_name=_('ItemModel.description.verbose_name'), help_text=_('ItemModel.description.help_text'), ) fcc_id = models.CharField( max_length=20, blank=True, null=True, verbose_name=_('ItemModel.fcc_id.verbose_name'), help_text=_('ItemModel.fcc_id.help_text'), ) location = models.ForeignKey( 'inventory.LocationModel', blank=True, null=True, on_delete=models.SET_NULL, related_name='items', verbose_name=_('ItemModel.location.verbose_name'), help_text=_('ItemModel.location.help_text'), ) # ________________________________________________________________________ # lent lent_to = models.CharField( max_length=64, blank=True, null=True, verbose_name=_('ItemModel.lent_to.verbose_name'), help_text=_('ItemModel.lent_to.help_text'), ) lent_from_date = models.DateField( blank=True, null=True, verbose_name=_('ItemModel.lent_from_date.verbose_name'), help_text=_('ItemModel.lent_from_date.help_text'), ) lent_until_date = models.DateField( blank=True, null=True, verbose_name=_('ItemModel.lent_until_date.verbose_name'), help_text=_('ItemModel.lent_until_date.help_text'), ) # ________________________________________________________________________ # received received_from = models.CharField( max_length=64, blank=True, null=True, verbose_name=_('ItemModel.received_from.verbose_name'), help_text=_('ItemModel.received_from.help_text'), ) received_date = models.DateField( blank=True, null=True, verbose_name=_('ItemModel.received_date.verbose_name'), help_text=_('ItemModel.received_date.help_text'), ) received_price = models.DecimalField( decimal_places=2, max_digits=6, # up to 9999 with a resolution of 2 decimal places blank=True, null=True, verbose_name=_('ItemModel.received_price.verbose_name'), help_text=_('ItemModel.received_price.help_text'), ) # ________________________________________________________________________ # handed over handed_over_to = models.CharField( max_length=64, blank=True, null=True, verbose_name=_('ItemModel.handed_over_to.verbose_name'), help_text=_('ItemModel.handed_over_to.help_text'), ) handed_over_date = models.DateField( blank=True, null=True, verbose_name=_('ItemModel.handed_over_date.verbose_name'), help_text=_('ItemModel.handed_over_date.help_text'), ) handed_over_price = models.DecimalField( decimal_places=2, max_digits=6, # up to 9999 with a resolution of 2 decimal places blank=True, null=True, verbose_name=_('ItemModel.handed_over_price.verbose_name'), help_text=_('ItemModel.handed_over_price.help_text'), ) def local_admin_link(self): url = reverse('admin:inventory_itemmodel_change', args=[self.id]) return url def verbose_name(self): parts = [str(part) for part in (self.kind, self.producer, self.name)] return ' - '.join(part for part in parts if part) class Meta: ordering = ('path_str',) verbose_name = _('ItemModel.verbose_name') verbose_name_plural = _('ItemModel.verbose_name_plural') class ItemLinkModel(BaseLink): item = models.ForeignKey(ItemModel, on_delete=models.CASCADE) def full_clean(self, **kwargs): if self.user_id is None: # inherit owner of this link from item instance self.user_id = self.item.user_id return super().full_clean(**kwargs) class Meta: verbose_name = _('ItemLinkModel.verbose_name') verbose_name_plural = _('ItemLinkModel.verbose_name_plural') ordering = ('position',) class ItemImageModel(BaseItemAttachmentModel): """ Store images to Items """ image = models.ImageField( upload_to=user_directory_path, verbose_name=_('ItemImageModel.image.verbose_name'), help_text=_('ItemImageModel.image.help_text'), ) def __str__(self): return self.name or self.image.name def full_clean(self, **kwargs): # Set name by image filename: if not self.name: filename = Path(self.image.name).name self.name = clean_filename(filename) return super().full_clean(**kwargs) class Meta: verbose_name = _('ItemImageModel.verbose_name') verbose_name_plural = _('ItemImageModel.verbose_name_plural') ordering = ('position',) class ItemFileModel(BaseItemAttachmentModel): """ Store files to Items """ file = models.FileField( upload_to=user_directory_path, verbose_name=_('ItemFileModel.file.verbose_name'), help_text=_('ItemFileModel.file.help_text'), ) def __str__(self): return self.name or self.file.name def full_clean(self, **kwargs): # Set name by filename: if not self.name: filename = Path(self.file.name).name self.name = clean_filename(filename) return super().full_clean(**kwargs) class Meta: verbose_name = _('ItemFileModel.verbose_name') verbose_name_plural = _('ItemFileModel.verbose_name_plural') ordering = ('position',)