educode_sales 1.10.22 → 1.10.23

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c2b8c0d76ccb06751726aeef62b4b04f234424db8b848d62f086b530b1213d25
4
- data.tar.gz: 88f36d9731d556cdfedd495e0ad198e90baeecf454352fc8faf17d9dd373c3a9
3
+ metadata.gz: ac157bfbdbc5c1aceeef3b0d0af4b81e74b6835ddda09a5beae4188f23720391
4
+ data.tar.gz: a4f7c4077fc9af0f5374fc3efec8bf42e5c3a57a27dc78090a5727cabe2f5510
5
5
  SHA512:
6
- metadata.gz: 99412e792e86479290e2d09a62aced8ae6bc6cd32d448450d9e0b4898d5df54358e683a70b94038eb37474ba663b6d1cbe9e4b24a8440dcef2e6ca17a3d19e06
7
- data.tar.gz: cb3ba8ffa9e9cf91ade0cf3a74fe5e5fc13767d05a1dfa12180fb699abbb70cbc380469b55b11b0900a7c0930afd2ba395148f532c23f3fcba70f7794fca7913
6
+ metadata.gz: 804531ab845025fe61054b79b248a5f1f83e4194d0c23cad2f0fb4c49978db71eb695815723d50e7255fa35a4aa0b0154babb156fdd5cd953808bb2a1b56a9e9
7
+ data.tar.gz: 13484d3b014be703413f41b03938881aeb56bd1b7cf97f721f055f9a0aa869dfedc6b948ddbd57bb7b3174c2e3aa171dc7efa5823821f3e2b903e1e1ec9b2591
@@ -417,6 +417,49 @@ module EducodeSales
417
417
  end
418
418
  end
419
419
 
420
+ #拜访分析
421
+ def visit_analysis
422
+ sort_by = params[:sort_by].present? ? params[:sort_by] : "desc"
423
+ user_name = params[:user_name]
424
+ visit_type = params[:visit_type].present? ? params[:visit_type].split(",") : ""
425
+ title_names = %w[本年拜访数 本季拜访数 本月拜访数 本周拜访数]
426
+ respond_to do |format|
427
+ format.js do
428
+ @user_names = EducodeSales::Attendance.pluck(:name).uniq.map{|d| {name: d, value: d}}
429
+ @visit_types = SaleTrend::VISIT_TYPE.map {|d| {name: d[0], value: d[1]}}
430
+ sql = "SELECT name, count(*) as name_count FROM `educode_sales_attendances` WHERE (attendance_date >= '#{Time.now.beginning_of_year}' and attendance_date <= '#{Time.now.end_of_year}') group by name order by name_count desc limit 30"
431
+ visit_count = EducodeSales::Attendance.find_by_sql(sql).map{|d| [d.name, d.name_count]}
432
+ #年拜访量前30的用户名
433
+ top_thirty_username = visit_count.map{ |d| d[0]}
434
+ @visit_count_data = visit_user_type_name(top_thirty_username, sort_by, visit_type, title_names)
435
+ end
436
+ format.json do
437
+ if params[:user_type].present? && params[:user_type] == "name"
438
+ if user_name.present?
439
+ sql_by_name = "SELECT name, count(*) as name_count FROM `educode_sales_attendances` WHERE (attendance_date >= '#{Time.now.beginning_of_year}' and attendance_date <= '#{Time.now.end_of_year}') and name like '%#{user_name}%' group by name"
440
+ else
441
+ sql_by_name = "SELECT name, count(*) as name_count FROM `educode_sales_attendances` WHERE (attendance_date >= '#{Time.now.beginning_of_year}' and attendance_date <= '#{Time.now.end_of_year}') group by name order by name_count desc limit 30"
442
+ end
443
+ visit_count = EducodeSales::Attendance.find_by_sql(sql_by_name).map{|d| [d.name, d.name_count]}
444
+ #年拜访量前30的用户名
445
+ top_thirty_username = visit_count.map{ |d| d[0]}
446
+ @visit_count_data = visit_user_type_name(top_thirty_username, sort_by, visit_type, title_names)
447
+ else
448
+ if user_name.present?
449
+ sql_by_customer = "SELECT name, customer, count(*) as customer_count FROM `educode_sales_attendances` WHERE (attendance_date >= '#{Time.now.beginning_of_year}' and attendance_date <= '#{Time.now.end_of_year}') and name like '%#{user_name}%' group by customer order by customer_count desc limit 30"
450
+ else
451
+ sql_by_customer = "SELECT name, customer, count(*) as customer_count FROM `educode_sales_attendances` WHERE (attendance_date >= '#{Time.now.beginning_of_year}' and attendance_date <= '#{Time.now.end_of_year}') group by customer order by customer_count desc limit 30"
452
+ end
453
+ visit_count = EducodeSales::Attendance.find_by_sql(sql_by_customer).map{|d| [d.customer, d.customer_count]}
454
+ #年拜访量前30的用户名
455
+ top_thirty_customer = visit_count.map{ |d| d[0]}
456
+ @visit_count_data = visit_user_type_customer(top_thirty_customer, sort_by, visit_type, title_names)
457
+ end
458
+ render json: {data: @visit_count_data }
459
+ end
460
+ end
461
+ end
462
+
420
463
  private
421
464
 
422
465
  def sale_trend_params
@@ -802,5 +845,64 @@ module EducodeSales
802
845
  @forecast_count_data_1 = @forecast_count_data[1]
803
846
  end
804
847
 
848
+ def visit_user_type_name(top_thirty_username, sort_by, visit_type, title_names)
849
+ #本年拜访数
850
+ visit_count_year = EducodeSales::Attendance.where("name in (?)", top_thirty_username)
851
+ .where(" attendance_date >= '#{Time.now.beginning_of_year}' and attendance_date <= '#{Time.now.end_of_year}' ")
852
+ .group(:name).select("name, count(*) name_count").order("name_count #{sort_by}")&.map{ |d| [d.name, d.name_count]}
853
+
854
+ #本季拜访数
855
+ current_year = Time.now.year
856
+ current_month = Time.now.month
857
+ start_month = (current_month - 1) / 3 * 3 + 1
858
+ end_month = start_month + 2
859
+ start_date = Date.new(current_year, start_month, 1).strftime("%Y-%m-%d") + " 00:00:00"
860
+ end_date = Date.new(current_year, end_month, -1).strftime("%Y-%m-%d") + " 23:59:59"
861
+ visit_count_season = EducodeSales::Attendance.where("name in (?)", top_thirty_username)
862
+ .where("attendance_date >= '#{start_date}' and attendance_date <= '#{end_date}'")
863
+ .group(:name).select("name, count(*) name_count").order("name_count #{sort_by}")&.map{ |d| [d.name, d.name_count]}
864
+
865
+ #本月拜访数
866
+ visit_count_month = EducodeSales::Attendance.where("name in (?)", top_thirty_username)
867
+ .where("attendance_date >= '#{Time.now.beginning_of_month}' and attendance_date <= '#{Time.now.end_of_month}'")
868
+ .group(:name).select("name, count(*) name_count").order("name_count #{sort_by}")&.map{ |d| [d.name, d.name_count]}
869
+
870
+ #本周拜访数
871
+ visit_count_week = EducodeSales::Attendance.where("name in (?)", top_thirty_username)
872
+ .where("attendance_date >= '#{Time.now.beginning_of_week}' and attendance_date <= '#{Time.now.end_of_week}'")
873
+ .group(:name).select("name, count(*) name_count").order("name_count #{sort_by}")&.map{ |d| [d.name, d.name_count]}
874
+
875
+ visit_analysis_charts(visit_count_year, visit_count_season, visit_count_month, visit_count_week, visit_type, title_names)
876
+ end
877
+
878
+ def visit_user_type_customer(top_thirty_customer, sort_by, visit_type, title_names)
879
+ #本年拜访数
880
+ visit_count_year = EducodeSales::Attendance.where("customer in (?)", top_thirty_customer)
881
+ .where(" attendance_date >= '#{Time.now.beginning_of_year}' and attendance_date <= '#{Time.now.end_of_year}' ")
882
+ .group(:customer).select("customer, count(*) customer_count").order("customer_count #{sort_by}")&.map{ |d| [d.customer, d.customer_count]}
883
+
884
+ #本季拜访数
885
+ current_year = Time.now.year
886
+ current_month = Time.now.month
887
+ start_month = (current_month - 1) / 3 * 3 + 1
888
+ end_month = start_month + 2
889
+ start_date = Date.new(current_year, start_month, 1).strftime("%Y-%m-%d") + " 00:00:00"
890
+ end_date = Date.new(current_year, end_month, -1).strftime("%Y-%m-%d") + " 23:59:59"
891
+ visit_count_season = EducodeSales::Attendance.where("customer in (?)", top_thirty_customer)
892
+ .where("attendance_date >= '#{start_date}' and attendance_date <= '#{end_date}'")
893
+ .group(:customer).select("customer, count(*) customer_count").order("customer_count #{sort_by}")&.map{ |d| [d.customer, d.customer_count]}
894
+
895
+ #本月拜访数
896
+ visit_count_month = EducodeSales::Attendance.where("customer in (?)", top_thirty_customer)
897
+ .where("attendance_date >= '#{Time.now.beginning_of_month}' and attendance_date <= '#{Time.now.end_of_month}'")
898
+ .group(:customer).select("customer, count(*) customer_count").order("customer_count #{sort_by}")&.map{ |d| [d.customer, d.customer_count]}
899
+
900
+ #本周拜访数
901
+ visit_count_week = EducodeSales::Attendance.where("customer in (?)", top_thirty_customer)
902
+ .where("attendance_date >= '#{Time.now.beginning_of_week}' and attendance_date <= '#{Time.now.end_of_week}'")
903
+ .group(:customer).select("customer, count(*) customer_count").order("customer_count #{sort_by}")&.map{ |d| [d.customer, d.customer_count]}
904
+
905
+ visit_analysis_charts(visit_count_year, visit_count_season, visit_count_month, visit_count_week, visit_type, title_names)
906
+ end
805
907
  end
806
908
  end
@@ -247,6 +247,86 @@ module EducodeSales
247
247
  [hash_a, hash_b]
248
248
  end
249
249
 
250
+ def visit_analysis_charts(visit_count_year, visit_count_season, visit_count_month, visit_count_week, visit_type, title_names)
251
+ names = visit_count_year.map{|d| d[0]}
252
+
253
+ visit_count_season_data = []
254
+ names.each do |name|
255
+ data = visit_count_season.find { |d| d[0] == name}
256
+ if data
257
+ visit_count_season_data << data
258
+ else
259
+ visit_count_season_data << [name, 0]
260
+ end
261
+ end
262
+
263
+ visit_count_month_data = []
264
+ names.each do |name|
265
+ data = visit_count_month.find { |d| d[0] == name}
266
+ if data
267
+ visit_count_month_data << data
268
+ else
269
+ visit_count_month_data << [name, 0]
270
+ end
271
+ end
272
+
273
+ visit_count_week_data = []
274
+ names.each do |name|
275
+ data = visit_count_week.find { |d| d[0] == name}
276
+ if data
277
+ visit_count_week_data << data
278
+ else
279
+ visit_count_week_data << [name, 0]
280
+ end
281
+ end
282
+
283
+ year = {
284
+ label: title_names[0],
285
+ data: visit_count_year.map {|d| d[1].to_i},
286
+ backgroundColor: 'rgba(255, 99, 132, 1)'}
287
+
288
+ season = {
289
+ label: title_names[1],
290
+ data: visit_count_season_data.map {|d| d[1].to_i},
291
+ backgroundColor: 'rgba(255, 159, 64, 1)'}
292
+
293
+ month = {
294
+ label: title_names[2],
295
+ data:visit_count_month_data.map {|d| d[1].to_i},
296
+ backgroundColor: 'rgba(54, 162, 235, 1)'}
297
+
298
+ week = {
299
+ label: title_names[3],
300
+ data: visit_count_week_data.map {|d| d[1].to_i},
301
+ backgroundColor: 'rgba(153, 102, 255, 1)'}
302
+
303
+ final_data = []
304
+ if visit_type.include?("1")
305
+ final_data << year
306
+ end
307
+ if visit_type.include?("2")
308
+ final_data << season
309
+ end
310
+ if visit_type.include?("3")
311
+ final_data << month
312
+ end
313
+ if visit_type.include?("4")
314
+ final_data << week
315
+ end
316
+
317
+ if visit_type.present?
318
+ {
319
+ labels: names,
320
+ datasets: final_data
321
+ }
322
+ else
323
+ {
324
+ labels: names,
325
+ datasets: [year, season, month, week]
326
+ }
327
+ end
328
+ end
329
+
250
330
  private
251
331
 
252
332
  def plan_get(staff_id, time_range, type, property)
@@ -9,5 +9,7 @@ module EducodeSales
9
9
  '#DC7633', '#839192', '#6C3483', '#B03A2E', '#7B7D7D', '#4D5656', '#28B463', '#0E6655', '#F39C12', '#0E6251', '#1B4F72',
10
10
  '#FAE5D3', '#82E0AA', '#FF00FF', '#663399', '#4B0082', '#7CFC00'
11
11
  ]
12
+
13
+ VISIT_TYPE = [["本年拜访数", 1],["本季拜访数", 2],["本月拜访数", 3],["本周拜访数", 4]]
12
14
  end
13
15
  end
@@ -0,0 +1,187 @@
1
+ <div id="tab_8">
2
+ <div class="" style="padding-right: 50px">
3
+ <div style="margin: 10px 10px 10px 10px">
4
+ <form class="layui-form layui-form-pane" lay-filter="search_visit_form">
5
+ <div class="layui-form-item">
6
+ <div class="layui-inline m-t-10">
7
+ <label class="layui-form-label">维度</label>
8
+ <div class="layui-input-inline">
9
+ <%= select_tag "user_type", options_for_select([['按销售经理','name'],['按客户','customer']],params[:user_type]), {'lay-filter': 'user_type'}%>
10
+ </div>
11
+ </div>
12
+ <div class="layui-inline m-t-10">
13
+ <label class="layui-form-label">拜访统计</label>
14
+ <div class="layui-input-inline">
15
+ <div id="visit_type"></div>
16
+ </div>
17
+ </div>
18
+ <div class="layui-inline m-t-10">
19
+ <label class="layui-form-label">销售经理</label>
20
+ <div class="layui-input-inline">
21
+ <div id="user_name"></div>
22
+ </div>
23
+ </div>
24
+ <div class="layui-inline m-t-10">
25
+ <label class="layui-form-label">排序</label>
26
+ <div class="layui-input-inline">
27
+ <%= select_tag "sort_by", options_for_select([['', ''], ['升序', 'asc'], ['降序', 'desc']], params[:sort_by]), { include_blank: true } %>
28
+ </div>
29
+ </div>
30
+ <div class="layui-inline">
31
+ <button type="reset" class="layui-btn layui-btn-primary" lay-submit lay-filter="reset_visit_search">重 置</button>
32
+ <button type="submit" class="layui-btn layui-btn-primary" lay-submit lay-filter="search_visit">搜 索</button>
33
+ </div>
34
+ </div>
35
+ </form>
36
+ </div>
37
+ <canvas id="visit_myChart" width="960" height="350"></canvas>
38
+ <div class="two-header" style="margin-top: 30px;">
39
+ <table id="visit_table" lay-filter="visit_table"></table>
40
+ </div>
41
+ </div>
42
+ </div>
43
+ <script>
44
+ layui.use(['form', 'jquery', 'request', 'element', 'laydate', 'table', 'miniPage'], function () {
45
+ var $ = layui.jquery,
46
+ form = layui.form,
47
+ table = layui.table,
48
+ request = layui.request;
49
+
50
+ //拜访统计选择
51
+ var visit_type_select = xmSelect.render({
52
+ el: '#visit_type',
53
+ name: 'visit_type',
54
+ data: <%=raw @visit_types.to_json %>,
55
+ });
56
+ //销售经理选择
57
+ var user_name_select = xmSelect.render({
58
+ el: '#user_name',
59
+ name: 'user_name',
60
+ data: <%=raw @user_names.to_json %>,
61
+ filterable: true,
62
+ radio: true
63
+ });
64
+
65
+ var options = {
66
+ events: false,
67
+ scales: {
68
+ yAxes: [{
69
+ ticks: {
70
+ suggestedMin: 0,
71
+ suggestedMax: 200,
72
+ stepSize: 20
73
+ }
74
+ }]
75
+ },
76
+ hover: {
77
+ animationDuration: 1
78
+ },
79
+ animation: {
80
+ duration: 1,
81
+ onComplete: function () {
82
+ var chartInstance = this.chart,
83
+ ctx = chartInstance.ctx;
84
+ ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
85
+ ctx.textAlign = 'center';
86
+ ctx.textBaseline = 'bottom';
87
+
88
+ this.data.datasets.forEach(function (dataset, i) {
89
+ var meta = chartInstance.controller.getDatasetMeta(i);
90
+ meta.data.forEach(function (bar, index) {
91
+ var data = dataset.data[index];
92
+ ctx.fillText(data, bar._model.x, bar._model.y - 5);
93
+ });
94
+ });
95
+ }
96
+ }
97
+ };
98
+
99
+ visit_count_data = <%=raw @visit_count_data.to_json %>;
100
+
101
+ //条形图
102
+ var ctx = document.getElementById('visit_myChart').getContext("2d");
103
+ var visit_myChart = new Chart(ctx, {
104
+ type: 'bar',
105
+ data: visit_count_data,
106
+ options: options
107
+ });
108
+
109
+ //重置按钮
110
+ form.on('submit(reset_visit_search)', function () {
111
+ form.val('search_visit_form', {
112
+ sort_by: ""
113
+ });
114
+ visit_type_select.setValue([]);
115
+ user_name_select.setValue([]);
116
+ return false;
117
+ });
118
+
119
+ //渲染表格
120
+ function renderTable(visit_count_data) {
121
+ var labels = [];
122
+ fields = [{field: 'col0', title: '', width:100}];
123
+ visit_count_data.labels.forEach(function (data, i) {
124
+ labels.push(data);
125
+ fields.push({field: 'col' + (i + 1), title: data, width: 100, align: 'center'})
126
+ });
127
+ var table_data = [];
128
+ visit_count_data.datasets.forEach(function (visit_data) {
129
+ var value = {};
130
+ value['col0'] = visit_data.label;
131
+ visit_data.data.forEach(function (v, i) {
132
+ value['col' + (i + 1)] = v
133
+ });
134
+ table_data.push(value)
135
+ });
136
+ table.render({
137
+ elem: '#visit_table',
138
+ height: 230,
139
+ limit: 1000,
140
+ page: false,
141
+ data: table_data,
142
+ cols: [fields]
143
+ });
144
+ }
145
+
146
+ renderTable(visit_count_data);
147
+ form.render();
148
+
149
+ //搜索监听
150
+ form.on("submit(search_visit)", function(data) {
151
+ var layer_index = layer.load(0, {shade: [0.1, '#fff']});
152
+ var visit_type_value = [];
153
+ if (document.getElementById('visit_type')) {
154
+ visit_type_select.getValue().forEach(function (d) {
155
+ visit_type_value.push(d.value)
156
+ })
157
+ }
158
+ data.field.visit_type = visit_type_value.join(",");
159
+ Rails.ajax({
160
+ url: '/missions/sale_trends/visit_analysis',
161
+ type: 'GET',
162
+ dataType: "json",
163
+ data: $.param(data.field, true),
164
+ success: function (res) {
165
+ visit_myChart.data.datasets = res.data.datasets;
166
+ visit_myChart.data.labels = res.data.labels;
167
+ visit_myChart.update();
168
+ renderTable(res.data);
169
+ layer.close(layer_index);
170
+
171
+ }
172
+ });
173
+ return false;
174
+ });
175
+ });
176
+ </script>
177
+
178
+
179
+
180
+
181
+
182
+
183
+
184
+
185
+
186
+
187
+
@@ -7,6 +7,7 @@
7
7
  <li class="">销售人员跟进分析</li>
8
8
  <li class="">中标预测图</li>
9
9
  <li class="">用户分析</li>
10
+ <li class="">拜访分析</li>
10
11
  </ul>
11
12
  <div class="layui-tab-content">
12
13
  <div class="layui-tab-item layui-show">
@@ -238,6 +239,9 @@
238
239
  <div class="layui-tab-item">
239
240
  <div id="page_7"></div>
240
241
  </div>
242
+ <div class="layui-tab-item">
243
+ <div id="page_8"></div>
244
+ </div>
241
245
  </div>
242
246
  </div>
243
247
 
@@ -264,6 +268,8 @@
264
268
  loadPage('/missions/sale_trends/goal_forecast')
265
269
  } else if (data.index == 6 && $("#tab_7").length == 0) {
266
270
  loadPage('/missions/sale_trends/user_stat')
271
+ } else if (data.index == 7 && $("#tab_8").length == 0) {
272
+ loadPage('/missions/sale_trends/visit_analysis')
267
273
  }
268
274
  });
269
275
 
@@ -0,0 +1 @@
1
+ $("#page_8").html("<%= j render 'visit_analysis' %>");
data/config/routes.rb CHANGED
@@ -173,6 +173,7 @@ EducodeSales::Engine.routes.draw do
173
173
  get :sales_followup_analysis
174
174
  get :goal_forecast
175
175
  get :user_stat
176
+ get :visit_analysis
176
177
  end
177
178
  end
178
179
 
@@ -1,3 +1,3 @@
1
1
  module EducodeSales
2
- VERSION = '1.10.22'
2
+ VERSION = '1.10.23'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: educode_sales
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.22
4
+ version: 1.10.23
5
5
  platform: ruby
6
6
  authors:
7
7
  - anke1460
@@ -574,6 +574,7 @@ files:
574
574
  - app/views/educode_sales/sale_trends/_sales_analysis.html.erb
575
575
  - app/views/educode_sales/sale_trends/_sales_followup_analysis.html.erb
576
576
  - app/views/educode_sales/sale_trends/_user_stat.html.erb
577
+ - app/views/educode_sales/sale_trends/_visit_analysis.html.erb
577
578
  - app/views/educode_sales/sale_trends/business_area.js.erb
578
579
  - app/views/educode_sales/sale_trends/business_followup_analysis.js.erb
579
580
  - app/views/educode_sales/sale_trends/goal_forecast.js.erb
@@ -583,6 +584,7 @@ files:
583
584
  - app/views/educode_sales/sale_trends/trends.html.erb
584
585
  - app/views/educode_sales/sale_trends/trends.json.jbuilder
585
586
  - app/views/educode_sales/sale_trends/user_stat.js.erb
587
+ - app/views/educode_sales/sale_trends/visit_analysis.js.erb
586
588
  - app/views/educode_sales/sales/index.html.erb
587
589
  - app/views/educode_sales/sales/index.json.jbuilder
588
590
  - app/views/educode_sales/sales/operations.html.erb