67060c73b2
Identity (discounts):
- DiscountsController: PUT /v1/discounts/{id}, DELETE /v1/discounts/{id}
- DiscountService.UpdateAsync (partial update, code-clash guard) + DeleteAsync
- UpdateDiscountRequest record (all fields optional incl. is_active)
- Frontend discountsConfig: canEdit + canDelete + is_active field
Content (scenes/colors — UI for existing CRUD endpoints):
- New SceneColorEditor.tsx: 3-tab modal (scenes / shared-colors / color-presets),
project-scoped, full add/edit/delete per tab, colour pickers + palette item editor
- Wired into TemplatesAdmin: "صحنهها و رنگها" button per template variant row
- Routes through the generic admin proxy with ?project_id=
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
65 lines
2.2 KiB
C#
65 lines
2.2 KiB
C#
using FlatRender.IdentitySvc.Application.Services.Interfaces;
|
|
using FlatRender.IdentitySvc.Models.Requests;
|
|
using FlatRender.IdentitySvc.Models.Responses;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
namespace FlatRender.IdentitySvc.Controllers;
|
|
|
|
[ApiController]
|
|
[Route("v1/discounts")]
|
|
[Authorize]
|
|
public class DiscountsController(IDiscountService discountService) : ControllerBase
|
|
{
|
|
[HttpPost("validate")]
|
|
[AllowAnonymous]
|
|
[ProducesResponseType(typeof(DiscountValidateResponse), 200)]
|
|
public async Task<IActionResult> Validate([FromBody] ValidateDiscountRequest request)
|
|
{
|
|
var tenantId = GetTenantIdOrDefault();
|
|
var result = await discountService.ValidateAsync(tenantId, request.Code, request.PlanId);
|
|
return Ok(result);
|
|
}
|
|
|
|
[HttpGet]
|
|
[ProducesResponseType(typeof(PagedResponse<DiscountResponse>), 200)]
|
|
public async Task<IActionResult> List([FromQuery] int page = 1, [FromQuery] int pageSize = 20)
|
|
{
|
|
var result = await discountService.ListAsync(GetTenantId(), page, pageSize);
|
|
return Ok(result);
|
|
}
|
|
|
|
[HttpPost]
|
|
[ProducesResponseType(typeof(DiscountResponse), 201)]
|
|
public async Task<IActionResult> Create([FromBody] CreateDiscountRequest request)
|
|
{
|
|
var result = await discountService.CreateAsync(GetTenantId(), request);
|
|
return StatusCode(201, result);
|
|
}
|
|
|
|
[HttpPut("{id:guid}")]
|
|
[ProducesResponseType(typeof(DiscountResponse), 200)]
|
|
public async Task<IActionResult> Update(Guid id, [FromBody] UpdateDiscountRequest request)
|
|
{
|
|
var result = await discountService.UpdateAsync(GetTenantId(), id, request);
|
|
return result == null ? NotFound() : Ok(result);
|
|
}
|
|
|
|
[HttpDelete("{id:guid}")]
|
|
[ProducesResponseType(204)]
|
|
public async Task<IActionResult> Delete(Guid id)
|
|
{
|
|
var ok = await discountService.DeleteAsync(GetTenantId(), id);
|
|
return ok ? NoContent() : NotFound();
|
|
}
|
|
|
|
private Guid GetTenantId() => Guid.Parse(User.FindFirst("tenant_id")?.Value
|
|
?? throw new UnauthorizedAccessException());
|
|
|
|
private Guid GetTenantIdOrDefault()
|
|
{
|
|
var claim = User.FindFirst("tenant_id")?.Value;
|
|
return claim != null ? Guid.Parse(claim) : Guid.Empty;
|
|
}
|
|
}
|