---
# System prepended metadata

title: 算錢

---

# 算錢

## 定義
| 名字 | 意思 | 
| -------- | -------- |
| set     |  套餐菜單     |
| menu     |  單點菜單     |
| item     |  餐點     |
| subtotal |  小計     |
| modifier | 變價 |
| mod | 變價 |
| rounding | 進位 |
| excludeOrderDiscount | 預設不打折扣 |
| excludeOrderSurcharge | 預設不收服務費 |
|promocode|優惠碼|
|coupon|優惠券|
|batch|訂單的一次下單|




## 這次整理的重點
讓前端照後端的業務邏輯 算法

訂單收據. 上面的數字
- item x2 **$100**
    - options
    - item level modifier
- subtotal
- order level modifier
    - surcharge 
    - discount
    - ricecoin
- 總折扣: 負的item+order mod 加總
- shipping: 運費
    - ?忘記有沒有顯示運費折扣折多少
- 總計: roundedTotal


function 概念 input -> logic -> output
f(x)=y

## 計算時機
系統流程
```mermaid
sequenceDiagram
    User->>Server: request orders
    Server->>Database: request orders
    Database->>Server: response orders
    Server->>Server: calculateOrder
    Server->>User: response orders
    User->>User: calculateOrder
```

## 計算步驟
1. 把訂單放入function
2. sort order level mod
    1. logic: 
        1. primary sort: 
            1. applyto: product>shipping>all
        1. secondary sort:
            1. type: Merchant>Surcharge>ShippingDiscount>Discount>Promocode>RiceCoin
3. batches: only status:{submitted,confirmed} 提交跟接單
4. item: 忽略取消的
5. 獲得所有提交跟接單的非取消的食物
6. 每個食物會 GetPrice(useDiscount:false):
    1. getBasePrice
    3. sort item level mod
    5. 計算item level mod calculatedAmount. 
        3. 後面的mod 會被前面的mod 影響
    6. 如果同時有comborule跟merchant. 只會算merchant
    7. useDiscount 
        4. true的話 也會算DISCOUNT
        5. false 不會算DISCOUNT
subtotal小計: 獲得所有提交跟接單的非取消的食物. 不算order mod, 只算item mod MERCHANT

modifierSum所有訂單變價總和: sum of order level mod calculatedAmount
1. 計算每個order level mod calculatedAmount
    2. 後面的mod 有機會被前面的影響
    3. 順序surcharge> product> shipping> all
        4. surcharge: 收服務費的食物的GetPrice(false). 得到calculated Amount
        5. product: 可打折扣的食物的GetPrice(false). 
            6. 折的錢不能超過product的錢
            7. 
            8. eg: 
            9. 紅茶100 + 綠茶50 + 可樂(eod) 20 全單 -$17
            10. base = 可以打折的食物的item.GetPrice(false)的加總 = 150
            11. a = 所有 item.GetPrice(false) = 170
            12. 攤分 紅茶100-(17/150*100) + 綠茶50-(17/150*100) + 20
            13. 加總攤分後結果 b = 147.3333333
            14. a-b = ???????
        6. shipping: (shippingfee*(1+mod.percent)+mod.amount)-shippingfee = calculatedAmount
        7. ALL: 
            1. base: item discount後的subtotal+ shippingfee
                9. 加 surcharge, product, shipping,all的calculatedAmount 成為新的base
            2. (base*(1+mod.percent)+mod.amount)-base = calculatedAmount 
3. 把order level mod calcualtedAmount 加起來


itemDiscountTotal所有item折扣總和: sum of item level mod discount calculatedAmount


roundedTotal總計: round(subtotal+shippingfee+modifierSum-itemDiscountTotal)


### 定義常用欄位
- item.GetBasePrice():
    price - discount - specialDiscount(沒在用) + sum(options price* quantity)
    紅茶100-20 + options[珍珠(1*5)+布丁(2*5)] 
    = 95
- item.GetPrice(true)
    basePrice + merchant + discount
- item.GetPrice(false)
    basePrice + merchant 
    

sorting
case1:
order.items = [A:100,B:100]
    order.modifers = [
    {type:"ALL",amount:-200,calculatedAmount:0},
    {type:"PRODUCT", amount:-200,calcultedAmount:-200},
    ]
case2: ?
order.items = [A:100,B:100]
    order.modifers = [
    {type:"ALL",percent:-20,calculatedAmount:}, // 180*(1-20%)=144
    {type:"PRODUCT", amount:-20,calcultedAmount:-20}, // 200-20=180
    ]




## background
modifier 屬性:
- amount: number
    - -$10 coupon. amount=-10
- percent: number 
    - -20% discount, percent=-20
- maxAmount: number
    - -10% coupon, 最多折100. 
- override: bool true/false
    - 應該沒在使用
    - true:
        - 當訂單需要重新計算, 直接相信calculatedAmount
    - false: 一般都是false
        - 當訂單需要重新計算, 請重新計算
- overrideItem
    - 忽略item的excludeOrderDiscount/excludeOrderSurcharge
- calculatedAmount
    - 儲存計算結果
- offeredBy
    - 影響statement report
    - value: DimOrder/Merchant

modifier level等級:
- item
- order

modifier type種類:
- RICECOIN
    - 代表ricecoin
    - eg: {type:"RICECOIN",amount:-100,applyTo:"ALL"}
    - order level only
    - 不會有percent. 不會applyTo:product/shipping
- PROMOCODE
    - promocode,coupon
    - eg: {type:"PROMOCODE",}
    - order level only
    - 有機會有amount, percent, applyTo:"ALL"/"SHIPPING"/"PRODUCT"
- DISCOUNT
    - 餐廳員工輸入的折扣
    - order,item level only
    - eg: {type:"DISCOUNT",percent:-10,applyTo:"PRODUCT"}
    - 有amount, percent
    - applyTo:"PRODUCT"
- SURCHARGE
    - 服務費 (manual>枱號群>開放時間>預設)
    - order level only
    - eg: {type:"SURCHARGE",percent:10,applyTo:"PRODUCT"}
    - 有percent
    - applyTo:"PRODUCT"
- SHIPPING_DISCOUNT
    - 餐廳提供的運費折扣
        - 運費折扣由來:
            - promocode/coupon applyTo:"shipping"
            - merchant.shipping
    - eg: {type:"SHIPPING_DISCOUNT",offeredBy: "Merchant",amount}
    - 一定是amount
    - order level only
- MERCHANT
    - 改價
    - item level only
    - eg: {type:"MERCHANT",offeredBy:"Merchant",amount:-}
    - 原價100, 改成20. amount=-80
- COMBORULE
    - 撞餐. 組合優惠
    - comborule, 買A送B
        - X comborule: itemA: 10$, item B: 20$. = 30$
        - O comborule: itemA: 10$, item B: 20$. = 10$
            - item B 身上會有item modifier. {type:"COMBORULE",amount:-20}


modifier applyTo 作用於:
- PRODUCT
    - 只折食物 
- SHIPPING
    - 只折運費
- ALL
    - 食物運費都折

rounding:
1. type
    1. up
    2. down
    3. off
    4. ''
3. digit 
    1. 0,1,2,3
 四捨五入 digit=0, type=off. 0.4=>0, 0.5=>1
 無條件上捨 digit=0, type=up. 0.1=>1
 無條件下捨 digit=0, type=down. 0.9=>0
 無條件下捨 digit=1, type=down. 0.99=>0.9
