update transaction by raw text

This commit is contained in:
BaoXuebin 2024-10-29 14:00:37 +08:00
parent 3e0766d2fe
commit 1d55b9eac6
4 changed files with 85 additions and 30 deletions

View File

@ -91,13 +91,8 @@ dataPath=自定义的目录
[MIT](https://github.com/BaoXuebin/beancount-gs/blob/main/License) @BaoXuebin [MIT](https://github.com/BaoXuebin/beancount-gs/blob/main/License) @BaoXuebin
## 赞助 ## 感谢️
[赞助地址](https://xdbin.com/sponsor) [赞助地址](https://xdbin.com/sponsor)
## 感谢 感谢 **@Cabin****@潇** 两位朋友的赞助支持❤️
<a href="https://jb.gg/OpenSourceSupport" style="display: flex; justify-content: left; align-items: center; flex-direction: row;">
<img alt="JetBrains" src="./jb_beam.png" style="width: 120px; height: 120px;" />
<h3>Licenses for Open Source Development</h3>
</a>

View File

@ -265,7 +265,9 @@ func FindConsecutiveMultilineTextInFile(filePath string, multilineLines []string
// cleanString 去除字符串中的首尾空白和中间的所有空格字符 // cleanString 去除字符串中的首尾空白和中间的所有空格字符
func cleanString(str string) string { 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 { if startLineNo < 1 || startLineNo > len(lines)+1 {
return nil, fmt.Errorf("插入行号无效") return nil, fmt.Errorf("插入行号无效")
} }
// 在指定位置插入新的内容 // 在指定位置插入新的内容
modifiedLines := append(lines[:startLineNo-1], append(newLines, lines[startLineNo-1:]...)...) modifiedLines := append(lines[:startLineNo-1], append(newLines, lines[startLineNo-1:]...)...)
return modifiedLines, nil return modifiedLines, nil

View File

@ -83,6 +83,7 @@ func RegisterRouter(router *gin.Engine) {
authorized.GET("/transaction/raw", service.QueryTransactionRawTextById) authorized.GET("/transaction/raw", service.QueryTransactionRawTextById)
authorized.GET("/transaction", service.QueryTransactions) authorized.GET("/transaction", service.QueryTransactions)
authorized.POST("/transaction", service.AddTransactions) authorized.POST("/transaction", service.AddTransactions)
authorized.POST("/transaction/raw", service.UpdateTransactionRawTextById)
authorized.DELETE("/transaction", service.DeleteTransactionById) authorized.DELETE("/transaction", service.DeleteTransactionById)
authorized.POST("/transaction/batch", service.AddBatchTransactions) authorized.POST("/transaction/batch", service.AddBatchTransactions)
authorized.GET("/transaction/payee", service.QueryTransactionPayees) authorized.GET("/transaction/payee", service.QueryTransactionPayees)

View File

@ -156,7 +156,12 @@ type TransactionForm struct {
Tags []string `form:"tags" json:"tags,omitempty"` Tags []string `form:"tags" json:"tags,omitempty"`
DivideDateList []string `form:"divideDateList" json:"divideDateList,omitempty"` DivideDateList []string `form:"divideDateList" json:"divideDateList,omitempty"`
Entries []TransactionEntryForm `form:"entries" json:"entries"` 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 { type TransactionEntryForm struct {
@ -391,33 +396,21 @@ func filterEmptyStrings(arr []string) []string {
return result return result
} }
func DeleteTransactionById(c *gin.Context) { func UpdateTransactionRawTextById(c *gin.Context) {
queryParams := script.GetQueryParams(c) var rawTextUpdateTransactionForm UpdateRawTextTransactionForm
if queryParams.ID == "" { if err := c.ShouldBindJSON(&rawTextUpdateTransactionForm); err != nil {
BadRequest(c, "Param 'id' must not be blank.")
return
}
ledgerConfig := script.GetLedgerConfigFromContext(c)
transactions := make([]Transaction, 0)
err := script.BQLQueryList(ledgerConfig, &queryParams, &transactions)
if err != nil {
BadRequest(c, err.Error()) BadRequest(c, err.Error())
return return
} }
ledgerConfig := script.GetLedgerConfigFromContext(c)
if len(transactions) == 0 { beanFilePath, err := getBeanFilePathByTransactionId(rawTextUpdateTransactionForm.ID, ledgerConfig)
InternalError(c, "No transaction found.")
return
}
month, err := script.GetMonth(transactions[0].Date)
if err != nil { if err != nil {
InternalError(c, err.Error()) InternalError(c, err.Error())
return return
} }
// 交易记录所在文件位置
beanFilePath := script.GetLedgerMonthFilePath(ledgerConfig.DataPath, month) result, e := script.BQLPrint(ledgerConfig, rawTextUpdateTransactionForm.ID)
result, e := script.BQLPrint(ledgerConfig, queryParams.ID)
if e != nil { if e != nil {
InternalError(c, e.Error()) InternalError(c, e.Error())
return return
@ -431,18 +424,83 @@ func DeleteTransactionById(c *gin.Context) {
} }
lines, e := script.RemoveLines(beanFilePath, startLine, endLine) lines, e := script.RemoveLines(beanFilePath, startLine, endLine)
if e != nil { 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()) InternalError(c, err.Error())
return 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 {
InternalError(c, err.Error())
return
}
lines, e := script.RemoveLines(beanFilePath, startLine, endLine)
if e != nil {
InternalError(c, e.Error())
return
}
err = script.WriteToFile(beanFilePath, lines) err = script.WriteToFile(beanFilePath, lines)
if err != nil { if err != nil {
InternalError(c, err.Error()) InternalError(c, err.Error())
return return
} }
OK(c, true) 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 { type transactionPayee struct {
Value string `bql:"distinct payee" json:"value"` Value string `bql:"distinct payee" json:"value"`
} }