educode_sales 1.10.21 → 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: 9d2ef3de0cf042aac3ccbab794698672f1023a85ca02955c411b4edf4f9a20c9
4
- data.tar.gz: 3c5c9fcb1bbeb580f6869ef75016007de086c3d4a684cfe6cf8982c842e026bc
3
+ metadata.gz: ac157bfbdbc5c1aceeef3b0d0af4b81e74b6835ddda09a5beae4188f23720391
4
+ data.tar.gz: a4f7c4077fc9af0f5374fc3efec8bf42e5c3a57a27dc78090a5727cabe2f5510
5
5
  SHA512:
6
- metadata.gz: 10cd26f67854df2f38eba390682d6372101a9796a9854c11db94f1c639e2173efd704c0204fca396bb72d2f1a056a7970f53d67bba2873f19025c88f0d673d7d
7
- data.tar.gz: 4213ae7c4af6f959a5baf3fd30f12c622707b58480fe7eb2894e3d31220a4a433a046a989ff19ceff78ae6f5e0323f53e4954af1c2d209b1703233e196662338
6
+ metadata.gz: 804531ab845025fe61054b79b248a5f1f83e4194d0c23cad2f0fb4c49978db71eb695815723d50e7255fa35a4aa0b0154babb156fdd5cd953808bb2a1b56a9e9
7
+ data.tar.gz: 13484d3b014be703413f41b03938881aeb56bd1b7cf97f721f055f9a0aa869dfedc6b948ddbd57bb7b3174c2e3aa171dc7efa5823821f3e2b903e1e1ec9b2591
@@ -3,7 +3,35 @@ require_dependency "educode_sales/application_controller"
3
3
  module EducodeSales
4
4
  class IdeasController < ApplicationController
5
5
 
6
- before_action :find_idea, only: [:edit, :destroy, :detail, :history, :update]
6
+ before_action :find_idea, only: [:edit, :destroy, :detail, :history, :update, :assign, :assign_staff, :assign_sale_staff, :update_sale_staff]
7
+
8
+ def assign
9
+ selected_staff_ids = @idea.assist_staff_ids.map(&:to_i)
10
+ staffs = Staff.where.not(role_id: 11).includes(:user)
11
+ gon.ideas_staffs = staffs.map { |d| { name: d.user.real_name, value: d.id, selected: selected_staff_ids.include?(d.id) } }
12
+ render layout: false
13
+ end
14
+
15
+ # 指派协作人 assist_staff_ids协作人
16
+ def assign_staff
17
+ @idea.assist_staff_ids = params[:to_id].to_s.split(",")
18
+ @idea.save
19
+ render_success
20
+ end
21
+
22
+ def assign_sale_staff
23
+ selected_staff_ids = Array(@idea.staff_id)
24
+ staffs = Staff.where.not(role_id: 11).includes(:user)
25
+ gon.sales_staffs = staffs.map { |d| { name: d.user.real_name, value: d.id, selected: selected_staff_ids.include?(d.id) } }
26
+ render layout: false
27
+ end
28
+
29
+ # 指派方案经理 staff_id
30
+ def update_sale_staff
31
+ @idea.staff_id = params[:to_id]
32
+ @idea.save
33
+ render_success
34
+ end
7
35
 
8
36
  def index
9
37
  respond_to do |format|
@@ -24,16 +52,14 @@ module EducodeSales
24
52
  level = @current_admin.role.role_areas.find_by(clazz: '方案管理').try(:level)
25
53
  case level
26
54
  when '自己'
27
- # business_ids = Business.joins(last_follow_up: :assign_follow_ups).where("educode_sales_assign_follow_ups.staff_id = ?", @current_admin.id).pluck(:id)
28
- # @businesses = Business.where("educode_sales_businesses.staff_id = ? OR educode_sales_businesses.id in (?)", @current_admin.id, business_ids)
29
- idea_ids = Idea.all.select { |d| Array(d.other_staff_ids).include?(@current_admin.id) }.map { |d| d.id }
55
+ idea_ids = Idea.all.select { |d| Array(d.other_staff_ids).include?(@current_admin.id) || d.sale_staff_id == @current_admin.id || Array(d.assist_staff_ids).include?(@current_admin.id) || d.staff_id == @current_admin.id }.map { |d| d.id }
30
56
  @ideas = Idea.where("educode_sales_ideas.creator_id = ? OR educode_sales_ideas.id in (?)", @current_admin.id, idea_ids)
31
57
  when '区域'
32
58
  # 查看区域商机,需要排除掉其它人员手上的监管学校
33
59
  other_staff_school_id = EducodeSales::StaffSchool.where.not(staff_id: @current_admin.id).where("school_id IN (SELECT school_id FROM educode_sales_staff_schools WHERE staff_id = #{@current_admin.id}) IS NOT TRUE").distinct.pluck :school_id
34
60
 
35
61
  school_ids = School.where(province: @current_admin.areas.pluck(:name)).pluck(:id) + StaffSchool.where(staff_id: @current_admin.id).pluck(:school_id) - other_staff_school_id
36
- idea_ids = Idea.all.select { |d| Array(d.other_staff_ids).include?(@current_admin.id) }.map { |d| d.id }
62
+ idea_ids = Idea.all.select { |d| Array(d.other_staff_ids).include?(@current_admin.id) || d.sale_staff_id == @current_admin.id || Array(d.assist_staff_ids).include?(@current_admin.id) || d.staff_id == @current_admin.id }.map { |d| d.id }
37
63
  @ideas = @ideas.joins(department: :school).where("schools.id in (?) OR educode_sales_ideas.creator_id = ? OR educode_sales_ideas.id in (?)", school_ids, @current_admin.id, idea_ids)
38
64
  else
39
65
  @ideas = @ideas
@@ -116,8 +142,8 @@ module EducodeSales
116
142
  idea.department_id = idea.business&.department_id
117
143
  end
118
144
  idea.attachment_ids = attachment_ids
119
- idea.assist_staff_ids = assist_staff_ids
120
- idea.other_staff_ids = other_staff_ids
145
+ # idea.assist_staff_ids = assist_staff_ids
146
+ # idea.other_staff_ids = other_staff_ids
121
147
  idea.save
122
148
  render_success
123
149
  end
@@ -134,11 +160,11 @@ module EducodeSales
134
160
  @idea.assign_attributes(idea_params)
135
161
  # @idea.school_id = Department.find_by_id(@idea.department_id)&.school_id
136
162
  assist_staff_ids = Array(params[:assist_staff_ids].to_s.split(","))
137
- @idea.assist_staff_ids = assist_staff_ids
163
+ # @idea.assist_staff_ids = assist_staff_ids
138
164
  attachment_ids = Array(params[:attachment_ids].to_s.split(","))
139
165
  @idea.attachment_ids = attachment_ids
140
166
  other_staff_ids = Array(params[:other_staff_ids].to_s.split(","))
141
- @idea.other_staff_ids = other_staff_ids
167
+ # @idea.other_staff_ids = other_staff_ids
142
168
  if @idea.business_id.present?
143
169
  @idea.school_id = @idea.business&.department&.school_id
144
170
  @idea.department_id = @idea.business&.department_id
@@ -267,7 +293,7 @@ module EducodeSales
267
293
  params.permit(:name, :level, :staff_id,
268
294
  :status, :types, :model, :hardware, :project,
269
295
  :money, :end_time, :content, :department_id, :school_id,
270
- :manager_name, :manager_phone, :school_name, :department_name, :sale_staff_id, :attachment_id, :idea_type, :business_id)
296
+ :manager_name, :manager_phone, :school_name, :department_name, :attachment_id, :idea_type, :business_id)
271
297
  end
272
298
 
273
299
  def find_idea
@@ -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
@@ -102,6 +102,8 @@
102
102
  <a class="layui-btn layui-btn-normal layui-btn-xs data-count-edit" lay-event="idea_recycle_s">恢复</a>
103
103
  <% end %>
104
104
  {{# }else{}}
105
+ <a class="layui-btn layui-btn-normal layui-btn-xs data-count-edit" lay-event="assign">指派协作人</a>
106
+ <a class="layui-btn layui-btn-normal layui-btn-xs data-count-edit" lay-event="assign_sale_staff">指派方案经理</a>
105
107
  <% if can? :add_follow, EducodeSales::Idea %>
106
108
  <a class="layui-btn layui-btn-normal layui-btn-xs data-count-add_follow" lay-event="add_follows">添加跟进</a>
107
109
  <% end %>
@@ -256,7 +258,7 @@
256
258
  },
257
259
  {
258
260
  title: '操作',
259
- minWidth: 500,
261
+ minWidth: 700,
260
262
  toolbar: '#currentTableBar',
261
263
  align: "center",
262
264
  fixed: 'right'
@@ -453,6 +455,40 @@
453
455
  $(window).on("resize", function () {
454
456
  layer.full(followup_index);
455
457
  });
458
+ } else if (obj.event === 'assign') { //协作人
459
+ var content = miniPage.getHrefContent('/missions/ideas/' + id + '/assign');
460
+ var openWH = miniPage.getOpenWidthHeight();
461
+ var name = data.name;
462
+ sindex = layer.open({
463
+ title: '指派协作人',
464
+ type: 1,
465
+ shade: 0.2,
466
+ maxmin: true,
467
+ shadeClose: true,
468
+ area: ['600px', '300px'],
469
+ content: content
470
+ });
471
+ $(window).on("resize", function () {
472
+ layer.full(sindex);
473
+ });
474
+ return false;
475
+ } else if (obj.event === 'assign_sale_staff') { //指派方案经理
476
+ var content = miniPage.getHrefContent('/missions/ideas/' + id + '/assign_sale_staff');
477
+ var openWH = miniPage.getOpenWidthHeight();
478
+ var name = data.name;
479
+ sindex = layer.open({
480
+ title: "指派方案经理",
481
+ type: 1,
482
+ shade: 0.2,
483
+ maxmin: true,
484
+ shadeClose: true,
485
+ area: ['600px', '300px'],
486
+ content: content
487
+ });
488
+ $(window).on("resize", function () {
489
+ layer.full(sindex);
490
+ });
491
+ return false;
456
492
  } else if (obj.event === 'idea_recycle') {
457
493
  layer.confirm('确定删除' + data.name, function (index) {
458
494
  request.delete('missions/ideas/' + id, {}, function (res) {
@@ -0,0 +1,45 @@
1
+ <%= Gon::Base.render_data %>
2
+ <div class="layui-form layuimini-form" style="padding:30px">
3
+ <div class="layui-form-item">
4
+ <label class="layui-form-label required">选择协作人:</label>
5
+ <div class="layui-input-block" style="width: 300px">
6
+ <div id="sales_staff_id"></div>
7
+ </div>
8
+ </div>
9
+ <hr>
10
+ <div class="layui-form-item">
11
+ <div class="layui-input-block">
12
+ <button class="layui-btn layui-btn-normal" lay-submit lay-filter="saveBtn">确认保存</button>
13
+ </div>
14
+ </div>
15
+ </div>
16
+
17
+ <script>
18
+ layui.use(['form', 'table', 'upload', 'laytpl', 'request', 'selectInput'], function () {
19
+ var form = layui.form,
20
+ layer = layui.layer,
21
+ table = layui.table,
22
+ laytpl = layui.laytpl,
23
+ request = layui.request,
24
+ $ = layui.$;
25
+
26
+ form.render();
27
+ staff_list_select = xmSelect.render({
28
+ el: '#sales_staff_id',
29
+ data: gon.ideas_staffs,
30
+ filterable: true,
31
+ radio: false,
32
+ })
33
+ var parentIndex = layer.index;
34
+ form.on('submit(saveBtn)', function (data) {
35
+ layer.confirm('确定指派协作人?', function (index) {
36
+ request.post('missions/ideas/' + parent.id + "/assign_staff", {to_id: staff_list_select.getValue('valueStr')}, function (res) {
37
+ layer.close(index);
38
+ layer.close(parentIndex)
39
+ parent.table.reload('ideas_table')
40
+ })
41
+ });
42
+ return false;
43
+ });
44
+ });
45
+ </script>
@@ -0,0 +1,45 @@
1
+ <%= Gon::Base.render_data %>
2
+ <div class="layui-form layuimini-form" style="padding:30px">
3
+ <div class="layui-form-item">
4
+ <label class="layui-form-label required">选择方案经理:</label>
5
+ <div class="layui-input-block" style="width: 300px">
6
+ <div id="sales_id"></div>
7
+ </div>
8
+ </div>
9
+ <hr>
10
+ <div class="layui-form-item">
11
+ <div class="layui-input-block">
12
+ <button class="layui-btn layui-btn-normal" lay-submit lay-filter="saveBtn">确认保存</button>
13
+ </div>
14
+ </div>
15
+ </div>
16
+
17
+ <script>
18
+ layui.use(['form', 'table', 'upload', 'laytpl', 'request', 'selectInput'], function () {
19
+ var form = layui.form,
20
+ layer = layui.layer,
21
+ table = layui.table,
22
+ laytpl = layui.laytpl,
23
+ request = layui.request,
24
+ $ = layui.$;
25
+
26
+ form.render();
27
+ staff_list_select = xmSelect.render({
28
+ el: '#sales_id',
29
+ data: gon.sales_staffs,
30
+ filterable: true,
31
+ radio: true,
32
+ })
33
+ var parentIndex = layer.index;
34
+ form.on('submit(saveBtn)', function (data) {
35
+ layer.confirm('确定指派方案经理?', function (index) {
36
+ request.post('missions/ideas/' + parent.id + "/update_sale_staff", {to_id: staff_list_select.getValue('valueStr')}, function (res) {
37
+ layer.close(index);
38
+ layer.close(parentIndex)
39
+ parent.table.reload('ideas_table')
40
+ })
41
+ });
42
+ return false;
43
+ });
44
+ });
45
+ </script>
@@ -41,20 +41,20 @@
41
41
  </div>
42
42
  </div>
43
43
  <div class="layui-col-md6">
44
- <labeL class="layui-form-label">协作人:</labeL>
44
+ <labeL class="layui-form-label required">项目名称:</labeL>
45
45
  <div class="layui-input-block">
46
- <div id="assist_staff_ids"></div>
46
+ <div id="business_id" style="width: 600px;"></div>
47
47
  </div>
48
48
  </div>
49
- </div>
50
- <div class="layui-row" style="padding-top: 15px">
51
- <div class="layui-col-md6">
52
- <labeL class="layui-form-label required">项目名称:</labeL>
49
+ <div class="layui-col-md6" style="display: none">
50
+ <labeL class="layui-form-label">协作人:</labeL>
53
51
  <div class="layui-input-block">
54
- <div id="business_id" style="width: 600px;"></div>
52
+ <div id="assist_staff_ids"></div>
55
53
  </div>
56
54
  </div>
57
- <div class="layui-col-md6">
55
+ </div>
56
+ <div class="layui-row" style="padding-top: 15px;display: none">
57
+ <div class="layui-col-md6" style="display: none">
58
58
  <labeL class="layui-form-label">方案经理:</labeL>
59
59
  <div class="layui-input-block">
60
60
  <div id="new_staff_id"></div>
@@ -96,7 +96,7 @@
96
96
  <%= select_tag "idea_type", options_for_select(EducodeSales::Idea.idea_types.keys, @idea&.idea_type), { 'lay-filter': 'idea_type', include_blank: false } %>
97
97
  </div>
98
98
  </div>
99
- <div class="layui-col-md6">
99
+ <div class="layui-col-md6" style="display: none">
100
100
  <labeL class="layui-form-label">指派人:</labeL>
101
101
  <div class="layui-input-block">
102
102
  <div id="other_staff_ids"></div>
@@ -41,20 +41,20 @@
41
41
  </div>
42
42
  </div>
43
43
  <div class="layui-col-md6">
44
- <labeL class="layui-form-label">协作人:</labeL>
44
+ <labeL class="layui-form-label required">项目名称:</labeL>
45
45
  <div class="layui-input-block">
46
- <div id="assist_staff_ids"></div>
46
+ <div id="business_id" style="width: 600px;"></div>
47
47
  </div>
48
48
  </div>
49
- </div>
50
- <div class="layui-row" style="padding-top: 15px">
51
- <div class="layui-col-md6">
52
- <labeL class="layui-form-label required">项目名称:</labeL>
49
+ <div class="layui-col-md6" style="display: none">
50
+ <labeL class="layui-form-label">协作人:</labeL>
53
51
  <div class="layui-input-block">
54
- <div id="business_id" style="width: 600px;"></div>
52
+ <div id="assist_staff_ids"></div>
55
53
  </div>
56
54
  </div>
57
- <div class="layui-col-md6">
55
+ </div>
56
+ <div class="layui-row" style="padding-top: 15px;display: none">
57
+ <div class="layui-col-md6" style="display: none">
58
58
  <labeL class="layui-form-label">方案经理:</labeL>
59
59
  <div class="layui-input-block">
60
60
  <div id="new_staff_id"></div>
@@ -96,7 +96,7 @@
96
96
  <%= select_tag "idea_type", options_for_select(EducodeSales::Idea.idea_types.keys, @idea&.idea_type), { 'lay-filter': 'idea_type', include_blank: false } %>
97
97
  </div>
98
98
  </div>
99
- <div class="layui-col-md6">
99
+ <div class="layui-col-md6" style="display: none">
100
100
  <labeL class="layui-form-label">指派人:</labeL>
101
101
  <div class="layui-input-block">
102
102
  <div id="other_staff_ids"></div>
@@ -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
 
@@ -383,6 +384,10 @@ EducodeSales::Engine.routes.draw do
383
384
  get :upload_file
384
385
  end
385
386
  member do
387
+ get :assign
388
+ post :assign_staff
389
+ get :assign_sale_staff
390
+ post :update_sale_staff
386
391
  get :show_schools
387
392
  post :follow_up
388
393
  put :update_advise
@@ -1,3 +1,3 @@
1
1
  module EducodeSales
2
- VERSION = '1.10.21'
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.21
4
+ version: 1.10.23
5
5
  platform: ruby
6
6
  authors:
7
7
  - anke1460
@@ -418,6 +418,8 @@ files:
418
418
  - app/views/educode_sales/ideas/add_courses.html.erb
419
419
  - app/views/educode_sales/ideas/add_event.html.erb
420
420
  - app/views/educode_sales/ideas/add_keys.html.erb
421
+ - app/views/educode_sales/ideas/assign.html.erb
422
+ - app/views/educode_sales/ideas/assign_sale_staff.html.erb
421
423
  - app/views/educode_sales/ideas/course_list.json.jbuilder
422
424
  - app/views/educode_sales/ideas/course_subject.json.jbuilder
423
425
  - app/views/educode_sales/ideas/daily_paper.html.erb
@@ -572,6 +574,7 @@ files:
572
574
  - app/views/educode_sales/sale_trends/_sales_analysis.html.erb
573
575
  - app/views/educode_sales/sale_trends/_sales_followup_analysis.html.erb
574
576
  - app/views/educode_sales/sale_trends/_user_stat.html.erb
577
+ - app/views/educode_sales/sale_trends/_visit_analysis.html.erb
575
578
  - app/views/educode_sales/sale_trends/business_area.js.erb
576
579
  - app/views/educode_sales/sale_trends/business_followup_analysis.js.erb
577
580
  - app/views/educode_sales/sale_trends/goal_forecast.js.erb
@@ -581,6 +584,7 @@ files:
581
584
  - app/views/educode_sales/sale_trends/trends.html.erb
582
585
  - app/views/educode_sales/sale_trends/trends.json.jbuilder
583
586
  - app/views/educode_sales/sale_trends/user_stat.js.erb
587
+ - app/views/educode_sales/sale_trends/visit_analysis.js.erb
584
588
  - app/views/educode_sales/sales/index.html.erb
585
589
  - app/views/educode_sales/sales/index.json.jbuilder
586
590
  - app/views/educode_sales/sales/operations.html.erb