models.py 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149
  1. #coding=utf-8
  2. from django.db import models,connection
  3. from django.db.models import Q, Sum
  4. from django.utils import timezone
  5. from libs.utils import strftime, strfdate
  6. from apps.exceptions import CustomError
  7. from apps.product.models import ProductBase
  8. from apps.supplier.models import Supplier
  9. from apps.account.models import User, Department
  10. from django.conf import settings
  11. from apps.base import Formater
  12. class Warehouse(models.Model):
  13. type = models.PositiveSmallIntegerField(choices=ProductBase.TYPE_CHOICES, verbose_name=u"类型",blank=True)
  14. name = models.CharField(max_length=100, verbose_name=u"名称")
  15. notes = models.CharField(max_length=500, verbose_name=u"备注",blank=True, null=True)
  16. enabled = models.BooleanField(verbose_name=u"在用", default=True)
  17. is_default = models.BooleanField(verbose_name=u"默认仓别", default=False)
  18. @staticmethod
  19. def getManagerWarehouses(user):
  20. return WarehouseAdmin.objects.filter(user=user).values_list('warehouse_id', flat=True)
  21. @staticmethod
  22. def getById(id):
  23. instance = Warehouse.objects.filter(pk=id).first()
  24. if not instance:
  25. raise CustomError(u'未找到相应的仓别')
  26. return instance
  27. @staticmethod
  28. def updateDefault(instance):
  29. if not instance.is_default:
  30. return
  31. Warehouse.objects.filter(Q(type=instance.type),~Q(id=instance.id)).update(is_default=False)
  32. @staticmethod
  33. def getPermissionByType(type, action):
  34. permissions = Warehouse.getPermissionMap()
  35. type = Warehouse.getValidType(type)
  36. return permissions[type][action]
  37. @staticmethod
  38. def getPermissionMap():
  39. permissions = {
  40. ProductBase.MATERIAL: {'view': 'warehouse.view_material_warehouse',
  41. 'add': 'warehouse.add_material_warehouse',
  42. 'delete': 'warehouse.delete_material_warehouse'},
  43. ProductBase.CONSUMABLE: {'view': 'warehouse.view_consumable_warehouse',
  44. 'add': 'warehouse.add_consumable_warehouse',
  45. 'delete': 'warehouse.delete_consumable_warehouse'},
  46. ProductBase.GOODS: {'view': 'warehouse.view_goods_warehouse',
  47. 'add': 'warehouse.add_goods_warehouse',
  48. 'delete': 'warehouse.delete_goods_warehouse'},
  49. }
  50. return permissions
  51. @staticmethod
  52. def getValidType(type):
  53. try:
  54. type = int(type)
  55. except:
  56. raise CustomError(u'错误的仓别类型')
  57. types = (r[0] for r in ProductBase.TYPE_CHOICES)
  58. if type not in types:
  59. raise CustomError(u'无效的仓别类型')
  60. return type
  61. def getPermission(self, action):
  62. permissions = Warehouse.getPermissionMap()
  63. return permissions[self.type][action]
  64. def removeStock(self):
  65. WarehouseStock.objects.filter(warehouse=self).delete()
  66. def removeAdmins(self):
  67. WarehouseAdmin.objects.filter(warehouse=self).delete()
  68. def addAdminByUserId(self,userid):
  69. WarehouseAdmin.objects.create(warehouse=self,user_id=userid)
  70. class Meta:
  71. db_table = "product_warehouse"
  72. verbose_name = u"原料仓别管理"
  73. ordering = ('-id',)
  74. index_together = (
  75. 'name',
  76. )
  77. default_permissions = ()
  78. permissions = (
  79. ("view_material_warehouse", u"浏览"),
  80. ("add_material_warehouse", u"添加"),
  81. ("delete_material_warehouse", u"删除"),
  82. )
  83. class WarehouseAdmin(models.Model):
  84. warehouse = models.ForeignKey(Warehouse, verbose_name=u"仓别", on_delete=models.PROTECT)
  85. user = models.ForeignKey(User, verbose_name=u"管理员", on_delete=models.PROTECT)
  86. class Meta:
  87. db_table = "product_warehouse_admin"
  88. verbose_name = u"耗材仓别管理"
  89. ordering = ('id',)
  90. default_permissions = ()
  91. permissions = (
  92. ("view_consumable_warehouse", u"浏览"),
  93. ("add_consumable_warehouse", u"添加"),
  94. ("delete_consumable_warehouse", u"删除"),
  95. )
  96. class WarehouseStockManager(models.Manager):
  97. def fetch_stock(self, user, time, product_name_model, query_warehouse, last_entry_date, last_deliver_date, type, warehouse_place, enable,
  98. page, page_size,empty,source,export=False):
  99. warehouse_ids = Warehouse.getManagerWarehouses(user)
  100. if not warehouse_ids:
  101. return [], 0, 0, 0
  102. if warehouse_ids.count() == 1:
  103. warehouse_ids = '(' + str(warehouse_ids[0]) + ')'
  104. else:
  105. warehouse_ids = tuple(int(item) for item in warehouse_ids)
  106. where_sql = ' AND product_warehouse.id in %s ' % str(warehouse_ids)
  107. if product_name_model:
  108. where_sql += ' AND (product_base.model LIKE "%%%s%%" or product_base.name LIKE "%%%s%%") '\
  109. % (product_name_model,product_name_model)
  110. if query_warehouse:
  111. where_sql += ' AND product_warehouse.id = %d ' % int(query_warehouse)
  112. if warehouse_place:
  113. where_sql += ' AND product_warehouse_stock.warehouse_place LIKE "%%%s%%" ' % warehouse_place
  114. where_sql += ' AND product_base.type = %d ' % int(type)
  115. if last_entry_date:
  116. if source:
  117. last_entry_date = last_entry_date.split('T')
  118. where_sql += ' AND (product_warehouse_stock.last_entry_time >= "%s 00:00:00" AND product_warehouse_stock.last_entry_time <= "%s 23:59:59") ' % (
  119. last_entry_date[0], last_entry_date[0])
  120. else:
  121. last_entry_date = last_entry_date.split(' - ')
  122. where_sql += ' AND (product_warehouse_stock.last_entry_time >= "%s 00:00:00" AND product_warehouse_stock.last_entry_time <= "%s 23:59:59") ' % (
  123. last_entry_date[0], last_entry_date[1])
  124. if last_deliver_date:
  125. if source:
  126. last_deliver_date = last_deliver_date.split('T')
  127. where_sql += ' AND (product_warehouse_stock.last_deliverd_time >= "%s 00:00:00" AND product_warehouse_stock.last_deliverd_time <= "%s 23:59:59") ' % (
  128. last_deliver_date[0], last_deliver_date[0])
  129. else:
  130. last_deliver_date = last_deliver_date.split(' - ')
  131. where_sql += ' AND (product_warehouse_stock.last_deliverd_time >= "%s 00:00:00" AND product_warehouse_stock.last_deliverd_time <= "%s 23:59:59") ' % (
  132. last_deliver_date[0], last_deliver_date[1])
  133. if time:
  134. where_sql += ' AND product_warehouse_record.happen_time <= "%s" ' % time
  135. if enable:
  136. if enable == '1':
  137. where_sql += ' AND product_base.enabled = 1 '
  138. elif enable == '0':
  139. where_sql += ' AND product_base.enabled = 0 '
  140. if export:
  141. page_sql = ''
  142. else:
  143. page_sql = ' LIMIT %d OFFSET %d ' % (page_size, page * page_size)
  144. search_empty = ''
  145. search_data = ''
  146. left_sql = ''
  147. if empty == '0':
  148. search_empty = ' WHERE count = 0 OR ISNULL(count) '
  149. elif empty == '1':
  150. search_empty = ' WHERE count > 0 '
  151. elif empty == '4':
  152. search_empty = ' WHERE count < 0 '
  153. if int(type) in [ProductBase.MATERIAL, ProductBase.CONSUMABLE] and (empty == '2' or empty == '3'):
  154. if int(type) == ProductBase.MATERIAL:
  155. search_data = ',material.stock_upper_limit as stock_upper_limit, material.stock_lower_limit as stock_lower_limit'
  156. left_sql = ' left join material on material.product_base_id=product_base.id'
  157. elif int(type) == ProductBase.CONSUMABLE:
  158. search_data = ',consumable.stock_upper_limit as stock_upper_limit, consumable.stock_lower_limit as stock_lower_limit'
  159. left_sql = ' left join consumable on consumable.product_base_id=product_base.id'
  160. if empty == '2':
  161. search_empty = ' WHERE count > stock_upper_limit '
  162. elif empty == '3':
  163. search_empty = ' WHERE (ISNULL(count) AND stock_lower_limit > 0) OR (count < stock_lower_limit) '
  164. sql = """
  165. SELECT
  166. product_base.name AS product_name,
  167. product_base.model,
  168. product_base.standard,
  169. product_base.code,
  170. product_base.unit,
  171. product_base.notes,
  172. product_base.name AS name1,
  173. product_warehouse.id AS warehouse_id,
  174. product_warehouse.name AS warehouse_name,
  175. product_warehouse_stock.warehouse_place,
  176. product_warehouse_stock.last_entry_time,
  177. product_warehouse_stock.last_deliverd_time,
  178. system_option.name AS product_type_text,
  179. product_base.id AS product_base_id,
  180. SUM(product_warehouse_record.count) AS count,
  181. SUM(product_warehouse_record.amount) AS amount,
  182. SUM(product_warehouse_record.amount2) AS amount2,
  183. product_warehouse_stock.id
  184. %(search_data)s
  185. FROM
  186. product_warehouse_stock LEFT JOIN
  187. product_warehouse_record ON product_warehouse_record.product_id = product_warehouse_stock.product_id AND product_warehouse_record.warehouse_id = product_warehouse_stock.warehouse_id LEFT JOIN
  188. product_base ON product_warehouse_stock.product_id = product_base.id LEFT JOIN
  189. product_warehouse ON product_warehouse_stock.warehouse_id = product_warehouse.id LEFT JOIN
  190. system_option on system_option.id = product_base.option_type_id
  191. %(left_sql)s
  192. WHERE 1=1 %(where_sql)s
  193. GROUP BY product_warehouse_stock.id
  194. """ % {'where_sql': where_sql, 'left_sql': left_sql, 'search_data': search_data}
  195. total_count_sql = 'SELECT COUNT(0),sum(count),sum(amount) FROM (%s) AS t %s' % (sql, search_empty)
  196. sql = 'SELECT * FROM (%(sql)s ) AS t %(search_empty)s %(page_sql)s' % {
  197. 'sql': sql, 'page_sql': page_sql, 'search_empty': search_empty}
  198. items = []
  199. cursor = connection.cursor()
  200. cursor.execute(sql)
  201. row = cursor.fetchone()
  202. while row:
  203. if not row[11]:
  204. if not row[10]:
  205. days = ''
  206. else:
  207. days = (timezone.now() - row[10]).days
  208. else:
  209. days = (timezone.now() - row[11]).days
  210. avg_cost_price = 0
  211. avg_cost_price2 = 0
  212. if row[14]:
  213. avg_cost_price = row[15] / row[14]
  214. avg_cost_price2 = row[16] / row[14]
  215. item = {
  216. 'product_name': row[0],
  217. 'product_model': row[1],
  218. 'product_standard': row[2],
  219. 'product_code': row[3],
  220. 'product_unit': row[4],
  221. 'product_notes': row[5],
  222. 'warehouse_id': row[7],
  223. 'warehouse_text': row[8],
  224. 'warehouse_place': row[9],
  225. 'last_entry_time': strftime(row[10]),
  226. 'last_deliverd_time': strftime(row[11]),
  227. 'option_type_text': row[12],
  228. 'product_id': row[13],
  229. 'days': days,
  230. 'stock': Formater.formatCountShow(row[14]),
  231. 'avg_cost_price': Formater.formatPriceShow(avg_cost_price),
  232. 'avg_cost_price2': Formater.formatPriceShow(avg_cost_price2),
  233. 'warehouse_amount': Formater.formatAmountShow(row[15]),
  234. 'product_warehouse_stock_id':row[17] or '',
  235. }
  236. items.append(item)
  237. row = cursor.fetchone()
  238. cursor.execute(total_count_sql)
  239. row = cursor.fetchone()
  240. if row:
  241. total_count = row[0]
  242. stock_count = Formater.formatCountShow(row[1])
  243. warehouse_amount = Formater.formatAmountShow(row[2])
  244. else:
  245. total_count = 0
  246. stock_count = 0
  247. warehouse_amount = 0
  248. return items, total_count, stock_count, warehouse_amount
  249. def fetch_stock_ledger(self, user, product_type, product_name, product_model, date, warehouse,exclude_zero, page,
  250. page_size, export=False):
  251. more = {
  252. 'prev_count': 0,
  253. 'prev_amount': 0,
  254. 'remain_count': 0,
  255. 'remain_amount': 0,
  256. 'rk_count': 0,
  257. 'rk_amount': 0,
  258. 'tl_count': 0,
  259. 'tl_amount': 0,
  260. 'py_count': 0,
  261. 'py_amount': 0,
  262. 'ck_count': 0,
  263. 'ck_amount': 0,
  264. 'th_count': 0,
  265. 'th_amount': 0,
  266. 'pk_count': 0,
  267. 'pk_amount': 0,
  268. 'in_count': 0,
  269. 'in_amount': 0,
  270. 'out_count': 0,
  271. 'out_amount': 0
  272. }
  273. in_types = []
  274. out_types = []
  275. rk_types = (WarehouseRecord.RK_ZJ, WarehouseRecord.RK_CG)
  276. tl_types = (WarehouseRecord.TL,)
  277. py_types = (WarehouseRecord.RK_PY,)
  278. ck_types = (WarehouseRecord.CK_ZJ, WarehouseRecord.CK_XS)
  279. th_types = (WarehouseRecord.TH,)
  280. pk_types = (WarehouseRecord.CK_PK,)
  281. rk_types = [str(item) for item in rk_types]
  282. tl_types = [str(item) for item in tl_types]
  283. py_types = [str(item) for item in py_types]
  284. ck_types = [str(item) for item in ck_types]
  285. th_types = [str(item) for item in th_types]
  286. pk_types = [str(item) for item in pk_types]
  287. in_types.extend(rk_types)
  288. in_types.extend(th_types)
  289. in_types.extend(py_types)
  290. out_types.extend(ck_types)
  291. out_types.extend(tl_types)
  292. out_types.extend(pk_types)
  293. prev_where_sql = ''
  294. detail_where_sql = ''
  295. date_begin = '0000-00-00'
  296. date_end = timezone.now().date()
  297. if date:
  298. date = date.split(' - ')
  299. date_begin = date[0]
  300. date_end = date[1]
  301. prev_where_sql += ' AND product_warehouse_record.happen_time < "%s" ' % date_begin
  302. detail_where_sql += ' AND product_warehouse_record.happen_time >= "%s" ' % date_begin
  303. detail_where_sql += ' AND product_warehouse_record.happen_time <= "%s 23:59:59" ' % date_end
  304. where_sql = ' product_base.type = %d ' % int(product_type)
  305. warehouse_ids = Warehouse.getManagerWarehouses(user)
  306. if not warehouse_ids:
  307. return [], 0, more
  308. if warehouse_ids.count() == 1:
  309. warehouse_ids = '(' + str(warehouse_ids[0]) + ')'
  310. else:
  311. warehouse_ids = tuple(int(item) for item in warehouse_ids)
  312. where_sql += ' AND t.warehouse_id in %s ' % str(warehouse_ids)
  313. if product_name:
  314. where_sql += ' AND product_base.name LIKE "%%%s%%" ' % product_name
  315. if product_model:
  316. where_sql += ' AND product_base.model LIKE "%%%s%%" ' % product_model
  317. if warehouse:
  318. where_sql += ' AND t.warehouse_id = %d ' % int(warehouse)
  319. page_sql = ' LIMIT %d OFFSET %d ' % (page_size, page * page_size)
  320. sql = """
  321. SELECT
  322. product_base.name AS product_name,
  323. product_base.model AS product_model,
  324. product_base.unit AS product_unit,
  325. SUM(t.prev_count) AS prev_count,
  326. SUM(t.prev_amount) AS prev_amount,
  327. SUM(t.prev_count + t.in_count + t.out_count) AS remain_count,
  328. SUM(t.prev_amount + t.in_amount + t.out_amount) AS remain_amount,
  329. SUM(t.in_count) AS in_count,
  330. SUM(t.in_amount) AS in_amount,
  331. SUM(t.rk_count) AS rk_count,
  332. SUM(t.rk_amount) AS rk_amount,
  333. SUM(t.tl_count) AS tl_count,
  334. SUM(t.tl_amount) AS tl_amount,
  335. SUM(t.py_count) AS py_count,
  336. SUM(t.py_amount) AS py_amount,
  337. SUM(t.out_count) AS out_count,
  338. SUM(t.out_amount) AS out_amount,
  339. SUM(t.ck_count) AS ck_count,
  340. SUM(t.ck_amount) AS ck_amount,
  341. SUM(t.th_count) AS th_count,
  342. SUM(t.th_amount) AS th_amount,
  343. SUM(t.pk_count) AS pk_count,
  344. SUM(t.pk_amount) AS pk_amount
  345. FROM
  346. (
  347. SELECT
  348. product_warehouse_record.product_id AS product_id,
  349. product_warehouse_record.warehouse_id AS warehouse_id,
  350. SUM(product_warehouse_record.count) AS prev_count,
  351. SUM(product_warehouse_record.amount) AS prev_amount,
  352. 0 AS in_count,
  353. 0 AS in_amount,
  354. 0 AS rk_count,
  355. 0 AS rk_amount,
  356. 0 AS tl_count,
  357. 0 AS tl_amount,
  358. 0 AS py_count,
  359. 0 AS py_amount,
  360. 0 AS out_count,
  361. 0 AS out_amount,
  362. 0 AS ck_count,
  363. 0 AS ck_amount,
  364. 0 AS th_count,
  365. 0 AS th_amount,
  366. 0 AS pk_count,
  367. 0 AS pk_amount
  368. FROM
  369. product_warehouse_record
  370. WHERE
  371. 1=1 %(prev_where_sql)s
  372. GROUP BY
  373. product_warehouse_record.product_id, product_warehouse_record.warehouse_id
  374. UNION ALL
  375. SELECT
  376. product_warehouse_record.product_id AS product_id,
  377. product_warehouse_record.warehouse_id AS warehouse_id,
  378. 0 AS prev_count,
  379. 0 AS prev_amount,
  380. SUM(IF(product_warehouse_record.type IN (%(in_types)s),product_warehouse_record.count,0)) AS in_count,
  381. SUM(IF(product_warehouse_record.type IN (%(in_types)s),product_warehouse_record.amount,0)) AS in_amount,
  382. SUM(IF(product_warehouse_record.type IN (%(rk_types)s),product_warehouse_record.count,0)) AS rk_count,
  383. SUM(IF(product_warehouse_record.type IN (%(rk_types)s),product_warehouse_record.amount,0)) AS rk_amount,
  384. SUM(IF(product_warehouse_record.type IN (%(tl_types)s),product_warehouse_record.count,0)) AS tl_count,
  385. SUM(IF(product_warehouse_record.type IN (%(tl_types)s),product_warehouse_record.amount,0)) AS tl_amount,
  386. SUM(IF(product_warehouse_record.type IN (%(py_types)s),product_warehouse_record.count,0)) AS py_count,
  387. SUM(IF(product_warehouse_record.type IN (%(py_types)s),product_warehouse_record.amount,0)) AS py_amount,
  388. SUM(IF(product_warehouse_record.type IN (%(out_types)s),product_warehouse_record.count,0)) AS out_count,
  389. SUM(IF(product_warehouse_record.type IN (%(out_types)s),product_warehouse_record.amount,0)) AS out_amount,
  390. SUM(IF(product_warehouse_record.type IN (%(ck_types)s),product_warehouse_record.count,0)) AS ck_count,
  391. SUM(IF(product_warehouse_record.type IN (%(ck_types)s),product_warehouse_record.amount,0)) AS ck_amount,
  392. SUM(IF(product_warehouse_record.type IN (%(th_types)s),product_warehouse_record.count,0)) AS th_count,
  393. SUM(IF(product_warehouse_record.type IN (%(th_types)s),product_warehouse_record.amount,0)) AS th_amount,
  394. SUM(IF(product_warehouse_record.type IN (%(pk_types)s),product_warehouse_record.count,0)) AS pk_count,
  395. SUM(IF(product_warehouse_record.type IN (%(pk_types)s),product_warehouse_record.amount,0)) AS pk_amount
  396. FROM
  397. product_warehouse_record
  398. WHERE
  399. 1=1 %(detail_where_sql)s
  400. GROUP BY
  401. product_warehouse_record.product_id , product_warehouse_record.warehouse_id
  402. ) AS t INNER JOIN
  403. product_base ON t.product_id = product_base.id
  404. WHERE
  405. %(where_sql)s
  406. GROUP BY
  407. t.product_id,t.warehouse_id
  408. ORDER BY
  409. product_base.id
  410. """ % {
  411. 'prev_where_sql': prev_where_sql,
  412. 'detail_where_sql': detail_where_sql,
  413. 'where_sql': where_sql,
  414. 'in_types': ','.join(in_types),
  415. 'rk_types': ','.join(rk_types),
  416. 'tl_types': ','.join(tl_types),
  417. 'py_types': ','.join(py_types),
  418. 'out_types': ','.join(out_types),
  419. 'ck_types': ','.join(ck_types),
  420. 'th_types': ','.join(th_types),
  421. 'pk_types': ','.join(pk_types),
  422. }
  423. where_zero_sql = ''
  424. if exclude_zero:
  425. where_zero_sql = """
  426. AND (
  427. tt.prev_count != 0 OR
  428. tt.prev_amount != 0 OR
  429. tt.remain_count != 0 OR
  430. tt.remain_amount != 0 OR
  431. tt.rk_count != 0 OR
  432. tt.rk_amount != 0 OR
  433. tt.tl_count != 0 OR
  434. tt.tl_amount != 0 OR
  435. tt.py_count != 0 OR
  436. tt.py_amount != 0 OR
  437. tt.ck_count != 0 OR
  438. tt.ck_amount != 0 OR
  439. tt.th_count != 0 OR
  440. tt.th_amount != 0 OR
  441. tt.pk_count != 0 OR
  442. tt.pk_amount != 0
  443. )
  444. """
  445. total = 0
  446. cursor = connection.cursor()
  447. if export:
  448. if where_zero_sql:
  449. sql = 'SELECT * FROM (%s) AS tt WHERE 1=1 %s' % (sql, where_zero_sql)
  450. else:
  451. if where_zero_sql:
  452. sum_sql = """
  453. SELECT
  454. SUM(tt.prev_count),
  455. SUM(tt.prev_amount),
  456. SUM(tt.remain_count),
  457. SUM(tt.remain_amount),
  458. SUM(tt.rk_count),
  459. SUM(tt.rk_amount),
  460. SUM(tt.tl_count),
  461. SUM(tt.tl_amount),
  462. SUM(tt.py_count),
  463. SUM(tt.py_amount),
  464. SUM(tt.ck_count),
  465. SUM(tt.ck_amount),
  466. SUM(tt.th_count),
  467. SUM(tt.th_amount),
  468. SUM(tt.pk_count),
  469. SUM(tt.pk_amount),
  470. SUM(tt.in_count),
  471. SUM(tt.in_amount),
  472. SUM(tt.out_count),
  473. SUM(tt.out_amount),
  474. COUNT(0)
  475. FROM
  476. (%s) AS tt WHERE 1=1 %s
  477. """ % (sql, where_zero_sql)
  478. sql = 'SELECT * FROM (%s) AS tt WHERE 1=1 %s %s' % (sql, where_zero_sql, page_sql)
  479. else:
  480. sum_sql = """
  481. SELECT
  482. SUM(tt.prev_count),
  483. SUM(tt.prev_amount),
  484. SUM(tt.remain_count),
  485. SUM(tt.remain_amount),
  486. SUM(tt.rk_count),
  487. SUM(tt.rk_amount),
  488. SUM(tt.tl_count),
  489. SUM(tt.tl_amount),
  490. SUM(tt.py_count),
  491. SUM(tt.py_amount),
  492. SUM(tt.ck_count),
  493. SUM(tt.ck_amount),
  494. SUM(tt.th_count),
  495. SUM(tt.th_amount),
  496. SUM(tt.pk_count),
  497. SUM(tt.pk_amount),
  498. SUM(tt.in_count),
  499. SUM(tt.in_amount),
  500. SUM(tt.out_count),
  501. SUM(tt.out_amount),
  502. COUNT(0)
  503. FROM
  504. (%s) AS tt
  505. """ % sql
  506. sql = '%s %s' % (sql, page_sql)
  507. cursor.execute(sum_sql)
  508. row = cursor.fetchone()
  509. if row:
  510. total = row[20]
  511. more = {
  512. 'prev_count': Formater.formatCountShow(row[0]),
  513. 'prev_amount': Formater.formatAmountShow(row[1]),
  514. 'remain_count': Formater.formatCountShow(row[2]),
  515. 'remain_amount': Formater.formatAmountShow(row[3]),
  516. 'rk_count': Formater.formatCountShow(row[4]),
  517. 'rk_amount': Formater.formatAmountShow(row[5]),
  518. 'tl_count': Formater.formatCountShow(row[6]),
  519. 'tl_amount': Formater.formatAmountShow(row[7]),
  520. 'py_count': Formater.formatCountShow(row[8]),
  521. 'py_amount': Formater.formatAmountShow(row[9]),
  522. 'ck_count': Formater.formatCountShow(-(row[10] or 0)),
  523. 'ck_amount': Formater.formatAmountShow(-(row[11] or 0)),
  524. 'th_count': Formater.formatCountShow(-(row[12] or 0)),
  525. 'th_amount': Formater.formatAmountShow(-(row[13] or 0)),
  526. 'pk_count': Formater.formatCountShow(-(row[14] or 0)),
  527. 'pk_amount': Formater.formatAmountShow(-(row[15] or 0)),
  528. 'in_count': Formater.formatCountShow(row[16]),
  529. 'in_amount': Formater.formatAmountShow(row[17]),
  530. 'out_count': Formater.formatCountShow(-(row[18] or 0)),
  531. 'out_amount': Formater.formatAmountShow(-(row[19] or 0))
  532. }
  533. else:
  534. total = 0
  535. more = {
  536. 'prev_count': 0,
  537. 'prev_amount': 0,
  538. 'remain_count': 0,
  539. 'remain_amount':0,
  540. 'rk_count': 0,
  541. 'rk_amount': 0,
  542. 'tl_count': 0,
  543. 'tl_amount': 0,
  544. 'py_count': 0,
  545. 'py_amount': 0,
  546. 'ck_count': 0,
  547. 'ck_amount':0,
  548. 'th_count': 0,
  549. 'th_amount': 0,
  550. 'pk_count': 0,
  551. 'pk_amount': 0,
  552. 'in_count': 0,
  553. 'in_amount': 0,
  554. 'out_count': 0,
  555. 'out_amount':0
  556. }
  557. data = []
  558. cursor.execute(sql)
  559. row = cursor.fetchone()
  560. while row:
  561. prev_avg = 0
  562. in_avg = 0
  563. out_avg = 0
  564. remain_avg = 0
  565. if row[6]:
  566. prev_avg = row[7] / row[6]
  567. if row[7]:
  568. in_avg = row[8] / row[7]
  569. if row[15]:
  570. out_avg = row[16] / row[15]
  571. if row[5]:
  572. remain_avg = row[6] / row[5]
  573. item = {
  574. 'product_name': row[0],
  575. 'product_model': row[1],
  576. 'unit': row[2],
  577. 'prev_count': Formater.formatCountShow(row[3]),
  578. 'prev_avg': Formater.formatPriceShow(prev_avg),
  579. 'prev_amount': Formater.formatAmountShow(row[4]),
  580. 'in_count': Formater.formatCountShow(row[7]),
  581. 'in_avg': Formater.formatPriceShow(in_avg),
  582. 'in_amount': Formater.formatAmountShow(row[8]),
  583. 'rk_count': Formater.formatCountShow(row[9]),
  584. 'rk_amount': Formater.formatAmountShow(row[10]),
  585. 'tl_count': Formater.formatCountShow(row[11]),
  586. 'tl_amount': Formater.formatAmountShow(row[12]),
  587. 'py_count': Formater.formatCountShow(row[13]),
  588. 'py_amount': Formater.formatAmountShow(row[14]),
  589. 'out_count': Formater.formatCountShow(-(row[15] or 0)),
  590. 'out_avg': Formater.formatPriceShow(out_avg),
  591. 'out_amount': Formater.formatAmountShow(-(row[16] or 0)),
  592. 'ck_count': Formater.formatCountShow(-(row[17] or 0)),
  593. 'ck_amount': Formater.formatAmountShow(-(row[18] or 0)),
  594. 'th_count': Formater.formatCountShow(-(row[19] or 0)),
  595. 'th_amount': Formater.formatAmountShow(-(row[20] or 0)),
  596. 'pk_count': Formater.formatCountShow(-(row[21] or 0)),
  597. 'pk_amount': Formater.formatAmountShow(-(row[22] or 0)),
  598. 'remain_count': Formater.formatCountShow(row[5]),
  599. 'remain_avg': Formater.formatPriceShow(remain_avg),
  600. 'remain_amount': Formater.formatAmountShow(row[6]),
  601. }
  602. data.append(item)
  603. row = cursor.fetchone()
  604. return data, total, more
  605. class WarehouseStock(models.Model):
  606. product = models.ForeignKey(ProductBase, verbose_name=u"产品", on_delete=models.PROTECT)
  607. warehouse = models.ForeignKey(Warehouse, verbose_name=u"仓别", on_delete=models.PROTECT)
  608. warehouse_place = models.CharField(max_length=200, verbose_name=u"库位", null=True)
  609. count = models.BigIntegerField(verbose_name=u"库存数量", default=0)
  610. amount = models.BigIntegerField(verbose_name=u"库存金额", default=0)
  611. amount2 = models.BigIntegerField(verbose_name=u"库存金额2", default=0)
  612. avg_cost_price = models.BigIntegerField(verbose_name=u"平均成本价", default=0)
  613. avg_cost_price2 = models.BigIntegerField(verbose_name=u"平均成本价2", default=0)
  614. last_entry_price = models.BigIntegerField(verbose_name=u"最新入库价", default=0)
  615. last_entry_time = models.DateTimeField(verbose_name=u"最后入库时间", null=True)
  616. last_deliverd_time = models.DateTimeField(verbose_name=u"最后出库时间", null=True)
  617. objects = WarehouseStockManager()
  618. @staticmethod
  619. def getByWarehouseAndProduct(warehouse,product):
  620. warehouse_stock = WarehouseStock.objects.filter(product=product, warehouse=warehouse).first()
  621. if not warehouse_stock:
  622. raise CustomError(u'仓别[%s]中没有[%s]的库存' % (warehouse.name, product.name))
  623. return warehouse_stock
  624. @staticmethod
  625. def createByWarehouse(warehouse):
  626. exist_products = WarehouseStock.objects.filter(warehouse_id=warehouse.id).values_list('product_id',flat=True)
  627. ids = ProductBase.objects.filter(Q(type=warehouse.type),~Q(id__in=exist_products)).values('id')
  628. if not ids:
  629. return
  630. sql = '''
  631. INSERT INTO product_warehouse_stock (
  632. product_id,
  633. warehouse_id,
  634. count,
  635. amount,
  636. amount2,
  637. avg_cost_price,
  638. avg_cost_price2,
  639. last_entry_price)
  640. SELECT
  641. id,
  642. %d,
  643. 0,
  644. 0,
  645. 0,
  646. 0,
  647. 0,
  648. 0
  649. FROM
  650. product_base
  651. where id in (%s)
  652. ''' % (warehouse.id, ','.join([str(item['id']) for item in ids]))
  653. cur = connection.cursor()
  654. cur.execute(sql)
  655. @staticmethod
  656. def createByProduct(product):
  657. exist_warehouses = WarehouseStock.objects.filter(product_id=product.id).values_list('warehouse_id', flat=True)
  658. ids = Warehouse.objects.filter(Q(type=product.type), ~Q(id__in=exist_warehouses)).values('id')
  659. if not ids:
  660. return
  661. sql = '''
  662. INSERT INTO product_warehouse_stock (
  663. product_id,
  664. warehouse_id,
  665. count,
  666. amount,
  667. amount2,
  668. avg_cost_price,
  669. avg_cost_price2,
  670. last_entry_price)
  671. SELECT
  672. %d,
  673. id,
  674. 0,
  675. 0,
  676. 0,
  677. 0,
  678. 0,
  679. 0
  680. FROM
  681. product_warehouse
  682. where id in (%s)
  683. ''' % (product.id, ','.join([str(item['id']) for item in ids]))
  684. cur = connection.cursor()
  685. cur.execute(sql)
  686. @staticmethod
  687. def removeStockByProduct(product):
  688. WarehouseStock.objects.filter(product=product).delete()
  689. @staticmethod
  690. def getPermissionByType(type, action):
  691. permissions = WarehouseStock.getPermissionMap()
  692. type = WarehouseStock.getValidType(type)
  693. return permissions[type][action]
  694. @staticmethod
  695. def getPermissionMap():
  696. permissions = {
  697. ProductBase.MATERIAL: {'view': 'warehouse.view_material_stock',
  698. 'export': 'warehouse.export_material_stock',
  699. 'log': 'warehouse.view_material_stock_log'
  700. },
  701. ProductBase.CONSUMABLE: {'view': 'warehouse.view_consumable_stock',
  702. 'export': 'warehouse.export_consumable_stock',
  703. 'log': 'warehouse.view_consumable_stock_log'
  704. },
  705. ProductBase.GOODS: {'view': 'warehouse.view_goods_stock',
  706. 'export': 'warehouse.export_goods_stock',
  707. 'log': 'warehouse.view_goods_stock_log'
  708. },
  709. }
  710. return permissions
  711. @staticmethod
  712. def getValidType(type):
  713. try:
  714. type = int(type)
  715. except:
  716. raise CustomError(u'错误的类型')
  717. types = (r[0] for r in ProductBase.TYPE_CHOICES)
  718. if type not in types:
  719. raise CustomError(u'无效的类型')
  720. return type
  721. class Meta:
  722. db_table = "product_warehouse_stock"
  723. verbose_name = u"成品仓别管理"
  724. ordering = ('-id',)
  725. default_permissions = ()
  726. permissions = (
  727. ("view_goods_warehouse", u"浏览"),
  728. ("add_goods_warehouse", u"添加"),
  729. ("delete_goods_warehouse", u"删除"),
  730. )
  731. class WarehouseRecord(models.Model):
  732. RK_ZJ = 0
  733. RK_CG = 1
  734. RK_PY = 2
  735. CK_ZJ = 3
  736. CK_XS = 4
  737. CK_PK = 5
  738. TH = 6
  739. TL = 7
  740. TYPE_CHOICES = (
  741. (RK_ZJ, u'直接入库'),
  742. (RK_CG, u'采购入库'),
  743. (RK_PY, u'盘盈入库'),
  744. (CK_ZJ, u'直接出库'),
  745. (CK_XS, u'销售出库'),
  746. (CK_PK, u'盘亏出库'),
  747. (TH, u'退货'),
  748. (TL, u'退料'),
  749. )
  750. type = models.IntegerField(choices=TYPE_CHOICES, verbose_name=u"类型")
  751. happen_time = models.DateTimeField(verbose_name=u"发生时间", default=timezone.now)
  752. product = models.ForeignKey(ProductBase, verbose_name=u"产品", on_delete=models.PROTECT)
  753. warehouse = models.ForeignKey(Warehouse, verbose_name=u"仓别", on_delete=models.PROTECT)
  754. count = models.BigIntegerField(verbose_name=u"数量")
  755. amount = models.BigIntegerField(verbose_name=u"总金额")
  756. amount2 = models.BigIntegerField(verbose_name=u"总金额2")
  757. cur_count = models.BigIntegerField(verbose_name=u"剩余数量", default=0)
  758. cur_amount = models.BigIntegerField(verbose_name=u"剩余金额", default=0)
  759. cur_amount2 = models.BigIntegerField(verbose_name=u"剩余金额2", default=0)
  760. @staticmethod
  761. def updateCurStockByProduct(warehouse_id, product_id):
  762. front_row = None
  763. rows = WarehouseRecord.objects.filter(warehouse_id=warehouse_id, product_id=product_id).order_by('happen_time','-id')
  764. for row in rows:
  765. WarehouseRecord.updateCurStockByFront(row, front_row)
  766. front_row = row
  767. @staticmethod
  768. def updateCurStockByFront(warehouse_record, front_row):
  769. if not front_row:
  770. warehouse_record.cur_count = warehouse_record.count
  771. warehouse_record.cur_amount = warehouse_record.amount
  772. warehouse_record.cur_amount2 = warehouse_record.amount2
  773. else:
  774. warehouse_record.cur_count = front_row.cur_count + warehouse_record.count
  775. warehouse_record.cur_amount = front_row.cur_amount + warehouse_record.amount
  776. warehouse_record.cur_amount2 = front_row.cur_amount2 + warehouse_record.amount2
  777. warehouse_record.save()
  778. @staticmethod
  779. def getPermissionByType(type, action):
  780. permissions = WarehouseRecord.getPermissionMap()
  781. type = WarehouseRecord.getValidType(type)
  782. return permissions[type][action]
  783. @staticmethod
  784. def getPermissionMap():
  785. permissions = {
  786. ProductBase.MATERIAL: {'view': 'product.view_material_stock_ledger',
  787. 'export': 'product.export_material_stock_ledger'
  788. },
  789. ProductBase.CONSUMABLE: {'view': 'product.view_consumable_stock_ledger',
  790. 'export': 'product.export_consumable_stock_ledger'
  791. },
  792. ProductBase.GOODS: {'view': 'product.view_goods_stock_ledger',
  793. 'export': 'product.export_goods_stock_ledger'
  794. },
  795. }
  796. return permissions
  797. @staticmethod
  798. def getValidType(type):
  799. try:
  800. type = int(type)
  801. except:
  802. raise CustomError(u'错误的类型')
  803. types = (r[0] for r in ProductBase.TYPE_CHOICES)
  804. if type not in types:
  805. raise CustomError(u'无效的类型')
  806. return type
  807. class Meta:
  808. db_table = "product_warehouse_record"
  809. verbose_name = u"退料查询"
  810. ordering = ('-id',)
  811. index_together = (
  812. 'type',
  813. 'happen_time',
  814. )
  815. default_permissions = ()
  816. permissions = (# 产品仓别出入库记录
  817. ("view_material_deliver_return_query", u"浏览"),
  818. ("export_material_deliver_return_query", u"导出"),
  819. ("print_material_deliver_return_query", u"打印"),
  820. )
  821. class WarehouseStockRecord(models.Model):
  822. product = models.ForeignKey(ProductBase, verbose_name=u"产品", on_delete=models.PROTECT)
  823. warehouse = models.ForeignKey(Warehouse, verbose_name=u"仓别", on_delete=models.PROTECT)
  824. supplier = models.ForeignKey(Supplier, verbose_name=u"供应商", null=True, on_delete=models.PROTECT)
  825. entry_time = models.DateTimeField(verbose_name=u"入库时间", default=timezone.now)
  826. entry_count = models.BigIntegerField(verbose_name=u"入库数量")
  827. entry_price = models.BigIntegerField(verbose_name=u"入库成本价")
  828. entry_price2 = models.BigIntegerField(verbose_name=u"入库成本价2")
  829. surplus_count = models.BigIntegerField(u'剩余数量')
  830. class Meta:
  831. db_table = "product_warehouse_stock_record"
  832. verbose_name = u"库存查询"
  833. ordering = ('-id',)
  834. index_together = (
  835. 'entry_time',
  836. 'surplus_count',
  837. )
  838. default_permissions = ()
  839. permissions = (# 产品仓别库存记录
  840. ("view_material_stock", u"浏览"),
  841. ("export_material_stock", u"导出"),
  842. ("view_material_stock_log", u"查看动态"),
  843. )
  844. class WarehouseRecordDetail(models.Model):
  845. warehouse_record = models.ForeignKey(WarehouseRecord, verbose_name=u"出入库记录",related_name='warehouse_record_detail_ref_warehouse_record', on_delete=models.PROTECT)
  846. warehouse_stock_record = models.ForeignKey(WarehouseStockRecord, verbose_name=u"库存记录", related_name='warehouse_record_detail_ref_stock_record',on_delete=models.PROTECT)
  847. count = models.BigIntegerField(verbose_name=u"数量")
  848. class Meta:
  849. db_table = "product_warehouse_record_detail"
  850. verbose_name = u"库存查询"
  851. ordering = ('-id',)
  852. default_permissions = ()
  853. permissions = (# 产品仓别出入库记录明细
  854. ("view_consumable_stock", u"浏览"),
  855. ("export_consumable_stock", u"导出"),
  856. ("view_consumable_stock_log", u"查看动态"),
  857. )
  858. class WarehouseBackMap(models.Model):
  859. back_detail = models.ForeignKey(WarehouseRecordDetail, verbose_name=u"退库明细", related_name="product_warehouse_back_map_ref_back_detail",on_delete=models.PROTECT)
  860. delivered_detail = models.ForeignKey(WarehouseRecordDetail, verbose_name=u"出库明细", related_name="product_warehouse_back_map_ref_delivered_detail",on_delete=models.PROTECT)
  861. back_count = models.BigIntegerField(verbose_name=u"退库数量")
  862. class Meta:
  863. db_table = "product_warehouse_back_map"
  864. verbose_name = u"库存查询"
  865. ordering = ('-id',)
  866. default_permissions = ()
  867. permissions = (# 产品仓别退库映射
  868. ("view_goods_stock", u"浏览"),
  869. ("export_goods_stock", u"导出"),
  870. ("view_goods_stock_log", u"查看动态"),
  871. )
  872. class Inventory(models.Model):
  873. MATERIAL = 0
  874. CONSUMABLE = 1
  875. GOODS = 2
  876. PRODUCT_TYPE_CHOICES = (
  877. (MATERIAL, u'原料'),
  878. (CONSUMABLE, u'耗材'),
  879. (GOODS, u'成品'),
  880. )
  881. SURPLUS = 0
  882. LOSS = 1
  883. TYPE_CHOICES = (
  884. (SURPLUS, u'盘盈'),
  885. (LOSS, u'盘亏'),
  886. )
  887. TYPE_PREFIX = ('MAPC', 'COPC', 'GOPC')
  888. no = models.CharField(max_length=50, verbose_name=u"盘存单号", editable=False)
  889. product_type = models.PositiveSmallIntegerField(choices=PRODUCT_TYPE_CHOICES, verbose_name=u"产品类型")
  890. warehouse = models.ForeignKey(Warehouse, verbose_name=u"仓别", on_delete=models.PROTECT)
  891. type = models.PositiveSmallIntegerField(choices=TYPE_CHOICES, verbose_name=u"单据类型")
  892. create_time = models.DateTimeField(verbose_name=u"创建时间", default=timezone.now)
  893. create_user = models.ForeignKey(User, verbose_name=u"创建人", on_delete=models.PROTECT, editable=False)
  894. department = models.ForeignKey(Department, verbose_name=u"创建部门", editable=False, on_delete=models.PROTECT)
  895. check_time = models.DateTimeField(verbose_name=u"审核时间", editable=False, blank=True, null=True)
  896. check_user = models.ForeignKey(User, related_name='inventory_checkuser', verbose_name=u"审核人", blank=True, null=True,on_delete=models.PROTECT)
  897. check_status = models.PositiveSmallIntegerField(choices=settings.CHECK_STATUS_CHOICES, verbose_name=u"审核状态",default=settings.DEFAULT)
  898. notes = models.CharField(max_length=500, verbose_name=u"备注", blank=True, null=True)
  899. total_count = models.BigIntegerField(verbose_name=u"合计数量", default=0)
  900. total_amount = models.BigIntegerField(verbose_name=u"合计金额", default=0)
  901. total_return_count = models.BigIntegerField(verbose_name=u"退货数量合计", default=0)
  902. total_return_amount = models.BigIntegerField(verbose_name=u"退货金额合计", default=0)
  903. total_deliver_count = models.BigIntegerField(verbose_name=u"出库数量合计", default=0)
  904. total_deliver_amount = models.BigIntegerField(verbose_name=u"出库金额合计", default=0)
  905. @staticmethod
  906. def getById(id):
  907. instance = Inventory.objects.filter(pk=id).first()
  908. if not instance:
  909. raise CustomError(u'未找到相应的盘存单')
  910. return instance
  911. def updateAmount(self):
  912. sum_count = 0
  913. sum_amount = 0
  914. sum_rows = InventoryDetail.objects.filter(main=self).aggregate(sum_count=Sum('count'), sum_amount=Sum('amount'))
  915. if sum_rows:
  916. sum_count = sum_rows['sum_count'] or 0
  917. sum_amount = sum_rows['sum_amount'] or 0
  918. self.total_count = sum_count
  919. self.total_amount = sum_amount
  920. self.save()
  921. def update_redundant(self):
  922. total_return_count = 0
  923. total_return_amount = 0
  924. total_deliver_count = 0
  925. total_deliver_amount = 0
  926. sum_row = InventoryDetail.objects.filter(main=self).aggregate(sum_return_count=Sum('return_count'),
  927. sum_return_amount=Sum('return_amount'),
  928. sum_deliver_count=Sum('deliver_count'),
  929. sum_deliver_amount=Sum('deliver_amount'))
  930. if sum_row:
  931. total_return_count = sum_row['sum_return_count'] or 0
  932. total_return_amount = sum_row['sum_return_amount'] or 0
  933. total_deliver_count = sum_row['sum_deliver_count'] or 0
  934. total_deliver_amount = sum_row['sum_deliver_amount'] or 0
  935. self.total_return_count = total_return_count
  936. self.total_return_amount = total_return_amount
  937. self.total_deliver_count = total_deliver_count
  938. self.total_deliver_amount = total_deliver_amount
  939. self.save()
  940. def save(self, *args, **kwargs):
  941. if self.no == None or self.no == '':
  942. prefix = Inventory.TYPE_PREFIX[self.product_type]
  943. now = timezone.now()
  944. rows = Inventory.objects.filter(create_time__gte=now.strftime('%Y-%m-%d')).order_by('-no')
  945. count = rows.count()
  946. if count == 0:
  947. self.no = '%s%s%03d' % (prefix, now.strftime('%Y%m%d'), count + 1)
  948. else:
  949. self.no = rows[0].no[:4] + str(int(rows[0].no[4:]) + 1)
  950. super(Inventory, self).save(*args, **kwargs)
  951. def getPermission(self, action):
  952. permissions = Inventory.getPermissionMap()
  953. return permissions[self.product_type][action]
  954. @staticmethod
  955. def getPermissionByType(type, action):
  956. permissions = Inventory.getPermissionMap()
  957. type = Inventory.getValidType(type)
  958. return permissions[type][action]
  959. @staticmethod
  960. def getPermissionMap():
  961. permissions = {
  962. Inventory.MATERIAL: {'view': 'warehouse.view_material_inventory',
  963. 'add': 'warehouse.add_material_inventory',
  964. 'check': 'warehouse.check_material_inventory',
  965. 'delete': 'warehouse.delete_material_inventory',
  966. 'export': 'warehouse.export_material_inventory',
  967. 'print': 'warehouse.print_material_inventory'
  968. },
  969. Inventory.CONSUMABLE: {'view': 'warehouse.view_consumable_inventory',
  970. 'add': 'warehouse.add_consumable_inventory',
  971. 'check': 'warehouse.check_consumable_inventory',
  972. 'delete': 'warehouse.delete_consumable_inventory',
  973. 'export': 'warehouse.export_consumable_inventory',
  974. 'print': 'warehouse.print_consumable_inventory'
  975. },
  976. Inventory.GOODS: {'view': 'goods.view_goods_inventory',
  977. 'add': 'goods.add_goods_inventory',
  978. 'check': 'goods.check_goods_inventory',
  979. 'delete': 'goods.delete_goods_inventory',
  980. 'export': 'goods.export_goods_inventory',
  981. 'print': 'goods.print_goods_inventory'
  982. },
  983. }
  984. return permissions
  985. @staticmethod
  986. def getValidType(type):
  987. try:
  988. type = int(type)
  989. except:
  990. raise CustomError(u'错误的盘存类型')
  991. types = (r[0] for r in Inventory.PRODUCT_TYPE_CHOICES)
  992. if type not in types:
  993. raise CustomError(u'无效的盘存类型')
  994. return type
  995. class Meta:
  996. db_table = "inventory"
  997. ordering = ('-id',)
  998. verbose_name = u"盘存管理"
  999. index_together = (
  1000. 'create_time', 'check_time'
  1001. )
  1002. unique_together = (
  1003. 'no',
  1004. )
  1005. default_permissions = ()
  1006. permissions = (
  1007. ("view_material_inventory", u"浏览"),
  1008. ("add_material_inventory", u"添加"),
  1009. ("check_material_inventory", u"审核"),
  1010. ("delete_material_inventory", u"删除"),
  1011. ("export_material_inventory", u"导出"),
  1012. ("print_material_inventory", u"打印"),
  1013. )
  1014. class InventoryDetail(models.Model):
  1015. main = models.ForeignKey(Inventory, related_name='inventory_details', on_delete=models.PROTECT)
  1016. product = models.ForeignKey(ProductBase, verbose_name=u"产品", on_delete=models.PROTECT)
  1017. warehouse_stock = models.ForeignKey(WarehouseStock, verbose_name=u'仓别库存', on_delete=models.PROTECT, blank=True, editable=False)
  1018. count = models.BigIntegerField(verbose_name=u"数量", default=0)
  1019. price = models.BigIntegerField(verbose_name=u"单价", default=0)
  1020. amount = models.BigIntegerField(verbose_name=u"金额", default=0)
  1021. warehouse_record = models.ForeignKey(WarehouseRecord,related_name='inventory_details_ref_warehouse_record', verbose_name=u'出入库记录', on_delete=models.PROTECT, blank=True, null=True)
  1022. warehouse_stock_record = models.ForeignKey(WarehouseStockRecord, related_name='inventory_details_ref_warehouse_stock_record', verbose_name=u'库存记录', on_delete=models.PROTECT, blank=True, null=True)
  1023. loss_stock_record = models.ForeignKey(WarehouseStockRecord, related_name='inventory_details_ref_loss_stock_record', verbose_name=u'盘亏库存记录', on_delete=models.PROTECT, blank=True, null=True)
  1024. return_count = models.BigIntegerField(verbose_name=u"退货数量", default=0)
  1025. return_amount = models.BigIntegerField(verbose_name=u"退货金额", default=0)
  1026. deliver_count = models.BigIntegerField(verbose_name=u"出库数量", default=0)
  1027. deliver_amount = models.BigIntegerField(verbose_name=u"出库金额", default=0)
  1028. notes = models.CharField(max_length=200, verbose_name=u"备注", blank=True, null=True)
  1029. class Meta:
  1030. verbose_name = u"盘存管理"
  1031. db_table = "inventory_detail"
  1032. ordering = ("-id",)
  1033. default_permissions = ()
  1034. permissions = (# 盘存明细
  1035. ("view_consumable_inventory", u"浏览"),
  1036. ("add_consumable_inventory", u"添加"),
  1037. ("check_consumable_inventory", u"审核"),
  1038. ("delete_consumable_inventory", u"删除"),
  1039. ("export_consumable_inventory", u"导出"),
  1040. ("print_consumable_inventory", u"打印"),
  1041. )
  1042. @staticmethod
  1043. def getById(id):
  1044. instance = InventoryDetail.objects.filter(pk=id).first()
  1045. if not instance:
  1046. raise CustomError(u'未找到相应的盘存明细')
  1047. return instance