Fix build and code structure improvements. New but essential UI functionality. CI improvements. Documentation improvements. AI module improvements.

This commit is contained in:
StellaOps Bot
2025-12-26 21:54:17 +02:00
parent 335ff7da16
commit c2b9cd8d1f
3717 changed files with 264714 additions and 48202 deletions

View File

@@ -0,0 +1,116 @@
// ----------------------------------------------------------------------------
// UpdateOrderStatusEndpoint
//
// Demonstrates:
// - PATCH operation for partial updates
// - Path parameters with request body
// - Write authorization claims
// - State machine validation
// ----------------------------------------------------------------------------
using Examples.OrderService.Models;
using Microsoft.Extensions.Logging;
using StellaOps.Microservice;
namespace Examples.OrderService.Endpoints;
/// <summary>
/// Request to update order status.
/// </summary>
public sealed record UpdateOrderStatusRequest
{
public required string OrderId { get; init; }
public required OrderStatus NewStatus { get; init; }
public string? Reason { get; init; }
public string? TrackingNumber { get; init; }
}
/// <summary>
/// Response after status update.
/// </summary>
public sealed record UpdateOrderStatusResponse
{
public required string OrderId { get; init; }
public required OrderStatus PreviousStatus { get; init; }
public required OrderStatus CurrentStatus { get; init; }
public required DateTimeOffset UpdatedAt { get; init; }
public string? Message { get; init; }
}
/// <summary>
/// Endpoint for updating order status with state machine validation.
/// </summary>
[StellaEndpoint("PATCH", "/orders/{id}/status", TimeoutSeconds = 10, RequiredClaims = ["orders:write"])]
[ValidateSchema(
ValidateRequest = true,
ValidateResponse = true,
Summary = "Update order status",
Description = "Updates the status of an order. Status transitions are validated against allowed state machine rules.",
Tags = ["orders", "write", "status"])]
public sealed class UpdateOrderStatusEndpoint : IStellaEndpoint<UpdateOrderStatusRequest, UpdateOrderStatusResponse>
{
private readonly ILogger<UpdateOrderStatusEndpoint> _logger;
// Valid state transitions
private static readonly Dictionary<OrderStatus, OrderStatus[]> ValidTransitions = new()
{
[OrderStatus.Pending] = [OrderStatus.Confirmed, OrderStatus.Cancelled],
[OrderStatus.Confirmed] = [OrderStatus.Processing, OrderStatus.Cancelled],
[OrderStatus.Processing] = [OrderStatus.Shipped, OrderStatus.Cancelled],
[OrderStatus.Shipped] = [OrderStatus.Delivered],
[OrderStatus.Delivered] = [OrderStatus.Refunded],
[OrderStatus.Cancelled] = [],
[OrderStatus.Refunded] = []
};
public UpdateOrderStatusEndpoint(ILogger<UpdateOrderStatusEndpoint> logger)
{
_logger = logger;
}
public Task<UpdateOrderStatusResponse> HandleAsync(
UpdateOrderStatusRequest request,
CancellationToken cancellationToken)
{
// Simulate current status lookup
var currentStatus = OrderStatus.Processing;
_logger.LogInformation(
"Updating order {OrderId} status: {CurrentStatus} -> {NewStatus}",
request.OrderId, currentStatus, request.NewStatus);
// Validate state transition
if (!IsValidTransition(currentStatus, request.NewStatus))
{
_logger.LogWarning(
"Invalid status transition for order {OrderId}: {Current} -> {New}",
request.OrderId, currentStatus, request.NewStatus);
// In real implementation, throw an exception that maps to 422
return Task.FromResult(new UpdateOrderStatusResponse
{
OrderId = request.OrderId,
PreviousStatus = currentStatus,
CurrentStatus = currentStatus, // Unchanged
UpdatedAt = DateTimeOffset.UtcNow,
Message = $"Invalid transition: {currentStatus} cannot transition to {request.NewStatus}"
});
}
return Task.FromResult(new UpdateOrderStatusResponse
{
OrderId = request.OrderId,
PreviousStatus = currentStatus,
CurrentStatus = request.NewStatus,
UpdatedAt = DateTimeOffset.UtcNow,
Message = request.NewStatus == OrderStatus.Shipped
? $"Shipped with tracking: {request.TrackingNumber}"
: null
});
}
private static bool IsValidTransition(OrderStatus current, OrderStatus target)
{
return ValidTransitions.TryGetValue(current, out var allowed) && allowed.Contains(target);
}
}