diff --git a/src/bill/getBillList.spec.ts b/src/bill/getBillList.spec.ts new file mode 100644 index 0000000..240efb7 --- /dev/null +++ b/src/bill/getBillList.spec.ts @@ -0,0 +1,98 @@ +import { describe, it, expect, vi } from 'vitest'; +import { getBillList } from './getBillList'; +import { callOpenApi } from '../functional'; +import { translatedVariableDictionary } from '../constant'; + +vi.mock('../functional', () => ({ + callOpenApi: vi.fn(), +})); + +describe('getBillList', () => { + it('should return a list of bills', async () => { + const mockResponse = { + TVBPMBILL11: [ + null, + { + row: [ + { + BILL_ID: 'PRC_K2S4R0S4Q3P0L0K9J0J9I5Q7P2Q4O6', + BILL_NO: '2126707', + AGE: '21', + BILL_NAME: '문화다양성의 보호와 증진에 관한 법률 일부개정법률안', + PROPOSER: '이자스민의원 등 10인', + PROPOSER_KIND: '의원', + PROPOSE_DT: '2024-05-29', + CURR_COMMITTEE_ID: '9700513', + CURR_COMMITTEE: '문화체육관광위원회', + COMMITTEE_DT: '2024-05-29', + COMMITTEE_PROC_DT: null, + LINK_URL: 'https://likms.assembly.go.kr/bill/billDetail.do?billId=PRC_K2S4R0S4Q3P0L0K9J0J9I5Q7P2Q4O6', + RST_PROPOSER: '이자스민', + LAW_PROC_RESULT_CD: null, + LAW_PROC_DT: null, + LAW_PRESENT_DT: null, + LAW_SUBMIT_DT: null, + CMT_PROC_RESULT_CD: null, + CMT_PROC_DT: null, + CMT_PRESENT_DT: null, + RST_MONA_CD: 'SZ51175J', + PROC_RESULT_CD: '임기만료폐기', + PROC_DT: '2024-05-29', + }, + ], + }, + ], + }; + + (callOpenApi as any).mockResolvedValueOnce(mockResponse); + + const bills = await getBillList({ page: 1, take: 10 }); + + expect(bills).toHaveLength(1); + expect(bills[0]).toEqual({ + [translatedVariableDictionary['의안ID']]: 'PRC_K2S4R0S4Q3P0L0K9J0J9I5Q7P2Q4O6', + [translatedVariableDictionary['의안번호']]: '2126707', + [translatedVariableDictionary['대']]: '21', + [translatedVariableDictionary['의안명']]: '문화다양성의 보호와 증진에 관한 법률 일부개정법률안', + [translatedVariableDictionary['제안자']]: '이자스민의원 등 10인', + [translatedVariableDictionary['제안자구분']]: '의원', + [translatedVariableDictionary['제안일']]: '2024-05-29', + [translatedVariableDictionary['소관위코드']]: '9700513', + [translatedVariableDictionary['소관위']]: '문화체육관광위원회', + [translatedVariableDictionary['소관위회부일']]: '2024-05-29', + [translatedVariableDictionary['위원회심사_처리일']]: null, + [translatedVariableDictionary['의안상세정보_URL']]: + 'https://likms.assembly.go.kr/bill/billDetail.do?billId=PRC_K2S4R0S4Q3P0L0K9J0J9I5Q7P2Q4O6', + [translatedVariableDictionary['대표발의자']]: '이자스민', + [translatedVariableDictionary['법사위처리결과']]: null, + [translatedVariableDictionary['법사위처리일']]: null, + [translatedVariableDictionary['법사위상정일']]: null, + [translatedVariableDictionary['법사위회부일']]: null, + [translatedVariableDictionary['소관위처리결과']]: null, + [translatedVariableDictionary['소관위처리일']]: null, + [translatedVariableDictionary['소관위상정일']]: null, + [translatedVariableDictionary['대표발의자코드']]: 'SZ51175J', + [translatedVariableDictionary['본회의심의결과']]: '임기만료폐기', + [translatedVariableDictionary['의결일']]: '2024-05-29', + }); + }); + + it('should return an empty list when no bills are found', async () => { + const mockResponse = { + TVBPMBILL11: [null, { row: [] }], + }; + + (callOpenApi as any).mockResolvedValueOnce(mockResponse); + + const bills = await getBillList({ page: 1, take: 10 }); + + expect(bills).toHaveLength(0); + }); + + it('should throw an error when callOpenApi fails', async () => { + const mockError = new Error('Failed to fetch bills'); + (callOpenApi as any).mockRejectedValueOnce(mockError); + + await expect(getBillList({ page: 1, take: 10 })).rejects.toThrow('Failed to fetch bills'); + }); +}); diff --git a/src/bill/getBillList.ts b/src/bill/getBillList.ts new file mode 100644 index 0000000..9d36dbd --- /dev/null +++ b/src/bill/getBillList.ts @@ -0,0 +1,100 @@ +import { callOpenApi } from '../functional'; +import { PaginationType } from '../types/callOpenApi'; +import { translatedVariableDictionary } from '../constant'; + +// https://open.assembly.go.kr/portal/data/service/selectAPIServicePage.do/O4K6HM0012064I15889 +// 법률안 심사 및 처리(의안검색) 구현 + +interface Bill { + BILL_ID: string; // 의안ID + BILL_NO: string; // 의안번호 + AGE: string; // 대 + BILL_NAME: string; // 의안명(한글) + PROPOSER: string; // 제안자 + PROPOSER_KIND: string; // 제안자구분 + PROPOSE_DT: string; // 제안일 + CURR_COMMITTEE_ID: string; // 소관위코드 + CURR_COMMITTEE: string; // 소관위 + COMMITTEE_DT: string; // 소관위회부일 + COMMITTEE_PROC_DT: string; // 위원회심사_처리일 + LINK_URL: string; // 의안상세정보_URL + RST_PROPOSER: string; // 대표발의자 + LAW_PROC_RESULT_CD: string; // 법사위처리결과 + LAW_PROC_DT: string; // 법사위처리일 + LAW_PRESENT_DT: string; // 법사위상정일 + LAW_SUBMIT_DT: string; // 법사위회부일 + CMT_PROC_RESULT_CD: string; // 소관위처리결과 + CMT_PROC_DT: string; // 소관위처리일 + CMT_PRESENT_DT: string; // 소관위상정일 + RST_MONA_CD: string; // 대표발의자코드 + PROC_RESULT_CD: string; // 본회의심의결과 + PROC_DT: string; // 의결일 +} + +type Row = { + [k in keyof Bill]: Bill[k] | null; +}; + +type Argument = { + billID?: string; // 의안ID, 예시: BILL_ID='PRC_Z2Z1Z0Z3X2L4M0H9A2V6K5R0V7P2H1' + billNumber?: string; // 의안번호, 예시: BILL_NO='2114286' + age?: string; // 대, 예시: AGE='21' + billName?: string; // 의안명(한글), 예시: BILL_NAME='의안명(한글) 검색어' (예시) BILL_NAME="80년 + proposer?: string; // 제안자, 예시: PROPOSER='제안자 검색어' (예시) PROPOSER=2012년 + proposerDivision?: string; // 제안자구분, 예시: PROPOSER_KIND='정부' + jurisdictionCommitteeCode?: string; // 소관위코드, 예시: CURR_COMMITTEE_ID='B002368' + jurisdictionCommittee?: string; // 소관위, 예시: CURR_COMMITTEE='소관위 검색어' (예시) CURR_COMMITTEE=2002 + plenarySessionReviewResult?: string; // 본회의심의결과, 예시: PROC_RESULT_CD='회기불계속폐기' + resolutionDate?: string; // 의결일, 예시: PROC_DT='2021-12-31' +} & PaginationType; + +const command = 'TVBPMBILL11'; + +const transform = (v: Row) => ({ + [translatedVariableDictionary['의안ID']]: v.BILL_ID, + [translatedVariableDictionary['의안번호']]: v.BILL_NO, + [translatedVariableDictionary['대']]: v.AGE, + [translatedVariableDictionary['의안명']]: v.BILL_NAME, + [translatedVariableDictionary['제안자']]: v.PROPOSER, + [translatedVariableDictionary['제안자구분']]: v.PROPOSER_KIND, + [translatedVariableDictionary['제안일']]: v.PROPOSE_DT, + [translatedVariableDictionary['소관위코드']]: v.CURR_COMMITTEE_ID, + [translatedVariableDictionary['소관위']]: v.CURR_COMMITTEE, + [translatedVariableDictionary['소관위회부일']]: v.COMMITTEE_DT, + [translatedVariableDictionary['위원회심사_처리일']]: v.COMMITTEE_PROC_DT, + [translatedVariableDictionary['의안상세정보_URL']]: v.LINK_URL, + [translatedVariableDictionary['대표발의자']]: v.RST_PROPOSER, + [translatedVariableDictionary['법사위처리결과']]: v.LAW_PROC_RESULT_CD, + [translatedVariableDictionary['법사위처리일']]: v.LAW_PROC_DT, + [translatedVariableDictionary['법사위상정일']]: v.LAW_PRESENT_DT, + [translatedVariableDictionary['법사위회부일']]: v.LAW_SUBMIT_DT, + [translatedVariableDictionary['소관위처리결과']]: v.CMT_PROC_RESULT_CD, + [translatedVariableDictionary['소관위처리일']]: v.CMT_PROC_DT, + [translatedVariableDictionary['소관위상정일']]: v.CMT_PRESENT_DT, + [translatedVariableDictionary['대표발의자코드']]: v.RST_MONA_CD, + [translatedVariableDictionary['본회의심의결과']]: v.PROC_RESULT_CD, + [translatedVariableDictionary['의결일']]: v.PROC_DT, +}); + +/** + * @description implementation of 법률안 심사 및 처리 API + */ +export const getBillList = async ({ page, take, ...rest }: Argument) => { + const res = await callOpenApi( + command, + { page, take }, + { + BILL_ID: rest.billID, + BILL_NO: rest.billNumber, + AGE: rest.age, + BILL_NAME: rest.billName, + PROPOSER: rest.proposer, + PROPOSER_KIND: rest.proposerDivision, + CURR_COMMITTEE_ID: rest.jurisdictionCommitteeCode, + CURR_COMMITTEE: rest.jurisdictionCommittee, + PROC_RESULT_CD: rest.plenarySessionReviewResult, + PROC_DT: rest.resolutionDate, + } + ); + return res.TVBPMBILL11[1].row.map(transform); +}; diff --git a/src/bill/index.spec.ts b/src/bill/index.spec.ts new file mode 100644 index 0000000..46c7995 --- /dev/null +++ b/src/bill/index.spec.ts @@ -0,0 +1,9 @@ +// src/bill/index.spec.ts +import { describe, it, expect } from 'vitest'; +import { getBillList } from './index'; + +describe('bill index.ts', () => { + it('should export getBillList', () => { + expect(getBillList).toBeDefined(); + }); +}); diff --git a/src/bill/index.ts b/src/bill/index.ts new file mode 100644 index 0000000..96b3451 --- /dev/null +++ b/src/bill/index.ts @@ -0,0 +1 @@ +export { getBillList } from './getBillList'; diff --git a/src/constant/index.ts b/src/constant/index.ts index e96c26b..de5226b 100644 --- a/src/constant/index.ts +++ b/src/constant/index.ts @@ -4,6 +4,10 @@ * @ignore `~코드`와 같은 이름을 지칭하는 변수의 경우 `Code`로 끝나야함 * @ignore `~일자`와 같은 이름을 지칭하는 변수의 경우 `Date`로 끝나야함 * @ignore `~구분`과 같은 이름을 지칭하는 변수의 경우 `Division`으로 끝나야함, 만약 `구분명`이라면 `Division`을 사용 + * @ignore `~처리`과 같은 이름을 지칭하는 변수의 경우 `Process`으로 끝나야함 + * @ignore `~상정`과 같은 이름을 지칭하는 변수의 경우 `Present`으로 끝나야함 + * @ignore `~회부`과 같은 이름을 지칭하는 변수의 경우 `Submit`으로 끝나야함 + * @ignore `~의결`과 같은 이름을 지칭하는 변수의 경우 `Resolution`으로 끝나야함 */ export const translatedVariableDictionary = { 국회의원코드: 'lawmakerCode', @@ -30,4 +34,29 @@ export const translatedVariableDictionary = { 약력: 'profile', 사무실호실: 'officeRoom', 사진: 'picture', + + // 의안 관련 추가 + 의안ID: 'billID', + 의안번호: 'billNumber', + 대: 'age', + 의안명: 'billName', + 제안자: 'proposer', + 제안자구분: 'proposerDivision', + 제안일: 'proposeDate', + 소관위코드: 'jurisdictionCommitteeCode', + 소관위: 'jurisdictionCommittee', + 소관위회부일: 'jurisdictionCommitteeSubmitDate', + 위원회심사_처리일: 'committeeReviewProcessDate', + 의안상세정보_URL: 'billDetailUrl', + 대표발의자: 'leadProposer', + 법사위처리결과: 'legislationAndJudiciaryCommitteeProcessResult', + 법사위처리일: 'legislationAndJudiciaryCommitteeProcessDate', + 법사위상정일: 'legislationAndJudiciaryCommitteePresentDate', + 법사위회부일: 'legislationAndJudiciaryCommitteeSubmitDate', + 소관위처리결과: 'jurisdictionCommitteeProcessResult', + 소관위처리일: 'jurisdictionCommitteeProcessDate', + 소관위상정일: 'jurisdictionCommitteePresentDate', + 대표발의자코드: 'leadProposerCode', + 본회의심의결과: 'plenarySessionReviewResult', + 의결일: 'resolutionDate', } as const; diff --git a/src/types/callOpenApi.ts b/src/types/callOpenApi.ts index 129878c..c3c2ce8 100644 --- a/src/types/callOpenApi.ts +++ b/src/types/callOpenApi.ts @@ -3,7 +3,7 @@ export type PaginationType = { take: number; }; -export type ApiCommand = 'ALLNAMEMBER' & string; +export type ApiCommand = ('ALLNAMEMBER' | 'TVBPMBILL11') & string; export const OpenApiResponseKind = { 'INFO-000': '정상 처리되었습니다.',