models.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. # coding=utf-8
  2. from django.db import models
  3. from django.db.models import Sum
  4. from django.utils import timezone
  5. from django.conf import settings
  6. from apps.account.models import User, Department
  7. from apps.exceptions import CustomError
  8. from apps.goods.models import Goods
  9. from apps.product.models import ProductBase
  10. from apps.warehouse.models import Warehouse, WarehouseStock, WarehouseRecord, WarehouseStockRecord
  11. class Material(models.Model):
  12. NONE = 0
  13. LOWER = 1
  14. UPPER = 2
  15. SUGGEST_CHOICES = (
  16. (NONE, u'不开启'),
  17. (LOWER, u'按库存下限预警'),
  18. (UPPER, u'按库存上限预警'),
  19. )
  20. product_base = models.ForeignKey(ProductBase, verbose_name=u"产品", on_delete=models.PROTECT, blank=True)
  21. htc_identification = models.CharField(max_length=100, verbose_name=u"产品标识", null=True, blank=True)
  22. stock_upper_limit = models.BigIntegerField(verbose_name=u"库存上限", null=True, blank=True)
  23. stock_lower_limit = models.BigIntegerField(verbose_name=u"库存下限", null=True, blank=True)
  24. purchase_suggest = models.PositiveSmallIntegerField(choices=SUGGEST_CHOICES, verbose_name=u"库存预警", default=NONE)
  25. class Meta:
  26. db_table = "material"
  27. verbose_name = u"原料产品管理"
  28. ordering = ('-id',)
  29. default_permissions = ()
  30. permissions = (
  31. ("view_material", u"浏览"),
  32. ("add_material", u"添加"),
  33. ("delete_material", u"删除"),
  34. ("export_material", u"导出"),
  35. ("import_material", u"导入"),
  36. ("view_material_cost", u"查看成本"),
  37. )
  38. @staticmethod
  39. def getById(id):
  40. instance = Material.objects.filter(pk=id).first()
  41. if not instance:
  42. raise CustomError(u'未找到相应的原料')
  43. return instance
  44. @staticmethod
  45. def getPurchaseSuggest():
  46. purchasesuggest = {
  47. u'不开启' : 0,
  48. u'按库存下限预警': 1,
  49. u'按库存上限预警': 2
  50. }
  51. return purchasesuggest
  52. @staticmethod
  53. def getPurchaseSuggestValue(value):
  54. purchasesuggest = Material.getPurchaseSuggest()
  55. try:
  56. purchase_suggest = purchasesuggest[value]
  57. except:
  58. raise CustomError(u'库存预警填写不正确')
  59. return purchase_suggest
  60. class Consumable(models.Model):
  61. product_base = models.ForeignKey(ProductBase, verbose_name=u"产品", on_delete=models.PROTECT, blank=True)
  62. stock_upper_limit = models.BigIntegerField(verbose_name=u"库存上限", null=True, blank=True)
  63. stock_lower_limit = models.BigIntegerField(verbose_name=u"库存下限", null=True, blank=True)
  64. purchase_suggest = models.PositiveSmallIntegerField(choices=Material.SUGGEST_CHOICES, verbose_name=u"库存预警", default=Material.NONE)
  65. class Meta:
  66. db_table = "consumable"
  67. verbose_name = u"耗材产品管理"
  68. ordering = ('-id',)
  69. default_permissions = ()
  70. permissions = (
  71. ("view_consumable", u"浏览"),
  72. ("add_consumable", u"添加"),
  73. ("delete_consumable", u"删除"),
  74. ("export_consumable", u"导出"),
  75. ("import_consumable", u"导入"),
  76. ("view_consumable_cost", u"查看成本"),
  77. )
  78. @staticmethod
  79. def getById(id):
  80. instance = Consumable.objects.filter(pk=id).first()
  81. if not instance:
  82. raise CustomError(u'未找到相应的耗材')
  83. return instance
  84. class Deliver(models.Model):
  85. MATERIAL = 0
  86. CONSUMABLE = 1
  87. PRODUCT_CHOICES = (
  88. (MATERIAL, u'原料'),
  89. (CONSUMABLE, u'耗材'),
  90. )
  91. PREFIX_CHOICES = (
  92. (MATERIAL, 'CM'),
  93. (CONSUMABLE, 'CC')
  94. )
  95. no = models.CharField(max_length=20, verbose_name=u"出库单号", editable=False)
  96. product_type = models.PositiveSmallIntegerField(choices=PRODUCT_CHOICES, verbose_name=u"产品类型")
  97. create_time = models.DateTimeField(verbose_name=u"创建时间", default=timezone.now)
  98. create_user = models.ForeignKey(User, verbose_name=u"创建人", related_name='deliver_ref_create_user', on_delete=models.PROTECT, blank=True, editable=False)
  99. department = models.ForeignKey(Department, verbose_name=u"创建部门", related_name='deliver_ref_department', on_delete=models.PROTECT, blank=True, editable=False)
  100. receiver = models.ForeignKey(User, verbose_name=u"领用人", related_name='deliver_ref_receiver',on_delete=models.PROTECT)
  101. receiver_department = models.ForeignKey(Department, verbose_name=u"领用车间", related_name='deliver_ref_receiver_department',
  102. on_delete=models.PROTECT, blank=True, editable=False)
  103. status = models.PositiveSmallIntegerField(choices=settings.CHECK_STATUS_CHOICES, verbose_name=u"审核状态", default=settings.DEFAULT)
  104. check_user = models.ForeignKey(User, related_name='deliver_ref_check_user', verbose_name=u"审核人", on_delete=models.PROTECT, blank=True, null=True)
  105. check_time = models.DateTimeField(verbose_name=u"审核时间", blank=True, null=True)
  106. warehouse = models.ForeignKey(Warehouse, verbose_name=u'仓别', on_delete=models.PROTECT)
  107. notes = models.CharField(max_length=200, verbose_name=u"备注", blank=True, null=True)
  108. goods = models.ForeignKey(Goods, verbose_name=u'成品', on_delete=models.PROTECT, blank=True, null=True)
  109. total_count = models.BigIntegerField(verbose_name=u'合计数量', default=0)
  110. total_cost = models.BigIntegerField(verbose_name=u'合计成本', default=0)
  111. return_count = models.BigIntegerField(verbose_name=u"合计退料数量", default=0)
  112. return_cost = models.BigIntegerField(verbose_name=u"合计退料成本", default=0)
  113. class Meta:
  114. db_table = "deliver"
  115. verbose_name = u"出库管理"
  116. ordering = ('-id',)
  117. index_together = (
  118. 'create_time', 'check_time', 'status'
  119. )
  120. unique_together = (
  121. 'no',
  122. )
  123. default_permissions = ()
  124. permissions = (
  125. ("view_material_deliver", u"浏览"),
  126. ("add_material_deliver", u"添加"),
  127. ("check_material_deliver", u"审核"),
  128. ("delete_material_deliver", u"删除"),
  129. ("export_material_deliver", u"导出"),
  130. ("print_material_deliver", u"打印"),
  131. )
  132. def getPermission(self, action):
  133. permissions = Deliver.getPermissionMap()
  134. return permissions[self.product_type][action]
  135. @staticmethod
  136. def getById(id):
  137. instances = Deliver.objects.filter(id=id).first()
  138. if not instances:
  139. raise CustomError(u'未找到相应的出库单')
  140. return instances
  141. @staticmethod
  142. def getPermissionByType(type, action):
  143. permissions = Deliver.getPermissionMap()
  144. type = Deliver.getValidType(type)
  145. return permissions[type][action]
  146. @staticmethod
  147. def getPermissionMap():
  148. permissions = {
  149. Deliver.MATERIAL: {'view': 'material.view_material_deliver',
  150. 'add': 'material.add_material_deliver',
  151. 'check': 'material.check_material_deliver',
  152. 'delete': 'material.delete_material_deliver',
  153. 'export': 'material.export_material_deliver',
  154. 'import': 'material.import_material_deliver',
  155. 'print': 'material.print_material_deliver'
  156. },
  157. Deliver.CONSUMABLE: {'view': 'material.view_consumable_deliver',
  158. 'add': 'material.add_consumable_deliver',
  159. 'check': 'material.check_consumable_deliver',
  160. 'delete': 'material.delete_consumable_deliver',
  161. 'export': 'material.export_consumable_deliver',
  162. 'import': 'material.import_consumable_deliver',
  163. 'print': 'material.print_consumable_deliver'
  164. },
  165. }
  166. return permissions
  167. @staticmethod
  168. def getValidType(type):
  169. try:
  170. type = int(type)
  171. except:
  172. raise CustomError(u'错误的出库类型')
  173. types = (r[0] for r in Deliver.PRODUCT_CHOICES)
  174. if type not in types:
  175. raise CustomError(u'无效的出库类型')
  176. return type
  177. def save(self, *args, **kwargs):
  178. if self.no == None or self.no == '':
  179. now = timezone.now()
  180. rows = Deliver.objects.filter(create_time__gte=now.strftime('%Y-%m-%d')).order_by('-no')
  181. count = rows.count()
  182. prefix = self.PREFIX_CHOICES[self.product_type][1]
  183. if count == 0:
  184. self.no = '%s%s%03d' % (prefix, now.strftime('%Y%m%d'), count + 1)
  185. else:
  186. self.no = rows[0].no[:2] + str(int(rows[0].no[2:]) + 1)
  187. super(Deliver, self).save(*args, **kwargs)
  188. def update_total(self):
  189. total_count = 0
  190. total_cost = 0
  191. sum_row = DeliverDetail.objects.filter(main=self).aggregate(total_count=Sum('count'), total_cost=Sum('total_cost'))
  192. if sum_row:
  193. total_count = sum_row['total_count'] or 0
  194. total_cost = sum_row['total_cost'] or 0
  195. self.total_count = total_count
  196. self.total_cost = total_cost
  197. self.save()
  198. def update_return(self):
  199. return_count = 0
  200. return_cost = 0
  201. sum_row = DeliverDetail.objects.filter(main=self).aggregate(return_count=Sum('return_count'),
  202. return_cost=Sum('return_cost'))
  203. if sum_row:
  204. return_count = sum_row['return_count'] or 0
  205. return_cost = sum_row['return_cost'] or 0
  206. self.return_count = return_count
  207. self.return_cost = return_cost
  208. self.save()
  209. class DeliverDetail(models.Model):
  210. main = models.ForeignKey(Deliver, verbose_name=u'出库单', on_delete=models.PROTECT, related_name='deliver_details')
  211. product_base = models.ForeignKey(ProductBase, verbose_name=u'产品', on_delete=models.PROTECT)
  212. count = models.BigIntegerField(verbose_name=u'数量', default=0)
  213. warehouse_stock = models.ForeignKey(WarehouseStock, verbose_name=u'仓别库存', on_delete=models.PROTECT, editable=False)
  214. warehouse_record = models.ForeignKey(WarehouseRecord, verbose_name=u'库存记录', on_delete=models.PROTECT, null=True,blank=True, related_name='deliver_detail_ref_warehouse_record')
  215. warehouse_stockrecord = models.ForeignKey(WarehouseStockRecord, verbose_name=u'入库库存记录', on_delete=models.PROTECT, null=True,blank=True, related_name='deliver_detail_ref_warehouse_stock_record')
  216. total_cost = models.BigIntegerField(verbose_name=u'成本合计', default=0)
  217. return_count = models.BigIntegerField(verbose_name=u'退料数量',default=0)
  218. return_cost = models.BigIntegerField(verbose_name=u'退料成本合计', default=0)
  219. notes = models.CharField(max_length=200, verbose_name=u"备注", blank=True, null=True)
  220. class Meta:
  221. db_table = "deliver_detail"
  222. verbose_name = u"出库管理"
  223. ordering = ('-id',)
  224. default_permissions = ()
  225. permissions = (
  226. ("view_consumable_deliver", u"浏览"),
  227. ("add_consumable_deliver", u"添加"),
  228. ("check_consumable_deliver", u"审核"),
  229. ("delete_consumable_deliver", u"删除"),
  230. ("export_consumable_deliver", u"导出"),
  231. ("print_consumable_deliver", u"打印"),
  232. )
  233. def updateReturn(self):
  234. return_count = 0
  235. return_cost = 0
  236. sum_row = DeliverReturnDetail.objects.filter(deliver_detail=self).aggregate(return_count=Sum('return_count'),
  237. return_cost=Sum('return_cost'))
  238. if sum_row:
  239. return_count = sum_row['return_count'] or 0
  240. return_cost = sum_row['return_cost'] or 0
  241. self.return_count = return_count
  242. self.return_cost = return_cost
  243. self.save()
  244. class DeliverReturn(models.Model):
  245. PREFIX_CHOICES = (
  246. (Deliver.MATERIAL, 'TM'),
  247. (Deliver.CONSUMABLE, 'TC')
  248. )
  249. no = models.CharField(max_length=20, verbose_name=u"退料单号", editable=False)
  250. product_type = models.PositiveSmallIntegerField(choices=Deliver.PRODUCT_CHOICES, verbose_name=u"产品类型")
  251. reason = models.CharField(max_length=500, verbose_name=u"原因", editable=False)
  252. create_time = models.DateTimeField(verbose_name=u"创建时间", default=timezone.now)
  253. create_user = models.ForeignKey(User, verbose_name=u"创建人", on_delete=models.PROTECT, blank=True, editable=False)
  254. department = models.ForeignKey(Department, verbose_name=u"创建部门", on_delete=models.PROTECT, blank=True, editable=False)
  255. return_count = models.BigIntegerField(verbose_name=u'退料合计数量', default=0)
  256. return_cost = models.BigIntegerField(verbose_name=u'退料合计成本', default=0)
  257. class Meta:
  258. db_table = "deliver_return"
  259. verbose_name = u"退料管理"
  260. ordering = ('-id',)
  261. index_together = (
  262. 'create_time',
  263. )
  264. unique_together = (
  265. 'no',
  266. )
  267. default_permissions = ()
  268. permissions = (
  269. ("view_material_deliver_return", u"浏览"),
  270. ("add_material_deliver_return", u"添加"),
  271. ("print_material_deliver_return", u"打印"),
  272. )
  273. @staticmethod
  274. def getByIds(ids):
  275. return DeliverReturn.objects.filter(id__in=ids)
  276. def getPermission(self, action):
  277. permissions = DeliverReturn.getPermissionMap()
  278. return permissions[self.product_type][action]
  279. @staticmethod
  280. def getById(id):
  281. instances = DeliverReturn.objects.filter(id=id).first()
  282. if not instances:
  283. raise CustomError(u'未找到相应的退料单')
  284. return instances
  285. @staticmethod
  286. def getPermissionByType(type, action):
  287. permissions = DeliverReturn.getPermissionMap()
  288. type = DeliverReturn.getValidType(type)
  289. return permissions[type][action]
  290. @staticmethod
  291. def getPermissionMap():
  292. permissions = {
  293. Deliver.MATERIAL: {'view': 'material.view_material_deliver_return',
  294. 'add': 'material.add_material_deliver_return',
  295. 'print': 'material.print_material_deliver_return'
  296. },
  297. Deliver.CONSUMABLE: {'view': 'material.view_consumable_deliver_return',
  298. 'add': 'material.add_consumable_deliver_return',
  299. 'print': 'material.print_consumable_deliver_return'
  300. },
  301. }
  302. return permissions
  303. @staticmethod
  304. def getValidType(type):
  305. try:
  306. type = int(type)
  307. except:
  308. raise CustomError(u'错误的退料类型')
  309. types = (r[0] for r in Deliver.PRODUCT_CHOICES)
  310. if type not in types:
  311. raise CustomError(u'无效的退料类型')
  312. return type
  313. def save(self, *args, **kwargs):
  314. if self.no == None or self.no == '':
  315. now = timezone.now()
  316. rows = DeliverReturn.objects.filter(create_time__gte=now.strftime('%Y-%m-%d')).order_by('-no')
  317. count = rows.count()
  318. prefix = self.PREFIX_CHOICES[self.product_type][1]
  319. if count == 0:
  320. self.no = '%s%s%03d' % (prefix, now.strftime('%Y%m%d'), count + 1)
  321. else:
  322. self.no = rows[0].no[:2] + str(int(rows[0].no[2:]) + 1)
  323. super(DeliverReturn, self).save(*args, **kwargs)
  324. def update_total(self):
  325. return_count = 0
  326. return_cost = 0
  327. sum_row = DeliverReturnDetail.objects.filter(main=self).aggregate(return_count=Sum('return_count'),
  328. return_cost=Sum('return_cost'))
  329. if sum_row:
  330. return_count = sum_row['return_count'] or 0
  331. return_cost = sum_row['return_cost'] or 0
  332. self.return_count = return_count
  333. self.return_cost = return_cost
  334. self.save()
  335. class DeliverReturnDetail(models.Model):
  336. main = models.ForeignKey(DeliverReturn, verbose_name=u'退料单', on_delete=models.PROTECT, related_name='deliver_return_details')
  337. deliver_detail = models.ForeignKey(DeliverDetail, verbose_name=u'出库明细', on_delete=models.PROTECT)
  338. product_base = models.ForeignKey(ProductBase, verbose_name=u'产品', on_delete=models.PROTECT)
  339. return_count = models.BigIntegerField(verbose_name=u'退料数量', default=0)
  340. return_cost = models.BigIntegerField(verbose_name=u'退料成本合计', default=0)
  341. warehouse_stock = models.ForeignKey(WarehouseStock, verbose_name=u'仓别库存', on_delete=models.PROTECT, editable=False)
  342. warehouse_record = models.ForeignKey(WarehouseRecord, verbose_name=u'库存记录', on_delete=models.PROTECT, null=True,
  343. blank=True, related_name='deliver_return_detail_ref_warehouse_record')
  344. notes = models.CharField(max_length=200, verbose_name=u"备注", blank=True, null=True)
  345. class Meta:
  346. db_table = "deliver_detail_return"
  347. verbose_name = u"退料管理"
  348. ordering = ('-id',)
  349. default_permissions = ()
  350. permissions = (# 退料管理明细
  351. ("view_consumable_deliver_return", u"浏览"),
  352. ("add_consumable_deliver_return", u"添加"),
  353. ("print_consumable_deliver_return", u"打印"),
  354. )