session.go 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. package basket
  2. import (
  3. "encoding/json"
  4. "html"
  5. "strings"
  6. "golang-fave/engine/sqlw"
  7. "golang-fave/utils"
  8. )
  9. type session struct {
  10. listCurrencies map[int]*currency
  11. totalSum float64
  12. Products map[int]*product `json:"products"`
  13. Currency *currency `json:"currency"`
  14. TotalSum string `json:"total_sum"`
  15. TotalCount int `json:"total_count"`
  16. }
  17. func (this *session) makePrice(product_price float64, product_currency_id int) float64 {
  18. if this.Currency == nil {
  19. return product_price
  20. }
  21. if this.Currency.Id == product_currency_id {
  22. return product_price
  23. }
  24. if product_currency_id == 1 {
  25. return product_price * this.Currency.Coefficient
  26. } else {
  27. if c, ok := this.listCurrencies[product_currency_id]; ok == true {
  28. return product_price / c.Coefficient
  29. } else {
  30. return product_price
  31. }
  32. }
  33. }
  34. func (this *session) updateProducts(db *sqlw.DB) {
  35. products_ids := []int{}
  36. for _, product := range this.Products {
  37. products_ids = append(products_ids, product.Id)
  38. }
  39. if len(products_ids) > 0 {
  40. if rows, err := db.Query(
  41. `SELECT
  42. shop_products.id,
  43. shop_products.name,
  44. shop_products.price,
  45. shop_products.alias,
  46. shop_currencies.id,
  47. shop_currencies.name,
  48. shop_currencies.coefficient,
  49. shop_currencies.code,
  50. shop_currencies.symbol,
  51. IF(image_this.filename IS NULL, IFNULL(shop_products.parent_id, shop_products.id), shop_products.id) as imgid,
  52. IFNULL(IFNULL(image_this.filename, image_parent.filename), '') as filename
  53. FROM
  54. shop_products
  55. LEFT JOIN shop_currencies ON shop_currencies.id = shop_products.currency
  56. LEFT JOIN (
  57. SELECT
  58. m.product_id,
  59. m.filename
  60. FROM
  61. shop_product_images as m
  62. LEFT JOIN (
  63. SELECT
  64. t.product_id,
  65. MIN(t.ord) as ordmin
  66. FROM
  67. shop_product_images as t
  68. GROUP BY
  69. t.product_id
  70. ) as u ON u.product_id = m.product_id AND u.ordmin = m.ord
  71. WHERE
  72. u.product_id IS NOT NULL
  73. ) as image_this ON image_this.product_id = shop_products.id
  74. LEFT JOIN (
  75. SELECT
  76. m.product_id,
  77. m.filename
  78. FROM
  79. shop_product_images as m
  80. LEFT JOIN (
  81. SELECT
  82. t.product_id,
  83. MIN(t.ord) as ordmin
  84. FROM
  85. shop_product_images as t
  86. GROUP BY
  87. t.product_id
  88. ) as u ON u.product_id = m.product_id AND u.ordmin = m.ord
  89. WHERE
  90. u.product_id IS NOT NULL
  91. ) as image_parent ON image_parent.product_id = shop_products.parent_id
  92. WHERE
  93. shop_products.active = 1 AND
  94. shop_products.id IN (` + strings.Join(utils.ArrayOfIntToArrayOfString(products_ids), ",") + `)
  95. ;`,
  96. ); err == nil {
  97. defer rows.Close()
  98. for rows.Next() {
  99. row := &utils.MySql_shop_product{}
  100. roc := &utils.MySql_shop_currency{}
  101. var img_product_id string
  102. var img_filename string
  103. if err = rows.Scan(
  104. &row.A_id,
  105. &row.A_name,
  106. &row.A_price,
  107. &row.A_alias,
  108. &roc.A_id,
  109. &roc.A_name,
  110. &roc.A_coefficient,
  111. &roc.A_code,
  112. &roc.A_symbol,
  113. &img_product_id,
  114. &img_filename,
  115. ); err == nil {
  116. if p, ok := this.Products[row.A_id]; ok == true {
  117. var product_image string
  118. if img_filename == "" {
  119. product_image = utils.GetImagePlaceholderSrc()
  120. } else {
  121. product_image = "/products/images/" + img_product_id + "/thumb-0-" + img_filename
  122. }
  123. p.Name = html.EscapeString(row.A_name)
  124. p.Image = product_image
  125. p.Link = "/shop/" + row.A_alias + "/"
  126. p.price = row.A_price
  127. p.currency.Id = roc.A_id
  128. p.currency.Name = html.EscapeString(roc.A_name)
  129. p.currency.Coefficient = roc.A_coefficient
  130. p.currency.Code = html.EscapeString(roc.A_code)
  131. p.currency.Symbol = html.EscapeString(roc.A_symbol)
  132. }
  133. }
  134. }
  135. }
  136. }
  137. }
  138. func (this *session) updateTotals(p *SBParam) {
  139. this.totalSum = 0
  140. this.TotalCount = 0
  141. for _, product := range this.Products {
  142. product.Price = utils.FormatProductPrice(this.makePrice(product.price, product.currency.Id), (*p.Config).Shop.Price.Format, (*p.Config).Shop.Price.Round)
  143. product.Sum = utils.FormatProductPrice(this.makePrice(product.price*float64(product.Quantity), product.currency.Id), (*p.Config).Shop.Price.Format, (*p.Config).Shop.Price.Round)
  144. this.totalSum += this.makePrice(product.price, product.currency.Id) * float64(product.Quantity)
  145. this.TotalCount += product.Quantity
  146. }
  147. this.TotalSum = utils.FormatProductPrice(this.totalSum, (*p.Config).Shop.Price.Format, (*p.Config).Shop.Price.Round)
  148. }
  149. func (this *session) Preload(p *SBParam) {
  150. user_currency := 1
  151. if cookie, err := p.R.Cookie("currency"); err == nil {
  152. user_currency = utils.StrToInt(cookie.Value)
  153. }
  154. // Clear list of currencies
  155. this.listCurrencies = map[int]*currency{}
  156. // Load currencies from database
  157. if rows, err := p.DB.Query(
  158. `SELECT
  159. id,
  160. name,
  161. coefficient,
  162. code,
  163. symbol
  164. FROM
  165. shop_currencies
  166. ORDER BY
  167. id ASC
  168. ;`,
  169. ); err == nil {
  170. defer rows.Close()
  171. for rows.Next() {
  172. roc := &utils.MySql_shop_currency{}
  173. if err = rows.Scan(
  174. &roc.A_id,
  175. &roc.A_name,
  176. &roc.A_coefficient,
  177. &roc.A_code,
  178. &roc.A_symbol,
  179. ); err == nil {
  180. this.listCurrencies[roc.A_id] = &currency{
  181. Id: roc.A_id,
  182. Name: html.EscapeString(roc.A_name),
  183. Coefficient: roc.A_coefficient,
  184. Code: html.EscapeString(roc.A_code),
  185. Symbol: html.EscapeString(roc.A_symbol),
  186. }
  187. }
  188. }
  189. }
  190. // Check if selected currency is exists
  191. if _, ok := this.listCurrencies[user_currency]; ok != true {
  192. user_currency = 1
  193. }
  194. // Remember selected currency
  195. if c, ok := this.listCurrencies[user_currency]; ok == true {
  196. this.Currency = &currency{
  197. Id: c.Id,
  198. Name: c.Name,
  199. Coefficient: c.Coefficient,
  200. Code: c.Code,
  201. Symbol: c.Symbol,
  202. }
  203. }
  204. }
  205. func (this *session) String(p *SBParam) string {
  206. this.updateProducts(p.DB)
  207. this.updateTotals(p)
  208. json, err := json.Marshal(this)
  209. if err != nil {
  210. return `{"msg":"basket_engine_error","message":"` + err.Error() + `"}`
  211. }
  212. return string(json)
  213. }
  214. func (this *session) Plus(p *SBParam, product_id int) {
  215. if prod, ok := this.Products[product_id]; ok == true {
  216. prod.Quantity++
  217. this.updateProducts(p.DB)
  218. this.updateTotals(p)
  219. return
  220. }
  221. row := &utils.MySql_shop_product{}
  222. roc := &utils.MySql_shop_currency{}
  223. var img_product_id string
  224. var img_filename string
  225. if err := p.DB.QueryRow(`
  226. SELECT
  227. shop_products.id,
  228. shop_products.name,
  229. shop_products.price,
  230. shop_products.alias,
  231. shop_currencies.id,
  232. shop_currencies.name,
  233. shop_currencies.coefficient,
  234. shop_currencies.code,
  235. shop_currencies.symbol,
  236. IF(image_this.filename IS NULL, IFNULL(shop_products.parent_id, shop_products.id), shop_products.id) as imgid,
  237. IFNULL(IFNULL(image_this.filename, image_parent.filename), '') as filename
  238. FROM
  239. shop_products
  240. LEFT JOIN shop_currencies ON shop_currencies.id = shop_products.currency
  241. LEFT JOIN (
  242. SELECT
  243. m.product_id,
  244. m.filename
  245. FROM
  246. shop_product_images as m
  247. LEFT JOIN (
  248. SELECT
  249. t.product_id,
  250. MIN(t.ord) as ordmin
  251. FROM
  252. shop_product_images as t
  253. GROUP BY
  254. t.product_id
  255. ) as u ON u.product_id = m.product_id AND u.ordmin = m.ord
  256. WHERE
  257. u.product_id IS NOT NULL
  258. ) as image_this ON image_this.product_id = shop_products.id
  259. LEFT JOIN (
  260. SELECT
  261. m.product_id,
  262. m.filename
  263. FROM
  264. shop_product_images as m
  265. LEFT JOIN (
  266. SELECT
  267. t.product_id,
  268. MIN(t.ord) as ordmin
  269. FROM
  270. shop_product_images as t
  271. GROUP BY
  272. t.product_id
  273. ) as u ON u.product_id = m.product_id AND u.ordmin = m.ord
  274. WHERE
  275. u.product_id IS NOT NULL
  276. ) as image_parent ON image_parent.product_id = shop_products.parent_id
  277. WHERE
  278. shop_products.active = 1 AND
  279. shop_products.id = ?
  280. LIMIT 1;`,
  281. product_id,
  282. ).Scan(
  283. &row.A_id,
  284. &row.A_name,
  285. &row.A_price,
  286. &row.A_alias,
  287. &roc.A_id,
  288. &roc.A_name,
  289. &roc.A_coefficient,
  290. &roc.A_code,
  291. &roc.A_symbol,
  292. &img_product_id,
  293. &img_filename,
  294. ); err == nil {
  295. var product_image string
  296. if img_filename == "" {
  297. product_image = utils.GetImagePlaceholderSrc()
  298. } else {
  299. product_image = "/products/images/" + img_product_id + "/thumb-0-" + img_filename
  300. }
  301. this.Products[product_id] = &product{
  302. currency: &currency{Id: roc.A_id, Name: roc.A_name, Coefficient: roc.A_coefficient, Code: roc.A_code, Symbol: roc.A_symbol},
  303. Id: row.A_id,
  304. Name: html.EscapeString(row.A_name),
  305. Image: product_image,
  306. Link: "/shop/" + row.A_alias + "/",
  307. price: row.A_price,
  308. Quantity: 1,
  309. }
  310. this.updateProducts(p.DB)
  311. this.updateTotals(p)
  312. }
  313. }
  314. func (this *session) Minus(p *SBParam, product_id int) {
  315. if prod, ok := this.Products[product_id]; ok == true {
  316. if prod.Quantity > 1 {
  317. prod.Quantity--
  318. } else {
  319. delete(this.Products, product_id)
  320. }
  321. this.updateProducts(p.DB)
  322. this.updateTotals(p)
  323. }
  324. }
  325. func (this *session) Remove(p *SBParam, product_id int) {
  326. if _, ok := this.Products[product_id]; ok == true {
  327. delete(this.Products, product_id)
  328. this.updateProducts(p.DB)
  329. this.updateTotals(p)
  330. }
  331. }
  332. func (this *session) ClearBasket(p *SBParam) {
  333. this.Products = map[int]*product{}
  334. this.updateProducts(p.DB)
  335. this.updateTotals(p)
  336. }
  337. func (this *session) ProductsCount() int {
  338. return this.TotalCount
  339. }
  340. func (this *session) GetAll(p *SBParam) *utils.MySql_basket {
  341. products := []utils.MySql_basket_product{}
  342. for _, product := range this.Products {
  343. products = append(products, utils.MySql_basket_product{
  344. A_product_id: product.Id,
  345. A_price: this.makePrice(product.price, product.currency.Id),
  346. A_quantity: product.Quantity,
  347. })
  348. }
  349. currency := utils.MySql_basket_currency{
  350. Id: this.Currency.Id,
  351. Name: this.Currency.Name,
  352. Coefficient: this.Currency.Coefficient,
  353. Code: this.Currency.Code,
  354. Symbol: this.Currency.Symbol,
  355. }
  356. all := utils.MySql_basket{
  357. Products: &products,
  358. Currency: &currency,
  359. TotalSum: this.totalSum,
  360. TotalCount: this.TotalCount,
  361. }
  362. return &all
  363. }