@simplysm/sd-claude 14.0.80 → 14.0.81

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/claude/references/sd-requirement-source-handling.md +17 -17
  2. package/claude/references/sd-simplysm14/README.md +58 -58
  3. package/claude/references/sd-simplysm14/manuals/client-component.md +739 -739
  4. package/claude/references/sd-simplysm14/manuals/client-crud.md +1 -1
  5. package/claude/references/sd-simplysm14/manuals/client-demo.md +1 -1
  6. package/claude/references/sd-simplysm14/manuals/client-setup.md +2 -2
  7. package/claude/references/sd-simplysm14/manuals/client-tab.md +2 -2
  8. package/claude/references/sd-simplysm14/manuals/logging.md +3 -3
  9. package/claude/references/sd-simplysm14/manuals/orm-union.md +7 -7
  10. package/claude/references/sd-simplysm14/manuals/orm.md +75 -75
  11. package/claude/references/sd-simplysm14/manuals/test.md +8 -8
  12. package/claude/rules/sd-base-rules.md +306 -293
  13. package/claude/rules/sd-design-rules.md +44 -44
  14. package/claude/skills/sd-commit/SKILL.md +17 -17
  15. package/claude/skills/sd-config/SKILL.md +4 -4
  16. package/claude/skills/sd-demo/SKILL.md +40 -48
  17. package/claude/skills/sd-demo/evals/fixtures/inventory-list/.specs/inventory/spec.md +99 -0
  18. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/package.json +12 -0
  19. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/index.ts +3 -0
  20. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/inbound/inbound.list.ts +150 -0
  21. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/inventory/inventory-master.list.ts +143 -0
  22. package/claude/skills/sd-demo/evals/fixtures/inventory-list/packages/demo-client/src/screens/outbound/outbound.list.ts +150 -0
  23. package/claude/skills/sd-demo/evals/fixtures/inventory-list/pnpm-workspace.yaml +2 -0
  24. package/claude/skills/sd-demo/evals/fixtures/inventory-list/sd.config.ts +12 -0
  25. package/claude/skills/sd-demo/evals/golden.jsonl +1 -5
  26. package/claude/skills/sd-dev/SKILL.md +49 -22
  27. package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/package.json +8 -0
  28. package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/src/.gitkeep +0 -0
  29. package/claude/skills/sd-dev/evals/fixtures/minimal-ts-pkg/tests/.gitkeep +0 -0
  30. package/claude/skills/sd-dev/evals/fixtures/{case-modify → minimal-ts-pkg}/tsconfig.json +1 -3
  31. package/claude/skills/sd-dev/evals/golden.jsonl +1 -3
  32. package/claude/skills/sd-docs/SKILL.md +8 -8
  33. package/claude/skills/sd-impl/SKILL.md +172 -82
  34. package/claude/skills/sd-impl/evals/fixtures/case-a-new-screen/.specs/260513120000_warehouse/spec.md +101 -0
  35. package/claude/skills/sd-impl/evals/fixtures/case-b-update-with-demo/.specs/260513120000_warehouse/spec.md +101 -0
  36. package/claude/skills/sd-impl/evals/fixtures/case-b-update-with-demo/packages/app/src/screens/box-register/box-register.view.ts +46 -0
  37. package/claude/skills/sd-impl/evals/fixtures/case-c-new-cross/.specs/260513120000_warehouse/spec.md +89 -0
  38. package/claude/skills/sd-impl/evals/fixtures/case-d-spec-modify/.specs/260513120000_warehouse/spec.md +101 -0
  39. package/claude/skills/sd-impl/evals/golden.jsonl +4 -6
  40. package/claude/skills/sd-review/SKILL.md +33 -0
  41. package/claude/skills/sd-review/evals/fixtures/code-review/src/foo.ts +7 -0
  42. package/claude/skills/sd-review/evals/fixtures/doc-review/docs/foo.md +4 -0
  43. package/claude/skills/sd-review/evals/golden.jsonl +2 -0
  44. package/claude/skills/sd-skill/SKILL.md +99 -91
  45. package/claude/skills/sd-skill/evals/fixtures/existing-skill/.claude/skills/todo-format/SKILL.md +14 -0
  46. package/claude/skills/sd-skill/evals/fixtures/new-skill/.gitkeep +0 -0
  47. package/claude/skills/sd-skill/evals/golden.jsonl +2 -0
  48. package/claude/skills/sd-spec/SKILL.md +251 -246
  49. package/claude/skills/sd-spec/references/example-spec.md +1 -1
  50. package/claude/skills/sd-unpack/SKILL.md +83 -83
  51. package/claude/skills/sd-use/SKILL.md +4 -4
  52. package/package.json +1 -1
  53. package/claude/skills/sd-demo/evals/fixtures/empty/.specs/260513120000_warehouse/spec.md +0 -45
  54. package/claude/skills/sd-demo/evals/fixtures/with-existing-screen/.specs/260513120000_warehouse/spec.md +0 -42
  55. package/claude/skills/sd-demo/evals/fixtures/with-existing-screen/packages/app/src/screens/dashboard/dashboard.view.ts +0 -33
  56. package/claude/skills/sd-demo/evals/fixtures/with-master-screen/.specs/260513120000_warehouse/spec.md +0 -45
  57. package/claude/skills/sd-demo/evals/fixtures/with-master-screen/packages/app/src/screens/dashboard/dashboard.view.ts +0 -33
  58. package/claude/skills/sd-demo/evals/fixtures/with-modal/.specs/260513120000_warehouse/spec.md +0 -75
  59. package/claude/skills/sd-demo/evals/fixtures/with-modal/packages/app/src/screens/dashboard/dashboard.view.ts +0 -33
  60. package/claude/skills/sd-demo/evals/fixtures/with-screens/.specs/260513120000_warehouse/spec.md +0 -45
  61. package/claude/skills/sd-demo/evals/fixtures/with-screens/packages/app/src/screens/dashboard/dashboard.view.ts +0 -33
  62. package/claude/skills/sd-dev/evals/fixtures/case-add/package.json +0 -13
  63. package/claude/skills/sd-dev/evals/fixtures/case-add/src/index.ts +0 -10
  64. package/claude/skills/sd-dev/evals/fixtures/case-add/tests/index.test.ts +0 -11
  65. package/claude/skills/sd-dev/evals/fixtures/case-add/tsconfig.json +0 -12
  66. package/claude/skills/sd-dev/evals/fixtures/case-bug/package.json +0 -13
  67. package/claude/skills/sd-dev/evals/fixtures/case-bug/src/index.ts +0 -10
  68. package/claude/skills/sd-dev/evals/fixtures/case-bug/tests/index.test.ts +0 -11
  69. package/claude/skills/sd-dev/evals/fixtures/case-bug/tsconfig.json +0 -12
  70. package/claude/skills/sd-dev/evals/fixtures/case-modify/package.json +0 -13
  71. package/claude/skills/sd-dev/evals/fixtures/case-modify/src/index.ts +0 -10
  72. package/claude/skills/sd-dev/evals/fixtures/case-modify/tests/index.test.ts +0 -11
  73. package/claude/skills/sd-impl/evals/fixtures/case-001-new-screen/spec.md +0 -55
  74. package/claude/skills/sd-impl/evals/fixtures/case-002-auto-process/spec.md +0 -55
  75. package/claude/skills/sd-impl/evals/fixtures/case-003-update-screen/packages/client/src/pages/book-list.ts +0 -22
  76. package/claude/skills/sd-impl/evals/fixtures/case-003-update-screen/spec.md +0 -57
  77. package/claude/skills/sd-impl/evals/fixtures/case-004-ambiguous-spec/spec.md +0 -58
  78. package/claude/skills/sd-impl/evals/fixtures/case-005-id-mismatch/spec.md +0 -52
  79. package/claude/skills/sd-impl/evals/fixtures/case-006-with-reference-units/packages/client/src/pages//352/261/260/353/236/230/354/262/230//352/261/260/353/236/230/354/262/230-/353/252/251/353/241/235.test.ts +0 -10
  80. package/claude/skills/sd-impl/evals/fixtures/case-006-with-reference-units/packages/client/src/pages//352/261/260/353/236/230/354/262/230//352/261/260/353/236/230/354/262/230-/353/252/251/353/241/235.ts +0 -11
  81. package/claude/skills/sd-impl/evals/fixtures/case-006-with-reference-units/packages/server/src/data-access//352/261/260/353/236/230/354/262/230-/354/240/221/352/267/274.ts +0 -12
  82. package/claude/skills/sd-impl/evals/fixtures/case-006-with-reference-units/packages/server/src/models//352/261/260/353/236/230/354/262/230.ts +0 -8
  83. package/claude/skills/sd-impl/evals/fixtures/case-006-with-reference-units/spec.md +0 -77
  84. package/claude/skills/sd-impl/evals/fixtures/case-new/.specs/260514120000_/352/261/260/353/236/230/354/262/230/spec.md +0 -101
  85. package/claude/skills/sd-impl/evals/fixtures/case-update/.specs/260514120000_/352/261/260/353/236/230/354/262/230/spec.md +0 -101
  86. package/claude/skills/sd-impl/evals/fixtures/case-update/src//352/261/260/353/236/230/354/262/230//352/261/260/353/236/230/354/262/230-/353/252/250/353/215/270.txt +0 -1
  87. package/claude/skills/sd-impl/evals/fixtures/case-update/src//352/261/260/353/236/230/354/262/230//352/261/260/353/236/230/354/262/230-/353/252/251/353/241/235.txt +0 -1
  88. package/claude/skills/sd-impl/references/spec-cross-check.md +0 -82
@@ -1,33 +0,0 @@
1
- import {
2
- ChangeDetectionStrategy,
3
- Component,
4
- ViewEncapsulation,
5
- signal,
6
- } from "@angular/core";
7
- import { SdBaseContainer, injectViewTypeSignal } from "@simplysm/angular";
8
-
9
- @Component({
10
- selector: "app-dashboard-view",
11
- standalone: true,
12
- changeDetection: ChangeDetectionStrategy.OnPush,
13
- encapsulation: ViewEncapsulation.None,
14
- imports: [SdBaseContainer],
15
- template: `
16
- <sd-base-container
17
- [(ready)]="ready"
18
- [initialized]="initialized()"
19
- [(busyCount)]="busyCount"
20
- [viewType]="viewType()"
21
- >
22
- <ng-template #contentTpl>
23
- <div class="p-default">대시보드</div>
24
- </ng-template>
25
- </sd-base-container>
26
- `,
27
- })
28
- export class DashboardView {
29
- ready = signal(false);
30
- initialized = signal(true);
31
- busyCount = signal(0);
32
- viewType = injectViewTypeSignal();
33
- }
@@ -1,13 +0,0 @@
1
- {
2
- "name": "sd-dev-eval-fixture",
3
- "version": "0.0.0",
4
- "type": "module",
5
- "scripts": {
6
- "test": "vitest run"
7
- },
8
- "devDependencies": {
9
- "@types/node": "^20.0.0",
10
- "typescript": "^5.4.0",
11
- "vitest": "^2.0.0"
12
- }
13
- }
@@ -1,10 +0,0 @@
1
- export function toCamelCase(input: string): string {
2
- return input
3
- .split(/[-_]/)
4
- .map((part, i) =>
5
- i === 0
6
- ? part.toLowerCase()
7
- : part.charAt(0).toUpperCase() + part.slice(1).toLowerCase(),
8
- )
9
- .join("");
10
- }
@@ -1,11 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { toCamelCase } from "../src/index.js";
3
-
4
- describe("toCamelCase", () => {
5
- it("converts kebab-case to camelCase", () => {
6
- expect(toCamelCase("foo-bar")).toBe("fooBar");
7
- });
8
- it("converts snake_case to camelCase", () => {
9
- expect(toCamelCase("foo_bar_baz")).toBe("fooBarBaz");
10
- });
11
- });
@@ -1,12 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "ESNext",
5
- "moduleResolution": "Bundler",
6
- "strict": true,
7
- "esModuleInterop": true,
8
- "skipLibCheck": true,
9
- "verbatimModuleSyntax": true
10
- },
11
- "include": ["src/**/*", "tests/**/*"]
12
- }
@@ -1,13 +0,0 @@
1
- {
2
- "name": "sd-dev-eval-fixture",
3
- "version": "0.0.0",
4
- "type": "module",
5
- "scripts": {
6
- "test": "vitest run"
7
- },
8
- "devDependencies": {
9
- "@types/node": "^20.0.0",
10
- "typescript": "^5.4.0",
11
- "vitest": "^2.0.0"
12
- }
13
- }
@@ -1,10 +0,0 @@
1
- export function toCamelCase(input: string): string {
2
- const parts = input.split(/[-_]/).filter(Boolean);
3
- return (
4
- parts[0].toLowerCase() +
5
- parts
6
- .slice(1)
7
- .map((p) => p.charAt(0).toUpperCase() + p.slice(1).toLowerCase())
8
- .join("")
9
- );
10
- }
@@ -1,11 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { toCamelCase } from "../src/index.js";
3
-
4
- describe("toCamelCase", () => {
5
- it("converts kebab-case to camelCase", () => {
6
- expect(toCamelCase("foo-bar")).toBe("fooBar");
7
- });
8
- it("converts snake_case to camelCase", () => {
9
- expect(toCamelCase("foo_bar_baz")).toBe("fooBarBaz");
10
- });
11
- });
@@ -1,12 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "ESNext",
5
- "moduleResolution": "Bundler",
6
- "strict": true,
7
- "esModuleInterop": true,
8
- "skipLibCheck": true,
9
- "verbatimModuleSyntax": true
10
- },
11
- "include": ["src/**/*", "tests/**/*"]
12
- }
@@ -1,13 +0,0 @@
1
- {
2
- "name": "sd-dev-eval-fixture",
3
- "version": "0.0.0",
4
- "type": "module",
5
- "scripts": {
6
- "test": "vitest run"
7
- },
8
- "devDependencies": {
9
- "@types/node": "^20.0.0",
10
- "typescript": "^5.4.0",
11
- "vitest": "^2.0.0"
12
- }
13
- }
@@ -1,10 +0,0 @@
1
- export function toCamelCase(input: string): string {
2
- return input
3
- .split(/[-_]/)
4
- .map((part, i) =>
5
- i === 0
6
- ? part.toLowerCase()
7
- : part.charAt(0).toUpperCase() + part.slice(1).toLowerCase(),
8
- )
9
- .join("");
10
- }
@@ -1,11 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { toCamelCase } from "../src/index.js";
3
-
4
- describe("toCamelCase", () => {
5
- it("converts kebab-case to camelCase", () => {
6
- expect(toCamelCase("foo-bar")).toBe("fooBar");
7
- });
8
- it("converts snake_case to camelCase", () => {
9
- expect(toCamelCase("foo_bar_baz")).toBe("fooBarBaz");
10
- });
11
- });
@@ -1,55 +0,0 @@
1
- # 도서 관리 시스템 spec
2
-
3
- ## §1 개요
4
-
5
- 도서관 내부 시스템. 사서가 도서를 등록·조회.
6
-
7
- ## §4 화면
8
-
9
- | ID | 이름 | Actor | 장치 |
10
- | ----- | -------- | ----- | ---- |
11
- | §4.1 | 도서 목록 | 사서 | PC |
12
-
13
- ### §4.1 도서 목록 [확정: 2026-05-01]
14
-
15
- **Actor**: 사서
16
- **관련 섹션**: §7.1 도서
17
- **장치**: PC 웹
18
-
19
- **기능 개요**:
20
- - 등록된 도서 전체 목록 표시.
21
- - 제목·저자로 부분일치 검색 (대소문자 무시).
22
-
23
- **와이어프레임**:
24
- ```
25
- [검색창: 제목/저자] [등록]
26
- +----------+----------+-----------+
27
- | 제목 | 저자 | 출판일 |
28
- +----------+----------+-----------+
29
- | ... | ... | ... |
30
- +----------+----------+-----------+
31
- ```
32
-
33
- **항목표**:
34
-
35
- | 항목 | 타입 | 비고 |
36
- | ------ | ------ | --------------------------------- |
37
- | 제목 | text | §7.1.title |
38
- | 저자 | text | §7.1.author |
39
- | 출판일 | date | §7.1.publishedAt, YYYY-MM-DD 형식 |
40
-
41
- **동작**:
42
- - 진입 시 도서 전체를 출판일 내림차순으로 로드.
43
- - 검색창 입력 시 제목·저자 부분일치 필터링 (대소문자 무시).
44
- - "등록" 클릭 시 등록 화면 (본 spec 범위 외).
45
-
46
- ## §7 도메인 모델
47
-
48
- ### §7.1 도서 [확정: 2026-05-01]
49
-
50
- | 필드 | 타입 | 제약 | 기본값 |
51
- | ----------- | ------------- | --------------------- | --------- |
52
- | id | string (UUID) | PK | 자동 생성 |
53
- | title | string | NOT NULL, 최대 200자 | - |
54
- | author | string | NOT NULL, 최대 100자 | - |
55
- | publishedAt | date | NOT NULL | - |
@@ -1,55 +0,0 @@
1
- # 도서관 시스템 spec
2
-
3
- ## §1 개요
4
-
5
- 도서관 자동 처리 - 대여 만료 임박 알림 발송.
6
-
7
- ## §5 자동 처리
8
-
9
- | ID | 이름 | 트리거 |
10
- | ----- | -------------- | ------------ |
11
- | §5.1 | 대여 만료 알림 | 매일 00:00 |
12
-
13
- ### §5.1 대여 만료 알림 [확정: 2026-05-01]
14
-
15
- **트리거**: 매일 00:00 (cron)
16
- **관련 섹션**: §7.1 대여, §7.2 알림 이력
17
-
18
- **처리 내용**:
19
-
20
- 1. 반납 예정일이 오늘 이후 3일 이내(오늘 포함)인 미반납 대여 레코드를 모두 조회.
21
- 2. 각 레코드의 사용자에게 이메일로 알림 발송.
22
- 3. 알림 발송 결과를 §7.2 알림 이력에 저장.
23
-
24
- **알림 내용**:
25
-
26
- - 제목: `도서 반납 예정 알림`
27
- - 본문: `대여하신 도서 [도서명] 의 반납 예정일은 [반납예정일] 입니다.` (`[도서명]`·`[반납예정일]` 치환)
28
-
29
- **중복 발송 방지**:
30
-
31
- - 같은 대여 레코드에 대해 같은 날짜에 알림이 이미 발송됐으면 (§7.2 에서 매칭) 재발송하지 않음.
32
-
33
- ## §7 도메인 모델
34
-
35
- ### §7.1 대여 [확정: 2026-05-01]
36
-
37
- | 필드 | 타입 | 제약 | 기본값 |
38
- | ----------- | ------------- | ------------------------------------- | ----------------- |
39
- | id | string (UUID) | PK | 자동 생성 |
40
- | bookId | string (UUID) | NOT NULL, FK→Book.id | - |
41
- | userId | string (UUID) | NOT NULL, FK→User.id | - |
42
- | borrowedAt | datetime | NOT NULL | 현재 시각 |
43
- | dueAt | datetime | NOT NULL | borrowedAt + 14일 |
44
- | returnedAt | datetime | nullable | NULL |
45
-
46
- ### §7.2 알림 이력 [확정: 2026-05-01]
47
-
48
- | 필드 | 타입 | 제약 | 기본값 |
49
- | ------ | ------------- | ----------------------------------- | ------------ |
50
- | id | string (UUID) | PK | 자동 생성 |
51
- | userId | string (UUID) | NOT NULL, FK→User.id | - |
52
- | rentalId | string (UUID) | NOT NULL, FK→Rental.id | - |
53
- | type | enum | `RENTAL_DUE_REMINDER` | - |
54
- | sentAt | datetime | NOT NULL | 현재 시각 |
55
- | payload | json | - | `{}` |
@@ -1,22 +0,0 @@
1
- // 기존 구현 - 카테고리 필드 없음 상태
2
- export interface Book {
3
- id: string;
4
- title: string;
5
- author: string;
6
- publishedAt: Date;
7
- }
8
-
9
- export async function loadBooks(): Promise<Book[]> {
10
- // 출판일 내림차순 로드
11
- throw new Error("stub - 테스트 환경 전용");
12
- }
13
-
14
- export function searchBooks(keyword: string, books: Book[]): Book[] {
15
- // 제목·저자 부분일치 (대소문자 무시)
16
- const lower = keyword.toLowerCase();
17
- return books.filter(
18
- (b) =>
19
- b.title.toLowerCase().includes(lower) ||
20
- b.author.toLowerCase().includes(lower)
21
- );
22
- }
@@ -1,57 +0,0 @@
1
- # 도서 관리 시스템 spec
2
-
3
- ## §1 개요
4
-
5
- 도서관 내부 시스템. 사서가 도서를 등록·조회.
6
-
7
- ## §4 화면
8
-
9
- | ID | 이름 | Actor | 장치 |
10
- | ----- | -------- | ----- | ---- |
11
- | §4.1 | 도서 목록 | 사서 | PC |
12
-
13
- ### §4.1 도서 목록 [확정: 2026-05-15]
14
-
15
- **Actor**: 사서
16
- **관련 섹션**: §7.1 도서
17
- **장치**: PC 웹
18
-
19
- **기능 개요**:
20
- - 등록된 도서 전체 목록 표시.
21
- - 제목·저자·**카테고리**로 부분일치 검색 (대소문자 무시).
22
-
23
- **와이어프레임**:
24
- ```
25
- [검색창: 제목/저자/카테고리] [등록]
26
- +----------+----------+-----------+-----------+
27
- | 제목 | 저자 | 카테고리 | 출판일 |
28
- +----------+----------+-----------+-----------+
29
- | ... | ... | ... | ... |
30
- +----------+----------+-----------+-----------+
31
- ```
32
-
33
- **항목표**:
34
-
35
- | 항목 | 타입 | 비고 |
36
- | -------- | ------ | --------------------------------- |
37
- | 제목 | text | §7.1.title |
38
- | 저자 | text | §7.1.author |
39
- | 카테고리 | text | §7.1.category |
40
- | 출판일 | date | §7.1.publishedAt, YYYY-MM-DD 형식 |
41
-
42
- **동작**:
43
- - 진입 시 도서 전체를 출판일 내림차순으로 로드.
44
- - 검색창 입력 시 제목·저자·카테고리 부분일치 필터링 (대소문자 무시).
45
- - "등록" 클릭 시 등록 화면 (본 spec 범위 외).
46
-
47
- ## §7 도메인 모델
48
-
49
- ### §7.1 도서 [확정: 2026-05-15]
50
-
51
- | 필드 | 타입 | 제약 | 기본값 |
52
- | ----------- | ------------- | --------------------- | --------- |
53
- | id | string (UUID) | PK | 자동 생성 |
54
- | title | string | NOT NULL, 최대 200자 | - |
55
- | author | string | NOT NULL, 최대 100자 | - |
56
- | category | string | NOT NULL, 최대 50자 | `기타` |
57
- | publishedAt | date | NOT NULL | - |
@@ -1,58 +0,0 @@
1
- # 도서 대여 spec
2
-
3
- ## §1 개요
4
-
5
- 도서관 시스템 - 도서 대여 처리.
6
-
7
- ## §4 화면
8
-
9
- | ID | 이름 | Actor |
10
- | ----- | -------------- | ----- |
11
- | §4.1 | 도서 대여 처리 | 사서 |
12
-
13
- ### §4.1 도서 대여 처리 [확정: 2026-05-15]
14
-
15
- **Actor**: 사서
16
- **관련 섹션**: §7.1 도서, §7.2 대여
17
- **장치**: PC 웹
18
-
19
- **기능 개요**:
20
- - 도서 검색 후 사용자 지정해 대여 등록.
21
-
22
- **와이어프레임**:
23
- ```
24
- [도서 검색] [선택]
25
- [사용자 ID 입력] [대여]
26
- ```
27
-
28
- **항목표**:
29
-
30
- | 항목 | 타입 | 비고 |
31
- | ------------ | ------ | ---------------- |
32
- | 도서 검색 | text | 제목·저자 검색 |
33
- | 사용자 ID | text | - |
34
-
35
- **동작**:
36
- - 도서 검색 후 1건 선택.
37
- - 사용자 ID 입력.
38
- - "대여" 클릭 시 §7.2 대여 레코드 생성.
39
- - **재고 부족 시 처리.**
40
-
41
- ## §7 도메인 모델
42
-
43
- ### §7.1 도서 [확정: 2026-05-15]
44
-
45
- | 필드 | 타입 | 제약 |
46
- | ---------- | ------------- | ------------- |
47
- | id | string (UUID) | PK |
48
- | title | string | NOT NULL |
49
- | stockCount | int | NOT NULL, ≥ 0 |
50
-
51
- ### §7.2 대여 [확정: 2026-05-15]
52
-
53
- | 필드 | 타입 | 제약 |
54
- | ---------- | ------------- | --------------------- |
55
- | id | string (UUID) | PK |
56
- | bookId | string (UUID) | NOT NULL, FK→Book.id |
57
- | userId | string (UUID) | NOT NULL |
58
- | borrowedAt | datetime | NOT NULL |
@@ -1,52 +0,0 @@
1
- # 도서 관리 spec
2
-
3
- ## §1 개요
4
-
5
- 도서관 시스템 minimal.
6
-
7
- ## §4 화면
8
-
9
- | ID | 이름 | Actor |
10
- | ----- | -------- | ----- |
11
- | §4.1 | 도서 목록 | 사서 |
12
- | §4.2 | 도서 등록 | 사서 |
13
-
14
- ### §4.1 도서 목록 [확정: 2026-05-01]
15
-
16
- **Actor**: 사서
17
-
18
- **기능 개요**: 등록된 도서 전체 목록 표시.
19
-
20
- **항목표**:
21
-
22
- | 항목 | 타입 | 비고 |
23
- | ------ | ---- | ----------- |
24
- | 제목 | text | §7.1.title |
25
- | 저자 | text | §7.1.author |
26
-
27
- **동작**: 진입 시 전체 목록 로드.
28
-
29
- ### §4.2 도서 등록 [확정: 2026-05-01]
30
-
31
- **Actor**: 사서
32
-
33
- **기능 개요**: 신규 도서 등록 폼.
34
-
35
- **항목표**:
36
-
37
- | 항목 | 타입 | 비고 |
38
- | ---- | ---- | ----------- |
39
- | 제목 | text | §7.1.title |
40
- | 저자 | text | §7.1.author |
41
-
42
- **동작**: 입력 후 "저장" 클릭 시 §7.1 레코드 생성.
43
-
44
- ## §7 도메인 모델
45
-
46
- ### §7.1 도서 [확정: 2026-05-01]
47
-
48
- | 필드 | 타입 | 제약 |
49
- | ------ | ------------- | -------- |
50
- | id | string (UUID) | PK |
51
- | title | string | NOT NULL |
52
- | author | string | NOT NULL |
@@ -1,10 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { CustomerListPage } from "./거래처-목록";
3
-
4
- describe("거래처 목록", () => {
5
- it("진입 시 거래처 전체를 로드", async () => {
6
- const page = new CustomerListPage();
7
- await page.onInit();
8
- expect(page.customers).toBeDefined();
9
- });
10
- });
@@ -1,11 +0,0 @@
1
- // §4.1 거래처 목록 (이미 풀구현)
2
- import type { Customer } from "../../../../server/src/models/거래처";
3
- import { loadCustomers } from "../../../../server/src/data-access/거래처-접근";
4
-
5
- export class CustomerListPage {
6
- customers: Customer[] = [];
7
-
8
- async onInit() {
9
- this.customers = await loadCustomers();
10
- }
11
- }
@@ -1,12 +0,0 @@
1
- import type { Customer } from "../models/거래처";
2
-
3
- export async function loadCustomers(): Promise<Customer[]> {
4
- // 등록일 내림차순
5
- return [];
6
- }
7
-
8
- export async function insertCustomer(
9
- input: Omit<Customer, "id" | "createdAt">,
10
- ): Promise<Customer> {
11
- throw new Error("stub");
12
- }
@@ -1,8 +0,0 @@
1
- export interface Customer {
2
- id: string;
3
- name: string;
4
- businessNumber: string;
5
- manager: string;
6
- contact: string;
7
- createdAt: Date;
8
- }
@@ -1,77 +0,0 @@
1
- # 거래처 관리 시스템 spec
2
-
3
- ## §1 개요
4
-
5
- 영업담당이 거래처를 등록·조회한다.
6
-
7
- ## §4 화면
8
-
9
- | ID | 이름 | Actor | 장치 |
10
- | ----- | ----------- | -------- | ---- |
11
- | §4.1 | 거래처 목록 | 영업담당 | PC |
12
- | §4.2 | 거래처 등록 | 영업담당 | PC |
13
-
14
- ### §4.1 거래처 목록 [확정: 2026-05-01, 구현: 2026-05-10]
15
-
16
- **Actor**: 영업담당
17
- **관련 섹션**: §7.1 거래처
18
- **장치**: PC 웹
19
-
20
- **기능 개요**:
21
-
22
- - 등록된 거래처 전체 목록 표시.
23
-
24
- **동작**:
25
-
26
- - 진입 시 거래처 전체를 등록일 내림차순 로드.
27
-
28
- ### §4.2 거래처 등록 [확정: 2026-05-15]
29
-
30
- **Actor**: 영업담당
31
- **관련 섹션**: §7.1 거래처
32
- **장치**: PC 웹
33
-
34
- **기능 개요**:
35
-
36
- - 신규 거래처 등록 폼.
37
-
38
- **와이어프레임**:
39
-
40
- ```
41
- +----------------------------+
42
- | 거래처명 (필수) |
43
- | 사업자번호 |
44
- | 담당자 |
45
- | 연락처 |
46
- | |
47
- | [등록] [취소] |
48
- +----------------------------+
49
- ```
50
-
51
- **항목표**:
52
-
53
- | 항목 | 타입 | 비고 |
54
- | ---------- | ---- | --------------------- |
55
- | 거래처명 | text | §7.1.name, NOT NULL |
56
- | 사업자번호 | text | §7.1.businessNumber |
57
- | 담당자 | text | §7.1.manager |
58
- | 연락처 | text | §7.1.contact |
59
-
60
- **동작**:
61
-
62
- - "등록" 클릭 시 §7.1 거래처 저장 (`createdAt` 자동 = 현재 시각).
63
- - 거래처명 미입력 시 등록 차단.
64
- - "취소" 클릭 시 입력 폐기 후 §4.1 거래처 목록으로 이동.
65
-
66
- ## §7 도메인 모델
67
-
68
- ### §7.1 거래처 [확정: 2026-05-01]
69
-
70
- | 필드 | 타입 | 제약 | 기본값 |
71
- | -------------- | ------------- | --------------------- | --------- |
72
- | id | string (UUID) | PK | 자동 생성 |
73
- | name | string | NOT NULL, 최대 100자 | - |
74
- | businessNumber | string | 10자리 숫자 | - |
75
- | manager | string | 최대 50자 | - |
76
- | contact | string | 최대 30자 | - |
77
- | createdAt | datetime | NOT NULL | 현재 시각 |