educode_sales 0.9.67 → 0.9.69

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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/educode_sales/indexlogo.png +0 -0
  3. data/app/assets/javascripts/educode_sales/extent/treeTable.js +235 -0
  4. data/app/controllers/educode_sales/activities_controller.rb +52 -38
  5. data/app/controllers/educode_sales/businesses_controller.rb +1 -1
  6. data/app/controllers/educode_sales/customers_controller.rb +107 -0
  7. data/app/controllers/educode_sales/follow_ups_controller.rb +6 -0
  8. data/app/controllers/educode_sales/operation_plans_controller.rb +8 -4
  9. data/app/controllers/educode_sales/plans_controller.rb +173 -11
  10. data/app/controllers/educode_sales/projects_controller.rb +420 -0
  11. data/app/controllers/educode_sales/recycles_controller.rb +11 -1
  12. data/app/controllers/educode_sales/roles_controller.rb +4 -1
  13. data/app/controllers/educode_sales/teachers_controller.rb +42 -17
  14. data/app/controllers/educode_sales/upload_files_controller.rb +9 -2
  15. data/app/helpers/educode_sales/application_helper.rb +1 -0
  16. data/app/models/educode_sales/activity.rb +4 -0
  17. data/app/models/educode_sales/assessments_setting.rb +2 -2
  18. data/app/models/educode_sales/business.rb +21 -5
  19. data/app/models/educode_sales/business_history.rb +8 -0
  20. data/app/models/educode_sales/business_info.rb +9 -0
  21. data/app/models/educode_sales/permission.rb +2 -1
  22. data/app/models/educode_sales/project.rb +53 -0
  23. data/app/models/educode_sales/role_area.rb +2 -1
  24. data/app/models/educode_sales/sale_plan.rb +3 -1
  25. data/app/models/educode_sales/staff.rb +2 -0
  26. data/app/views/educode_sales/activities/_follows.html.erb +50 -36
  27. data/app/views/educode_sales/activities/_index.html.erb +82 -9
  28. data/app/views/educode_sales/activities/edit.html.erb +25 -68
  29. data/app/views/educode_sales/activities/files.html.erb +157 -0
  30. data/app/views/educode_sales/activities/files.json.jbuilder +13 -0
  31. data/app/views/educode_sales/activities/follow_ups.json.jbuilder +1 -1
  32. data/app/views/educode_sales/activities/index.json.jbuilder +2 -2
  33. data/app/views/educode_sales/activities/new.html.erb +21 -60
  34. data/app/views/educode_sales/activities/show_teachers.html.erb +1 -1
  35. data/app/views/educode_sales/activities/upload_file.html.erb +43 -0
  36. data/app/views/educode_sales/businesses/get_export_data.json.jbuilder +3 -0
  37. data/app/views/educode_sales/businesses/index.html.erb +5 -0
  38. data/app/views/educode_sales/businesses/index.json.jbuilder +3 -0
  39. data/app/views/educode_sales/businesses/new.html.erb +1 -1
  40. data/app/views/educode_sales/businesses/time_line.html.erb +9 -5
  41. data/app/views/educode_sales/customers/edit_major.html.erb +872 -0
  42. data/app/views/educode_sales/customers/list.html.erb +602 -0
  43. data/app/views/educode_sales/customers/list.json.jbuilder +33 -0
  44. data/app/views/educode_sales/follow_ups/index.json.jbuilder +2 -2
  45. data/app/views/educode_sales/plans/_yearPlan.html.erb +234 -0
  46. data/app/views/educode_sales/plans/business_infos.json.jbuilder +23 -0
  47. data/app/views/educode_sales/plans/edit_bussiness_info.html.erb +79 -0
  48. data/app/views/educode_sales/plans/edit_bussiness_info_extra.html.erb +260 -0
  49. data/app/views/educode_sales/plans/edit_year_plan.html.erb +237 -0
  50. data/app/views/educode_sales/plans/index.html.erb +8 -0
  51. data/app/views/educode_sales/plans/new_year.html.erb +204 -0
  52. data/app/views/educode_sales/plans/plan_business_infos.json.jbuilder +42 -0
  53. data/app/views/educode_sales/plans/years_plan.json.jbuilder +17 -0
  54. data/app/views/educode_sales/projects/detail.html.erb +269 -0
  55. data/app/views/educode_sales/projects/edit.html.erb +246 -0
  56. data/app/views/educode_sales/projects/history.html.erb +41 -0
  57. data/app/views/educode_sales/projects/index.html.erb +688 -0
  58. data/app/views/educode_sales/projects/index.json.jbuilder +69 -0
  59. data/app/views/educode_sales/recycles/_monthly.html.erb +1 -1
  60. data/app/views/educode_sales/recycles/_yearPlan.html.erb +118 -0
  61. data/app/views/educode_sales/recycles/index.html.erb +26 -22
  62. data/app/views/educode_sales/recycles/monthPlan.json.jbuilder +0 -1
  63. data/app/views/educode_sales/recycles/yearPlan.json.jbuilder +14 -0
  64. data/app/views/educode_sales/teachers/_index.html.erb +17 -1
  65. data/app/views/educode_sales/teachers/index.json.jbuilder +2 -0
  66. data/app/views/layouts/educode_sales/application.html.erb +25 -0
  67. data/config/routes.rb +31 -0
  68. data/db/migrate/20230330141213_create_educode_sales_activity_follow_ups.rb +6 -0
  69. data/db/migrate/20230405074036_add_year_to_sale_plans.rb +38 -0
  70. data/db/migrate/20230411134203_add_realname_to_teacher.rb +5 -0
  71. data/db/migrate/20230412083510_add_p_staff_id_to_businesses.rb +20 -0
  72. data/db/migrate/20230412092000_create_business_histories.rb +10 -0
  73. data/db/migrate/20230413015619_add_permissions_to_projects.rb +11 -0
  74. data/db/migrate/20230413031029_add_pre_time_to_businesses.rb +5 -0
  75. data/lib/educode_sales/version.rb +1 -1
  76. metadata +38 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5df645421c2aa112db563a37427dc4371924632bbca76efa21b74acec0911793
4
- data.tar.gz: bcc515a472ec5c92f66b9bb833dcfe4ca4e2330634df6bfb0b9b058501a90f90
3
+ metadata.gz: 5de22a63054e2a25d82a48c86687b07143302a4216d3690cb5431fcf17ca7672
4
+ data.tar.gz: b375afaa7854500c9bc3a7dbc6a8f83ef3c86e89bc9d5cf826280fde12102c98
5
5
  SHA512:
6
- metadata.gz: ee2b4439e08af8c4ca6810fc5fe5ef04d0d410c38a6bc32c8ca3bdcc0caea46e1ce3ac29b178c2c632f5edddd5190046f47e00605a1c33496e7e7a4c9aeb7c89
7
- data.tar.gz: 41c923fe3dd2dd68df2c141add67467fd52b1ffc5bc5ac36a010272cb38b75d1cab760f6e136b24d32c22642dee5f19f84da10c279d9b22d12eb728e4b66d4e9
6
+ metadata.gz: 015b587adf4090852c386117efff6d8fd7ea39a3a0bb6191d806cc96a68cb2c83e8cd487de8bcc7a221052fb4ebbe1eb0a67660865ddaadaf8746f4e309273f7
7
+ data.tar.gz: aae61faba2cf647fa61460ba958c89d761d8321a9eaa0bdc66855a8336bdc6552387f7d48f86fb9cd400a6e478ae58c7153e7311c5c85adc3de51f39a95fbc01
@@ -0,0 +1,235 @@
1
+ layui.define(['jquery'], function(exports) {
2
+ var MOD_NAME = 'treeTable',
3
+ o = layui.jquery,
4
+ tree = function() {};
5
+ tree.prototype.config = function() {
6
+ return {
7
+ top_value: 0,
8
+ primary_key: 'id',
9
+ parent_key: 'pid',
10
+ hide_class: 'layui-hide',
11
+ icon: {
12
+ open: 'layui-icon layui-icon-triangle-d',
13
+ close: 'layui-icon layui-icon-triangle-r',
14
+ left: 16,
15
+ },
16
+ cols: [],
17
+ checked: {},
18
+ is_click_icon: false,
19
+ is_checkbox: false,
20
+ is_cache: true,
21
+ };
22
+ }
23
+ tree.prototype.template = function(e) {
24
+ var t = this,
25
+ level = [],
26
+ tbody = '',
27
+ is_table = o('table' + e.elem).length || !(e.is_click_icon = true),
28
+ checkbox = e.is_checkbox ? '<div class="layui-unselect layui-form-checkbox cbx" lay-skin="primary"><i class="layui-icon layui-icon-ok"></i></div>' : '',
29
+ checked = checkbox ? checkbox.replace('cbx', 'cbx layui-form-checked') : '',
30
+ thead = checkbox && '<th style="width:28px;">' + (o.inArray(e.top_value, e.checked.data) > -1 ? checked : checkbox) + '</th>';
31
+ o.each(t.data(e, e.data), function(idx, item) {
32
+ var tr = '',
33
+ is_checked = false,
34
+ hide_class = (item[e.parent_key] == e.top_value) || (item[e.parent_key] == t.cache(e, item[e.parent_key])) ? '' : e.hide_class;
35
+ // 设置每行数据层级
36
+ item.level = level[item[e.primary_key]] = item[e.parent_key] != e.top_value ? (level[item[e.parent_key]] + 1) : 0;
37
+ // 设置是否为最后一级
38
+ item.is_end = !e.childs[item[e.primary_key]];
39
+ o.each(e.cols, function(index, obj) {
40
+ var style = '';
41
+ obj.width && (style += 'width:' + obj.width + ';'), obj.align && (style += 'text-align:' + obj.align + ';'), style && (style = 'style="' + style + '"');
42
+ // 标记设置行checkbox选中
43
+ if(e.is_checkbox && e.checked && o.inArray(item[e.checked.key], e.checked.data) > -1) {
44
+ is_checked = true;
45
+ }
46
+ // 第一次遍历头部的时候拼接表格头部
47
+ idx || (thead += '<th ' + style + '>' + obj.title + '</th>');
48
+ // 指定列加入开启、关闭小图标
49
+ var icon = (obj.key == e.icon_key && !item.is_end) ? '<i class="' + (t.cache(e, item[e.primary_key]) ? e.icon.open : e.icon.close) + '"></i>' : '<span></span>';
50
+ // 指定列小图标按照层级向后位移
51
+ var left = (obj.key == e.icon_key ? level[item[e.primary_key]] * e.icon.left + 'px' : '');
52
+ icon = icon.replace('>', ' style="margin-left:' + left + ';">');
53
+ // 拼接行
54
+ tr += '<td ' + style + (left ? 'data-down' : '') + '>' + icon + (is_table ? '' : (is_checked ? checked : checkbox)) + (obj.template ? obj.template(item) : item[obj.key]) + '</td>';
55
+ });
56
+ var box = is_table ? o(is_checked ? checked : checkbox).wrap('<td style="width:28px;">').parent().prop('outerHTML') : '';
57
+ tbody += '<tr class="' + hide_class + '" data-id="' + item[e.primary_key] + '" data-pid="' + item[e.parent_key] + '">' + box + tr + '</tr>';
58
+ });
59
+ // 处理表树和树的赋值模板
60
+ var table = is_table ? '<thead><tr data-id="' + e.top_value + '">' + thead + '</tr></thead><tbody>' + tbody + '</tbody>' : tbody.replace(/<tr/g, '<ul').replace(/tr>/g, 'ul>').replace(/<td/g, '<li').replace(/td>/g, 'li>');
61
+ // 确认点击图标或点击列触发展开关闭
62
+ var click_btn = e.is_click_icon ? '[data-down] i:not(.layui-icon-ok)' : '[data-down]';
63
+ // 模板渲染并处理点击展开收起等功能
64
+ o(e.elem).html(table).off('click', click_btn).on('click', click_btn, function() {
65
+ var tr = o(this).parents('[data-id]'),
66
+ td = tr.find('[data-down]'),
67
+ id = tr.data('id'),
68
+ pid = tr.data('pid'),
69
+ is_open = (td.find('i:not(.layui-icon-ok)').attr('class') == e.icon.close);
70
+ if(is_open) {
71
+ // 展开子级(子级出现、更改图标)
72
+ td.find('i:not(.layui-icon-ok)').attr('class', e.icon.open);
73
+ td.parents(e.elem).find('[data-pid=' + id + ']').removeClass(e.hide_class);
74
+ t.cache(e, id, true);
75
+ } else {
76
+ // 关闭子级(更改图标、隐藏所有子孙级)
77
+ td.find('i:not(.layui-icon-ok)').attr('class', e.icon.close);
78
+ t.childs_hide(e, id);
79
+ }
80
+ // 设置监听展开关闭
81
+ layui.event.call(this, MOD_NAME, 'tree(flex)', {
82
+ elem: this,
83
+ item: e.childs[pid][id],
84
+ table: e.elem,
85
+ is_open: is_open,
86
+ })
87
+ }).off('click', '.cbx').on('click', '.cbx', function() {
88
+ var is_checked = o(this).toggleClass('layui-form-checked').hasClass('layui-form-checked'),
89
+ tr = o(this).parents('[data-id]'),
90
+ id = tr.data('id'),
91
+ pid = tr.data('pid');
92
+ t.childs_checkbox(e, id, is_checked);
93
+ t.parents_checkbox(e, pid);
94
+ // 设置监听checkbox选择
95
+ layui.event.call(this, MOD_NAME, 'tree(box)', {
96
+ elem: this,
97
+ item: pid === undefined ? {} : e.childs[pid][id],
98
+ table: e.elem,
99
+ is_checked: is_checked,
100
+ })
101
+ }).off('click', '[lay-filter]').on('click', '[lay-filter]', function() {
102
+ var tr = o(this).parents('[data-id]'),
103
+ id = tr.data('id'),
104
+ pid = tr.data('pid'),
105
+ filter = o(this).attr("lay-filter");
106
+ return layui.event.call(this, MOD_NAME, 'tree(' + filter + ')', {
107
+ elem: this,
108
+ item: e.childs[pid][id],
109
+ })
110
+ });
111
+ e.end && e.end(e);
112
+ };
113
+ // 同级全部选中父级选中/同级全部取消取消父级
114
+ tree.prototype.parents_checkbox = function(e, pid) {
115
+ var po = o(e.elem).find('[data-pid=' + pid + ']'),
116
+ co = o(e.elem).find('[data-id=' + pid + ']'),
117
+ len = o(e.elem).find('[data-pid=' + pid + '] .cbx.layui-form-checked').length;
118
+ if(po.length == len || len == 0) {
119
+ var pid = co.data('pid');
120
+ len ? co.find('.cbx').addClass('layui-form-checked') : co.find('.cbx').removeClass('layui-form-checked');
121
+ pid === undefined || this.parents_checkbox(e, pid);
122
+ }
123
+ };
124
+ // 子级反选
125
+ tree.prototype.childs_checkbox = function(e, id, is_checked) {
126
+ var t = this;
127
+ o(e.elem).find('[data-pid=' + id + ']').each(function() {
128
+ var checkbox = o(this).find('.cbx');
129
+ is_checked ? checkbox.addClass('layui-form-checked') : checkbox.removeClass('layui-form-checked');
130
+ t.childs_checkbox(e, o(this).data('id'), is_checked);
131
+ })
132
+ };
133
+ // 点击收起循环隐藏子级元素
134
+ tree.prototype.childs_hide = function(e, id) {
135
+ var t = this;
136
+ t.cache(e, id, false);
137
+ o(e.elem).find('[data-pid=' + id + ']:not(.' + e.hide_class + ')').each(function() {
138
+ var td = o(this).find('[data-down]'),
139
+ i = td.find('i:not(.layui-icon-ok)');
140
+ // 关闭更换小图标
141
+ i.length && i.attr('class', e.icon.close);
142
+ // 隐藏子级
143
+ td.parents(e.elem).find('[data-pid=' + id + ']').addClass(e.hide_class);
144
+ t.childs_hide(e, o(this).data('id'))
145
+ });
146
+ };
147
+ // 重新组合数据,父子级关系跟随
148
+ tree.prototype.data = function(e) {
149
+ var lists = [],
150
+ childs = [];
151
+ o.each(e.data, function(idx, item) {
152
+ lists[item[e.primary_key]] = item;
153
+ if(!childs[item[e.parent_key]]) {
154
+ childs[item[e.parent_key]] = [];
155
+ }
156
+ childs[item[e.parent_key]][item[e.primary_key]] = item;
157
+ });
158
+ e.childs = childs;
159
+ return this.tree_data(e, lists, e.top_value, []);
160
+ };
161
+ tree.prototype.tree_data = function(e, lists, pid, data) {
162
+ var t = this;
163
+ if(lists[pid]) {
164
+ data.push(lists[pid]);
165
+ delete lists[pid]
166
+ }
167
+ o.each(e.data, function(index, item) {
168
+ if(item[e.parent_key] == pid) {
169
+ data.concat(t.tree_data(e, lists, item[e.primary_key], data))
170
+ }
171
+ });
172
+ return data;
173
+ };
174
+ tree.prototype.render = function(e) {
175
+ var t = this;
176
+ e = o.extend(t.config(), e);
177
+ if(e.url) {
178
+ o.get(e.url, function(res) {
179
+ e.data = res;
180
+ t.template(e);
181
+ })
182
+ } else {
183
+ t.template(e);
184
+ }
185
+ return e;
186
+ };
187
+ // 获取已选值集合
188
+ tree.prototype.checked = function(e) {
189
+ var ids = [];
190
+ o(e.elem).find('.cbx.layui-form-checked').each(function() {
191
+ var id = o(this).parents('[data-id]').data('id');
192
+ ids.push(id);
193
+ })
194
+ return ids;
195
+ };
196
+ // 全部展开
197
+ tree.prototype.openAll = function(e) {
198
+ var t = this;
199
+ o.each(e.data, function(idx, item) {
200
+ item[e.primary_key] && t.cache(e, item[e.primary_key], true);
201
+ })
202
+ t.render(e);
203
+ }
204
+ // 全部关闭
205
+ tree.prototype.closeAll = function(e) {
206
+ localStorage.setItem(e.elem.substr(1), '');
207
+ this.render(e);
208
+ }
209
+ tree.prototype.on = function(events, callback) {
210
+ return layui.onevent.call(this, MOD_NAME, events, callback)
211
+ };
212
+ // 存储折叠状态
213
+ tree.prototype.cache = function(e, val, option) {
214
+ if(!e.is_cache) {
215
+ return false;
216
+ }
217
+ var t = this,
218
+ name = e.elem.substr(1),
219
+ val = val.toString(),
220
+ cache = localStorage.getItem(name) ? localStorage.getItem(name).split(',') : [],
221
+ index = o.inArray(val, cache);
222
+ if(option === undefined) {
223
+ return index == -1 ? false : val
224
+ }
225
+ if(option && index == -1) {
226
+ cache.push(val)
227
+ }
228
+ if(!option && index > -1) {
229
+ cache.splice(index, 1)
230
+ }
231
+ localStorage.setItem(name, cache.join(','));
232
+ };
233
+ var tree = new tree();
234
+ exports(MOD_NAME, tree)
235
+ });
@@ -5,13 +5,17 @@ module EducodeSales
5
5
  def index
6
6
  respond_to do |format|
7
7
  format.html do
8
- @staffs = Staff.all.map { |d| [ d.user&.real_name, d.id ]}
8
+ common = Common.find_by(clazz: 'staff_type', name: '销售')
9
+ @staffs = Staff.joins(:user).where(job_type: common.id).where.not(role_id: 11).map { |d| [d.user.real_name, d.id]}
10
+
11
+ role = EducodeSales::Role.find_by(name: '生态经理')
12
+ @staff_manage = Staff.joins(:user).where(role_id: role.id).map { |d| [d.user.real_name, d.id]}
9
13
  end
10
14
  format.json do
11
15
  @activities = Activity
12
16
  if params[:q].present?
13
17
  if params[:q][:staff_id].present?
14
- @activities = @activities.where(staff_id: params[:q][:staff_id])
18
+ @activities = @activities.where(sales_id: params[:q][:staff_id])
15
19
  end
16
20
  if params[:q][:clazz_id].present?
17
21
  @activities = @activities.where(clazz_id: params[:q][:clazz_id])
@@ -56,8 +60,7 @@ module EducodeSales
56
60
  manage_ids = @activity.manages.pluck(:staff_id)
57
61
  assist_ids = @activity.assists.pluck(:staff_id)
58
62
  gon.staff_manage = Staff.all.map { |d| {name: d.user&.real_name, value: d.id, selected: manage_ids.include?(d.id)}}
59
- gon.assists = Staff.all.map { |d| {name: d.user&.real_name, value: d.id, selected: assist_ids.include?(d.id)}}
60
- gon.experts = @activity.experts.map { |d| {name: d.name, value: d.user_id || d.name, selected: true}}
63
+ gon.assistss = @activity.assists.map { |d| {name: d.name, value: d.user_id || d.name, selected: true}}
61
64
 
62
65
  gon.invitation_list = @activity.invitations.map { |d| {name: d.name, value: d.user_id || d.name, selected: true}}
63
66
 
@@ -74,15 +77,13 @@ module EducodeSales
74
77
  params[:staff_manage_id].each do |d|
75
78
  EducodeSales::ActivityStaff.create(staff_id: d, clazz_id: 'manage', activity_id: activity.id)
76
79
  end
80
+
77
81
  params[:staff_assist_id].each do |d|
78
- EducodeSales::ActivityStaff.create(staff_id: d, clazz_id: 'assist', activity_id: activity.id)
79
- end
80
- params[:expert_ids].each do |d|
81
82
  if d[0].to_i > 0
82
83
  u = User.find(d[0].to_i)
83
- EducodeSales::ActivityStaff.create(name: u.real_name, clazz_id: 'expert', user_id: d[0].to_i, activity_id: activity.id)
84
+ EducodeSales::ActivityStaff.create(name: u.real_name, clazz_id: 'assist', user_id: d[0].to_i, activity_id: activity.id)
84
85
  else
85
- EducodeSales::ActivityStaff.create(name: d[1], clazz_id: 'expert', activity_id: activity.id)
86
+ EducodeSales::ActivityStaff.create(name: d[1], clazz_id: 'assist', activity_id: activity.id)
86
87
  end
87
88
  end
88
89
  params[:invitation_ids].each do |d|
@@ -93,11 +94,6 @@ module EducodeSales
93
94
  EducodeSales::ActivityStaff.create(name: d[1], clazz_id: 'invitation', activity_id: activity.id)
94
95
  end
95
96
  end
96
- if params[:attachment_id].present?
97
- attachment = @current_admin.user.attachments.find(params[:attachment_id])
98
- attachment.container = activity
99
- attachment.save
100
- end
101
97
  render_success
102
98
  else
103
99
  render_failure activity
@@ -119,7 +115,6 @@ module EducodeSales
119
115
  sales_id: params[:sales_id] || @current_admin.id
120
116
  )
121
117
  manages = []
122
- experts = []
123
118
  assists = []
124
119
  invitations = []
125
120
  params[:staff_manage_id].each do |d|
@@ -127,14 +122,11 @@ module EducodeSales
127
122
  end
128
123
 
129
124
  params[:staff_assist_id].each do |d|
130
- assists << EducodeSales::ActivityStaff.find_or_initialize_by(staff_id: d, clazz_id: 'assist', activity_id: activity.id)
131
- end
132
- params[:expert_ids].each do |d|
133
125
  if d[0].to_i > 0
134
126
  u = User.find(d[0].to_i)
135
- experts << EducodeSales::ActivityStaff.find_or_initialize_by(name: u.real_name, clazz_id: 'expert', user_id: d[0].to_i, activity_id: activity.id)
127
+ assists << EducodeSales::ActivityStaff.find_or_initialize_by(name: u.real_name, clazz_id: 'assist', user_id: d[0].to_i, activity_id: activity.id)
136
128
  else
137
- experts << EducodeSales::ActivityStaff.find_or_initialize_by(name: d[1], clazz_id: 'expert', activity_id: activity.id)
129
+ assists << EducodeSales::ActivityStaff.find_or_initialize_by(name: d[1], clazz_id: 'assist', activity_id: activity.id)
138
130
  end
139
131
  end
140
132
  params[:invitation_ids].each do |d|
@@ -147,25 +139,8 @@ module EducodeSales
147
139
  end
148
140
  activity.manages = manages
149
141
  activity.assists = assists
150
- activity.experts = experts
151
142
  activity.invitations = invitations
152
-
153
- if params[:attachment_id].present?
154
- if activity.attachment&.id && activity.attachment&.id != params[:attachment_id].to_i
155
- file_path = File.join(Rails.root, "public", "files", 'educode_sales', activity.attachment.disk_filename)
156
- File.delete(file_path) if File.exist?(file_path)
157
- activity.attachment.destroy
158
- end
159
- attachment = @current_admin.user.attachments.find(params[:attachment_id])
160
- attachment.container = activity
161
- attachment.save
162
- else
163
- if activity.attachment
164
- file_path = File.join(Rails.root, "public", "files", 'educode_sales', activity.attachment.disk_filename)
165
- File.delete(file_path) if File.exist?(file_path)
166
- activity.attachment.destroy
167
- end
168
- end
143
+
169
144
  if activity.save
170
145
  render_success
171
146
  else
@@ -190,6 +165,10 @@ module EducodeSales
190
165
  render layout: false
191
166
  end
192
167
 
168
+ def upload_file
169
+ render layout: false
170
+ end
171
+
193
172
  def show_schools
194
173
  respond_to do |format|
195
174
  format.html do
@@ -231,6 +210,41 @@ module EducodeSales
231
210
  @data = @data.distinct.page(params[:page]).per(params[:limit])
232
211
  end
233
212
 
213
+ def update_advise
214
+ activity = Activity.find(params[:id])
215
+ if activity.last_follow_up
216
+ activity.last_follow_up.update(advise: params[:content])
217
+ render_success
218
+ else
219
+ render_failure '无跟进动态,暂不能添加建议'
220
+ end
221
+ end
222
+
223
+ def add_advise
224
+ followup = ActivityFollowUp.find(params[:id])
225
+ followup.update(advise: params[:content])
226
+ render_success
227
+ end
228
+
229
+
230
+ def files
231
+ respond_to do |format|
232
+ format.html do
233
+ render layout: false
234
+ end
235
+ format.json do
236
+ activity = Activity.find(params[:id])
237
+ @files = activity.attachments
238
+ if params[:sort].present? && params[:sort][:field]
239
+ @files = @files.order("#{params[:sort][:field]} #{params[:sort][:order]}")
240
+ else
241
+ @files = @files.order("created_on desc")
242
+ end
243
+ @files = @files.page(params[:page]).per(params[:limit])
244
+ end
245
+ end
246
+ end
247
+
234
248
  private
235
249
 
236
250
  def activity_params
@@ -395,7 +395,7 @@ module EducodeSales
395
395
 
396
396
  gon.levels = EducodeSales::BusinessLevel.level_ids.keys.map { |d| {name: d, value: d, selected: levels.include?(d)}}
397
397
  gon.watche_ids = Staff.all.map { |d| {name: d.user&.real_name, value: d.id, selected: staff_ids.include?(d.id)}}
398
- gon.department = {value: @business.department_id, name: "#{@business.department.school.name}-#{@business.department.name}"}
398
+ gon.department = {value: @business.department_id, name: "#{@business.department&.school&.name}-#{@business.department&.name}"}
399
399
  gon.value = @business.department_id
400
400
  render layout: false
401
401
  end
@@ -156,6 +156,97 @@ module EducodeSales
156
156
  end
157
157
  end
158
158
 
159
+ def list
160
+ authorize! :read, Customer
161
+ respond_to do |format|
162
+ format.html do
163
+ common = Common.find_by(clazz: 'staff_type', name: '销售')
164
+ @staffs = Staff.joins(:user).where(job_type: common.id).map { |d| [d.user.real_name, d.id] }
165
+ gon.school_tags = SchoolTag.where(for_missions: true).map { |d| {value: d.id, name: d.name } }
166
+ end
167
+ format.json do
168
+ if @current_admin.is_admin?
169
+ @customers = School.all
170
+ else
171
+ level = @current_admin.role.role_areas.find_by(clazz: '客户管理').level
172
+ case level
173
+ when '自己'
174
+ school_ids = CustomerExtension.where(customer_staff_id: @current_admin.id).pluck(:school_id)
175
+ @customers = School.where(id: school_ids)
176
+ when '区域'
177
+ a_school_ids = School.where(province: @current_admin.areas.pluck(:name)).ids
178
+ b_school_ids = CustomerExtension.where(customer_staff_id: @current_admin.id).pluck(:school_id)
179
+ school_ids = a_school_ids + b_school_ids + StaffSchool.where(staff_id: @current_admin.id).pluck(:school_id)
180
+ @customers = School.where(id: school_ids)
181
+ else
182
+ @customers = School.all
183
+ end
184
+ end
185
+
186
+ @customers = @customers.select("
187
+ schools.*,
188
+ departments.id AS department_id,
189
+ departments.name AS department_name,
190
+ department_majors.name AS major,
191
+ department_majors.id AS major_id
192
+ ")
193
+
194
+ @customers = @customers.joins("
195
+ LEFT JOIN departments ON schools.id = departments.school_id
196
+ LEFT JOIN department_majors ON department_majors.department_id = departments.id
197
+ ")
198
+ part_a_ids = CustomerFollow.all.pluck(:school_id)
199
+ part_b_ids = Business.where(id: EducodeSales::FollowUp.pluck(:business_id)).pluck(:school_id)
200
+ ids = part_a_ids + part_b_ids + CustomerAdd.all.pluck(:school_id)
201
+ @customers = @customers.where(id: ids)
202
+ if params[:q].present? && params[:q][:name].present?
203
+ @customers = @customers.where("schools.name like ?", "%#{params[:q][:name]}%")
204
+ end
205
+ if params[:q].present? && params[:q][:area].present?
206
+ @customers = @customers.where("schools.province = ?", "#{params[:q][:area]}")
207
+ end
208
+ if params[:q].present? && params[:q][:staff_id].present?
209
+ school_ids = EducodeSales::CustomerExtension.where(customer_staff_id: params[:q][:staff_id]).pluck(:school_id)
210
+ @customers = @customers.where(id: school_ids)
211
+ end
212
+ if params[:q].present? && params[:q][:property].present?
213
+ property = params[:q][:property].split(",").map(&:to_i)
214
+ @customers = @customers.joins(:school_tags).where("school_tags.id in (?)", property).distinct
215
+ end
216
+
217
+ if params[:q].present? && params[:q][:date].present?
218
+ ids = EducodeSales::CustomerFollow.all.pluck(:school_id)
219
+ @customers = @customers.where(id: ids)
220
+ school_ids = []
221
+ date = params[:q][:date].split(" - ")
222
+ @customers.each do |d|
223
+ business_ids = EducodeSales::Business.where(school_id: d.id).ids
224
+ follow_ups = EducodeSales::FollowUp.where(business_id: business_ids)
225
+ customer_follows = EducodeSales::CustomerFollow.where(school_id: d.id)
226
+ next if follow_ups.blank? && customer_follows.blank?
227
+ a_last_follow_time = follow_ups.last&.created_at&.to_s
228
+ b_last_follow_time = customer_follows.last&.created_at&.to_s
229
+ if a_last_follow_time.present? && b_last_follow_time.present?
230
+ last_follow_time = ((a_last_follow_time < b_last_follow_time) ? b_last_follow_time : a_last_follow_time)
231
+ else
232
+ last_follow_time = (a_last_follow_time || b_last_follow_time)
233
+ end
234
+ if last_follow_time.present? && last_follow_time > date[0] && last_follow_time < date[1]
235
+ school_ids << d.id
236
+ end
237
+ end
238
+ @customers = @customers.where(id: school_ids)
239
+ end
240
+
241
+ if params[:page].present?
242
+ @customers = @customers.order(id: :desc).page(params[:page]).per(params[:limit])
243
+ else
244
+ @customers = @customers.order(id: :desc)
245
+ end
246
+ end
247
+ end
248
+ end
249
+
159
250
  def update_major
160
251
  department = Department.find(params[:id])
161
252
  major = department.department_majors.find(params[:major_id])
@@ -256,6 +347,18 @@ module EducodeSales
256
347
  render layout: false
257
348
  end
258
349
 
350
+ def edit_major
351
+ @school = School.find(params[:id])
352
+ @school_property = @school.school_property
353
+ if params[:major].present?
354
+ @major = DepartmentMajor.find_by(id: params[:major])
355
+ end
356
+ if params[:department_id].present?
357
+ @department = Department.find_by(id: params[:department_id])
358
+ end
359
+ render layout: false
360
+ end
361
+
259
362
  def batch_update_school_tags
260
363
  xlsx = Roo::Spreadsheet.open(params[:file])
261
364
  ods = xlsx.sheet(0)
@@ -288,6 +391,10 @@ module EducodeSales
288
391
 
289
392
  def update
290
393
  @school = School.find(params[:id])
394
+ if params[:department_id].present?
395
+ department = @school.departments.find(params[:department_id]).update(name: params[:department])
396
+ end
397
+
291
398
  ActiveRecord::Base.transaction do
292
399
  property = SchoolProperty.find_or_create_by!(project_985: params[:project_985].present? ? 1 : 0,
293
400
  project_211: params[:project_211].present? ? 1 : 0,
@@ -257,6 +257,12 @@ module EducodeSales
257
257
  render_success
258
258
  end
259
259
 
260
+ def comment
261
+ followup = FollowUp.find(params[:id])
262
+ followup.update(comment: params[:comment])
263
+ render_success
264
+ end
265
+
260
266
  private
261
267
 
262
268
  def load_business
@@ -72,11 +72,15 @@ module EducodeSales
72
72
  def create
73
73
  plan = @current_admin.operation_plans.build(plan_params)
74
74
  plan.month = params["month"] + "-1"
75
- plan.teacher_id = @current_admin.teachers.find(params[:teacher_id]).id
76
- if plan.save
77
- render_success
75
+ if (Integer(params[:teacher_id]) rescue nil)
76
+ plan.teacher_id = @current_admin.teachers.find(params[:teacher_id]).id
77
+ if plan.save
78
+ render_success
79
+ else
80
+ render_failure plan
81
+ end
78
82
  else
79
- render_failure plan
83
+ render_failure '不存在该教师'
80
84
  end
81
85
  end
82
86