星空二开对接地磅,电子称方案分享原创
101人赞赏了该文章
1,335次浏览
编辑于2023年11月07日 12:05:48
因为社区上对接地磅的案例比较少,今天就厚脸皮分享一个不太成熟的案例给大家!不足之处望各位大佬多多指教
业务场景:客户需要扫描托码或者箱码,箱/托的标准重量应当事先维护好一个值,也可以给客户做一个装托/箱单,给他生成托码箱码标准重量信息这些,这里就只分享地磅的对接方法和代码。
准备工作:端口模拟工具(VSPD6.9),端口模拟发送软件(bittly),这种软件不一定要用这两个,网上搜一堆,主要是用来模拟连接地磅,模拟地磅发送数据的。因为我们大部分的电子称,地磅基本都是用串口连接的,所以我们本地开发需要这些工具。还需要了解一下端口传输速率的一些基础知识,或者看这个类也可以:KDSerialPortConfig,上面会有相关的参数属性说明,对着地磅,电子称的说明抄就可以了。
设计说明:如下图案例是根发货通知单来进行称重的,所以开发了扫描发货单号自动拉取发货单的相关信息到称重单上。
49.3区域显示当前地磅的重量,右侧显示当前箱码,当前地磅重量与标准重量对比是否符合称重要求。如满足则自动将当前箱/托信息记录到明细行。
代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Text;
using BW.K3Cloud.DiBangApp.Business.Plugin.Utils;
using Kingdee.BOS;
using Kingdee.BOS.App;
using Kingdee.BOS.App.Data;
using Kingdee.BOS.Contracts;
using Kingdee.BOS.Core.Bill.PlugIn;
using Kingdee.BOS.Core.Bill.PlugIn.Args;
using Kingdee.BOS.Core.DynamicForm;
using Kingdee.BOS.Core.DynamicForm.Operation;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.Core.DynamicForm.PlugIn.ControlModel;
using Kingdee.BOS.Core.Enums;
using Kingdee.BOS.Core.List;
using Kingdee.BOS.Core.Metadata.ConvertElement;
using Kingdee.BOS.Core.Metadata.ConvertElement.ServiceArgs;
using Kingdee.BOS.DataEntity;
using Kingdee.BOS.Orm;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.ServiceHelper;
using Kingdee.BOS.Util;
namespace BW.K3Cloud.DiBangApp.Business.Plugin
{
[Description("称重单表单插件")]
[HotUpdate]
public class WeighBillEdit : AbstractBillPlugIn
{
private readonly string red = "#FF0000";
private readonly string green = "#00FF00";
private readonly string blue = "#0000FF";
/// 是否显示保存信息
private bool isShowMessage = true;
public override void AfterBindData(EventArgs e)
{
base.AfterBindData(e);
int height = 25;
this.View.GetControl("FScan").SetCustomPropertyValue("height", height);
this.View.GetControl("FTorrSTDWeight").SetCustomPropertyValue("height", height);
this.View.GetControl("FErrorRate").SetCustomPropertyValue("height", height);
this.View.GetControl("FSCSWeight").SetCustomPropertyValue("height", height);
//设置按钮大小颜色
this.View.GetControl("FStartWeight").SetCustomPropertyValue("FontSize", 16);
this.View.GetControl("FEndWeight").SetCustomPropertyValue("FontSize", 16);
this.View.GetControl("FScan").Enabled = false;
// this.View.GetControl("FDeliveryNotice").SetFocus();
}
public override void BeforeF7Select(BeforeF7SelectEventArgs e)
{
base.BeforeF7Select(e);
//发货通知选单
if (e.FieldKey.EqualsIgnoreCase("FDeliveryNotice"))
{
ListShowParameter show = new ListShowParameter();
show.FormId = "SAL_DELIVERYNOTICE";
show.IsLookUp = true; //是否显示返回数据
show.MultiSelect = false; //是否多选
show.IsUseDefaultScheme = true;
show.ListType = Convert.ToInt32(BOSEnums.Enu_GetListDataType.List);
show.ListFilterParameter.Filter =
"FDocumentStatus='C' and FCLOSESTATUS='A' and FCancelStatus='A' and FTerminationStatus='A'";
this.View.ShowForm(show, result =>
{
var returnData = result.ReturnData;
if (returnData == null) return;
var resObj = (ListSelectedRowCollection)returnData;
var fhObj = KEDUtils.GetQueryData(this.Context, "SAL_DELIVERYNOTICE",
$"FID = {resObj[0].PrimaryKeyValue}");
this.setHeadValue(fhObj);
});
}
}
public override void ButtonClick(ButtonClickEventArgs e)
{
base.ButtonClick(e);
//开始称重
if (e.Key.EqualsIgnoreCase("FStartWeight"))
{
//获取端口名称
var comPort = this.Model.GetValue("FDBProt").ToString();
//new 一个串口配置对象
var kdSerialPort = new KDSerialPortConfig
{
PortName = comPort,
Rate = 9600,
Parity = 0,
Bits = 8,
StopBits = 1,
Timeout = -1
};
this.View.GetControl<SerialPortControl>("FSerialPortCtrl").Init(kdSerialPort); // 初始化并打开端口
this.View.ShowMessage("地磅连接成功!");
this.View.GetControl("FScan").Enabled = true;
this.View.GetControl("FScan").SetFocus();
}
//结束称重
if (e.Key.EqualsIgnoreCase("FEndWeight"))
{
this.View.GetControl<SerialPortControl>("FSerialPortCtrl").Close();//关闭串口
this.View.GetControl("FScan").Enabled = false;
this.View.ShowMessage("地磅连接关闭成功!");
}
}
public override void BarItemClick(BarItemClickEventArgs e)
{
base.BarItemClick(e);
if (e.BarItemKey.EqualsIgnoreCase("tbPushSaleOutStock"))
{
var pkValue = this.Model.GetValue("FFHFID",0).ToString();
var billTypeId = "193822715afc48aa9fa6d6beca7700ab";//标准发货通知单
var ruleId = "DeliveryNotice-OutStock"; //默认单据转换为发货通知单
var targetFormId = "SAL_OUTSTOCK"; //默认目标单为销售出库单
Dictionary<string, object> dic = this.GetPushData();
var pushEntryIds = dic.Keys.ToList();
DynamicObject[] objects = this.Push(this.Context, "SAL_DELIVERYNOTICE", targetFormId, ruleId,
pkValue, pushEntryIds, "FEntity", billTypeId);
var outView = KEDUtils.CreateBillView(this.Context, targetFormId);
outView.Model.DataObject = objects[0];
var fhEntry = outView.Model.GetEntityDataObject(outView.Model.BusinessInfo.GetEntity("FEntity")).ToList();
foreach (var valuePair in dic)
{
int index = fhEntry.FindIndex(x => x["FSourceEntryId"].ToString().Equals(valuePair.Key));
outView.Model.SetValue("FRealQty", valuePair.Value, index);
outView.InvokeFieldUpdateService("FRealQty", index);
}
var saveBill = KEDUtils.SaveBill(this.Context, targetFormId, outView.Model.DataObject);
if (saveBill.IsSuccess)
{
this.Model.SetValue("FJoinOutBills", saveBill.OperateResult.First().Number);
isShowMessage = false;
this.View.InvokeFormOperation(FormOperationEnum.Save);
this.View.ShowMessage("下推出库单成功!");
if (Convert.ToBoolean(this.Model.GetValue("FOutBillAudit")))
{
IOperationResult result = KEDUtils.SubmitAndAuditBill(this.Context, targetFormId,
new[] { saveBill.OperateResult.First().PKValue });
if (!result.IsSuccess)
{
throw new KDException("下推单据自动审核失败!", result.ValidationErrors[0].Message);
}
}
}
else
throw new KDException("下推单据保存失败!", saveBill.ValidationErrors[0].Message);
}
}
public override void PortDataReceived(KDSerialPortEventArgs e)
{
base.PortDataReceived(e);
var hexToStr = this.HexToStr(e.Value.ToString());
if (hexToStr.Length == 12)
{
string substring = hexToStr.Substring(2, 6);
var int32 = Convert.ToDouble(substring);
var sjWeight = Math.Round(int32/10,1);
this.Model.SetValue("FSCSWeight",sjWeight,0);
}
}
public override void DataChanged(DataChangedEventArgs e)
{
base.DataChanged(e);
//条码扫描
if (e.Field.Key.EqualsIgnoreCase("FScan"))
{
var fhBillNo = this.Model.GetValue("FDeliveryNotice");
var boxCodes = DBUtils.ExecuteDynamicObject(this.Context,
"/*dialect*/select A.FPackBoxNo,A.FBoxQty,A.FTorrNo,A.FTorrMaterialId,A.FTorrWeight,A.FSTDWeight,A.FPackSTDWeight " +
"from KED_T_PackBoxEntry A join KED_T_InstallTorr B on A.FID=B.FID " +
$"where B.FDeliveryNotice='{fhBillNo}' and A.FPackBoxNo='{e.NewValue}'");
if (!boxCodes.Any())
{
this.View.ShowErrMessage($"根据当前发货通知单号:{fhBillNo},托码:{e.NewValue},找不到对应的装托数据!请确认条码是否正确!");
return;
}
var sjWeight = Convert.ToDouble(this.Model.GetValue("FSCSWeight"));//地磅重量
var boxCodeObj = boxCodes[0];
var bzWeight = Convert.ToDouble(boxCodeObj["FTorrWeight"]);//标准重量
var btQty = Convert.ToDouble(boxCodeObj["FBoxQty"]);//本托数量
this.Model.SetValue("FTorrSTDWeight",bzWeight,0);
this.Model.SetValue("FTorrQty",btQty,0);
this.SetBigFont("FTorrLable",e.NewValue,blue);
//判断重量是否满足
if (IsOk())
{
var boxEntry = this.Model.GetEntityDataObject(Model.BusinessInfo.GetEntity("FPackBoxEntry"));
if (boxEntry.Any())
{
var any = boxEntry.Any(x => x["FPackBoxNo"].Equals(e.NewValue));
if (any)
{
this.View.ShowErrMessage("当前托已称过重量!请勿重复操作!");
return;
}
}
this.Model.CreateNewEntryRow("FPackBoxEntry");
var rowIndex = this.Model.GetEntryCurrentRowIndex("FPackBoxEntry");
this.Model.SetValue("FPackBoxNo",e.NewValue,rowIndex);
this.Model.SetValue("FBoxQty",boxCodeObj["FBoxQty"],rowIndex);
this.Model.SetValue("FTorrWeight",bzWeight,rowIndex);
this.Model.SetValue("FTorrActualWeight",sjWeight,rowIndex);
this.Model.SetItemValueByID("FBTMaterialId",boxCodeObj["FTorrMaterialId"],rowIndex);
//获取发货明细行索引
var informEntity = this.Model.GetEntityDataObject(this.View.BusinessInfo.GetEntity("FEntity")).ToList();
int fhIndex = informEntity.FindIndex(x => x["FFHMaterialId_Id"].ToString().Equals(boxCodeObj["FTorrMaterialId"].ToString()));
//计算已装托数量,写到发货明细单据体
this.Model.SetValue("FWeightOKQty",Convert.ToInt32(informEntity[fhIndex]["FWeightOKQty"]) + btQty ,fhIndex);
this.SetBigFont("FIsOkLable","通过",green);
this.View.GetControl("FCorrectMp3").InvokeControlMethod("Play", null);
}
else
{
this.SetBigFont("FIsOkLable","不通过",red);
this.View.GetControl("FScanErrorMp3").InvokeControlMethod("Play", null);
}
}
//发货通知单单号值更新-扫码录入
if (e.Field.Key.EqualsIgnoreCase("FDeliveryNotice"))
{
var fhObj = KEDUtils.GetQueryData(this.Context, "SAL_DELIVERYNOTICE",
$"FBillNo = '{e.NewValue}' and FDocumentStatus='C' and FCLOSESTATUS='A' and FCancelStatus='A' and FTerminationStatus='A'");
if (fhObj == null)
{
this.View.ShowErrMessage("条码错误或原源据状态或已关闭!请检查!");
return;
}
this.setHeadValue(fhObj);
this.View.GetControl("FScan").SetFocus();
}
//地磅重量
if (e.Field.Key.EqualsIgnoreCase("FSCSWeight"))
{
this.SetBigFont(e.NewValue, IsOk() ? green : red);
}
//标准重量,和误差率
if (e.Field.Key.EqualsIgnoreCase("FTorrSTDWeight") || e.Field.Key.EqualsIgnoreCase("FErrorRate"))
{
var errorRate = Convert.ToDouble(this.Model.GetValue("FErrorRate"));//误差率
var bzWeight = Convert.ToDouble(Model.GetValue("FTorrSTDWeight"));//标准重量
Control control = this.View.GetControl("FDesignLable");
control.SetCustomPropertyValue("Text",$"实际重量要大于等于:{(bzWeight * (1-errorRate/100)):0.0},且小于等于:{(bzWeight * (1+errorRate/100)):0.0}");
}
}
public override void AfterSave(AfterSaveEventArgs e)
{
base.AfterSave(e);
if (!isShowMessage)
{
e.OperationResult.IsShowMessage = false;
isShowMessage = true;
}
}
public override void BeforeClosed(BeforeClosedEventArgs e)
{
base.BeforeClosed(e);
//关闭单据时,把连接串口关闭
this.View.GetControl<SerialPortControl>("FSerialPortCtrl").Close();//关闭串口
}
public override void AfterDeleteRow(AfterDeleteRowEventArgs e)
{
base.AfterDeleteRow(e);
if (e.EntityKey.EqualsIgnoreCase("FPackBoxEntry"))
{
var rowObj = e.DataEntity;
//获取发货明细行索引
var informEntity = this.Model.GetEntityDataObject(this.View.BusinessInfo.GetEntity("FEntity")).ToList();
int fhIndex = informEntity.FindIndex(x => x["FFHMaterialId_Id"].Equals(rowObj["FBTMaterialId_Id"]));
this.Model.SetValue("FWeightOKQty",Convert.ToInt32(informEntity[fhIndex]["FWeightOKQty"]) - Convert.ToInt32(rowObj["FBoxQty"]),fhIndex);
}
}
private bool IsOk()
{
var sjWeight = Convert.ToDouble(this.Model.GetValue("FSCSWeight")); // 地磅重量
var errorRate = Convert.ToDouble(this.Model.GetValue("FErrorRate")); // 误差率
var bzWeight = Convert.ToDouble(this.Model.GetValue("FTorrSTDWeight")); // 标准重量
var upperLimit = Math.Round(bzWeight * (1 + errorRate / 100), 1);
var lowerLimit = Math.Round(bzWeight * (1 - errorRate / 100), 1);
return sjWeight <= upperLimit && sjWeight >= lowerLimit;
}
/// 设置标签显示区信息
private void SetBigFont(object weight,string color)
{
Control control = this.View.GetControl("FWeightShow");
control.SetCustomPropertyValue("Text",weight);
control.SetCustomPropertyValue("forecolor",color);
}
/// 设置标签显示区信息
private void SetBigFont(string lableKey,object value,string color)
{
Control control = this.View.GetControl(lableKey);
control.SetCustomPropertyValue("Text",value);
control.SetCustomPropertyValue("forecolor",color);
}
/// 填充发货单数据
private void setHeadValue(DynamicObject fhObj)
{
this.Model.SetValue("FDeliveryNotice", fhObj["BillNo"], 0);
this.Model.SetItemValueByID("FCustomerID", fhObj["CustomerID_Id"], 0);
var fhEntry = (DynamicObjectCollection)fhObj["SAL_DELIVERYNOTICEENTRY"];
this.Model.DeleteEntryData("FEntity");
foreach (var rowObj in fhEntry)
{
this.Model.CreateNewEntryRow("FEntity");
int rowIndex = this.Model.GetEntryCurrentRowIndex("FEntity");
this.View.Model.SetItemValueByID("FFHMaterialID", rowObj["MaterialId_Id"], rowIndex);
this.Model.SetValue("FFhEntryId", rowObj["Id"], rowIndex);
this.Model.SetValue("FFHFID", fhObj["Id"], rowIndex);
this.Model.SetValue("FSourceBillType", "SAL_DELIVERYNOTICE", rowIndex);
this.Model.SetValue("FSourceBillNo", fhObj["BillNo"], rowIndex);
this.Model.SetValue("FSaleQty", rowObj["Qty"], rowIndex);
}
this.View.UpdateView("FEntity");
}
// 返回十六进制代表的字符串
private string HexToStr(string mHex)
{
mHex = mHex.Replace(" ", "");
if (mHex.Length <= 0) return "";
byte[] vBytes
= new byte[mHex.Length / 2];
for (int i = 0;
i < mHex.Length;
i += 2)
if (!byte.TryParse(mHex.Substring(i, 2), NumberStyles.HexNumber, null, out
vBytes[i / 2]))
vBytes[i / 2] = 0;
return
Encoding.Default.GetString(vBytes);
}
/// 获取下推单据的数据包
private Dictionary<string, object> GetPushData()
{
Dictionary<string, object> dic = new Dictionary<string, object>();
var fhEntry = this.Model.GetEntityDataObject(this.Model.BusinessInfo.GetEntity("FEntity"));
foreach (var fhRow in fhEntry)
{
var weightQty = Convert.ToInt32(fhRow["FWeightOKQty"]);
//判断数量
if (weightQty > 0)
{
dic.Add(fhRow["FFhEntryId"].ToString(),weightQty);
}
}
if (!dic.Any())
throw new KDException("", "请先进行称重!");
return dic;
}
/// <summary>
/// 通用下推(按分录下推)
/// </summary>
/// <param name="ctx">上下文</param>
/// <param name="sourceFormId">源单key</param>
/// <param name="targetFormId">目标单key</param>
/// <param name="ruleId">单据转换规则ID</param>
/// <param name="pkValue">源单ID</param>
/// <param name="entryIds">源单单据体entryId</param>
/// <param name="entryKey">源单单据体Entrykey</param>
/// <param name="billTypeID">单据类型内码</param>
/// <returns></returns>
/// <exception cref="KDBusinessException"></exception>
private DynamicObject[] Push(Context ctx, string sourceFormId, string targetFormId, string ruleId,
string pkValue, List<string> entryIds, string entryKey, object billTypeID)
{
//使用转换规则标识获取指定的转换规则
ConvertRuleMetaData ruleMeta = ConvertServiceHelper.GetConvertRule(ctx, ruleId);
IConvertService convertService = ServiceHelper.GetService<IConvertService>();
ConvertRuleElement rules = ruleMeta.Rule;
if (rules == null)
throw new KDBusinessException("", $"未找到{sourceFormId}到{targetFormId}之间,启用的转换规则,无法自动下推!");
//开始构建下推参数: 待下推的源单数据行
List<ListSelectedRow> srcSelectedRows = new List<ListSelectedRow>();
foreach (var entryId in entryIds)
{
srcSelectedRows.Add(
new ListSelectedRow(pkValue, entryId, 0, sourceFormId) { EntryEntityKey = entryKey });
}
//指定目标单单据类型:
//情况比较复杂,没有合适的案例做参照,示例代码暂略,直接留空,会下推到默认的单据类型
string targetBillTypeId = string.Empty;
if (billTypeID != null)
{
BillTypeMapPolicyElement rulesPolicy = null;
foreach (var policy in rules.Policies)
{
if (policy.GetType().Name.Equals("BillTypeMapPolicyElement"))
{
rulesPolicy = (BillTypeMapPolicyElement)policy;
break;
}
}
if (rulesPolicy != null)
foreach (var billType in rulesPolicy.BillTypeMaps)
{
if (billType.SourceBillTypeId == null) continue;
if (billType.SourceBillTypeId.Equals(billTypeID.ToString()))
{
targetBillTypeId = billType.TargetBillTypeId;
break;
}
}
}
// 指定目标单据主业务组织:情况更加复杂,需要涉及到业务委托关系,缺少合适案例,示例代码暂略
// 建议在转换规则中,配置好主业务组织字段的映射关系:运行时,由系统根据映射关系,自动从上游单据取主业务组织,避免由插件指定
long targetOrgId = 0;
//自定义参数字典:把一些自定义参数,传递到转换插件中;转换插件再根据这些参数,进行特定处理
Dictionary<string, object> custParams = new Dictionary<string, object>();
//组装下推参数对象
PushArgs pushArgs = new PushArgs(rules, srcSelectedRows.ToArray())
{ TargetBillTypeId = targetBillTypeId, TargetOrgId = targetOrgId, CustomParams = custParams };
//调用下推服务,生成下游单据数据包
ConvertOperationResult operationResult = convertService.Push(ctx, pushArgs, OperateOption.Create());
//开始处理下推结果: 获取下推生成的下游单据数据包
DynamicObject[] objs = (from p in operationResult.TargetDataEntities select p.DataEntity).ToArray();
//未下推成功目标单,抛出错误,中断审核
if (objs.Length == 0)
throw new KDBusinessException("", $"由{sourceFormId}自动下推{targetFormId},没有成功生成数据包,自动下推失败!");
return objs;
}
}
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Text;
using BW.K3Cloud.DiBangApp.Business.Plugin.Utils;
using Kingdee.BOS;
using Kingdee.BOS.App;
using Kingdee.BOS.App.Data;
using Kingdee.BOS.Contracts;
using Kingdee.BOS.Core.Bill.PlugIn;
using Kingdee.BOS.Core.Bill.PlugIn.Args;
using Kingdee.BOS.Core.DynamicForm;
using Kingdee.BOS.Core.DynamicForm.Operation;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.Core.DynamicForm.PlugIn.ControlModel;
using Kingdee.BOS.Core.Enums;
using Kingdee.BOS.Core.List;
using Kingdee.BOS.Core.Metadata.ConvertElement;
using Kingdee.BOS.Core.Metadata.ConvertElement.ServiceArgs;
using Kingdee.BOS.DataEntity;
using Kingdee.BOS.Orm;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.ServiceHelper;
using Kingdee.BOS.Util;
namespace BW.K3Cloud.DiBangApp.Business.Plugin
{
[Description("称重单表单插件")]
[HotUpdate]
public class WeighBillEdit : AbstractBillPlugIn
{
private readonly string red = "#FF0000";
private readonly string green = "#00FF00";
private readonly string blue = "#0000FF";
/// 是否显示保存信息
private bool isShowMessage = true;
public override void AfterBindData(EventArgs e)
{
base.AfterBindData(e);
int height = 25;
this.View.GetControl("FScan").SetCustomPropertyValue("height", height);
this.View.GetControl("FTorrSTDWeight").SetCustomPropertyValue("height", height);
this.View.GetControl("FErrorRate").SetCustomPropertyValue("height", height);
this.View.GetControl("FSCSWeight").SetCustomPropertyValue("height", height);
//设置按钮大小颜色
this.View.GetControl("FStartWeight").SetCustomPropertyValue("FontSize", 16);
this.View.GetControl("FEndWeight").SetCustomPropertyValue("FontSize", 16);
this.View.GetControl("FScan").Enabled = false;
// this.View.GetControl("FDeliveryNotice").SetFocus();
}
public override void BeforeF7Select(BeforeF7SelectEventArgs e)
{
base.BeforeF7Select(e);
//发货通知选单
if (e.FieldKey.EqualsIgnoreCase("FDeliveryNotice"))
{
ListShowParameter show = new ListShowParameter();
show.FormId = "SAL_DELIVERYNOTICE";
show.IsLookUp = true; //是否显示返回数据
show.MultiSelect = false; //是否多选
show.IsUseDefaultScheme = true;
show.ListType = Convert.ToInt32(BOSEnums.Enu_GetListDataType.List);
show.ListFilterParameter.Filter =
"FDocumentStatus='C' and FCLOSESTATUS='A' and FCancelStatus='A' and FTerminationStatus='A'";
this.View.ShowForm(show, result =>
{
var returnData = result.ReturnData;
if (returnData == null) return;
var resObj = (ListSelectedRowCollection)returnData;
var fhObj = KEDUtils.GetQueryData(this.Context, "SAL_DELIVERYNOTICE",
$"FID = {resObj[0].PrimaryKeyValue}");
this.setHeadValue(fhObj);
});
}
}
public override void ButtonClick(ButtonClickEventArgs e)
{
base.ButtonClick(e);
//开始称重
if (e.Key.EqualsIgnoreCase("FStartWeight"))
{
//获取端口名称
var comPort = this.Model.GetValue("FDBProt").ToString();
//new 一个串口配置对象
var kdSerialPort = new KDSerialPortConfig
{
PortName = comPort,
Rate = 9600,
Parity = 0,
Bits = 8,
StopBits = 1,
Timeout = -1
};
this.View.GetControl<SerialPortControl>("FSerialPortCtrl").Init(kdSerialPort); // 初始化并打开端口
this.View.ShowMessage("地磅连接成功!");
this.View.GetControl("FScan").Enabled = true;
this.View.GetControl("FScan").SetFocus();
}
//结束称重
if (e.Key.EqualsIgnoreCase("FEndWeight"))
{
this.View.GetControl<SerialPortControl>("FSerialPortCtrl").Close();//关闭串口
this.View.GetControl("FScan").Enabled = false;
this.View.ShowMessage("地磅连接关闭成功!");
}
}
public override void BarItemClick(BarItemClickEventArgs e)
{
base.BarItemClick(e);
if (e.BarItemKey.EqualsIgnoreCase("tbPushSaleOutStock"))
{
var pkValue = this.Model.GetValue("FFHFID",0).ToString();
var billTypeId = "193822715afc48aa9fa6d6beca7700ab";//标准发货通知单
var ruleId = "DeliveryNotice-OutStock"; //默认单据转换为发货通知单
var targetFormId = "SAL_OUTSTOCK"; //默认目标单为销售出库单
Dictionary<string, object> dic = this.GetPushData();
var pushEntryIds = dic.Keys.ToList();
DynamicObject[] objects = this.Push(this.Context, "SAL_DELIVERYNOTICE", targetFormId, ruleId,
pkValue, pushEntryIds, "FEntity", billTypeId);
var outView = KEDUtils.CreateBillView(this.Context, targetFormId);
outView.Model.DataObject = objects[0];
var fhEntry = outView.Model.GetEntityDataObject(outView.Model.BusinessInfo.GetEntity("FEntity")).ToList();
foreach (var valuePair in dic)
{
int index = fhEntry.FindIndex(x => x["FSourceEntryId"].ToString().Equals(valuePair.Key));
outView.Model.SetValue("FRealQty", valuePair.Value, index);
outView.InvokeFieldUpdateService("FRealQty", index);
}
var saveBill = KEDUtils.SaveBill(this.Context, targetFormId, outView.Model.DataObject);
if (saveBill.IsSuccess)
{
this.Model.SetValue("FJoinOutBills", saveBill.OperateResult.First().Number);
isShowMessage = false;
this.View.InvokeFormOperation(FormOperationEnum.Save);
this.View.ShowMessage("下推出库单成功!");
if (Convert.ToBoolean(this.Model.GetValue("FOutBillAudit")))
{
IOperationResult result = KEDUtils.SubmitAndAuditBill(this.Context, targetFormId,
new[] { saveBill.OperateResult.First().PKValue });
if (!result.IsSuccess)
{
throw new KDException("下推单据自动审核失败!", result.ValidationErrors[0].Message);
}
}
}
else
throw new KDException("下推单据保存失败!", saveBill.ValidationErrors[0].Message);
}
}
public override void PortDataReceived(KDSerialPortEventArgs e)
{
base.PortDataReceived(e);
var hexToStr = this.HexToStr(e.Value.ToString());
if (hexToStr.Length == 12)
{
string substring = hexToStr.Substring(2, 6);
var int32 = Convert.ToDouble(substring);
var sjWeight = Math.Round(int32/10,1);
this.Model.SetValue("FSCSWeight",sjWeight,0);
}
}
public override void DataChanged(DataChangedEventArgs e)
{
base.DataChanged(e);
//条码扫描
if (e.Field.Key.EqualsIgnoreCase("FScan"))
{
var fhBillNo = this.Model.GetValue("FDeliveryNotice");
var boxCodes = DBUtils.ExecuteDynamicObject(this.Context,
"/*dialect*/select A.FPackBoxNo,A.FBoxQty,A.FTorrNo,A.FTorrMaterialId,A.FTorrWeight,A.FSTDWeight,A.FPackSTDWeight " +
"from KED_T_PackBoxEntry A join KED_T_InstallTorr B on A.FID=B.FID " +
$"where B.FDeliveryNotice='{fhBillNo}' and A.FPackBoxNo='{e.NewValue}'");
if (!boxCodes.Any())
{
this.View.ShowErrMessage($"根据当前发货通知单号:{fhBillNo},托码:{e.NewValue},找不到对应的装托数据!请确认条码是否正确!");
return;
}
var sjWeight = Convert.ToDouble(this.Model.GetValue("FSCSWeight"));//地磅重量
var boxCodeObj = boxCodes[0];
var bzWeight = Convert.ToDouble(boxCodeObj["FTorrWeight"]);//标准重量
var btQty = Convert.ToDouble(boxCodeObj["FBoxQty"]);//本托数量
this.Model.SetValue("FTorrSTDWeight",bzWeight,0);
this.Model.SetValue("FTorrQty",btQty,0);
this.SetBigFont("FTorrLable",e.NewValue,blue);
//判断重量是否满足
if (IsOk())
{
var boxEntry = this.Model.GetEntityDataObject(Model.BusinessInfo.GetEntity("FPackBoxEntry"));
if (boxEntry.Any())
{
var any = boxEntry.Any(x => x["FPackBoxNo"].Equals(e.NewValue));
if (any)
{
this.View.ShowErrMessage("当前托已称过重量!请勿重复操作!");
return;
}
}
this.Model.CreateNewEntryRow("FPackBoxEntry");
var rowIndex = this.Model.GetEntryCurrentRowIndex("FPackBoxEntry");
this.Model.SetValue("FPackBoxNo",e.NewValue,rowIndex);
this.Model.SetValue("FBoxQty",boxCodeObj["FBoxQty"],rowIndex);
this.Model.SetValue("FTorrWeight",bzWeight,rowIndex);
this.Model.SetValue("FTorrActualWeight",sjWeight,rowIndex);
this.Model.SetItemValueByID("FBTMaterialId",boxCodeObj["FTorrMaterialId"],rowIndex);
//获取发货明细行索引
var informEntity = this.Model.GetEntityDataObject(this.View.BusinessInfo.GetEntity("FEntity")).ToList();
int fhIndex = informEntity.FindIndex(x => x["FFHMaterialId_Id"].ToString().Equals(boxCodeObj["FTorrMaterialId"].ToString()));
//计算已装托数量,写到发货明细单据体
this.Model.SetValue("FWeightOKQty",Convert.ToInt32(informEntity[fhIndex]["FWeightOKQty"]) + btQty ,fhIndex);
this.SetBigFont("FIsOkLable","通过",green);
this.View.GetControl("FCorrectMp3").InvokeControlMethod("Play", null);
}
else
{
this.SetBigFont("FIsOkLable","不通过",red);
this.View.GetControl("FScanErrorMp3").InvokeControlMethod("Play", null);
}
}
//发货通知单单号值更新-扫码录入
if (e.Field.Key.EqualsIgnoreCase("FDeliveryNotice"))
{
var fhObj = KEDUtils.GetQueryData(this.Context, "SAL_DELIVERYNOTICE",
$"FBillNo = '{e.NewValue}' and FDocumentStatus='C' and FCLOSESTATUS='A' and FCancelStatus='A' and FTerminationStatus='A'");
if (fhObj == null)
{
this.View.ShowErrMessage("条码错误或原源据状态或已关闭!请检查!");
return;
}
this.setHeadValue(fhObj);
this.View.GetControl("FScan").SetFocus();
}
//地磅重量
if (e.Field.Key.EqualsIgnoreCase("FSCSWeight"))
{
this.SetBigFont(e.NewValue, IsOk() ? green : red);
}
//标准重量,和误差率
if (e.Field.Key.EqualsIgnoreCase("FTorrSTDWeight") || e.Field.Key.EqualsIgnoreCase("FErrorRate"))
{
var errorRate = Convert.ToDouble(this.Model.GetValue("FErrorRate"));//误差率
var bzWeight = Convert.ToDouble(Model.GetValue("FTorrSTDWeight"));//标准重量
Control control = this.View.GetControl("FDesignLable");
control.SetCustomPropertyValue("Text",$"实际重量要大于等于:{(bzWeight * (1-errorRate/100)):0.0},且小于等于:{(bzWeight * (1+errorRate/100)):0.0}");
}
}
public override void AfterSave(AfterSaveEventArgs e)
{
base.AfterSave(e);
if (!isShowMessage)
{
e.OperationResult.IsShowMessage = false;
isShowMessage = true;
}
}
public override void BeforeClosed(BeforeClosedEventArgs e)
{
base.BeforeClosed(e);
//关闭单据时,把连接串口关闭
this.View.GetControl<SerialPortControl>("FSerialPortCtrl").Close();//关闭串口
}
public override void AfterDeleteRow(AfterDeleteRowEventArgs e)
{
base.AfterDeleteRow(e);
if (e.EntityKey.EqualsIgnoreCase("FPackBoxEntry"))
{
var rowObj = e.DataEntity;
//获取发货明细行索引
var informEntity = this.Model.GetEntityDataObject(this.View.BusinessInfo.GetEntity("FEntity")).ToList();
int fhIndex = informEntity.FindIndex(x => x["FFHMaterialId_Id"].Equals(rowObj["FBTMaterialId_Id"]));
this.Model.SetValue("FWeightOKQty",Convert.ToInt32(informEntity[fhIndex]["FWeightOKQty"]) - Convert.ToInt32(rowObj["FBoxQty"]),fhIndex);
}
}
private bool IsOk()
{
var sjWeight = Convert.ToDouble(this.Model.GetValue("FSCSWeight")); // 地磅重量
var errorRate = Convert.ToDouble(this.Model.GetValue("FErrorRate")); // 误差率
var bzWeight = Convert.ToDouble(this.Model.GetValue("FTorrSTDWeight")); // 标准重量
var upperLimit = Math.Round(bzWeight * (1 + errorRate / 100), 1);
var lowerLimit = Math.Round(bzWeight * (1 - errorRate / 100), 1);
return sjWeight <= upperLimit && sjWeight >= lowerLimit;
}
/// 设置标签显示区信息
private void SetBigFont(object weight,string color)
{
Control control = this.View.GetControl("FWeightShow");
control.SetCustomPropertyValue("Text",weight);
control.SetCustomPropertyValue("forecolor",color);
}
/// 设置标签显示区信息
private void SetBigFont(string lableKey,object value,string color)
{
Control control = this.View.GetControl(lableKey);
control.SetCustomPropertyValue("Text",value);
control.SetCustomPropertyValue("forecolor",color);
}
/// 填充发货单数据
private void setHeadValue(DynamicObject fhObj)
{
this.Model.SetValue("FDeliveryNotice", fhObj["BillNo"], 0);
this.Model.SetItemValueByID("FCustomerID", fhObj["CustomerID_Id"], 0);
var fhEntry = (DynamicObjectCollection)fhObj["SAL_DELIVERYNOTICEENTRY"];
this.Model.DeleteEntryData("FEntity");
foreach (var rowObj in fhEntry)
{
this.Model.CreateNewEntryRow("FEntity");
int rowIndex = this.Model.GetEntryCurrentRowIndex("FEntity");
this.View.Model.SetItemValueByID("FFHMaterialID", rowObj["MaterialId_Id"], rowIndex);
this.Model.SetValue("FFhEntryId", rowObj["Id"], rowIndex);
this.Model.SetValue("FFHFID", fhObj["Id"], rowIndex);
this.Model.SetValue("FSourceBillType", "SAL_DELIVERYNOTICE", rowIndex);
this.Model.SetValue("FSourceBillNo", fhObj["BillNo"], rowIndex);
this.Model.SetValue("FSaleQty", rowObj["Qty"], rowIndex);
}
this.View.UpdateView("FEntity");
}
// 返回十六进制代表的字符串
private string HexToStr(string mHex)
{
mHex = mHex.Replace(" ", "");
if (mHex.Length <= 0) return "";
byte[] vBytes
= new byte[mHex.Length / 2];
for (int i = 0;
i < mHex.Length;
i += 2)
if (!byte.TryParse(mHex.Substring(i, 2), NumberStyles.HexNumber, null, out
vBytes[i / 2]))
vBytes[i / 2] = 0;
return
Encoding.Default.GetString(vBytes);
}
/// 获取下推单据的数据包
private Dictionary<string, object> GetPushData()
{
Dictionary<string, object> dic = new Dictionary<string, object>();
var fhEntry = this.Model.GetEntityDataObject(this.Model.BusinessInfo.GetEntity("FEntity"));
foreach (var fhRow in fhEntry)
{
var weightQty = Convert.ToInt32(fhRow["FWeightOKQty"]);
//判断数量
if (weightQty > 0)
{
dic.Add(fhRow["FFhEntryId"].ToString(),weightQty);
}
}
if (!dic.Any())
throw new KDException("", "请先进行称重!");
return dic;
}
/// <summary>
/// 通用下推(按分录下推)
/// </summary>
/// <param name="ctx">上下文</param>
/// <param name="sourceFormId">源单key</param>
/// <param name="targetFormId">目标单key</param>
/// <param name="ruleId">单据转换规则ID</param>
/// <param name="pkValue">源单ID</param>
/// <param name="entryIds">源单单据体entryId</param>
/// <param name="entryKey">源单单据体Entrykey</param>
/// <param name="billTypeID">单据类型内码</param>
/// <returns></returns>
/// <exception cref="KDBusinessException"></exception>
private DynamicObject[] Push(Context ctx, string sourceFormId, string targetFormId, string ruleId,
string pkValue, List<string> entryIds, string entryKey, object billTypeID)
{
//使用转换规则标识获取指定的转换规则
ConvertRuleMetaData ruleMeta = ConvertServiceHelper.GetConvertRule(ctx, ruleId);
IConvertService convertService = ServiceHelper.GetService<IConvertService>();
ConvertRuleElement rules = ruleMeta.Rule;
if (rules == null)
throw new KDBusinessException("", $"未找到{sourceFormId}到{targetFormId}之间,启用的转换规则,无法自动下推!");
//开始构建下推参数: 待下推的源单数据行
List<ListSelectedRow> srcSelectedRows = new List<ListSelectedRow>();
foreach (var entryId in entryIds)
{
srcSelectedRows.Add(
new ListSelectedRow(pkValue, entryId, 0, sourceFormId) { EntryEntityKey = entryKey });
}
//指定目标单单据类型:
//情况比较复杂,没有合适的案例做参照,示例代码暂略,直接留空,会下推到默认的单据类型
string targetBillTypeId = string.Empty;
if (billTypeID != null)
{
BillTypeMapPolicyElement rulesPolicy = null;
foreach (var policy in rules.Policies)
{
if (policy.GetType().Name.Equals("BillTypeMapPolicyElement"))
{
rulesPolicy = (BillTypeMapPolicyElement)policy;
break;
}
}
if (rulesPolicy != null)
foreach (var billType in rulesPolicy.BillTypeMaps)
{
if (billType.SourceBillTypeId == null) continue;
if (billType.SourceBillTypeId.Equals(billTypeID.ToString()))
{
targetBillTypeId = billType.TargetBillTypeId;
break;
}
}
}
// 指定目标单据主业务组织:情况更加复杂,需要涉及到业务委托关系,缺少合适案例,示例代码暂略
// 建议在转换规则中,配置好主业务组织字段的映射关系:运行时,由系统根据映射关系,自动从上游单据取主业务组织,避免由插件指定
long targetOrgId = 0;
//自定义参数字典:把一些自定义参数,传递到转换插件中;转换插件再根据这些参数,进行特定处理
Dictionary<string, object> custParams = new Dictionary<string, object>();
//组装下推参数对象
PushArgs pushArgs = new PushArgs(rules, srcSelectedRows.ToArray())
{ TargetBillTypeId = targetBillTypeId, TargetOrgId = targetOrgId, CustomParams = custParams };
//调用下推服务,生成下游单据数据包
ConvertOperationResult operationResult = convertService.Push(ctx, pushArgs, OperateOption.Create());
//开始处理下推结果: 获取下推生成的下游单据数据包
DynamicObject[] objs = (from p in operationResult.TargetDataEntities select p.DataEntity).ToArray();
//未下推成功目标单,抛出错误,中断审核
if (objs.Length == 0)
throw new KDBusinessException("", $"由{sourceFormId}自动下推{targetFormId},没有成功生成数据包,自动下推失败!");
return objs;
}
}
}
推荐阅读