From 5ce969ed34e91c931cce38e2feb5d2c208633a96 Mon Sep 17 00:00:00 2001
From: chengsc <Demo@DESKTOP-CPA90BF>
Date: 星期日, 03 十一月 2024 18:34:53 +0800
Subject: [PATCH] 修改问题
---
Wms/WMS.BLL/BllSoServer/ExportNoticeServer.cs | 322 ++++++++++++++++++++++++++++++++---------------------
1 files changed, 192 insertions(+), 130 deletions(-)
diff --git a/Wms/WMS.BLL/BllSoServer/ExportNoticeServer.cs b/Wms/WMS.BLL/BllSoServer/ExportNoticeServer.cs
index f671968..1a22d15 100644
--- a/Wms/WMS.BLL/BllSoServer/ExportNoticeServer.cs
+++ b/Wms/WMS.BLL/BllSoServer/ExportNoticeServer.cs
@@ -41,7 +41,7 @@
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
- public bool ErpAddExportNotice(SoInfo model)
+ public void HttpAddExportNotice(SoInfo model)
{
try
{
@@ -226,7 +226,7 @@
SONo = billNo,
Type = model.SoType,
Status = "0",
- Origin = "WMS",
+ Origin = model.Origin,
CustomerNo = model.Customer,
CustomerName = customer.CustomerName,
LogisticsId = logisticsId,
@@ -242,12 +242,10 @@
if (n <= 0 || m <= 0)
{
- Db.RollbackTran();
- return false;
+ throw new Exception("鍏ュ簱鍗曟垨鏄庣粏娣诲姞淇濆瓨澶辫触");
}
Db.CommitTran();
- return true;
-
+
}
catch (Exception ex)
{
@@ -259,16 +257,27 @@
}
catch (Exception ex)
{
- Db.RollbackTran();
throw new Exception(ex.Message);
}
}
//鍥炰紶鍑哄簱鍗�
- public bool FinishSo(int id, string url, int userId)
+ public bool FinishSo(int id, string url, string userNo, string pwd, int userId)
{
try
{
+ var loginPwd = Md5Tools.CalcMd5(pwd);
+ var date = Db.Queryable<SysUserInfor>().First(m => m.IsDel == "0" && m.UserName == userNo && m.PassWord == loginPwd);
+
+ if (date == null) //璐﹀彿瀵嗙爜鏄惁姝g‘
+ {
+ throw new Exception("璐﹀彿瀵嗙爜涓嶆纭垨娌℃湁姝よ处鍙�");
+ }
+ if (date.Status != "0") //褰撳墠璐﹀彿鏄惁姝e父鍚敤
+ {
+ throw new Exception("褰撳墠璐﹀彿闈炲惎鐢ㄧ姸鎬�");
+ }
+
var notice = Db.Queryable<BllExportNotice>().First(m => m.Id == id && m.IsDel == "0");
if (notice == null)
{
@@ -283,7 +292,7 @@
{
throw new Exception("鏈煡璇㈠埌鍗曟嵁鏄庣粏淇℃伅");
}
- if (userId == notice.UpdateUser)
+ if (date.Id == notice.UpdateUser)
{
throw new Exception("澶嶆牳澶辫触锛屽鏍镐汉鍛樺拰鍏抽棴璁㈠崟浜哄憳涓嶈兘鐩稿悓锛�");
}
@@ -318,10 +327,10 @@
notice.Status = "6";
notice.CheckTime = DateTime.Now;
- notice.CheckUser = userId;
+ notice.CheckUser = date.Id;
Db.Updateable(notice).ExecuteCommand();
- new OperationSOServer().AddLogOperationSo("鍑哄簱浣滀笟", "鍑哄簱鍗曟嵁", notice.SONo, "澶嶆牳", $"澶嶆牳浜嗗崟鎹彿涓簕notice.SONo}鐨勫崟鎹俊鎭�", userId);
+ new OperationSOServer().AddLogOperationSo("鍑哄簱浣滀笟", "鍑哄簱鍗曟嵁", notice.SONo, "澶嶆牳", $"{date.RealName}澶嶆牳浜嗗崟鎹彿涓簕notice.SONo}鐨勫崟鎹俊鎭�", userId);
return true;
}
catch (Exception e)
@@ -363,31 +372,31 @@
.LeftJoin<SysUserInfor>((a, b, c, d, e) => a.CheckUser == e.Id)
.Select((a, b, c, d, e) => new ExportNoticeDto()
{
- Id = a.Id,
- SONo = a.SONo,
- Type = a.Type,
- Status = a.Status,
- Origin = a.Origin,
- CustomerNo = a.CustomerNo,
- CustomerName = a.CustomerName,
- LotNo = a.LotNo,
- LotText = a.LotText,
- SupplierLot = a.SupplierLot,
- LogisticsId = a.LogisticsId,
+ //Id = a.Id,
+ //SONo = a.SONo,
+ //Type = a.Type,
+ //Status = a.Status,
+ //Origin = a.Origin,
+ //CustomerNo = a.CustomerNo,
+ //CustomerName = a.CustomerName,
+ //LotNo = a.LotNo,
+ //LotText = a.LotText,
+ //SupplierLot = a.SupplierLot,
+ //LogisticsId = a.LogisticsId,
LogisticsName = b.CarrierName,
- IsWave = a.IsWave,
- WaveNo = a.WaveNo,
- IsDespatch = a.IsDespatch,
- Demo = a.Demo,
+ //IsWave = a.IsWave,
+ //WaveNo = a.WaveNo,
+ //IsDespatch = a.IsDespatch,
+ //Demo = a.Demo,
CreateUserName = c.RealName,
UpdateUserName = c.RealName,
- CreateTime = a.CreateTime,
- UpdateTime = a.UpdateTime,
+ //CreateTime = a.CreateTime,
+ //UpdateTime = a.UpdateTime,
CheckUserName = e.RealName,
- CheckTime = a.CheckTime
- })
+ //CheckTime = a.CheckTime
+ },true)
.OrderByDescending(a => a.CreateTime)
.ToOffsetPage(page, limit, ref total);
count = total;
@@ -436,7 +445,7 @@
inspectStatus = "0";
break;
case "4"://涓嶅悎鏍煎搧鍑哄簱
- skuType = "(0,1,2,3)";
+ skuType = "(0,1,2,3,4)";
inspectStatus = "2";
break;
case "5"://涓棿鍝佸嚭搴�
@@ -444,8 +453,8 @@
inspectStatus = "0,1";
break;
case "6"://浠e偍鍑哄簱
- skuType = "(0,1,2,3)";
- inspectStatus = "0,1";
+ skuType = "(0,1,2,3,4)";
+ inspectStatus = "0,1,2";
break;
case "8"://瀵勫瓨鍑哄簱
skuType = "(0,1,2,3)";
@@ -478,6 +487,7 @@
.AndIF(!string.IsNullOrWhiteSpace(inspectStatus), it => inspectStatus.Contains(it.InspectStatus))
.And(m => skuList.Contains(m.SkuNo))
.AndIF(type == "6", m => m.OwnerNo == ownerNo)//浠e偍鍑哄簱闇�瑕佸叧鑱旇揣涓�
+ .AndIF(type != "6", m=> string.IsNullOrWhiteSpace(m.OwnerNo))
.AndIF(!string.IsNullOrWhiteSpace(msg), it => (it.SkuNo.Contains(msg) || it.SkuName.Contains(msg) || it.LotNo.Contains(msg)))
.And(it => (it.Qty - it.LockQty - it.FrozenQty) > 0)
.And(it => (it.Status == "0" || it.Status == "1"))
@@ -1233,9 +1243,9 @@
{
throw new Exception("鏈煡璇㈠埌鍑哄簱鍗曟嵁淇℃伅");
}
- if (notice.Status != "4")
+ if (notice.Status != "4" && notice.Status != "3")
{
- throw new Exception("鍙傛暟寮傚父,璇锋鏌ョ姸鎬佹槸鍚︿负鎵ц瀹屾垚鎴栬鍗曞叧闂�");
+ throw new Exception("鍙傛暟寮傚父,璇锋鏌ョ姸鎬佹槸鍚︿负姝e湪鎵ц鎴栨墽琛屽畬鎴�");
}
//鎬诲簱瀛樹俊鎭�
var stockList = Db.Queryable<DataStock>().ToList();
@@ -1256,64 +1266,67 @@
foreach (var d in noticeDetail)
{
- //鏇存敼搴撳瓨鏄庣粏閿佸畾鏁伴噺
- //var orders = dataContext.WmsExportOrder.Where(o => o.ExportDetailId == d.Id
- // && o.ExportExecuteFlag != "4" && o.ExportExecuteFlag == "3" && o.pickingType == 0).ToList();
- //foreach (var o in orders)
- //{
- // if (o.ExportQuantity > o.PickedNum) //鍒ゆ柇鎷h揣鏄惁宸叉嫞瀹�
- // {
- // var pq = dataContext.WmsStockTray.Where(t => t.StockGoodId == o.ExportGoodsCode && t.StockStockCode == o.ExportStockCode);
-
- // if (string.IsNullOrWhiteSpace(o.ExportLotNo))
- // {
- // pq = pq.Where(t => t.StockLotNo == null || t.StockLotNo == "");
- // }
- // else
- // {
- // pq = pq.Where(t => t.StockLotNo == o.ExportLotNo);
- // }
- // var pallet = pq.FirstOrDefault();
- // //搴撳瓨鎵樼洏淇℃伅閿佸畾鏁伴噺杩樺師涓烘湭閿佸畾
- // if (pq != null)
- // {
- // pallet.LockQuantity -= o.ExportQuantity.Value - o.PickedNum;
- // pallet.StockQuantity += o.ExportQuantity.Value - o.PickedNum;
- // }
- // }
- //}
-
- if (d.Qty != d.CompleteQty)
+ if (notice.Type == "0")//鎴愬搧鍑哄簱
{
- throw new Exception("褰撳墠鍗曟嵁鏄庣粏涓鍒掓暟閲忎笌鎷h揣鏁伴噺涓嶇锛岃鏍稿疄");
- }
- #region 搴撳瓨琛ㄥ噺鍘婚攣瀹氭暟閲忎笌鎬绘暟閲�(PDA鎷h揣鐨勬椂鍊欏凡缁忓噺鍘绘暟閲忎簡)
- /*var sq = stocks.Where(s => s.SkuNo == d.SkuNo);
- if (!string.IsNullOrWhiteSpace(d.LotNo))
- {
- sq = sq.Where(s => s.LotNo == d.LotNo);
- }
- else
- {
- sq = sq.Where(s => string.IsNullOrWhiteSpace(s.LotNo));
- }
- var st = sq.FirstOrDefault();
- if (st != null)
- {
- if (d.CompleteQty <= d.Qty)
+ if (d.Qty != d.CompleteQty)
{
- st.Qty += d.Qty - d.CompleteQty.Value;
+ throw new Exception("褰撳墠鍗曟嵁鏄庣粏涓鍒掓暟閲忎笌鎷h揣鏁伴噺涓嶇锛岃鏍稿疄");
+ }
+ }
+ if (d.Qty < d.CompleteQty)
+ {
+ //鏇存敼搴撳瓨鏄庣粏閿佸畾鏁伴噺
+ var allotList = Db.Queryable<BllExportAllot>().Where(o => o.SODetailNo == d.Id && o.Status == "3" && o.IsDel == "0").ToList();
+ foreach (var o in allotList)
+ {
+ if (o.Qty > o.CompleteQty) //鍒ゆ柇鎷h揣鏄惁宸叉嫞瀹�
+ {
+ var pq = Db.Queryable<DataStockDetail>().Where(t => t.IsDel == "0" && t.Id == o.StockId && t.SkuNo == o.SkuNo);
+
+ if (string.IsNullOrWhiteSpace(o.LotNo))
+ {
+ pq = pq.Where(t => string.IsNullOrWhiteSpace(t.LotNo));
+ }
+ else
+ {
+ pq = pq.Where(t => t.LotNo == o.LotNo);
+ }
+ var pallet = pq.First();
+ //搴撳瓨鎵樼洏淇℃伅閿佸畾鏁伴噺杩樺師涓烘湭閿佸畾
+ if (pq != null)
+ {
+ //pallet.Qty -= o.CompleteQty.Value - o.Qty;
+ pallet.LockQty -= o.Qty - o.CompleteQty.Value;
+ Db.Updateable(pallet).UpdateColumns(it => new { it.LockQty }).ExecuteCommand();
+ }
+ }
+ }
+
+
+ #region 搴撳瓨琛ㄥ噺鍘婚攣瀹氭暟閲忎笌鎬绘暟閲�(PDA鎷h揣鐨勬椂鍊欏凡缁忓噺鍘绘暟閲忎簡)
+ var sq = stocks.Where(s => s.SkuNo == d.SkuNo);
+ if (!string.IsNullOrWhiteSpace(d.LotNo))
+ {
+ sq = sq.Where(s => s.LotNo == d.LotNo);
}
else
{
- st.Qty -= d.CompleteQty.Value - d.Qty;
+ sq = sq.Where(s => string.IsNullOrWhiteSpace(s.LotNo));
}
- st.LockQty -= d.Qty;
- st.Qty -= d.Qty;
- //淇敼鎬诲簱瀛樿〃
- Db.Updateable(st).UpdateColumns(it => new { it.Qty, it.LockQty }).ExecuteCommand();
- }*/
- #endregion
+ if (notice.Type == "6")//浠e偍
+ {
+ sq = sq.Where(s => s.OwnerNo == notice.CustomerNo);
+ }
+ var st = sq.FirstOrDefault();
+ if (st != null)
+ {
+ st.LockQty -= d.Qty - d.CompleteQty.Value;
+ //淇敼鎬诲簱瀛樿〃
+ Db.Updateable(st).UpdateColumns(it => new { it.LockQty }).ExecuteCommand();
+ }
+ #endregion
+ }
+
}
//娣诲姞鎿嶄綔鏃ュ織璁板綍
var k = new OperationSOServer().AddLogOperationSo("鍑哄簱浣滀笟", "鍑哄簱鍗曟嵁", notice.SONo, "鍏冲崟", $"鍏抽棴浜嗗崟鎹彿涓簕notice.SONo}鐨勫崟鎹俊鎭�", userId);
@@ -2163,6 +2176,10 @@
{
str += "3.瑕佸嚭搴撶殑鎵樼洏姝e湪鍏ュ簱銆�";
}
+ if (string.IsNullOrWhiteSpace(str))
+ {
+ str += "鎵樼洏鍙墽琛岋紝鏃犻渶涓嬪彂鍑哄簱浠诲姟";
+ }
if (outDto1.Count > 0)
{
// 姝e紡杩愯绋嬪簭鏀惧紑
@@ -2173,22 +2190,22 @@
try
{
var time1 = DateTime.Now;//鍙戦�佹椂闂� .ToString("yyyy-MM-dd HH:mm:ss")
- //response = HttpHelper.DoPost(url, jsonData, "涓嬪彂缁橶CS鍑哄簱鍛戒护", "WCS");
+ response = HttpHelper.DoPost(url, jsonData, "涓嬪彂缁橶CS鍑哄簱鍛戒护", "WCS");
var time2 = DateTime.Now;//杩斿洖鏃堕棿 .ToString("yyyy-MM-dd HH:mm:ss")
//////瑙f瀽杩斿洖鏁版嵁
var wcsModel = JsonConvert.DeserializeObject<WcsModel>(response);
- //if (wcsModel.StatusCode == 0)
- //{
- //鏇存敼浠诲姟鐨勫彂閫佽繑鍥炴椂闂�//
- new TaskServer().EditTaskIssueOk(list2, time1, time2);
- str += "涓嬪彂鎴愬姛";
- //}
- //if (wcsModel.StatusCode == -1)
- //{
- // new TaskServer().EditTaskIssueNo(list2, time1, time2, wcsModel.Msg);
- // throw new Exception(wcsModel.Msg);
- //}
+ if (wcsModel.StatusCode == 0)
+ {
+ //鏇存敼浠诲姟鐨勫彂閫佽繑鍥炴椂闂�//
+ new TaskServer().EditTaskIssueOk(list2, time1, time2);
+ str += "涓嬪彂鎴愬姛";
+ }
+ if (wcsModel.StatusCode == -1)
+ {
+ new TaskServer().EditTaskIssueNo(list2, time1, time2, wcsModel.Msg);
+ throw new Exception(wcsModel.Msg);
+ }
}
catch (Exception ex)
{
@@ -3215,26 +3232,63 @@
{
throw new Exception("鑾峰彇澶辫触锛屾湭鎵惧埌鎸囧畾鍑哄簱鍗曪紒");
}
- if (detail.Status != "0" && detail.Status != "1" && detail.AllotQty >= detail.Qty)
- {
- throw new Exception("鑾峰彇澶辫触锛屽嚭搴撳崟鐘舵�佷笉鏄瓑寰呮墽琛屾垨鍒嗛厤涓紒");
- }
- if (detail.AllotQty >= detail.Qty)
- {
- throw new Exception("鑾峰彇澶辫触锛屽嚭搴撳崟宸插垎閰嶅畬鎴�!");
- }
+
var notice = Db.Queryable<BllExportNotice>().First(a => a.SONo == detail.SONo);
if (notice == null)
{
throw new Exception("鑾峰彇澶辫触锛屾湭鎵惧埌鎸囧畾鍑哄簱鍗�!");
}
- if (notice.Status == "3" && detail.AllotQty >= detail.Qty || notice.Status == "4" || notice.Status == "5")
+ if (notice.Type != "1" && notice.Type != "2" && notice.Type != "3")
{
- throw new Exception("鑾峰彇澶辫触锛屽嚭搴撳崟鐘舵�佷笉鍏佽!");
+ if (detail.Status != "0" && detail.Status != "1" && detail.AllotQty >= detail.Qty)
+ {
+ throw new Exception("鑾峰彇澶辫触锛屽嚭搴撳崟鐘舵�佷笉鏄瓑寰呮墽琛屾垨鍒嗛厤涓紒");
+ }
+ if (detail.AllotQty >= detail.Qty)
+ {
+ throw new Exception("鑾峰彇澶辫触锛屽嚭搴撳崟宸插垎閰嶅畬鎴�!");
+ }
+
+ if (notice.Status == "3" && detail.AllotQty >= detail.Qty || notice.Status == "4" || notice.Status == "5")
+ {
+ throw new Exception("鑾峰彇澶辫触锛屽嚭搴撳崟鐘舵�佷笉鍏佽!");
+ }
+ }
+ string inspectStatus = string.Empty;
+ switch (notice.Type)//0锛氬師鏂� 1锛氬寘鏉� 2锛氭垚鍝� 3锛氳�楁潗 4锛氬崐鎴愬搧
+ {
+ case "0"://鎴愬搧鍑哄簱
+ inspectStatus = "1";
+ break;
+ case "1"://棰嗘枡鍑哄簱
+ inspectStatus = "1";
+ break;
+ case "2"://鎶芥鍑哄簱
+ inspectStatus = "0,1,2";
+ break;
+ case "3"://鐗╂枡鍙栨牱鍑哄簱
+ inspectStatus = "0";
+ break;
+ case "4"://涓嶅悎鏍煎搧鍑哄簱
+ inspectStatus = "2";
+ break;
+ case "5"://涓棿鍝佸嚭搴�
+ inspectStatus = "1";
+ break;
+ case "6"://浠e偍鍑哄簱
+ inspectStatus = "0,1,2";
+ break;
+ case "8"://瀵勫瓨鍑哄簱
+ inspectStatus = "0,1";
+ break;
+ default: //鍏跺畠鍑哄簱
+ inspectStatus = "0,1";
+ break;
}
#endregion
Expression<Func<DataStockDetail, bool>> item = Expressionable.Create<DataStockDetail>()
+ .AndIF(!string.IsNullOrWhiteSpace(inspectStatus), m => inspectStatus.Contains(m.InspectStatus))
.AndIF(!string.IsNullOrWhiteSpace(houseNo), m => m.WareHouseNo == houseNo)
.AndIF(!string.IsNullOrWhiteSpace(roadwayNo), m => m.RoadwayNo == roadwayNo)
.AndIF(!string.IsNullOrWhiteSpace(locateNo), m => m.LocatNo == locateNo)
@@ -3282,29 +3336,36 @@
{
throw new Exception("鎿嶄綔澶辫触锛屾湭鎵惧埌鎸囧畾鍑哄簱鍗曡鎯咃紒");
}
- if (detail.AllotQty >= detail.Qty || (detail.Status != "0" && detail.Status != "1"))
- {
- throw new Exception("鎿嶄綔澶辫触锛屽嚭搴撳崟宸插垎閰嶅畬鎴愶紒");
- }
var notice = Db.Queryable<BllExportNotice>().First(a => a.IsDel == "0" && a.SONo == detail.SONo);
if (notice == null)
{
throw new Exception("鎿嶄綔澶辫触锛屾湭鎵惧埌鎸囧畾鍑哄簱鍗曪紒");
}
- if (notice.Status == "3" && detail.AllotQty >= detail.Qty || notice.Status == "4" || notice.Status == "5")
+ if (notice.Type != "1" && notice.Type != "2" && notice.Type !="3")
{
- throw new Exception("鎿嶄綔澶辫触锛屽嚭搴撳崟宸插垎閰嶅畬鎴愶紒");
+ if (detail.AllotQty >= detail.Qty || (detail.Status != "0" && detail.Status != "1"))
+ {
+ throw new Exception("鎿嶄綔澶辫触锛屽嚭搴撳崟宸插垎閰嶅畬鎴愶紒");
+ }
+
+ if (notice.Status == "3" && detail.AllotQty >= detail.Qty || notice.Status == "4" || notice.Status == "5")
+ {
+ throw new Exception("鎿嶄綔澶辫触锛屽嚭搴撳崟宸插垎閰嶅畬鎴愶紒");
+ }
+
+ //鍗曟嵁鏄庣粏闇�瑕佺殑鍑哄簱鏁伴噺
+ var needQty = detail.Qty - detail.AllotQty;
+ //鍒嗛厤鐨勫嚭搴撴暟閲�
+ var outQty = model.StockList.Select(s => s.Qty).ToList().Sum();
+ if (outQty < needQty)
+ {
+ throw new Exception("鎿嶄綔澶辫触锛屽嚭搴撴暟閲忎笉鑳藉ぇ浜庤鍒掓暟閲忥紒");
+ }
}
+
#endregion
- //鍗曟嵁鏄庣粏闇�瑕佺殑鍑哄簱鏁伴噺
- var needQty = detail.Qty - detail.AllotQty;
- //鍒嗛厤鐨勫嚭搴撴暟閲�
- var outQty = model.StockList.Select(s => s.Qty).ToList().Sum();
- if (outQty != needQty)
- {
- throw new Exception("鎿嶄綔澶辫触锛屽嚭搴撴暟閲忎笌璁″垝鏁伴噺涓嶄竴鑷达紒");
- }
+
var stockIds = model.StockList.Select(a => a.StockId).ToList();
//搴撳瓨鏄庣粏
var stockList = Db.Queryable<DataStockDetail>().Where(a => stockIds.Contains(a.Id)).ToList();
@@ -3313,7 +3374,7 @@
var allots = Db.Queryable<BllExportAllot>().Where(m => m.IsDel == "0" && m.SODetailNo == detail.Id && m.Status == "0").ToList();
//搴撳瓨鎬昏〃
- //var stockz = Db.Queryable<DataStock>().First(d => d.IsDel == "0" && d.SkuNo == detail.SkuNo && d.LotNo == detail.LotNo);
+ var stockz = Db.Queryable<DataStock>().First(d => d.IsDel == "0" && d.SkuNo == detail.SkuNo && d.LotNo == detail.LotNo);
var allotList = new List<BllExportAllot>();
decimal outQtys = 0;
@@ -3350,7 +3411,7 @@
IsBelt = stock.IsBelt,
Qty = st.Qty,
CompleteQty = 0,
- Status = "0",
+ Status = notice.Status == "4"? "2":"0",
LogisticsId = notice.LogisticsId,
IsAdvance = "0",
OutMode = "",//鍑哄簱鍙�
@@ -3369,11 +3430,12 @@
//搴撳瓨鏄庣粏
stock.LockQty += st.Qty;
stock.Status = stock.LockQty == stock.Qty ? "2" : "1";
-
- //搴撳瓨鎬昏〃
- //stockz.LockQty += st.Qty;
- //Db.Updateable(stockz).ExecuteCommand();
-
+ if (detail.AllotQty+ st.Qty > detail.Qty)
+ {
+ //搴撳瓨鎬昏〃
+ stockz.LockQty += (decimal)detail.AllotQty + st.Qty - detail.Qty;
+ Db.Updateable(stockz).ExecuteCommand();
+ }
Db.Updateable(stock).UpdateColumns(it => new { it.LockQty, it.Status }).ExecuteCommand();
outQtys += st.Qty;
--
Gitblit v1.8.0