tree_dao.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. /*
  2. * @description: 树结构数据库操作相关
  3. * @Author: CP
  4. * @Date: 2020-09-11 14:49:27
  5. * @FilePath: \construction_management\dao\tree_dao.go
  6. */
  7. package dao
  8. import (
  9. "errors"
  10. "fmt"
  11. "log"
  12. "strconv"
  13. "strings"
  14. "github.com/go-xorm/xorm"
  15. "go.mod/models"
  16. )
  17. //数据库操作引擎
  18. type TreeDao struct {
  19. engine *xorm.Engine
  20. }
  21. //获得一个DAO对象
  22. func NewTreeDao(engine *xorm.Engine) *TreeDao {
  23. return &TreeDao{
  24. engine: engine,
  25. }
  26. }
  27. //id获得数据
  28. func (d *TreeDao) Get(id int, projectId int) *models.CmTree {
  29. // data := &models.CmTree{Id: id, ProjectId: projectId, Isdelete: 0}
  30. // // Get取到值后,会自动赋值到data中
  31. // ok, err := d.engine.Get(data)
  32. // if ok && err == nil {
  33. // return data
  34. // } else {
  35. // data.Id = 0
  36. // return data
  37. // }
  38. // fmt.Println("sqlid=")
  39. // fmt.Println(id)
  40. data := &models.CmTree{}
  41. _, err := d.engine.
  42. Where("id=? and project_id=? and isdelete=0", id, projectId).
  43. Get(data)
  44. // fmt.Println(data)
  45. if err != nil {
  46. data.Id = 0
  47. return data
  48. }
  49. return data
  50. }
  51. // 获得该目录下的标段
  52. func (d *TreeDao) GetBidsection(id int) []models.CmTree {
  53. datalist := make([]models.CmTree, 0)
  54. err := d.engine.
  55. Asc("serial").
  56. Where("parent_id=? and isfolder=0 and isdelete=0", id).
  57. Find(&datalist)
  58. if err != nil {
  59. return datalist
  60. } else {
  61. return datalist
  62. }
  63. }
  64. // 获得某一深度的 结构数据(不包含子集) 正序
  65. func (d *TreeDao) GetAllDepth(depth int, projectId int) []models.CmTree {
  66. datalist := make([]models.CmTree, 0)
  67. err := d.engine.
  68. Asc("serial").
  69. Where("depth=? and project_id=? and isdelete=0", depth, projectId).
  70. Find(&datalist)
  71. if err != nil {
  72. return datalist
  73. } else {
  74. return datalist
  75. }
  76. }
  77. // 获得该目录下所有的目录
  78. func (d *TreeDao) GetChildFolder(id int) []models.CmTree {
  79. datalist := make([]models.CmTree, 0)
  80. err := d.engine.
  81. Asc("serial").
  82. Where("parent_id=? and isfolder=1 and isdelete=0", id).
  83. Find(&datalist)
  84. if err != nil {
  85. return datalist
  86. } else {
  87. return datalist
  88. }
  89. }
  90. // 获得某一深度的某一归属 结构数据(不包含子集) 正序
  91. func (d *TreeDao) GetALLDepthByAttribution(depth int, projectId int, attribution string) []models.CmTree {
  92. datalist := make([]models.CmTree, 0)
  93. err := d.engine.
  94. Asc("serial").
  95. Where("depth=? and project_id=? and attribution like ? and isdelete=0", depth, projectId, attribution+"%").
  96. Find(&datalist)
  97. if err != nil {
  98. return datalist
  99. } else {
  100. return datalist
  101. }
  102. }
  103. // 获得该目录下所有的目录和标段
  104. func (d *TreeDao) GetFolderAndBid(projectId int, attribution string) []models.CmTree {
  105. datalist := make([]models.CmTree, 0)
  106. err := d.engine.
  107. Asc("serial").
  108. Where("project_id=? and attribution like ? and isdelete=0", projectId, attribution+"%").
  109. Find(&datalist)
  110. if err != nil {
  111. return datalist
  112. } else {
  113. return datalist
  114. }
  115. }
  116. // 获得标段的目录
  117. func (d *TreeDao) GetBidParentId(bidsectionId int, projectId int) *models.CmTree {
  118. data := &models.CmTree{}
  119. _, err := d.engine.
  120. Where("bidsection_id=? and project_id=? and isdelete=0", bidsectionId, projectId).
  121. Get(data)
  122. if err != nil {
  123. data.Id = 0
  124. return data
  125. }
  126. return data
  127. }
  128. // 获得谋归属下的项目节
  129. func (d *TreeDao) GetAttribution(attribution string, projectId int) []models.CmTree {
  130. datalist := make([]models.CmTree, 0)
  131. err := d.engine.
  132. Asc("serial").
  133. Where("attribution like ? and project_id=? and isdelete=0", attribution+"%", projectId).
  134. Find(&datalist)
  135. if err != nil {
  136. return datalist
  137. } else {
  138. return datalist
  139. }
  140. }
  141. // 删除目录以及下属目录所有数据
  142. func (d *TreeDao) DeleteFolderAndBid(id int, projectId int, attribution string) error {
  143. session := d.engine.NewSession()
  144. defer session.Close()
  145. err := session.Begin()
  146. if err != nil {
  147. return errors.New("删除出错-db")
  148. }
  149. // 删除树结构中 目录和资源
  150. data := &models.CmTree{Isdelete: 1}
  151. _, err = session.
  152. Where("id=? or (project_id=? and attribution like ?) and isdelete=0", id, projectId, attribution+"%").
  153. Update(data)
  154. if err != nil {
  155. session.Rollback()
  156. return errors.New("删除目录出错")
  157. }
  158. // 获得已删除不是目录的资源
  159. datalist := make([]models.CmTree, 0)
  160. err = d.engine.
  161. Where("project_id=? and isdelete=1 and isfolder=0", projectId).
  162. Find(&datalist)
  163. // 删除标段
  164. if len(datalist) > 0 {
  165. idList := []string{}
  166. for _, bidData := range datalist {
  167. idList = append(idList, strconv.Itoa(bidData.Id))
  168. }
  169. inId := strings.Join(idList, ",")
  170. _, err = session.Exec("UPDATE cm_bidsection SET `isdelete` = 1 where id in (?)", inId)
  171. if err != nil {
  172. session.Rollback()
  173. return errors.New("删除标段出错")
  174. }
  175. }
  176. err = session.Commit()
  177. if err != nil {
  178. session.Rollback()
  179. return errors.New("删除出错-db")
  180. }
  181. return nil
  182. }
  183. // 移动目录
  184. func (d *TreeDao) Move(treeNode *models.CmTree, moveFolder *models.CmTree) error {
  185. session := d.engine.NewSession()
  186. defer session.Close()
  187. err := session.Begin()
  188. if err != nil {
  189. return errors.New("移动出错-db")
  190. }
  191. // 原目录父节点替换目标目录的ID
  192. _, err = session.Exec("UPDATE cm_tree SET `parent_id` = ? where id = ? and isdelete=0", moveFolder.Id, treeNode.Id)
  193. if err != nil {
  194. return err //errors.New("移动目录出错---")
  195. }
  196. // data := &models.CmTree{ParentId: moveFolder.Id}
  197. // _, err = session.
  198. // Where("id=? and isdelete=0", treeNode.Id).
  199. // Update(data)
  200. // if err != nil {
  201. // session.Rollback()
  202. // return err //errors.New("移动目录出错---")
  203. // }
  204. // 移动目录的归属和标段的归属关系--TODO 效率问题在修改
  205. // 1-原来目录的归属
  206. attribution := fmt.Sprintf("%s%d-", treeNode.Attribution, treeNode.Serial)
  207. // 2-移动后目录的归属--跟目录的话,所属为空
  208. movrAttribution := ""
  209. if moveFolder.Id != 0 {
  210. movrAttribution = fmt.Sprintf("%s%d-", moveFolder.Attribution, moveFolder.Serial)
  211. }
  212. // 3-获得移动后最大序列号
  213. depth := moveFolder.Depth + 1
  214. datalist := d.GetALLDepthByAttribution(depth, moveFolder.ProjectId, movrAttribution)
  215. maxIndex := len(datalist)
  216. serial := 0
  217. if maxIndex != 0 {
  218. serial = datalist[maxIndex-1].Serial + 1
  219. }
  220. // 3-1 深度差=原目录depth-目标目录depth
  221. difference := (treeNode.Depth - 1) - moveFolder.Depth
  222. // 移动后目录depth=原目录depth-差
  223. // 4-移动原目录或标段-最大序号
  224. _, err = session.Exec("UPDATE cm_tree SET `attribution` = ?,`serial` = ?,`depth` =`depth` - ? where id = ? and isdelete=0",
  225. movrAttribution, serial, difference, treeNode.Id)
  226. if err != nil {
  227. session.Rollback()
  228. log.Println("移动目录或标段1, error=", err)
  229. return errors.New("移动目录或标段出错1")
  230. }
  231. //
  232. // 5-移动原目录下所有子目录和标段-项目下
  233. movrAttribution = fmt.Sprintf("%s%d-", movrAttribution, serial)
  234. //`attribution` = replace(`attribution`, '"+attribution+"', '"+movrAttribution+"')
  235. _, err = session.Exec("UPDATE cm_tree SET "+
  236. "`depth` =`depth` - ? where attribution like ? and project_id=? and isdelete=0", difference, attribution+"%", treeNode.ProjectId)
  237. //_, err = session.Exec("UPDATE from cm_tree SET `attribution` = replace(`attribution`, ?, ?) where attribution like ?", attribution,movrAttribution,attribution+"%")
  238. if err != nil {
  239. session.Rollback()
  240. log.Println("移动目录或标段2, error=", err)
  241. return errors.New("移动目录或标段出错2")
  242. }
  243. // 6-目录孩子们的归属设置
  244. err = d.replaceContractAttribution(session, attribution, movrAttribution, treeNode.ProjectId)
  245. if err != nil {
  246. session.Rollback()
  247. return errors.New("移动失败")
  248. }
  249. err = session.Commit()
  250. if err != nil {
  251. session.Rollback()
  252. return errors.New("移动出错-db")
  253. }
  254. return nil
  255. }
  256. // 获得项目文件夹
  257. func (d *TreeDao) GetAllTree(projectId int) []models.CmTree {
  258. datalist := make([]models.CmTree, 0)
  259. err := d.engine.
  260. Asc("id").
  261. Where("project_id=? and isdelete=0", projectId).
  262. Find(&datalist)
  263. if err != nil {
  264. return datalist
  265. } else {
  266. return datalist
  267. }
  268. }
  269. // treeNode重命名
  270. func (d *TreeDao) Rename(data *models.CmTree, columns []string) error {
  271. session := d.engine.NewSession()
  272. defer session.Close()
  273. err := session.Begin()
  274. if err != nil {
  275. return errors.New("重命名失败-db")
  276. }
  277. // 重命名treeNode
  278. _, err = session.Id(data.Id).MustCols(columns...).Update(data)
  279. if err != nil {
  280. session.Rollback()
  281. return errors.New("标段重命名失败")
  282. }
  283. // 重命名标段
  284. bidsection := models.CmBidsection{}
  285. bidsection.Id = data.BidsectionId
  286. bidsection.Name = data.Name
  287. _, err = session.Id(bidsection.Id).MustCols(columns...).Update(bidsection)
  288. if err != nil {
  289. session.Rollback()
  290. return errors.New("标段重命名失败-bid")
  291. }
  292. err = session.Commit()
  293. if err != nil {
  294. session.Rollback()
  295. return errors.New("重命名失败-db")
  296. }
  297. return nil
  298. }
  299. //创建
  300. func (d *TreeDao) Create(data *models.CmTree) error {
  301. _, err := d.engine.Insert(data)
  302. return err
  303. }
  304. // 更新
  305. func (d *TreeDao) Update(data *models.CmTree, columns []string) error {
  306. _, err := d.engine.Id(data.Id).MustCols(columns...).Update(data)
  307. return err
  308. }
  309. // 更新标段目录上合同金额和总数
  310. func (d *TreeDao) UpdateContractsAndPayPrice(projectId int, bidsectionId int, contractTotal int, priceTotal float64) error {
  311. // 1.更新标段 上的合同总金额
  312. _, err := d.engine.Exec("UPDATE cm_tree SET `contracts` = ?,`contracts_pay` = ? "+
  313. "where project_id = ? and bidsection_id = ? ",
  314. contractTotal, priceTotal,
  315. projectId, bidsectionId)
  316. if err != nil {
  317. return errors.New("编辑标段目录-金额合计出错")
  318. }
  319. return nil
  320. }
  321. // 更新标段目录上合同金额和总数
  322. func (d *TreeDao) UpdateContractsAndIncomePrice(projectId int, bidsectionId int, contractTotal int, priceTotal float64) error {
  323. // 1.更新标段 上的合同总金额
  324. _, err := d.engine.Exec("UPDATE cm_tree SET `contracts` = ?,`contracts_income` = ? "+
  325. "where project_id = ? and bidsection_id = ? ",
  326. contractTotal, priceTotal,
  327. projectId, bidsectionId)
  328. if err != nil {
  329. return errors.New("编辑标段目录-金额合计出错")
  330. }
  331. // _, err :=d.engine.Where("project_id = ? and bidsection_id = ?",projectId,bidsectionId).MustCols().Update(treeCm)
  332. // _, err := d.engine.Id(data.Id).MustCols(columns...).Update(data)
  333. return nil
  334. }
  335. //替换项目节归属
  336. func (d *TreeDao) replaceContractAttribution(session *xorm.Session, attributionChildren string, moveAttributionChildren string, projectId int) error {
  337. // 1.获得需要替换的数据
  338. sectionData := d.GetAttribution(attributionChildren, projectId)
  339. if len(sectionData) == 0 {
  340. return nil
  341. }
  342. attributionSql := " attribution = case id "
  343. idList := make([]int, 0)
  344. for _, item := range sectionData {
  345. // 替换归属
  346. attributionSql += fmt.Sprintf("when %d then '%s' ", item.Id, strings.Replace(item.Attribution, attributionChildren, moveAttributionChildren, 1))
  347. idList = append(idList, item.Id)
  348. }
  349. attributionSql += " end "
  350. id := strings.Replace(strings.Trim(fmt.Sprint(idList), "[]"), " ", ",", -1)
  351. sql := "update cm_tree set " + attributionSql + " WHERE id IN (" + id + ")"
  352. _, err := session.Exec(sql)
  353. if err != nil {
  354. log.Println("替换标段归属, error=", err)
  355. return err
  356. }
  357. return nil
  358. }
  359. // 根据bid更新记录中的安全、质量巡检相关字段
  360. func (d *TreeDao) UpdateCounts(key string, value int64, bid int) error {
  361. attributionSql := fmt.Sprintf("%s = %d ", key, value)
  362. sql := "update cm_tree set " + attributionSql + "where bidsection_id = ?"
  363. _, err := d.engine.Exec(sql, bid)
  364. return err
  365. }