|
|
@@ -0,0 +1,682 @@
|
|
|
+# Implementation Plan: Industry Invoice Platform (行业发票平台)
|
|
|
+
|
|
|
+**Date:** 2026-07-08
|
|
|
+**Branch:** fapiao
|
|
|
+**Status:** Planning
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## Overview
|
|
|
+
|
|
|
+Copy the Alipay industry invoice platform (https://fxkp.alipay.com/industry-invoice-platform/) as a new module in the payment platform. 8 pages with full CRUD, import/export, and mock APIs. Multi-tenant + enterprise + admin data scoping on all tables.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 1. Database Tables
|
|
|
+
|
|
|
+All tables use `PaymentEnterpriseBaseEntity` (inherits `PaymentTenantBaseEntity` → `PaymentBaseEntity`), providing: `id` (snowflake), `status`, `description`, `created_time`, `updated_time`, `tenant_id`, `enterprise_id`.
|
|
|
+
|
|
|
+Flyway migration file: `V1.2__create_pay_invoice_tables.sql`
|
|
|
+
|
|
|
+### 1.1 `pay_invoice_order` — 交易及发票订单
|
|
|
+
|
|
|
+| Column | Type | Constraint | Notes |
|
|
|
+|---|---|---|---|
|
|
|
+| id | BIGINT | PK (snowflake) | From PaymentEnterpriseBaseEntity |
|
|
|
+| status | VARCHAR(10) | DEFAULT '0' | From PaymentEnterpriseBaseEntity |
|
|
|
+| description | TEXT | | From PaymentEnterpriseBaseEntity |
|
|
|
+| created_time | TIMESTAMP | NOT NULL DEFAULT NOW() | From PaymentEnterpriseBaseEntity |
|
|
|
+| updated_time | TIMESTAMP | NOT NULL DEFAULT NOW() | From PaymentEnterpriseBaseEntity |
|
|
|
+| tenant_id | BIGINT | | From PaymentTenantBaseEntity |
|
|
|
+| enterprise_id | VARCHAR(64) | | From PaymentEnterpriseBaseEntity |
|
|
|
+| order_no | VARCHAR(64) | NOT NULL | 订单编号 |
|
|
|
+| alipay_trade_no | VARCHAR(64) | | 支付宝交易号 |
|
|
|
+| payment_time | TIMESTAMP | | 支付时间 |
|
|
|
+| natural_person_name | VARCHAR(64) | | 自然人姓名 |
|
|
|
+| collection_account_type | VARCHAR(32) | | 收款账户类型: ALIPAY / BANK_CARD |
|
|
|
+| tax_inclusive_amount | DECIMAL(18,2) | | 含税金额 |
|
|
|
+| trade_status | VARCHAR(32) | NOT NULL DEFAULT 'PENDING_ASSOCIATE' | 交易状态 |
|
|
|
+| invoice_no | VARCHAR(64) | | 发票号码 |
|
|
|
+| invoice_pretax_amount | DECIMAL(18,2) | | 发票税前金额 |
|
|
|
+| invoice_tax_amount | DECIMAL(18,2) | | 发票税额 |
|
|
|
+| red_invoice_no | VARCHAR(64) | | 红票号码 |
|
|
|
+| clerk_name | VARCHAR(64) | | 营业员姓名 |
|
|
|
+| attachment_url | TEXT | | 附件URL JSON array |
|
|
|
+
|
|
|
+Indexes:
|
|
|
+- `idx_invoice_order_enterprise` ON `(enterprise_id)`
|
|
|
+- `idx_invoice_order_order_no` ON `(order_no)`
|
|
|
+- `idx_invoice_order_trade_no` ON `(alipay_trade_no)`
|
|
|
+- `idx_invoice_order_trade_status` ON `(trade_status)`
|
|
|
+- `idx_invoice_order_created_time` ON `(created_time)`
|
|
|
+
|
|
|
+### 1.2 `pay_invoice_supplier` — 供应商
|
|
|
+
|
|
|
+| Column | Type | Constraint | Notes |
|
|
|
+|---|---|---|---|
|
|
|
+| id | BIGINT | PK (snowflake) | |
|
|
|
+| status, description, created_time, updated_time, tenant_id, enterprise_id | | | From base entities |
|
|
|
+| supplier_name | VARCHAR(128) | NOT NULL | 供应商名称 |
|
|
|
+| account_type | VARCHAR(32) | NOT NULL | ALIPAY_PHONE / ALIPAY_EMAIL |
|
|
|
+| collection_account | VARCHAR(128) | NOT NULL | 收款账户 |
|
|
|
+| phone | VARCHAR(20) | | 联系电话 |
|
|
|
+| confirm_status | VARCHAR(32) | NOT NULL DEFAULT 'PENDING' | CONFIRMED / PENDING / REJECTED |
|
|
|
+
|
|
|
+Indexes:
|
|
|
+- `idx_invoice_supplier_enterprise` ON `(enterprise_id)`
|
|
|
+- `idx_invoice_supplier_name` ON `(supplier_name)`
|
|
|
+- `idx_invoice_supplier_confirm_status` ON `(confirm_status)`
|
|
|
+
|
|
|
+### 1.3 `pay_invoice_employee` — 员工管理
|
|
|
+
|
|
|
+| Column | Type | Constraint | Notes |
|
|
|
+|---|---|---|---|
|
|
|
+| id | BIGINT | PK (snowflake) | |
|
|
|
+| status, description, created_time, updated_time, tenant_id, enterprise_id | | | From base entities |
|
|
|
+| employee_name | VARCHAR(64) | NOT NULL | 员工姓名 |
|
|
|
+| phone | VARCHAR(20) | NOT NULL | 手机号 |
|
|
|
+| id_number | VARCHAR(20) | NOT NULL | 身份证号 |
|
|
|
+| role | VARCHAR(32) | NOT NULL | CLERK / INVOICER / SUPER_ADMIN |
|
|
|
+| allow_miniapp_supplier | BOOLEAN | DEFAULT FALSE | 允许小程序选供应商 |
|
|
|
+
|
|
|
+Indexes:
|
|
|
+- `idx_invoice_employee_enterprise` ON `(enterprise_id)`
|
|
|
+- `idx_invoice_employee_role` ON `(role)`
|
|
|
+
|
|
|
+### 1.4 `pay_invoice_product` — 常用商品
|
|
|
+
|
|
|
+| Column | Type | Constraint | Notes |
|
|
|
+|---|---|---|---|
|
|
|
+| id | BIGINT | PK (snowflake) | |
|
|
|
+| status, description, created_time, updated_time, tenant_id, enterprise_id | | | From base entities |
|
|
|
+| product_name | VARCHAR(128) | NOT NULL | 商品名称 |
|
|
|
+| category | VARCHAR(32) | NOT NULL | 报废产品分类 |
|
|
|
+| unit | VARCHAR(32) | | 单位 |
|
|
|
+| spec | VARCHAR(128) | | 规格 |
|
|
|
+
|
|
|
+Indexes:
|
|
|
+- `idx_invoice_product_enterprise` ON `(enterprise_id)`
|
|
|
+- `idx_invoice_product_category` ON `(category)`
|
|
|
+
|
|
|
+### 1.5 `pay_invoice_company` — 企业信息
|
|
|
+
|
|
|
+| Column | Type | Constraint | Notes |
|
|
|
+|---|---|---|---|
|
|
|
+| id | BIGINT | PK (snowflake) | |
|
|
|
+| status, description, created_time, updated_time, tenant_id, enterprise_id | | | From base entities |
|
|
|
+| company_name | VARCHAR(128) | | 企业名称 |
|
|
|
+| tax_id | VARCHAR(64) | | 税号 |
|
|
|
+| bank_name | VARCHAR(128) | | 开户银行 |
|
|
|
+| bank_account | VARCHAR(64) | | 银行账号 |
|
|
|
+| address | VARCHAR(256) | | 地址 |
|
|
|
+| phone | VARCHAR(20) | | 电话 |
|
|
|
+| tax_region | VARCHAR(64) | | 纳税地区 |
|
|
|
+| issuer | VARCHAR(64) | | 开票人 |
|
|
|
+| contact_name | VARCHAR(64) | | 业务联系人姓名 |
|
|
|
+| contact_phone | VARCHAR(20) | | 业务联系人电话 |
|
|
|
+| monthly_quota | DECIMAL(18,2) | DEFAULT 10000000 | 月度授信额度 |
|
|
|
+| available_quota | DECIMAL(18,2) | | 可用额度 |
|
|
|
+| downloaded_count | INTEGER | DEFAULT 0 | 已下载张数 |
|
|
|
+| used_count | INTEGER | DEFAULT 0 | 已使用张数 |
|
|
|
+| tax_calculation_method | VARCHAR(32) | DEFAULT 'SIMPLE' | 计税方式 |
|
|
|
+| default_invoice_type | VARCHAR(32) | DEFAULT 'NORMAL' | 默认票种 |
|
|
|
+| default_tax_rate | VARCHAR(16) | DEFAULT '1%' | 默认税率 |
|
|
|
+| audit_after_payment | BOOLEAN | DEFAULT TRUE | 货品审核后付款 |
|
|
|
+| invite_as_supplier | BOOLEAN | DEFAULT FALSE | 邀请为供应商 |
|
|
|
+| receipt_plaintext | BOOLEAN | DEFAULT FALSE | 电子回单明文 |
|
|
|
+| employee_quota_management | BOOLEAN | DEFAULT FALSE | 员工额度管理 |
|
|
|
+
|
|
|
+Index:
|
|
|
+- `idx_invoice_company_enterprise` ON `(enterprise_id)` UNIQUE (one record per enterprise)
|
|
|
+
|
|
|
+### 1.6 `pay_invoice_task` — 任务中心
|
|
|
+
|
|
|
+| Column | Type | Constraint | Notes |
|
|
|
+|---|---|---|---|
|
|
|
+| id | BIGINT | PK (snowflake) | |
|
|
|
+| status, description, created_time, updated_time, tenant_id, enterprise_id | | | From base entities |
|
|
|
+| task_type | VARCHAR(32) | NOT NULL | 任务类型 |
|
|
|
+| task_status | VARCHAR(32) | NOT NULL DEFAULT 'PENDING' | PENDING / PROCESSING / SUCCESS / FAILED |
|
|
|
+| start_time | TIMESTAMP | | 任务开始时间 |
|
|
|
+| completion_time | TIMESTAMP | | 完成时间 |
|
|
|
+| product_name | VARCHAR(128) | | 商品名称 |
|
|
|
+| file_url | VARCHAR(512) | | 导出文件URL |
|
|
|
+| total_count | INTEGER | DEFAULT 0 | 总记录数 |
|
|
|
+| success_count | INTEGER | DEFAULT 0 | 成功数 |
|
|
|
+| fail_count | INTEGER | DEFAULT 0 | 失败数 |
|
|
|
+| error_message | TEXT | | 错误信息 |
|
|
|
+
|
|
|
+Indexes:
|
|
|
+- `idx_invoice_task_enterprise` ON `(enterprise_id)`
|
|
|
+- `idx_invoice_task_type` ON `(task_type)`
|
|
|
+- `idx_invoice_task_status` ON `(task_status)`
|
|
|
+
|
|
|
+### 1.7 `pay_invoice_tax_payment` — 缴税记录
|
|
|
+
|
|
|
+| Column | Type | Constraint | Notes |
|
|
|
+|---|---|---|---|
|
|
|
+| id | BIGINT | PK (snowflake) | |
|
|
|
+| status, description, created_time, updated_time, tenant_id, enterprise_id | | | From base entities |
|
|
|
+| payment_mode | VARCHAR(32) | NOT NULL | INDIVIDUAL / ENTERPRISE_PROXY |
|
|
|
+| tax_amount | DECIMAL(18,2) | | 缴税金额 |
|
|
|
+| tax_period | VARCHAR(32) | | 纳税期间 |
|
|
|
+| payment_time | TIMESTAMP | | 缴税时间 |
|
|
|
+| payment_status | VARCHAR(32) | DEFAULT 'UNPAID' | UNPAID / PAID |
|
|
|
+| enterprise_proxy_enabled | BOOLEAN | DEFAULT FALSE | 是否开通企业代缴 |
|
|
|
+
|
|
|
+Indexes:
|
|
|
+- `idx_invoice_tax_enterprise` ON `(enterprise_id)`
|
|
|
+- `idx_invoice_tax_status` ON `(payment_status)`
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 2. Backend Module Structure
|
|
|
+
|
|
|
+```
|
|
|
+module/payment/invoice/
|
|
|
+├── InvoiceModuleConfig.java (optional: module-level @Configuration if needed)
|
|
|
+
|
|
|
+├── order/ # 1. 交易及发票管理
|
|
|
+│ ├── controller/
|
|
|
+│ │ └── OrderController.java
|
|
|
+│ ├── dto/
|
|
|
+│ │ ├── OrderQueryDTO.java
|
|
|
+│ │ ├── OrderVO.java
|
|
|
+│ │ ├── OrderBatchImportDTO.java
|
|
|
+│ │ ├── OrderBatchCancelDTO.java
|
|
|
+│ │ └── InvoiceDetailVO.java
|
|
|
+│ ├── entity/
|
|
|
+│ │ └── OrderEntity.java
|
|
|
+│ ├── enums/
|
|
|
+│ │ └── OrderEnums.java (TradeStatus, CollectionAccountType)
|
|
|
+│ ├── mapper/
|
|
|
+│ │ └── OrderMapper.java
|
|
|
+│ └── service/
|
|
|
+│ ├── OrderService.java (list, detail, batchImport, batchCancel, export)
|
|
|
+│ └── impl/
|
|
|
+│ └── OrderServiceImpl.java (optional — if following existing pattern)
|
|
|
+
|
|
|
+├── account/ # 2. 转账账户管理
|
|
|
+│ ├── controller/
|
|
|
+│ │ └── InvoiceAccountController.java
|
|
|
+│ ├── dto/
|
|
|
+│ │ └── AccountBalanceVO.java
|
|
|
+│ ├── entity/
|
|
|
+│ │ └── InvoiceAccountEntity.java
|
|
|
+│ ├── mapper/
|
|
|
+│ │ └── InvoiceAccountMapper.java
|
|
|
+│ └── service/
|
|
|
+│ └── InvoiceAccountService.java
|
|
|
+
|
|
|
+├── tax/ # 3. 缴税管理
|
|
|
+│ ├── controller/
|
|
|
+│ │ └── TaxPaymentController.java
|
|
|
+│ ├── dto/
|
|
|
+│ │ ├── TaxPaymentQueryDTO.java
|
|
|
+│ │ └── TaxPaymentVO.java
|
|
|
+│ ├── entity/
|
|
|
+│ │ └── TaxPaymentEntity.java
|
|
|
+│ ├── enums/
|
|
|
+│ │ └── TaxEnums.java (PaymentMode, PaymentStatus)
|
|
|
+│ ├── mapper/
|
|
|
+│ │ └── TaxPaymentMapper.java
|
|
|
+│ └── service/
|
|
|
+│ └── TaxPaymentService.java
|
|
|
+
|
|
|
+├── employee/ # 4. 员工管理
|
|
|
+│ ├── controller/
|
|
|
+│ │ └── InvoiceEmployeeController.java
|
|
|
+│ ├── dto/
|
|
|
+│ │ ├── EmployeeSaveDTO.java
|
|
|
+│ │ └── EmployeeVO.java
|
|
|
+│ ├── entity/
|
|
|
+│ │ └── InvoiceEmployeeEntity.java
|
|
|
+│ ├── enums/
|
|
|
+│ │ └── InvoiceEmployeeEnums.java (EmployeeRole)
|
|
|
+│ ├── mapper/
|
|
|
+│ │ └── InvoiceEmployeeMapper.java
|
|
|
+│ └── service/
|
|
|
+│ └── InvoiceEmployeeService.java
|
|
|
+
|
|
|
+├── product/ # 5. 常用商品管理
|
|
|
+│ ├── controller/
|
|
|
+│ │ └── ProductController.java
|
|
|
+│ ├── dto/
|
|
|
+│ │ ├── ProductSaveDTO.java
|
|
|
+│ │ └── ProductVO.java
|
|
|
+│ ├── entity/
|
|
|
+│ │ └── ProductEntity.java
|
|
|
+│ ├── enums/
|
|
|
+│ │ └── ProductEnums.java (ProductCategory)
|
|
|
+│ ├── mapper/
|
|
|
+│ │ └── ProductMapper.java
|
|
|
+│ └── service/
|
|
|
+│ └── ProductService.java
|
|
|
+
|
|
|
+├── company/ # 6. 企业信息
|
|
|
+│ ├── controller/
|
|
|
+│ │ └── CompanyController.java
|
|
|
+│ ├── dto/
|
|
|
+│ │ ├── CompanyVO.java
|
|
|
+│ │ ├── ContactUpdateDTO.java
|
|
|
+│ │ └── InvoiceInfoUpdateDTO.java
|
|
|
+│ ├── entity/
|
|
|
+│ │ └── CompanyEntity.java
|
|
|
+│ ├── enums/
|
|
|
+│ │ └── CompanyEnums.java (TaxCalcMethod, DefaultInvoiceType)
|
|
|
+│ ├── mapper/
|
|
|
+│ │ └── CompanyMapper.java
|
|
|
+│ └── service/
|
|
|
+│ └── CompanyService.java
|
|
|
+
|
|
|
+├── supplier/ # 7. 供应商管理
|
|
|
+│ ├── controller/
|
|
|
+│ │ └── SupplierController.java
|
|
|
+│ ├── dto/
|
|
|
+│ │ ├── SupplierSaveDTO.java
|
|
|
+│ │ ├── SupplierQueryDTO.java
|
|
|
+│ │ └── SupplierVO.java
|
|
|
+│ ├── entity/
|
|
|
+│ │ └── SupplierEntity.java
|
|
|
+│ ├── enums/
|
|
|
+│ │ └── SupplierEnums.java (AccountType, ConfirmStatus)
|
|
|
+│ ├── mapper/
|
|
|
+│ │ └── SupplierMapper.java
|
|
|
+│ └── service/
|
|
|
+│ └── SupplierService.java
|
|
|
+
|
|
|
+└── task/ # 8. 任务中心
|
|
|
+ ├── controller/
|
|
|
+ │ └── TaskController.java
|
|
|
+ ├── dto/
|
|
|
+ │ ├── TaskQueryDTO.java
|
|
|
+ │ └── TaskVO.java
|
|
|
+ ├── entity/
|
|
|
+ │ └── TaskEntity.java
|
|
|
+ ├── enums/
|
|
|
+ │ └── TaskEnums.java (TaskType, TaskStatus)
|
|
|
+ ├── mapper/
|
|
|
+ │ └── TaskMapper.java
|
|
|
+ ├── scheduler/
|
|
|
+ │ └── InvoiceTaskScheduler.java (poll export/import tasks, execute asynchronously)
|
|
|
+ └── service/
|
|
|
+ ├── TaskService.java
|
|
|
+ └── InvoiceMockDataService.java (singleton mock data factory for all modules)
|
|
|
+```
|
|
|
+
|
|
|
+**Key design decisions:**
|
|
|
+- Controllers: `@RestController` with `@RequestMapping("/payment/invoice/<submodule>")`
|
|
|
+- Services: `@Service @RequiredArgsConstructor` using `LambdaQueryWrapper` for queries
|
|
|
+- Mappers: `@Mapper extends BaseMapper<Entity>`
|
|
|
+- All entities extend `PaymentEnterpriseBaseEntity` (auto-tenant + auto-enterprise)
|
|
|
+- `InvoiceMockDataService` generates realistic mock data using Faker-like patterns for all modules
|
|
|
+- PageResult wrapping: `PageResult.of(pageNo, pageSize, total, items)`
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 3. API Endpoints (Mock Implementations)
|
|
|
+
|
|
|
+### 3.1 Order Controller
|
|
|
+```
|
|
|
+GET /payment/invoice/order/list — paginated list with filters
|
|
|
+GET /payment/invoice/order/{id} — order detail
|
|
|
+GET /payment/invoice/order/invoice/{id} — invoice detail (红票/蓝票)
|
|
|
+POST /payment/invoice/order/batch-import — batch import (multipart .xlsx)
|
|
|
+POST /payment/invoice/order/batch-cancel — batch cancel by order IDs
|
|
|
+GET /payment/invoice/order/export/orders — export orders as .xlsx
|
|
|
+GET /payment/invoice/order/export/invoices — export invoices as .xlsx
|
|
|
+GET /payment/invoice/order/template — download import template
|
|
|
+```
|
|
|
+
|
|
|
+### 3.2 Account Controller
|
|
|
+```
|
|
|
+GET /payment/invoice/account/balance — get account balance + pending amount
|
|
|
+GET /payment/invoice/account/recharge-info — get recharge bank account info
|
|
|
+POST /payment/invoice/account/recharge — (mock) recharge
|
|
|
+```
|
|
|
+
|
|
|
+### 3.3 Tax Payment Controller
|
|
|
+```
|
|
|
+GET /payment/invoice/tax/config — get tax payment config (mode, proxy enabled)
|
|
|
+POST /payment/invoice/tax/mode — set payment mode (individual / enterprise)
|
|
|
+POST /payment/invoice/tax/enable-proxy — enable enterprise proxy payment
|
|
|
+GET /payment/invoice/tax/records — tax payment history
|
|
|
+```
|
|
|
+
|
|
|
+### 3.4 Employee Controller
|
|
|
+```
|
|
|
+GET /payment/invoice/employee/list — employee list
|
|
|
+POST /payment/invoice/employee — add employee
|
|
|
+PUT /payment/invoice/employee/{id} — update employee
|
|
|
+DELETE /payment/invoice/employee/{id} — delete employee
|
|
|
+```
|
|
|
+
|
|
|
+### 3.5 Product Controller
|
|
|
+```
|
|
|
+GET /payment/invoice/product/list — product list (filter by category)
|
|
|
+POST /payment/invoice/product — add product
|
|
|
+PUT /payment/invoice/product/{id} — update product
|
|
|
+DELETE /payment/invoice/product/{id} — delete product
|
|
|
+GET /payment/invoice/product/categories — category tree
|
|
|
+```
|
|
|
+
|
|
|
+### 3.6 Company Controller
|
|
|
+```
|
|
|
+GET /payment/invoice/company/info — get company info (auto-create if missing)
|
|
|
+POST /payment/invoice/company/sync-tax — mock sync tax info
|
|
|
+POST /payment/invoice/company/verify — mock company verification
|
|
|
+PUT /payment/invoice/company/contact — update contact info
|
|
|
+PUT /payment/invoice/company/invoice-info — update invoice settings
|
|
|
+PUT /payment/invoice/company/trade-rules — update trade rule toggles
|
|
|
+```
|
|
|
+
|
|
|
+### 3.7 Supplier Controller
|
|
|
+```
|
|
|
+GET /payment/invoice/supplier/list — paginated list with search filters
|
|
|
+POST /payment/invoice/supplier — add supplier
|
|
|
+PUT /payment/invoice/supplier/{id} — update supplier
|
|
|
+DELETE /payment/invoice/supplier/{id} — delete supplier
|
|
|
+POST /payment/invoice/supplier/batch-import — batch import (.xlsx)
|
|
|
+GET /payment/invoice/supplier/template — download import template
|
|
|
+```
|
|
|
+
|
|
|
+### 3.8 Task Controller
|
|
|
+```
|
|
|
+GET /payment/invoice/task/list — paginated task list
|
|
|
+GET /payment/invoice/task/{id} — task detail
|
|
|
+GET /payment/invoice/task/{id}/download — download export file
|
|
|
+```
|
|
|
+
|
|
|
+### Mock Data Strategy
|
|
|
+
|
|
|
+`InvoiceMockDataService` will be injected into each service constructor. It generates:
|
|
|
+
|
|
|
+- **Orders:** 50+ records with realistic Chinese names, amounts, statuses distributed across all 8 statuses
|
|
|
+- **Employees:** 5-10 records with masked phone/ID
|
|
|
+- **Products:** 20+ products distributed across all 9 categories
|
|
|
+- **Company:** 1 record per enterprise with hardcoded defaults (10M quota)
|
|
|
+- **Suppliers:** 15+ records with various account types and confirm statuses
|
|
|
+- **Tasks:** 10+ historical tasks with various types and statuses
|
|
|
+- **Account:** Fixed balance values
|
|
|
+
|
|
|
+Each service method checks if real data exists; if not, falls back to mock data.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 4. Frontend Component Structure
|
|
|
+
|
|
|
+```
|
|
|
+src/views/module_payment/invoice/
|
|
|
+├── order/
|
|
|
+│ ├── index.vue # main page with search + table
|
|
|
+│ ├── components/
|
|
|
+│ │ ├── SearchForm.vue # search filters
|
|
|
+│ │ ├── OrderTable.vue # data table with actions
|
|
|
+│ │ ├── OrderDetailDialog.vue # order detail modal
|
|
|
+│ │ ├── InvoiceDetailDialog.vue # invoice detail (红票/蓝票) modal
|
|
|
+│ │ └── BatchImportDialog.vue # batch import with template download + upload
|
|
|
+│ └── index.ts # (if needed for local types)
|
|
|
+
|
|
|
+├── account/
|
|
|
+│ ├── index.vue # balance display + recharge section
|
|
|
+│ └── components/
|
|
|
+│ ├── BalanceCard.vue # account balance + pending amount
|
|
|
+│ └── RechargeGuide.vue # collapsible "how to recharge" section
|
|
|
+
|
|
|
+├── payTaxes/
|
|
|
+│ ├── index.vue # tax payment mode selection
|
|
|
+│ └── components/
|
|
|
+│ ├── IndividualPayment.vue # 个人缴税 view
|
|
|
+│ └── EnterpriseProxy.vue # 企业代缴 view with "立即开通" flow
|
|
|
+
|
|
|
+├── employeeManagement/
|
|
|
+│ ├── index.vue # employee list + add/edit dialogs
|
|
|
+│ └── components/
|
|
|
+│ ├── EmployeeTable.vue # table with masked fields
|
|
|
+│ ├── AddEmployeeDialog.vue # role selector + dynamic form
|
|
|
+│ └── EditEmployeeDialog.vue # role readonly, edit form
|
|
|
+
|
|
|
+├── goods/
|
|
|
+│ ├── index.vue # left category tree + right product table
|
|
|
+│ └── components/
|
|
|
+│ ├── CategoryTree.vue # 9-category scrapped product tree
|
|
|
+│ └── ProductTable.vue # product list by selected category
|
|
|
+
|
|
|
+├── company/
|
|
|
+│ ├── index.vue # enterprise info dashboard
|
|
|
+│ └── components/
|
|
|
+│ ├── BasicInfoSection.vue # 8 read-only fields
|
|
|
+│ ├── ContactSection.vue # editable contact
|
|
|
+│ ├── CreditLimitSection.vue # 授信额度 4 fields
|
|
|
+│ ├── InvoiceInfoSection.vue # editable invoice settings
|
|
|
+│ ├── TradeRuleSection.vue # 4 toggle switches
|
|
|
+│ └── ServiceProviderSection.vue # 服务商授权管理 link
|
|
|
+
|
|
|
+├── suppliers/
|
|
|
+│ ├── index.vue # supplier list with search + batch import
|
|
|
+│ └── components/
|
|
|
+│ ├── SupplierTable.vue # table with confirm_status filter
|
|
|
+│ ├── AddSupplierDialog.vue # add/edit with save+next
|
|
|
+│ └── BatchImportSupplier.vue # batch import dialog
|
|
|
+
|
|
|
+└── tasks/
|
|
|
+ ├── index.vue # task center with search
|
|
|
+ └── components/
|
|
|
+ ├── TaskTable.vue # task list
|
|
|
+ └── TaskDetailDrawer.vue # task detail side panel
|
|
|
+```
|
|
|
+
|
|
|
+API modules:
|
|
|
+```
|
|
|
+src/api/module_payment/invoice/
|
|
|
+├── order.ts
|
|
|
+├── account.ts
|
|
|
+├── tax.ts
|
|
|
+├── employee.ts
|
|
|
+├── product.ts
|
|
|
+├── company.ts
|
|
|
+├── supplier.ts
|
|
|
+└── task.ts
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 5. Menu Tree Structure (sys_menu table)
|
|
|
+
|
|
|
+Insert SQL in a migration or seed file. Menu entries reference the dynamic component paths that the frontend `transformRoutes` resolves via `import.meta.glob("../../views/**/**.vue")`.
|
|
|
+
|
|
|
+```
|
|
|
+Industry Invoice Platform (parent menu)
|
|
|
+├── type: 1 (directory), route_path: /invoice-platform, route_name: InvoicePlatform
|
|
|
+│ component_path: (empty, Layout handles it), icon: "invoice", order: 500
|
|
|
+
|
|
|
+├── 交易及发票管理 (type: 2 menu)
|
|
|
+│ parent_id: <parent>, route_path: /invoice-platform/order
|
|
|
+│ route_name: InvoiceOrder, component_path: module_payment/invoice/order/index
|
|
|
+│ permission: module_payment:invoice:order:list
|
|
|
+
|
|
|
+├── 转账账户管理
|
|
|
+│ parent_id: <parent>, route_path: /invoice-platform/account
|
|
|
+│ route_name: InvoiceAccount, component_path: module_payment/invoice/account/index
|
|
|
+│ permission: module_payment:invoice:account:view
|
|
|
+
|
|
|
+├── 缴税管理
|
|
|
+│ parent_id: <parent>, route_path: /invoice-platform/payTaxes
|
|
|
+│ route_name: InvoicePayTaxes, component_path: module_payment/invoice/payTaxes/index
|
|
|
+│ permission: module_payment:invoice:tax:view
|
|
|
+
|
|
|
+├── 员工管理
|
|
|
+│ parent_id: <parent>, route_path: /invoice-platform/employee
|
|
|
+│ route_name: InvoiceEmployee, component_path: module_payment/invoice/employeeManagement/index
|
|
|
+│ permission: module_payment:invoice:employee:list
|
|
|
+
|
|
|
+├── 常用商品管理
|
|
|
+│ parent_id: <parent>, route_path: /invoice-platform/goods
|
|
|
+│ route_name: InvoiceGoods, component_path: module_payment/invoice/goods/index
|
|
|
+│ permission: module_payment:invoice:product:list
|
|
|
+
|
|
|
+├── 企业信息
|
|
|
+│ parent_id: <parent>, route_path: /invoice-platform/company
|
|
|
+│ route_name: InvoiceCompany, component_path: module_payment/invoice/company/index
|
|
|
+│ permission: module_payment:invoice:company:view
|
|
|
+
|
|
|
+├── 供应商管理
|
|
|
+│ parent_id: <parent>, route_path: /invoice-platform/suppliers
|
|
|
+│ route_name: InvoiceSuppliers, component_path: module_payment/invoice/suppliers/index
|
|
|
+│ permission: module_payment:invoice:supplier:list
|
|
|
+
|
|
|
+└── 任务中心
|
|
|
+ parent_id: <parent>, route_path: /invoice-platform/tasks
|
|
|
+ route_name: InvoiceTasks, component_path: module_payment/invoice/tasks/index
|
|
|
+ permission: module_payment:invoice:task:list
|
|
|
+```
|
|
|
+
|
|
|
+**Important:** The `component_path` values must match the file structure `module_payment/invoice/<folder>/index.vue`, because the permission store's `transformRoutes` resolves these with `modules[`../../views/${normalizedRoute.component}.vue`]`.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 6. Implementation Order (7 phases)
|
|
|
+
|
|
|
+### Phase 1: Database + Entities (Foundation)
|
|
|
+1. Create `V1.2__create_pay_invoice_tables.sql` with all 7 tables + indexes
|
|
|
+2. Run migration
|
|
|
+3. Create all entity classes extending `PaymentEnterpriseBaseEntity`
|
|
|
+4. Create all enum classes
|
|
|
+5. Create all mapper interfaces
|
|
|
+
|
|
|
+### Phase 2: Mock Service + Core Backend
|
|
|
+1. Implement `InvoiceMockDataService` with mock data generation
|
|
|
+2. Implement `CompanyService` — single-record per enterprise, auto-create on first access
|
|
|
+3. Implement `OrderService` — list, detail, batch cancel, export
|
|
|
+4. Implement `SupplierService` — list, CRUD, batch import
|
|
|
+5. Implement `InvoiceEmployeeService` — CRUD
|
|
|
+6. Implement `ProductService` — CRUD + categories
|
|
|
+7. Implement `InvoiceAccountService` — balance query
|
|
|
+8. Implement `TaxPaymentService` — config + history
|
|
|
+9. Implement `TaskService` — list, detail
|
|
|
+
|
|
|
+### Phase 3: Backend Controllers
|
|
|
+1. Create all DTOs (VO + QueryDTO + SaveDTO)
|
|
|
+2. Create all controllers with `@PreAuthorize` annotations matching menu permissions
|
|
|
+3. Wire endpoints to services
|
|
|
+
|
|
|
+### Phase 4: Frontend - API Layer + Foundation
|
|
|
+1. Create `src/api/module_payment/invoice/` with all 8 API modules
|
|
|
+2. Set up type definitions for request/response shapes
|
|
|
+
|
|
|
+### Phase 5: Frontend - Simple Pages (bottom-up)
|
|
|
+Implement pages in order of complexity:
|
|
|
+1. **任务中心** — simplest (table + filters, no CRUD)
|
|
|
+2. **供应商管理** — simple CRUD table
|
|
|
+3. **常用商品管理** — left tree + right table
|
|
|
+4. **员工管理** — CRUD with dynamic form
|
|
|
+5. **缴税管理** — radio toggle + button
|
|
|
+6. **转账账户管理** — cards + collapsible section
|
|
|
+
|
|
|
+### Phase 6: Frontend - Complex Pages
|
|
|
+7. **企业信息** — multi-section dashboard with edit modes
|
|
|
+8. **交易及发票管理** — most complex (search, table, batch ops, export, detail dialogs)
|
|
|
+
|
|
|
+### Phase 7: Menu Config + Integration
|
|
|
+1. Insert `sys_menu` records
|
|
|
+2. Test navigation and route generation
|
|
|
+3. Test tenant/enterprise scoping (verify mock data returns different records per tenant/enterprise)
|
|
|
+4. Full integration smoke test
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 7. Critical Design Notes
|
|
|
+
|
|
|
+### 7.1 Tenant Isolation
|
|
|
+All tables have `tenant_id` + `enterprise_id` columns. `TenantInnerInterceptor` auto-injects `tenant_id` on INSERT and auto-filters on SELECT. The `enterprise_id` must be set manually in the service layer when creating records (typically from the request context or current enterprise selection).
|
|
|
+
|
|
|
+**Mock data handling:** `InvoiceMockDataService` should accept `tenantId` and `enterpriseId` parameters so mock data is scoped correctly. Each enterprise sees only their own records.
|
|
|
+
|
|
|
+### 7.2 Batch Import Flow
|
|
|
+1. Frontend: download template (`GET /template` returns a pre-formatted .xlsx)
|
|
|
+2. Frontend: upload file (`POST /batch-import` multipart)
|
|
|
+3. Backend: parse .xlsx with Apache POI (already in project dependencies), validate rows, insert to DB
|
|
|
+4. Create a task record in `pay_invoice_task` for tracking
|
|
|
+5. Return success/fail counts
|
|
|
+
|
|
|
+### 7.3 Export Flow
|
|
|
+1. Frontend: click export triggers `GET /export/orders` or `GET /export/invoices`
|
|
|
+2. Backend: generates .xlsx using `ExcelUtil`, saves to temp storage
|
|
|
+3. Create a task record in `pay_invoice_task` with `task_status = 'SUCCESS'`
|
|
|
+4. Return download URL in task detail
|
|
|
+
|
|
|
+### 7.4 Scheduler (InvoiceTaskScheduler)
|
|
|
+A `@Scheduled` job that polls `pay_invoice_task` for `PENDING` tasks and processes them asynchronously. This handles:
|
|
|
+- Batch import parsing in background (for large files)
|
|
|
+- Export file generation
|
|
|
+- Cleanup of old/stale tasks
|
|
|
+
|
|
|
+### 7.5 Frontend Multi-tenant
|
|
|
+The frontend already has an `enterprise.store.ts` for enterprise selection. All API calls should pass `enterprise_id` as a parameter (the backend's `PaymentEnterpriseBaseEntity` handles filtering). The current enterprise is available via `useEnterpriseStore()`.
|
|
|
+
|
|
|
+### 7.6 Mock vs Real Switch
|
|
|
+Each service method should follow this pattern:
|
|
|
+```java
|
|
|
+// In production, real API calls would go here
|
|
|
+// For now, return mock data
|
|
|
+return invoiceMockDataService.getOrders(tenantId, enterpriseId, queryDTO);
|
|
|
+```
|
|
|
+This makes future migration to real APIs straightforward — just replace the mock service call with a real API client call.
|
|
|
+
|
|
|
+### 7.7 File Upload Size Limit
|
|
|
+Configure Spring multipart max size to 3MB for batch import (matches the Alipay constraint):
|
|
|
+```yaml
|
|
|
+spring.servlet.multipart.max-file-size: 3MB
|
|
|
+spring.servlet.multipart.max-request-size: 3MB
|
|
|
+```
|
|
|
+But use a controller-level check to allow larger uploads elsewhere.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 8. Files to Create (Total: ~65 files)
|
|
|
+
|
|
|
+### Backend (~40 files)
|
|
|
+| Layer | Files |
|
|
|
+|---|---|
|
|
|
+| SQL Migration | 1 file |
|
|
|
+| Entities | 7 files |
|
|
|
+| Enums | 7 files |
|
|
|
+| Mappers | 8 files |
|
|
|
+| DTOs | ~15 files |
|
|
|
+| Services | 9 files (8 services + 1 mock service) |
|
|
|
+| Controllers | 8 files |
|
|
|
+| Scheduler | 1 file |
|
|
|
+
|
|
|
+### Frontend (~25 files)
|
|
|
+| Layer | Files |
|
|
|
+|---|---|
|
|
|
+| API modules | 8 files |
|
|
|
+| View pages | 8 files |
|
|
|
+| Components | ~12 files |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 9. Risks & Mitigations
|
|
|
+
|
|
|
+| Risk | Mitigation |
|
|
|
+|---|---|
|
|
|
+| Dynamic route resolution fails for new view paths | Verify `component_path` in sys_menu matches actual file path relative to `src/views/` |
|
|
|
+| Tenant interceptor not working for invoice tables | Tables use `tenant_id` column like existing `pay_*` tables — automatically picked up |
|
|
|
+| `enterprise_id` is String not Long (existing convention) | Use `String enterpriseId` consistently; `InvoiceMockDataService` uses String parameter |
|
|
|
+| Red/Blue invoice display not well-defined | Mock it: red invoice = negative amounts + red color; blue = normal |
|
|
|
+| Large batch import ~3MB causing timeout | Use task scheduler for async processing; immediate response with task ID |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 10. Estimated Effort
|
|
|
+
|
|
|
+| Phase | Effort (hours) |
|
|
|
+|---|---|
|
|
|
+| Phase 1: DB + Entities | 3-4 |
|
|
|
+| Phase 2: Mock + Core Services | 6-8 |
|
|
|
+| Phase 3: Controllers + DTOs | 4-5 |
|
|
|
+| Phase 4: Frontend API Layer | 2-3 |
|
|
|
+| Phase 5: Simple Pages | 8-10 |
|
|
|
+| Phase 6: Complex Pages | 8-10 |
|
|
|
+| Phase 7: Menu + Integration | 2-4 |
|
|
|
+| **Total** | **33-44 hours** |
|