zjxpcyc 6 년 전
부모
커밋
cc2f2eeeb4
9개의 변경된 파일433개의 추가작업 그리고 33개의 파일을 삭제
  1. 82
    0
      controllers/customer/customer.go
  2. 42
    0
      controllers/message.go
  3. 0
    15
      controllers/sms.go
  4. 66
    15
      models/customer/customer.go
  5. 1
    0
      models/customer/types.go
  6. 94
    3
      service/customer/customer.go
  7. 16
    0
      service/customer/types.go
  8. 61
    0
      utils/pagenavi.go
  9. 71
    0
      utils/pagenavi_test.go

+ 82
- 0
controllers/customer/customer.go 파일 보기

@@ -0,0 +1,82 @@
1
+package customer
2
+
3
+import (
4
+	"errors"
5
+	"net/http"
6
+	"spaceofcheng/services/controllers"
7
+	"spaceofcheng/services/models"
8
+	"spaceofcheng/services/models/model"
9
+	"spaceofcheng/services/service/customer"
10
+	"spaceofcheng/services/utils"
11
+)
12
+
13
+// CustomerController 用户
14
+type CustomerController struct {
15
+	serv *customer.CustomerServ
16
+	controllers.BaseController
17
+}
18
+
19
+// Constructor 初始化 Controller
20
+// @Title Constructor
21
+// @Description 初始化 Controller, 系统自动调用
22
+func (c *CustomerController) Constructor() {
23
+	c.serv = customer.NewCustomerServ(c.Context)
24
+}
25
+
26
+// CustWXList 获取客户列表
27
+func (c *CustomerController) CustWXList() {
28
+	phone := c.GetString("phone")
29
+	page, _ := c.GetInt("page")
30
+
31
+	custList, total, err := c.serv.GetCustWithWXList(phone, page)
32
+	if err != nil {
33
+		utils.LogError("获取客户列表失败: " + err.Error())
34
+		c.ResponseError(
35
+			errors.New("获取客户列表失败"),
36
+			http.StatusInternalServerError,
37
+		)
38
+	}
39
+
40
+	c.ResponseJSON(map[string]interface{}{
41
+		"list":  custList,
42
+		"total": total,
43
+	})
44
+}
45
+
46
+// GetCustOrUserByID 获取用户信息
47
+func (c *CustomerController) GetCustOrUserByID() {
48
+	userMapRaw := c.Context.Get("userMap")
49
+	if userMapRaw == nil {
50
+		c.ResponseError(errors.New("获取用户信息失败, 请确认使用微信浏览"))
51
+	}
52
+
53
+	userMap := userMapRaw.(model.TaUserMapping)
54
+
55
+	if userMap.UserType == models.USERMAP_USER {
56
+		// 如果是用户
57
+		userID := userMap.UserId
58
+		user, err := c.serv.GetCustUserByID(userID)
59
+		if err != nil {
60
+			utils.LogError(err)
61
+			c.ResponseError(errors.New("获取用户信息失败, 请重试"))
62
+		}
63
+
64
+		c.ResponseJSON(map[string]interface{}{
65
+			"user":     user,
66
+			"userType": userMap.UserType,
67
+		})
68
+	} else {
69
+		// 如果是客户
70
+		custID := userMap.UserId
71
+		cust, err := c.serv.GetCustWithWXByID(custID)
72
+		if err != nil {
73
+			utils.LogError(err)
74
+			c.ResponseError(errors.New("获取用户信息失败, 请重试"))
75
+		}
76
+
77
+		c.ResponseJSON(map[string]interface{}{
78
+			"customer": cust,
79
+			"userType": userMap.UserType,
80
+		})
81
+	}
82
+}

+ 42
- 0
controllers/message.go 파일 보기

@@ -0,0 +1,42 @@
1
+package controllers
2
+
3
+import (
4
+	"errors"
5
+	"spaceofcheng/services/utils"
6
+)
7
+
8
+// SendCaptcha 发送验证码
9
+func (c *BaseController) SendCaptcha() {
10
+	phone := c.GetString("phone")
11
+
12
+	if phone == "" {
13
+		c.ResponseError(errors.New("请确定手机号码"))
14
+	}
15
+
16
+	if err := utils.SendCaptcha(phone); err != nil {
17
+		utils.LogError(err)
18
+		c.ResponseError(errors.New("验证码发送失败, 请重试"))
19
+	}
20
+
21
+	c.ResponseJSON("ok")
22
+}
23
+
24
+// ValidCaptcha 发送验证码
25
+func (c *BaseController) ValidCaptcha() {
26
+	phone := c.GetString("phone")
27
+
28
+	if phone == "" {
29
+		c.ResponseError(errors.New("请确定手机号码"))
30
+	}
31
+
32
+	captcha := c.GetString("captcha")
33
+	if captcha == "" {
34
+		c.ResponseError(errors.New("验证码不能为空"))
35
+	}
36
+
37
+	if err := utils.ValidCaptcha(phone, captcha); err != nil {
38
+		c.ResponseError(err)
39
+	}
40
+
41
+	c.ResponseJSON("ok")
42
+}

+ 0
- 15
controllers/sms.go 파일 보기

@@ -1,15 +0,0 @@
1
-package controllers
2
-
3
-import (
4
-	"errors"
5
-)
6
-
7
-// SendSMS 发送短信
8
-func (c *BaseController) SendSMS() {
9
-	phone := c.GetString("phone")
10
-
11
-	if phone == "" {
12
-		c.ResponseError(errors.New("请确定手机号码"))
13
-	}
14
-
15
-}

+ 66
- 15
models/customer/customer.go 파일 보기

@@ -5,6 +5,9 @@ import (
5 5
 	"spaceofcheng/services/models"
6 6
 	"spaceofcheng/services/models/model"
7 7
 	"spaceofcheng/services/utils"
8
+	"time"
9
+
10
+	"github.com/yl10/kit/guid"
8 11
 
9 12
 	"github.com/go-xorm/xorm"
10 13
 )
@@ -24,7 +27,7 @@ func NewCustomerDAO(ctx *utils.Context) *CustomerDAO {
24 27
 }
25 28
 
26 29
 // CustWithWXList 客户列表
27
-func (m *CustomerDAO) CustWithWXList(phone string, page ...int) ([]CustWithWX, error) {
30
+func (m *CustomerDAO) CustWithWXList(phone string, page ...int) ([]CustWithWX, int64, error) {
28 31
 	if phone == "" {
29 32
 		phone = "%"
30 33
 	} else {
@@ -57,21 +60,16 @@ func (m *CustomerDAO) CustWithWXList(phone string, page ...int) ([]CustWithWX, e
57 60
 		AND t.status > ?
58 61
 		ORDER BY
59 62
 			t.create_date DESC
60
-		LIMIT ? OFFSET ?	
61 63
 	`
62 64
 
63 65
 	var cust []CustWithWX
64
-	if err := m.db.SQL(
65
-		query,
66
-		phone,
67
-		models.STATUS_DEL,
68
-		pageNum,
69
-		offset,
70
-	).Find(&cust); err != nil {
71
-		return nil, err
66
+
67
+	cnt, err := utils.GetPageList(m.db, &cust, []int{pageNum, offset}, query, phone, models.STATUS_DEL)
68
+	if err != nil {
69
+		return nil, 0, err
72 70
 	}
73 71
 
74
-	return cust, nil
72
+	return cust, cnt, nil
75 73
 }
76 74
 
77 75
 // GetCustWithWXByID 获取客户(微信)信息
@@ -101,17 +99,22 @@ func (m *CustomerDAO) GetCustWithWXByID(custID string) (*CustWithWX, error) {
101 99
 
102 100
 // GetCustomerByPhone 依据手机号获取客户信息
103 101
 func (m *CustomerDAO) GetCustomerByPhone(phone string) (*model.TaCustomer, error) {
104
-	cust := model.TaCustomer{}
102
+	custs := []model.TaCustomer{}
105 103
 
106
-	has, err := m.db.Where("phone=?", phone).Get(&cust)
107
-	if err != nil {
104
+	if err := m.db.Where("phone=?", phone).Find(&custs); err != nil {
108 105
 		return nil, err
109 106
 	}
110 107
 
111
-	if !has {
108
+	if len(custs) == 0 {
112 109
 		return nil, nil
113 110
 	}
114 111
 
112
+	if len(custs) > 0 {
113
+		return nil, errors.New("数据异常, 一个手机绑定了多个用户")
114
+	}
115
+
116
+	cust := custs[0]
117
+
115 118
 	return &cust, nil
116 119
 }
117 120
 
@@ -124,3 +127,51 @@ func (m *CustomerDAO) UpdateUserMapping(userMap *model.TaUserMapping, cols []str
124 127
 	_, err := m.db.Where("mapping_id=?", userMap.MappingId).Cols(cols...).Update(&userMap)
125 128
 	return err
126 129
 }
130
+
131
+// GetCaseByID 获取案场
132
+func (m *CustomerDAO) GetCaseByID(caseID string) (*model.SysCase, error) {
133
+	if caseID == "" {
134
+		return nil, errors.New("获取案场信息失败")
135
+	}
136
+
137
+	cs := model.SysCase{}
138
+	has, err := m.db.Where("case_id=?", caseID).Get(&cs)
139
+	if err != nil {
140
+		return nil, err
141
+	}
142
+
143
+	if !has {
144
+		return nil, nil
145
+	}
146
+
147
+	return &cs, nil
148
+}
149
+
150
+// GetUserByID 获取系统用户
151
+func (m *CustomerDAO) GetUserByID(userID string) (*model.SysUser, error) {
152
+	if userID == "" {
153
+		return nil, errors.New("获取相关人员信息失败")
154
+	}
155
+
156
+	user := model.SysUser{}
157
+	has, err := m.db.Where("user_id=?", userID).Get(&user)
158
+	if err != nil {
159
+		return nil, err
160
+	}
161
+
162
+	if !has {
163
+		return nil, nil
164
+	}
165
+
166
+	return &user, nil
167
+}
168
+
169
+// SaveCustomer 新增客户
170
+func (m *CustomerDAO) SaveCustomer(cust *model.TaCustomer) error {
171
+	cust.CustomerId = guid.NewGUIDString()
172
+	cust.CreateDate = time.Now().Local()
173
+	cust.Status = models.STATUS_NORMAL
174
+
175
+	_, err := m.db.Insert(&cust)
176
+	return err
177
+}

+ 1
- 0
models/customer/types.go 파일 보기

@@ -8,4 +8,5 @@ import (
8 8
 type CustWithWX struct {
9 9
 	model.TaCustomer    `xorm:"extends"`
10 10
 	model.TaUserMapping `xorm:"extends"`
11
+	Points              int
11 12
 }

+ 94
- 3
service/customer/customer.go 파일 보기

@@ -1,12 +1,14 @@
1 1
 package customer
2 2
 
3 3
 import (
4
+	"encoding/json"
4 5
 	"errors"
5 6
 	"spaceofcheng/services/models"
6 7
 	"spaceofcheng/services/models/customer"
7 8
 	"spaceofcheng/services/models/model"
8 9
 	"spaceofcheng/services/service/events"
9 10
 	"spaceofcheng/services/utils"
11
+	"strconv"
10 12
 )
11 13
 
12 14
 // CustomerServ 系统处理
@@ -24,7 +26,7 @@ func NewCustomerServ(ctx *utils.Context) *CustomerServ {
24 26
 }
25 27
 
26 28
 // GetCustWithWXList 获取客户列表
27
-func (s *CustomerServ) GetCustWithWXList(phone string, page ...int) ([]customer.CustWithWX, error) {
29
+func (s *CustomerServ) GetCustWithWXList(phone string, page ...int) ([]customer.CustWithWX, int64, error) {
28 30
 	return s.dao.CustWithWXList(phone, page...)
29 31
 }
30 32
 
@@ -42,15 +44,46 @@ func (s *CustomerServ) GetCustWithWXByID(custID string) (*customer.CustWithWX, e
42 44
 	return cust, nil
43 45
 }
44 46
 
47
+// GetCustUserByID 获取用户信息(自定义内容)
48
+func (s *CustomerServ) GetCustUserByID(userID string) (*UserProfile, error) {
49
+	user, err := s.dao.GetUserByID(userID)
50
+	if err != nil {
51
+		return nil, err
52
+	}
53
+
54
+	if user.Status != models.STATUS_NORMAL {
55
+		return nil, errors.New("用户状态异常")
56
+	}
57
+
58
+	userProfile := UserProfile{
59
+		UserId:     user.UserId,
60
+		UserName:   user.UserName,
61
+		RealName:   user.RealName,
62
+		Sex:        user.Sex,
63
+		WorkNo:     user.WorkNo,
64
+		Email:      user.Email,
65
+		Phone:      user.Phone,
66
+		Headimgurl: user.Headimgurl,
67
+	}
68
+
69
+	return &userProfile, nil
70
+}
71
+
45 72
 // BindWechat 绑定微信用户
46
-func (s *CustomerServ) BindWechat(userMap *model.TaUserMapping, phone string) (*models.TaCustomer, error) {
73
+func (s *CustomerServ) BindWechat(userMap *model.TaUserMapping, phone, caseID, userID string) (*model.TaCustomer, error) {
47 74
 	cust, err := s.dao.GetCustomerByPhone(phone)
48 75
 	if err != nil {
49 76
 		return nil, err
50 77
 	}
51 78
 
79
+	// 用户不存在, 则新增
52 80
 	if cust == nil {
53
-		return nil, errors.New("手机号对应用户不存在")
81
+		newCust, err := s.SaveNewCustomer(phone, caseID, userID)
82
+		if err != nil {
83
+			return nil, err
84
+		}
85
+
86
+		cust = newCust
54 87
 	}
55 88
 
56 89
 	if cust.Status != models.STATUS_NORMAL {
@@ -76,3 +109,61 @@ func (s *CustomerServ) BindWechat(userMap *model.TaUserMapping, phone string) (*
76 109
 
77 110
 	return cust, nil
78 111
 }
112
+
113
+// SaveNewCustomer 新增客户
114
+func (s *CustomerServ) SaveNewCustomer(phone, caseID, userID string) (*model.TaCustomer, error) {
115
+	// 校验案场信息
116
+	cs, err := s.dao.GetCaseByID(caseID)
117
+	if err != nil {
118
+		return nil, err
119
+	}
120
+
121
+	if cs == nil || cs.Status == models.STATUS_DEL {
122
+		return nil, errors.New("系统无该推荐案场")
123
+	}
124
+
125
+	// 校验推荐人
126
+	user, err := s.dao.GetUserByID(userID)
127
+	if err != nil {
128
+		return nil, err
129
+	}
130
+
131
+	if user == nil || user.Status == models.STATUS_DEL {
132
+		return nil, errors.New("系统无该推荐人")
133
+	}
134
+
135
+	// 微信信息
136
+	userMap := s.ctx.Get("userMap").(model.TaUserMapping)
137
+	wxInfo := make(map[string]interface{})
138
+	if err := json.Unmarshal([]byte(userMap.AccountInfo), &wxInfo); err != nil {
139
+		utils.LogError(err.Error())
140
+		return nil, errors.New("校验用户微信信息失败")
141
+	}
142
+
143
+	nickyName := wxInfo["nickname"].(string)
144
+	sex := wxInfo["sex"].(string)
145
+	headimgurl := wxInfo["headimgurl"].(string)
146
+
147
+	sexInt, _ := strconv.Atoi(sex)
148
+	if sexInt == 0 {
149
+		sexInt = 1 // 默认男性
150
+	}
151
+
152
+	cust := model.TaCustomer{
153
+		OrgId:         cs.OrgId,
154
+		CustomerName:  nickyName,
155
+		Name:          nickyName,
156
+		Sex:           sexInt,
157
+		Headimgurl:    headimgurl,
158
+		RecommendId:   user.UserId,
159
+		RecommendName: user.RealName,
160
+		RecommendCase: cs.CaseId,
161
+	}
162
+
163
+	if err := s.dao.SaveCustomer(&cust); err != nil {
164
+		utils.LogError("更新客户信息失败: " + err.Error())
165
+		return nil, errors.New("更新客户信息失败")
166
+	}
167
+
168
+	return &cust, nil
169
+}

+ 16
- 0
service/customer/types.go 파일 보기

@@ -0,0 +1,16 @@
1
+package customer
2
+
3
+type UserProfile struct {
4
+	UserId     string
5
+	UserName   string
6
+	RealName   string
7
+	Sex        int
8
+	WorkNo     string
9
+	Email      string
10
+	Phone      string
11
+	Headimgurl string
12
+}
13
+
14
+func (t *UserProfile) TableName() string {
15
+	return "sys_user"
16
+}

+ 61
- 0
utils/pagenavi.go 파일 보기

@@ -0,0 +1,61 @@
1
+package utils
2
+
3
+import (
4
+	"errors"
5
+	"regexp"
6
+	"strconv"
7
+
8
+	"github.com/go-xorm/xorm"
9
+)
10
+
11
+// GetPageList 获取列表
12
+func GetPageList(db *xorm.Session, target interface{}, limit []int, sqlorArgs ...interface{}) (int64, error) {
13
+	if sqlorArgs == nil || len(sqlorArgs) == 0 {
14
+		return 0, errors.New("SQL 语句不存在")
15
+	}
16
+
17
+	countSQLorArgs := GetCountSQL(sqlorArgs...)
18
+	cntRes, err := db.Query(countSQLorArgs...)
19
+	if err != nil {
20
+		return 0, err
21
+	}
22
+
23
+	cntStr := string(cntRes[0]["cnt"])
24
+	cnt, _ := strconv.ParseInt(cntStr, 10, 64)
25
+
26
+	sql, args := PackLimitToSQL(limit, sqlorArgs...)
27
+
28
+	err = db.SQL(sql, args...).Find(target)
29
+	if err != nil {
30
+		return 0, err
31
+	}
32
+
33
+	return cnt, nil
34
+}
35
+
36
+// GetCountSQL 获取计算 Count 的相关 SQL 脚本
37
+func GetCountSQL(sqlorArgs ...interface{}) []interface{} {
38
+	sql := sqlorArgs[0].(string)
39
+
40
+	re := regexp.MustCompile("(?ims)(select .* from)")
41
+	cntSQL := re.ReplaceAllString(sql, "select count(*) as cnt from")
42
+
43
+	newSQLorArgs := []interface{}{cntSQL}
44
+	newSQLorArgs = append(newSQLorArgs, sqlorArgs[1:])
45
+	return newSQLorArgs
46
+}
47
+
48
+// PackLimitToSQL 添加 limit 语句到 sql 最后
49
+func PackLimitToSQL(limit []int, sqlorArgs ...interface{}) (string, []interface{}) {
50
+	sql := sqlorArgs[0].(string)
51
+	args := sqlorArgs[1:]
52
+
53
+	switch len(limit) {
54
+	case 1:
55
+		return sql + " LIMIT " + strconv.Itoa(limit[0]), args
56
+	case 2:
57
+		return sql + " LIMIT " + strconv.Itoa(limit[0]) + " OFFSET " + strconv.Itoa(limit[1]), args
58
+	default:
59
+		return sql, args
60
+	}
61
+}

+ 71
- 0
utils/pagenavi_test.go 파일 보기

@@ -0,0 +1,71 @@
1
+package utils_test
2
+
3
+import (
4
+	"spaceofcheng/services/utils"
5
+	"testing"
6
+)
7
+
8
+func TestGetCountSQL(t *testing.T) {
9
+	testCases := []map[string]string{
10
+		map[string]string{
11
+			"sql":      "Select field1, field2 From table",
12
+			"expected": "select count(*) as cnt from table",
13
+		},
14
+		map[string]string{
15
+			"sql": `Select 
16
+								field1, field2 From table where status = ?`,
17
+			"expected": "select count(*) as cnt from table where status = ?",
18
+		},
19
+	}
20
+
21
+	for inx, cs := range testCases {
22
+		sql := cs["sql"]
23
+		expected := cs["expected"]
24
+
25
+		var res []interface{}
26
+		if inx < 1 {
27
+			res = utils.GetCountSQL(sql)
28
+		} else {
29
+			res = utils.GetCountSQL(sql, inx)
30
+		}
31
+
32
+		if res == nil || len(res) == 0 {
33
+			t.Fatalf("Test GetCountSQL fail --1")
34
+		}
35
+
36
+		newSQL := res[0].(string)
37
+		if newSQL != expected {
38
+			t.Fatalf("Test GetCountSQL fail: %s", newSQL)
39
+		}
40
+	}
41
+}
42
+
43
+func TestPackLimitToSQL(t *testing.T) {
44
+	testCases := []map[string]string{
45
+		map[string]string{
46
+			"sql":      "Select * From table",
47
+			"expected": "Select * From table LIMIT 1 OFFSET 0",
48
+		},
49
+		map[string]string{
50
+			"sql":      "Select * From table",
51
+			"expected": "Select * From table LIMIT 1",
52
+		},
53
+	}
54
+
55
+	for inx, cs := range testCases {
56
+		sql := cs["sql"]
57
+		expected := cs["expected"]
58
+
59
+		var sqlRes string
60
+		if inx < 1 {
61
+			sqlRes, _ = utils.PackLimitToSQL([]int{inx + 1, inx}, sql)
62
+		} else {
63
+			sqlRes, _ = utils.PackLimitToSQL([]int{inx}, sql, inx)
64
+		}
65
+
66
+		if sqlRes != expected {
67
+			t.Fatalf("\n%v: Test PackLimitToSQL fail: %s", inx+1, sqlRes)
68
+		}
69
+	}
70
+
71
+}