diff --git a/README.md b/README.md index 3fbddbf..e880965 100644 --- a/README.md +++ b/README.md @@ -91,13 +91,8 @@ dataPath=自定义的目录 [MIT](https://github.com/BaoXuebin/beancount-gs/blob/main/License) @BaoXuebin -## 赞助 +## 感谢️ [赞助地址](https://xdbin.com/sponsor) -## 感谢 - - -JetBrains -

Licenses for Open Source Development

-
+感谢 **@Cabin**,**@潇** 两位朋友的赞助支持❤️ \ No newline at end of file diff --git a/script/file.go b/script/file.go index b8f6b5f..932cb94 100644 --- a/script/file.go +++ b/script/file.go @@ -265,7 +265,9 @@ func FindConsecutiveMultilineTextInFile(filePath string, multilineLines []string // cleanString 去除字符串中的首尾空白和中间的所有空格字符 func cleanString(str string) string { - return strings.ReplaceAll(strings.TrimSpace(str), " ", "") + all := strings.ReplaceAll(strings.TrimSpace(str), " ", "") + // 去除逗号,处理金额千分位 + return strings.ReplaceAll(all, ",", "") } // 删除指定行范围的内容 @@ -303,7 +305,6 @@ func InsertLines(lines []string, startLineNo int, newLines []string) ([]string, if startLineNo < 1 || startLineNo > len(lines)+1 { return nil, fmt.Errorf("插入行号无效") } - // 在指定位置插入新的内容 modifiedLines := append(lines[:startLineNo-1], append(newLines, lines[startLineNo-1:]...)...) return modifiedLines, nil diff --git a/server.go b/server.go index af88ad0..ef5b233 100644 --- a/server.go +++ b/server.go @@ -83,6 +83,7 @@ func RegisterRouter(router *gin.Engine) { authorized.GET("/transaction/raw", service.QueryTransactionRawTextById) authorized.GET("/transaction", service.QueryTransactions) authorized.POST("/transaction", service.AddTransactions) + authorized.POST("/transaction/raw", service.UpdateTransactionRawTextById) authorized.DELETE("/transaction", service.DeleteTransactionById) authorized.POST("/transaction/batch", service.AddBatchTransactions) authorized.GET("/transaction/payee", service.QueryTransactionPayees) diff --git a/service/transactions.go b/service/transactions.go index b10263c..75f8557 100644 --- a/service/transactions.go +++ b/service/transactions.go @@ -156,7 +156,12 @@ type TransactionForm struct { Tags []string `form:"tags" json:"tags,omitempty"` DivideDateList []string `form:"divideDateList" json:"divideDateList,omitempty"` Entries []TransactionEntryForm `form:"entries" json:"entries"` - Raw RawTransaction `json:"raw,omitempty"` + RawText string `json:"rawText,omitempty"` +} + +type UpdateRawTextTransactionForm struct { + ID string `form:"id" binding:"required" json:"id"` + RawText string `form:"rawText" json:"rawText,omitempty" binding:"required"` } type TransactionEntryForm struct { @@ -391,38 +396,73 @@ func filterEmptyStrings(arr []string) []string { return result } -func DeleteTransactionById(c *gin.Context) { - queryParams := script.GetQueryParams(c) - if queryParams.ID == "" { - BadRequest(c, "Param 'id' must not be blank.") +func UpdateTransactionRawTextById(c *gin.Context) { + var rawTextUpdateTransactionForm UpdateRawTextTransactionForm + if err := c.ShouldBindJSON(&rawTextUpdateTransactionForm); err != nil { + BadRequest(c, err.Error()) return } ledgerConfig := script.GetLedgerConfigFromContext(c) - transactions := make([]Transaction, 0) - err := script.BQLQueryList(ledgerConfig, &queryParams, &transactions) + + beanFilePath, err := getBeanFilePathByTransactionId(rawTextUpdateTransactionForm.ID, ledgerConfig) if err != nil { - BadRequest(c, err.Error()) + InternalError(c, err.Error()) return } - if len(transactions) == 0 { - InternalError(c, "No transaction found.") + result, e := script.BQLPrint(ledgerConfig, rawTextUpdateTransactionForm.ID) + if e != nil { + InternalError(c, e.Error()) return } - month, err := script.GetMonth(transactions[0].Date) + oldLines := filterEmptyStrings(strings.Split(result, "\r\n")) + startLine, endLine, err := script.FindConsecutiveMultilineTextInFile(beanFilePath, oldLines) if err != nil { InternalError(c, err.Error()) return } - // 交易记录所在文件位置 - beanFilePath := script.GetLedgerMonthFilePath(ledgerConfig.DataPath, month) + lines, e := script.RemoveLines(beanFilePath, startLine, endLine) + if e != nil { + InternalError(c, e.Error()) + return + } + newLines := filterEmptyStrings(strings.Split(rawTextUpdateTransactionForm.RawText, "\r\n")) + if len(newLines) > 0 { + lines, e = script.InsertLines(lines, startLine, newLines) + if e != nil { + InternalError(c, e.Error()) + return + } + } + err = script.WriteToFile(beanFilePath, lines) + if err != nil { + InternalError(c, err.Error()) + return + } + OK(c, true) +} + +func DeleteTransactionById(c *gin.Context) { + queryParams := script.GetQueryParams(c) + if queryParams.ID == "" { + BadRequest(c, "Param 'id' must not be blank.") + return + } + ledgerConfig := script.GetLedgerConfigFromContext(c) + result, e := script.BQLPrint(ledgerConfig, queryParams.ID) if e != nil { InternalError(c, e.Error()) return } + beanFilePath, err := getBeanFilePathByTransactionId(queryParams.ID, ledgerConfig) + if err != nil { + InternalError(c, err.Error()) + return + } + oldLines := filterEmptyStrings(strings.Split(result, "\r\n")) startLine, endLine, err := script.FindConsecutiveMultilineTextInFile(beanFilePath, oldLines) if err != nil { @@ -431,7 +471,7 @@ func DeleteTransactionById(c *gin.Context) { } lines, e := script.RemoveLines(beanFilePath, startLine, endLine) if e != nil { - InternalError(c, err.Error()) + InternalError(c, e.Error()) return } err = script.WriteToFile(beanFilePath, lines) @@ -439,10 +479,28 @@ func DeleteTransactionById(c *gin.Context) { InternalError(c, err.Error()) return } - OK(c, true) } +func getBeanFilePathByTransactionId(transactionId string, ledgerConfig *script.Config) (string, error) { + queryParams := script.QueryParams{ID: transactionId, Where: true} + transactions := make([]Transaction, 0) + err := script.BQLQueryList(ledgerConfig, &queryParams, &transactions) + if err != nil { + return "", err + } + if len(transactions) == 0 { + return "", errors.New("no transaction found") + } + month, err := script.GetMonth(transactions[0].Date) + if err != nil { + return "", err + } + // 交易记录所在文件位置 + beanFilePath := script.GetLedgerMonthFilePath(ledgerConfig.DataPath, month) + return beanFilePath, nil +} + type transactionPayee struct { Value string `bql:"distinct payee" json:"value"` }