遇到的问题:
一:下推的时候收料通知单的仓库不是必填,但采购入库单的字段是必填的,无法默认传值,只能额外插入新的数据仓库才能下推成功?
方法一:先下推 下推成功后 入库订单为暂存 (暂存状态的数据可以不是很全) 然后由暂存状态转为保存状态 (把需要额外填的数据放入保存的json里) 保存状态后提交 提交后审核数据。
方法二:金蝶老师建议的Bos平台配置单据。
问题2:一个收料通知单里一个源单号可能对应多个物料号,下推的时候可能只会下推当中的一个物料,用单据查询的如何需要如何查询?如果只是根据Fid和物料号去条件过滤查出的数据不准。
解决方法:单据分录内码 多个筛选条件的时候 用and 拼接
json工具类
public class JsonHelper
{
/// <summary>
/// 将对象序列化为JSON格式
/// </summary>
/// <param name="o">对象</param>
/// <returns>json字符串</returns>
public static string SerializeObject(object o)
{
string json = JsonConvert.SerializeObject(o);
return json;
}
/// <summary>
/// 解析JSON字符串生成对象实体
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="json">json字符串(eg.{"ID":"112","Name":"石子儿"})</param>
/// <returns>对象实体</returns>
public static T DeserializeJsonToObject<T>(string json) where T : class
{
JsonSerializer serializer = new JsonSerializer();
StringReader sr = new StringReader(json);
object o = serializer.Deserialize(new JsonTextReader(sr), typeof(T));
T t = o as T;
return t;
}
/// <summary>
/// 解析JSON数组生成对象实体集合
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="json">json数组字符串(eg.[{"ID":"112","Name":"石子儿"}])</param>
/// <returns>对象实体集合</returns>
public static List<T> DeserializeJsonToList<T>(string json) where T : class
{
JsonSerializer serializer = new JsonSerializer();
StringReader sr = new StringReader(json);
object o = serializer.Deserialize(new JsonTextReader(sr), typeof(List<T>));
List<T> list = o as List<T>;
return list;
}
/// <summary>
/// 反序列化JSON到给定的匿名对象.
/// </summary>
/// <typeparam name="T">匿名对象类型</typeparam>
/// <param name="json">json字符串</param>
/// <param name="anonymousTypeObject">匿名对象</param>
/// <returns>匿名对象</returns>
public static T DeserializeAnonymousType<T>(string json, T anonymousTypeObject)
{
T t = JsonConvert.DeserializeAnonymousType(json, anonymousTypeObject);
return t;
}
public static string ToJson(DataTable dt)
{
//JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
//javaScriptSerializer.MaxJsonLength = Int32.MaxValue; //取得最大数值
ArrayList arrayList = new ArrayList();
foreach (DataRow dataRow in dt.Rows)
{
Dictionary<string, object> dictionary = new Dictionary<string, object>(); //实例化一个参数集合
foreach (DataColumn dataColumn in dt.Columns)
{
string s_value = dataRow[dataColumn.ColumnName].ToString();
dictionary.Add(dataColumn.ColumnName, s_value);
}
arrayList.Add(dictionary); //ArrayList集合中添加键值
}
// return javaScriptSerializer.Serialize(arrayList); //返回一个json字符串
return JsonConvert.SerializeObject(arrayList);
}
/// <summary>
/// 对象序列化成 XML String
/// </summary>
public static string XmlSerialize<T>(T obj)
{
string xmlString = string.Empty;
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
using (MemoryStream ms = new MemoryStream())
{
xmlSerializer.Serialize(ms, obj);
xmlString = Encoding.UTF8.GetString(ms.ToArray());
}
return xmlString;
}
/// <summary>
/// XML String 反序列化成对象
/// </summary>
public static T XmlDeserialize<T>(string xmlString)
{
T t = default(T);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
using (Stream xmlStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlString)))
{
using (XmlReader xmlReader = XmlReader.Create(xmlStream))
{
Object obj = xmlSerializer.Deserialize(xmlReader);
t = (T)obj;
}
}
return t;
}
Hettclient 工具类:
public class HttpClient
{
/// <summary>
/// Seivice URL
/// </summary>
public string Url { get; set; }
/// <summary>
/// 内容
/// </summary>
public string Content { get; set; }
/// <summary>
/// Cookie,保证登录后,所有访问持有一个Cookie;
/// </summary>
static CookieContainer Cookie = new CookieContainer();
/// <summary>
/// HTTP访问
/// </summary>
public string AsyncRequest()
{
HttpWebRequest httpRequest = HttpWebRequest.Create(Url) as HttpWebRequest;
httpRequest.Method = "POST";
httpRequest.ContentType = "application/json";
httpRequest.CookieContainer = Cookie;
httpRequest.Timeout = 1000 * 60 * 10;//10min
using (Stream reqStream = httpRequest.GetRequestStream())
{
JObject jObj = new JObject();
jObj.Add("format", 1);
jObj.Add("useragent", "ApiClient");
jObj.Add("rid", Guid.NewGuid().ToString().GetHashCode().ToString());
jObj.Add("parameters", Content);
jObj.Add("timestamp", DateTime.Now);
jObj.Add("v", "1.0");
string sContent = jObj.ToString();
var bytes = UnicodeEncoding.UTF8.GetBytes(sContent);
reqStream.Write(bytes, 0, bytes.Length);
reqStream.Flush();
}
using (var repStream = httpRequest.GetResponse().GetResponseStream())
{
using (var reader = new StreamReader(repStream))
{
return ValidateResult(reader.ReadToEnd());
}
}
}
public static string ValidateResult(string responseText)
{
if (responseText.StartsWith("response_error:"))
{
return responseText.TrimStart("response_error:".ToCharArray());
}
return responseText;
}
}
金蝶社区的入门教程:
https://vip.kingdee.com/article/71624106696524544
分录内码:比如一个单据编号下多个物料号的时候 可以根据分录内码下推一条,相当于明细子表的id一样
1.WebAPI如何查询单据体分录内码?
使用Web API ExecuteBillQuery 服务,查询单据数据,如果需要输出单据体内码,请按照如下格式填写单据体主键标识:单据体标识 + “_” + 单据体主键字段名
Json请求示例:
{
"FormId": "PUR_PurchaseOrder",
"FieldKeys": "FPOOrderEntry_FEntryID",
"FilterString": "",
"OrderString": "",
"TopRowCount": 0,
"StartRow": 0,
"Limit": 0
}
收料通知单:FDetailEntity_FEntryID
采购入库单:FInStockEntry_FEntryId
Bos平台的截图:
2.FilterString:过滤条件,字符串类型(非必录) 如何多个筛选条件并行
用and拼接,比如:“FilterString”: "FDocumentStatus = ‘C’ and FStatus = ‘4’ "
3.下推的流程,因为从收料通知单下推采购入库单的过程不知道如何传值,所以我的解决方法是先下推采购入库单为暂存状态,再去根据fid去查找到暂存的采购入库单 修改 提交 审批
{
"Ids": "",
"Numbers": [],//如果只想下推一条,而不是整个单据就不要再这里填入单据编码,填了就会整个单据下推
"EntryIds": "\"101462\"",//单据分录内码
"RuleId": "",
"TargetBillTypeId": "",
"TargetOrgId": 0,
"TargetFormId": "STK_InStock", //入库单的单据编号
"IsEnableDefaultRule": "true", //是否启用默认转换规则,布尔类型,默认false(非必录)
"IsDraftWhenSaveFail": "true",//保存失败时是否暂存
"CustomParams": {}{}
}
4.暂存的数据如何修改?以及传入自己想修改的部分
先查询出这条暂存数据的fid和单据内码分录
{
"Creator": "",
"NeedUpDateFields": ["FInStockEntry","FStockId"],//修改的字段
"NeedReturnFields": ["FStockId"],
"IsDeleteEntry": "false",//默认为true 修改数据的时候为false
"SubSystemId": "",
"IsVerifyBaseDataField": "false",
"IsEntryBatchFill": "true",
"ValidateFlag": "true",
"NumberSearch": "true",
"InterationFlags": "",
"Model": {
"FID": 100271, //主键id
"FInStockEntry": [
{
"FEntryID": 101812,//单据分录内码
"FStockId": {
"FNumber": "1.11" //仓库数据
},
}
],"F_aaaa_Entity":[{"F_aaaa_Base":{"FNUMBER":"1.01.0000"},"F_aaaa_Text":"9999080" },{"F_aaaa_Base": { "FNUMBER": "1.01.0000"},"F_aaaa_Text": "99998083"}
]
}
}
5.如何查询收料通知单下推为采购入库单后实际的实收数量?
在收料通知单无法查看到已收数量,这个数据只能在收料通知单下推为采购入库单的时候才能查看,第二个情况,就是考虑到我们实际使用中收料通知单只会下推为采购入库单,所以可以根据源单号在采购入库单查询所有然后累加这个值:
//已入库数量查询 “CGSL000092”
public double Num(string FSRCBillNo )
{
double num = 0;
HttpClient httpClient = new HttpClient();
List<object> Parameters = new List<object>();
//根据 源单号 查询采购入库单
String data = "{\n" +
" \"FormId\": \"STK_InStock\",\n" +
" \"FieldKeys\": \"FRealQty \",\n" +
" \"FilterString\": \"FSRCBillNo = \'"+FSRCBillNo + "\'and FDocumentStatus = 'C'" +
" \", \"OrderString\": \"\",\n" +
" \"TopRowCount\": 0,\n" +
" \"StartRow\": 0,\n" +
" \"Limit\": 0\n" +
"}";
httpClient.Url = "http://192.168.1.208/k3cloud/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExecuteBillQuery.common.kdsvc";
Parameters.Add(data);
httpClient.Content = JsonConvert.SerializeObject(Parameters);
string jsonString = httpClient.AsyncRequest().ToString();
JArray jarry = JArray.Parse(jsonString);
//string fid = jarry[0][0].ToString();
// "[[10.0000000000],[1990.0000000000],[30.0000000000]]"
double value = 0;
if (jarry.Count > 0) {
for (int i = 0; i < jarry.Count; i++)
{
if (jarry[i] != null)
{
value += (double)jarry[i][0];
}
}
}
return value;
}