educode_sales 0.5.5 → 0.5.9

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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/educode_sales//345/256/242/346/210/267/347/256/241/347/220/206.png +0 -0
  3. data/app/controllers/educode_sales/businesses_controller.rb +20 -1
  4. data/app/controllers/educode_sales/customer_extensions_controller.rb +17 -0
  5. data/app/controllers/educode_sales/customer_follows_controller.rb +41 -0
  6. data/app/controllers/educode_sales/customers_controller.rb +194 -0
  7. data/app/controllers/educode_sales/follow_ups_controller.rb +58 -1
  8. data/app/controllers/educode_sales/home_controller.rb +18 -2
  9. data/app/controllers/educode_sales/roles_controller.rb +4 -1
  10. data/app/controllers/educode_sales/sale_trends_controller.rb +19 -9
  11. data/app/controllers/educode_sales/sales_controller.rb +3 -0
  12. data/app/controllers/educode_sales/teachers_controller.rb +41 -14
  13. data/app/models/educode_sales/customer.rb +4 -0
  14. data/app/models/educode_sales/customer_extension.rb +7 -0
  15. data/app/models/educode_sales/customer_follow.rb +5 -0
  16. data/app/models/educode_sales/permission.rb +2 -1
  17. data/app/models/educode_sales/role_area.rb +1 -0
  18. data/app/models/educode_sales/teacher.rb +2 -1
  19. data/app/models/educode_sales/teacher_assign_follow.rb +6 -0
  20. data/app/views/educode_sales/activities/index.html.erb +4 -5
  21. data/app/views/educode_sales/activities/show_teachers.html.erb +1 -1
  22. data/app/views/educode_sales/businesses/_follows.html.erb +258 -0
  23. data/app/views/educode_sales/businesses/edit_follow_record.html.erb +69 -6
  24. data/app/views/educode_sales/businesses/index.html.erb +155 -66
  25. data/app/views/educode_sales/businesses/index.json.jbuilder +1 -1
  26. data/app/views/educode_sales/businesses/new.html.erb +3 -0
  27. data/app/views/educode_sales/businesses/new_follow_record.html.erb +70 -6
  28. data/app/views/educode_sales/businesses/show_follow.html.erb +15 -10
  29. data/app/views/educode_sales/businesses/show_follow.json.jbuilder +1 -0
  30. data/app/views/educode_sales/businesses/show_follow_record.html.erb +8 -0
  31. data/app/views/educode_sales/businesses/time_line.html.erb +1 -1
  32. data/app/views/educode_sales/customers/edit.html.erb +60 -0
  33. data/app/views/educode_sales/customers/edit_department.html.erb +52 -0
  34. data/app/views/educode_sales/customers/edit_follow_record.html.erb +50 -0
  35. data/app/views/educode_sales/customers/give.html.erb +51 -0
  36. data/app/views/educode_sales/customers/index.html.erb +485 -0
  37. data/app/views/educode_sales/customers/index.json.jbuilder +25 -0
  38. data/app/views/educode_sales/customers/new.html.erb +89 -0
  39. data/app/views/educode_sales/customers/new_department.html.erb +53 -0
  40. data/app/views/educode_sales/customers/new_follow_record.html.erb +54 -0
  41. data/app/views/educode_sales/customers/show_department.json.jbuilder +13 -0
  42. data/app/views/educode_sales/customers/show_follow.html.erb +439 -0
  43. data/app/views/educode_sales/customers/show_follow.json.jbuilder +13 -0
  44. data/app/views/educode_sales/customers/show_follow_record.html.erb +17 -0
  45. data/app/views/educode_sales/follow_ups/index.json.jbuilder +20 -0
  46. data/app/views/educode_sales/home/sales_place.json.jbuilder +9 -0
  47. data/app/views/educode_sales/operation_plans/_monthPlan.html.erb +6 -0
  48. data/app/views/educode_sales/operation_plans/_monthly.html.erb +2 -0
  49. data/app/views/educode_sales/operation_plans/_weekPlan.html.erb +6 -0
  50. data/app/views/educode_sales/operation_plans/_weekly.html.erb +2 -0
  51. data/app/views/educode_sales/places/index.json.jbuilder +1 -1
  52. data/app/views/educode_sales/plans/_monthPlan.html.erb +5 -0
  53. data/app/views/educode_sales/plans/_monthly.html.erb +1 -0
  54. data/app/views/educode_sales/plans/_weekPlan.html.erb +5 -0
  55. data/app/views/educode_sales/plans/_weekly.html.erb +1 -0
  56. data/app/views/educode_sales/recycles/index.html.erb +1 -1
  57. data/app/views/educode_sales/roles/edit.html.erb +8 -0
  58. data/app/views/educode_sales/sale_trends/trends.html.erb +2 -2
  59. data/app/views/educode_sales/sales/index.html.erb +58 -19
  60. data/app/views/educode_sales/sales/index.json.jbuilder +31 -16
  61. data/app/views/educode_sales/sales/operations.html.erb +4 -1
  62. data/app/views/educode_sales/teachers/course_list.json.jbuilder +1 -1
  63. data/app/views/educode_sales/teachers/edit.html.erb +53 -7
  64. data/app/views/educode_sales/teachers/index.html.erb +42 -3
  65. data/app/views/educode_sales/teachers/index.json.jbuilder +6 -3
  66. data/app/views/educode_sales/teachers/new.html.erb +55 -17
  67. data/app/views/educode_sales/teachers/show_follow.html.erb +10 -5
  68. data/app/views/educode_sales/teachers/show_follow.json.jbuilder +1 -0
  69. data/app/views/layouts/educode_sales/application.html.erb +8 -1
  70. data/config/routes.rb +26 -0
  71. data/db/migrate/20210902064109_create_educode_sales_role_permissions.rb +15 -0
  72. data/db/migrate/20211201023750_create_educode_sales_teacher_assign_follows.rb +11 -0
  73. data/db/migrate/20211206054756_add_year_to_follow_ups.rb +5 -0
  74. data/db/migrate/20211214100803_create_customer_extensions.rb +9 -0
  75. data/db/migrate/20211215025029_create_educode_sales_customer_follows.rb +12 -0
  76. data/lib/educode_sales/version.rb +1 -1
  77. metadata +30 -2
@@ -0,0 +1,7 @@
1
+ module EducodeSales
2
+ class CustomerExtension < ApplicationRecord
3
+ belongs_to :customer_staff, class_name: 'Staff', optional: true
4
+ belongs_to :school
5
+
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module EducodeSales
2
+ class CustomerFollow < ApplicationRecord
3
+ belongs_to :staff
4
+ end
5
+ end
@@ -10,7 +10,8 @@ module EducodeSales
10
10
  '运营分工': 'operation_job',
11
11
  '教师运营': 'teacher',
12
12
  '活动运营': 'activity',
13
- '运营计划': 'operation_plan'
13
+ '运营计划': 'operation_plan',
14
+ '客户管理': 'customer'
14
15
  }
15
16
  end
16
17
  end
@@ -8,6 +8,7 @@ module EducodeSales
8
8
  '销售计划': 'SalePlan',
9
9
  '教师运营': 'Teacher',
10
10
  '运营计划': 'Operation',
11
+ '客户管理': 'Customer',
11
12
  }
12
13
  end
13
14
  end
@@ -6,8 +6,9 @@ module EducodeSales
6
6
  has_many :operation_plans, dependent: :destroy
7
7
  has_many :course_subjects, dependent: :destroy
8
8
  has_many :key_person, dependent: :destroy
9
+ has_many :teacher_assign_follows
9
10
  belongs_to :department, optional: true
10
- belongs_to :staff
11
+ belongs_to :staff, optional: true
11
12
  belongs_to :user, optional: true
12
13
  # belongs_to :follow_up, counter_cache: true, optional: true
13
14
  belongs_to :follow_up, class_name: 'TeacherFollow', optional: true
@@ -0,0 +1,6 @@
1
+ module EducodeSales
2
+ class TeacherAssignFollow < ApplicationRecord
3
+ belongs_to :staff
4
+ belongs_to :teacher
5
+ end
6
+ end
@@ -52,24 +52,23 @@
52
52
  {
53
53
  field: 'name',
54
54
  title: '活动名称',
55
- width: 400,
56
55
  templet: '#teachers'
57
56
  },
58
57
  {
59
58
  field: 'start_at',
60
- width: 120,
59
+ width: 200,
61
60
  title: '时间',
62
61
  sort: true,
63
62
  },
64
63
  {
65
64
  field: 'days',
66
65
  title: '天数',
67
- width: 100
66
+ width: 200
68
67
  },
69
68
  {
70
69
  field: 'teachers_count',
71
70
  title: '教师数',
72
- width: 100,
71
+ width: 200,
73
72
  totalRow:true,
74
73
  templet: '#teachers_count'
75
74
  },
@@ -77,7 +76,7 @@
77
76
  field: 'students_count',
78
77
  title: '学生数',
79
78
  totalRow:'{{ parseInt(d.TOTAL_NUMS) }}',
80
- width: 100
79
+ width: 200
81
80
  },
82
81
  {
83
82
  title: '操作',
@@ -2,7 +2,7 @@
2
2
  <script type="text/html" id="teacher_toolbar">
3
3
  <div class="layui-btn-container">
4
4
  <span class="table-label">教师列表</span>
5
- <button class="layui-btn layui-btn-normal layui-btn-sm data-add-btn pull-right" lay-event="search_new"> 添加
5
+ <button class="layui-btn layui-btn-normal layui-btn-sm data-add-btn pull-right" lay-event="search_new"> 添加教师
6
6
  </button>
7
7
  </div>
8
8
  </script>
@@ -0,0 +1,258 @@
1
+ <div style="margin: 10px 10px 10px 10px">
2
+ <form class="layui-form layui-form-pane" lay-filter="search_follows">
3
+ <div class="layui-form-item">
4
+ <div class="layui-inline">
5
+ <label class="layui-form-label">所属商机</label>
6
+ <div class="layui-input-inline">
7
+ <input type="text" name="name" autocomplete="off" class="layui-input">
8
+ </div>
9
+ </div>
10
+ <div class="layui-inline">
11
+ <label class="layui-form-label">单位</label>
12
+ <div class="layui-input-inline">
13
+ <input type="text" name="department" autocomplete="off" class="layui-input">
14
+ </div>
15
+ </div>
16
+ <div class="layui-inline">
17
+ <label class="layui-form-label">销售人员</label>
18
+ <div class="layui-input-inline">
19
+ <%= select_tag "staff_id", options_for_select(@staffs, params[:staff_id]), { 'lay-filter': 'staff_id', include_blank: true } %>
20
+ </div>
21
+ </div>
22
+ <div class="layui-inline">
23
+ <label class="layui-form-label">区域</label>
24
+ <div class="layui-input-inline">
25
+ <%= select_tag "area", options_for_select(EducodeSales::Common.where(clazz: 'area').pluck(:name, :id)), { include_blank: true } %>
26
+ </div>
27
+ </div>
28
+ <div class="layui-inline">
29
+ <label class="layui-form-label">跟进时间</label>
30
+ <div class="layui-input-inline">
31
+ <input type="text" class="layui-input" id="follows_date" name="follows_date" autocomplete="off" placeholder=" - ">
32
+ </div>
33
+ </div>
34
+
35
+ <div class="layui-inline">
36
+ <button type="reset" class="layui-btn layui-btn-primary" lay-submit lay-filter="reset_follows_search">重置
37
+ </button>
38
+ <button type="submit" class="layui-btn layui-btn-primary" lay-submit lay-filter="search_follows">搜 索
39
+ </button>
40
+ </div>
41
+ </div>
42
+ </form>
43
+ </div>
44
+ <div class="">
45
+ <table class="layui-hide" id="teachers_table" style="min-height: 300px;" lay-filter="teachers_table"></table>
46
+ </div>
47
+ <script type="text/html" id="toolbarDemo_follows">
48
+ <div class="layui-btn-container">
49
+ <span class="table-label">跟进动态</span>
50
+ </div>
51
+ </script>
52
+ <script type="text/html" id="currentTableBar_follows">
53
+ <a class="layui-btn layui-btn-normal layui-btn-xs data-count-edit" lay-event="add_event">详情</a>
54
+ </script>
55
+ <script type="text/html" id="business">
56
+ <a href="javascript:void(0);" lay-event="business" class="layui-table-link">{{ d.business }}</a>
57
+ </script>
58
+
59
+
60
+ <script>
61
+ layui.use(['form', 'table', 'miniPage', 'element', 'request', 'laydate'], function () {
62
+ var $ = layui.jquery,
63
+ form = layui.form,
64
+ request = layui.request,
65
+ dropdown = layui.dropdown,
66
+ miniPage = layui.miniPage,
67
+ laydate = layui.laydate;
68
+
69
+ var laydate = layui.laydate;
70
+
71
+ laydate.render({
72
+ elem: '#follows_date',
73
+ range: true
74
+ });
75
+
76
+ table = layui.table;
77
+ table.render({
78
+ elem: '#teachers_table',
79
+ url: '/missions/follow_ups',
80
+ // where: {q: form.val('search_form')},
81
+ toolbar: '#toolbarDemo_follows',
82
+ defaultToolbar: ['filter'],
83
+ initSort: {
84
+ field: 'created_at' //排序字段,对应 cols 设定的各字段名
85
+ ,type: 'desc' //排序方式 asc: 升序、desc: 降序、null: 默认排序
86
+ },
87
+ cols: [
88
+ [
89
+ {
90
+ field: 'id',
91
+ width: 60,
92
+ title:'序号',type: 'numbers',
93
+ },
94
+ {
95
+ field: 'description',
96
+ title: '最新进展',
97
+ templet:'<div><span title="{{d.description}}">{{d.description}}</span></div>'
98
+ },
99
+ {
100
+ field: 'advise',
101
+ width: 120,
102
+ title: '团队建议',
103
+ templet:'<div><span title="{{d.advise}}">{{d.advise}}</span></div>'
104
+ },
105
+ {
106
+ field: 'clazz',
107
+ width: 80,
108
+ title: '类型',
109
+ templet:'<div><span title="{{d.clazz}}">{{d.clazz}}</span></div>'
110
+ },
111
+ {
112
+ field: 'stage',
113
+ title: '阶段',
114
+ width: 90,
115
+ templet:'<div><span title="{{d.stage}}">{{d.stage}}</span></div>'
116
+ },
117
+ {
118
+ field: 'key_people',
119
+ width: 90,
120
+ title: '关键人',
121
+ templet:'<div><span title="{{d.key_people}}">{{d.key_people}}</span></div>'
122
+ },
123
+ {
124
+ field: 'business',
125
+ width: 120,
126
+ title: '所属商机',
127
+ templet:'#business'
128
+ },
129
+ {
130
+ field: 'school',
131
+ width: 120,
132
+ title: '单位',
133
+ templet:'<div><span title="{{d.school}}">{{d.school}}</span></div>'
134
+ },
135
+ {
136
+ field: 'staff',
137
+ width: 90,
138
+ title: '跟进人',
139
+ },
140
+ {
141
+ field: 'created_at',
142
+ width: 120,
143
+ title: '跟进时间',
144
+ sort: true,
145
+ templet:'<div><span title="{{d.created_at}}">{{d.created_at}}</span></div>'
146
+
147
+ },
148
+ {
149
+ title: '操作',
150
+ width: 80,
151
+ toolbar: '#currentTableBar_follows',
152
+ align: "center",
153
+ fixed: 'right'
154
+ }
155
+ ]
156
+ ],
157
+ limit: 20,
158
+ limits: [10,15,20,30,40,50,60,70,80,90],
159
+ page: true,
160
+ });
161
+
162
+
163
+
164
+
165
+
166
+ var sort = {}, search = {};
167
+ table.on('sort(teachers_table)', function (obj) {
168
+ sort.field = obj.field;
169
+ sort.order = obj.type;
170
+ table.reload('teachers_table', {
171
+ initSort: obj,
172
+ where: {
173
+ sort: sort,
174
+ q: search
175
+ }
176
+ });
177
+ })
178
+
179
+ // 监听搜索操作
180
+ form.on('submit(search_follows)', function (data) {
181
+ search = data.field
182
+ table.reload('teachers_table', {
183
+ page: {
184
+ curr: 1
185
+ },
186
+ where: {q: search, sort: sort}
187
+ }, 'data');
188
+ table.reload('businesses_table', {
189
+ page: {
190
+ curr: 1
191
+ },
192
+ where: {q: search, sort: sort}
193
+ }, 'data');
194
+ form.val('search_form', {
195
+ name: data.field.name, department: data.field.department, staff_id: data.field.staff_id, area: data.field.area
196
+ })
197
+ return false;
198
+ });
199
+
200
+ form.on('submit(reset_follows_search)', function (data) {
201
+ var field = data.field;
202
+ form.val('search_follows', {
203
+ area: "",
204
+ follows_date: "",
205
+ name: "",
206
+ department: "",
207
+ staff_id: ""
208
+ })
209
+ return false;
210
+ });
211
+ table.on('tool(teachers_table)', function (obj) {
212
+ var data = obj.data;
213
+ id = data.id
214
+ if (obj.event === 'add_event') { // 监听添加操作
215
+ var content = miniPage.getHrefContent('/missions/businesses/show_follow_record?follow_up_id=' + data.id);
216
+ var openWH = miniPage.getOpenWidthHeight();
217
+ show_index = layer.open({
218
+ title: '查看商机跟进记录',
219
+ type: 1,
220
+ shade: 0.2,
221
+ maxmin: true,
222
+ shadeClose: true,
223
+ area: [openWH[0] + 'px', openWH[1] + 'px'],
224
+ offset: [openWH[2] + 'px', openWH[3] + 'px'],
225
+ content: content
226
+ });
227
+ $(window).on("resize", function () {
228
+ layer.full(index);
229
+ });
230
+ } else if (obj.event === 'business') {
231
+ console.log(data);
232
+ business_id = data.business_id
233
+ business_name = data.business
234
+ content = miniPage.getHrefContent('/missions/businesses/show_follow?id=' + data.business_id);
235
+ openWH = miniPage.getOpenWidthHeight();
236
+ index = layer.open({
237
+ title: '商机列表/' + data.business + '的跟进记录',
238
+ type: 1,
239
+ shade: 0.2,
240
+ maxmin: true,
241
+ shadeClose: true,
242
+ area: [openWH[0] + 'px', openWH[1] + 'px'],
243
+ offset: [openWH[2] + 'px', openWH[3] + 'px'],
244
+ content: content
245
+ });
246
+ $(window).on("resize", function () {
247
+ layer.full(index);
248
+ });
249
+ }
250
+ });
251
+
252
+ });
253
+ </script>
254
+ <style>
255
+ .layui-table-tool-temp{
256
+ padding-right: 30px; !important;
257
+ }
258
+ </style>
@@ -77,10 +77,10 @@
77
77
  </div>
78
78
  </div>
79
79
  <br>
80
- <div class="layui-inline">
80
+ <div class="layui-inline place_select">
81
81
  <label class="layui-form-label">渠道</label>
82
- <div class="layui-input-inline">
83
- <%= select_tag "place_id", options_for_select(@places, @follow_up.place_id), include_blank: true %>
82
+ <div class="layui-input-inline" style="z-index: 101">
83
+ <div id="edit_place" style="width: 190px;"></div>
84
84
  </div>
85
85
  </div>
86
86
  <div class="layui-inline">
@@ -89,6 +89,15 @@
89
89
  <input name="divide_amount" class="layui-input" value="<%= @follow_up.divide_amount%>">
90
90
  </div>
91
91
  </div>
92
+ <div class="layui-form-item">
93
+ <div class="layui-inline">
94
+ <label class="layui-form-label required">所属年度</label>
95
+ <div class="layui-input-inline">
96
+ <input type="text" class="layui-input" name="year" lay-verify="required" autocomplete="off" id="edit_year"
97
+ value="<%= @follow_up&.year%>"
98
+ placeholder="请选择年度"> </div>
99
+ </div>
100
+ </div>
92
101
  <div class="layui-form-item">
93
102
  <label class="layui-form-label">指定跟进人</label>
94
103
  <div class="layui-input-inline">
@@ -141,6 +150,10 @@
141
150
  laydate.render({
142
151
  elem: '#invitation_at_edit'
143
152
  })
153
+ laydate.render({
154
+ elem: '#edit_year',
155
+ type: 'year'
156
+ })
144
157
 
145
158
  laydate.render({
146
159
  elem: '#reception_at_edit'
@@ -174,6 +187,49 @@
174
187
  }
175
188
  })
176
189
  sales_list.setValue(gon.sales)
190
+ var places_list = xmSelect.render({
191
+ el: '#edit_place',
192
+ remoteSearch: true,
193
+ clickClose: true,
194
+ model: {
195
+ icon: 'hidden',
196
+ label: {
197
+ type: 'text',
198
+ text: {
199
+ //左边拼接的字符
200
+ left: '',
201
+ //右边拼接的字符
202
+ right: '',
203
+ //中间的分隔符
204
+ separator: ', ',
205
+ },
206
+ }
207
+ },
208
+ delay: 1000,
209
+ radio: true,
210
+ paging: true,
211
+ pageRemote: true,
212
+ filterable: true,
213
+ remoteMethod: function (val, cb, show, pageIndex) {
214
+ $.ajax( '/missions/sales_place', {
215
+ method: 'get',
216
+ data: {
217
+ q: val,
218
+ page: pageIndex
219
+ },
220
+ dataType: 'json',
221
+ success: function (res) {
222
+ var data = res.data;
223
+ if (res.code == 0) {
224
+ cb(res.data, res.count);
225
+ } else {
226
+ layer.msg(res.msg, {time: 2000, icon: 2, shade: 0.01});
227
+ }
228
+ }
229
+ })
230
+ }
231
+ })
232
+ places_list.setValue(gon.place)
177
233
 
178
234
  form.render();
179
235
  form.on('submit(update_follow_up)', function (data) {
@@ -181,8 +237,9 @@
181
237
  sales_list.getValue().forEach(function(d) {
182
238
  assign_follow.push(d.value);
183
239
  })
184
- data.field.assign_follow_up = assign_follow;
185
- request.authPut("missions/follow_ups/<%= @follow_up.id%>", data.field, function (res) {
240
+ data.field.assign_follow_up = assign_follow;
241
+ data.field.place_id = places_list.getValue()[0].value;
242
+ request.authPut("missions/follow_ups/<%= @follow_up.id%>", data.field, function (res) {
186
243
  if (res.success == false) {
187
244
  layer.alert(res.msg)
188
245
  } else {
@@ -190,6 +247,7 @@
190
247
  parent.layer.close(parent.layer.getFrameIndex(window.name))
191
248
  parent.table.reload('sale_plan_follow_table')
192
249
  parent.table.reload('businesses_table')
250
+ parent.table.reload('teachers_table')
193
251
  }
194
252
  })
195
253
 
@@ -198,4 +256,9 @@
198
256
  });
199
257
 
200
258
  });
201
- </script>
259
+ </script>
260
+ <style>
261
+ .place_select xm-select > .xm-body{
262
+ width: 300px; !important;
263
+ }
264
+ </style>