shop.go 15 KB

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