educode_sales 1.10.41 → 1.10.46
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/educode_sales/plans_controller.rb +14 -0
- data/app/controllers/educode_sales/sale_trends_controller.rb +65 -0
- data/app/controllers/educode_sales/teachers_controller.rb +7 -2
- data/app/helpers/educode_sales/sale_trends_helper.rb +410 -0
- data/app/views/educode_sales/plans/_target_track.html.erb +178 -0
- data/app/views/educode_sales/plans/index.html.erb +5 -0
- data/app/views/educode_sales/plans/target_track.js.erb +1 -0
- data/app/views/educode_sales/sale_trends/_return_money_forecast.html.erb +176 -0
- data/app/views/educode_sales/sale_trends/return_money_forecast.js.erb +1 -0
- data/app/views/educode_sales/sale_trends/trends.html.erb +6 -0
- data/app/views/educode_sales/teachers/_index.html.erb +21 -9
- data/config/routes.rb +2 -0
- data/lib/educode_sales/version.rb +1 -1
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee0e4fc5519c5e1dc171f8d0402f6f3e681e9b89636a7f424a642aaf88a23ce9
|
4
|
+
data.tar.gz: c060d33dfc08508f868182e5c3b8f8d780a20c03d8c300631a7a7c39316bfccc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 = ?"
|
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.
|
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
|
-
|
115
|
-
|
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
|
-
|
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
|
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.
|
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-
|
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.
|
779
|
+
rubygems_version: 3.0.0
|
776
780
|
signing_key:
|
777
781
|
specification_version: 4
|
778
782
|
summary: Summary of EducodeSales.
|