Compare commits

..

5 Commits

Author SHA1 Message Date
初意 21322cb17f
Update build_beancount.yml 2024-07-09 00:43:07 +08:00
初意 9443404136
Update build_beancount.yml 2024-07-09 00:26:21 +08:00
BaoXuebin fdfa12c7d0 add build beancount dockerfile 2024-07-09 00:15:01 +08:00
BaoXuebin 5cd829ae27 query transaction api add isAnotherCurrency filed 2024-07-08 23:59:35 +08:00
BaoXuebin b8488f5fd6 add: beancount deps, beancount build dockerfile 2024-07-08 14:32:58 +08:00
6 changed files with 132 additions and 72 deletions

36
.github/workflows/build_beancount.yml vendored Normal file
View File

@ -0,0 +1,36 @@
name: Build and Push Docker Image to Docker Hub
# 仅手动触发
on:
workflow_dispatch:
inputs:
tag:
description: 'Tag for the Docker image'
required: false
default: '2.3.6'
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
-
name: Build and push
uses: docker/build-push-action@v4
with:
context: ./lib
platforms: linux/amd64,linux/arm64
push: true
tags: xdbin/beancount-alpine:${{ github.event.inputs.tag }}
labels: ${{ steps.meta.outputs.labels }}

View File

@ -1,60 +1,26 @@
# 构建beancount2.3.6
FROM python:3.11.9-alpine3.19 as beancount_builder
WORKDIR /build
RUN echo "https://mirrors.aliyun.com/alpine/v3.16/main/" > /etc/apk/repositories \
&& echo "https://mirrors.aliyun.com/alpine/v3.16/community/" >> /etc/apk/repositories \
&& set -x \
&& apk add --no-cache gcc musl-dev \
&& python3 -mvenv /app \
&& wget https://github.com/beancount/beancount/archive/refs/tags/2.3.6.tar.gz \
&& tar -zxvf 2.3.6.tar.gz \
&& /app/bin/pip install ./beancount-2.3.6 -i https://mirrors.aliyun.com/pypi/simple/ \
&& find /app -name __pycache__ -exec rm -rf -v {} + \
&& apk del gcc musl-dev
# 构建 beancount-gs # 构建 beancount-gs
FROM golang:1.17.3-alpine AS go_builder FROM golang:1.17.3 AS go_builder
ENV GO111MODULE=on \ ENV GO111MODULE=on \
GOPROXY=https://goproxy.cn,direct \ GOPROXY=https://goproxy.cn,direct \
GIN_MODE=release \ GIN_MODE=release \
CGO_ENABLED=0 \ CGO_ENABLED=0 \
PORT=80 PORT=80
WORKDIR /build WORKDIR /app
COPY . . COPY . .
COPY public/icons /build/public/default_icons COPY public/icons ./public/default_icons
RUN go build . RUN go build .
# 镜像 # 镜像
FROM python:3.11.9-alpine3.19 FROM xdbin/beancount-alpine:2.3.6
WORKDIR /app WORKDIR /app
COPY --from=go_builder /app/beancount-gs ./
#RUN echo "https://mirrors.aliyun.com/alpine/v3.16/main/" > /etc/apk/repositories \ COPY --from=go_builder /app/template ./template
# && echo "https://mirrors.aliyun.com/alpine/v3.16/community/" >> /etc/apk/repositories \ COPY --from=go_builder /app/config ./config
# && set -x \ COPY --from=go_builder /app/public ./public
# && apk update \ COPY --from=go_builder /app/logs ./logs
# && apk add --no-cache gcc musl-dev \
# && python3 -mvenv /app/beancount \
# && /app/beancount/bin/pip install --no-cache-dir beancount==2.3.6 -i https://mirrors.aliyun.com/pypi/simple/ \
# && apk del gcc musl-dev
# 大概116M的文件
COPY --from=beancount_builder /app /app/beancount
COPY --from=go_builder /build/beancount-gs /app
COPY --from=go_builder /build/template /app/template
COPY --from=go_builder /build/config /app/config
COPY --from=go_builder /build/public /app/public
COPY --from=go_builder /build/logs /app/logs
ENV LANG=C.UTF-8 \
SHELL=/bin/bash \
PS1="\u@\h:\w \$ " \
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/app/bin:/app/beancount/bin"
EXPOSE 80 EXPOSE 80

49
lib/Dockerfile Normal file
View File

@ -0,0 +1,49 @@
# 第一阶段:构建阶段
FROM python:3.11.9-alpine3.19 as builder
# 设置环境变量,防止 Python 创建 .pyc 文件
ENV PYTHONUNBUFFERED=1
# 替换为阿里云的镜像源,并安装必要的依赖
RUN echo "https://mirrors.aliyun.com/alpine/v3.15/main/" > /etc/apk/repositories && \
echo "https://mirrors.aliyun.com/alpine/v3.15/community/" >> /etc/apk/repositories && \
apk update && \
apk add --no-cache --virtual .build-deps \
gcc \
g++ \
musl-dev
# 设置工作目录
WORKDIR /app
# 创建虚拟环境
RUN python3 -m venv /app/venv
# 将 Beancount 源码压缩包复制到容器中
COPY beancount-2.3.6.tar.gz /app
# 解压 Beancount 源码到 /beancount 目录
RUN mkdir /beancount && \
tar -xzf /app/beancount-2.3.6.tar.gz -C /beancount --strip-components=1
# 激活虚拟环境并安装 Beancount
RUN /app/venv/bin/pip install --upgrade pip -i https://mirrors.aliyun.com/pypi/simple/ && \
/app/venv/bin/pip install /beancount -i https://mirrors.aliyun.com/pypi/simple/ && \
# 清理不必要的文件
rm -rf /app/beancount-2.3.6.tar.gz && \
find /app -name __pycache__ -exec rm -rf -v {} +
# 第二阶段:运行阶段
FROM python:3.11.9-alpine3.19
# 设置环境变量,防止 Python 创建 .pyc 文件
ENV PYTHONUNBUFFERED=1
# 设置工作目录
WORKDIR /app
# 从构建阶段复制虚拟环境到当前镜像
COPY --from=builder /app/venv /app/venv
# 将虚拟环境的 bin 目录添加到 PATH 环境变量
ENV PATH="/app/venv/bin:$PATH"

BIN
lib/beancount-2.3.6.tar.gz Normal file

Binary file not shown.

View File

@ -80,27 +80,27 @@ func getMaxDate(str_date1 string, str_date2 string) string {
// 获取1-2个日期字符串中最小的日期值 // 获取1-2个日期字符串中最小的日期值
// 如果双参数均为空,则返回账簿开始记账日期 // 如果双参数均为空,则返回账簿开始记账日期
func getMinDate(str_date1 string, str_date2 string) string { //func getMinDate(str_date1 string, str_date2 string) string {
//time_layout := "2006-01-02 15:04:05" // //time_layout := "2006-01-02 15:04:05"
var min_date string // var min_date string
if str_date1 != "" && str_date2 == "" { // if str_date1 != "" && str_date2 == "" {
// 只定义了第一个账户,取第一个账户的日期为准 // // 只定义了第一个账户,取第一个账户的日期为准
min_date = str_date1 // min_date = str_date1
} else if str_date1 == "" && str_date2 != "" { // } else if str_date1 == "" && str_date2 != "" {
// 只定义了第二个账户,取第二个账户的日期为准 // // 只定义了第二个账户,取第二个账户的日期为准
min_date = str_date2 // min_date = str_date2
} else if str_date1 != "" && str_date2 != "" { // } else if str_date1 != "" && str_date2 != "" {
// 重复定义的账户,取最早的时间 // // 重复定义的账户,取最早的时间
t1 := getTimeStamp(str_date1) // t1 := getTimeStamp(str_date1)
t2 := getTimeStamp(str_date2) // t2 := getTimeStamp(str_date2)
if t1 < t2 { // if t1 < t2 {
min_date = str_date1 // min_date = str_date1
} else { // } else {
min_date = str_date2 // min_date = str_date2
} // }
} else if str_date1 == "" && str_date2 == "" { // } else if str_date1 == "" && str_date2 == "" {
// 没有定义账户,取固定日期"1970-01-01" // // 没有定义账户,取固定日期"1970-01-01"
min_date = "1970-01-01" // min_date = "1970-01-01"
} // }
return min_date // return min_date
} //}

View File

@ -31,6 +31,7 @@ type Transaction struct {
Tags []string `bql:"tags" json:"tags"` Tags []string `bql:"tags" json:"tags"`
CurrencySymbol string `json:"currencySymbol,omitempty"` CurrencySymbol string `json:"currencySymbol,omitempty"`
CostCurrencySymbol string `json:"costCurrencySymbol,omitempty"` CostCurrencySymbol string `json:"costCurrencySymbol,omitempty"`
IsAnotherCurrency bool `json:"isAnotherCurrency,omitempty"`
} }
func QueryTransactions(c *gin.Context) { func QueryTransactions(c *gin.Context) {
@ -44,8 +45,16 @@ func QueryTransactions(c *gin.Context) {
InternalError(c, err.Error()) InternalError(c, err.Error())
return return
} }
currencyMap := script.GetLedgerCurrencyMap(ledgerConfig.Id)
// 格式化金额 // 格式化金额
for i := 0; i < len(transactions); i++ { for i := 0; i < len(transactions); i++ {
_, ok := currencyMap[transactions[i].Currency]
if ok {
transactions[i].IsAnotherCurrency = transactions[i].Currency != ledgerConfig.OperatingCurrency
}
symbol := script.GetCommoditySymbol(ledgerConfig.Id, transactions[i].Currency) symbol := script.GetCommoditySymbol(ledgerConfig.Id, transactions[i].Currency)
transactions[i].CurrencySymbol = symbol transactions[i].CurrencySymbol = symbol
transactions[i].CostCurrencySymbol = symbol transactions[i].CostCurrencySymbol = symbol