Skip to content

Feature/add getBillList function #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Aug 2, 2024
Merged
98 changes: 98 additions & 0 deletions src/bill/getBillList.spec.ts
Original file line number Diff line number Diff line change
@@ -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');
});
});
113 changes: 113 additions & 0 deletions src/bill/getBillList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
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 = {
BILL_ID?: string; // 의안ID, 예시: BILL_ID='PRC_Z2Z1Z0Z3X2L4M0H9A2V6K5R0V7P2H1'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

argument 이름 통일하는게 좋을 듯 싶은데

여기처럼 Open API에 있는 인자값을 따라가는게 맞을까요
아니면 sdk기에 따로 변수를 convert하는편이 좋을까요?

저는 개인적으로 후자가 맞다고 봅니다. sdk기에

일단 이건 정해서 싹 수정하면 되는 내용이라 이야기만 하면 될 것 같아요

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

후자에 동의합니다
그렇게 하려고 하더라도 요청할 때 키값은 맞춰야 하니 정보 매핑해서 관리는 해야하는거죠?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네네 그래서 함수딴에서 구조분해할당으로 매핑하는 코드가 있는거고요

BILL_NO?: string; // 의안번호, 예시: BILL_NO='2114286'
AGE?: string; // 대, 예시: AGE='21'
BILL_NAME?: string; // 의안명(한글), 예시: BILL_NAME='의안명(한글) 검색어' (예시) BILL_NAME="80년
PROPOSER?: string; // 제안자, 예시: PROPOSER='제안자 검색어' (예시) PROPOSER=2012년
PROPOSER_KIND?: string; // 제안자구분, 예시: PROPOSER_KIND='정부'
CURR_COMMITTEE_ID?: string; // 소관위코드, 예시: CURR_COMMITTEE_ID='B002368'
CURR_COMMITTEE?: string; // 소관위, 예시: CURR_COMMITTEE='소관위 검색어' (예시) CURR_COMMITTEE=2002
PROC_RESULT_CD?: string; // 본회의심의결과, 예시: PROC_RESULT_CD='회기불계속폐기'
PROC_DT?: 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 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

엇, 제가 작성했던거야 사용자들이 argument 이해하기 쉽게 변수명 transform해서 넣어놨던건데
이럴거면 굳이 구조분해할당이 필요없지않나 싶읍니다.

Argument 프로퍼티명을 수정해보는건 어떨까요

BILL_ID: BILL_ID,
BILL_NO: BILL_NO,
AGE: AGE,
BILL_NAME: BILL_NAME,
PROPOSER: PROPOSER,
PROPOSER_KIND: PROPOSER_KIND,
CURR_COMMITTEE_ID: CURR_COMMITTEE_ID,
CURR_COMMITTEE: CURR_COMMITTEE,
PROC_RESULT_CD: PROC_RESULT_CD,
PROC_DT: PROC_DT,
} = rest;

const res = await callOpenApi<typeof command, Row>(
command,
{ page, take },
{
BILL_ID,
BILL_NO,
AGE,
BILL_NAME,
PROPOSER,
PROPOSER_KIND,
CURR_COMMITTEE_ID,
CURR_COMMITTEE,
PROC_RESULT_CD,
PROC_DT,
}
);
return res.TVBPMBILL11[1].row.map(transform);
};
9 changes: 9 additions & 0 deletions src/bill/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// src/bill/index.spec.ts
import { describe, it, expect } from 'vitest';
import { getBillList } from './index';

describe('bill index.ts', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

엇 이게 필요한가요

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

export, import 관련해서 vitest 테스트 커버리지 이슈라면 #15 에서 다루고 있습니다.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

테스트 과정에서 문제가 있어서 저걸로 풀기는 했는데, vitest에 정확한 이해도를 가지고 있진 않아요
요거 판단해주시믄 감사하겠습니닷

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

삭제하고 함 돌려보죠
저도 이해도를 가지고 있진않은데 해결이 되고, 타 라이브러리들 참고했을 때 istanbul 사용하더라고요

it('should export getBillList', () => {
expect(getBillList).toBeDefined();
});
});
1 change: 1 addition & 0 deletions src/bill/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { getBillList } from './getBillList';
29 changes: 29 additions & 0 deletions src/constant/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
* @ignore `~코드`와 같은 이름을 지칭하는 변수의 경우 `Code`로 끝나야함
* @ignore `~일자`와 같은 이름을 지칭하는 변수의 경우 `Date`로 끝나야함
* @ignore `~구분`과 같은 이름을 지칭하는 변수의 경우 `Division`으로 끝나야함, 만약 `구분명`이라면 `Division`을 사용
* @ignore `~처리`과 같은 이름을 지칭하는 변수의 경우 `Process`으로 끝나야함
* @ignore `~상정`과 같은 이름을 지칭하는 변수의 경우 `Present`으로 끝나야함
* @ignore `~회부`과 같은 이름을 지칭하는 변수의 경우 `Submit`으로 끝나야함
* @ignore `~의결`과 같은 이름을 지칭하는 변수의 경우 `Resolution`으로 끝나야함
*/
export const translatedVariableDictionary = {
국회의원코드: 'lawmakerCode',
Expand All @@ -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;
2 changes: 1 addition & 1 deletion src/types/callOpenApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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': '정상 처리되었습니다.',
Expand Down
Loading