王 垚
2021-11-12 0ce538e3c3dc01153ce1bfc2d75276881206c222
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
using System;
using System.Collections.Generic;
using Kingdee.BOS.Util;
using Kingdee.BOS.Core.Metadata;
using Kingdee.BOS.Core.Metadata.EntityElement;
using Kingdee.BOS.Core.DynamicForm.PlugIn;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.Contracts;
using Kingdee.BOS.App;
using Kingdee.BOS.Core.Metadata.FieldElement;
using System.ComponentModel;
using Kingdee.BOS.ServiceHelper;
using Kingdee.K3.SCM.App;
 
namespace Demo.BillView.PRD
{
    /// <summary>
    /// 日计划工单下推后,建立生产汇报单与生产订单的关联关系
    /// </summary>
    /// <remarks>
    /// 要求:
    /// 1. 需要引入单据体的源单类型、源单编号字段
    /// 2. 本插件挂在直接调拨单的保存操作上
    /// 生产汇报单关联生产订单
    /// </remarks>
    [Description("日计划工单下推后,建立生产汇报单与生产订单的关联关系")]
    [HotUpdate]
    public class Pro_DayPlanPushSCHB : AbstractOperationServicePlugIn
    {
        public override void OnPreparePropertys(PreparePropertysEventArgs e)
        {
            base.OnPreparePropertys(e);
            e.FieldKeys.Add("FSrcBillType");
            e.FieldKeys.Add("FSrcBillNo");
            e.FieldKeys.Add("FID");
            e.FieldKeys.Add("FTreeEntity_FEntryID");
            e.FieldKeys.Add("FBillNo");
            e.FieldKeys.Add("FBFLowId");
            e.FieldKeys.Add("FMaterialId");
            e.FieldKeys.Add("FBaseUnitQty");
            e.FieldKeys.Add("FBaseJoinQty");
        }
        private const string POFormId = "PRD_MO";
        private List<string> FentryIdList = new List<string>();
        public override void BeforeExecuteOperationTransaction(BeforeExecuteOperationTransaction e)
        {
            base.BeforeExecuteOperationTransaction(e);
            HashSet<string> poBillNos = new HashSet<string>();
            Entity entity = this.BusinessInfo.GetEntity("FEntity");//获取明细信息
            Entity linkEntry = this.BusinessInfo.GetEntity("FEntity_Link");
            Field fldSrcFormId = this.BusinessInfo.GetField("FSrcBillType");
            Field fldSrcBillNo = this.BusinessInfo.GetField("FSrcBillNo");
            // 对单据体进行循环,取关联的源单编号
            foreach (var billObj in e.SelectedRows)
            {
                DynamicObjectCollection entryRows = entity.DynamicProperty.GetValue(billObj.DataEntity)
                            as DynamicObjectCollection;
                foreach (var entryRow in entryRows)
                {
                    //生产用料清单为空时
                    if (Convert.ToString(entryRow["FDayPlanBillNo"]) == "")
                        continue;
                    string srcFormId = "";
                    string srcSrcBillNo = "";
                    string FPPBOMFENTRYID = "";
 
                    srcFormId = fldSrcFormId.DynamicProperty.GetValue<string>(entryRow);
                    srcSrcBillNo = fldSrcBillNo.DynamicProperty.GetValue<string>(entryRow);
                    //srcFormId = "PRD_MO";
                    //srcSrcBillNo = entryRow["FPPBOMBILLNO"]?.ToString();
                    //string FPPBOMFID = entryRow["FPPOMFID"]?.ToString();
                    //FPPBOMFENTRYID = entryRow["FPPBOMFENTRYID"]?.ToString();
 
                    if (string.IsNullOrWhiteSpace(srcFormId)
                        || string.IsNullOrWhiteSpace(srcSrcBillNo)
                        )
                    {// 源单不是采购订单,略过
                        continue;
                    }
                    // 源单编号已经登记,不再重复记录,略过
                    if (poBillNos.Contains(srcSrcBillNo)) continue;
                    // Link已经记录了源单信息,略过
                    //DynamicObjectCollection linkRows = linkEntry.DynamicProperty.GetValue(entryRow)
                    //        as DynamicObjectCollection;
                    //if (linkRows.Count > 0) continue;
                    bool Ret = SourceVerification(Convert.ToString(entryRow["Id"]));
                    if (!Ret) continue;
 
                    poBillNos.Add(srcSrcBillNo);
                }
            }
            if (poBillNos.Count == 0) return;
            DynamicObject[] poObjs = this.LoadPurchaseOrder(poBillNos);
            if (poObjs == null || poObjs.Length == 0) return;
            Dictionary<string, Dictionary<string, DynamicObject>> dctAllBills = this.BuildDictionary(poObjs);
            string srcTableNumber = this.GetPOEntryTableNumber();
            List<DynamicObject> allNewLinkRows = new List<DynamicObject>();
            // 循环单据体,为单据体,建立起源单关联信息:
            foreach (var billObj in e.SelectedRows)
            {
                DynamicObjectCollection entryRows = entity.DynamicProperty.GetValue(billObj.DataEntity)
                            as DynamicObjectCollection;
                foreach (var entryRow in entryRows)
                {
                    string srcFormId = fldSrcFormId.DynamicProperty.GetValue<string>(entryRow);
                    string srcSrcBillNo = fldSrcBillNo.DynamicProperty.GetValue<string>(entryRow);
                    //  srcFormId = "PRD_PPBOM";
                    //  srcSrcBillNo = entryRow["FPPBOMBILLNO"]?.ToString();
                    //string FPPBOMFID = entryRow["FPPOMFID"]?.ToString();
                    //string FPPBOMFENTRYID = entryRow["FPPBOMFENTRYID"]?.ToString();
 
                    if (string.IsNullOrWhiteSpace(srcFormId)
                        || string.IsNullOrWhiteSpace(srcSrcBillNo)
                      )
                    {// 源单不是销售订单,略过
                        continue;
                    }
                    Dictionary<string, DynamicObject> dctOneBill = null;
                    if (dctAllBills.TryGetValue(srcSrcBillNo, out dctOneBill) == false) continue;
                    DynamicObject materialObj = entryRow["MaterialId"] as DynamicObject;
                    if (materialObj == null) continue;
                    string materialNumber = Convert.ToString(materialObj["number"]);
                    DynamicObject srcRow = null;
                    if (dctOneBill.TryGetValue(materialNumber, out srcRow) == false) continue;
                    // Link已经记录了源单信息,略过
                    bool Ret = SourceVerification(Convert.ToString(entryRow["Id"]));
                    if (!Ret) continue;
 
                    //记录源单ID 用于更新
                    if (!FentryIdList.Contains(entryRow["Id"]?.ToString()))
                        FentryIdList.Add(entryRow["Id"]?.ToString());
 
                    DynamicObjectCollection linkRows = linkEntry.DynamicProperty.GetValue(entryRow)
                            as DynamicObjectCollection;
                    DynamicObject linkRow = new DynamicObject(linkEntry.DynamicObjectType);
                    linkRow["STableName"] = srcTableNumber;
                    this.FillLinkRow(srcRow, entryRow, linkRow);
                    linkRows.Add(linkRow);
                    allNewLinkRows.Add(linkRow);
                }
            }
            // 为新建的源单关联信息,设置内码
            IDBService dbService = Kingdee.K3.SCM.App.ServiceHelper.GetService<IDBService>();
            dbService.AutoSetPrimaryKey(this.Context, allNewLinkRows.ToArray(), linkEntry.DynamicObjectType);
        }
 
        //       /// <summary>
        //       /// 保存操作关联关系写入完成后 更改源单信息
        //       /// </summary>
        //       /// <param name="e"></param>
        //       public override void AfterExecuteOperationTransaction(AfterExecuteOperationTransaction e)
        //       {
        //           base.AfterExecuteOperationTransaction(e);
        //           //更改LK表信息 以及 源单关联信息
        //           List<string> sqlList = new List<string>();
        //           string sql = "";
        //           if (FentryIdList.Count > 0)
        //           {
        //               string FentryId = string.Join(",", FentryIdList.ToArray());
        //  //             sql = string.Format(@"/*dialect*/
        //  //update a set FBASEQTY = FQTY
        //  //from T_STK_STKTRANSFERINENTRY_LK a
        //  //join T_STK_STKTRANSFERINENTRY b on a.FENTRYID = b.FENTRYID
        //  //where 
        //  //--a.FSTABLENAME = 'T_PRD_PPBOMENTRY' and
        //  //a.FENTRYID in ({0})", FentryId);
        //  //             sqlList.Add(sql);
        //               sql = string.Format(@"/*dialect*/update T_STK_STKTRANSFERINENTRY_R 
        //set FSrcBillTypeId = 'PRD_PPBOM',FSRCBILLNO=b.FPPBOMBILLNO
        //,FTRANSRESERVELINK=1
        //from T_STK_STKTRANSFERINENTRY_R a 
        //join T_STK_STKTRANSFERINENTRY b on a.FENTRYID=b.FENTRYID
        //where a.FENTRYID in({0})", FentryId);
        //               sqlList.Add(sql);
        //               DBServiceHelper.ExecuteBatch(Context, sqlList);
        //           }
 
        //       }
        /// <summary>
        /// 加载相关的生产订单信息
        /// </summary>
        /// <param name="poBillNos"></param>
        /// <returns></returns>
        private DynamicObject[] LoadPurchaseOrder(HashSet<string> poBillNos)
        {
            IViewService viewService = Kingdee.K3.SCM.App.ServiceHelper.GetService<IViewService>();
            string formId = "PRD_MO";
 
            // 指定需要加载的用料清单字段
            List<SelectorItemInfo> fields = new List<SelectorItemInfo>();
            fields.Add(new SelectorItemInfo("FID"));// 单据主键
            fields.Add(new SelectorItemInfo("FTreeEntity_FEntryID"));// 单据体主键
            fields.Add(new SelectorItemInfo("FBillNo"));// 单据编号
            fields.Add(new SelectorItemInfo("FBFLowId"));// 业务流程
            fields.Add(new SelectorItemInfo("FMaterialId"));// 物料
            fields.Add(new SelectorItemInfo("FBaseUnitQty"));//基本单位数量
            fields.Add(new SelectorItemInfo("FBFLOWID"));//业务流程 
 
            // 指定过滤条件
            string filter = string.Format(" FBillNo IN ('{0}') ", string.Join("','", poBillNos));
            OQLFilter ofilter = OQLFilter.CreateHeadEntityFilter(filter);
            var objs = viewService.Load(this.Context, formId, fields, ofilter);
            return objs;
        }
        /// <summary>
        /// 把生产订单单据体行构建为字典:Dictionary(单据编号, Dictionary(物料编码, 源单行));
        /// </summary>
        /// <param name="poObjs"></param>
        /// <returns></returns>
        private Dictionary<string, Dictionary<string, DynamicObject>> BuildDictionary(DynamicObject[] poObjs)
        {
            Dictionary<string, Dictionary<string, DynamicObject>> dctAllBills =
                new Dictionary<string, Dictionary<string, DynamicObject>>();
            foreach (var poObj in poObjs)
            {
                string billNo = Convert.ToString(poObj["BillNo"]);
                Dictionary<string, DynamicObject> dctOneBill = new Dictionary<string, DynamicObject>();
                DynamicObjectCollection entryRows = poObj["TreeEntity"] as DynamicObjectCollection;
                foreach (var entryRow in entryRows)
                {
                    DynamicObject materialObj = entryRow["MaterialId"] as DynamicObject;
                    if (materialObj == null) continue;
                    string materialNumber = Convert.ToString(materialObj["number"]);
                    dctOneBill[materialNumber] = entryRow;
                }
                dctAllBills.Add(billNo, dctOneBill);
            }
            return dctAllBills;
        }
        /// <summary>
        /// 获取用料清单关联主实体表格编码
        /// </summary>
        /// <returns></returns>
        private string GetPOEntryTableNumber()
        {
            IBusinessFlowService bfMetaService = Kingdee.K3.SCM.App.ServiceHelper.GetService<IBusinessFlowService>();
            var tableDefine = bfMetaService.LoadTableDefine(this.Context, POFormId, "FTreeEntity");
            return tableDefine.TableNumber;
        }
        /// <summary>
        /// 填写源单信息
        /// </summary>
        /// <param name="srcRow">源单行</param>
        /// <param name="toRow">目标单行</param>
        /// <param name="linkRow">关联行</param>
        private void FillLinkRow(DynamicObject srcRow, DynamicObject toRow, DynamicObject linkRow)
        {
            //剩余调拨数量 (基本单位数量 - 基本单位汇报选单数量)
            decimal remainQty = DBServiceHelper.ExecuteScalar<decimal>(Context, $"select FBASEUNITQTY -isnull(FRepQuaSelQty,0) from  T_PRD_MOENTRY t1  left join  T_PRD_MOENTRY_A t2 on t1.FENTRYID = t2.FENTRYID where t1.FENTRYID={srcRow["Id"]?.ToString()}", 0);
            linkRow["FlowId"] = srcRow["BFLowId_Id"];
            linkRow["FlowLineId"] = 13;
            linkRow["RuleId"] = "PRD_PPBOM-STK_TransferDirect";
            linkRow["SBillId"] = ((DynamicObject)srcRow.Parent)[0];
            linkRow["SId"] = srcRow[0];
            // 原始携带量
            linkRow["BASEQUAQTY"] = remainQty;//剩余汇报数量
            linkRow["BASEQUAQTYOLD"] = toRow["FinishQty"]; //本次汇报数量(基本单位完成数量)
        }
 
        /// <summary>
        /// 验证是否生成过生产订单对应的源单
        /// </summary>
        /// <returns></returns>
        public bool SourceVerification(string FTID)
        {
            string sql = $" select count(*) from T_BF_INSTANCEENTRY where FSTABLENAME= 'T_PRD_MOENTRY' and FTTABLENAME = 'T_PRD_MORPTENTRY' and FTID = '{FTID}'";
            int count = DBServiceHelper.ExecuteScalar<int>(Context, sql, 0);
            if (count == 0)
                return true;
            else
                return false;
        }
 
    }
}