#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (C) 2012 Étienne Loks # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # See the file COPYING for details. import datetime from django.contrib.gis.db import models from django.db.models.signals import post_save, post_delete from django.template.defaultfilters import slugify from django.utils.translation import ugettext_lazy as _, ugettext from ishtar_common.models import GeneralType, \ LightHistorizedItem, OwnPerms, Address, Person, post_save_cache class WarehouseType(GeneralType): class Meta: verbose_name = _(u"Warehouse type") verbose_name_plural = _(u"Warehouse types") ordering = ('label',) post_save.connect(post_save_cache, sender=WarehouseType) post_delete.connect(post_save_cache, sender=WarehouseType) class Warehouse(Address, OwnPerms): SHOW_URL = 'show-warehouse' name = models.CharField(_(u"Name"), max_length=200) warehouse_type = models.ForeignKey(WarehouseType, verbose_name=_(u"Warehouse type")) person_in_charge = models.ForeignKey( Person, on_delete=models.SET_NULL, related_name='warehouse_in_charge', verbose_name=_(u"Person in charge"), null=True, blank=True) comment = models.TextField(_(u"Comment"), null=True, blank=True) associated_divisions = models.ManyToManyField( 'WarehouseDivision', verbose_name=_("Divisions"), blank=True, through='WarehouseDivisionLink' ) TABLE_COLS = ['name', 'warehouse_type'] class Meta: verbose_name = _(u"Warehouse") verbose_name_plural = _(u"Warehouses") permissions = ( ("view_warehouse", ugettext(u"Can view all Warehouses")), ("view_own_warehouse", ugettext(u"Can view own Warehouse")), ("add_own_warehouse", ugettext(u"Can add own Warehouse")), ("change_own_warehouse", ugettext(u"Can change own Warehouse")), ("delete_own_warehouse", ugettext(u"Can delete own Warehouse")), ) def __unicode__(self): return u"%s (%s)" % (self.name, unicode(self.warehouse_type)) @property def associated_filename(self): return datetime.date.today().strftime('%Y-%m-%d') + '-' + \ slugify(unicode(self)) class WarehouseDivision(GeneralType): class Meta: verbose_name = _(u"Warehouse division") verbose_name_plural = _(u"Warehouse divisions") post_save.connect(post_save_cache, sender=WarehouseDivision) post_delete.connect(post_save_cache, sender=WarehouseDivision) class WarehouseDivisionLink(models.Model): RELATIVE_MODELS = {Warehouse: 'warehouse'} warehouse = models.ForeignKey(Warehouse) division = models.ForeignKey(WarehouseDivision) order = models.IntegerField(_("Order"), default=10) class Meta: ordering = ('warehouse', 'order') unique_together = ('warehouse', 'division') def __unicode__(self): return u"{} - {}".format(self.warehouse, self.division) class ContainerType(GeneralType): length = models.IntegerField(_(u"Length (mm)"), blank=True, null=True) width = models.IntegerField(_(u"Width (mm)"), blank=True, null=True) height = models.IntegerField(_(u"Height (mm)"), blank=True, null=True) volume = models.IntegerField(_(u"Volume (l)"), blank=True, null=True) reference = models.CharField(_(u"Ref."), max_length=30) class Meta: verbose_name = _(u"Container type") verbose_name_plural = _(u"Container types") ordering = ('label',) post_save.connect(post_save_cache, sender=ContainerType) post_delete.connect(post_save_cache, sender=ContainerType) class Container(LightHistorizedItem): TABLE_COLS = ['reference', 'container_type__label', 'location__name'] # search parameters EXTRA_REQUEST_KEYS = { 'location': 'location__pk', 'container_type': 'container_type__pk', 'reference': 'reference__icontains', } SHOW_URL = 'show-container' # fields location = models.ForeignKey(Warehouse, verbose_name=_(u"Warehouse"), related_name='containers') container_type = models.ForeignKey(ContainerType, verbose_name=_("Container type")) reference = models.CharField(_(u"Container ref."), max_length=40) comment = models.TextField(_(u"Comment")) class Meta: verbose_name = _(u"Container") verbose_name_plural = _(u"Containers") def __unicode__(self): lbl = u" - ".join((self.reference, unicode(self.container_type), unicode(self.location))) return lbl @property def associated_filename(self): return datetime.date.today().strftime('%Y-%m-%d') + '-' + \ "-".join([str(slugify(getattr(self, attr))) for attr in ('location', 'container_type', 'reference')]) @property def precise_location(self): location = unicode(self.location) locas = [ u"{} {}".format(loca.division.division, loca.reference) for loca in ContainerLocalisation.objects.filter( container=self) ] return location + u" - " + u", ".join(locas) class ContainerLocalisation(models.Model): container = models.ForeignKey(Container, verbose_name=_(u"Container")) division = models.ForeignKey(WarehouseDivisionLink, verbose_name=_(u"Division")) reference = models.CharField(_(u"Reference"), max_length=200, default='') class Meta: verbose_name = _(u"Container localisation") verbose_name_plural = _(u"Container localisations") unique_together = ('container', 'division') ordering = ('container', 'division__order') def __unicode__(self): lbl = u" - ".join((unicode(self.container), unicode(self.division), self.reference)) return lbl