educode_sales 1.10.41 → 1.10.46

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: 75f1104743151bb685cb17c27471acf756a43103c059b78fdbbc85d897008420
4
- data.tar.gz: 1abca2361e351da1e62f2a04e1a98c72e01f953ab653d6e6fc3904294532e38e
3
+ metadata.gz: ee0e4fc5519c5e1dc171f8d0402f6f3e681e9b89636a7f424a642aaf88a23ce9
4
+ data.tar.gz: c060d33dfc08508f868182e5c3b8f8d780a20c03d8c300631a7a7c39316bfccc
5
5
  SHA512:
6
- metadata.gz: b93100ae277a43e93b44ed6ba56433123a8427d44b34ec3706b09e62987698d3672b81f8322bc6fc4af43f0e4ea0b2758b71e11368b87b33d7225ca28287b0a2
7
- data.tar.gz: 1ddb1e12b4f3102d9ad751d04fc00975cd18c765fa378f454862a73e8f2927b8cc3810ad151ae06b9d1451a26bfb2604ec730822dc63a72da23449d9fe948b17
6
+ metadata.gz: 5d82966240ed50554d5525c93254d1f282fe9a604e350f9ae81309726187f43d419e9849b1047f6b996bd6bebd91c12d57b0ea1c9691e5913eb41a29da0df206
7
+ data.tar.gz: 433b7c1181791a6a47a5d35ff5df90363607e9d8c1592056d9fbf546b373c42a29d0bc67d92bdfc67b7f6f504970ff61edf55a2b5b992e3d993dc2fe3861cc14
@@ -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,7 +204,7 @@ 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
209
 
210
210
  if params[:sort].present? && params[:sort][:field]
@@ -212,7 +212,12 @@ module EducodeSales
212
212
  else
213
213
  @teachers = @teachers.order("educode_sales_teachers.created_at desc")
214
214
  end
215
- @teachers = @teachers.page(params[:page]).per(params[:limit])
215
+ @teachers = @teachers.includes(:teacher_assign_follows, :department, :user, :follow_up, :activity_teachers, [assign_staffs: :staff])
216
+ if params[:type].to_s == 'export'
217
+ @teachers = @teachers.page(1).per(1000)
218
+ else
219
+ @teachers = @teachers.page(params[:page]).per(params[:limit])
220
+ end
216
221
  end
217
222
 
218
223
  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.46'
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.46
5
5
  platform: ruby
6
6
  authors:
7
7
  - anke1460
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-22 00:00:00.000000000 Z
11
+ date: 2023-07-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -503,6 +503,7 @@ files:
503
503
  - app/views/educode_sales/places/new.html.erb
504
504
  - app/views/educode_sales/plans/_monthPlan.html.erb
505
505
  - app/views/educode_sales/plans/_monthly.html.erb
506
+ - app/views/educode_sales/plans/_target_track.html.erb
506
507
  - app/views/educode_sales/plans/_weekPlan.html.erb
507
508
  - app/views/educode_sales/plans/_weekly.html.erb
508
509
  - app/views/educode_sales/plans/_yearPlan.html.erb
@@ -532,6 +533,7 @@ files:
532
533
  - app/views/educode_sales/plans/show_monthly.html.erb
533
534
  - app/views/educode_sales/plans/show_week.html.erb
534
535
  - app/views/educode_sales/plans/show_weekly.html.erb
536
+ - app/views/educode_sales/plans/target_track.js.erb
535
537
  - app/views/educode_sales/plans/weekly.js.erb
536
538
  - app/views/educode_sales/plans/year_plan.js.erb
537
539
  - app/views/educode_sales/plans/years_plan.json.jbuilder
@@ -577,6 +579,7 @@ files:
577
579
  - app/views/educode_sales/sale_trends/_business_area.html.erb
578
580
  - app/views/educode_sales/sale_trends/_business_followup_analysis.html.erb
579
581
  - app/views/educode_sales/sale_trends/_goal_forecast.html.erb
582
+ - app/views/educode_sales/sale_trends/_return_money_forecast.html.erb
580
583
  - app/views/educode_sales/sale_trends/_sales_analysis.html.erb
581
584
  - app/views/educode_sales/sale_trends/_sales_followup_analysis.html.erb
582
585
  - app/views/educode_sales/sale_trends/_user_stat.html.erb
@@ -585,6 +588,7 @@ files:
585
588
  - app/views/educode_sales/sale_trends/business_followup_analysis.js.erb
586
589
  - app/views/educode_sales/sale_trends/goal_forecast.js.erb
587
590
  - app/views/educode_sales/sale_trends/operations.html.erb
591
+ - app/views/educode_sales/sale_trends/return_money_forecast.js.erb
588
592
  - app/views/educode_sales/sale_trends/sales_analysis.js.erb
589
593
  - app/views/educode_sales/sale_trends/sales_followup_analysis.js.erb
590
594
  - app/views/educode_sales/sale_trends/trends.html.erb
@@ -772,7 +776,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
772
776
  - !ruby/object:Gem::Version
773
777
  version: '0'
774
778
  requirements: []
775
- rubygems_version: 3.0.9
779
+ rubygems_version: 3.0.0
776
780
  signing_key:
777
781
  specification_version: 4
778
782
  summary: Summary of EducodeSales.