def flush(self): formula = self.vars_value.nodeValue() expr = self.expr_value.nodeValue() try: for key, value in self.var_dict.items(): kind = value[0] wvalue = str(value[1].value if value[1].value != '' else 0) \ if kind else str(value[1]) try: if formula: formula = formula.replace(key, wvalue) except Exception as e: pass try: if expr: expr = expr.replace(key, wvalue) except Exception as e: pass expr = str(eval(expr, evalenv(self))) self.value = expr self.setText(formula + expr + self.subfix_value.nodeValue()) self.setStyleSheet("background-color: rgb(170, 255, 127);") except Exception as e: self.setToolTip("结果异常," + key + "的值异常") self.setStyleSheet("background-color: rgb(255, 255, 0);")
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
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 exprBox(self, element): widget = XmlExprBox(self.scrollAreaWidgetContents, element) self.boxresize(widget) # 后缀 sibfix = '' # 计算过程 expr = '' # 显示的表达式 va = '' vid = element.AttributeNode("ID").value() if element.hasChildNodes(): q = element.firstChild() while not q.isNull(): b = q.toElement() if b.tagName() == "subfix": sibfix = b.text() elif b.name() == "expr": expr = b.text() elif b.name() == "vars": va = b.text() q = q.nextSibling() # 把文件中的#变量,改为实例中的变量。 expr = expr.replace('#', 'self.') expr = self.set_vars(expr) va = self.set_vars(va) result = '' try: result = str(eval(expr, evalenv(self))) widget.setText(va + result + sibfix) except: return "公式格式错误" if vid: setattr(self, vid, result)
def is_drawamount_enough(self): formula_treeitem = self.get_treeitem(self.treeWidget_formula) while 1: presamount = Decimal('0') try: fitem = next(formula_treeitem) precision = int(fitem.text(7)) presamount = Decimal( rnd(eval(fitem.text(4), evalenv(self)), precision)) stuffkind = fitem.text(2) drawstuff_treeitem = self.get_treeitem( self.treeWidget_drawstuff) while 1: try: ditem = next(drawstuff_treeitem) if ditem.text(1) != stuffkind: continue this_presamount = rnd( Decimal(ditem.text(7)) * Decimal(ditem.text(20)) / Decimal(ditem.text(21)), precision) presamount -= this_presamount except StopIteration: break if presamount > 0: fitem.setText(9, '0') else: fitem.setText(9, '1') except StopIteration: break except SyntaxError: continue
def draw_stuff(self): it = QTreeWidgetItemIterator(self.treeWidget_formula) while it.value(): item = it.value() # 标记为0的列即为未领够料的记录 if item.text(9) == '0': stuffkind = item.text(2) precision = int(item.text(7)) loss = item.text(8) # 处理产品信息的变量,去除系统变量 item.setText(4, self.reckon_expression(item.text(4), 1)) # 计划量 try: presamount = Decimal( rnd(eval(item.text(4), evalenv(self)), precision)) except SyntaxError: if stuffkind + ' 计划量' not in self.errormsg: self.errormsg.append(stuffkind + ' 计划量') presamount = 0 # 把计划量加到产品信息变量中 # self.detail['presamount'] = presamount # 实际量公式,去除系统变量 item.setText(5, self.reckon_expression(item.text(5), 1)) # 领取量公式,去除系统变量 item.setText(6, self.reckon_expression(item.text(6), 1)) # 计算领料量,返回领料情况res, 和标记:是否已经领购料 res = self.reckon_drawamount(stuffkind, presamount, precision, item.text(5), item.text(6), loss) if len(res): self.treeWidget_drawstuff_add_item(res) it += 1 self.is_drawamount_enough()
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 setupExpr(self, widgetAndElement): widget = widgetAndElement[0] element = widgetAndElement[1] # 后缀 subfix = '' # 计算过程 expr = '' # 显示的表达式 va = '' vid = element.attributeNode("ID").value() if element.hasChildNodes(): q = element.firstChild() while not q.isNull(): b = q.toElement() if b.tagName() == "subfix": subfix = b.text() elif b.tagName() == "expr": expr = b.text() elif b.tagName() == "vars": va = b.text() q = q.nextSibling() # 把文件中的#变量,改为实例中的变量。 # expr = expr.replace('#', 'self.') expr_status, expr_result = self.set_vars(widget, expr) vars_status, va_result = self.set_vars(widget, va) result = 0 if expr_status: widget.setStyleSheet("background-color: rgb(170, 255, 127);") try: result = eval(expr_result, evalenv(self)) widget.setStyleSheet("background-color: rgb(255, 0, 0);") except (SyntaxError, NameError): pass else: widget.setToolTip(expr_result) widget.setStyleSheet("background-color: rgb(255, 255, 0);") if vars_status: widget.setText(va_result + str(result) + subfix) else: widget.setText(va + str(result) + subfix)
def exprBox(self): widget = QtWidgets.QLineEdit(self.scrollAreaWidgetContents) self.boxresize(widget) widget.setEnabled(False) widget.setStyleSheet("background-color: rgb(85, 255, 255);") # style = self.reader.attributes().value("showformat") # 后缀 sibfix = '' # 计算过程 expr = '' # 显示的表达式 va = '' vid = self.reader.attributes().value("ID") while 1: self.reader.readNextStartElement() if self.reader.isEndElement() and self.reader.name() == "Expr": break if self.reader.name() == "subfix": sibfix = self.reader.readElementText() elif self.reader.name() == "expr": expr = self.reader.readElementText() elif self.reader.name() == "vars": va = self.reader.readElementText() # 把文件中的#变量,改为实例中的变量。 expr = expr.replace('#', 'self.') expr = self.set_vars(expr) va = self.set_vars(va) try: result = str(eval(expr, evalenv(self))) widget.setText(va + result + sibfix) if id: setattr(self, id, decimal.Decimal(result)) except: return "公式格式错误" # widget.setText(self.reader.readElementText(1)) if vid: setattr(self, vid, result)
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
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 on_treeWidget_drawstuff_droped(self, event, pos): try: data = event.mimeData().data( 'application/x-qabstractitemmodeldatalist') data_items = decode_data(data) p_str = data_items[0][0] srid = int(p_str) # 如果该批次物料已经有领料记录则不做任何操作 if self.has_drawstuff(p_str): return stuff = dict() for item in self.stuff_repository: if srid == item['autoid']: stuff = item break if stuff is None: raise KeyError stuffkind = stuff['stuffkind'] it_formula = self.get_treeitem(self.treeWidget_formula) while 1: try: treeitem = next(it_formula) if treeitem.text(2) == stuffkind: planamount_expression = treeitem.text(4) pracamount_expression = treeitem.text(5) drawamount_expression = treeitem.text(6) precision = int(treeitem.text(7)) loss = treeitem.text(8) try: presamount = Decimal( rnd(eval(planamount_expression, evalenv(self)), precision)) except SyntaxError: if stuffkind + ' 计划量' not in self.errormsg: self.errormsg.append(stuffkind + ' 计划量') presamount = 0 # 没有领够料,继续拖新的物料批次 if treeitem.text(9) == '0': # 获取出该物料其他批次的实际领取量 it_drawstuff = self.get_treeitem( self.treeWidget_drawstuff) try: new_presamount = presamount while 1: drawitem = next(it_drawstuff) if drawitem.text(1) != stuffkind: continue # 转化为计划量 = 领取量 * 计划量 / 实际量 has_drawamount = rnd( Decimal(drawitem.text(9)) * Decimal(drawitem.text(20)) / Decimal(drawitem.text(21)), int(drawitem.text(22))) new_presamount -= has_drawamount except StopIteration: pass # 计算本批的领取量 res = self.reckon_drawamount( p_str, new_presamount, precision, pracamount_expression, drawamount_expression, loss, False) # 已经领够料,还继续拖新的物料批次 elif treeitem.text(9) == '1': res = self.reckon_drawamount( p_str, presamount, precision, pracamount_expression, drawamount_expression, loss, False) if len(res): res[0]['oripresamount'] = presamount self.treeWidget_drawstuff_add_item(res) self.is_drawamount_enough() break except StopIteration: break except ValueError: SaveExcept(ValueError, "拖动库存信息时出错,传入的不是srid", p_str, self.stuff_repository) except KeyError: SaveExcept(ValueError, "拖动库存信息时出错,没有找到对应的库存记录,", p_str, self.stuff_repository)
def reckon_drawamount(self, stuffkindorsrid, presamount, precision, prac_expression, draw_expression, loss=0, flat=True): # stuffkindorsrid: 根据flat决定类型, True是物料种类,False是srid # presamount: 计划量 # precision: 计算结果精度 # prac_expression: 实际量公式 # draw_expression: 领取公式 # loss: 损耗限度 # flat: 是否需要继续领下一批物料,默认为True即继续领下一批物料, # False则不再领取下一批物料 # 要领取的物料批次 draw_list = [] # 已经领取了的量 has_drawamount = 0 # 分析公式,获取变量 pattern = re.findall(r'@\w*@', draw_expression) # 把变量设置为对应的值 for item in self.stuff_repository: item['oripresamount'] = 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 has_draw_stuff = self.get_treeitem(self.treeWidget_drawstuff) # 检查该批次是否已经选择过了 draw_flag = 0 while 1: try: stuff = next(has_draw_stuff) if int(stuff.text(0)) == item['autoid']: draw_flag = 1 break except StopIteration: break if draw_flag == 1: continue item['loss'] = loss item['presamount'] = 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 if drawamount == 0: continue elif item['amount'] >= drawamount: item['drawamount'] = drawamount item['newpracamount'] = item['pracamount'] draw_list.append(item) break else: # 转化为计划量 = 领取量 * 计划量 / 实际量 has_drawamount = Decimal( rnd(item['amount'] * presamount / item['pracamount'], precision)) item['newpracamount'] = rnd(item['amount'], precision) item['drawamount'] = rnd(item['amount'], precision) draw_list.append(item) if not flat: # 指定库存记录时,默认按领够料处理 break return draw_list
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: formula_item = self.get_treeitem(self.treeWidget_formula) while 1: try: treeitem = next(formula_item) if treeitem.text(2) == var_name: if treeitem.text(9) == '0': # stuffkind = item.text(2) precision = int(treeitem.text(7)) loss = treeitem.text(8) # 处理产品信息的变量,去除系统变量 treeitem.setText( 4, self.reckon_expression( treeitem.text(4), iterdepth + 1)) # 计划量 try: presamount = Decimal( rnd( eval(treeitem.text(4), evalenv(self)), precision)) except SyntaxError: if var_name + ' 计划量' not in self.errormsg: self.errormsg.append(var_name + ' 计划量') presamount = 0 # 把计划量加到产品信息变量中 # self.detail['presamount'] = presamount # 实际量公式,去除系统变量 treeitem.setText( 5, self.reckon_expression( treeitem.text(5), iterdepth + 1)) # 领取量公式,去除系统变量 treeitem.setText( 6, self.reckon_expression( treeitem.text(6), iterdepth + 1)) # 计算领料量,返回领料情况res, 和标记:是否已经领购料 res = self.reckon_drawamount( var_name, presamount, precision, treeitem.text(5), treeitem.text(6), loss) if len(res): self.treeWidget_drawstuff_add_item(res) self.is_drawamount_enough() expression = self.reckon_expression( expression, iterdepth + 1) except (StopIteration, RuntimeError) as e: 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