Device.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  1. package Stock
  2. import (
  3. "ERP_storage/logs"
  4. "ERP_storage/models/Basic"
  5. "ERP_storage/models/IOTNetworkCard"
  6. "errors"
  7. "fmt"
  8. "strconv"
  9. "strings"
  10. "time"
  11. _ "github.com/astaxie/beego/cache/redis"
  12. "github.com/beego/beego/v2/adapter/orm"
  13. orm2 "github.com/beego/beego/v2/client/orm"
  14. "gogs.baozhida.cn/zoie/ERP_libs/lib"
  15. )
  16. type Device struct {
  17. Id int `orm:"column(ID);size(11);auto;pk"`
  18. T_contract_number string `orm:"size(256);null"` // 合同编号
  19. T_product_id int `orm:"size(20);null"` // 产品id
  20. T_in_number string `orm:"size(256);null"` // 入库编号
  21. T_out_number string `orm:"size(256);null"` // 出库编号
  22. T_sn string `orm:"size(256);null"` // 设备sn
  23. T_iccid string `orm:"size(256);null"` // sim卡号
  24. T_imei string `orm:"size(256);null"` // 模组imei
  25. T_State int `orm:"size(2);default(2)"` // 1-已出库 2-未出库/入库
  26. T_remark string `orm:"type(text);null"` // 备注
  27. T_project string `orm:"type(text);null"` // 出库项目
  28. T_project_log string `orm:"type(text);null"` // 出库项目
  29. T_device_number string `orm:"size(256);null"` // 移动端设备编号
  30. T_batch_number string `orm:"type(256);null"` // 批次号
  31. CreateTime time.Time `orm:"column(create_time);type(timestamp);null;auto_now_add"` //auto_now_add 第一次保存时才设置时间
  32. UpdateTime time.Time `orm:"column(update_time);type(timestamp);null;auto_now"` //auto_now 每次 model 保存时都会对时间自动更新
  33. }
  34. func (t *Device) TableName() string {
  35. return "device" // 数据库名称 // ************** 替换 FormulaList **************
  36. }
  37. type DeviceDaoImpl struct {
  38. orm orm.Ormer
  39. }
  40. func NewDevice(orm orm.Ormer) *DeviceDaoImpl {
  41. return &DeviceDaoImpl{orm: orm}
  42. }
  43. func init() {
  44. //注册模型
  45. orm.RegisterModel(new(Device))
  46. }
  47. type Device_R struct {
  48. Id int
  49. T_contract_number string // 合同编号
  50. T_in_number string // 入库编号
  51. T_out_number string // 出库编号
  52. T_sn string // 设备sn
  53. T_iccid string // 物联网卡号
  54. T_imei string // 模组imei
  55. T_State int // 1-已出库 2-未出库
  56. T_device_state int // 1-已出库 2-未出库
  57. T_remark string
  58. T_project string
  59. T_project_log string
  60. // ---------产品信息-----------
  61. T_product_id int
  62. T_product_name string
  63. T_product_class int
  64. T_product_class_name string
  65. T_product_model string
  66. T_product_spec string
  67. T_product_img string
  68. T_device_number string // 设备编号
  69. }
  70. // 单个设备转换
  71. func DeviceToDevice_R(t Device_R) (r Device_R) {
  72. r.Id = t.Id
  73. r.T_contract_number = t.T_contract_number
  74. r.T_product_id = t.T_product_id
  75. r.T_in_number = t.T_in_number
  76. r.T_out_number = t.T_out_number
  77. r.T_sn = t.T_sn
  78. r.T_iccid = t.T_iccid
  79. r.T_imei = t.T_imei
  80. r.T_State = t.T_device_state
  81. r.T_device_state = t.T_device_state
  82. r.T_remark = t.T_remark
  83. r.T_project = t.T_project
  84. r.T_project_log = t.T_project_log
  85. r.T_product_name = t.T_product_name
  86. r.T_product_class = t.T_product_class
  87. r.T_product_model = t.T_product_model
  88. r.T_product_spec = t.T_product_spec
  89. r.T_product_img = t.T_product_img
  90. r.T_product_class_name = Basic.Read_ProductClass_Get(t.T_product_class)
  91. // 单个查询物联网卡信息
  92. if len(r.T_iccid) > 0 {
  93. card, _ := IOTNetworkCard.Read_IOTNetworkCard_ByT_iccid(r.T_iccid)
  94. r.T_device_number = card.T_device_number
  95. }
  96. return r
  97. }
  98. // 批量处理设备转换
  99. func DevicesToDevice_Rs(devices []Device_R) []Device_R {
  100. if len(devices) == 0 {
  101. return []Device_R{}
  102. }
  103. // 收集所有ICCID
  104. iccids := make([]string, 0, len(devices))
  105. for _, device := range devices {
  106. if len(device.T_iccid) > 0 {
  107. iccids = append(iccids, device.T_iccid)
  108. }
  109. }
  110. // 批量查询物联网卡信息
  111. cardMap, err := IOTNetworkCard.Read_IOTNetworkCards_ByT_iccids(iccids)
  112. if err != nil {
  113. logs.Error(lib.FuncName(), "批量查询物联网卡失败:", err)
  114. }
  115. // 批量查询产品类别信息
  116. productClassMap := make(map[int]string)
  117. for _, device := range devices {
  118. if device.T_product_class > 0 {
  119. if _, exists := productClassMap[device.T_product_class]; !exists {
  120. productClassMap[device.T_product_class] = Basic.Read_ProductClass_Get(device.T_product_class)
  121. }
  122. }
  123. }
  124. // 转换设备信息
  125. results := make([]Device_R, len(devices))
  126. for i, device := range devices {
  127. r := Device_R{
  128. Id: device.Id,
  129. T_contract_number: device.T_contract_number,
  130. T_product_id: device.T_product_id,
  131. T_in_number: device.T_in_number,
  132. T_out_number: device.T_out_number,
  133. T_sn: device.T_sn,
  134. T_iccid: device.T_iccid,
  135. T_imei: device.T_imei,
  136. T_State: device.T_device_state,
  137. T_device_state: device.T_device_state,
  138. T_remark: device.T_remark,
  139. T_project: device.T_project,
  140. T_project_log: device.T_project_log,
  141. T_product_name: device.T_product_name,
  142. T_product_class: device.T_product_class,
  143. T_product_model: device.T_product_model,
  144. T_product_spec: device.T_product_spec,
  145. T_product_img: device.T_product_img,
  146. }
  147. // 设置产品类别名称
  148. if className, exists := productClassMap[device.T_product_class]; exists {
  149. r.T_product_class_name = className
  150. }
  151. // 设置设备编号
  152. if len(device.T_iccid) > 0 {
  153. if card, exists := cardMap[device.T_iccid]; exists {
  154. r.T_device_number = card.T_device_number
  155. }
  156. }
  157. results[i] = r
  158. }
  159. return results
  160. }
  161. // 添加
  162. func (dao *DeviceDaoImpl) Add_Device(r Device) (id int64, err error) {
  163. now := time.Now().Format("15:04:05")
  164. date, _ := lib.TimeStrToTime(r.CreateTime.Format("2006-01-02") + " " + now)
  165. r.CreateTime = date
  166. id, err = dao.orm.Insert(&r)
  167. if err != nil {
  168. logs.Error(lib.FuncName(), err)
  169. }
  170. return id, err
  171. }
  172. // T_type 1-出库 2-入库
  173. func (dao *DeviceDaoImpl) AddOrUpdate_Device(r Device, T_type int) (id int64, err error) {
  174. now := time.Now().Format("15:04:05")
  175. date, _ := lib.TimeStrToTime(r.CreateTime.Format("2006-01-02") + " " + now)
  176. r.CreateTime = date
  177. id, err = dao.orm.Insert(&r)
  178. if err != nil {
  179. logs.Error(lib.FuncName(), err)
  180. }
  181. return
  182. }
  183. func (dao *DeviceDaoImpl) Read_Device_ByT_sn(T_sn string) (r Device, err error) {
  184. qs := dao.orm.QueryTable(new(Device))
  185. var list []Device
  186. _, err = qs.Limit(1, 0).Filter("T_sn", T_sn).OrderBy("-CreateTime").All(&list)
  187. if err != nil {
  188. logs.Error(lib.FuncName(), err)
  189. }
  190. if len(list) == 0 {
  191. return r, orm.ErrNoRows
  192. }
  193. if len(list) > 0 {
  194. r = list[0]
  195. }
  196. return
  197. }
  198. func (dao *DeviceDaoImpl) Read_DeviceSn_List(T_contract_number string, T_product_id int, T_in_number, T_out_number string) (r []string, err error) {
  199. qs := dao.orm.QueryTable(new(Device))
  200. // 过滤
  201. cond := orm.NewCondition()
  202. cond.And("T_product_id", T_product_id)
  203. if len(T_contract_number) > 0 {
  204. cond = cond.And("T_contract_number", T_contract_number)
  205. }
  206. if len(T_in_number) > 0 {
  207. cond = cond.And("T_in_number", T_in_number)
  208. }
  209. if len(T_out_number) > 0 {
  210. cond = cond.And("T_out_number", T_out_number)
  211. }
  212. var maps []Device
  213. _, err = qs.SetCond((*orm2.Condition)(cond)).All(&maps)
  214. if err != nil {
  215. logs.Error(lib.FuncName(), err)
  216. return
  217. }
  218. for _, v := range maps {
  219. r = append(r, v.T_sn)
  220. }
  221. return
  222. }
  223. func (dao *DeviceDaoImpl) Read_Device_List(T_name, T_product_name, T_product_model string, T_State, page, page_z int) (r []Device_R, cnt int64) {
  224. var offset int
  225. if page <= 1 {
  226. offset = 0
  227. } else {
  228. offset = (page - 1) * page_z
  229. }
  230. // 使用参数化查询代替字符串拼接,防止SQL注入并提高性能
  231. whereConditions := []string{"d.t__state > 0"}
  232. var params []interface{}
  233. // 构建搜索条件
  234. if len(T_name) > 0 {
  235. searchTerm := "%" + T_name + "%"
  236. whereConditions = append(whereConditions, "(d.t_contract_number LIKE ? OR d.t_out_number LIKE ? OR d.t_sn LIKE ? OR d.t_iccid LIKE ? OR d.t_project LIKE ?)")
  237. params = append(params, searchTerm, searchTerm, searchTerm, searchTerm, searchTerm)
  238. }
  239. if T_State > 0 {
  240. whereConditions = append(whereConditions, "d.t__state = ?")
  241. params = append(params, T_State)
  242. }
  243. if len(T_product_name) > 0 {
  244. whereConditions = append(whereConditions, "p.t_name LIKE ?")
  245. params = append(params, "%"+T_product_name+"%")
  246. }
  247. if len(T_product_model) > 0 {
  248. whereConditions = append(whereConditions, "p.t_model LIKE ?")
  249. params = append(params, "%"+T_product_model+"%")
  250. }
  251. // 组合WHERE条件
  252. whereClause := " WHERE " + strings.Join(whereConditions, " AND ")
  253. // 优化子查询:使用窗口函数替代子查询(MySQL 5.7不支持窗口函数,使用JOIN优化)
  254. // 使用FORCE INDEX提示优化器使用主键索引
  255. countSQL := `
  256. SELECT COUNT(*)
  257. FROM (
  258. SELECT d.t_sn
  259. FROM device d
  260. FORCE INDEX (PRIMARY)
  261. JOIN product p ON d.t_product_id = p.ID
  262. JOIN (
  263. SELECT t_sn, MAX(create_time) AS max_create_time
  264. FROM device
  265. GROUP BY t_sn
  266. ) latest ON d.t_sn = latest.t_sn AND d.create_time = latest.max_create_time
  267. ` + whereClause + `
  268. ) AS count_query`
  269. // 执行计数查询
  270. var count int64
  271. err := dao.orm.Raw(countSQL, params...).QueryRow(&count)
  272. if err != nil {
  273. logs.Error(lib.FuncName(), "Count query error:", err)
  274. return nil, 0
  275. }
  276. if count == 0 {
  277. return nil, 0
  278. }
  279. // 主查询 - 只选择需要的列,避免使用SELECT *
  280. dataSQL := `
  281. SELECT
  282. d.ID, d.t_contract_number, d.t_product_id, d.t_in_number, d.t_out_number,
  283. d.t_sn, d.t_iccid, d.t_imei, d.t__state AS t_device_state, d.t_remark,
  284. d.t_project, d.t_project_log, d.t_device_number, d.t_batch_number,
  285. p.t_name AS t_product_name, p.t_model AS t_product_model,
  286. p.t_class AS t_product_class, p.t_spec AS t_product_spec, p.t_img AS t_product_img
  287. FROM device d
  288. FORCE INDEX (PRIMARY)
  289. JOIN product p ON d.t_product_id = p.ID
  290. JOIN (
  291. SELECT t_sn, MAX(create_time) AS max_create_time
  292. FROM device
  293. GROUP BY t_sn
  294. ) latest ON d.t_sn = latest.t_sn AND d.create_time = latest.max_create_time
  295. ` + whereClause + `
  296. ORDER BY d.create_time DESC`
  297. // 添加分页
  298. if page_z != 9999 {
  299. dataSQL += " LIMIT ?, ?"
  300. params = append(params, offset, page_z)
  301. }
  302. // 执行数据查询
  303. var maps []Device_R
  304. _, err = dao.orm.Raw(dataSQL, params...).QueryRows(&maps)
  305. if err != nil {
  306. logs.Error(lib.FuncName(), "Data query error:", err)
  307. return nil, 0
  308. }
  309. // 批量获取设备历史记录,避免N+1查询
  310. if len(maps) > 0 {
  311. // 批量获取历史记录
  312. historyMap := dao.batchReadDeviceHistory(maps)
  313. // 填充历史记录
  314. for i := range maps {
  315. if history, exists := historyMap[maps[i].T_sn]; exists {
  316. maps[i].T_remark = history.T_remark
  317. maps[i].T_project_log = history.T_project_log
  318. }
  319. }
  320. // 批量处理设备转换,避免N+1查询
  321. r = DevicesToDevice_Rs(maps)
  322. }
  323. return r, count
  324. }
  325. func (dao *DeviceDaoImpl) Read_Device_List_upback(T_name, T_product_name, T_product_model string, T_State, page, page_z int) (r []Device_R, cnt int64) {
  326. var offset int
  327. if page <= 1 {
  328. offset = 0
  329. } else {
  330. offset = (page - 1) * page_z
  331. }
  332. // 过滤
  333. sqlWhere := " WHERE d.t__state > 0"
  334. if len(T_name) > 0 {
  335. sqlWhere += " AND (d.t_contract_number like \"%" + T_name + "%\" or d.t_out_number like \"%" + T_name +
  336. "%\" or d.t_sn like \"%" + T_name + "%\" or d.t_iccid like \"%" + T_name + "%\" or d.t_project like \"%" + T_name + "%\")"
  337. }
  338. if T_State > 0 {
  339. sqlWhere += fmt.Sprintf(" AND d.t__state = %d", T_State)
  340. }
  341. if len(T_product_name) > 0 {
  342. sqlWhere += " AND p.t_name like \"%" + T_product_name + "%\""
  343. }
  344. if len(T_product_model) > 0 {
  345. sqlWhere += " AND p.t_model like \"%" + T_product_model + "%\""
  346. }
  347. var maps_z []orm2.ParamsList
  348. // 获取总条数
  349. sql := "SELECT COUNT(*) FROM device d JOIN product p ON d.t_product_id = p.ID JOIN (SELECT t_sn, MAX(create_time) AS max_create_time FROM device GROUP BY t_sn) latest " +
  350. "ON d.t_sn = latest.t_sn AND d.create_time = latest.max_create_time"
  351. sql = sql + sqlWhere
  352. fmt.Println(sql)
  353. _, err := dao.orm.Raw(sql).ValuesList(&maps_z)
  354. if err != nil {
  355. return r, 0
  356. }
  357. if len(maps_z) == 0 {
  358. return r, 0
  359. }
  360. sql = "SELECT *,d.t__state as t_device_state,p.t_name AS t_product_name,p.t_model AS t_product_model,p.t_class AS t_product_class,p.t_spec AS t_product_spec " +
  361. "FROM device d JOIN product p ON d.t_product_id = p.ID JOIN (SELECT t_sn, MAX(create_time) AS max_create_time FROM device GROUP BY t_sn) latest " +
  362. "ON d.t_sn = latest.t_sn AND d.create_time = latest.max_create_time"
  363. sql = sql + sqlWhere
  364. sql += " ORDER BY d.create_time DESC"
  365. if page_z != 9999 {
  366. sql += " LIMIT " + strconv.Itoa(offset) + "," + strconv.Itoa(page_z)
  367. }
  368. fmt.Println(sql)
  369. var maps []Device_R
  370. _, err = dao.orm.Raw(sql).QueryRows(&maps)
  371. if err != nil {
  372. return r, 0
  373. }
  374. for _, v := range maps {
  375. v.T_remark, v.T_project_log = dao.Read_Device_History(v.T_sn)
  376. r = append(r, DeviceToDevice_R(v))
  377. }
  378. count, _ := strconv.Atoi(maps_z[0][0].(string))
  379. return r, int64(count)
  380. }
  381. /**
  382. * 批量获取设备历史记录,避免N+1查询问题
  383. * @param devices 设备列表
  384. * @return 设备SN到历史记录的映射
  385. */
  386. func (dao *DeviceDaoImpl) batchReadDeviceHistory(devices []Device_R) map[string]struct {
  387. T_remark string
  388. T_project_log string
  389. } {
  390. if len(devices) == 0 {
  391. return make(map[string]struct {
  392. T_remark string
  393. T_project_log string
  394. })
  395. }
  396. // 收集所有设备SN
  397. snList := make([]string, 0, len(devices))
  398. for _, device := range devices {
  399. snList = append(snList, device.T_sn)
  400. }
  401. // 构建IN子句
  402. placeholders := make([]string, len(snList))
  403. args := make([]interface{}, len(snList))
  404. for i, sn := range snList {
  405. placeholders[i] = "?"
  406. args[i] = sn
  407. }
  408. // 批量查询所有设备的历史记录
  409. sql := `SELECT t_sn, t__state, create_time, t_out_number, t_in_number, t_project
  410. FROM device
  411. WHERE t_sn IN (` + strings.Join(placeholders, ",") + `)
  412. ORDER BY t_sn, create_time`
  413. var historyRecords []struct {
  414. T_sn string
  415. T_State int
  416. CreateTime time.Time
  417. T_out_number string
  418. T_in_number string
  419. T_project string
  420. }
  421. _, err := dao.orm.Raw(sql, args...).QueryRows(&historyRecords)
  422. if err != nil {
  423. logs.Error(lib.FuncName(), err)
  424. return make(map[string]struct {
  425. T_remark string
  426. T_project_log string
  427. })
  428. }
  429. // 按设备SN分组并构建历史记录
  430. result := make(map[string]struct {
  431. T_remark string
  432. T_project_log string
  433. })
  434. for _, record := range historyRecords {
  435. if _, exists := result[record.T_sn]; !exists {
  436. result[record.T_sn] = struct {
  437. T_remark string
  438. T_project_log string
  439. }{}
  440. }
  441. history := result[record.T_sn]
  442. if record.T_State == 1 {
  443. // 出库记录
  444. history.T_remark += fmt.Sprintf("%s:%s(%s)|", record.CreateTime.Format("2006-01-02"), "出库", record.T_out_number)
  445. if len(record.T_project) > 0 {
  446. history.T_project_log += fmt.Sprintf("%s:%s(%s):%s|", record.CreateTime.Format("2006-01-02"), "出库", record.T_out_number, record.T_project)
  447. }
  448. } else if record.T_State == 2 {
  449. // 入库记录
  450. history.T_remark += fmt.Sprintf("%s:%s(%s)|", record.CreateTime.Format("2006-01-02"), "入库", record.T_in_number)
  451. }
  452. result[record.T_sn] = history
  453. }
  454. return result
  455. }
  456. /**
  457. * 获取单个设备的历史记录(保留原方法以兼容其他调用)
  458. * @param T_sn 设备SN
  459. * @return 备注和项目日志
  460. */
  461. func (dao *DeviceDaoImpl) Read_Device_History(T_sn string) (T_remark string, T_project string) {
  462. qs := dao.orm.QueryTable(new(Device))
  463. var maps []Device
  464. _, err := qs.Filter("T_sn", T_sn).OrderBy("CreateTime").All(&maps)
  465. if err != nil {
  466. logs.Error(lib.FuncName(), err)
  467. return
  468. }
  469. for _, v := range maps {
  470. if v.T_State == 1 {
  471. T_remark += fmt.Sprintf("%s:%s(%s)|", v.CreateTime.Format("2006-01-02"), "出库", v.T_out_number)
  472. if len(v.T_project) > 0 {
  473. T_project += fmt.Sprintf("%s:%s(%s):%s|", v.CreateTime.Format("2006-01-02"), "出库", v.T_out_number, v.T_project)
  474. }
  475. }
  476. if v.T_State == 2 {
  477. T_remark += fmt.Sprintf("%s:%s(%s)|", v.CreateTime.Format("2006-01-02"), "入库", v.T_in_number)
  478. }
  479. }
  480. return
  481. }
  482. func (dao *DeviceDaoImpl) Delete_Device_ByT_in_number(T_number, T_sn string) (err error) {
  483. qs := dao.orm.QueryTable(new(Device))
  484. var device Device
  485. err = qs.Filter("T_sn", T_sn).Filter("T_in_number", T_number).One(&device)
  486. if err != nil {
  487. return
  488. }
  489. var count int64
  490. count, err = qs.Filter("T_sn", T_sn).Filter("CreateTime__gt", device.CreateTime).Count()
  491. if err != nil {
  492. logs.Error(lib.FuncName(), err)
  493. return
  494. }
  495. if count > 1 {
  496. return errors.New("设备已出库,无法删除")
  497. }
  498. _, err = dao.orm.Delete(&device)
  499. if err != nil {
  500. logs.Error(lib.FuncName(), err)
  501. return
  502. }
  503. return err
  504. }
  505. func (dao *DeviceDaoImpl) Delete_Device_ByT_out_number(T_number, T_sn string) (err error) {
  506. qs := dao.orm.QueryTable(new(Device))
  507. var device Device
  508. err = qs.Filter("T_sn", T_sn).Filter("T_out_number", T_number).One(&device)
  509. if err != nil {
  510. return
  511. }
  512. var count int64
  513. count, err = qs.Filter("T_sn", T_sn).Filter("CreateTime__gt", device.CreateTime).Count()
  514. if err != nil {
  515. logs.Error(lib.FuncName(), err)
  516. return
  517. }
  518. if count > 1 {
  519. return errors.New("设备已入库,无法删除")
  520. }
  521. _, err = dao.orm.Delete(&device)
  522. if err != nil {
  523. logs.Error(lib.FuncName(), err)
  524. return
  525. }
  526. return err
  527. }
  528. func (dao *DeviceDaoImpl) Update_Device_ByT_out_number_T_project(T_number, T_project string) error {
  529. qs := dao.orm.QueryTable(new(Device))
  530. var list []Device
  531. _, err := qs.Filter("T_out_number", T_number).All(&list)
  532. if err != nil {
  533. logs.Error(lib.FuncName(), err)
  534. return err
  535. }
  536. for _, deivce := range list {
  537. deivce.T_project = T_project
  538. _, err = dao.orm.Update(&deivce, "T_project")
  539. if err != nil {
  540. logs.Error(lib.FuncName(), err)
  541. return err
  542. }
  543. }
  544. return nil
  545. }
  546. func (dao *DeviceDaoImpl) Update_Device_CreateTimeByT_out_number(T_number, T_date string) error {
  547. now := time.Now().Format("15:04:05")
  548. date, _ := lib.TimeStrToTime(T_date + " " + now)
  549. qs := dao.orm.QueryTable(new(Device))
  550. var list []Device
  551. _, err := qs.Filter("T_out_number", T_number).All(&list)
  552. if err != nil {
  553. logs.Error(lib.FuncName(), err)
  554. return err
  555. }
  556. for _, device := range list {
  557. //device.CreateTime = date
  558. //_, err = dao.orm.Update(&device, "CreateTime")
  559. _, err = dao.orm.Raw("UPDATE device SET create_time = ? WHERE id = ?", date, device.Id).Exec()
  560. if err != nil {
  561. logs.Error(lib.FuncName(), err)
  562. return err
  563. }
  564. }
  565. return nil
  566. }
  567. func (dao *DeviceDaoImpl) Update_Device_CreateTimeByT_in_number(T_number, T_date string) error {
  568. now := time.Now().Format("15:04:05")
  569. date, _ := lib.TimeStrToTime(T_date + " " + now)
  570. qs := dao.orm.QueryTable(new(Device))
  571. var list []Device
  572. _, err := qs.Filter("T_in_number", T_number).All(&list)
  573. if err != nil {
  574. logs.Error(lib.FuncName(), err)
  575. return err
  576. }
  577. for _, device := range list {
  578. //device.CreateTime = date
  579. //_, err = dao.orm.Update(&device, "CreateTime")
  580. _, err = dao.orm.Raw("UPDATE device SET create_time = ? WHERE id = ?", date, device.Id).Exec()
  581. if err != nil {
  582. logs.Error(lib.FuncName(), err)
  583. return err
  584. }
  585. }
  586. return nil
  587. }
  588. /**
  589. * 根据IMEI查询上次入库的批次号
  590. * @param imei 设备IMEI
  591. * @return 批次号,如果未找到则返回空字符串
  592. */
  593. func (dao *DeviceDaoImpl) Read_Device_BatchNumber_ByImei(imei string) (string, error) {
  594. if len(imei) == 0 {
  595. return "", nil
  596. }
  597. // 直接查询device表,获取该IMEI对应的最新入库记录的批次号
  598. // T_State = 2 是入库状态,入库时已将t_batch_number保存到device表
  599. sql := `SELECT t_batch_number
  600. FROM device
  601. WHERE t_imei = ? AND t__state = 2
  602. ORDER BY create_time DESC
  603. LIMIT 1`
  604. var batchNumber string
  605. err := dao.orm.Raw(sql, imei).QueryRow(&batchNumber)
  606. if err != nil {
  607. if err.Error() == orm.ErrNoRows.Error() {
  608. // 未找到记录,返回空字符串
  609. return "", nil
  610. }
  611. logs.Error(lib.FuncName(), err)
  612. return "", err
  613. }
  614. return batchNumber, nil
  615. }
  616. /**
  617. * 根据入库单号批量更新所有相关设备的批次号
  618. * 先查询出所有t_in_number对应的设备,然后根据T_imei修改,不属于该入库编号的也要同步修改
  619. * @param inNumber 入库单号
  620. * @param batchNumber 批次号
  621. * @return 错误信息
  622. */
  623. func (dao *DeviceDaoImpl) Update_Device_BatchNumber_ByInNumber(inNumber, batchNumber string) error {
  624. if len(inNumber) == 0 || len(batchNumber) == 0 {
  625. return nil
  626. }
  627. // 1. 先查询出所有该入库单号下的设备IMEI列表
  628. sql := `SELECT DISTINCT t_imei FROM device WHERE t_in_number = ? AND t__state = 2 AND t_imei IS NOT NULL AND t_imei != ''`
  629. var imeiList []string
  630. _, err := dao.orm.Raw(sql, inNumber).QueryRows(&imeiList)
  631. if err != nil {
  632. logs.Error(lib.FuncName(), err)
  633. return err
  634. }
  635. if len(imeiList) == 0 {
  636. // 没有找到相关设备,直接返回
  637. return nil
  638. }
  639. // 2. 根据IMEI列表批量更新所有相关设备的批次号(包括不属于当前入库编号的设备)
  640. // 构建IN子句
  641. placeholders := make([]string, len(imeiList))
  642. args := make([]interface{}, len(imeiList)+1)
  643. args[0] = batchNumber
  644. for i, imei := range imeiList {
  645. placeholders[i] = "?"
  646. args[i+1] = imei
  647. }
  648. updateSQL := `UPDATE device
  649. SET t_batch_number = ?
  650. WHERE t_imei IN (` + strings.Join(placeholders, ",") + `)`
  651. _, err = dao.orm.Raw(updateSQL, args...).Exec()
  652. if err != nil {
  653. logs.Error(lib.FuncName(), err)
  654. return err
  655. }
  656. return nil
  657. }