Sin descripción

models.py 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. from django.db import models
  2. from django.utils.html import format_html
  3. from django.contrib.postgres.fields import HStoreField, ArrayField
  4. from taggit.managers import TaggableManager
  5. from django.contrib.auth.models import User
  6. from django.db.models.signals import post_save
  7. from django.dispatch import receiver
  8. from mptt.models import MPTTModel, TreeForeignKey, TreeManyToManyField
  9. from djrichtextfield.models import RichTextField
  10. from django_editorjs_fields import EditorJsJSONField # Django >= 3.1
  11. from django_editorjs_fields import EditorJsTextField
  12. from filebrowser.fields import FileBrowseField
  13. import qrcode
  14. import base64
  15. import uuid
  16. from django.conf import settings
  17. from django_google_maps.fields import AddressField, GeoLocationField
  18. from phonenumber_field.modelfields import PhoneNumberField
  19. # Create your models here.
  20. PROCESS = "process"
  21. STATUS_CHOICES = [
  22. ('process', 'Process'),
  23. ('fn', 'Finished'),
  24. ('purchase', 'Purchase')
  25. ]
  26. GENDER_CHOICES = [
  27. ('na', 'N/A'),
  28. ('lgbt', 'LGBT'),
  29. ('male', 'Male'),
  30. ('female', 'Female'),
  31. ]
  32. MENU_GROUP_CHOICES = [
  33. ('primary', 'Primary'),
  34. ('footer', 'Footer'),
  35. ('secondary', 'Secondary'),
  36. ]
  37. class Profile(models.Model):
  38. STORE_OWNER = 1
  39. CHEF = 2
  40. EMPLOYEE = 3
  41. ROLE_CHOICES = (
  42. (STORE_OWNER, 'Store Owner'),
  43. (CHEF, 'Chef'),
  44. (EMPLOYEE, 'Employee'),
  45. )
  46. user = models.OneToOneField(User, on_delete=models.CASCADE)
  47. location = models.CharField(max_length=30, blank=True)
  48. birthdate = models.DateField(null=True, blank=True)
  49. role = models.PositiveSmallIntegerField(choices=ROLE_CHOICES, null=True, blank=True)
  50. store = models.ForeignKey('Store', on_delete=models.CASCADE, null=True, blank=False)
  51. def __str__(self): # __unicode__ for Python 2
  52. return self.user.username
  53. @receiver(post_save, sender=User)
  54. def create_or_update_user_profile(sender, instance, created, **kwargs):
  55. if created:
  56. Profile.objects.create(user=instance)
  57. else:
  58. try:
  59. instance.profile.save()
  60. except:
  61. Profile.objects.create(user=instance)
  62. class GeneralField(models.Model):
  63. created_at = models.DateTimeField(auto_now_add=True)
  64. updated_at = models.DateTimeField(auto_now=True)
  65. owner = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
  66. class Meta:
  67. abstract = True
  68. class ProcesslField(models.Model):
  69. inProcess = models.CharField(max_length=100, blank=True, null=True)
  70. status = models.CharField(max_length=100,choices=STATUS_CHOICES,default=PROCESS)
  71. class Meta:
  72. abstract = True
  73. class MenuItem(GeneralField, models.Model):
  74. name = models.CharField(max_length=100)
  75. tagline = models.TextField(blank=True, null=True)
  76. store = models.ForeignKey('Store', on_delete=models.CASCADE)
  77. qrCode = models.FileField(blank=True, null=True, upload_to='uploads/%Y/%m/%d/')
  78. featureImage = models.ImageField(upload_to='uploads/%Y/%m/%d/', blank=True, null=True)
  79. description = models.TextField(blank=True, null=True)
  80. '''
  81. photos = ArrayField(
  82. models.FileField(upload_to='uploads/%Y/%m/%d/'),
  83. size=8,blank=True,null=True)
  84. '''
  85. def __str__(self):
  86. return self.name
  87. def save(self, *args, **kwargs):
  88. self.qrCode.name = self.genCode()
  89. super(MenuItem, self).save(*args, **kwargs)
  90. @property
  91. def qrImage(self):
  92. if self.qrCode:
  93. return format_html('<img src="{}" width="100%">', self.qrCode.url)
  94. else:
  95. return "-"
  96. def genCode(self):
  97. img = qrcode.make(f"{self.store.name}#{self.name}#{self.id}")
  98. rid = uuid.uuid4().hex
  99. path = settings.MEDIA_ROOT+f"/qr/{rid}.png"
  100. rpath = f"qr/{rid}.png"
  101. img.save(path)
  102. return rpath
  103. class Ingredient(GeneralField, models.Model):
  104. name = models.CharField(max_length=200)
  105. qty = models.DecimalField(decimal_places=2, max_digits=5)
  106. unit = models.CharField(max_length=10)
  107. comment = models.TextField(blank=True, null=True)
  108. menu = models.ForeignKey('MenuItem', on_delete=models.CASCADE)
  109. class Store(GeneralField, models.Model):
  110. name = models.CharField(max_length=100, blank=False, null=False, default="Unititled")
  111. addressText = models.TextField(blank=True, null=True)
  112. province = models.CharField(max_length=100, blank=True, null=True)
  113. storeType = models.CharField("Store Type", max_length=100, blank=True, null=True)
  114. qrCode = models.FileField(blank=True, null=True, upload_to='uploads/%Y/%m/%d/')
  115. description = models.TextField(blank=True, null=True)
  116. address = AddressField(max_length=100, null=True, blank=True)
  117. geolocation = GeoLocationField(blank=True, null=True)
  118. logo = models.ImageField(blank=True, null=True, upload_to='uploads/%Y/%m/%d/')
  119. phone_number = PhoneNumberField(blank=True, null=True)
  120. fax_number = PhoneNumberField(blank=True, null=True)
  121. lineId = models.CharField(max_length=100, blank=True, null=True)
  122. email = models.EmailField(max_length=200, blank=True, null=True)
  123. '''
  124. photos = ArrayField(
  125. models.FileField(upload_to='uploads/%Y/%m/%d/'),
  126. size=8,blank=True,null=True)
  127. '''
  128. def __str__(self):
  129. return f"{self.name}"
  130. def save(self, *args, **kwargs):
  131. self.qrCode.name = self.genCode()
  132. super(Store, self).save(*args, **kwargs)
  133. @property
  134. def qrImage(self):
  135. if self.qrCode:
  136. return format_html('<img src="{}" width="100%">', self.qrCode.url)
  137. else:
  138. return "-"
  139. def genCode(self):
  140. img = qrcode.make(f"{self.name}#{self.id}")
  141. rid = uuid.uuid4().hex
  142. path = settings.MEDIA_ROOT+f"/qr/{rid}.png"
  143. rpath = f"qr/{rid}.png"
  144. img.save(path)
  145. return rpath
  146. class Table(GeneralField, models.Model):
  147. store = models.ForeignKey('Store', on_delete=models.CASCADE)
  148. code = models.CharField(max_length=100, default="N\A")
  149. nSeats = models.IntegerField(default=1)
  150. occupy = models.BooleanField(default=False)
  151. qrCode = models.FileField(blank=True, null=True, upload_to='uploads/%Y/%m/%d/')
  152. def __str__(self):
  153. return f"{self.code}"
  154. def save(self, *args, **kwargs):
  155. self.qrCode.name = self.genCode()
  156. super(Table, self).save(*args, **kwargs)
  157. @property
  158. def qrImage(self):
  159. if self.qrCode:
  160. return format_html('<img src="{}" width="100%">', self.qrCode.url)
  161. else:
  162. return "-"
  163. def genCode(self):
  164. img = qrcode.make(f"{self.store.name}#{self.code}")
  165. rid = uuid.uuid4().hex
  166. path = settings.MEDIA_ROOT+f"/qr/{rid}.png"
  167. rpath = f"qr/{rid}.png"
  168. img.save(path)
  169. return rpath
  170. class BookingTable(GeneralField, models.Model):
  171. table = models.ForeignKey(Table, on_delete=models.CASCADE)
  172. onDate = models.DateField(null=True)
  173. onTime = models.TimeField(null=True)
  174. note = models.TextField(blank=True, null=True)
  175. store = models.ForeignKey('Store', on_delete=models.CASCADE, null=True)
  176. qrCode = models.FileField(blank=True, null=True, upload_to='uploads/%Y/%m/%d/')
  177. def __str__(self):
  178. return f"{self.table}@{self.onDate}({self.note})"
  179. def save(self, *args, **kwargs):
  180. self.qrCode.name = self.genCode()
  181. super(BookingTable, self).save(*args, **kwargs)
  182. @property
  183. def qrImage(self):
  184. if self.qrCode:
  185. return format_html('<img src="{}" width="100%">', self.qrCode.url)
  186. else:
  187. return "-"
  188. def genCode(self):
  189. img = qrcode.make(f"{self.store.name}#{self.table.code}#{self.onDate}@{self.onTime}")
  190. rid = uuid.uuid4().hex
  191. path = settings.MEDIA_ROOT+f"/qr/{rid}.png"
  192. rpath = f"qr/{rid}.png"
  193. img.save(path)
  194. return rpath
  195. class Order(GeneralField, models.Model):
  196. PURCHASE = 'purchase'
  197. table = models.ForeignKey(Table, null=True, on_delete=models.SET_NULL)
  198. note = models.TextField(blank=True, null=True)
  199. store = models.ForeignKey('Store', on_delete=models.SET_NULL, default=None, null=True)
  200. #items = models.ManyToManyField(MenuItem)
  201. qrCode = models.FileField(blank=True, null=True, upload_to='uploads/%Y/%m/%d/')
  202. def save(self, *args, **kwargs):
  203. self.qrCode.name = self.genCode()
  204. super(Order, self).save(*args, **kwargs)
  205. @property
  206. def qrImage(self):
  207. if self.qrCode:
  208. return format_html('<img src="{}" width="100%">', self.qrCode.url)
  209. else:
  210. return "-"
  211. def genCode(self):
  212. img = qrcode.make(f"{self.store.name}#{self.table.code}#{self.id}")
  213. rid = uuid.uuid4().hex
  214. path = settings.MEDIA_ROOT+f"/qr/{rid}.png"
  215. rpath = f"qr/{rid}.png"
  216. img.save(path)
  217. return rpath
  218. class OrderItem(GeneralField, models.Model):
  219. item = models.ForeignKey(MenuItem, on_delete=models.CASCADE)
  220. qty = models.IntegerField(default=1)
  221. order = models.ForeignKey(Order, on_delete=models.CASCADE)
  222. note = models.TextField(blank=True, null=True)
  223. store = models.ForeignKey('Store', on_delete=models.SET_NULL, default=None, null=True)
  224. @property
  225. def store_items(self):
  226. return MenuItem.objects.filter(store = order.store)
  227. class StoreFile(GeneralField, models.Model):
  228. store = models.ForeignKey('Store', on_delete=models.CASCADE)
  229. storeFile = models.FileField(upload_to='uploads/%Y/%m/%d/')
  230. tags = TaggableManager(blank=True)
  231. class MenuFile(GeneralField, models.Model):
  232. menuItem = models.ForeignKey('MenuItem', on_delete=models.CASCADE, null=True)
  233. menuFile = models.FileField(upload_to='uploads/%Y/%m/%d/')
  234. tags = TaggableManager(blank=True)
  235. class Setting(GeneralField, models.Model):
  236. store = models.OneToOneField(Store, on_delete=models.CASCADE, primary_key=True)
  237. data = HStoreField(blank=True, null=True)
  238. note = models.CharField(max_length=200, blank=True, null=True)
  239. class UIMenu(GeneralField,MPTTModel, models.Model):
  240. name = models.CharField(max_length=200)
  241. parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')
  242. group = models.CharField(choices=MENU_GROUP_CHOICES, max_length=200, default='primary')
  243. url = models.CharField(max_length=200)
  244. icon = models.CharField(max_length=100, blank=True, null=True, default='file')
  245. store = models.ForeignKey('Store', on_delete=models.CASCADE, default=None, null=True)
  246. nOrder = models.IntegerField(default=1)
  247. class MPTTMeta:
  248. order_insertion_by = ['-nOrder']
  249. def __str__(self):
  250. return f"{self.name}"
  251. class PostCategory(MPTTModel, models.Model):
  252. name = models.CharField(max_length=200)
  253. parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')
  254. class MPTTMeta:
  255. order_insertion_by = ['name']
  256. def __str__(self):
  257. return f"{self.name}"
  258. class Post(GeneralField, models.Model):
  259. title = models.CharField(max_length=200)
  260. content = RichTextField(blank=True)
  261. description = models.TextField(blank=True, null=True)
  262. store = models.ForeignKey('Store', on_delete=models.CASCADE, default=None, null=True)
  263. category = TreeManyToManyField(PostCategory, blank=True, null=True)
  264. featureImage = models.ImageField(upload_to='uploads/%Y/%m/%d/', blank=True, null=True)
  265. tags = TaggableManager(blank=True)
  266. relateMenus = models.ManyToManyField('MenuItem', blank=True, null=True)
  267. #photos = ArrayField(models.ImageField(upload_to='uploads/%Y/%m/%d/'), blank=True, null=True)
  268. @property
  269. def cats(self):
  270. return ",".join([ c.name for c in self.category.all()])
  271. def __str__(self):
  272. return f"{self.title}"
  273. class PostFile(GeneralField, models.Model):
  274. post = models.ForeignKey('Post', on_delete=models.CASCADE)
  275. file = models.FileField(upload_to='uploads/%Y/%m/%d/')
  276. tags = TaggableManager(blank=True)
  277. class Customer(GeneralField, models.Model):
  278. fullName = models.CharField(max_length=200)
  279. email = models.EmailField(blank=True, null=True)
  280. lineId = models.CharField(max_length=100, blank=True, null=True)
  281. gender = models.CharField(choices=GENDER_CHOICES, default='na', max_length=40)
  282. store = models.ForeignKey('Store', on_delete=models.CASCADE, default=None, null=True)
  283. qrCode = models.FileField(blank=True, null=True, upload_to='uploads/%Y/%m/%d/')
  284. def save(self, *args, **kwargs):
  285. self.qrCode.name = self.genCode()
  286. super(Customer, self).save(*args, **kwargs)
  287. @property
  288. def qrImage(self):
  289. if self.qrCode:
  290. return format_html('<img src="{}" width="100%">', self.qrCode.url)
  291. else:
  292. return "-"
  293. def genCode(self):
  294. img = qrcode.make(f"{self.fullName}#{self.email}#{self.lineId}#{self.store.name}")
  295. rid = uuid.uuid4().hex
  296. path = settings.MEDIA_ROOT+f"/qr/{rid}.png"
  297. rpath = f"qr/{rid}.png"
  298. img.save(path)
  299. return rpath
  300. class Message(GeneralField, MPTTModel, models.Model):
  301. subject = models.CharField(max_length=255)
  302. email = models.EmailField()
  303. lineId = models.CharField(max_length=200, blank=True, null=True)
  304. body = models.TextField()
  305. reply = models.TextField(blank=True, null=True)
  306. store = models.ForeignKey("Store", on_delete=models.CASCADE)
  307. parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')
  308. tel = PhoneNumberField(blank=True, null=True)
  309. messageFile = models.FileField(blank=True, null=True, upload_to='uploads/%Y/%m/%d/')
  310. def __str__(self):
  311. return f"{self.subject} {self.created_at}"
  312. class Code(GeneralField, models.Model):
  313. store = models.OneToOneField('Store', on_delete=models.CASCADE, default=None, null=True)
  314. jsCode = models.TextField(blank=True)
  315. cssCode = models.TextField(blank=True)
  316. pluginCode = models.TextField(blank=True)
  317. # body_default = models.TextField()
  318. # body_editorjs = EditorJsJSONField(
  319. # plugins=[
  320. # "@editorjs/image",
  321. # "@editorjs/header",
  322. # "editorjs-github-gist-plugin",
  323. # "@editorjs/code@2.6.0", # version allowed :)
  324. # "@editorjs/list@latest",
  325. # "@editorjs/inline-code",
  326. # "@editorjs/table",
  327. # '@editorjs/raw',
  328. # '@editorjs/embed',
  329. # ],
  330. # ) # Django >= 3.1
  331. # body_editorjs_text = EditorJsTextField()
  332. # image = FileBrowseField("Image", max_length=200, directory="images/", extensions=[".jpg"], blank=True)
  333. # document = FileBrowseField("PDF", max_length=200, directory="documents/", extensions=[".pdf",".doc"], blank=True)
  334. # code = models.TextField(blank=True)