shop.go 15 KB

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