from django.db import models from django.utils.html import format_html from django.contrib.postgres.fields import HStoreField, ArrayField from taggit.managers import TaggableManager from django.contrib.auth.models import User from django.db.models.signals import post_save from django.dispatch import receiver from mptt.models import MPTTModel, TreeForeignKey, TreeManyToManyField from djrichtextfield.models import RichTextField from django_editorjs_fields import EditorJsJSONField # Django >= 3.1 from django_editorjs_fields import EditorJsTextField from filebrowser.fields import FileBrowseField import qrcode import base64 import uuid from django.conf import settings from django_google_maps.fields import AddressField, GeoLocationField from phonenumber_field.modelfields import PhoneNumberField # Create your models here. PROCESS = "process" STATUS_CHOICES = [ ('process', 'Process'), ('fn', 'Finished'), ('purchase', 'Purchase') ] GENDER_CHOICES = [ ('na', 'N/A'), ('lgbt', 'LGBT'), ('male', 'Male'), ('female', 'Female'), ] MENU_GROUP_CHOICES = [ ('primary', 'Primary'), ('footer', 'Footer'), ('secondary', 'Secondary'), ] class Profile(models.Model): STORE_OWNER = 1 CHEF = 2 EMPLOYEE = 3 ROLE_CHOICES = ( (STORE_OWNER, 'Store Owner'), (CHEF, 'Chef'), (EMPLOYEE, 'Employee'), ) user = models.OneToOneField(User, on_delete=models.CASCADE) location = models.CharField(max_length=30, blank=True) birthdate = models.DateField(null=True, blank=True) role = models.PositiveSmallIntegerField(choices=ROLE_CHOICES, null=True, blank=True) store = models.ForeignKey('Store', on_delete=models.CASCADE, null=True, blank=False) def __str__(self): # __unicode__ for Python 2 return self.user.username @receiver(post_save, sender=User) def create_or_update_user_profile(sender, instance, created, **kwargs): if created: Profile.objects.create(user=instance) else: try: instance.profile.save() except: Profile.objects.create(user=instance) class GeneralField(models.Model): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) owner = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True) class Meta: abstract = True class ProcesslField(models.Model): inProcess = models.CharField(max_length=100, blank=True, null=True) status = models.CharField(max_length=100,choices=STATUS_CHOICES,default=PROCESS) class Meta: abstract = True class MenuItem(GeneralField, models.Model): name = models.CharField(max_length=100) tagline = models.TextField(blank=True, null=True) store = models.ForeignKey('Store', on_delete=models.CASCADE) qrCode = models.FileField(blank=True, null=True, upload_to='uploads/%Y/%m/%d/') featureImage = models.ImageField(upload_to='uploads/%Y/%m/%d/', blank=True, null=True) description = models.TextField(blank=True, null=True) ''' photos = ArrayField( models.FileField(upload_to='uploads/%Y/%m/%d/'), size=8,blank=True,null=True) ''' def __str__(self): return self.name def save(self, *args, **kwargs): self.qrCode.name = self.genCode() super(MenuItem, self).save(*args, **kwargs) @property def qrImage(self): if self.qrCode: return format_html('', self.qrCode.url) else: return "-" def genCode(self): img = qrcode.make(f"{self.store.name}#{self.name}#{self.id}") rid = uuid.uuid4().hex path = settings.MEDIA_ROOT+f"/qr/{rid}.png" rpath = f"qr/{rid}.png" img.save(path) return rpath class Ingredient(GeneralField, models.Model): name = models.CharField(max_length=200) qty = models.DecimalField(decimal_places=2, max_digits=5) unit = models.CharField(max_length=10) comment = models.TextField(blank=True, null=True) menu = models.ForeignKey('MenuItem', on_delete=models.CASCADE) class Store(GeneralField, models.Model): name = models.CharField(max_length=100, blank=False, null=False, default="Unititled") addressText = models.TextField(blank=True, null=True) province = models.CharField(max_length=100, blank=True, null=True) storeType = models.CharField("Store Type", max_length=100, blank=True, null=True) qrCode = models.FileField(blank=True, null=True, upload_to='uploads/%Y/%m/%d/') description = models.TextField(blank=True, null=True) address = AddressField(max_length=100, null=True, blank=True) geolocation = GeoLocationField(blank=True, null=True) logo = models.ImageField(blank=True, null=True, upload_to='uploads/%Y/%m/%d/') phone_number = PhoneNumberField(blank=True, null=True) fax_number = PhoneNumberField(blank=True, null=True) lineId = models.CharField(max_length=100, blank=True, null=True) email = models.EmailField(max_length=200, blank=True, null=True) ''' photos = ArrayField( models.FileField(upload_to='uploads/%Y/%m/%d/'), size=8,blank=True,null=True) ''' def __str__(self): return f"{self.name}" def save(self, *args, **kwargs): self.qrCode.name = self.genCode() super(Store, self).save(*args, **kwargs) @property def qrImage(self): if self.qrCode: return format_html('', self.qrCode.url) else: return "-" def genCode(self): img = qrcode.make(f"{self.name}#{self.id}") rid = uuid.uuid4().hex path = settings.MEDIA_ROOT+f"/qr/{rid}.png" rpath = f"qr/{rid}.png" img.save(path) return rpath class Table(GeneralField, models.Model): store = models.ForeignKey('Store', on_delete=models.CASCADE) code = models.CharField(max_length=100, default="N\A") nSeats = models.IntegerField(default=1) occupy = models.BooleanField(default=False) qrCode = models.FileField(blank=True, null=True, upload_to='uploads/%Y/%m/%d/') def __str__(self): return f"{self.code}" def save(self, *args, **kwargs): self.qrCode.name = self.genCode() super(Table, self).save(*args, **kwargs) @property def qrImage(self): if self.qrCode: return format_html('', self.qrCode.url) else: return "-" def genCode(self): img = qrcode.make(f"{self.store.name}#{self.code}") rid = uuid.uuid4().hex path = settings.MEDIA_ROOT+f"/qr/{rid}.png" rpath = f"qr/{rid}.png" img.save(path) return rpath class BookingTable(GeneralField, models.Model): table = models.ForeignKey(Table, on_delete=models.CASCADE) onDate = models.DateField(null=True) onTime = models.TimeField(null=True) note = models.TextField(blank=True, null=True) store = models.ForeignKey('Store', on_delete=models.CASCADE, null=True) qrCode = models.FileField(blank=True, null=True, upload_to='uploads/%Y/%m/%d/') def __str__(self): return f"{self.table}@{self.onDate}({self.note})" def save(self, *args, **kwargs): self.qrCode.name = self.genCode() super(BookingTable, self).save(*args, **kwargs) @property def qrImage(self): if self.qrCode: return format_html('', self.qrCode.url) else: return "-" def genCode(self): img = qrcode.make(f"{self.store.name}#{self.table.code}#{self.onDate}@{self.onTime}") rid = uuid.uuid4().hex path = settings.MEDIA_ROOT+f"/qr/{rid}.png" rpath = f"qr/{rid}.png" img.save(path) return rpath class Order(GeneralField, models.Model): PURCHASE = 'purchase' table = models.ForeignKey(Table, null=True, on_delete=models.SET_NULL) note = models.TextField(blank=True, null=True) store = models.ForeignKey('Store', on_delete=models.SET_NULL, default=None, null=True) #items = models.ManyToManyField(MenuItem) qrCode = models.FileField(blank=True, null=True, upload_to='uploads/%Y/%m/%d/') def save(self, *args, **kwargs): self.qrCode.name = self.genCode() super(Order, self).save(*args, **kwargs) @property def qrImage(self): if self.qrCode: return format_html('', self.qrCode.url) else: return "-" def genCode(self): img = qrcode.make(f"{self.store.name}#{self.table.code}#{self.id}") rid = uuid.uuid4().hex path = settings.MEDIA_ROOT+f"/qr/{rid}.png" rpath = f"qr/{rid}.png" img.save(path) return rpath class OrderItem(GeneralField, models.Model): item = models.ForeignKey(MenuItem, on_delete=models.CASCADE) qty = models.IntegerField(default=1) order = models.ForeignKey(Order, on_delete=models.CASCADE) note = models.TextField(blank=True, null=True) store = models.ForeignKey('Store', on_delete=models.SET_NULL, default=None, null=True) @property def store_items(self): return MenuItem.objects.filter(store = order.store) class StoreFile(GeneralField, models.Model): store = models.ForeignKey('Store', on_delete=models.CASCADE) storeFile = models.FileField(upload_to='uploads/%Y/%m/%d/') tags = TaggableManager(blank=True) class MenuFile(GeneralField, models.Model): menuItem = models.ForeignKey('MenuItem', on_delete=models.CASCADE, null=True) menuFile = models.FileField(upload_to='uploads/%Y/%m/%d/') tags = TaggableManager(blank=True) class Setting(GeneralField, models.Model): store = models.OneToOneField(Store, on_delete=models.CASCADE, primary_key=True) data = HStoreField(blank=True, null=True) note = models.CharField(max_length=200, blank=True, null=True) class UIMenu(GeneralField,MPTTModel, models.Model): name = models.CharField(max_length=200) parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children') group = models.CharField(choices=MENU_GROUP_CHOICES, max_length=200, default='primary') url = models.CharField(max_length=200) icon = models.CharField(max_length=100, blank=True, null=True, default='file') store = models.ForeignKey('Store', on_delete=models.CASCADE, default=None, null=True) nOrder = models.IntegerField(default=1) class MPTTMeta: order_insertion_by = ['-nOrder'] def __str__(self): return f"{self.name}" class PostCategory(MPTTModel, models.Model): name = models.CharField(max_length=200) parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children') class MPTTMeta: order_insertion_by = ['name'] def __str__(self): return f"{self.name}" class Post(GeneralField, models.Model): title = models.CharField(max_length=200) content = RichTextField(blank=True) description = models.TextField(blank=True, null=True) store = models.ForeignKey('Store', on_delete=models.CASCADE, default=None, null=True) category = TreeManyToManyField(PostCategory, blank=True, null=True) featureImage = models.ImageField(upload_to='uploads/%Y/%m/%d/', blank=True, null=True) tags = TaggableManager(blank=True) relateMenus = models.ManyToManyField('MenuItem', blank=True, null=True) #photos = ArrayField(models.ImageField(upload_to='uploads/%Y/%m/%d/'), blank=True, null=True) @property def cats(self): return ",".join([ c.name for c in self.category.all()]) def __str__(self): return f"{self.title}" class PostFile(GeneralField, models.Model): post = models.ForeignKey('Post', on_delete=models.CASCADE) file = models.FileField(upload_to='uploads/%Y/%m/%d/') tags = TaggableManager(blank=True) class Customer(GeneralField, models.Model): fullName = models.CharField(max_length=200) email = models.EmailField(blank=True, null=True) lineId = models.CharField(max_length=100, blank=True, null=True) gender = models.CharField(choices=GENDER_CHOICES, default='na', max_length=40) store = models.ForeignKey('Store', on_delete=models.CASCADE, default=None, null=True) qrCode = models.FileField(blank=True, null=True, upload_to='uploads/%Y/%m/%d/') def save(self, *args, **kwargs): self.qrCode.name = self.genCode() super(Customer, self).save(*args, **kwargs) @property def qrImage(self): if self.qrCode: return format_html('', self.qrCode.url) else: return "-" def genCode(self): img = qrcode.make(f"{self.fullName}#{self.email}#{self.lineId}#{self.store.name}") rid = uuid.uuid4().hex path = settings.MEDIA_ROOT+f"/qr/{rid}.png" rpath = f"qr/{rid}.png" img.save(path) return rpath class Message(GeneralField, MPTTModel, models.Model): subject = models.CharField(max_length=255) email = models.EmailField() lineId = models.CharField(max_length=200, blank=True, null=True) body = models.TextField() reply = models.TextField(blank=True, null=True) store = models.ForeignKey("Store", on_delete=models.CASCADE) parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children') tel = PhoneNumberField(blank=True, null=True) messageFile = models.FileField(blank=True, null=True, upload_to='uploads/%Y/%m/%d/') def __str__(self): return f"{self.subject} {self.created_at}" class Code(GeneralField, models.Model): store = models.OneToOneField('Store', on_delete=models.CASCADE, default=None, null=True) jsCode = models.TextField(blank=True) cssCode = models.TextField(blank=True) pluginCode = models.TextField(blank=True) # body_default = models.TextField() # body_editorjs = EditorJsJSONField( # plugins=[ # "@editorjs/image", # "@editorjs/header", # "editorjs-github-gist-plugin", # "@editorjs/code@2.6.0", # version allowed :) # "@editorjs/list@latest", # "@editorjs/inline-code", # "@editorjs/table", # '@editorjs/raw', # '@editorjs/embed', # ], # ) # Django >= 3.1 # body_editorjs_text = EditorJsTextField() # image = FileBrowseField("Image", max_length=200, directory="images/", extensions=[".jpg"], blank=True) # document = FileBrowseField("PDF", max_length=200, directory="documents/", extensions=[".pdf",".doc"], blank=True) # code = models.TextField(blank=True)