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
@@ -0,0 +1,237 @@
1
+
2
+ <div>
3
+ <table class="layui-hide" id="yearTable" lay-filter="yearTable"></table>
4
+ </div>
5
+
6
+
7
+ <script type="text/html" id="editYearTableBar">
8
+ <a class="layui-btn layui-btn-normal layui-btn-xs data-count-edit" lay-event="edit">编辑</a>
9
+ <a class="layui-btn layui-btn-danger layui-btn-xs data-count-delete" lay-event="delete">删除</a>
10
+ </script>
11
+ <script>
12
+ layui.use(['form', 'table', 'laytpl', 'request', 'laydate'], function () {
13
+ var form = layui.form,
14
+ layer = layui.layer,
15
+ table = layui.table,
16
+ request = layui.request,
17
+ laydate = layui.laydate,
18
+ $ = layui.$;
19
+
20
+ form.render();
21
+
22
+ form.on('submit(add_y_plan)', function (data) {
23
+ request.authPost("missions/plans/create_sales_plan", {}, function (res) {
24
+ table.reload('yearPlanTable');
25
+ layer.close(parent.yindex);
26
+ })
27
+ })
28
+
29
+ table.render({
30
+ elem: '#yearTable',
31
+ url: '/missions/plans/plan_business_infos?year=' + parent.year,
32
+ height: 400,
33
+ defaultToolbar: ['filter'],
34
+ initSort: {
35
+ field: 'created_at',
36
+ type: 'desc'
37
+ },
38
+ cols: [
39
+ [
40
+ {
41
+ field: 'id',
42
+ width: 60,
43
+ title:'序号',
44
+ type: 'numbers',
45
+ fixed: 'left'
46
+ },
47
+ {
48
+ field: 'business_name',
49
+ width: 160,
50
+ title: '商机名称',
51
+ },
52
+ {
53
+ field: 'school',
54
+ width: 150,
55
+ title: '单位'
56
+ },
57
+ {
58
+ field: 'department',
59
+ width: 150,
60
+ title: '二级部门'
61
+ },
62
+ {
63
+ field: 'stage',
64
+ width: 100,
65
+ title: '阶段',
66
+ },
67
+ {
68
+ field: 'staff_manages',
69
+ width: 100,
70
+ title: '销售经理',
71
+ },
72
+ {
73
+ field: 'created_at',
74
+ width: 180,
75
+ title: '创建时间',
76
+ },
77
+ {
78
+ field: 'sale_way',
79
+ width: 100,
80
+ title: '销售方式',
81
+ },
82
+ {
83
+ field: 'clazz',
84
+ width: 100,
85
+ title: '目标类型',
86
+ },
87
+ {
88
+ field: 'budget_amount',
89
+ width: 100,
90
+ title: '预算额',
91
+ },
92
+ {
93
+ field: 'plan_bid_on',
94
+ width: 170,
95
+ title: '计划投标时间',
96
+ },
97
+ {
98
+ field: 'actual_bidded_on',
99
+ width: 170,
100
+ title: '实际投标时间',
101
+ },
102
+ {
103
+ field: 'bidded_amount',
104
+ width: 170,
105
+ title: '中标额',
106
+ },
107
+ {
108
+ field: 'plan_sign_on',
109
+ width: 170,
110
+ title: '计划签单时间',
111
+ },
112
+ {
113
+ field: 'actual_sign_on',
114
+ width: 170,
115
+ title: '实际签单时间',
116
+ },
117
+ {
118
+ field: 'sign_amount',
119
+ width: 170,
120
+ title: '签单额',
121
+ },
122
+ {
123
+ field: 'plan_deploy_on',
124
+ width: 170,
125
+ title: '计划部署时间',
126
+ },
127
+ {
128
+ field: 'actual_deploy_on',
129
+ width: 170,
130
+ title: '实际部署时间',
131
+ },
132
+ {
133
+ field: 'plan_check_on',
134
+ width: 170,
135
+ title: '计划验收时间',
136
+ },
137
+ {
138
+ field: 'actual_check_on',
139
+ width: 170,
140
+ title: '实际验收时间',
141
+ },
142
+ {
143
+ field: 'prepayment_plan_on',
144
+ width: 170,
145
+ title: '预收款计划回款时间',
146
+ },
147
+ {
148
+ field: 'prepayment_actual_on',
149
+ width: 170,
150
+ title: '预收款实际回款时间',
151
+ },
152
+ {
153
+ field: 'prepayment_amount',
154
+ width: 170,
155
+ title: '预收款',
156
+ },
157
+ {
158
+ field: 'check_fee_plan_on',
159
+ width: 170,
160
+ title: '验收款计划回款时间',
161
+ },
162
+ {
163
+ field: 'check_fee_actual_on',
164
+ width: 170,
165
+ title: '验收款实际回款时间',
166
+ },
167
+ {
168
+ field: 'check_fee',
169
+ width: 170,
170
+ title: '验收款',
171
+ },
172
+ {
173
+ field: 'qa_plan_on',
174
+ width: 170,
175
+ title: '质保金计划回款时间',
176
+ },
177
+ {
178
+ field: 'qa_actual_on',
179
+ width: 170,
180
+ title: '质保金实际回款时间',
181
+ },
182
+ {
183
+ field: 'qa_amount',
184
+ width: 170,
185
+ title: '质保金',
186
+ },
187
+ {
188
+ field: 'account_receivable',
189
+ width: 170,
190
+ title: '应收款',
191
+ },
192
+ {
193
+ title: '操作',
194
+ minWidth: 200,
195
+ toolbar: '#editYearTableBar',
196
+ align: "center",
197
+ fixed: 'right'
198
+ }
199
+ ]
200
+ ],
201
+ limit: 20,
202
+ limits: [10,15,20,30,40,50,60,70,80,90],
203
+ page: true,
204
+ });
205
+
206
+ table.on('tool(yearTable)', function (obj) {
207
+ var data = obj.data;
208
+ id = data.id;
209
+ year = data.year;
210
+ if (obj.event === 'edit') {
211
+ content = miniPage.getHrefContent('/missions/plans/edit_bussiness_info_extra?id='+ id);
212
+ openWH = miniPage.getOpenWidthHeight();
213
+ sindex = layer.open({
214
+ title: '编辑',
215
+ type: 1,
216
+ shade: 0.2,
217
+ maxmin: true,
218
+ shadeClose: true,
219
+ area: [openWH[0] + 'px', openWH[1] + 'px'],
220
+ offset: [openWH[2] + 'px', openWH[3] + 'px'],
221
+ content: content
222
+ });
223
+ $(window).on("resize", function () {
224
+ layer.full(index);
225
+ });
226
+ return false;
227
+ } else if (obj.event === 'delete') {
228
+ layer.confirm('确定删除' + data.id, function (index) {
229
+ request.delete('missions/plans/' + data.id +'/delete_business_info', {}, function (res) {
230
+ layer.close(index);
231
+ table.reload("yearTable")
232
+ })
233
+ });
234
+ }
235
+ })
236
+ });
237
+ </script>
@@ -4,6 +4,7 @@
4
4
  <li data="weekly">周报</li>
5
5
  <li data="month">月计划</li>
6
6
  <li data="monthly">月报</li>
7
+ <li data="year">年计划</li>
7
8
  </ul>
8
9
  <div class="layui-tab-content">
9
10
  <div class="layui-tab-item layui-show">
@@ -18,6 +19,9 @@
18
19
  <div class="layui-tab-item">
19
20
  <%= render 'monthly' %>
20
21
  </div>
22
+ <div class="layui-tab-item">
23
+ <%= render 'yearPlan' %>
24
+ </div>
21
25
  </div>
22
26
  </div>
23
27
 
@@ -46,6 +50,10 @@
46
50
  $("#month_table_wraper .layui-table-fixed-r")[0].classList.remove('layui-hide');
47
51
  $("#month_table_wraper .layui-table-fixed-r .layui-table-body")[0].style.height="auto";
48
52
  break;
53
+ case 'year':
54
+ $("#year_table_wraper .layui-table-fixed-r")[0].classList.remove('layui-hide');
55
+ $("#year_table_wraper .layui-table-fixed-r .layui-table-body")[0].style.height="auto";
56
+ break;
49
57
  }
50
58
 
51
59
 
@@ -0,0 +1,204 @@
1
+ <div class="layui-form layuimini-form">
2
+ <div class="layui-form-item" style="padding: 25px">
3
+ <div class="layui-inline">
4
+ <label class="layui-form-label required">年份</label>
5
+ <div class="layui-input-inline">
6
+ <input type="text" lay-verify="required" class="layui-input" id="new_year_field" autocomplete="off" name="year">
7
+ </div>
8
+ </div>
9
+ <div class="layui-inline">
10
+ <label class="layui-form-label required">选择商机</label>
11
+ <div class="layui-input-inline" style="width: 400px">
12
+ <%= select_tag "business_id", options_for_select(@businesses), {"lay-verify": "required", include_blank: true} %>
13
+ </div>
14
+ </div>
15
+ <div class="layui-inline">
16
+ <label class="layui-form-label required">目标类型</label>
17
+ <div class="layui-input-inline" style="width: 150px">
18
+ <%= select_tag "clazz", options_for_select(@clazz), {"lay-verify": "required", include_blank: true} %>
19
+ </div>
20
+ </div>
21
+ <div class="layui-inline">
22
+ <div class="layui-input-inline">
23
+ <button type="submit" class="layui-btn layui-btn-normal" lay-submit lay-filter="add_year_plan">提交</button>
24
+ </div>
25
+ </div>
26
+ </div>
27
+ </div>
28
+
29
+ <div>
30
+ <table class="layui-hide" id="yearTable" lay-filter="yearTable"></table>
31
+ </div>
32
+ <div class="layui-form layuimini-form" style="text-align: center;margin-top:20px;">
33
+ <button type="submit" class="layui-btn layui-btn-normal" lay-submit lay-filter="add_y_plan">提交</button>
34
+ </div>
35
+
36
+ <script type="text/html" id="newYearTableBar">
37
+ <a class="layui-btn layui-btn-normal layui-btn-xs data-count-edit" lay-event="edit">编辑</a>
38
+ <a class="layui-btn layui-btn-danger layui-btn-xs data-count-delete" lay-event="delete">删除</a>
39
+ </script>
40
+ <script>
41
+ layui.use(['form', 'table', 'laytpl', 'request', 'laydate'], function () {
42
+ var form = layui.form,
43
+ layer = layui.layer,
44
+ table = layui.table,
45
+ request = layui.request,
46
+ laydate = layui.laydate,
47
+ $ = layui.$;
48
+ laydate.render({
49
+ elem: '#new_year_field',
50
+ type: 'year'
51
+ });
52
+ form.render();
53
+
54
+ var parentIndex = layer.index;
55
+
56
+ form.on('submit(add_year_plan)', function (data) {
57
+ request.authPost("missions/plans/create_business_info", data.field, function (res) {
58
+ if (res.success == false) {
59
+ layer.alert(res.msg)
60
+ } else {
61
+ console.log("resss", data.field)
62
+ table.reload('yearTable', {
63
+ where: data.field
64
+ })
65
+ }
66
+ })
67
+ return false;
68
+ });
69
+ form.on('submit(add_y_plan)', function (data) {
70
+ request.authPost("missions/plans/create_sales_plan", {}, function (res) {
71
+ table.reload('yearPlanTable');
72
+ layer.close(parent.yindex);
73
+ })
74
+ })
75
+
76
+ table.render({
77
+ elem: '#yearTable',
78
+ url: '/missions/plans/business_infos',
79
+ height: 400,
80
+ defaultToolbar: ['filter'],
81
+ initSort: {
82
+ field: 'created_at',
83
+ type: 'desc'
84
+ },
85
+ cols: [
86
+ [
87
+ {
88
+ field: 'id',
89
+ width: 60,
90
+ title:'序号',
91
+ type: 'numbers',
92
+ fixed: 'left'
93
+ },
94
+ {
95
+ field: 'business_name',
96
+ width: 160,
97
+ title: '商机名称',
98
+ },
99
+ {
100
+ field: 'school',
101
+ width: 150,
102
+ title: '单位'
103
+ },
104
+ {
105
+ field: 'department',
106
+ width: 150,
107
+ title: '二级部门'
108
+ },
109
+ {
110
+ field: 'stage',
111
+ width: 100,
112
+ title: '阶段',
113
+ },
114
+ {
115
+ field: 'staff_manages',
116
+ width: 100,
117
+ title: '销售经理',
118
+ },
119
+ {
120
+ field: 'created_at',
121
+ width: 180,
122
+ title: '创建时间',
123
+ },
124
+ {
125
+ field: 'sale_way',
126
+ width: 100,
127
+ title: '销售方式',
128
+ },
129
+ {
130
+ field: 'clazz',
131
+ width: 100,
132
+ title: '目标类型',
133
+ },
134
+ {
135
+ field: 'budget_amount',
136
+ width: 100,
137
+ title: '预算额',
138
+ },
139
+ {
140
+ field: 'plan_bid_on',
141
+ width: 170,
142
+ title: '计划投标时间',
143
+ },
144
+ {
145
+ field: 'plan_sign_on',
146
+ width: 170,
147
+ title: '计划签单时间',
148
+ },
149
+ {
150
+ field: 'prepayment_plan_on',
151
+ width: 170,
152
+ title: '计划回款时间',
153
+ },
154
+ {
155
+ field: 'prepayment_amount',
156
+ width: 170,
157
+ title: '计划回款额',
158
+ },
159
+ {
160
+ title: '操作',
161
+ minWidth: 200,
162
+ toolbar: '#newYearTableBar',
163
+ align: "center",
164
+ fixed: 'right'
165
+ }
166
+ ]
167
+ ],
168
+ limit: 20,
169
+ limits: [10,15,20,30,40,50,60,70,80,90],
170
+ page: true,
171
+ });
172
+
173
+ table.on('tool(yearTable)', function (obj) {
174
+ var data = obj.data;
175
+ id = data.id;
176
+ year = data.year;
177
+ if (obj.event === 'edit') {
178
+ content = miniPage.getHrefContent('/missions/plans/edit_bussiness_info?id='+ id);
179
+ openWH = miniPage.getOpenWidthHeight();
180
+ sindex = layer.open({
181
+ title: '编辑',
182
+ type: 1,
183
+ shade: 0.2,
184
+ maxmin: true,
185
+ shadeClose: true,
186
+ area: [openWH[0] + 'px', openWH[1] + 'px'],
187
+ offset: [openWH[2] + 'px', openWH[3] + 'px'],
188
+ content: content
189
+ });
190
+ $(window).on("resize", function () {
191
+ layer.full(index);
192
+ });
193
+ return false;
194
+ } else if (obj.event === 'delete') {
195
+ layer.confirm('确定删除' + data.business_name + data.clazz, function (index) {
196
+ request.delete('missions/plans/' + data.id +'/delete_business_info', {}, function (res) {
197
+ layer.close(index);
198
+ table.reload("yearTable")
199
+ })
200
+ });
201
+ }
202
+ })
203
+ });
204
+ </script>
@@ -0,0 +1,42 @@
1
+ json.data do
2
+ json.array! @data do |d|
3
+ json.id d.id
4
+ json.staff d.staff.user.real_name
5
+ json.clazz EducodeSales::SalePlan::CLAZZ_NAME.invert[d.clazz]
6
+ json.year d.year
7
+ json.business_name d.business.name
8
+ json.department d.business.department&.name
9
+ json.school d.business.department&.school&.name
10
+ json.stage d.business.last_follow_up&.stage&.name
11
+ json.staff_manages d.business.last_follow_up&.assign_follow_ups.present? ? (d.business.last_follow_up.assign_follow_ups.map{ |d| d.staff.user.real_name}.join("、")) : d.business.staff&.user&.real_name
12
+ json.created_at d.created_at.to_s
13
+ json.sale_way d.business.last_follow_up&.place&.name.present? ? '渠道' : '直销'
14
+ json.budget_amount d.business&.last_follow_up ? d.business.last_follow_up.budget_amount.to_f.round(2) : 0
15
+ json.plan_bid_on d.plan_bid_on
16
+ json.plan_sign_on d.plan_sign_on
17
+ json.bidded_amount d.bidded_amount
18
+ json.plan_sign_on d.plan_sign_on
19
+ json.actual_sign_on d.actual_sign_on
20
+ json.sign_amount d.sign_amount
21
+ json.plan_deploy_on d.plan_deploy_on
22
+ json.actual_deploy_on d.actual_deploy_on
23
+ json.plan_check_on d.plan_check_on
24
+ json.actual_check_on d.actual_check_on
25
+ json.prepayment_plan_on d.prepayment_plan_on
26
+ json.prepayment_actual_on d.prepayment_actual_on
27
+ json.prepayment_amount d.prepayment_amount
28
+ json.check_fee_plan_on d.check_fee_plan_on
29
+ json.check_fee_actual_on d.check_fee_actual_on
30
+ json.check_fee d.check_fee
31
+ json.qa_plan_on d.qa_plan_on
32
+ json.qa_actual_on d.qa_actual_on
33
+ json.qa_amount d.qa_amount
34
+ json.account_receivable d.account_receivable
35
+ json.account_receivable_clazz d.account_receivable_clazz
36
+ json.invoice_amount d.invoice_amount
37
+
38
+ end
39
+ end
40
+
41
+ json.code 0
42
+ json.count @data.total_count
@@ -0,0 +1,17 @@
1
+ json.data do
2
+ json.array! @sale_plans do |d|
3
+ json.id d.id
4
+ json.staff d.staff.user.real_name
5
+ json.clazz EducodeSales::SalePlan::CLAZZ_NAME.invert[d.clazz]
6
+ json.year d.year
7
+ json.target_money d['annual'] || 0
8
+ json.plan_money d['budget_amounts']&.round(2) || 0
9
+ json.minimum_money d['annual'].present? ? (d['annual'].to_f * 0.8).round(2) : 0
10
+ json.finish_money 0
11
+ json.finish_rate 0
12
+ json.updated_at d.updated_at.to_s
13
+ end
14
+ end
15
+
16
+ json.code 0
17
+ json.count @sale_plans.total_count