models.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. from django.db import models
  2. from erp.models import InboundBill, MaterialDetail, OutboundBill,OutMaterialDetail
  3. from django.db.models import Sum
  4. from django.db.models.signals import post_save, post_delete
  5. from django.dispatch import receiver
  6. class BoundListModel(models.Model):
  7. STATUS =(
  8. ("100", '入库申请'), ("101", '入库同意'), ("102", '组盘中'), ("103", '部分入库'), ("104", '已入库'),
  9. ("111", '质检合格'),
  10. ("200", '出库申请'), ("201", '出库同意'), ("202", '出库中'), ("203", '部分出库'), ("204", '已出库'),
  11. ("300", '完成')
  12. )
  13. audit_status = models.BooleanField(default=False, verbose_name='审核状态')
  14. bound_month = models.CharField(max_length=255, verbose_name="月份")
  15. bound_date = models.DateField(verbose_name="单据日期")
  16. bound_code = models.CharField(max_length=255, verbose_name="出入库编号",unique=True)
  17. bound_code_type = models.CharField(max_length=255, verbose_name="单据类型")
  18. bound_bs_type = models.CharField(max_length=255, verbose_name="业务类型")
  19. bound_type = models.CharField(max_length=255, verbose_name="出入库类型")
  20. bound_desc = models.CharField(default='', max_length=255, verbose_name="出入库描述")
  21. bound_department = models.CharField(max_length=255, verbose_name="部门")
  22. base_type = models.IntegerField(default=0, verbose_name="基准类型")
  23. bound_status = models.CharField(max_length=255, verbose_name="单据状态",choices=STATUS, default='100')
  24. note = models.CharField(default='', max_length=255, verbose_name="备注")
  25. creater = models.CharField(default='uesr', max_length=255, verbose_name="Who Created")
  26. openid = models.CharField(max_length=255, verbose_name="Openid")
  27. is_delete = models.BooleanField(default=False, verbose_name='Delete Label')
  28. create_time = models.DateTimeField(auto_now_add=True, verbose_name="Create Time")
  29. update_time = models.DateTimeField(auto_now=True, blank=True, null=True, verbose_name="Update Time")
  30. relate_bill = models.ForeignKey(InboundBill, on_delete=models.CASCADE, verbose_name="关联单据", related_name='bound_list',null=True, blank=True)
  31. relate_out_bill = models.ForeignKey(OutboundBill, on_delete=models.CASCADE, verbose_name="关联出库单据", related_name='bound_out_list',null=True, blank=True)
  32. class Meta:
  33. db_table = 'boundlist'
  34. verbose_name = 'Bound List'
  35. verbose_name_plural = "Bound List"
  36. ordering = ['bound_status','-id']
  37. class BoundBatchModel(models.Model):
  38. CONTAINER_STATUS = (
  39. (0, '入库申请'),
  40. (1, '入库中'),
  41. (2, '部分入库'),
  42. (3, '在库'),
  43. (4, '出库中'),
  44. (5, '部分出库'),
  45. (6, '已出库'),
  46. )
  47. bound_number = models.CharField(max_length=255, verbose_name="入库批次号",blank=False, null=False, unique=True)
  48. sourced_number = models.CharField(max_length=255, verbose_name="来源批次号",blank=True, null=True)
  49. bound_month = models.CharField(max_length=255, verbose_name="月份")
  50. bound_batch_order = models.IntegerField(default=0, verbose_name="批次顺序")
  51. warehouse_code = models.CharField(max_length=255, verbose_name="仓库编码")
  52. warehouse_name = models.CharField(max_length=255, verbose_name="仓库名称")
  53. goods_code = models.CharField(max_length=255, verbose_name="商品编码")
  54. goods_desc = models.CharField(max_length=255, verbose_name="商品描述")
  55. goods_std = models.CharField(default='待填写', max_length=255, verbose_name="商品标准",blank=True, null=True)
  56. goods_unit = models.CharField(default='待填写', max_length=255, verbose_name="商品单位")
  57. goods_qty = models.BigIntegerField(default=0, verbose_name="商品数量")
  58. goods_package = models.CharField(default='待填写', max_length=255, verbose_name="商品包装")
  59. goods_in_qty = models.BigIntegerField(default=0, verbose_name="组盘入库数量")
  60. goods_in_location_qty = models.BigIntegerField(default=0, verbose_name="库位入库数量")
  61. goods_out_qty = models.BigIntegerField(default=0, verbose_name="出库数量")
  62. goods_actual_qty = models.BigIntegerField(default=0, verbose_name="库位上出库数量")
  63. status = models.IntegerField(choices=CONTAINER_STATUS, default=0, verbose_name='批次状态')
  64. container_number = models.IntegerField( default=0, verbose_name="托盘数目")
  65. goods_weight = models.FloatField(default=0, verbose_name="商品单重")
  66. goods_total_weight = models.FloatField(default=0, verbose_name="商品总重")
  67. note = models.CharField(default='', max_length=255, verbose_name="备注")
  68. creater = models.CharField(default='uesr', max_length=255, verbose_name="Who Created")
  69. openid = models.CharField(max_length=255, verbose_name="Openid")
  70. is_delete = models.BooleanField(default=False, verbose_name='Delete Label')
  71. create_time = models.DateTimeField(auto_now_add=True, verbose_name="Create Time")
  72. update_time = models.DateTimeField(auto_now=True, blank=True, null=True, verbose_name="Update Time")
  73. relate_material = models.ForeignKey(MaterialDetail, on_delete=models.CASCADE, verbose_name="关联物料", related_name='bound_batch',null=True, blank=True)
  74. class Meta:
  75. db_table = 'boundbatch'
  76. verbose_name = 'Bound Batch'
  77. verbose_name_plural = "Bound Batch"
  78. ordering = ['-id']
  79. def __str__(self):
  80. return f"{self.bound_number} - {self.goods_code} - {self.goods_desc}"
  81. def save(self, *args, **kwargs):
  82. # self.goods_actual_qty = self.goods_in_qty - self.goods_out_qty
  83. self.goods_actual_qty = self.goods_in_location_qty
  84. super().save(*args, **kwargs)
  85. class OutBoundDemandModel(models.Model):
  86. OUT_TYPE = (
  87. (0, '发货出库'),
  88. (4, '其他出库'),
  89. )
  90. bound_list = models.ForeignKey(BoundListModel, on_delete=models.CASCADE, verbose_name="Bound List", related_name='out_demand')
  91. goods_code = models.CharField(max_length=255, verbose_name="商品编码")
  92. goods_desc = models.CharField(max_length=255, verbose_name="商品描述")
  93. goods_std = models.CharField(default='待填写', max_length=255, verbose_name="商品标准",blank=True, null=True)
  94. goods_unit = models.CharField(default='待填写', max_length=255, verbose_name="商品单位")
  95. goods_qty = models.BigIntegerField(default=0, verbose_name="计划数量")
  96. working = models.BooleanField(default=False, verbose_name="是否在工作")
  97. creater = models.CharField(default='uesr', max_length=255, verbose_name="Who Created")
  98. create_time = models.DateTimeField(auto_now_add=True, verbose_name="Create Time")
  99. update_time = models.DateTimeField(auto_now=True, blank=True, null=True, verbose_name="Update Time")
  100. is_delete = models.BooleanField(default=False, verbose_name='Delete Label')
  101. out_type = models.IntegerField(choices=OUT_TYPE, default=4, verbose_name="出库类型")
  102. class Meta:
  103. db_table = 'outbounddemand'
  104. verbose_name = '出库需求'
  105. verbose_name_plural = "出库需求"
  106. ordering = ['-id']
  107. class MaterialStatistics(models.Model):
  108. goods_code = models.CharField(max_length=255, verbose_name="商品编码", unique=True)
  109. goods_desc = models.CharField(max_length=255, verbose_name="商品描述")
  110. goods_std = models.CharField(default='待填写', max_length=255, verbose_name="商品标准", blank=True, null=True)
  111. goods_unit = models.CharField(default='待填写', max_length=255, verbose_name="商品单位")
  112. total_quantity = models.BigIntegerField(default=0, verbose_name="计划数量")
  113. total_demanded_quantity = models.BigIntegerField(default=0, verbose_name="需求数量")
  114. def __str__(self):
  115. return f"{self.goods_code} - {self.goods_desc}"
  116. @property
  117. def bound_batches(self):
  118. return BoundBatchModel.objects.filter(goods_code=self.goods_code).exclude(goods_actual_qty=0).order_by('bound_batch_order')
  119. class Meta:
  120. db_table = 'materialstatistics'
  121. verbose_name = '物料统计'
  122. verbose_name_plural = "物料统计"
  123. ordering = ['goods_code']
  124. @receiver([post_save, post_delete], sender=BoundBatchModel)
  125. def update_material_statistics(sender, instance, **kwargs):
  126. goods_code = instance.goods_code
  127. stats, created = MaterialStatistics.objects.get_or_create(
  128. goods_code=goods_code,
  129. defaults={
  130. 'goods_desc': instance.goods_desc,
  131. 'goods_std': instance.goods_std or '待填写',
  132. 'goods_unit': instance.goods_unit or '待填写',
  133. }
  134. )
  135. # 更新物料信息为最新批次的信息(可选)
  136. stats.goods_desc = instance.goods_desc
  137. if instance.goods_std and instance.goods_std != '待填写':
  138. stats.goods_std = instance.goods_std
  139. if instance.goods_unit and instance.goods_unit != '待填写':
  140. stats.goods_unit = instance.goods_unit
  141. stats.save()
  142. # 计算总数量
  143. total = BoundBatchModel.objects.filter(goods_code=goods_code).aggregate(
  144. total=Sum('goods_in_location_qty')
  145. )['total'] or 0
  146. stats.total_quantity = total
  147. stats.save()
  148. @receiver([post_save, post_delete], sender=OutBoundDemandModel)
  149. def update_material_demanded(sender, instance, **kwargs):
  150. goods_code = instance.goods_code
  151. stats, created = MaterialStatistics.objects.get_or_create(
  152. goods_code=goods_code,
  153. defaults={
  154. 'goods_desc': instance.goods_desc,
  155. 'goods_std': instance.goods_std or '待填写',
  156. 'goods_unit': instance.goods_unit or '待填写',
  157. }
  158. )
  159. # 更新物料信息为最新批次的信息(可选)
  160. stats.goods_desc = instance.goods_desc
  161. if instance.goods_std and instance.goods_std != '待填写':
  162. stats.goods_std = instance.goods_std
  163. if instance.goods_unit and instance.goods_unit != '待填写':
  164. stats.goods_unit = instance.goods_unit
  165. stats.save()
  166. # 计算总数量
  167. total = OutBoundDemandModel.objects.filter(goods_code=goods_code,working=True).aggregate(
  168. total=Sum('goods_qty')
  169. )['total'] or 0
  170. stats.total_demanded_quantity = total
  171. stats.save()
  172. class OutBatchModel(models.Model):
  173. CONTAINER_STATUS = (
  174. (0, '申请'),
  175. (1, '在途'),
  176. (2, '已出库')
  177. )
  178. OUT_TYPE = (
  179. (0, '发货出库'),
  180. (4, '其他出库'),
  181. )
  182. bound_list = models.ForeignKey(BoundListModel, on_delete=models.CASCADE, verbose_name="Bound List", related_name='out_batch_list',blank=True, null=True)
  183. out_number = models.CharField(max_length=255, verbose_name="出库批次号",blank=False, null=False)
  184. batch_number = models.ForeignKey(BoundBatchModel, on_delete=models.CASCADE, verbose_name="批次号", related_name='out_batch')
  185. out_date = models.DateTimeField(verbose_name="出库日期")
  186. out_type = models.IntegerField(choices=OUT_TYPE, default=4, verbose_name="出库类型")
  187. out_note = models.CharField(default='', max_length=255, verbose_name="出库备注")
  188. warehouse_code = models.CharField(max_length=255, verbose_name="仓库编码")
  189. warehouse_name = models.CharField(max_length=255, verbose_name="仓库名称")
  190. goods_code = models.CharField(max_length=255, verbose_name="商品编码")
  191. goods_desc = models.CharField(max_length=255, verbose_name="商品描述")
  192. goods_std = models.CharField(default='待填写', max_length=255, verbose_name="商品标准",blank=True, null=True)
  193. goods_unit = models.CharField(default='待填写', max_length=255, verbose_name="商品单位")
  194. goods_qty = models.BigIntegerField(default=0, verbose_name="商品数量")
  195. goods_out_qty = models.BigIntegerField(default=0, verbose_name="出库数量")
  196. status = models.IntegerField(choices=CONTAINER_STATUS, default=0, verbose_name='批次状态')
  197. container_number = models.IntegerField( default=0, verbose_name="托盘数目")
  198. goods_weight = models.FloatField(default=0, verbose_name="商品单重")
  199. goods_total_weight = models.FloatField(default=0, verbose_name="商品总重")
  200. creater = models.CharField(default='uesr', max_length=255, verbose_name="Who Created")
  201. openid = models.CharField(max_length=255, verbose_name="Openid")
  202. is_delete = models.BooleanField(default=False, verbose_name='Delete Label')
  203. create_time = models.DateTimeField(auto_now_add=True, verbose_name="Create Time")
  204. update_time = models.DateTimeField(auto_now=True, blank=True, null=True, verbose_name="Update Time")
  205. relate_material = models.ForeignKey(OutMaterialDetail, on_delete=models.CASCADE, verbose_name="关联物料", related_name='out_batch',null=True, blank=True)
  206. class Meta:
  207. db_table = 'outbatch'
  208. verbose_name = 'Out Batch'
  209. verbose_name_plural = "Out Batch"
  210. ordering = ['-id']
  211. # 利用创建好的批次来与申请单相对应
  212. class OutBoundDetailModel(models.Model):
  213. CONTAINER_STATUS = (
  214. (0, '出库申请'),
  215. (1, '出库中'),
  216. (2, '已出库'),
  217. (3, '入库中'),
  218. (4, '已入库')
  219. )
  220. bound_list = models.ForeignKey(BoundListModel, on_delete=models.CASCADE, verbose_name="Bound List", related_name='out_bound_detail')
  221. bound_batch = models.ForeignKey(OutBatchModel, on_delete=models.PROTECT, verbose_name="Bound Batch", related_name='out_bound_batch_detail')
  222. bound_batch_number = models.ForeignKey(BoundBatchModel, on_delete=models.CASCADE, verbose_name="Bound Batch Number", related_name='out_bound_batch_number_detail')
  223. status = models.IntegerField(choices=CONTAINER_STATUS, default=0, verbose_name='批次状态')
  224. detail_code = models.CharField(max_length=255, verbose_name="明细编号")
  225. creater = models.CharField(default='uesr', max_length=255, verbose_name="Who Created")
  226. openid = models.CharField(max_length=255, verbose_name="Openid")
  227. is_delete = models.BooleanField(default=False, verbose_name='Delete Label')
  228. create_time = models.DateTimeField(auto_now_add=True, verbose_name="Create Time")
  229. update_time = models.DateTimeField(auto_now=True, blank=True, null=True, verbose_name="Update Time")
  230. class Meta:
  231. db_table = 'Outbounddetail'
  232. verbose_name = 'OutBound Detail'
  233. verbose_name_plural = "OutBound Detail"
  234. ordering = ['-id']
  235. class BatchLogModel(models.Model):
  236. BATCH_LOG_TYPE = (
  237. (0, '入库'),
  238. (1, '出库'),
  239. (2, '移库'),
  240. (9, '其他'),
  241. )
  242. batch_id =models.ForeignKey(BoundBatchModel, on_delete=models.CASCADE, verbose_name="批次ID", related_name='batch_log')
  243. log_type = models.IntegerField(choices=BATCH_LOG_TYPE, default=9, verbose_name="日志类型")
  244. log_date = models.DateTimeField(verbose_name="日志日期")
  245. goods_code = models.CharField(max_length=255, verbose_name="商品编码")
  246. goods_desc = models.CharField(max_length=255, verbose_name="商品描述")
  247. goods_qty = models.BigIntegerField(default=0, verbose_name="商品数量")
  248. log_content = models.CharField(max_length=255, verbose_name="日志内容")
  249. creater = models.CharField(default='uesr', max_length=255, verbose_name="Who Created")
  250. openid = models.CharField(max_length=255, verbose_name="Openid")
  251. is_delete = models.BooleanField(default=False, verbose_name='Delete Label')
  252. create_time = models.DateTimeField(auto_now_add=True, verbose_name="Create Time")
  253. update_time = models.DateTimeField(auto_now=True, blank=True, null=True, verbose_name="Update Time")
  254. class Meta:
  255. db_table = 'batchlog'
  256. verbose_name = 'Batch Log'
  257. verbose_name_plural = "Batch Log"
  258. # 利用创建好的批次来与申请单相对应
  259. class BoundDetailModel(models.Model):
  260. CONTAINER_STATUS = (
  261. (0, '入库申请'),
  262. (1, '入库中'),
  263. (2, '在库'),
  264. (3, '出库中'),
  265. (4, '已出库')
  266. )
  267. bound_list = models.ForeignKey(BoundListModel, on_delete=models.CASCADE, verbose_name="Bound List", related_name='bound_detail')
  268. bound_batch = models.ForeignKey(BoundBatchModel, on_delete=models.PROTECT, verbose_name="Bound Batch", related_name='bound_batch_detail')
  269. status = models.IntegerField(choices=CONTAINER_STATUS, default=0, verbose_name='批次状态')
  270. detail_code = models.CharField(max_length=255, verbose_name="明细编号",unique=True)
  271. creater = models.CharField(default='uesr', max_length=255, verbose_name="Who Created")
  272. openid = models.CharField(max_length=255, verbose_name="Openid")
  273. is_delete = models.BooleanField(default=False, verbose_name='Delete Label')
  274. create_time = models.DateTimeField(auto_now_add=True, verbose_name="Create Time")
  275. update_time = models.DateTimeField(auto_now=True, blank=True, null=True, verbose_name="Update Time")
  276. class Meta:
  277. db_table = 'bounddetail'
  278. verbose_name = 'Bound Detail'
  279. verbose_name_plural = "Bound Detail"
  280. ordering = ['-id']