models.py 8.89 KB
Newer Older
Skia's avatar
Skia committed
1 2
from django.db import models
from django.utils.translation import ugettext_lazy as _
3
from django.utils import timezone
Skia's avatar
Skia committed
4
from django.conf import settings
Skia's avatar
Skia committed
5
from django.core.urlresolvers import reverse
Skia's avatar
Skia committed
6

7
from datetime import timedelta
8
from random import randrange
9

Skia's avatar
Skia committed
10
from club.models import Club
11 12
from accounting.models import CurrencyField
from core.models import Group, User
Skia's avatar
Skia committed
13

14 15 16 17 18 19 20
class Customer(models.Model):
    """
    This class extends a user to make a customer. It adds some basic customers informations, such as the accound ID, and
    is used by other accounting classes as reference to the customer, rather than using User
    """
    user = models.OneToOneField(User, primary_key=True)
    account_id = models.CharField(_('account id'), max_length=10, unique=True)
Skia's avatar
Skia committed
21
    amount = CurrencyField(_('amount'))
22 23 24 25 26 27 28 29

    class Meta:
        verbose_name = _('customer')
        verbose_name_plural = _('customers')

    def __str__(self):
        return self.user.username

30 31 32
    def generate_account_id():
        return randrange(0, 4000) # TODO: improve me!

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
class ProductType(models.Model):
    """
    This describes a product type
    Useful only for categorizing, changes are made at the product level for now
    """
    name = models.CharField(_('name'), max_length=30)
    description = models.TextField(_('description'), null=True, blank=True)
    icon = models.ImageField(upload_to='products', null=True, blank=True)

    def is_owned_by(self, user):
        """
        Method to see if that object can be edited by the given user
        """
        if user.is_in_group(settings.SITH_GROUPS['accounting-admin']['name']):
            return True
        return False

    def __str__(self):
        return self.name

class Product(models.Model):
    """
    This describes a product, with all its related informations
    """
    name = models.CharField(_('name'), max_length=30)
    description = models.TextField(_('description'), blank=True)
    product_type = models.ForeignKey(ProductType, related_name='products', null=True, blank=True)
    code = models.CharField(_('code'), max_length=10)
    purchase_price = CurrencyField(_('purchase price'))
    selling_price = CurrencyField(_('selling price'))
    special_selling_price = CurrencyField(_('special selling price'))
    icon = models.ImageField(upload_to='products', null=True, blank=True)
    club = models.ForeignKey(Club, related_name="products")

67
    def is_owned_by(self, user):
68 69 70 71 72 73 74 75 76 77
        """
        Method to see if that object can be edited by the given user
        """
        if user.is_in_group(settings.SITH_GROUPS['accounting-admin']['name']):
            return True
        return False

    def __str__(self):
        return self.name

Skia's avatar
Skia committed
78 79 80 81
class Counter(models.Model):
    name = models.CharField(_('name'), max_length=30)
    club = models.ForeignKey(Club, related_name="counters")
    products = models.ManyToManyField(Product, related_name="counters", blank=True)
Skia's avatar
Skia committed
82 83
    type = models.CharField(_('subscription type'),
            max_length=255,
Skia's avatar
Skia committed
84
            choices=[('BAR',_('Bar')), ('OFFICE',_('Office')), ('EBOUTIC',_('Eboutic'))])
Skia's avatar
Skia committed
85 86
    edit_groups = models.ManyToManyField(Group, related_name="editable_counters", blank=True)
    view_groups = models.ManyToManyField(Group, related_name="viewable_counters", blank=True)
Skia's avatar
Skia committed
87
    barmen_session = {}
Skia's avatar
Skia committed
88 89 90

    def __getattribute__(self, name):
        if name == "owner_group":
91
            return Group.objects.filter(name=self.club.unix_name+settings.SITH_BOARD_SUFFIX).first()
Skia's avatar
Skia committed
92 93 94 95
        return object.__getattribute__(self, name)

    def __str__(self):
        return self.name
Skia's avatar
Skia committed
96 97

    def get_absolute_url(self):
Skia's avatar
Skia committed
98 99
        if self.type == "EBOUTIC":
            return reverse('eboutic:main')
Skia's avatar
Skia committed
100 101
        return reverse('counter:details', kwargs={'counter_id': self.id})

102 103 104
    def can_be_edited_by(self, user):
        return user.is_in_group(settings.SITH_GROUPS['counter-admin']['name'])

Skia's avatar
Skia committed
105
    def can_be_viewed_by(self, user):
Skia's avatar
Skia committed
106
        return user.is_in_group(settings.SITH_MAIN_BOARD_GROUP)
107

Skia's avatar
Skia committed
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
    def add_barman(counter_id, user_id):
        """
        Logs a barman in to the given counter
        A user is stored as a tuple with its login time
        """
        counter_id = int(counter_id)
        user_id = int(user_id)
        if counter_id not in Counter.barmen_session.keys():
            Counter.barmen_session[counter_id] = {'users': {(user_id, timezone.now())}, 'time': timezone.now()}
        else:
            Counter.barmen_session[counter_id]['users'].add((user_id, timezone.now()))

    def del_barman(counter_id, user_id):
        """
        Logs a barman out and store its permanency
        """
        counter_id = int(counter_id)
        user_id = int(user_id)
        user_tuple = None
        for t in Counter.barmen_session[counter_id]['users']:
            if t[0] == user_id: user_tuple = t
        Counter.barmen_session[counter_id]['users'].remove(user_tuple)
        u = User.objects.filter(id=user_id).first()
        c = Counter.objects.filter(id=counter_id).first()
        Permanency(user=u, counter=c, start=user_tuple[1], end=Counter.barmen_session[counter_id]['time']).save()

134
    def get_barmen_list(counter_id):
Skia's avatar
Skia committed
135
        """
Skia's avatar
Skia committed
136
        Returns the barman list as list of User
Skia's avatar
Skia committed
137 138 139

        Also handle the timeout of the barmen
        """
140
        bl = []
Skia's avatar
Skia committed
141
        counter_id = int(counter_id)
142
        if counter_id in list(Counter.barmen_session.keys()):
Skia's avatar
Skia committed
143 144
            for b in Counter.barmen_session[counter_id]['users']:
                # Reminder: user is stored as a tuple with its login time
Skia's avatar
Skia committed
145
                bl.append(User.objects.filter(id=b[0]).first())
146 147 148
            if (timezone.now() - Counter.barmen_session[counter_id]['time']) < timedelta(minutes=settings.SITH_BARMAN_TIMEOUT):
                Counter.barmen_session[counter_id]['time'] = timezone.now()
            else:
Skia's avatar
Skia committed
149 150 151
                for b in bl:
                    Counter.del_barman(counter_id, b.id)
                bl = []
152 153 154
                Counter.barmen_session[counter_id]['users'] = set()
        return bl

Skia's avatar
Skia committed
155
    def get_random_barman(counter_id):
Skia's avatar
Skia committed
156
        bl = Counter.get_barmen_list(counter_id)
Skia's avatar
Skia committed
157
        return bl[randrange(0, len(bl))]
Skia's avatar
Skia committed
158 159 160 161 162 163 164

class Refilling(models.Model):
    """
    Handle the refilling
    """
    counter = models.ForeignKey(Counter, related_name="refillings", blank=False)
    amount = CurrencyField(_('amount'))
165 166
    operator = models.ForeignKey(User, related_name="refillings_as_operator", blank=False)
    customer = models.ForeignKey(Customer, related_name="refillings", blank=False)
Skia's avatar
Skia committed
167 168
    date = models.DateTimeField(_('date'), auto_now=True)
    payment_method = models.CharField(_('payment method'), max_length=255,
169 170 171
            choices=settings.SITH_COUNTER_PAYMENT_METHOD, default='cash')
    bank = models.CharField(_('bank'), max_length=255,
            choices=settings.SITH_COUNTER_BANK, default='other')
Skia's avatar
Skia committed
172 173

    def __str__(self):
Skia's avatar
Skia committed
174
        return "Refilling: %.2f for %s" % (self.amount, self.customer.user.get_display_name())
Skia's avatar
Skia committed
175 176 177 178 179 180

    # def get_absolute_url(self):
    #     return reverse('counter:details', kwargs={'counter_id': self.id})

    def save(self, *args, **kwargs):
        self.full_clean()
Skia's avatar
Skia committed
181
        self.customer.amount += self.amount
Skia's avatar
Skia committed
182
        self.customer.save()
Skia's avatar
Skia committed
183
        super(Refilling, self).save(*args, **kwargs)
Skia's avatar
Skia committed
184 185 186 187 188 189 190 191 192

class Selling(models.Model):
    """
    Handle the sellings
    """
    product = models.ForeignKey(Product, related_name="sellings", blank=False)
    counter = models.ForeignKey(Counter, related_name="sellings", blank=False)
    unit_price = CurrencyField(_('unit price'))
    quantity = models.IntegerField(_('quantity'))
193 194
    seller = models.ForeignKey(User, related_name="sellings_as_operator", blank=False)
    customer = models.ForeignKey(Customer, related_name="buyings", blank=False)
Skia's avatar
Skia committed
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
    date = models.DateTimeField(_('date'), auto_now=True)

    def __str__(self):
        return "Selling: %d x %s (%f) for %s" % (self.quantity, self.product.name,
                self.quantity*self.unit_price, self.customer.user.get_display_name())

    def save(self, *args, **kwargs):
        self.full_clean()
        self.customer.amount -= self.quantity * self.unit_price
        self.customer.save()
        super(Selling, self).save(*args, **kwargs)

    # def get_absolute_url(self):
    #     return reverse('counter:details', kwargs={'counter_id': self.id})

Skia's avatar
Skia committed
210 211 212 213 214 215 216 217 218 219 220 221 222
class Permanency(models.Model):
    """
    This class aims at storing a traceability of who was barman where and when
    """
    user = models.ForeignKey(User, related_name="permanencies")
    counter = models.ForeignKey(Counter, related_name="permanencies")
    start = models.DateTimeField(_('start date'))
    end = models.DateTimeField(_('end date'))

    def __str__(self):
        return "%s in %s from %s to %s" % (self.user, self.counter,
                self.start.strftime("%Y-%m-%d %H:%M:%S"), self.end.strftime("%Y-%m-%d %H:%M:%S"))

223 224 225 226 227 228

# TODO:
# une classe Vente
# foreign key vers comptoir, vendeur, client, produit, mais stocker le prix du produit, pour gerer les maj de prix
# une classe Rechargement
# foreign key vers comptoir, vendeur, client, plus montant
Skia's avatar
Skia committed
229