shop.go 15 KB

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