From 4cb994cdbc4d3c396d4b9e50f7c7128f940fb218 Mon Sep 17 00:00:00 2001 From: "DESKTOP-KUL8TT4\\siina" Date: Fri, 30 Aug 2024 11:44:03 +0900 Subject: [PATCH] =?UTF-8?q?pbp-cs=20=ED=94=84=EB=A1=9C=EC=84=B8=EC=8A=A4?= =?UTF-8?q?=20=EC=A0=95=EB=A6=AC=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- quantec/cs/quantecAllTask/README.md | 386 ++++++++++++++++++ quantec/cs/quantecComponents/README.md | 18 + quantec/cs/quantecContract/README.md | 213 ++++++++++ quantec/cs/quantecHanaMTS/README.md | 7 + quantec/cs/quantecLogin/README.md | 37 ++ quantec/cs/quantecSampleData/README.md | 7 + .../quantecAssetAnalysis/README.md | 0 .../240821_PB플랫폼 수정요청_리포트.pptx | Bin quantec/{cs => pbp}/quantecReport/README.md | 2 + quantec/{cs => pbp}/quantecReport/image-1.png | Bin quantec/{cs => pbp}/quantecReport/image-2.png | Bin quantec/{cs => pbp}/quantecReport/image-3.png | Bin quantec/{cs => pbp}/quantecReport/image.png | Bin 13 files changed, 670 insertions(+) create mode 100644 quantec/cs/quantecAllTask/README.md create mode 100644 quantec/cs/quantecComponents/README.md create mode 100644 quantec/cs/quantecHanaMTS/README.md create mode 100644 quantec/cs/quantecLogin/README.md create mode 100644 quantec/cs/quantecSampleData/README.md rename quantec/{cs => pbp}/quantecAssetAnalysis/README.md (100%) rename quantec/{cs => pbp}/quantecReport/240821_PB플랫폼 수정요청_리포트.pptx (100%) rename quantec/{cs => pbp}/quantecReport/README.md (99%) rename quantec/{cs => pbp}/quantecReport/image-1.png (100%) rename quantec/{cs => pbp}/quantecReport/image-2.png (100%) rename quantec/{cs => pbp}/quantecReport/image-3.png (100%) rename quantec/{cs => pbp}/quantecReport/image.png (100%) diff --git a/quantec/cs/quantecAllTask/README.md b/quantec/cs/quantecAllTask/README.md new file mode 100644 index 0000000..ec30d2d --- /dev/null +++ b/quantec/cs/quantecAllTask/README.md @@ -0,0 +1,386 @@ +# PBP-CS 모든 프로세스 모음 + +> 개발 도중 프로세스 및 코드에 대한 이해도가 낮은 이유로 개발이 어려움을 느끼며 차후 개발에서 개발 속도 및 변경 부작용을 없애고 이해도를 높이고자 이 문서를 작성함 + +

+ +### 2024-08-29 (현 하나증권 중심) + +**공병훈 교수**{style="font-style:italic"}는 플랫폼이란 "서로 연결된 관계를 맺으며 가치를 만드는 체계"라는 표현을 사용하였다. 상호의존적인 관계를 형성하며 서로 다른 그룹들간의 상호작요을 쉽게 하여 가치를 창조한다. +플랫폼에 대한 자세한 내용은 다음 링크로 확인하면 좋다. + + +


+ +## Login -> Assets + +> [로그인]페이지에서 [내 자산]으로 화면이 넘아갈때의 프로세스를 아래 기술한다. + +```mermaid +flowchart LR + Login --> Assets +``` + +### - Login + +```mermaid +--- +title: src/app/login/page.tsx +--- +classDiagram + class Login{ + param: ref, sccofnstcd + } + class LoginTask{ + onConfirm?(bool: boolean): void; // 로그 인 완료 + } + class CookieInfo{ + } + class Spinner{ + } + Login *-- LoginTask : Component + Login *-- CookieInfo : Component + Login *-- Spinner : Component + Login <-- LoginTask : onConfirmLogin +``` + +

+ +- 로그인 페이지에서 URL파라미터 증권사코드 sccoFnstCd값 받아서 처리 +
<예)"270 (하나증권)">
+그리고 증권사코드를 localStorage에 저장 저장하는 키는 각 2개임 +
accessKey, everywhereKey
accessKey는 웹뷰용 접근 증권사 코드, +everywhereKey는 전방위용 접근 증권사 코드 라고한다... + +```javascript + if (sccoFnstCd) { + localStorage.setItem(accessKey, sccoFnstCd.toString()); + localStorage.setItem(everywhereKey, sccoFnstCd.toString()); + } else { + localStorage.setItem(accessKey, ''); + localStorage.setItem(everywhereKey, ''); + } +``` + +> ISSUE: 간헐적 백엔드에 270값 안 넘오는 현상 발견됨 + +- onConfirmLogin 함수에서는 LoginTask의 onConfirm에 함수 제공. +

+ +```javascript +const onConfirmLogin = () => { + if (ref !== null && ref !== undefined && ref !== '') { + router.push(ref); + return; + } + router.push('/assets'); + } +``` + +위의 onConfirmLogin에서 브라우저 url param의 ref를 받아서 유무 처리 후 route 처리. + +** 결론적으로 Login 페이지에서 sccoFnstCd(증권사코드)를 localStorage 처리, route처리 하는 기능. {style="color:red"} + +

+ +```mermaid +classDiagram + class LoginTask{ + counselSeq?: number; + onConfirm?(bool: boolean): void; // 로그 인 완료 + onBack?(): void; // 화면뒤로 + isTest?: boolean; + isMTS?: boolean; + ----------default set------ + isTest = false, isMTS = false + } +``` + +

+ +```mermaid +--- +title: src/components/task/login/LoginTask.tsx +--- +classDiagram + class LoginTask{ + } + class AlertModal{ + } + class PinNumberLoginTask{ + onConfirm(): void; + onBack(): void; + onLoginFail(bool: boolean, idx: number): void; + isMTS: boolean; + } + class ReSignupProcess{ + onConfirm, + onClose, + isDeviceChange = false, + FailCount, + isPasswordInput = false + } + class SignupProcess{ + counselSequence?: string; + onConfirm?(loginCustomerId: string): void; + onClose?(): void; + onBack?(): void; + } + + LoginTask --> PinNumberLoginTask : 1) defaultLoginOption === 'pinnumber'
&& !loginFail
&& !isTest
&& !isNewUser + + LoginTask --> ReSignupProcess : 2) loginFail
&& !isTest + + LoginTask --> SignupProcess : 3) isNewUser + + PinNumberLoginTask --> LoginTask : 4) onConfirmLogin()
onLoginFail() +``` + +

+ +- isTest가 왜 존재 하는지? (true로 변경시 빈화면 나오게 됨) +- defaultLoginOption = process.env.NEXT_PUBLIC_DEFAULT_LOGIN_VIEW +
# 간편비밀번호 사용 여부 pinnumber or password +
NEXT_PUBLIC_DEFAULT_LOGIN_VIEW=pinnumber | password +
현재는 pinnumber + +- 위의 1), 2), 3)을 하나의 함수로 처리하는게 좋을듯 하다. + +4) localStorage의 'KEY'를 가져와서 `getUser` 함수 실행 + +


+ +#### PinNumberLoginTask로 로그인이 되었을때 + +```javascript +const onConfirmLogin = async () => { + const user = localStorage.getItem(KEY); + + if (user) { + const decodeUser = decodeAES(user); + await getUser(decodeUser); + } else { + setAlertModal({ + title: '로그인 실패', + content: ( + <> + 아이디가 없습니다. 회원가입을 안하셨다면 회원가입을 하시거나
사용 기기를 변경하셨다면
본인 + 인증을 해주신 후
로그인을 시도 해주세요. + + ) + }); + } + }; +``` + +```javascript +const getUser = useCallback( + async (customerId: string) => { + setIsLoading(true); + const customer = await getUserInfoApi({ + customerId, + sccoFnstCd: '', + role: '' + }); + setIsLoading(false); + + if (isEmptyString(customer.userId)) { + const msg = `LocalStorage에 아이디가 존재하고, 간편비밀번호 로그인에 성공했지만, DB에 회원정보가 없음(${customerId})`; + commonRecordingLog(recoilFrontEndLog, 'LoginTask', 'api', msg); + setAlertModal({ + title: '로그인 실패', + content: '회원정보를 가져올 수 없습니다.\n회원가입을 다시 해주세요.' + }); + } else { + await fetch('/api/setSessions', { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({customerId: customer.userId, sccoFnstCd}) + }); + + if (fristLoginValue === null || fristLoginValue === undefined) { + if (customer.pushStatusDate !== null && customer.pushStatusDate !== undefined) { + if (customer.pushStatus === '01') { + setToastMessage([ + { + id: getUniqueKey(), + text: `${moment(customer.pushStatusDate).format( + 'YYYY.MM.DD HH:mm' + )} 이벤트*혜택 알림 수신에 동의하셨습니다.`, + bottom: 70 + } + ]); + } else { + setToastMessage([ + { + id: getUniqueKey(), + text: `${moment(customer.pushStatusDate).format( + 'YYYY.MM.DD HH:mm' + )} 이벤트*혜택 알림 수신에 거부하셨습니다.`, + bottom: 70 + } + ]); + } + } + localStorage.setItem(firstLoginKey, 'Y'); + } + + setLoginState(customer); + setUserId(customerId || ''); + const encodeId = encodeAES(customerId); + + localStorage.setItem(KEY, encodeId); + onConfirm?.(true); + } + }, + [ + setIsLoading, + recoilFrontEndLog, + setAlertModal, + sccoFnstCd, + fristLoginValue, + setLoginState, + setUserId, + KEY, + onConfirm, + firstLoginKey, + setToastMessage + ] + ); +``` + +

+getUserInfoApi API를 호출함 getUserInfo의 내용에 많은 정보가 기록되어 있는 것을 알 수 있음 + +```javascript +export const getUserInfoApi = async (obj: IUserInfoInput): Promise => { + return api.get('/customer', {customerId: obj.customerId}); +}; +``` + +```javascript +export interface IUserInfoInput { + customerId?: string; + sccoFnstCd: string; + ci?: string; + userId?: string; + role: string; +} + +export interface IUserInfoOutput { + sccoFnstCd: string; // * 23.11.10 ADD yeong + securitiesName: string; // * 23.11.10 ADD yeong + userId: string; + ci: string; + di: string; + password: string; + mobileNumber: string; + birth: string; + gender: number; + email: string; + osType?: string; + osPlatform?: string; + roles?: string; + token?: string; + appVersion?: string; + userLevel?: string; + userName: string; + nickName?: string; + activeStep: string; + joinDate?: string; + lastDate?: string; + authCode?: string; + passwordErrorCount: number; + passwordDate: string; + investmentPropensity: InvestmentPropensity; // * 23.11.10 ADD yeong + customerStatusCode: string; // * 23.11.10 ADD yeong + pushStatus: string; // 01 등록, 02 해제 + pushStatusDate: string; +} + + +``` + +

+정치영팀장의 계정으로 접속하였을때 아래의 값을 출력함 + +```json +{ + "securitiesName": "하나증권", + "userId": "5000001008", + "userName": "정치영", + "mobileNumber": "01051670729", + "birth": "19790417", + "gender": 1, + "email": null, + "sccoCustomerIdentifyId": null, + "remarks": null, + "passwordErrorCount": 0, + "passwordDate": "2024-08-21 10:51:34", + "activeStep": "20", + "investmentPropensity": { + "investmentPropensityCode": "1", + "investmentPropensity": "공격투자형", + "lastSurveyDate": "20240826", + "remainingDateCount": 361, + "validYn": "Y", + "todayTryCount": 0 + }, + "pushStatus": "01", + "pushStatusDate": "2024-08-13 14:28:51" +} + +``` + +- getUserInfoApi의 결과 값을 /api/setSessions로 전달하여 내용을 저장 +- getUser함수에서 성공하면 LoginTask의 onConfirm을 Login의 onConfirmLogin으로 true를 전달한다. + +```mermaid + +flowchart LR + node_1("LoginTask") + node_2("Login") + node_1 --"onConfirm={true}"--> node_2 + +``` + +Login에 있는 onConfirmLogin을 실행함으로써 /assets으로 route하게됨 + +

+ +### - Assets + +```mermaid +--- +title: src/app/assets/page.tsx +--- +classDiagram + class Assets{ + + } + class AssetMain{ + + } + class Spinner{ + + } + class CookieInfo{ + + } + class Navigation{ + + } + class RequestReplyTask{ + + } + + Assets *-- AssetMain + Assets *-- Spinner + Assets *-- CookieInfo + Assets *-- AssetMain + Assets *-- Navigation + Assets *-- RequestReplyTask + +``` + +

diff --git a/quantec/cs/quantecComponents/README.md b/quantec/cs/quantecComponents/README.md new file mode 100644 index 0000000..c81469e --- /dev/null +++ b/quantec/cs/quantecComponents/README.md @@ -0,0 +1,18 @@ +```mermaid + classDiagram + class Login{ + param: ref, sccofnstcd + } + class LoginTask{ + counselSeq?: number; + onConfirm?(bool: boolean): void; // 로그 인 완료 + onBack?(): void; // 화면뒤로 + isTest?: boolean; + isMTS?: boolean; + } + class CookieInfo{ + } + class Spinner{ + } + +``` diff --git a/quantec/cs/quantecContract/README.md b/quantec/cs/quantecContract/README.md index f3a7492..aaa083d 100644 --- a/quantec/cs/quantecContract/README.md +++ b/quantec/cs/quantecContract/README.md @@ -60,6 +60,10 @@ CS 로그인 정보 +USERID_INDEX_20231118 + +정치영팀장 U2FsdGVkX19+ppz/We/H+2mKzTSmj3vA2PwN3pOVjYQ= + ```json { "origin": "http://localhost:3200", @@ -790,3 +794,212 @@ module.exports = { ### 약관 변경 사항 (24-08-23 11:30) > > 정BJ: 로그인시 팝업으로 뜨는 변경약관 동의는 이제 "필수"이다 이걸 동의하지 않는다면 서비스를 사용할 수 없다. + +### HAZELCAST 캐시화된 DB 캐시 Clear + +클네임:hazelcast-cluster-dev + +210.179.172.127:5050 + +### 업무 2024-08-27 + +`/terms/product/roboadvisor` API는 [GET] [POST] 사용이 필요 없어짐 + +로보어드바이저 투자일임계약 약관 등록은 투자 일음 계약서에 포함되어 있기 때문에 따로 필요 없음 기존의 일임계약서를 대체함 + +가입시 +`/goods/portfolio/investPortfolio`오류.. + +"해당 계좌는 사용할 수 없는 계좌입니다." + +이건 InvestTask.tsx의 investResult의 변수값을 저 위의 api에 던짐 + +getUserId `/user/id` + +```json +{ + "value": "5000003080", + "success": true +} + +``` + +```json +{ + "investDivType": "", + "inputDivType": "02", + "account": "39784625010", + "portfolioId": null, + "portfolioName": "김익희님의 포트폴리오 20240827-1619", + "referencePortfolioId": null, + "counselSeq": null, + "strategyId": "", + "totalInvestAmount": 20000000, + "totalUsdInvestAmount": 0, + "strategyList": [ + { + "strategyId": "KP014NaN", + "investAmount": 20000000, + "investmentWeight": 1 + } + ], + "descriptionAgreeSeq": 630, + "investmentTypeDvsn": "01", + "contractAgreeSeq": 631 +} + +```` + +api_mpot에서 + +TC_USER_ACCOUNT의 + +UID = 5000003080 + +REQUEST_STATUS_CODE 01 ---> 03 + +QTDB에서 TC5002MT 테이블에 + +270 39784625010 Y 20240826184739 100159 2024-02-01 15:48:54.000 + +이거 생성함 + +가입이 완료되면 포트폴리오는 +TP0010MT에 정보 생성함 + +하지만 그 생성하는 과정에서 하나증권 api를 타기 때문에 실패! + +


+ +### 업무 2024-08-27 + +assetMain에서 모든 계좌에 가입되어 있는 포트폴리오가지고 +포트폴리오를 조회해서 +포트폴리오의 투자 문서를 가져올꺼임 + +portfolioDetail에서 onClickInvestmentDocs를 보면 setInvestmentDocsData에 + +```javascript + + ptflId: portfolio.portfolioId, + buyDate: portfolioDetail?.accountPortfolioDetailInfo[0].firstDate || '', + type: '3', // 보고서 타입 [1:보고서리스트,2:보고서상세] + year: '', + quarter: '', + account: portfolio.accountNo + +``` + +이런식으로 데이터 만들어서 +InvestmentDocsTask에 값을 보내고 있음 + +그리고 각각 InvestmentDoc, StrategyDoc, DiscretionaryContractDoc, OperationaryReportDoc로 보내서 가입시 동의 또는 운영시 작성된 약관, 리포트 리스트를 보여줌 + +```javascript +/** + * Get 전략 설명서 + * @returns + * @param params + */ +export const getInvestmentStrategyReport = async ( + params: IInvestmentStrategyCommonParam +): Promise => { + return api.get('/doc/strategy', params); +}; + +/** + * Get 운용 보고서 + * @returns + * @param params + */ +export const getInvestmentOperationReport = async ( + params: IOperationParams +): Promise => { + return api.get('/doc/report/operation', params); +}; + +/** + * Get 일임 계약서 + * @returns + * @param params + */ +export const getInvestmentContractReport = async ( + params: IInvestmentDiscretionaryDocParams +): Promise => { + return api.get('/doc/discretion', params); +}; + +``` + +위의 api로 문서 호출 + +```json +// PortfolioDetailData +{ + "portfolioName": "정치영님의 포트폴리오 20240807-1603", + "portfolioDesc": null, + "chartDataModelList": [ + { + "x": "20240807", + "y": 0, + "marker": [] + } + ], + "strategyCount": 1, + "accountPortfolioStrategyOperationInfo": { + "investAmount": 2000000, + "totalProfitAndLossAmount": 0, + "valueAmount": 2000000, + "rate": 0 + }, + "accountPortfolioDetailInfo": [ + { + "portfolioId": 360, + "portfolioName": "정치영님의 포트폴리오 20240807-1603", + "strategyId": "KP0132", + "strategyName": "멀티팩터의 교향곡을 만드는 종목", + "firstDate": "20240807", + "investmentPropensityCode": "3", + "investmentPropensity": "위험중립형", + "strategyTitle": "콴텍 Q-Growth 국내 주식", + "globalType": "1", + "weight": 100, + "itype": "1", + "strategyStatusCode": "A", + "strategyStatusName": "활성화", + "reservationOrderTypeCode": null, + "reservationOrderTypeName": "해지", + "reservationStatusCode": null, + "reservationStatusName": "주문실패", + "weightRate": 1, + "minimumInvestmentAmount": 1500000, + "firstInvestAmount": 2000000, + "addInvestAmount": 0, + "investAmount": 2000000, + "valueAmount": 2000000, + "rate": 0, + "activeStatusCode": "4", + "activeStatusName": "운용중" + } + ], + "strategyAssetsRateResultList": null, + "accountStrategyFirstDateCalEtcInfo": null, + "managementPlan": null, + "managementAlgorithmName": null, + "managementAlgorithmRate": null, + "managementAlgorithmUniverse": null, + "managementAlgorithmBenchmark": null, + "managementAlgorithmCoreFector": null, + "managementAlgorithmStyle": null, + "managementAlgorithmRiskManagement": null +} +``` + +이렇게 조회했을때 firstDate가 있으니까 이 부분을 이용해서 + +firstDate가 있으니까 이것을 기준으로 TP0015MT의 LAST_WRK_DTM이 앞서면 + +firstDate < LAST_WRK_DTM 되어 있다면 DB에 있는 약관이 가입한 포트폴리오보다 최신이라는 뜻이 되니까 변경된 약관 동의를 출력 + +### 업무 2024-08-29 + diff --git a/quantec/cs/quantecHanaMTS/README.md b/quantec/cs/quantecHanaMTS/README.md new file mode 100644 index 0000000..e63fc86 --- /dev/null +++ b/quantec/cs/quantecHanaMTS/README.md @@ -0,0 +1,7 @@ +# TEST_하나증권_MTS입점(NEW) + +> Q. 하나증권에 계좌가 없는 준회원이다. ci값은 안넘어 올 수 있는데 이경우 콴텍 전략 마켓은 열어주기로 했다는데 해당 메시지는 화면에서 표시되는건가요? 아니면 백엔드 api? +> +> W. 준회원의 의미는 하나증권MTS 회원인데 계좌가 없다는 뜻? +> +> diff --git a/quantec/cs/quantecLogin/README.md b/quantec/cs/quantecLogin/README.md new file mode 100644 index 0000000..4e5b0c0 --- /dev/null +++ b/quantec/cs/quantecLogin/README.md @@ -0,0 +1,37 @@ +## PBP-CS 로그인 + +#### 1.TaskProcess +> + +```mermaid +classDiagram + class Browser{ + } + + class Login{ + sccofnstcd: url param; + } + class LoginTask{ + counselSeq?: number; + onConfirm?(bool: boolean): void; // 로그 인 완료 + isTest?: boolean; + isMTS?: boolean; + } + class PinNumberLoginTask{ + onConfirm(): void; + onLoginFail(bool: boolean, idx: number): void; + isMTS: boolean; + } + class ReSignupProcess{ + + } + class Assets{ + + } + + Browser --> Login : "/login?ref=&sccofnstcd=270" + Login --> LoginTask + LoginTask --> Assets :onConfirm={onConfirmLogin} + LoginTask --> PinNumberLoginTask + LoginTask <-- PinNumberLoginTask +``` diff --git a/quantec/cs/quantecSampleData/README.md b/quantec/cs/quantecSampleData/README.md new file mode 100644 index 0000000..3d762d1 --- /dev/null +++ b/quantec/cs/quantecSampleData/README.md @@ -0,0 +1,7 @@ +## PBP-CS 샘플데이터 + +PBP-CS는 현재 하나증권 데이터를 받아서 테스트를 하고 있기 때문에 테스트에 어려움 local, dev에서 각 페이지를 통과할 수 있는 방법을 강구하자는 바임 + +### 1. 로그인 +> +> 로그인시 매직키패드 및 diff --git a/quantec/cs/quantecAssetAnalysis/README.md b/quantec/pbp/quantecAssetAnalysis/README.md similarity index 100% rename from quantec/cs/quantecAssetAnalysis/README.md rename to quantec/pbp/quantecAssetAnalysis/README.md diff --git a/quantec/cs/quantecReport/240821_PB플랫폼 수정요청_리포트.pptx b/quantec/pbp/quantecReport/240821_PB플랫폼 수정요청_리포트.pptx similarity index 100% rename from quantec/cs/quantecReport/240821_PB플랫폼 수정요청_리포트.pptx rename to quantec/pbp/quantecReport/240821_PB플랫폼 수정요청_리포트.pptx diff --git a/quantec/cs/quantecReport/README.md b/quantec/pbp/quantecReport/README.md similarity index 99% rename from quantec/cs/quantecReport/README.md rename to quantec/pbp/quantecReport/README.md index 55e008b..9218988 100644 --- a/quantec/cs/quantecReport/README.md +++ b/quantec/pbp/quantecReport/README.md @@ -437,3 +437,5 @@ 4. 기획팀에서 전달 받은 피드백 ppt파일 [기획 수정 요청 ppt 파일](<240821_PB플랫폼 수정요청_리포트.pptx>) + +>> 2024-08-28 우선 데이터 맞추어 놨고 디자인은 차후 수정하겠음 diff --git a/quantec/cs/quantecReport/image-1.png b/quantec/pbp/quantecReport/image-1.png similarity index 100% rename from quantec/cs/quantecReport/image-1.png rename to quantec/pbp/quantecReport/image-1.png diff --git a/quantec/cs/quantecReport/image-2.png b/quantec/pbp/quantecReport/image-2.png similarity index 100% rename from quantec/cs/quantecReport/image-2.png rename to quantec/pbp/quantecReport/image-2.png diff --git a/quantec/cs/quantecReport/image-3.png b/quantec/pbp/quantecReport/image-3.png similarity index 100% rename from quantec/cs/quantecReport/image-3.png rename to quantec/pbp/quantecReport/image-3.png diff --git a/quantec/cs/quantecReport/image.png b/quantec/pbp/quantecReport/image.png similarity index 100% rename from quantec/cs/quantecReport/image.png rename to quantec/pbp/quantecReport/image.png