educode_sales 1.10.21 → 1.10.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/educode_sales/ideas_controller.rb +36 -10
- data/app/controllers/educode_sales/sale_trends_controller.rb +102 -0
- data/app/helpers/educode_sales/sale_trends_helper.rb +80 -0
- data/app/models/educode_sales/sale_trend.rb +2 -0
- data/app/views/educode_sales/ideas/_index.html.erb +37 -1
- data/app/views/educode_sales/ideas/assign.html.erb +45 -0
- data/app/views/educode_sales/ideas/assign_sale_staff.html.erb +45 -0
- data/app/views/educode_sales/ideas/edit.html.erb +9 -9
- data/app/views/educode_sales/ideas/new.html.erb +9 -9
- data/app/views/educode_sales/sale_trends/_visit_analysis.html.erb +187 -0
- data/app/views/educode_sales/sale_trends/trends.html.erb +6 -0
- data/app/views/educode_sales/sale_trends/visit_analysis.js.erb +1 -0
- data/config/routes.rb +5 -0
- data/lib/educode_sales/version.rb +1 -1
- metadata +5 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ac157bfbdbc5c1aceeef3b0d0af4b81e74b6835ddda09a5beae4188f23720391
|
|
4
|
+
data.tar.gz: a4f7c4077fc9af0f5374fc3efec8bf42e5c3a57a27dc78090a5727cabe2f5510
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 804531ab845025fe61054b79b248a5f1f83e4194d0c23cad2f0fb4c49978db71eb695815723d50e7255fa35a4aa0b0154babb156fdd5cd953808bb2a1b56a9e9
|
|
7
|
+
data.tar.gz: 13484d3b014be703413f41b03938881aeb56bd1b7cf97f721f055f9a0aa869dfedc6b948ddbd57bb7b3174c2e3aa171dc7efa5823821f3e2b903e1e1ec9b2591
|
|
@@ -3,7 +3,35 @@ require_dependency "educode_sales/application_controller"
|
|
|
3
3
|
module EducodeSales
|
|
4
4
|
class IdeasController < ApplicationController
|
|
5
5
|
|
|
6
|
-
before_action :find_idea, only: [:edit, :destroy, :detail, :history, :update]
|
|
6
|
+
before_action :find_idea, only: [:edit, :destroy, :detail, :history, :update, :assign, :assign_staff, :assign_sale_staff, :update_sale_staff]
|
|
7
|
+
|
|
8
|
+
def assign
|
|
9
|
+
selected_staff_ids = @idea.assist_staff_ids.map(&:to_i)
|
|
10
|
+
staffs = Staff.where.not(role_id: 11).includes(:user)
|
|
11
|
+
gon.ideas_staffs = staffs.map { |d| { name: d.user.real_name, value: d.id, selected: selected_staff_ids.include?(d.id) } }
|
|
12
|
+
render layout: false
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# 指派协作人 assist_staff_ids协作人
|
|
16
|
+
def assign_staff
|
|
17
|
+
@idea.assist_staff_ids = params[:to_id].to_s.split(",")
|
|
18
|
+
@idea.save
|
|
19
|
+
render_success
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def assign_sale_staff
|
|
23
|
+
selected_staff_ids = Array(@idea.staff_id)
|
|
24
|
+
staffs = Staff.where.not(role_id: 11).includes(:user)
|
|
25
|
+
gon.sales_staffs = staffs.map { |d| { name: d.user.real_name, value: d.id, selected: selected_staff_ids.include?(d.id) } }
|
|
26
|
+
render layout: false
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# 指派方案经理 staff_id
|
|
30
|
+
def update_sale_staff
|
|
31
|
+
@idea.staff_id = params[:to_id]
|
|
32
|
+
@idea.save
|
|
33
|
+
render_success
|
|
34
|
+
end
|
|
7
35
|
|
|
8
36
|
def index
|
|
9
37
|
respond_to do |format|
|
|
@@ -24,16 +52,14 @@ module EducodeSales
|
|
|
24
52
|
level = @current_admin.role.role_areas.find_by(clazz: '方案管理').try(:level)
|
|
25
53
|
case level
|
|
26
54
|
when '自己'
|
|
27
|
-
|
|
28
|
-
# @businesses = Business.where("educode_sales_businesses.staff_id = ? OR educode_sales_businesses.id in (?)", @current_admin.id, business_ids)
|
|
29
|
-
idea_ids = Idea.all.select { |d| Array(d.other_staff_ids).include?(@current_admin.id) }.map { |d| d.id }
|
|
55
|
+
idea_ids = Idea.all.select { |d| Array(d.other_staff_ids).include?(@current_admin.id) || d.sale_staff_id == @current_admin.id || Array(d.assist_staff_ids).include?(@current_admin.id) || d.staff_id == @current_admin.id }.map { |d| d.id }
|
|
30
56
|
@ideas = Idea.where("educode_sales_ideas.creator_id = ? OR educode_sales_ideas.id in (?)", @current_admin.id, idea_ids)
|
|
31
57
|
when '区域'
|
|
32
58
|
# 查看区域商机,需要排除掉其它人员手上的监管学校
|
|
33
59
|
other_staff_school_id = EducodeSales::StaffSchool.where.not(staff_id: @current_admin.id).where("school_id IN (SELECT school_id FROM educode_sales_staff_schools WHERE staff_id = #{@current_admin.id}) IS NOT TRUE").distinct.pluck :school_id
|
|
34
60
|
|
|
35
61
|
school_ids = School.where(province: @current_admin.areas.pluck(:name)).pluck(:id) + StaffSchool.where(staff_id: @current_admin.id).pluck(:school_id) - other_staff_school_id
|
|
36
|
-
idea_ids = Idea.all.select { |d| Array(d.other_staff_ids).include?(@current_admin.id) }.map { |d| d.id }
|
|
62
|
+
idea_ids = Idea.all.select { |d| Array(d.other_staff_ids).include?(@current_admin.id) || d.sale_staff_id == @current_admin.id || Array(d.assist_staff_ids).include?(@current_admin.id) || d.staff_id == @current_admin.id }.map { |d| d.id }
|
|
37
63
|
@ideas = @ideas.joins(department: :school).where("schools.id in (?) OR educode_sales_ideas.creator_id = ? OR educode_sales_ideas.id in (?)", school_ids, @current_admin.id, idea_ids)
|
|
38
64
|
else
|
|
39
65
|
@ideas = @ideas
|
|
@@ -116,8 +142,8 @@ module EducodeSales
|
|
|
116
142
|
idea.department_id = idea.business&.department_id
|
|
117
143
|
end
|
|
118
144
|
idea.attachment_ids = attachment_ids
|
|
119
|
-
idea.assist_staff_ids = assist_staff_ids
|
|
120
|
-
idea.other_staff_ids = other_staff_ids
|
|
145
|
+
# idea.assist_staff_ids = assist_staff_ids
|
|
146
|
+
# idea.other_staff_ids = other_staff_ids
|
|
121
147
|
idea.save
|
|
122
148
|
render_success
|
|
123
149
|
end
|
|
@@ -134,11 +160,11 @@ module EducodeSales
|
|
|
134
160
|
@idea.assign_attributes(idea_params)
|
|
135
161
|
# @idea.school_id = Department.find_by_id(@idea.department_id)&.school_id
|
|
136
162
|
assist_staff_ids = Array(params[:assist_staff_ids].to_s.split(","))
|
|
137
|
-
@idea.assist_staff_ids = assist_staff_ids
|
|
163
|
+
# @idea.assist_staff_ids = assist_staff_ids
|
|
138
164
|
attachment_ids = Array(params[:attachment_ids].to_s.split(","))
|
|
139
165
|
@idea.attachment_ids = attachment_ids
|
|
140
166
|
other_staff_ids = Array(params[:other_staff_ids].to_s.split(","))
|
|
141
|
-
@idea.other_staff_ids = other_staff_ids
|
|
167
|
+
# @idea.other_staff_ids = other_staff_ids
|
|
142
168
|
if @idea.business_id.present?
|
|
143
169
|
@idea.school_id = @idea.business&.department&.school_id
|
|
144
170
|
@idea.department_id = @idea.business&.department_id
|
|
@@ -267,7 +293,7 @@ module EducodeSales
|
|
|
267
293
|
params.permit(:name, :level, :staff_id,
|
|
268
294
|
:status, :types, :model, :hardware, :project,
|
|
269
295
|
:money, :end_time, :content, :department_id, :school_id,
|
|
270
|
-
:manager_name, :manager_phone, :school_name, :department_name, :
|
|
296
|
+
:manager_name, :manager_phone, :school_name, :department_name, :attachment_id, :idea_type, :business_id)
|
|
271
297
|
end
|
|
272
298
|
|
|
273
299
|
def find_idea
|
|
@@ -417,6 +417,49 @@ module EducodeSales
|
|
|
417
417
|
end
|
|
418
418
|
end
|
|
419
419
|
|
|
420
|
+
#拜访分析
|
|
421
|
+
def visit_analysis
|
|
422
|
+
sort_by = params[:sort_by].present? ? params[:sort_by] : "desc"
|
|
423
|
+
user_name = params[:user_name]
|
|
424
|
+
visit_type = params[:visit_type].present? ? params[:visit_type].split(",") : ""
|
|
425
|
+
title_names = %w[本年拜访数 本季拜访数 本月拜访数 本周拜访数]
|
|
426
|
+
respond_to do |format|
|
|
427
|
+
format.js do
|
|
428
|
+
@user_names = EducodeSales::Attendance.pluck(:name).uniq.map{|d| {name: d, value: d}}
|
|
429
|
+
@visit_types = SaleTrend::VISIT_TYPE.map {|d| {name: d[0], value: d[1]}}
|
|
430
|
+
sql = "SELECT name, count(*) as name_count FROM `educode_sales_attendances` WHERE (attendance_date >= '#{Time.now.beginning_of_year}' and attendance_date <= '#{Time.now.end_of_year}') group by name order by name_count desc limit 30"
|
|
431
|
+
visit_count = EducodeSales::Attendance.find_by_sql(sql).map{|d| [d.name, d.name_count]}
|
|
432
|
+
#年拜访量前30的用户名
|
|
433
|
+
top_thirty_username = visit_count.map{ |d| d[0]}
|
|
434
|
+
@visit_count_data = visit_user_type_name(top_thirty_username, sort_by, visit_type, title_names)
|
|
435
|
+
end
|
|
436
|
+
format.json do
|
|
437
|
+
if params[:user_type].present? && params[:user_type] == "name"
|
|
438
|
+
if user_name.present?
|
|
439
|
+
sql_by_name = "SELECT name, count(*) as name_count FROM `educode_sales_attendances` WHERE (attendance_date >= '#{Time.now.beginning_of_year}' and attendance_date <= '#{Time.now.end_of_year}') and name like '%#{user_name}%' group by name"
|
|
440
|
+
else
|
|
441
|
+
sql_by_name = "SELECT name, count(*) as name_count FROM `educode_sales_attendances` WHERE (attendance_date >= '#{Time.now.beginning_of_year}' and attendance_date <= '#{Time.now.end_of_year}') group by name order by name_count desc limit 30"
|
|
442
|
+
end
|
|
443
|
+
visit_count = EducodeSales::Attendance.find_by_sql(sql_by_name).map{|d| [d.name, d.name_count]}
|
|
444
|
+
#年拜访量前30的用户名
|
|
445
|
+
top_thirty_username = visit_count.map{ |d| d[0]}
|
|
446
|
+
@visit_count_data = visit_user_type_name(top_thirty_username, sort_by, visit_type, title_names)
|
|
447
|
+
else
|
|
448
|
+
if user_name.present?
|
|
449
|
+
sql_by_customer = "SELECT name, customer, count(*) as customer_count FROM `educode_sales_attendances` WHERE (attendance_date >= '#{Time.now.beginning_of_year}' and attendance_date <= '#{Time.now.end_of_year}') and name like '%#{user_name}%' group by customer order by customer_count desc limit 30"
|
|
450
|
+
else
|
|
451
|
+
sql_by_customer = "SELECT name, customer, count(*) as customer_count FROM `educode_sales_attendances` WHERE (attendance_date >= '#{Time.now.beginning_of_year}' and attendance_date <= '#{Time.now.end_of_year}') group by customer order by customer_count desc limit 30"
|
|
452
|
+
end
|
|
453
|
+
visit_count = EducodeSales::Attendance.find_by_sql(sql_by_customer).map{|d| [d.customer, d.customer_count]}
|
|
454
|
+
#年拜访量前30的用户名
|
|
455
|
+
top_thirty_customer = visit_count.map{ |d| d[0]}
|
|
456
|
+
@visit_count_data = visit_user_type_customer(top_thirty_customer, sort_by, visit_type, title_names)
|
|
457
|
+
end
|
|
458
|
+
render json: {data: @visit_count_data }
|
|
459
|
+
end
|
|
460
|
+
end
|
|
461
|
+
end
|
|
462
|
+
|
|
420
463
|
private
|
|
421
464
|
|
|
422
465
|
def sale_trend_params
|
|
@@ -802,5 +845,64 @@ module EducodeSales
|
|
|
802
845
|
@forecast_count_data_1 = @forecast_count_data[1]
|
|
803
846
|
end
|
|
804
847
|
|
|
848
|
+
def visit_user_type_name(top_thirty_username, sort_by, visit_type, title_names)
|
|
849
|
+
#本年拜访数
|
|
850
|
+
visit_count_year = EducodeSales::Attendance.where("name in (?)", top_thirty_username)
|
|
851
|
+
.where(" attendance_date >= '#{Time.now.beginning_of_year}' and attendance_date <= '#{Time.now.end_of_year}' ")
|
|
852
|
+
.group(:name).select("name, count(*) name_count").order("name_count #{sort_by}")&.map{ |d| [d.name, d.name_count]}
|
|
853
|
+
|
|
854
|
+
#本季拜访数
|
|
855
|
+
current_year = Time.now.year
|
|
856
|
+
current_month = Time.now.month
|
|
857
|
+
start_month = (current_month - 1) / 3 * 3 + 1
|
|
858
|
+
end_month = start_month + 2
|
|
859
|
+
start_date = Date.new(current_year, start_month, 1).strftime("%Y-%m-%d") + " 00:00:00"
|
|
860
|
+
end_date = Date.new(current_year, end_month, -1).strftime("%Y-%m-%d") + " 23:59:59"
|
|
861
|
+
visit_count_season = EducodeSales::Attendance.where("name in (?)", top_thirty_username)
|
|
862
|
+
.where("attendance_date >= '#{start_date}' and attendance_date <= '#{end_date}'")
|
|
863
|
+
.group(:name).select("name, count(*) name_count").order("name_count #{sort_by}")&.map{ |d| [d.name, d.name_count]}
|
|
864
|
+
|
|
865
|
+
#本月拜访数
|
|
866
|
+
visit_count_month = EducodeSales::Attendance.where("name in (?)", top_thirty_username)
|
|
867
|
+
.where("attendance_date >= '#{Time.now.beginning_of_month}' and attendance_date <= '#{Time.now.end_of_month}'")
|
|
868
|
+
.group(:name).select("name, count(*) name_count").order("name_count #{sort_by}")&.map{ |d| [d.name, d.name_count]}
|
|
869
|
+
|
|
870
|
+
#本周拜访数
|
|
871
|
+
visit_count_week = EducodeSales::Attendance.where("name in (?)", top_thirty_username)
|
|
872
|
+
.where("attendance_date >= '#{Time.now.beginning_of_week}' and attendance_date <= '#{Time.now.end_of_week}'")
|
|
873
|
+
.group(:name).select("name, count(*) name_count").order("name_count #{sort_by}")&.map{ |d| [d.name, d.name_count]}
|
|
874
|
+
|
|
875
|
+
visit_analysis_charts(visit_count_year, visit_count_season, visit_count_month, visit_count_week, visit_type, title_names)
|
|
876
|
+
end
|
|
877
|
+
|
|
878
|
+
def visit_user_type_customer(top_thirty_customer, sort_by, visit_type, title_names)
|
|
879
|
+
#本年拜访数
|
|
880
|
+
visit_count_year = EducodeSales::Attendance.where("customer in (?)", top_thirty_customer)
|
|
881
|
+
.where(" attendance_date >= '#{Time.now.beginning_of_year}' and attendance_date <= '#{Time.now.end_of_year}' ")
|
|
882
|
+
.group(:customer).select("customer, count(*) customer_count").order("customer_count #{sort_by}")&.map{ |d| [d.customer, d.customer_count]}
|
|
883
|
+
|
|
884
|
+
#本季拜访数
|
|
885
|
+
current_year = Time.now.year
|
|
886
|
+
current_month = Time.now.month
|
|
887
|
+
start_month = (current_month - 1) / 3 * 3 + 1
|
|
888
|
+
end_month = start_month + 2
|
|
889
|
+
start_date = Date.new(current_year, start_month, 1).strftime("%Y-%m-%d") + " 00:00:00"
|
|
890
|
+
end_date = Date.new(current_year, end_month, -1).strftime("%Y-%m-%d") + " 23:59:59"
|
|
891
|
+
visit_count_season = EducodeSales::Attendance.where("customer in (?)", top_thirty_customer)
|
|
892
|
+
.where("attendance_date >= '#{start_date}' and attendance_date <= '#{end_date}'")
|
|
893
|
+
.group(:customer).select("customer, count(*) customer_count").order("customer_count #{sort_by}")&.map{ |d| [d.customer, d.customer_count]}
|
|
894
|
+
|
|
895
|
+
#本月拜访数
|
|
896
|
+
visit_count_month = EducodeSales::Attendance.where("customer in (?)", top_thirty_customer)
|
|
897
|
+
.where("attendance_date >= '#{Time.now.beginning_of_month}' and attendance_date <= '#{Time.now.end_of_month}'")
|
|
898
|
+
.group(:customer).select("customer, count(*) customer_count").order("customer_count #{sort_by}")&.map{ |d| [d.customer, d.customer_count]}
|
|
899
|
+
|
|
900
|
+
#本周拜访数
|
|
901
|
+
visit_count_week = EducodeSales::Attendance.where("customer in (?)", top_thirty_customer)
|
|
902
|
+
.where("attendance_date >= '#{Time.now.beginning_of_week}' and attendance_date <= '#{Time.now.end_of_week}'")
|
|
903
|
+
.group(:customer).select("customer, count(*) customer_count").order("customer_count #{sort_by}")&.map{ |d| [d.customer, d.customer_count]}
|
|
904
|
+
|
|
905
|
+
visit_analysis_charts(visit_count_year, visit_count_season, visit_count_month, visit_count_week, visit_type, title_names)
|
|
906
|
+
end
|
|
805
907
|
end
|
|
806
908
|
end
|
|
@@ -247,6 +247,86 @@ module EducodeSales
|
|
|
247
247
|
[hash_a, hash_b]
|
|
248
248
|
end
|
|
249
249
|
|
|
250
|
+
def visit_analysis_charts(visit_count_year, visit_count_season, visit_count_month, visit_count_week, visit_type, title_names)
|
|
251
|
+
names = visit_count_year.map{|d| d[0]}
|
|
252
|
+
|
|
253
|
+
visit_count_season_data = []
|
|
254
|
+
names.each do |name|
|
|
255
|
+
data = visit_count_season.find { |d| d[0] == name}
|
|
256
|
+
if data
|
|
257
|
+
visit_count_season_data << data
|
|
258
|
+
else
|
|
259
|
+
visit_count_season_data << [name, 0]
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
visit_count_month_data = []
|
|
264
|
+
names.each do |name|
|
|
265
|
+
data = visit_count_month.find { |d| d[0] == name}
|
|
266
|
+
if data
|
|
267
|
+
visit_count_month_data << data
|
|
268
|
+
else
|
|
269
|
+
visit_count_month_data << [name, 0]
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
visit_count_week_data = []
|
|
274
|
+
names.each do |name|
|
|
275
|
+
data = visit_count_week.find { |d| d[0] == name}
|
|
276
|
+
if data
|
|
277
|
+
visit_count_week_data << data
|
|
278
|
+
else
|
|
279
|
+
visit_count_week_data << [name, 0]
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
year = {
|
|
284
|
+
label: title_names[0],
|
|
285
|
+
data: visit_count_year.map {|d| d[1].to_i},
|
|
286
|
+
backgroundColor: 'rgba(255, 99, 132, 1)'}
|
|
287
|
+
|
|
288
|
+
season = {
|
|
289
|
+
label: title_names[1],
|
|
290
|
+
data: visit_count_season_data.map {|d| d[1].to_i},
|
|
291
|
+
backgroundColor: 'rgba(255, 159, 64, 1)'}
|
|
292
|
+
|
|
293
|
+
month = {
|
|
294
|
+
label: title_names[2],
|
|
295
|
+
data:visit_count_month_data.map {|d| d[1].to_i},
|
|
296
|
+
backgroundColor: 'rgba(54, 162, 235, 1)'}
|
|
297
|
+
|
|
298
|
+
week = {
|
|
299
|
+
label: title_names[3],
|
|
300
|
+
data: visit_count_week_data.map {|d| d[1].to_i},
|
|
301
|
+
backgroundColor: 'rgba(153, 102, 255, 1)'}
|
|
302
|
+
|
|
303
|
+
final_data = []
|
|
304
|
+
if visit_type.include?("1")
|
|
305
|
+
final_data << year
|
|
306
|
+
end
|
|
307
|
+
if visit_type.include?("2")
|
|
308
|
+
final_data << season
|
|
309
|
+
end
|
|
310
|
+
if visit_type.include?("3")
|
|
311
|
+
final_data << month
|
|
312
|
+
end
|
|
313
|
+
if visit_type.include?("4")
|
|
314
|
+
final_data << week
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
if visit_type.present?
|
|
318
|
+
{
|
|
319
|
+
labels: names,
|
|
320
|
+
datasets: final_data
|
|
321
|
+
}
|
|
322
|
+
else
|
|
323
|
+
{
|
|
324
|
+
labels: names,
|
|
325
|
+
datasets: [year, season, month, week]
|
|
326
|
+
}
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
|
|
250
330
|
private
|
|
251
331
|
|
|
252
332
|
def plan_get(staff_id, time_range, type, property)
|
|
@@ -9,5 +9,7 @@ module EducodeSales
|
|
|
9
9
|
'#DC7633', '#839192', '#6C3483', '#B03A2E', '#7B7D7D', '#4D5656', '#28B463', '#0E6655', '#F39C12', '#0E6251', '#1B4F72',
|
|
10
10
|
'#FAE5D3', '#82E0AA', '#FF00FF', '#663399', '#4B0082', '#7CFC00'
|
|
11
11
|
]
|
|
12
|
+
|
|
13
|
+
VISIT_TYPE = [["本年拜访数", 1],["本季拜访数", 2],["本月拜访数", 3],["本周拜访数", 4]]
|
|
12
14
|
end
|
|
13
15
|
end
|
|
@@ -102,6 +102,8 @@
|
|
|
102
102
|
<a class="layui-btn layui-btn-normal layui-btn-xs data-count-edit" lay-event="idea_recycle_s">恢复</a>
|
|
103
103
|
<% end %>
|
|
104
104
|
{{# }else{}}
|
|
105
|
+
<a class="layui-btn layui-btn-normal layui-btn-xs data-count-edit" lay-event="assign">指派协作人</a>
|
|
106
|
+
<a class="layui-btn layui-btn-normal layui-btn-xs data-count-edit" lay-event="assign_sale_staff">指派方案经理</a>
|
|
105
107
|
<% if can? :add_follow, EducodeSales::Idea %>
|
|
106
108
|
<a class="layui-btn layui-btn-normal layui-btn-xs data-count-add_follow" lay-event="add_follows">添加跟进</a>
|
|
107
109
|
<% end %>
|
|
@@ -256,7 +258,7 @@
|
|
|
256
258
|
},
|
|
257
259
|
{
|
|
258
260
|
title: '操作',
|
|
259
|
-
minWidth:
|
|
261
|
+
minWidth: 700,
|
|
260
262
|
toolbar: '#currentTableBar',
|
|
261
263
|
align: "center",
|
|
262
264
|
fixed: 'right'
|
|
@@ -453,6 +455,40 @@
|
|
|
453
455
|
$(window).on("resize", function () {
|
|
454
456
|
layer.full(followup_index);
|
|
455
457
|
});
|
|
458
|
+
} else if (obj.event === 'assign') { //协作人
|
|
459
|
+
var content = miniPage.getHrefContent('/missions/ideas/' + id + '/assign');
|
|
460
|
+
var openWH = miniPage.getOpenWidthHeight();
|
|
461
|
+
var name = data.name;
|
|
462
|
+
sindex = layer.open({
|
|
463
|
+
title: '指派协作人',
|
|
464
|
+
type: 1,
|
|
465
|
+
shade: 0.2,
|
|
466
|
+
maxmin: true,
|
|
467
|
+
shadeClose: true,
|
|
468
|
+
area: ['600px', '300px'],
|
|
469
|
+
content: content
|
|
470
|
+
});
|
|
471
|
+
$(window).on("resize", function () {
|
|
472
|
+
layer.full(sindex);
|
|
473
|
+
});
|
|
474
|
+
return false;
|
|
475
|
+
} else if (obj.event === 'assign_sale_staff') { //指派方案经理
|
|
476
|
+
var content = miniPage.getHrefContent('/missions/ideas/' + id + '/assign_sale_staff');
|
|
477
|
+
var openWH = miniPage.getOpenWidthHeight();
|
|
478
|
+
var name = data.name;
|
|
479
|
+
sindex = layer.open({
|
|
480
|
+
title: "指派方案经理",
|
|
481
|
+
type: 1,
|
|
482
|
+
shade: 0.2,
|
|
483
|
+
maxmin: true,
|
|
484
|
+
shadeClose: true,
|
|
485
|
+
area: ['600px', '300px'],
|
|
486
|
+
content: content
|
|
487
|
+
});
|
|
488
|
+
$(window).on("resize", function () {
|
|
489
|
+
layer.full(sindex);
|
|
490
|
+
});
|
|
491
|
+
return false;
|
|
456
492
|
} else if (obj.event === 'idea_recycle') {
|
|
457
493
|
layer.confirm('确定删除' + data.name, function (index) {
|
|
458
494
|
request.delete('missions/ideas/' + id, {}, function (res) {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<%= Gon::Base.render_data %>
|
|
2
|
+
<div class="layui-form layuimini-form" style="padding:30px">
|
|
3
|
+
<div class="layui-form-item">
|
|
4
|
+
<label class="layui-form-label required">选择协作人:</label>
|
|
5
|
+
<div class="layui-input-block" style="width: 300px">
|
|
6
|
+
<div id="sales_staff_id"></div>
|
|
7
|
+
</div>
|
|
8
|
+
</div>
|
|
9
|
+
<hr>
|
|
10
|
+
<div class="layui-form-item">
|
|
11
|
+
<div class="layui-input-block">
|
|
12
|
+
<button class="layui-btn layui-btn-normal" lay-submit lay-filter="saveBtn">确认保存</button>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<script>
|
|
18
|
+
layui.use(['form', 'table', 'upload', 'laytpl', 'request', 'selectInput'], function () {
|
|
19
|
+
var form = layui.form,
|
|
20
|
+
layer = layui.layer,
|
|
21
|
+
table = layui.table,
|
|
22
|
+
laytpl = layui.laytpl,
|
|
23
|
+
request = layui.request,
|
|
24
|
+
$ = layui.$;
|
|
25
|
+
|
|
26
|
+
form.render();
|
|
27
|
+
staff_list_select = xmSelect.render({
|
|
28
|
+
el: '#sales_staff_id',
|
|
29
|
+
data: gon.ideas_staffs,
|
|
30
|
+
filterable: true,
|
|
31
|
+
radio: false,
|
|
32
|
+
})
|
|
33
|
+
var parentIndex = layer.index;
|
|
34
|
+
form.on('submit(saveBtn)', function (data) {
|
|
35
|
+
layer.confirm('确定指派协作人?', function (index) {
|
|
36
|
+
request.post('missions/ideas/' + parent.id + "/assign_staff", {to_id: staff_list_select.getValue('valueStr')}, function (res) {
|
|
37
|
+
layer.close(index);
|
|
38
|
+
layer.close(parentIndex)
|
|
39
|
+
parent.table.reload('ideas_table')
|
|
40
|
+
})
|
|
41
|
+
});
|
|
42
|
+
return false;
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
</script>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<%= Gon::Base.render_data %>
|
|
2
|
+
<div class="layui-form layuimini-form" style="padding:30px">
|
|
3
|
+
<div class="layui-form-item">
|
|
4
|
+
<label class="layui-form-label required">选择方案经理:</label>
|
|
5
|
+
<div class="layui-input-block" style="width: 300px">
|
|
6
|
+
<div id="sales_id"></div>
|
|
7
|
+
</div>
|
|
8
|
+
</div>
|
|
9
|
+
<hr>
|
|
10
|
+
<div class="layui-form-item">
|
|
11
|
+
<div class="layui-input-block">
|
|
12
|
+
<button class="layui-btn layui-btn-normal" lay-submit lay-filter="saveBtn">确认保存</button>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<script>
|
|
18
|
+
layui.use(['form', 'table', 'upload', 'laytpl', 'request', 'selectInput'], function () {
|
|
19
|
+
var form = layui.form,
|
|
20
|
+
layer = layui.layer,
|
|
21
|
+
table = layui.table,
|
|
22
|
+
laytpl = layui.laytpl,
|
|
23
|
+
request = layui.request,
|
|
24
|
+
$ = layui.$;
|
|
25
|
+
|
|
26
|
+
form.render();
|
|
27
|
+
staff_list_select = xmSelect.render({
|
|
28
|
+
el: '#sales_id',
|
|
29
|
+
data: gon.sales_staffs,
|
|
30
|
+
filterable: true,
|
|
31
|
+
radio: true,
|
|
32
|
+
})
|
|
33
|
+
var parentIndex = layer.index;
|
|
34
|
+
form.on('submit(saveBtn)', function (data) {
|
|
35
|
+
layer.confirm('确定指派方案经理?', function (index) {
|
|
36
|
+
request.post('missions/ideas/' + parent.id + "/update_sale_staff", {to_id: staff_list_select.getValue('valueStr')}, function (res) {
|
|
37
|
+
layer.close(index);
|
|
38
|
+
layer.close(parentIndex)
|
|
39
|
+
parent.table.reload('ideas_table')
|
|
40
|
+
})
|
|
41
|
+
});
|
|
42
|
+
return false;
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
</script>
|
|
@@ -41,20 +41,20 @@
|
|
|
41
41
|
</div>
|
|
42
42
|
</div>
|
|
43
43
|
<div class="layui-col-md6">
|
|
44
|
-
<labeL class="layui-form-label"
|
|
44
|
+
<labeL class="layui-form-label required">项目名称:</labeL>
|
|
45
45
|
<div class="layui-input-block">
|
|
46
|
-
<div id="
|
|
46
|
+
<div id="business_id" style="width: 600px;"></div>
|
|
47
47
|
</div>
|
|
48
48
|
</div>
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
<div class="layui-col-md6">
|
|
52
|
-
<labeL class="layui-form-label required">项目名称:</labeL>
|
|
49
|
+
<div class="layui-col-md6" style="display: none">
|
|
50
|
+
<labeL class="layui-form-label">协作人:</labeL>
|
|
53
51
|
<div class="layui-input-block">
|
|
54
|
-
<div id="
|
|
52
|
+
<div id="assist_staff_ids"></div>
|
|
55
53
|
</div>
|
|
56
54
|
</div>
|
|
57
|
-
|
|
55
|
+
</div>
|
|
56
|
+
<div class="layui-row" style="padding-top: 15px;display: none">
|
|
57
|
+
<div class="layui-col-md6" style="display: none">
|
|
58
58
|
<labeL class="layui-form-label">方案经理:</labeL>
|
|
59
59
|
<div class="layui-input-block">
|
|
60
60
|
<div id="new_staff_id"></div>
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
<%= select_tag "idea_type", options_for_select(EducodeSales::Idea.idea_types.keys, @idea&.idea_type), { 'lay-filter': 'idea_type', include_blank: false } %>
|
|
97
97
|
</div>
|
|
98
98
|
</div>
|
|
99
|
-
<div class="layui-col-md6">
|
|
99
|
+
<div class="layui-col-md6" style="display: none">
|
|
100
100
|
<labeL class="layui-form-label">指派人:</labeL>
|
|
101
101
|
<div class="layui-input-block">
|
|
102
102
|
<div id="other_staff_ids"></div>
|
|
@@ -41,20 +41,20 @@
|
|
|
41
41
|
</div>
|
|
42
42
|
</div>
|
|
43
43
|
<div class="layui-col-md6">
|
|
44
|
-
<labeL class="layui-form-label"
|
|
44
|
+
<labeL class="layui-form-label required">项目名称:</labeL>
|
|
45
45
|
<div class="layui-input-block">
|
|
46
|
-
<div id="
|
|
46
|
+
<div id="business_id" style="width: 600px;"></div>
|
|
47
47
|
</div>
|
|
48
48
|
</div>
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
<div class="layui-col-md6">
|
|
52
|
-
<labeL class="layui-form-label required">项目名称:</labeL>
|
|
49
|
+
<div class="layui-col-md6" style="display: none">
|
|
50
|
+
<labeL class="layui-form-label">协作人:</labeL>
|
|
53
51
|
<div class="layui-input-block">
|
|
54
|
-
<div id="
|
|
52
|
+
<div id="assist_staff_ids"></div>
|
|
55
53
|
</div>
|
|
56
54
|
</div>
|
|
57
|
-
|
|
55
|
+
</div>
|
|
56
|
+
<div class="layui-row" style="padding-top: 15px;display: none">
|
|
57
|
+
<div class="layui-col-md6" style="display: none">
|
|
58
58
|
<labeL class="layui-form-label">方案经理:</labeL>
|
|
59
59
|
<div class="layui-input-block">
|
|
60
60
|
<div id="new_staff_id"></div>
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
<%= select_tag "idea_type", options_for_select(EducodeSales::Idea.idea_types.keys, @idea&.idea_type), { 'lay-filter': 'idea_type', include_blank: false } %>
|
|
97
97
|
</div>
|
|
98
98
|
</div>
|
|
99
|
-
<div class="layui-col-md6">
|
|
99
|
+
<div class="layui-col-md6" style="display: none">
|
|
100
100
|
<labeL class="layui-form-label">指派人:</labeL>
|
|
101
101
|
<div class="layui-input-block">
|
|
102
102
|
<div id="other_staff_ids"></div>
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
<div id="tab_8">
|
|
2
|
+
<div class="" style="padding-right: 50px">
|
|
3
|
+
<div style="margin: 10px 10px 10px 10px">
|
|
4
|
+
<form class="layui-form layui-form-pane" lay-filter="search_visit_form">
|
|
5
|
+
<div class="layui-form-item">
|
|
6
|
+
<div class="layui-inline m-t-10">
|
|
7
|
+
<label class="layui-form-label">维度</label>
|
|
8
|
+
<div class="layui-input-inline">
|
|
9
|
+
<%= select_tag "user_type", options_for_select([['按销售经理','name'],['按客户','customer']],params[:user_type]), {'lay-filter': 'user_type'}%>
|
|
10
|
+
</div>
|
|
11
|
+
</div>
|
|
12
|
+
<div class="layui-inline m-t-10">
|
|
13
|
+
<label class="layui-form-label">拜访统计</label>
|
|
14
|
+
<div class="layui-input-inline">
|
|
15
|
+
<div id="visit_type"></div>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
<div class="layui-inline m-t-10">
|
|
19
|
+
<label class="layui-form-label">销售经理</label>
|
|
20
|
+
<div class="layui-input-inline">
|
|
21
|
+
<div id="user_name"></div>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
<div class="layui-inline m-t-10">
|
|
25
|
+
<label class="layui-form-label">排序</label>
|
|
26
|
+
<div class="layui-input-inline">
|
|
27
|
+
<%= select_tag "sort_by", options_for_select([['', ''], ['升序', 'asc'], ['降序', 'desc']], params[:sort_by]), { include_blank: true } %>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
<div class="layui-inline">
|
|
31
|
+
<button type="reset" class="layui-btn layui-btn-primary" lay-submit lay-filter="reset_visit_search">重 置</button>
|
|
32
|
+
<button type="submit" class="layui-btn layui-btn-primary" lay-submit lay-filter="search_visit">搜 索</button>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
</form>
|
|
36
|
+
</div>
|
|
37
|
+
<canvas id="visit_myChart" width="960" height="350"></canvas>
|
|
38
|
+
<div class="two-header" style="margin-top: 30px;">
|
|
39
|
+
<table id="visit_table" lay-filter="visit_table"></table>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
<script>
|
|
44
|
+
layui.use(['form', 'jquery', 'request', 'element', 'laydate', 'table', 'miniPage'], function () {
|
|
45
|
+
var $ = layui.jquery,
|
|
46
|
+
form = layui.form,
|
|
47
|
+
table = layui.table,
|
|
48
|
+
request = layui.request;
|
|
49
|
+
|
|
50
|
+
//拜访统计选择
|
|
51
|
+
var visit_type_select = xmSelect.render({
|
|
52
|
+
el: '#visit_type',
|
|
53
|
+
name: 'visit_type',
|
|
54
|
+
data: <%=raw @visit_types.to_json %>,
|
|
55
|
+
});
|
|
56
|
+
//销售经理选择
|
|
57
|
+
var user_name_select = xmSelect.render({
|
|
58
|
+
el: '#user_name',
|
|
59
|
+
name: 'user_name',
|
|
60
|
+
data: <%=raw @user_names.to_json %>,
|
|
61
|
+
filterable: true,
|
|
62
|
+
radio: true
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
var options = {
|
|
66
|
+
events: false,
|
|
67
|
+
scales: {
|
|
68
|
+
yAxes: [{
|
|
69
|
+
ticks: {
|
|
70
|
+
suggestedMin: 0,
|
|
71
|
+
suggestedMax: 200,
|
|
72
|
+
stepSize: 20
|
|
73
|
+
}
|
|
74
|
+
}]
|
|
75
|
+
},
|
|
76
|
+
hover: {
|
|
77
|
+
animationDuration: 1
|
|
78
|
+
},
|
|
79
|
+
animation: {
|
|
80
|
+
duration: 1,
|
|
81
|
+
onComplete: function () {
|
|
82
|
+
var chartInstance = this.chart,
|
|
83
|
+
ctx = chartInstance.ctx;
|
|
84
|
+
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
|
|
85
|
+
ctx.textAlign = 'center';
|
|
86
|
+
ctx.textBaseline = 'bottom';
|
|
87
|
+
|
|
88
|
+
this.data.datasets.forEach(function (dataset, i) {
|
|
89
|
+
var meta = chartInstance.controller.getDatasetMeta(i);
|
|
90
|
+
meta.data.forEach(function (bar, index) {
|
|
91
|
+
var data = dataset.data[index];
|
|
92
|
+
ctx.fillText(data, bar._model.x, bar._model.y - 5);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
visit_count_data = <%=raw @visit_count_data.to_json %>;
|
|
100
|
+
|
|
101
|
+
//条形图
|
|
102
|
+
var ctx = document.getElementById('visit_myChart').getContext("2d");
|
|
103
|
+
var visit_myChart = new Chart(ctx, {
|
|
104
|
+
type: 'bar',
|
|
105
|
+
data: visit_count_data,
|
|
106
|
+
options: options
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
//重置按钮
|
|
110
|
+
form.on('submit(reset_visit_search)', function () {
|
|
111
|
+
form.val('search_visit_form', {
|
|
112
|
+
sort_by: ""
|
|
113
|
+
});
|
|
114
|
+
visit_type_select.setValue([]);
|
|
115
|
+
user_name_select.setValue([]);
|
|
116
|
+
return false;
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
//渲染表格
|
|
120
|
+
function renderTable(visit_count_data) {
|
|
121
|
+
var labels = [];
|
|
122
|
+
fields = [{field: 'col0', title: '', width:100}];
|
|
123
|
+
visit_count_data.labels.forEach(function (data, i) {
|
|
124
|
+
labels.push(data);
|
|
125
|
+
fields.push({field: 'col' + (i + 1), title: data, width: 100, align: 'center'})
|
|
126
|
+
});
|
|
127
|
+
var table_data = [];
|
|
128
|
+
visit_count_data.datasets.forEach(function (visit_data) {
|
|
129
|
+
var value = {};
|
|
130
|
+
value['col0'] = visit_data.label;
|
|
131
|
+
visit_data.data.forEach(function (v, i) {
|
|
132
|
+
value['col' + (i + 1)] = v
|
|
133
|
+
});
|
|
134
|
+
table_data.push(value)
|
|
135
|
+
});
|
|
136
|
+
table.render({
|
|
137
|
+
elem: '#visit_table',
|
|
138
|
+
height: 230,
|
|
139
|
+
limit: 1000,
|
|
140
|
+
page: false,
|
|
141
|
+
data: table_data,
|
|
142
|
+
cols: [fields]
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
renderTable(visit_count_data);
|
|
147
|
+
form.render();
|
|
148
|
+
|
|
149
|
+
//搜索监听
|
|
150
|
+
form.on("submit(search_visit)", function(data) {
|
|
151
|
+
var layer_index = layer.load(0, {shade: [0.1, '#fff']});
|
|
152
|
+
var visit_type_value = [];
|
|
153
|
+
if (document.getElementById('visit_type')) {
|
|
154
|
+
visit_type_select.getValue().forEach(function (d) {
|
|
155
|
+
visit_type_value.push(d.value)
|
|
156
|
+
})
|
|
157
|
+
}
|
|
158
|
+
data.field.visit_type = visit_type_value.join(",");
|
|
159
|
+
Rails.ajax({
|
|
160
|
+
url: '/missions/sale_trends/visit_analysis',
|
|
161
|
+
type: 'GET',
|
|
162
|
+
dataType: "json",
|
|
163
|
+
data: $.param(data.field, true),
|
|
164
|
+
success: function (res) {
|
|
165
|
+
visit_myChart.data.datasets = res.data.datasets;
|
|
166
|
+
visit_myChart.data.labels = res.data.labels;
|
|
167
|
+
visit_myChart.update();
|
|
168
|
+
renderTable(res.data);
|
|
169
|
+
layer.close(layer_index);
|
|
170
|
+
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
return false;
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
</script>
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
<li class="">销售人员跟进分析</li>
|
|
8
8
|
<li class="">中标预测图</li>
|
|
9
9
|
<li class="">用户分析</li>
|
|
10
|
+
<li class="">拜访分析</li>
|
|
10
11
|
</ul>
|
|
11
12
|
<div class="layui-tab-content">
|
|
12
13
|
<div class="layui-tab-item layui-show">
|
|
@@ -238,6 +239,9 @@
|
|
|
238
239
|
<div class="layui-tab-item">
|
|
239
240
|
<div id="page_7"></div>
|
|
240
241
|
</div>
|
|
242
|
+
<div class="layui-tab-item">
|
|
243
|
+
<div id="page_8"></div>
|
|
244
|
+
</div>
|
|
241
245
|
</div>
|
|
242
246
|
</div>
|
|
243
247
|
|
|
@@ -264,6 +268,8 @@
|
|
|
264
268
|
loadPage('/missions/sale_trends/goal_forecast')
|
|
265
269
|
} else if (data.index == 6 && $("#tab_7").length == 0) {
|
|
266
270
|
loadPage('/missions/sale_trends/user_stat')
|
|
271
|
+
} else if (data.index == 7 && $("#tab_8").length == 0) {
|
|
272
|
+
loadPage('/missions/sale_trends/visit_analysis')
|
|
267
273
|
}
|
|
268
274
|
});
|
|
269
275
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
$("#page_8").html("<%= j render 'visit_analysis' %>");
|
data/config/routes.rb
CHANGED
|
@@ -173,6 +173,7 @@ EducodeSales::Engine.routes.draw do
|
|
|
173
173
|
get :sales_followup_analysis
|
|
174
174
|
get :goal_forecast
|
|
175
175
|
get :user_stat
|
|
176
|
+
get :visit_analysis
|
|
176
177
|
end
|
|
177
178
|
end
|
|
178
179
|
|
|
@@ -383,6 +384,10 @@ EducodeSales::Engine.routes.draw do
|
|
|
383
384
|
get :upload_file
|
|
384
385
|
end
|
|
385
386
|
member do
|
|
387
|
+
get :assign
|
|
388
|
+
post :assign_staff
|
|
389
|
+
get :assign_sale_staff
|
|
390
|
+
post :update_sale_staff
|
|
386
391
|
get :show_schools
|
|
387
392
|
post :follow_up
|
|
388
393
|
put :update_advise
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: educode_sales
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.10.
|
|
4
|
+
version: 1.10.23
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- anke1460
|
|
@@ -418,6 +418,8 @@ files:
|
|
|
418
418
|
- app/views/educode_sales/ideas/add_courses.html.erb
|
|
419
419
|
- app/views/educode_sales/ideas/add_event.html.erb
|
|
420
420
|
- app/views/educode_sales/ideas/add_keys.html.erb
|
|
421
|
+
- app/views/educode_sales/ideas/assign.html.erb
|
|
422
|
+
- app/views/educode_sales/ideas/assign_sale_staff.html.erb
|
|
421
423
|
- app/views/educode_sales/ideas/course_list.json.jbuilder
|
|
422
424
|
- app/views/educode_sales/ideas/course_subject.json.jbuilder
|
|
423
425
|
- app/views/educode_sales/ideas/daily_paper.html.erb
|
|
@@ -572,6 +574,7 @@ files:
|
|
|
572
574
|
- app/views/educode_sales/sale_trends/_sales_analysis.html.erb
|
|
573
575
|
- app/views/educode_sales/sale_trends/_sales_followup_analysis.html.erb
|
|
574
576
|
- app/views/educode_sales/sale_trends/_user_stat.html.erb
|
|
577
|
+
- app/views/educode_sales/sale_trends/_visit_analysis.html.erb
|
|
575
578
|
- app/views/educode_sales/sale_trends/business_area.js.erb
|
|
576
579
|
- app/views/educode_sales/sale_trends/business_followup_analysis.js.erb
|
|
577
580
|
- app/views/educode_sales/sale_trends/goal_forecast.js.erb
|
|
@@ -581,6 +584,7 @@ files:
|
|
|
581
584
|
- app/views/educode_sales/sale_trends/trends.html.erb
|
|
582
585
|
- app/views/educode_sales/sale_trends/trends.json.jbuilder
|
|
583
586
|
- app/views/educode_sales/sale_trends/user_stat.js.erb
|
|
587
|
+
- app/views/educode_sales/sale_trends/visit_analysis.js.erb
|
|
584
588
|
- app/views/educode_sales/sales/index.html.erb
|
|
585
589
|
- app/views/educode_sales/sales/index.json.jbuilder
|
|
586
590
|
- app/views/educode_sales/sales/operations.html.erb
|