package controllers import ( "ERP_storage/Nats" "ERP_storage/Nats/NatsServer" "ERP_storage/conf" "ERP_storage/dto" "ERP_storage/logs" "ERP_storage/models/Account" "ERP_storage/models/Basic" "ERP_storage/models/Contract" "ERP_storage/models/Stock" "errors" "fmt" "math" "os" "sort" "strconv" "strings" "time" "github.com/beego/beego/v2/adapter/orm" beego "github.com/beego/beego/v2/server/web" "github.com/robfig/cron/v3" "github.com/xuri/excelize/v2" natslibs "gogs.baozhida.cn/zoie/ERP_libs/Nats" userlibs "gogs.baozhida.cn/zoie/ERP_libs/User" "gogs.baozhida.cn/zoie/ERP_libs/lib" ) type StockController struct { beego.Controller User userlibs.User } func (c *StockController) Prepare() { c.User = *Account.User_r } func (c *StockController) Device_List() { // 分页参数 初始化 page, _ := c.GetInt("page") if page < 1 { page = 1 } page_z, _ := c.GetInt("page_z") if page_z < 1 { page_z = conf.Page_size } T_state, _ := c.GetInt("T_state") T_name := c.GetString("T_name") T_product_name := c.GetString("T_product_name") // 产品名称 T_product_model := c.GetString("T_product_model") // 产品型号 DeviceDao := Stock.NewDevice(orm.NewOrm()) R_List, R_cnt := DeviceDao.Read_Device_List(T_name, T_product_name, T_product_model, T_state, page, page_z) var r_jsons lib.R_JSONS r_jsons.Num = R_cnt r_jsons.Data = R_List r_jsons.Page = page r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(page_z))) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons} c.ServeJSON() return } func (c *StockController) Device_Excel() { T_state, _ := c.GetInt("T_state") T_name := c.GetString("T_name") T_product_name := c.GetString("T_product_name") // 产品名称 T_product_model := c.GetString("T_product_model") // 产品型号 DeviceDao := Stock.NewDevice(orm.NewOrm()) R_List, _ := DeviceDao.Read_Device_List(T_name, T_product_name, T_product_model, T_state, 0, 9999) // 生成Excel文件名 filename := fmt.Sprintf("设备列表(%s)", lib.GetRandstring(6, "0123456789", 0)) // 创建Excel文件 f := excelize.NewFile() // 设置样式 Style1, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Bold: true, Size: 14, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"}, }) Style2, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Bold: true, Size: 10, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true}, 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}, }, }) Style3, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Size: 10, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true}, 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}, }, }) // 设置工作表名称 f.SetSheetName("Sheet1", "设备列表") // 设置标题 f.MergeCell("设备列表", "A1", "M1") f.SetRowStyle("设备列表", 1, 1, Style1) f.SetCellValue("设备列表", "A1", "宝智达科技设备列表") f.SetRowHeight("设备列表", 1, 30) // 设置表头 f.SetCellStyle("设备列表", "A2", "M2", Style2) f.SetRowHeight("设备列表", 2, 20) // 设置表头内容 f.SetCellValue("设备列表", "A2", "序号") f.SetCellValue("设备列表", "B2", "合同编号") f.SetCellValue("设备列表", "C2", "出库单号") f.SetCellValue("设备列表", "D2", "关联项目") f.SetCellValue("设备列表", "E2", "产品名称") f.SetCellValue("设备列表", "F2", "产品分类") f.SetCellValue("设备列表", "G2", "产品型号") f.SetCellValue("设备列表", "H2", "产品规格") f.SetCellValue("设备列表", "I2", "设备SN") f.SetCellValue("设备列表", "J2", "模组imei") f.SetCellValue("设备列表", "K2", "物联网卡号") f.SetCellValue("设备列表", "L2", "设备编号") f.SetCellValue("设备列表", "M2", "状态") // 设置列宽 f.SetColWidth("设备列表", "A", "A", 8) // 序号 f.SetColWidth("设备列表", "B", "B", 15) // 合同编号 f.SetColWidth("设备列表", "C", "C", 15) // 出库单号 f.SetColWidth("设备列表", "D", "D", 20) // 关联项目 f.SetColWidth("设备列表", "E", "E", 20) // 产品名称 f.SetColWidth("设备列表", "F", "F", 15) // 产品分类 f.SetColWidth("设备列表", "G", "G", 15) // 产品型号 f.SetColWidth("设备列表", "H", "H", 15) // 产品规格 f.SetColWidth("设备列表", "I", "I", 20) // 设备SN f.SetColWidth("设备列表", "J", "J", 15) // 模组imei f.SetColWidth("设备列表", "K", "K", 20) // 物联网卡号 f.SetColWidth("设备列表", "L", "L", 18) // 设备编号 f.SetColWidth("设备列表", "M", "M", 10) // 状态 // 填充数据 for i, device := range R_List { row := i + 3 // 从第3行开始填充数据 // 状态转换 stateText := "未出库" if device.T_State == 1 { stateText = "已出库" } f.SetCellStyle("设备列表", fmt.Sprintf("A%d", row), fmt.Sprintf("M%d", row), Style3) //f.SetRowHeight("设备列表", row, 20) f.SetCellValue("设备列表", fmt.Sprintf("A%d", row), i+1) // 序号 f.SetCellValue("设备列表", fmt.Sprintf("B%d", row), device.T_contract_number) // 合同编号 f.SetCellValue("设备列表", fmt.Sprintf("C%d", row), device.T_out_number) // 出库单号 f.SetCellValue("设备列表", fmt.Sprintf("D%d", row), device.T_project) // 关联项目 f.SetCellValue("设备列表", fmt.Sprintf("E%d", row), device.T_product_name) // 产品名称 f.SetCellValue("设备列表", fmt.Sprintf("F%d", row), device.T_product_class_name) // 产品分类 f.SetCellValue("设备列表", fmt.Sprintf("G%d", row), device.T_product_model) // 产品型号 f.SetCellValue("设备列表", fmt.Sprintf("H%d", row), device.T_product_spec) // 产品规格 f.SetCellValue("设备列表", fmt.Sprintf("I%d", row), device.T_sn) // 设备SN f.SetCellValue("设备列表", fmt.Sprintf("J%d", row), device.T_imei) // 模组imei f.SetCellValue("设备列表", fmt.Sprintf("K%d", row), device.T_iccid) // 物联网卡号 f.SetCellValue("设备列表", fmt.Sprintf("L%d", row), device.T_device_number) // 设备编号 f.SetCellValue("设备列表", fmt.Sprintf("M%d", row), stateText) // 状态 } // 保存文件 if err := f.SaveAs("ofile/" + filename + ".xlsx"); err != nil { fmt.Println(err) } var url string //// 上传 OSS nats := natslibs.NewNats(Nats.Nats, conf.NatsSubj_Prefix) url, is := nats.Qiniu_UploadFile(lib.GetCurrentDirectory()+"/ofile/"+filename+".xlsx", "ofile/"+filename+".xlsx") if !is { c.Data["json"] = lib.JSONS{Code: 202, Msg: "oss!"} c.ServeJSON() return } //删除目录 err := os.Remove("ofile/" + filename + ".xlsx") if err != nil { logs.Error(lib.FuncName(), err) } c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: url} c.ServeJSON() return } func (c *StockController) Device_Check() { T_sn := c.GetString("T_sn") T_type, _ := c.GetInt("T_type") //1-出库 2-入库 T_product_id, _ := c.GetInt("T_product_id") T_date := c.GetString("T_date") // 检查MQTT授权 //mqtt := Stock.Read_MqttUser(T_sn) //if len(mqtt.Username) == 0 { // c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("【%s】未授权,请先授权!", T_sn)} // c.ServeJSON() // return //} DeviceDao := Stock.NewDevice(orm.NewOrm()) date, is := lib.DateStrToTime(T_date) if !is { c.Data["json"] = lib.JSONS{Code: 202, Msg: "日期格式错误!"} c.ServeJSON() return } checkTime := date.Format("2006-01-02") + time.Now().Format(" 15:04:05") // T_State 1-已出库 2-未出库/入库 // 查询checkTime时间前最后一条记录 lastBeforeCheckTime, errBefore := DeviceDao.Read_Device_LastBeforeCheckTime(T_sn, checkTime) // 查询checkTime时间后第一条记录 firstAfterCheckTime, errAfter := DeviceDao.Read_Device_FirstAfterCheckTime(T_sn, checkTime) // 如果是入库操作 if T_type == 2 { // 根据表格逻辑判断: // 1. 时间前无数据,时间后有入库记录 if (errBefore != nil || lastBeforeCheckTime.Id == 0) && errAfter == nil && firstAfterCheckTime.T_State == 2 && len(firstAfterCheckTime.T_in_number) > 0 { c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("【%s】已入库,请勿重复提交!", T_sn)} c.ServeJSON() return } // 2. 时间前已入库 if errBefore == nil && lastBeforeCheckTime.T_State == 2 && len(lastBeforeCheckTime.T_in_number) > 0 { c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("【%s】已入库,请勿重复提交!", T_sn)} c.ServeJSON() return } // 3. 时间前已出库,时间后有入库记录 if errBefore == nil && lastBeforeCheckTime.T_State == 1 && len(lastBeforeCheckTime.T_out_number) > 0 && errAfter == nil && firstAfterCheckTime.T_State == 2 && len(firstAfterCheckTime.T_in_number) > 0 { c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("【%s】已入库,请勿重复提交!", T_sn)} c.ServeJSON() return } } // 如果是出库操作 if T_type == 1 { // 根据表格逻辑判断: // 1. 时间前无数据 -> 未入库 if errBefore != nil || lastBeforeCheckTime.Id == 0 { c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("【%s】未入库,请先入库!", T_sn)} c.ServeJSON() return } // 2. 时间前已入库,时间后有出库记录 if lastBeforeCheckTime.T_State == 2 && len(lastBeforeCheckTime.T_in_number) > 0 && errAfter == nil && firstAfterCheckTime.T_State == 1 && len(firstAfterCheckTime.T_out_number) > 0 { c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("【%s】已出库,请勿重复提交!", T_sn)} c.ServeJSON() return } // 3. 时间前已出库 if lastBeforeCheckTime.T_State == 1 && len(lastBeforeCheckTime.T_out_number) > 0 { c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("【%s】已出库,请勿重复提交!", T_sn)} c.ServeJSON() return } // 检查产品是否一致 if lastBeforeCheckTime.T_product_id != T_product_id { c.Data["json"] = lib.JSONS{Code: 202, Msg: "入库产品与出库产品不一致,请检查!"} c.ServeJSON() return } } c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"} c.ServeJSON() return } func (c *StockController) Device_Take_Stock() { T_product_name := c.GetString("T_product_name") // 产品名称 T_product_model := c.GetString("T_product_model") // 产品型号 T_sn_list := c.GetString("T_sn_list") // sn列表 DeviceDao := Stock.NewDevice(orm.NewOrm()) // 获取库存中的所有设备(如果有产品名称和型号过滤) R_List, _ := DeviceDao.Read_Device_List("", T_product_name, T_product_model, 0, 0, 9999) // 创建设备SN到设备信息的映射,用于快速查找 deviceMap := make(map[string]Stock.Device_R) // 保存在库设备列表 var inStockDevices []Stock.Device_R for _, device := range R_List { deviceMap[device.T_sn] = device // 收集所有在库设备(状态为2) if device.T_State == 2 { inStockDevices = append(inStockDevices, device) } } // 创建结果数据结构 type DeviceCheckResult struct { T_sn string `json:"t_sn"` // 设备SN T_exists bool `json:"t_exists"` // 是否存在于库存 T_state int `json:"t_state"` // 设备状态:1-已出库 2-未出库/入库 T_state_desc string `json:"t_state_desc"` // 状态描述 T_product_id int `json:"t_product_id"` // 产品ID T_product_name string `json:"t_product_name"` // 产品名称 T_product_model string `json:"t_product_model"` // 产品型号 T_iccid string `json:"t_iccid"` // SIM卡号 T_imei string `json:"t_imei"` // 模组IMEI T_in_number string `json:"t_in_number"` // 入库编号 T_out_number string `json:"t_out_number"` // 出库编号 T_from_input bool `json:"t_from_input"` // 是否来自输入列表 } // 处理每个输入的SN var results []DeviceCheckResult var processedSNs = make(map[string]bool) // 用于跟踪已处理的SN // 解析输入的SN列表(如果有) var snList []string if len(T_sn_list) > 0 { snList = lib.SplitString(T_sn_list, ",") for _, sn := range snList { sn = strings.TrimSpace(sn) if len(sn) == 0 { continue } result := DeviceCheckResult{ T_sn: sn, T_exists: false, T_from_input: true, // 标记为来自输入列表 } // 检查设备是否存在于库存 if device, exists := deviceMap[sn]; exists { result.T_exists = true result.T_state = device.T_State result.T_product_id = device.T_product_id result.T_product_name = device.T_product_name result.T_product_model = device.T_product_model result.T_iccid = device.T_iccid result.T_imei = device.T_imei result.T_in_number = device.T_in_number result.T_out_number = device.T_out_number // 设置状态描述 if device.T_State == 1 { result.T_state_desc = "已出库" } else if device.T_State == 2 { result.T_state_desc = "在库" } else { result.T_state_desc = "未知状态" } } else { // 设备不存在于库存 result.T_state_desc = "未入库" } results = append(results, result) processedSNs[sn] = true } } // 添加所有在库设备(如果还没有处理过) for _, device := range inStockDevices { // 如果这个SN已经处理过(来自输入列表),则跳过 if _, processed := processedSNs[device.T_sn]; processed { continue } result := DeviceCheckResult{ T_sn: device.T_sn, T_exists: true, T_state: device.T_State, T_state_desc: "在库", T_product_id: device.T_product_id, T_product_name: device.T_product_name, T_product_model: device.T_product_model, T_iccid: device.T_iccid, T_imei: device.T_imei, T_in_number: device.T_in_number, T_out_number: device.T_out_number, T_from_input: false, // 标记为不是来自输入列表 } results = append(results, result) } // 统计结果 totalInputCount := 0 existsCount := 0 inStockCount := 0 outStockCount := 0 notExistsCount := 0 for _, result := range results { if result.T_from_input { totalInputCount++ if result.T_exists { existsCount++ if result.T_state == 2 { inStockCount++ } else if result.T_state == 1 { outStockCount++ } } else { notExistsCount++ } } } // 组装返回数据 r_jsons := map[string]interface{}{ "devices": results, "stats": map[string]interface{}{ "total_input": totalInputCount, "exists": existsCount, "in_stock": inStockCount, "out_stock": outStockCount, "not_exists": notExistsCount, "total_in_stock": len(inStockDevices), }, } c.Data["json"] = lib.JSONS{Code: 200, Msg: "盘点完成", Data: r_jsons} c.ServeJSON() return } func (c *StockController) Stock_List() { // 分页参数 初始化 page, _ := c.GetInt("page") if page < 1 { page = 1 } page_z, _ := c.GetInt("page_z") if page_z < 1 { page_z = conf.Page_size } // 查询 T_depot_id, _ := c.GetInt("T_depot_id") // 查询 T_product_name := c.GetString("T_product_name") T_product_model := c.GetString("T_product_model") T_product_class, _ := c.GetInt("T_product_class") userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) Basic.Read_Depot_All_Map() StockDao := Stock.NewStock(orm.NewOrm()) R_List, R_cnt := StockDao.Read_Stock_List(T_depot_id, T_product_class, T_product_name, T_product_model, page, page_z) var r_jsons lib.R_JSONS r_jsons.Num = R_cnt r_jsons.Data = R_List r_jsons.Page = page r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(page_z))) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons} c.ServeJSON() return } // 修改库存排序 func (c *StockController) Stock_Edit_Sort() { T_id, _ := c.GetInt("T_id") T_sort, _ := c.GetInt("T_sort") StockDao := Stock.NewStock(orm.NewOrm()) Stock_r, err := StockDao.Read_Stock_ById(T_id) if err != nil { c.Data["json"] = lib.JSONS{Code: 203, Msg: "T_id Err!"} c.ServeJSON() return } Stock_r.T_sort = T_sort if err = StockDao.Update_Stock(Stock_r, "T_sort"); err != nil { c.Data["json"] = lib.JSONS{Code: 203, Msg: "修改失败"} c.ServeJSON() return } NatsServer.AddUserLogs(c.User.T_uuid, "库存", "修改", Stock_r) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"} c.ServeJSON() return } func (c *StockController) Stock_Detail_List() { // 查询 T_depot_id, _ := c.GetInt("T_depot_id") // 查询 T_product_id, _ := c.GetInt("T_product_id") T_start_date := c.GetString("T_start_date") T_end_date := c.GetString("T_end_date") now := time.Now() if len(T_start_date) == 0 { T_start_date = time.Date(now.Year(), 1, 1, 0, 0, 0, 0, time.Local).Format("2006-01") } else { T_start_date_t, _ := lib.DateStrToTime(T_start_date) T_start_date = T_start_date_t.Format("2006-01") } if len(T_end_date) == 0 { T_end_date = now.Format("2006-01") } else { T_end_date_t, _ := lib.DateStrToTime(T_end_date) T_end_date = T_end_date_t.Format("2006-01") } StockOutDao := Stock.NewStockOut(orm.NewOrm()) StockMonthDao := Stock.NewStockMonth(orm.NewOrm()) R_List := StockMonthDao.Read_StockMonth_List(T_depot_id, T_product_id, 0, T_start_date, T_end_date) for i := 0; i < len(R_List); i++ { R_List[i].T_project = strings.Join(StockOutDao.Read_StockOut_T_project(T_depot_id, R_List[i].T_product_id, R_List[i].T_month), "|") } c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: R_List} c.ServeJSON() return } func (c *StockController) Stock_Detail_Excel() { // 查询 T_depot_id, _ := c.GetInt("T_depot_id") T_product_id, _ := c.GetInt("T_product_id") // 查询 T_start_date := c.GetString("T_start_date") T_end_date := c.GetString("T_end_date") now := time.Now() if len(T_start_date) == 0 { T_start_date = time.Date(now.Year(), 1, 1, 0, 0, 0, 0, time.Local).Format("2006-01") } else { T_start_date_t, _ := lib.DateStrToTime(T_start_date) T_start_date = T_start_date_t.Format("2006-01") } if len(T_end_date) == 0 { T_end_date = now.Format("2006-01") } else { T_end_date_t, _ := lib.DateStrToTime(T_end_date) T_end_date = T_end_date_t.Format("2006-01") } var class_List []Basic.ProductClass_R filename := fmt.Sprintf("进销存(%s)", lib.GetRandstring(6, "0123456789", 0)) if T_product_id > 0 { product, _ := Basic.Read_Product_ById(T_product_id) filename = fmt.Sprintf("进销存-%s明细(%s)", product.T_name, lib.GetRandstring(6, "0123456789", 0)) class, _ := Basic.Read_ProductClass_ById(product.T_class) class_List = append(class_List, Basic.ProductClassToProductClass_R(class)) } else { class_List, _ = Basic.Read_ProductClass_List("", 0, 0, 9999) } f := excelize.NewFile() // 设置单元格的值 Style1, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Bold: true, Size: 12, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"}, }) Style2, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Bold: true, Size: 10, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true}, 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}, }, }) Style3, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Bold: true, Size: 10, Family: "宋体", Color: "FF0000"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true}, 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}, }, }) Style4, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Size: 10, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true}, 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}, }, }) StockMonthDao := Stock.NewStockMonth(orm.NewOrm()) StockOutDao := Stock.NewStockOut(orm.NewOrm()) var j = 0 for _, r := range class_List { StockList := StockMonthDao.Read_StockMonth_List(T_depot_id, T_product_id, r.Id, T_start_date, T_end_date) if len(StockList) == 0 { continue } if j == 0 { f.SetSheetName("Sheet1", r.T_name) } else { f.NewSheet(r.T_name) } j += 1 f.MergeCell(r.T_name, "A1", "K1") f.SetRowStyle(r.T_name, 1, 1, Style1) f.SetCellValue(r.T_name, "A1", fmt.Sprintf("宝智达科技产品进销存统计表")) f.SetRowHeight(r.T_name, 1, 30) // 这里设置表头 f.SetCellStyle(r.T_name, "A2", "K2", Style2) f.SetRowHeight(r.T_name, 2, 20) f.SetCellValue(r.T_name, "A2", "序号") f.SetCellValue(r.T_name, "B2", "产品名称") f.SetCellValue(r.T_name, "C2", "型号") f.SetCellValue(r.T_name, "D2", "规格") f.SetCellValue(r.T_name, "E2", "月份") f.SetCellValue(r.T_name, "F2", "期初库存") f.SetCellValue(r.T_name, "G2", "当月入库(正常生产新购入库产品)") f.SetCellValue(r.T_name, "H2", "退货入库(退还重新入库产品)") f.SetCellValue(r.T_name, "I2", "当月出库") f.SetCellValue(r.T_name, "J2", "期末库存") f.SetCellValue(r.T_name, "K2", "出库项目") //f.SetCellValue(r.T_name, "K2", "备注") // 设置列宽 f.SetColWidth(r.T_name, "A", "A", 10) f.SetColWidth(r.T_name, "B", "B", 10) f.SetColWidth(r.T_name, "C", "D", 10) f.SetColWidth(r.T_name, "D", "D", 10) f.SetColWidth(r.T_name, "E", "E", 10) f.SetColWidth(r.T_name, "F", "F", 10) f.SetColWidth(r.T_name, "G", "G", 10) f.SetColWidth(r.T_name, "H", "H", 10) f.SetColWidth(r.T_name, "I", "I", 10) f.SetColWidth(r.T_name, "J", "J", 10) f.SetColWidth(r.T_name, "K", "K", 70) //f.SetColWidth(r.T_name, "K", "K", 10) line := 2 // 循环写入数据 for _, v := range StockList { line++ product, _ := Basic.Read_Product_ById(v.T_product_id) f.SetCellValue(r.T_name, fmt.Sprintf("A%d", line), line-2) f.SetCellValue(r.T_name, fmt.Sprintf("B%d", line), product.T_name) f.SetCellValue(r.T_name, fmt.Sprintf("C%d", line), product.T_model) f.SetCellValue(r.T_name, fmt.Sprintf("D%d", line), product.T_spec) f.SetCellValue(r.T_name, fmt.Sprintf("E%d", line), v.T_month) f.SetCellValue(r.T_name, fmt.Sprintf("F%d", line), v.T_beginning) f.SetCellValue(r.T_name, fmt.Sprintf("G%d", line), v.T_in) f.SetCellValue(r.T_name, fmt.Sprintf("H%d", line), v.T_return) f.SetCellValue(r.T_name, fmt.Sprintf("I%d", line), v.T_out) f.SetCellValue(r.T_name, fmt.Sprintf("J%d", line), v.T_ending) if product.T_early_warning > v.T_ending { f.SetCellStyle(r.T_name, fmt.Sprintf("J%d", line), fmt.Sprintf("J%d", line), Style3) } else { f.SetCellStyle(r.T_name, fmt.Sprintf("J%d", line), fmt.Sprintf("J%d", line), Style4) } T_project := StockOutDao.Read_StockOut_T_project(T_depot_id, product.Id, v.T_month) //f.SetCellValue(r.T_name, fmt.Sprintf("J%d", line), v.T_project) f.SetCellValue(r.T_name, fmt.Sprintf("K%d", line), strings.Join(T_project, "\r\n")) } f.SetCellStyle(r.T_name, "A2", fmt.Sprintf("I%d", line), Style4) Style5, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Size: 10, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "left", Vertical: "center", WrapText: true}, 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}, }, }) f.SetCellStyle(r.T_name, "K2", fmt.Sprintf("K%d", line), Style5) } // 保存文件 if err := f.SaveAs("ofile/" + filename + ".xlsx"); err != nil { fmt.Println(err) } var url string //// 上传 OSS nats := natslibs.NewNats(Nats.Nats, conf.NatsSubj_Prefix) url, is := nats.Qiniu_UploadFile(lib.GetCurrentDirectory()+"/ofile/"+filename+".xlsx", "ofile/"+filename+".xlsx") if !is { c.Data["json"] = lib.JSONS{Code: 202, Msg: "oss!"} c.ServeJSON() return } //删除目录 err := os.Remove("ofile/" + filename + ".xlsx") if err != nil { logs.Error(lib.FuncName(), err) } c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: url} c.ServeJSON() return } func (c *StockController) StockIn_List() { // 分页参数 初始化 page, _ := c.GetInt("page") if page < 1 { page = 1 } page_z, _ := c.GetInt("page_z") if page_z < 1 { page_z = conf.Page_size } // 查询 T_depot_id, _ := c.GetInt("T_depot_id") T_start_date := c.GetString("T_start_date") T_end_date := c.GetString("T_end_date") T_name := c.GetString("T_name") T_batch_number := c.GetString("T_batch_number") userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) Basic.Read_Depot_All_Map() StockInDao := Stock.NewStockIn(orm.NewOrm()) R_List, R_cnt := StockInDao.Read_StockIn_List(T_batch_number, T_name, T_depot_id, T_start_date, T_end_date, page, page_z) var r_jsons lib.R_JSONS r_jsons.Num = R_cnt r_jsons.Data = R_List r_jsons.Page = page r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(page_z))) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons} c.ServeJSON() return } func (c *StockController) StockIn_List_Product() { // 分页参数 初始化 page, _ := c.GetInt("page") if page < 1 { page = 1 } page_z, _ := c.GetInt("page_z") if page_z < 1 { page_z = conf.Page_size } // 查询 T_depot_id, _ := c.GetInt("T_depot_id") T_name := c.GetString("T_name") T_start_date := c.GetString("T_start_date") T_end_date := c.GetString("T_end_date") T_product_name := c.GetString("T_product_name") // 产品名称 T_product_model := c.GetString("T_product_model") // 产品型号 userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) Basic.Read_Depot_All_Map() StockInDao := Stock.NewStockIn(orm.NewOrm()) R_List, R_cnt := StockInDao.Read_StockInProduct_List(T_name, T_start_date, T_end_date, T_depot_id, T_product_name, T_product_model, page, page_z) var r_jsons lib.R_JSONS r_jsons.Num = R_cnt r_jsons.Data = R_List r_jsons.Page = page r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(page_z))) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons} c.ServeJSON() return } func (c *StockController) StockIn_List_Product_Excel() { // 查询 T_depot_id, _ := c.GetInt("T_depot_id") T_name := c.GetString("T_name") T_start_date := c.GetString("T_start_date") T_end_date := c.GetString("T_end_date") T_product_name := c.GetString("T_product_name") // 产品名称 T_product_model := c.GetString("T_product_model") // 产品型号 userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) Basic.Read_Depot_All_Map() StockInDao := Stock.NewStockIn(orm.NewOrm()) R_List, _ := StockInDao.Read_StockInProduct_List(T_name, T_start_date, T_end_date, T_depot_id, T_product_name, T_product_model, 0, 9999) filename := fmt.Sprintf("入库明细单(%s)", lib.GetRandstring(6, "0123456789", 0)) f := excelize.NewFile() // 设置单元格的值 Style1, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Bold: true, Size: 12, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"}, }) Style2, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Bold: true, Size: 11, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"}, 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}, }, }) Style3, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Size: 11, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "left", Vertical: "center", WrapText: true}, 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}, }, }) f.MergeCell("Sheet1", "A1", "L1") f.SetRowStyle("Sheet1", 1, 1, Style1) f.SetCellValue("Sheet1", "A1", fmt.Sprintf("入库明细单")) f.SetRowHeight("Sheet1", 1, 30) // 这里设置表头 f.SetCellStyle("Sheet1", "A2", "L2", Style2) f.SetRowHeight("Sheet1", 2, 20) f.SetCellValue("Sheet1", "A2", "序号") f.SetCellValue("Sheet1", "B2", "入库单号") f.SetCellValue("Sheet1", "C2", "经办人") f.SetCellValue("Sheet1", "D2", "入库日期") f.SetCellValue("Sheet1", "E2", "入库仓库") f.SetCellValue("Sheet1", "F2", "入库类型") f.SetCellValue("Sheet1", "G2", "产品名称") f.SetCellValue("Sheet1", "H2", "产品型号") f.SetCellValue("Sheet1", "I2", "数量") f.SetCellValue("Sheet1", "J2", "是否关联SN") f.SetCellValue("Sheet1", "K2", "备注") f.SetCellValue("Sheet1", "L2", "SN") // 设置列宽 f.SetColWidth("Sheet1", "A", "A", 10) f.SetColWidth("Sheet1", "B", "B", 15) f.SetColWidth("Sheet1", "C", "D", 10) f.SetColWidth("Sheet1", "D", "D", 10) f.SetColWidth("Sheet1", "E", "E", 10) f.SetColWidth("Sheet1", "F", "F", 10) f.SetColWidth("Sheet1", "G", "G", 20) f.SetColWidth("Sheet1", "H", "H", 15) f.SetColWidth("Sheet1", "I", "I", 10) f.SetColWidth("Sheet1", "J", "J", 12) f.SetColWidth("Sheet1", "K", "K", 30) f.SetColWidth("Sheet1", "L", "L", 100) line := 2 for _, product := range R_List { line += 1 f.SetCellValue("Sheet1", fmt.Sprintf("A%d", line), line-2) f.SetCellValue("Sheet1", fmt.Sprintf("B%d", line), product.T_number) f.SetCellValue("Sheet1", fmt.Sprintf("C%d", line), product.T_submit_name) f.SetCellValue("Sheet1", fmt.Sprintf("D%d", line), product.T_date) f.SetCellValue("Sheet1", fmt.Sprintf("E%d", line), product.T_depot_name) var type_str string if product.T_type == 1 { type_str = "入库" } else { type_str = "退库" } f.SetCellValue("Sheet1", fmt.Sprintf("F%d", line), type_str) f.SetCellValue("Sheet1", fmt.Sprintf("G%d", line), product.T_product_name) f.SetCellValue("Sheet1", fmt.Sprintf("H%d", line), product.T_product_model) f.SetCellValue("Sheet1", fmt.Sprintf("I%d", line), product.T_num) var relation_sn string if product.T_product_relation_sn == 1 { relation_sn = "是" } else { relation_sn = "否" } f.SetCellValue("Sheet1", fmt.Sprintf("J%d", line), relation_sn) f.SetCellValue("Sheet1", fmt.Sprintf("K%d", line), product.T_remark) f.SetCellValue("Sheet1", fmt.Sprintf("L%d", line), product.T_relation_sn) } f.SetCellStyle("Sheet1", "A3", fmt.Sprintf("L%d", line), Style3) // 保存文件 if err := f.SaveAs("ofile/" + filename + ".xlsx"); err != nil { fmt.Println(err) } var url string //// 上传 OSS nats := natslibs.NewNats(Nats.Nats, conf.NatsSubj_Prefix) url, is := nats.Qiniu_UploadFile(lib.GetCurrentDirectory()+"/ofile/"+filename+".xlsx", "ofile/"+filename+".xlsx") if !is { c.Data["json"] = lib.JSONS{Code: 202, Msg: "oss!"} c.ServeJSON() return } //删除目录 err := os.Remove("ofile/" + filename + ".xlsx") if err != nil { logs.Error(lib.FuncName(), err) } c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: url} c.ServeJSON() return } func (c *StockController) StockIn_Get() { // 查询 T_number := c.GetString("T_number") o := orm.NewOrm() StockInDao := Stock.NewStockIn(o) StockInProductDao := Stock.NewStockInProduct(o) stockIn, err := StockInDao.Read_StockIn_ByT_number(T_number) if err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"} c.ServeJSON() return } productList := StockInProductDao.Read_StockInProduct_List_ByT_number(stockIn.T_number) var pList []Stock.StockInProduct_R for _, v := range productList { pList = append(pList, Stock.StockInProductToStockInProduct_R(v)) } userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) Basic.Read_Depot_All_Map() c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: Stock.StockInToStockIn_Detail(stockIn, pList)} c.ServeJSON() return } func (c *StockController) StockIn_generate_number() { StockOutDao := Stock.NewStockOut(orm.NewOrm()) rand_x := 0 T_number := "" for true { T_number = "RK-" + lib.GetRandstring(8, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", int64(rand_x)) _, err := StockOutDao.Read_StockOut_ByT_number(T_number) if err != nil && err.Error() == orm.ErrNoRows.Error() { break } rand_x += 1 } c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: T_number} c.ServeJSON() return } func (c *StockController) StockIn_Add() { o := orm.NewOrm() o.Begin() StockInDao := Stock.NewStockIn(o) T_number := c.GetString("T_number") // 检查前端传入的T_number是否已提交过 _, err := StockInDao.Read_StockIn_ByT_number(T_number) if err != nil && err.Error() != orm.ErrNoRows.Error() { // 数据库查询错误 o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "查询入库编号失败"} c.ServeJSON() return } if err == nil { // 入库编号已存在,不需要做任何处理 o.Rollback() c.Data["json"] = lib.JSONS{Code: 200, Msg: "入库编号已存在,无需重复提交!", Data: T_number} c.ServeJSON() return } T_depot_id, _ := c.GetInt("T_depot_id") T_type, _ := c.GetInt("T_type") // 1-入库 2-退库 T_date := c.GetString("T_date") T_product := c.GetString("T_product") T_remark := c.GetString("T_remark") T_project := c.GetString("T_project") T_return_user := c.GetString("T_return_user") T_batch_number := c.GetString("T_batch_number") T_company_name := c.GetString("T_company_name") date, is := lib.DateStrToTime(T_date) if !is { c.Data["json"] = lib.JSONS{Code: 202, Msg: "日期格式错误!"} c.ServeJSON() return } if T_type == 2 && len(T_project) == 0 { c.Data["json"] = lib.JSONS{Code: 202, Msg: "退库时,项目不能为空!"} c.ServeJSON() return } NatsServer.AddUserLogs(c.User.T_uuid, "仓库管理", "入库", T_product) var_ := Stock.StockIn{ T_number: T_number, T_depot_id: T_depot_id, T_type: T_type, T_date: T_date, T_remark: T_remark, T_submit: c.User.T_uuid, T_project: T_project, T_return_user: T_return_user, T_batch_number: T_batch_number, T_state: Stock.StockInWarehouse, T_warehouse: c.User.T_uuid, T_company_name: T_company_name, } StockInProductDao := Stock.NewStockInProduct(o) StockDao := Stock.NewStock(o) DeviceDao := Stock.NewDevice(o) _, err = StockInDao.Add_StockIn(var_) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "入库失败"} c.ServeJSON() return } if len(T_product) == 0 { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "产品明细不能为空"} c.ServeJSON() return } productList := lib.SplitString(T_product, "|") allProductList := []int{} for _, v := range productList { product_id, _ := strconv.Atoi(strings.Split(v, "-")[0]) allProductList = append(allProductList, product_id) product, _ := Basic.Read_Product_ById(product_id) num, _ := strconv.Atoi(strings.Split(v, "-")[1]) T_relation_sn := strings.Split(v, "-")[2] if T_relation_sn == "" && product.T_relation_sn == 1 { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("%s关联SN,请先添加SN!", product.T_name)} c.ServeJSON() return } if len(T_relation_sn) > 0 { snList := strings.Split(strings.Trim(T_relation_sn, ","), ",") num = len(snList) for _, sn := range snList { mqtt := Stock.Read_MqttUser(sn) // 添加设备 device := Stock.Device{ T_contract_number: "", T_out_number: "", T_product_id: product_id, T_in_number: T_number, T_sn: sn, T_iccid: mqtt.Iccid, T_imei: mqtt.Imei, T_State: 2, T_batch_number: T_batch_number, CreateTime: date, } _, err = DeviceDao.AddOrUpdate_Device(device, 2) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: sn + "入库失败"} c.ServeJSON() return } } } stockInProduct := Stock.StockInProduct{ T_number: T_number, T_product_id: product_id, T_depot_id: T_depot_id, T_num: num, // 入库数量 T_date: T_date, // 入库日期 T_relation_sn: T_relation_sn, T_batch_number: T_batch_number, } _, err = StockInProductDao.Add_StockInProduct(stockInProduct) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "入库失败"} c.ServeJSON() return } _, err = StockDao.AddOrUpdate_Stock(T_depot_id, product.Id, product.T_class, product.T_name, product.T_model, num, 2) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "入库失败"} c.ServeJSON() return } } // 批量更新所有相关设备的批次号 err = DeviceDao.Update_Device_BatchNumber_ByInNumber(T_number, T_batch_number) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "更新设备批次号失败"} c.ServeJSON() return } o.Commit() StockIn_Edit_StockMonth(T_date, T_depot_id, allProductList) NatsServer.AddUserLogs(c.User.T_uuid, "入库", "入库", var_) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: T_number} c.ServeJSON() return } func StockIn_Edit_StockMonth(T_date string, T_depot_id int, allProductList []int) error { if len(T_date) == 0 { return errors.New("日期不能为空") } date, _ := lib.DateStrToTime(T_date) //if date.Year() == time.Now().Year() && date.Month() == time.Now().Month() { // // 修改本月数据不同步库存 // return nil //} //T_month := date.Format("2006-01") months := generateMonthList(date, "in") o := orm.NewOrm() StockOutDao := Stock.NewStockOut(o) StockMonthDao := Stock.NewStockMonth(o) StockOutProductDao := Stock.NewStockOutProduct(o) StockInProductDao := Stock.NewStockInProduct(o) for _, T_product_id := range allProductList { for _, T_month := range months { // 获取当前产品本月出入库数量 lastMonth := StockMonthDao.Read_LastMonth_StockMonth_ByT_depot_id_T_product_id(T_depot_id, T_product_id, T_month) stockMonth := StockMonthDao.Read_StockMonth_ByT_depot_id_T_product_id(T_depot_id, T_product_id, T_month) if stockMonth.Id > 0 { // 修改 stockMonth.T_in = StockInProductDao.Read_StockIn_Total(T_depot_id, T_product_id, T_month) stockMonth.T_return = StockInProductDao.Read_StockReturn_Total(T_depot_id, T_product_id, T_month) if len(lastMonth) > 0 { stockMonth.T_beginning = lastMonth[0].T_ending } else { stockMonth.T_beginning = 0 } // 期末库存 = 期初库存+入库-出库 stockMonth.T_ending = stockMonth.T_beginning + stockMonth.T_in - stockMonth.T_out err := StockMonthDao.Update_StockMonth(stockMonth, "T_in", "T_return", "T_beginning", "T_ending") if err != nil { return err } } else { product, _ := Basic.Read_Product_ById(T_product_id) // 添加库存记录 stockMonth = Stock.StockMonth{ T_depot_id: T_depot_id, T_product_id: T_product_id, T_product_class: product.T_class, T_month: T_month, } // 获取当前产品本月出入库数量 stockMonth.T_in = StockInProductDao.Read_StockIn_Total(T_depot_id, T_product_id, T_month) stockMonth.T_out = StockOutProductDao.Read_StockOut_Total(T_depot_id, T_product_id, T_month) stockMonth.T_return = StockInProductDao.Read_StockReturn_Total(T_depot_id, T_product_id, T_month) if len(lastMonth) > 0 { stockMonth.T_beginning = lastMonth[0].T_ending } else { stockMonth.T_beginning = 0 } // 期末库存 = 期初库存+入库-出库 stockMonth.T_ending = stockMonth.T_beginning + stockMonth.T_in - stockMonth.T_out stockMonth.T_project = StockOutDao.Read_StockOut_T_contract_number(T_depot_id, T_product_id, T_month) _, err := StockMonthDao.Add_StockMonth(stockMonth) if err != nil { return err } } } } return nil } func (c *StockController) StockIn_Edit() { T_number := c.GetString("T_number") // 入库单号 //T_depot_id, _ := c.GetInt("T_depot_id") T_date := c.GetString("T_date") T_product := c.GetString("T_product") T_remark := c.GetString("T_remark") T_project := c.GetString("T_project") T_return_user := c.GetString("T_return_user") T_batch_number := c.GetString("T_batch_number") T_company_name := c.GetString("T_company_name") date, is := lib.DateStrToTime(T_date) if !is { c.Data["json"] = lib.JSONS{Code: 202, Msg: "日期格式错误!"} c.ServeJSON() return } if date.Year() != time.Now().Year() && date.Month() != time.Now().Month() { T_date = "" } NatsServer.AddUserLogs(c.User.T_uuid, "仓库管理", "修改入库", T_product) o := orm.NewOrm() o.Begin() StockInDao := Stock.NewStockIn(o) StockInProductDao := Stock.NewStockInProduct(o) StockDao := Stock.NewStock(o) DeviceDao := Stock.NewDevice(o) // 查询入库信息 stockIn, err := StockInDao.Read_StockIn_ByT_number(T_number) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"} c.ServeJSON() return } T_old_date := stockIn.T_date // 查询入库产品信息 productOldList := StockInProductDao.Read_StockInProduct_List_ByT_number(stockIn.T_number) var oldProductList []dto.StockProduct var newProductList []dto.StockProduct allProductListMap := make(map[int]struct{}) productOldMap := map[int]dto.StockProduct{} for _, product := range productOldList { stockProduct := dto.StockProduct{ T_product_id: product.T_product_id, T_num: product.T_num, T_relation_sn: lib.SplitString(product.T_relation_sn, ","), } oldProductList = append(oldProductList, stockProduct) productOldMap[product.T_product_id] = stockProduct if _, ok := allProductListMap[product.T_product_id]; !ok { allProductListMap[product.T_product_id] = struct{}{} } } productNewList := lib.SplitString(T_product, "|") productNewMap := map[int]dto.StockProduct{} for _, v := range productNewList { product_id, _ := strconv.Atoi(strings.Split(v, "-")[0]) num, _ := strconv.Atoi(strings.Split(v, "-")[1]) T_relation_sn := strings.Split(v, "-")[2] snList := lib.SplitString(T_relation_sn, ",") if len(snList) > 0 { num = len(snList) } stockProduct := dto.StockProduct{ T_product_id: product_id, T_num: num, T_relation_sn: snList, } newProductList = append(newProductList, stockProduct) productNewMap[product_id] = stockProduct if _, ok := allProductListMap[product_id]; !ok { allProductListMap[product_id] = struct{}{} } } // 判断产品列表信息是否相同 StockProductListIsEqual, needDelete, needAdd, needEdit, snDiff := dto.StockProductListsEqual(oldProductList, newProductList) // 两次提交的数据相同,则不用修改 if !StockProductListIsEqual { if len(needDelete) > 0 { // 删除入库产品列表 for _, v := range needDelete { product, _ := Basic.Read_Product_ById(v.T_product_id) // 删除入库产品列表 err = StockInProductDao.Delete_StockInProduct(stockIn.T_number, stockIn.T_depot_id, v.T_product_id) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "删除产品入库信息失败!"} c.ServeJSON() return } if product.T_relation_sn == 1 { // 删除该入库单关联sn for _, sn := range v.T_relation_sn { err = DeviceDao.Delete_Device_ByT_in_number(stockIn.T_number, sn) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "删除入库设备失败"} c.ServeJSON() return } } } // 减少库存 _, err = StockDao.AddOrUpdate_Stock(stockIn.T_depot_id, product.Id, product.T_class, product.T_name, product.T_model, v.T_num, 1) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "更新库存信息失败"} c.ServeJSON() return } } } if len(needAdd) > 0 { // 新增入库产品列表 for _, v := range needAdd { product, _ := Basic.Read_Product_ById(v.T_product_id) if product.T_relation_sn == 1 && len(v.T_relation_sn) == 0 { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("%s关联SN,请先添加SN!", product.T_name)} c.ServeJSON() return } // 添加该入库单关联sn for _, sn := range v.T_relation_sn { mqtt := Stock.Read_MqttUser(sn) // 添加设备 device := Stock.Device{ T_contract_number: "", T_out_number: "", T_product_id: v.T_product_id, T_in_number: stockIn.T_number, T_sn: sn, T_iccid: mqtt.Iccid, T_imei: mqtt.Imei, T_State: 2, T_batch_number: T_batch_number, CreateTime: date, UpdateTime: stockIn.UpdateTime, } _, err = DeviceDao.AddOrUpdate_Device(device, 2) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: sn + "入库失败"} c.ServeJSON() return } } stockInProduct := Stock.StockInProduct{ T_number: T_number, T_product_id: v.T_product_id, T_depot_id: stockIn.T_depot_id, T_num: v.T_num, // 入库数量 T_date: stockIn.T_date, // 入库日期 T_relation_sn: strings.Join(v.T_relation_sn, ","), } _, err = StockInProductDao.Add_StockInProduct(stockInProduct) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "入库失败"} c.ServeJSON() return } // 增加库存 _, err = StockDao.AddOrUpdate_Stock(stockIn.T_depot_id, product.Id, product.T_class, product.T_name, product.T_model, v.T_num, 2) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "增加库存失败"} c.ServeJSON() return } } } if len(needEdit) > 0 { for _, v := range needEdit { product, _ := Basic.Read_Product_ById(v.T_product_id) stockInProduct := Stock.StockInProduct{ T_number: stockIn.T_number, T_product_id: v.T_product_id, T_depot_id: stockIn.T_depot_id, T_num: productNewMap[v.T_product_id].T_num, // 入库数量 T_date: stockIn.T_date, // 入库日期 } // 入库数量比之前多,增加库存 var T_type int var T_num int if productNewMap[v.T_product_id].T_num > productOldMap[v.T_product_id].T_num { // 增加库存 T_type = 2 T_num = productNewMap[v.T_product_id].T_num - productOldMap[v.T_product_id].T_num } else { // 减少库存 T_type = 1 T_num = productOldMap[v.T_product_id].T_num - productNewMap[v.T_product_id].T_num } _, err = StockDao.AddOrUpdate_Stock(stockIn.T_depot_id, product.Id, product.T_class, product.T_name, product.T_model, T_num, T_type) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: err.Error()} c.ServeJSON() return } // 更新产品库存表 err = StockInProductDao.Update_StockInProduct(stockInProduct) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "修改入库产品信息失败"} c.ServeJSON() return } } } for _, diff := range snDiff { product, _ := Basic.Read_Product_ById(diff.T_product_id) // 删除减少的sn if len(diff.T_delete_relation_sn) > 0 { for _, sn := range diff.T_delete_relation_sn { err = DeviceDao.Delete_Device_ByT_in_number(stockIn.T_number, sn) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: err.Error()} c.ServeJSON() return } } // 减少库存 _, err = StockDao.AddOrUpdate_Stock(stockIn.T_depot_id, product.Id, product.T_class, product.T_name, product.T_model, len(diff.T_delete_relation_sn), 1) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: err.Error()} c.ServeJSON() return } } if len(diff.T_add_relation_sn) > 0 { for _, sn := range diff.T_add_relation_sn { mqtt := Stock.Read_MqttUser(sn) // 添加设备 device := Stock.Device{ T_contract_number: "", T_out_number: "", T_product_id: diff.T_product_id, T_in_number: stockIn.T_number, T_sn: sn, T_iccid: mqtt.Iccid, T_imei: mqtt.Imei, T_State: 2, CreateTime: date, UpdateTime: stockIn.UpdateTime, } _, err = DeviceDao.AddOrUpdate_Device(device, 2) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: sn + "入库失败"} c.ServeJSON() return } } // 增加库存 _, err = StockDao.AddOrUpdate_Stock(stockIn.T_depot_id, product.Id, product.T_class, product.T_name, product.T_model, len(diff.T_add_relation_sn), 2) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "入库失败"} c.ServeJSON() return } } stockInProduct := Stock.StockInProduct{ T_number: stockIn.T_number, T_product_id: diff.T_product_id, T_depot_id: stockIn.T_depot_id, T_num: productNewMap[diff.T_product_id].T_num, // 入库数量 T_date: stockIn.T_date, // 入库日期 T_relation_sn: strings.Join(productNewMap[diff.T_product_id].T_relation_sn, ","), } // 更新产品库存表 err = StockInProductDao.Update_StockInProduct(stockInProduct) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "修改入库产品信息失败"} c.ServeJSON() return } } } stockIn.T_remark = T_remark if len(T_date) > 0 { stockIn.T_date = T_date } if len(T_project) > 0 { stockIn.T_project = T_project } if len(T_return_user) > 0 { stockIn.T_return_user = T_return_user } if len(T_batch_number) > 0 { stockIn.T_batch_number = T_batch_number } if len(T_company_name) > 0 { stockIn.T_company_name = T_company_name } err = StockInDao.Update_StockIn(stockIn, "T_remark", "T_date", "T_project", "T_return_user", "T_batch_number", "T_company_name") if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "修改入库失败"} c.ServeJSON() return } o.Commit() if len(T_date) > 0 && T_old_date != T_date { // 修改出库产品日期 StockInProductDao.Update_StockInProduct_T_date(stockIn.T_number, T_date) DeviceDao.Update_Device_CreateTimeByT_in_number(stockIn.T_number, T_date) } // 修改出库产品日期 StockInProductDao.Update_StockInProduct_T_batch_number(stockIn.T_number, T_batch_number) // 修改设备批次号 DeviceDao.Update_Device_BatchNumber_ByInNumber(stockIn.T_number, T_batch_number) // 更新月份统计表 allProductList := []int{} for i, _ := range allProductListMap { allProductList = append(allProductList, i) } StockIn_Edit_StockMonth(stockIn.T_date, stockIn.T_depot_id, allProductList) NatsServer.AddUserLogs(c.User.T_uuid, "入库", "修改", stockIn) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: T_number} c.ServeJSON() return } // 删除入库 func (c *StockController) StockIn_Del() { T_number := c.GetString("T_number") // 入库单号 o := orm.NewOrm() o.Begin() StockInDao := Stock.NewStockIn(o) StockInProductDao := Stock.NewStockInProduct(o) StockDao := Stock.NewStock(o) DeviceDao := Stock.NewDevice(o) // 查询入库信息 stockIn, err := StockInDao.Read_StockIn_ByT_number(T_number) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"} c.ServeJSON() return } // 查询入库产品信息 productOldList := StockInProductDao.Read_StockInProduct_List_ByT_number(stockIn.T_number) var oldProductList []dto.StockProduct allProductList := []int{} for _, product := range productOldList { oldProductList = append(oldProductList, dto.StockProduct{ T_product_id: product.T_product_id, T_num: product.T_num, T_relation_sn: lib.SplitString(product.T_relation_sn, ","), }) allProductList = append(allProductList, product.T_product_id) } // 删除入库产品列表 for _, v := range oldProductList { product, _ := Basic.Read_Product_ById(v.T_product_id) // 删除入库产品列表 err = StockInProductDao.Delete_StockInProduct(stockIn.T_number, stockIn.T_depot_id, v.T_product_id) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "删除产品入库信息失败!"} c.ServeJSON() return } if product.T_relation_sn == 1 { // 删除该入库单关联sn for _, sn := range v.T_relation_sn { err = DeviceDao.Delete_Device_ByT_in_number(stockIn.T_number, sn) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "删除入库设备失败"} c.ServeJSON() return } } } // 减少库存 _, err = StockDao.AddOrUpdate_Stock(stockIn.T_depot_id, product.Id, product.T_class, product.T_name, product.T_model, v.T_num, 1) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "更新库存信息失败"} c.ServeJSON() return } } err = StockInDao.Delete_StockIn(stockIn) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "删除入库失败"} c.ServeJSON() return } o.Commit() // 更新月份统计表 StockIn_Edit_StockMonth(stockIn.T_date, stockIn.T_depot_id, allProductList) NatsServer.AddUserLogs(c.User.T_uuid, "入库", "删除", stockIn) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: T_number} c.ServeJSON() return } // 导出出库单 func (c *StockController) StockIn_Excel() { // 查询 T_number := c.GetString("T_number") o := orm.NewOrm() StockInDao := Stock.NewStockIn(o) StockInProductDao := Stock.NewStockInProduct(o) stockIn, err := StockInDao.Read_StockIn_ByT_number(T_number) if err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"} c.ServeJSON() return } productList := StockInProductDao.Read_StockInProduct_List_ByT_number(stockIn.T_number) var pList []Stock.StockInProduct_R for _, v := range productList { pList = append(pList, Stock.StockInProductToStockInProduct_R(v)) } userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) stockInDetail := Stock.StockInToStockIn_Detail(stockIn, pList) T_date, _ := lib.DateStrToTime(stockIn.T_date) filename := fmt.Sprintf("冷链产品入库单(%s)", lib.GetRandstring(6, "0123456789", 0)) f := excelize.NewFile() // 设置单元格的值 Style1, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Bold: true, Size: 12, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"}, }) Style2, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Size: 11, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "left", Vertical: "center"}, }) Style3, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Size: 10, Family: "宋体", Bold: true}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true}, 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}, }, }) Style4, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Size: 11, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true}, 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}, }, }) productList2 := lib.ChunkBy(productList, 10) for i, products := range productList2 { if len(products) < 10 { products = append(products, make([]Stock.StockInProduct, 10-len(products))...) } row := i*17 + 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) f.SetRowStyle("Sheet1", row, row, Style1) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("宝智达科技产品进销存统计表")) f.SetRowHeight("Sheet1", row, 20) row += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) f.SetRowStyle("Sheet1", row, row, Style1) title := "硬件入库单" if len(productList2) > 1 { title += fmt.Sprintf(" %d/%d", i+1, len(productList2)) } f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), title) f.SetRowHeight("Sheet1", row, 20) row += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) f.SetRowStyle("Sheet1", row, row, Style2) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("入库单号:%s", stockIn.T_number)) f.SetRowHeight("Sheet1", row, 20) row += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) f.SetRowStyle("Sheet1", row, row, Style2) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("项目名称:%s", stockIn.T_remark)) f.SetRowHeight("Sheet1", row, 20) row += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) f.SetRowStyle("Sheet1", row, row, Style2) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("入库时间:%s", T_date.Format("2006年01月02日"))) f.SetRowHeight("Sheet1", row, 20) // 这里设置表头 row += 1 f.SetRowHeight("Sheet1", row, 20) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), "序号") f.SetCellValue("Sheet1", fmt.Sprintf("B%d", row), "产品名称") f.SetCellValue("Sheet1", fmt.Sprintf("C%d", row), "型号") f.SetCellValue("Sheet1", fmt.Sprintf("D%d", row), "单位") f.SetCellValue("Sheet1", fmt.Sprintf("E%d", row), "领用数量") f.SetCellValue("Sheet1", fmt.Sprintf("F%d", row), "备注") // 设置列宽 f.SetColWidth("Sheet1", "A", "A", 5) f.SetColWidth("Sheet1", "B", "B", 20) f.SetColWidth("Sheet1", "C", "C", 12) f.SetColWidth("Sheet1", "D", "D", 10) f.SetColWidth("Sheet1", "E", "E", 10) f.SetColWidth("Sheet1", "F", "F", 15) f.SetCellStyle("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row), Style3) sRow := row // 循环写入数据 for j, v := range products { row += 1 product, _ := Basic.Read_Product_ById(v.T_product_id) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), j+1) f.SetCellValue("Sheet1", fmt.Sprintf("B%d", row), product.T_name) f.SetCellValue("Sheet1", fmt.Sprintf("C%d", row), product.T_model) f.SetCellValue("Sheet1", fmt.Sprintf("D%d", row), product.T_spec) if v.T_num > 0 { f.SetCellValue("Sheet1", fmt.Sprintf("E%d", row), v.T_num) f.SetCellValue("Sheet1", fmt.Sprintf("F%d", row), stockIn.T_remark) } } f.SetCellStyle("Sheet1", fmt.Sprintf("A%d", sRow), fmt.Sprintf("F%d", row), Style4) row += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("C%d", row)) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("制单:%s", c.User.T_name)) f.MergeCell("Sheet1", fmt.Sprintf("D%d", row), fmt.Sprintf("F%d", row)) f.SetCellValue("Sheet1", fmt.Sprintf("D%d", row), fmt.Sprintf("经办人:%s", stockInDetail.T_submit_name)) f.SetRowStyle("Sheet1", row, row, Style2) f.SetRowHeight("Sheet1", row, 20) } // 保存文件 if err = f.SaveAs("ofile/" + filename + ".xlsx"); err != nil { fmt.Println(err) } var url string //// 上传 OSS nats := natslibs.NewNats(Nats.Nats, conf.NatsSubj_Prefix) url, is := nats.Qiniu_UploadFile(lib.GetCurrentDirectory()+"/ofile/"+filename+".xlsx", "ofile/"+filename+".xlsx") if !is { c.Data["json"] = lib.JSONS{Code: 202, Msg: "oss!"} c.ServeJSON() return } //删除目录 err = os.Remove("ofile/" + filename + ".xlsx") if err != nil { logs.Error(lib.FuncName(), err) } c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: url} c.ServeJSON() return } // 批量导出出库单 func (c *StockController) StockIn_Excel_Batch() { // 查询 T_number_list := c.GetString("T_number_list") o := orm.NewOrm() StockInDao := Stock.NewStockIn(o) StockInProductDao := Stock.NewStockInProduct(o) list := strings.Split(strings.Trim(T_number_list, "|"), "|") userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) filename := fmt.Sprintf("冷链产品入库单(%s)", lib.GetRandstring(6, "0123456789", 0)) f := excelize.NewFile() // 设置单元格的值 Style1, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Bold: true, Size: 12, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"}, }) Style2, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Size: 11, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "left", Vertical: "center"}, }) Style3, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Size: 10, Family: "宋体", Bold: true}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true}, 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}, }, }) Style4, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Size: 11, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true}, 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}, }, }) var num int for _, T_number := range list { stockIn, err := StockInDao.Read_StockIn_ByT_number(T_number) if err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"} c.ServeJSON() return } productList := StockInProductDao.Read_StockInProduct_List_ByT_number(stockIn.T_number) var pList []Stock.StockInProduct_R for _, v := range productList { pList = append(pList, Stock.StockInProductToStockInProduct_R(v)) } stockInDetail := Stock.StockInToStockIn_Detail(stockIn, pList) T_date, _ := lib.DateStrToTime(stockIn.T_date) productList2 := lib.ChunkBy(productList, 10) for i, products := range productList2 { if len(products) < 10 { products = append(products, make([]Stock.StockInProduct, 10-len(products))...) } row := num*18 + 1 num += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) f.SetRowStyle("Sheet1", row, row, Style1) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("宝智达科技产品进销存统计表")) f.SetRowHeight("Sheet1", row, 20) row += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) f.SetRowStyle("Sheet1", row, row, Style1) title := "硬件入库单" if len(productList2) > 1 { title += fmt.Sprintf(" %d/%d", i+1, len(productList2)) } f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), title) f.SetRowHeight("Sheet1", row, 20) row += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) f.SetRowStyle("Sheet1", row, row, Style2) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("入库单号:%s", stockIn.T_number)) f.SetRowHeight("Sheet1", row, 20) row += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) f.SetRowStyle("Sheet1", row, row, Style2) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("项目名称:%s", stockIn.T_remark)) f.SetRowHeight("Sheet1", row, 20) row += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) f.SetRowStyle("Sheet1", row, row, Style2) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("入库时间:%s", T_date.Format("2006年01月02日"))) f.SetRowHeight("Sheet1", row, 20) // 这里设置表头 row += 1 f.SetRowHeight("Sheet1", row, 20) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), "序号") f.SetCellValue("Sheet1", fmt.Sprintf("B%d", row), "产品名称") f.SetCellValue("Sheet1", fmt.Sprintf("C%d", row), "型号") f.SetCellValue("Sheet1", fmt.Sprintf("D%d", row), "单位") f.SetCellValue("Sheet1", fmt.Sprintf("E%d", row), "领用数量") f.SetCellValue("Sheet1", fmt.Sprintf("F%d", row), "备注") // 设置列宽 f.SetColWidth("Sheet1", "A", "A", 5) f.SetColWidth("Sheet1", "B", "B", 20) f.SetColWidth("Sheet1", "C", "C", 12) f.SetColWidth("Sheet1", "D", "D", 10) f.SetColWidth("Sheet1", "E", "E", 10) f.SetColWidth("Sheet1", "F", "F", 15) f.SetCellStyle("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row), Style3) sRow := row // 循环写入数据 for j, v := range products { row += 1 product, _ := Basic.Read_Product_ById(v.T_product_id) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), j+1) f.SetCellValue("Sheet1", fmt.Sprintf("B%d", row), product.T_name) f.SetCellValue("Sheet1", fmt.Sprintf("C%d", row), product.T_model) f.SetCellValue("Sheet1", fmt.Sprintf("D%d", row), product.T_spec) if v.T_num > 0 { f.SetCellValue("Sheet1", fmt.Sprintf("E%d", row), v.T_num) f.SetCellValue("Sheet1", fmt.Sprintf("F%d", row), stockIn.T_remark) } } f.SetCellStyle("Sheet1", fmt.Sprintf("A%d", sRow), fmt.Sprintf("F%d", row), Style4) row += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("C%d", row)) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("制单:%s", c.User.T_name)) f.MergeCell("Sheet1", fmt.Sprintf("D%d", row), fmt.Sprintf("F%d", row)) f.SetCellValue("Sheet1", fmt.Sprintf("D%d", row), fmt.Sprintf("经办人:%s", stockInDetail.T_submit_name)) f.SetRowStyle("Sheet1", row, row, Style2) f.SetRowHeight("Sheet1", row, 20) // 空一行 row += 1 //f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) //f.SetRowStyle("Sheet1", row, row, Style1) //f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), "") // 插入下一页分页符 f.InsertPageBreak("Sheet1", fmt.Sprintf("A%d", row)) } } // 保存文件 if err := f.SaveAs("ofile/" + filename + ".xlsx"); err != nil { fmt.Println(err) } var url string //// 上传 OSS nats := natslibs.NewNats(Nats.Nats, conf.NatsSubj_Prefix) url, is := nats.Qiniu_UploadFile(lib.GetCurrentDirectory()+"/ofile/"+filename+".xlsx", "ofile/"+filename+".xlsx") if !is { c.Data["json"] = lib.JSONS{Code: 202, Msg: "oss!"} c.ServeJSON() return } //删除目录 err := os.Remove("ofile/" + filename + ".xlsx") if err != nil { logs.Error(lib.FuncName(), err) } c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: url} c.ServeJSON() return } // 退库申请 func (c *StockController) StockIn_Apply_List() { // 分页参数 初始化 page, _ := c.GetInt("page") if page < 1 { page = 1 } page_z, _ := c.GetInt("page_z") if page_z < 1 { page_z = conf.Page_size } // 查询 T_depot_id, _ := c.GetInt("T_depot_id") T_start_date := c.GetString("T_start_date") T_end_date := c.GetString("T_end_date") T_name := c.GetString("T_name") T_state := c.GetString("T_state") userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) Basic.Read_Depot_All_Map() StockInDao := Stock.NewStockIn(orm.NewOrm()) R_List, R_cnt := StockInDao.Read_StockIn_Apply_List(Stock.StockInTypeApply, c.User.T_uuid, T_state, T_name, T_depot_id, T_start_date, T_end_date, page, page_z) var r_jsons lib.R_JSONS r_jsons.Num = R_cnt r_jsons.Data = R_List r_jsons.Page = page r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(page_z))) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons} c.ServeJSON() return } func (c *StockController) StockIn_Apply_Warehouse_List() { // 分页参数 初始化 page, _ := c.GetInt("page") if page < 1 { page = 1 } page_z, _ := c.GetInt("page_z") if page_z < 1 { page_z = conf.Page_size } // 查询 T_depot_id, _ := c.GetInt("T_depot_id") T_start_date := c.GetString("T_start_date") T_end_date := c.GetString("T_end_date") T_name := c.GetString("T_name") T_state := c.GetString("T_state") T_uuid := c.GetString("T_uuid") userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) Basic.Read_Depot_All_Map() StockInDao := Stock.NewStockIn(orm.NewOrm()) R_List, R_cnt := StockInDao.Read_StockIn_Apply_List(Stock.StockInTypeWarehouse, T_uuid, T_state, T_name, T_depot_id, T_start_date, T_end_date, page, page_z) var r_jsons lib.R_JSONS r_jsons.Num = R_cnt r_jsons.Data = R_List r_jsons.Page = page r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(page_z))) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons} c.ServeJSON() return } func (c *StockController) StockIn_Apply() { o := orm.NewOrm() o.Begin() StockInDao := Stock.NewStockIn(o) T_number := c.GetString("T_number") // 检查前端传入的T_number是否已提交过 _, err := StockInDao.Read_StockIn_ByT_number(T_number) if err != nil && err.Error() != orm.ErrNoRows.Error() { // 数据库查询错误 o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "查询入库编号失败"} c.ServeJSON() return } if err == nil { // 入库编号已存在,不需要做任何处理 o.Rollback() c.Data["json"] = lib.JSONS{Code: 200, Msg: "入库编号已存在,无需重复提交!", Data: T_number} c.ServeJSON() return } T_depot_id, _ := c.GetInt("T_depot_id") T_product := c.GetString("T_product") T_remark := c.GetString("T_remark") T_project := c.GetString("T_project") T_company_name := c.GetString("T_company_name") T_return_user := c.GetString("T_return_user") if len(T_return_user) == 0 { T_return_user = c.User.T_uuid } if len(T_project) == 0 { c.Data["json"] = lib.JSONS{Code: 202, Msg: "项目不能为空!"} c.ServeJSON() return } NatsServer.AddUserLogs(c.User.T_uuid, "仓库管理", "退库", T_product) var_ := Stock.StockIn{ T_number: T_number, T_depot_id: T_depot_id, T_type: 2, T_remark: T_remark, T_submit: c.User.T_uuid, T_project: T_project, T_return_user: T_return_user, T_company_name: T_company_name, T_state: 1, T_application_date: time.Now().Format("2006-01-02"), } StockInProductDao := Stock.NewStockInProduct(o) _, err = StockInDao.Add_StockIn(var_) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "入库失败"} c.ServeJSON() return } if len(T_product) == 0 { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "产品明细不能为空"} c.ServeJSON() return } productList := lib.SplitString(T_product, "|") allProductList := []int{} for _, v := range productList { product_id, _ := strconv.Atoi(strings.Split(v, "-")[0]) allProductList = append(allProductList, product_id) num, _ := strconv.Atoi(strings.Split(v, "-")[1]) stockInProduct := Stock.StockInProduct{ T_number: T_number, T_product_id: product_id, T_depot_id: T_depot_id, T_num: num, // 入库数量 } _, err = StockInProductDao.Add_StockInProduct(stockInProduct) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "入库失败"} c.ServeJSON() return } } o.Commit() NatsServer.AddUserLogs(c.User.T_uuid, "退库申请", "退库申请", var_) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: T_number} c.ServeJSON() return } func (c *StockController) StockIn_Apply_Edit() { T_number := c.GetString("T_number") // 入库单号 //T_depot_id, _ := c.GetInt("T_depot_id") T_product := c.GetString("T_product") T_remark := c.GetString("T_remark") T_project := c.GetString("T_project") T_batch_number := c.GetString("T_batch_number") T_company_name := c.GetString("T_company_name") NatsServer.AddUserLogs(c.User.T_uuid, "仓库管理", "修改入库", T_product) o := orm.NewOrm() o.Begin() StockInDao := Stock.NewStockIn(o) StockInProductDao := Stock.NewStockInProduct(o) // 查询入库信息 stockIn, err := StockInDao.Read_StockIn_ByT_number(T_number) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"} c.ServeJSON() return } // 查询入库产品信息 productOldList := StockInProductDao.Read_StockInProduct_List_ByT_number(stockIn.T_number) var oldProductList []dto.StockProduct var newProductList []dto.StockProduct allProductListMap := make(map[int]struct{}) productOldMap := map[int]dto.StockProduct{} for _, product := range productOldList { stockProduct := dto.StockProduct{ T_product_id: product.T_product_id, T_num: product.T_num, T_relation_sn: lib.SplitString(product.T_relation_sn, ","), } oldProductList = append(oldProductList, stockProduct) productOldMap[product.T_product_id] = stockProduct if _, ok := allProductListMap[product.T_product_id]; !ok { allProductListMap[product.T_product_id] = struct{}{} } } productNewList := lib.SplitString(T_product, "|") productNewMap := map[int]dto.StockProduct{} for _, v := range productNewList { product_id, _ := strconv.Atoi(strings.Split(v, "-")[0]) num, _ := strconv.Atoi(strings.Split(v, "-")[1]) T_relation_sn := strings.Split(v, "-")[2] snList := lib.SplitString(T_relation_sn, ",") if len(snList) > 0 { num = len(snList) } stockProduct := dto.StockProduct{ T_product_id: product_id, T_num: num, T_relation_sn: snList, } newProductList = append(newProductList, stockProduct) productNewMap[product_id] = stockProduct if _, ok := allProductListMap[product_id]; !ok { allProductListMap[product_id] = struct{}{} } } // 判断产品列表信息是否相同 StockProductListIsEqual, needDelete, needAdd, needEdit, _ := dto.StockProductListsEqual(oldProductList, newProductList) // 两次提交的数据相同,则不用修改 if !StockProductListIsEqual { if len(needDelete) > 0 { // 删除入库产品列表 for _, v := range needDelete { // 删除入库产品列表 err = StockInProductDao.Delete_StockInProduct(stockIn.T_number, stockIn.T_depot_id, v.T_product_id) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "删除产品入库信息失败!"} c.ServeJSON() return } } } if len(needAdd) > 0 { // 新增入库产品列表 for _, v := range needAdd { stockInProduct := Stock.StockInProduct{ T_number: T_number, T_product_id: v.T_product_id, T_depot_id: stockIn.T_depot_id, T_num: v.T_num, // 入库数量 T_date: stockIn.T_date, // 入库日期 T_relation_sn: strings.Join(v.T_relation_sn, ","), } _, err = StockInProductDao.Add_StockInProduct(stockInProduct) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "入库失败"} c.ServeJSON() return } } } if len(needEdit) > 0 { for _, v := range needEdit { stockInProduct := Stock.StockInProduct{ T_number: stockIn.T_number, T_product_id: v.T_product_id, T_depot_id: stockIn.T_depot_id, T_num: productNewMap[v.T_product_id].T_num, // 入库数量 T_date: stockIn.T_date, // 入库日期 } // 更新产品库存表 err = StockInProductDao.Update_StockInProduct(stockInProduct) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "修改入库产品信息失败"} c.ServeJSON() return } } } } stockIn.T_remark = T_remark if len(T_project) > 0 { stockIn.T_project = T_project } if len(T_batch_number) > 0 { stockIn.T_batch_number = T_batch_number } if len(T_company_name) > 0 { stockIn.T_company_name = T_company_name } err = StockInDao.Update_StockIn(stockIn, "T_remark", "T_project", "T_batch_number", "T_company_name") if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "修改入库失败"} c.ServeJSON() return } o.Commit() NatsServer.AddUserLogs(c.User.T_uuid, "退库", "修改", stockIn) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: T_number} c.ServeJSON() return } // 删除入库 func (c *StockController) StockIn_Apply_Del() { T_number := c.GetString("T_number") // 入库单号 o := orm.NewOrm() o.Begin() StockInDao := Stock.NewStockIn(o) StockInProductDao := Stock.NewStockInProduct(o) // 查询入库信息 stockIn, err := StockInDao.Read_StockIn_ByT_number(T_number) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"} c.ServeJSON() return } // 查询入库产品信息 productOldList := StockInProductDao.Read_StockInProduct_List_ByT_number(stockIn.T_number) var oldProductList []dto.StockProduct allProductList := []int{} for _, product := range productOldList { oldProductList = append(oldProductList, dto.StockProduct{ T_product_id: product.T_product_id, T_num: product.T_num, T_relation_sn: lib.SplitString(product.T_relation_sn, ","), }) allProductList = append(allProductList, product.T_product_id) } // 删除入库产品列表 for _, v := range oldProductList { // 删除入库产品列表 err = StockInProductDao.Delete_StockInProduct(stockIn.T_number, stockIn.T_depot_id, v.T_product_id) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "删除产品入库信息失败!"} c.ServeJSON() return } } err = StockInDao.Delete_StockIn(stockIn) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "删除入库失败"} c.ServeJSON() return } o.Commit() NatsServer.AddUserLogs(c.User.T_uuid, "入库申请", "删除", stockIn) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: T_number} c.ServeJSON() return } func (c *StockController) StockIn_Warehouse() { T_number := c.GetString("T_number") T_date := c.GetString("T_date") T_remark := c.GetString("T_remark") T_project := c.GetString("T_project") T_product := c.GetString("T_product") date, is := lib.DateStrToTime(T_date) if !is { c.Data["json"] = lib.JSONS{Code: 202, Msg: "日期格式错误!"} c.ServeJSON() return } if len(T_project) == 0 { c.Data["json"] = lib.JSONS{Code: 202, Msg: "项目不能为空!"} c.ServeJSON() return } NatsServer.AddUserLogs(c.User.T_uuid, "退库申请", "确认入库", T_product) o := orm.NewOrm() o.Begin() StockInDao := Stock.NewStockIn(o) StockInProductDao := Stock.NewStockInProduct(o) StockDao := Stock.NewStock(o) DeviceDao := Stock.NewDevice(o) // 查询入库信息 stockIn, err := StockInDao.Read_StockIn_ByT_number(T_number) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"} c.ServeJSON() return } productList := lib.SplitString(T_product, "|") allProductList := []int{} for _, v := range productList { product_id, _ := strconv.Atoi(strings.Split(v, "-")[0]) allProductList = append(allProductList, product_id) product, _ := Basic.Read_Product_ById(product_id) num, _ := strconv.Atoi(strings.Split(v, "-")[1]) if num == 0 { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("%s出库数量不能为0!", product.T_name)} c.ServeJSON() return } T_relation_sn := strings.Split(v, "-")[2] if T_relation_sn == "" && product.T_relation_sn == 1 { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("%s关联SN,请先添加SN!", product.T_name)} c.ServeJSON() return } if len(T_relation_sn) > 0 { snList := strings.Split(T_relation_sn, ",") if product.T_relation_sn == 1 && num != len(snList) { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("%s SN数量与出库数量不一致,请核查!", product.T_name)} c.ServeJSON() return } if len(snList) > 0 { for _, sn := range snList { mqtt := Stock.Read_MqttUser(sn) // 根据IMEI查询上次入库的批次号 batchNumber, err := DeviceDao.Read_Device_BatchNumber_ByImei(mqtt.Imei) if err != nil { logs.Error(lib.FuncName(), err) } device := Stock.Device{ T_product_id: product_id, T_in_number: T_number, T_sn: sn, T_iccid: mqtt.Iccid, T_imei: mqtt.Imei, T_State: 2, T_project: stockIn.T_project, T_batch_number: batchNumber, CreateTime: date, } _, err = DeviceDao.AddOrUpdate_Device(device, 1) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "出库失败"} c.ServeJSON() return } } } } // 3、添加出库产品清单 stockInProduct := Stock.StockInProduct{ T_number: T_number, T_product_id: product_id, T_depot_id: stockIn.T_depot_id, T_num: num, // 入库数量 T_date: T_date, // 入库日期 T_relation_sn: T_relation_sn, T_state: 1, } // 更新产品表 err = StockInProductDao.Update_StockInProduct(stockInProduct) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "修改出库产品信息失败"} c.ServeJSON() return } // 5、更新产品库存列表、占用库存 _, err = StockDao.AddOrUpdate_Stock(stockIn.T_depot_id, product.Id, product.T_class, product.T_name, product.T_model, num, 2) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "入库失败"} c.ServeJSON() return } } if len(T_remark) > 0 { stockIn.T_remark = T_remark } if len(T_project) > 0 { stockIn.T_project = T_project } stockIn.T_warehouse = c.User.T_uuid stockIn.T_state = Stock.StockInWarehouse stockIn.T_date = T_date err = StockInDao.Update_StockIn(stockIn, "T_state", "T_date", "T_warehouse", "T_project", "T_remark") if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "出库审批失败"} c.ServeJSON() return } o.Commit() // 更新月份统计表 StockIn_Edit_StockMonth(stockIn.T_date, stockIn.T_depot_id, allProductList) NatsServer.AddUserLogs(c.User.T_uuid, "入库申请", "确认出库", stockIn) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: T_number} c.ServeJSON() return } func (c *StockController) StockOut_List() { // 分页参数 初始化 page, _ := c.GetInt("page") if page < 1 { page = 1 } page_z, _ := c.GetInt("page_z") if page_z < 1 { page_z = conf.Page_size } // 查询 T_depot_id, _ := c.GetInt("T_depot_id") T_contract_number := c.GetString("T_contract_number") T_start_date := c.GetString("T_start_date") T_end_date := c.GetString("T_end_date") T_name := c.GetString("T_name") userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) Basic.Read_Depot_All_Map() StockOutDao := Stock.NewStockOut(orm.NewOrm()) R_List, R_cnt := StockOutDao.Read_StockOut_List(T_name, T_depot_id, T_contract_number, T_start_date, T_end_date, page, page_z) var r_jsons lib.R_JSONS r_jsons.Num = R_cnt r_jsons.Data = R_List r_jsons.Page = page r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(page_z))) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons} c.ServeJSON() return } func (c *StockController) StockOut_List_Product() { // 分页参数 初始化 page, _ := c.GetInt("page") if page < 1 { page = 1 } page_z, _ := c.GetInt("page_z") if page_z < 1 { page_z = conf.Page_size } // 查询 T_depot_id, _ := c.GetInt("T_depot_id") T_name := c.GetString("T_name") T_start_date := c.GetString("T_start_date") T_end_date := c.GetString("T_end_date") T_product_name := c.GetString("T_product_name") // 产品名称 T_product_model := c.GetString("T_product_model") // 产品型号 userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) Basic.Read_Depot_All_Map() StockOutDao := Stock.NewStockOut(orm.NewOrm()) R_List, R_cnt := StockOutDao.Read_StockOutProduct_List(T_name, T_start_date, T_end_date, T_depot_id, T_product_name, T_product_model, page, page_z) var r_jsons lib.R_JSONS r_jsons.Num = R_cnt r_jsons.Data = R_List r_jsons.Page = page r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(page_z))) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons} c.ServeJSON() return } func (c *StockController) StockOut_List_Product_Excel() { // 查询 T_depot_id, _ := c.GetInt("T_depot_id") T_name := c.GetString("T_name") T_start_date := c.GetString("T_start_date") T_end_date := c.GetString("T_end_date") T_product_name := c.GetString("T_product_name") // 产品名称 T_product_model := c.GetString("T_product_model") // 产品型号 userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) Basic.Read_Depot_All_Map() StockOutDao := Stock.NewStockOut(orm.NewOrm()) R_List, _ := StockOutDao.Read_StockOutProduct_List(T_name, T_start_date, T_end_date, T_depot_id, T_product_name, T_product_model, 0, 9999) filename := fmt.Sprintf("出库明细单(%s)", lib.GetRandstring(6, "0123456789", 0)) f := excelize.NewFile() // 设置单元格的值 Style1, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Bold: true, Size: 12, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"}, }) Style2, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Bold: true, Size: 11, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"}, 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}, }, }) Style3, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Size: 11, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "left", Vertical: "center", WrapText: true}, 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}, }, }) f.MergeCell("Sheet1", "A1", "L1") f.SetRowStyle("Sheet1", 1, 1, Style1) f.SetCellValue("Sheet1", "A1", fmt.Sprintf("出库明细单")) f.SetRowHeight("Sheet1", 1, 30) // 这里设置表头 f.SetCellStyle("Sheet1", "A2", "L2", Style2) f.SetRowHeight("Sheet1", 2, 20) f.SetCellValue("Sheet1", "A2", "序号") f.SetCellValue("Sheet1", "B2", "出库单号") f.SetCellValue("Sheet1", "C2", "领取人") f.SetCellValue("Sheet1", "D2", "出库日期") f.SetCellValue("Sheet1", "E2", "出库仓库") f.SetCellValue("Sheet1", "F2", "关联项目") f.SetCellValue("Sheet1", "G2", "产品名称") f.SetCellValue("Sheet1", "H2", "产品型号") f.SetCellValue("Sheet1", "I2", "数量") f.SetCellValue("Sheet1", "J2", "是否关联SN") f.SetCellValue("Sheet1", "K2", "备注") f.SetCellValue("Sheet1", "L2", "SN") // 设置列宽 f.SetColWidth("Sheet1", "A", "A", 10) f.SetColWidth("Sheet1", "B", "B", 15) f.SetColWidth("Sheet1", "C", "D", 10) f.SetColWidth("Sheet1", "D", "D", 10) f.SetColWidth("Sheet1", "E", "E", 10) f.SetColWidth("Sheet1", "F", "F", 20) f.SetColWidth("Sheet1", "G", "G", 20) f.SetColWidth("Sheet1", "H", "H", 15) f.SetColWidth("Sheet1", "I", "I", 10) f.SetColWidth("Sheet1", "J", "J", 12) f.SetColWidth("Sheet1", "K", "K", 30) f.SetColWidth("Sheet1", "L", "L", 100) line := 2 for _, product := range R_List { line += 1 f.SetCellValue("Sheet1", fmt.Sprintf("A%d", line), line-2) f.SetCellValue("Sheet1", fmt.Sprintf("B%d", line), product.T_number) f.SetCellValue("Sheet1", fmt.Sprintf("C%d", line), product.T_receive_name) f.SetCellValue("Sheet1", fmt.Sprintf("D%d", line), product.T_date) f.SetCellValue("Sheet1", fmt.Sprintf("E%d", line), product.T_depot_name) f.SetCellValue("Sheet1", fmt.Sprintf("F%d", line), product.T_project) f.SetCellValue("Sheet1", fmt.Sprintf("G%d", line), product.T_product_name) f.SetCellValue("Sheet1", fmt.Sprintf("H%d", line), product.T_product_model) f.SetCellValue("Sheet1", fmt.Sprintf("I%d", line), product.T_num) var relation_sn string if product.T_product_relation_sn == 1 { relation_sn = "是" } else { relation_sn = "否" } f.SetCellValue("Sheet1", fmt.Sprintf("J%d", line), relation_sn) f.SetCellValue("Sheet1", fmt.Sprintf("K%d", line), product.T_remark) f.SetCellValue("Sheet1", fmt.Sprintf("L%d", line), product.T_relation_sn) } f.SetCellStyle("Sheet1", "A3", fmt.Sprintf("L%d", line), Style3) // 保存文件 if err := f.SaveAs("ofile/" + filename + ".xlsx"); err != nil { fmt.Println(err) } var url string //// 上传 OSS nats := natslibs.NewNats(Nats.Nats, conf.NatsSubj_Prefix) url, is := nats.Qiniu_UploadFile(lib.GetCurrentDirectory()+"/ofile/"+filename+".xlsx", "ofile/"+filename+".xlsx") if !is { c.Data["json"] = lib.JSONS{Code: 202, Msg: "oss!"} c.ServeJSON() return } //删除目录 err := os.Remove("ofile/" + filename + ".xlsx") if err != nil { logs.Error(lib.FuncName(), err) } c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: url} c.ServeJSON() return } func (c *StockController) StockOut_Get() { // 查询 T_number := c.GetString("T_number") o := orm.NewOrm() StockOutDao := Stock.NewStockOut(o) StockOutProductDao := Stock.NewStockOutProduct(o) stockOut, err := StockOutDao.Read_StockOut_ByT_number(T_number) if err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"} c.ServeJSON() return } productList := StockOutProductDao.Read_StockOutProduct_List(stockOut.T_number) var pList []Stock.StockOutProduct_R for _, v := range productList { pList = append(pList, Stock.StockOutProductToStockOutProduct_R(v)) } userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) Basic.Read_Depot_All_Map() c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: Stock.StockOutToStockOut_Detail(stockOut, pList)} c.ServeJSON() return } func (c *StockController) StockOut_generate_number() { StockOutDao := Stock.NewStockOut(orm.NewOrm()) rand_x := 0 T_number := "" for true { T_number = "CK-" + lib.GetRandstring(8, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", int64(rand_x)) _, err := StockOutDao.Read_StockOut_ByT_number(T_number) if err != nil && err.Error() == orm.ErrNoRows.Error() { break } rand_x += 1 } c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: T_number} c.ServeJSON() return } func (c *StockController) StockOut_Add() { o := orm.NewOrm() o.Begin() StockOutDao := Stock.NewStockOut(o) // 检查前端传入的T_number是否已提交过 T_number := c.GetString("T_number") _, err := StockOutDao.Read_StockOut_ByT_number(T_number) if err == nil { // 入库编号已存在,不需要做任何处理 o.Rollback() c.Data["json"] = lib.JSONS{Code: 200, Msg: "出库编号已存在,无需重复提交!", Data: T_number} c.ServeJSON() return } if err != nil && err.Error() != orm.ErrNoRows.Error() { // 数据库查询错误 o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "查询入库编号失败"} c.ServeJSON() return } T_contract_number := c.GetString("T_contract_number") T_depot_id, _ := c.GetInt("T_depot_id") T_type, _ := c.GetInt("T_type") // 出库类型 1-领料出库 2-销售出库 T_date := c.GetString("T_date") T_receive := c.GetString("T_receive") T_product := c.GetString("T_product") T_remark := c.GetString("T_remark") T_project := c.GetString("T_project") T_delivery_type, _ := c.GetInt("T_delivery_type") T_signer_unit := c.GetString("T_signer_unit") T_signer := c.GetString("T_signer") T_signer_phone := c.GetString("T_signer_phone") T_signer_date := c.GetString("T_signer_date") T_courier_number := c.GetString("T_courier_number") date, is := lib.DateStrToTime(T_date) if !is { c.Data["json"] = lib.JSONS{Code: 202, Msg: "日期格式错误!"} c.ServeJSON() return } var_ := Stock.StockOut{ T_number: T_number, T_contract_number: T_contract_number, T_depot_id: T_depot_id, T_type: T_type, T_date: T_date, T_receive: T_receive, T_remark: T_remark, T_project: T_project, T_submit: c.User.T_uuid, // 销售出库 T_delivery_type: T_delivery_type, // 1-自送 2-自提 3-快递 T_signer_unit: T_signer_unit, T_signer: T_signer, T_signer_phone: T_signer_phone, T_signer_date: T_signer_date, T_courier_number: T_courier_number, T_state: Stock.StockOutAlreadyOut, } StockOutProductDao := Stock.NewStockOutProduct(o) StockDao := Stock.NewStock(o) DeviceDao := Stock.NewDevice(o) ContractDao := Contract.NewContract(o) ContractProductDao := Contract.NewContractProduct(o) _, err = StockOutDao.Add_StockOut(var_) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "出库失败"} c.ServeJSON() return } // 1、添加出库单 contract, _ := ContractDao.Read_Contract_ByT_number(T_contract_number) if contract.Id == 0 && T_type == 2 { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "合同编号错误!"} c.ServeJSON() return } if len(T_product) == 0 { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "产品明细不能为空"} c.ServeJSON() return } productList := lib.SplitString(T_product, "|") allProductList := []int{} for _, v := range productList { product_id, _ := strconv.Atoi(strings.Split(v, "-")[0]) allProductList = append(allProductList, product_id) product, _ := Basic.Read_Product_ById(product_id) num, _ := strconv.Atoi(strings.Split(v, "-")[1]) T_relation_sn := strings.Split(v, "-")[2] if T_relation_sn == "" && product.T_relation_sn == 1 { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("%s关联SN,请先添加SN!", product.T_name)} c.ServeJSON() return } if len(T_relation_sn) > 0 { snList := lib.SplitString(T_relation_sn, ",") num = len(snList) for _, sn := range snList { mqtt := Stock.Read_MqttUser(sn) // 根据IMEI查询上次入库的批次号 batchNumber, err := DeviceDao.Read_Device_BatchNumber_ByImei(mqtt.Imei) if err != nil { logs.Error(lib.FuncName(), err) } device := Stock.Device{ T_contract_number: T_contract_number, T_product_id: product_id, T_out_number: T_number, T_sn: sn, T_iccid: mqtt.Iccid, T_imei: mqtt.Imei, T_State: 1, T_project: T_project, T_batch_number: batchNumber, CreateTime: date, } _, err = DeviceDao.AddOrUpdate_Device(device, 1) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "出库失败"} c.ServeJSON() return } } } // 3、添加出库产品清单 stockOutProduct := Stock.StockOutProduct{ T_number: T_number, T_product_id: product_id, T_depot_id: T_depot_id, T_num: num, // 出库数量 T_date: T_date, // 出库日期 T_relation_sn: T_relation_sn, T_state: 1, } _, err = StockOutProductDao.Add_StockOutProduct(stockOutProduct) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "出库失败"} c.ServeJSON() return } // 4、更改合同产品列表清单 contractProduct, _ := ContractProductDao.Read_ContractProduct_ByT_number_T_product_id(T_contract_number, product_id) contractProduct.T_product_out += num if contractProduct.T_product_out > contractProduct.T_product_total && T_type == 2 { o.Rollback() p, _ := Basic.Read_Product_ById(product_id) c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("【%s】出库数量超过预计出库数量!", p.T_name)} c.ServeJSON() return } contractProduct.T_State = 2 if contractProduct.T_product_out == 0 { contractProduct.T_State = 1 } if contractProduct.T_product_out == contractProduct.T_product_total { contractProduct.T_State = 3 } err = ContractProductDao.Update_ContractProduct(contractProduct, "T_product_out", "T_State") if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "更新合同产品清单失败"} c.ServeJSON() return } // 5、更新产品库存列表 _, err = StockDao.AddOrUpdate_Stock(T_depot_id, product.Id, product.T_class, product.T_name, product.T_model, num, 1) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "更新库存失败" + err.Error()} c.ServeJSON() return } } o.Commit() o2 := orm.NewOrm() o2.Begin() ContractDao2 := Contract.NewContract(o2) ContractProductDao2 := Contract.NewContractProduct(o2) // 5、更新合同出库状态 var T_out int if contract.T_State == 1 { T_out = 2 // 查询合同产品清单是否全部都为已出库 state := ContractProductDao2.Read_ContractProduct_T_State_List(contract.T_number) if state == 1 { T_out = 1 } if state == 3 { T_out = 3 } } if T_out != contract.T_out { contract.T_out = T_out err = ContractDao2.Update_Contract(contract, "T_out") if err != nil { o2.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "更新合同出库状态失败"} c.ServeJSON() return } } o2.Commit() StockOut_Edit_StockMonth(T_date, T_depot_id, allProductList) NatsServer.AddUserLogs(c.User.T_uuid, "出库", "出库", var_) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: T_number} c.ServeJSON() return } func (c *StockController) StockOut_Edit_Delivery() { T_number := c.GetString("T_number") T_remark := c.GetString("T_remark") T_project := c.GetString("T_project") T_delivery_type, _ := c.GetInt("T_delivery_type") T_signer_unit := c.GetString("T_signer_unit") T_signer := c.GetString("T_signer") T_signer_phone := c.GetString("T_signer_phone") T_signer_date := c.GetString("T_signer_date") T_courier_number := c.GetString("T_courier_number") o := orm.NewOrm() StockOutDao := Stock.NewStockOut(o) stockOut, err := StockOutDao.Read_StockOut_ByT_number(T_number) if err != nil { c.Data["json"] = lib.JSONS{Code: 203, Msg: "出库编号错误!"} c.ServeJSON() return } if len(T_remark) > 0 { stockOut.T_remark = T_remark } if len(T_project) > 0 { stockOut.T_project = T_project } if T_delivery_type > 0 { stockOut.T_delivery_type = T_delivery_type } if len(T_signer_unit) > 0 { stockOut.T_signer_unit = T_signer_unit } if len(T_signer) > 0 { stockOut.T_signer = T_signer } if len(T_signer_phone) > 0 { stockOut.T_signer_phone = T_signer_phone } if len(T_signer_date) > 0 { stockOut.T_signer_date = T_signer_date } if len(T_courier_number) > 0 { stockOut.T_courier_number = T_courier_number } err = StockOutDao.Update_StockOut(stockOut, "T_remark", "T_delivery_type", "T_signer_unit", "T_signer", "T_signer_phone", "T_signer_date", "T_courier_number", "T_project") if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "出库失败"} c.ServeJSON() return } NatsServer.AddUserLogs(c.User.T_uuid, "出库", "修改发货单", stockOut) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: T_number} c.ServeJSON() return } func (c *StockController) StockOut_Edit() { T_number := c.GetString("T_number") // 出库单号 //T_depot_id, _ := c.GetInt("T_depot_id") T_date := c.GetString("T_date") T_receive := c.GetString("T_receive") T_project := c.GetString("T_project") T_product := c.GetString("T_product") T_remark := c.GetString("T_remark") date, is := lib.DateStrToTime(T_date) if !is { c.Data["json"] = lib.JSONS{Code: 202, Msg: "日期格式错误!"} c.ServeJSON() return } if date.Year() != time.Now().Year() && date.Month() != time.Now().Month() { T_date = "" } NatsServer.AddUserLogs(c.User.T_uuid, "仓库管理", "修改出库", T_product) o := orm.NewOrm() o.Begin() StockOutDao := Stock.NewStockOut(o) StockOutProductDao := Stock.NewStockOutProduct(o) StockDao := Stock.NewStock(o) DeviceDao := Stock.NewDevice(o) // 查询出库信息 StockOut, err := StockOutDao.Read_StockOut_ByT_number(T_number) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"} c.ServeJSON() return } T_old_date := StockOut.T_date // 查询出库产品信息 productOldList := StockOutProductDao.Read_StockOutProduct_List(StockOut.T_number) var oldProductList []dto.StockProduct var newProductList []dto.StockProduct productOldMap := map[int]dto.StockProduct{} allProductListMap := make(map[int]struct{}) for _, product := range productOldList { stockProduct := dto.StockProduct{ T_product_id: product.T_product_id, T_num: product.T_num, T_relation_sn: lib.SplitString(product.T_relation_sn, ","), } oldProductList = append(oldProductList, stockProduct) productOldMap[product.T_product_id] = stockProduct if _, ok := allProductListMap[product.T_product_id]; !ok { allProductListMap[product.T_product_id] = struct{}{} } } productNewList := lib.SplitString(T_product, "|") productNewMap := map[int]dto.StockProduct{} for _, v := range productNewList { product_id, _ := strconv.Atoi(strings.Split(v, "-")[0]) num, _ := strconv.Atoi(strings.Split(v, "-")[1]) T_relation_sn := strings.Split(v, "-")[2] snList := lib.SplitString(T_relation_sn, ",") if len(snList) > 0 { num = len(snList) } stockProduct := dto.StockProduct{ T_product_id: product_id, T_num: num, T_relation_sn: snList, } newProductList = append(newProductList, stockProduct) productNewMap[product_id] = stockProduct if _, ok := allProductListMap[product_id]; !ok { allProductListMap[product_id] = struct{}{} } } // 判断产品列表信息是否相同 StockProductListIsEqual, needDelete, needAdd, needEdit, snDiff := dto.StockProductListsEqual(oldProductList, newProductList) // 两次提交的数据相同,则不用修改 if !StockProductListIsEqual { if len(needDelete) > 0 { // 删除入库产品列表 for _, v := range needDelete { product, _ := Basic.Read_Product_ById(v.T_product_id) // 删除入库产品列表 err = StockOutProductDao.Delete_StockOutProduct(StockOut.T_number, StockOut.T_depot_id, v.T_product_id) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "删除产品入库信息失败!"} c.ServeJSON() return } if product.T_relation_sn == 1 { // 删除该入库单关联sn for _, sn := range v.T_relation_sn { err = DeviceDao.Delete_Device_ByT_out_number(StockOut.T_number, sn) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "删除入库设备失败"} c.ServeJSON() return } } } // 增加库存 _, err = StockDao.AddOrUpdate_Stock(StockOut.T_depot_id, product.Id, product.T_class, product.T_name, product.T_model, v.T_num, 2) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "更新库存信息失败"} c.ServeJSON() return } } } if len(needAdd) > 0 { // 新增入库产品列表 for _, v := range needAdd { product, _ := Basic.Read_Product_ById(v.T_product_id) if product.T_relation_sn == 1 && len(v.T_relation_sn) == 0 { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("%s关联SN,请先添加SN!", product.T_name)} c.ServeJSON() return } // 添加该入库单关联sn for _, sn := range v.T_relation_sn { mqtt := Stock.Read_MqttUser(sn) // 添加设备 device := Stock.Device{ T_contract_number: "", T_out_number: StockOut.T_number, T_product_id: v.T_product_id, T_in_number: "", T_sn: sn, T_iccid: mqtt.Iccid, T_imei: mqtt.Imei, T_State: 1, CreateTime: date, UpdateTime: StockOut.UpdateTime, } _, err = DeviceDao.AddOrUpdate_Device(device, 1) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: sn + "入库失败"} c.ServeJSON() return } } StockOutProduct := Stock.StockOutProduct{ T_number: T_number, T_product_id: v.T_product_id, T_depot_id: StockOut.T_depot_id, T_num: v.T_num, // 入库数量 T_date: StockOut.T_date, // 入库日期 T_relation_sn: strings.Join(v.T_relation_sn, ","), T_state: 1, } _, err = StockOutProductDao.Add_StockOutProduct(StockOutProduct) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "入库失败"} c.ServeJSON() return } // 减少库存 _, err = StockDao.AddOrUpdate_Stock(StockOut.T_depot_id, product.Id, product.T_class, product.T_name, product.T_model, v.T_num, 1) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "增加库存失败"} c.ServeJSON() return } } } if len(needEdit) > 0 { for _, v := range needEdit { product, _ := Basic.Read_Product_ById(v.T_product_id) StockOutProduct := Stock.StockOutProduct{ T_number: StockOut.T_number, T_product_id: v.T_product_id, T_depot_id: StockOut.T_depot_id, T_num: productNewMap[v.T_product_id].T_num, // 入库数量 T_date: StockOut.T_date, // 入库日期 T_state: 1, } // 出库数量比之前多,减少库存 var T_type int var T_num int if productNewMap[v.T_product_id].T_num > productOldMap[v.T_product_id].T_num { // 减少库存 T_type = 1 T_num = productNewMap[v.T_product_id].T_num - productOldMap[v.T_product_id].T_num } else { // 增加库存 T_type = 2 T_num = productOldMap[v.T_product_id].T_num - productNewMap[v.T_product_id].T_num } _, err = StockDao.AddOrUpdate_Stock(StockOut.T_depot_id, product.Id, product.T_class, product.T_name, product.T_model, T_num, T_type) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: err.Error()} c.ServeJSON() return } // 更新产品库存表 err = StockOutProductDao.Update_StockOutProduct(StockOutProduct) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "修改出库产品信息失败"} c.ServeJSON() return } } } for _, diff := range snDiff { product, _ := Basic.Read_Product_ById(diff.T_product_id) // 删除减少的sn if len(diff.T_delete_relation_sn) > 0 { for _, sn := range diff.T_delete_relation_sn { err = DeviceDao.Delete_Device_ByT_out_number(StockOut.T_number, sn) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: err.Error()} c.ServeJSON() return } } // 增加库存 _, err = StockDao.AddOrUpdate_Stock(StockOut.T_depot_id, product.Id, product.T_class, product.T_name, product.T_model, len(diff.T_delete_relation_sn), 2) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: err.Error()} c.ServeJSON() return } } if len(diff.T_add_relation_sn) > 0 { for _, sn := range diff.T_add_relation_sn { mqtt := Stock.Read_MqttUser(sn) // 添加设备 device := Stock.Device{ T_contract_number: "", T_out_number: StockOut.T_number, T_product_id: diff.T_product_id, T_in_number: "", T_sn: sn, T_iccid: mqtt.Iccid, T_imei: mqtt.Imei, T_State: 1, CreateTime: date, UpdateTime: StockOut.UpdateTime, } _, err = DeviceDao.AddOrUpdate_Device(device, 1) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: sn + "入库失败"} c.ServeJSON() return } } // 减少库存 _, err = StockDao.AddOrUpdate_Stock(StockOut.T_depot_id, product.Id, product.T_class, product.T_name, product.T_model, len(diff.T_add_relation_sn), 1) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "入库失败"} c.ServeJSON() return } } StockOutProduct := Stock.StockOutProduct{ T_number: StockOut.T_number, T_product_id: diff.T_product_id, T_depot_id: StockOut.T_depot_id, T_num: productNewMap[diff.T_product_id].T_num, // 入库数量 T_date: StockOut.T_date, // 入库日期 T_relation_sn: strings.Join(productNewMap[diff.T_product_id].T_relation_sn, ","), T_state: 1, } // 更新产品库存表 err = StockOutProductDao.Update_StockOutProduct(StockOutProduct) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "修改出库产品信息失败"} c.ServeJSON() return } } } StockOut.T_remark = T_remark if len(T_receive) > 0 { StockOut.T_receive = T_receive } if len(T_project) > 0 { StockOut.T_project = T_project } if len(T_date) > 0 { StockOut.T_date = T_date } err = StockOutDao.Update_StockOut(StockOut, "T_remark", "T_receive", "T_project", "T_date") if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "修改入库失败"} c.ServeJSON() return } o.Commit() if len(T_date) > 0 && T_old_date != T_date { // 修改出库产品日期 StockOutProductDao.Update_StockOutProduct_T_date(StockOut.T_number, T_date) DeviceDao.Update_Device_CreateTimeByT_out_number(StockOut.T_number, T_date) } if len(T_project) > 0 { DeviceDao.Update_Device_ByT_out_number_T_project(StockOut.T_number, T_project) } // 更新月份统计表 allProductList := []int{} for i, _ := range allProductListMap { allProductList = append(allProductList, i) } StockOut_Edit_StockMonth(StockOut.T_date, StockOut.T_depot_id, allProductList) NatsServer.AddUserLogs(c.User.T_uuid, "出库", "修改", StockOut) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: T_number} c.ServeJSON() return } // 删除出库 func (c *StockController) StockOut_Del() { T_number := c.GetString("T_number") // 入库单号 o := orm.NewOrm() o.Begin() StockOutDao := Stock.NewStockOut(o) StockOutProductDao := Stock.NewStockOutProduct(o) StockDao := Stock.NewStock(o) DeviceDao := Stock.NewDevice(o) // 查询出库信息 stockOut, err := StockOutDao.Read_StockOut_ByT_number(T_number) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"} c.ServeJSON() return } // 查询出库产品信息 productOldList := StockOutProductDao.Read_StockOutProduct_List(stockOut.T_number) var oldProductList []dto.StockProduct allProductList := []int{} for _, product := range productOldList { oldProductList = append(oldProductList, dto.StockProduct{ T_product_id: product.T_product_id, T_num: product.T_num, T_relation_sn: lib.SplitString(product.T_relation_sn, ","), }) allProductList = append(allProductList, product.T_product_id) } // 删除入库产品列表 for _, v := range oldProductList { product, _ := Basic.Read_Product_ById(v.T_product_id) // 删除入库产品列表 err = StockOutProductDao.Delete_StockOutProduct(stockOut.T_number, stockOut.T_depot_id, v.T_product_id) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "删除产品出库信息失败!"} c.ServeJSON() return } if product.T_relation_sn == 1 { // 删除该入库单关联sn for _, sn := range v.T_relation_sn { err = DeviceDao.Delete_Device_ByT_out_number(stockOut.T_number, sn) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "删除出库设备失败"} c.ServeJSON() return } } } // 增加库存 _, err = StockDao.AddOrUpdate_Stock(stockOut.T_depot_id, product.Id, product.T_class, product.T_name, product.T_model, v.T_num, 2) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "更新库存信息失败"} c.ServeJSON() return } } err = StockOutDao.Delete_StockOut(stockOut) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "删除出库失败"} c.ServeJSON() return } o.Commit() // 更新月份统计表 StockOut_Edit_StockMonth(stockOut.T_date, stockOut.T_depot_id, allProductList) NatsServer.AddUserLogs(c.User.T_uuid, "出库", "删除", stockOut) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: T_number} c.ServeJSON() return } // 导出出库单 func (c *StockController) StockOut_Excel() { // 查询 T_number := c.GetString("T_number") o := orm.NewOrm() StockOutDao := Stock.NewStockOut(o) StockOutProductDao := Stock.NewStockOutProduct(o) stockOut, err := StockOutDao.Read_StockOut_ByT_number(T_number) if err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"} c.ServeJSON() return } productList := StockOutProductDao.Read_StockOutProduct_List(stockOut.T_number) //productList = append(productList, productList...) //productList = append(productList, productList...) //productList = append(productList, productList...) var pList []Stock.StockOutProduct_R for _, v := range productList { pList = append(pList, Stock.StockOutProductToStockOutProduct_R(v)) } userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) stockOutDetail := Stock.StockOutToStockOut_Detail(stockOut, pList) T_date, _ := lib.DateStrToTime(stockOut.T_date) filename := fmt.Sprintf("冷链产品出库单(%s)", lib.GetRandstring(6, "0123456789", 0)) f := excelize.NewFile() // 设置单元格的值 Style1, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Bold: true, Size: 12, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"}, }) Style2, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Size: 11, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "left", Vertical: "center"}, }) Style3, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Size: 10, Family: "宋体", Bold: true}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true}, 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}, }, }) Style4, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Size: 11, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true}, 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}, }, }) productList2 := lib.ChunkBy(productList, 10) for i, products := range productList2 { if len(products) < 10 { products = append(products, make([]Stock.StockOutProduct, 10-len(products))...) } row := i*17 + 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) f.SetRowStyle("Sheet1", row, row, Style1) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("宝智达科技产品进销存统计表")) f.SetRowHeight("Sheet1", row, 20) row += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) f.SetRowStyle("Sheet1", row, row, Style1) title := "硬件出库单" if len(productList2) > 1 { title += fmt.Sprintf(" %d/%d", i+1, len(productList2)) } f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), title) f.SetRowHeight("Sheet1", row, 20) row += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) f.SetRowStyle("Sheet1", row, row, Style2) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("出库单号:%s", stockOut.T_number)) f.SetRowHeight("Sheet1", row, 20) row += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) f.SetRowStyle("Sheet1", row, row, Style2) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("项目名称:%s", stockOut.T_project)) f.SetRowHeight("Sheet1", row, 20) row += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) f.SetRowStyle("Sheet1", row, row, Style2) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("领用时间:%s", T_date.Format("2006年01月02日"))) f.SetRowHeight("Sheet1", row, 20) // 这里设置表头 row += 1 f.SetRowHeight("Sheet1", row, 20) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), "序号") f.SetCellValue("Sheet1", fmt.Sprintf("B%d", row), "产品名称") f.SetCellValue("Sheet1", fmt.Sprintf("C%d", row), "型号") f.SetCellValue("Sheet1", fmt.Sprintf("D%d", row), "单位") f.SetCellValue("Sheet1", fmt.Sprintf("E%d", row), "领用数量") f.SetCellValue("Sheet1", fmt.Sprintf("F%d", row), "备注") // 设置列宽 f.SetColWidth("Sheet1", "A", "A", 5) f.SetColWidth("Sheet1", "B", "B", 20) f.SetColWidth("Sheet1", "C", "C", 12) f.SetColWidth("Sheet1", "D", "D", 10) f.SetColWidth("Sheet1", "E", "E", 10) f.SetColWidth("Sheet1", "F", "F", 15) f.SetCellStyle("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row), Style3) sRow := row // 循环写入数据 for j, v := range products { row += 1 product, _ := Basic.Read_Product_ById(v.T_product_id) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), j+1) f.SetCellValue("Sheet1", fmt.Sprintf("B%d", row), product.T_name) f.SetCellValue("Sheet1", fmt.Sprintf("C%d", row), product.T_model) f.SetCellValue("Sheet1", fmt.Sprintf("D%d", row), product.T_spec) if v.T_num > 0 { f.SetCellValue("Sheet1", fmt.Sprintf("E%d", row), v.T_num) f.SetCellValue("Sheet1", fmt.Sprintf("F%d", row), stockOut.T_remark) } } f.SetCellStyle("Sheet1", fmt.Sprintf("A%d", sRow), fmt.Sprintf("F%d", row), Style4) row += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("C%d", row)) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("制单:%s", c.User.T_name)) f.MergeCell("Sheet1", fmt.Sprintf("D%d", row), fmt.Sprintf("F%d", row)) f.SetCellValue("Sheet1", fmt.Sprintf("D%d", row), fmt.Sprintf("领用人:%s", stockOutDetail.T_receive_name)) f.SetRowStyle("Sheet1", row, row, Style2) f.SetRowHeight("Sheet1", row, 20) } // 保存文件 if err = f.SaveAs("ofile/" + filename + ".xlsx"); err != nil { fmt.Println(err) } var url string //// 上传 OSS nats := natslibs.NewNats(Nats.Nats, conf.NatsSubj_Prefix) url, is := nats.Qiniu_UploadFile(lib.GetCurrentDirectory()+"/ofile/"+filename+".xlsx", "ofile/"+filename+".xlsx") if !is { c.Data["json"] = lib.JSONS{Code: 202, Msg: "oss!"} c.ServeJSON() return } //删除目录 err = os.Remove("ofile/" + filename + ".xlsx") if err != nil { logs.Error(lib.FuncName(), err) } c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: url} c.ServeJSON() return } func (c *StockController) StockOut_Excel_Batch() { // 查询 T_number_list := c.GetString("T_number_list") o := orm.NewOrm() StockOutDao := Stock.NewStockOut(o) StockOutProductDao := Stock.NewStockOutProduct(o) list := strings.Split(strings.Trim(T_number_list, "|"), "|") userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) filename := fmt.Sprintf("冷链产品出库单(%s)", lib.GetRandstring(6, "0123456789", 0)) f := excelize.NewFile() // 设置单元格的值 Style1, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Bold: true, Size: 12, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"}, }) Style2, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Size: 11, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "left", Vertical: "center"}, }) Style3, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Size: 10, Family: "宋体", Bold: true}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true}, 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}, }, }) Style4, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Size: 11, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true}, 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}, }, }) var num int for _, T_number := range list { stockOut, err := StockOutDao.Read_StockOut_ByT_number(T_number) if err != nil { c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"} c.ServeJSON() return } productList := StockOutProductDao.Read_StockOutProduct_List(stockOut.T_number) var pList []Stock.StockOutProduct_R for _, v := range productList { pList = append(pList, Stock.StockOutProductToStockOutProduct_R(v)) } stockOutDetail := Stock.StockOutToStockOut_Detail(stockOut, pList) T_date, _ := lib.DateStrToTime(stockOut.T_date) productList2 := lib.ChunkBy(productList, 10) for i, products := range productList2 { if len(products) < 10 { products = append(products, make([]Stock.StockOutProduct, 10-len(products))...) } row := num*18 + 1 num += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) f.SetRowStyle("Sheet1", row, row, Style1) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("宝智达科技产品进销存统计表")) f.SetRowHeight("Sheet1", row, 20) row += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) f.SetRowStyle("Sheet1", row, row, Style1) title := "硬件出库单" if len(productList2) > 1 { title += fmt.Sprintf(" %d/%d", i+1, len(productList2)) } f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), title) f.SetRowHeight("Sheet1", row, 20) row += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) f.SetRowStyle("Sheet1", row, row, Style2) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("出库单号:%s", stockOut.T_number)) f.SetRowHeight("Sheet1", row, 20) row += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) f.SetRowStyle("Sheet1", row, row, Style2) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("项目名称:%s", stockOut.T_project)) f.SetRowHeight("Sheet1", row, 20) row += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) f.SetRowStyle("Sheet1", row, row, Style2) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("领用时间:%s", T_date.Format("2006年01月02日"))) f.SetRowHeight("Sheet1", row, 20) // 这里设置表头 row += 1 f.SetRowHeight("Sheet1", row, 20) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), "序号") f.SetCellValue("Sheet1", fmt.Sprintf("B%d", row), "产品名称") f.SetCellValue("Sheet1", fmt.Sprintf("C%d", row), "型号") f.SetCellValue("Sheet1", fmt.Sprintf("D%d", row), "单位") f.SetCellValue("Sheet1", fmt.Sprintf("E%d", row), "领用数量") f.SetCellValue("Sheet1", fmt.Sprintf("F%d", row), "备注") // 设置列宽 f.SetColWidth("Sheet1", "A", "A", 5) f.SetColWidth("Sheet1", "B", "B", 20) f.SetColWidth("Sheet1", "C", "C", 12) f.SetColWidth("Sheet1", "D", "D", 10) f.SetColWidth("Sheet1", "E", "E", 10) f.SetColWidth("Sheet1", "F", "F", 15) f.SetCellStyle("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row), Style3) sRow := row // 循环写入数据 for j, v := range products { row += 1 product, _ := Basic.Read_Product_ById(v.T_product_id) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), j+1) f.SetCellValue("Sheet1", fmt.Sprintf("B%d", row), product.T_name) f.SetCellValue("Sheet1", fmt.Sprintf("C%d", row), product.T_model) f.SetCellValue("Sheet1", fmt.Sprintf("D%d", row), product.T_spec) if v.T_num > 0 { f.SetCellValue("Sheet1", fmt.Sprintf("E%d", row), v.T_num) f.SetCellValue("Sheet1", fmt.Sprintf("F%d", row), stockOut.T_remark) } } f.SetCellStyle("Sheet1", fmt.Sprintf("A%d", sRow), fmt.Sprintf("F%d", row), Style4) row += 1 f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("C%d", row)) f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("制单:%s", c.User.T_name)) f.MergeCell("Sheet1", fmt.Sprintf("D%d", row), fmt.Sprintf("F%d", row)) f.SetCellValue("Sheet1", fmt.Sprintf("D%d", row), fmt.Sprintf("领用人:%s", stockOutDetail.T_receive_name)) f.SetRowStyle("Sheet1", row, row, Style2) f.SetRowHeight("Sheet1", row, 20) // 空一行 row += 1 //f.MergeCell("Sheet1", fmt.Sprintf("A%d", row), fmt.Sprintf("F%d", row)) //f.SetRowStyle("Sheet1", row, row, Style1) //f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), "") // 插入下一页分页符 f.InsertPageBreak("Sheet1", fmt.Sprintf("A%d", row)) } } // 保存文件 if err := f.SaveAs("ofile/" + filename + ".xlsx"); err != nil { fmt.Println(err) } var url string //// 上传 OSS nats := natslibs.NewNats(Nats.Nats, conf.NatsSubj_Prefix) url, is := nats.Qiniu_UploadFile(lib.GetCurrentDirectory()+"/ofile/"+filename+".xlsx", "ofile/"+filename+".xlsx") if !is { c.Data["json"] = lib.JSONS{Code: 202, Msg: "oss!"} c.ServeJSON() return } //删除目录 err := os.Remove("ofile/" + filename + ".xlsx") if err != nil { logs.Error(lib.FuncName(), err) } c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: url} c.ServeJSON() return } func StockOut_Edit_StockMonth(T_date string, T_depot_id int, allProductList []int) error { date, _ := lib.DateStrToTime(T_date) //if date.Year() == time.Now().Year() && date.Month() == time.Now().Month() { // // 修改本月数据不同步库存 // return nil //} //T_month := date.Format("2006-01") months := generateMonthList(date, "out") o := orm.NewOrm() StockOutDao := Stock.NewStockOut(o) StockMonthDao := Stock.NewStockMonth(o) StockOutProductDao := Stock.NewStockOutProduct(o) StockInProductDao := Stock.NewStockInProduct(o) for _, T_product_id := range allProductList { for _, T_month := range months { // 获取当前产品本月出入库数量 lastMonth := StockMonthDao.Read_LastMonth_StockMonth_ByT_depot_id_T_product_id(T_depot_id, T_product_id, T_month) stockMonth := StockMonthDao.Read_StockMonth_ByT_depot_id_T_product_id(T_depot_id, T_product_id, T_month) if stockMonth.Id > 0 { // 修改 stockMonth.T_out = StockOutProductDao.Read_StockOut_Total(T_depot_id, T_product_id, T_month) stockMonth.T_return = StockInProductDao.Read_StockReturn_Total(T_depot_id, T_product_id, T_month) if len(lastMonth) > 0 { stockMonth.T_beginning = lastMonth[0].T_ending } else { stockMonth.T_beginning = 0 } // 期末库存 = 期初库存+入库-出库 stockMonth.T_ending = stockMonth.T_beginning + stockMonth.T_in - stockMonth.T_out err := StockMonthDao.Update_StockMonth(stockMonth, "T_out", "T_return", "T_beginning", "T_ending") if err != nil { return err } } else { product, _ := Basic.Read_Product_ById(T_product_id) // 添加库存记录 stockMonth = Stock.StockMonth{ T_depot_id: T_depot_id, T_product_id: T_product_id, T_product_class: product.T_class, T_month: T_month, } // 获取当前产品本月出入库数量 stockMonth.T_in = StockInProductDao.Read_StockIn_Total(T_depot_id, T_product_id, T_month) stockMonth.T_out = StockOutProductDao.Read_StockOut_Total(T_depot_id, T_product_id, T_month) stockMonth.T_return = StockInProductDao.Read_StockReturn_Total(T_depot_id, T_product_id, T_month) if len(lastMonth) > 0 { stockMonth.T_beginning = lastMonth[0].T_ending } else { stockMonth.T_beginning = 0 } // 期末库存 = 期初库存+入库-出库 stockMonth.T_ending = stockMonth.T_beginning + stockMonth.T_in - stockMonth.T_out stockMonth.T_project = StockOutDao.Read_StockOut_T_contract_number(T_depot_id, T_product_id, T_month) _, err := StockMonthDao.Add_StockMonth(stockMonth) if err != nil { return err } } } } return nil } func Cron_StockMonth() { //创建一个定时任务对象 c := cron.New(cron.WithSeconds()) //给对象增加定时任务 // @monthly 每月运行一次,每月第一天午夜 0 0 0 1 * * //c.AddFunc("0 */1 * * * ?", Cron_StockMonth_Add) c.AddFunc("@monthly", Cron_StockMonth_Add) //启动定时任务 c.Start() defer c.Stop() //查询语句,阻塞,让main函数不退出,保持程序运行 select {} } // 保存每月入库出库明细 func Cron_StockMonth_Add() { T_month := time.Now().Format("2006-01") //T_month := time.Now().AddDate(0, -1, 0).Format("2006-01") logs.Info("开始统计" + T_month + "库存明细数据") o := orm.NewOrm() StockDao := Stock.NewStock(o) StockOutDao := Stock.NewStockOut(o) StockMonthDao := Stock.NewStockMonth(o) StockOutProductDao := Stock.NewStockOutProduct(o) StockInProductDao := Stock.NewStockInProduct(o) stockList, _ := StockDao.Read_Stock_List(0, 0, "", "", 0, 9999) for _, stock := range stockList { lastMonth := StockMonthDao.Read_LastMonth_StockMonth_ByT_depot_id_T_product_id(stock.T_depot_id, stock.T_product_id, T_month) stockMonth := StockMonthDao.Read_StockMonth_ByT_depot_id_T_product_id(stock.T_depot_id, stock.T_product_id, T_month) if stockMonth.Id > 0 { // 修改 stockMonth.T_in = StockInProductDao.Read_StockIn_Total(stock.T_depot_id, stock.T_product_id, T_month) stockMonth.T_out = StockOutProductDao.Read_StockOut_Total(stock.T_depot_id, stock.T_product_id, T_month) stockMonth.T_return = StockInProductDao.Read_StockReturn_Total(stock.T_depot_id, stock.T_product_id, T_month) if len(lastMonth) > 0 { stockMonth.T_beginning = lastMonth[0].T_ending } else { stockMonth.T_beginning = 0 } // 期末库存 = 期初库存+入库-出库 stockMonth.T_ending = stockMonth.T_beginning + stockMonth.T_in - stockMonth.T_out err := StockMonthDao.Update_StockMonth(stockMonth, "T_in", "T_out", "T_beginning", "T_ending", "T_return") if err != nil { NatsServer.AddSysLogs("库存明细统计", fmt.Sprintf("库存明细统计失败%s:%d:%d", T_month, stock.T_depot_id, stock.T_product_id), stockMonth) } } else { stockMonth = Stock.StockMonth{ T_depot_id: stock.T_depot_id, T_product_id: stock.T_product_id, T_product_class: stock.T_product_class, T_month: T_month, } // 获取当前产品本月出入库数量 stockMonth.T_in = StockInProductDao.Read_StockIn_Total(stock.T_depot_id, stock.T_product_id, T_month) stockMonth.T_out = StockOutProductDao.Read_StockOut_Total(stock.T_depot_id, stock.T_product_id, T_month) if len(lastMonth) > 0 { stockMonth.T_beginning = lastMonth[0].T_ending } else { stockMonth.T_beginning = 0 } // 期末库存 = 期初库存+入库-出库 stockMonth.T_ending = stockMonth.T_beginning + stockMonth.T_in - stockMonth.T_out stockMonth.T_project = StockOutDao.Read_StockOut_T_contract_number(stock.T_depot_id, stock.T_product_id, T_month) _, err := StockMonthDao.Add_StockMonth(stockMonth) if err != nil { NatsServer.AddSysLogs("库存明细统计", fmt.Sprintf("库存明细统计失败%s:%d:%d", T_month, stock.T_depot_id, stock.T_product_id), stockMonth) } } } } func generateMonthList(startMonth time.Time, t_type string) []string { var months []string endMonth := time.Now() if t_type == "in" { endMonth = endMonth.AddDate(0, 1, 0) } for month := startMonth; month.Before(endMonth); month = month.AddDate(0, 1, 0) { months = append(months, month.Format("2006-01")) } return months } // 我的申请列表 func (c *StockController) StockOut_Apply_List() { // 分页参数 初始化 page, _ := c.GetInt("page") if page < 1 { page = 1 } page_z, _ := c.GetInt("page_z") if page_z < 1 { page_z = conf.Page_size } // 查询 T_depot_id, _ := c.GetInt("T_depot_id") T_state, _ := c.GetInt("T_state") T_contract_number := c.GetString("T_contract_number") T_start_date := c.GetString("T_start_date") T_end_date := c.GetString("T_end_date") T_name := c.GetString("T_name") userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) Basic.Read_Depot_All_Map() StockOutDao := Stock.NewStockOut(orm.NewOrm()) R_List, R_cnt := StockOutDao.Read_StockOut_Audit_List(c.User.T_uuid, T_name, Stock.StockInTypeApply, T_state, T_depot_id, T_contract_number, T_start_date, T_end_date, page, page_z) var r_jsons lib.R_JSONS r_jsons.Num = R_cnt r_jsons.Data = R_List r_jsons.Page = page r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(page_z))) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons} c.ServeJSON() return } // 出库申请 func (c *StockController) StockOut_Apply() { rand_x := 0 T_number := "" o := orm.NewOrm() StockOutDao := Stock.NewStockOut(o) for true { T_number = "CK-" + lib.GetRandstring(8, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", int64(rand_x)) _, err := StockOutDao.Read_StockOut_ByT_number(T_number) if err != nil && err.Error() == orm.ErrNoRows.Error() { break } rand_x += 1 } T_contract_number := c.GetString("T_contract_number") T_depot_id, _ := c.GetInt("T_depot_id") T_product := c.GetString("T_product") T_remark := c.GetString("T_remark") T_project := c.GetString("T_project") T_company_name := c.GetString("T_company_name") T_payment_method := c.GetString("T_payment_method") T_receive := c.GetString("T_receive") if len(T_company_name) == 0 { c.Data["json"] = lib.JSONS{Code: 202, Msg: "公司名称不能为空"} c.ServeJSON() return } if len(T_payment_method) == 0 { c.Data["json"] = lib.JSONS{Code: 202, Msg: "付款方式不能为空"} c.ServeJSON() return } if len(T_receive) == 0 { T_receive = c.User.T_uuid } var_ := Stock.StockOut{ T_number: T_number, T_contract_number: T_contract_number, T_depot_id: T_depot_id, T_type: 1, T_application_date: time.Now().Format("2006-01-02"), T_receive: T_receive, T_remark: T_remark, T_project: T_project, T_submit: c.User.T_uuid, T_state: Stock.StockOutWaitAudit, T_company_name: T_company_name, T_payment_method: T_payment_method, } o.Begin() StockOutProductDao := Stock.NewStockOutProduct(o) StockDao := Stock.NewStock(o) _, err := StockOutDao.Add_StockOut(var_) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "出库失败"} c.ServeJSON() return } // 1、添加出库单 if len(T_product) == 0 { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "产品明细不能为空"} c.ServeJSON() return } productList := lib.SplitString(T_product, "|") allProductList := []int{} for _, v := range productList { product_id, _ := strconv.Atoi(strings.Split(v, "-")[0]) allProductList = append(allProductList, product_id) product, _ := Basic.Read_Product_ById(product_id) num, _ := strconv.Atoi(strings.Split(v, "-")[1]) if num == 0 { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("%s出库数量不能为0!", product.T_name)} c.ServeJSON() return } // 2、添加出库产品清单 stockOutProduct := Stock.StockOutProduct{ T_number: T_number, T_product_id: product_id, T_depot_id: T_depot_id, T_num: num, // 出库数量 T_state: 2, } _, err = StockOutProductDao.Add_StockOutProduct(stockOutProduct) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "申请出库失败"} c.ServeJSON() return } // 3、增加占用库存 _, err = StockDao.AddOrUpdate_Occupy_Stock(T_depot_id, product.Id, product.T_class, product.T_name, product.T_model, num, 2) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "更新占用库存失败" + err.Error()} c.ServeJSON() return } } o.Commit() NatsServer.AddUserLogs(c.User.T_uuid, "出库申请", "出库申请", var_) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: T_number} c.ServeJSON() return } // 修改出库申请 func (c *StockController) StockOut_Apply_Edit() { T_number := c.GetString("T_number") // 出库单号 //T_depot_id, _ := c.GetInt("T_depot_id") T_project := c.GetString("T_project") T_product := c.GetString("T_product") T_remark := c.GetString("T_remark") T_receive := c.GetString("T_receive") T_company_name := c.GetString("T_company_name") T_payment_method := c.GetString("T_payment_method") NatsServer.AddUserLogs(c.User.T_uuid, "仓库管理", "修改出库", T_product) o := orm.NewOrm() o.Begin() StockOutDao := Stock.NewStockOut(o) StockOutProductDao := Stock.NewStockOutProduct(o) StockDao := Stock.NewStock(o) // 查询入库信息 StockOut, err := StockOutDao.Read_StockOut_ByT_number(T_number) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"} c.ServeJSON() return } if StockOut.T_state == Stock.StockOutAlreadyOut { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "当前出库单已出库,不能修改!"} c.ServeJSON() return } // 查询入库产品信息 productOldList := StockOutProductDao.Read_StockOutProduct_List(StockOut.T_number) var oldProductList []dto.StockProduct var newProductList []dto.StockProduct productOldMap := map[int]dto.StockProduct{} allProductListMap := make(map[int]struct{}) for _, product := range productOldList { stockProduct := dto.StockProduct{ T_product_id: product.T_product_id, T_num: product.T_num, T_relation_sn: lib.SplitString(product.T_relation_sn, ","), } oldProductList = append(oldProductList, stockProduct) productOldMap[product.T_product_id] = stockProduct if _, ok := allProductListMap[product.T_product_id]; !ok { allProductListMap[product.T_product_id] = struct{}{} } if StockOut.T_state != Stock.StockOutAuditManagerUnPass && StockOut.T_state != Stock.StockOutAuditFinanceUnPass { // 减少占用库存 product2, _ := Basic.Read_Product_ById(product.T_product_id) _, err = StockDao.AddOrUpdate_Occupy_Stock(StockOut.T_depot_id, product2.Id, product2.T_class, product2.T_name, product2.T_model, product.T_num, 1) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "更新占用库存失败"} c.ServeJSON() return } } } productNewList := lib.SplitString(T_product, "|") productNewMap := map[int]dto.StockProduct{} for _, v := range productNewList { product_id, _ := strconv.Atoi(strings.Split(v, "-")[0]) product, _ := Basic.Read_Product_ById(product_id) num, _ := strconv.Atoi(strings.Split(v, "-")[1]) if num == 0 { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("%s出库数量不能为0!", product.T_name)} c.ServeJSON() return } T_relation_sn := strings.Split(v, "-")[2] stockProduct := dto.StockProduct{ T_product_id: product_id, T_num: num, T_relation_sn: lib.SplitString(T_relation_sn, ","), } newProductList = append(newProductList, stockProduct) productNewMap[product_id] = stockProduct if _, ok := allProductListMap[product_id]; !ok { allProductListMap[product_id] = struct{}{} } // 增加占用库存 _, err = StockDao.AddOrUpdate_Occupy_Stock(StockOut.T_depot_id, product.Id, product.T_class, product.T_name, product.T_model, num, 2) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "更新占用库存失败"} c.ServeJSON() return } } // 判断产品列表信息是否相同 StockProductListIsEqual, needDelete, needAdd, needEdit, _ := dto.StockProductListsEqual(oldProductList, newProductList) // 两次提交的数据相同,则不用修改 if !StockProductListIsEqual { if len(needDelete) > 0 { // 删除入库产品列表 for _, v := range needDelete { // 删除入库产品列表 err = StockOutProductDao.Delete_StockOutProduct(StockOut.T_number, StockOut.T_depot_id, v.T_product_id) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "删除产品入库信息失败!"} c.ServeJSON() return } } } if len(needAdd) > 0 { // 新增入库产品列表 for _, v := range needAdd { StockOutProduct := Stock.StockOutProduct{ T_number: T_number, T_product_id: v.T_product_id, T_depot_id: StockOut.T_depot_id, T_num: v.T_num, // 出库数量 T_state: 1, } _, err = StockOutProductDao.Add_StockOutProduct(StockOutProduct) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "入库失败"} c.ServeJSON() return } } } if len(needEdit) > 0 { for _, v := range needEdit { StockOutProduct := Stock.StockOutProduct{ T_number: StockOut.T_number, T_product_id: v.T_product_id, T_depot_id: StockOut.T_depot_id, T_num: productNewMap[v.T_product_id].T_num, // 入库数量 T_state: 1, } // 更新产品表 err = StockOutProductDao.Update_StockOutProduct(StockOutProduct) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "修改出库产品信息失败"} c.ServeJSON() return } } } } StockOut.T_remark = T_remark if len(T_project) > 0 { StockOut.T_project = T_project } if len(T_company_name) > 0 { StockOut.T_company_name = T_company_name } if len(T_payment_method) > 0 { StockOut.T_payment_method = T_payment_method } if len(T_receive) > 0 { StockOut.T_receive = T_receive } StockOut.T_state = Stock.StockOutWaitAudit err = StockOutDao.Update_StockOut(StockOut, "T_remark", "T_receive", "T_project", "T_company_name", "T_payment_method", "T_state") if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "修改入库失败"} c.ServeJSON() return } o.Commit() NatsServer.AddUserLogs(c.User.T_uuid, "出库申请", "修改", StockOut) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: T_number} c.ServeJSON() return } // 删除出库申请 func (c *StockController) StockOut_Apply_Del() { T_number := c.GetString("T_number") // 入库单号 o := orm.NewOrm() o.Begin() StockOutDao := Stock.NewStockOut(o) StockOutProductDao := Stock.NewStockOutProduct(o) StockDao := Stock.NewStock(o) // 查询出库信息 stockOut, err := StockOutDao.Read_StockOut_ByT_number(T_number) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"} c.ServeJSON() return } // 查询出库产品信息 productOldList := StockOutProductDao.Read_StockOutProduct_List(stockOut.T_number) var oldProductList []dto.StockProduct allProductList := []int{} for _, product := range productOldList { oldProductList = append(oldProductList, dto.StockProduct{ T_product_id: product.T_product_id, T_num: product.T_num, T_relation_sn: lib.SplitString(product.T_relation_sn, ","), }) allProductList = append(allProductList, product.T_product_id) } // 删除入库产品列表 for _, v := range oldProductList { product, _ := Basic.Read_Product_ById(v.T_product_id) // 删除入库产品列表 err = StockOutProductDao.Delete_StockOutProduct(stockOut.T_number, stockOut.T_depot_id, v.T_product_id) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "删除产品出库信息失败!"} c.ServeJSON() return } // 减少占用库存 _, err = StockDao.AddOrUpdate_Occupy_Stock(stockOut.T_depot_id, product.Id, product.T_class, product.T_name, product.T_model, v.T_num, 1) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "更新占用库存失败" + err.Error()} c.ServeJSON() return } } err = StockOutDao.Delete_StockOut(stockOut) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "删除出库失败"} c.ServeJSON() return } o.Commit() NatsServer.AddUserLogs(c.User.T_uuid, "出库申请", "删除", stockOut) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: T_number} c.ServeJSON() return } // 财务 func (c *StockController) StockOut_Finance_List() { // 分页参数 初始化 page, _ := c.GetInt("page") if page < 1 { page = 1 } page_z, _ := c.GetInt("page_z") if page_z < 1 { page_z = conf.Page_size } // 查询 T_depot_id, _ := c.GetInt("T_depot_id") T_state, _ := c.GetInt("T_state") T_contract_number := c.GetString("T_contract_number") T_start_date := c.GetString("T_start_date") T_end_date := c.GetString("T_end_date") T_name := c.GetString("T_name") userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) Basic.Read_Depot_All_Map() StockOutDao := Stock.NewStockOut(orm.NewOrm()) R_List, R_cnt := StockOutDao.Read_StockOut_Audit_List("", T_name, Stock.StockOutTypeFinance, T_state, T_depot_id, T_contract_number, T_start_date, T_end_date, page, page_z) var r_jsons lib.R_JSONS r_jsons.Num = R_cnt r_jsons.Data = R_List r_jsons.Page = page r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(page_z))) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons} c.ServeJSON() return } // 管理员 func (c *StockController) StockOut_Manager_List() { // 分页参数 初始化 page, _ := c.GetInt("page") if page < 1 { page = 1 } page_z, _ := c.GetInt("page_z") if page_z < 1 { page_z = conf.Page_size } // 查询 T_depot_id, _ := c.GetInt("T_depot_id") T_state, _ := c.GetInt("T_state") T_contract_number := c.GetString("T_contract_number") T_start_date := c.GetString("T_start_date") T_end_date := c.GetString("T_end_date") T_name := c.GetString("T_name") userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) Basic.Read_Depot_All_Map() StockOutDao := Stock.NewStockOut(orm.NewOrm()) R_List, R_cnt := StockOutDao.Read_StockOut_Audit_List("", T_name, Stock.StockOutTypeManager, T_state, T_depot_id, T_contract_number, T_start_date, T_end_date, page, page_z) var r_jsons lib.R_JSONS r_jsons.Num = R_cnt r_jsons.Data = R_List r_jsons.Page = page r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(page_z))) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons} c.ServeJSON() return } // 仓管 func (c *StockController) StockOut_Warehouse_List() { // 分页参数 初始化 page, _ := c.GetInt("page") if page < 1 { page = 1 } page_z, _ := c.GetInt("page_z") if page_z < 1 { page_z = conf.Page_size } // 查询 T_depot_id, _ := c.GetInt("T_depot_id") T_state, _ := c.GetInt("T_state") T_contract_number := c.GetString("T_contract_number") T_start_date := c.GetString("T_start_date") T_end_date := c.GetString("T_end_date") T_name := c.GetString("T_name") userList, _ := NatsServer.Read_User_List_All() Account.Read_User_All_Map(userList) Basic.Read_Depot_All_Map() StockOutDao := Stock.NewStockOut(orm.NewOrm()) R_List, R_cnt := StockOutDao.Read_StockOut_Audit_List(c.User.T_uuid, T_name, Stock.StockOutTypeWarehouse, T_state, T_depot_id, T_contract_number, T_start_date, T_end_date, page, page_z) var r_jsons lib.R_JSONS r_jsons.Num = R_cnt r_jsons.Data = R_List r_jsons.Page = page r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(page_z))) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons} c.ServeJSON() return } // 财务/总经理审核 func (c *StockController) StockOut_Audit() { T_number := c.GetString("T_number") // 出库单号 //T_depot_id, _ := c.GetInt("T_depot_id") T_audit, _ := c.GetInt("T_audit") // 审核 2财务通过 3财务不通过 4总经理通过 5总经理不通过 6已出库 T_approval_opinion := c.GetString("T_approval_opinion") // 审批意见 T_approval_img := c.GetString("T_approval_img") // 审批意见 T_type := c.GetString("T_type") // 类型 Finance Manager o := orm.NewOrm() o.Begin() StockOutDao := Stock.NewStockOut(o) StockDao := Stock.NewStock(o) StockOutProductDao := Stock.NewStockOutProduct(o) StockOut, err := StockOutDao.Read_StockOut_ByT_number(T_number) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"} c.ServeJSON() return } StockOut.T_state = T_audit if T_type == Stock.StockOutTypeFinance { StockOut.T_finance_approval_opinion = T_approval_opinion StockOut.T_finance_approval_img = T_approval_img } else { StockOut.T_manager_approval_opinion = T_approval_opinion StockOut.T_manager_approval_img = T_approval_img } if T_audit == Stock.StockOutAuditFinanceUnPass || T_audit == Stock.StockOutAuditManagerUnPass { productList := StockOutProductDao.Read_StockOutProduct_List(StockOut.T_number) for _, v := range productList { product, _ := Basic.Read_Product_ById(v.T_product_id) _, err = StockDao.AddOrUpdate_Occupy_Stock(StockOut.T_depot_id, product.Id, product.T_class, product.T_name, product.T_model, v.T_num, 1) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: err.Error()} c.ServeJSON() return } } } err = StockOutDao.Update_StockOut(StockOut, "T_state", "T_finance_approval_opinion", "T_manager_approval_opinion", "T_finance_approval_img", "T_manager_approval_img") if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "出库审批失败"} c.ServeJSON() return } o.Commit() NatsServer.AddUserLogs(c.User.T_uuid, "出库申请", "审批", StockOut) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: T_number} c.ServeJSON() return } // 仓管出库 func (c *StockController) StockOut_Warehouse() { T_number := c.GetString("T_number") // 出库单号 T_date := c.GetString("T_date") date, is := lib.DateStrToTime(T_date) if !is { c.Data["json"] = lib.JSONS{Code: 202, Msg: "日期格式错误!"} c.ServeJSON() return } NatsServer.AddUserLogs(c.User.T_uuid, "仓库管理", "确认出库", T_number) o := orm.NewOrm() o.Begin() StockOutDao := Stock.NewStockOut(o) StockOutProductDao := Stock.NewStockOutProduct(o) DeviceDao := Stock.NewDevice(o) StockDao := Stock.NewStock(o) // 查询入库信息 StockOut, err := StockOutDao.Read_StockOut_ByT_number(T_number) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"} c.ServeJSON() return } T_product := c.GetString("T_product") productList := lib.SplitString(T_product, "|") allProductList := []int{} for _, v := range productList { product_id, _ := strconv.Atoi(strings.Split(v, "-")[0]) allProductList = append(allProductList, product_id) product, _ := Basic.Read_Product_ById(product_id) num, _ := strconv.Atoi(strings.Split(v, "-")[1]) if num == 0 { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("%s出库数量不能为0!", product.T_name)} c.ServeJSON() return } T_relation_sn := strings.Split(v, "-")[2] if T_relation_sn == "" && product.T_relation_sn == 1 { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("%s关联SN,请先添加SN!", product.T_name)} c.ServeJSON() return } if len(T_relation_sn) > 0 { snList := strings.Split(T_relation_sn, ",") if product.T_relation_sn == 1 && num != len(snList) { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("%s SN数量与出库数量不一致,请核查!", product.T_name)} c.ServeJSON() return } if len(snList) > 0 { for _, sn := range snList { mqtt := Stock.Read_MqttUser(sn) // 根据IMEI查询上次入库的批次号 batchNumber, err := DeviceDao.Read_Device_BatchNumber_ByImei(mqtt.Imei) if err != nil { logs.Error(lib.FuncName(), err) } device := Stock.Device{ T_contract_number: StockOut.T_contract_number, T_product_id: product_id, T_out_number: T_number, T_sn: sn, T_iccid: mqtt.Iccid, T_imei: mqtt.Imei, T_State: 1, T_project: StockOut.T_project, T_batch_number: batchNumber, CreateTime: date, } _, err = DeviceDao.AddOrUpdate_Device(device, 1) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 202, Msg: "出库失败"} c.ServeJSON() return } } } } // 3、添加出库产品清单 stockOutProduct := Stock.StockOutProduct{ T_number: T_number, T_product_id: product_id, T_depot_id: StockOut.T_depot_id, T_num: num, // 出库数量 T_date: T_date, // 出库日期 T_relation_sn: T_relation_sn, T_state: 1, } // 更新产品表 err = StockOutProductDao.Update_StockOutProduct(stockOutProduct) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "修改出库产品信息失败"} c.ServeJSON() return } // 5、更新产品库存列表、占用库存 _, err = StockDao.Stock_Warehouse(StockOut.T_depot_id, product.Id, product.T_class, product.T_name, product.T_model, num) if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: err.Error()} c.ServeJSON() return } } StockOut.T_warehouse = c.User.T_uuid StockOut.T_state = Stock.StockOutAlreadyOut StockOut.T_date = T_date err = StockOutDao.Update_StockOut(StockOut, "T_state", "T_date", "T_warehouse") if err != nil { o.Rollback() c.Data["json"] = lib.JSONS{Code: 203, Msg: "出库审批失败"} c.ServeJSON() return } o.Commit() StockOut_Edit_StockMonth(StockOut.T_date, StockOut.T_depot_id, allProductList) NatsServer.AddUserLogs(c.User.T_uuid, "出库申请", "出库", StockOut) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: T_number} c.ServeJSON() return } // StockMonth_Update_Return 批量更新所有StockMonth的退库数据 func (c *StockController) StockMonth_Update_Return() { // 可选参数:指定仓库和时间范围 T_depot_id, _ := c.GetInt("T_depot_id") T_start_date := c.GetString("T_start_date") // 格式:2024-01 T_end_date := c.GetString("T_end_date") // 格式:2024-12 // 调用后台更新函数 count, err := UpdateAllStockMonthReturn(T_depot_id, T_start_date, T_end_date) if err != nil { c.Data["json"] = lib.JSONS{Code: 203, Msg: fmt.Sprintf("更新失败:%v", err)} c.ServeJSON() return } NatsServer.AddUserLogs(c.User.T_uuid, "库存月度统计", "批量更新退库数据", fmt.Sprintf("更新了%d条记录", count)) c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: fmt.Sprintf("成功更新%d条记录", count)} c.ServeJSON() } // UpdateAllStockMonthReturn 批量更新所有StockMonth记录的退库数量 // T_depot_id: 仓库ID,0表示所有仓库 // T_start_date: 开始月份,格式:2024-01,为空则不限制 // T_end_date: 结束月份,格式:2024-12,为空则不限制 func UpdateAllStockMonthReturn(T_depot_id int, T_start_date, T_end_date string) (count int, err error) { o := orm.NewOrm() StockMonthDao := Stock.NewStockMonth(o) StockInProductDao := Stock.NewStockInProduct(o) // 读取所有StockMonth记录 allStockMonths, err := StockMonthDao.Read_All_StockMonth() if err != nil { logs.Error(lib.FuncName(), err) return 0, err } count = 0 for _, stockMonth := range allStockMonths { // 如果指定了仓库ID,则过滤 if T_depot_id > 0 && stockMonth.T_depot_id != T_depot_id { continue } // 如果指定了开始月份,则过滤 if len(T_start_date) > 0 && stockMonth.T_month < T_start_date { continue } // 如果指定了结束月份,则过滤 if len(T_end_date) > 0 && stockMonth.T_month > T_end_date { continue } // 查询该产品在该月份的退库数量 returnTotal := StockInProductDao.Read_StockReturn_Total(stockMonth.T_depot_id, stockMonth.T_product_id, stockMonth.T_month) // 如果退库数量与原值不同,则更新 if stockMonth.T_return != returnTotal { stockMonth.T_return = returnTotal err = StockMonthDao.Update_StockMonth(stockMonth, "T_return") if err != nil { logs.Error(lib.FuncName(), fmt.Sprintf("更新失败:仓库%d,产品%d,月份%s", stockMonth.T_depot_id, stockMonth.T_product_id, stockMonth.T_month), err) continue } count++ } } logs.Info(fmt.Sprintf("批量更新退库数据完成,共更新%d条记录", count)) return count, nil } // Company_Device_Statistics 查询公司借出和退回设备统计 func (c *StockController) Company_Device_Statistics() { // 查询参数(对前端返回扁平化分组列表,不再返回分页包装) T_company_name := c.GetString("T_company_name") // 公司名称 T_depot_id, _ := c.GetInt("T_depot_id") // 仓库ID T_start_date := c.GetString("T_start_date") // 开始日期 T_end_date := c.GetString("T_end_date") // 结束日期 StockOutDao := Stock.NewStockOut(orm.NewOrm()) R_List, _ := StockOutDao.Read_Company_Device_Statistics(T_company_name, T_start_date, T_end_date, T_depot_id, 1, 9999) // 1) 先按公司分组并排序,顺序与导出一致 companyMap := make(map[string][]Stock.CompanyDeviceStatistics) for _, stat := range R_List { if len(stat.T_stock_out_list) == 0 { continue } companyMap[stat.T_company_name] = append(companyMap[stat.T_company_name], stat) } companyNames := make([]string, 0, len(companyMap)) for name := range companyMap { companyNames = append(companyNames, name) } sort.Strings(companyNames) // 2) 构造前端友好的结构:按公司返回 rows 列表 + 汇总 type RowItem struct { Seq int `json:"seq"` OutNumber string `json:"out_number"` ProductName string `json:"product_name"` DeviceSN string `json:"device_sn"` Num int `json:"num"` Unit string `json:"unit"` Remark string `json:"remark"` ReturnNumber string `json:"return_number"` ReturnDeviceSN string `json:"return_device_sn"` ReturnRemark string `json:"return_remark"` } type CompanyBlock struct { CompanyName string `json:"company_name"` StatisticDateLabel string `json:"statistic_date_label"` OutTotal int `json:"out_total"` ReturnTotal int `json:"return_total"` Rows []RowItem `json:"rows"` } resp := make([]CompanyBlock, 0, len(companyNames)) for _, companyName := range companyNames { statList := companyMap[companyName] // 构建退库 SN -> 信息 的映射 type ReturnInfo struct { ReturnNumber string SN string Num int Unit string Total float64 Remark string } returnSNMap := make(map[string]ReturnInfo) for _, stat := range statList { for _, ret := range stat.T_stock_return_list { for _, sn := range ret.T_device_list { if len(sn) > 0 { returnSNMap[sn] = ReturnInfo{ ReturnNumber: ret.T_stock_return_number, SN: sn, Num: ret.T_num, Unit: ret.T_unit, Total: ret.T_total, Remark: ret.T_remark, } } } } } seqNo := 1 cumulativeOutTotal := 0 cumulativeReturnTotal := 0 rows := make([]RowItem, 0) for _, stat := range statList { for _, out := range stat.T_stock_out_list { validSNs := make([]string, 0) for _, sn := range out.T_device_list { if len(sn) > 0 { validSNs = append(validSNs, sn) } } if len(validSNs) == 0 { continue } cumulativeOutTotal += out.T_num currentReturnNum := 0 returnRemark := "" for _, sn := range validSNs { if retInfo, exists := returnSNMap[sn]; exists { currentReturnNum++ if len(returnRemark) == 0 { returnRemark = retInfo.Remark } } } cumulativeReturnTotal += currentReturnNum for idx, sn := range validSNs { row := RowItem{ DeviceSN: sn, } if retInfo, ok := returnSNMap[sn]; ok { row.ReturnDeviceSN = sn row.ReturnNumber = retInfo.ReturnNumber } if idx == 0 { row.Seq = seqNo row.ProductName = out.T_product_name row.OutNumber = stat.T_stock_out_number row.Num = out.T_num row.Unit = out.T_unit row.Remark = out.T_remark if len(returnRemark) > 0 { row.ReturnRemark = returnRemark } } rows = append(rows, row) } seqNo++ } } resp = append(resp, CompanyBlock{ OutTotal: cumulativeOutTotal, ReturnTotal: cumulativeReturnTotal, Rows: rows, }) } c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: resp} c.ServeJSON() return } // Company_Device_Statistics_Excel 导出公司借出和退回设备统计Excel func (c *StockController) Company_Device_Statistics_Excel() { // 查询参数 T_company_name := c.GetString("T_company_name") // 公司名称 T_depot_id, _ := c.GetInt("T_depot_id") // 仓库ID T_start_date := c.GetString("T_start_date") // 开始日期 T_end_date := c.GetString("T_end_date") // 结束日期 StockOutDao := Stock.NewStockOut(orm.NewOrm()) R_List, _ := StockOutDao.Read_Company_Device_Statistics(T_company_name, T_start_date, T_end_date, T_depot_id, 1, 9999) // 生成Excel文件名 filename := fmt.Sprintf("公司设备借出退回统计(%s)", lib.GetRandstring(6, "0123456789", 0)) // 创建Excel文件 f := excelize.NewFile() // 设置样式 StyleTitle, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Bold: true, Size: 14, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"}, }) StyleHeader, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Bold: true, Size: 10, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true}, 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", Color: []string{"#E0E0E0"}, Pattern: 1}, }) StyleCell, _ := f.NewStyle( &excelize.Style{ Font: &excelize.Font{Size: 10, Family: "宋体"}, Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center", WrapText: true}, 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}, }, }) currentRow := 1 sheetName := "Sheet1" // 按公司名称分组数据 companyMap := make(map[string][]Stock.CompanyDeviceStatistics) for _, stat := range R_List { if len(stat.T_stock_out_list) == 0 { continue } companyMap[stat.T_company_name] = append(companyMap[stat.T_company_name], stat) } // 提取并排序公司名称,确保导出顺序稳定 companyNames := make([]string, 0, len(companyMap)) for name := range companyMap { companyNames = append(companyNames, name) } sort.Strings(companyNames) // 按排序后的公司名称遍历 for _, companyName := range companyNames { statList := companyMap[companyName] // 合并标题行 f.MergeCell(sheetName, fmt.Sprintf("A%d", currentRow), fmt.Sprintf("L%d", currentRow)) f.SetCellValue(sheetName, fmt.Sprintf("A%d", currentRow), "出库申请单/退库单") f.SetCellStyle(sheetName, fmt.Sprintf("A%d", currentRow), fmt.Sprintf("L%d", currentRow), StyleTitle) f.SetRowHeight(sheetName, currentRow, 25) currentRow++ // 出库信息行 f.MergeCell(sheetName, fmt.Sprintf("A%d", currentRow), fmt.Sprintf("H%d", currentRow)) f.SetCellValue(sheetName, fmt.Sprintf("A%d", currentRow), "公司名称:"+companyName) f.MergeCell(sheetName, fmt.Sprintf("I%d", currentRow), fmt.Sprintf("L%d", currentRow)) f.SetCellValue(sheetName, fmt.Sprintf("I%d", currentRow), "") f.SetCellStyle(sheetName, fmt.Sprintf("A%d", currentRow), fmt.Sprintf("L%d", currentRow), StyleCell) currentRow++ // 日期行 f.MergeCell(sheetName, fmt.Sprintf("A%d", currentRow), fmt.Sprintf("H%d", currentRow)) f.SetCellValue(sheetName, fmt.Sprintf("A%d", currentRow), "统计日期:"+time.Now().Format("2006-01-02")) f.MergeCell(sheetName, fmt.Sprintf("I%d", currentRow), fmt.Sprintf("L%d", currentRow)) f.SetCellValue(sheetName, fmt.Sprintf("I%d", currentRow), "") f.SetCellStyle(sheetName, fmt.Sprintf("A%d", currentRow), fmt.Sprintf("L%d", currentRow), StyleCell) currentRow++ // 表头(增加出库单号和退库单号列) headers := []string{"序号", "出库单号", "品名", "设备编号", "数量", "单位", "累计", "备注", "退库单号", "退库设备编号", "累计", "备注"} for i, header := range headers { cell := fmt.Sprintf("%s%d", string(rune('A'+i)), currentRow) f.SetCellValue(sheetName, cell, header) f.SetCellStyle(sheetName, cell, cell, StyleHeader) } currentRow++ // 构建出库SN到退库信息的映射(包含退库单号) type ReturnInfo struct { ReturnNumber string // 退库单号 SN string Num int Unit string Total float64 Remark string } returnSNMap := make(map[string]ReturnInfo) // 出库SN -> 退库信息 // 收集该公司所有的退库信息 for _, stat := range statList { for _, ret := range stat.T_stock_return_list { for _, sn := range ret.T_device_list { if len(sn) > 0 { returnSNMap[sn] = ReturnInfo{ ReturnNumber: ret.T_stock_return_number, // 关联的退库单号 SN: sn, Num: ret.T_num, Unit: ret.T_unit, Total: ret.T_total, Remark: ret.T_remark, } } } } } // 遍历该公司所有出库单的出库明细,按SN展开 seqNo := 1 cumulativeOutTotal := 0 // 累计出库总数 cumulativeReturnTotal := 0 // 累计退库总数 cumulativeStartRow := currentRow // 记录每个出库单号的起始行和结束行,用于后续合并 type OutNumberRange struct { StartRow int EndRow int Number string } outNumberRanges := make([]OutNumberRange, 0) // 记录每个退库单号的起始行和结束行 type ReturnNumberRange struct { StartRow int EndRow int Number string } //returnNumberRanges := make([]ReturnNumberRange, 0) for _, stat := range statList { outNumberStartRow := currentRow // 记录当前出库单号的起始行 //hasReturnInThisOut := false // 标记当前出库单是否有退库 //returnNumberStartRow := currentRow for _, out := range stat.T_stock_out_list { // 过滤掉空的SN validSNs := make([]string, 0) for _, sn := range out.T_device_list { if len(sn) > 0 { validSNs = append(validSNs, sn) } } if len(validSNs) == 0 { continue } // 累加当前产品的出库数量 cumulativeOutTotal += out.T_num // 计算当前产品的退库数量和获取退库备注 currentReturnNum := 0 returnRemark := "" for _, sn := range validSNs { if retInfo, exists := returnSNMap[sn]; exists { currentReturnNum++ if len(returnRemark) == 0 { returnRemark = retInfo.Remark // 使用第一个退库记录的备注 } } } cumulativeReturnTotal += currentReturnNum // 标记该出库单是否有退库 //if currentReturnNum > 0 { // hasReturnInThisOut = true //} startRow := currentRow // 为每个SN创建一行 for idx, sn := range validSNs { // 出库单号(C列)和设备编号(D列) f.SetCellValue(sheetName, fmt.Sprintf("D%d", currentRow), sn) // 退库信息(如果该SN已退库,则显示) if retInfo, exists := returnSNMap[sn]; exists { f.SetCellValue(sheetName, fmt.Sprintf("J%d", currentRow), sn) // 退库设备编号 f.SetCellValue(sheetName, fmt.Sprintf("I%d", currentRow), retInfo.ReturnNumber) // 退库单号只在第一行显示 // if idx == 0 && currentReturnNum > 0 { // f.SetCellValue(sheetName, fmt.Sprintf("I%d", currentRow), retInfo.ReturnNumber) // } } // 只在第一行设置序号、品名、出库单号、数量、单位、累计、备注 if idx == 0 { f.SetCellValue(sheetName, fmt.Sprintf("A%d", currentRow), seqNo) f.SetCellValue(sheetName, fmt.Sprintf("C%d", currentRow), out.T_product_name) f.SetCellValue(sheetName, fmt.Sprintf("B%d", currentRow), stat.T_stock_out_number) // 出库单号 f.SetCellValue(sheetName, fmt.Sprintf("E%d", currentRow), out.T_num) f.SetCellValue(sheetName, fmt.Sprintf("F%d", currentRow), out.T_unit) //f.SetCellValue(sheetName, fmt.Sprintf("G%d", currentRow), cumulativeOutTotal) // 显示累计出库总数 f.SetCellValue(sheetName, fmt.Sprintf("H%d", currentRow), out.T_remark) // 退库数量、单位、累计合计、备注 if currentReturnNum > 0 { //f.SetCellValue(sheetName, fmt.Sprintf("K%d", currentRow), currentReturnNum) //f.SetCellValue(sheetName, fmt.Sprintf("L%d", currentRow), out.T_unit) //f.SetCellValue(sheetName, fmt.Sprintf("M%d", currentRow), cumulativeReturnTotal) // 显示累计退库总数 f.SetCellValue(sheetName, fmt.Sprintf("L%d", currentRow), returnRemark) // 显示退库备注 } } // 设置单元格样式 for col := 'A'; col <= 'L'; col++ { cell := fmt.Sprintf("%s%d", string(col), currentRow) f.SetCellStyle(sheetName, cell, cell, StyleCell) } currentRow++ } // 如果有多个SN,合并序号、品名、数量、单位、累计、备注列(出库单号C列和退库单号I列在外层统一合并) if len(validSNs) > 1 { endRow := currentRow - 1 f.MergeCell(sheetName, fmt.Sprintf("A%d", startRow), fmt.Sprintf("A%d", endRow)) f.MergeCell(sheetName, fmt.Sprintf("C%d", startRow), fmt.Sprintf("C%d", endRow)) f.MergeCell(sheetName, fmt.Sprintf("E%d", startRow), fmt.Sprintf("E%d", endRow)) f.MergeCell(sheetName, fmt.Sprintf("F%d", startRow), fmt.Sprintf("F%d", endRow)) f.MergeCell(sheetName, fmt.Sprintf("G%d", startRow), fmt.Sprintf("G%d", endRow)) f.MergeCell(sheetName, fmt.Sprintf("H%d", startRow), fmt.Sprintf("H%d", endRow)) } seqNo++ } // 记录当前出库单号的范围 if currentRow > outNumberStartRow { outNumberRanges = append(outNumberRanges, OutNumberRange{ StartRow: outNumberStartRow, EndRow: currentRow - 1, Number: stat.T_stock_out_number, }) } } // 合并相同出库单号的单元格(C列) for _, rng := range outNumberRanges { if rng.EndRow > rng.StartRow { f.MergeCell(sheetName, fmt.Sprintf("B%d", rng.StartRow), fmt.Sprintf("B%d", rng.EndRow)) } } // 合并相同退库单号的单元格(I列) // for _, rng := range returnNumberRanges { // if rng.EndRow > rng.StartRow { // f.MergeCell(sheetName, fmt.Sprintf("I%d", rng.StartRow), fmt.Sprintf("I%d", rng.EndRow)) // } // } // 合并出库累计 f.MergeCell(sheetName, fmt.Sprintf("G%d", cumulativeStartRow), fmt.Sprintf("G%d", currentRow-1)) f.SetCellValue(sheetName, fmt.Sprintf("G%d", cumulativeStartRow), cumulativeOutTotal) // 显示累计出库总数 // 合并退库累计 f.MergeCell(sheetName, fmt.Sprintf("K%d", cumulativeStartRow), fmt.Sprintf("K%d", currentRow-1)) f.SetCellValue(sheetName, fmt.Sprintf("K%d", cumulativeStartRow), cumulativeReturnTotal) // 显示累计退库总数 // 添加空行 currentRow++ } // 设置列宽(14列) f.SetColWidth(sheetName, "A", "A", 8) // 序号 f.SetColWidth(sheetName, "B", "B", 20) // 品名 f.SetColWidth(sheetName, "C", "C", 20) // 出库单号 f.SetColWidth(sheetName, "D", "D", 30) // 设备编号 f.SetColWidth(sheetName, "E", "F", 10) // 数量、单位 f.SetColWidth(sheetName, "G", "G", 12) // 累计 f.SetColWidth(sheetName, "H", "H", 20) // 备注 f.SetColWidth(sheetName, "I", "I", 20) // 退库单号 f.SetColWidth(sheetName, "J", "J", 30) // 退库设备编号 f.SetColWidth(sheetName, "K", "K", 12) // 累计 f.SetColWidth(sheetName, "L", "L", 20) // 备注 // 保存文件 filepath := "./ofile/" + filename + ".xlsx" if err := f.SaveAs(filepath); err != nil { logs.Error(lib.FuncName(), err) c.Data["json"] = lib.JSONS{Code: 201, Msg: "生成Excel失败"} c.ServeJSON() return } var url string //// 上传 OSS nats := natslibs.NewNats(Nats.Nats, conf.NatsSubj_Prefix) url, is := nats.Qiniu_UploadFile(lib.GetCurrentDirectory()+"/ofile/"+filename+".xlsx", "ofile/"+filename+".xlsx") if !is { c.Data["json"] = lib.JSONS{Code: 202, Msg: "oss!"} c.ServeJSON() return } //删除目录 err := os.Remove("ofile/" + filename + ".xlsx") if err != nil { logs.Error(lib.FuncName(), err) } c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: url} c.ServeJSON() return } // Company_Name_List 获取所有出库的公司名称列表 func (c *StockController) Stock_Out_Company_Name_List() { T_name := c.GetString("T_name") // 公司名称(模糊查询) StockOutDao := Stock.NewStockOut(orm.NewOrm()) R_List, err := StockOutDao.Read_Company_Name_List(T_name) if err != nil { c.Data["json"] = lib.JSONS{Code: 201, Msg: "查询失败"} c.ServeJSON() return } c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: R_List} c.ServeJSON() return } // Company_Name_List 获取所有出库的公司名称列表 func (c *StockController) Stock_Out_Project_List() { T_name := c.GetString("T_name") // 公司名称(模糊查询) StockOutDao := Stock.NewStockOut(orm.NewOrm()) R_List, err := StockOutDao.Read_Project_List(T_name) if err != nil { c.Data["json"] = lib.JSONS{Code: 201, Msg: "查询失败"} c.ServeJSON() return } c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: R_List} c.ServeJSON() return }