educode_sales 0.6.1 → 0.6.5

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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/educode_sales/money_plans.png +0 -0
  3. data/app/controllers/educode_sales/businesses_controller.rb +29 -8
  4. data/app/controllers/educode_sales/customers_controller.rb +45 -34
  5. data/app/controllers/educode_sales/follow_ups_controller.rb +1 -1
  6. data/app/controllers/educode_sales/money_plans_controller.rb +65 -0
  7. data/app/controllers/educode_sales/places_controller.rb +5 -1
  8. data/app/controllers/educode_sales/roles_controller.rb +4 -1
  9. data/app/controllers/educode_sales/sale_trends_controller.rb +44 -1
  10. data/app/controllers/educode_sales/staffs_controller.rb +3 -4
  11. data/app/controllers/educode_sales/teachers_controller.rb +13 -2
  12. data/app/models/educode_sales/permission.rb +3 -2
  13. data/app/models/educode_sales/role_area.rb +1 -0
  14. data/app/views/educode_sales/businesses/_follows.html.erb +18 -15
  15. data/app/views/educode_sales/businesses/edit.html.erb +3 -0
  16. data/app/views/educode_sales/businesses/edit_follow_record.html.erb +11 -2
  17. data/app/views/educode_sales/businesses/file.html.erb +8 -4
  18. data/app/views/educode_sales/businesses/index.html.erb +117 -26
  19. data/app/views/educode_sales/businesses/index.json.jbuilder +4 -2
  20. data/app/views/educode_sales/businesses/new_follow_record.html.erb +7 -2
  21. data/app/views/educode_sales/businesses/show_follow.html.erb +2 -1
  22. data/app/views/educode_sales/businesses/time_line.html.erb +1 -1
  23. data/app/views/educode_sales/customers/edit.html.erb +735 -22
  24. data/app/views/educode_sales/customers/edit_follow_record.html.erb +1 -1
  25. data/app/views/educode_sales/customers/index.html.erb +17 -18
  26. data/app/views/educode_sales/customers/index.json.jbuilder +3 -3
  27. data/app/views/educode_sales/customers/new.html.erb +713 -27
  28. data/app/views/educode_sales/customers/new_follow_record.html.erb +1 -1
  29. data/app/views/educode_sales/customers/show_follow.html.erb +1 -1
  30. data/app/views/educode_sales/customers/show_follow_record.html.erb +3 -3
  31. data/app/views/educode_sales/follow_ups/index.json.jbuilder +1 -0
  32. data/app/views/educode_sales/money_plans/index.html.erb +222 -0
  33. data/app/views/educode_sales/money_plans/index.json.jbuilder +21 -0
  34. data/app/views/educode_sales/places/index.html.erb +80 -2
  35. data/app/views/educode_sales/places/index.json.jbuilder +3 -1
  36. data/app/views/educode_sales/plans/_monthPlan.html.erb +2 -1
  37. data/app/views/educode_sales/plans/_weekPlan.html.erb +2 -1
  38. data/app/views/educode_sales/recycles/business.json.jbuilder +2 -2
  39. data/app/views/educode_sales/roles/edit.html.erb +9 -1
  40. data/app/views/educode_sales/sale_trends/trends.html.erb +93 -13
  41. data/app/views/educode_sales/sale_trends/trends.json.jbuilder +3 -14
  42. data/app/views/educode_sales/sales/index.html.erb +25 -17
  43. data/app/views/educode_sales/sales/index.json.jbuilder +17 -7
  44. data/app/views/educode_sales/sales/operations.json.jbuilder +2 -2
  45. data/app/views/educode_sales/teachers/index.html.erb +19 -18
  46. data/app/views/educode_sales/teachers/index.json.jbuilder +1 -1
  47. data/app/views/layouts/educode_sales/application.html.erb +13 -2
  48. data/config/routes.rb +2 -0
  49. data/db/migrate/20210902064109_create_educode_sales_role_permissions.rb +8 -0
  50. data/db/migrate/20211220102720_add_position_to_commons.rb +12 -0
  51. data/db/migrate/20211221075146_add_school_id_to_educode_sales_businesses.rb +8 -0
  52. data/lib/educode_sales/version.rb +1 -1
  53. metadata +8 -2
@@ -2,9 +2,9 @@
2
2
  <script type="text/html" id="toolbarDemo">
3
3
  <div class="layui-btn-container">
4
4
  <span class="table-label">附件信息</span>
5
- <%# if can? :create, EducodeSales::file %>
5
+ <% if can? :upload_file, EducodeSales::Business %>
6
6
  <button class="layui-btn layui-btn-normal layui-btn-sm data-add-btn pull-right" lay-event="upload_file">上传文件</button>
7
- <%# end %>
7
+ <% end %>
8
8
  </div>
9
9
  </script>
10
10
 
@@ -12,8 +12,12 @@
12
12
 
13
13
  <script type="text/html" id="currentTableBar_file">
14
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>
15
+ <% if can? :download_file, EducodeSales::Business %>
16
+ <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>
17
+ <% end %>
18
+ <% if can? :delete_file, EducodeSales::Business %>
19
+ <a class="layui-btn layui-btn-xs layui-btn-danger data-count-delete" lay-event="delete">删除</a>
20
+ <% end %>
17
21
  </script>
18
22
 
19
23
  <script type="text/html" id="showchance">
@@ -18,6 +18,7 @@
18
18
  <label class="layui-form-label">商机名称</label>
19
19
  <div class="layui-input-inline">
20
20
  <input type="text" name="name" autocomplete="off" class="layui-input" value="<%=params[:name] %>">
21
+ <input type="text" style="display: none" name="place_id" autocomplete="off" class="layui-input" value="<%=params[:place_id] %>">
21
22
  </div>
22
23
  </div>
23
24
  <div class="layui-inline">
@@ -27,46 +28,54 @@
27
28
  </div>
28
29
  </div>
29
30
  <div class="layui-inline">
30
- <label class="layui-form-label">销售人员</label>
31
+ <label class="layui-form-label">最新跟进人</label>
31
32
  <div class="layui-input-inline">
32
33
  <%= select_tag "staff_id", options_for_select(@staffs, params[:staff_id]), { 'lay-filter': 'staff_id', include_blank: true } %>
33
34
  </div>
34
35
  </div>
35
- <div class="layui-inline">
36
+ <div class="layui-inline show_item" style="display:none;">
36
37
  <label class="layui-form-label">项目类型</label>
37
38
  <div class="layui-input-inline">
38
- <%= select_tag "business_type", options_for_select(EducodeSales::Common.where(clazz: 'business_type').pluck(:name, :id), params[:clazz_id]), { 'lay-filter': 'clazz_id', include_blank: true } %>
39
+ <div id="business_type" style="width: 190px;"></div>
39
40
  </div>
40
41
  </div>
41
- <div class="layui-inline">
42
+ <div class="layui-inline show_item" style="display:none;">
42
43
  <label class="layui-form-label">项目阶段</label>
43
44
  <div class="layui-input-inline">
44
- <%= select_tag "business_step", options_for_select(EducodeSales::Common.where(clazz: 'business_step').pluck(:name, :id)), { include_blank: true } %>
45
+ <div id="business_step" style="width: 190px;"></div>
45
46
  </div>
46
47
  </div>
47
- <div class="layui-inline">
48
+ <div class="layui-inline show_item" style="display:none;">
48
49
  <label class="layui-form-label">渠道名称</label>
49
50
  <div class="layui-input-inline">
50
51
  <div id="index_place" style="width: 190px;"></div>
51
52
  </div>
52
53
  </div>
53
- <div class="layui-inline">
54
+ <div class="layui-inline show_item" style="display:none;">
54
55
  <label class="layui-form-label">区域</label>
55
56
  <div class="layui-input-inline">
56
57
  <%= select_tag "area", options_for_select(EducodeSales::Common.where(clazz: 'area').pluck(:name, :id)), { include_blank: true } %>
57
58
  </div>
58
59
  </div>
59
- <div class="layui-inline">
60
- <label class="layui-form-label">起止时间</label>
60
+ <div class="layui-inline show_item" style="display:none;">
61
+ <label class="layui-form-label">创建时间</label>
61
62
  <div class="layui-input-inline">
62
63
  <input type="text" class="layui-input" id="date" name="date" placeholder=" - ">
63
64
  </div>
64
65
  </div>
66
+ <div class="layui-inline show_item" style="display:none;">
67
+ <label class="layui-form-label">招标时间</label>
68
+ <div class="layui-input-inline">
69
+ <input type="text" class="layui-input" id="invitation_at" name="invitation_at" placeholder=" - ">
70
+ </div>
71
+ </div>
65
72
  <div class="layui-inline">
66
73
  <button type="reset" class="layui-btn layui-btn-primary" lay-submit lay-filter="reset_business_search">重置
67
74
  </button>
68
75
  <button type="submit" id="search_bt" class="layui-btn layui-btn-primary" lay-submit lay-filter="search_bussiness">搜索
69
76
  </button>
77
+ <button type="submit" class="layui-btn layui-btn-normal" lay-submit lay-filter="show_hide">展开/收起
78
+ </button>
70
79
  </div>
71
80
  </div>
72
81
  </form>
@@ -107,6 +116,9 @@
107
116
  <script type="text/html" id="show_follow">
108
117
  <a href="javascript:void(0);" lay-event="show_follow" class="layui-table-link">{{ d.follow_ups_count }}</a>
109
118
  </script>
119
+ <script type="text/html" id="school_name">
120
+ <a href="<%= base_url%>/colleges/{{d.school_id}}/statistics" class="layui-table-link" target="_blank">{{ d.school }}</a>
121
+ </script>
110
122
 
111
123
 
112
124
  <script>
@@ -122,6 +134,10 @@
122
134
  elem: '#date',
123
135
  range: true
124
136
  });
137
+ laydate.render({
138
+ elem: '#invitation_at',
139
+ range: true
140
+ });
125
141
 
126
142
  var is_show = <%=params[:name].present? || params[:clazz_id].present? || params[:place_id].present? || params[:school].present? %>
127
143
  if(is_show){
@@ -131,6 +147,15 @@
131
147
  $('.businesses_list_div').addClass('layui-show');
132
148
  }
133
149
 
150
+ var business_type_list = xmSelect.render({
151
+ el: '#business_type',
152
+ data: gon.business_type
153
+ })
154
+ business_type_list.setValue(gon.type)
155
+ var business_step_list = xmSelect.render({
156
+ el: '#business_step',
157
+ data: gon.business_step
158
+ })
134
159
  var index_place_list = xmSelect.render({
135
160
  el: '#index_place',
136
161
  model: {
@@ -203,7 +228,7 @@
203
228
  field: 'school',
204
229
  width: 150,
205
230
  title: '单位',
206
- templet:'<div><span title="{{d.school}}">{{d.school}}</span></div>'
231
+ templet:'#school_name'
207
232
  },
208
233
  {
209
234
  field: 'department',
@@ -235,6 +260,22 @@
235
260
  width: 90,
236
261
  title: '阶段'
237
262
  },
263
+ {
264
+ field: 'source',
265
+ width: 90,
266
+ title: '商机来源'
267
+ },
268
+ {
269
+ field: 'last_follow_person',
270
+ width: 100,
271
+ title: '最新跟进人'
272
+ },
273
+ {
274
+ field: 'latest_time',
275
+ width: 200,
276
+ title: '最新跟进时间',
277
+ sort: true
278
+ },
238
279
  {
239
280
  field: 'invitation_at',
240
281
  width: 105,
@@ -281,24 +322,16 @@
281
322
  totalRow: true
282
323
  },
283
324
  {
284
- field: 'place',
285
- width: 160,
286
- title: '渠道',
287
- },
288
- {
289
- field: 'source',
290
- width: 90,
291
- title: '商机来源'
292
- },
293
- {
294
- field: 'last_follow_person',
325
+ field: 'wait_return_money',
295
326
  width: 100,
296
- title: '最新跟进人'
327
+ title: '待回款',
328
+ sort: true,
329
+ totalRow: true
297
330
  },
298
331
  {
299
- field: 'latest_time',
300
- width: 200,
301
- title: '最新跟进时间'
332
+ field: 'place',
333
+ width: 160,
334
+ title: '渠道',
302
335
  },
303
336
  {
304
337
  title: '操作',
@@ -390,6 +423,7 @@
390
423
  });
391
424
  }
392
425
  function time_line(id,name) {
426
+ business_id = id
393
427
  var content = miniPage.getHrefContent('/missions/businesses/time_line?business_id=' + id);
394
428
  var openWH = miniPage.getOpenWidthHeight();
395
429
  sindex = layer.open({
@@ -475,7 +509,17 @@
475
509
 
476
510
  // 监听搜索操作
477
511
  form.on('submit(search_bussiness)', function (data) {
512
+ var business_type = [];
513
+ business_type_list.getValue().forEach(function(d) {
514
+ business_type.push(d.value);
515
+ })
516
+ var business_step = [];
517
+ business_step_list.getValue().forEach(function(d) {
518
+ business_step.push(d.value);
519
+ })
478
520
  data.field.place_id = index_place_list.getValue('valueStr');
521
+ data.field.business_type = business_type.toString();
522
+ data.field.business_step = business_step.toString();
479
523
  search = data.field
480
524
  console.log(search);
481
525
  table.reload('businesses_table', {
@@ -497,12 +541,59 @@
497
541
  return false;
498
542
  });
499
543
 
544
+ form.on('submit(show_hide)', function (data) {
545
+ $(".show_item").toggle()
546
+ return false;
547
+ });
500
548
  form.on('submit(reset_business_search)', function (data) {
501
549
  var field = data.field;
502
550
  form.val('search_form', {
503
551
  name: '', department: '', staff_id: '', business_type: '', business_step: '',
504
- place_id: '', date: '', area: ''
552
+ place_id: '', date: '', area: '', invitation_at: ''
505
553
  })
554
+ var index_place_list = xmSelect.render({
555
+ el: '#index_place',
556
+ model: {
557
+ icon: 'hidden',
558
+ label: {
559
+ type: 'text',
560
+ text: {
561
+ //左边拼接的字符
562
+ left: '',
563
+ //右边拼接的字符
564
+ right: '',
565
+ //中间的分隔符
566
+ separator: ', ',
567
+ },
568
+ }
569
+ },
570
+ remoteSearch: true,
571
+ clickClose: true,
572
+ delay: 1000,
573
+ paging: true,
574
+ radio: true,
575
+ pageRemote: true,
576
+ filterable: true,
577
+ remoteMethod: function (val, cb, show, pageIndex) {
578
+ $.ajax( '/missions/sales_place', {
579
+ method: 'get',
580
+ data: {
581
+ q: val,
582
+ page: pageIndex
583
+ },
584
+ dataType: 'json',
585
+ success: function (res) {
586
+ var data = res.data;
587
+ if (res.code == 0) {
588
+ cb(res.data, res.count);
589
+ } else {
590
+ layer.msg(res.msg, {time: 2000, icon: 2, shade: 0.01});
591
+ }
592
+
593
+ }
594
+ })
595
+ }
596
+ })
506
597
  return false;
507
598
  });
508
599
 
@@ -5,7 +5,8 @@ json.data do
5
5
  json.name d.name
6
6
  json.department d.department.name
7
7
  json.school d.department.school.name
8
- json.follow_ups_count d.follow_ups_count
8
+ json.school_id d.department.school.id
9
+ json.follow_ups_count d.follow_ups.where(deleted_at: nil).size
9
10
  follow_ups_count += d.follow_ups_count
10
11
  json.follow_up_id d.last_follow_up_id
11
12
  # json.teachers_count d.follow_ups.sum(:key_people_count)
@@ -19,13 +20,14 @@ json.data do
19
20
  json.total_amount d.last_follow_up&.total_amount
20
21
  json.actual_amount d.last_follow_up&.actual_amount
21
22
  json.return_money d.return_money
23
+ json.wait_return_money d.wait_return_money
22
24
  json.place d.last_follow_up&.place&.name
23
25
  json.last_follow_person d.last_follow_up.present? ? d.last_follow_up.staff.user.real_name : EducodeSales::Staff.find(d.staff_id).user.real_name
24
26
  json.source d.source
25
27
  json.assign_follow_ups d.last_follow_up.present? ? d.last_follow_up.assign_follow_ups.pluck(:staff_id) : []
26
28
  json.current_staff_id @current_admin.id
27
29
  json.staff_id d.staff_id
28
- json.latest_time d.last_follow_up.present? ? d.last_follow_up.created_at.to_s : d.created_at.to_s
30
+ json.latest_time d.last_follow_up.present? ? d.last_follow_up.created_at.to_s : ''
29
31
  end
30
32
  end
31
33
 
@@ -74,13 +74,15 @@
74
74
  <input name="total_amount" type="number" class="layui-input" autocomplete="off"
75
75
  value="<%= @last_follow_up&.total_amount%>">
76
76
  </div>
77
- </div>
77
+ 客户采购支出的费用。总额的生命历程:1.在最初阶段,是商机的预算总额;2.在挂网阶段,是项目的挂网预算总额;3.在中标阶段,是项目的中标总额。 </div>
78
+ <br>
78
79
  <div class="layui-inline">
79
80
  <label class="layui-form-label">合同额(万)</label>
80
81
  <div class="layui-input-inline">
81
82
  <input name="actual_amount" type="number" class="layui-input" autocomplete="off" placeholder="本单位的签单金额"
82
83
  value="<%= @last_follow_up&.actual_amount%>">
83
84
  </div>
85
+ 客户签给头歌的费用。合同额的生命历程:1.在中标之前,合同额都是0;2.在中标之后,实际与头歌签合同的金额。
84
86
  </div>
85
87
  <br>
86
88
  <div class="layui-inline new_place_select">
@@ -88,7 +90,9 @@
88
90
  <div class="layui-input-inline" style="z-index: 101">
89
91
  <div id="place" style="width: 190px;"></div>
90
92
  </div>
93
+ 总额里,渠道拿到的部分。
91
94
  </div>
95
+ <br>
92
96
  <div class="layui-inline">
93
97
  <label class="layui-form-label">渠道分成(万)</label>
94
98
  <div class="layui-input-inline">
@@ -106,7 +110,7 @@
106
110
  </div>
107
111
  <div class="layui-form-item">
108
112
  <label class="layui-form-label">指定跟进人</label>
109
- <div class="layui-input-inline" style="z-index: 100">
113
+ <div class="layui-input-inline" >
110
114
  <div id="assign_follow" style="width: 512px;"></div>
111
115
  </div>
112
116
  <div class="layui-inline" style="padding: 9px 15px">
@@ -144,6 +148,7 @@
144
148
  </div>
145
149
  </div>
146
150
  </div>
151
+ </div>
147
152
 
148
153
  <script>
149
154
  layui.use(['form', 'table', 'upload', 'layer', 'laytpl', 'request', 'laydate', 'xmSelect'], function () {
@@ -12,7 +12,7 @@
12
12
  <span class="table-label pull-right" style="padding-right: 20px">温馨提示:仅可以在24小时之内,编辑/删除最新的跟进记录</span>
13
13
  </div>
14
14
  </script>
15
- <div class="edit-table tool">
15
+ <div class=" tool">
16
16
  <div class="z-index">
17
17
  <table class="layui-hide" id="sale_plan_follow_table" lay-filter="sale_plan_follow_table"></table>
18
18
  </div>
@@ -121,6 +121,7 @@
121
121
  field: 'description',
122
122
  width: 120,
123
123
  title: '最新进展',
124
+ templet:'<div><span title="{{d.description}}">{{d.description}}</span></div>'
124
125
  },
125
126
  {
126
127
  field: 'invitation_at',
@@ -43,7 +43,7 @@
43
43
  function demo(){
44
44
  layer.closeAll()
45
45
  business_id = parent.business_id
46
- var content = miniPage.getHrefContent('/missions/businesses/show_follow?id=' + parent.business_id);
46
+ var content = miniPage.getHrefContent('/missions/businesses/show_follow?id=' + business_id);
47
47
  var openWH = miniPage.getOpenWidthHeight();
48
48
  sindex = layer.open({
49
49
  title: '商机列表/'+ parent.business_name +'的跟进记录',