backend phase 15 & frontend phase 8
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Asp.Versioning;
|
||||
using Baya.Application.Features.PartnerCenters.Commands.CreatePartnerCenter;
|
||||
using Baya.Application.Features.PartnerCenters.Commands.SponsorNurse;
|
||||
using Baya.Application.Features.PartnerCenters.Commands.UpdatePartnerCenter;
|
||||
using Baya.Application.Features.PartnerCenters.Commands.VerifyPartnerCenter;
|
||||
using Baya.Application.Features.PartnerCenters.Queries.GetPartnerCenterById;
|
||||
using Baya.Application.Features.PartnerCenters.Queries.ListPartnerCenters;
|
||||
using Baya.Application.Models.Common;
|
||||
using Baya.Application.Models.PartnerCenters;
|
||||
using Baya.Infrastructure.Identity.Identity.PermissionManager;
|
||||
using Baya.WebFramework.Attributes;
|
||||
using Baya.WebFramework.BaseController;
|
||||
using Mediator;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Baya.Web.Api.Controllers.V1;
|
||||
|
||||
/// <summary>
|
||||
/// Admin partner-center console (admin/super_admin). Creates/updates/verifies licensed centers and sponsors
|
||||
/// nurses. The settlement IBAN is encrypted at rest and returned <b>masked</b> (last 4). Internal-only, audited.
|
||||
/// </summary>
|
||||
[ApiVersion("1")]
|
||||
[ApiController]
|
||||
[Route("api/v{version:apiVersion}/admin/partner-centers")]
|
||||
[Authorize(ConstantPolicies.DynamicPermission)]
|
||||
[Display(Description = "Admin partner-center management (licensed sponsor / merchant-of-record)")]
|
||||
public sealed class AdminPartnerCentersController(ISender sender) : BaseController
|
||||
{
|
||||
[HttpPost]
|
||||
[ProducesOkApiResponseType<PartnerCenterDetailDto>]
|
||||
public async Task<IActionResult> Create(CreatePartnerCenterCommand command, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(command, cancellationToken));
|
||||
|
||||
[HttpPatch("{id}")]
|
||||
[ProducesOkApiResponseType<PartnerCenterDetailDto>]
|
||||
public async Task<IActionResult> Update(long id, UpdatePartnerCenterCommand command, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(command with { Id = id }, cancellationToken));
|
||||
|
||||
[HttpPost("{id}/verify")]
|
||||
[ProducesOkApiResponseType<PartnerCenterDetailDto>]
|
||||
public async Task<IActionResult> Verify(long id, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(new VerifyPartnerCenterCommand(id), cancellationToken));
|
||||
|
||||
[HttpPost("{id}/sponsor-nurse")]
|
||||
[ProducesOkApiResponseType]
|
||||
public async Task<IActionResult> SponsorNurse(long id, SponsorNurseCommand command, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(command with { CenterId = id }, cancellationToken));
|
||||
|
||||
[HttpGet]
|
||||
[ProducesOkApiResponseType<PagedResult<PartnerCenterListItemDto>>]
|
||||
public async Task<IActionResult> List([FromQuery] ListPartnerCentersQuery query, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(query, cancellationToken));
|
||||
|
||||
[HttpGet("{id}")]
|
||||
[ProducesOkApiResponseType<PartnerCenterDetailDto>]
|
||||
public async Task<IActionResult> GetById(long id, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(new GetPartnerCenterByIdQuery(id), cancellationToken));
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Asp.Versioning;
|
||||
using Baya.Application.Features.Messaging.Queries.GetTicketThread;
|
||||
using Baya.Application.Features.Messaging.Queries.ListTicketsForAdmin;
|
||||
using Baya.Application.Models.Common;
|
||||
using Baya.Application.Models.Messaging;
|
||||
using Baya.Infrastructure.Identity.Identity.PermissionManager;
|
||||
using Baya.WebFramework.Attributes;
|
||||
using Baya.WebFramework.BaseController;
|
||||
using Mediator;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Baya.Web.Api.Controllers.V1;
|
||||
|
||||
/// <summary>Admin ticket console (support/admin): the global queue and the <b>admin</b> thread view (internal
|
||||
/// notes included). Internal-only, RBAC-gated, audited.</summary>
|
||||
[ApiVersion("1")]
|
||||
[ApiController]
|
||||
[Route("api/v{version:apiVersion}/admin/tickets")]
|
||||
[Authorize(ConstantPolicies.DynamicPermission)]
|
||||
[Display(Description = "Admin ticket queue + full (internal-inclusive) thread view")]
|
||||
public sealed class AdminTicketsController(ISender sender) : BaseController
|
||||
{
|
||||
[HttpGet]
|
||||
[ProducesOkApiResponseType<PagedResult<TicketSummaryDto>>]
|
||||
public async Task<IActionResult> List([FromQuery] ListTicketsForAdminQuery query, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(query, cancellationToken));
|
||||
|
||||
// Admin view — internal notes ARE returned.
|
||||
[HttpGet("{id}")]
|
||||
[ProducesOkApiResponseType<TicketThreadDto>]
|
||||
public async Task<IActionResult> Thread(long id, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(new GetTicketThreadQuery(id, AsAdmin: true), cancellationToken));
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Asp.Versioning;
|
||||
using Baya.Application.Features.PartnerCenters.Queries.GetCenterDashboard;
|
||||
using Baya.Application.Models.PartnerCenters;
|
||||
using Baya.WebFramework.Attributes;
|
||||
using Baya.WebFramework.BaseController;
|
||||
using Mediator;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Baya.Web.Api.Controllers.V1;
|
||||
|
||||
/// <summary>The partner-center portal — scoped to the center's own dashboard account (or staff). Surfaces the
|
||||
/// sponsored nurses + booking/invoice counts + the masked settlement summary.</summary>
|
||||
[ApiVersion("1")]
|
||||
[ApiController]
|
||||
[Route("api/v{version:apiVersion}/centers")]
|
||||
[Authorize]
|
||||
[Display(Description = "Partner-center dashboard (center account scoped)")]
|
||||
public sealed class CentersController(ISender sender) : BaseController
|
||||
{
|
||||
[HttpGet("{id}/dashboard")]
|
||||
[ProducesOkApiResponseType<CenterDashboardDto>]
|
||||
public async Task<IActionResult> Dashboard(long id, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(new GetCenterDashboardQuery(id), cancellationToken));
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Asp.Versioning;
|
||||
using Baya.Application.Features.PartnerCenters.Queries.GetCenterForBooking;
|
||||
using Baya.Application.Models.PartnerCenters;
|
||||
using Baya.Infrastructure.Identity.Identity.PermissionManager;
|
||||
using Baya.WebFramework.Attributes;
|
||||
using Baya.WebFramework.BaseController;
|
||||
using Mediator;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Baya.Web.Api.Controllers.V1;
|
||||
|
||||
/// <summary>Internal/admin resolver: which center legally covers a booking (invoice issuer + settlement target).
|
||||
/// The single merchant-of-record decision — invoices and settlement follow <c>partner_centers</c>.</summary>
|
||||
[ApiVersion("1")]
|
||||
[ApiController]
|
||||
[Route("api/v{version:apiVersion}/internal/bookings")]
|
||||
[Authorize(ConstantPolicies.DynamicPermission)]
|
||||
[Display(Description = "Internal: resolve the invoice issuer / settlement center for a booking")]
|
||||
public sealed class InternalCentersController(ISender sender) : BaseController
|
||||
{
|
||||
[HttpGet("{bookingId}/center")]
|
||||
[ProducesOkApiResponseType<CenterForBookingDto>]
|
||||
public async Task<IActionResult> CenterForBooking(long bookingId, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(new GetCenterForBookingQuery(bookingId), cancellationToken));
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Asp.Versioning;
|
||||
using Baya.Application.Features.Messaging.Commands.AddParticipant;
|
||||
using Baya.Application.Features.Messaging.Commands.CloseTicket;
|
||||
using Baya.Application.Features.Messaging.Commands.LogEmergencyTicket;
|
||||
using Baya.Application.Features.Messaging.Commands.OpenTicket;
|
||||
using Baya.Application.Features.Messaging.Commands.PostMessage;
|
||||
using Baya.Application.Features.Messaging.Commands.RemoveParticipant;
|
||||
using Baya.Application.Features.Messaging.Commands.ReopenTicket;
|
||||
using Baya.Application.Features.Messaging.Queries.GetTicketThread;
|
||||
using Baya.Application.Features.Messaging.Queries.ListMyTickets;
|
||||
using Baya.Application.Models.Common;
|
||||
using Baya.Application.Models.Messaging;
|
||||
using Baya.WebFramework.Attributes;
|
||||
using Baya.WebFramework.BaseController;
|
||||
using Mediator;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Baya.Web.Api.Controllers.V1;
|
||||
|
||||
/// <summary>
|
||||
/// The ticket system — the only sanctioned post-booking communication channel. All reads/writes are
|
||||
/// participation-gated (staff may attach to any ticket). The user thread view never contains an internal note.
|
||||
/// </summary>
|
||||
[ApiVersion("1")]
|
||||
[ApiController]
|
||||
[Route("api/v{version:apiVersion}/tickets")]
|
||||
[Authorize]
|
||||
[Display(Description = "Post-booking ticket communication (participant-scoped)")]
|
||||
public sealed class TicketsController(ISender sender) : BaseController
|
||||
{
|
||||
[HttpPost]
|
||||
[ProducesOkApiResponseType<OpenTicketResult>]
|
||||
public async Task<IActionResult> Open(OpenTicketCommand command, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(command, cancellationToken));
|
||||
|
||||
[HttpPost("emergency")]
|
||||
[ProducesOkApiResponseType<OpenTicketResult>]
|
||||
public async Task<IActionResult> Emergency(LogEmergencyTicketCommand command, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(command, cancellationToken));
|
||||
|
||||
[HttpPost("{id}/messages")]
|
||||
[ProducesOkApiResponseType<PostMessageResult>]
|
||||
public async Task<IActionResult> PostMessage(long id, PostMessageCommand command, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(command with { TicketId = id }, cancellationToken));
|
||||
|
||||
[HttpPost("{id}/participants")]
|
||||
[ProducesOkApiResponseType]
|
||||
public async Task<IActionResult> AddParticipant(long id, AddParticipantCommand command, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(command with { TicketId = id }, cancellationToken));
|
||||
|
||||
[HttpDelete("{id}/participants/{userId}")]
|
||||
[ProducesOkApiResponseType]
|
||||
public async Task<IActionResult> RemoveParticipant(long id, int userId, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(new RemoveParticipantCommand(id, userId), cancellationToken));
|
||||
|
||||
[HttpPost("{id}/close")]
|
||||
[ProducesOkApiResponseType]
|
||||
public async Task<IActionResult> Close(long id, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(new CloseTicketCommand(id), cancellationToken));
|
||||
|
||||
[HttpPost("{id}/reopen")]
|
||||
[ProducesOkApiResponseType]
|
||||
public async Task<IActionResult> Reopen(long id, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(new ReopenTicketCommand(id), cancellationToken));
|
||||
|
||||
[HttpGet]
|
||||
[ProducesOkApiResponseType<PagedResult<TicketSummaryDto>>]
|
||||
public async Task<IActionResult> ListMine([FromQuery] ListMyTicketsQuery query, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(query, cancellationToken));
|
||||
|
||||
// User view — internal notes are stripped in the query projection.
|
||||
[HttpGet("{id}")]
|
||||
[ProducesOkApiResponseType<TicketThreadDto>]
|
||||
public async Task<IActionResult> Thread(long id, CancellationToken cancellationToken)
|
||||
=> OperationResult(await sender.Send(new GetTicketThreadQuery(id, AsAdmin: false), cancellationToken));
|
||||
}
|
||||
Reference in New Issue
Block a user