掛單管理

This commit is contained in:
minom committed 2026-11-06 18:06:50 +08:00
1 parent 8db6019ba3
commit 9e251fc7d4
12 files changed
+2197 -116

No files matched your search

+161 -52
View File
@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
using System.util.collections;
using System.Web;
using System.Web.Http;
using static Model.admin_log;
@@ -30,7 +31,7 @@ public class guadanOrderController : ApiController
var query = _db.GuaDanOrder
.Where(a => a.IsCancel == false)
.Where(a => a.IsDeleted == false);
if(!string.IsNullOrEmpty(search.guaDanOrderNo))
if (!string.IsNullOrEmpty(search.guaDanOrderNo))
{
query = query.Where(order => order.GuaDanOrderNo == search.guaDanOrderNo);
}
@@ -87,14 +88,14 @@ public class guadanOrderController : ApiController
.Where(c => c.GuaDanOrderNo == a.GuaDanOrderNo && c.IsDeleted == false)
.Where(c => c.RegionRoomBedStatus.Code != GuaDanOrderGuest.STATUS_CANCELLED)
.Count(),
guadan_status = _db.GuaDanOrderGuest
guadan_status = _db.GuaDanOrderGuest
.Where(g => g.GuaDanOrderNo == a.GuaDanOrderNo && a.IsDeleted == false)
.Where(g => g.StatusCode != GuaDanOrderGuest.STATUS_CANCELLED)
.All(g => g.StatusCode == "401") ? new { code=501, name="預約" }:
.All(g => g.StatusCode == "401") ? new { code = 501, name = "預約" } :
_db.GuaDanOrderGuest
.Where(g => g.GuaDanOrderNo == a.GuaDanOrderNo && a.IsDeleted == false)
.Where(g => g.StatusCode != GuaDanOrderGuest.STATUS_CANCELLED)
.All(g => g.StatusCode == "403") ? new { code = 502, name = "全部退房" } :
.All(g => g.StatusCode == "403") ? new { code = 502, name = "全部退房" } :
_db.GuaDanOrderGuest
.Where(g => g.GuaDanOrderNo == a.GuaDanOrderNo && a.IsDeleted == false)
.Where(g => g.StatusCode != GuaDanOrderGuest.STATUS_CANCELLED)
@@ -110,6 +111,114 @@ public class guadanOrderController : ApiController
data
});
}
[HttpPost]
[Route("api/guadan/getorderbyuuid")]
public async Task<IHttpActionResult> getGuadanOrderByUuid([FromBody] dynamic req)
{
if (!Guid.TryParse((string)req.uuid, out Guid targetGuid))
{
return BadRequest("無效的 GUID 格式");
}
var order = await _db.GuaDanOrder
.Where(a => a.Uuid == targetGuid)
.Where(a => a.IsCancel == false && a.IsDeleted == false)
.FirstOrDefaultAsync();
if (order == null)
{
return BadRequest("未找到對應掛單資料");
}
// 1. 先把全台/全區的 Region 載入記憶體做成字典,方便 GetParentPath 快速查找
var regionDict = _db.Region.ToDictionary(r => r.Uuid);
// 2. 修改你的 GetParentPath 邏輯(改用高效的 while 迴圈)
List<string> GetRegionPathNames(Guid? startRegionUuid)
{
var pathNames = new List<string>();
Guid? nextId = startRegionUuid;
while (nextId.HasValue && regionDict.TryGetValue(nextId.Value, out var reg))
{
pathNames.Add(reg.Name); // 收集區域名稱
nextId = reg.ParentUuid; // 假設你的欄位叫 ParentUuid,請依實際欄位修改
}
// 反轉順序讓它變成:[大區域, 中區域, 小區域]
pathNames.Reverse();
return pathNames;
}
var result = new
{
order_form = new
{
order.admin,
order.followers,
startdate = order.StartDate?.ToString("yyyy-MM-dd"),
enddate = order.EndDate?.ToString("yyyy-MM-dd"),
order.CreateUser,
order.CreatedAt,
order.UpdatedAt,
note = order.Notes,
orderNo = order.GuaDanOrderNo,
order.BookerFollowerNum,
bookerName = order.BookerName,
bookerPhone = order.BookerPhone,
order.IsDeleted,
uuid = order.Uuid,
activityNum = order.ActivityNum,
},
details = _db.GuaDanOrderGuest
.Where(g => g.GuaDanOrderNo == order.GuaDanOrderNo && g.IsDeleted == false)
.Select(g => new
{
g.Uuid,
g.GuaDanOrderNo,
g.RoomUuid,
g.BedUuid,
checkinat = g.CheckInAt,
checkoutat = g.CheckOutAt,
gender = g.Sex,
specialNeeds = g.Handi,
name = g.Name,
statuscode = g.StatusCode,
g.FollowerNum,
bedName = _db.RegionRoomBed.Where(b => b.Uuid == g.BedUuid).Select(b => b.Name).FirstOrDefault(),
// 先把資料庫能查的查出來
roomRaw = _db.Room.Where(r => r.Uuid == g.RoomUuid).Select(r => new
{
r.Name,
r.RegionUuid
}).FirstOrDefault()
}).AsEnumerable() // 🔥 關鍵:從這裡切斷,後面的 Select 會在 C# 記憶體內執行
.Select(g => new
{
g.Uuid,
g.GuaDanOrderNo,
g.RoomUuid,
g.BedUuid,
g.checkinat,
g.checkoutat,
g.gender,
g.specialNeeds,
g.name,
g.statuscode,
g.FollowerNum,
g.bedName,
room = g.roomRaw == null ? null : new
{
g.roomRaw.Name,
g.roomRaw.RegionUuid,
// 在記憶體中,這時候可以直接查字典拿到當前區域名稱
regionName = regionDict.TryGetValue(g.roomRaw.RegionUuid, out var r) ? r.Name : null,
// 🔥 這時候呼叫區域函式就不會報錯了!
resion = GetRegionPathNames(g.roomRaw.RegionUuid)
}
})
.ToList()
};
return Ok(result);
}
[HttpGet]
[Route("api/guadan/getorderbyid")]
public async Task<IHttpActionResult> getGuadanOrderById(string orderId)
@@ -187,12 +296,53 @@ public class guadanOrderController : ApiController
return Ok(guadanorder);
}
[HttpPost]
[Route("api/guadan/changeGuadanGuest")]
public async Task<IHttpActionResult> ChangeGuadanGuest([FromBody] dynamic req)
{
var json = req;
if (json != null && json.guest != null)
{
var guest = json.guest;
}
return Ok();
}
[HttpPost]
[Route("api/guadan/updateGandan")]
public async Task<IHttpActionResult> UpdateGandan([FromBody] dynamic req)
{
var json = req;
if (json != null && json.order != null)
{
var order = json.order;
string guadanOrderNo = order.GuaDanOrderNo;
var oldOrder = _db.GuaDanOrder.Where(a => a.GuaDanOrderNo == guadanOrderNo).FirstOrDefault();
if (oldOrder == null)
{
return BadRequest("未找到對應掛單資料");
}
oldOrder.StartDate = order.startdate;
oldOrder.EndDate = order.enddate;
oldOrder.UpdatedAt = DateTime.Now;
oldOrder.Notes = order.note;
oldOrder.BookerName = order.bookerName;
oldOrder.BookerPhone = order.bookerPhone;
await _db.SaveChangesAsync();
}
return Ok();
}
[HttpPost]
[Route("api/guadan/saveGandan")]
public async Task<IHttpActionResult> SaveGandan([FromBody] dynamic req)
{
var json = req;
if (json != null&&json.order!=null) {
if (json != null && json.order != null)
{
var order = json.order;
if (string.IsNullOrEmpty(order.GuaDanOrderNo))
{//表示新增掛單
@@ -215,12 +365,12 @@ public class guadanOrderController : ApiController
var list = new List<GuaDanOrderGuest>();
var guest = new GuaDanOrderGuest();
var bedList = new List<RegionAndRoomAndBedSchedule>();
if (json.detail!=null)
if (json.detail != null)
{
var details = json.detail;
foreach (var detail in details)
{
guest=new GuaDanOrderGuest
guest = new GuaDanOrderGuest
{
GuaDanOrderNo = guadanorder.GuaDanOrderNo,
Uuid = Guid.NewGuid(),
@@ -240,7 +390,7 @@ public class guadanOrderController : ApiController
return BadRequest("無效的 GUID 格式");
}
if (detail.bedUuid!=null&&!string.IsNullOrEmpty((string)detail.bedUuid))
if (detail.bedUuid != null && !string.IsNullOrEmpty((string)detail.bedUuid))
{
var bed = _db.RegionRoomBed.Where(r => r.Uuid == targetGuid);
if (bed == null)
@@ -255,7 +405,8 @@ public class guadanOrderController : ApiController
if (!bedIsCanUse)
return BadRequest("床位在該時間段內已被占用");
}
else {
else
{
return BadRequest("未設定床位");
}
@@ -284,54 +435,12 @@ public class guadanOrderController : ApiController
}
}
_db.GuaDanOrder.Add(guadanorder);
_db.GuaDanOrderGuest.AddRange(list);
_db.RegionAndRoomAndBedSchedule.AddRange(bedList);
_db.SaveChanges();
}
else
{//表示更新掛單
var model =await _db.GuaDanOrder.FindAsync((string)order.Uuid);
if (model == null)
{
return BadRequest("未找到對應掛單資料");
}
model.StartDate = order.startdate;
model.EndDate = order.enddate;
model.Notes = order.note;
model.BookerName = order.bookerName;
model.BookerPhone = order.bookerPhone;
model.ActivityNum = order.activityNum;
//更新掛單明細...還要處理RegionAndRoomAndBedSchedule
}
//if (json.detail != null)
//{
// var details = json.detail;
// foreach (var detail in details)
// {
// var guadanDetail = new GuaDanOrderGuest
// {
// GuaDanOrderNo = order.GuaDanOrderNo,
// //FollowerNum = detail.guestName,
// Uuid = detail.uuid,
// StatusCode = "401", // 預約狀態
// RoomUuid = detail.roomUuid,
// BedUuid = detail.bedUuid,
// CheckInAt = detail.checkInAt,
// CheckOutAt = detail.checkOutAt,
// Sex = detail.gender,
// Handi = detail.handi,
// IsDeleted = false,
// Name = detail.name,
// };
// _db.GuaDanOrderGuest.Add(guadanDetail);
// }
// //return BadRequest("掛單資料不可為空");
//}
}
return Ok();
}
+2 -1
View File
@@ -236,7 +236,7 @@ public class regionController : ApiController
isactive = c.IsActive,
statuscode = c.StatusCode,
Gender = c.Gender,
Limits=c.Limits,
}).ToList(),
}).ToList(),
@@ -349,6 +349,7 @@ public class regionController : ApiController
public string statuscode { get; set; }
public bool isactive { get; set; }
public bool Gender { get; set; }
public string Limits { get; set; }
}
public class RegionDto
+80 -11
View File
@@ -195,6 +195,7 @@ public class regionRoomBedController : ApiController
oldBed.IsActive = bed.IsActive;
oldBed.Name = bed.Name;
oldBed.Gender = bed.Gender;
oldBed.Limits = bed.Limits;
_db.SaveChanges();
//創建床位
@@ -294,18 +295,86 @@ public class regionRoomBedController : ApiController
.Distinct()
.ToList();
// 空閒床位 = 所有床位 - 忙碌床位
var availableBeds = _db.RegionRoomBed.Select(b=>new {
b.Name ,b.Uuid,b.StatusCode,b.IsActive,
b.RoomUuid,
Room=_db.Room.Where(r=>r.Uuid==b.RoomUuid).
Select(r=>new { r.Name,r.RegionUuid,
RegionName=_db.Region.Where(g=>g.Uuid==r.RegionUuid).Select(g=>g.Name).FirstOrDefault()}).FirstOrDefault(),
})
.Where(b => !busyBedUuids.Contains(b.Uuid))
.ToList();
// 1. 先把全台/全區的 Region 載入記憶體做成字典,方便 GetParentPath 快速查找
var regionDict = _db.Region.ToDictionary(r => r.Uuid);
// 2. 修改你的 GetParentPath 邏輯(改用高效的 while 迴圈)
List<string> GetRegionPathNames(Guid? startRegionUuid)
{
var pathNames = new List<string>();
Guid? nextId = startRegionUuid;
while (nextId.HasValue && regionDict.TryGetValue(nextId.Value, out var reg))
{
pathNames.Add(reg.Name); // 收集區域名稱
nextId = reg.ParentUuid; // 假設你的欄位叫 ParentUuid,請依實際欄位修改
}
// 反轉順序讓它變成:[大區域, 中區域, 小區域]
pathNames.Reverse();
return pathNames;
}
// 3. 步驟 A:純資料庫查詢 (只撈取需要的資料,不呼叫 C# 函式)
var dbBeds = _db.RegionRoomBed
.Where(b => !busyBedUuids.Contains(b.Uuid)) // 建議過濾條件放在 ToList 之前,減少傳輸資料量
.Select(b => new
{
b.Name,
b.Uuid,
b.StatusCode,
b.IsActive,
b.RoomUuid,
b.Limits,
// 直接在 SQL 層級把 Room 撈出來
Room = _db.Room
.Where(r => r.Uuid == b.RoomUuid)
.Select(r => new
{
r.Name,
r.RegionUuid
})
.FirstOrDefault()
})
.AsEnumerable(); // 💡 關鍵:從這裡開始切換到記憶體(LINQ to Objects)
// 4. 步驟 B:在記憶體中加工,呼叫 GetRegionPathNames
var availableBeds = dbBeds.Select(b => new
{
b.Name,
b.Uuid,
b.StatusCode,
b.IsActive,
b.RoomUuid,
b.Limits,
// 💡 此時已經在記憶體中,可以安全地呼叫 C# 函式
RegionPath = GetRegionPathNames(b.Room?.RegionUuid),
Room = b.Room == null ? null : new
{
b.Room.Name,
b.Room.RegionUuid,
// 從你已經載入的字典中直接抓 RegionName,省去在 SQL 裡面重複 Join Region 表
// 💡 修正關鍵:用 is 語法自動拆箱並安全檢查,完美避開 ?? 的型態限制
RegionName = b.Room.RegionUuid is Guid rId && regionDict.TryGetValue(rId, out var reg)
? reg.Name
: null
}
}).ToList();
// 空閒床位 = 所有床位 - 忙碌床位
//var availableBeds = _db.RegionRoomBed.Select(b=>new {
// b.Name ,b.Uuid,b.StatusCode,b.IsActive,
// b.RoomUuid,b.Limits,
// resion = GetRegionPathNames(b.RoomUuid),
// Room =_db.Room.Where(r=>r.Uuid==b.RoomUuid).
// Select(r=>new { r.Name,r.RegionUuid,
// RegionName=_db.Region.Where(g=>g.Uuid==r.RegionUuid).
// Select(g=>g.Name).FirstOrDefault()}).FirstOrDefault(),
//})
// .Where(b => !busyBedUuids.Contains(b.Uuid))
// .ToList();
return Ok(new { availableBeds });
}