class ProductputinModule(QWidget, Ui_Form):
    accepted = pyqtSignal()

    def __init__(self, autoid:int=0, ppid: int=0, parent=None):
        super(ProductputinModule, self).__init__(parent)
        self.setupUi(self)
        self.ppid = ppid
        self.autoid = autoid
        self.bpamount = decimal.Decimal('0')
        self.mpamount = decimal.Decimal('0')
        self.spamount = decimal.Decimal('0')
        self.a_box_samount = decimal.Decimal('0')
        self.oddments_list = []
        self.units = set()
        self.WC = WorkshopController()
        self.LC = LabrecordsController()
        self.PC = ProductController()
        self.product_detail = dict()
        self.ori_detail = dict()
        self.new_detail = dict()
        if not self.ppid and not self.autoid:
            return
        # 把autoid和ppid补全
        self.get_autoid_or_ppid()
        # 获取产品信息
        self.get_productdetail()
        # 设置比例、一箱数量等参数
        self.basicdetail()
        # 获取寄库和入库位置的下拉选项
        self.get_postiton()
        # 获取报告书的状态和编号
        self.get_labdetail()
        # 获取入库信息
        self.get_putinnote()
        # 获取零头领取信息
        self.get_oddment()
        # 整箱数量的校验器
        self.set_valitor(self.lineEdit_amount, 0)
        # 零头数量的校验器
        self.set_valitor(self.lineEdit_oddment, 0, self.a_box_samount)
        self.set_total_amount()

    def get_autoid_or_ppid(self):
        values_list = ('autoid', 'ppid')
        if self.autoid:
            key_dict = {'autoid': self.autoid}
        else:
            key_dict = {'ppid': self.ppid}
        res = self.WC.get_productputinnote(False, *values_list, **key_dict)
        if not len(res):
            return
        self.autoid = res[0]['autoid']
        self.ppid = res[0]['ppid']

    def set_valitor(self, widget, bottom=0, top=0):
        intvalitor = QIntValidator()
        intvalitor.setBottom(bottom)
        if top != 0:
            intvalitor.setTop(top)
        widget.setValidator(intvalitor)

    def get_postiton(self):
        values_list_ws = ("warehouseid",)
        key_dict_ws = {
            'ppid': self.ppid
        }
        ws_list = self.WC.get_productputinnote(
            True, *values_list_ws, **key_dict_ws
        )
        if not len(ws_list):
            return
        warehouseid = ws_list[0]

        values_list_dppositon = ('dpposition',)
        values_list_positon = ('position',)
        key_dict_position = {
            'warehouseid': warehouseid
        }
        dppos_list = self.WC.get_productputinnote(
            True, *values_list_dppositon, **key_dict_position)
        pos_list = self.WC.get_productputinnote(
            True, *values_list_positon, **key_dict_position)
        if len(dppos_list):
            self.comboBox_dpposition.addItems(dppos_list.distinct())
        if len(pos_list):
            self.comboBox_piposition.addItems(pos_list.distinct())

    def get_productdetail(self):
        VALUES_LIST = (
            "prodid", "prodname", "spec", "package", "bpamount", "bpunit",
            "mpamount", "mpunit", "spamount", "spunit", "lpunit"
        )
        key_dict = {
            'autoid': self.ppid
        }
        res = self.PC.get_producingplan(
            False, *VALUES_LIST, **key_dict
        )
        if len(res) != 1:
            return
        self.product_detail = res[0]
        self.label_product.setText(
            self.product_detail['prodid'] + ' ' + \
            self.product_detail['prodname']
        )
        self.label_spec.setText(self.product_detail['spec'])
        self.label_package.setText(self.product_detail['package'])
        self.label_piunit.setText(self.product_detail['spunit'])
        self.label_dpunit.setText(self.product_detail['spunit'])

    def basicdetail(self):
        if self.product_detail['bpamount'] != decimal.Decimal('0'):
            self.bpamount = self.product_detail['bpamount']
        else:
            self.bpamount = decimal.Decimal('1')
        if self.product_detail['mpamount'] != decimal.Decimal('0'):
            self.mpamount = self.product_detail['mpamount']
        else:
            self.mpamount = decimal.Decimal('1')
        if self.product_detail['spamount'] != decimal.Decimal('0'):
            self.spamount = self.product_detail['spamount']
        else:
            self.spamount = decimal.Decimal('1')
        self.a_box_samount = self.bpamount * self.mpamount * self.spamount
        self.units = [
            self.product_detail['lpunit'], self.product_detail['bpunit'],
            self.product_detail['mpunit'], self.product_detail['spunit']
        ]

    def get_labdetail(self):
        values_list = ("paperno", "status")
        key_dict = {
            'labtype': 4,
            'ciid': self.ppid
        }
        res = self.LC.get_labrecord(
            False, *values_list, **key_dict
        )
        if not len(res):
            return
        # 选择最后一条符合条件的成品报告
        detail = res.order_by('-autoid')[0]
        self.label_reportpaperno.setText(detail['paperno'])
        self.label_checkstatus.setText(CHECK_STATUS[detail['status']])

    def get_putinnote(self):
        values_list = (
            "dpamount", "piamount", "packamount", "unittype",
            "pidate", "piapplyerid", "piapplyername", "piqaid", "piqaname",
            "warehousemanid", "warehousemanname", "pistatus", "position",
            "dpposition", "dpwarehousemanid", "dpwarehousemanname",
            "warehouseid", "warehousename", "oddment", "dpdate", "oddment"
        )
        key_dict = {
            'autoid': self.autoid
        }
        res = self.WC.get_productputinnote(
            False, *values_list, **key_dict
        )
        if not len(res):
            return
        # 选择第一条
        self.ori_detail = res[0]

        self.label_dpdate.setText(
            str(self.ori_detail['dpdate']) if type(self.ori_detail['dpdate'])
                                              is datetime.date else ''
        )
        self.label_pidate.setText(
            str(self.ori_detail['pidate']) if type(self.ori_detail['pidate'])
                                              is datetime.date else ''
        )
        self.comboBox_unittype.setCurrentIndex(self.ori_detail['unittype'])
        self.label_warehouse.setText(
            self.ori_detail['warehouseid'] + ' ' +
            self.ori_detail['warehousename']
        )
        self.comboBox_dpposition.setCurrentText(self.ori_detail['dpposition'])
        self.comboBox_piposition.setCurrentText(self.ori_detail['position'])
        self.pushButton_applyer.setText(
            self.ori_detail['piapplyerid'] + ' ' +
            self.ori_detail['piapplyername']
        )
        self.pushButton_qa.setSign(
            True, self.ori_detail['piqaid'] + ' ' + self.ori_detail['piqaname']
        )
        self.pushButton_dpwsman.setText(
            self.ori_detail['dpwarehousemanid'] + ' ' +
            self.ori_detail['dpwarehousemanname']
        )
        self.pushButton_piwsman.setSign(
            True, self.ori_detail['warehousemanid'] + ' ' +
            self.ori_detail['warehousemanname']
        )

        self.lineEdit_amount.setText(str(self.ori_detail['dpamount']))
        self.lineEdit_oddment.setText(str(self.ori_detail['oddment']))
        self.label_unit.setText(self.units[self.ori_detail['unittype']])
        self.label_oddmentunit.setText(self.units[3])

        self.label_dpamount.setText(str(self.ori_detail['piamount']))
        self.label_piamount.setText(str(self.ori_detail['piamount']))

        if self.ori_detail['pistatus'] == 0:
            self.pushButton_accept.setVisible(True)
            self.pushButton_save.setVisible(True)
            self.pushButton_cancel.setVisible(False)
            self.pushButton_dp.setVisible(False)
            self.pushButton_pi.setVisible(False)
        elif self.ori_detail['pistatus'] == 1:
            self.pushButton_accept.setVisible(False)
            self.pushButton_save.setVisible(False)
            self.pushButton_cancel.setVisible(True)
            self.pushButton_dp.setVisible(True)
            self.pushButton_pi.setVisible(False)
        elif self.ori_detail['pistatus'] == 2:
            self.pushButton_accept.setVisible(False)
            self.pushButton_save.setVisible(False)
            self.pushButton_cancel.setVisible(False)
            self.pushButton_dp.setVisible(False)
            self.pushButton_pi.setVisible(True)
        elif self.ori_detail['pistatus'] == 3:
            self.pushButton_accept.setVisible(False)
            self.pushButton_save.setVisible(False)
            self.pushButton_cancel.setVisible(False)
            self.pushButton_dp.setVisible(False)
            self.pushButton_pi.setVisible(False)

    def get_oddment(self):
        self.treeWidget_oddments.clear()
        self.treeWidget_oddments.hideColumn(0)
        values_list = (
            "autoid", "batchno", "amount", "unit", "makedate", "ppid"
        )
        key_dict = {
            'dppid': self.ppid
        }
        res = self.PC.get_oddmentdrawnotes(False, *values_list, **key_dict)
        if not len(res):
            return

        for item in res:
            if item['unit'] not in self.units:
                continue
            qtreeitem = QTreeWidgetItem(self.treeWidget_oddments)
            qtreeitem.setText(0, str(item['autoid']))
            qtreeitem.setText(1, item['batchno'])
            qtreeitem.setText(2, str(item['amount']))
            qtreeitem.setText(3, item['unit'])
            qtreeitem.setText(4, str(self.a_box_samount - item['amount']))
            qtreeitem.setText(5, str(item['makedate']))
            self.oddments_list.append(
                (2, self.ppid, self.a_box_samount,
                 item['ppid'], item['amount'])
            )
        for i in range(1, 6):
            self.treeWidget_oddments.resizeColumnToContents(i)
        if self.treeWidget_oddments.topLevelItemCount() > 0:
            self.checkBox_has_draw_oddments.setCheckState(2)

    @pyqtSlot(int)
    def on_comboBox_unittype_currentIndexChanged(self, p_int):
        self.label_unit.setText(self.units[p_int])
        try:
            if p_int != self.ori_detail['unittype']:
                self.new_detail['unittype'] = p_int
            else:
                try:
                    del self.new_detail['unittype']
                except KeyError:
                    pass
        except KeyError:
            self.new_detail['unittype'] = p_int
        self.set_total_amount()

    @pyqtSlot(str)
    def on_lineEdit_amount_textEdited(self, p_str):
        if p_str == '':
            amount = decimal.Decimal('0')
        else:
            amount = decimal.Decimal(p_str)
        try:
            if amount != self.ori_detail['dpamount']:
                self.new_detail['dpamount'] = amount
            else:
                try:
                    del self.new_detail['dpamount']
                except KeyError:
                    pass

            self.set_total_amount()

        except KeyError:
            self.new_detail['dpamount'] = amount
        except decimal.InvalidOperation:
            pass

    def set_total_amount(self):
        if self.lineEdit_amount.text() != '':
            amount = decimal.Decimal(self.lineEdit_amount.text())
        else:
            amount = decimal.Decimal('0')
        if self.lineEdit_oddment.text() != '':
            oddment = decimal.Decimal(self.lineEdit_oddment.text())
        else:
            oddment = decimal.Decimal('0')
        unit_index = self.comboBox_unittype.currentIndex()
        this_batchno_amount = 0
        if unit_index == 0:
            this_batchno_amount = amount * self.a_box_samount + oddment
        elif unit_index == 1:
            this_batchno_amount = amount * self.mpamount * self.spamount + oddment
        elif unit_index == 2:
            this_batchno_amount = amount * self.spamount + oddment
        elif unit_index == 3:
            this_batchno_amount = amount + oddment
        merge_amount = self.treeWidget_oddments.topLevelItemCount() * \
                       self.a_box_samount
        piamount = this_batchno_amount + merge_amount
        self.label_dpamount.setText(str(piamount))
        self.label_piamount.setText(str(piamount))
        try:
            if piamount != self.ori_detail['piamount']:
                self.new_detail['piamount'] = piamount
            else:
                try:
                    del self.new_detail['piamount']
                except KeyError:
                    pass
        except KeyError:
            self.new_detail['piamount'] = piamount

    @pyqtSlot(str)
    def on_lineEdit_oddment_textEdited(self, p_str):
        if p_str == '':
            amount = decimal.Decimal('0')
        else:
            amount = decimal.Decimal(p_str)
        try:
            if amount != self.ori_detail['oddment']:
                self.new_detail['oddment'] = amount
            else:
                try:
                    del self.new_detail['oddment']
                except KeyError:
                    pass
            self.set_total_amount()
        except KeyError:
            self.new_detail['oddment'] = amount
        except decimal.InvalidOperation:
            pass

    @pyqtSlot(bool, str)
    def on_pushButton_qa_signChanged(self, p_bool, p_str):
        if p_bool:
            self.pushButton_accept.setEnabled(True)
            piqaid, piqaname = p_str.split(' ')
        else:
            self.pushButton_accept.setEnabled(False)
            piqaid, piqaname = ('', '')
        try:
            if piqaid != self.ori_detail['piqaid']:
                self.new_detail['piqaid'] = piqaid
                self.new_detail['piqaname'] = piqaname
            else:
                try:
                    del self.new_detail['piqaid']
                    del self.new_detail['piqaname']
                except KeyError:
                    pass
        except KeyError:
            self.new_detail['piqaid'] = piqaid
            self.new_detail['piqaname'] = piqaname

    @pyqtSlot(bool, str)
    def on_pushButton_applyer_signChanged(self, p_bool, p_str):
        if p_bool:
            piapplyerid, piapplyername = p_str.split(' ')
        else:
            piapplyerid, piapplyername = ('', '')
        try:
            if piapplyerid != self.ori_detail['piapplyerid']:
                self.new_detail['piapplyerid'] = piapplyerid
                self.new_detail['piapplyername'] = piapplyername
            else:
                try:
                    del self.new_detail['piapplyerid']
                    del self.new_detail['piapplyername']
                except KeyError:
                    pass
        except KeyError:
            self.new_detail['piapplyerid'] = piapplyerid
            self.new_detail['piapplyername'] = piapplyername

    @pyqtSlot(str)
    def on_comboBox_dpposition_currentTextChanged(self, p_str):
        try:
            if p_str != self.ori_detail['dpposition']:
                self.new_detail['dpposition'] = p_str
            else:
                try:
                    del self.new_detail['dpposition']
                except KeyError:
                    pass
        except KeyError:
            self.new_detail['dpposition'] = p_str

    @pyqtSlot(str)
    def on_comboBox_piposition_currentTextChanged(self, p_str):
        try:
            if p_str != self.ori_detail['position']:
                self.new_detail['position'] = p_str
            else:
                try:
                    del self.new_detail['position']
                except KeyError:
                    pass
        except KeyError:
            self.new_detail['position'] = p_str

    @pyqtSlot()
    def on_pushButton_save_clicked(self):
        if self.has_changed():
            self.WC.update_productputinnote(self.autoid, **self.new_detail)

    @pyqtSlot()
    def on_pushButton_accept_clicked(self):
        if self.pushButton_applyer.text() in ('', ' '):
            self.pushButton_applyer.setSign(
                True, user.user_id + ' ' +user.user_name
            )
            self.new_detail['piapplyerid'] = user.user_id
            self.new_detail['piapplyername'] = user.user_name
            self.new_detail['dpdate'] = user.now_date
        self.new_detail['pistatus'] = 1

        self.WC.update_productputinnote(self.autoid, **self.new_detail)
        realamount = decimal.Decimal(self.label_piamount.text())
        detail = {'realamount': realamount}
        self.PC.update_producingplan(self.ppid, **detail)

        self.pushButton_save.setVisible(False)
        self.pushButton_accept.setVisible(False)
        self.pushButton_cancel.setVisible(True)
        self.pushButton_dp.setVisible(False)
        self.pushButton_pi.setVisible(False)
        self.accepted.emit()

    @pyqtSlot()
    def on_pushButton_cancel_clicked(self):
        self.new_detail['piapplyerid'] = ''
        self.new_detail['piapplyername'] = ''
        self.new_detail['pistatus'] = 0

        self.WC.update_productputinnote(self.autoid, **self.new_detail)

        self.pushButton_save.setVisible(True)
        self.pushButton_accept.setVisible(True)
        self.pushButton_cancel.setVisible(False)
        self.pushButton_dp.setVisible(False)
        self.pushButton_pi.setVisible(False)
        self.accepted.emit()

    @pyqtSlot()
    def on_pushButton_dp_clicked(self):
        self.new_detail['dpwarehousemanid'] = user.user_id
        self.new_detail['dpwarehousemanname'] = user.user_name
        self.new_detail['pistatus'] = 2

        self.WC.update_productputinnote(self.autoid, **self.new_detail)

        self.pushButton_save.setVisible(False)
        self.pushButton_accept.setVisible(False)
        self.pushButton_cancel.setVisible(False)
        self.pushButton_dp.setVisible(False)
        self.pushButton_pi.setVisible(True)
        self.accepted.emit()

    @pyqtSlot()
    def on_pushButton_pi_clicked(self):
        if self.label_checkstatus.text() != '检验合格':
            mesgbox = MessageBox(
                parent=self, title="提示", text="当前产品尚未检验合格无法入库"
            )
            mesgbox.exec()
            return
        self.new_detail['warehousemanid'] = user.user_id
        self.new_detail['warehousemanname'] = user.user_name
        self.new_detail['pidate'] = user.now_date
        self.new_detail['pistatus'] = 3
        # 计算要入库的产品信息
        putin_msg = self.get_putin_msg()
        self.WC.update_productputinnote(self.autoid, True, putin_msg, **self.new_detail)

        self.pushButton_save.setVisible(False)
        self.pushButton_accept.setVisible(False)
        self.pushButton_cancel.setVisible(False)
        self.pushButton_dp.setVisible(False)
        self.pushButton_pi.setVisible(False)
        self.accepted.emit()

    def get_putin_msg(self):
        return_detail = []
        return_detail += self.oddments_list
        # 全部的入库数量
        all_amount = decimal.Decimal(self.label_piamount.text())
        # 本批零头数量
        if self.lineEdit_oddment.text() not in ('', '0'):
            oddment_amount = decimal.Decimal(self.lineEdit_oddment.text())
            return_detail.append((1, self.ppid, oddment_amount, 0, 0))
        else:
            oddment_amount = 0
        # 合箱数量
        merge_amount = decimal.Decimal(self.treeWidget_oddments.topLevelItemCount()) * self.a_box_samount

        # 本批整箱数量
        spamount_of_total_box = all_amount - oddment_amount - merge_amount
        return_detail.append((0, self.ppid, spamount_of_total_box,0 ,0))
        return return_detail

    def has_changed(self):
        if not len(self.new_detail):
            return False
        if self.pushButton_applyer.text() in ('', ' '):
            self.pushButton_applyer.setSign(
                True, user.user_id + ' ' +user.user_name
            )
            self.new_detail['piapplyerid'] = user.user_id
            self.new_detail['piapplyername'] = user.user_name
        return True
示例#2
0
class QrcodeinputModule(QWidget, Ui_Form):
    """ 二维码入库文件模块,可以查看到所有产品批次的二维码记录。
    提供了右键下载二维码和导入二维码的功能。

    导入二维码和覆盖二维码功能尚未实现。
    导入二维码只把文件里的数据导入,不会覆盖旧有的数据
    覆盖二维码会先把旧的二维码删除了,同时需要把二维码库中的使用状态used改未0
    导入和覆盖进行的同时还需要把新二维码在二维码库中的状态改为used=1
    """
    def __init__(self, parent=None):
        super(QrcodeinputModule, self).__init__(parent)
        self.setupUi(self)
        if '58' not in user.powers:
            self.close()
        if user.powers['58'] == 0:
            self.close()
        self.power = '{:03b}'.format(user.powers['58'])

        self.WC = WorkshopController()
        self.PC = ProductController()
        self.SC = SystemController()
        self.prodlist = dict()
        # 获取二维码信息
        self.get_product_list()

    def get_product_list(self):
        self.treeWidget_prodlist.clear()
        self.treeWidget_prodlist.hideColumn(0)
        key_dict = {'pltype': 0}
        index = self.tabWidget.currentIndex()
        if index in (0, 1):
            key_dict['qrflag'] = index

        self.prodlist = self.PC.get_producingplan(False, *VALUES_LIST,
                                                  **key_dict)
        if not len(self.prodlist):
            return
        for item in self.prodlist:
            qtreeitem = QTreeWidgetItem(self.treeWidget_prodlist)
            qtreeitem.setText(0, str(item['autoid']))
            qtreeitem.setText(1, item['prodid'] + item['prodname'])
            qtreeitem.setText(2, item['batchno'])
            qtreeitem.setText(3, item['spec'])
            qtreeitem.setText(4, item['package'])
            qtreeitem.setText(5, str(item['makedate']))
        for i in range(1, 6):
            self.treeWidget_prodlist.resizeColumnToContents(i)

    @pyqtSlot(QPoint)
    def on_treeWidget_prodlist_customContextMenuRequested(self, pos):
        if self.power[1] == '0':
            return
        qtreeitem = self.treeWidget_prodlist.selectedItems()
        if not len(qtreeitem):
            return
        select_ppid = int(qtreeitem[0].text(0))

        menu = QMenu()
        button1 = menu.addAction("生成入库数据文件")
        # button2 = menu.addAction("导入入库二维码数据")
        # button3 = menu.addAction("覆盖入库二维码数据")
        g_pos = self.treeWidget_prodlist.mapToGlobal(pos)
        action = menu.exec(g_pos)
        if action == button1:
            clipboard = QApplication.clipboard()
            dir = clipboard.property("qrcodeinputurl")
            filename = "入库数据" + str(user.now_date).replace("-", "") + ".xml"
            if not dir:
                dir = "C:\\"
            file_route, ext = QFileDialog.getSaveFileName(
                self, "请选择入库文件输出路径", dir + filename, "*.xml;;All Files(*)")

            if not file_route:
                return
            selected_dir = re.findall(r'^(.+/|.+\\)', file_route)[0]
            clipboard.setProperty("qrcodeinputurl", selected_dir)

            self.makeqrcodeinputfile(select_ppid, file_route)
            self.PC.update_producingplan(select_ppid, qrflag=1)
            self.get_product_list()

    @pyqtSlot(int)
    def on_tabWidget_currentChanged(self, index):
        getattr(self, 'tab_' + str(index)).setLayout(self.gridLayout_2)
        self.get_product_list()

    def makeqrcodeinputfile(self, ppid, file_route):
        for item in self.prodlist:
            if item['autoid'] == ppid:
                proddetail = item
                break
        key_dict = {'ppid': ppid}
        res = self.WC.get_qrcoderep(False, *VALUES_LIST_QRCODE, **key_dict)
        if not len(res):
            return
        # 把二维码按比例分组
        q_list, proportion_list = self.sort_qrcode(res)
        # 把比例相同的合并成一个同一个项目
        q_list_merge, proportion_list_merge = self.merge_qrcode(
            q_list, proportion_list)
        xml = QXmlStreamWriter()
        qfile = QFile(file_route)
        if qfile.open(QIODevice.WriteOnly):
            xml.setDevice(qfile)
        else:
            return

        xml.setAutoFormatting(True)
        xml.writeStartDocument()
        # 添加头文件信息
        self.addxmlheader(xml)
        self.addxmlproddetail(xml, proddetail)
        for i in range(0, len(proportion_list_merge)):
            spnum = proportion_list[i][0]
            mpnum = proportion_list[i][1]
            bpnum = proportion_list[i][2]
            lpnum = proportion_list[i][3]
            xml.writeStartElement("Batch")
            xml.writeAttribute('batchNo', proddetail['batchno'])
            xml.writeAttribute('specification', proddetail['spec'])
            xml.writeAttribute('minPackUnit', proddetail['spunit'])
            if spnum != 0:
                minTagUnit = proddetail['spunit']
            elif mpnum != 0:
                minTagUnit = proddetail['mpunit']
            else:
                minTagUnit = proddetail['bpunit']
            tagPackRatio = ''
            for num in (lpnum, bpnum, mpnum, spnum):
                if num != 0:
                    if tagPackRatio == '':
                        tagPackRatio = str(num)
                    else:
                        tagPackRatio += ':' + str(num)
            xml.writeAttribute('minTagUnit', minTagUnit)
            xml.writeAttribute('tagPackRatio', tagPackRatio)
            xml.writeAttribute('produceDate', str(proddetail['makedate']))
            xml.writeAttribute('operator', user.user_name)
            xml.writeAttribute('oprDate', str(user.now_date))
            xml.writeAttribute('count', str(len(q_list_merge[i])))
            xml.writeAttribute('countUnit',
                               '1' if minTagUnit == tagPackRatio else '2')
            qrcode = q_list_merge[i]
            for code in qrcode:
                xml.writeStartElement("Data")
                xml.writeAttribute('code', code)
                xml.writeEndElement()

            xml.writeEndElement()
        xml.writeEndElement()
        xml.writeEndElement()
        xml.writeEndDocument()

    def sort_qrcode(self, qrcode_list):
        q_list = []
        temp_q_list = []
        next_box = False
        # 比例
        proportion_list = []
        temp_proportion_list = []
        spnum = 0
        mpnum = 0
        bpnum = 0
        lpnum = 0

        # qrcode_s = ''
        qrcode_m = ''
        qrcode_b = ''
        qrcode_l = ''
        max_lv = 'lp'
        first_qrcode = qrcode_list[0]
        # qrcode0 = first_qrcode['qrcode0']
        # qrcode1 = first_qrcode['qrcode1']
        qrcode2 = first_qrcode['qrcode2']
        qrcode3 = first_qrcode['qrcode3']
        if qrcode3 == '' and qrcode2 == '':
            max_lv = 'mp'
        elif qrcode3 == '' and qrcode2 != '':
            max_lv = 'bp'

        for item in qrcode_list:

            if qrcode_m == '' and item['qrcode1'] != '':
                qrcode_m = item['qrcode1']
            elif qrcode_m != item['qrcode1']:
                temp_q_list.append(qrcode_m)
                qrcode_m = item['qrcode1']
                mpnum += 1
                if max_lv == 'mp':
                    next_box = True

            if qrcode_b == '' and item['qrcode2'] != '':
                qrcode_b = item['qrcode2']
            elif qrcode_b != item['qrcode2']:
                temp_q_list.append(qrcode_b)
                qrcode_b = item['qrcode2']
                bpnum += 1
                if max_lv == 'bp':
                    next_box = True
            if qrcode_l == '' and item['qrcode3'] != '':
                qrcode_l = item['qrcode3']
            elif qrcode_l != item['qrcode3']:
                temp_q_list.append(qrcode_l)
                qrcode_l = item['qrcode3']
                lpnum += 1
                if max_lv == 'lp':
                    next_box = True

            if next_box:
                q_list.append(temp_q_list)
                temp_q_list = []
                for num in (spnum, mpnum, bpnum, lpnum):
                    temp_proportion_list.append(num)
                spnum = 0
                mpnum = 0
                bpnum = 0
                lpnum = 0
                proportion_list.append(temp_proportion_list)
                temp_proportion_list = []
                next_box = False

            if item['qrcode0'] != '':
                temp_q_list.append(item['qrcode0'])
                spnum += 1
        if len(temp_q_list):
            if qrcode_m != '':
                temp_q_list.append(qrcode_m)
                mpnum += 1
            if qrcode_b != '':
                temp_q_list.append(qrcode_b)
                bpnum += 1
            if qrcode_l != '':
                temp_q_list.append(qrcode_l)
                lpnum += 1

            q_list.append(temp_q_list)
            for item in (spnum, mpnum, bpnum, lpnum):
                temp_proportion_list.append(item)
            proportion_list.append(temp_proportion_list)
        return q_list, proportion_list

    def merge_qrcode(self, q_list, proportion_list):
        q_list_merge = []
        proportion_list_merge = []
        for i in range(0, len(proportion_list)):
            proprotion = proportion_list[i]
            if proprotion in proportion_list_merge:
                index = proportion_list_merge.index(proprotion)
                q_list_merge[index] += q_list[i]
            else:
                proportion_list_merge.append(proprotion)
                q_list_merge.append(q_list[i])
        return q_list_merge, proportion_list_merge

    def addxmlheader(self, xml):
        company = "智普飞扬"
        mancode = "19060310"
        key_dict_sys = {'varname__in': ("company", "mancode")}
        res = self.SC.get_syssetting(False, *VALUES_LIST_SYS, **key_dict_sys)
        if len(res):
            for item in res:
                if item['varname'] == "company":
                    company = item['varvalue']
                elif item['varname'] == "mancode":
                    mancode = item['varvalue']
        xml.writeStartElement("DataList")
        xml.writeAttribute("corpName", company)
        xml.writeAttribute("manCode", mancode)
        xml.writeAttribute("dataType", "wareHouseIn")
        xml.writeAttribute("version", "1.0")
        xml.writeAttribute("xmlns: xsi",
                           "http://www.w3.org/2001/XMLSchema-instance")
        xml.writeAttribute("xsi: noNamespaceSchemaLocation",
                           "兽药产品入库数据_生产企业.xsd")

    def addxmlproddetail(self, xml, proddetail):
        xml.writeStartElement("Product")
        xml.writeAttribute("productName", proddetail['commonname'])
        xml.writeAttribute("pzwh", proddetail['allowno'])
        xml.writeAttribute(
            "packing",
            str(proddetail['basicamount']) + proddetail['basicunit'])
class EditProducingplan(QDialog, Ui_Dialog):
    created = pyqtSignal(int)

    def __init__(self, autoid=None, parent=None):
        super(EditProducingplan, self).__init__(parent)
        self.setupUi(self)

        # if '20' not in user.powers:
        #     self.close()
        #     self.accept_button.setVisible(False)
        #     self.cancel_button.setVisible(False)
        #     self.pushButton_audit.setVisible(False)
        # if user.powers['20'] == 0:
        #     self.close()
        # self.power = '{:03b}'.format(user.powers['20'])
        # if self.power[1] == '0':
        #     self.accept_button.setVisible(False)
        #     self.cancel_button.setVisible(False)
        #     self.pushButton_audit.setVisible(False)

        self.PC = ProductController()
        self.WC = WarehouseController()

        self.autoid = autoid
        self.prod_id = 0
        self.ori_detail = {}
        self.new_detail = {}
        self.detail = {}
        self.stuff_list = []
        self.stuff_repository = []
        self.no_enough_stuff_list = []
        self.treewidget_meterial.hideColumn(1)
        self.treeWidget_package.hideColumn(1)
        # 公式错误信息
        self.errormsg = []

        self.prodname.setup(DB_TABLE[0], PRODUCT_VALUE_TUPLE, PRODUCT_KEY,
                            VALUE_NAME, None, 650, 250)

        self.prodname.getItem.connect(self.setproduct)
        self.set_validator()
        if autoid is not None:
            self.get_detail()
            self.set_treewidget_formula((0, 1, 2), self.treewidget_meterial)
            self.set_treewidget_formula((3, 4), self.treeWidget_package)
        else:
            self.makedate.setDate(QDate.currentDate())

    def set_validator(self):

        doubleValitor = QDoubleValidator()
        doubleValitor.setBottom(0)
        doubleValitor.setDecimals(2)
        doubleValitor.setNotation(QDoubleValidator.StandardNotation)
        self.planamount.setValidator(doubleValitor)

    def setproduct(self, qtreeitem: QTreeWidgetItem):
        self.prod_id = qtreeitem.text(0)
        self.commonname.setText(qtreeitem.text(3))
        self.spec.setText(qtreeitem.text(4))
        self.package_2.setText(qtreeitem.text(5))
        if self.prod_id:
            # flag:产品的类型,0成品,1半成品,2退货, 3验证
            flag = self.productkind.currentIndex()
            key_dict = {'autoid': self.prod_id}
            res = self.PC.get_product_or_stuff_dictionary(
                flag, False, **key_dict)
            if res:
                self.unit.setText(res[0].spunit)
                if flag in (0, 1):
                    lineid = res[0].plid
                elif flag == 2:
                    lineid = res[0].wplid
                elif flag == 3:
                    lineid = res[0].vplid
                else:
                    lineid = 0
                if lineid:
                    productline = ProductLineConroller()
                    pline = productline.get_productline(lineid, flag)
                    if pline:
                        self.prodline.setText(pline[0].linename)
                        self.productworkshop.setText(pline[0].deptid + ' ' +
                                                     pline[0].deptname)

    def set_autoid(self, autoid: int):
        self.autoid = autoid
        # 查询autoid对应的记录,并关联到表格中
        self.get_detail()
        self.new_detail.clear()

    def get_detail(self):
        res = self.PC.get_producingplan(autoid=self.autoid)
        if res:
            # 把生产指令的内容填入表格中
            self.set_data(res[0])
            self.ori_detail = model_to_dict(res[0])
            self.detail = self.ori_detail
        else:
            errordialig = QErrorMessage(self)
            errordialig.setWindowTitle("错误")

    # 初始化编辑生产指令的内容
    def set_data(self, detail):
        self.productkind.setCurrentIndex(detail.pltype)
        self.prodname.setText(detail.prodid + ' ' + detail.prodname)
        self.commonname.setText(detail.commonname)
        self.spec.setText(detail.spec)
        self.package_2.setText(detail.package)
        self.planamount.setText(str(detail.planamount))
        self.unit.setText(detail.spunit)
        self.batchno.setText(detail.batchno)
        self.makedate.setDate(
            QDate(detail.makedate)
            if type(detail.makedate) is datetime.date else user.now_date)
        self.remarks.setText(detail.remark)
        lineid = detail.lineid

        if lineid:
            productline = ProductLineConroller()
            pline = productline.get_productline(lineid, detail.pltype)
            if pline:
                self.prodline.setText(pline[0].linename)
                self.productworkshop.setText(pline[0].deptid + ' ' +
                                             pline[0].deptname)
                self.new_detail['linename'] = pline[0].linename
                self.new_detail['workshopid'] = pline[0].deptid
                self.new_detail['workshopname'] = pline[0].deptname

    def set_treewidget_formula(self, stufftype=(0, 1, 2), qtree=None):
        prodtype = 1 if self.productkind.currentIndex() == 1 else 0
        qtree.clear()
        condition = {
            'prodid': self.prod_id,
            'stufftype__in': stufftype,
            'prodtype': prodtype
        }
        # 获取配方
        self.formula = self.PC.get_data(6, False, *VALUES_TUPLE_PD,
                                        **condition)
        if not len(self.formula):
            return
        stuffkind_list = self.formula.values_list('stuffkind', flat=True)
        condition_sk = {'stuffkind__in': stuffkind_list, 'amount__gt': 0}
        self.stuff_repository = self.WC.get_data(2, False, *VALUES_TUPLE_SD,
                                                 **condition_sk)
        for it in self.stuff_repository:
            condition_lock = {'srid': it['autoid']}
            drawamount_list = self.PC.get_data(
                7, True, *VALUES_TUPLE_SL,
                **condition_lock).exclude(ppid=self.autoid)
            it['realamount'] = it['amount'] - sum(drawamount_list)
        for item in self.formula:
            parent_treeitem = QTreeWidgetItem(qtree)

            parent_treeitem.setText(0, item['stuffkind'])
            parent_treeitem.setText(2, item['formula'])

            stuffkind = item['stuffkind']
            condition_sf = {'stuffkind': stuffkind, 'amount__gt': 0}

            # 获取库存
            stuffrepository = self.WC.get_data(2, False, *VALUES_TUPLE_SD,
                                               **condition_sf)
            if not len(stuffrepository):
                brush = QBrush(1)
                brush.setColor(QColor(255, 85, 0))
                for i in range(0, 13):
                    parent_treeitem.setBackground(i, brush)
                    # Decimal(rnd(eval(presexpression, evalenv(self)),
                    #             precision))
                parent_treeitem.setText(
                    6,
                    str(self.no_stuffrep_count_presamount(item)) +
                    item['presunit'])
                self.no_enough_stuff_list.append(stuffkind)
                continue

            draw_status = self.draw_stuff(item)
            if not draw_status:
                self.no_enough_stuff_list.append(stuffkind)
                brush = QBrush(1)
                brush.setColor(QColor(255, 255, 127))
                for i in range(1, 13):
                    parent_treeitem.setBackground(i, brush)

            for it in stuffrepository:
                condition_lock = {'srid': it['autoid']}
                drawamount_list = self.PC.get_data(7, True, *VALUES_TUPLE_SL,
                                                   **condition_lock)
                qtreeitem = QTreeWidgetItem(parent_treeitem)
                qtreeitem.setText(1, str(it['autoid']))
                qtreeitem.setText(0, it['stuffname'])
                qtreeitem.setText(3, it['batchno'])
                qtreeitem.setText(4, str(it['amount']))
                qtreeitem.setText(5, str(sum(drawamount_list)))
                for sr in self.stuff_list:
                    if it['autoid'] == sr['autoid']:
                        qtreeitem.setText(
                            7,
                            str(sr['newpracamount']) + item['pracunit'])
                        qtreeitem.setText(
                            8,
                            str(sr['drawamount']) + item['drawunit'])

                        parent_treeitem.setText(
                            6,
                            str(sr['presamount']) + item['presunit'])
                        break
                if stufftype == (0, 1, 2):
                    qtreeitem.setText(9, str(it['content']) + it['cunit'])
                    qtreeitem.setText(10, str(it['water']) + '%')
                    qtreeitem.setText(11, str(it['rdensity']))
                    qtreeitem.setText(12, str(it['impurity']))
        qtree.expandAll()
        qtree.resizeColumnToContents(0)
        for i in range(2, 13 if stufftype == (0, 1, 2) else 9):
            qtree.resizeColumnToContents(i)
        qtree.collapseAll()

    def no_stuffrep_count_presamount(self, item):
        stuffkind = item['stuffkind']
        precision = item['precision']
        loss = item['loss']
        # 处理产品信息的变量,去除系统变量
        presexpression = self.reckon_expression(item['presexpression'], 1)
        # 计划量
        try:
            presamount = Decimal(
                rnd(eval(presexpression, evalenv(self)), precision))
            return presamount
        except SyntaxError:
            if stuffkind + ' 计划量' not in self.errormsg:
                self.errormsg.append(stuffkind + ' 计划量')
            return 0

    # 系统根据配方自动领料
    def draw_stuff(self, item):
        stuffkind = item['stuffkind']
        precision = item['precision']
        loss = item['loss']
        # 处理产品信息的变量,去除系统变量
        presexpression = self.reckon_expression(item['presexpression'], 1)
        # 计划量
        try:
            presamount = Decimal(
                rnd(eval(presexpression, evalenv(self)), precision))
        except SyntaxError:
            if stuffkind + ' 计划量' not in self.errormsg:
                self.errormsg.append(stuffkind + ' 计划量')
            presamount = 0

        # 实际量公式,去除系统变量
        pracexpression = self.reckon_expression(item['pracexpression'], 1)
        # 领取量公式,去除系统变量
        drawexpression = self.reckon_expression(item['drawexpression'], 1)
        # 计算领料量,返回领料情况res, 和标记:是否已经领购料
        res = self.reckon_drawamount(stuffkind, presamount, precision,
                                     pracexpression, drawexpression, loss)
        if len(res):
            self.stuff_list_additem(res)

        return self.is_drawamount_enough(stuffkind, presamount)

    # 判断领取的物料是否足够
    def is_drawamount_enough(self, stuffkind, presamount):
        new_presamount = 0
        for item in self.stuff_list:
            if item['stuffkind'] == stuffkind:
                new_presamount += item['newpresamount']

        return True if new_presamount >= presamount else False

    # 把领取的物料加到领料记录中,如果发现重复的情况则替换旧的记录
    def stuff_list_additem(self, newitems):
        for newitem in newitems:
            flat = 0
            for item in self.stuff_list:
                if newitem['autoid'] == item['autoid']:
                    # item = newitem
                    flat = 1
                    break
            if flat == 0:
                self.stuff_list.append(newitem)

    # 计算系统变量
    def reckon_expression(self, expression, iterdepth):
        # iterdepth:迭代深度,超过50则抛出RuntimeError
        # 产品信息变量,ex: @planamount@, @spec@, @package@
        if iterdepth > 50:
            raise RuntimeError
        pattern = re.findall(r'@[%?!()()::.#\w]*@', expression)
        for item in pattern:
            # 引用其他物料
            if len(item[1:-1].split('.')) == 2:
                var_name, var_item = item[1:-1].split('.')
                value = Decimal('0')
                # 标记是否找到了对应的物料
                find_stuff_flag = 0
                for stuff in self.stuff_list:
                    if stuff['stuffkind'] == var_name:
                        find_stuff_flag = 1
                        if var_item == '计划量':
                            value = stuff[VAR_ITEM[var_item]]
                            expression = expression.replace(item, str(value))
                            break
                        else:
                            value += stuff[VAR_ITEM[var_item]]
                        expression = expression.replace(item, str(value))
                # 没有找到对应的物料则再本领料单中继续寻找
                if find_stuff_flag == 0:
                    for item in self.formula:
                        try:
                            if item['stuffkind'] == var_name:
                                # stuffkind = item.text(2)
                                precision = item['precision']
                                loss = item['loss']
                                # 处理产品信息的变量,去除系统变量
                                presexpression = self.reckon_expression(
                                    item['presexpression'], iterdepth + 1)
                                # 计划量
                                try:
                                    presamount = Decimal(
                                        rnd(
                                            eval(presexpression,
                                                 evalenv(self)), precision))
                                except SyntaxError:
                                    if var_name + ' 计划量' not in self.errormsg:
                                        self.errormsg.append(var_name + ' 计划量')
                                    presamount = 0
                                # 把计划量加到产品信息变量中
                                # self.detail['presamount'] = presamount
                                # 实际量公式,去除系统变量
                                pracexpression = self.reckon_expression(
                                    item['pracexpression'], iterdepth + 1)
                                # 领取量公式,去除系统变量
                                drawexpression = self.reckon_expression(
                                    item['drawexpression'], iterdepth + 1)
                                # 计算领料量,返回领料情况res, 和标记:是否已经领购料
                                res = self.reckon_drawamount(
                                    var_name, presamount, precision,
                                    pracexpression, drawexpression, loss)
                                if len(res):
                                    self.stuff_list_additem(res)
                                    # self.is_drawamount_enough()
                                    expression = self.reckon_expression(
                                        expression, iterdepth + 1)
                        except RuntimeError:
                            break
            # 引用生产指令的参数
            else:
                key = item.replace('@', '')
                if key in self.detail:
                    expression = expression.replace(item,
                                                    str(self.detail[key]))
        # pattern_1 = re.findall(r'@[%?!()()::.#\w]*@', expression)
        return expression

    # 计算实际量
    def reckon_pracamount(self, autoid, presamount, precision, expression):
        # stuffkind: 物料种类
        # presamount: 计划量
        # expression: 实际量的公式
        stuff_detail = []
        # 最终要领取的批次和实际量
        # 分析公式,获取变量
        pattern = re.findall(r'@\w*@', expression)
        # 把变量设置为对应的值
        for item in self.stuff_repository:
            if autoid != item['autoid']:
                continue
            for key in pattern:
                k = key.replace('@', '')
                if k == 'presamount':
                    expression = expression.replace(key, str(presamount))
                elif k in item:
                    expression = expression.replace(key, str(item[k]))
                elif k in self.detail:
                    expression = expression.replace(key, str(self.detail[k]))
            try:
                pracamount = Decimal(
                    rnd(eval(expression, evalenv(self)), precision))
            except SyntaxError:
                if item['stuffkind'] + ' 实际量' not in self.errormsg:
                    self.errormsg.append(item['stuffkind'] + ' 实际量')
                pracamount = 0

            item['pracamount'] = pracamount

    # 计算领取量
    # stuffkindorsrid: 根据flat决定类型, True是物料种类,False是srid
    # presamount: 计划量
    # precision: 计算结果精度
    # prac_expression: 实际量公式
    # draw_expression: 领取公式
    # loss: 损耗限度
    # flat: 是否需要继续领下一批物料,默认为True即继续领下一批物料,
    #       False则不再领取下一批物料
    def reckon_drawamount(self,
                          stuffkindorsrid,
                          presamount,
                          precision,
                          prac_expression,
                          draw_expression,
                          loss=0,
                          flat=True):

        # 要领取的物料批次
        draw_list = []
        # 已经领取了的量
        has_drawamount = 0
        # 分析公式,获取变量
        pattern = re.findall(r'@\w*@', draw_expression)
        # 把变量设置为对应的值
        for item in self.stuff_repository:

            item['presamount'] = presamount
            new_expression = draw_expression
            if has_drawamount != 0:
                presamount -= has_drawamount
                has_drawamount = 0
            if stuffkindorsrid != (item['stuffkind']
                                   if flat else str(item['autoid'])):
                continue
            item['loss'] = loss
            item['newpresamount'] = presamount
            item['precision'] = precision
            # 算出该批次对应的实际量
            self.reckon_pracamount(item['autoid'], presamount, precision,
                                   prac_expression)
            for key in pattern:

                k = key.replace('@', '')
                if k in item:
                    new_expression = new_expression.replace(key, str(item[k]))
                elif k in self.detail:
                    new_expression = new_expression.replace(
                        key, str(self.detail[k]))
            try:
                drawamount = Decimal(
                    rnd(eval(new_expression, evalenv(self)), precision))
            except SyntaxError:
                if stuffkindorsrid + ' 领取量' not in self.errormsg:
                    self.errormsg.append(stuffkindorsrid + ' 领取量')
                drawamount = 0
                continue
            if item['realamount'] >= drawamount:
                item['drawamount'] = drawamount
                item['newpracamount'] = item['pracamount']
                draw_list.append(item)
                break
            else:
                # 转化为计划量 = 领取量 * 计划量 / 实际量
                has_drawamount = Decimal(
                    rnd(item['realamount'] * presamount / item['pracamount'],
                        precision))
                item['newpresamount'] = has_drawamount
                item['newpracamount'] = rnd(item['realamount'], precision)
                item['drawamount'] = rnd(item['realamount'], precision)
                draw_list.append(item)
                if not flat:
                    # 指定库存记录时,默认按领够料处理
                    break
        return draw_list

    # 产品种类改变时
    @pyqtSlot(int)
    def on_productkind_currentIndexChanged(self, p_int):
        if p_int in (0, 2, 3):
            self.prodname.setup(DB_TABLE[0], PRODUCT_VALUE_TUPLE, PRODUCT_KEY,
                                VALUE_NAME, None, 650, 250)
        else:
            self.prodname.setup(DB_TABLE[1], STUFF_VALUE_TUPLE, STUFF_KEY,
                                VALUE_NAME, None, 650, 250)

    # 修改计划量时触发
    @pyqtSlot()
    def on_planamount_editingFinished(self):
        p_str = self.planamount.text()
        planamount = Decimal(p_str) if p_str != '' else 0
        try:
            if planamount != self.ori_detail['planamount']:
                self.new_detail['planamount'] = planamount
                self.detail['planamount'] = planamount
            else:
                try:
                    del self.new_detail['planamount']
                except KeyError:
                    pass
        except KeyError:
            self.new_detail['planamount'] = planamount
            self.detail['planamount'] = planamount

        self.stuff_list = []
        self.stuff_repository = []
        self.no_enough_stuff_list = []
        self.set_treewidget_formula((0, 1, 2), self.treewidget_meterial)
        self.set_treewidget_formula((3, 4), self.treeWidget_package)

    # 修改批号时触发
    @pyqtSlot(str)
    def on_batchno_textEdited(self, p_str):
        try:
            if p_str != self.ori_detail['batchno']:
                self.new_detail['batchno'] = p_str
            else:
                try:
                    del self.new_detail['batchno']
                except KeyError:
                    pass
        except KeyError:
            self.new_detail['batchno'] = p_str

    # 修改生产日期时触发
    @pyqtSlot(QDate)
    def on_makedate_dateChanged(self, q_date):
        p_date = q_date.toPyDate()
        try:
            if p_date != self.ori_detail['makedate']:
                self.new_detail['makedate'] = p_date
            else:
                try:
                    del self.new_detail['makedate']
                except KeyError:
                    pass
        except KeyError:
            self.new_detail['makedate'] = p_date

    # 修改备注时触发
    @pyqtSlot(str)
    def on_remarks_textChanged(self, p_str):
        try:
            if p_str != self.ori_detail['remark']:
                self.new_detail['remark'] = p_str
            else:
                try:
                    del self.new_detail['remark']
                except KeyError:
                    pass
        except KeyError:
            self.new_detail['remark'] = p_str

    @pyqtSlot()
    def on_accept_button_clicked(self):
        if self.prodname.flat == 0:
            text = "没有找到对应的产品信息,请修改后重试!"
            informative = "选择好产品名称后请不要再修改,否则将导致系统无法找到正确的产品!"
            errordialig = MessageBox(self, text=text, informative=informative)
            errordialig.exec()
            self.prodname.setFocus()
            return
        if len(self.no_enough_stuff_list):
            text = "以下物料不足!"
            informative = ";\n".join(self.no_enough_stuff_list)
            errordialig = MessageBox(self,
                                     text=text,
                                     informative=informative,
                                     yes_text="继续下达指令")
            res = errordialig.exec()
            if res == 65536:
                self.prodname.setFocus()
                return
        # 有修改过数据
        if self.new_detail:
            try:
                # 修改过记录,把当前的人员和日期存入修改记录中
                self.new_detail['instructorid'] = user.user_id
                self.new_detail['instructorname'] = user.user_name
                self.new_detail['plandate'] = user.now_date
                self.new_detail['deptid'] = user.dept_id
                self.new_detail['deptname'] = user.dept_name
                self.new_detail['bpconstitutorid'] = user.user_id
                self.new_detail['bpconstitutorname'] = user.user_name
                self.new_detail['bpconsdate'] = user.now_date

                # autoid不为空,则为修改记录
                # 否则为插入记录
                if self.autoid:
                    self.PC.update_producingplan(autoid=self.autoid,
                                                 **self.new_detail)
                    condition = {'ppid': self.autoid}
                    self.PC.delete_data(7, condition)
                else:
                    prodtype = self.productkind.currentIndex()
                    prod_id = self.prodname.namelist.currentItem().text(0)
                    self.new_detail['id'] = prod_id
                    ppid = self.PC.update_producingplan(prodtype=prodtype,
                                                        **self.new_detail)
                    self.autoid = ppid
                    self.created.emit(self.autoid)
                for item in self.stuff_list:
                    detail = {
                        'ppid': self.autoid,
                        'srid': item['autoid'],
                        'drawamount': item['drawamount'],
                        'stuffkind': item['stuffkind']
                    }
                    self.PC.update_data(7, **detail)
                self.accept()
            except Exception as e:
                SaveExcept(e, "提交生产指令时出错", **self.new_detail)
        else:
            self.close()

    @pyqtSlot()
    def on_cancel_button_clicked(self):
        self.close()

    @pyqtSlot()
    def on_pushButton_audit_clicked(self):
        if len(self.no_enough_stuff_list):
            text = "以下物料不足!无法执行指令!"
            informative = ";\n".join(self.no_enough_stuff_list)
            errordialig = MessageBox(self, text=text, informative=informative)
            errordialig.exec()
            return
        if self.autoid is None:
            self.new_detail['instructorid'] = user.user_id
            self.new_detail['instructorname'] = user.user_name
            self.new_detail['plandate'] = user.now_date
            self.new_detail['deptid'] = user.dept_id
            self.new_detail['deptname'] = user.dept_name
            self.new_detail['bpconstitutorid'] = user.user_id
            self.new_detail['bpconstitutorname'] = user.user_name
            self.new_detail['bpconsdate'] = user.now_date

        self.new_detail['status'] = 1
        self.new_detail['statustime'] = user.now_time
        self.new_detail['warrantorid'] = user.user_id
        self.new_detail['warrantorname'] = user.user_name
        self.new_detail['warrantdate'] = user.now_date
        self.new_detail['qadate'] = user.now_date
        self.new_detail['bpwarrantorid'] = user.user_id
        self.new_detail['bpwarrantorname'] = user.user_name
        self.new_detail['bpwarrantdate'] = user.now_date
        if self.autoid is None:
            prodtype = self.productkind.currentIndex()
            prod_id = self.prodname.namelist.currentItem().text(0)
            self.new_detail['id'] = prod_id
            ppid = self.PC.update_producingplan(prodtype=prodtype,
                                                **self.new_detail)
            self.autoid = ppid
            self.created.emit(self.autoid)
            # self.PC.update_data(3, **self.new_detail)
        else:
            condition = {'autoid': self.autoid}
            self.PC.update_data(3, condition, **self.new_detail)
        for item in self.stuff_list:
            if item['drawamount'] == 0:
                continue
            detail = {
                'ppid': self.autoid,
                'srid': item['autoid'],
                'drawamount': item['drawamount'],
                'stuffkind': item['stuffkind']
            }
            self.PC.update_data(7, **detail)
        self.accept()
class PackageInstructionModule(QWidget, Ui_Form):

    def __init__(self, autoid, parent=None):
        super(PackageInstructionModule, self).__init__(parent)
        self.autoid = autoid
        self.setupUi(self)
        self.SC = StuffController()
        self.PC = ProductController()
        self.ori_detail = dict()
        self.new_detail = dict()
        # 获取物料信息
        self.get_stufflist()
        # 获取批包装指令信息
        self.get_detail()

    # 获取已经领取了的物料
    def get_stufflist(self):
        values_tupe = (
            "autoid", "lrid", "stuffid", "stuffname", "batchno", "spec",
            "package", "presamount", "content", "cunit", "water",
            "impurity", "rdensity", "presunit"
        )
        key_dict = {
            'ppid': self.autoid,
            'stufftype__in': (3, 4)
        }
        res = self.SC.get_prodstuff(False, *values_tupe, **key_dict)
        if len(res):
            for item in res:
                qtreeitem = QTreeWidgetItem(self.treeWidget_stufflist)
                qtreeitem.setText(0, str(item['autoid']))  # autoid
                qtreeitem.setText(1, str(item['lrid']))  # lrid
                qtreeitem.setText(2, item['stuffid'] + ' ' + item[
                    'stuffname'])  # 物料
                qtreeitem.setText(3, item['batchno'])  # 进厂批号
                qtreeitem.setText(4, item['spec'])  # 含量规格
                qtreeitem.setText(5, item['package'])  # 包装规格
                qtreeitem.setText(6, str(item['presamount']) + item[
                    'presunit'])  # 计划量
                qtreeitem.setText(7, str(item['content']) + item[
                    'cunit'])  # 含量/效价
                qtreeitem.setText(8, str(item['water']) + '%')  # 水分
                qtreeitem.setText(9, str(item['impurity']))  # 相对密度
                qtreeitem.setText(10, str(item['rdensity']))  # 杂质

            self.treeWidget_stufflist.hideColumn(0)
            self.treeWidget_stufflist.hideColumn(1)
            for i in range(2, 11):
                self.treeWidget_stufflist.resizeColumnToContents(i)



    def get_detail(self):
        values_list = (
            'bpconstitutorid', 'bpconstitutorname', 'bpwarrantorid', 'bpwarrantorname',
            'bpexecutorid', 'bpexecutorname', 'bpconsdate', 'bpwarrantdate',
            'bpexecutedate', 'bpdate'
        )
        key_dict = {
            'autoid': self.autoid
        }
        res = self.PC.get_producingplan(False, *values_list, **key_dict)
        if len(res) == 0:
            return

        self.ori_detail = res[0]
        self.pushButton_bpconstitutor.setText(
            self.ori_detail['bpconstitutorid'] + ' ' +
            self.ori_detail['bpconstitutorname']
        )
        self.pushButton_bpwarrantor.setText(
            self.ori_detail['bpwarrantorid'] + ' ' +
            self.ori_detail['bpwarrantorname']
        )
        self.pushButton_bpexecutor.setText(
            self.ori_detail['bpexecutorid'] + ' ' +
            self.ori_detail['bpexecutorname']
        )
        if type(self.ori_detail['bpconsdate']) is datetime.date:
            self.dateEdit_bpconsdate.setDate(self.ori_detail['bpconsdate'])
        if type(self.ori_detail['bpwarrantdate']) is datetime.date:
            self.dateEdit_bpwarrantdate.setDate(self.ori_detail['bpwarrantdate'])
        if type(self.ori_detail['bpexecutedate']) is datetime.date:
            self.dateEdit_bpexecutedate.setDate(self.ori_detail['bpexecutedate'])
        else:
            self.dateEdit_bpexecutedate.setDate(user.now_date)
        if type(self.ori_detail['bpdate']) is datetime.date:
            self.dateEdit_bpdate.setDate(self.ori_detail['bpdate'])
        else:
            self.dateEdit_bpdate.setDate(user.now_date)

    @pyqtSlot(bool, str)
    def on_pushButton_bpexecutor_signChanged(self, p_bool, p_str):
        id, name = p_str.split(' ') if p_bool else ('', '')
        try:
            if id != self.ori_detail['bpexecutorid'] or name != self.ori_detail[
                'bpexecutorname']:
                self.new_detail['bpexecutorid'] = id
                self.new_detail['bpexecutorname'] = name
            else:
                try:
                    del self.new_detail['bpexecutorid']
                    del self.new_detail['bpexecutorname']
                except KeyError:
                    pass
        except KeyError:
            self.new_detail['bpexecutorid'] = id
            self.new_detail['bpexecutorname'] = name

    @pyqtSlot(QDate)
    def on_dateEdit_bpexecutedate_dateChanged(self, q_date):
        try:
            if type(self.ori_detail['bpexecutedate']) is str:
                self.new_detail['bpexecutedate'] = q_date.toPyDate()
                return
            if q_date != QDate(self.ori_detail['bpexecutedate']):
                self.new_detail['bpexecutedate'] = q_date.toPyDate()
            else:
                try:
                    del self.new_detail['bpexecutedate']
                except KeyError:
                    pass
        except KeyError:
            self.new_detail['bpexecutedate'] = q_date.toPyDate()

    @pyqtSlot(QDate)
    def on_dateEdit_bpdate_dateChanged(self, q_date):
        try:
            if type(self.ori_detail['bpdate']) is str:
                self.new_detail['bpdate'] = q_date.toPyDate()
                return
            if q_date != QDate(self.ori_detail['bpdate']):
                self.new_detail['bpdate'] = q_date.toPyDate()
            else:
                try:
                    del self.new_detail['bpdate']
                except KeyError:
                    pass
        except KeyError:
            self.new_detail['bpdate'] = q_date.toPyDate()

    @pyqtSlot()
    def on_pushButton_accept_clicked(self):
        if len(self.new_detail):
            res = self.PC.update_producingplan(self.autoid, **self.new_detail)
class PreProdPutInModule(QWidget, Ui_Form):
    accepted = pyqtSignal()

    def __init__(self, autoid: int = 0, ppid: int = 0, parent=None):
        super(PreProdPutInModule, self).__init__(parent)
        self.setupUi(self)
        self.ppid = ppid
        self.autoid = autoid
        self.content = decimal.Decimal('-1')
        self.water = decimal.Decimal('-1')
        self.rdensity = decimal.Decimal('-1')
        self.impurity = decimal.Decimal('-1')
        self.lrid = 0
        self.checkdate = user.now_date
        # self.units = set()
        self.unit = ''
        self.cunit = '%'
        self.expireddays = 730
        self.countercheckdays = 365
        self.WC = WorkshopController()
        self.LC = LabrecordsController()
        self.PC = ProductController()
        self.SC = StuffController()
        self.product_detail = dict()
        self.ori_detail = dict()
        self.new_detail = dict()

        # 把autoid和ppid补全
        self.get_autoid_or_ppid()
        # 获取入库位置的下拉选项
        self.get_postiton()

        # 整箱数量的校验器
        self.set_valitor(self.lineEdit_amount, 0)
        # 获取产品信息
        self.get_productdetail()
        # 设置含量单位、复检日期、有效期等参数
        self.basicdetail()

        # 获取报告书的状态和编号
        self.get_labdetail()
        # 获取入库信息
        self.get_putinnote()

    def get_autoid_or_ppid(self):
        values_list = ('autoid', 'ppid')
        if self.autoid:
            key_dict = {'autoid': self.autoid}
        else:
            key_dict = {'ppid': self.ppid}
        res = self.WC.get_productputinnote(False, *values_list, **key_dict)
        if not len(res):
            return
        if self.autoid:
            self.ppidid = res[0]['ppid']
        else:
            self.autoid = res[0]['autoid']

    def set_valitor(self, widget, bottom=0, top=0):
        intvalitor = QIntValidator()
        intvalitor.setBottom(bottom)
        if top != 0:
            intvalitor.setTop(top)
        widget.setValidator(intvalitor)

    def get_postiton(self):

        key_dict_ws = {'ppid': self.ppid}
        ws_list = self.WC.get_productputinnote(True, *VALUES_LIST_WS,
                                               **key_dict_ws)
        if not len(ws_list):
            return
        warehouseid = ws_list[0]

        values_list_positon = ('position', )
        key_dict_position = {'warehouseid': warehouseid}
        pos_list = self.WC.get_productputinnote(True, *values_list_positon,
                                                **key_dict_position)
        if len(pos_list):
            self.comboBox_piposition.addItems(pos_list.distinct())

    def get_productdetail(self):

        key_dict = {'autoid': self.ppid}
        res = self.PC.get_producingplan(False, *VALUES_LIST_PROD, **key_dict)
        if len(res) != 1:
            return
        self.product_detail = res[0]
        self.label_product.setText(
            self.product_detail['prodid'] + ' ' + \
            self.product_detail['prodname']
        )
        self.label_spec.setText(self.product_detail['spec'])
        self.label_package.setText(self.product_detail['package'])
        self.label_unit.setText(self.product_detail['basicunit'])

    def basicdetail(self):
        if not len(self.product_detail):
            return
        stuffid = self.product_detail['prodid']
        stuffname = self.product_detail['prodname']
        key_dict = {'stuffid': stuffid, 'stuffname': stuffname}
        res = self.SC.get_stuffdict(False, *VALUES_TUPLE_STUFF, **key_dict)
        if not len(res):
            return
        self.cunit = res[0]['cunit']
        self.expireddays = res[0]['expireddays']
        self.countercheckdays = res[0]['countercheckdays']
        self.label_contentunit.setText(self.cunit)

    def get_labdetail(self):
        values_list = ('autoid', 'paperno', 'status', 'reportdate')
        key_dict = {'labtype': 2, 'ciid': self.ppid}
        res = self.LC.get_labrecord(False, *values_list, **key_dict)
        if not len(res):
            return
        # 选择最后一条符合条件的成品报告
        detail = res.order_by('-autoid')[0]
        self.lrid = detail['autoid']
        self.checkdate = detail['reportdate']
        self.label_reportpaperno.setText(detail['paperno'])
        self.label_checkstatus.setText(CHECK_STATUS[detail['status']])

    def get_putinnote(self):

        key_dict = {'autoid': self.autoid}
        res = self.WC.get_productputinnote(False, *VALUES_TUPLE_PUTIN,
                                           **key_dict)
        if not len(res):
            return
        # 选择第一条
        self.ori_detail = res[0]

        self.label_warehouse.setText(self.ori_detail['warehouseid'] + ' ' +
                                     self.ori_detail['warehousename'])
        self.comboBox_piposition.setCurrentText(self.ori_detail['position'])
        self.pushButton_applyer.setText(self.ori_detail['piapplyerid'] + ' ' +
                                        self.ori_detail['piapplyername'])
        self.pushButton_qa.setSign(
            True,
            self.ori_detail['piqaid'] + ' ' + self.ori_detail['piqaname'])
        self.pushButton_piwsman.setSign(
            True, self.ori_detail['warehousemanid'] + ' ' +
            self.ori_detail['warehousemanname'])
        self.lineEdit_amount.setText(to_str(self.ori_detail['piamount']))

        if self.ori_detail['pistatus'] == 0:
            self.pushButton_accept.setVisible(True)
            self.pushButton_save.setVisible(True)
            self.pushButton_cancel.setVisible(False)
            self.pushButton_pi.setVisible(False)
        elif self.ori_detail['pistatus'] == 1:
            self.pushButton_accept.setVisible(False)
            self.pushButton_save.setVisible(False)
            self.pushButton_cancel.setVisible(True)
            self.pushButton_pi.setVisible(True)
        elif self.ori_detail['pistatus'] == 3:
            self.pushButton_accept.setVisible(False)
            self.pushButton_save.setVisible(False)
            self.pushButton_cancel.setVisible(False)
            self.pushButton_pi.setVisible(False)

    @pyqtSlot(str)
    def on_lineEdit_amount_textEdited(self, p_str):
        if p_str == '':
            amount = decimal.Decimal('0')
        else:
            amount = decimal.Decimal(p_str)
        try:
            if amount != self.ori_detail['piamount']:
                self.new_detail['piamount'] = amount
            else:
                try:
                    del self.new_detail['piamount']
                except KeyError:
                    pass
        except KeyError:
            self.new_detail['piamount'] = amount

    @pyqtSlot(bool, str)
    def on_pushButton_qa_signChanged(self, p_bool, p_str):
        if p_bool:
            self.pushButton_accept.setEnabled(True)
            piqaid, piqaname = p_str.split(' ')
        else:
            self.pushButton_accept.setEnabled(False)
            piqaid, piqaname = ('', '')
        try:
            if piqaid != self.ori_detail['piqaid']:
                self.new_detail['piqaid'] = piqaid
                self.new_detail['piqaname'] = piqaname
            else:
                try:
                    del self.new_detail['piqaid']
                    del self.new_detail['piqaname']
                except KeyError:
                    pass
        except KeyError:
            self.new_detail['piqaid'] = piqaid
            self.new_detail['piqaname'] = piqaname

    @pyqtSlot(bool, str)
    def on_pushButton_applyer_signChanged(self, p_bool, p_str):
        if p_bool:
            piapplyerid, piapplyername = p_str.split(' ')
        else:
            piapplyerid, piapplyername = ('', '')
        try:
            if piapplyerid != self.ori_detail['piapplyerid']:
                self.new_detail['piapplyerid'] = piapplyerid
                self.new_detail['piapplyername'] = piapplyername
            else:
                try:
                    del self.new_detail['piapplyerid']
                    del self.new_detail['piapplyername']
                except KeyError:
                    pass
        except KeyError:
            self.new_detail['piapplyerid'] = piapplyerid
            self.new_detail['piapplyername'] = piapplyername

    @pyqtSlot(str)
    def on_comboBox_piposition_currentTextChanged(self, p_str):
        try:
            if p_str != self.ori_detail['position']:
                self.new_detail['position'] = p_str
            else:
                try:
                    del self.new_detail['position']
                except KeyError:
                    pass
        except KeyError:
            self.new_detail['position'] = p_str

    @pyqtSlot()
    def on_pushButton_save_clicked(self):
        if self.has_changed():
            self.WC.update_productputinnote(self.autoid, **self.new_detail)

    @pyqtSlot()
    def on_pushButton_accept_clicked(self):
        if self.lineEdit_amount.text() in ('', '0'):
            msg = MessageBox(self, text="入库数量不能未空")
            msg.show()
            return
        if self.pushButton_applyer.text() in ('', ' '):
            self.pushButton_applyer.setSign(
                True, user.user_id + ' ' + user.user_name)
            self.new_detail['piapplyerid'] = user.user_id
            self.new_detail['piapplyername'] = user.user_name
            self.new_detail['pidate'] = user.now_date
        self.new_detail['pistatus'] = 1

        self.WC.update_productputinnote(self.autoid, **self.new_detail)
        realamount = decimal.Decimal(self.lineEdit_amount.text())
        detail = {'realamount': realamount}
        self.PC.update_producingplan(self.ppid, **detail)

        self.pushButton_save.setVisible(False)
        self.pushButton_accept.setVisible(False)
        self.pushButton_cancel.setVisible(True)
        self.pushButton_pi.setVisible(True)
        self.accepted.emit()

    @pyqtSlot()
    def on_pushButton_cancel_clicked(self):
        self.new_detail['piapplyerid'] = ''
        self.new_detail['piapplyername'] = ''
        self.new_detail['pistatus'] = 0

        self.WC.update_productputinnote(self.autoid, **self.new_detail)

        self.pushButton_save.setVisible(True)
        self.pushButton_accept.setVisible(True)
        self.pushButton_cancel.setVisible(False)
        self.pushButton_pi.setVisible(False)
        self.accepted.emit()

    @pyqtSlot()
    def on_pushButton_pi_clicked(self):
        if self.label_checkstatus.text() != '检验合格':
            mesgbox = MessageBox(parent=self,
                                 title="提示",
                                 text="当前产品尚未检验合格无法入库")
            mesgbox.exec()
            return

        self.new_detail['warehousemanid'] = user.user_id
        self.new_detail['warehousemanname'] = user.user_name
        self.new_detail['pidate'] = user.now_date
        self.new_detail['pistatus'] = 3

        # 计算要入库的产品信息
        putin_msg = self.get_putin_msg()
        res = self.WC.update_preproductputinnote(self.autoid, putin_msg,
                                                 **self.new_detail)
        if not res:
            return
        self.pushButton_piwsman.setSign(True,
                                        user.user_id + ' ' + user.user_name)
        self.pushButton_save.setVisible(False)
        self.pushButton_accept.setVisible(False)
        self.pushButton_cancel.setVisible(False)
        self.pushButton_pi.setVisible(False)
        self.accepted.emit()

    def get_putin_msg(self):

        return_dict = self.product_detail
        return_dict['stuffid'] = return_dict.pop('prodid')
        return_dict['stuffname'] = return_dict.pop('prodname')
        return_dict['stuffkind'] = return_dict.pop('commonname')
        return_dict['ciid'] = self.autoid
        return_dict['pltype'] = 1
        return_dict['stufftype'] = 1
        return_dict['expireddate'] = self.product_detail['makedate'] + \
            datetime.timedelta(days=self.expireddays)
        return_dict['amount'] = decimal.Decimal(self.lineEdit_amount.text())
        return_dict['piamount'] = decimal.Decimal(self.lineEdit_amount.text())
        return_dict['position'] = self.comboBox_piposition.currentText()
        return_dict['checkindate'] = user.now_date
        return_dict['putindate'] = user.now_date
        return_dict['warehousemanid'] = user.user_id
        return_dict['warehousemanname'] = user.user_name
        return_dict['content'] = self.content
        return_dict['cunit'] = self.cunit
        return_dict['water'] = self.water
        return_dict['rdensity'] = self.rdensity
        return_dict['impurity'] = self.impurity
        return_dict['lrid'] = self.lrid
        return_dict['checkdate'] = self.checkdate
        return_dict['nextcheckdate'] = self.checkdate + \
            datetime.timedelta(days=self.countercheckdays)
        return_dict['deptid'] = self.ori_detail['warehouseid']
        return_dict['deptname'] = self.ori_detail['warehousename']
        return return_dict

    def has_changed(self):
        if not len(self.new_detail):
            return False
        if self.pushButton_applyer.text() in ('', ' '):
            self.pushButton_applyer.setSign(
                True, user.user_id + ' ' + user.user_name)
            self.new_detail['piapplyerid'] = user.user_id
            self.new_detail['piapplyername'] = user.user_name
        return True