diff --git a/src/components/designer/es-modeling/EventStormingModelCanvas.vue b/src/components/designer/es-modeling/EventStormingModelCanvas.vue
index f2e266f5..74a8dc1f 100644
--- a/src/components/designer/es-modeling/EventStormingModelCanvas.vue
+++ b/src/components/designer/es-modeling/EventStormingModelCanvas.vue
@@ -2017,7 +2017,6 @@
import ModelDraftDialog from "../modeling/ModelDraftDialog"
import EventStormingTestTerminal from "./testTerminals/EventStormingTestTerminal.vue";
import ModelDraftDialogWithXAI from "../context-mapping-modeling/dialogs/ModelDraftDialogWithXAI.vue"
- import DraftGeneratorByFunctions from "../modeling/generators/es-ddl-generators/DraftGeneratorByFunctions";
import {
CreateAggregateActionsByFunctions,
CreateAggregateClassIdByDrafts,
@@ -2535,28 +2534,12 @@
CreateCommandActionsByFunctions: {generator: null},
CreatePolicyActionsByFunctions: {generator: null},
CommandGWTGeneratorByFunctions: {generator: null},
-
- DraftGeneratorByFunctions: {
- generator: null,
- initialAccumulatedDrafts: {},
- accumulatedDrafts: {},
- generate: (structuredDescription, boundedContext) => {},
- updateAccumulatedDrafts: (output, targetBoundedContext) => {}
- },
-
- PreProcessingFunctionsGenerator: {
- generator: null
- }
+ PreProcessingFunctionsGenerator: {generator: null}
},
generatorsInGeneratorUI: {
- PreProcessingFunctionsGenerator: {
- callbacks: {},
- initialInputs: [],
- inputs: [],
- buildInitialInputs: () => {},
- initInputs: () => {},
- generateIfInputsExist: () => {}
+ CreateAggregateActionsByFunctions: {
+ callbacks: {}
}
},
@@ -2865,201 +2848,12 @@
})
// 이 Generator의 호출은 ESDialoger.jump()에서 간접적으로 이루어짐
- this.generatorsInGeneratorUI.PreProcessingFunctionsGenerator.callbacks = {
+ this.generatorsInGeneratorUI.CreateAggregateActionsByFunctions.callbacks = {
+ // 공통 처리 루트로 들어가기 위한 작업
onInputParamsCheckBefore: (inputParams) => {
- if(this.generatorsInGeneratorUI.PreProcessingFunctionsGenerator.initialInputs.length > 0)
- return
-
- this.generatorsInGeneratorUI.PreProcessingFunctionsGenerator.buildInitialInputs(inputParams.passedGeneratorInputs)
- this.generatorsInGeneratorUI.PreProcessingFunctionsGenerator.initInputs()
- this.generatorsInGeneratorUI.PreProcessingFunctionsGenerator.inputs.shift() // 이미 대상이 된 옵션 제거
- },
-
- onFirstResponse: (returnObj) => {
- this.modelDraftDialogWithXAIDto = {
- ...this.modelDraftDialogWithXAIDto,
- isShow: true,
- draftUIInfos: {
- leftBoundedContextCount: this.generatorsInGeneratorUI.PreProcessingFunctionsGenerator.inputs.length + 1,
- directMessage: "",
- progress: 0
- },
- isGeneratorButtonEnabled: true,
- actions: {
- stop: () => {
- returnObj.actions.stopGeneration()
- },
- retry: () => {
- this.generatorsInGeneratorUI.PreProcessingFunctionsGenerator.initInputs()
- this.generatorsInGeneratorUI.PreProcessingFunctionsGenerator.generateIfInputsExist()
- }
- }
- }
- },
-
- onModelCreated: (returnObj) => {
- this.modelDraftDialogWithXAIDto.draftUIInfos.directMessage = returnObj.directMessage
- this.modelDraftDialogWithXAIDto.draftUIInfos.progress = returnObj.progress
- },
-
- onGenerationSucceeded: (returnObj) => {
- this.modelDraftDialogWithXAIDto = {
- ...this.modelDraftDialogWithXAIDto,
- draftUIInfos: {
- leftBoundedContextCount: this.generatorsInGeneratorUI.PreProcessingFunctionsGenerator.inputs.length + 1,
- directMessage: returnObj.directMessage,
- progress: 100
- }
- }
-
- this.generators.DraftGeneratorByFunctions.generate(JSON.stringify(returnObj.modelValue.output), returnObj.inputParams.boundedContext)
- },
-
- onRetry: (returnObj) => {
- alert(`[!] An error occurred while analysing your requirements, please try again..\n* Error log \n${returnObj.errorMessage}`)
- this.modelDraftDialogWithXAIDto.isShow = false
- },
-
- onStopped: () => {
- this.modelDraftDialogWithXAIDto.isShow = false
- }
- }
- this.generatorsInGeneratorUI.PreProcessingFunctionsGenerator.buildInitialInputs = (passedGeneratorInputs) => {
- this.generatorsInGeneratorUI.PreProcessingFunctionsGenerator.initialInputs = JSON.parse(JSON.stringify(passedGeneratorInputs))
-
- // 제공된 정보를 기반으로 아직 생성되지는 않았으나, 참조할 수 있는 초안 정보를 미리 생성함
- // 이 정보는 추후에 AI가 초안을 실제 생성한 경우, AI의 디폴트 선택 옵션의 내용으로 순차적으로 업데이트됨
- const accumulatedDrafts = {};
- passedGeneratorInputs.forEach(item => {
- const boundedContext = item.boundedContext;
- if (boundedContext && boundedContext.aggregates && boundedContext.aggregates.length > 0) {
- const aggregates = boundedContext.aggregates.map(aggregate => ({
- aggregate: {
- name: aggregate.name,
- alias: aggregate.alias
- },
- entities: [],
- valueObjects: []
- }));
- accumulatedDrafts[boundedContext.name] = aggregates;
- }
- });
- this.generators.DraftGeneratorByFunctions.initialAccumulatedDrafts = accumulatedDrafts;
- }
- this.generatorsInGeneratorUI.PreProcessingFunctionsGenerator.initInputs = () => {
- this.modelDraftDialogWithXAIDto.draftOptions = []
-
- this.generatorsInGeneratorUI.PreProcessingFunctionsGenerator.inputs = JSON.parse(JSON.stringify(
- this.generatorsInGeneratorUI.PreProcessingFunctionsGenerator.initialInputs
- ))
-
- this.generators.DraftGeneratorByFunctions.accumulatedDrafts = JSON.parse(JSON.stringify(
- this.generators.DraftGeneratorByFunctions.initialAccumulatedDrafts
- ))
- }
- this.generatorsInGeneratorUI.PreProcessingFunctionsGenerator.generateIfInputsExist = () => {
- if(this.generatorsInGeneratorUI.PreProcessingFunctionsGenerator.inputs.length > 0) {
- this.generators.PreProcessingFunctionsGenerator.generator.client.input = this.generatorsInGeneratorUI.PreProcessingFunctionsGenerator.inputs.shift()
- this.generators.PreProcessingFunctionsGenerator.generator.generate()
- return true
- }
- return false
- }
-
- this.generators.PreProcessingFunctionsGenerator.generator = new PreProcessingFunctionsGenerator({
- input: null,
- ...this.generatorsInGeneratorUI.PreProcessingFunctionsGenerator.callbacks
- })
-
- this.generators.DraftGeneratorByFunctions.generator = new DraftGeneratorByFunctions({
- input: null,
-
- onFirstResponse: (returnObj) => {
- this.modelDraftDialogWithXAIDto = {
- ...this.modelDraftDialogWithXAIDto,
- isShow: true,
- draftUIInfos: {
- leftBoundedContextCount: this.generatorsInGeneratorUI.PreProcessingFunctionsGenerator.inputs.length + 1,
- directMessage: "",
- progress: 0
- },
- isGeneratorButtonEnabled: true,
- actions: {
- ...this.modelDraftDialogWithXAIDto.actions,
- stop: () => {
- returnObj.actions.stopGeneration()
- }
- }
- }
- },
-
- onModelCreated: (returnObj) => {
- this.modelDraftDialogWithXAIDto.draftUIInfos.directMessage = returnObj.directMessage
- this.modelDraftDialogWithXAIDto.draftUIInfos.progress = returnObj.progress
- },
-
- onGenerationSucceeded: (returnObj) => {
- const getXAIDtoDraftOptions = (output, targetBoundedContext, description) => {
- return {
- boundedContext: targetBoundedContext.name,
- boundedContextAlias: targetBoundedContext.displayName,
- description: description,
- options: output.options.map(option => ({
- ...option,
- boundedContext: targetBoundedContext,
- description: description
- })),
- conclusions: output.conclusions,
- defaultOptionIndex: output.defaultOptionIndex
- }
- }
-
- this.modelDraftDialogWithXAIDto = {
- ...this.modelDraftDialogWithXAIDto,
- draftOptions: [
- ...this.modelDraftDialogWithXAIDto.draftOptions,
- getXAIDtoDraftOptions(
- returnObj.modelValue.output,
- returnObj.inputParams.boundedContext,
- returnObj.inputParams.description
- )
- ],
- draftUIInfos: {
- leftBoundedContextCount: this.generatorsInGeneratorUI.PreProcessingFunctionsGenerator.inputs.length,
- directMessage: returnObj.directMessage,
- progress: 100
- }
- }
-
- this.generators.DraftGeneratorByFunctions.updateAccumulatedDrafts(returnObj.modelValue.output, returnObj.inputParams.boundedContext)
- if(!this.generatorsInGeneratorUI.PreProcessingFunctionsGenerator.generateIfInputsExist())
- return
- },
-
- onRetry: (returnObj) => {
- alert(`[!] There was an error creating your draft, please try again.\n* Error log \n${returnObj.errorMessage}`)
- this.modelDraftDialogWithXAIDto.isShow = false
- },
-
- onStopped: () => {
- this.modelDraftDialogWithXAIDto.isShow = false
- }
- })
- this.generators.DraftGeneratorByFunctions.generate = (structuredDescription, boundedContext) => {
- // 해당 초안은 새롭게 생성시킬 대상이기 때문에 초가화된 상태로 전달함
- this.generators.DraftGeneratorByFunctions.accumulatedDrafts[boundedContext.name] = []
-
- this.generators.DraftGeneratorByFunctions.generator.client.input = {
- description: structuredDescription,
- boundedContext: boundedContext,
- accumulatedDrafts: this.generators.DraftGeneratorByFunctions.accumulatedDrafts
- }
- this.generators.DraftGeneratorByFunctions.generator.generate()
- }
- this.generators.DraftGeneratorByFunctions.updateAccumulatedDrafts = (output, targetBoundedContext) => {
- this.generators.DraftGeneratorByFunctions.accumulatedDrafts = {
- ...this.generators.DraftGeneratorByFunctions.accumulatedDrafts,
- ...DraftGeneratorByFunctions.outputToAccumulatedDrafts(output, targetBoundedContext)
+ console.log("[*] 바로 이벤트 스토밍 생성 실행", {inputParams})
+ this.generateFromDraftWithXAI(inputParams.draftOptions)
+ return {stop: true}
}
}
},
diff --git a/src/components/designer/modeling/generators/ESDialoger.vue b/src/components/designer/modeling/generators/ESDialoger.vue
index 2908db44..9861fa4d 100644
--- a/src/components/designer/modeling/generators/ESDialoger.vue
+++ b/src/components/designer/modeling/generators/ESDialoger.vue
@@ -94,7 +94,7 @@
:isStartMapping="isStartMapping"
:processingRate="processingRate"
:currentProcessingBoundedContext="currentProcessingBoundedContext"
- @createModel="jump"
+ @createModel="generateAggregateDrafts"
@closeDialog="showDevideBoundedContextDialog = false"
@stop="stop"
@reGenerate="reGenerate"
@@ -102,6 +102,17 @@
@mappingRequirements="mappingRequirements"
>
+
+
+
+
{
+ this.modelDraftDialogWithXAIDto = {
+ ...this.modelDraftDialogWithXAIDto,
+ isShow: true,
+ draftUIInfos: {
+ leftBoundedContextCount: this.generators.PreProcessingFunctionsGenerator.inputs.length + 1,
+ directMessage: "",
+ progress: 0
+ },
+ isGeneratorButtonEnabled: true,
+ actions: {
+ stop: () => {
+ returnObj.actions.stopGeneration()
+ },
+ retry: () => {
+ this.generators.PreProcessingFunctionsGenerator.initInputs()
+ this.generators.PreProcessingFunctionsGenerator.generateIfInputsExist()
+ }
+ }
+ }
+ },
+
+ onModelCreated: (returnObj) => {
+ this.modelDraftDialogWithXAIDto.draftUIInfos.directMessage = returnObj.directMessage
+ this.modelDraftDialogWithXAIDto.draftUIInfos.progress = returnObj.progress
+ },
+
+ onGenerationSucceeded: (returnObj) => {
+ this.modelDraftDialogWithXAIDto = {
+ ...this.modelDraftDialogWithXAIDto,
+ draftUIInfos: {
+ leftBoundedContextCount: this.generators.PreProcessingFunctionsGenerator.inputs.length + 1,
+ directMessage: returnObj.directMessage,
+ progress: 100
+ }
+ }
+
+ this.generators.DraftGeneratorByFunctions.generate(JSON.stringify(returnObj.modelValue.output), returnObj.inputParams.boundedContext)
+ },
+
+ onRetry: (returnObj) => {
+ alert(`[!] An error occurred while analysing your requirements, please try again..\n* Error log \n${returnObj.errorMessage}`)
+ this.modelDraftDialogWithXAIDto.isShow = false
+ },
+
+ onStopped: () => {
+ this.modelDraftDialogWithXAIDto.isShow = false
+ }
+ })
+ this.generators.PreProcessingFunctionsGenerator.buildInitialInputs = (selectedStructureOption) => {
+ const passedGeneratorInputs = selectedStructureOption.boundedContexts.map(bc => ({
+ boundedContext: {
+ name: bc.name,
+ alias: bc.alias,
+ displayName: bc.alias,
+ description: bc.requirements,
+ aggregates: bc.aggregates
+ },
+ description: bc.requirements
+ }))
+
+ this.generators.PreProcessingFunctionsGenerator.initialInputs = structuredClone(passedGeneratorInputs)
+
+ // 제공된 정보를 기반으로 아직 생성되지는 않았으나, 참조할 수 있는 초안 정보를 미리 생성함
+ // 이 정보는 추후에 AI가 초안을 실제 생성한 경우, AI의 디폴트 선택 옵션의 내용으로 순차적으로 업데이트됨
+ const accumulatedDrafts = {};
+ passedGeneratorInputs.forEach(item => {
+ const boundedContext = item.boundedContext;
+ if (boundedContext && boundedContext.aggregates && boundedContext.aggregates.length > 0) {
+ const aggregates = boundedContext.aggregates.map(aggregate => ({
+ aggregate: {
+ name: aggregate.name,
+ alias: aggregate.alias
+ },
+ entities: [],
+ valueObjects: []
+ }));
+ accumulatedDrafts[boundedContext.name] = aggregates;
+ }
+ });
+ this.generators.DraftGeneratorByFunctions.initialAccumulatedDrafts = accumulatedDrafts;
+ }
+ this.generators.PreProcessingFunctionsGenerator.initInputs = () => {
+ this.modelDraftDialogWithXAIDto.draftOptions = []
+
+ this.generators.PreProcessingFunctionsGenerator.inputs = structuredClone(
+ this.generators.PreProcessingFunctionsGenerator.initialInputs
+ )
+
+ this.generators.DraftGeneratorByFunctions.accumulatedDrafts = structuredClone(
+ this.generators.DraftGeneratorByFunctions.initialAccumulatedDrafts
+ )
+ }
+ this.generators.PreProcessingFunctionsGenerator.generateIfInputsExist = () => {
+ if(this.generators.PreProcessingFunctionsGenerator.inputs.length > 0) {
+ this.generators.PreProcessingFunctionsGenerator.generator.client.input = this.generators.PreProcessingFunctionsGenerator.inputs.shift()
+ this.generators.PreProcessingFunctionsGenerator.generator.generate()
+ return true
+ }
+ return false
+ }
+
+
+ this.generators.DraftGeneratorByFunctions.generator = new DraftGeneratorByFunctions({
+ input: null,
+
+ onFirstResponse: (returnObj) => {
+ this.modelDraftDialogWithXAIDto = {
+ ...this.modelDraftDialogWithXAIDto,
+ isShow: true,
+ draftUIInfos: {
+ leftBoundedContextCount: this.generators.PreProcessingFunctionsGenerator.inputs.length + 1,
+ directMessage: "",
+ progress: 0
+ },
+ isGeneratorButtonEnabled: true,
+ actions: {
+ ...this.modelDraftDialogWithXAIDto.actions,
+ stop: () => {
+ returnObj.actions.stopGeneration()
+ }
+ }
+ }
+ },
+
+ onModelCreated: (returnObj) => {
+ this.modelDraftDialogWithXAIDto.draftUIInfos.directMessage = returnObj.directMessage
+ this.modelDraftDialogWithXAIDto.draftUIInfos.progress = returnObj.progress
+ },
+
+ onGenerationSucceeded: (returnObj) => {
+ const getXAIDtoDraftOptions = (output, targetBoundedContext, description) => {
+ return {
+ boundedContext: targetBoundedContext.name,
+ boundedContextAlias: targetBoundedContext.displayName,
+ description: description,
+ options: output.options.map(option => ({
+ ...option,
+ boundedContext: targetBoundedContext,
+ description: description
+ })),
+ conclusions: output.conclusions,
+ defaultOptionIndex: output.defaultOptionIndex
+ }
+ }
+
+ this.modelDraftDialogWithXAIDto = {
+ ...this.modelDraftDialogWithXAIDto,
+ draftOptions: [
+ ...this.modelDraftDialogWithXAIDto.draftOptions,
+ getXAIDtoDraftOptions(
+ returnObj.modelValue.output,
+ returnObj.inputParams.boundedContext,
+ returnObj.inputParams.description
+ )
+ ],
+ draftUIInfos: {
+ leftBoundedContextCount: this.generators.PreProcessingFunctionsGenerator.inputs.length,
+ directMessage: returnObj.directMessage,
+ progress: 100
+ }
+ }
+
+ this.generators.DraftGeneratorByFunctions.updateAccumulatedDrafts(returnObj.modelValue.output, returnObj.inputParams.boundedContext)
+ if(!this.generators.PreProcessingFunctionsGenerator.generateIfInputsExist())
+ return
+ },
+
+ onRetry: (returnObj) => {
+ alert(`[!] There was an error creating your draft, please try again.\n* Error log \n${returnObj.errorMessage}`)
+ this.modelDraftDialogWithXAIDto.isShow = false
+ },
+
+ onStopped: () => {
+ this.modelDraftDialogWithXAIDto.isShow = false
+ }
+ })
+ this.generators.DraftGeneratorByFunctions.generate = (structuredDescription, boundedContext) => {
+ // 해당 초안은 새롭게 생성시킬 대상이기 때문에 초가화된 상태로 전달함
+ this.generators.DraftGeneratorByFunctions.accumulatedDrafts[boundedContext.name] = []
+
+ this.generators.DraftGeneratorByFunctions.generator.client.input = {
+ description: structuredDescription,
+ boundedContext: boundedContext,
+ accumulatedDrafts: this.generators.DraftGeneratorByFunctions.accumulatedDrafts
+ }
+ this.generators.DraftGeneratorByFunctions.generator.generate()
+ }
+ this.generators.DraftGeneratorByFunctions.updateAccumulatedDrafts = (output, targetBoundedContext) => {
+ this.generators.DraftGeneratorByFunctions.accumulatedDrafts = {
+ ...this.generators.DraftGeneratorByFunctions.accumulatedDrafts,
+ ...DraftGeneratorByFunctions.outputToAccumulatedDrafts(output, targetBoundedContext)
+ }
+ }
},
watch: {
"prompt": {
@@ -250,6 +471,11 @@
inputDDL: '',
pendingBCGeneration: false,
+ textChunker: null,
+ chunks: [],
+ currentChunkIndex: 0,
+ summarizedChunks: [],
+ summarizedResult: "",
summarizedResult: "",
isSummarizeStarted: false,
userStoryChunks: [],
@@ -257,7 +483,39 @@
bcInAspectIndex: 0,
isStartMapping: false,
processingRate: 0,
- currentProcessingBoundedContext: ""
+ currentProcessingBoundedContext: "",
+
+ modelDraftDialogWithXAIDto: {
+ isShow: false,
+ draftOptions: [],
+ draftUIInfos: {
+ leftBoundedContextCount: 0
+ },
+ isGeneratorButtonEnabled: true,
+ actions: {
+ stop: () => {},
+ retry: () => {}
+ }
+ },
+
+ generators: {
+ PreProcessingFunctionsGenerator: {
+ generator: null,
+ initialInputs: [],
+ inputs: [],
+ buildInitialInputs: (selectedStructureOption) => {},
+ initInputs: () => {},
+ generateIfInputsExist: () => {}
+ },
+
+ DraftGeneratorByFunctions: {
+ generator: null,
+ initialAccumulatedDrafts: {},
+ accumulatedDrafts: {},
+ generate: (structuredDescription, boundedContext) => {},
+ updateAccumulatedDrafts: (output, targetBoundedContext) => {}
+ }
+ },
}
},
methods: {
@@ -485,66 +743,56 @@
this.showDevideBoundedContextDialog = true;
},
- jump(selectedStructureOption){
- if(!selectedStructureOption) return
-
- console.log("[*] 선택된 BC 구성 옵션을 기반으로 생성이 시도됨", {selectedStructureOption})
- var me = this
+ uuid: function () {
+ function s4() {
+ return Math.floor((1 + Math.random()) * 0x10000)
+ .toString(16)
+ .substring(1);
+ }
- try {
+ return s4() + s4() + s4() + s4() + s4() + s4() + s4() + s4();
+ },
- if(me.isServerProject) me.state.associatedProject = me.modelIds.projectId
- // 새탭 생성시에 해당 BC 정보를 이용해서 자동으로 생성
- let generatorInputs = selectedStructureOption.boundedContexts.map(bc => ({
- boundedContext: {
- name: bc.name,
- alias: bc.alias,
- displayName: bc.alias,
- description: bc.requirements,
- aggregates: bc.aggregates
- },
- description: bc.requirements
- }))
- const passedGeneratorInputs = JSON.parse(JSON.stringify(generatorInputs))
- const currentGeneratorInput = generatorInputs.shift()
-
- me.state = {
- ...me.state,
- userStory: me.value.userStory,
- ...currentGeneratorInput,
- leftGeneratorInputs: generatorInputs,
- passedGeneratorInputs: passedGeneratorInputs,
- generator: "PreProcessingFunctionsGenerator"
- }
- console.log("[*] 생성 준비를 위한 입력값 구축 완료", {state: me.state})
+ generateAggregateDrafts(selectedStructureOption){
+ if(!selectedStructureOption) return
+ console.log("[*] 선택된 BC 구성 옵션을 기반으로 생성이 시도됨", {selectedStructureOption})
- } catch(e) {
+ this.generators.PreProcessingFunctionsGenerator.buildInitialInputs(selectedStructureOption)
+ this.generators.PreProcessingFunctionsGenerator.initInputs()
+ this.generators.PreProcessingFunctionsGenerator.generateIfInputsExist()
+ },
- console.error("[*] 생성 준비를 위한 입력값 구축과정에서 에러 발생", {error: e, selectedStructureOption})
- alert("[!] There was an error building inputs for event storm generation, please try again.")
- return
+ generateFromDraftWithXAI(draftOptions){
+ if(this.isServerProject) this.state.associatedProject = this.modelIds.projectId
+ this.state = {
+ ...this.state,
+ userStory: this.value.userStory,
+ draftOptions: draftOptions,
+ generator: "CreateAggregateActionsByFunctions"
}
+ console.log("[*] 생성 준비를 위한 입력값 구축 완료", {state: this.state})
+ try {
- try{
-
- if(!me.value.modelList){
- me.value.modelList = []
+ if(!this.value.modelList){
+ this.value.modelList = []
}
- me.$emit("input", me.value);
- me.$emit("change", 'eventStorming');
+ this.$emit("input", this.value);
+ this.$emit("change", 'eventStorming');
// GeneratorUI.createGenerator() 함수에서 해당 값을 받아서 자동 처리 수행
- localStorage["gen-state"] = JSON.stringify(me.state);;
- window.open(`/#/storming/${me.modelIds.ESDefinitionId}`, "_blank")
- me.isCreatedModel = true;
+ localStorage["gen-state"] = JSON.stringify(this.state);;
+ window.open(`/#/storming/${this.modelIds.ESDefinitionId}`, "_blank")
+ this.isCreatedModel = true;
+
+ }
+ catch(e) {
- }catch(e){
+ console.log("[*] 생성 준비를 위한 입력값 구축과정에서 에러 발생", {error: e, state: this.state, selectedStructureOption})
- console.log("[*] 생성 준비를 위한 입력값 구축과정에서 에러 발생", {error: e, state: me.state, selectedStructureOption})
if(e.name=="QuotaExceededError"){
var keys = Object.keys(localStorage);
var values = keys.map(function(key) {
@@ -560,24 +808,11 @@
}
}
+ this.generateFromDraftWithXAI(draftOptions)
}
- this.jump();
-
- }
- },
-
- uuid: function () {
- function s4() {
- return Math.floor((1 + Math.random()) * 0x10000)
- .toString(16)
- .substring(1);
}
-
- return s4() + s4() + s4() + s4() + s4() + s4() + s4() + s4();
- },
-
-
+ }
}
}
diff --git a/src/components/designer/modeling/generators/FormattedJSONAIGenerator.js b/src/components/designer/modeling/generators/FormattedJSONAIGenerator.js
index 0262d9a5..de224d15 100644
--- a/src/components/designer/modeling/generators/FormattedJSONAIGenerator.js
+++ b/src/components/designer/modeling/generators/FormattedJSONAIGenerator.js
@@ -125,7 +125,10 @@ class FormattedJSONAIGenerator extends AIGenerator {
async generate() {
await this.onInputParamsCheckBefore(this.client.input, this.generatorName)
- if(this.client.onInputParamsCheckBefore) await this.client.onInputParamsCheckBefore(this.client.input, this.generatorName)
+ if(this.client.onInputParamsCheckBefore) {
+ const signals = await this.client.onInputParamsCheckBefore(this.client.input, this.generatorName)
+ if(signals && signals.stop) return
+ }
for(let key of this.checkInputParamsKeys)
diff --git a/src/components/designer/modeling/generators/GeneratorUI.vue b/src/components/designer/modeling/generators/GeneratorUI.vue
index c0f2951c..e96831d9 100644
--- a/src/components/designer/modeling/generators/GeneratorUI.vue
+++ b/src/components/designer/modeling/generators/GeneratorUI.vue
@@ -299,6 +299,7 @@
import DDLDraftGenerator from './DDLDraftGenerator.js'
import DDLBoundedContextDistributeGenerator from './es-ddl-generators/DDLBoundedContextDistributeGenerator.js'
import PreProcessingFunctionsGenerator from './es-ddl-generators/PreProcessingFunctionsGenerator.js'
+ import { CreateAggregateActionsByFunctions } from './es-generators'
//import UserStoryGenerator from './UserStoryGenerator.js'
@@ -533,6 +534,7 @@
case "DDLDraftGenerator": this.generatorComponent = new DDLDraftGenerator(this); break;
case "DDLBoundedContextDistributeGenerator": this.generatorComponent = new DDLBoundedContextDistributeGenerator(this); break;
case "PreProcessingFunctionsGenerator": this.generatorComponent = new PreProcessingFunctionsGenerator(this); break;
+ case "CreateAggregateActionsByFunctions": this.generatorComponent = new CreateAggregateActionsByFunctions(this); break;
}
return this.generatorComponent;
@@ -714,7 +716,7 @@
this.showGenerateBtn = false
}
- if(this.generatorName === "PreProcessingFunctionsGenerator") {
+ if(this.generatorName === "CreateAggregateActionsByFunctions") {
this.openGeneratorUI = false
}
},
diff --git a/src/components/designer/modeling/generators/es-generators/CreateAggregateActionsByFunctions/CreateAggregateActionsByFunctions.js b/src/components/designer/modeling/generators/es-generators/CreateAggregateActionsByFunctions/CreateAggregateActionsByFunctions.js
index f92f020d..96d5e57d 100644
--- a/src/components/designer/modeling/generators/es-generators/CreateAggregateActionsByFunctions/CreateAggregateActionsByFunctions.js
+++ b/src/components/designer/modeling/generators/es-generators/CreateAggregateActionsByFunctions/CreateAggregateActionsByFunctions.js
@@ -296,6 +296,11 @@ Structural Rules:
- Must have exactly one primary key attribute
- For composite keys, create a ValueObject and use it as the primary key
- Reference other Aggregates using their class names, not IDs
+ - Avoid creating separate transaction objects when the main aggregate can manage the lifecycle:
+ * Do not create Transaction entities if their properties duplicate the main aggregate
+ * Use the aggregate root to manage state transitions and history
+ * Consider Event Sourcing for tracking historical changes instead of transaction objects
+ * Transaction records should only be created when they have unique business value beyond the aggregate's lifecycle
8. ValueObjects:
- Must contain multiple related properties
diff --git a/src/components/designer/modeling/generators/testTerminals/ESDialogerTestTerminal.vue b/src/components/designer/modeling/generators/testTerminals/ESDialogerTestTerminal.vue
index 49b80aa2..2cf257c7 100644
--- a/src/components/designer/modeling/generators/testTerminals/ESDialogerTestTerminal.vue
+++ b/src/components/designer/modeling/generators/testTerminals/ESDialogerTestTerminal.vue
@@ -22,9 +22,13 @@ export default {
promptCommand() {
const COMMANDS = {
- directJumpByLibrary: {
- command: () => this._directJumpByLibrary(),
- description: "도서-대출 도서관 시나리오로 바로 ES 모델링을 실행"
+ directGenerateAggregateDrafts: {
+ command: () => this._directGenerateAggregateDrafts(),
+ description: "도서관 시나리오 및 도서-대출 BC 구성으로 바로 애그리거트 초안 생성 실행"
+ },
+ directGenerateFromAggregateDrafts: {
+ command: () => this._directGenerateFromAggregateDrafts(),
+ description: "도서관 시나리오 및 도서-대출 BC 초안으로 바로 이벤트 스토밍 생성 실행"
}
}
@@ -62,83 +66,546 @@ export default {
},
- _directJumpByLibrary() {
+ _directGenerateAggregateDrafts() {
this.generator.stop();
this.state.startTemplateGenerate = false
this.done = true;
- this.value.userStory = `도서관의 도서 관리와 대출/반납을 통합적으로 관리하는 화면을 만들려고 해.
-
-'도서 관리' 화면에서는 새로운 도서를 등록하고 현재 보유한 도서들의 상태를 관리할 수 있어야 해. 도서 등록 시에는 도서명, ISBN, 저자, 출판사, 카테고리 정보를 입력받아야 해. ISBN은 13자리 숫자여야 하고 중복 확인이 필요해. 카테고리는 소설/비소설/학술/잡지 중에서 선택할 수 있어야 해. 등록된 도서는 처음에 '대출가능' 상태가 되고, 이후 대출/반납 상황에 따라 '대출중', '예약중' 상태로 자동으로 변경되어야 해. 도서가 훼손되거나 분실된 경우 '폐기' 처리가 가능해야 하며, 폐기된 도서는 더 이상 대출이 불가능해야 해.
-
-'대출/반납' 화면에서는 회원이 도서를 대출하고 반납하는 것을 관리할 수 있어야 해. 대출 신청 시에는 회원번호와 이름으로 회원을 확인하고, 대출할 도서를 선택해야 해. 도서는 도서명이나 ISBN으로 검색할 수 있어야 해. 대출 기간은 7일/14일/30일 중에서 선택할 수 있어. 만약 대출하려는 도서가 이미 대출 중이라면, 예약 신청이 가능해야 해. 대출이 완료되면 해당 도서의 상태는 자동으로 '대출중'으로 변경되어야 해.
-
-대출 현황 화면에서는 현재 대출 중인 도서들의 목록을 볼 수 있어야 해. 각 대출 건에 대해 대출일, 반납예정일, 현재 상태(대출중/연체/반납완료)를 확인할 수 있어야 하고, 대출 중인 도서는 연장이나 반납 처리가 가능해야 해. 도서가 반납되면 자동으로 해당 도서의 상태가 '대출가능'으로 변경되어야 해. 만약 예약자가 있는 도서가 반납되면, 해당 도서는 '예약중' 상태로 변경되어야 해.
+ this.showDevideBoundedContextDialog = true
+ this.resultDevideBoundedContext = {
+ "도메인": {
+ "boundedContexts": [
+ {
+ "name": "BookManagement",
+ "alias": "도서 관리",
+ "aggregates": [
+ {
+ "name": "Book",
+ "alias": "도서"
+ }
+ ],
+ "requirements": [
+ {
+ "type": "userStory",
+ "text": "'도서 관리' 화면에서는 새로운 도서를 등록하고 현재 보유한 도서들의 상태를 관리할 수 있어야 해. 도서 등록 시에는 도서명, ISBN, 저자, 출판사, 카테고리 정보를 입력받아야 해. ISBN은 13자리 숫자여야 하고 중복 확인이 필요해. 카테고리는 소설/비소설/학술/잡지 중에서 선택할 수 있어야 해. 등록된 도서는 처음에 '대출가능' 상태가 되고, 이후 대출/반납 상황에 따라 '대출중', '예약중' 상태로 자동으로 변경되어야 해. 도서가 훼손되거나 분실된 경우 '폐기' 처리가 가능해야 하며, 폐기된 도서는 더 이상 대출이 불가능해야 해."
+ }
+ ]
+ },
+ {
+ "name": "LoanManagement",
+ "alias": "대출/반납",
+ "aggregates": [
+ {
+ "name": "Loan",
+ "alias": "대출"
+ },
+ {
+ "name": "Reservation",
+ "alias": "예약"
+ }
+ ],
+ "requirements": [
+ {
+ "type": "userStory",
+ "text": "'대출/반납' 화면에서는 회원이 도서를 대출하고 반납하는 것을 관리할 수 있어야 해. 대출 신청 시에는 회원번호와 이름으로 회원을 확인하고, 대출할 도서를 선택해야 해. 도서는 도서명이나 ISBN으로 검색할 수 있어야 해. 대출 기간은 7일/14일/30일 중에서 선택할 수 있어. 만약 대출하려는 도서가 이미 대출 중이라면, 예약 신청이 가능해야 해. 대출이 완료되면 해당 도서의 상태는 자동으로 '대출중'으로 변경되어야 해. 대출 현황 화면에서는 현재 대출 중인 도서들의 목록을 볼 수 있어야 해. 각 대출 건에 대해 대출일, 반납예정일, 현재 상태(대출중/연체/반납완료)를 확인할 수 있어야 하고, 대출 중인 도서는 연장이나 반납 처리가 가능해야 해. 도서가 반납되면 자동으로 해당 도서의 상태가 '대출가능'으로 변경되어야 해. 만약 예약자가 있는 도서가 반납되면, 해당 도서는 '예약중' 상태로 변경되어야 해. 각 도서별로 대출 이력과 상태 변경 이력을 조회할 수 있어야 하고, 이를 통해 도서의 대출 현황과 상태 변화를 추적할 수 있어야 해."
+ }
+ ]
+ }
+ ],
+ "relations": [
+ {
+ "name": "BookLoanManagement",
+ "type": "Customer-Supplier",
+ "upStream": {
+ "name": "BookManagement",
+ "alias": "도서 관리"
+ },
+ "downStream": {
+ "name": "LoanManagement",
+ "alias": "대출/반납"
+ }
+ }
+ ],
+ "thoughts": "도서 관리와 대출/반납 관리는 서로 다른 기능적 요구사항을 가지고 있으며, 각 컨텍스트는 높은 응집력과 낮은 결합력을 유지합니다. 도서 관리에서는 도서의 등록과 상태 관리에 초점을 맞추고 있으며, 대출/반납 관리에서는 대출 프로세스와 관련된 기능을 처리합니다. 두 컨텍스트 간의 의존성을 최소화하기 위해 Customer-Supplier 관계를 설정하였습니다.",
+ "explanations": [
+ {
+ "sourceContext": "도서 관리",
+ "targetContext": "대출/반납",
+ "relationType": "Customer-Supplier",
+ "reason": "대출/반납 기능은 도서 관리 기능의 데이터를 사용하여 대출 상태를 업데이트해야 하므로, 도서 관리가 대출/반납의 데이터 공급자 역할을 합니다.",
+ "interactionPattern": "REST API를 통해 도서 상태 정보를 조회하고 업데이트하는 방식으로 상호작용합니다."
+ }
+ ],
+ "devisionAspect": "도메인"
+ },
+ "조직적": {
+ "boundedContexts": [
+ {
+ "name": "BookManagement",
+ "alias": "도서 관리",
+ "aggregates": [
+ {
+ "name": "Book",
+ "alias": "도서"
+ },
+ {
+ "name": "Category",
+ "alias": "카테고리"
+ }
+ ],
+ "requirements": [
+ {
+ "type": "userStory",
+ "text": "'도서 관리' 화면에서는 새로운 도서를 등록하고 현재 보유한 도서들의 상태를 관리할 수 있어야 해. 도서 등록 시에는 도서명, ISBN, 저자, 출판사, 카테고리 정보를 입력받아야 해. ISBN은 13자리 숫자여야 하고 중복 확인이 필요해. 카테고리는 소설/비소설/학술/잡지 중에서 선택할 수 있어야 해. 등록된 도서는 처음에 '대출가능' 상태가 되고, 이후 대출/반납 상황에 따라 '대출중', '예약중' 상태로 자동으로 변경되어야 해. 도서가 훼손되거나 분실된 경우 '폐기' 처리가 가능해야 하며, 폐기된 도서는 더 이상 대출이 불가능해야 해."
+ }
+ ]
+ },
+ {
+ "name": "LoanManagement",
+ "alias": "대출/반납 관리",
+ "aggregates": [
+ {
+ "name": "Loan",
+ "alias": "대출"
+ },
+ {
+ "name": "Member",
+ "alias": "회원"
+ }
+ ],
+ "requirements": [
+ {
+ "type": "userStory",
+ "text": "'대출/반납' 화면에서는 회원이 도서를 대출하고 반납하는 것을 관리할 수 있어야 해. 대출 신청 시에는 회원번호와 이름으로 회원을 확인하고, 대출할 도서를 선택해야 해. 도서는 도서명이나 ISBN으로 검색할 수 있어야 해. 대출 기간은 7일/14일/30일 중에서 선택할 수 있어. 만약 대출하려는 도서가 이미 대출 중이라면, 예약 신청이 가능해야 해. 대출이 완료되면 해당 도서의 상태는 자동으로 '대출중'으로 변경되어야 해."
+ },
+ {
+ "type": "userStory",
+ "text": "대출 현황 화면에서는 현재 대출 중인 도서들의 목록을 볼 수 있어야 해. 각 대출 건에 대해 대출일, 반납예정일, 현재 상태(대출중/연체/반납완료)를 확인할 수 있어야 하고, 대출 중인 도서는 연장이나 반납 처리가 가능해야 해. 도서가 반납되면 자동으로 해당 도서의 상태가 '대출가능'으로 변경되어야 해. 만약 예약자가 있는 도서가 반납되면, 해당 도서는 '예약중' 상태로 변경되어야 해."
+ },
+ {
+ "type": "userStory",
+ "text": "각 도서별로 대출 이력과 상태 변경 이력을 조회할 수 있어야 하고, 이를 통해 도서의 대출 현황과 상태 변화를 추적할 수 있어야 해."
+ }
+ ]
+ }
+ ],
+ "relations": [
+ {
+ "name": "BookLoanIntegration",
+ "type": "Customer-Supplier",
+ "upStream": {
+ "name": "BookManagement",
+ "alias": "도서 관리"
+ },
+ "downStream": {
+ "name": "LoanManagement",
+ "alias": "대출/반납 관리"
+ }
+ }
+ ],
+ "thoughts": "The division into 'BookManagement' and 'LoanManagement' contexts was driven by the need for high cohesion and low coupling. 'BookManagement' focuses on the registration and status management of books, while 'LoanManagement' handles the loan and return processes involving members. These contexts are related through a customer-supplier relationship, where 'LoanManagement' depends on 'BookManagement' for book status updates.",
+ "explanations": [
+ {
+ "sourceContext": "도서 관리",
+ "targetContext": "대출/반납 관리",
+ "relationType": "Customer-Supplier",
+ "reason": "The 'LoanManagement' context relies on the 'BookManagement' context for accurate book status information, such as availability and reservation status. Therefore, a customer-supplier relationship is appropriate.",
+ "interactionPattern": "REST API calls are used for 'LoanManagement' to query and update book statuses from 'BookManagement'."
+ }
+ ],
+ "devisionAspect": "조직적"
+ },
+ "페르소나": {
+ "boundedContexts": [
+ {
+ "name": "BookManagement",
+ "alias": "도서 관리",
+ "aggregates": [
+ {
+ "name": "Book",
+ "alias": "도서"
+ }
+ ],
+ "requirements": [
+ {
+ "type": "userStory",
+ "text": "'도서 관리' 화면에서는 새로운 도서를 등록하고 현재 보유한 도서들의 상태를 관리할 수 있어야 해. 도서 등록 시에는 도서명, ISBN, 저자, 출판사, 카테고리 정보를 입력받아야 해. ISBN은 13자리 숫자여야 하고 중복 확인이 필요해. 카테고리는 소설/비소설/학술/잡지 중에서 선택할 수 있어야 해. 등록된 도서는 처음에 '대출가능' 상태가 되고, 이후 대출/반납 상황에 따라 '대출중', '예약중' 상태로 자동으로 변경되어야 해. 도서가 훼손되거나 분실된 경우 '폐기' 처리가 가능해야 하며, 폐기된 도서는 더 이상 대출이 불가능해야 해."
+ }
+ ]
+ },
+ {
+ "name": "LoanManagement",
+ "alias": "대출/반납 관리",
+ "aggregates": [
+ {
+ "name": "Loan",
+ "alias": "대출"
+ },
+ {
+ "name": "Reservation",
+ "alias": "예약"
+ }
+ ],
+ "requirements": [
+ {
+ "type": "userStory",
+ "text": "'대출/반납' 화면에서는 회원이 도서를 대출하고 반납하는 것을 관리할 수 있어야 해. 대출 신청 시에는 회원번호와 이름으로 회원을 확인하고, 대출할 도서를 선택해야 해. 도서는 도서명이나 ISBN으로 검색할 수 있어야 해. 대출 기간은 7일/14일/30일 중에서 선택할 수 있어. 만약 대출하려는 도서가 이미 대출 중이라면, 예약 신청이 가능해야 해. 대출이 완료되면 해당 도서의 상태는 자동으로 '대출중'으로 변경되어야 해. 대출 현황 화면에서는 현재 대출 중인 도서들의 목록을 볼 수 있어야 해. 각 대출 건에 대해 대출일, 반납예정일, 현재 상태(대출중/연체/반납완료)를 확인할 수 있어야 하고, 대출 중인 도서는 연장이나 반납 처리가 가능해야 해. 도서가 반납되면 자동으로 해당 도서의 상태가 '대출가능'으로 변경되어야 해. 만약 예약자가 있는 도서가 반납되면, 해당 도서는 '예약중' 상태로 변경되어야 해. 각 도서별로 대출 이력과 상태 변경 이력을 조회할 수 있어야 하고, 이를 통해 도서의 대출 현황과 상태 변화를 추적할 수 있어야 해."
+ }
+ ]
+ }
+ ],
+ "relations": [
+ {
+ "name": "BookLoanManagement",
+ "type": "Customer-Supplier",
+ "upStream": {
+ "name": "BookManagement",
+ "alias": "도서 관리"
+ },
+ "downStream": {
+ "name": "LoanManagement",
+ "alias": "대출/반납 관리"
+ }
+ }
+ ],
+ "thoughts": "도서 관리와 대출/반납 관리는 서로 다른 기능과 데이터를 다루기 때문에 높은 응집도를 유지하면서 서로의 의존성을 최소화할 수 있습니다. 도서 관리에서는 도서의 등록, 상태 관리에 집중하고, 대출/반납 관리에서는 회원과의 상호작용을 통해 대출 및 반납 프로세스를 관리합니다. 이 두 컨텍스트는 도서의 상태 변화에 대해 서로 상호작용해야 하므로 Customer-Supplier 관계를 통해 도서 관리가 대출/반납 관리에게 필요한 정보를 제공하는 구조로 설계되었습니다.",
+ "explanations": [
+ {
+ "sourceContext": "도서 관리",
+ "targetContext": "대출/반납 관리",
+ "relationType": "Customer-Supplier",
+ "reason": "대출/반납 관리에서 도서의 상태를 변경할 때 도서 관리의 정보를 참고해야 하기 때문에 도서 관리가 대출/반납 관리에 서비스를 제공하는 형태로 관계가 설정되었습니다.",
+ "interactionPattern": "REST API를 통해 도서 상태 변경 정보를 주고받는 방식으로 상호작용합니다."
+ }
+ ],
+ "devisionAspect": "페르소나"
+ },
+ "거래/성능": {
+ "boundedContexts": [
+ {
+ "name": "BookManagement",
+ "alias": "도서 관리",
+ "aggregates": [
+ {
+ "name": "Book",
+ "alias": "도서"
+ }
+ ],
+ "requirements": [
+ {
+ "type": "userStory",
+ "text": "'도서 관리' 화면에서는 새로운 도서를 등록하고 현재 보유한 도서들의 상태를 관리할 수 있어야 해. 도서 등록 시에는 도서명, ISBN, 저자, 출판사, 카테고리 정보를 입력받아야 해. ISBN은 13자리 숫자여야 하고 중복 확인이 필요해. 카테고리는 소설/비소설/학술/잡지 중에서 선택할 수 있어야 해. 등록된 도서는 처음에 '대출가능' 상태가 되고, 이후 대출/반납 상황에 따라 '대출중', '예약중' 상태로 자동으로 변경되어야 해. 도서가 훼손되거나 분실된 경우 '폐기' 처리가 가능해야 하며, 폐기된 도서는 더 이상 대출이 불가능해야 해."
+ }
+ ]
+ },
+ {
+ "name": "LoanManagement",
+ "alias": "대출/반납",
+ "aggregates": [
+ {
+ "name": "Loan",
+ "alias": "대출"
+ },
+ {
+ "name": "Reservation",
+ "alias": "예약"
+ }
+ ],
+ "requirements": [
+ {
+ "type": "userStory",
+ "text": "'대출/반납' 화면에서는 회원이 도서를 대출하고 반납하는 것을 관리할 수 있어야 해. 대출 신청 시에는 회원번호와 이름으로 회원을 확인하고, 대출할 도서를 선택해야 해. 도서는 도서명이나 ISBN으로 검색할 수 있어야 해. 대출 기간은 7일/14일/30일 중에서 선택할 수 있어. 만약 대출하려는 도서가 이미 대출 중이라면, 예약 신청이 가능해야 해. 대출이 완료되면 해당 도서의 상태는 자동으로 '대출중'으로 변경되어야 해. 대출 현황 화면에서는 현재 대출 중인 도서들의 목록을 볼 수 있어야 해. 각 대출 건에 대해 대출일, 반납예정일, 현재 상태(대출중/연체/반납완료)를 확인할 수 있어야 하고, 대출 중인 도서는 연장이나 반납 처리가 가능해야 해. 도서가 반납되면 자동으로 해당 도서의 상태가 '대출가능'으로 변경되어야 해. 만약 예약자가 있는 도서가 반납되면, 해당 도서는 '예약중' 상태로 변경되어야 해. 각 도서별로 대출 이력과 상태 변경 이력을 조회할 수 있어야 하고, 이를 통해 도서의 대출 현황과 상태 변화를 추적할 수 있어야 해."
+ }
+ ]
+ }
+ ],
+ "relations": [
+ {
+ "name": "LoanManagementToBookManagement",
+ "type": "Customer-Supplier",
+ "upStream": {
+ "name": "BookManagement",
+ "alias": "도서 관리"
+ },
+ "downStream": {
+ "name": "LoanManagement",
+ "alias": "대출/반납"
+ }
+ }
+ ],
+ "thoughts": "도서 관리와 대출/반납은 서로 다른 기능과 데이터를 다루므로 두 개의 Bounded Context로 나누었습니다. 도서 관리는 도서의 등록, 상태 관리, 폐기 처리를 담당하고, 대출/반납은 도서의 대출, 반납, 예약을 관리합니다. 도서 상태 변경은 대출/반납에 의해 영향을 받기 때문에 Customer-Supplier 관계로 설정하였습니다.",
+ "explanations": [
+ {
+ "sourceContext": "대출/반납",
+ "targetContext": "도서 관리",
+ "relationType": "Customer-Supplier",
+ "reason": "대출/반납 시스템이 도서 관리 시스템의 도서 상태 정보를 필요로 하며, 대출 및 반납 시 도서 상태가 변경되기 때문입니다.",
+ "interactionPattern": "Req/Res"
+ }
+ ],
+ "devisionAspect": "거래/성능"
+ },
+ "인프라": {
+ "boundedContexts": [
+ {
+ "name": "BookManagement",
+ "alias": "도서 관리",
+ "aggregates": [
+ {
+ "name": "Book",
+ "alias": "도서"
+ }
+ ],
+ "requirements": [
+ {
+ "type": "userStory",
+ "text": "'도서 관리' 화면에서는 새로운 도서를 등록하고 현재 보유한 도서들의 상태를 관리할 수 있어야 해. 도서 등록 시에는 도서명, ISBN, 저자, 출판사, 카테고리 정보를 입력받아야 해. ISBN은 13자리 숫자여야 하고 중복 확인이 필요해. 카테고리는 소설/비소설/학술/잡지 중에서 선택할 수 있어야 해. 등록된 도서는 처음에 '대출가능' 상태가 되고, 이후 대출/반납 상황에 따라 '대출중', '예약중' 상태로 자동으로 변경되어야 해. 도서가 훼손되거나 분실된 경우 '폐기' 처리가 가능해야 하며, 폐기된 도서는 더 이상 대출이 불가능해야 해."
+ }
+ ]
+ },
+ {
+ "name": "LoanManagement",
+ "alias": "대출/반납",
+ "aggregates": [
+ {
+ "name": "Loan",
+ "alias": "대출"
+ },
+ {
+ "name": "LoanHistory",
+ "alias": "대출 이력"
+ }
+ ],
+ "requirements": [
+ {
+ "type": "userStory",
+ "text": "'대출/반납' 화면에서는 회원이 도서를 대출하고 반납하는 것을 관리할 수 있어야 해. 대출 신청 시에는 회원번호와 이름으로 회원을 확인하고, 대출할 도서를 선택해야 해. 도서는 도서명이나 ISBN으로 검색할 수 있어야 해. 대출 기간은 7일/14일/30일 중에서 선택할 수 있어. 만약 대출하려는 도서가 이미 대출 중이라면, 예약 신청이 가능해야 해. 대출이 완료되면 해당 도서의 상태는 자동으로 '대출중'으로 변경되어야 해."
+ },
+ {
+ "type": "userStory",
+ "text": "대출 현황 화면에서는 현재 대출 중인 도서들의 목록을 볼 수 있어야 해. 각 대출 건에 대해 대출일, 반납예정일, 현재 상태(대출중/연체/반납완료)를 확인할 수 있어야 하고, 대출 중인 도서는 연장이나 반납 처리가 가능해야 해. 도서가 반납되면 자동으로 해당 도서의 상태가 '대출가능'으로 변경되어야 해. 만약 예약자가 있는 도서가 반납되면, 해당 도서는 '예약중' 상태로 변경되어야 해."
+ },
+ {
+ "type": "userStory",
+ "text": "각 도서별로 대출 이력과 상태 변경 이력을 조회할 수 있어야 하고, 이를 통해 도서의 대출 현황과 상태 변화를 추적할 수 있어야 해."
+ }
+ ]
+ }
+ ],
+ "relations": [
+ {
+ "name": "BookLoanManagement",
+ "type": "Customer-Supplier",
+ "upStream": {
+ "name": "BookManagement",
+ "alias": "도서 관리"
+ },
+ "downStream": {
+ "name": "LoanManagement",
+ "alias": "대출/반납"
+ }
+ }
+ ],
+ "thoughts": "도서 관리와 대출/반납 관리는 서로 다른 책임을 가지고 있으며, 높은 응집력과 낮은 결합도를 유지하기 위해 두 개의 Bounded Context로 분리되었습니다. 도서 관리에서는 도서의 등록 및 상태 관리를 담당하고, 대출/반납 관리에서는 대출 및 반납 프로세스를 처리합니다. 두 컨텍스트 간의 관계는 도서 관리가 대출/반납 관리에 필요한 도서 정보를 제공하는 Customer-Supplier 관계로 정의되었습니다.",
+ "explanations": [
+ {
+ "sourceContext": "도서 관리",
+ "targetContext": "대출/반납",
+ "relationType": "Customer-Supplier",
+ "reason": "도서 관리 컨텍스트는 대출/반납 관리 컨텍스트에 도서의 상태 정보를 제공하며, 이는 대출/반납 프로세스에 필수적이기 때문에 Customer-Supplier 관계로 정의되었습니다.",
+ "interactionPattern": "REST API를 통해 도서 상태 정보를 제공하고, 대출/반납 관리에서 이를 활용하여 대출 상태를 업데이트합니다."
+ }
+ ],
+ "devisionAspect": "인프라"
+ }
+}
-각 도서별로 대출 이력과 상태 변경 이력을 조회할 수 있어야 하고, 이를 통해 도서의 대출 현황과 상태 변화를 추적할 수 있어야 해.`
+ const selectedStructureOption = this.resultDevideBoundedContext["도메인"]
- this.state = {
- "generator": "DevideBoundedContextGenerator",
- "firstMessageIsTyping": false,
- "secondMessageIsTyping": false,
- "userStory": "",
- "communicationStyle": "Choreography",
- "aggregateDetail": false,
- "uiStyle": null,
- "startTemplateGenerate": false
-}
+ this.generateAggregateDrafts(selectedStructureOption)
+ },
- const selectedBoundedContext = {
- "boundedContexts": [
- {
- "name": "BookManagement",
- "alias": "도서 관리",
- "aggregates": [
+ _directGenerateFromAggregateDrafts() {
+ const selectedDrafts = {
+ "BookManagement": {
+ "structure": [
{
- "name": "Book",
- "alias": "도서"
+ "aggregate": {
+ "name": "Book",
+ "alias": "도서"
+ },
+ "entities": [],
+ "valueObjects": [
+ {
+ "name": "LoanReference",
+ "alias": "대출 참조",
+ "referencedAggregate": {
+ "name": "Loan",
+ "alias": "대출"
+ }
+ },
+ {
+ "name": "BookCategory",
+ "alias": "도서 카테고리"
+ },
+ {
+ "name": "BookStatus",
+ "alias": "도서 상태"
+ }
+ ]
}
],
- "requirements": "'도서 관리' 화면에서는 새로운 도서를 등록하고 현재 보유한 도서들의 상태를 관리할 수 있어야 해. 도서 등록 시에는 도서명, ISBN, 저자, 출판사, 카테고리 정보를 입력받아야 해. ISBN은 13자리 숫자여야 하고 중복 확인이 필요해. 카테고리는 소설/비소설/학술/잡지 중에서 선택할 수 있어야 해. 등록된 도서는 처음에 '대출가능' 상태가 되고, 이후 대출/반납 상황에 따라 '대출중', '예약중' 상태로 자동으로 변경되어야 해. 도서가 훼손되거나 분실된 경우 '폐기' 처리가 가능해야 하며, 폐기된 도서는 더 이상 대출이 불가능해야 해. 각 도서별로 대출 이력과 상태 변경 이력을 조회할 수 있어야 하고, 이를 통해 도서의 대출 현황과 상태 변화를 추적할 수 있어야 해."
+ "analysis": {
+ "transactionalConsistency": "단일 Aggregate 경계를 통해 강한 일관성을 유지하며 트랜잭션 안전성을 보장",
+ "performanceScalability": "단일 Aggregate 접근으로 단순하지만, 높은 부하에서는 성능 병목이 발생할 가능성 존재",
+ "domainAlignment": "도서 등록 및 관리라는 도메인 목표와 높은 일치도",
+ "maintainability": "구조가 단순하여 유지보수가 용이하나 기능 확장 시 복잡성 증가 가능",
+ "futureFlexibility": "추가 기능 확장에는 구조적 변경이 필요할 수 있음"
+ },
+ "pros": {
+ "cohesion": "도서와 상태 관리에 초점이 맞춰진 높은 응집도",
+ "coupling": "Loan과의 최소 참조를 통해 낮은 결합도",
+ "consistency": "강한 트랜잭션 일관성 제공",
+ "encapsulation": "도서 관련 비즈니스 규칙이 명확히 캡슐화됨",
+ "complexity": "구조가 단순하고 명확함",
+ "independence": "다른 Aggregate와 독립적으로 작동 가능",
+ "performance": "도서 정보와 상태 관리를 단일 Aggregate에서 처리"
+ },
+ "cons": {
+ "cohesion": "모든 도서 상태 관리 규칙을 포함할 경우 응집도가 과도해질 수 있음",
+ "coupling": "Loan과의 참조가 필요",
+ "consistency": "모든 상태 관리 로직이 포함되므로 관리 복잡도 증가 가능",
+ "encapsulation": "상태 변경 규칙이 복잡할 경우 내부 논리 부담 증가",
+ "complexity": "확장 시 복잡도가 증가 가능",
+ "independence": "Loan 정보 없이 도서 상태 관리가 불가능",
+ "performance": "대량 데이터 처리 시 병목 가능"
+ },
+ "isAIRecommended": false,
+ "boundedContext": {
+ "name": "BookManagement",
+ "alias": "도서 관리",
+ "displayName": "도서 관리",
+ "description": [
+ {
+ "type": "userStory",
+ "text": "'도서 관리' 화면에서는 새로운 도서를 등록하고 현재 보유한 도서들의 상태를 관리할 수 있어야 해. 도서 등록 시에는 도서명, ISBN, 저자, 출판사, 카테고리 정보를 입력받아야 해. ISBN은 13자리 숫자여야 하고 중복 확인이 필요해. 카테고리는 소설/비소설/학술/잡지 중에서 선택할 수 있어야 해. 등록된 도서는 처음에 '대출가능' 상태가 되고, 이후 대출/반납 상황에 따라 '대출중', '예약중' 상태로 자동으로 변경되어야 해. 도서가 훼손되거나 분실된 경우 '폐기' 처리가 가능해야 하며, 폐기된 도서는 더 이상 대출이 불가능해야 해."
+ }
+ ],
+ "aggregates": [
+ {
+ "name": "Book",
+ "alias": "도서"
+ }
+ ]
+ },
+ "description": "{\"userStories\":[{\"title\":\"도서 등록\",\"description\":\"도서 관리자 입장에서 새로운 도서를 등록하여 도서 목록을 관리할 수 있어야 한다.\",\"acceptance\":[\"도서명, ISBN, 저자, 출판사, 카테고리 정보를 입력받아야 한다.\",\"ISBN은 13자리 숫자여야 하며 중복 등록이 불가능하다.\",\"카테고리는 소설, 비소설, 학술, 잡지 중 하나를 선택해야 한다.\",\"등록된 도서는 기본적으로 '대출가능' 상태여야 한다.\"]},{\"title\":\"도서 상태 관리\",\"description\":\"도서 관리자 입장에서 대출, 반납, 예약 상태 변경 및 도서 폐기 처리를 통해 도서를 관리할 수 있어야 한다.\",\"acceptance\":[\"도서 상태는 '대출가능', '대출중', '예약중', '폐기' 중 하나여야 한다.\",\"대출 또는 반납 시 상태가 자동으로 업데이트되어야 한다.\",\"폐기된 도서는 대출이 불가능해야 한다.\",\"훼손 또는 분실된 도서는 폐기 처리할 수 있어야 한다.\"]}],\"entities\":{\"Book\":{\"properties\":[{\"name\":\"bookId\",\"type\":\"string\",\"required\":true,\"isPrimaryKey\":true},{\"name\":\"title\",\"type\":\"string\",\"required\":true},{\"name\":\"isbn\",\"type\":\"string\",\"required\":true,\"validation\":\"13자리 숫자\",\"isUnique\":true},{\"name\":\"author\",\"type\":\"string\",\"required\":true},{\"name\":\"publisher\",\"type\":\"string\",\"required\":true},{\"name\":\"category\",\"type\":\"enum\",\"required\":true,\"values\":[\"소설\",\"비소설\",\"학술\",\"잡지\"]},{\"name\":\"status\",\"type\":\"enum\",\"required\":true,\"values\":[\"대출가능\",\"대출중\",\"예약중\",\"폐기\"]}]},\"Loan\":{\"properties\":[{\"name\":\"loanId\",\"type\":\"string\",\"required\":true,\"isPrimaryKey\":true},{\"name\":\"bookId\",\"type\":\"string\",\"required\":true,\"isForeignKey\":true,\"foreignEntity\":\"Book\"},{\"name\":\"loanDate\",\"type\":\"date\",\"required\":true},{\"name\":\"returnDate\",\"type\":\"date\",\"required\":false},{\"name\":\"status\",\"type\":\"enum\",\"required\":true,\"values\":[\"대출중\",\"반납완료\",\"예약중\"]}]},\"businessRules\":[{\"businessRulesThoughts\":{\"summary\":\"ISBN 유효성 검증 규칙\",\"details\":{\"validationComplexity\":\"간단한 형식 및 중복 체크\",\"businessImpact\":\"데이터의 무결성 유지\",\"maintainability\":\"추가 ISBN 형식이 생길 경우 확장 가능\"},\"additionalConsiderations\":\"ISBN의 글로벌 규격 준수 여부 확인 필요\"},\"name\":\"ISBNValidation\",\"description\":\"ISBN은 13자리 숫자여야 하며 중복 등록이 불가능하다.\"},{\"businessRulesThoughts\":{\"summary\":\"도서 상태 전환 규칙\",\"details\":{\"validationComplexity\":\"자동 상태 전환 로직 구현\",\"businessImpact\":\"도서 관리 프로세스 간소화\",\"maintainability\":\"상태 추가 시 업데이트 필요\"},\"additionalConsiderations\":\"상태 전환 시 데이터 변경 기록 유지 필요\"},\"name\":\"BookStatusChange\",\"description\":\"대출, 반납, 예약 상황에 따라 도서 상태가 자동으로 변경되어야 한다.\"},{\"businessRulesThoughts\":{\"summary\":\"폐기 도서 대출 제한 규칙\",\"details\":{\"validationComplexity\":\"간단한 상태 조건 체크\",\"businessImpact\":\"대출 관리 정확성 향상\",\"maintainability\":\"규칙 자체는 유지보수가 용이\"},\"additionalConsiderations\":\"폐기된 도서 데이터의 명확한 구분 필요\"},\"name\":\"DiscardedBookRestriction\",\"description\":\"폐기된 도서는 대출이 불가능해야 한다.\"}],\"interfaces\":{\"BookManagement\":{\"interfaceThoughts\":{\"summary\":\"도서 관리 인터페이스\",\"details\":{\"usability\":\"간단하고 명확한 입력 폼 제공\",\"dataFlow\":\"도서 등록 및 상태 업데이트를 지원\",\"responsiveness\":\"빠른 상태 전환 및 데이터 저장 가능\"},\"additionalConsiderations\":\"도서 상태 변경에 대한 실시간 업데이트 필요\"},\"sections\":[{\"name\":\"BookRegistration\",\"type\":\"form\",\"fields\":[{\"name\":\"title\",\"type\":\"text\",\"required\":true},{\"name\":\"isbn\",\"type\":\"text\",\"required\":true},{\"name\":\"author\",\"type\":\"text\",\"required\":true},{\"name\":\"publisher\",\"type\":\"text\",\"required\":true},{\"name\":\"category\",\"type\":\"select\",\"required\":true,\"values\":[\"소설\",\"비소설\",\"학술\",\"잡지\"]}],\"actions\":[\"Submit\",\"Clear\"]},{\"name\":\"BookStatusManagement\",\"type\":\"table\",\"fields\":[{\"name\":\"bookId\",\"type\":\"text\",\"required\":true},{\"name\":\"title\",\"type\":\"text\",\"required\":true},{\"name\":\"status\",\"type\":\"select\",\"required\":true,\"values\":[\"대출가능\",\"대출중\",\"예약중\",\"폐기\"]}],\"actions\":[\"UpdateStatus\",\"Discard\"]}]}}}}"
},
- {
- "name": "LoanManagement",
- "alias": "대출/반납 관리",
- "aggregates": [
+ "LoanManagement": {
+ "structure": [
{
- "name": "Loan",
- "alias": "대출"
- },
- {
- "name": "Member",
- "alias": "회원"
+ "aggregate": {
+ "name": "Loan",
+ "alias": "대출"
+ },
+ "entities": [
+ {
+ "name": "LoanDetail",
+ "alias": "대출 세부 정보"
+ }
+ ],
+ "valueObjects": [
+ {
+ "name": "Member",
+ "alias": "회원"
+ },
+ {
+ "name": "BookReference",
+ "alias": "도서 참조",
+ "referencedAggregate": {
+ "name": "Book",
+ "alias": "도서"
+ }
+ },
+ {
+ "name": "LoanStatus",
+ "alias": "대출 상태"
+ }
+ ]
}
],
- "requirements": "'대출/반납' 화면에서는 회원이 도서를 대출하고 반납하는 것을 관리할 수 있어야 해. 대출 신청 시에는 회원번호와 이름으로 회원을 확인하고, 대출할 도서를 선택해야 해. 도서는 도서명이나 ISBN으로 검색할 수 있어야 해. 대출 기간은 7일/14일/30일 중에서 선택할 수 있어. 만약 대출하려는 도서가 이미 대출 중이라면, 예약 신청이 가능해야 해. 대출이 완료되면 해당 도서의 상태는 자동으로 '대출중'으로 변경되어야 해. 대출 현황 화면에서는 현재 대출 중인 도서들의 목록을 볼 수 있어야 해. 각 대출 건에 대해 대출일, 반납예정일, 현재 상태(대출중/연체/반납완료)를 확인할 수 있어야 하고, 대출 중인 도서는 연장이나 반납 처리가 가능해야 해. 도서가 반납되면 자동으로 해당 도서의 상태가 '대출가능'으로 변경되어야 해. 만약 예약자가 있는 도서가 반납되면, 해당 도서는 '예약중' 상태로 변경되어야 해."
- }
- ],
- "relations": [
- {
- "name": "BookLoanStatusUpdate",
- "type": "Customer-Supplier",
- "upStream": "BookManagement",
- "downStream": "LoanManagement"
- }
- ],
- "thoughts": "도서 관리와 대출/반납 관리는 서로 다른 업무 전문성을 가지고 있으며, 도서의 상태 관리와 대출 프로세스는 각각의 응집도가 높은 기능이다. 두 컨텍스트는 도서의 상태 변경을 통해 연결되므로 Customer-Supplier 관계로 설정하였다.",
- "explanations": [
- {
- "sourceContext": "BookManagement",
- "targetContext": "LoanManagement",
- "relationType": "Customer-Supplier",
- "reason": "도서 관리 시스템은 도서의 상태를 관리하고, 대출/반납 시스템은 그 상태를 기반으로 대출 프로세스를 관리한다. 따라서 도서 관리 시스템이 상위 시스템으로서 도서 상태 정보를 제공한다.",
- "interactionPattern": "도서 상태 변경 시 이벤트를 발행하고, 대출/반납 시스템은 이를 구독하여 상태를 업데이트한다."
+ "analysis": {
+ "transactionalConsistency": "단일 Aggregate 경계 내에서 강한 일관성을 유지하여 대출 생명 주기를 원자적으로 처리",
+ "performanceScalability": "기본 작업에 대해 좋은 성능을 제공하지만 복잡한 쿼리에서는 확장성 문제 발생 가능",
+ "domainAlignment": "핵심 대출 도메인 개념 및 비즈니스 규칙과 밀접하게 정렬됨",
+ "maintainability": "단순한 구조로 유지보수가 용이하지만 기능이 증가함에 따라 복잡성이 증가할 가능성 있음",
+ "futureFlexibility": "구조적 변경 없이 광범위한 기능 추가에 제한적"
+ },
+ "pros": {
+ "cohesion": "대출 중심의 높은 응집성",
+ "coupling": "ValueObject 참조를 통해 낮은 결합도",
+ "consistency": "대출 경계 내에서 강한 일관성",
+ "encapsulation": "잘 캡슐화된 대출 로직",
+ "complexity": "단순하고 직관적인 구조",
+ "independence": "Member 및 Book과 독립적으로 발전 가능",
+ "performance": "효율적인 대출 작업"
+ },
+ "cons": {
+ "cohesion": "대출 기능이 증가할 경우 분할 필요",
+ "coupling": "Member 및 Book Aggregate에 의존",
+ "consistency": "세심한 트랜잭션 관리 필요",
+ "encapsulation": "일부 대출 규칙이 UI로 누출될 가능성",
+ "complexity": "참조 동기화 관리 필요",
+ "independence": "Member 및 Book 없이 작동 불가",
+ "performance": "전체 대출 정보를 위해 다중 Aggregate 조회 필요"
+ },
+ "isAIRecommended": false,
+ "boundedContext": {
+ "name": "LoanManagement",
+ "alias": "대출/반납",
+ "displayName": "대출/반납",
+ "description": [
+ {
+ "type": "userStory",
+ "text": "'대출/반납' 화면에서는 회원이 도서를 대출하고 반납하는 것을 관리할 수 있어야 해. 대출 신청 시에는 회원번호와 이름으로 회원을 확인하고, 대출할 도서를 선택해야 해. 도서는 도서명이나 ISBN으로 검색할 수 있어야 해. 대출 기간은 7일/14일/30일 중에서 선택할 수 있어. 만약 대출하려는 도서가 이미 대출 중이라면, 예약 신청이 가능해야 해. 대출이 완료되면 해당 도서의 상태는 자동으로 '대출중'으로 변경되어야 해. 대출 현황 화면에서는 현재 대출 중인 도서들의 목록을 볼 수 있어야 해. 각 대출 건에 대해 대출일, 반납예정일, 현재 상태(대출중/연체/반납완료)를 확인할 수 있어야 하고, 대출 중인 도서는 연장이나 반납 처리가 가능해야 해. 도서가 반납되면 자동으로 해당 도서의 상태가 '대출가능'으로 변경되어야 해. 만약 예약자가 있는 도서가 반납되면, 해당 도서는 '예약중' 상태로 변경되어야 해. 각 도서별로 대출 이력과 상태 변경 이력을 조회할 수 있어야 하고, 이를 통해 도서의 대출 현황과 상태 변화를 추적할 수 있어야 해."
+ }
+ ],
+ "aggregates": [
+ {
+ "name": "Loan",
+ "alias": "대출"
+ },
+ {
+ "name": "Reservation",
+ "alias": "예약"
+ }
+ ]
+ },
+ "description": "{\"userStories\":[{\"title\":\"도서 대출 신청\",\"description\":\"회원으로서 내가 도서를 대출하고 싶다. 그래서 내가 원하는 책을 읽을 수 있다.\",\"acceptance\":[\"회원번호와 이름을 입력하여 회원을 확인할 수 있어야 한다.\",\"대출할 도서를 도서명이나 ISBN으로 검색하여 선택할 수 있어야 한다.\",\"대출 기간은 7일, 14일, 30일 중 선택할 수 있어야 한다.\",\"이미 대출 중인 도서는 예약 신청이 가능해야 한다.\",\"대출 완료 시 도서 상태는 '대출중'으로 변경되어야 한다.\"]},{\"title\":\"대출 도서 관리\",\"description\":\"회원으로서 내가 대출 중인 도서를 확인하고 연장하거나 반납하고 싶다. 그래서 대출 상태를 관리할 수 있다.\",\"acceptance\":[\"대출일, 반납 예정일, 상태(대출중/연체/반납완료)를 확인할 수 있어야 한다.\",\"대출 중인 도서는 연장하거나 반납할 수 있어야 한다.\",\"반납 완료 시 도서 상태는 '대출가능'으로 변경되어야 한다.\",\"예약자가 있는 도서가 반납되면 상태는 '예약중'으로 변경되어야 한다.\"]},{\"title\":\"도서 이력 조회\",\"description\":\"도서관 직원으로서 내가 특정 도서의 대출 이력과 상태 변경 이력을 조회하고 싶다. 그래서 도서의 상태 변화를 추적할 수 있다.\",\"acceptance\":[\"도서별 대출 이력과 상태 변경 이력을 확인할 수 있어야 한다.\",\"대출 현황과 상태 변화가 명확히 표시되어야 한다.\"]}],\"entities\":{\"Member\":{\"properties\":[{\"name\":\"memberId\",\"type\":\"string\",\"required\":true,\"isPrimaryKey\":true},{\"name\":\"name\",\"type\":\"string\",\"required\":true},{\"name\":\"phoneNumber\",\"type\":\"string\",\"required\":true},{\"name\":\"email\",\"type\":\"string\",\"required\":true}]},\"Book\":{\"properties\":[{\"name\":\"bookId\",\"type\":\"string\",\"required\":true,\"isPrimaryKey\":true},{\"name\":\"title\",\"type\":\"string\",\"required\":true},{\"name\":\"isbn\",\"type\":\"string\",\"required\":true},{\"name\":\"status\",\"type\":\"enum\",\"required\":true,\"values\":[\"대출가능\",\"대출중\",\"연체\",\"예약중\"]},{\"name\":\"history\",\"type\":\"list\",\"required\":false}]}},\"businessRules\":[{\"name\":\"ValidLoanStatus\",\"description\":\"대출하려는 도서가 '대출가능' 상태여야 대출 가능\"},{\"name\":\"ReturnBookStatusUpdate\",\"description\":\"반납 시 예약자가 있으면 도서 상태는 '예약중', 예약자가 없으면 '대출가능'으로 변경\"}],\"interfaces\":{\"LoanReturn\":{\"sections\":[{\"name\":\"LoanRequest\",\"type\":\"form\",\"fields\":[{\"name\":\"memberId\",\"type\":\"text\",\"required\":true},{\"name\":\"name\",\"type\":\"text\",\"required\":true},{\"name\":\"bookSearch\",\"type\":\"search\",\"required\":true},{\"name\":\"loanPeriod\",\"type\":\"select\",\"required\":true,\"values\":[\"7일\",\"14일\",\"30일\"]}],\"actions\":[\"Submit\",\"Clear\"]},{\"name\":\"LoanStatus\",\"type\":\"table\",\"fields\":[{\"name\":\"loanDate\",\"type\":\"date\",\"required\":true},{\"name\":\"returnDueDate\",\"type\":\"date\",\"required\":true},{\"name\":\"status\",\"type\":\"enum\",\"required\":true,\"values\":[\"대출중\",\"연체\",\"반납완료\"]}],\"actions\":[\"Extend\",\"Return\"]}]}}}"
}
- ],
- "devisionAspect": "조직적"
-}
+ }
+
+ this.value.userStory = `도서관의 도서 관리와 대출/반납을 통합적으로 관리하는 화면을 만들려고 해.
+
+'도서 관리' 화면에서는 새로운 도서를 등록하고 현재 보유한 도서들의 상태를 관리할 수 있어야 해. 도서 등록 시에는 도서명, ISBN, 저자, 출판사, 카테고리 정보를 입력받아야 해. ISBN은 13자리 숫자여야 하고 중복 확인이 필요해. 카테고리는 소설/비소설/학술/잡지 중에서 선택할 수 있어야 해. 등록된 도서는 처음에 '대출가능' 상태가 되고, 이후 대출/반납 상황에 따라 '대출중', '예약중' 상태로 자동으로 변경되어야 해. 도서가 훼손되거나 분실된 경우 '폐기' 처리가 가능해야 하며, 폐기된 도서는 더 이상 대출이 불가능해야 해.
+
+'대출/반납' 화면에서는 회원이 도서를 대출하고 반납하는 것을 관리할 수 있어야 해. 대출 신청 시에는 회원번호와 이름으로 회원을 확인하고, 대출할 도서를 선택해야 해. 도서는 도서명이나 ISBN으로 검색할 수 있어야 해. 대출 기간은 7일/14일/30일 중에서 선택할 수 있어. 만약 대출하려는 도서가 이미 대출 중이라면, 예약 신청이 가능해야 해. 대출이 완료되면 해당 도서의 상태는 자동으로 '대출중'으로 변경되어야 해.
+
+대출 현황 화면에서는 현재 대출 중인 도서들의 목록을 볼 수 있어야 해. 각 대출 건에 대해 대출일, 반납예정일, 현재 상태(대출중/연체/반납완료)를 확인할 수 있어야 하고, 대출 중인 도서는 연장이나 반납 처리가 가능해야 해. 도서가 반납되면 자동으로 해당 도서의 상태가 '대출가능'으로 변경되어야 해. 만약 예약자가 있는 도서가 반납되면, 해당 도서는 '예약중' 상태로 변경되어야 해.
+
+각 도서별로 대출 이력과 상태 변경 이력을 조회할 수 있어야 하고, 이를 통해 도서의 대출 현황과 상태 변화를 추적할 수 있어야 해.`
+
+ this.state = {
+ "generator": "DevideBoundedContextGenerator",
+ "firstMessageIsTyping": false,
+ "secondMessageIsTyping": false,
+ "userStory": "",
+ "communicationStyle": "Choreography",
+ "aggregateDetail": false,
+ "uiStyle": null,
+ "startTemplateGenerate": false
+ }
- this.jump(selectedBoundedContext)
+ this.generateFromDraftWithXAI(selectedDrafts)
}
}
}