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();
StartTime = StartTime.Date;
EndTime = EndTime?.Date;
var data = beds.Select(a =>
{
var bedSchedules = _db.RegionAndRoomAndBedSchedule
.Where(s => s.GuaDanOrderGuest.StatusCode != "403")
.Where(s => s.GuaDanOrderGuest.StatusCode != "404")
.Where(b => b.TargetUuid == a.Uuid
&& (b.ScheduleDate == null
|| (b.ScheduleDate >= StartTime && b.ScheduleDate < EndTime)))
.ToList()
.Select(c => new
{
c.Uuid,
c.Description,
c.IsDeleted,
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.StatusCode,
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,
StatusCode = bed.StatusCode,
IsActive = bed.IsActive,
Gender = bed.Gender,
Uuid = Guid.NewGuid(),
};
_db.RegionRoomBed.Add(regionBed);
_db.SaveChanges();
//創建床位
return Ok(new
{
uuid = regionBed.Uuid,
roomUuid = regionBed.RoomUuid,
statuscode = regionBed.StatusCode,
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.StatusCode = bed.StatusCode;
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 start = startTime.Date;
var end = endTime.Date;
// 找出所有在日期範圍內被占用的床位
var busyBedUuids = await _db.RegionAndRoomAndBedSchedule
.Where(s => s.GuaDanOrderGuest.StatusCode != "403")
.Where(s => s.GuaDanOrderGuest.StatusCode != "404")
.Where(a => a.IsCancel == false)
.Where(s => s.IsDeleted == false
&& (s.ScheduleDate == null // 長期占用
|| (s.ScheduleDate >= start && s.ScheduleDate < end)))
.Select(s => s.TargetUuid)
.Distinct()
.ToListAsync();
// 可用床位 = 所有床位 - 忙碌床位
var availableBeds = _db.RegionRoomBed
.Where(b => !busyBedUuids.Contains(b.Uuid));
var result = await availableBeds
.GroupBy(b => b.Gender)
.Select(g => new
{
Gender = g.Key,
Count = g.Count()
})
.ToListAsync();
var male = result.Where(r => r.Gender == true).Select(r => r.Count).FirstOrDefault();
var female = result.Where(r => r.Gender == false).Select(r => r.Count).FirstOrDefault();
return Ok(new {male, female});
}
[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.IsCancel && 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,
StatusCode = "401",
};
_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,
CreatedBy = "系统自动分配",
CreatedAt = DateTime.Now,
GuaDanOrderNo = guest.GuaDanOrderNo,
Title = "掛單",
GuaDanOrderGuestUuid = guest.Uuid,
};
_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,
CreatedBy = "系统自动分配",
CreatedAt = DateTime.Now,
GuaDanOrderNo = guest.GuaDanOrderNo,
Title = "掛單",
GuaDanOrderGuestUuid = guest.Uuid,
};
_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; }
}
}