educode_sales 0.4.8 → 0.5.2
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/assets/images/educode_sales//345/233/236/346/224/266/347/253/231.png +0 -0
- data/app/controllers/educode_sales/businesses_controller.rb +84 -5
- data/app/controllers/educode_sales/follow_ups_controller.rb +4 -3
- data/app/controllers/educode_sales/home_controller.rb +1 -1
- data/app/controllers/educode_sales/operation_plans_controller.rb +34 -6
- data/app/controllers/educode_sales/operation_reports_controller.rb +33 -3
- data/app/controllers/educode_sales/operations_controller.rb +1 -1
- data/app/controllers/educode_sales/plans_controller.rb +43 -15
- data/app/controllers/educode_sales/recycles_controller.rb +95 -0
- data/app/controllers/educode_sales/roles_controller.rb +5 -0
- data/app/controllers/educode_sales/sale_reports_controller.rb +34 -4
- data/app/controllers/educode_sales/sale_trends_controller.rb +176 -5
- data/app/controllers/educode_sales/sales_controller.rb +6 -2
- data/app/controllers/educode_sales/staffs_controller.rb +4 -4
- data/app/controllers/educode_sales/upload_files_controller.rb +112 -0
- data/app/models/concerns/deletable.rb +8 -0
- data/app/models/educode_sales/application_record.rb +2 -0
- data/app/models/educode_sales/business.rb +15 -2
- data/app/models/educode_sales/common.rb +6 -1
- data/app/models/educode_sales/follow_up.rb +4 -2
- data/app/models/educode_sales/recycle.rb +5 -0
- data/app/models/educode_sales/sale_plan.rb +3 -0
- data/app/models/educode_sales/sale_report.rb +2 -0
- data/app/views/educode_sales/businesses/edit_follow_record.html.erb +15 -0
- data/app/views/educode_sales/businesses/edit_plan.html.erb +2 -2
- data/app/views/educode_sales/businesses/file.html.erb +155 -0
- data/app/views/educode_sales/businesses/index.html.erb +71 -4
- data/app/views/educode_sales/businesses/index.json.jbuilder +3 -1
- data/app/views/educode_sales/businesses/new_follow_record.html.erb +22 -1
- data/app/views/educode_sales/businesses/show_follow.html.erb +46 -9
- data/app/views/educode_sales/businesses/show_follow.json.jbuilder +3 -0
- data/app/views/educode_sales/businesses/show_follow_record.html.erb +80 -2
- data/app/views/educode_sales/businesses/time_line.html.erb +62 -0
- data/app/views/educode_sales/businesses/upload_file.html.erb +43 -0
- data/app/views/educode_sales/operation_plans/_monthly.html.erb +4 -4
- data/app/views/educode_sales/operation_plans/_weekly.html.erb +4 -4
- data/app/views/educode_sales/operation_plans/index.html.erb +6 -1
- data/app/views/educode_sales/operation_plans/new_month.html.erb +15 -1
- data/app/views/educode_sales/operation_plans/new_week.html.erb +20 -5
- data/app/views/educode_sales/operation_reports/audit.html.erb +23 -15
- data/app/views/educode_sales/operation_reports/edit.html.erb +9 -9
- data/app/views/educode_sales/operation_reports/show.html.erb +22 -19
- data/app/views/educode_sales/places/index.html.erb +6 -1
- data/app/views/educode_sales/places/index.json.jbuilder +11 -1
- data/app/views/educode_sales/plans/_monthly.html.erb +4 -4
- data/app/views/educode_sales/plans/_weekly.html.erb +4 -4
- data/app/views/educode_sales/plans/index.html.erb +6 -1
- data/app/views/educode_sales/plans/new_monthly.html.erb +6 -6
- data/app/views/educode_sales/plans/new_week.html.erb +1 -1
- data/app/views/educode_sales/plans/new_weekly.html.erb +7 -7
- data/app/views/educode_sales/recycles/_business.html.erb +122 -0
- data/app/views/educode_sales/recycles/_monthPlan.html.erb +123 -0
- data/app/views/educode_sales/recycles/_monthly.html.erb +121 -0
- data/app/views/educode_sales/recycles/_weekPlan.html.erb +128 -0
- data/app/views/educode_sales/recycles/_weekly.html.erb +122 -0
- data/app/views/educode_sales/recycles/business.json.jbuilder +16 -0
- data/app/views/educode_sales/recycles/index.html.erb +58 -0
- data/app/views/educode_sales/recycles/monthPlan.json.jbuilder +16 -0
- data/app/views/educode_sales/recycles/monthly.json.jbuilder +15 -0
- data/app/views/educode_sales/recycles/weekPlan.json.jbuilder +16 -0
- data/app/views/educode_sales/recycles/weekly.json.jbuilder +15 -0
- data/app/views/educode_sales/roles/index.html.erb +19 -1
- data/app/views/educode_sales/roles/rename.html.erb +50 -0
- data/app/views/educode_sales/sale_reports/audit.html.erb +24 -13
- data/app/views/educode_sales/sale_reports/edit.html.erb +7 -7
- data/app/views/educode_sales/sale_reports/show.html.erb +13 -10
- data/app/views/educode_sales/sale_trends/trends.html.erb +228 -8
- data/app/views/educode_sales/sale_trends/trends.json.jbuilder +14 -0
- data/app/views/educode_sales/sales/index.html.erb +72 -6
- data/app/views/educode_sales/sales/index.json.jbuilder +35 -1
- data/app/views/educode_sales/sales/operations.json.jbuilder +11 -1
- data/app/views/educode_sales/staffs/index.html.erb +6 -1
- data/app/views/educode_sales/staffs/index.json.jbuilder +11 -1
- data/app/views/educode_sales/teachers/add_keys.html.erb +3 -3
- data/app/views/educode_sales/teachers/index.html.erb +7 -2
- data/app/views/educode_sales/teachers/new.html.erb +1 -0
- data/app/views/educode_sales/upload_files/index.json.jbuilder +13 -0
- data/app/views/layouts/educode_sales/application.html.erb +3 -0
- data/config/routes.rb +30 -0
- data/db/migrate/20210902064109_create_educode_sales_role_permissions.rb +6 -0
- data/db/migrate/20211102085743_add_bidded_date_educode_sales_follow_ups.rb +6 -0
- data/db/migrate/20211109015617_create_educode_sales_recycles.rb +25 -0
- data/lib/educode_sales/version.rb +1 -1
- metadata +26 -2
@@ -7,7 +7,7 @@ module EducodeSales
|
|
7
7
|
def trends
|
8
8
|
# authorize! :trends, EducodeSales::SaleTrend
|
9
9
|
@year = params[:year] ? params[:year] : Time.now.year
|
10
|
-
@years = (1..(Time.now.year - 2014)).map { |d| 2014 + d }
|
10
|
+
@years = (1..(Time.now.year - 2014)).reverse_each.map { |d| 2014 + d }
|
11
11
|
year_time = "#{@year}-01-01 00:00:00"
|
12
12
|
year_over_time = "#{@year}-12-31 23:59:59"
|
13
13
|
x = Common.find_by(extras: EducodeSales::Common::XTYPE)&.id
|
@@ -15,14 +15,132 @@ module EducodeSales
|
|
15
15
|
@sale_trend = SaleTrend.find_or_create_by(year: @year)
|
16
16
|
@business_amount = Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id != ? AND educode_sales_follow_ups.clazz_id != ?", x, o).sum(:total_amount).round(2)
|
17
17
|
stage_ids = Common.where(clazz: '商机阶段', name: ['已中标','已签单','已验收','回款中', '服务中','已结束']).pluck(:id)
|
18
|
-
@goal_amount = Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id != ?", x).where("educode_sales_follow_ups.
|
18
|
+
@goal_amount = Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id != ?", x).where("educode_sales_follow_ups.bidded_date >= ? AND educode_sales_follow_ups.bidded_date <= ? AND educode_sales_follow_ups.stage_id IN (?)", "#{@year}-01-01", "#{@year}-12-31", stage_ids).sum(:total_amount).round(2)
|
19
19
|
s_stage_ids = Common.where(clazz: '商机阶段', name: ['已签单','已验收','回款中', '服务中','已结束']).pluck(:id)
|
20
|
-
@service_amount = Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id != ?", x).where("educode_sales_follow_ups.
|
20
|
+
@service_amount = Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id != ?", x).where("educode_sales_follow_ups.signed_date >= ? AND educode_sales_follow_ups.signed_date <= ? AND educode_sales_follow_ups.stage_id IN (?)", "#{@year}-01-01", "#{@year}-12-31", s_stage_ids).sum(:total_amount).round(2)
|
21
21
|
@return_amount = Business.joins(last_follow_up: :money_plans).where("educode_sales_follow_ups.clazz_id != ?", x).where.not("educode_sales_money_plans.clazz!= ?", 1).where("educode_sales_money_plans.date_at >= ? AND educode_sales_money_plans.date_at <= ? ", year_time, year_over_time).sum(:amount).round(2)
|
22
|
-
a = Common.where(clazz: '商机类型', name:
|
22
|
+
a = Common.where(clazz: '商机类型', name: Common.find_by(extras: EducodeSales::Common::ATYPE)&.name).pluck(:id)
|
23
23
|
@a_amount = Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id IN (?)", a).sum(:total_amount).round(2)
|
24
|
-
b = Common.where(clazz: '商机类型', name:
|
24
|
+
b = Common.where(clazz: '商机类型', name: Common.find_by(extras: EducodeSales::Common::BTYPE)&.name).pluck(:id)
|
25
25
|
@b_amount = Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id IN (?)", b).sum(:total_amount).round(2)
|
26
|
+
|
27
|
+
common = Common.find_by(clazz: 'staff_type', name: '销售')
|
28
|
+
names = Staff.includes(:user).where(job_type: common.id).map { |d| [d.user.real_name, d.id] }
|
29
|
+
x_business_ids = []
|
30
|
+
default_dates = (7.day.ago.to_date..Date.today).to_a #默认时间范围
|
31
|
+
Business.all.each do |d|
|
32
|
+
if d.last_follow_up&.clazz&.id == x
|
33
|
+
x_business_ids << d.id
|
34
|
+
end
|
35
|
+
end
|
36
|
+
colors = ['#FF0000', '#FF7F00', '#FFFF00', '#00FF00', '#00FFFF', '#0000FF', '#8B00FF', 'rgba(255, 99, 132, 1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)', 'rgba(75, 192, 192, 1)', 'rgba(153, 102, 255, 1)', 'rgba(255, 159, 64, 1)']
|
37
|
+
@follow_count_range = params[:follow_count_range] || "day"
|
38
|
+
@goal_count_range = params[:goal_count_range] || "day"
|
39
|
+
# 商机跟进数图表
|
40
|
+
@follow_count_data = day_follow_count_chart(default_dates,names,x_business_ids,colors)
|
41
|
+
if params[:follow_count_range].present?
|
42
|
+
case params[:follow_count_range]
|
43
|
+
when "week"
|
44
|
+
when "month" #按月
|
45
|
+
if params[:date_month].present?
|
46
|
+
# (Date.new(2020,12,1)..Date.new(2021,12,1)).map { |d| d.strftime("%Y-%m")}.uniq
|
47
|
+
date = params[:date_month].split(" - ")
|
48
|
+
dates = ((date[0]+"-01").to_date..(date[1]+"-01").to_date).map { |d| d.strftime("%Y-%m")}.uniq
|
49
|
+
@follow_count_data = month_follow_count_chart(dates,names,x_business_ids,colors)
|
50
|
+
end
|
51
|
+
when "year" #按年
|
52
|
+
if params[:date_year].present?
|
53
|
+
date = params[:date_year].split(" - ")
|
54
|
+
dates = (date[0]..date[1]).to_a
|
55
|
+
@follow_count_data = year_follow_count_chart(dates,names,x_business_ids,colors)
|
56
|
+
end
|
57
|
+
else #按天
|
58
|
+
if params[:date].present?
|
59
|
+
date = params[:date].split(" - ")
|
60
|
+
dates = (date[0].to_date..date[1].to_date).to_a
|
61
|
+
@follow_count_data = day_follow_count_chart(dates,names,x_business_ids,colors)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
# 已中标图表
|
68
|
+
goal_default_dates = ("#{Time.now.year}-01".."#{Time.now.year}-#{Time.now.month}").to_a
|
69
|
+
sale_names = ['已中标','已签单','已回款']
|
70
|
+
@goal_count_data =
|
71
|
+
{
|
72
|
+
labels: goal_default_dates,
|
73
|
+
datasets: sale_names.map do |name|{
|
74
|
+
label: name,
|
75
|
+
data: goal_default_dates.map{ |d|
|
76
|
+
case sale_names.index(name)
|
77
|
+
when 0
|
78
|
+
Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id != ?", x).where("educode_sales_follow_ups.bidded_date >= ? AND educode_sales_follow_ups.bidded_date <= ? AND educode_sales_follow_ups.stage_id IN (?)", "#{d}-01", "#{d}-31", stage_ids).sum(:total_amount).round(2)
|
79
|
+
when 1
|
80
|
+
Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id != ?", x).where("educode_sales_follow_ups.signed_date >= ? AND educode_sales_follow_ups.signed_date <= ? AND educode_sales_follow_ups.stage_id IN (?)", "#{d}-01", "#{d}-31", s_stage_ids).sum(:total_amount).round(2)
|
81
|
+
else
|
82
|
+
Business.joins(last_follow_up: :money_plans).where("educode_sales_follow_ups.clazz_id != ?", x).where.not("educode_sales_money_plans.clazz!= ?", 1).where("educode_sales_money_plans.date_at >= ? AND educode_sales_money_plans.date_at <= ? ", "#{d}-01", "#{d}-31").sum(:amount).round(2)
|
83
|
+
end
|
84
|
+
},
|
85
|
+
backgroundColor: colors[sale_names.index(name)+1],
|
86
|
+
borderColor: colors[sale_names.index(name)+1],
|
87
|
+
borderWidth: 1
|
88
|
+
}
|
89
|
+
end
|
90
|
+
}
|
91
|
+
if params[:goal_count_range].present?
|
92
|
+
case params[:goal_count_range]
|
93
|
+
when "week"
|
94
|
+
when "month" #按月
|
95
|
+
if params[:goal_date_month].present?
|
96
|
+
date = params[:goal_date_month].split(" - ")
|
97
|
+
dates = ((date[0]+"-01").to_date..(date[1]+"-01").to_date).map { |d| d.strftime("%Y-%m")}.uniq
|
98
|
+
@goal_count_data = {
|
99
|
+
labels: dates,
|
100
|
+
datasets: sale_names.map do |name|{
|
101
|
+
label: name,
|
102
|
+
data: dates.map{ |d|
|
103
|
+
case sale_names.index(name)
|
104
|
+
when 0
|
105
|
+
Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id != ?", x).where("educode_sales_follow_ups.bidded_date >= ? AND educode_sales_follow_ups.bidded_date <= ? AND educode_sales_follow_ups.stage_id IN (?)", "#{d}-01", "#{d}-31", stage_ids).sum(:total_amount).round(2)
|
106
|
+
when 1
|
107
|
+
Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id != ?", x).where("educode_sales_follow_ups.signed_date >= ? AND educode_sales_follow_ups.signed_date <= ? AND educode_sales_follow_ups.stage_id IN (?)", "#{d}-01", "#{d}-31", s_stage_ids).sum(:total_amount).round(2)
|
108
|
+
else
|
109
|
+
Business.joins(last_follow_up: :money_plans).where("educode_sales_follow_ups.clazz_id != ?", x).where.not("educode_sales_money_plans.clazz!= ?", 1).where("educode_sales_money_plans.date_at >= ? AND educode_sales_money_plans.date_at <= ? ", "#{d}-01", "#{d}-31").sum(:amount).round(2)
|
110
|
+
end },
|
111
|
+
backgroundColor: colors[sale_names.index(name)+1],
|
112
|
+
borderColor: colors[sale_names.index(name)+1],
|
113
|
+
borderWidth: 1
|
114
|
+
}
|
115
|
+
end
|
116
|
+
}
|
117
|
+
end
|
118
|
+
else #按年
|
119
|
+
if params[:goal_date_year].present?
|
120
|
+
date = params[:goal_date_year].split(" - ")
|
121
|
+
dates = (date[0]..date[1]).to_a
|
122
|
+
@goal_count_data = {
|
123
|
+
labels: dates,
|
124
|
+
datasets:sale_names.map do |name| {
|
125
|
+
label: name,
|
126
|
+
data: dates.map{ |d|
|
127
|
+
case sale_names.index(name)
|
128
|
+
when 0
|
129
|
+
Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id != ?", x).where("educode_sales_follow_ups.bidded_date >= ? AND educode_sales_follow_ups.bidded_date <= ? AND educode_sales_follow_ups.stage_id IN (?)", "#{d}-01-01", "#{d}-12-31", stage_ids).sum(:total_amount).round(2)
|
130
|
+
when 1
|
131
|
+
Business.joins(:last_follow_up).where("educode_sales_follow_ups.clazz_id != ?", x).where("educode_sales_follow_ups.signed_date >= ? AND educode_sales_follow_ups.signed_date <= ? AND educode_sales_follow_ups.stage_id IN (?)", "#{d}-01-01", "#{d}-12-31", s_stage_ids).sum(:total_amount).round(2)
|
132
|
+
else
|
133
|
+
Business.joins(last_follow_up: :money_plans).where("educode_sales_follow_ups.clazz_id != ?", x).where.not("educode_sales_money_plans.clazz!= ?", 1).where("educode_sales_money_plans.date_at >= ? AND educode_sales_money_plans.date_at <= ? ", "#{d}-01-01", "#{d}-12-31").sum(:amount).round(2)
|
134
|
+
end },
|
135
|
+
backgroundColor: colors[sale_names.index(name)+1],
|
136
|
+
borderColor: colors[sale_names.index(name)+1],
|
137
|
+
borderWidth: 1
|
138
|
+
}
|
139
|
+
end
|
140
|
+
}
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
26
144
|
end
|
27
145
|
|
28
146
|
def sale_trends
|
@@ -44,5 +162,58 @@ module EducodeSales
|
|
44
162
|
params.permit(:chance_money, :ballot_money, :sign_money, :returned_money)
|
45
163
|
end
|
46
164
|
|
165
|
+
def day_follow_count_chart(dates,names,x_business_ids,colors)
|
166
|
+
{
|
167
|
+
labels: dates,
|
168
|
+
datasets:names.map do |name|
|
169
|
+
{
|
170
|
+
hidden: names.index(name) < 3 ? false : true,
|
171
|
+
label: name[0],
|
172
|
+
data: dates.map{ |d| @follow_up = FollowUp.where(staff_id: name[1], created_at: d.beginning_of_day..d.end_of_day).where.not(business: x_business_ids).count },
|
173
|
+
backgroundColor: "#fff",
|
174
|
+
pointBorderColor: "#fff",
|
175
|
+
borderColor: colors[names.index(name)%10],
|
176
|
+
pointBackgroundColor: colors[names.index(name)%10],
|
177
|
+
borderWidth: 1
|
178
|
+
}
|
179
|
+
end
|
180
|
+
}
|
181
|
+
end
|
182
|
+
def month_follow_count_chart(dates,names,x_business_ids,colors)
|
183
|
+
{
|
184
|
+
labels: dates,
|
185
|
+
datasets:names.map do |name|
|
186
|
+
{
|
187
|
+
hidden: names.index(name) < 3 ? false : true,
|
188
|
+
label: name[0],
|
189
|
+
data: dates.map { |d| @follow_up = FollowUp.where( staff_id: name[1]).where("created_at >= ? AND created_at <= ?", "#{d}-01", "#{d}-31").where.not(business: x_business_ids).count },
|
190
|
+
backgroundColor: "#fff",
|
191
|
+
pointBorderColor: "#fff",
|
192
|
+
borderColor: colors[names.index(name)%10],
|
193
|
+
pointBackgroundColor: colors[names.index(name)%10],
|
194
|
+
borderWidth: 1
|
195
|
+
}
|
196
|
+
end
|
197
|
+
}
|
198
|
+
end
|
199
|
+
def year_follow_count_chart(dates,names,x_business_ids,colors)
|
200
|
+
{
|
201
|
+
labels: dates,
|
202
|
+
datasets:names.map do |name|
|
203
|
+
{
|
204
|
+
hidden: names.index(name) < 3 ? false : true,
|
205
|
+
label: name[0],
|
206
|
+
data: dates.map { |d| @follow_up = FollowUp.where( staff_id: name[1]).where("created_at >= ? AND created_at <= ?", "#{d}-01-01", "#{d}-12-31").where.not(business: x_business_ids).count },
|
207
|
+
backgroundColor: "#fff",
|
208
|
+
pointBorderColor: "#fff",
|
209
|
+
borderColor: colors[names.index(name)%10],
|
210
|
+
pointBackgroundColor: colors[names.index(name)%10],
|
211
|
+
borderWidth: 1
|
212
|
+
}
|
213
|
+
end
|
214
|
+
}
|
215
|
+
end
|
216
|
+
|
217
|
+
|
47
218
|
end
|
48
219
|
end
|
@@ -12,8 +12,12 @@ module EducodeSales
|
|
12
12
|
end
|
13
13
|
format.json do
|
14
14
|
common = Common.find_by(clazz: 'staff_type', name: '销售')
|
15
|
-
@a_clazz = Common.find_by(clazz: 'business_type', name:
|
16
|
-
@b_clazz = Common.find_by(clazz: 'business_type', name:
|
15
|
+
@a_clazz = Common.find_by(clazz: 'business_type', name: Common.find_by(extras: EducodeSales::Common::ATYPE)&.name)
|
16
|
+
@b_clazz = Common.find_by(clazz: 'business_type', name: Common.find_by(extras: EducodeSales::Common::BTYPE)&.name)
|
17
|
+
@c_clazz = Common.find_by(clazz: 'business_type', name: Common.find_by(extras: EducodeSales::Common::CTYPE)&.name)
|
18
|
+
@d_clazz = Common.find_by(clazz: 'business_type', name: Common.find_by(extras: EducodeSales::Common::DTYPE)&.name)
|
19
|
+
@e_clazz = Common.find_by(clazz: 'business_type', name: Common.find_by(extras: EducodeSales::Common::ETYPE)&.name)
|
20
|
+
@o_clazz = Common.find_by(clazz: 'business_type', name: Common.find_by(extras: EducodeSales::Common::OTYPE)&.name)
|
17
21
|
@x = Common.find_by(extras: EducodeSales::Common::XTYPE)
|
18
22
|
@step_ids = Common.where(name: %w(已中标 已签单 已验收 回款中 服务中 已结束), clazz: 'business_step').pluck(:id)
|
19
23
|
|
@@ -8,7 +8,7 @@ module EducodeSales
|
|
8
8
|
format.html do
|
9
9
|
end
|
10
10
|
format.json do
|
11
|
-
@staffs = Staff.where(is_admin: false).page(params[:page]).per(params[:limit])
|
11
|
+
@staffs = Staff.where(is_admin: false, deleted_at: nil).page(params[:page]).per(params[:limit])
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
@@ -37,10 +37,10 @@ module EducodeSales
|
|
37
37
|
|
38
38
|
def destroy
|
39
39
|
staff = Staff.find(params[:id])
|
40
|
-
staff.
|
40
|
+
staff.update(deleted_at: Time.now, expired_at: Time.now.days_ago(1))
|
41
41
|
render_success
|
42
|
-
rescue ActiveRecord::DeleteRestrictionError => e
|
43
|
-
|
42
|
+
# rescue ActiveRecord::DeleteRestrictionError => e
|
43
|
+
# render_failure '该用户已有数据产生,暂不能删除'
|
44
44
|
end
|
45
45
|
|
46
46
|
def disable
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require_dependency "educode_sales/application_controller"
|
2
|
+
|
3
|
+
module EducodeSales
|
4
|
+
class UploadFilesController < ApplicationController
|
5
|
+
|
6
|
+
def index
|
7
|
+
respond_to do |format|
|
8
|
+
format.html do
|
9
|
+
end
|
10
|
+
format.json do
|
11
|
+
@files = Attachment.where(description: "business", container_id:params[:business_id])
|
12
|
+
if params[:sort].present? && params[:sort][:field]
|
13
|
+
@files = @files.order("#{params[:sort][:field]} #{params[:sort][:order]}")
|
14
|
+
else
|
15
|
+
@files = @files.order("created_on desc")
|
16
|
+
end
|
17
|
+
@files = @files.page(params[:page]).per(params[:limit])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def create
|
23
|
+
folder = edu_setting('attachment_folder')
|
24
|
+
upload_file = params["file"]
|
25
|
+
raise "未上传文件" unless upload_file
|
26
|
+
save_path = File.join(folder)
|
27
|
+
ext = file_ext(upload_file.original_filename)
|
28
|
+
local_path, digest = file_save_to_local(save_path, upload_file.tempfile, ext)
|
29
|
+
content_type = upload_file.content_type.presence || 'application/octet-stream'
|
30
|
+
disk_filename = local_path[save_path.size + 1, local_path.size]
|
31
|
+
@attachment = Attachment.where(disk_filename: disk_filename,
|
32
|
+
author_id: @current_admin.id).first
|
33
|
+
if @attachment.blank?
|
34
|
+
@attachment = Attachment.new
|
35
|
+
@attachment.filename = upload_file.original_filename
|
36
|
+
@attachment.description = "business"
|
37
|
+
@attachment.disk_filename = local_path[save_path.size + 1, local_path.size]
|
38
|
+
@attachment.filesize = upload_file.tempfile.size
|
39
|
+
@attachment.content_type = content_type
|
40
|
+
@attachment.digest = digest
|
41
|
+
@attachment.author_id = @current_admin.id
|
42
|
+
@attachment.container_id = params[:business_id]
|
43
|
+
@attachment.save!
|
44
|
+
else
|
45
|
+
logger.info "文件已存在,id = #{@attachment.id}, filename = #{@attachment.filename}"
|
46
|
+
end
|
47
|
+
render_success
|
48
|
+
end
|
49
|
+
|
50
|
+
def destroy
|
51
|
+
folder = edu_setting('attachment_folder')
|
52
|
+
file = Attachment.find(params[:id])
|
53
|
+
file.destroy
|
54
|
+
File.delete(folder.to_s + '/' + file.disk_filename) if FileTest::exist?(folder.to_s + '/' + file.disk_filename)
|
55
|
+
render_success
|
56
|
+
end
|
57
|
+
|
58
|
+
def download
|
59
|
+
folder = edu_setting('attachment_folder')
|
60
|
+
file = Attachment.find_by_id(params[:id])
|
61
|
+
raise "未找到文件" unless file
|
62
|
+
send_file(folder.to_s + '/' + file.disk_filename, filename: file.title, stream: true, type: file.content_type.presence || 'application/octet-stream')
|
63
|
+
end
|
64
|
+
|
65
|
+
def edu_setting name
|
66
|
+
EduSetting.get(name)
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
def file_ext(file_name)
|
71
|
+
ext = ''
|
72
|
+
exts = file_name.split(".")
|
73
|
+
if exts.size > 1
|
74
|
+
ext = ".#{exts.last}"
|
75
|
+
end
|
76
|
+
ext
|
77
|
+
end
|
78
|
+
|
79
|
+
def file_save_to_local(save_path, temp_file, ext)
|
80
|
+
unless Dir.exists?(save_path)
|
81
|
+
FileUtils.mkdir_p(save_path) ##不成功这里会抛异常
|
82
|
+
end
|
83
|
+
|
84
|
+
digest = md5_file(temp_file)
|
85
|
+
digest = "#{digest}_#{(Time.now.to_f * 1000).to_i}"
|
86
|
+
local_file_path = File.join(save_path, digest) + ext
|
87
|
+
save_temp_file(temp_file, local_file_path)
|
88
|
+
|
89
|
+
[local_file_path, digest]
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
def md5_file(temp_file)
|
94
|
+
md5 = Digest::MD5.new
|
95
|
+
temp_file.rewind
|
96
|
+
while (buffer = temp_file.read(8192))
|
97
|
+
md5.update(buffer)
|
98
|
+
end
|
99
|
+
md5.hexdigest
|
100
|
+
end
|
101
|
+
|
102
|
+
def save_temp_file(temp_file, save_file_path)
|
103
|
+
File.open(save_file_path, 'wb') do |f|
|
104
|
+
temp_file.rewind
|
105
|
+
while (buffer = temp_file.read(8192))
|
106
|
+
f.write(buffer)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
@@ -1,10 +1,23 @@
|
|
1
1
|
module EducodeSales
|
2
2
|
class Business < ApplicationRecord
|
3
|
+
|
3
4
|
belongs_to :staff
|
4
5
|
belongs_to :department
|
5
6
|
belongs_to :last_follow_up, class_name: 'FollowUp', optional: true
|
6
7
|
|
7
|
-
has_many :sale_plans
|
8
|
-
has_many :follow_ups
|
8
|
+
has_many :sale_plans
|
9
|
+
has_many :follow_ups
|
10
|
+
|
11
|
+
default_scope -> {where(deleted_at: nil)}
|
12
|
+
|
13
|
+
def soft_destroy(user_id)
|
14
|
+
self.update(deleted_at: Time.now)
|
15
|
+
self.sale_plans.each do |d|
|
16
|
+
d.soft_destroy(user_id)
|
17
|
+
end
|
18
|
+
self.follow_ups.update_all(deleted_at: Time.now)
|
19
|
+
EducodeSales::Recycle.create(source: self, deleter_id: user_id)
|
20
|
+
end
|
21
|
+
|
9
22
|
end
|
10
23
|
end
|
@@ -4,6 +4,11 @@ module EducodeSales
|
|
4
4
|
|
5
5
|
XTYPE = "x_class"
|
6
6
|
OTYPE = 'o_class'
|
7
|
+
ATYPE = 'a_class'
|
8
|
+
BTYPE = 'b_class'
|
9
|
+
CTYPE = 'c_class'
|
10
|
+
DTYPE = 'd_class'
|
11
|
+
ETYPE = 'e_class'
|
7
12
|
|
8
13
|
validates :name, uniqueness: {scope: :clazz, message: '已存在'}
|
9
14
|
|
@@ -21,7 +26,7 @@ module EducodeSales
|
|
21
26
|
}
|
22
27
|
|
23
28
|
def self.job_type_name
|
24
|
-
self.where(clazz: 'staff_type'
|
29
|
+
self.where(clazz: 'staff_type').pluck(:id, :name).to_h
|
25
30
|
end
|
26
31
|
|
27
32
|
def self.teacher_source_name
|
@@ -1,14 +1,16 @@
|
|
1
1
|
module EducodeSales
|
2
2
|
class FollowUp < ApplicationRecord
|
3
|
+
include ::Deletable
|
3
4
|
belongs_to :business, counter_cache: true
|
4
5
|
belongs_to :place, optional: true
|
5
|
-
has_many :money_plans
|
6
|
+
has_many :money_plans
|
6
7
|
has_many :key_person
|
7
8
|
has_many :teachers, through: :key_person
|
8
|
-
has_many :assign_follow_ups
|
9
|
+
has_many :assign_follow_ups
|
9
10
|
belongs_to :staff
|
10
11
|
belongs_to :stage, class_name: 'Common'
|
11
12
|
belongs_to :clazz, class_name: 'Common'
|
13
|
+
default_scope -> {where(deleted_at: nil)}
|
12
14
|
|
13
15
|
|
14
16
|
end
|
@@ -1,9 +1,12 @@
|
|
1
1
|
module EducodeSales
|
2
2
|
class SalePlan < ApplicationRecord
|
3
|
+
include ::Deletable
|
3
4
|
belongs_to :business
|
4
5
|
belongs_to :staff
|
5
6
|
validates :business_id, presence: true
|
6
7
|
|
7
8
|
validates :month, presence: true
|
9
|
+
|
10
|
+
default_scope -> {where(deleted_at: nil)}
|
8
11
|
end
|
9
12
|
end
|
@@ -41,6 +41,21 @@
|
|
41
41
|
id="invitation_at_edit" placeholder="请选择日期">
|
42
42
|
</div>
|
43
43
|
</div>
|
44
|
+
<div class="layui-inline">
|
45
|
+
<label class="layui-form-label">中标时间</label>
|
46
|
+
<div class="layui-input-inline">
|
47
|
+
<input type="text" class="layui-input" value="<%= @follow_up.bidded_date %>" name="bidded_date"
|
48
|
+
id="invitation_at_edit" placeholder="请选择日期">
|
49
|
+
</div>
|
50
|
+
</div>
|
51
|
+
<br>
|
52
|
+
<div class="layui-inline">
|
53
|
+
<label class="layui-form-label">签单时间</label>
|
54
|
+
<div class="layui-input-inline">
|
55
|
+
<input type="text" class="layui-input" value="<%= @follow_up.signed_date %>" name="signed_date"
|
56
|
+
id="invitation_at_edit" placeholder="请选择日期">
|
57
|
+
</div>
|
58
|
+
</div>
|
44
59
|
<div class="layui-inline">
|
45
60
|
<label class="layui-form-label">验收时间</label>
|
46
61
|
<div class="layui-input-inline">
|
@@ -56,13 +56,13 @@
|
|
56
56
|
</div>
|
57
57
|
</script>
|
58
58
|
<script type="text/html" id="return_money_tabar">
|
59
|
-
{{# if(parent.is_latest){ }}
|
59
|
+
{{# if(parent.is_latest && parent.flag){ }}
|
60
60
|
<a class="layui-btn layui-btn-normal layui-btn-xs data-count-edit" lay-event="edit">保存</a>
|
61
61
|
<a class="layui-btn layui-btn-danger layui-btn-xs data-count-edit" lay-event="delete">删除</a>
|
62
62
|
{{# } }}
|
63
63
|
</script>
|
64
64
|
<script>
|
65
|
-
if(!parent.is_latest){
|
65
|
+
if(!parent.is_latest || !parent.flag){
|
66
66
|
document.getElementById("show_plan_box").style.display="none";//隐藏
|
67
67
|
}
|
68
68
|
layui.use(['form', 'table', 'upload', 'laytpl', 'request', 'laydate'], function () {
|
@@ -0,0 +1,155 @@
|
|
1
|
+
<%= Gon::Base.render_data %>
|
2
|
+
<script type="text/html" id="toolbarDemo">
|
3
|
+
<div class="layui-btn-container">
|
4
|
+
<span class="table-label">附件信息</span>
|
5
|
+
<%# if can? :create, EducodeSales::file %>
|
6
|
+
<button class="layui-btn layui-btn-normal layui-btn-sm data-add-btn pull-right" lay-event="upload_file">上传文件</button>
|
7
|
+
<%# end %>
|
8
|
+
</div>
|
9
|
+
</script>
|
10
|
+
|
11
|
+
<table class="layui-hide" id="file" lay-filter="file"></table>
|
12
|
+
|
13
|
+
<script type="text/html" id="currentTableBar_file">
|
14
|
+
<a class="layui-btn layui-btn-normal layui-btn-xs data-count-edit" lay-event="preview">预览</a>
|
15
|
+
<a href="/missions/upload_files/download?id={{d.id}}" class="layui-btn layui-btn-normal layui-btn-xs data-count-edit" lay-event="download">下载</a>
|
16
|
+
<a class="layui-btn layui-btn-xs layui-btn-danger data-count-delete" lay-event="delete">删除</a>
|
17
|
+
</script>
|
18
|
+
|
19
|
+
<script type="text/html" id="showchance">
|
20
|
+
<a href="/missions/businesses" class="layui-table-link">{{ d.chance }}</a>
|
21
|
+
</script>
|
22
|
+
|
23
|
+
<script>
|
24
|
+
layui.use(['form', 'table', 'miniPage', 'element', 'request'], function () {
|
25
|
+
var $ = layui.jquery,
|
26
|
+
form = layui.form,
|
27
|
+
table = layui.table,
|
28
|
+
request = layui.request,
|
29
|
+
upload = layui.upload;
|
30
|
+
miniPage = layui.miniPage;
|
31
|
+
|
32
|
+
|
33
|
+
var business_id = parent.id
|
34
|
+
table.render({
|
35
|
+
elem: '#file',
|
36
|
+
url: '/missions/upload_files?business_id='+business_id,
|
37
|
+
toolbar: '#toolbarDemo',
|
38
|
+
defaultToolbar: [],
|
39
|
+
cols: [
|
40
|
+
[
|
41
|
+
{
|
42
|
+
field: 'id',
|
43
|
+
width: 80,
|
44
|
+
title:'序号',type: 'numbers',
|
45
|
+
},
|
46
|
+
{
|
47
|
+
field: 'name',
|
48
|
+
title: '文件名'
|
49
|
+
},
|
50
|
+
{
|
51
|
+
field: 'size',
|
52
|
+
width: 100,
|
53
|
+
title: '文件大小',
|
54
|
+
},
|
55
|
+
{
|
56
|
+
field: 'created_on',
|
57
|
+
width: 200,
|
58
|
+
title: '上传时间',
|
59
|
+
sort: true
|
60
|
+
},
|
61
|
+
{
|
62
|
+
field: 'upload_person',
|
63
|
+
width: 80,
|
64
|
+
totalRow:true,
|
65
|
+
title: '上传人',
|
66
|
+
},
|
67
|
+
{
|
68
|
+
title: '操作',
|
69
|
+
width: 200,
|
70
|
+
toolbar: '#currentTableBar_file',
|
71
|
+
align: "center"
|
72
|
+
}
|
73
|
+
]
|
74
|
+
],
|
75
|
+
limit: 20,
|
76
|
+
limits: [10,15,20,30,40,50,60,70,80,90],
|
77
|
+
page: true
|
78
|
+
});
|
79
|
+
|
80
|
+
|
81
|
+
var sort = {};
|
82
|
+
table.on('sort(file)', function (obj) {
|
83
|
+
sort.field = obj.field;
|
84
|
+
sort.order = obj.type;
|
85
|
+
table.reload('file', {
|
86
|
+
initSort: obj,
|
87
|
+
where: {
|
88
|
+
sort: sort
|
89
|
+
}
|
90
|
+
});
|
91
|
+
})
|
92
|
+
|
93
|
+
|
94
|
+
table.on('toolbar(file)', function (obj) {
|
95
|
+
if (obj.event === 'upload_file') { //
|
96
|
+
id =parent.id
|
97
|
+
var content = miniPage.getHrefContent('/missions/businesses/upload_file');
|
98
|
+
var openWH = miniPage.getOpenWidthHeight();
|
99
|
+
import_index = layer.open({
|
100
|
+
title: '上传文件',
|
101
|
+
type: 1,
|
102
|
+
shade: 0.2,
|
103
|
+
shadeClose: true,
|
104
|
+
area: ['200px', '100px'],
|
105
|
+
offset: 'auto',
|
106
|
+
closeBtn: 0,
|
107
|
+
content: content,
|
108
|
+
});
|
109
|
+
$(window).on("resize", function () {
|
110
|
+
layer.full(index);
|
111
|
+
});
|
112
|
+
}
|
113
|
+
});
|
114
|
+
|
115
|
+
|
116
|
+
table.on('tool(file)', function (obj) {
|
117
|
+
var data = obj.data;
|
118
|
+
var id = data.id
|
119
|
+
name = data.disk_filename
|
120
|
+
folder = gon.folder
|
121
|
+
console.log(folder);
|
122
|
+
if (obj.event === 'preview') {
|
123
|
+
if (data.content_type.split("/")[0] === "image"){
|
124
|
+
layer.photos({
|
125
|
+
photos: { "data": [{"src": '/business_file/' + name}] }
|
126
|
+
,anim: 5 //0-6的选择,指定弹出图片动画类型,默认随机
|
127
|
+
});
|
128
|
+
}else if (data.content_type.split("/")[1] === "pdf"){
|
129
|
+
var pdf = '/business_file/' + name;
|
130
|
+
console.log(pdf);
|
131
|
+
var openWH = miniPage.getOpenWidthHeight();
|
132
|
+
layer.open({
|
133
|
+
title: data.name,
|
134
|
+
type: 2,
|
135
|
+
area: ['1000px', '750px'],
|
136
|
+
fixed: false, //不固定
|
137
|
+
maxmin: true,
|
138
|
+
content: pdf
|
139
|
+
});
|
140
|
+
}else{
|
141
|
+
layer.msg("附件不支持预览,请下载查看!")
|
142
|
+
}
|
143
|
+
return false;
|
144
|
+
}else if (obj.event === 'delete') {
|
145
|
+
layer.confirm('确定删除' + data.name, function (index) {
|
146
|
+
request.delete('missions/upload_files/' + data.id + '?disk_filename=' + data.disk_filename, {}, function (res) {
|
147
|
+
layer.close(index);
|
148
|
+
table.reload("file")
|
149
|
+
})
|
150
|
+
});
|
151
|
+
}
|
152
|
+
});
|
153
|
+
|
154
|
+
});
|
155
|
+
</script>
|