This commit is contained in:
Simmons 2024-07-17 15:13:00 +08:00
commit eb98dd1596
110 changed files with 14630 additions and 0 deletions

242
api/test.data/chart.go Normal file
View File

@ -0,0 +1,242 @@
package test_data
import (
"github.com/gin-gonic/gin"
"testData/model/response"
test_data "testData/repository/test.data"
"testData/request"
"testData/utils"
)
type ITestService interface {
}
type TestService struct{}
func InitTestService() *TestService {
return &TestService{}
}
// @Tags 数据分析平台
// @Summary 查询参数
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.QuerySelection true "查询参数"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}"
// @Router /testData/selection [post]
func (S *TestService) Selection(c *gin.Context) {
r := request.QuerySelection{}
_ = c.ShouldBind(&r)
if msg, ok := utils.ValidateInfo2CN(r); !ok {
response.FailWithMessage(msg, c)
return
}
response.OkWithData(test_data.QuerySelection(&r), c)
}
// @Tags 数据分析平台
// @Summary 直方图
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.Histogram true "直方图"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}"
// @Router /testData/histogram [post]
func (S *TestService) Histogram(c *gin.Context) {
r := request.Histogram{}
_ = c.ShouldBind(&r)
if msg, ok := utils.ValidateInfo2CN(r); !ok {
response.FailWithMessage(msg, c)
return
}
data, err := test_data.Histogram(&r)
if err != nil {
response.FailWithMessage(err.Error(), c)
return
}
response.OkWithData(gin.H{"data": data}, c)
}
// @Tags 数据分析平台
// @Summary 散点图
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.Scatter true "散点图"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}"
// @Router /testData/scatter [post]
func (S *TestService) Scatter(c *gin.Context) {
r := request.Scatter{}
_ = c.ShouldBind(&r)
if msg, ok := utils.ValidateInfo2CN(r); !ok {
response.FailWithMessage(msg, c)
return
}
data, x, y, err := test_data.Scatter(&r)
if err != nil {
response.FailWithMessage(err.Error(), c)
return
}
response.OkWithData(gin.H{"data": data, "x": x, "y": y}, c)
}
// @Tags 数据分析平台
// @Summary 饼状图
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.Pie true "饼状图"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}"
// @Router /testData/pie [post]
func (S *TestService) Pie(c *gin.Context) {
r := request.Pie{}
_ = c.ShouldBind(&r)
if msg, ok := utils.ValidateInfo2CN(r); !ok {
response.FailWithMessage(msg, c)
return
}
data, err := test_data.Pie(&r)
if err != nil {
response.FailWithMessage(err.Error(), c)
return
}
response.OkWithData(data, c)
}
// @Tags 数据分析平台
// @Summary 折线图
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.Line true "折线图"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}"
// @Router /testData/line [post]
func (S *TestService) Line(c *gin.Context) {
r := request.Line{}
_ = c.ShouldBind(&r)
if msg, ok := utils.ValidateInfo2CN(r); !ok {
response.FailWithMessage(msg, c)
return
}
data, err := test_data.Line(&r)
if err != nil {
response.FailWithMessage(err.Error(), c)
return
}
response.OkWithData(data, c)
}
// @Tags 数据分析平台
// @Summary CP Map图
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.CPMap true "CP Map图"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}"
// @Router /testData/cpMap [post]
func (S *TestService) CPMap(c *gin.Context) {
r := request.CPMap{}
_ = c.ShouldBind(&r)
if msg, ok := utils.ValidateInfo2CN(r); !ok {
response.FailWithMessage(msg, c)
return
}
res, err := test_data.CPMap(&r)
if err != nil {
response.FailWithMessage(err.Error(), c)
return
}
response.OkWithData(res, c)
}
// @Tags 数据分析平台
// @Summary 导出CP Map图
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.CPMap true "CP Map图"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}"
// @Router /testData/cpMap/export [post]
func (S *TestService) CPMapExport(c *gin.Context) {
r := request.CPMap{}
_ = c.ShouldBind(&r)
if msg, ok := utils.ValidateInfo2CN(r); !ok {
response.FailWithMessage(msg, c)
return
}
response.OkWithData(test_data.ExportCPMap(&r), c)
}
// @Tags 数据分析平台
// @Summary 导出直方图
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.Histogram true "CP Map图"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}"
// @Router /testData/ftHistogram/export [post]
func (S *TestService) ExportHistogram(c *gin.Context) {
r := request.Histogram{}
_ = c.ShouldBind(&r)
if msg, ok := utils.ValidateInfo2CN(r); !ok {
response.FailWithMessage(msg, c)
return
}
response.OkWithData(test_data.ExportHistogram(&r), c)
}
// @Tags 数据分析平台
// @Summary 导出散点图
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.Scatter true "CP Map图"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}"
// @Router /testData/scatter/export [post]
func (S *TestService) ExportScatter(c *gin.Context) {
r := request.Scatter{}
_ = c.ShouldBind(&r)
if msg, ok := utils.ValidateInfo2CN(r); !ok {
response.FailWithMessage(msg, c)
return
}
response.OkWithData(test_data.ExportScatter(&r), c)
}
// @Tags 数据分析平台
// @Summary Log各Site差异图
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.LogSiteChart true "Log各Site差异图"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}"
// @Router /testData/logSite [post]
func (S *TestService) LogSite(c *gin.Context) {
r := request.LogSiteChart{}
_ = c.ShouldBind(&r)
if msg, ok := utils.ValidateInfo2CN(r); !ok {
response.FailWithMessage(msg, c)
return
}
response.OkWithData(test_data.LogSiteChart(&r), c)
}
// @Tags 数据分析平台
// @Summary 参数极限
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.SelectionLimit true "参数极限"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}"
// @Router /testData/selection/limit [post]
func (S *TestService) SelectionLimit(c *gin.Context) {
r := request.SelectionLimit{}
_ = c.ShouldBind(&r)
if msg, ok := utils.ValidateInfo2CN(r); !ok {
response.FailWithMessage(msg, c)
return
}
max, min := test_data.SelectionLimit(&r)
response.OkWithData(gin.H{"max": max, "min": min}, c)
}

View File

@ -0,0 +1,93 @@
package test_data
import (
"github.com/gin-gonic/gin"
"testData/model/response"
test_data "testData/repository/test.data"
"testData/request"
"testData/utils"
)
type IReportChartService interface {
}
type ReportChartService struct{}
func InitReportChartService() *ReportChartService {
return &ReportChartService{}
}
// @Tags 数据分析平台-生产
// @Summary 封装良率折线图
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.PackagePassProbabilityLine true "查询参数"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}"
// @Router /testData/report/packagePassProbabilityLine [post]
func (S *ReportChartService) PackagePassProbabilityLine(c *gin.Context) {
r := request.PackagePassProbabilityLine{}
_ = c.ShouldBind(&r)
if msg, ok := utils.ValidateInfo2CN(r); !ok {
response.FailWithMessage(msg, c)
return
}
lines, max, min := test_data.PackagePassProbabilityLine(&r)
response.OkWithData(gin.H{"lines": lines, "max": max, "min": min}, c)
}
// @Tags 数据分析平台-生产
// @Summary 封装良率折线图
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.PackagePassProbabilityLine true "查询参数"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}"
// @Router /testData/report/packageOrderNumberBar [post]
func (S *ReportChartService) PackageOrderNumberBar(c *gin.Context) {
r := request.PackagePassProbabilityLine{}
_ = c.ShouldBind(&r)
if msg, ok := utils.ValidateInfo2CN(r); !ok {
response.FailWithMessage(msg, c)
return
}
response.OkWithData(test_data.OrderNumberHistogram(&r), c)
}
// @Tags 数据分析平台-生产
// @Summary 测试良率-按供应商
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.PassProbabilityByFactory true "查询参数"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}"
// @Router /testData/report/fTPassProbabilityByFactory [post]
func (S *ReportChartService) FTPassProbabilityByFactory(c *gin.Context) {
r := request.PassProbabilityByFactory{}
_ = c.ShouldBind(&r)
if msg, ok := utils.ValidateInfo2CN(r); !ok {
response.FailWithMessage(msg, c)
return
}
lines, histogram, max, min := test_data.PassProbabilityByFactory(&r)
response.OkWithData(gin.H{"lines": lines, "histogram": histogram, "max": max, "min": min}, c)
}
// @Tags 数据分析平台-生产
// @Summary 测试良率-按产品型号
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.PassProbabilityByProduct true "查询参数"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}"
// @Router /testData/report/fTPassProbabilityByProduct [post]
func (S *ReportChartService) FTPassProbabilityByProduct(c *gin.Context) {
r := request.PassProbabilityByProduct{}
_ = c.ShouldBind(&r)
if msg, ok := utils.ValidateInfo2CN(r); !ok {
response.FailWithMessage(msg, c)
return
}
lines, histogram, binLines, binHistogram := test_data.FTPassProbabilityByProduct(&r)
response.OkWithData(gin.H{"lines": lines, "histogram": histogram, "bin_lines": binLines, "bin_histogram": binHistogram}, c)
}

View File

@ -0,0 +1,95 @@
package test_data
import (
"github.com/gin-gonic/gin"
"testData/global"
"testData/model"
"testData/model/response"
test_data "testData/repository/test.data"
"testData/request"
"testData/utils"
)
type IReportListService interface {
}
type ReportListService struct{}
func InitReportService() *ReportListService {
global.PostGreSQL.AutoMigrate(&model.Report{}, &model.FinalReport{}, &model.ReportSites{}, &model.BinFail{})
return &ReportListService{}
}
// @Tags 数据分析平台-生产
// @Summary 晶圆记录
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.WaferList true "查询参数"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}"
// @Router /testData/report/wafer [post]
func (S *ReportListService) WaferList(c *gin.Context) {
r := request.WaferList{}
_ = c.ShouldBind(&r)
if msg, ok := utils.ValidateInfo2CN(r); !ok {
response.FailWithMessage(msg, c)
return
}
response.OkWithData(test_data.WaferList(&r), c)
}
// @Tags 数据分析平台-生产
// @Summary CP记录
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.CPList true "查询参数"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}"
// @Router /testData/report/cp [post]
func (S *ReportListService) CPList(c *gin.Context) {
r := request.CPList{}
_ = c.ShouldBind(&r)
if msg, ok := utils.ValidateInfo2CN(r); !ok {
response.FailWithMessage(msg, c)
return
}
list, total := test_data.CPList(&r)
response.OkWithData(gin.H{"list": list, "total": total}, c)
}
// @Tags 数据分析平台-生产
// @Summary 封装记录
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.ABList true "查询参数"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}"
// @Router /testData/report/ab [post]
func (S *ReportListService) ABList(c *gin.Context) {
r := request.ABList{}
_ = c.ShouldBind(&r)
if msg, ok := utils.ValidateInfo2CN(r); !ok {
response.FailWithMessage(msg, c)
return
}
response.OkWithData(test_data.ABList(&r), c)
}
// @Tags 数据分析平台-生产
// @Summary FT记录
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.FTList true "查询参数"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}"
// @Router /testData/report/ft [post]
func (S *ReportListService) FTList(c *gin.Context) {
r := request.FTList{}
_ = c.ShouldBind(&r)
if msg, ok := utils.ValidateInfo2CN(r); !ok {
response.FailWithMessage(msg, c)
return
}
list, total := test_data.FTList(&r)
response.OkWithData(gin.H{"list": list, "total": total}, c)
}

129
api/test.data/upload.go Normal file
View File

@ -0,0 +1,129 @@
package test_data
import (
"github.com/gin-gonic/gin"
"os"
"path/filepath"
"strings"
"testData/model"
"testData/model/response"
test_data "testData/repository/test.data"
"time"
)
type UploadService struct {
}
func InitUpload() *UploadService {
return &UploadService{}
}
// @Tags 数据分析平台
// @Summary 上传没录入文件
// @Security ApiKeyAuth
// @accept multipart/form-data
// @Param file formData file true "file"
// @Param value formData file true "product_name"
// @Param value formData file true "lot"
// @Param value formData file true "sub_batch"
// -// @Param data body request.SelectionLimit true "参数极限"
// @Produce application/json
// @Success 200 {string} string "{"success":true,"data":{},"msg":"操作成功"}"
// @Router /testData/upload [post]
func (D *UploadService) UploadAnswerFile(c *gin.Context) {
form, err := c.MultipartForm()
if err != nil {
response.FailWithMessage(err.Error(), c)
return
}
files := form.File["file"]
if len(form.Value["product_name"]) < 1 {
response.FailWithMessage("缺少产品名称", c)
return
}
productName := form.Value["product_name"][0]
if len(form.Value["lot"]) < 1 {
response.FailWithMessage("缺少批次", c)
return
}
lot := form.Value["lot"][0]
if len(form.Value["sub_batch"]) < 1 {
response.FailWithMessage("缺少子批次", c)
return
}
subBatch := form.Value["sub_batch"][0]
if len(form.Value["step"]) < 1 {
response.FailWithMessage("缺少工序", c)
return
}
step := form.Value["step"][0]
if len(form.Value["machine"]) < 1 {
response.FailWithMessage("缺少机台类型", c)
return
}
machine := form.Value["machine"][0]
if (lot == "" && subBatch == "") || productName == "" || step == "" || machine == "" {
response.FailWithMessage("信息不全", c)
return
}
fileTexts := make([]*model.FileText, 0)
for _, file := range files {
suffix := file.Filename[strings.LastIndex(file.Filename, "."):]
fileName := time.Now().Format("20060102150405") + suffix
os.MkdirAll("testData/siyuanUpload", os.ModePerm)
filePath := filepath.Join("testData/siyuanUpload", fileName)
if err = c.SaveUploadedFile(file, filePath); err != nil {
response.FailWithMessage(err.Error(), c)
return
}
fileTexts = append(fileTexts, &model.FileText{
Name: fileName,
Path: filePath,
Factory: "",
ProductName: productName,
Lot: lot,
SubBatch: subBatch,
})
}
//for _, file := range files {
// os.MkdirAll("testData/siyuanUpload", os.ModePerm)
// filePath := filepath.Join("testData/siyuanUpload", file.Filename)
// if err = c.SaveUploadedFile(file, filePath); err != nil {
// response.FailWithMessage(err.Error(), c)
// return
// }
// archive, err := zip.OpenReader(filePath)
// if err != nil {
// response.FailWithMessage(err.Error(), c)
// return
// }
// for _, archiveFile := range archive.File {
// archiveFilePath := filepath.Join("testData/siyuanUpload", archiveFile.Name)
// dstFile, err := os.OpenFile(archiveFilePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, archiveFile.Mode())
// if err != nil {
// log.Println("创建文件" + archiveFilePath + "失败")
// }
// inArchiveFile, err := archiveFile.Open()
// if err != nil {
// log.Println("打开压缩包内文件" + archiveFile.Name + "失败")
// }
// if _, err := io.Copy(dstFile, inArchiveFile); err != nil {
// log.Println("拷贝压缩包文件至" + archiveFilePath + "失败")
// }
// dstFile.Close()
// inArchiveFile.Close()
// fileTexts = append(fileTexts, &model.FileText{
// Name: archiveFile.Name,
// Path: archiveFilePath,
// Factory: "",
// ProductName: productName,
// Lot: lot,
// SubBatch: subBatch,
// })
// }
// archive.Close()
//}
test_data.HandleUploadFiles(fileTexts, step, machine)
response.Ok(c)
}

112
config.yml Normal file
View File

@ -0,0 +1,112 @@
dev: true # 是否为开发环境
dbType: mysql # postgres or mysql
Basedb: # mysql配置
user: root
password: 123456
host: 192.168.0.219:3306
dbname: sys_base
charset: utf8mb4
Wip:
user: root
password: 123456
host: 192.168.0.219:3306
dbname: wip
charset: utf8mb4
Bug:
user: root
password: 123456
host: 192.168.0.219:3306
dbname: bug
charset: utf8mb4
Tdb: # mysql配置
user: tpdb
password: TpMysql12#$
host: 192.168.0.55:3306
dbname: test_program
charset: utf8mb4
db: # mysql配置
user: tpdb
password: TpMysql12#$
host: 192.168.0.55:3306
dbname: flybook
storeDB: store
charset: utf8mb4
AttendanceDB:
user: tpdb
password: TpMysql12#$
host: 192.168.0.55:3306
dbname: attendance
charset: utf8mb4
DataFlowDB:
user: root
password: 123456
host: 192.168.0.219:3306
dbname: data_flow
charset: utf8mb4
ForumDB:
user: root
password: 123456
host: 192.168.0.219:3306
dbname: forum
charset: utf8mb4
postgres: # Postgres配置
user: tpdb
password: TpMysql12#$
host: 192.168.0.56
port: 5432
dbname: test_data
redis:
# host: redis:6379 # docker-compose 时
host: 192.168.0.219:6379
db: 10
password: ""
oracle:
host: 192.168.0.30:1521
user: tkplusemi
password: tkplusemi
SID: topprod
mongodb:
host: 192.168.0.219
port: 27017
system:
port: :28007
signingKey: "tkpluse-jwt-online-token"
captchaLength: 6
domain: http://192.168.0.195:28007/ # 必须以/ 结尾
testProgramDomain: http://192.168.0.189:28000/
ip2location: # 通过ip获取地理位置
getCoordinate: https://apis.map.qq.com/ws/location/v1/ip?ip=%s&key=XFZBZ-U2VWI-BWUGT-5FDUJ-BF6MS-RYBGC
getLocation: https://apis.map.qq.com/ws/geocoder/v1/?location=%f,%f&key=XFZBZ-U2VWI-BWUGT-5FDUJ-BF6MS-RYBGC&get_poi=1
flybook:
public:
AppId: cli_a00ba57c05b8500d
AppSecret: C8GNm4Yyb3IBI1Zd9dEjldJA137ewix3
VerificationToken: KMcvkJAvXfsNGE085eDkuclOAU7reueO
EncryptKey: D88KluIYjaeGL5cAVeRJxbRzjyjGOWgH
positionIDLength: 6
AD:
Addr: 192.168.0.38:636
BindUserName: "administrator@tkpluse.com"
BindPassword: "123qweASD!@#"
RootOu: "OU=TKPLUSE"
SearchDN: "DC=tkpluse,DC=com"

1627
docs/docs.go Normal file

File diff suppressed because it is too large Load Diff

1554
docs/swagger.json Normal file

File diff suppressed because it is too large Load Diff

1021
docs/swagger.yaml Normal file

File diff suppressed because it is too large Load Diff

17
global/global.go Normal file
View File

@ -0,0 +1,17 @@
package global
import (
"github.com/emersion/go-imap/client"
"go.mongodb.org/mongo-driver/mongo"
"go.uber.org/zap"
"gorm.io/gorm"
)
var (
PostGreSQL *gorm.DB
BaseDB *gorm.DB
Oracle *gorm.DB
MongoDB *mongo.Client
Log *zap.SugaredLogger
IMAP *client.Client
)

125
go.mod Normal file
View File

@ -0,0 +1,125 @@
module testData
go 1.19
require github.com/natefinch/lumberjack v2.0.0+incompatible
require (
gitee.com/golang-module/carbon/v2 v2.3.11 // indirect
github.com/KyleBanks/depth v1.2.1 // indirect
github.com/PuerkitoBio/purell v1.2.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect
github.com/bytedance/sonic v1.11.2 // indirect
github.com/casbin/casbin/v2 v2.82.0 // indirect
github.com/casbin/gorm-adapter/v3 v3.21.0 // indirect
github.com/casbin/govaluate v1.1.1 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/dzwvip/oracle v1.3.0 // indirect
github.com/emersion/go-imap v1.2.1 // indirect
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/extrame/ole2 v0.0.0-20160812065207-d69429661ad7 // indirect
github.com/extrame/xls v0.0.1 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.9.1 // indirect
github.com/glebarez/go-sqlite v1.22.0 // indirect
github.com/glebarez/sqlite v1.10.0 // indirect
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-openapi/jsonpointer v0.20.3 // indirect
github.com/go-openapi/jsonreference v0.20.5 // indirect
github.com/go-openapi/spec v0.20.15 // indirect
github.com/go-openapi/swag v0.22.10 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.19.0 // indirect
github.com/go-sql-driver/mysql v1.7.1 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/godror/godror v0.35.0 // indirect
github.com/godror/knownpb v0.1.1 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
github.com/golang-sql/sqlexp v0.1.0 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect
github.com/jackc/pgx/v5 v5.5.4 // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.7 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/microsoft/go-mssqldb v1.7.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/montanaflynn/stats v0.7.1 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/richardlehane/mscfb v1.0.4 // indirect
github.com/richardlehane/msoleps v1.0.3 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.18.2 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/swaggo/files v1.0.1 // indirect
github.com/swaggo/gin-swagger v1.6.0 // indirect
github.com/swaggo/swag v1.16.3 // indirect
github.com/thoas/go-funk v0.9.3 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
github.com/wolfogre/go-pprof-practice v0.0.0-20230706085634-23c8f603cac9 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d // indirect
github.com/xuri/excelize/v2 v2.8.2-0.20240717004416-68a1704900e0 // indirect
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 // indirect
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect
go.mongodb.org/mongo-driver v1.14.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/arch v0.7.0 // indirect
golang.org/x/crypto v0.25.0 // indirect
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
golang.org/x/net v0.27.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
google.golang.org/protobuf v1.34.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gorm.io/driver/mysql v1.5.4 // indirect
gorm.io/driver/postgres v1.5.6 // indirect
gorm.io/driver/sqlserver v1.5.3 // indirect
gorm.io/gorm v1.25.10 // indirect
gorm.io/plugin/dbresolver v1.5.1 // indirect
modernc.org/libc v1.42.1 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.7.2 // indirect
modernc.org/sqlite v1.29.3 // indirect
)

448
go.sum Normal file
View File

@ -0,0 +1,448 @@
gitee.com/golang-module/carbon/v2 v2.3.11 h1:lnHx65PlT/U0htW4c2fegVbDW3t5JuFT0ySQl1686EY=
gitee.com/golang-module/carbon/v2 v2.3.11/go.mod h1:10QdzWG6q/NUePI6ag183B0313WrwdtM0zMCWPdTLD8=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.0/go.mod h1:Q28U+75mpCaSCDowNEmhIo/rmgdkqmkmzI7N6TGR4UY=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0/go.mod h1:cw4zVQgBby0Z5f2v0itn6se2dDP17nTjbZFXW5uPyHA=
github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o=
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.0/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
github.com/PuerkitoBio/purell v1.2.1 h1:QsZ4TjvwiMpat6gBCBxEQI0rcS9ehtkKtSpiUnd9N28=
github.com/PuerkitoBio/purell v1.2.1/go.mod h1:ZwHcC/82TOaovDi//J/804umJFFmbOHPngi8iYYv/Eo=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
github.com/bytedance/sonic v1.11.2 h1:ywfwo0a/3j9HR8wsYGWsIWl2mvRsI950HyoxiBERw5A=
github.com/bytedance/sonic v1.11.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
github.com/casbin/casbin/v2 v2.82.0 h1:2CgvunqQQoepcbGRnMc9vEcDhuqh3B5yWKoj+kKSxf8=
github.com/casbin/casbin/v2 v2.82.0/go.mod h1:jX8uoN4veP85O/n2674r2qtfSXI6myvxW85f6TH50fw=
github.com/casbin/gorm-adapter/v3 v3.21.0 h1:1YOVpBvGc38H717WKSNCUuhsixFOjF8jmNukq792WBc=
github.com/casbin/gorm-adapter/v3 v3.21.0/go.mod h1:pvTTuyP2Es8VPHLyUssGtvOb3ETYD2tG7TfT5K8X2Sg=
github.com/casbin/govaluate v1.1.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
github.com/casbin/govaluate v1.1.1 h1:J1rFKIBhiC5xr0APd5HP6rDL+xt+BRoyq1pa4o2i/5c=
github.com/casbin/govaluate v1.1.1/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0=
github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko=
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/dzwvip/oracle v1.3.0 h1:b84ehEOASYkwLYutaVoq7N+ZagR9OThSVeQMLCIaeR4=
github.com/dzwvip/oracle v1.3.0/go.mod h1:WPibibY0r04N94fkltknygB+r9lqud8MUmMAgcWola4=
github.com/emersion/go-imap v1.2.1 h1:+s9ZjMEjOB8NzZMVTM3cCenz2JrQIGGo5j1df19WjTA=
github.com/emersion/go-imap v1.2.1/go.mod h1:Qlx1FSx2FTxjnjWpIlVNEuX+ylerZQNFE5NsmKFSejY=
github.com/emersion/go-message v0.15.0/go.mod h1:wQUEfE+38+7EW8p8aZ96ptg6bAb1iwdgej19uXASlE4=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/extrame/ole2 v0.0.0-20160812065207-d69429661ad7 h1:n+nk0bNe2+gVbRI8WRbLFVwwcBQ0rr5p+gzkKb6ol8c=
github.com/extrame/ole2 v0.0.0-20160812065207-d69429661ad7/go.mod h1:GPpMrAfHdb8IdQ1/R2uIRBsNfnPnwsYE9YYI5WyY1zw=
github.com/extrame/xls v0.0.1 h1:jI7L/o3z73TyyENPopsLS/Jlekm3nF1a/kF5hKBvy/k=
github.com/extrame/xls v0.0.1/go.mod h1:iACcgahst7BboCpIMSpnFs4SKyU9ZjsvZBfNbUxZOJI=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ=
github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc=
github.com/glebarez/sqlite v1.10.0 h1:u4gt8y7OND/cCei/NMHmfbLxF6xP2wgKcT/BJf2pYkc=
github.com/glebarez/sqlite v1.10.0/go.mod h1:IJ+lfSOmiekhQsFTJRx/lHtGYmCdtAiTaf5wI9u5uHA=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-openapi/jsonpointer v0.20.3 h1:jykzYWS/kyGtsHfRt6aV8JTB9pcQAXPIA7qlZ5aRlyk=
github.com/go-openapi/jsonpointer v0.20.3/go.mod h1:c7l0rjoouAuIxCm8v/JWKRgMjDG/+/7UBWsXMrv6PsM=
github.com/go-openapi/jsonreference v0.20.5 h1:hutI+cQI+HbSQaIGSfsBsYI0pHk+CATf8Fk5gCSj0yI=
github.com/go-openapi/jsonreference v0.20.5/go.mod h1:thAqAp31UABtI+FQGKAQfmv7DbFpKNUlva2UPCxKu2Y=
github.com/go-openapi/spec v0.20.15 h1:8bDcVxF607pTh9NpPwgsH4J5Uhh5mV5XoWnkurdiY+U=
github.com/go-openapi/spec v0.20.15/go.mod h1:o0upgqg5uYFG7O5mADrDVmSG3Wa6y6OLhwiCqQ+sTv4=
github.com/go-openapi/swag v0.22.10 h1:4y86NVn7Z2yYd6pfS4Z+Nyh3aAUL3Nul+LMbhFKy0gA=
github.com/go-openapi/swag v0.22.10/go.mod h1:Cnn8BYtRlx6BNE3DPN86f/xkapGIcLWzh3CLEb4C1jI=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4=
github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/godror/godror v0.33.3/go.mod h1:FbrZ7po7LyS3gUTdW/K1+kIoePvP/E044HpwptL4vqw=
github.com/godror/godror v0.35.0 h1:V9sTD76SBPREtjsDL6YtZjW2FTwF9uI+ZIVTt/phzMo=
github.com/godror/godror v0.35.0/go.mod h1:jW1+pN+z/V0h28p9XZXVNtEvfZP/2EBfaSjKJLp3E4g=
github.com/godror/godror v0.43.0 h1:qMbQwG0ejJnKma3bBvrJg1rkiyP5b4v6uxvx9zDrKJw=
github.com/godror/godror v0.43.0/go.mod h1:82Uc/HdjsFVnzR5c9Yf6IkTBalK80jzm/U6xojbTo94=
github.com/godror/knownpb v0.1.0/go.mod h1:4nRFbQo1dDuwKnblRXDxrfCFYeT4hjg3GjMqef58eRE=
github.com/godror/knownpb v0.1.1 h1:A4J7jdx7jWBhJm18NntafzSC//iZDHkDi1+juwQ5pTI=
github.com/godror/knownpb v0.1.1/go.mod h1:4nRFbQo1dDuwKnblRXDxrfCFYeT4hjg3GjMqef58eRE=
github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA=
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY=
github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
github.com/jackc/pgx/v5 v5.5.4 h1:Xp2aQS8uXButQdnCMWNmvx6UysWQQC+u1EoizjguY+8=
github.com/jackc/pgx/v5 v5.5.4/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo=
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/microsoft/go-mssqldb v1.6.0/go.mod h1:00mDtPbeQCRGC1HwOOR5K/gr30P1NcEG0vx6Kbv2aJU=
github.com/microsoft/go-mssqldb v1.7.0 h1:sgMPW0HA6Ihd37Yx0MzHyKD726C2kY/8KJsQtXHNaAs=
github.com/microsoft/go-mssqldb v1.7.0/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM=
github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/oklog/ulid/v2 v2.0.2/go.mod h1:mtBL0Qe/0HAx6/a4Z30qxVIAL1eQDweXq5lxOEiwQ68=
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM=
github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg=
github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M=
github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo=
github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg=
github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk=
github.com/thoas/go-funk v0.7.0/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q=
github.com/thoas/go-funk v0.9.3 h1:7+nAEx3kn5ZJcnDm2Bh23N2yOtweO14bi//dvRtgLpw=
github.com/thoas/go-funk v0.9.3/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/wolfogre/go-pprof-practice v0.0.0-20230706085634-23c8f603cac9 h1:JUZL5TQ/WK5veU2N171inEvwseqf4V0TxgGKl2Ypyvs=
github.com/wolfogre/go-pprof-practice v0.0.0-20230706085634-23c8f603cac9/go.mod h1:guVzD2XeU5rwULTURC4peeFyZya60U0BLKqisEjCylA=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
github.com/xuri/efp v0.0.0-20230802181842-ad255f2331ca/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 h1:Chd9DkqERQQuHpXjR/HSV1jLZA6uaoiwwH3vSuF3IW0=
github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d h1:llb0neMWDQe87IzJLS4Ci7psK/lVsjIS2otl+1WyRyY=
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
github.com/xuri/excelize/v2 v2.8.0 h1:Vd4Qy809fupgp1v7X+nCS/MioeQmYVVzi495UCTqB7U=
github.com/xuri/excelize/v2 v2.8.0/go.mod h1:6iA2edBTKxKbZAa7X5bDhcCg51xdOn1Ar5sfoXRGrQg=
github.com/xuri/excelize/v2 v2.8.1 h1:pZLMEwK8ep+CLIUWpWmvW8IWE/yxqG0I1xcN6cVMGuQ=
github.com/xuri/excelize/v2 v2.8.1/go.mod h1:oli1E4C3Pa5RXg1TBXn4ENCXDV5JUMlBluUhG7c+CEE=
github.com/xuri/excelize/v2 v2.8.2-0.20240717004416-68a1704900e0 h1:m8LOTcksvhzoCRSI4fwlCaaBJ3MShtjhfTrxv2AboHk=
github.com/xuri/excelize/v2 v2.8.2-0.20240717004416-68a1704900e0/go.mod h1:0hWeRQBdU+HQng3S1AXdYm8Ob0dbevUncXAWI0QswPU=
github.com/xuri/nfp v0.0.0-20230819163627-dc951e3ffe1a/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 h1:qhbILQo1K3mphbwKh1vNm4oGezE1eF9fQWmNiIpSfI4=
github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 h1:hPVCafDV85blFTabnqKgNhDCkJX25eik94Si9cTER4A=
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk=
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc=
golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=
golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/mysql v1.4.3/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c=
gorm.io/driver/mysql v1.5.4 h1:igQmHfKcbaTVyAIHNhhB888vvxh8EdQ2uSUT0LPcBso=
gorm.io/driver/mysql v1.5.4/go.mod h1:9rYxJph/u9SWkWc9yY4XJ1F/+xO0S/ChOmbk3+Z5Tvs=
gorm.io/driver/postgres v1.5.4 h1:Iyrp9Meh3GmbSuyIAGyjkN+n9K+GHX9b9MqsTL4EJCo=
gorm.io/driver/postgres v1.5.4/go.mod h1:Bgo89+h0CRcdA33Y6frlaHHVuTdOf87pmyzwW9C/BH0=
gorm.io/driver/postgres v1.5.6 h1:ydr9xEd5YAM0vxVDY0X139dyzNz10spDiDlC7+ibLeU=
gorm.io/driver/postgres v1.5.6/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA=
gorm.io/driver/sqlserver v1.5.3 h1:rjupPS4PVw+rjJkfvr8jn2lJ8BMhT4UW5FwuJY0P3Z0=
gorm.io/driver/sqlserver v1.5.3/go.mod h1:B+CZ0/7oFJ6tAlefsKoyxdgDCXJKSgwS2bMOQZT0I00=
gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.7 h1:VsD6acwRjz2zFxGO50gPO6AkNs7KKnvfzUjHQhZDz/A=
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/plugin/dbresolver v1.5.1 h1:s9Dj9f7r+1rE3nx/Ywzc85nXptUEaeOO0pt27xdopM8=
gorm.io/plugin/dbresolver v1.5.1/go.mod h1:l4Cn87EHLEYuqUncpEeTC2tTJQkjngPSD+lo8hIvcT0=
modernc.org/libc v1.42.1 h1:W2T7qUhyCmEaFxqNec9x0T6ohiffM/jvifCSwKC9Gj8=
modernc.org/libc v1.42.1/go.mod h1:UbS9Tjnye2q6hLYa7gw/q73fXB9lyn/fXLBGzgser8g=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E=
modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E=
modernc.org/sqlite v1.29.3 h1:6L71d3zXVB8oubdVSuwiurNyYRetQ3It8l1FSwylwQ0=
modernc.org/sqlite v1.29.3/go.mod h1:MjUIBKZ+tU/lqjNLbVAAMjsQPdWdA/ciwdhsT9kBwk8=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

40
initialization/base.db.go Normal file
View File

@ -0,0 +1,40 @@
package initialization
import (
"github.com/spf13/viper"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"testData/global"
"time"
)
func InitBaseDB() {
user := viper.GetString("Basedb.user")
password := viper.GetString("Basedb.password")
host := viper.GetString("Basedb.host")
dbname := viper.GetString("Basedb.dbname")
charset := viper.GetString("Basedb.charset")
dsn := user + ":" + password + "@tcp(" + host + ")/" + dbname + "?charset=" + charset + "&parseTime=True&loc=Local"
mysqlConfig := mysql.Config{
DSN: dsn, // DSN data source name
DefaultStringSize: 255, // string 类型字段的默认长度
DisableDatetimePrecision: true, // 禁用 datetime 精度MySQL 5.6 之前的数据库不支持
DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
DontSupportRenameColumn: true, // 用 `change` 重命名列MySQL 8 之前的数据库和 MariaDB 不支持重命名列
SkipInitializeWithVersion: false, // 根据版本自动配置
}
if db, err := gorm.Open(mysql.New(mysqlConfig), &gorm.Config{
DisableForeignKeyConstraintWhenMigrating: true,
Logger: logger.Default.LogMode(logger.Silent),
}); err != nil {
global.Log.Errorf("%s", err)
panic(err)
} else {
sqlDB, _ := db.DB()
sqlDB.SetMaxIdleConns(10) // 设置空闲连接池中连接的最大数量
sqlDB.SetMaxOpenConns(100) // 设置打开数据库连接的最大数量
sqlDB.SetConnMaxLifetime(time.Hour) // 设置了连接可复用的最大时间
global.BaseDB = db
}
}

17
initialization/config.go Normal file
View File

@ -0,0 +1,17 @@
package initialization
import (
"github.com/spf13/viper"
"os"
)
func InitConfig() {
workDir, _ := os.Getwd()
viper.SetConfigName("config")
viper.SetConfigType("yml")
viper.AddConfigPath(workDir)
err := viper.ReadInConfig()
if err != nil {
panic(err)
}
}

49
initialization/logger.go Normal file
View File

@ -0,0 +1,49 @@
package initialization
import (
"github.com/natefinch/lumberjack"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"os"
"testData/global"
"time"
)
func InitLogger() {
writeSyncer := getLogWriter()
encoder := getEncoder()
core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel)
// 显示日志发生的代码行号
//logger := zap.New(core, zap.AddCaller())
// 不显示日志发生的代码行号
logger := zap.New(core)
global.Log = logger.Sugar()
}
func getEncoder() zapcore.Encoder {
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = func(t time.Time, encoder zapcore.PrimitiveArrayEncoder) {
encoder.AppendString(t.Format("2006-01-02 15:04:05"))
}
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
return zapcore.NewConsoleEncoder(encoderConfig)
}
func getLogWriter() zapcore.WriteSyncer {
lumberJackLogger := &lumberjack.Logger{
Filename: "./log/message.log", // 日志文件路径
MaxSize: 1, // 每个日志文件保存最大尺寸,单位 M
MaxBackups: 15, // 日志最多保存多少个备份
MaxAge: 30, // 文件最多保存多少天
Compress: false, // 是否压缩
LocalTime: true, // 是否使用本地时间
}
defer lumberJackLogger.Close()
// 日志输出至console和文件
return zapcore.NewMultiWriteSyncer(
zapcore.AddSync(lumberJackLogger),
zapcore.AddSync(os.Stdout),
)
// 日志只输出到文件
//return zapcore.AddSync(lumberJackLogger)
}

23
initialization/mongo.go Normal file
View File

@ -0,0 +1,23 @@
package initialization
import (
"context"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readpref"
"testData/global"
)
func InitMongoDB() {
//host := viper.GetString("mongodb.host")
//port := viper.GetString("mongodb.port")
//client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI("mongodb://"+host+":"+port))
client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI("mongodb://localhost:27017"))
if err != nil {
panic(err)
}
if err = client.Ping(context.TODO(), readpref.Primary()); err != nil {
panic(err)
}
global.MongoDB = client
}

21
initialization/oracle.go Normal file
View File

@ -0,0 +1,21 @@
package initialization
import (
"github.com/dzwvip/oracle"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"testData/global"
)
func InitOracle() {
con, err := gorm.Open(oracle.Open("tkplusemi/tkplusemi@192.168.0.30:1521/topprod"), //
&gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
//QueryFields: true,
})
if err != nil {
println("oracle connect error:", err)
panic(err)
}
global.Oracle = con
}

36
initialization/postgre.go Normal file
View File

@ -0,0 +1,36 @@
package initialization
import (
"fmt"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"log"
"testData/global"
"testData/model"
"time"
)
func InitPostgres() {
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Shanghai",
"192.168.0.56",
"tpdb",
"TpMysql12#$",
"test_data",
"5432",
)
if db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
DisableForeignKeyConstraintWhenMigrating: true,
//Logger: logger.Default.LogMode(logger.Silent),
}); err != nil {
log.Printf("PostgreSQL Connection error: %s", err)
panic(err)
} else {
postgresDB, _ := db.DB()
postgresDB.SetMaxIdleConns(10)
postgresDB.SetMaxOpenConns(100)
postgresDB.SetConnMaxLifetime(time.Hour)
_ = db.AutoMigrate(&model.FileHandled{})
global.PostGreSQL = db
_ = global.PostGreSQL.AutoMigrate(&model.FileHandled{})
}
}

40
initialization/router.go Normal file
View File

@ -0,0 +1,40 @@
package initialization
import (
"github.com/gin-gonic/gin"
"github.com/spf13/viper"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
"net/http"
testdata "testData/api/test.data"
_ "testData/docs"
"testData/middleware"
"testData/model/response"
"testData/router"
)
func InitRouter() *gin.Engine {
r := gin.New()
r.Use(gin.Recovery(), middleware.Cors(), middleware.Log())
// 判断是否线上环境
if viper.GetBool("dev") {
r.GET("/docs/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
}
r.StaticFS("files", http.Dir("./files"))
testData := r.Group("testData")
{
router.InitChartRouter(testData)
router.InitReportListRouter(testData)
router.InitReportChartRouter(testData)
}
testDataUpload := r.Group("testData")
testDataUploadService := testdata.InitUpload()
{
testDataUpload.POST("upload", testDataUploadService.UploadAnswerFile)
}
r.NoRoute(func(c *gin.Context) {
response.FailWithMessage("Not Found", c)
})
return r
}

View File

@ -0,0 +1,23 @@
package initialization
import (
"github.com/spf13/viper"
"net/http"
"time"
)
func RunServer() {
port := viper.GetString("system.port")
r := InitRouter()
s := &http.Server{
Addr: port,
Handler: r,
ReadTimeout: 120 * time.Second,
WriteTimeout: 120 * time.Second,
MaxHeaderBytes: 1 << 20,
}
println("run on port", port)
if err := s.ListenAndServe(); err != nil {
panic(err)
}
}

1021
log/message.log Normal file

File diff suppressed because it is too large Load Diff

29
main.go Normal file
View File

@ -0,0 +1,29 @@
package main
import (
"testData/initialization"
)
func main() {
initialization.InitConfig()
initialization.InitPostgres()
initialization.InitBaseDB()
initialization.InitOracle()
//initialization.InitMongoDB()
initialization.InitLogger()
//var reports []*model.Report
//global.PostGreSQL.Where("step = ?", "FT").Find(&reports)
//fmt.Println(len(reports))
//for _, report := range reports {
// test_data.SaveFT(report)
//}
//var fileHandles []*model.FileHandled
//global.PostGreSQL.Where("product = ? AND lot = ? AND wafer_id IN ?", "TP2202B", "EP5NYR.1", []string{"01", "02", "04", "06"}).
// Find(&fileHandles)
//for _, fileHandle := range fileHandles {
// var report *model.Report
// global.PostGreSQL.Where("product = ? AND lot = ? AND wafer_id = ?", "TP2202B", "EP5NYR.1", fileHandle.WaferID).Find(&report)
// test_data.SaveCP(fileHandle.Product, fileHandle.Lot, fileHandle.WaferID, report)
//}
initialization.RunServer()
}

48
middleware/casbin.go Normal file
View File

@ -0,0 +1,48 @@
package middleware
import (
"github.com/gin-gonic/gin"
"testData/global"
"testData/model"
"testData/model/response"
"testData/service"
"testData/utils"
)
func CasbinHandler() gin.HandlerFunc {
return func(c *gin.Context) {
user, _ := utils.JWTGetUser(c)
// 获取请求的PATH
obj := c.Request.URL.Path
// 获取请求方法
act := c.Request.Method
// 获取用户的角色
//sub := user.RoleId
var isExist bool
var u *model.User
global.BaseDB.Where("user_id = ?", user.UserId).Preload("Role").Find(&u)
for _, v := range u.Role {
sub := v.RoleId
e := service.CasbinServiceApp.Casbin()
// 判断策略中是否存在
success, _ := e.Enforce(sub, obj, act)
if success {
isExist = true
}
}
if isExist {
c.Next()
} else {
response.FailWithDetailed(gin.H{}, "权限不足", c)
c.Abort()
return
}
//if success {
// c.Next()
//} else {
// response.FailWithDetailed(gin.H{}, "权限不足", c)
// c.Abort()
// return
//}
}
}

25
middleware/cors.go Normal file
View File

@ -0,0 +1,25 @@
package middleware
import (
"github.com/gin-gonic/gin"
"net/http"
)
// Cors 处理跨域请求,支持options访问
func Cors() gin.HandlerFunc {
return func(c *gin.Context) {
c.Header("Access-Control-Allow-Origin", c.Request.Header.Get("Origin"))
c.Header("Access-Control-Allow-Headers", "Content-Type, AccessToken, X-CSRF-Token, Authorization, Token, X-Token, X-User-Id, Origin, X-Requested-With")
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT")
//c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
c.Header("Access-Control-Expose-Headers", c.GetHeader("Access-Control-Request-Headers"))
c.Header("Access-Control-Allow-Credentials", "true")
c.Writer.Header().Set("Access-Control-Max-Age", "3600")
// 放行所有OPTIONS方法
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(http.StatusNoContent)
}
// 处理请求
c.Next()
}
}

39
middleware/jwt.go Normal file
View File

@ -0,0 +1,39 @@
package middleware
import (
"github.com/gin-gonic/gin"
"testData/model/response"
"testData/repository"
"testData/utils"
)
func JWTAuth() gin.HandlerFunc {
return func(c *gin.Context) {
token := c.Request.Header.Get("x-token")
if token == "" {
response.FailWithDetailed(gin.H{"reload": true}, "未登录或非法访问", c)
c.Abort()
return
}
j := utils.NewJWT()
// parseToken 解析token包含的信息
claims, err := j.ParseToken(token)
if err != nil {
if err == utils.TokenExpired {
response.FailWithDetailed(gin.H{"reload": true}, "授权已过期", c)
c.Abort()
return
}
response.FailWithDetailed(gin.H{"reload": true}, err.Error(), c)
c.Abort()
return
}
if err, u := repository.GetUserByID(claims.ID); err != nil {
response.FailWithDetailed(gin.H{"reload": true}, err.Error(), c)
c.Abort()
} else {
c.Set("claims", u)
c.Next()
}
}
}

30
middleware/log.go Normal file
View File

@ -0,0 +1,30 @@
package middleware
import (
"github.com/gin-gonic/gin"
"testData/global"
"testData/model"
"time"
)
func Log() gin.HandlerFunc {
return func(c *gin.Context) {
startTime := time.Now()
c.Next()
statusCode := c.Writer.Status()
endTime := time.Now()
u, _ := c.Get("claims")
user := &model.User{}
if u != nil {
user = u.(*model.User)
} else {
user.Username = "未登录"
}
latencyTime := endTime.Sub(startTime)
reqMethod := c.Request.Method
reqUri := c.Request.RequestURI
clientIp := c.ClientIP()
global.Log.Infof("| %15s | %3d | %15s | %6s | %s | %s",
clientIp, statusCode, latencyTime, reqMethod, user.Username, reqUri)
}
}

12
middleware/recovery.go Normal file
View File

@ -0,0 +1,12 @@
package middleware
import (
"github.com/gin-gonic/gin"
"testData/global"
)
func Recovery() func(c *gin.Context) {
return gin.CustomRecovery(func(c *gin.Context, err interface{}) {
global.Log.Errorf("%s", err)
})
}

21
model/api.go Normal file
View File

@ -0,0 +1,21 @@
package model
import (
"gorm.io/gorm"
"time"
)
type Api struct {
ID uint `gorm:"primaryKey" json:"id"`
Path string `json:"path" gorm:"comment:api路径"` // api路径
Description string `json:"description" gorm:"comment:api描述"` // api描述
ApiGroup string `json:"group" gorm:"comment:api分组"` // api分组
Method string `json:"method" gorm:"default:POST;comment:方法"` // 方法:POST|GET|PUT|DELETE
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"-"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}
func (Api) TableName() string {
return "api"
}

9
model/casbin.go Normal file
View File

@ -0,0 +1,9 @@
package model
type Casbin struct {
Ptype string `json:"ptype" gorm:"column:ptype"`
AuthorityId string `json:"role" gorm:"column:v0"`
Path string `json:"path" gorm:"column:v1"`
Method string `json:"method" gorm:"column:v2"`
ApiId string `json:"api_id" gorm:"column:v3"`
}

44
model/chart.go Normal file
View File

@ -0,0 +1,44 @@
package model
type Histogram struct {
Field string
Average float64
StandardDeviation float64
N float64
Max string
Min string
X []string
Y []string
}
type Scatter struct {
Field string
Datas [][]string
}
type ScatterLimit struct {
Max string
Min string
}
type Pie struct {
Name string `json:"name"`
Value int `json:"value"`
}
type Line struct {
Name string
X []string
Y []string
}
type CPMap struct {
X string
Y string
Field []Field
}
type Field struct {
Name string
Value string
}

5
model/company.go Normal file
View File

@ -0,0 +1,5 @@
package model
type Company struct {
ID int64 `json:"id" gorm:"primaryKey"`
}

25
model/department.go Normal file
View File

@ -0,0 +1,25 @@
package model
import (
"gorm.io/gorm"
"time"
)
type Departments struct {
ID uint `gorm:"primaryKey" json:"id"`
DepartmentId string `json:"department_id" gorm:"index"`
Name string `json:"name"`
Description string `json:"description" gorm:"type:text"`
ParentId uint `json:"parent_id"`
UUID string `json:"uuid"`
DN string `json:"dn"`
TencentID int64 `json:"tencent_id"`
Children []*Departments `json:"children" gorm:"foreignkey:ParentId"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"-"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}
func (Departments) TableName() string {
return "departments"
}

129
model/erp.go Normal file
View File

@ -0,0 +1,129 @@
package model
import "time"
type TcSfcFile struct {
TcSfc01 string `json:"tc_sfc01"` // PBI
TcSfc02 time.Time `json:"tc_sfc02"` // 下单日期
TcSfc04 string `json:"tc_sfc04"` // 厂商编号
PmcFile PmcFile `gorm:"foreignKey:Pmc01;references:TcSfc04"`
TcSfc08 string `json:"tc_sfc08"` // 加工类型
TcSfdFile []TcSfdFile `gorm:"foreignKey:TcSfd01;references:TcSfc01"`
TcSfeFile []TcSfeFile `gorm:"foreignKey:TcSfe01;references:TcSfc01"`
}
func (TcSfcFile) TableName() string { return "tc_sfc_file" }
type TcSfdFile struct {
TcSfd01 string `json:"tc_sfd01"` // PBI
TcSfd02 int `json:"tc_sfd02"` // 回货项次
TcSfd03 string `json:"tc_sfd03"` // 料号
ImaFile ImaFile `gorm:"foreignKey:Ima01;references:TcSfd03"`
TcSfd05 float64 `json:"tc_sfd05"` // 数量
TcSfd06 string `json:"tc_sfd06"` // 批号
TcSfd13 string `json:"tc_sfd13"` // 委外工单号
SfbFile SfbFile `gorm:"foreignKey:Sfb01;references:TcSfd13"`
//RvbFile []RvbFile `gorm:"foreignKey:Rvb34;references:TcSfd13"`
TcSfd14 string `json:"tc_sfd14"` // 委外采购单号
RvaFile []RvaFile `gorm:"foreignKey:Rva02;references:TcSfd14"`
TcSfdUd02 string `json:"tc_sfdud02" gorm:"column:TC_SFDUD02"` // 丝印
}
func (TcSfdFile) TableName() string { return "tc_sfd_file" }
type TcSfeFile struct {
TcSfe01 string `json:"tc_sfe01"` // PBI
TcSfe02 int `json:"tc_sfe02"` // 回货项次
TcSfe04 string `json:"tc_sfe04"` // 料号
ImaFile ImaFile `gorm:"foreignKey:Ima01;references:TcSfe04"`
TcSfe10 string `json:"tc_sfe10"` // 晶圆批号
TcSfe15 string `json:"tc_sfe15"` // 片号
TcSfe17 string `json:"tc_sfe17"` // 是否主芯
}
func (TcSfeFile) TableName() string { return "tc_sfe_file" }
type ImaFile struct {
Ima01 string `json:"ima01"` // 料号
Ima02 string `json:"ima02"` // 型号
Ima021 string `json:"ima021"` // 规格
}
func (ImaFile) TableName() string { return "ima_file" }
type PmmFile struct {
Pmm01 string `json:"pmm01"` // 采购单号
Pmm04 time.Time `json:"pmm04"` // 采购日期
Pmm09 string `json:"pmm09"` // 供应厂商编号
PmnFile PmnFile `gorm:"foreignKey:Pmn01;references:Pmm01"`
PmcFile PmcFile `gorm:"foreignKey:Pmc01;references:Pmm09"`
RvbFile []RvbFile `gorm:"foreignKey:Rvb04;references:Pmm01"`
}
func (PmmFile) TableName() string { return "pmm_file" }
type PmnFile struct {
Pmn01 string `json:"pmn01"`
Pmn04 string `json:"pmn04"` // 料件编号
ImaFile ImaFile `gorm:"foreignKey:Ima01;references:Pmn04"`
Pmn20 float64 `json:"pmn20"` // 采购量
Pmn53 float64 `json:"pmn53"` // 已交量
Pmn82 string `json:"pmn82"` // 采购数量
Pmn041 string `json:"pmn041"` // 品名规格
}
func (PmnFile) TableName() string { return "pmn_file" }
type RvaFile struct {
Rva01 string `json:"rva01"` // 收货单号
IddFile []IddFile `gorm:"foreignKey:Idd10;references:Rva01"`
Rva02 string `json:"rva02"` // 采购单号
Rva06 string `json:"rva06"`
}
func (RvaFile) TableName() string { return "rva_file" }
type RvvFile struct {
Rvv36 string `json:"rvv36"` // 采购单号
Rvv84 string `json:"rvv84"` // 数量
RvaFile []RvaFile `gorm:"foreignKey:Rva02;references:Rvv36"`
}
func (RvvFile) TableName() string { return "rvv_file" }
type PmcFile struct {
Pmc01 string `json:"pmc01"` // 厂商编号
Pmc03 string `json:"pmc03"` // 厂商名称
}
func (PmcFile) TableName() string { return "pmc_file" }
type RvbFile struct {
Rvb01 string `json:"rvb01"` // 收货单号
//IddFile IddFile `gorm:"foreignKey:Idd10;references:Rvb01"`
Rvb04 string `json:"rvb04"` // 采购单号
Rvb12 time.Time `json:"rvb12"` // 收货日期
Rvb29 float64 `json:"rvb29"` // 退货量
Rvb30 float64 `json:"rvb30"` // 入库数
Rvb34 string `json:"rvb34"` // PBI
Rvb38 string `json:"rvb38"` // 批号
}
func (RvbFile) TableName() string { return "rvb_file" }
type IddFile struct {
Idd01 string `json:"idd01"` // 料号
Idd04 string `json:"idd04"` // 批号
Idd06 string `json:"idd06"` // 良品/不良品
Idd10 string `json:"idd10"` // 收货单号
Idd13 float64 `json:"idd13"` // 数量
}
func (IddFile) TableName() string { return "idd_file" }
type SfbFile struct {
Sfb01 string `json:"sfb01"`
Sfb04 string `json:"sfb04"`
}
func (SfbFile) TableName() string { return "sfb_file" }

95
model/excel.go Normal file
View File

@ -0,0 +1,95 @@
package model
import (
"gorm.io/gorm"
"time"
)
type FileText struct {
ID uint `gorm:"primaryKey" json:"id"`
Name string `json:"name" gorm:"comment:文件名;index"`
Path string `json:"path" gorm:"comment:文件路径;index"`
Size string `json:"size" gorm:"comment:文件大小"`
ModTime int64 `json:"modtime" gorm:"comment:文件修改时间"`
IsCsv bool `json:"isCsv" gorm:"comment:是否为csv文件"`
Sha1 string `json:"sha1" gorm:"comment:文件sha1值"`
Factory string `json:"factory" gorm:"comment:厂商"`
Processed bool `json:"processed" gorm:"comment:是否已处理"`
ProductName string `json:"product_name"`
Lot string `json:"lot" gorm:"comment:批次号"`
SubBatch string `json:"sub_batch" gorm:"子批次"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"-"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}
func (FileText) TableName() string {
return "file_text"
}
type FileCompress struct {
ID uint `gorm:"primaryKey" json:"id"`
Name string `json:"name" gorm:"comment:文件名;index"`
Path string `json:"path" gorm:"comment:文件路径;index"`
Size string `json:"size" gorm:"comment:文件大小"`
ModTime int64 `json:"modtime" gorm:"comment:文件修改时间"`
NewName string `json:"newName" gorm:"comment:重命名后的文件名"`
NewPath string `json:"newPath" gorm:"comment:重命名后的文件路径"`
Decompressed bool `json:"decompressed" gorm:"comment:是否已解压"`
Unzip string `json:"unzip" gorm:"comment:解压后的文件路径"`
Sha1 string `json:"sha1" gorm:"comment:文件sha1值"`
Factory string `json:"factory" gorm:"comment:厂商"`
ProductName string `json:"product_name"`
Lot string `json:"lot" gorm:"comment:批次号"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"-"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}
func (FileCompress) TableName() string {
return "file_compress"
}
type FileHandled struct {
ID int `json:"id" gorm:"primary_key"`
Name string `json:"name"`
Path string `json:"path"`
Size string `json:"size"`
Factory string `json:"factory"` // 厂商
PBI string `json:"pbi" comment:"PBI"`
Product string `json:"product"` // 产品型号
Step string `json:"step"` // 测试工序
Lot string `json:"lot"` // 批号
SubBatch string `json:"sub_batch"` // 子批
TestMachineModel string `json:"test_machine_model"` // 测试机台型号
TestMachine string `json:"test_machine"` // 测试机台
TestProgram string `json:"test_program"` // 测试程序
WaferID string `json:"wafer_id"`
BeginningTime string `json:"beginning_time"` // 开始时间
EndingTime string `json:"ending_time"` // 结束时间
SbinHbin string `json:"sbin_hbin"` // Sbin/Hbin
TitleInfo string `json:"title_info"` // 参数信息
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"-"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
}
type DataInfo struct {
Unit string
LimitL string
LimitU string
}
type BinInfo struct {
//Number string
Name string
HBin string
}
type CQ774P struct {
ID int `json:"id" gorm:"primary_key"`
Data string `json:"data" gorm:"type:text"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"-"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
}

26
model/factory.go Normal file
View File

@ -0,0 +1,26 @@
package model
import (
"gorm.io/gorm"
"time"
)
type Factory struct {
ID int64 `json:"id" gorm:"primaryKey"`
Name string `json:"name"`
Email string `json:"email"`
Keyword string `json:"keyword"`
FactoryExcel []FactoryExcel `json:"factory_excel" gorm:"foreignKey:FactoryID;references:ID"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"-"`
DeletedAt *gorm.DeletedAt `json:"-" gorm:"index"`
}
type FactoryExcel struct {
ID int64 `json:"id" gorm:"primaryKey"`
ExcelTitle string `json:"excel_title"`
Title string `json:"title"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"-"`
DeletedAt *gorm.DeletedAt `json:"-" gorm:"index"`
}

38
model/menu.go Normal file
View File

@ -0,0 +1,38 @@
package model
import (
"gorm.io/gorm"
"time"
)
type Menu struct {
ID uint `json:"id" gorm:"primary_key"`
Name string `json:"name"` // 路由名称 英文名
Title string `json:"title"` // 菜单名称
GroupName string `json:"group_name"` // 项目名称
Role []*Role `json:"role" gorm:"many2many:role_menus"`
//ParentID uint `json:"parent_id"` // 父菜单ID
//Sort uint `json:"sort"`
//Children []*Menu `json:"children" gorm:"foreignkey:ParentID"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"-"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
}
type MenuForLeader struct {
GroupName string `json:"group_name"` // 项目名称
Menus []*Menus `json:"menus"` // 菜单
}
type Menus struct {
ID uint `json:"id"`
Name string `json:"name"` // 路由名称
Title string `json:"title"` // 菜单名称
}
/*
resp:
{
roles:["name", "name"] // Menu.Name
}
*/

22
model/position.go Normal file
View File

@ -0,0 +1,22 @@
package model
import (
"gorm.io/gorm"
"time"
)
type Position struct {
ID uint `gorm:"primaryKey" json:"id"`
PositionId string `json:"position_id" gorm:"index"`
Name string `json:"name"`
Description string `json:"description" gorm:"type:text"`
ParentId uint `json:"parent_id"`
Children []*Position `json:"children" gorm:"foreignkey:ParentId"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"-"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}
func (Position) TableName() string {
return "positions"
}

128
model/report.go Normal file
View File

@ -0,0 +1,128 @@
package model
import (
"gorm.io/gorm"
"time"
)
type Report struct {
ID int64 `json:"id" gorm:"primaryKey"`
Product string `json:"product"` // 成品型号
Lot string `json:"lot"` //晶圆批次
Factory string `json:"factory"` // 测试厂
TestMachine string `json:"test_machine"` // 测试机台
TestProgram string `json:"test_program"` // 测试程序
PBI string `json:"pbi"` // PBI
SubBatch string `json:"sub_batch"` // 子批次
OrderDate string `json:"order_date"` // 下单日期
Seal string `json:"seal"` // 丝印
TestQuantity string `json:"test_quantity"` // 测试数量
FirstPassQuantity string `json:"first_pass_quantity"` // 初测良品数量
FirstPassProbability string `json:"first_pass_probability"` // 初测良率
PassQuantity string `json:"pass_quantity"` // 良品数量(包括回收数据)
PassProbability string `json:"pass_probability"` // 良率(包括回收数据)
WaferID string `json:"wafer_id"` // 片号
TestTime string `json:"test_time"` // 测试时间
Step string `json:"step"` // 工序
StackingMaterials bool `json:"stacking_materials"` // 是否叠料
BinFail []BinFail `json:"bin_fail" gorm:"foreignKey:ReportID"` // 硬件和软件Bin的不良数量
Site []ReportSites `json:"site" gorm:"foreignKey:ReportID"` // Site测试情况
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"-"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}
type FinalReport struct {
ID int64 `json:"id" gorm:"primaryKey"`
Product string `json:"product"`
Lot string `json:"lot"`
PBI string `json:"pbi"`
Step string `json:"step"`
ReportTestQuantity string `json:"report_test_quantity"` // 报表测试数量
ReportPassQuantity string `json:"report_pass_quantity"` // 报表良品数量
ReportPassProbability string `json:"report_pass_probability"` // 报表良率
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"-"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}
type ReportSites struct {
ID int64 `json:"id" gorm:"primaryKey"`
ReportID int64 `json:"report_id"`
Site string `json:"site"` // Site
TestQuantity string `json:"test_quantity"` // 测试总数
PassQuantity string `json:"pass_quantity"` // 测试良品数
PassProbability string `json:"pass_probability"` // 良率
BinFail []BinFail `json:"bin_fail" gorm:"foreignKey:ReportSiteID"` // 硬件和软件Bin的不良数量
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"-"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}
type BinFail struct {
ID int64 `json:"id" gorm:"primaryKey"`
ReportID int64 `json:"report_id"`
ReportSiteID int64 `json:"report_site_id"`
HardBin string `json:"hard_bin"` // 硬件Bin名称
SoftBin string `json:"soft_bin"` // 软件Bin名称
Quantity string `json:"quantity"` // 数量
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"-"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}
type ReportList struct {
ID int64 `json:"id" gorm:"primaryKey"`
Product string `json:"product"` // 成品型号
Lot string `json:"lot"` //晶圆批次
Factory string `json:"factory"` // 测试厂
TestMachine string `json:"test_machine"` // 测试机台
TestProgram string `json:"test_program"` // 测试程序
PBI string `json:"pbi"` // PBI
SubBatch string `json:"sub_batch"` // 子批次
OrderDate string `json:"order_date"` // 下单日期
Seal string `json:"seal"` // 丝印
TestQuantity string `json:"test_quantity"` // 测试数量
FirstPassQuantity string `json:"first_pass_quantity"` // 初测良品数量
FirstPassProbability string `json:"first_pass_probability"` // 初测良率
PassQuantity string `json:"pass_quantity"` // 良品数量(包括回收数据)
PassProbability string `json:"pass_probability"` // 良率(包括回收数据)
ReportTestQuantity string `json:"report_test_quantity"` // 报表测试数量
ReportPassQuantity string `json:"report_pass_quantity"` // 报表良品数量
ReportPassProbability string `json:"report_pass_probability"` // 报表良率
WaferID string `json:"wafer_id"` // 片号
TestTime string `json:"test_time"` // 测试时间
Step string `json:"step"` // 工序
TestQuantityDiff string `json:"test_quantity_diff"` // 测试数量差异
TestQuantityDiffLabel bool `json:"test_quantity_diff_label"`
PassQuantityDiff string `json:"pass_quantity_diff"` // 良品数量差异
PassQuantityDiffLabel bool `json:"pass_quantity_diff_label"`
ReturnProbability string `json:"return_probability"` // 回收率
ReturnProbabilityLabel bool `json:"return_probability_label"`
StackingMaterials bool `json:"stacking_materials"` // 是否叠料
SoftBinFailMap map[string]float64 `json:"soft_bin_fail_map"` // 软件Bin的不良数量
HardBinFailMap map[string]float64 `json:"hard_bin_fail_map"` // 硬件Bin的不良数量
SoftBinFail []*ReportBinFail `json:"soft_bin_fail"` // 软件Bin的不良数量
HardBinFail []*ReportBinFail `json:"hard_bin_fail"` // 硬件Bin的不良数量
Site []*ReportListSites `json:"site"` // Site测试情况
}
type ReportListSites struct {
ID int64 `json:"id" gorm:"primaryKey"`
ReportID int64 `json:"report_id"`
Site string `json:"site"` // Site
TestQuantity string `json:"test_quantity"` // 测试总数
PassQuantity string `json:"pass_quantity"` // 测试良品数
PassProbability string `json:"pass_probability"` // 良率
SoftBinFailMap map[string]float64 `json:"soft_bin_fail_map"` // 软件Bin的不良数量
HardBinFailMap map[string]float64 `json:"hard_bin_fail_map"` // 硬件Bin的不良数量
SoftBinFail []*ReportBinFail `json:"soft_bin_fail"` // 软件Bin的不良数量
HardBinFail []*ReportBinFail `json:"hard_bin_fail"` // 硬件Bin的不良数量
}
type ReportBinFail struct {
Bin string `json:"bin"`
Quantity float64 `json:"quantity"`
Proportion string `json:"proportion"`
ReportProportion string `json:"report_proportion"`
}

43
model/report.list.go Normal file
View File

@ -0,0 +1,43 @@
package model
type WaferList struct {
OrderDate string `json:"order_date"` // 下单日期
PBI string `json:"pbi"` // 订单号
Product string `json:"product"` // 晶圆型号
Factory string `json:"factory"` // 晶圆厂
WaferSize string `json:"wafer_size"` // 晶圆尺寸
Quantity float64 `json:"quantity"` // 投片数量
OnlineQuantity float64 `json:"online_quantity"` // 在线数量
ReturnDate string `json:"return_date"` // 回货日期
Lot string `json:"lot"` // 批号
ReturnQuantity float64 `json:"return_quantity"` // 回货数量
}
type ABList struct {
OrderDate string `json:"order_date"` // 下单日期
PBI string `json:"pbi"` // 订单号
OutsourcingPBI string `json:"outsourcing_pbi"` // 委外工单号
Product string `json:"product"` // 成品型号
WaferProduct string `json:"wafer_product"` // 晶圆型号
Package string `json:"package"` // 封装
Factory string `json:"factory"` // 封装厂
Lot string `json:"lot"` // 批号
Seal string `json:"seal"` // 丝印
WaferID string `json:"wafer_id"` // 片号
Quantity float64 `json:"quantity"` // 订单数量
OnlineQuantity float64 `json:"online_quantity"` // 在线数量
IsFinish string `json:"is_finish"` // 是否已完成
PassProbability string `json:"pass_probability"` // 良率
StockOutQuantity float64 `json:"stock_out_quantity"` // 出库数
StockInQuantity float64 `json:"stock_in_quantity"` // 入库数
FailQuantity float64 `json:"fail_quantity"` // 封装不良品
ABWaferList []*ABWaferList `json:"ab_wafer_list"`
}
type ABWaferList struct {
Material string `json:"material"` // 料号
Product string `json:"product"` // 品名
Specification string `json:"specification"` // 规格
Lot string `json:"lot"` // 批号
WaferID string `json:"wafer_id"` // 片号
}

View File

@ -0,0 +1,54 @@
package response
import (
"github.com/gin-gonic/gin"
"net/http"
)
type Response struct {
Code int `json:"code"`
Data interface{} `json:"data"`
Msg string `json:"msg"`
}
const (
ERROR = 7
SUCCESS = 0
)
func Result(code int, data interface{}, msg string, c *gin.Context) {
// 开始时间
c.JSON(http.StatusOK, Response{
code,
data,
msg,
})
}
func Ok(c *gin.Context) {
Result(SUCCESS, map[string]interface{}{}, "操作成功", c)
}
func OkWithMessage(message string, c *gin.Context) {
Result(SUCCESS, map[string]interface{}{}, message, c)
}
func OkWithData(data interface{}, c *gin.Context) {
Result(SUCCESS, data, "操作成功", c)
}
func OkWithDetailed(data interface{}, message string, c *gin.Context) {
Result(SUCCESS, data, message, c)
}
func Fail(c *gin.Context) {
Result(ERROR, map[string]interface{}{}, "操作失败", c)
}
func FailWithMessage(message string, c *gin.Context) {
Result(ERROR, map[string]interface{}{}, message, c)
}
func FailWithDetailed(data interface{}, message string, c *gin.Context) {
Result(ERROR, data, message, c)
}

23
model/role.go Normal file
View File

@ -0,0 +1,23 @@
package model
import (
"gorm.io/gorm"
"time"
)
type Role struct {
ID uint `json:"id" gorm:"primary_key"`
RoleId string `json:"role_id" gorm:"index"`
Name string `json:"name"`
ParentId uint `json:"parent_id"`
Children []*Role `json:"children" gorm:"foreignkey:ParentId"`
Menu []*Menu `json:"menu" gorm:"many2many:role_menus;foreignKey:ID"`
User []*User `json:"user" gorm:"many2many:user_role;foreignkey:RoleId;references:UserId"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"-"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}
func (Role) TableName() string {
return "roles"
}

84
model/user.go Normal file
View File

@ -0,0 +1,84 @@
package model
import (
"gorm.io/gorm"
"time"
)
type User struct {
ID uint `gorm:"primaryKey" json:"id"`
Uuid string `json:"uuid" gorm:"index"`
UserId string `json:"user_id"`
Email string `json:"email" gorm:"index"`
Username string `json:"username" gorm:"index"`
LinuxName string `json:"linux_name" gorm:"index"`
Phone string `json:"phone" gorm:"index"`
//RoleId string `json:"role_id"`
//Role Role `json:"role" gorm:"foreignkey:RoleId;references:RoleId"`
Role []*Role `json:"role" gorm:"many2many:user_role;foreignkey:UserId;references:RoleId"`
DepartmentId string `json:"department_id"`
Department Departments `json:"department" gorm:"foreignkey:DepartmentId;references:DepartmentId"`
Departments []Departments `json:"departments" gorm:"many2many:user_department_relations;foreignkey:UserId;references:DepartmentId"`
PositionId string `json:"position_id"`
Position Position `json:"position" gorm:"foreignkey:PositionId;references:PositionId"`
LastLoginAt string `json:"last_login_at"`
LastLoginIp string `json:"last_login_ip"`
LastLoginAddress string `json:"last_login_address"`
Password string `json:"-"`
Gender string `json:"gender"`
Active bool `json:"active"`
IsManager bool `json:"is_manager" gorm:"default:false"`
IsRestrict bool `json:"is_restrict" gorm:"default:false"`
IpRange string `json:"ip_range"`
// 补充字段
Company string `json:"company" gorm:"comment:归属分公司"`
DefaultShell string `json:"default_shell" gorm:"用户默认shell"`
Home string `json:"home" gorm:"comment:用户home目录路径"`
Uid string `json:"uid" gorm:"comment:用户在Nis中的uid"`
Salt string `json:"-" gorm:"comment:密码盐"`
Iv string `json:"-"`
SosManager bool `json:"sos_manager" gorm:"comment:为true,默认加载到sos配置文件的admin中"`
ProjectManager bool `json:"project_manager" gorm:"comment:为true,能查看所有项目"`
CompanyManager bool `json:"company_manager" gorm:"comment:为true可管理用户,用户组"`
Groups []*Group `json:"groups" gorm:"many2many:user_group;"`
DN string `json:"dn"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"-"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}
func (User) TableName() string {
return "users"
}
type LoginRecord struct {
ID uint `gorm:"primaryKey" json:"id"`
Uuid string `json:"uuid" gorm:"index"`
Username string `json:"username"`
IP string `json:"ip"`
Address string `json:"address"`
Msg string `json:"msg"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"-"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}
func (LoginRecord) TableName() string {
return "login_Record"
}
//
// Group
/* @Description: 根据项目将项目内成员分组如TP0001S */
type Group struct {
ID uint `gorm:"primaryKey" json:"id"`
Name string `json:"name" gorm:"comment:组名"`
Users []*User `json:"users" gorm:"many2many:user_group;"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"-"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}
func (Group) TableName() string {
return "group"
}

324
repository/STS8200.go Normal file
View File

@ -0,0 +1,324 @@
package repository
import (
"bytes"
"encoding/csv"
"encoding/json"
"errors"
"github.com/extrame/xls"
"github.com/xuri/excelize/v2"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
"gorm.io/gorm"
"io/ioutil"
"log"
"os"
"path"
"path/filepath"
"strings"
"testData/global"
"testData/model"
"testData/utils"
)
func HandleSTS8200Excel(fileText *model.FileText, step string) {
rows := make([][]string, 0)
if strings.ToLower(path.Ext(fileText.Name)) == ".csv" {
csvBytes, err := ioutil.ReadFile(fileText.Path)
if err != nil {
log.Println("open err:", err)
return
}
//解决读取csv中文乱码的问题
reader := csv.NewReader(transform.NewReader(bytes.NewReader(csvBytes), simplifiedchinese.GBK.NewDecoder()))
//reader := csv.NewReader(file)
reader.FieldsPerRecord = -1
csvRows, err := reader.ReadAll()
if err != nil {
log.Println("open err:", err)
return
}
rows = csvRows
} else if strings.ToLower(path.Ext(fileText.Name)) == ".xls" {
if xlFile, err := xls.Open(fileText.Path, "utf-8"); err == nil {
//第一个sheet
sheet := xlFile.GetSheet(0)
if sheet.MaxRow != 0 {
temp := make([][]string, 0)
for i := 0; i < int(sheet.MaxRow); i++ {
row := sheet.Row(i)
if row == nil {
continue
}
data := make([]string, 0)
if row.LastCol() > 0 {
for j := 0; j < row.LastCol(); j++ {
col := row.Col(j)
data = append(data, col)
}
temp = append(temp, data)
}
}
rows = append(rows, temp...)
} else {
log.Println("open err:", err)
return
}
}
} else if strings.ToLower(path.Ext(fileText.Name)) == ".xlsx" {
xlsxFile, err := excelize.OpenFile(fileText.Path)
if err != nil {
log.Println("open err:", err)
return
}
sheetName := xlsxFile.GetSheetName(0)
rows, err = xlsxFile.GetRows(sheetName)
if err != nil {
log.Println("xlsx读取数据失败:", err)
return
}
}
details := make(map[string]string)
newExcel := make([][]string, 0)
var title []string
titleInfoMap := make(map[string]model.DataInfo)
sBinMap := make(map[string]model.BinInfo)
sbinStartIndex, sbinEndIndex := -1, -1
titleIndex, unitIndex, limitLIndex, limitUIndex, dataIndex := -1, -1, -1, -1, -1
for i := 1; i < len(rows); i++ {
if rows[i][0] == "" {
continue
}
if i == len(rows)-1 && unitIndex == -1 {
log.Println("特殊文件格式,文件路径为:", fileText.Path)
return
}
if sbinEndIndex < 0 {
if strings.Contains(rows[i][0], "SBin") {
if sbinStartIndex < 0 {
sbinStartIndex = i
}
s := rows[i][0]
if strings.Index(s, "]") != -1 {
sbinNumStartIndex := strings.Index(s, "[")
sbinNumEndIndex := strings.Index(s, "]")
var startIndex, endIndex int
for index := sbinNumEndIndex + 1; index < len(s); index++ {
if startIndex == 0 {
if s[index] != ' ' {
startIndex = index
}
} else {
if s[index] == ' ' || s[index] == '_' {
endIndex = index
break
}
}
}
sBinMap[s[sbinNumStartIndex+1:sbinNumEndIndex]] = model.BinInfo{
Name: s[startIndex:endIndex],
HBin: s[strings.LastIndex(s, " ")+1:],
}
//sBinMap[s[startIndex:endIndex]] = model.BinInfo{
// Number: s[sbinNumStartIndex+1 : sbinNumEndIndex],
// HBin: s[strings.LastIndex(s, " ")+1:],
//}
}
} else {
if sbinStartIndex > 0 {
sbinEndIndex = i
continue
}
}
}
//if len(sBinMap) == 0 {
rows[i][0] = strings.ReplaceAll(rows[i][0], "", ":")
splitIndex := strings.Index(rows[i][0], ":")
if splitIndex != -1 {
details[rows[i][0][:splitIndex]] = rows[i][0][splitIndex+1:]
}
//}
if titleIndex < 0 {
if strings.Contains(rows[i][0], "SITE_NUM") {
titleIndex = i
title = rows[i]
continue
}
} else {
if unitIndex < 0 {
if strings.Contains(rows[i][0], "Unit") {
rows[i] = append(rows[i], utils.FillData(len(rows[titleIndex])-len(rows[i]))...)
unitIndex = i
continue
}
}
if limitLIndex < 0 {
if strings.Contains(rows[i][0], "LimitL") {
rows[i] = append(rows[i], utils.FillData(len(rows[titleIndex])-len(rows[i]))...)
limitLIndex = i
continue
}
}
if limitUIndex < 0 {
if strings.Contains(rows[i][0], "LimitU") {
rows[i] = append(rows[i], utils.FillData(len(rows[titleIndex])-len(rows[i]))...)
limitUIndex = i
continue
}
}
if dataIndex < 0 && limitUIndex > 0 {
if rows[i][0] != rows[i][2] {
dataIndex = i
break
}
}
}
}
if titleIndex != -1 {
for k, v := range rows[titleIndex] {
titleInfoMap[v] = model.DataInfo{
Unit: rows[unitIndex][k],
LimitL: rows[limitLIndex][k],
LimitU: rows[limitUIndex][k],
}
}
for i := dataIndex; i < len(rows); i++ {
if len(rows[i]) < len(rows[titleIndex]) {
rows[i] = append(rows[i], utils.FillData(len(rows[titleIndex])-len(rows[i]))...)
}
newExcel = append(newExcel, rows[i])
}
} else {
log.Println("特殊文件格式,文件路径为:", fileText.Path)
return
}
if details["Test_Code"] == "" {
details["Test_Code"] = step
} else {
details["Test_Code"] = details["Test_Code"][:2]
}
strReader := transform.NewReader(bytes.NewReader([]byte(details["Device_Name"])), simplifiedchinese.GBK.NewDecoder())
product, _ := ioutil.ReadAll(strReader)
if string(product) == "" {
product = []byte(fileText.ProductName)
}
testProgram := details["Program"][strings.LastIndex(details["Program"], "\\")+1:]
sbinHbin, _ := json.Marshal(&sBinMap)
titleInfo, _ := json.Marshal(&titleInfoMap)
fileName := string(product) + "_" + fileText.Lot + "_" + details["Test_Code"] + ".csv"
var waferID string
if fileText.Factory == "saimeike" {
if step == "CP1" || step == "CP2" {
length := len(fileText.Name)
waferID = fileText.Name[length-10 : length-8]
fileName = string(product) + "_" + fileText.Lot + "_" + waferID + "_" + details["Test_Code"] + ".csv"
} else {
if strings.Index(fileText.SubBatch, "-") != strings.LastIndex(fileText.SubBatch, "-") {
fileText.SubBatch = fileText.SubBatch[:strings.LastIndex(fileText.SubBatch, "-")]
}
fileName = string(product) + "_" + fileText.Lot + "_" + fileText.SubBatch + "_" + details["Test_Code"] + ".csv"
}
} else if fileText.Factory == "xinde" {
s := strings.Split(fileText.Name, "_")
if len(s) < 5 {
log.Println("文件名格式有误,文件路径为:", fileText.Path)
return
}
waferIDStr := s[len(s)-3]
if len(waferIDStr) < 5 {
log.Println("文件名格式有误,文件路径为:", fileText.Path)
return
}
splitIndex := strings.Index(waferIDStr, "-")
if splitIndex == -1 {
log.Println("文件名格式有误,文件路径为:", fileText.Path)
return
}
waferID = waferIDStr[splitIndex+1 : splitIndex+3]
if _, ok := details["WAFER_ID"]; ok {
details["Test_Code"] = "CP"
if len(waferIDStr[:splitIndex]) < 8 {
fileText.Lot = strings.ToUpper(waferIDStr[:splitIndex])
}
fileText.SubBatch = ""
fileName = string(product) + "_" + fileText.Lot + "_" + waferID + "_" + details["Test_Code"] + ".csv"
}
} else if fileText.Factory == "qipai" {
//details["Test_Code"]
} else if fileText.Factory == "changdian" {
if details["Device_Name"] == "" {
log.Println("文件缺少产品型号信息,文件路径为:", fileText.Path)
return
}
product = []byte(details["Device_Name"])
fileName = details["Device_Name"] + "_" + fileText.Lot + "_" + fileText.SubBatch + "_" + details["Test_Code"] + ".csv"
}
//strings.ReplaceAll(fileText.Lot, ".", "-")
dirPath := filepath.Join("/testData/test/" + fileText.Factory)
utils.MakeDir(dirPath)
filePath := filepath.Join(dirPath, fileName)
var fileHandled *model.FileHandled
if _, err := os.Stat(filePath); err != nil {
if os.IsNotExist(err) {
newExcel = append([][]string{title}, newExcel...)
_, err = os.Create(filePath)
if err != nil {
log.Println("创建文件失败:", err)
return
}
if errors.Is(global.PostGreSQL.Where("name = ?", fileName).First(&fileHandled).Error, gorm.ErrRecordNotFound) {
global.PostGreSQL.Create(&model.FileHandled{
Name: fileName,
Path: filePath,
Size: "",
Product: string(product),
Factory: fileText.Factory,
Step: details["Test_Code"],
Lot: fileText.Lot,
SubBatch: fileText.SubBatch,
TestMachineModel: "STS8200",
TestMachine: details["Tester ID"],
TestProgram: testProgram,
BeginningTime: details["Beginning Time"],
EndingTime: details["Ending Time"],
SbinHbin: string(sbinHbin),
TitleInfo: string(titleInfo),
WaferID: waferID,
})
}
}
}
newCsv, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
log.Println("打开新Excel错误:", fileText.Path)
return
}
defer newCsv.Close()
writer := csv.NewWriter(newCsv)
defer writer.Flush()
err = writer.WriteAll(newExcel)
if err != nil {
log.Println("写入新Excel错误:", fileText.Path)
return
}
newFile, err := os.Stat(filePath)
if err != nil {
log.Println("获取新Excel信息:", fileText.Path)
return
}
global.PostGreSQL.Model(&fileHandled).Where("name = ?", fileName).Updates(map[string]interface{}{
"product": string(product),
"step": details["Test_Code"],
"test_machine_model": "STS8200",
"test_machine": details["Tester ID"],
"test_program": testProgram,
"beginning_time": details["Beginning Time"],
"ending_time": details["Ending Time"],
"sbin_hbin": string(sbinHbin),
"title_info": string(titleInfo),
"size": utils.FormatFileSize(float64(newFile.Size())),
})
}

286
repository/TQT601.go Normal file
View File

@ -0,0 +1,286 @@
package repository
import (
"encoding/csv"
"encoding/json"
"errors"
"github.com/extrame/xls"
"gorm.io/gorm"
"log"
"os"
"path/filepath"
"strings"
"testData/global"
"testData/model"
"testData/utils"
)
func HandlerTQT601Excel(fileText *model.FileText, step string) {
var isXls bool
file, err := os.Open(fileText.Path)
if err != nil {
log.Println("open err:", err)
return
}
reader := csv.NewReader(file)
reader.FieldsPerRecord = -1
reader.LazyQuotes = true
rows, err := reader.ReadAll()
if err != nil {
if xlFile, err := xls.Open(fileText.Path, "utf-8"); err == nil {
//第一个sheet
sheet := xlFile.GetSheet(0)
if sheet.MaxRow != 0 {
temp := make([][]string, sheet.MaxRow)
for i := 0; i < int(sheet.MaxRow); i++ {
row := sheet.Row(i)
data := make([]string, 0)
if row.LastCol() > 0 {
for j := 0; j < row.LastCol(); j++ {
col := row.Col(j)
data = append(data, col)
}
temp[i] = data
}
}
rows = append(rows, temp...)
}
isXls = true
} else {
log.Println("open err:", err)
return
}
}
newExcel := make([][]string, 0)
var title []string
details := make(map[string]string)
titleInfoMap := make(map[string]model.DataInfo)
index, titleIndex, unitIndex, limitLIndex, limitUIndex := 0, -1, -1, -1, -1
if len(rows) == 0 {
log.Println(fileText.Path, "文件为空")
return
}
for {
if index == len(rows)-1 {
break
}
if !isXls {
rows[index][0], err = utils.DecodeToUnicode(rows[index][0])
if err != nil {
return
}
rows[index] = strings.Split(rows[index][0], "\t")
}
if len(titleInfoMap) == 0 {
if strings.Contains(rows[index][0], "=") {
splitIndex := strings.Index(rows[index][0], "=")
details[rows[index][0][:splitIndex]] = rows[index][0][splitIndex+1:]
}
if titleIndex < 0 && len(rows[index]) > 1 {
if strings.Contains(rows[index][1], "Test") {
titleIndex = index
index++
continue
}
} else {
if limitUIndex < 0 && len(rows[index]) > 1 {
if strings.Contains(rows[index][1], "High_limits") {
limitUIndex = index
index++
continue
}
}
if limitLIndex < 0 && len(rows[index]) > 1 {
if strings.Contains(rows[index][1], "Low_limits") {
limitLIndex = index
index++
continue
}
}
if unitIndex < 0 && len(rows[index]) > 1 {
if strings.Contains(rows[index][1], "Units") {
unitIndex = index
rows[limitUIndex] = append(rows[limitUIndex], utils.FillData(len(rows[titleIndex])-len(rows[limitUIndex]))...)
rows[limitLIndex] = append(rows[limitLIndex], utils.FillData(len(rows[titleIndex])-len(rows[limitLIndex]))...)
rows[unitIndex] = append(rows[unitIndex], utils.FillData(len(rows[titleIndex])-len(rows[unitIndex]))...)
title = append(title, []string{"DieID", "SBIN"}...)
for rowIndex := 2; rowIndex < len(rows[index]); rowIndex++ {
title = append(title, rows[titleIndex][rowIndex])
titleInfoMap[rows[titleIndex][rowIndex]] = model.DataInfo{
Unit: rows[unitIndex][rowIndex],
LimitL: rows[limitLIndex][rowIndex],
LimitU: rows[limitUIndex][rowIndex],
}
}
//newExcel = append(newExcel, title)
index++
continue
}
}
}
} else {
if len(rows[index]) > 1 {
if strings.Contains(rows[index][1], "Test") || strings.Contains(rows[index][1], "High_limits") ||
strings.Contains(rows[index][1], "Low_limits") || strings.Contains(rows[index][1], "Units") {
index++
continue
}
if !strings.Contains(rows[index][1], "SBIN") {
rows[index] = append(rows[index], utils.FillData(len(rows[titleIndex])-len(rows[index]))...)
newExcel = append(newExcel, rows[index])
}
}
}
index++
}
fileText.Name = strings.ReplaceAll(fileText.Name, "__", "_")
if details["Test_Code"] == "" {
details["Test_Code"] = step
} else {
details["Test_Code"] = details["Test_Code"][:2]
}
pointLastIndex := strings.LastIndex(fileText.Name, ".")
pointIndex := pointLastIndex - 1
for {
if pointIndex == 0 {
log.Println("文件名格式错误:", fileText.Path)
return
}
if fileText.Name[pointIndex] == '.' {
break
}
pointIndex--
}
if pointIndex != pointLastIndex {
start, end := pointIndex, pointIndex+2
//for {
// if fileText.Name[end] == '_' {
// break
// }
// end++
// if end > pointLastIndex {
// fmt.Println("文件名格式错误:", fileText.Path)
// return
// }
//}
for {
if fileText.Name[start] == '_' {
break
}
start--
if start < 0 {
log.Println("文件名格式错误:", fileText.Path)
return
}
}
for i := 2; i < start; i++ {
if details["Test_Code"] == "FT" {
if fileText.Name[i-2:i] == "FT" {
for {
if fileText.Name[i] == '_' {
break
}
i++
}
if i > start-1 {
log.Println("文件名格式错误:", fileText.Path)
return
}
details["product"] = fileText.Name[i+1 : start]
break
}
} else if details["Test_Code"] == "RT" {
if fileText.Name[i-2:i] == "RT" {
for {
if fileText.Name[i] == '_' {
break
}
i++
}
details["product"] = fileText.Name[i+1 : start]
break
}
}
}
details["lot"] = fileText.Name[start+1 : end]
}
testProgram := details["TestProgram"]
fileName := details["product"] + "_" + details["lot"] + "_" + details["Test_Code"] + ".csv"
utils.MakeDir("/testData/test")
filePath := filepath.Join("/testData/test", fileName)
titleInfo, _ := json.Marshal(&titleInfoMap)
var fileHandled *model.FileHandled
if _, err = os.Stat(filePath); err != nil {
if os.IsNotExist(err) {
newExcel = append([][]string{title}, newExcel...)
_, err = os.Create(filePath)
if err != nil {
log.Println("创建文件失败:", err)
return
}
if errors.Is(global.PostGreSQL.Where("name = ?", fileName).First(&fileHandled).Error, gorm.ErrRecordNotFound) {
global.PostGreSQL.Create(&model.FileHandled{
Name: fileName,
Path: filePath,
Size: "",
Factory: fileText.Factory,
Product: details["product"],
Step: details["Test_Code"],
Lot: details["lot"],
TestMachineModel: "TQT601",
TestMachine: details["TesterNO."],
TestProgram: testProgram,
BeginningTime: details["Beginning Time"],
EndingTime: details["Ending Time"],
TitleInfo: string(titleInfo),
})
}
}
}
newCsv, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
log.Println("打开新Excel错误:", err)
return
}
defer newCsv.Close()
global.PostGreSQL.Where("name = ?", fileName).First(&fileHandled)
writer := csv.NewWriter(newCsv)
defer writer.Flush()
err = writer.WriteAll(newExcel)
if err != nil {
log.Println("写入新Excel错误:", err)
return
}
newFile, err := os.Stat(filePath)
if err != nil {
log.Println("获取新Excel信息:", err)
return
}
if fileHandled.TestMachine != "" {
details["TesterNO."] = fileHandled.TestMachine
}
if fileHandled.TestProgram != "" {
testProgram = fileHandled.TestProgram
}
if fileHandled.BeginningTime != "" {
details["Beginning Time"] = fileHandled.BeginningTime
}
if fileHandled.EndingTime != "" {
details["Ending Time"] = fileHandled.EndingTime
}
if fileHandled.TitleInfo != "" {
titleInfo = []byte(fileHandled.TitleInfo)
}
global.PostGreSQL.Where("name = ?", fileName).Model(&fileHandled).Updates(map[string]interface{}{
"product": details["product"],
"step": details["Test_Code"],
"test_machine_model": "TQT601",
"test_machine": details["TesterNO."],
"test_program": testProgram,
"beginning_time": details["Beginning Time"],
"ending_time": details["Ending Time"],
"title_info": string(titleInfo),
"size": utils.FormatFileSize(float64(newFile.Size())),
})
}

40
repository/changdian.go Normal file
View File

@ -0,0 +1,40 @@
package repository
import (
"log"
"os"
"path"
"strings"
"testData/global"
"testData/model"
)
// ChangDian 长电
func ChangDian() {
var fileTexts []*model.FileText
global.PostGreSQL.
Where("factory = ?", "changdian").
Where("name LIKE ? OR name LIKE ?", "%FT%", "%RT%").Find(&fileTexts)
for _, fileText := range fileTexts {
if path.Ext(fileText.Name) == ".xls" {
continue
}
if strings.Contains(fileText.Name, "FT_MT") || strings.Contains(fileText.Name, "FT_EQC") ||
strings.Contains(fileText.Name, "FT_GU") || strings.Contains(fileText.Name, "FT_VT") ||
strings.Contains(fileText.Name, "FT_ET") {
continue
}
file, err := os.Open(fileText.Path)
if err != nil {
log.Println(err)
}
var step string
if strings.Contains(fileText.Name, "RT") {
step = "RT"
} else {
step = "FT"
}
HandleSTS8200Excel(fileText, step)
file.Close()
}
}

25
repository/chengte.go Normal file
View File

@ -0,0 +1,25 @@
package repository
import (
"strings"
"testData/global"
"testData/model"
)
// ChengTe 诚特
func ChengTe() {
var fileTexts []*model.FileText
global.PostGreSQL.Debug().
Where("factory = ?", "chengte").
Where("name LIKE ? AND name NOT LIKE ? AND name NOT LIKE ? AND name NOT LIKE ? AND name NOT LIKE ?",
"%FT%", "%FT_LV%", "%FT_EQC%", "%FT_QC%", "%FT_NT%").Find(&fileTexts)
for _, fileText := range fileTexts {
var step string
if strings.Contains(fileText.Name, "RT") {
step = "RT"
} else {
step = "FT"
}
HandlerTQT601Excel(fileText, step)
}
}

38
repository/csv.go Normal file
View File

@ -0,0 +1,38 @@
package repository
import (
"bufio"
"log"
"os"
"strings"
)
func GetCsvDatas(selections []string) {
//selections := []string{"SITE_NUM", "VREF_BF", "IB_VOR_BF", "SOFT_BIN"}
f, err := os.Open("./SY8821-QLGKRN_CQ774P.1_FT.csv")
if err != nil {
log.Println(err)
}
defer f.Close()
scanner := bufio.NewScanner(f)
m := make(map[string]int)
datas := make([]map[string]string, 0)
for scanner.Scan() {
line := scanner.Text()
s := strings.Split(line, ",")
if len(m) == 0 {
for index, cell := range s {
if index == len(s)-1 {
continue
}
m[cell] = index
}
continue
}
data := make(map[string]string)
for _, selection := range selections {
data[selection] = s[m[selection]]
}
datas = append(datas, data)
}
}

39
repository/qipai.go Normal file
View File

@ -0,0 +1,39 @@
package repository
import (
"fmt"
"path"
"strings"
"testData/global"
"testData/model"
)
// QiPai 气派
func QiPai() {
var fileTexts []*model.FileText
global.PostGreSQL.
Where("factory = ?", "qipai").Find(&fileTexts)
for _, fileText := range fileTexts {
if strings.ToLower(path.Ext(fileText.Name)) != ".csv" &&
strings.ToLower(path.Ext(fileText.Name)) != ".xls" && strings.ToLower(path.Ext(fileText.Name)) != ".xlsx" {
continue
}
s := strings.Split(fileText.Name, "_")
if len(s) == 9 && strings.Contains(fileText.Name, "P(A)_STS8200_4Site_(1P0)") {
ss := strings.Split(fileText.Name, "P(A)_STS8200_4Site_(1P0)")
sss := strings.Split(ss[0], "_")
fmt.Println(sss)
product := sss[len(sss)-2]
if strings.Index(product, "(") != -1 {
product = product[:strings.Index(product, "(")]
}
lotArray := strings.Split(sss[1], "-")
if len(lotArray) > 4 {
fmt.Println(sss[1])
}
//fmt.Println("批号:", sss[2])
fmt.Println("产品型号:", product)
}
//HandleSTS8200Excel(fileText, "")
}
}

45
repository/saimeike.go Normal file
View File

@ -0,0 +1,45 @@
package repository
import (
"path"
"strings"
"testData/global"
"testData/model"
)
func SaiMeiKe() {
// 赛美科
var fileTexts []*model.FileText
global.PostGreSQL.
Where("factory = ?", "saimeike").Find(&fileTexts)
for _, fileText := range fileTexts {
//fileText.Name = strings.ToLower(fileText.Name)
//if path.Ext(fileText.Name) != ".csv" && path.Ext(fileText.Name) != ".xls" && path.Ext(fileText.Name) != ".xlsx" {
// continue
//}
if strings.ToLower(path.Ext(fileText.Name)) != ".csv" &&
strings.ToLower(path.Ext(fileText.Name)) != ".xls" && strings.ToLower(path.Ext(fileText.Name)) != ".xlsx" {
continue
}
var step string
if len(fileText.Name) > 8 {
if fileText.Name[len(fileText.Name)-7:] == "cp1.csv" {
step = "CP1"
} else if fileText.Name[len(fileText.Name)-7:] == "cp2.csv" {
step = "CP2"
}
}
messages := strings.Split(fileText.Name, "_")
if len(messages) >= 3 {
if strings.Contains(messages[2], "r") {
step = "RT"
} else if strings.Contains(messages[2], "t") {
step = "FT"
}
}
if step == "" {
continue
}
HandleSTS8200Excel(fileText, step)
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,368 @@
package test_data
import (
"bufio"
"encoding/json"
"log"
"math"
"os"
"strconv"
"strings"
"testData/global"
"testData/model"
"testData/request"
)
func LotInAFileSelection(product, lot, pbi, subBatch, step string) ([]string, []string, []string, []string) {
var fileHandle *model.FileHandled
global.PostGreSQL.Where("product = ? AND lot = ? AND pbi = ? AND sub_batch = ? AND step = ?",
product, lot, pbi, subBatch, step).Find(&fileHandle)
f, err := os.Open(fileHandle.Path)
if err != nil {
log.Println(err)
}
defer f.Close()
scanner := bufio.NewScanner(f)
var selection []string
datas := make([][]string, 0)
fieldMap := make(map[string]int)
for scanner.Scan() {
line := scanner.Text()
s := strings.Split(line, ",")
datas = append(datas, s[:len(s)-1])
if len(datas) == 1 {
if step == "CP" {
selection = s[8 : len(s)-1]
} else {
selection = s[6 : len(s)-1]
}
for index, cell := range s {
if index == len(s)-1 {
continue
}
fieldMap[cell] = index
}
}
}
binMap := make(map[string]interface{})
hBinMap := make(map[string]int)
siteMap := make(map[string]int)
for _, data := range datas {
siteMap[data[fieldMap["SITE_NUM"]]] = 1
}
var sBin, hBin, site []string
_ = json.Unmarshal([]byte(fileHandle.SbinHbin), &binMap)
for k, v := range binMap {
sBin = append(sBin, k)
sBinInfoMap := v.(map[string]interface{})
hBinMap[sBinInfoMap["HBin"].(string)] = 1
}
for k := range siteMap {
site = append(site, k)
}
for k := range hBinMap {
hBin = append(hBin, k)
}
return selection, sBin, hBin, site
}
func LotInAFile(product, lot, pbi, subBatch, waferID string) ([][]string, map[string]int) {
var fileHandle *model.FileHandled
if subBatch != "" {
global.PostGreSQL.Where("product = ? AND lot = ? AND pbi = ? AND sub_batch = ? AND step != ?",
product, lot, pbi, subBatch, "RT").Find(&fileHandle)
} else if waferID != "" {
global.PostGreSQL.Where("product = ? AND lot = ? AND pbi = ? AND wafer_id = ?",
product, lot, pbi, waferID).Find(&fileHandle)
} else {
return nil, nil
}
f, err := os.Open(fileHandle.Path)
if err != nil {
log.Println(err)
}
defer f.Close()
xyMap := make(map[string]int)
scanner := bufio.NewScanner(f)
datas := make([][]string, 0)
fieldMap := make(map[string]int)
for scanner.Scan() {
line := scanner.Text()
s := strings.Split(line, ",")
if strings.Contains(fileHandle.Step, "CP") {
x := s[fieldMap["X_COORD"]]
y := s[fieldMap["Y_COORD"]]
if _, ok := xyMap[x+","+y]; !ok {
xyMap[x+","+y] = len(datas)
datas = append(datas, s[:len(s)-1])
} else {
datas[xyMap[x+","+y]] = s[:len(s)-1]
}
} else {
datas = append(datas, s[:len(s)-1])
}
if len(datas) == 1 {
for index, cell := range s {
if index == len(s)-1 {
continue
}
fieldMap[cell] = index
}
}
}
if len(datas) >= 1 {
datas = datas[1:]
}
return datas, fieldMap
}
func LotInMultipleFilesSelection(product, lot, pbi string) map[string][]string {
var fileHandles []*model.FileHandled
global.PostGreSQL.Where("product = ? AND lot = ? AND pbi = ?", product, lot, pbi).Find(&fileHandles)
datas := make([][]string, 0)
fieldMap := make(map[string]int)
binMap := make(map[string]interface{})
subBatchMap := make(map[string]int)
waferIDMap := make(map[string]int)
var selection []string
var subBatch, waferID []string
for _, fileHandle := range fileHandles {
if strings.Contains(fileHandle.Step, "CP") {
waferIDMap[fileHandle.WaferID] = 1
} else {
subBatchMap[fileHandle.SubBatch] = 1
}
singleDatas := make([][]string, 0)
_ = json.Unmarshal([]byte(fileHandle.SbinHbin), &binMap)
f, err := os.Open(fileHandle.Path)
if err != nil {
log.Println(err)
}
scanner := bufio.NewScanner(f)
xyMap := make(map[string]int)
for scanner.Scan() {
line := scanner.Text()
s := strings.Split(line, ",")
if strings.Contains(fileHandle.Step, "CP") {
x := s[fieldMap["X_COORD"]]
y := s[fieldMap["Y_COORD"]]
if _, ok := xyMap[x+","+y]; !ok {
xyMap[x+","+y] = len(singleDatas)
singleDatas = append(singleDatas, s[:len(s)-1])
}
} else {
singleDatas = append(singleDatas, s[:len(s)-1])
}
if len(singleDatas) == 1 {
if strings.Contains(fileHandle.Step, "CP") {
selection = s[8 : len(s)-1]
} else {
selection = s[6 : len(s)-1]
}
for index, cell := range s {
if index == len(s)-1 {
continue
}
fieldMap[cell] = index
}
}
}
if len(singleDatas) >= 1 {
singleDatas = singleDatas[1:]
}
datas = append(datas, singleDatas...)
f.Close()
}
sBinMap := make(map[string]int)
siteMap := make(map[string]int)
for _, data := range datas {
sBinMap[data[fieldMap["SOFT_BIN"]]] = 1
siteMap[data[fieldMap["SITE_NUM"]]] = 1
}
hBinMap := make(map[string]int)
var sBin, hBin, site []string
for k := range sBinMap {
if _, ok := binMap[k]; ok {
sBin = append(sBin, k)
sBinInfoMap := binMap[k].(map[string]interface{})
hBinMap[sBinInfoMap["HBin"].(string)] = 1
}
}
for k := range siteMap {
site = append(site, k)
}
for k := range hBinMap {
hBin = append(hBin, k)
}
for k := range subBatchMap {
subBatch = append(subBatch, k)
}
for k := range waferIDMap {
waferID = append(waferID, k)
}
res := make(map[string][]string)
res["selection"] = selection
res["sbin"] = sBin
res["hbin"] = hBin
res["site"] = site
res["subBatch"] = subBatch
res["waferID"] = waferID
return res
}
func LotInMultipleFiles(product, lot, pbi string) ([][]string, map[string]int) {
var fileHandles []*model.FileHandled
global.PostGreSQL.Where("product = ? AND lot = ? AND pbi = ? AND step != ?", product, lot, pbi, "RT").Find(&fileHandles)
datas := make([][]string, 0)
fieldMap := make(map[string]int)
for _, fileHandle := range fileHandles {
fileDatas := make([][]string, 0)
f, err := os.Open(fileHandle.Path)
if err != nil {
log.Println(err)
}
xyMap := make(map[string]int)
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text()
s := strings.Split(line, ",")
if strings.Contains(fileHandle.Step, "CP") {
x := s[fieldMap["X_COORD"]]
y := s[fieldMap["Y_COORD"]]
if _, ok := xyMap[x+","+y]; !ok {
xyMap[x+","+y] = len(fileDatas)
fileDatas = append(fileDatas, s[:len(s)-1])
} else {
fileDatas[xyMap[x+","+y]] = s[:len(s)-1]
}
} else {
fileDatas = append(fileDatas, s[:len(s)-1])
}
if len(datas) == 0 {
for index, cell := range s {
if index == len(s)-1 {
continue
}
fieldMap[cell] = index
}
}
}
f.Close()
if len(fileDatas) >= 1 {
fileDatas = fileDatas[1:]
}
datas = append(datas, fileDatas...)
}
return datas, fieldMap
}
func SelectionLimit(req *request.SelectionLimit) (string, string) {
// CP测试没有子批次
var fileHandle *model.FileHandled
global.PostGreSQL.Where("pbi = ? AND product = ? AND lot = ? AND wafer_id = ?", req.PBI, req.Product, req.Lot, req.WaferID).
Find(&fileHandle)
f, err := os.Open(fileHandle.Path)
if err != nil {
log.Println(err)
return "", ""
}
defer f.Close()
scanner := bufio.NewScanner(f)
datas := make([][]string, 0)
fieldMap := make(map[string]int)
for scanner.Scan() {
line := scanner.Text()
s := strings.Split(line, ",")
datas = append(datas, s[:len(s)-1])
if len(datas) == 1 {
for index, cell := range s {
if index == len(s)-1 {
continue
}
fieldMap[cell] = index
}
}
}
if len(datas) >= 1 {
datas = datas[1:]
}
maxStr := strconv.Itoa(math.MinInt)
minStr := strconv.Itoa(math.MaxInt)
sbinHbinMap := make(map[string]map[string]string)
selectionData := make(map[string]int)
sbinHbinByte := []byte(fileHandle.SbinHbin)
_ = json.Unmarshal(sbinHbinByte, &sbinHbinMap)
for _, data := range datas {
binInfoMap := sbinHbinMap[data[fieldMap["SOFT_BIN"]]]
// 筛选Site
var siteInclude bool
if len(req.Site) == 0 {
siteInclude = true
} else {
for _, site := range req.Site {
if data[fieldMap["SITE_NUM"]] == site {
siteInclude = true
break
}
}
}
if !siteInclude {
continue
}
// 筛选Soft Bin
var sBinInclude bool
if len(req.SBin) == 0 {
sBinInclude = true
} else {
for _, bin := range req.SBin {
if data[fieldMap["SOFT_BIN"]] == bin {
sBinInclude = true
break
}
}
}
if !sBinInclude {
continue
}
// 筛选Hard Bin
var hBinInclude bool
if len(req.HBin) == 0 {
hBinInclude = true
} else {
for _, bin := range req.HBin {
if binInfoMap["HBin"] == bin {
hBinInclude = true
break
}
}
}
if !hBinInclude {
continue
}
if len(data) > fieldMap[req.Selection] && data[fieldMap[req.Selection]] != "" {
selectionData[data[fieldMap[req.Selection]]] = 1
}
}
for k := range selectionData {
maxDecimal, _ := strconv.ParseFloat(maxStr, 64)
minDecimal, _ := strconv.ParseFloat(minStr, 64)
dataDecimal, _ := strconv.ParseFloat(k, 64)
if dataDecimal <= minDecimal {
minStr = k
}
if maxDecimal <= dataDecimal {
maxStr = k
}
}
if maxStr == strconv.Itoa(math.MinInt) {
maxStr = "NA"
}
if minStr == strconv.Itoa(math.MaxInt) {
minStr = "NA"
}
return maxStr, minStr
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,117 @@
package test_data
import "github.com/xuri/excelize/v2"
func NormalSheetStyle(f *excelize.File) int {
style, _ := f.NewStyle(&excelize.Style{
Border: []excelize.Border{
{Type: "left", Color: "000000", Style: 1},
{Type: "top", Color: "000000", Style: 1},
{Type: "bottom", Color: "000000", Style: 1},
{Type: "right", Color: "000000", Style: 1},
},
Fill: excelize.Fill{Type: "pattern", Pattern: 1, Color: []string{}},
Font: &excelize.Font{Family: "微软雅黑", Size: 10, Bold: false},
Alignment: &excelize.Alignment{
Horizontal: "center",
},
})
return style
}
func TitleStyle(f *excelize.File) int {
style, _ := f.NewStyle(&excelize.Style{
Border: []excelize.Border{
{Type: "left", Color: "000000", Style: 1},
{Type: "top", Color: "000000", Style: 1},
{Type: "bottom", Color: "000000", Style: 1},
{Type: "right", Color: "000000", Style: 1},
},
Fill: excelize.Fill{Type: "pattern", Pattern: 1, Color: []string{"#4F81BD"}},
Font: &excelize.Font{Family: "微软雅黑", Size: 10, Bold: false},
Alignment: &excelize.Alignment{
Horizontal: "center",
},
})
return style
}
func ActualLimitStyle(f *excelize.File) int {
style, _ := f.NewStyle(&excelize.Style{
Border: []excelize.Border{
{Type: "left", Color: "000000", Style: 1},
{Type: "top", Color: "000000", Style: 1},
{Type: "bottom", Color: "000000", Style: 1},
{Type: "right", Color: "000000", Style: 1},
},
Fill: excelize.Fill{Type: "pattern", Pattern: 1, Color: []string{"#D0D8E8"}},
Font: &excelize.Font{Family: "微软雅黑", Size: 10, Bold: false},
Alignment: &excelize.Alignment{
Horizontal: "center",
},
})
return style
}
func LimitStyle(f *excelize.File) int {
style, _ := f.NewStyle(&excelize.Style{
Border: []excelize.Border{
{Type: "left", Color: "000000", Style: 1},
{Type: "top", Color: "000000", Style: 1},
{Type: "bottom", Color: "000000", Style: 1},
{Type: "right", Color: "000000", Style: 1},
},
Fill: excelize.Fill{Type: "pattern", Pattern: 1, Color: []string{"#FFF2CC"}},
Font: &excelize.Font{Family: "微软雅黑", Size: 10, Bold: false},
Alignment: &excelize.Alignment{
Horizontal: "center",
},
})
return style
}
func CPMapPassStyle(f *excelize.File) int {
style, _ := f.NewStyle(&excelize.Style{
Border: []excelize.Border{
{Type: "left", Color: "000000", Style: 1},
{Type: "top", Color: "000000", Style: 1},
{Type: "bottom", Color: "000000", Style: 1},
{Type: "right", Color: "000000", Style: 1},
},
Fill: excelize.Fill{Type: "pattern", Pattern: 1, Color: []string{"#4FFF00"}},
Font: &excelize.Font{Family: "微软雅黑", Size: 10, Bold: false},
})
return style
}
func CPMapFailStyle(f *excelize.File) int {
style, _ := f.NewStyle(&excelize.Style{
Border: []excelize.Border{
{Type: "left", Color: "000000", Style: 1},
{Type: "top", Color: "000000", Style: 1},
{Type: "bottom", Color: "000000", Style: 1},
{Type: "right", Color: "000000", Style: 1},
},
Fill: excelize.Fill{Type: "pattern", Pattern: 1, Color: []string{"#FF0000"}},
Font: &excelize.Font{Family: "微软雅黑", Size: 10, Bold: false},
})
return style
}
func NormalNumberSheetStyle(f *excelize.File) int {
style, _ := f.NewStyle(&excelize.Style{
Border: []excelize.Border{
{Type: "left", Color: "000000", Style: 1},
{Type: "top", Color: "000000", Style: 1},
{Type: "bottom", Color: "000000", Style: 1},
{Type: "right", Color: "000000", Style: 1},
},
NumFmt: 2,
Fill: excelize.Fill{Type: "pattern", Pattern: 1, Color: []string{}},
Font: &excelize.Font{Family: "微软雅黑", Size: 10, Bold: false},
Alignment: &excelize.Alignment{
Horizontal: "center",
},
})
return style
}

View File

@ -0,0 +1,455 @@
package test_data
import (
"gitee.com/golang-module/carbon/v2"
"github.com/shopspring/decimal"
"gorm.io/gorm"
"math"
"sort"
"strconv"
"testData/global"
"testData/model"
"testData/request"
)
func PackagePassProbabilityLine(r *request.PackagePassProbabilityLine) ([]*model.Line, int, int) {
var sql string
if r.OrderDateStart != "" && r.OrderDateEnd != "" {
sql += "tc_sfc02 BETWEEN DATE '" + r.OrderDateStart + "' AND DATE '" + r.OrderDateEnd + "'"
}
//else if r.OrderDateStart != "" && r.OrderDateEnd == "" {
// sql += "tc_sfc02 >= DATE '" + r.OrderDateStart + "'"
//} else if r.OrderDateStart == "" && r.OrderDateEnd != "" {
// sql += "tc_sfc02 <= DATE '" + r.OrderDateEnd + "'"
//}
var factories, x []string
if len(r.Factory) == 0 {
global.Oracle.Model(&model.TcSfcFile{}).Where("tc_sfc08 LIKE ?", "%AB%").Where(sql).
Group("tc_sfc04").Select("tc_sfc04").Find(&factories)
} else {
factories = r.Factory
}
productMap := make(map[string]int)
for _, product := range r.Product {
productMap[product] = 1
}
lotMap := make(map[string]int)
for _, lot := range r.Lot {
lotMap[lot] = 1
}
specificationMap := make(map[string]int)
for _, specification := range r.Package {
specificationMap[specification] = 1
}
if r.DateSize == "天" {
days := int(carbon.Parse(r.OrderDateStart).DiffAbsInDays(carbon.Parse(r.OrderDateEnd))) + 1
for i := 0; i < days; i++ {
x = append(x, carbon.Parse(r.OrderDateStart).AddDays(i).Format("Y-m-d"))
}
} else if r.DateSize == "周" {
weeks := int(carbon.Parse(r.OrderDateStart).DiffAbsInWeeks(carbon.Parse(r.OrderDateEnd))) + 1
for i := 0; i < weeks; i++ {
x = append(x, carbon.Parse(r.OrderDateStart).AddWeeks(i).Format("Y-m-d"))
}
} else if r.DateSize == "月" {
months := int(carbon.Parse(r.OrderDateStart).DiffAbsInMonths(carbon.Parse(r.OrderDateEnd))) + 1
for i := 0; i < months; i++ {
x = append(x, carbon.Parse(r.OrderDateStart).AddMonths(i).Format("Y-m"))
}
} else if r.DateSize == "年" {
years := int(carbon.Parse(r.OrderDateStart).DiffAbsInYears(carbon.Parse(r.OrderDateEnd))) + 1
for i := 0; i < years; i++ {
x = append(x, carbon.Parse(r.OrderDateStart).AddYears(i).Format("Y"))
}
}
max := math.MinInt
min := math.MaxInt
var line []*model.Line
for _, factory := range factories {
var tcSfcFile []*model.TcSfcFile
global.Oracle.Where("tc_sfc08 LIKE ? AND tc_sfc04 = ?", "%AB%", factory).Where(sql).
Preload("PmcFile").
Preload("TcSfdFile", func(db *gorm.DB) *gorm.DB {
return db.Preload("ImaFile").Preload("RvaFile", func(db *gorm.DB) *gorm.DB {
return db.Preload("IddFile")
})
}).Preload("TcSfeFile", func(db *gorm.DB) *gorm.DB {
return db.Preload("ImaFile")
}).Order("tc_sfc02").Find(&tcSfcFile)
quantityMap := make(map[string][]float64)
var y []string
for _, tcSfc := range tcSfcFile {
for _, tcSfd := range tcSfc.TcSfdFile {
if _, ok := productMap[tcSfd.ImaFile.Ima02]; !ok && len(productMap) > 0 {
continue
}
if _, ok := specificationMap[tcSfd.ImaFile.Ima021]; !ok && len(specificationMap) > 0 {
continue
}
var stockInQuantity, failQuantity float64
for _, rva := range tcSfd.RvaFile {
for _, idd := range rva.IddFile {
if _, ok := lotMap[idd.Idd04]; !ok && len(lotMap) > 0 {
continue
}
stockInQuantity += idd.Idd13
if idd.Idd06 == "BIN99" {
failQuantity += idd.Idd13
}
}
}
var s string
if r.DateSize == "天" {
s = carbon.Parse(r.OrderDateStart).AddDays(int(carbon.Parse(r.OrderDateStart).
DiffAbsInDays(carbon.CreateFromStdTime(tcSfc.TcSfc02)))).Format("Y-m-d")
} else if r.DateSize == "周" {
s = carbon.Parse(r.OrderDateStart).AddWeeks(int(carbon.Parse(r.OrderDateStart).
DiffAbsInWeeks(carbon.CreateFromStdTime(tcSfc.TcSfc02)))).Format("Y-m-d")
} else if r.DateSize == "月" {
s = carbon.Parse(r.OrderDateStart).AddMonths(int(carbon.Parse(r.OrderDateStart).
DiffAbsInMonths(carbon.CreateFromStdTime(tcSfc.TcSfc02)))).Format("Y-m")
} else if r.DateSize == "年" {
s = carbon.Parse(r.OrderDateStart).AddYears(int(carbon.Parse(r.OrderDateStart).
DiffAbsInYears(carbon.CreateFromStdTime(tcSfc.TcSfc02)))).Format("Y")
}
if _, ok := quantityMap[s]; !ok {
quantityMap[s] = []float64{stockInQuantity - failQuantity, stockInQuantity}
} else {
quantityMap[s][0] += stockInQuantity - failQuantity
quantityMap[s][1] += stockInQuantity
}
}
}
for _, xDate := range x {
if _, ok := quantityMap[xDate]; ok {
if quantityMap[xDate][1] == 0 {
y = append(y, "")
} else {
passProbability := decimal.NewFromFloat(quantityMap[xDate][0]).Div(decimal.NewFromFloat(quantityMap[xDate][1])).
Round(4).Mul(decimal.NewFromFloat(100))
passProbabilityInt, _ := strconv.Atoi(passProbability.Round(0).String())
if passProbabilityInt > max {
max = passProbabilityInt + 1
}
if passProbabilityInt < min {
min = passProbabilityInt - 1
}
y = append(y, passProbability.String())
}
} else {
y = append(y, "")
}
}
line = append(line, &model.Line{
Name: factory,
X: x,
Y: y,
})
}
return line, max, min
}
func OrderNumberHistogram(r *request.PackagePassProbabilityLine) []*model.Histogram {
var fTHistogram []*model.Histogram
var sql string
if r.OrderDateStart != "" && r.OrderDateEnd != "" {
sql += "tc_sfc02 BETWEEN DATE '" + r.OrderDateStart + "' AND DATE '" + r.OrderDateEnd + "'"
}
//else if r.OrderDateStart != "" && r.OrderDateEnd == "" {
// sql += "tc_sfc02 >= DATE '" + r.OrderDateStart + "'"
//} else if r.OrderDateStart == "" && r.OrderDateEnd != "" {
// sql += "tc_sfc02 <= DATE '" + r.OrderDateEnd + "'"
//}
var factories, x []string
if len(r.Factory) == 0 {
global.Oracle.Model(&model.TcSfcFile{}).Where("tc_sfc08 LIKE ?", "%AB%").Where(sql).
Group("tc_sfc04").Select("tc_sfc04").Find(&factories)
} else {
factories = r.Factory
}
productMap := make(map[string]int)
for _, product := range r.Product {
productMap[product] = 1
}
lotMap := make(map[string]int)
for _, lot := range r.Lot {
lotMap[lot] = 1
}
specificationMap := make(map[string]int)
for _, specification := range r.Package {
specificationMap[specification] = 1
}
if r.DateSize == "天" {
days := int(carbon.Parse(r.OrderDateStart).DiffAbsInDays(carbon.Parse(r.OrderDateEnd))) + 1
for i := 0; i < days; i++ {
x = append(x, carbon.Parse(r.OrderDateStart).AddDays(i).Format("Y-m-d"))
}
} else if r.DateSize == "周" {
weeks := int(carbon.Parse(r.OrderDateStart).DiffAbsInWeeks(carbon.Parse(r.OrderDateEnd))) + 1
for i := 0; i < weeks; i++ {
x = append(x, carbon.Parse(r.OrderDateStart).AddWeeks(i).Format("Y-m-d"))
}
} else if r.DateSize == "月" {
months := int(carbon.Parse(r.OrderDateStart).DiffAbsInMonths(carbon.Parse(r.OrderDateEnd))) + 1
for i := 0; i < months; i++ {
x = append(x, carbon.Parse(r.OrderDateStart).AddMonths(i).Format("m"))
}
} else if r.DateSize == "年" {
years := int(carbon.Parse(r.OrderDateStart).DiffAbsInYears(carbon.Parse(r.OrderDateEnd))) + 1
for i := 0; i < years; i++ {
x = append(x, carbon.Parse(r.OrderDateStart).AddYears(i).Format("Y"))
}
}
for _, factory := range factories {
var tcSfcFile []*model.TcSfcFile
global.Oracle.Where("tc_sfc08 LIKE ? AND tc_sfc04 = ?", "%AB%", factory).Where(sql).
Preload("PmcFile").
Preload("TcSfdFile", func(db *gorm.DB) *gorm.DB {
return db.Preload("ImaFile").Preload("RvaFile", func(db *gorm.DB) *gorm.DB {
return db.Preload("IddFile")
})
}).Preload("TcSfeFile", func(db *gorm.DB) *gorm.DB {
return db.Preload("ImaFile")
}).Order("tc_sfc02").Find(&tcSfcFile)
quantityMap := make(map[string]float64)
var y []string
for _, tcSfc := range tcSfcFile {
for _, tcSfd := range tcSfc.TcSfdFile {
if _, ok := productMap[tcSfd.ImaFile.Ima02]; !ok && len(productMap) > 0 {
continue
}
if _, ok := specificationMap[tcSfd.ImaFile.Ima021]; !ok && len(specificationMap) > 0 {
continue
}
var stockInQuantity float64
for _, rva := range tcSfd.RvaFile {
for _, idd := range rva.IddFile {
if _, ok := lotMap[idd.Idd04]; !ok && len(lotMap) > 0 {
continue
}
stockInQuantity += idd.Idd13
}
}
var s string
if r.DateSize == "天" {
s = carbon.Parse(r.OrderDateStart).AddDays(int(carbon.Parse(r.OrderDateStart).
DiffAbsInDays(carbon.CreateFromStdTime(tcSfc.TcSfc02)))).Format("Y-m-d")
} else if r.DateSize == "周" {
s = carbon.Parse(r.OrderDateStart).AddWeeks(int(carbon.Parse(r.OrderDateStart).
DiffAbsInWeeks(carbon.CreateFromStdTime(tcSfc.TcSfc02)))).Format("Y-m-d")
} else if r.DateSize == "月" {
s = carbon.Parse(r.OrderDateStart).AddMonths(int(carbon.Parse(r.OrderDateStart).
DiffAbsInMonths(carbon.CreateFromStdTime(tcSfc.TcSfc02)))).Format("m")
} else if r.DateSize == "年" {
s = carbon.Parse(r.OrderDateStart).AddYears(int(carbon.Parse(r.OrderDateStart).
DiffAbsInYears(carbon.CreateFromStdTime(tcSfc.TcSfc02)))).Format("Y")
}
if _, ok := quantityMap[s]; !ok {
quantityMap[s] = stockInQuantity
} else {
quantityMap[s] += stockInQuantity
}
}
}
for _, xDate := range x {
if _, ok := quantityMap[xDate]; ok {
y = append(y, decimal.NewFromFloat(quantityMap[xDate]).String())
} else {
y = append(y, "0")
}
}
fTHistogram = append(fTHistogram, &model.Histogram{
Field: factory,
X: x,
Y: y,
})
}
return fTHistogram
}
func PassProbabilityByFactory(r *request.PassProbabilityByFactory) ([]*model.Line, []*model.Histogram, int, int) {
var lines []*model.Line
var histogram []*model.Histogram
max := math.MinInt
min := math.MaxInt
startDate := carbon.Now().SubYear().StartOfMonth().Format("Y-m-d")
endDate := carbon.Now().EndOfMonth().Format("Y-m-d")
var factorys []string
var sql string
if r.Factory != "" {
sql += "factory = '" + r.Factory + "'"
}
global.PostGreSQL.Model(&model.Report{}).Where("step = ? AND order_date BETWEEN ? AND ?", r.Type, startDate, endDate).
Where(sql).Group("factory").Select("Factory").Find(&factorys)
for _, factory := range factorys {
var x, lineY, histogramY []string
var reports []*model.Report
global.PostGreSQL.Where("step = ? AND factory = ? AND order_date BETWEEN ? AND ?", r.Type, factory, startDate, endDate).
Find(&reports)
factoryMap := make(map[string][]string)
for _, report := range reports {
if _, ok := factoryMap[report.OrderDate[:7]]; !ok {
factoryMap[report.OrderDate[:7]] = []string{report.TestQuantity, report.PassQuantity}
} else {
factoryMapTestQuantity, _ := decimal.NewFromString(factoryMap[report.OrderDate[:7]][0])
factoryMapPassQuantity, _ := decimal.NewFromString(factoryMap[report.OrderDate[:7]][1])
testQuantity, _ := decimal.NewFromString(report.TestQuantity)
passQuantity, _ := decimal.NewFromString(report.PassQuantity)
factoryMap[report.OrderDate[:7]] = []string{factoryMapTestQuantity.Add(testQuantity).String(),
factoryMapPassQuantity.Add(passQuantity).String()}
}
}
month := carbon.Now().SubYear().StartOfMonth().Format("Y-m")
for {
if month == carbon.Now().EndOfMonth().Format("Y-m") {
break
}
x = append(x, month)
if _, ok := factoryMap[month]; !ok {
lineY = append(lineY, "")
histogramY = append(histogramY, "")
} else {
testQuantity, _ := decimal.NewFromString(factoryMap[month][0])
passQuantity, _ := decimal.NewFromString(factoryMap[month][1])
passProbability := passQuantity.Div(testQuantity).
Round(4).Mul(decimal.NewFromFloat(100))
passProbabilityInt, _ := strconv.Atoi(passProbability.Round(0).String())
if passProbabilityInt > max {
max = passProbabilityInt + 1
}
if passProbabilityInt < min {
min = passProbabilityInt - 1
}
lineY = append(lineY, passProbability.String())
histogramY = append(histogramY, factoryMap[month][0])
}
month = carbon.Parse(month).AddMonth().Format("Y-m")
}
lines = append(lines, &model.Line{
Name: factory,
X: x,
Y: lineY,
})
histogram = append(histogram, &model.Histogram{
Field: factory,
X: x,
Y: histogramY,
})
}
return lines, histogram, max, min
}
func FTPassProbabilityByProduct(r *request.PassProbabilityByProduct) (*model.Line, *model.Histogram, *model.Line, *model.Histogram) {
var line, binLine *model.Line
var histogram, binHistogram *model.Histogram
max := math.MinInt
min := math.MaxInt
startDate := carbon.Now().SubYear().StartOfMonth().Format("Y-m-d")
endDate := carbon.Now().EndOfMonth().Format("Y-m-d")
var sql string
if r.Factory != "" {
sql += "factory = '" + r.Factory + "'"
}
var reports []*model.Report
global.PostGreSQL.Where("step = ? AND product = ? AND order_date BETWEEN ? AND ?",
r.Type, r.Product, startDate, endDate).Preload("BinFail", func(db *gorm.DB) *gorm.DB {
return db.Where("report_site_id = ?", 0)
}).Where(sql).Find(&reports)
productMap := make(map[string][]string)
binMap := make(map[string]float64)
var x, lineY, histogramY []string
for _, report := range reports {
if _, ok := productMap[report.OrderDate[:7]]; !ok {
productMap[report.OrderDate[:7]] = []string{report.TestQuantity, report.PassQuantity}
} else {
factoryMapTestQuantity, _ := decimal.NewFromString(productMap[report.OrderDate[:7]][0])
factoryMapPassQuantity, _ := decimal.NewFromString(productMap[report.OrderDate[:7]][1])
testQuantity, _ := decimal.NewFromString(report.TestQuantity)
passQuantity, _ := decimal.NewFromString(report.PassQuantity)
productMap[report.OrderDate[:7]] = []string{factoryMapTestQuantity.Add(testQuantity).String(),
factoryMapPassQuantity.Add(passQuantity).String()}
}
for _, binFail := range report.BinFail {
if _, ok := binMap[binFail.HardBin]; !ok {
binMap[binFail.HardBin] = 0
}
quantityDecimal, _ := decimal.NewFromString(binFail.Quantity)
quantity, _ := quantityDecimal.Float64()
binMap[binFail.HardBin] += quantity
}
}
month := carbon.Now().SubYear().StartOfMonth().Format("Y-m")
var testStr, passStr string
for {
if month == carbon.Now().EndOfMonth().Format("Y-m") {
break
}
x = append(x, month)
if _, ok := productMap[month]; !ok {
lineY = append(lineY, "")
histogramY = append(histogramY, "")
} else {
testQuantity, _ := decimal.NewFromString(productMap[month][0])
passQuantity, _ := decimal.NewFromString(productMap[month][1])
testDecimal, _ := decimal.NewFromString(testStr)
passDecimal, _ := decimal.NewFromString(passStr)
testStr = testDecimal.Add(testQuantity).String()
passStr = passDecimal.Add(passQuantity).String()
passProbability := passQuantity.Div(testQuantity).
Round(4).Mul(decimal.NewFromFloat(100))
passProbabilityInt, _ := strconv.Atoi(passProbability.Round(0).String())
if passProbabilityInt > max {
max = passProbabilityInt + 1
}
if passProbabilityInt < min {
min = passProbabilityInt - 1
}
lineY = append(lineY, passProbability.String())
histogramY = append(histogramY, productMap[month][0])
}
month = carbon.Parse(month).AddMonth().Format("Y-m")
}
var binX, binHistogramY, binLineY []string
for bin := range binMap {
if bin != "1" {
binX = append(binX, bin)
}
}
sort.Slice(binX, func(i, j int) bool {
return binMap[binX[i]] > binMap[binX[j]]
})
var accumulation float64
testDecimal, _ := decimal.NewFromString(testStr)
passDecimal, _ := decimal.NewFromString(passStr)
failQuantity, _ := testDecimal.Sub(passDecimal).Float64()
for _, bin := range binX {
binHistogramY = append(binHistogramY, decimal.NewFromFloat(binMap[bin]).String())
accumulation += binMap[bin]
binLineY = append(binLineY, decimal.NewFromFloat(accumulation).Div(decimal.NewFromFloat(failQuantity)).
Round(4).Mul(decimal.NewFromFloat(100)).String())
}
line = &model.Line{
Name: r.Product,
X: x,
Y: lineY,
}
histogram = &model.Histogram{
Field: r.Product,
X: x,
Y: histogramY,
}
binLine = &model.Line{
Name: r.Product,
X: binX,
Y: binLineY,
}
binHistogram = &model.Histogram{
Field: r.Product,
X: binX,
Y: binHistogramY,
}
return line, histogram, binLine, binHistogram
}

View File

@ -0,0 +1,743 @@
package test_data
import (
"bufio"
"encoding/json"
"errors"
"gitee.com/golang-module/carbon/v2"
"github.com/shopspring/decimal"
"github.com/xuri/excelize/v2"
"gorm.io/gorm"
"log"
"os"
"strconv"
"strings"
"testData/global"
"testData/model"
"time"
)
//func Emails() {
// fmt.Println("Connecting to server...")
//
// // Connect to server
// c, err := client.DialTLS("imap.exmail.qq.com:993", nil)
// if err != nil {
// fmt.Println("连接IMAP服务器出错:", err)
// return
// }
// fmt.Println("Connected QQ Imap Receive Server(imap.exmail.qq.com)...")
//
// // Login
// if err = c.Login("wip@tkplusemi.com", "Tkpluse123ip"); err != nil {
// fmt.Println("登陆IMAP服务器出错:", err)
// return
// }
// //if err := c.Login("jh_peng@tkplusemi.com", "Jimmy123"); err != nil {
// // log.Fatal(err)
// //}
// fmt.Println("Logged in...")
//
// global.IMAP = c
//
// // List mailboxes
// mailboxes := make(chan *imap.MailboxInfo, 10)
// done := make(chan error, 10)
// go func() {
// done <- global.IMAP.List("", "*", mailboxes)
// }()
// log.Println("Mailboxes:")
// for m := range mailboxes {
// fmt.Println("* " + m.Name)
// }
//
// if err := <-done; err != nil {
// fmt.Println(err)
// }
//
// // Select INBOX
// mbox, err := global.IMAP.Select("INBOX", false)
// if err != nil {
// fmt.Println(err)
// }
// fmt.Println("mbox:", mbox)
// //fmt.Println("Flags for INBOX:", mbox.Flags)
//
// // 创建搜索条件
// criteria := imap.NewSearchCriteria()
// // 搜索未读标志的邮件
// criteria.WithoutFlags = []string{"\\Seen"}
// // 获取未读标志邮件的UID
// ids, _ := global.IMAP.UidSearch(criteria)
// // 按UID获取邮件
// seqset := new(imap.SeqSet)
// seqset.AddNum(ids...)
//
// // 获取邮件
// messages := make(chan *imap.Message)
// section := imap.BodySectionName{}
// // 获取邮件标志, 内容
// items := []imap.FetchItem{imap.FetchFlags, section.FetchItem()}
// done = make(chan error, len(ids))
// go func() {
// // 按UID获取邮件
// done <- global.IMAP.UidFetch(seqset, items, messages)
// }()
//
// var index int
// var factorys []*model.Factory
// global.PostGreSQL.Find(&factorys)
//
// imap.CharsetReader = charset.Reader
// for msg := range messages {
// start := time.Now()
// r := msg.GetBody(&section)
// if r == nil {
// log.Println("服务器未返回邮件正文")
// }
// fmt.Printf("获取邮件内容耗时:%s\n", time.Now().Sub(start).String())
// mr, err := mail.CreateReader(r)
// if err != nil {
// log.Fatal(err)
// }
// header := mr.Header
// var subject string
// // 获取邮件发件人
// if from, err := header.AddressList("From"); err == nil {
// fmt.Println(from[0].Address)
// startFrom := time.Now()
// address := from[0].Address
// if orgsender, err := header.AddressList("X-Qq-Csender"); err == nil { // X-Qq-Orgsender
// if len(orgsender) > 0 && orgsender[0].Address != "" {
// address = orgsender[0].Address
// }
// }
// if len(from) != 1 {
// fmt.Printf("当前邮件耗时:%s\n", time.Now().Sub(start).String())
// fmt.Printf("当前邮件处理From耗时:%s\n", time.Now().Sub(startFrom).String())
// continue
// }
// var needHandle bool
// for j := 0; j < len(factorys); j++ {
// if address != factorys[j].Email {
// continue
// }
// // 获取邮件主题
// if subject, err = header.Subject(); err == nil {
// if !strings.Contains(subject, factorys[j].Keyword) || factorys[j].Keyword == "" {
// continue
// }
// needHandle = true
// index = j
// log.Println("Subject:", subject)
// }
//
// }
// if !needHandle {
// fmt.Printf("当前邮件耗时:%s\n", time.Now().Sub(start).String())
// fmt.Printf("当前邮件处理From耗时:%s\n", time.Now().Sub(startFrom).String())
// continue
// }
// log.Println("From:", from)
// }
// var companyName string
// companyName = factorys[index].Name
// // 处理邮件正文
// for {
// p, err := mr.NextPart()
// if err == io.EOF {
// break
// } else if err != nil {
// log.Fatal("NextPart:err ", err)
// }
// switch h := p.Header.(type) {
// case *mail.AttachmentHeader:
// // 正文内附件
// b, _ := ioutil.ReadAll(p.Body)
// filename, _ := h.Filename()
// var a []byte
// p.Body.Read(a)
// suffixIndex := strings.LastIndex(filename, ".")
// suffix := strings.ToLower(filename[suffixIndex:])
// filename = filename[:suffixIndex] + suffix
// if suffix != ".xlsx" && suffix != ".xls" && suffix != ".csv" {
// continue
// }
//
// // 根据公司名生成文件路径
// folderPath := utils.MakeSavePath(companyName)
// var newFileName string
// if strings.Contains(filename, ".xlsx") {
// newFileName = filepath.Join(folderPath, time.Now().Format("20060102150405.xlsx"))
// f, _ := os.OpenFile(newFileName, os.O_RDWR|os.O_CREATE, 0766)
// _, err = f.Write(b)
// if err != nil {
// log.Println("download file", filename, "err")
// _ = os.Remove(filename)
// }
// f.Close()
// } else if strings.Contains(filename, ".xls") {
// newFileName = filepath.Join(folderPath, time.Now().Format("20060102150405.xls"))
// f, _ := os.OpenFile(newFileName, os.O_RDWR|os.O_CREATE, 0766)
// _, err = f.Write(b)
// if err != nil {
// log.Println("download file", filename, "err")
// _ = os.Remove(filename)
// }
// _ = f.Close()
// utils.ToXlsx("xls", newFileName)
// newFileName += ".xlsx"
// } else if strings.Contains(filename, ".csv") {
// newFileName = filepath.Join(folderPath, time.Now().Format("20060102150405.xlsx"))
// rows := strings.Split(string(b), "\r\n")
// f := excelize.NewFile()
// // 获取Sheet工作表名称
// sheetName := f.GetSheetName(0)
// for i := 0; i < len(rows); i++ {
// columns := strings.Split(rows[i], ",")
// _ = f.SetSheetRow(sheetName, string(byte(65))+strconv.Itoa(i+1), &columns)
// }
// _ = f.SaveAs(newFileName)
// _ = f.Close()
// }
// // 处理Excel
// switch companyName {
//
// }
// fmt.Printf("当前邮件耗时:%s\n", time.Now().Sub(start).String())
// default:
// fmt.Printf("当前邮件耗时:%s\n", time.Now().Sub(start).String())
// continue
// }
// }
// }
// // 添加标志
// item := imap.FormatFlagsOp(imap.AddFlags, true)
// // 已读标志\Seen
// flags := []interface{}{imap.SeenFlag}
// // 将处理的未读邮件设置为已读
// err = global.IMAP.UidStore(seqset, item, flags, nil)
// if err != nil {
// log.Println(err)
// }
// global.IMAP.Logout()
//}
func SMCFT(filePath string) {
file, _ := excelize.OpenFile(filePath)
sheetName := "FT0801 test Yield(" + carbon.Now().SubMonth().Format("Y.m") + ")"
rows, err := file.GetRows(sheetName)
if err != nil {
log.Println(err)
}
if len(rows) < 3 {
log.Println("Sheet ", sheetName, "格式不规范")
return
}
title := make(map[string]int)
for index, cell := range rows[1] {
title[cell] = index
}
var fTReports []*model.Report
_ = global.Oracle.Transaction(func(tx *gorm.DB) error {
for i := 2; i < len(rows); i++ {
var tcSFDFile *model.TcSfdFile
tx.Where("tc_sfd01 = ? AND tc_sfd06 = ?", rows[i][title["客户订单号"]], rows[i][title["客户批号"]]).Find(&tcSFDFile)
orderDate := carbon.Parse("20" + strings.Split(rows[i][title["客户订单号"]], "-")[1][:6]).Format("Y-m-d")
fTReports = append(fTReports, &model.Report{
Product: rows[i][title["完成型号"]],
Lot: rows[i][title["客户批号"]],
Factory: "saimeike",
TestProgram: rows[i][title["测试程序"]],
PBI: rows[i][title["客户订单号"]],
SubBatch: rows[i][title["厂内批号"]],
OrderDate: orderDate,
Seal: strings.ReplaceAll(tcSFDFile.TcSfdUd02, "'", ""),
TestQuantity: rows[i][title["主数量"]],
PassQuantity: rows[i][title["PASS数"]],
PassProbability: rows[i][title["良率"]],
Step: "FT",
})
}
return nil
})
global.PostGreSQL.Create(&fTReports)
}
func QiPaiFT(filePath string) {
file, _ := excelize.OpenFile(filePath)
sheetName := file.GetSheetName(1)
rows, err := file.GetRows(sheetName)
if err != nil {
log.Println(err)
}
if len(rows) < 2 {
log.Println("Sheet ", sheetName, "格式不规范")
return
}
title := make(map[string]int)
for index, cell := range rows[0] {
title[cell] = index
}
var fTReports []*model.Report
_ = global.Oracle.Transaction(func(tx *gorm.DB) error {
for i := 1; i < len(rows); i++ {
var tcSFDFile *model.TcSfdFile
tx.Where("tc_sfd01 = ? AND tc_sfd06 = ?", rows[i][title["客户订单编号"]], rows[i][title["芯片批号"]]).Find(&tcSFDFile)
orderDate := carbon.Parse("20" + strings.Split(rows[i][title["客户订单编号"]], "-")[1][:6]).Format("Y-m-d")
fTReports = append(fTReports, &model.Report{
Product: rows[i][title["出货品名"]],
Lot: rows[i][title["芯片批号"]],
Factory: "qipai",
TestProgram: "",
PBI: rows[i][title["客户订单编号"]],
SubBatch: rows[i][title["组装批次"]],
OrderDate: orderDate,
Seal: strings.ReplaceAll(tcSFDFile.TcSfdUd02, "'", ""),
TestQuantity: rows[i][title["订单数量"]],
PassQuantity: rows[i][title["入库良品数量"]],
PassProbability: rows[i][title["总良率"]],
Step: "FT",
})
}
return nil
})
global.PostGreSQL.Create(&fTReports)
}
func QingYiFT(filePath string) {
file, _ := excelize.OpenFile(filePath)
sheetName := "Test " + time.Now().Format("01") + "月"
rows, err := file.GetRows(sheetName)
if err != nil {
log.Println(err)
}
if len(rows) < 4 {
log.Println("Sheet ", sheetName, "格式不规范")
return
}
title := make(map[string]int)
for index, cell := range rows[2] {
title[cell] = index
}
var fTReports []*model.Report
_ = global.Oracle.Transaction(func(tx *gorm.DB) error {
for i := 3; i < len(rows); i++ {
var tcSFDFile *model.TcSfdFile
tx.Where("tc_sfd01 = ? AND tc_sfd06 = ?", rows[i][title["订单号"]], rows[i][title["下单批号"]]).Find(&tcSFDFile)
orderDate := carbon.Parse("20" + strings.Split(rows[i][title["订单号"]], "-")[1][:6]).Format("Y-m-d")
fTReports = append(fTReports, &model.Report{
Product: rows[i][title["产品型号"]],
Lot: rows[i][title["下单批号"]],
Factory: "qingyi",
TestProgram: rows[i][title["测试程序"]],
PBI: rows[i][title["订单号"]],
SubBatch: rows[i][title["厂内批号"]],
OrderDate: orderDate,
Seal: strings.ReplaceAll(tcSFDFile.TcSfdUd02, "'", ""),
TestQuantity: rows[i][title["测试投入数"]],
PassQuantity: rows[i][title["测试良品数"]],
PassProbability: rows[i][title["良率"]],
Step: "FT",
})
}
return nil
})
global.PostGreSQL.Create(&fTReports)
}
func RuiSiFT(filePath string) {
file, _ := excelize.OpenFile(filePath)
sheetName := file.GetSheetName(1)
rows, err := file.GetRows(sheetName)
if err != nil {
log.Println(err)
}
if len(rows) < 2 {
log.Println("Sheet ", sheetName, "格式不规范")
return
}
title := make(map[string]int)
for index, cell := range rows[0] {
title[strings.ReplaceAll(cell, " ", "")] = index
}
var fTReports []*model.Report
for i := 1; i < len(rows); i++ {
if rows[i][0] == "" {
break
}
orderDate := carbon.Parse("20" + strings.Split(rows[i][title["订单号码"]], "-")[1][:6]).Format("Y-m-d")
quantityDecimal, _ := decimal.NewFromString(rows[i][title["数量"]])
failDecimal, _ := decimal.NewFromString(rows[i][title["不良品数量"]])
missingDecimal, _ := decimal.NewFromString(rows[i][title["缺失数量"]])
fTReports = append(fTReports, &model.Report{
Product: rows[i][title["产品型号"]],
Lot: rows[i][title["LOTNO"]],
Factory: "ruisi",
TestProgram: rows[i][title["测试程序"]],
PBI: rows[i][title["订单号码"]],
SubBatch: rows[i][title["厂内批号"]],
OrderDate: orderDate,
Seal: rows[i][title["印字内容"]],
TestQuantity: rows[i][title["数量"]],
PassQuantity: quantityDecimal.Sub(failDecimal).Sub(missingDecimal).String(),
PassProbability: rows[i][title["良率"]],
Step: "FT",
})
}
global.PostGreSQL.Create(&fTReports)
}
func SuQianChangDianFT(filePath string) {
file, _ := excelize.OpenFile(filePath)
sheetName := file.GetSheetName(0)
rows, err := file.GetRows(sheetName)
if err != nil {
log.Println(err)
}
if len(rows) < 2 {
log.Println("Sheet ", sheetName, "格式不规范")
return
}
title := make(map[string]int)
for index, cell := range rows[0] {
title[strings.ReplaceAll(cell, "\n", "")] = index
}
var fTReports []*model.Report
_ = global.Oracle.Transaction(func(tx *gorm.DB) error {
for i := 1; i < len(rows); i++ {
var tcSFDFile *model.TcSfdFile
tx.Where("tc_sfd01 = ? AND tc_sfd06 = ?", rows[i][title["订单号"]], rows[i][title["下单批号"]]).Find(&tcSFDFile)
orderDate := carbon.Parse("20" + strings.Split(rows[i][title["客户订单号order number"]], "-")[1][:6]).Format("Y-m-d")
fTReports = append(fTReports, &model.Report{
Product: rows[i][title["产品型号Device"]],
Lot: rows[i][title["客户批号Customer lot"]],
Factory: "changdian",
TestProgram: rows[i][title["测试程序test program"]],
PBI: rows[i][title["客户订单号order number"]],
SubBatch: rows[i][title["扩散批号wafer lot"]],
OrderDate: orderDate,
Seal: strings.ReplaceAll(tcSFDFile.TcSfdUd02, "'", ""),
TestQuantity: rows[i][title["投料量order quantity"]],
PassQuantity: rows[i][title["测试流出数Test out"]],
PassProbability: rows[i][title["测试良率yield of test"]],
Step: "FT",
})
}
return nil
})
global.PostGreSQL.Create(&fTReports)
}
func SMCCP(filePath string) {
file, _ := excelize.OpenFile(filePath)
sheetName := file.GetSheetName(0)
rows, err := file.GetRows(sheetName)
if err != nil {
log.Println(err)
}
if len(rows) < 7 {
log.Println("Sheet ", sheetName, "格式不规范")
return
}
title := make(map[string]int)
for index, cell := range rows[0] {
title[cell] = index
}
rows[2][0] = strings.ReplaceAll(rows[2][0], "", ":")
rows[2][0] = strings.ReplaceAll(rows[2][0], ": ", ":")
infosArray := strings.Split(rows[2][0], " ")
m := make(map[string]string)
for _, infos := range infosArray {
if infos != "" {
info := strings.Split(infos, ":")
m[info[0]] = info[1]
}
}
var cpReports []*model.Report
_ = global.Oracle.Transaction(func(tx *gorm.DB) error {
for i := 1; i < len(rows); i++ {
if rows[i][0] == "Total" {
break
}
var tcSFDFile *model.TcSfdFile
tx.Where("tc_sfd01 = ? AND tc_sfd06 = ?", m["型号"], m["批号"]).Find(&tcSFDFile)
orderDate := carbon.Parse("20" + strings.Split(rows[i][title["客户订单号order number"]], "-")[1][:6]).Format("Y-m-d")
cpReports = append(cpReports, &model.Report{
Product: m["出货型号"],
Lot: rows[i][title["客户批号Customer lot"]],
Factory: "saimeike",
TestProgram: m["测试程序名"],
PBI: "",
OrderDate: orderDate,
TestQuantity: rows[i][title["Total"]],
PassQuantity: rows[i][title["Pass"]],
PassProbability: rows[i][title["良率(%)"]],
WaferID: rows[i][title["片号"]],
TestTime: rows[i][title["测试时间"]],
Step: m["测试工步"],
})
}
return nil
})
global.PostGreSQL.Create(&cpReports)
}
func SaveCP(pbi, product, lot, waferID string, report *model.Report) {
var fileHandle *model.FileHandled
global.PostGreSQL.Where("pbi = ? AND product = ? AND lot = ? AND wafer_id = ?", pbi, product, lot, waferID).
Find(&fileHandle)
f, err := os.Open(fileHandle.Path)
if err != nil {
log.Println(err)
return
}
defer f.Close()
scanner := bufio.NewScanner(f)
datas := make([][]string, 0)
fieldMap := make(map[string]int)
for scanner.Scan() {
line := scanner.Text()
s := strings.Split(line, ",")
datas = append(datas, s[:len(s)-1])
if len(datas) == 1 {
for index, cell := range s {
if index == len(s)-1 {
continue
}
fieldMap[cell] = index
}
}
}
if len(datas) >= 1 {
datas = datas[1:]
}
sbinHbinMap := make(map[string]map[string]string)
sbinHbinByte := []byte(fileHandle.SbinHbin)
_ = json.Unmarshal(sbinHbinByte, &sbinHbinMap)
binCounter := make(map[string]int)
firstBinCounter := make(map[string]int)
firstBinCounters := make(map[string]map[string]int)
var latestDatas [][]string
var firstDatas [][]string
for _, data := range datas {
isAppendData := true
for _, mainData := range latestDatas {
if mainData[0] == data[fieldMap["X_COORD"]] && mainData[1] == data[fieldMap["Y_COORD"]] {
mainData = []string{data[fieldMap["X_COORD"]], data[fieldMap["Y_COORD"]],
data[fieldMap["SITE_NUM"]], data[fieldMap["SOFT_BIN"]]}
isAppendData = false
break
}
}
if isAppendData {
latestDatas = append(latestDatas, []string{data[fieldMap["X_COORD"]], data[fieldMap["Y_COORD"]], data[fieldMap["SITE_NUM"]],
data[fieldMap["SOFT_BIN"]]})
firstDatas = append(firstDatas, []string{data[fieldMap["X_COORD"]], data[fieldMap["Y_COORD"]], data[fieldMap["SITE_NUM"]],
data[fieldMap["SOFT_BIN"]]})
}
}
for _, mainData := range latestDatas {
binCounter[mainData[3]]++
//if _, ok := siteCounters[mainData[2]]; !ok {
// siteCounters[mainData[2]] = make(map[string]int)
//}
//siteCounters[mainData[2]][mainData[3]]++
}
for _, siteData := range firstDatas {
firstBinCounter[siteData[3]]++
if _, ok := firstBinCounters[siteData[2]]; !ok {
firstBinCounters[siteData[2]] = make(map[string]int)
}
firstBinCounters[siteData[2]][siteData[3]]++
}
firstPassProbabilityDecimal := decimal.NewFromFloat(float64(firstBinCounter["1"]) / float64(len(firstDatas)) * 100).Round(2).String()
passProbabilityDecimal := decimal.NewFromFloat(float64(binCounter["1"]) / float64(len(latestDatas)) * 100).Round(2).String()
global.PostGreSQL.Model(&report).Updates(map[string]interface{}{
"test_quantity": strconv.Itoa(len(latestDatas)),
"first_pass_quantity": strconv.Itoa(firstBinCounter["1"]),
"first_pass_probability": firstPassProbabilityDecimal,
"pass_quantity": strconv.Itoa(binCounter["1"]),
"pass_probability": passProbabilityDecimal + "%",
})
var binFail []*model.BinFail
for bin, num := range binCounter {
binFail = append(binFail, &model.BinFail{
ReportID: report.ID,
HardBin: sbinHbinMap[bin]["HBin"],
SoftBin: bin,
Quantity: strconv.Itoa(num),
})
}
var siteReports []*model.ReportSites
for site := range firstBinCounters {
siteReports = append(siteReports, &model.ReportSites{
ReportID: report.ID,
Site: site,
})
}
global.PostGreSQL.Create(&siteReports)
siteReports = []*model.ReportSites{}
global.PostGreSQL.Where("report_id = ?", report.ID).Find(&siteReports)
for _, siteReport := range siteReports {
var sum, pass int
for bin, num := range firstBinCounters[siteReport.Site] {
sum += num
if bin == "1" {
pass += num
}
binFail = append(binFail, &model.BinFail{
ReportID: report.ID,
ReportSiteID: siteReport.ID,
HardBin: sbinHbinMap[bin]["HBin"],
SoftBin: bin,
Quantity: strconv.Itoa(num),
})
}
sumDecimal := decimal.NewFromInt(int64(sum))
passDecimal := decimal.NewFromInt(int64(pass))
global.PostGreSQL.Model(&siteReport).Updates(map[string]interface{}{
"test_quantity": sumDecimal.String(),
"pass_quantity": passDecimal.String(),
"pass_probability": passDecimal.Div(sumDecimal).Mul(decimal.NewFromInt(100)).Round(2).String() + "%",
})
}
global.PostGreSQL.Create(&binFail)
}
func SaveFT(report *model.Report) { //pbi, product, lot, subBatch string,
var ftFile *model.FileHandled
global.PostGreSQL.Where("pbi = ? AND product = ? AND lot = ? AND sub_batch = ? AND step = ?",
report.PBI, report.Product, report.Lot, report.SubBatch, "FT").Find(&ftFile)
ft, err := os.Open(ftFile.Path)
if err != nil {
log.Println(err)
return
}
defer ft.Close()
scanner := bufio.NewScanner(ft)
datas := make([][]string, 0)
fieldMap := make(map[string]int)
for scanner.Scan() {
line := scanner.Text()
s := strings.Split(line, ",")
datas = append(datas, s[:len(s)-1])
if len(datas) == 1 {
for index, cell := range s {
if index == len(s)-1 {
continue
}
fieldMap[cell] = index
}
}
}
if len(datas) >= 1 {
datas = datas[1:]
}
sbinHbinMap := make(map[string]map[string]string)
sbinHbinByte := []byte(ftFile.SbinHbin)
_ = json.Unmarshal(sbinHbinByte, &sbinHbinMap)
binCounter := make(map[string]int)
siteCounters := make(map[string]map[string]int)
for _, data := range datas {
binCounter[data[fieldMap["SOFT_BIN"]]]++
if _, ok := siteCounters[data[fieldMap["SITE_NUM"]]]; !ok {
siteCounters[data[fieldMap["SITE_NUM"]]] = make(map[string]int)
}
siteCounters[data[fieldMap["SITE_NUM"]]][data[fieldMap["SOFT_BIN"]]]++
}
var rtFile *model.FileHandled
var passCounter int
if !errors.Is(global.PostGreSQL.Where("pbi = ? AND product = ? AND lot = ? AND sub_batch = ? AND step = ?",
report.PBI, report.Product, report.Lot, report.SubBatch, "RT").
Find(&rtFile).Error, gorm.ErrRecordNotFound) {
rt, err := os.Open(rtFile.Path)
if err != nil {
log.Println(err)
}
defer rt.Close()
rtScanner := bufio.NewScanner(rt)
rtDatas := make([][]string, 0)
rtFieldMap := make(map[string]int)
for rtScanner.Scan() {
line := rtScanner.Text()
s := strings.Split(line, ",")
rtDatas = append(rtDatas, s[:len(s)-1])
if len(rtDatas) == 1 {
for index, cell := range s {
if index == len(s)-1 {
continue
}
rtFieldMap[cell] = index
}
}
}
if len(rtDatas) >= 1 {
rtDatas = rtDatas[1:]
}
for _, rtData := range rtDatas {
if rtData[rtFieldMap["SOFT_BIN"]] == "1" {
passCounter++
}
}
}
firstPassProbabilityDecimal := decimal.NewFromFloat(float64(binCounter["1"]) / float64(len(datas)) * 100).Round(2).String()
passProbabilityDecimal := decimal.NewFromFloat(float64(binCounter["1"]+passCounter) / float64(len(datas)) * 100).Round(2).String()
global.PostGreSQL.Model(&report).Updates(map[string]interface{}{
"test_quantity": strconv.Itoa(len(datas)),
"first_pass_quantity": strconv.Itoa(binCounter["1"]),
"first_pass_probability": firstPassProbabilityDecimal + "%",
"pass_quantity": strconv.Itoa(binCounter["1"] + passCounter),
"pass_probability": passProbabilityDecimal + "%",
})
var binFail []*model.BinFail
for bin, num := range binCounter {
binFail = append(binFail, &model.BinFail{
ReportID: report.ID,
HardBin: sbinHbinMap[bin]["HBin"],
SoftBin: bin,
Quantity: strconv.Itoa(num),
})
}
var siteReports []*model.ReportSites
for site := range siteCounters {
siteReports = append(siteReports, &model.ReportSites{
ReportID: report.ID,
Site: site,
})
}
global.PostGreSQL.Create(&siteReports)
siteReports = []*model.ReportSites{}
global.PostGreSQL.Where("report_id = ?", report.ID).Find(&siteReports)
for _, siteReport := range siteReports {
var sum, pass int
for bin, num := range siteCounters[siteReport.Site] {
sum += num
if bin == "1" {
pass += num
}
binFail = append(binFail, &model.BinFail{
ReportID: report.ID,
ReportSiteID: siteReport.ID,
HardBin: sbinHbinMap[bin]["HBin"],
SoftBin: bin,
Quantity: strconv.Itoa(num),
})
}
sumDecimal := decimal.NewFromInt(int64(sum))
passDecimal := decimal.NewFromInt(int64(pass))
global.PostGreSQL.Model(&siteReport).Updates(map[string]interface{}{
"test_quantity": sumDecimal.String(),
"pass_quantity": passDecimal.String(),
"pass_probability": passDecimal.Div(sumDecimal).Mul(decimal.NewFromInt(100)).Round(2).String() + "%",
})
}
global.PostGreSQL.Create(&binFail)
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,21 @@
package test_data
import (
"errors"
"testData/model"
"testData/repository"
)
func HandleUploadFiles(fileTexts []*model.FileText, step, machine string) error {
if step == "" {
return errors.New("未输入工序")
}
for _, fileText := range fileTexts {
if machine == "STS8200" {
repository.HandleSTS8200Excel(fileText, step)
} else if machine == "TQT601" {
repository.HandlerTQT601Excel(fileText, step)
}
}
return nil
}

19
repository/user.go Normal file
View File

@ -0,0 +1,19 @@
package repository
import (
"errors"
"testData/global"
"testData/model"
)
// 用户中心 通过ID获取用户信息
func GetUserByID(id uint) (err error, user *model.User) {
var u model.User
if err = global.BaseDB.Preload("Department").Preload("Departments").Preload("Position").Preload("Role").First(&u, id).Error; err != nil {
return errors.New("用户不存在"), &u
}
if !u.Active {
return errors.New("账号已被取消激活,若有疑问请联系管理员"), nil
}
return nil, &u
}

29
repository/xinde.go Normal file
View File

@ -0,0 +1,29 @@
package repository
import (
"path"
"strings"
"testData/global"
"testData/model"
)
// XinDe 芯德
func XinDe() {
var fileTexts []*model.FileText
global.PostGreSQL.
Where("factory = ?", "xinde").Order("mod_time").Find(&fileTexts)
for _, fileText := range fileTexts {
//fileText.Name = strings.ToLower(fileText.Name)
//if path.Ext(fileText.Name) != ".csv" && path.Ext(fileText.Name) != ".xls" && path.Ext(fileText.Name) != ".xlsx" {
// continue
//}
if strings.ToLower(path.Ext(fileText.Name)) != ".csv" &&
strings.ToLower(path.Ext(fileText.Name)) != ".xls" && strings.ToLower(path.Ext(fileText.Name)) != ".xlsx" {
continue
}
if fileText.ProductName == "" || fileText.Lot == "" {
continue
}
HandleSTS8200Excel(fileText, "")
}
}

15
request/casbin.go Normal file
View File

@ -0,0 +1,15 @@
package request
// Casbin info structure
type CasbinInfo struct {
//ApiId uint `json:"api_id" validate:"required" label:"API—ID"` // API ID
Path string `json:"path" validate:"required" label:"路径"` // 路径
Method string `json:"method" validate:"required" label:"方法"` // 方法
}
// Casbin structure for input parameters
type CasbinInReceive struct {
AuthorityId string `json:"role_id" validate:"required" label:"权限id"` // 权限id
KeyWord string `json:"key_word"`
CasbinInfos []CasbinInfo `json:"apis"`
}

146
request/chart.go Normal file
View File

@ -0,0 +1,146 @@
package request
// QuerySelection 查询参数
type QuerySelection struct {
Product string `json:"product"` // 产品型号
Lot string `json:"lot"` // 批号
PBI string `json:"pbi"` // PBI
SubBatch string `json:"sub_batch"` // 子批号
Step string `json:"step"` // 工序
WaferID string `json:"wafer_id"` // 片号
}
// Histogram 直方图
type Histogram struct {
Selections []string `json:"selections"` // 参数
Product string `json:"product"` // 产品型号
Lot string `json:"lot"` // 批号
PBI string `json:"pbi"` // PBI
SubBatch []string `json:"sub_batch"` // 子批号
WaferID []string `json:"wafer_id"` // 片号
Step string `json:"step"` // 工序
Site []string `json:"site"`
Bin []string `json:"bin"`
Offset float64 `json:"offset"` // 偏移量
Average float64 `json:"average"`
StandardDeviation float64 `json:"standard_deviation"`
SpliteSubBatch bool `json:"splite_sub_batch"`
OnlyPass bool `json:"only_pass"`
SpliteSite bool `json:"splite_site"`
XMax string `json:"x_max"`
XMin string `json:"x_min"`
}
// Scatter 散点图
type Scatter struct {
//X string `json:"x"`
//Y string `json:"y"`
//Selections []string `json:"selections"` // 参数
XYSelection []XYSelection `json:"xy_selection"`
Product string `json:"product"` // 产品型号
Lot string `json:"lot"` // 批号
PBI string `json:"pbi"` // PBI
SubBatch []string `json:"sub_batch"` // 子批号
WaferID []string `json:"wafer_id"`
Step string `json:"step"` // 工序
Site []string `json:"site"`
Bin []string `json:"bin"`
SpliteSubBatch bool `json:"splite_sub_batch"`
OnlyPass bool `json:"only_pass"`
SpliteSite bool `json:"splite_site"`
}
type XYSelection struct {
X string `json:"x"`
Y string `json:"y"`
}
type Pie struct {
Selection string `json:"selection"` // 参数
Product string `json:"product"` // 产品型号
Lot string `json:"lot"` // 批号
PBI string `json:"pbi"` // PBI
SubBatch string `json:"sub_batch"` // 子批号
Max string `json:"max"` // 最大值
Min string `json:"min"` // 最小值
Step string `json:"step"` // 工序
Site []string `json:"site"`
Bin []string `json:"bin"`
PieInterval []PieInterval `json:"pie_interval"` // 分区间
}
type PieInterval struct {
Name string `json:"name"` // 区间名称
Max string `json:"max"` // 最大值
Min string `json:"min"` // 最小值
}
type Line struct {
Selection string `json:"selection"` // 参数
Product string `json:"product"` // 产品型号
Lot string `json:"lot"` // 批号
PBI string `json:"pbi"` // PBI
SubBatch string `json:"sub_batch"` // 子批号
Step string `json:"step"` // 工序
Site []string `json:"site"`
Bin []string `json:"bin"`
Offset string `json:"offset"` // 偏移量
}
type CPMap struct {
PBI string `json:"pbi"`
Selection []string `json:"selection"` // 参数
Product string `json:"product"` // 产品型号
SubBatch string `json:"sub_batch"` // 子批号
Lot string `json:"lot"` // 批号
WaferID string `json:"wafer_id"` // 片号
Step string `json:"step"` // 工序
Site []string `json:"site"`
SBin []string `json:"sbin"`
HBin []string `json:"hbin"`
SBinColor []CPMapColor `json:"sbin_color"`
HBinColor []CPMapColor `json:"hbin_color"`
SelectionColor []SelectionColor `json:"selection_color"`
}
type LogSiteChart struct {
Product string `json:"product"`
Lot string `json:"lot"`
PBI string `json:"pbi"`
SubBatch string `json:"sub_batch"` // 子批
Step string `json:"step"` // 工序
Site []string `json:"site"`
Selection string `json:"selection"`
ContentType string `json:"content_type"` // 内容类型
Bin []string `json:"bin"`
}
type ProductInInterval struct {
Product string `json:"product"`
Bin []string `json:"bin"`
}
type CPMapColor struct {
Color string `json:"color"` // Bin颜色
Name string `json:"name"` // Bin名称
}
type SelectionColor struct {
Name string `json:"name"` // 参数名称
Color string `json:"color"` // 参数颜色
Max string `json:"max"` // 参数范围最大值
Min string `json:"min"` // 参数范围最小值
}
type SelectionLimit struct {
PBI string `json:"pbi"`
Product string `json:"product"`
Lot string `json:"lot"`
SubBatch string `json:"sub_batch"` // 子批
WaferID string `json:"wafer_id"`
Step string `json:"step"` // 工序
Selection string `json:"selection"`
Site []string `json:"site"`
SBin []string `json:"sbin"`
HBin []string `json:"hbin"`
}

22
request/report.chart.go Normal file
View File

@ -0,0 +1,22 @@
package request
type PackagePassProbabilityLine struct {
Product []string `json:"product"` // 成品型号
Lot []string `json:"lot"` // 晶圆批次
Package []string `json:"package"` // 封装形式
Factory []string `json:"factory"` // 封装厂
OrderDateStart string `json:"order_date_start"` // 下单日期开始时间
OrderDateEnd string `json:"order_date_end"` // 下单日期结束时间
DateSize string `json:"date_size"` // 时间大小
}
type PassProbabilityByFactory struct {
Factory string `json:"factory"` // 封装厂
Type string `json:"type" validate:"required"`
}
type PassProbabilityByProduct struct {
Product string `json:"product" validate:"required"` // 成品型号
Factory string `json:"factory"` // 封装厂
Type string `json:"type" validate:"required"`
}

Some files were not shown because too many files have changed in this diff Show More