# coding=utf-8

import traceback
import json

from django.conf import settings
from django.db.models import ProtectedError, Q, F, Sum
from django.utils import timezone
from django.views.decorators.csrf import csrf_exempt
from django.db import transaction, IntegrityError, connection

from apps.purchase.models import GodownEntryDetail
from libs.utils import strftime, strfdate
from apps.account.decorators import token_required, permission_required, valid_permission, isHasPermissions
from apps.base import Formater
from apps.customer.models import Customer
from apps.foundation.models import BizLog, Option
from apps.goods.models import Goods
from apps.material.filters import MaterialFilter, ConsumableFilter, DeliverFilter, InventoryFilter, DeliverReturnFilter
from apps.material.models import Material, Consumable, Deliver, DeliverDetail, DeliverReturn, DeliverReturnDetail
from apps.material.resources import MaterialResource, ConsumableResource, ConsumableImporter, MaterialImporter, \
    DeliverResource, DeliverDetailResource, InventoryResource, InventoryDetailResource, DeliverQueryResource, \
    DeliverReturnQueryResource
from apps.material.serializers import MaterialSerializer, ConsumableSerializer, DeliverSerializer, \
    DeliverDetailSerializer, InventorySerializer, InventoryDetailSerializer, DeliverReturnSerializer, \
    DeliverReturnViewSerializer, DeliverReturnDetailSerializer
from apps.product.models import ProductBase
from apps.product.serializers import ProductBaseSerializer
from apps.warehouse.models import WarehouseStock, Inventory, InventoryDetail, Warehouse,WarehouseRecord
from django.conf import settings
from apps.warehouse.biz import BizWarehouse, GetWarehouseSrockRecord
from apps.goods.models import GoodsGodownEntry,GoodsGodownEntryDetail
from apps.purchase.models import GodownEntry,GodownEntryDetail

from libs.http import JSONResponse, JSONError, DataGridJSONResponse
from libs import utils
from apps.exceptions import CustomError, ExportChange


@permission_required('material.view_material')
def material_list(request):
    f = MaterialFilter(request.GET, queryset=Material.objects.filter())
    rows, total = utils.get_page_data(request, f.qs)
    serializer = MaterialSerializer(rows, many=True)
    return DataGridJSONResponse(serializer.data, total)


@permission_required('material.export_material')
def material_export(request):
    f = MaterialFilter(request.GET, queryset=Material.objects.filter())
    serializer = MaterialSerializer(f.qs, many=True)
    export_data = ExportChange.dict_to_obj(serializer)
    export_data = MaterialResource().export(export_data)
    filename = utils.attachment_save(export_data)
    BizLog.objects.addnew(request.user, BizLog.EXPORT, u"导出原料单")
    return JSONResponse({'filename': filename})

@csrf_exempt
@permission_required('material.add_material')
def material_save(request):
    id = request.GET.get('id')
    data = json.loads(request.body)
    try:
        with transaction.atomic():
            product_base_id = None
            data['type'] = ProductBase.MATERIAL
            serializer = MaterialSerializer.factory(request.user, data, id)
            if serializer.instance:
                product_base_id = serializer.instance.product_base_id

            pb = ProductBaseSerializer.factory(request.user, data, product_base_id)
            pb = pb.validSave()
            data['product_base'] = pb.id
            serializer.validSave()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'保存失败！')
    return JSONResponse()

@permission_required('material.delete_material')
def material_delete(request):
    id = int(request.GET.get('id'))

    try:
        with transaction.atomic():
            material = Material.getById(id)
            product_base_id = material.product_base.id
            BizLog.objects.addnew(request.user, BizLog.DELETE, u"删除原料[%s]，id=%d" % (material.product_base.name, material.id))
            material.delete()
            WarehouseStock.removeStockByProduct(material.product_base)
            ProductBase.objects.filter(id=product_base_id).delete()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except ProtectedError:
        return JSONError(u'该原料已被使用，禁止删除！')
    except IntegrityError:
        return JSONError(u'该原料已被使用，禁止删除！')
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'删除失败！')

    return JSONResponse({})

@csrf_exempt
@token_required
def material_options(request):
    data = {}
    data['suggest'] = Material.SUGGEST_CHOICES
    return JSONResponse(data)


@csrf_exempt
@permission_required('material.import_material')
def material_import(request):
    file = request.FILES.get('excel_file')

    try:
        line = 2
        importer = MaterialImporter()
        excel_rows = importer.getExcelData(file)
        with transaction.atomic():
            for excel_row in excel_rows:
                try:
                    row = importer.validRow(excel_row)
                    option = Option.getByName(row[u'类别'], Option.MATERIAL_MODE)
                    data = {
                        'name': row[u'名称'],
                        'model': row[u'代码'],
                        'option_type': option.id,
                        'unit': row[u'单位'],
                        'standard': row[u'规格'],
                        'warehouse_place': row[u'库位'],
                        'htc_identification': row[u'产品标识'],
                        'purchase_suggest':  Material.getPurchaseSuggestValue(row[u'库存预警']),
                        'stock_upper_limit': row[u'库存上限'],
                        'stock_lower_limit': row[u'库存下限'],
                        'notes': row[u'备注'],
                        'enabled': 1,
                    }
                    data['type'] = ProductBase.MATERIAL
                    pb = ProductBaseSerializer.factory(request.user, data)
                    pb = pb.validSave()
                    data['product_base'] = pb.id
                    serializer = MaterialSerializer.factory(request.user, data)
                    serializer.validSave()
                except CustomError,e:
                    raise CustomError(u'第%d行:%s' % (line,e.get_error_msg()))
                except Exception,e:
                    raise CustomError(u'第%d行:%s' %(line,unicode(e)))

                line += 1
            BizLog.objects.addnew(request.user, BizLog.IMPORT, u"导入原料数据[%s]条" % (line - 2))
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'导入失败！')
    return JSONResponse()



@token_required
def material_select(request):
    param = request.GET.get('param')
    supplier = request.GET.get('supplier')
    warehouse = request.GET.get('warehouse')
    rows = Material.objects.filter(product_base__enabled=True)

    if param:
        rows = rows.filter(
            Q(product_base__name__icontains=param) | Q(product_base__model__icontains=param)
        )
    rows, total = utils.get_page_data(request, rows)
    data = []
    for row in rows:
        record_data = []
        if supplier and warehouse:
            record_data = GetWarehouseSrockRecord.getRecord(row.product_base.id, warehouse, supplier)

        item = {
            'id': row.id,
            'product_id': row.product_base.id,
            'name': row.product_base.name,
            'model': row.product_base.model,
            'option_type': row.product_base.option_type.name,
            'unit': row.product_base.unit,
            'warehouse_place': row.product_base.warehouse_place,
            'record_data': record_data,
            'standard': row.product_base.standard
        }
        data.append(item)
    return DataGridJSONResponse(data, total)


@permission_required('material.view_consumable')
def consumable_list(request):
    f = ConsumableFilter(request.GET, queryset=Consumable.objects.filter())
    rows, total = utils.get_page_data(request, f.qs)
    serializer = ConsumableSerializer(rows, many=True)
    return DataGridJSONResponse(serializer.data, total)


@permission_required('material.export_consumable')
def consumable_export(request):
    f = ConsumableFilter(request.GET, queryset=Consumable.objects.filter())
    serializer = ConsumableSerializer(f.qs, many=True)
    export_data = ExportChange.dict_to_obj(serializer)
    export_data = ConsumableResource().export(export_data)
    filename = utils.attachment_save(export_data)
    BizLog.objects.addnew(request.user, BizLog.EXPORT, u"导出耗材单")
    return JSONResponse({'filename': filename})

@csrf_exempt
@permission_required('material.add_consumable')
def consumable_save(request):
    id = request.GET.get('id')
    data = json.loads(request.body)
    try:
        with transaction.atomic():
            product_base_id = None
            data['type'] = ProductBase.CONSUMABLE
            serializer = ConsumableSerializer.factory(request.user, data, id)
            if serializer.instance:
                product_base_id = serializer.instance.product_base_id

            pb = ProductBaseSerializer.factory(request.user, data, product_base_id)
            pb = pb.validSave()
            data['product_base'] = pb.id
            serializer.validSave()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'保存失败！')
    return JSONResponse()

@permission_required('material.delete_consumable')
def consumable_delete(request):
    id = int(request.GET.get('id'))

    try:
        with transaction.atomic():
            consumable = Consumable.getById(id)
            product_base_id = consumable.product_base.id
            BizLog.objects.addnew(request.user, BizLog.DELETE, u"删除耗材[%s]，id=%d" % (consumable.product_base.name, consumable.id))
            consumable.delete()
            WarehouseStock.removeStockByProduct(consumable.product_base)
            ProductBase.objects.filter(id=product_base_id).delete()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except ProtectedError:
        return JSONError(u'该耗材已被使用，禁止删除！')
    except IntegrityError:
        return JSONError(u'该耗材已被使用，禁止删除！')
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'删除失败！')
    return JSONResponse({})

@csrf_exempt
@permission_required('material.import_consumable')
def consumable_import(request):
    file = request.FILES.get('excel_file')

    try:
        line = 2
        importer = ConsumableImporter()
        excel_rows = importer.getExcelData(file)
        with transaction.atomic():
            for excel_row in excel_rows:
                try:
                    row = importer.validRow(excel_row)
                    option = Option.getByName(row[u'类别'], Option.CONSUMABLE_MODE)
                    data = {
                        'name': row[u'名称'],
                        'model': row[u'代码'],
                        'option_type': option.id,
                        'unit': row[u'单位'],
                        'standard': row[u'规格'],
                        'warehouse_place': row[u'库位'],
                        'purchase_suggest': Material.getPurchaseSuggestValue(row[u'库存预警']),
                        'stock_upper_limit': row[u'库存上限'],
                        'stock_lower_limit': row[u'库存下限'],
                        'notes': row[u'备注'],
                        'enabled': 1,
                    }
                    data['type'] = ProductBase.CONSUMABLE
                    pb = ProductBaseSerializer.factory(request.user,data)
                    pb = pb.validSave()
                    data['product_base'] = pb.id
                    serializer = ConsumableSerializer.factory(request.user,data)
                    serializer.validSave()
                except CustomError,e:
                    raise CustomError(u'第%d行:%s' % (line,e.get_error_msg()))
                except Exception,e:
                    raise CustomError(u'第%d行:%s' %(line,unicode(e)))
                line += 1
            BizLog.objects.addnew(request.user, BizLog.IMPORT, u"导入耗材数据[%s]条" % (line - 2))
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'导入失败！')
    return JSONResponse()


@token_required
def consumable_select(request):
    param = request.GET.get('param')
    supplier = request.GET.get('supplier')
    warehouse = request.GET.get('warehouse')
    rows = Consumable.objects.filter(product_base__enabled=True)

    if param:
        rows = rows.filter(
            Q(product_base__name__icontains=param) | Q(product_base__model__icontains=param)
        )
    rows, total = utils.get_page_data(request, rows)
    data = []
    for row in rows:
        record_data = []
        if supplier and warehouse:
            record_data = GetWarehouseSrockRecord.getRecord(row.product_base.id, warehouse, supplier)
        item = {
            'id': row.id,
            'product_id': row.product_base.id,
            'name': row.product_base.name,
            'model': row.product_base.model,
            'option_type': row.product_base.option_type.name,
            'unit': row.product_base.unit,
            'warehouse_place': row.product_base.warehouse_place,
            'record_data': record_data,
            'standard': row.product_base.standard
        }
        data.append(item)
    return DataGridJSONResponse(data, total)


@token_required
def deliver_list(request):
    type = int(request.GET.get('type'))
    product_notes = request.GET.get('product_notes')
    try:
        valid_permission(request.user, Deliver.getPermissionByType(type, 'view'))
    except:
        return DataGridJSONResponse([], 0)
    warehouses_ids = Warehouse.getManagerWarehouses(request.user)
    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = Deliver.objects.filter(product_type=type, warehouse_id__in=warehouses_ids)
    rows = rows.filter(
        Q(department_id__in=department_ids) | Q(create_user_id__in=user_ids) | Q(create_user=request.user))
    if product_notes:
        g_ids = rows.values_list('id')
        d_ids = DeliverDetail.objects.filter(main_id__in=g_ids, notes__icontains=product_notes).values_list('main_id')
        rows = rows.filter(id__in=d_ids)
    f = DeliverFilter(request.GET, queryset=rows)
    total_row = f.qs.aggregate(total_count=Sum('total_count'), total_cost=Sum('total_cost'))
    more = {
        'total_count': Formater.formatCountShow(total_row['total_count']),
        'total_cost': Formater.formatAmountShow(total_row['total_cost'])
    }
    rows, total = utils.get_page_data(request, f.qs)
    serializer = DeliverSerializer(rows, many=True)
    return DataGridJSONResponse(serializer.data, total, more)


@csrf_exempt
@token_required
def deliver_export(request):
    id = request.GET.get('id')

    try:
        type = Deliver.getValidType(request.GET.get('type'))
        if type == Deliver.MATERIAL:
            perm = 'material.view_material_cost'
        elif type == Deliver.CONSUMABLE:
            perm = 'material.view_consumable_cost'
        is_show_cost = isHasPermissions(request.user, perm)
        if id:
            instance = Deliver.getById(id)
            valid_permission(request.user, instance.getPermission('export'))
            deliver_detail = DeliverDetail.objects.filter(main=instance)
            serializer = DeliverDetailSerializer(deliver_detail, many=True)
            export_data = ExportChange.dict_to_obj(serializer)
            export_data = DeliverDetailResource(is_show_cost).export(export_data)
            filename = utils.attachment_save(export_data)
            BizLog.objects.addnew(request.user, BizLog.EXPORT, u"导出原料/耗材出库单[%s]明细，id=%d" % (instance.no, instance.id))
        else:
            warehouses_ids = Warehouse.getManagerWarehouses(request.user)
            department_ids = request.user.getSubDepartmentIds()
            user_ids = request.user.getSubEmployeeIds()
            rows = Deliver.objects.filter(product_type=type, warehouse_id__in=warehouses_ids)
            rows = rows.filter(
                Q(department_id__in=department_ids) | Q(create_user_id__in=user_ids) | Q(create_user=request.user))
            f = DeliverFilter(request.GET, queryset=rows)
            serializer = DeliverSerializer(f.qs, many=True)
            valid_permission(request.user, Deliver.getPermissionByType(type, 'export'))
            export_data = ExportChange.dict_to_obj(serializer)
            export_data = DeliverResource(is_show_cost).export(export_data)
            filename = utils.attachment_save(export_data)
            BizLog.objects.addnew(request.user, BizLog.EXPORT, u"导出原料/耗材出库单")
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'导出失败！')
    return JSONResponse({'filename': filename})


@csrf_exempt
@token_required
def deliver_save(request):
    source = request.GET.get('source')
    id = request.GET.get('id')
    # detail_id:添加保存，出库直接保存，不需要添加明细detail_id=-1，添加明细保存默认detail_id=0，修改保存，detail_id=明细id
    detail_id = -1
    if source == 'touch':
        main_data = json.loads(request.body)['main']
        items_data = json.loads(request.body)['item']
        detail_id = json.loads(request.body)['detail']
    else:
        main_data = json.loads(request.POST.get('main'))
        items_data = json.loads(request.POST.get('item'))

    try:
        type = Deliver.getValidType(request.GET.get('type'))
        main_data['product_type'] = type
        with transaction.atomic():
            serializer = DeliverSerializer.factory(request.user, main_data, id)
            if serializer.instance and serializer.instance.status == settings.PASS:
                raise CustomError(u'该出库单已审核，禁止修改！')
            serializer = serializer.validSave()
            valid_permission(request.user, serializer.getPermission('add'))
            if source == 'touch' and detail_id >= 0:
                # 手机端保存，如果是修改，先删除要修改的明细
                DeliverDetail.objects.filter(id=int(detail_id)).delete()
                for item in items_data:
                    warehouse_stock = WarehouseStock.getByWarehouseAndProduct(serializer.warehouse,item['product_base'])
                    instance = DeliverDetail.objects.create(
                        main_id=id,
                        product_base_id=item['product_base'],
                        warehouse_stock=warehouse_stock,
                        warehouse_stockrecord_id=item['warehouse_stockrecord'],
                        total_cost=Formater.formatAmount(item['total_cost']),
                        count=Formater.formatCount(item['count']),
                        notes=item['notes'],
                    )

                    BizLog.objects.addnew(
                        request.user,
                        BizLog.INSERT,
                        u"APP添加原料/耗材出库明细[%s]，id=%d" % (instance.product_base.name, instance.id),
                        item
                    )
            else:
                DeliverDetail.objects.filter(main=serializer).delete()
                for item in items_data:
                    item['main'] = serializer.id
                    detail_serializer = DeliverDetailSerializer.factory(request.user, data=item)
                    detail_serializer.validSave()
            serializer.update_total()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'保存失败！')
    return JSONResponse(serializer.id)


@token_required
def deliver_delete(request):
    id = request.GET.get('id')
    try:
        with transaction.atomic():
            instance = Deliver.getById(id)
            valid_permission(request.user, instance.getPermission('delete'))
            if instance.status == settings.PASS:
                raise CustomError(u'该出库单已审核，禁止删除！')

            BizLog.objects.addnew(request.user, BizLog.DELETE, u"删除原料/耗材出库单[%s]，id=%d" % (instance.no, instance.id))
            DeliverDetail.objects.filter(main=instance).delete()
            instance.delete()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except ProtectedError:
        return JSONError(u'该出库单已被引用，禁止删除！')
    except IntegrityError:
        return JSONError(u'该出库单已被引用，禁止删除！')
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'删除失败！')

    return JSONResponse({})


@token_required
def deliver_detail(request):
    id = request.GET.get('id')
    if not id:
        return JSONResponse()
    instance = Deliver.getById(id)
    company = instance.department.getCompany()
    if instance.status == settings.PASS:
        status_text = u'已审核'
    else:
        status_text = u'待审核'
    main_data = {
        'id': instance.id,
        'warehouse_id': instance.warehouse_id,
        'warehouse_name': instance.warehouse.name,
        'receiver_id': instance.receiver_id,
        'receiver_name': instance.receiver and instance.receiver.name or '',
        'receiver_department_name': instance.receiver_department and instance.receiver_department.name or '',
        'goods_id': instance.goods_id,
        'goods_name': instance.goods and instance.goods.product_base.name or '',
        'create_user_name': instance.create_user.name,
        'create_time': Formater.formatStrTime(instance.create_time),
        'total_count': Formater.formatCountShow(instance.total_count),
        'total_cost': Formater.formatAmountShow(instance.total_cost),
        'status_text': status_text,
        'status': instance.status,
        'check_user_text': instance.check_user and instance.check_user.name or ' ',
        'check_time': Formater.formatStrTime(instance.create_time),
        'notes': instance.notes,
        'no': instance.no,
        'company': company.name
    }

    data = {
        'main_data': main_data,
        'items_data': []
    }
    detail_rows = DeliverDetail.objects.filter(main=instance)
    for detail_row in detail_rows:
        no = ''
        if detail_row.warehouse_stockrecord_id:
            godownentry = GodownEntryDetail.objects.filter(stock_record=detail_row.warehouse_stockrecord).first()
            if godownentry:
                no = godownentry.main.no
            else:
                no = InventoryDetail.objects.filter(
                    warehouse_stock_record=detail_row.warehouse_stockrecord).first().main.no
        record_data = GetWarehouseSrockRecord.getRecord(detail_row.product_base.id, instance.warehouse_id)
        item_data = {
            'detail_id': detail_row.id,
            'id': detail_row.product_base_id,
            'name': detail_row.product_base.name,
            'model': detail_row.product_base.model,
            'total_cost': Formater.formatAmountShow(detail_row.total_cost),
            'count': Formater.formatCountShow(detail_row.count),
            'entry_no': detail_row.warehouse_stockrecord_id,
            'no': no,
            'record_data': record_data,
            'warehouse_stock_count': Formater.formatCountShow(detail_row.warehouse_stock.count),
            'unit': detail_row.product_base.unit or '',
            'notes': detail_row.notes or ''
        }
        data['items_data'].append(item_data)

    return JSONResponse(data)

@token_required
def deliver_check(request):
    id = request.GET.get('id')
    try:
        with transaction.atomic():
            instance = Deliver.getById(id)
            valid_permission(request.user, instance.getPermission('check'))
            if instance.status == settings.PASS:
                raise CustomError(u'该出库单已审核')
            deliver_details = DeliverDetail.objects.filter(main=instance)
            for deliver_detail in deliver_details:
                warehouse_record = BizWarehouse.deliveredByStockRecord(WarehouseRecord.CK_ZJ,
                                                  deliver_detail.warehouse_stockrecord,
                                                  deliver_detail.count)
                deliver_detail.warehouse_record = warehouse_record
                deliver_detail.total_cost = -warehouse_record.amount
                deliver_detail.save()
            instance.update_total()
            instance.status = settings.PASS
            instance.check_user = request.user
            instance.check_time = timezone.now()
            BizLog.objects.addnew(
                request.user,
                BizLog.CHECK,
                u"审核原料/耗材出库[%s]，id=%d" % (instance.no, instance.id),
            )

            instance.save()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'审核失败')
    return JSONResponse({})

@token_required
def goods_select(request):
    goods = Goods.objects.filter(product_base__enabled=True)
    data = []
    for row in goods:
        item = {
            'id': row.id,
            'value': row.product_base.name
        }
        data.append(item)
    return JSONResponse(data)

@token_required
def get_amount(request):
    product_id = request.GET.get('product_id')
    warehouse = request.GET.get('warehouse')
    count = request.GET.get('count')
    try:
        product = ProductBase.getById(product_id)
        warehouse = Warehouse.getById(warehouse)
        amount, amount2, max_entry_price, max_entry_price2 = BizWarehouse.tryDelivered(product, warehouse, Formater.formatCount(count))
        data = {
            'total_cost': Formater.formatAmountShow(amount),
            'max_entry_price': Formater.formatPriceShow(max_entry_price)
        }
    except CustomError, e:
        traceback.print_exc()
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'获取成本合计失败！')
    return JSONResponse(data)

@token_required
def edit_warehouse(request):
    rows = json.loads(request.POST.get('data'))
    data = []
    try:
        for row in rows:
            count = Formater.formatCount(row['count'])
            product = ProductBase.getById(row['product_id'])
            warehouse = Warehouse.getById(row['warehouse'])
            amount, amount2, max_entry_price, max_entry_price2 = BizWarehouse.tryDelivered(product, warehouse, count)
            item = {
                'id': row['product_id'],
                'num': row['num'],
                'total_cost': Formater.formatAmountShow(amount),
                'max_entry_price': Formater.formatPriceShow(max_entry_price)
            }
            data.append(item)
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'获取成本合计失败！')
    return JSONResponse(data)

@token_required
def get_customer(request):
    goods = Customer.objects.filter()
    data = []
    for row in goods:
        item = {
            'id': row.id,
            'value': row.name
        }
        data.append(item)
    return JSONResponse(data)


@token_required
def inventory_list(request):
    product_type = int(request.GET.get('product_type'))
    product_name = request.GET.get('product_name')
    product_model = request.GET.get('product_model')
    product_notes = request.GET.get('product_notes')
    try:
        valid_permission(request.user, Inventory.getPermissionByType(product_type, 'view'))
    except:
        return DataGridJSONResponse([], 0)
    rows = Inventory.objects.filter(product_type=product_type)
    if product_name:
        ids = InventoryDetail.objects.filter(product__name__icontains=product_name).values_list('main_id')
        rows = rows.filter(id__in=ids)
    if product_model:
        ids = InventoryDetail.objects.filter(product__model__icontains=product_model).values_list('main_id')
        rows = rows.filter(id__in=ids)
    if product_notes:
        g_ids = rows.values_list('id')
        d_ids = InventoryDetail.objects.filter(main_id__in=g_ids, notes__icontains=product_notes).values_list('main_id')
        rows = rows.filter(id__in=d_ids)
    warehouses_ids = Warehouse.getManagerWarehouses(request.user)
    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = rows.filter(warehouse_id__in=warehouses_ids)
    rows = rows.filter(
        Q(department_id__in=department_ids) | Q(create_user_id__in=user_ids) | Q(create_user=request.user))
    f = InventoryFilter(request.GET, queryset=rows)
    total_row = f.qs.aggregate(sum_count=Sum('total_count'), sum_amount=Sum('total_amount'))
    more = {
        'sum_count': Formater.formatCountShow(total_row['sum_count']),
        'sum_amount': Formater.formatAmountShow(total_row['sum_amount'])
    }

    rows, total = utils.get_page_data(request, f.qs)
    serializer = InventorySerializer(rows, many=True)
    return DataGridJSONResponse(serializer.data, total, more)

@csrf_exempt
@token_required
def inventory_save(request):
    id = request.GET.get('id')
    data = json.loads(request.body)

    try:
        with transaction.atomic():
            pb = InventorySerializer.factory(request.user, data['order_data'], id)
            if pb.instance and pb.instance.check_status == settings.PASS:
                raise CustomError(u'该盘存单已审核')
            pb = pb.validSave()
            valid_permission(request.user, pb.getPermission('add'))
            InventoryDetail.objects.filter(main_id=pb.id).delete()
            for item in data['items']:
                item['main'] = pb.id
                pbd = InventoryDetailSerializer.factory(request.user, item)
                pbd.validSave()

            pb.updateAmount()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'保存失败')
    return JSONResponse({})


@csrf_exempt
@token_required
def inventory_delete(request):
    id = int(request.GET.get('id'))
    try:
        with transaction.atomic():
            order = Inventory.getById(id)
            valid_permission(request.user, order.getPermission('delete'))
            if order.check_status == settings.PASS:
                raise CustomError(u'该盘存单已审核,禁止删除')
            BizLog.objects.addnew(request.user, BizLog.DELETE, u"删除盘存单[%s]，id=%d" % (order.no, order.id))
            InventoryDetail.objects.filter(main__id=order.id).delete()
            order.delete()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except ProtectedError:
        return JSONError(u'该盘存单已被引用,禁止删除')
    except IntegrityError:
        return JSONError(u'该盘存单已被引用,禁止删除')
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'删除失败！')

    return JSONResponse({})


@csrf_exempt
@token_required
def inventory_detail(request):
    id = int(request.GET.get('id'))
    instance = Inventory.getById(id)
    company = Inventory.getById(id).department.getCompany()
    rows = InventoryDetail.objects.filter(main_id=id)
    if instance.check_status == settings.PASS:
        status_text = u'已审核'
    else:
        status_text = u'待审核'
    if instance.type == instance.SURPLUS:
        type_text = u'盘盈'
    elif instance.type == instance.LOSS:
        type_text = u'盘亏'
    else:
        type_text = ''
    main_data = {
        'id': instance.id,
        'warehouse_id': instance.warehouse_id,
        'warehouse_name': instance.warehouse.name,
        'create_user_name': instance.create_user.name,
        'create_time': Formater.formatStrTime(instance.create_time),
        'status': instance.check_status,
        'type_text': type_text,
        'status_text': status_text,
        'check_user_text': instance.check_user and instance.check_user.name or ' ',
        'check_time': Formater.formatStrTime(instance.create_time),
        'total_count': Formater.formatCountShow(instance.total_count),
        'total_amount': Formater.formatAmountShow(instance.total_amount),
        'notes': instance.notes or '',
        'no': instance.no,
        'company': company.name
    }
    data = {
        'company': company.name,
        'inventory_type':instance.type,
        'main_data': main_data,
        'items_data': [],
    }
    for row in rows:
        record_data = GetWarehouseSrockRecord.getRecord(row.product_id, row.main.warehouse_id)
        product_base = row.product

        if product_base.type == ProductBase.GOODS:
            g_row = GoodsGodownEntryDetail.objects.filter(stock_record_id=row.loss_stock_record_id).first()
        else:
            g_row = GodownEntryDetail.objects.filter(stock_record_id=row.loss_stock_record_id).first()

        if not g_row:
            g_row = InventoryDetail.objects.filter(warehouse_stock_record_id=row.loss_stock_record_id).first()

        item = {
            'id': row.id,
            'product_id': row.product_id,
            'loss_stock_record': row.loss_stock_record_id,
            'product_name': row.product.name,
            'unit': row.product.unit,
            'product_model': row.product.model,
            'warehouse_text': row.main.warehouse.name,
            'surplus_count': row.loss_stock_record and Formater.formatCountShow(row.loss_stock_record.surplus_count) or '',
            'count': Formater.formatCountShow(row.count),
            'price': Formater.formatPriceShow(row.price),
            'amount': Formater.formatAmountShow(row.amount),
            'type_text': row.product.get_type_display(),
            'option_type_text': row.product.option_type.name,
            'notes': row.notes or '',
            'entry_no': g_row and g_row.main.no or '',
            'entry_notes': g_row and g_row.main.notes or '',
            'record_data': record_data
        }
        data['items_data'].append(item)
    return JSONResponse(data)


@csrf_exempt
@token_required
def inventory_export(request):
    product_type = int(request.GET.get('product_type'))
    warehouses_ids = Warehouse.getManagerWarehouses(request.user)
    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = Inventory.objects.filter(product_type=product_type, warehouse_id__in=warehouses_ids)
    rows = rows.filter(
        Q(department_id__in=department_ids) | Q(create_user_id__in=user_ids) | Q(create_user=request.user))
    f = InventoryFilter(request.GET, queryset=rows)
    serializer = InventorySerializer(f.qs, many=True)
    valid_permission(request.user, Inventory.getPermissionByType(product_type, 'export'))
    export_data = ExportChange.dict_to_obj(serializer)
    perm = ''
    if product_type == Inventory.MATERIAL:
        perm = 'material.view_material_cost'
    elif product_type == Inventory.CONSUMABLE:
        perm = 'material.view_consumable_cost'
    is_show_cost = isHasPermissions(request.user, perm)
    export_data = InventoryResource(is_show_cost).export(export_data)
    filename = utils.attachment_save(export_data)
    BizLog.objects.addnew(request.user, BizLog.EXPORT, u"导出盘存单")
    return JSONResponse({'filename': filename})

@csrf_exempt
@token_required
def inventory_detail_export(request):
    id = request.GET.get('id')
    order = Inventory.getById(id)
    valid_permission(request.user, order.getPermission('export'))
    serializer = InventoryDetailSerializer(InventoryDetail.objects.filter(main_id=id), many=True)
    export_data = ExportChange.dict_to_obj(serializer)
    perm = ''
    if order.product_type == Inventory.MATERIAL:
        perm = 'material.view_material_cost'
    elif order.product_type == Inventory.CONSUMABLE:
        perm = 'material.view_consumable_cost'
    is_show_cost = isHasPermissions(request.user, perm)
    export_data = InventoryDetailResource(is_show_cost).export(export_data)
    filename = utils.attachment_save(export_data)
    BizLog.objects.addnew(request.user, BizLog.EXPORT, u"导出盘存明细单")
    return JSONResponse({'filename': filename})


@csrf_exempt
@token_required
def inventory_check(request):
    id = int(request.GET.get('id'))
    try:
        with transaction.atomic():
            order = Inventory.getById(id)
            valid_permission(request.user, order.getPermission('check'))
            if order.check_status == settings.PASS:
                raise CustomError(u'该盘存单已审核,不允许重复操作')

            d_rows = InventoryDetail.objects.filter(main_id=id)
            if order.type == Inventory.SURPLUS:
                for d_row in d_rows:
                    stock_record = BizWarehouse.entry(WarehouseRecord.RK_PY, d_row.product, d_row.main.warehouse, None, d_row.count, d_row.price, d_row.price)
                    d_row.warehouse_stock_record = stock_record
                    d_row.save()
            else:
                for d_row in d_rows:
                    warehouse_record = BizWarehouse.deliveredByStockRecord(WarehouseRecord.CK_PK, d_row.loss_stock_record, d_row.count)

                    if warehouse_record.count != 0:
                        d_row.price = warehouse_record.amount / warehouse_record.count
                    d_row.amount = -warehouse_record.amount
                    d_row.warehouse_record = warehouse_record
                    d_row.save()

                order.updateAmount()

            order.check_status = settings.PASS
            order.check_user = request.user
            order.check_time = timezone.now()
            order.save()

            BizLog.objects.addnew(
                request.user,
                BizLog.CHECK,
                u"审核盘存单[%s]，id=%d" % (order.no, order.id),
            )

    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'审核失败！')

    return JSONResponse({})


@token_required
def deliver_query_list(request):# 原料耗材出库查询
    try:
        valid_permission(request.user, getPermissionByType(int(request.GET.get('type')), 'view'))
    except:
        return DataGridJSONResponse([], 0)
    rows = get_filter_data(request)
    total_row = rows.aggregate(total_count1=Sum('deliver_detail_ref_warehouse_record__count'),
                               total_count2=Sum('inventory_details_ref_warehouse_record__count'),
                               total_cost1=Sum('deliver_detail_ref_warehouse_record__total_cost'),
                               total_cost2=Sum('inventory_details_ref_warehouse_record__amount'),
                               return_count=Sum('deliver_detail_ref_warehouse_record__return_count'),
                               return_cost=Sum('deliver_detail_ref_warehouse_record__return_cost'))
    more = {
        'total_count': Formater.formatCountShow((total_row['total_count1'] or 0) + (total_row['total_count2'] or 0)),
        'total_cost': Formater.formatAmountShow((total_row['total_cost1'] or 0) + (total_row['total_cost2'] or 0)),
        'return_count': Formater.formatCountShow(total_row['return_count']),
        'return_cost': Formater.formatAmountShow(total_row['return_cost']),
    }
    rows, total = utils.get_page_data(request, rows)
    data = get_deliver_query_data(rows)
    return DataGridJSONResponse(data, total, more)

@token_required
def deliver_query_export(request):
    type = int(request.GET.get('type'))
    try:
        valid_permission(request.user, getPermissionByType(type, 'export'))
        rows = get_filter_data(request)
        data = get_deliver_query_data(rows)
        export_data = ExportChange.dict_to_obj2(data)
        if type == ProductBase.MATERIAL:
            perm = 'material.view_material_cost'
        elif type == ProductBase.CONSUMABLE:
            perm = 'material.view_consumable_cost'
        is_show_cost = isHasPermissions(request.user, perm)
        export_data = DeliverQueryResource(is_show_cost).export(export_data)
        filename = utils.attachment_save(export_data)
        BizLog.objects.addnew(request.user, BizLog.EXPORT, u"导出出库查询")
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'导出出库查询失败！')
    return JSONResponse({'filename': filename})


@token_required
def deliver_query_detail(request):
    rows = get_filter_data(request)
    data = get_deliver_query_data(rows)
    return JSONResponse(data)

def get_filter_data(request):
    product_type = int(request.GET.get('type'))
    happen_time = request.GET.get('happen_time')
    no = request.GET.get('no')
    goods = request.GET.get('goods')
    receiver = request.GET.get('receiver')
    name = request.GET.get('name')
    model = request.GET.get('model')
    type = request.GET.get('deliver_type')
    notes = request.GET.get('notes')
    warehouse = request.GET.get('warehouse')
    create_user = request.GET.get('create_user')
    rows = WarehouseRecord.objects.filter(product__type=product_type, type__in=[3,4,5]).order_by('-id')
    if happen_time:
        happen_time_begin = happen_time.split(' - ')[0]
        happen_time_end = happen_time.split(' - ')[1] + ' 23:59:59'
        rows = rows.filter(happen_time__gt=happen_time_begin, happen_time__lt=happen_time_end)
    if no:
        rows = rows.filter(Q(deliver_detail_ref_warehouse_record__main__no__icontains=no) | Q(
            inventory_details_ref_warehouse_record__main____no__icontains=no))
    if notes:
        rows = rows.filter(Q(deliver_detail_ref_warehouse_record__notes__icontains=notes) | Q(
            inventory_details_ref_warehouse_record__notes__icontains=notes))
    if receiver:
        rows = rows.filter(deliver_detail_ref_warehouse_record__main__receiver__name__icontains=receiver)
    if goods:
        rows = rows.filter(deliver_detail_ref_warehouse_record__main__goods__product_base__name__icontains=goods)
    if create_user:
        rows = rows.filter(Q(deliver_detail_ref_warehouse_record__main__create_user__name__icontains=create_user) |
                           Q(inventory_details_ref_warehouse_record__main__create_user__name__icontains=create_user))
    if name:
        rows = rows.filter(product__name__icontains=name)
    if model:
        rows = rows.filter(product__model__icontains=model)
    if type:
        rows = rows.filter(type=type)
    if warehouse:
        rows = rows.filter(warehouse__name__icontains=warehouse)
    warehouses_ids = Warehouse.getManagerWarehouses(request.user)
    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = rows.filter(warehouse_id__in=warehouses_ids)
    rows = rows.filter(Q(
        Q(deliver_detail_ref_warehouse_record__main__department_id__in=department_ids)
        | Q(deliver_detail_ref_warehouse_record__main__create_user_id__in=user_ids)
        | Q(deliver_detail_ref_warehouse_record__main__create_user=request.user)) | Q(
        Q(inventory_details_ref_warehouse_record__main__department_id__in=department_ids)
        | Q(inventory_details_ref_warehouse_record__main__create_user_id__in=user_ids)
        | Q(inventory_details_ref_warehouse_record__main__create_user=request.user)
    ))
    return rows

def get_deliver_query_data(rows):
    rows = rows.values(
        'id',
        'type',
        'product__name',
        'product__model',
        'product__unit',
        'product__type',
        'product__warehouse_place',
        'inventory_details_ref_warehouse_record__count',
        'inventory_details_ref_warehouse_record__amount',
        'warehouse__name',
        'happen_time',
        'cur_count',
        'deliver_detail_ref_warehouse_record__count',
        'deliver_detail_ref_warehouse_record__total_cost',
        'deliver_detail_ref_warehouse_record__return_count',
        'deliver_detail_ref_warehouse_record__return_cost',
        'deliver_detail_ref_warehouse_record__notes',
        'deliver_detail_ref_warehouse_record__main__receiver__name',
        'deliver_detail_ref_warehouse_record__main__check_user__name',
        'deliver_detail_ref_warehouse_record__main__create_user__name',
        'deliver_detail_ref_warehouse_record__main__check_time',
        'deliver_detail_ref_warehouse_record__main__goods__product_base__name',
        'deliver_detail_ref_warehouse_record__main__no',
        'deliver_detail_ref_warehouse_record__warehouse_stockrecord__godown_entry_detail_ref_stock_record__main__no',

        'inventory_details_ref_warehouse_record__main__no',
        'inventory_details_ref_warehouse_record__main__check_user__name',
        'inventory_details_ref_warehouse_record__main__create_user__name',
        'inventory_details_ref_warehouse_record__notes'
        # 'inventory_details_ref_warehouse_record__loss_stock_record__godown_entry_detail_ref_stock_record__main__no',

    )
    data = []
    for row in rows:
        warehouse_record_type = WarehouseRecord.TYPE_CHOICES[row['type']][1]
        product_type_text = ProductBase.TYPE_CHOICES[row['product__type']][1]
        no = row['deliver_detail_ref_warehouse_record__main__no']
        check_user = row['deliver_detail_ref_warehouse_record__main__check_user__name']
        create_user = row['deliver_detail_ref_warehouse_record__main__create_user__name']
        receiver = row['deliver_detail_ref_warehouse_record__main__receiver__name']
        notes = row['deliver_detail_ref_warehouse_record__notes']
        name = row['product__name']
        model = row['product__model']
        unit = row['product__unit']
        entry_no = row['deliver_detail_ref_warehouse_record__warehouse_stockrecord__godown_entry_detail_ref_stock_record__main__no']
        warehouse_place = row['product__warehouse_place']
        count = Formater.formatCountShow(row['deliver_detail_ref_warehouse_record__count'])
        total_cost = Formater.formatAmountShow(row['deliver_detail_ref_warehouse_record__total_cost'])
        return_count = Formater.formatCountShow(row['deliver_detail_ref_warehouse_record__return_count'])
        return_cost = Formater.formatAmountShow(row['deliver_detail_ref_warehouse_record__return_cost'])

        if row['type'] == WarehouseRecord.CK_PK:
            no = row['inventory_details_ref_warehouse_record__main__no']
            # entry_no = row['inventory_details_ref_warehouse_record__loss_stock_record__godown_entry_detail_ref_stock_record__main__no']
            check_user = row['inventory_details_ref_warehouse_record__main__check_user__name']
            create_user = row['inventory_details_ref_warehouse_record__main__create_user__name']
            receiver = ''
            notes = row['inventory_details_ref_warehouse_record__notes']
            count = Formater.formatCountShow(row['inventory_details_ref_warehouse_record__count'])
            total_cost = Formater.formatAmountShow(row['inventory_details_ref_warehouse_record__amount'])
            return_count = '0.00'
            return_cost = '0.0000'
        item = {
            'id': row['id'],
            'type': warehouse_record_type,
            'product_type': product_type_text,

            'name': name,
            'model': model,
            'unit': unit,
            'warehouse_place': warehouse_place,

            'warehouse': row['warehouse__name'],
            'happen_time': Formater.formatStrTime(row['happen_time']),
            'cur_count': Formater.formatCountShow(row['cur_count']),

            'count': count,
            'total_cost': total_cost,
            'return_count': return_count,
            'return_cost': return_cost,

            'receiver': receiver,
            'check_user': check_user,
            'create_user': create_user,
            'notes': notes,
            'no': no,
            'entry_no': entry_no
        }
        data.append(item)
    return data

def getPermissionByType(type, action):
    permissions = {
        ProductBase.MATERIAL: {'view': 'plan.view_material_deliver_query',
                               'export': 'plan.export_material_deliver_query',
                               },
        ProductBase.CONSUMABLE: {'view': 'plan.view_consumable_deliver_query',
                                 'export': 'plan.export_consumable_deliver_query',
                               }
    }
    return permissions[type][action]

@token_required
def deliver_return_list(request):
    type = int(request.GET.get('type'))
    product_notes = request.GET.get('product_notes')
    try:
        valid_permission(request.user, DeliverReturn.getPermissionByType(type, 'view'))
    except:
        return DataGridJSONResponse([], 0)
    warehouses_ids = Warehouse.getManagerWarehouses(request.user)
    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = Deliver.objects.filter(product_type=type, status=settings.PASS,
                                                  warehouse_id__in=warehouses_ids)
    rows = rows.filter(
        Q(department_id__in=department_ids) | Q(create_user_id__in=user_ids) | Q(create_user=request.user))

    if product_notes:
        g_ids = rows.values_list('id')
        d_ids = DeliverDetail.objects.filter(main_id__in=g_ids, notes__icontains=product_notes).values_list('main_id')
        rows = rows.filter(id__in=d_ids)

    f = DeliverFilter(request.GET, queryset=rows)
    total_row = f.qs.aggregate(total_count=Sum('total_count'), total_cost=Sum('total_cost'),
                               return_count=Sum('return_count'), return_cost=Sum('return_cost'))
    more = {
        'total_count': Formater.formatCountShow(total_row['total_count']),
        'total_cost': Formater.formatAmountShow(total_row['total_cost']),
        'return_count': Formater.formatCountShow(total_row['return_count']),
        'return_cost': Formater.formatAmountShow(total_row['return_cost'])
    }
    rows, total = utils.get_page_data(request, f.qs)
    serializer = DeliverReturnViewSerializer(rows, many=True)
    return DataGridJSONResponse(serializer.data, total, more)

@token_required
def deliver_return_select_list(request):
    id = int(request.GET.get('id'))

    ids = DeliverReturnDetail.objects.filter(deliver_detail__main_id=id).values_list('main_id',flat=True)
    rows = DeliverReturn.objects.filter(id__in=ids)
    data = []
    for row in rows:
        data.append(row)
    serializer = DeliverReturnSerializer(data, many=True)
    return DataGridJSONResponse(serializer.data, rows.count())

@token_required
def deliver_return_detail(request):
    id = request.GET.get('id')
    ids = request.GET.get('ids')
    data = {
        'main_data': '',
        'deliver_data': [],
        'items_data': []
    }
    if ids:
        id_list = ids.split(',')
        deliver_returns = DeliverReturn.getByIds(id_list)
        for deliver_return in deliver_returns:
            deliver_data = {
                'no': deliver_return.no,
                'return_count': Formater.formatCountShow(deliver_return.return_count),
                'return_cost': Formater.formatAmountShow(deliver_return.return_cost),
                'reason': deliver_return.reason
            }
            data['deliver_data'].append(deliver_data)
    instance = Deliver.getById(id)
    company = instance.department.getCompany()
    main_data = {
        'warehouse_id': instance.warehouse_id,
        'warehouse_name': instance.warehouse.name,
        'receiver_id': instance.receiver_id,
        'receiver_name': instance.receiver.name,
        'goods_id': instance.goods_id,
        'goods_name': instance.goods and instance.goods.product_base.name ,
        'create_user_name': instance.create_user.name,
        'create_time': Formater.formatStrTime(instance.create_time),
        'total_count': Formater.formatCountShow(instance.total_count),
        'total_cost': Formater.formatAmountShow(instance.total_cost),
        'return_count': Formater.formatCountShow(instance.return_count),
        'return_cost': Formater.formatAmountShow(instance.return_cost),
        'notes': instance.notes,
        'no': instance.no,
        'company': company.name,
    }
    data['main_data'] = main_data
    detail_rows = DeliverDetail.objects.filter(main=instance)
    for detail_row in detail_rows:
        item_data = {
            'id': detail_row.id,
            'product_id': detail_row.product_base_id,
            'name': detail_row.product_base.name,
            'model': detail_row.product_base.model,
            'total_cost': Formater.formatAmountShow(detail_row.total_cost),
            'count': Formater.formatCountShow(detail_row.count),
            'cur_count': Formater.formatCountShow(detail_row.count - detail_row.return_count),
            'warehouse_stock_count': Formater.formatCountShow(detail_row.warehouse_stock.count),
            'unit':detail_row.product_base.unit or '',
            'notes':detail_row.notes or ''
        }
        data['items_data'].append(item_data)

    return JSONResponse(data)

@token_required
def deliver_return_save(request):
    id = request.GET.get('id')
    main_data = json.loads(request.POST.get('main'))
    items_data = json.loads(request.POST.get('item'))
    try:
        type = DeliverReturn.getValidType(request.GET.get('type'))
        main_data['product_type'] = type
        with transaction.atomic():
            serializer = DeliverReturnSerializer.factory(request.user, main_data)
            serializer = serializer.validSave()
            valid_permission(request.user, serializer.getPermission('add'))
            for item in items_data:
                item['main'] = serializer.id
                detail_serializer = DeliverReturnDetailSerializer.factory(request.user, data=item)
                detail_serializer = detail_serializer.validSave()
                detail_serializer.deliver_detail.updateReturn()
            serializer.update_total()
            deliver = Deliver.getById(id)
            deliver.update_return()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'保存失败！')
    return JSONResponse()


@token_required
def deliver_return_query_list(request):# 原料耗材退料查询
    try:
        valid_permission(request.user, getPermissionByType(int(request.GET.get('type')), 'view'))
    except:
        return DataGridJSONResponse([], 0)
    rows = get_return_filter_data(request)
    total_row = rows.aggregate(return_count=Sum('deliver_return_detail_ref_warehouse_record__return_count'),
                               return_cost=Sum('deliver_return_detail_ref_warehouse_record__return_cost'))
    more = {
        'return_count': Formater.formatCountShow(total_row['return_count']),
        'return_cost': Formater.formatAmountShow(total_row['return_cost']),
    }
    rows, total = utils.get_page_data(request, rows)
    data = get_deliver_return_query_data(rows)
    return DataGridJSONResponse(data, total, more)

@token_required
def deliver_return_query_export(request):
    type = int(request.GET.get('type'))
    try:
        valid_permission(request.user, getReturnPermissionByType(type, 'export'))
        rows = get_return_filter_data(request)
        data = get_deliver_return_query_data(rows)
        export_data = ExportChange.dict_to_obj2(data)
        if type == ProductBase.MATERIAL:
            perm = 'material.view_material_cost'
        elif type == ProductBase.CONSUMABLE:
            perm = 'material.view_consumable_cost'
        is_show_cost = isHasPermissions(request.user, perm)
        export_data = DeliverReturnQueryResource(is_show_cost).export(export_data)
        filename = utils.attachment_save(export_data)
        BizLog.objects.addnew(request.user, BizLog.EXPORT, u"导出原料/耗材退料查询")
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'导出原料/耗材退料查询失败！')
    return JSONResponse({'filename': filename})


@token_required
def deliver_return_query_detail(request):
    rows = get_return_filter_data(request)
    data = get_deliver_return_query_data(rows)
    return JSONResponse(data)

def get_return_filter_data(request):
    product_type = int(request.GET.get('type'))
    create_time = request.GET.get('create_time')
    warehouse = request.GET.get('warehouse')
    return_no = request.GET.get('return_no')
    no = request.GET.get('no')
    name = request.GET.get('name')
    model = request.GET.get('model')
    notes = request.GET.get('notes')
    reason = request.GET.get('reason')
    create_user = request.GET.get('create_user')
    rows = WarehouseRecord.objects.filter(product__type=product_type, type=7).order_by('-id')
    if create_time:
        create_time_begin = create_time.split(' - ')[0]
        create_time_end = create_time.split(' - ')[1] + ' 23:59:59'
        rows = rows.filter(deliver_return_detail_ref_warehouse_record__main__create_time__gt=create_time_begin,
                           deliver_return_detail_ref_warehouse_record__main__create_time__lt=create_time_end)
    if no:
        rows = rows.filter(deliver_return_detail_ref_warehouse_record__deliver_detail__main__no__icontains=no)
    if notes:
        rows = rows.filter(deliver_return_detail_ref_warehouse_record__notes__icontains=notes)
    if create_user:
        rows = rows.filter(deliver_return_detail_ref_warehouse_record__main__create_user__name__icontains=create_user)
    if warehouse:
        rows = rows.filter(deliver_return_detail_ref_warehouse_record__deliver_detail__main__warehouse__name__icontains=warehouse)
    if return_no:
        rows = rows.filter(
            deliver_return_detail_ref_warehouse_record__main__no__icontains=return_no)
    if reason:
        rows = rows.filter(deliver_return_detail_ref_warehouse_record__main__reason__icontains=reason)
    if name:
        rows = rows.filter(deliver_return_detail_ref_warehouse_record__product_base__name__icontains=name)
    if model:
        rows = rows.filter(deliver_return_detail_ref_warehouse_record__product_base__name__icontains=model)
    warehouses_ids = Warehouse.getManagerWarehouses(request.user)
    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = rows.filter(warehouse_id__in=warehouses_ids)
    rows = rows.filter(
        Q(deliver_return_detail_ref_warehouse_record__main__department_id__in=department_ids)
        | Q(deliver_return_detail_ref_warehouse_record__main__create_user_id__in=user_ids)
        | Q(deliver_return_detail_ref_warehouse_record__main__create_user=request.user))
    return rows

def get_deliver_return_query_data(rows):
    rows = rows.values(
        'id',
        'type',
        'deliver_return_detail_ref_warehouse_record__product_base__name',
        'deliver_return_detail_ref_warehouse_record__product_base__model',
        'deliver_return_detail_ref_warehouse_record__product_base__type',
        'deliver_return_detail_ref_warehouse_record__product_base__warehouse_place',
        'warehouse__name',
        'cur_count',
        'deliver_return_detail_ref_warehouse_record__return_count',
        'deliver_return_detail_ref_warehouse_record__return_cost',
        'deliver_return_detail_ref_warehouse_record__notes',
        'deliver_return_detail_ref_warehouse_record__main__create_user__name',
        'deliver_return_detail_ref_warehouse_record__main__create_time',
        'deliver_return_detail_ref_warehouse_record__main__reason',
        'deliver_return_detail_ref_warehouse_record__main__no',
        'deliver_return_detail_ref_warehouse_record__deliver_detail__main__no',
    )
    data = []
    for row in rows:
        warehouse_record_type = WarehouseRecord.TYPE_CHOICES[row['type']][1]
        product_type_text = ProductBase.TYPE_CHOICES[row['deliver_return_detail_ref_warehouse_record__product_base__type']][1]
        item = {
            'id': row['id'],
            'type': warehouse_record_type,
            'product_type': product_type_text,

            'name': row['deliver_return_detail_ref_warehouse_record__product_base__name'],
            'model': row['deliver_return_detail_ref_warehouse_record__product_base__model'],
            'warehouse_place': row['deliver_return_detail_ref_warehouse_record__product_base__warehouse_place'],

            'warehouse': row['warehouse__name'],
            'cur_count': Formater.formatCountShow(row['cur_count']),

            'create_user': row['deliver_return_detail_ref_warehouse_record__main__create_user__name'],
            'create_time': Formater.formatStrTime(row['deliver_return_detail_ref_warehouse_record__main__create_time']),
            'return_count': Formater.formatCountShow(row['deliver_return_detail_ref_warehouse_record__return_count']),
            'return_cost': Formater.formatAmountShow(row['deliver_return_detail_ref_warehouse_record__return_cost']),
            'reason': row['deliver_return_detail_ref_warehouse_record__main__reason'],
            'notes': row['deliver_return_detail_ref_warehouse_record__notes'],
            'return_no': row['deliver_return_detail_ref_warehouse_record__main__no'],

            'no': row['deliver_return_detail_ref_warehouse_record__deliver_detail__main__no']
        }
        data.append(item)
    return data

def getReturnPermissionByType(type, action):
    permissions = {
        ProductBase.MATERIAL: {'view': 'warehouse.view_material_deliver_return_query',
                               'export': 'warehouse.export_material_deliver_return_query',
                               },
        ProductBase.CONSUMABLE: {'view': 'purchase.view_consumable_deliver_return_query',
                                 'export': 'purchase.export_consumable_deliver_return_query',
                               }
    }
    return permissions[type][action]


@csrf_exempt
@token_required
def stock_log(request):
    keyword = request.GET.get('keyword')
    action = request.GET.get('action')
    happen_time = request.GET.get('happen_time')
    warehouse_id = request.GET.get('warehouse_id')
    product_id = request.GET.get('product_id')

    product_base = ProductBase.getById(int(product_id))
    valid_permission(request.user, WarehouseStock.getPermissionByType(product_base.type, 'log'))

    page, page_size = utils.get_page_info(request)

    product_id = int(product_id)
    warehouse_id = int(warehouse_id)
    where = ''

    if happen_time:
        happen_time = happen_time.split(' - ')
        where += " AND m.happen_time >= '%s' " % happen_time[0]
        where += " AND m.happen_time <= '%s' " % (happen_time[1] + ' 23:59:59')
    if action:
        where += ' AND m.type = %d' % int(action)

    if keyword and len(keyword) > 0:
        where += " AND (m.order_no like '%" + keyword + "%' " \
                 " or m.warehouse_name like '%" + keyword + "%' )"

    page_sql = ' LIMIT %d OFFSET %d ' % (page_size, page * page_size)
    sql = """SELECT * FROM(
    		  SELECT
    			pwr.type,
    			pwr.happen_time,
    			(CASE WHEN pwr.type in (3, 4)  THEN gd.`no`
    					WHEN pwr.type = 5 THEN iv.`no`
    					WHEN pwr.type = 6 THEN gr.`no`
    					WHEN pwr.type = 7 THEN gdr.`no`
    					else '' END) AS order_no,
    			(CASE WHEN pwr.type in (3, 4) THEN dd.total_cost
    					WHEN pwr.type = 5 THEN ind.price
    					WHEN pwr.type = 6 THEN gedr.price
    					WHEN pwr.type = 7 THEN gdrd.return_cost
    					else '' END) AS order_price,
    			pwr.count,
    			pwr.amount,
    			pwr.amount/pwr.count as cost,
    			pw.name as warehouse_name,
    			pwr.warehouse_id AS warehouse_id,
    			pwr.product_id AS product_id,
    			pwr.id AS id,
    			pwr.cur_count as cur_count,
    			pwr.cur_amount as cur_amount
    			FROM product_warehouse_record pwr LEFT JOIN
    			product_warehouse pw ON pwr.warehouse_id = pw.id LEFT JOIN
    			product_warehouse_stock pws ON pwr.product_id = pws.product_id AND pwr.warehouse_id=pws.warehouse_id LEFT JOIN
    			deliver_detail dd ON pwr.id=dd.warehouse_record_id LEFT JOIN
    			deliver gd ON dd.main_id=gd.id LEFT JOIN
    			deliver_detail_return gdrd ON pwr.id = gdrd.warehouse_record_id LEFT JOIN
    			deliver_return gdr ON gdrd.main_id = gdr.id LEFT JOIN
    			godown_entry_detail_return gedr ON pwr.id=gedr.warehouse_record_id LEFT JOIN
    			godown_entry_return gr ON gedr.main_id=gr.id LEFT JOIN
    			inventory_detail ind on ind.warehouse_record_id=pwr.id left join 
    			inventory iv ON iv.id=ind.main_id
    			WHERE pwr.warehouse_id = %(warehose)d AND  pwr.product_id = %(product)d AND pwr.type >=3
          UNION ALL
    		SELECT
    			pwr.type,
    			pwr.happen_time,
    			(CASE WHEN pwr.type in (0, 1) THEN ge.`no`
    			            WHEN pwr.type = 2 THEN iv.`no`
    						else '' END) AS order_no,
    			(CASE WHEN pwr.type in (0, 1) THEN ged.price
    			       WHEN pwr.type = 2 THEN ind.price
    					else '' END) AS order_price,
    			pwr.count,
    			pwr.amount,
    			pwr.amount/pwr.count as cost,
    			pw.name as warehouse_name,
    			pwr.warehouse_id AS warehouse_id,
    			pwr.product_id AS product_id,
    			pwr.id AS id,
    			pwr.cur_count as cur_count,
    			pwr.cur_amount as cur_amount
    			FROM product_warehouse_record pwr LEFT JOIN
    			product_warehouse pw ON pwr.warehouse_id = pw.id LEFT JOIN
    			product_warehouse_stock pws ON pwr.product_id = pws.product_id AND pwr.warehouse_id=pws.warehouse_id LEFT JOIN
    			product_warehouse_record_detail pwrd ON pwr.id=pwrd.warehouse_record_id LEFT JOIN
    			godown_entry_detail ged ON pwrd.warehouse_stock_record_id=ged.stock_record_id LEFT JOIN
    			godown_entry ge ON ged.main_id=ge.id LEFT JOIN
    			inventory_detail ind on ind.warehouse_stock_record_id = pwrd.warehouse_stock_record_id left join 
    			inventory iv ON iv.id = ind.main_id
    			WHERE pwr.warehouse_id = %(warehose)d AND  pwr.product_id = %(product)d AND (pwr.type <= 2)
    	        ) as m
                WHERE 1=1 %(where)s
                ORDER BY m.happen_time DESC
                """ % {'warehose': warehouse_id, 'product': product_id, 'where': where}

    sum_sql = """ SELECT
                        COUNT(0)
                        FROM
                        (%s) AS t
                        """ % sql
    items = []
    sql = '%s %s' % (sql, page_sql)
    cursor = connection.cursor()
    cursor.execute(sql)
    row = cursor.fetchone()
    total = 0
    while row:
        action_text = WarehouseRecord.TYPE_CHOICES[row[0]][1]
        text = ''
        if row[0] == WarehouseRecord.RK_ZJ:
            text = u'入库单[' + row[2] + u']'
        elif row[0] == WarehouseRecord.RK_CG:
            text = u'采购转入库,入库单[' + row[2] + u']'
        elif row[0] == WarehouseRecord.RK_PY:
            text = u'盘盈单[' + row[2] + u']'
        elif row[0] == WarehouseRecord.CK_ZJ:
            text = u'出库单[' + row[2] + ']'
        elif row[0] == WarehouseRecord.CK_XS:
            text = u'订单转出库,出库单[' + row[2] + u']'
        elif row[0] == WarehouseRecord.CK_PK:
            text = u'盘亏单[' + row[2] + u']'
        elif row[0] == WarehouseRecord.TH:
            text = u'退货单[' + row[2] + u']'
        elif row[0] == WarehouseRecord.TL:
            text = u'退料单[' + row[2] + u']'

        item = {
            'action': row[0],
            'action_text': action_text,
            'create_time': strftime(row[1]),
            'order_no': row[2],
            'count': Formater.formatCountShow(row[4]),
            'cost': Formater.formatPriceShow(row[6]),
            'price': Formater.formatPriceShow(row[3]),
            'warehouse_text': row[7],
            'text': text,
            'cur_count': Formater.formatCountShow(row[11]),
            'cur_amount': Formater.formatAmountShow(row[12]),
        }
        items.append(item)
        row = cursor.fetchone()

    cursor.execute(sum_sql)
    row = cursor.fetchone()
    if row:
        total = row[0]

    return DataGridJSONResponse(items, total)
