Sfoglia il codice sorgente

更新分支信息

abiao 4 anni fa
parent
commit
df6bf986fa
100 ha cambiato i file con 8266 aggiunte e 1932 eliminazioni
  1. 4 0
      .gitignore
  2. 12 5
      go/gopath/src/fohow.com/apps/controllers/ad_controller/ad_controller.go
  3. 6 6
      go/gopath/src/fohow.com/apps/controllers/address_controller/address_controller.go
  4. 31 31
      go/gopath/src/fohow.com/apps/controllers/article_controller/article_controller.go
  5. 35 12
      go/gopath/src/fohow.com/apps/controllers/balance_controller/balance_controller.go
  6. 5 5
      go/gopath/src/fohow.com/apps/controllers/cent_controller/cent_controller.go
  7. 1 1
      go/gopath/src/fohow.com/apps/controllers/cron_controller/init.go
  8. 7 5
      go/gopath/src/fohow.com/apps/controllers/cron_controller/sync_balance.go
  9. 11 1
      go/gopath/src/fohow.com/apps/controllers/cron_controller/update_sold_count.go
  10. 9 17
      go/gopath/src/fohow.com/apps/controllers/customer_service_controller/customer_service_controller.go
  11. 10 3
      go/gopath/src/fohow.com/apps/controllers/live_controller/live_controller.go
  12. 14 11
      go/gopath/src/fohow.com/apps/controllers/mp_controller/mp_controller.go
  13. 39 51
      go/gopath/src/fohow.com/apps/controllers/order_controller/cart_controller.go
  14. 2 2
      go/gopath/src/fohow.com/apps/controllers/order_controller/init.go
  15. 261 127
      go/gopath/src/fohow.com/apps/controllers/order_controller/order_controller.go
  16. 19 175
      go/gopath/src/fohow.com/apps/controllers/pay_controller/after_pay_controller.go
  17. 2 2
      go/gopath/src/fohow.com/apps/controllers/pay_controller/init.go
  18. 3 3
      go/gopath/src/fohow.com/apps/controllers/pay_controller/pay_balance_controller.go
  19. 3 3
      go/gopath/src/fohow.com/apps/controllers/pay_controller/pay_cashcz_controller.go
  20. 7 5
      go/gopath/src/fohow.com/apps/controllers/pay_controller/pay_controller.go
  21. 232 96
      go/gopath/src/fohow.com/apps/controllers/pay_controller/pay_exchange_controller.go
  22. 4 41
      go/gopath/src/fohow.com/apps/controllers/pay_controller/recharge_controller.go
  23. 153 498
      go/gopath/src/fohow.com/apps/controllers/permit_controller/permit_controller.go
  24. 175 0
      go/gopath/src/fohow.com/apps/controllers/pick_address_controller/pick_address_controller.go
  25. 4 4
      go/gopath/src/fohow.com/apps/controllers/poster_controller/poster_controller.go
  26. 2 2
      go/gopath/src/fohow.com/apps/controllers/product_controller/init.go
  27. 190 12
      go/gopath/src/fohow.com/apps/controllers/product_controller/product_controller.go
  28. 23 0
      go/gopath/src/fohow.com/apps/controllers/promotion_controller/init.go
  29. 37 0
      go/gopath/src/fohow.com/apps/controllers/promotion_controller/promotion_controller.go
  30. 27 0
      go/gopath/src/fohow.com/apps/controllers/railsadmin_controller/balance_order_controller.go
  31. 12 3
      go/gopath/src/fohow.com/apps/controllers/railsadmin_controller/cache_controller.go
  32. 2 1
      go/gopath/src/fohow.com/apps/controllers/railsadmin_controller/generate_controller.go
  33. 1 6
      go/gopath/src/fohow.com/apps/controllers/railsadmin_controller/intro_user_controller.go
  34. 22 4
      go/gopath/src/fohow.com/apps/controllers/railsadmin_controller/live_award_controller.go
  35. 42 0
      go/gopath/src/fohow.com/apps/controllers/railsadmin_controller/order_award_controller.go
  36. 25 1
      go/gopath/src/fohow.com/apps/controllers/railsadmin_controller/order_dispatch_controller.go
  37. 2 2
      go/gopath/src/fohow.com/apps/controllers/railsadmin_controller/order_refund_controller.go
  38. 1 1
      go/gopath/src/fohow.com/apps/controllers/railsadmin_controller/tmpl_controller.go
  39. 12 13
      go/gopath/src/fohow.com/apps/controllers/railsadmin_controller/update_shop_application.go
  40. 1 1
      go/gopath/src/fohow.com/apps/controllers/share_controller/share_controller.go
  41. 32 0
      go/gopath/src/fohow.com/apps/controllers/sys_controller/init.go
  42. 31 0
      go/gopath/src/fohow.com/apps/controllers/sys_controller/sys_controller.go
  43. 18 2
      go/gopath/src/fohow.com/apps/controllers/test_controller/test_controller.go
  44. 199 0
      go/gopath/src/fohow.com/apps/controllers/user_controller/agent_apply_controller.go
  45. 2 14
      go/gopath/src/fohow.com/apps/controllers/user_controller/binding_controller.go
  46. 6 109
      go/gopath/src/fohow.com/apps/controllers/user_controller/binding_wx_phone_controller.go
  47. 1 1
      go/gopath/src/fohow.com/apps/controllers/user_controller/invite_controller.go
  48. 0 8
      go/gopath/src/fohow.com/apps/controllers/user_controller/one_click_binding_controller.go
  49. 44 13
      go/gopath/src/fohow.com/apps/controllers/user_controller/user_controller.go
  50. 1 1
      go/gopath/src/fohow.com/apps/controllers/xcx_controller/xcx_controller.go
  51. 106 0
      go/gopath/src/fohow.com/apps/helper/aes.go
  52. 174 0
      go/gopath/src/fohow.com/apps/helper/array.go
  53. 137 0
      go/gopath/src/fohow.com/apps/helper/captcha/bilinear.go
  54. 273 0
      go/gopath/src/fohow.com/apps/helper/captcha/captcha.go
  55. 224 0
      go/gopath/src/fohow.com/apps/helper/captcha/draw.go
  56. 60 0
      go/gopath/src/fohow.com/apps/helper/hash.go
  57. 151 0
      go/gopath/src/fohow.com/apps/helper/idcard.go
  58. 1136 0
      go/gopath/src/fohow.com/apps/helper/ip/ip2location.go
  59. 146 0
      go/gopath/src/fohow.com/apps/helper/math.go
  60. 166 0
      go/gopath/src/fohow.com/apps/helper/mime.go
  61. 147 0
      go/gopath/src/fohow.com/apps/helper/random.go
  62. 113 0
      go/gopath/src/fohow.com/apps/helper/raw.go
  63. 221 0
      go/gopath/src/fohow.com/apps/helper/result.go
  64. 281 0
      go/gopath/src/fohow.com/apps/helper/slice.go
  65. 401 0
      go/gopath/src/fohow.com/apps/helper/str.go
  66. 161 0
      go/gopath/src/fohow.com/apps/helper/time.go
  67. 99 0
      go/gopath/src/fohow.com/apps/helper/url.go
  68. 139 0
      go/gopath/src/fohow.com/apps/helpers/benefit_helper.go
  69. 24 0
      go/gopath/src/fohow.com/apps/helpers/intro_helper.go
  70. 12 0
      go/gopath/src/fohow.com/apps/helpers/invite_helper.go
  71. 646 37
      go/gopath/src/fohow.com/apps/helpers/promotion_helper.go
  72. 101 0
      go/gopath/src/fohow.com/apps/helpers/recharge_helper.go
  73. 2 2
      go/gopath/src/fohow.com/apps/helpers/sms_helper.go
  74. 113 205
      go/gopath/src/fohow.com/apps/init.go
  75. 1 1
      go/gopath/src/fohow.com/apps/models/address_model/init.go
  76. 141 0
      go/gopath/src/fohow.com/apps/models/address_model/pick_address.go
  77. 28 0
      go/gopath/src/fohow.com/apps/models/balance_model/balance.go
  78. 0 167
      go/gopath/src/fohow.com/apps/models/base_config/base_config.go
  79. 0 7
      go/gopath/src/fohow.com/apps/models/base_config/init.go
  80. 39 19
      go/gopath/src/fohow.com/apps/models/live_model/live_broad.go
  81. 19 24
      go/gopath/src/fohow.com/apps/models/order_model/cart.go
  82. 16 1
      go/gopath/src/fohow.com/apps/models/order_model/init.go
  83. 82 38
      go/gopath/src/fohow.com/apps/models/order_model/order.go
  84. 76 20
      go/gopath/src/fohow.com/apps/models/order_model/order_detail.go
  85. 165 0
      go/gopath/src/fohow.com/apps/models/order_model/order_dt_item.go
  86. 1 9
      go/gopath/src/fohow.com/apps/models/pay_model/init.go
  87. 0 57
      go/gopath/src/fohow.com/apps/models/pay_model/pay_config.go
  88. 44 0
      go/gopath/src/fohow.com/apps/models/product_model/commend_words.go
  89. 3 0
      go/gopath/src/fohow.com/apps/models/product_model/init.go
  90. 157 36
      go/gopath/src/fohow.com/apps/models/product_model/product.go
  91. 103 0
      go/gopath/src/fohow.com/apps/models/product_model/product_commend.go
  92. 46 0
      go/gopath/src/fohow.com/apps/models/product_model/product_item.go
  93. 9 0
      go/gopath/src/fohow.com/apps/models/promotion_model/init.go
  94. 19 10
      go/gopath/src/fohow.com/apps/models/order_model/promotion.go
  95. 87 0
      go/gopath/src/fohow.com/apps/models/promotion_model/present.go
  96. 118 0
      go/gopath/src/fohow.com/apps/models/promotion_model/promotion_model.go
  97. 1 1
      go/gopath/src/fohow.com/apps/models/sms_model/sms.go
  98. 10 0
      go/gopath/src/fohow.com/apps/models/sys_config/init.go
  99. 286 0
      go/gopath/src/fohow.com/apps/models/sys_config/sys_config.go
  100. 0 0
      go/gopath/src/fohow.com/apps/models/token_model/init.go

+ 4 - 0
.gitignore

@@ -22,3 +22,7 @@ test.go
 coverage.*
 src/plugins/project-create-params.json
 .env
+
+./go/gopath/src/app.com/app.com
+./go/gopath/src/app.com/logs/*
+./go/gopath/src/app.com/nginx/ngx_dev_config

+ 12 - 5
go/gopath/src/fohow.com/apps/controllers/ad_controller/ad_controller.go

@@ -13,7 +13,7 @@ import (
 	"fohow.com/apps"
 	// "fohow.com/apps/models/activity_model"
 	"fohow.com/apps/models/ad_model"
-	// "fohow.com/apps/models/product_model"
+	"fohow.com/apps/models/user_model"
 	// "fohow.com/cache"
 )
 
@@ -41,8 +41,15 @@ func (self *AdController) GetItems() {
 	// if pCache == "false" {
 	// 	cache.Cache.Delete(k)
 	// }
-	ads := []*ad_model.AdItem{}
 
+	if adCode == "shop_apply" {
+		wxUId := self.GetCurrentWxUserIdByToken()
+		wxUser := user_model.GetWxUserById(wxUId, true)
+		if wxUser != nil && wxUser.Rank < 1 {
+			adCode = "user_apply_shop"
+		}
+	}
+	ads := []*ad_model.AdItem{}
 	_ads := ad_model.GetAdsByCode(adCode, cache)
 	if _ads != nil {
 		ads = _ads
@@ -84,7 +91,7 @@ func (self *AdController) GetItems() {
 	default:
 		self.Data["json"] = ads
 	}
-	self.ServeJSON()
+	self.ServeResultJSON()
 }
 
 //根据广告位id,获取广告图
@@ -111,7 +118,7 @@ func (self *AdController) Click() {
 	}
 	ad.ClickTimes = ad.ClickTimes + 1
 	ad.Save()
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	//if wxUser != nil {
 	clickStat := ad_model.GetClickStatByWxUId(ad.Id, wxUId)
 	if clickStat == nil {
@@ -136,7 +143,7 @@ func (self *AdController) Show() {
 	}
 	ad.ShowTimes = ad.ShowTimes + 1
 	ad.Save()
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	//if wxUser != nil {
 	showStat := ad_model.GetShowStatByWxUId(ad.Id, wxUId)
 	if showStat == nil {

+ 6 - 6
go/gopath/src/fohow.com/apps/controllers/address_controller/address_controller.go

@@ -39,7 +39,7 @@ func (self *AddressController) List() {
 		sort = "created_at"
 	}
 	//uId := self.GetCurrentUserId()
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	addresses := address_model.GetUserAddressList(wxUId, sort)
 	self.Data["json"] = addresses
 	self.ServeJSON()
@@ -48,7 +48,7 @@ func (self *AddressController) List() {
 //取默认地址
 func (self *AddressController) DefaultAddress() {
 	//uId := self.GetCurrentUserId()
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	address := address_model.GetUserDefaultAddress(wxUId)
 	self.Data["json"] = address
 	self.ServeJSON()
@@ -70,7 +70,7 @@ func (self *AddressController) CreateAddress() {
 		self.ReturnError(404, apps.ParamsRequired, "", nil)
 	}
 	uId := self.GetCurrentUserId()
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 
 	addresses := address_model.GetAddressesByWxUId(wxUId)
 	/*	if len(addresses) >= 5 {
@@ -103,7 +103,7 @@ func (self *AddressController) UpdateAddress() {
 	//if item.UserId != uId {
 	//	self.ReturnError(404, apps.NoExist, "", nil)
 	//}
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	if item.WxUserId != wxUId {
 		self.ReturnError(404, apps.NoExist, "", nil)
 	}
@@ -140,7 +140,7 @@ func (self *AddressController) DeleteAddress() {
 	//if item.UserId != uId {
 	//	self.ReturnError(403, apps.AddressNotMatch, "", nil)
 	//}
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	if item.WxUserId != wxUId {
 		self.ReturnError(404, apps.NoExist, "", nil)
 	}
@@ -163,7 +163,7 @@ func (self *AddressController) SetDefault() {
 	_id := self.Ctx.Input.Param(":id")
 	id, _ := strconv.ParseInt(_id, 10, 64)
 	//uId := self.GetCurrentUserId()
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	address := address_model.GetAddressByWxUIdAndId(wxUId, id)
 
 	if address != nil {

+ 31 - 31
go/gopath/src/fohow.com/apps/controllers/article_controller/article_controller.go

@@ -27,39 +27,39 @@ import (
 )
 
 //文章列表
-// func (self *ArticleController) GetList() {
-// 	_catId := self.Ctx.Input.Param(":cat_id")
-// 	catId, _ := strconv.ParseInt(_catId, 10, 64)
-// 	// cat_id, _ := self.GetInt64("cat_id", 12)
-// 	page, _ := self.GetInt64("page", 1)
-// 	perPage, _ := self.GetInt64("per_page", 20)
-// 	if perPage <= 0 || perPage > 100 {
-// 		perPage = 20
-// 	}
-// 	type ArticlesWithCat struct {
-// 		Articles     []*article_model.Article  `orm:"-"         json:"articles"`
-// 		ArticleCat   *article_model.ArticleCat `orm:"-"         json:"article_cat"`
-// 		ArticleCount int64                     `orm:"-"         json:"article_count"`
-// 	}
-// 	articleList := article_model.GetListByCatId(catId, page, perPage, (true && !self.IsDev()))
-// 	articleCat := article_model.GetArticleCatById(catId, true)
-// 	articleCount := article_model.GetListCountByCatId(catId)
+func (self *ArticleController) GetList() {
+	_catId := self.Ctx.Input.Param(":cat_id")
+	catId, _ := strconv.ParseInt(_catId, 10, 64)
+	// cat_id, _ := self.GetInt64("cat_id", 12)
+	page, _ := self.GetInt64("page", 1)
+	perPage, _ := self.GetInt64("per_page", 20)
+	if perPage <= 0 || perPage > 100 {
+		perPage = 20
+	}
+	type ArticlesWithCat struct {
+		Articles     []*article_model.Article  `orm:"-"         json:"articles"`
+		ArticleCat   *article_model.ArticleCat `orm:"-"         json:"article_cat"`
+		ArticleCount int64                     `orm:"-"         json:"article_count"`
+	}
+	articleList := article_model.GetListByCatId(catId, page, perPage, true && !self.IsDev())
+	articleCat := article_model.GetArticleCatById(catId, true)
+	articleCount := article_model.GetListCountByCatId(catId)
 
-// 	list := new(ArticlesWithCat)
-// 	list.Articles = articleList
-// 	list.ArticleCat = articleCat
-// 	list.ArticleCount = articleCount
-// 	self.Data["json"] = list
-// 	self.ServeJSON()
-// }
+	list := new(ArticlesWithCat)
+	list.Articles = articleList
+	list.ArticleCat = articleCat
+	list.ArticleCount = articleCount
+	self.Data["json"] = list
+	self.ServeJSON()
+}
 
 // //热门新闻
-// func (self *ArticleController) GetHotest() {
-// 	useCache, _ := self.GetBool("cache", true)
-// 	list := article_model.Hotest(useCache)
-// 	self.Data["json"] = list
-// 	self.ServeJSON()
-// }
+func (self *ArticleController) GetHotest() {
+	useCache, _ := self.GetBool("cache", true)
+	list := article_model.Hotest(useCache)
+	self.Data["json"] = list
+	self.ServeJSON()
+}
 
 //文章详情
 func (self *ArticleController) GetDetail() {
@@ -74,7 +74,7 @@ func (self *ArticleController) GetDetail() {
 		self.ReturnError(403, apps.NoExist, "", nil)
 	}
 	if self.IsWxClient() {
-		wxUId := self.GetCurrentWxUserId()
+		wxUId := self.GetCurrentWxUserIdByToken()
 		if wxUId > 0 {
 			now := time.Now().Unix()
 			k := cache.GetKey(cache.ArticleDetailOpenBenefitByAId, id, wxUId, now)

+ 35 - 12
go/gopath/src/fohow.com/apps/controllers/balance_controller/balance_controller.go

@@ -2,7 +2,10 @@ package balance_controller
 
 import (
 	"fmt"
+	"fohow.com/libs/lib_redis"
+	"fohow.com/libs/tool"
 	"github.com/astaxie/beego"
+	"strings"
 
 	// "crypto/md5"
 	// "encoding/hex"
@@ -24,7 +27,7 @@ import (
 const (
 	TAKE_CASH_AMOUNT_LIMIT_MIN    = 1000    //10元
 	TAKE_CASH_AMOUNT_LIMIT_MAX    = 2000000 //2w
-	WX_TAKE_CASH_AMOUNT_LIMIT_MAX = 500000  //5000元
+	WX_TAKE_CASH_AMOUNT_LIMIT_MAX = 20000   //5000元
 )
 
 //提货券和提货券余额
@@ -34,7 +37,7 @@ func (self *BalanceController) GetBalanceInfo() {
 		ShowInviteMode int64 `orm:"-" json:"show_invite_mode"` //是否群主
 	}
 	//user := self.GetCurrentUser(true)
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	wxUser := user_model.GetWxUserById(wxUId, true)
 	if wxUser == nil {
 		self.ReturnError(403, apps.UserNeedLogin, "", nil)
@@ -56,7 +59,7 @@ func (self *BalanceController) GetBalanceList() {
 	cache, _ := self.GetBool("cache", false)
 
 	//user := self.GetCurrentUser(cache)
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 
 	list := balance_model.GetBalanceListByWxUId(wxUId, page, perPage, cache)
 	count := balance_model.GetBalanceCountByWxUId(wxUId)
@@ -78,7 +81,7 @@ func (self *BalanceController) GetBalanceDetail() {
 	_id := self.Ctx.Input.Param(":id")
 	id, _ := strconv.ParseInt(_id, 10, 64)
 	//uId := self.GetCurrentUserId()
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	item := balance_model.GetBalanceById(id)
 	if item == nil {
 		self.ReturnError(403, apps.NoExist, "", nil)
@@ -124,8 +127,9 @@ func (self *BalanceController) GetCashBalanceList() {
 //现金账户信息
 func (self *BalanceController) GetCashBalanceInfo() {
 	type BalanceInfo struct {
-		Available int64 `orm:"-" json:"available"` //对应页面上可提现余额,单位分,进账+出账
-		Total     int64 `orm:"-" json:"total"`     //对应页面上累积收入,单位分,只算进账
+		Available   int64 `orm:"-" json:"available"`    //对应页面上可提现余额,单位分,进账+出账
+		Total       int64 `orm:"-" json:"total"`        //对应页面上累积收入,单位分,只算进账
+		CanTransfer bool  `orm:"-" json:"can_transfer"` //是否可转提货券
 	}
 	wxUser := self.GetCurrentWxUser(true)
 	if wxUser == nil {
@@ -136,7 +140,16 @@ func (self *BalanceController) GetCashBalanceInfo() {
 	//余额
 	info.Available = balance_model.GetCashTotalBalance(wxUser.Id)
 	info.Total = balance_model.GetCashEnterBalance(wxUser.Id)
+	info.CanTransfer = true
+	specialDepartStr := beego.AppConfig.String("SpecialDepart")
 
+	specialDeparts := strings.Split(specialDepartStr, ",")
+	departUser := fmt.Sprintf("%d", wxUser.Depart)
+	contain := tool.StringsContains(specialDeparts, departUser)
+
+	if contain >= 0 {
+		info.CanTransfer = false
+	}
 	self.Data["json"] = info
 	self.ServeJSON()
 }
@@ -160,9 +173,9 @@ func (self *BalanceController) TakeCash() {
 	}*/
 	user := self.GetCurrentUser(false)
 
-	if user.BankAccount == "" || user.AccountName == "" {
+	/*if user.BankAccount == "" || user.AccountName == "" {
 		self.ReturnError(403, []string{"notBindbank", "请完善您的银行卡信息"}, "", nil)
-	}
+	}*/
 
 	wxUser := self.GetCurrentWxUser(false)
 	todayOrderList := balance_model.GetTakeCashOrderListByWxUIdAndTime(wxUser.Id, time.Now(), false)
@@ -197,9 +210,9 @@ func (self *BalanceController) TakeCash() {
 		o.Save()
 	}
 	//提现成功加入提现处理队列
-	//cashKey := lib_redis.GetAutoTakeCashList()
-	//takeId := fmt.Sprintf("%d", o.Id)
-	//lib_redis.ThrowInRedisList(cashKey, takeId)
+	cashKey := lib_redis.GetAutoTakeCashList()
+	takeId := fmt.Sprintf("%d", o.Id)
+	lib_redis.ThrowInRedisList(cashKey, takeId)
 
 	self.Data["json"] = o
 	self.ServeJSON()
@@ -234,7 +247,7 @@ func (self *BalanceController) GetTakeCashOrders() {
 	cache, _ := self.GetBool("cache", false)
 
 	//user := self.GetCurrentUser(cache)
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 
 	list := balance_model.GetTakeCashOrderListByWxUId(wxUId, page, perPage, cache)
 	listCount := balance_model.GetTakeCashOrderCountByWxUId(wxUId, cache)
@@ -298,6 +311,16 @@ func (self *BalanceController) TransferToBalance() {
 		self.ReturnError(403, apps.TakeCashAmountInvalid, "", nil)
 	}
 
+	specialDepartStr := beego.AppConfig.String("SpecialDepart")
+	specialDeparts := strings.Split(specialDepartStr, ",")
+	departUser := fmt.Sprintf("%d", wxUser.Depart)
+	contain := tool.StringsContains(specialDeparts, departUser)
+
+	//三部会员禁止转提货券
+	if contain >= 0 {
+		self.ReturnError(403, apps.NoExist, "", nil)
+	}
+
 	canExtract := balance_model.GetCashTotalBalance(wxUser.Id)
 
 	//余额不足

+ 5 - 5
go/gopath/src/fohow.com/apps/controllers/cent_controller/cent_controller.go

@@ -45,7 +45,7 @@ func (self *CentController) GetCentInfo() {
 		Total int64 `orm:"-" json:"total"` //余额,单位分
 	}
 	//user := self.GetCurrentUser(true)
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	//wxUId := int64(1781)
 	wxUser := user_model.GetWxUserById(wxUId, true)
 	if wxUser == nil {
@@ -67,7 +67,7 @@ func (self *CentController) GetCentList() {
 	cache, _ := self.GetBool("cache", false)
 
 	//user := self.GetCurrentUser(cache)
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	//wxUId := int64(1781)
 	list := cent_model.GetCentBalanceListByWxUId(wxUId, page, perPage, cache)
 	count := cent_model.GetCentBalanceCountByWxUId(wxUId)
@@ -89,7 +89,7 @@ func (self *CentController) GetCentDetail() {
 	_id := self.Ctx.Input.Param(":id")
 	id, _ := strconv.ParseInt(_id, 10, 64)
 	//uId := self.GetCurrentUserId()
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	//wxUId := int64(1781)
 	item := cent_model.GetCentById(id)
 	if item == nil {
@@ -106,7 +106,7 @@ func (self *CentController) GetCentDetail() {
 
 //获得七日签到任务状态
 func (self *CentController) GetSignStatus() {
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	wxUser := user_model.GetWxUserById(wxUId, true)
 	if wxUser == nil {
 		self.ReturnError(403, apps.UserNeedLogin, "", nil)
@@ -195,7 +195,7 @@ func (self *CentController) GetSignStatus() {
 // 每日签到,领取积分
 func (self *CentController) SignEveryday() {
 
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	wxUser := user_model.GetWxUserById(wxUId, true)
 	if wxUser == nil {
 		self.ReturnError(403, apps.UserNeedLogin, "", nil)

+ 1 - 1
go/gopath/src/fohow.com/apps/controllers/cron_controller/init.go

@@ -66,7 +66,7 @@ func exec(name string) {
 	switch name {
 	case "take_cash": //提现
 		//takeCash()
-		//autoTakeCash() //redis队列处理
+		autoTakeCash() //redis队列处理
 	case "orderReceiveAutomatically": //已发货订单7天自动收货
 		go OrderReceiveAutomatically()
 	case "updateUserNicknameAndHead": //修复数据-只执行一次

+ 7 - 5
go/gopath/src/fohow.com/apps/controllers/cron_controller/sync_balance.go

@@ -3,7 +3,7 @@ package cron_controller
 import (
 	"crypto/md5"
 	"fmt"
-	"fohow.com/apps/models/pay_model"
+	"fohow.com/apps/models/sys_config"
 	"fohow.com/libs/lib_redis"
 	"github.com/go-redis/redis"
 	"io"
@@ -61,7 +61,7 @@ func takeCash() {
 		} else {
 			check_state = wx_mp.PAY_NO_CHECK
 		}*/
-		payCode := pay_model.GetPayConfigByDepart(wxUser.Depart, true)
+		payCode := sys_config.GetPayConfigByDepart(wxUser.Depart, true)
 		ret := wx_mp.Transfers(wxUser.Openid, item.Count, item.OrderId, check_state, user.RealName, payCode, "提现")
 		if ret["result_code"] == wx_mp.PAY_SUCCESS {
 			item.State = 1
@@ -121,9 +121,13 @@ func autoTakeCash() {
 			beego.BeeLogger.Error("Take cash User[%d] is not exist", wxUser.UserId)
 			continue
 		}
+
+		//提现成功,剔除队列
+		lib_redis.ThrowOutRedisList(cashKey, takeId)
+
 		var check_state string
 		check_state = wx_mp.PAY_NO_CHECK
-		payCode := pay_model.GetPayConfigByDepart(wxUser.Depart, true)
+		payCode := sys_config.GetPayConfigByDepart(wxUser.Depart, true)
 
 		ret := wx_mp.Transfers(wxUser.Openid, cashRecord.Count, cashRecord.OrderId, check_state, user.RealName, payCode, "提现")
 		if ret["result_code"] == wx_mp.PAY_SUCCESS {
@@ -133,8 +137,6 @@ func autoTakeCash() {
 			cashRecord.Remark = "提现已打款"
 			cashRecord.PaiedAt = time.Now().Unix()
 			cashRecord.Save()
-			//提现成功,剔除队列
-			lib_redis.ThrowOutRedisList(cashKey, takeId)
 		} else {
 			cashRecord.State = 2
 			cashRecord.Remark = ret["err_code_des"]

+ 11 - 1
go/gopath/src/fohow.com/apps/controllers/cron_controller/update_sold_count.go

@@ -26,11 +26,21 @@ func updateSoldCount() {
 	beego.BeeLogger.Warn("updateSoldCount.len(list):%d", len(list))
 	for _, product := range list {
 		//统计商品总销量
-		soldCount := order_model.GetSoldCountByPId(product.Id, false)
+		soldCount := order_model.GetDetailSoldCountByPId(product.Id, false)
 		product.SaleNums = soldCount
 		beego.BeeLogger.Warn("updateSoldCount.productId:%d", product.Id)
 		beego.BeeLogger.Warn("updateSoldCount.SaleNums:%d", soldCount)
 		product.Save()
+		/*	//套装商品拆分更新销量
+			if product.Package {
+				package_list := product_model.GetPackageList(product.Id, true)
+				for _, item := range package_list {
+					item_pd := product_model.GetProductById(item.ItemId, true)
+					count := item.Nums * soldCount
+					item_pd.SaleNums += count
+					item_pd.Save()
+				}
+			}*/
 	}
 
 }

+ 9 - 17
go/gopath/src/fohow.com/apps/controllers/customer_service_controller/customer_service_controller.go

@@ -2,6 +2,7 @@ package customer_service_controller
 
 import (
 	"fohow.com/apps"
+	"fohow.com/apps/models/ad_model"
 	"github.com/astaxie/beego/context"
 	//"fohow.com/libs/kefu"
 	//"github.com/astaxie/beego"
@@ -24,23 +25,14 @@ func (self *CustomerServiceController) Init(ctx *context.Context, controllerName
 }
 
 func (self *CustomerServiceController) GetRabbitKfImgByUnionid() {
-
-	// 2018/09/15这里先返回小兔二维码,不查询第五创
-	qrCodeImgUrl := "https://fohow.oss-cn-shenzhen.aliyuncs.com/xcx/kf/kfewm.jpg"
-	//qrCodeImgUrl := "http://rabbit-mall.oss-cn-shenzhen.aliyuncs.com/xcx/kf/xcx_xiaola.jpg"
-	//wxUser := self.GetCurrentWxUser(true)
-	//if wxUser != nil{
-	//	result := kefu.GetKfQrcodeImgFromD5c(wxUser.Unionid)
-	//
-	//	if result!= nil && result.CheckCode == "0000"{
-	//
-	//		qrCodeImgUrl = result.ImgPath
-	//	}
-	//}
-	//
-	//if wxUser == nil{
-	//	beego.BeeLogger.Warn("wxUser not Login, cannot get QrcodeImgFromD5c!")
-	//}
+	adCode := "kf_qrcode"
+	qrCodeImgUrl := ""
+	_ads := ad_model.GetAdsByCode(adCode, true)
+	if _ads != nil {
+		qrCodeImgUrl = _ads[0].Img
+	} else {
+		qrCodeImgUrl = "https://fohow.oss-cn-shenzhen.aliyuncs.com/xcx/kf/kfewm.jpg"
+	}
 	self.Data["json"] = qrCodeImgUrl
 	self.ServeJSON()
 }

+ 10 - 3
go/gopath/src/fohow.com/apps/controllers/live_controller/live_controller.go

@@ -5,6 +5,7 @@ import (
 	// "strings"
 
 	"fohow.com/apps/models/live_model"
+	"fohow.com/apps/models/user_model"
 	"github.com/astaxie/beego/context"
 	"time"
 
@@ -42,7 +43,6 @@ func (self *LiveController) Latest() {
 	page, _ := self.GetInt64("page")
 	perPage, _ := self.GetInt64("per_page")
 	cache, _ := self.GetBool("cache", false)
-	ptype := self.GetString("ptype")
 
 	if page <= 0 {
 		page = 1
@@ -56,8 +56,15 @@ func (self *LiveController) Latest() {
 		ListCount int64                   `json:"list_count"`
 	}
 
-	lives := live_model.GetLatest(page, perPage, recommend, cache)
-	count := live_model.GetLatestCount(recommend, ptype, cache)
+	wxUId := self.GetCurrentWxUserIdByToken()
+
+	wxUser := user_model.GetWxUserById(wxUId, false)
+	if wxUser == nil {
+		self.ReturnError(403, apps.NoExist, "", nil)
+	}
+
+	lives := live_model.GetLatest(page, perPage, recommend, wxUser.Depart, wxUser.Rank, cache)
+	count := live_model.GetLatestCount(recommend, wxUser.Depart, wxUser.Rank)
 	timeNowUnix := time.Now().Unix()
 	for _, live := range lives {
 		//beego.BeeLogger.Warn("live_timeNowUnix: %d", timeNowUnix)

+ 14 - 11
go/gopath/src/fohow.com/apps/controllers/mp_controller/mp_controller.go

@@ -41,7 +41,7 @@ func (self *MpController) Handler() {
 	}
 	gzh := wx_gongzhonghao_model.GetGZHByAppId(mpappid, false)
 
-	//beego.BeeLogger.Warn("Request.Method:%s", self.Ctx.Request.Method)
+	beego.BeeLogger.Warn("Request.Method:%s", self.Ctx.Request.Method)
 	//在开发者首次提交验证申请时,微信服务器将发送GET请求到填写的URL上,
 	//并且带上四个参数(signature、timestamp、nonce、echostr),
 	//开发者通过对签名(即signature)的效验,来判断此条消息的真实性。
@@ -58,6 +58,9 @@ func (self *MpController) Handler() {
 		// sign := util.MsgSign(gzh.Token, t, n, encryptedMsg)
 		//明文模式
 		sign := util.Sign(gzh.Token, t, n)
+
+		beego.BeeLogger.Warn("Request.sign:%s", sign)
+
 		if sign != s {
 			text := fmt.Sprintf("check signature fail,sign=[%s],params[sign]=[%s]", sign, s)
 			self.Ctx.WriteString(text)
@@ -103,16 +106,16 @@ func (self *MpController) Config() {
 
 //微信JS-SDK配置注入
 func (self *MpController) GetAccessToken() {
-	// type Ret struct {
-	// 	Token string `json:"token"`
-	// }
-	// appId := self.GetString("a")
-	// appSecret := self.GetString("s")
-	// token := wx_mp.GetAccessToken(appId, appSecret)
-	// beego.BeeLogger.Warn("rails get token(%s, %s)=%s", appId, appSecret, token)
-	// ret := &Ret{Token: token}
-	// self.Data["json"] = ret
-	// self.ServeJSON()
+	type Ret struct {
+		Token string `json:"token"`
+	}
+	appId := self.GetString("a")
+	appSecret := self.GetString("s")
+	token := wx_mp.GetAccessToken(appId, appSecret)
+	beego.BeeLogger.Warn("rails get token(%s, %s)=%s", appId, appSecret, token)
+	ret := &Ret{Token: token}
+	self.Data["json"] = ret
+	self.ServeJSON()
 }
 
 //是否关注公众号

+ 39 - 51
go/gopath/src/fohow.com/apps/controllers/order_controller/cart_controller.go

@@ -9,7 +9,6 @@ import (
 	"github.com/astaxie/beego"
 	"strconv"
 	"strings"
-	"time"
 )
 
 //加入购物车
@@ -21,16 +20,18 @@ func (self *OrderController) CreateCart() {
 	if count <= 0 {
 		self.ReturnError(403, apps.ParamsError, "", nil)
 	}
-	product := product_model.GetProductById(pId, false)
+	product := product_model.GetProductById(pId, true)
 	if product == nil {
 		self.ReturnError(403, apps.NoExist, "", nil)
 	}
 	if count > product.Count {
 		self.ReturnError(403, apps.ProductStockNotEnough, "", nil)
 	}
-	uId := self.GetCurrentUserId()
-	wxUId := self.GetCurrentWxUserId()
-
+	wxUId := self.GetCurrentWxUserIdByToken()
+	//店铺专区商品区分
+	if product.Ptype != product_model.TYPE_DIRECT_SALE {
+		self.ReturnError(403, apps.ProductErrorType, "", nil)
+	}
 	//限新逻辑: 微信支付完成购买过商品的用户
 	if product.IsOnlyNew {
 		paiedOrder := order_model.GetPaiedOrderByWxUIdAndPayWayLimitOne(wxUId, order_model.PAY_WAY_WEIXIN, false)
@@ -39,12 +40,12 @@ func (self *OrderController) CreateCart() {
 		}
 	}
 	//秒杀商品不允许加入购物车
-	if product.SeckilShowPrice > 0 {
-		now := time.Now()
-		if now.Unix() >= product.SeckillStart.Unix() && now.Unix() <= product.SeckillEnd.Unix() {
-			self.ReturnError(403, apps.SeckillNotAllow, "", nil)
-		}
-	}
+	//if product.SeckilShowPrice > 0 {
+	//	now := time.Now()
+	//	if now.Unix() >= product.SeckillStart.Unix() && now.Unix() <= product.SeckillEnd.Unix() {
+	//		self.ReturnError(403, apps.SeckillNotAllow, "", nil)
+	//	}
+	//}
 
 	//限购逻辑
 	if product.PurchaseLimitCount > 0 {
@@ -58,7 +59,9 @@ func (self *OrderController) CreateCart() {
 			self.ReturnError(403, []string{apps.SingleOverLimitCount[0], fmt.Sprintf("该商品单次限购%d件", product.SinglePurchLimit)}, "", nil)
 		}
 	}
-	cart := new(order_model.Cart).Create(wxUId, uId, product.Id, count)
+
+	wxUser := self.GetCurrentWxUser(false)
+	cart := new(order_model.Cart).Create(wxUId, wxUser.Id, product.Id, count)
 	result := false
 	if cart != nil {
 		result = true
@@ -85,7 +88,7 @@ func (self *OrderController) ChangeItemNums() {
 	if cartItem == nil {
 		self.ReturnError(403, apps.NoExist, "", nil)
 	}
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	if cartItem.WxUserId != wxUId {
 		self.ReturnError(403, apps.AccountError, "", nil)
 	}
@@ -116,7 +119,7 @@ func (self *OrderController) ChangeItemState() {
 	if cartItem == nil {
 		self.ReturnError(403, apps.NoExist, "", nil)
 	}
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	if cartItem.WxUserId != wxUId {
 		self.ReturnError(403, apps.AccountError, "", nil)
 	}
@@ -139,7 +142,7 @@ func (self *OrderController) ChangeItemState() {
 func (self *OrderController) MultChangeItemState() {
 
 	//uId := self.GetCurrentUserId()
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	ids := self.GetString("ids")
 	nums := self.GetString("nums")
 
@@ -188,7 +191,7 @@ func (self *OrderController) ChangeAllState() {
 
 	state, _ := self.GetBool("state", false)
 	//uId := self.GetCurrentUserId()
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	list := order_model.GetCartItemsByWxUserId(wxUId)
 	for _, item := range list {
 		cartItem := order_model.GetCartById(item.Id)
@@ -213,8 +216,8 @@ func (self *OrderController) ChangeAllState() {
 
 //获取会员购物车信息
 func (self *OrderController) GetCartList() {
-	cache, _ := self.GetBool("cache", false)
-	wxUserId := self.GetCurrentWxUserId()
+	cache, _ := self.GetBool("cache", true)
+	wxUserId := self.GetCurrentWxUserIdByToken()
 	list := order_model.GetCartItemsByWxUserId(wxUserId)
 
 	for _, item := range list {
@@ -240,10 +243,25 @@ func (self *OrderController) GetCartList() {
 				item.ColorName = productColor.Name
 			}
 		}
+		item.Package = product.Package
+		if product.Package {
+			packageList := product_model.GetPackageList(product.Id, true)
+			for _, package_one := range packageList {
+				cart_package := &order_model.ProductItem{}
+				cart_package.ProductId = package_one.ProductId
+				cart_package.ItemId = package_one.ItemId
+				cart_package.ItemTitle = package_one.ItemTitle
+				cart_package.Nums = package_one.Nums
+				item.PackageList = append(item.PackageList, cart_package)
+			}
+		}
+		item.SeckillStartAt = product.SeckillStart.Unix()
+		item.SeckillEndAt = product.SeckillEnd.Unix()
+		item.SeckilShowPrice = product.SeckilShowPrice
 		item.Cover = product_model.GetCoverByPId(item.ProductId, cache)
 		item.OriginalPrice = product.Price
 		item.ProductName = product.Name
-
+		item.Pv = product.Pv
 	}
 	count := int64(0)
 	total := int64(0)
@@ -270,36 +288,6 @@ func ClearProductCart(userId, productId int64) {
 	}
 }
 
-//获取会员已选购购物车信息
-func (self *OrderController) GetCartBuyList() {
-	cache, _ := self.GetBool("cache", false)
-	uId := self.GetCurrentUserId()
-	isBuy := true
-	list := order_model.GetCartItemsByUserIdAndBuy(uId, isBuy)
-	count := int64(0)
-	total := int64(0)
-	for _, item := range list {
-		count += item.Count
-		product := product_model.GetProductById(item.ProductId, cache)
-		wxUser := user_model.GetWxUserById(item.WxUserId, cache)
-		if wxUser != nil {
-			wxUser.Head = user_model.GetFullImgUrl(wxUser.Head)
-		}
-		item.Cover = product_model.GetCoverByPId(item.ProductId, cache)
-		item.OriginalPrice = product.Price
-		item.ProductName = product.Name
-		total += item.Count * product.Price
-	}
-
-	type Ret struct {
-		List  []*order_model.Cart `json:"list"`
-		Count int64               `json:"count"`
-		Total int64               `json:"total"`
-	}
-	self.Data["json"] = &Ret{Total: total, Count: count, List: list}
-	self.ServeJSON()
-}
-
 //删除购物车产品项
 func (self *OrderController) DeleteItem() {
 	_cid := self.Ctx.Input.Param(":id")
@@ -311,7 +299,7 @@ func (self *OrderController) DeleteItem() {
 	if cartItem == nil {
 		self.ReturnError(403, apps.NoExist, "", nil)
 	}
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	if cartItem.WxUserId != wxUId {
 		self.ReturnError(403, apps.AccountError, "", nil)
 	}
@@ -328,7 +316,7 @@ func (self *OrderController) DeleteItem() {
 
 //批量删除购物车
 func (self *OrderController) MultChangeItemDelete() {
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	ids := self.GetString("ids")
 	s_arr := strings.Split(ids, ",")
 	for _, s_item := range s_arr {

+ 2 - 2
go/gopath/src/fohow.com/apps/controllers/order_controller/init.go

@@ -16,8 +16,8 @@ import (
 
 var (
 	//需要校验用户登录的Action
-	exceptCheckUserLoginAction   = []string{"Create", "Detail", "List", "Operate", "GetExpressNo", "MultChangeItemState", "GetCartList"}
-	exceptCheckWxUserLoginAction = []string{"GetExpressNo", "MultChangeItemState", "GetCartList"}
+	exceptCheckUserLoginAction   = []string{}
+	exceptCheckWxUserLoginAction = []string{}
 )
 
 type OrderController struct {

+ 261 - 127
go/gopath/src/fohow.com/apps/controllers/order_controller/order_controller.go

@@ -2,8 +2,8 @@ package order_controller
 
 import (
 	"fmt"
-	"fohow.com/apps/models/base_config"
 	"fohow.com/apps/models/cent_model"
+	"fohow.com/apps/models/sys_config"
 	"fohow.com/libs/lib_redis"
 	// "fmt"
 	"strconv"
@@ -14,7 +14,6 @@ import (
 	"fohow.com/apps"
 
 	"fohow.com/apps/models/balance_model"
-	"fohow.com/apps/models/merchant_model"
 	"fohow.com/apps/models/order_model"
 	"fohow.com/apps/models/product_model"
 	"fohow.com/apps/models/user_model"
@@ -30,7 +29,7 @@ var MultreateOrder sync.Mutex
 var MultShopOrder sync.Mutex
 var MultCentOrder sync.Mutex
 
-//下单
+//单品下单
 func (self *OrderController) Create() {
 	createOrder.Lock()
 	defer createOrder.Unlock()
@@ -41,22 +40,27 @@ func (self *OrderController) Create() {
 	if count <= 0 {
 		self.ReturnError(403, apps.ParamsError, "", nil)
 	}
-	product := product_model.GetProductById(pId, false)
+	product := product_model.GetProductById(pId, true)
 	if product == nil {
 		self.ReturnError(403, apps.NoExist, "", nil)
 	}
-	uId := self.GetCurrentUserId()
-	wxUId := self.GetCurrentWxUserId()
+
+	wxUId := self.GetCurrentWxUserIdByToken()
 	//user := self.GetCurrentUser(true)
 	//黑名单用户返回账户异常
 	//if user.IsBlackUser == 1 {
 	//	self.ReturnError(403, apps.AccountError, "", nil)
 	//}
+	//店铺专区下单
+	if product.Ptype != product_model.TYPE_DIRECT_SALE {
+		self.ReturnError(403, apps.ProductErrorType, "", nil)
+	}
 	if product.SinglePurchLimit > 0 {
 		if product.SinglePurchLimit < count {
 			self.ReturnError(403, []string{apps.SingleOverLimitCount[0], fmt.Sprintf("该商品单次限购%d件", product.SinglePurchLimit)}, "", nil)
 		}
 	}
+
 	if product.PurchaseLimitCount > 0 {
 		if product.PurchaseLimitCount < count {
 			self.ReturnError(403, []string{apps.OverLimitCount[0], fmt.Sprintf("该商品限购%d件", product.PurchaseLimitCount)}, "", nil)
@@ -78,6 +82,7 @@ func (self *OrderController) Create() {
 	if wxUser == nil {
 		self.ReturnError(403, apps.NoExist, "", nil)
 	}
+	uId := wxUser.UserId
 	orderType := order_model.ORDER_TYPE_NORMAL
 	//秒杀逻辑: 判断是否处于秒杀时间段内
 	if product.SeckilShowPrice > 0 {
@@ -109,8 +114,8 @@ func (self *OrderController) Create() {
 	if wxUId == 76 {
 		totalPrice = 1
 	}
-	freight := base_config.GetFreight()
-	if totalPrice >= base_config.GetOrderLimit() {
+	freight := sys_config.GetFreight()
+	if totalPrice >= sys_config.GetOrderLimit() {
 		freight = int64(0)
 	}
 
@@ -119,10 +124,17 @@ func (self *OrderController) Create() {
 	if order == nil {
 		self.ReturnError(403, apps.CreateOrderFail, "", nil)
 	}
+	order.Pv = product.Pv * count
+	specialPromotion, specialstr := sys_config.GetSpetialPromotion()
+	if specialPromotion {
+		order.Promotions = specialstr
+	}
+
 	order.Save()
 	//创建订单明细
-	go new(order_model.OrderDetail).Create(order.OrderId, order.Id, product.Id, product.Price, product.RoboBalancePrice, product.Name,
-		sizeName, colorName, count)
+	new(order_model.OrderDetail).Create(order.OrderId, order.Id, product.Id, product.RelateProductId, product.Price, product.RoboBalancePrice, product.Name,
+		sizeName, colorName, count, wxUser.Depart)
+
 	//未支付订单加入取消队列
 	cancelKey := lib_redis.GetOrderCancelList()
 	lib_redis.ThrowInRedisList(cancelKey, order.OrderId)
@@ -157,8 +169,7 @@ func (self *OrderController) GetExpressNo() {
 func (self *OrderController) MultipleCreate() {
 	MultreateOrder.Lock()
 	defer MultreateOrder.Unlock()
-	uId := self.GetCurrentUserId()
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	ids := self.GetString("ids")
 	nums := self.GetString("nums")
 	if len(nums) <= 0 || len(ids) <= 0 {
@@ -169,6 +180,7 @@ func (self *OrderController) MultipleCreate() {
 		self.ReturnError(403, apps.NoExist, "", nil)
 	}
 	totalPrice := int64(0)
+	totalPv := int64(0)
 	c_arr := strings.Split(ids, ",")
 	c_nums := strings.Split(nums, ",")
 
@@ -184,10 +196,14 @@ func (self *OrderController) MultipleCreate() {
 		if cartItem.WxUserId != wxUId {
 			//self.ReturnError(403, apps.AccountError, "", nil)
 		}
-		product := product_model.GetProductById(cartItem.ProductId, false)
+		product := product_model.GetProductById(cartItem.ProductId, true)
 		if product == nil {
 			self.ReturnError(403, apps.NoExist, "", nil)
 		}
+		//专区下单判断
+		if product.Ptype != product_model.TYPE_DIRECT_SALE {
+			self.ReturnError(403, apps.ProductErrorType, "", nil)
+		}
 		if product.SinglePurchLimit > 0 {
 			if product.SinglePurchLimit < cNums {
 				self.ReturnError(403, []string{apps.SingleOverLimitCount[0], fmt.Sprintf("%s商品单次限购%d件", product.Name, product.SinglePurchLimit)}, "", nil)
@@ -212,7 +228,7 @@ func (self *OrderController) MultipleCreate() {
 	}
 
 	//创建订单
-	order := new(order_model.Order).CreateNew(wxUId, uId,
+	order := new(order_model.Order).CreateNew(wxUId, wxUser.UserId,
 		totalPrice, int64(0), order_model.ORDER_TYPE_NORMAL, wxUser.Depart, order_model.SOURCE_XCX)
 	if order == nil {
 		self.ReturnError(403, apps.CreateOrderFail, "", nil)
@@ -229,22 +245,31 @@ func (self *OrderController) MultipleCreate() {
 		if cartItem.WxUserId != wxUId {
 			//self.ReturnError(403, apps.AccountError, "", nil)
 		}
-		product := product_model.GetProductById(cartItem.ProductId, false)
+		product := product_model.GetProductById(cartItem.ProductId, true)
 		if product == nil {
 			self.ReturnError(403, apps.NoExist, "", nil)
 		}
-		//创建订单明细
+		//统计订单总价及总pv
 		totalPrice += product.Price * cNums
-		CreateOrderDetails(product, order, cNums)
+		totalPv += product.Pv * cNums
+
+		//创建订单明细
+		CreateOrderDetails(product, order, cNums, wxUser.Depart)
 	}
-	freight := base_config.GetFreight()
-	if totalPrice >= base_config.GetOrderLimit() {
+	freight := sys_config.GetFreight()
+	if totalPrice >= sys_config.GetOrderLimit() {
 		freight = int64(0)
 	}
+	order.Pv = totalPv
 	order.TotalPrice = totalPrice
 	order.Freight = freight
+	specialPromotion, specialstr := sys_config.GetSpetialPromotion()
+	if specialPromotion {
+		order.Promotions = specialstr
+	}
 	order.Save()
-	go ClearCart(order.UserId, order.OrderId)
+	//购物册清理
+	go ClearCart(order.WxUserId, order.OrderId)
 	//未支付订单加入取消队列
 	cancelKey := lib_redis.GetOrderCancelList()
 	lib_redis.ThrowInRedisList(cancelKey, order.OrderId)
@@ -259,18 +284,19 @@ func (self *OrderController) MultipleCreate() {
 func (self *OrderController) MultShopCreate() {
 	MultShopOrder.Lock()
 	defer MultShopOrder.Unlock()
-	uId := self.GetCurrentUserId()
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	ids := self.GetString("ids")
 	nums := self.GetString("nums")
 	if len(nums) <= 0 || len(ids) <= 0 {
 		self.ReturnError(403, apps.NoCart, "", nil)
 	}
 	//非群主店铺专区不能下单
-	wxUser := user_model.GetWxUserByUserId(uId, false)
-	if wxUser.Rank != int64(2) {
+	wxUser := self.GetCurrentWxUser(true)
+	uId := wxUser.UserId
+	if wxUser.Rank < int64(2) {
 		self.ReturnError(403, apps.OtherSNotAllow, "", nil)
 	}
+
 	totalPrice := int64(0)
 	//创建订单
 	order := new(order_model.Order).CreateNew(wxUId, uId,
@@ -284,13 +310,16 @@ func (self *OrderController) MultShopCreate() {
 		pId, _ := strconv.ParseInt(s_item, 10, 64)
 		cNums := int64(1)
 		cNums, _ = strconv.ParseInt(c_nums[key], 10, 64)
-		product := product_model.GetProductById(pId, false)
+		product := product_model.GetProductById(pId, true)
 		if product == nil {
 			self.ReturnError(403, apps.NoExist, "", nil)
 		}
-		if product.Ptype != product_model.SHOP_SALE {
+		//专区商品改为判断主商品
+		relatePrd := product_model.GetProductById(product.RelateProductId, true)
+		if relatePrd != nil && relatePrd.Ptype != product_model.SHOP_SALE {
 			self.ReturnError(403, apps.NoShopSale, "", nil)
 		}
+
 		if product.SinglePurchLimit > 0 {
 			if product.SinglePurchLimit < cNums {
 				self.ReturnError(403, []string{apps.SingleOverLimitCount[0], fmt.Sprintf("%s商品单次限购%d件", product.Name, product.SinglePurchLimit)}, "", nil)
@@ -315,10 +344,10 @@ func (self *OrderController) MultShopCreate() {
 		}
 		//创建订单明细
 		totalPrice += product.Price * cNums
-		CreateOrderDetails(product, order, cNums)
+		CreateOrderDetails(product, order, cNums, wxUser.Depart)
 	}
-	freight := base_config.GetFreight()
-	if totalPrice >= base_config.GetOrderLimit() {
+	freight := sys_config.GetFreight()
+	if totalPrice >= sys_config.GetOrderLimit() {
 		freight = int64(0)
 	}
 	order.TotalPrice = totalPrice
@@ -339,14 +368,13 @@ func (self *OrderController) MultShopCreate() {
 func (self *OrderController) MultCentCreate() {
 	MultCentOrder.Lock()
 	defer MultCentOrder.Unlock()
-	uId := self.GetCurrentUserId()
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	ids := self.GetString("ids")
 	nums := self.GetString("nums")
 	if len(nums) <= 0 || len(ids) <= 0 {
 		self.ReturnError(403, apps.NoCart, "", nil)
 	}
-	wxUser := user_model.GetWxUserByUserId(uId, false)
+	wxUser := user_model.GetWxUserById(wxUId, false)
 	if wxUser == nil {
 		self.ReturnError(403, apps.NoExist, "", nil)
 	}
@@ -362,7 +390,10 @@ func (self *OrderController) MultCentCreate() {
 		if product == nil {
 			self.ReturnError(403, apps.NoExist, "", nil)
 		}
-		if product.Ptype != product_model.CENT_SALE {
+
+		//专区商品改为判断主商品
+		relatePrd := product_model.GetProductById(product.RelateProductId, true)
+		if relatePrd != nil && relatePrd.Ptype != product_model.CENT_SALE {
 			self.ReturnError(403, apps.NoShopSale, "", nil)
 		}
 		if product.SinglePurchLimit > 0 {
@@ -392,9 +423,9 @@ func (self *OrderController) MultCentCreate() {
 	}
 
 	//订单合法性判断
-	freight := base_config.GetFreight()
-	if totalPrice < base_config.GetOrderLimit() {
-		self.ReturnError(403, []string{apps.OrderNotEnough[0], fmt.Sprintf("订单金额不能低于%d积分", base_config.GetOrderLimit()/int64(100))}, "", nil)
+	freight := sys_config.GetFreight()
+	if totalPrice < sys_config.GetOrderLimit() {
+		self.ReturnError(403, []string{apps.OrderNotEnough[0], fmt.Sprintf("订单金额不能低于%d积分", sys_config.GetOrderLimit()/int64(100))}, "", nil)
 	} else {
 		freight = int64(0)
 	}
@@ -405,8 +436,7 @@ func (self *OrderController) MultCentCreate() {
 	}
 
 	//创建订单
-	order := new(order_model.Order).CreateNew(wxUId, uId,
-		totalPrice, int64(0), order_model.ORDER_TYPE_CENT, wxUser.Depart, order_model.SOURCE_XCX)
+	order := new(order_model.Order).CreateNew(wxUId, wxUser.UserId, totalPrice, int64(0), order_model.ORDER_TYPE_CENT, wxUser.Depart, order_model.SOURCE_XCX)
 	if order == nil {
 		self.ReturnError(403, apps.CreateOrderFail, "", nil)
 	}
@@ -419,7 +449,7 @@ func (self *OrderController) MultCentCreate() {
 		if product == nil {
 			self.ReturnError(403, apps.NoExist, "", nil)
 		}
-		CreateOrderDetails(product, order, cNums)
+		CreateOrderDetails(product, order, cNums, wxUser.Depart)
 	}
 	order.TotalPrice = totalPrice
 	order.Freight = freight
@@ -435,14 +465,26 @@ func (self *OrderController) MultCentCreate() {
 	self.ServeJSON()
 }
 
-func ClearCart(userId int64, orderId string) {
+func ClearCart(wxUserId int64, orderId string) {
 	orderDetails := order_model.GetAllDetailsOrderId(orderId, false)
 	for _, item := range orderDetails {
-		cartItem := order_model.GetCartByUidAndPid(userId, item.ProductId)
+		cartItem := order_model.GetCartByWxUidAndPid(wxUserId, item.ProductId)
 		if cartItem != nil {
 			cartItem.Delete()
 		}
 	}
+	//清除过期的秒杀商品项
+	list := order_model.GetCartItemsByWxUserId(wxUserId)
+	for _, item := range list {
+		product := product_model.GetProductById(item.ProductId, true)
+		if product != nil {
+			if product.SeckilShowPrice > 0 && product.SeckillEnd.Unix() < time.Now().Unix() {
+				cartItem := order_model.GetCartByWxUidAndPid(wxUserId, item.ProductId)
+				cartItem.Delete()
+			}
+		}
+
+	}
 }
 
 //获取用户订单详情
@@ -456,35 +498,23 @@ func (self *OrderController) Detail() {
 		beego.BeeLogger.Error("order not exist id=[%s]", oId)
 		self.ReturnError(404, apps.OrderNotExist, "", nil)
 	}
-	orderList := order_model.GetAllDetailsOrderId(o.OrderId, false)
-	for _, item := range orderList {
+	orderDtList := order_model.GetAllDetailsOrderId(o.OrderId, false)
+	for _, item := range orderDtList {
 		product := product_model.GetProductById(item.ProductId, cache)
 		if product == nil {
 			self.ReturnError(403, apps.ProductNotExist, "", nil)
 		}
-		//获取商品属性详情
-		product.SizeName = item.SizeName
-		product.ColorName = item.ColorName
-		product.OrderCount = item.Count
-		product.IsZeng = item.Send
-		o.Count += item.Count
-		if product.SeckilShowPrice > 0 {
-			now := time.Now()
-			product.SeckillStartAt = product.SeckillStart.Unix()
-			product.SeckillEndAt = product.SeckillEnd.Unix()
-			if product.SeckillStart.Unix() > now.Unix() {
-				product.SeckillState = product_model.SECKILL_PREPARING_STATE
-				product.SeckillStateCn = product_model.SECKILL_PREPARING_STATE_CN
-			} else if product.SeckillStart.Unix() <= now.Unix() && now.Unix() < product.SeckillEnd.Unix() {
-				product.IsUnderSeckill = true
-				product.SeckillState = product_model.SECKILL_UNDER_STATE
-				product.SeckillStateCn = product_model.SECKILL_UNDER_STATE_CN
-			} else {
-				product.SeckillState = product_model.SECKILL_END_STATE
-				product.SeckillStateCn = product_model.SECKILL_END_STATE_CN
-			}
+
+		if item.Commend || o.Status != order_model.STATUS_COMPLETE {
+			item.Commend = true
 		}
-		o.ProductList = append(o.ProductList, product)
+		item.Package = product.Package
+		if product.Package {
+			item.PacakageList = order_model.GetOrderDetailPackages(item.Id, item.Count, true)
+		}
+		o.Count += item.Count
+		item.Cover = product.Cover
+		o.ProductList = append(o.ProductList, item)
 	}
 	wxUser := self.GetCurrentWxUser(cache)
 	if wxUser == nil {
@@ -498,6 +528,7 @@ func (self *OrderController) Detail() {
 	}
 
 	o.StatusCn = order_model.STATUS_CN_TEXT[o.Status]
+	o.ShutWechat = sys_config.GetShutWechatPromotion()
 	o.CTime = o.CreatedAt.Unix()
 	o.DTime = o.DispatchTime.Unix()
 	if o.DTime < 0 {
@@ -505,6 +536,60 @@ func (self *OrderController) Detail() {
 	}
 	o.WxUser = wxUser
 	self.Data["json"] = o
+	self.ServeResultJSON()
+}
+
+//获取用户待评价订单列表
+func (self *OrderController) WaitCommendList() {
+
+	status := self.GetString("status")
+	page, _ := self.GetInt("page")
+	//perPage, _ := self.GetInt("per_page")
+	if page <= 0 {
+		page = 1
+	}
+	perPage := 100
+	cache, _ := self.GetBool("cache", false)
+	//uId := self.GetCurrentUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
+	orders := order_model.GetUserOrders(wxUId, status, page, perPage)
+	count := order_model.GetUserOrdersCount(wxUId, status)
+	var latestOrders []*order_model.Order
+	for _, item := range orders {
+		commend := false
+		orderDtList := order_model.GetAllDetailsOrderId(item.OrderId, false)
+		for _, orderDtItem := range orderDtList {
+			product := product_model.GetProductById(orderDtItem.ProductId, cache)
+			if product == nil {
+				continue
+			}
+			orderDtItem.Package = product.Package
+			item.Count += orderDtItem.Count
+			if orderDtItem.Commend || item.Status != order_model.STATUS_COMPLETE {
+				orderDtItem.Commend = true
+			}
+			if !orderDtItem.Commend {
+				commend = true
+			}
+			if product.Package {
+				orderDtItem.PacakageList = order_model.GetOrderDetailPackages(orderDtItem.Id, item.Count, true)
+			}
+			orderDtItem.Cover = product.Cover
+			if !orderDtItem.Commend {
+				item.ProductList = append(item.ProductList, orderDtItem)
+			}
+		}
+		if commend {
+			latestOrders = append(latestOrders, item)
+		} else {
+			count = count - 1
+		}
+	}
+	type Ret struct {
+		List      []*order_model.Order `json:"list"`
+		ListCount int64                `json:"list_count"`
+	}
+	self.Data["json"] = &Ret{ListCount: count, List: latestOrders}
 	self.ServeJSON()
 }
 
@@ -520,57 +605,87 @@ func (self *OrderController) List() {
 	if perPage <= 0 || perPage > 100 {
 		perPage = 20
 	}
+	order_status := ""
+	if status == order_model.WAIT_COMMEN {
+		perPage = 100
+		order_status = order_model.STATUS_COMPLETE
+	} else {
+		order_status = status
+	}
 	cache, _ := self.GetBool("cache", false)
 	//uId := self.GetCurrentUserId()
-	wxUId := self.GetCurrentWxUserId()
-	orders := order_model.GetUserOrders(wxUId, status, page, perPage)
+	wxUId := self.GetCurrentWxUserIdByToken()
+	orders := order_model.GetUserOrders(wxUId, order_status, page, perPage)
 	count := order_model.GetUserOrdersCount(wxUId, status)
-
-	for _, item := range orders {
-		orderList := order_model.GetAllDetailsOrderId(item.OrderId, false)
-		for _, orderItem := range orderList {
-			product := product_model.GetProductById(orderItem.ProductId, cache)
-			if product == nil {
-				continue
+	var latestOrders []*order_model.Order
+
+	if status != order_model.WAIT_COMMEN {
+		for _, item := range orders {
+			orderDtList := order_model.GetAllDetailsOrderId(item.OrderId, false)
+			for _, orderDtItem := range orderDtList {
+				product := product_model.GetProductById(orderDtItem.ProductId, cache)
+				if product == nil {
+					continue
+				}
+				orderDtItem.Package = product.Package
+				item.Count += orderDtItem.Count
+				if orderDtItem.Commend || item.Status != order_model.STATUS_COMPLETE {
+					orderDtItem.Commend = true
+				}
+				if product.Package {
+					orderDtItem.PacakageList = order_model.GetOrderDetailPackages(orderDtItem.Id, item.Count, true)
+				}
+				orderDtItem.Cover = product.Cover
+				item.ProductList = append(item.ProductList, orderDtItem)
 			}
-			product.SizeName = orderItem.SizeName
-			product.ColorName = orderItem.ColorName
-			product.OrderCount = orderItem.Count
-			item.Count += orderItem.Count
-			product.OrderCount = orderItem.Count
-			product.IsZeng = orderItem.Send
-
-			if product.SeckilShowPrice > 0 {
-				now := time.Now()
-				product.SeckillStartAt = product.SeckillStart.Unix()
-				product.SeckillEndAt = product.SeckillEnd.Unix()
-				if product.SeckillStart.Unix() > now.Unix() {
-					product.SeckillState = product_model.SECKILL_PREPARING_STATE
-					product.SeckillStateCn = product_model.SECKILL_PREPARING_STATE_CN
-				} else if product.SeckillStart.Unix() <= now.Unix() && now.Unix() < product.SeckillEnd.Unix() {
-					product.IsUnderSeckill = true
-					product.SeckillState = product_model.SECKILL_UNDER_STATE
-					product.SeckillStateCn = product_model.SECKILL_UNDER_STATE_CN
-				} else {
-					product.SeckillState = product_model.SECKILL_END_STATE
-					product.SeckillStateCn = product_model.SECKILL_END_STATE_CN
+			latestOrders = append(latestOrders, item)
+		}
+
+	} else {
+
+		for _, item := range orders {
+			commend := false
+			orderDtList := order_model.GetAllDetailsOrderId(item.OrderId, false)
+			for _, orderDtItem := range orderDtList {
+				product := product_model.GetProductById(orderDtItem.ProductId, cache)
+				if product == nil {
+					continue
+				}
+				orderDtItem.Package = product.Package
+				item.Count += orderDtItem.Count
+				if orderDtItem.Commend || item.Status != order_model.STATUS_COMPLETE {
+					orderDtItem.Commend = true
+				}
+				if !orderDtItem.Commend {
+					commend = true
+				}
+				if product.Package {
+					orderDtItem.PacakageList = order_model.GetOrderDetailPackages(orderDtItem.Id, item.Count, true)
+				}
+				orderDtItem.Cover = product.Cover
+				if !orderDtItem.Commend {
+					item.ProductList = append(item.ProductList, orderDtItem)
 				}
 			}
-			item.ProductList = append(item.ProductList, product)
+			if commend {
+				latestOrders = append(latestOrders, item)
+			} else {
+				count = count - 1
+			}
 		}
 	}
 	type Ret struct {
 		List      []*order_model.Order `json:"list"`
 		ListCount int64                `json:"list_count"`
 	}
-	self.Data["json"] = &Ret{ListCount: count, List: orders}
-	self.ServeJSON()
+	self.Data["json"] = &Ret{ListCount: count, List: latestOrders}
+	self.ServeResultJSON()
 }
 
 //用户更改订单状态
 func (self *OrderController) Operate() {
 	oId := self.Ctx.Input.Param(":order_id")
-	o := order_model.GetOrderById(oId, true)
+	o := order_model.GetOrderById(oId, false)
 	if o == nil {
 		self.ReturnError(404, apps.OrderNotExist, "", nil)
 	}
@@ -578,7 +693,7 @@ func (self *OrderController) Operate() {
 	//if uId != o.UserId {
 	//	self.ReturnError(404, apps.OrderNotExist, "", nil)
 	//}
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	if wxUId != o.WxUserId {
 		self.ReturnError(404, apps.OrderNotExist, "", nil)
 	}
@@ -628,32 +743,7 @@ func (self *OrderController) Operate() {
 	self.ServeJSON()
 }
 
-// 商家处理中订单数量提示
-func (self *OrderController) MerchantListCount() {
-	merchantId, _ := self.GetInt64("merchant_id", 0)
-
-	uId := self.GetCurrentUserId()
-
-	count := int64(0)
-	merchantUser := merchant_model.GetMerchantUserRelationByUserId(uId, true)
-	if merchantUser != nil {
-		if merchantUser.MerchantId != merchantId {
-			self.ReturnError(403, apps.ParamsError, "", nil)
-		}
-	} else {
-		self.ReturnError(403, apps.ParamsError, "", nil)
-	}
-	count = order_model.GetMerchantOrdersCount(merchantId, 0, 0, 0, 0, order_model.STATUS_PROCESSING, "",
-		strings.TrimSpace(merchantUser.ManageProductIds), "", "", "", "", "", "")
-
-	type Ret struct {
-		ListCount int64 `json:"list_count"`
-	}
-	self.Data["json"] = &Ret{ListCount: count}
-	self.ServeJSON()
-}
-
-func CreateOrderDetails(product *product_model.Product, order *order_model.Order, cNums int64) {
+func CreateOrderDetails(product *product_model.Product, order *order_model.Order, cNums, depart int64) {
 	//获取商品属性详情
 	sizeName := ""
 	colorName := ""
@@ -669,5 +759,49 @@ func CreateOrderDetails(product *product_model.Product, order *order_model.Order
 			colorName = productColor.Name
 		}
 	}
-	new(order_model.OrderDetail).Create(order.OrderId, order.Id, product.Id, product.Price, product.RoboBalancePrice, product.Name, sizeName, colorName, cNums)
+	new(order_model.OrderDetail).Create(order.OrderId, order.Id, product.Id, product.RelateProductId, product.Price, product.RoboBalancePrice, product.Name, sizeName, colorName, cNums, depart)
+}
+
+//用户评论订单明细
+func (self *OrderController) OrderCommend() {
+	_detail_id := self.Ctx.Input.Param(":detail_id")
+	detail_id, _ := strconv.ParseInt(_detail_id, 10, 64)
+	detail := self.GetString("detail")
+	score, _ := self.GetInt64("score")
+
+	od := order_model.GetOrderDetailById(detail_id)
+	if od == nil {
+		self.ReturnError(404, apps.OrderNotExist, "", nil)
+	}
+	if od.Commend {
+		self.ReturnError(404, apps.DetailHasCommend, "", nil)
+	}
+	if len(detail) == 0 {
+		self.ReturnError(404, apps.DetailNotAllow, "", nil)
+	}
+
+	wxUId := self.GetCurrentWxUserIdByToken()
+	o := order_model.GetOrderById(od.OrderNo, false)
+	if o.WxUserId != wxUId {
+		self.ReturnError(403, apps.AccountError, "", nil)
+	}
+
+	//订单 状态已完成才允许评论
+	if o.Status == order_model.STATUS_COMPLETE {
+		//先更改明细评论状态
+		od.Commend = true
+		od.Save()
+		//创建商品评论
+		new(product_model.ProductCommend).Create(o.WxUserId, od.ProductId, score, detail, o.OrderId)
+	} else {
+		self.ReturnError(403, apps.ParamsError, "", nil)
+	}
+
+	type apiRet struct {
+		Status bool `json:"status"`
+	}
+	self.Data["json"] = &apiRet{
+		Status: true,
+	}
+	self.ServeJSON()
 }

+ 19 - 175
go/gopath/src/fohow.com/apps/controllers/pay_controller/after_pay_controller.go

@@ -8,24 +8,20 @@ import (
 
 	"fohow.com/apps"
 	"fohow.com/apps/helpers"
-	"fohow.com/apps/models/base_config"
 	"fohow.com/libs/lib_redis"
-	"math"
-
 	// "fohow.com/apps/models/balance_model"
 	// "fohow.com/apps/models/project_join_model"
 	// "fohow.com/apps/models/project_model"
 	"fohow.com/apps/models/balance_model"
 	"fohow.com/apps/models/order_model"
 	"fohow.com/apps/models/pay_model"
-	"fohow.com/cache"
+	"fohow.com/apps/models/sys_config"
 	"fohow.com/libs/wx_mp"
 	"github.com/astaxie/beego"
 	"strconv"
 	"strings"
 	"time"
-	//"fohow.com/apps/models/product_model"
-	"fmt"
+
 	"fohow.com/apps/models/user_model"
 )
 
@@ -89,7 +85,7 @@ func (self *PayController) wxPayBalanceAsync() {
 
 	orderId := strings.Split(params.OutTradeNO, "_")[0]
 	order := balance_model.GetBalanceOrderByOId(orderId, false)
-	payCode := pay_model.GetPayConfigByDepart(order.Depart, true)
+	payCode := sys_config.GetPayConfigByDepart(order.Depart, true)
 	// 签名校验参数
 	if !wx_mp.VerifyPayResult(params, payCode) {
 		beego.BeeLogger.Error("VerifyPayResult not pass")
@@ -112,25 +108,12 @@ func (self *PayController) wxPayBalanceAsync() {
 		self.Ctx.WriteString(wx_mp.MapToXmlString(notifyResponse))
 		return
 	}
-	order.PaiedPrice = totalFee
-	order.State = 1
-	order.TradeNo = params.TransactionId
-	order.PayWay = balance_model.PAY_WAY_TYPE_SERVICE_WXPAY
-	order.PaiedAt = time.Now().Unix()
-	if err := order.Save(); err != nil {
-		beego.BeeLogger.Error("weixinpay async return. save oId=%s fail", order.OrderId)
-		self.Ctx.WriteString(wx_mp.MapToXmlString(notifyResponse))
-		return
-	}
-	go recharge(order.WxUserId, order.UserId, order.TotalPrice, order.OrderId)
-	wxUser := user_model.GetWxUserById(order.WxUserId, false)
-	if wxUser != nil {
-		newSendInviterBenefit(wxUser, order.OrderId, user_model.BALANCE_BENEFIT)
-	}
-	if totalFee >= base_config.GetBuyCash() && wxUser.ShowInviteMode != 1 {
-		//升级群主
-		UpdateIntroUser(wxUser)
-	}
+
+	// 发放充值佣金
+	go helpers.PatchRechargeBalance(order.Id, totalFee, params.TransactionId)
+
+	//发放赠品
+	go helpers.BalanceOrderPromotion(order.OrderId, order.WxUserId, order.Depart)
 
 	notifyResponse["return_code"] = wx_mp.PAY_SUCCESS
 	//beego.BeeLogger.Warn("小程序购买提货券微信支付回调通知,订单编号=%s  订单状态=%d", order.OrderId, order.State)
@@ -139,148 +122,6 @@ func (self *PayController) wxPayBalanceAsync() {
 
 }
 
-//升级群主
-func UpdateIntroUser(wxUser *user_model.WxUser) {
-
-	if wxUser == nil || wxUser.ShowInviteMode == int64(1) {
-		return
-	}
-	//升级群主,打开推广模块
-	wxUser.ShowInviteMode = int64(1)
-	wxUser.Rank = int64(1)
-	wxUser.PartnerTime = time.Now().Unix()
-	wxUser.Save()
-	//更改下级群主关系
-	inviteList := user_model.GetWxUsersByInviteIdAll(wxUser.Id, false)
-	go user_model.UpdateClass(inviteList, wxUser.Id, wxUser.IntroUserId)
-	//消除user,wxuser缓存
-	userKey := fmt.Sprintf("user.GetByUid[%d]", wxUser.UserId)
-	wxUserKey := cache.GetKey(cache.GetWxUserById, wxUser.Id)
-	cache.Cache.Delete(userKey)
-	cache.Cache.Delete(wxUserKey)
-}
-
-func FindInviter(wxUser *user_model.WxUser) *user_model.WxUser {
-	inviter := user_model.GetWxUserById(wxUser.InviteId, false)
-	if inviter == nil {
-		return nil
-	}
-	if inviter.ShowInviteMode == int64(1) {
-		return inviter
-	} else {
-		return FindInviter(inviter)
-	}
-}
-
-func newSendInviterBenefit(wxUser *user_model.WxUser, orderId, source string) {
-
-	//20.12.01 新规--(微信支付金额-运费)>0,按(微信支付金额-运费)*20%给上级代理返佣金(代理本人下订单,也是返给上级代理)
-	benefitWxUser := FindInviter(wxUser)
-	if benefitWxUser == nil || benefitWxUser.Id == int64(1) {
-		return
-	}
-	//beego.BeeLogger.Warn("benefitWxUser: %s", benefitWxUser)
-	//beego.BeeLogger.Warn("newSendInviterBenefit:%v,%v,%s", wxUser, benefitWxUser, orderId)
-	if source == user_model.SOURCE_PRODUCT_BENEFIT {
-		productOrder := order_model.GetOrderById(orderId, true)
-		if productOrder == nil {
-			return
-		}
-
-		if benefitWxUser != nil {
-			//发放群主收益,(微信支付金额-运费)>0,按(微信支付金额-运费)*20%给上级代理返佣金
-			be_total := float64(productOrder.PaiedPrice-productOrder.Freight) * float64(0.2)
-			count := int64(math.Floor(be_total + 0.5))
-
-			//beego.BeeLogger.Warn("count %d", count)
-			remark := fmt.Sprintf("%s%s", wxUser.Nickname, "购物")
-			if count > 0 {
-				//发放佣金
-				inviteOrder := new(user_model.InviteOrder).Create(benefitWxUser.Id, wxUser.Id, wxUser.Id, count, productOrder.TotalPrice, user_model.SOURCE_PRODUCT_BENEFIT, productOrder.OrderId)
-				s := balance_model.CASH_SOURCE_PRODUCT_BENEFIT
-				cb := balance_model.GetCashBalanceByWxUIdAndRIdAndSource(benefitWxUser.Id, productOrder.OrderId, s)
-				if cb == nil {
-					cb = new(balance_model.CashBalance).Create(inviteOrder.BenefitWxUId, count, s, productOrder.OrderId, remark)
-					if cb != nil {
-						//标志进账
-						inviteOrder.IsEnterBalance = true
-						inviteOrder.EnterTime = cb.CreatedAt
-						inviteOrder.Save()
-					}
-				}
-			}
-		}
-	} else if source == user_model.BALANCE_BENEFIT {
-		balanceOrder := balance_model.GetBalanceOrderByOId(orderId, false)
-		if balanceOrder == nil {
-			return
-		}
-		//下线充值,上线获得540返利
-		if benefitWxUser != nil {
-			count := int64(0)
-			//发放一级收益, 上级群主返利540
-			if balanceOrder.PaiedPrice == base_config.GetBuyCash() {
-				count = base_config.GetCashAward()
-			}
-			if count > 0 {
-				inviteOrder := new(user_model.InviteOrder).Create(benefitWxUser.Id, wxUser.Id, wxUser.Id, count, balanceOrder.TotalPrice, user_model.BALANCE_BENEFIT, balanceOrder.OrderId)
-				//发放现金佣金
-				s := balance_model.BALANCE_SOURCE_BENEFIT
-				remark := fmt.Sprintf("%s%s", wxUser.Nickname, "充值提货券")
-				b := balance_model.GetCashBalanceByWxUIdAndRIdAndSource(benefitWxUser.Id, balanceOrder.OrderId, s)
-				if b == nil {
-					b = new(balance_model.CashBalance).Create(inviteOrder.BenefitWxUId, count, s, balanceOrder.OrderId, remark)
-					if b != nil {
-						//标志进账
-						inviteOrder.IsEnterBalance = true
-						inviteOrder.EnterTime = b.CreatedAt
-						inviteOrder.Save()
-					}
-				}
-			}
-		}
-	}
-}
-
-func shopSendInviterBenefit(wxUser *user_model.WxUser, orderId, source string) {
-
-	//非群主店铺专区不能下单
-	if wxUser == nil || wxUser.Rank != int64(2) {
-		return
-	}
-	//店长购物给上级返佣8%
-	benefitWxUser := FindInviter(wxUser)
-	if benefitWxUser == nil || benefitWxUser.Id == int64(1) {
-		return
-	}
-	//beego.BeeLogger.Warn("shop_benefitWxUser: %s", benefitWxUser)
-	//beego.BeeLogger.Warn("shop_newSendInviterBenefit:%v,%v,%s", wxUser, benefitWxUser, orderId)
-	if source == user_model.SOURCE_PRODUCT_BENEFIT {
-		productOrder := order_model.GetOrderById(orderId, false)
-		if productOrder == nil || productOrder.OrderType != order_model.ORDER_TYPE_SHOP {
-			return
-		}
-		if benefitWxUser != nil {
-			//不扣提货券,只计算8%佣金
-			count := int64(math.Floor(float64(productOrder.TotalPrice) * order_model.SHOP_BENETFIT_BL))
-			remark := fmt.Sprintf("%s%s", wxUser.Nickname, "店铺专区购物")
-			//发放佣金
-			inviteOrder := new(user_model.InviteOrder).Create(benefitWxUser.Id, wxUser.Id, wxUser.Id, count, productOrder.TotalPrice, user_model.SOURCE_PRODUCT_BENEFIT, productOrder.OrderId)
-			s := balance_model.CASH_SOURCE_PRODUCT_BENEFIT
-			cb := balance_model.GetCashBalanceByWxUIdAndRIdAndSource(benefitWxUser.Id, productOrder.OrderId, s)
-			if cb == nil {
-				cb = new(balance_model.CashBalance).Create(inviteOrder.BenefitWxUId, count, s, productOrder.OrderId, remark)
-				if cb != nil {
-					//标志进账
-					inviteOrder.IsEnterBalance = true
-					inviteOrder.EnterTime = cb.CreatedAt
-					inviteOrder.Save()
-				}
-			}
-		}
-	}
-}
-
 //微信购买商品
 func (self *PayController) wxPayExchangeAsync() {
 	var notifyResponse = map[string]string{
@@ -298,9 +139,10 @@ func (self *PayController) wxPayExchangeAsync() {
 	}
 	orderId := strings.Split(params.OutTradeNO, "_")[0]
 	order := order_model.GetOrderById(orderId, false)
-	payCode := pay_model.GetPayConfigByDepart(order.Depart, true)
+	payCode := sys_config.GetPayConfigByDepart(order.Depart, true)
 	// 签名校验参数
-	if !wx_mp.VerifyPayResult(params, payCode) && !wx_mp.VerifyGzhPayResult(params, payCode) {
+	//&& !wx_mp.VerifyGzhPayResult(params, payCode)
+	if !wx_mp.VerifyPayResult(params, payCode) {
 		beego.BeeLogger.Error("VerifyPayResult not pass")
 		self.Ctx.WriteString(wx_mp.MapToXmlString(notifyResponse))
 		return
@@ -337,18 +179,21 @@ func (self *PayController) wxPayExchangeAsync() {
 	//go notice()
 	wxUser := user_model.GetWxUserById(order.WxUserId, true)
 	if order.OrderType == order_model.ORDER_TYPE_NORMAL {
-		go newSendInviterBenefit(wxUser, order.OrderId, user_model.SOURCE_PRODUCT_BENEFIT)
+		go helpers.NewSendInviterBenefit(wxUser, order.OrderId, user_model.SOURCE_PRODUCT_BENEFIT)
 	} else if order.OrderType == order_model.ORDER_TYPE_SHOP {
-		go shopSendInviterBenefit(wxUser, order.OrderId, user_model.SOURCE_PRODUCT_BENEFIT)
+		go helpers.ShopSendInviterBenefit(wxUser, order.OrderId, user_model.SOURCE_PRODUCT_BENEFIT)
 	}
 
 	//发放赠品
-	go helpers.SetOrderPromotion(order.OrderId, wxUser.Id)
+	go helpers.SetOrderPromotionPro(order.OrderId, wxUser.Id)
 	//已支付订单移除队列
 	cancelKey := lib_redis.GetOrderCancelList()
 	lib_redis.ThrowOutRedisList(cancelKey, order.OrderId)
 	//更新商品售量
 	go UpdatePdSaleNums(order)
+	//赠品写入订单
+	go helpers.PresentTransferToOrder(order.OrderId, order.WxUserId)
+
 	notifyResponse["return_code"] = wx_mp.PAY_SUCCESS
 	//beego.BeeLogger.Warn("商品购买微信支付回调通知,订单编号=%s  订单状态=%s", order.OrderId, order.Status)
 	self.Ctx.WriteString(wx_mp.MapToXmlString(notifyResponse))
@@ -370,7 +215,6 @@ func UpdatePdSaleNums(order *order_model.Order) {
 	for _, item := range orderDtList {
 		SaleNumsMap[item.ProductId] = item.Count
 	}
-
 	go order_model.UpdateSaleNums(SaleNumsMap)
 }
 
@@ -393,7 +237,7 @@ func (self *PayController) wxPayCashczAsync() {
 
 	orderId := strings.Split(params.OutTradeNO, "_")[0]
 	order := balance_model.GetRechargeCashOrderByOId(orderId, false)
-	payCode := pay_model.GetPayConfigByDepart(order.Id, true)
+	payCode := sys_config.GetPayConfigByDepart(order.Id, true)
 	// 签名校验参数
 	if !wx_mp.VerifyPayResult(params, payCode) {
 		beego.BeeLogger.Error("wxPayCashczAsync.VerifyPayResult not pass")

+ 2 - 2
go/gopath/src/fohow.com/apps/controllers/pay_controller/init.go

@@ -28,8 +28,8 @@ import (
 
 var (
 	//不需要校验用户登录的Action
-	exceptCheckUserLoginAction   = []string{"Pay", "PayAsync"}
-	exceptCheckWxUserLoginAction = []string{"Pay", "PayAsync"}
+	exceptCheckUserLoginAction   = []string{"PayAsync"}
+	exceptCheckWxUserLoginAction = []string{"PayAsync"}
 )
 
 type PayController struct {

+ 3 - 3
go/gopath/src/fohow.com/apps/controllers/pay_controller/pay_balance_controller.go

@@ -2,7 +2,7 @@ package pay_controller
 
 import (
 	"fmt"
-	"fohow.com/apps/models/pay_model"
+	"fohow.com/apps/models/sys_config"
 
 	"github.com/astaxie/beego"
 
@@ -38,11 +38,11 @@ func (self *PayController) wxPayBalance(orderId string) {
 	}
 	totalPrice := balanceOrder.PaiedPrice
 	//获取paycode
-	payCode := pay_model.GetPayConfigByDepart(wxUser.Depart, true)
+	payCode := sys_config.GetPayConfigByDepart(wxUser.Depart, true)
 	beego.BeeLogger.Debug("pay.total_price(%d)", totalPrice)
 	//获取预支付信息/v1/pay/:target:string/async/:payway:string
 	notifyUrl := fmt.Sprintf("%s/v1/pay/%s/async/%s", beego.AppConfig.String("ApiHost"), BALANCE_TARGET, balance_model.PAY_WAY_TYPE_SERVICE_WXPAY) // balance "service_wxpay"
-	body := "FOHOW玖玖-购买提货券"
+	body := "凤凰菁选-购买提货券"
 	payData := wx_mp.GetPayData(wxUser.Openid, balanceOrder.OrderId, totalPrice, body, notifyUrl, self.Ctx.Input.IP(), payCode)
 	//返回数据
 	type PayData struct {

+ 3 - 3
go/gopath/src/fohow.com/apps/controllers/pay_controller/pay_cashcz_controller.go

@@ -4,7 +4,7 @@ import (
 	"fmt"
 	"fohow.com/apps"
 	"fohow.com/apps/models/balance_model"
-	"fohow.com/apps/models/pay_model"
+	"fohow.com/apps/models/sys_config"
 	"fohow.com/libs/wx_mp"
 	"github.com/astaxie/beego"
 )
@@ -37,8 +37,8 @@ func (self *PayController) wxPayCashcz(orderId string) {
 	}
 	//获取预支付信息/v1/pay/:target:string/async/:payway:string
 	notifyUrl := fmt.Sprintf("%s/v1/pay/%s/async/%s", beego.AppConfig.String("ApiHost"), CASH_TARGET, balance_model.PAY_WAY_TYPE_RECHARGE_WXPAY) // rechargeCashOrder "recharge_wxpay"
-	body := "FOHOW玖玖-余额充值"
-	payCode := pay_model.GetPayConfigByDepart(wxUser.Depart, true)
+	body := "凤凰菁选-余额充值"
+	payCode := sys_config.GetPayConfigByDepart(wxUser.Depart, true)
 	payData := wx_mp.GetPayData(wxUser.Openid, reCashOrder.OrderId, reCashOrder.TotalPrice, body, notifyUrl, self.Ctx.Input.IP(), payCode)
 
 	//返回数据

+ 7 - 5
go/gopath/src/fohow.com/apps/controllers/pay_controller/pay_controller.go

@@ -25,11 +25,13 @@ type PayUrl struct {
 func (self *PayController) Pay() {
 	oId := self.GetString("order_id")
 	payWay := self.GetString("pay_way")
-	tradPwd := self.GetString("trad_pwd")
+	//tradPwd := self.GetString("trad_pwd")
+	remark := self.GetString("remark")
+
 	source := self.GetString("s")
-	useCoupon, _ := self.GetBool("use_coupon", true)
+	useCoupon, _ := self.GetBool("use_coupon", false)
 
-	beego.BeeLogger.Debug("pay.oId(%s).payway(%s).(%v)", oId, payWay, payWay == balance_model.PAY_WAY_TYPE_RECHARGE_WXPAY)
+	beego.BeeLogger.Debug("pay.oId(%s).payway(%s).(%v).use_coupon(%t)", oId, payWay, payWay == balance_model.PAY_WAY_TYPE_RECHARGE_WXPAY, useCoupon)
 	if oId == "" || payWay == "" {
 		self.ReturnError(500, apps.ParamsError, "", nil)
 	}
@@ -52,9 +54,9 @@ func (self *PayController) Pay() {
 		order := order_model.GetOrderById(oId, false)
 
 		if order != nil && order.OrderType != order_model.ORDER_TYPE_CENT {
-			self.payExchange(oId, payWay, tradPwd, returnUrl, source, useCoupon)
+			self.payExchange(oId, payWay, returnUrl, source, remark, useCoupon)
 		} else {
-			self.payCentExchange(oId, returnUrl, source)
+			self.payCentExchange(oId, returnUrl, source, remark)
 		}
 
 	case CASH_TARGET:

+ 232 - 96
go/gopath/src/fohow.com/apps/controllers/pay_controller/pay_exchange_controller.go

@@ -2,10 +2,10 @@ package pay_controller
 
 import (
 	"fmt"
-	"fohow.com/apps/models/base_config"
+	"fohow.com/apps/helper"
 	"fohow.com/apps/models/cent_model"
+	"fohow.com/apps/models/sys_config"
 	"fohow.com/libs/lib_redis"
-
 	// "net/url"
 	// "strings"
 	"time"
@@ -32,28 +32,55 @@ var createDrawCode sync.Mutex
 var payOrder sync.Mutex
 
 //支付订单
-func (self *PayController) payExchange(oId, payWay, tradPwd, returnUrl, source string, useCoupon bool) {
+func (self *PayController) payExchange(oId, payWay, returnUrl, source, remark string, useCoupon bool) {
 	payOrder.Lock()
 	defer payOrder.Unlock()
-	var payUrl string
+	var payUrl, tel, addr, concat, allowAddr, allowPro string
 	var payData map[string]string
-	wxUId := self.GetCurrentWxUserId()
-	uId := self.GetCurrentUserId()
-
+	var specialPromotion bool
+	wxUId := self.GetCurrentWxUserIdByToken()
+	pick_dept_id, _ := self.GetInt64("pick_dept")
+	pick_way, _ := self.GetInt64("pick_way")
 	//地址
 	addressId, _ := self.GetInt64("address_id")
-	address := address_model.GetUserAddressById(addressId)
-	if address == nil || address.WxUserId != wxUId {
-		self.ReturnError(403, apps.AddressNotMatch, "", nil)
-	}
+	if pick_way == order_model.PICK_EXPRESS {
+		address := address_model.GetUserAddressById(addressId)
+		//beego.BeeLogger.Warn("address.wxuserId--%d", address.WxUserId)
+		beego.BeeLogger.Warn("wxUId-%d", wxUId)
 
-	if source != order_model.SOURCE_XCX && source != order_model.SOURCE_GZH {
+		if address == nil || address.WxUserId != wxUId {
+			self.ReturnError(403, apps.AddressNotMatch, "", nil)
+		}
+		concat = address.Contact
+		tel = address.Tel
+		addr = fmt.Sprintf("%s%s%s%s", address.Province, address.City, address.District, address.Address)
+		allowAddr = fmt.Sprintf("%s%s", address.Province, address.City)
+		allowPro = address.Province
+	} else {
+		//物流方式
+		pick_addr_id, _ := self.GetInt64("pick_addr_id")
+		pick_address := address_model.GetUserPickAddressById(pick_addr_id)
+		pick_dept := user_model.GetDepartRecordById(pick_dept_id, true)
+		if pick_dept == nil || pick_address == nil || pick_address.WxUserId != wxUId {
+			self.ReturnError(403, apps.AddressNotMatch, "", nil)
+		}
+		concat = pick_address.Contact
+		tel = pick_address.Tel
+		addr = pick_dept.PickAddress
+		allow_arr := strings.Split(addr, "市")
+		allowAddr = fmt.Sprintf("%s市", allow_arr[0])
+		allow_prv_arr := strings.Split(addr, "省")
+		allowPro = fmt.Sprintf("%s省", allow_prv_arr[0])
+	}
+	if source != order_model.SOURCE_XCX && source != order_model.SOURCE_APP {
 		self.ReturnError(403, apps.ParamsError, "", nil)
 	}
+
 	wxUser := user_model.GetWxUserById(wxUId, false)
 	if wxUser == nil {
 		self.ReturnError(403, apps.UserNeedLogin, "", nil)
 	}
+	uId := wxUser.UserId
 	//订单状态
 	order := order_model.GetOrderById(oId, false)
 	if order == nil || order.WxUserId != wxUId {
@@ -62,64 +89,90 @@ func (self *PayController) payExchange(oId, payWay, tradPwd, returnUrl, source s
 	if order.Status != order_model.STATUS_UNPAY {
 		self.ReturnError(403, apps.NotUnPay, "", nil)
 	}
-	//第一次支付已更新支付方式,第一次支付才计算支付金额
-	if len(order.PayWay) <= 0 {
-		SaleNumsMap := make(map[int64]int64)
-		//支付方式判断
-		if (order.OrderType == order_model.ORDER_TYPE_SEKILL || order.OrderType == order_model.ORDER_TYPE_SHOP) && payWay == pay_model.PAYWAY_BALANCE {
-			self.ReturnError(403, apps.NotRightPayWay, "", nil)
+	SaleNumsMap := make(map[int64]int64)
+
+	storeMap := make(map[int64]int64)
+	specialPromotion = order.SpecialPro
+	//支付方式判断
+	if order.OrderType == order_model.ORDER_TYPE_SHOP && payWay == pay_model.PAYWAY_BALANCE {
+		self.ReturnError(403, apps.NotRightPayWay, "", nil)
+	}
+
+	//获取购物商品明细
+	total_price := int64(0)
+	total_quan := int64(0)
+	total_weixin := int64(0)
+	list := order_model.GetAllDetailsOrderId(order.OrderId, false)
+	for _, item := range list {
+		//商品状态
+		product := product_model.GetProductById(item.ProductId, false)
+		if product == nil {
+			self.ReturnError(403, []string{apps.ProductNotExist[0], fmt.Sprintf("%s产品不存在", product.Name)}, "", nil)
 		}
-		//获取购物商品明细
-		buy_price_total := int64(0)
-		total_price := int64(0)
-		list := order_model.GetAllDetailsOrderId(order.OrderId, false)
-		for _, item := range list {
-			//商品状态
-			product := product_model.GetProductById(item.ProductId, false)
-			if product == nil {
-				self.ReturnError(403, []string{apps.ProductNotExist[0], fmt.Sprintf("%s产品不存在", product.Name)}, "", nil)
-			}
-			//商品下架
-			if product.Status == product_model.PRODUCT_STATUS_DOWN {
-				self.ReturnError(403, []string{apps.ProductOffSale[0], fmt.Sprintf("%s产品已经下架", product.Name)}, "", nil)
+		//商品下架
+		if product.Status == product_model.PRODUCT_STATUS_DOWN {
+			self.ReturnError(403, []string{apps.ProductOffSale[0], fmt.Sprintf("%s产品已经下架", product.Name)}, "", nil)
+		}
+
+		//秒杀逻辑: 判断是否处于秒杀时间段内
+		if product.SeckilShowPrice > 0 {
+			now := time.Now()
+			if now.Unix() < product.SeckillStart.Unix() {
+				self.ReturnError(403, []string{apps.SeckillNotStart[0], fmt.Sprintf("%s秒杀活动尚未开始", product.Name)}, "", nil)
+			} else if now.Unix() > product.SeckillEnd.Unix() {
+				self.ReturnError(403, []string{apps.SeckillIsEnd[0], fmt.Sprintf("%s秒杀活动已经结束", product.Name)}, "", nil)
 			}
-			//秒杀逻辑: 判断是否处于秒杀时间段内
-			if product.SeckilShowPrice > 0 {
-				now := time.Now()
-				if now.Unix() < product.SeckillStart.Unix() {
-					self.ReturnError(403, []string{apps.SeckillNotStart[0], fmt.Sprintf("%s秒杀活动尚未开始", product.Name)}, "", nil)
-				} else if now.Unix() > product.SeckillEnd.Unix() {
-					self.ReturnError(403, []string{apps.SeckillIsEnd[0], fmt.Sprintf("%s秒杀活动已经结束", product.Name)}, "", nil)
+		}
+		//限购逻辑
+		if product.PurchaseLimitCount > 0 {
+			if product.PurchaseLimitCount < item.Count {
+				self.ReturnError(403, []string{apps.OverLimitCount[0], fmt.Sprintf("%s商品限购%d件", product.Name, product.PurchaseLimitCount)}, "", nil)
+			} else {
+				purchaseTotalCount := order_model.GetOrderCountByPIdAndWxUId(product.Id, wxUId)
+				//历史已经买够到限购数量了
+				if product.PurchaseLimitCount <= purchaseTotalCount {
+					self.ReturnError(403, []string{apps.PurchasedReachLimit[0], fmt.Sprintf("%s商品限购%d件", product.Name, product.PurchaseLimitCount)}, "", nil)
 				}
-			}
-			//限购逻辑
-			if product.PurchaseLimitCount > 0 {
-				if product.PurchaseLimitCount < item.Count {
-					self.ReturnError(403, []string{apps.OverLimitCount[0], fmt.Sprintf("%s商品限购%d件", product.Name, product.PurchaseLimitCount)}, "", nil)
-				} else {
-					purchaseTotalCount := order_model.GetOrderCountByPIdAndWxUId(product.Id, wxUId)
-					//历史已经买够到限购数量了
-					if product.PurchaseLimitCount <= purchaseTotalCount {
-						self.ReturnError(403, []string{apps.PurchasedReachLimit[0], fmt.Sprintf("%s商品限购%d件", product.Name, product.PurchaseLimitCount)}, "", nil)
-					}
-					//历史没买够数量,但是历史总数+想购买的数量 超过限购数量
-					if product.PurchaseLimitCount < (purchaseTotalCount + item.Count) {
-						canBuyCount := product.PurchaseLimitCount - purchaseTotalCount
-						self.ReturnError(403, []string{apps.PurchasedReachLimit[0], fmt.Sprintf("%s您还可以购买%d件", product.Name, canBuyCount)}, "", nil)
-					}
+				//历史没买够数量,但是历史总数+想购买的数量 超过限购数量
+				if product.PurchaseLimitCount < (purchaseTotalCount + item.Count) {
+					canBuyCount := product.PurchaseLimitCount - purchaseTotalCount
+					self.ReturnError(403, []string{apps.PurchasedReachLimit[0], fmt.Sprintf("%s您还可以购买%d件", product.Name, canBuyCount)}, "", nil)
 				}
 			}
-			buy_price_total += product.BuyPrice * item.Count
-			total_price += product.Price * item.Count
-			SaleNumsMap[product.Id] = item.Count
 		}
+		//仅发货地区省,市判断
+		if len(product.OnlyDeliveryArea) > 0 {
+			if product_model.GetProductByIdAndProvince(product.Id, allowPro, true) == nil && helper.NewStr(product.OnlyDeliveryArea).Strpos(allowAddr, 0) < 0 {
+				self.ReturnError(403, []string{apps.OnlyDeliveryArea[0], fmt.Sprintf("%s产品不在限售区域内", product.Name)}, "", nil)
+			}
+		}
+
+		//微信支付金额统计
+		if product.Pv >= product.Price || specialPromotion {
+			total_quan += product.Price * item.Count
+		}
+		total_price += product.Price * item.Count
+		SaleNumsMap[product.Id] = item.Count
+		storeMap[product.Id] = item.Count
+	}
+	//beego.BeeLogger.Error("SaleNumsMap1 %v", SaleNumsMap)
 
+	resultStore, prdName := FindNotEnoughPrd(storeMap)
+	if resultStore {
+		self.ReturnError(403, []string{apps.ProductStockNotEnough[0], fmt.Sprintf("%s商品库存不足", prdName)}, "", nil)
+	}
+	//订单公共信息更新
+	order.AddressId = addressId
+	order.Remark = remark
+	order.Contact = concat
+	order.Tel = tel
+	order.Address = addr
+	order.TotalPrice = total_price
+	order.PickDept = pick_dept_id
+	order.PickWay = pick_way
+	//第一次支付已更新支付方式,第一次支付才计算支付金额
+	if len(order.PayWay) <= 0 {
 		order.PayWay = payWay
-		order.Contact = address.Contact
-		order.Tel = address.Tel
-		order.Address = fmt.Sprintf("%s%s%s%s", address.Province, address.City, address.District, address.Address)
-		order.BuyPrice = buy_price_total
-		order.TotalPrice = total_price
 		//支付信息判断
 		//黑名单用户
 		curUser := user_model.GetUserById(wxUser.UserId, false)
@@ -131,23 +184,42 @@ func (self *PayController) payExchange(oId, payWay, tradPwd, returnUrl, source s
 			self.ReturnError(403, apps.NotUnPay, "", nil)
 		}
 		//若账户有提货券则优先抵扣提货券
-		needWx := true
+		needWx := false
 		totalCoupon := int64(0)
 		userLeftBalanceCount := balance_model.GetUserTotalBalance(wxUId)
 		tp := order.TotalPrice
-		freight := base_config.GetFreight()
-		if tp >= base_config.GetOrderLimit() {
+		freight := sys_config.GetFreight()
+		if tp >= sys_config.GetOrderLimit() || pick_way == order_model.PICK_SHOP {
 			freight = int64(0)
 		}
 		tp += freight
-		if order.OrderType != order_model.ORDER_TYPE_SEKILL && useCoupon {
-			if userLeftBalanceCount < tp {
+		total_quan += freight
+
+		quanLittle := false
+		if useCoupon {
+			if userLeftBalanceCount < total_quan {
+				quanLittle = true
 				totalCoupon = userLeftBalanceCount
 			} else {
-				needWx = false
-				totalCoupon = tp
+				totalCoupon = total_quan
+			}
+		}
+		total_weixin = tp - totalCoupon
+
+		//特殊促销期间券不够不允许支付
+		if sys_config.GetShutWechatPromotion() && total_weixin > 0 {
+			if quanLittle {
+				self.ReturnError(403, apps.NotEnoughPay, "", nil)
+			} else {
+				self.ReturnError(403, apps.PayWayNotAllow, "", nil)
 			}
 		}
+
+		if total_weixin > 0 {
+			needWx = true
+		}
+		order.Freight = freight
+
 		//先扣减提货券
 		if totalCoupon > 0 {
 			source := balance_model.BALANCE_SOURCE_EXCHANGE_PRODUCT
@@ -166,12 +238,14 @@ func (self *PayController) payExchange(oId, payWay, tradPwd, returnUrl, source s
 			order.Source = source
 			order.Save()
 			//发放赠品
-			go helpers.SetOrderPromotion(order.OrderId, wxUser.Id)
+			go helpers.SetOrderPromotionPro(order.OrderId, wxUser.Id)
 			//已支付订单移除未支付队列
 			cancelKey := lib_redis.GetOrderCancelList()
 			lib_redis.ThrowOutRedisList(cancelKey, order.OrderId)
 			//更新已售数量
 			go order_model.UpdateSaleNums(SaleNumsMap)
+			//赠品写入订单
+			go helpers.PresentTransferToOrder(order.OrderId, wxUId)
 			//go CreateOrderNotify(order, product)
 			//wxUser := user_model.GetWxUserById(order.WxUserId, true)
 			//go sendInviterBenefit(wxUser, order.OrderId, user_model.SOURCE_PRODUCT_BENEFIT)
@@ -180,22 +254,21 @@ func (self *PayController) payExchange(oId, payWay, tradPwd, returnUrl, source s
 			//self.Data["json"] = self.FormatResult([]interface{}{result})
 			self.Data["json"] = result
 		case true: // 微信支付
-			order.Contact = address.Contact
-			order.PaiedPrice = tp - totalCoupon
-			order.Tel = address.Tel
-			order.Address = fmt.Sprintf("%s%s%s%s", address.Province, address.City, address.District, address.Address)
+			order.PaiedPrice = total_weixin
 			order.Source = source
 			order.Save()
-			if order.Source == order_model.SOURCE_XCX { //小程序微信支付
-				freight := base_config.GetFreight()
-				if order.TotalPrice >= base_config.GetOrderLimit() {
+			if source == order_model.SOURCE_XCX { //小程序微信支付
+				freight := sys_config.GetFreight()
+				if order.TotalPrice >= sys_config.GetOrderLimit() {
 					freight = int64(0)
 				}
 				order.TotalPrice += freight
 				notifyUrl := fmt.Sprintf("%s/v1/pay/%s/async/%s", beego.AppConfig.String("ApiHost"), EXCHANGE_TARGET, pay_model.PAYWAY_WEIXINPAY)
-				body := fmt.Sprintf("FOHOW玖玖-购买商品")
+				body := fmt.Sprintf("凤凰菁选-购买商品")
 				//获取paycode
-				payCode := pay_model.GetPayConfigByDepart(wxUser.Depart, true)
+				payCode := sys_config.GetPayConfigByDepart(wxUser.Depart, false)
+
+				beego.BeeLogger.Warn("payCode--%s", payCode)
 				payData := wx_mp.GetPayData(wxUser.Openid, order.OrderId, order.PaiedPrice, body, notifyUrl, self.Ctx.Input.IP(), payCode)
 
 				//返回数据
@@ -205,15 +278,34 @@ func (self *PayController) payExchange(oId, payWay, tradPwd, returnUrl, source s
 				}
 				self.Data["json"] = &PayData{NeedWx: true, PayData: payData}
 
+			} else if source == order_model.SOURCE_APP {
+				freight := sys_config.GetFreight()
+				if order.TotalPrice >= sys_config.GetOrderLimit() {
+					freight = int64(0)
+				}
+				order.TotalPrice += freight
+				notifyUrl := fmt.Sprintf("%s/v1/pay/%s/async/%s", beego.AppConfig.String("ApiHost"), EXCHANGE_TARGET, pay_model.PAYWAY_WEIXINPAY)
+				body := fmt.Sprintf("FOHOW玖玖-购买商品")
+				//获取paycode
+				payCode := "app" //sys_config.GetPayConfigByDepart(wxUser.Depart, true)
+				payData := wx_mp.GetAppPayData(order.OrderId, order.PaiedPrice, body, notifyUrl, self.Ctx.Input.IP(), payCode)
+				beego.BeeLogger.Warn("pay_data --%v", payData)
+				//返回数据
+				type PayData struct {
+					NeedWx  bool              `json:"need_wx"`
+					PayData map[string]string `json:"pay_data"`
+				}
+				self.Data["json"] = &PayData{NeedWx: true, PayData: payData}
+
 			} else { //公众号微信支付
 
 				notifyUrl := fmt.Sprintf("%s/v1/pay/%s/async/%s", beego.AppConfig.String("ApiHost"), EXCHANGE_TARGET, pay_model.PAYWAY_WEIXINPAY)
-				body := fmt.Sprintf("FOHOW玖玖-购买商品")
+				body := fmt.Sprintf("凤凰菁选-购买商品")
 				wxGzh := user_model.GetWxUserGzhByWxUIdAndAppId(wxUser.Id, beego.AppConfig.String("WxMPAppId"), false)
 				if wxGzh == nil {
 					self.ReturnError(403, apps.NoExist, "", nil)
 				}
-				payCode := pay_model.GetPayConfigByDepart(wxUser.Depart, true)
+				payCode := sys_config.GetPayConfigByDepart(wxUser.Depart, true)
 				payData := wx_mp.GetPayData(wxGzh.GzhOpenId, order.OrderId, order.PaiedPrice, body, notifyUrl, self.Ctx.Input.IP(), payCode)
 
 				//返回数据
@@ -227,12 +319,13 @@ func (self *PayController) payExchange(oId, payWay, tradPwd, returnUrl, source s
 			beego.BeeLogger.Error("pay way not match, payway:%s", payWay)
 		}
 	} else {
+		order.Save()
 		//如果是第二次支付
-		if order.Source == order_model.SOURCE_XCX { //小程序微信支付
+		if source == order_model.SOURCE_XCX { //小程序微信支付
 
 			notifyUrl := fmt.Sprintf("%s/v1/pay/%s/async/%s", beego.AppConfig.String("ApiHost"), EXCHANGE_TARGET, pay_model.PAYWAY_WEIXINPAY)
-			body := fmt.Sprintf("FOHOW玖玖-购买商品")
-			payCode := pay_model.GetPayConfigByDepart(wxUser.Depart, true)
+			body := fmt.Sprintf("凤凰菁选-购买商品")
+			payCode := sys_config.GetPayConfigByDepart(wxUser.Depart, true)
 			payData := wx_mp.GetPayData(wxUser.Openid, order.OrderId, order.PaiedPrice, body, notifyUrl, self.Ctx.Input.IP(), payCode)
 
 			//返回数据
@@ -242,15 +335,30 @@ func (self *PayController) payExchange(oId, payWay, tradPwd, returnUrl, source s
 			}
 			self.Data["json"] = &PayData{NeedWx: true, PayData: payData}
 
+		} else if source == order_model.SOURCE_APP {
+			notifyUrl := fmt.Sprintf("%s/v1/pay/%s/async/%s", beego.AppConfig.String("ApiHost"), EXCHANGE_TARGET, pay_model.PAYWAY_WEIXINPAY)
+			body := fmt.Sprintf("FOHOW玖玖-购买商品")
+			//payCode := sys_config.GetPayConfigByDepart(wxUser.Depart, true)
+			payCode := "app" //sys_config.GetPayConfigByDepart(wxUser.Depart, true)
+
+			payData := wx_mp.GetAppPayData(order.OrderId, order.PaiedPrice, body, notifyUrl, self.Ctx.Input.IP(), payCode)
+
+			//返回数据
+			type PayData struct {
+				NeedWx  bool              `json:"need_wx"`
+				PayData map[string]string `json:"pay_data"`
+			}
+			self.Data["json"] = &PayData{NeedWx: true, PayData: payData}
+
 		} else { //公众号微信支付
 
 			notifyUrl := fmt.Sprintf("%s/v1/pay/%s/async/%s", beego.AppConfig.String("ApiHost"), EXCHANGE_TARGET, pay_model.PAYWAY_WEIXINPAY)
-			body := fmt.Sprintf("FOHOW玖玖-购买商品")
+			body := fmt.Sprintf("凤凰菁选-购买商品")
 			wxGzh := user_model.GetWxUserGzhByWxUIdAndAppId(wxUser.Id, beego.AppConfig.String("WxMPAppId"), false)
 			if wxGzh == nil {
 				self.ReturnError(403, apps.NoExist, "", nil)
 			}
-			payCode := pay_model.GetPayConfigByDepart(wxUser.Depart, true)
+			payCode := sys_config.GetPayConfigByDepart(wxUser.Depart, true)
 
 			//payData := wx_mp.GetPayData(wxGzh.GzhOpenId, order.OrderId , order.TotalPrice, body,notifyUrl, self.Ctx.Input.IP())
 			payData := wx_mp.GetPayData(wxGzh.GzhOpenId, order.OrderId, order.PaiedPrice, body, notifyUrl, self.Ctx.Input.IP(), payCode)
@@ -267,12 +375,12 @@ func (self *PayController) payExchange(oId, payWay, tradPwd, returnUrl, source s
 }
 
 //支付积分订单
-func (self *PayController) payCentExchange(oId, returnUrl, source string) {
+func (self *PayController) payCentExchange(oId, returnUrl, source, remark string) {
 	payOrder.Lock()
 	defer payOrder.Unlock()
 	var payUrl string
 	var payData map[string]string
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	//地址
 	addressId, _ := self.GetInt64("address_id")
 	address := address_model.GetUserAddressById(addressId)
@@ -280,7 +388,7 @@ func (self *PayController) payCentExchange(oId, returnUrl, source string) {
 		self.ReturnError(403, apps.AddressNotMatch, "", nil)
 	}
 
-	if source != order_model.SOURCE_XCX && source != order_model.SOURCE_GZH {
+	if source != order_model.SOURCE_XCX && source != order_model.SOURCE_APP {
 		self.ReturnError(403, apps.ParamsError, "", nil)
 	}
 	wxUser := user_model.GetWxUserById(wxUId, false)
@@ -296,9 +404,7 @@ func (self *PayController) payCentExchange(oId, returnUrl, source string) {
 		self.ReturnError(403, apps.NotUnPay, "", nil)
 	}
 	SaleNumsMap := make(map[int64]int64)
-
 	//获取购物商品明细
-	buy_price_total := int64(0)
 	total_price := int64(0)
 	list := order_model.GetAllDetailsOrderId(order.OrderId, false)
 	for _, item := range list {
@@ -328,16 +434,19 @@ func (self *PayController) payCentExchange(oId, returnUrl, source string) {
 				}
 			}
 		}
-		buy_price_total += product.BuyPrice * item.Count
 		total_price += product.Price * item.Count
 		SaleNumsMap[product.Id] = item.Count
 	}
-
+	storeMap := SaleNumsMap
+	resultStore, prdName := FindNotEnoughPrd(storeMap)
+	if resultStore {
+		self.ReturnError(403, []string{apps.ProductStockNotEnough[0], fmt.Sprintf("%s商品库存不足", prdName)}, "", nil)
+	}
+	order.Remark = remark
 	order.PayWay = order_model.PAY_WAY_CENT
 	order.Contact = address.Contact
 	order.Tel = address.Tel
 	order.Address = fmt.Sprintf("%s%s%s%s", address.Province, address.City, address.District, address.Address)
-	order.BuyPrice = buy_price_total
 	order.TotalPrice = total_price
 	//支付信息判断
 	//黑名单用户
@@ -352,8 +461,8 @@ func (self *PayController) payCentExchange(oId, returnUrl, source string) {
 	//直接抵扣积分,积分不够则报错
 	userLeftCent := cent_model.GetCentTotalBalance(wxUId)
 	tp := order.TotalPrice
-	freight := base_config.GetFreight()
-	if tp >= base_config.GetOrderLimit() {
+	freight := sys_config.GetFreight()
+	if tp >= sys_config.GetOrderLimit() {
 		freight = int64(0)
 	}
 	tp += freight
@@ -406,3 +515,30 @@ func CreateOrderNotify(order *order_model.Order, product *product_model.Product)
 		}
 	}
 }
+
+//获取库存不足商品
+func FindNotEnoughPrd(storeMap map[int64]int64) (bool, string) {
+	//判断商品库存
+	for pId, nums := range storeMap {
+		product := product_model.GetProductById(pId, true)
+		if product.Package {
+			//beego.BeeLogger.Error("product id %d", product.Id)
+			packageList := product_model.GetPackageList(pId, true)
+			for _, one := range packageList {
+				if _, ok := storeMap[one.ItemId]; ok {
+					//基本商品存在
+					storeMap[one.ItemId] = storeMap[one.ItemId] + nums*one.Nums
+				} else {
+					storeMap[one.ItemId] = nums * one.Nums
+				}
+			}
+		}
+	}
+	for r_pid, r_nums := range storeMap {
+		product := product_model.GetProductById(r_pid, false)
+		if product.Count > int64(0) && product.Count < (r_nums+product.SaleNums) {
+			return true, product.Name
+		}
+	}
+	return false, ""
+}

+ 4 - 41
go/gopath/src/fohow.com/apps/controllers/pay_controller/recharge_controller.go

@@ -4,7 +4,7 @@ import (
 	"fmt"
 	"fohow.com/apps"
 	"fohow.com/apps/models/balance_model"
-	"fohow.com/apps/models/base_config"
+	"fohow.com/apps/models/sys_config"
 	"github.com/astaxie/beego"
 	"strings"
 )
@@ -14,7 +14,7 @@ func (self *PayController) CreateBalanceOrder() {
 
 	//校验兑换提货券数量,为正整数
 	//count, _ := self.GetInt64("count") //兑换数量
-	count := base_config.GetBuyCash()
+	count := sys_config.GetBuyCash()
 
 	if count <= 0 {
 		self.ReturnError(403, apps.RechargeCountWrong, "", nil)
@@ -37,8 +37,8 @@ func (self *PayController) CreateBalanceOrder() {
 		self.ReturnError(403, apps.PayWayNoMatch, "", nil)
 	}
 	tp := int64(0)
-	if count == base_config.GetBuyCash() {
-		tp = base_config.GetSendCash()
+	if count == sys_config.GetBuyCash() {
+		tp = sys_config.GetSendCash()
 	} else {
 		tp = count
 	}
@@ -49,43 +49,6 @@ func (self *PayController) CreateBalanceOrder() {
 	self.ServeJSON()
 }
 
-//添加提货券记录
-func recharge(wxUId, uId, c int64, rId string) {
-	source := balance_model.BALANCE_SOURCE_RECHARGE
-	item := balance_model.GetBalanceBySourceAndRId(source, rId)
-	if item != nil {
-		return
-	}
-	b := new(balance_model.Balance).Create(wxUId, uId, c, source, rId, fmt.Sprintf("¥%0.2f", float64(c)/100))
-	if b != nil {
-		go rechargeNotice(uId, b)
-	}
-}
-
-//提货券充值成功通知
-func rechargeNotice(uId int64, balance *balance_model.Balance) {
-	//user := user_model.GetUserById(uId, false)
-	//openId := user.GetOpenid()
-	//if openId == "" {
-	//	beego.BeeLogger.Error("Recharge notice, didn't get openId of user:[%s]", user.Tel)
-	//	return
-	//}
-	/*url := ""
-	if beego.AppConfig.String("RunMode") == "prod" {
-		// url = "http://api.d5c360.com/v1/cfc/25"
-		url = fmt.Sprintf("%s/v1/cfc/25", beego.AppConfig.String("ApiHost"))
-	} else {
-		url = fmt.Sprintf("%s/user/balance", beego.AppConfig.String("MHost"))
-	}
-	title := "成功充值到账, 快去选购众筹项目吧!\n"
-	amount := fmt.Sprintf("%0.2f 元", float64(balance.Count)/100)
-	account := user.Tel
-	rechargeType := "线上充值"
-	cTime := balance.CreatedAt.Format("2006-01-02 15:04:05")
-	remark := "\n点击可查看交易明细>"
-	beego.BeeLogger.Warn("Recharge notice to user:[%s], openId:[%s], amount:[%s]", user.RealName, openId, amount)*/
-}
-
 //余额充值订单
 func (self *PayController) CreateRechargeCashOrder() {
 

+ 153 - 498
go/gopath/src/fohow.com/apps/controllers/permit_controller/permit_controller.go

@@ -1,8 +1,12 @@
 package permit_controller
 
 import (
+	"crypto/md5"
+	"encoding/hex"
 	"fmt"
-	"strconv"
+	"fohow.com/apps/models/token_model"
+	"fohow.com/libs/lib_redis"
+	"fohow.com/libs/tool"
 
 	// "math/rand"
 	// "crypto/md5"
@@ -23,13 +27,12 @@ import (
 	// "fohow.com/apps/models/order_model"
 	// "fohow.com/apps/models/product_model"
 	// "fohow.com/apps/models/shop_model"
-	// "fohow.com/apps/models/sms_model"
+	"fohow.com/apps/models/sms_model"
 	"fohow.com/apps/models/user_model"
 	// "fohow.com/apps/models/wx_gongzhonghao_model"
 	"fohow.com/cache"
 	// "fohow.com/libs/tool"
 	"fohow.com/libs/wx_mp"
-	// "fohow.com/libs/wx_open"
 )
 
 var (
@@ -51,11 +54,8 @@ func (self *PermitController) Init(ctx *context.Context, controllerName, actionN
 //小程序授权
 func (self *PermitController) XcxAuthorize() {
 	params := self.GetString("userinfo")
-	channel, _ := self.GetInt64("channel", 0)
-	// beego.BeeLogger.Warn("XcxAuthorize userinfo: %s", params)
-	inviteId, _ := self.GetInt64("invite_id", 0)
-	first := false
-	beego.BeeLogger.Warn("XcxAuthorize inviteId: %d", inviteId)
+	cache, _ := self.GetBool("cache", false)
+	//beego.BeeLogger.Warn("XcxAuthorize inviteId: %d", inviteId)
 	type UserInfo struct {
 		NickName  string `json:"nickName"`  // 用户的昵称
 		Gender    int64  `json:"gender"`    // 用户的性别, 值为1时是男性, 值为2时是女性, 值为0时是未知
@@ -72,7 +72,9 @@ func (self *PermitController) XcxAuthorize() {
 		Iv            string    `json:"iv"`
 		EncryptedData string    `json:"encryptedData"`
 		UserInfo      *UserInfo `json:"userInfo"`
+		Wxlogincode   string    `json:"wxlogincode"`
 	}
+
 	info := new(Info)
 	err := json.Unmarshal([]byte(params), &info)
 
@@ -80,56 +82,74 @@ func (self *PermitController) XcxAuthorize() {
 		beego.BeeLogger.Error("XcxAuthorize err: %s, info:%s", err, info)
 		self.ReturnError(403, apps.ParamsError, "", nil)
 	}
-
-	sessionKey, _ := self.GetSession(apps.XcxSessionKey).(string)
-	// beego.BeeLogger.Warn("sessionKey:%s", sessionKey)
-	type EncryptedData struct {
-		UnionId string `json:"unionId"`
-		OpenId  string `json:"openId"`
+	wxUser := self.GetCurrentWxUser(cache)
+	user := self.GetCurrentUser(cache)
+	if wxUser == nil {
+		self.ReturnError(401, apps.WxUserNotExist, "", nil)
 	}
+	//更新用户信息
+	wxUser.Nickname = info.UserInfo.NickName
+	wxUser.Sex = info.UserInfo.Gender
+	wxUser.City = info.UserInfo.City
+	wxUser.Province = info.UserInfo.Province
+	wxUser.Country = info.UserInfo.Country
+	wxUser.Save()
+	user.Nickname = wxUser.Nickname
+	user.Country = wxUser.Country
+	user.Province = wxUser.Province
+	user.City = wxUser.City
+	user.Sex = wxUser.Sex
+	user.Save()
+
+	beego.BeeLogger.Warn("XcxAuthorize wxUser after save() Nickname:%s, Sex:%s, City:%s, Province:%s, Country:%s ", wxUser.Nickname, wxUser.Sex, wxUser.City, wxUser.Province, wxUser.Country)
 
-	if sessionKey == "" {
-		self.ReturnError(403, apps.UserNeedLogin, "", nil)
+	// 如果微信用户已绑定手机,则找出userId,并且赋值给session[userId]
+	if wxUser != nil {
+		wxUser.UploadHead(info.UserInfo.AvatarUrl)
+		user.CopyWxUserHead(wxUser.Head)
 	}
+	type Ret struct {
+		Result bool               `json:"result"`
+		WxUser *user_model.WxUser `json:"wx_user"`
+	}
+	self.Data["json"] = &Ret{WxUser: wxUser, Result: true}
+	self.ServeJSON()
+}
 
-	pc := helpers.WxBizDataCrypt{AppID: beego.AppConfig.String("WxFohowXcxAppId"), SessionKey: sessionKey}
-	// beego.BeeLogger.Warn("EncryptedData:%s", info.EncryptedData)
-	// beego.BeeLogger.Warn("Iv:%s", info.Iv)
-	result, err := pc.Decrypt(info.EncryptedData, info.Iv, true) //第三个参数解释: 需要返回 JSON 数据类型时 使用 true, 需要返回 map 数据类型时 使用 false
-	if err != nil {
-		beego.BeeLogger.Error("xcx XcxAuthorize descrypt failed, err:%s", err)
-		self.ReturnError(403, apps.XcxAuthorizeError, "", nil)
+//小程序登录
+func (self *PermitController) XcxLogin() {
+	code := self.GetString("code")
+	inviteId, _ := self.GetInt64("invite_id", 0)
+	//beego.BeeLogger.Warn("XcxLogin code=%s", code)
+	if code == "" {
+		self.ReturnError(403, apps.ParamsRequired, "", nil)
 	}
-	encryptedData := &EncryptedData{}
-	json.Unmarshal([]byte(result.(string)), encryptedData)
-	if encryptedData.UnionId == "" || encryptedData.OpenId == "" {
-		self.ReturnError(403, apps.UserAuthorizeFailed, "", nil)
+	appId := beego.AppConfig.String("WxFohowXcxAppId")
+	appSecret := beego.AppConfig.String("WxFohowXcxAppSecret")
+	key := wx_mp.GetXcxSessionKey(appId, appSecret, code)
+	if key == nil {
+		self.ReturnError(403, apps.XcxGetSessionKeyError, "", nil)
 	}
-	wxUser := user_model.GetWxUserByUnionid(encryptedData.UnionId, false)
-	ip := self.Ctx.Input.IP()
-	var user *user_model.User
-	if wxUser != nil && wxUser.UserId > 0 {
-		//查找已注册会员
-		user = user_model.GetUserById(wxUser.UserId, false)
+	//beego.BeeLogger.Warn("XcxLogin key=%s", key)
+	wxUser := user_model.GetWxUserByUnionid(key.Unionid, false)
+	if wxUser != nil {
+		if len(wxUser.Head) > 0 {
+			wxUser.FullHead = self.GetFullImgUrl(wxUser.Head)
+		}
 	} else {
 		//注册会员
+		ip := self.Ctx.Input.IP()
+		var user *user_model.User
+		//注册会员
 		user = user_model.Create("", ip)
-	}
-	if user == nil {
-		self.ReturnError(403, apps.RegisterUserError, "", nil)
-	}
 
-	if wxUser != nil {
-		wxUser.Openid = encryptedData.OpenId
-	} else {
-		//首次授权
-		first = true
+		//注册微信会员
 		introUserId := int64(1)
 		depart := int64(0)
 		if inviteId == int64(0) {
 			inviteId = int64(1)
 		}
-		beego.BeeLogger.Warn("XcxAuthorize_quickCreate_inviteId:%d", inviteId)
+		//beego.BeeLogger.Warn("XcxAuthorize_quickCreate_inviteId:%d", inviteId)
 		inviter := user_model.GetWxUserById(inviteId, false)
 		if inviter != nil {
 			if inviter.ShowInviteMode == 1 && inviteId != int64(1) {
@@ -140,51 +160,30 @@ func (self *PermitController) XcxAuthorize() {
 			}
 			depart = inviter.Depart
 		}
-		wxUser = new(user_model.WxUser).QuickCreate(encryptedData.OpenId, encryptedData.UnionId, ip, channel, time.Now().Unix(), user.Id, inviteId, introUserId, depart)
-	}
-	user.Nickname = wxUser.Nickname
-	user.Country = wxUser.Country
-	user.Province = wxUser.Province
-	user.City = wxUser.City
-	user.Sex = wxUser.Sex
-	//参数第一,cookie第二
-	cId, _ := strconv.ParseInt(self.Ctx.GetCookie("sign_up_channel"), 10, 64)
-	user.SignupChannelId = cId
-	user.Save()
-	if user != nil {
-		self.SetSession(apps.SessionUserKey, user.Id)
+		wxUser = new(user_model.WxUser).QuickCreate(key.Openid, key.Unionid, ip, user.Id, inviteId, introUserId, depart)
+		//赠送积分
+		go helpers.SendCent(wxUser.Id, inviteId)
 	}
-	//wxUser.UserId = user.Id
-	wxUser.Nickname = info.UserInfo.NickName
-	wxUser.Sex = info.UserInfo.Gender
-	wxUser.City = info.UserInfo.City
-	wxUser.Province = info.UserInfo.Province
-	wxUser.Country = info.UserInfo.Country
-	// beego.BeeLogger.Warn("XcxAuthorize wxUser before save() Nickname:%s, Sex:%s, City:%s, Province:%s, Country:%s ", wxUser.Nickname, wxUser.Sex, wxUser.City, wxUser.Province, wxUser.Country)
-	wxUser.Save()
-	beego.BeeLogger.Warn("XcxAuthorize wxUser after save() Nickname:%s, Sex:%s, City:%s, Province:%s, Country:%s ", wxUser.Nickname, wxUser.Sex, wxUser.City, wxUser.Province, wxUser.Country)
+	//self.SetSession(apps.XcxSessionKey, key.SessionKey)
+	sessionKey := lib_redis.GetKeySessionKey(wxUser.Id)
+	lib_redis.SetRedisValue(sessionKey, key.SessionKey, time.Hour*10)
 
-	if wxUser != nil {
-		self.SetSession(apps.SessionWxUserKey, wxUser.Id)
-	}
-	//赠送积分
-	if first {
-		//go wxUser.UploadHead(info.UserInfo.AvatarUrl)
-		wxUser.UploadHead(info.UserInfo.AvatarUrl)
-		go user.XcxPermitUploadHead(info.UserInfo.AvatarUrl)
-		go helpers.SendCent(wxUser.Id, inviteId)
+	//更新会员token
+	var jwtUser token_model.JwtUser
+	jwtUser.Id = wxUser.Id
+	token, err := token_model.GenerateToken(&jwtUser, 0)
+	if err != nil {
+		self.ReturnError(401, apps.TokenError, "", nil)
 	}
-	// 如果微信用户已绑定手机,则找出userId,并且赋值给session[userId]
-	if wxUser != nil && wxUser.UserId > 0 {
-		user := user_model.GetUserById(wxUser.UserId, false)
-		user.CopyWxUserHead(wxUser.Head)
-		self.SetSession(apps.SessionUserKey, wxUser.UserId)
+	type Ret struct {
+		TokenKey string             `json:"token"`
+		WxUser   *user_model.WxUser `json:"wx_user"`
 	}
-	self.Data["json"] = encryptedData
+	self.Data["json"] = &Ret{WxUser: wxUser, TokenKey: token}
 	self.ServeJSON()
 }
 
-//小程序授权
+//小程序再次保存用户头像
 func (self *PermitController) SaveWxuserInfo() {
 	params := self.GetString("userinfo")
 	type UserInfo struct {
@@ -196,140 +195,57 @@ func (self *PermitController) SaveWxuserInfo() {
 		Country   string `json:"country"`   // 用户所在国家
 		AvatarUrl string `json:"avatarUrl"` // 头像
 	}
-	type Info struct {
-		ErrMsg        string    `json:"errMsg"`
-		RawData       string    `json:"rawData"`
-		Signature     string    `json:"signature"`
-		Iv            string    `json:"iv"`
-		EncryptedData string    `json:"encryptedData"`
-		UserInfo      *UserInfo `json:"userInfo"`
+	if len(params) <= 0 {
+		self.ReturnError(403, apps.ParamsError, "", nil)
 	}
-	info := new(Info)
+
+	info := new(UserInfo)
 	err := json.Unmarshal([]byte(params), &info)
 
 	if err != nil {
-		beego.BeeLogger.Error("XcxAuthorize err: %s, info:%s", err, info)
+		beego.BeeLogger.Info("SaveWxuserInfo info:%s", info)
 		self.ReturnError(403, apps.ParamsError, "", nil)
 	}
 
-	sessionKey, _ := self.GetSession(apps.XcxSessionKey).(string)
-	// beego.BeeLogger.Warn("sessionKey:%s", sessionKey)
-	type EncryptedData struct {
-		UnionId string `json:"unionId"`
-		OpenId  string `json:"openId"`
-	}
-
-	if sessionKey == "" {
-		self.ReturnError(403, apps.UserNeedLogin, "", nil)
-	}
-
-	pc := helpers.WxBizDataCrypt{AppID: beego.AppConfig.String("WxFohowXcxAppId"), SessionKey: sessionKey}
-	// beego.BeeLogger.Warn("EncryptedData:%s", info.EncryptedData)
-	// beego.BeeLogger.Warn("Iv:%s", info.Iv)
-	result, err := pc.Decrypt(info.EncryptedData, info.Iv, true) //第三个参数解释: 需要返回 JSON 数据类型时 使用 true, 需要返回 map 数据类型时 使用 false
-	if err != nil {
-		beego.BeeLogger.Error("xcx XcxAuthorize descrypt failed, err:%s", err)
-		self.ReturnError(403, apps.XcxAuthorizeError, "", nil)
-	}
-	encryptedData := &EncryptedData{}
-	json.Unmarshal([]byte(result.(string)), encryptedData)
-	if encryptedData.UnionId == "" || encryptedData.OpenId == "" {
-		self.ReturnError(403, apps.UserAuthorizeFailed, "", nil)
-	}
+	wxUId := self.GetCurrentWxUserIdByToken()
+	beego.BeeLogger.Info("SaveWxuserInfo wxUId:%d", wxUId)
 
-	wxUser := user_model.GetWxUserByUnionid(encryptedData.UnionId, false)
+	wxUser := user_model.GetWxUserById(wxUId, true)
 	if wxUser == nil {
 		self.ReturnError(403, apps.WxUserInfoError, "", nil)
 	}
+	headPath := wxUser.UploadHead(info.AvatarUrl)
 
-	beego.BeeLogger.Warn("SaveWxuserInfo ")
-	wxUser.UploadHead(info.UserInfo.AvatarUrl)
-	type Ret struct {
-		Result bool `json:"result"`
-	}
-
-	self.Data["json"] = &Ret{Result: true}
-	self.ServeJSON()
-}
-
-//小程序登录
-func (self *PermitController) XcxLogin() {
-	code := self.GetString("code")
-	if code == "" {
-		self.ReturnError(403, apps.ParamsRequired, "", nil)
-	}
-	appId := beego.AppConfig.String("WxFohowXcxAppId")
-	appSecret := beego.AppConfig.String("WxFohowXcxAppSecret")
-	key := wx_mp.GetXcxSessionKey(appId, appSecret, code)
-	if key == nil {
-		self.ReturnError(403, apps.XcxGetSessionKeyError, "", nil)
-	}
-	// beego.BeeLogger.Warn("XcxLogin key=%s", key)
-	// beego.BeeLogger.Warn("XcxLogin key=%s, key.Openid=%s", key, key.Openid)
-	wxUser := user_model.GetByOpenid(key.Openid, false)
-	// beego.BeeLogger.Warn("XcxLogin key=[%s], key.Openid=[%s], wxUser= [%s]", key, key.Openid, wxUser)
-
-	if wxUser != nil {
-		wxUser.FullHead = self.GetFullImgUrl(wxUser.Head)
-		self.SetSession(apps.SessionWxUserKey, wxUser.Id)
-	}
-
-	// 如果微信用户已绑定手机,则找出userId,并且赋值给session[userId]
-	if wxUser != nil && wxUser.UserId > 0 {
-		self.SetSession(apps.SessionUserKey, wxUser.UserId)
-	}
+	//更新用户信息
+	wxUser.Nickname = info.NickName
+	wxUser.Sex = info.Gender
+	wxUser.City = info.City
+	wxUser.Province = info.Province
+	wxUser.Country = info.Country
+	wxUser.Save()
 
-	self.SetSession(apps.XcxSessionKey, key.SessionKey)
-	// beego.BeeLogger.Warn("XcxLogin SessionKey=%s", key.SessionKey)
-	if self.CruSession == nil {
-		self.ReturnError(200, apps.NoExist, "", nil)
-	}
-	sId := self.CruSession.SessionID()
-	// beego.BeeLogger.Warn("XcxLogin sId=%s", sId)
+	user := user_model.GetUserById(wxUser.UserId, true)
+	if user != nil {
+		user.Nickname = wxUser.Nickname
+		user.Country = wxUser.Country
+		user.Province = wxUser.Province
+		user.City = wxUser.City
+		user.Sex = wxUser.Sex
+		user.Save()
+		go user.CopyWxUserHead(wxUser.Head)
+	}
+	//消除user,wxuser缓存
+	go wxUser.CleanCache()
+	headImag := tool.GetCdnFullImgUrl(headPath)
+	//beego.BeeLogger.Info("save_wx_user_info err: %v ", wxUser)
 	type Ret struct {
-		SessionKey string             `json:"session_key"`
-		WxUser     *user_model.WxUser `json:"wx_user"`
+		Result bool   `json:"result"`
+		Head   string `json:"head"`
 	}
-	self.Data["json"] = &Ret{SessionKey: sId, WxUser: wxUser}
-
+	self.Data["json"] = &Ret{Result: true, Head: headImag}
 	self.ServeJSON()
 }
 
-//生成订单ID
-func createUnionId(prefix string) string {
-	n := time.Now().Format("20060102150405")
-	u := uuid.NewV4().String()
-	c := strings.Split(u, "-")
-	oId := strings.ToUpper(fmt.Sprintf("%s%s%s", prefix, n, c[0]))
-	beego.BeeLogger.Info("createUnionId=%s", oId)
-	return oId
-}
-
-func (self *PermitController) XcxTest() {
-	wxUser := self.GetCurrentWxUser(true)
-	self.Data["json"] = wxUser
-	self.ServeJSON()
-}
-
-// // 统一登录路径
-// // 该接口尽量不被前端调用,供服务器开发者使用
-// func (self *PermitController) Login() {
-// 	cb := self.GetString("cb")
-// 	url := ""
-// 	if self.IsWxClient() {
-// 		url = fmt.Sprintf("%s/login/mp?cb=%s", beego.AppConfig.String("ApiHost"), cb)
-// 	}
-// 	self.Redirect(url, 302)
-// 	return
-// }
-
-// // 退出登录
-// func (self *PermitController) Logout() {
-// 	self.DelSession(apps.SessionUserKey)
-// 	self.DelSession(apps.SessionWxUserKey)
-// 	self.ReturnError(200, apps.HasLogout, "", nil)
-// }
-
 //公众号静默授权回调
 func (self *PermitController) AfterWxMpAuth() {
 	// beego.BeeLogger.Warn("AfterWxMpAuth........")
@@ -377,52 +293,6 @@ func (self *PermitController) AfterWxMpAuth() {
 	self.ServeJSON()
 }
 
-// //公众号静默授权
-// func (self *PermitController) WxMpAuth() {
-// 	// beego.BeeLogger.Warn("WxMpAuth.......")
-// 	if !self.IsWxClient() {
-// 		self.ReturnError(403, apps.NotWeixinClient, "", nil)
-// 	}
-// 	_id := self.Ctx.Input.Param(":id")
-// 	cb := self.GetString("cb")
-// 	id, _ := strconv.ParseInt(_id, 10, 64)
-// 	gzh := wx_gongzhonghao_model.GetGZHById(id, true)
-// 	if gzh == nil {
-// 		self.ReturnError(403, apps.GongZhongHaoNoExist, "", nil)
-// 	}
-// 	appId := gzh.AppId
-// 	u := strings.Split(uuid.NewV4().String(), "-")[0]
-// 	state := fmt.Sprintf("AuthCb[%s]", u)
-// 	cache.Cache.Put(state, cb, 60*time.Second)
-// 	redirectURI := fmt.Sprintf("%s/auth/mp/%d/after",
-// 		beego.AppConfig.String("ApiHost"), gzh.Id)
-// 	scope := "snsapi_base"
-// 	url := wx_mp.AuthCodeURL(appId, redirectURI, scope, state)
-// 	// beego.BeeLogger.Warn("wx mp auth, redirect url: %s", url)
-// 	self.Redirect(url, 302)
-// }
-
-// //check是否授权过某个公众号
-// func (self *PermitController) CheckWxAuth() {
-// 	_gId := self.Ctx.Input.Param(":id")
-// 	gId, _ := strconv.ParseInt(_gId, 10, 64)
-// 	gzh := wx_gongzhonghao_model.GetGZHById(gId, true)
-// 	type Ret struct {
-// 		IsAuth int64 `json:"is_auth"`
-// 	}
-// 	var auth int64 = 0
-// 	wxUser := self.GetCurrentWxUser(true)
-// 	if gzh != nil {
-// 		authWxUser := user_model.GetAuthWxUserByMpIdAndUnionId(gzh.WxHao, wxUser.Unionid, false)
-// 		if authWxUser != nil {
-// 			auth = 1
-// 		}
-// 	}
-// 	// beego.BeeLogger.Warn("check auth: %v", auth)
-// 	self.Data["json"] = &Ret{IsAuth: auth}
-// 	self.ServeJSON()
-// }
-
 // 微信公众号平台登录
 func (self *PermitController) WxMpLogin() {
 	cb := self.GetString("cb")
@@ -524,15 +394,7 @@ func (self *PermitController) AfterWxMpLogin() {
 		wxUserGzh.GzhOpenId = mpOpenid
 		go wxUserGzh.UpdateField("GzhOpenId")
 	}
-	if wxUser != nil {
-		self.SetSession(apps.SessionWxUserKey, wxUser.Id)
-	}
 
-	// 如果微信用户已绑定手机,则找出userId,并且赋值给session[userId]
-	if wxUser != nil && wxUser.UserId > 0 {
-		self.SetSession(apps.SessionUserKey, wxUser.UserId)
-		// beego.BeeLogger.Warn("AfterWxAutoLogin, wxUser.UserId=%d", wxUser.UserId)
-	}
 	if cbUrl, ok := cache.Cache.Get(state).(string); ok {
 		if cbUrl == "" {
 			self.Redirect(beego.AppConfig.String("WxHost"), 302)
@@ -701,250 +563,43 @@ func (self *PermitController) Logout() {
 	self.ReturnError(200, apps.HasLogout, "", nil)
 }
 
-// // 微信开放平台登录
-// func (self *PermitController) WxOpenLogin() {
-// 	cb := self.GetString("cb")
-// 	u := strings.Split(uuid.NewV4().String(), "-")[0]
-// 	state := fmt.Sprintf("loginCb[%s]", u)
-// 	cache.Cache.Put(state, cb, 60*time.Second)
-// 	appId := beego.AppConfig.String("WxOpenAppId")
-// 	redirectURI := fmt.Sprintf("%s/login/open/after",
-// 		beego.AppConfig.String("ApiHost"))
-// 	url := wx_open.AuthCodeURL(appId, redirectURI, "snsapi_login", state)
-// 	self.Redirect(url, 302)
-// 	return
-// }
-
-// //微信开放平台登录
-// func (self *PermitController) AfterWxOpenLogin() {
-// 	scope := "snsapi_login"
-// 	code := self.GetString("code")
-// 	state := self.GetString("state")
-// 	a := beego.AppConfig.String("WxOpenAppId")
-// 	s := beego.AppConfig.String("WxOpenAppSecret")
-// 	redirectURI := fmt.Sprintf("%s/after_wx_open_login",
-// 		beego.AppConfig.String("ApiHost"))
-// 	token, err := wx_open.AuthExchangeToken(code, a, s, redirectURI, scope)
-// 	if err != nil {
-// 		self.ReturnError(403, apps.NetworkBusy, "", nil)
-// 	}
-// 	openOpenid := token.OpenId
-// 	unionId := token.UnionId
-// 	// 这里不能取缓存数据,因为UserId这个字段在外部有可能已被赋值
-// 	wxUser := user_model.GetWxUserByUnionid(unionId, false)
-// 	if wxUser == nil {
-// 		info, err := wx_open.AuthUserInfo(token.AccessToken, redirectURI, scope, openOpenid, a, s)
-// 		if err == nil {
-// 			ip := self.Ctx.Input.IP()
-// 			wxUser = new(user_model.WxUser).Create("", openOpenid, token.UnionId, info.Nickname,
-// 				info.City, info.Country, info.Province, ip, int64(info.Sex), 1, time.Now().Unix())
-// 			//上传头像至alioss
-// 			go wxUser.UploadHead(info.HeadImageURL)
-// 		}
-// 	} else {
-// 		if wxUser.OpenOpenid != openOpenid {
-// 			wxUser.OpenOpenid = openOpenid
-// 			go wxUser.UpdateField("OpenOpenid")
-// 		}
-// 	}
-// 	self.SetSession(apps.SessionWxUserKey, wxUser.Id)
-// 	// 如果微信用户已绑定手机,则找出userId,并且赋值给session[userId]
-// 	if wxUser.UserId > 0 {
-// 		self.SetSession(apps.SessionUserKey, wxUser.UserId)
-// 	}
-// 	if cbUrl, ok := cache.Cache.Get(state).(string); ok {
-// 		if cbUrl == "" {
-// 			if wxUser.UserId <= 0 {
-// 				self.Redirect(fmt.Sprintf("%s/user/binding/state", beego.AppConfig.String("WWWHost")), 302)
-// 				return
-
-// 			}
-// 			self.Redirect(beego.AppConfig.String("WWWHost"), 302)
-// 			return
-// 		}
-// 		self.Redirect(cbUrl, 302)
-// 		return
-// 	} else {
-// 		self.Redirect(beego.AppConfig.String("WWWHost"), 302)
-// 		return
-// 	}
-// 	self.ReturnError(403, apps.NetworkBusy, "", nil)
-// }
-
-// //PC端手机号码登录
-// func (self *PermitController) TelLogin() {
-// 	//防止用户先登录微信user,未绑定手机,同时又使用tel登录,默认清除wxuser的session
-// 	self.DelSession(apps.SessionWxUserKey)
-
-// 	tel := self.GetString("tel")
-// 	pwd := self.GetString("pwd")
-
-// 	user := user_model.GetByTel(tel, false)
-// 	signUpURL := fmt.Sprintf("%s/v1/signup", beego.AppConfig.String("ApiHost"))
-// 	if user == nil {
-// 		self.ReturnError(403, apps.UserNotExist, signUpURL, nil)
-// 	}
-// 	md5Ctx := md5.New()
-// 	md5Ctx.Write([]byte(pwd))
-// 	cipherStr := md5Ctx.Sum(nil)
-// 	md5Pwd := hex.EncodeToString(cipherStr)
-
-// 	if user.Pwd != md5Pwd {
-// 		self.ReturnError(403, apps.LoginPasswordError, "", nil)
-// 	}
-// 	self.SetSession(apps.SessionUserKey, user.Id)
-// 	// 找出微信用户
-// 	wxUser := user_model.GetWxUserByUserId(user.Id, false)
-// 	if wxUser != nil {
-// 		self.SetSession(apps.SessionWxUserKey, wxUser.Id)
-// 	}
-// 	// self.Data["json"] = "ok"
-// 	self.ServeJSON()
-// }
-
-// //使用key登录,key通过GenerateLoginKey生成
-// func (self *PermitController) KeyLogin() {
-// 	//不支持微信端
-// 	if self.IsWxClient() {
-// 		self.ReturnError(403, apps.NoExist, "", nil)
-// 	}
-// 	key := self.Ctx.Input.Param(":key")
-// 	uId, _ := self.GetInt64("user_id")
-
-// 	if key == "" || uId == 0 {
-// 		self.ReturnError(403, apps.ParamsRequired, "", nil)
-// 	}
-
-// 	k := cache.GetKey(cache.WapAutoLoginKey, uId)
-// 	//校验key
-// 	if s, ok := cache.Cache.Get(k).(string); ok {
-// 		// beego.BeeLogger.Warn("11111111, k:%s, s: %s, key: %s, uId: %d", k, s, key, uId)
-// 		if s == key {
-// 			// self.DelSession(apps.SessionUserKey)
-// 			self.SetSession(apps.SessionUserKey, uId)
-// 			//销毁缓存
-// 			cache.Cache.Delete(k)
-// 		} else {
-// 			self.ReturnError(403, apps.NoExist, "", nil)
-// 		}
-// 	} else {
-// 		self.ReturnError(403, apps.NoExist, "", nil)
-// 	}
-
-// 	// self.Data["json"] = "ok"
-// 	self.ServeJSON()
-// }
-
-// //PC端注册
-// func (self *PermitController) SignUp() {
-// 	code := self.GetString("code")
-// 	tel := self.GetString("tel")
-// 	k := fmt.Sprintf("%s%s", sms_model.SIGN_UP, tel)
-// 	if cacheCode, ok := cache.Cache.Get(k).(string); ok {
-// 		if code != cacheCode {
-// 			self.ReturnError(403, apps.TelCodesError, "", nil)
-// 		}
-// 	} else {
-// 		//验证码过期
-// 		self.ReturnError(403, apps.TelCodesExpired, "", nil)
-// 	}
-
-// 	user := user_model.GetByTel(tel, false)
-// 	if user == nil {
-// 		loginPwd := tool.Get8Uuid()
-// 		md5Ctx := md5.New()
-// 		md5Ctx.Write([]byte(loginPwd))
-// 		cipherStr := md5Ctx.Sum(nil)
-// 		md5Pwd := hex.EncodeToString(cipherStr)
-// 		ip := self.Ctx.Input.IP()
-// 		user = user_model.Create(tel, md5Pwd, ip)
-// 		// 注册渠道处理
-// 		cId, _ := strconv.ParseInt(self.Ctx.GetCookie("sign_up_channel"), 10, 64)
-// 		channel := user_model.GetSignUpChannelById(cId, true)
-// 		if channel != nil {
-// 			user.SignupChannelId = cId
-// 			user.Save()
-// 			// wpsvip注册的用户,因为真功夫项目的,需要通知赠送稻米
-// 			if cId == 8 {
-// 				key1 := beego.AppConfig.String("CookieWpsVipUId")
-// 				key2 := beego.AppConfig.String("CookieWpsVipExtra")
-// 				wpsUserId, _ := strconv.ParseInt(self.Ctx.GetCookie(key1), 10, 64)
-// 				extra := self.Ctx.GetCookie(key2)
-// 				go wps.Reward(wpsUserId, extra, wps.OT_ZGF_ZHUC)
-// 				go wps_user_model.CreateWpsUser(wpsUserId, user.Id, 0, extra)
-// 			}
-// 		}
-// 		sign, template, action := sms_model.GetAliMsgContent(sms_model.LOGIN_PWD)
-// 		go sms_model.SendSmsWithAli([]string{tel}, sign, template, action, loginPwd)
-// 	} else {
-// 		self.ReturnError(403, apps.PhoneExist, "", nil)
-// 	}
-
-// 	self.SetSession(apps.SessionUserKey, user.Id)
-// 	//如果是体验金专题页面点击过来的,也送
-// 	key := beego.AppConfig.String("TYJName")
-// 	c := self.Ctx.GetCookie(key)
-
-// 	if c != "" {
-// 		id, err := strconv.ParseInt(c, 10, 64)
-// 		if err == nil {
-// 			trialInfo := trial_coin_model.GetTrialCoinById(id, true)
-// 			if trialInfo != nil && trialInfo.Deadline.Unix() >= time.Now().Unix() {
-// 				new(trial_coin_model.TrialCoinOrder).Create(user.Id, trialInfo.Id, trialInfo.Amount)
-// 			}
-// 		}
-// 	}
-
-// 	self.Data["json"] = user_model.User{Tel: tel}
-// 	self.ServeJSON()
-// }
-
-// //忘记密码
-// func (self *PermitController) ResetPwd() {
-// 	code := self.GetString("code")
-// 	tel := self.GetString("tel")
-// 	pwd := self.GetString("pwd")
-// 	confirmedPwd := self.GetString("confirmed_pwd")
-// 	if pwd != confirmedPwd {
-// 		self.ReturnError(403, apps.PasswordError, "", nil)
-// 	}
-
-// 	lengthPwd := len(pwd)
-// 	if lengthPwd < 6 || lengthPwd > 20 {
-// 		self.ReturnError(403, apps.PasswordLengthError, "", nil)
-// 	}
-
-// 	k := fmt.Sprintf("%s%s", sms_model.RESET_PWD, tel)
-// 	if cacheCode, ok := cache.Cache.Get(k).(string); ok {
-// 		if code != cacheCode {
-// 			self.ReturnError(403, apps.TelCodesError, "", nil)
-// 		}
-// 	} else {
-// 		//验证码过期
-// 		self.ReturnError(403, apps.TelCodesExpired, "", nil)
-// 	}
-// 	md5Ctx := md5.New()
-// 	md5Ctx.Write([]byte(pwd))
-// 	cipherStr := md5Ctx.Sum(nil)
-// 	md5Pwd := hex.EncodeToString(cipherStr)
-
-// 	user := user_model.GetByTel(tel, false)
-// 	if user == nil {
-// 		self.ReturnError(403, apps.UserNotExist, "", nil)
-// 	} else {
-// 		user.Pwd = md5Pwd
-// 		user.Save()
-// 	}
-
-// 	self.Data["json"] = user_model.User{Tel: tel}
-// 	self.ServeJSON()
-// }
-
-// func createXkUser(uid, openid string) {
-// 	if uid == "" || openid == "" {
-// 		return
-// 	}
-// 	url := fmt.Sprintf("http://api.xikego.com/v1/createwxuser/superd5c/%s/%s", uid, openid)
-// 	tool.PostJSON(url, nil)
-// 	return
-// }
+//忘记密码
+func (self *PermitController) ResetPwd() {
+	code := self.GetString("code")
+	tel := self.GetString("tel")
+	pwd := self.GetString("pwd")
+	confirmedPwd := self.GetString("confirmed_pwd")
+	if pwd != confirmedPwd {
+		self.ReturnError(403, apps.PasswordError, "", nil)
+	}
+
+	lengthPwd := len(pwd)
+	if lengthPwd < 6 || lengthPwd > 20 {
+		self.ReturnError(403, apps.PasswordLengthError, "", nil)
+	}
+
+	k := fmt.Sprintf("%s%s", sms_model.RESET_PWD, tel)
+	if cacheCode, ok := cache.Cache.Get(k).(string); ok {
+		if code != cacheCode {
+			self.ReturnError(403, apps.TelCodesError, "", nil)
+		}
+	} else {
+		//验证码过期
+		self.ReturnError(403, apps.TelCodesExpired, "", nil)
+	}
+	md5Ctx := md5.New()
+	md5Ctx.Write([]byte(pwd))
+	cipherStr := md5Ctx.Sum(nil)
+	md5Pwd := hex.EncodeToString(cipherStr)
+
+	user := user_model.GetByTel(tel, false)
+	if user == nil {
+		self.ReturnError(403, apps.UserNotExist, "", nil)
+	} else {
+		user.Pwd = md5Pwd
+		user.Save()
+	}
+
+	self.Data["json"] = user_model.User{Tel: tel}
+	self.ServeJSON()
+}

+ 175 - 0
go/gopath/src/fohow.com/apps/controllers/pick_address_controller/pick_address_controller.go

@@ -0,0 +1,175 @@
+package pick_address_controller
+
+import (
+	"fohow.com/apps/models/user_model"
+	"strconv"
+
+	"fohow.com/apps"
+	"github.com/astaxie/beego/context"
+
+	"fohow.com/apps/models/address_model"
+)
+
+var (
+	//不需要校验登录的Action
+	exceptCheckUserLoginAction   = []string{"List", "DefaultPickAddress", "CreatePickAddress", "UpdatePickAddress", "DeletePickAddress", "SetDefault"}
+	exceptCheckWxUserLoginAction = []string{}
+)
+
+type PickAddressController struct {
+	apps.BaseController
+}
+
+func (self *PickAddressController) Init(ctx *context.Context, controllerName, actionName string, app interface{}) {
+	self.BaseController.Init(ctx, controllerName, actionName, app)
+	self.ExceptCheckUserLoginAction = exceptCheckUserLoginAction
+	self.ExceptCheckWxUserLoginAction = exceptCheckWxUserLoginAction
+}
+
+//获取用户地址列表
+func (self *PickAddressController) List() {
+	sort := self.GetString("sort")
+	if sort == "" {
+		sort = "created_at"
+	}
+	//uId := self.GetCurrentUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
+	pic_addresses := address_model.GetUserPickAddressList(wxUId, sort)
+	self.Data["json"] = pic_addresses
+	self.ServeJSON()
+}
+
+//取默认地址
+func (self *PickAddressController) DefaultPickAddress() {
+	//uId := self.GetCurrentUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
+	pic_address := address_model.GetUserDefaultPickAddress(wxUId)
+	self.Data["json"] = pic_address
+	self.ServeJSON()
+}
+
+func (self *PickAddressController) CreatePickAddress() {
+	contact := self.GetString("contact")
+	tel := self.GetString("tel")
+	setDefault, _ := self.GetInt64("set_default")
+
+	if len(tel) != 11 {
+		self.ReturnError(404, apps.PhoneInvalid, "", nil)
+	}
+	if contact == "" || tel == "" {
+		self.ReturnError(404, apps.ParamsRequired, "", nil)
+	}
+	uId := self.GetCurrentUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
+
+	pic_addresses := address_model.GetPickAddressesByWxUId(wxUId)
+	/*	if len(pic_addresses) >= 5 {
+		self.ReturnError(404, apps.UserPickAddressFull, "", nil)
+	}*/
+
+	//无默认地址的情况下,新增的地址为默认地址
+	hasDefaultAddr := false
+	for _, item := range pic_addresses {
+		if item.State == 1 {
+			hasDefaultAddr = true
+			break
+		}
+	}
+
+	item := address_model.CreatePickAddress(wxUId, uId, contact, tel, "")
+	if (setDefault == 1 || !hasDefaultAddr) && item != nil {
+		item.SetDefault()
+		item.State = 1
+	}
+	self.Data["json"] = item
+	self.ServeJSON()
+}
+
+func (self *PickAddressController) UpdatePickAddress() {
+	_id := self.Ctx.Input.Param(":id")
+	id, _ := strconv.ParseInt(_id, 10, 64)
+	item := address_model.GetUserPickAddressById(id)
+	//uId := self.GetCurrentUserId()
+	//if item.UserId != uId {
+	//	self.ReturnError(404, apps.NoExist, "", nil)
+	//}
+	wxUId := self.GetCurrentWxUserIdByToken()
+	if item.WxUserId != wxUId {
+		self.ReturnError(404, apps.NoExist, "", nil)
+	}
+	contact := self.GetString("contact")
+	tel := self.GetString("tel")
+	setDefault, _ := self.GetInt64("set_default")
+
+	if len(tel) != 11 {
+		self.ReturnError(404, apps.ParamsError, "", nil)
+	}
+	if contact == "" || tel == "" {
+		self.ReturnError(404, apps.ParamsRequired, "", nil)
+	}
+	item = item.Update(contact, tel, "")
+
+	if setDefault == 1 {
+		item.SetDefault()
+		item.State = 1
+	}
+
+	self.Data["json"] = item
+	self.ServeJSON()
+}
+
+func (self *PickAddressController) DeletePickAddress() {
+	_id := self.Ctx.Input.Param(":id")
+	id, _ := strconv.ParseInt(_id, 10, 64)
+	item := address_model.GetUserPickAddressById(id)
+	//uId := self.GetCurrentUserId()
+	//if item.UserId != uId {
+	//	self.ReturnError(403, apps.PickAddressNotMatch, "", nil)
+	//}
+	wxUId := self.GetCurrentWxUserIdByToken()
+	if item.WxUserId != wxUId {
+		self.ReturnError(404, apps.NoExist, "", nil)
+	}
+	//如果删除的是默认地址,设置一个默认地址
+	if item.State == 1 {
+		allPickAddress := address_model.GetUserPickAddressList(wxUId, "id")
+		for _, pic_address := range allPickAddress {
+			if pic_address.State == 0 {
+				pic_address.State = 1
+				pic_address.Save()
+				break
+			}
+		}
+	}
+	go item.Delete()
+	self.ServeJSON()
+}
+
+func (self *PickAddressController) SetDefault() {
+	_id := self.Ctx.Input.Param(":id")
+	id, _ := strconv.ParseInt(_id, 10, 64)
+	//uId := self.GetCurrentUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
+	pic_address := address_model.GetPickAddressByWxUIdAndId(wxUId, id)
+
+	if pic_address != nil {
+		pic_address.SetDefault()
+		pic_address.State = 1
+	} else {
+		self.ReturnError(404, apps.NoExist, "", nil)
+	}
+
+	self.Data["json"] = pic_address
+	self.ServeJSON()
+}
+
+//获取用户地址列表
+func (self *PickAddressController) PickDepartList() {
+	sort := self.GetString("sort")
+	if sort == "" {
+		sort = "created_at"
+	}
+	pic_departs := user_model.GetPickDepartList(sort)
+	self.Data["json"] = pic_departs
+	self.ServeJSON()
+}

+ 4 - 4
go/gopath/src/fohow.com/apps/controllers/poster_controller/poster_controller.go

@@ -35,7 +35,7 @@ func GetCdnFullImgUrl(img string) string {
 	}
 }
 
-var DEFAULT_HEAD string = "xcx/poster/default_head.png"
+var DEFAULT_HEAD = "xcx/poster/default_head.png"
 
 func (self *PosterController) Init(ctx *context.Context, controllerName, actionName string, app interface{}) {
 	self.BaseController.Init(ctx, controllerName, actionName, app)
@@ -51,7 +51,7 @@ func (self *PosterController) GetPosterXcxQrcode() {
 	id, _ := strconv.ParseInt(_id, 10, 64)
 	useCache, _ := self.GetBool("cache", false)
 
-	wxUid := self.GetCurrentWxUserId()
+	wxUid := self.GetCurrentWxUserIdByToken()
 
 	posterQrcodeRecord := poster_model.GetPosterQrcodeRecordByWIdAndTypeAndRId(wxUid, id, _type, useCache)
 
@@ -115,7 +115,7 @@ func (self *PosterController) UpdatePosterXcxQrcode() {
 	id, _ := strconv.ParseInt(_id, 10, 64)
 	useCache, _ := self.GetBool("cache", false)
 
-	wxUid := self.GetCurrentWxUserId()
+	wxUid := self.GetCurrentWxUserIdByToken()
 
 	posterQrcodeRecord := poster_model.GetPosterQrcodeRecordByWIdAndTypeAndRId(wxUid, id, _type, useCache)
 
@@ -224,7 +224,7 @@ func (self *PosterController) ScanPosterXcxQrcode() {
 	posterQrcodeRecord.ScanTimes = posterQrcodeRecord.ScanTimes + 1
 	posterQrcodeRecord.Save()
 
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 	scanRecord := poster_model.GetPosterQrcodeRecordByWxUId(posterQrcodeRecord.Id, wxUId)
 	if scanRecord == nil {
 		go new(poster_model.PosterQrcodeScanRecord).Create(posterQrcodeRecord.Id, wxUId, self.Ctx.Input.IP())

+ 2 - 2
go/gopath/src/fohow.com/apps/controllers/product_controller/init.go

@@ -16,8 +16,8 @@ import (
 
 var (
 	//需要校验用户登录的Action
-	exceptCheckUserLoginAction   = []string{"GetPdDetail", "GetProductSizesByPid", "Latest", "Get", "Categories", "GetProductsByCat", "GetNeedShare"}
-	exceptCheckWxUserLoginAction = []string{"GetPdDetail", "GetProductSizesByPid", "Latest", "Get", "Categories", "GetProductsByCat"}
+	exceptCheckUserLoginAction   = []string{"GetProductsCommends", "GetPdDetail", "GetProductSizesByPid", "Latest", "Get", "Categories", "GetProductsByCat", "GetNeedShare", "GetCommendWords"}
+	exceptCheckWxUserLoginAction = []string{"GetProductsCommends", "GetPdDetail", "GetProductSizesByPid", "Latest", "Get", "Categories", "GetProductsByCat", "GetCommendWords"}
 )
 
 type ProductController struct {

+ 190 - 12
go/gopath/src/fohow.com/apps/controllers/product_controller/product_controller.go

@@ -1,6 +1,8 @@
 package product_controller
 
 import (
+	"fmt"
+	"fohow.com/apps/models/user_model"
 	// "fmt"
 	"strconv"
 	"strings"
@@ -22,6 +24,8 @@ func (self *ProductController) Latest() {
 	perPage, _ := self.GetInt64("per_page")
 	cache, _ := self.GetBool("cache", false)
 	ptype := self.GetString("ptype")
+	price_sort, _ := self.GetInt64("price_sort")
+	sale_sort, _ := self.GetInt64("sale_sort")
 
 	if page <= 0 {
 		page = 1
@@ -40,14 +44,16 @@ func (self *ProductController) Latest() {
 		ListCount int64                    `json:"list_count"`
 	}
 
-	pds := product_model.GetLatest(page, perPage, recommend, ptype, cache)
+	pds := product_model.GetLatest(page, perPage, recommend, price_sort, sale_sort, ptype, cache)
 	count := product_model.GetLatestCount(recommend, ptype, cache)
 	for _, pd := range pds {
 		pd.SoldCount = pd.SaleNums
 		if pd.Count > pd.SoldCount {
 			pd.LeftCount = pd.Count - pd.SoldCount
 		}
-		pd.SoldCount = pd.SoldCount + pd.VirtualSoldCount
+		//pd.SoldCount = pd.SoldCount + pd.VirtualSoldCount
+		pd.SoldCount = product_model.GetProductCountByRelateId(pd.RelateProductId, true)
+
 		if pd.SeckilShowPrice > 0 {
 			now := time.Now()
 			pd.SeckillStartAt = pd.SeckillStart.Unix()
@@ -65,8 +71,62 @@ func (self *ProductController) Latest() {
 				pd.SeckillStateCn = product_model.SECKILL_END_STATE_CN
 			}
 		}
+		if pd.Package {
+			pd.PackageList = product_model.GetPackageList(pd.Id, true)
+		}
+		//判断是否预售
+		pd.IsDeliver = false
 		pd.DeliverStartTime = pd.DeliverStartAt.Unix()
 		pd.DeliverStopTime = pd.DeliverStopAt.Unix()
+		if pd.DeliverStartTime > 0 {
+			pd.IsDeliver = true
+			if time.Now().Unix() <= pd.DeliverStartTime {
+				pd.DeliverState = product_model.DELIVER_STATE_1
+			} else if time.Now().Unix() > pd.DeliverStopTime {
+				pd.DeliverState = product_model.DELIVER_STATE_3
+			} else {
+				pd.DeliverState = product_model.DELIVER_STATE_2
+			}
+		}
+		pd.HaveSize = false
+		//店铺列表专区商品增加规格显示
+		if ptype != product_model.TYPE_DIRECT_SALE && product_model.GetProductAttrConfig(pd.RelateProductId) != nil {
+			pd.HaveSize = true
+			list := product_model.GetProductConfigAttrsByPId(pd.RelateProductId)
+			for _, item := range list {
+				productKeyConfig := product_model.GetProductAttrKey(item.AttrKeyId)
+				if productKeyConfig != nil {
+					if item.SizeType == product_model.SIZE_TYPE_1 {
+						attrList := product_model.GetProductAttrsByKId(productKeyConfig.Id)
+						for _, attr := range attrList {
+							prodSize := product_model.GetProductByIdAndSizeId(pd.RelateProductId, attr.Id, true)
+							if prodSize != nil {
+								size := &product_model.ProductAttr{}
+								size.Id = attr.Id
+								//beego.BeeLogger.Warn("size_id --- %d", size.Id)
+								size.Name = attr.Name
+								productKeyConfig.ProductAttr = append(productKeyConfig.ProductAttr, size)
+							}
+						}
+						pd.Size = productKeyConfig
+					}
+					if item.SizeType == product_model.SIZE_TYPE_2 {
+						attrList := product_model.GetProductAttrsByKId(productKeyConfig.Id)
+						for _, attr := range attrList {
+							prodColor := product_model.GetProductByIdAndColorId(pd.RelateProductId, attr.Id, true)
+							if prodColor != nil {
+								size := &product_model.ProductAttr{}
+								size.Id = attr.Id
+								//beego.BeeLogger.Warn("color_id --- %d", size.Id)
+								size.Name = attr.Name
+								productKeyConfig.ProductAttr = append(productKeyConfig.ProductAttr, size)
+							}
+						}
+						pd.Color = productKeyConfig
+					}
+				}
+			}
+		}
 	}
 
 	self.Data["json"] = &Ret{List: pds, ListCount: count}
@@ -76,7 +136,7 @@ func (self *ProductController) Latest() {
 //商品详情
 func (self *ProductController) Get() {
 	_id := self.Ctx.Input.Param(":id")
-	cache, _ := self.GetBool("cache", false)
+	cache, _ := self.GetBool("cache", true)
 
 	pId, _ := strconv.ParseInt(_id, 10, 64)
 	pd := product_model.GetProductById(pId, cache)
@@ -88,7 +148,9 @@ func (self *ProductController) Get() {
 	if pd.Count > pd.SoldCount {
 		pd.LeftCount = pd.Count - pd.SoldCount
 	}
-	pd.SoldCount = pd.SoldCount + pd.VirtualSoldCount
+	//pd.SoldCount = pd.SoldCount + pd.VirtualSoldCount
+	pd.SoldCount = product_model.GetProductCountByRelateId(pd.RelateProductId, true)
+
 	pd.Cover = product_model.GetCoverByPId(pId, cache)
 	pd.Album = product_model.GetPicturesByPIdAndPType(pId, product_model.PIC_TYPE_ALBUM, cache)
 	pd.ShareImg = self.GetCdnFullImgUrl(pd.ShareImg)
@@ -110,16 +172,33 @@ func (self *ProductController) Get() {
 			pd.SeckillStateCn = product_model.SECKILL_END_STATE_CN
 		}
 	}
+	if pd.Package {
+		pd.PackageList = product_model.GetPackageList(pd.Id, true)
+	}
 	pd.HaveSize = false
 	if product_model.GetProductAttrConfig(pd.RelateProductId) != nil {
 		pd.HaveSize = true
 	}
 
+	//判断是否预售
+	pd.IsDeliver = false
 	pd.DeliverStartTime = pd.DeliverStartAt.Unix()
 	pd.DeliverStopTime = pd.DeliverStopAt.Unix()
+	if pd.DeliverStartTime > 0 {
+		pd.IsDeliver = true
+		if time.Now().Unix() <= pd.DeliverStartTime {
+			pd.DeliverState = product_model.DELIVER_STATE_1
+		} else if time.Now().Unix() > pd.DeliverStopTime {
+			pd.DeliverState = product_model.DELIVER_STATE_3
+		} else {
+			pd.DeliverState = product_model.DELIVER_STATE_2
+		}
+	}
+
 	// ret.Product = pd
 	self.Data["json"] = pd
-	self.ServeJSON()
+	self.ServeResultJSON()
+	//self.ServeJSON()
 }
 
 //商品详情
@@ -140,11 +219,26 @@ func (self *ProductController) GetPdDetail() {
 		Product *product_model.Product `json:"product"`
 	}
 	if pd != nil {
+		//获取颜色,规格名称
+		if sizeId > int64(0) {
+			prd_size := product_model.GetProductAttrValueById(sizeId)
+			if prd_size != nil {
+				pd.SizeName = prd_size.Name
+			}
+		}
+		if colorId > int64(0) {
+			prd_color := product_model.GetProductAttrValueById(colorId)
+			if prd_color != nil {
+				pd.ColorName = prd_color.Name
+			}
+		}
 		pd.SoldCount = pd.SaleNums
 		if pd.Count > pd.SoldCount {
 			pd.LeftCount = pd.Count - pd.SoldCount
 		}
-		pd.SoldCount = pd.SoldCount + pd.VirtualSoldCount
+		//pd.SoldCount = pd.SoldCount + pd.VirtualSoldCount
+		pd.SoldCount = product_model.GetProductCountByRelateId(pd.RelateProductId, true)
+
 		pd.Cover = product_model.GetCoverByPId(pd.Id, cache)
 		pd.Album = product_model.GetPicturesByPIdAndPType(pd.Id, product_model.PIC_TYPE_ALBUM, cache)
 		pd.ShareImg = self.GetCdnFullImgUrl(pd.ShareImg)
@@ -169,8 +263,23 @@ func (self *ProductController) GetPdDetail() {
 		if product_model.GetProductAttrConfig(pd.RelateProductId) != nil {
 			pd.HaveSize = true
 		}
+		if pd.Package {
+			pd.PackageList = product_model.GetPackageList(pd.Id, true)
+		}
+		//判断是否预售
+		pd.IsDeliver = false
 		pd.DeliverStartTime = pd.DeliverStartAt.Unix()
 		pd.DeliverStopTime = pd.DeliverStopAt.Unix()
+		if pd.DeliverStartTime > 0 {
+			pd.IsDeliver = true
+			if time.Now().Unix() <= pd.DeliverStartTime {
+				pd.DeliverState = product_model.DELIVER_STATE_1
+			} else if time.Now().Unix() > pd.DeliverStopTime {
+				pd.DeliverState = product_model.DELIVER_STATE_3
+			} else {
+				pd.DeliverState = product_model.DELIVER_STATE_2
+			}
+		}
 	}
 	ret := &Ret{}
 	ret.Product = pd
@@ -200,7 +309,11 @@ func (self *ProductController) GetProductsByCat() {
 	catId, _ := strconv.ParseInt(_id, 10, 64)
 	page, _ := self.GetInt64("page")
 	perPage, _ := self.GetInt64("per_page")
+	words := self.GetString("words")
 	cache, _ := self.GetBool("cache", false)
+	price_sort, _ := self.GetInt64("price_sort")
+	sale_sort, _ := self.GetInt64("sale_sort")
+
 	if page <= 0 {
 		page = 1
 	}
@@ -211,14 +324,16 @@ func (self *ProductController) GetProductsByCat() {
 		List      []*product_model.Product `json:"list"`
 		ListCount int64                    `json:"list_count"`
 	}
-	list := product_model.GetProductsByCatId(catId, page, perPage, cache)
-	count := product_model.GetProductCountByCatId(catId, cache)
+	list := product_model.GetProductsByCatId(catId, page, perPage, price_sort, sale_sort, words, cache)
+	count := product_model.GetProductCountByCatId(catId, words, cache)
 	for _, pd := range list {
 		pd.SoldCount = pd.SaleNums
 		if pd.Count > pd.SoldCount {
 			pd.LeftCount = pd.Count - pd.SoldCount
 		}
-		pd.SoldCount = pd.SoldCount + pd.VirtualSoldCount
+		//pd.SoldCount = pd.SoldCount + pd.VirtualSoldCount
+		pd.SoldCount = product_model.GetProductCountByRelateId(pd.RelateProductId, true)
+
 		if pd.SeckilShowPrice > 0 {
 			now := time.Now()
 			pd.SeckillStartAt = pd.SeckillStart.Unix()
@@ -236,9 +351,23 @@ func (self *ProductController) GetProductsByCat() {
 				pd.SeckillStateCn = product_model.SECKILL_END_STATE_CN
 			}
 		}
-
+		if pd.Package {
+			pd.PackageList = product_model.GetPackageList(pd.Id, true)
+		}
+		//判断是否预售
+		pd.IsDeliver = false
 		pd.DeliverStartTime = pd.DeliverStartAt.Unix()
 		pd.DeliverStopTime = pd.DeliverStopAt.Unix()
+		if pd.DeliverStartTime > 0 {
+			pd.IsDeliver = true
+			if time.Now().Unix() <= pd.DeliverStartTime {
+				pd.DeliverState = product_model.DELIVER_STATE_1
+			} else if time.Now().Unix() > pd.DeliverStopTime {
+				pd.DeliverState = product_model.DELIVER_STATE_3
+			} else {
+				pd.DeliverState = product_model.DELIVER_STATE_2
+			}
+		}
 	}
 	self.Data["json"] = &Ret{List: list, ListCount: count}
 	self.ServeJSON()
@@ -255,7 +384,7 @@ func (self *ProductController) GetNeedShare() {
 		self.ReturnError(403, apps.NoExist, "", nil)
 	}
 
-	wxUId := self.GetCurrentWxUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
 
 	type Ret struct {
 		NeedShare int64 `json:"need_share"`
@@ -306,7 +435,7 @@ func (self *ProductController) GetProductSizesByPid() {
 		Size    *product_model.ProductAttrKey `json:"size_list"`
 		Color   *product_model.ProductAttrKey `json:"color_list"`
 	}
-	product := product_model.GetProductById(pId, false)
+	product := product_model.GetProductById(pId, true)
 
 	ret := &Ret{}
 	if product != nil {
@@ -350,3 +479,52 @@ func (self *ProductController) GetProductSizesByPid() {
 	self.Data["json"] = ret
 	self.ServeJSON()
 }
+
+//获取某商品评论列表
+func (self *ProductController) GetProductsCommends() {
+	_id := self.Ctx.Input.Param(":product_id")
+	prdId, _ := strconv.ParseInt(_id, 10, 64)
+	page, _ := self.GetInt64("page")
+	perPage, _ := self.GetInt64("per_page")
+	cache, _ := self.GetBool("cache", false)
+	if page <= 0 {
+		page = 1
+	}
+	if perPage <= 0 || perPage > 100 {
+		perPage = 20
+	}
+	type Ret struct {
+		List      []*product_model.ProductCommend `json:"list"`
+		ListCount int64                           `json:"list_count"`
+	}
+	list := product_model.GetProductCommends(prdId, true, cache, page, perPage)
+	count := product_model.GetProductCommendCountByProductId(prdId, true, cache)
+	for _, cd := range list {
+		wxUser := user_model.GetWxUserById(cd.WxUserId, true)
+		if wxUser != nil {
+			cd.Head = product_model.GetCdnFullImgUrl(wxUser.Head)
+			name := string([]rune(wxUser.Nickname)[:1])
+			cd.NickName = fmt.Sprintf("%s*", name)
+		}
+		cd.CreateTime = cd.CreatedAt.Unix()
+	}
+	self.Data["json"] = &Ret{List: list, ListCount: count}
+	self.ServeJSON()
+}
+
+func (self *ProductController) GetCommendWords() {
+
+	perPage, _ := self.GetInt64("per_page")
+	cache, _ := self.GetBool("cache", true)
+
+	if perPage <= 0 {
+		perPage = 10
+	}
+	type Ret struct {
+		List []*product_model.CommendWord `json:"list"`
+	}
+	list := product_model.GetCommendWordsList(perPage, cache)
+
+	self.Data["json"] = &Ret{List: list}
+	self.ServeJSON()
+}

+ 23 - 0
go/gopath/src/fohow.com/apps/controllers/promotion_controller/init.go

@@ -0,0 +1,23 @@
+package promotion_controller
+
+import (
+	"github.com/astaxie/beego/context"
+
+	"fohow.com/apps"
+)
+
+var (
+	//以下Action无需登录校验,exceptCheckUserLoginAction = []string{"*"} *代表全部不需要
+	exceptCheckUserLoginAction   = []string{""}
+	exceptCheckWxUserLoginAction = []string{""}
+)
+
+type PromotionController struct {
+	apps.BaseController
+}
+
+func (self *PromotionController) Init(ctx *context.Context, controllerName, actionName string, app interface{}) {
+	self.BaseController.Init(ctx, controllerName, actionName, app)
+	self.ExceptCheckUserLoginAction = exceptCheckUserLoginAction
+	self.ExceptCheckWxUserLoginAction = exceptCheckWxUserLoginAction
+}

+ 37 - 0
go/gopath/src/fohow.com/apps/controllers/promotion_controller/promotion_controller.go

@@ -0,0 +1,37 @@
+package promotion_controller
+
+import (
+	"fohow.com/apps/models/product_model"
+	"fohow.com/apps/models/promotion_model"
+)
+
+//赠券列表
+func (self *PromotionController) GetList() {
+
+	//page, _ := self.GetInt64("page", 1)
+	perPage, _ := self.GetInt64("per_page", 20)
+	if perPage <= 0 || perPage > 100 {
+		perPage = 20
+	}
+	type Result struct {
+		Presents []*promotion_model.Present `json:"present"`
+		Count    int64                      `json:"count"`
+	}
+	wxUId := self.GetCurrentWxUserIdByToken()
+
+	promotionList := promotion_model.GetAllNoPatchPresents(wxUId)
+	for _, v := range promotionList {
+		v.SourceName = promotion_model.SOURCE_CN[v.Source]
+		product := product_model.GetProductById(v.SendProd, false)
+		if product != nil {
+			v.ProductName = product.Name
+			v.ProductImage = self.GetCdnFullImgUrl(product.Cover)
+		}
+	}
+
+	list := new(Result)
+	list.Presents = promotionList
+	list.Count = int64(len(promotionList))
+	self.Data["json"] = list
+	self.ServeJSON()
+}

+ 27 - 0
go/gopath/src/fohow.com/apps/controllers/railsadmin_controller/balance_order_controller.go

@@ -0,0 +1,27 @@
+package railsadmin_controller
+
+import (
+	"fohow.com/apps"
+	"fohow.com/apps/helpers"
+	"fohow.com/apps/models/balance_model"
+	"github.com/astaxie/beego"
+	"strconv"
+)
+
+//充值订单审核
+func (self *RailsadminController) ConfirmBalanceOrder() {
+
+	_id := self.Ctx.Input.Param(":id")
+	id, _ := strconv.ParseInt(_id, 10, 64)
+	beego.BeeLogger.Warn("BalanceOrder id:(%d)", id)
+
+	order := balance_model.GetBalanceOrderById(id, false)
+	if order == nil {
+		self.ReturnError(404, apps.NoExist, "", nil)
+	}
+	//发放上级佣金
+	go helpers.PatchRechargeBalance(id, order.PaiedPrice, "")
+	//发放赠品
+	go helpers.BalanceOrderPromotion(order.OrderId, order.WxUserId, order.Depart)
+	self.ServeJSON()
+}

+ 12 - 3
go/gopath/src/fohow.com/apps/controllers/railsadmin_controller/cache_controller.go

@@ -1,10 +1,10 @@
 package railsadmin_controller
 
 import (
-	"github.com/astaxie/beego"
-	"github.com/astaxie/beego/context"
 	"fohow.com/apps"
 	"fohow.com/cache"
+	"github.com/astaxie/beego"
+	"github.com/astaxie/beego/context"
 	"strconv"
 )
 
@@ -31,10 +31,19 @@ func (self *RailsadminController) CleanCache() {
 	id, _ := strconv.ParseInt(_id, 10, 64)
 	beego.BeeLogger.Warn("t: %s, id: %d", t, id)
 
-	if t == "project" {
+	switch {
+	case t == "project":
 		beego.BeeLogger.Warn("railsadmin after update clean cache: %d", id)
 		k := cache.GetKey(cache.GetProjectById, id)
 		cache.Cache.Delete(k)
+	case t == "package":
+		beego.BeeLogger.Warn("railsadmin after save clean package cache: %d", id)
+		k := cache.GetKey(cache.GetProductPackagetByPId, id)
+		cache.Cache.Delete(k)
+	case t == "product":
+		beego.BeeLogger.Warn("railsadmin after save clean product cache: %d", id)
+		k := cache.GetKey(cache.GetProductByPId, id)
+		cache.Cache.Delete(k)
 	}
 	self.ServeJSON()
 }

+ 2 - 1
go/gopath/src/fohow.com/apps/controllers/railsadmin_controller/generate_controller.go

@@ -173,7 +173,8 @@ func (self *RailsadminController) GenerateXcxQrcode() {
 		wxUser.Save()
 		qrcodeUrl = self.GetFullImgUrl(uploadPath)
 	}
-
+	//消除user,wxuser缓存
+	go wxUser.CleanCache()
 	self.Data["json"] = &Ret{QrcodeUrl: qrcodeUrl}
 	self.ServeJSON()
 }

+ 1 - 6
go/gopath/src/fohow.com/apps/controllers/railsadmin_controller/intro_user_controller.go

@@ -1,10 +1,8 @@
 package railsadmin_controller
 
 import (
-	"fmt"
 	"fohow.com/apps"
 	"fohow.com/apps/models/user_model"
-	"fohow.com/cache"
 	"github.com/astaxie/beego"
 	"strconv"
 	"time"
@@ -33,9 +31,6 @@ func (self *RailsadminController) UpdateIntroUser() {
 	inviteList := user_model.GetWxUsersByInviteIdAll(wxUser.Id, false)
 	go user_model.UpdateClass(inviteList, wxUser.Id, wxUser.IntroUserId)
 	//消除user,wxuser缓存
-	userKey := fmt.Sprintf("user.GetByUid[%d]", wxUser.UserId)
-	wxUserKey := cache.GetKey(cache.GetWxUserById, wxUser.Id)
-	cache.Cache.Delete(userKey)
-	cache.Cache.Delete(wxUserKey)
+	go wxUser.CleanCache()
 	self.ServeJSON()
 }

+ 22 - 4
go/gopath/src/fohow.com/apps/controllers/railsadmin_controller/live_award_controller.go

@@ -3,6 +3,7 @@ package railsadmin_controller
 import (
 	"fmt"
 	"fohow.com/apps"
+	"fohow.com/apps/helpers"
 	"fohow.com/apps/models/balance_model"
 	"fohow.com/apps/models/cent_model"
 	"fohow.com/apps/models/live_model"
@@ -14,7 +15,7 @@ import (
 	"time"
 )
 
-//
+//发放直播赠品
 func (self *RailsadminController) LiveAward() {
 
 	_id := self.Ctx.Input.Param(":id")
@@ -54,7 +55,7 @@ func (self *RailsadminController) LiveAward() {
 			product := product_model.GetProductById(LiveAward.Prod1, true)
 			if product != nil {
 				totalPrice += LiveAward.Nums1 * product.Price
-				go order_model.SendCreate(order.OrderId, order.Id, product.Id, product.Price, product.Price, product.Name, sendNums1)
+				go order_model.SendCreate(order.OrderId, order.Id, product.Id, product.Price, product.Price, product.Name, sendNums1, order.Depart)
 			}
 
 		}
@@ -64,7 +65,7 @@ func (self *RailsadminController) LiveAward() {
 			product := product_model.GetProductById(LiveAward.Prod2, true)
 			if product != nil {
 				totalPrice += LiveAward.Nums2 * product.Price
-				go order_model.SendCreate(order.OrderId, order.Id, product.Id, product.Price, product.Price, product.Name, sendNums2)
+				go order_model.SendCreate(order.OrderId, order.Id, product.Id, product.Price, product.Price, product.Name, sendNums2, order.Depart)
 			}
 		}
 
@@ -75,7 +76,7 @@ func (self *RailsadminController) LiveAward() {
 			//赠送赠品1
 			if product != nil {
 				totalPrice += LiveAward.Nums3 * product.Price
-				go order_model.SendCreate(order.OrderId, order.Id, product.Id, product.Price, product.Price, product.Name, sendNums3)
+				go order_model.SendCreate(order.OrderId, order.Id, product.Id, product.Price, product.Price, product.Name, sendNums3, order.Depart)
 			}
 		}
 		order.Address = LiveAward.Address
@@ -109,3 +110,20 @@ func (self *RailsadminController) LiveAward() {
 
 	self.ServeJSON()
 }
+
+//发放充值赠品
+func (self *RailsadminController) PatchCashAward() {
+
+	_id := self.Ctx.Input.Param(":id")
+	id, _ := strconv.ParseInt(_id, 10, 64)
+
+	beego.BeeLogger.Warn("PatchCashAward id:(%d)", id)
+
+	order := order_model.GetOrderByIntId(id)
+	if order != nil {
+		go helpers.PresentTransferToOrder(order.OrderId, order.WxUserId)
+	}
+
+	beego.BeeLogger.Warn("----------------end patch cash recharge awards order_id ---%s ", order.OrderId)
+	self.ServeJSON()
+}

+ 42 - 0
go/gopath/src/fohow.com/apps/controllers/railsadmin_controller/order_award_controller.go

@@ -0,0 +1,42 @@
+package railsadmin_controller
+
+import (
+	"fohow.com/apps"
+	"fohow.com/apps/helpers"
+	"fohow.com/apps/models/order_model"
+	"fohow.com/apps/models/user_model"
+	"github.com/astaxie/beego"
+	"strconv"
+	"sync"
+)
+
+var orderAwardLock sync.Mutex
+
+//订单发货
+func (self *RailsadminController) OrderAward() {
+
+	_id := self.Ctx.Input.Param(":id")
+	id, _ := strconv.ParseInt(_id, 10, 64)
+
+	beego.BeeLogger.Warn("OrderAward id:(%d)", id)
+
+	defer orderAwardLock.Unlock()
+	orderAwardLock.Lock()
+	o := order_model.GetOrderByIntId(id)
+	if o == nil {
+		self.ReturnError(404, apps.OrderNotExist, "", nil)
+	}
+	//只能处理待发货订单
+	if o.Status != order_model.STATUS_PROCESSING && !o.HasCommission {
+		self.ReturnError(403, apps.OrderStatusNotSuit, "", nil)
+	}
+
+	o.HasCommission = true
+	if !o.Save() {
+		beego.BeeLogger.Error("user[%d]", id)
+	}
+	wxUser := user_model.GetWxUserById(o.WxUserId, true)
+	go helpers.NewSendInviterBenefit(wxUser, o.OrderId, user_model.SOURCE_PRODUCT_BENEFIT)
+
+	self.ServeJSON()
+}

+ 25 - 1
go/gopath/src/fohow.com/apps/controllers/railsadmin_controller/order_dispatch_controller.go

@@ -4,7 +4,9 @@ import (
 	"fohow.com/apps"
 	"fohow.com/apps/helpers"
 	"fohow.com/apps/models/order_model"
+	"fohow.com/apps/models/product_model"
 	"github.com/astaxie/beego"
+	"github.com/astaxie/beego/orm"
 	"strconv"
 	"sync"
 	"time"
@@ -51,6 +53,28 @@ func (self *RailsadminController) OrderDispatch() {
 		beego.BeeLogger.Error("user[%d]", id)
 	}
 	go helpers.DispathSendSms([]string{o.Tel}, o.ExpressOrderNo)
-
+	go updateSoldCount(o.Id)
 	self.ServeJSON()
 }
+
+//更新商品出库数量
+func updateSoldCount(Id int64) {
+	var list []*order_model.OrderDtItem
+	sql := `
+		select *
+		  from base_details where order_id=?;
+	`
+	_, err := orm.NewOrm().Raw(sql, Id).QueryRows(&list)
+	if err != nil {
+		beego.Debug("updateOutCount err=[%s]", err)
+		return
+	}
+	beego.BeeLogger.Warn("updateSoldCount.len(list):%d", len(list))
+	for _, item := range list {
+		product := product_model.GetProductById(item.ProductId, true)
+		if product != nil {
+			product.OutNums += item.Nums
+			product.Save()
+		}
+	}
+}

+ 2 - 2
go/gopath/src/fohow.com/apps/controllers/railsadmin_controller/order_refund_controller.go

@@ -5,7 +5,7 @@ import (
 	"fohow.com/apps"
 	"fohow.com/apps/models/balance_model"
 	"fohow.com/apps/models/order_model"
-	"fohow.com/apps/models/pay_model"
+	"fohow.com/apps/models/sys_config"
 	"fohow.com/libs/wx_mp"
 	"math/rand"
 	"strings"
@@ -81,7 +81,7 @@ func (self *RailsadminController) OrderRefund() {
 			outTradeNo := fmt.Sprintf("%s-%d", refund.OrderId, refund.Id)
 			outRefundNo := createOrderId("refund")
 			remark := fmt.Sprintf("%s%s", refund.OrderId, "退款")
-			payCode := pay_model.GetPayConfigByDepart(o.Depart, true)
+			payCode := sys_config.GetPayConfigByDepart(o.Depart, true)
 			payData := wx_mp.GetRefundDataPay(outTradeNo, outRefundNo, refund.RefundFee, o.TradeNo, remark, payCode)
 			if payData != nil {
 				if payData["return_code"] == "SUCCESS" {

+ 1 - 1
go/gopath/src/fohow.com/apps/controllers/railsadmin_controller/tmpl_controller.go

@@ -24,7 +24,7 @@ func (self *RailsadminController) SendTemplate() {
 	item.LastUpdatedAt = time.Now()
 	go item.Save()
 	s := item.MsgType                         //模板:0 订单待支付提醒 1新项目通知 2提货通知
-	wxGongzhonghaoId := item.WxGongzhonghaoId //微信公众号ID,1:FOHOW玖玖
+	wxGongzhonghaoId := item.WxGongzhonghaoId //微信公众号ID,1:凤凰菁选
 
 	DEFAULTGONGZHONGHAO := int64(1)
 	if beego.BConfig.RunMode == beego.DEV {

+ 12 - 13
go/gopath/src/fohow.com/apps/controllers/railsadmin_controller/update_shop_application.go

@@ -3,10 +3,10 @@ package railsadmin_controller
 import (
 	"fmt"
 	"fohow.com/apps"
+	"fohow.com/apps/helpers"
 	"fohow.com/apps/models/balance_model"
-	"fohow.com/apps/models/base_config"
+	"fohow.com/apps/models/sys_config"
 	"fohow.com/apps/models/user_model"
-	"fohow.com/cache"
 	"github.com/astaxie/beego"
 	"strconv"
 	"time"
@@ -44,12 +44,11 @@ func (self *RailsadminController) UpdateShopApplication() {
 	//更改下级会员群主ID
 	inviteList := user_model.GetWxUsersByInviteIdAll(wxUser.Id, false)
 	go user_model.UpdateClass(inviteList, wxUser.Id, wxUser.IntroUserId)
-
+	//发放赠品
+	//helpers.ShopOrderPromotion(shopApplication.Id, wxUser.Id, wxUser.Depart)
+	helpers.CreateShopApplyOrder(shopApplication.Id)
 	//消除user,wxuser缓存
-	userKey := fmt.Sprintf("user.GetByUid[%d]", wxUser.UserId)
-	wxUserKey := cache.GetKey(cache.GetWxUserById, wxUser.Id)
-	cache.Cache.Delete(userKey)
-	cache.Cache.Delete(wxUserKey)
+	go wxUser.CleanCache()
 	self.ServeJSON()
 }
 
@@ -60,9 +59,9 @@ func ApplySuccessInviterBenefit(wxUser *user_model.WxUser, shopId int64, source
 	}
 	//本人充值16800--发放4200提货券
 	rId := fmt.Sprintf("shop-apply-%d", shopId)
-	c := base_config.GetUserCash()
-	if shopApply.Total == base_config.GetAgentApply() {
-		c = base_config.GetAgentCash()
+	c := sys_config.GetUserCash()
+	if shopApply.Total == sys_config.GetAgentApply() {
+		c = sys_config.GetAgentCash()
 	}
 	benefitWxUser := GetInviter(wxUser)
 	if benefitWxUser == nil || benefitWxUser.Id == int64(1) {
@@ -82,10 +81,10 @@ func ApplySuccessInviterBenefit(wxUser *user_model.WxUser, shopId int64, source
 
 	//发放佣金  13800-4500 16800-5000
 	count := int64(0)
-	if shopApply.Total == base_config.GetUserApply() {
-		count = base_config.GetUserAward()
+	if shopApply.Total == sys_config.GetUserApply() {
+		count = sys_config.GetUserAward()
 	} else {
-		count = base_config.GetAgentAward()
+		count = sys_config.GetAgentAward()
 	}
 	if count > int64(0) {
 		remark := fmt.Sprintf("%s%s", wxUser.Nickname, "店长申请成功")

+ 1 - 1
go/gopath/src/fohow.com/apps/controllers/share_controller/share_controller.go

@@ -36,7 +36,7 @@ func (self *ShareController) DoShare() {
 	ri := self.GetString("ri")
 	rp := self.GetString("rp")
 	to := self.GetString("to")
-	uId := self.GetCurrentWxUserId()
+	uId := self.GetCurrentWxUserIdByToken()
 	//wxUser := self.GetCurrentWxUser(true)
 	//if wxUser == nil {
 	//	self.ReturnError(403, apps.WxUserNeedLogin, "", nil)

+ 32 - 0
go/gopath/src/fohow.com/apps/controllers/sys_controller/init.go

@@ -0,0 +1,32 @@
+package sys_controller
+
+import (
+	// "fmt"
+	// "os"
+	// "net/url"
+	// "strings"
+
+	// "github.com/astaxie/beego"
+	"github.com/astaxie/beego/context"
+	// "github.com/go-wkhtmltoimage"
+	// "github.com/skip2/go-qrcode"
+
+	"fohow.com/apps"
+)
+
+var (
+	//需要校验用户登录的Action
+	exceptCheckUserLoginAction   = []string{""}
+	exceptCheckWxUserLoginAction = []string{""}
+)
+
+type SysController struct {
+	apps.BaseController
+}
+
+func (self *SysController) Init(ctx *context.Context, controllerName, actionName string, app interface{}) {
+	// beego.BeeLogger.Info("invote controller Init func")
+	self.BaseController.Init(ctx, controllerName, actionName, app)
+	self.ExceptCheckUserLoginAction = exceptCheckUserLoginAction
+	self.ExceptCheckWxUserLoginAction = exceptCheckWxUserLoginAction
+}

+ 31 - 0
go/gopath/src/fohow.com/apps/controllers/sys_controller/sys_controller.go

@@ -0,0 +1,31 @@
+package sys_controller
+
+import (
+	// "github.com/astaxie/beego"
+	// "github.com/astaxie/beego/context"
+
+	"fohow.com/apps"
+	"fohow.com/apps/models/sys_config"
+
+	"fohow.com/apps/models/user_model"
+)
+
+//获取当前会员申店配置金额
+func (self *SysController) GetCurApplyInfo() {
+	type ApplyInfo struct {
+		Total int64 `orm:"-" json:"total"` //余额,单位分
+	}
+	wxUId := self.GetCurrentWxUserIdByToken()
+	wxUser := user_model.GetWxUserById(wxUId, true)
+	if wxUser == nil {
+		self.ReturnError(403, apps.UserNeedLogin, "", nil)
+	}
+	applyTotal := sys_config.GetUserApply()
+	if wxUser.Rank >= 1 {
+		applyTotal = sys_config.GetAgentApply()
+	}
+	info := new(ApplyInfo)
+	info.Total = applyTotal
+	self.Data["json"] = info
+	self.ServeJSON()
+}

+ 18 - 2
go/gopath/src/fohow.com/apps/controllers/test_controller/test_controller.go

@@ -6,6 +6,7 @@ import (
 	"fohow.com/apps/models/user_model"
 	"fohow.com/libs/lib_redis"
 	"fohow.com/libs/wx_mp"
+	"github.com/astaxie/beego"
 	"math/rand"
 	"strings"
 	"time"
@@ -49,7 +50,9 @@ func (self *TestController) TestOrderListen() {
 
 //测试redis 存储userInfo
 func (self *TestController) GetUserInfoFromRedis() {
-	userId := int64(1388)
+
+	//-------测试个人------------//
+	userId := int64(1458)
 	key := fmt.Sprintf("userinfo_%d", userId)
 	var user user_model.User
 	ok, resp := lib_redis.GetRedisValue(key, user)
@@ -59,11 +62,24 @@ func (self *TestController) GetUserInfoFromRedis() {
 		lib_redis.SetJsonEx(key, resp, 90*60)
 
 	}
+	beego.BeeLogger.Warn("resp---%v", resp)
+
+	//-------测试数组------------//
+	key_ar := fmt.Sprintf("array_userinfo_a")
+	var users []user_model.User
+	ok, resp_ar := lib_redis.GetRedisValue(key_ar, users)
+	if !ok {
+		//发送请求
+		resp_ar = user_model.GetUserByIsRegistAndIsRegistBefore()
+		lib_redis.SetJsonEx(key_ar, resp_ar, 90*60)
+
+	}
+	beego.BeeLogger.Warn("resp_ar---%v", resp_ar)
 	type Ret struct {
 		Resp interface{} `json:"resp"`
 	}
 	ret := &Ret{}
-	ret.Resp = resp
+	ret.Resp = resp_ar
 	self.Data["json"] = ret
 	self.ServeJSON()
 }

+ 199 - 0
go/gopath/src/fohow.com/apps/controllers/user_controller/agent_apply_controller.go

@@ -0,0 +1,199 @@
+package user_controller
+
+import (
+	"fohow.com/apps"
+	"fohow.com/apps/models/user_model"
+	"strconv"
+	"time"
+)
+
+//申请代理
+func (self *UserController) AgentApplication() {
+	mobile := self.GetString("mobile")
+	wxId, _ := self.GetInt64("wx_uid", 0)
+
+	introUserId := self.GetCurrentWxUserIdByToken()
+	//introUserId := int64(30608)
+	/*	if len(mobile) != 11 {
+		self.ReturnError(404, apps.ParamsError, "", nil)
+	}*/
+
+	wxUser := user_model.GetWxUserById(wxId, false)
+	if wxUser == nil {
+		self.ReturnError(403, apps.WxUserNotExist, "", nil)
+	}
+	if wxUser.Rank >= user_model.WX_USER_RANK_ONE {
+		self.ReturnError(403, apps.AlreadyAgent, "", nil)
+	}
+
+	curWxUser := user_model.GetWxUserById(introUserId, true)
+	if curWxUser == nil {
+		self.ReturnError(403, apps.UserNeedLogin, "", nil)
+	}
+	if curWxUser.Rank < user_model.WX_USER_RANK_ONE {
+		self.ReturnError(403, apps.ComNotAllow, "", nil)
+	}
+	record := user_model.GetAgentApplyByWxUId(wxUser.Id)
+	if record != nil {
+		self.ReturnError(403, apps.ShopNoRepit, "", nil)
+	}
+	hTime := time.Now().Unix()
+	record = new(user_model.AgentApply).Create(introUserId, wxUser.Id, hTime, wxUser.Depart, mobile, wxUser.Nickname)
+	if record == nil {
+		self.ReturnError(403, apps.CreateOrderFail, "", nil)
+	}
+
+	type Ret struct {
+		Result bool `json:"result"`
+	}
+	ret := &Ret{Result: true}
+	self.Data["json"] = ret
+	self.ServeJSON()
+}
+
+//审核申请代理
+func (self *UserController) ComAgentApplication() {
+	_id := self.Ctx.Input.Param(":id")
+	applyId, _ := strconv.ParseInt(_id, 10, 64)
+	introUserId := self.GetCurrentWxUserIdByToken()
+	//introUserId := int64(30608)
+	record := user_model.GetAgentApplyById(applyId)
+	if record == nil {
+		self.ReturnError(403, apps.NoExist, "", nil)
+	}
+
+	curWxUser := user_model.GetWxUserById(introUserId, true)
+	if curWxUser == nil {
+		self.ReturnError(403, apps.UserNeedLogin, "", nil)
+	}
+
+	if curWxUser.Rank < user_model.WX_USER_RANK_THERE && curWxUser.Depart != record.Depart {
+		self.ReturnError(403, apps.ComNotAllow, "", nil)
+
+	}
+	record.Status = true
+	record.ComTime = time.Now().Unix()
+	record.ComUser = introUserId
+	err := record.Save()
+	if err == nil {
+		//申请会员升级代理
+		applyuser := user_model.GetWxUserById(record.WxUId, false)
+		applyuser.Rank = user_model.COPARTNER_STATE_YES
+		applyuser.ShowInviteMode = 1
+		applyuser.Save()
+	}
+
+	type Ret struct {
+		Result bool `json:"result"`
+	}
+	ret := &Ret{Result: true}
+	self.Data["json"] = ret
+	self.ServeJSON()
+}
+
+//获取我的代理列表
+func (self *UserController) GetMyAgentList() {
+	page, _ := self.GetInt64("page", 1)
+	perPage, _ := self.GetInt64("per_page", 20)
+	if perPage <= 0 || perPage > 100 {
+		perPage = 20
+	}
+	cache, _ := self.GetBool("cache", false)
+
+	//user := self.GetCurrentUser(cache)
+	wxUId := self.GetCurrentWxUserIdByToken()
+	//wxUId := int64(30608)
+	curWxUser := user_model.GetWxUserById(wxUId, true)
+	if curWxUser == nil {
+		self.ReturnError(403, apps.UserNeedLogin, "", nil)
+	}
+	if curWxUser.Rank < user_model.WX_USER_RANK_THERE {
+		self.ReturnError(403, apps.AccountError, "", nil)
+	}
+	list := user_model.GetAllApplys(curWxUser.Depart, page, perPage, cache)
+	count := user_model.GetAllApplyCount(curWxUser.Depart, false)
+	type AgentInfo struct {
+		AgentList  []*user_model.AgentApply `orm:"-" json:"agent_list"`
+		AgentCount int64                    `orm:"-" json:"count"`
+	}
+
+	self.Data["json"] = &AgentInfo{AgentList: list, AgentCount: count}
+	self.ServeJSON()
+}
+
+//获取代理申请详细
+func (self *UserController) GetAgentDetail() {
+	_id := self.Ctx.Input.Param(":id")
+	id, _ := strconv.ParseInt(_id, 10, 64)
+	//uId := self.GetCurrentUserId()
+	wxUId := self.GetCurrentWxUserIdByToken()
+	//wxUId := int64(30608)
+	curWxUser := user_model.GetWxUserById(wxUId, true)
+	if curWxUser == nil {
+		self.ReturnError(403, apps.UserNeedLogin, "", nil)
+	}
+
+	//wxUId := int64(1781)
+	item := user_model.GetAgentApplyById(id)
+	if item == nil {
+		self.ReturnError(403, apps.NoExist, "", nil)
+	}
+	introUser := user_model.GetWxUserById(item.IntroUserId, false)
+	itemUser := user_model.GetWxUserById(item.WxUId, false)
+	if item.Depart != curWxUser.Depart {
+		self.ReturnError(403, apps.ComNotAllow, "", nil)
+	}
+
+	if introUser != nil {
+		item.IntroHead = self.GetFullImgUrl(introUser.Head)
+		item.IntroNickName = introUser.Nickname
+	}
+
+	if itemUser != nil {
+		item.Head = self.GetFullImgUrl(itemUser.Head)
+		item.SaleGroupSum = itemUser.SaleGroupSum
+		item.SaleGroup = itemUser.SaleGroup
+	}
+
+	self.Data["json"] = item
+	self.ServeJSON()
+}
+
+// 获取某用户信息
+func (self *UserController) GetUserInfo() {
+	useCache, err := self.GetBool("cache", true)
+	_id := self.Ctx.Input.Param(":id")
+	id, _ := strconv.ParseInt(_id, 10, 64)
+	if err != nil {
+		useCache = false
+	}
+	wxUser := user_model.GetWxUserById(id, useCache)
+	if wxUser != nil {
+		wxUser.Head = self.GetFullImgUrl(wxUser.Head)
+	}
+	type Ret struct {
+		WxUser *user_model.WxUser `json:"wx_user"`
+	}
+
+	user := &Ret{WxUser: wxUser}
+	self.Data["json"] = user
+	self.ServeJSON()
+}
+
+//获取代理申请详细
+func (self *UserController) GetAgentDetailByWxUid() {
+	_id := self.Ctx.Input.Param(":wx_uid")
+	id, _ := strconv.ParseInt(_id, 10, 64)
+	//uId := self.GetCurrentUserId()
+	curId := self.GetCurrentWxUserIdByToken()
+	//curId := int64(30608)
+	curWxUser := user_model.GetWxUserById(curId, true)
+	if curWxUser == nil {
+		self.ReturnError(403, apps.UserNeedLogin, "", nil)
+	}
+	//wxUId := int64(1781)
+	item := user_model.GetAgentApplyByWxUId(id)
+
+	self.Data["json"] = item
+	self.ServeJSON()
+}

+ 2 - 14
go/gopath/src/fohow.com/apps/controllers/user_controller/binding_controller.go

@@ -80,17 +80,6 @@ func (self *UserController) BindingTel() {
 			user.SignupChannelId = cId
 		}
 		user.Save()
-		if user != nil {
-			self.SetSession(apps.SessionUserKey, user.Id)
-		}
-		// sign, template, action := sms_model.GetAliMsgContent(sms_model.LOGIN_PWD)
-		// go sms_model.SendSmsWithAli([]string{tel}, sign, template, action, loginPwd)
-		//go user_model.UpdateIsRegistD5c(user)
-		//go address_model.UpdateAddressUserId(wxUser)
-		//go balance_model.UpdateBalanceUserId(wxUser)
-		//go balance_model.UpdateBalanceOrderUserId(wxUser)
-		//go order_model.UpdateOrderUserId(wxUser)
-		//go exchange_model.UpdateExOrderUser(wxUser)
 	}
 	self.Data["json"] = user
 	self.ServeJSON()
@@ -131,9 +120,8 @@ func (self *UserController) BindingTelNew() {
 		}
 		user.Tel = tel
 		user.Save()
-		if user != nil {
-			self.SetSession(apps.SessionUserKey, user.Id)
-		}
+		//消除user,wxuser缓存
+		go wxUser.CleanCache()
 	}
 	self.Data["json"] = user
 	self.ServeJSON()

+ 6 - 109
go/gopath/src/fohow.com/apps/controllers/user_controller/binding_wx_phone_controller.go

@@ -5,110 +5,10 @@ import (
 	"fohow.com/apps"
 	"fohow.com/apps/helpers"
 	"fohow.com/apps/models/user_model"
+	"fohow.com/libs/lib_redis"
 	"github.com/astaxie/beego"
 )
 
-func (self *UserController) BindingWxPhone() {
-
-	wxUser := self.GetCurrentWxUser(false)
-
-	//如果已经绑定了user,直接返回
-	if wxUser.UserId != 0 {
-		self.ReturnError(403, apps.WxUserHasBindingTel, "", nil)
-	}
-
-	var tel string
-
-	//获取参数
-	//sign := self.GetString("sign")
-	//unixTime := self.GetString("tistamp")
-	//tel := self.GetString("phonumer")
-	//beego.BeeLogger.Warn("BindingWxPhone-sign:%s, unixTime:%s, tel:%s", sign, unixTime, tel)
-	//if strings.TrimSpace(tel) == "" || strings.TrimSpace(sign) == "" || strings.TrimSpace(unixTime) == ""{
-	//	self.ReturnError(403, apps.ParamsError, "", nil)
-	//}
-	//
-	//if !self.CheckParamsIsValid(tel, sign, unixTime){
-	//	self.ReturnError(403, apps.ParamsError, "", nil)
-	//}
-
-	sessionKey, _ := self.GetSession(apps.XcxSessionKey).(string)
-	if sessionKey == "" {
-		self.ReturnError(403, apps.UserNeedLogin, "", nil)
-	}
-
-	params := self.GetString("userinfo")
-	type Info struct {
-		Iv            string `json:"iv"`
-		EncryptedData string `json:"encryptedData"`
-	}
-	info := new(Info)
-	err := json.Unmarshal([]byte(params), &info)
-
-	if err != nil {
-		beego.BeeLogger.Error("BindingWxPhone err: %s, info:%s", err, info)
-		self.ReturnError(403, apps.ParamsError, "", nil)
-	}
-
-	type WatermarkInfo struct {
-		Appid     string `json:"appid"`
-		Timestamp string `json:"timestamp"`
-	}
-	type EncryptedData struct {
-		PhoneNumber     string         `json:"phoneNumber"`
-		PurePhoneNumber string         `json:"purePhoneNumber"`
-		CountryCode     string         `json:"countryCode"`
-		Watermark       *WatermarkInfo `json:"watermark"`
-	}
-	//phoneNumber	String	用户绑定的手机号(国外手机号会有区号)
-	//purePhoneNumber	String	没有区号的手机号
-	//countryCode	String	区
-
-	pc := helpers.WxBizDataCrypt{AppID: beego.AppConfig.String("WxFohowXcxAppId"), SessionKey: sessionKey}
-	result, err := pc.Decrypt(info.EncryptedData, info.Iv, true) //第三个参数解释: 需要返回 JSON 数据类型时 使用 true, 需要返回 map 数据类型时 使用 false
-	if err != nil {
-		beego.BeeLogger.Error("xcx BindingWxPhone descrypt failed, err:%s", err)
-		self.ReturnError(403, apps.BindingWxPhoneError, "", nil)
-	}
-	encryptedData := &EncryptedData{}
-	json.Unmarshal([]byte(result.(string)), encryptedData)
-
-	if encryptedData.PurePhoneNumber == "" {
-		self.ReturnError(403, apps.BindingWxPhoneError, "", nil)
-	}
-
-	tel = encryptedData.PurePhoneNumber
-
-	user := user_model.GetByTel(tel, false)
-	if user != nil {
-		self.ReturnError(403, apps.BindingTelExisted, "", nil)
-	} else { //手机号未被注册
-
-		ip := self.Ctx.Input.IP()
-		user = user_model.Create(tel, ip)
-		if user == nil {
-			self.ReturnError(403, apps.BindingUserTelError, "", nil)
-		}
-		wxUser.UserId = user.Id
-		wxUser.Save()
-		user.CopyWxUserHead(wxUser.Head)
-		user.Nickname = wxUser.Nickname
-		user.Country = wxUser.Country
-		user.Province = wxUser.Province
-		user.City = wxUser.City
-		user.Sex = wxUser.Sex
-		user.Save()
-		// 如果微信用户已绑定手机,则找出userId,并且赋值给session[userId]
-		if wxUser != nil && wxUser.UserId > 0 {
-			self.SetSession(apps.SessionWxUserKey, wxUser.Id)
-			self.SetSession(apps.SessionUserKey, wxUser.UserId)
-		}
-	}
-	self.Data["json"] = user
-	self.ServeJSON()
-
-}
-
 func (self *UserController) BindingWxPhoneNew() {
 
 	wxUser := self.GetCurrentWxUser(false)
@@ -119,11 +19,13 @@ func (self *UserController) BindingWxPhoneNew() {
 	}
 
 	var tel string
-
-	sessionKey, _ := self.GetSession(apps.XcxSessionKey).(string)
+	wxUserKey := lib_redis.GetKeySessionKey(wxUser.Id)
+	_, sessionKey := lib_redis.GetSimpleValue(wxUserKey)
+	//sessionKey, _ := self.GetSession(apps.XcxSessionKey).(string)
 	if sessionKey == "" {
-		self.ReturnError(403, apps.UserNeedLogin, "", nil)
+		//self.ReturnError(403, apps.UserNeedLogin, "", nil)
 	}
+	//beego.BeeLogger.Warn("XcxLogin SessionKeys=%s", sessionKey)
 
 	params := self.GetString("userinfo")
 	type Info struct {
@@ -177,11 +79,6 @@ func (self *UserController) BindingWxPhoneNew() {
 		}
 		user.Tel = tel
 		user.Save()
-		// 如果微信用户已绑定手机,则找出userId,并且赋值给session[userId]
-		if wxUser != nil && wxUser.UserId > 0 {
-			self.SetSession(apps.SessionWxUserKey, wxUser.Id)
-			self.SetSession(apps.SessionUserKey, wxUser.UserId)
-		}
 	}
 	self.Data["json"] = user
 	self.ServeJSON()

+ 1 - 1
go/gopath/src/fohow.com/apps/controllers/user_controller/invite_controller.go

@@ -288,7 +288,7 @@ func (self *UserController) SetWxUserInviter() {
 		return
 	}
 	ivId, _ := strconv.ParseInt(self.Ctx.Input.Param(":wx_inviter"), 10, 64)
-	currectWxUId := self.GetCurrentWxUserId()
+	currectWxUId := self.GetCurrentWxUserIdByToken()
 	if currectWxUId != 0 && ivId != 0 {
 		go helpers.SetInviter(currectWxUId, ivId)
 	}

+ 0 - 8
go/gopath/src/fohow.com/apps/controllers/user_controller/one_click_binding_controller.go

@@ -18,7 +18,6 @@ func (self *UserController) OneClickBindingTel() {
 	if tel == "" {
 		self.ReturnError(403, apps.WxUserNotRegistD5c, "", nil)
 	}
-
 	user := user_model.GetByTel(tel, false)
 	if user != nil {
 		self.ReturnError(403, apps.BindingTelExisted, "", nil)
@@ -47,13 +46,6 @@ func (self *UserController) OneClickBindingTel() {
 		// 	user.SignupChannelId = cId
 		// }
 		user.Save()
-		// sign, template, action := sms_model.GetAliMsgContent(sms_model.LOGIN_PWD)
-		// go sms_model.SendSmsWithAli([]string{tel}, sign, template, action, loginPwd)
-		// 如果微信用户已绑定手机,则找出userId,并且赋值给session[userId]
-		if wxUser != nil && wxUser.UserId > 0 {
-			self.SetSession(apps.SessionWxUserKey, wxUser.Id)
-			self.SetSession(apps.SessionUserKey, wxUser.UserId)
-		}
 	}
 	self.Data["json"] = user
 	self.ServeJSON()

+ 44 - 13
go/gopath/src/fohow.com/apps/controllers/user_controller/user_controller.go

@@ -2,8 +2,8 @@ package user_controller
 
 import (
 	"fmt"
-	"fohow.com/apps/models/base_config"
 	"fohow.com/apps/models/cent_model"
+	"fohow.com/apps/models/sys_config"
 	"strconv"
 
 	// "strconv"
@@ -299,11 +299,11 @@ func (self *UserController) BindingIdCard() {
 		self.ReturnError(403, apps.BindingIdCardLengthError, "", nil)
 	}
 
-	userWithIdCard := user_model.GetUserByIdCardNo(idCard, false)
-	if userWithIdCard != nil {
-		self.ReturnError(403, apps.BindingIdCardExist, "", nil)
-	}
-
+	/*	userWithIdCard := user_model.GetUserByIdCardNo(idCard, false)
+		if userWithIdCard != nil {
+			self.ReturnError(403, apps.BindingIdCardExist, "", nil)
+		}
+	*/
 	birth, err := time.Parse("20060102", idCard[6:14])
 	if err == nil {
 		user.Birthday = birth
@@ -315,7 +315,7 @@ func (self *UserController) BindingIdCard() {
 		self.ReturnError(403, apps.BindingIdCardEmpty, "", nil)
 	}
 	if age >= 0 && age < 18 {
-		self.ReturnError(403, apps.IdCardAgeNotBeAdult, "", nil)
+		//self.ReturnError(403, apps.IdCardAgeNotBeAdult, "", nil)
 	}
 
 	user.Age = age
@@ -411,9 +411,9 @@ func (self *UserController) ShopApplication() {
 	if wxUser.Rank > user_model.WX_USER_RANK_ONE {
 		self.ReturnError(403, apps.AlreadyShop, "", nil)
 	}
-	total := base_config.GetUserApply()
+	total := sys_config.GetUserApply()
 	if wxUser.Rank == user_model.WX_USER_RANK_ONE {
-		total = base_config.GetAgentApply()
+		total = sys_config.GetAgentApply()
 	}
 	k := fmt.Sprintf("%s%s", sms_model.SHOP_APPLICATION, mobile)
 	if cacheCode, ok := cache.Cache.Get(k).(string); ok {
@@ -540,10 +540,7 @@ func (self *UserController) SysUserBind() {
 	}
 
 	//清掉wxuser缓存
-	userKey := fmt.Sprintf("user.GetByUid[%d]", wxUser.UserId)
-	wxUserKey := cache.GetKey(cache.GetWxUserById, wxUser.Id)
-	cache.Cache.Delete(userKey)
-	cache.Cache.Delete(wxUserKey)
+	go wxUser.CleanCache()
 	type Ret struct {
 		Result bool `json:"result"`
 	}
@@ -551,3 +548,37 @@ func (self *UserController) SysUserBind() {
 	self.Data["json"] = ret
 	self.ServeJSON()
 }
+
+//修改用户信息
+func (self *UserController) UpdateUserInfo() {
+
+	nickName := self.GetString("nickname")
+	birthday := self.GetString("birthday")
+	sex, sexErr := self.GetInt64("sex")
+	//qq := self.GetString("qq")
+
+	user := self.GetCurrentUser(false)
+	wxUser := self.GetCurrentWxUser(false)
+	file, _, err := self.GetFile("head")
+	if err == nil {
+		user.UploadHead(file)
+		wxUser.Head = user.Head
+	}
+
+	if sexErr == nil {
+		user.Sex = sex
+		wxUser.Sex = sex
+	}
+
+	if birthday != "" {
+		t, _ := time.Parse("2006-01-02", birthday)
+		user.Birthday = t
+	}
+	user.Nickname = nickName
+	wxUser.Nickname = nickName
+	user.Save()
+	wxUser.Save()
+	// user.BirthdayStr = birthday
+	self.Data["json"] = wxUser
+	self.ServeJSON()
+}

+ 1 - 1
go/gopath/src/fohow.com/apps/controllers/xcx_controller/xcx_controller.go

@@ -127,7 +127,7 @@ func (self *XcxController) FigureChannel() {
 	cq := channel_xcx_qrcode_model.GetById(id)
 	beego.BeeLogger.Warn("xcx_controller.FigureChannel_(%v)", cq)
 	if cq != nil {
-		wxUId := self.GetCurrentWxUserId()
+		wxUId := self.GetCurrentWxUserIdByToken()
 		if wxUId > 0 {
 			beego.BeeLogger.Warn("xcx_controller.FigureChannel_wxUId_(%d)", wxUId)
 			go new(channel_xcx_qrcode_model.SignUpChannelQrcodeResult).Create(cq.Id, wxUId)

+ 106 - 0
go/gopath/src/fohow.com/apps/helper/aes.go

@@ -0,0 +1,106 @@
+package helper
+
+import (
+	"bytes"
+	"crypto/aes"
+	"crypto/cipher"
+	"encoding/base64"
+	"errors"
+)
+
+//加密base64
+func EnPwdCode(pwd []byte, key []byte, url bool) (string, error) {
+	result, err := AesEcrypt(pwd, key)
+	if err != nil {
+		return "", err
+	}
+	if url {
+		return base64.URLEncoding.EncodeToString(result), err
+	} else {
+		return base64.StdEncoding.EncodeToString(result), err
+	}
+
+}
+
+//解密
+func DePwdCode(pwd string, key []byte, url bool) ([]byte, error) {
+	var pwdByte []byte
+	var err error
+	if url {
+		pwdByte, err = base64.URLEncoding.DecodeString(pwd)
+		if err != nil {
+			return nil, err
+		}
+		//执行AES解密
+
+	} else {
+		pwdByte, err = base64.StdEncoding.DecodeString(pwd)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return AesDeCrypt(pwdByte, key)
+}
+
+//PKCS7 填充模式
+func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
+	padding := blockSize - len(ciphertext)%blockSize
+	//Repeat()函数的功能是把切片[]byte{byte(padding)}复制padding个,然后合并成新的字节切片返回
+	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
+	return append(ciphertext, padtext...)
+}
+
+//填充的反向操作,删除填充字符串
+func PKCS7UnPadding(origData []byte) ([]byte, error) {
+	//获取数据长度
+	length := len(origData)
+	if length == 0 {
+		return nil, errors.New("加密字符串错误!")
+	} else {
+		//获取填充字符串长度
+		unpadding := int(origData[length-1])
+		//截取切片,删除填充字节,并且返回明文
+		return origData[:(length - unpadding)], nil
+	}
+}
+
+//实现加密
+func AesEcrypt(origData []byte, key []byte) ([]byte, error) {
+	//创建加密算法实例
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		return nil, err
+	}
+	//获取块的大小
+	blockSize := block.BlockSize()
+	//对数据进行填充,让数据长度满足需求
+	origData = PKCS7Padding(origData, blockSize)
+	//采用AES加密方法中CBC加密模式
+	blocMode := cipher.NewCBCEncrypter(block, key[:blockSize])
+	crypted := make([]byte, len(origData))
+	//执行加密
+	blocMode.CryptBlocks(crypted, origData)
+	return crypted, nil
+}
+
+//实现解密
+func AesDeCrypt(cypted []byte, key []byte) ([]byte, error) {
+	//创建加密算法实例
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		return nil, err
+	}
+	//获取块大小
+	blockSize := block.BlockSize()
+	//创建加密客户端实例
+	blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
+	origData := make([]byte, len(cypted))
+	//这个函数也可以用来解密
+	blockMode.CryptBlocks(origData, cypted)
+	//去除填充字符串
+	origData, err = PKCS7UnPadding(origData)
+	if err != nil {
+		return nil, err
+	}
+	return origData, err
+}

+ 174 - 0
go/gopath/src/fohow.com/apps/helper/array.go

@@ -0,0 +1,174 @@
+package helper
+
+type Array struct {
+	data []interface{} // 泛型数组
+	size int           // 元素数量
+}
+
+type ArrayInterface interface {
+	// 添加
+	Add(int, interface{}) // 插入元素
+	AddLast(interface{})
+	AddFirst(interface{})
+	// 删除
+	Remove(int) interface{}
+	RemoveFirst() interface{}
+	RemoveLast() interface{}
+	// 查找
+	Find(interface{}) int      // 查找元素返回第一个索引
+	FindAll(interface{}) []int // 查找元素返回所有索引
+	Contains(interface{}) bool // 查找是否存在元素
+	Get(int) interface{}
+	// 修改
+	Set(int, interface{})
+	// 基本方法
+	GetCapacity() int // 获得数组容量
+	GetSize() int     // 获得元素个数
+	IsEmpty() bool    // 查看数组是否为空
+}
+
+// 获得自定义数组,参数为数组的初始长度
+func GetArray(capacity int) *Array {
+	arr := &Array{}
+	arr.data = make([]interface{}, capacity)
+	arr.size = 0
+	return arr
+}
+
+// 获得数组容量
+func (a *Array) GetCapacity() int {
+	return len(a.data)
+}
+
+// 获得数组元素个数
+func (a *Array) GetSize() int {
+	return a.size
+}
+
+// 判断数组是否为空
+func (a *Array) IsEmpty() bool {
+	return a.size == 0
+}
+
+// newCapacity 新数组容量
+// 逻辑:声明新的数组,将原数组的值 copy 到新数组中
+func (a *Array) resize(newCapacity int) {
+	newArr := make([]interface{}, newCapacity)
+	for i := 0; i < a.size; i++ {
+		newArr[i] = a.data[i]
+	}
+	a.data = newArr
+}
+
+// 获得元素的首个索引,不存在则返回 -1
+func (a *Array) Find(element interface{}) int {
+	for i := 0; i < a.size; i++ {
+		if element == a.data[i] {
+			return i
+		}
+	}
+	return -1
+}
+
+// 获得元素的所有索引,返回索引组成的切片
+func (a *Array) FindAll(element interface{}) (indexes []int) {
+	for i := 0; i < a.size; i++ {
+		if element == a.data[i] {
+			indexes = append(indexes, i)
+		}
+	}
+	return
+}
+
+// 查看数组是否存在元素,返回 bool
+func (a *Array) Contains(element interface{}) bool {
+	if a.Find(element) == -1 {
+		return false
+	}
+	return true
+}
+
+// 获得索引对应元素,需要判断索引有效范围
+func (a *Array) Get(index int) interface{} {
+	if index < 0 || index > a.size-1 {
+		panic("Get failed, index is illegal.")
+	}
+	return a.data[index]
+}
+
+//修改索引对应元素值
+func (a *Array) Set(index int, element interface{}) {
+	if index < 0 || index > a.size-1 {
+		panic("Set failed, index is illegal.")
+	}
+	a.data[index] = element
+}
+func (a *Array) Add(index int, element interface{}) {
+	if index < 0 || index > a.GetCapacity() {
+		panic("Add failed, require index >= 0 and index <= capacity")
+	}
+	// 数组已满则扩容
+	if a.size == len(a.data) {
+		a.resize(2 * a.size)
+	}
+	// 将插入的索引位置之后的元素后移,腾出插入位置
+	for i := a.size - 1; i >= index; i-- {
+		a.data[i+1] = a.data[i]
+	}
+	a.data[index] = element
+	// 维护数组元素的数量
+	a.size++
+}
+
+func (a *Array) AddLast(element interface{}) {
+	a.Add(a.size, element)
+}
+
+func (a *Array) AddFirst(element interface{}) {
+	a.Add(0, element)
+}
+
+func (a *Array) Remove(index int) interface{} {
+	if index < 0 || index >= a.size {
+		panic("Remove failed, index is illegal.")
+	}
+
+	removeEle := a.data[index]
+	// 从 index 之后的元素,都向前移动一个位置
+	for i := index + 1; i < a.size; i++ {
+		a.data[i-1] = a.data[i]
+	}
+	a.size--
+	// 清理最后一个元素
+	a.data[a.size] = nil
+
+	// 考虑边界情况,不能 resize 为0
+	if a.size == len(a.data)/4 && len(a.data)/2 != 0 {
+		a.resize(len(a.data) / 2)
+	}
+	return removeEle
+}
+
+func (a *Array) RemoveFirst() interface{} {
+	return a.Remove(0)
+}
+
+func (a *Array) RemoveLast() interface{} {
+	return a.Remove(a.size - 1)
+}
+
+//重写 String 方法
+//重写数组打印时的展示形式,只需要重写 String 方法
+//func (a *Array) String() string {
+//	var buffer bytes.Buffer
+//	buffer.WriteString(fmt.Sprintf("Array: size = %d, capacity = %d\n", a.size, a.GetCapacity()))
+//	buffer.WriteString("[")
+//	for i := 0; i < a.size; i++ {
+//		buffer.WriteString(fmt.Sprint(a.data[i]))
+//		if i != a.size - 1 {
+//			buffer.WriteString(",")
+//		}
+//	}
+//	buffer.WriteString("]")
+//	return buffer.String()
+//}//

+ 137 - 0
go/gopath/src/fohow.com/apps/helper/captcha/bilinear.go

@@ -0,0 +1,137 @@
+package captcha
+
+// Bilinear Interpolation 双线性插值
+// 引用自 code.google.com/p/graphics-go/interp
+// 主要处理旋转验证码后消除锯齿
+
+import (
+	"image"
+	"image/color"
+	"math"
+)
+
+var bili = Bilinear{}
+
+type Bilinear struct{}
+
+func (Bilinear) RGBA(src *image.RGBA, x, y float64) color.RGBA {
+	p := findLinearSrc(src.Bounds(), x, y)
+
+	// Array offsets for the surrounding pixels.
+	off00 := offRGBA(src, p.low.X, p.low.Y)
+	off01 := offRGBA(src, p.high.X, p.low.Y)
+	off10 := offRGBA(src, p.low.X, p.high.Y)
+	off11 := offRGBA(src, p.high.X, p.high.Y)
+
+	var fr, fg, fb, fa float64
+
+	fr += float64(src.Pix[off00+0]) * p.frac00
+	fg += float64(src.Pix[off00+1]) * p.frac00
+	fb += float64(src.Pix[off00+2]) * p.frac00
+	fa += float64(src.Pix[off00+3]) * p.frac00
+
+	fr += float64(src.Pix[off01+0]) * p.frac01
+	fg += float64(src.Pix[off01+1]) * p.frac01
+	fb += float64(src.Pix[off01+2]) * p.frac01
+	fa += float64(src.Pix[off01+3]) * p.frac01
+
+	fr += float64(src.Pix[off10+0]) * p.frac10
+	fg += float64(src.Pix[off10+1]) * p.frac10
+	fb += float64(src.Pix[off10+2]) * p.frac10
+	fa += float64(src.Pix[off10+3]) * p.frac10
+
+	fr += float64(src.Pix[off11+0]) * p.frac11
+	fg += float64(src.Pix[off11+1]) * p.frac11
+	fb += float64(src.Pix[off11+2]) * p.frac11
+	fa += float64(src.Pix[off11+3]) * p.frac11
+
+	var c color.RGBA
+	c.R = uint8(fr + 0.5)
+	c.G = uint8(fg + 0.5)
+	c.B = uint8(fb + 0.5)
+	c.A = uint8(fa + 0.5)
+	return c
+}
+
+type BilinearSrc struct {
+	// Top-left and bottom-right interpolation sources
+	low, high image.Point
+	// Fraction of each pixel to take. The 0 suffix indicates
+	// top/left, and the 1 suffix indicates bottom/right.
+	frac00, frac01, frac10, frac11 float64
+}
+
+func findLinearSrc(b image.Rectangle, sx, sy float64) BilinearSrc {
+	maxX := float64(b.Max.X)
+	maxY := float64(b.Max.Y)
+	minX := float64(b.Min.X)
+	minY := float64(b.Min.Y)
+	lowX := math.Floor(sx - 0.5)
+	lowY := math.Floor(sy - 0.5)
+	if lowX < minX {
+		lowX = minX
+	}
+	if lowY < minY {
+		lowY = minY
+	}
+
+	highX := math.Ceil(sx - 0.5)
+	highY := math.Ceil(sy - 0.5)
+	if highX >= maxX {
+		highX = maxX - 1
+	}
+	if highY >= maxY {
+		highY = maxY - 1
+	}
+
+	// In the variables below, the 0 suffix indicates top/left, and the
+	// 1 suffix indicates bottom/right.
+
+	// Center of each surrounding pixel.
+	x00 := lowX + 0.5
+	y00 := lowY + 0.5
+	x01 := highX + 0.5
+	y01 := lowY + 0.5
+	x10 := lowX + 0.5
+	y10 := highY + 0.5
+	x11 := highX + 0.5
+	y11 := highY + 0.5
+
+	p := BilinearSrc{
+		low:  image.Pt(int(lowX), int(lowY)),
+		high: image.Pt(int(highX), int(highY)),
+	}
+
+	// Literally, edge cases. If we are close enough to the edge of
+	// the image, curtail the interpolation sources.
+	if lowX == highX && lowY == highY {
+		p.frac00 = 1.0
+	} else if sy-minY <= 0.5 && sx-minX <= 0.5 {
+		p.frac00 = 1.0
+	} else if maxY-sy <= 0.5 && maxX-sx <= 0.5 {
+		p.frac11 = 1.0
+	} else if sy-minY <= 0.5 || lowY == highY {
+		p.frac00 = x01 - sx
+		p.frac01 = sx - x00
+	} else if sx-minX <= 0.5 || lowX == highX {
+		p.frac00 = y10 - sy
+		p.frac10 = sy - y00
+	} else if maxY-sy <= 0.5 {
+		p.frac10 = x11 - sx
+		p.frac11 = sx - x10
+	} else if maxX-sx <= 0.5 {
+		p.frac01 = y11 - sy
+		p.frac11 = sy - y01
+	} else {
+		p.frac00 = (x01 - sx) * (y10 - sy)
+		p.frac01 = (sx - x00) * (y11 - sy)
+		p.frac10 = (x11 - sx) * (sy - y00)
+		p.frac11 = (sx - x10) * (sy - y01)
+	}
+
+	return p
+}
+
+func offRGBA(src *image.RGBA, x, y int) int {
+	return (y-src.Rect.Min.Y)*src.Stride + (x-src.Rect.Min.X)*4
+}

+ 273 - 0
go/gopath/src/fohow.com/apps/helper/captcha/captcha.go

@@ -0,0 +1,273 @@
+package captcha
+
+import (
+	"github.com/golang/freetype"
+	"github.com/golang/freetype/truetype"
+	"image"
+	"image/color"
+	"image/draw"
+	"io/ioutil"
+	"math"
+	"math/rand"
+	"time"
+)
+
+type Captcha struct {
+	frontColors []color.Color
+	bkgColors   []color.Color
+	disturlvl   DisturLevel
+	fonts       []*truetype.Font
+	size        image.Point
+}
+
+type StrType int
+
+const (
+	NUM   StrType = iota // 数字
+	LOWER                // 小写字母
+	UPPER                // 大写字母
+	ALL                  // 全部
+	CLEAR                // 去除部分易混淆的字符
+)
+
+type DisturLevel int
+
+const (
+	NORMAL DisturLevel = 4
+	MEDIUM DisturLevel = 8
+	HIGH   DisturLevel = 16
+)
+
+func New() *Captcha {
+	c := &Captcha{
+		disturlvl: HIGH,
+		size:      image.Point{82, 32},
+	}
+	c.frontColors = []color.Color{color.Black}
+	c.bkgColors = []color.Color{color.Transparent}
+	c.SetFont("config/font/comic.ttf")
+	return c
+}
+
+// AddFont 添加一个字体
+func (c *Captcha) AddFont(path string) error {
+	fontdata, erro := ioutil.ReadFile(path)
+	if erro != nil {
+		return erro
+	}
+	font, erro := freetype.ParseFont(fontdata)
+	if erro != nil {
+		return erro
+	}
+	if c.fonts == nil {
+		c.fonts = []*truetype.Font{}
+	}
+	c.fonts = append(c.fonts, font)
+	return nil
+}
+
+//AddFontFromBytes allows to load font from slice of bytes, for example, load the font packed by https://github.com/jteeuwen/go-bindata
+func (c *Captcha) AddFontFromBytes(contents []byte) error {
+	font, err := freetype.ParseFont(contents)
+	if err != nil {
+		return err
+	}
+	if c.fonts == nil {
+		c.fonts = []*truetype.Font{}
+	}
+	c.fonts = append(c.fonts, font)
+	return nil
+}
+
+// SetFont 设置字体 可以设置多个
+func (c *Captcha) SetFont(paths ...string) error {
+	for _, v := range paths {
+		if erro := c.AddFont(v); erro != nil {
+			return erro
+		}
+	}
+	return nil
+}
+
+func (c *Captcha) SetDisturbance(d DisturLevel) {
+	if d > 0 {
+		c.disturlvl = d
+	}
+}
+
+func (c *Captcha) SetFrontColor(colors ...color.Color) {
+	if len(colors) > 0 {
+		c.frontColors = c.frontColors[:0]
+		for _, v := range colors {
+			c.frontColors = append(c.frontColors, v)
+		}
+	}
+}
+
+func (c *Captcha) SetBkgColor(colors ...color.Color) {
+	if len(colors) > 0 {
+		c.bkgColors = c.bkgColors[:0]
+		for _, v := range colors {
+			c.bkgColors = append(c.bkgColors, v)
+		}
+	}
+}
+
+func (c *Captcha) SetSize(w, h int) {
+	if w < 48 {
+		w = 48
+	}
+	if h < 20 {
+		h = 20
+	}
+	c.size = image.Point{w, h}
+}
+
+func (c *Captcha) randFont() *truetype.Font {
+	return c.fonts[rand.Intn(len(c.fonts))]
+}
+
+// 绘制背景
+func (c *Captcha) drawBkg(img *Image) {
+	/*ra := rand.New(rand.NewSource(time.Now().UnixNano()))
+	//填充主背景色
+	bgcolorindex := ra.Intn(len(c.bkgColors))
+	bkg := image.NewUniform(c.bkgColors[bgcolorindex])
+	img.FillBkg(bkg)*/
+}
+
+// 绘制噪点
+func (c *Captcha) drawNoises(img *Image) {
+	ra := rand.New(rand.NewSource(time.Now().UnixNano()))
+
+	// 待绘制图片的尺寸
+	size := img.Bounds().Size()
+	dlen := int(c.disturlvl)
+	// 绘制干扰斑点
+	for i := 0; i < dlen; i++ {
+		x := ra.Intn(size.X)
+		y := ra.Intn(size.Y)
+		r := ra.Intn(size.Y/20) + 1
+		colorindex := ra.Intn(len(c.frontColors))
+		img.DrawCircle(x, y, r, i%4 != 0, c.frontColors[colorindex])
+	}
+
+	// 绘制干扰线
+	for i := 0; i < dlen; i++ {
+		x := ra.Intn(size.X)
+		y := ra.Intn(size.Y)
+		o := int(math.Pow(-1, float64(i)))
+		w := ra.Intn(size.Y) * o
+		h := ra.Intn(size.Y/10) * o
+		colorindex := ra.Intn(len(c.frontColors))
+		img.DrawLine(x, y, x+w, y+h, c.frontColors[colorindex])
+		colorindex++
+	}
+
+}
+
+// 绘制文字
+func (c *Captcha) drawString(img *Image, str string) {
+
+	if c.fonts == nil {
+		panic("没有设置任何字体")
+	}
+	tmp := NewImage(c.size.X, c.size.Y)
+
+	// 文字大小为图片高度的 0.6
+	fsize := int(float64(c.size.Y) * 0.6)
+	// 用于生成随机角度
+	r := rand.New(rand.NewSource(time.Now().UnixNano()))
+
+	// 文字之间的距离
+	// 左右各留文字的1/4大小为内部边距
+	padding := fsize / 4
+	gap := (c.size.X - padding*2) / (len(str))
+
+	// 逐个绘制文字到图片上
+	for i, char := range str {
+		// 创建单个文字图片
+		// 以文字为尺寸创建正方形的图形
+		str := NewImage(fsize, fsize)
+		// str.FillBkg(image.NewUniform(color.Black))
+		// 随机取一个前景色
+		colorindex := r.Intn(len(c.frontColors))
+
+		//随机取一个字体
+		font := c.randFont()
+		str.DrawString(font, c.frontColors[colorindex], string(char), float64(fsize))
+
+		// 转换角度后的文字图形
+		rs := str.Rotate(float64(r.Intn(40) - 20))
+		// 计算文字位置
+		s := rs.Bounds().Size()
+		left := i*gap + padding
+		top := (c.size.Y - s.Y) / 2
+		// 绘制到图片上
+		draw.Draw(tmp, image.Rect(left, top, left+s.X, top+s.Y), rs, image.ZP, draw.Over)
+	}
+
+	if c.size.Y >= 48 {
+		// 高度大于48添加波纹 小于48波纹影响用户识别
+		tmp.distortTo(float64(fsize)/10, 200.0)
+	}
+
+	/*font := c.randFont()
+	t := strings.ToUpper(helper.NewHash(helper.NewUUID().Bytes()).Md5().String())
+	tmp.DrawString(font, color.RGBA{98, 98, 98, 255}, t, 6)*/
+
+	draw.Draw(img, tmp.Bounds(), tmp, image.ZP, draw.Over)
+}
+
+// Create 生成一个验证码图片
+func (c *Captcha) Create(num int, t StrType) (*Image, string) {
+	if num <= 0 {
+		num = 4
+	}
+	dst := NewImage(c.size.X, c.size.Y)
+	//tmp := NewImage(c.size.X, c.size.Y)
+	c.drawBkg(dst)
+	c.drawNoises(dst)
+
+	str := string(c.randStr(num, int(t)))
+	c.drawString(dst, str)
+
+	/*uuid := helper.NewUUID().String()
+	c.drawString(dst, uuid)*/
+
+	return dst, str
+}
+
+func (c *Captcha) CreateCustom(str string) *Image {
+	if len(str) == 0 {
+		str = "unkown"
+	}
+	dst := NewImage(c.size.X, c.size.Y)
+	c.drawBkg(dst)
+	c.drawNoises(dst)
+	c.drawString(dst, str)
+	return dst
+}
+
+var fontKinds = [][]int{{10, 48}, {26, 97}, {26, 65}}
+var letters = []byte("34578acdefghjkmnpqstwxyABCDEFGHJKMNPQRSVWXY")
+
+// 生成随机字符串
+// size 个数 kind 模式
+func (c *Captcha) randStr(size int, kind int) []byte {
+	ikind, result := kind, make([]byte, size)
+	isAll := kind > 2 || kind < 0
+	rand.Seed(time.Now().UnixNano())
+	for i := 0; i < size; i++ {
+		if isAll {
+			ikind = rand.Intn(3)
+		}
+		scope, base := fontKinds[ikind][0], fontKinds[ikind][1]
+		result[i] = uint8(base + rand.Intn(scope))
+		// 不易混淆字符模式:重新生成字符
+		if kind == 4 {
+			result[i] = letters[rand.Intn(len(letters))]
+		}
+	}
+	return result
+}

+ 224 - 0
go/gopath/src/fohow.com/apps/helper/captcha/draw.go

@@ -0,0 +1,224 @@
+package captcha
+
+import (
+	"github.com/golang/freetype"
+	"github.com/golang/freetype/truetype"
+	"image"
+	"image/color"
+	"image/draw"
+	"math"
+)
+
+// Image 图片
+type Image struct {
+	*image.RGBA
+}
+
+// NewImage 创建一个新的图片
+func NewImage(w, h int) *Image {
+	img := &Image{image.NewRGBA(image.Rect(0, 0, w, h))}
+	return img
+}
+
+func sign(x int) int {
+	if x > 0 {
+		return 1
+	}
+	return -1
+}
+
+// DrawLine 画直线
+// Bresenham算法(https://zh.wikipedia.org/zh-cn/布雷森漢姆直線演算法)
+// x1,y1 起点 x2,y2终点
+func (img *Image) DrawLine(x1, y1, x2, y2 int, c color.Color) {
+	dx, dy, flag := int(math.Abs(float64(x2-x1))),
+		int(math.Abs(float64(y2-y1))),
+		false
+	if dy > dx {
+		flag = true
+		x1, y1 = y1, x1
+		x2, y2 = y2, x2
+		dx, dy = dy, dx
+	}
+	ix, iy := sign(x2-x1), sign(y2-y1)
+	n2dy := dy * 2
+	n2dydx := (dy - dx) * 2
+	d := n2dy - dx
+	for x1 != x2 {
+		if d < 0 {
+			d += n2dy
+		} else {
+			y1 += iy
+			d += n2dydx
+		}
+		if flag {
+			img.Set(y1, x1, c)
+		} else {
+			img.Set(x1, y1, c)
+		}
+		x1 += ix
+	}
+}
+
+func (img *Image) drawCircle8(xc, yc, x, y int, c color.Color) {
+	img.Set(xc+x, yc+y, c)
+	img.Set(xc-x, yc+y, c)
+	img.Set(xc+x, yc-y, c)
+	img.Set(xc-x, yc-y, c)
+	img.Set(xc+y, yc+x, c)
+	img.Set(xc-y, yc+x, c)
+	img.Set(xc+y, yc-x, c)
+	img.Set(xc-y, yc-x, c)
+}
+
+// DrawCircle 画圆
+// xc,yc 圆心坐标 r 半径 fill是否填充颜色
+func (img *Image) DrawCircle(xc, yc, r int, fill bool, c color.Color) {
+	size := img.Bounds().Size()
+	// 如果圆在图片可见区域外,直接退出
+	if xc+r < 0 || xc-r >= size.X || yc+r < 0 || yc-r >= size.Y {
+		return
+	}
+	x, y, d := 0, r, 3-2*r
+	for x <= y {
+		if fill {
+			for yi := x; yi <= y; yi++ {
+				img.drawCircle8(xc, yc, x, yi, c)
+			}
+		} else {
+			img.drawCircle8(xc, yc, x, y, c)
+		}
+		if d < 0 {
+			d = d + 4*x + 6
+		} else {
+			d = d + 4*(x-y) + 10
+			y--
+		}
+		x++
+	}
+}
+
+// DrawString 写字
+func (img *Image) DrawString(font *truetype.Font, c color.Color, str string, fontsize float64) {
+	ctx := freetype.NewContext()
+	// default 72dpi
+	ctx.SetDst(img)
+	ctx.SetClip(img.Bounds())
+	ctx.SetSrc(image.NewUniform(c))
+	ctx.SetFontSize(fontsize)
+	ctx.SetFont(font)
+	// 写入文字的位置
+	pt := freetype.Pt(0, int(-fontsize/6)+ctx.PointToFixed(fontsize).Ceil())
+	ctx.DrawString(str, pt)
+}
+
+// Rotate 旋转
+func (img *Image) Rotate(angle float64) image.Image {
+	return new(rotate).Rotate(angle, img.RGBA).transformRGBA()
+}
+
+// 填充背景
+func (img *Image) FillBkg(c image.Image) {
+	draw.Draw(img, img.Bounds(), c, image.ZP, draw.Over)
+}
+
+// 水波纹, amplude=振幅, period=周期
+// copy from https://github.com/dchest/captcha/blob/master/image.go
+func (img *Image) distortTo(amplude float64, period float64) {
+	w := img.Bounds().Max.X
+	h := img.Bounds().Max.Y
+
+	oldm := img.RGBA
+
+	dx := 1.4 * math.Pi / period
+	for x := 0; x < w; x++ {
+		for y := 0; y < h; y++ {
+			xo := amplude * math.Sin(float64(y)*dx)
+			yo := amplude * math.Cos(float64(x)*dx)
+			rgba := oldm.RGBAAt(x+int(xo), y+int(yo))
+			if rgba.A > 0 {
+				oldm.SetRGBA(x, y, rgba)
+			}
+		}
+	}
+}
+
+func inBounds(b image.Rectangle, x, y float64) bool {
+	if x < float64(b.Min.X) || x >= float64(b.Max.X) {
+		return false
+	}
+	if y < float64(b.Min.Y) || y >= float64(b.Max.Y) {
+		return false
+	}
+	return true
+}
+
+type rotate struct {
+	dx   float64
+	dy   float64
+	sin  float64
+	cos  float64
+	neww float64
+	newh float64
+	src  *image.RGBA
+}
+
+func radian(angle float64) float64 {
+	return angle * math.Pi / 180.0
+}
+
+func (r *rotate) Rotate(angle float64, src *image.RGBA) *rotate {
+	r.src = src
+	srsize := src.Bounds().Size()
+	width, height := srsize.X, srsize.Y
+
+	// 源图四个角的坐标(以图像中心为坐标系原点)
+	// 左下角,右下角,左上角,右上角
+	srcwp, srchp := float64(width)*0.5, float64(height)*0.5
+	srcx1, srcy1 := -srcwp, srchp
+	srcx2, srcy2 := srcwp, srchp
+	srcx3, srcy3 := -srcwp, -srchp
+	srcx4, srcy4 := srcwp, -srchp
+
+	r.sin, r.cos = math.Sincos(radian(angle))
+	// 旋转后的四角坐标
+	desx1, desy1 := r.cos*srcx1+r.sin*srcy1, -r.sin*srcx1+r.cos*srcy1
+	desx2, desy2 := r.cos*srcx2+r.sin*srcy2, -r.sin*srcx2+r.cos*srcy2
+	desx3, desy3 := r.cos*srcx3+r.sin*srcy3, -r.sin*srcx3+r.cos*srcy3
+	desx4, desy4 := r.cos*srcx4+r.sin*srcy4, -r.sin*srcx4+r.cos*srcy4
+
+	// 新的高度很宽度
+	r.neww = math.Max(math.Abs(desx4-desx1), math.Abs(desx3-desx2)) + 0.5
+	r.newh = math.Max(math.Abs(desy4-desy1), math.Abs(desy3-desy2)) + 0.5
+	r.dx = -0.5*r.neww*r.cos - 0.5*r.newh*r.sin + srcwp
+	r.dy = 0.5*r.neww*r.sin - 0.5*r.newh*r.cos + srchp
+	return r
+}
+
+func (r *rotate) pt(x, y int) (float64, float64) {
+	return float64(-y)*r.sin + float64(x)*r.cos + r.dy,
+		float64(y)*r.cos + float64(x)*r.sin + r.dx
+}
+
+func (r *rotate) transformRGBA() image.Image {
+
+	srcb := r.src.Bounds()
+	b := image.Rect(0, 0, int(r.neww), int(r.newh))
+	dst := image.NewRGBA(b)
+
+	for y := b.Min.Y; y < b.Max.Y; y++ {
+		for x := b.Min.X; x < b.Max.X; x++ {
+			sx, sy := r.pt(x, y)
+			if inBounds(srcb, sx, sy) {
+				// 消除锯齿填色
+				c := bili.RGBA(r.src, sx, sy)
+				off := (y-dst.Rect.Min.Y)*dst.Stride + (x-dst.Rect.Min.X)*4
+				dst.Pix[off+0] = c.R
+				dst.Pix[off+1] = c.G
+				dst.Pix[off+2] = c.B
+				dst.Pix[off+3] = c.A
+			}
+		}
+	}
+	return dst
+}

+ 60 - 0
go/gopath/src/fohow.com/apps/helper/hash.go

@@ -0,0 +1,60 @@
+package helper
+
+import (
+	"crypto/md5"
+	"crypto/sha1"
+	"crypto/sha256"
+	"crypto/sha512"
+	"fmt"
+)
+
+type Hash struct {
+	data []byte
+}
+type HashData struct {
+	hash interface{}
+}
+
+func NewHashData(hash interface{}) *HashData {
+	return &HashData{hash: hash}
+}
+func NewHash(data []byte) *Hash {
+	return &Hash{data: data}
+}
+
+//Md5
+func (d *Hash) Md5() *HashData {
+	return NewHashData(md5.Sum(d.data))
+}
+
+//Sha1
+func (d *Hash) Sha1() *HashData {
+	return NewHashData(sha1.Sum(d.data))
+}
+
+//Sha256
+func (d *Hash) Sha256() *HashData {
+	return NewHashData(sha256.Sum256(d.data))
+}
+
+//Sha512
+func (d *Hash) Sha512() *HashData {
+	return NewHashData(sha512.Sum512(d.data))
+}
+
+//返回加密byte
+func (d *HashData) Result() interface{} {
+	return d.hash
+}
+
+//返回加密字符
+func (d *HashData) String() (s string) {
+	switch v := d.hash.(type) {
+	case [16]byte, [20]byte, [32]byte, [64]byte:
+		s = fmt.Sprintf("%x", v)
+	default:
+		s = ""
+	}
+	return s
+
+}

File diff suppressed because it is too large
+ 151 - 0
go/gopath/src/fohow.com/apps/helper/idcard.go


File diff suppressed because it is too large
+ 1136 - 0
go/gopath/src/fohow.com/apps/helper/ip/ip2location.go


+ 146 - 0
go/gopath/src/fohow.com/apps/helper/math.go

@@ -0,0 +1,146 @@
+package helper
+
+import (
+	"errors"
+	"math"
+	"math/rand"
+	"strconv"
+	"time"
+)
+
+type Math struct {
+}
+
+func NewMath() *Math {
+	return &Math{}
+}
+
+//返回绝对值
+func (s *Math) Abs(number float64) float64 {
+	return math.Abs(number)
+}
+
+//返回随机整数
+func (s *Math) Rand(min int, max int) (int, error) {
+	if min > max {
+		return 0, errors.New("min: min cannot be greater than max")
+	}
+	if int31 := 1<<31 - 1; max > int31 {
+		return 0, errors.New("max: max can not be greater than " + strconv.Itoa(int31))
+	}
+	if min == max {
+		return min, nil
+	}
+	r := rand.New(rand.NewSource(time.Now().UnixNano()))
+	return r.Intn(max+1-min) + min, nil
+}
+
+//对浮点数进行四舍五入
+func (s *Math) Round(value float64) float64 {
+	return math.Floor(value + 0.5)
+}
+
+//向下舍入为最接近的整数
+func (s *Math) Floor(value float64) float64 {
+	return math.Floor(value)
+}
+
+//向上舍入为最接近的整数
+func (s *Math) Ceil(value float64) float64 {
+	return math.Ceil(value)
+}
+
+//返回圆周率的值
+func (s *Math) Pi() float64 {
+	return math.Pi
+}
+
+//返回最大值
+func (s *Math) Max(nums ...float64) (float64, error) {
+	if len(nums) < 2 {
+		return 0, errors.New("nums: the nums length is less than 2")
+	}
+	max := nums[0]
+	for i := 1; i < len(nums); i++ {
+		max = math.Max(max, nums[i])
+	}
+	return max, nil
+}
+
+//返回最小值
+func (s *Math) Min(nums ...float64) (float64, error) {
+	if len(nums) < 2 {
+		return 0, errors.New("nums: the nums length is less than 2")
+	}
+	min := nums[0]
+	for i := 1; i < len(nums); i++ {
+		min = math.Min(min, nums[i])
+	}
+	return min, nil
+}
+
+//十进制转换为二进制
+func (s *Math) Decbin(number int64) string {
+	return strconv.FormatInt(number, 2)
+}
+
+//二进制转换为十进制
+func (s *Math) Bindec(str string) (string, error) {
+	i, err := strconv.ParseInt(str, 2, 0)
+	if err != nil {
+		return "", err
+	}
+	return strconv.FormatInt(i, 10), nil
+}
+
+//十六进制值转换为 ASCII 字符
+func (s *Math) Hex2bin(data string) (string, error) {
+	i, err := strconv.ParseInt(data, 16, 0)
+	if err != nil {
+		return "", err
+	}
+	return strconv.FormatInt(i, 2), nil
+}
+
+//ASCII 字符的字符串转换为十六进制值
+func (s *Math) Bin2hex(str string) (string, error) {
+	i, err := strconv.ParseInt(str, 2, 0)
+	if err != nil {
+		return "", err
+	}
+	return strconv.FormatInt(i, 16), nil
+}
+
+//十进制转换为十六进制
+func (s *Math) Dechex(number int64) string {
+	return strconv.FormatInt(number, 16)
+}
+
+//十六进制转换为十进制
+func (s *Math) Hexdec(str string) (int64, error) {
+	return strconv.ParseInt(str, 16, 0)
+}
+
+//十进制转换为八进制
+func (s *Math) Decoct(number int64) string {
+	return strconv.FormatInt(number, 8)
+}
+
+//八进制转换为十进制
+func (s *Math) Octdec(str string) (int64, error) {
+	return strconv.ParseInt(str, 8, 0)
+}
+
+//任意进制之间转换数字
+func (s *Math) BaseConvert(number string, frombase, tobase int) (string, error) {
+	i, err := strconv.ParseInt(number, frombase, 0)
+	if err != nil {
+		return "", err
+	}
+	return strconv.FormatInt(i, tobase), nil
+}
+
+//判断是否为合法数值
+func (s *Math) IsNan(val float64) bool {
+	return math.IsNaN(val)
+}

+ 166 - 0
go/gopath/src/fohow.com/apps/helper/mime.go

@@ -0,0 +1,166 @@
+package helper
+
+var MimeExt = map[string]string{
+	"image/jpg":                   "jpg",
+	"image/jpeg":                  "jpeg",
+	"image/png":                   "png",
+	"image/gif":                   "gif",
+	"image/webp":                  "webp",
+	"image/x-canon-cr2":           "cr2",
+	"image/tiff":                  "tif",
+	"image/bmp":                   "bmp",
+	"image/heif":                  "heif",
+	"image/vnd.ms-photo":          "jxr",
+	"image/vnd.adobe.photoshop":   "psd",
+	"image/vnd.microsoft.icon":    "ico",
+	"image/vnd.dwg":               "dwg",
+	"video/mp4":                   "mp4",
+	"video/x-m4v":                 "m4v",
+	"video/x-matroska":            "mkv",
+	"video/webm":                  "webm",
+	"video/quicktime":             "mov",
+	"video/x-msvideo":             "avi",
+	"video/x-ms-wmv":              "wmv",
+	"video/mpeg":                  "mpg",
+	"video/x-flv":                 "flv",
+	"video/3gpp":                  "3gp",
+	"audio/midi":                  "mid",
+	"audio/mpeg":                  "mp3",
+	"audio/m4a":                   "m4a",
+	"audio/ogg":                   "ogg",
+	"audio/x-flac":                "flac",
+	"audio/x-wav":                 "wav",
+	"audio/amr":                   "amr",
+	"audio/aac":                   "aac",
+	"application/epub+zip":        "epub",
+	"application/zip":             "zip",
+	"application/x-tar":           "tar",
+	"application/vnd.rar":         "rar",
+	"application/gzip":            "gz",
+	"application/x-bzip2":         "bz2",
+	"application/x-7z-compressed": "7z",
+	"application/x-xz":            "xz",
+	"application/pdf":             "pdf",
+	"application/vnd.microsoft.portable-executable": "exe",
+	"application/x-shockwave-flash":                 "swf",
+	"application/rtf":                               "rtf",
+	"application/x-iso9660-image":                   "iso",
+	"application/octet-stream":                      "eot",
+	"application/postscript":                        "ps",
+	"application/vnd.sqlite3":                       "sqlite",
+	"application/x-nintendo-nes-rom":                "nes",
+	"application/x-google-chrome-extension":         "crx",
+	"application/vnd.ms-cab-compressed":             "cab",
+	"application/vnd.debian.binary-package":         "deb",
+	"application/x-unix-archive":                    "ar",
+	"application/x-compress":                        "Z",
+	"application/x-lzip":                            "lz",
+	"application/x-rpm":                             "rpm",
+	"application/x-executable":                      "elf",
+	"application/dicom":                             "dcm",
+	"application/msword":                            "doc",
+	"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
+	"application/vnd.ms-excel": "xls",
+	"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":         "xlsx",
+	"application/vnd.ms-powerpoint":                                             "ppt",
+	"application/vnd.openxmlformats-officedocument.presentationml.presentation": "pptx",
+}
+
+var ImageMime = map[string]string{
+	"jpg":  "image/jpg",
+	"jpeg": "image/jpeg",
+	"png":  "image/png",
+	"gif":  "image/gif",
+	"webp": "image/webp",
+	"cr2":  "image/x-canon-cr2",
+	"tif":  "image/tiff",
+	"bmp":  "image/bmp",
+	"heif": "image/heif",
+	"jxr":  "image/vnd.ms-photo",
+	"psd":  "image/vnd.adobe.photoshop",
+	"ico":  "image/vnd.microsoft.icon",
+	"dwg":  "image/vnd.dwg",
+}
+var VideoMime = map[string]string{
+	"mp4":  "video/mp4",
+	"m4v":  "video/x-m4v",
+	"mkv":  "video/x-matroska",
+	"webm": "video/webm",
+	"mov":  "video/quicktime",
+	"avi":  "video/x-msvideo",
+	"wmv":  "video/x-ms-wmv",
+	"mpg":  "video/mpeg",
+	"flv":  "video/x-flv",
+	"3gp":  "video/3gpp",
+}
+var AudioMime = map[string]string{
+	"mid":  "audio/midi",
+	"mp3":  "audio/mpeg",
+	"m4a":  "audio/m4a",
+	"ogg":  "audio/ogg",
+	"flac": "audio/x-flac",
+	"wav":  "audio/x-wav",
+	"amr":  "audio/amr",
+	"aac":  "audio/aac",
+}
+var DocumentMime = map[string]string{
+	"dcm":  "application/dicom",
+	"doc":  "application/msword",
+	"docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+	"xls":  "application/vnd.ms-excel",
+	"xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+	"ppt":  "application/vnd.ms-powerpoint",
+	"pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
+}
+var ArchiveMime = map[string]string{
+	"epub":   "application/epub+zip",
+	"zip":    "application/zip",
+	"tar":    "application/x-tar",
+	"rar":    "application/vnd.rar",
+	"gz":     "application/gzip",
+	"bz2":    "application/x-bzip2",
+	"7z":     "application/x-7z-compressed",
+	"xz":     "application/x-xz",
+	"pdf":    "application/pdf",
+	"exe":    "application/vnd.microsoft.portable-executable",
+	"swf":    "application/x-shockwave-flash",
+	"rtf":    "application/rtf",
+	"iso":    "application/x-iso9660-image",
+	"eot":    "application/octet-stream",
+	"ps":     "application/postscript",
+	"sqlite": "application/vnd.sqlite3",
+	"nes":    "application/x-nintendo-nes-rom",
+	"crx":    "application/x-google-chrome-extension",
+	"cab":    "application/vnd.ms-cab-compressed",
+	"deb":    "application/vnd.debian.binary-package",
+	"ar":     "application/x-unix-archive",
+	"Z":      "application/x-compress",
+	"lz":     "application/x-lzip",
+	"rpm":    "application/x-rpm",
+	"elf":    "application/x-executable",
+}
+
+const TYPE_IMAGE = "image"
+const TYPE_VIDEO = "video"
+const TYPE_AUDIO = "audio"
+const TYPE_ARCHIVE = "archive"
+const TYPE_DOCUMENTS = "document"
+
+func GetMime(e string, t string) (mime string, ok bool) {
+	if t == TYPE_VIDEO {
+		mime, ok = VideoMime[e]
+	} else if t == TYPE_AUDIO {
+		mime, ok = AudioMime[e]
+	} else if t == TYPE_ARCHIVE {
+		mime, ok = ArchiveMime[e]
+	} else if t == TYPE_DOCUMENTS {
+		mime, ok = DocumentMime[e]
+	} else if t == TYPE_IMAGE {
+		mime, ok = ImageMime[e]
+	}
+	return
+}
+func GetExt(m string) (ext string, ok bool) {
+	ext, ok = MimeExt[m]
+	return
+}

+ 147 - 0
go/gopath/src/fohow.com/apps/helper/random.go

@@ -0,0 +1,147 @@
+package helper
+
+import (
+	"encoding/hex"
+	"math"
+	"math/rand"
+	"time"
+)
+
+type Random struct {
+	rand *rand.Rand
+}
+
+type RandomSpec struct {
+	Value []rune
+}
+
+func NewRandomSpec(value []rune) *RandomSpec {
+	return &RandomSpec{Value: value}
+}
+
+type UUID struct {
+	bytes []byte
+}
+
+//生成UUID
+func NewUUID() *UUID {
+	bytes := make([]byte, 16)
+	rand.Read(bytes)
+	bytes[6] = byte(0x40 | (int(bytes[6]) & 0xf))
+	bytes[8] = byte(0x80 | (int(bytes[8]) & 0x3f))
+	return &UUID{bytes: bytes}
+}
+
+func NewRandom() *Random {
+	return &Random{rand.New(rand.NewSource(time.Now().UnixNano()))}
+}
+func (v *RandomSpec) Result() *Result {
+	return NewResult(v.String())
+}
+
+//返回随机数为字符
+func (s *RandomSpec) String() string {
+	return string(s.Value)
+}
+
+//返回UUID为字符
+func (uuid *UUID) String() string {
+	str := hex.EncodeToString(uuid.bytes)
+	return str[:8] + "-" + str[8:12] + "-" + str[12:16] + "-" + str[16:20] + "-" + str[20:]
+}
+func (uuid *UUID) Result() *Result {
+	return NewResult(uuid.String())
+}
+
+//返回UUID为Bytes
+func (uuid *UUID) Bytes() []byte {
+	val := make([]byte, 16)
+	copy(val, uuid.bytes)
+	return val
+}
+
+//生成指定区间随机数
+func (r Random) RandInt(min, max int) int {
+	if min >= max || min == 0 || max == 0 {
+		return max
+	}
+	return r.Intn(max-min) + min
+}
+
+//随机数
+func (r Random) Intn(size int) int {
+	return r.rand.Intn(size)
+}
+
+//随机字母
+func (r Random) Alpha(size int) *RandomSpec {
+	return NewRandomSpec(r.Spec(size, 0, 0, true, false, nil))
+}
+
+//随机字母和数字
+func (r Random) AlphaNum(size int) *RandomSpec {
+	return NewRandomSpec(r.Spec(size, 0, 0, true, true, nil))
+}
+
+//随机数字
+func (r Random) Num(size int) *RandomSpec {
+	return NewRandomSpec(r.Spec(size, 0, 0, false, true, nil))
+}
+
+//随机Ascii
+func (r Random) Ascii(size int) *RandomSpec {
+	return NewRandomSpec(r.Spec(size, 32, 127, false, false, nil))
+}
+
+func (r Random) Spec(count int, start, end int, letters, numbers bool, chars []rune) []rune {
+	if count == 0 {
+		return nil
+	}
+	if start == 0 && end == 0 {
+		end = 'z' + 1
+		start = ' '
+		if !letters && !numbers {
+			start = 0
+			end = math.MaxInt32
+		}
+	}
+	buffer := make([]rune, count)
+	gap := end - start
+	for count != 0 {
+		count--
+		var ch rune
+		if len(chars) == 0 {
+			ch = rune(r.Intn(gap) + start)
+		} else {
+			ch = chars[r.Intn(gap)+start]
+		}
+		if letters && ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) ||
+			numbers && (ch >= '0' && ch <= '9') ||
+			(!letters && !numbers) {
+			if ch >= rune(56320) && ch <= rune(57343) {
+				if count == 0 {
+					count++
+				} else {
+					buffer[count] = ch
+					count--
+					buffer[count] = rune(55296 + r.Intn(128))
+				}
+			} else if ch >= rune(55296) && ch <= rune(56191) {
+				if count == 0 {
+					count++
+				} else {
+					buffer[count] = rune(56320 + r.Intn(128))
+					count--
+					buffer[count] = ch
+				}
+			} else if ch >= rune(56192) && ch <= rune(56319) {
+				count++
+			} else {
+				buffer[count] = ch
+			}
+		} else {
+			count++
+		}
+	}
+	return buffer
+}

+ 113 - 0
go/gopath/src/fohow.com/apps/helper/raw.go

@@ -0,0 +1,113 @@
+package helper
+
+import (
+	"encoding/json"
+	"fmt"
+	"reflect"
+	"strconv"
+)
+
+type Raw struct {
+	val interface{}
+}
+type argInt []int
+
+func NewRaw(val interface{}) *Raw {
+	return &Raw{val: val}
+}
+
+//json解码
+func (v *Raw) JSONDecode(val interface{}) error {
+	return json.Unmarshal(v.val.([]byte), val)
+}
+
+//json加密
+func (v *Raw) JSONEncode() ([]byte, error) {
+	j, err := json.Marshal(v.val)
+	if err == nil {
+		return j, nil
+	}
+	return nil, err
+}
+func (a argInt) Get(i int, args ...int) (r int) {
+	if i >= 0 && i < len(a) {
+		r = a[i]
+	}
+	if len(args) > 0 {
+		r = args[0]
+	}
+	return r
+}
+
+func (v *Raw) Result(args ...int) *Result {
+	return NewResult(v.ToStr(args...))
+}
+
+func (v *Raw) String(args ...int) (s string) {
+	return v.ToStr(args...)
+}
+func (v *Raw) Str(args ...int) *Str {
+	return NewStr(v.ToStr(args...))
+}
+
+//是否为空
+func (r *Raw) Empty() bool {
+	if r.val == nil {
+		return true
+	}
+	v := reflect.ValueOf(r.val)
+	switch v.Kind() {
+	case reflect.String, reflect.Array:
+		return v.Len() == 0
+	case reflect.Map, reflect.Slice:
+		return v.Len() == 0 || v.IsNil()
+	case reflect.Bool:
+		return !v.Bool()
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return v.Int() == 0
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return v.Uint() == 0
+	case reflect.Float32, reflect.Float64:
+		return v.Float() == 0
+	case reflect.Interface, reflect.Ptr:
+		return v.IsNil()
+	}
+	return reflect.DeepEqual(r.val, reflect.Zero(v.Type()).Interface())
+}
+func (v *Raw) ToStr(args ...int) (s string) {
+	switch v := v.val.(type) {
+	case bool:
+		s = strconv.FormatBool(v)
+	case float32:
+		s = strconv.FormatFloat(float64(v), 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 32))
+	case float64:
+		s = strconv.FormatFloat(v, 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 64))
+	case int:
+		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
+	case int8:
+		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
+	case int16:
+		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
+	case int32:
+		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
+	case int64:
+		s = strconv.FormatInt(v, argInt(args).Get(0, 10))
+	case uint:
+		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
+	case uint8:
+		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
+	case uint16:
+		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
+	case uint32:
+		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
+	case uint64:
+		s = strconv.FormatUint(v, argInt(args).Get(0, 10))
+	case string:
+		s = v
+	case []byte:
+		s = string(v)
+	default:
+		s = fmt.Sprintf("%v", v)
+	}
+	return s
+}

+ 221 - 0
go/gopath/src/fohow.com/apps/helper/result.go

@@ -0,0 +1,221 @@
+package helper
+
+import (
+	"reflect"
+	"strings"
+)
+
+type Result struct {
+	val interface{}
+}
+
+func NewResult(val interface{}) *Result {
+	return &Result{val: val}
+}
+
+func (r *Result) String(defaultval ...string) string {
+	switch val := r.val.(type) {
+	case string:
+		return val
+	default:
+		for k, v := range defaultval {
+			if k == 0 {
+				return v
+			}
+		}
+		return ""
+	}
+}
+
+func (r *Result) Val() interface{} {
+	return r.val
+}
+
+func (r *Result) Result() interface{} {
+	return r.val
+}
+
+func (r *Result) Int(defaultval ...int) int {
+	switch val := r.val.(type) {
+	case int:
+		return val
+	case string:
+		return NewStr(val).ToInt()
+	default:
+		for k, v := range defaultval {
+			if k == 0 {
+				return v
+			}
+		}
+		return 0
+	}
+}
+
+func (r *Result) Int64(defaultval ...int64) int64 {
+	switch val := r.val.(type) {
+	case int64:
+		return val
+	case string:
+		return NewStr(val).ToInt64()
+	default:
+		for k, v := range defaultval {
+			if k == 0 {
+				return v
+			}
+		}
+		return 0
+	}
+}
+
+func (r *Result) Uint64(defaultval ...uint64) uint64 {
+	switch val := r.val.(type) {
+	case uint64:
+		return val
+	case string:
+		return NewStr(val).ToUint64()
+	default:
+		for k, v := range defaultval {
+			if k == 0 {
+				return v
+			}
+		}
+		return 0
+	}
+}
+
+func (r *Result) Float32(defaultval ...float32) float32 {
+	switch val := r.val.(type) {
+	case float32:
+		return val
+	case string:
+		return NewStr(val).ToFloat32()
+	default:
+		for k, v := range defaultval {
+			if k == 0 {
+				return v
+			}
+		}
+		return 0
+	}
+}
+
+func (r *Result) Float64(defaultval ...float64) float64 {
+	switch val := r.val.(type) {
+	case float64:
+		return val
+	case string:
+		return NewStr(val).ToFloat64()
+	default:
+		for k, v := range defaultval {
+			if k == 0 {
+				return v
+			}
+		}
+		return 0
+	}
+}
+
+func (r *Result) Bool(defaultval ...bool) bool {
+	switch val := r.val.(type) {
+	case bool:
+		return val
+	case string:
+		return NewStr(val).ToBool()
+	default:
+		for k, v := range defaultval {
+			if k == 0 {
+				return v
+			}
+		}
+		return false
+	}
+}
+
+func (r *Result) Bytes(defaultval ...[]byte) []byte {
+	switch val := r.val.(type) {
+	case []byte:
+		return val
+	case string:
+		return NewStr(val).ToBytes()
+	default:
+		for k, v := range defaultval {
+			if k == 0 {
+				return v
+			}
+		}
+		return nil
+	}
+}
+
+//是否为空
+func (r *Result) Empty() bool {
+	if r.val == nil {
+		return true
+	}
+	v := reflect.ValueOf(r.val)
+	switch v.Kind() {
+	case reflect.String, reflect.Array:
+		return v.Len() == 0
+	case reflect.Map, reflect.Slice:
+		return v.Len() == 0 || v.IsNil()
+	case reflect.Bool:
+		return !v.Bool()
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return v.Int() == 0
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return v.Uint() == 0
+	case reflect.Float32, reflect.Float64:
+		return v.Float() == 0
+	case reflect.Interface, reflect.Ptr:
+		return v.IsNil()
+	}
+	return reflect.DeepEqual(r.val, reflect.Zero(v.Type()).Interface())
+}
+
+//判断是否为数字
+func (r *Result) IsNumeric() bool {
+	switch r.val.(type) {
+	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
+		return true
+	case float32, float64, complex64, complex128:
+		return true
+	case string:
+		str := r.val.(string)
+		if str == "" {
+			return false
+		}
+		str = strings.TrimSpace(str)
+		if str[0] == '-' || str[0] == '+' {
+			if len(str) == 1 {
+				return false
+			}
+			str = str[1:]
+		}
+		if len(str) > 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X') {
+			for _, h := range str[2:] {
+				if !((h >= '0' && h <= '9') || (h >= 'a' && h <= 'f') || (h >= 'A' && h <= 'F')) {
+					return false
+				}
+			}
+			return true
+		}
+		p, s, l := 0, 0, len(str)
+		for i, v := range str {
+			if v == '.' {
+				if p > 0 || s > 0 || i+1 == l {
+					return false
+				}
+				p = i
+			} else if v == 'e' || v == 'E' {
+				if i == 0 || s > 0 || i+1 == l {
+					return false
+				}
+				s = i
+			} else if v < '0' || v > '9' {
+				return false
+			}
+		}
+		return true
+	}
+	return false
+}

+ 281 - 0
go/gopath/src/fohow.com/apps/helper/slice.go

@@ -0,0 +1,281 @@
+package helper
+
+import (
+	"errors"
+	"math"
+	"math/rand"
+	"reflect"
+	"strings"
+	"time"
+)
+
+type Slice struct {
+}
+
+func NewSlice() *Slice {
+	return &Slice{}
+}
+
+//用给定的值填充切片
+func (slice *Slice) Fill(startIndex int, num uint, value interface{}) map[int]interface{} {
+	m := make(map[int]interface{})
+	var i uint
+	for i = 0; i < num; i++ {
+		m[startIndex] = value
+		startIndex++
+	}
+	return m
+}
+
+//交换切片中的键和值
+func (slice *Slice) Flip(m map[interface{}]interface{}) map[interface{}]interface{} {
+	n := make(map[interface{}]interface{})
+	for i, v := range m {
+		n[v] = i
+	}
+	return n
+}
+
+//返回切片的键名
+func (slice *Slice) Keys(elements map[interface{}]interface{}) []interface{} {
+	i, keys := 0, make([]interface{}, len(elements))
+	for key := range elements {
+		keys[i] = key
+		i++
+	}
+	return keys
+}
+
+//返回切片中所有的值
+func (slice *Slice) Values(elements map[interface{}]interface{}) []interface{} {
+	i, vals := 0, make([]interface{}, len(elements))
+	for _, val := range elements {
+		vals[i] = val
+		i++
+	}
+	return vals
+}
+
+//合并一个或多个切片
+func (slice *Slice) Merge(ss ...[]interface{}) []interface{} {
+	n := 0
+	for _, v := range ss {
+		n += len(v)
+	}
+	s := make([]interface{}, 0, n)
+	for _, v := range ss {
+		s = append(s, v...)
+	}
+	return s
+}
+
+//将一个切片分割成多个
+func (slice *Slice) Chunk(s []interface{}, size int) ([][]interface{}, error) {
+	if size < 1 {
+		return nil, errors.New("size: cannot be less than 1")
+	}
+	length := len(s)
+	chunks := int(math.Ceil(float64(length) / float64(size)))
+	var n [][]interface{}
+	for i, end := 0, 0; chunks > 0; chunks-- {
+		end = (i + 1) * size
+		if end > length {
+			end = length
+		}
+		n = append(n, s[i*size:end])
+		i++
+	}
+	return n, nil
+}
+
+//以指定长度将一个值填充进切片
+func (slice *Slice) Pad(s []interface{}, size int, val interface{}) []interface{} {
+	if size == 0 || (size > 0 && size < len(s)) || (size < 0 && size > -len(s)) {
+		return s
+	}
+	n := size
+	if size < 0 {
+		n = -size
+	}
+	n -= len(s)
+	tmp := make([]interface{}, n)
+	for i := 0; i < n; i++ {
+		tmp[i] = val
+	}
+	if size > 0 {
+		return append(s, tmp...)
+	}
+	return append(tmp, s...)
+}
+
+//从切片中取出一段
+func (slice *Slice) Slice(s []interface{}, offset, length uint) ([]interface{}, error) {
+	if offset > uint(len(s)) {
+		return nil, errors.New("offset: the offset is less than the length of s")
+	}
+	end := offset + length
+	if end < uint(len(s)) {
+		return s[offset:end], nil
+	} else {
+		return s[offset:], nil
+	}
+}
+
+//从切片中随机取出一个或多个单元
+func (slice *Slice) Rand(elements []interface{}) []interface{} {
+	r := rand.New(rand.NewSource(time.Now().UnixNano()))
+	n := make([]interface{}, len(elements))
+	for i, v := range r.Perm(len(elements)) {
+		n[i] = elements[v]
+	}
+	return n
+}
+
+//返回切片中指定的一列
+func (slice *Slice) Column(input map[string]map[string]interface{}, columnKey string) []interface{} {
+	columns := make([]interface{}, 0, len(input))
+	for _, val := range input {
+		if v, ok := val[columnKey]; ok {
+			columns = append(columns, v)
+		}
+	}
+	return columns
+}
+
+//将一个或多个单元压入切片的末尾(入栈)
+func (slice *Slice) Push(s *[]interface{}, elements ...interface{}) int {
+	*s = append(*s, elements...)
+	return len(*s)
+}
+
+// 弹出切片最后一个单元(出栈)
+func (slice *Slice) Pop(s *[]interface{}) interface{} {
+	if len(*s) == 0 {
+		return nil
+	}
+	ep := len(*s) - 1
+	e := (*s)[ep]
+	*s = (*s)[:ep]
+	return e
+}
+
+//在切片开头插入一个或多个单元
+func (slice *Slice) Unshift(s *[]interface{}, elements ...interface{}) int {
+	*s = append(elements, *s...)
+	return len(*s)
+}
+
+//将切片开头的单元移出切片
+func (slice *Slice) Shift(s *[]interface{}) interface{} {
+	if len(*s) == 0 {
+		return nil
+	}
+	f := (*s)[0]
+	*s = (*s)[1:]
+	return f
+}
+
+//检查切片里是否有指定的键名或索引
+func (slice *Slice) KeyExists(key interface{}, m map[interface{}]interface{}) bool {
+	_, ok := m[key]
+	return ok
+}
+
+//创建一个切片,用一个切片的值作为其键名,另一个切片的值作为其值
+func (slice *Slice) Combine(s1, s2 []interface{}) (map[interface{}]interface{}, error) {
+	if len(s1) != len(s2) {
+		return nil, errors.New("the number of elements for each slice isn't equal")
+	}
+	m := make(map[interface{}]interface{}, len(s1))
+	for i, v := range s1 {
+		m[v] = s2[i]
+	}
+	return m, nil
+}
+
+//返回单元顺序相反的切片
+func (slice *Slice) Reverse(s []interface{}) []interface{} {
+	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
+		s[i], s[j] = s[j], s[i]
+	}
+	return s
+}
+
+//将一个一维切片的值转化为字符串
+func (slice *Slice) Implode(glue string, pieces []string) string {
+	return slice.Join(glue, pieces)
+}
+func (slice *Slice) Join(glue string, pieces []string) string {
+	return strings.Join(pieces, glue)
+}
+
+//检查切片中是否存在某个值
+func (slice *Slice) InValue(needle interface{}, haystack interface{}) bool {
+	val := reflect.ValueOf(haystack)
+	switch val.Kind() {
+	case reflect.Slice, reflect.Array:
+		for i := 0; i < val.Len(); i++ {
+			if reflect.DeepEqual(needle, val.Index(i).Interface()) {
+				return true
+			}
+		}
+	case reflect.Map:
+		for _, k := range val.MapKeys() {
+			if reflect.DeepEqual(needle, val.MapIndex(k).Interface()) {
+				return true
+			}
+		}
+	default:
+		return false
+	}
+
+	return false
+}
+
+//判断操作键是否在切片
+func (slice *Slice) InKey(key interface{}, s map[interface{}]interface{}) (interface{}, bool) {
+	if v, ok := s[key]; ok {
+		return v, true
+	} else {
+		return nil, false
+	}
+}
+
+//获取操作键值 key支持多维如 a.b
+func (slice *Slice) GetValue(key string, s map[interface{}]interface{}) interface{} {
+	keys := strings.Split(key, ".")
+	tmp := s
+	for index, k := range keys {
+		if v, ok := slice.InKey(k, tmp); ok {
+			switch v.(type) {
+			case map[interface{}]interface{}:
+				{
+					tmp = v.(map[interface{}]interface{})
+					if index == len(keys)-1 {
+						return tmp
+					}
+				}
+			default:
+				{
+					return v
+				}
+			}
+		}
+	}
+	return nil
+}
+
+//获取type Name
+func (slice *Slice) GetTypeName(t interface{}) string {
+	return reflect.TypeOf(t).Name()
+}
+
+//获取type Field
+func (slice *Slice) GetTypeField(t interface{}) []reflect.StructField {
+	var f []reflect.StructField
+	of := reflect.TypeOf(t)
+	for i := 0; i < of.NumField(); i++ {
+		f = append(f, of.Field(i))
+	}
+	return f
+}

+ 401 - 0
go/gopath/src/fohow.com/apps/helper/str.go

@@ -0,0 +1,401 @@
+package helper
+
+import (
+	"math/big"
+	"strconv"
+	"strings"
+	"unicode"
+	"unsafe"
+)
+
+type Str struct {
+	value string
+}
+
+func NewStr(value string) *Str {
+	return &Str{value: value}
+}
+
+//设置字符
+func (s *Str) Set(v string) *Str {
+	if v != "" {
+		s.value = v
+	} else {
+		s.Clear()
+	}
+	return s
+}
+
+//将一个一维切片的值转化为字符串
+func (s *Str) Join(glue string, pieces []string) *Str {
+	s.value = NewSlice().Implode(glue, pieces)
+	return s
+}
+
+//移除字符串两侧的空白字符或其他预定义字符
+func (s *Str) Trim(characterMask ...string) *Str {
+	if len(characterMask) == 0 {
+		s.value = strings.TrimSpace(s.value)
+	} else {
+		s.value = strings.Trim(s.value, characterMask[0])
+	}
+	return s
+}
+
+//移除字符串左侧的空白字符或其他预定义字符
+func (s *Str) Ltrim(characterMask ...string) *Str {
+	if len(characterMask) == 0 {
+		s.value = strings.TrimLeftFunc(s.value, unicode.IsSpace)
+	} else {
+		s.value = strings.TrimLeft(s.value, characterMask[0])
+	}
+	return s
+}
+
+//移除字符串右侧的空白字符或其他预定义字符
+func (s *Str) Rtrim(characterMask ...string) *Str {
+	if len(characterMask) == 0 {
+		s.value = strings.TrimRightFunc(s.value, unicode.IsSpace)
+	} else {
+		s.value = strings.TrimRight(s.value, characterMask[0])
+	}
+	return s
+}
+
+//小写字母转大写
+func (s *Str) Upper() *Str {
+	s.value = strings.ToUpper(s.value)
+	return s
+}
+
+//大写字母转小写
+func (s *Str) Lower() *Str {
+	s.value = strings.ToLower(s.value)
+	return s
+}
+
+//首字符转换为大写
+func (s *Str) Ucfirst() *Str {
+	for _, v := range s.value {
+		u := string(unicode.ToUpper(v))
+		s.value = u + s.value[len(u):]
+	}
+	return s
+}
+
+//首字符转换为小写
+func (s *Str) Lcfirst() *Str {
+	for _, v := range s.value {
+		u := string(unicode.ToLower(v))
+		s.value = u + s.value[len(u):]
+	}
+	return s
+}
+
+//每个单词的首字符转换为大写
+func (s *Str) Ucwords() *Str {
+	s.value = strings.Title(s.value)
+	return s
+}
+
+//查找字符串在另一字符串中第一次出现的位置 对大小写敏感
+func (s *Str) Strpos(needle string, offset int) int {
+	length := len(s.value)
+	if length == 0 || offset > length || -offset > length {
+		return -1
+	}
+	if offset < 0 {
+		offset += length
+	}
+	pos := strings.Index(s.value[offset:], needle)
+	if pos == -1 {
+		return -1
+	}
+	return pos + offset
+}
+
+//查找字符串在另一字符串中第一次出现的位置(不区分大小写)
+func (s *Str) Stripos(needle string, offset int) int {
+	length := len(s.value)
+	if length == 0 || offset > length || -offset > length {
+		return -1
+	}
+
+	haystack := s.value[offset:]
+	if offset < 0 {
+		offset += length
+	}
+	pos := strings.Index(strings.ToLower(haystack), strings.ToLower(needle))
+	if pos == -1 {
+		return -1
+	}
+	return pos + offset
+}
+
+//查找字符串在另一字符串中最后一次出现的位置(区分大小写)
+func (s *Str) Strrpos(needle string, offset int) int {
+	pos, length := 0, len(s.value)
+	if length == 0 || offset > length || -offset > length {
+		return -1
+	}
+	var haystack string
+	if offset < 0 {
+		haystack = s.value[:offset+length+1]
+	} else {
+		haystack = s.value[offset:]
+	}
+	pos = strings.LastIndex(haystack, needle)
+	if offset > 0 && pos != -1 {
+		pos += offset
+	}
+	return pos
+}
+
+//查找字符串在另一字符串中最后一次出现的位置(不区分大小写)
+func (s *Str) Strripos(needle string, offset int) int {
+	pos, length := 0, len(s.value)
+	if length == 0 || offset > length || -offset > length {
+		return -1
+	}
+	var haystack string
+	if offset < 0 {
+		haystack = s.value[:offset+length+1]
+	} else {
+		haystack = s.value[offset:]
+	}
+	pos = strings.LastIndex(strings.ToLower(haystack), strings.ToLower(needle))
+	if offset > 0 && pos != -1 {
+		pos += offset
+	}
+	return pos
+}
+
+//字母下划线命名转换驼峰命名
+func (s *Str) Camel() *Str {
+	data := make([]byte, 0, len(s.value))
+	flag, num := true, len(s.value)-1
+	for i := 0; i <= num; i++ {
+		d := s.value[i]
+		if d == '_' {
+			flag = true
+			continue
+		} else if flag {
+			if d >= 'a' && d <= 'z' {
+				d = d - 32
+			}
+			flag = false
+		}
+		data = append(data, d)
+	}
+	s.value = string(data[:])
+	return s
+}
+
+//字母驼峰命名转换为下划线命名
+func (s *Str) Snake() *Str {
+	num := len(s.value)
+	data := make([]byte, 0, num*2)
+	j := false
+	for i := 0; i < num; i++ {
+		d := s.value[i]
+		if i > 0 && d >= 'A' && d <= 'Z' && j {
+			data = append(data, '_')
+		}
+		if d != '_' {
+			j = true
+		}
+		data = append(data, d)
+	}
+	s.value = string(data[:])
+	return s.Lower()
+}
+
+//将字符串转换为切片
+func (s *Str) ToBytes() []byte {
+	return *(*[]byte)(unsafe.Pointer(
+		&struct {
+			string
+			Cap int
+		}{s.value, len(s.value)},
+	))
+}
+
+//转换为Bool
+func (s *Str) ToBool() bool {
+	if b, err := strconv.ParseBool(s.String()); err == nil {
+		return b
+	}
+	return false
+}
+
+//转换为float32
+func (s *Str) ToFloat32() float32 {
+	if v, err := strconv.ParseFloat(s.String(), 32); err == nil {
+		return float32(v)
+	}
+	return 0
+}
+
+//转换为float64
+func (s *Str) ToFloat64() float64 {
+	if f, err := strconv.ParseFloat(s.String(), 64); err == nil {
+		return f
+	}
+	return 0
+}
+
+//转换为int
+func (s *Str) ToInt() int {
+	if i, err := strconv.ParseInt(s.String(), 10, 32); err == nil {
+		return int(i)
+	}
+	return 0
+}
+
+//转换为int8
+func (s *Str) ToInt8() int8 {
+	if i, err := strconv.ParseInt(s.String(), 10, 8); err == nil {
+		return int8(i)
+	}
+	return 0
+}
+
+//转换为int16
+func (s *Str) ToInt16() int16 {
+	if i, err := strconv.ParseInt(s.String(), 10, 16); err == nil {
+		return int16(i)
+	}
+	return 0
+}
+
+//转换为int32
+func (s *Str) ToInt32() int32 {
+	if i, err := strconv.ParseInt(s.String(), 10, 32); err == nil {
+		return int32(i)
+	}
+	return 0
+}
+
+//转换为int64
+func (s *Str) ToInt64() int64 {
+	v, err := strconv.ParseInt(s.String(), 10, 64)
+	if err != nil {
+		i := new(big.Int)
+		ni, ok := i.SetString(s.String(), 10)
+		if !ok {
+			return 0
+		}
+		return ni.Int64()
+	}
+	return v
+}
+
+//转换为uint
+func (s *Str) ToUint() uint {
+	if i, err := strconv.ParseUint(s.String(), 10, 32); err == nil {
+		return uint(i)
+	}
+	return 0
+}
+
+//转换为uint8
+func (s *Str) ToUint8() uint8 {
+	if i, err := strconv.ParseUint(s.String(), 10, 8); err == nil {
+		return uint8(i)
+	}
+	return 0
+}
+
+//转换为uint16
+func (s *Str) ToUint16() uint16 {
+	if i, err := strconv.ParseUint(s.String(), 10, 16); err == nil {
+		return uint16(i)
+	}
+	return 0
+}
+
+//转换为uint32
+func (s *Str) ToUint32() uint32 {
+	if i, err := strconv.ParseUint(s.String(), 10, 32); err == nil {
+		return uint32(i)
+	}
+	return 0
+}
+
+//Md5
+func (s *Str) ToMd5() *HashData {
+	return NewHash([]byte(s.value)).Md5()
+}
+
+//Sha1
+func (s *Str) ToSha1() *HashData {
+	return NewHash([]byte(s.value)).Sha1()
+}
+
+//Sha256
+func (s *Str) ToSha256() *HashData {
+	return NewHash([]byte(s.value)).Sha256()
+}
+
+//Sha512
+func (s *Str) ToSha512() *HashData {
+	return NewHash([]byte(s.value)).Sha512()
+}
+
+//转换为uint64
+func (s *Str) ToUint64() uint64 {
+	v, err := strconv.ParseUint(s.String(), 10, 64)
+	if err != nil {
+		i := new(big.Int)
+		ni, ok := i.SetString(s.String(), 10)
+		if !ok {
+			return 0
+		}
+		return ni.Uint64()
+	}
+	return v
+}
+
+//判断后缀
+func (s *Str) HasSuffix(suffix string) bool {
+	return strings.HasSuffix(s.value, suffix)
+}
+
+//判断前缀
+func (s *Str) HasPrefix(prefix string) bool {
+	return strings.HasSuffix(s.value, prefix)
+}
+
+//字符串分割
+func (s *Str) Explode(delimiter string) []string {
+	return strings.Split(s.value, delimiter)
+}
+
+func (s *Str) String() string {
+	if s.Exist() {
+		return s.value
+	}
+	return ""
+}
+
+//清除字符串
+func (s *Str) Clear() {
+	s.Set(string(0x1E))
+}
+
+//检查字符串是否存在
+func (s *Str) Exist() bool {
+	return s.value != string(0x1E)
+}
+
+//字符串组是否包含某字符串
+func StringsContains(array []string, val string) (index int) {
+	index = -1
+	for i := 0; i < len(array); i++ {
+		if array[i] == val {
+			index = i
+			return index
+		}
+	}
+	return index
+}

+ 161 - 0
go/gopath/src/fohow.com/apps/helper/time.go

@@ -0,0 +1,161 @@
+package helper
+
+import (
+	"fmt"
+	"github.com/araddon/dateparse"
+	"strings"
+	"time"
+)
+
+var TimeLoad, _ = time.LoadLocation("PRC")
+
+//当前Unix时间
+func Time() int64 {
+	return time.Now().Unix()
+}
+
+//将英文文本日期时间解析为 Unix 时间戳
+func Strtotime(format, strtime string) (int64, error) {
+	t, err := time.Parse(format, strtime)
+	if err != nil {
+		return 0, err
+	}
+	return t.Unix(), nil
+}
+
+// 格式化时间
+func Date(format string, timestamp int64) string {
+	return time.Unix(timestamp, 0).Format(format)
+}
+
+//检查时间是否合法
+func Checkdate(month int, day int, year int) bool {
+	if month < 1 || month > 12 || day < 1 || day > 31 || year < 1 || year > 32767 {
+		return false
+	}
+	switch month {
+	case 4, 6, 9, 11:
+		if day > 30 {
+			return false
+		}
+	case 2:
+		// leap year
+		if year%4 == 0 && (year%100 != 0 || year%400 == 0) {
+			if day > 29 {
+				return false
+			}
+		} else if day > 28 {
+			return false
+		}
+	}
+	return true
+}
+
+func GetTime(value string) string {
+	var t time.Time
+	if value == "" {
+		t = time.Now().In(TimeLoad)
+	} else {
+		t = TimeParseAny(value)
+	}
+	return fmt.Sprintf("%02d", t.Hour()) + ":" + fmt.Sprintf("%02d", t.Minute()) + ":" + fmt.Sprintf("%02d", t.Second())
+}
+
+func GetDate(value string) string {
+	var t time.Time
+	if value == "" {
+		t = time.Now().In(TimeLoad)
+	} else {
+		t = TimeParseAny(value)
+	}
+	return fmt.Sprintf("%d", t.Year()) + "-" + fmt.Sprintf("%02d", t.Month()) + "-" + fmt.Sprintf("%02d", t.Day())
+}
+
+func GetDateMonth(value string) string {
+	var t time.Time
+	if value == "" {
+		t = time.Now().In(TimeLoad)
+	} else {
+		t = TimeParseAny(value)
+	}
+	return fmt.Sprintf("%d", t.Year()) + "-" + fmt.Sprintf("%02d", t.Month())
+}
+func GetDateTime(value string) string {
+	var t time.Time
+	if value == "" {
+		t = time.Now().In(TimeLoad)
+	} else {
+		t = TimeParseAny(value)
+	}
+	return fmt.Sprintf("%d", t.Year()) + "-" + fmt.Sprintf("%02d", t.Month()) + "-" + fmt.Sprintf("%02d", t.Day()) + " " + fmt.Sprintf("%02d", t.Hour()) + ":" + fmt.Sprintf("%02d", t.Minute()) + ":" + fmt.Sprintf("%02d", t.Second())
+}
+
+func TimeParseAny(value string) time.Time {
+	birStrLen := strings.Count(value, "") - 1
+	switch birStrLen {
+	case 10, 19:
+		t, _ := dateparse.ParseIn(value, TimeLoad)
+		return t
+	default:
+		t, _ := dateparse.ParseAny(value)
+		return t.In(TimeLoad)
+	}
+}
+
+func Gettime(t *time.Time) string {
+	if t == nil {
+		return ""
+	}
+	T := t.Format("2006-01-02")
+	return T
+}
+
+func TimeParse(value string) (T *time.Time) {
+	if value == "" {
+		return nil
+	}
+	birStrLen := strings.Count(value, "") - 1
+	switch birStrLen {
+	case 10, 19:
+		t, _ := dateparse.ParseIn(value, TimeLoad)
+		T = &t
+	default:
+		t, _ := dateparse.ParseAny(value)
+		t.In(TimeLoad)
+		T = &t
+	}
+	return
+}
+
+/**
+【今天】加多少天
+@param pAddDays 要加多少天?
+return 返回今天加pAddDays后的日期
+*/
+func TodayAddNDays(pAddDays int) string {
+	var t time.Time
+	t = time.Now().In(TimeLoad).AddDate(0, 0, pAddDays)
+	return fmt.Sprintf("%d", t.Year()) + "-" + fmt.Sprintf("%02d", t.Month()) + "-" + fmt.Sprintf("%02d", t.Day())
+}
+
+//开始日期
+func GetSystemBeginDate(BeginDate string) *time.Time {
+	var t *time.Time
+	if BeginDate == "" {
+		t = TimeParse(GetDateTime(BeginDate))
+	} else {
+		t = TimeParse(BeginDate)
+	}
+	return t
+}
+
+//结束日期
+func GetSystemEndDate(EndDate string) *time.Time {
+	var t *time.Time
+	if EndDate == "" {
+		t = TimeParse("2099-12-31 23:59:59")
+	} else {
+		t = TimeParse(EndDate)
+	}
+	return t
+}

+ 99 - 0
go/gopath/src/fohow.com/apps/helper/url.go

@@ -0,0 +1,99 @@
+package helper
+
+import (
+	"encoding/base64"
+	"net/url"
+	"strings"
+)
+
+type Url struct {
+	str string
+}
+
+func NewUrl(str string) *Url {
+	return &Url{str}
+}
+
+//解析 URL
+// -1: all; 1: scheme; 2: host; 4: port; 8: user; 16: pass; 32: path; 64: query; 128: fragment
+func (l *Url) ParseURL(component int) (map[string]string, error) {
+	u, err := url.Parse(l.str)
+	if err != nil {
+		return nil, err
+	}
+	if component == -1 {
+		component = 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128
+	}
+	var components = make(map[string]string)
+	if (component & 1) == 1 {
+		components["scheme"] = u.Scheme
+	}
+	if (component & 2) == 2 {
+		components["host"] = u.Hostname()
+	}
+	if (component & 4) == 4 {
+		components["port"] = u.Port()
+	}
+	if (component & 8) == 8 {
+		components["user"] = u.User.Username()
+	}
+	if (component & 16) == 16 {
+		components["pass"], _ = u.User.Password()
+	}
+	if (component & 32) == 32 {
+		components["path"] = u.Path
+	}
+	if (component & 64) == 64 {
+		components["query"] = u.RawQuery
+	}
+	if (component & 128) == 128 {
+		components["fragment"] = u.Fragment
+	}
+	return components, nil
+}
+
+//URL编码
+func (l *Url) URLEncode() string {
+	return url.QueryEscape(l.str)
+}
+
+//URL编码还原
+func (l *Url) URLDecode() (string, error) {
+	return url.QueryUnescape(l.str)
+}
+
+//按照 RFC 3986 对 URL 进行编码
+func (l *Url) Rawurlencode() string {
+	return strings.Replace(url.QueryEscape(l.str), "+", "%20", -1)
+}
+
+//对已编码的 URL 字符串进行解码
+func (l *Url) Rawurldecode() (string, error) {
+	return url.QueryUnescape(strings.Replace(l.str, "%20", "+", -1))
+}
+
+//生成 URL-encode 之后的请求字符串
+/*func (l *Url) HTTPBuildQuery(queryData url.Values) string {
+	return queryData.Encode()
+}*/
+
+//Base64编码
+func (l *Url) Base64Encode() string {
+	return base64.StdEncoding.EncodeToString([]byte(l.str))
+}
+
+//Base64编码还原
+func (l *Url) Base64Decode() (string, error) {
+	str := l.str
+	switch len(str) % 4 {
+	case 2:
+		str += "=="
+	case 3:
+		str += "="
+	}
+	data, err := base64.StdEncoding.DecodeString(str)
+	if err != nil {
+		return "", err
+	}
+	return NewRaw(data).ToStr(), nil
+}

+ 139 - 0
go/gopath/src/fohow.com/apps/helpers/benefit_helper.go

@@ -0,0 +1,139 @@
+package helpers
+
+import (
+	"fmt"
+	"fohow.com/apps/models/balance_model"
+	"fohow.com/apps/models/order_model"
+	"fohow.com/apps/models/sys_config"
+	"fohow.com/apps/models/user_model"
+	"math"
+)
+
+func NewSendInviterBenefit(wxUser *user_model.WxUser, orderId, source string) {
+
+	//三部代理--佣金计入本人账户 0317
+	//specialDepartStr := beego.AppConfig.String("SpecialDepart")
+	//specialDeparts := strings.Split(specialDepartStr, ",")
+	//departUser := fmt.Sprintf("%d", wxUser.Depart)
+	//contain := tool.StringsContains(specialDeparts, departUser) //是否结算给
+
+	var benefitWxUser *user_model.WxUser
+	if wxUser.ShowInviteMode == int64(1) {
+		benefitWxUser = wxUser
+	} else {
+		//20.12.01 新规--(微信支付金额-运费)>0,按(微信支付金额-运费)*20%给上级代理返佣金(代理本人下订单,也是返给上级代理)
+		benefitWxUser = FindInviter(wxUser)
+	}
+	if benefitWxUser == nil || benefitWxUser.Id == int64(1) {
+		return
+	}
+
+	if source == user_model.SOURCE_PRODUCT_BENEFIT {
+		productOrder := order_model.GetOrderById(orderId, true)
+		if productOrder == nil {
+			return
+		}
+
+		if benefitWxUser != nil {
+			//发放群主收益,(微信支付金额-运费)>0,按(微信支付金额-运费)*20%给上级代理返佣金
+			//val := []int64{productOrder.Pv - productOrder.Freight, productOrder.Pv}
+			//计算佣金的业绩=max(pv-max(扣提货券-运费,0),0)
+			award_cash := productOrder.Pv
+			couponFee := productOrder.CouponPrice - productOrder.Freight
+			if couponFee > 0 {
+				award_cash = productOrder.Pv - couponFee
+			}
+			if award_cash <= 0 {
+				return
+			}
+			be_total := float64(award_cash) * (float64(sys_config.GetCashAward()) / float64(100))
+			count := int64(math.Floor(be_total + 0.5))
+			//beego.BeeLogger.Warn("count %d", count)
+			remark := fmt.Sprintf("%s%s", wxUser.Nickname, "购物")
+			if count > 0 {
+				//发放佣金
+				inviteOrder := new(user_model.InviteOrder).Create(benefitWxUser.Id, wxUser.Id, wxUser.Id, count, productOrder.TotalPrice, user_model.SOURCE_PRODUCT_BENEFIT, productOrder.OrderId)
+				s := balance_model.CASH_SOURCE_PRODUCT_BENEFIT
+				cb := balance_model.GetCashBalanceByWxUIdAndRIdAndSource(benefitWxUser.Id, productOrder.OrderId, s)
+				if cb == nil {
+					cb = new(balance_model.CashBalance).Create(inviteOrder.BenefitWxUId, count, s, productOrder.OrderId, remark)
+					if cb != nil {
+						//标志进账
+						inviteOrder.IsEnterBalance = true
+						inviteOrder.EnterTime = cb.CreatedAt
+						inviteOrder.Save()
+					}
+				}
+			}
+		}
+	} else if source == user_model.BALANCE_BENEFIT {
+		balanceOrder := balance_model.GetBalanceOrderByOId(orderId, false)
+		if balanceOrder == nil {
+			return
+		}
+		//下线充值,上线获得540返利
+		if benefitWxUser != nil {
+			count := int64(0)
+			//读取上级配置收益比例
+			if balanceOrder.PaiedPrice >= sys_config.GetBuyCash() {
+				be_total := balanceOrder.PaiedPrice * sys_config.GetCashAward()
+				count = be_total / int64(100)
+			}
+			if count > 0 {
+				inviteOrder := new(user_model.InviteOrder).Create(benefitWxUser.Id, wxUser.Id, wxUser.Id, count, balanceOrder.TotalPrice, user_model.BALANCE_BENEFIT, balanceOrder.OrderId)
+				//发放现金佣金
+				s := balance_model.BALANCE_SOURCE_BENEFIT
+				remark := fmt.Sprintf("%s%s", wxUser.Nickname, "充值提货券")
+				b := balance_model.GetCashBalanceByWxUIdAndRIdAndSource(benefitWxUser.Id, balanceOrder.OrderId, s)
+				if b == nil {
+					b = new(balance_model.CashBalance).Create(inviteOrder.BenefitWxUId, count, s, balanceOrder.OrderId, remark)
+					if b != nil {
+						//标志进账
+						inviteOrder.IsEnterBalance = true
+						inviteOrder.EnterTime = b.CreatedAt
+						inviteOrder.Save()
+					}
+				}
+			}
+		}
+	}
+}
+
+func ShopSendInviterBenefit(wxUser *user_model.WxUser, orderId, source string) {
+
+	//非群主店铺专区不能下单
+	if wxUser == nil || wxUser.Rank != int64(2) {
+		return
+	}
+	//店长购物给上级返佣8%
+	benefitWxUser := FindInviter(wxUser)
+	if benefitWxUser == nil || benefitWxUser.Id == int64(1) {
+		return
+	}
+	//beego.BeeLogger.Warn("shop_benefitWxUser: %s", benefitWxUser)
+	//beego.BeeLogger.Warn("shop_newSendInviterBenefit:%v,%v,%s", wxUser, benefitWxUser, orderId)
+	if source == user_model.SOURCE_PRODUCT_BENEFIT {
+		productOrder := order_model.GetOrderById(orderId, false)
+		if productOrder == nil || productOrder.OrderType != order_model.ORDER_TYPE_SHOP {
+			return
+		}
+		if benefitWxUser != nil {
+			//不扣提货券,只计算8%佣金
+			count := int64(math.Floor(float64(productOrder.TotalPrice) * order_model.SHOP_BENETFIT_BL))
+			remark := fmt.Sprintf("%s%s", wxUser.Nickname, "店铺专区购物")
+			//发放佣金
+			inviteOrder := new(user_model.InviteOrder).Create(benefitWxUser.Id, wxUser.Id, wxUser.Id, count, productOrder.TotalPrice, user_model.SOURCE_PRODUCT_BENEFIT, productOrder.OrderId)
+			s := balance_model.CASH_SOURCE_PRODUCT_BENEFIT
+			cb := balance_model.GetCashBalanceByWxUIdAndRIdAndSource(benefitWxUser.Id, productOrder.OrderId, s)
+			if cb == nil {
+				cb = new(balance_model.CashBalance).Create(inviteOrder.BenefitWxUId, count, s, productOrder.OrderId, remark)
+				if cb != nil {
+					//标志进账
+					inviteOrder.IsEnterBalance = true
+					inviteOrder.EnterTime = cb.CreatedAt
+					inviteOrder.Save()
+				}
+			}
+		}
+	}
+}

+ 24 - 0
go/gopath/src/fohow.com/apps/helpers/intro_helper.go

@@ -0,0 +1,24 @@
+package helpers
+
+import (
+	"fohow.com/apps/models/user_model"
+	"time"
+)
+
+//升级群主
+func UpdateIntroUser(wxUser *user_model.WxUser) {
+
+	if wxUser == nil || wxUser.ShowInviteMode == int64(1) {
+		return
+	}
+	//升级群主,打开推广模块
+	wxUser.ShowInviteMode = int64(1)
+	wxUser.Rank = int64(1)
+	wxUser.PartnerTime = time.Now().Unix()
+	wxUser.Save()
+	//更改下级群主关系
+	inviteList := user_model.GetWxUsersByInviteIdAll(wxUser.Id, false)
+	go user_model.UpdateClass(inviteList, wxUser.Id, wxUser.IntroUserId)
+	//消除user,wxuser缓存
+	go wxUser.CleanCache()
+}

+ 12 - 0
go/gopath/src/fohow.com/apps/helpers/invite_helper.go

@@ -46,3 +46,15 @@ func SetInviter(loginedWxUId, ivId int64) {
 		beego.BeeLogger.Info("Wxuser Inviter Relationship-setInviter(), wxUserId:%d, inviteId:%d", wxUser.Id, wxUser.InviteId)
 	}
 }
+
+func FindInviter(wxUser *user_model.WxUser) *user_model.WxUser {
+	inviter := user_model.GetWxUserById(wxUser.InviteId, false)
+	if inviter == nil {
+		return nil
+	}
+	if inviter.ShowInviteMode == int64(1) {
+		return inviter
+	} else {
+		return FindInviter(inviter)
+	}
+}

+ 646 - 37
go/gopath/src/fohow.com/apps/helpers/promotion_helper.go

@@ -6,11 +6,14 @@ import (
 	"fohow.com/apps/models/cent_model"
 	"fohow.com/apps/models/order_model"
 	"fohow.com/apps/models/product_model"
+	"fohow.com/apps/models/promotion_model"
+	"fohow.com/apps/models/user_model"
+	"fohow.com/libs/tool"
 	"github.com/astaxie/beego"
 	"time"
 )
 
-//发放促销商品
+//订单促销
 /*
 	如果促销条件中,设置的项目有一项不满足即视为不满足促销条件
 */
@@ -31,7 +34,7 @@ func SetOrderPromotion(orderId string, wxUid int64) {
 
 	queryDate := time.Now()
 	// 获取所有有效促销记录
-	effectivePromotions := order_model.GetEffetivePromotions(queryDate, order.OrderType, false)
+	effectivePromotions := promotion_model.GetEffetivePromotions(queryDate, order.OrderType, order.Depart, false)
 	for _, item := range effectivePromotions {
 		//beego.Warn("item_name%d", item.Name)
 
@@ -51,45 +54,276 @@ func SetOrderPromotion(orderId string, wxUid int64) {
 			firstFlag = false
 			continue
 		}
-		nums := int64(99)
-		nums1 := int64(99)
-		nums2 := int64(99)
-		nums3 := int64(99)
-		nums4 := int64(99)
+		nums := int64(999)
+		nums1 := int64(999)
+		nums2 := int64(999)
+		nums3 := int64(999)
+		nums4 := int64(999)
+		nums5 := int64(999)
+		nums6 := int64(999)
 		if item.Prod1 > 0 {
+			prd := product_model.GetProductById(item.Prod1, true)
 			nums1 = int64(0)
-			detail1 := order_model.GetDetailsByOrderIdAndPid(orderId, item.Prod1)
-			if detail1 != nil && item.Prod1 > 0 && item.Nums1 > 0 {
-				nums1 = int64(detail1.Count / item.Nums1)
+			if prd != nil {
+				detail_nums1 := order_model.GetDetailsByOrderIdAndRelatePid(orderId, prd.RelateProductId)
+				if detail_nums1 > int64(0) && item.Prod1 > 0 && item.Nums1 > 0 {
+					nums1 = int64(detail_nums1 / item.Nums1)
+				}
 			}
 		}
 
 		if item.Prod2 > 0 {
+			prd := product_model.GetProductById(item.Prod2, true)
 			nums2 = int64(0)
-			detail2 := order_model.GetDetailsByOrderIdAndPid(orderId, item.Prod2)
-			if detail2 != nil && item.Prod2 > 0 && item.Nums2 > 0 {
-				nums2 = int64(detail2.Count / item.Nums2)
+			if prd != nil {
+				detail_nums2 := order_model.GetDetailsByOrderIdAndRelatePid(orderId, prd.RelateProductId)
+				if detail_nums2 > int64(0) && item.Prod2 > 0 && item.Nums2 > 0 {
+					nums2 = int64(detail_nums2 / item.Nums2)
+				}
+			}
+		}
+
+		if item.Prod3 > 0 {
+			prd := product_model.GetProductById(item.Prod3, true)
+			if prd != nil {
+				nums3 = int64(0)
+				detail_nums3 := order_model.GetDetailsByOrderIdAndRelatePid(orderId, prd.RelateProductId)
+				if detail_nums3 > 0 && item.Prod3 > 0 && item.Nums3 > 0 {
+					nums3 = int64(detail_nums3 / item.Nums3)
+				}
+			}
+		}
+		if item.MinTotal > 0 {
+			nums4 = int64(order.TotalPrice / item.MinTotal)
+		}
+
+		if item.Prod4 > 0 {
+			prd := product_model.GetProductById(item.Prod4, true)
+			nums5 = int64(0)
+			if prd != nil {
+				detail_nums4 := order_model.GetDetailsByOrderIdAndRelatePid(orderId, prd.RelateProductId)
+				if detail_nums4 > 0 && item.Prod4 > 0 && item.Nums4 > 0 {
+					nums5 = int64(detail_nums4 / item.Nums4)
+				}
+			}
+		}
+
+		if item.Prod5 > 0 {
+			prd := product_model.GetProductById(item.Prod5, true)
+			nums6 = int64(0)
+			if prd != nil {
+				detail_nums5 := order_model.GetDetailsByOrderIdAndRelatePid(orderId, prd.RelateProductId)
+				if detail_nums5 > 0 && item.Prod5 > 0 && item.Nums5 > 0 {
+					nums6 = int64(detail_nums5 / item.Nums5)
+				}
+			}
+		}
+
+		val := []int64{nums1, nums2, nums3, nums4, nums5, nums6}
+		nums = tool.Min(val...)
+		if !item.IsMore {
+			val := []int64{nums, 1}
+			nums = tool.Min(val...)
+		}
+		if nums == int64(999) || nums == int64(0) {
+			numsFlag = false
+		}
+		/*	beego.Warn("item_name-1%d", item.Name)
+			beego.Warn("firstFlag%v", firstFlag)
+			beego.Warn("totalFlag%v", totalFlag)
+			beego.Warn("numsFlag%v", numsFlag)
+			beego.Warn("nums%d", nums)*/
+
+		//满足促销条件
+		if firstFlag && totalFlag && numsFlag {
+
+			if item.SendProd1 > 0 && item.SendNums1 > 0 {
+				sendNums1 := nums * item.SendNums1
+				//赠送赠品1
+				product := product_model.GetProductById(item.SendProd1, true)
+				go order_model.SendCreate(order.OrderId, order.Id, product.Id, product.Price, product.Price, product.Name, sendNums1, order.Depart)
+			}
+			if item.SendProd2 > 0 && item.SendNums2 > 0 {
+				sendNums2 := nums * item.SendNums2
+				//赠送赠品1
+				product := product_model.GetProductById(item.SendProd2, true)
+				go order_model.SendCreate(order.OrderId, order.Id, product.Id, product.Price, product.Price, product.Name, sendNums2, order.Depart)
+			}
+
+			if item.SendProd3 > 0 && item.SendNums3 > 0 {
+				sendNums3 := nums * item.SendNums3
+				//赠送赠品1
+				product := product_model.GetProductById(item.SendProd3, true)
+				go order_model.SendCreate(order.OrderId, order.Id, product.Id, product.Price, product.Price, product.Name, sendNums3, order.Depart)
+			}
+
+			if item.SendProd4 > 0 && item.SendNums4 > 0 {
+				sendNums4 := nums * item.SendNums4
+				//赠送赠品1
+				product := product_model.GetProductById(item.SendProd4, true)
+				go order_model.SendCreate(order.OrderId, order.Id, product.Id, product.Price, product.Price, product.Name, sendNums4, order.Depart)
+			}
+
+			if item.SendProd5 > 0 && item.SendNums5 > 0 {
+				sendNums5 := nums * item.SendNums5
+				//赠送赠品1
+				product := product_model.GetProductById(item.SendProd5, true)
+				go order_model.SendCreate(order.OrderId, order.Id, product.Id, product.Price, product.Price, product.Name, sendNums5, order.Depart)
+			}
+			//赠送积分 or 代办费
+			if item.Cash > 0 {
+				totalCash := nums * item.Cash
+				source := balance_model.BALANCE_SOURCE_PROMOTION
+				remark := fmt.Sprintf("促销赠送提货券")
+				new(balance_model.Balance).Create(order.WxUserId, order.UserId, totalCash, source, order.OrderId, remark)
+			}
+			if item.Cent > 0 {
+				totalCent := nums * item.Cent
+				source := cent_model.PROMOTION_SEND
+				remark := fmt.Sprintf("促销活动赠送")
+				new(cent_model.CentBalance).Create(order.WxUserId, totalCent, source, order.OrderId, remark)
+			}
+		}
+	}
+}
+
+//订单促销
+/*
+	如果促销条件中,设置的项目有一项不满足即视为不满足促销条件
+*/
+func SetOrderPromotionPro(orderId string, wxUid int64) {
+	beego.BeeLogger.Warn("******* SetOrderPromotionPro orderId:%s wxUid:%d", orderId, wxUid)
+
+	firstOrder := false
+	//获取订单明细
+	order := order_model.GetOrderById(orderId, false)
+	if order == nil {
+		return
+	}
+	//检查会员是否首次下单
+	list := order_model.GetWxUserOrders(wxUid)
+	if len(list) == 1 {
+		firstOrder = true
+	}
+
+	queryDate := time.Now()
+	// 获取所有有效促销记录
+	effectivePromotions := promotion_model.GetEffetivePromotions(queryDate, order.OrderType, order.Depart, false)
+	for _, item := range effectivePromotions {
+		//beego.Warn("item_name%d", item.Name)
+
+		firstFlag := true
+		totalFlag := true
+		numsFlag := true
+		if item.MaxTotal > 0 && order.TotalPrice > item.MaxTotal {
+			totalFlag = false
+			continue
+		}
+		if item.IsFirst && !firstOrder {
+			firstFlag = false
+			continue
+		}
+		if item.MinTotal > 0 && order.TotalPrice < item.MinTotal {
+			totalFlag = false
+			firstFlag = false
+			continue
+		}
+		nums := int64(999)
+		nums1 := int64(999)
+		nums2 := int64(999)
+		nums3 := int64(999)
+		nums4 := int64(999)
+		nums5 := int64(999)
+		nums6 := int64(999)
+		if item.Prod1 > 0 {
+			prd := product_model.GetProductById(item.Prod1, true)
+			nums1 = int64(0)
+			if prd != nil {
+				detail_nums1 := int64(0)
+				detailItem := order_model.GetDetailsByOrderIdAndPid(orderId, item.Prod1)
+				if detailItem != nil {
+					detail_nums1 = detailItem.Count
+				}
+				if detail_nums1 > int64(0) && item.Prod1 > 0 && item.Nums1 > 0 {
+					nums1 = int64(detail_nums1 / item.Nums1)
+				}
+			}
+		}
+
+		if item.Prod2 > 0 {
+			prd := product_model.GetProductById(item.Prod2, true)
+			nums2 = int64(0)
+			if prd != nil {
+				detail_nums2 := int64(0)
+				detailItem := order_model.GetDetailsByOrderIdAndPid(orderId, item.Prod2)
+				if detailItem != nil {
+					detail_nums2 = detailItem.Count
+				}
+				//detail_nums2 := order_model.GetDetailsByOrderIdAndRelatePid(orderId, prd.RelateProductId)
+				if detail_nums2 > int64(0) && item.Prod2 > 0 && item.Nums2 > 0 {
+					nums2 = int64(detail_nums2 / item.Nums2)
+				}
 			}
 		}
 
 		if item.Prod3 > 0 {
 			nums3 = int64(0)
-			detail3 := order_model.GetDetailsByOrderIdAndPid(orderId, item.Prod3)
-			if detail3 != nil && item.Prod3 > 0 && item.Nums3 > 0 {
-				nums3 = int64(detail3.Count / item.Nums3)
+			prd := product_model.GetProductById(item.Prod3, true)
+			if prd != nil {
+				detail_nums3 := int64(0)
+				detailItem := order_model.GetDetailsByOrderIdAndPid(orderId, item.Prod3)
+				if detailItem != nil {
+					detail_nums3 = detailItem.Count
+				}
+				//detail_nums3 := order_model.GetDetailsByOrderIdAndRelatePid(orderId, prd.RelateProductId)
+				if detail_nums3 > 0 && item.Prod3 > 0 && item.Nums3 > 0 {
+					nums3 = int64(detail_nums3 / item.Nums3)
+				}
 			}
 		}
 		if item.MinTotal > 0 {
 			nums4 = int64(order.TotalPrice / item.MinTotal)
+		}
+
+		if item.Prod4 > 0 {
+			prd := product_model.GetProductById(item.Prod4, true)
+			nums5 = int64(0)
+			if prd != nil {
+				detail_nums4 := int64(0)
+				detailItem := order_model.GetDetailsByOrderIdAndPid(orderId, item.Prod4)
+				if detailItem != nil {
+					detail_nums4 = detailItem.Count
+				}
+				//detail_nums4 := order_model.GetDetailsByOrderIdAndRelatePid(orderId, prd.RelateProductId)
+				if detail_nums4 > 0 && item.Prod4 > 0 && item.Nums4 > 0 {
+					nums5 = int64(detail_nums4 / item.Nums4)
+				}
+			}
+		}
 
+		if item.Prod5 > 0 {
+			prd := product_model.GetProductById(item.Prod5, true)
+			nums6 = int64(0)
+			if prd != nil {
+				detail_nums5 := int64(0)
+				detailItem := order_model.GetDetailsByOrderIdAndPid(orderId, item.Prod5)
+				if detailItem != nil {
+					detail_nums5 = detailItem.Count
+				}
+				//detail_nums5 := order_model.GetDetailsByOrderIdAndRelatePid(orderId, prd.RelateProductId)
+				if detail_nums5 > 0 && item.Prod5 > 0 && item.Nums5 > 0 {
+					nums6 = int64(detail_nums5 / item.Nums5)
+				}
+			}
 		}
-		val := []int64{nums1, nums2, nums3, nums4}
-		nums = min(val...)
+
+		val := []int64{nums1, nums2, nums3, nums4, nums5, nums6}
+		nums = tool.Min(val...)
 		if !item.IsMore {
 			val := []int64{nums, 1}
-			nums = min(val...)
+			nums = tool.Min(val...)
 		}
-		if nums == int64(99) || nums == int64(0) {
+		if nums == int64(999) || nums == int64(0) {
 			numsFlag = false
 		}
 		/*	beego.Warn("item_name-1%d", item.Name)
@@ -105,20 +339,34 @@ func SetOrderPromotion(orderId string, wxUid int64) {
 				sendNums1 := nums * item.SendNums1
 				//赠送赠品1
 				product := product_model.GetProductById(item.SendProd1, true)
-				go order_model.SendCreate(order.OrderId, order.Id, product.Id, product.Price, product.Price, product.Name, sendNums1)
+				go order_model.SendCreate(order.OrderId, order.Id, product.Id, product.Price, product.Price, product.Name, sendNums1, order.Depart)
 			}
 			if item.SendProd2 > 0 && item.SendNums2 > 0 {
 				sendNums2 := nums * item.SendNums2
 				//赠送赠品1
 				product := product_model.GetProductById(item.SendProd2, true)
-				go order_model.SendCreate(order.OrderId, order.Id, product.Id, product.Price, product.Price, product.Name, sendNums2)
+				go order_model.SendCreate(order.OrderId, order.Id, product.Id, product.Price, product.Price, product.Name, sendNums2, order.Depart)
 			}
 
 			if item.SendProd3 > 0 && item.SendNums3 > 0 {
 				sendNums3 := nums * item.SendNums3
 				//赠送赠品1
 				product := product_model.GetProductById(item.SendProd3, true)
-				go order_model.SendCreate(order.OrderId, order.Id, product.Id, product.Price, product.Price, product.Name, sendNums3)
+				go order_model.SendCreate(order.OrderId, order.Id, product.Id, product.Price, product.Price, product.Name, sendNums3, order.Depart)
+			}
+
+			if item.SendProd4 > 0 && item.SendNums4 > 0 {
+				sendNums4 := nums * item.SendNums4
+				//赠送赠品1
+				product := product_model.GetProductById(item.SendProd4, true)
+				go order_model.SendCreate(order.OrderId, order.Id, product.Id, product.Price, product.Price, product.Name, sendNums4, order.Depart)
+			}
+
+			if item.SendProd5 > 0 && item.SendNums5 > 0 {
+				sendNums5 := nums * item.SendNums5
+				//赠送赠品1
+				product := product_model.GetProductById(item.SendProd5, true)
+				go order_model.SendCreate(order.OrderId, order.Id, product.Id, product.Price, product.Price, product.Name, sendNums5, order.Depart)
 			}
 			//赠送积分 or 代办费
 			if item.Cash > 0 {
@@ -147,20 +395,6 @@ func max(vals ...int64) int64 {
 	return max
 }
 
-func min(vals ...int64) int64 {
-	min := int64(0)
-	for _, val := range vals {
-		if val <= int64(0) {
-			min = int64(0)
-			break
-		}
-		if val <= min || min == int64(0) {
-			min = val
-		}
-	}
-	return min
-}
-
 /*
 
 找到所有当前时间>《开始时间》且 当前时间<《结束时间》 且《是否启用》=1的促销记录
@@ -184,3 +418,378 @@ func min(vals ...int64) int64 {
 	找下一个促销记录
 }
 */
+
+//充值促销
+
+func BalanceOrderPromotion(orderId string, wxUid, depart int64) {
+	beego.BeeLogger.Warn("******* BalanceOrderPromotion orderId:%s wxUid:%d", orderId, wxUid)
+
+	//获取订单明细
+	balanceOrder := balance_model.GetBalanceOrderByOId(orderId, false)
+	if balanceOrder == nil {
+		return
+	}
+	queryDate := time.Now()
+	// 获取所有有效促销记录
+	effectivePromotions := promotion_model.GetBalanceEffetivePromotions(queryDate, depart, false)
+	for _, item := range effectivePromotions {
+		//beego.Warn("item_name%d", item.Name)
+
+		totalFlag := true
+		numsFlag := true
+		if item.MaxTotal > 0 && balanceOrder.PaiedPrice > item.MaxTotal {
+			totalFlag = false
+			continue
+		}
+
+		if item.MinTotal > 0 && balanceOrder.PaiedPrice < item.MinTotal {
+			totalFlag = false
+			continue
+		}
+
+		count := int64(0)
+
+		if item.MinTotal > 0 {
+			count = int64(balanceOrder.PaiedPrice / item.MinTotal)
+		}
+
+		if count == int64(0) {
+			numsFlag = false
+		}
+		if !item.IsMore {
+			val := []int64{count, 1}
+			count = tool.Min(val...)
+		}
+
+		beego.Warn("item_name-1%d", item.Name)
+		beego.Warn("totalFlag%v", totalFlag)
+		beego.Warn("numsFlag%v", numsFlag)
+		beego.Warn("nums%d", count)
+
+		//满足促销条件
+		if totalFlag && numsFlag {
+			source := promotion_model.SOURCE_BALANCE
+			remark := fmt.Sprintf("充值订单(%s)充值成功--促销(%s)", orderId, item.Name)
+			if item.SendProd1 > 0 && item.SendNums1 > 0 {
+				sendNums1 := count * item.SendNums1
+				//生成赠品
+				product := product_model.GetProductById(item.SendProd1, true)
+				if product != nil {
+					total := sendNums1 * product.Price
+					go new(promotion_model.Present).CreatePresent(wxUid, product.Price, total, product.Id, sendNums1, source, remark)
+				}
+			}
+			if item.SendProd2 > 0 && item.SendNums2 > 0 {
+				sendNums2 := count * item.SendNums2
+				//赠送赠品1
+				product := product_model.GetProductById(item.SendProd2, true)
+				if product != nil {
+					total := sendNums2 * product.Price
+					go new(promotion_model.Present).CreatePresent(wxUid, product.Price, total, product.Id, sendNums2, source, remark)
+				}
+			}
+
+			if item.SendProd3 > 0 && item.SendNums3 > 0 {
+				sendNums3 := count * item.SendNums3
+				//赠送赠品3
+				product := product_model.GetProductById(item.SendProd3, true)
+				if product != nil {
+					total := sendNums3 * product.Price
+					go new(promotion_model.Present).CreatePresent(wxUid, product.Price, total, product.Id, sendNums3, source, remark)
+				}
+			}
+
+			//赠送积分 or 代办费
+			if item.Cash > 0 {
+				totalCash := count * item.Cash
+				source := balance_model.BALANCE_SOURCE_BALANCE_RECHARGE_PROMOTION
+				remark := fmt.Sprintf("充值促销赠送提货券")
+				new(balance_model.Balance).Create(balanceOrder.WxUserId, balanceOrder.UserId, totalCash, source, balanceOrder.OrderId, remark)
+			}
+
+			if item.Cent > 0 {
+				totalCent := count * item.Cent
+				source := cent_model.PROMOTION_SEND
+				remark := fmt.Sprintf("充值促销活动赠送")
+				new(cent_model.CentBalance).Create(balanceOrder.WxUserId, totalCent, source, balanceOrder.OrderId, remark)
+			}
+		}
+	}
+}
+
+//店长申请促销
+func ShopOrderPromotion(shopApplyId, wxUid, depart int64) {
+	beego.BeeLogger.Warn("******* ShopOrderPromotion shopApplyId:%d wxUid:%d", shopApplyId, wxUid)
+
+	//获取订单明细
+	shopApply := user_model.GetShopApplicationById(shopApplyId)
+	if shopApply == nil {
+		return
+	}
+	queryDate := time.Now()
+	// 获取所有有效促销记录
+	effectivePromotions := promotion_model.GetShopEffetivePromotions(queryDate, depart, false)
+	for _, item := range effectivePromotions {
+		//beego.Warn("item_name%d", item.Name)
+
+		totalFlag := true
+		numsFlag := true
+		if item.Total > 0 && shopApply.Total != item.Total {
+			totalFlag = false
+			continue
+		}
+		count := int64(0)
+
+		if item.Total > 0 {
+			count = int64(1)
+		}
+
+		if count == int64(0) {
+			numsFlag = false
+		}
+
+		beego.Warn("item_name-1%d", item.Name)
+		beego.Warn("totalFlag%v", totalFlag)
+		beego.Warn("numsFlag%v", numsFlag)
+		beego.Warn("nums%d", count)
+
+		//满足促销条件
+		if totalFlag && numsFlag {
+			orderId := fmt.Sprintf("shopapply-(%d)", shopApply.Id)
+			source := promotion_model.SOURCE_SHOP
+			remark := fmt.Sprintf("店长申请成功(%d)--促销(%s)", shopApply.Id, item.Name)
+			if item.SendProd1 > 0 && item.SendNums1 > 0 {
+				sendNums1 := count * item.SendNums1
+				//生成赠品
+				product := product_model.GetProductById(item.SendProd1, true)
+				if product != nil {
+					total := sendNums1 * product.Price
+					go new(promotion_model.Present).CreatePresent(wxUid, product.Price, total, product.Id, sendNums1, source, remark)
+				}
+			}
+			if item.SendProd2 > 0 && item.SendNums2 > 0 {
+				sendNums2 := count * item.SendNums2
+				//赠送赠品1
+				product := product_model.GetProductById(item.SendProd2, true)
+				if product != nil {
+					total := sendNums2 * product.Price
+					go new(promotion_model.Present).CreatePresent(wxUid, product.Price, total, product.Id, sendNums2, source, remark)
+				}
+			}
+
+			if item.SendProd3 > 0 && item.SendNums3 > 0 {
+				sendNums3 := count * item.SendNums3
+				//赠送赠品3
+				product := product_model.GetProductById(item.SendProd3, true)
+				if product != nil {
+					total := sendNums3 * product.Price
+					go new(promotion_model.Present).CreatePresent(wxUid, product.Price, total, product.Id, sendNums3, source, remark)
+				}
+			}
+
+			if item.SendProd4 > 0 && item.SendNums4 > 0 {
+				sendNums4 := count * item.SendNums4
+				//赠送赠品4
+				product := product_model.GetProductById(item.SendProd4, true)
+				if product != nil {
+					total := sendNums4 * product.Price
+					go new(promotion_model.Present).CreatePresent(wxUid, product.Price, total, product.Id, sendNums4, source, remark)
+				}
+			}
+
+			if item.SendProd5 > 0 && item.SendNums5 > 0 {
+				sendNums5 := count * item.SendNums5
+				//赠送赠品3
+				product := product_model.GetProductById(item.SendProd5, true)
+				if product != nil {
+					total := sendNums5 * product.Price
+					go new(promotion_model.Present).CreatePresent(wxUid, product.Price, total, product.Id, sendNums5, source, remark)
+				}
+			}
+
+			//赠送积分 or 代办费
+			if item.Cash > 0 {
+				totalCash := count * item.Cash
+				source := balance_model.BALANCE_SOURCE_SHOP_PROMOTION
+				remark := fmt.Sprintf("店长申请促销赠送提货券")
+				new(balance_model.Balance).Create(shopApply.WxUId, shopApply.UserId, totalCash, source, orderId, remark)
+			}
+
+			if item.Cent > 0 {
+				totalCent := count * item.Cent
+				source := cent_model.PROMOTION_SEND
+				remark := fmt.Sprintf("店长申请促销活动赠送")
+				new(cent_model.CentBalance).Create(shopApply.WxUId, totalCent, source, orderId, remark)
+			}
+		}
+	}
+}
+
+//赠品明细写入订单
+func PresentTransferToOrder(orderId string, wxUid int64) {
+	beego.BeeLogger.Warn("******* PresentTransferToOrder shopApplyId:%s wxUid:%d", orderId, wxUid)
+	//获取订单明细
+	order := order_model.GetOrderById(orderId, false)
+	if order == nil {
+		return
+	}
+	// 获取所有未写入赠品记录
+	presents := promotion_model.GetAllNoPatchPresents(wxUid)
+	for _, item := range presents {
+		//赠送赠品
+		product := product_model.GetProductById(item.SendProd, true)
+		if product != nil {
+			item.OrderId = orderId
+			item.Status = true
+			item.Save()
+			order_model.SendCreate(order.OrderId, order.Id, product.Id, product.Price, product.Price, product.Name, item.SendNums, order.Depart)
+		}
+	}
+	beego.BeeLogger.Warn("******* End PresentTransferToOrder shopApplyId:%s wxUid:%d", orderId, wxUid)
+
+}
+
+//创建店铺申请订单
+func CreateShopApplyOrder(shopAppplyId int64) {
+
+	beego.BeeLogger.Warn("begin do shopAppply id:(%d)", shopAppplyId)
+
+	shopApply := user_model.GetShopApplicationById(shopAppplyId)
+
+	if shopApply == nil {
+		beego.BeeLogger.Warn("shopApply error id:(%d)", shopAppplyId)
+		return
+	}
+
+	wxUser := user_model.GetWxUserById(shopApply.WxUId, false)
+	if wxUser == nil {
+		beego.BeeLogger.Warn("shopApply wxuser no existst id:(%d)", shopAppplyId)
+		return
+	}
+	//创建赠品订单
+	order := new(order_model.Order).CreateNew(wxUser.Id, wxUser.UserId,
+		int64(0), int64(0), order_model.ORDER_TYPE_NORMAL, wxUser.Depart, order_model.SOURCE_XCX)
+	if order == nil {
+		return
+	}
+	total := int64(0)
+	delOrder := true
+	queryDate := time.Now()
+	// 获取所有有效促销记录
+	effectivePromotions := promotion_model.GetShopEffetivePromotions(queryDate, shopApply.Depart, false)
+	for _, item := range effectivePromotions {
+		//beego.Warn("item_name%d", item.Name)
+
+		totalFlag := true
+		numsFlag := true
+		if item.Total > 0 && shopApply.Total != item.Total {
+			totalFlag = false
+			continue
+		}
+		count := int64(0)
+
+		if item.Total > 0 {
+			count = int64(1)
+		}
+
+		if count == int64(0) {
+			numsFlag = false
+		}
+
+		beego.Warn("item_name-1%d", item.Name)
+		beego.Warn("totalFlag%v", totalFlag)
+		beego.Warn("numsFlag%v", numsFlag)
+		beego.Warn("nums%d", count)
+
+		//满足促销条件
+		if totalFlag && numsFlag {
+			orderId := fmt.Sprintf("shopapply-(%d)", shopApply.Id)
+			order.Source = promotion_model.SOURCE_SHOP
+			order.Remark = fmt.Sprintf("店长申请成功(%d)--促销(%s)", shopApply.Id, item.Name)
+			if item.SendProd1 > 0 && item.SendNums1 > 0 {
+				sendNums1 := count * item.SendNums1
+				//生成赠品
+				product := product_model.GetProductById(item.SendProd1, true)
+				if product != nil {
+					delOrder = false
+					total += sendNums1 * product.Price
+					go new(order_model.OrderDetail).Create(order.OrderId, order.Id, product.Id, product.RelateProductId, product.Price, product.RoboBalancePrice, product.Name, "", "", sendNums1, order.Depart)
+
+				}
+			}
+			if item.SendProd2 > 0 && item.SendNums2 > 0 {
+				sendNums2 := count * item.SendNums2
+				//赠送赠品1
+				product := product_model.GetProductById(item.SendProd2, true)
+				if product != nil {
+					delOrder = false
+					total += sendNums2 * product.Price
+					go new(order_model.OrderDetail).Create(order.OrderId, order.Id, product.Id, product.RelateProductId, product.Price, product.RoboBalancePrice, product.Name, "", "", sendNums2, order.Depart)
+
+				}
+			}
+
+			if item.SendProd3 > 0 && item.SendNums3 > 0 {
+				sendNums3 := count * item.SendNums3
+				//赠送赠品3
+				product := product_model.GetProductById(item.SendProd3, true)
+				if product != nil {
+					delOrder = false
+					total += sendNums3 * product.Price
+					go new(order_model.OrderDetail).Create(order.OrderId, order.Id, product.Id, product.RelateProductId, product.Price, product.RoboBalancePrice, product.Name, "", "", sendNums3, order.Depart)
+
+				}
+			}
+
+			if item.SendProd4 > 0 && item.SendNums4 > 0 {
+				sendNums4 := count * item.SendNums4
+				//赠送赠品4
+				product := product_model.GetProductById(item.SendProd4, true)
+				if product != nil {
+					delOrder = false
+					total += sendNums4 * product.Price
+					go new(order_model.OrderDetail).Create(order.OrderId, order.Id, product.Id, product.RelateProductId, product.Price, product.RoboBalancePrice, product.Name, "", "", sendNums4, order.Depart)
+				}
+			}
+
+			if item.SendProd5 > 0 && item.SendNums5 > 0 {
+				sendNums5 := count * item.SendNums5
+				//赠送赠品5
+				product := product_model.GetProductById(item.SendProd5, true)
+				if product != nil {
+					delOrder = false
+					total += sendNums5 * product.Price
+					go new(order_model.OrderDetail).Create(order.OrderId, order.Id, product.Id, product.RelateProductId, product.Price, product.RoboBalancePrice, product.Name, "", "", sendNums5, order.Depart)
+				}
+			}
+
+			//赠送积分 or 代办费
+			if item.Cash > 0 {
+				totalCash := count * item.Cash
+				source := balance_model.BALANCE_SOURCE_SHOP_PROMOTION
+				remark := fmt.Sprintf("店长申请促销赠送提货券")
+				new(balance_model.Balance).Create(shopApply.WxUId, shopApply.UserId, totalCash, source, orderId, remark)
+			}
+
+			if item.Cent > 0 {
+				totalCent := count * item.Cent
+				source := cent_model.PROMOTION_SEND
+				remark := fmt.Sprintf("店长申请促销活动赠送")
+				new(cent_model.CentBalance).Create(shopApply.WxUId, totalCent, source, orderId, remark)
+			}
+		}
+	}
+	if !delOrder {
+		order.Status = order_model.STATUS_PROCESSING
+		order.TotalPrice = total
+		order.Contact = shopApply.Name
+		order.Address = shopApply.Address
+		order.Tel = shopApply.Mobile
+		order.Save()
+	} else {
+		order.Delete()
+	}
+
+	beego.BeeLogger.Warn("----------------end generate shopapply order ---%d ", shopApply.Id)
+	return
+}

+ 101 - 0
go/gopath/src/fohow.com/apps/helpers/recharge_helper.go

@@ -0,0 +1,101 @@
+package helpers
+
+import (
+	"fmt"
+	"fohow.com/apps/models/sys_config"
+	"fohow.com/libs/tool"
+	"github.com/astaxie/beego"
+	"strings"
+	"time"
+
+	"fohow.com/apps/models/balance_model"
+	"fohow.com/apps/models/user_model"
+	// "st.com/libs/wx_mp"
+)
+
+//充值成功发放佣金
+func PatchRechargeBalance(oId, totalFee int64, transactionId string) {
+
+	beego.BeeLogger.Warn("*******PatchRechargeBalance Begin oId:%d", oId)
+
+	order := balance_model.GetBalanceOrderById(oId, true)
+	if order == nil || order.State == int64(1) {
+		beego.BeeLogger.Error("充值订单状态错误或者不存在%d", oId)
+		return
+	}
+	payWay := ""
+	if len(transactionId) > 0 {
+		payWay = balance_model.PAY_WAY_TYPE_SERVICE_WXPAY
+	}
+	order.PaiedPrice = totalFee
+	order.State = 1
+	order.TradeNo = transactionId
+	order.PayWay = payWay
+	order.PaiedAt = time.Now().Unix()
+	if err := order.Save(); err != nil {
+		beego.BeeLogger.Error("weixinpay async return. save oId=%s fail", order.OrderId)
+		return
+	}
+	recharge(order.WxUserId, order.UserId, order.TotalPrice, order.OrderId)
+	wxUser := user_model.GetWxUserById(order.WxUserId, false)
+	if wxUser != nil {
+		NewSendInviterBenefit(wxUser, order.OrderId, user_model.BALANCE_BENEFIT)
+	}
+	if totalFee >= sys_config.GetBuyCash() && wxUser.ShowInviteMode != 1 {
+
+		//升级群主---0317手动升级群主
+		specialDepartStr := beego.AppConfig.String("SpecialDepart")
+		specialDeparts := strings.Split(specialDepartStr, ",")
+		departUser := fmt.Sprintf("%d", wxUser.Depart)
+		contain := tool.StringsContains(specialDeparts, departUser)
+
+		/*		specialDepart, err := beego.AppConfig.Int64("SpecialDepart")
+				if err != nil {
+					beego.BeeLogger.Error("%s", err)
+					return
+				}*/
+		if contain >= 0 {
+			UpdateIntroUser(wxUser)
+		}
+	}
+
+	beego.BeeLogger.Warn("*******PatchRechargeBalance End oId:%d", oId)
+
+}
+
+//添加提货券记录
+func recharge(wxUId, uId, c int64, rId string) {
+	source := balance_model.BALANCE_SOURCE_RECHARGE
+	item := balance_model.GetBalanceBySourceAndRId(source, rId)
+	if item != nil {
+		return
+	}
+	b := new(balance_model.Balance).Create(wxUId, uId, c, source, rId, fmt.Sprintf("¥%0.2f", float64(c)/100))
+	if b != nil {
+		go rechargeNotice(uId, b)
+	}
+}
+
+//提货券充值成功通知
+func rechargeNotice(uId int64, balance *balance_model.Balance) {
+	//user := user_model.GetUserById(uId, false)
+	//openId := user.GetOpenid()
+	//if openId == "" {
+	//	beego.BeeLogger.Error("Recharge notice, didn't get openId of user:[%s]", user.Tel)
+	//	return
+	//}
+	/*url := ""
+	if beego.AppConfig.String("RunMode") == "prod" {
+		// url = "http://api.d5c360.com/v1/cfc/25"
+		url = fmt.Sprintf("%s/v1/cfc/25", beego.AppConfig.String("ApiHost"))
+	} else {
+		url = fmt.Sprintf("%s/user/balance", beego.AppConfig.String("MHost"))
+	}
+	title := "成功充值到账, 快去选购众筹项目吧!\n"
+	amount := fmt.Sprintf("%0.2f 元", float64(balance.Count)/100)
+	account := user.Tel
+	rechargeType := "线上充值"
+	cTime := balance.CreatedAt.Format("2006-01-02 15:04:05")
+	remark := "\n点击可查看交易明细>"
+	beego.BeeLogger.Warn("Recharge notice to user:[%s], openId:[%s], amount:[%s]", user.RealName, openId, amount)*/
+}

+ 2 - 2
go/gopath/src/fohow.com/apps/helpers/sms_helper.go

@@ -14,13 +14,13 @@ func DispathSendSms(tels []string, expressNo string) {
 	if tels == nil || len(tels) == 0 {
 		return
 	}
-	kefuTel := "13322912052"
+	kefuTel := "13322915052"
 	mobile := strings.Join(tels, ",")
 	params := fmt.Sprintf(`{"tel":"%s","expressNo":"%s"}`, kefuTel, expressNo)
 	/*	ok, resp := alidayu.SendSMS(mobile, sign, template, params)*/
 	dysms.HTTPDebugEnable = true
 	dysms.SetACLClient(beego.AppConfig.String("AliSmsAccessId"), beego.AppConfig.String("AliSmsAccessSecret")) // dysms.New(ACCESSID, ACCESSKEY)
-	sign := "FOHOW商城售后"
+	sign := "凤凰菁选"
 	//sign := "凤凰玖玖"
 	template := "SMS_201456487"
 	// 短信发送

+ 113 - 205
go/gopath/src/fohow.com/apps/init.go

@@ -2,6 +2,7 @@ package apps
 
 import (
 	"fmt"
+	"fohow.com/apps/models/token_model"
 	"regexp"
 	"strings"
 	// "time"
@@ -14,8 +15,6 @@ import (
 	// "fohow.com/apps/models/balance_model"
 	"fohow.com/apps/models/channel_gzh_qrcode_model"
 	"fohow.com/apps/models/user_model"
-	// "fohow.com/libs/tool"
-	// "fohow.com/libs/wx_mp"
 )
 
 const (
@@ -27,18 +26,23 @@ const (
 
 var (
 	// 共用
-	BindFail              = []string{"bindFail", "迁移失败,请联系管理员"}
-	HasBind               = []string{"hasBind", "该会员编号已绑定会员"}
-	DailySignRepeat       = []string{"dailySignRepeat", "已经领取过啦"}
-	RedisError            = []string{"redisError", "redis初始化错误"}
-	RedisGetError         = []string{"redisGetError", "redisGet错误"}
-	RedisJsonError        = []string{"redisJsonError", "json转换错误"}
-	OrderRefundError      = []string{"orderRefundError", "退款失败"}
-	OtherSNotAllow        = []string{"othersNotAllow", "非店长无法在专区下单!"}
-	AlreadyShop           = []string{"alreadyShop", "您已经是店主,请勿重复申请"}
+	ComNotAllow = []string{"notAllow", "权限不够,请联系管理员"}
+
+	BindFail         = []string{"bindFail", "迁移失败,请联系管理员"}
+	HasBind          = []string{"hasBind", "该会员编号已绑定会员"}
+	DailySignRepeat  = []string{"dailySignRepeat", "已经领取过啦"}
+	RedisError       = []string{"redisError", "redis初始化错误"}
+	RedisGetError    = []string{"redisGetError", "redisGet错误"}
+	RedisJsonError   = []string{"redisJsonError", "json转换错误"}
+	OrderRefundError = []string{"orderRefundError", "退款失败"}
+	OtherSNotAllow   = []string{"othersNotAllow", "非店长无法在专区下单!"}
+	AlreadyShop      = []string{"alreadyShop", "您已经是店主,请勿重复申请"}
+	AlreadyAgent     = []string{"alreadyShop", "该会员已是代理,请勿重复申请"}
+
 	ShopNoRepit           = []string{"shopNoRepit", "请勿重复申请"}
 	NoCart                = []string{"noCart", "请选择您需要结算的产品"}
-	NoExist               = []string{"noExist", "不存在"}
+	NoExist               = []string{"noExist", "该记录不存在"}
+	TokenError            = []string{"tokenError", "生成令牌出错"}
 	HasOver               = []string{"hasOver", "已结束"}
 	NoShopSale            = []string{"noShopSale", "该商品非专区商品"}
 	HasPaied              = []string{"hasPaied", "已支付"}
@@ -61,13 +65,15 @@ var (
 	// 登录相关
 	HasLogin            = []string{"hasLogin", "已登录"}
 	HasLogout           = []string{"hasLogout", "已登出"}
-	UserNeedLogin       = []string{"userNeedLogin", "需要用户登录"}
+	UserNeedLogin       = []string{"userNeedLogin", "授权无效,需要用户登录"}
 	UserAuthorizeFailed = []string{"userAuthorizeFailed", "用户授权失败"}
 	UserNeedTel         = []string{"userNeedTel", "需要用户绑定手机"}
 	UserTelNotMatch     = []string{"userTelNotMatch", "手机号码不匹配,请使用当前登录用户的号码"}
 	WxUserNeedLogin     = []string{"wxUserNeedLogin", "需要微信用户登录"}
 	NotWeixinClient     = []string{"notWeixinClient", "不是微信客户端"}
 	SignupNotOpen       = []string{"signupNotOpen", "注册暂未开放,敬请期待"}
+	ProductErrorType    = []string{"productErrorType", "请您前往店铺专区下单"}
+
 	// 支付相关
 	PayWayNoMatch = []string{"payWayNoMatch", "请选择正确的支付方式"}
 	//请输入充值数额
@@ -85,6 +91,8 @@ var (
 	OnlyPlayInWeixin = []string{"onlyPlayInWeixin", "只能在微信客户端进行"}
 	OrderNotExist    = []string{"orderNotExist", "订单不存在"}
 	OrderExist       = []string{"orderExist", "订单已存在"}
+	DetailNotAllow   = []string{"detailNotAllow", "评论内容不能为空"}
+	DetailHasCommend = []string{"detailHasCommend", "商品已评论"}
 
 	PayFail               = []string{"payFail", "支付失败"}
 	ParamsError           = []string{"paramsError", "参数错误"}
@@ -97,11 +105,10 @@ var (
 	ProductOffSale        = []string{"productOffSale", "产品已经下架"}
 	OverLimitCount        = []string{"overLimitCount", "超过限购数量"}
 	SingleOverLimitCount  = []string{"singleOverLimitCount", "超过限购数量"}
-
-	PurchasedReachLimit = []string{"purchasedReachLimit", "已购买总数已达到限购数量"}
-
-	RedirectTo = []string{"redirectTo", "302跳转"}
-	ReduceFail = []string{"reduceFail", "帮砍失败"}
+	PurchasedReachLimit   = []string{"purchasedReachLimit", "已购买总数已达到限购数量"}
+	OnlyDeliveryArea      = []string{"onlyDeliveryArea", "产品不在限售区域内"}
+	RedirectTo            = []string{"redirectTo", "302跳转"}
+	ReduceFail            = []string{"reduceFail", "帮砍失败"}
 
 	UserNotExist = []string{"userNotExist", "用户不存在"}
 
@@ -110,15 +117,18 @@ var (
 	UploadUserHeadError = []string{"uploadUserHeadError", "上传头像错误"}
 	AddressNotMatch     = []string{"addressNotMatch", "地址不匹配"}
 	NotUnPay            = []string{"notUnPay", "无法支付,该订单已支付或者已过期"}
-	NotRightPayWay      = []string{"notRightPayWay", "无法支付,该订单只支持微信支付"}
-	HasAlreadyPay       = []string{"hasAlreadyPay", "该订单已支付过"}
-	NotPayInTime        = []string{"notPayInTime", "没在规定时间内完成支付"}
-	PayWayNotAllow      = []string{"payWayNotAllow", "不支持该支付方式"}
-	PayNoAuthed         = []string{"payNoAuthed", "支付未授权"}
-	PhoneInvalid        = []string{"phoneInvalid", "手机号码格式不正确"}
-	PhoneExist          = []string{"phoneExist", "手机号码已被注册,请更换其他号码"}
-	SMSInvalid          = []string{"smsInvalid", "短信验证码不正确"}
-	CodesSendTooOften   = []string{"codesSendTooOften", "短信验证码发送过于频繁,请半小时后重试"}
+	NotPayWayTime       = []string{"notPayWayTime", "无法支付,促销期间只允许提货券支付"}
+
+	NotEnoughPay      = []string{"notEnouphPay", "无法支付,提货券余额不足!"}
+	NotRightPayWay    = []string{"notRightPayWay", "无法支付,该订单只支持微信支付"}
+	HasAlreadyPay     = []string{"hasAlreadyPay", "该订单已支付过"}
+	NotPayInTime      = []string{"notPayInTime", "没在规定时间内完成支付"}
+	PayWayNotAllow    = []string{"payWayNotAllow", "暂不支持微信支付!"}
+	PayNoAuthed       = []string{"payNoAuthed", "支付未授权"}
+	PhoneInvalid      = []string{"phoneInvalid", "手机号码格式不正确"}
+	PhoneExist        = []string{"phoneExist", "手机号码已被注册,请更换其他号码"}
+	SMSInvalid        = []string{"smsInvalid", "短信验证码不正确"}
+	CodesSendTooOften = []string{"codesSendTooOften", "短信验证码发送过于频繁,请半小时后重试"}
 
 	WxMenusCreatedFailed = []string{"wxMenusCreatedFailed", "微信菜单创建失败"}
 	//小程序相关
@@ -232,7 +242,8 @@ func (self *BaseController) GetCurrentUserId() int64 {
 }
 
 func (self *BaseController) GetCurrentUser(useCache bool) *user_model.User {
-	id := self.GetCurrentUserId()
+
+	id := self.GetCurrentWxUser(useCache).UserId
 	if id <= 0 {
 		return nil
 	}
@@ -243,13 +254,8 @@ func (self *BaseController) GetCurrentUser(useCache bool) *user_model.User {
 	return u
 }
 
-func (self *BaseController) GetCurrentWxUserId() int64 {
-	id, _ := self.GetSession(SessionWxUserKey).(int64)
-	return id
-}
-
 func (self *BaseController) GetCurrentWxUser(useCache bool) *user_model.WxUser {
-	id := self.GetCurrentWxUserId()
+	id := self.GetCurrentWxUserIdByToken()
 	if id <= 0 {
 		return nil
 	}
@@ -260,70 +266,27 @@ func (self *BaseController) GetCurrentWxUser(useCache bool) *user_model.WxUser {
 	return u
 }
 
-// //检查是否是邀请注册,绑定上下级关系, 发送微信通知。使用范围:注册、绑定手机、拉新专题
-// func (self *BaseController) CheckInviteBinding(user *user_model.User) {
-// 	if user == nil {
-// 		return
-// 	}
-// 	//邀请注册,绑定关系
-// 	inviteKey := beego.AppConfig.String("InviteName")
-// 	inviterId := self.Ctx.GetCookie(inviteKey)
-// 	if inviterId != "" {
-// 		id, err := strconv.ParseInt(inviterId, 10, 64)
-// 		if err == nil {
-// 			inviter := user_model.GetUserById(id, true)
-// 			if inviter != nil && user.InviteId == 0 {
-// 				//绑定关系
-// 				user.InviteId = id
-// 				go user.Save()
-// 				//增加邀请收益统计记录, 记录注册用户的ip
-// 				ip := self.Ctx.Input.IP()
-// 				new(user_model.UserInviteBenefitStat).Create(user.Id, user.InviteId,
-// 					1, 0, time.Now(), ip)
-// 				//给邀请人发邀请成功的通知
-// 				WxInviter := user_model.GetWxUserByUserId(inviter.Id, true)
-// 				if WxInviter != nil {
-// 					//给邀请人发注册成功通知
-// 					openId := WxInviter.MpOpenid
-// 					url := fmt.Sprintf("%s/v1/cfc/36", beego.AppConfig.String("ApiHost"))
-// 					title := "有人通过您的邀请,并成功注册\n"
-// 					telwStar := tool.ReplaceTelMid4(inviter.Tel)
-// 					nickName, account := telwStar, telwStar
-// 					if user.Nickname != "" {
-// 						nickName = user.Nickname
-// 					}
-// 					cTime := inviter.CreatedAt.Format("2006-01-02 15:04:05")
-// 					remark := "\n点击详情,可以看一看TA"
-// 					wx_mp.TmplmsgInviteSignUp(openId, url, title, nickName, account, cTime, remark)
-// 				}
-// 				//给新人发红包,并发通知
-// 				c := int64(user_model.BenefitNewUser)
-// 				s := balance_model.BALANCE_SOURCE_SIGN_UP_ONLINE
-// 				remark := balance_model.BALANCE_SOURCE_SIGN_UP_ONLINE_NAME
-// 				rId := ""
-// 				balance := new(balance_model.Balance).Create(user.Id, c, s, rId, remark, 1)
-// 				if balance != nil {
-// 					wxUser := user_model.GetWxUserByUserId(user.Id, true)
-// 					//发送红包的通知
-// 					if wxUser != nil {
-// 						openId := wxUser.MpOpenid
-// 						url := fmt.Sprintf("%s/v1/cfc/37", beego.AppConfig.String("ApiHost"))
-// 						first := "注册成功,返现金额已到账\n"
-// 						count := fmt.Sprintf("%0.2f 元", float64(c)/100.0)
-// 						//新用户,余额是0
-// 						leftAmount := c //balance_model.GetUserTotalBalance(user.Id)
-// 						balance := fmt.Sprintf("%0.2f 元", float64(leftAmount)/100.0)
-// 						ctime := time.Now().Format("2006-01-02 15:04:05")
-// 						remark := "\n点击立即提现>"
-// 						wx_mp.TmplmsgBalanceChange(openId, url, first, ctime, count, balance, remark)
-// 					}
-// 				}
-// 			}
-// 		}
-// 	}
-// }
-
-//检验是否需要关注
+//根据token解析userId
+func (self *BaseController) GetCurrentWxUserIdByToken() int64 {
+	return getCurrentUserIdByToken(self.Ctx)
+}
+
+//TODO校验是否微信客户端
+func getCurrentUserIdByToken(ctx *context.Context) int64 {
+	inputToken := ""
+	wxUserId := int64(0)
+	requestAuthordata := ctx.Request.Header.Get("Authorization")
+	if len(requestAuthordata) > 0 {
+		authorizationData := strings.SplitN(ctx.Request.Header.Get("Authorization"), " ", 2)
+		inputToken = authorizationData[1]
+	}
+	token_user, err := token_model.ValidateToken(inputToken)
+	if err == nil {
+		wxUserId = token_user.Id
+	}
+	return wxUserId
+}
+
 //sceneId, 关注场景id
 func (self *BaseController) CheckWxUserSubscribe(sceneId int64) {
 	beego.BeeLogger.Info("check wx_user subscribe")
@@ -361,109 +324,42 @@ func (self *BaseController) CheckWxUserSubscribe(sceneId int64) {
 }
 
 func checkWxUserLogin(ctx *context.Context) {
-	// TODO : 整个项目也应该更加适合采用 token 机制
-	beego.BeeLogger.Info("check wx_user login")
-	if !isWxClient(ctx) {
-		return
-	}
-	wxUserId, ok := ctx.Input.Session(SessionWxUserKey).(int64)
-	if ok {
-		_, ok := ctx.Input.Session(SessionUserKey).(int64)
-		if !ok {
-			// 如果微信用户登录了,且有绑定了user,则设置用户登录
-			wxUser := user_model.GetWxUserById(wxUserId, true)
-			beego.BeeLogger.Warn("wx_user has login, ", wxUser)
-			if wxUser != nil && int(wxUser.UserId) > 0 {
-				ctx.Output.Session(SessionUserKey, wxUser.UserId)
-			}
-		}
-	} else {
-		// beego.BeeLogger.Warn("---------------%v", ctx.Input.IsAjax())
-		// beego.BeeLogger.Warn("---------------%s", ctx.Input)
-		// if ctx.Input.IsAjax() {
-
-		beego.BeeLogger.Info("show the request : %s from UserAgent: %s", ctx.Input.URI(), ctx.Input.UserAgent())
-		uri := ctx.Input.URI()
-		//外链进来需要自动登录
-		if strings.Contains(uri, "/v1/cfc/") && isWxClient(ctx) {
-
-			// 微信用户自动登录
-			url := fmt.Sprintf("%s/login/mp?cb=%s%s",
-				beego.AppConfig.String("ApiHost"),
-				ctx.Input.Site(), ctx.Input.URI())
-			ctx.Redirect(302, url)
-			return
-
-		} else {
+	//beego.BeeLogger.Info("show the request : %s from UserAgent: %s", ctx.Input.URI(), ctx.Input.UserAgent())
+	//检测 token 是否合法
+	var inputToken string
+	//beego.BeeLogger.Warn("request authorizationData : %s", ctx.Request.Header.Get("Authorization"))
+	requestAuthordata := ctx.Request.Header.Get("Authorization")
+	if len(requestAuthordata) > 0 {
+		authorizationData := strings.SplitN(ctx.Request.Header.Get("Authorization"), " ", 2)
+		if len(authorizationData) != 2 {
 			errCode := &ErrCode{
 				Code:     UserNeedLogin[0],
 				Msg:      UserNeedLogin[1],
 				Redirect: "",
 				Data:     nil,
 			}
-			ctx.Output.SetStatus(401)
+			//换成userNeedLogin
+			ctx.Output.SetStatus(403)
 			ctx.Output.JSON(errCode, true, true)
-			return
-
-		}
-
-		// } else {
-		// // FIXME : 这里 IsAjax 判断是否有问题? 微信来的应该属于api请求
-		// beego.BeeLogger.Debug("WEIXIN user not login", ctx.Input)
-
-		// errCode := &ErrCode{
-		// 	Code:     UserNeedLogin[0], // FIXME : 这里应该 是 WxUserNeedLogin, 因为前端编码用了UserNeedLogin,以后一起修改
-		// 	Msg:      UserNeedLogin[1],
-		// 	Redirect: "",
-		// 	Data:     nil,
-		// }
-		// ctx.Output.SetStatus(401)
-		// ctx.Output.JSON(errCode, true, true)
-		// return
-
-		// beego.BeeLogger.Warn("this is not a ajax request!")
-		// 微信用户自动登录
-		// if isWxClient(ctx) {
-		// 	// beego.BeeLogger.Warn("---------------%s", ctx.Input.Site())
-		// 	url := fmt.Sprintf("%s/login/mp?cb=%s%s",
-		// 		beego.AppConfig.String("ApiHost"),
-		// 		ctx.Input.Site(), ctx.Input.URI())
-		// 	// beego.BeeLogger.Warn("auto login mp cb url=%s", url)
-		// 	ctx.Redirect(302, url)
-		// 	return
-		// }
-		// }
-	}
-}
-
-func checkUserLogin(ctx *context.Context) {
-	beego.BeeLogger.Info("check user login")
-	userId, ok := ctx.Input.Session(SessionUserKey).(int64)
-	if ok {
-		_, ok := ctx.Input.Session(SessionWxUserKey).(int64)
-		if !ok {
-			beego.BeeLogger.Info("user has login, try to set seesion[wx_user]")
-			// 如果用户登录了,且有绑定了wx_user,则设置微信用户登录
-			wxUser := user_model.GetWxUserByUserId(userId, true)
-			if wxUser != nil {
-				ctx.Output.Session(SessionWxUserKey, wxUser.Id)
+		} else {
+			inputToken = authorizationData[1]
+			var wxUser *user_model.WxUser
+			user_token, err := token_model.ValidateToken(inputToken)
+			wxUser = user_model.GetWxUserById(user_token.Id, true)
+			if err != nil || wxUser == nil {
+				beego.BeeLogger.Warn("token error : %v", err)
+				// 验证 Token 无效
+				errCode := &ErrCode{
+					Code:     UserNeedLogin[0],
+					Msg:      UserNeedLogin[1],
+					Redirect: "",
+					Data:     nil,
+				}
+				ctx.Output.SetStatus(403)
+				ctx.Output.JSON(errCode, true, true)
 			}
 		}
 	} else {
-		_, ok := ctx.Input.Session(SessionWxUserKey).(int64)
-		if ok {
-			beego.BeeLogger.Info("user not login, wx_user is login,and try to ask user binding tel.")
-			// 如果用户没登录了,但采用微信账户登录,则需要微信用户绑定手机从而创建用户记录
-			errCode := &ErrCode{
-				Code:     UserNeedTel[0],
-				Msg:      UserNeedTel[1],
-				Redirect: fmt.Sprintf("%s/user/binding/state", beego.AppConfig.String("WWWHost")),
-				Data:     nil,
-			}
-			ctx.Output.SetStatus(401)
-			ctx.Output.JSON(errCode, true, true)
-			return
-		}
 		errCode := &ErrCode{
 			Code:     UserNeedLogin[0],
 			Msg:      UserNeedLogin[1],
@@ -472,8 +368,8 @@ func checkUserLogin(ctx *context.Context) {
 		}
 		ctx.Output.SetStatus(401)
 		ctx.Output.JSON(errCode, true, true)
-		return
 	}
+	return
 }
 
 //检查来自大后台的请求是否为服务器IP
@@ -494,9 +390,9 @@ func CheckIsInvokeFromRailsAdmin(ctx *context.Context) {
 }
 
 func (self *BaseController) Prepare() {
-	beego.BeeLogger.Info("invote controller Prepare func")
+	//beego.BeeLogger.Info("invote controller Prepare func")
 	needChkWxUserLogin := true
-	needChkUserLogin := true
+	//needChkUserLogin := true
 	// needChkWxUserSubscribe := false
 	_, actionName := self.GetControllerAndAction()
 
@@ -508,21 +404,10 @@ func (self *BaseController) Prepare() {
 			}
 		}
 	}
-	if len(self.ExceptCheckUserLoginAction) > 0 {
-		for _, an := range self.ExceptCheckUserLoginAction {
-			if strings.ToLower(an) == "*" || strings.ToLower(an) == strings.ToLower(actionName) {
-				needChkUserLogin = false
-				break
-			}
-		}
-	}
 
 	if needChkWxUserLogin {
 		checkWxUserLogin(self.Ctx)
 	}
-	if needChkUserLogin {
-		checkUserLogin(self.Ctx)
-	}
 
 }
 
@@ -622,3 +507,26 @@ func (self *BaseController) GetCdnFullImgUrl(img string) string {
 		return fmt.Sprintf("%s/%s", beego.AppConfig.String("AliCDNImgHost"), img)
 	}
 }
+
+// ServeJSON sends a json response with encoding charset.
+func (c *BaseController) ServeResultJSON(encoding ...bool) {
+	from := c.GetString("source")
+	//beego.BeeLogger.Warn("from--%s", from)
+	type Result struct {
+		Result interface{} `json:"result"`
+	}
+	var (
+		hasIndent   = true
+		hasEncoding = false
+	)
+	if beego.AppConfig.String("RunMode") == "prod" {
+		hasIndent = false
+	}
+	if len(encoding) > 0 && encoding[0] == true {
+		hasEncoding = true
+	}
+	if from == beego.AppConfig.String("SourceList") {
+		c.Data["json"] = &Result{Result: c.Data["json"]}
+	}
+	c.Ctx.Output.JSON(c.Data["json"], hasIndent, hasEncoding)
+}

+ 1 - 1
go/gopath/src/fohow.com/apps/models/address_model/init.go

@@ -5,5 +5,5 @@ import (
 )
 
 func init() {
-	orm.RegisterModel(new(Address))
+	orm.RegisterModel(new(Address), new(PickAddress))
 }

+ 141 - 0
go/gopath/src/fohow.com/apps/models/address_model/pick_address.go

@@ -0,0 +1,141 @@
+package address_model
+
+import (
+	"fmt"
+	"time"
+
+	"github.com/astaxie/beego"
+	"github.com/astaxie/beego/orm"
+)
+
+const (
+	pick_addresses_tablename = "pick_addresses"
+)
+
+type PickAddress struct {
+	Id        int64     `orm:"column(id);pk"                                  json:"id"`         // int(11)
+	WxUserId  int64     `orm:"column(wx_user_id);null"                        json:"wx_user_id"` // int(11)
+	Contact   string    `orm:"column(contact);null"                           json:"contact"`    // varchar(255)
+	Tel       string    `orm:"column(tel);null"                               json:"tel"`        // varchar(255)
+	Remark    string    `orm:"column(remark);null"                            json:"remark"`     // text
+	State     int64     `orm:"column(state);null"                             json:"state"`      // tinyint(1)
+	CreatedAt time.Time `orm:"column(created_at);auto_now_add;type(datetime)" json:"-"`          // datetime
+	UpdatedAt time.Time `orm:"column(updated_at);auto_now;type(datetime)"     json:"-"`          // datetime
+}
+
+func (self *PickAddress) TableName() string {
+	return pick_addresses_tablename
+}
+
+func (self *PickAddress) SetDefault() *PickAddress {
+	pick_addresses := GetPickAddressesByWxUId(self.WxUserId)
+	for _, pick_address := range pick_addresses {
+		if pick_address.Id == self.Id {
+			pick_address.State = 1
+		} else {
+			pick_address.State = 0
+		}
+		go pick_address.Save()
+	}
+	return self
+}
+
+func GetUserPickAddressById(pick_addressId int64) *PickAddress {
+	pick_address := &PickAddress{}
+	if err := orm.NewOrm().QueryTable(pick_address).Filter("id", pick_addressId).Limit(1).
+		One(pick_address); err != nil {
+		beego.BeeLogger.Error("get pick_address by id=[%s] err=[%s]", pick_addressId, err)
+		return nil
+	}
+	return pick_address
+}
+
+// 找出微信用户的默认地址
+func GetUserDefaultPickAddress(wxUId int64) *PickAddress {
+	item := &PickAddress{}
+	if err := orm.NewOrm().QueryTable(item).
+		Filter("wx_user_id", wxUId).OrderBy("-state").
+		Limit(1).One(item); err != nil {
+		// beego.BeeLogger.Error("get user default pick_address user_id=[%d] err=[%s]", uId, err)
+		return nil
+	}
+	return item
+}
+
+// 找出用户的所有地址
+func GetPickAddressesByWxUId(wxUId int64) (items []*PickAddress) {
+	o := orm.NewOrm()
+	_, err := o.QueryTable(new(PickAddress)).
+		Filter("wx_user_id", wxUId).All(&items)
+	if err != nil {
+		beego.BeeLogger.Error("GetPickAddressesByWxUId err=%s", wxUId, err)
+		return nil
+	}
+	return items
+}
+
+//根据userid, id找地址
+func GetPickAddressByWxUIdAndId(wxUId, id int64) *PickAddress {
+	item := &PickAddress{}
+	if err := orm.NewOrm().QueryTable(item).
+		Filter("wx_user_id", wxUId).Filter("id", id).
+		Limit(1).One(item); err != nil {
+		beego.BeeLogger.Error("get pick_address wx_user_id=[%d] id=[%d] err=[%s]", wxUId, id, err)
+		return nil
+	}
+	return item
+}
+
+func GetUserPickAddressList(wxUId int64, sort string) (items []*PickAddress) {
+	o := orm.NewOrm()
+	orderBy := fmt.Sprintf("-%s", sort)
+	_, err := o.QueryTable(new(PickAddress)).
+		Filter("wx_user_id", wxUId).OrderBy(orderBy).All(&items)
+	if err != nil {
+		beego.BeeLogger.Error("GetUserPickAddressList err=%s", wxUId, err)
+		return nil
+	}
+	return items
+}
+
+func CreatePickAddress(wxUId, uId int64, contact, tel, remark string) *PickAddress {
+	item := &PickAddress{
+		WxUserId: wxUId,
+		Contact:  contact,
+		Tel:      tel,
+
+		Remark: remark}
+	id, err := orm.NewOrm().Insert(item)
+	if err != nil {
+		beego.BeeLogger.Error("insert PickAddress err=[%s]", err)
+		return nil
+	}
+	item.Id = id
+	return item
+}
+
+func (self *PickAddress) Update(contact, tel, remark string) *PickAddress {
+	self.Contact = contact
+	self.Tel = tel
+	self.Remark = remark
+	self.Save()
+	return self
+
+}
+
+func (self *PickAddress) Delete() error {
+	o := orm.NewOrm()
+	if _, err := o.Delete(&PickAddress{Id: self.Id}); err != nil {
+		beego.BeeLogger.Error("Delete PickAddress id=[%d] .err=[%s]", self.Id, err)
+		return err
+	}
+	return nil
+}
+
+func (self *PickAddress) Save() error {
+	if _, err := orm.NewOrm().Update(self); err != nil {
+		beego.BeeLogger.Error("Save PickAddress id=[%d] .err=[%s]", self.Id, err)
+		return err
+	}
+	return nil
+}

+ 28 - 0
go/gopath/src/fohow.com/apps/models/balance_model/balance.go

@@ -51,6 +51,12 @@ const (
 	BALANCE_SOURCE_PROMOTION      = "promotion"
 	BALANCE_SOURCE_PROMOTION_NAME = "促销赠送"
 
+	BALANCE_SOURCE_SHOP_PROMOTION         = "shop_promotion"
+	BALANCE_SOURCE_BALANCE_PROMOTION_NAME = "店长促销赠送"
+
+	BALANCE_SOURCE_BALANCE_RECHARGE_PROMOTION      = "balance_promotion"
+	BALANCE_SOURCE_BALANCE_RECHARGE_PROMOTION_NAME = "充值订单促销赠送"
+
 	PAY_WAY_TYPE_SERVICE_WXPAY = "service_wxpay"
 )
 
@@ -136,6 +142,10 @@ func (self *Balance) GetSourceName() string {
 		sourceName = SHOP_APPYCATION_NAME
 	case BALANCE_SOURCE_PROMOTION:
 		sourceName = BALANCE_SOURCE_PROMOTION_NAME
+	case BALANCE_SOURCE_SHOP_PROMOTION:
+		sourceName = BALANCE_SOURCE_BALANCE_PROMOTION_NAME
+	case BALANCE_SOURCE_BALANCE_RECHARGE_PROMOTION:
+		sourceName = BALANCE_SOURCE_BALANCE_RECHARGE_PROMOTION_NAME
 	}
 	return sourceName
 }
@@ -268,6 +278,24 @@ func GetBalanceOrderByOId(oId string, useCache bool) *BalanceOrder {
 	return item
 }
 
+func GetBalanceOrderById(id int64, useCache bool) *BalanceOrder {
+	k := fmt.Sprintf("balance_model.GetBalanceOrderById[%d]", id)
+	if useCache {
+		if order, ok := cache.Cache.Get(k).(*BalanceOrder); ok {
+			return order
+		}
+	}
+
+	item := &BalanceOrder{}
+	if err := orm.NewOrm().QueryTable(item).Filter("id", id).Limit(1).
+		One(item); err != nil {
+		beego.BeeLogger.Info("GetBalanceOrderById(%d), err=%s", id, err)
+		return nil
+	}
+	cache.Cache.Put(k, item, 5*time.Minute)
+	return item
+}
+
 func GetBuyBalanceByRelateId(rId string, useCache bool) *Balance {
 	k := fmt.Sprintf("balance_model.GetBuyBalanceByRelateId[%s]", rId)
 	if useCache {

+ 0 - 167
go/gopath/src/fohow.com/apps/models/base_config/base_config.go

@@ -1,167 +0,0 @@
-package base_config
-
-import (
-	"github.com/astaxie/beego"
-	"github.com/astaxie/beego/orm"
-	"time"
-)
-
-const (
-	base_configs_tablename = "base_configs"
-)
-
-type BaseConfig struct {
-	Id         int64 `orm:"column(id);pk"                                       json:"id"` // int(11)
-	BuyCash    int64 `orm:"column(buy_cash)"                                    json:"-"`  // int(11)
-	SendCash   int64 `orm:"column(send_cash)"                                   json:"-"`  // int(11)
-	CashAward  int64 `orm:"column(cash_award)"                                  json:"-"`  // int(11)
-	OrderLimit int64 `orm:"column(order_limit)"                                 json:"-"`  // int(11)
-	Freight    int64 `orm:"column(freight)"                                     json:"-"`  // int(11)
-
-	UserApply int64 `orm:"column(user_apply)"                                   json:"-"` // int(11)
-	UserCash  int64 `orm:"column(user_cash)"                                    json:"-"` // int(11)
-	UserAward int64 `orm:"column(user_award)"                                   json:"-"` // int(11)
-
-	AgentApply int64 `orm:"column(agent_apply)"                                   json:"-"` // int(11)
-	AgentCash  int64 `orm:"column(agent_cash)"                                    json:"-"` // int(11)
-	AgentAward int64 `orm:"column(agent_award)"                                   json:"-"` // int(11)
-
-	CreatedAt time.Time `orm:"column(created_at);null;auto_now_add;type(datetime)" json:"-"` // datetime
-	UpdatedAt time.Time `orm:"column(updated_at);null;auto_now;type(datetime)"     json:"-"` // datetime
-}
-
-func (self *BaseConfig) TableName() string {
-	return base_configs_tablename
-}
-
-// 获取购券支付金额
-func GetBuyCash() int64 {
-	baseConfig := &BaseConfig{}
-	if err := orm.NewOrm().QueryTable(baseConfig).Limit(1).One(baseConfig); err != nil {
-		beego.BeeLogger.Error("get BaseConfig by  err=%s", err)
-		baseConfig = nil
-		return int64(0)
-	}
-
-	return baseConfig.BuyCash
-}
-
-// 购券实得金额
-func GetSendCash() int64 {
-	baseConfig := &BaseConfig{}
-	if err := orm.NewOrm().QueryTable(baseConfig).Limit(1).One(baseConfig); err != nil {
-		beego.BeeLogger.Error("get BaseConfig by  err=%s", err)
-		baseConfig = nil
-		return int64(0)
-	}
-
-	return baseConfig.SendCash
-}
-
-// 获取购券返佣
-func GetCashAward() int64 {
-	baseConfig := &BaseConfig{}
-	if err := orm.NewOrm().QueryTable(baseConfig).Limit(1).One(baseConfig); err != nil {
-		beego.BeeLogger.Error("get BaseConfig by  err=%s", err)
-		baseConfig = nil
-		return int64(0)
-	}
-
-	return baseConfig.CashAward
-}
-
-// 订单免运金额
-func GetOrderLimit() int64 {
-	baseConfig := &BaseConfig{}
-	if err := orm.NewOrm().QueryTable(baseConfig).Limit(1).One(baseConfig); err != nil {
-		beego.BeeLogger.Error("get BaseConfig by  err=%s", err)
-		baseConfig = nil
-		return int64(0)
-	}
-
-	return baseConfig.OrderLimit
-}
-
-// 获取购券支付金额
-func GetFreight() int64 {
-	baseConfig := &BaseConfig{}
-	if err := orm.NewOrm().QueryTable(baseConfig).Limit(1).One(baseConfig); err != nil {
-		beego.BeeLogger.Error("get BaseConfig by  err=%s", err)
-		baseConfig = nil
-		return int64(0)
-	}
-
-	return baseConfig.Freight
-}
-
-// 会员申店金额
-func GetUserApply() int64 {
-	baseConfig := &BaseConfig{}
-	if err := orm.NewOrm().QueryTable(baseConfig).Limit(1).One(baseConfig); err != nil {
-		beego.BeeLogger.Error("get BaseConfig by  err=%s", err)
-		baseConfig = nil
-		return int64(0)
-	}
-
-	return baseConfig.UserApply
-}
-
-// 会员申店反券
-func GetUserCash() int64 {
-	baseConfig := &BaseConfig{}
-	if err := orm.NewOrm().QueryTable(baseConfig).Limit(1).One(baseConfig); err != nil {
-		beego.BeeLogger.Error("get BaseConfig by  err=%s", err)
-		baseConfig = nil
-		return int64(0)
-	}
-
-	return baseConfig.UserCash
-}
-
-// 会员申店返佣
-func GetUserAward() int64 {
-	baseConfig := &BaseConfig{}
-	if err := orm.NewOrm().QueryTable(baseConfig).Limit(1).One(baseConfig); err != nil {
-		beego.BeeLogger.Error("get BaseConfig by  err=%s", err)
-		baseConfig = nil
-		return int64(0)
-	}
-
-	return baseConfig.UserAward
-}
-
-// 代理申店金额
-func GetAgentApply() int64 {
-	baseConfig := &BaseConfig{}
-	if err := orm.NewOrm().QueryTable(baseConfig).Limit(1).One(baseConfig); err != nil {
-		beego.BeeLogger.Error("get BaseConfig by  err=%s", err)
-		baseConfig = nil
-		return int64(0)
-	}
-
-	return baseConfig.AgentApply
-}
-
-// 代理申店反券
-func GetAgentCash() int64 {
-	baseConfig := &BaseConfig{}
-	if err := orm.NewOrm().QueryTable(baseConfig).Limit(1).One(baseConfig); err != nil {
-		beego.BeeLogger.Error("get BaseConfig by  err=%s", err)
-		baseConfig = nil
-		return int64(0)
-	}
-
-	return baseConfig.AgentCash
-}
-
-// 代理申店返佣
-func GetAgentAward() int64 {
-	baseConfig := &BaseConfig{}
-	if err := orm.NewOrm().QueryTable(baseConfig).Limit(1).One(baseConfig); err != nil {
-		beego.BeeLogger.Error("get BaseConfig by  err=%s", err)
-		baseConfig = nil
-		return int64(0)
-	}
-
-	return baseConfig.AgentAward
-}

+ 0 - 7
go/gopath/src/fohow.com/apps/models/base_config/init.go

@@ -1,7 +0,0 @@
-package base_config
-
-import "github.com/astaxie/beego/orm"
-
-func init() {
-	orm.RegisterModel(new(BaseConfig))
-}

+ 39 - 19
go/gopath/src/fohow.com/apps/models/live_model/live_broad.go

@@ -30,6 +30,7 @@ type LiveBroad struct {
 	DateFomat      int       `orm:"-"                                             json:"date"`                        // varchar(255)
 	HourFomat      string    `orm:"-"                                             json:"begin_hour"`                  // varchar(255)
 	EndHourFomat   string    `orm:"-"                                             json:"end_hour"`                    // varchar(255)
+	RankStrs       string    `orm:"column(rank_strs);null"              json:"rank_strs"`                             // int(11)
 	CreatedAt      time.Time `orm:"column(created_at);null;auto_now_add;type(datetime)"  json:"created_at,omitempty"` // datetime
 	UpdatedAt      time.Time `orm:"column(updated_at);null;auto_now;type(datetime)"      json:"updated_at,omitempty"` // datetime
 }
@@ -71,19 +72,30 @@ func GetCurrentShowLive(useCache bool) *LiveBroad {
 }
 
 //获取最直播列表
-func GetLatest(page, perPage, recommend int64, useCache bool) (LiveBroads []*LiveBroad) {
-	k := fmt.Sprintf("LiveBroad_model.GetLatest.page(%d).perPage(%d).recommend(%d)", page, perPage, recommend)
+func GetLatest(page, perPage, recommend, depart, rank int64, useCache bool) (list []*LiveBroad) {
+	k := fmt.Sprintf("LiveBroad_model.GetLatest.page(%d).perPage(%d).recommend(%d).depart(%d)", page, perPage, recommend, depart)
 	if useCache {
 		if ret, ok := cache.Cache.Get(k).([]*LiveBroad); ok {
 			return ret
 		}
 	}
-	o := orm.NewOrm()
-	_, err := o.QueryTable(new(LiveBroad)).Filter("recommend__gt", recommend).OrderBy("-recommend", "-created_at").Limit(perPage, (page-1)*perPage).All(&LiveBroads)
+	sql := `
+		select a.* from
+		live_broads a left join depart_records_live_broads b on a.id=b.live_broad_id
+		where a.recommend > ? and (b.depart_record_id=? or b.depart_record_id is null ) and (find_in_set(?,a.rank_strs) or a.rank_strs="" )
+		order by recommend desc, created_at desc  limit %d, %d ; 
+		`
+	sql = fmt.Sprintf(sql, (page-1)*perPage, perPage)
+
+	//beego.BeeLogger.Warn("sql=%s", sql)
+
+	_, err := orm.NewOrm().Raw(sql, recommend, depart, rank).QueryRows(&list)
 	if err != nil {
-		beego.BeeLogger.Debug("GetLatest err=%s", err)
+		beego.BeeLogger.Warn("live_model.GetLatest(%d) err=%s", depart, err)
+		return nil
 	}
-	for _, pd := range LiveBroads {
+
+	for _, pd := range list {
 		pd.Cover = GetCdnFullImgUrl(pd.Cover)
 		pd.BeginTimeFomat = pd.BeginDate.Format("1-02 15:04")
 		pd.EndTimeFomat = pd.EndDate.Format("1-02 15:04")
@@ -93,21 +105,29 @@ func GetLatest(page, perPage, recommend int64, useCache bool) (LiveBroads []*Liv
 		pd.EndHourFomat = pd.EndDate.Format("15:04")
 
 	}
-	cache.Cache.Put(k, LiveBroads, 10*time.Minute)
-	return LiveBroads
+	cache.Cache.Put(k, list, 10*time.Minute)
+	return list
 }
 
-func GetLatestCount(recommend int64, ptype string, useCache bool) int64 {
-	k := fmt.Sprintf("LiveBroad_model.GetLatestCount.recommend(%d)", recommend)
-	if useCache {
-		if ret, ok := cache.Cache.Get(k).(int64); ok {
-			return ret
-		}
+//获取部门直播间总数
+func GetLatestCount(recommend, depart, rank int64) int64 {
+	type Ret struct {
+		Count int64 `json:"count"` //人数
 	}
-	item := new(LiveBroad)
+	ret := &Ret{}
 	o := orm.NewOrm()
-	count, _ := o.QueryTable(item).Filter("recommend__gt", recommend).Count()
-
-	cache.Cache.Put(k, count, 10*time.Minute)
-	return count
+	sql := `
+		 select count(DISTINCT a.id) as count from
+		live_broads a left join depart_records_live_broads b on a.id=b.live_broad_id
+		where a.recommend > ? and (b.depart_record_id=? or b.depart_record_id is null )  and (find_in_set(?,a.rank_strs) or a.rank_strs="" )  ; 
+		`
+	err := o.Raw(sql, recommend, depart, rank).QueryRow(ret)
+	if err != nil {
+		beego.BeeLogger.Error("GetLatestCount, depart:%d, err=[%s]", depart, err)
+		return 0
+	}
+	if ret.Count < 0 {
+		return 0
+	}
+	return ret.Count
 }

+ 19 - 24
go/gopath/src/fohow.com/apps/models/order_model/cart.go

@@ -18,19 +18,25 @@ const (
 )
 
 type Cart struct {
-	Id            int64     `orm:"column(id);pk"                                       json:"id"`         // int(11)
-	ProductId     int64     `orm:"column(product_id)"                                  json:"product_id"` // int(11)
-	UserId        int64     `orm:"column(user_id)"                            json:"user_id"`             // varchar(64)
-	WxUserId      int64     `orm:"column(wx_user_id)"                                  json:"wx_user_id"`
-	CreatedAt     time.Time `orm:"column(created_at);null;auto_now_add;type(datetime)" json:"-"`    // datetime
-	Count         int64     `orm:"column(nums)"                                       json:"count"` // int(11)
-	IsBuy         bool      `orm:"column(is_buy)" 			json:"is_under_seckill"`
-	ProductName   string    `orm:"-"     json:"product_name"`   // decimal(10,2)
-	SizeName      string    `orm:"-"     json:"size_name"`      //   varchar(64)
-	ColorName     string    `orm:"-"     json:"color_name"`     //  varchar(64)
-	Cover         string    `orm:"-"     json:"cover"`          // decimal(10,2)
-	OriginalPrice int64     `orm:"-"     json:"original_price"` // decimal(10,2)
-	Attrs         string    `orm:"-"     json:"attrs"`          // decimal(10,2)
+	Id              int64          `orm:"column(id);pk"                                       json:"id"`         // int(11)
+	ProductId       int64          `orm:"column(product_id)"                                  json:"product_id"` // int(11)
+	UserId          int64          `orm:"column(user_id)"                            json:"user_id"`             // varchar(64)
+	WxUserId        int64          `orm:"column(wx_user_id)"                                  json:"wx_user_id"`
+	CreatedAt       time.Time      `orm:"column(created_at);null;auto_now_add;type(datetime)" json:"-"`    // datetime
+	Count           int64          `orm:"column(nums)"                                       json:"count"` // int(11)
+	IsBuy           bool           `orm:"column(is_buy)" json:"is_under_seckill"`
+	ProductName     string         `orm:"-"     json:"product_name"`       // decimal(10,2)
+	SizeName        string         `orm:"-"     json:"size_name"`          //   varchar(64)
+	ColorName       string         `orm:"-"     json:"color_name"`         //  varchar(64)
+	Cover           string         `orm:"-"     json:"cover"`              // decimal(10,2)
+	OriginalPrice   int64          `orm:"-"     json:"original_price"`     // decimal(10,2)
+	Attrs           string         `orm:"-"     json:"attrs"`              // decimal(10,2)
+	SeckillStartAt  int64          `orm:"-"     json:"seckill_start"`      // datetime
+	SeckillEndAt    int64          `orm:"-"     json:"seckill_end"`        // datetime
+	SeckilShowPrice int64          `orm:"-"     json:"seckill_show_price"` // datetime
+	Package         bool           `orm:"-"     json:"package"`
+	Pv              int64          `orm:"-"     json:"pv"`           // pv
+	PackageList     []*ProductItem `orm:"-"     json:"package_list"` // varchar(255)
 }
 
 func (self *Cart) TableName() string {
@@ -134,17 +140,6 @@ func GetCartById(id int64) (cart *Cart) {
 	return cart
 }
 
-// 根据UserId,productId获取购物车记录
-func GetCartByUidAndPid(uId, pId int64) (cart *Cart) {
-	cart = &Cart{}
-	if err := orm.NewOrm().QueryTable(cart).Filter("user_id", uId).Filter("product_id", pId).Limit(1).
-		One(cart); err != nil {
-		beego.BeeLogger.Error("get cart by uId=%d err=%s", uId, err)
-		cart = nil
-	}
-	return cart
-}
-
 // 根据wxUserId,productId获取购物车记录
 func GetCartByWxUidAndPid(wxUserId, pId int64) (cart *Cart) {
 	cart = &Cart{}

+ 16 - 1
go/gopath/src/fohow.com/apps/models/order_model/init.go

@@ -3,10 +3,25 @@ package order_model
 import (
 	// "time"
 
+	"fmt"
+	"github.com/astaxie/beego"
+
 	// "github.com/astaxie/beego"
 	"github.com/astaxie/beego/orm"
+	"strings"
 )
 
 func init() {
-	orm.RegisterModel(new(Order), new(Cart), new(OrderDetail), new(OrderRefund))
+	orm.RegisterModel(new(Order), new(Cart), new(OrderDetail), new(OrderRefund), new(OrderDtItem))
+}
+
+func GetCdnFullImgUrl(img string) string {
+	if img == "" {
+		return ""
+	}
+	if strings.HasPrefix(img, "http://") || strings.HasPrefix(img, "https://") {
+		return img
+	} else {
+		return fmt.Sprintf("%s/%s", beego.AppConfig.String("AliCDNImgHost"), img)
+	}
 }

+ 82 - 38
go/gopath/src/fohow.com/apps/models/order_model/order.go

@@ -4,6 +4,8 @@ import (
 	"crypto/md5"
 	"encoding/hex"
 	"fmt"
+	"fohow.com/apps/helper"
+	"fohow.com/apps/models/sys_config"
 	"strconv"
 	"strings"
 	"time"
@@ -27,6 +29,7 @@ const (
 	STATUS_COMPLETE    = "complete"    //"已完成"
 	STATUS_DISPATCH    = "dispatch"    // '待收货',
 	STATUS_REFUNDED    = "refunded"    // '已退款',
+	WAIT_COMMEN        = "waitcommen"  //"待评价"
 
 	ORDER_ID_PREFIX_EX = "EX" //兑换订单
 
@@ -35,6 +38,8 @@ const (
 	PAY_WAY_INTEGRAl = "integral"  //提货券支付
 	PAY_WAY_CENT     = "cent"      //积分支付
 
+	SOURCE_APP = "app"
+
 	SOURCE_XCX     = "xcx"
 	SOURCE_GZH     = "gzh"
 	SOURCE_D5C_SYS = "d5c_sys"
@@ -57,6 +62,10 @@ const (
 	SHOP_BENETFIT_BL = float64(0.08)
 
 	ZT_PASSWORD = "pQtIjP"
+
+	//物流类型 0:快递运输, 1:门店自提
+	PICK_EXPRESS = int64(0)
+	PICK_SHOP    = int64(1)
 )
 
 var STATUS_CN_TEXT = map[string]string{
@@ -75,43 +84,51 @@ var ORDER_TYPE_CN_TEXT = map[int64]string{
 }
 
 type Order struct {
-	Id             int64                    `orm:"column(id);pk"                                       json:"id"`       // int(11)
-	OrderId        string                   `orm:"column(order_id)"                                    json:"order_id"` // varchar(255)
-	OrderType      int64                    `orm:"column(order_type)"                                  json:"order_type"`
-	WxUserId       int64                    `orm:"column(wx_user_id)"                                  json:"wx_user_id"`
-	UserId         int64                    `orm:"column(user_id)"                                     json:"user_id"`          // int(11)
-	TotalPrice     int64                    `orm:"column(total_price)"                                 json:"total_price"`      // int(11)
-	PaiedPrice     int64                    `orm:"column(paied_price);null"                            json:"paied_price"`      // int(11)
-	CouponPrice    int64                    `orm:"column(coupon_price);null"                           json:"coupon_price"`     // int(11)
-	CentPrice      int64                    `orm:"column(cent_price);null"                             json:"cent_price"`       // int(11)
-	BuyPrice       int64                    `orm:"column(buy_price);null"                              json:"-"`                // int(11)
-	Count          int64                    `orm:"column(count);null"                                  json:"count"`            // int(11)
-	PaiedAt        int64                    `orm:"column(paied_at);null"                               json:"paied_at"`         // int(11)
-	TradeNo        string                   `orm:"column(trade_no);null"                               json:"trade_no"`         // varchar(255)
-	Status         string                   `orm:"column(status);null"                                 json:"status"`           // varchar(255)
-	StatusCn       string                   `orm:"-"                                                   json:"status_cn"`        // varchar(255)
-	PayWay         string                   `orm:"column(pay_way);null"                                json:"pay_way"`          // varchar(255)
-	Source         string                   `orm:"column(source);null"                                 json:"source"`           // varchar(255)
-	Tel            string                   `orm:"column(tel);null"                                    json:"tel"`              // varchar(255)
-	Address        string                   `orm:"column(address);null"                                json:"address"`          // varchar(255)
-	Contact        string                   `orm:"column(contact);null"                                json:"contact"`          // varchar(255)
-	ExpressCompany string                   `orm:"column(express_company);null"                        json:"express_company"`  // varchar(255)
-	ExpressOrderNo string                   `orm:"column(express_order_no);null"                       json:"express_order_no"` // varchar(255)
-	Remark         string                   `orm:"column(remark);null"                                 json:"remark"`           // varchar(255)
-	OrderRemark    string                   `orm:"column(order_remark);null"                           json:"-"`                // varchar(255)
-	ExpressCode    string                   `orm:"column(express_code);null"                           json:"express_code"`     // varchar(255)
-	Sign           string                   `orm:"-"                                                   json:"sign"`             // varchar(255)
-	CTime          int64                    `orm:"-"                                 json:"ctime"`                              // int(11)
-	DTime          int64                    `orm:"-"                                 json:"dtime"`                              // int(11)
-	Freight        int64                    `orm:"column(freight);null"                            json:"freight"`              // int(11)
-	Depart         int64                    `orm:"column(depart)" json:"-"`                                                     // datetime
-	DispatchTime   time.Time                `orm:"column(dispatch_time);null;type(datetime)"           json:"dispatch_time"`
-	ReceiveTime    time.Time                `orm:"column(receive_time);null;type(datetime)"            json:"receive_time"`
-	PaiedTime      time.Time                `orm:"column(paied_time);null;type(datetime)"              json:"paied_time"` // int(11)
-	CreatedAt      time.Time                `orm:"column(created_at);null;auto_now_add;type(datetime)" json:"-"`          // datetime
-	UpdatedAt      time.Time                `orm:"column(updated_at);null;auto_now;type(datetime)"     json:"-"`          // datetime
-	WxUser         *user_model.WxUser       `orm:"-"                                 json:"wx_user"`
-	ProductList    []*product_model.Product `orm:"-"                                 json:"product_list"` // varchar(255)
+	Id             int64              `orm:"column(id);pk"                                       json:"id"`       // int(11)
+	OrderId        string             `orm:"column(order_id)"                                    json:"order_id"` // varchar(255)
+	OrderType      int64              `orm:"column(order_type)"                                  json:"order_type"`
+	WxUserId       int64              `orm:"column(wx_user_id)"                                  json:"wx_user_id"`
+	UserId         int64              `orm:"column(user_id)"                                     json:"user_id"`          // int(11)
+	TotalPrice     int64              `orm:"column(total_price)"                                 json:"total_price"`      // int(11)
+	PaiedPrice     int64              `orm:"column(paied_price);null"                            json:"paied_price"`      // int(11)
+	CouponPrice    int64              `orm:"column(coupon_price);null"                           json:"coupon_price"`     // int(11)
+	CentPrice      int64              `orm:"column(cent_price);null"                             json:"cent_price"`       // int(11)
+	BuyPrice       int64              `orm:"column(buy_price);null"                              json:"-"`                // int(11)
+	Count          int64              `orm:"column(count);null"                                  json:"count"`            // int(11)
+	PaiedAt        int64              `orm:"column(paied_at);null"                               json:"paied_at"`         // int(11)
+	TradeNo        string             `orm:"column(trade_no);null"                               json:"trade_no"`         // varchar(255)
+	Status         string             `orm:"column(status);null"                                 json:"status"`           // varchar(255)
+	StatusCn       string             `orm:"-"                                                   json:"status_cn"`        // varchar(255)
+	PayWay         string             `orm:"column(pay_way);null"                                json:"pay_way"`          // varchar(255)
+	Source         string             `orm:"column(source);null"                                 json:"source"`           // varchar(255)
+	Tel            string             `orm:"column(tel);null"                                    json:"tel"`              // varchar(255)
+	Address        string             `orm:"column(address);null"                                json:"address"`          // varchar(255)
+	Contact        string             `orm:"column(contact);null"                                json:"contact"`          // varchar(255)
+	ExpressCompany string             `orm:"column(express_company);null"                        json:"express_company"`  // varchar(255)
+	ExpressOrderNo string             `orm:"column(express_order_no);null"                       json:"express_order_no"` // varchar(255)
+	Remark         string             `orm:"column(remark);null"                                 json:"remark"`           // varchar(255)
+	OrderRemark    string             `orm:"column(order_remark);null"                           json:"-"`                // varchar(255)
+	ExpressCode    string             `orm:"column(express_code);null"                           json:"express_code"`     // varchar(255)
+	Sign           string             `orm:"-"                                                   json:"sign"`             // varchar(255)
+	CTime          int64              `orm:"-"                                 json:"ctime"`                              // int(11)
+	DTime          int64              `orm:"-"                                 json:"dtime"`                              // int(11)
+	Freight        int64              `orm:"column(freight);null"                            json:"freight"`              // int(11)
+	Depart         int64              `orm:"column(depart)" json:"-"`                                                     // datetime
+	Pv             int64              `orm:"column(pv)"            json:"pv"`                                             // varchar(255)
+	PickWay        int64              `orm:"column(pick_way)"            json:"pick_way"`                                 // 物流方式
+	PickDept       int64              `orm:"column(pick_dept)"           json:"pick_dept"`                                // 自提部门
+	AddressId      int64              `orm:"column(address_id)"          json:"address_id"`                               // 地址ID
+	DispatchTime   time.Time          `orm:"column(dispatch_time);null;type(datetime)"           json:"dispatch_time"`
+	ReceiveTime    time.Time          `orm:"column(receive_time);null;type(datetime)"            json:"receive_time"`
+	PaiedTime      time.Time          `orm:"column(paied_time);null;type(datetime)"              json:"paied_time"` // int(11)
+	HasCommission  bool               `orm:"has_commission"                                      json:"-"`
+	CreatedAt      time.Time          `orm:"column(created_at);null;auto_now_add;type(datetime)" json:"-"` // datetime
+	UpdatedAt      time.Time          `orm:"column(updated_at);null;auto_now;type(datetime)"     json:"-"` // datetime
+	Promotions     string             `orm:"column(promotions);null"                           json:"-"`   // varchar(255)
+	SpecialPro     bool               `orm:"-"                                 json:"special_promotion"`   // int(11)
+	ShutWechat     bool               `orm:"-"                                 json:"shut_wechat"`         // int(11)
+	WxUser         *user_model.WxUser `orm:"-"                                 json:"wx_user"`
+	ProductList    []*OrderDetail     `orm:"-"                                 json:"product_list"` // varchar(255)
 }
 
 func (self *Order) TableName() string {
@@ -185,6 +202,11 @@ func GetOrderById(oId string, useCache bool) (order *Order) {
 		item.CTime = item.CreatedAt.Unix()
 		item.DTime = item.DispatchTime.Unix()
 	}
+	item.SpecialPro = false
+	pro := helper.NewStr(item.Promotions).Strrpos(sys_config.SPECIAL_PROMOTION, 0)
+	if pro >= 0 {
+		item.SpecialPro = true
+	}
 	cache.Cache.Put(k, item, 5*time.Minute)
 	return item
 
@@ -198,7 +220,7 @@ func GetOrderByIntId(id int64) (order *Order) {
 		beego.BeeLogger.Error("get order by id=%d err=%s", id, err)
 		order = nil
 	}
-	if len(order.ExpressOrderNo) > 0 {
+	if order != nil && len(order.ExpressOrderNo) > 0 {
 		order.Sign = GenExpressPassword(order.ExpressOrderNo)
 	}
 	return order
@@ -219,6 +241,15 @@ func (self *Order) Save() bool {
 	return true
 }
 
+func (self *Order) Delete() error {
+	o := orm.NewOrm()
+	if _, err := o.Delete(&Order{Id: self.Id}); err != nil {
+		beego.BeeLogger.Error("Delete Order id=[%d] .err=[%s]", self.Id, err)
+		return err
+	}
+	return nil
+}
+
 //生成订单ID
 func createOrderId(prefix string) string {
 	n := time.Now().Format("20060102")
@@ -699,12 +730,25 @@ func GetPaiedOrderByWxUIdAndPayWayLimitOne(wxUserId int64, payWay string, useCac
 func UpdateSaleNums(saleProducts map[int64]int64) bool {
 
 	for pId, nums := range saleProducts {
+
+		//beego.BeeLogger.Error("pId,Nums %d--%d", pId, nums)
+
 		product := product_model.GetProductById(pId, true)
 		if product == nil {
 			continue
 		}
 		product.SaleNums += nums
 		product.Save()
+		//套装商品拆分更新销量
+		if product.Package {
+			package_list := product_model.GetPackageList(product.Id, true)
+			for _, item := range package_list {
+				item_pd := product_model.GetProductById(item.ItemId, true)
+				count := item.Nums * nums
+				item_pd.SaleNums += count
+				item_pd.Save()
+			}
+		}
 	}
 	return true
 }

+ 76 - 20
go/gopath/src/fohow.com/apps/models/order_model/order_detail.go

@@ -22,21 +22,27 @@ const (
 )
 
 type OrderDetail struct {
-	Id                   int64     `orm:"column(id);pk"                                       json:"id"`         // int(11)
-	ProductId            int64     `orm:"column(product_id)"                                  json:"product_id"` // int(11)
-	OrderId              int64     `orm:"column(order_id)"                            json:"-"`                  // int(11)
-	Send                 bool      `orm:"column(is_zeng)"                                json:"send"`
-	OrderNo              string    `orm:"column(order_no)"                            json:"order_id"`             // varchar(64)
-	Price                int64     `orm:"column(price)"                                       json:"price"`        // int(11)
-	CreatedAt            time.Time `orm:"column(created_at);null;auto_now_add;type(datetime)" json:"-"`            // datetime
-	Count                int64     `orm:"column(nums)"                                       json:"count"`         // int(11)
-	ProductName          string    `orm:"column(product_name)"                                json:"product_name"` // varchar(255)
-	SizeName             string    `orm:"column(size_name)"                                json:"size_name"`       // varchar(255)
-	ColorName            string    `orm:"column(color_name)"                                json:"color_name"`     // varchar(255)
-	Cover                string    `orm:"-"     json:"cover"`                                                      // decimal(10,2)
-	OriginalPrice        float64   `orm:"-"     json:"original_price"`                                             // decimal(10,2)
-	UnitRoboBalancePrice int64     `orm:"column(unit_robo_balance_price)"                     json:"unit_robo_balance_price"`
-	Attrs                string    `orm:"-"     json:"attrs"` // decimal(10,2)
+	Id                   int64          `orm:"column(id);pk"                                    json:"id"`         // int(11)
+	ProductId            int64          `orm:"column(product_id)"                               json:"product_id"` // int(11)
+	OrderId              int64          `orm:"column(order_id)"                                 json:"-"`          // int(11)
+	Send                 bool           `orm:"column(is_zeng)"                                  json:"send"`
+	OrderNo              string         `orm:"column(order_no)"                                 json:"order_id"`        // varchar(64)
+	Price                int64          `orm:"column(price)"                                       json:"price"`        // int(11)
+	CreatedAt            time.Time      `orm:"column(created_at);null;auto_now_add;type(datetime)" json:"-"`            // datetime
+	Count                int64          `orm:"column(nums)"                                       json:"count"`         // int(11)
+	ProductName          string         `orm:"column(product_name)"                                json:"product_name"` // varchar(255)
+	SizeName             string         `orm:"column(size_name)"                                json:"size_name"`       // varchar(255)
+	ColorName            string         `orm:"column(color_name)"                               json:"color_name"`      // varchar(255)
+	Cover                string         `orm:"-"     json:"cover"`                                                      // decimal(10,2)
+	OriginalPrice        float64        `orm:"-"     json:"original_price"`                                             // decimal(10,2)
+	Commend              bool           `orm:"column(commend)"                                  json:"commend"`
+	UnitRoboBalancePrice int64          `orm:"column(unit_robo_balance_price)"                  json:"unit_robo_balance_price"`
+	RelateProductId      int64          `orm:"column(relate_product_id)"                        json:"-"`
+	Attrs                string         `orm:"-"                                                json:"attrs"` // decimal(10,2)
+	Depart               int64          `orm:"column(depart)" json:"-"`                                       // datetime
+	Pv                   int64          `orm:"column(pv)"            json:"pv"`                               // varchar(255)
+	Package              bool           `orm:"-"                                                json:"package"`
+	PacakageList         []*ProductItem `orm:"-"                                                json:"package_list"` // varchar(255)
 }
 
 func (self *OrderDetail) TableName() string {
@@ -44,19 +50,21 @@ func (self *OrderDetail) TableName() string {
 }
 
 //创建订单项
-func (self *OrderDetail) Create(oId string, orderId, pId, pPrice, unitRoboBalancePrice int64, pName, sizeName, colorName string,
-	pCount int64) *OrderDetail {
+func (self *OrderDetail) Create(oId string, orderId, pId, relatePId, pPrice, unitRoboBalancePrice int64, pName, sizeName, colorName string,
+	pCount, depart int64) *OrderDetail {
 	item := &OrderDetail{
 		OrderNo:              oId,
 		OrderId:              orderId,
 		Count:                pCount,
 		ProductId:            pId,
+		RelateProductId:      relatePId,
 		Price:                pPrice,
 		UnitRoboBalancePrice: unitRoboBalancePrice,
 		ProductName:          pName,
 		SizeName:             sizeName,
 		ColorName:            colorName,
 		Send:                 false,
+		Depart:               depart,
 	}
 	id, err := orm.NewOrm().Insert(item)
 	if err != nil {
@@ -64,12 +72,16 @@ func (self *OrderDetail) Create(oId string, orderId, pId, pPrice, unitRoboBalanc
 		return nil
 	}
 	item.Id = id
+	if item != nil {
+		go GenerateOrderDtItem(item)
+	}
+
 	return item
 }
 
 //创建订单项
 func SendCreate(oId string, orderId, pId, pPrice, unitRoboBalancePrice int64, pName string,
-	pCount int64) *OrderDetail {
+	pCount, depart int64) *OrderDetail {
 	item := &OrderDetail{
 		OrderNo:              oId,
 		OrderId:              orderId,
@@ -79,6 +91,7 @@ func SendCreate(oId string, orderId, pId, pPrice, unitRoboBalancePrice int64, pN
 		UnitRoboBalancePrice: unitRoboBalancePrice,
 		ProductName:          pName,
 		Send:                 true,
+		Depart:               depart,
 	}
 	id, err := orm.NewOrm().Insert(item)
 	if err != nil {
@@ -86,6 +99,13 @@ func SendCreate(oId string, orderId, pId, pPrice, unitRoboBalancePrice int64, pN
 		return nil
 	}
 	item.Id = id
+	if item != nil {
+		go GenerateOrderDtItem(item)
+		//更新赠品已售数量
+		sendMap := map[int64]int64{pId: pCount}
+		go UpdateSaleNums(sendMap)
+	}
+
 	return item
 }
 
@@ -152,10 +172,46 @@ func GetStaticOrderDetails(bDate, eDate time.Time, state string, isSend bool) (d
 //根据订单Id,获取所有订单项
 func GetDetailsByOrderIdAndPid(oId string, pId int64) (orderDetail *OrderDetail) {
 	orderDetail = &OrderDetail{}
-	if err := orm.NewOrm().QueryTable(orderDetail).Filter("order_no", oId).Filter("product_id", pId).Limit(1).
+	if err := orm.NewOrm().QueryTable(orderDetail).Filter("order_no", oId).Filter("product_id", pId).Filter("is_zeng", false).Limit(1).
 		One(orderDetail); err != nil {
-		beego.BeeLogger.Error("get order detail item by id=%s err=%s", oId, err)
+		beego.BeeLogger.Error("get order detail product nums=%s err=%s", oId, err)
 		orderDetail = nil
 	}
 	return orderDetail
 }
+
+//根据订单Id,获取所有订单项
+func GetDetailsByOrderIdAndRelatePid(oId string, pId int64) int64 {
+	sql := `
+		SELECT
+			sum(nums) as count
+		FROM
+			order_details
+		WHERE
+			order_no =? 
+		and
+			relate_product_id = ?
+	`
+	type Ret struct {
+		Count int64 `json:"count"`
+	}
+
+	var ret Ret
+	err := orm.NewOrm().Raw(sql, oId, pId).QueryRow(&ret)
+
+	if err != nil {
+		beego.BeeLogger.Warn("order_models.GetDetailsByOrderIdAndRelatePid(%d, %s) err[%s]", pId, oId, err)
+		return 0
+	}
+	return ret.Count
+}
+
+//根据订单明细ID获取明细
+func GetOrderDetailById(id int64) *OrderDetail {
+	detail := &OrderDetail{Id: id}
+	if err := orm.NewOrm().Read(detail); err != nil {
+		// beego.BeeLogger.Error("get name product cat by id err=[%s][", err)
+		return nil
+	}
+	return detail
+}

+ 165 - 0
go/gopath/src/fohow.com/apps/models/order_model/order_dt_item.go

@@ -0,0 +1,165 @@
+package order_model
+
+import (
+	"fmt"
+	"fohow.com/apps/models/product_model"
+	"fohow.com/cache"
+	"github.com/astaxie/beego"
+	"github.com/astaxie/beego/orm"
+	"time"
+)
+
+const (
+	order_dt_items_tablename = "base_details"
+)
+
+type OrderDtItem struct {
+	Id        int64     `orm:"column(id);pk"                json:"id"`          // int(11)
+	OrderId   int64     `orm:"column(order_id)"             json:"order_id"`    // int(11)
+	OrderNo   string    `orm:"column(order_no);null"        json:"order_no"`    // varchar(64)
+	OrderDtId int64     `orm:"column(dt_id)"                json:"order_dt_id"` // int(11)
+	ProductId int64     `orm:"column(product_id)"           json:"product_id"`  // int(11)
+	Price     int64     `orm:"column(price)"                json:"price"`       // int(11)
+	Title     string    `orm:"column(product_name);null"    json:"title"`       // varchar(64)
+	Nums      int64     `orm:"column(nums);null"            json:"nums"`        // tinyint(1)
+	Send      bool      `orm:"column(is_zeng)"              json:"send"`
+	SizeName  string    `orm:"column(size_name)"            json:"size_name"`           // varchar(255)
+	ColorName string    `orm:"column(color_name)"           json:"color_name"`          // varchar(255)
+	CreatedAt time.Time `orm:"column(created_at);auto_now_add;type(datetime)" json:"-"` // datetime
+	UpdatedAt time.Time `orm:"column(updated_at);auto_now;type(datetime)"     json:"-"` // datetime
+}
+
+func (self *OrderDtItem) TableName() string {
+	return order_dt_items_tablename
+}
+
+type ProductItem struct {
+	ProductId int64  `orm:"column(product_id)"           json:"product_id"` // int(11)
+	Title     string `orm:"column(title);null"           json:"title"`      // varchar(64)
+	ItemId    int64  `orm:"column(item_id);null"         json:"item_id"`    // tinyint(1)
+	ItemTitle string `orm:"column(item_title);null"      json:"item_title"` // varchar(64)
+	Nums      int64  `orm:"column(nums);null"            json:"nums"`       // tinyint(1)
+}
+
+//创建订单明细项
+func (self *OrderDtItem) Create(orderNo, title, sizeName, colorName string, pId, price, pCount, orderId, orderDtId int64, send bool) *OrderDtItem {
+	item := &OrderDtItem{
+		OrderNo:   orderNo,
+		OrderId:   orderId,
+		OrderDtId: orderDtId,
+		ProductId: pId,
+		Price:     price,
+		Title:     title,
+		Nums:      pCount,
+		Send:      send,
+		SizeName:  sizeName,
+		ColorName: colorName,
+	}
+	id, err := orm.NewOrm().Insert(item)
+	if err != nil {
+		beego.BeeLogger.Error("insert cart item err=[%s]", err)
+		return nil
+	}
+	item.Id = id
+	return item
+}
+
+//生成订单明细
+func GenerateOrderDtItem(detail_item *OrderDetail) error {
+	sizeName := ""
+	colorName := ""
+	product := product_model.GetProductById(detail_item.ProductId, true)
+	if product.Package {
+		product_list := product_model.GetPackageList(product.Id, false)
+		for _, pd := range product_list {
+			pd_info := product_model.GetProductById(pd.ItemId, true)
+
+			//获取商品属性详情
+			if pd_info.SizeId > 0 {
+				productSize := product_model.GetProductAttrValueById(pd_info.SizeId)
+				if productSize != nil {
+					sizeName = productSize.Name
+				}
+			}
+			if pd_info.ColorId > 0 {
+				productColor := product_model.GetProductAttrValueById(pd_info.ColorId)
+				if productColor != nil {
+					colorName = productColor.Name
+				}
+			}
+			count := detail_item.Count * pd.Nums
+			new(OrderDtItem).Create(detail_item.OrderNo, pd.ItemTitle, sizeName, colorName, pd.ItemId, detail_item.Price, count, detail_item.OrderId, detail_item.Id, detail_item.Send)
+		}
+	} else {
+		//获取商品属性详情
+		if product.SizeId > 0 {
+			productSize := product_model.GetProductAttrValueById(product.SizeId)
+			if productSize != nil {
+				sizeName = productSize.Name
+			}
+		}
+		if product.ColorId > 0 {
+			productColor := product_model.GetProductAttrValueById(product.ColorId)
+			if productColor != nil {
+				colorName = productColor.Name
+			}
+		}
+		new(OrderDtItem).Create(detail_item.OrderNo, product.Name, sizeName, colorName, product.Id, detail_item.Price, detail_item.Count, detail_item.OrderId, detail_item.Id, detail_item.Send)
+	}
+	//更新明细pv
+	detail_item.Pv = product.Pv
+	detail_item.Save()
+	//beego.BeeLogger.Warn("orderdtbase  GenerateOrderDtItem ")
+	return nil
+}
+
+//生成订单明细套装
+func GetOrderDetailPackages(orderDtId, nums int64, useCache bool) (list []*ProductItem) {
+	k := fmt.Sprintf("order_model.GetOrderDetailPackages(%d)", orderDtId)
+	if useCache {
+		if ret, ok := cache.Cache.Get(k).([]*ProductItem); ok {
+			return ret
+		}
+	}
+	//sql := fmt.Sprintf("select total_price as investment, user_id, paied_at as invest_time from %s where project_id = ? and state = ? and is_refunded = ? and is_deleted = ? order by invest_time desc, id desc limit %d, %d",
+
+	sql :=
+		fmt.Sprintf(`
+		select product_id as item_id,product_name as item_title,ceil(nums/%d) as nums from
+		base_details
+		where dt_id = ?  ;
+		`, nums)
+	_, err := orm.NewOrm().Raw(sql, orderDtId).QueryRows(&list)
+	if err != nil {
+		beego.BeeLogger.Warn("order_model.GetOrderDetailPackages(%d) err=%s", orderDtId, err)
+		return nil
+	}
+	cache.Cache.Put(k, list, 10*time.Minute)
+	return list
+}
+
+//获取某个商品明细已售总数
+func GetDetailSoldCountByPId(pId int64, useCache bool) int64 {
+	k := fmt.Sprintf("order_model.GetDetailSoldCountByPId(%d)", pId)
+	if useCache {
+		if ret, ok := cache.Cache.Get(k).(int64); ok {
+			return ret
+		}
+	}
+	type Ret struct {
+		Count int64
+	}
+	ret := &Ret{}
+	o := orm.NewOrm()
+	new_tbn := "base_details"
+	tbn := new(Order).TableName()
+	sql := fmt.Sprintf("SELECT sum(`nums`) as count FROM `%s` WHERE order_no in ( select order_id from `%s` where  status not in (?, ?, ?) ) and product_id=?;", new_tbn, tbn)
+	err := o.Raw(sql, STATUS_CLOSED, STATUS_UNPAY, STATUS_REFUNDED, pId).QueryRow(ret)
+	if err != nil {
+		beego.BeeLogger.Error("GetSoldCountByPId err=[%s]", err)
+		return 0
+	}
+
+	cache.Cache.Put(k, ret.Count, 10*time.Minute)
+	return ret.Count
+}

+ 1 - 9
go/gopath/src/fohow.com/apps/models/pay_model/init.go

@@ -1,15 +1,7 @@
 package pay_model
 
-import (
-	// "time"
-
-	// "github.com/astaxie/beego"
-	// "github.com/astaxie/beego/orm"
-	"github.com/astaxie/beego/orm"
-)
-
 func init() {
-	orm.RegisterModel(new(PayConfig))
+
 }
 
 const (

+ 0 - 57
go/gopath/src/fohow.com/apps/models/pay_model/pay_config.go

@@ -1,57 +0,0 @@
-package pay_model
-
-import (
-	"fmt"
-	"fohow.com/cache"
-	"github.com/astaxie/beego"
-	"github.com/astaxie/beego/orm"
-	"time"
-)
-
-const (
-	pay_configs_tablename = "pay_configs"
-)
-
-type PayConfig struct {
-	Id        int64     `orm:"column(id);pk"                                        json:"id"` // int(11)
-	PayCode   string    `orm:"column(pay_code)"                                    json:"-"`
-	Depart    int64     `orm:"column(depart)"                                      json:"-"`                     // int(11)
-	CreatedAt time.Time `orm:"column(created_at);null;auto_now_add;type(datetime)"  json:"created_at,omitempty"` // datetime
-	UpdatedAt time.Time `orm:"column(updated_at);null;auto_now;type(datetime)"      json:"updated_at,omitempty"` // datetime
-}
-
-func (self *PayConfig) TableName() string {
-	return pay_configs_tablename
-}
-
-func (self *PayConfig) Save() error {
-	if _, err := orm.NewOrm().Update(self); err != nil {
-		beego.BeeLogger.Error("Save PayConfig id=[%d] .err=[%s]", self.Id, err)
-		return err
-	}
-	return nil
-}
-
-//根据部门获取收款商户
-func GetPayConfigByDepart(depart int64, useCache bool) string {
-	payCode := "fohow"
-	k := fmt.Sprintf("pay_model.GetPayConfigByDepart.depart(%d)", depart)
-	if useCache {
-		if s, ok := cache.Cache.Get(k).(*PayConfig); ok {
-			return s.PayCode
-		}
-	}
-
-	item := new(PayConfig)
-	o := orm.NewOrm()
-	err := o.QueryTable(item).Filter("depart", depart).OrderBy("-id").Limit(1).One(item)
-	if err != nil {
-		beego.BeeLogger.Info("pay_model.GetPayConfigByDepart.depart(%d) err[%s]", depart, err)
-		return payCode
-	}
-
-	if item != nil {
-		cache.Cache.Put(k, item, 5*time.Minute)
-	}
-	return item.PayCode
-}

+ 44 - 0
go/gopath/src/fohow.com/apps/models/product_model/commend_words.go

@@ -0,0 +1,44 @@
+package product_model
+
+import (
+	"fmt"
+	"fohow.com/cache"
+	"github.com/astaxie/beego"
+	"github.com/astaxie/beego/orm"
+	"time"
+)
+
+const (
+	commend_words_tablename = "commend_words"
+)
+
+type CommendWord struct {
+	Id    int64  `orm:"column(id);pk"                json:"id"`    // int(11)
+	Sort  int64  `orm:"column(sort)"           json:"sort"`        // int(11)
+	Title string `orm:"column(title);null"           json:"title"` // varchar(64)
+	State bool   `orm:"column(state);null"         json:"-"`       // tinyint(1)
+
+}
+
+func (self *CommendWord) TableName() string {
+	return commend_words_tablename
+}
+
+func GetCommendWordsList(perSize int64, useCache bool) (items []*CommendWord) {
+	k := fmt.Sprintf("product_model.GetCommendWordsList(%d)", perSize)
+
+	if useCache {
+		if ret, ok := cache.Cache.Get(k).([]*CommendWord); ok {
+			return ret
+		}
+	}
+
+	o := orm.NewOrm()
+	_, err := o.QueryTable(new(CommendWord)).Filter("state", true).Limit(perSize).OrderBy("-sort").All(&items)
+	if err != nil {
+		beego.BeeLogger.Debug("GetCommendWordsList err=%s", err)
+	}
+
+	cache.Cache.Put(k, items, 10*time.Minute)
+	return items
+}

+ 3 - 0
go/gopath/src/fohow.com/apps/models/product_model/init.go

@@ -15,6 +15,9 @@ func init() {
 		new(ProductAttrConfig),
 		new(Picture),
 		new(ProductCat),
+		new(ProductCommend),
+		new(ProductItem),
+		new(CommendWord),
 	)
 }
 

+ 157 - 36
go/gopath/src/fohow.com/apps/models/product_model/product.go

@@ -35,6 +35,12 @@ const (
 	//规格类型
 	SIZE_TYPE_1 = "size"  //类型
 	SIZE_TYPE_2 = "color" //颜色
+
+	//预售状态
+	DELIVER_STATE_1 = int64(1) //未开始
+	DELIVER_STATE_2 = int64(2) //进行中
+	DELIVER_STATE_3 = int64(3) //已结束
+
 )
 
 func (self *Product) TableName() string {
@@ -83,44 +89,79 @@ type Product struct {
 	DeliverStartAt   time.Time `orm:"column(deliver_start_at);null;auto_now_add;type(datetime)" json:"-"` // datetime
 	DeliverStopTime  int64     `orm:"-" json:"deliver_stop_time"`                                         // datetime
 	DeliverStartTime int64     `orm:"-" json:"deliver_start_time"`                                        // datetime
+	IsDeliver        bool      `orm:"-"                                        json:"is_deliver"`
+	DeliverState     int64     `orm:"-" json:"deliver_state"` // datetime
 
 	IsOnlyNew  bool  `orm:"column(is_only_new)"                                        json:"is_only_new"`
 	OrderCount int64 `orm:"-"                                   json:"order_count"` // int(11)
 
-	Specification  string `orm:"column(specification)"                          json:"specification"`    // varchar(255)
-	NoDeliveryArea string `orm:"column(no_delivery_area)"                       json:"no_delivery_area"` // varchar(255)
+	Specification    string `orm:"column(specification)"                          json:"specification"`      // varchar(255)
+	NoDeliveryArea   string `orm:"column(no_delivery_area)"                       json:"no_delivery_area"`   // varchar(255)
+	OnlyDeliveryArea string `orm:"column(only_delivery_area)"                     json:"only_delivery_area"` // varchar(255)
 
 	//视频资料
 	VideoState bool   `orm:"column(video_state)"                                        json:"video_state"`
 	VideoUrl   string `orm:"column(video_url)"                       json:"video_url"` // varchar(255)
 	VideoImg   string `orm:"-"                       json:"video_img"`                 // varchar(255)
 	//规格相关
-	RelateProductId  int64  `orm:"column(relate_product_id)"                          json:"relate_product_id"` // varchar(255)
-	ShowFlag         bool   `orm:"column(show_flag)"                          json:"-"`                         // varchar(255)
-	SizeId           int64  `orm:"column(size_id)"                          json:"size_id"`                     // varchar(255)
-	ColorId          int64  `orm:"column(color_id)"                          json:"color_id"`                   // varchar(255)
-	HaveSize         bool   `orm:"-"                         json:"have_size"`                                  // bool
-	IsZeng           bool   `orm:"-"                         json:"is_zeng"`                                    // bool
-	SizeName         string `orm:"-"                       json:"size_name"`                                    // varchar(255)
-	ColorName        string `orm:"-"                       json:"color_name"`                                   // varchar(255)
-	SinglePurchLimit int64  `orm:"column(single_purch_limit)"     json:"-"`                                     // varchar(255)
-
+	RelateProductId int64 `orm:"column(relate_product_id)"                          json:"relate_product_id"` // varchar(255)
+	ShowFlag        bool  `orm:"column(show_flag)"                          json:"-"`                         // varchar(255)
+	SizeId          int64 `orm:"column(size_id)"                       json:"size_id"`                        // varchar(255)
+	ColorId         int64 `orm:"column(color_id)"                      json:"color_id"`                       // varchar(255)
+
+	HaveSize         bool            `orm:"-"                                     json:"have_size"`  // bool
+	SizeName         string          `orm:"-"                                     json:"size_name"`  // varchar(255)
+	ColorName        string          `orm:"-"                                     json:"color_name"` // varchar(255)
+	KeyWords         string          `orm:"column(key_words)"                     json:"key_words"`  // varchar(255)
+	SinglePurchLimit int64           `orm:"column(single_purch_limit)"            json:"-"`          // varchar(255)
+	Pv               int64           `orm:"column(pv)"                  json:"pv"`                   // varchar(255)
+	OutNums          int64           `orm:"column(out_nums)"            json:"-"`                    // varchar(255)
+	Package          bool            `orm:"column(package)"                          json:"package"` // varchar(255)
+	PackageList      []*ProductItem  `orm:"-"                           json:"package_list"`         // varchar(255)
+	Size             *ProductAttrKey `orm:"-"                            json:"size_list"`           // varchar(255)
+	Color            *ProductAttrKey `orm:"-"                           json:"color_list"`           // varchar(255)
 }
 
 //获取最新推荐商品
-func GetLatest(page, perPage, recommend int64, ptype string, useCache bool) (products []*Product) {
+func GetLatest(page, perPage, recommend, priceSort, saleSort int64, ptype string, useCache bool) (products []*Product) {
 	k := fmt.Sprintf("product_model.GetLatest.page(%d).perPage(%d).recommend(%d)", page, perPage, recommend)
 	if useCache {
 		if ret, ok := cache.Cache.Get(k).([]*Product); ok {
 			return ret
 		}
 	}
-	o := orm.NewOrm()
-	_, err := o.QueryTable(new(Product)).Filter("status", 1).
-		Filter("recommend__gt", recommend).Filter("show_flag", true).Filter("ptype", ptype).
-		OrderBy("-recommend", "-created_at").
-		Limit(perPage, (page-1)*perPage).
-		All(&products)
+	var priceSql, saleSql, orderSql string
+	if priceSort == int64(1) {
+		//降序
+		priceSql = "price desc"
+	} else if priceSort == int64(2) {
+		//升序
+		priceSql = "price asc"
+	}
+	if saleSort == int64(1) {
+		//降序
+		saleSql = "sale_nums desc"
+	} else if priceSort == int64(2) {
+		saleSql = "sale_nums asc"
+	}
+	if len(priceSql) <= 0 && len(saleSql) <= 0 {
+		orderSql = "recommend desc,created_at desc"
+	} else if len(priceSql) <= 0 {
+		orderSql = saleSql
+	} else if len(saleSql) <= 0 {
+		orderSql = priceSql
+	} else {
+		orderSql = fmt.Sprintf("%s,%s", priceSql, saleSql)
+	}
+	sql := `
+		select * from products
+		where status = ? and recommend > ? and show_flag=? and ptype=?
+		order by %s limit %d, %d; 
+	`
+	sql = fmt.Sprintf(sql, orderSql, (page-1)*perPage, perPage)
+	//beego.BeeLogger.Warn("sql=%s", sql)
+	_, err := orm.NewOrm().Raw(sql, 1, recommend, true, ptype).QueryRows(&products)
+
 	if err != nil {
 		beego.BeeLogger.Debug("GetLatest err=%s", err)
 	}
@@ -152,7 +193,8 @@ func GetLatestCount(recommend int64, ptype string, useCache bool) int64 {
 
 //根据商品Id,获取商品信息
 func GetProductById(id int64, useCache bool) *Product {
-	k := fmt.Sprintf("product_model.GetProductById[%d]", id)
+	//k := fmt.Sprintf("product_model.GetProductById[%d]", id)
+	k := cache.GetKey(cache.GetProductByPId, id)
 	if useCache {
 		if v, ok := cache.Cache.Get(k).(*Product); ok {
 			return v
@@ -168,37 +210,90 @@ func GetProductById(id int64, useCache bool) *Product {
 	return item
 }
 
-func GetProductsByCatId(cId, page, perPage int64, useCache bool) (products []*Product) {
-	k := fmt.Sprintf("product_model.GetProductsByCatId(%d).page(%d).perPage(%d)", cId, page, perPage)
+//判断商品是否在当前省可发货
+func GetProductByIdAndProvince(id int64, province string, useCache bool) *Product {
+	//k := fmt.Sprintf("product_model.GetProductById[%d]", id)
+	k := cache.GetKey(cache.GetProductByPIdAndProvince, id, province)
+	if useCache {
+		if v, ok := cache.Cache.Get(k).(*Product); ok {
+			return v
+		}
+	}
+	item := new(Product)
+	sql := `
+		select id from
+		products
+		where id = ? and find_in_set(?,only_delivery_area);
+		`
+	err := orm.NewOrm().Raw(sql, id, province).QueryRow(&item)
+	if err != nil {
+		beego.BeeLogger.Warn("product_model.GetProductByIdAndProvince(%d) err=%s", id, province, err)
+		return nil
+	}
+	cache.Cache.Put(k, item, 10*time.Minute)
+	return item
+}
+
+func GetProductsByCatId(cId, page, perPage, priceSort, saleSort int64, words string, useCache bool) (products []*Product) {
+	k := fmt.Sprintf("product_model.GetProductsByCatId(%d).page(%d).perPage(%d).words(%d)", cId, page, perPage, words)
 	if useCache {
 		if ret, ok := cache.Cache.Get(k).([]*Product); ok {
 			return ret
 		}
 	}
-	o := orm.NewOrm()
-	qs := o.QueryTable(new(Product)).Filter("status", 1).Filter("show_flag", true).Filter("ptype", TYPE_DIRECT_SALE)
-	if cId != 0 {
-		qs = qs.Filter("category_id", cId)
+	var priceSql, saleSql, orderSql string
+	if priceSort == int64(1) {
+		//降序
+		priceSql = "price desc"
+	} else if priceSort == int64(2) {
+		//升序
+		priceSql = "price asc"
+	}
+	if saleSort == int64(1) {
+		//降序
+		saleSql = "sale_nums desc"
+	} else if priceSort == int64(2) {
+		saleSql = "sale_nums asc"
+	}
+	if len(priceSql) <= 0 && len(saleSql) <= 0 {
+		orderSql = "recommend desc,created_at desc"
+	} else if len(priceSql) <= 0 {
+		orderSql = saleSql
+	} else if len(saleSql) <= 0 {
+		orderSql = priceSql
 	} else {
-		qs = qs.Exclude("category_id", 3) //3为审核类别,暂写死
+		orderSql = fmt.Sprintf("%s,%s", priceSql, saleSql)
+	}
+
+	var cidSql string
+	if cId != 0 {
+		cidSql = fmt.Sprintf("and category_id=%d", cId)
+	}
+
+	if len(words) > 0 {
+		cidSql = cidSql + fmt.Sprintf(" and key_words like '%s'", "%"+words+"%")
 	}
-	_, err := qs.
-		OrderBy("-recommend", "-created_at").
-		Limit(perPage, (page-1)*perPage).
-		All(&products)
+
+	sql := `
+		select * from products
+		where status = ? and show_flag=? and ptype=? %s
+		order by %s limit %d, %d ; 
+		`
+	sql = fmt.Sprintf(sql, cidSql, orderSql, (page-1)*perPage, perPage)
+	//beego.BeeLogger.Warn("cate sql=%s", sql)
+	_, err := orm.NewOrm().Raw(sql, 1, true, TYPE_DIRECT_SALE).QueryRows(&products)
+
 	if err != nil {
 		beego.BeeLogger.Debug("GetProductsByCatId err=%s", err)
 	}
 	for _, pd := range products {
 		pd.Cover = GetCoverByPId(pd.Id, useCache)
-		//TODO: 订单相关
-		// pd.SaleCount = pd.GetSaleCount()
 	}
 	cache.Cache.Put(k, products, 10*time.Minute)
 	return products
 }
 
-func GetProductCountByCatId(cId int64, useCache bool) int64 {
+func GetProductCountByCatId(cId int64, words string, useCache bool) int64 {
 	k := fmt.Sprintf("product_model.GetProductCountByCatId(%d)", cId)
 	if useCache {
 		if ret, ok := cache.Cache.Get(k).(int64); ok {
@@ -210,8 +305,9 @@ func GetProductCountByCatId(cId int64, useCache bool) int64 {
 	qs := o.QueryTable(item)
 	if cId != 0 {
 		qs = qs.Filter("category_id", cId)
-	} else {
-		qs = qs.Exclude("category_id", 3) //3为审核类别,暂写死
+	}
+	if len(words) > 0 {
+		qs = qs.Filter("key_words__icontains", words)
 	}
 	count, _ := qs.Filter("status", 1).Filter("show_flag", true).Filter("ptype", TYPE_DIRECT_SALE).Count()
 
@@ -368,3 +464,28 @@ func GetProductByIdAndColorId(relateId, colorId int64, useCache bool) *Product {
 	cache.Cache.Put(k, item, 5*time.Minute)
 	return item
 }
+
+//获取某主商品销售总量
+func GetProductCountByRelateId(relateId int64, useCache bool) int64 {
+	type Ret struct {
+		Count int64
+	}
+	ret := &Ret{}
+	k := fmt.Sprintf("product_model.GetProductCountByRelateId(%d)", relateId)
+	if useCache {
+		if ret, ok := cache.Cache.Get(k).(int64); ok {
+			return ret
+		}
+	}
+	o := orm.NewOrm()
+	sql := fmt.Sprintf("SELECT sum(`virtual_sold_count`+ `sale_nums`) as count FROM `products` WHERE  relate_product_id=%d;", relateId)
+	err := o.Raw(sql).QueryRow(ret)
+	if err != nil {
+		beego.BeeLogger.Error("GetSumBalancePerfomance err=[%s]", err)
+		return 0
+	}
+
+	cache.Cache.Put(k, ret.Count, 10*time.Minute)
+	return ret.Count
+
+}

+ 103 - 0
go/gopath/src/fohow.com/apps/models/product_model/product_commend.go

@@ -0,0 +1,103 @@
+package product_model
+
+import (
+	// "time"
+
+	"fmt"
+	"fohow.com/cache"
+	"github.com/astaxie/beego"
+	"github.com/astaxie/beego/orm"
+	"time"
+)
+
+const (
+	product_commends_tablename = "product_commends"
+)
+
+type ProductCommend struct {
+	Id         int64     `orm:"column(id);pk"          json:"id"`                             // int(11)
+	NickName   string    `orm:"-"                      json:"nick_name"`                      // varchar(20)
+	Head       string    `orm:"-"                      json:"head"`                           // varchar(20)
+	CreateTime int64     `orm:"-"                      json:"create_time"`                    // varchar(20)
+	WxUserId   int64     `orm:"column(wx_user_id);null" json:"-"`                             // int(11)
+	ProductId  int64     `orm:"column(product_id);null" json:"-"`                             // int(11)
+	OrderId    string    `orm:"column(order_id);"       json:"-"`                             // varchar(20)
+	Detail     string    `orm:"column(detail);"         json:"detail"`                        // varchar(20)
+	IsEnable   bool      `orm:"column(is_enable);null"  json:"-"`                             // tinyint(1)
+	IsTop      bool      `orm:"column(is_top);null"     json:"-"`                             // tinyint(1)
+	Score      int64     `orm:"column(score);null"      json:"score"`                         // int(11)
+	Recommend  int64     `orm:"column(recommend);null" json:"-"`                              // int(11)
+	CreatedAt  time.Time `orm:"column(created_at);null;auto_now_add;type(datetime)" json:"-"` // datetime
+	UpdatedAt  time.Time `orm:"column(updated_at);null;auto_now;type(datetime)"     json:"-"` // datetime
+}
+
+func (self *ProductCommend) TableName() string {
+	return product_commends_tablename
+}
+
+func (self *ProductCommend) Create(wxUId, pId, score int64, detail, orderId string) (item *ProductCommend) {
+	item = &ProductCommend{
+		ProductId: pId,
+		WxUserId:  wxUId,
+		Detail:    detail,
+		Score:     score,
+		OrderId:   orderId,
+		IsEnable:  true,
+	}
+	id, err := orm.NewOrm().Insert(item)
+	if err != nil {
+		beego.BeeLogger.Error("Create ProductCommend err=[%s]", err)
+		return nil
+	}
+	item.Id = id
+	return item
+}
+
+func GetProductCommendById(id int64) *ProductCommend {
+	cat := &ProductCommend{Id: id}
+	if err := orm.NewOrm().Read(cat); err != nil {
+		// beego.BeeLogger.Error("get name product cat by id err=[%s][", err)
+		return nil
+	}
+	return cat
+}
+
+//获取商品评论列表
+func GetProductCommends(productId int64, status, useCache bool, page, perPage int64) (commends []*ProductCommend) {
+	k := fmt.Sprintf("product_model.GetProductCommends(%d).page(%d).perPage(%d)", productId, page, perPage)
+	if useCache {
+		if ret, ok := cache.Cache.Get(k).([]*ProductCommend); ok {
+			return ret
+		}
+	}
+	commend := new(ProductCommend)
+	qs := orm.NewOrm().QueryTable(commend)
+	qs = qs.Filter("product_id", productId).Filter("is_enable", status)
+
+	if _, err := qs.OrderBy("-is_top", "-recommend", "-created_at").
+		Limit(perPage, (page-1)*perPage).All(&commends); err != nil {
+		beego.BeeLogger.Debug("get productCommeds[%d] commend list err=[%s]", productId, err)
+		return nil
+	}
+	cache.Cache.Put(k, commends, 10*time.Minute)
+
+	return commends
+}
+
+//获取商品评论列表总条数
+func GetProductCommendCountByProductId(productId int64, status, useCache bool) int64 {
+	k := fmt.Sprintf("product_model.GetProductCommendCountByProductId(%d)", productId)
+	if useCache {
+		if ret, ok := cache.Cache.Get(k).(int64); ok {
+			return ret
+		}
+	}
+	item := new(ProductCommend)
+	o := orm.NewOrm()
+	qs := o.QueryTable(item)
+
+	count, _ := qs.Filter("is_enable", status).Filter("product_id", productId).Count()
+
+	cache.Cache.Put(k, count, 10*time.Minute)
+	return count
+}

+ 46 - 0
go/gopath/src/fohow.com/apps/models/product_model/product_item.go

@@ -0,0 +1,46 @@
+package product_model
+
+import (
+	"fohow.com/cache"
+	"github.com/astaxie/beego"
+	"github.com/astaxie/beego/orm"
+	"time"
+)
+
+const (
+	product_items_tablename = "product_items"
+)
+
+type ProductItem struct {
+	Id        int64     `orm:"column(id);pk"                json:"id"`                  // int(11)
+	ProductId int64     `orm:"column(product_id)"           json:"product_id"`          // int(11)
+	Title     string    `orm:"column(title);null"           json:"-"`                   // varchar(64)
+	ItemId    int64     `orm:"column(item_id);null"         json:"item_id"`             // tinyint(1)
+	ItemTitle string    `orm:"column(item_title);null"      json:"item_title"`          // varchar(64)
+	Nums      int64     `orm:"column(nums);null"            json:"nums"`                // tinyint(1)
+	CreatedAt time.Time `orm:"column(created_at);auto_now_add;type(datetime)" json:"-"` // datetime
+	UpdatedAt time.Time `orm:"column(updated_at);auto_now;type(datetime)"     json:"-"` // datetime
+}
+
+func (self *ProductItem) TableName() string {
+	return product_items_tablename
+}
+
+// 根据商品Id找出商品对应套装明细
+func GetPackageList(pId int64, useCache bool) (items []*ProductItem) {
+	//k := fmt.Sprintf("product_model.GetPackageList(%d)", pId)
+	k := cache.GetKey(cache.GetProductPackagetByPId, pId)
+	if useCache {
+		if ret, ok := cache.Cache.Get(k).([]*ProductItem); ok {
+			return ret
+		}
+	}
+	o := orm.NewOrm()
+	_, err := o.QueryTable(new(ProductItem)).Filter("product_id", pId).OrderBy("id").All(&items)
+	if err != nil {
+		beego.BeeLogger.Debug("GetPackageList err=%s", err)
+	}
+
+	cache.Cache.Put(k, items, 10*time.Minute)
+	return items
+}

+ 9 - 0
go/gopath/src/fohow.com/apps/models/promotion_model/init.go

@@ -0,0 +1,9 @@
+package promotion_model
+
+import (
+	"github.com/astaxie/beego/orm"
+)
+
+func init() {
+	orm.RegisterModel(new(Promotion), new(ShopPromotion), new(BalancePromotion), new(Present))
+}

+ 19 - 10
go/gopath/src/fohow.com/apps/models/order_model/promotion.go

@@ -1,4 +1,4 @@
-package order_model
+package promotion_model
 
 import (
 	"fmt"
@@ -17,9 +17,10 @@ type Promotion struct {
 	Name      string    `orm:"column(name)"                            json:"name"` // varchar(64)
 	BeginTime time.Time `orm:"column(begin_time)"                      json:"-"`
 	EndTime   time.Time `orm:"column(end_time)"                        json:"-"`
-	IsEnable  bool      `orm:"column(is_enable)"                        json:"is_enable"`    // int(11)
-	IsFirst   bool      `orm:"column(is_first)"                        json:"is_first"`      // int(11)
+	IsEnable  bool      `orm:"column(is_enable)"                       json:"-"`             // int(11)
+	IsFirst   bool      `orm:"column(is_first)"                        json:"-"`             // int(11)
 	IsMore    bool      `orm:"column(is_more)"                         json:"-"`             // int(11)
+	Depart    int64     `orm:"column(depart)"                          json:"-"`             // int(11)
 	OrderType int64     `orm:"column(order_type)"                      json:"order_type"`    // varchar(64)
 	MinTotal  int64     `orm:"column(min_total)"                       json:"min_total"`     // int(11)
 	MaxTotal  int64     `orm:"column(max_total)"                       json:"-"`             // datetime
@@ -29,12 +30,20 @@ type Promotion struct {
 	Nums2     int64     `orm:"column(nums2)"                           json:"nums2"`         // int(11)
 	Prod3     int64     `orm:"column(prod3)"                           json:"prod3"`         // int(11)
 	Nums3     int64     `orm:"column(nums3)"                           json:"nums3"`         // int(11)
+	Prod4     int64     `orm:"column(prod4)"                           json:"-"`             // int(11)
+	Nums4     int64     `orm:"column(nums4)"                           json:"-"`             // int(11)
+	Prod5     int64     `orm:"column(prod5)"                           json:"-"`             // int(11)
+	Nums5     int64     `orm:"column(nums5)"                           json:"-"`             // int(11)
 	SendProd1 int64     `orm:"column(send_prod1)"                      json:"send_prod1"`    // int(11)
 	SendNums1 int64     `orm:"column(send_nums1)"                      json:"send_nums1"`    // int(11)
 	SendProd2 int64     `orm:"column(send_prod2)"                      json:"send_prod2"`    // int(11)
 	SendNums2 int64     `orm:"column(send_nums2)"                      json:"send_nums2"`    // int(11)
 	SendProd3 int64     `orm:"column(send_prod3)"                      json:"send_prod3"`    // int(11)
 	SendNums3 int64     `orm:"column(send_nums3)"                      json:"send_nums3"`    // int(11)
+	SendProd4 int64     `orm:"column(send_prod4)"                      json:"-"`             // int(11)
+	SendNums4 int64     `orm:"column(send_nums4)"                      json:"-"`             // int(11)
+	SendProd5 int64     `orm:"column(send_prod5)"                      json:"-"`             // int(11)
+	SendNums5 int64     `orm:"column(send_nums5)"                      json:"-"`             // int(11)
 	Cash      int64     `orm:"column(cash)"                            json:"cash"`          // int(11)
 	Cent      int64     `orm:"column(cent)"                            json:"cent"`          // int(11)
 	CreatedAt time.Time `orm:"column(created_at);null;auto_now_add;type(datetime)" json:"-"` // datetime
@@ -45,8 +54,8 @@ func (self *Promotion) TableName() string {
 	return promotions_tablename
 }
 
-func GetEffetivePromotions(queryDate time.Time, orderType int64, useCache bool) (list []*Promotion) {
-	k := fmt.Sprintf("product_model.GetEffetivePromotions(%s)", queryDate.Format("2006-01-02"))
+func GetEffetivePromotions(queryDate time.Time, orderType, depart int64, useCache bool) (list []*Promotion) {
+	k := fmt.Sprintf("promotion_model.GetEffetivePromotions(%s)", queryDate.Format("2006-01-02"))
 	if useCache {
 		if ret, ok := cache.Cache.Get(k).([]*Promotion); ok {
 			return ret
@@ -54,14 +63,14 @@ func GetEffetivePromotions(queryDate time.Time, orderType int64, useCache bool)
 	}
 
 	sql := `
-		select * from
-		promotions
-		where DATE_FORMAT(DATE_ADD(begin_time,INTERVAL 8 HOUR),'%Y-%m-%d') <= ? and DATE_FORMAT(DATE_ADD(end_time,INTERVAL 8 HOUR),'%Y-%m-%d') >= ? and order_type = ? and is_enable = 1 ;
+		select a.* from
+		promotions a left join depart_records_promotions b on a.id=b.promotion_id
+		where DATE_ADD(a.begin_time,INTERVAL 8 HOUR) <= ? and DATE_ADD(a.end_time,INTERVAL 8 HOUR) >= ? and a.order_type = ? and (b.depart_record_id=? or b.depart_record_id is null ) and a.is_enable = 1 ;
 		`
 
-	_, err := orm.NewOrm().Raw(sql, queryDate.Format("2006-01-02"), queryDate.Format("2006-01-02"), orderType).QueryRows(&list)
+	_, err := orm.NewOrm().Raw(sql, queryDate.Format("2006-01-02 15:04:05"), queryDate.Format("2006-01-02 15:04:05"), orderType, depart).QueryRows(&list)
 	if err != nil {
-		beego.BeeLogger.Warn("product_model.GetSeckillPromotions(%s) err=%s", queryDate.Format("2006-01-02"), err)
+		beego.BeeLogger.Warn("promotion_model.GetEffetivePromotions(%s) err=%s", queryDate.Format("2006-01-02"), err)
 		return nil
 	}
 

+ 87 - 0
go/gopath/src/fohow.com/apps/models/promotion_model/present.go

@@ -0,0 +1,87 @@
+package promotion_model
+
+import (
+	// "fmt"
+	"time"
+
+	"github.com/astaxie/beego"
+	"github.com/astaxie/beego/orm"
+)
+
+const (
+	SOURCE_BALANCE     = "balance"
+	SOURCE_SHOP        = "shop"
+	SOURCE_OTHERS      = "others"
+	presents_tablename = "presents"
+)
+
+var SOURCE_CN = map[string]string{
+	SOURCE_SHOP:    "店长促销发放",
+	SOURCE_BALANCE: "充值促销发放",
+	SOURCE_OTHERS:  "手工添加",
+}
+
+type Present struct {
+	Id           int64     `orm:"column(id);pk"                                       json:"id"`             // int(11)
+	WxUId        int64     `orm:"column(wx_user_id)"                                  json:"wx_user_id"`     // int(11)
+	Price        int64     `orm:"column(price)"                                        json:"price"`         // int(11)
+	Total        int64     `orm:"column(total)"                                        json:"total"`         // int(11)
+	SendProd     int64     `orm:"column(send_prod1)"                                  json:"send_prod1"`     // int(11)
+	SendNums     int64     `orm:"column(send_nums1)"                                  json:"send_nums1"`     // int(11)
+	OrderId      string    `orm:"column(order_id);null"                                     json:"order_id"` // varchar(32)
+	Source       string    `orm:"column(source);null"                                     json:"source"`     // varchar(32)
+	Remark       string    `orm:"column(remark);null"                                     json:"remark"`     // varchar(32)
+	Status       bool      `orm:"column(status)"                         json:"-"`                           // int(11)
+	SourceName   string    `orm:"-"                                                   json:"source_name"`    // varchar(255)
+	ProductName  string    `orm:"-"                                                   json:"product_name"`   // varchar(255)
+	ProductImage string    `orm:"-"                                                   json:"product_image"`  // varchar(255)
+	CreatedAt    time.Time `orm:"column(created_at);null;auto_now_add;type(datetime)" json:"created_at"`     // datetime
+	UpdatedAt    time.Time `orm:"column(updated_at);null;auto_now;type(datetime)"     json:"updated_at"`     // datetime
+}
+
+func (self *Present) TableName() string {
+	return presents_tablename
+}
+
+//创建点击统计项
+func (self *Present) CreatePresent(wxUId, price, total, prd, nums int64, source, remark string) *Present {
+	item := &Present{
+		WxUId:    wxUId,
+		Price:    price,
+		Total:    total,
+		SendProd: prd,
+		SendNums: nums,
+		Source:   source,
+		Status:   false,
+		Remark:   remark,
+	}
+	id, err := orm.NewOrm().Insert(item)
+	if err != nil {
+		beego.BeeLogger.Error("insert Present err=[%s]", err)
+		return nil
+	}
+	item.Id = id
+	return item
+}
+
+func (self *Present) Save() error {
+	if _, err := orm.NewOrm().Update(self); err != nil {
+		beego.BeeLogger.Error("Save Present id=[%d] .err=[%s]", self.Id, err)
+		return err
+	}
+	return nil
+}
+
+//获取所有未写入订单赠品
+func GetAllNoPatchPresents(wxUId int64) (presents []*Present) {
+	present := new(Present)
+	qs := orm.NewOrm().QueryTable(present)
+	qs = qs.Filter("wx_user_id", wxUId)
+	qs = qs.Filter("status", false)
+
+	if _, err := qs.OrderBy("-created_at").All(&presents); err != nil {
+		beego.BeeLogger.Debug("GetAllNoPatchPresents,  wxUId=[%d] order list err=[%s]", wxUId, err)
+		return nil
+	}
+	return presents
+}

+ 118 - 0
go/gopath/src/fohow.com/apps/models/promotion_model/promotion_model.go

@@ -0,0 +1,118 @@
+package promotion_model
+
+import (
+	// "strings"
+	"fmt"
+	"fohow.com/cache"
+	"github.com/astaxie/beego"
+	"github.com/astaxie/beego/orm"
+
+	"time"
+)
+
+const (
+	balance_promotions_tablename = "balance_promotions"
+	shop_promotions_tablename    = "shop_promotions"
+)
+
+type BalancePromotion struct {
+	Id        int64     `orm:"column(id);pk"                           json:"-"` // int(11)
+	Name      string    `orm:"column(name)"                            json:"-"` // varchar(64)
+	BeginTime time.Time `orm:"column(begin_time)"                      json:"-"`
+	EndTime   time.Time `orm:"column(end_time)"                        json:"-"`
+	IsEnable  bool      `orm:"column(is_enable)"                       json:"-"`             // int(11)
+	IsMore    bool      `orm:"column(is_more)"                         json:"-"`             // int(11)
+	Depart    int64     `orm:"column(depart)"                          json:"-"`             // varchar(64)
+	MinTotal  int64     `orm:"column(min_total)"                       json:"-"`             // int(11)
+	MaxTotal  int64     `orm:"column(max_total)"                       json:"-"`             // datetime
+	SendProd1 int64     `orm:"column(send_prod1)"                      json:"-"`             // int(11)
+	SendNums1 int64     `orm:"column(send_nums1)"                      json:"-"`             // int(11)
+	SendProd2 int64     `orm:"column(send_prod2)"                      json:"-"`             // int(11)
+	SendNums2 int64     `orm:"column(send_nums2)"                      json:"-"`             // int(11)
+	SendProd3 int64     `orm:"column(send_prod3)"                      json:"-"`             // int(11)
+	SendNums3 int64     `orm:"column(send_nums3)"                      json:"-"`             // int(11)
+	Cash      int64     `orm:"column(cash)"                            json:"-"`             // int(11)
+	Cent      int64     `orm:"column(cent)"                            json:"-"`             // int(11)
+	CreatedAt time.Time `orm:"column(created_at);null;auto_now_add;type(datetime)" json:"-"` // datetime
+	UpdatedAt time.Time `orm:"column(updated_at);null;auto_now;type(datetime)"     json:"-"` // datetime
+}
+
+type ShopPromotion struct {
+	Id        int64     `orm:"column(id);pk"                           json:"-"` // int(11)
+	Name      string    `orm:"column(name)"                            json:"-"` // varchar(64)
+	BeginTime time.Time `orm:"column(begin_time)"                      json:"-"`
+	EndTime   time.Time `orm:"column(end_time)"                        json:"-"`
+	IsEnable  bool      `orm:"column(is_enable)"                       json:"-"`             // int(11)
+	Depart    int64     `orm:"column(depart)"                          json:"-"`             // varchar(64)
+	Total     int64     `orm:"column(total)"                           json:"-"`             // int(11)
+	SendProd1 int64     `orm:"column(send_prod1)"                      json:"-"`             // int(11)
+	SendNums1 int64     `orm:"column(send_nums1)"                      json:"-"`             // int(11)
+	SendProd2 int64     `orm:"column(send_prod2)"                      json:"-"`             // int(11)
+	SendNums2 int64     `orm:"column(send_nums2)"                      json:"-"`             // int(11)
+	SendProd3 int64     `orm:"column(send_prod3)"                      json:"-"`             // int(11)
+	SendNums3 int64     `orm:"column(send_nums3)"                      json:"-"`             // int(11)
+	SendProd4 int64     `orm:"column(send_prod4)"                      json:"-"`             // int(11)
+	SendNums4 int64     `orm:"column(send_nums4)"                      json:"-"`             // int(11)
+	SendProd5 int64     `orm:"column(send_prod5)"                      json:"-"`             // int(11)
+	SendNums5 int64     `orm:"column(send_nums5)"                      json:"-"`             // int(11)
+	Cash      int64     `orm:"column(cash)"                            json:"-"`             // int(11)
+	Cent      int64     `orm:"column(cent)"                            json:"-"`             // int(11)
+	CreatedAt time.Time `orm:"column(created_at);null;auto_now_add;type(datetime)" json:"-"` // datetime
+	UpdatedAt time.Time `orm:"column(updated_at);null;auto_now;type(datetime)"     json:"-"` // datetime
+}
+
+func (self *ShopPromotion) TableName() string {
+	return shop_promotions_tablename
+}
+
+func (self *BalancePromotion) TableName() string {
+	return balance_promotions_tablename
+}
+
+func GetBalanceEffetivePromotions(queryDate time.Time, depart int64, useCache bool) (list []*BalancePromotion) {
+	k := fmt.Sprintf("promotion_model.GetBalanceEffetivePromotions(%s)", queryDate.Format("2006-01-02"))
+	if useCache {
+		if ret, ok := cache.Cache.Get(k).([]*BalancePromotion); ok {
+			return ret
+		}
+	}
+
+	sql := `
+		select a.* from
+		balance_promotions  a left join depart_records_balance_promotions b on a.id=b.balance_promotion_id
+		where DATE_ADD(a.begin_time,INTERVAL 8 HOUR) <= ? and DATE_ADD(a.end_time,INTERVAL 8 HOUR) >= ? and b.depart_record_id = ? and a.is_enable = 1 ;
+		`
+
+	_, err := orm.NewOrm().Raw(sql, queryDate.Format("2006-01-02 15:04:05"), queryDate.Format("2006-01-02 15:04:05"), depart).QueryRows(&list)
+	if err != nil {
+		beego.BeeLogger.Warn("promotion_model.GetBalanceEffetivePromotions(%s) err=%s", queryDate.Format("2006-01-02"), err)
+		return nil
+	}
+
+	cache.Cache.Put(k, list, 10*time.Minute)
+	return list
+}
+
+func GetShopEffetivePromotions(queryDate time.Time, depart int64, useCache bool) (list []*ShopPromotion) {
+	k := fmt.Sprintf("promotion_model.GetShopEffetivePromotions(%s)", queryDate.Format("2006-01-02"))
+	if useCache {
+		if ret, ok := cache.Cache.Get(k).([]*ShopPromotion); ok {
+			return ret
+		}
+	}
+
+	sql := `
+		select a.* from
+		shop_promotions a left join depart_records_shop_promotions b on a.id=b.shop_promotion_id
+		where DATE_ADD(a.begin_time,INTERVAL 8 HOUR) <= ? and DATE_ADD(a.end_time,INTERVAL 8 HOUR) >= ? and b.depart_record_id = ?  and is_enable = 1 ;
+		`
+
+	_, err := orm.NewOrm().Raw(sql, queryDate.Format("2006-01-02 15:04:05"), queryDate.Format("2006-01-02 15:04:05"), depart).QueryRows(&list)
+	if err != nil {
+		beego.BeeLogger.Warn("promotion_model.GetShopEffetivePromotions(%s) err=%s", queryDate.Format("2006-01-02"), err)
+		return nil
+	}
+
+	cache.Cache.Put(k, list, 10*time.Minute)
+	return list
+}

+ 1 - 1
go/gopath/src/fohow.com/apps/models/sms_model/sms.go

@@ -27,7 +27,7 @@ const (
 )
 
 func GetAliMsgContent(msg_type string) (string, string, string) {
-	sign := "凤凰玖玖"
+	sign := "凤凰菁选商城"
 	action := ""
 	template := ""
 	switch msg_type {

+ 10 - 0
go/gopath/src/fohow.com/apps/models/sys_config/init.go

@@ -0,0 +1,10 @@
+package sys_config
+
+import "github.com/astaxie/beego/orm"
+
+func init() {
+	orm.RegisterModel(
+		new(SysConfig),
+		new(PayConfig),
+	)
+}

+ 286 - 0
go/gopath/src/fohow.com/apps/models/sys_config/sys_config.go

@@ -0,0 +1,286 @@
+package sys_config
+
+import (
+	"fmt"
+	"fohow.com/apps/helper"
+	"fohow.com/cache"
+	"github.com/astaxie/beego"
+	"github.com/astaxie/beego/orm"
+	"strconv"
+	"time"
+)
+
+const (
+	CODE_BUY_CASH         = "BUY_CASH"
+	CODE_SEND_CASH        = "SEND_CASH"
+	CODE_CASH_AWARD       = "CASH_AWARD"
+	CODE_FREIGHT_LIMIT    = "FREIGHT_LIMIT"
+	CODE_FREIGHT          = "FREIGHT"
+	CODE_USER_SHOP_APPLY  = "USER_SHOP_APPLY"
+	CODE_USER_APPLY_RET   = "USER_APPLY_RET"
+	CODE_USER_APPLY_QUAN  = "USER_APPLY_QUAN"
+	CODE_AGENT_SHOP_APPLY = "AGENT_SHOP_APPLY"
+	CODE_AGENT_APPLY_RET  = "AGENT_APPLY_RET"
+	CODE_AGENT_APPLY_QUAN = "AGENT_APPLY_QUAN"
+	SPECIAL_PROMOTION     = "SPECIAL_PROMOTION"
+	SHUT_WECHAT           = "SHUT_WECHAT"
+	CODE_FOHOW_OUBIAO     = "oubiao"
+	CODE_FOHOW            = "fohow"
+	sys_configs_tablename = "sys_configs"
+	pay_configs_tablename = "pay_configs"
+)
+
+type SysConfig struct {
+	Id        int64     `orm:"column(id);pk"                              json:"id"`         // int(11)
+	Code      string    `orm:"column(code);null"                          json:"-"`          // varchar(64)
+	CodeType  int64     `orm:"column(config_type)"                        json:"-"`          // int(11)
+	CodeValue string    `orm:"column(code_value);null"                    json:"-"`          // varchar(64)
+	DepartId  int64     `orm:"column(depart_record_id)"                   json:"-"`          // int(11)
+	Sort      int64     `orm:"column(sort)"                               json:"-"`          // int(11)
+	CreatedAt time.Time `orm:"column(created_at);null;auto_now_add;type(datetime)" json:"-"` // datetime
+	UpdatedAt time.Time `orm:"column(updated_at);null;auto_now;type(datetime)"     json:"-"` // datetime
+}
+
+func (self *SysConfig) TableName() string {
+	return sys_configs_tablename
+}
+
+type PayConfig struct {
+	Id        int64     `orm:"column(id);pk"                                        json:"id"` // int(11)
+	PayCode   string    `orm:"column(pay_code)"                                    json:"-"`
+	Depart    int64     `orm:"column(depart)"                                      json:"-"`                     // int(11)
+	CreatedAt time.Time `orm:"column(created_at);null;auto_now_add;type(datetime)"  json:"created_at,omitempty"` // datetime
+	UpdatedAt time.Time `orm:"column(updated_at);null;auto_now;type(datetime)"      json:"updated_at,omitempty"` // datetime
+}
+
+func (self *PayConfig) TableName() string {
+	return pay_configs_tablename
+}
+
+// 获取购券支付金额
+func GetBuyCash() int64 {
+	SysConfig := &SysConfig{}
+	if err := orm.NewOrm().QueryTable(SysConfig).Filter("code", CODE_BUY_CASH).Limit(1).One(SysConfig); err != nil {
+		beego.BeeLogger.Error("get SysConfig by  err=%s", err)
+		SysConfig = nil
+		return int64(0)
+	}
+	value, err := strconv.ParseInt(SysConfig.CodeValue, 10, 64)
+	if err != nil {
+		return int64(0)
+	}
+	return value
+}
+
+// 购券实得金额
+func GetSendCash() int64 {
+	SysConfig := &SysConfig{}
+	if err := orm.NewOrm().QueryTable(SysConfig).Filter("code", CODE_SEND_CASH).Limit(1).One(SysConfig); err != nil {
+		beego.BeeLogger.Error("get SysConfig by  err=%s", err)
+		SysConfig = nil
+		return int64(0)
+	}
+	value, err := strconv.ParseInt(SysConfig.CodeValue, 10, 64)
+	if err != nil {
+		return int64(0)
+	}
+	return value
+}
+
+// 获取购券返佣
+func GetCashAward() int64 {
+	SysConfig := &SysConfig{}
+	if err := orm.NewOrm().QueryTable(SysConfig).Filter("code", CODE_CASH_AWARD).Limit(1).One(SysConfig); err != nil {
+		beego.BeeLogger.Error("get SysConfig by  err=%s", err)
+		SysConfig = nil
+		return int64(0)
+	}
+	value, err := strconv.ParseInt(SysConfig.CodeValue, 10, 64)
+	if err != nil {
+		return int64(0)
+	}
+	return value
+}
+
+// 订单免运金额
+func GetOrderLimit() int64 {
+	SysConfig := &SysConfig{}
+	if err := orm.NewOrm().QueryTable(SysConfig).Filter("code", CODE_FREIGHT_LIMIT).Limit(1).One(SysConfig); err != nil {
+		beego.BeeLogger.Error("get SysConfig by  err=%s", err)
+		SysConfig = nil
+		return int64(0)
+	}
+	value, err := strconv.ParseInt(SysConfig.CodeValue, 10, 64)
+	if err != nil {
+		return int64(0)
+	}
+	return value
+}
+
+// 获取运费金额
+func GetFreight() int64 {
+	SysConfig := &SysConfig{}
+	if err := orm.NewOrm().QueryTable(SysConfig).Filter("code", CODE_FREIGHT).Limit(1).One(SysConfig); err != nil {
+		beego.BeeLogger.Error("get SysConfig by  err=%s", err)
+		SysConfig = nil
+		return int64(0)
+	}
+	value, err := strconv.ParseInt(SysConfig.CodeValue, 10, 64)
+	if err != nil {
+		return int64(0)
+	}
+	return value
+}
+
+// 会员申店金额
+func GetUserApply() int64 {
+	SysConfig := &SysConfig{}
+	if err := orm.NewOrm().QueryTable(SysConfig).Filter("code", CODE_USER_SHOP_APPLY).Limit(1).One(SysConfig); err != nil {
+		beego.BeeLogger.Error("get SysConfig by  err=%s", err)
+		SysConfig = nil
+		return int64(0)
+	}
+	value, err := strconv.ParseInt(SysConfig.CodeValue, 10, 64)
+	if err != nil {
+		return int64(0)
+	}
+	return value
+}
+
+// 会员申店反券
+func GetUserCash() int64 {
+	SysConfig := &SysConfig{}
+	if err := orm.NewOrm().QueryTable(SysConfig).Filter("code", CODE_USER_APPLY_QUAN).Limit(1).One(SysConfig); err != nil {
+		beego.BeeLogger.Error("get SysConfig by  err=%s", err)
+		SysConfig = nil
+		return int64(0)
+	}
+	value, err := strconv.ParseInt(SysConfig.CodeValue, 10, 64)
+	if err != nil {
+		return int64(0)
+	}
+	return value
+}
+
+// 会员申店返佣
+func GetUserAward() int64 {
+	SysConfig := &SysConfig{}
+	if err := orm.NewOrm().QueryTable(SysConfig).Filter("code", CODE_USER_APPLY_RET).Limit(1).One(SysConfig); err != nil {
+		beego.BeeLogger.Error("get SysConfig by  err=%s", err)
+		SysConfig = nil
+		return int64(0)
+	}
+	value, err := strconv.ParseInt(SysConfig.CodeValue, 10, 64)
+	if err != nil {
+		return int64(0)
+	}
+	return value
+}
+
+// 代理申店金额
+func GetAgentApply() int64 {
+	SysConfig := &SysConfig{}
+	if err := orm.NewOrm().QueryTable(SysConfig).Filter("code", CODE_AGENT_SHOP_APPLY).Limit(1).One(SysConfig); err != nil {
+		beego.BeeLogger.Error("get SysConfig by  err=%s", err)
+		SysConfig = nil
+		return int64(0)
+	}
+	value, err := strconv.ParseInt(SysConfig.CodeValue, 10, 64)
+	if err != nil {
+		return int64(0)
+	}
+	return value
+}
+
+// 代理申店反券
+func GetAgentCash() int64 {
+	SysConfig := &SysConfig{}
+	if err := orm.NewOrm().QueryTable(SysConfig).Filter("code", CODE_AGENT_APPLY_QUAN).Limit(1).One(SysConfig); err != nil {
+		beego.BeeLogger.Error("get SysConfig by  err=%s", err)
+		SysConfig = nil
+		return int64(0)
+	}
+	value, err := strconv.ParseInt(SysConfig.CodeValue, 10, 64)
+	if err != nil {
+		return int64(0)
+	}
+	return value
+}
+
+// 代理申店返佣
+func GetAgentAward() int64 {
+	SysConfig := &SysConfig{}
+	if err := orm.NewOrm().QueryTable(SysConfig).Filter("code", CODE_AGENT_APPLY_RET).Limit(1).One(SysConfig); err != nil {
+		beego.BeeLogger.Error("get SysConfig by  err=%s", err)
+		return int64(0)
+	}
+	value, err := strconv.ParseInt(SysConfig.CodeValue, 10, 64)
+	if err != nil {
+		return int64(0)
+	}
+	return value
+}
+
+//根据部门获取收款商户
+func GetPayConfigByDepart(depart int64, useCache bool) string {
+	k := fmt.Sprintf("pay_model.GetPayConfigByDepart.depart(%d)", depart)
+	if useCache {
+		if s, ok := cache.Cache.Get(k).(*PayConfig); ok {
+			return s.PayCode
+		}
+	}
+
+	item := new(PayConfig)
+	o := orm.NewOrm()
+	err := o.QueryTable(item).Filter("depart", depart).OrderBy("-id").Limit(1).One(item)
+	if err != nil {
+		beego.BeeLogger.Info("pay_model.GetPayConfigByDepart.depart(%d) err[%s]", depart, err)
+		return CODE_FOHOW_OUBIAO
+	}
+
+	if item != nil {
+		cache.Cache.Put(k, item, 5*time.Minute)
+	}
+	return item.PayCode
+}
+
+//获取特殊促销时间段配置
+func GetSpetialPromotion() (bool, string) {
+	sysConfig := SysConfig{}
+	if err := orm.NewOrm().QueryTable(sysConfig).Filter("code", SPECIAL_PROMOTION).Limit(1).One(&sysConfig); err != nil {
+		beego.BeeLogger.Error("get sysConfig by  err=%s", err)
+		return false, ""
+	}
+	promotionArr := helper.NewStr(sysConfig.CodeValue).Explode("_")
+
+	if len(promotionArr) == 2 {
+		beginTime := helper.NewStr(promotionArr[0]).ToInt64()
+		endTime := helper.NewStr(promotionArr[1]).ToInt64()
+		nowTime := time.Now().Unix()
+		if nowTime >= beginTime && nowTime <= endTime {
+			beego.BeeLogger.Warn("promotionArr2----%v", promotionArr)
+			return true, sysConfig.Code
+		}
+	}
+	return false, ""
+}
+
+//关闭微信支付时间段
+func GetShutWechatPromotion() bool {
+	sysConfig := SysConfig{}
+	if err := orm.NewOrm().QueryTable(sysConfig).Filter("code", SHUT_WECHAT).Limit(1).One(&sysConfig); err != nil {
+		beego.BeeLogger.Error("get sysConfig by  err=%s", err)
+		return false
+	}
+	promotionArr := helper.NewStr(sysConfig.CodeValue).Explode("_")
+	if len(promotionArr) == 2 {
+		beginTime := helper.NewStr(promotionArr[0]).ToInt64()
+		endTime := helper.NewStr(promotionArr[1]).ToInt64()
+		nowTime := time.Now().Unix()
+		if nowTime >= beginTime && nowTime <= endTime {
+			beego.BeeLogger.Warn("GetShutWechatPromotion----%v", promotionArr)
+			return true
+		}
+	}
+	return false
+}

+ 0 - 0
go/gopath/src/fohow.com/apps/models/token_model/init.go


Some files were not shown because too many files changed in this diff