# Tasks: Table QR Code (餐桌码)

**Input**: Design documents from `/specs/002-table-qrcode/`
**Prerequisites**: plan.md, spec.md, data-model.md, contracts/api.md, research.md

## Format: `[ID] [P?] [Story] Description`

- **[P]**: Can run in parallel (different files, no dependencies)
- **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3, US4)

---

## Phase 1: Setup

**Purpose**: 添加依赖和创建数据库表

- [x] T001 Add ZXing dependencies to `ruoyi-admin/pom.xml` (core 3.5.2 + javase 3.5.2)
- [x] T002 Execute DDL to create `table_qrcode` table per data-model.md (SQL file created at sql/table_qrcode.sql)

---

## Phase 2: Foundational (Backend Core Layer)

**Purpose**: 后端核心层 — Entity、Mapper、Service，所有用户故事的前置依赖

**CRITICAL**: Phase 3+ 的所有工作必须在本阶段完成后才能开始

- [x] T003 Create `TableQrcode` entity class in `ruoyi-system/src/main/java/com/ruoyi/system/domain/TableQrcode.java` following PosStore pattern (@Data, @TableName, @TableId with IdType.AUTO)
- [x] T004 [P] Create `TableQrcodeMapper` interface in `ruoyi-system/src/main/java/com/ruoyi/system/mapper/TableQrcodeMapper.java` extending BaseMapper<TableQrcode>
- [x] T005 [P] Create `TableQrcodeMapper.xml` in `ruoyi-system/src/main/resources/mapper/chanting/TableQrcodeMapper.xml` with resultMap and selectTableQrcodeList query (support filter by storeId, type, status, useStatus, nightMarketId)
- [x] T006 Create `ITableQrcodeService` interface in `ruoyi-system/src/main/java/com/ruoyi/system/service/ITableQrcodeService.java` extending IService<TableQrcode> with CRUD methods
- [x] T007 Create `TableQrcodeServiceImpl` in `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TableQrcodeServiceImpl.java` extending ServiceImpl, autowire TableQrcodeMapper, implement all interface methods

**Checkpoint**: 后端核心层就绪，可以开始实现 API 和前端

---

## Phase 3: User Story 1 — 餐桌码 CRUD API (Priority: P1) MVP

**Goal**: 摊主和夜市管理员可以通过 API 创建/查询/编辑/删除餐桌码

**Independent Test**: 通过 Postman/curl 调用 CRUD 接口，验证创建、列表、详情、更新、删除功能正常，权限控制正确

### Implementation

- [x] T008 [US1] Create `TableQrcodeController` in `ruoyi-admin/src/main/java/com/ruoyi/app/tableqrcode/TableQrcodeController.java` with @RestController, @RequestMapping("/table-qrcode"), extends BaseController, autowire ITableQrcodeService + IInfoUserService + IPosStoreService
- [x] T009 [US1] Implement POST `/table-qrcode/add` — validate tableNo required, type=0 requires storeId, type=1 no storeId; get userId from JwtUtil, lookup InfoUser for userType; stall owner (type=4) auto-fills storeId from user info; night market admin (type=3) gets nightMarketId from user info; check duplicate tableNo under same store/night market; generate qrCode URL and save
- [x] T010 [US1] Implement GET `/table-qrcode/list` — support query params (storeId, type, status, useStatus); stall owner only sees own storeId; night market admin sees all under nightMarketId; return list with storeName join
- [x] T011 [US1] Implement GET `/table-qrcode/{id}` — return detail with storeName; verify ownership (stall owner can only get own codes)
- [x] T012 [US1] Implement PUT `/table-qrcode/update` — allow updating tableNo and remark only (not type or storeId); verify ownership
- [x] T013 [US1] Implement DELETE `/table-qrcode/delete/{id}` — reject if useStatus=1 (in use); verify ownership
- [x] T014 [US1] Implement PUT `/table-qrcode/changeStatus` — toggle status between 0 and 1; verify ownership

**Checkpoint**: 所有 CRUD API 可通过 HTTP 工具独立测试

---

## Phase 4: User Story 2 — 二维码生成与展示 (Priority: P2)

**Goal**: 可以查看和下载餐桌二维码图片

**Independent Test**: 调用二维码接口，返回 Base64 图片数据，可解码还原为 URL

### Implementation

- [x] T015 [US2] Implement QR code generation utility in `TableQrcodeServiceImpl` — use ZXing BitMatrix → PNG → Base64 encode; generate 300x300 QR image from qrCode URL field
- [x] T016 [US2] Implement GET `/table-qrcode/qrcode/{id}` endpoint — if qrCode field is null, generate URL and save first; return Base64 encoded PNG image in AjaxResult data field

**Checkpoint**: 通过 API 可以获取到 Base64 格式的二维码图片

---

## Phase 5: User Story 3 — 扫码跳转入口 (Priority: P3)

**Goal**: 顾客扫码后跳转到对应的页面（摊位商品或摊位选择）

**Independent Test**: 浏览器访问 scan URL，验证重定向到正确页面

### Implementation

- [x] T017 [US3] Implement GET `/table-qrcode/scan` endpoint — validate tableId exists and status=0 (enabled); update useStatus to 1; type=0 redirect to store product page with storeId + tableId; type=1 redirect to stall selection page with nightMarketId + tableId

**Checkpoint**: 浏览器访问 scan URL 能正确重定向

---

## Phase 6: User Story 4 — 前端管理页面 (Priority: P2)

**Goal**: 商家端有完整的餐桌码管理页面

**Independent Test**: 启动 foodie-store 前端，访问 /table-qrcode 页面，完成创建→列表→查看二维码→编辑→删除完整流程

### Implementation

- [x] T018 [P] [US4] Create API module `foodie-store/src/api/tableQrcode.js` — define all API calls (add, list, getById, update, delete, changeStatus, getQrcodeImage) using axios request util from src/router/request.js
- [x] T019 [US4] Create `foodie-store/src/views/TableQRCode.vue` management page with:
  - Filter section: type select, status select, query button
  - Data table: tableNo, type (摊位码/公用码 tag), storeName, useStatus (空闲/使用中 tag), status (el-switch toggle), operations (查看二维码, 编辑, 删除)
  - Create/Edit dialog: tableNo input, type select (el-radio), remark textarea
  - QR code dialog: el-image showing base64 QR code, download button
  - Follow existing patterns from StallManage.vue (Element UI components, layout, loading states)
- [x] T020 [US4] Register `/table-qrcode` route in `foodie-store/src/router/index.js` pointing to TableQRCode.vue component

**Checkpoint**: 前端完整功能可用，可以完成 CRUD + 查看二维码全流程

---

## Phase 7: Polish & Cross-Cutting Concerns

**Purpose**: 集成测试和优化

- [ ] T021 Verify backend compilation with no errors (mvn compile)
- [ ] T022 Verify frontend build with no errors (npm run build)
- [ ] T023 Run quickstart.md validation — test complete flow: create → list → QR code → edit → disable → delete
- [ ] T024 Verify permission isolation — stall owner cannot access other stalls' codes, night market admin can view all

## Phase 8: 餐桌码列表补全门店名称（2026-08-24）

- [x] T025 为 `TableQrcodeController.list` 增加回归测试，验证关联门店的餐桌码返回正确 `storeName`，无 `storeId` 的公用码返回 `null` — `ruoyi-admin/src/test/java/com/ruoyi/app/tableqrcode/TableQrcodeControllerTest.java`
- [x] T026 保留现有权限查询，在列表返回前批量查询涉及的门店并回填 `storeName`，不得逐条查库 — `ruoyi-admin/src/main/java/com/ruoyi/app/tableqrcode/TableQrcodeController.java`
- [x] T027 使用 JDK 21 运行 `TableQrcodeControllerTest`、受影响模块构建及差异检查

---

## Dependencies & Execution Order

### Phase Dependencies

- **Setup (Phase 1)**: No dependencies — start immediately
- **Foundational (Phase 2)**: Depends on Phase 1 completion — BLOCKS all user stories
- **US1 CRUD (Phase 3)**: Depends on Phase 2
- **US2 二维码 (Phase 4)**: Depends on Phase 2 and Phase 3 (needs CRUD to create data first)
- **US3 扫码 (Phase 5)**: Depends on Phase 2
- **US4 前端 (Phase 6)**: Depends on Phase 3 + Phase 4 (needs working backend APIs)
- **Polish (Phase 7)**: Depends on all phases

### User Story Dependencies

- **US1 (CRUD)**: Depends on Foundational — no dependency on other stories
- **US2 (二维码)**: Depends on US1 (needs data to generate QR codes for)
- **US3 (扫码)**: Depends on Foundational only — can parallel with US1
- **US4 (前端)**: Depends on US1 + US2 (needs backend APIs ready)

### Parallel Opportunities

- T004 + T005 can run in parallel (different files)
- T018 can start in parallel with Phase 3/4 backend work (API module independent)
- T017 (scan endpoint) can be developed in parallel with US2 (二维码)

---

## Implementation Strategy

### MVP (US1 + US2)

1. Phase 1: Setup (dependencies + table)
2. Phase 2: Foundational (Entity, Mapper, Service)
3. Phase 3: US1 CRUD API
4. Phase 4: US2 二维码生成
5. Phase 6: US4 前端页面 (T018 → T019 → T020)
6. Phase 7: Polish (T021-T024)
7. **STOP and VALIDATE**: 完整流程测试

### Full Delivery (add US3)

8. Phase 5: US3 扫码入口
9. Final integration test

---

## Notes

- [P] tasks = different files, no dependencies
- [Story] label maps task to specific user story for traceability
- Backend paths use forward slashes in Java packages
- Frontend is a separate project at E:\QtwCode\foodie\foodie-store
- Follow existing project patterns exactly (see research.md for pattern decisions)
- Commit after each task or logical group
- Stop at any checkpoint to validate independently
