backend phase 9
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Asp.Versioning;
|
||||
using Baya.Application.Features.Bookings.Commands.UpsertCancellationPolicy;
|
||||
using Baya.Application.Features.Bookings.Queries.ListCancellationPolicies;
|
||||
using Baya.Application.Models.Booking;
|
||||
using Baya.Infrastructure.Identity.Identity.PermissionManager;
|
||||
using Baya.WebFramework.Attributes;
|
||||
using Baya.WebFramework.BaseController;
|
||||
using Baya.WebFramework.ServiceConfiguration;
|
||||
using Mediator;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.RateLimiting;
|
||||
|
||||
namespace Baya.Web.Api.Controllers.V1;
|
||||
|
||||
/// <summary>
|
||||
/// Admin management of the cancellation/refund tiers. Editing a policy never mutates an already-snapshotted
|
||||
/// cancellation — past cancellations froze the code + percentage onto the booking.
|
||||
/// </summary>
|
||||
[ApiVersion("1")]
|
||||
[ApiController]
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
[Authorize(ConstantPolicies.DynamicPermission)]
|
||||
[EnableRateLimiting(RateLimitingServiceExtension.SensitivePolicy)]
|
||||
[Display(Description = "Admin cancellation-policy management (upsert + list)")]
|
||||
public sealed class AdminCancellationPoliciesController(ISender sender) : BaseController
|
||||
{
|
||||
[HttpPost("[action]")]
|
||||
[ProducesOkApiResponseType<CancellationPolicyDto>]
|
||||
public async Task<IActionResult> Upsert(UpsertCancellationPolicyCommand command, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(command, cancellationToken));
|
||||
|
||||
[HttpGet("[action]")]
|
||||
[ProducesOkApiResponseType<IReadOnlyList<CancellationPolicyDto>>]
|
||||
public async Task<IActionResult> List(CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(new ListCancellationPoliciesQuery(), cancellationToken));
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Asp.Versioning;
|
||||
using Baya.Application.Features.Bookings.Commands.DetectNoShowSessions;
|
||||
using Baya.Application.Features.Bookings.Queries.ListAdminEvv;
|
||||
using Baya.Application.Models.Booking;
|
||||
using Baya.Application.Models.Common;
|
||||
using Baya.Infrastructure.Identity.Identity.PermissionManager;
|
||||
using Baya.WebFramework.Attributes;
|
||||
using Baya.WebFramework.BaseController;
|
||||
using Baya.WebFramework.ServiceConfiguration;
|
||||
using Mediator;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.RateLimiting;
|
||||
|
||||
namespace Baya.Web.Api.Controllers.V1;
|
||||
|
||||
/// <summary>
|
||||
/// The admin EVV-review surface: the mismatch/no-show queue and the manual no-show sweep trigger (the same
|
||||
/// idempotent command the deferred cron will call).
|
||||
/// </summary>
|
||||
[ApiVersion("1")]
|
||||
[ApiController]
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
[Authorize(ConstantPolicies.DynamicPermission)]
|
||||
[EnableRateLimiting(RateLimitingServiceExtension.SensitivePolicy)]
|
||||
[Display(Description = "Admin EVV review queue (location mismatch / no-show) + manual no-show sweep")]
|
||||
public sealed class AdminEvvController(ISender sender) : BaseController
|
||||
{
|
||||
[HttpGet("[action]")]
|
||||
[ProducesOkApiResponseType<PagedResult<AdminEvvItemDto>>]
|
||||
public async Task<IActionResult> List([FromQuery] ListAdminEvvQuery query, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(query, cancellationToken));
|
||||
|
||||
[HttpPost("[action]")]
|
||||
[ProducesOkApiResponseType<NoShowSweepResult>]
|
||||
public async Task<IActionResult> DetectNoShows(CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(new DetectNoShowSessionsCommand(), cancellationToken));
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Asp.Versioning;
|
||||
using Baya.Application.Features.Bookings.Commands.CancelSession;
|
||||
using Baya.Application.Features.Bookings.Commands.CheckInVisit;
|
||||
using Baya.Application.Features.Bookings.Commands.CheckOutVisit;
|
||||
using Baya.Application.Features.Bookings.Queries.GetVisitVerification;
|
||||
using Baya.Application.Features.Bookings.Queries.ListSessionsForNurse;
|
||||
using Baya.Application.Models.Booking;
|
||||
using Baya.Application.Models.Common;
|
||||
using Baya.WebFramework.Attributes;
|
||||
using Baya.WebFramework.BaseController;
|
||||
using Baya.WebFramework.ServiceConfiguration;
|
||||
using Mediator;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.RateLimiting;
|
||||
|
||||
namespace Baya.Web.Api.Controllers.V1;
|
||||
|
||||
/// <summary>
|
||||
/// The per-visit surface: the assigned nurse's EVV check-in/out, their "today" session list, per-session EVV
|
||||
/// detail (raw GPS gated to the owning nurse + admin), and a single-session cancel. Tenancy is enforced in
|
||||
/// the handlers via <c>ICurrentUser</c>.
|
||||
/// </summary>
|
||||
[ApiVersion("1")]
|
||||
[ApiController]
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
[Authorize]
|
||||
[Display(Description = "Booking sessions & EVV (check-in/out, today's visits, EVV detail, session cancel)")]
|
||||
public sealed class BookingSessionsController(ISender sender) : BaseController
|
||||
{
|
||||
[HttpPost("[action]/{id}")]
|
||||
[ProducesOkApiResponseType<VisitVerificationDto>]
|
||||
public async Task<IActionResult> CheckIn(long id, CheckInVisitCommand command, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(command with { SessionId = id }, cancellationToken));
|
||||
|
||||
[HttpPost("[action]/{id}")]
|
||||
[ProducesOkApiResponseType<VisitVerificationDto>]
|
||||
public async Task<IActionResult> CheckOut(long id, CheckOutVisitCommand command, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(command with { SessionId = id }, cancellationToken));
|
||||
|
||||
[HttpGet("[action]")]
|
||||
[ProducesOkApiResponseType<PagedResult<BookingSessionListItemDto>>]
|
||||
public async Task<IActionResult> Today([FromQuery] ListSessionsForNurseQuery query, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(query, cancellationToken));
|
||||
|
||||
[HttpGet("[action]/{id}")]
|
||||
[ProducesOkApiResponseType<VisitVerificationDto>]
|
||||
public async Task<IActionResult> Evv(long id, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(new GetVisitVerificationQuery(id), cancellationToken));
|
||||
|
||||
[HttpPost("[action]/{id}")]
|
||||
[EnableRateLimiting(RateLimitingServiceExtension.SensitivePolicy)]
|
||||
[ProducesOkApiResponseType<CancellationResultDto>]
|
||||
public async Task<IActionResult> Cancel(long id, CancelSessionCommand command, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(command with { SessionId = id }, cancellationToken));
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Asp.Versioning;
|
||||
using Baya.Application.Features.Bookings.Commands.CancelBooking;
|
||||
using Baya.Application.Features.Bookings.Commands.ConvertRequestToBooking;
|
||||
using Baya.Application.Features.Bookings.Commands.SubmitCareInstructions;
|
||||
using Baya.Application.Features.Bookings.Commands.TransitionBookingStatus;
|
||||
using Baya.Application.Features.Bookings.Queries.GetBookingDetail;
|
||||
using Baya.Application.Features.Bookings.Queries.GetCareInstructions;
|
||||
using Baya.Application.Features.Bookings.Queries.ListBookings;
|
||||
using Baya.Application.Models.Booking;
|
||||
using Baya.Application.Models.Common;
|
||||
using Baya.WebFramework.Attributes;
|
||||
using Baya.WebFramework.BaseController;
|
||||
using Baya.WebFramework.ServiceConfiguration;
|
||||
using Mediator;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.RateLimiting;
|
||||
|
||||
namespace Baya.Web.Api.Controllers.V1;
|
||||
|
||||
/// <summary>
|
||||
/// The confirmed-booking surface: the (mock) payment-capture conversion, role-scoped detail + list, the
|
||||
/// admin/dispute status transition, and the stage-2 care-instructions submit (customer/admin) + gated read
|
||||
/// (assigned nurse/admin, post-confirmation). Tenancy is enforced in the handlers; money is IRR digit-strings.
|
||||
/// </summary>
|
||||
[ApiVersion("1")]
|
||||
[ApiController]
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
[Authorize]
|
||||
[Display(Description = "Confirmed bookings (convert/detail/list, transition, care instructions)")]
|
||||
public sealed class BookingsController(ISender sender) : BaseController
|
||||
{
|
||||
// The mock/test conversion path — b10's real card capture calls ConvertRequestToBooking directly.
|
||||
[HttpPost("[action]")]
|
||||
[EnableRateLimiting(RateLimitingServiceExtension.SensitivePolicy)]
|
||||
[ProducesOkApiResponseType<BookingDetailDto>]
|
||||
public async Task<IActionResult> Convert(ConvertRequestToBookingCommand command, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(command, cancellationToken));
|
||||
|
||||
[HttpGet("[action]/{id}")]
|
||||
[ProducesOkApiResponseType<BookingDetailDto>]
|
||||
public async Task<IActionResult> Get(long id, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(new GetBookingDetailQuery(id), cancellationToken));
|
||||
|
||||
[HttpGet("[action]")]
|
||||
[ProducesOkApiResponseType<PagedResult<BookingListItemDto>>]
|
||||
public async Task<IActionResult> List([FromQuery] ListBookingsQuery query, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(query, cancellationToken));
|
||||
|
||||
// Admin/dispute moves only (enforced in the handler); cancellation goes through Cancel below.
|
||||
[HttpPost("[action]/{id}")]
|
||||
[ProducesOkApiResponseType<BookingDetailDto>]
|
||||
public async Task<IActionResult> Transition(long id, TransitionBookingStatusCommand command, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(command with { BookingId = id }, cancellationToken));
|
||||
|
||||
[HttpPost("[action]/{id}")]
|
||||
[EnableRateLimiting(RateLimitingServiceExtension.SensitivePolicy)]
|
||||
[ProducesOkApiResponseType<CancellationResultDto>]
|
||||
public async Task<IActionResult> Cancel(long id, CancelBookingCommand command, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(command with { BookingId = id }, cancellationToken));
|
||||
|
||||
[HttpPost("[action]/{id}")]
|
||||
[ProducesOkApiResponseType<CareInstructionsDto>]
|
||||
public async Task<IActionResult> SubmitCareInstructions(long id, SubmitCareInstructionsCommand command, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(command with { BookingId = id }, cancellationToken));
|
||||
|
||||
// Gated stage-2 read — assigned nurse + admin only, post-confirmation.
|
||||
[HttpGet("[action]/{id}")]
|
||||
[ProducesOkApiResponseType<CareInstructionsDto>]
|
||||
public async Task<IActionResult> CareInstructions(long id, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(new GetCareInstructionsQuery(id), cancellationToken));
|
||||
}
|
||||
Reference in New Issue
Block a user