系统设置
1.如何在表单的子网格右上角隐藏关联视图按钮
表单编辑器
2.如何控制子网格按钮的显示隐藏
Dynamics 365子网格根据条件隐藏新建/添加按钮 - 微软MVP(15-18)罗勇 - 博客园
前台
1.访问后台方法
访问后台的方法有很多,有通过action访问的,有通过workflow访问的,js的直接查询方法也有两种,一种通过直接查询实体名,只能通过主键查询。另一种fetch可以更灵活的查询。
//直接查询实体
var rest = new fwREST();
var objStr = "accounts?$select=hms_sapcustomerid&$filter=accountid eq (" + customerid + ")";
rest.get(objStr).then(function (ob) {
if (ob.value.error != undefined || ob.value.length > 1) {
} else {
var hms_sapcustomerid = ob.value[0]["hms_sapcustomerid"];
}
});
//请求的封装方法
this.executeWebAPI = function (requestType, requestUri, requestData, successCallback, errorCallback, isAsync) {
var req = new XMLHttpRequest();
if (isAsync == null) {
isAsync = true;
}
req.open(requestType, encodeURI(requestUri), isAsync);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.setRequestHeader("Prefer", "odata.include-annotations=*");
req.onreadystatechange = function () {
if (this.readyState == 4 /* complete */) {
req.onreadystatechange = null;
if (this.status == 200) {
if (successCallback) {
successCallback(JSON.parse(this.responseText));
}
}
else if (this.status == 204) {
if (successCallback) {
successCallback(this.getResponseHeader("OData-EntityId"));
}
}
else {
var error = JSON.parse(this.response).error;
if (errorCallback) { errorCallback(error); }
else { Xrm.Utility.alertDialog(error.message); }
}
}
};
req.send(JSON.stringify(requestData));
}
//fetch的查询方式
var cancelorderId = formContext.data.entity.getId().replace("{", "").replace("}", "");
if (!!cancelorderId) {
var fetchxml = "<fetch mapping='logical' aggregate='false'>" +
"<entity name='hms_changeconfirmeddetail'>" +
"<attribute name='hms_changeconfirmeddetailid' />" +//主键
"<filter type='and' >" +
"<condition attribute='hms_cancelapplyid' operator='eq' value='" + cancelorderId + "' />" +
"<condition attribute='hms_changetype' operator='not-null' />" +
"</filter>" +
"</entity>" +
"</fetch>";
var req = new XMLHttpRequest();
req.open("get", Xrm.Page.context.getClientUrl() + "/api/data/v8.0/hms_changeconfirmeddetails?fetchXml=" + encodeURI(fetchxml), false);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function () {
if (this.readyState == 4) {
if (this.status == 200) {
var data = JSON.parse(this.responseText);
if (data.value.length > 0) {
show = true;
} else {
show = false;
}
}
}
};
req.send();
}
//查询结果用于过滤lookup字段的可选范围
var clientURL = formContext.context.getClientUrl();
var uri = clientURL + "/api/data/v8.0/accounts?$filter=accountid eq " + customerid + "&$select=hms_sapcustomerid";
HMS.CRMUtil.executeWebAPI("GET", uri, null, function (data) {
var length = data.value.length;
if (length > 0) {
var hms_sapcustomerid = data.value[0].hms_sapcustomerid;
var contactWithCustomer = "<filter type='and'>" +
"<condition attribute='hms_name' operator='eq' value='" + hms_sapcustomerid + "'/>" +
"</filter>"
formContext.getControl("hms_soldtoparty").addCustomFilter(contactWithCustomer, "hms_sapsoldtoparty");
}
}, null, false);
2.给lookup字段赋值
formContext.getAttribute("hms_salesorganizationid").setValue([{ id: hms_salesorganizationid, name: ob.value[0]["hms_name"], entityType: 'hms_salesorganization' }]);
3.判断是否页面已保存
if (Xrm.Page.data.entity.getIsDirty()) {
Xrm.Utility.alertDialog("页面尚未保存!");
return;
}
4.阻止保存语句
context.getEventArgs().preventDefault();
5.提示
// 弹窗提示
var alertStrings = { confirmButtonLabel: "Yes", text: "This is an alert.", title: "Sample title" };
var alertOptions = { height: 120, width: 260 };
Xrm.Navigation.openAlertDialog(alertStrings, alertOptions).then(
function (success) {
console.log("Alert dialog closed");
},
function (error) {
console.log(error.message);
}
);
//上方提示栏位
formContext.ui.setFormNotification("未查询到产品型号相关信息!!", "WARNING", "salesPriceCheckError");
setTimeout(function () {
formContext.ui.clearFormNotification('salesPriceCheckError');
}, 5000);
6.设置字段是否必填
formContext.getAttribute("hms_soldtoparty").setRequiredLevel("none");//设置该字段为非必填
formContext.getAttribute("hms_soldtoparty").setRequiredLevel("required");//设置该字段为必填
7.限制lookup字段的查询范围
formContext.getControl("hms_soldtoparty").addCustomFilter(allContacts, "hms_sapsoldtoparty");
8.设置字段可编辑
formContext.getControl("hms_changetype").setDisabled(false); //可编辑
formContext.getControl("hms_changetype").setDisabled(true); //不可编辑
9.设置可见性
//设置字段可见性
formContext.getControl(arg).setVisible(true);//可见
formContext.getControl(arg).setVisible(false);//不可见
//设置选项卡可见性
Xrm.Page.ui.tabs.get("mainform").setVisible(true);
//设置选项卡内某个节可见性
Xrm.Page.ui.tabs.get("mainform").sections.get("doactioniframe").setVisible(true);
10.打开指定实体指定ID的表单
var newid = dataobj.Data.id;
var entityFormOptions = {};
entityFormOptions["entityName"] = "salesorder";
entityFormOptions["entityId"] = newid;
Xrm.Navigation.openForm(entityFormOptions).then(
function (success) {
console.log(success);
},
function (error) {
console.log(error);
});
11.多项选项集字段
11.1 设置可选值
//通用过滤选项集值的函数 attributeName:需要过滤的选项集的属性名 valuesArr:需要保留的选项值
function filterOptionSet (attributeName, valuesArr) {
var optionSet = Xrm.Page.ui.controls.get(attributeName);
var optionSetValues = optionSet.getAttribute().getOptions();
optionSet.clearOptions();
optionSetValues.forEach(function (element) {
var index = valuesArr.indexOf(element.value);
if (index === -1) {
optionSet.removeOption(element.value);
}
else {
optionSet.addOption(element);
}
}, valuesArr);
}
11.2 自定义选择框选项
new Xrm.OptionSetItem(1,'111');
let optionsetControl = Xrm.Page.getControl(field);
optionsetControl.clearOptions();
optionsetControl.addOption(item);
11.3 隐藏不需要的选项
//先判断字段是否可编辑,考虑历史数据的显示
filterOptionSet("hms_documenttype", [10, 20, 30, 40]);
function filterOptionSet(attributeName, valuesArr) {
var fieldstatus = formContext.getControl(attributeName).getDisabled();
if (!fieldstatus) {
var optionSet = Xrm.Page.ui.controls.get(attributeName);
var optionSetValues = optionSet.getAttribute().getOptions();
optionSetValues.forEach(function (element) {
var index = valuesArr.indexOf(element.value);
if (index > -1) {
optionSet.removeOption(element.value);
}
}, valuesArr);
var fieldvalue = Xrm.Page.getAttribute(attributeName).getValue();
if (valuesArr.indexOf(fieldvalue) > -1) {
Xrm.Page.getAttribute(attributeName).setValue(null);
}
}
}
11.4 设置值
//给多项选项集字段取值时,取到的是字符串“1,2,3”,需要转成数组,然后注意转成数字数组后赋值给字段才可。
var new_majorcusttype = ob.value[0]["new_majorcusttype"];
if (new_majorcusttype != null) {
debugger;
var arr = new_majorcusttype.split(",");
let numArray = arr.map(str => parseInt(str));
formContext.getAttribute("hms_majorcusttype").setValue(numArray);
}
12.给lookup字段设置默认查找视图
formContext.getControl("hms_systemuserid").setDefaultView("EBD6ED09-6686-EB11-B02E-00155D93E403");
13.获取当前操作人员ID
var systemuserid = Xrm.Page.context.getUserId().replace("{", "").replace("}", "");
14.获取当前表单实体ID
var id = Xrm.Page.data.entity.getId().replace("{", "").replace("}", "");
15.设置窗体lookup类型字段的查询视图
16.点击按钮弹出人员选择或者其他选择弹窗
var viewId = "{00000000-0000-0000-0000-000000000001}"//HMS.CRMUtil.newGUID();
//2. 获取自定义查询实体的type code,避免同一个实体在不同系统中typecode不相同带来的问题
var objectTypeCode = Mscrm.EntityPropUtil.EntityTypeName2CodeMap["hms_faeengineercard"];
//4. 构造自定义视图
var layoutXML = "<grid name='resultset' object='" + objectTypeCode + "' jump='hms_name' select='1' icon='0' preview='0'>" +
"<row name='result' id='hms_faeengineercard'>" +
"<cell name='hms_systemuserid' width='150' />" +
"<cell name='hms_engineerstatus' width='80' />" +
"<cell name='hms_belongtoarea' width='80' />" +
"<cell name='hms_onhandticketnum' width='90' />" +
"<cell name='hms_skilledservicetype' width='200' />" +
"<cell name='hms_skilledproduct' width='200' />" +
"<cell name='hms_skilledarea' width='200' />" +
"<cell name='hms_domainname' width='150' />" +
"</row>" +
"</grid>";
var customerView = {
Type: 0, //固定值0
fetchXml: fetchXml,
id: viewId,
layoutXml: layoutXML,
name: viewName,
recordType: objectTypeCode
};
//5. 构造dialogOption
var lookupOptions = {
defaultEntityType: "hms_faeengineercard",
entityTypes: ["hms_faeengineercard"],
viewIds: [viewId],
allowMultiSelect: false,
defaultViewId: viewId,
customViews: [customerView]
};
//6. 构造dialog调用参数
Xrm.Utility.lookupObjects(lookupOptions)
.then(function (result) {
debugger;
var domainName = JSON.parse(result[0].keyValues).hms_domainname.value;
var systemUserId = HMS.SupportTicket.RibbonEvent.getSystemUserIdByDomainName("'" + domainName + "'");
var clientURL = Xrm.Page.context.getClientUrl();
var uri = clientURL + "/api/data/v8.0/hms_supporttickets" + supportTicketId.replace("{", "(").replace("}", ")");
var requestData = { "hms_assigntosystemuserid": systemUserId };
HMS.CRMUtil.executeWebAPI(
"PATCH",
uri,
requestData,
function (data) {
// 刷新视图列表
Mscrm.Utilities.refreshCurrentGrid(Mscrm.EntityPropUtil.EntityTypeName2CodeMap["hms_supportticket"]);
},
function (data) {
debugger;
alert("分派工单出错," + data.message);
});
})
.fail(function (error) {
// Do sth.
});
17.刷新视图列表
Mscrm.Utilities.refreshCurrentGrid(Mscrm.EntityPropUtil.EntityTypeName2CodeMap["hms_supportticket"]);
18.判断当前表单是不是新建状态未保存过
var formType = formContext.ui.getFormType();
if (formType != 1) {
//已经保存过了
} else {
//新建状态
}
19.触发字段onchange事件
formContextmaketaction.getAttribute(fieldname).fireOnChange()
20.设置iframe的url
var hisiframe = Xrm.Page.context.getClientUrl() + "/WebResources/hms_explain.html";
var iFramehis = formContextmaketaction.ui.controls.get("IFRAME_levelexplain");
iFramehis.setSrc(hisiframe);
21.自定义单选或多选lookup弹出窗口
/// <summary>
/// 功能:根据工程师角色推荐分派专员
/// </summary>
this.createAssignViewWithEngineerRole = function (supportTicketId) {
// 当工单不满足分派条件 直接返回
if (!HMS.SupportTicket.RibbonEvent.validateTicket(supportTicketId)) {
return;
}
// 根据擅长业务查找FAE工程师
var fetchData = {
name: "分派专员"
};
var fetchXml = [
"<fetch>",
" <entity name='systemuser'>",
" <attribute name='systemuserid' />",
" <attribute name='fullname' />",
" <attribute name='domainname' />",
" <link-entity name='systemuserroles' from='systemuserid' to='systemuserid' link-type='inner'>",
" <link-entity name='role' from='roleid' to='roleid' link-type='inner'>",
" <filter type='or'>",
" <condition attribute='name' operator='eq' value='", fetchData.name/*分派专员*/, "'/>",
" </filter>",
" </link-entity>",
" </link-entity>",
" </entity>",
"</fetch>",
].join("");
HMS.SupportTicket.RibbonEvent.createAssignViewForAssigner(fetchXml, supportTicketId);
}
/// <summary>
/// 功能:生成分派专员视图。
/// </summary>
this.createAssignViewForAssigner = function (fetchXml, supportTicketId) {
debugger;
//1. 定义视图唯一编号guid,可用guid工具生成,只要不重复即可。
var viewId = "{00000000-0000-0000-0000-000000000002}";
//2. 获取自定义查询实体的type code,避免同一个实体在不同系统中typecode不相同带来的问题
var objectTypeCode = Mscrm.EntityPropUtil.EntityTypeName2CodeMap["systemuser"];
//4. 构造自定义视图
var layoutXML = "<grid name='resultset' object='" + objectTypeCode + "' jump='hms_name' select='1' icon='0' preview='0'>" +
"<row name='result' id='systemuser'>" +
"<cell name='fullname' width='150' />" +
"<cell name='domainname' width='150' />" +
"</row>" +
"</grid>";
var customerView = {
Type: 0, //固定值0
fetchXml: fetchXml,
id: viewId,
layoutXml: layoutXML,
name: "分派专员",
recordType: objectTypeCode
};
//5. 构造dialogOption
var lookupOptions = {
defaultEntityType: "systemuser",
entityTypes: ["systemuser"],
viewIds: [viewId],
allowMultiSelect: false,
defaultViewId: viewId,
customViews: [customerView]
};
//6. 构造dialog调用参数
Xrm.Utility.lookupObjects(lookupOptions)
.then(function (result) {
debugger;
var domainName = JSON.parse(result[0].keyValues).domainname.value;
var systemUserId = HMS.SupportTicket.RibbonEvent.getSystemUserIdByDomainName("'" + domainName + "'");
var clientURL = Xrm.Page.context.getClientUrl();
var uri = clientURL + "/api/data/v8.0/hms_supporttickets" + supportTicketId.replace("{", "(").replace("}", ")");
var requestData = { "hms_assigntosystemuserid": systemUserId };
HMS.CRMUtil.executeWebAPI(
"PATCH",
uri,
requestData,
function (data) {
// 刷新视图列表
Mscrm.Utilities.refreshCurrentGrid(Mscrm.EntityPropUtil.EntityTypeName2CodeMap["hms_supportticket"]);
},
function (data) {
debugger;
alert("分派工单出错," + data.message);
});
})
.fail(function (error) {
// Do sth.
});
}
后台
1.创建数据库连接服务
ClientCredentials clientCredent = new ClientCredentials();
clientCredent.UserName.UserName = UserName + "@" + DomainName;
clientCredent.UserName.Password = Password;
Uri uri = new Uri(ServiceUri);
IServiceManagement<IOrganizationService> sm = ServiceConfigurationFactory.CreateManagement<IOrganizationService>(uri);
IOrganizationService organizationService = new OrganizationServiceProxy(sm, clientCredent);
OrganizationServiceProxy serviceProxy = new OrganizationServiceProxy(sm, clientCredent);
2.实体赋值
注意,此方法只能用来赋值,不能用来取值
Entity entity = new Entity("salesorder", Guid.Parse("0745f62c-3acf-eb11-a13a-00505687c0be"));
entity["hms_so"] = "1000005748";//SO
entity["hms_sapstatus"] = "成功";//SAP状态
organizationService.Update(entity);
3.查询数据(使用方法查询、关联查询)
//先创建个返还申请明细的查询
QueryExpression queryExpression = new QueryExpression("hms_retrunrequestorderdetail");
//查询出全部列
queryExpression.ColumnSet = new ColumnSet(true);
//设置查询条件为固定ID的数据
//queryExpression.Criteria.AddCondition("hms_retrunrequestorderid", ConditionOperator.Equal, target.Id);
//关联上返还申请主表
var linkEntity1 = queryExpression.AddLink("hms_retrunrequestorder", "hms_retrunrequestorderid", "hms_retrunrequestorderid");
//判断主表状态为审批通过的
linkEntity1.LinkCriteria.AddCondition("hms_status", ConditionOperator.Equal, 40/*审批通过*/);
//查询出指定返还申请的所有明细
var result = organizationService.RetrieveMultiple(queryExpression);
//如果能查询到
if (result != null && result.Entities != null)
{
//获取查询处的返还申请明细实体集合
var returnRequestOrderDetails = result.Entities;
//循环该集合
foreach (var detail in returnRequestOrderDetails)
{
if (detail.GetAttributeValue<EntityReference>("hms_salesorderexecutedetailid") == null)
{
continue;
}
//获取返还申请明细中关联的物料领用申请执行明细ID
var salesOrderExecuteDetailId = detail.GetAttributeValue<EntityReference>("hms_salesorderexecutedetailid").Id;
//定义一个返还申请明细的查询
queryExpression = new QueryExpression("hms_retrunrequestorderdetail");
//查询出所有列
queryExpression.ColumnSet = new ColumnSet(true);
//按指定的物料领用执行明细查询
queryExpression.Criteria.AddCondition("hms_salesorderexecutedetailid", ConditionOperator.Equal, salesOrderExecuteDetailId);
//返还数量不为空的
queryExpression.Criteria.AddCondition("hms_count", ConditionOperator.NotNull);
//关联上返还申请主表通过主表id
var linkEntity = queryExpression.AddLink("hms_retrunrequestorder", "hms_retrunrequestorderid", "hms_retrunrequestorderid");
//判断主表状态为审批通过的
linkEntity.LinkCriteria.AddCondition("hms_status", ConditionOperator.Equal, 40/*审批通过*/);
//查询出所有数据
result = organizationService.RetrieveMultiple(queryExpression);
if (result != null && result.Entities != null && result.Entities.Count > 0)
{
//计算出此物料领用明细关联出的所有返还申请明细返还数量的和
var totalReturnCount = result.Entities.Sum(s => s.GetAttributeValue<decimal>("hms_count"));
// 定义一个物料领用申请执行明细实体
Entity materialRequisitionOrder = new Entity("hms_salesorderexecutedetail", salesOrderExecuteDetailId);
//更新他的实际返还数量
materialRequisitionOrder["hms_actualreturnquantity"] = totalReturnCount;
organizationService.Update(materialRequisitionOrder);
}
}
}
4.常用查询(查询单条、多条)
查询单条
Entity entity = service.Retrieve(ename, new Guid(eid), new ColumnSet(true));
查询多条
QueryExpression queryExpression = new QueryExpression()
{
EntityName = "hms_salesorderdetail",
ColumnSet = new ColumnSet(true)
};
queryExpression.Criteria.AddCondition("hms_stockplace", ConditionOperator.Null);
queryExpression.Criteria.AddCondition("hms_salesorderid", ConditionOperator.Equal, entity.Id);
var orderDetailList = service.RetrieveMultiple(queryExpression);
if (orderDetailList.Entities.Count > 0)
{
throw new InvalidPluginExecutionException("销售合同明细库存地点不能为空!");
}
5.使用fetch查询
5.1关联查询
var cancelApplyId = target.GetAttributeValue<EntityReference>("hms_cancelapplyid").Id;
var fetchXml = $@"
<fetch>
<entity name='hms_company'>
<attribute name='hms_sapfactoryname' />
<link-entity name='salesorder' from='hms_companyid' to='hms_companyid' link-type='inner'>
<link-entity name='hms_cancelapply' from='hms_salesorderid' to='salesorderid' link-type='inner'>
<filter>
<condition attribute='hms_cancelapplyid' operator='eq' value='{cancelApplyId}'/>
</filter>
</link-entity>
</link-entity>
</entity>
</fetch>";
FetchExpression fetchExpression = new FetchExpression(fetchXml);
var result = service.RetrieveMultiple(fetchExpression);
if (result != null && result.Entities != null && result.Entities.Count > 0)
{
var company = result.Entities[0];
target["hms_factory"] = company.GetAttributeValue<string>("hms_sapfactoryname");
}
5.2分组查询合并数量
var fetchXml = $@"
<fetch mapping='logical' aggregate='true' version='1.0'>
<entity name='hms_deliverydetail'>
<attribute name='hms_count' alias='sum_hms_count' aggregate='sum' />
<attribute name='hms_itemid' alias='group_itemid' groupby='true' />
<attribute name='hms_deliveryproductid' alias='group_deliveryproductid' groupby='true' />
<filter>
<condition attribute='hms_deliveryid' operator='eq' value='{image.Id}'/>
</filter>
</entity>
</fetch>";
FetchExpression fetchExpression = new FetchExpression(fetchXml);
var result = service.RetrieveMultiple(fetchExpression);
if (result != null && result.Entities != null && result.Entities.Count > 0)
{
lineCount = result.Entities.Count;
workflowRequestTableRecords = new WorkflowRequestTableRecord[lineCount];
int k = 0;
foreach (var sourceEntity in result.Entities)
{
workflowRequestTableField = new WorkflowRequestTableField[10];
i = 0;
//交货单
workflowRequestTableField[i] = GetTableFields(workflowRequestTableField, "jhd", i);
string deliveryproductname = ((EntityReference)((AliasedValue)sourceEntity.Attributes["group_deliveryproductid"]).Value).Name;
workflowRequestTableField[i].fieldValue = deliveryproductname;
i++;
//物料编号
workflowRequestTableField[i] = GetTableFields(workflowRequestTableField, "wlbm", i);
string itemname = ((EntityReference)((AliasedValue)sourceEntity.Attributes["group_itemid"]).Value).Name;
workflowRequestTableField[i].fieldValue = itemname;
i++;
//物料描述
workflowRequestTableField[i] = GetTableFields(workflowRequestTableField, "wlms", i);
Guid itemid = ((EntityReference)((AliasedValue)sourceEntity.Attributes["group_itemid"]).Value).Id;
workflowRequestTableField[i].fieldValue = GetOABussinessValue(itemid, "hms_item", "hms_itemdescription", service);
i++;
//合计数量
workflowRequestTableField[i] = GetTableFields(workflowRequestTableField, "slhj", i);
string coun = ((AliasedValue)sourceEntity.Attributes["sum_hms_count"]).Value.ToString();
workflowRequestTableField[i].fieldValue = coun;
workflowRequestTableRecords[k] = new WorkflowRequestTableRecord();
workflowRequestTableRecords[k].workflowRequestTableFields = workflowRequestTableField;
k++;
}
}
6.通过多条件过滤数据,匹配到的更新,否则新增
ExecuteMultipleRequest multipleReq = new ExecuteMultipleRequest()
{
Settings = new ExecuteMultipleSettings()
{
ContinueOnError = true,
ReturnResponses = true
},
Requests = new OrganizationRequestCollection()
};
Boolean failed = false;
//Insert data into CRM
if ((response.Subrc == 0) && zscrm009s.Length > 0)
{
for (int i = 0; i < zscrm009s.Length; i++)
{
//t052 payTerm = payTerms[i];
var soldToPart = zscrm009s[i];
var businessPartnerNumber = soldToPart.Kunnr;
if (businessPartnerNumber.Length == 10 && businessPartnerNumber.StartsWith("0000"))
{
businessPartnerNumber = businessPartnerNumber.Substring(4);
}
//售达方联合主键
KeyAttributeCollection keyCollect = new KeyAttributeCollection();
keyCollect.Add("hms_name", soldToPart.Kunnr); // SAP客户编码
keyCollect.Add("hms_salesorganizationnumber", soldToPart.Vkorg);// 销售组织编号
keyCollect.Add("hms_sapdistributionchannel", soldToPart.Vtweg);// 分销渠道
keyCollect.Add("hms_productgroup", soldToPart.Spart);// 产品组
Entity soldToParty = new Entity("hms_sapsoldtoparty", keyCollect);
// SAP客户编码
soldToParty["hms_name"] = soldToPart.Kunnr;
// 销售组织编号
soldToParty["hms_salesorganizationnumber"] = soldToPart.Vkorg;
// 分销渠道
soldToParty["hms_sapdistributionchannel"] = soldToPart.Vtweg;
// 产品组
soldToParty["hms_productgroup"] = soldToPart.Spart;
组织名称
soldToParty["hms_salesorganizationid"] = RetrieveSalesOrg(serviceProxy, soldToPart.Vkorg);
分销渠道
soldToParty["hms_distributionchannels"] = DistributionChannels(soldToPart.Vtweg);
合作伙伴功能
soldToParty["hms_partnerfunction"] = soldToPart.Parvw;
组织名称
soldToParty["hms_orgname"] = soldToPart.Name1;
//同步销售视图删除标识 20210810 yhx
string LoevmV = soldToPart.LoevmV;
soldToParty["hms_loevmv"] = string.IsNullOrEmpty(LoevmV) ? true : false;
//同步财务视图删除标识
string Loevm = soldToPart.Loevm;
soldToParty["hms_loevm"] = string.IsNullOrEmpty(Loevm) ? true : false;
UpsertRequest req = new UpsertRequest()
{
Target = soldToParty
};
multipleReq.Requests.Add(req);
if (multipleReq.Requests.Count >= 1000)
{
//Insert/Update payment term into CRM
mulresponse = (ExecuteMultipleResponse)serviceProxy.Execute(multipleReq);
if (mulresponse.IsFaulted || failed)
{
failed = true;
results[1] = "获取SAP售达方数据成功,更新至CRM时出错,请重试或联系系统管理员。";
}
else
{
results[1] = "获取SAP售达方数据成功并已同步至CRM售达方中。";
}
multipleReq.Requests.Clear();
}
}
if (multipleReq.Requests.Count > 0)
{
//Insert/Update payment term into CRM
mulresponse = (ExecuteMultipleResponse)serviceProxy.Execute(multipleReq);
if (mulresponse.IsFaulted || failed)
{
failed = true;
results[1] = "获取SAP售达方数据成功,更新至CRM时出错,请重试或联系系统管理员。";
}
else
{
results[1] = "获取SAP售达方数据成功并已同步至CRM售达方中。";
}
}
}
else
{
results[1] = "未获取到满足条件的SAP售达方数据。";
}
}
7.错误提示
throw new InvalidPluginExecutionException("非草稿或退回状态下不能删除");
8.共享数据
/// <summary>
/// 共享记录(读与写) 需要添加引用Microsoft.Crm.Sdk.proxy;
/// using Microsoft.Crm.Sdk.Messages;
/// </summary>
/// <param name="teamOrSystem">要共享给用户或者团队</param>
/// <param name="record">要共享的记录</param>
private static void Grant(IOrganizationService service, EntityReference teamOrSystemUser, EntityReference record)
{
GrantAccessRequest grantAccessRequest = new GrantAccessRequest
{
Target = record,
PrincipalAccess = new PrincipalAccess
{
Principal = teamOrSystemUser,
AccessMask = AccessRights.WriteAccess | AccessRights.ReadAccess |
}
};
service.Execute(grantAccessRequest);
}
//撤销共享
var revokeUserAccessReq = new RevokeAccessRequest
{
Revokee = new EntityReference("LogicalName",Guid),//需要撤销共享的团队
Target = new EntityReference("LogicalName", Guid),//需要撤销的目标实体
};
SysService.Execute(revokeUserAccessReq);
9.新增数据
查询单条
Entity entity = service.Retrieve(ename, new Guid(eid), new ColumnSet(true));
查询多条
QueryExpression queryExpression = new QueryExpression()
{
EntityName = "hms_salesorderdetail",
ColumnSet = new ColumnSet(true)
};
queryExpression.Criteria.AddCondition("hms_stockplace", ConditionOperator.Null);
queryExpression.Criteria.AddCondition("hms_salesorderid", ConditionOperator.Equal, entity.Id);
var orderDetailList = service.RetrieveMultiple(queryExpression);
if (orderDetailList.Entities.Count > 0)
{
throw new InvalidPluginExecutionException("销售合同明细库存地点不能为空!");
}
10.修改数据
string str = "D2B83152-EC20-EC11-A13C-00505687C0BE,DFDBB45A-EC20-EC11-A13C-00505687C0BE";
string[] arr = str.Split(',');
for (int i = 0; i < arr.Length; i++)
{
Entity entity = new Entity("hms_delivery", Guid.Parse(arr[i]));
entity["hms_tallystatus"] = new OptionSetValue(50);
entity["hms_deliverystatus"] = new OptionSetValue(50);
organizationService.Update(entity);
}
11.执行多条数据
//批量执行可以是新增、修改,或者判断没有就新增否则修改分别对应不同的Request
//CreateRequest、UpdateRequest、UpsertRequest
//值得注意的是UpsertRequest需要指定对比的key字段
//Entity deliveryProduct = new Entity("hms_deliveryproduct", "hms_name", sapDelivery.VBELN);
//如果是UpdateRequest那么要赋值id
ExecuteMultipleRequest multipleReq = new ExecuteMultipleRequest();
multipleReq = new ExecuteMultipleRequest()
{
Settings = new ExecuteMultipleSettings()
{
ContinueOnError = true,
ReturnResponses = true
},
Requests = new OrganizationRequestCollection()
};
foreach (var deliveryProduct in deliveryProductEntities.Entities)
{
Entity entity = new Entity("hms_deliveryproduct", deliveryProduct.Id);
entity["hms_isinsertdliverydata"] = true;
UpdateRequest req = new UpdateRequest()
{
Target = entity
};
multipleReq.Requests.Add(req);
}
//Insert/Update product into CRM
ExecuteMultipleResponse mulresponse = new ExecuteMultipleResponse();
try
{
mulresponse = (ExecuteMultipleResponse)serviceProxy.Execute(multipleReq);
}
catch (Exception ex)
{
results[1] = "更新交货单的交货标识字段失败:: " + ex.Message;
}
12.人员赋予角色
AssociateEntitiesRequest associateEntitiesRequest = new AssociateEntitiesRequest()
{
RelationshipName = "多对多关系名称"
};
associateEntitiesRequest.Moniker1 = new EntityReference("systemuser", new Guid(entityid));
associateEntitiesRequest.Moniker2 = new EntityReference("role", new Guid(item));
OrganizationService.Execute(associateEntitiesRequest);
13. 团队成员增删管理
//新增成员方法
public void AddUsersToTeam(IOrganizationService serviceadmin,EntityReference team, params EntityReference[] users)
{
var req = new AddMembersTeamRequest
{
TeamId = team.Id,
MemberIds = users.Select(x => x.Id).ToArray()
};
serviceadmin.Execute(req);
}
//删除成员方法
private void RemoveMember(IOrganizationService orgService, EntityReference team,Entity systemUser)
{
var request = new RemoveMembersTeamRequest
{
TeamId = team.Id,
MemberIds = new[] { systemUser.Id }
};
orgService.Execute(request);
}
数据库
1.获取表单下拉框选项值的Text
CREATE FUNCTION [dbo].[fn_GetOptionSetValueName]
(
@entity_name nvarchar(50),
@colume_name nvarchar(50),
@attributevalue int
)
RETURNS varchar(50)
AS
BEGIN;
declare @return_value varchar(100);
SET @return_value =
(
SELECT Value
FROM dbo.StringMap
WHERE AttributeName = @colume_name
and AttributeValue = @attributevalue
AND ObjectTypeCode =
(
SELECT distinct ObjectTypeCode
FROM MetadataSchema.Entity
WHERE Name = @entity_name
)
);
RETURN @return_value;
END
系统运维
1.设置系统登录超时时间
Get-ADFSRelyingPartyTrust
Set-ADFSRelyingPartyTrust -Targetname "CRM IFD Replaying Party" -TokenLifetime 1440
2.在登录页添加修改密码
参考以下两个,注意ADFS的地址,不是系统的地址端口
Dynamics CRM修改密码界面_dynimiccrm修改密码-CSDN博客
3.登录页面的自定义,如隐藏Logo等
AD FS 用户登录自定义 | Microsoft Learn
4.其他
ADFS 3.0登录页面不用输入域名的实现方法_adfs 域名 免-CSDN博客
工具使用
1.下载地址
常用的工具有开发工具和调试工具
开发工具 plugin工具下载地址
Walkthrough: Register a plug-in using the plug-in registration tool | Microsoft Docs
调试工具有以下两种,需要从谷歌市场中下载(需要翻墙)
按钮开发工具为Ribbon Workbench
Develop 1 Ltd | Ribbon Workbench for Dynamics 365 & Dynamics CRM
2.Plugin监听执行顺序
PreValidation 数据未发生变化之前
PreOperation 数据未发生变化之前
PostOperation 数据发生变化之后,此时使用组织服务查询数据得到的是变化后的数据,删除操作在此阶段无法查询到数据
每个阶段之间不会互相影响,即PreValidation中执行的操作即使PreOperation中报错也会生效,但是同一个实体在不同的Step的同一个事件中,只要有一个Step报错其他Step中的操作就会回滚
相同的事件,可以通过 Excution Order来设置执行的顺序
3.Plugin监听事件Message
Create 创建
Update 更新
Delete 删除
Assign 分派
GrantAccess 共享
ModifyAccess 修改共享权限
RevokeAccess 移除共享
分派会触发Assign和Update(如果设置了监听ownerid字段)
开发步骤
- 创建实体
- 新建字段
- 新建窗体
- 新建js
- 注册按钮
- 新建类库
- 在VS中安装
D365 Developer Extensions扩展
- 在VS中安装nuget工具Microsoft.CrmSdk.CoreAssemblies
- 新建CS文件
- 注册Assembly 注意需要给类库新增签名hms.snk否则会在创建时报错
- 在窗体中引用js需要主要的事
注意事项
1.在用rest查询数据时,一定注意实体名要加s,id字段要写成_idfield_value的样式
字段联动开发逻辑
fun1
可编辑字段赋值
fun2
显示控制
fun3
不可编辑字段赋值
//所有表单打开控制字段显示隐藏
fun2
//复制单据,第一次打开单据控制,仅用于复制单据有字段联动触发存在可编辑字段带出值为最新
formtype!=1&&((orderStatuts == 10 || orderStatuts == 60) && hms_createtype == 2 && hms_iffirstopen)
fun1
//字段联动存在不可编辑字段赋值,若希望草稿状态单据打开时保持带出字段信息最新
status==10 or 60
fun3
//字段change事件所有方法都触发
fieldchange(changefun)
如果不需要带出最新数据,只需要写两个方法,一个是字段控制显示逻辑,一个是控制字段赋值逻辑
changefun(){
fun1
fun2
fun3
}