Skip to content

Commit

Permalink
feat: add transactions' metadata for Alipay/WeChat bills (#25)
Browse files Browse the repository at this point in the history
* feat(alipay): add tx metadata

Signed-off-by: Triple-Z <me@triplez.cn>

* feat(wechat): add tx metadata

Signed-off-by: Triple-Z <me@triplez.cn>
  • Loading branch information
Triple-Z authored Jun 26, 2021
1 parent 608ad73 commit e5d5ef1
Show file tree
Hide file tree
Showing 8 changed files with 232 additions and 38 deletions.
38 changes: 15 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,40 +39,32 @@ go get -u github.com/deb-sig/double-entry-generator
### 支付宝

```bash
double-entry-generator translate --config ./example/alipay/config.yaml ./example/alipay/example-alipay-records.csv
double-entry-generator translate \
--config ./example/alipay/config.yaml \
--output ./example/alipay/example-alipay-output.beancount \
./example/alipay/example-alipay-records.csv
```

其中 `--config` 是配置文件,默认情况下,使用支付宝作为提供方,也可手动指定 `--provider`。具体参考[使用文档](doc/double-entry-generator_translate.md)。默认生成的文件是 `default_output.beancount`:

```
option "title" "测试"
option "operating_currency" "CNY"
1970-01-01 open Expenses:Food
1970-01-01 open Income:Earnings
1970-01-01 open Assets:Alipay
1970-01-01 open Expenses:Test
1970-01-01 open Liabilities:CreditCard:Test
2019-09-30 * "肯德基(张江高科餐厅)" "张江高科餐厅"
Expenses:Food 27.00 CNY
Liabilities:CreditCard:Test -27.00 CNY
2019-09-30 * "中欧基金管理有限公司" "余额宝-2019.09.29-收益发放"
Assets:Alipay 0.01 CNY
Income:Earnings -0.01 CNY
```
其中 `--config` 是配置文件,默认情况下,使用支付宝作为提供方,也可手动指定 `--provider`。具体参考[使用文档](doc/double-entry-generator_translate.md)。默认生成的文件是 `default_output.beancount`,若有 `--output``-o` 指定输出文件,则会输出到指定的文件中。如上述例子会将转换结果输出至 `./example/alipay/example-alipay-output.beancount` 文件中。

### 微信

```bash
double-entry-generator translate --config ./example/wechat/config.yaml --provider wechat ./example/wechat/example-wechat-records.csv
double-entry-generator translate \
--config ./example/wechat/config.yaml \
--provider wechat \
--output ./example/wechat/example-wechat-output.beancount \
./example/wechat/example-wechat-records.csv
```

### Huobi Global (Crypto)

```bash
double-entry-generator translate --config ./example/huobi/config.yaml --provider huobi ./example/huobi/example-huobi-records.csv
double-entry-generator translate \
--config ./example/huobi/config.yaml \
--provider huobi \
--output ./example/huobi/example-huobi-output.beancount \
./example/huobi/example-huobi-records.csv
```

## 账单下载与格式问题
Expand Down
104 changes: 93 additions & 11 deletions example/alipay/example-alipay-output.beancount
Original file line number Diff line number Diff line change
Expand Up @@ -15,48 +15,130 @@ option "operating_currency" "CNY"
1970-01-01 open Income:Alipay:YuEBao:PnL
1970-01-01 open Income:FIXME

2020-06-02 * "蚂蚁财富-蚂蚁(杭州)基金销售有限公司" "蚂蚁财富-ABCD-卖出至余额宝" ; 其他-交易成功-投资理财
2020-06-02 * "蚂蚁财富-蚂蚁(杭州)基金销售有限公司" "蚂蚁财富-ABCD-卖出至余额宝"
Assets:Alipay 15.40 CNY
Assets:Alipay:Invest -15.40 CNY
Income:Alipay:Invest:PnL
category: "投资理财"
method: "余额宝"
orderId: "123456"
payTime: "2020-06-02 15:34:06 +0800 CST"
source: "支付宝"
status: "交易成功"
txType: "其他"

2020-06-09 * "广发基金管理有限公司" "余额宝-2020.06.08-收益发放" ; 其他-交易成功-投资理财
2020-06-09 * "广发基金管理有限公司" "余额宝-2020.06.08-收益发放"
Assets:Alipay 0.11 CNY
Income:Alipay:YuEBao:PnL -0.11 CNY
category: "投资理财"
method: "余额宝"
orderId: "123456"
payTime: "2020-06-09 02:57:13 +0800 CST"
source: "支付宝"
status: "交易成功"
txType: "其他"

2020-06-14 * "东莞肯德基有限公司" "KFCAPIDGB012345" ; 支出-交易成功-餐饮美食
2020-06-14 * "东莞肯德基有限公司" "KFCAPIDGB012345"
Expenses:Food 79.00 CNY
Assets:Alipay -79.00 CNY
category: "餐饮美食"
merchantId: "ABC9876"
method: "余额宝"
orderId: "123456"
payTime: "2020-06-14 12:43:26 +0800 CST"
source: "支付宝"
status: "交易成功"
txType: "支出"

2021-05-19 * "蚂蚁财富-蚂蚁(杭州)基金销售有限公司" "蚂蚁财富-XZY指数C-买入" ; 其他-交易成功-投资理财
2021-05-19 * "蚂蚁财富-蚂蚁(杭州)基金销售有限公司" "蚂蚁财富-XZY指数C-买入"
Assets:Alipay:Invest 50.00 CNY
Assets:Alipay -50.00 CNY
category: "投资理财"
orderId: "123456"
payTime: "2021-05-19 09:42:54 +0800 CST"
source: "支付宝"
status: "交易成功"
txType: "其他"

2021-05-20 * "苏宁易购官方旗舰店" "【礼遇价】三星128g内存卡microSD存储卡tf卡行车记录仪卡switch监控摄像头" ; 支出-交易成功-数码电器
2021-05-20 * "苏宁易购官方旗舰店" "【礼遇价】三星128g内存卡microSD存储卡tf卡行车记录仪卡switch监控摄像头"
Expenses:Electronics 87.90 CNY
Assets:Bank:CN:CMB-9876:Savings -87.90 CNY
category: "数码电器"
merchantId: "ABC9876"
method: "招商银行(9876)"
orderId: "123456"
payTime: "2021-05-20 12:34:34 +0800 CST"
source: "支付宝"
status: "交易成功"
txType: "支出"

2021-05-30 * "广发基金管理有限公司" "余额宝-单次转入" ; 其他-交易成功-投资理财
2021-05-30 * "广发基金管理有限公司" "余额宝-单次转入"
Assets:Alipay 2.00 CNY
Assets:Alipay -2.00 CNY
category: "投资理财"
merchantId: "ABC9876"
method: "余额"
orderId: "123456"
payTime: "2021-05-30 23:43:37 +0800 CST"
source: "支付宝"
status: "交易成功"
txType: "其他"

2021-06-01 * "dettol滴露官方旗舰店" "【直接下单付款】滴露消毒液1.2L*2家用杀菌消毒水衣物地板宠物" ; 支出-交易关闭-日用百货
2021-06-01 * "dettol滴露官方旗舰店" "【直接下单付款】滴露消毒液1.2L*2家用杀菌消毒水衣物地板宠物"
Expenses:Groceries 109.90 CNY
Assets:Bank:CN:CMB-9876:Savings -109.90 CNY
category: "日用百货"
merchantId: "ABC9876"
method: "招商银行(9876)"
orderId: "123456"
payTime: "2021-06-01 00:10:22 +0800 CST"
source: "支付宝"
status: "交易关闭"
txType: "支出"

2021-06-01 * "dettol滴露官方旗舰店" "退款-【直接下单付款】滴露消毒液1.2L*2家用杀菌消毒水衣物地板宠物" ; 其他-退款成功-退款
2021-06-01 * "dettol滴露官方旗舰店" "退款-【直接下单付款】滴露消毒液1.2L*2家用杀菌消毒水衣物地板宠物"
Assets:Bank:CN:CMB-9876:Savings 109.90 CNY
Expenses:Groceries -109.90 CNY
category: "退款"
merchantId: "ABC9876"
method: "招商银行(9876)"
orderId: "123456"
payTime: "2021-06-01 00:13:56 +0800 CST"
source: "支付宝"
status: "退款成功"
txType: "其他"

2021-06-14 * "蚂蚁会员(北京)网络技术服务有限公司" "相互宝分摊-6月第1期-*" ; 支出-交易成功-互助保障
2021-06-14 * "蚂蚁会员(北京)网络技术服务有限公司" "相互宝分摊-6月第1期-*"
Expenses:Insurance 6.51 CNY
Assets:Bank:CN:CMB-9876:Savings -6.51 CNY
category: "互助保障"
merchantId: "ABC9876"
method: "招商银行(9876)"
orderId: "123456"
payTime: "2021-06-14 14:00:38 +0800 CST"
source: "支付宝"
status: "交易成功"
txType: "支出"

2021-06-24 * "*三" "商品" ; 收入-交易成功-收入
2021-06-24 * "*三" "商品"
Assets:Alipay 10.00 CNY
Income:Alipay:ShouKuanMa -10.00 CNY
category: "收入"
merchantId: "123456"
orderId: "123456"
payTime: "2021-06-24 00:00:00 +0800 CST"
source: "支付宝"
status: "交易成功"
txType: "收入"

2021-06-25 * "*三" "我就随便转着玩" ; 收入-交易成功-转账红包
2021-06-25 * "*三" "我就随便转着玩"
Assets:Alipay 42.00 CNY
Income:FIXME -42.00 CNY
category: "转账红包"
method: "余额"
orderId: "123456"
payTime: "2021-06-25 00:00:00 +0800 CST"
source: "支付宝"
status: "交易成功"
txType: "收入"

36 changes: 36 additions & 0 deletions example/wechat/example-wechat-output.beancount
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,60 @@ option "operating_currency" "CNY"
2019-09-24 * "同性好友" "/"
Assets:Digital:Wechat:Cash 0.35 CNY
Income:Wechat:RedPacket -0.35 CNY
merchantId: "129847129"
method: "/"
orderId: "3985734"
payTime: "2019-09-24 10:10:11 +0800 CST"
source: "微信支付"
txType: "收入"

2019-09-26 * "云膳过桥米线(传奇广场店)" "总共消费:28.16"
Expenses:Food:Meal 28.16 CNY
Assets:Bank:CN:BOC:Savings -28.16 CNY
merchantId: "129847129"
method: "中国银行(1234)"
orderId: "3985734"
payTime: "2019-09-26 12:45:27 +0800 CST"
source: "微信支付"
txType: "支出"

2020-11-27 * "用户A" "收款方备注:二维码收款"
Assets:Digital:Wechat:Cash 23.00 CNY
Income:Service -23.00 CNY
merchantId: "/"
method: "零钱"
orderId: "3985734"
payTime: "2020-11-27 19:29:00 +0800 CST"
source: "微信支付"
txType: "收入"

2021-01-17 * "/" "/"
Assets:Digital:WeChat:Cash 2000.00 CNY
Assets:Bank:CN:ICBC:Savings -2000.00 CNY
merchantId: "129847129"
method: "工商银行(9876)"
orderId: "3985734"
payTime: "2021-01-17 10:07:31 +0800 CST"
source: "微信支付"
txType: "/"

2021-01-17 * "某餐厅" "收款方备注:二维码收款"
Expenses:Food:Meal 12.00 CNY
Assets:Digital:Wechat:Cash -12.00 CNY
merchantId: "129847129"
method: "零钱通"
orderId: "3985734"
payTime: "2021-01-17 18:03:35 +0800 CST"
source: "微信支付"
txType: "支出"

2021-01-22 * "房东" "转账备注:微信转账"
Expenses:Housing:Rent 500.00 CNY
Assets:Digital:Wechat:Cash -500.00 CNY
merchantId: "129847129"
method: "零钱通"
orderId: "3985734"
payTime: "2021-01-22 12:34:56 +0800 CST"
source: "微信支付"
txType: "支出"

1 change: 1 addition & 0 deletions pkg/compiler/beancount/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ func (b *BeanCount) writeBill(file *os.File, index int) error {
PlusAccount: o.PlusAccount,
MinusAccount: o.MinusAccount,
PnlAccount: o.ExtraAccounts[ir.PnlAccount],
Metadata: o.Metadata,
Currency: b.Config.DefaultCurrency,
})
case ir.OrderTypeHuobiTrade: // Huobi trades
Expand Down
3 changes: 2 additions & 1 deletion pkg/compiler/beancount/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
var normalOrder = `{{ .PayTime.Format "2006-01-02" }} * "{{ .Peer }}" "{{ .Item }}"{{ if .Note }} ; {{ .Note }}{{ end }}
{{ .PlusAccount }} {{ .Money | printf "%.2f" }} {{ .Currency }}
{{ .MinusAccount }} -{{ .Money | printf "%.2f" }} {{ .Currency }}
{{ if .PnlAccount }} {{ .PnlAccount }}{{ printf "\n" }}{{ end }}
{{ if .PnlAccount }} {{ .PnlAccount }}{{ printf "\n" }}{{ end }}{{ range $key, $value := .Metadata }}{{ if $value }} {{ $key }}: "{{ $value }}"{{ printf "\n" }}{{end}}{{end}}
`

type NormalOrderVars struct {
Expand All @@ -22,6 +22,7 @@ type NormalOrderVars struct {
MinusAccount string
PnlAccount string
Currency string
Metadata map[string]string // unordered metadata map
}

// 火币买入模版(手续费单位为购买单位货币)
Expand Down
1 change: 1 addition & 0 deletions pkg/ir/ir.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ type Order struct {
ExtraAccounts map[Account]string
MinusAccount string
PlusAccount string
Metadata map[string]string
}

// Unit is the key commodity names
Expand Down
47 changes: 44 additions & 3 deletions pkg/provider/alipay/convert.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package alipay

import (
"fmt"

"github.com/deb-sig/double-entry-generator/pkg/ir"
)

Expand All @@ -15,13 +13,13 @@ func (a *Alipay) convertToIR() *ir.IR {
Peer: o.Peer,
Item: o.ItemName,
Method: o.Method,
Note: fmt.Sprintf("%s-%s-%s", o.TxTypeOriginal, o.Status, o.Category),
PayTime: o.PayTime,
Money: o.Money,
OrderID: &o.DealNo,
TxType: conevertType(o.TxType),
TxTypeOriginal: o.TxTypeOriginal,
}
irO.Metadata = getMetadata(o)
if o.MerchantId != "" {
irO.MerchantOrderID = &o.MerchantId
}
Expand All @@ -40,3 +38,46 @@ func conevertType(t TxTypeType) ir.TxType {
return ir.TxTypeUnknown
}
}

func getMetadata(o Order) map[string]string {
// FIXME(TripleZ): hard-coded, bad pattern
source := "支付宝"
var status, method, category, txType, orderId, merchantId, paytime string

paytime = o.PayTime.String()

if o.DealNo != "" {
orderId = o.DealNo
}

if o.MerchantId != "" {
merchantId = o.MerchantId
}

if o.Category != "" {
category = o.Category
}

if o.TxTypeOriginal != "" {
txType = o.TxTypeOriginal
}

if o.Method != "" {
method = o.Method
}

if o.Status != "" {
status = o.Status
}

return map[string]string{
"source": source,
"payTime": paytime,
"orderId": orderId,
"merchantId": merchantId,
"txType": txType,
"category": category,
"method": method,
"status": status,
}
}
Loading

0 comments on commit e5d5ef1

Please sign in to comment.