kpsul/kfet/models.py

349 lines
12 KiB
Python
Raw Normal View History

2016-08-02 10:40:46 +02:00
from django.db import models
from django.core.exceptions import PermissionDenied
from django.contrib.auth.models import User
from django.core.validators import RegexValidator
from gestioncof.models import CofProfile
from django.utils.six.moves import reduce
import datetime
def choices_length(choices):
return reduce(lambda m, choice: max(m, len(choice[0])), choices, 0)
def default_promo():
now = datetime.date.today()
return now.month <= 8 and now.year-1 or now.year
class Account(models.Model):
cofprofile = models.OneToOneField(
CofProfile, on_delete = models.PROTECT,
related_name = "account_kfet")
trigramme = models.CharField(
unique = True,
max_length = 3,
validators = [RegexValidator(regex='^[^a-z]{3}$')])
balance = models.DecimalField(
max_digits = 6, decimal_places = 2,
default = 0)
frozen = models.BooleanField(default = False)
# Optional
PROMO_CHOICES = [(r,r) for r in range(1980, datetime.date.today().year+1)]
promo = models.IntegerField(
choices = PROMO_CHOICES,
blank = True, null = True, default = default_promo())
nickname = models.CharField(
max_length = 255,
blank = True, default = "")
password = models.CharField(
max_length = 255,
unique = True,
blank = True, null = True, default = None)
def __str__(self):
return self.trigramme
@staticmethod
def is_free(trigramme):
try:
account = Account.objects.filter(trigramme=trigramme).get()
return False
except Account.DoesNotExist:
return True
# Méthode save() avec auth +
# Args:
# - auth_user : request.user
# - data : datas pour User et CofProfile
# Action:
# - Enregistre User, CofProfile à partir de "data"
# - Enregistre Account
# Permissions
# - Edition si request.user:
# - modifie son compte (ne peut pas modifier nickname)
# ou - a la perm kfet.change_account
# - Ajout si request.user a la perm kfet.add_account
def save_api(self, auth_user, data = None):
if self.pk:
# Account update
# Checking permissions
user = self.cofprofile.user
if not auth_user.has_perm('kfet.change_account') \
and request.user != user:
raise PermissionDenied
# Updating User with data
user.first_name = data.get("first_name", user.first_name)
user.last_name = data.get("last_name", user.last_name)
user.email = data.get("email", user.email)
user.save()
# Updating CofProfile with data
cof = self.cofprofile
cof.departement = data.get("departement", cof.departement)
cof.save()
# Nickname is not editable by the user
if not auth_user.has_perm('kfet.change_account'):
account_old = Account.objects.get(pk=self.pk)
self.nickname = account_old.nickname
else:
# New account
# Checking permissions
if not auth_user.has_perm('kfet.add_account'):
raise PermissionDenied
# Creating or updating User instance
username = data.get("username")
(user, _) = User.objects.get_or_create(username=username)
if "first_name" in data:
user.first_name = data['first_name']
if "last_name" in data:
user.last_name = data['last_name']
if "email" in data:
user.email = data['email']
user.save()
# Creating or updating CofProfile instance
(cof, _) = CofProfile.objects.get_or_create(user=user)
if "login_clipper" in data:
cof.login_clipper = data['login_clipper']
if "departement" in data:
cof.departement = data['departement']
cof.save()
# Check if cof is linked to an account
if hasattr(cof, 'account_kfet'):
raise Account.UserHasAccount(cof.account_kfet.trigramme)
self.cofprofile = cof
self.save()
# Surcharge de delete
# Pas de suppression possible
# Cas à régler plus tard
def delete(self, *args, **kwargs):
pass
class UserHasAccount(Exception):
def __init__(self, trigramme):
self.trigramme = trigramme
class AccountNegative(models.Model):
account = models.OneToOneField(
Account, on_delete = models.PROTECT,
related_name = "negative")
start = models.DateTimeField(default = datetime.datetime.now())
balance_offset = models.DecimalField(max_digits = 6, decimal_places = 2)
authorized_overdraft = models.DecimalField(
max_digits = 6, decimal_places = 2,
default = 0)
comment = models.CharField(max_length = 255, blank = True)
class Checkout(models.Model):
created_by = models.ForeignKey(
Account, on_delete = models.PROTECT,
related_name = "+")
name = models.CharField(max_length = 45)
valid_from = models.DateTimeField()
valid_to = models.DateTimeField()
balance = models.DecimalField(max_digits = 6, decimal_places = 2)
is_protected = models.BooleanField(default = False)
class CheckoutTransfer(models.Model):
from_checkout = models.ForeignKey(
Checkout, on_delete = models.PROTECT,
related_name = "transfers_from")
to_checkout = models.ForeignKey(
Checkout, on_delete = models.PROTECT,
related_name = "transfers_to")
amount = models.DecimalField(
max_digits = 6, decimal_places = 2)
class Statement(models.Model):
by = models.ForeignKey(
Account, on_delete = models.PROTECT,
related_name = "+")
checkout = models.ForeignKey(
Checkout, on_delete = models.PROTECT,
related_name = "statements")
balance_old = models.DecimalField(max_digits = 6, decimal_places = 2)
balance_new = models.DecimalField(max_digits = 6, decimal_places = 2)
amount_taken = models.DecimalField(max_digits = 6, decimal_places = 2)
amount_error = models.DecimalField(max_digits = 6, decimal_places = 2)
at = models.DateTimeField(auto_now_add = True)
class ArticleCategory(models.Model):
name = models.CharField(max_length = 45)
class Article(models.Model):
name = models.CharField(max_length = 45)
is_sold = models.BooleanField(default = True)
price = models.DecimalField(max_digits = 6, decimal_places = 2)
stock = models.IntegerField(default = 0)
category = models.ForeignKey(
ArticleCategory, on_delete = models.PROTECT,
related_name = "articles")
class ArticleRule(models.Model):
article_on = models.OneToOneField(
Article, on_delete = models.PROTECT,
related_name = "rule_on")
article_to = models.OneToOneField(
Article, on_delete = models.PROTECT,
related_name = "rule_to")
ratio = models.PositiveSmallIntegerField()
class Inventory(models.Model):
articles = models.ManyToManyField(
Article,
through = 'InventoryArticle',
related_name = "inventories")
by = models.ForeignKey(
Account, on_delete = models.PROTECT,
related_name = "+")
at = models.DateTimeField(auto_now_add = True)
# Optional
order = models.OneToOneField(
'Order', on_delete = models.PROTECT,
related_name = "inventory",
blank = True, null = True, default = None)
class InventoryArticle(models.Model):
inventory = models.ForeignKey(
Inventory, on_delete = models.PROTECT)
article = models.ForeignKey(
Article, on_delete = models.PROTECT)
stock_old = models.IntegerField()
stock_new = models.IntegerField()
stock_error = models.IntegerField(default = 0)
class Supplier(models.Model):
articles = models.ManyToManyField(
Article,
through = 'SupplierArticle',
related_name = "suppliers")
name = models.CharField(max_length = 45)
address = models.TextField()
email = models.EmailField()
phone = models.CharField(max_length = 10)
comment = models.TextField()
class SupplierArticle(models.Model):
supplier = models.ForeignKey(
Supplier, on_delete = models.PROTECT)
article = models.ForeignKey(
Article, on_delete = models.PROTECT)
BOX_TYPE_CHOICES = (
("caisse", "Caisse"),
("carton", "Carton"),
("palette", "Palette"),
("fût", "Fût"),
)
box_type = models.CharField(
choices = BOX_TYPE_CHOICES,
max_length = choices_length(BOX_TYPE_CHOICES))
box_capacity = models.PositiveSmallIntegerField()
price_HT = models.DecimalField(max_digits = 7, decimal_places = 4)
TVA = models.DecimalField(max_digits = 4, decimal_places = 2)
rights = models.DecimalField(max_digits = 7, decimal_places = 4)
class Order(models.Model):
supplier = models.ForeignKey(
Supplier, on_delete = models.PROTECT,
related_name = "orders")
articles = models.ManyToManyField(
Article,
through = "OrderArticle",
related_name = "orders")
at = models.DateTimeField(auto_now_add = True)
amount = models.DecimalField(max_digits = 6, decimal_places = 2)
class OrderArticle(models.Model):
order = models.ForeignKey(
Order, on_delete = models.PROTECT)
article = models.ForeignKey(
Article, on_delete = models.PROTECT)
quantity_ordered = models.IntegerField()
quantity_received = models.IntegerField()
class TransferGroup(models.Model):
at = models.DateTimeField(auto_now_add = True)
# Optional
comment = models.CharField(
max_length = 255,
blank = True, default = "")
valid_by = models.ForeignKey(
Account, on_delete = models.PROTECT,
related_name = "+",
blank = True, null = True, default = None)
class Transfer(models.Model):
group = models.ForeignKey(
TransferGroup, on_delete = models.PROTECT,
related_name = "transfers")
from_acc = models.ForeignKey(
Account, on_delete = models.PROTECT,
related_name = "transfers_from")
to_acc = models.ForeignKey(
Account, on_delete = models.PROTECT,
related_name = "transfers_to")
amount = models.DecimalField(max_digits = 6, decimal_places = 2)
# Optional
canceled_by = models.ForeignKey(
Account, on_delete = models.PROTECT,
null = True, blank = True, default = None,
related_name = "+")
canceled_at = models.DateTimeField(
null = True, blank = True, default = None)
class OperationGroup(models.Model):
on_acc = models.ForeignKey(
Account, on_delete = models.PROTECT,
related_name = "operations")
checkout = models.ForeignKey(
Checkout, on_delete = models.PROTECT,
related_name = "operations")
at = models.DateTimeField(auto_now_add = True)
amount = models.IntegerField()
is_cof = models.BooleanField(default = False)
# Optional
comment = models.CharField(
max_length = 255,
blank = True, default = "")
valid_by = models.ForeignKey(
Account, on_delete = models.PROTECT,
related_name = "+",
blank = True, null = True, default = True)
class Operation(models.Model):
PURCHASE = 'purchase'
DEPOSIT = 'deposit'
WITHDRAW = 'withdraw'
TYPE_ORDER_CHOICES = (
(PURCHASE, 'Achat'),
(DEPOSIT, 'Charge'),
(WITHDRAW, 'Retrait'),
)
group = models.ForeignKey(
OperationGroup, on_delete = models.PROTECT,
related_name = "+")
type = models.CharField(
choices = TYPE_ORDER_CHOICES,
max_length = choices_length(TYPE_ORDER_CHOICES))
amount = models.DecimalField(max_digits = 6, decimal_places = 2)
on_checkout = models.BooleanField(default = True)
# Optional
article = models.ForeignKey(
Article, on_delete = models.PROTECT,
related_name = "operations",
blank = True, null = True, default = None)
canceled_by = models.ForeignKey(
Account, on_delete = models.PROTECT,
related_name = "+",
blank = True, null = True, default = None)
canceled_at = models.DateTimeField(
blank = True, null = True, default = None)
addcost_for = models.ForeignKey(
Account, on_delete = models.PROTECT,
related_name = "addcosts",
blank = True, null = True, default = None)
addcost_amount = models.DecimalField(max_digits = 6, decimal_places = 2)