From a03d58eb1adc267952c4263fb1494ce11420b353 Mon Sep 17 00:00:00 2001 From: Leo Date: Thu, 24 Apr 2025 13:37:17 +0800 Subject: [PATCH] feature: erp mat --- cmd/erp_mat.go | 28 ++++++++++ erp-mat/common/excelkit.go | 101 +++++++++++++++++++++++++++++++++ erp-mat/common/types.go | 111 +++++++++++++++++++++++++++++++++++++ 3 files changed, 240 insertions(+) create mode 100644 cmd/erp_mat.go create mode 100644 erp-mat/common/excelkit.go create mode 100644 erp-mat/common/types.go diff --git a/cmd/erp_mat.go b/cmd/erp_mat.go new file mode 100644 index 0000000..ff249ca --- /dev/null +++ b/cmd/erp_mat.go @@ -0,0 +1,28 @@ +package cmd + +import ( + "cu-helper/erp-mat/common" + "github.com/mizuki1412/go-core-kit/init/initkit" + "github.com/spf13/cobra" +) + +//erp剩余材料按类型统计 + +func init() { + rootCmd.AddCommand(erpMatCmd) + defFlagsErp(erpMatCmd) +} + +var erpMatCmd = &cobra.Command{ + Use: "mat", + Short: "Generate erp materials remain list", + Run: func(cmd *cobra.Command, args []string) { + initkit.BindFlags(cmd) + common.GenExcelFile() + }, +} + +func defFlagsErp(cmd *cobra.Command) { + cmd.Flags().String("folderPath", "", "erp导出文件夹路径") + cmd.Flags().String("templatePath", "", "模板路径") +} diff --git a/erp-mat/common/excelkit.go b/erp-mat/common/excelkit.go new file mode 100644 index 0000000..a1fab67 --- /dev/null +++ b/erp-mat/common/excelkit.go @@ -0,0 +1,101 @@ +package common + +import ( + "fmt" + "github.com/mizuki1412/go-core-kit/class/exception" + "github.com/mizuki1412/go-core-kit/library/mathkit" + "github.com/mizuki1412/go-core-kit/service/configkit" + "github.com/mizuki1412/go-core-kit/service/logkit" + "github.com/spf13/cast" + "github.com/xuri/excelize/v2" + "os" + "path/filepath" + "strings" + "time" +) + +type summary struct { + Quantity float64 + Amount float64 +} + +func GenExcelFile() { + folderPath := cast.ToString(configkit.Get("folderPath", "")) + if folderPath == "" { + panic(exception.New("folder path is empty")) + } + templatePath := cast.ToString(configkit.Get("templatePath", "")) + if templatePath == "" { + panic(exception.New("templatePath is empty")) + } + files, err := os.ReadDir(folderPath) + if err != nil { + panic(exception.New(err.Error())) + } + f, err := excelize.OpenFile(templatePath) + if err != nil { + panic(exception.New(err.Error())) + } + // 存储按列号汇总的数据 + index := 3 + for _, file := range files { + if !file.IsDir() && strings.HasSuffix(file.Name(), ".xlsx") { + filePath := filepath.Join(folderPath, file.Name()) + logkit.Info("处理文件:" + filePath) + summaryMap, projectName := processFile(filePath) + for col, s := range summaryMap { + f.SetCellValue("汇总表", fmt.Sprintf("A%d", index), projectName) + f.SetCellValue("汇总表", col+fmt.Sprintf("%d", index), cast.ToFloat64(mathkit.FloatRound(s.Quantity, 2))) + f.SetCellValue("汇总表", col+fmt.Sprintf("%d", index+1), cast.ToFloat64(mathkit.FloatRound(s.Amount, 2))) + } + index += 2 + } + } + // Save the file + if err := f.SaveAs("/Users/leo/Documents/ERP材料核对/材料汇总(" + time.Now().Format("1月2日") + ").xlsx"); err != nil { + panic(exception.New(err.Error())) + } + logkit.Info("生成结束...") +} + +// 处理单个excel +func processFile(filePath string) (map[string]*summary, string) { + f, err := excelize.OpenFile(filePath) + if err != nil { + panic(exception.New(err.Error())) + } + defer f.Close() + sheetList := f.GetSheetList() + if len(sheetList) == 0 { + panic(exception.New("无Sheet")) + } + sheet := sheetList[0] //获取第一个Sheet + projectName, _ := f.GetCellValue(sheet, "B3") + summaryMap := make(map[string]*summary) + row := 5 + for { + eCell, err := f.GetCellValue(sheet, fmt.Sprintf("E%d", row)) + if err != nil { + panic(exception.New(err.Error())) + } + if eCell == "" { + break + } + kCell, _ := f.GetCellValue(sheet, fmt.Sprintf("K%d", row)) + mCell, _ := f.GetCellValue(sheet, fmt.Sprintf("M%d", row)) + quantity := cast.ToFloat64(kCell) + amount := cast.ToFloat64(mCell) + col := getMatType(eCell) + if strings.Contains(col, "~") { + quantity /= 1000 + col = strings.ReplaceAll(col, "~", "") + } + if summaryMap[col] == nil { + summaryMap[col] = &summary{} + } + summaryMap[col].Quantity += quantity + summaryMap[col].Amount += amount + row++ + } + return summaryMap, projectName +} diff --git a/erp-mat/common/types.go b/erp-mat/common/types.go new file mode 100644 index 0000000..267a106 --- /dev/null +++ b/erp-mat/common/types.go @@ -0,0 +1,111 @@ +package common + +import "github.com/mizuki1412/go-core-kit/class/exception" + +//物料描述 + +func getMatType(matName string) string { + switch matName { + case "光缆_GYTA-4B1.3": + return "C" + case "光缆_GYTA-4B1.3(m)": + return "C~" + case "光缆_GYTA-6B1.3": + return "D" + case "光缆_GYTA-6B1.3(m)": + return "D~" + case "光缆_GYTA-12B1.3", "光缆_GYTS - 12B1.3": + return "E" + case "光缆_GYTA-12B1.3(m)": + return "E~" + case "光缆_GYTA-24B1.3", "光缆_GYTA53-24B1.3": + return "G" + case "光缆_GYTA-24B1.3(m)": + return "G~" + case "光缆_GYTA-48B1.3": + return "I" + case "光缆_GYTA-48B1.3(m)": + return "I~" + case "光缆_单根钢丝加强件、低烟无卤阻燃聚烯烃护套、通信用室内蝶形引入光缆_GJXH 1B6a2(米)": + return "L" + case "光分路器_盒式封装(报价包括SC连接器插头,以1.5m长的G.657A2(B6a2)、d2.0mm尾纤为基础) 1×2": + return "M" + case "光分路器_插片式封装(报价包括光纤适配器,以1.5m长的G.657A2(B6a2)、d2.0mm尾纤,SC/UPC类型适配器及插头为基础) 1×4", "光分路器_盒式封装(报价包括SC连接器插头,以1.5m长的G.657A2(B6a2)、d2.0mm尾纤为基础) 1×4", "光分路器_插片式封装 1×4": + return "N" + case "光分路器_盒式封装(报价包括SC连接器插头,以1.5m长的G.657A2(B6a2)、d2.0mm尾纤为基础) 1×8", "光分路器_托盘式封装(报价包括光纤适配器,以1.5m长的G.657A2(B6a2)、d2.0mm尾纤,SC/UPC类型适配器及插头为基础) 1×8", "光分路器_PLC 盒式 1×8 FC/UPC d2.0 1.5m", "光分路器_PLC 盒式 1×8 SC/UPC d2.0 1.5m", "光分路器_插片式封装(报价包括光纤适配器,以1.5m长的G.657A2(B6a2)、d2.0mm尾纤,SC/UPC类型适配器及插头为基础) 1×8": + return "O" + case "光分路器_盒式封装(报价包括SC连接器插头,以1.5m长的G.657A2(B6a2)、d2.0mm尾纤为基础) 1×16", "光分路器_托盘式封装(报价包括光纤适配器,以1.5m长的G.657A2(B6a2)、d2.0mm尾纤,SC/UPC类型适配器及插头为基础) 1×16", "光分路器_盒式封装 1×16", "光分路器_托盘式封装 1×16": + return "P" + case "光分路器_盒式封装(报价包括SC连接器插头,以1.5m长的G.657A2(B6a2)、d2.0mm尾纤为基础) 1×32", "光分路器_托盘式封装(报价包括光纤适配器,以1.5m长的G.657A2(B6a2)、d2.0mm尾纤,SC/UPC类型适配器及插头为基础) 1×32", "光分路器_PLC 盒式 1×32 FC/UPC d2.0 1.5m": + return "Q" + case "光分路器_盒式封装(报价包括SC连接器插头,以1.5m长的G.657A2(B6a2)、d2.0mm尾纤为基础) 1×64", "光分路器_托盘式封装(报价包括光纤适配器,以1.5m长的G.657A2(B6a2)、d2.0mm尾纤,SC/UPC类型适配器及插头为基础) 1×64", "光分路器_盒式封装 1×64", "光分路器_托盘式封装 1×64": + return "R" + case "光缆交接箱满配箱型005:传统型-落地式-复合材料(SMC)箱体-144芯_1030×570×310(含底座)", "144芯传统光缆交接箱(SMC)_SC或FC型_含底座、14块12芯熔配一体化托盘组件(束状纤)、12个直熔单元": + return "T" + case "光缆交接箱满配箱型006:传统型-落地式-复合材料(SMC)箱体-288芯_1550×760×370(含底座)", "288芯传统光缆交接箱(SMC)_SC或FC型_含底座、28块12芯熔配一体化托盘组件(束状纤)、12个直熔单元": + return "U" + case "光缆交接箱满配箱型008:传统型-落地式-复合材料(SMC)箱体-576芯(双面)_1550×760×630(含底座)", "576芯双面传统光缆交接箱(SMC)_SC或FC型_含底座、56块12芯熔配一体化托盘组件(束状纤)、24个直熔单元": + return "V" + case "SMC非金属光缆分纤箱-16路壁挂/抱杆_385x295x110mm-2个1:8插片式安装位-满配", "SMC非金属光缆分纤箱-12芯壁挂/抱杆_ 345x235x100mm-1个1:8盒式安装位-满配", "室外型壁挂式光纤分线箱(镀锌板)_12芯": + return "W" + case "室外型壁挂式光纤分线箱(镀锌板)_24芯": + return "X" + case "光缆接头盒_双端 12芯 4孔 架空", "光缆终端盒_12芯(含法兰盘/适配器型、金属)", "光缆接头盒_双端 12芯 4孔 管道": + return "AE" + case "光缆接头盒_双端 24芯 4孔 管道", "光缆接头盒_双端 24芯 4孔 架空": + return "AF" + case "光缆接头盒_双端 48芯 4孔 架空": + return "AG" + case "光跳纤_SC/PC接头": + return "AU" + case "基准光跳纤(1米,外护套3mm,不含接头)_G.652型": + return "AV" + case "光跳纤_FC/PC接头": + return "AW" + case "光跳纤_FC-FC 2M(G.652型 外护套2mm)", "光跳纤_FC-FC 2M(G.652型 外护套3mm)", "光跳纤_FC-FC 2M(G.652型 外护套3mm)_光跳纤_FC-FC 2M(G.652型 外护套3mm)": + return "AH" + case "光跳纤_FC-SC 2M(G.652型 外护套2mm)", "光跳纤_FC-SC 2M(G.652型 外护套3mm)_光跳纤_FC-SC 2M(G.652型 外护套3mm)": + return "AI" + case "光跳纤_FC-FC 3M(G.652型 外护套2mm)", "光跳纤_FC-FC 3M(G.652型 外护套3mm)": + return "AK" + case "光跳纤_FC-SC 3M(G.652型 外护套2mm)", "光跳纤_FC-SC 3M(G.652型 外护套3mm)": + return "AL" + case "光跳纤_FC-SC 15M(G.652型 外护套3mm)": + return "AR" + case "光跳纤_SC-SC 1M(G.652型 外护套3mm)": + return "AT" + case "光跳纤_SC-SC 2M(G.652型 外护套2mm)", "光跳纤_SC-SC 2M(G.652型 外护套3mm)", "光跳纤_SC-SC 2M(G.652型 外护套3mm)_光跳纤_SC-SC 2M(G.652型 外护套3mm)": + return "AJ" + case "光跳纤_SC-SC 3M(G.652型 外护套3mm)": + return "AM" + case "光纤配线架_12芯束状尾纤_FC/PC_1.0m(0.9mm)_公开市场": + return "AX" + case "光纤配线架_熔配一体化托盘12芯_公开市场", "综合配线架_熔配一体化托盘 12芯_公开市场": + return "AY" + case "熔配一体化子框_48芯": + return "AZ" + case "光纤配线架_2000×840×300mm(线路侧)配置-满配576芯_FC型,含8个72芯机框,48块12芯熔配一体化托盘组件(束状纤)", "光纤配线架_2200x600x300mm(线路侧)配置-满配504芯_FC型,含42块12芯熔配一体化托盘组件(束状纤)、3个存储单元": + return "BA" + case "华为-扩容-MDU-GPON MDU-LAN设备B+光模块_OSG020201(含华为接入FTTx及铜线软件V2.00)", "华为-扩容-MDU-XG PON MDU-LAN设备N1光模块_OSX10GG201(含华为接入FTTx及铜线软件V2.00)", "扩容-MDU-10G EPON MDU-LAN设备PR30光模块_OSX10GE202(含华为接入FTTx及铜线软件V2.00)", "扩容-MDU-XG PON MDU-LAN设备N1光模块_OSX10GG201(含华为接入FTTx及铜线软件V2.00)": + return "BB" + case "华为-扩容-MDU-XG PON MDU-LAN盒式设备(24端口GE)_MA5821-24*GE口(含华为接入FTTx及铜线软件V2.00)", "扩容-MDU-XG PON MDU-LAN盒式设备(24端口GE)_MA5821-24*GE口(含华为接入FTTx及铜线软件V2.00)": + return "BC" + case "华为-扩容-MDU-XG PON MDU-LAN盒式设备(24端口GE+24端口POTS)_MA5822-24*GE口+24*POTS口(含华为接入FTTx及铜线软件V2.00)", "扩容-MDU-XG PON MDU-LAN盒式设备(24端口GE+24端口POTS)_MA5822-24*GE口+24*POTS口(含华为接入FTTx及铜线软件V2.00)": + return "BD" + case "扩容-MDU-10G PON MDU-LAN插卡设备POTS业务接口板(64路POTS)_MA5616-ASPB(含华为接入FTTx及铜线软件V2.00)", "扩容-MDU-10G PON MDU-LAN插卡设备系统软件_MA5616-H83SSYS01600(含华为接入FTTx及铜线软件V2.00)", "扩容-MDU-10G PON MDU-LAN插卡设备主机_MA5616(含华为接入FTTx及铜线软件V2.00)", "扩容-MDU-10G PON MDU-LAN插卡设备主控板(含单PON口,适用于XG PON)_MA5616-H833XP1A02(含华为接入FTTx及铜线软件V2.00)": + return "BE" + case "华为-扩容-安装材料费_安装材料费(1%)", "安装材料费(以成交价为基准进行计算,仅在新建场景使用)_安装材料费(1%)": + return "BF" + case "华为-扩容-督导调测费_督导费(3%)", "督导调测费(以成交价为基准进行计算)_督导费(3%)": + return "BG" + case "光纤收发器_EB200-SD1", "光纤收发器_EB200-SD1C", "光纤收发器_EB200-SS1": + return "BH" + case "金属光缆终端盒-12芯壁挂282*135*50mm_可装适配器12芯-满配": + return "BI" + case "数字通信电缆_超5类4对UTP电缆 HSYV5E 4*2*0.5": + return "BJ" + default: + panic(exception.New(matName + " 无该类型材料,请添加!!!")) + return "" + } +}