using System.Threading.Tasks; using System; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Logging; using AyaNova.Models; using AyaNova.Api.ControllerHelpers; using AyaNova.Biz; using Microsoft.EntityFrameworkCore; using System.Linq; using System.Collections.Generic; using AyaNova.Util; namespace AyaNova.Api.Controllers { [ApiController] [ApiVersion("8.0")] [Route("api/v{version:apiVersion}/schedule")] [Produces("application/json")] [Authorize] public class ScheduleController : ControllerBase { private readonly AyContext ct; private readonly ILogger log; private readonly ApiServerState serverState; /// /// ctor /// /// /// /// public ScheduleController(AyContext dbcontext, ILogger logger, ApiServerState apiServerState) { ct = dbcontext; log = logger; serverState = apiServerState; } /// /// Get personal schedule for parameters specified /// time zone UTC offset in minutes is required to be passed in /// timestamps returned are in Unix Epoch milliseconds converted for local time display /// /// Personal schedule parameters /// From route path /// [HttpPost("personal")] public async Task PostPersonalSchedule([FromBody] PersonalScheduleParams p, ApiVersion apiVersion) { if (!serverState.IsOpen) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); if (!ModelState.IsValid) return BadRequest(new ApiErrorResponse(ModelState)); List r = new List(); var UserId = UserIdFromContext.Id(HttpContext.Items); var UType = UserTypeFromContext.Type(HttpContext.Items); //Note: query will return records that fall within viewed range even if they start or end outside of it //However in month view (only, rest are as is) we can see up to 6 days before or after the month so in the interest of filling those voids: //Adjust query dates to encompass actual potential view range DateTime ViewStart = p.Start; DateTime ViewEnd = p.End; //this covers the largest possible window that could display due to nearly a week of the last or next month showing if (p.View == ScheduleView.Month) { ViewStart = p.Start.AddDays(-6); ViewEnd = p.End.AddDays(6); } //WORKORDERS if (p.WorkOrders && (UType == UserType.Service || UType == UserType.ServiceContractor)) { //Note: query for *overlapping* ranges, not *contained* entirely in view range r.AddRange(await ct.ViewSchedulePersonalWorkOrder.Where(x => x.SchedUserId == UserId && ViewStart <= x.StopDate && x.StartDate <= ViewEnd) .Select(x => MakeWOSchedItem(x, p)) .ToListAsync()); } return Ok(ApiOkResponse.Response(r)); } private static PersonalScheduleListItem MakeWOSchedItem(ViewSchedulePersonalWorkOrder v, PersonalScheduleParams p) { var s = new PersonalScheduleListItem(); s.Id = v.WoItemSchedUserId; s.Color = ColorFromWOItem(v, p); s.TextColor = TextColor(s.Color); s.Start = (DateTime)v.StartDate; s.End = (DateTime)v.StopDate; s.Type = AyaType.WorkOrderItemScheduledUser; s.Name = NameFromWOItem(v, p); return s; } // private static long? EpochSeconds(DateTime? dt, int tzOffset = 0) // { // if (dt == null) return null; // DateTimeOffset dto = new DateTimeOffset((DateTime)dt); // return dto.ToUnixTimeMilliseconds() + (tzOffset * 60000); // } private static string ColorFromWOItem(ViewSchedulePersonalWorkOrder v, PersonalScheduleParams p) { switch (p.ColorSource) { case PersonalScheduleWorkOrderColorSource.WorkOrderStatus: return v.WorkOrderStatusColor; case PersonalScheduleWorkOrderColorSource.WorkOrderItemStatus: return v.WorkOrderItemStatusColor; case PersonalScheduleWorkOrderColorSource.WorkOrderItemPriority: return v.WorkOrderItemPriorityColor; } return string.Empty; } private static string TextColor(string hexcolor) { if (string.IsNullOrWhiteSpace(hexcolor)) return "black"; hexcolor = hexcolor.Replace("#", ""); var r = StringUtil.HexToInt(hexcolor.Substring(0, 2)); var g = StringUtil.HexToInt(hexcolor.Substring(2, 2)); var b = StringUtil.HexToInt(hexcolor.Substring(4, 2)); var yiq = (r * 299 + g * 587 + b * 114) / 1000; return yiq >= 128 ? "black" : "white"; } private static string NameFromWOItem(ViewSchedulePersonalWorkOrder v, PersonalScheduleParams p) { // Name=[wonumber customername] return v.Serial.ToString() + " " + v.CustomerName; } public enum PersonalScheduleWorkOrderColorSource : int { None = 0, WorkOrderStatus = 2, WorkOrderItemStatus = 3, WorkOrderItemPriority = 4 } public enum ScheduleView : int { Day = 1, Week = 2, Month = 3, Day4 = 4 } public class PersonalScheduleParams { public ScheduleView View { get; set; } public DateTime Start { get; set; } public DateTime End { get; set; } public PersonalScheduleWorkOrderColorSource ColorSource { get; set; } public bool WorkOrders { get; set; } public bool Reviews { get; set; } public bool Reminders { get; set; } } public class PersonalScheduleListItem { //Never be null dates in here even though source records might be have null dates because they are not queried for and //can't be displayed on a calendar anyway //user can simply filter a data table by null dates to see them //we shouldn't have allowed null dates in the first place in v7 but here we are :) public DateTime Start { get; set; } public DateTime End { get; set; } public bool Timed { get { return true; } } public string Name { get; set; } public string Color { get; set; } public string TextColor { get; set; } public AyaType Type { get; set; } public long Id { get; set; } } //------------ }//eoc }//eons