using DocumentFormat.OpenXml.EMMA; using DocumentFormat.OpenXml.Office.CustomUI; using DocumentFormat.OpenXml.Wordprocessing; using Microsoft.AspNet.SignalR; using Model; using Org.BouncyCastle.Asn1.Ocsp; using System; using System.Collections.Generic; using System.Data.Entity; using System.Linq; using System.Threading.Tasks; using System.Web; using System.Web.Http; /// /// regionRoomBedController 的摘要描述 /// [ezAuthorize] public class regionRoomBedController : ApiController { private Model.ezEntities _db = new Model.ezEntities(); public regionRoomBedController() { // // TODO: 在這裡新增建構函式邏輯 // } [HttpGet] [Route("api/region/room/bed/list")] public IHttpActionResult GetRegionRoomBedListByRoomId(Guid? roomUuid, DateTime StartTime, DateTime? EndTime) { if (StartTime == null || EndTime == null) return BadRequest("时间不能为空"); if (roomUuid == null) return BadRequest("roomId不能为空"); // 先取出床位 var beds = _db.RegionRoomBed .Where(a => a.RoomUuid == roomUuid) .ToList(); // 取出所有相关排程 var schedules = _db.RegionAndRoomAndBedSchedule .Where(b => b.IsDeleted == false && b.IsActive) .ToList(); var data = beds.Select(a => { // 在内存中处理日期比较 var bedSchedules = schedules .Where(b => b.TargetUuid == a.Uuid && (b.ScheduleDate == null // 长期占用 || (b.ScheduleDate >= StartTime.Date && b.ScheduleDate <= EndTime.Value.Date))) .Select(c => new { c.Uuid, c.Description, c.IsDeleted, c.IsActive, c.GuaDanOrderNo, c.UseType, c.Title, c.TargetUuid, scheduledate = c.ScheduleDate, }) .ToList(); bool canUsed = !bedSchedules.Any(); return new { a.Uuid, a.Name, a.Gender, a.IsActive, a.StatusUuid, a.RoomUuid, canUsed, schedule = bedSchedules }; }); return Ok(data); } [HttpPost] [Route("api/region/bed/create")] public IHttpActionResult CreateBed([FromBody] RegionRoomBed bed) { var room = _db.Room.Find(bed.RoomUuid); if (room == null) { return BadRequest("當前客房不存在"); } if(room.Gender != bed.Gender) { return BadRequest("床為性別和房間性別必須一致"); } if (room.BedCount != null && room.BedCount < room.RegionRoomBed.Count() + 1) { return BadRequest("該客房床位已滿"); } var regionBed = new RegionRoomBed { Name = bed.Name, RoomUuid = bed.RoomUuid, StatusUuid = bed.StatusUuid, IsActive = bed.IsActive, Gender = bed.Gender, Uuid = Guid.NewGuid(), }; _db.RegionRoomBed.Add(regionBed); _db.SaveChanges(); //創建床位 return Ok(new { uuid = regionBed.Uuid, roomUuid = regionBed.RoomUuid, statusuuid = regionBed.StatusUuid, isactive = regionBed.IsActive, gender = regionBed.Gender, name = regionBed.Name, }); } [HttpPost] [Route("api/region/bed/update")] public IHttpActionResult UpdateBed([FromBody] RegionRoomBed bed) { if (string.IsNullOrWhiteSpace(bed.Name)) { return BadRequest("床位名稱不可為空"); } var oldBed = _db.RegionRoomBed.Find(bed.Uuid); if (oldBed == null) { return BadRequest("更新失敗,床位不存在"); } var room = _db.Room.Find(bed.RoomUuid); if (room == null) { return BadRequest("當前客房不存在"); } if (room.Gender != bed.Gender) { return BadRequest("床為性別和房間性別必須一致"); } oldBed.StatusUuid = bed.StatusUuid; oldBed.IsActive = bed.IsActive; oldBed.Name = bed.Name; oldBed.Gender = bed.Gender; _db.SaveChanges(); //創建床位 return Ok(new { message = "床位更新成功" }); } [HttpPost] [Route("api/region/bed/delete")] public IHttpActionResult delete([FromUri] Guid uuid) { var bed = _db.RegionRoomBed.Find(uuid); if (bed == null) { return BadRequest("未找到床位"); } _db.RegionRoomBed.Remove(bed); _db.SaveChanges(); return Ok(new { message = "刪除成功" }); } [HttpGet] [Route("api/region/bed/getavailablebedcountbytime")] public async Task GetCanUseBedCountByTime(DateTime startTime, DateTime endTime) { //获取某个时间段内可用床位数量 var counts = await RegionAndRoomAndBedSchedule.GetAvailableBedCountsAsync(_db, startTime, endTime); return Ok(counts); } [HttpPost] [Route("api/region/bed/preallocation")] public async Task PreAutoAllocationBed([FromBody] ConfirmAllocationRequest request) { DateTime allocationStart = request.CheckInAt; DateTime? allocationEnd = request.CheckOutAt; bool isAllallocation = true; //是否全部分配完毕 // 获取可用床位列表 var availableBeds = await RegionAndRoomAndBedSchedule.GetAvailableBedsAsync(_db, allocationStart, allocationEnd); // 将床位按房间分组 var roomGroups = availableBeds .GroupBy(b => b.RoomUuid) .Select(g => new { RoomUuid = g.Key, Beds = g.ToList(), Gender = g.First().Room.Gender // bool,不可空 }) .ToList(); var data = new List(); // 按性别分组请求 var maleFollowers = request.PreBeds.Where(f => f.sex == "M").ToList(); var femaleFollowers = request.PreBeds.Where(f => f.sex == "F").ToList(); void AllocateByGender(List followers, bool isMale) { var rooms = roomGroups.Where(r => r.Gender == isMale).ToList(); int remaining = followers.Count; int index = 0; while (remaining > 0 && rooms.Any(r => r.Beds.Count > 0)) { // 找能容纳所有人的房间 var fullRoom = rooms .Where(r => r.Beds.Count >= remaining) .OrderBy(r => r.Beds.Count - remaining) // 分配后剩余床位最少优先 .FirstOrDefault(); if (fullRoom != null) { // 分配所有剩余人员 for (int i = index; i < followers.Count; i++) { var follower = followers[i]; var bed = fullRoom.Beds.First(); data.Add(new FollowerBedResponse { num = follower.num, sex = follower.sex, bedUuid = bed.Uuid }); fullRoom.Beds.Remove(bed); remaining--; index++; } break; // 全部分配完 } else { // 找剩余床位最多的房间 var room = rooms.OrderByDescending(r => r.Beds.Count).First(); int toAssign = Math.Min(remaining, room.Beds.Count); for (int i = 0; i < toAssign; i++) { var follower = followers[index++]; var bed = room.Beds.First(); data.Add(new FollowerBedResponse { num = follower.num, sex = follower.sex, bedUuid = bed.Uuid }); room.Beds.Remove(bed); remaining--; } } } if(index < followers.Count) { isAllallocation = false; return; } // 剩余无法分配的人员 for (int i = index; i < followers.Count; i++) { data.Add(new FollowerBedResponse { num = followers[i].num, sex = followers[i].sex, bedUuid = null }); } } // 先分配男生,再分配女生 AllocateByGender(maleFollowers, true); if (!isAllallocation) { return BadRequest("分配失敗,床位不足"); } AllocateByGender(femaleFollowers, false); if (!isAllallocation) { return BadRequest("分配失敗,床位不足"); } return Ok(new { message = "預分配成功", data }); } [HttpPost] [Route("api/region/bed/confirmallocation")] public async Task ConfirmAutoAllocationBed([FromBody] ConfirmAllocationRequest request) { if (request?.PreBeds == null || !request.PreBeds.Any()) return BadRequest("请求床位不能为空"); using (var transaction = _db.Database.BeginTransaction()) { try { DateTime allocationStart = request.CheckInAt.Date; // 保證時間清零 DateTime? allocationEnd = request.CheckOutAt?.Date; foreach (var req in request.PreBeds) { if (req.bedUuid != null) { // 先拉出床位相關排程到內存,避免 EF 不支援 .Date var schedules = _db.RegionAndRoomAndBedSchedule .Where(s => s.IsDeleted == false && s.IsActive && s.TargetUuid == req.bedUuid) .ToList(); bool conflictExists = schedules.Any(s => s.ScheduleDate == null // 長期占用 || (allocationEnd.HasValue ? (s.ScheduleDate >= allocationStart && s.ScheduleDate <= allocationEnd.Value) : s.ScheduleDate >= allocationStart) ); if (conflictExists) { transaction.Rollback(); return BadRequest($"床位 {req.bedUuid} 在时间段内已被占用,分配失败"); } } // 找到房間 UUID Guid? roomUuid = null; if (req.bedUuid != null) { var bed = _db.RegionRoomBed.Find(req.bedUuid); if (bed != null) roomUuid = bed.RoomUuid; } // 新增挂单入住客人记录 var guest = new GuaDanOrderGuest { GuaDanOrderNo = request.OrderNo, FollowerNum = req.num, BedUuid = req.bedUuid, Uuid = Guid.NewGuid(), RoomUuid = roomUuid, CheckInAt = allocationStart, CheckOutAt = allocationEnd, }; _db.GuaDanOrderGuest.Add(guest); // 新增每日排程 if (allocationEnd.HasValue) { for (var date = allocationStart; date <= allocationEnd.Value; date = date.AddDays(1)) { var newSchedule = new RegionAndRoomAndBedSchedule { Uuid = Guid.NewGuid(), TargetUuid = req.bedUuid, ScheduleDate = date, UseType = (int)RegionAndRoomAndBedSchedule.SchedulePurpose.Bed_Reservation, IsDeleted = false, IsActive = true, CreatedBy = "系统自动分配", CreatedAt = DateTime.Now, GuaDanOrderNo = guest.GuaDanOrderNo }; _db.RegionAndRoomAndBedSchedule.Add(newSchedule); } } else { // 長期占用 var newSchedule = new RegionAndRoomAndBedSchedule { Uuid = Guid.NewGuid(), TargetUuid = req.bedUuid, ScheduleDate = null, UseType = (int)RegionAndRoomAndBedSchedule.SchedulePurpose.Bed_Reservation, IsDeleted = false, IsActive = true, CreatedBy = "系统自动分配", CreatedAt = DateTime.Now, GuaDanOrderNo = guest.GuaDanOrderNo }; _db.RegionAndRoomAndBedSchedule.Add(newSchedule); } } await _db.SaveChangesAsync(); transaction.Commit(); return Ok(new { message = "分配成功" }); } catch (Exception ex) { transaction.Rollback(); return InternalServerError(ex); } } } private bool BedIsCanUsed(RegionRoomBed bed, DateTime? StartTime, DateTime? EndTime) { if(!bed.IsActive) { return false; } return true; } public class FollowerBedRequest { public int num { get; set; } public string sex { get; set; } } public class FollowerBedResponse { public int num { get; set; } public string sex { get; set; } public Guid? bedUuid { get; set; } = null; public string bedName { get; set; } } public class ConfirmAllocationRequest { public List PreBeds { get; set; } public string OrderNo { get; set; } public DateTime CheckInAt { get; set; } public DateTime? CheckOutAt { get; set; } } }