# Etapa 2 — Backend: Company y Office CRUD ## Contexto Ro-ut v2.1.5 tiene la arquitectura completa (SSR React + GraphQL embebido + PostgreSQL) pero solo implementa autenticación y un CRUD básico de usuarios. El schema SQL ya incluye las tablas `Company` y `Office` con todos los campos planeados (Etapa 1 completada). La Etapa 2 expone estas entidades vía GraphQL siguiendo el mismo patrón 4-archivos que User: **model → controller → schema → resolver**. ## Patrón a seguir (basado en User) Cada entidad necesita 4 archivos nuevos + actualización de 3 archivos de registro: | Capa | Patrón User | Company | Office | |------|-------------|---------|--------| | Model | `dataUsuario.ts` | `dataCompany.ts` | `dataOffice.ts` | | Controller | `dataUsuario.ts` | `dataCompany.ts` | `dataOffice.ts` | | Schema | `user.schema.ts` | `company.schema.ts` | `office.schema.ts` | | Resolver | `user.resolver.ts` | `company.resolver.ts` | `office.resolver.ts` | ## Archivos a crear ### 1. Model — `src/server/models/apiPostgresModel/dataCompany.ts` - `getCompany(id)` → SELECT por Id - `getCompanies()` → SELECT sin filtro - `insertCompany(company)` → INSERT RETURNING Id - `editCompany(id, company)` → UPDATE - `deleteCompany(id)` → DELETE ### 2. Model — `src/server/models/apiPostgresModel/dataOffice.ts` - `getOffice(id)` → SELECT por Id - `getOffices()` → SELECT sin filtro - `getOfficesByCompany(companyId)` → SELECT por FK_Company - `insertOffice(office)` → INSERT RETURNING Id - `editOffice(id, office)` → UPDATE - `deleteOffice(id)` → DELETE ### 3. Controller — `src/server/controllers/controllerGraphQL/dataCompany.ts` - Mapea model results: `Id` → `id` (string) - Exporta: `getCompany`, `getCompanies`, `insertCompany`, `editCompany`, `deleteCompany` ### 4. Controller — `src/server/controllers/controllerGraphQL/dataOffice.ts` - Mapea model results: `Id` → `id` (string) - Exporta: `getOffice`, `getOffices`, `getOfficesByCompany`, `insertOffice`, `editOffice`, `deleteOffice` ### 5. Schema — `src/server/GraphQL/schema/company.schema.ts` - `@ObjectType('Company')` — campos: id, name, businessName, type, country, phone - `@InputType('InputCompany')` — campos editables: name, businessName, type, country, phone - `@ObjectType('CompaniesQuery')` — fields: `company(id)`, `companies()` - `@ObjectType('CompanyMutation')` — mutations: `insertCompany`, `editCompany`, `deleteCompany` - Cada field/mutation llama al controller correspondiente ### 6. Schema — `src/server/GraphQL/schema/office.schema.ts` - `@ObjectType('Office')` — campos: id, name, address, email, city, country, lat, lng, company (FK) - `@InputType('InputOffice')` — campos editables - `@ObjectType('OfficesQuery')` — fields: `office(id)`, `offices()`, `officesByCompany(companyId)` - `@ObjectType('OfficeMutation')` — mutations: `insertOffice`, `editOffice`, `deleteOffice` ### 7. Resolver — `src/server/GraphQL/resolvers/company.resolver.ts` - `@Resolver(() => CompanyMutation)` — query `companyMutation()` → CompanyMutation - `@Resolver(() => CompaniesQuery)` — query `companiesQuery()` → CompaniesQuery ### 8. Resolver — `src/server/GraphQL/resolvers/office.resolver.ts` - `@Resolver(() => OfficeMutation)` — query `officeMutation()` → OfficeMutation - `@Resolver(() => OfficesQuery)` — query `officesQuery()` → OfficesQuery ### 9. Tests — `src/server/tests/server/company/index.test.ts` - Tests supertest para: insert, get, list, edit, delete (patrón exacto de `user/index.test.ts`) ### 10. Tests — `src/server/tests/server/office/index.test.ts` - Tests supertest para: insert, get, list, getByCompany, edit, delete ## Archivos a modificar ### 1. `src/server/models/apiPostgresModel/index.ts` ```ts export * from './dataLogIn'; export * from './dataUsuario'; export * from './dataCompany'; export * from './dataOffice'; ``` ### 2. `src/server/controllers/controllerGraphQL/index.ts` ```ts export * from './dataUsuario'; export * from './dataLogin'; export * from './dataCompany'; export * from './dataOffice'; ``` ### 3. `src/server/GraphQL/schema/index.ts` - Import `Company`/`InputCompany`/`CompaniesQuery`/`CompanyMutation` de `company.schema.ts` - Import `Office`/`InputOffice`/`OfficesQuery`/`OfficeMutation` de `office.schema.ts` - Asegurar que se exporten (type-graphql necesita los imports para registrar los decoradores) ### 4. `src/server/GraphQL/resolvers/index.ts` - Import y export `CompanyMutationResolver`, `CompaniesQueryResolver` (o como se llamen) - Import y export `OfficeMutationResolver`, `OfficesQueryResolver` ### 5. `src/server/GraphQL/server.ts` - Agregar los 4 resolvers a `buildSchemaSync({ resolvers: [...] })` ## Ejecución Este plan será ejecutado por un **agente en background** usando la skill global **background-orchestrator**. El agente se encarga de: - Crear los 10 archivos nuevos siguiendo el patrón exacto de User - Modificar los 5 archivos de registro - Verificar con `npm run lint`, `npm run build` y `npm run test:backend` - Crear el PR correspondiente en Gitea ## Verificación 1. `npm run lint` — sin errores 2. `npm run build` — compila sin errores (type-graphql registra todos los decoradores) 3. `npm run test:backend` — tests de integración verdes (requiere PostgreSQL con schema completo) 4. `npm run test:frontend` — tests frontend sin cambios