191 lines
5.8 KiB
Markdown
191 lines
5.8 KiB
Markdown
# Draft 欄位改進方案
|
||
|
||
## 問題描述
|
||
|
||
原本的 `draft` 欄位被用於兩種不同目的,導致資料結構混亂:
|
||
|
||
1. **暫存沖帳分配** - 在個人沖帳流程中暫存使用者的沖帳金額分配
|
||
2. **歷史沖帳記錄** - 記錄已完成的沖帳明細
|
||
|
||
這導致兩種不同用途的資料互相覆蓋,造成資料不一致的問題。
|
||
|
||
## 改進方案
|
||
|
||
將原本的純陣列格式改為物件格式,包含兩個子陣列:
|
||
|
||
### 新的 draft 欄位格式
|
||
```json
|
||
{
|
||
"transfer_draft": [
|
||
{
|
||
"pro_order_detail_num": "訂單明細編號",
|
||
"reconcile": "沖帳金額"
|
||
}
|
||
],
|
||
"pro_order_detail_items": [
|
||
{
|
||
"pro_order_detail_num": "訂單明細編號",
|
||
"reconcile": "沖帳金額",
|
||
"activity_name": "活動名稱",
|
||
"actitem_name": "項目名稱",
|
||
"price": "原始金額",
|
||
"register_date": "報名日期",
|
||
"order_no": "訂單編號"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 1. `transfer_draft` - 暫存沖帳分配
|
||
**用途:**
|
||
- 在 `personal_reconcile.aspx` 中暫存使用者的沖帳金額分配
|
||
- 顯示 📝 圖示表示有暫存資料
|
||
- 支援「暫存」和「重新分配」功能
|
||
|
||
### 2. `pro_order_detail_items` - 沖帳明細記錄
|
||
**用途:**
|
||
- 在 `balance_reconcile.aspx` 中顯示歷史沖帳記錄
|
||
- 在 `balance_reconcile_query.aspx` 中顯示選取項目
|
||
- 包含完整的活動和項目資訊
|
||
|
||
## 向後相容性
|
||
|
||
程式碼會自動檢測格式並處理:
|
||
|
||
### 新格式(物件)
|
||
```json
|
||
{
|
||
"transfer_draft": [...],
|
||
"pro_order_detail_items": [...]
|
||
}
|
||
```
|
||
|
||
### 舊格式(陣列)
|
||
```json
|
||
[
|
||
{
|
||
"pro_order_detail_num": "12345",
|
||
"reconcile": 5000
|
||
}
|
||
]
|
||
```
|
||
|
||
## 修改的檔案
|
||
|
||
### personal_reconcile.aspx
|
||
- 更新 `loadFromDraftOrAutoDistribute()` 方法支援新舊格式
|
||
- 更新 `saveDraft()` 方法使用新格式
|
||
- 新增 `hasTransferDraft()` 方法檢查暫存資料
|
||
- 更新顯示邏輯使用新格式
|
||
|
||
### balance_reconcile.aspx
|
||
- 更新歷史記錄載入邏輯支援新格式
|
||
- 更新詳細資訊顯示邏輯支援新格式
|
||
- 保持向後相容性
|
||
|
||
### balance_reconcile_query.aspx
|
||
- 更新 `getDraftItems()` 方法支援新舊格式
|
||
- 更新項目顯示邏輯
|
||
|
||
## 資料安全保護機制
|
||
|
||
為了確保 `transfer_draft` 和 `pro_order_detail_items` 的操作互不影響,實作了以下保護機制:
|
||
|
||
### 1. 統一工具函數
|
||
所有頁面都使用統一的 `draft-utils.js` 工具函數:
|
||
- `window.DraftUtils.getDraftObject(draft)` - 安全解析 draft 欄位
|
||
- `window.DraftUtils.getDraftField(draft, fieldName)` - 安全取得特定欄位
|
||
- `window.DraftUtils.updateDraftField(draft, fieldName, newValue)` - 安全更新特定欄位
|
||
- `window.DraftUtils.hasTransferDraft(draft)` - 檢查是否有暫存資料
|
||
- `window.DraftUtils.hasProOrderDetailItems(draft)` - 檢查是否有歷史記錄
|
||
|
||
### 2. 操作範例
|
||
|
||
**更新 transfer_draft(不會影響 pro_order_detail_items):**
|
||
```javascript
|
||
const currentDraft = this.dialog.selected.draft || '';
|
||
const newTransferDraft = this.dialog.items
|
||
.filter(item => Number(item.reconcile) > 0)
|
||
.map(item => ({
|
||
pro_order_detail_num: item.num,
|
||
reconcile: Number(item.reconcile)
|
||
}));
|
||
|
||
const newDraftObj = window.DraftUtils.updateDraftField(currentDraft, 'transfer_draft', newTransferDraft);
|
||
```
|
||
|
||
**更新 pro_order_detail_items(不會影響 transfer_draft):**
|
||
```javascript
|
||
const currentDraft = item.draft || '';
|
||
const newDetailItems = [
|
||
{
|
||
pro_order_detail_num: "123",
|
||
reconcile: 5000,
|
||
activity_name: "法會",
|
||
actitem_name: "護持金"
|
||
}
|
||
];
|
||
|
||
const newDraftObj = window.DraftUtils.updateDraftField(currentDraft, 'pro_order_detail_items', newDetailItems);
|
||
```
|
||
|
||
**檢查是否有暫存資料:**
|
||
```javascript
|
||
if (window.DraftUtils.hasTransferDraft(item.draft)) {
|
||
console.log('有暫存資料');
|
||
}
|
||
```
|
||
|
||
**取得特定欄位:**
|
||
```javascript
|
||
const transferDraft = window.DraftUtils.getDraftField(item.draft, 'transfer_draft');
|
||
const detailItems = window.DraftUtils.getDraftField(item.draft, 'pro_order_detail_items');
|
||
```
|
||
|
||
### 3. 統一工具檔案
|
||
建立了 `draft-utils.js` 統一工具檔案,所有頁面都引用此檔案:
|
||
- 所有 draft 操作函數統一管理
|
||
- 格式驗證功能
|
||
- 向後相容性處理
|
||
- 詳細的使用範例
|
||
- 避免程式碼重複,提升維護性
|
||
|
||
### 4. 頁面引用方式
|
||
每個 `.aspx` 頁面都在 `<script>` 標籤前加入:
|
||
```html
|
||
<script src="draft-utils.js"></script>
|
||
```
|
||
|
||
然後使用 `window.DraftUtils` 來呼叫工具函數,確保所有頁面使用相同的邏輯。
|
||
|
||
### 5. 完整工具函數清單
|
||
`draft-utils.js` 提供以下工具函數:
|
||
|
||
**基本操作:**
|
||
- `getDraftObject(draft)` - 解析 draft 欄位,返回標準化物件
|
||
- `getDraftField(draft, fieldName)` - 安全取得特定欄位
|
||
- `updateDraftField(draft, fieldName, newValue)` - 安全更新特定欄位
|
||
- `clearDraftField(draft, fieldName)` - 清除特定欄位
|
||
|
||
**檢查函數:**
|
||
- `hasTransferDraft(draft)` - 檢查是否有暫存資料
|
||
- `hasProOrderDetailItems(draft)` - 檢查是否有歷史記錄
|
||
|
||
**工具函數:**
|
||
- `mergeDraftObjects(draft1, draft2)` - 合併兩個 draft 物件
|
||
- `validateDraftFormat(draft)` - 驗證 draft 格式
|
||
- `getDraftSummary(draft)` - 取得 draft 摘要資訊
|
||
- `migrateLegacyFormat(draft)` - 將舊格式轉換為新格式
|
||
- `cleanEmptyDraft(draft)` - 清理空的 draft 欄位
|
||
- `formatDraftJson(draft)` - 格式化 draft JSON 為可讀字串
|
||
|
||
## 優點
|
||
|
||
1. **職責分離** - 每個子陣列有明確的用途
|
||
2. **資料一致性** - 避免不同用途的資料互相覆蓋
|
||
3. **向後相容** - 支援舊格式,無需資料庫變更
|
||
4. **易於維護** - 程式碼邏輯更清晰
|
||
5. **擴展性** - 未來可以添加更多子陣列
|
||
6. **資料安全** - 確保各欄位操作互不影響
|
||
7. **程式碼統一** - 所有頁面使用相同的工具函數
|
||
8. **功能完整** - 提供豐富的工具函數支援各種操作需求 |