educode_sales 1.10.48 → 1.10.58

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/educode_sales/modules/easyeditor/easyeditor.css +130 -0
  3. data/app/assets/stylesheets/educode_sales/modules/easyeditor/fangge-style.css +4 -0
  4. data/app/controllers/educode_sales/application_controller.rb +22 -0
  5. data/app/controllers/educode_sales/business_courses_controller.rb +255 -0
  6. data/app/controllers/educode_sales/businesses_controller.rb +43 -7
  7. data/app/controllers/educode_sales/contracts_controller.rb +6 -0
  8. data/app/controllers/educode_sales/home_controller.rb +7 -0
  9. data/app/controllers/educode_sales/money_plan_records_controller.rb +6 -2
  10. data/app/controllers/educode_sales/money_plans_controller.rb +3 -0
  11. data/app/controllers/educode_sales/sale_trends_controller.rb +1 -1
  12. data/app/controllers/educode_sales/shixun_dectects_controller.rb +172 -0
  13. data/app/controllers/educode_sales/shixuns_controller.rb +218 -0
  14. data/app/controllers/educode_sales/subject_trends_controller.rb +144 -0
  15. data/app/controllers/educode_sales/subjects_controller.rb +213 -0
  16. data/app/helpers/educode_sales/application_helper.rb +10 -0
  17. data/app/helpers/educode_sales/business_courses_helper.rb +60 -0
  18. data/app/helpers/educode_sales/sale_trends_helper.rb +52 -52
  19. data/app/helpers/educode_sales/subject_helper.rb +33 -0
  20. data/app/models/educode_sales/business.rb +22 -0
  21. data/app/models/educode_sales/business_deliver_subject.rb +49 -0
  22. data/app/models/educode_sales/business_subject.rb +68 -0
  23. data/app/models/educode_sales/business_subject_shixun.rb +75 -0
  24. data/app/models/educode_sales/business_subject_staff.rb +36 -0
  25. data/app/models/educode_sales/permission.rb +2 -1
  26. data/app/models/educode_sales/shixun_dectect.rb +12 -0
  27. data/app/views/educode_sales/business_courses/edit.html.erb +174 -0
  28. data/app/views/educode_sales/business_courses/index.html.erb +334 -0
  29. data/app/views/educode_sales/business_courses/index.json.jbuilder +16 -0
  30. data/app/views/educode_sales/business_courses/list_shixuns.html.erb +292 -0
  31. data/app/views/educode_sales/business_courses/list_shixuns.json.jbuilder +23 -0
  32. data/app/views/educode_sales/business_courses/list_subjects.html.erb +212 -0
  33. data/app/views/educode_sales/business_courses/list_subjects.json.jbuilder +17 -0
  34. data/app/views/educode_sales/business_courses/new.html.erb +237 -0
  35. data/app/views/educode_sales/businesses/index.html.erb +11 -9
  36. data/app/views/educode_sales/contracts/_list.html.erb +16 -1
  37. data/app/views/educode_sales/contracts/index.html.erb +5 -2
  38. data/app/views/educode_sales/contracts/list.js.erb +4 -1
  39. data/app/views/educode_sales/money_plan_records/_index.html.erb +21 -5
  40. data/app/views/educode_sales/money_plan_records/index.js.erb +4 -1
  41. data/app/views/educode_sales/money_plans/list.html.erb +6 -2
  42. data/app/views/educode_sales/sale_trends/_return_money_forecast.html.erb +1 -1
  43. data/app/views/educode_sales/sale_trends/_user_stat.html.erb +1 -1
  44. data/app/views/educode_sales/sale_trends/_visit_analysis.html.erb +1 -1
  45. data/app/views/educode_sales/sale_trends/return_money_forecast.js.erb +1 -1
  46. data/app/views/educode_sales/sale_trends/trends.html.erb +6 -6
  47. data/app/views/educode_sales/sale_trends/user_stat.js.erb +1 -1
  48. data/app/views/educode_sales/sale_trends/visit_analysis.js.erb +1 -1
  49. data/app/views/educode_sales/shixun_dectects/index.html.erb +516 -0
  50. data/app/views/educode_sales/shixun_dectects/index.json.jbuilder +23 -0
  51. data/app/views/educode_sales/shixun_dectects/markdown.html.erb +60 -0
  52. data/app/views/educode_sales/shixuns/edit.html.erb +208 -0
  53. data/app/views/educode_sales/shixuns/index.html.erb +723 -0
  54. data/app/views/educode_sales/shixuns/index.json.jbuilder +26 -0
  55. data/app/views/educode_sales/shixuns/new.html.erb +261 -0
  56. data/app/views/educode_sales/subject_trends/trends.html.erb +676 -0
  57. data/app/views/educode_sales/subjects/edit.html.erb +86 -0
  58. data/app/views/educode_sales/subjects/index.html.erb +285 -0
  59. data/app/views/educode_sales/subjects/index.json.jbuilder +16 -0
  60. data/app/views/educode_sales/subjects/list_shixuns.html.erb +354 -0
  61. data/app/views/educode_sales/subjects/list_shixuns.json.jbuilder +22 -0
  62. data/app/views/educode_sales/subjects/new.html.erb +254 -0
  63. data/app/views/layouts/educode_sales/application.html.erb +38 -0
  64. data/config/routes.rb +37 -0
  65. data/lib/educode_sales/version.rb +1 -1
  66. metadata +42 -7
  67. data/app/assets/images/educode_sales/indexlogo.png +0 -0
@@ -0,0 +1,49 @@
1
+ module EducodeSales
2
+ class BusinessDeliverSubject < ApplicationRecord
3
+ belongs_to :business
4
+ has_many :business_subjects, dependent: :destroy
5
+ has_many :subjects ,through: :business_subjects
6
+ has_many :manages, as: :container, dependent: :destroy, class_name: "EducodeSales::BusinessSubjectStaff"
7
+
8
+
9
+ # constructed:待建设, signed: 已签协议,construction: 建设中,completed: 已完成,delivered: 已交付, accepted: 已验收
10
+ enum status: { constructed:1, signed:2, construction: 3, completed:4, delivered: 5, accepted: 6 }
11
+
12
+ scope :undelivered, -> {where.not(status: "delivered")}
13
+ # 实践课程完成统计
14
+ def subject_competed_count
15
+ all_count = subjects.count
16
+ completed_count = subjects.where("subjects.status = 2 or subjects.public = 2").count
17
+
18
+ " #{completed_count} / #{all_count} "
19
+ end
20
+
21
+ # 实训项目完成进度
22
+ def shixun_competed_count
23
+ " #{business_subjects.joins(:business_subject_shixuns).where("educode_sales_business_subject_shixuns.shixun_status in (6,7,8)").count } / #{business_subjects.joins(:business_subject_shixuns).count} "
24
+ end
25
+
26
+ # 课程经理
27
+ def subject_manages
28
+ manages.joins(staff: :user).pluck("CONCAT(users.lastname, users.firstname) ").join(",") || "--"
29
+ end
30
+
31
+
32
+ def delvier_date
33
+ business.last_follow_up&.reception_at
34
+ end
35
+
36
+ def add_subjects(subject_ids = [])
37
+ subjects = Subject.where.not(id: BusinessSubject.joins(:business_deliver_subject).pluck(:subject_id)).unhidden # 1先创建实践项目下,通过实践课程无法选该实践项目
38
+ subject_ids.each do |item|
39
+ now_subject = subjects.find_by(id: item)
40
+ if now_subject.present?
41
+ add_item = BusinessSubject.find_or_create_by(subject_id: item)
42
+ add_item.update(business: business, business_deliver_subject_id: id)
43
+ end
44
+ end
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -0,0 +1,68 @@
1
+ module EducodeSales
2
+ class BusinessSubject < ApplicationRecord
3
+ belongs_to :business, optional: true
4
+ belongs_to :business_deliver_subject, optional: true
5
+ belongs_to :school, optional: true
6
+ belongs_to :subject, optional: true
7
+ has_many :business_subject_shixuns
8
+ has_many :staffs, ->{subject_staffs}, as: :container, dependent: :destroy, class_name: "EducodeSales::BusinessSubjectStaff"
9
+ has_many :manages, ->{subject_manges}, as: :container, dependent: :destroy, class_name: "EducodeSales::BusinessSubjectStaff"
10
+
11
+
12
+
13
+ # 销售名称
14
+ def staffs_name
15
+ staff_names = BusinessSubjectStaff.joins(staff: :user)
16
+ .where("educode_sales_business_subject_staffs.category = #{ BusinessSubjectStaff::CATEGORY_TYPES::SUBJECT_STAFF } and educode_sales_business_subject_staffs.container_id = #{self.id} and
17
+ educode_sales_business_subject_staffs.container_type = #{BusinessSubjectStaff::CONTAINER_TYPES::SUBJECT} ")
18
+ .pluck("DISTINCT CONCAT(users.lastname, users.firstname) ")
19
+ .join(",")
20
+ # staffs.joins(staff: :user).pluck("CONCAT(users.lastname, users.firstname) ").join(",")
21
+ staff_names
22
+ end
23
+
24
+ # 课程经理名称
25
+ def manges_name
26
+ manages.joins(staff: :user).pluck("CONCAT(users.lastname, users.firstname) ").join(",")
27
+ end
28
+
29
+ # 实训完成统计
30
+ def shixun_compeled_count
31
+ " #{business_subject_shixuns.where("educode_sales_business_subject_shixuns.shixun_status in (6,7,8)").count} / #{business_subject_shixuns.count}"
32
+ end
33
+
34
+ def school_name
35
+ school.try(:name)
36
+ end
37
+
38
+ # def deliver_date
39
+ # business ? business.last_follow_up.try(:reception_at)&.strftime("%Y-%m-%d") || "--" : deliver_date.strftime("%Y-%m-%d")
40
+ # end
41
+
42
+
43
+ # def b_name
44
+ # business ? business.name : '--'
45
+ # end
46
+
47
+ def staffs
48
+ business ? business.staff&.name : staffs_name
49
+ end
50
+
51
+ def manges
52
+ business_deliver_subject ? business_deliver_subject.subject_manages : manges_name
53
+ end
54
+
55
+
56
+ def add_subject_shixuns(shixun_ids=[]) # 1先创建实践项目下,通过实践课程无法选该实践项目
57
+ shixuns = Shixun.where.not(id: BusinessSubjectShixun.joins(:business_subject).pluck(:shixun_id)) # 1先创建实践项目下,通过实践课程无法选该实践项目
58
+ shixun_ids.each do |item|
59
+ now_shixun = shixuns.find_by(id: item)
60
+ if now_shixun.present?
61
+ add_item = BusinessSubjectShixun.create_with(name: now_shixun.name).find_or_create_by(shixun_id: item)
62
+ add_item.update(business_subject_id: self.id )
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ end
@@ -0,0 +1,75 @@
1
+ module EducodeSales
2
+ class BusinessSubjectShixun < ApplicationRecord
3
+
4
+ belongs_to :business_subject, optional: true
5
+ belongs_to :school, optional: true
6
+ belongs_to :shixun, optional: true
7
+ has_many :staffs, as: :container, dependent: :destroy, class_name: "EducodeSales::BusinessSubjectStaff"
8
+ has_many :shixun_members, as: :container, dependent: :destroy, class_name: "EducodeSales::BusinessSubjectStaff"
9
+ has_many :shixun_producer, ->{ shixun_producer }, as: :container, dependent: :destroy, class_name: "EducodeSales::BusinessSubjectStaff"
10
+ belongs_to :last_dectect, foreign_key: :shixun_dectect_id, class_name: "EducodeSales::ShixunDectect", optional: true
11
+
12
+ module CATEGORY_TYPE
13
+ TRAINING = 1 # 管培
14
+ WORKER = 2 # 全职
15
+ PLURALIST = 3 # 兼职
16
+ end
17
+
18
+ scope :search_type, ->(type) {where(shixun_type: type.to_i) if type.to_i != 0}
19
+ scope :search_level, ->(level) {where(level: level.to_i) if level.to_i != 0}
20
+ scope :search_status, ->(status) {where(shixun_status: status.to_i) if status.to_i != 0}
21
+ scope :search_category, ->(category) {where(category: category.to_i) if category.to_i != 0}
22
+ scope :training, -> {where(category: CATEGORY_TYPE::TRAINING)}
23
+ scope :worker, -> {where(category: CATEGORY_TYPE::WORKER)}
24
+ scope :pluralist, -> {where(category: CATEGORY_TYPE::PLURALIST)}
25
+ scope :completed, -> {where(shixun_status: [6,7,8])}
26
+ scope :un_completed, -> {where.not(shixun_status: [6,7,8])}
27
+ # 项目状态: 待建设(constructed) 已签协议(signed) 建设中(construction) 审核中(review),返修中(repair) 已内部公开(public), 已公开发布(published) 已经付费(paid)
28
+ # enum shixun_status: { constructed: 1, signed: 2, construction: 3, review: 4, repair: 5, public: 6, published: 7,paid: 8}
29
+
30
+ def shixun_manages
31
+ staffs.joins(staff: :user).where(category: BusinessSubjectStaff::CATEGORY_TYPES::SHIXUN_MANAGE).pluck("CONCAT(users.lastname, users.firstname) ").join(",")
32
+ end
33
+
34
+ def shixun_producer
35
+ staffs.joins(staff: :user).where(category: BusinessSubjectStaff::CATEGORY_TYPES::SHIXUN_PRODUCER).pluck("CONCAT(users.lastname, users.firstname) ").join(",")
36
+ end
37
+
38
+ def shixun_staff
39
+ staffs.joins(staff: :user).where(category: BusinessSubjectStaff::CATEGORY_TYPES::SHIXUN_STAFF).pluck("CONCAT(users.lastname, users.firstname) ").join(",")
40
+ end
41
+ def all_staff
42
+ staffs.joins(staff: :user).distinct.select("users.id")
43
+ end
44
+ def shixun_school
45
+ name = ""
46
+ shixuns = BusinessSubjectShixun.find(id)
47
+ if shixuns.school.present?
48
+ name = shixuns.school.name
49
+ end
50
+ if shixuns.business_subject.present?
51
+ if shixuns.business_subject.business.present?
52
+ name = shixuns.business_subject.business.school.name
53
+ end
54
+ end
55
+ p name
56
+ end
57
+
58
+ # 查询审核历史和审核人
59
+ def audit_history
60
+ ShixunDectect.joins("join educode_sales_staffs on educode_sales_staffs.id = educode_sales_shixun_dectects.reviewed_id
61
+ join users on users.id = educode_sales_staffs.user_id")
62
+ .where(business_subject_shixun_id: id)
63
+ .where("dectect_type != 0")
64
+ .select("educode_sales_shixun_dectects.*,
65
+ CONCAT(users.lastname, users.firstname) as examine_name")
66
+ .order("created_at desc")
67
+ .all
68
+ end
69
+
70
+ # def school_name
71
+ # business_subject ? business_subject.school_name : school.name
72
+ # end
73
+ end
74
+
75
+ end
@@ -0,0 +1,36 @@
1
+ module EducodeSales
2
+ class BusinessSubjectStaff < ApplicationRecord
3
+
4
+ belongs_to :staff
5
+ belongs_to :container, polymorphic: true, optional: true, touch: true
6
+
7
+
8
+ # 类型
9
+ enum container_type: { "EducodeSales::BusinessDeliverSubject": 1, "EducodeSales::BusinessSubject": 2, "EducodeSales::BusinessSubjectShixun": 3 }
10
+
11
+
12
+ # # 项目状态: 待建设(constructed) 已签协议(signed) 建设中(construction) 审核中(review),返修中(repair) 已内部公开(public), 已公开发布(published) 已经付费(paid)
13
+ # enum category_type: { constructed: 1, signed: 2, construction: 3, review: 4, repair: 5, public: 6, published: 7,paid: 8 }
14
+
15
+ module CONTAINER_TYPES
16
+ BUSSINESS = 1
17
+ SUBJECT = 2
18
+ SHIXUN = 3
19
+ end
20
+
21
+ module CATEGORY_TYPES
22
+ BUSINESS_MANAGE = 1 # 商机交付课程: 课程经理
23
+ SUBJECT_MANAGE = 2 # 实践课程管理: 课程经理
24
+ SUBJECT_STAFF = 3 # 实践课程管理: 销售
25
+ SHIXUN_MANAGE = 4 # 实训项目管理: 课程组长
26
+ SHIXUN_PRODUCER = 5 # 实训项目管理: 制作人
27
+ SHIXUN_STAFF = 6 # 实训项目管理: 销售
28
+ end
29
+
30
+ scope :subject_staffs, ->{where(category: CATEGORY_TYPES::SUBJECT_STAFF)}
31
+ scope :subject_manges, ->{where(category: CATEGORY_TYPES::SUBJECT_MANAGE)}
32
+ scope :shixun_producer, ->{where(category: CATEGORY_TYPES::SHIXUN_PRODUCER)}
33
+
34
+ end
35
+
36
+ end
@@ -17,7 +17,8 @@ module EducodeSales
17
17
  '方案管理': 'idea',
18
18
  '项目管理': 'project',
19
19
  '合同管理': 'contract',
20
- '产品目录': 'product_category'
20
+ '产品目录': 'product_category',
21
+ '课程管理': 'business_courses'
21
22
  }
22
23
  end
23
24
  end
@@ -0,0 +1,12 @@
1
+ module EducodeSales
2
+ class ShixunDectect < ApplicationRecord
3
+
4
+ belongs_to :business_subject_shixun
5
+ belongs_to :reviewed_staff, foreign_key: :reviewed_id, class_name: "EducodeSales::Staff"
6
+
7
+ # 状态: refused: 拒绝, agreed: 同意 review 审核中
8
+ enum dectect_type: {review:0, refused: 1, agreed: 2}
9
+
10
+ end
11
+
12
+ end
@@ -0,0 +1,174 @@
1
+ <%= Gon::Base.render_data %>
2
+ <form class="layui-form" action="" style="width: 90%;margin-top: 20px" lay-filter='test'>
3
+ <input style="display: none" value="<%=@item.id %>" name="id">
4
+ <div class="layui-form-item">
5
+ <label class="layui-form-label">商机名称:<span style="color: red"> *</span></label>
6
+ <div class="layui-input-block">
7
+ <input type="text" name="name"
8
+ lay-verify="required" disabled
9
+ value="<%= @item.name %>" class="layui-input"
10
+ style="width: 50%">
11
+ </div>
12
+ </div>
13
+ <div class="layui-form-item" >
14
+ <label class="layui-form-label" style="width: 112px">实践课程名称:<span style="color: red"> *</span></label>
15
+ <div class="layui-input-block">
16
+ <div id="subject_ids" style="width: 48%;margin-left: 20px"></div>
17
+ </div>
18
+ </div>
19
+
20
+ <div class="layui-form-item">
21
+ <label class="layui-form-label">交付状态:<span style="color: red"> *</span></label>
22
+ <div class="layui-input-block">
23
+ <div class="layui-col-md6" >
24
+ <%= select_tag "status", options_for_select(
25
+ [ ["待建设", "constructed"], ["已签协议", "signed"], ["建设中", "construction"],
26
+ ["已完成", "completed"], ["已交付", "delivered"], ["已验收", "accepted"]],
27
+ selected:@item.status
28
+ )%>
29
+ </div>
30
+ </div>
31
+ </div>
32
+ <div class="layui-form-item">
33
+ <label class="layui-form-label">课程经理:<span style="color: red"> *</span></label>
34
+ <div class="layui-input-block">
35
+ <div id="manage_id" style="width: 50%;"></div>
36
+ </div>
37
+ </div>
38
+
39
+ <div class="layui-form-item">
40
+ <label class="layui-form-label"></label>
41
+ <div class="layui-input-block">
42
+ <button class="layui-btn layui-btn-normal" lay-submit lay-filter="saveBtn">确认保存</button>
43
+ </div>
44
+ </div>
45
+ </form>
46
+ <script>
47
+ layui.use(['form', 'layer', 'laytpl', 'xmSelect', 'table'], function () {
48
+ var form = layui.form,
49
+ layer = layui.layer,
50
+ table = layui.table,
51
+ xmSelect = layui.xmSelect,
52
+ $ = layui.$
53
+
54
+
55
+ // 解决form表单中的select无法渲染的问题
56
+ form.render();
57
+ form.render('select' ,'test')
58
+ //科目ids
59
+ var subject_ids = xmSelect.render({
60
+ el: '#subject_ids',
61
+ name: "subject_ids",
62
+ remoteSearch: true,
63
+ autoRow: true,
64
+ delay: 1000,
65
+ tips: '- -',
66
+ searchTips: '支持名称搜索,请至少输入一个字符',
67
+ paging: true,
68
+ pageRemote: true,
69
+ filterable: true,
70
+ remoteMethod: function (val, cb, show, pageIndex) {
71
+ if (!val) {
72
+ return cb([]);
73
+ }
74
+ $.ajax('/missions/business_courses/subjects', {
75
+ method: 'get',
76
+ data: {
77
+ q: val,
78
+ page: pageIndex
79
+ },
80
+ dataType: 'json',
81
+ success: function (res) {
82
+ console.log(res)
83
+ var data = res.data;
84
+ if (res.code == 0) {
85
+ cb(res.data, res.count);
86
+ } else {
87
+ layer.msg(res.msg, {time: 2000, icon: 2, shade: 0.01});
88
+ }
89
+ }
90
+ })
91
+ }
92
+ })
93
+ //加载 如果商机已有实践课程
94
+ <% unless @subjects.blank? %>
95
+ var select_subject_ids = JSON.parse('<%=raw @subjects.to_json %>')
96
+ select_subject_ids.forEach((item)=>{
97
+ item.selected = true
98
+ })
99
+ subject_ids.update({
100
+ data:select_subject_ids
101
+ })
102
+ <% end %>
103
+ var manage_id = xmSelect.render({
104
+ el: '#manage_id',
105
+ name:'manage_id',
106
+ data: gon.staffs,
107
+ filterable: true,
108
+ paging: true,
109
+ tips: '- -',
110
+ multiple: true
111
+ })
112
+ <% if @value_list.present? %>
113
+ manage_id.setValue(<%=@value_list %>)
114
+ <% end %>
115
+
116
+ function isNull(str){
117
+ return str === "" || str === null
118
+ }
119
+
120
+ form.on('submit(saveBtn)', function (data) {
121
+
122
+ console.log(form.val())
123
+ let new_data = form.val();
124
+
125
+ if(isNull(new_data.business_id)){
126
+ layer.msg('请选商机');
127
+ return false
128
+ }
129
+ if(isNull(new_data.subject_ids)){
130
+ layer.msg('请选实践课程');
131
+ return false
132
+ }
133
+ if(isNull(new_data.manage_id)){
134
+ layer.msg('请选课堂经理');
135
+ return false
136
+ }
137
+ if(isNull(new_data.state)){
138
+ layer.msg('请选状态');
139
+ return false
140
+ }
141
+
142
+
143
+ var business = data.field
144
+ $.ajax('/missions/business_courses/'+business.id, {
145
+ method: 'PATCH',
146
+ data: {
147
+ business:business
148
+ },
149
+ dataType: 'json',
150
+ success: function (res) {
151
+ var data = res.data;
152
+ if (res.success) {
153
+ layer.closeAll();
154
+ table.reload('table', {
155
+ done: function () {
156
+ }
157
+ });
158
+ } else {
159
+ layer.msg(res.msg);
160
+ }
161
+ }
162
+ })
163
+
164
+
165
+
166
+ return false;
167
+ });
168
+ });
169
+ </script>
170
+ <style>
171
+ .input_width{
172
+ width: 50%;
173
+ }
174
+ </style>