from django.db import models
from django.contrib.auth.models import AbstractUser
from django.core.validators import MaxValueValidator, MinValueValidator,FileExtensionValidator
from django.core.exceptions import ValidationError
from django.dispatch import receiver
from django.db.models.signals import (post_save)
from django.core.mail import send_mail
from django.contrib import messages
from django.utils.timezone import localtime, now
import datetime
from datetime import datetime, timedelta,date
#import magic
""" Core Models for Cellar Management System """
ext_validator = FileExtensionValidator(['png','jpg','pdf'])
#def validate_file_mimetype(file):
# accept=['image/png','image/jpeg','application/pdf']
# file_mime_type = magic.from_buffer(file.read(1024),mime=True)
# print(file_mime_type)
# if file_mime_type not in accept:
# raise ValidationError("Unsupported Filetype")
[docs]
class Account (models.Model):
""" Account is the top level object in the system.
It is used to group users and data and enables Cellar Management to be used by multiple users"""
account = models.CharField(max_length=30, default='')
class Meta:
ordering = ["account"]
def __str__(self):
return self.account
[docs]
class User(AbstractUser):
ROLES = [
('G', 'Guest'),
('M', 'Member'),
('O', 'Owner'), #Account Owner
('A', 'Admin'),
]
username = models.CharField(max_length=25,unique=True)
role = models.CharField(max_length=1,
choices=ROLES,
blank=False,
default='G')
email = models.EmailField('email',blank=False)
account = models.CharField(max_length=30, default='Guest')
[docs]
class Country (models.Model):
country = models.CharField(max_length=30, default='')
class Meta:
ordering = ["country"]
def __str__(self):
return self.country
[docs]
class Region(models.Model):
country = models.ForeignKey(Country,on_delete=models.CASCADE)
region = models.CharField(max_length = 64,unique=True)
def __str__(self):
return f"{self.country}:{self.region}"
[docs]
class SubRegion(models.Model):
region = models.ForeignKey(Region,on_delete=models.CASCADE)
subregion = models.CharField(max_length = 64,unique=True)
def __str__(self):
return f"{self.region}:{self.subregion}"
[docs]
class Style(models.Model):
name=models.CharField(max_length=40)
class Meta:
ordering = ["id"]
def __str__(self):
return self.name
[docs]
class Bottle(models.Model):
size=models.CharField(max_length=40)
cl = models.DecimalField(max_digits=5,decimal_places=2)
def __str__(self):
return self.size
[docs]
class ShipUnit(models.Model):
ship_unit=models.CharField(max_length=40)
qty=models.IntegerField()
def __str__(self):
return self.ship_unit
[docs]
class LocationType (models.Model):
location_type=models.CharField(max_length=50)
location_max_qty = models.IntegerField(default='1',null=False)
location_note=models.CharField(max_length=100,default='',null=True)
def __str__(self):
return self.location_type
[docs]
class Addition (models.Model):
ORDERED = 'Ordered'
RECEIVED = 'Received'
PART_ALLOCATED = 'Part Allocated'
PUT_AWAY = 'Put Away'
DRUNK = 'Drunk'
TRIED = 'Tried'
STATUSES = (
(ORDERED, 'Ordered'),
(RECEIVED,'Received'),
(PART_ALLOCATED,'Part Allocated'),
(PUT_AWAY,'Put Away'),
(TRIED,'Tried'),
(DRUNK,'Drunk'),
)
name = models.CharField(max_length=(75),default='')
style = models.ForeignKey(Style,on_delete=models.CASCADE)
country = models.ForeignKey(Country,on_delete=models.CASCADE)
year = models.CharField(max_length=(4),default='-')
size = models.ForeignKey(Bottle,on_delete=models.CASCADE)
price = models.DecimalField(max_digits=5,decimal_places=2,default='.00',null=True,blank=True,help_text='Price for the Ship Qty i.e. case')
abv = models.DecimalField(max_digits=5,decimal_places=2,default='.00',blank=True,null=True)
source = models.CharField(max_length=(50),blank=True,null=True)
duty = models.DecimalField(max_digits=5,decimal_places=2,default='.00',null=True,)
vat = models.BooleanField(default=True)
quantity = models.PositiveIntegerField()
delivery_qty = models.PositiveIntegerField()
delivery_unit = models.ForeignKey(ShipUnit,related_name='Del_Unit',on_delete=models.CASCADE)
order_ref = models.CharField(max_length=(50),null=True,default='',blank=True)
ship_costs = models.DecimalField(max_digits=5,decimal_places=2,default='.00',null=True,blank=True)
expected_delivery = models.DateField(blank=True)
addition_status =models.CharField(max_length=(14),choices=STATUSES,default='Ordered')
allocation_qty = models.PositiveIntegerField(default='0',blank=True)
wine_location = models.ManyToManyField('Location',blank=True)
account=models.ForeignKey(Account,default='1',on_delete=models.CASCADE)
@property
def pending_allocation(self):
if self.addition_status != 'Put Away':
return self.quantity - self.allocation_qty
else:
return 0
def __str__(self):
return self.name
[docs]
class Location (models.Model):
type = models.ForeignKey(LocationType,on_delete=models.CASCADE)
name = models.CharField(max_length=20,default='',null=False)
location_qty = models.IntegerField(default='0',null=False)
account=models.ForeignKey(Account,default='1',on_delete=models.CASCADE)
def __str__(self):
return f"{self.name}"
class Meta:
ordering = ["type","name"]
[docs]
class Image(models.Model):
name = models.CharField(max_length = 64)
image = models.ImageField(upload_to='images/')
account=models.ForeignKey(Account,default='1',on_delete=models.CASCADE)
def __str__(self):
return self.name
[docs]
class WineLocationValues(models.Model):
wine = models.ForeignKey(Addition,on_delete=models.CASCADE)
location = models.ForeignKey(Location,on_delete=models.CASCADE)
quantity = models.IntegerField(default='0',null=False)
style = models.ForeignKey(Style,on_delete=models.CASCADE)
location_type=models.CharField(max_length=50,default='')
vintage = models.CharField(max_length=(4),default='')
country = models.CharField(max_length=30, default='')
size=models.CharField(max_length=40)
price = models.DecimalField(max_digits=5,decimal_places=2,default='0.00',null=True,blank=True,help_text='Price per bottle - inc all costs')
account=models.ForeignKey(Account,default='1',on_delete=models.CASCADE)
def __str__(self):
return f"ID {self.pk} : {self.wine} - {self.location} - {self.quantity}"
[docs]
class DataLoads(models.Model):
name = models.CharField(max_length = 64,unique=True)
excel = models.FileField(upload_to='dataloads/')
date_created = models.DateField(auto_now_add=True)
account=models.ForeignKey(Account,default='1',on_delete=models.CASCADE)
def __str__(self):
return self.name
[docs]
class CellarReady(models.Model):
status = models.CharField(max_length=30)
def __str__(self):
return self.status