session.go 10 KB

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