{"id":50995242,"url":"https://github.com/group10-tc-01/fcs-campaign","last_synced_at":"2026-06-20T08:31:59.835Z","repository":{"id":362599136,"uuid":"1257720368","full_name":"group10-tc-01/fcs-campaign","owner":"group10-tc-01","description":"Serviço de Campanhas e Transparência da plataforma Conexão Solidária — administração de campanhas por GestorONG, exposição pública de campanhas ativas e atualização do valor arrecadado após doações","archived":false,"fork":false,"pushed_at":"2026-06-18T02:21:46.000Z","size":126,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-18T04:16:26.255Z","etag":null,"topics":["aspnet-core","clean-architecture","dotnet","fiap","hackathon","jwt","keycloak","microsservicos"],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/group10-tc-01.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-03T00:24:08.000Z","updated_at":"2026-06-07T23:00:11.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/group10-tc-01/fcs-campaign","commit_stats":null,"previous_names":["group10-tc-01/fcs-campaign"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/group10-tc-01/fcs-campaign","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/group10-tc-01%2Ffcs-campaign","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/group10-tc-01%2Ffcs-campaign/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/group10-tc-01%2Ffcs-campaign/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/group10-tc-01%2Ffcs-campaign/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/group10-tc-01","download_url":"https://codeload.github.com/group10-tc-01/fcs-campaign/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/group10-tc-01%2Ffcs-campaign/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34563535,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-20T02:00:06.407Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aspnet-core","clean-architecture","dotnet","fiap","hackathon","jwt","keycloak","microsservicos"],"created_at":"2026-06-20T08:31:59.740Z","updated_at":"2026-06-20T08:31:59.820Z","avatar_url":"https://github.com/group10-tc-01.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# fcs-campaign\n\nServiço de **Campanhas e Transparência** da plataforma **Conexão Solidária**. É responsável pela administração de campanhas por **GestorONG**, exposição pública de campanhas ativas e atualização idempotente do valor arrecadado após o processamento de doações.\n\n\u003e Microsserviço que compõe o MVP da Conexão Solidária junto a `fcs-identity`, `fcs-donations`, `fcs-donation-worker`, `fcs-audit-logs`, `fcs-solidarity-web` e `fcs-solidarity-infra`.\n\n---\n\n## Responsabilidades\n\n- Criação, edição, conclusão e cancelamento de **Campanhas** por usuários com role `GestorONG`.\n- Listagem administrativa de campanhas.\n- Listagem pública de campanhas ativas para o **Painel de Transparência**.\n- Validação interna de elegibilidade de campanha para receber intenção de doação.\n- Atualização interna e idempotente do `TotalAmountRaised` quando uma doação é processada.\n- Persistência própria no `CampaignsDb`, sem foreign key para databases de outros serviços.\n- Auditoria explícita de eventos relevantes via tópico Kafka `audit-log-requested`.\n\nA aplicação **não** recebe intenções de doação diretamente. Esse fluxo pertence à `fcs-donations`, que valida a campanha via API interna e publica eventos para processamento assíncrono pelo `fcs-donation-worker`.\n\nDocumentação completa da arquitetura: [group10-tc-01/fcs-fase05-docs](https://github.com/group10-tc-01/fcs-fase05-docs).\n\nReferências diretas:\n\n- [Visão geral da arquitetura](https://github.com/group10-tc-01/fcs-fase05-docs/blob/main/architecture/overview.md)\n- [Modelo da fcs-campaigns](https://github.com/group10-tc-01/fcs-fase05-docs/blob/main/architecture/fcs-campaigns-model.md)\n- [Fluxos de endpoints](https://github.com/group10-tc-01/fcs-fase05-docs/blob/main/architecture/endpoint-flows.md)\n- [Modelo de banco de dados](https://github.com/group10-tc-01/fcs-fase05-docs/blob/main/architecture/database-model.md)\n\nADRs relevantes:\n\n- [ADR 0002 - Separação de serviços de campanhas e doações](https://github.com/group10-tc-01/fcs-fase05-docs/blob/main/adr/0002-service-boundaries-for-campaigns-and-donations.md)\n- [ADR 0005 - Campanhas gerenciam campanhas e transparência](https://github.com/group10-tc-01/fcs-fase05-docs/blob/main/adr/0005-campaigns-own-campaign-management-and-transparency.md)\n- [ADR 0007 - Validação de elegibilidade via HTTP](https://github.com/group10-tc-01/fcs-fase05-docs/blob/main/adr/0007-validate-campaign-eligibility-over-http.md)\n- [ADR 0010 - Worker atualiza campanhas via API interna](https://github.com/group10-tc-01/fcs-fase05-docs/blob/main/adr/0010-worker-updates-campaigns-through-internal-api.md)\n- [ADR 0011 - SQL Server para databases de serviço](https://github.com/group10-tc-01/fcs-fase05-docs/blob/main/adr/0011-use-sql-server-for-service-databases.md)\n- [ADR 0012 - Entity Framework Core](https://github.com/group10-tc-01/fcs-fase05-docs/blob/main/adr/0012-use-entity-framework-core.md)\n\n---\n\n## Perfis e Roles\n\nRoles canônicas do MVP:\n\n| Role        | Uso no serviço |\n|-------------|----------------|\n| `GestorONG` | Pode criar, editar, concluir, cancelar e consultar campanhas administrativas |\n| `Doador`    | Não administra campanhas; participa por meio da `fcs-donations` |\n\n\u003e Termos a evitar: `Admin`, `User`, `Manager`, `SuperAdmin`. Os perfis canônicos do domínio são **Doador** e **GestorONG**.\n\n---\n\n## Estrutura do projeto\n\n```text\nsrc/\n  fcs.Campaign.Domain/                  # Campaign, CampaignDonationEntry, regras de domínio\n  fcs.Campaign.Application/             # Casos de uso, CQRS, validação, auditoria\n  fcs.Campaign.Messages/                # Contratos de mensagens quando necessário\n  fcs.Campaign.Infrastructure.Auth/     # Validação de JWT emitido pelo Keycloak\n  fcs.Campaign.Infrastructure.SqlServer/# EF Core + CampaignsDb\n  fcs.Campaign.Infrastructure.Kafka/    # Publicação de eventos de auditoria\n  fcs.Campaign.WebApi/                  # Controllers v1, controllers internos, middlewares, DI, /health\ntests/\n  fcs.Campaign.UnitTests/\n  fcs.Campaign.IntegratedTests/\n  fcs.Campaign.FunctionalTests/\n  fcs.Campaign.CommomTestsUtilities/\n```\n\nEstrutura interna alinhada ao padrão da fase 04 ([ADR 0023](https://github.com/group10-tc-01/fcs-fase05-docs/blob/main/adr/0023-use-phase-04-dotnet-service-structure.md)).\n\n---\n\n## Endpoints\n\nBase path público versionado: `/api/v1`.\n\n| Método | Rota                                      | Acesso      | Descrição |\n|--------|-------------------------------------------|-------------|-----------|\n| POST   | `/api/v1/campaigns`                       | `GestorONG` | Cria uma campanha ativa |\n| PUT    | `/api/v1/campaigns/{id}`                  | `GestorONG` | Edita uma campanha ativa |\n| PATCH  | `/api/v1/campaigns/{id}/complete`         | `GestorONG` | Conclui uma campanha ativa |\n| PATCH  | `/api/v1/campaigns/{id}/cancel`           | `GestorONG` | Cancela uma campanha ativa |\n| GET    | `/api/v1/campaigns?page=1\u0026pageSize=10`    | `GestorONG` | Lista campanhas para gestão |\n| GET    | `/api/v1/transparency/campaigns`          | Público     | Lista campanhas ativas para transparência |\n| GET    | `/health`                                 | Operacional | Healthcheck |\n\nEndpoints internos entre serviços:\n\n| Método | Rota                                                   | Acesso interno | Descrição |\n|--------|--------------------------------------------------------|----------------|-----------|\n| GET    | `/internal/campaigns/{id}/donation-eligibility`        | Cluster/rede   | Informa se a campanha pode receber doação |\n| POST   | `/internal/campaigns/{id}/donation-processed`          | Cluster/rede   | Reflete uma doação processada de forma idempotente |\n\nPadrão de resposta `ApiResponse\u003cT\u003e` documentado em [endpoints.md](https://github.com/group10-tc-01/fcs-fase05-docs/blob/main/architecture/endpoints.md).\n\n### Exemplo: criar campanha\n\n```http\nPOST /api/v1/campaigns\nAuthorization: Bearer \u003cjwt-gestorong\u003e\nContent-Type: application/json\n\n{\n  \"title\": \"Campanha de inverno\",\n  \"description\": \"Arrecadação para compra de cobertores.\",\n  \"startDate\": \"2026-06-01T00:00:00Z\",\n  \"endDate\": \"2026-07-01T00:00:00Z\",\n  \"financialGoal\": 10000.00\n}\n```\n\n### Exemplo: consultar transparência\n\n```http\nGET /api/v1/transparency/campaigns?page=1\u0026pageSize=10\n```\n\n### Exemplo: validar elegibilidade de doação\n\n```http\nGET /internal/campaigns/{campaignId}/donation-eligibility\n```\n\n### Exemplo: refletir doação processada\n\n```http\nPOST /internal/campaigns/{campaignId}/donation-processed\nContent-Type: application/json\n\n{\n  \"donationId\": \"00000000-0000-0000-0000-000000000001\",\n  \"amount\": 100.00,\n  \"processedAt\": \"2026-06-01T12:00:00Z\"\n}\n```\n\nO endpoint é idempotente por `CampaignId + DonationId`. Uma segunda chamada com a mesma doação não soma o valor novamente.\n\n---\n\n## Regras de negócio\n\n- Apenas `GestorONG` administra campanhas.\n- Toda campanha nova nasce com status `Active`.\n- Apenas campanhas `Active` podem ser editadas.\n- Transições permitidas:\n  - `Active -\u003e Completed`\n  - `Active -\u003e Canceled`\n- Campanhas `Completed` ou `Canceled` não voltam para `Active`.\n- `EndDate` não pode estar no passado.\n- `FinancialGoal` deve ser maior que zero.\n- Apenas campanhas `Active` aparecem no painel público de transparência.\n- Apenas campanhas `Active` podem receber doação.\n- Doações processadas são refletidas no total arrecadado com idempotência por `DonationId`.\n\n---\n\n## Pré-requisitos\n\n- [.NET 8 SDK](https://dotnet.microsoft.com/download)\n- [Docker](https://docs.docker.com/get-docker/) e Docker Compose\n- Keycloak/realm da plataforma disponível via `fcs-identity` ou ambiente integrado\n- Portas livres no host: `5433` (SQL Server), `9092` (Kafka), `2181` (Zookeeper), `5341` (Seq), `8080` (API em container), `5000` (API local)\n\n---\n\n## Subindo o ambiente local\n\nO `docker-compose.yml` deste repositório sobe **apenas** as dependências locais deste serviço (SQL Server, Kafka, Zookeeper, Seq) e, opcionalmente, a própria API. Para o ambiente completo integrado da Conexão Solidária utilize o repositório `fcs-solidarity-infra`.\n\n### 1. Subir dependências\n\n```bash\ndocker compose up -d sqlserver zookeeper kafka seq\n```\n\nURLs úteis:\n\n- Seq: http://localhost:5341\n- SQL Server: `localhost,5433` (`sa` / `Your_password123`)\n- Kafka: `localhost:9092`\n\n### 2. Aplicar migrations\n\n```bash\ndotnet ef database update \\\n  --project src/fcs.Campaign.Infrastructure.SqlServer \\\n  --startup-project src/fcs.Campaign.WebApi\n```\n\n### 3. Rodar a API localmente\n\n```bash\ndotnet restore\ndotnet build\ndotnet run --project src/fcs.Campaign.WebApi\n```\n\nPor padrão a API sobe em `http://localhost:5000` (perfil `Development`). Acesse o Swagger em `http://localhost:5000/swagger`.\n\n### 3b. Rodar a API também em container\n\n```bash\ndocker compose up -d --build api\n```\n\nA API ficará exposta em `http://localhost:8080`.\n\n---\n\n## Configuração\n\nConfiguração principal em `src/fcs.Campaign.WebApi/appsettings.json`:\n\n```json\n{\n  \"ConnectionStrings\": {\n    \"SqlServer\": \"Server=localhost,5433;Database=CampaignsDb;User Id=sa;Password=Your_password123;TrustServerCertificate=True;\"\n  },\n  \"KafkaSettings\": {\n    \"BootstrapServers\": \"localhost:9092\",\n    \"TopicName\": \"audit-log-requested\"\n  },\n  \"Keycloak\": {\n    \"Authority\": \"http://localhost:8081/realms/conexao-solidaria\",\n    \"Audience\": \"solidarity-api\"\n  }\n}\n```\n\nO JWT é emitido pelo Keycloak via `fcs-identity`. Este serviço apenas valida o token e a role `GestorONG`.\n\n---\n\n## Testes\n\n```bash\n# Todos os testes\ndotnet test\n\n# Por projeto\ndotnet test tests/fcs.Campaign.UnitTests\ndotnet test tests/fcs.Campaign.IntegratedTests\ndotnet test tests/fcs.Campaign.FunctionalTests\n```\n\nCobertura mínima exigida pela esteira: **80%** ([ADR 0025](https://github.com/group10-tc-01/fcs-fase05-docs/blob/main/adr/0025-test-strategy-for-apis-and-worker.md)).\n\n---\n\n## Observabilidade\n\n- Logs estruturados com **Serilog**.\n- **OpenTelemetry** para tracing e métricas.\n- **Seq** disponível no ambiente local.\n- Endpoint operacional:\n  - `GET /health`\n\nEndpoints internos e operacionais não devem ser publicados na borda pública da plataforma ([ADR 0027](https://github.com/group10-tc-01/fcs-fase05-docs/blob/main/adr/0027-keep-internal-apis-cluster-private.md)).\n\n---\n\n## CI/CD\n\nA esteira está em `.github/workflows/` reutilizando os workflows reutilizáveis do repositório `fcs-pipelines` ([ADR 0022](https://github.com/group10-tc-01/fcs-fase05-docs/blob/main/adr/0022-reuse-fcs-pipelines-for-ci-cd.md)):\n\n- `branch-name-check.yml` - política de nomes de branch\n- `dotnet-service-ci.yml` - build .NET, testes, SonarCloud, Trivy, build da imagem Docker\n- `dotnet-service-delivery.yml` - push da imagem para Azure Container Registry e deploy em AKS\n\nGates principais: secret scan (Gitleaks), dependency scan, restore/build, testes com cobertura mínima de 80%, SonarCloud, Docker build, Trivy, deploy condicional e healthcheck pós-rollout.\n\n---\n\n## Kubernetes\n\nManifests Kubernetes deste serviço (Deployment, Service, ConfigMap, Secret) ficam em `k8s/` ou diretório equivalente neste repositório. Para o ambiente integrado (Kind local ou AKS), com Keycloak, Kafka, Prometheus e Grafana compartilhados, consulte o repositório `fcs-solidarity-infra` ([ADR 0026](https://github.com/group10-tc-01/fcs-fase05-docs/blob/main/adr/0026-use-separated-kubernetes-namespaces.md)).\n\nNamespace alvo: `fcs-campaigns`.\n\n---\n\n## Banco de dados\n\n- Engine: **SQL Server** ([ADR 0011](https://github.com/group10-tc-01/fcs-fase05-docs/blob/main/adr/0011-use-sql-server-for-service-databases.md))\n- ORM: **Entity Framework Core** ([ADR 0012](https://github.com/group10-tc-01/fcs-fase05-docs/blob/main/adr/0012-use-entity-framework-core.md))\n- Database: `CampaignsDb`\n- Tabelas principais:\n  - `Campaigns`\n  - `CampaignDonationEntries`\n\nPara aplicar as migrations:\n\n```bash\ndotnet ef database update \\\n  --project src/fcs.Campaign.Infrastructure.SqlServer \\\n  --startup-project src/fcs.Campaign.WebApi\n```\n\n---\n\n## Auditoria\n\nEventos publicados no tópico Kafka `audit-log-requested`:\n\n- `CampaignCreated`\n- `CampaignUpdated`\n- `CampaignCompleted`\n- `CampaignCanceled`\n- `DonationReflected`\n- `DuplicateDonationIgnored`\n\nAuditoria é explícita nos casos de uso relevantes e não usa outbox neste serviço, conforme modelo consolidado em [database-model.md](https://github.com/group10-tc-01/fcs-fase05-docs/blob/main/architecture/database-model.md).\n\n---\n\n## Como este serviço atende ao hackathon\n\n| Requisito do hackathon | Onde é atendido |\n|------------------------|-----------------|\n| Gestão de campanhas por `GestorONG` | Endpoints `/api/v1/campaigns` protegidos por role |\n| Campanhas com status `Active`, `Completed`, `Canceled` | Entidade `Campaign` e `CampaignStatus` |\n| Painel público de transparência | `GET /api/v1/transparency/campaigns` |\n| Bloquear doação para campanha concluída/cancelada | `GET /internal/campaigns/{id}/donation-eligibility` |\n| Atualizar valor arrecadado após processamento assíncrono | `POST /internal/campaigns/{id}/donation-processed` |\n| Idempotência no processamento da doação | Tabela `CampaignDonationEntries` com índice único `CampaignId + DonationId` |\n| Autenticação JWT e RBAC | Validação de token Keycloak e role `GestorONG` |\n| Microsserviço distinto | `fcs-campaign` separado de `fcs-identity`, `fcs-donations` e `fcs-donation-worker` |\n| Banco próprio por serviço | `CampaignsDb` |\n| Docker e pipeline | `Dockerfile`, `docker-compose.yml` e workflows em `.github/workflows` |\n\nOs fluxos de cadastro/login pertencem à `fcs-identity`; as intenções de doação pertencem à `fcs-donations`; o consumo do evento de doação pertence ao `fcs-donation-worker`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgroup10-tc-01%2Ffcs-campaign","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgroup10-tc-01%2Ffcs-campaign","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgroup10-tc-01%2Ffcs-campaign/lists"}