shop.go 17 KB

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