shop.go 16 KB

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