Files
17168ERP/web/App_Code/api/regionRoomBedController.cs

468 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
/// <summary>
/// regionRoomBedController 的摘要描述
/// </summary>
[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<IHttpActionResult> 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<IHttpActionResult> 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<FollowerBedResponse>();
// 按性别分组请求
var maleFollowers = request.PreBeds.Where(f => f.sex == "M").ToList();
var femaleFollowers = request.PreBeds.Where(f => f.sex == "F").ToList();
void AllocateByGender(List<FollowerBedResponse> 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<IHttpActionResult> 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<FollowerBedResponse> PreBeds { get; set; }
public string OrderNo { get; set; }
public DateTime CheckInAt { get; set; }
public DateTime? CheckOutAt { get; set; }
}
}