掛單管理
This commit is contained in:
1 parent
8db6019ba3
commit
9e251fc7d4
12 files changed
+2197
-116
No files matched your search
@@ -2047,6 +2047,7 @@ namespace Model
|
||||
public System.Guid Uuid { get; set; }
|
||||
public System.Guid RoomUuid { get; set; }
|
||||
public string StatusCode { get; set; }
|
||||
public string Limits { get; set; }
|
||||
|
||||
public virtual Room Room { get; set; }
|
||||
public virtual RegionRoomBedStatus RegionRoomBedStatus { get; set; }
|
||||
|
||||
@@ -1202,6 +1202,7 @@
|
||||
<Property Name="Uuid" Type="uniqueidentifier" Nullable="false" />
|
||||
<Property Name="RoomUuid" Type="uniqueidentifier" Nullable="false" />
|
||||
<Property Name="StatusCode" Type="nvarchar" MaxLength="20" Nullable="false" />
|
||||
<Property Name="Limits" Type="varchar(max)" />
|
||||
</EntityType>
|
||||
<EntityType Name="RegionRoomBedStatus">
|
||||
<Key>
|
||||
@@ -5507,6 +5508,7 @@
|
||||
<NavigationProperty Name="Room" Relationship="Model.FK_RegionRoomBed_RoomUuid" FromRole="RegionRoomBed" ToRole="Room" />
|
||||
<NavigationProperty Name="RegionRoomBedStatus" Relationship="Model.FK_RegionRoomBed_StatusCode" FromRole="RegionRoomBed" ToRole="RegionRoomBedStatus" />
|
||||
<NavigationProperty Name="GuaDanOrderGuest" Relationship="Model.FK_GuaDanOrderGuest_BedUuid" FromRole="RegionRoomBed" ToRole="GuaDanOrderGuest" />
|
||||
<Property Name="Limits" Type="String" MaxLength="Max" FixedLength="false" Unicode="false" />
|
||||
</EntityType>
|
||||
<EntityType Name="RegionRoomBedStatus">
|
||||
<Key>
|
||||
@@ -7277,6 +7279,7 @@
|
||||
<EntitySetMapping Name="RegionRoomBed">
|
||||
<EntityTypeMapping TypeName="Model.RegionRoomBed">
|
||||
<MappingFragment StoreEntitySet="RegionRoomBed">
|
||||
<ScalarProperty Name="Limits" ColumnName="Limits" />
|
||||
<ScalarProperty Name="StatusCode" ColumnName="StatusCode" />
|
||||
<ScalarProperty Name="RoomUuid" ColumnName="RoomUuid" />
|
||||
<ScalarProperty Name="Uuid" ColumnName="Uuid" />
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user