# coding=utf-8
import traceback
import json
import os
from collections import OrderedDict
from datetime import timedelta

from django.db.models import Q, Count, Sum, F
from apps.base import Formater
from _mysql_exceptions import IntegrityError
from django.db.models import ProtectedError
from django.utils import timezone
from django.views.decorators.csrf import csrf_exempt
from django.db import transaction, IntegrityError
from apps.warehouse.biz import BizWarehouse, GetWarehouseSrockRecord
from libs import utils
from django.conf import settings
from libs.http import JSONResponse, JSONError, DataGridJSONResponse
from apps.exceptions import CustomError, ExportChange
from apps.account.decorators import token_required, permission_required, valid_permission, isHasPermissions

from apps.account.models import User, Department
from apps.foundation.models import BizLog, Option
from apps.product.models import ProductBase
from apps.warehouse.models import WarehouseRecord, Warehouse, WarehouseStockRecord, WarehouseRecordDetail
from apps.warehouse.models import WarehouseStock, InventoryDetail
from apps.goods.models import GoodsGodownEntryDetail
from apps.material.models import DeliverDetail, DeliverReturnDetail
from apps.supplier.models import Supplier
from apps.config.models import Config

from apps.finance.serializers import FinanceIncomeSerializer, dbFinanceIncome
from apps.purchase.filters import PurchasePlanFilter, PurchaseOrderFilter, PurchasePriceFilter, GodownEntryFilter, \
    PurchasePaymentFilter, PurchaseOrderDetailFilter, GodownEntryReturnFilter, GodownEntryReturnDetailFilter, PurchasePriceExportFilter
from apps.purchase.models import PurchasePlan, PurchasePlanDetail, PurchaseOrder, PurchaseOrderDetail, PurchasePrice, \
    GodownEntryReturn, GodownEntryReturnDetail, PurchaseInvoiceImage, PurchasePay
from apps.purchase.resources import GodownEntryResource, GodownEntryDetailResource, GodownEntryImporter, \
    PurchasePlanResource, PurchasePlanDetailResource, PurchaseOrderResource, PurchaseOrderDetailResource, \
    PurchasePaymentResource, PurchasePaymentDetailResource, PurchaseInvoiceResource, GodownEntryQueryResource, \
    GodownEntryReturnResource, GodownEntryReturnDetailResource, GodownEntryReturnQueryResource, PurchasePlanImporter, PurchasePriceResource
from apps.purchase.serializers import PurchaseUser, GodownEntryDetail, GodownEntry, PurchasePaymentDetail, \
    PurchasePayment, PurchasePlanSerializer, PurchasePlanDetailSerializer, PurchaseOrderDetailSerializer, \
    PurchaseUserSerializer, PurchasePriceSerializer, GodownEntrySerializer, GodownEntryDetailSerializer, \
    PurchaseOrderSerializer, PurchasePaymentSerializer, GodownEntryReturnSerializer, GodownEntryReturnDetailSerializer, \
    PurchasePaySerializer


@csrf_exempt
@permission_required('purchase.view_purchase_plan')
def purchase_list(request):
    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = PurchasePlan.objects.filter(Q(create_user_id__in=user_ids) | Q(department_id__in=department_ids) | Q(create_user=request.user))
    f = PurchasePlanFilter(request.GET, queryset=rows)
    total_row = f.qs.aggregate(total_count=Sum('total_count'))
    more = {
        'total_count': Formater.formatCountShow(total_row['total_count'])
    }
    rows, total = utils.get_page_data(request, f.qs)
    serializer = PurchasePlanSerializer(rows, many=True)
    return DataGridJSONResponse(serializer.data, total, more)

@csrf_exempt
@permission_required('purchase.export_purchase_plan')
def purchase_export(request):
    id = request.GET.get('id')
    if id:
        production = PurchasePlan.getById(id)
        goods_rows = PurchasePlanDetail.objects.filter(purchase__id=production.id)
        serializer = PurchasePlanDetailSerializer(goods_rows, many=True)
        export_data = ExportChange.dict_to_obj(serializer)
        export_data = PurchasePlanDetailResource().export(export_data)
        filename = utils.attachment_save(export_data)
        return JSONResponse({'filename': filename})

    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = PurchasePlan.objects.filter(Q(create_user_id__in=user_ids) | Q(department_id__in=department_ids) | Q(create_user=request.user))
    f = PurchasePlanFilter(request.GET, queryset=rows)
    serializer = PurchasePlanSerializer(f.qs, many=True)
    export_data = ExportChange.dict_to_obj(serializer)
    export_data = PurchasePlanResource().export(export_data)
    filename = utils.attachment_save(export_data)
    return JSONResponse({'filename': filename})

@csrf_exempt
@permission_required('purchase.export_purchase_plan_price')
def purchase_price_export(request):
    id = request.GET.get('id')

    rows = PurchasePrice.objects.filter(purchase_detail__purchase_id=id,report=True)
    if rows.count() == 0:
        return JSONError(u'该采购单没有上传价格')
    f = PurchasePriceExportFilter(request.GET, queryset=rows)
    serializer = PurchasePriceSerializer(f.qs, many=True)
    export_data = ExportChange.dict_to_obj(serializer)
    export_data = PurchasePriceResource().export(export_data)
    filename = utils.attachment_save(export_data)
    return JSONResponse({'filename': filename})

@csrf_exempt
@permission_required('purchase.add_purchase_plan')
def purchase_import(request):
    file = request.FILES.get('excel_file')
    main_data = json.loads(request.POST.get('main_data'))

    try:
        line = 2
        importer = PurchasePlanImporter()
        excel_rows = importer.getExcelData(file)
        with transaction.atomic():
            serializer = PurchasePlanSerializer.factory(request.user, main_data)
            serializer = serializer.validSave()
            for excel_row in excel_rows:
                try:
                    row = importer.validRow(excel_row)
                    type = ProductBase.CONSUMABLE
                    if row[u'产品类别'] == u'原料':
                        type = ProductBase.MATERIAL

                    model = row[u'产品代码']
                    product_base = ProductBase.objects.filter(model=model, type=type)
                    if product_base.count() == 0:
                        raise CustomError(u'产品代码不存在')
                    elif product_base.count() > 1:
                        raise CustomError(u'产品代码重复，前往基础数据设置修改')
                    else:
                        product_base = product_base.first()

                    # quality_request = None
                    # if row[u'质量要求']:
                    #     quality_request = Option.getByName(row[u'质量要求'], Option.QUALITY_REQUEST).id

                    items_data = {}
                    items_data['purchase'] = serializer.id
                    items_data['quality_request_text'] = row[u'质量要求']
                    items_data['product'] = product_base.id
                    items_data['purchase_count'] = row[u'数量']
                    items_data['product_time'] = row[u'需求时间']
                    items_data['notes'] = row[u'备注']

                    detail_serializer = PurchasePlanDetailSerializer.factory(request.user, items_data)
                    detail_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
            serializer.updateTotalCount()
            BizLog.objects.addnew(request.user, BizLog.IMPORT, u"导入采购计划[%s]，id=%d" % (serializer.no, serializer.id))
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'导入失败！')
    return JSONResponse()

@csrf_exempt
@permission_required('purchase.add_purchase_plan')
def purchase_save(request):
    id = request.GET.get('id')
    purchase_base_data = json.loads(request.POST.get('items'))
    purchase_data = json.loads(request.POST.get('purchase'))
    try:
        with transaction.atomic():
            pb = PurchasePlanSerializer.factory(request.user, purchase_data, id)
            if pb.instance and pb.instance.status == settings.PASS:
                raise CustomError(u'审核通过,禁止修改')
            pb = pb.validSave()
            PurchasePlanDetail.objects.filter(purchase=pb).delete()
            for purchase_base in purchase_base_data:
                purchase_base['purchase'] = pb.id
                purchase_base['product'] = purchase_base['id']
                if 'product_time' in purchase_base and not purchase_base['product_time']:
                    purchase_base['product_time'] = None
                production = PurchasePlanDetailSerializer.factory(request.user, purchase_base)
                production.validSave()
            pb.updateTotalCount()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'保存失败')

    return JSONResponse()


@csrf_exempt
@permission_required('purchase.check_purchase_plan')
def purchase_check(request):
    id = request.GET.get('id')
    #c_type = request.GET.get('c_type')
    status = int(request.GET.get('status'))
    try:
        with transaction.atomic():
            purchase = PurchasePlan.getById(id)
            if status == settings.PASS:
                if purchase.status == settings.PASS:
                    raise CustomError(u'该采购计划已审核')
                purchase.status = settings.PASS
                purchase.check_user = request.user
                purchase.check_time = timezone.now()
                BizLog.objects.addnew(
                    request.user,
                    BizLog.CHECK,
                    u"审核采购计划[%s]，id=%d" % (purchase.name, purchase.id),
                )
            else:
                if purchase.status == settings.DEFAULT:
                    raise CustomError(u'该采购计划未审核')
                # if purchase.check_user2:
                #     raise CustomError(u'该采购计划已复核')
                is_report = purchase.isReport()
                is_compact = purchase.isCompart()
                if is_compact:
                    raise CustomError(u'已生成采购合同,禁止撤销审核')
                if is_report:
                    raise CustomError(u'已有上报的询价记录,禁止撤销审核')
                purchaseprices = PurchasePrice.objects.filter(purchase_detail__purchase=purchase)
                purchaseprices.delete()
                PurchaseUser.objects.filter(purchase=purchase).delete()
                purchase.status = settings.DEFAULT
                purchase.check_user = None
                purchase.check_time = None
                BizLog.objects.addnew(
                    request.user,
                    BizLog.CHECK,
                    u"撤消审核采购计划[%s]，id=%d" % (purchase.name, purchase.id),
                )
            purchase.save()
            # if c_type == 'check':
            #     # 审核
            #
            # elif c_type == 'check2':
            #     #复核
            #     if status == settings.PASS:
            #         if purchase.status == settings.DEFAULT:
            #             raise CustomError(u'该采购计划未审核')
            #         if purchase.check_user3:
            #             raise CustomError(u'该采购计划已批准')
            #
            #         purchase.check_user2 = request.user
            #         purchase.check_time2 = timezone.now()
            #         BizLog.objects.addnew(
            #             request.user,
            #             BizLog.CHECK,
            #             u"复核采购计划[%s]，id=%d" % (purchase.name, purchase.id),
            #         )
            #     else:
            #         if not purchase.check_user2:
            #             raise CustomError(u'该采购计划未复核')
            #         if purchase.check_user3:
            #             raise CustomError(u'该采购计划已批准')
            #
            #         purchase.check_user2 = None
            #         purchase.check_time2 = None
            #         BizLog.objects.addnew(
            #             request.user,
            #             BizLog.CHECK,
            #             u"撤消复核采购计划[%s]，id=%d" % (purchase.name, purchase.id),
            #         )
            # elif c_type == 'check3':
            #     #批准
            #     if status == settings.PASS:
            #         if not purchase.check_user2:
            #             raise CustomError(u'该采购计划未复核')
            #         if purchase.check_user3:
            #             raise CustomError(u'该采购计划已批准')
            #         purchase.status = status
            #         purchase.check_user3 = request.user
            #         purchase.check_time3 = timezone.now()
            #         BizLog.objects.addnew(
            #             request.user,
            #             BizLog.CHECK,
            #             u"批准采购计划[%s]，id=%d" % (purchase.name, purchase.id),
            #         )
            #     else:
            #         if not purchase.check_user3:
            #             raise CustomError(u'该采购计划未批准')
            #         is_report = purchase.isReport()
            #         is_compact = purchase.isCompart()
            #         if is_compact:
            #             raise CustomError(u'已生成采购合同,禁止撤销')
            #         if is_report:
            #             raise CustomError(u'已有上报的询价记录,禁止撤销')
            #
            #         purchase.status = settings.CHECKING
            #         purchase.check_user3 = None
            #         purchase.check_time3 = None
            #         BizLog.objects.addnew(
            #             request.user,
            #             BizLog.CHECK,
            #             u"撤消批准采购计划[%s]，id=%d" % (purchase.name, purchase.id),
            #         )

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


@csrf_exempt
@permission_required('purchase.delete_purchase_plan')
def purchase_delete(request):
    id = int(request.GET.get('id'))
    try:
        with transaction.atomic():
            purchase = PurchasePlan.getById(id)
            if purchase.status == settings.PASS:
                raise CustomError(u'该采购计划已审核,禁止删除')
            is_report = purchase.isReport()
            is_compact = purchase.isCompart()
            if is_compact:
                raise CustomError(u'已生成采购合同,禁止撤销审核')
            if is_report:
                raise CustomError(u'已有上报的询价记录,禁止撤销审核')
            BizLog.objects.addnew(request.user, BizLog.DELETE, u"删除采购计划[%s]，id=%d" % (purchase.name, purchase.id))
            PurchasePlanDetail.objects.filter(purchase__id=purchase.id).delete()
            purchase.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('purchase.view_purchase_plan')
def purchase_detail(request):
    id = request.GET.get('id')
    purchase = PurchasePlan.getById(id)
    company = purchase.department.getCompany()
    product_rows = PurchasePlanDetail.objects.filter(purchase__id=purchase.id)
    data = {
        'purchase': [],
        'product_items': []
    }
    if purchase.status == settings.PASS:
        status_text = u'已审核'
    else:
        status_text = u'待审核'
    production_item = {
        'name': purchase.name,
        'no': purchase.no,
        'company': company.name,
        'status_text': status_text,
        'notes': purchase.notes,
        'demend_user_id': purchase.demend_user and purchase.demend_user.id,
        'demend_user': purchase.demend_user and purchase.demend_user.name or '',
        'check_user': purchase.check_user and purchase.check_user.name or '',
        'check_time': Formater.formatStrTime(purchase.check_time),
        'create_time': Formater.formatStrTime(purchase.create_time),
    }
    data['purchase'].append(production_item)
    for row in product_rows:
        count = row.purchase_count - row.product.stock_count
        if count < 0:
            count = 0

        item = {
            'id': row.id,
            'product_id': row.product.id,
            'name': row.product.name,
            'model': row.product.model,
            'unit': row.product.unit,
            'standard': row.product.standard or '',
            'product_notes': row.product.notes or '',
            'quality_request_text': row.quality_request_text or '',
            'count': Formater.formatCountShow(count),
            'stock_count': Formater.formatCountShow(row.product.stock_count),
            'purchase_count': Formater.formatCountShow(row.purchase_count),
            'product_time': Formater.formatStrTimeS(row.product_time),
            'product_time1': Formater.formatStrDate(row.product_time),
            'notes': row.notes or ''
        }
        data['product_items'].append(item)
    return JSONResponse(data)


@csrf_exempt
@permission_required('purchase.add_purchase_user_plan')
def purchase_user_save(request):
    id = request.GET.get('id')
    touch = request.GET.get('touch')
    if touch:
        users = json.loads(request.body)['users']
    else:
        users = json.loads(request.POST.get('users'))

    users_list = []
    for user in users:
        users_list.append(user['id'])
    try:
        purchase_data = PurchasePlan.getById(id)
        purchase_details = purchase_data.getPurchaseDetails()
        # 对比采购员名单,多的添加,少的删除
        purchase_user_datas = PurchaseUser.objects.filter(purchase=purchase_data).values_list('purchase_user_id',flat=True)
        purchase_user_adds = [val for val in users_list if val not in purchase_user_datas]

        purchase_user_deletes = []
        report_users = PurchasePrice.objects.filter(purchase_detail__purchase=purchase_data,report=True).values_list('purchase_user_id',flat=True).order_by('purchase_user_id').distinct()
        for val in purchase_user_datas:
            if val not in users_list and val not in report_users:
                purchase_user_deletes.append(val)

        with transaction.atomic():
            PurchasePrice.objects.filter(purchase_user__in=purchase_user_deletes, purchase_detail__purchase=purchase_data).delete()
            PurchaseUser.objects.filter(purchase=purchase_data, purchase_user__id__in=purchase_user_deletes).delete()
            for purchase_user_add in purchase_user_adds:
                purchase_user_data = {
                    'purchase': purchase_data.id,
                    'purchase_user': purchase_user_add,
                    }
                production = PurchaseUserSerializer.factory(request.user, purchase_user_data)
                production.validSave()
                for purchase_detail in purchase_details:
                    data = {
                        'purchase_detail': purchase_detail.id,
                        'purchase_user': purchase_user_add,
                        'report': False,
                        'price': 0,
                    }
                    item = PurchasePriceSerializer.factory(request.user, data)
                    item.validSave()
    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 purchase_table(request):
    id = request.GET.get('id')
    purchaseplan = PurchasePlan.getById(id)
    data = {
        'plan_details': [],
        'purchase_users': [],
        'purchase_prices':[]
    }

    purchasedetails = PurchasePlanDetail.objects.filter(purchase=purchaseplan)
    for purchasedetail in purchasedetails:
        item = {
            'id':purchasedetail.id,
            'name': purchasedetail.product.name,
            'model': purchasedetail.product.model,
            'unit': purchasedetail.product.unit,
            'count': Formater.formatCountShow(purchasedetail.purchase_count),
        }
        data['plan_details'].append(item)

    purchaseusers = PurchaseUser.objects.filter(purchase=purchaseplan)
    for purchaseuser in purchaseusers:
        item = {
            'id':purchaseuser.purchase_user.id,
            'name':purchaseuser.purchase_user.name,
            'plan_id':purchaseuser.purchase_id
        }
        data['purchase_users'].append(item)

    purchaseprices = PurchasePrice.objects.filter(purchase_detail__purchase=purchaseplan,report=True)
    for purchaseprice in purchaseprices:
        item = {
            'id': purchaseprice.id,
            'user_id': purchaseprice.purchase_user_id,
            'detail_id': purchaseprice.purchase_detail_id,
            'supplier': purchaseprice.supplier.name,
            'price': Formater.formatPriceShow(purchaseprice.price),
            'notes': purchaseprice.notes,
        }
        data['purchase_prices'].append(item)

    return JSONResponse(data)


@csrf_exempt
@permission_required('purchase.view_purchase_user_plan')
def purchase_price_list(request):
    f = PurchasePriceFilter(request.GET, queryset=PurchasePrice.objects.filter(
        Q(purchase_user=request.user) & Q(purchase_detail__is_compact=False)))
    rows, total = utils.get_page_data(request, f.qs)
    serializer = PurchasePriceSerializer(rows, many=True)
    return DataGridJSONResponse(serializer.data, total)

@csrf_exempt
@permission_required('purchase.add_purchase_price_plan')
def purchase_price_save(request):
    id = request.GET.get('id')
    data = json.loads(request.body)
    try:
        if 'tax_rate' in data and data['tax_rate'] == '':
            data['tax_rate'] = None
        purchase_price = PurchasePrice.getById(id)
        if purchase_price.report:
            raise CustomError(u'询价已上报,禁止录入')
        with transaction.atomic():
            production = PurchasePriceSerializer.factory(request.user, data, id)
            production.validSave()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'保存失败！')

    return JSONResponse()


@csrf_exempt
@permission_required('purchase.add_purchase_price_plan')
def purchase_price_report(request):
    try:
        with transaction.atomic():
            purchase_prices = PurchasePrice.objects.filter(purchase_user=request.user, supplier__isnull=False)
            purchase_price_ids = purchase_prices.values_list('id', flat=True)
            purchase_prices.update(report=True)
            BizLog.objects.addnew(
                request.user,
                BizLog.UPDATE,
                u"上报询价",
                purchase_price_ids
            )
    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 purchase_price_detail(request):
    id = request.GET.get('id')

    rows = PurchasePrice.objects.filter(purchase_detail__purchase_id=id, report=True)

    data = []
    for row in rows:
        item = {
            'id': row.id,
            'name': row.purchase_detail.product.name,
            'supplier_name': row.supplier.name,
            'user_name': row.purchase_user.name,
            'price': Formater.formatPriceShow(row.price),
        }
        data.append(item)
    return JSONResponse({'data': data})


@csrf_exempt
@permission_required('purchase.edit_purchase_price')
def purchase_price_edit_save(request):
    data = json.loads(request.POST.get('data'))
    try:
        with transaction.atomic():
           for item in data:
               order = PurchasePrice.objects.filter(id=int(item['id'])).first()
               if not order:
                   raise CustomError(u'未找到单据')

               order.price = Formater.formatPrice(item['price'])
               order.save()

           BizLog.objects.addnew(
               request.user,
               BizLog.UPDATE,
               u"修改询价",
               order.purchase_detail.purchase.no
           )
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'保存失败')
    return JSONResponse({})

@csrf_exempt
@permission_required('purchase.view_purchase_order')
def purchase_order_list(request):
    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = PurchaseOrder.objects.filter(Q(create_user_id__in=user_ids) | Q(department_id__in=department_ids) | Q(create_user=request.user))
    f = PurchaseOrderFilter(request.GET, queryset=rows)
    total_row = f.qs.aggregate(sum_count=Sum('count'), sum_amount=Sum('amount'))
    more = {
        'sum_count': Formater.formatCountShow(total_row['sum_count']),
        'sum_amount': Formater.formatAmountShowWithTwoDecimalPlaces(total_row['sum_amount'])
    }

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

@csrf_exempt
@permission_required('purchase.export_purchase_order')
def purchase_order_export(request):
    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = PurchaseOrder.objects.filter(Q(create_user_id__in=user_ids) | Q(department_id__in=department_ids) | Q(create_user=request.user))
    f = PurchaseOrderFilter(request.GET, queryset=rows)
    serializer = PurchaseOrderSerializer(f.qs, many=True)
    export_data = ExportChange.dict_to_obj(serializer)
    export_data = PurchaseOrderResource().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('purchase.edit_purchase_order')
def purchase_order_edit(request):
    id = request.GET.get('id')
    data = json.loads(request.body)

    try:
        with transaction.atomic():

            order = PurchaseOrder.objects.filter(id=id).first()
            # if order.status > PurchaseOrder.DRAFT:
            if order.status != PurchaseOrder.DEFAULT:
                raise CustomError(u'该合同已审核，禁止修改')

            order.supplier_id = data['supplier']
            order.payment_type = data['payment_type']
            order.notes = data['notes']
            order.deliver_time = data['deliver_time']
            order.no = data['no']
            order.consignee_name = data['consignee_name']
            order.consignee_tel = data['consignee_tel']
            order.save()

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


@csrf_exempt
@permission_required('purchase.add_purchase_order | purchase.senior_purchase_order')
def purchase_order_save(request):
    id = request.GET.get('id')
    data = json.loads(request.body)

    try:
        with transaction.atomic():
            pb = PurchaseOrderSerializer.factory(request.user, data['order_data'], id)
            # if pb.instance and pb.instance.status == PurchaseOrder.TAKE_EFFECT:
            if pb.instance and pb.instance.status != PurchaseOrder.DEFAULT:
                raise CustomError(u'该合同已审核，禁止修改')
            pb = pb.validSave()
            PurchaseOrderDetail.objects.filter(main_id=pb.id).delete()
            for item in data['items']:
                item['main'] = pb.id
                pbd = PurchaseOrderDetailSerializer.factory(request.user, item)
                pbd.validSave()

            pb.updateAmount()

            if pb.plan:
                pb.plan.updateCompact()

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

@csrf_exempt
@permission_required('purchase.add_purchase_order')
def purchase_plan_to_order(request):
    touch = request.GET.get('touch')
    if touch:
        data = json.loads(request.body)['data']
    else:
        data = json.loads(request.POST.get('data'))

    try:
        with transaction.atomic():
            price_ids = [row['user_price_id'] for row in data]
            supplier_rows = PurchasePrice.objects.filter(id__in=price_ids).values('supplier_id','purchase_user_id','purchase_user__department_id').order_by('supplier_id','purchase_user_id','purchase_user__department_id').distinct()
            for supplier_row in supplier_rows:
                order = PurchaseOrder.objects.create(
                    supplier_id=supplier_row['supplier_id'],
                    create_user_id=supplier_row['purchase_user_id'],
                    department_id=supplier_row['purchase_user__department_id']
                )  # 生成采购合同

                purchase_plan = None
                price_rows = PurchasePrice.objects.filter(supplier_id=supplier_row['supplier_id'], purchase_user_id=supplier_row['purchase_user_id'], id__in=price_ids)
                if price_rows.count > 0:
                    purchase_plan = price_rows[0].purchase_detail.purchase

                for price_row in price_rows:
                    if price_row.purchase_detail.is_compact:
                        raise CustomError(u'[%s]上报的产品[%s]已生成合同，不允许再次生成' % (price_row.purchase_user.name, price_row.purchase_detail.product.name))
                    PurchaseOrderDetail.objects.create(
                        main=order,
                        quality_request_text=price_row.purchase_detail.quality_request_text,
                        count=price_row.purchase_detail.purchase_count,
                        price=price_row.price,
                        amount=price_row.purchase_detail.purchase_count * price_row.price,
                        product=price_row.purchase_detail.product
                    )

                order.no = order.order_no
                order.plan = purchase_plan
                order.save()

                order.updateAmount()

                if purchase_plan:
                    purchase_plan.updateCompact()

    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 purchase_order_detail(request):
    id = request.GET.get('id')
    source = request.GET.get('source')
    purchase_order = PurchaseOrder.getById(id)
    user = purchase_order.create_user
    company = purchase_order.department.getCompany()
    rows = PurchaseOrderDetail.objects.filter(main_id=id)
    create_time = purchase_order.create_time
    deliver_time = purchase_order.deliver_time

    if source:

        status_text = PurchaseOrder.STATUS_CHOICES[purchase_order.status][1]
        arrval_text = PurchaseOrder.ARRVAL_CHOICES[purchase_order.arrval][1]

        entries_list = []
        Godownentrys = GodownEntry.objects.filter(purchase_order=purchase_order)
        entries_list.extend([s[0] for s in Godownentrys.values_list('no')])
        entries_text = ','.join(entries_list)
        main_data = {
            'order_no': purchase_order.order_no,
            'no': purchase_order.no,
            'notes': purchase_order.notes,
            'supplier_text': purchase_order.supplier and purchase_order.supplier.name or '',
            'payment_type': purchase_order.payment_type,
            'count': Formater.formatCountShow(purchase_order.count),
            'amount': Formater.formatAmountShow(purchase_order.amount),
            'apply_amount': Formater.formatAmountShow(purchase_order.apply_amount),
            'status': purchase_order.status,
            'status_text': status_text,
            'arrval_text': arrval_text,
            'entries_text': entries_text,
            'check_user': purchase_order.check_user and purchase_order.check_user.name or '',
            'check_time': Formater.formatStrTime(purchase_order.check_time),
            'create_user': purchase_order.create_user and purchase_order.create_user.name or '',
            'create_time': Formater.formatStrTime(purchase_order.create_time),
            'deliver_time': Formater.formatStrTime(purchase_order.deliver_time),
            # 'check_user2': purchase_order.check_user2 and purchase_order.check_user2.name or '',
            # 'check_time2': Formater.formatStrTime(purchase_order.check_time2),
            # 'check_user3': purchase_order.check_user3 and purchase_order.check_user3.name or '',
            # 'check_time3': Formater.formatStrTime(purchase_order.check_time3),
            'consignee_name': purchase_order.consignee_name,
            'consignee_tel': purchase_order.consignee_tel,
        }
        data = {
            'main_data': main_data,
            'items_data': []
        }
    else:
        data = {
            'company': company.name,
            'tel': user.tel,
            'create_time': Formater.formatStrDate(create_time),
            'deliver_time': deliver_time,
            'items_data': []
        }
    for row in rows:
        g_rows = GodownEntryDetail.objects.filter(main__purchase_order_id=id, main__status=settings.PASS, product_base_id=row.product_id)
        arrval_date = ''
        arrval_nos = ''
        if g_rows:
            arrval_nos = ','.join([s[0] for s in g_rows.values_list('main__no')])
            arrval_date = ','.join([utils.strfdate(s[0]) for s in g_rows.values_list('main__check_time')])

        item = {
            'id': row.id,
            'product_id': row.product_id,
            'name': row.product.name,
            'model': row.product.model,
            'unit': row.product.unit,
            'standard': row.product.standard,
            'type_text': row.product.get_type_display(),
            'options_type_text': row.product.option_type.name,
            'type': row.product.type,
            'options_type': row.product.option_type_id,
            'quality_request_text': row.quality_request_text or '',
            'warehouse_place': row.product.warehouse_place,
            'count': Formater.formatCountShow(row.count),
            'arrval_count': Formater.formatCountShow(row.arrval_count),
            'price': Formater.formatPriceShow(row.price),
            'amount': Formater.formatAmountShowWithTwoDecimalPlaces(row.amount),
            'arrval_date': arrval_date,
            'arrval_nos': arrval_nos,
            'invoice_no': row.invoice_no or '',
            'avg_cost_price': Formater.formatPriceShow(row.product.avg_cost_price),
            'max_price': Formater.formatPriceShow(row.product.max_price),
            'min_price': Formater.formatPriceShow(row.product.min_price),
        }
        data['items_data'].append(item)
    return JSONResponse(data)


@csrf_exempt
@token_required
def select_purchase_order(request):
    no = request.GET.get('no')
    if not no:
        return JSONError(u'请输入合同单号！')

    # rows = PurchaseOrderDetail.objects.filter(main__no=no, main__status=PurchaseOrder.TAKE_EFFECT)
    rows = PurchaseOrderDetail.objects.filter(main__no=no, main__status=PurchaseOrder.PASS)
    if rows.count() == 0:
        return JSONError(u'合同单号不正确或该合同尚未审核！')
    if rows[0].main.apply_amount >= rows[0].main.amount:
        return JSONError(u'该合同已付款完毕！')
    result = {
          'order_id': rows[0].main.id,
          'apply_amount': Formater.formatAmountShow(rows[0].main.apply_amount),
          'amount': Formater.formatAmountShow(rows[0].main.amount),
          'data': []
    }
    for row in rows:
        item = {
            'id': row.id,
            'name': row.product.name,
            'model': row.product.model,
            'order_no': row.main.no,
            'supplier_name': row.main.supplier.name,
            'count': Formater.formatCountShow(row.count),
            'amount': Formater.formatAmountShow(row.amount),
        }
        result['data'].append(item)
    return JSONResponse(result)


@csrf_exempt
@permission_required('purchase.delete_purchase_order')
def purchase_order_delete(request):
    id = int(request.GET.get('id'))
    try:
        with transaction.atomic():
            order = PurchaseOrder.getById(id)
            # if order.status != PurchaseOrder.DRAFT:
            if order.status != PurchaseOrder.DEFAULT:
                raise CustomError(u'该采购合同已审核, 不允许删除')

            # 删除发票图片
            image_rows = PurchaseInvoiceImage.objects.filter(order_detail__main_id=order.id)
            images_files = []
            for image_row in image_rows:
                images_files.append({'url': image_row.invoice_image})

            image_rows.delete()

            BizLog.objects.addnew(request.user, BizLog.DELETE, u"删除采购合同[%s]，id=%d" % (order.no, order.id))
            purchase = order.plan
            PurchaseOrderDetail.objects.filter(main=order).delete()
            order.delete()

            if purchase:
                purchase.updateCompact()

            try:
                for item in images_files:
                    os.remove("%s/%s" % (settings.MEDIA_ROOT, item['url']))
            except:
                pass
    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('purchase.check_purchase_order')
def purchase_order_check(request):
    id = request.GET.get('id')
    status = int(request.GET.get('status'))
    try:
        with transaction.atomic():
            order = PurchaseOrder.getById(id)
            if status == PurchaseOrder.PASS:
                if order.status == PurchaseOrder.PASS:
                    raise CustomError(u'该采购合同已审核')
                if not order.no:
                    raise CustomError(u'该采购合同未填写合同号, 不允许审核')
                exist_rows = PurchaseOrder.objects.filter(Q(no=order.no), ~Q(id=id)).first()
                if exist_rows:
                    raise CustomError(u'该采购合同单号已存在')
                order.status = PurchaseOrder.PASS
                order.check_user = request.user
                order.check_time = timezone.now()
                BizLog.objects.addnew(
                    request.user,
                    BizLog.CHECK,
                    u"审核采购合同[%s]，id=%d" % (order.no, order.id),
                )
            else:
                if order.status == PurchaseOrder.DEFAULT:
                    raise CustomError(u'该采购合同尚未审核')
                g_row = GodownEntry.objects.filter(purchase_order=order).first()
                if g_row:
                    raise CustomError(u'该合同已存在入库单, 不允许撤销审核')
                pay = PurchasePayment.objects.filter(order=order).first()
                if pay:
                    raise CustomError(u'该合同已存在付款单, 不允许撤销审核')

                d_row = PurchaseOrderDetail.objects.filter(main=order, invoice_no__isnull=False, check_status=settings.PASS).first()
                if d_row:
                    raise CustomError(u'该合同已审核发票, 不允许撤销审核')
                order.status = PurchaseOrder.DEFAULT
                order.check_user = None
                order.check_time = None
                BizLog.objects.addnew(
                    request.user,
                    BizLog.CHECK,
                    u"采购合同取消审核[%s]，id=%d" % (order.no, order.id),
                )
            order.save()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'审核失败')
    return JSONResponse({})

@csrf_exempt
@permission_required('purchase.export_purchase_order')
def purchase_order_export_detail(request):
    id = request.GET.get('id')
    serializer = PurchaseOrderDetailSerializer(PurchaseOrderDetail.objects.filter(main_id=id), many=True)
    export_data = ExportChange.dict_to_obj(serializer)
    export_data = PurchaseOrderDetailResource().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('purchase.check_purchase_order')
def purchase_order_payment(request):
    # 简易模式，耗材、原料入库单付款，自动生成付款单，并自动审核。同时创建收支单
    id = request.GET.get('id') # 入库单id
    handing_amount = request.POST.get('handing_amount')
    handing_account = request.POST.get('handing_account')

    transport_account = request.POST.get('transport_account')
    transport_amount = request.POST.get('transport_amount')

    order_amount = Formater.formatAmount(request.POST.get('order_amount') or 0)
    order_account = request.POST.get('order_account')

    try:
        with transaction.atomic():
            godownentry_process = Config.getValue('godownentry_process')
            if godownentry_process != '1':
                raise CustomError('当前入库模式非简易模式，禁止付款！')
            godownEntry = GodownEntry.getById(id)
            if godownEntry.status != settings.PASS:
                raise CustomError('当前入库单未审核，禁止付款！')
            if godownEntry.product_type == GodownEntry.MATERIAL:
                type1 = dbFinanceIncome.MATERIAL_ENTRY_PAY
                type2 = dbFinanceIncome.MATERIAL_ENTRY_UNLOAD
                type3 = dbFinanceIncome.MATERIAL_ENTRY_FARE
            else:
                type1 = dbFinanceIncome.CONSUMABLE_ENTRY_PAY
                type2 = dbFinanceIncome.CONSUMABLE_ENTRY_UNLOAD
                type3 = dbFinanceIncome.CONSUMABLE_ENTRY_FARE

            if int(order_amount):
                # 简易流程下，如果使用了入库管理里面的付款按钮，自动生成付款单，创建付款明细
                if not order_account:
                    raise CustomError('请选择订单费用付款账户！')
                # 订单费用
                purchase_order = godownEntry.purchase_order
                payment = PurchasePayment.objects.filter(order=purchase_order).first()
                if payment:
                    # 再次付款
                    if payment.is_clear:
                        raise CustomError('当前入库单已结清，禁止付款！')
                    actual_amount = order_amount + payment.actual_amount
                    order_data = {
                                  'actual_amount': actual_amount,
                                  'is_clear': True if actual_amount >= payment.amount else False,
                                  }
                    pb = PurchasePaymentSerializer.factory(request.user, order_data, payment.id)
                else:
                    # 首次付款
                    order_data = {'order': purchase_order.id,
                                  'status': settings.PASS,
                                  'amount': purchase_order.amount,
                                  'apply_amount': purchase_order.apply_amount,
                                  'actual_amount': order_amount,
                                  'is_pay': True,
                                  'check_time': timezone.now(),
                                  'check_user': request.user.id,
                                  'is_clear': True if order_amount >= purchase_order.amount else False,
                                  }
                    pb = PurchasePaymentSerializer.factory(request.user, order_data)
                pb.validSave()
                payment = pb.instance
                purchase_order.updateApplyAmount()  # 更新合同单的申请金额
                # 创建付款明细
                data={
                    'main':payment.id,
                    'payment_type':order_account,
                    'actual_amount':order_amount,
                }
                pb = PurchasePaySerializer.factory(request.user, data)
                pb.validSave()

                income_data = {
                    'referer_no': purchase_order.no,
                    'type': type1,
                    'amount': -abs(float(Formater.formatAmountShow(order_amount))),
                    'account': order_account,
                    'check_status': settings.PASS,
                    'check_user': request.user.id,
                    'department': request.user.department_id,
                    'check_time': timezone.now(),
                    'notes': ''
                }
                income = FinanceIncomeSerializer.factory(request.user, income_data)
                income.validSave()

            if int(transport_amount):
                if not transport_account:
                    raise CustomError('请选择运输费用付款账户！')
                income_data = {
                    'referer_no': purchase_order.no,
                    'type': type3,
                    'amount': -abs(float(transport_amount)),
                    'account': transport_account,
                    'check_status': settings.PASS,
                    'check_user': request.user.id,
                    'department': request.user.department_id,
                    'check_time': timezone.now(),
                    'notes': ''
                }
                income = FinanceIncomeSerializer.factory(request.user, income_data)
                income.validSave()

            if int(handing_amount):
                if not handing_account:
                    raise CustomError('请选择运输费用付款账户！')
                income_data = {
                    'referer_no': purchase_order.no,
                    'type': type2,
                    'amount': -abs(float(handing_amount)),
                    'account': transport_account,
                    'check_status': settings.PASS,
                    'check_user': request.user.id,
                    'department': request.user.department_id,
                    'check_time': timezone.now(),
                    'notes': ''
                }
                income = FinanceIncomeSerializer.factory(request.user, income_data)
                income.validSave()
            BizLog.objects.addnew(request.user, BizLog.INSERT, u"入库单[{}]付款".format(godownEntry.no), request.POST)
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'审核失败')
    return JSONResponse({})

@csrf_exempt
@permission_required('purchase.view_purchase_payment')
def purchase_payment_list(request):
    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = PurchasePayment.objects.filter(Q(create_user_id__in=user_ids) | Q(department_id__in=department_ids) | Q(create_user=request.user))
    f = PurchasePaymentFilter(request.GET, queryset=rows)
    total_row = f.qs.aggregate(sum_amount=Sum('amount'),sum_apply_amount=Sum('apply_amount'),sum_actual_amount=Sum('actual_amount'))
    more = {
        'sum_amount': Formater.formatAmountShowWithTwoDecimalPlaces(total_row['sum_amount']),
        'sum_apply_amount': Formater.formatAmountShowWithTwoDecimalPlaces(total_row['sum_apply_amount']),
        'sum_actual_amount': Formater.formatAmountShowWithTwoDecimalPlaces(total_row['sum_actual_amount'])
    }

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


@csrf_exempt
@permission_required('purchase.export_purchase_payment')
def purchase_payment_export(request):
    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = PurchasePayment.objects.filter(Q(create_user_id__in=user_ids) | Q(department_id__in=department_ids) | Q(create_user=request.user))
    f = PurchasePaymentFilter(request.GET, queryset=rows)
    serializer = PurchasePaymentSerializer(f.qs, many=True)
    export_data = ExportChange.dict_to_obj(serializer)
    export_data = PurchasePaymentResource().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('purchase.add_purchase_payment')
def purchase_payment_save(request):
    id = request.GET.get('id')
    data = json.loads(request.body)

    try:
        with transaction.atomic():
            apply_amount = Formater.formatAmount(data['apply_amount']) # 申请金额
            if apply_amount <= 0:
                raise CustomError(u'本次申请金额必须大于0')
            total_amount = apply_amount
            amount = Formater.formatAmount(data['amount']) # 合同金额
            sum_rows = PurchasePayment.objects.filter(order_id=data['order_id']).aggregate(sum_amount=Sum('apply_amount'))
            if sum_rows:
                total_amount += sum_rows['sum_amount'] or 0

            # if total_amount > amount:
            #     raise CustomError(u'该合同申请金额大于合同总金额')

            order_data = {'order': data['order_id'], 'amount': amount, 'apply_amount': apply_amount, 'notes': data['notes']}
            pb = PurchasePaymentSerializer.factory(request.user, order_data, id)
            if pb.instance and pb.instance.status == settings.PASS:
                raise CustomError(u'该付款单已审核')
            # 更新原合同单的申请金额
            if pb.instance:
                order = pb.instance.order
                order.apply_amount -= pb.instance.apply_amount
                order.save()
            pb = pb.validSave()
            pb.order.updateApplyAmount() #更新合同单的申请金额

    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 purchase_payment_detail(request):
    id = request.GET.get('id')
    company = PurchasePayment.getById(id).department.getCompany()
    payment = PurchasePayment.getById(id)
    rows = PurchaseOrderDetail.objects.filter(main_id=payment.order_id)
    order_id = None
    if rows:
        order_id = rows[0].main_id

    result = {'company': company.name, 'order_id': order_id, 'data': []}
    for row in rows:
        item = {
            'id': row.id,
            'product_id': row.product_id,
            'purchase_detail_id': row.id,
            'supplier_name': row.main.supplier.name,
            'supplier_account': row.main.supplier.account,
            'name': row.product.name,
            'model': row.product.model,
            'order_no': row.main.no,
            'amount': Formater.formatAmountShowWithTwoDecimalPlaces(row.amount),
            'count': Formater.formatCountShow(row.count),
            'price': Formater.formatPriceShow(row.price),
            'avg_cost_price': Formater.formatPriceShow(row.product.avg_cost_price),
            'unit': row.product.unit or '',
            'standard': row.product.standard or '',
            'quality_request_text': row.quality_request_text or '',
            'max_price': Formater.formatPriceShow(row.product.max_price),
            'min_price': Formater.formatPriceShow(row.product.min_price),
        }
        result['data'].append(item)
    return JSONResponse(result)


@csrf_exempt
@permission_required('purchase.delete_purchase_payment')
def purchase_payment_delete(request):
    id = int(request.GET.get('id'))
    try:
        with transaction.atomic():
            payment = PurchasePayment.getById(id)
            if payment.status != settings.DEFAULT:
                raise CustomError(u'该付款单已审核, 不允许删除')

            #更新合同单的申请金额
            payment.order.apply_amount -= payment.apply_amount
            payment.order.save()

            BizLog.objects.addnew(request.user, BizLog.DELETE, u"删除采购付款单[%s]，id=%d" % (payment.no, payment.id))
            PurchasePaymentDetail.objects.filter(main=payment).delete()
            payment.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('purchase.check_purchase_payment')
def purchase_payment_check(request):
    id = request.GET.get('id')
    status = int(request.GET.get('status'))
    try:
        with transaction.atomic():
            order = PurchasePayment.getById(id)
            if status == settings.PASS:
                if order.status == settings.PASS:
                    raise CustomError(u'该付款单已审核')
                order.status = settings.PASS
                order.check_user = request.user
                order.check_time = timezone.now()
                BizLog.objects.addnew(
                    request.user,
                    BizLog.CHECK,
                    u"审核采购付款[%s]，id=%d" % (order.no, order.id),
                )
            else:
                if order.status == settings.DEFAULT:
                    raise CustomError(u'该付款单尚未审核')
                # if order.review_time:
                #     raise CustomError(u'该付款单已复核，请先撤销复核')
                if order.is_pay:
                    raise CustomError(u'该付款单已付款,禁止撤销审核')
                order.status = settings.DEFAULT
                order.check_user = None
                order.check_time = None
                BizLog.objects.addnew(
                    request.user,
                    BizLog.CHECK,
                    u"采购付款单取消审核[%s]，id=%d" % (order.no, order.id),
                )
            order.save()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'审核失败')
    return JSONResponse({})


@csrf_exempt
@permission_required('purchase.export_purchase_payment')
def purchase_payment_export_detail(request):
    id = request.GET.get('id')
    payment = PurchasePayment.getById(id)
    rows = PurchaseOrderDetail.objects.filter(main_id=payment.order_id)
    export_data = PurchasePaymentDetailResource().export(rows)
    filename = utils.attachment_save(export_data)
    BizLog.objects.addnew(request.user, BizLog.EXPORT, u"导出付款管理明细")
    return JSONResponse({'filename': filename})

@csrf_exempt
@token_required
def purchase_payment_clear(request):
    id = request.GET.get('id') # 合同id
    try:
        with transaction.atomic():
            order = PurchaseOrder.getById(id)
            PurchasePayment.objects.filter(order=order).update(is_clear=True)
            BizLog.objects.addnew(request.user, BizLog.INSERT, u"结清合同{}".format(order.no))
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'保存失败')
    return JSONResponse({})


@csrf_exempt
@permission_required('purchase.pay_purchase_payment')
def purchase_payment_pay(request):
    id = request.GET.get('id')
    data = json.loads(request.body)
    try:
        with transaction.atomic():
            payment = PurchasePayment.getById(id)

            if payment.apply_amount <= payment.actual_amount:
                raise CustomError(u'付款单已付款完毕')

            # if not payment.ratify_time:
            #     raise CustomError(u'付款单未批准,禁止付款')
            # if not payment.review_time:
            #     raise CustomError(u'付款单未复核,禁止付款')
            if payment.status == settings.DEFAULT:
                raise CustomError(u'付款单未审核,禁止付款')
            try:
                data['actual_amount'] = Formater.formatAmount(data['actual_amount'])
            except:
                raise CustomError(u'付款金额无效')

            if data['actual_amount'] <= 0:
                raise CustomError(u'付款金额应该大于零')
            data['main'] = payment.id
            pb = PurchasePaySerializer.factory(request.user, data)
            pb = pb.validSave()
            payment.updateActualAmount()
            payment.is_pay = True
            payment.save()
            BizLog.objects.addnew(
                request.user,
                BizLog.UPDATE,
                u"采购付款单[%s]付款，id=%d" % (payment.no, payment.id),
            )
    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 purchase_payment_pay_detail(request):
    id = request.GET.get('id')
    try:
        instances = PurchasePay.getByMainId(id)
        data = []
        for instance in instances:
            item = {
                'id': instance.id,
                'payment_type': instance.payment_type.name,
                'payment_time': Formater.formatStrTime(instance.payment_time),
                'actual_amount': Formater.formatAmountShowWithTwoDecimalPlaces(instance.actual_amount),
                'payment_user_text': instance.payment_user.name,
                'notes': instance.notes or ''
            }
            data.append(item)
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'没有付款记录')
    return JSONResponse(data)

@csrf_exempt
@permission_required('purchase.view_purchase_invoice')
def purchase_invoice_list(request):
    invoice = request.GET.get('invoice')
    # rows = PurchaseOrderDetail.objects.filter(main__status=PurchaseOrder.TAKE_EFFECT)
    rows = PurchaseOrderDetail.objects.filter(main__status=PurchaseOrder.PASS)
    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = rows.filter(Q(main__create_user_id__in=user_ids) | Q(main__department_id__in=department_ids) | Q(main__create_user=request.user))
    if invoice == '0':
        rows = rows.filter(invoice_no__isnull=True)
    elif invoice == '1':
        rows = rows.filter(invoice_no__isnull=False)
    f = PurchaseOrderDetailFilter(request.GET, queryset=rows)

    total_row = f.qs.aggregate(sum_invoice_amount=Sum('invoice_amount'), sum_amount=Sum('amount'))
    more = {
        'sum_amount': Formater.formatAmountShow(total_row['sum_amount']),
        'sum_invoice_amount': Formater.formatAmountShow(total_row['sum_invoice_amount'])
    }

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


@csrf_exempt
@permission_required('purchase.export_purchase_invoice')
def purchase_invoice_export(request):
    invoice = request.GET.get('invoice')
    # rows = PurchaseOrderDetail.objects.filter(main__status=PurchaseOrder.TAKE_EFFECT)
    rows = PurchaseOrderDetail.objects.filter(main__status=PurchaseOrder.PASS)
    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = rows.filter(Q(main__create_user_id__in=user_ids) | Q(main__department_id__in=department_ids) | Q(
        main__create_user=request.user))
    if invoice == '0':
        rows = rows.filter(invoice_no__isnull=True)
    elif invoice == '1':
        rows = rows.filter(invoice_no__isnull=False)

    f = PurchaseOrderDetailFilter(request.GET, queryset=rows)
    serializer = PurchaseOrderDetailSerializer(f.qs, many=True)
    export_data = ExportChange.dict_to_obj(serializer)
    export_data = PurchaseInvoiceResource().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('purchase.add_purchase_invoice')
def purchase_invoice_save(request):
    data = json.loads(request.body)

    try:
        with transaction.atomic():
            try:
                amount = Formater.formatAmount(data['invoice_amount'])
            except:
                raise CustomError(u'发票金额无效')

            items = data['items']
            for item in items:
                order = PurchaseOrderDetail.getById(item['id'])
                if order.check_status == settings.PASS:
                    raise CustomError(u'合同[%s]中产品[%s]发票已审核' % (order.main.no, order.product.name))

                order.invoice_no = data['invoice_no']
                order.invoice_amount = amount
                order.invoice_date = data['invoice_date']
                order.create_user = request.user
                order.department = request.user.department
                order.create_time = timezone.now()
                order.save()
            BizLog.objects.addnew(
                request.user,
                BizLog.INSERT,
                u"录入发票[%s]" % data['invoice_no'],
                data
            )
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'保存失败')
    return JSONResponse({})

@csrf_exempt
@permission_required('purchase.check_purchase_invoice')
def purchase_invoice_check(request):
    id = request.GET.get('id')
    status = int(request.GET.get('status'))
    try:
        with transaction.atomic():
            order = PurchaseOrderDetail.getById(id)
            if status == settings.PASS:
                if order.check_status == settings.PASS:
                    raise CustomError(u'该单据已审核')
                if not order.invoice_no or order.invoice_no == '':
                    raise CustomError(u'该单据尚未录入发票')
                order.check_status = settings.PASS
                order.check_user = request.user
                order.check_time = timezone.now()
                BizLog.objects.addnew(
                    request.user,
                    BizLog.CHECK,
                    u"审核采购发票[%s]，id=%d" % (order.main.no, order.id),
                )
            else:
                if order.check_status == settings.DEFAULT:
                    raise CustomError(u'该单据尚未审核')
                order.check_status = settings.DEFAULT
                order.check_user = None
                order.check_time = None
                BizLog.objects.addnew(
                    request.user,
                    BizLog.CHECK,
                    u"采购发票取消审核[%s]，id=%d" % (order.main.no, order.id),
                )
            order.save()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'审核失败')
    return JSONResponse({})


@csrf_exempt
@permission_required('purchase.add_purchase_invoice')
def purchase_invoice_upload_image(request):
    ids = request.POST.get('ids')
    files = request.FILES.getlist('file')
    try:
        with transaction.atomic():
            ids = str(ids).split(',')
            from models import path_and_rename
            for id in ids:
                order = PurchaseOrderDetail.objects.filter(id=id).first()
                if not order:
                    raise CustomError(u'未找到合同')
                if order.check_status == settings.PASS:
                    raise CustomError(u'该合同已生效')
                for file in files:
                    filename = "%s%d-%s.%s" % (
                        path_and_rename.path,
                        order.id,
                        timezone.now().strftime('%Y%m%d%H%M%S%f'),
                        file.name.split('.')[-1]
                    )
                    filename = filename.lower()
                    full_filename = "%s/%s" % (settings.MEDIA_ROOT, filename)
                    with open(full_filename, 'wb+') as destination:
                        for chunk in file.chunks():
                            destination.write(chunk)
                    #utils.resize_image(full_filename, 800)

                    PurchaseInvoiceImage.objects.create(order_detail=order, invoice_image=filename)
    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 purchase_invoice_images(request):
    id = request.GET.get('id')
    rows = PurchaseInvoiceImage.objects.filter(order_detail_id=int(id))
    rows, total = utils.get_page_data(request, rows)
    data = []
    for row in rows:
        item = {
            'id': row.id,
            'check_status': row.order_detail.check_status,
            'order_detail_id': row.order_detail.id,
            'image': unicode(row.invoice_image),
            'image_name': str(row.invoice_image).split('/')[-1],
            'image_url': row.invoice_image.url,
        }
        data.append(item)
    return DataGridJSONResponse(data, total)

@csrf_exempt
@permission_required('purchase.add_purchase_invoice')
def purchase_invoice_del_image(request):
    id = request.GET.get('id')

    try:
        with transaction.atomic():
            img = PurchaseInvoiceImage.objects.filter(id=int(id)).first()
            if img.order_detail.check_status == settings.PASS:
                raise CustomError(u'该发票已审核, 不允许删除')
            img.delete()
            try:
                os.remove("%s/%s" % (settings.MEDIA_ROOT, img.invoice_image))
            except:
                pass
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except:
        traceback.print_exc()
        return JSONError(u"删除失败")
    return JSONResponse({})



@csrf_exempt
@token_required
def search_product(request):
    param = request.GET.get('param')
    type = request.GET.get('type')
    warehouse_id = request.GET.get('warehouse')
    rows = ProductBase.objects.filter(enabled=True, type__lt=ProductBase.GOODS)

    user_department = Department.getById(request.user.department.id)

    if user_department.company.product_range:
        if user_department.company.product_range == Department.MATERIAL:
            rows = rows.filter(type=ProductBase.MATERIAL)
        elif user_department.company.product_range == Department.CONSUMABLE:
            rows = rows.filter(type=ProductBase.CONSUMABLE)

    if type:
        rows = rows.filter(type=int(type))

    if param:
        rows = rows.filter(Q(name__icontains=param) | Q(model__icontains=param) | Q(code__icontains=param))

    rows, total = utils.get_page_data(request, rows)

    data = []
    for row in rows:
        record_data = []
        if warehouse_id:
            record_data = GetWarehouseSrockRecord.getRecord(row.id, warehouse_id)

        item = {
            'id': row.id,
            'name': row.name,
            'model': row.model,
            'unit': row.unit,
            'standard': row.standard,
            'warehouse_place': row.warehouse_place,
            'type_text': row.get_type_display(),
            'option_type_text': row.option_type and row.option_type.name or '',
            'record_data': record_data
        }
        data.append(item)

    return JSONResponse({'data': data, 'total': total})

@csrf_exempt
@token_required
def search_user(request):
    id = request.GET.get('id')
    purchase = PurchasePlan.getById(id)
    purchase_users = PurchaseUser.objects.filter(purchase=purchase)
    rows = User.objects.filter()
    data = []
    for row in rows:
        item = {
            'id': row.id,
            'name': row.name,
            'department': row.department.name,
            'check': 0,
            'is_report': 0,
            'name_dept': u"{}--{}".format(row.name,row.department.name),
        }
        for purchase_user in purchase_users:
            if purchase_user.purchase_user.id == row.id:
                item['check'] = 1
                is_report = PurchasePrice.objects.filter(purchase_user_id=row.id,purchase_detail__purchase=purchase,report=True).count()
                if is_report:
                    item['is_report'] = 1
                break
        data.append(item)
    return JSONResponse(data)


@csrf_exempt
@token_required
def search_price(request):
    rows = PurchasePrice.objects.filter(Q(supplier__isnull=False) & Q(purchase_user=request.user) & Q(report=False))
    data = []
    for row in rows:
        item = {
            'id': row.id,
            'name': row.purchase_detail.product.name,
            'model': row.purchase_detail.product.model,
            'price': Formater.formatPriceShow(row.price),
            'supplier': row.supplier.name,
            'notes': row.notes or '',
        }
        data.append(item)
    return JSONResponse(data)

@token_required
def godownentry_list(request):
    type = int(request.GET.get('type'))
    product_notes = request.GET.get('product_notes')
    try:
        valid_permission(request.user,GodownEntry.getPermissionByType(type, 'view'))
    except:
        return DataGridJSONResponse([], 0)

    warehouses_ids = Warehouse.getManagerWarehouses(request.user)
    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = GodownEntry.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 = GodownEntryDetail.objects.filter(main_id__in=g_ids, notes__icontains=product_notes).values_list('main_id')
        rows = rows.filter(id__in=d_ids)

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


@csrf_exempt
@token_required
def godownentry_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 = GodownEntry.getValidType(request.GET.get('type'))
        main_data['product_type'] = type
        with transaction.atomic():
            serializer = GodownEntrySerializer.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'))
            # 简易流程：添加入库单，同时生成合同，自动审核合同。
            godownentry_process = Config.getValue('godownentry_process')
            if main_data.has_key('purchase_order') and main_data['purchase_order']:
                # 合同中点到货，会执行此接口。此时无论那种流程，都不应该在创建合同。
                godownentry_process = ''
            pb = None
            if godownentry_process == '1':
                order_data = {
                    'supplier':serializer.supplier.id,
                    'status':PurchaseOrder.PASS,
                    'arrval':PurchaseOrder.ALL_ARRVAL,
                    'check_time':timezone.now(),
                    'check_user':request.user.id,
                    'count':0,
                    'amount':0,
                }
                pb = PurchaseOrderSerializer.factory(request.user, order_data)
                pb = pb.validSave()
                pb.no = pb.order_no
                serializer.purchase_order = pb
                serializer.save()

            GodownEntryDetail.objects.filter(main=serializer).delete()
            for item in items_data:
                item['main'] = serializer.id
                detail_serializer = GodownEntryDetailSerializer.factory(request.user, data=item)
                detail_serializer.validSave()

                if godownentry_process == '1':
                    detail = detail_serializer.instance
                    dict = {
                        'main':pb.id,
                        'product':detail.product_base.id,
                        'count':item['count'],
                        'price':item['price'],
                        'amount':detail.amount,
                        'is_arrval':True,
                    }
                    pbd = PurchaseOrderDetailSerializer.factory(request.user, dict)
                    pbd.validSave()
                    pbd.instance.arrval_count = detail.count
                    pbd.instance.save()
            serializer.update_total()
            if pb:
                pb.count = serializer.total_count
                pb.amount = serializer.total_amount
                pb.apply_amount = serializer.total_amount
                pb.save()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'保存失败！')
    return JSONResponse()



@token_required
def godownentry_delete(request):
    id = request.GET.get('id')
    try:
        with transaction.atomic():
            instance = GodownEntry.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))
            GodownEntryDetail.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 godownentry_detail(request):
    id = request.GET.get('id')
    instance = GodownEntry.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,
        'supplier_id': instance.supplier_id,
        'supplier_name': instance.supplier.name,
        'create_user_text': instance.create_user.name,
        'status': instance.status,
        'status_text': status_text,
        'check_user_text': instance.check_user and instance.check_user.name or ' ',
        'check_time': Formater.formatStrTime(instance.check_time),
        'total_count': Formater.formatCountShow(instance.total_count),
        'total_amount': Formater.formatAmountShow(instance.total_amount),
        'create_time': Formater.formatStrTime(instance.create_time),
        'notes': instance.notes or '',
        'no': instance.no,
        'company': company.name,
        'purchase_order_no':instance.purchase_order and instance.purchase_order.no or ''
    }

    data = {
        'main_data': main_data,
        'items_data': []
    }
    detail_rows = GodownEntryDetail.objects.filter(main=instance)
    for detail_row in detail_rows:
        item_data = {
            'id': detail_row.id,
            'product_base_id': detail_row.product_base_id,
            'product_base_name': detail_row.product_base.name,
            'product_base_model': detail_row.product_base.model,
            'price': Formater.formatPriceShow(detail_row.price),
            'count': Formater.formatCountShow(detail_row.count),
            'amount': Formater.formatAmountShow(detail_row.amount),
            'invoice_amount': Formater.formatAmountShow(detail_row.invoice_amount),
            'warehouse_place': detail_row.product_base.warehouse_place or '',
            'unit':detail_row.product_base.unit or '',
            'notes':detail_row.notes or ''
        }
        data['items_data'].append(item_data)

    return JSONResponse(data)


@token_required
def godownentry_export(request):
    try:
        type = GodownEntry.getValidType(request.GET.get('type'))
        warehouses_ids = Warehouse.getManagerWarehouses(request.user)
        department_ids = request.user.getSubDepartmentIds()
        user_ids = request.user.getSubEmployeeIds()
        rows = GodownEntry.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 = GodownEntryFilter(request.GET, queryset=rows)
        serializer = GodownEntrySerializer(f.qs, many=True)
        valid_permission(request.user, GodownEntry.getPermissionByType(type, 'export'))
        export_data = ExportChange.dict_to_obj(serializer)
        if type == GodownEntry.MATERIAL:
            perm = 'material.view_material_cost'
        elif type == GodownEntry.CONSUMABLE:
            perm = 'material.view_consumable_cost'
        is_show_cost = isHasPermissions(request.user, perm)
        export_data = GodownEntryResource(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 godownentry_export_detail(request):
    id = request.GET.get('id')
    instance = GodownEntry.getById(id)
    try:
        valid_permission(request.user, instance.getPermission('export'))
        godown_entry_detail = GodownEntryDetail.objects.filter(main=instance)
        serializer = GodownEntryDetailSerializer(godown_entry_detail, many=True)
        export_data = ExportChange.dict_to_obj(serializer)
        if instance.product_type == GodownEntry.MATERIAL:
            perm = 'material.view_material_cost'
        elif instance.product_type == GodownEntry.CONSUMABLE:
            perm = 'material.view_consumable_cost'
        is_show_cost = isHasPermissions(request.user, perm)
        export_data = GodownEntryDetailResource(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))
    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 godownentry_import(request):
    file = request.FILES.get('excel_file')
    main_data = json.loads(request.POST.get('main_data'))

    try:
        type = GodownEntry.getValidType(request.GET.get('type'))
        main_data['product_type'] = type
        valid_permission(request.user, GodownEntry.getPermissionByType(type, 'import'))
        line = 2
        importer = GodownEntryImporter()
        excel_rows = importer.getExcelData(file)
        with transaction.atomic():
            godownentry_process = Config.getValue('godownentry_process')
            serializer = GodownEntrySerializer.factory(request.user, main_data)
            serializer = serializer.validSave()

            # 简易流程：添加入库单，同时生成合同，自动审核合同。
            if main_data.has_key('purchase_order') and main_data['purchase_order']:
                # 合同中点到货，会执行此接口。此时无论那种流程，都不应该在创建合同。
                godownentry_process = ''
            pb = None
            if godownentry_process == '1':
                order_data = {
                    'supplier': serializer.supplier.id,
                    'status': PurchaseOrder.PASS,
                    'arrval': PurchaseOrder.ALL_ARRVAL,
                    'check_time': timezone.now(),
                    'check_user': request.user.id,
                    'count': 0,
                    'amount': 0,
                }
                pb = PurchaseOrderSerializer.factory(request.user, order_data)
                pb = pb.validSave()
                pb.no = pb.order_no
                serializer.purchase_order = pb
                serializer.save()

            for excel_row in excel_rows:
                try:
                    row = importer.validRow(excel_row)
                    model = row[u'产品代码']
                    product_base = ProductBase.objects.filter(model=model, type=type)
                    if product_base.count() == 0:
                        raise CustomError(u'产品代码不存在')
                    elif product_base.count() > 1:
                        raise CustomError(u'产品代码重复，前往基础数据设置修改')
                    else:
                        product_base = product_base.first()
                    items_data = {}
                    items_data['product_base'] = product_base.id
                    items_data['main'] = serializer.id
                    items_data['price'] = row[u'单价']
                    items_data['count'] = row[u'数量']
                    items_data['invoice_amount'] = row[u'发票金额']
                    items_data['notes'] = row[u'备注']

                    detail_serializer = GodownEntryDetailSerializer.factory(request.user, items_data)
                    detail_serializer.validSave()

                    if godownentry_process == '1':
                        detail = detail_serializer.instance
                        dict = {
                            'main': pb.id,
                            'product': detail.product_base.id,
                            'count': items_data['count'],
                            'price': items_data['price'],
                            'amount': detail.amount,
                            'is_arrval': True,
                        }
                        pbd = PurchaseOrderDetailSerializer.factory(request.user, dict)
                        pbd.validSave()
                        pbd.instance.arrval_count = detail.count
                        pbd.instance.save()

                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
            serializer.update_total()
            if pb:
                pb.count = serializer.total_count
                pb.amount = serializer.total_amount
                pb.apply_amount = serializer.total_amount
                pb.save()
            BizLog.objects.addnew(request.user, BizLog.IMPORT, u"导入入库单[%s]，id=%d" % (serializer.no, serializer.id))
    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 godownentry_import_mult(request):
    # 原料、耗材批量导入，导入模板包含供应商
    file = request.FILES.get('excel_file')
    main_data = json.loads(request.POST.get('main_data'))
    print 11111111, main_data
    try:
        type = GodownEntry.getValidType(request.GET.get('type'))
        main_data['product_type'] = type
        valid_permission(request.user, GodownEntry.getPermissionByType(type, 'import'))
        line = 2
        importer = GodownEntryImporter()
        excel_rows = importer.getExcelData(file)
        with transaction.atomic():
            godownentry_process = Config.getValue('godownentry_process')
            for excel_row in excel_rows:
                try:
                    row = importer.validRow(excel_row)
                    supplier = Supplier.objects.filter(name=row[u'供应商'], type=main_data['product_type']).first()
                    if not supplier:
                        raise CustomError(u'第{}行供应商{}不存在'.format(line, row[u'供应商'], ))
                    main_data['supplier'] = supplier.id
                    main_data['notes'] = row[u'入库备注']
                    serializer = GodownEntrySerializer.factory(request.user, main_data)
                    serializer = serializer.validSave()

                    # 简易流程：添加入库单，同时生成合同，自动审核合同。
                    if main_data.has_key('purchase_order') and main_data['purchase_order']:
                        # 合同中点到货，会执行此接口。此时无论那种流程，都不应该在创建合同。
                        godownentry_process = ''
                    pb = None
                    if godownentry_process == '1':
                        order_data = {
                            'supplier': serializer.supplier.id,
                            'status': PurchaseOrder.PASS,
                            'arrval': PurchaseOrder.ALL_ARRVAL,
                            'check_time': timezone.now(),
                            'check_user': request.user.id,
                            'count': 0,
                            'amount': 0,
                        }
                        pb = PurchaseOrderSerializer.factory(request.user, order_data)
                        pb = pb.validSave()
                        pb.no = pb.order_no
                        serializer.purchase_order = pb
                        serializer.save()


                    model = row[u'产品代码']
                    product_base = ProductBase.objects.filter(model=model, type=type)
                    if product_base.count() == 0:
                        raise CustomError(u'产品代码不存在')
                    elif product_base.count() > 1:
                        raise CustomError(u'产品代码重复，前往基础数据设置修改')
                    else:
                        product_base = product_base.first()
                    items_data = {}
                    items_data['product_base'] = product_base.id
                    items_data['main'] = serializer.id
                    items_data['price'] = row[u'单价']
                    items_data['count'] = row[u'数量']
                    items_data['invoice_amount'] = row[u'发票金额']
                    items_data['notes'] = row[u'备注']

                    detail_serializer = GodownEntryDetailSerializer.factory(request.user, items_data)
                    detail_serializer.validSave()

                    if godownentry_process == '1':
                        detail = detail_serializer.instance
                        dict = {
                            'main': pb.id,
                            'product': detail.product_base.id,
                            'count': items_data['count'],
                            'price': items_data['price'],
                            'amount': detail.amount,
                            'is_arrval': True,
                        }
                        pbd = PurchaseOrderDetailSerializer.factory(request.user, dict)
                        pbd.validSave()
                        pbd.instance.arrval_count = detail.count
                        pbd.instance.save()
                    serializer.update_total()
                    if pb:
                        pb.count = serializer.total_count
                        pb.amount = serializer.total_amount
                        pb.apply_amount = serializer.total_amount
                        pb.save()
                except CustomError, e:
                    raise CustomError(u'第%d行:%s' % (line, e.get_error_msg()))
                except Exception, e:
                    traceback.print_exc()
                    raise CustomError(u'第%d行:%s' % (line, unicode(e)))
                line += 1
                if line % 100 == 0:
                    print line
            print '000000llkkkkkk'
            BizLog.objects.addnew(request.user, BizLog.IMPORT, u"导入入库单[%s]，id=%d" % (serializer.no, serializer.id))
    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 godownentry_senior_edit(request):
    def updateStock(product_base, warehouse):
        sum_row = WarehouseRecord.objects.filter(
            warehouse=warehouse,
            product=product_base
        ).aggregate(
            count=Sum('count'),
            amount=Sum('amount'),
            amount2=Sum('amount2')
        )
        warehouse_stock = WarehouseStock.objects.filter(product=product_base, warehouse=warehouse).first()
        if warehouse_stock:
            warehouse_stock.count = sum_row['count'] or 0
            warehouse_stock.amount = sum_row['amount'] or 0
            warehouse_stock.amount2 = sum_row['amount2'] or 0
            if warehouse_stock.count != 0:
                warehouse_stock.avg_cost_price = warehouse_stock.amount / warehouse_stock.count
                warehouse_stock.avg_cost_price2 = warehouse_stock.amount2 / warehouse_stock.count
            warehouse_stock.save()

        sum_row = WarehouseStock.objects.filter(
            product=product_base
        ).aggregate(
            count=Sum('count'),
            amount=Sum('amount'),
            amount2=Sum('amount2')
        )

        product_base.stock_count = sum_row['count'] or 0
        product_base.stock_amount = sum_row['amount'] or 0
        product_base.stock_amount2 = sum_row['amount2'] or 0
        if product_base.stock_count > 0:
            product_base.avg_cost_price = product_base.stock_amount / product_base.stock_count
            product_base.avg_cost_price2 = product_base.stock_amount2 / product_base.stock_count
        product_base.save()


    def updateWarehouseRecord(warehouse_record):
        sum_row = WarehouseRecordDetail.objects.filter(
            warehouse_record=warehouse_record
        ).aggregate(
            sum_amount=Sum(F('count') * F('warehouse_stock_record__entry_price')),
            sum_amount2=Sum(F('count') * F('warehouse_stock_record__entry_price2')),
            sum_count=Sum('count')
        )
        warehouse_record.amount = sum_row['sum_amount'] or 0
        warehouse_record.amount2 = sum_row['sum_amount2'] or 0
        warehouse_record.count = sum_row['sum_count'] or 0
        warehouse_record.save()

    def changeEntryPrice(entry_detail,entry_price,entry_price2):
        changeEntryPriceBase(entry_detail, entry_price, entry_price2)
        rows = WarehouseRecordDetail.objects.filter(warehouse_stock_record=entry_detail.stock_record)

        ck_type = (WarehouseRecord.CK_ZJ, WarehouseRecord.CK_XS,)
        pk_type = (WarehouseRecord.CK_PK,)
        tl_type = (WarehouseRecord.TL,)
        th_type = (WarehouseRecord.TH,)
        for row in rows:
            warehouse_record = row.warehouse_record
            updateWarehouseRecord(warehouse_record)
            if warehouse_record.type in ck_type:
                deliver_detail = DeliverDetail.objects.filter(warehouse_record=warehouse_record).first()
                if deliver_detail:
                    #更新出库明细的合计成本
                    deliver_detail.total_cost = warehouse_record.amount
                    deliver_detail.save()

                    # 更新出库单的合计成本
                    order = deliver_detail.main
                    sum_row = DeliverDetail.objects.filter(
                        main=order
                    ).aggregate(
                        sum_cost=Sum('total_cost')
                    )
                    order.total_cost = sum_row['sum_cost'] or 0
                    order.save()
            elif warehouse_record.type in tl_type:
                detail = DeliverReturnDetail.objects.filter(warehouse_record=warehouse_record).first()
                if detail:
                    #更新退料明细的合计成本
                    old_amount = detail.return_cost
                    detail.return_cost = warehouse_record.amount
                    detail.save()

                    # 更新出库明细的退料合计成本
                    new_amount = detail.return_cost
                    detail.deliver_detail.return_cost += new_amount - old_amount
                    detail.deliver_detail.save()

                    #更新出库单的退料合计成本
                    detail.deliver_detail.main.return_cost += new_amount - old_amount
                    detail.deliver_detail.main.save()

                    #更新退料单的合计成本
                    order = detail.main
                    sum_row = DeliverReturnDetail.objects.filter(
                        main=order
                    ).aggregate(
                        sum_cost=Sum('return_cost')
                    )
                    order.return_cost = sum_row['sum_cost'] or 0
                    order.save()

            elif warehouse_record.type in th_type:
                detail = GodownEntryReturnDetail.objects.filter(warehouse_record=warehouse_record).first()
                if detail:
                    old_amount = detail.amount
                    #更新退货明细的成本
                    detail.amount = warehouse_record.amount
                    detail.price = 0
                    if detail.count:
                        detail.price = detail.amount / detail.count
                    detail.save()

                    #更新入库明细的退货成本
                    if detail.godownentry_detail:
                        new_amount = detail.amount
                        detail.godownentry_detail.return_amount += new_amount - old_amount
                        detail.godownentry_detail.save()

                        #更新入库单的退货成本
                        detail.godownentry_detail.main.return_amount += new_amount - old_amount
                        detail.godownentry_detail.main.save()

                    #更新退货单的合计成本
                    order = detail.main
                    sum_row = GodownEntryReturnDetail.objects.filter(
                        main=order
                    ).aggregate(
                        sum_cost=Sum('amount')
                    )
                    order.total_amount = sum_row['sum_cost'] or 0
                    order.save()
            elif warehouse_record.type in pk_type:
                detail = InventoryDetail.objects.filter(warehouse_record=warehouse_record).first()
                if detail:
                    #更新盘存明细
                    detail.amount = warehouse_record.amount
                    detail.price = 0
                    if detail.count:
                        detail.price = detail.amount / detail.count
                    detail.save()

                    # 更新盘存单
                    order = detail.main
                    sum_row = InventoryDetail.objects.filter(
                        main=order
                    ).aggregate(
                        sum_amount=Sum('amount')
                    )
                    order.total_amount = sum_row['sum_amount'] or 0
                    order.save()


    def changeEntryPriceBase(entry_detail,entry_price,entry_price2):
        entry_detail.price = entry_price
        entry_detail.amount = entry_detail.count * entry_price
        entry_detail.save()

        if entry_detail.stock_record:
            entry_detail.stock_record.entry_price = entry_price
            entry_detail.stock_record.entry_price2 = entry_price2
            entry_detail.stock_record.save()

    def changeSupplier(godownentry, new_supplier_id):
        new_supplier = Supplier.objects.filter(id=new_supplier_id).first()
        if not new_supplier:
            raise CustomError(u'未找到相应的供应商')
        godownentry.supplier = new_supplier
        godownentry.save()
        rows = GodownEntryDetail.objects.filter(main=godownentry)
        for row in rows:
            if not row.stock_record:
                continue
            row.stock_record.supplier = new_supplier
            row.stock_record.save()

    def changePrice(godownentry_detail,new_entry_price):
        changeEntryPrice(godownentry_detail, new_entry_price, new_entry_price)
        updateStock(godownentry_detail.product_base, godownentry_detail.main.warehouse)

    def addCount(godownentry_detail,add_count):
        godownentry_detail.count += add_count
        godownentry_detail.amount = godownentry_detail.count * godownentry_detail.price
        godownentry_detail.save()
        if godownentry_detail.stock_record:
            godownentry_detail.stock_record.entry_count += add_count
            godownentry_detail.stock_record.surplus_count += add_count
            godownentry_detail.stock_record.save()

            record_detail = WarehouseRecordDetail.objects.filter(
                warehouse_stock_record=godownentry_detail.stock_record,
                warehouse_record__type__in=(WarehouseRecord.RK_CG, WarehouseRecord.RK_ZJ)
            ).first()
            if record_detail:
                record_detail.count += add_count
                record_detail.save()
                updateWarehouseRecord(record_detail.warehouse_record)
        updateStock(godownentry_detail.product_base, godownentry_detail.main.warehouse)

    def decCount(godownentry_detail,red_count):
        godownentry_detail.count -= red_count
        godownentry_detail.amount = godownentry_detail.count * godownentry_detail.price
        godownentry_detail.save()
        if godownentry_detail.stock_record:
            if red_count > godownentry_detail.stock_record.surplus_count:
                raise CustomError(u'该入库单中的配件[%s]，剩余%s，不能减少%s，请使用退货减少库存' % (
                    godownentry_detail.product_base.name,
                    Formater.formatCountShow(godownentry_detail.stock_record.surplus_count),
                    Formater.formatCountShow(red_count)
                ))
            godownentry_detail.stock_record.entry_count -= red_count
            godownentry_detail.stock_record.surplus_count -= red_count
            godownentry_detail.stock_record.save()

            record_detail = WarehouseRecordDetail.objects.filter(
                warehouse_stock_record=godownentry_detail.stock_record,
                warehouse_record__type__in=(WarehouseRecord.RK_CG, WarehouseRecord.RK_ZJ)
            ).first()
            if record_detail:
                record_detail.count -= red_count
                record_detail.save()
                updateWarehouseRecord(record_detail.warehouse_record)

        updateStock(godownentry_detail.product_base, godownentry_detail.main.warehouse)

    main_data = json.loads(request.POST.get('main'))
    new_rows = json.loads(request.POST.get('item'))
    id = request.GET.get('id')
    new_supplier_id = main_data['supplier']

    try:
        new_supplier_id = int(new_supplier_id)
    except:
        return JSONError(u"无效的供应商！")


    try:
        with transaction.atomic():
            godownentry = GodownEntry.objects.filter(pk=int(id)).first()
            if not godownentry:
                raise CustomError(u'未找到相应的入库单')
            valid_permission(request.user, godownentry.getPermission('edit'))
            if godownentry.status != settings.PASS:
                raise CustomError(u'未通过审核的入库单不允许高级修改')

            if new_supplier_id != godownentry.supplier_id:
                changeSupplier(godownentry,new_supplier_id)

            for row in new_rows:
                new_entry_count = Formater.formatCount(row['new_count'])
                new_entry_price = Formater.formatPrice(row['new_price'])
                if new_entry_count < 0:
                    raise CustomError(u'入库数量不能小于0')
                if new_entry_price < 0:
                    raise CustomError(u'入库价不能小于0')

                detail = GodownEntryDetail.objects.filter(id=int(row['new_detail_id'])).first()
                if not detail:
                    continue
                if detail.price !=  new_entry_price:
                    changePrice(detail,new_entry_price)
                if detail.count < new_entry_count:
                    addCount(detail,new_entry_count-detail.count)
                if detail.count > new_entry_count:
                    decCount(detail, detail.count-new_entry_count)

                WarehouseRecord.updateCurStockByProduct(detail.main.warehouse_id,detail.product_base_id)

            count = 0
            amount = 0
            sum_row = GodownEntryDetail.objects.filter(main=godownentry).aggregate(
                count_sum=Sum('count'),
                amount_sum=Sum('amount')
            )
            if sum_row:
                count = sum_row['count_sum'] or 0
                amount = sum_row['amount_sum'] or 0
            godownentry.total_count = count
            godownentry.total_amount = amount
            godownentry.save()

            BizLog.objects.addnew(
                request.user,
                BizLog.UPDATE,
                u"原料高级修改[单号=%s],id=%d" % (godownentry.no, godownentry.id)
            )
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'修改失败')
    return JSONResponse({})


@token_required
def godownentry_check(request):
    id = request.GET.get('id')
    try:
        with transaction.atomic():
            instance = GodownEntry.getById(id)
            valid_permission(request.user, instance.getPermission('check'))
            if instance.status == settings.PASS:
                raise CustomError(u'该入库单已审核')
            godownentry_details = GodownEntryDetail.objects.filter(main=instance)
            for godownentry_detail in godownentry_details:
                if instance.purchase_order:
                    type = WarehouseRecord.RK_CG
                else:
                    type = WarehouseRecord.RK_ZJ

                stock_record = BizWarehouse.entry(type,
                                                  godownentry_detail.product_base,
                                                  instance.warehouse,
                                                  instance.supplier,
                                                  godownentry_detail.count,
                                                  godownentry_detail.price,
                                                  godownentry_detail.price)
                godownentry_detail.stock_record = stock_record
                godownentry_detail.save()

                # 更新产品入库最高价和最低价
                product = ProductBase.objects.filter(id=godownentry_detail.product_base_id).first()
                if product:
                    if product.max_price < godownentry_detail.price:
                        product.max_price = godownentry_detail.price
                    if product.min_price > godownentry_detail.price:
                        product.min_price = godownentry_detail.price
                    if not product.min_price:
                        product.min_price = godownentry_detail.price
                    product.save()

            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()
            if instance.purchase_order:
                instance.purchase_order.updateArrval()
    except CustomError, e:
        return JSONError(e.get_error_msg())
    except Exception, e:
        traceback.print_exc()
        return JSONError(u'审核失败')
    return JSONResponse({})

@token_required
def godownentry_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(godownentry_total_count=Sum('godown_entry_detail_ref_stock_record__count'),
                               inventory_total_count=Sum('inventory_details_ref_warehouse_stock_record__count'),
                               godownentry_total_return_count = Sum('godown_entry_detail_ref_stock_record__return_count'),
                               inventory_total_return_count = Sum('inventory_details_ref_warehouse_stock_record__return_count'),
                               godownentry_total_amount=Sum('godown_entry_detail_ref_stock_record__amount'),
                               inventory_total_amount=Sum('inventory_details_ref_warehouse_stock_record__amount'),
                               godownentry_total_deliver_count=Sum('godown_entry_detail_ref_stock_record__deliver_count'),
                               inventory_total_deliver_count=Sum('inventory_details_ref_warehouse_stock_record__deliver_count'),
                               total_surplus_count=Sum('surplus_count')
                               )
    more = {
        'total_count': Formater.formatCountShow((total_row['godownentry_total_count'] or 0) + (total_row['inventory_total_count'] or 0)),
        'total_return_count': Formater.formatCountShow((total_row['godownentry_total_return_count'] or 0) + (total_row['inventory_total_return_count'] or 0)),
        'total_amount': Formater.formatAmountShow((total_row['godownentry_total_amount'] or 0) + (total_row['inventory_total_amount'] or 0)),
        'total_deliver_count': Formater.formatCountShow((total_row['godownentry_total_deliver_count'] or 0) + (total_row['inventory_total_deliver_count'] or 0)),
        'total_surplus_count':Formater.formatCountShow(total_row['total_surplus_count'] or 0)
    }

    rows, total = utils.get_page_data(request, rows)
    data = get_godownentry_query_data(rows)
    return DataGridJSONResponse(data, total, more)


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


@token_required
def godownentry_query_detail(request):
    rows = get_filter_data(request)
    data = get_godownentry_query_data(rows)
    return JSONResponse(data)


def get_filter_data(request):
    product_type = int(request.GET.get('type'))
    check_time = request.GET.get('check_time')
    no = request.GET.get('no')
    supplier = request.GET.get('supplier')
    create_user = request.GET.get('create_user')
    product_text = request.GET.get('product_text')
    product_model = request.GET.get('product_model')
    warehouse = request.GET.get('warehouse')
    entry_type = request.GET.get('entry_type')
    notes = request.GET.get('notes')
    rows = WarehouseStockRecord.objects.filter(product__type=product_type,
                                               warehouse_record_detail_ref_stock_record__warehouse_record__type__in=[0,
                                                                                                                     1,
                                                                                                                     2]).order_by(
        '-id')
    if entry_type:
        rows = rows.filter(warehouse_record_detail_ref_stock_record__warehouse_record__type=int(entry_type))
    if product_text:
        rows = rows.filter(product__name__icontains=product_text)
    if product_model:
        rows = rows.filter(product__model__icontains=product_model)
    if warehouse:
        rows = rows.filter(warehouse__name__icontains=warehouse)
    if check_time:
        check_time_begin = check_time.split(' - ')[0]
        check_time_end = check_time.split(' - ')[1] + ' 23:59:59'
        rows = rows.filter(Q(Q(godown_entry_detail_ref_stock_record__main__check_time__gt=check_time_begin) &
                             Q(godown_entry_detail_ref_stock_record__main__check_time__lt=check_time_end)) |
                           Q(Q(inventory_details_ref_warehouse_stock_record__main__check_time__gt=check_time_begin) &
                             Q(inventory_details_ref_warehouse_stock_record__main__check_time__lt=check_time_end)))
    if no:
        rows = rows.filter(Q(godown_entry_detail_ref_stock_record__main__no__icontains=no) |
                           Q(inventory_details_ref_warehouse_stock_record__main__no__icontains=no))
    if notes:
        rows = rows.filter(Q(godown_entry_detail_ref_stock_record__notes__icontains=notes) |
                           Q(inventory_details_ref_warehouse_stock_record__notes__icontains=notes))
    if supplier:
        rows = rows.filter(godown_entry_detail_ref_stock_record__main__supplier__name__icontains=supplier)
    if create_user:
        rows = rows.filter(
            Q(godown_entry_detail_ref_stock_record__main__create_user__name__icontains=create_user) |
            Q(inventory_details_ref_warehouse_stock_record__main__create_user__name__icontains=create_user))

    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(inventory_details_ref_warehouse_stock_record__main__department_id__in=department_ids)
                       | Q(inventory_details_ref_warehouse_stock_record__main__create_user_id__in=user_ids)
                       | Q(inventory_details_ref_warehouse_stock_record__main__create_user=request.user))
                       | Q(Q(godown_entry_detail_ref_stock_record__main__department_id__in=department_ids)
                        | Q(godown_entry_detail_ref_stock_record__main__create_user_id__in=user_ids)
                        | Q(godown_entry_detail_ref_stock_record__main__create_user=request.user)
    ))

    return rows


def get_godownentry_query_data(rows):

    rows = rows.values(
        'id',
        'godown_entry_detail_ref_stock_record__main__supplier__name',
        'godown_entry_detail_ref_stock_record__product_base__name',
        'godown_entry_detail_ref_stock_record__product_base__model',
        'godown_entry_detail_ref_stock_record__product_base__unit',
        'godown_entry_detail_ref_stock_record__product_base__type',
        'godown_entry_detail_ref_stock_record__product_base__warehouse_place',

        'inventory_details_ref_warehouse_stock_record__product__name',
        'inventory_details_ref_warehouse_stock_record__product__model',
        'inventory_details_ref_warehouse_stock_record__product__unit',
        'inventory_details_ref_warehouse_stock_record__product__type',
        'inventory_details_ref_warehouse_stock_record__product__warehouse_place',

        'warehouse__name',
        'warehouse_record_detail_ref_stock_record__warehouse_record__type',

        'godown_entry_detail_ref_stock_record__id',
        'godown_entry_detail_ref_stock_record__price',
        'godown_entry_detail_ref_stock_record__count',
        'godown_entry_detail_ref_stock_record__return_count',
        'godown_entry_detail_ref_stock_record__amount',
        'godown_entry_detail_ref_stock_record__notes',
        'godown_entry_detail_ref_stock_record__deliver_count',
        'godown_entry_detail_ref_stock_record__main__create_user__name',
        'godown_entry_detail_ref_stock_record__main__check_time',
        'godown_entry_detail_ref_stock_record__main__no',

        'inventory_details_ref_warehouse_stock_record__price',
        'inventory_details_ref_warehouse_stock_record__count',
        'inventory_details_ref_warehouse_stock_record__return_count',
        'inventory_details_ref_warehouse_stock_record__amount',
        'inventory_details_ref_warehouse_stock_record__notes',
        'inventory_details_ref_warehouse_stock_record__deliver_count',
        'inventory_details_ref_warehouse_stock_record__main__create_user__name',
        'inventory_details_ref_warehouse_stock_record__main__check_time',
        'inventory_details_ref_warehouse_stock_record__main__no',
    )

    data = []
    for row in rows:
        warehouse_record_type = WarehouseRecord.TYPE_CHOICES[row['warehouse_record_detail_ref_stock_record__warehouse_record__type']][1]
        if row['warehouse_record_detail_ref_stock_record__warehouse_record__type'] == WarehouseRecord.RK_PY:
            product_type_text = ProductBase.TYPE_CHOICES[row['inventory_details_ref_warehouse_stock_record__product__type']][1]
            surplus_count = row['inventory_details_ref_warehouse_stock_record__count'] - row['inventory_details_ref_warehouse_stock_record__return_count'] - row['inventory_details_ref_warehouse_stock_record__deliver_count']
            item = {
                'id': row['id'],
                'type': warehouse_record_type,
                'product_type': product_type_text,
                'supplier': '',
                'product_name': row['inventory_details_ref_warehouse_stock_record__product__name'],
                'product_model': row['inventory_details_ref_warehouse_stock_record__product__model'],
                'product_unit': row['inventory_details_ref_warehouse_stock_record__product__unit'],
                'warehouse_place': row['inventory_details_ref_warehouse_stock_record__product__warehouse_place'],
                'warehouse': row['warehouse__name'],
                'price': Formater.formatPriceShow(row['inventory_details_ref_warehouse_stock_record__price']),
                'count': Formater.formatCountShow(row['inventory_details_ref_warehouse_stock_record__count']),
                'return_count': Formater.formatCountShow(row['inventory_details_ref_warehouse_stock_record__return_count']),
                'amount': Formater.formatAmountShow(row['inventory_details_ref_warehouse_stock_record__amount']),
                'deliver_count': Formater.formatCountShow(row['inventory_details_ref_warehouse_stock_record__deliver_count']),
                'surplus_count': Formater.formatCountShow(surplus_count),
                'create_user': row['inventory_details_ref_warehouse_stock_record__main__create_user__name'],
                'check_time': Formater.formatStrTime(row['inventory_details_ref_warehouse_stock_record__main__check_time']),
                'notes': row['inventory_details_ref_warehouse_stock_record__notes'],
                'no': row['inventory_details_ref_warehouse_stock_record__main__no'],
                'is_PY': True # 是否是盘盈单
            }
        else:
            product_type_text = ProductBase.TYPE_CHOICES[row['godown_entry_detail_ref_stock_record__product_base__type']][1]
            surplus_count = row['godown_entry_detail_ref_stock_record__count'] - row['godown_entry_detail_ref_stock_record__return_count'] - row['godown_entry_detail_ref_stock_record__deliver_count']
            item = {
                'id': row['id'],
                'godownentry_detail_id': row['godown_entry_detail_ref_stock_record__id'],
                'type': warehouse_record_type,
                'product_type': product_type_text,
                'supplier': row['godown_entry_detail_ref_stock_record__main__supplier__name'],
                'product_name': row['godown_entry_detail_ref_stock_record__product_base__name'],
                'product_model': row['godown_entry_detail_ref_stock_record__product_base__model'],
                'product_unit': row['godown_entry_detail_ref_stock_record__product_base__unit'],
                'warehouse_place': row['godown_entry_detail_ref_stock_record__product_base__warehouse_place'],
                'warehouse': row['warehouse__name'],
                'price': Formater.formatPriceShow(row['godown_entry_detail_ref_stock_record__price']),
                'count': Formater.formatCountShow(row['godown_entry_detail_ref_stock_record__count']),
                'return_count': Formater.formatCountShow(row['godown_entry_detail_ref_stock_record__return_count']),
                'amount': Formater.formatAmountShow(row['godown_entry_detail_ref_stock_record__amount']),
                'deliver_count': Formater.formatCountShow(row['godown_entry_detail_ref_stock_record__deliver_count']),
                'surplus_count': Formater.formatCountShow(surplus_count),
                'create_user': row['godown_entry_detail_ref_stock_record__main__create_user__name'],
                'check_time': Formater.formatStrTime(row['godown_entry_detail_ref_stock_record__main__check_time']),
                'notes': row['godown_entry_detail_ref_stock_record__notes'],
                'no': row['godown_entry_detail_ref_stock_record__main__no'],
                'is_PY': False
            }
        data.append(item)
    return data

def getPermissionByType(type, action):
    permissions = {
        ProductBase.MATERIAL: {'view': 'purchase.view_material_godownentry_query',
                               'export': 'purchase.export_material_godownentry_query',
                               },
        ProductBase.CONSUMABLE: {'view': 'purchase.view_consumable_godownentry_query',
                                 'export': 'purchase.export_consumable_godownentry_query',
                               }
    }
    return permissions[type][action]


@token_required
def godownentry_return_list(request):
    type = int(request.GET.get('type'))
    product_notes = request.GET.get('product_notes')
    try:
        valid_permission(request.user, GodownEntryReturn.getPermissionByType(type, 'view'))
    except:
        return DataGridJSONResponse([], 0)
    warehouses_ids = Warehouse.getManagerWarehouses(request.user)
    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = GodownEntryReturn.objects.filter(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 = GodownEntryReturnDetail.objects.filter(main_id__in=g_ids, notes__icontains=product_notes).values_list('main_id')
        rows = rows.filter(id__in=d_ids)
    f = GodownEntryReturnFilter(request.GET, queryset=rows)
    total_row = f.qs.aggregate(total_count=Sum('total_count'), total_amount=Sum('total_amount'))
    more = {
        'total_count': Formater.formatCountShow(total_row['total_count']),
        'total_amount': Formater.formatAmountShow(total_row['total_amount'])
    }
    rows, total = utils.get_page_data(request, f.qs)
    serializer = GodownEntryReturnSerializer(rows, many=True)
    return DataGridJSONResponse(serializer.data, total, more)


@csrf_exempt
@token_required
def godownentry_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 = GodownEntryReturn.getValidType(request.GET.get('type'))
        main_data['type'] = type
        with transaction.atomic():
            serializer = GodownEntryReturnSerializer.factory(request.user, main_data, id)
            if serializer.instance and serializer.instance.status == settings.PASS:
                raise CustomError(u'该退货单已审核，禁止修改！')
            valid_permission(request.user, GodownEntryReturn.getPermissionByType(type, 'add'))
            serializer = serializer.validSave()
            GodownEntryReturnDetail.objects.filter(main=serializer).delete()
            for item in items_data:
                item['main'] = serializer.id
                item['amount'] = item['total_cost']
                detail_serializer = GodownEntryReturnDetailSerializer.factory(request.user, 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()


@token_required
def godownentry_return_detail(request):
    id = request.GET.get('id')
    instance = GodownEntryReturn.getById(id)
    company = instance.department.getCompany()
    warehouse_id = instance.warehouse_id
    supplier_id = instance.supplier and instance.supplier_id or None
    if instance.status == settings.PASS:
        status_text = u'已审核'
    else:
        status_text = u'待审核'
    main_data = {
        'id': instance.id,
        'warehouse_id': warehouse_id,
        'warehouse_name': instance.warehouse.name,
        'supplier_id': supplier_id,
        'supplier_name': instance.supplier and instance.supplier.name or '',
        'create_user_name': instance.create_user.name,
        'create_time': Formater.formatStrTime(instance.create_time),
        'status': instance.status,
        '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 = {
        'main_data': main_data,
        'items_data': []
    }
    detail_rows = GodownEntryReturnDetail.objects.filter(main=instance)
    for detail_row in detail_rows:

        is_godown = False
        godownentry_detail = None
        if detail_row.godownentry_detail:
            is_godown = True
            godownentry_detail = detail_row.godownentry_detail_id
        record_data = GetWarehouseSrockRecord.getRecord(detail_row.product_base_id, warehouse_id, supplier_id)
        item_data = {
            'detail_id': detail_row.id,
            'id': detail_row.id,
            'product_base_id': detail_row.product_base_id,
            'product_base_name': detail_row.product_base.name,
            'product_base_model': detail_row.product_base.model,
            'price': Formater.formatPriceShow(detail_row.price),
            'count': Formater.formatCountShow(detail_row.count),
            'amount': Formater.formatAmountShow(detail_row.amount),
            'warehouse_place': detail_row.product_base.warehouse_place,
            'unit':detail_row.product_base.unit or '',
            'is_godown': is_godown,
            'godownentry_detail': godownentry_detail,
            'notes': detail_row.notes or '',
            'entry_no': detail_row.godownentry_detail and detail_row.godownentry_detail.main.no or '',
            'record_data':record_data
        }
        data['items_data'].append(item_data)

    return JSONResponse(data)

@token_required
def get_godownentry_detail_data(request):
    id = request.GET.get('id')
    godownentry_detail = GodownEntryDetail.getById(id)
    supplier_id = godownentry_detail.main.supplier_id or None
    warehouse_id = godownentry_detail.main.warehouse_id or None
    record_data = GetWarehouseSrockRecord.getRecord(godownentry_detail.product_base_id, warehouse_id, supplier_id)
    data = {
        'main': {
            'supplier': supplier_id,
            'supplier_text': godownentry_detail.main.supplier.name or '',
            'warehouse': warehouse_id,
        },
        'items':[{
            'product_base_id': godownentry_detail.product_base_id,
            'product_base_name': godownentry_detail.product_base.name,
            'product_base_model': godownentry_detail.product_base.model,
            'unit': godownentry_detail.product_base.unit or '',
            'count': Formater.formatCountShow(godownentry_detail.count),
            'price': Formater.formatPriceShow(godownentry_detail.price),
            'godownentry_detail_id': id,
            'notes': godownentry_detail.notes or '',
            'record_data':record_data
        }]
    }
    return JSONResponse(data)

@token_required
def godownentry_return_export(request):
    try:
        type = GodownEntryReturn.getValidType(request.GET.get('type'))
        warehouses_ids = Warehouse.getManagerWarehouses(request.user)
        department_ids = request.user.getSubDepartmentIds()
        user_ids = request.user.getSubEmployeeIds()
        rows = GodownEntryReturn.objects.filter(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 = GodownEntryReturnFilter(request.GET, queryset=rows)
        serializer = GodownEntryReturnSerializer(f.qs, many=True)
        valid_permission(request.user, GodownEntryReturn.getPermissionByType(type, 'export'))
        export_data = ExportChange.dict_to_obj(serializer)
        if type == GodownEntryReturn.MATERIAL:
            perm = 'material.view_material_cost'
        elif type == GodownEntryReturn.CONSUMABLE:
            perm = 'material.view_consumable_cost'
        is_show_cost = isHasPermissions(request.user, perm)
        export_data = GodownEntryReturnResource(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 godownentry_return_export_detail(request):
    id = request.GET.get('id')
    instance = GodownEntryReturn.getById(id)
    if instance.type == GodownEntryReturn.MATERIAL:
        perm = 'material.view_material_cost'
    elif instance.type == GodownEntryReturn.CONSUMABLE:
        perm = 'material.view_consumable_cost'
    is_show_cost = isHasPermissions(request.user, perm)
    try:
        valid_permission(request.user, instance.getPermission('export'))
        godown_entry_return_detail = GodownEntryReturnDetail.objects.filter(main=instance)
        serializer = GodownEntryReturnDetailSerializer(godown_entry_return_detail, many=True)
        export_data = ExportChange.dict_to_obj(serializer)
        export_data = GodownEntryReturnDetailResource(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))
    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 godownentry_return_check(request):
    id = request.GET.get('id')
    try:
        with transaction.atomic():
            instance = GodownEntryReturn.getById(id)
            valid_permission(request.user, instance.getPermission('check'))
            if instance.status == settings.PASS:
                raise CustomError(u'该退货单已审核!')
            godownentry_return_details = GodownEntryReturnDetail.objects.filter(main=instance)
            for return_detail in godownentry_return_details:
                if return_detail.godownentry_detail:
                    warehouse_record = BizWarehouse.entryBack(return_detail.godownentry_detail.stock_record, return_detail.count)
                else:
                    warehouse_record = BizWarehouse.entryBatchBack(return_detail.product_base, return_detail.main.warehouse, return_detail.count, return_detail.main.supplier)
                return_detail.warehouse_record = warehouse_record
                return_detail.amount = -warehouse_record.amount
                return_detail.price = return_detail.amount / return_detail.count
                return_detail.save()

            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.update_total()
            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 godownentry_return_delete(request):
    id = request.GET.get('id')
    try:
        with transaction.atomic():
            instance = GodownEntryReturn.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))
            GodownEntryReturnDetail.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 godownentry_return_query_list(request):
    product_type = int(request.GET.get('type'))
    try:
        valid_permission(request.user, getReturnPermissionByType(product_type, 'view'))
    except:
        return DataGridJSONResponse([], 0)
    warehouses_ids = Warehouse.getManagerWarehouses(request.user)
    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = GodownEntryReturnDetail.objects.filter(product_base__type=product_type, main__status=settings.PASS, main__warehouse_id__in=warehouses_ids)
    rows = rows.filter(
        Q(main__department_id__in=department_ids) | Q(main__create_user_id__in=user_ids) | Q(main__create_user=request.user))
    f = GodownEntryReturnDetailFilter(request.GET, queryset=rows)
    total_row = f.qs.aggregate(total_count=Sum('count'), total_amount=Sum('amount'))
    more = {
        'total_count': Formater.formatCountShow(total_row['total_count']),
        'total_amount': Formater.formatAmountShow(total_row['total_amount'])
    }
    rows, total = utils.get_page_data(request, f.qs)
    serializer = GodownEntryReturnDetailSerializer(rows, many=True)
    return DataGridJSONResponse(serializer.data, total, more)

@token_required
def godownentry_return_query_export(request):
    product_type = int(request.GET.get('type'))
    try:
        warehouses_ids = Warehouse.getManagerWarehouses(request.user)
        department_ids = request.user.getSubDepartmentIds()
        user_ids = request.user.getSubEmployeeIds()
        rows = GodownEntryReturnDetail.objects.filter(product_base__type=product_type, main__status=settings.PASS,
                                                      main__warehouse_id__in=warehouses_ids)
        rows = rows.filter(
            Q(main__department_id__in=department_ids) | Q(main__create_user_id__in=user_ids) | Q(main__create_user=request.user))
        f = GodownEntryReturnDetailFilter(request.GET, queryset=rows)
        serializer = GodownEntryReturnDetailSerializer(f.qs, many=True)
        valid_permission(request.user, getReturnPermissionByType(product_type, 'export'))
        export_data = ExportChange.dict_to_obj(serializer)
        if product_type == ProductBase.MATERIAL:
            perm = 'material.view_material_cost'
        elif product_type == ProductBase.CONSUMABLE:
            perm = 'material.view_consumable_cost'
        is_show_cost = isHasPermissions(request.user, perm)
        export_data = GodownEntryReturnQueryResource(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 godownentry_return_query_detail(request):
    product_type = int(request.GET.get('type'))
    warehouses_ids = Warehouse.getManagerWarehouses(request.user)
    department_ids = request.user.getSubDepartmentIds()
    user_ids = request.user.getSubEmployeeIds()
    rows = GodownEntryReturnDetail.objects.filter(product_base__type=product_type, main__status=settings.PASS,
                                                  main__warehouse_id__in=warehouses_ids)
    rows = rows.filter(
        Q(main__department_id__in=department_ids) | Q(main__create_user_id__in=user_ids) | Q(main__create_user=request.user))
    f = GodownEntryReturnDetailFilter(request.GET, queryset=rows)

    serializer = GodownEntryReturnDetailSerializer(f.qs, many=True)
    return JSONResponse(serializer.data)

def getReturnPermissionByType(type, action):
    permissions = {
        ProductBase.MATERIAL: {'view': 'account.view_material_godownentry_return_query',
                               'export': 'account.export_material_godownentry_return_query',
                               },
        ProductBase.CONSUMABLE: {'view': 'account.view_consumable_godownentry_return_query',
                                 'export': 'account.export_consumable_godownentry_return_query',
                               }
    }
    return permissions[type][action]
