diff --git a/negodata/backend/README.md b/negodata/backend/README.md index 87efd66..a475691 100644 --- a/negodata/backend/README.md +++ b/negodata/backend/README.md @@ -1,6 +1,6 @@ # Negodata Backend -DerbyMasters_Server 아키텍처를 이식한 FastAPI 골격. 기능은 **JWT id/pw 로그인**만 예시 구현. +DerbyMasters_Server 아키텍처를 이식한 FastAPI 백엔드. 인증(JWT) 위에 **견적·협력사·상품·견적설정·대시보드·알림·협상카드·회사유저관리** 도메인과 **견적 마감 스케줄러**를 구현. [negosium-backend](../../backend/README.md) 와 동일 구조이며, 실행·테스트·벤치마크 종합은 [레포 최상위 README](../../README.md) 참고. ## 디렉토리 구조 @@ -9,19 +9,20 @@ DerbyMasters_Server 아키텍처를 이식한 FastAPI 골격. 기능은 **JWT id negodata/backend/ ├── web_main.py # 엔트리포인트 (uvicorn) ├── config/ # 환경설정 (APP_ENV 별 toml 로드) +├── conftest.py, tests/ # pytest (test DB 자동 create/drop) — 아래 '테스트' ├── common/ -│ ├── enums.py # ErrorType / DBType / DBWRType / EXCEPTION_* +│ ├── enums.py # ErrorType / 코드값 enum / EXCEPTION_* │ ├── models/gmodel.py # 프로토콜 베이스 (WebPacketProtocol 등) │ └── database/ │ ├── db_session_manager.py# ★ DB Read/Write + 람다 실행 핵심 -│ └── model/models.py # ORM 모델 (tbl_account) -├── crud/user_crud.py # DB 접근 (I*CRUD 인터페이스 + 구현) -├── services/auth_service.py # 비즈니스 로직 +│ └── model/models.py # ORM 모델 (companies·users·quotations·sessions·items·suppliers·notifications·cards …) +├── crud/ # 도메인별 DB 접근(I*CRUD 인터페이스+구현): quotation·supplier·item·dashboard·notification·card·user … +├── services/ # 비즈니스 로직: quotation·supplier·item·dashboard·notification·company_user·auth·email … +├── scheduler/ # 견적 마감 크론 잡(만료 마감 · 협상종결 마감) └── router/ - ├── router.py # FastAPI app - └── v1/ - ├── auth/{account,protocol}.py # 엔드포인트 / Req_·Res_ - └── validator/dependencies.py # ★ JWT 발급·검증, 해시, RemoveNoneResponse + ├── router.py # FastAPI app (CORS 등) + └── v1/ # 도메인별 라우터: auth·quotation·quotation_setting·supplier·item·card·dashboard·notification·company + └── validator/dependencies.py # ★ JWT 발급·검증, 해시(bcrypt), RemoveNoneResponse, RequireOwner ``` ## 핵심 패턴 @@ -40,22 +41,53 @@ negodata/backend/ - **ResponseNone**: 응답의 `None` 필드 재귀 제거(`RemoveNoneResponse`). - **bcrypt 비차단**: `GetHashedPW`/`VerifyPW` 를 `asyncio.to_thread` 로 오프로드(이벤트 루프 비차단). → [벤치마크](../../README.md#성능--벤치마크) -## 엔드포인트 -| Method | Path | 설명 | -|---|---|---| -| POST | `/v1/auth/create` | 계정 생성 (pw bcrypt 해시) | -| POST | `/v1/auth/login` | 로그인, access/refresh 토큰 발급 | -| POST | `/v1/auth/refresh_token` | access 토큰 재발급 (refresh 필요) | -| GET | `/v1/auth/me` | 내 정보 (access 토큰 필요) | +## API 도메인 (`/v1/*`) +전체 스펙은 실행 후 **http://localhost:9400/docs** (Swagger). 주요 도메인: -## 실행 / 테스트 +| prefix | 요약 | +|---|---| +| `/v1/auth` | 로그인 · access 토큰 재발급 · 내 정보(`me`). ※ 무인증 계정 생성은 제거됨 | +| `/v1/company/user` | 최고관리자(OWNER) 전용 — 자기 회사 직원 계정 생성·관리 | +| `/v1/quotation` | 견적 생성·목록·단건·마감·재생성 + 세션·채팅·낙찰결과·카드·초청메일 | +| `/v1/quotation-setting` | 견적 설정(마진율 등) — **유저별** 소유 | +| `/v1/supplier`, `/v1/item` | 협력사 / 상품 CRUD (회사 스코프) | +| `/v1/card` | 협상 카드 | +| `/v1/dashboard` | 요약(회사 전체 + 내 견적) | +| `/v1/notification` | 알림함(목록 · 읽음 처리) | + +> 인증 헤더: `Authorization: Bearer `. 회사 소유 자원은 토큰의 회사로 스코프되고, 계정 관리는 OWNER 만 가능. + +## 실행 ```bash -# 레포 최상위에서 docker compose up -d (backend만; DB 는 외부 PostgreSQL). 상세는 루트 README. cd negodata/backend -pip install -r requirements.txt # 실행 -python web_main.py # APP_ENV 기본 local -pip install pytest pytest-asyncio httpx # 테스트 도구 -python -m pytest +pip install -r requirements.txt +python web_main.py # APP_ENV 기본 local → http://localhost:9400/docs ``` -- 서버: http://localhost:9400/docs -- 환경: `config.{local,test,docker}.toml` (`APP_ENV` 로 선택, docker 는 DB 호스트=`host.docker.internal`, database=`negodata_db`) +환경: `config.{local,test,prod}.toml` (`APP_ENV` 로 선택). + +## 테스트 + +**테스트는 도커가 아니라 호스트(venv)에서 돌린다** — DB(PostgreSQL)만 도커(`negosium-db`, `127.0.0.1:5432`)면 되고, 앱 컨테이너 안엔 pytest 가 없다. test DB(`negosium_test_db`)는 알아서 만들어졌다 지워지므로 **수동 세팅이 필요 없다.** + +```bash +cd negodata/backend +python3 -m venv .venv && source .venv/bin/activate # 최초 1회 (venv 없을 때) +pip install -r requirements.txt # httpx 포함 +pip install pytest pytest-asyncio # 테스트 도구(requirements 에 없음) + +python -m pytest # 전체 (venv 활성화 상태) +python -m pytest -v # 테스트별 PASS/FAIL +python -m pytest tests/test_company_scope.py # 파일 하나만 +python -m pytest -k scope # 이름에 'scope' 든 것만 +``` +venv 를 활성화(`source .venv/bin/activate`)하지 않으면 `.venv/bin/python -m pytest` 로 직접 지정한다. +(시스템에 `python` 명령이 없거나 pytest 가 venv 밖에 없으면 맨 `python -m pytest` 는 실패한다.) +정상이면 마지막 줄에 `NN passed`. + +동작 방식 (전부 [conftest.py](conftest.py) 가 자동 처리 — 손댈 것 없음): +- `APP_ENV` 를 `test` 로 자동 설정 → [config.test.toml](config/config.test.toml) 의 **`negosium_test_db`** 사용(dev DB `negosium_db` 와 완전 분리). +- **세션 시작 시 test DB 를 새로 만들고(CREATE), 끝나면 내린다(DROP).** 매번 현재 모델로 새로 빌드돼 스키마가 낡을 일이 없다. 남는 DB 도 없음. +- 테이블은 `create_all` 로 자동 생성, 매 테스트 전 `TRUNCATE` 로 비워 격리. +- 안전가드: 이름에 `test` 없는 DB 는 만들지도 지우지도 않는다(실 DB 보호). + +> 즉 새로 clone 받은 팀원도 **Postgres 만 켜져 있으면 `python -m pytest` 한 방**이면 끝. diff --git a/negodata/front/README.md b/negodata/front/README.md index f22beba..a2b84f5 100644 --- a/negodata/front/README.md +++ b/negodata/front/README.md @@ -21,8 +21,9 @@ negosium/negodata 협상 플랫폼의 웹 프론트엔드. docker compose up -d --build ``` -- 프론트: **http://localhost:3001** (compose 가 컨테이너 `:3000` → 호스트 `:3001` 로 매핑) +- 프론트: **http://localhost:3000** (compose 서비스 `negodata-front`, `3000:3000` 매핑) - 소스를 바인드마운트하므로 코드 수정은 HMR 로 자동 반영된다. +- (참고: 공급사용 `negosium-front` 는 별개로 `:3300`) ### 프론트만 단독 개발 (선택) @@ -80,7 +81,7 @@ src/ api/ generated/ # orval 자동생성 (직접 수정 금지) mutator/ # custom-fetch (요청 공통 로직: baseURL·토큰·에러) - features/ # 도메인별: auth, products(상품), partners(협력사), quotations(견적), cards + features/ # 도메인별: auth, quotations(견적), products(상품), partners(협력사), cards(협상카드), dashboard, members(회원관리), onboarding components/ # ui(shadcn), layout pages/ # 화면 stores/ # zustand 스토어