소스 검색

临时提交

qdy 4 주 전
부모
커밋
cccd5fa6cc

BIN
.DS_Store 파일 보기


+ 22
- 4
go.mod 파일 보기

@@ -3,9 +3,8 @@ module git.x2erp.com/qdy/go-svc-mercury
3 3
 go 1.25.4
4 4
 
5 5
 require (
6
-	git.x2erp.com/qdy/go-base v0.1.70
7
-	git.x2erp.com/qdy/go-db v0.1.70
8
-	go-micro.dev/v4 v4.11.0
6
+	git.x2erp.com/qdy/go-base v0.2.17
7
+	git.x2erp.com/qdy/go-db v0.2.17
9 8
 )
10 9
 
11 10
 require (
@@ -14,4 +13,23 @@ require (
14 13
 	gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
15 14
 )
16 15
 
17
-require gopkg.in/yaml.v2 v2.4.0 // indirect
16
+require (
17
+	filippo.io/edwards25519 v1.1.0 // indirect
18
+	github.com/go-resty/resty/v2 v2.17.0 // indirect
19
+	github.com/go-sql-driver/mysql v1.9.3 // indirect
20
+	github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
21
+	github.com/golang-sql/sqlexp v0.1.0 // indirect
22
+	github.com/google/uuid v1.6.0 // indirect
23
+	github.com/jmoiron/sqlx v1.4.0 // indirect
24
+	github.com/lib/pq v1.10.9 // indirect
25
+	github.com/microsoft/go-mssqldb v1.9.4 // indirect
26
+	github.com/sijms/go-ora/v2 v2.9.0 // indirect
27
+	github.com/stretchr/testify v1.11.1 // indirect
28
+	go.uber.org/multierr v1.10.0 // indirect
29
+	go.uber.org/zap v1.27.1 // indirect
30
+	golang.org/x/crypto v0.46.0 // indirect
31
+	golang.org/x/net v0.48.0 // indirect
32
+	golang.org/x/text v0.32.0 // indirect
33
+	gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
34
+	gopkg.in/yaml.v2 v2.4.0 // indirect
35
+)

+ 63
- 3
go.sum 파일 보기

@@ -1,14 +1,74 @@
1
-git.x2erp.com/qdy/go-base v0.1.44 h1:xHpMppSNj79lqdUc+lmgGXOgEvHyNotUayoe5/hHWr4=
2
-git.x2erp.com/qdy/go-base v0.1.44/go.mod h1:Q+YLwpCoU8CVSnzATLdz2LAzVMlz/CEGzo8DePf7cug=
1
+filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
2
+filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
3
+git.x2erp.com/qdy/go-base v0.1.70 h1:P5IOfSN6CnXcBYIrs+4BULYemPyzcgrFMkI7TcCri5A=
4
+git.x2erp.com/qdy/go-base v0.2.17 h1:uZ/rp/j78E6k16mOe7YOZb9/Hb5vI1FQ1JQMJGXVacM=
5
+git.x2erp.com/qdy/go-base v0.2.17/go.mod h1:f9SWxJLOW7k4D5HHZu4qSPb04yRGqBrfCuytPnOqN1Q=
6
+git.x2erp.com/qdy/go-db v0.1.70 h1:5VfvFxCmQ0+9OFEaPrTODYJ99wam+4lPjz4Y024SUdc=
7
+git.x2erp.com/qdy/go-db v0.2.17 h1:otPqNhpu9Zt8B2R77lGdpzW9vX/2NVs7BC32Ylyi0s4=
8
+git.x2erp.com/qdy/go-db v0.2.17/go.mod h1:/+k/JZ/KkDtWs3sHOerhVPK0kL4bJ/aIDizAIdsYyTE=
9
+github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U=
10
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4=
11
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4=
12
+github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.3.1 h1:Wgf5rZba3YZqeTNJPtvqZoBu1sBN/L4sry+u2U3Y75w=
13
+github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1 h1:bFWuoEKg+gImo7pvkiQEFAc8ocibADgXeiLAxWhWmkI=
14
+github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs=
3 15
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
16
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
17
+github.com/go-resty/resty/v2 v2.17.0 h1:pW9DeXcaL4Rrym4EZ8v7L19zZiIlWPg5YXAcVmt+gN0=
18
+github.com/go-resty/resty/v2 v2.17.0/go.mod h1:kCKZ3wWmwJaNc7S29BRtUhJwy7iqmn+2mLtQrOyQlVA=
19
+github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
20
+github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
21
+github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
22
+github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
23
+github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
24
+github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
25
+github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
26
+github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
27
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
28
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
29
+github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
30
+github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
31
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
4 32
 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
33
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
5 34
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
6 35
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
7 36
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
8 37
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
38
+github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
39
+github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
40
+github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
41
+github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
42
+github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
43
+github.com/microsoft/go-mssqldb v1.9.4 h1:sHrj3GcdgkxytZ09aZ3+ys72pMeyEXJowT44j74pNgs=
44
+github.com/microsoft/go-mssqldb v1.9.4/go.mod h1:GBbW9ASTiDC+mpgWDGKdm3FnFLTUsLYN3iFL90lQ+PA=
45
+github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
46
+github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
47
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
48
+github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
9 49
 github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
10
-go-micro.dev/v4 v4.11.0 h1:DZ2xcr0pnZJDlp6MJiCLhw4tXRxLw9xrJlPT91kubr0=
50
+github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
51
+github.com/sijms/go-ora/v2 v2.9.0 h1:+iQbUeTeCOFMb5BsOMgUhV8KWyrv9yjKpcK4x7+MFrg=
52
+github.com/sijms/go-ora/v2 v2.9.0/go.mod h1:QgFInVi3ZWyqAiJwzBQA+nbKYKH77tdp1PYoCqhR2dU=
53
+github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
54
+github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
55
+go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
56
+go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
57
+go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
58
+go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
59
+golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
60
+golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
61
+golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
62
+golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
63
+golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
64
+golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
65
+golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
66
+golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
11 67
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
12 68
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
69
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
70
+gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
71
+gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
13 72
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
14 73
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
74
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

+ 92
- 0
internal/cmd/sql_scheme.md 파일 보기

@@ -0,0 +1,92 @@
1
+我需要创建一个服装行业数据仓库的商品资料表,用于统计分析并为配货、补货、调拨提供决策支持。
2
+
3
+## 表信息
4
+- **表名**: `dw_product_master` (dw=数据仓库,product_master=商品主档)
5
+- **模型名称**: `DWProductMaster`
6
+- **表注释**: 商品资料主表 - 服装行业数据仓库核心表,存储商品基础信息与统计分析维度
7
+
8
+## 字段需求(国际化命名)
9
+
10
+### 1. 主键标识
11
+- **id**: 主键ID (bigint, 自增)
12
+
13
+### 2. 商品基础信息
14
+- **product_code**: 商品编码/货号 (varchar(50), 唯一索引)
15
+- **product_barcode**: 国际商品条码/EAN码 (varchar(20), 索引)
16
+- **product_name**: 商品名称 (varchar(200))
17
+- **product_name_en**: 商品英文名称 (varchar(200), 可选)
18
+- **product_short_name**: 商品简称/缩写 (varchar(100))
19
+
20
+### 3. 分类与品牌
21
+- **category_id**: 商品分类ID (bigint, 索引)
22
+- **category_code**: 分类代码 (varchar(20))
23
+- **category_name**: 分类名称 (varchar(100))
24
+- **brand_id**: 品牌ID (bigint, 索引)
25
+- **brand_code**: 品牌代码 (varchar(20))
26
+- **brand_name**: 品牌名称 (varchar(100))
27
+
28
+### 4. 规格属性(服装行业特性)
29
+- **style_code**: 款式编码 (varchar(30), 索引)
30
+- **color_code**: 颜色代码 (varchar(20))
31
+- **color_name**: 颜色名称 (varchar(50))
32
+- **size_code**: 尺码代码 (varchar(10))
33
+- **size_name**: 尺码名称 (varchar(20))
34
+- **season_code**: 季节代码 (varchar(10)) - SS(春夏)/FW(秋冬)
35
+- **year**: 年份 (smallint) - 如2024
36
+- **collection**: 系列/批次 (varchar(50))
37
+
38
+### 5. 供应链信息
39
+- **supplier_id**: 供应商ID (bigint, 索引)
40
+- **supplier_code**: 供应商代码 (varchar(30))
41
+- **supplier_name**: 供应商名称 (varchar(100))
42
+- **min_order_qty**: 最小起订量 (int)
43
+- **lead_time_days**: 采购提前期(天) (smallint)
44
+
45
+### 6. 价格信息
46
+- **cost_price**: 成本价 (decimal(10,2))
47
+- **suggested_retail_price**: 建议零售价 (decimal(10,2))
48
+- **current_price**: 当前售价 (decimal(10,2))
49
+- **currency_code**: 货币代码 (varchar(3), 默认'CNY')
50
+
51
+### 7. 库存与配补调相关
52
+- **safety_stock**: 安全库存水平 (int)
53
+- **max_stock**: 最高库存量 (int)
54
+- **reorder_point**: 补货点 (int)
55
+- **economic_order_qty**: 经济订货量 (int)
56
+- **abc_class**: ABC分类 (varchar(1)) - A/B/C
57
+- **xyz_class**: XYZ分类 (varchar(1)) - X/Y/Z (基于需求稳定性)
58
+
59
+### 8. 销售与绩效指标
60
+- **sales_velocity**: 销售流速(日均销量) (decimal(10,2))
61
+- **sell_through_rate**: 售罄率 (decimal(5,4))
62
+- **gross_margin**: 毛利率 (decimal(5,4))
63
+- **return_rate**: 退货率 (decimal(5,4))
64
+
65
+### 9. 状态与时间
66
+- **product_status**: 商品状态 (varchar(20)) - active/inactive/discontinued
67
+- **launch_date**: 上市日期 (date)
68
+- **discontinuation_date**: 停售日期 (date, 可选)
69
+- **data_date**: 数据日期 (date) - 数据仓库快照日期
70
+- **created_at**: 创建时间
71
+- **updated_at**: 更新时间
72
+- **deleted_at**: 删除时间
73
+
74
+## 索引要求
75
+1. 主键: id
76
+2. 唯一索引: product_code
77
+3. 普通索引: 
78
+   - product_barcode
79
+   - category_id
80
+   - brand_id
81
+   - supplier_id
82
+   - style_code
83
+   - 复合索引: (category_id, brand_id, season_code)
84
+
85
+## 特别要求
86
+1. 字段命名遵循国际化驼峰规则(snake_case英文)
87
+2. 所有业务字段都需中文注释说明
88
+3. 价格字段使用decimal精确计算
89
+4. 性能指标字段可为NULL,初始导入时可能无数据
90
+5. 参考 `/Users/kenqdy/Documents/v-bdx-workspace/svc-configure/internal/tables/config_project_skill.go` 的代码风格
91
+
92
+请生成完整的Go GORM表定义代码。

+ 145
- 0
internal/services/agent_to_doris.go 파일 보기

@@ -0,0 +1,145 @@
1
+package service
2
+
3
+import (
4
+	"fmt"
5
+	"strings"
6
+	"time"
7
+
8
+	"git.x2erp.com/qdy/go-base/logger"
9
+	"git.x2erp.com/qdy/go-base/types"
10
+	"git.x2erp.com/qdy/go-db/factory/doris"
11
+	"git.x2erp.com/qdy/go-db/factory/http"
12
+)
13
+
14
+// queryToCSVAndInsert 处理单次查询并将结果插入到Doris
15
+func queryToCSVAndInsert(queryRequest types.QueryRequest) *types.QueryResult[interface{}] {
16
+	// 记录查询开始时间
17
+	queryStartTime := time.Now()
18
+
19
+	// 1. 获取HTTP工厂实例
20
+	httpFactory, err := http.GetHTTPFactory()
21
+	if err != nil {
22
+		logger.Errorf("Failed to get HTTP factory: %v", err)
23
+		return &types.QueryResult[interface{}]{
24
+			Success: false,
25
+			Error:   fmt.Sprintf("failed to get HTTP factory: %v", err),
26
+		}
27
+	}
28
+	logger.Debug("HTTP factory created successfully")
29
+
30
+	// 2. 获取Doris工厂实例
31
+	dorisFactory, err := doris.GetDorisFactory(httpFactory)
32
+	if err != nil {
33
+		logger.Errorf("Failed to get Doris factory: %v", err)
34
+		return &types.QueryResult[interface{}]{
35
+			Success: false,
36
+			Error:   fmt.Sprintf("failed to get Doris factory: %v", err),
37
+		}
38
+	}
39
+	logger.Debug("Doris factory created successfully")
40
+
41
+	// 3. 创建HTTP客户端
42
+	httpClient := httpFactory.CreateClient()
43
+
44
+	agentQueryRequest := types.QueryRequest{
45
+		SQL:              queryRequest.SQL,
46
+		Params:           queryRequest.Params,
47
+		PositionalParams: queryRequest.PositionalParams,
48
+		WriterHeader:     queryRequest.WriterHeader,
49
+	}
50
+
51
+	// 4. 发送POST请求到 /api/query/csv 获取CSV格式数据
52
+	resp, err := httpClient.PostWithAuth(
53
+		queryRequest.AgentUrl,
54
+		agentQueryRequest,
55
+		queryRequest.AgentToken,
56
+		nil,
57
+	)
58
+
59
+	queryEndTime := time.Now()
60
+	queryDuration := queryEndTime.Sub(queryStartTime)
61
+
62
+	if err != nil {
63
+		logger.Errorf("Query request failed: %v", err)
64
+		return &types.QueryResult[interface{}]{
65
+			Success:   false,
66
+			Error:     fmt.Sprintf("查询失败: %v", err),
67
+			QueryTime: queryDuration,
68
+		}
69
+	}
70
+
71
+	if resp.StatusCode() != 200 {
72
+		logger.Errorf("Query request failed with status code: %d", resp.StatusCode())
73
+		return &types.QueryResult[interface{}]{
74
+			Success:   false,
75
+			Error:     fmt.Sprintf("查询请求失败, 状态码: %d", resp.StatusCode()),
76
+			QueryTime: queryDuration,
77
+		}
78
+	}
79
+
80
+	// 5. 获取CSV数据
81
+	csvData := string(resp.Body())
82
+	if len(csvData) == 0 {
83
+		logger.Warn("No data queried")
84
+		return &types.QueryResult[interface{}]{
85
+			Success:   true,
86
+			Error:     "没有查询到数据",
87
+			QueryTime: queryDuration,
88
+		}
89
+	}
90
+
91
+	// 估算数据行数(CSV行数)
92
+	var totalRows int
93
+	if queryRequest.WriterHeader {
94
+		// 如果有表头,需要减1
95
+		lines := strings.Count(csvData, "\n")
96
+		if lines > 0 {
97
+			totalRows = lines - 1
98
+		}
99
+	} else {
100
+		totalRows = strings.Count(csvData, "\n")
101
+	}
102
+
103
+	logger.Debug("Query successful, retrieved %d rows of data", totalRows)
104
+
105
+	// 6. 插入数据到Doris
106
+	database := queryRequest.DorisDatabase
107
+	table := queryRequest.DorisTable
108
+	skipHeader := !queryRequest.WriterHeader // 如果包含表头,则跳过
109
+
110
+	saveStartTime := time.Now()
111
+	err = dorisFactory.InsertCSV(database, table, csvData, skipHeader)
112
+	saveEndTime := time.Now()
113
+	saveDuration := saveEndTime.Sub(saveStartTime)
114
+
115
+	if err != nil {
116
+		logger.Errorf("Failed to insert data into Doris: %v", err)
117
+		return &types.QueryResult[interface{}]{
118
+			Success:   false,
119
+			Error:     fmt.Sprintf("数据插入Doris失败: %v", err),
120
+			QueryTime: queryDuration,
121
+			SaveTime:  saveDuration,
122
+			Count:     totalRows,
123
+		}
124
+	}
125
+
126
+	logger.Debug("Data successfully inserted into Doris: database=%s, table=%s, rows=%d",
127
+		database, table, totalRows)
128
+
129
+	return &types.QueryResult[interface{}]{
130
+		Success:   true,
131
+		QueryTime: queryDuration,
132
+		SaveTime:  saveDuration,
133
+		Count:     totalRows,
134
+	}
135
+}
136
+
137
+// ServiceHandler 服务处理器(供router使用)
138
+func ServiceAgentToDoris(queryRequest types.QueryRequest) *types.QueryResult[interface{}] {
139
+	// 添加调试日志,确认 queryRequest 是否有数据
140
+	logger.Debug("Processing query request: SQL=%s, AgentUrl=%s, Params count=%d",
141
+		queryRequest.SQL, queryRequest.AgentUrl, len(queryRequest.PositionalParams))
142
+
143
+	// 执行查询并插入
144
+	return queryToCSVAndInsert(queryRequest)
145
+}

tables/decision_task.go → internal/tables/decision_task.go 파일 보기


tables/dim_category.go → internal/tables/dim_category.go 파일 보기


tables/dim_city.go → internal/tables/dim_city.go 파일 보기


tables/dim_city_temperature.go → internal/tables/dim_city_temperature.go 파일 보기


tables/dim_date.go → internal/tables/dim_date.go 파일 보기


+ 40
- 0
internal/tables/dim_depot.go 파일 보기

@@ -0,0 +1,40 @@
1
+package tables
2
+
3
+import (
4
+	"time"
5
+
6
+	"git.x2erp.com/qdy/go-db/sqldef"
7
+)
8
+
9
+func init() {
10
+	sqldef.AddRegistration(func(r *sqldef.Registry) {
11
+		tb := sqldef.NewTable("dim_depot", "店铺档案表").
12
+			ID("dim_depot_id", 32).Comment("店铺编码主键").End().
13
+			String("depot_id", 32).Comment("店铺编码").End().
14
+			String("depot_name", 64).NotNull().Comment("渠道名称(如:天猫旗舰店)").End().
15
+			String("depot_type", 32).NotNull().Comment("渠道类型(如:线上/线下/奥莱)").End().
16
+			String("tenant_id", 8).NotNull().Comment("租户ID").End().
17
+			String("city_id", 32).NotNull().Comment("店铺所在城市").End().
18
+			String("depot_address", 32).NotNull().Comment("店铺地址").End().
19
+			String("creator", 32).NotNull().Comment("创建人").End().
20
+			DateTime("created_at").NotNull().Default("CURRENT_TIMESTAMP").Comment("创建时间").End()
21
+		r.RegisterTable(tb.Build())
22
+	})
23
+}
24
+
25
+// DimDepot 店铺档案表结构体(原ConfigChannel调整为匹配表结构)
26
+type DimDepot struct {
27
+	DimDepotID   string    `gorm:"column:dim_depot_id;type:varchar(32);primaryKey;comment:店铺编码主键"`
28
+	DepotID      string    `gorm:"column:depot_id;type:varchar(32);comment:店铺编码"`
29
+	DepotName    string    `gorm:"column:depot_name;type:varchar(64);not null;comment:渠道名称(如:天猫旗舰店)"`
30
+	DepotType    string    `gorm:"column:depot_type;type:varchar(32);not null;comment:渠道类型(如:线上/线下/奥莱)"`
31
+	TenantID     string    `gorm:"column:tenant_id;type:varchar(8);not null;comment:租户ID"`
32
+	CityID       string    `gorm:"column:city_id;type:varchar(32);not null;comment:店铺所在城市"`
33
+	DepotAddress string    `gorm:"column:depot_address;type:varchar(32);not null;comment:店铺地址"`
34
+	Creator      string    `gorm:"column:creator;type:varchar(32);not null;comment:创建人"`
35
+	CreatedAt    time.Time `gorm:"column:created_at;type:datetime;not null;default:CURRENT_TIMESTAMP;comment:创建时间"`
36
+}
37
+
38
+func (DimDepot) TableName() string {
39
+	return "dim_depot"
40
+}

tables/dim_discount_rule.go → internal/tables/dim_discount_rule.go 파일 보기


tables/dim_season.go → internal/tables/dim_season.go 파일 보기

@@ -9,7 +9,7 @@ import (
9 9
 func init() {
10 10
 	sqldef.AddRegistration(func(r *sqldef.Registry) {
11 11
 		tb := sqldef.NewTable("dim_season", "季节波段档案表").
12
-			ID("season_id", 32).Comment("季节波段ID,主键").End().
12
+			ID("season_id", 32).NotNull().Comment("季节波段ID,主键").End().
13 13
 			String("season_code", 32).NotNull().Unique().Comment("季节编码(如:2024FA)").End().
14 14
 			String("season_name", 64).NotNull().Comment("季节名称(如:2024秋冬)").End().
15 15
 			Int("year").NotNull().Comment("年份").End().
@@ -17,7 +17,6 @@ func init() {
17 17
 			DateTime("plan_start").NotNull().Comment("季节计划开始日期").End().
18 18
 			DateTime("plan_end").NotNull().Comment("季节计划结束日期").End().
19 19
 			String("creator", 32).NotNull().Comment("创建人").End().
20
-			String("tenant_id", 8).NotNull().Comment("租户ID").End().
21 20
 			DateTime("created_at").NotNull().Default("CURRENT_TIMESTAMP").Comment("创建时间").End()
22 21
 		r.RegisterTable(tb.Build())
23 22
 	})
@@ -33,7 +32,6 @@ type DimSeason struct {
33 32
 	PlanEnd    time.Time `gorm:"column:plan_end;not null;comment:季节计划结束日期"`
34 33
 	Creator    string    `gorm:"column:creator;type:varchar(32);not null;comment:创建人"`
35 34
 	CreatedAt  time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:创建时间"`
36
-	TenantId   string    `gorm:"column:tenant_id;type:varchar(8);comment:租户ID"`
37 35
 }
38 36
 
39 37
 func (DimSeason) TableName() string { return "dim_season" }

tables/dim_store.go → internal/tables/dim_store.go 파일 보기


tables/dim_store_group.go → internal/tables/dim_store_group.go 파일 보기


tables/dwa_discount_daily.go → internal/tables/dwa_discount_daily.go 파일 보기


tables/dws_discount_analysis.go → internal/tables/dws_discount_analysis.go 파일 보기


tables/fact_campaign_plan.go → internal/tables/fact_campaign_plan.go 파일 보기


tables/inventory_snapshot.go → internal/tables/inventory_snapshot.go 파일 보기


tables/product_sku.go → internal/tables/product_sku.go 파일 보기


tables/purchase_receipt.go → internal/tables/purchase_receipt.go 파일 보기


tables/sales_transaction.go → internal/tables/sales_transaction.go 파일 보기


+ 54
- 28
main.go 파일 보기

@@ -3,19 +3,22 @@ package main
3 3
 import (
4 4
 	"log"
5 5
 
6
-	"git.x2erp.com/qdy/go-db/dbstart"
7 6
 	"git.x2erp.com/qdy/go-db/factory/database"
8 7
 
9
-	"git.x2erp.com/qdy/go-base/bootstraps"
8
+	"git.x2erp.com/qdy/go-base/config"
9
+	"git.x2erp.com/qdy/go-base/consul"
10
+	"git.x2erp.com/qdy/go-base/container"
10 11
 	"git.x2erp.com/qdy/go-base/ctx"
11 12
 	"git.x2erp.com/qdy/go-base/logger"
12 13
 	"git.x2erp.com/qdy/go-base/middleware"
13 14
 	"git.x2erp.com/qdy/go-base/webx"
15
+	"git.x2erp.com/qdy/go-base/webx/health"
16
+	"git.x2erp.com/qdy/go-base/webx/router"
14 17
 )
15 18
 
16 19
 var (
17
-	serviceName    = "svc-ai"
18
-	serviceVersion = "1"
20
+	appName    = "svc-mercury"
21
+	appVersion = "1"
19 22
 )
20 23
 
21 24
 // 定义结构体
@@ -33,37 +36,60 @@ type UserResponse struct {
33 36
 }
34 37
 
35 38
 func main() {
36
-	// 1. 初始化基础启动器
37
-	boot := bootstraps.NewBootstrapper(serviceName, serviceVersion)
38 39
 
39
-	// 2. 初始化数据库(都在bootstraps包中)
40
-	dbBoot := dbstart.NewDBBootstrapper(boot.GetConfig())
41
-	dbBoot.Init()
40
+	//0.日志
41
+	//logger.InitBootLog()
42
+	logBootFactory := logger.InitBootLog()
43
+
44
+	//1.获取配置文件
45
+	cfg := config.GetConfig()
46
+	cfg.SetAppName(appName)
47
+	cfg.SetAppVersion(appVersion)
48
+
49
+	//2.创建关闭容器
50
+	ctr := container.NewContainer(cfg)
51
+
52
+	//注册日志,实现自动关闭
53
+	container.Reg(ctr, logBootFactory)
54
+
55
+	//3.创建数据库工厂--如果需求
56
+	dbFactory := container.Create(ctr, database.CreateDBFactory)
42 57
 
43
-	agentDB := dbBoot.GetDBFactory("agent")
44 58
 	// 赋值认证中间件参数
45
-	middleware.JWTAuthMiddlewareInit(boot.GetConfig())
59
+	middleware.JWTAuthMiddlewareInit(cfg)
60
+
61
+	//测试数据库连接
62
+	dbFactory.TestConnection()
63
+
64
+	//得到webservice服务工厂
65
+	webxFactory := webx.GetWebServiceFactory()
66
+
67
+	//建立hhtpService服务
68
+	webServcie, _ := webxFactory.CreateService(cfg.GetServiceConfig())
69
+
70
+	//建立路由-api
71
+	routerService := router.NewWebService(webServcie.GetRouter())
72
+
73
+	//注册路由--api
74
+	registerDorisRouter(routerService, dbFactory)
46 75
 
47
-	// 3. 启动服务
48
-	//boot.StartService("default")
76
+	// 注册健康检查-api
77
+	health.RegisterConsulHealthCheck(routerService)
49 78
 
50
-	router := boot.GetRouter("default")
51
-	// 3. 创建 WebService 并传入数据库接口
52
-	ws := webx.NewWebService(router)
79
+	//启动服务
80
+	webServcie.Run()
53 81
 
54
-	//使用默认数据库
55
-	registerDefaultRouter(ws, dbBoot.GetDefaultDBFactory())
82
+	//启用运行日志
83
+	container.Create(ctr, logger.InitRuntimeLogger)
56 84
 
57
-	//启动第2个服务
58
-	routerDoris := boot.GetRouter("doris")
59
-	wsDoris := webx.NewWebService(routerDoris)
60
-	registerDorisRouter(wsDoris, agentDB)
85
+	//注册到注册中心
86
+	container.Create(ctr, consul.Register)
87
+	//等待关闭
88
+	webServcie.WaitForServiceShutdown(ctr)
61 89
 
62
-	// 6. 运行服务
63
-	boot.Run(dbBoot)
64 90
 }
65 91
 
66
-func registerDorisRouter(ws *webx.WebService, dbFactory *database.DBFactory) {
92
+func registerDorisRouter(ws *router.RouterService, dbFactory *database.DBFactory) {
67 93
 	// GET示例:路径参数绑定
68 94
 	ws.GET("/app/users/{id}",
69 95
 		func(id string, reqCtx *ctx.RequestContext) (UserResponse, error) {
@@ -99,7 +125,7 @@ func registerDorisRouter(ws *webx.WebService, dbFactory *database.DBFactory) {
99 125
 
100 126
 }
101 127
 
102
-func registerDefaultRouter(ws *webx.WebService, dbFactory *database.DBFactory) {
128
+func registerDefaultRouter(ws *router.RouterService, dbFactory *database.DBFactory) {
103 129
 	// GET示例:路径参数绑定
104 130
 	ws.GET("/api/users/{id}",
105 131
 		func(id string, reqCtx *ctx.RequestContext) (UserResponse, error) {
@@ -145,7 +171,7 @@ func registerDefaultRouter(ws *webx.WebService, dbFactory *database.DBFactory) {
145 171
 
146 172
 func getUser(id string, dbFactory *database.DBFactory) (UserResponse, error) {
147 173
 	if dbFactory != nil {
148
-		dbFactory.TestConnection(dbFactory.GetDBType())
174
+		dbFactory.TestConnection()
149 175
 	}
150 176
 
151 177
 	// 查询数据库...
@@ -159,7 +185,7 @@ func getUser(id string, dbFactory *database.DBFactory) (UserResponse, error) {
159 185
 // 业务函数示例
160 186
 func getUserOracle(id string, dbFactory *database.DBFactory) (UserResponse, error) {
161 187
 	if dbFactory != nil {
162
-		dbFactory.TestConnection(dbFactory.GetDBType())
188
+		dbFactory.TestConnection()
163 189
 	}
164 190
 
165 191
 	sql, queryParams := getSQLWithPaginationSQL(0, 10)

+ 0
- 38
tables/config_channel.go 파일 보기

@@ -1,38 +0,0 @@
1
-package tables
2
-
3
-import (
4
-	"time"
5
-
6
-	"git.x2erp.com/qdy/go-db/sqldef"
7
-)
8
-
9
-func init() {
10
-	sqldef.AddRegistration(func(r *sqldef.Registry) {
11
-		tb := sqldef.NewTable("config_channel", "渠道档案表").
12
-			ID("channel_id", 32).Comment("渠道编码,主键").End().
13
-			String("channel_name", 64).NotNull().Comment("渠道名称(如:天猫旗舰店)").End().
14
-			String("channel_type", 32).NotNull().Comment("渠道类型(如:线上/线下/奥莱)").End().
15
-			String("store_id", 32).Comment("关联门店/仓库ID,对应ERP编码").End().
16
-			String("tenant_id", 8).NotNull().Comment("租户ID").End().
17
-			String("store_group_id", 32).NotNull().Comment("所属店铺组").End().
18
-			String("creator", 32).NotNull().Comment("创建人").End().
19
-			DateTime("created_at").NotNull().Default("CURRENT_TIMESTAMP").Comment("创建时间").End()
20
-		r.RegisterTable(tb.Build())
21
-	})
22
-}
23
-
24
-// ConfigChannel 渠道档案表结构体
25
-type ConfigChannel struct {
26
-	ChannelID    string    `gorm:"column:channel_id;type:varchar(32);primaryKey;not null;comment:渠道编码,主键"`
27
-	ChannelName  string    `gorm:"column:channel_name;type:varchar(64);not null;comment:渠道名称(如:天猫旗舰店)"`
28
-	ChannelType  string    `gorm:"column:channel_type;type:varchar(32);not null;comment:渠道类型(如:线上/线下/奥莱)"`
29
-	StoreID      string    `gorm:"column:store_id;type:varchar(32);comment:关联门店/仓库ID,对应ERP编码"`
30
-	TenantId     string    `gorm:"column:tenant_id;type:varchar(8);comment:租户ID"`
31
-	Creator      string    `gorm:"column:creator;type:varchar(32);not null;comment:创建人"`
32
-	CreatedAt    time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:创建时间"`
33
-	StoreGroupID string    `gorm:"column:store_group_id;type:varchar(32);comment:所属店铺组"`
34
-}
35
-
36
-func (ConfigChannel) TableName() string {
37
-	return "config_channel"
38
-}

Loading…
취소
저장