317 lines
8.7 KiB
Go
317 lines
8.7 KiB
Go
package service
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/sha1"
|
|
"encoding/hex"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/exec"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/beancount-gs/script"
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
func CheckBeancount(c *gin.Context) {
|
|
cmd := exec.Command("bean-query", "--version")
|
|
output, err := cmd.Output()
|
|
if err != nil {
|
|
InternalError(c, err.Error())
|
|
return
|
|
}
|
|
OK(c, string(output))
|
|
}
|
|
|
|
func QueryServerConfig(c *gin.Context) {
|
|
OK(c, script.GetServerConfig())
|
|
}
|
|
|
|
type QueryLedgerResult struct {
|
|
Mail string `json:"mail"`
|
|
Title string `json:"title"`
|
|
CreateDate string `json:"createDate"`
|
|
OperatingCurrency string `json:"operatingCurrency"`
|
|
}
|
|
|
|
type LedgerSort []QueryLedgerResult
|
|
|
|
func (s LedgerSort) Len() int {
|
|
return len(s)
|
|
}
|
|
|
|
func (s LedgerSort) Swap(i, j int) {
|
|
s[i], s[j] = s[j], s[i]
|
|
}
|
|
|
|
func (s LedgerSort) Less(i, j int) bool {
|
|
return s[i].CreateDate <= s[j].CreateDate && s[i].Mail <= s[j].Mail
|
|
}
|
|
|
|
func QueryLedgerList(c *gin.Context) {
|
|
result := make([]QueryLedgerResult, 0)
|
|
for _, config := range script.GetLedgerConfigMap() {
|
|
result = append(result, QueryLedgerResult{
|
|
Title: config.Title,
|
|
Mail: config.Mail,
|
|
CreateDate: config.CreateDate,
|
|
OperatingCurrency: config.OperatingCurrency,
|
|
})
|
|
}
|
|
sort.Sort(LedgerSort(result))
|
|
OK(c, result)
|
|
}
|
|
|
|
type UpdateConfigForm struct {
|
|
Secret string `form:"secret" binding:"required"`
|
|
StartDate string `form:"startDate" binding:"required"`
|
|
DataPath string `form:"dataPath" binding:"required"`
|
|
OperatingCurrency string `form:"operatingCurrency" binding:"required"`
|
|
OpeningBalances string `form:"openingBalances" binding:"required"`
|
|
IsBak bool `form:"isBak" binding:"required"`
|
|
}
|
|
|
|
func UpdateServerConfig(c *gin.Context) {
|
|
var updateConfigForm UpdateConfigForm
|
|
if err := c.ShouldBindJSON(&updateConfigForm); err != nil {
|
|
BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
if !script.EqualServerSecret(updateConfigForm.Secret) {
|
|
ServerSecretNotMatch(c)
|
|
return
|
|
}
|
|
var serverConfig = script.Config{
|
|
OperatingCurrency: updateConfigForm.OperatingCurrency,
|
|
DataPath: updateConfigForm.DataPath,
|
|
StartDate: updateConfigForm.StartDate,
|
|
OpeningBalances: updateConfigForm.OpeningBalances,
|
|
IsBak: updateConfigForm.IsBak,
|
|
}
|
|
// 更新配置
|
|
err := script.UpdateServerConfig(serverConfig)
|
|
if err != nil {
|
|
InternalError(c, err.Error())
|
|
return
|
|
}
|
|
// 账本目录不存在,则创建
|
|
dataPath := serverConfig.DataPath
|
|
if !script.FileIfExist(dataPath) {
|
|
err = script.MkDir(dataPath)
|
|
if err != nil {
|
|
InternalError(c, err.Error())
|
|
return
|
|
}
|
|
}
|
|
// 加载账户缓存
|
|
err = script.LoadLedgerConfigMap()
|
|
if err != nil {
|
|
InternalError(c, err.Error())
|
|
return
|
|
}
|
|
err = script.LoadLedgerAccountsMap()
|
|
if err != nil {
|
|
InternalError(c, err.Error())
|
|
return
|
|
}
|
|
QueryServerConfig(c)
|
|
}
|
|
|
|
type LoginForm struct {
|
|
LedgerName string `form:"ledgerName" binding:"required"`
|
|
Secret string `form:"secret"`
|
|
OperatingCurrency string `form:"operatingCurrency"`
|
|
StartDate string `form:"startDate"`
|
|
OpeningBalances string `form:"openingBalances"`
|
|
IsBak bool `form:"isBak"`
|
|
}
|
|
|
|
func OpenOrCreateLedger(c *gin.Context) {
|
|
var loginForm LoginForm
|
|
if err := c.ShouldBindJSON(&loginForm); err != nil {
|
|
BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
// is mail exist white list
|
|
if !script.IsInWhiteList(loginForm.LedgerName) {
|
|
LedgerIsNotExist(c)
|
|
return
|
|
}
|
|
|
|
t := sha1.New()
|
|
_, err := io.WriteString(t, loginForm.LedgerName+loginForm.Secret)
|
|
if err != nil {
|
|
LedgerIsNotAllowAccess(c)
|
|
return
|
|
}
|
|
|
|
ledgerId := hex.EncodeToString(t.Sum(nil))
|
|
userLedger := script.GetLedgerConfigByMail(loginForm.LedgerName)
|
|
if userLedger != nil {
|
|
if ledgerId != userLedger.Id {
|
|
LedgerIsNotAllowAccess(c)
|
|
return
|
|
}
|
|
// 账本已存在,返回账本信息
|
|
resultMap := make(map[string]string)
|
|
resultMap["ledgerId"] = ledgerId
|
|
resultMap["title"] = userLedger.Title
|
|
resultMap["currency"] = userLedger.OperatingCurrency
|
|
resultMap["currencySymbol"] = script.GetCommoditySymbol(userLedger.OperatingCurrency)
|
|
resultMap["createDate"] = userLedger.CreateDate
|
|
OK(c, resultMap)
|
|
return
|
|
}
|
|
|
|
userLedger, err = createNewLedger(loginForm, ledgerId)
|
|
if err != nil {
|
|
InternalError(c, err.Error())
|
|
return
|
|
}
|
|
|
|
resultMap := make(map[string]string)
|
|
resultMap["ledgerId"] = ledgerId
|
|
resultMap["title"] = userLedger.Title
|
|
resultMap["currency"] = userLedger.OperatingCurrency
|
|
resultMap["currencySymbol"] = script.GetCommoditySymbol(userLedger.OperatingCurrency)
|
|
resultMap["createDate"] = userLedger.CreateDate
|
|
OK(c, resultMap)
|
|
}
|
|
|
|
func DeleteLedger(c *gin.Context) {
|
|
ledgerConfig := script.GetLedgerConfigFromContext(c)
|
|
// remove from ledger_config.json
|
|
ledgerConfigMap := script.GetLedgerConfigMap()
|
|
delete(ledgerConfigMap, ledgerConfig.Id)
|
|
err := script.WriteLedgerConfigMap(ledgerConfigMap)
|
|
if err != nil {
|
|
InternalError(c, "Failed to update ledger_config.json")
|
|
return
|
|
}
|
|
// remove from account cache
|
|
script.ClearLedgerAccounts(ledgerConfig.Id)
|
|
script.LogInfo(ledgerConfig.Mail, "Success clear ledger account cache "+ledgerConfig.Id)
|
|
// remove from account types cache
|
|
script.ClearLedgerAccountTypes(ledgerConfig.Id)
|
|
script.LogInfo(ledgerConfig.Mail, "Success clear ledger account types cache "+ledgerConfig.Id)
|
|
// delete source file
|
|
err = os.RemoveAll(ledgerConfig.DataPath)
|
|
if err != nil {
|
|
script.LogError(ledgerConfig.Mail, "Failed to delete ledger, cause by "+err.Error())
|
|
InternalError(c, "Failed to delete ledger")
|
|
return
|
|
}
|
|
script.LogInfo(ledgerConfig.Mail, "Success delete "+ledgerConfig.DataPath)
|
|
OK(c, "OK")
|
|
}
|
|
|
|
func CheckLedger(c *gin.Context) {
|
|
var stderr bytes.Buffer
|
|
ledgerConfig := script.GetLedgerConfigFromContext(c)
|
|
cmd := exec.Command("bean-check", script.GetLedgerIndexFilePath(ledgerConfig.DataPath))
|
|
cmd.Stderr = &stderr
|
|
_, err := cmd.Output()
|
|
result := make([]string, 0)
|
|
if err != nil {
|
|
errors := strings.Split(stderr.String(), "\r\n")
|
|
for _, e := range errors {
|
|
if e == "" {
|
|
continue
|
|
}
|
|
result = append(result, e)
|
|
}
|
|
}
|
|
OK(c, result)
|
|
}
|
|
|
|
func createNewLedger(loginForm LoginForm, ledgerId string) (*script.Config, error) {
|
|
// create new ledger
|
|
serverConfig := script.GetServerConfig()
|
|
ledgerConfigMap := script.GetLedgerConfigMap()
|
|
|
|
currency := loginForm.OperatingCurrency
|
|
if currency == "" {
|
|
currency = serverConfig.OperatingCurrency
|
|
}
|
|
startDate := loginForm.StartDate
|
|
if startDate == "" {
|
|
startDate = serverConfig.StartDate
|
|
}
|
|
openingBalances := loginForm.OpeningBalances
|
|
if openingBalances == "" {
|
|
openingBalances = serverConfig.OpeningBalances
|
|
}
|
|
|
|
ledgerConfig := script.Config{
|
|
Id: ledgerId,
|
|
Mail: loginForm.LedgerName,
|
|
Title: loginForm.LedgerName,
|
|
DataPath: serverConfig.DataPath + "/" + ledgerId,
|
|
OperatingCurrency: currency,
|
|
StartDate: startDate,
|
|
OpeningBalances: openingBalances,
|
|
IsBak: loginForm.IsBak,
|
|
CreateDate: time.Now().Format("2006-01-02"),
|
|
}
|
|
// init ledger files
|
|
err := initLedgerFiles(script.GetTemplateLedgerConfigDirPath(), ledgerConfig.DataPath, ledgerConfig)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// add ledger config to ledger_config.json
|
|
ledgerConfigMap[ledgerId] = ledgerConfig
|
|
err = script.WriteLedgerConfigMap(ledgerConfigMap)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// add accounts cache
|
|
err = script.LoadLedgerAccounts(ledgerId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// add currency cache
|
|
err = script.LoadLedgerCurrencyMap(ledgerConfig)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &ledgerConfig, nil
|
|
}
|
|
|
|
func initLedgerFiles(sourceFilePath string, targetFilePath string, ledgerConfig script.Config) error {
|
|
return copyFile(sourceFilePath, targetFilePath, ledgerConfig)
|
|
}
|
|
|
|
func copyFile(sourceFilePath string, targetFilePath string, ledgerConfig script.Config) error {
|
|
rd, err := ioutil.ReadDir(sourceFilePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, fi := range rd {
|
|
newSourceFilePath := sourceFilePath + "/" + fi.Name()
|
|
newTargetFilePath := targetFilePath + "/" + fi.Name()
|
|
if fi.IsDir() {
|
|
err = script.MkDir(newTargetFilePath)
|
|
if err == nil {
|
|
err = copyFile(newSourceFilePath, newTargetFilePath, ledgerConfig)
|
|
}
|
|
} else if !script.FileIfExist(newTargetFilePath) {
|
|
var fileContent, err = script.ReadFile(newSourceFilePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = script.WriteFile(newTargetFilePath, strings.ReplaceAll(strings.ReplaceAll(string(fileContent), "%startDate%", ledgerConfig.StartDate), "%operatingCurrency%", ledgerConfig.OperatingCurrency))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
script.LogInfo(ledgerConfig.Mail, "Success create file "+newTargetFilePath)
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|