educode_sales 0.9.3 → 0.9.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/educode_sales/businesses_controller.rb +7 -6
- data/app/controllers/educode_sales/sale_trends_controller.rb +281 -259
- data/app/models/educode_sales/sale_trend.rb +2 -0
- data/app/views/educode_sales/sale_trends/_business_area.html.erb +83 -0
- data/app/views/educode_sales/sale_trends/_business_followup_analysis.html.erb +110 -0
- data/app/views/educode_sales/sale_trends/_sales_analysis.html.erb +121 -0
- data/app/views/educode_sales/sale_trends/_sales_followup_analysis.html.erb +106 -0
- data/app/views/educode_sales/sale_trends/business_area.js.erb +1 -0
- data/app/views/educode_sales/sale_trends/business_followup_analysis.js.erb +1 -0
- data/app/views/educode_sales/sale_trends/sales_analysis.js.erb +1 -0
- data/app/views/educode_sales/sale_trends/sales_followup_analysis.js.erb +1 -0
- data/app/views/educode_sales/sale_trends/trends.html.erb +223 -541
- data/config/routes.rb +4 -0
- data/lib/educode_sales/version.rb +1 -1
- metadata +10 -2
@@ -8,17 +8,23 @@ module EducodeSales
|
|
8
8
|
# authorize! :trends, EducodeSales::SaleTrend
|
9
9
|
@year = params[:year] ? params[:year] : Time.now.year
|
10
10
|
@years = ['全部'] + (1..(Time.now.year - 2014)).reverse_each.map { |d| 2014 + d }
|
11
|
+
x = Common.find_by(extras: EducodeSales::Common::XTYPE)&.id
|
12
|
+
o = Common.find_by(extras: EducodeSales::Common::OTYPE)&.id
|
11
13
|
if (@year == '全部')
|
12
|
-
x = Common.find_by(extras: EducodeSales::Common::XTYPE)&.id
|
13
|
-
o = Common.find_by(extras: EducodeSales::Common::OTYPE)&.id
|
14
14
|
@business_amount = Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id != ?", x).sum(:total_amount).round(2)
|
15
15
|
stage_ids = Common.where(clazz: '商机阶段', name: ['已中标', '已签单', '已验收', '回款中', '服务中', '已结束']).pluck(:id)
|
16
|
-
|
16
|
+
# 中标总金额, 已回款总金额
|
17
|
+
total_return = Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id != ?", x).where("educode_sales_follow_ups.stage_id IN (?)", stage_ids).select("sum(total_amount) AS total, sum(educode_sales_businesses.return_money) AS return_money")
|
18
|
+
@goal_amount = total_return[0]['total']&.round(2) || 0
|
19
|
+
|
17
20
|
@actual_goal_amount = Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id != ?", x).where("educode_sales_follow_ups.stage_id IN (?)", stage_ids).sum(:actual_amount).round(2)
|
18
21
|
s_stage_ids = Common.where(clazz: '商机阶段', name: ['已签单', '已验收', '回款中', '服务中', '已结束']).pluck(:id)
|
19
22
|
@service_amount = Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id != ?", x).where("educode_sales_follow_ups.stage_id IN (?)", s_stage_ids).sum(:total_amount).round(2)
|
20
23
|
@actual_service_amount = Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id != ?", x).where("educode_sales_follow_ups.stage_id IN (?)", s_stage_ids).sum(:actual_amount).round(2)
|
21
|
-
@return_amount = Business.joins(last_follow_up: :money_plans).where("educode_sales_follow_ups.clazz_id != ?", x).where.not("educode_sales_money_plans.clazz!= ?", 1).sum(:amount).round(2)
|
24
|
+
# @return_amount = Business.joins(last_follow_up: :money_plans).where("educode_sales_follow_ups.clazz_id != ?", x).where.not("educode_sales_money_plans.clazz!= ?", 1).sum(:amount).round(2)
|
25
|
+
@return_amount = total_return[0]['return_money']&.round(2) || 0
|
26
|
+
@receivable_amount = @goal_amount - @return_amount
|
27
|
+
|
22
28
|
a = Common.where(clazz: '商机类型', name: Common.find_by(extras: EducodeSales::Common::ATYPE)&.name).pluck(:id)
|
23
29
|
@a_amount = Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id IN (?)", a).sum(:total_amount).round(2)
|
24
30
|
b = Common.where(clazz: '商机类型', name: Common.find_by(extras: EducodeSales::Common::BTYPE)&.name).pluck(:id)
|
@@ -26,215 +32,298 @@ module EducodeSales
|
|
26
32
|
else
|
27
33
|
year_time = "#{@year}-01-01 00:00:00"
|
28
34
|
year_over_time = "#{@year}-12-31 23:59:59"
|
29
|
-
|
30
|
-
o = Common.find_by(extras: EducodeSales::Common::OTYPE)&.id
|
35
|
+
|
31
36
|
@sale_trend = SaleTrend.find_or_create_by(year: @year)
|
32
37
|
@business_amount = Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id != ?", x).where("educode_sales_follow_ups.year = ?", @year).sum(:total_amount).round(2)
|
33
38
|
stage_ids = Common.where(clazz: '商机阶段', name: ['已中标', '已签单', '已验收', '回款中', '服务中', '已结束']).pluck(:id)
|
34
|
-
|
39
|
+
|
40
|
+
# 中标总金额, 已回款总金额
|
41
|
+
total_return = Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id != ?", x).where("educode_sales_follow_ups.bidded_date >= ? AND educode_sales_follow_ups.bidded_date <= ? AND educode_sales_follow_ups.stage_id IN (?)", "#{@year}-01-01", "#{@year}-12-31", stage_ids).select("sum(total_amount) AS total, sum(educode_sales_businesses.return_money) AS return_money")
|
42
|
+
@goal_amount = total_return[0]['total']&.round(2) || 0
|
43
|
+
|
35
44
|
@actual_goal_amount = Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id != ?", x).where("educode_sales_follow_ups.bidded_date >= ? AND educode_sales_follow_ups.bidded_date <= ? AND educode_sales_follow_ups.stage_id IN (?)", "#{@year}-01-01", "#{@year}-12-31", stage_ids).sum(:actual_amount).round(2)
|
36
45
|
s_stage_ids = Common.where(clazz: '商机阶段', name: ['已签单', '已验收', '回款中', '服务中', '已结束']).pluck(:id)
|
37
46
|
@service_amount = Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id != ?", x).where("educode_sales_follow_ups.signed_date >= ? AND educode_sales_follow_ups.signed_date <= ? AND educode_sales_follow_ups.stage_id IN (?)", "#{@year}-01-01", "#{@year}-12-31", s_stage_ids).sum(:total_amount).round(2)
|
38
47
|
@actual_service_amount = Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id != ?", x).where("educode_sales_follow_ups.signed_date >= ? AND educode_sales_follow_ups.signed_date <= ? AND educode_sales_follow_ups.stage_id IN (?)", "#{@year}-01-01", "#{@year}-12-31", s_stage_ids).sum(:actual_amount).round(2)
|
39
|
-
@return_amount = Business.joins(last_follow_up: :money_plans).where("educode_sales_follow_ups.clazz_id != ?", x).where.not("educode_sales_money_plans.clazz!= ?", 1).where("educode_sales_money_plans.date_at >= ? AND educode_sales_money_plans.date_at <= ? ", year_time, year_over_time).sum(:amount).round(2)
|
48
|
+
# @return_amount = Business.joins(last_follow_up: :money_plans).where("educode_sales_follow_ups.clazz_id != ?", x).where.not("educode_sales_money_plans.clazz!= ?", 1).where("educode_sales_money_plans.date_at >= ? AND educode_sales_money_plans.date_at <= ? ", year_time, year_over_time).sum(:amount).round(2)
|
49
|
+
@return_amount = total_return[0]['return_money']&.round(2) || 0
|
50
|
+
@receivable_amount = @goal_amount - @return_amount
|
51
|
+
|
40
52
|
a = Common.where(clazz: '商机类型', name: Common.find_by(extras: EducodeSales::Common::ATYPE)&.name).pluck(:id)
|
41
53
|
@a_amount = Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id IN (?)", a).where("educode_sales_follow_ups.year = ?", @year).sum(:total_amount).round(2)
|
42
54
|
b = Common.where(clazz: '商机类型', name: Common.find_by(extras: EducodeSales::Common::BTYPE)&.name).pluck(:id)
|
43
55
|
@b_amount = Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id IN (?)", b).where("educode_sales_follow_ups.year = ?", @year).sum(:total_amount).round(2)
|
44
56
|
end
|
45
57
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def sale_trends
|
61
|
+
sale_trend = SaleTrend.find_by(year: params[:year])
|
62
|
+
if sale_trend.update(sale_trend_params)
|
63
|
+
render_success
|
64
|
+
else
|
65
|
+
render_failure sale_trend
|
55
66
|
end
|
56
|
-
|
67
|
+
end
|
68
|
+
|
69
|
+
def operations
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
# 商机跟进数
|
74
|
+
def business_followup_analysis
|
75
|
+
common = EducodeSales::Common.find_by(clazz: 'staff_type', name: '销售')
|
76
|
+
names = EducodeSales::Staff.includes(:user).where(job_type: common.id).map { |d| [d.user.real_name, d.id, d.role_id] }
|
77
|
+
x = EducodeSales::Common.find_by(extras: EducodeSales::Common::XTYPE)&.id
|
78
|
+
x_business_ids = EducodeSales::Business.joins(last_follow_up: :clazz).where("educode_sales_commons.id = ?",x).pluck :id
|
79
|
+
|
57
80
|
@follow_count_range = params[:follow_count_range] || "week"
|
58
|
-
@goal_count_range = params[:goal_count_range] || "month"
|
59
81
|
# 商机跟进数图表
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
date = params[:date_year].split(" - ")
|
80
|
-
dates = (date[0]..date[1]).to_a
|
81
|
-
@follow_count_data = year_follow_count_chart(dates, names, x_business_ids, colors)
|
82
|
+
respond_to do |format|
|
83
|
+
format.html do
|
84
|
+
|
85
|
+
end
|
86
|
+
format.js do
|
87
|
+
default_dates = (30.day.ago.to_date..Date.today).map { |d| d.strftime("%Y-%W") }.uniq #默认时间范围
|
88
|
+
@follow_count_data = business_followup_charts(default_dates, names, x_business_ids, SaleTrend::COLORS, [30.day.ago.to_date.beginning_of_week, Date.today], "%Y-%u") do |default_dates|
|
89
|
+
default_dates.map { |date|
|
90
|
+
d = date.split("-")
|
91
|
+
year = d[0].to_i
|
92
|
+
week = d[1].to_i
|
93
|
+
if week == 0
|
94
|
+
0
|
95
|
+
else
|
96
|
+
month = Date.commercial(year, week).strftime("%m月%d日")
|
97
|
+
day = Date.commercial(year, week, 7).strftime("%m月%d日")
|
98
|
+
date.to_s + "(#{month}-#{day})"
|
99
|
+
end
|
100
|
+
} - [0]
|
82
101
|
end
|
83
|
-
|
84
|
-
|
85
|
-
if params[:
|
86
|
-
|
87
|
-
|
88
|
-
|
102
|
+
end
|
103
|
+
format.json do
|
104
|
+
if params[:follow_count_range].present?
|
105
|
+
case params[:follow_count_range]
|
106
|
+
when "week" #按周
|
107
|
+
if params[:date_week].present?
|
108
|
+
date = params[:date_week].split(" - ")
|
109
|
+
dates = (date[0].to_date..date[1].to_date).map { |d| d.strftime("%Y-%W") }.uniq
|
110
|
+
@follow_count_data = business_followup_charts(dates, names, x_business_ids, SaleTrend::COLORS, date, "%Y%u") do |dates|
|
111
|
+
dates.map { |date|
|
112
|
+
d = date.split("-")
|
113
|
+
year = d[0].to_i
|
114
|
+
week = d[1].to_i
|
115
|
+
if week == 0
|
116
|
+
0
|
117
|
+
else
|
118
|
+
month = Date.commercial(year, week).strftime("%m月%d日")
|
119
|
+
day = Date.commercial(year, week, 7).strftime("%m月%d日")
|
120
|
+
date.to_s + "(#{month}-#{day})"
|
121
|
+
end
|
122
|
+
} - [0]
|
123
|
+
end
|
124
|
+
else
|
125
|
+
return render json: {msg: '请选择时间范围', success: false }
|
126
|
+
end
|
127
|
+
when "month" #按月
|
128
|
+
if params[:date_month].present?
|
129
|
+
date = params[:date_month].split(" - ")
|
130
|
+
dates = ((date[0] + "-01").to_date..(date[1] + "-01").to_date).map { |d| d.strftime("%Y-%m") }.uniq
|
131
|
+
@follow_count_data = business_followup_charts(dates, names, x_business_ids, SaleTrend::COLORS, [(date[0] + "-01").to_date, (date[1] + "-01").to_date.end_of_month], '%Y%m')
|
132
|
+
else
|
133
|
+
return render json: {msg: '请选择时间范围', success: false }
|
134
|
+
end
|
135
|
+
when "year" #按年
|
136
|
+
if params[:date_year].present?
|
137
|
+
date = params[:date_year].split(" - ")
|
138
|
+
dates = (date[0]..date[1]).to_a.map { |d| d.to_s}
|
139
|
+
@follow_count_data = business_followup_charts(dates, names, x_business_ids, SaleTrend::COLORS, ["#{date[0]}-01-01".to_date.beginning_of_year, "#{date[1]}-01-01".to_date.end_of_year], '%Y')
|
140
|
+
else
|
141
|
+
return render json: {msg: '请选择时间范围', success: false }
|
142
|
+
end
|
143
|
+
else
|
144
|
+
#按天
|
145
|
+
if params[:date].present?
|
146
|
+
date = params[:date].split(" - ")
|
147
|
+
dates = (date[0].to_date..date[1].to_date).to_a.map { |d| d.to_s}
|
148
|
+
@follow_count_data = business_followup_charts(dates, names, x_business_ids, SaleTrend::COLORS, [date[0].to_date, date[1].to_date], '%Y%m%d')
|
149
|
+
else
|
150
|
+
return render json: {msg: '请选择时间范围', success: false }
|
151
|
+
end
|
152
|
+
end
|
89
153
|
end
|
154
|
+
render json: {data: @follow_count_data }
|
90
155
|
end
|
91
156
|
end
|
92
157
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
{
|
100
|
-
label: "商机总额",
|
101
|
-
data: provinces.map { |province|
|
102
|
-
if params[:business_type].blank?
|
103
|
-
Business.joins(:last_follow_up).where("educode_sales_businesses.department_id in (?)", School.joins(:departments).where(province: province).pluck("departments.id")).where("educode_sales_follow_ups.clazz_id != ?", x).sum(:total_amount).round(2)
|
104
|
-
else
|
105
|
-
Business.joins(:last_follow_up).where("educode_sales_businesses.department_id in (?)", School.joins(:departments).where(province: province).pluck("departments.id")).where("educode_sales_follow_ups.clazz_id = ?", params[:business_type]).sum(:total_amount).round(2)
|
106
|
-
end
|
107
|
-
},
|
108
|
-
backgroundColor: colors[0],
|
109
|
-
borderColor: colors[0],
|
110
|
-
borderWidth: 1
|
111
|
-
}
|
112
|
-
]
|
113
|
-
}
|
114
|
-
else
|
115
|
-
@business_data = {
|
116
|
-
labels: provinces,
|
117
|
-
datasets: [
|
118
|
-
{
|
119
|
-
label: "商机数量",
|
120
|
-
data: provinces.map { |province|
|
121
|
-
if params[:business_type].blank?
|
122
|
-
Business.joins(:last_follow_up).where("educode_sales_businesses.department_id in (?)", School.joins(:departments).where(province: province).pluck("departments.id")).where("educode_sales_follow_ups.clazz_id != ?", x).count
|
123
|
-
else
|
124
|
-
Business.joins(:last_follow_up).where("educode_sales_businesses.department_id in (?)", School.joins(:departments).where(province: province).pluck("departments.id")).where("educode_sales_follow_ups.clazz_id = ?", params[:business_type]).count
|
125
|
-
end
|
126
|
-
},
|
127
|
-
backgroundColor: colors[0],
|
128
|
-
borderColor: colors[0],
|
129
|
-
borderWidth: 1
|
130
|
-
}
|
131
|
-
]
|
132
|
-
}
|
133
|
-
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# 销售额分析
|
161
|
+
def sales_analysis
|
162
|
+
respond_to do |format|
|
163
|
+
format.html do
|
134
164
|
|
135
|
-
# 销售人员跟进分析
|
136
|
-
begin_time = Time.now.at_beginning_of_year.to_s
|
137
|
-
end_time = Time.now.at_end_of_year.to_s
|
138
|
-
customer_time_range = params[:customer_time_range]
|
139
|
-
case customer_time_range
|
140
|
-
when 'last_week'
|
141
|
-
begin_time = (Time.now - 1.week).at_beginning_of_week.to_s
|
142
|
-
end_time = (Time.now - 1.week).at_end_of_week.to_s
|
143
|
-
when 'this_week'
|
144
|
-
begin_time = Time.now.at_beginning_of_week.to_s
|
145
|
-
end_time = Time.now.at_end_of_week.to_s
|
146
|
-
when 'last_month'
|
147
|
-
begin_time = (Time.now - 1.month).at_beginning_of_month.to_s
|
148
|
-
end_time = (Time.now - 1.month).at_end_of_month.to_s
|
149
|
-
when 'this_month'
|
150
|
-
begin_time = Time.now.at_beginning_of_month.to_s
|
151
|
-
end_time = Time.now.at_end_of_month.to_s
|
152
|
-
when 'last_year'
|
153
|
-
begin_time = (Time.now - 1.year).at_beginning_of_year.to_s
|
154
|
-
end_time = (Time.now - 1.year).at_end_of_year.to_s
|
155
|
-
when 'this_year'
|
156
|
-
begin_time = Time.now.at_beginning_of_year.to_s
|
157
|
-
end_time = Time.now.at_end_of_year.to_s
|
158
|
-
when 'all'
|
159
|
-
begin_time = (Time.now - 5.year).at_beginning_of_year.to_s
|
160
|
-
end_time = (Time.now + 5.year).at_end_of_year.to_s
|
161
|
-
when 'diy'
|
162
|
-
if params[:customer_date].present?
|
163
|
-
date = params[:customer_date].split(" - ")
|
164
|
-
begin_time = date[0] + "00:00:00"
|
165
|
-
end_time = date[1] + "23:59:59"
|
166
165
|
end
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
labels: staff_names,
|
174
|
-
datasets: [
|
175
|
-
{
|
176
|
-
label: "跟进客户数",
|
177
|
-
data: staff_ids.map { |staff_id|
|
178
|
-
(EducodeSales::CustomerFollow.where(staff_id: staff_id).where("created_at >= ? AND created_at <= ?", begin_time, end_time).pluck(:school_id) + EducodeSales::Business.where(id: EducodeSales::FollowUp.where(staff_id: staff_id).where("created_at >= ? AND created_at <= ?", begin_time, end_time).pluck(:business_id).uniq).pluck(:school_id)).uniq.size
|
179
|
-
},
|
180
|
-
backgroundColor: colors[0],
|
181
|
-
borderColor: colors[0],
|
182
|
-
borderWidth: 1
|
183
|
-
}
|
184
|
-
]
|
185
|
-
}
|
186
|
-
else
|
187
|
-
@customer_data = {
|
188
|
-
labels: staff_names,
|
189
|
-
datasets: [
|
190
|
-
{
|
191
|
-
label: "跟进客户次数",
|
192
|
-
data: staff_ids.map { |staff_id|
|
193
|
-
EducodeSales::CustomerFollow.where(staff_id: staff_id).where("created_at >= ? AND created_at <= ?", begin_time, end_time).size + EducodeSales::FollowUp.where(staff_id: staff_id).where("created_at >= ? AND created_at <= ?", begin_time, end_time).size
|
194
|
-
},
|
195
|
-
backgroundColor: colors[0],
|
196
|
-
borderColor: colors[0],
|
197
|
-
borderWidth: 1
|
198
|
-
}
|
199
|
-
]
|
200
|
-
}
|
201
|
-
end
|
166
|
+
format.js do
|
167
|
+
x = EducodeSales::Common.find_by(extras: EducodeSales::Common::XTYPE)&.id
|
168
|
+
count_type = params[:count_type] || "actual_amount"
|
169
|
+
stage_ids = Common.where(clazz: '商机阶段', name: ['已中标', '已签单', '已验收', '回款中', '服务中', '已结束']).pluck(:id)
|
170
|
+
s_stage_ids = Common.where(clazz: '商机阶段', name: ['已签单', '已验收', '回款中', '服务中', '已结束']).pluck(:id)
|
171
|
+
@goal_count_range = params[:goal_count_range] || "month"
|
202
172
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
173
|
+
goal_default_dates = ("#{Time.now.year}-01-01".to_date.."#{Time.now.year}-#{Time.now.month}-01".to_date).map { |d| d.strftime("%Y-%m") }.uniq
|
174
|
+
sale_names = ['已中标', '已签单', '已回款']
|
175
|
+
@goal_count_data = month_sale_chart(goal_default_dates, sale_names, SaleTrend::COLORS, x, stage_ids, s_stage_ids, count_type)
|
176
|
+
if params[:goal_count_range].present?
|
177
|
+
case params[:goal_count_range]
|
178
|
+
when "week"
|
179
|
+
when "month" #按月
|
180
|
+
if params[:goal_date_month].present?
|
181
|
+
date = params[:goal_date_month].split(" - ")
|
182
|
+
dates = ((date[0] + "-01").to_date..(date[1] + "-01").to_date).map { |d| d.strftime("%Y-%m") }.uniq
|
183
|
+
@goal_count_data = month_sale_chart(dates, sale_names, SaleTrend::COLORS, x, stage_ids, s_stage_ids, count_type)
|
184
|
+
end
|
185
|
+
else
|
186
|
+
#按年
|
187
|
+
if params[:goal_date_year].present?
|
188
|
+
date = params[:goal_date_year].split(" - ")
|
189
|
+
dates = (date[0]..date[1]).to_a
|
190
|
+
@goal_count_data = year_sale_chart(dates, sale_names, SaleTrend::COLORS, x, stage_ids, s_stage_ids, count_type)
|
191
|
+
end
|
192
|
+
end
|
222
193
|
end
|
223
194
|
end
|
224
195
|
end
|
225
196
|
end
|
226
197
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
198
|
+
# 商机区域分布
|
199
|
+
def business_area
|
200
|
+
respond_to do |format|
|
201
|
+
format.html do
|
202
|
+
|
203
|
+
end
|
204
|
+
format.js do
|
205
|
+
x = EducodeSales::Common.find_by(extras: EducodeSales::Common::XTYPE)&.id
|
206
|
+
provinces = EducodeSales::Common.where(clazz: 'area').pluck(:name)
|
207
|
+
if params[:business_count_type] == 'money' || params[:business_count_type].blank?
|
208
|
+
@business_data = {
|
209
|
+
labels: provinces,
|
210
|
+
datasets: [
|
211
|
+
{
|
212
|
+
label: "商机总额",
|
213
|
+
data: provinces.map { |province|
|
214
|
+
if params[:business_type].blank?
|
215
|
+
Business.joins(:last_follow_up).where("educode_sales_businesses.department_id in (?)", School.joins(:departments).where(province: province).pluck("departments.id")).where("educode_sales_follow_ups.clazz_id != ?", x).sum(:total_amount).round(2)
|
216
|
+
else
|
217
|
+
Business.joins(:last_follow_up).where("educode_sales_businesses.department_id in (?)", School.joins(:departments).where(province: province).pluck("departments.id")).where("educode_sales_follow_ups.clazz_id = ?", params[:business_type]).sum(:total_amount).round(2)
|
218
|
+
end
|
219
|
+
},
|
220
|
+
backgroundColor: SaleTrend::COLORS[0],
|
221
|
+
borderColor: SaleTrend::COLORS[0],
|
222
|
+
borderWidth: 1
|
223
|
+
}
|
224
|
+
]
|
225
|
+
}
|
226
|
+
else
|
227
|
+
@business_data = {
|
228
|
+
labels: provinces,
|
229
|
+
datasets: [
|
230
|
+
{
|
231
|
+
label: "商机数量",
|
232
|
+
data: provinces.map { |province|
|
233
|
+
if params[:business_type].blank?
|
234
|
+
Business.joins(:last_follow_up).where("educode_sales_businesses.department_id in (?)", School.joins(:departments).where(province: province).pluck("departments.id")).where("educode_sales_follow_ups.clazz_id != ?", x).count
|
235
|
+
else
|
236
|
+
Business.joins(:last_follow_up).where("educode_sales_businesses.department_id in (?)", School.joins(:departments).where(province: province).pluck("departments.id")).where("educode_sales_follow_ups.clazz_id = ?", params[:business_type]).count
|
237
|
+
end
|
238
|
+
},
|
239
|
+
backgroundColor: SaleTrend::COLORS[0],
|
240
|
+
borderColor: SaleTrend::COLORS[0],
|
241
|
+
borderWidth: 1
|
242
|
+
}
|
243
|
+
]
|
244
|
+
}
|
245
|
+
end
|
246
|
+
end
|
233
247
|
end
|
234
248
|
end
|
235
249
|
|
236
|
-
|
250
|
+
# 销售人员跟进分析
|
251
|
+
def sales_followup_analysis
|
252
|
+
respond_to do |format|
|
253
|
+
format.html do
|
237
254
|
|
255
|
+
end
|
256
|
+
format.js do
|
257
|
+
# 销售人员跟进分析
|
258
|
+
@goal_count_range = params[:goal_count_range] || "month"
|
259
|
+
begin_time = Time.now.at_beginning_of_year.to_s
|
260
|
+
end_time = Time.now.at_end_of_year.to_s
|
261
|
+
customer_time_range = params[:customer_time_range]
|
262
|
+
case customer_time_range
|
263
|
+
when 'last_week'
|
264
|
+
begin_time = (Time.now - 1.week).at_beginning_of_week.to_s
|
265
|
+
end_time = (Time.now - 1.week).at_end_of_week.to_s
|
266
|
+
when 'this_week'
|
267
|
+
begin_time = Time.now.at_beginning_of_week.to_s
|
268
|
+
end_time = Time.now.at_end_of_week.to_s
|
269
|
+
when 'last_month'
|
270
|
+
begin_time = (Time.now - 1.month).at_beginning_of_month.to_s
|
271
|
+
end_time = (Time.now - 1.month).at_end_of_month.to_s
|
272
|
+
when 'this_month'
|
273
|
+
begin_time = Time.now.at_beginning_of_month.to_s
|
274
|
+
end_time = Time.now.at_end_of_month.to_s
|
275
|
+
when 'last_year'
|
276
|
+
begin_time = (Time.now - 1.year).at_beginning_of_year.to_s
|
277
|
+
end_time = (Time.now - 1.year).at_end_of_year.to_s
|
278
|
+
when 'this_year'
|
279
|
+
begin_time = Time.now.at_beginning_of_year.to_s
|
280
|
+
end_time = Time.now.at_end_of_year.to_s
|
281
|
+
when 'all'
|
282
|
+
begin_time = (Time.now - 5.year).at_beginning_of_year.to_s
|
283
|
+
end_time = (Time.now + 5.year).at_end_of_year.to_s
|
284
|
+
when 'diy'
|
285
|
+
if params[:customer_date].present?
|
286
|
+
date = params[:customer_date].split(" - ")
|
287
|
+
begin_time = date[0] + " 00:00:00"
|
288
|
+
end_time = date[1] + " 23:59:59"
|
289
|
+
end
|
290
|
+
end
|
291
|
+
common = Common.find_by(clazz: 'staff_type', name: '销售')
|
292
|
+
staff_names = Staff.joins(:user).where(job_type: common.id).map { |d| d.user.real_name }
|
293
|
+
staff_ids = Staff.joins(:user).where(job_type: common.id).pluck(:id)
|
294
|
+
if params[:customer_count_type] == 'money' || params[:customer_count_type].blank?
|
295
|
+
@customer_data = {
|
296
|
+
labels: staff_names,
|
297
|
+
datasets: [
|
298
|
+
{
|
299
|
+
label: "跟进客户数",
|
300
|
+
data: staff_ids.map { |staff_id|
|
301
|
+
(EducodeSales::CustomerFollow.where(staff_id: staff_id).where("created_at >= ? AND created_at <= ?", begin_time, end_time).pluck(:school_id) + EducodeSales::Business.where(id: EducodeSales::FollowUp.where(staff_id: staff_id).where("created_at >= ? AND created_at <= ?", begin_time, end_time).pluck(:business_id).uniq).pluck(:school_id)).uniq.size
|
302
|
+
},
|
303
|
+
backgroundColor: SaleTrend::COLORS[0],
|
304
|
+
borderColor: SaleTrend::COLORS[0],
|
305
|
+
borderWidth: 1
|
306
|
+
}
|
307
|
+
]
|
308
|
+
}
|
309
|
+
else
|
310
|
+
@customer_data = {
|
311
|
+
labels: staff_names,
|
312
|
+
datasets: [
|
313
|
+
{
|
314
|
+
label: "跟进客户次数",
|
315
|
+
data: staff_ids.map { |staff_id|
|
316
|
+
EducodeSales::CustomerFollow.where(staff_id: staff_id).where("created_at >= ? AND created_at <= ?", begin_time, end_time).size + EducodeSales::FollowUp.where(staff_id: staff_id).where("created_at >= ? AND created_at <= ?", begin_time, end_time).size
|
317
|
+
},
|
318
|
+
backgroundColor: SaleTrend::COLORS[0],
|
319
|
+
borderColor: SaleTrend::COLORS[0],
|
320
|
+
borderWidth: 1
|
321
|
+
}
|
322
|
+
]
|
323
|
+
}
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
238
327
|
end
|
239
328
|
|
240
329
|
private
|
@@ -243,54 +332,24 @@ module EducodeSales
|
|
243
332
|
params.permit(:chance_money, :ballot_money, :sign_money, :returned_money)
|
244
333
|
end
|
245
334
|
|
246
|
-
def
|
247
|
-
|
248
|
-
|
249
|
-
datasets: names.map.with_index do |name, i|
|
250
|
-
{
|
251
|
-
# hidden: i < 3 ? false : true,
|
252
|
-
hidden: name[2] == 11,
|
253
|
-
label: name[0],
|
254
|
-
data: dates.map { |d| @follow_up = FollowUp.where(staff_id: name[1], created_at: d.beginning_of_day..d.end_of_day).where.not(business: x_business_ids).count },
|
255
|
-
backgroundColor: "#fff",
|
256
|
-
pointBorderColor: colors[i % 15 + 1],
|
257
|
-
borderColor: colors[i % 15 + 1],
|
258
|
-
pointBackgroundColor: colors[i % 15 + 1],
|
259
|
-
borderWidth: 2
|
260
|
-
}
|
261
|
-
end
|
262
|
-
}
|
263
|
-
end
|
335
|
+
def business_followup_charts(dates, names, x_business_ids, colors, date, clazz)
|
336
|
+
not_business = x_business_ids.present? ? x_business_ids.join(',') : ''
|
337
|
+
staff_ids = names.present? ? names.map { |d| d[1]}.join(",") : ''
|
264
338
|
|
265
|
-
|
339
|
+
sql = "SELECT DATE_FORMAT(created_at, '#{clazz}') as week, count(*) as counts, staff_id
|
340
|
+
FROM educode_sales_follow_ups
|
341
|
+
WHERE date(created_at) >= '#{date[0]}' and date(created_at) <= '#{date[1]}'
|
342
|
+
AND business_id NOT IN (#{not_business}) and educode_sales_follow_ups.deleted_at IS NULL
|
343
|
+
AND staff_id IN (#{staff_ids})
|
344
|
+
GROUP BY DATE_FORMAT(created_at, '#{clazz}'), staff_id"
|
345
|
+
data = EducodeSales::FollowUp.find_by_sql(sql).group_by { |d| "#{d['staff_id']}-#{d['week']}" }
|
266
346
|
{
|
267
|
-
labels: dates
|
268
|
-
d = date.split("-")
|
269
|
-
year = d[0].to_i
|
270
|
-
week = d[1].to_i
|
271
|
-
if week == 0
|
272
|
-
0
|
273
|
-
else
|
274
|
-
month = Date.commercial(year, week).strftime("%m月%d日")
|
275
|
-
day = Date.commercial(year, week, 7).strftime("%m月%d日")
|
276
|
-
date.to_s + "(#{month}-#{day})"
|
277
|
-
end
|
278
|
-
} - [0],
|
347
|
+
labels: block_given? ? yield(dates) : dates,
|
279
348
|
datasets: names.map.with_index do |name, i|
|
280
349
|
{
|
281
|
-
# hidden: i < 3 ? false : true,
|
282
350
|
label: name[0],
|
283
351
|
hidden: name[2] == 11, #role_id:11 离职角色
|
284
|
-
data: dates.map { |
|
285
|
-
d = d.split("-")
|
286
|
-
year = d[0].to_i
|
287
|
-
week = d[1].to_i
|
288
|
-
if week == 0
|
289
|
-
@follow_up = 999999
|
290
|
-
else
|
291
|
-
@follow_up = FollowUp.where(staff_id: name[1]).where("created_at >= ? AND created_at <= ?", Date.commercial(year, week).strftime("%Y-%m-%d"), Date.commercial(year, week, 7).strftime("%Y-%m-%d")).where.not(business: x_business_ids).count
|
292
|
-
end
|
293
|
-
} - [999999],
|
352
|
+
data: dates.map { |date| data["#{name[1]}-#{ date.gsub("-", '')}"]&.[](0)&.[]('counts') || 0 },
|
294
353
|
backgroundColor: "#fff",
|
295
354
|
pointBorderColor: colors[i % 15 + 1],
|
296
355
|
borderColor: colors[i % 15 + 1],
|
@@ -301,43 +360,6 @@ module EducodeSales
|
|
301
360
|
}
|
302
361
|
end
|
303
362
|
|
304
|
-
def month_follow_count_chart(dates, names, x_business_ids, colors)
|
305
|
-
{
|
306
|
-
labels: dates,
|
307
|
-
datasets: names.map.with_index do |name, i|
|
308
|
-
{
|
309
|
-
# hidden: i < 3 ? false : true,
|
310
|
-
label: name[0],
|
311
|
-
hidden: name[2] == 11,
|
312
|
-
data: dates.map { |d| @follow_up = FollowUp.where(staff_id: name[1]).where("created_at >= ? AND created_at <= ?", "#{d}-01", "#{d}-31").where.not(business: x_business_ids).count },
|
313
|
-
backgroundColor: "#fff",
|
314
|
-
pointBorderColor: colors[i % 15 + 1],
|
315
|
-
borderColor: colors[i % 15 + 1],
|
316
|
-
pointBackgroundColor: colors[i % 15 + 1],
|
317
|
-
borderWidth: 2,
|
318
|
-
}
|
319
|
-
end
|
320
|
-
}
|
321
|
-
end
|
322
|
-
|
323
|
-
def year_follow_count_chart(dates, names, x_business_ids, colors)
|
324
|
-
{
|
325
|
-
labels: dates,
|
326
|
-
datasets: names.map.with_index do |name, i|
|
327
|
-
{
|
328
|
-
# hidden: i < 3 ? false : true,
|
329
|
-
label: name[0],
|
330
|
-
hidden: name[2] == 11,
|
331
|
-
data: dates.map { |d| @follow_up = FollowUp.where(staff_id: name[1]).where("created_at >= ? AND created_at <= ?", "#{d}-01-01", "#{d}-12-31").where.not(business: x_business_ids).count },
|
332
|
-
backgroundColor: "#fff",
|
333
|
-
pointBorderColor: colors[i % 15 + 1],
|
334
|
-
borderColor: colors[i % 15 + 1],
|
335
|
-
pointBackgroundColor: colors[i % 15 + 1],
|
336
|
-
borderWidth: 2
|
337
|
-
}
|
338
|
-
end
|
339
|
-
}
|
340
|
-
end
|
341
363
|
|
342
364
|
def month_sale_chart(dates, names, colors, x, stage_ids, s_stage_ids, count_type)
|
343
365
|
{
|
@@ -1,4 +1,6 @@
|
|
1
1
|
module EducodeSales
|
2
2
|
class SaleTrend < ApplicationRecord
|
3
|
+
|
4
|
+
COLORS = ['#44D7B6', '#4CACFF', '#F7B500', '#FF0000', '#FF7F00', '#FFFF00', '#00FF00', '#00FFFF', '#0000FF', '#8B00FF', 'rgba(255, 99, 132, 1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)', 'rgba(75, 192, 192, 1)', 'rgba(153, 102, 255, 1)', 'rgba(255, 159, 64, 1)', 'rgba(255, 0, 250, 1)']
|
3
5
|
end
|
4
6
|
end
|