# coding=utf-8
from django.utils import timezone
from apps.foundation.models import Option
from apps.exceptions import CustomError
from django.db import models
from django.conf import settings
from django.db.models import Sum, Q, Count
from apps.account.models import User, Department
from apps.supplier.models import Supplier
from apps.product.models import ProductBase
from apps.warehouse.models import Warehouse, WarehouseStock, WarehouseStockRecord, WarehouseRecord
from libs.filefield import PathAndRename


class PurchasePlan(models.Model):
    no = models.CharField(max_length=20, verbose_name=u"单号", editable=False)
    name = models.CharField(max_length=100, verbose_name=u"名称")
    status = models.PositiveSmallIntegerField(choices=settings.CHECK_STATUS_CHOICES, verbose_name=u"审核状态", default=settings.DEFAULT)
    create_user = models.ForeignKey(User, verbose_name=u"创建人", related_name='purchase_plan_ref_create_user',
                                    on_delete=models.PROTECT, blank=True, editable=False)
    department = models.ForeignKey(Department, verbose_name=u"创建部门", related_name='purchase_plan_ref_department', blank=True, editable=False, on_delete=models.PROTECT)
    demend_user = models.ForeignKey(User, verbose_name=u"需求人", related_name='purchase_plan_ref_demend_user', on_delete=models.PROTECT, blank=True, null=True)
    demend_department = models.ForeignKey(Department, verbose_name=u"需求车间", related_name='purchase_plan_ref_demend_department', on_delete=models.PROTECT, null=True, blank=True)
    create_time = models.DateTimeField(verbose_name=u"下单时间",  default=timezone.now)
    check_user = models.ForeignKey(User, verbose_name=u"审核人",related_name='purchase_plan_ref_check_user', on_delete=models.PROTECT, null=True)
    check_time = models.DateTimeField(verbose_name=u"审核时间", null=True)
    total_count = models.BigIntegerField(verbose_name=u"合计数量", default=0)
    notes = models.CharField(max_length=100, verbose_name=u"备注", null=True, blank=True)

    # check_user2 = models.ForeignKey(User, verbose_name=u"复核人", related_name='purchase_plan_ref_check_user2',
    #                                 on_delete=models.PROTECT, null=True, blank=True)
    # check_time2 = models.DateTimeField(verbose_name=u"复核时间", null=True)
    #
    # check_user3 = models.ForeignKey(User, verbose_name=u"批准人", related_name='purchase_plan_ref_check_user3',
    #                                 on_delete=models.PROTECT, null=True, blank=True)
    # check_time3 = models.DateTimeField(verbose_name=u"批准时间", null=True)
    class Meta:
        db_table = "purchase_plan"
        verbose_name = u"计划管理"
        ordering = ('-id',)
        index_together = (
            'name',
            'create_time','status','check_time'
        )
        unique_together = (
            'no',
        )
        default_permissions = ()
        permissions = (# 采购计划管理
            ("view_purchase_plan", u"浏览"),
            ("add_purchase_plan", u"添加"),
            ("check_purchase_plan", u"审核"),
            ("delete_purchase_plan", u"删除"),
            ("export_purchase_plan", u"导出"),
            ("print_purchase_plan", u"打印"),
            ("export_purchase_plan_price", u"导出询价汇总"),
            ("add_purchase_user_plan", u"添加采购员"),
            ("check2_purchase_plan", u"复核"),
            ("check3_purchase_plan", u"批准"),
        )

    def isReport(self):
        purchaseprcies = PurchasePrice.objects.filter(purchase_detail__purchase=self, report=True).count()
        if purchaseprcies:
            return True
        return False

    def isCompart(self):
        purchaseprcies = PurchasePlanDetail.objects.filter(purchase=self, is_compact=True).count()
        if purchaseprcies:
            return True
        return False

    def updateTotalCount(self):
        total_count = 0
        sum_row = PurchasePlanDetail.objects.filter(purchase=self).aggregate(Sum('purchase_count'))
        if sum_row:
            total_count = sum_row['purchase_count__sum'] or 0
        self.total_count = total_count
        self.save()

    def getPurchaseDetails(self):
        return PurchasePlanDetail.objects.filter(purchase=self)

    @staticmethod
    def getById(id):
        instance = PurchasePlan.objects.filter(pk=id).first()
        if not instance:
            raise CustomError(u'未找到相应的采购计划')
        return instance

    def save(self, *args, **kwargs):
        if self.no == None or self.no == '':
            now = timezone.now()
            rows = PurchasePlan.objects.filter(create_time__gte=now.strftime('%Y-%m-%d')).order_by('-no')
            count = rows.count()
            if count == 0:
                self.no = 'CG%s%03d' % (now.strftime('%Y%m%d'), count + 1)
            else:
                self.no = rows[0].no[:2] + str(int(rows[0].no[2:]) + 1)
        super(PurchasePlan, self).save(*args, **kwargs)

    def removeCompact(self):
        PurchasePlanDetail.objects.filter(purchase=self).update(is_compact=False)

    def updateCompact(self):
        self.removeCompact()
        product_ids = PurchaseOrderDetail.objects.filter(main__plan=self).values_list('product_id',flat=True)
        PurchasePlanDetail.objects.filter(purchase=self,product_id__in=product_ids).update(is_compact=True)


class PurchasePlanDetail(models.Model):
    purchase = models.ForeignKey(PurchasePlan, verbose_name=u"采购计划", on_delete=models.PROTECT)
    product = models.ForeignKey(ProductBase, verbose_name=u"产品", on_delete=models.PROTECT)
    #quality_request = models.ForeignKey(Option, verbose_name=u"质量要求", null=True, blank=True, on_delete=models.PROTECT)
    quality_request_text = models.CharField(max_length=100, verbose_name=u"质量要求", null=True, blank=True)
    purchase_count = models.BigIntegerField(u"采购数量", default=0)
    product_time = models.DateTimeField(verbose_name=u"需求时间", null=True, blank=True)
    notes = models.CharField(max_length=100, verbose_name=u"备注", null=True, blank=True)
    is_compact = models.BooleanField(verbose_name=u"生成采购合同", default=False)

    class Meta:
        db_table = "purchase_plan_detail"
        verbose_name = u"退料查询"
        default_permissions = ()
        permissions = (# 采购计划明细
            ("view_consumable_deliver_return_query", u"浏览"),
            ("export_consumable_deliver_return_query", u"导出"),
            ("print_consumable_deliver_return_query", u"打印"),
        )

    @staticmethod
    def getById(id):
        instance = PurchasePlanDetail.objects.filter(id=id).first()
        if not instance:
            raise CustomError(u'未找到相应的采购计划明细')
        return instance

class PurchaseUser(models.Model):
    purchase = models.ForeignKey(PurchasePlan, verbose_name=u"采购计划", on_delete=models.PROTECT)
    purchase_user = models.ForeignKey(User, verbose_name=u"采购员", on_delete=models.PROTECT, blank=True)

    class Meta:
        db_table = "purchase_user"
        verbose_name = u"询价管理"
        default_permissions = ()
        permissions = (
            ("view_purchase_user_plan", u"浏览"),
            ("add_purchase_price_plan", u"上报价格"),
            ("edit_purchase_price", u"修改询价"),
        )


class PurchasePrice(models.Model):
    purchase_detail = models.ForeignKey(PurchasePlanDetail, verbose_name=u"采购计划明细", on_delete=models.PROTECT, blank=True)
    purchase_user = models.ForeignKey(User, verbose_name=u"采购员", on_delete=models.PROTECT, blank=True)
    report = models.BooleanField(verbose_name=u"上报", default=False)
    supplier = models.ForeignKey(Supplier, verbose_name=u"供应商", on_delete=models.PROTECT, null=True)
    price = models.BigIntegerField(u"价格", default=0)
    tax_rate = models.FloatField(verbose_name=u"税率", null=True, blank=True)
    notes = models.CharField(max_length=100, verbose_name=u"备注", null=True, blank=True)

    class Meta:
        db_table = "purchase_plan_price"
        verbose_name = u"入库查询"
        ordering = ('-id',)
        default_permissions = ()
        permissions = (# 询价记录
            ("view_material_godownentry_query", u"浏览"),
            ("export_material_godownentry_query", u"导出"),
            ("print_material_godownentry_query", u"打印"),
        )

    @staticmethod
    def getById(id):
        instances = PurchasePrice.objects.filter(pk=id).first()
        if not instances:
            raise CustomError(u'未找到相应的询价记录')
        return instances


class PurchaseOrder(models.Model):
    DEFAULT = 0
    PASS = 1
    STATUS_CHOICES = (
        (DEFAULT, u'未审核'),
        (PASS, u'已审核')
    )

    NO_ARRVAL = 0
    PART_ARRVAL = 1
    ALL_ARRVAL = 2
    ARRVAL_CHOICES = (
        (NO_ARRVAL, u'未到货'),
        (PART_ARRVAL, u'部分到货'),
        (ALL_ARRVAL, u'全部到货'),
    )

    no = models.CharField(max_length=50, verbose_name=u"合同号",  null=True)
    order_no = models.CharField(max_length=50, verbose_name=u"单号", editable=False)
    supplier = models.ForeignKey(Supplier, verbose_name=u"供应商", on_delete=models.PROTECT)
    count = models.BigIntegerField(u'数量', default=0)
    amount = models.BigIntegerField(u'金额', default=0)
    apply_amount = models.BigIntegerField(verbose_name=u'申请金额', default=0)
    plan = models.ForeignKey(PurchasePlan, verbose_name=u"采购计划", on_delete=models.PROTECT, blank=True,null=True)
    status = models.PositiveSmallIntegerField(choices=STATUS_CHOICES, verbose_name=u"状态", default=DEFAULT)
    arrval = models.PositiveSmallIntegerField(choices=ARRVAL_CHOICES, verbose_name=u"到货", default=NO_ARRVAL)
    notes = models.CharField(max_length=200, verbose_name=u"备注", blank=True, null=True)
    create_time = models.DateTimeField(verbose_name=u"创建时间", default=timezone.now)
    create_user = models.ForeignKey(User, related_name='purchase_order_ref_create_user', verbose_name=u"创建人", on_delete=models.PROTECT, editable=False)
    department = models.ForeignKey(Department, verbose_name=u"创建部门", editable=False, on_delete=models.PROTECT)
    check_time = models.DateTimeField(verbose_name=u"审核时间", null=True)
    check_user = models.ForeignKey(User, related_name='purchase_order_ref_check_user', verbose_name=u"审核人", on_delete=models.PROTECT, null=True)
    payment_type = models.CharField(max_length=50, verbose_name=u"付款方式", null=True, blank=True)
    deliver_time = models.CharField(max_length=200, verbose_name=u"交货时间", blank=True, null=True)

    # check_user2 = models.ForeignKey(User, verbose_name=u"复核人", related_name='purchase_order_ref_check_user2',
    #                                 on_delete=models.PROTECT, null=True, blank=True)
    # check_time2 = models.DateTimeField(verbose_name=u"复核时间", null=True)
    #
    # check_user3 = models.ForeignKey(User, verbose_name=u"批准人", related_name='purchase_order_ref_check_user3',
    #                                 on_delete=models.PROTECT, null=True, blank=True)
    # check_time3 = models.DateTimeField(verbose_name=u"批准时间", null=True)
    consignee_name = models.CharField(max_length=100, verbose_name=u"收货人姓名", null=True)
    consignee_tel = models.CharField(max_length=100, verbose_name=u"收货人电话", null=True)

    handing_amount = models.BigIntegerField(u'装卸费用', default=0)
    transport_amount = models.BigIntegerField(u'运输费用', default=0)

    class Meta:
        db_table = "purchase_order"
        verbose_name = u"合同管理"
        ordering = ('-id',)
        index_together = (
            'create_time', 'check_time', 'status', 'no'
        )
        unique_together = (
            'order_no',
        )
        default_permissions = ()
        permissions = (# 采购合同管理
            ("view_purchase_order", u"浏览"),
            ("add_purchase_order", u"添加"),
            ("edit_purchase_order", u"修改"),
            ("senior_purchase_order", u"高级修改"),
            ("check_purchase_order", u"审核"),
            ("delete_purchase_order", u"删除"),
            ("export_purchase_order", u"导出"),
            ("print_purchase_order", u"打印"),
            # ("check2_purchase_order", u"复核"),
            # ("check3_purchase_order", u"批准"),
        )

    def updateApplyAmount(self):
        sum_amount = 0
        sum_rows = PurchasePayment.objects.filter(order=self).aggregate(sum_amount=Sum('apply_amount'))
        if sum_rows:
            sum_amount = sum_rows['sum_amount'] or 0

        self.apply_amount = sum_amount
        self.save()

    def save(self, *args, **kwargs):
        if self.order_no == None or self.order_no == '':
            now = timezone.now()
            rows = PurchaseOrder.objects.filter(create_time__gte=now.strftime('%Y-%m-%d')).order_by('-order_no')
            count = rows.count()
            if count == 0:
                self.order_no = 'CN%s%03d' % (now.strftime('%Y%m%d'), count + 1)
            else:
                self.order_no = rows[0].order_no[:2] + str(int(rows[0].order_no[2:]) + 1)
        super(PurchaseOrder, self).save(*args, **kwargs)

    @staticmethod
    def getById(id):
        instance = PurchaseOrder.objects.filter(pk=id).first()
        if not instance:
            raise CustomError(u'未找到相应的采购合同')
        return instance

    def updateAmount(self):
        sum_count = 0
        sum_amount = 0

        sum_row = PurchaseOrderDetail.objects.filter(main=self).aggregate(sum_count=Sum('count'), sum_amount=Sum('amount'))
        if sum_row:
            sum_count = sum_row['sum_count'] or 0
            sum_amount = sum_row['sum_amount'] or 0

        self.count = sum_count
        self.amount = sum_amount
        self.save()

    def updateArrval(self):
        rows = PurchaseOrderDetail.objects.filter(main=self)
        for row in rows:
            arrval_count = 0
            g_rows = GodownEntryDetail.objects.filter(product_base_id=row.product_id, main__purchase_order=self, main__status=settings.PASS).aggregate(sum_count=Sum('count'))
            if g_rows:
                arrval_count = g_rows['sum_count'] or 0
            row.arrval_count = arrval_count
            if row.arrval_count >= row.count:
                row.is_arrval = True
            else:
                row.is_arrval = False
            row.save()

        sum_arrval_count = 0
        d_rows = PurchaseOrderDetail.objects.filter(main=self).aggregate(sum_count=Sum('arrval_count'))
        if d_rows:
            sum_arrval_count = d_rows['sum_count'] or 0

        if sum_arrval_count == 0:
            self.arrval = PurchaseOrder.NO_ARRVAL
            self.save()
        else:
            all_arrval = True
            for row in rows:
                if not row.is_arrval:
                    all_arrval = False
                    break

            if all_arrval:
                self.arrval = PurchaseOrder.ALL_ARRVAL
            else:
                self.arrval = PurchaseOrder.PART_ARRVAL
            self.save()

path_and_rename = PathAndRename("purchase_order/invoice/")
class PurchaseOrderDetail(models.Model):
    main = models.ForeignKey(PurchaseOrder, verbose_name=u'采购合同', on_delete=models.PROTECT)
    product = models.ForeignKey(ProductBase, verbose_name=u'产品', on_delete=models.PROTECT)
    #quality_request = models.ForeignKey(Option, verbose_name=u"质量标准", null=True, on_delete=models.PROTECT)
    quality_request_text = models.CharField(max_length=100, verbose_name=u"质量要求", null=True, blank=True)
    count = models.BigIntegerField(u'数量', default=0)
    price = models.BigIntegerField(u'单价', default=0)
    amount = models.BigIntegerField(u'金额', default=0)
    arrval_count = models.BigIntegerField(u'到货数量', default=0)
    is_arrval = models.BooleanField(verbose_name=u"全部到货", default=0)
    invoice_no = models.CharField(max_length=50, verbose_name=u"发票号", null=True)
    invoice_amount = models.BigIntegerField(u'发票金额', null=True)
    invoice_date = models.DateField(verbose_name=u"开票日期", null=True)
    create_time = models.DateTimeField(verbose_name=u"录入时间", null=True)
    create_user = models.ForeignKey(User, related_name='purchase_order_detail_ref_create_user', verbose_name=u"录入人",
                                   on_delete=models.PROTECT, null=True)
    department = models.ForeignKey(Department, verbose_name=u"录入部门", null=True, on_delete=models.PROTECT)
    check_time = models.DateTimeField(verbose_name=u"审核时间", null=True)
    check_user = models.ForeignKey(User, related_name='purchase_order_detail_ref_check_user', verbose_name=u"审核人",
                                   on_delete=models.PROTECT, null=True)
    check_status = models.PositiveSmallIntegerField(choices=settings.CHECK_STATUS_CHOICES,
                                              verbose_name=u"审核状态", default=settings.DEFAULT)

    class Meta:
        db_table = "purchase_order_detail"
        verbose_name = u"发票管理"
        ordering = ('-id',)
        default_permissions = ()
        permissions = (# 采购合同明细
            ("view_purchase_invoice", u"浏览"),
            ("add_purchase_invoice", u"录入"),
            ("check_purchase_invoice", u"审核"),
            ("export_purchase_invoice", u"导出"),
        )

    @staticmethod
    def getById(id):
        instances = PurchaseOrderDetail.objects.filter(id=id).first()
        if not instances:
            raise CustomError(u'未找到相应的合同明细')
        return instances

class PurchaseInvoiceImage(models.Model):
    order_detail = models.ForeignKey(PurchaseOrderDetail, related_name='invoice_image_ref_purchase_order_detail', verbose_name=u"合同明细",
                                    editable=False)
    invoice_image = models.ImageField(verbose_name=u"发票图片", default='', null=True, upload_to=path_and_rename,
                                      blank=True)
    class Meta:
        db_table = "purchase_invoice_image"
        verbose_name = u"采购合同发票图片"

class PurchasePayment(models.Model):
    no = models.CharField(max_length=20, verbose_name=u"单号", editable=False)
    order = models.ForeignKey(PurchaseOrder, verbose_name=u"合同", on_delete=models.PROTECT)
    status = models.PositiveSmallIntegerField(choices=settings.CHECK_STATUS_CHOICES, default=settings.DEFAULT, verbose_name=u"状态")
    amount = models.BigIntegerField(verbose_name=u'合同金额', default=0) # 1、标准模式：材料费用+ 运费+装卸费。2、简易模式：材料费用
    actual_amount = models.BigIntegerField(verbose_name=u'实付金额', default=0) # 已付金额
    apply_amount = models.BigIntegerField(verbose_name=u'申请金额', default=0) # 简易费用，此值为材料费用
    is_pay = models.BooleanField(verbose_name=u"是否付款", default=0)
    notes = models.CharField(max_length=200, verbose_name=u"申请备注", blank=True, null=True)
    create_time = models.DateTimeField(verbose_name=u"创建时间", default=timezone.now)
    create_user = models.ForeignKey(User, related_name='purchase_payment_ref_create_user', verbose_name=u"创建人", on_delete=models.PROTECT, editable=False)
    department = models.ForeignKey(Department, verbose_name=u"创建部门", editable=False, on_delete=models.PROTECT)
    check_time = models.DateTimeField(verbose_name=u"审核时间", null=True)
    check_user = models.ForeignKey(User, related_name='purchase_payment_ref_check_user', verbose_name=u"审核人", on_delete=models.PROTECT, null=True)
    # review_user = models.ForeignKey(User, verbose_name=u"复核人", related_name='purchase_payment_ref_review_user',
    #                                 on_delete=models.PROTECT, null=True, blank=True)
    # review_time = models.DateTimeField(verbose_name=u"复核时间", null=True)
    #
    # ratify_user = models.ForeignKey(User, verbose_name=u"批准人", related_name='purchase_payment_ref_ratify_user',
    #                                 on_delete=models.PROTECT, null=True, blank=True)
    # ratify_time = models.DateTimeField(verbose_name=u"批准时间", null=True)
    is_clear = models.BooleanField(verbose_name=u"是否结清", default=0)

    class Meta:
        db_table = "purchase_payment"
        verbose_name = u"付款管理"
        ordering = ('-id',)
        index_together = (
            'create_time', 'check_time', 'status'
        )
        unique_together = (
            'no',
        )
        default_permissions = ()
        permissions = (
            ("view_purchase_payment", u"浏览"),
            ("add_purchase_payment", u"添加"),
            ("check_purchase_payment", u"审核"),
            # ("review_purchase_payment", u"复核"),
            # ("ratify_purchase_payment", u"批准"),
            ("pay_purchase_payment", u"付款"),
            ("delete_purchase_payment", u"删除"),
            ("export_purchase_payment", u"导出"),
            ("print_purchase_payment", u"打印"),
        )

    @staticmethod
    def getById(id):
        instance = PurchasePayment.objects.filter(pk=id).first()
        if not instance:
            raise CustomError(u'未找到相应的付款单')
        return instance

    def updateAmount(self):
        sum_amount = 0
        sum_row = PurchasePaymentDetail.objects.filter(main=self).aggregate(sum_amount=Sum('purchase_detail__amount'))
        if sum_row:
            sum_amount = sum_row['sum_amount'] or 0

        self.amount = sum_amount
        self.save()

    def updateActualAmount(self):
        sum_actual_amount = 0
        sum_row = PurchasePay.objects.filter(main=self).aggregate(sum_actual_amount=Sum('actual_amount'))
        if sum_row:
            sum_actual_amount = sum_row['sum_actual_amount'] or 0

        self.actual_amount = sum_actual_amount
        self.save()

    def save(self, *args, **kwargs):
        if self.no == None or self.no == '':
            now = timezone.now()
            rows = PurchasePayment.objects.filter(create_time__gte=now.strftime('%Y-%m-%d')).order_by('-no')
            count = rows.count()
            if count == 0:
                self.no = 'CY%s%03d' % (now.strftime('%Y%m%d'), count + 1)
            else:
                self.no = rows[0].no[:2] + str(int(rows[0].no[2:]) + 1)
        super(PurchasePayment, self).save(*args, **kwargs)


class PurchasePaymentDetail(models.Model):
    main = models.ForeignKey(PurchasePayment, verbose_name=u"付款单", on_delete=models.PROTECT)
    purchase_detail = models.ForeignKey(PurchaseOrderDetail, verbose_name=u"合同明细", on_delete=models.PROTECT)
    class Meta:
        db_table = "purchase_payment_detail"
        verbose_name = u"入库查询"
        ordering = ('-id',)
        default_permissions = ()
        permissions = ( # 付款明细
            ("view_consumable_godownentry_query", u"浏览"),
            ("export_consumable_godownentry_query", u"导出"),
            ("print_consumable_godownentry_query", u"打印"),
        )

class PurchasePay(models.Model):
    main = models.ForeignKey(PurchasePayment, verbose_name=u"付款单", on_delete=models.PROTECT)
    payment_type = models.ForeignKey(Option, verbose_name=u"付款方式", on_delete=models.PROTECT)
    payment_time = models.DateTimeField(verbose_name=u"付款时间", default=timezone.now)
    actual_amount = models.BigIntegerField(verbose_name=u'实付金额', default=0)
    payment_user = models.ForeignKey(User, verbose_name=u"付款人", editable=False,on_delete=models.PROTECT)
    payment_department = models.ForeignKey(Department, verbose_name=u"付款部门", editable=False, on_delete=models.PROTECT)
    notes = models.CharField(max_length=200, verbose_name=u"备注", blank=True, null=True)

    class Meta:
        db_table = "purchase_pay"
        verbose_name = u"付款明细"
        ordering = ('-id',)
        default_permissions = ()

    @staticmethod
    def getByMainId(id):
        instances = PurchasePay.objects.filter(main_id=id)
        if not instances:
            raise CustomError(u'未找到相应的付款单')
        return instances

    @staticmethod
    def getById(id):
        instance = PurchasePay.objects.filter(id=id).first()
        if not instance:
            raise CustomError(u'未找到相应的付款单')
        return instance

class GodownEntry(models.Model):
    MATERIAL = 0
    CONSUMABLE = 1
    PRODUCT_CHOICES = (
        (MATERIAL, u'原料'),
        (CONSUMABLE, u'耗材'),
    )
    PREFIX_CHOICES = (
        (MATERIAL, 'MR'),
        (CONSUMABLE, 'CR'),
    )

    no = models.CharField(max_length=20, verbose_name=u"入库单号", editable=False)
    supplier = models.ForeignKey(Supplier, verbose_name=u'供应商', on_delete=models.PROTECT)
    purchase_order = models.ForeignKey(PurchaseOrder, verbose_name=u'采购合同', blank=True, null=True, on_delete=models.PROTECT)
    total_count = models.BigIntegerField(verbose_name=u'数量合计', default=0)
    total_amount = models.BigIntegerField(verbose_name=u'金额合计', default=0)
    total_invoice_amount = models.BigIntegerField(verbose_name=u'发票金额合计', default=0) #等于明细里面的发票金额合计
    create_user = models.ForeignKey(User, related_name='godown_entry_ref_create_user', verbose_name=u"创建人", on_delete=models.PROTECT, editable=False)
    department = models.ForeignKey(Department, verbose_name=u"创建部门", on_delete=models.PROTECT, editable=False)
    create_time = models.DateTimeField(verbose_name=u"创建时间", default=timezone.now)
    status = models.PositiveSmallIntegerField(choices=settings.CHECK_STATUS_CHOICES, default=settings.DEFAULT, verbose_name=u"审核状态")
    check_user = models.ForeignKey(User, related_name='godown_entry_ref_check_user', verbose_name=u"审核人", on_delete=models.PROTECT, blank=True, null=True)
    check_time = models.DateTimeField(verbose_name=u"审核时间", blank=True, null=True)
    notes = models.TextField(verbose_name=u"备注", blank=True, null=True)
    warehouse = models.ForeignKey(Warehouse, verbose_name=u'仓别', on_delete=models.PROTECT)
    product_type = models.PositiveSmallIntegerField(choices=PRODUCT_CHOICES, verbose_name=u"产品类型")
    total_return_count = models.BigIntegerField(verbose_name=u"退货数量合计", default=0)
    total_return_amount = models.BigIntegerField(verbose_name=u"退货金额合计", default=0)
    total_deliver_count = models.BigIntegerField(verbose_name=u"出库数量合计", default=0)
    total_deliver_amount = models.BigIntegerField(verbose_name=u"出库金额合计", default=0)


    class Meta:
        db_table = "godown_entry"
        verbose_name = u"入库管理"
        ordering = ('-id',)
        index_together = (
            'create_time', 'check_time', 'status'
        )
        unique_together = (
            'no',
        )
        default_permissions = ()
        permissions = (
            ("view_material_godown_entry", u"浏览"),
            ("add_material_godown_entry", u"添加"),
            ("check_material_godown_entry", u"审核"),
            ("delete_material_godown_entry", u"删除"),
            ("export_material_godown_entry", u"导出"),
            ("import_material_godown_entry", u"导入"),
            ("print_material_godown_entry", u"打印"),
            ("edit_material_godown_entry", u"高级修改"),
        )

    @staticmethod
    def getById(id):
        instances = GodownEntry.objects.filter(id=id).first()
        if not instances:
            raise CustomError(u'未找到相应的入库单')
        return instances

    @staticmethod
    def getPermissionByType(type, action):
        permissions = GodownEntry.getPermissionMap()
        type = GodownEntry.getValidType(type)
        return permissions[type][action]

    @staticmethod
    def getPermissionMap():
        permissions = {
            GodownEntry.MATERIAL: {'view': 'purchase.view_material_godown_entry',
                                   'add': 'purchase.add_material_godown_entry',
                                   'check': 'purchase.check_material_godown_entry',
                                   'delete': 'purchase.delete_material_godown_entry',
                                   'export': 'purchase.export_material_godown_entry',
                                   'import': 'purchase.import_material_godown_entry',
                                   'print': 'purchase.print_material_godown_entry',
                                   'edit': "purchase.edit_consumable_godown_entry",
                                   },

            GodownEntry.CONSUMABLE: {'view': 'purchase.view_consumable_godown_entry',
                                   'add': 'purchase.add_consumable_godown_entry',
                                   'check': 'purchase.check_consumable_godown_entry',
                                   'delete': 'purchase.delete_consumable_godown_entry',
                                   'export': 'purchase.export_consumable_godown_entry',
                                   'import': 'purchase.import_consumable_godown_entry',
                                   'print': 'purchase.print_consumable_godown_entry',
                                   'edit': "purchase.edit_consumable_godown_entry",
                                   },
        }
        return permissions


    @staticmethod
    def getValidType(type):
        try:
            type = int(type)
        except:
            raise CustomError(u'错误的入库类型')

        types = (r[0] for r in GodownEntry.PRODUCT_CHOICES)
        if type not in types:
            raise CustomError(u'无效的入库类型')
        return type

    def getPermission(self, action):
        permissions = GodownEntry.getPermissionMap()
        return permissions[self.product_type][action]

    def save(self, *args, **kwargs):
        if self.no == None or self.no == '':
            now = timezone.now()
            rows = GodownEntry.objects.filter(create_time__gte=now.strftime('%Y-%m-%d'), product_type=self.product_type).order_by('-no')
            count = rows.count()
            prefix = GodownEntry.PREFIX_CHOICES[self.product_type][1]
            if count == 0:
                self.no = '%s%s%03d' % (prefix, now.strftime('%Y%m%d'), count + 1)
            else:
                self.no = rows[0].no[:2] + str(int(rows[0].no[2:]) + 1)
        super(GodownEntry, self).save(*args, **kwargs)

    def update_total(self):
        total_count = 0
        total_amount = 0
        total_invoice_amount = 0
        sum_row = GodownEntryDetail.objects.filter(main=self).aggregate(total_count=Sum('count'),\
                                        total_amount=Sum('amount'), total_invoice_amount=Sum('invoice_amount'))
        if sum_row:
            total_count = sum_row['total_count'] or 0
            total_amount = sum_row['total_amount'] or 0
            total_invoice_amount = sum_row['total_invoice_amount'] or 0
        self.total_count = total_count
        self.total_amount = total_amount
        self.total_invoice_amount = total_invoice_amount
        self.save()

    def update_redundant(self):
        total_return_count = 0
        total_return_amount = 0
        total_deliver_count = 0
        total_deliver_amount = 0

        sum_row = GodownEntryDetail.objects.filter(main=self).aggregate(sum_return_count=Sum('return_count'), sum_return_amount=Sum('return_amount'),
                                                                        sum_deliver_count=Sum('deliver_count'), sum_deliver_amount=Sum('deliver_amount'))
        if sum_row:
            total_return_count = sum_row['sum_return_count'] or 0
            total_return_amount = sum_row['sum_return_amount'] or 0
            total_deliver_count = sum_row['sum_deliver_count'] or 0
            total_deliver_amount = sum_row['sum_deliver_amount'] or 0

        self.total_return_count = total_return_count
        self.total_return_amount = total_return_amount
        self.total_deliver_count = total_deliver_count
        self.total_deliver_amount = total_deliver_amount
        self.save()


class GodownEntryDetail(models.Model):
    main = models.ForeignKey(GodownEntry, verbose_name=u'入库单',related_name='godown_entry_detail_ref_main', on_delete=models.PROTECT)
    product_base = models.ForeignKey(ProductBase, verbose_name=u'产品', on_delete=models.PROTECT)
    count = models.BigIntegerField(verbose_name=u'数量', default=0)
    price = models.BigIntegerField(verbose_name=u'单价', default=0)
    warehouse_stock = models.ForeignKey(WarehouseStock, verbose_name=u'仓别库存', on_delete=models.PROTECT, editable=False)
    stock_record = models.ForeignKey(WarehouseStockRecord, verbose_name=u'库存记录', on_delete=models.PROTECT, null=True,blank=True, related_name='godown_entry_detail_ref_stock_record',)

    amount = models.BigIntegerField(verbose_name=u'金额', default=0)#数量*单价
    invoice_amount = models.BigIntegerField(verbose_name=u'发票金额', default=0) #手工录入
    return_count = models.BigIntegerField(verbose_name=u"退货数量", default=0)
    return_amount = models.BigIntegerField(verbose_name=u"退货金额", default=0)
    deliver_count = models.BigIntegerField(verbose_name=u"出库数量", default=0)
    deliver_amount = models.BigIntegerField(verbose_name=u"出库金额", default=0)
    notes = models.CharField(max_length=200, verbose_name=u"备注", blank=True, null=True)

    class Meta:
        db_table = "godown_entry_detail"
        verbose_name = u"入库管理"
        ordering = ('-id',)
        default_permissions = ()
        permissions = (# 原料/耗材入库明细
            ("view_consumable_godown_entry", u"浏览"),
            ("add_consumable_godown_entry", u"添加"),
            ("check_consumable_godown_entry", u"审核"),
            ("delete_consumable_godown_entry", u"删除"),
            ("export_consumable_godown_entry", u"导出"),
            ("import_consumable_godown_entry", u"导入"),
            ("print_consumable_godown_entry", u"打印"),
            ("edit_consumable_godown_entry", u"高级修改"),
        )

    @staticmethod
    def getById(id):
        instances = GodownEntryDetail.objects.filter(id=id).first()
        if not instances:
            raise CustomError(u'未找到相应的入库明细')
        return instances


class GodownEntryReturn(models.Model):
    MATERIAL = 0
    CONSUMABLE = 1
    PRODUCT_CHOICES = (
        (MATERIAL, u'原料'),
        (CONSUMABLE, u'耗材'),
    )
    PREFIX_CHOICES = (
        (MATERIAL, 'MT'),
        (CONSUMABLE, 'CT'),
    )
    no = models.CharField(max_length=20, verbose_name=u"单号", editable=False)
    type = models.PositiveSmallIntegerField(choices=PRODUCT_CHOICES, verbose_name=u"产品类型")
    supplier = models.ForeignKey(Supplier, verbose_name=u"供应商", null=True, blank=True, on_delete=models.PROTECT)
    warehouse = models.ForeignKey(Warehouse, verbose_name=u"仓别", on_delete=models.PROTECT)

    create_time = models.DateTimeField(verbose_name=u"创建时间", default=timezone.now)
    create_user = models.ForeignKey(User, related_name='godown_entry_return_ref_create_user', verbose_name=u"创建人", on_delete=models.PROTECT, editable=False)
    department = models.ForeignKey(Department, verbose_name=u"创建部门", editable=False, on_delete=models.PROTECT)
    status = models.PositiveSmallIntegerField(choices=settings.CHECK_STATUS_CHOICES, default=settings.DEFAULT, verbose_name=u"审核状态")
    check_user = models.ForeignKey(User, related_name='godown_entry_return_ref_check_user', verbose_name=u"审核人", on_delete=models.PROTECT, blank=True, null=True)
    check_time = models.DateTimeField(verbose_name=u"审核时间", blank=True, null=True)
    notes = models.CharField(max_length=200, verbose_name=u"备注", blank=True, null=True)

    total_count = models.BigIntegerField(verbose_name=u"合计数量", default=0)
    total_amount = models.BigIntegerField(verbose_name=u"合计金额", default=0)

    class Meta:
        db_table = "godown_entry_return"
        verbose_name = u"退货管理"
        ordering = ('-id',)
        index_together = (
            'create_time', 'check_time', 'status'
        )
        unique_together = (
            'no',
        )
        default_permissions = ()
        permissions = (
            ("view_material_godown_entry_return", u"浏览"),
            ("add_material_godown_entry_return", u"添加"),
            ("check_material_godown_entry_return", u"审核"),
            ("delete_material_godown_entry_return", u"删除"),
            ("export_material_godown_entry_return", u"导出"),
            ("print_material_godown_entry_return", u"打印"),
        )

    @staticmethod
    def getById(id):
        instances = GodownEntryReturn.objects.filter(id=id).first()
        if not instances:
            raise CustomError(u'未找到相应的退货单')
        return instances

    @staticmethod
    def getPermissionByType(type, action):
        permissions = GodownEntryReturn.getPermissionMap()
        type = GodownEntryReturn.getValidType(type)
        return permissions[type][action]

    @staticmethod
    def getPermissionMap():
        permissions = {
            GodownEntryReturn.MATERIAL: {'view': 'purchase.view_material_godown_entry_return',
                                   'add': 'purchase.add_material_godown_entry_return',
                                   'check': 'purchase.check_material_godown_entry_return',
                                   'delete': 'purchase.delete_material_godown_entry_return',
                                   'export': 'purchase.export_material_godown_entry_return',
                                   'print': 'purchase.print_material_godown_entry_return'
                                   },

            GodownEntryReturn.CONSUMABLE: {'view': 'purchase.view_consumable_godown_entry_return',
                                     'add': 'purchase.add_consumable_godown_entry_return',
                                     'check': 'purchase.check_consumable_godown_entry_return',
                                     'delete': 'purchase.delete_consumable_godown_entry_return',
                                     'export': 'purchase.export_consumable_godown_entry_return',
                                     'print': 'purchase.print_consumable_godown_entry_return'
                                     },
        }
        return permissions

    @staticmethod
    def getValidType(type):
        try:
            type = int(type)
        except:
            raise CustomError(u'错误的退货类型')

        types = (r[0] for r in GodownEntryReturn.PRODUCT_CHOICES)
        if type not in types:
            raise CustomError(u'无效的退货类型')
        return type

    def getPermission(self, action):
        permissions = GodownEntryReturn.getPermissionMap()
        return permissions[self.type][action]

    def save(self, *args, **kwargs):
        if self.no == None or self.no == '':
            now = timezone.now()
            rows = GodownEntryReturn.objects.filter(create_time__gte=now.strftime('%Y-%m-%d'), type=self.type).order_by('-no')
            count = rows.count()
            prefix = GodownEntryReturn.PREFIX_CHOICES[self.type][1]
            if count == 0:
                self.no = '%s%s%03d' % (prefix, now.strftime('%Y%m%d'), count + 1)
            else:
                self.no = rows[0].no[:2] + str(int(rows[0].no[2:]) + 1)
        super(GodownEntryReturn, self).save(*args, **kwargs)


    def update_total(self):
        total_count = 0
        total_amount = 0
        sum_row = GodownEntryReturnDetail.objects.filter(main=self).aggregate(total_count=Sum('count'), total_amount=Sum('amount'))
        if sum_row:
            total_count = sum_row['total_count'] or 0
            total_amount = sum_row['total_amount'] or 0
        self.total_count = total_count
        self.total_amount = total_amount
        self.save()


class GodownEntryReturnDetail(models.Model):
    main = models.ForeignKey(GodownEntryReturn, verbose_name=u"退货单", related_name='godown_entry_return_detail_ref_main', on_delete=models.PROTECT)
    product_base = models.ForeignKey(ProductBase, verbose_name=u'产品')
    count = models.BigIntegerField(verbose_name=u"数量", default=0)
    price = models.BigIntegerField(verbose_name=u"单价", default=0)
    amount = models.BigIntegerField(verbose_name=u"金额", default=0)
    warehouse_stock = models.ForeignKey(WarehouseStock, verbose_name=u'仓别库存', on_delete=models.PROTECT, editable=False)
    warehouse_record = models.ForeignKey(WarehouseRecord, verbose_name=u'出入库记录', on_delete=models.PROTECT, null=True,
                                     blank=True, related_name='godown_entry_return_detail_ref_warehouse_record', )
    godownentry_detail = models.ForeignKey(GodownEntryDetail, verbose_name=u"入库明细", on_delete=models.PROTECT, null=True, blank=True)
    notes = models.CharField(max_length=200, verbose_name=u"备注", blank=True, null=True)

    class Meta:
        db_table = "godown_entry_detail_return"
        verbose_name = u"退货管理"
        ordering = ('-id',)
        default_permissions = ()
        permissions = (# 退货明细
            ("view_consumable_godown_entry_return", u"浏览"),
            ("add_consumable_godown_entry_return", u"添加"),
            ("check_consumable_godown_entry_return", u"审核"),
            ("delete_consumable_godown_entry_return", u"删除"),
            ("export_consumable_godown_entry_return", u"导出"),
            ("print_consumable_godown_entry_return", u"打印"),
        )

    @staticmethod
    def getById(id):
        instances = GodownEntryReturnDetail.objects.filter(id=id).first()
        if not instances:
            raise CustomError(u'未找到相应的退货明细')
        return instances

    @staticmethod
    def getById2(id):
        instances = GodownEntryReturnDetail.objects.filter(id=id).first()
        if not instances:
            return None
        return instances
