2026-02-05 21:35:26 +01:00
|
|
|
using System.Security.Claims;
|
|
|
|
|
using Books.Api.Authorization;
|
2026-01-18 02:52:30 +01:00
|
|
|
using Books.Api.Commands.Companies;
|
2026-02-05 21:35:26 +01:00
|
|
|
using Books.Api.Commands.UserAccess;
|
2026-01-18 02:52:30 +01:00
|
|
|
using Books.Api.Domain.Companies;
|
2026-02-05 21:35:26 +01:00
|
|
|
using Books.Api.Domain.UserAccess;
|
2026-01-18 02:52:30 +01:00
|
|
|
using Books.Api.EventFlow.Repositories;
|
|
|
|
|
using Books.Api.GraphQL.InputTypes;
|
|
|
|
|
using Books.Api.GraphQL.Types;
|
|
|
|
|
using EventFlow;
|
|
|
|
|
using GraphQL;
|
|
|
|
|
using GraphQL.Types;
|
|
|
|
|
|
|
|
|
|
namespace Books.Api.GraphQL.Mutations;
|
|
|
|
|
|
|
|
|
|
public class BooksMutation : ObjectGraphType
|
|
|
|
|
{
|
|
|
|
|
public BooksMutation()
|
|
|
|
|
{
|
|
|
|
|
Name = "Mutation";
|
|
|
|
|
Description = "Root mutation for the Books API";
|
|
|
|
|
|
|
|
|
|
// createCompany(input: CreateCompanyInput!): CompanyType
|
|
|
|
|
Field<CompanyType>("createCompany")
|
|
|
|
|
.Description("Create a new company")
|
|
|
|
|
.Argument<NonNullGraphType<CreateCompanyInputType>>("input", "The company data")
|
|
|
|
|
.ResolveAsync(async ctx =>
|
|
|
|
|
{
|
|
|
|
|
var input = ctx.GetArgument<CreateCompanyInput>("input");
|
|
|
|
|
var commandBus = ctx.RequestServices!.GetRequiredService<ICommandBus>();
|
|
|
|
|
var repository = ctx.RequestServices!.GetRequiredService<ICompanyRepository>();
|
|
|
|
|
|
|
|
|
|
var companyId = CompanyId.New;
|
|
|
|
|
|
|
|
|
|
var command = new CreateCompanyCommand(
|
|
|
|
|
companyId,
|
|
|
|
|
input.Name,
|
|
|
|
|
input.Cvr,
|
|
|
|
|
input.Address,
|
|
|
|
|
input.PostalCode,
|
|
|
|
|
input.City,
|
|
|
|
|
input.Country ?? "DK",
|
|
|
|
|
input.FiscalYearStartMonth ?? 1,
|
|
|
|
|
input.Currency ?? "DKK",
|
|
|
|
|
input.VatRegistered ?? false,
|
|
|
|
|
input.VatPeriodFrequency);
|
|
|
|
|
|
|
|
|
|
await commandBus.PublishAsync(command, ctx.CancellationToken);
|
|
|
|
|
|
2026-02-05 21:35:26 +01:00
|
|
|
// Grant the creating user owner access to the new company
|
|
|
|
|
var httpContext = ctx.RequestServices!.GetRequiredService<IHttpContextAccessor>().HttpContext;
|
|
|
|
|
var userId = httpContext?.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
|
|
|
|
if (userId != null)
|
|
|
|
|
{
|
|
|
|
|
var accessId = UserCompanyAccessId.FromUserAndCompany(userId, companyId.Value);
|
|
|
|
|
var grantCmd = new GrantUserCompanyAccessCommand(
|
|
|
|
|
accessId, userId, companyId.Value, CompanyRole.Owner, userId);
|
|
|
|
|
await commandBus.PublishAsync(grantCmd, ctx.CancellationToken);
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-18 02:52:30 +01:00
|
|
|
// Return the created company (eventually consistent)
|
|
|
|
|
return await repository.GetByIdAsync(companyId.Value, ctx.CancellationToken);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// updateCompany(id: ID!, input: UpdateCompanyInput!): CompanyType
|
|
|
|
|
Field<CompanyType>("updateCompany")
|
|
|
|
|
.Description("Update an existing company")
|
|
|
|
|
.Argument<NonNullGraphType<IdGraphType>>("id", "The company ID")
|
|
|
|
|
.Argument<NonNullGraphType<UpdateCompanyInputType>>("input", "The updated company data")
|
|
|
|
|
.ResolveAsync(async ctx =>
|
|
|
|
|
{
|
|
|
|
|
var id = ctx.GetArgument<string>("id");
|
2026-02-05 21:35:26 +01:00
|
|
|
|
|
|
|
|
// Require Owner or Accountant role to update a company
|
|
|
|
|
var accessService = ctx.RequestServices!.GetRequiredService<ICompanyAccessService>();
|
|
|
|
|
await accessService.RequireAccessAsync(id, CompanyRole.Accountant, ctx.CancellationToken);
|
|
|
|
|
|
2026-01-18 02:52:30 +01:00
|
|
|
var input = ctx.GetArgument<UpdateCompanyInput>("input");
|
|
|
|
|
var commandBus = ctx.RequestServices!.GetRequiredService<ICommandBus>();
|
|
|
|
|
var repository = ctx.RequestServices!.GetRequiredService<ICompanyRepository>();
|
|
|
|
|
|
|
|
|
|
var companyId = CompanyId.With(id);
|
|
|
|
|
|
|
|
|
|
var command = new UpdateCompanyCommand(
|
|
|
|
|
companyId,
|
|
|
|
|
input.Name,
|
|
|
|
|
input.Cvr,
|
|
|
|
|
input.Address,
|
|
|
|
|
input.PostalCode,
|
|
|
|
|
input.City,
|
|
|
|
|
input.Country ?? "DK",
|
|
|
|
|
input.FiscalYearStartMonth ?? 1,
|
|
|
|
|
input.Currency ?? "DKK",
|
|
|
|
|
input.VatRegistered ?? false,
|
|
|
|
|
input.VatPeriodFrequency);
|
|
|
|
|
|
|
|
|
|
await commandBus.PublishAsync(command, ctx.CancellationToken);
|
|
|
|
|
|
|
|
|
|
return await repository.GetByIdAsync(companyId.Value, ctx.CancellationToken);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|