Eddie 2023-08-14 - reject future date on activity creating and report

This commit is contained in:
Frede Hundewadt 2023-08-15 07:59:15 +02:00
parent e30acdb005
commit d70f59628b
9 changed files with 188 additions and 127 deletions

View file

@ -175,7 +175,15 @@ public partial class AdvisorActivityCreatePage : IDisposable
SelectedDate = string.IsNullOrWhiteSpace(_userPref.WorkDate)
? DateTime.Now
: DateTime.Parse(_userPref.WorkDate);
// 2023-08-14 - reject orders for past or future dates
if (SelectedDate.Date != DateTime.Now.Date)
{
Toaster.ShowError($"Aktivitetsdato er ikke dagens dato. Dato ændres til {DateTime.Now.Date}");
SelectedDate = DateTime.Now;
await PreferenceService.SetWorkDate(SelectedDate);
}
// raise flag if report is closed
ReportClosed = await ReportRepo.ReportExist($"{SelectedDate:yyyy-MM-dd}");

View file

@ -19,7 +19,7 @@
@attribute [Authorize(Roles = "Advisor,Supervisor")]
@page "/advisor/reports/new"
<PageTitle>Opret Dagsrapport for @ThisWorkDate</PageTitle>
<PageTitle>Opret Dagsrapport for @_thisWorkDate</PageTitle>
@* report header *@
<div class="row sticky-top bg-dark text-white rounded-2 mb-2 py-2 align-items-center">
@ -54,7 +54,7 @@
<option value="sales">Salgsdag</option>
<option value="meeting">Salgsmøde</option>
<option value="office">Kontordag</option>
@if (IsSupervisor)
@if (_isSupervisor)
{
<option value="supervisor">Medkørende Supervisor</option>
}
@ -62,39 +62,38 @@
<option value="leave">Ferie</option>
</select>
<ValidationMessage For="@(() => Report.DayTypeEnum)"/>
</td>
@if (Report.DayTypeEnum.ToLower().Contains("leave"))
{
Report.Figures.KmMorning = 0;
<td>
<InputDate class="form-control" @bind-Value="BeginLeave"/>
<InputDate class="form-control" @bind-Value="_beginLeave"/>
</td>
<td>
<InputDate class="form-control" @bind-Value="EndLeave"/>
<InputDate class="form-control" @bind-Value="_endLeave"/>
</td>
}
else
{
Report.Figures.KmMorning = KmMorning;
Report.Figures.KmMorning = _kmMorning;
<td>
<input type="time" id="checkIn" class="form-control"
@bind-Value="CheckIn" @bind-Value:event="oninput" onchange="@OnTimeChanged"/>
@bind-Value="_checkIn" @bind-Value:event="oninput" onchange="@OnTimeChanged"/>
</td>
<td>
<input type="time" id="checkOut" class="form-control"
@bind-Value="CheckOut" @bind-Value:event="oninput" onchange="@OnTimeChanged"/>
@bind-Value="_checkOut" @bind-Value:event="oninput" onchange="@OnTimeChanged"/>
</td>
}
<td class="text-end">
<button type="button" class="btn btn-warning"
@onclick="@GetKeyFigures" disabled="@(!NoFigures)">
@onclick="@GetKeyFigures" disabled="@(!_noFigures)">
Nøgletal
</button>
</td>
<td class="text-end">
<button type="button" class="btn btn-primary"
@onclick="@SubmitReport" disabled="@(NoFigures || Working)">
@onclick="@SubmitReport" disabled="@(_noFigures || _working)">
Gem Rapport
</button>
</td>
@ -145,11 +144,11 @@
<tr>
<td>
<InputNumber class="form-control" @bind-Value="@Report.Figures.KmEvening"
disabled="@(NoFigures)"/>
disabled="@(_noFigures)"/>
</td>
<td>
<InputNumber class="form-control" @bind-Value="@Report.Figures.KmMorning"
disabled="@(NoFigures)"/>
disabled="@(_noFigures)"/>
</td>
<td>
<InputNumber class="form-control" @bind-Value="@Report.Figures.Distance"
@ -173,7 +172,7 @@
<tr>
<td>
<InputNumber class="form-control" @bind-Value="@Report.Figures.DistancePrivate"
disabled="@(NoFigures)"/>
disabled="@(_noFigures)"/>
</td>
<td>
<InputNumber class="form-control" @bind-Value="@Report.Figures.DistancePrivateMonth"
@ -183,10 +182,10 @@
</tbody>
</table>
</div>
@if (Activities.Any())
@if (_activities.Any())
{
<div class="row">
<AdvisorActivityListComponent ActivityList="Activities"/>
<AdvisorActivityListComponent ActivityList="_activities"/>
</div>
}
}
@ -196,9 +195,9 @@
</div>
</EditForm>
@if (Working)
@if (_working)
{
<WorkingThreeDots/>
}
<ConfirmationModal BodyMessage="@Prompt" OnOkClicked="ConfirmReportCallback" OnCancelClicked="OnCancelCallback" @ref="ConfirmReportModal"/>
<ConfirmationModal BodyMessage="@_prompt" OnOkClicked="ConfirmReportCallback" OnCancelClicked="OnCancelCallback" @ref="_confirmModal"/>

View file

@ -44,24 +44,24 @@ public partial class AdvisorReportCreatePage : IDisposable
// ##########################################################################
private EditContext ReportContext { get; set; }
private ReportDto Report { get; set; } = new();
private List<ReportItemView> Activities { get; set; } = new();
private ReportFiguresDto InitialValues { get; set; } = new();
private UserPreference Preference { get; set; } = new();
private bool FormInvalid { get; set; } = true;
private bool NoFigures { get; set; } = true;
private bool Working { get; set; }
private DateTime ThisWorkDate { get; set; }
private TimeOnly CheckIn { get; set; } = new(12, 0);
private TimeOnly CheckOut { get; set; } = new(12, 0);
private DateTime BeginLeave { get; set; } = DateTime.Now;
private DateTime EndLeave { get; set; } = DateTime.Now;
private ConfirmationModal ConfirmReportModal { get; set; }
private string Prompt { get; set; } = "";
private string WorkDate { get; set; } = "";
private int CurrKmMonth { get; set; }
private int CurrKmPrivate { get; set; }
private bool IsSupervisor { get; set; }
private int KmMorning { get; set; }
private List<ReportItemView> _activities = new();
private ReportFiguresDto _initialValues = new();
private UserPreference _preference = new();
private bool _formInvalid = true;
private bool _noFigures = true;
private bool _working;
private DateTime _thisWorkDate;
private TimeOnly _checkIn = new(12, 0);
private TimeOnly _checkOut = new(12, 0);
private DateTime _beginLeave = DateTime.Now;
private DateTime _endLeave = DateTime.Now;
private ConfirmationModal _confirmModal;
private string _prompt = "";
private string _workDate = "";
private int _currKmMonth;
private int _currKmPrivate;
private bool _isSupervisor;
private int _kmMorning;
/// <summary>
@ -69,46 +69,46 @@ public partial class AdvisorReportCreatePage : IDisposable
/// </summary>
protected override async Task OnInitializedAsync()
{
Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent();
IsSupervisor = await UserInfo.IsSupervisor();
ReportContext = new EditContext(Report);
ReportContext.OnFieldChanged += HandleFieldChanged;
ReportContext.OnValidationStateChanged += ValidationChanged;
Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent();
_isSupervisor = await UserInfo.IsSupervisor();
PreferenceService.OnChange += ProfileServiceOnOnChange;
Preference = await PreferenceService.GetPreference();
_preference = await PreferenceService.GetPreference();
KmMorning = await PreferenceService.GetKmMorning();
_kmMorning = await PreferenceService.GetKmMorning();
Logger.LogDebug("{}", JsonSerializer.Serialize(Preference));
Logger.LogDebug("{}", JsonSerializer.Serialize(_preference));
WorkDate = Preference.WorkDate;
if (string.IsNullOrWhiteSpace(WorkDate))
_workDate = _preference.WorkDate;
if (string.IsNullOrWhiteSpace(_workDate))
{
ThisWorkDate = DateTime.Now;
WorkDate = $"{ThisWorkDate:yyyy-MM-dd}";
await PreferenceService.SetWorkDate(ThisWorkDate);
_thisWorkDate = DateTime.Now;
_workDate = $"{_thisWorkDate:yyyy-MM-dd}";
await PreferenceService.SetWorkDate(_thisWorkDate);
}
else
{
ThisWorkDate = DateTime.Parse(WorkDate);
_thisWorkDate = DateTime.Parse(_workDate);
}
if (await AdvisorSalesReportRepo.ReportExist(WorkDate))
if (await AdvisorSalesReportRepo.ReportExist(_workDate))
{
Navigator.NavigateTo($"/advisor/reports/view/{ThisWorkDate:yyyy-MM-dd}");
Navigator.NavigateTo($"/advisor/reports/view/{_thisWorkDate:yyyy-MM-dd}");
}
BeginLeave = ThisWorkDate;
EndLeave = ThisWorkDate;
_beginLeave = _thisWorkDate;
_endLeave = _thisWorkDate;
Report.FromDateTime = $"{ThisWorkDate:yyyy-MM-dd'T'12:00:00}";
Report.ToDateTime = $"{ThisWorkDate:yyyy-MM-dd'T'12:00:00}";
Report.FromDateTime = $"{_thisWorkDate:yyyy-MM-dd'T'12:00:00}";
Report.ToDateTime = $"{_thisWorkDate:yyyy-MM-dd'T'12:00:00}";
Report.Figures.KmMorning = 0;
Report.Figures.KmEvening = 0;
@ -122,30 +122,30 @@ public partial class AdvisorReportCreatePage : IDisposable
private void ProfileServiceOnOnChange(UserPreference userPreference)
{
Preference = userPreference;
WorkDate = Preference.WorkDate;
_preference = userPreference;
_workDate = _preference.WorkDate;
StateHasChanged();
}
private async Task GetKeyFigures()
{
if (Working)
if (_working)
return;
Working = true;
_working = true;
Report.Figures = new ReportFiguresDto();
InitialValues = new ReportFiguresDto();
Activities = new List<ReportItemView>();
_initialValues = new ReportFiguresDto();
_activities = new List<ReportItemView>();
var data = await AdvisorSalesReportRepo.InitializeReportData(WorkDate);
var data = await AdvisorSalesReportRepo.InitializeReportData(_workDate);
if(data.ReportClosed)
Navigator.NavigateTo($"/advisor/reports/view/{ThisWorkDate:yyyy-MM-dd}");
Navigator.NavigateTo($"/advisor/reports/view/{_thisWorkDate:yyyy-MM-dd}");
Report.Figures = data.ReportData;
InitialValues = data.ReportData;
Activities = data.ReportItems;
CurrKmMonth = data.ReportData.DistanceMonth;
CurrKmPrivate = data.ReportData.DistancePrivate;
_initialValues = data.ReportData;
_activities = data.ReportItems;
_currKmMonth = data.ReportData.DistanceMonth;
_currKmPrivate = data.ReportData.DistancePrivate;
if (Report.DayTypeEnum.ToLower().Contains("leave"))
{
@ -156,28 +156,25 @@ public partial class AdvisorReportCreatePage : IDisposable
}
else
{
Report.Figures.KmMorning = KmMorning;
Report.Figures.KmMorning = _kmMorning;
}
NoFigures = false;
Working = false;
_noFigures = false;
_working = false;
}
/// <summary>
/// Field data change event
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void HandleFieldChanged(object sender, FieldChangedEventArgs e)
{
// Console.WriteLine($"e FieldName => {e.FieldIdentifier.FieldName}");
FormInvalid = !ReportContext.Validate();
if (KmMorning == 0)
_formInvalid = !ReportContext.Validate();
if (_kmMorning == 0)
{
KmMorning = Report.Figures.KmMorning;
_kmMorning = Report.Figures.KmMorning;
}
Report.Figures.Distance = Report.Figures.KmEvening - Report.Figures.KmMorning;
Report.Figures.DistanceMonth = Report.Figures.Distance + CurrKmMonth;
Report.Figures.DistancePrivateMonth = Report.Figures.DistancePrivate + CurrKmPrivate;
Report.Figures.DistanceMonth = Report.Figures.Distance + _currKmMonth;
Report.Figures.DistancePrivateMonth = Report.Figures.DistancePrivate + _currKmPrivate;
if (Report.Figures.Distance is > 1000 or < 0 && Report.Figures.KmMorning > 0)
{
Toaster.ShowError($"Kørte km for rapporten er '{Report.Figures.Distance}'. Er du sikker på at det er rigtigt?");
@ -185,14 +182,10 @@ public partial class AdvisorReportCreatePage : IDisposable
StateHasChanged();
}
/// <summary>
/// Validation change event
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ValidationChanged(object sender, ValidationStateChangedEventArgs e)
{
FormInvalid = false;
_formInvalid = false;
ReportContext.OnFieldChanged -= HandleFieldChanged;
ReportContext.OnValidationStateChanged -= ValidationChanged;
ReportContext = new EditContext(Report);
@ -200,76 +193,88 @@ public partial class AdvisorReportCreatePage : IDisposable
ReportContext.OnValidationStateChanged += ValidationChanged;
}
/// <summary>
/// Save report confirmed callback
/// </summary>
private async Task ConfirmReportCallback()
{
// attempt to eliminate doubled click on submit button
if (Working)
if (_working)
return;
Working = true;
_working = true;
var result = await AdvisorSalesReportRepo.CreateReport(WorkDate, Report);
// post report to backend
var result = await AdvisorSalesReportRepo.CreateReport(_workDate, Report);
Logger.LogDebug("CreateReport.result => {}", JsonSerializer.Serialize(result));
// reset km and date confirmation
await PreferenceService.SetKmMorning(0);
// reset date confirmed
await PreferenceService.SetDateConfirmed(false);
Navigator.NavigateTo($"/advisor/reports/view/{ThisWorkDate:yyyy-MM-dd}");
Navigator.NavigateTo($"/advisor/reports/view/{_thisWorkDate:yyyy-MM-dd}");
}
/// <summary>
/// Submit report
/// </summary>
private void SubmitReport()
{
// attempt to eliminate doubled click on submit button
if (Working)
if (_working)
return;
// 2023-08-14 - reject report for a future date
if (_endLeave.Date > DateTime.Now.Date)
{
Toaster.ShowError("Du har rod i ferie datoer. Prøver du at lave ferierapport før ferien er færdig?");
return;
}
// check day type
if (string.IsNullOrWhiteSpace(Report.DayTypeEnum))
{
Toaster.ShowError("Dagtype skal vælges");
return;
}
// distance day check - only if not leave
if (Report.Figures.KmMorning > Report.Figures.KmEvening && !Report.DayTypeEnum.ToLower().Contains("leave"))
{
Toaster.ShowError("Km udregning er negativ - kontroller venligst km tal");
return;
}
// local working variables
DateTime checkIn;
DateTime checkOut;
// create a date time object using workDate and workHour input
if (Report.DayTypeEnum.ToLower().Contains("leave"))
{
checkIn = new DateTime(BeginLeave.Year, BeginLeave.Month, BeginLeave.Day, 0, 0, 0);
checkOut = new DateTime(EndLeave.Year, EndLeave.Month, EndLeave.Day, 0, 0, 0);
checkIn = new DateTime(_beginLeave.Year, _beginLeave.Month, _beginLeave.Day, 0, 0, 0);
checkOut = new DateTime(_endLeave.Year, _endLeave.Month, _endLeave.Day, 0, 0, 0);
}
else
{
checkIn = new DateTime(ThisWorkDate.Year, ThisWorkDate.Month, ThisWorkDate.Day, CheckIn.Hour, CheckIn.Minute, 0);
checkOut = new DateTime(ThisWorkDate.Year, ThisWorkDate.Month, ThisWorkDate.Day, CheckOut.Hour, CheckOut.Minute, 0);
checkIn = new DateTime(_thisWorkDate.Year, _thisWorkDate.Month, _thisWorkDate.Day, _checkIn.Hour, _checkIn.Minute, 0);
checkOut = new DateTime(_thisWorkDate.Year, _thisWorkDate.Month, _thisWorkDate.Day, _checkOut.Hour, _checkOut.Minute, 0);
}
// assign a workday number if the day is marked as salesDay
Report.SalesDayNumber = Report.DayTypeEnum == "sales" ? Report.Figures.SalesDayCount + 1 : 0;
// format report date time input
Report.FromDateTime = checkIn.ToString("yyyy-MM-dd'T'HH:mm:ss", CultureInfo.InvariantCulture);
Report.ToDateTime = checkOut.ToString("yyyy-MM-dd'T'HH:mm:ss", CultureInfo.InvariantCulture);
Logger.LogDebug("_workDate => {workDate}", $"{ThisWorkDate:yyyy-MM-dd}");
Logger.LogDebug("_report => {report}", JsonSerializer.Serialize(Report));
Logger.LogDebug("_workDate => {workDate}", $"{_thisWorkDate:yyyy-MM-dd}");
Logger.LogDebug("Report => {report}", JsonSerializer.Serialize(Report));
if (Report.DayTypeEnum is "leave" or "sickLeave")
{
// reset distance calculation
Report.Figures.KmEvening = 0;
Report.Figures.KmMorning = 0;
Report.Figures.DistanceMonth = CurrKmMonth;
Report.Figures.DistancePrivateMonth = CurrKmPrivate;
Report.Figures.DistanceMonth = _currKmMonth;
Report.Figures.DistancePrivateMonth = _currKmPrivate;
}
// pop confirmation
@ -278,36 +283,31 @@ public partial class AdvisorReportCreatePage : IDisposable
? $"Kørte km for rapporten er <strong>'{Report.Figures.KmEvening - Report.Figures.KmMorning}'</strong>. Er du sikker på at det er rigtigt?<br/>"
: "";
Prompt = $"{warning}<br/>Gem rapport for {ThisWorkDate.ToLongDateString()}?";
_prompt = $"{warning}<br/>Gem rapport for {_thisWorkDate.ToLongDateString()}?";
ConfirmReportModal.Show();
_confirmModal.Show();
}
/// <summary>
/// On Time changed - update the Report Date fields
/// </summary>
private void OnTimeChanged()
{
var f = new DateTime(ThisWorkDate.Year, ThisWorkDate.Month, ThisWorkDate.Day, CheckIn.Hour, CheckIn.Minute,0);
var f = new DateTime(_thisWorkDate.Year, _thisWorkDate.Month, _thisWorkDate.Day, _checkIn.Hour, _checkIn.Minute,0);
Report.FromDateTime = $"{f:yyyy-MM-dd'T'HH:mm}";
var t = new DateTime(ThisWorkDate.Year, ThisWorkDate.Month, ThisWorkDate.Day, CheckOut.Hour, CheckOut.Minute,0);
var t = new DateTime(_thisWorkDate.Year, _thisWorkDate.Month, _thisWorkDate.Day, _checkOut.Hour, _checkOut.Minute,0);
Report.ToDateTime = $"{t:yyyy-MM-dd'T'HH:mm}";
}
/// <summary>
/// Set workDate callback
/// </summary>
/// <param name="workDate"></param>
private void SetWorkDateCallback(string workDate)
{
WorkDate = workDate;
ThisWorkDate = DateTime.Parse(workDate);
_workDate = workDate;
_thisWorkDate = DateTime.Parse(workDate);
NoFigures = true;
_noFigures = true;
Report.Figures = new ReportFiguresDto();
InitialValues = new ReportFiguresDto();
Activities = new List<ReportItemView>();
_initialValues = new ReportFiguresDto();
_activities = new List<ReportItemView>();
Report.Figures.KmEvening = 0;
Report.Figures.KmMorning = 0;
@ -315,14 +315,17 @@ public partial class AdvisorReportCreatePage : IDisposable
Report.Figures.DistanceMonth = 0;
Report.Figures.DistancePrivate = 0;
Report.Figures.DistancePrivateMonth = 0;
Report.FromDateTime = $"{ThisWorkDate:yyyy-MM-dd'T'12:00}";
Report.ToDateTime = $"{ThisWorkDate:yyyy-MM-dd'T'12:00}";
Report.FromDateTime = $"{_thisWorkDate:yyyy-MM-dd'T'12:00}";
Report.ToDateTime = $"{_thisWorkDate:yyyy-MM-dd'T'12:00}";
}
private void OnCancelCallback()
{
ConfirmReportModal.Hide();
_confirmModal.Hide();
}
public void Dispose()
{
Interceptor.DisposeEvent();

View file

@ -1,8 +1,8 @@
{
"appInfo": {
"name": "Wonky Online",
"version": "213.0",
"rc": false,
"version": "222.0",
"rc": true,
"sandBox": true,
"image": "grumpy-coder.png",
"sdk": "dotnet 7.0"

View file

@ -0,0 +1,10 @@
namespace Wonky.Entity.DTO;
public class WebShopLineDto
{
public string Discount { get; set; } = "";
public string Quantity { get; set; } = "";
public string Sku { get; set; } = "";
public string Text { get; set; } = "";
public string UnitPrice { get; set; } = "";
}

View file

@ -0,0 +1,11 @@
using System.ComponentModel.DataAnnotations;
namespace Wonky.Entity.DTO;
public class WebShopOrderDto
{
[MaxLength(20)] public string ReferenceNumber { get; set; } = "";
[MaxLength(255)] public string OrderNote { get; set; } = "";
[Required] public bool ConditionsAccepted { get; set; }
[Required] public List<WebShopLineDto> Lines { get; set; } = new();
}

View file

@ -0,0 +1,8 @@
namespace Wonky.Entity.Views;
public class WebShopLineView
{
public string Sku { get; set; } = "";
public string Quantity { get; set; } = "";
public string Text { get; set; } = "";
}

View file

@ -0,0 +1,9 @@
namespace Wonky.Entity.Views;
public class WebShorOrderListView
{
public string SalesHeadId { get; set; } = "";
public string ReferenceNumber { get; set; } = "";
public string YourRef { get; set; } = "";
public string OrderDate { get; set; } = "";
}

View file

@ -0,0 +1,13 @@
namespace Wonky.Entity.Views;
public class WebShopOrderView
{
public string OurRef { get; set; } = "";
public string ReferenceNumber { get; set; } = "";
public string YourRef { get; set; } = "";
public string OrderNote { get; set; } = "";
public bool Closed { get; set; }
public string OrderDate { get; set; } = "";
public List<WebShopLineView> Lines { get; set; } = new();
}