@k2works/claude-code-booster 4.8.0 → 4.11.0

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 (747) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +42 -42
  3. package/bin/claude-code-booster +90 -90
  4. package/lib/assets/.claude/README.md +279 -271
  5. package/lib/assets/.claude/agents/xp-architect.md +250 -250
  6. package/lib/assets/.claude/agents/xp-executive.md +207 -207
  7. package/lib/assets/.claude/agents/xp-interaction-designer.md +239 -239
  8. package/lib/assets/.claude/agents/xp-product-manager.md +245 -245
  9. package/lib/assets/.claude/agents/xp-programmer.md +268 -268
  10. package/lib/assets/.claude/agents/xp-project-manager.md +229 -229
  11. package/lib/assets/.claude/agents/xp-technical-writer.md +224 -224
  12. package/lib/assets/.claude/agents/xp-tester.md +265 -265
  13. package/lib/assets/.claude/agents/xp-user-representative.md +204 -204
  14. package/lib/assets/.claude/scripts/generate-inception-deck.mjs +911 -911
  15. package/lib/assets/.claude/settings.json +11 -11
  16. package/lib/assets/.claude/skills/ai-agent-guidelines/SKILL.md +111 -111
  17. package/lib/assets/.claude/skills/analyzing-architecture/SKILL.md +83 -83
  18. package/lib/assets/.claude/skills/analyzing-business-architecture/SKILL.md +122 -122
  19. package/lib/assets/.claude/skills/analyzing-business-case/SKILL.md +148 -148
  20. package/lib/assets/.claude/skills/analyzing-business-strategy/SKILL.md +277 -277
  21. package/lib/assets/.claude/skills/analyzing-data-model/SKILL.md +77 -77
  22. package/lib/assets/.claude/skills/analyzing-domain-model/SKILL.md +117 -117
  23. package/lib/assets/.claude/skills/analyzing-inception-deck/SKILL.md +84 -84
  24. package/lib/assets/.claude/skills/analyzing-non-functional/SKILL.md +95 -95
  25. package/lib/assets/.claude/skills/analyzing-operation/SKILL.md +95 -95
  26. package/lib/assets/.claude/skills/analyzing-requirements/SKILL.md +91 -91
  27. package/lib/assets/.claude/skills/analyzing-review/SKILL.md +174 -174
  28. package/lib/assets/.claude/skills/analyzing-tech-stack/SKILL.md +101 -101
  29. package/lib/assets/.claude/skills/analyzing-test-strategy/SKILL.md +89 -89
  30. package/lib/assets/.claude/skills/analyzing-ui-design/SKILL.md +80 -80
  31. package/lib/assets/.claude/skills/analyzing-usecases/SKILL.md +72 -72
  32. package/lib/assets/.claude/skills/creating-adr/SKILL.md +113 -113
  33. package/lib/assets/.claude/skills/creating-development-strategy/SKILL.md +101 -0
  34. package/lib/assets/.claude/skills/creating-iteration-report/SKILL.md +210 -210
  35. package/lib/assets/.claude/skills/creating-journal/SKILL.md +129 -129
  36. package/lib/assets/.claude/skills/creating-release-report/SKILL.md +161 -161
  37. package/lib/assets/.claude/skills/creating-slides/SKILL.md +86 -86
  38. package/lib/assets/.claude/skills/creating-slides/agents/openai.yaml +4 -4
  39. package/lib/assets/.claude/skills/creating-slides/references/manga-css.md +45 -45
  40. package/lib/assets/.claude/skills/creating-slides/scripts/slide_tools.py +239 -239
  41. package/lib/assets/.claude/skills/developing-backend/SKILL.md +100 -100
  42. package/lib/assets/.claude/skills/developing-frontend/SKILL.md +93 -93
  43. package/lib/assets/.claude/skills/developing-release/SKILL.md +120 -120
  44. package/lib/assets/.claude/skills/developing-review/SKILL.md +175 -175
  45. package/lib/assets/.claude/skills/developing-uiux-review/SKILL.md +207 -207
  46. package/lib/assets/.claude/skills/generating-bmc/SKILL.md +123 -123
  47. package/lib/assets/.claude/skills/generating-slides/SKILL.md +94 -94
  48. package/lib/assets/.claude/skills/git-commit/SKILL.md +81 -81
  49. package/lib/assets/.claude/skills/killing-processes/SKILL.md +44 -44
  50. package/lib/assets/.claude/skills/operating-backup/SKILL.md +59 -59
  51. package/lib/assets/.claude/skills/operating-cicd/SKILL.md +54 -54
  52. package/lib/assets/.claude/skills/operating-deploy/SKILL.md +67 -67
  53. package/lib/assets/.claude/skills/operating-docs/SKILL.md +219 -219
  54. package/lib/assets/.claude/skills/operating-provision/SKILL.md +77 -77
  55. package/lib/assets/.claude/skills/operating-qt/SKILL.md +147 -147
  56. package/lib/assets/.claude/skills/operating-review/SKILL.md +171 -171
  57. package/lib/assets/.claude/skills/operating-script/SKILL.md +145 -145
  58. package/lib/assets/.claude/skills/operating-setup/SKILL.md +63 -63
  59. package/lib/assets/.claude/skills/orchestrating-analysis/SKILL.md +104 -104
  60. package/lib/assets/.claude/skills/orchestrating-development/SKILL.md +168 -168
  61. package/lib/assets/.claude/skills/orchestrating-operation/SKILL.md +158 -158
  62. package/lib/assets/.claude/skills/orchestrating-project/SKILL.md +144 -144
  63. package/lib/assets/.claude/skills/planning-releases/SKILL.md +119 -119
  64. package/lib/assets/.claude/skills/practicing-getting-start-tdd/SKILL.md +266 -266
  65. package/lib/assets/.claude/skills/syncing-github-project/SKILL.md +151 -151
  66. package/lib/assets/.claude/skills/tracking-progress/SKILL.md +91 -91
  67. package/lib/assets/.claude/skills/validating-design/SKILL.md +130 -0
  68. package/lib/assets/.claude/skills/validating-iteration-plan/SKILL.md +238 -238
  69. package/lib/assets/.claude/skills/validating-operating-setup/SKILL.md +118 -0
  70. package/lib/assets/.devcontainer/devcontainer.json +37 -37
  71. package/lib/assets/.env.example +17 -17
  72. package/lib/assets/.gitattributes +4 -4
  73. package/lib/assets/.github/workflows/docker-publish.yml +77 -77
  74. package/lib/assets/.github/workflows/mkdocs.yml +39 -39
  75. package/lib/assets/AGENTS.md +94 -94
  76. package/lib/assets/CLAUDE.md +195 -193
  77. package/lib/assets/README.md +291 -291
  78. package/lib/assets/docker-compose.yml +33 -33
  79. package/lib/assets/docs/adr/index.md +10 -10
  80. package/lib/assets/docs/article/functional-desgin-ppp/all/01-immutability-and-data-transformation.md +475 -475
  81. package/lib/assets/docs/article/functional-desgin-ppp/all/02-function-composition.md +519 -519
  82. package/lib/assets/docs/article/functional-desgin-ppp/all/03-polymorphism.md +537 -537
  83. package/lib/assets/docs/article/functional-desgin-ppp/all/04-data-validation.md +300 -300
  84. package/lib/assets/docs/article/functional-desgin-ppp/all/05-property-based-testing.md +320 -320
  85. package/lib/assets/docs/article/functional-desgin-ppp/all/06-tdd-and-functional.md +498 -498
  86. package/lib/assets/docs/article/functional-desgin-ppp/all/07-composite-pattern.md +298 -298
  87. package/lib/assets/docs/article/functional-desgin-ppp/all/08-decorator-pattern.md +291 -291
  88. package/lib/assets/docs/article/functional-desgin-ppp/all/09-adapter-pattern.md +336 -336
  89. package/lib/assets/docs/article/functional-desgin-ppp/all/10-strategy-pattern.md +303 -303
  90. package/lib/assets/docs/article/functional-desgin-ppp/all/11-command-pattern.md +286 -286
  91. package/lib/assets/docs/article/functional-desgin-ppp/all/12-visitor-pattern.md +322 -322
  92. package/lib/assets/docs/article/functional-desgin-ppp/all/13-abstract-factory-pattern.md +319 -319
  93. package/lib/assets/docs/article/functional-desgin-ppp/all/14-abstract-server-pattern.md +365 -365
  94. package/lib/assets/docs/article/functional-desgin-ppp/all/15-gossiping-bus-drivers.md +156 -156
  95. package/lib/assets/docs/article/functional-desgin-ppp/all/16-payroll-system.md +178 -178
  96. package/lib/assets/docs/article/functional-desgin-ppp/all/17-video-rental-system.md +312 -312
  97. package/lib/assets/docs/article/functional-desgin-ppp/all/18-concurrency-system.md +287 -287
  98. package/lib/assets/docs/article/functional-desgin-ppp/all/19-wa-tor-simulation.md +286 -286
  99. package/lib/assets/docs/article/functional-desgin-ppp/all/20-pattern-interactions.md +274 -274
  100. package/lib/assets/docs/article/functional-desgin-ppp/all/21-best-practices.md +294 -294
  101. package/lib/assets/docs/article/functional-desgin-ppp/all/22-oo-to-fp-migration.md +337 -337
  102. package/lib/assets/docs/article/functional-desgin-ppp/all/index.md +388 -388
  103. package/lib/assets/docs/article/functional-desgin-ppp/clojure/01-immutability-and-data-transformation.md +273 -273
  104. package/lib/assets/docs/article/functional-desgin-ppp/clojure/02-function-composition.md +380 -380
  105. package/lib/assets/docs/article/functional-desgin-ppp/clojure/03-polymorphism.md +384 -384
  106. package/lib/assets/docs/article/functional-desgin-ppp/clojure/04-clojure-spec.md +350 -350
  107. package/lib/assets/docs/article/functional-desgin-ppp/clojure/05-property-based-testing.md +352 -352
  108. package/lib/assets/docs/article/functional-desgin-ppp/clojure/06-tdd-in-functional.md +383 -383
  109. package/lib/assets/docs/article/functional-desgin-ppp/clojure/07-composite-pattern.md +529 -529
  110. package/lib/assets/docs/article/functional-desgin-ppp/clojure/08-decorator-pattern.md +395 -395
  111. package/lib/assets/docs/article/functional-desgin-ppp/clojure/09-adapter-pattern.md +399 -399
  112. package/lib/assets/docs/article/functional-desgin-ppp/clojure/10-strategy-pattern.md +485 -485
  113. package/lib/assets/docs/article/functional-desgin-ppp/clojure/11-command-pattern.md +566 -566
  114. package/lib/assets/docs/article/functional-desgin-ppp/clojure/12-visitor-pattern.md +567 -567
  115. package/lib/assets/docs/article/functional-desgin-ppp/clojure/13-abstract-factory-pattern.md +475 -475
  116. package/lib/assets/docs/article/functional-desgin-ppp/clojure/14-abstract-server-pattern.md +462 -462
  117. package/lib/assets/docs/article/functional-desgin-ppp/clojure/15-gossiping-bus-drivers.md +325 -325
  118. package/lib/assets/docs/article/functional-desgin-ppp/clojure/16-payroll-system.md +401 -401
  119. package/lib/assets/docs/article/functional-desgin-ppp/clojure/17-video-rental-system.md +450 -450
  120. package/lib/assets/docs/article/functional-desgin-ppp/clojure/18-concurrency-system.md +475 -475
  121. package/lib/assets/docs/article/functional-desgin-ppp/clojure/19-wator-simulation.md +739 -739
  122. package/lib/assets/docs/article/functional-desgin-ppp/clojure/20-pattern-interactions.md +567 -567
  123. package/lib/assets/docs/article/functional-desgin-ppp/clojure/21-best-practices.md +518 -518
  124. package/lib/assets/docs/article/functional-desgin-ppp/clojure/22-oo-to-fp-migration.md +532 -532
  125. package/lib/assets/docs/article/functional-desgin-ppp/clojure/index.md +241 -241
  126. package/lib/assets/docs/article/functional-desgin-ppp/elixir/01-immutability-and-data-transformation.md +383 -383
  127. package/lib/assets/docs/article/functional-desgin-ppp/elixir/02-function-composition.md +374 -374
  128. package/lib/assets/docs/article/functional-desgin-ppp/elixir/03-polymorphism.md +375 -375
  129. package/lib/assets/docs/article/functional-desgin-ppp/elixir/04-data-validation.md +195 -195
  130. package/lib/assets/docs/article/functional-desgin-ppp/elixir/05-property-based-testing.md +268 -268
  131. package/lib/assets/docs/article/functional-desgin-ppp/elixir/06-tdd-and-fp.md +294 -294
  132. package/lib/assets/docs/article/functional-desgin-ppp/elixir/07-effects-and-pure-functions.md +164 -164
  133. package/lib/assets/docs/article/functional-desgin-ppp/elixir/08-error-handling-strategies.md +168 -168
  134. package/lib/assets/docs/article/functional-desgin-ppp/elixir/09-io-and-external-systems.md +254 -254
  135. package/lib/assets/docs/article/functional-desgin-ppp/elixir/10-concurrency-patterns.md +269 -269
  136. package/lib/assets/docs/article/functional-desgin-ppp/elixir/11-command-pattern.md +148 -148
  137. package/lib/assets/docs/article/functional-desgin-ppp/elixir/12-visitor-pattern.md +176 -176
  138. package/lib/assets/docs/article/functional-desgin-ppp/elixir/13-abstract-factory-pattern.md +604 -604
  139. package/lib/assets/docs/article/functional-desgin-ppp/elixir/14-abstract-server-pattern.md +729 -729
  140. package/lib/assets/docs/article/functional-desgin-ppp/elixir/15-gossiping-bus-drivers.md +291 -291
  141. package/lib/assets/docs/article/functional-desgin-ppp/elixir/16-payroll-system.md +420 -420
  142. package/lib/assets/docs/article/functional-desgin-ppp/elixir/17-video-rental-system.md +319 -319
  143. package/lib/assets/docs/article/functional-desgin-ppp/elixir/18-concurrency-system.md +466 -466
  144. package/lib/assets/docs/article/functional-desgin-ppp/elixir/19-wator-simulation.md +523 -523
  145. package/lib/assets/docs/article/functional-desgin-ppp/elixir/20-pattern-interactions.md +287 -287
  146. package/lib/assets/docs/article/functional-desgin-ppp/elixir/21-best-practices.md +340 -340
  147. package/lib/assets/docs/article/functional-desgin-ppp/elixir/22-oo-to-fp-migration.md +395 -395
  148. package/lib/assets/docs/article/functional-desgin-ppp/elixir/index.md +248 -248
  149. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/01-immutability-and-data-transformation.md +384 -384
  150. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/02-function-composition.md +452 -452
  151. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/03-polymorphism.md +495 -495
  152. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/04-data-validation.md +416 -416
  153. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/05-property-based-testing.md +382 -382
  154. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/06-tdd-functional.md +687 -687
  155. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/07-composite-pattern.md +442 -442
  156. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/08-decorator-pattern.md +479 -479
  157. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/09-adapter-pattern.md +479 -479
  158. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/10-strategy-pattern.md +427 -427
  159. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/11-command-pattern.md +428 -428
  160. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/12-visitor-pattern.md +339 -339
  161. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/13-abstract-factory-pattern.md +309 -309
  162. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/14-abstract-server-pattern.md +596 -596
  163. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/15-gossiping-bus-drivers.md +355 -355
  164. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/16-payroll-system.md +350 -350
  165. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/17-video-rental-system.md +414 -414
  166. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/18-concurrency-system.md +367 -367
  167. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/19-wator-simulation.md +403 -403
  168. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/20-pattern-interactions.md +291 -291
  169. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/21-best-practices.md +324 -324
  170. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/22-oo-to-fp-migration.md +332 -332
  171. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/index.md +274 -274
  172. package/lib/assets/docs/article/functional-desgin-ppp/haskell/01-immutability-and-data-transformation.md +298 -298
  173. package/lib/assets/docs/article/functional-desgin-ppp/haskell/02-function-composition.md +304 -304
  174. package/lib/assets/docs/article/functional-desgin-ppp/haskell/03-polymorphism.md +362 -362
  175. package/lib/assets/docs/article/functional-desgin-ppp/haskell/04-data-validation.md +257 -257
  176. package/lib/assets/docs/article/functional-desgin-ppp/haskell/05-property-based-testing.md +254 -254
  177. package/lib/assets/docs/article/functional-desgin-ppp/haskell/06-tdd-functional.md +283 -283
  178. package/lib/assets/docs/article/functional-desgin-ppp/haskell/07-composite-pattern.md +395 -395
  179. package/lib/assets/docs/article/functional-desgin-ppp/haskell/08-decorator-pattern.md +319 -319
  180. package/lib/assets/docs/article/functional-desgin-ppp/haskell/09-adapter-pattern.md +382 -382
  181. package/lib/assets/docs/article/functional-desgin-ppp/haskell/10-strategy-pattern.md +287 -287
  182. package/lib/assets/docs/article/functional-desgin-ppp/haskell/11-command-pattern.md +303 -303
  183. package/lib/assets/docs/article/functional-desgin-ppp/haskell/12-visitor-pattern.md +326 -326
  184. package/lib/assets/docs/article/functional-desgin-ppp/haskell/13-abstract-factory-pattern.md +332 -332
  185. package/lib/assets/docs/article/functional-desgin-ppp/haskell/14-abstract-server-pattern.md +379 -379
  186. package/lib/assets/docs/article/functional-desgin-ppp/haskell/15-gossiping-bus-drivers.md +177 -177
  187. package/lib/assets/docs/article/functional-desgin-ppp/haskell/16-payroll-system.md +219 -219
  188. package/lib/assets/docs/article/functional-desgin-ppp/haskell/17-video-rental-system.md +244 -244
  189. package/lib/assets/docs/article/functional-desgin-ppp/haskell/18-concurrency-system.md +363 -363
  190. package/lib/assets/docs/article/functional-desgin-ppp/haskell/19-wator-simulation.md +438 -438
  191. package/lib/assets/docs/article/functional-desgin-ppp/haskell/20-pattern-interactions.md +325 -325
  192. package/lib/assets/docs/article/functional-desgin-ppp/haskell/21-best-practices.md +403 -403
  193. package/lib/assets/docs/article/functional-desgin-ppp/haskell/22-oo-to-fp-migration.md +469 -469
  194. package/lib/assets/docs/article/functional-desgin-ppp/haskell/index.md +174 -174
  195. package/lib/assets/docs/article/functional-desgin-ppp/index.md +90 -90
  196. package/lib/assets/docs/article/functional-desgin-ppp/rust/01-immutability-and-data-transformation.md +450 -450
  197. package/lib/assets/docs/article/functional-desgin-ppp/rust/02-function-composition.md +463 -463
  198. package/lib/assets/docs/article/functional-desgin-ppp/rust/03-polymorphism.md +425 -425
  199. package/lib/assets/docs/article/functional-desgin-ppp/rust/04-data-validation.md +273 -273
  200. package/lib/assets/docs/article/functional-desgin-ppp/rust/05-property-based-testing.md +247 -247
  201. package/lib/assets/docs/article/functional-desgin-ppp/rust/06-tdd-and-functional.md +841 -841
  202. package/lib/assets/docs/article/functional-desgin-ppp/rust/07-composite-pattern.md +384 -384
  203. package/lib/assets/docs/article/functional-desgin-ppp/rust/08-decorator-pattern.md +383 -383
  204. package/lib/assets/docs/article/functional-desgin-ppp/rust/09-adapter-pattern.md +339 -339
  205. package/lib/assets/docs/article/functional-desgin-ppp/rust/10-strategy-pattern.md +331 -331
  206. package/lib/assets/docs/article/functional-desgin-ppp/rust/11-command-pattern.md +356 -356
  207. package/lib/assets/docs/article/functional-desgin-ppp/rust/12-visitor-pattern.md +379 -379
  208. package/lib/assets/docs/article/functional-desgin-ppp/rust/13-abstract-factory-pattern.md +361 -361
  209. package/lib/assets/docs/article/functional-desgin-ppp/rust/14-abstract-server-pattern.md +392 -392
  210. package/lib/assets/docs/article/functional-desgin-ppp/rust/15-gossiping-bus-drivers.md +300 -300
  211. package/lib/assets/docs/article/functional-desgin-ppp/rust/16-payroll-system.md +297 -297
  212. package/lib/assets/docs/article/functional-desgin-ppp/rust/17-video-rental-system.md +304 -304
  213. package/lib/assets/docs/article/functional-desgin-ppp/rust/18-concurrency-system.md +315 -315
  214. package/lib/assets/docs/article/functional-desgin-ppp/rust/19-wator-simulation.md +311 -311
  215. package/lib/assets/docs/article/functional-desgin-ppp/rust/20-pattern-interactions.md +304 -304
  216. package/lib/assets/docs/article/functional-desgin-ppp/rust/21-best-practices.md +336 -336
  217. package/lib/assets/docs/article/functional-desgin-ppp/rust/22-oo-to-fp-migration.md +349 -349
  218. package/lib/assets/docs/article/functional-desgin-ppp/rust/index.md +243 -243
  219. package/lib/assets/docs/article/functional-desgin-ppp/scala/01-immutability-and-data-transformation.md +328 -328
  220. package/lib/assets/docs/article/functional-desgin-ppp/scala/02-function-composition.md +348 -348
  221. package/lib/assets/docs/article/functional-desgin-ppp/scala/03-polymorphism.md +357 -357
  222. package/lib/assets/docs/article/functional-desgin-ppp/scala/04-data-validation.md +364 -364
  223. package/lib/assets/docs/article/functional-desgin-ppp/scala/05-property-based-testing.md +515 -515
  224. package/lib/assets/docs/article/functional-desgin-ppp/scala/06-tdd-functional.md +557 -557
  225. package/lib/assets/docs/article/functional-desgin-ppp/scala/07-composite-pattern.md +363 -363
  226. package/lib/assets/docs/article/functional-desgin-ppp/scala/08-decorator-pattern.md +327 -327
  227. package/lib/assets/docs/article/functional-desgin-ppp/scala/09-adapter-pattern.md +517 -517
  228. package/lib/assets/docs/article/functional-desgin-ppp/scala/10-strategy-pattern.md +441 -441
  229. package/lib/assets/docs/article/functional-desgin-ppp/scala/11-command-pattern.md +407 -407
  230. package/lib/assets/docs/article/functional-desgin-ppp/scala/12-visitor-pattern.md +379 -379
  231. package/lib/assets/docs/article/functional-desgin-ppp/scala/13-abstract-factory-pattern.md +398 -398
  232. package/lib/assets/docs/article/functional-desgin-ppp/scala/14-abstract-server-pattern.md +476 -476
  233. package/lib/assets/docs/article/functional-desgin-ppp/scala/15-gossiping-bus-drivers.md +391 -391
  234. package/lib/assets/docs/article/functional-desgin-ppp/scala/16-payroll-system.md +342 -342
  235. package/lib/assets/docs/article/functional-desgin-ppp/scala/17-video-rental-system.md +324 -324
  236. package/lib/assets/docs/article/functional-desgin-ppp/scala/18-concurrency-system.md +730 -730
  237. package/lib/assets/docs/article/functional-desgin-ppp/scala/19-wator-simulation.md +624 -624
  238. package/lib/assets/docs/article/functional-desgin-ppp/scala/20-pattern-interactions.md +512 -512
  239. package/lib/assets/docs/article/functional-desgin-ppp/scala/21-best-practices.md +433 -433
  240. package/lib/assets/docs/article/functional-desgin-ppp/scala/22-oo-to-fp-migration.md +688 -688
  241. package/lib/assets/docs/article/functional-desgin-ppp/scala/index.md +243 -243
  242. package/lib/assets/docs/article/getting-start-tdd/clojure/01-todo-list-and-first-test.md +166 -166
  243. package/lib/assets/docs/article/getting-start-tdd/clojure/02-fake-it-and-triangulation.md +162 -162
  244. package/lib/assets/docs/article/getting-start-tdd/clojure/03-obvious-implementation-and-refactoring.md +135 -135
  245. package/lib/assets/docs/article/getting-start-tdd/clojure/04-version-control-and-conventional-commits.md +88 -88
  246. package/lib/assets/docs/article/getting-start-tdd/clojure/05-package-management-and-static-analysis.md +299 -299
  247. package/lib/assets/docs/article/getting-start-tdd/clojure/06-task-runner-and-ci-cd.md +241 -241
  248. package/lib/assets/docs/article/getting-start-tdd/clojure/07-protocols-and-records.md +131 -131
  249. package/lib/assets/docs/article/getting-start-tdd/clojure/08-multimethods-and-design-patterns.md +130 -130
  250. package/lib/assets/docs/article/getting-start-tdd/clojure/09-namespaces-and-module-design.md +127 -127
  251. package/lib/assets/docs/article/getting-start-tdd/clojure/10-higher-order-functions-and-composition.md +114 -114
  252. package/lib/assets/docs/article/getting-start-tdd/clojure/11-persistent-data-and-pipeline.md +138 -138
  253. package/lib/assets/docs/article/getting-start-tdd/clojure/12-error-handling-and-spec.md +161 -161
  254. package/lib/assets/docs/article/getting-start-tdd/clojure/index.md +65 -65
  255. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter01.md +232 -232
  256. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter02.md +244 -244
  257. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter03.md +202 -202
  258. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter04.md +92 -92
  259. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter05.md +256 -256
  260. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter06.md +195 -195
  261. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter07.md +214 -214
  262. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter08.md +249 -249
  263. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter09.md +174 -174
  264. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter10.md +166 -166
  265. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter11.md +192 -192
  266. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter12.md +211 -211
  267. package/lib/assets/docs/article/getting-start-tdd/csharp/index.md +83 -83
  268. package/lib/assets/docs/article/getting-start-tdd/elixir/01-todo-list-and-first-test.md +87 -87
  269. package/lib/assets/docs/article/getting-start-tdd/elixir/02-fake-it-and-triangulation.md +95 -95
  270. package/lib/assets/docs/article/getting-start-tdd/elixir/03-obvious-implementation-and-refactoring.md +109 -109
  271. package/lib/assets/docs/article/getting-start-tdd/elixir/04-version-control-and-conventional-commits.md +96 -96
  272. package/lib/assets/docs/article/getting-start-tdd/elixir/05-package-management-and-static-analysis.md +88 -88
  273. package/lib/assets/docs/article/getting-start-tdd/elixir/06-task-runner-and-ci-cd.md +71 -71
  274. package/lib/assets/docs/article/getting-start-tdd/elixir/07-structs-and-protocols.md +110 -110
  275. package/lib/assets/docs/article/getting-start-tdd/elixir/08-pattern-matching-and-guards.md +108 -108
  276. package/lib/assets/docs/article/getting-start-tdd/elixir/09-module-design-and-behaviours.md +104 -104
  277. package/lib/assets/docs/article/getting-start-tdd/elixir/10-higher-order-functions-and-pipeline.md +178 -178
  278. package/lib/assets/docs/article/getting-start-tdd/elixir/11-stream-and-lazy-evaluation.md +142 -142
  279. package/lib/assets/docs/article/getting-start-tdd/elixir/12-error-handling-and-with.md +145 -145
  280. package/lib/assets/docs/article/getting-start-tdd/elixir/index.md +35 -35
  281. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter01.md +202 -202
  282. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter02.md +246 -246
  283. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter03.md +218 -218
  284. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter04.md +179 -179
  285. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter05.md +267 -267
  286. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter06.md +190 -190
  287. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter07.md +161 -161
  288. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter08.md +175 -175
  289. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter09.md +222 -222
  290. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter10.md +189 -189
  291. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter11.md +212 -212
  292. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter12.md +215 -215
  293. package/lib/assets/docs/article/getting-start-tdd/fsharp/index.md +71 -71
  294. package/lib/assets/docs/article/getting-start-tdd/go/01-todo-list-and-first-test.md +213 -213
  295. package/lib/assets/docs/article/getting-start-tdd/go/02-fake-it-and-triangulation.md +302 -302
  296. package/lib/assets/docs/article/getting-start-tdd/go/03-obvious-implementation-and-refactoring.md +339 -339
  297. package/lib/assets/docs/article/getting-start-tdd/go/04-version-control-and-conventional-commits.md +112 -112
  298. package/lib/assets/docs/article/getting-start-tdd/go/05-package-management-and-static-analysis.md +272 -272
  299. package/lib/assets/docs/article/getting-start-tdd/go/06-task-runner-and-ci-cd.md +233 -233
  300. package/lib/assets/docs/article/getting-start-tdd/go/07-encapsulation-and-polymorphism.md +394 -394
  301. package/lib/assets/docs/article/getting-start-tdd/go/08-design-patterns.md +422 -422
  302. package/lib/assets/docs/article/getting-start-tdd/go/09-solid-principles-and-module-design.md +400 -400
  303. package/lib/assets/docs/article/getting-start-tdd/go/10-higher-order-functions-and-composition.md +226 -226
  304. package/lib/assets/docs/article/getting-start-tdd/go/11-immutable-data-and-pipeline.md +296 -296
  305. package/lib/assets/docs/article/getting-start-tdd/go/12-error-handling-and-type-safety.md +411 -411
  306. package/lib/assets/docs/article/getting-start-tdd/go/index.md +83 -83
  307. package/lib/assets/docs/article/getting-start-tdd/haskell/01-todo-list-and-first-test.md +279 -279
  308. package/lib/assets/docs/article/getting-start-tdd/haskell/02-fake-it-and-triangulation.md +337 -337
  309. package/lib/assets/docs/article/getting-start-tdd/haskell/03-obvious-implementation-and-refactoring.md +257 -257
  310. package/lib/assets/docs/article/getting-start-tdd/haskell/04-version-control-and-conventional-commits.md +182 -182
  311. package/lib/assets/docs/article/getting-start-tdd/haskell/05-package-management-and-static-analysis.md +313 -313
  312. package/lib/assets/docs/article/getting-start-tdd/haskell/06-task-runner-and-ci-cd.md +309 -309
  313. package/lib/assets/docs/article/getting-start-tdd/haskell/07-algebraic-data-types-and-type-classes.md +412 -412
  314. package/lib/assets/docs/article/getting-start-tdd/haskell/08-pattern-matching-and-guards.md +390 -390
  315. package/lib/assets/docs/article/getting-start-tdd/haskell/09-module-design-and-smart-constructors.md +461 -461
  316. package/lib/assets/docs/article/getting-start-tdd/haskell/10-higher-order-functions-and-currying.md +434 -434
  317. package/lib/assets/docs/article/getting-start-tdd/haskell/11-function-composition-and-point-free.md +392 -392
  318. package/lib/assets/docs/article/getting-start-tdd/haskell/12-monad-and-error-handling.md +631 -631
  319. package/lib/assets/docs/article/getting-start-tdd/haskell/index.md +49 -49
  320. package/lib/assets/docs/article/getting-start-tdd/index.md +93 -93
  321. package/lib/assets/docs/article/getting-start-tdd/integration/01-language-overview.md +375 -375
  322. package/lib/assets/docs/article/getting-start-tdd/integration/02-test-framework-comparison.md +349 -349
  323. package/lib/assets/docs/article/getting-start-tdd/integration/03-tdd-pattern-comparison.md +445 -445
  324. package/lib/assets/docs/article/getting-start-tdd/integration/04-type-system-comparison.md +409 -409
  325. package/lib/assets/docs/article/getting-start-tdd/integration/05-dev-environment-comparison.md +330 -330
  326. package/lib/assets/docs/article/getting-start-tdd/integration/06-learning-roadmap.md +290 -290
  327. package/lib/assets/docs/article/getting-start-tdd/integration/index.md +69 -69
  328. package/lib/assets/docs/article/getting-start-tdd/java/01-todo-list-and-first-test.md +234 -234
  329. package/lib/assets/docs/article/getting-start-tdd/java/02-fake-it-and-triangulation.md +261 -261
  330. package/lib/assets/docs/article/getting-start-tdd/java/03-obvious-implementation-and-refactoring.md +185 -185
  331. package/lib/assets/docs/article/getting-start-tdd/java/04-version-control-and-conventional-commits.md +115 -115
  332. package/lib/assets/docs/article/getting-start-tdd/java/05-package-management-and-static-analysis.md +382 -382
  333. package/lib/assets/docs/article/getting-start-tdd/java/06-task-runner-and-ci-cd.md +272 -272
  334. package/lib/assets/docs/article/getting-start-tdd/java/07-encapsulation-and-polymorphism.md +626 -626
  335. package/lib/assets/docs/article/getting-start-tdd/java/08-design-patterns.md +393 -393
  336. package/lib/assets/docs/article/getting-start-tdd/java/09-solid-principles-and-module-design.md +310 -310
  337. package/lib/assets/docs/article/getting-start-tdd/java/10-higher-order-functions-and-composition.md +188 -188
  338. package/lib/assets/docs/article/getting-start-tdd/java/11-immutable-data-and-pipeline.md +167 -167
  339. package/lib/assets/docs/article/getting-start-tdd/java/12-error-handling-and-type-safety.md +205 -205
  340. package/lib/assets/docs/article/getting-start-tdd/java/index.md +61 -61
  341. package/lib/assets/docs/article/getting-start-tdd/node/01-todo-list-and-first-test.md +244 -244
  342. package/lib/assets/docs/article/getting-start-tdd/node/02-fake-it-and-triangulation.md +262 -262
  343. package/lib/assets/docs/article/getting-start-tdd/node/03-obvious-implementation-and-refactoring.md +169 -169
  344. package/lib/assets/docs/article/getting-start-tdd/node/04-version-control-and-conventional-commits.md +112 -112
  345. package/lib/assets/docs/article/getting-start-tdd/node/05-package-management-and-static-analysis.md +314 -314
  346. package/lib/assets/docs/article/getting-start-tdd/node/06-task-runner-and-ci-cd.md +235 -235
  347. package/lib/assets/docs/article/getting-start-tdd/node/07-encapsulation-and-polymorphism.md +327 -327
  348. package/lib/assets/docs/article/getting-start-tdd/node/08-design-patterns.md +322 -322
  349. package/lib/assets/docs/article/getting-start-tdd/node/09-solid-principles-and-module-design.md +285 -285
  350. package/lib/assets/docs/article/getting-start-tdd/node/10-higher-order-functions-and-composition.md +199 -199
  351. package/lib/assets/docs/article/getting-start-tdd/node/11-immutable-data-and-pipeline.md +207 -207
  352. package/lib/assets/docs/article/getting-start-tdd/node/12-error-handling-and-type-safety.md +295 -295
  353. package/lib/assets/docs/article/getting-start-tdd/node/index.md +56 -56
  354. package/lib/assets/docs/article/getting-start-tdd/php/01-todo-list-and-first-test.md +259 -259
  355. package/lib/assets/docs/article/getting-start-tdd/php/02-fake-it-and-triangulation.md +200 -200
  356. package/lib/assets/docs/article/getting-start-tdd/php/03-obvious-implementation-and-refactoring.md +248 -248
  357. package/lib/assets/docs/article/getting-start-tdd/php/04-version-control-and-conventional-commits.md +141 -141
  358. package/lib/assets/docs/article/getting-start-tdd/php/05-package-management-and-static-analysis.md +410 -410
  359. package/lib/assets/docs/article/getting-start-tdd/php/06-task-runner-and-ci-cd.md +321 -321
  360. package/lib/assets/docs/article/getting-start-tdd/php/07-encapsulation-and-polymorphism.md +372 -372
  361. package/lib/assets/docs/article/getting-start-tdd/php/08-design-patterns.md +453 -453
  362. package/lib/assets/docs/article/getting-start-tdd/php/09-solid-principles-and-module-design.md +460 -460
  363. package/lib/assets/docs/article/getting-start-tdd/php/10-higher-order-functions-and-composition.md +182 -182
  364. package/lib/assets/docs/article/getting-start-tdd/php/11-immutable-data-and-pipeline.md +266 -266
  365. package/lib/assets/docs/article/getting-start-tdd/php/12-error-handling-and-type-safety.md +308 -308
  366. package/lib/assets/docs/article/getting-start-tdd/php/index.md +84 -84
  367. package/lib/assets/docs/article/getting-start-tdd/python/01-todo-list-and-first-test.md +201 -201
  368. package/lib/assets/docs/article/getting-start-tdd/python/02-fake-it-and-triangulation.md +247 -247
  369. package/lib/assets/docs/article/getting-start-tdd/python/03-obvious-implementation-and-refactoring.md +199 -199
  370. package/lib/assets/docs/article/getting-start-tdd/python/04-version-control-and-conventional-commits.md +87 -87
  371. package/lib/assets/docs/article/getting-start-tdd/python/05-package-management-and-static-analysis.md +274 -274
  372. package/lib/assets/docs/article/getting-start-tdd/python/06-task-runner-and-ci-cd.md +190 -190
  373. package/lib/assets/docs/article/getting-start-tdd/python/07-encapsulation-and-polymorphism.md +208 -208
  374. package/lib/assets/docs/article/getting-start-tdd/python/08-design-patterns.md +172 -172
  375. package/lib/assets/docs/article/getting-start-tdd/python/09-solid-principles-and-module-design.md +130 -130
  376. package/lib/assets/docs/article/getting-start-tdd/python/10-higher-order-functions-and-composition.md +122 -122
  377. package/lib/assets/docs/article/getting-start-tdd/python/11-immutable-data-and-pipeline.md +116 -116
  378. package/lib/assets/docs/article/getting-start-tdd/python/12-error-handling-and-type-safety.md +126 -126
  379. package/lib/assets/docs/article/getting-start-tdd/python/index.md +55 -55
  380. package/lib/assets/docs/article/getting-start-tdd/ruby/01-todo-list-and-first-test.md +231 -231
  381. package/lib/assets/docs/article/getting-start-tdd/ruby/02-fake-it-and-triangulation.md +238 -238
  382. package/lib/assets/docs/article/getting-start-tdd/ruby/03-obvious-implementation-and-refactoring.md +228 -228
  383. package/lib/assets/docs/article/getting-start-tdd/ruby/04-version-control-and-conventional-commits.md +112 -112
  384. package/lib/assets/docs/article/getting-start-tdd/ruby/05-package-management-and-static-analysis.md +287 -287
  385. package/lib/assets/docs/article/getting-start-tdd/ruby/06-task-runner-and-ci-cd.md +248 -248
  386. package/lib/assets/docs/article/getting-start-tdd/ruby/07-encapsulation-and-polymorphism.md +279 -279
  387. package/lib/assets/docs/article/getting-start-tdd/ruby/08-design-patterns.md +329 -329
  388. package/lib/assets/docs/article/getting-start-tdd/ruby/09-solid-principles-and-module-design.md +196 -196
  389. package/lib/assets/docs/article/getting-start-tdd/ruby/10-higher-order-functions-and-composition.md +175 -175
  390. package/lib/assets/docs/article/getting-start-tdd/ruby/11-immutable-data-and-pipeline.md +237 -237
  391. package/lib/assets/docs/article/getting-start-tdd/ruby/12-error-handling-and-type-safety.md +398 -398
  392. package/lib/assets/docs/article/getting-start-tdd/ruby/index.md +83 -83
  393. package/lib/assets/docs/article/getting-start-tdd/rust/01-todo-list-and-first-test.md +211 -211
  394. package/lib/assets/docs/article/getting-start-tdd/rust/02-fake-it-and-triangulation.md +264 -264
  395. package/lib/assets/docs/article/getting-start-tdd/rust/03-obvious-implementation-and-refactoring.md +233 -233
  396. package/lib/assets/docs/article/getting-start-tdd/rust/04-version-control-and-conventional-commits.md +92 -92
  397. package/lib/assets/docs/article/getting-start-tdd/rust/05-package-management-and-static-analysis.md +212 -212
  398. package/lib/assets/docs/article/getting-start-tdd/rust/06-task-runner-and-ci-cd.md +164 -164
  399. package/lib/assets/docs/article/getting-start-tdd/rust/07-encapsulation-and-polymorphism.md +142 -142
  400. package/lib/assets/docs/article/getting-start-tdd/rust/08-design-patterns.md +145 -145
  401. package/lib/assets/docs/article/getting-start-tdd/rust/09-solid-principles-and-module-design.md +110 -110
  402. package/lib/assets/docs/article/getting-start-tdd/rust/10-higher-order-functions-and-composition.md +94 -94
  403. package/lib/assets/docs/article/getting-start-tdd/rust/11-immutable-data-and-pipeline.md +105 -105
  404. package/lib/assets/docs/article/getting-start-tdd/rust/12-error-handling-and-type-safety.md +112 -112
  405. package/lib/assets/docs/article/getting-start-tdd/rust/index.md +83 -83
  406. package/lib/assets/docs/article/getting-start-tdd/scala/01-todo-list-and-first-test.md +111 -111
  407. package/lib/assets/docs/article/getting-start-tdd/scala/02-fake-it-and-triangulation.md +107 -107
  408. package/lib/assets/docs/article/getting-start-tdd/scala/03-obvious-implementation-and-refactoring.md +99 -99
  409. package/lib/assets/docs/article/getting-start-tdd/scala/04-version-control-and-conventional-commits.md +123 -123
  410. package/lib/assets/docs/article/getting-start-tdd/scala/05-package-management-and-static-analysis.md +196 -196
  411. package/lib/assets/docs/article/getting-start-tdd/scala/06-task-runner-and-ci-cd.md +186 -186
  412. package/lib/assets/docs/article/getting-start-tdd/scala/07-case-classes-and-traits.md +139 -139
  413. package/lib/assets/docs/article/getting-start-tdd/scala/08-pattern-matching-and-sealed-traits.md +106 -106
  414. package/lib/assets/docs/article/getting-start-tdd/scala/09-packages-and-module-design.md +75 -75
  415. package/lib/assets/docs/article/getting-start-tdd/scala/10-higher-order-functions-and-composition.md +104 -104
  416. package/lib/assets/docs/article/getting-start-tdd/scala/11-collections-and-lazy-evaluation.md +94 -94
  417. package/lib/assets/docs/article/getting-start-tdd/scala/12-error-handling-and-type-safety.md +92 -92
  418. package/lib/assets/docs/article/getting-start-tdd/scala/index.md +65 -65
  419. package/lib/assets/docs/article/grokking-concurrency/all/index.md +404 -404
  420. package/lib/assets/docs/article/grokking-concurrency/all/part-1-ch02-sequential.md +554 -554
  421. package/lib/assets/docs/article/grokking-concurrency/all/part-2-ch04-05-threads.md +469 -469
  422. package/lib/assets/docs/article/grokking-concurrency/all/part-3-ch06-multitasking.md +520 -520
  423. package/lib/assets/docs/article/grokking-concurrency/all/part-4-ch07-parallel-patterns.md +420 -420
  424. package/lib/assets/docs/article/grokking-concurrency/all/part-5-ch08-09-synchronization.md +510 -510
  425. package/lib/assets/docs/article/grokking-concurrency/all/part-6-ch10-11-nonblocking-io.md +435 -435
  426. package/lib/assets/docs/article/grokking-concurrency/all/part-7-ch12-async.md +465 -465
  427. package/lib/assets/docs/article/grokking-concurrency/all/part-8-ch13-mapreduce.md +377 -377
  428. package/lib/assets/docs/article/grokking-concurrency/clojure/index.md +116 -116
  429. package/lib/assets/docs/article/grokking-concurrency/clojure/part-1.md +108 -108
  430. package/lib/assets/docs/article/grokking-concurrency/clojure/part-2.md +101 -101
  431. package/lib/assets/docs/article/grokking-concurrency/clojure/part-3.md +122 -122
  432. package/lib/assets/docs/article/grokking-concurrency/clojure/part-4.md +123 -123
  433. package/lib/assets/docs/article/grokking-concurrency/clojure/part-5.md +118 -118
  434. package/lib/assets/docs/article/grokking-concurrency/clojure/part-6.md +89 -89
  435. package/lib/assets/docs/article/grokking-concurrency/clojure/part-7.md +100 -100
  436. package/lib/assets/docs/article/grokking-concurrency/clojure/part-8.md +120 -120
  437. package/lib/assets/docs/article/grokking-concurrency/csharp/index.md +101 -101
  438. package/lib/assets/docs/article/grokking-concurrency/csharp/part-1.md +97 -97
  439. package/lib/assets/docs/article/grokking-concurrency/csharp/part-2.md +123 -123
  440. package/lib/assets/docs/article/grokking-concurrency/csharp/part-3.md +101 -101
  441. package/lib/assets/docs/article/grokking-concurrency/csharp/part-4.md +112 -112
  442. package/lib/assets/docs/article/grokking-concurrency/csharp/part-5.md +99 -99
  443. package/lib/assets/docs/article/grokking-concurrency/csharp/part-6.md +61 -61
  444. package/lib/assets/docs/article/grokking-concurrency/csharp/part-7.md +84 -84
  445. package/lib/assets/docs/article/grokking-concurrency/csharp/part-8.md +92 -92
  446. package/lib/assets/docs/article/grokking-concurrency/fsharp/index.md +65 -65
  447. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-1.md +80 -80
  448. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-2.md +103 -103
  449. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-3.md +94 -94
  450. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-4.md +110 -110
  451. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-5.md +104 -104
  452. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-6.md +93 -93
  453. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-7.md +121 -121
  454. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-8.md +107 -107
  455. package/lib/assets/docs/article/grokking-concurrency/haskell/index.md +248 -248
  456. package/lib/assets/docs/article/grokking-concurrency/haskell/part-1.md +96 -96
  457. package/lib/assets/docs/article/grokking-concurrency/haskell/part-2.md +96 -96
  458. package/lib/assets/docs/article/grokking-concurrency/haskell/part-3.md +91 -91
  459. package/lib/assets/docs/article/grokking-concurrency/haskell/part-4.md +106 -106
  460. package/lib/assets/docs/article/grokking-concurrency/haskell/part-5.md +99 -99
  461. package/lib/assets/docs/article/grokking-concurrency/haskell/part-6.md +95 -95
  462. package/lib/assets/docs/article/grokking-concurrency/haskell/part-7.md +111 -111
  463. package/lib/assets/docs/article/grokking-concurrency/haskell/part-8.md +118 -118
  464. package/lib/assets/docs/article/grokking-concurrency/index.md +66 -66
  465. package/lib/assets/docs/article/grokking-concurrency/java/index.md +102 -102
  466. package/lib/assets/docs/article/grokking-concurrency/java/part-1.md +308 -308
  467. package/lib/assets/docs/article/grokking-concurrency/java/part-2.md +334 -334
  468. package/lib/assets/docs/article/grokking-concurrency/java/part-3.md +221 -221
  469. package/lib/assets/docs/article/grokking-concurrency/java/part-4.md +213 -213
  470. package/lib/assets/docs/article/grokking-concurrency/java/part-5.md +112 -112
  471. package/lib/assets/docs/article/grokking-concurrency/java/part-6.md +69 -69
  472. package/lib/assets/docs/article/grokking-concurrency/java/part-7.md +101 -101
  473. package/lib/assets/docs/article/grokking-concurrency/java/part-8.md +101 -101
  474. package/lib/assets/docs/article/grokking-concurrency/python/index.md +313 -313
  475. package/lib/assets/docs/article/grokking-concurrency/python/part-1.md +239 -239
  476. package/lib/assets/docs/article/grokking-concurrency/python/part-2.md +418 -418
  477. package/lib/assets/docs/article/grokking-concurrency/python/part-3.md +227 -227
  478. package/lib/assets/docs/article/grokking-concurrency/python/part-4.md +299 -299
  479. package/lib/assets/docs/article/grokking-concurrency/python/part-5.md +315 -315
  480. package/lib/assets/docs/article/grokking-concurrency/python/part-6.md +297 -297
  481. package/lib/assets/docs/article/grokking-concurrency/python/part-7.md +314 -314
  482. package/lib/assets/docs/article/grokking-concurrency/python/part-8.md +360 -360
  483. package/lib/assets/docs/article/grokking-concurrency/rust/index.md +270 -270
  484. package/lib/assets/docs/article/grokking-concurrency/rust/part-1.md +108 -108
  485. package/lib/assets/docs/article/grokking-concurrency/rust/part-2.md +120 -120
  486. package/lib/assets/docs/article/grokking-concurrency/rust/part-3.md +126 -126
  487. package/lib/assets/docs/article/grokking-concurrency/rust/part-4.md +175 -175
  488. package/lib/assets/docs/article/grokking-concurrency/rust/part-5.md +158 -158
  489. package/lib/assets/docs/article/grokking-concurrency/rust/part-6.md +94 -94
  490. package/lib/assets/docs/article/grokking-concurrency/rust/part-7.md +133 -133
  491. package/lib/assets/docs/article/grokking-concurrency/rust/part-8.md +155 -155
  492. package/lib/assets/docs/article/grokking-concurrency/scala/index.md +69 -69
  493. package/lib/assets/docs/article/grokking-concurrency/scala/part-1.md +78 -78
  494. package/lib/assets/docs/article/grokking-concurrency/scala/part-2.md +112 -112
  495. package/lib/assets/docs/article/grokking-concurrency/scala/part-3.md +93 -93
  496. package/lib/assets/docs/article/grokking-concurrency/scala/part-4.md +110 -110
  497. package/lib/assets/docs/article/grokking-concurrency/scala/part-5.md +119 -119
  498. package/lib/assets/docs/article/grokking-concurrency/scala/part-6.md +83 -83
  499. package/lib/assets/docs/article/grokking-concurrency/scala/part-7.md +131 -131
  500. package/lib/assets/docs/article/grokking-concurrency/scala/part-8.md +129 -129
  501. package/lib/assets/docs/article/grokkingfp/all/index.md +368 -368
  502. package/lib/assets/docs/article/grokkingfp/all/part-1-ch01-fp-introduction.md +530 -530
  503. package/lib/assets/docs/article/grokkingfp/all/part-1-ch02-pure-functions.md +923 -923
  504. package/lib/assets/docs/article/grokkingfp/all/part-2-ch03-immutable-data.md +1128 -1128
  505. package/lib/assets/docs/article/grokkingfp/all/part-2-ch04-higher-order-functions.md +1104 -1104
  506. package/lib/assets/docs/article/grokkingfp/all/part-2-ch05-flatmap.md +1026 -1026
  507. package/lib/assets/docs/article/grokkingfp/all/part-3-ch06-option.md +785 -785
  508. package/lib/assets/docs/article/grokkingfp/all/part-3-ch07-either-adt.md +871 -871
  509. package/lib/assets/docs/article/grokkingfp/all/part-4-ch08-io-monad.md +972 -972
  510. package/lib/assets/docs/article/grokkingfp/all/part-4-ch09-streams.md +926 -926
  511. package/lib/assets/docs/article/grokkingfp/all/part-5-ch10-concurrency.md +870 -870
  512. package/lib/assets/docs/article/grokkingfp/all/part-6-ch11-application.md +715 -715
  513. package/lib/assets/docs/article/grokkingfp/all/part-6-ch12-testing.md +626 -626
  514. package/lib/assets/docs/article/grokkingfp/all/writing-plan.md +712 -712
  515. package/lib/assets/docs/article/grokkingfp/clojure/index.md +276 -276
  516. package/lib/assets/docs/article/grokkingfp/clojure/part-1.md +667 -667
  517. package/lib/assets/docs/article/grokkingfp/clojure/part-2.md +643 -643
  518. package/lib/assets/docs/article/grokkingfp/clojure/part-3.md +620 -620
  519. package/lib/assets/docs/article/grokkingfp/clojure/part-4.md +697 -697
  520. package/lib/assets/docs/article/grokkingfp/clojure/part-5.md +751 -751
  521. package/lib/assets/docs/article/grokkingfp/clojure/part-6.md +721 -721
  522. package/lib/assets/docs/article/grokkingfp/csharp/index.md +246 -246
  523. package/lib/assets/docs/article/grokkingfp/csharp/part-1.md +811 -811
  524. package/lib/assets/docs/article/grokkingfp/csharp/part-2.md +971 -971
  525. package/lib/assets/docs/article/grokkingfp/csharp/part-3.md +981 -981
  526. package/lib/assets/docs/article/grokkingfp/csharp/part-4.md +949 -949
  527. package/lib/assets/docs/article/grokkingfp/csharp/part-5.md +947 -947
  528. package/lib/assets/docs/article/grokkingfp/csharp/part-6.md +739 -739
  529. package/lib/assets/docs/article/grokkingfp/elixir/index.md +203 -203
  530. package/lib/assets/docs/article/grokkingfp/elixir/part-1.md +712 -712
  531. package/lib/assets/docs/article/grokkingfp/elixir/part-2.md +838 -838
  532. package/lib/assets/docs/article/grokkingfp/elixir/part-3.md +985 -985
  533. package/lib/assets/docs/article/grokkingfp/elixir/part-4.md +974 -974
  534. package/lib/assets/docs/article/grokkingfp/elixir/part-5.md +1286 -1286
  535. package/lib/assets/docs/article/grokkingfp/elixir/part-6.md +1049 -1049
  536. package/lib/assets/docs/article/grokkingfp/fsharp/index.md +210 -210
  537. package/lib/assets/docs/article/grokkingfp/fsharp/part-1.md +714 -714
  538. package/lib/assets/docs/article/grokkingfp/fsharp/part-2.md +961 -961
  539. package/lib/assets/docs/article/grokkingfp/fsharp/part-3.md +972 -972
  540. package/lib/assets/docs/article/grokkingfp/fsharp/part-4.md +832 -832
  541. package/lib/assets/docs/article/grokkingfp/fsharp/part-5.md +911 -911
  542. package/lib/assets/docs/article/grokkingfp/fsharp/part-6.md +922 -922
  543. package/lib/assets/docs/article/grokkingfp/haskell/index.md +234 -234
  544. package/lib/assets/docs/article/grokkingfp/haskell/part-1.md +591 -591
  545. package/lib/assets/docs/article/grokkingfp/haskell/part-2.md +866 -866
  546. package/lib/assets/docs/article/grokkingfp/haskell/part-3.md +915 -915
  547. package/lib/assets/docs/article/grokkingfp/haskell/part-4.md +878 -878
  548. package/lib/assets/docs/article/grokkingfp/haskell/part-5.md +845 -845
  549. package/lib/assets/docs/article/grokkingfp/haskell/part-6.md +844 -844
  550. package/lib/assets/docs/article/grokkingfp/index.md +143 -143
  551. package/lib/assets/docs/article/grokkingfp/java/index.md +211 -211
  552. package/lib/assets/docs/article/grokkingfp/java/part-1.md +648 -648
  553. package/lib/assets/docs/article/grokkingfp/java/part-2.md +675 -675
  554. package/lib/assets/docs/article/grokkingfp/java/part-3.md +672 -672
  555. package/lib/assets/docs/article/grokkingfp/java/part-4.md +771 -771
  556. package/lib/assets/docs/article/grokkingfp/java/part-5.md +959 -959
  557. package/lib/assets/docs/article/grokkingfp/java/part-6.md +1328 -1328
  558. package/lib/assets/docs/article/grokkingfp/python/index.md +258 -258
  559. package/lib/assets/docs/article/grokkingfp/python/part-1.md +443 -443
  560. package/lib/assets/docs/article/grokkingfp/python/part-2.md +958 -958
  561. package/lib/assets/docs/article/grokkingfp/python/part-3.md +1004 -1004
  562. package/lib/assets/docs/article/grokkingfp/python/part-4.md +765 -765
  563. package/lib/assets/docs/article/grokkingfp/python/part-5.md +747 -747
  564. package/lib/assets/docs/article/grokkingfp/python/part-6.md +861 -861
  565. package/lib/assets/docs/article/grokkingfp/ruby/index.md +330 -330
  566. package/lib/assets/docs/article/grokkingfp/ruby/part-1.md +755 -755
  567. package/lib/assets/docs/article/grokkingfp/ruby/part-2.md +938 -938
  568. package/lib/assets/docs/article/grokkingfp/ruby/part-3.md +946 -946
  569. package/lib/assets/docs/article/grokkingfp/ruby/part-4.md +921 -921
  570. package/lib/assets/docs/article/grokkingfp/ruby/part-5.md +908 -908
  571. package/lib/assets/docs/article/grokkingfp/ruby/part-6.md +1412 -1412
  572. package/lib/assets/docs/article/grokkingfp/rust/index.md +242 -242
  573. package/lib/assets/docs/article/grokkingfp/rust/part-1.md +634 -634
  574. package/lib/assets/docs/article/grokkingfp/rust/part-2.md +1060 -1060
  575. package/lib/assets/docs/article/grokkingfp/rust/part-3.md +994 -994
  576. package/lib/assets/docs/article/grokkingfp/rust/part-4.md +573 -573
  577. package/lib/assets/docs/article/grokkingfp/rust/part-5.md +705 -705
  578. package/lib/assets/docs/article/grokkingfp/rust/part-6.md +508 -508
  579. package/lib/assets/docs/article/grokkingfp/scala/index.md +171 -171
  580. package/lib/assets/docs/article/grokkingfp/scala/part-1.md +543 -543
  581. package/lib/assets/docs/article/grokkingfp/scala/part-2.md +946 -946
  582. package/lib/assets/docs/article/grokkingfp/scala/part-3.md +919 -919
  583. package/lib/assets/docs/article/grokkingfp/scala/part-4.md +742 -742
  584. package/lib/assets/docs/article/grokkingfp/scala/part-5.md +722 -722
  585. package/lib/assets/docs/article/grokkingfp/scala/part-6.md +867 -867
  586. package/lib/assets/docs/article/grokkingfp/typescript/index.md +273 -273
  587. package/lib/assets/docs/article/grokkingfp/typescript/part-1.md +561 -561
  588. package/lib/assets/docs/article/grokkingfp/typescript/part-2.md +1129 -1129
  589. package/lib/assets/docs/article/grokkingfp/typescript/part-3.md +842 -842
  590. package/lib/assets/docs/article/grokkingfp/typescript/part-4.md +1087 -1087
  591. package/lib/assets/docs/article/grokkingfp/typescript/part-5.md +717 -717
  592. package/lib/assets/docs/article/grokkingfp/typescript/part-6.md +982 -982
  593. package/lib/assets/docs/article/index.md +41 -41
  594. package/lib/assets/docs/article/practical-database-design/index.md +121 -121
  595. package/lib/assets/docs/article/practical-database-design/part1/chapter01.md +288 -288
  596. package/lib/assets/docs/article/practical-database-design/part1/chapter02.md +518 -518
  597. package/lib/assets/docs/article/practical-database-design/part1/chapter03.md +557 -557
  598. package/lib/assets/docs/article/practical-database-design/part2/chapter04.md +924 -924
  599. package/lib/assets/docs/article/practical-database-design/part2/chapter05.md +1627 -1627
  600. package/lib/assets/docs/article/practical-database-design/part2/chapter06.md +2716 -2716
  601. package/lib/assets/docs/article/practical-database-design/part2/chapter07.md +2082 -2082
  602. package/lib/assets/docs/article/practical-database-design/part2/chapter08.md +2105 -2105
  603. package/lib/assets/docs/article/practical-database-design/part2/chapter09.md +2031 -2031
  604. package/lib/assets/docs/article/practical-database-design/part2/chapter10.md +1387 -1387
  605. package/lib/assets/docs/article/practical-database-design/part2/chapter11.md +1677 -1677
  606. package/lib/assets/docs/article/practical-database-design/part2/chapter12.md +1417 -1417
  607. package/lib/assets/docs/article/practical-database-design/part2/chapter13.md +1434 -1434
  608. package/lib/assets/docs/article/practical-database-design/part3/chapter14.md +667 -667
  609. package/lib/assets/docs/article/practical-database-design/part3/chapter15.md +1625 -1625
  610. package/lib/assets/docs/article/practical-database-design/part3/chapter16.md +1915 -1915
  611. package/lib/assets/docs/article/practical-database-design/part3/chapter17.md +1708 -1708
  612. package/lib/assets/docs/article/practical-database-design/part3/chapter18.md +2095 -2095
  613. package/lib/assets/docs/article/practical-database-design/part3/chapter19.md +1123 -1123
  614. package/lib/assets/docs/article/practical-database-design/part3/chapter20.md +1031 -1031
  615. package/lib/assets/docs/article/practical-database-design/part3/chapter21.md +1382 -1382
  616. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter14-orm.md +991 -991
  617. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter15-orm.md +1300 -1300
  618. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter16-orm.md +1166 -1166
  619. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter17-orm.md +1584 -1584
  620. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter18-orm.md +1183 -1183
  621. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter19-orm.md +1016 -1016
  622. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter20-orm.md +1753 -1753
  623. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter21-orm.md +1447 -1447
  624. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter22-orm.md +1878 -1878
  625. package/lib/assets/docs/article/practical-database-design/part4/chapter22.md +965 -965
  626. package/lib/assets/docs/article/practical-database-design/part4/chapter23.md +2069 -2069
  627. package/lib/assets/docs/article/practical-database-design/part4/chapter24.md +2439 -2439
  628. package/lib/assets/docs/article/practical-database-design/part4/chapter25.md +3661 -3661
  629. package/lib/assets/docs/article/practical-database-design/part4/chapter26.md +2916 -2916
  630. package/lib/assets/docs/article/practical-database-design/part4/chapter27.md +3105 -3105
  631. package/lib/assets/docs/article/practical-database-design/part4/chapter28.md +2697 -2697
  632. package/lib/assets/docs/article/practical-database-design/part4/chapter29.md +2544 -2544
  633. package/lib/assets/docs/article/practical-database-design/part4/chapter30.md +2180 -2180
  634. package/lib/assets/docs/article/practical-database-design/part4/chapter31.md +1192 -1192
  635. package/lib/assets/docs/article/practical-database-design/part4/chapter32.md +2101 -2101
  636. package/lib/assets/docs/article/practical-database-design/part5/chapter33.md +1032 -1032
  637. package/lib/assets/docs/article/practical-database-design/part5/chapter34.md +1609 -1609
  638. package/lib/assets/docs/article/practical-database-design/part5/chapter35.md +1453 -1453
  639. package/lib/assets/docs/article/practical-database-design/part5/chapter36.md +1292 -1292
  640. package/lib/assets/docs/article/practical-database-design/part5/chapter37.md +1470 -1470
  641. package/lib/assets/docs/article/practical-database-design/part5/chapter38.md +1698 -1698
  642. package/lib/assets/docs/article/practical-database-design/part5/chapter39.md +2334 -2334
  643. package/lib/assets/docs/article/practical-database-design/study/study2-1.md +1693 -1693
  644. package/lib/assets/docs/article/practical-database-design/study/study2-2.md +1347 -1347
  645. package/lib/assets/docs/article/practical-database-design/study/study2-3.md +2044 -2044
  646. package/lib/assets/docs/article/practical-database-design/study/study2-4.md +2229 -2229
  647. package/lib/assets/docs/article/practical-database-design/study/study2-5.md +2418 -2418
  648. package/lib/assets/docs/article/practical-database-design/study/study3-1.md +2205 -2205
  649. package/lib/assets/docs/article/practical-database-design/study/study3-2.md +2221 -2221
  650. package/lib/assets/docs/article/practical-database-design/study/study3-3.md +2253 -2253
  651. package/lib/assets/docs/article/practical-database-design/study/study3-4.md +2106 -2106
  652. package/lib/assets/docs/article/practical-database-design/study/study3-5.md +2507 -2507
  653. package/lib/assets/docs/article/practical-database-design/study/study4-1.md +2587 -2587
  654. package/lib/assets/docs/article/practical-database-design/study/study4-2.md +2075 -2075
  655. package/lib/assets/docs/article/practical-database-design/study/study4-3.md +1805 -1805
  656. package/lib/assets/docs/article/practical-database-design/study/study4-4.md +1895 -1895
  657. package/lib/assets/docs/article/practical-database-design/study/study4-5.md +2878 -2878
  658. package/lib/assets/docs/assets/css/extra.css +29 -29
  659. package/lib/assets/docs/assets/js/extra.js +44 -44
  660. package/lib/assets/docs/design/index.md +44 -44
  661. package/lib/assets/docs/development/index.md +39 -39
  662. package/lib/assets/docs/index.md +33 -33
  663. package/lib/assets/docs/operation/index.md +27 -27
  664. package/lib/assets/docs/reference/CodexCLIMCP/343/202/242/343/203/227/343/203/252/343/202/261/343/203/274/343/202/267/343/203/247/343/203/263/351/226/213/347/231/272/343/203/225/343/203/255/343/203/274.md +546 -546
  665. package/lib/assets/docs/reference/CodexCLIMCP/343/202/265/343/203/274/343/203/220/343/203/274/350/250/255/345/256/232/346/211/213/351/240/206.md +341 -341
  666. package/lib/assets/docs/reference/Java/343/202/242/343/203/227/343/203/252/343/202/261/343/203/274/343/202/267/343/203/247/343/203/263/347/222/260/345/242/203/346/247/213/347/257/211/343/202/254/343/202/244/343/203/211.md +581 -581
  667. package/lib/assets/docs/reference/SonarQube/343/203/255/343/203/274/343/202/253/343/203/253/347/222/260/345/242/203/343/202/273/343/203/203/343/203/210/343/202/242/343/203/203/343/203/227/346/211/213/351/240/206/346/233/270.md +642 -642
  668. package/lib/assets/docs/reference/TypeScript/343/202/242/343/203/227/343/203/252/343/202/261/343/203/274/343/202/267/343/203/247/343/203/263/347/222/260/345/242/203/346/247/213/347/257/211/343/202/254/343/202/244/343/203/211.md +465 -465
  669. package/lib/assets/docs/reference/UI/350/250/255/350/250/210/343/202/254/343/202/244/343/203/211.md +450 -450
  670. package/lib/assets/docs/reference/images/Ansoff.drawio.svg +3 -3
  671. package/lib/assets/docs/reference/images/BMC.drawio.svg +3 -3
  672. package/lib/assets/docs/reference/images/BrandBasicStrategy.drawio.svg +3 -3
  673. package/lib/assets/docs/reference/images/BrandCategorization.drawio.svg +3 -3
  674. package/lib/assets/docs/reference/images/BrandRecurutementStrategy.drawio.svg +3 -3
  675. package/lib/assets/docs/reference/images/BrandValue.drawio.svg +3 -3
  676. package/lib/assets/docs/reference/images/BusinessActivitiy.svg +3 -3
  677. package/lib/assets/docs/reference/images/HRM.drawio.svg +3 -3
  678. package/lib/assets/docs/reference/images/MarketingStructure.drawio.svg +3 -3
  679. package/lib/assets/docs/reference/images/OrganizationElemnts.svg +3 -3
  680. package/lib/assets/docs/reference/images/PPM.drawio.svg +3 -3
  681. package/lib/assets/docs/reference/images/PositioningMap.drawio.svg +3 -3
  682. package/lib/assets/docs/reference/images/ProductLayer.drawio.svg +3 -3
  683. package/lib/assets/docs/reference/images/ProductMix.drawio.svg +3 -3
  684. package/lib/assets/docs/reference/images/SWOT.drawio.svg +3 -3
  685. package/lib/assets/docs/reference/images/TargetMarket.drawio.svg +3 -3
  686. package/lib/assets/docs/reference/images/ThreeGenericStrategies.drawio.svg +3 -3
  687. package/lib/assets/docs/reference/images/VRIO.drawio.svg +3 -3
  688. package/lib/assets/docs/reference/images/ValueChain.drawio.svg +3 -3
  689. package/lib/assets/docs/reference/index.md +53 -53
  690. package/lib/assets/docs/reference//343/202/210/343/201/204/343/202/275/343/203/225/343/203/210/343/202/246/343/202/247/343/202/242/343/201/250/343/201/257.md +250 -250
  691. package/lib/assets/docs/reference//343/202/242/343/203/274/343/202/255/343/203/206/343/202/257/343/203/201/343/203/243/350/250/255/350/250/210/343/202/254/343/202/244/343/203/211.md +2216 -2216
  692. package/lib/assets/docs/reference//343/202/244/343/203/263/343/203/225/343/203/251/350/250/255/350/250/210/343/202/254/343/202/244/343/203/211.md +1878 -1878
  693. package/lib/assets/docs/reference//343/202/250/343/202/257/343/202/271/343/203/210/343/203/252/343/203/274/343/203/240/343/203/227/343/203/255/343/202/260/343/203/251/343/203/237/343/203/263/343/202/260.md +550 -550
  694. package/lib/assets/docs/reference//343/202/263/343/203/274/343/203/207/343/202/243/343/203/263/343/202/260/343/201/250/343/203/206/343/202/271/343/203/210/343/202/254/343/202/244/343/203/211.md +705 -705
  695. package/lib/assets/docs/reference//343/203/206/343/202/271/343/203/210/346/210/246/347/225/245/343/202/254/343/202/244/343/203/211.md +1313 -1313
  696. package/lib/assets/docs/reference//343/203/207/343/203/274/343/202/277/343/203/242/343/203/207/343/203/253/350/250/255/350/250/210/343/202/254/343/202/244/343/203/211.md +311 -311
  697. package/lib/assets/docs/reference//343/203/211/343/203/241/343/202/244/343/203/263/343/203/242/343/203/207/343/203/253/350/250/255/350/250/210/343/202/254/343/202/244/343/203/211.md +599 -599
  698. package/lib/assets/docs/reference//343/203/223/343/202/270/343/203/215/343/202/271/343/202/242/343/203/274/343/202/255/343/203/206/343/202/257/343/203/201/343/203/243/345/210/206/346/236/220/343/202/254/343/202/244/343/203/211.md +528 -528
  699. package/lib/assets/docs/reference//343/203/246/343/203/274/343/202/271/343/202/261/343/203/274/343/202/271/344/275/234/346/210/220/343/202/254/343/202/244/343/203/211.md +689 -689
  700. package/lib/assets/docs/reference//343/203/252/343/203/252/343/203/274/343/202/271/343/202/254/343/202/244/343/203/211.md +461 -461
  701. package/lib/assets/docs/reference//343/203/252/343/203/252/343/203/274/343/202/271/343/203/273/343/202/244/343/203/206/343/203/254/343/203/274/343/202/267/343/203/247/343/203/263/350/250/210/347/224/273/343/202/254/343/202/244/343/203/211.md +580 -580
  702. package/lib/assets/docs/reference//343/203/255/343/202/270/343/202/253/343/203/253/343/202/267/343/203/263/343/202/255/343/203/263/343/202/260.md +1367 -1367
  703. package/lib/assets/docs/reference//344/274/201/346/245/255/347/265/214/345/226/266/350/253/226.md +2637 -2637
  704. package/lib/assets/docs/reference//347/222/260/345/242/203/345/244/211/346/225/260/347/256/241/347/220/206/343/202/254/343/202/244/343/203/211.md +665 -665
  705. package/lib/assets/docs/reference//347/265/214/345/226/266/346/210/246/347/225/245/345/210/206/346/236/220/343/202/254/343/202/244/343/203/211.md +566 -566
  706. package/lib/assets/docs/reference//350/246/201/344/273/266/345/256/232/347/276/251/343/202/254/343/202/244/343/203/211.md +1248 -1248
  707. package/lib/assets/docs/reference//350/250/200/350/252/236/345/210/245/351/226/213/347/231/272/343/202/254/343/202/244/343/203/211.md +518 -518
  708. package/lib/assets/docs/reference//351/201/213/345/226/266/347/256/241/347/220/206.md +1482 -1482
  709. package/lib/assets/docs/reference//351/201/213/347/224/250/343/202/271/343/202/257/343/203/252/343/203/227/343/203/210/344/275/234/346/210/220/343/202/254/343/202/244/343/203/211.md +421 -421
  710. package/lib/assets/docs/reference//351/201/213/347/224/250/350/246/201/344/273/266/345/256/232/347/276/251/343/202/254/343/202/244/343/203/211.md +392 -392
  711. package/lib/assets/docs/reference//351/226/213/347/231/272/343/202/254/343/202/244/343/203/211.md +305 -305
  712. package/lib/assets/docs/reference//351/235/236/346/251/237/350/203/275/350/246/201/344/273/266/345/256/232/347/276/251/343/202/254/343/202/244/343/203/211.md +1236 -1236
  713. package/lib/assets/docs/requirements/index.md +17 -17
  714. package/lib/assets/docs/review/index.md +5 -5
  715. package/lib/assets/docs/strategy/index.md +17 -17
  716. package/lib/assets/docs/template/ADR.md +30 -30
  717. package/lib/assets/docs/template/AWS/343/202/271/343/203/206/343/203/274/343/202/270/343/203/263/343/202/260/347/222/260/345/242/203/343/202/273/343/203/203/343/203/210/343/202/242/343/203/203/343/203/227/346/211/213/351/240/206/346/233/270.md +1366 -1366
  718. package/lib/assets/docs/template/AWS/343/203/227/343/203/255/343/203/200/343/202/257/343/202/267/343/203/247/343/203/263/347/222/260/345/242/203/343/202/273/343/203/203/343/203/210/343/202/242/343/203/203/343/203/227/346/211/213/351/240/206/346/233/270.md +634 -634
  719. package/lib/assets/docs/template/README.md +50 -50
  720. package/lib/assets/docs/template/index.md +24 -24
  721. package/lib/assets/docs/template//343/201/276/343/201/232/343/201/223/343/202/214/343/202/222/350/252/255/343/202/202/343/201/206/343/203/252/343/202/271/343/203/210.md +12 -12
  722. package/lib/assets/docs/template//343/202/242/343/203/227/343/203/252/343/202/261/343/203/274/343/202/267/343/203/247/343/203/263/351/226/213/347/231/272/347/222/260/345/242/203/343/202/273/343/203/203/343/203/210/343/202/242/343/203/203/343/203/227/346/211/213/351/240/206/346/233/270.md +547 -547
  723. package/lib/assets/docs/template//343/202/244/343/203/206/343/203/254/343/203/274/343/202/267/343/203/247/343/203/263/345/256/214/344/272/206/345/240/261/345/221/212/346/233/270.md +58 -58
  724. package/lib/assets/docs/template//343/202/244/343/203/206/343/203/254/343/203/274/343/202/267/343/203/247/343/203/263/350/250/210/347/224/273.md +327 -327
  725. package/lib/assets/docs/template//343/202/244/343/203/263/343/202/273/343/203/227/343/202/267/343/203/247/343/203/263/343/203/207/343/203/203/343/202/255.md +13 -13
  726. package/lib/assets/docs/template//343/203/223/343/202/270/343/203/215/343/202/271/343/202/242/343/203/274/343/202/255/343/203/206/343/202/257/343/203/201/343/203/243.md +379 -379
  727. package/lib/assets/docs/template//343/203/252/343/203/252/343/203/274/343/202/271/345/256/214/344/272/206/345/240/261/345/221/212/346/233/270.md +275 -275
  728. package/lib/assets/docs/template//344/272/213/344/276/213/345/210/206/346/236/220.md +513 -513
  729. package/lib/assets/docs/template//344/274/201/346/245/255/345/210/206/346/236/220.md +573 -573
  730. package/lib/assets/docs/template//345/256/214/345/205/250/345/275/242/345/274/217/343/201/256/343/203/246/343/203/274/343/202/271/343/202/261/343/203/274/343/202/271.md +69 -69
  731. package/lib/assets/docs/template//350/246/201/344/273/266/345/256/232/347/276/251.md +669 -669
  732. package/lib/assets/docs/template//350/250/255/350/250/210.md +173 -173
  733. package/lib/assets/docs/template//351/226/213/347/231/272/347/222/260/345/242/203/343/202/273/343/203/203/343/203/210/343/202/242/343/203/203/343/203/227/346/211/213/351/240/206/346/233/270.md +688 -688
  734. package/lib/assets/gulpfile.js +25 -25
  735. package/lib/assets/mkdocs.yml +139 -139
  736. package/lib/assets/ops/docker/mkdoc/Dockerfile +19 -19
  737. package/lib/assets/ops/docker/sonarqube-local/docker-compose.yml +57 -57
  738. package/lib/assets/ops/scripts/journal.js +180 -180
  739. package/lib/assets/ops/scripts/mkdocs.js +82 -82
  740. package/lib/assets/ops/scripts/release.js +431 -431
  741. package/lib/assets/ops/scripts/sonar_local.js +726 -726
  742. package/lib/assets/ops/scripts/ssh.js +190 -190
  743. package/lib/assets/ops/scripts/vault.js +299 -299
  744. package/lib/assets/package-lock.json +1653 -1653
  745. package/lib/assets/package.json +40 -40
  746. package/lib/gulpfile.js +37 -37
  747. package/package.json +41 -41
@@ -1,1627 +1,1627 @@
1
- # 第5章:マスタ情報の設計
2
-
3
- 販売管理システムの基盤となるマスタ情報を TDD で設計していきます。本章では、組織・社員・商品・取引先といった基本的なマスタテーブルの設計と実装を行います。
4
-
5
- ## 5.1 部門マスタの設計
6
-
7
- 企業の組織構造を管理する部門マスタを設計します。
8
-
9
- ### 組織階層の概念
10
-
11
- 企業の組織は階層構造を持っています。部門マスタでは、この階層構造を「部門パス」で表現します。
12
-
13
- ```plantuml
14
- @startwbs
15
-
16
- * 全社 : 10000
17
- ** 営業本部 : 11000
18
- *** 東日本営業部 : 11100
19
- **** 営業1課 : 11101
20
- **** 営業2課 : 11102
21
- *** 西日本営業部 : 11200
22
- **** 営業3課 : 11201
23
- **** 営業4課 : 11202
24
- ** 管理本部 : 12000
25
- *** 総務部 : 12100
26
- **** 庶務課 : 12101
27
- **** 人事課 : 12102
28
- *** 経理部 : 12200
29
- **** 経理課 : 12201
30
- **** 財務課 : 12202
31
-
32
- @endwbs
33
- ```
34
-
35
- ### 部門マスタの ER 図
36
-
37
- ```plantuml
38
- @startuml
39
-
40
- title 部門マスタ
41
-
42
- entity 部門マスタ {
43
- 部門コード <<PK>>
44
- 開始日 <<PK>>
45
- --
46
- 終了日
47
- 部門名
48
- 組織階層
49
- 部門パス
50
- 最下層区分
51
- 作成日時
52
- 作成者名
53
- 更新日時
54
- 更新者名
55
- }
56
-
57
- note right of 部門マスタ
58
- 部門パスの例:
59
- 10000~11000~11100
60
- (チルダで連結)
61
- end note
62
-
63
- @enduml
64
- ```
65
-
66
- ### 部門マスタの項目説明
67
-
68
- | 項目 | 説明 | 例 |
69
- |-----|------|-----|
70
- | **部門コード** | 部門を一意に識別するコード | `11101` |
71
- | **開始日** | 部門の有効期間開始日 | `2025-01-01` |
72
- | **終了日** | 部門の有効期間終了日 | `null`(有効) |
73
- | **部門名** | 部門の名称 | `営業1課` |
74
- | **組織階層** | 階層の深さ(0から開始) | `3` |
75
- | **部門パス** | ルートからのパス(チルダ連結) | `10000~11000~11100~11101` |
76
- | **最下層区分** | 最下層(末端)かどうか | `true` |
77
-
78
- ### 組織改正への対応(履歴管理)
79
-
80
- 組織改正が発生した場合、同じ部門コードでも開始日が異なるレコードを登録することで、組織の変遷を管理できます。
81
-
82
- ```plantuml
83
- @startuml
84
-
85
- title 組織改正の履歴管理
86
-
87
- entity "部門マスタ(2024年度)" as dept2024 {
88
- 部門コード: 11000
89
- 開始日: 2024-01-01
90
- 終了日: 2024-12-31
91
- --
92
- 部門名: 営業部
93
- 組織階層: 1
94
- 部門パス: 10000~11000
95
- }
96
-
97
- entity "部門マスタ(2025年度)" as dept2025 {
98
- 部門コード: 11000
99
- 開始日: 2025-01-01
100
- 終了日: null
101
- --
102
- 部門名: 営業本部
103
- 組織階層: 1
104
- 部門パス: 10000~11000
105
- }
106
-
107
- dept2024 -[hidden]- dept2025
108
-
109
- note bottom of dept2025
110
- 同じ部門コードでも
111
- 開始日が異なれば
112
- 別レコードとして登録可能
113
- end note
114
-
115
- @enduml
116
- ```
117
-
118
- ### マイグレーション:部門マスタテーブルの作成
119
-
120
- <details>
121
- <summary>SQL 実装</summary>
122
-
123
- ```sql
124
- -- src/main/resources/db/migration/V002__create_department_master.sql
125
-
126
- -- 部門マスタ(日本語テーブル名・カラム名)
127
- CREATE TABLE "部門マスタ" (
128
- "部門コード" VARCHAR(10) NOT NULL,
129
- "開始日" DATE NOT NULL,
130
- "終了日" DATE,
131
- "部門名" VARCHAR(40) NOT NULL,
132
- "組織階層" INTEGER NOT NULL DEFAULT 0,
133
- "部門パス" VARCHAR(100),
134
- "最下層区分" BOOLEAN NOT NULL DEFAULT FALSE,
135
- "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
136
- "作成者名" VARCHAR(50),
137
- "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
138
- "更新者名" VARCHAR(50),
139
- PRIMARY KEY ("部門コード", "開始日")
140
- );
141
-
142
- -- インデックス
143
- CREATE INDEX idx_部門マスタ_部門パス ON "部門マスタ"("部門パス");
144
- CREATE INDEX idx_部門マスタ_組織階層 ON "部門マスタ"("組織階層");
145
- ```
146
-
147
- </details>
148
-
149
- ### TDD:部門の登録と取得
150
-
151
- #### Red: 失敗するテストを書く
152
-
153
- <details>
154
- <summary>DepartmentRepositoryTest.java</summary>
155
-
156
- ```java
157
- // src/test/java/com/example/sms/infrastructure/persistence/repository/DepartmentRepositoryTest.java
158
- package com.example.sms.infrastructure.persistence.repository;
159
-
160
- import com.example.sms.application.port.out.DepartmentRepository;
161
- import com.example.sms.domain.model.department.Department;
162
- import com.example.sms.testsetup.BaseIntegrationTest;
163
- import org.junit.jupiter.api.*;
164
- import org.springframework.beans.factory.annotation.Autowired;
165
-
166
- import java.time.LocalDate;
167
-
168
- import static org.assertj.core.api.Assertions.*;
169
-
170
- @DisplayName("部門リポジトリ")
171
- class DepartmentRepositoryTest extends BaseIntegrationTest {
172
-
173
- @Autowired
174
- private DepartmentRepository departmentRepository;
175
-
176
- @BeforeEach
177
- void setUp() {
178
- departmentRepository.deleteAll();
179
- }
180
-
181
- @Nested
182
- @DisplayName("登録")
183
- class Registration {
184
-
185
- @Test
186
- @DisplayName("部門を登録できる")
187
- void canRegisterDepartment() {
188
- // Arrange
189
- var department = Department.builder()
190
- .departmentCode("10000")
191
- .startDate(LocalDate.of(2025, 1, 1))
192
- .departmentName("本社")
193
- .hierarchyLevel(0)
194
- .departmentPath("10000")
195
- .isLeaf(false)
196
- .build();
197
-
198
- // Act
199
- departmentRepository.save(department);
200
-
201
- // Assert
202
- var result = departmentRepository.findByCode("10000");
203
- assertThat(result).isPresent();
204
- assertThat(result.get().getDepartmentName()).isEqualTo("本社");
205
- assertThat(result.get().getHierarchyLevel()).isEqualTo(0);
206
- }
207
-
208
- @Test
209
- @DisplayName("階層構造を持つ部門を登録できる")
210
- void canRegisterHierarchicalDepartments() {
211
- // Arrange: 親部門
212
- var parent = Department.builder()
213
- .departmentCode("10000")
214
- .startDate(LocalDate.of(2025, 1, 1))
215
- .departmentName("本社")
216
- .hierarchyLevel(0)
217
- .departmentPath("10000")
218
- .isLeaf(false)
219
- .build();
220
- departmentRepository.save(parent);
221
-
222
- // Arrange: 子部門
223
- var child = Department.builder()
224
- .departmentCode("11000")
225
- .startDate(LocalDate.of(2025, 1, 1))
226
- .departmentName("営業本部")
227
- .hierarchyLevel(1)
228
- .departmentPath("10000~11000")
229
- .isLeaf(false)
230
- .build();
231
- departmentRepository.save(child);
232
-
233
- // Arrange: 孫部門(最下層)
234
- var grandChild = Department.builder()
235
- .departmentCode("11101")
236
- .startDate(LocalDate.of(2025, 1, 1))
237
- .departmentName("営業1課")
238
- .hierarchyLevel(3)
239
- .departmentPath("10000~11000~11100~11101")
240
- .isLeaf(true)
241
- .build();
242
- departmentRepository.save(grandChild);
243
-
244
- // Act
245
- var result = departmentRepository.findByCode("11101");
246
-
247
- // Assert
248
- assertThat(result).isPresent();
249
- assertThat(result.get().getDepartmentPath()).isEqualTo("10000~11000~11100~11101");
250
- assertThat(result.get().isLeaf()).isTrue();
251
- }
252
- }
253
-
254
- @Nested
255
- @DisplayName("履歴管理")
256
- class HistoryManagement {
257
-
258
- @Test
259
- @DisplayName("同じ部門コードでも開始日が異なれば登録できる(組織改正対応)")
260
- void canRegisterSameCodeWithDifferentStartDate() {
261
- // Arrange: 旧組織
262
- var oldDept = Department.builder()
263
- .departmentCode("11000")
264
- .startDate(LocalDate.of(2024, 1, 1))
265
- .endDate(LocalDate.of(2024, 12, 31))
266
- .departmentName("営業部")
267
- .hierarchyLevel(1)
268
- .departmentPath("10000~11000")
269
- .isLeaf(false)
270
- .build();
271
- departmentRepository.save(oldDept);
272
-
273
- // Arrange: 新組織
274
- var newDept = Department.builder()
275
- .departmentCode("11000")
276
- .startDate(LocalDate.of(2025, 1, 1))
277
- .departmentName("営業本部")
278
- .hierarchyLevel(1)
279
- .departmentPath("10000~11000")
280
- .isLeaf(false)
281
- .build();
282
- departmentRepository.save(newDept);
283
-
284
- // Act: 現在有効な部門を取得
285
- var result = departmentRepository.findByCodeAndDate("11000", LocalDate.of(2025, 4, 1));
286
-
287
- // Assert
288
- assertThat(result).isPresent();
289
- assertThat(result.get().getDepartmentName()).isEqualTo("営業本部");
290
- }
291
- }
292
- }
293
- ```
294
-
295
- </details>
296
-
297
- #### Green: テストを通す実装
298
-
299
- <details>
300
- <summary>Department.java(エンティティ)</summary>
301
-
302
- ```java
303
- // src/main/java/com/example/sms/domain/model/department/Department.java
304
- package com.example.sms.domain.model.department;
305
-
306
- import lombok.*;
307
- import java.time.LocalDate;
308
- import java.time.LocalDateTime;
309
-
310
- @Data
311
- @Builder
312
- @NoArgsConstructor
313
- @AllArgsConstructor
314
- public class Department {
315
- private String departmentCode;
316
- private LocalDate startDate;
317
- private LocalDate endDate;
318
- private String departmentName;
319
- @Builder.Default
320
- private Integer hierarchyLevel = 0;
321
- private String departmentPath;
322
- @Builder.Default
323
- private boolean isLeaf = false;
324
- private LocalDateTime createdAt;
325
- private String createdBy;
326
- private LocalDateTime updatedAt;
327
- private String updatedBy;
328
- }
329
- ```
330
-
331
- </details>
332
-
333
- <details>
334
- <summary>DepartmentRepository.java(Output Port)</summary>
335
-
336
- ```java
337
- // src/main/java/com/example/sms/application/port/out/DepartmentRepository.java
338
- package com.example.sms.application.port.out;
339
-
340
- import com.example.sms.domain.model.department.Department;
341
-
342
- import java.time.LocalDate;
343
- import java.util.List;
344
- import java.util.Optional;
345
-
346
- /**
347
- * 部門リポジトリ(Output Port)
348
- */
349
- public interface DepartmentRepository {
350
-
351
- void save(Department department);
352
-
353
- Optional<Department> findByCode(String departmentCode);
354
-
355
- Optional<Department> findByCodeAndDate(String departmentCode, LocalDate baseDate);
356
-
357
- List<Department> findAll();
358
-
359
- List<Department> findByHierarchyLevel(int level);
360
-
361
- List<Department> findChildren(String parentPath);
362
-
363
- void update(Department department);
364
-
365
- void deleteAll();
366
- }
367
- ```
368
-
369
- </details>
370
-
371
- <details>
372
- <summary>DepartmentMapper.xml</summary>
373
-
374
- ```xml
375
- <?xml version="1.0" encoding="UTF-8" ?>
376
- <!DOCTYPE mapper
377
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
378
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
379
- <mapper namespace="com.example.sms.infrastructure.persistence.mapper.DepartmentMapper">
380
-
381
- <resultMap id="DepartmentResultMap" type="com.example.sms.domain.model.department.Department">
382
- <result property="departmentCode" column="部門コード"/>
383
- <result property="startDate" column="開始日"/>
384
- <result property="endDate" column="終了日"/>
385
- <result property="departmentName" column="部門名"/>
386
- <result property="hierarchyLevel" column="組織階層"/>
387
- <result property="departmentPath" column="部門パス"/>
388
- <result property="isLeaf" column="最下層区分"/>
389
- <result property="createdAt" column="作成日時"/>
390
- <result property="createdBy" column="作成者名"/>
391
- <result property="updatedAt" column="更新日時"/>
392
- <result property="updatedBy" column="更新者名"/>
393
- </resultMap>
394
-
395
- <insert id="insert" parameterType="com.example.sms.domain.model.department.Department">
396
- INSERT INTO "部門マスタ" (
397
- "部門コード", "開始日", "終了日", "部門名",
398
- "組織階層", "部門パス", "最下層区分",
399
- "作成日時", "作成者名", "更新日時", "更新者名"
400
- ) VALUES (
401
- #{departmentCode}, #{startDate}, #{endDate}, #{departmentName},
402
- #{hierarchyLevel}, #{departmentPath}, #{isLeaf},
403
- CURRENT_TIMESTAMP, #{createdBy}, CURRENT_TIMESTAMP, #{updatedBy}
404
- )
405
- </insert>
406
-
407
- <select id="findByCode" resultMap="DepartmentResultMap">
408
- SELECT * FROM "部門マスタ"
409
- WHERE "部門コード" = #{departmentCode}
410
- AND ("終了日" IS NULL OR "終了日" > CURRENT_DATE)
411
- ORDER BY "開始日" DESC
412
- LIMIT 1
413
- </select>
414
-
415
- <select id="findByCodeAndDate" resultMap="DepartmentResultMap">
416
- SELECT * FROM "部門マスタ"
417
- WHERE "部門コード" = #{departmentCode}
418
- AND "開始日" &lt;= #{baseDate}
419
- AND ("終了日" IS NULL OR "終了日" > #{baseDate})
420
- ORDER BY "開始日" DESC
421
- LIMIT 1
422
- </select>
423
-
424
- <delete id="deleteAll">
425
- TRUNCATE TABLE "部門マスタ" CASCADE
426
- </delete>
427
- </mapper>
428
- ```
429
-
430
- </details>
431
-
432
- ---
433
-
434
- ## 5.2 社員マスタの設計
435
-
436
- 部門に所属する社員を管理するマスタを設計します。
437
-
438
- ### 社員マスタの ER 図
439
-
440
- ```plantuml
441
- @startuml
442
-
443
- title 社員マスタ
444
-
445
- entity 社員マスタ {
446
- 社員コード <<PK>>
447
- --
448
- 社員名
449
- 社員名カナ
450
- 部門コード <<FK>>
451
- 開始日 <<FK>>
452
- 作成日時
453
- 作成者名
454
- 更新日時
455
- 更新者名
456
- }
457
-
458
- entity 部門マスタ {
459
- 部門コード <<PK>>
460
- 開始日 <<PK>>
461
- --
462
- ...
463
- }
464
-
465
- 社員マスタ }o--|| 部門マスタ
466
-
467
- @enduml
468
- ```
469
-
470
- ### マイグレーション:社員マスタテーブルの作成
471
-
472
- <details>
473
- <summary>SQL 実装</summary>
474
-
475
- ```sql
476
- -- src/main/resources/db/migration/V003__create_employee_master.sql
477
-
478
- -- 社員マスタ
479
- CREATE TABLE "社員マスタ" (
480
- "社員コード" VARCHAR(10) PRIMARY KEY,
481
- "社員名" VARCHAR(20) NOT NULL,
482
- "社員名カナ" VARCHAR(40),
483
- "部門コード" VARCHAR(10),
484
- "開始日" DATE,
485
- "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
486
- "作成者名" VARCHAR(50),
487
- "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
488
- "更新者名" VARCHAR(50),
489
- FOREIGN KEY ("部門コード", "開始日") REFERENCES "部門マスタ"("部門コード", "開始日")
490
- );
491
-
492
- CREATE INDEX idx_社員マスタ_部門コード ON "社員マスタ"("部門コード");
493
- ```
494
-
495
- </details>
496
-
497
- ### エンティティ(ドメイン層)
498
-
499
- <details>
500
- <summary>Employee.java</summary>
501
-
502
- ```java
503
- // src/main/java/com/example/sms/domain/model/employee/Employee.java
504
- package com.example.sms.domain.model.employee;
505
-
506
- import lombok.*;
507
- import java.time.LocalDate;
508
- import java.time.LocalDateTime;
509
-
510
- @Data
511
- @Builder
512
- @NoArgsConstructor
513
- @AllArgsConstructor
514
- public class Employee {
515
- private String employeeCode;
516
- private String employeeName;
517
- private String employeeNameKana;
518
- private String departmentCode;
519
- private LocalDate departmentStartDate;
520
- private LocalDateTime createdAt;
521
- private String createdBy;
522
- private LocalDateTime updatedAt;
523
- private String updatedBy;
524
- }
525
- ```
526
-
527
- </details>
528
-
529
- ---
530
-
531
- ## 5.3 商品マスタの設計
532
-
533
- 販売管理システムで扱う「商品」の情報を管理するマスタを設計します。
534
-
535
- ### 商品マスタの構造
536
-
537
- ```plantuml
538
- @startuml
539
- !define TABLE(x) entity x << (T,#FFAAAA) >>
540
-
541
- skinparam linetype ortho
542
- left to right direction
543
-
544
- TABLE(顧客別販売単価) {
545
- 商品コード (FK)
546
- 取引先コード (FK)
547
- --
548
- 販売単価
549
- 作成日時
550
- 作成者名
551
- 更新日時
552
- 更新者名
553
- }
554
-
555
- TABLE(商品マスタ) {
556
- 商品コード
557
- --
558
- 商品正式名
559
- 商品名
560
- 商品名カナ
561
- 商品区分
562
- 製品型番
563
- 販売単価
564
- 仕入単価
565
- 税区分
566
- 商品分類コード (FK)
567
- 雑区分
568
- 在庫管理対象区分
569
- 在庫引当区分
570
- 仕入先コード (FK)
571
- 作成日時
572
- 作成者名
573
- 更新日時
574
- 更新者名
575
- }
576
-
577
- TABLE(商品分類マスタ) {
578
- 商品分類コード
579
- --
580
- 商品分類名
581
- 商品分類階層
582
- 商品分類パス
583
- 最下層区分
584
- 作成日時
585
- 作成者名
586
- 更新日時
587
- 更新者名
588
- }
589
-
590
- 顧客別販売単価 }o--|| 商品マスタ
591
- 商品マスタ }o..|| 商品分類マスタ
592
-
593
- @enduml
594
- ```
595
-
596
- ### 商品区分と税区分
597
-
598
- 商品には「商品区分」と「税区分」という2つの区分があります。
599
-
600
- #### 商品区分
601
-
602
- | 区分値 | 説明 |
603
- |-------|------|
604
- | 商品 | 仕入れて販売する商品 |
605
- | 製品 | 自社で製造した製品 |
606
- | サービス | 無形のサービス |
607
- | 諸口 | その他の一時的な商品 |
608
-
609
- #### 税区分
610
-
611
- | 区分値 | 説明 |
612
- |-------|------|
613
- | 外税 | 税抜価格で管理し、別途消費税を計算 |
614
- | 内税 | 税込価格で管理 |
615
- | 非課税 | 消費税対象外 |
616
-
617
- ### マイグレーション:商品マスタテーブルの作成
618
-
619
- <details>
620
- <summary>SQL 実装</summary>
621
-
622
- ```sql
623
- -- src/main/resources/db/migration/V004__create_product_master.sql
624
-
625
- -- 商品区分 ENUM
626
- CREATE TYPE 商品区分 AS ENUM ('商品', '製品', 'サービス', '諸口');
627
-
628
- -- 税区分 ENUM
629
- CREATE TYPE 税区分 AS ENUM ('外税', '内税', '非課税');
630
-
631
- -- 商品分類マスタ
632
- CREATE TABLE "商品分類マスタ" (
633
- "商品分類コード" VARCHAR(10) PRIMARY KEY,
634
- "商品分類名" VARCHAR(50) NOT NULL,
635
- "商品分類階層" INTEGER NOT NULL DEFAULT 0,
636
- "商品分類パス" VARCHAR(100),
637
- "最下層区分" BOOLEAN NOT NULL DEFAULT FALSE,
638
- "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
639
- "作成者名" VARCHAR(50),
640
- "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
641
- "更新者名" VARCHAR(50)
642
- );
643
-
644
- -- 商品マスタ
645
- CREATE TABLE "商品マスタ" (
646
- "商品コード" VARCHAR(20) PRIMARY KEY,
647
- "商品正式名" VARCHAR(200),
648
- "商品名" VARCHAR(100) NOT NULL,
649
- "商品名カナ" VARCHAR(200),
650
- "商品区分" 商品区分 NOT NULL DEFAULT '商品',
651
- "製品型番" VARCHAR(50),
652
- "販売単価" DECIMAL(15, 2) DEFAULT 0,
653
- "仕入単価" DECIMAL(15, 2) DEFAULT 0,
654
- "税区分" 税区分 NOT NULL DEFAULT '外税',
655
- "商品分類コード" VARCHAR(10) REFERENCES "商品分類マスタ"("商品分類コード"),
656
- "雑区分" BOOLEAN DEFAULT FALSE,
657
- "在庫管理対象区分" BOOLEAN DEFAULT TRUE,
658
- "在庫引当区分" BOOLEAN DEFAULT TRUE,
659
- "仕入先コード" VARCHAR(20),
660
- "仕入先枝番" VARCHAR(10),
661
- "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
662
- "作成者名" VARCHAR(50),
663
- "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
664
- "更新者名" VARCHAR(50)
665
- );
666
-
667
- -- インデックス
668
- CREATE INDEX idx_商品マスタ_商品区分 ON "商品マスタ"("商品区分");
669
- CREATE INDEX idx_商品マスタ_商品分類コード ON "商品マスタ"("商品分類コード");
670
- CREATE INDEX idx_商品分類マスタ_商品分類パス ON "商品分類マスタ"("商品分類パス");
671
- ```
672
-
673
- </details>
674
-
675
- ### TDD:商品の登録と取得
676
-
677
- #### Red: 失敗するテストを書く
678
-
679
- <details>
680
- <summary>ProductRepositoryTest.java</summary>
681
-
682
- ```java
683
- // src/test/java/com/example/sms/infrastructure/persistence/repository/ProductRepositoryTest.java
684
- package com.example.sms.infrastructure.persistence.repository;
685
-
686
- import com.example.sms.application.port.out.ProductRepository;
687
- import com.example.sms.domain.model.product.Product;
688
- import com.example.sms.domain.model.product.ProductCategory;
689
- import com.example.sms.domain.model.product.TaxCategory;
690
- import com.example.sms.testsetup.BaseIntegrationTest;
691
- import org.junit.jupiter.api.*;
692
- import org.springframework.beans.factory.annotation.Autowired;
693
-
694
- import java.math.BigDecimal;
695
-
696
- import static org.assertj.core.api.Assertions.*;
697
-
698
- @DisplayName("商品リポジトリ")
699
- class ProductRepositoryTest extends BaseIntegrationTest {
700
-
701
- @Autowired
702
- private ProductRepository productRepository;
703
-
704
- @BeforeEach
705
- void setUp() {
706
- productRepository.deleteAll();
707
- }
708
-
709
- @Nested
710
- @DisplayName("登録")
711
- class Registration {
712
-
713
- @Test
714
- @DisplayName("商品を登録できる")
715
- void canRegisterProduct() {
716
- // Arrange
717
- var product = Product.builder()
718
- .productCode("PROD001")
719
- .productName("テスト商品")
720
- .productCategory(ProductCategory.PRODUCT)
721
- .sellingPrice(new BigDecimal("1000"))
722
- .purchasePrice(new BigDecimal("700"))
723
- .taxCategory(TaxCategory.EXCLUSIVE)
724
- .build();
725
-
726
- // Act
727
- productRepository.save(product);
728
-
729
- // Assert
730
- var result = productRepository.findByCode("PROD001");
731
- assertThat(result).isPresent();
732
- assertThat(result.get().getProductName()).isEqualTo("テスト商品");
733
- assertThat(result.get().getSellingPrice()).isEqualByComparingTo(new BigDecimal("1000"));
734
- }
735
-
736
- @Test
737
- @DisplayName("全ての商品区分を登録できる")
738
- void canRegisterAllCategories() {
739
- var categories = ProductCategory.values();
740
-
741
- for (int i = 0; i < categories.length; i++) {
742
- var product = Product.builder()
743
- .productCode("CAT-" + String.format("%03d", i))
744
- .productName("商品" + categories[i].getDisplayName())
745
- .productCategory(categories[i])
746
- .taxCategory(TaxCategory.EXCLUSIVE)
747
- .build();
748
-
749
- productRepository.save(product);
750
-
751
- var result = productRepository.findByCode(product.getProductCode());
752
- assertThat(result).isPresent();
753
- assertThat(result.get().getProductCategory()).isEqualTo(categories[i]);
754
- }
755
- }
756
- }
757
-
758
- @Nested
759
- @DisplayName("税区分")
760
- class TaxCategories {
761
-
762
- @Test
763
- @DisplayName("外税商品を登録できる")
764
- void canRegisterExclusiveTax() {
765
- var product = createProduct("TAX001", "外税商品", TaxCategory.EXCLUSIVE);
766
- productRepository.save(product);
767
-
768
- var result = productRepository.findByCode("TAX001");
769
- assertThat(result.get().getTaxCategory()).isEqualTo(TaxCategory.EXCLUSIVE);
770
- }
771
-
772
- @Test
773
- @DisplayName("内税商品を登録できる")
774
- void canRegisterInclusiveTax() {
775
- var product = createProduct("TAX002", "内税商品", TaxCategory.INCLUSIVE);
776
- productRepository.save(product);
777
-
778
- var result = productRepository.findByCode("TAX002");
779
- assertThat(result.get().getTaxCategory()).isEqualTo(TaxCategory.INCLUSIVE);
780
- }
781
-
782
- @Test
783
- @DisplayName("非課税商品を登録できる")
784
- void canRegisterTaxFree() {
785
- var product = createProduct("TAX003", "非課税商品", TaxCategory.TAX_FREE);
786
- productRepository.save(product);
787
-
788
- var result = productRepository.findByCode("TAX003");
789
- assertThat(result.get().getTaxCategory()).isEqualTo(TaxCategory.TAX_FREE);
790
- }
791
- }
792
-
793
- private Product createProduct(String code, String name, TaxCategory taxCategory) {
794
- return Product.builder()
795
- .productCode(code)
796
- .productName(name)
797
- .productCategory(ProductCategory.PRODUCT)
798
- .taxCategory(taxCategory)
799
- .build();
800
- }
801
- }
802
- ```
803
-
804
- </details>
805
-
806
- #### Green: テストを通す実装
807
-
808
- <details>
809
- <summary>Product.java(エンティティ)</summary>
810
-
811
- ```java
812
- // src/main/java/com/example/sms/domain/model/product/Product.java
813
- package com.example.sms.domain.model.product;
814
-
815
- import lombok.*;
816
- import java.math.BigDecimal;
817
- import java.time.LocalDateTime;
818
-
819
- @Data
820
- @Builder
821
- @NoArgsConstructor
822
- @AllArgsConstructor
823
- public class Product {
824
- private String productCode;
825
- private String productFullName;
826
- private String productName;
827
- private String productNameKana;
828
- private ProductCategory productCategory;
829
- private String modelNumber;
830
- @Builder.Default
831
- private BigDecimal sellingPrice = BigDecimal.ZERO;
832
- @Builder.Default
833
- private BigDecimal purchasePrice = BigDecimal.ZERO;
834
- private TaxCategory taxCategory;
835
- private String classificationCode;
836
- @Builder.Default
837
- private boolean isMiscellaneous = false;
838
- @Builder.Default
839
- private boolean isInventoryManaged = true;
840
- @Builder.Default
841
- private boolean isInventoryAllocated = true;
842
- private String supplierCode;
843
- private String supplierBranchNumber;
844
- private LocalDateTime createdAt;
845
- private String createdBy;
846
- private LocalDateTime updatedAt;
847
- private String updatedBy;
848
- }
849
- ```
850
-
851
- </details>
852
-
853
- <details>
854
- <summary>ProductCategory.java(商品区分 Enum)</summary>
855
-
856
- ```java
857
- // src/main/java/com/example/sms/domain/model/product/ProductCategory.java
858
- package com.example.sms.domain.model.product;
859
-
860
- import lombok.Getter;
861
- import lombok.RequiredArgsConstructor;
862
-
863
- @Getter
864
- @RequiredArgsConstructor
865
- public enum ProductCategory {
866
- PRODUCT("商品"),
867
- MANUFACTURED("製品"),
868
- SERVICE("サービス"),
869
- MISCELLANEOUS("諸口");
870
-
871
- private final String displayName;
872
-
873
- public static ProductCategory fromDisplayName(String displayName) {
874
- for (ProductCategory category : values()) {
875
- if (category.displayName.equals(displayName)) {
876
- return category;
877
- }
878
- }
879
- throw new IllegalArgumentException("不正な商品区分: " + displayName);
880
- }
881
- }
882
- ```
883
-
884
- </details>
885
-
886
- <details>
887
- <summary>TaxCategory.java(税区分 Enum)</summary>
888
-
889
- ```java
890
- // src/main/java/com/example/sms/domain/model/product/TaxCategory.java
891
- package com.example.sms.domain.model.product;
892
-
893
- import lombok.Getter;
894
- import lombok.RequiredArgsConstructor;
895
-
896
- @Getter
897
- @RequiredArgsConstructor
898
- public enum TaxCategory {
899
- EXCLUSIVE("外税"),
900
- INCLUSIVE("内税"),
901
- TAX_FREE("非課税");
902
-
903
- private final String displayName;
904
-
905
- public static TaxCategory fromDisplayName(String displayName) {
906
- for (TaxCategory category : values()) {
907
- if (category.displayName.equals(displayName)) {
908
- return category;
909
- }
910
- }
911
- throw new IllegalArgumentException("不正な税区分: " + displayName);
912
- }
913
- }
914
- ```
915
-
916
- </details>
917
-
918
- ### 顧客別販売単価の設計
919
-
920
- 特定の顧客に対して、標準単価とは異なる販売単価を設定できる仕組みです。
921
-
922
- <details>
923
- <summary>SQL 実装</summary>
924
-
925
- ```sql
926
- -- src/main/resources/db/migration/V005__create_customer_price.sql
927
-
928
- -- 顧客別販売単価
929
- CREATE TABLE "顧客別販売単価" (
930
- "商品コード" VARCHAR(20) NOT NULL REFERENCES "商品マスタ"("商品コード"),
931
- "取引先コード" VARCHAR(20) NOT NULL,
932
- "適用開始日" DATE NOT NULL,
933
- "適用終了日" DATE,
934
- "販売単価" DECIMAL(15, 2) NOT NULL,
935
- "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
936
- "作成者名" VARCHAR(50),
937
- "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
938
- "更新者名" VARCHAR(50),
939
- PRIMARY KEY ("商品コード", "取引先コード", "適用開始日")
940
- );
941
- ```
942
-
943
- </details>
944
-
945
- ---
946
-
947
- ## 5.4 原価管理の設計
948
-
949
- 商品の原価を計算する方法には8種類あります。
950
-
951
- ### 8種類の原価法
952
-
953
- | 原価法 | 説明 |
954
- |-------|------|
955
- | **個別原価法** | 個々の商品ごとに原価を管理 |
956
- | **先入先出法** | 最も古い在庫から順に払い出す |
957
- | **後入先出法** | 最も新しい在庫から順に払い出す |
958
- | **総平均法** | 期間全体の平均原価を使用 |
959
- | **移動平均法** | 仕入れのたびに平均原価を再計算 |
960
- | **単純平均法** | 単純に平均値を使用 |
961
- | **最終仕入原価法** | 最後に仕入れた原価を使用 |
962
- | **売価還元法** | 売価から逆算して原価を算出 |
963
-
964
- ### 原価法の選択基準
965
-
966
- ```plantuml
967
- @startuml
968
-
969
- title 原価法の選択フロー
970
-
971
- start
972
-
973
- if (商品の個別管理が必要?) then (yes)
974
- :個別原価法;
975
- stop
976
- else (no)
977
- endif
978
-
979
- if (期中の原価変動が大きい?) then (yes)
980
- if (リアルタイム管理が必要?) then (yes)
981
- :移動平均法;
982
- else (no)
983
- :総平均法;
984
- endif
985
- stop
986
- else (no)
987
- endif
988
-
989
- if (簡便な管理でよい?) then (yes)
990
- :最終仕入原価法;
991
- stop
992
- else (no)
993
- :先入先出法;
994
- stop
995
- endif
996
-
997
- @enduml
998
- ```
999
-
1000
- 本システムでは**移動平均法**を採用し、仕入れのたびに平均原価を再計算します。
1001
-
1002
- ---
1003
-
1004
- ## 5.5 消費税の設計
1005
-
1006
- ### 税区分の考え方
1007
-
1008
- | 税区分 | 説明 | 計算方法 |
1009
- |-------|------|---------|
1010
- | **外税** | 税抜価格で管理 | 価格 × 税率 = 消費税額 |
1011
- | **内税** | 税込価格で管理 | 価格 × 税率 ÷ (1 + 税率) = 消費税額 |
1012
- | **非課税** | 消費税対象外 | 消費税額 = 0 |
1013
-
1014
- ### 消費税計算の実装
1015
-
1016
- <details>
1017
- <summary>TaxCalculator.java</summary>
1018
-
1019
- ```java
1020
- // src/main/java/com/example/sms/domain/type/TaxCalculator.java
1021
- package com.example.sms.domain.type;
1022
-
1023
- import com.example.sms.domain.model.product.TaxCategory;
1024
- import lombok.RequiredArgsConstructor;
1025
- import java.math.BigDecimal;
1026
- import java.math.RoundingMode;
1027
-
1028
- @RequiredArgsConstructor
1029
- public class TaxCalculator {
1030
-
1031
- private final BigDecimal taxRate;
1032
-
1033
- /**
1034
- * 消費税額を計算する
1035
- */
1036
- public BigDecimal calculateTax(BigDecimal price, TaxCategory taxCategory) {
1037
- return switch (taxCategory) {
1038
- case EXCLUSIVE -> price.multiply(taxRate)
1039
- .setScale(0, RoundingMode.DOWN);
1040
- case INCLUSIVE -> price.multiply(taxRate)
1041
- .divide(BigDecimal.ONE.add(taxRate), 0, RoundingMode.DOWN);
1042
- case TAX_FREE -> BigDecimal.ZERO;
1043
- };
1044
- }
1045
-
1046
- /**
1047
- * 税込金額を計算する
1048
- */
1049
- public BigDecimal calculateTaxIncludedPrice(BigDecimal price, TaxCategory taxCategory) {
1050
- return switch (taxCategory) {
1051
- case EXCLUSIVE -> price.add(calculateTax(price, taxCategory));
1052
- case INCLUSIVE -> price;
1053
- case TAX_FREE -> price;
1054
- };
1055
- }
1056
- }
1057
- ```
1058
-
1059
- </details>
1060
-
1061
- ---
1062
-
1063
- ## 5.6 顧客マスタの設計
1064
-
1065
- 顧客と仕入先を統合管理する取引先マスタを設計します。
1066
-
1067
- ### 取引先マスタの構造
1068
-
1069
- ```plantuml
1070
- @startuml
1071
- left to right direction
1072
-
1073
- entity 取引先マスタ {
1074
- 取引先コード <<PK>>
1075
- --
1076
- 取引先名
1077
- 取引先カナ
1078
- 顧客区分
1079
- 仕入先区分
1080
- 郵便番号
1081
- 住所1
1082
- 住所2
1083
- 取引先分類コード
1084
- 取引禁止フラグ
1085
- 雑区分
1086
- 取引先グループコード
1087
- 与信限度額
1088
- 与信一時増加枠
1089
- 更新日時
1090
- 更新者名
1091
- }
1092
-
1093
- entity 顧客マスタ {
1094
- 顧客コード(FK) <<PK>>
1095
- 顧客枝番 <<PK>>
1096
- --
1097
- 顧客区分
1098
- 請求先コード
1099
- 請求先枝番
1100
- 回収先コード
1101
- 回収先枝番
1102
- 顧客名
1103
- 顧客名カナ
1104
- 自社担当者コード
1105
- 顧客担当者名
1106
- 顧客請求区分
1107
- 顧客締日1
1108
- 顧客支払月1
1109
- 顧客支払日1
1110
- 顧客支払方法1
1111
- ...
1112
- }
1113
-
1114
- entity 仕入先マスタ {
1115
- 仕入先コード(FK) <<PK>>
1116
- 仕入先枝番 <<PK>>
1117
- --
1118
- 仕入先担当者名
1119
- 部門名
1120
- 電話番号
1121
- FAX番号
1122
- メールアドレス
1123
- ...
1124
- }
1125
-
1126
- entity 出荷先マスタ {
1127
- 取引先コード(FK)
1128
- 顧客枝番(FK)
1129
- 出荷先番号 <<PK>>
1130
- --
1131
- 出荷先名
1132
- 地域コード
1133
- 出荷先郵便番号
1134
- 出荷先住所1
1135
- 出荷先住所2
1136
- ...
1137
- }
1138
-
1139
- 取引先マスタ ||--o| 顧客マスタ
1140
- 取引先マスタ ||--o| 仕入先マスタ
1141
- 顧客マスタ ||--o{ 出荷先マスタ
1142
-
1143
- @enduml
1144
- ```
1145
-
1146
- ### 請求先・回収先の概念
1147
-
1148
- 顧客マスタでは、実際に商品を購入する顧客と、請求書を送付する先(請求先)、代金を回収する先(回収先)を分けて管理できます。
1149
-
1150
- ```plantuml
1151
- @startuml
1152
-
1153
- title 請求先・回収先の関係
1154
-
1155
- actor "購入者\n(A支店)" as buyer
1156
- actor "請求先\n(本社経理部)" as billing
1157
- actor "回収先\n(本社財務部)" as collection
1158
-
1159
- buyer -right-> billing : 請求書送付先
1160
- billing -right-> collection : 代金支払元
1161
-
1162
- note bottom of buyer
1163
- 顧客コード: C001
1164
- 顧客枝番: 01
1165
- 請求先コード: C001
1166
- 請求先枝番: 00
1167
- end note
1168
-
1169
- note bottom of billing
1170
- 顧客コード: C001
1171
- 顧客枝番: 00
1172
- (本社)
1173
- end note
1174
-
1175
- @enduml
1176
- ```
1177
-
1178
- ### マイグレーション:取引先関連テーブルの作成
1179
-
1180
- <details>
1181
- <summary>SQL 実装</summary>
1182
-
1183
- ```sql
1184
- -- src/main/resources/db/migration/V006__create_partner_master.sql
1185
-
1186
- -- 請求区分 ENUM
1187
- CREATE TYPE 請求区分 AS ENUM ('都度', '締め');
1188
-
1189
- -- 支払方法 ENUM
1190
- CREATE TYPE 支払方法 AS ENUM ('現金', '振込', '手形', '小切手', 'その他');
1191
-
1192
- -- 取引先グループマスタ
1193
- CREATE TABLE "取引先グループマスタ" (
1194
- "取引先グループコード" VARCHAR(10) PRIMARY KEY,
1195
- "取引先グループ名" VARCHAR(50) NOT NULL,
1196
- "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1197
- "作成者名" VARCHAR(50),
1198
- "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1199
- "更新者名" VARCHAR(50)
1200
- );
1201
-
1202
- -- 取引先マスタ
1203
- CREATE TABLE "取引先マスタ" (
1204
- "取引先コード" VARCHAR(20) PRIMARY KEY,
1205
- "取引先名" VARCHAR(100) NOT NULL,
1206
- "取引先カナ" VARCHAR(200),
1207
- "顧客区分" BOOLEAN DEFAULT FALSE,
1208
- "仕入先区分" BOOLEAN DEFAULT FALSE,
1209
- "郵便番号" VARCHAR(10),
1210
- "住所1" VARCHAR(100),
1211
- "住所2" VARCHAR(100),
1212
- "取引先分類コード" VARCHAR(10),
1213
- "取引禁止フラグ" BOOLEAN DEFAULT FALSE,
1214
- "雑区分" BOOLEAN DEFAULT FALSE,
1215
- "取引先グループコード" VARCHAR(10) REFERENCES "取引先グループマスタ"("取引先グループコード"),
1216
- "与信限度額" DECIMAL(15, 2) DEFAULT 0,
1217
- "与信一時増加枠" DECIMAL(15, 2) DEFAULT 0,
1218
- "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1219
- "作成者名" VARCHAR(50),
1220
- "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1221
- "更新者名" VARCHAR(50)
1222
- );
1223
-
1224
- -- 顧客マスタ
1225
- CREATE TABLE "顧客マスタ" (
1226
- "顧客コード" VARCHAR(20) NOT NULL REFERENCES "取引先マスタ"("取引先コード"),
1227
- "顧客枝番" VARCHAR(10) NOT NULL DEFAULT '00',
1228
- "顧客区分" VARCHAR(10),
1229
- "請求先コード" VARCHAR(20),
1230
- "請求先枝番" VARCHAR(10),
1231
- "回収先コード" VARCHAR(20),
1232
- "回収先枝番" VARCHAR(10),
1233
- "顧客名" VARCHAR(100),
1234
- "顧客名カナ" VARCHAR(200),
1235
- "自社担当者コード" VARCHAR(10),
1236
- "顧客担当者名" VARCHAR(50),
1237
- "顧客部門名" VARCHAR(50),
1238
- "顧客郵便番号" VARCHAR(10),
1239
- "顧客都道府県" VARCHAR(10),
1240
- "顧客住所1" VARCHAR(100),
1241
- "顧客住所2" VARCHAR(100),
1242
- "顧客電話番号" VARCHAR(20),
1243
- "顧客FAX番号" VARCHAR(20),
1244
- "顧客メールアドレス" VARCHAR(100),
1245
- "顧客請求区分" 請求区分 DEFAULT '締め',
1246
- "顧客締日1" INTEGER,
1247
- "顧客支払月1" INTEGER,
1248
- "顧客支払日1" INTEGER,
1249
- "顧客支払方法1" 支払方法,
1250
- "顧客締日2" INTEGER,
1251
- "顧客支払月2" INTEGER,
1252
- "顧客支払日2" INTEGER,
1253
- "顧客支払方法2" 支払方法,
1254
- "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1255
- "作成者名" VARCHAR(50),
1256
- "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1257
- "更新者名" VARCHAR(50),
1258
- PRIMARY KEY ("顧客コード", "顧客枝番")
1259
- );
1260
-
1261
- -- 仕入先マスタ
1262
- CREATE TABLE "仕入先マスタ" (
1263
- "仕入先コード" VARCHAR(20) NOT NULL REFERENCES "取引先マスタ"("取引先コード"),
1264
- "仕入先枝番" VARCHAR(10) NOT NULL DEFAULT '00',
1265
- "仕入先担当者名" VARCHAR(50),
1266
- "部門名" VARCHAR(50),
1267
- "電話番号" VARCHAR(20),
1268
- "FAX番号" VARCHAR(20),
1269
- "メールアドレス" VARCHAR(100),
1270
- "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1271
- "作成者名" VARCHAR(50),
1272
- "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1273
- "更新者名" VARCHAR(50),
1274
- PRIMARY KEY ("仕入先コード", "仕入先枝番")
1275
- );
1276
-
1277
- -- 地域マスタ
1278
- CREATE TABLE "地域マスタ" (
1279
- "地域コード" VARCHAR(10) PRIMARY KEY,
1280
- "地域名" VARCHAR(50) NOT NULL,
1281
- "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1282
- "作成者名" VARCHAR(50),
1283
- "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1284
- "更新者名" VARCHAR(50)
1285
- );
1286
-
1287
- -- 出荷先マスタ
1288
- CREATE TABLE "出荷先マスタ" (
1289
- "取引先コード" VARCHAR(20) NOT NULL,
1290
- "顧客枝番" VARCHAR(10) NOT NULL,
1291
- "出荷先番号" VARCHAR(10) NOT NULL,
1292
- "出荷先名" VARCHAR(100) NOT NULL,
1293
- "地域コード" VARCHAR(10) REFERENCES "地域マスタ"("地域コード"),
1294
- "出荷先郵便番号" VARCHAR(10),
1295
- "出荷先住所1" VARCHAR(100),
1296
- "出荷先住所2" VARCHAR(100),
1297
- "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1298
- "作成者名" VARCHAR(50),
1299
- "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1300
- "更新者名" VARCHAR(50),
1301
- PRIMARY KEY ("取引先コード", "顧客枝番", "出荷先番号"),
1302
- FOREIGN KEY ("取引先コード", "顧客枝番") REFERENCES "顧客マスタ"("顧客コード", "顧客枝番")
1303
- );
1304
-
1305
- -- インデックス
1306
- CREATE INDEX idx_取引先マスタ_取引先グループ ON "取引先マスタ"("取引先グループコード");
1307
- CREATE INDEX idx_顧客マスタ_請求先 ON "顧客マスタ"("請求先コード", "請求先枝番");
1308
- ```
1309
-
1310
- </details>
1311
-
1312
- ### エンティティ(ドメイン層)
1313
-
1314
- <details>
1315
- <summary>Partner.java</summary>
1316
-
1317
- ```java
1318
- // src/main/java/com/example/sms/domain/model/partner/Partner.java
1319
- package com.example.sms.domain.model.partner;
1320
-
1321
- import lombok.*;
1322
- import java.math.BigDecimal;
1323
- import java.time.LocalDateTime;
1324
-
1325
- @Data
1326
- @Builder
1327
- @NoArgsConstructor
1328
- @AllArgsConstructor
1329
- public class Partner {
1330
- private String partnerCode;
1331
- private String partnerName;
1332
- private String partnerNameKana;
1333
- @Builder.Default
1334
- private boolean isCustomer = false;
1335
- @Builder.Default
1336
- private boolean isSupplier = false;
1337
- private String postalCode;
1338
- private String address1;
1339
- private String address2;
1340
- private String classificationCode;
1341
- @Builder.Default
1342
- private boolean isTradingProhibited = false;
1343
- @Builder.Default
1344
- private boolean isMiscellaneous = false;
1345
- private String groupCode;
1346
- @Builder.Default
1347
- private BigDecimal creditLimit = BigDecimal.ZERO;
1348
- @Builder.Default
1349
- private BigDecimal temporaryCreditIncrease = BigDecimal.ZERO;
1350
- private LocalDateTime createdAt;
1351
- private String createdBy;
1352
- private LocalDateTime updatedAt;
1353
- private String updatedBy;
1354
- }
1355
- ```
1356
-
1357
- </details>
1358
-
1359
- ---
1360
-
1361
- ## 5.7 取引条件の設計
1362
-
1363
- 顧客との取引条件(締日・支払日など)を管理します。
1364
-
1365
- ### 締日・支払月・支払日の管理
1366
-
1367
- | 項目 | 説明 | 例 |
1368
- |-----|------|-----|
1369
- | **締日** | 請求の締め日 | 20日、末日 |
1370
- | **支払月** | 締め月から何ヶ月後か | 0(当月)、1(翌月) |
1371
- | **支払日** | 支払日 | 10日、25日、末日 |
1372
-
1373
- ### 都度請求と締め請求
1374
-
1375
- | 請求区分 | 説明 |
1376
- |---------|------|
1377
- | **都度請求** | 取引のたびに請求書を発行 |
1378
- | **締め請求** | 締日でまとめて請求書を発行 |
1379
-
1380
- ### 与信管理
1381
-
1382
- ```plantuml
1383
- @startuml
1384
-
1385
- title 与信チェックフロー
1386
-
1387
- start
1388
-
1389
- :受注登録;
1390
-
1391
- :売掛残高を取得;
1392
- :受注済残高を取得;
1393
- :今回受注金額を加算;
1394
-
1395
- :与信限度額を取得;
1396
- :一時増加枠を取得;
1397
-
1398
- if (売掛残高 + 受注済残高 + 今回受注 > 与信限度額 + 一時増加枠) then (yes)
1399
- :与信オーバー警告;
1400
- if (強制登録?) then (yes)
1401
- :受注登録(警告付き);
1402
- else (no)
1403
- :受注キャンセル;
1404
- stop
1405
- endif
1406
- else (no)
1407
- endif
1408
-
1409
- :受注確定;
1410
-
1411
- stop
1412
-
1413
- @enduml
1414
- ```
1415
-
1416
- ### 請求区分・支払方法の Enum
1417
-
1418
- <details>
1419
- <summary>BillingType.java</summary>
1420
-
1421
- ```java
1422
- // src/main/java/com/example/sms/domain/model/partner/BillingType.java
1423
- package com.example.sms.domain.model.partner;
1424
-
1425
- import lombok.Getter;
1426
- import lombok.RequiredArgsConstructor;
1427
-
1428
- @Getter
1429
- @RequiredArgsConstructor
1430
- public enum BillingType {
1431
- ON_DEMAND("都度"),
1432
- PERIODIC("締め");
1433
-
1434
- private final String displayName;
1435
-
1436
- public static BillingType fromDisplayName(String displayName) {
1437
- for (BillingType type : values()) {
1438
- if (type.displayName.equals(displayName)) {
1439
- return type;
1440
- }
1441
- }
1442
- throw new IllegalArgumentException("不正な請求区分: " + displayName);
1443
- }
1444
- }
1445
- ```
1446
-
1447
- </details>
1448
-
1449
- <details>
1450
- <summary>PaymentMethod.java</summary>
1451
-
1452
- ```java
1453
- // src/main/java/com/example/sms/domain/model/partner/PaymentMethod.java
1454
- package com.example.sms.domain.model.partner;
1455
-
1456
- import lombok.Getter;
1457
- import lombok.RequiredArgsConstructor;
1458
-
1459
- @Getter
1460
- @RequiredArgsConstructor
1461
- public enum PaymentMethod {
1462
- CASH("現金"),
1463
- TRANSFER("振込"),
1464
- BILL("手形"),
1465
- CHECK("小切手"),
1466
- OTHER("その他");
1467
-
1468
- private final String displayName;
1469
-
1470
- public static PaymentMethod fromDisplayName(String displayName) {
1471
- for (PaymentMethod method : values()) {
1472
- if (method.displayName.equals(displayName)) {
1473
- return method;
1474
- }
1475
- }
1476
- throw new IllegalArgumentException("不正な支払方法: " + displayName);
1477
- }
1478
- }
1479
- ```
1480
-
1481
- </details>
1482
-
1483
- ---
1484
-
1485
- ## 第5章のまとめ
1486
-
1487
- ### 作成したテーブル
1488
-
1489
- | テーブル名 | 説明 |
1490
- |-----------|------|
1491
- | `部門マスタ` | 組織階層を管理する部門情報 |
1492
- | `社員マスタ` | 部門に所属する社員情報 |
1493
- | `商品分類マスタ` | 商品の分類階層 |
1494
- | `商品マスタ` | 販売商品の情報 |
1495
- | `顧客別販売単価` | 顧客ごとの特別単価 |
1496
- | `取引先グループマスタ` | 取引先のグループ |
1497
- | `取引先マスタ` | 顧客・仕入先の統合情報 |
1498
- | `顧客マスタ` | 顧客固有情報 |
1499
- | `仕入先マスタ` | 仕入先固有情報 |
1500
- | `地域マスタ` | 地域情報 |
1501
- | `出荷先マスタ` | 顧客の出荷先情報 |
1502
-
1503
- ### ER 図(第5章完了時点)
1504
-
1505
- ```plantuml
1506
- @startuml
1507
-
1508
- title マスタ情報 ER図
1509
-
1510
- entity 部門マスタ {
1511
- 部門コード <<PK>>
1512
- 開始日 <<PK>>
1513
- --
1514
- 終了日
1515
- 部門名
1516
- 組織階層
1517
- 部門パス
1518
- 最下層区分
1519
- }
1520
-
1521
- entity 社員マスタ {
1522
- 社員コード <<PK>>
1523
- --
1524
- 社員名
1525
- 社員名カナ
1526
- 部門コード <<FK>>
1527
- 開始日 <<FK>>
1528
- }
1529
-
1530
- entity 商品分類マスタ {
1531
- 商品分類コード <<PK>>
1532
- --
1533
- 商品分類名
1534
- 商品分類階層
1535
- 商品分類パス
1536
- 最下層区分
1537
- }
1538
-
1539
- entity 商品マスタ {
1540
- 商品コード <<PK>>
1541
- --
1542
- 商品正式名
1543
- 商品名
1544
- 商品名カナ
1545
- 商品区分
1546
- 販売単価
1547
- 仕入単価
1548
- 税区分
1549
- 商品分類コード <<FK>>
1550
- ...
1551
- }
1552
-
1553
- entity 顧客別販売単価 {
1554
- 商品コード <<PK,FK>>
1555
- 取引先コード <<PK>>
1556
- 適用開始日 <<PK>>
1557
- --
1558
- 適用終了日
1559
- 販売単価
1560
- }
1561
-
1562
- entity 取引先マスタ {
1563
- 取引先コード <<PK>>
1564
- --
1565
- 取引先名
1566
- 顧客区分
1567
- 仕入先区分
1568
- 与信限度額
1569
- ...
1570
- }
1571
-
1572
- entity 顧客マスタ {
1573
- 顧客コード <<PK,FK>>
1574
- 顧客枝番 <<PK>>
1575
- --
1576
- 請求先コード
1577
- 顧客請求区分
1578
- 顧客締日1
1579
- ...
1580
- }
1581
-
1582
- entity 仕入先マスタ {
1583
- 仕入先コード <<PK,FK>>
1584
- 仕入先枝番 <<PK>>
1585
- --
1586
- 仕入先担当者名
1587
- ...
1588
- }
1589
-
1590
- entity 出荷先マスタ {
1591
- 取引先コード <<PK,FK>>
1592
- 顧客枝番 <<PK,FK>>
1593
- 出荷先番号 <<PK>>
1594
- --
1595
- 出荷先名
1596
- 地域コード <<FK>>
1597
- ...
1598
- }
1599
-
1600
- 部門マスタ ||--o{ 社員マスタ
1601
- 商品分類マスタ ||--o{ 商品マスタ
1602
- 商品マスタ ||--o{ 顧客別販売単価
1603
- 取引先マスタ ||--o| 顧客マスタ
1604
- 取引先マスタ ||--o| 仕入先マスタ
1605
- 顧客マスタ ||--o{ 出荷先マスタ
1606
-
1607
- @enduml
1608
- ```
1609
-
1610
- ### 設計のポイント
1611
-
1612
- 1. **組織階層管理**: 部門マスタは `部門パス` で階層構造を表現
1613
- 2. **履歴管理**: 部門マスタは `開始日` による世代管理を採用
1614
- 3. **統合マスタ**: 取引先マスタで顧客・仕入先を統合管理
1615
- 4. **日本語 DB / 英語 Java**: テーブル・カラムは日本語、Java コードは英語で統一
1616
- 5. **PostgreSQL ENUM**: 区分値は日本語 ENUM 型で型安全性を確保
1617
- 6. **与信管理**: 与信限度額と一時増加枠で柔軟な与信管理を実現
1618
-
1619
- ---
1620
-
1621
- ## 次章の予告
1622
-
1623
- 第6章では、受注・出荷・売上の設計に進みます。販売管理の中核となる業務フローを TDD で実装していきます。
1624
-
1625
- ---
1626
-
1627
- [← 第4章:販売管理システムのアーキテクチャ](./chapter04.md) | [第6章:受注・出荷・売上の設計 →](./chapter06.md)
1
+ # 第5章:マスタ情報の設計
2
+
3
+ 販売管理システムの基盤となるマスタ情報を TDD で設計していきます。本章では、組織・社員・商品・取引先といった基本的なマスタテーブルの設計と実装を行います。
4
+
5
+ ## 5.1 部門マスタの設計
6
+
7
+ 企業の組織構造を管理する部門マスタを設計します。
8
+
9
+ ### 組織階層の概念
10
+
11
+ 企業の組織は階層構造を持っています。部門マスタでは、この階層構造を「部門パス」で表現します。
12
+
13
+ ```plantuml
14
+ @startwbs
15
+
16
+ * 全社 : 10000
17
+ ** 営業本部 : 11000
18
+ *** 東日本営業部 : 11100
19
+ **** 営業1課 : 11101
20
+ **** 営業2課 : 11102
21
+ *** 西日本営業部 : 11200
22
+ **** 営業3課 : 11201
23
+ **** 営業4課 : 11202
24
+ ** 管理本部 : 12000
25
+ *** 総務部 : 12100
26
+ **** 庶務課 : 12101
27
+ **** 人事課 : 12102
28
+ *** 経理部 : 12200
29
+ **** 経理課 : 12201
30
+ **** 財務課 : 12202
31
+
32
+ @endwbs
33
+ ```
34
+
35
+ ### 部門マスタの ER 図
36
+
37
+ ```plantuml
38
+ @startuml
39
+
40
+ title 部門マスタ
41
+
42
+ entity 部門マスタ {
43
+ 部門コード <<PK>>
44
+ 開始日 <<PK>>
45
+ --
46
+ 終了日
47
+ 部門名
48
+ 組織階層
49
+ 部門パス
50
+ 最下層区分
51
+ 作成日時
52
+ 作成者名
53
+ 更新日時
54
+ 更新者名
55
+ }
56
+
57
+ note right of 部門マスタ
58
+ 部門パスの例:
59
+ 10000~11000~11100
60
+ (チルダで連結)
61
+ end note
62
+
63
+ @enduml
64
+ ```
65
+
66
+ ### 部門マスタの項目説明
67
+
68
+ | 項目 | 説明 | 例 |
69
+ |-----|------|-----|
70
+ | **部門コード** | 部門を一意に識別するコード | `11101` |
71
+ | **開始日** | 部門の有効期間開始日 | `2025-01-01` |
72
+ | **終了日** | 部門の有効期間終了日 | `null`(有効) |
73
+ | **部門名** | 部門の名称 | `営業1課` |
74
+ | **組織階層** | 階層の深さ(0から開始) | `3` |
75
+ | **部門パス** | ルートからのパス(チルダ連結) | `10000~11000~11100~11101` |
76
+ | **最下層区分** | 最下層(末端)かどうか | `true` |
77
+
78
+ ### 組織改正への対応(履歴管理)
79
+
80
+ 組織改正が発生した場合、同じ部門コードでも開始日が異なるレコードを登録することで、組織の変遷を管理できます。
81
+
82
+ ```plantuml
83
+ @startuml
84
+
85
+ title 組織改正の履歴管理
86
+
87
+ entity "部門マスタ(2024年度)" as dept2024 {
88
+ 部門コード: 11000
89
+ 開始日: 2024-01-01
90
+ 終了日: 2024-12-31
91
+ --
92
+ 部門名: 営業部
93
+ 組織階層: 1
94
+ 部門パス: 10000~11000
95
+ }
96
+
97
+ entity "部門マスタ(2025年度)" as dept2025 {
98
+ 部門コード: 11000
99
+ 開始日: 2025-01-01
100
+ 終了日: null
101
+ --
102
+ 部門名: 営業本部
103
+ 組織階層: 1
104
+ 部門パス: 10000~11000
105
+ }
106
+
107
+ dept2024 -[hidden]- dept2025
108
+
109
+ note bottom of dept2025
110
+ 同じ部門コードでも
111
+ 開始日が異なれば
112
+ 別レコードとして登録可能
113
+ end note
114
+
115
+ @enduml
116
+ ```
117
+
118
+ ### マイグレーション:部門マスタテーブルの作成
119
+
120
+ <details>
121
+ <summary>SQL 実装</summary>
122
+
123
+ ```sql
124
+ -- src/main/resources/db/migration/V002__create_department_master.sql
125
+
126
+ -- 部門マスタ(日本語テーブル名・カラム名)
127
+ CREATE TABLE "部門マスタ" (
128
+ "部門コード" VARCHAR(10) NOT NULL,
129
+ "開始日" DATE NOT NULL,
130
+ "終了日" DATE,
131
+ "部門名" VARCHAR(40) NOT NULL,
132
+ "組織階層" INTEGER NOT NULL DEFAULT 0,
133
+ "部門パス" VARCHAR(100),
134
+ "最下層区分" BOOLEAN NOT NULL DEFAULT FALSE,
135
+ "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
136
+ "作成者名" VARCHAR(50),
137
+ "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
138
+ "更新者名" VARCHAR(50),
139
+ PRIMARY KEY ("部門コード", "開始日")
140
+ );
141
+
142
+ -- インデックス
143
+ CREATE INDEX idx_部門マスタ_部門パス ON "部門マスタ"("部門パス");
144
+ CREATE INDEX idx_部門マスタ_組織階層 ON "部門マスタ"("組織階層");
145
+ ```
146
+
147
+ </details>
148
+
149
+ ### TDD:部門の登録と取得
150
+
151
+ #### Red: 失敗するテストを書く
152
+
153
+ <details>
154
+ <summary>DepartmentRepositoryTest.java</summary>
155
+
156
+ ```java
157
+ // src/test/java/com/example/sms/infrastructure/persistence/repository/DepartmentRepositoryTest.java
158
+ package com.example.sms.infrastructure.persistence.repository;
159
+
160
+ import com.example.sms.application.port.out.DepartmentRepository;
161
+ import com.example.sms.domain.model.department.Department;
162
+ import com.example.sms.testsetup.BaseIntegrationTest;
163
+ import org.junit.jupiter.api.*;
164
+ import org.springframework.beans.factory.annotation.Autowired;
165
+
166
+ import java.time.LocalDate;
167
+
168
+ import static org.assertj.core.api.Assertions.*;
169
+
170
+ @DisplayName("部門リポジトリ")
171
+ class DepartmentRepositoryTest extends BaseIntegrationTest {
172
+
173
+ @Autowired
174
+ private DepartmentRepository departmentRepository;
175
+
176
+ @BeforeEach
177
+ void setUp() {
178
+ departmentRepository.deleteAll();
179
+ }
180
+
181
+ @Nested
182
+ @DisplayName("登録")
183
+ class Registration {
184
+
185
+ @Test
186
+ @DisplayName("部門を登録できる")
187
+ void canRegisterDepartment() {
188
+ // Arrange
189
+ var department = Department.builder()
190
+ .departmentCode("10000")
191
+ .startDate(LocalDate.of(2025, 1, 1))
192
+ .departmentName("本社")
193
+ .hierarchyLevel(0)
194
+ .departmentPath("10000")
195
+ .isLeaf(false)
196
+ .build();
197
+
198
+ // Act
199
+ departmentRepository.save(department);
200
+
201
+ // Assert
202
+ var result = departmentRepository.findByCode("10000");
203
+ assertThat(result).isPresent();
204
+ assertThat(result.get().getDepartmentName()).isEqualTo("本社");
205
+ assertThat(result.get().getHierarchyLevel()).isEqualTo(0);
206
+ }
207
+
208
+ @Test
209
+ @DisplayName("階層構造を持つ部門を登録できる")
210
+ void canRegisterHierarchicalDepartments() {
211
+ // Arrange: 親部門
212
+ var parent = Department.builder()
213
+ .departmentCode("10000")
214
+ .startDate(LocalDate.of(2025, 1, 1))
215
+ .departmentName("本社")
216
+ .hierarchyLevel(0)
217
+ .departmentPath("10000")
218
+ .isLeaf(false)
219
+ .build();
220
+ departmentRepository.save(parent);
221
+
222
+ // Arrange: 子部門
223
+ var child = Department.builder()
224
+ .departmentCode("11000")
225
+ .startDate(LocalDate.of(2025, 1, 1))
226
+ .departmentName("営業本部")
227
+ .hierarchyLevel(1)
228
+ .departmentPath("10000~11000")
229
+ .isLeaf(false)
230
+ .build();
231
+ departmentRepository.save(child);
232
+
233
+ // Arrange: 孫部門(最下層)
234
+ var grandChild = Department.builder()
235
+ .departmentCode("11101")
236
+ .startDate(LocalDate.of(2025, 1, 1))
237
+ .departmentName("営業1課")
238
+ .hierarchyLevel(3)
239
+ .departmentPath("10000~11000~11100~11101")
240
+ .isLeaf(true)
241
+ .build();
242
+ departmentRepository.save(grandChild);
243
+
244
+ // Act
245
+ var result = departmentRepository.findByCode("11101");
246
+
247
+ // Assert
248
+ assertThat(result).isPresent();
249
+ assertThat(result.get().getDepartmentPath()).isEqualTo("10000~11000~11100~11101");
250
+ assertThat(result.get().isLeaf()).isTrue();
251
+ }
252
+ }
253
+
254
+ @Nested
255
+ @DisplayName("履歴管理")
256
+ class HistoryManagement {
257
+
258
+ @Test
259
+ @DisplayName("同じ部門コードでも開始日が異なれば登録できる(組織改正対応)")
260
+ void canRegisterSameCodeWithDifferentStartDate() {
261
+ // Arrange: 旧組織
262
+ var oldDept = Department.builder()
263
+ .departmentCode("11000")
264
+ .startDate(LocalDate.of(2024, 1, 1))
265
+ .endDate(LocalDate.of(2024, 12, 31))
266
+ .departmentName("営業部")
267
+ .hierarchyLevel(1)
268
+ .departmentPath("10000~11000")
269
+ .isLeaf(false)
270
+ .build();
271
+ departmentRepository.save(oldDept);
272
+
273
+ // Arrange: 新組織
274
+ var newDept = Department.builder()
275
+ .departmentCode("11000")
276
+ .startDate(LocalDate.of(2025, 1, 1))
277
+ .departmentName("営業本部")
278
+ .hierarchyLevel(1)
279
+ .departmentPath("10000~11000")
280
+ .isLeaf(false)
281
+ .build();
282
+ departmentRepository.save(newDept);
283
+
284
+ // Act: 現在有効な部門を取得
285
+ var result = departmentRepository.findByCodeAndDate("11000", LocalDate.of(2025, 4, 1));
286
+
287
+ // Assert
288
+ assertThat(result).isPresent();
289
+ assertThat(result.get().getDepartmentName()).isEqualTo("営業本部");
290
+ }
291
+ }
292
+ }
293
+ ```
294
+
295
+ </details>
296
+
297
+ #### Green: テストを通す実装
298
+
299
+ <details>
300
+ <summary>Department.java(エンティティ)</summary>
301
+
302
+ ```java
303
+ // src/main/java/com/example/sms/domain/model/department/Department.java
304
+ package com.example.sms.domain.model.department;
305
+
306
+ import lombok.*;
307
+ import java.time.LocalDate;
308
+ import java.time.LocalDateTime;
309
+
310
+ @Data
311
+ @Builder
312
+ @NoArgsConstructor
313
+ @AllArgsConstructor
314
+ public class Department {
315
+ private String departmentCode;
316
+ private LocalDate startDate;
317
+ private LocalDate endDate;
318
+ private String departmentName;
319
+ @Builder.Default
320
+ private Integer hierarchyLevel = 0;
321
+ private String departmentPath;
322
+ @Builder.Default
323
+ private boolean isLeaf = false;
324
+ private LocalDateTime createdAt;
325
+ private String createdBy;
326
+ private LocalDateTime updatedAt;
327
+ private String updatedBy;
328
+ }
329
+ ```
330
+
331
+ </details>
332
+
333
+ <details>
334
+ <summary>DepartmentRepository.java(Output Port)</summary>
335
+
336
+ ```java
337
+ // src/main/java/com/example/sms/application/port/out/DepartmentRepository.java
338
+ package com.example.sms.application.port.out;
339
+
340
+ import com.example.sms.domain.model.department.Department;
341
+
342
+ import java.time.LocalDate;
343
+ import java.util.List;
344
+ import java.util.Optional;
345
+
346
+ /**
347
+ * 部門リポジトリ(Output Port)
348
+ */
349
+ public interface DepartmentRepository {
350
+
351
+ void save(Department department);
352
+
353
+ Optional<Department> findByCode(String departmentCode);
354
+
355
+ Optional<Department> findByCodeAndDate(String departmentCode, LocalDate baseDate);
356
+
357
+ List<Department> findAll();
358
+
359
+ List<Department> findByHierarchyLevel(int level);
360
+
361
+ List<Department> findChildren(String parentPath);
362
+
363
+ void update(Department department);
364
+
365
+ void deleteAll();
366
+ }
367
+ ```
368
+
369
+ </details>
370
+
371
+ <details>
372
+ <summary>DepartmentMapper.xml</summary>
373
+
374
+ ```xml
375
+ <?xml version="1.0" encoding="UTF-8" ?>
376
+ <!DOCTYPE mapper
377
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
378
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
379
+ <mapper namespace="com.example.sms.infrastructure.persistence.mapper.DepartmentMapper">
380
+
381
+ <resultMap id="DepartmentResultMap" type="com.example.sms.domain.model.department.Department">
382
+ <result property="departmentCode" column="部門コード"/>
383
+ <result property="startDate" column="開始日"/>
384
+ <result property="endDate" column="終了日"/>
385
+ <result property="departmentName" column="部門名"/>
386
+ <result property="hierarchyLevel" column="組織階層"/>
387
+ <result property="departmentPath" column="部門パス"/>
388
+ <result property="isLeaf" column="最下層区分"/>
389
+ <result property="createdAt" column="作成日時"/>
390
+ <result property="createdBy" column="作成者名"/>
391
+ <result property="updatedAt" column="更新日時"/>
392
+ <result property="updatedBy" column="更新者名"/>
393
+ </resultMap>
394
+
395
+ <insert id="insert" parameterType="com.example.sms.domain.model.department.Department">
396
+ INSERT INTO "部門マスタ" (
397
+ "部門コード", "開始日", "終了日", "部門名",
398
+ "組織階層", "部門パス", "最下層区分",
399
+ "作成日時", "作成者名", "更新日時", "更新者名"
400
+ ) VALUES (
401
+ #{departmentCode}, #{startDate}, #{endDate}, #{departmentName},
402
+ #{hierarchyLevel}, #{departmentPath}, #{isLeaf},
403
+ CURRENT_TIMESTAMP, #{createdBy}, CURRENT_TIMESTAMP, #{updatedBy}
404
+ )
405
+ </insert>
406
+
407
+ <select id="findByCode" resultMap="DepartmentResultMap">
408
+ SELECT * FROM "部門マスタ"
409
+ WHERE "部門コード" = #{departmentCode}
410
+ AND ("終了日" IS NULL OR "終了日" > CURRENT_DATE)
411
+ ORDER BY "開始日" DESC
412
+ LIMIT 1
413
+ </select>
414
+
415
+ <select id="findByCodeAndDate" resultMap="DepartmentResultMap">
416
+ SELECT * FROM "部門マスタ"
417
+ WHERE "部門コード" = #{departmentCode}
418
+ AND "開始日" &lt;= #{baseDate}
419
+ AND ("終了日" IS NULL OR "終了日" > #{baseDate})
420
+ ORDER BY "開始日" DESC
421
+ LIMIT 1
422
+ </select>
423
+
424
+ <delete id="deleteAll">
425
+ TRUNCATE TABLE "部門マスタ" CASCADE
426
+ </delete>
427
+ </mapper>
428
+ ```
429
+
430
+ </details>
431
+
432
+ ---
433
+
434
+ ## 5.2 社員マスタの設計
435
+
436
+ 部門に所属する社員を管理するマスタを設計します。
437
+
438
+ ### 社員マスタの ER 図
439
+
440
+ ```plantuml
441
+ @startuml
442
+
443
+ title 社員マスタ
444
+
445
+ entity 社員マスタ {
446
+ 社員コード <<PK>>
447
+ --
448
+ 社員名
449
+ 社員名カナ
450
+ 部門コード <<FK>>
451
+ 開始日 <<FK>>
452
+ 作成日時
453
+ 作成者名
454
+ 更新日時
455
+ 更新者名
456
+ }
457
+
458
+ entity 部門マスタ {
459
+ 部門コード <<PK>>
460
+ 開始日 <<PK>>
461
+ --
462
+ ...
463
+ }
464
+
465
+ 社員マスタ }o--|| 部門マスタ
466
+
467
+ @enduml
468
+ ```
469
+
470
+ ### マイグレーション:社員マスタテーブルの作成
471
+
472
+ <details>
473
+ <summary>SQL 実装</summary>
474
+
475
+ ```sql
476
+ -- src/main/resources/db/migration/V003__create_employee_master.sql
477
+
478
+ -- 社員マスタ
479
+ CREATE TABLE "社員マスタ" (
480
+ "社員コード" VARCHAR(10) PRIMARY KEY,
481
+ "社員名" VARCHAR(20) NOT NULL,
482
+ "社員名カナ" VARCHAR(40),
483
+ "部門コード" VARCHAR(10),
484
+ "開始日" DATE,
485
+ "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
486
+ "作成者名" VARCHAR(50),
487
+ "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
488
+ "更新者名" VARCHAR(50),
489
+ FOREIGN KEY ("部門コード", "開始日") REFERENCES "部門マスタ"("部門コード", "開始日")
490
+ );
491
+
492
+ CREATE INDEX idx_社員マスタ_部門コード ON "社員マスタ"("部門コード");
493
+ ```
494
+
495
+ </details>
496
+
497
+ ### エンティティ(ドメイン層)
498
+
499
+ <details>
500
+ <summary>Employee.java</summary>
501
+
502
+ ```java
503
+ // src/main/java/com/example/sms/domain/model/employee/Employee.java
504
+ package com.example.sms.domain.model.employee;
505
+
506
+ import lombok.*;
507
+ import java.time.LocalDate;
508
+ import java.time.LocalDateTime;
509
+
510
+ @Data
511
+ @Builder
512
+ @NoArgsConstructor
513
+ @AllArgsConstructor
514
+ public class Employee {
515
+ private String employeeCode;
516
+ private String employeeName;
517
+ private String employeeNameKana;
518
+ private String departmentCode;
519
+ private LocalDate departmentStartDate;
520
+ private LocalDateTime createdAt;
521
+ private String createdBy;
522
+ private LocalDateTime updatedAt;
523
+ private String updatedBy;
524
+ }
525
+ ```
526
+
527
+ </details>
528
+
529
+ ---
530
+
531
+ ## 5.3 商品マスタの設計
532
+
533
+ 販売管理システムで扱う「商品」の情報を管理するマスタを設計します。
534
+
535
+ ### 商品マスタの構造
536
+
537
+ ```plantuml
538
+ @startuml
539
+ !define TABLE(x) entity x << (T,#FFAAAA) >>
540
+
541
+ skinparam linetype ortho
542
+ left to right direction
543
+
544
+ TABLE(顧客別販売単価) {
545
+ 商品コード (FK)
546
+ 取引先コード (FK)
547
+ --
548
+ 販売単価
549
+ 作成日時
550
+ 作成者名
551
+ 更新日時
552
+ 更新者名
553
+ }
554
+
555
+ TABLE(商品マスタ) {
556
+ 商品コード
557
+ --
558
+ 商品正式名
559
+ 商品名
560
+ 商品名カナ
561
+ 商品区分
562
+ 製品型番
563
+ 販売単価
564
+ 仕入単価
565
+ 税区分
566
+ 商品分類コード (FK)
567
+ 雑区分
568
+ 在庫管理対象区分
569
+ 在庫引当区分
570
+ 仕入先コード (FK)
571
+ 作成日時
572
+ 作成者名
573
+ 更新日時
574
+ 更新者名
575
+ }
576
+
577
+ TABLE(商品分類マスタ) {
578
+ 商品分類コード
579
+ --
580
+ 商品分類名
581
+ 商品分類階層
582
+ 商品分類パス
583
+ 最下層区分
584
+ 作成日時
585
+ 作成者名
586
+ 更新日時
587
+ 更新者名
588
+ }
589
+
590
+ 顧客別販売単価 }o--|| 商品マスタ
591
+ 商品マスタ }o..|| 商品分類マスタ
592
+
593
+ @enduml
594
+ ```
595
+
596
+ ### 商品区分と税区分
597
+
598
+ 商品には「商品区分」と「税区分」という2つの区分があります。
599
+
600
+ #### 商品区分
601
+
602
+ | 区分値 | 説明 |
603
+ |-------|------|
604
+ | 商品 | 仕入れて販売する商品 |
605
+ | 製品 | 自社で製造した製品 |
606
+ | サービス | 無形のサービス |
607
+ | 諸口 | その他の一時的な商品 |
608
+
609
+ #### 税区分
610
+
611
+ | 区分値 | 説明 |
612
+ |-------|------|
613
+ | 外税 | 税抜価格で管理し、別途消費税を計算 |
614
+ | 内税 | 税込価格で管理 |
615
+ | 非課税 | 消費税対象外 |
616
+
617
+ ### マイグレーション:商品マスタテーブルの作成
618
+
619
+ <details>
620
+ <summary>SQL 実装</summary>
621
+
622
+ ```sql
623
+ -- src/main/resources/db/migration/V004__create_product_master.sql
624
+
625
+ -- 商品区分 ENUM
626
+ CREATE TYPE 商品区分 AS ENUM ('商品', '製品', 'サービス', '諸口');
627
+
628
+ -- 税区分 ENUM
629
+ CREATE TYPE 税区分 AS ENUM ('外税', '内税', '非課税');
630
+
631
+ -- 商品分類マスタ
632
+ CREATE TABLE "商品分類マスタ" (
633
+ "商品分類コード" VARCHAR(10) PRIMARY KEY,
634
+ "商品分類名" VARCHAR(50) NOT NULL,
635
+ "商品分類階層" INTEGER NOT NULL DEFAULT 0,
636
+ "商品分類パス" VARCHAR(100),
637
+ "最下層区分" BOOLEAN NOT NULL DEFAULT FALSE,
638
+ "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
639
+ "作成者名" VARCHAR(50),
640
+ "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
641
+ "更新者名" VARCHAR(50)
642
+ );
643
+
644
+ -- 商品マスタ
645
+ CREATE TABLE "商品マスタ" (
646
+ "商品コード" VARCHAR(20) PRIMARY KEY,
647
+ "商品正式名" VARCHAR(200),
648
+ "商品名" VARCHAR(100) NOT NULL,
649
+ "商品名カナ" VARCHAR(200),
650
+ "商品区分" 商品区分 NOT NULL DEFAULT '商品',
651
+ "製品型番" VARCHAR(50),
652
+ "販売単価" DECIMAL(15, 2) DEFAULT 0,
653
+ "仕入単価" DECIMAL(15, 2) DEFAULT 0,
654
+ "税区分" 税区分 NOT NULL DEFAULT '外税',
655
+ "商品分類コード" VARCHAR(10) REFERENCES "商品分類マスタ"("商品分類コード"),
656
+ "雑区分" BOOLEAN DEFAULT FALSE,
657
+ "在庫管理対象区分" BOOLEAN DEFAULT TRUE,
658
+ "在庫引当区分" BOOLEAN DEFAULT TRUE,
659
+ "仕入先コード" VARCHAR(20),
660
+ "仕入先枝番" VARCHAR(10),
661
+ "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
662
+ "作成者名" VARCHAR(50),
663
+ "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
664
+ "更新者名" VARCHAR(50)
665
+ );
666
+
667
+ -- インデックス
668
+ CREATE INDEX idx_商品マスタ_商品区分 ON "商品マスタ"("商品区分");
669
+ CREATE INDEX idx_商品マスタ_商品分類コード ON "商品マスタ"("商品分類コード");
670
+ CREATE INDEX idx_商品分類マスタ_商品分類パス ON "商品分類マスタ"("商品分類パス");
671
+ ```
672
+
673
+ </details>
674
+
675
+ ### TDD:商品の登録と取得
676
+
677
+ #### Red: 失敗するテストを書く
678
+
679
+ <details>
680
+ <summary>ProductRepositoryTest.java</summary>
681
+
682
+ ```java
683
+ // src/test/java/com/example/sms/infrastructure/persistence/repository/ProductRepositoryTest.java
684
+ package com.example.sms.infrastructure.persistence.repository;
685
+
686
+ import com.example.sms.application.port.out.ProductRepository;
687
+ import com.example.sms.domain.model.product.Product;
688
+ import com.example.sms.domain.model.product.ProductCategory;
689
+ import com.example.sms.domain.model.product.TaxCategory;
690
+ import com.example.sms.testsetup.BaseIntegrationTest;
691
+ import org.junit.jupiter.api.*;
692
+ import org.springframework.beans.factory.annotation.Autowired;
693
+
694
+ import java.math.BigDecimal;
695
+
696
+ import static org.assertj.core.api.Assertions.*;
697
+
698
+ @DisplayName("商品リポジトリ")
699
+ class ProductRepositoryTest extends BaseIntegrationTest {
700
+
701
+ @Autowired
702
+ private ProductRepository productRepository;
703
+
704
+ @BeforeEach
705
+ void setUp() {
706
+ productRepository.deleteAll();
707
+ }
708
+
709
+ @Nested
710
+ @DisplayName("登録")
711
+ class Registration {
712
+
713
+ @Test
714
+ @DisplayName("商品を登録できる")
715
+ void canRegisterProduct() {
716
+ // Arrange
717
+ var product = Product.builder()
718
+ .productCode("PROD001")
719
+ .productName("テスト商品")
720
+ .productCategory(ProductCategory.PRODUCT)
721
+ .sellingPrice(new BigDecimal("1000"))
722
+ .purchasePrice(new BigDecimal("700"))
723
+ .taxCategory(TaxCategory.EXCLUSIVE)
724
+ .build();
725
+
726
+ // Act
727
+ productRepository.save(product);
728
+
729
+ // Assert
730
+ var result = productRepository.findByCode("PROD001");
731
+ assertThat(result).isPresent();
732
+ assertThat(result.get().getProductName()).isEqualTo("テスト商品");
733
+ assertThat(result.get().getSellingPrice()).isEqualByComparingTo(new BigDecimal("1000"));
734
+ }
735
+
736
+ @Test
737
+ @DisplayName("全ての商品区分を登録できる")
738
+ void canRegisterAllCategories() {
739
+ var categories = ProductCategory.values();
740
+
741
+ for (int i = 0; i < categories.length; i++) {
742
+ var product = Product.builder()
743
+ .productCode("CAT-" + String.format("%03d", i))
744
+ .productName("商品" + categories[i].getDisplayName())
745
+ .productCategory(categories[i])
746
+ .taxCategory(TaxCategory.EXCLUSIVE)
747
+ .build();
748
+
749
+ productRepository.save(product);
750
+
751
+ var result = productRepository.findByCode(product.getProductCode());
752
+ assertThat(result).isPresent();
753
+ assertThat(result.get().getProductCategory()).isEqualTo(categories[i]);
754
+ }
755
+ }
756
+ }
757
+
758
+ @Nested
759
+ @DisplayName("税区分")
760
+ class TaxCategories {
761
+
762
+ @Test
763
+ @DisplayName("外税商品を登録できる")
764
+ void canRegisterExclusiveTax() {
765
+ var product = createProduct("TAX001", "外税商品", TaxCategory.EXCLUSIVE);
766
+ productRepository.save(product);
767
+
768
+ var result = productRepository.findByCode("TAX001");
769
+ assertThat(result.get().getTaxCategory()).isEqualTo(TaxCategory.EXCLUSIVE);
770
+ }
771
+
772
+ @Test
773
+ @DisplayName("内税商品を登録できる")
774
+ void canRegisterInclusiveTax() {
775
+ var product = createProduct("TAX002", "内税商品", TaxCategory.INCLUSIVE);
776
+ productRepository.save(product);
777
+
778
+ var result = productRepository.findByCode("TAX002");
779
+ assertThat(result.get().getTaxCategory()).isEqualTo(TaxCategory.INCLUSIVE);
780
+ }
781
+
782
+ @Test
783
+ @DisplayName("非課税商品を登録できる")
784
+ void canRegisterTaxFree() {
785
+ var product = createProduct("TAX003", "非課税商品", TaxCategory.TAX_FREE);
786
+ productRepository.save(product);
787
+
788
+ var result = productRepository.findByCode("TAX003");
789
+ assertThat(result.get().getTaxCategory()).isEqualTo(TaxCategory.TAX_FREE);
790
+ }
791
+ }
792
+
793
+ private Product createProduct(String code, String name, TaxCategory taxCategory) {
794
+ return Product.builder()
795
+ .productCode(code)
796
+ .productName(name)
797
+ .productCategory(ProductCategory.PRODUCT)
798
+ .taxCategory(taxCategory)
799
+ .build();
800
+ }
801
+ }
802
+ ```
803
+
804
+ </details>
805
+
806
+ #### Green: テストを通す実装
807
+
808
+ <details>
809
+ <summary>Product.java(エンティティ)</summary>
810
+
811
+ ```java
812
+ // src/main/java/com/example/sms/domain/model/product/Product.java
813
+ package com.example.sms.domain.model.product;
814
+
815
+ import lombok.*;
816
+ import java.math.BigDecimal;
817
+ import java.time.LocalDateTime;
818
+
819
+ @Data
820
+ @Builder
821
+ @NoArgsConstructor
822
+ @AllArgsConstructor
823
+ public class Product {
824
+ private String productCode;
825
+ private String productFullName;
826
+ private String productName;
827
+ private String productNameKana;
828
+ private ProductCategory productCategory;
829
+ private String modelNumber;
830
+ @Builder.Default
831
+ private BigDecimal sellingPrice = BigDecimal.ZERO;
832
+ @Builder.Default
833
+ private BigDecimal purchasePrice = BigDecimal.ZERO;
834
+ private TaxCategory taxCategory;
835
+ private String classificationCode;
836
+ @Builder.Default
837
+ private boolean isMiscellaneous = false;
838
+ @Builder.Default
839
+ private boolean isInventoryManaged = true;
840
+ @Builder.Default
841
+ private boolean isInventoryAllocated = true;
842
+ private String supplierCode;
843
+ private String supplierBranchNumber;
844
+ private LocalDateTime createdAt;
845
+ private String createdBy;
846
+ private LocalDateTime updatedAt;
847
+ private String updatedBy;
848
+ }
849
+ ```
850
+
851
+ </details>
852
+
853
+ <details>
854
+ <summary>ProductCategory.java(商品区分 Enum)</summary>
855
+
856
+ ```java
857
+ // src/main/java/com/example/sms/domain/model/product/ProductCategory.java
858
+ package com.example.sms.domain.model.product;
859
+
860
+ import lombok.Getter;
861
+ import lombok.RequiredArgsConstructor;
862
+
863
+ @Getter
864
+ @RequiredArgsConstructor
865
+ public enum ProductCategory {
866
+ PRODUCT("商品"),
867
+ MANUFACTURED("製品"),
868
+ SERVICE("サービス"),
869
+ MISCELLANEOUS("諸口");
870
+
871
+ private final String displayName;
872
+
873
+ public static ProductCategory fromDisplayName(String displayName) {
874
+ for (ProductCategory category : values()) {
875
+ if (category.displayName.equals(displayName)) {
876
+ return category;
877
+ }
878
+ }
879
+ throw new IllegalArgumentException("不正な商品区分: " + displayName);
880
+ }
881
+ }
882
+ ```
883
+
884
+ </details>
885
+
886
+ <details>
887
+ <summary>TaxCategory.java(税区分 Enum)</summary>
888
+
889
+ ```java
890
+ // src/main/java/com/example/sms/domain/model/product/TaxCategory.java
891
+ package com.example.sms.domain.model.product;
892
+
893
+ import lombok.Getter;
894
+ import lombok.RequiredArgsConstructor;
895
+
896
+ @Getter
897
+ @RequiredArgsConstructor
898
+ public enum TaxCategory {
899
+ EXCLUSIVE("外税"),
900
+ INCLUSIVE("内税"),
901
+ TAX_FREE("非課税");
902
+
903
+ private final String displayName;
904
+
905
+ public static TaxCategory fromDisplayName(String displayName) {
906
+ for (TaxCategory category : values()) {
907
+ if (category.displayName.equals(displayName)) {
908
+ return category;
909
+ }
910
+ }
911
+ throw new IllegalArgumentException("不正な税区分: " + displayName);
912
+ }
913
+ }
914
+ ```
915
+
916
+ </details>
917
+
918
+ ### 顧客別販売単価の設計
919
+
920
+ 特定の顧客に対して、標準単価とは異なる販売単価を設定できる仕組みです。
921
+
922
+ <details>
923
+ <summary>SQL 実装</summary>
924
+
925
+ ```sql
926
+ -- src/main/resources/db/migration/V005__create_customer_price.sql
927
+
928
+ -- 顧客別販売単価
929
+ CREATE TABLE "顧客別販売単価" (
930
+ "商品コード" VARCHAR(20) NOT NULL REFERENCES "商品マスタ"("商品コード"),
931
+ "取引先コード" VARCHAR(20) NOT NULL,
932
+ "適用開始日" DATE NOT NULL,
933
+ "適用終了日" DATE,
934
+ "販売単価" DECIMAL(15, 2) NOT NULL,
935
+ "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
936
+ "作成者名" VARCHAR(50),
937
+ "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
938
+ "更新者名" VARCHAR(50),
939
+ PRIMARY KEY ("商品コード", "取引先コード", "適用開始日")
940
+ );
941
+ ```
942
+
943
+ </details>
944
+
945
+ ---
946
+
947
+ ## 5.4 原価管理の設計
948
+
949
+ 商品の原価を計算する方法には8種類あります。
950
+
951
+ ### 8種類の原価法
952
+
953
+ | 原価法 | 説明 |
954
+ |-------|------|
955
+ | **個別原価法** | 個々の商品ごとに原価を管理 |
956
+ | **先入先出法** | 最も古い在庫から順に払い出す |
957
+ | **後入先出法** | 最も新しい在庫から順に払い出す |
958
+ | **総平均法** | 期間全体の平均原価を使用 |
959
+ | **移動平均法** | 仕入れのたびに平均原価を再計算 |
960
+ | **単純平均法** | 単純に平均値を使用 |
961
+ | **最終仕入原価法** | 最後に仕入れた原価を使用 |
962
+ | **売価還元法** | 売価から逆算して原価を算出 |
963
+
964
+ ### 原価法の選択基準
965
+
966
+ ```plantuml
967
+ @startuml
968
+
969
+ title 原価法の選択フロー
970
+
971
+ start
972
+
973
+ if (商品の個別管理が必要?) then (yes)
974
+ :個別原価法;
975
+ stop
976
+ else (no)
977
+ endif
978
+
979
+ if (期中の原価変動が大きい?) then (yes)
980
+ if (リアルタイム管理が必要?) then (yes)
981
+ :移動平均法;
982
+ else (no)
983
+ :総平均法;
984
+ endif
985
+ stop
986
+ else (no)
987
+ endif
988
+
989
+ if (簡便な管理でよい?) then (yes)
990
+ :最終仕入原価法;
991
+ stop
992
+ else (no)
993
+ :先入先出法;
994
+ stop
995
+ endif
996
+
997
+ @enduml
998
+ ```
999
+
1000
+ 本システムでは**移動平均法**を採用し、仕入れのたびに平均原価を再計算します。
1001
+
1002
+ ---
1003
+
1004
+ ## 5.5 消費税の設計
1005
+
1006
+ ### 税区分の考え方
1007
+
1008
+ | 税区分 | 説明 | 計算方法 |
1009
+ |-------|------|---------|
1010
+ | **外税** | 税抜価格で管理 | 価格 × 税率 = 消費税額 |
1011
+ | **内税** | 税込価格で管理 | 価格 × 税率 ÷ (1 + 税率) = 消費税額 |
1012
+ | **非課税** | 消費税対象外 | 消費税額 = 0 |
1013
+
1014
+ ### 消費税計算の実装
1015
+
1016
+ <details>
1017
+ <summary>TaxCalculator.java</summary>
1018
+
1019
+ ```java
1020
+ // src/main/java/com/example/sms/domain/type/TaxCalculator.java
1021
+ package com.example.sms.domain.type;
1022
+
1023
+ import com.example.sms.domain.model.product.TaxCategory;
1024
+ import lombok.RequiredArgsConstructor;
1025
+ import java.math.BigDecimal;
1026
+ import java.math.RoundingMode;
1027
+
1028
+ @RequiredArgsConstructor
1029
+ public class TaxCalculator {
1030
+
1031
+ private final BigDecimal taxRate;
1032
+
1033
+ /**
1034
+ * 消費税額を計算する
1035
+ */
1036
+ public BigDecimal calculateTax(BigDecimal price, TaxCategory taxCategory) {
1037
+ return switch (taxCategory) {
1038
+ case EXCLUSIVE -> price.multiply(taxRate)
1039
+ .setScale(0, RoundingMode.DOWN);
1040
+ case INCLUSIVE -> price.multiply(taxRate)
1041
+ .divide(BigDecimal.ONE.add(taxRate), 0, RoundingMode.DOWN);
1042
+ case TAX_FREE -> BigDecimal.ZERO;
1043
+ };
1044
+ }
1045
+
1046
+ /**
1047
+ * 税込金額を計算する
1048
+ */
1049
+ public BigDecimal calculateTaxIncludedPrice(BigDecimal price, TaxCategory taxCategory) {
1050
+ return switch (taxCategory) {
1051
+ case EXCLUSIVE -> price.add(calculateTax(price, taxCategory));
1052
+ case INCLUSIVE -> price;
1053
+ case TAX_FREE -> price;
1054
+ };
1055
+ }
1056
+ }
1057
+ ```
1058
+
1059
+ </details>
1060
+
1061
+ ---
1062
+
1063
+ ## 5.6 顧客マスタの設計
1064
+
1065
+ 顧客と仕入先を統合管理する取引先マスタを設計します。
1066
+
1067
+ ### 取引先マスタの構造
1068
+
1069
+ ```plantuml
1070
+ @startuml
1071
+ left to right direction
1072
+
1073
+ entity 取引先マスタ {
1074
+ 取引先コード <<PK>>
1075
+ --
1076
+ 取引先名
1077
+ 取引先カナ
1078
+ 顧客区分
1079
+ 仕入先区分
1080
+ 郵便番号
1081
+ 住所1
1082
+ 住所2
1083
+ 取引先分類コード
1084
+ 取引禁止フラグ
1085
+ 雑区分
1086
+ 取引先グループコード
1087
+ 与信限度額
1088
+ 与信一時増加枠
1089
+ 更新日時
1090
+ 更新者名
1091
+ }
1092
+
1093
+ entity 顧客マスタ {
1094
+ 顧客コード(FK) <<PK>>
1095
+ 顧客枝番 <<PK>>
1096
+ --
1097
+ 顧客区分
1098
+ 請求先コード
1099
+ 請求先枝番
1100
+ 回収先コード
1101
+ 回収先枝番
1102
+ 顧客名
1103
+ 顧客名カナ
1104
+ 自社担当者コード
1105
+ 顧客担当者名
1106
+ 顧客請求区分
1107
+ 顧客締日1
1108
+ 顧客支払月1
1109
+ 顧客支払日1
1110
+ 顧客支払方法1
1111
+ ...
1112
+ }
1113
+
1114
+ entity 仕入先マスタ {
1115
+ 仕入先コード(FK) <<PK>>
1116
+ 仕入先枝番 <<PK>>
1117
+ --
1118
+ 仕入先担当者名
1119
+ 部門名
1120
+ 電話番号
1121
+ FAX番号
1122
+ メールアドレス
1123
+ ...
1124
+ }
1125
+
1126
+ entity 出荷先マスタ {
1127
+ 取引先コード(FK)
1128
+ 顧客枝番(FK)
1129
+ 出荷先番号 <<PK>>
1130
+ --
1131
+ 出荷先名
1132
+ 地域コード
1133
+ 出荷先郵便番号
1134
+ 出荷先住所1
1135
+ 出荷先住所2
1136
+ ...
1137
+ }
1138
+
1139
+ 取引先マスタ ||--o| 顧客マスタ
1140
+ 取引先マスタ ||--o| 仕入先マスタ
1141
+ 顧客マスタ ||--o{ 出荷先マスタ
1142
+
1143
+ @enduml
1144
+ ```
1145
+
1146
+ ### 請求先・回収先の概念
1147
+
1148
+ 顧客マスタでは、実際に商品を購入する顧客と、請求書を送付する先(請求先)、代金を回収する先(回収先)を分けて管理できます。
1149
+
1150
+ ```plantuml
1151
+ @startuml
1152
+
1153
+ title 請求先・回収先の関係
1154
+
1155
+ actor "購入者\n(A支店)" as buyer
1156
+ actor "請求先\n(本社経理部)" as billing
1157
+ actor "回収先\n(本社財務部)" as collection
1158
+
1159
+ buyer -right-> billing : 請求書送付先
1160
+ billing -right-> collection : 代金支払元
1161
+
1162
+ note bottom of buyer
1163
+ 顧客コード: C001
1164
+ 顧客枝番: 01
1165
+ 請求先コード: C001
1166
+ 請求先枝番: 00
1167
+ end note
1168
+
1169
+ note bottom of billing
1170
+ 顧客コード: C001
1171
+ 顧客枝番: 00
1172
+ (本社)
1173
+ end note
1174
+
1175
+ @enduml
1176
+ ```
1177
+
1178
+ ### マイグレーション:取引先関連テーブルの作成
1179
+
1180
+ <details>
1181
+ <summary>SQL 実装</summary>
1182
+
1183
+ ```sql
1184
+ -- src/main/resources/db/migration/V006__create_partner_master.sql
1185
+
1186
+ -- 請求区分 ENUM
1187
+ CREATE TYPE 請求区分 AS ENUM ('都度', '締め');
1188
+
1189
+ -- 支払方法 ENUM
1190
+ CREATE TYPE 支払方法 AS ENUM ('現金', '振込', '手形', '小切手', 'その他');
1191
+
1192
+ -- 取引先グループマスタ
1193
+ CREATE TABLE "取引先グループマスタ" (
1194
+ "取引先グループコード" VARCHAR(10) PRIMARY KEY,
1195
+ "取引先グループ名" VARCHAR(50) NOT NULL,
1196
+ "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1197
+ "作成者名" VARCHAR(50),
1198
+ "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1199
+ "更新者名" VARCHAR(50)
1200
+ );
1201
+
1202
+ -- 取引先マスタ
1203
+ CREATE TABLE "取引先マスタ" (
1204
+ "取引先コード" VARCHAR(20) PRIMARY KEY,
1205
+ "取引先名" VARCHAR(100) NOT NULL,
1206
+ "取引先カナ" VARCHAR(200),
1207
+ "顧客区分" BOOLEAN DEFAULT FALSE,
1208
+ "仕入先区分" BOOLEAN DEFAULT FALSE,
1209
+ "郵便番号" VARCHAR(10),
1210
+ "住所1" VARCHAR(100),
1211
+ "住所2" VARCHAR(100),
1212
+ "取引先分類コード" VARCHAR(10),
1213
+ "取引禁止フラグ" BOOLEAN DEFAULT FALSE,
1214
+ "雑区分" BOOLEAN DEFAULT FALSE,
1215
+ "取引先グループコード" VARCHAR(10) REFERENCES "取引先グループマスタ"("取引先グループコード"),
1216
+ "与信限度額" DECIMAL(15, 2) DEFAULT 0,
1217
+ "与信一時増加枠" DECIMAL(15, 2) DEFAULT 0,
1218
+ "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1219
+ "作成者名" VARCHAR(50),
1220
+ "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1221
+ "更新者名" VARCHAR(50)
1222
+ );
1223
+
1224
+ -- 顧客マスタ
1225
+ CREATE TABLE "顧客マスタ" (
1226
+ "顧客コード" VARCHAR(20) NOT NULL REFERENCES "取引先マスタ"("取引先コード"),
1227
+ "顧客枝番" VARCHAR(10) NOT NULL DEFAULT '00',
1228
+ "顧客区分" VARCHAR(10),
1229
+ "請求先コード" VARCHAR(20),
1230
+ "請求先枝番" VARCHAR(10),
1231
+ "回収先コード" VARCHAR(20),
1232
+ "回収先枝番" VARCHAR(10),
1233
+ "顧客名" VARCHAR(100),
1234
+ "顧客名カナ" VARCHAR(200),
1235
+ "自社担当者コード" VARCHAR(10),
1236
+ "顧客担当者名" VARCHAR(50),
1237
+ "顧客部門名" VARCHAR(50),
1238
+ "顧客郵便番号" VARCHAR(10),
1239
+ "顧客都道府県" VARCHAR(10),
1240
+ "顧客住所1" VARCHAR(100),
1241
+ "顧客住所2" VARCHAR(100),
1242
+ "顧客電話番号" VARCHAR(20),
1243
+ "顧客FAX番号" VARCHAR(20),
1244
+ "顧客メールアドレス" VARCHAR(100),
1245
+ "顧客請求区分" 請求区分 DEFAULT '締め',
1246
+ "顧客締日1" INTEGER,
1247
+ "顧客支払月1" INTEGER,
1248
+ "顧客支払日1" INTEGER,
1249
+ "顧客支払方法1" 支払方法,
1250
+ "顧客締日2" INTEGER,
1251
+ "顧客支払月2" INTEGER,
1252
+ "顧客支払日2" INTEGER,
1253
+ "顧客支払方法2" 支払方法,
1254
+ "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1255
+ "作成者名" VARCHAR(50),
1256
+ "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1257
+ "更新者名" VARCHAR(50),
1258
+ PRIMARY KEY ("顧客コード", "顧客枝番")
1259
+ );
1260
+
1261
+ -- 仕入先マスタ
1262
+ CREATE TABLE "仕入先マスタ" (
1263
+ "仕入先コード" VARCHAR(20) NOT NULL REFERENCES "取引先マスタ"("取引先コード"),
1264
+ "仕入先枝番" VARCHAR(10) NOT NULL DEFAULT '00',
1265
+ "仕入先担当者名" VARCHAR(50),
1266
+ "部門名" VARCHAR(50),
1267
+ "電話番号" VARCHAR(20),
1268
+ "FAX番号" VARCHAR(20),
1269
+ "メールアドレス" VARCHAR(100),
1270
+ "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1271
+ "作成者名" VARCHAR(50),
1272
+ "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1273
+ "更新者名" VARCHAR(50),
1274
+ PRIMARY KEY ("仕入先コード", "仕入先枝番")
1275
+ );
1276
+
1277
+ -- 地域マスタ
1278
+ CREATE TABLE "地域マスタ" (
1279
+ "地域コード" VARCHAR(10) PRIMARY KEY,
1280
+ "地域名" VARCHAR(50) NOT NULL,
1281
+ "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1282
+ "作成者名" VARCHAR(50),
1283
+ "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1284
+ "更新者名" VARCHAR(50)
1285
+ );
1286
+
1287
+ -- 出荷先マスタ
1288
+ CREATE TABLE "出荷先マスタ" (
1289
+ "取引先コード" VARCHAR(20) NOT NULL,
1290
+ "顧客枝番" VARCHAR(10) NOT NULL,
1291
+ "出荷先番号" VARCHAR(10) NOT NULL,
1292
+ "出荷先名" VARCHAR(100) NOT NULL,
1293
+ "地域コード" VARCHAR(10) REFERENCES "地域マスタ"("地域コード"),
1294
+ "出荷先郵便番号" VARCHAR(10),
1295
+ "出荷先住所1" VARCHAR(100),
1296
+ "出荷先住所2" VARCHAR(100),
1297
+ "作成日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1298
+ "作成者名" VARCHAR(50),
1299
+ "更新日時" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1300
+ "更新者名" VARCHAR(50),
1301
+ PRIMARY KEY ("取引先コード", "顧客枝番", "出荷先番号"),
1302
+ FOREIGN KEY ("取引先コード", "顧客枝番") REFERENCES "顧客マスタ"("顧客コード", "顧客枝番")
1303
+ );
1304
+
1305
+ -- インデックス
1306
+ CREATE INDEX idx_取引先マスタ_取引先グループ ON "取引先マスタ"("取引先グループコード");
1307
+ CREATE INDEX idx_顧客マスタ_請求先 ON "顧客マスタ"("請求先コード", "請求先枝番");
1308
+ ```
1309
+
1310
+ </details>
1311
+
1312
+ ### エンティティ(ドメイン層)
1313
+
1314
+ <details>
1315
+ <summary>Partner.java</summary>
1316
+
1317
+ ```java
1318
+ // src/main/java/com/example/sms/domain/model/partner/Partner.java
1319
+ package com.example.sms.domain.model.partner;
1320
+
1321
+ import lombok.*;
1322
+ import java.math.BigDecimal;
1323
+ import java.time.LocalDateTime;
1324
+
1325
+ @Data
1326
+ @Builder
1327
+ @NoArgsConstructor
1328
+ @AllArgsConstructor
1329
+ public class Partner {
1330
+ private String partnerCode;
1331
+ private String partnerName;
1332
+ private String partnerNameKana;
1333
+ @Builder.Default
1334
+ private boolean isCustomer = false;
1335
+ @Builder.Default
1336
+ private boolean isSupplier = false;
1337
+ private String postalCode;
1338
+ private String address1;
1339
+ private String address2;
1340
+ private String classificationCode;
1341
+ @Builder.Default
1342
+ private boolean isTradingProhibited = false;
1343
+ @Builder.Default
1344
+ private boolean isMiscellaneous = false;
1345
+ private String groupCode;
1346
+ @Builder.Default
1347
+ private BigDecimal creditLimit = BigDecimal.ZERO;
1348
+ @Builder.Default
1349
+ private BigDecimal temporaryCreditIncrease = BigDecimal.ZERO;
1350
+ private LocalDateTime createdAt;
1351
+ private String createdBy;
1352
+ private LocalDateTime updatedAt;
1353
+ private String updatedBy;
1354
+ }
1355
+ ```
1356
+
1357
+ </details>
1358
+
1359
+ ---
1360
+
1361
+ ## 5.7 取引条件の設計
1362
+
1363
+ 顧客との取引条件(締日・支払日など)を管理します。
1364
+
1365
+ ### 締日・支払月・支払日の管理
1366
+
1367
+ | 項目 | 説明 | 例 |
1368
+ |-----|------|-----|
1369
+ | **締日** | 請求の締め日 | 20日、末日 |
1370
+ | **支払月** | 締め月から何ヶ月後か | 0(当月)、1(翌月) |
1371
+ | **支払日** | 支払日 | 10日、25日、末日 |
1372
+
1373
+ ### 都度請求と締め請求
1374
+
1375
+ | 請求区分 | 説明 |
1376
+ |---------|------|
1377
+ | **都度請求** | 取引のたびに請求書を発行 |
1378
+ | **締め請求** | 締日でまとめて請求書を発行 |
1379
+
1380
+ ### 与信管理
1381
+
1382
+ ```plantuml
1383
+ @startuml
1384
+
1385
+ title 与信チェックフロー
1386
+
1387
+ start
1388
+
1389
+ :受注登録;
1390
+
1391
+ :売掛残高を取得;
1392
+ :受注済残高を取得;
1393
+ :今回受注金額を加算;
1394
+
1395
+ :与信限度額を取得;
1396
+ :一時増加枠を取得;
1397
+
1398
+ if (売掛残高 + 受注済残高 + 今回受注 > 与信限度額 + 一時増加枠) then (yes)
1399
+ :与信オーバー警告;
1400
+ if (強制登録?) then (yes)
1401
+ :受注登録(警告付き);
1402
+ else (no)
1403
+ :受注キャンセル;
1404
+ stop
1405
+ endif
1406
+ else (no)
1407
+ endif
1408
+
1409
+ :受注確定;
1410
+
1411
+ stop
1412
+
1413
+ @enduml
1414
+ ```
1415
+
1416
+ ### 請求区分・支払方法の Enum
1417
+
1418
+ <details>
1419
+ <summary>BillingType.java</summary>
1420
+
1421
+ ```java
1422
+ // src/main/java/com/example/sms/domain/model/partner/BillingType.java
1423
+ package com.example.sms.domain.model.partner;
1424
+
1425
+ import lombok.Getter;
1426
+ import lombok.RequiredArgsConstructor;
1427
+
1428
+ @Getter
1429
+ @RequiredArgsConstructor
1430
+ public enum BillingType {
1431
+ ON_DEMAND("都度"),
1432
+ PERIODIC("締め");
1433
+
1434
+ private final String displayName;
1435
+
1436
+ public static BillingType fromDisplayName(String displayName) {
1437
+ for (BillingType type : values()) {
1438
+ if (type.displayName.equals(displayName)) {
1439
+ return type;
1440
+ }
1441
+ }
1442
+ throw new IllegalArgumentException("不正な請求区分: " + displayName);
1443
+ }
1444
+ }
1445
+ ```
1446
+
1447
+ </details>
1448
+
1449
+ <details>
1450
+ <summary>PaymentMethod.java</summary>
1451
+
1452
+ ```java
1453
+ // src/main/java/com/example/sms/domain/model/partner/PaymentMethod.java
1454
+ package com.example.sms.domain.model.partner;
1455
+
1456
+ import lombok.Getter;
1457
+ import lombok.RequiredArgsConstructor;
1458
+
1459
+ @Getter
1460
+ @RequiredArgsConstructor
1461
+ public enum PaymentMethod {
1462
+ CASH("現金"),
1463
+ TRANSFER("振込"),
1464
+ BILL("手形"),
1465
+ CHECK("小切手"),
1466
+ OTHER("その他");
1467
+
1468
+ private final String displayName;
1469
+
1470
+ public static PaymentMethod fromDisplayName(String displayName) {
1471
+ for (PaymentMethod method : values()) {
1472
+ if (method.displayName.equals(displayName)) {
1473
+ return method;
1474
+ }
1475
+ }
1476
+ throw new IllegalArgumentException("不正な支払方法: " + displayName);
1477
+ }
1478
+ }
1479
+ ```
1480
+
1481
+ </details>
1482
+
1483
+ ---
1484
+
1485
+ ## 第5章のまとめ
1486
+
1487
+ ### 作成したテーブル
1488
+
1489
+ | テーブル名 | 説明 |
1490
+ |-----------|------|
1491
+ | `部門マスタ` | 組織階層を管理する部門情報 |
1492
+ | `社員マスタ` | 部門に所属する社員情報 |
1493
+ | `商品分類マスタ` | 商品の分類階層 |
1494
+ | `商品マスタ` | 販売商品の情報 |
1495
+ | `顧客別販売単価` | 顧客ごとの特別単価 |
1496
+ | `取引先グループマスタ` | 取引先のグループ |
1497
+ | `取引先マスタ` | 顧客・仕入先の統合情報 |
1498
+ | `顧客マスタ` | 顧客固有情報 |
1499
+ | `仕入先マスタ` | 仕入先固有情報 |
1500
+ | `地域マスタ` | 地域情報 |
1501
+ | `出荷先マスタ` | 顧客の出荷先情報 |
1502
+
1503
+ ### ER 図(第5章完了時点)
1504
+
1505
+ ```plantuml
1506
+ @startuml
1507
+
1508
+ title マスタ情報 ER図
1509
+
1510
+ entity 部門マスタ {
1511
+ 部門コード <<PK>>
1512
+ 開始日 <<PK>>
1513
+ --
1514
+ 終了日
1515
+ 部門名
1516
+ 組織階層
1517
+ 部門パス
1518
+ 最下層区分
1519
+ }
1520
+
1521
+ entity 社員マスタ {
1522
+ 社員コード <<PK>>
1523
+ --
1524
+ 社員名
1525
+ 社員名カナ
1526
+ 部門コード <<FK>>
1527
+ 開始日 <<FK>>
1528
+ }
1529
+
1530
+ entity 商品分類マスタ {
1531
+ 商品分類コード <<PK>>
1532
+ --
1533
+ 商品分類名
1534
+ 商品分類階層
1535
+ 商品分類パス
1536
+ 最下層区分
1537
+ }
1538
+
1539
+ entity 商品マスタ {
1540
+ 商品コード <<PK>>
1541
+ --
1542
+ 商品正式名
1543
+ 商品名
1544
+ 商品名カナ
1545
+ 商品区分
1546
+ 販売単価
1547
+ 仕入単価
1548
+ 税区分
1549
+ 商品分類コード <<FK>>
1550
+ ...
1551
+ }
1552
+
1553
+ entity 顧客別販売単価 {
1554
+ 商品コード <<PK,FK>>
1555
+ 取引先コード <<PK>>
1556
+ 適用開始日 <<PK>>
1557
+ --
1558
+ 適用終了日
1559
+ 販売単価
1560
+ }
1561
+
1562
+ entity 取引先マスタ {
1563
+ 取引先コード <<PK>>
1564
+ --
1565
+ 取引先名
1566
+ 顧客区分
1567
+ 仕入先区分
1568
+ 与信限度額
1569
+ ...
1570
+ }
1571
+
1572
+ entity 顧客マスタ {
1573
+ 顧客コード <<PK,FK>>
1574
+ 顧客枝番 <<PK>>
1575
+ --
1576
+ 請求先コード
1577
+ 顧客請求区分
1578
+ 顧客締日1
1579
+ ...
1580
+ }
1581
+
1582
+ entity 仕入先マスタ {
1583
+ 仕入先コード <<PK,FK>>
1584
+ 仕入先枝番 <<PK>>
1585
+ --
1586
+ 仕入先担当者名
1587
+ ...
1588
+ }
1589
+
1590
+ entity 出荷先マスタ {
1591
+ 取引先コード <<PK,FK>>
1592
+ 顧客枝番 <<PK,FK>>
1593
+ 出荷先番号 <<PK>>
1594
+ --
1595
+ 出荷先名
1596
+ 地域コード <<FK>>
1597
+ ...
1598
+ }
1599
+
1600
+ 部門マスタ ||--o{ 社員マスタ
1601
+ 商品分類マスタ ||--o{ 商品マスタ
1602
+ 商品マスタ ||--o{ 顧客別販売単価
1603
+ 取引先マスタ ||--o| 顧客マスタ
1604
+ 取引先マスタ ||--o| 仕入先マスタ
1605
+ 顧客マスタ ||--o{ 出荷先マスタ
1606
+
1607
+ @enduml
1608
+ ```
1609
+
1610
+ ### 設計のポイント
1611
+
1612
+ 1. **組織階層管理**: 部門マスタは `部門パス` で階層構造を表現
1613
+ 2. **履歴管理**: 部門マスタは `開始日` による世代管理を採用
1614
+ 3. **統合マスタ**: 取引先マスタで顧客・仕入先を統合管理
1615
+ 4. **日本語 DB / 英語 Java**: テーブル・カラムは日本語、Java コードは英語で統一
1616
+ 5. **PostgreSQL ENUM**: 区分値は日本語 ENUM 型で型安全性を確保
1617
+ 6. **与信管理**: 与信限度額と一時増加枠で柔軟な与信管理を実現
1618
+
1619
+ ---
1620
+
1621
+ ## 次章の予告
1622
+
1623
+ 第6章では、受注・出荷・売上の設計に進みます。販売管理の中核となる業務フローを TDD で実装していきます。
1624
+
1625
+ ---
1626
+
1627
+ [← 第4章:販売管理システムのアーキテクチャ](./chapter04.md) | [第6章:受注・出荷・売上の設計 →](./chapter06.md)