guadan
This commit is contained in:
33
web/App_Code/GuaDanStatusCode.cs
Normal file
33
web/App_Code/GuaDanStatusCode.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Web;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// GuaDanStatusCode 的摘要描述
|
||||||
|
/// </summary>
|
||||||
|
public static class GuaDanStatusCode
|
||||||
|
{
|
||||||
|
public static class Bed
|
||||||
|
{
|
||||||
|
public const string Empty = "101"; // 空床:床位可分配
|
||||||
|
public const string Occupied = "102"; // 占用中:床位已有人使用
|
||||||
|
public const string Repair = "103"; // 維修停用:床位維修或不可使用
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Room
|
||||||
|
{
|
||||||
|
public const string Empty = "301"; // 空房:房間所有床位皆為空
|
||||||
|
public const string Partly = "302"; // 部分入住:房間有人,但仍有空床
|
||||||
|
public const string Full = "303"; // 已滿:房間所有床位皆已入住
|
||||||
|
public const string Repair = "304"; // 維修停用:房間維修或不可使用
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Guadan
|
||||||
|
{
|
||||||
|
public const string Booked = "401"; // 預訂成功:默認就是預訂成功狀態
|
||||||
|
public const string CheckedIn = "402"; // 已入住:已辦理入住
|
||||||
|
public const string CheckedOut = "403"; // 已退房
|
||||||
|
public const string Cancelled = "404"; // 已取消:取消後的狀態,不是取消的動作
|
||||||
|
}
|
||||||
|
}
|
||||||
184
web/App_Code/api/HandleBedInUsedController.cs
Normal file
184
web/App_Code/api/HandleBedInUsedController.cs
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
using Model;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Web;
|
||||||
|
using System.Web.Http;
|
||||||
|
using System.Web.Http.Results;
|
||||||
|
using static GuaDanStatusCode;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// HandleBedInUsedController 的摘要描述
|
||||||
|
/// </summary>
|
||||||
|
public class HandleBedInUsedController : ApiController
|
||||||
|
{
|
||||||
|
private Model.ezEntities _db = new Model.ezEntities();
|
||||||
|
public HandleBedInUsedController()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// TODO: 在這裡新增建構函式邏輯
|
||||||
|
//
|
||||||
|
}
|
||||||
|
[HttpPost]
|
||||||
|
[Route("api/bed/inuse/list")]
|
||||||
|
public IHttpActionResult Get([FromBody] UuidModel uuidModel)
|
||||||
|
{
|
||||||
|
//獲取已被預約或者正在入住的床位,如果有指定就會查詢指定條件,如果沒有指定就會返回所有
|
||||||
|
var query = _db.GuaDanOrderGuest
|
||||||
|
.Where(gd => gd.StatusCode == GuaDanStatusCode.Guadan.CheckedIn
|
||||||
|
|| gd.StatusCode == GuaDanStatusCode.Guadan.Booked).ToList();
|
||||||
|
if (uuidModel.bedUuid.HasValue)
|
||||||
|
{
|
||||||
|
// 優先按床位查詢
|
||||||
|
query = query.Where(g => g.BedUuid == uuidModel.bedUuid.Value).ToList();
|
||||||
|
}
|
||||||
|
else if (uuidModel.roomUuid.HasValue)
|
||||||
|
{
|
||||||
|
// 如果沒有 bed,但有 room
|
||||||
|
query = query.Where(g => g.RoomUuid == uuidModel.roomUuid.Value).ToList();
|
||||||
|
}
|
||||||
|
else if (uuidModel.regionUuid.HasValue)
|
||||||
|
{
|
||||||
|
// 如果只有 region
|
||||||
|
//query = query.Where(g => g.Room.RegionUuid == uuidModel.regionUuid.Value);
|
||||||
|
query = query.Where(g => IsRegionOrAncestor(g.Room, uuidModel.regionUuid.Value)).ToList();
|
||||||
|
|
||||||
|
}
|
||||||
|
var data = query.Select(g => new
|
||||||
|
{
|
||||||
|
g.BedUuid,
|
||||||
|
g.RoomUuid,
|
||||||
|
g.Room.RegionUuid,
|
||||||
|
g.GuaDanOrderNo,
|
||||||
|
g.RegionRoomBed.Name,
|
||||||
|
fullName = GetFullBedName(g.BedUuid.Value),
|
||||||
|
g.followers.u_name,
|
||||||
|
guadan_during = new { g.CheckInAt, g.CheckOutAt },
|
||||||
|
status = new { g.StatusCode, g.RegionRoomBedStatus.Name }
|
||||||
|
});
|
||||||
|
return Ok(data.ToList());
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[Route("api/bed/inuse/cancel/singlebed/booking")]
|
||||||
|
public IHttpActionResult CancelSingleBedBooking([FromBody] UuidModel uuidModel)
|
||||||
|
{
|
||||||
|
if (uuidModel?.bedUuid == null)
|
||||||
|
return BadRequest("床位ID不能為空");
|
||||||
|
|
||||||
|
using (var transaction = _db.Database.BeginTransaction())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 查詢符合條件的訂單
|
||||||
|
var orders = _db.GuaDanOrderGuest
|
||||||
|
.Where(g => g.BedUuid == uuidModel.bedUuid)
|
||||||
|
.Where(g => g.StatusCode == GuaDanStatusCode.Guadan.Booked || g.StatusCode == GuaDanStatusCode.Guadan.CheckedIn)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (!orders.Any())
|
||||||
|
return NotFound();
|
||||||
|
|
||||||
|
// 更新狀態
|
||||||
|
foreach (var order in orders)
|
||||||
|
{
|
||||||
|
if (!StatusTransitionManager.CanTransition(order.StatusCode, GuaDanStatusCode.Guadan.Cancelled))
|
||||||
|
{
|
||||||
|
return BadRequest("當前狀態不能被取消");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
order.StatusCode = GuaDanStatusCode.Guadan.Cancelled; // 假設Cancelled是取消狀態
|
||||||
|
}
|
||||||
|
var schedules = _db.RegionAndRoomAndBedSchedule
|
||||||
|
.Where(s => s.TargetUuid == uuidModel.bedUuid)
|
||||||
|
.Where(s => s.GuaDanOrderGuest.StatusCode == GuaDanStatusCode.Guadan.Booked
|
||||||
|
|| s.GuaDanOrderGuest.StatusCode == GuaDanStatusCode.Guadan.CheckedIn)
|
||||||
|
.ToList();
|
||||||
|
foreach (var schedule in schedules)
|
||||||
|
{
|
||||||
|
schedule.IsCancel = true;
|
||||||
|
}
|
||||||
|
_db.SaveChanges();
|
||||||
|
transaction.Commit();
|
||||||
|
|
||||||
|
return Ok(new { message = "取消成功", cancelledCount = orders.Count });
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
transaction.Rollback();
|
||||||
|
return InternalServerError(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[HttpGet]
|
||||||
|
[Route("api/bed/inuse/region/list")]
|
||||||
|
public IHttpActionResult GetRegionList()
|
||||||
|
{
|
||||||
|
var regions = _db.Region
|
||||||
|
.Select(r => new
|
||||||
|
{
|
||||||
|
r.Uuid,
|
||||||
|
r.Name,
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
return Ok(regions);
|
||||||
|
}
|
||||||
|
[HttpGet]
|
||||||
|
[Route("api/bed/inuse/room/list")]
|
||||||
|
public IHttpActionResult GetRoomList([FromUri] Guid? regionUuid = null)
|
||||||
|
{
|
||||||
|
var room = _db.Room.Where(r => !r.IsDeleted && r.IsActive.Value).ToList();
|
||||||
|
if (regionUuid != null)
|
||||||
|
{
|
||||||
|
room = room.Where(r => IsRegionOrAncestor(r, regionUuid.Value)).ToList();
|
||||||
|
}
|
||||||
|
var data = room.Select(r => new
|
||||||
|
{
|
||||||
|
r.Uuid,
|
||||||
|
r.Name,
|
||||||
|
fullName = r.Region.Name + "/" + r.Name,
|
||||||
|
}).ToList();
|
||||||
|
return Ok(data);
|
||||||
|
}
|
||||||
|
public string GetFullBedName(Guid bedUuid)
|
||||||
|
{
|
||||||
|
var bed = _db.RegionRoomBed.Find(bedUuid);
|
||||||
|
if (bed == null)
|
||||||
|
return "";
|
||||||
|
var name = bed.Name;
|
||||||
|
var room = bed.Room;
|
||||||
|
if (room == null)
|
||||||
|
return name;
|
||||||
|
name = room.Name + "/" + name;
|
||||||
|
|
||||||
|
var region = room?.Region;
|
||||||
|
while (region != null)
|
||||||
|
{
|
||||||
|
name = region.Name + "/" + name;
|
||||||
|
region = region.Region2; // 遞迴向上
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
bool IsRegionOrAncestor(Model.Room room, Guid regionUuid)
|
||||||
|
{
|
||||||
|
//判斷傳入的regionuuid是否是room的祖先
|
||||||
|
if (room.RegionUuid == regionUuid)
|
||||||
|
return true;
|
||||||
|
var region = room.Region;
|
||||||
|
while (region != null)
|
||||||
|
{
|
||||||
|
if (region.Uuid == regionUuid) return true;
|
||||||
|
region = region.Region2;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public class UuidModel
|
||||||
|
{
|
||||||
|
public Guid? regionUuid = null;
|
||||||
|
public Guid? roomUuid = null;
|
||||||
|
public Guid? bedUuid = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -80,9 +80,9 @@ public class guadanGuestQueryController: ApiController
|
|||||||
{
|
{
|
||||||
var today = DateTime.Now.Date;
|
var today = DateTime.Now.Date;
|
||||||
var data = await _db.GuaDanOrderGuest
|
var data = await _db.GuaDanOrderGuest
|
||||||
.Where(guest => guest.StatusCode == "402")
|
.Where(guest => guest.StatusCode == "402" || guest.StatusCode == "403")
|
||||||
.Where(guest => guest.RegionAndRoomAndBedSchedule
|
.Where(guest => guest.RegionAndRoomAndBedSchedule
|
||||||
.Any(s => s.ScheduleDate == date.Date && s.ScheduleDate == today) == true)
|
.Any(s => s.ScheduleDate == date.Date && s.ScheduleDate <= today) == true)
|
||||||
.Select(guest => new
|
.Select(guest => new
|
||||||
{
|
{
|
||||||
name = guest.followers.u_name,
|
name = guest.followers.u_name,
|
||||||
@@ -96,7 +96,7 @@ public class guadanGuestQueryController: ApiController
|
|||||||
public async Task<IHttpActionResult> GetBookingGuest([FromUri] DateTime date)
|
public async Task<IHttpActionResult> GetBookingGuest([FromUri] DateTime date)
|
||||||
{
|
{
|
||||||
var data = await _db.GuaDanOrderGuest
|
var data = await _db.GuaDanOrderGuest
|
||||||
.Where(guest => guest.StatusCode == "402" || guest.StatusCode == "401")
|
.Where(guest => guest.StatusCode == "402" || guest.StatusCode == "401" || guest.StatusCode == "403")
|
||||||
.Where(guest => guest.RegionAndRoomAndBedSchedule.Any(s => s.ScheduleDate == date.Date) == true)
|
.Where(guest => guest.RegionAndRoomAndBedSchedule.Any(s => s.ScheduleDate == date.Date) == true)
|
||||||
.Select(guest => new
|
.Select(guest => new
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,12 +24,12 @@ public class guadanOrderController : ApiController
|
|||||||
var query = _db.GuaDanOrder
|
var query = _db.GuaDanOrder
|
||||||
.Where(a => a.IsCancel == false)
|
.Where(a => a.IsCancel == false)
|
||||||
.Where(a => a.IsDeleted == false);
|
.Where(a => a.IsDeleted == false);
|
||||||
if(search.guadanUser != null)
|
if (search.guadanUser != null)
|
||||||
{
|
{
|
||||||
query = query.Where(order => order.BookerName == search.guadanUser);
|
query = query.Where(order => order.BookerName == search.guadanUser);
|
||||||
}
|
}
|
||||||
if (search.startDate != null && search.endDate != null)
|
if (search.startDate != null && search.endDate != null)
|
||||||
{
|
{
|
||||||
query = query.Where(order => order.StartDate >= search.startDate)
|
query = query.Where(order => order.StartDate >= search.startDate)
|
||||||
.Where(order => order.EndDate <= search.endDate);
|
.Where(order => order.EndDate <= search.endDate);
|
||||||
}
|
}
|
||||||
@@ -56,11 +56,28 @@ public class guadanOrderController : ApiController
|
|||||||
created_at = a.CreatedAt,
|
created_at = a.CreatedAt,
|
||||||
updated_at = a.UpdatedAt,
|
updated_at = a.UpdatedAt,
|
||||||
notes = a.Notes,
|
notes = a.Notes,
|
||||||
|
activity = _db.activities
|
||||||
|
.Where(act => act.num == a.ActivityNum)
|
||||||
|
.Select(act => new
|
||||||
|
{
|
||||||
|
subject = act.subject
|
||||||
|
})
|
||||||
|
.FirstOrDefault(),
|
||||||
bookerName = a.BookerName,
|
bookerName = a.BookerName,
|
||||||
guest_count = _db.GuaDanOrderGuest
|
guest_count = _db.GuaDanOrderGuest
|
||||||
.Where(c => c.GuaDanOrderNo == a.GuaDanOrderNo && c.IsDeleted == false)
|
.Where(c => c.GuaDanOrderNo == a.GuaDanOrderNo && c.IsDeleted == false)
|
||||||
.Where(c => c.RegionRoomBedStatus.Code != GuaDanOrderGuest.STATUS_CANCELLED)
|
.Where(c => c.RegionRoomBedStatus.Code != GuaDanOrderGuest.STATUS_CANCELLED)
|
||||||
.Count(),
|
.Count(),
|
||||||
|
statusName = _db.GuaDanOrderGuest
|
||||||
|
.Where(g => g.GuaDanOrderNo == a.GuaDanOrderNo)
|
||||||
|
.All(g => g.StatusCode == "404") ? "預約" :
|
||||||
|
_db.GuaDanOrderGuest
|
||||||
|
.Where(g => g.GuaDanOrderNo == a.GuaDanOrderNo)
|
||||||
|
.All(g => g.StatusCode == "403") ? "全部退房" :
|
||||||
|
_db.GuaDanOrderGuest
|
||||||
|
.Where(g => g.GuaDanOrderNo == a.GuaDanOrderNo)
|
||||||
|
.Any(g => g.StatusCode == "401") ? "正在入住" :
|
||||||
|
"混合狀態"
|
||||||
})
|
})
|
||||||
.Skip((search.page - 1) * search.pageSize)
|
.Skip((search.page - 1) * search.pageSize)
|
||||||
.Take(search.pageSize)
|
.Take(search.pageSize)
|
||||||
@@ -81,7 +98,7 @@ public class guadanOrderController : ApiController
|
|||||||
.FirstOrDefaultAsync();
|
.FirstOrDefaultAsync();
|
||||||
if (order == null)
|
if (order == null)
|
||||||
{
|
{
|
||||||
return BadRequest("未找到对应订单");
|
return BadRequest("未找到對應訂單");
|
||||||
}
|
}
|
||||||
var result = new
|
var result = new
|
||||||
{
|
{
|
||||||
@@ -115,7 +132,7 @@ public class guadanOrderController : ApiController
|
|||||||
}
|
}
|
||||||
if (model.Uuid.HasValue)
|
if (model.Uuid.HasValue)
|
||||||
{
|
{
|
||||||
return BadRequest("已存在对应挂单资料");
|
return BadRequest("已存在對應掛單資料");
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -174,7 +191,7 @@ public class guadanOrderController : ApiController
|
|||||||
var order = await _db.GuaDanOrder.FindAsync(model.Uuid.Value);
|
var order = await _db.GuaDanOrder.FindAsync(model.Uuid.Value);
|
||||||
if (order == null)
|
if (order == null)
|
||||||
{
|
{
|
||||||
return BadRequest("未找到对应挂单资料");
|
return BadRequest("未找到對應掛單資料");
|
||||||
}
|
}
|
||||||
order.StartDate = model.startdate;
|
order.StartDate = model.startdate;
|
||||||
order.EndDate = model.enddate;
|
order.EndDate = model.enddate;
|
||||||
@@ -194,9 +211,9 @@ public class guadanOrderController : ApiController
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
if(_db.GuaDanOrderGuest.Any(a => a.GuaDanOrderNo == guadan.GuaDanOrderNo) )
|
if (_db.GuaDanOrderGuest.Any(a => a.GuaDanOrderNo == guadan.GuaDanOrderNo))
|
||||||
{
|
{
|
||||||
return BadRequest($"该挂单已经存在挂单莲友,不能取消!");
|
return BadRequest($"該掛單已經存在掛單蓮友,不能取消!");
|
||||||
}
|
}
|
||||||
using (var transaction = _db.Database.BeginTransaction())
|
using (var transaction = _db.Database.BeginTransaction())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -46,12 +46,13 @@ public class guadanOrderGuestController : ApiController
|
|||||||
checkoutat = a.CheckOutAt.HasValue ? a.CheckOutAt.Value.ToString("yyyy-MM-dd") : null,
|
checkoutat = a.CheckOutAt.HasValue ? a.CheckOutAt.Value.ToString("yyyy-MM-dd") : null,
|
||||||
phone = null,
|
phone = null,
|
||||||
roomName = a.Room.Name,
|
roomName = a.Room.Name,
|
||||||
bedName = a.RegionRoomBed.Name,
|
bedName = GetBedString(a.RegionRoomBed),
|
||||||
orderNo = a.GuaDanOrderNo,
|
orderNo = a.GuaDanOrderNo,
|
||||||
follower = a.followers == null ? null : new FollowerDto
|
follower = a.followers == null ? null : new FollowerDto
|
||||||
{
|
{
|
||||||
num = a.followers.num,
|
num = a.followers.num,
|
||||||
u_name = a.followers.u_name
|
u_name = a.followers.u_name,
|
||||||
|
sex = a.followers.sex
|
||||||
},
|
},
|
||||||
statuscode = a.StatusCode,
|
statuscode = a.StatusCode,
|
||||||
statusName = a.RegionRoomBedStatus?.Name,
|
statusName = a.RegionRoomBedStatus?.Name,
|
||||||
@@ -59,7 +60,22 @@ public class guadanOrderGuestController : ApiController
|
|||||||
|
|
||||||
return Ok(data);
|
return Ok(data);
|
||||||
}
|
}
|
||||||
|
public string GetBedString(RegionRoomBed bed)
|
||||||
|
{
|
||||||
|
if (bed == null)
|
||||||
|
return "";
|
||||||
|
var room = bed.Room;
|
||||||
|
var name = room.Name + "/" + bed.Name;
|
||||||
|
var region = room.Region;
|
||||||
|
name = region.Name + "/" + name;
|
||||||
|
var parentRegion = region.Region2;
|
||||||
|
while(parentRegion != null)
|
||||||
|
{
|
||||||
|
name = parentRegion.Name + "/" + name;
|
||||||
|
parentRegion = parentRegion.Region2;
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Route("api/guadanorderguest/create")]
|
[Route("api/guadanorderguest/create")]
|
||||||
public async Task<IHttpActionResult> create([FromBody] guadan_order_guest_dto model)
|
public async Task<IHttpActionResult> create([FromBody] guadan_order_guest_dto model)
|
||||||
@@ -650,6 +666,7 @@ public class guadanOrderGuestController : ApiController
|
|||||||
{
|
{
|
||||||
public int num { get; set; }
|
public int num { get; set; }
|
||||||
public string u_name { get; set; }
|
public string u_name { get; set; }
|
||||||
|
public string sex { get; set; }
|
||||||
}
|
}
|
||||||
public class XuZhuModel
|
public class XuZhuModel
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing.Drawing2D;
|
using System.Drawing.Drawing2D;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Web.Http;
|
using System.Web.Http;
|
||||||
using System.Web.Routing;
|
using System.Web.Routing;
|
||||||
@@ -39,7 +40,7 @@ public class regionController : ApiController
|
|||||||
var startDate = filter.StartDate.Date;
|
var startDate = filter.StartDate.Date;
|
||||||
var endDate = filter.EndDate.Date;
|
var endDate = filter.EndDate.Date;
|
||||||
|
|
||||||
var query = _db.Region//区域状态是否启用这里只设置了过滤了有客房的区域,是否要过滤所有
|
var query = _db.Region//區域狀態是否啟用這裡只設置了過濾了有客房的區域,是否要過濾所有
|
||||||
.Where(r => !r.IsDeleted)
|
.Where(r => !r.IsDeleted)
|
||||||
.Where(r => r.IsActive)
|
.Where(r => r.IsActive)
|
||||||
.Where(r => r.Room.Any());
|
.Where(r => r.Room.Any());
|
||||||
@@ -68,6 +69,7 @@ public class regionController : ApiController
|
|||||||
r.Uuid,
|
r.Uuid,
|
||||||
r.Name,
|
r.Name,
|
||||||
regionPath = r.Name,
|
regionPath = r.Name,
|
||||||
|
isStop = !IsRegionAvailable(r.Uuid),
|
||||||
Room = r.Room
|
Room = r.Room
|
||||||
.Where(room => filter.Gender == null || room.Gender == filter.Gender)
|
.Where(room => filter.Gender == null || room.Gender == filter.Gender)
|
||||||
.Where(room =>
|
.Where(room =>
|
||||||
@@ -149,6 +151,30 @@ public class regionController : ApiController
|
|||||||
Summary = summary,
|
Summary = summary,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
public bool IsRegionAvailable(Guid regionUuid)
|
||||||
|
{
|
||||||
|
var current = _db.Region.FirstOrDefault(r => r.Uuid == regionUuid);
|
||||||
|
while (current != null)
|
||||||
|
{
|
||||||
|
// 當前區域不可用就直接返回 false
|
||||||
|
if (!current.IsActive || current.IsDeleted)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 沒有父區域了,說明一路上都可用
|
||||||
|
if (!current.ParentUuid.HasValue)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 繼續往父區域走
|
||||||
|
current = _db.Region.FirstOrDefault(r => r.Uuid == current.ParentUuid.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 沒查到(極端情況,比如資料庫被改了)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 遞迴生成區域完整路徑
|
/// 遞迴生成區域完整路徑
|
||||||
@@ -228,25 +254,25 @@ public class regionController : ApiController
|
|||||||
{
|
{
|
||||||
var allRegions = _db.Region.ToList();
|
var allRegions = _db.Region.ToList();
|
||||||
|
|
||||||
// 根区域
|
// 根區域
|
||||||
var rootRegions = allRegions
|
var rootRegions = allRegions
|
||||||
.Where(r => r.ParentUuid == null)
|
.Where(r => r.ParentUuid == null)
|
||||||
.OrderBy(r => r.SortOrder)
|
.OrderBy(r => r.SortOrder)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// 生成树并按性别过滤
|
// 生成樹並按性別過濾
|
||||||
var tree = rootRegions
|
var tree = rootRegions
|
||||||
.Select(r => BuildRegionDtoByGender(r, allRegions, request.IsMale))
|
.Select(r => BuildRegionDtoByGender(r, allRegions, request.IsMale))
|
||||||
.Where(r => r != null) // 去掉没有房间的区域
|
.Where(r => r != null) // 去掉沒有房間的區域
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
return Ok(tree);
|
return Ok(tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据性别过滤房间的 BuildRegionDto
|
// 根據性別過濾房間的 BuildRegionDto
|
||||||
private RegionDto BuildRegionDtoByGender(Region region, List<Region> allRegions, bool? gender)
|
private RegionDto BuildRegionDtoByGender(Region region, List<Region> allRegions, bool? gender)
|
||||||
{
|
{
|
||||||
// 过滤房间按性别
|
// 過濾房間按性別
|
||||||
var rooms = region.Room?
|
var rooms = region.Room?
|
||||||
.Where(a => !gender.HasValue || a.Gender == gender.Value)
|
.Where(a => !gender.HasValue || a.Gender == gender.Value)
|
||||||
.Select(a => new RoomDto
|
.Select(a => new RoomDto
|
||||||
@@ -268,14 +294,14 @@ public class regionController : ApiController
|
|||||||
})
|
})
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// 递归生成子区域
|
// 遞迴生成子區域
|
||||||
var children = allRegions
|
var children = allRegions
|
||||||
.Where(r => r.ParentUuid == region.Uuid)
|
.Where(r => r.ParentUuid == region.Uuid)
|
||||||
.Select(child => BuildRegionDtoByGender(child, allRegions, gender))
|
.Select(child => BuildRegionDtoByGender(child, allRegions, gender))
|
||||||
.Where(c => c != null) // 去掉没有房间的子区域
|
.Where(c => c != null) // 去掉沒有房間的子區域
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// 如果这个区域既没有房间也没有子区域,则返回 null
|
// 如果這個區域既沒有房間也沒有子區域,則返回 null
|
||||||
if (!rooms.Any() && !children.Any())
|
if (!rooms.Any() && !children.Any())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -297,10 +323,10 @@ public class regionController : ApiController
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 请求模型
|
// 請求模型
|
||||||
public class GenderRequest
|
public class GenderRequest
|
||||||
{
|
{
|
||||||
public bool? IsMale { get; set; } // true = 男, false = 女, null = 不过滤
|
public bool? IsMale { get; set; } // true = 男, false = 女, null = 不過濾
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RoomDto
|
public class RoomDto
|
||||||
@@ -374,10 +400,28 @@ public class regionController : ApiController
|
|||||||
var region = _db.Region.FirstOrDefault(r => r.Uuid == dto.Uuid);
|
var region = _db.Region.FirstOrDefault(r => r.Uuid == dto.Uuid);
|
||||||
if (region == null)
|
if (region == null)
|
||||||
return NotFound();
|
return NotFound();
|
||||||
if(dto.RoomCount < region.Room.Count())
|
if (dto.RoomCount < region.Room.Count())
|
||||||
{
|
{
|
||||||
return BadRequest("客房數量小於已存在的客房數量");
|
return BadRequest("客房數量小於已存在的客房數量");
|
||||||
}
|
}
|
||||||
|
if (dto.IsActive == false)
|
||||||
|
{
|
||||||
|
var regionIds = GetAllRegionIds(region.Uuid);
|
||||||
|
var hasPendingBeds = _db.RegionRoomBed
|
||||||
|
.Where(b => regionIds.Contains(b.Room.RegionUuid))
|
||||||
|
.SelectMany(b => b.GuaDanOrderGuest)
|
||||||
|
.Any(g => !g.IsDeleted &&
|
||||||
|
(g.RegionRoomBedStatus.Code == GuaDanOrderGuest.STATUS_BOOKED || // 預約中
|
||||||
|
g.RegionRoomBedStatus.Code == GuaDanOrderGuest.STATUS_CHECKED_IN)); // 已入住
|
||||||
|
if (hasPendingBeds)
|
||||||
|
{
|
||||||
|
return Content(HttpStatusCode.BadRequest, new
|
||||||
|
{
|
||||||
|
code = "BED_IS_USED",
|
||||||
|
message = "該區域有床位正在掛單中,請先處理"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
region.Name = dto.Name;
|
region.Name = dto.Name;
|
||||||
region.Description = dto.Description;
|
region.Description = dto.Description;
|
||||||
region.SortOrder = dto.SortOrder;
|
region.SortOrder = dto.SortOrder;
|
||||||
@@ -416,6 +460,25 @@ public class regionController : ApiController
|
|||||||
return Ok(new { message = "刪除成功" });
|
return Ok(new { message = "刪除成功" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Guid> GetAllRegionIds(Guid regionUuid)
|
||||||
|
{
|
||||||
|
var regionIds = new List<Guid> { regionUuid };
|
||||||
|
|
||||||
|
var children = _db.Region
|
||||||
|
.Where(r => r.ParentUuid == regionUuid)
|
||||||
|
.Select(r => r.Uuid)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
foreach (var childId in children)
|
||||||
|
{
|
||||||
|
regionIds.AddRange(GetAllRegionIds(childId));
|
||||||
|
}
|
||||||
|
|
||||||
|
return regionIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 遞迴刪除子節點
|
// 遞迴刪除子節點
|
||||||
private void DeleteRegionRecursive(Region region)
|
private void DeleteRegionRecursive(Region region)
|
||||||
{
|
{
|
||||||
@@ -438,7 +501,7 @@ public class regionController : ApiController
|
|||||||
[Route("api/region/regionwithroom")]
|
[Route("api/region/regionwithroom")]
|
||||||
public IHttpActionResult GetRegionWithRoom()
|
public IHttpActionResult GetRegionWithRoom()
|
||||||
{
|
{
|
||||||
//返回有房间的region
|
//返回有房間的region
|
||||||
var data = _db.Region.Where(a => a.Room.Count() > 0)
|
var data = _db.Region.Where(a => a.Room.Count() > 0)
|
||||||
.Select(r => new
|
.Select(r => new
|
||||||
{
|
{
|
||||||
@@ -459,7 +522,7 @@ public class regionController : ApiController
|
|||||||
[Route("api/room/roomwithbed")]
|
[Route("api/room/roomwithbed")]
|
||||||
public IHttpActionResult GetRoomWithBed(Guid? RegionUuid = null)
|
public IHttpActionResult GetRoomWithBed(Guid? RegionUuid = null)
|
||||||
{
|
{
|
||||||
//获取所有有床位的房间
|
//獲取所有有床位的房間
|
||||||
var query = _db.Room
|
var query = _db.Room
|
||||||
.Select(r => new
|
.Select(r => new
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data.Entity;
|
using System.Data.Entity;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Web.Http;
|
using System.Web.Http;
|
||||||
@@ -66,7 +67,7 @@ public class regionRoomBedController : ApiController
|
|||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
bool canUsed = !bedSchedules.Any();
|
bool canUsed = !bedSchedules.Any();
|
||||||
|
bool bedIsStop = IsBedStopped(a);
|
||||||
return new
|
return new
|
||||||
{
|
{
|
||||||
a.Uuid,
|
a.Uuid,
|
||||||
@@ -76,6 +77,7 @@ public class regionRoomBedController : ApiController
|
|||||||
a.StatusCode,
|
a.StatusCode,
|
||||||
a.RoomUuid,
|
a.RoomUuid,
|
||||||
canUsed,
|
canUsed,
|
||||||
|
bedIsStop,
|
||||||
schedule = bedSchedules
|
schedule = bedSchedules
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -83,6 +85,33 @@ public class regionRoomBedController : ApiController
|
|||||||
|
|
||||||
return Ok(data);
|
return Ok(data);
|
||||||
}
|
}
|
||||||
|
public bool IsBedStopped(RegionRoomBed bed)
|
||||||
|
{
|
||||||
|
// 1️⃣ 床位本身不可用
|
||||||
|
if (!bed.IsActive || bed.IsDeleted)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// 2️⃣ 所属房间不可用
|
||||||
|
var room = bed.Room;
|
||||||
|
if (room == null || !room.IsActive.Value || room.IsDeleted)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// 3️⃣ 所属区域不可用
|
||||||
|
var region = room.Region;
|
||||||
|
while (region != null)
|
||||||
|
{
|
||||||
|
if (!region.IsActive || region.IsDeleted)
|
||||||
|
return true; // 有任意一级区域不可用就返回 true
|
||||||
|
|
||||||
|
if (!region.ParentUuid.HasValue)
|
||||||
|
break; // 到顶层了
|
||||||
|
|
||||||
|
region = _db.Region.FirstOrDefault(r => r.Uuid == region.ParentUuid.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4️⃣ 全部检查通过 → 床位可用
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Route("api/region/bed/create")]
|
[Route("api/region/bed/create")]
|
||||||
@@ -147,6 +176,20 @@ public class regionRoomBedController : ApiController
|
|||||||
{
|
{
|
||||||
return BadRequest("床為性別和房間性別必須一致");
|
return BadRequest("床為性別和房間性別必須一致");
|
||||||
}
|
}
|
||||||
|
if (bed.IsActive == false)
|
||||||
|
{
|
||||||
|
var hasPendingBeds = oldBed.GuaDanOrderGuest.Any(g => !g.IsDeleted &&
|
||||||
|
(g.RegionRoomBedStatus.Code == GuaDanOrderGuest.STATUS_BOOKED || // 预约中
|
||||||
|
g.RegionRoomBedStatus.Code == GuaDanOrderGuest.STATUS_CHECKED_IN));
|
||||||
|
if (hasPendingBeds)
|
||||||
|
{
|
||||||
|
return Content(HttpStatusCode.BadRequest, new
|
||||||
|
{
|
||||||
|
code = "BED_IS_USED",
|
||||||
|
message = "該床位正在掛單中,請先處理"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
oldBed.StatusCode = bed.StatusCode;
|
oldBed.StatusCode = bed.StatusCode;
|
||||||
oldBed.IsActive = bed.IsActive;
|
oldBed.IsActive = bed.IsActive;
|
||||||
oldBed.Name = bed.Name;
|
oldBed.Name = bed.Name;
|
||||||
@@ -158,18 +201,38 @@ public class regionRoomBedController : ApiController
|
|||||||
}
|
}
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Route("api/region/bed/delete")]
|
[Route("api/region/bed/delete")]
|
||||||
public IHttpActionResult delete([FromUri] Guid uuid)
|
public IHttpActionResult Delete([FromUri] Guid uuid)
|
||||||
{
|
{
|
||||||
var bed = _db.RegionRoomBed.Find(uuid);
|
var bed = _db.RegionRoomBed.Find(uuid);
|
||||||
if (bed == null)
|
if (bed == null)
|
||||||
{
|
{
|
||||||
return BadRequest("未找到床位");
|
return BadRequest("未找到床位");
|
||||||
}
|
}
|
||||||
_db.RegionRoomBed.Remove(bed);
|
|
||||||
_db.SaveChanges();
|
try
|
||||||
return Ok(new { message = "刪除成功" });
|
{
|
||||||
|
_db.RegionRoomBed.Remove(bed);
|
||||||
|
_db.SaveChanges();
|
||||||
|
return Ok(new { message = "刪除成功" });
|
||||||
|
}
|
||||||
|
catch (System.Data.Entity.Infrastructure.DbUpdateException ex)
|
||||||
|
{
|
||||||
|
// 判斷是否為外鍵關聯錯誤
|
||||||
|
if (ex.InnerException?.InnerException is System.Data.SqlClient.SqlException sqlEx &&
|
||||||
|
(sqlEx.Number == 547)) // 547 = SQL Server 外鍵違反錯誤碼
|
||||||
|
{
|
||||||
|
return BadRequest("刪除失敗:該床位已被使用或存在關聯資料,無法刪除。");
|
||||||
|
}
|
||||||
|
|
||||||
|
return InternalServerError(ex); // 其他資料庫錯誤
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return InternalServerError(ex); // 其他未預期錯誤
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Route("api/region/bed/getavailablebedcountbytime")]
|
[Route("api/region/bed/getavailablebedcountbytime")]
|
||||||
public async Task<IHttpActionResult> GetCanUseBedCountByTime(DateTime startTime, DateTime endTime)
|
public async Task<IHttpActionResult> GetCanUseBedCountByTime(DateTime startTime, DateTime endTime)
|
||||||
@@ -192,6 +255,7 @@ public class regionRoomBedController : ApiController
|
|||||||
|
|
||||||
// 可用床位 = 所有床位 - 忙碌床位
|
// 可用床位 = 所有床位 - 忙碌床位
|
||||||
var availableBeds = _db.RegionRoomBed
|
var availableBeds = _db.RegionRoomBed
|
||||||
|
.Where(b => b.IsActive)
|
||||||
.Where(b => !busyBedUuids.Contains(b.Uuid));
|
.Where(b => !busyBedUuids.Contains(b.Uuid));
|
||||||
|
|
||||||
var result = await availableBeds
|
var result = await availableBeds
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System.Collections.Generic;
|
|||||||
using System.Data.Entity;
|
using System.Data.Entity;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.ServiceModel.Channels;
|
using System.ServiceModel.Channels;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
@@ -99,6 +100,23 @@ public class regionRoomController : ApiController
|
|||||||
{
|
{
|
||||||
return BadRequest("請輸入床位數量");
|
return BadRequest("請輸入床位數量");
|
||||||
}
|
}
|
||||||
|
if (room.IsActive == false)
|
||||||
|
{
|
||||||
|
var hasPendingBeds = oldRoom.RegionRoomBed
|
||||||
|
.SelectMany(b => b.GuaDanOrderGuest)
|
||||||
|
.Any(g => !g.IsDeleted &&
|
||||||
|
(g.RegionRoomBedStatus.Code == GuaDanOrderGuest.STATUS_BOOKED || // 预约中
|
||||||
|
g.RegionRoomBedStatus.Code == GuaDanOrderGuest.STATUS_CHECKED_IN)); // 已入住
|
||||||
|
if (hasPendingBeds)
|
||||||
|
{
|
||||||
|
return Content(HttpStatusCode.BadRequest, new
|
||||||
|
{
|
||||||
|
code = "BED_IS_USED",
|
||||||
|
message = "該房间有床位正在掛單中,請先處理"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
oldRoom.Name = room.Name;
|
oldRoom.Name = room.Name;
|
||||||
oldRoom.BedCount = room.BedCount;
|
oldRoom.BedCount = room.BedCount;
|
||||||
oldRoom.Gender = room.Gender;
|
oldRoom.Gender = room.Gender;
|
||||||
|
|||||||
@@ -94,6 +94,10 @@
|
|||||||
<template v-slot:item.name="{item}">
|
<template v-slot:item.name="{item}">
|
||||||
{{item.follower?.u_name}}
|
{{item.follower?.u_name}}
|
||||||
</template>
|
</template>
|
||||||
|
<template v-slot:item.sex="{item}">
|
||||||
|
{{item.follower?.sex}}
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #item.actions="{ item }">
|
<template #item.actions="{ item }">
|
||||||
<div>
|
<div>
|
||||||
<!-- 取消預訂 -->
|
<!-- 取消預訂 -->
|
||||||
@@ -325,13 +329,13 @@
|
|||||||
<div v-for="bed in region_modal.currentSelectBeds" :key="bed.uuid" @click="selectBed(bed)" style="padding: 8px; border: 1px solid #d9d9d9; cursor: pointer; max-height: 250px;" :style="{
|
<div v-for="bed in region_modal.currentSelectBeds" :key="bed.uuid" @click="selectBed(bed)" style="padding: 8px; border: 1px solid #d9d9d9; cursor: pointer; max-height: 250px;" :style="{
|
||||||
backgroundColor: region_modal.currentSelectBed?.uuid === bed.uuid
|
backgroundColor: region_modal.currentSelectBed?.uuid === bed.uuid
|
||||||
? '#bae7ff' // 當前選中
|
? '#bae7ff' // 當前選中
|
||||||
: (bed.canUsed ? '#f6ffed' : '#fff1f0'), // 可用綠色,不可用紅色
|
: ((bed.canUsed && bed.isActive && !bed.bedIsStop) ? '#f6ffed' : '#fff1f0'), // 可用綠色,不可用紅色
|
||||||
color: bed.canUsed ? 'black' : '#999', // 不可用時灰色文字
|
color: (bed.canUsed && bed.isActive && !bed.bedIsStop) ? 'black' : '#999', // 不可用時灰色文字
|
||||||
pointerEvents: bed.canUsed ? 'auto' : 'none' // 不可用時無法點擊
|
pointerEvents: (bed.canUsed && bed.isActive && !bed.bedIsStop) ? 'auto' : 'none' // 不可用時無法點擊
|
||||||
}">
|
}">
|
||||||
<div style="font-weight: 500;">{{ bed.name }}</div>
|
<div style="font-weight: 500;">{{ bed.name }}</div>
|
||||||
<div style="margin-top: 4px; font-size: 12px;">
|
<div style="margin-top: 4px; font-size: 12px;">
|
||||||
{{ bed.canUsed ? '可用' : '不可用' }}
|
{{ (!bed.isActive || bed.bedIsStop) ? '停用' : (bed.canUsed ? '可用' : '不可用') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@@ -884,6 +888,10 @@
|
|||||||
text: '姓名',
|
text: '姓名',
|
||||||
value: 'name'
|
value: 'name'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
text: '性別',
|
||||||
|
value: 'sex'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
text: '掛單開始時間',
|
text: '掛單開始時間',
|
||||||
value: 'checkinat'
|
value: 'checkinat'
|
||||||
@@ -892,10 +900,6 @@
|
|||||||
text: '掛單結束時間',
|
text: '掛單結束時間',
|
||||||
value: 'checkoutat'
|
value: 'checkoutat'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
text: '房間',
|
|
||||||
value: 'roomName'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
text: '床位',
|
text: '床位',
|
||||||
value: 'bedName'
|
value: 'bedName'
|
||||||
|
|||||||
@@ -51,6 +51,9 @@
|
|||||||
<template #item.created_at="{item}">
|
<template #item.created_at="{item}">
|
||||||
{{item.created_at | timeString('YYYY/MM/DD HH:mm')}}
|
{{item.created_at | timeString('YYYY/MM/DD HH:mm')}}
|
||||||
</template>
|
</template>
|
||||||
|
<template #item.activity="{item}">
|
||||||
|
{{item.activity?.subject}}
|
||||||
|
</template>
|
||||||
</v-data-table>
|
</v-data-table>
|
||||||
<v-container>
|
<v-container>
|
||||||
<v-row class="align-baseline" wrap="false">
|
<v-row class="align-baseline" wrap="false">
|
||||||
@@ -114,7 +117,7 @@
|
|||||||
{ text: '掛單人數', value: 'guest_count' },
|
{ text: '掛單人數', value: 'guest_count' },
|
||||||
{ text: '狀態', value: 'statusName', align: 'center' },
|
{ text: '狀態', value: 'statusName', align: 'center' },
|
||||||
{ text: '建立時間', value: 'created_at', align: 'center' },
|
{ text: '建立時間', value: 'created_at', align: 'center' },
|
||||||
{ text: '備註', value: 'notes', align: 'center' },
|
{ text: '關聯活動', value: 'activity', align: 'center' },
|
||||||
{ text: '操作', value: 'actions', align: 'center' }
|
{ text: '操作', value: 'actions', align: 'center' }
|
||||||
],
|
],
|
||||||
options: {
|
options: {
|
||||||
|
|||||||
@@ -108,8 +108,9 @@
|
|||||||
|
|
||||||
</asp:Content>
|
</asp:Content>
|
||||||
<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
|
<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
|
||||||
<div v-for="region in regions" :key="region.uuid" class="region-block mb-4">
|
<div v-for="region in regions" :key="region.uuid" class="region-block mb-4"
|
||||||
<h2 class="region-title mb-3">{{ region.regionPath }}</h2>
|
:style="region.isStop ? { pointerEvents: 'none', opacity: '0.6', backgroundColor: '#f8d7da' } : {}">
|
||||||
|
<h2 class="region-title mb-3">{{region.isStop?(region.regionPath + '(已停用)'): region.regionPath }}</h2>
|
||||||
|
|
||||||
<div class="row g-3 justify-content-start">
|
<div class="row g-3 justify-content-start">
|
||||||
<div v-for="room in region.room" :key="room.ruid" class="col-12 col-md-6 col-lg-6">
|
<div v-for="room in region.room" :key="room.ruid" class="col-12 col-md-6 col-lg-6">
|
||||||
@@ -319,6 +320,14 @@
|
|||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.regions = res.data.regions;
|
this.regions = res.data.regions;
|
||||||
this.summary = res.data.summary; // 保存後端統計
|
this.summary = res.data.summary; // 保存後端統計
|
||||||
|
try {
|
||||||
|
this.regions.sort((a, b) => {
|
||||||
|
return Number(a.isStop) - Number(b.isStop);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error('API 錯誤', err);
|
console.error('API 錯誤', err);
|
||||||
|
|||||||
217
web/admin/region/handle_bed_in_used.aspx
Normal file
217
web/admin/region/handle_bed_in_used.aspx
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
<%@ Page Title="" Language="C#" MasterPageFile="~/admin/Templates/TBS5ADM001/MasterPage.master" AutoEventWireup="true" CodeFile="handle_bed_in_used.aspx.cs" Inherits="admin_region_handle_bed_in_used" %>
|
||||||
|
|
||||||
|
<asp:Content ID="Content1" ContentPlaceHolderID="page_header" Runat="Server">
|
||||||
|
</asp:Content>
|
||||||
|
<asp:Content ID="Content2" ContentPlaceHolderID="page_nav" Runat="Server">
|
||||||
|
<nav>
|
||||||
|
<div>
|
||||||
|
<label style="display: inline-block;">區域:</label>
|
||||||
|
<select style="display: inline-block; min-width:150px; max-width:20%;"
|
||||||
|
class="form-select"
|
||||||
|
v-model="selectedRegionUuid"
|
||||||
|
:disabled="isFromUrl"
|
||||||
|
@change="onRegionChange"
|
||||||
|
><option :value="null">請選擇區域</option>
|
||||||
|
<option
|
||||||
|
v-for="region in regions"
|
||||||
|
:key="region.uuid"
|
||||||
|
:value="region.uuid"
|
||||||
|
>
|
||||||
|
{{ region.name }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<label style="display: inline-block;margin-left: 20px;">客房:</label>
|
||||||
|
<select style="display: inline-block; min-width:200px; max-width:20%;"
|
||||||
|
class="form-select"
|
||||||
|
v-model="selectedRoomUuid"
|
||||||
|
:disabled="isFromUrl"
|
||||||
|
@change="onRoomChange"
|
||||||
|
>
|
||||||
|
<option :value="null">請選擇房間</option>
|
||||||
|
<option v-for="room in rooms" :key="room.uuid" :value="room.uuid">{{room.fullName}}</option>
|
||||||
|
</select>
|
||||||
|
<label style="display: inline-block;margin-left: 20px;">床位:</label>
|
||||||
|
<select style="display: inline-block; width:100px;"
|
||||||
|
class="form-select"
|
||||||
|
v-model="selectedBedUuid"
|
||||||
|
:disabled="isFromUrl"
|
||||||
|
></select>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
</asp:Content>
|
||||||
|
<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
|
||||||
|
<div>
|
||||||
|
<v-data-table
|
||||||
|
:items="items"
|
||||||
|
show-select
|
||||||
|
v-model:selected="selectedItems"
|
||||||
|
item-key="bedUuid"
|
||||||
|
|
||||||
|
:headers="headers">
|
||||||
|
<template #item.actions="{item}">
|
||||||
|
<button class="btn btn-outline-danger" type="button" @click="confirmAndCancelSingleBedBooking(item)">取消預約</button>
|
||||||
|
</template>
|
||||||
|
<template #item.guadan_during="{item}">
|
||||||
|
{{item.guadan_during.checkInAt|timeString('YYYY-MM-DD')}} - {{item.guadan_during.checkOutAt|timeString('YYYY-MM-DD')}}
|
||||||
|
</template>
|
||||||
|
<template #item.status="{item}">
|
||||||
|
{{item.status.name}}
|
||||||
|
</template>
|
||||||
|
</v-data-table>
|
||||||
|
</div>
|
||||||
|
<!-- 更新修改確認彈出視窗 -->
|
||||||
|
<message-modal ref="messageModal"></message-modal>
|
||||||
|
<!-- 刪除確認彈出視窗 -->
|
||||||
|
<confirm-modal ref="confirmModal"></confirm-modal>
|
||||||
|
</asp:Content>
|
||||||
|
<asp:Content ID="Content4" ContentPlaceHolderID="offCanvasRight" Runat="Server">
|
||||||
|
</asp:Content>
|
||||||
|
<asp:Content ID="Content5" ContentPlaceHolderID="footer_script" Runat="Server">
|
||||||
|
<script>
|
||||||
|
Vue.filter('timeString', function (value, myFormat) {
|
||||||
|
return value == null || value == "" ? "" : moment(value).format(myFormat || 'YYYY-MM-DD, HH:mm:ss');
|
||||||
|
});
|
||||||
|
new Vue({
|
||||||
|
el: '#app',
|
||||||
|
vuetify: new Vuetify(vuetify_options),
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
regionUuidFromUrl: '<%= Request.QueryString["region"] %>' || null,
|
||||||
|
roomUuidFromUrl: '<%= Request.QueryString["room"] %>' || null,
|
||||||
|
bedUuidFromUrl: '<%= Request.QueryString["bed"] %>' || null,
|
||||||
|
// 用戶選擇的值
|
||||||
|
selectedRegionUuid: null,
|
||||||
|
selectedRoomUuid: null,
|
||||||
|
selectedBedUuid: null,
|
||||||
|
regions: [],
|
||||||
|
rooms: [],
|
||||||
|
bed: [],
|
||||||
|
selectedItems: [],
|
||||||
|
items: [],
|
||||||
|
headers: [
|
||||||
|
{ text: '床位名稱', value: 'fullName' },
|
||||||
|
{ text: '掛單號:', value: 'guaDanOrderNo' },
|
||||||
|
{ text: '掛單人', value: 'u_name' },
|
||||||
|
{ text: '掛單時間', value: 'guadan_during' },
|
||||||
|
{ text: '掛單狀態', value: 'status' },
|
||||||
|
{ text: '', value: 'actions' },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onRegionChange() {
|
||||||
|
console.log("選擇的區域 UUID:", this.selectedRegionUuid);
|
||||||
|
this.selectedRoomUuid = null;
|
||||||
|
this.selectedBedUuid = null;
|
||||||
|
this.GetInUsedBed();
|
||||||
|
this.GetRoomList();
|
||||||
|
},
|
||||||
|
onRoomChange() {
|
||||||
|
console.log("選擇的客房 UUID:", this.selectedRoomUuid);
|
||||||
|
this.GetInUsedBed();
|
||||||
|
},
|
||||||
|
async GetInUsedBed() {
|
||||||
|
//獲取已經預約或者入住的床位
|
||||||
|
try {
|
||||||
|
const payload = {
|
||||||
|
regionUuid: this.selectedRegionUuid || null,
|
||||||
|
roomUuid: this.selectedRoomUuid || null,
|
||||||
|
bedUuid: this.selectedBedUuid || null
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await axios.post(HTTP_HOST + "api/bed/inuse/list", payload);
|
||||||
|
|
||||||
|
// 假設返回的就是床位數組
|
||||||
|
this.items = response.data;
|
||||||
|
|
||||||
|
console.log("已獲取床位:");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("獲取床位失敗:", error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async confirmAndCancelSingleBedBooking(item) {
|
||||||
|
// 先彈出確認彈出視窗
|
||||||
|
this.$refs.confirmModal.open({
|
||||||
|
message: `確定要取消床位 ${item.name || ''} 的所有預約嗎?`,
|
||||||
|
onConfirm: async () => {
|
||||||
|
try {
|
||||||
|
const payload = {
|
||||||
|
bedUuid: item.bedUuid || null
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await axios.post(
|
||||||
|
HTTP_HOST + "api/bed/inuse/cancel/singlebed/booking",
|
||||||
|
payload
|
||||||
|
);
|
||||||
|
|
||||||
|
// 刷新床位列表
|
||||||
|
this.GetInUsedBed();
|
||||||
|
|
||||||
|
// 成功提示
|
||||||
|
console.log("取消成功:", item.bedUuid);
|
||||||
|
this.$refs.messageModal.open({
|
||||||
|
title: '取消成功',
|
||||||
|
message: response?.data?.message || '取消成功!',
|
||||||
|
status: 'success'
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("取消失敗:", error);
|
||||||
|
this.$refs.messageModal.open({
|
||||||
|
title: '取消失敗',
|
||||||
|
message: error.response?.data?.message || '取消過程中發生錯誤!',
|
||||||
|
status: 'error'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async CancelAllBedBooking() {
|
||||||
|
//取消符合條件的所有床位的所有預約
|
||||||
|
},
|
||||||
|
async GetRegionList() {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(
|
||||||
|
HTTP_HOST + "api/bed/inuse/region/list"
|
||||||
|
);
|
||||||
|
this.regions = response.data;
|
||||||
|
} catch (error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async GetRoomList() {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(
|
||||||
|
HTTP_HOST + "api/bed/inuse/room/list", {
|
||||||
|
params: {
|
||||||
|
regionUuid: this.selectedRegionUuid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
this.rooms = response.data;
|
||||||
|
} catch (error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.selectedRegionUuid = this.regionUuidFromUrl;
|
||||||
|
this.selectedRoomUuid = this.roomUuidFromUrl;
|
||||||
|
this.selectedBedUuid = this.bedUuidFromUrl;
|
||||||
|
this.GetInUsedBed();
|
||||||
|
this.GetRegionList();
|
||||||
|
this.GetRoomList();
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 判斷是否來自 URL,禁用下拉框
|
||||||
|
isFromUrl() {
|
||||||
|
return this.regionUuidFromUrl || this.roomUuidFromUrl || this.bedUuidFromUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</asp:Content>
|
||||||
14
web/admin/region/handle_bed_in_used.aspx.cs
Normal file
14
web/admin/region/handle_bed_in_used.aspx.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Web;
|
||||||
|
using System.Web.UI;
|
||||||
|
using System.Web.UI.WebControls;
|
||||||
|
|
||||||
|
public partial class admin_region_handle_bed_in_used : MyWeb.config
|
||||||
|
{
|
||||||
|
protected void Page_Load(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -252,7 +252,7 @@
|
|||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label">狀態</label>
|
<label class="form-label">狀態</label>
|
||||||
<select class="form-control" v-model="room_bed.newBedForm.statuscode">
|
<select class="form-control" v-model="room_bed.newBedForm.statuscode" disabled>
|
||||||
<option v-for="status in room_bed.bed_status" :value="status.code">
|
<option v-for="status in room_bed.bed_status" :value="status.code">
|
||||||
{{status.name}}
|
{{status.name}}
|
||||||
</option>
|
</option>
|
||||||
@@ -349,6 +349,23 @@
|
|||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
|
|
||||||
|
<!-- 停用區域如果有床位正在掛單提示彈出視窗 -->
|
||||||
|
<div v-if="bed_is_used_modal" style="position:fixed; top:0; left:0; width:100%; height:100%;
|
||||||
|
background:rgba(0,0,0,0.5); display:flex; align-items:center; justify-content:center; z-index:9999;">
|
||||||
|
<div style="background:#fff; padding:20px; border-radius:8px; width:300px; text-align:center;">
|
||||||
|
<p style="margin-bottom:15px;">{{bed_is_used_modal_message}}</p>
|
||||||
|
<div style="display:flex; justify-content:flex-end; gap:10px;">
|
||||||
|
<button @click="closeBedInUsedModal"
|
||||||
|
class="btn btn-danger"
|
||||||
|
type="button" style="padding:6px 12px; border:none; border-radius:4px; cursor:pointer;">关闭</button>
|
||||||
|
<a :href="bed_is_used_modal_link" target="_blank" class="btn btn-primary">
|
||||||
|
前往处理
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 更新修改確認彈出視窗 -->
|
<!-- 更新修改確認彈出視窗 -->
|
||||||
<message-modal ref="messageModal"></message-modal>
|
<message-modal ref="messageModal"></message-modal>
|
||||||
<!-- 刪除確認彈出視窗 -->
|
<!-- 刪除確認彈出視窗 -->
|
||||||
@@ -477,13 +494,14 @@
|
|||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
el: '#app',
|
el: '#app',
|
||||||
vuetify: new Vuetify(vuetify_options),
|
vuetify: new Vuetify(vuetify_options),
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
bed_is_used_modal: false,
|
||||||
|
bed_is_used_modal_message: null,
|
||||||
|
bed_is_used_modal_link: "handle_bed_in_used.aspx", // 默认链接
|
||||||
selectedId: null, // 被選中項目ID
|
selectedId: null, // 被選中項目ID
|
||||||
selectedType: null, // 'region' 或 'room'
|
selectedType: null, // 'region' 或 'room'
|
||||||
expandAllFlag: false, // 控制全部展開
|
expandAllFlag: false, // 控制全部展開
|
||||||
@@ -546,6 +564,11 @@
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
closeBedInUsedModal() {
|
||||||
|
this.bed_is_used_modal = false;
|
||||||
|
this.bed_is_used_modal_message = null;
|
||||||
|
this.bed_is_used_modal_link = "handle_bed_in_used.aspx"; // 默认链接
|
||||||
|
},
|
||||||
expandAll() {
|
expandAll() {
|
||||||
this.expandAllFlag = true;
|
this.expandAllFlag = true;
|
||||||
this.collapseAllFlag = false;
|
this.collapseAllFlag = false;
|
||||||
@@ -634,7 +657,10 @@
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const url = this.form.uuid ? '/api/region/update' : '/api/region/create';
|
const url = this.form.uuid
|
||||||
|
? HTTP_HOST + '/api/region/update'
|
||||||
|
: HTTP_HOST + '/api/region/create';
|
||||||
|
|
||||||
axios.post(url, this.form)
|
axios.post(url, this.form)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
//alert('儲存成功');
|
//alert('儲存成功');
|
||||||
@@ -649,10 +675,20 @@
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.$refs.messageModal.open({
|
console.error('更新失敗', error);
|
||||||
title: '更新提示',
|
const code = error.response?.data?.code;
|
||||||
message: error.response?.data?.message || "儲存失敗,請稍後再試。",
|
const message = error.response?.data?.message || error.message ||
|
||||||
});
|
"未知錯誤,請稍後再試";
|
||||||
|
if (code === "BED_IS_USED") {
|
||||||
|
this.bed_is_used_modal = true;
|
||||||
|
this.bed_is_used_modal_message = message
|
||||||
|
this.bed_is_used_modal_link = this.bed_is_used_modal_link + '?region=' + this.form.uuid
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this.$refs.messageModal.open({
|
||||||
|
message: (message)
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
deleteRegion() {
|
deleteRegion() {
|
||||||
@@ -665,7 +701,7 @@
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
confirmDeleteRegion() {
|
confirmDeleteRegion() {
|
||||||
axios.post('/api/region/delete', { Uuid: this.form.uuid })
|
axios.post(HTTP_HOST + 'api/region/delete', { Uuid: this.form.uuid })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.showDeleteModal = false;
|
this.showDeleteModal = false;
|
||||||
this.$refs.messageModal.open({
|
this.$refs.messageModal.open({
|
||||||
@@ -717,7 +753,7 @@
|
|||||||
uuid: null,
|
uuid: null,
|
||||||
RoomUuid: this.currentSelectRoom.uuid,
|
RoomUuid: this.currentSelectRoom.uuid,
|
||||||
Name: '',
|
Name: '',
|
||||||
statuscode: null,
|
statuscode: "101",
|
||||||
IsActive: true,
|
IsActive: true,
|
||||||
Gender: this.currentSelectRoom.gender, // 不設預設值,強制選擇
|
Gender: this.currentSelectRoom.gender, // 不設預設值,強制選擇
|
||||||
};
|
};
|
||||||
@@ -732,7 +768,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
var res = await axios.post('/api/region/bed/create', this.room_bed.newBedForm);
|
var res = await axios.post(HTTP_HOST + 'api/region/bed/create', this.room_bed.newBedForm);
|
||||||
this.room_bed.showBedModal = false;
|
this.room_bed.showBedModal = false;
|
||||||
this.$refs.messageModal.open({
|
this.$refs.messageModal.open({
|
||||||
title: '成功',
|
title: '成功',
|
||||||
@@ -825,12 +861,20 @@
|
|||||||
await this.loadRegions();
|
await this.loadRegions();
|
||||||
this.room_bed.bed_items = this.currentSelectRoom.beds;
|
this.room_bed.bed_items = this.currentSelectRoom.beds;
|
||||||
//this.selectRegion(this.findRegionById(this.regions, this.form.id));
|
//this.selectRegion(this.findRegionById(this.regions, this.form.id));
|
||||||
} catch (err) {
|
} catch (error) {
|
||||||
console.log(err)
|
console.error('更新失敗', error);
|
||||||
this.$refs.messageModal.open({
|
const code = error.response?.data?.code;
|
||||||
title: '錯誤',
|
const message = error.response?.data?.message || error.message ||
|
||||||
message: err.response?.data?.message || '更新失敗'
|
"未知錯誤,請稍後再試";
|
||||||
});
|
if (code === "BED_IS_USED") {
|
||||||
|
this.bed_is_used_modal = true;
|
||||||
|
this.bed_is_used_modal_message = message;
|
||||||
|
this.bed_is_used_modal_link = this.bed_is_used_modal_link + '?bed=' + this.room_bed.newBedForm.uuid
|
||||||
|
} else {
|
||||||
|
this.$refs.messageModal.open({
|
||||||
|
message: (message)
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getBedStatus() {
|
getBedStatus() {
|
||||||
@@ -887,9 +931,18 @@
|
|||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('更新失敗', error);
|
console.error('更新失敗', error);
|
||||||
this.$refs.messageModal.open({
|
const code = error.response?.data?.code;
|
||||||
message: (error.response?.data?.message || error.message)
|
const message = error.response?.data?.message || error.message ||
|
||||||
});
|
"未知錯誤,請稍後再試";
|
||||||
|
if (code === "BED_IS_USED") {
|
||||||
|
this.bed_is_used_modal = true;
|
||||||
|
this.bed_is_used_modal_message = message;
|
||||||
|
this.bed_is_used_modal_link = this.bed_is_used_modal_link + '?room=' + this.room.room_form.uuid
|
||||||
|
} else {
|
||||||
|
this.$refs.messageModal.open({
|
||||||
|
message: (message)
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user