shop.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. package fetdata
  2. import (
  3. "math"
  4. "sort"
  5. "strings"
  6. "golang-fave/engine/wrapper"
  7. "golang-fave/utils"
  8. )
  9. type ShopPagination struct {
  10. Num string
  11. Link string
  12. Current bool
  13. Dots bool
  14. }
  15. type Shop struct {
  16. wrap *wrapper.Wrapper
  17. category *ShopCategory
  18. product *ShopProduct
  19. products []*ShopProduct
  20. productsCount int
  21. productsPerPage int
  22. productsMaxPage int
  23. productsCurrPage int
  24. pagination []*ShopPagination
  25. paginationPrev *ShopPagination
  26. paginationNext *ShopPagination
  27. bufferCats map[int]*utils.MySql_shop_category
  28. }
  29. func (this *Shop) load() *Shop {
  30. if this == nil {
  31. return this
  32. }
  33. sql_nums := `
  34. SELECT
  35. COUNT(*)
  36. FROM
  37. shop_products
  38. WHERE
  39. active = 1
  40. ;
  41. `
  42. sql_rows := `
  43. SELECT
  44. shop_products.id,
  45. shop_products.user,
  46. shop_products.currency,
  47. shop_products.price,
  48. shop_products.name,
  49. shop_products.alias,
  50. shop_products.vendor,
  51. shop_products.quantity,
  52. shop_products.category,
  53. shop_products.briefly,
  54. shop_products.content,
  55. UNIX_TIMESTAMP(shop_products.datetime) as datetime,
  56. shop_products.active,
  57. users.id,
  58. users.first_name,
  59. users.last_name,
  60. users.email,
  61. users.admin,
  62. users.active,
  63. shop_currencies.id,
  64. shop_currencies.name,
  65. shop_currencies.coefficient,
  66. shop_currencies.code,
  67. shop_currencies.symbol,
  68. cats.id,
  69. cats.user,
  70. cats.name,
  71. cats.alias,
  72. cats.lft,
  73. cats.rgt,
  74. cats.depth,
  75. cats.parent_id
  76. FROM
  77. shop_products
  78. LEFT JOIN users ON users.id = shop_products.user
  79. LEFT JOIN shop_currencies ON shop_currencies.id = shop_products.currency
  80. LEFT JOIN (
  81. SELECT
  82. main.id,
  83. main.user,
  84. main.name,
  85. main.alias,
  86. main.lft,
  87. main.rgt,
  88. depth.depth,
  89. MAX(main.parent_id) AS parent_id
  90. FROM
  91. (
  92. SELECT
  93. node.id,
  94. node.user,
  95. node.name,
  96. node.alias,
  97. node.lft,
  98. node.rgt,
  99. parent.id AS parent_id
  100. FROM
  101. shop_cats AS node,
  102. shop_cats AS parent
  103. WHERE
  104. node.lft BETWEEN parent.lft AND parent.rgt AND
  105. node.id > 1
  106. ORDER BY
  107. node.lft ASC
  108. ) AS main
  109. LEFT JOIN (
  110. SELECT
  111. node.id,
  112. (COUNT(parent.id) - 1) AS depth
  113. FROM
  114. shop_cats AS node,
  115. shop_cats AS parent
  116. WHERE
  117. node.lft BETWEEN parent.lft AND parent.rgt
  118. GROUP BY
  119. node.id
  120. ORDER BY
  121. node.lft ASC
  122. ) AS depth ON depth.id = main.id
  123. WHERE
  124. main.id > 1 AND
  125. main.id <> main.parent_id
  126. GROUP BY
  127. main.id
  128. ) AS cats ON cats.id = shop_products.category
  129. WHERE
  130. shop_products.active = 1
  131. ORDER BY
  132. shop_products.id DESC
  133. LIMIT ?, ?;
  134. `
  135. // Category selected
  136. if this.category != nil {
  137. var cat_ids []string
  138. if rows, err := this.wrap.DB.Query(
  139. `SELECT
  140. node.id
  141. FROM
  142. shop_cats AS node,
  143. shop_cats AS parent
  144. WHERE
  145. node.lft BETWEEN parent.lft AND parent.rgt AND
  146. node.id > 1 AND
  147. parent.id = ?
  148. GROUP BY
  149. node.id
  150. ORDER BY
  151. node.lft ASC
  152. ;`,
  153. this.category.Id(),
  154. ); err == nil {
  155. defer rows.Close()
  156. for rows.Next() {
  157. var cat_id string
  158. if err := rows.Scan(&cat_id); err == nil {
  159. cat_ids = append(cat_ids, cat_id)
  160. }
  161. }
  162. }
  163. sql_nums = `
  164. SELECT
  165. COUNT(*)
  166. FROM
  167. (
  168. SELECT
  169. COUNT(*)
  170. FROM
  171. shop_products
  172. LEFT JOIN shop_cat_product_rel ON shop_cat_product_rel.product_id = shop_products.id
  173. WHERE
  174. shop_products.active = 1 AND
  175. shop_cat_product_rel.category_id IN (` + strings.Join(cat_ids, ", ") + `)
  176. GROUP BY
  177. shop_products.id
  178. ) AS tbl
  179. ;
  180. `
  181. sql_rows = `
  182. SELECT
  183. shop_products.id,
  184. shop_products.user,
  185. shop_products.currency,
  186. shop_products.price,
  187. shop_products.name,
  188. shop_products.alias,
  189. shop_products.vendor,
  190. shop_products.quantity,
  191. shop_products.category,
  192. shop_products.briefly,
  193. shop_products.content,
  194. UNIX_TIMESTAMP(shop_products.datetime) AS datetime,
  195. shop_products.active,
  196. users.id,
  197. users.first_name,
  198. users.last_name,
  199. users.email,
  200. users.admin,
  201. users.active,
  202. shop_currencies.id,
  203. shop_currencies.name,
  204. shop_currencies.coefficient,
  205. shop_currencies.code,
  206. shop_currencies.symbol,
  207. cats.id,
  208. cats.user,
  209. cats.name,
  210. cats.alias,
  211. cats.lft,
  212. cats.rgt,
  213. cats.depth,
  214. cats.parent_id
  215. FROM
  216. shop_products
  217. LEFT JOIN shop_cat_product_rel ON shop_cat_product_rel.product_id = shop_products.id
  218. LEFT JOIN users ON users.id = shop_products.user
  219. LEFT JOIN shop_currencies ON shop_currencies.id = shop_products.currency
  220. LEFT JOIN (
  221. SELECT
  222. main.id,
  223. main.user,
  224. main.name,
  225. main.alias,
  226. main.lft,
  227. main.rgt,
  228. depth.depth,
  229. MAX(main.parent_id) AS parent_id
  230. FROM
  231. (
  232. SELECT
  233. node.id,
  234. node.user,
  235. node.name,
  236. node.alias,
  237. node.lft,
  238. node.rgt,
  239. parent.id AS parent_id
  240. FROM
  241. shop_cats AS node,
  242. shop_cats AS parent
  243. WHERE
  244. node.lft BETWEEN parent.lft AND parent.rgt AND
  245. node.id > 1
  246. ORDER BY
  247. node.lft ASC
  248. ) AS main
  249. LEFT JOIN (
  250. SELECT
  251. node.id,
  252. (COUNT(parent.id) - 1) AS depth
  253. FROM
  254. shop_cats AS node,
  255. shop_cats AS parent
  256. WHERE
  257. node.lft BETWEEN parent.lft AND parent.rgt
  258. GROUP BY
  259. node.id
  260. ORDER BY
  261. node.lft ASC
  262. ) AS depth ON depth.id = main.id
  263. WHERE
  264. main.id > 1 AND
  265. main.id <> main.parent_id
  266. GROUP BY
  267. main.id
  268. ) AS cats ON cats.id = shop_products.category
  269. WHERE
  270. shop_products.active = 1 AND
  271. shop_cat_product_rel.category_id IN (` + strings.Join(cat_ids, ", ") + `)
  272. GROUP BY
  273. shop_products.id
  274. ORDER BY
  275. shop_products.id DESC
  276. LIMIT ?, ?;
  277. `
  278. }
  279. product_ids := []string{}
  280. if err := this.wrap.DB.QueryRow(sql_nums).Scan(&this.productsCount); err == nil {
  281. if this.category == nil {
  282. this.productsPerPage = (*this.wrap.Config).Shop.Pagination.Index
  283. } else {
  284. this.productsPerPage = (*this.wrap.Config).Shop.Pagination.Category
  285. }
  286. this.productsMaxPage = int(math.Ceil(float64(this.productsCount) / float64(this.productsPerPage)))
  287. this.productsCurrPage = this.wrap.GetCurrentPage(this.productsMaxPage)
  288. offset := this.productsCurrPage*this.productsPerPage - this.productsPerPage
  289. if rows, err := this.wrap.DB.Query(sql_rows, offset, this.productsPerPage); err == nil {
  290. defer rows.Close()
  291. for rows.Next() {
  292. rp := utils.MySql_shop_product{}
  293. ru := utils.MySql_user{}
  294. rc := utils.MySql_shop_currency{}
  295. ro := utils.MySql_shop_category{}
  296. if err := rows.Scan(
  297. &rp.A_id,
  298. &rp.A_user,
  299. &rp.A_currency,
  300. &rp.A_price,
  301. &rp.A_name,
  302. &rp.A_alias,
  303. &rp.A_vendor,
  304. &rp.A_quantity,
  305. &rp.A_category,
  306. &rp.A_briefly,
  307. &rp.A_content,
  308. &rp.A_datetime,
  309. &rp.A_active,
  310. &ru.A_id,
  311. &ru.A_first_name,
  312. &ru.A_last_name,
  313. &ru.A_email,
  314. &ru.A_admin,
  315. &ru.A_active,
  316. &rc.A_id,
  317. &rc.A_name,
  318. &rc.A_coefficient,
  319. &rc.A_code,
  320. &rc.A_symbol,
  321. &ro.A_id,
  322. &ro.A_user,
  323. &ro.A_name,
  324. &ro.A_alias,
  325. &ro.A_lft,
  326. &ro.A_rgt,
  327. &ro.A_depth,
  328. &ro.A_parent,
  329. ); err == nil {
  330. product_ids = append(product_ids, utils.IntToStr(rp.A_id))
  331. this.products = append(this.products, &ShopProduct{
  332. wrap: this.wrap,
  333. object: &rp,
  334. user: &User{wrap: this.wrap, object: &ru},
  335. currency: &Currency{wrap: this.wrap, object: &rc},
  336. category: &ShopCategory{wrap: this.wrap, object: &ro},
  337. })
  338. }
  339. }
  340. }
  341. }
  342. // Product images
  343. product_images := map[int][]*ShopProductImage{}
  344. if len(product_ids) > 0 {
  345. if rows, err := this.wrap.DB.Query(
  346. `SELECT
  347. shop_product_images.product_id,
  348. shop_product_images.filename
  349. FROM
  350. shop_product_images
  351. WHERE
  352. shop_product_images.product_id IN (` + strings.Join(product_ids, ", ") + `)
  353. ORDER BY
  354. shop_product_images.filename ASC
  355. ;`,
  356. ); err == nil {
  357. defer rows.Close()
  358. for rows.Next() {
  359. img := utils.MySql_shop_product_image{}
  360. if err := rows.Scan(
  361. &img.A_product_id,
  362. &img.A_filename,
  363. ); err == nil {
  364. product_images[img.A_product_id] = append(product_images[img.A_product_id], &ShopProductImage{wrap: this.wrap, object: &img})
  365. }
  366. }
  367. }
  368. }
  369. for index, product := range this.products {
  370. if pimgs, ok := product_images[product.Id()]; ok {
  371. this.products[index].images = pimgs
  372. }
  373. }
  374. // Build pagination
  375. if true {
  376. for i := 1; i < this.productsCurrPage; i++ {
  377. if this.productsCurrPage >= 5 && i > 1 && i < this.productsCurrPage-1 {
  378. continue
  379. }
  380. if this.productsCurrPage >= 5 && i > 1 && i < this.productsCurrPage {
  381. this.pagination = append(this.pagination, &ShopPagination{
  382. Dots: true,
  383. })
  384. }
  385. link := this.wrap.R.URL.Path
  386. if i > 1 {
  387. link = link + "?p=" + utils.IntToStr(i)
  388. }
  389. this.pagination = append(this.pagination, &ShopPagination{
  390. Num: utils.IntToStr(i),
  391. Link: link,
  392. Current: false,
  393. })
  394. }
  395. // Current page
  396. link := this.wrap.R.URL.Path
  397. if this.productsCurrPage > 1 {
  398. link = link + "?p=" + utils.IntToStr(this.productsCurrPage)
  399. }
  400. this.pagination = append(this.pagination, &ShopPagination{
  401. Num: utils.IntToStr(this.productsCurrPage),
  402. Link: link,
  403. Current: true,
  404. })
  405. for i := this.productsCurrPage + 1; i <= this.productsMaxPage; i++ {
  406. if this.productsCurrPage < this.productsMaxPage-3 && i == this.productsCurrPage+3 {
  407. this.pagination = append(this.pagination, &ShopPagination{
  408. Dots: true,
  409. })
  410. }
  411. if this.productsCurrPage < this.productsMaxPage-3 && i > this.productsCurrPage+1 && i <= this.productsMaxPage-1 {
  412. continue
  413. }
  414. link := this.wrap.R.URL.Path
  415. if i > 1 {
  416. link = link + "?p=" + utils.IntToStr(i)
  417. }
  418. this.pagination = append(this.pagination, &ShopPagination{
  419. Num: utils.IntToStr(i),
  420. Link: link,
  421. Current: false,
  422. })
  423. }
  424. } else {
  425. for i := 1; i <= this.productsMaxPage; i++ {
  426. link := this.wrap.R.URL.Path
  427. if i > 1 {
  428. link = link + "?p=" + utils.IntToStr(i)
  429. }
  430. this.pagination = append(this.pagination, &ShopPagination{
  431. Num: utils.IntToStr(i),
  432. Link: link,
  433. Current: i == this.productsCurrPage,
  434. })
  435. }
  436. }
  437. // Pagination prev/next
  438. if this.productsMaxPage > 1 {
  439. link := this.wrap.R.URL.Path
  440. if this.productsCurrPage-1 > 1 {
  441. link = this.wrap.R.URL.Path + "?p=" + utils.IntToStr(this.productsCurrPage-1)
  442. }
  443. this.paginationPrev = &ShopPagination{
  444. Num: utils.IntToStr(this.productsCurrPage - 1),
  445. Link: link,
  446. Current: this.productsCurrPage <= 1,
  447. }
  448. if this.productsCurrPage >= 1 && this.productsCurrPage < this.productsMaxPage {
  449. link = this.wrap.R.URL.Path + "?p=" + utils.IntToStr(this.productsCurrPage+1)
  450. } else {
  451. link = this.wrap.R.URL.Path + "?p=" + utils.IntToStr(this.productsMaxPage)
  452. }
  453. this.paginationNext = &ShopPagination{
  454. Num: utils.IntToStr(this.productsCurrPage + 1),
  455. Link: link,
  456. Current: this.productsCurrPage >= this.productsMaxPage,
  457. }
  458. }
  459. return this
  460. }
  461. func (this *Shop) Category() *ShopCategory {
  462. if this == nil {
  463. return nil
  464. }
  465. return this.category
  466. }
  467. func (this *Shop) Product() *ShopProduct {
  468. if this == nil {
  469. return nil
  470. }
  471. return this.product
  472. }
  473. func (this *Shop) HaveProducts() bool {
  474. if this == nil {
  475. return false
  476. }
  477. if len(this.products) <= 0 {
  478. return false
  479. }
  480. return true
  481. }
  482. func (this *Shop) Products() []*ShopProduct {
  483. if this == nil {
  484. return []*ShopProduct{}
  485. }
  486. return this.products
  487. }
  488. func (this *Shop) ProductsCount() int {
  489. if this == nil {
  490. return 0
  491. }
  492. return this.productsCount
  493. }
  494. func (this *Shop) ProductsPerPage() int {
  495. if this == nil {
  496. return 0
  497. }
  498. return this.productsPerPage
  499. }
  500. func (this *Shop) ProductsMaxPage() int {
  501. if this == nil {
  502. return 0
  503. }
  504. return this.productsMaxPage
  505. }
  506. func (this *Shop) ProductsCurrPage() int {
  507. if this == nil {
  508. return 0
  509. }
  510. return this.productsCurrPage
  511. }
  512. func (this *Shop) Pagination() []*ShopPagination {
  513. if this == nil {
  514. return []*ShopPagination{}
  515. }
  516. return this.pagination
  517. }
  518. func (this *Shop) PaginationPrev() *ShopPagination {
  519. if this == nil {
  520. return nil
  521. }
  522. return this.paginationPrev
  523. }
  524. func (this *Shop) PaginationNext() *ShopPagination {
  525. if this == nil {
  526. return nil
  527. }
  528. return this.paginationNext
  529. }
  530. func (this *Shop) Categories(parent, depth int) []*ShopCategory {
  531. if this.bufferCats == nil {
  532. this.bufferCats = map[int]*utils.MySql_shop_category{}
  533. if rows, err := this.wrap.DB.Query(`
  534. SELECT
  535. main.id,
  536. main.user,
  537. main.name,
  538. main.alias,
  539. main.lft,
  540. main.rgt,
  541. depth.depth,
  542. MAX(main.parent_id) AS parent_id
  543. FROM
  544. (
  545. SELECT
  546. node.id,
  547. node.user,
  548. node.name,
  549. node.alias,
  550. node.lft,
  551. node.rgt,
  552. parent.id AS parent_id
  553. FROM
  554. shop_cats AS node,
  555. shop_cats AS parent
  556. WHERE
  557. node.lft BETWEEN parent.lft AND parent.rgt AND
  558. node.id > 1
  559. ORDER BY
  560. node.lft ASC
  561. ) AS main
  562. LEFT JOIN (
  563. SELECT
  564. node.id,
  565. (COUNT(parent.id) - 1) AS depth
  566. FROM
  567. shop_cats AS node,
  568. shop_cats AS parent
  569. WHERE
  570. node.lft BETWEEN parent.lft AND parent.rgt
  571. GROUP BY
  572. node.id
  573. ORDER BY
  574. node.lft ASC
  575. ) AS depth ON depth.id = main.id
  576. WHERE
  577. main.id > 1 AND
  578. main.id <> main.parent_id
  579. GROUP BY
  580. main.id
  581. ORDER BY
  582. main.lft ASC
  583. ;
  584. `); err == nil {
  585. defer rows.Close()
  586. for rows.Next() {
  587. row := utils.MySql_shop_category{}
  588. if err := rows.Scan(
  589. &row.A_id,
  590. &row.A_user,
  591. &row.A_name,
  592. &row.A_alias,
  593. &row.A_lft,
  594. &row.A_rgt,
  595. &row.A_depth,
  596. &row.A_parent,
  597. ); err == nil {
  598. this.bufferCats[row.A_id] = &row
  599. }
  600. }
  601. }
  602. }
  603. depth_tmp := 0
  604. result := []*ShopCategory{}
  605. for _, cat := range this.bufferCats {
  606. if parent <= 1 {
  607. if depth <= 0 {
  608. result = append(result, (&ShopCategory{wrap: this.wrap, object: cat}).load(&this.bufferCats))
  609. } else {
  610. if cat.A_depth <= depth {
  611. result = append(result, (&ShopCategory{wrap: this.wrap, object: cat}).load(&this.bufferCats))
  612. }
  613. }
  614. } else {
  615. if cat.A_parent == parent {
  616. if depth_tmp == 0 {
  617. depth_tmp = cat.A_depth
  618. }
  619. if depth <= 0 {
  620. result = append(result, (&ShopCategory{wrap: this.wrap, object: cat}).load(&this.bufferCats))
  621. } else {
  622. if (cat.A_depth - depth_tmp + 1) <= depth {
  623. result = append(result, (&ShopCategory{wrap: this.wrap, object: cat}).load(&this.bufferCats))
  624. }
  625. }
  626. }
  627. }
  628. }
  629. sort.Slice(result, func(i, j int) bool { return result[i].Left() < result[j].Left() })
  630. return result
  631. }