educode_sales 1.10.41 → 1.10.48

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: 75f1104743151bb685cb17c27471acf756a43103c059b78fdbbc85d897008420
4
- data.tar.gz: 1abca2361e351da1e62f2a04e1a98c72e01f953ab653d6e6fc3904294532e38e
3
+ metadata.gz: da45d6ae994d92a3ef3274e654b591e9165ba976e765e2c8e09b786f7f0b5c05
4
+ data.tar.gz: fe907bc45b55f7dbe5b454eb785693302f460622576a7a14cde80efc9cf3d293
5
5
  SHA512:
6
- metadata.gz: b93100ae277a43e93b44ed6ba56433123a8427d44b34ec3706b09e62987698d3672b81f8322bc6fc4af43f0e4ea0b2758b71e11368b87b33d7225ca28287b0a2
7
- data.tar.gz: 1ddb1e12b4f3102d9ad751d04fc00975cd18c765fa378f454862a73e8f2927b8cc3810ad151ae06b9d1451a26bfb2604ec730822dc63a72da23449d9fe948b17
6
+ metadata.gz: 8dc1ac6fd68d7a04df6f28d39a74f565701600b25348c60a6586f3b8027f63b796132489e6f0dd37e4a896ee9241f44c5764ec5f4fb2e740b38033060c0ff10f
7
+ data.tar.gz: b3b6130b8e98a8b5bdd05281af4f7faf27e690725de86337fec94abf974b8be798f8a451ed4f549affbe8e548bd66bd485b3f177a80b70e57f74f59c49459fe1
@@ -114,11 +114,15 @@ module EducodeSales
114
114
  last_follow_up = @business.last_follow_up
115
115
  if @business.clazz.present?
116
116
  follow_up.clazz_changed = @business.clazz_id != follow_up.clazz_id
117
- if follow_up.clazz_changed
117
+ if follow_up.clazz_changed
118
118
  if @business.clazz.extras == 'a_class'
119
119
  @business.state_id = 3
120
120
  end
121
- clazz_changes = "#{@business.clazz.extras.split('_')[0]}-#{follow_up.clazz.extras.split('_')[0]}"
121
+ if @business.clazz.extras.present? && follow_up.clazz.extras.present?
122
+ clazz_changes = "#{@business.clazz.extras.split('_')[0]}-#{follow_up.clazz.extras.split('_')[0]}"
123
+ else
124
+ clazz_changes = "-"
125
+ end
122
126
  business_clazz_change = EducodeSales::BusinessClazzChange.find_or_initialize_by(business_id: @business.id, clazz_changed: clazz_changes)
123
127
  business_clazz_change.save unless business_clazz_change.persisted?
124
128
  end
@@ -510,6 +510,20 @@ module EducodeSales
510
510
  @months = (1..12).map { |d| d }
511
511
  end
512
512
 
513
+
514
+ def target_track
515
+ respond_to do |format|
516
+ format.html do
517
+
518
+ end
519
+ format.js do
520
+ common = Common.find_by(clazz: 'staff_type', name: '销售')
521
+ @staffs = Staff.joins(:user).where(job_type: common.id).map { |d| [d.user.real_name, d.id]}
522
+ gon.school_tags = SchoolTag.where(for_missions: true).map { |d| {value: d.id, name: d.name } }
523
+ end
524
+ end
525
+ end
526
+
513
527
  private
514
528
 
515
529
  def plan_params
@@ -418,6 +418,15 @@ module EducodeSales
418
418
  end
419
419
  end
420
420
 
421
+ #回款预测图
422
+ def return_money_forecast
423
+ respond_to do |format|
424
+ format.js do
425
+ return_forecast_by_money
426
+ end
427
+ end
428
+ end
429
+
421
430
  def user_stat
422
431
  respond_to do |format|
423
432
  format.html do
@@ -927,5 +936,61 @@ module EducodeSales
927
936
 
928
937
  visit_analysis_charts(visit_count_year, visit_count_season, visit_count_month, visit_count_week, visit_type, title_names)
929
938
  end
939
+
940
+
941
+ def return_forecast_by_money
942
+ property = params[:property] || nil
943
+ staff_id = params[:staff_id] || nil
944
+ @forecast_count_range = params[:forecast_count_range] || "month"
945
+ forecast_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
946
+ sale_names = %w[实际回款额 计划回款额 实际回款 计划回款额-全部 计划回款额-o类]
947
+ case @forecast_count_range
948
+ when "week"
949
+ # 年初第一天周数是0会导致周数重复计算
950
+ if params[:forecast_date_day].present?
951
+ date = params[:forecast_date_day].split(" - ")
952
+ dates = (date[0].to_date..date[1].to_date).map { |d| d.strftime("%Y-%W") }.uniq.select { |d| d.split("-")[1] != '00' }
953
+ @return_forecast_count_data = return_money_forecast_week(dates, sale_names, staff_id, property)
954
+ else
955
+ forecast_default_dates = ("#{Time.now.year}-01-01".to_date.."#{Time.now.year}-#{Time.now.month}-01".to_date).map { |d| d.strftime("%Y-%W") }.uniq.select { |d| d.split("-")[1] != '00' }
956
+ @return_forecast_count_data = return_money_forecast_week(forecast_default_dates, sale_names, staff_id, property)
957
+ end
958
+ when "quarter"
959
+ # 按年
960
+ if params[:forecast_date_year].present?
961
+ date = params[:forecast_date_year].split(" - ")
962
+ dates = (date[0]..date[1]).to_a
963
+ dates = dates.map { |d| [d.to_s + "-" + "1", d.to_s + "-" + "2", d.to_s + "-" + "3", d.to_s + "-" + "4"] }.flatten
964
+ @return_forecast_count_data = return_money_forecast_quarter(dates, sale_names, staff_id, property)
965
+ else
966
+ forecast_default_dates = ("#{Time.now.year}-01-01".to_date.."#{Time.now.year}-#{Time.now.month}-01".to_date).map { |d| d.strftime("%Y") }.uniq
967
+ forecast_default_dates = forecast_default_dates.map { |d| [d.to_s + "-" + "1", d.to_s + "-" + "2", d.to_s + "-" + "3", d.to_s + "-" + "4"] }.flatten
968
+ @return_forecast_count_data = return_money_forecast_quarter(forecast_default_dates, sale_names, staff_id, property)
969
+ end
970
+ when "month" # 按月
971
+ if params[:forecast_date_month].present?
972
+ date = params[:forecast_date_month].split(" - ")
973
+ date[0] = (date[0] + "-01").to_date.to_s
974
+ date[1] = (date[1] + "-01").to_date.end_of_month.to_s
975
+ dates = ((date[0] + "-01").to_date..(date[1] + "-01").to_date).map { |d| d.strftime("%Y-%m") }.uniq
976
+ @return_forecast_count_data = return_money_forecast_month(dates, sale_names, staff_id, property)
977
+ else
978
+ @return_forecast_count_data = return_money_forecast_month(forecast_default_dates, sale_names, staff_id, property)
979
+ end
980
+ else
981
+ # 按年
982
+ if params[:forecast_date_year].present?
983
+ date = params[:forecast_date_year].split(" - ")
984
+ dates = (date[0]..date[1]).to_a
985
+ @return_forecast_count_data = return_money_forecast_year(dates, sale_names, staff_id, property)
986
+ else
987
+ forecast_default_dates = ("#{Time.now.year}-01-01".to_date.."#{Time.now.year}-#{Time.now.month}-01".to_date).map { |d| d.strftime("%Y") }.uniq
988
+ @return_forecast_count_data = return_money_forecast_year(forecast_default_dates, sale_names, staff_id, property)
989
+ end
990
+ end
991
+ @return_forecast_count_data_0 = @return_forecast_count_data[0]
992
+ @return_forecast_count_data_1 = @return_forecast_count_data[1]
993
+ end
994
+
930
995
  end
931
996
  end
@@ -204,15 +204,31 @@ module EducodeSales
204
204
  end
205
205
 
206
206
  if params[:q].present? && params[:q][:is_contact].present?
207
- @teachers = @teachers.where("last_follow.is_contact = ?" , params[:q][:is_contact].to_i)
207
+ @teachers = @teachers.where("last_follow.is_contact = ?", params[:q][:is_contact].to_i)
208
208
  end
209
-
210
- if params[:sort].present? && params[:sort][:field]
209
+ if params[:sort].present? && params[:sort][:field] && params[:sort][:field] == 'created_at'
210
+ @teachers = @teachers.order("educode_sales_teachers.created_at #{params[:sort][:order]}")
211
+ elsif params[:sort].present? && params[:sort][:field] && params[:sort][:field] == 'last_login_on'
212
+ @teachers = @teachers.order("users.last_login_on #{params[:sort][:order]}")
213
+ elsif params[:sort].present? && params[:sort][:field] && params[:sort][:field] == 'created_on'
214
+ @teachers = @teachers.order("users.created_on #{params[:sort][:order]}")
215
+ elsif params[:sort].present? && params[:sort][:field] && params[:sort][:field] == 'latest_time'
216
+ @teachers = @teachers.order("last_follow.created_at #{params[:sort][:order]}")
217
+ elsif params[:sort].present? && params[:sort][:field] && params[:sort][:field] == 'experience'
218
+ @teachers = @teachers.order("users.experience #{params[:sort][:order]}")
219
+ elsif params[:sort].present? && params[:sort][:field] && params[:sort][:field] == 'grade'
220
+ @teachers = @teachers.order("users.grade #{params[:sort][:order]}")
221
+ elsif params[:sort].present? && params[:sort][:field]
211
222
  @teachers = @teachers.order("#{params[:sort][:field]} #{params[:sort][:order]}")
212
223
  else
213
224
  @teachers = @teachers.order("educode_sales_teachers.created_at desc")
214
225
  end
215
- @teachers = @teachers.page(params[:page]).per(params[:limit])
226
+ @teachers = @teachers.includes(:teacher_assign_follows, :department, :user, :follow_up, :activity_teachers, [assign_staffs: :staff])
227
+ if params[:type].to_s == 'export'
228
+ @teachers = @teachers.page(1).per(1000)
229
+ else
230
+ @teachers = @teachers.page(params[:page]).per(params[:limit])
231
+ end
216
232
  end
217
233
 
218
234
  end
@@ -1,6 +1,7 @@
1
1
  module EducodeSales
2
2
  module SaleTrendsHelper
3
3
  NAMES = %w[计划投标额 计划投标额累计 实际中标额 实际中标额累计]
4
+ RETURN_NAMES = %w[实际回款额 计划回款额 实际回款 计划回款额-全部 计划回款额-o类]
4
5
 
5
6
  def goal_forecast_quarter(labels, selects, staff_id = nil, property)
6
7
  plan_get = plan_get(staff_id, labels, "quarter", property)
@@ -337,6 +338,274 @@ module EducodeSales
337
338
  end
338
339
  end
339
340
 
341
+
342
+ def return_money_forecast_week(labels, selects, staff_id = nil, property)
343
+ plan_return = plan_return(staff_id, labels, "week", property)
344
+ actual_return = actual_return(staff_id, labels, "week", property)
345
+ plan_return_by_o = plan_return_by_o(staff_id, labels, "week", property)
346
+ datasets = selects.map.with_index do |select, i|
347
+ data = if select == RETURN_NAMES[0]
348
+ labels.map do |d|
349
+ week = d.split("-").last
350
+ year = d.split("-").first
351
+ yearweek = "#{year}#{week}".to_i
352
+ actual_return[yearweek].to_f.round(3)
353
+ end
354
+ elsif select == RETURN_NAMES[1]
355
+ arr = labels.map do |d|
356
+ week = d.split("-").last
357
+ year = d.split("-").first
358
+ yearweek = "#{year}#{week}".to_i
359
+ plan_return[yearweek].to_f.round(3)
360
+ end
361
+ arr.map.with_index(1) { |num, i| arr.first(i).inject(:+) }
362
+ elsif select == RETURN_NAMES[2]
363
+ labels.map do |d|
364
+ week = d.split("-").last
365
+ year = d.split("-").first
366
+ yearweek = "#{year}#{week}".to_i
367
+ actual_return[yearweek].to_f.round(3)
368
+ end
369
+ elsif select == RETURN_NAMES[3]
370
+ labels.map do |d|
371
+ week = d.split("-").last
372
+ year = d.split("-").first
373
+ yearweek = "#{year}#{week}".to_i
374
+ plan_return[yearweek].to_f.round(3)
375
+ end
376
+ elsif select == RETURN_NAMES[4]
377
+ arr = labels.map do |d|
378
+ week = d.split("-").last
379
+ year = d.split("-").first
380
+ yearweek = "#{year}#{week}".to_i
381
+ plan_return_by_o[yearweek].to_f.round(3)
382
+ end
383
+ arr.map.with_index(1) { |num, i| arr.first(i).inject(:+) }
384
+ end
385
+ type = if select == RETURN_NAMES[0] || select == RETURN_NAMES[1]
386
+ 'bar'
387
+ else
388
+ "line"
389
+ end
390
+ backgroundColor = if select == RETURN_NAMES[0] || select == RETURN_NAMES[1]
391
+ 'rgba(54, 162, 235, 1)'
392
+ else
393
+ SaleTrend::COLORS[i]
394
+ 'rgba(54, 162, 235, 0)'
395
+ end
396
+ {
397
+ type: type,
398
+ label: select,
399
+ data: data&.map { |d| d.round(2) },
400
+ backgroundColor: backgroundColor,
401
+ borderColor: SaleTrend::COLORS[i],
402
+ borderWidth: 1
403
+ }
404
+ end
405
+
406
+ hash_a = {
407
+ labels: labels,
408
+ datasets: [datasets[0], datasets[1]]
409
+ }
410
+ hash_b = {
411
+ labels: labels,
412
+ datasets: [datasets[2], datasets[3], datasets[4]]
413
+ }
414
+ [hash_a, hash_b]
415
+ end
416
+
417
+ def return_money_forecast_quarter(labels, selects, staff_id = nil, property)
418
+ plan_return = plan_return(staff_id, labels, "quarter", property)
419
+ actual_return = actual_return(staff_id, labels, "quarter", property)
420
+ plan_return_by_o = plan_return_by_o(staff_id, labels, "quarter", property)
421
+ datasets = selects.map.with_index do |select, i|
422
+ data = if select == RETURN_NAMES[0]
423
+ labels.map do |d|
424
+ quarter = d.split("-").last.to_i
425
+ year = d.split("-").first.to_i
426
+ actual_return[[year, quarter]]&.pluck(:amount)&.reject(&:blank?)&.sum.to_f.round(3)
427
+ end
428
+ elsif select == RETURN_NAMES[1]
429
+ arr = labels.map do |d|
430
+ quarter = d.split("-").last.to_i
431
+ year = d.split("-").first.to_i
432
+ plan_return[[year, quarter]]&.pluck(:plan_return_money)&.reject(&:blank?)&.sum.to_f.round(3)
433
+ end
434
+ arr.map.with_index(1) { |num, i| arr.first(i).inject(:+) }
435
+ elsif select == RETURN_NAMES[2]
436
+ labels.map do |d|
437
+ quarter = d.split("-").last.to_i
438
+ year = d.split("-").first.to_i
439
+ actual_return[[year, quarter]]&.pluck(:amount)&.reject(&:blank?)&.sum.to_f.round(3)
440
+ end
441
+ elsif select == RETURN_NAMES[3]
442
+ labels.map do |d|
443
+ quarter = d.split("-").last.to_i
444
+ year = d.split("-").first.to_i
445
+ plan_return[[year, quarter]]&.pluck(:plan_return_money)&.reject(&:blank?)&.sum.to_f.round(3)
446
+ end
447
+ elsif select == RETURN_NAMES[4]
448
+ arr = labels.map do |d|
449
+ quarter = d.split("-").last.to_i
450
+ year = d.split("-").first.to_i
451
+ plan_return_by_o[[year, quarter]]&.pluck(:plan_return_money)&.reject(&:blank?)&.sum.to_f.round(3)
452
+ end
453
+ arr.map.with_index(1) { |num, i| arr.first(i).inject(:+) }
454
+ end
455
+ type = if select == RETURN_NAMES[0] || select == RETURN_NAMES[1]
456
+ 'bar'
457
+ else
458
+ "line"
459
+ end
460
+ backgroundColor = if select == RETURN_NAMES[0] || select == RETURN_NAMES[1]
461
+ 'rgba(54, 162, 235, 1)'
462
+ else
463
+ SaleTrend::COLORS[i]
464
+ 'rgba(54, 162, 235, 0)'
465
+ end
466
+ {
467
+ type: type,
468
+ label: select,
469
+ data: data.map { |d| d.round(2) },
470
+ backgroundColor: backgroundColor,
471
+ borderColor: SaleTrend::COLORS[i],
472
+ borderWidth: 1
473
+ }
474
+ end
475
+
476
+ hash_a = {
477
+ labels: labels,
478
+ datasets: [datasets[0], datasets[1]]
479
+ }
480
+ hash_b = {
481
+ labels: labels,
482
+ datasets: [datasets[2], datasets[3], datasets[4]]
483
+ }
484
+ [hash_a, hash_b]
485
+ end
486
+
487
+
488
+ def return_money_forecast_month(labels, selects, staff_id = nil, property)
489
+ plan_return = plan_return(staff_id, labels, "month", property)
490
+ actual_return = actual_return(staff_id, labels, "month", property)
491
+ plan_return_by_o = plan_return_by_o(staff_id, labels, "month", property)
492
+ datasets = selects.map.with_index do |select, i|
493
+ data = if select == RETURN_NAMES[0]
494
+ labels.map do |d|
495
+ quarter = d.split("-").last.to_i
496
+ year = d.split("-").first.to_i
497
+ actual_return[[year, quarter]]&.pluck(:amount)&.reject(&:blank?)&.sum.to_f.round(3)
498
+ end
499
+ elsif select == RETURN_NAMES[1]
500
+ arr = labels.map do |d|
501
+ quarter = d.split("-").last.to_i
502
+ year = d.split("-").first.to_i
503
+ plan_return[[year, quarter]]&.pluck(:plan_return_money)&.reject(&:blank?)&.sum.to_f.round(3)
504
+ end
505
+ arr.map.with_index(1) { |num, i| arr.first(i).inject(:+) }
506
+ elsif select == RETURN_NAMES[2]
507
+ labels.map do |d|
508
+ quarter = d.split("-").last.to_i
509
+ year = d.split("-").first.to_i
510
+ actual_return[[year, quarter]]&.pluck(:amount)&.reject(&:blank?)&.sum.to_f.round(3)
511
+ end
512
+ elsif select == RETURN_NAMES[3]
513
+ labels.map do |d|
514
+ quarter = d.split("-").last.to_i
515
+ year = d.split("-").first.to_i
516
+ plan_return[[year, quarter]]&.pluck(:plan_return_money)&.reject(&:blank?)&.sum.to_f.round(3)
517
+ end
518
+ elsif select == RETURN_NAMES[4]
519
+ arr = labels.map do |d|
520
+ quarter = d.split("-").last.to_i
521
+ year = d.split("-").first.to_i
522
+ plan_return_by_o[[year, quarter]]&.pluck(:plan_return_money)&.reject(&:blank?)&.sum.to_f.round(3)
523
+ end
524
+ arr.map.with_index(1) { |num, i| arr.first(i).inject(:+) }
525
+ end
526
+ type = if select == RETURN_NAMES[0] || select == RETURN_NAMES[1]
527
+ 'bar'
528
+ else
529
+ "line"
530
+ end
531
+ backgroundColor = if select == RETURN_NAMES[0] || select == RETURN_NAMES[1]
532
+ 'rgba(54, 162, 235, 1)'
533
+ else
534
+ SaleTrend::COLORS[i]
535
+ 'rgba(54, 162, 235, 0)'
536
+ end
537
+ {
538
+ type: type,
539
+ label: select,
540
+ data: data.map { |d| d.round(2) },
541
+ backgroundColor: backgroundColor,
542
+ borderColor: SaleTrend::COLORS[i],
543
+ borderWidth: 1
544
+ }
545
+ end
546
+
547
+ hash_a = {
548
+ labels: labels,
549
+ datasets: [datasets[0], datasets[1]]
550
+ }
551
+ hash_b = {
552
+ labels: labels,
553
+ datasets: [datasets[2], datasets[3], datasets[4]]
554
+ }
555
+ [hash_a, hash_b]
556
+ end
557
+
558
+ def return_money_forecast_year(labels, selects, staff_id = nil, property)
559
+ plan_return = plan_return(staff_id, labels, "year", property)
560
+ actual_return = actual_return(staff_id, labels, "year", property)
561
+ plan_return_by_o = plan_return_by_o(staff_id, labels, "year", property)
562
+ datasets = selects.map.with_index do |select, i|
563
+ data = if select == RETURN_NAMES[0]
564
+ labels.map { |d| actual_return[d.to_i] || 0 }
565
+ elsif select == RETURN_NAMES[1]
566
+ arr = labels.map { |d| plan_return[d.to_i] || 0 }
567
+ arr.map.with_index(1) { |num, i| arr.first(i).inject(:+) }
568
+ elsif select == RETURN_NAMES[2]
569
+ labels.map { |d| actual_return[d.to_i] || 0 }
570
+ elsif select == RETURN_NAMES[3]
571
+ labels.map { |d| plan_return[d.to_i] || 0 }
572
+ elsif select == RETURN_NAMES[4]
573
+ arr = labels.map { |d| plan_return_by_o[d.to_i] || 0 }
574
+ arr.map.with_index(1) { |num, i| arr.first(i).inject(:+) }
575
+ end
576
+
577
+ type = if select == RETURN_NAMES[0] || select == RETURN_NAMES[1]
578
+ 'bar'
579
+ else
580
+ "line"
581
+ end
582
+ backgroundColor = if RETURN_NAMES[0] || select == RETURN_NAMES[1]
583
+ 'rgba(54, 162, 235, 1)'
584
+ else
585
+ SaleTrend::COLORS[i]
586
+ 'rgba(54, 162, 235, 0)'
587
+ end
588
+ {
589
+ type: type,
590
+ label: select,
591
+ data: data.map { |d| d.round(2) },
592
+ backgroundColor: backgroundColor,
593
+ borderColor: SaleTrend::COLORS[i],
594
+ borderWidth: 1
595
+ }
596
+ end
597
+
598
+ hash_a = {
599
+ labels: labels,
600
+ datasets: [datasets[0], datasets[1]]
601
+ }
602
+ hash_b = {
603
+ labels: labels,
604
+ datasets: [datasets[2], datasets[3], datasets[4]]
605
+ }
606
+ [hash_a, hash_b]
607
+ end
608
+
340
609
  private
341
610
 
342
611
  def plan_get(staff_id, time_range, type, property)
@@ -433,5 +702,146 @@ module EducodeSales
433
702
  end
434
703
  end
435
704
 
705
+ def plan_return(staff_id, time_range, type, property)
706
+ # plan_return_money 计划回款额
707
+ start_time = case type
708
+ when "month"
709
+ time_range.first + "-01"
710
+ when "year"
711
+ time_range.first + "-01-01"
712
+ when "week"
713
+ time_range.first.split("-").first + "-01-01"
714
+ when "quarter"
715
+ time_range.first.split("-").first + "-01-01"
716
+ end
717
+ end_time = case type
718
+ when "month"
719
+ time_range.last + "-31"
720
+ when "year"
721
+ time_range.last + "-12-31"
722
+ when "week"
723
+ time_range.last.split("-").first + "-12-31"
724
+ when "quarter"
725
+ time_range.last.split("-").first + "-12-31"
726
+ end
727
+ staff_id = staff_id.present? ? Array(staff_id) : nil
728
+ data = Business.joins(:last_follow_up)
729
+ .where("educode_sales_follow_ups.plan_return_date >= ? and educode_sales_follow_ups.plan_return_date <= ?", start_time, end_time)
730
+ if staff_id.present?
731
+ data = data.joins("LEFT JOIN educode_sales_follow_ups AS last_follow_up ON educode_sales_businesses.last_follow_up_id = last_follow_up.id AND last_follow_up.deleted_at IS NULL
732
+ LEFT JOIN educode_sales_assign_follow_ups ON educode_sales_assign_follow_ups.follow_up_id = last_follow_up.id").
733
+ where("(educode_sales_assign_follow_ups.id IS NOT NULL AND educode_sales_assign_follow_ups.staff_id = ?) OR (educode_sales_assign_follow_ups.id IS NULL AND educode_sales_businesses.staff_id = ?)", staff_id, staff_id)
734
+ end
735
+ if property.present?
736
+ data = data.joins(department: [school: :school_tags]).where("school_tags.id = ?", property)
737
+ end
738
+ case type
739
+ when "week"
740
+ data.select("educode_sales_follow_ups.*, yearweek(educode_sales_follow_ups.plan_return_date) as week").group("yearweek(educode_sales_follow_ups.plan_return_date)").sum("educode_sales_follow_ups.plan_return_money")
741
+ when "quarter"
742
+ data = data.select("educode_sales_follow_ups.*, quarter(educode_sales_follow_ups.plan_return_date) as quarter, year(educode_sales_follow_ups.invitation_at) as year")
743
+ data.group_by { |d| [d.year, d.quarter] }
744
+ when "month"
745
+ data = data.select("educode_sales_follow_ups.*, year(educode_sales_follow_ups.plan_return_date) as year, month(educode_sales_follow_ups.plan_return_date) as month")
746
+ data.group_by { |d| [d.year, d.month] }
747
+ when "year"
748
+ data.select("educode_sales_follow_ups.*, year(educode_sales_follow_ups.plan_return_date) as year").group("year(educode_sales_follow_ups.plan_return_date)").sum("educode_sales_follow_ups.plan_return_money")
749
+ end
750
+ end
751
+
752
+
753
+ def actual_return(staff_id, time_range, type, property)
754
+ # money_plan_records表中 amount: 回款金额
755
+ start_time = case type
756
+ when "month"
757
+ time_range.first + "-01"
758
+ when "year"
759
+ time_range.first + "-01-01"
760
+ when "week"
761
+ time_range.first.split("-").first + "-01-01"
762
+ when "quarter"
763
+ time_range.first.split("-").first + "-01-01"
764
+ end
765
+ end_time = case type
766
+ when "month"
767
+ time_range.last + "-31"
768
+ when "year"
769
+ time_range.last + "-12-31"
770
+ when "week"
771
+ time_range.last.split("-").first + "-12-31"
772
+ when "quarter"
773
+ time_range.last.split("-").first + "-12-31"
774
+ end
775
+ staff_id = staff_id.present? ? Array(staff_id) : nil
776
+ data = MoneyPlanRecord.joins(business: [department: [school: :school_tags]]).where("educode_sales_money_plan_records.date_at >= ? and educode_sales_money_plan_records.date_at <= ?", start_time, end_time)
777
+ if staff_id.present?
778
+ data = data.joins("LEFT JOIN educode_sales_follow_ups AS last_follow_up ON educode_sales_businesses.last_follow_up_id = last_follow_up.id AND last_follow_up.deleted_at IS NULL
779
+ LEFT JOIN educode_sales_assign_follow_ups ON educode_sales_assign_follow_ups.follow_up_id = last_follow_up.id").
780
+ where("(educode_sales_assign_follow_ups.id IS NOT NULL AND educode_sales_assign_follow_ups.staff_id = ?) OR (educode_sales_assign_follow_ups.id IS NULL AND educode_sales_businesses.staff_id = ?)", staff_id, staff_id)
781
+ end
782
+ if property.present?
783
+ data = data.where("school_tags.id = ?", property)
784
+ end
785
+ case type
786
+ when "week"
787
+ data.select("educode_sales_money_plan_records.*, yearweek(educode_sales_money_plan_records.date_at) as week").group("yearweek(educode_sales_money_plan_records.date_at)").sum("educode_sales_money_plan_records.amount")
788
+ when "quarter"
789
+ data = data.select("educode_sales_money_plan_records.*, quarter(educode_sales_money_plan_records.date_at) as quarter, year(educode_sales_money_plan_records.date_at) as year")
790
+ data.group_by { |d| [d.year, d.quarter] }
791
+ when "month"
792
+ data = data.select("educode_sales_money_plan_records.*, year(educode_sales_money_plan_records.date_at) as year, month(educode_sales_money_plan_records.date_at) as month")
793
+ data.group_by { |d| [d.year, d.month] }
794
+ when "year"
795
+ data.select("educode_sales_money_plan_records.*, year(educode_sales_money_plan_records.date_at) as year").group("year(educode_sales_money_plan_records.date_at)").sum("educode_sales_money_plan_records.amount")
796
+ end
797
+ end
798
+
799
+ def plan_return_by_o(staff_id, time_range, type, property)
800
+ # plan_return_money 计划回款额-o类
801
+ clazz_id = Common.find_by(name: "O类-中标商机", clazz: "business_type", extras: "o_class").id
802
+ start_time = case type
803
+ when "month"
804
+ time_range.first + "-01"
805
+ when "year"
806
+ time_range.first + "-01-01"
807
+ when "week"
808
+ time_range.first.split("-").first + "-01-01"
809
+ when "quarter"
810
+ time_range.first.split("-").first + "-01-01"
811
+ end
812
+ end_time = case type
813
+ when "month"
814
+ time_range.last + "-31"
815
+ when "year"
816
+ time_range.last + "-12-31"
817
+ when "week"
818
+ time_range.last.split("-").first + "-12-31"
819
+ when "quarter"
820
+ time_range.last.split("-").first + "-12-31"
821
+ end
822
+ staff_id = staff_id.present? ? Array(staff_id) : nil
823
+ data = Business.joins(:last_follow_up).where("educode_sales_businesses.clazz_id = ?", clazz_id)
824
+ .where("educode_sales_follow_ups.plan_return_date >= ? and educode_sales_follow_ups.plan_return_date <= ?", start_time, end_time)
825
+ if staff_id.present?
826
+ data = data.joins("LEFT JOIN educode_sales_follow_ups AS last_follow_up ON educode_sales_businesses.last_follow_up_id = last_follow_up.id AND last_follow_up.deleted_at IS NULL
827
+ LEFT JOIN educode_sales_assign_follow_ups ON educode_sales_assign_follow_ups.follow_up_id = last_follow_up.id").
828
+ where("(educode_sales_assign_follow_ups.id IS NOT NULL AND educode_sales_assign_follow_ups.staff_id = ?) OR (educode_sales_assign_follow_ups.id IS NULL AND educode_sales_businesses.staff_id = ?)", staff_id, staff_id)
829
+ end
830
+ if property.present?
831
+ data = data.joins(department: [school: :school_tags]).where("school_tags.id = ?", property)
832
+ end
833
+ case type
834
+ when "week"
835
+ data.select("educode_sales_follow_ups.*, yearweek(educode_sales_follow_ups.plan_return_date) as week").group("yearweek(educode_sales_follow_ups.plan_return_date)").sum("educode_sales_follow_ups.plan_return_money")
836
+ when "quarter"
837
+ data = data.select("educode_sales_follow_ups.*, quarter(educode_sales_follow_ups.plan_return_date) as quarter, year(educode_sales_follow_ups.invitation_at) as year")
838
+ data.group_by { |d| [d.year, d.quarter] }
839
+ when "month"
840
+ data = data.select("educode_sales_follow_ups.*, year(educode_sales_follow_ups.plan_return_date) as year, month(educode_sales_follow_ups.plan_return_date) as month")
841
+ data.group_by { |d| [d.year, d.month] }
842
+ when "year"
843
+ data.select("educode_sales_follow_ups.*, year(educode_sales_follow_ups.plan_return_date) as year").group("year(educode_sales_follow_ups.plan_return_date)").sum("educode_sales_follow_ups.plan_return_money")
844
+ end
845
+ end
436
846
  end
437
847
  end
@@ -0,0 +1,178 @@
1
+ <%= Gon::Base.render_data %>
2
+ <div id="target_track_wraper">
3
+ <div class="layuimini-main min-height-table" id="monthly_table_wraper">
4
+ <form class="layui-form layui-form-pane" lay-filter="assessment_progress_form">
5
+ <div class="layui-form-item">
6
+ <div class="layui-inline">
7
+ <label class="layui-form-label">人员</label>
8
+ <div class="layui-input-inline large-select">
9
+ <%= select_tag "staff_id", options_for_select(@staffs), { id: 'weekly_staff_id', include_blank: true} %>
10
+ </div>
11
+ </div>
12
+ <div class="layui-inline">
13
+ <label class="layui-form-label">年度</label>
14
+ <div class="layui-input-inline">
15
+ <input type="text" class="layui-input" autocomplete="off" name="assessment_year" value="<%= Time.now.year %>" id="assessment_year">
16
+ </div>
17
+ </div>
18
+ <div class="layui-inline">
19
+ <label class="layui-form-label">客户类型</label>
20
+ <div class="layui-input-inline">
21
+ <div id="property" style="width: 190px;"></div>
22
+ </div>
23
+ </div>
24
+ <div class="layui-inline">
25
+ <label class="layui-form-label">目标类别</label>
26
+ <div class="layui-input-inline">
27
+ <div id="clazz" style="width: 190px;"></div>
28
+ </div>
29
+ </div>
30
+ <div class="layui-inline">
31
+ <button type="reset" class="layui-btn layui-btn-primary" lay-submit lay-filter="progress_resert_btn">重置
32
+ </button>
33
+ <button type="submit" class="layui-btn layui-btn-primary" lay-submit lay-filter="progress_search_btn">检索
34
+ </button>
35
+ </div>
36
+ </div>
37
+ </form>
38
+ <table class="layui-tab" id="finished_table" lay-filter="progressTable"></table>
39
+ </div>
40
+ <script type="text/html" id="progress_Toolbar">
41
+ <div class="layui-btn-container">
42
+ <button class="layui-btn layui-btn-default layui-btn-sm data-add-btn pull-right" lay-event="add"> 导出</button>
43
+ <button class="layui-btn layui-btn-primary layui-btn-sm data-add-btn pull-right" lay-event="add"> 人员显示</button>
44
+ <button class="layui-btn layui-btn-primary layui-btn-sm data-add-btn pull-right" lay-event="add"> 分类显示</button>
45
+ </div>
46
+ </script>
47
+
48
+ <script>
49
+ layui.use(['form', 'table', 'miniPage', 'element', 'rate', 'laydate', 'request', 'xmSelect'], function () {
50
+
51
+ var $ = layui.jquery,
52
+ form = layui.form,
53
+ laydate = layui.laydate,
54
+ request = layui.request,
55
+ table = layui.table,
56
+ rate = layui.rate,
57
+ xmSelect = layui.xmSelect,
58
+ miniPage = layui.miniPage,
59
+ dropdown = layui.dropdown;
60
+
61
+
62
+ laydate.render({
63
+ elem: '#assessment_year',
64
+ type: 'year'
65
+ });
66
+
67
+ var property_list = xmSelect.render({
68
+ el: '#property',
69
+ data: gon.school_tags
70
+ })
71
+
72
+ var clazz = xmSelect.render({
73
+ el: '#clazz',
74
+ data: [{value: '中标', name: '中标'}, {value: '回款', name: '回款'}, {value: '商机', name: '商机'}]
75
+ })
76
+
77
+
78
+ var progress_table = table.render({
79
+ elem: '#finished_table'
80
+ ,toolbar: '#progress_Toolbar'
81
+ ,totalRow:true
82
+ ,title: "绩效考核指标完成情况" // 目前发现的作用(导出文件的文件名)
83
+ ,defaultToolbar: ['filter']
84
+ ,cols:[
85
+ [ //标题栏
86
+ {field: 'id', title: '序号', width: 120, rowspan: 2, colspan: 9},
87
+ {field: 'name', title: '姓名', width: 120, rowspan: 2, colspan: 9},
88
+ {field: 'assessment', title: '类别', width: 120, rowspan: 2},
89
+ ,{field: 'year', align: 'center', title: '年度目标', width: 100, rowspan: 2}
90
+ ,{align: 'center', title: '客户类型', width: 120,rowspan: 2}
91
+ ,{align: 'center', title: '分项目标', width: 120, rowspan: 2}
92
+ ,{field: 'name', title: '年度计划', width: 120, rowspan: 2}
93
+ ,{field: 'name', title: '年度完成', width: 120, rowspan: 2}
94
+
95
+ ,{align: 'center', title: '1月', colspan: 3}
96
+ ,{align: 'center', title: '2月', colspan: 3}
97
+ ,{align: 'center', title: '3月', colspan: 3}
98
+ ,{align: 'center', title: '4月', colspan: 3}
99
+ ,{align: 'center', title: '5月', colspan: 3}
100
+ ,{align: 'center', title: '6月', colspan: 3}
101
+ ,{align: 'center', title: '7月', colspan: 3}
102
+ ,{align: 'center', title: '8月', colspan: 3}
103
+ ,{align: 'center', title: '9月', colspan: 3}
104
+ ,{align: 'center', title: '10月', colspan: 3}
105
+ ,{align: 'center', title: '11月', colspan: 3}
106
+ ,{align: 'center', title: '12月', colspan: 3}
107
+ ],
108
+ [
109
+ {field: 'target_1', title: '目标', width: 100, totalRow:true}
110
+ ,{field: 'plan_1', title: '计划', width: 100, totalRow:true}
111
+ ,{field: 'finish_1', title: '完成', width: 100, totalRow:true}
112
+
113
+ ,{field: 'target_2', title: '目标', width: 100, totalRow:true}
114
+ ,{field: 'plan_2', title: '计划', width: 100, totalRow:true}
115
+ ,{field: 'finish_2', title: '完成', width: 100, totalRow:true}
116
+
117
+ ,{field: 'target_3', title: '目标', width: 100, totalRow:true}
118
+ ,{field: 'plan_3', title: '计划', width: 100, totalRow:true}
119
+ ,{field: 'finish_3', title: '完成', width: 100, totalRow:true}
120
+
121
+ ,{field: 'target_4', title: '目标', width: 100, totalRow:true}
122
+ ,{field: 'plan_4', title: '计划', width: 100, totalRow:true}
123
+ ,{field: 'finish_4', title: '完成', width: 100, totalRow:true}
124
+
125
+ ,{field: 'target_5', title: '目标', width: 100, totalRow:true}
126
+ ,{field: 'plan_5', title: '计划', width: 100, totalRow:true}
127
+ ,{field: 'finish_5', title: '完成', width: 100, totalRow:true}
128
+
129
+ ,{field: 'target_6', title: '目标', width: 100, totalRow:true}
130
+ ,{field: 'plan_6', title: '计划', width: 100, totalRow:true}
131
+ ,{field: 'finish_6', title: '完成', width: 100, totalRow:true}
132
+
133
+ ,{field: 'target_7', title: '目标', width: 100, totalRow:true}
134
+ ,{field: 'plan_7', title: '计划', width: 100, totalRow:true}
135
+ ,{field: 'finish_7', title: '完成', width: 100, totalRow:true}
136
+
137
+ ,{field: 'target_8', title: '目标', width: 100, totalRow:true}
138
+ ,{field: 'plan_8', title: '计划', width: 100, totalRow:true}
139
+ ,{field: 'finish_8', title: '完成', width: 100, totalRow:true}
140
+
141
+ ,{field: 'target_9', title: '目标', width: 100, totalRow:true}
142
+ ,{field: 'plan_9', title: '计划', width: 100, totalRow:true}
143
+ ,{field: 'finish_9', title: '完成', width: 100, totalRow:true}
144
+
145
+ ,{field: 'target_10', title: '目标', width: 100, totalRow:true}
146
+ ,{field: 'plan_10', title: '计划', width: 100, totalRow:true}
147
+ ,{field: 'finish_10', title: '完成', width: 100, totalRow:true}
148
+
149
+ ,{field: 'target_11', title: '目标', width: 100, totalRow:true}
150
+ ,{field: 'plan_11', title: '计划', width: 100, totalRow:true}
151
+ ,{field: 'finish_11', title: '完成', width: 100, totalRow:true}
152
+
153
+ ,{field: 'target_12', title: '目标', width: 100, totalRow:true}
154
+ ,{field: 'plan_12', title: '计划', width: 100, totalRow:true}
155
+ ,{field: 'finish_12', title: '完成', width: 100, totalRow:true}
156
+
157
+ ]]
158
+ });
159
+ loadFinishTable(form.val('assessment_progress_form'))
160
+
161
+ form.on('submit(progress_search_btn)', function (data) {
162
+ var search = data.field;
163
+ search.assessment_id = assement_list.getValue('valueStr').split(",");
164
+ loadFinishTable(search);
165
+ return false;
166
+ })
167
+
168
+ function loadFinishTable(search) {
169
+ table.reload('finished_table', {
170
+ where: search,
171
+ url: '/missions/assessments/finished'
172
+ });
173
+ }
174
+
175
+ })
176
+
177
+ </script>
178
+ </div>
@@ -5,6 +5,7 @@
5
5
  <li data="month">月计划</li>
6
6
  <li data="monthly">月报</li>
7
7
  <li data="year">年计划</li>
8
+ <!-- <li data="target_track">年度执行</li> -->
8
9
  </ul>
9
10
  <div class="layui-tab-content">
10
11
  <div class="layui-tab-item layui-show">
@@ -22,6 +23,8 @@
22
23
  <div class="layui-tab-item">
23
24
  <div id="year_plan_tab_wraper"></div>
24
25
  </div>
26
+ <div class="layui-tab-item" id="target_track_tab">
27
+ </div>
25
28
  </div>
26
29
  </div>
27
30
 
@@ -70,6 +73,8 @@
70
73
  loadPage('/missions/plans/monthly')
71
74
  } else if (data.index == 4 && $("#year_table_wraper").length == 0) {
72
75
  loadPage('/missions/plans/year_plan')
76
+ } else if (data.index == 5 && $("#target_track_wraper").length == 0) {
77
+ loadPage('/missions/plans/target_track')
73
78
  }
74
79
  });
75
80
 
@@ -0,0 +1 @@
1
+ $("#target_track_tab").html("<%= j render 'target_track' %>");
@@ -0,0 +1,176 @@
1
+ <div id="tab_9">
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_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
+ <% common = EducodeSales::Common.find_by(clazz: 'staff_type', name: '销售')
10
+ staffs = EducodeSales::Staff.where(job_type: common.id) %>
11
+ <%= select_tag "staff_id", options_for_select(staffs.includes(:user).map { |d| [d.user.real_name, d.id] }, params[:staff_id]), {'lay-filter': 'staff_id', include_blank: true} %>
12
+ </div>
13
+ </div>
14
+ <div class="layui-inline m-t-10">
15
+ <label class="layui-form-label">视图</label>
16
+ <div class="layui-input-inline">
17
+ <%= select_tag "forecast_count_range", options_for_select([['按周', 'week'], ['按月', 'month'], ['按季', 'quarter'], ['按年', 'year']], params[:forecast_count_range] || "month"), {'lay-filter': 'return_forecast_count'} %>
18
+ </div>
19
+ </div>
20
+ <div class="layui-inline m-t-10">
21
+ <label class="layui-form-label">时间范围</label>
22
+ <div class="layui-input-inline">
23
+ <input type="text" class="layui-input forecast_month " id="return_forecast_date_month" name="forecast_date_month" placeholder=" - " value="<%= params[:forecast_date_month].present? ? params[:forecast_date_month] : Time.now.year.to_s + "-01" + " - " + Time.now.strftime("%Y-%m") %>" autocomplete="off">
24
+ <input type="text" class="layui-input forecast_year layui-hide" id="return_forecast_date_year" name="forecast_date_year" placeholder=" - " value="<%= params[:forecast_date_year] %>" autocomplete="off">
25
+ <input type="text" class="layui-input forecast_day layui-hide" id="return_forecast_date_day" name="forecast_date_day" placeholder=" - " value="<%= params[:forecast_date_day] %>" autocomplete="off">
26
+ </div>
27
+ </div>
28
+ <div class="layui-inline m-t-10">
29
+ <label class="layui-form-label">客户类型</label>
30
+ <div class="layui-input-inline">
31
+ <%= select_tag "property", options_for_select(SchoolTag.where(for_missions: true).pluck(:name, :id), params[:property]), {include_blank: true} %>
32
+ </div>
33
+ </div>
34
+ <div class="layui-inline m-t-10">
35
+ <button type="reset" class="layui-btn layui-btn-primary" lay-submit lay-filter="reset_search">重 置</button>
36
+ <button type="button" class="forecast_count_bt layui-btn layui-btn-primary" lay-submit lay-filter="search_sales">确 定</button>
37
+ </div>
38
+ </div>
39
+ </form>
40
+ </div>
41
+ <canvas id="return_forecast_myChart2" width="960" height="350"></canvas>
42
+ <canvas id="return_forecast_myChart2_1" width="960" height="350" style="margin-top: 30px;"></canvas>
43
+ </div>
44
+ </div>
45
+
46
+ <script>
47
+ layui.use(['form', 'jquery', 'request', 'laydate', 'element'], function () {
48
+ var $ = layui.jquery,
49
+ form = layui.form,
50
+ request = layui.request,
51
+ laydate = layui.laydate;
52
+
53
+ form.render();
54
+
55
+ var opt = {
56
+ events: false,
57
+ tooltips: {
58
+ enabled: false
59
+ },
60
+ layout: {
61
+ padding: {
62
+ left: 20,
63
+ right: 20,
64
+ top: 20,
65
+ bottom: 0
66
+ }
67
+ },
68
+ hover: {
69
+ animationDuration: 1
70
+ },
71
+ animation: {
72
+ duration: 1,
73
+ onComplete: function () {
74
+ var chartInstance = this.chart, ctx = chartInstance.ctx;
75
+ ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
76
+ ctx.textAlign = 'center';
77
+ ctx.textBaseline = 'bottom';
78
+
79
+ this.data.datasets.forEach(function (dataset, i) {
80
+ ctx.fillStyle = "#444";
81
+ var meta = chartInstance.controller.getDatasetMeta(i);
82
+ meta.data.forEach(function (bar, index) {
83
+ var data = dataset.data[index];
84
+ ctx.fillText(data, bar._model.x, bar._model.y - 5);
85
+ });
86
+ });
87
+ }
88
+ }
89
+ };
90
+
91
+ laydate.render({
92
+ type: 'year',
93
+ elem: '#return_forecast_date_year',
94
+ range: true
95
+ });
96
+
97
+ laydate.render({
98
+ elem: '#return_forecast_date_day',
99
+ range: true
100
+ });
101
+
102
+ laydate.render({
103
+ type: 'month',
104
+ elem: '#return_forecast_date_month',
105
+ range: true
106
+ });
107
+
108
+ var forecast_type = "month";
109
+ if (forecast_type === "month") {
110
+ $(".forecast_year").addClass('layui-hide');
111
+ $(".forecast_day").addClass('layui-hide');
112
+ $(".forecast_month").removeClass('layui-hide')
113
+ } else if (forecast_type === "year" || forecast_type === "quarter") {
114
+ $(".forecast_month").addClass('layui-hide');
115
+ $(".forecast_year").removeClass('layui-hide');
116
+ $(".forecast_day").addClass('layui-hide')
117
+ } else {
118
+ $(".forecast_day").removeClass('layui-hide');
119
+ $(".forecast_month").addClass('layui-hide');
120
+ $(".forecast_year").addClass('layui-hide')
121
+ }
122
+
123
+ form.on('select(return_forecast_count)', function (data) {
124
+ const value = data.value;
125
+ if (value === "month") {
126
+ $(".forecast_year").addClass('layui-hide');
127
+ $(".forecast_day").addClass('layui-hide');
128
+ $(".forecast_month").removeClass('layui-hide')
129
+ } else if (value === "year" || value === "quarter") {
130
+ $(".forecast_month").addClass('layui-hide');
131
+ $(".forecast_year").removeClass('layui-hide');
132
+ $(".forecast_day").addClass('layui-hide')
133
+ } else {
134
+ $(".forecast_day").removeClass('layui-hide');
135
+ $(".forecast_month").addClass('layui-hide');
136
+ $(".forecast_year").addClass('layui-hide')
137
+ }
138
+ });
139
+
140
+ //重置按钮
141
+ form.on('submit(reset_search)', function () {
142
+ form.val('search_form', {
143
+ staff_id: "",
144
+ property: ""
145
+ });
146
+ return false;
147
+ });
148
+
149
+ var ctx = document.getElementById('return_forecast_myChart2');
150
+ var return_forecast_myChart2 = new Chart(ctx, {
151
+ type: 'bar',
152
+ data: <%=raw @return_forecast_count_data_0.to_json %>,
153
+ options: opt
154
+ });
155
+
156
+ var ctx01 = document.getElementById('return_forecast_myChart2_1');
157
+ var return_forecast_myChart2_1 = new Chart(ctx01, {
158
+ type: 'bar',
159
+ data: <%=raw @return_forecast_count_data_1.to_json %>,
160
+ options: opt
161
+ });
162
+
163
+ form.on("submit(search_sales)", function (data) {
164
+ var layer_index = layer.load(0, {shade: [0.1, '#fff']});
165
+ Rails.ajax({
166
+ url: '/missions/sale_trends/return_money_forecast',
167
+ type: 'GET',
168
+ data: $.param(data.field, true),
169
+ dataType: "script",
170
+ success: function (res) {
171
+ layer.close(layer_index);
172
+ }
173
+ });
174
+ })
175
+ })
176
+ </script>
@@ -0,0 +1 @@
1
+ $("#page_9").html("<%= j render 'return_money_forecast' %>");
@@ -8,6 +8,7 @@
8
8
  <li class="">中标预测图</li>
9
9
  <li class="">用户分析</li>
10
10
  <li class="">拜访分析</li>
11
+ <li class="">回款预测图</li>
11
12
  </ul>
12
13
  <div class="layui-tab-content">
13
14
  <div class="layui-tab-item layui-show">
@@ -242,6 +243,9 @@
242
243
  <div class="layui-tab-item">
243
244
  <div id="page_8"></div>
244
245
  </div>
246
+ <div class="layui-tab-item">
247
+ <div id="page_9"></div>
248
+ </div>
245
249
  </div>
246
250
  </div>
247
251
 
@@ -270,6 +274,8 @@
270
274
  loadPage('/missions/sale_trends/user_stat')
271
275
  } else if (data.index == 7 && $("#tab_8").length == 0) {
272
276
  loadPage('/missions/sale_trends/visit_analysis')
277
+ } else if (data.index == 8 && $("#tab_9").length == 0) {
278
+ loadPage('/missions/sale_trends/return_money_forecast')
273
279
  }
274
280
  });
275
281
 
@@ -111,12 +111,14 @@
111
111
  <% if can? :create, EducodeSales::Teacher %>
112
112
  <button class="layui-btn layui-btn-normal layui-btn-sm data-add-btn pull-right" lay-event="import">导入数据</button>
113
113
  <button class="layui-btn layui-btn-normal layui-btn-sm data-add-btn pull-right" lay-event="add">添加老师</button>
114
- <% end %>
115
- </button>
114
+ <% end %>
115
+ <% if can? :export_teacher_list, EducodeSales::Teacher %>
116
+ <button class="layui-btn layui-btn-normal layui-btn-sm data-add-btn pull-right" lay-event="export">导出</button>
117
+ <% end %>
116
118
  </div>
117
119
  </script>
118
120
  <div class="">
119
- <table class="layui-hide" id="teachers_table" style="min-height: 300px;" lay-filter="teachers_table"></table>
121
+ <table class="layui-hide" id="teachers_table" style="min-height: 300px;" lay-filter="teachers_table"></table>
120
122
  </div>
121
123
  <script type="text/html" id="currentTableBar">
122
124
  <% if can? :create, EducodeSales::TeacherFollow %>
@@ -295,7 +297,8 @@
295
297
  field: 'followup_at',
296
298
  width: 180,
297
299
  title: '最新跟进时间',
298
- hide: gon.filter.followup_at
300
+ hide: gon.filter.followup_at,
301
+ sort: true
299
302
  },
300
303
  {
301
304
  field: 'latest_time',
@@ -401,16 +404,16 @@
401
404
  ]];
402
405
 
403
406
  table = layui.table;
404
- table.render({
407
+ var teachers_table = table.render({
405
408
  elem: '#teachers_table',
406
409
  url: '/missions/teachers',
407
410
  where: {q: form.val('search_form')},
408
411
  toolbar: '#toolbarDemo',
409
- totalRow:true,
412
+ totalRow: true,
410
413
  defaultToolbar: ['filter'],
411
414
  cols: cols_table,
412
415
  limit: 20,
413
- limits: [10,15,20,30,40,50,60,70,80,90],
416
+ limits: [10, 15, 20, 30, 40, 50, 60, 70, 80, 90],
414
417
  page: true,
415
418
  done: function (res) {
416
419
  drowpdwonRender()
@@ -418,11 +421,11 @@
418
421
  });
419
422
  var dropmenu = gon.menus;
420
423
 
421
- drowpdwonRender = function() {
424
+ drowpdwonRender = function () {
422
425
  dropdown.render({
423
426
  elem: '.more-btn',
424
427
  data: dropmenu,
425
- click: function(data, othis){
428
+ click: function (data, othis) {
426
429
  var elem = $(this.elem);
427
430
  id = elem.data('id');
428
431
  switch (data.event) {
@@ -640,6 +643,15 @@
640
643
  $(window).on("resize", function () {
641
644
  layer.full(index);
642
645
  });
646
+ } else if (obj.event === 'export') {
647
+ layer.load(0, {});
648
+ var data = form.val('search_teachers');
649
+ console.log(data)
650
+ request.authGet("missions/teachers?type=export&" + $.param({q: data}), {}, function (res) {
651
+ data = res.data;
652
+ table.exportFile(teachers_table.config.id, data, 'xls')
653
+ layer.closeAll('loading');
654
+ })
643
655
  }
644
656
  });
645
657
 
data/config/routes.rb CHANGED
@@ -174,6 +174,7 @@ EducodeSales::Engine.routes.draw do
174
174
  get :goal_forecast
175
175
  get :user_stat
176
176
  get :visit_analysis
177
+ get :return_money_forecast
177
178
  end
178
179
  end
179
180
 
@@ -266,6 +267,7 @@ EducodeSales::Engine.routes.draw do
266
267
  get :month_plan
267
268
  get :monthly
268
269
  get :year_plan
270
+ get :target_track
269
271
  end
270
272
  member do
271
273
  delete :delete_business_info
@@ -1,3 +1,3 @@
1
1
  module EducodeSales
2
- VERSION = '1.10.41'
2
+ VERSION = '1.10.48'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: educode_sales
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.41
4
+ version: 1.10.48
5
5
  platform: ruby
6
6
  authors:
7
7
  - anke1460
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-22 00:00:00.000000000 Z
11
+ date: 2023-07-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -105,6 +105,7 @@ files:
105
105
  - app/assets/images/educode_sales/icon-login.png
106
106
  - app/assets/images/educode_sales/icon.png
107
107
  - app/assets/images/educode_sales/indexLogo.png
108
+ - app/assets/images/educode_sales/indexlogo.png
108
109
  - app/assets/images/educode_sales/loading-0.gif
109
110
  - app/assets/images/educode_sales/loading-1.gif
110
111
  - app/assets/images/educode_sales/loading-2.gif
@@ -503,6 +504,7 @@ files:
503
504
  - app/views/educode_sales/places/new.html.erb
504
505
  - app/views/educode_sales/plans/_monthPlan.html.erb
505
506
  - app/views/educode_sales/plans/_monthly.html.erb
507
+ - app/views/educode_sales/plans/_target_track.html.erb
506
508
  - app/views/educode_sales/plans/_weekPlan.html.erb
507
509
  - app/views/educode_sales/plans/_weekly.html.erb
508
510
  - app/views/educode_sales/plans/_yearPlan.html.erb
@@ -532,6 +534,7 @@ files:
532
534
  - app/views/educode_sales/plans/show_monthly.html.erb
533
535
  - app/views/educode_sales/plans/show_week.html.erb
534
536
  - app/views/educode_sales/plans/show_weekly.html.erb
537
+ - app/views/educode_sales/plans/target_track.js.erb
535
538
  - app/views/educode_sales/plans/weekly.js.erb
536
539
  - app/views/educode_sales/plans/year_plan.js.erb
537
540
  - app/views/educode_sales/plans/years_plan.json.jbuilder
@@ -577,6 +580,7 @@ files:
577
580
  - app/views/educode_sales/sale_trends/_business_area.html.erb
578
581
  - app/views/educode_sales/sale_trends/_business_followup_analysis.html.erb
579
582
  - app/views/educode_sales/sale_trends/_goal_forecast.html.erb
583
+ - app/views/educode_sales/sale_trends/_return_money_forecast.html.erb
580
584
  - app/views/educode_sales/sale_trends/_sales_analysis.html.erb
581
585
  - app/views/educode_sales/sale_trends/_sales_followup_analysis.html.erb
582
586
  - app/views/educode_sales/sale_trends/_user_stat.html.erb
@@ -585,6 +589,7 @@ files:
585
589
  - app/views/educode_sales/sale_trends/business_followup_analysis.js.erb
586
590
  - app/views/educode_sales/sale_trends/goal_forecast.js.erb
587
591
  - app/views/educode_sales/sale_trends/operations.html.erb
592
+ - app/views/educode_sales/sale_trends/return_money_forecast.js.erb
588
593
  - app/views/educode_sales/sale_trends/sales_analysis.js.erb
589
594
  - app/views/educode_sales/sale_trends/sales_followup_analysis.js.erb
590
595
  - app/views/educode_sales/sale_trends/trends.html.erb
@@ -757,7 +762,7 @@ homepage: https://www.educoder.net
757
762
  licenses:
758
763
  - MIT
759
764
  metadata: {}
760
- post_install_message:
765
+ post_install_message:
761
766
  rdoc_options: []
762
767
  require_paths:
763
768
  - lib
@@ -773,7 +778,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
773
778
  version: '0'
774
779
  requirements: []
775
780
  rubygems_version: 3.0.9
776
- signing_key:
781
+ signing_key:
777
782
  specification_version: 4
778
783
  summary: Summary of EducodeSales.
779
784
  test_files: []