Compare commits
2 Commits
1e8bf1eeeb
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac88ebdedb | ||
|
|
6fdd040d4d |
297
e2e/new-features.spec.js
Normal file
297
e2e/new-features.spec.js
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
// @ts-check
|
||||||
|
const { test, expect } = require('@playwright/test');
|
||||||
|
const { login } = require('./helpers/auth');
|
||||||
|
|
||||||
|
async function loginAsAdmin(page) {
|
||||||
|
await login(page, 'admin');
|
||||||
|
await page.locator('input[name="lg_idx"]').first().check();
|
||||||
|
await page.click('button[type="submit"]');
|
||||||
|
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 30000 });
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loginAsLocal(page) {
|
||||||
|
await login(page, 'local');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
// CT-01: 페이지네이션
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
test.describe('CT-01: 페이지네이션', () => {
|
||||||
|
test('발주 목록에 데이터 테이블 존재', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin/bag-orders');
|
||||||
|
await expect(page.locator('table.data-table')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('판매 목록에 데이터 테이블 존재', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin/bag-sales');
|
||||||
|
await expect(page.locator('table.data-table')).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
// CT-02: 엑셀 저장
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
test.describe('CT-02: 엑셀 저장', () => {
|
||||||
|
test('발주 엑셀 다운로드', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin/bag-orders');
|
||||||
|
const downloadPromise = page.waitForEvent('download', { timeout: 10000 });
|
||||||
|
await page.locator('a[href*="export"]').first().click();
|
||||||
|
const download = await downloadPromise;
|
||||||
|
expect(download.suggestedFilename()).toContain('.csv');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('재고 엑셀 다운로드', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin/bag-inventory');
|
||||||
|
const downloadPromise = page.waitForEvent('download', { timeout: 10000 });
|
||||||
|
await page.locator('a[href*="export"]').first().click();
|
||||||
|
const download = await downloadPromise;
|
||||||
|
expect(download.suggestedFilename()).toContain('.csv');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
// CT-03: 인쇄 버튼
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
test.describe('CT-03: 인쇄 버튼', () => {
|
||||||
|
test('발주 목록에 인쇄 버튼 존재', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin/bag-orders');
|
||||||
|
await expect(page.locator('button:has-text("인쇄"), a:has-text("인쇄")')).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
// CT-06: 대시보드 실 데이터
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
test.describe('CT-06: 대시보드 실 데이터', () => {
|
||||||
|
test('대시보드에 통계 표시', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin');
|
||||||
|
const content = await page.textContent('main');
|
||||||
|
expect(content).toBeTruthy();
|
||||||
|
expect(content.length).toBeGreaterThan(50);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
// P2-15: 지정판매소 다조건 조회
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
test.describe('P2-15: 지정판매소 다조건 조회', () => {
|
||||||
|
test('이름 검색 필터', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin/designated-shops?ds_name=CU');
|
||||||
|
await expect(page).toHaveURL(/ds_name=CU/);
|
||||||
|
await expect(page.locator('table.data-table')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('상태 필터', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin/designated-shops?ds_state=1');
|
||||||
|
await expect(page.locator('table.data-table')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('검색 폼에서 이름 입력 후 조회', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin/designated-shops');
|
||||||
|
const nameInput = page.locator('input[name="ds_name"]');
|
||||||
|
if (await nameInput.count() > 0) {
|
||||||
|
await nameInput.fill('GS');
|
||||||
|
await page.click('button:has-text("조회")');
|
||||||
|
await expect(page).toHaveURL(/ds_name=GS/);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
// P2-17: 지정판매소 지도
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
test.describe('P2-17: 지정판매소 지도', () => {
|
||||||
|
test('지도 페이지 접근', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin/designated-shops/map');
|
||||||
|
await expect(page).toHaveURL(/\/map/);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
// P2-18: 지정판매소 현황
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
test.describe('P2-18: 지정판매소 현황', () => {
|
||||||
|
test('현황 페이지 접근', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin/designated-shops/status');
|
||||||
|
await expect(page).toHaveURL(/\/status/);
|
||||||
|
await expect(page.locator('table.data-table').first()).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
// P5-04: 년 판매 현황
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
test.describe('P5-04: 년 판매 현황', () => {
|
||||||
|
test('년 판매 현황 접근', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin/reports/yearly-sales');
|
||||||
|
await expect(page).toHaveURL(/yearly-sales/);
|
||||||
|
await expect(page.locator('table.data-table')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('연도 변경 조회', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin/reports/yearly-sales?year=2025');
|
||||||
|
await expect(page).toHaveURL(/year=2025/);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
// P5-05: 지정판매소별 판매현황
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
test.describe('P5-05: 판매소별 판매현황', () => {
|
||||||
|
test('판매소별 현황 접근', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin/reports/shop-sales');
|
||||||
|
await expect(page).toHaveURL(/shop-sales/);
|
||||||
|
await expect(page.locator('table.data-table')).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
// P5-06: 홈택스 엑셀
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
test.describe('P5-06: 홈택스 세금계산서 엑셀', () => {
|
||||||
|
test('홈택스 엑셀 내보내기', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
// 다운로드를 트리거하는 URL이므로 evaluate로 fetch 테스트
|
||||||
|
const status = await page.evaluate(async () => {
|
||||||
|
const res = await fetch('/admin/reports/hometax-export');
|
||||||
|
return res.status;
|
||||||
|
});
|
||||||
|
expect(status).toBe(200);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
// P5-08: 반품/파기 현황
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
test.describe('P5-08: 반품/파기 현황', () => {
|
||||||
|
test('반품/파기 목록 접근', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin/reports/returns');
|
||||||
|
await expect(page).toHaveURL(/returns/);
|
||||||
|
await expect(page.locator('table.data-table')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('기간 필터 조회', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin/reports/returns?start_date=2026-01-01&end_date=2026-12-31');
|
||||||
|
await expect(page.locator('table.data-table')).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
// P5-10: LOT 수불 조회
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
test.describe('P5-10: LOT 수불 조회', () => {
|
||||||
|
test('LOT 수불 페이지 접근', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin/reports/lot-flow');
|
||||||
|
await expect(page).toHaveURL(/lot-flow/);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('LOT 번호 검색', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin/reports/lot-flow?lot=LOT-2025');
|
||||||
|
await expect(page).toHaveURL(/lot=LOT/);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
// P5-11: 기타 입출고
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
test.describe('P5-11: 기타 입출고', () => {
|
||||||
|
test('기타 입출고 페이지 접근', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin/reports/misc-flow');
|
||||||
|
await expect(page).toHaveURL(/misc-flow/);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('기타 입출고 등록 폼 표시', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin/reports/misc-flow');
|
||||||
|
await expect(page.locator('select[name="bmf_type"]')).toBeVisible();
|
||||||
|
await expect(page.locator('input[name="bmf_qty"]')).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
// 사이트 메뉴 CRUD (DOM 조작)
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
test.describe('사이트 메뉴 CRUD 동작', () => {
|
||||||
|
test.beforeEach(async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('불출 처리 폼 → 사이트 레이아웃', async ({ page }) => {
|
||||||
|
await page.goto('/bag/issue/create');
|
||||||
|
await expect(page.locator('a:has-text("발주 입고 관리")')).toBeVisible();
|
||||||
|
expect(await page.locator('a:has-text("회원 관리")').count()).toBe(0);
|
||||||
|
await expect(page.locator('select[name="bi2_bag_code"]')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('발주 등록 폼 → 사이트 레이아웃', async ({ page }) => {
|
||||||
|
await page.goto('/bag/order/create');
|
||||||
|
await expect(page.locator('a:has-text("불출 관리")')).toBeVisible();
|
||||||
|
await expect(page.locator('input[name="bo_order_date"]')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('입고 처리 폼 → 사이트 레이아웃', async ({ page }) => {
|
||||||
|
await page.goto('/bag/receiving/create');
|
||||||
|
await expect(page.locator('a:has-text("재고 관리")')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('판매 등록 폼 → 사이트 레이아웃', async ({ page }) => {
|
||||||
|
await page.goto('/bag/sale/create');
|
||||||
|
await expect(page.locator('a:has-text("판매 현황")')).toBeVisible();
|
||||||
|
await expect(page.locator('select[name="bs_ds_idx"]')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('주문 접수 폼 → 사이트 레이아웃', async ({ page }) => {
|
||||||
|
await page.goto('/bag/shop-order/create');
|
||||||
|
await expect(page.locator('a:has-text("봉투 수불 관리")')).toBeVisible();
|
||||||
|
await expect(page.locator('select[name="so_ds_idx"]')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('재고 조정 폼', async ({ page }) => {
|
||||||
|
await page.goto('/bag/inventory/adjust');
|
||||||
|
await expect(page.locator('select[name="bag_code"]')).toBeVisible();
|
||||||
|
await expect(page.locator('select[name="adjust_type"]')).toBeVisible();
|
||||||
|
await expect(page.locator('input[name="qty"]')).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
// 엑셀 내보내기 다운로드
|
||||||
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
test.describe('엑셀 내보내기 다운로드', () => {
|
||||||
|
test('지정판매소 엑셀', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin/designated-shops');
|
||||||
|
const downloadPromise = page.waitForEvent('download', { timeout: 10000 });
|
||||||
|
await page.locator('a[href*="export"]').first().click();
|
||||||
|
const download = await downloadPromise;
|
||||||
|
expect(download.suggestedFilename()).toContain('.csv');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('판매 엑셀', async ({ page }) => {
|
||||||
|
await loginAsLocal(page);
|
||||||
|
await page.goto('/admin/bag-sales');
|
||||||
|
const downloadPromise = page.waitForEvent('download', { timeout: 10000 });
|
||||||
|
await page.locator('a[href*="export"]').first().click();
|
||||||
|
const download = await downloadPromise;
|
||||||
|
expect(download.suggestedFilename()).toContain('.csv');
|
||||||
|
});
|
||||||
|
});
|
||||||
34
jobs.md
34
jobs.md
@@ -47,10 +47,10 @@
|
|||||||
| P2-12 | 업체 조회 / 인쇄 | 낮음 | P2-11 | **완료** |
|
| P2-12 | 업체 조회 / 인쇄 | 낮음 | P2-11 | **완료** |
|
||||||
| P2-13 | 무료용 대상자 관리 (CRUD) | 중간 | — | **완료** |
|
| P2-13 | 무료용 대상자 관리 (CRUD) | 중간 | — | **완료** |
|
||||||
| P2-14 | 무료용 대상자 조회 / 인쇄 | 낮음 | P2-13 | **완료** |
|
| P2-14 | 무료용 대상자 조회 / 인쇄 | 낮음 | P2-13 | **완료** |
|
||||||
| P2-15 | 지정판매소 다조건 조회 + 엑셀 + 인쇄 | 중간 | — | 대기 |
|
| P2-15 | 지정판매소 다조건 조회 + 엑셀 + 인쇄 | 중간 | — | **완료** |
|
||||||
| P2-16 | 지정판매소 바코드 출력 | 낮음 | P2-15 | 대기 |
|
| P2-16 | 지정판매소 바코드 출력 | 낮음 | P2-15 | Phase 6+ |
|
||||||
| P2-17 | 지정판매소 지도 표시 | 낮음 | — | 대기 |
|
| P2-17 | 지정판매소 지도 표시 | 낮음 | — | **완료** |
|
||||||
| P2-18 | 지정판매소 현황 (신규/취소) | 낮음 | — | 대기 |
|
| P2-18 | 지정판매소 현황 (신규/취소) | 낮음 | — | **완료** |
|
||||||
| P2-19 | 지자체 수정/삭제 기능 | 중간 | — | **완료** |
|
| P2-19 | 지자체 수정/삭제 기능 | 중간 | — | **완료** |
|
||||||
| P2-20 | PASSWORD 변경 기능 | 중간 | — | **완료** |
|
| P2-20 | PASSWORD 변경 기능 | 중간 | — | **완료** |
|
||||||
| P2-21 | 로그인 5회 실패 lock | 중간 | — | **완료** |
|
| P2-21 | 로그인 5회 실패 lock | 중간 | — | **완료** |
|
||||||
@@ -94,14 +94,14 @@
|
|||||||
| P5-01 | 판매 대장 (일자별/기간별) | 높음 | P4-04 | **완료** |
|
| P5-01 | 판매 대장 (일자별/기간별) | 높음 | P4-04 | **완료** |
|
||||||
| P5-02 | 일계표 (일계 + 월간 누계) | 높음 | P4-04 | **완료** |
|
| P5-02 | 일계표 (일계 + 월간 누계) | 높음 | P4-04 | **완료** |
|
||||||
| P5-03 | 기간별 판매현황 | 중간 | P4-04 | **완료** |
|
| P5-03 | 기간별 판매현황 | 중간 | P4-04 | **완료** |
|
||||||
| P5-04 | 년 판매 현황 (월별/분기별) | 중간 | P4-04 | Phase 6+ |
|
| P5-04 | 년 판매 현황 (월별/분기별) | 중간 | P4-04 | **완료** |
|
||||||
| P5-05 | 지정판매소별 판매현황 (수량/금액) | 중간 | P4-04 | Phase 6+ |
|
| P5-05 | 지정판매소별 판매현황 (수량/금액) | 중간 | P4-04 | **완료** |
|
||||||
| P5-06 | 홈택스 세금계산서 엑셀 생성 | 높음 | P4-04 | Phase 6+ |
|
| P5-06 | 홈택스 세금계산서 엑셀 생성 | 높음 | P4-04 | **완료** |
|
||||||
| P5-07 | 봉투 수불 현황 (재고/입고/판매/불출) | 높음 | P3-08, P4-04 | **완료** |
|
| P5-07 | 봉투 수불 현황 (재고/입고/판매/불출) | 높음 | P3-08, P4-04 | **완료** |
|
||||||
| P5-08 | 반품/파기 현황 | 중간 | P4-06 | Phase 6+ |
|
| P5-08 | 반품/파기 현황 | 중간 | P4-06 | **완료** |
|
||||||
| P5-09 | 봉투 수급 계획 | 낮음 | P5-07 | Phase 6+ |
|
| P5-09 | 봉투 수급 계획 | 낮음 | P5-07 | Phase 6+ |
|
||||||
| P5-10 | LOT 수불 조회 | 중간 | P3-02 | Phase 6+ |
|
| P5-10 | LOT 수불 조회 | 중간 | P3-02 | **완료** |
|
||||||
| P5-11 | 기타 입출고 | 낮음 | P3-08 | Phase 6+ |
|
| P5-11 | 기타 입출고 | 낮음 | P3-08 | **완료** |
|
||||||
| P5-12 | 봉투 스캔 현황 (횟수/위치) | 낮음 | — | Phase 6+ |
|
| P5-12 | 봉투 스캔 현황 (횟수/위치) | 낮음 | — | Phase 6+ |
|
||||||
|
|
||||||
### Phase 6 — 모바일앱
|
### Phase 6 — 모바일앱
|
||||||
@@ -119,13 +119,13 @@
|
|||||||
|
|
||||||
| ID | 작업 | 우선순위 | 상태 |
|
| ID | 작업 | 우선순위 | 상태 |
|
||||||
|----|------|---------|------|
|
|----|------|---------|------|
|
||||||
| CT-01 | 페이지네이션 공통 구현 | 높음 | 대기 |
|
| CT-01 | 페이지네이션 공통 구현 | 높음 | **완료** |
|
||||||
| CT-02 | 엑셀 저장 공통 컴포넌트 | 높음 | 대기 |
|
| CT-02 | 엑셀 저장 공통 컴포넌트 | 높음 | **완료** |
|
||||||
| CT-03 | 인쇄 공통 컴포넌트 (결재란 포함) | 높음 | 대기 |
|
| CT-03 | 인쇄 공통 컴포넌트 (결재란 포함) | 높음 | **완료** |
|
||||||
| CT-04 | 바코드 스캐너 연동 (Electron + serialport) | 중간 | 대기 |
|
| CT-04 | 바코드 스캐너 연동 (Electron + serialport) | 중간 | Phase 6+ |
|
||||||
| CT-05 | CRUD 로깅 (전체 데이터 변경 이력) | 중간 | 대기 |
|
| CT-05 | CRUD 로깅 (전체 데이터 변경 이력) | 중간 | **완료** |
|
||||||
| CT-06 | 대시보드 실 데이터 연동 | 낮음 | 대기 |
|
| CT-06 | 대시보드 실 데이터 연동 | 낮음 | **완료** |
|
||||||
| CT-07 | 2차 인증 적용 | 중간 | 대기 |
|
| CT-07 | 2차 인증 적용 | 중간 | **완료** |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user