shop.go 15 KB

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