123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149 |
- #coding=utf-8
- from django.db import models,connection
- from django.db.models import Q, Sum
- from django.utils import timezone
- from libs.utils import strftime, strfdate
- from apps.exceptions import CustomError
- from apps.product.models import ProductBase
- from apps.supplier.models import Supplier
- from apps.account.models import User, Department
- from django.conf import settings
- from apps.base import Formater
- class Warehouse(models.Model):
- type = models.PositiveSmallIntegerField(choices=ProductBase.TYPE_CHOICES, verbose_name=u"类型",blank=True)
- name = models.CharField(max_length=100, verbose_name=u"名称")
- notes = models.CharField(max_length=500, verbose_name=u"备注",blank=True, null=True)
- enabled = models.BooleanField(verbose_name=u"在用", default=True)
- is_default = models.BooleanField(verbose_name=u"默认仓别", default=False)
- @staticmethod
- def getManagerWarehouses(user):
- return WarehouseAdmin.objects.filter(user=user).values_list('warehouse_id', flat=True)
- @staticmethod
- def getById(id):
- instance = Warehouse.objects.filter(pk=id).first()
- if not instance:
- raise CustomError(u'未找到相应的仓别')
- return instance
- @staticmethod
- def updateDefault(instance):
- if not instance.is_default:
- return
- Warehouse.objects.filter(Q(type=instance.type),~Q(id=instance.id)).update(is_default=False)
- @staticmethod
- def getPermissionByType(type, action):
- permissions = Warehouse.getPermissionMap()
- type = Warehouse.getValidType(type)
- return permissions[type][action]
- @staticmethod
- def getPermissionMap():
- permissions = {
- ProductBase.MATERIAL: {'view': 'warehouse.view_material_warehouse',
- 'add': 'warehouse.add_material_warehouse',
- 'delete': 'warehouse.delete_material_warehouse'},
- ProductBase.CONSUMABLE: {'view': 'warehouse.view_consumable_warehouse',
- 'add': 'warehouse.add_consumable_warehouse',
- 'delete': 'warehouse.delete_consumable_warehouse'},
- ProductBase.GOODS: {'view': 'warehouse.view_goods_warehouse',
- 'add': 'warehouse.add_goods_warehouse',
- 'delete': 'warehouse.delete_goods_warehouse'},
- }
- return permissions
- @staticmethod
- def getValidType(type):
- try:
- type = int(type)
- except:
- raise CustomError(u'错误的仓别类型')
- types = (r[0] for r in ProductBase.TYPE_CHOICES)
- if type not in types:
- raise CustomError(u'无效的仓别类型')
- return type
- def getPermission(self, action):
- permissions = Warehouse.getPermissionMap()
- return permissions[self.type][action]
- def removeStock(self):
- WarehouseStock.objects.filter(warehouse=self).delete()
- def removeAdmins(self):
- WarehouseAdmin.objects.filter(warehouse=self).delete()
- def addAdminByUserId(self,userid):
- WarehouseAdmin.objects.create(warehouse=self,user_id=userid)
- class Meta:
- db_table = "product_warehouse"
- verbose_name = u"原料仓别管理"
- ordering = ('-id',)
- index_together = (
- 'name',
- )
- default_permissions = ()
- permissions = (
- ("view_material_warehouse", u"浏览"),
- ("add_material_warehouse", u"添加"),
- ("delete_material_warehouse", u"删除"),
- )
- class WarehouseAdmin(models.Model):
- warehouse = models.ForeignKey(Warehouse, verbose_name=u"仓别", on_delete=models.PROTECT)
- user = models.ForeignKey(User, verbose_name=u"管理员", on_delete=models.PROTECT)
- class Meta:
- db_table = "product_warehouse_admin"
- verbose_name = u"耗材仓别管理"
- ordering = ('id',)
- default_permissions = ()
- permissions = (
- ("view_consumable_warehouse", u"浏览"),
- ("add_consumable_warehouse", u"添加"),
- ("delete_consumable_warehouse", u"删除"),
- )
- class WarehouseStockManager(models.Manager):
- def fetch_stock(self, user, time, product_name_model, query_warehouse, last_entry_date, last_deliver_date, type, warehouse_place, enable,
- page, page_size,empty,source,export=False):
- warehouse_ids = Warehouse.getManagerWarehouses(user)
- if not warehouse_ids:
- return [], 0, 0, 0
- if warehouse_ids.count() == 1:
- warehouse_ids = '(' + str(warehouse_ids[0]) + ')'
- else:
- warehouse_ids = tuple(int(item) for item in warehouse_ids)
- where_sql = ' AND product_warehouse.id in %s ' % str(warehouse_ids)
- if product_name_model:
- where_sql += ' AND (product_base.model LIKE "%%%s%%" or product_base.name LIKE "%%%s%%") '\
- % (product_name_model,product_name_model)
- if query_warehouse:
- where_sql += ' AND product_warehouse.id = %d ' % int(query_warehouse)
- if warehouse_place:
- where_sql += ' AND product_warehouse_stock.warehouse_place LIKE "%%%s%%" ' % warehouse_place
- where_sql += ' AND product_base.type = %d ' % int(type)
- if last_entry_date:
- if source:
- last_entry_date = last_entry_date.split('T')
- where_sql += ' AND (product_warehouse_stock.last_entry_time >= "%s 00:00:00" AND product_warehouse_stock.last_entry_time <= "%s 23:59:59") ' % (
- last_entry_date[0], last_entry_date[0])
- else:
- last_entry_date = last_entry_date.split(' - ')
- where_sql += ' AND (product_warehouse_stock.last_entry_time >= "%s 00:00:00" AND product_warehouse_stock.last_entry_time <= "%s 23:59:59") ' % (
- last_entry_date[0], last_entry_date[1])
- if last_deliver_date:
- if source:
- last_deliver_date = last_deliver_date.split('T')
- where_sql += ' AND (product_warehouse_stock.last_deliverd_time >= "%s 00:00:00" AND product_warehouse_stock.last_deliverd_time <= "%s 23:59:59") ' % (
- last_deliver_date[0], last_deliver_date[0])
- else:
- last_deliver_date = last_deliver_date.split(' - ')
- where_sql += ' AND (product_warehouse_stock.last_deliverd_time >= "%s 00:00:00" AND product_warehouse_stock.last_deliverd_time <= "%s 23:59:59") ' % (
- last_deliver_date[0], last_deliver_date[1])
- if time:
- where_sql += ' AND product_warehouse_record.happen_time <= "%s" ' % time
- if enable:
- if enable == '1':
- where_sql += ' AND product_base.enabled = 1 '
- elif enable == '0':
- where_sql += ' AND product_base.enabled = 0 '
- if export:
- page_sql = ''
- else:
- page_sql = ' LIMIT %d OFFSET %d ' % (page_size, page * page_size)
- search_empty = ''
- search_data = ''
- left_sql = ''
- if empty == '0':
- search_empty = ' WHERE count = 0 OR ISNULL(count) '
- elif empty == '1':
- search_empty = ' WHERE count > 0 '
- elif empty == '4':
- search_empty = ' WHERE count < 0 '
- if int(type) in [ProductBase.MATERIAL, ProductBase.CONSUMABLE] and (empty == '2' or empty == '3'):
- if int(type) == ProductBase.MATERIAL:
- search_data = ',material.stock_upper_limit as stock_upper_limit, material.stock_lower_limit as stock_lower_limit'
- left_sql = ' left join material on material.product_base_id=product_base.id'
- elif int(type) == ProductBase.CONSUMABLE:
- search_data = ',consumable.stock_upper_limit as stock_upper_limit, consumable.stock_lower_limit as stock_lower_limit'
- left_sql = ' left join consumable on consumable.product_base_id=product_base.id'
- if empty == '2':
- search_empty = ' WHERE count > stock_upper_limit '
- elif empty == '3':
- search_empty = ' WHERE (ISNULL(count) AND stock_lower_limit > 0) OR (count < stock_lower_limit) '
- sql = """
- SELECT
- product_base.name AS product_name,
- product_base.model,
- product_base.standard,
- product_base.code,
- product_base.unit,
- product_base.notes,
- product_base.name AS name1,
- product_warehouse.id AS warehouse_id,
- product_warehouse.name AS warehouse_name,
- product_warehouse_stock.warehouse_place,
- product_warehouse_stock.last_entry_time,
- product_warehouse_stock.last_deliverd_time,
- system_option.name AS product_type_text,
- product_base.id AS product_base_id,
- SUM(product_warehouse_record.count) AS count,
- SUM(product_warehouse_record.amount) AS amount,
- SUM(product_warehouse_record.amount2) AS amount2,
- product_warehouse_stock.id
- %(search_data)s
- FROM
- product_warehouse_stock LEFT JOIN
- 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
- product_base ON product_warehouse_stock.product_id = product_base.id LEFT JOIN
- product_warehouse ON product_warehouse_stock.warehouse_id = product_warehouse.id LEFT JOIN
- system_option on system_option.id = product_base.option_type_id
- %(left_sql)s
- WHERE 1=1 %(where_sql)s
- GROUP BY product_warehouse_stock.id
- """ % {'where_sql': where_sql, 'left_sql': left_sql, 'search_data': search_data}
- total_count_sql = 'SELECT COUNT(0),sum(count),sum(amount) FROM (%s) AS t %s' % (sql, search_empty)
- sql = 'SELECT * FROM (%(sql)s ) AS t %(search_empty)s %(page_sql)s' % {
- 'sql': sql, 'page_sql': page_sql, 'search_empty': search_empty}
- items = []
- cursor = connection.cursor()
- cursor.execute(sql)
- row = cursor.fetchone()
- while row:
- if not row[11]:
- if not row[10]:
- days = ''
- else:
- days = (timezone.now() - row[10]).days
- else:
- days = (timezone.now() - row[11]).days
- avg_cost_price = 0
- avg_cost_price2 = 0
- if row[14]:
- avg_cost_price = row[15] / row[14]
- avg_cost_price2 = row[16] / row[14]
- item = {
- 'product_name': row[0],
- 'product_model': row[1],
- 'product_standard': row[2],
- 'product_code': row[3],
- 'product_unit': row[4],
- 'product_notes': row[5],
- 'warehouse_id': row[7],
- 'warehouse_text': row[8],
- 'warehouse_place': row[9],
- 'last_entry_time': strftime(row[10]),
- 'last_deliverd_time': strftime(row[11]),
- 'option_type_text': row[12],
- 'product_id': row[13],
- 'days': days,
- 'stock': Formater.formatCountShow(row[14]),
- 'avg_cost_price': Formater.formatPriceShow(avg_cost_price),
- 'avg_cost_price2': Formater.formatPriceShow(avg_cost_price2),
- 'warehouse_amount': Formater.formatAmountShow(row[15]),
- 'product_warehouse_stock_id':row[17] or '',
- }
- items.append(item)
- row = cursor.fetchone()
- cursor.execute(total_count_sql)
- row = cursor.fetchone()
- if row:
- total_count = row[0]
- stock_count = Formater.formatCountShow(row[1])
- warehouse_amount = Formater.formatAmountShow(row[2])
- else:
- total_count = 0
- stock_count = 0
- warehouse_amount = 0
- return items, total_count, stock_count, warehouse_amount
- def fetch_stock_ledger(self, user, product_type, product_name, product_model, date, warehouse,exclude_zero, page,
- page_size, export=False):
- more = {
- 'prev_count': 0,
- 'prev_amount': 0,
- 'remain_count': 0,
- 'remain_amount': 0,
- 'rk_count': 0,
- 'rk_amount': 0,
- 'tl_count': 0,
- 'tl_amount': 0,
- 'py_count': 0,
- 'py_amount': 0,
- 'ck_count': 0,
- 'ck_amount': 0,
- 'th_count': 0,
- 'th_amount': 0,
- 'pk_count': 0,
- 'pk_amount': 0,
- 'in_count': 0,
- 'in_amount': 0,
- 'out_count': 0,
- 'out_amount': 0
- }
- in_types = []
- out_types = []
- rk_types = (WarehouseRecord.RK_ZJ, WarehouseRecord.RK_CG)
- tl_types = (WarehouseRecord.TL,)
- py_types = (WarehouseRecord.RK_PY,)
- ck_types = (WarehouseRecord.CK_ZJ, WarehouseRecord.CK_XS)
- th_types = (WarehouseRecord.TH,)
- pk_types = (WarehouseRecord.CK_PK,)
- rk_types = [str(item) for item in rk_types]
- tl_types = [str(item) for item in tl_types]
- py_types = [str(item) for item in py_types]
- ck_types = [str(item) for item in ck_types]
- th_types = [str(item) for item in th_types]
- pk_types = [str(item) for item in pk_types]
- in_types.extend(rk_types)
- in_types.extend(th_types)
- in_types.extend(py_types)
- out_types.extend(ck_types)
- out_types.extend(tl_types)
- out_types.extend(pk_types)
- prev_where_sql = ''
- detail_where_sql = ''
- date_begin = '0000-00-00'
- date_end = timezone.now().date()
- if date:
- date = date.split(' - ')
- date_begin = date[0]
- date_end = date[1]
- prev_where_sql += ' AND product_warehouse_record.happen_time < "%s" ' % date_begin
- detail_where_sql += ' AND product_warehouse_record.happen_time >= "%s" ' % date_begin
- detail_where_sql += ' AND product_warehouse_record.happen_time <= "%s 23:59:59" ' % date_end
- where_sql = ' product_base.type = %d ' % int(product_type)
- warehouse_ids = Warehouse.getManagerWarehouses(user)
- if not warehouse_ids:
- return [], 0, more
- if warehouse_ids.count() == 1:
- warehouse_ids = '(' + str(warehouse_ids[0]) + ')'
- else:
- warehouse_ids = tuple(int(item) for item in warehouse_ids)
- where_sql += ' AND t.warehouse_id in %s ' % str(warehouse_ids)
- if product_name:
- where_sql += ' AND product_base.name LIKE "%%%s%%" ' % product_name
- if product_model:
- where_sql += ' AND product_base.model LIKE "%%%s%%" ' % product_model
- if warehouse:
- where_sql += ' AND t.warehouse_id = %d ' % int(warehouse)
- page_sql = ' LIMIT %d OFFSET %d ' % (page_size, page * page_size)
- sql = """
- SELECT
- product_base.name AS product_name,
- product_base.model AS product_model,
- product_base.unit AS product_unit,
- SUM(t.prev_count) AS prev_count,
- SUM(t.prev_amount) AS prev_amount,
- SUM(t.prev_count + t.in_count + t.out_count) AS remain_count,
- SUM(t.prev_amount + t.in_amount + t.out_amount) AS remain_amount,
- SUM(t.in_count) AS in_count,
- SUM(t.in_amount) AS in_amount,
- SUM(t.rk_count) AS rk_count,
- SUM(t.rk_amount) AS rk_amount,
- SUM(t.tl_count) AS tl_count,
- SUM(t.tl_amount) AS tl_amount,
- SUM(t.py_count) AS py_count,
- SUM(t.py_amount) AS py_amount,
- SUM(t.out_count) AS out_count,
- SUM(t.out_amount) AS out_amount,
- SUM(t.ck_count) AS ck_count,
- SUM(t.ck_amount) AS ck_amount,
- SUM(t.th_count) AS th_count,
- SUM(t.th_amount) AS th_amount,
- SUM(t.pk_count) AS pk_count,
- SUM(t.pk_amount) AS pk_amount
- FROM
- (
- SELECT
- product_warehouse_record.product_id AS product_id,
- product_warehouse_record.warehouse_id AS warehouse_id,
- SUM(product_warehouse_record.count) AS prev_count,
- SUM(product_warehouse_record.amount) AS prev_amount,
- 0 AS in_count,
- 0 AS in_amount,
- 0 AS rk_count,
- 0 AS rk_amount,
- 0 AS tl_count,
- 0 AS tl_amount,
- 0 AS py_count,
- 0 AS py_amount,
- 0 AS out_count,
- 0 AS out_amount,
- 0 AS ck_count,
- 0 AS ck_amount,
- 0 AS th_count,
- 0 AS th_amount,
- 0 AS pk_count,
- 0 AS pk_amount
- FROM
- product_warehouse_record
- WHERE
- 1=1 %(prev_where_sql)s
- GROUP BY
- product_warehouse_record.product_id, product_warehouse_record.warehouse_id
- UNION ALL
- SELECT
- product_warehouse_record.product_id AS product_id,
- product_warehouse_record.warehouse_id AS warehouse_id,
- 0 AS prev_count,
- 0 AS prev_amount,
- SUM(IF(product_warehouse_record.type IN (%(in_types)s),product_warehouse_record.count,0)) AS in_count,
- SUM(IF(product_warehouse_record.type IN (%(in_types)s),product_warehouse_record.amount,0)) AS in_amount,
- SUM(IF(product_warehouse_record.type IN (%(rk_types)s),product_warehouse_record.count,0)) AS rk_count,
- SUM(IF(product_warehouse_record.type IN (%(rk_types)s),product_warehouse_record.amount,0)) AS rk_amount,
- SUM(IF(product_warehouse_record.type IN (%(tl_types)s),product_warehouse_record.count,0)) AS tl_count,
- SUM(IF(product_warehouse_record.type IN (%(tl_types)s),product_warehouse_record.amount,0)) AS tl_amount,
- SUM(IF(product_warehouse_record.type IN (%(py_types)s),product_warehouse_record.count,0)) AS py_count,
- SUM(IF(product_warehouse_record.type IN (%(py_types)s),product_warehouse_record.amount,0)) AS py_amount,
- SUM(IF(product_warehouse_record.type IN (%(out_types)s),product_warehouse_record.count,0)) AS out_count,
- SUM(IF(product_warehouse_record.type IN (%(out_types)s),product_warehouse_record.amount,0)) AS out_amount,
- SUM(IF(product_warehouse_record.type IN (%(ck_types)s),product_warehouse_record.count,0)) AS ck_count,
- SUM(IF(product_warehouse_record.type IN (%(ck_types)s),product_warehouse_record.amount,0)) AS ck_amount,
- SUM(IF(product_warehouse_record.type IN (%(th_types)s),product_warehouse_record.count,0)) AS th_count,
- SUM(IF(product_warehouse_record.type IN (%(th_types)s),product_warehouse_record.amount,0)) AS th_amount,
- SUM(IF(product_warehouse_record.type IN (%(pk_types)s),product_warehouse_record.count,0)) AS pk_count,
- SUM(IF(product_warehouse_record.type IN (%(pk_types)s),product_warehouse_record.amount,0)) AS pk_amount
- FROM
- product_warehouse_record
- WHERE
- 1=1 %(detail_where_sql)s
- GROUP BY
- product_warehouse_record.product_id , product_warehouse_record.warehouse_id
- ) AS t INNER JOIN
- product_base ON t.product_id = product_base.id
- WHERE
- %(where_sql)s
- GROUP BY
- t.product_id,t.warehouse_id
- ORDER BY
- product_base.id
- """ % {
- 'prev_where_sql': prev_where_sql,
- 'detail_where_sql': detail_where_sql,
- 'where_sql': where_sql,
- 'in_types': ','.join(in_types),
- 'rk_types': ','.join(rk_types),
- 'tl_types': ','.join(tl_types),
- 'py_types': ','.join(py_types),
- 'out_types': ','.join(out_types),
- 'ck_types': ','.join(ck_types),
- 'th_types': ','.join(th_types),
- 'pk_types': ','.join(pk_types),
- }
- where_zero_sql = ''
- if exclude_zero:
- where_zero_sql = """
- AND (
- tt.prev_count != 0 OR
- tt.prev_amount != 0 OR
- tt.remain_count != 0 OR
- tt.remain_amount != 0 OR
- tt.rk_count != 0 OR
- tt.rk_amount != 0 OR
- tt.tl_count != 0 OR
- tt.tl_amount != 0 OR
- tt.py_count != 0 OR
- tt.py_amount != 0 OR
- tt.ck_count != 0 OR
- tt.ck_amount != 0 OR
- tt.th_count != 0 OR
- tt.th_amount != 0 OR
- tt.pk_count != 0 OR
- tt.pk_amount != 0
- )
- """
- total = 0
- cursor = connection.cursor()
- if export:
- if where_zero_sql:
- sql = 'SELECT * FROM (%s) AS tt WHERE 1=1 %s' % (sql, where_zero_sql)
- else:
- if where_zero_sql:
- sum_sql = """
- SELECT
- SUM(tt.prev_count),
- SUM(tt.prev_amount),
- SUM(tt.remain_count),
- SUM(tt.remain_amount),
- SUM(tt.rk_count),
- SUM(tt.rk_amount),
- SUM(tt.tl_count),
- SUM(tt.tl_amount),
- SUM(tt.py_count),
- SUM(tt.py_amount),
- SUM(tt.ck_count),
- SUM(tt.ck_amount),
- SUM(tt.th_count),
- SUM(tt.th_amount),
- SUM(tt.pk_count),
- SUM(tt.pk_amount),
- SUM(tt.in_count),
- SUM(tt.in_amount),
- SUM(tt.out_count),
- SUM(tt.out_amount),
- COUNT(0)
- FROM
- (%s) AS tt WHERE 1=1 %s
- """ % (sql, where_zero_sql)
- sql = 'SELECT * FROM (%s) AS tt WHERE 1=1 %s %s' % (sql, where_zero_sql, page_sql)
- else:
- sum_sql = """
- SELECT
- SUM(tt.prev_count),
- SUM(tt.prev_amount),
- SUM(tt.remain_count),
- SUM(tt.remain_amount),
- SUM(tt.rk_count),
- SUM(tt.rk_amount),
- SUM(tt.tl_count),
- SUM(tt.tl_amount),
- SUM(tt.py_count),
- SUM(tt.py_amount),
- SUM(tt.ck_count),
- SUM(tt.ck_amount),
- SUM(tt.th_count),
- SUM(tt.th_amount),
- SUM(tt.pk_count),
- SUM(tt.pk_amount),
- SUM(tt.in_count),
- SUM(tt.in_amount),
- SUM(tt.out_count),
- SUM(tt.out_amount),
- COUNT(0)
- FROM
- (%s) AS tt
- """ % sql
- sql = '%s %s' % (sql, page_sql)
- cursor.execute(sum_sql)
- row = cursor.fetchone()
- if row:
- total = row[20]
- more = {
- 'prev_count': Formater.formatCountShow(row[0]),
- 'prev_amount': Formater.formatAmountShow(row[1]),
- 'remain_count': Formater.formatCountShow(row[2]),
- 'remain_amount': Formater.formatAmountShow(row[3]),
- 'rk_count': Formater.formatCountShow(row[4]),
- 'rk_amount': Formater.formatAmountShow(row[5]),
- 'tl_count': Formater.formatCountShow(row[6]),
- 'tl_amount': Formater.formatAmountShow(row[7]),
- 'py_count': Formater.formatCountShow(row[8]),
- 'py_amount': Formater.formatAmountShow(row[9]),
- 'ck_count': Formater.formatCountShow(-(row[10] or 0)),
- 'ck_amount': Formater.formatAmountShow(-(row[11] or 0)),
- 'th_count': Formater.formatCountShow(-(row[12] or 0)),
- 'th_amount': Formater.formatAmountShow(-(row[13] or 0)),
- 'pk_count': Formater.formatCountShow(-(row[14] or 0)),
- 'pk_amount': Formater.formatAmountShow(-(row[15] or 0)),
- 'in_count': Formater.formatCountShow(row[16]),
- 'in_amount': Formater.formatAmountShow(row[17]),
- 'out_count': Formater.formatCountShow(-(row[18] or 0)),
- 'out_amount': Formater.formatAmountShow(-(row[19] or 0))
- }
- else:
- total = 0
- more = {
- 'prev_count': 0,
- 'prev_amount': 0,
- 'remain_count': 0,
- 'remain_amount':0,
- 'rk_count': 0,
- 'rk_amount': 0,
- 'tl_count': 0,
- 'tl_amount': 0,
- 'py_count': 0,
- 'py_amount': 0,
- 'ck_count': 0,
- 'ck_amount':0,
- 'th_count': 0,
- 'th_amount': 0,
- 'pk_count': 0,
- 'pk_amount': 0,
- 'in_count': 0,
- 'in_amount': 0,
- 'out_count': 0,
- 'out_amount':0
- }
- data = []
- cursor.execute(sql)
- row = cursor.fetchone()
- while row:
- prev_avg = 0
- in_avg = 0
- out_avg = 0
- remain_avg = 0
- if row[6]:
- prev_avg = row[7] / row[6]
- if row[7]:
- in_avg = row[8] / row[7]
- if row[15]:
- out_avg = row[16] / row[15]
- if row[5]:
- remain_avg = row[6] / row[5]
- item = {
- 'product_name': row[0],
- 'product_model': row[1],
- 'unit': row[2],
- 'prev_count': Formater.formatCountShow(row[3]),
- 'prev_avg': Formater.formatPriceShow(prev_avg),
- 'prev_amount': Formater.formatAmountShow(row[4]),
- 'in_count': Formater.formatCountShow(row[7]),
- 'in_avg': Formater.formatPriceShow(in_avg),
- 'in_amount': Formater.formatAmountShow(row[8]),
- 'rk_count': Formater.formatCountShow(row[9]),
- 'rk_amount': Formater.formatAmountShow(row[10]),
- 'tl_count': Formater.formatCountShow(row[11]),
- 'tl_amount': Formater.formatAmountShow(row[12]),
- 'py_count': Formater.formatCountShow(row[13]),
- 'py_amount': Formater.formatAmountShow(row[14]),
- 'out_count': Formater.formatCountShow(-(row[15] or 0)),
- 'out_avg': Formater.formatPriceShow(out_avg),
- 'out_amount': Formater.formatAmountShow(-(row[16] or 0)),
- 'ck_count': Formater.formatCountShow(-(row[17] or 0)),
- 'ck_amount': Formater.formatAmountShow(-(row[18] or 0)),
- 'th_count': Formater.formatCountShow(-(row[19] or 0)),
- 'th_amount': Formater.formatAmountShow(-(row[20] or 0)),
- 'pk_count': Formater.formatCountShow(-(row[21] or 0)),
- 'pk_amount': Formater.formatAmountShow(-(row[22] or 0)),
- 'remain_count': Formater.formatCountShow(row[5]),
- 'remain_avg': Formater.formatPriceShow(remain_avg),
- 'remain_amount': Formater.formatAmountShow(row[6]),
- }
- data.append(item)
- row = cursor.fetchone()
- return data, total, more
- class WarehouseStock(models.Model):
- product = models.ForeignKey(ProductBase, verbose_name=u"产品", on_delete=models.PROTECT)
- warehouse = models.ForeignKey(Warehouse, verbose_name=u"仓别", on_delete=models.PROTECT)
- warehouse_place = models.CharField(max_length=200, verbose_name=u"库位", null=True)
- count = models.BigIntegerField(verbose_name=u"库存数量", default=0)
- amount = models.BigIntegerField(verbose_name=u"库存金额", default=0)
- amount2 = models.BigIntegerField(verbose_name=u"库存金额2", default=0)
- avg_cost_price = models.BigIntegerField(verbose_name=u"平均成本价", default=0)
- avg_cost_price2 = models.BigIntegerField(verbose_name=u"平均成本价2", default=0)
- last_entry_price = models.BigIntegerField(verbose_name=u"最新入库价", default=0)
- last_entry_time = models.DateTimeField(verbose_name=u"最后入库时间", null=True)
- last_deliverd_time = models.DateTimeField(verbose_name=u"最后出库时间", null=True)
- objects = WarehouseStockManager()
- @staticmethod
- def getByWarehouseAndProduct(warehouse,product):
- warehouse_stock = WarehouseStock.objects.filter(product=product, warehouse=warehouse).first()
- if not warehouse_stock:
- raise CustomError(u'仓别[%s]中没有[%s]的库存' % (warehouse.name, product.name))
- return warehouse_stock
- @staticmethod
- def createByWarehouse(warehouse):
- exist_products = WarehouseStock.objects.filter(warehouse_id=warehouse.id).values_list('product_id',flat=True)
- ids = ProductBase.objects.filter(Q(type=warehouse.type),~Q(id__in=exist_products)).values('id')
- if not ids:
- return
- sql = '''
- INSERT INTO product_warehouse_stock (
- product_id,
- warehouse_id,
- count,
- amount,
- amount2,
- avg_cost_price,
- avg_cost_price2,
- last_entry_price)
- SELECT
- id,
- %d,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0
- FROM
- product_base
- where id in (%s)
- ''' % (warehouse.id, ','.join([str(item['id']) for item in ids]))
- cur = connection.cursor()
- cur.execute(sql)
- @staticmethod
- def createByProduct(product):
- exist_warehouses = WarehouseStock.objects.filter(product_id=product.id).values_list('warehouse_id', flat=True)
- ids = Warehouse.objects.filter(Q(type=product.type), ~Q(id__in=exist_warehouses)).values('id')
- if not ids:
- return
- sql = '''
- INSERT INTO product_warehouse_stock (
- product_id,
- warehouse_id,
- count,
- amount,
- amount2,
- avg_cost_price,
- avg_cost_price2,
- last_entry_price)
- SELECT
- %d,
- id,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0
- FROM
- product_warehouse
- where id in (%s)
- ''' % (product.id, ','.join([str(item['id']) for item in ids]))
- cur = connection.cursor()
- cur.execute(sql)
- @staticmethod
- def removeStockByProduct(product):
- WarehouseStock.objects.filter(product=product).delete()
- @staticmethod
- def getPermissionByType(type, action):
- permissions = WarehouseStock.getPermissionMap()
- type = WarehouseStock.getValidType(type)
- return permissions[type][action]
- @staticmethod
- def getPermissionMap():
- permissions = {
- ProductBase.MATERIAL: {'view': 'warehouse.view_material_stock',
- 'export': 'warehouse.export_material_stock',
- 'log': 'warehouse.view_material_stock_log'
- },
- ProductBase.CONSUMABLE: {'view': 'warehouse.view_consumable_stock',
- 'export': 'warehouse.export_consumable_stock',
- 'log': 'warehouse.view_consumable_stock_log'
- },
- ProductBase.GOODS: {'view': 'warehouse.view_goods_stock',
- 'export': 'warehouse.export_goods_stock',
- 'log': 'warehouse.view_goods_stock_log'
- },
- }
- return permissions
- @staticmethod
- def getValidType(type):
- try:
- type = int(type)
- except:
- raise CustomError(u'错误的类型')
- types = (r[0] for r in ProductBase.TYPE_CHOICES)
- if type not in types:
- raise CustomError(u'无效的类型')
- return type
- class Meta:
- db_table = "product_warehouse_stock"
- verbose_name = u"成品仓别管理"
- ordering = ('-id',)
- default_permissions = ()
- permissions = (
- ("view_goods_warehouse", u"浏览"),
- ("add_goods_warehouse", u"添加"),
- ("delete_goods_warehouse", u"删除"),
- )
- class WarehouseRecord(models.Model):
- RK_ZJ = 0
- RK_CG = 1
- RK_PY = 2
- CK_ZJ = 3
- CK_XS = 4
- CK_PK = 5
- TH = 6
- TL = 7
- TYPE_CHOICES = (
- (RK_ZJ, u'直接入库'),
- (RK_CG, u'采购入库'),
- (RK_PY, u'盘盈入库'),
- (CK_ZJ, u'直接出库'),
- (CK_XS, u'销售出库'),
- (CK_PK, u'盘亏出库'),
- (TH, u'退货'),
- (TL, u'退料'),
- )
- type = models.IntegerField(choices=TYPE_CHOICES, verbose_name=u"类型")
- happen_time = models.DateTimeField(verbose_name=u"发生时间", default=timezone.now)
- product = models.ForeignKey(ProductBase, verbose_name=u"产品", on_delete=models.PROTECT)
- warehouse = models.ForeignKey(Warehouse, verbose_name=u"仓别", on_delete=models.PROTECT)
- count = models.BigIntegerField(verbose_name=u"数量")
- amount = models.BigIntegerField(verbose_name=u"总金额")
- amount2 = models.BigIntegerField(verbose_name=u"总金额2")
- cur_count = models.BigIntegerField(verbose_name=u"剩余数量", default=0)
- cur_amount = models.BigIntegerField(verbose_name=u"剩余金额", default=0)
- cur_amount2 = models.BigIntegerField(verbose_name=u"剩余金额2", default=0)
- @staticmethod
- def updateCurStockByProduct(warehouse_id, product_id):
- front_row = None
- rows = WarehouseRecord.objects.filter(warehouse_id=warehouse_id, product_id=product_id).order_by('happen_time','-id')
- for row in rows:
- WarehouseRecord.updateCurStockByFront(row, front_row)
- front_row = row
- @staticmethod
- def updateCurStockByFront(warehouse_record, front_row):
- if not front_row:
- warehouse_record.cur_count = warehouse_record.count
- warehouse_record.cur_amount = warehouse_record.amount
- warehouse_record.cur_amount2 = warehouse_record.amount2
- else:
- warehouse_record.cur_count = front_row.cur_count + warehouse_record.count
- warehouse_record.cur_amount = front_row.cur_amount + warehouse_record.amount
- warehouse_record.cur_amount2 = front_row.cur_amount2 + warehouse_record.amount2
- warehouse_record.save()
- @staticmethod
- def getPermissionByType(type, action):
- permissions = WarehouseRecord.getPermissionMap()
- type = WarehouseRecord.getValidType(type)
- return permissions[type][action]
- @staticmethod
- def getPermissionMap():
- permissions = {
- ProductBase.MATERIAL: {'view': 'product.view_material_stock_ledger',
- 'export': 'product.export_material_stock_ledger'
- },
- ProductBase.CONSUMABLE: {'view': 'product.view_consumable_stock_ledger',
- 'export': 'product.export_consumable_stock_ledger'
- },
- ProductBase.GOODS: {'view': 'product.view_goods_stock_ledger',
- 'export': 'product.export_goods_stock_ledger'
- },
- }
- return permissions
- @staticmethod
- def getValidType(type):
- try:
- type = int(type)
- except:
- raise CustomError(u'错误的类型')
- types = (r[0] for r in ProductBase.TYPE_CHOICES)
- if type not in types:
- raise CustomError(u'无效的类型')
- return type
- class Meta:
- db_table = "product_warehouse_record"
- verbose_name = u"退料查询"
- ordering = ('-id',)
- index_together = (
- 'type',
- 'happen_time',
- )
- default_permissions = ()
- permissions = (# 产品仓别出入库记录
- ("view_material_deliver_return_query", u"浏览"),
- ("export_material_deliver_return_query", u"导出"),
- ("print_material_deliver_return_query", u"打印"),
- )
- class WarehouseStockRecord(models.Model):
- product = models.ForeignKey(ProductBase, verbose_name=u"产品", on_delete=models.PROTECT)
- warehouse = models.ForeignKey(Warehouse, verbose_name=u"仓别", on_delete=models.PROTECT)
- supplier = models.ForeignKey(Supplier, verbose_name=u"供应商", null=True, on_delete=models.PROTECT)
- entry_time = models.DateTimeField(verbose_name=u"入库时间", default=timezone.now)
- entry_count = models.BigIntegerField(verbose_name=u"入库数量")
- entry_price = models.BigIntegerField(verbose_name=u"入库成本价")
- entry_price2 = models.BigIntegerField(verbose_name=u"入库成本价2")
- surplus_count = models.BigIntegerField(u'剩余数量')
- class Meta:
- db_table = "product_warehouse_stock_record"
- verbose_name = u"库存查询"
- ordering = ('-id',)
- index_together = (
- 'entry_time',
- 'surplus_count',
- )
- default_permissions = ()
- permissions = (# 产品仓别库存记录
- ("view_material_stock", u"浏览"),
- ("export_material_stock", u"导出"),
- ("view_material_stock_log", u"查看动态"),
- )
- class WarehouseRecordDetail(models.Model):
- warehouse_record = models.ForeignKey(WarehouseRecord, verbose_name=u"出入库记录",related_name='warehouse_record_detail_ref_warehouse_record', on_delete=models.PROTECT)
- warehouse_stock_record = models.ForeignKey(WarehouseStockRecord, verbose_name=u"库存记录", related_name='warehouse_record_detail_ref_stock_record',on_delete=models.PROTECT)
- count = models.BigIntegerField(verbose_name=u"数量")
- class Meta:
- db_table = "product_warehouse_record_detail"
- verbose_name = u"库存查询"
- ordering = ('-id',)
- default_permissions = ()
- permissions = (# 产品仓别出入库记录明细
- ("view_consumable_stock", u"浏览"),
- ("export_consumable_stock", u"导出"),
- ("view_consumable_stock_log", u"查看动态"),
- )
- class WarehouseBackMap(models.Model):
- back_detail = models.ForeignKey(WarehouseRecordDetail, verbose_name=u"退库明细", related_name="product_warehouse_back_map_ref_back_detail",on_delete=models.PROTECT)
- delivered_detail = models.ForeignKey(WarehouseRecordDetail, verbose_name=u"出库明细", related_name="product_warehouse_back_map_ref_delivered_detail",on_delete=models.PROTECT)
- back_count = models.BigIntegerField(verbose_name=u"退库数量")
- class Meta:
- db_table = "product_warehouse_back_map"
- verbose_name = u"库存查询"
- ordering = ('-id',)
- default_permissions = ()
- permissions = (# 产品仓别退库映射
- ("view_goods_stock", u"浏览"),
- ("export_goods_stock", u"导出"),
- ("view_goods_stock_log", u"查看动态"),
- )
- class Inventory(models.Model):
- MATERIAL = 0
- CONSUMABLE = 1
- GOODS = 2
- PRODUCT_TYPE_CHOICES = (
- (MATERIAL, u'原料'),
- (CONSUMABLE, u'耗材'),
- (GOODS, u'成品'),
- )
- SURPLUS = 0
- LOSS = 1
- TYPE_CHOICES = (
- (SURPLUS, u'盘盈'),
- (LOSS, u'盘亏'),
- )
- TYPE_PREFIX = ('MAPC', 'COPC', 'GOPC')
- no = models.CharField(max_length=50, verbose_name=u"盘存单号", editable=False)
- product_type = models.PositiveSmallIntegerField(choices=PRODUCT_TYPE_CHOICES, verbose_name=u"产品类型")
- warehouse = models.ForeignKey(Warehouse, verbose_name=u"仓别", on_delete=models.PROTECT)
- type = models.PositiveSmallIntegerField(choices=TYPE_CHOICES, verbose_name=u"单据类型")
- create_time = models.DateTimeField(verbose_name=u"创建时间", default=timezone.now)
- create_user = models.ForeignKey(User, verbose_name=u"创建人", on_delete=models.PROTECT, editable=False)
- department = models.ForeignKey(Department, verbose_name=u"创建部门", editable=False, on_delete=models.PROTECT)
- check_time = models.DateTimeField(verbose_name=u"审核时间", editable=False, blank=True, null=True)
- check_user = models.ForeignKey(User, related_name='inventory_checkuser', verbose_name=u"审核人", blank=True, null=True,on_delete=models.PROTECT)
- check_status = models.PositiveSmallIntegerField(choices=settings.CHECK_STATUS_CHOICES, verbose_name=u"审核状态",default=settings.DEFAULT)
- notes = models.CharField(max_length=500, verbose_name=u"备注", blank=True, null=True)
- total_count = models.BigIntegerField(verbose_name=u"合计数量", default=0)
- total_amount = models.BigIntegerField(verbose_name=u"合计金额", default=0)
- total_return_count = models.BigIntegerField(verbose_name=u"退货数量合计", default=0)
- total_return_amount = models.BigIntegerField(verbose_name=u"退货金额合计", default=0)
- total_deliver_count = models.BigIntegerField(verbose_name=u"出库数量合计", default=0)
- total_deliver_amount = models.BigIntegerField(verbose_name=u"出库金额合计", default=0)
- @staticmethod
- def getById(id):
- instance = Inventory.objects.filter(pk=id).first()
- if not instance:
- raise CustomError(u'未找到相应的盘存单')
- return instance
- def updateAmount(self):
- sum_count = 0
- sum_amount = 0
- sum_rows = InventoryDetail.objects.filter(main=self).aggregate(sum_count=Sum('count'), sum_amount=Sum('amount'))
- if sum_rows:
- sum_count = sum_rows['sum_count'] or 0
- sum_amount = sum_rows['sum_amount'] or 0
- self.total_count = sum_count
- self.total_amount = sum_amount
- self.save()
- def update_redundant(self):
- total_return_count = 0
- total_return_amount = 0
- total_deliver_count = 0
- total_deliver_amount = 0
- sum_row = InventoryDetail.objects.filter(main=self).aggregate(sum_return_count=Sum('return_count'),
- sum_return_amount=Sum('return_amount'),
- sum_deliver_count=Sum('deliver_count'),
- sum_deliver_amount=Sum('deliver_amount'))
- if sum_row:
- total_return_count = sum_row['sum_return_count'] or 0
- total_return_amount = sum_row['sum_return_amount'] or 0
- total_deliver_count = sum_row['sum_deliver_count'] or 0
- total_deliver_amount = sum_row['sum_deliver_amount'] or 0
- self.total_return_count = total_return_count
- self.total_return_amount = total_return_amount
- self.total_deliver_count = total_deliver_count
- self.total_deliver_amount = total_deliver_amount
- self.save()
- def save(self, *args, **kwargs):
- if self.no == None or self.no == '':
- prefix = Inventory.TYPE_PREFIX[self.product_type]
- now = timezone.now()
- rows = Inventory.objects.filter(create_time__gte=now.strftime('%Y-%m-%d')).order_by('-no')
- count = rows.count()
- if count == 0:
- self.no = '%s%s%03d' % (prefix, now.strftime('%Y%m%d'), count + 1)
- else:
- self.no = rows[0].no[:4] + str(int(rows[0].no[4:]) + 1)
- super(Inventory, self).save(*args, **kwargs)
- def getPermission(self, action):
- permissions = Inventory.getPermissionMap()
- return permissions[self.product_type][action]
- @staticmethod
- def getPermissionByType(type, action):
- permissions = Inventory.getPermissionMap()
- type = Inventory.getValidType(type)
- return permissions[type][action]
- @staticmethod
- def getPermissionMap():
- permissions = {
- Inventory.MATERIAL: {'view': 'warehouse.view_material_inventory',
- 'add': 'warehouse.add_material_inventory',
- 'check': 'warehouse.check_material_inventory',
- 'delete': 'warehouse.delete_material_inventory',
- 'export': 'warehouse.export_material_inventory',
- 'print': 'warehouse.print_material_inventory'
- },
- Inventory.CONSUMABLE: {'view': 'warehouse.view_consumable_inventory',
- 'add': 'warehouse.add_consumable_inventory',
- 'check': 'warehouse.check_consumable_inventory',
- 'delete': 'warehouse.delete_consumable_inventory',
- 'export': 'warehouse.export_consumable_inventory',
- 'print': 'warehouse.print_consumable_inventory'
- },
- Inventory.GOODS: {'view': 'goods.view_goods_inventory',
- 'add': 'goods.add_goods_inventory',
- 'check': 'goods.check_goods_inventory',
- 'delete': 'goods.delete_goods_inventory',
- 'export': 'goods.export_goods_inventory',
- 'print': 'goods.print_goods_inventory'
- },
- }
- return permissions
- @staticmethod
- def getValidType(type):
- try:
- type = int(type)
- except:
- raise CustomError(u'错误的盘存类型')
- types = (r[0] for r in Inventory.PRODUCT_TYPE_CHOICES)
- if type not in types:
- raise CustomError(u'无效的盘存类型')
- return type
- class Meta:
- db_table = "inventory"
- ordering = ('-id',)
- verbose_name = u"盘存管理"
- index_together = (
- 'create_time', 'check_time'
- )
- unique_together = (
- 'no',
- )
- default_permissions = ()
- permissions = (
- ("view_material_inventory", u"浏览"),
- ("add_material_inventory", u"添加"),
- ("check_material_inventory", u"审核"),
- ("delete_material_inventory", u"删除"),
- ("export_material_inventory", u"导出"),
- ("print_material_inventory", u"打印"),
- )
- class InventoryDetail(models.Model):
- main = models.ForeignKey(Inventory, related_name='inventory_details', on_delete=models.PROTECT)
- product = models.ForeignKey(ProductBase, verbose_name=u"产品", on_delete=models.PROTECT)
- warehouse_stock = models.ForeignKey(WarehouseStock, verbose_name=u'仓别库存', on_delete=models.PROTECT, blank=True, editable=False)
- count = models.BigIntegerField(verbose_name=u"数量", default=0)
- price = models.BigIntegerField(verbose_name=u"单价", default=0)
- amount = models.BigIntegerField(verbose_name=u"金额", default=0)
- warehouse_record = models.ForeignKey(WarehouseRecord,related_name='inventory_details_ref_warehouse_record', verbose_name=u'出入库记录', on_delete=models.PROTECT, blank=True, null=True)
- 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)
- 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)
- return_count = models.BigIntegerField(verbose_name=u"退货数量", default=0)
- return_amount = models.BigIntegerField(verbose_name=u"退货金额", default=0)
- deliver_count = models.BigIntegerField(verbose_name=u"出库数量", default=0)
- deliver_amount = models.BigIntegerField(verbose_name=u"出库金额", default=0)
- notes = models.CharField(max_length=200, verbose_name=u"备注", blank=True, null=True)
- class Meta:
- verbose_name = u"盘存管理"
- db_table = "inventory_detail"
- ordering = ("-id",)
- default_permissions = ()
- permissions = (# 盘存明细
- ("view_consumable_inventory", u"浏览"),
- ("add_consumable_inventory", u"添加"),
- ("check_consumable_inventory", u"审核"),
- ("delete_consumable_inventory", u"删除"),
- ("export_consumable_inventory", u"导出"),
- ("print_consumable_inventory", u"打印"),
- )
- @staticmethod
- def getById(id):
- instance = InventoryDetail.objects.filter(pk=id).first()
- if not instance:
- raise CustomError(u'未找到相应的盘存明细')
- return instance
|