# Path: depot/models.py
# class Depot(models.Model):
#     """
#     A depot has a name and many depot managers.
# 
#     :author: Leo Tappe
#     :author: Benedikt Seidl
#     """
# 
#     name = models.CharField(max_length=32)
#     description = models.CharField(max_length=256, blank=True)
#     organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
#     manager_users = models.ManyToManyField(User, blank=True)
#     manager_groups = models.ManyToManyField(Group, blank=True)
#     active = models.BooleanField(default=True)
# 
#     def managed_by(self, user):
#         """
#         Depots are managed by superusers, the organization's managers,
#         any manager user and any user in a manager group.
#         """
# 
#         return (user.is_superuser
#                 or self.organization.managed_by(user)
#                 or self.manager_users.filter(id=user.id).exists()
#                 or self.manager_groups.filter(id__in=user.groups.all()).exists())
# 
#     def show_internal_items(self, user):
#         """
#         Internal items can be seen by superusers and organization members.
#         """
# 
#         return user.is_superuser or self.organization.is_member(user)
# 
#     def visible_items(self, user):
#         """
#         Return the list of items the user is allowed to see in this depot.
#         """
# 
#         if self.show_internal_items(user):
#             return self.active_items.all()
#         else:
#             return self.public_items.all()
# 
#     @property
#     def managers(self):
#         """
#         The list of users explicitly listed as managers of this depot.
#         Does not include any organization managers or superusers which are
#         not added to the depot.
#         """
# 
#         return User.objects.filter(
#             models.Q(id__in=self.manager_users.all())
#             | models.Q(groups__in=self.manager_groups.all())
#         ).distinct()
# 
#     @property
#     def public_items(self):
#         """
#         List all items with the visibility set to public.
#         """
# 
#         return self.item_set.filter(visibility=Item.VISIBILITY_PUBLIC)
# 
#     @property
#     def active_items(self):
#         return self.item_set.filter(
#             models.Q(visibility=Item.VISIBILITY_PUBLIC)
#             | models.Q(visibility=Item.VISIBILITY_INTERNAL)
#         )
# 
#     @staticmethod
#     def filter_by_user(user):
#         """
#         Filter for depots managed by the given user
#         """
# 
#         return (models.Q(organization__managers__id=user.id)
#                 | models.Q(manager_users__id=user.id)
#                 | models.Q(manager_groups__id__in=user.groups.all()))
# 
#     def __str__(self):
#         return self.name
# 
# class Item(models.Model):
#     """
#     An item describes one or more instances of an object in a depot.
# 
#     It always belongs to a single depot and has a unique name within the depot.
#     The location field can be used to roughly describe where
#     the item can be found in the depot.
#     Items can either be public or internal which affects the visibility
#     of the item to users outside of the organization connected to the depot.
#     The quantity describes how many version of the item exist in the depot.
# 
#     :author: Leo Tappe
#     """
# 
#     VISIBILITY_PUBLIC = '1'
#     VISIBILITY_INTERNAL = '2'
#     VISIBILITY_DELETED = '3'
#     VISIBILITY_LEVELS = (
#         (VISIBILITY_PUBLIC, _('public')),
#         (VISIBILITY_INTERNAL, _('internal')),
#         (VISIBILITY_DELETED, _('deleted')),
#     )
# 
#     name = models.CharField(max_length=32)
#     description = models.CharField(max_length=1024, blank=True)
#     quantity = models.PositiveSmallIntegerField()
#     visibility = models.CharField(max_length=1, choices=VISIBILITY_LEVELS)
#     location = models.CharField(max_length=256, blank=True)
#     depot = models.ForeignKey(Depot, on_delete=models.CASCADE)
# 
#     @staticmethod
#     def filter_by_user(user):
#         """
#         Filter for items managed by the given user
#         """
# 
#         return (models.Q(depot__organization__managers__id=user.id)
#                 | models.Q(depot__manager_users__id=user.id)
#                 | models.Q(depot__manager_groups__id__in=user.groups.all()))
# 
#     class Meta:
#         unique_together = (
#             ('name', 'depot'),
#         )
# 
#     def __str__(self):
#         return self.name


import uuid
from datetime import datetime
from django.db import models
from django.core.exceptions import ValidationError
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
from depot.models import Depot, Item
    A rental defines the amount of items and has a start and return date.
    Only items from one depot can be requested for rental at once.

    When requesting a rental, the user has to enter his full name and email
    address as well as describing the purpose of his rental. If they are
    logged in, the user's id will be stored as well.

    After creating a rental request, it is in the PENDING state. From this,
    it can be either APPROVED or DECLINED by a depot manager or REVOKED by
    the requesting user. If all items were returned correctly, it can be
    set to RETURNED to finish the rental process.

    :author: Benedikt Seidl
    """

    STATE_PENDING = '1'
    STATE_APPROVED = '2'
    STATE_DECLINED = '3'
    STATE_REVOKED = '4'
    STATE_RETURNED = '5'
    STATES = (
        (STATE_PENDING, _('pending')),
        (STATE_APPROVED, _('approved')),
        (STATE_DECLINED, _('declined')),
        (STATE_REVOKED, _('revoked')),
        (STATE_RETURNED, _('returned')),
    )

    uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    depot = models.ForeignKey(Depot, on_delete=models.CASCADE)

# Path: depot/models.py
# class Depot(models.Model):
#     """
#     A depot has a name and many depot managers.
# 
#     :author: Leo Tappe
#     :author: Benedikt Seidl
#     """
# 
#     name = models.CharField(max_length=32)
#     description = models.CharField(max_length=256, blank=True)
#     organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
#     manager_users = models.ManyToManyField(User, blank=True)
#     manager_groups = models.ManyToManyField(Group, blank=True)
#     active = models.BooleanField(default=True)
# 
#     def managed_by(self, user):
#         """
#         Depots are managed by superusers, the organization's managers,
#         any manager user and any user in a manager group.
#         """
# 
#         return (user.is_superuser
#                 or self.organization.managed_by(user)
#                 or self.manager_users.filter(id=user.id).exists()
#                 or self.manager_groups.filter(id__in=user.groups.all()).exists())
# 
#     def show_internal_items(self, user):
#         """
#         Internal items can be seen by superusers and organization members.
#         """
# 
#         return user.is_superuser or self.organization.is_member(user)
# 
#     def visible_items(self, user):
#         """
#         Return the list of items the user is allowed to see in this depot.
#         """
# 
#         if self.show_internal_items(user):
#             return self.active_items.all()
#         else:
#             return self.public_items.all()
# 
#     @property
#     def managers(self):
#         """
#         The list of users explicitly listed as managers of this depot.
#         Does not include any organization managers or superusers which are
#         not added to the depot.
#         """
# 
#         return User.objects.filter(
#             models.Q(id__in=self.manager_users.all())
#             | models.Q(groups__in=self.manager_groups.all())
#         ).distinct()
# 
#     @property
#     def public_items(self):
#         """
#         List all items with the visibility set to public.
#         """
# 
#         return self.item_set.filter(visibility=Item.VISIBILITY_PUBLIC)
# 
#     @property
#     def active_items(self):
#         return self.item_set.filter(
#             models.Q(visibility=Item.VISIBILITY_PUBLIC)
#             | models.Q(visibility=Item.VISIBILITY_INTERNAL)
#         )
# 
#     @staticmethod
#     def filter_by_user(user):
#         """
#         Filter for depots managed by the given user
#         """
# 
#         return (models.Q(organization__managers__id=user.id)
#                 | models.Q(manager_users__id=user.id)
#                 | models.Q(manager_groups__id__in=user.groups.all()))
# 
#     def __str__(self):
#         return self.name
# 
# class Item(models.Model):
#     """
#     An item describes one or more instances of an object in a depot.
# 
#     It always belongs to a single depot and has a unique name within the depot.
#     The location field can be used to roughly describe where
#     the item can be found in the depot.
#     Items can either be public or internal which affects the visibility
#     of the item to users outside of the organization connected to the depot.
#     The quantity describes how many version of the item exist in the depot.
# 
#     :author: Leo Tappe
#     """
# 
#     VISIBILITY_PUBLIC = '1'
#     VISIBILITY_INTERNAL = '2'
#     VISIBILITY_DELETED = '3'
#     VISIBILITY_LEVELS = (
#         (VISIBILITY_PUBLIC, _('public')),
#         (VISIBILITY_INTERNAL, _('internal')),
#         (VISIBILITY_DELETED, _('deleted')),
#     )
# 
#     name = models.CharField(max_length=32)
#     description = models.CharField(max_length=1024, blank=True)
#     quantity = models.PositiveSmallIntegerField()
#     visibility = models.CharField(max_length=1, choices=VISIBILITY_LEVELS)
#     location = models.CharField(max_length=256, blank=True)
#     depot = models.ForeignKey(Depot, on_delete=models.CASCADE)
# 
#     @staticmethod
#     def filter_by_user(user):
#         """
#         Filter for items managed by the given user
#         """
# 
#         return (models.Q(depot__organization__managers__id=user.id)
#                 | models.Q(depot__manager_users__id=user.id)
#                 | models.Q(depot__manager_groups__id__in=user.groups.all()))
# 
#     class Meta:
#         unique_together = (
#             ('name', 'depot'),
#         )
# 
#     def __str__(self):
#         return self.name


# Path: rental/models.py
import uuid
from datetime import datetime
from django.db import models
from django.core.exceptions import ValidationError
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
from depot.models import Depot, Item

    A rental defines the amount of items and has a start and return date.
    Only items from one depot can be requested for rental at once.

    When requesting a rental, the user has to enter his full name and email
    address as well as describing the purpose of his rental. If they are
    logged in, the user's id will be stored as well.

    After creating a rental request, it is in the PENDING state. From this,
    it can be either APPROVED or DECLINED by a depot manager or REVOKED by
    the requesting user. If all items were returned correctly, it can be
    set to RETURNED to finish the rental process.

    :author: Benedikt Seidl
    """

    STATE_PENDING = '1'
    STATE_APPROVED = '2'
    STATE_DECLINED = '3'
    STATE_REVOKED = '4'
    STATE_RETURNED = '5'
    STATES = (
        (STATE_PENDING, _('pending')),
        (STATE_APPROVED, _('approved')),
        (STATE_DECLINED, _('declined')),
        (STATE_REVOKED, _('revoked')),
        (STATE_RETURNED, _('returned')),
    )

    uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    depot = models.ForeignKey(Depot, on_delete=models.CASCADE)

    items = models.ManyToManyField(Item, through='ItemRental')