books/backend/Books.Api/GraphQL/Mutations/BooksMutation.cs
Nicolaj Hartmann 66f6fa138d Initial commit: Books accounting system with EventFlow CQRS
Backend (.NET 10):
- EventFlow CQRS/Event Sourcing with PostgreSQL
- GraphQL.NET API with mutations and queries
- Custom ReadModelSqlGenerator for snake_case PostgreSQL columns
- Hangfire for background job processing
- Integration tests with isolated test databases

Frontend (React/Vite):
- Initial project structure

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 02:52:30 +01:00

82 lines
3.2 KiB
C#

using Books.Api.Commands.Companies;
using Books.Api.Domain.Companies;
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);
// 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");
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);
});
}
}