服务端的TigerApi 框架,基于.NET6 2024 版本
Rodney Chen
2025-03-10 40df5d91f800bb8b7be2638c13b4f9292d461221
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
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
using Rhea.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tiger.Business.WMS.Transaction;
using Tiger.IBusiness;
using Tiger.Model;
 
namespace Tiger.Business.WMS.Common
{
    /// <summary>
    /// 备料单发料事务
    /// </summary>
    public class Preparation : WMSTransactionBase, IPreparation
    {
        #region Propertys & Variables
        public string UserCode { get; set; }
        public long UserId { get; set; }
        public string OrgCode { get; set; }
        private DbClient _MainDB;
        public DbClient MainDB => _MainDB;
        private DbClient CommitDB;
        public Inventory CurInvItem { get; set; }
        public ScanShelfInfo CurScanShelf { get; set; }
        /// <summary>
        /// 跟客户端通讯时的指令,有具体功能定义,默认为Normal
        /// </summary>
        public string Command { get; set; } = "Normal";
        /// <summary>
        /// 是否需要临时存储数据库提交操作,待需要的时候再提交
        /// </summary>
        public bool NeedTemporaryStoreDBCommitAction { get; set; } = false;
        protected Dictionary<string, List<Action>> DBCommitList { get; set; } = new();
        #endregion Propertys & Variables
 
        #region Functions
        public IPreparation Init(string id, string userCode, string apiHost, string orgCode)
        {
            TransID = id;
            UserCode = userCode;
            ApiHost = apiHost;
            OrgCode = orgCode;
            _MainDB = Biz.Db;
 
            return this;
        }
 
        /// <summary>
        /// 获取提交数据的DbClient对象
        /// </summary>
        /// <returns></returns>
        public DbClient GetCommitDB()
        {
            return CommitDB ??= Biz.Db;
        }
 
        /// <summary>
        /// 增加暂存的数据库操作
        /// </summary>
        /// <param name="groupName">暂存的分组</param>
        /// <param name="action">暂存的数据库操作</param>
        public void AddCommitAction(string group, Action action)
        {
            //增加附加的保存内容
            if (!action.IsNullOrEmpty())
            {
                if (!DBCommitList.ContainsKey(group))
                {
                    DBCommitList.Add(group, new List<Action>());
                }
                var commitList = DBCommitList[group];
                commitList.Add(action);
            }
        }
 
        /// <summary>
        /// 暂存的数据库操作提交到数据库
        /// </summary>
        /// <param name="appendToSave">附加的保存内容</param>
        public void SaveCommitListToDB(Action appendToSave = null)
        {
            //增加附加的保存内容
            if (!appendToSave.IsNullOrEmpty())
            {
                if (!DBCommitList.ContainsKey("AppendSaveAction"))
                {
                    DBCommitList.Add("AppendSaveAction", new List<Action>());
                }
                var appendList = DBCommitList["AppendSaveAction"];
                appendList.Add(appendToSave);
            }
 
            //如果不需要临时存储数据库提交操作,则把提交操作列表提交到数据库
            if (!NeedTemporaryStoreDBCommitAction)
            {
                //恢复临时存储标记为false
                NeedTemporaryStoreDBCommitAction = false;
 
                var dbTran = GetCommitDB().UseTran(() =>
                {
                    //在同一个事务中保存所有工步的数据
                    foreach (var wipSn in DBCommitList.Keys.Where(q => q != "AppendSaveAction"))
                    {
                        foreach (var action in DBCommitList[wipSn])
                        {
                            action.Invoke();
                        }
                    }
                    //附加的保存内容
                    if (DBCommitList.ContainsKey("AppendSaveAction"))
                    {
                        foreach (var action in DBCommitList["AppendSaveAction"])
                        {
                            action.Invoke();
                        }
                    }
                });
                if (dbTran.IsSuccess)
                {
                    //保存成功则清空提交操作列表
                    DBCommitList.Clear();
                }
                else
                {
                    //抛出异常
                    throw dbTran.ErrorException;
                }
            }
        }
 
        /// <summary>
        /// 上架
        /// </summary>
        /// <param name="inventory">要上架的库存对象</param>
        /// <param name="option">授权查询选项</param>
        /// <param name="targetLocation">要上架的储位代码</param>
        /// <param name="isTransfer">是否移库操作</param>
        /// <returns></returns>
        public Result PutOn(AuthOption option, string targetLocation)
        {
            var result = new Result(Result.Flags.Success);
            try
            {
                var location = Biz.Db.Queryable<V_WH_UNIT>().Where(q => q.LOCATION_CODE == targetLocation && q.AUTH_ORG == option.CurOrg).IncludesAllFirstLayer().First();
                if (!location.IsNullOrEmpty())
                {
                    var isTransfer = CurInvItem.Location.LOCATION_CODE != location.LOCATION_CODE;
                    foreach (var item in CurInvItem.Items)
                    {
                        item.STATUS = WMS_ITEM.STATUSs.InStore.GetValue();
                        item.SUPP_LOTNO = CurInvItem.Barcode.LotNo;
                        item.FIRST_IN_DATE = item.FIRST_IN_DATE <= DateTime.MinValue ? DateTime.Now : item.FIRST_IN_DATE;
                        item.PROD_DATE = item.PROD_DATE <= DateTime.MinValue ? item.FIRST_IN_DATE : item.PROD_DATE;
                        item.WH_ID = location.WH_ID;
                        item.REGION_ID = location.REGION_ID;
                        item.SHELF_ID = location.SHELF_ID;
                        item.LOCATION_ID = location.LOCATION_ID;
                        CurInvItem.History.Add(new WMS_ITEM_HIS(item, $"条码[{CurInvItem.SN}]{(isTransfer ? $"从储位[{CurInvItem?.Location?.LOCATION_CODE}]移库" : "上架")}到储位[{location.LOCATION_CODE}]成功{(isTransfer ? "" : $",操作单据[{item.TRANS_NO}]")}"));
                    }
                    foreach (var item in CurInvItem.Packages)
                    {
                        item.WH_ID = location.WH_ID;
                        item.REGION_ID = location.REGION_ID;
                        item.SHELF_ID = location.SHELF_ID;
                        item.LOCATION_ID = location.LOCATION_ID;
                    }
                    foreach (var item in CurInvItem.ItemsExt)
                    {
                        item.AUTH_ORG = option.OrgCode;
                        item.SN = CurInvItem.Barcode.SN;
                    }
                    //更新储存信息
                    CurInvItem.Warehouse = location.Warehouse;
                    CurInvItem.Region = location.Region;
                    CurInvItem.Shelf = location.Shelf;
                    CurInvItem.Location = location.Location;
 
                    //创建变量克隆对象用于传入DBSubmitAction中保存当前需要暂存的数据值
                    var _Items = CurInvItem.Items.Clone();
                    var _Packages = CurInvItem.Packages.Clone();
                    var _History = CurInvItem.History.Clone();
                    var _ItemsExt = CurInvItem.ItemsExt.Clone();
                    AddCommitAction("PutOn", () =>
                    {
                        //使用统一的事务DB对象
                        var db = GetCommitDB();
                        //数据保存逻辑
                        db.Storageable(_Items, UserCode).ExecuteCommand();
                        db.Storageable(_Packages, UserCode).ExecuteCommand();
                        db.Insertable(_History, UserCode).ExecuteCommand();
                        var x = db.Storageable(_ItemsExt, UserCode).ToStorage();
                        x.AsInsertable.ExecuteCommand();//不存在插入
                        x.AsUpdateable.ExecuteCommand();//存在更新
                    });
                }
                else
                {
                    result.Flag = Result.Flags.Failed;
                    result.LocaleMsg = new("WMS.WmsItem.PutOn.LocationNotExists", targetLocation);
                }
            }
            catch (Exception ex)
            {
                result.CatchExceptionWithLog(ex, Biz.L("WMS.WmsItem.PutOn.Exception", CurInvItem.SN, targetLocation));
            }
            return result;
        }
 
        /// <summary>
        /// 下架
        /// </summary>
        /// <param name="option">授权查询选项</param>
        /// <param name="status">下架后状态</param>
        /// <param name="clearLocation">是否清理储区货架储位信息</param>
        /// <returns></returns>
        public Result TakeDown(AuthOption option, WMS_ITEM.STATUSs status)
        {
            return TakeDown(CurInvItem.Items.ToDictionary(k => k.SN, v => v.QTY), option, status);
        }
 
        /// <summary>
        /// 下架
        /// </summary>
        /// <param name="inventory">要下架的库存对象</param>
        /// <param name="qtyList">要下架的最小包装数量字典,key:sn,value:qty</param>
        /// <param name="option">授权查询选项</param>
        /// <param name="status">下架后状态</param>
        /// <param name="clearLocation">是否清理储区货架储位信息</param>
        /// <returns></returns>
        public Result TakeDown(Dictionary<string, double> qtyList, AuthOption option, WMS_ITEM.STATUSs status)
        {
            var result = new Result(Result.Flags.Success);
            try
            {
                //如果要下架的数量字典为空则认为是全部下架
                qtyList = qtyList.IsNullOrEmpty(CurInvItem.Items.ToDictionary(k => k.SN, v => v.QTY));
 
                foreach (var item in CurInvItem.Items)
                {
                    if (qtyList.ContainsKey(item.SN) && qtyList[item.SN] > 0)
                    {
                        var downQty = qtyList[item.SN];
                        if (item.QTY > downQty)
                        {
                            item.QTY -= downQty;
                            var pkg = CurInvItem.Packages.First(q => q.SN == item.SN);
                            pkg.QTY = item.QTY;
                        }
                        else
                        {
                            item.STATUS = status.GetValue();
                            var pkg = CurInvItem.Packages.First(q => q.SN == item.SN);
                            pkg.PARENT_SN = null;
                            pkg.Parent = null;
                            //如果下架数量等于库存数量则清理储区货架储位信息,否则保留仓库信息
                            //item.WH_ID = null;
                            item.REGION_ID = null;
                            item.SHELF_ID = null;
                            item.LOCATION_ID = null;
                            //pkg.WH_ID = null;
                            pkg.REGION_ID = null;
                            pkg.SHELF_ID = null;
                            pkg.LOCATION_ID = null;
                        }
                        CurInvItem.History.Add(new WMS_ITEM_HIS(item, $"条码[{CurInvItem.SN}]从储位[{CurInvItem?.Location?.LOCATION_CODE}]下架数量[{downQty}]成功,状态[{item.STATUS.GetEnumDesc<WMS_ITEM.STATUSs>()}],操作单据[{item.TRANS_NO}]"));
                    }
                }
                CurInvItem.Packages = WMS_ITEM_PKG.UpdateQty(CurInvItem.Packages);
 
                //创建变量克隆对象用于传入DBSubmitAction中保存当前需要暂存的数据值
                var _Items = CurInvItem.Items.Clone();
                var _Packages = CurInvItem.Packages.Clone();
                var _History = CurInvItem.History.Clone();
                AddCommitAction("TakeDown", () =>
                {
                    //使用统一的事务DB对象
                    var db = GetCommitDB();
                    //数据保存逻辑
                    db.Updateable(_Items, UserCode).ExecuteCommand();
                    db.Insertable(_History, UserCode).ExecuteCommand();
                    db.Updateable(_Packages, UserCode).ExecuteCommand();
                });
            }
            catch (Exception ex)
            {
                result.CatchExceptionWithLog(ex, Biz.L("WMS.WmsItem.TakeDown.Exception", CurInvItem.SN, CurInvItem?.Location?.LOCATION_CODE));
            }
            return result;
        }
 
        #endregion Functions
 
        public override bool Close(bool needSaveHistoryLog = false)
        {
            //needSaveHistoryLog = true;
            //保存操作日志
 
            this.IsFinished = true;
            return IsFinished ? base.Close(needSaveHistoryLog) : IsFinished;
        }
    }
}