educode_sales 1.10.21 → 1.10.23

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 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