educode_sales 0.9.83 → 0.9.84

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e769e1841e12580e3813a004cc14dca465f65b884df4152f78bcc212aa4f2c75
4
- data.tar.gz: 04c60143e5bac234b3384359b3edfa651d4daac44145672e2d6cce9a75ea6679
3
+ metadata.gz: e498fa041334cb4b387425a7a7f7ff49dffffcee5a72e363b61cb9f32167ff06
4
+ data.tar.gz: 54d79d72be99cab109f9b40fdd4dd789f72f20d115663abd7d99db70f0ee2527
5
5
  SHA512:
6
- metadata.gz: 0a68e73f50aa323fb5fdb40d17885d04dda68460d2bb899aa2297a984f6497ea66dadaaaaaaeb03d41716d006b19235ff23063d2a0292e13671bce5d8a3732c1
7
- data.tar.gz: 28cb221ad77fc7c40a592e045c7f0c381b6938292bbaff792513a01ac1611ba9fd884b0049de218ee9ab48fa783555110e410216184ce7f81d4f6cb2ef9f68fa
6
+ metadata.gz: 1e29ad8d3c8dd8c0753dc6662e26c332444cbf10842d308977883c47149c676b0b1c06c515bcfc33e10fe0bfccbc1cecb5ab1c7f2534001c0c1d7a11042a5def
7
+ data.tar.gz: 5077f36f7bb732c196608fd15c696c06b3d0cf5c74e32c24495b67eadc8b5527eacb1a545966aeea4e3401410ed0e1fbe23c2fb60aea58a8b5513fd1fd570ba6
@@ -233,12 +233,14 @@ module EducodeSales
233
233
  @business = Business.find(params[:id])
234
234
  @last_follow_up = @business.last_follow_up
235
235
  @deployment_type = EducodeSales::FollowUp::BUSINESS_DEPLOYMENT
236
+ @signed_clazz = EducodeSales::FollowUp.signed_clazzs.keys
237
+
236
238
  signed_department = @last_follow_up.signed_department
237
239
  if signed_department
238
- gon.department = {value: signed_department.id, name: "#{signed_department&.school&.name}-#{signed_department&.name}"}
240
+ gon.department = [{value: signed_department.id, name: "#{signed_department&.school&.name}-#{signed_department&.name}"}]
239
241
  gon.value = signed_department.id
240
242
  else
241
- gon.department = {}
243
+ gon.department = []
242
244
  gon.value = ''
243
245
  end
244
246
 
@@ -454,7 +456,7 @@ module EducodeSales
454
456
 
455
457
  private
456
458
  def follow_up_params
457
- params.permit(:o_business_deployment, :plan_signed_date, :bidded_days, :signed_date, :signed_department_id, :service_years, :service_start_time, :service_end_time, :funding_source)
459
+ params.permit(:o_business_deployment, :plan_signed_date, :bidded_days, :signed_date, :signed_department_id, :service_years, :service_start_time, :service_end_time, :funding_source, :signed_clazz)
458
460
  end
459
461
 
460
462
  def product_up_params
@@ -391,7 +391,7 @@ module EducodeSales
391
391
  staff_id = params[:staff_id] || nil
392
392
  @forecast_count_range = params[:forecast_count_range] || "month"
393
393
  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
394
- sale_names = %w[计划投标额 实际中标额]
394
+ sale_names = %w[计划投标额 计划投标额累计 实际中标额 实际中标额累计]
395
395
  case @forecast_count_range
396
396
  when "week"
397
397
  # 年初第一天周数是0会导致周数重复计算
@@ -0,0 +1,6 @@
1
+ require_dependency "educode_sales/application_controller"
2
+
3
+ module EducodeSales
4
+ class SalesDetailsController < ApplicationController
5
+ end
6
+ end
@@ -1,45 +1,58 @@
1
1
  module EducodeSales
2
2
  module SaleTrendsHelper
3
-
3
+ NAMES = %w[计划投标额 计划投标额累计 实际中标额 实际中标额累计]
4
4
  def goal_forecast_quarter(labels, selects, staff_id = nil)
5
5
  plan_get = plan_get(staff_id, labels, "quarter")
6
6
  actual_get = actual_get(staff_id, labels, "quarter")
7
- datasets = selects.map do |select|
8
- if select == "计划投标额"
9
- {
10
- label: select,
11
- data: labels.map do |d|
12
- quarter = d.split("-").last.to_i
13
- year = d.split("-").first.to_i
14
- plan_get[[year, quarter]]&.pluck(:budget_amount)&.reject(&:blank?)&.sum.to_f
15
- end,
16
- backgroundColor: [
17
- 'rgba(255, 99, 132, 0.2)',
18
- ],
19
- borderColor: [
20
- 'rgba(255,99,132,1)',
21
- ],
22
- borderWidth: 1
23
- }
24
- else
25
- {
26
- label: select,
27
- data: labels.map do |d|
28
- quarter = d.split("-").last.to_i
29
- year = d.split("-").first.to_i
30
- actual_get[[year, quarter]]&.pluck(:actual_amount)&.reject(&:blank?)&.sum.to_f
31
- end,
32
- backgroundColor: [
33
- 'rgba(54, 162, 235, 0.2)',
34
- ],
35
- borderColor: [
36
- 'rgba(54, 162, 235, 1)',
37
- ],
38
- borderWidth: 1
39
- }
40
- end
7
+ datasets = selects.map.with_index do |select, i|
8
+ data = if select == NAMES[0]
9
+ labels.map do |d|
10
+ quarter = d.split("-").last.to_i
11
+ year = d.split("-").first.to_i
12
+ plan_get[[year, quarter]]&.pluck(:budget_amount)&.reject(&:blank?)&.sum.to_f
13
+ end
14
+ elsif select == NAMES[1]
15
+ arr = labels.map do |d|
16
+ quarter = d.split("-").last.to_i
17
+ year = d.split("-").first.to_i
18
+ plan_get[[year, quarter]]&.pluck(:budget_amount)&.reject(&:blank?)&.sum.to_f
19
+ end
20
+ arr.map.with_index(1) { |num, i| arr.first(i).inject(:+) }
21
+ elsif select == NAMES[2]
22
+ labels.map do |d|
23
+ quarter = d.split("-").last.to_i
24
+ year = d.split("-").first.to_i
25
+ actual_get[[year, quarter]]&.pluck(:actual_amount)&.reject(&:blank?)&.sum.to_f
26
+ end
27
+ elsif select == NAMES[3]
28
+ arr = labels.map do |d|
29
+ quarter = d.split("-").last.to_i
30
+ year = d.split("-").first.to_i
31
+ actual_get[[year, quarter]]&.pluck(:actual_amount)&.reject(&:blank?)&.sum.to_f
32
+ end
33
+ arr.map.with_index(1) { |num, i| arr.first(i).inject(:+) }
34
+ end
35
+ type = if select == NAMES[3] || select == NAMES[1]
36
+ 'line'
37
+ else
38
+ "bar"
39
+ end
40
+ backgroundColor = if select == NAMES[3] || select == NAMES[1]
41
+ 'rgba(54, 162, 235, 0.2)'
42
+ else
43
+ SaleTrend::COLORS[i]
44
+ end
45
+ {
46
+ type: type,
47
+ label: select,
48
+ data: data,
49
+ backgroundColor:
50
+ backgroundColor,
51
+ borderColor:
52
+ SaleTrend::COLORS[i],
53
+ borderWidth: 1
54
+ }
41
55
  end
42
-
43
56
  {
44
57
  labels: labels,
45
58
  datasets: datasets
@@ -50,42 +63,58 @@ module EducodeSales
50
63
 
51
64
  plan_get = plan_get(staff_id, labels, "week")
52
65
  actual_get = actual_get(staff_id, labels, "week")
53
- datasets = selects.map do |select|
54
- if select == "计划投标额"
55
- {
56
- label: select,
57
- data: labels.map do |d|
58
- week = d.split("-").last
59
- year = d.split("-").first
60
- yearweek = "#{year}#{week}".to_i
61
- plan_get[yearweek].to_f
62
- end,
63
- backgroundColor: [
64
- 'rgba(255, 99, 132, 0.2)',
65
- ],
66
- borderColor: [
67
- 'rgba(255,99,132,1)',
68
- ],
69
- borderWidth: 1
70
- }
71
- else
72
- {
73
- label: select,
74
- data: labels.map do |d|
75
- week = d.split("-").last
76
- year = d.split("-").first
77
- yearweek = "#{year}#{week}".to_i
78
- actual_get[yearweek].to_f
79
- end,
80
- backgroundColor: [
81
- 'rgba(54, 162, 235, 0.2)',
82
- ],
83
- borderColor: [
84
- 'rgba(54, 162, 235, 1)',
85
- ],
86
- borderWidth: 1
87
- }
88
- end
66
+ datasets = selects.map.with_index do |select, i|
67
+ data = if select == NAMES[0]
68
+ labels.map do |d|
69
+ week = d.split("-").last
70
+ year = d.split("-").first
71
+ yearweek = "#{year}#{week}".to_i
72
+ plan_get[yearweek].to_f
73
+ end
74
+ elsif select == NAMES[1]
75
+ arr = labels.map do |d|
76
+ week = d.split("-").last
77
+ year = d.split("-").first
78
+ yearweek = "#{year}#{week}".to_i
79
+ plan_get[yearweek].to_f
80
+ end
81
+ arr.map.with_index(1) { |num, i| arr.first(i).inject(:+) }
82
+ elsif select == NAMES[2]
83
+ labels.map do |d|
84
+ week = d.split("-").last
85
+ year = d.split("-").first
86
+ yearweek = "#{year}#{week}".to_i
87
+ actual_get[yearweek].to_f
88
+ end
89
+ elsif select == NAMES[3]
90
+ arr = labels.map do |d|
91
+ week = d.split("-").last
92
+ year = d.split("-").first
93
+ yearweek = "#{year}#{week}".to_i
94
+ actual_get[yearweek].to_f
95
+ end
96
+ arr.map.with_index(1) { |num, i| arr.first(i).inject(:+) }
97
+ end
98
+ type = if select == NAMES[0] || select == NAMES[2]
99
+ 'bar'
100
+ else
101
+ "line"
102
+ end
103
+ backgroundColor = if select == NAMES[0] || select == NAMES[2]
104
+ SaleTrend::COLORS[i]
105
+ else
106
+ 'rgba(54, 162, 235, 0.2)'
107
+ end
108
+ {
109
+ type: type,
110
+ label: select,
111
+ data: data,
112
+ backgroundColor:
113
+ backgroundColor,
114
+ borderColor:
115
+ SaleTrend::COLORS[i],
116
+ borderWidth: 1
117
+ }
89
118
  end
90
119
 
91
120
  {
@@ -97,40 +126,55 @@ module EducodeSales
97
126
  def goal_forecast_month(labels, selects, staff_id = nil)
98
127
  plan_get = plan_get(staff_id, labels, "month")
99
128
  actual_get = actual_get(staff_id, labels, "month")
100
- datasets = selects.map do |select|
101
- if select == "计划投标额"
102
- {
103
- label: select,
104
- data: labels.map do |d|
105
- month = d.split("-").last.to_i
106
- year = d.split("-").first.to_i
107
- plan_get[[year, month]]&.pluck(:budget_amount)&.reject(&:blank?)&.sum.to_f
108
- end,
109
- backgroundColor: [
110
- 'rgba(255, 99, 132, 0.2)',
111
- ],
112
- borderColor: [
113
- 'rgba(255,99,132,1)',
114
- ],
115
- borderWidth: 1
116
- }
117
- else
118
- {
119
- label: select,
120
- data: labels.map do |d|
121
- month = d.split("-").last.to_i
122
- year = d.split("-").first.to_i
123
- actual_get[[year, month]]&.pluck(:actual_amount)&.reject(&:blank?)&.sum.to_f
124
- end,
125
- backgroundColor: [
126
- 'rgba(54, 162, 235, 0.2)',
127
- ],
128
- borderColor: [
129
- 'rgba(54, 162, 235, 1)',
130
- ],
131
- borderWidth: 1
132
- }
133
- end
129
+ datasets = selects.map.with_index do |select, i|
130
+ data = if select == NAMES[0]
131
+ labels.map do |d|
132
+ month = d.split("-").last.to_i
133
+ year = d.split("-").first.to_i
134
+ plan_get[[year, month]]&.pluck(:budget_amount)&.reject(&:blank?)&.sum.to_f
135
+ end
136
+ elsif select == NAMES[1]
137
+ arr = labels.map do |d|
138
+ month = d.split("-").last.to_i
139
+ year = d.split("-").first.to_i
140
+ plan_get[[year, month]]&.pluck(:budget_amount)&.reject(&:blank?)&.sum.to_f
141
+ end
142
+ arr.map.with_index(1) { |num, i| arr.first(i).inject(:+) }
143
+ elsif select == NAMES[2]
144
+ labels.map do |d|
145
+ month = d.split("-").last.to_i
146
+ year = d.split("-").first.to_i
147
+ actual_get[[year, month]]&.pluck(:actual_amount)&.reject(&:blank?)&.sum.to_f
148
+ end
149
+ elsif select == NAMES[3]
150
+ arr = labels.map do |d|
151
+ month = d.split("-").last.to_i
152
+ year = d.split("-").first.to_i
153
+ actual_get[[year, month]]&.pluck(:actual_amount)&.reject(&:blank?)&.sum.to_f
154
+ end
155
+ arr.map.with_index(1) { |num, i| arr.first(i).inject(:+) }
156
+ end
157
+
158
+ type = if select == NAMES[3] || select == NAMES[1]
159
+ 'line'
160
+ else
161
+ "bar"
162
+ end
163
+ backgroundColor = if select == NAMES[3] || select == NAMES[1]
164
+ 'rgba(54, 162, 235, 0.2)'
165
+ else
166
+ SaleTrend::COLORS[i]
167
+ end
168
+ {
169
+ type: type,
170
+ label: select,
171
+ data: data,
172
+ backgroundColor:
173
+ backgroundColor,
174
+ borderColor:
175
+ SaleTrend::COLORS[i],
176
+ borderWidth: 1
177
+ }
134
178
  end
135
179
 
136
180
  {
@@ -142,34 +186,40 @@ module EducodeSales
142
186
  def goal_forecast_year(labels, selects, staff_id = nil)
143
187
  plan_get = plan_get(staff_id, labels, "year")
144
188
  actual_get = actual_get(staff_id, labels, "year")
145
- datasets = selects.map do |select|
146
- if select == "计划投标额"
147
- {
148
- label: select,
149
- data: labels.map { |d| plan_get[d.to_i] || 0 },
150
- backgroundColor: [
151
- 'rgba(255, 99, 132, 0.2)',
152
- ],
153
- borderColor: [
154
- 'rgba(255,99,132,1)',
155
- ],
156
- borderWidth: 1
157
- }
158
- else
159
- {
160
- label: select,
161
- data: labels.map { |d| actual_get[d.to_i] || 0 },
162
- backgroundColor: [
163
- 'rgba(54, 162, 235, 0.2)',
164
- ],
165
- borderColor: [
166
- 'rgba(54, 162, 235, 1)',
167
- ],
168
- borderWidth: 1
169
- }
170
- end
171
- end
189
+ datasets = selects.map.with_index do |select, i|
190
+ data = if select == NAMES[0]
191
+ labels.map { |d| plan_get[d.to_i] || 0 }
192
+ elsif select == NAMES[1]
193
+ arr = labels.map { |d| plan_get[d.to_i] || 0 }
194
+ arr.map.with_index(1) { |num, i| arr.first(i).inject(:+) }
195
+ elsif select == NAMES[2]
196
+ labels.map { |d| actual_get[d.to_i] || 0 }
197
+ elsif select == NAMES[3]
198
+ arr = labels.map { |d| actual_get[d.to_i] || 0 }
199
+ arr.map.with_index(1) { |num, i| arr.first(i).inject(:+) }
200
+ end
172
201
 
202
+ type = if select == NAMES[3] || select == NAMES[1]
203
+ 'line'
204
+ else
205
+ "bar"
206
+ end
207
+ backgroundColor = if select == NAMES[3] || select == NAMES[1]
208
+ 'rgba(54, 162, 235, 0.2)'
209
+ else
210
+ SaleTrend::COLORS[i]
211
+ end
212
+ {
213
+ type: type,
214
+ label: select,
215
+ data: data,
216
+ backgroundColor:
217
+ backgroundColor,
218
+ borderColor:
219
+ SaleTrend::COLORS[i],
220
+ borderWidth: 1
221
+ }
222
+ end
173
223
  {
174
224
  labels: labels,
175
225
  datasets: datasets
@@ -180,9 +230,29 @@ module EducodeSales
180
230
 
181
231
  def plan_get(staff_id, time_range, type)
182
232
  # budget_amount 预算额
233
+ start_time = case type
234
+ when "month"
235
+ time_range.first + "-01"
236
+ when "year"
237
+ time_range.first + "-01-01"
238
+ when "week"
239
+ time_range.first.split("-").first + "-01-01"
240
+ when "quarter"
241
+ time_range.first.split("-").first + "-01-01"
242
+ end
243
+ end_time = case type
244
+ when "month"
245
+ time_range.last + "-31"
246
+ when "year"
247
+ time_range.last + "-12-31"
248
+ when "week"
249
+ time_range.last.split("-").first + "-12-31"
250
+ when "quarter"
251
+ time_range.last.split("-").first + "-12-31"
252
+ end
183
253
  staff_id = staff_id.present? ? Array(staff_id) : nil
184
254
  data = Business.joins(:last_follow_up)
185
- .where("educode_sales_follow_ups.invitation_at >= ? and educode_sales_follow_ups.invitation_at <= ? #{staff_id.present? ? "AND educode_sales_follow_ups.staff_id in (#{staff_id.join(",")})" : ""}", time_range.first, time_range.last)
255
+ .where("educode_sales_follow_ups.invitation_at >= ? and educode_sales_follow_ups.invitation_at <= ? #{staff_id.present? ? "AND educode_sales_follow_ups.staff_id in (#{staff_id.join(",")})" : ""}", start_time, end_time)
186
256
  case type
187
257
  when "week"
188
258
  data.select("educode_sales_follow_ups.*, yearweek(educode_sales_follow_ups.invitation_at) as week").group("yearweek(educode_sales_follow_ups.invitation_at)").sum(:budget_amount)
@@ -198,10 +268,30 @@ module EducodeSales
198
268
  end
199
269
 
200
270
  def actual_get(staff_id, time_range, type)
271
+ start_time = case type
272
+ when "month"
273
+ time_range.first + "-01"
274
+ when "year"
275
+ time_range.first + "-01-01"
276
+ when "week"
277
+ time_range.first.split("-").first + "-01-01"
278
+ when "quarter"
279
+ time_range.first.split("-").first + "-01-01"
280
+ end
281
+ end_time = case type
282
+ when "month"
283
+ time_range.last + "-31"
284
+ when "year"
285
+ time_range.last + "-12-31"
286
+ when "week"
287
+ time_range.last.split("-").first + "-12-31"
288
+ when "quarter"
289
+ time_range.last.split("-").first + "-12-31"
290
+ end
201
291
  # actual_amount 合同额
202
292
  staff_id = staff_id.present? ? Array(staff_id) : nil
203
293
  data = Business.joins(:last_follow_up)
204
- .where("educode_sales_follow_ups.bidded_date >= ? and educode_sales_follow_ups.bidded_date <= ? #{staff_id.present? ? "AND educode_sales_follow_ups.staff_id in (#{staff_id.join(",")})" : ""}", time_range.first, time_range.last)
294
+ .where("educode_sales_follow_ups.bidded_date >= ? and educode_sales_follow_ups.bidded_date <= ? #{staff_id.present? ? "AND educode_sales_follow_ups.staff_id in (#{staff_id.join(",")})" : ""}", start_time, end_time)
205
295
  case type
206
296
  when "week"
207
297
  data.select("educode_sales_follow_ups.*, yearweek(educode_sales_follow_ups.bidded_date) as week").group("yearweek(educode_sales_follow_ups.bidded_date)").sum(:actual_amount)
@@ -10,6 +10,8 @@ module EducodeSales
10
10
 
11
11
  InfoClazz = ['跟进信息', '建议信息', '评论信息', '审核信息']
12
12
 
13
+ enum signed_clazz: ['直签', '代签', '总集', '渠道']
14
+
13
15
  enum funding_source: ['贷款资金', '财政资金', '自由资金']
14
16
 
15
17
  include ::Deletable
@@ -2,12 +2,12 @@ module EducodeSales
2
2
  class SaleTrend < ApplicationRecord
3
3
 
4
4
  COLORS = [
5
- '#44D7B6', '#4CACFF', '#F7B500', '#FF0000', '#FF7F00', '#FFFF00', '#00FF00', '#00FFFF', '#0000FF',
6
- '#8B00FF', 'rgba(255, 99, 132, 1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)', 'rgba(75, 192, 192, 1)',
5
+ '#44D7B6', '#7CFC00', '#4CACFF', "#110FD7", '#F7B500', '#48D1CC', '#FF0000', '#FF7F00', '#FFFF00', '#00FF00', '#00FFFF', '#0000FF',
6
+ '#8B00FF', 'rgba(255, 99, 132, 1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)', 'rgba(75, 192, 192, 1)',
7
7
  'rgba(153, 102, 255, 1)', 'rgba(255, 159, 64, 1)', 'rgba(255, 0, 250, 1)', '#A2D9CE', '#D6EAF8', '#E8DAEF', '#FADBD8',
8
8
  '#F5B7B1', '#E6B0AA', '#FCF3CF', '#FDEBD0', '#F6DDCC', '#D98880', '#EC7063', '#A569BD', '#85C1E9', '#45B39D', '#F7DC6F',
9
9
  '#DC7633', '#839192', '#6C3483', '#B03A2E', '#7B7D7D', '#4D5656', '#28B463', '#0E6655', '#F39C12', '#0E6251', '#1B4F72',
10
- '#FAE5D3', '#82E0AA', '#FF00FF', '#663399', '#4B0082', '#7CFC00', '#48D1CC'
10
+ '#FAE5D3', '#82E0AA', '#FF00FF', '#663399', '#4B0082', '#7CFC00'
11
11
  ]
12
12
  end
13
13
  end
@@ -0,0 +1,7 @@
1
+ module EducodeSales
2
+ class SalesDetail < ApplicationRecord
3
+ belongs_to :business
4
+ belongs_to :product_catalog
5
+ belongs_to :staff
6
+ end
7
+ end
@@ -0,0 +1,230 @@
1
+ module EducodeSales
2
+ class ReturnForecastService
3
+ attr_reader :user, :params, :request
4
+ # ReturnForecastService.new(current_user, request, params).call
5
+ def initialize(user, request, params)
6
+ @user = user
7
+ @request = request
8
+ @params = params
9
+ end
10
+
11
+ def call
12
+ end
13
+
14
+ def return_forecast_quarter(labels, selects, staff_id = nil)
15
+ plan_get = plan_get(staff_id, labels, "quarter")
16
+ actual_get = actual_get(staff_id, labels, "quarter")
17
+ datasets = selects.map do |select|
18
+ if select == "计划投标额"
19
+ {
20
+ label: select,
21
+ data: labels.map do |d|
22
+ quarter = d.split("-").last.to_i
23
+ year = d.split("-").first.to_i
24
+ plan_get[[year, quarter]]&.pluck(:budget_amount)&.reject(&:blank?)&.sum.to_f
25
+ end,
26
+ backgroundColor: [
27
+ 'rgba(255, 99, 132, 0.2)',
28
+ ],
29
+ borderColor: [
30
+ 'rgba(255,99,132,1)',
31
+ ],
32
+ borderWidth: 1
33
+ }
34
+ else
35
+ {
36
+ label: select,
37
+ data: labels.map do |d|
38
+ quarter = d.split("-").last.to_i
39
+ year = d.split("-").first.to_i
40
+ actual_get[[year, quarter]]&.pluck(:actual_amount)&.reject(&:blank?)&.sum.to_f
41
+ end,
42
+ backgroundColor: [
43
+ 'rgba(54, 162, 235, 0.2)',
44
+ ],
45
+ borderColor: [
46
+ 'rgba(54, 162, 235, 1)',
47
+ ],
48
+ borderWidth: 1
49
+ }
50
+ end
51
+ end
52
+
53
+ {
54
+ labels: labels,
55
+ datasets: datasets
56
+ }
57
+ end
58
+
59
+ def return_forecast_week(labels, selects, staff_id = nil)
60
+
61
+ plan_get = plan_get(staff_id, labels, "week")
62
+ actual_get = actual_get(staff_id, labels, "week")
63
+ datasets = selects.map do |select|
64
+ if select == "计划投标额"
65
+ {
66
+ label: select,
67
+ data: labels.map do |d|
68
+ week = d.split("-").last
69
+ year = d.split("-").first
70
+ yearweek = "#{year}#{week}".to_i
71
+ plan_get[yearweek].to_f
72
+ end,
73
+ backgroundColor: [
74
+ 'rgba(255, 99, 132, 0.2)',
75
+ ],
76
+ borderColor: [
77
+ 'rgba(255,99,132,1)',
78
+ ],
79
+ borderWidth: 1
80
+ }
81
+ else
82
+ {
83
+ label: select,
84
+ data: labels.map do |d|
85
+ week = d.split("-").last
86
+ year = d.split("-").first
87
+ yearweek = "#{year}#{week}".to_i
88
+ actual_get[yearweek].to_f
89
+ end,
90
+ backgroundColor: [
91
+ 'rgba(54, 162, 235, 0.2)',
92
+ ],
93
+ borderColor: [
94
+ 'rgba(54, 162, 235, 1)',
95
+ ],
96
+ borderWidth: 1
97
+ }
98
+ end
99
+ end
100
+
101
+ {
102
+ labels: labels,
103
+ datasets: datasets
104
+ }
105
+ end
106
+
107
+ def return_forecast_month(labels, selects, staff_id = nil)
108
+ plan_get = plan_get(staff_id, labels, "month")
109
+ actual_get = actual_get(staff_id, labels, "month")
110
+ datasets = selects.map do |select|
111
+ if select == "计划投标额"
112
+ {
113
+ label: select,
114
+ data: labels.map do |d|
115
+ month = d.split("-").last.to_i
116
+ year = d.split("-").first.to_i
117
+ plan_get[[year, month]]&.pluck(:budget_amount)&.reject(&:blank?)&.sum.to_f
118
+ end,
119
+ backgroundColor: [
120
+ 'rgba(255, 99, 132, 0.2)',
121
+ ],
122
+ borderColor: [
123
+ 'rgba(255,99,132,1)',
124
+ ],
125
+ borderWidth: 1
126
+ }
127
+ else
128
+ {
129
+ label: select,
130
+ data: labels.map do |d|
131
+ month = d.split("-").last.to_i
132
+ year = d.split("-").first.to_i
133
+ actual_get[[year, month]]&.pluck(:actual_amount)&.reject(&:blank?)&.sum.to_f
134
+ end,
135
+ backgroundColor: [
136
+ 'rgba(54, 162, 235, 0.2)',
137
+ ],
138
+ borderColor: [
139
+ 'rgba(54, 162, 235, 1)',
140
+ ],
141
+ borderWidth: 1
142
+ }
143
+ end
144
+ end
145
+
146
+ {
147
+ labels: labels,
148
+ datasets: datasets
149
+ }
150
+ end
151
+
152
+ def return_forecast_year(labels, selects, staff_id = nil)
153
+ plan_get = plan_get(staff_id, labels, "year")
154
+ actual_get = actual_get(staff_id, labels, "year")
155
+ datasets = selects.map do |select|
156
+ if select == "计划投标额"
157
+ {
158
+ label: select,
159
+ data: labels.map { |d| plan_get[d.to_i] || 0 },
160
+ backgroundColor: [
161
+ 'rgba(255, 99, 132, 0.2)',
162
+ ],
163
+ borderColor: [
164
+ 'rgba(255,99,132,1)',
165
+ ],
166
+ borderWidth: 1
167
+ }
168
+ else
169
+ {
170
+ label: select,
171
+ data: labels.map { |d| actual_get[d.to_i] || 0 },
172
+ backgroundColor: [
173
+ 'rgba(54, 162, 235, 0.2)',
174
+ ],
175
+ borderColor: [
176
+ 'rgba(54, 162, 235, 1)',
177
+ ],
178
+ borderWidth: 1
179
+ }
180
+ end
181
+ end
182
+
183
+ {
184
+ labels: labels,
185
+ datasets: datasets
186
+ }
187
+ end
188
+
189
+ private
190
+
191
+ def plan_get(staff_id, time_range, type)
192
+ # budget_amount 预算额
193
+ staff_id = staff_id.present? ? Array(staff_id) : nil
194
+ data = Business.joins(:last_follow_up)
195
+ .where("educode_sales_follow_ups.invitation_at >= ? and educode_sales_follow_ups.invitation_at <= ? #{staff_id.present? ? "AND educode_sales_follow_ups.staff_id in (#{staff_id.join(",")})" : ""}", time_range.first, time_range.last)
196
+ case type
197
+ when "week"
198
+ data.select("educode_sales_follow_ups.*, yearweek(educode_sales_follow_ups.invitation_at) as week").group("yearweek(educode_sales_follow_ups.invitation_at)").sum(:budget_amount)
199
+ when "quarter"
200
+ data = data.select("educode_sales_follow_ups.*, quarter(educode_sales_follow_ups.invitation_at) as quarter, year(educode_sales_follow_ups.invitation_at) as year")
201
+ data.group_by { |d| [d.year, d.quarter] }
202
+ when "month"
203
+ data = data.select("educode_sales_follow_ups.*, year(educode_sales_follow_ups.invitation_at) as year, month(educode_sales_follow_ups.invitation_at) as month")
204
+ data.group_by { |d| [d.year, d.month] }
205
+ when "year"
206
+ data.select("educode_sales_follow_ups.*, year(educode_sales_follow_ups.invitation_at) as year").group("year(educode_sales_follow_ups.invitation_at)").sum(:budget_amount)
207
+ end
208
+ end
209
+
210
+ def actual_get(staff_id, time_range, type)
211
+ # actual_amount 合同额
212
+ staff_id = staff_id.present? ? Array(staff_id) : nil
213
+ data = Business.joins(:last_follow_up)
214
+ .where("educode_sales_follow_ups.bidded_date >= ? and educode_sales_follow_ups.bidded_date <= ? #{staff_id.present? ? "AND educode_sales_follow_ups.staff_id in (#{staff_id.join(",")})" : ""}", time_range.first, time_range.last)
215
+ case type
216
+ when "week"
217
+ data.select("educode_sales_follow_ups.*, yearweek(educode_sales_follow_ups.bidded_date) as week").group("yearweek(educode_sales_follow_ups.bidded_date)").sum(:actual_amount)
218
+ when "quarter"
219
+ data = data.select("educode_sales_follow_ups.*, quarter(educode_sales_follow_ups.bidded_date) as quarter, year(educode_sales_follow_ups.bidded_date) as year")
220
+ data.group_by { |d| [d.year, d.quarter] }
221
+ when "month"
222
+ data = data.select("educode_sales_follow_ups.*, year(educode_sales_follow_ups.bidded_date) as year, month(educode_sales_follow_ups.bidded_date) as month")
223
+ data.group_by { |d| [d.year, d.month] }
224
+ when "year"
225
+ data.select("educode_sales_follow_ups.*, year(educode_sales_follow_ups.bidded_date) as year").group("year(educode_sales_follow_ups.bidded_date)").sum(:actual_amount)
226
+ end
227
+ end
228
+
229
+ end
230
+ end
@@ -102,7 +102,7 @@
102
102
  <hr>
103
103
  <div class="layui-inline">
104
104
  <label class="layui-form-label">计划签单时间:</label>
105
- <div class="layui-input-inline" style="line-height: 38px;">
105
+ <div class="layui-input-inline" style="line-height: 38px;width: 100px;">
106
106
  <input type="text" class="layui-input date" name="plan_signed_date" autocomplete="off" value="<%= @last_follow_up&.plan_signed_date %>">
107
107
  </div>
108
108
  </div>
@@ -115,10 +115,16 @@
115
115
  </div>
116
116
  <div class="layui-inline">
117
117
  <label class="layui-form-label" style="width:100px;">实际签单时间:</label>
118
- <div class="layui-input-inline" style="line-height: 38px;">
118
+ <div class="layui-input-inline" style="line-height: 38px;width: 100px;">
119
119
  <input type="text" class="layui-input date" name="signed_date" autocomplete="off" value="<%= @last_follow_up&.signed_date %>">
120
120
  </div>
121
121
  </div>
122
+ <div class="layui-inline">
123
+ <label class="layui-form-label">签约类型:</label>
124
+ <div class="layui-input-inline" style="line-height: 38px;width:110px;">
125
+ <%= select_tag "signed_clazz", options_for_select(@signed_clazz, @last_follow_up&.signed_clazz), class: 'required' %>
126
+ </div>
127
+ </div>
122
128
  <div class="layui-inline">
123
129
  <label class="layui-form-label" style="width:100px;">签约单位:</label>
124
130
  <div class="layui-input-inline" style="line-height: 38px;">
@@ -611,7 +617,7 @@
611
617
  initValue: gon.value, // 渲染初始化默认值
612
618
  hasSelectIcon: false,
613
619
  placeholder: '请输入头歌平台上单位部门', // 渲染的inputplaceholder值
614
- data: [gon.department],
620
+ data: gon.department,
615
621
  remoteSearch: true, // 是否启用远程搜索 默认是false,和远程搜索回调保存同步
616
622
  remoteMethod: function (value, cb) { // 远程搜索的回调函数
617
623
  if (!value) {
@@ -139,7 +139,7 @@
139
139
 
140
140
  var ctx = document.getElementById('forecast_myChart2');
141
141
  var forecast_myChart2 = new Chart(ctx, {
142
- type: 'line',
142
+ type: 'bar',
143
143
  data: <%=raw @forecast_count_data.to_json %>,
144
144
  options: {
145
145
  elements: {
@@ -71,6 +71,8 @@
71
71
  <dd><a href="/missions/contracts/product_list" class="<%= current?('layui-this', product_list_contracts_path) %>"><i style="padding-right: 35px"></i><%= image_tag "educode_sales/4.商机管理.png",size:"15"%><i style="font-size: 25px; padding-right: 15px"></i>产品目录</a>
72
72
  </dd>
73
73
  <% end %>
74
+ <dd><a href="/missions/sales_details" class="<%= current?('layui-this', sales_details_path) %>"><i style="padding-right: 35px"></i><%= image_tag "educode_sales/4.商机管理.png",size:"15"%><i style="font-size: 25px; padding-right: 15px"></i>销售明细</a>
75
+ </dd>
74
76
  <% if can? :read, EducodeSales::MoneyPlan %>
75
77
  <dd><a href="/missions/money_plans" class="<%= current?('layui-this', money_plans_path) %>"><i style="padding-right: 35px"></i><%= image_tag "educode_sales/money_plans.png",size:"15"%><i style="font-size: 25px; padding-right: 15px"></i>回款计划</a>
76
78
  </dd>
data/config/routes.rb CHANGED
@@ -22,6 +22,9 @@ EducodeSales::Engine.routes.draw do
22
22
  resources :sessions do
23
23
  end
24
24
 
25
+ resources :sales_details do
26
+ end
27
+
25
28
  resources :contracts do
26
29
  collection do
27
30
  get :follow_ups
@@ -0,0 +1,16 @@
1
+ class CreateEducodeSalesSalesDetails < ActiveRecord::Migration[5.2]
2
+ def change
3
+ create_table :educode_sales_sales_details do |t|
4
+ t.references :business
5
+ t.references :product_catalog
6
+ t.references :staff
7
+ t.float :price
8
+ t.float :amount
9
+ t.float :total_price
10
+ t.integer :custom_clazz
11
+ t.date :delivery_date
12
+
13
+ t.timestamps
14
+ end
15
+ end
16
+ end
@@ -1,3 +1,3 @@
1
1
  module EducodeSales
2
- VERSION = '0.9.83'
2
+ VERSION = '0.9.84'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: educode_sales
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.83
4
+ version: 0.9.84
5
5
  platform: ruby
6
6
  authors:
7
7
  - anke1460
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-10 00:00:00.000000000 Z
11
+ date: 2023-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -173,6 +173,7 @@ files:
173
173
  - app/controllers/educode_sales/sale_reports_controller.rb
174
174
  - app/controllers/educode_sales/sale_trends_controller.rb
175
175
  - app/controllers/educode_sales/sales_controller.rb
176
+ - app/controllers/educode_sales/sales_details_controller.rb
176
177
  - app/controllers/educode_sales/sessions_controller.rb
177
178
  - app/controllers/educode_sales/staffs_controller.rb
178
179
  - app/controllers/educode_sales/teacher_follows_controller.rb
@@ -243,6 +244,7 @@ files:
243
244
  - app/models/educode_sales/sale_plan.rb
244
245
  - app/models/educode_sales/sale_report.rb
245
246
  - app/models/educode_sales/sale_trend.rb
247
+ - app/models/educode_sales/sales_detail.rb
246
248
  - app/models/educode_sales/staff.rb
247
249
  - app/models/educode_sales/staff_permission.rb
248
250
  - app/models/educode_sales/staff_school.rb
@@ -250,6 +252,7 @@ files:
250
252
  - app/models/educode_sales/teacher.rb
251
253
  - app/models/educode_sales/teacher_assign_follow.rb
252
254
  - app/models/educode_sales/teacher_follow.rb
255
+ - app/services/return_forecast_service.rb
253
256
  - app/views/educode_sales/activities/_follows.html.erb
254
257
  - app/views/educode_sales/activities/_index.html.erb
255
258
  - app/views/educode_sales/activities/edit.html.erb
@@ -535,6 +538,7 @@ files:
535
538
  - app/views/educode_sales/sales/school.html.erb
536
539
  - app/views/educode_sales/sales/trends.html.erb
537
540
  - app/views/educode_sales/sales/xschool.html.erb
541
+ - app/views/educode_sales/sales_details/index.html.erb
538
542
  - app/views/educode_sales/sessions/login.html.erb
539
543
  - app/views/educode_sales/staffs/edit.html.erb
540
544
  - app/views/educode_sales/staffs/follow_up_departments.json.jbuilder
@@ -666,6 +670,7 @@ files:
666
670
  - db/migrate/20230430134710_create_educode_sales_assign_staffs.rb
667
671
  - db/migrate/20230501034307_create_educode_sales_follow_up_trends.rb
668
672
  - db/migrate/20230502142912_create_educode_sales_product_catalogs.rb
673
+ - db/migrate/20230510144317_create_educode_sales_sales_details.rb
669
674
  - lib/educode_sales.rb
670
675
  - lib/educode_sales/engine.rb
671
676
  - lib/educode_sales/version.rb