educode_sales 0.9.99 → 1.0.1
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.
- checksums.yaml +4 -4
- data/app/controllers/educode_sales/businesses_controller.rb +31 -25
- data/app/controllers/educode_sales/contracts_controller.rb +1 -1
- data/app/controllers/educode_sales/home_controller.rb +11 -5
- data/app/controllers/educode_sales/recycles_controller.rb +17 -1
- data/app/controllers/educode_sales/sale_trends_controller.rb +1 -1
- data/app/controllers/educode_sales/sales_details_controller.rb +8 -7
- data/app/helpers/educode_sales/sale_trends_helper.rb +4 -4
- data/app/models/educode_sales/business.rb +4 -4
- data/app/models/educode_sales/sales_detail.rb +1 -0
- data/app/models/educode_sales/user_stat_service.rb +81 -0
- data/app/views/educode_sales/businesses/edit.html.erb +71 -128
- data/app/views/educode_sales/businesses/search.json.jbuilder +2 -1
- data/app/views/educode_sales/contracts/new_sales_detail.html.erb +6 -0
- data/app/views/educode_sales/home/search_customer.json.jbuilder +7 -2
- data/app/views/educode_sales/recycles/_follow_up.html.erb +143 -0
- data/app/views/educode_sales/recycles/follow_up.json.jbuilder +21 -0
- data/app/views/educode_sales/recycles/index.html.erb +4 -0
- data/app/views/educode_sales/sale_trends/_user_stat.html.erb +0 -11
- data/app/views/educode_sales/sales_details/_index.html.erb +10 -1
- data/app/views/educode_sales/sales_details/index.json.jbuilder +2 -0
- data/config/routes.rb +2 -0
- data/db/migrate/20230523115007_add_proprietorship_educode_sales_sales_details.rb +18 -0
- data/lib/educode_sales/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a74ba09bc53597cf1bc110d4c32b29a405d7f4d25bb16287429327ac66799f49
|
4
|
+
data.tar.gz: 6a0969f7bb8afa5ea2e34670164d9fd81f45a7ca085d8987492d10643b91ca5e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d522ae7272dc2de4f6c9d766b0f813a1e0812d7f455e0ec6ffc228887feb4647962e679c231c0f4c06b18ec87c44e09be95b9d5a77ddcd8e5abb2440272277e5
|
7
|
+
data.tar.gz: 459678b2f2f085ad8eb877701637dbb8e52a72deb8fba6682ad1a99625cf0f26c276ff1fd8620342abb0d0a65c1b148220a9da56061076ce9cea61b071cf0477
|
@@ -429,31 +429,24 @@ module EducodeSales
|
|
429
429
|
gon.department = {value: @business.department_id, name: "#{@business.department&.school&.name}-#{@business.department&.name}"}
|
430
430
|
gon.value = @business.department_id
|
431
431
|
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
gon.
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
gon.place = [{value: @business.place_id, name: @business.place.name}]
|
444
|
-
gon.place_id = @business.place_id
|
445
|
-
else
|
446
|
-
gon.place = []
|
447
|
-
gon.place_id = ''
|
448
|
-
end
|
449
|
-
|
450
|
-
if @business.customer
|
451
|
-
gon.customer = [{value: @business.customer_id, name: "#{@business.customer.school.name} #{@business.customer.name}"}]
|
452
|
-
gon.customer_id = @business.customer_id
|
432
|
+
if ['会议活动', '渠道代理', '客户'].include?(@business.source_way) && @business.sourcable.present?
|
433
|
+
if @business.source_way == '客户'
|
434
|
+
gon.sourcable = [{name: "#{@business.sourcable.school.name} #{@business.sourcable.name}", value: @business.sourcable_id}]
|
435
|
+
else
|
436
|
+
gon.sourcable = [{name: @business.sourcable.name, value: @business.sourcable_id}]
|
437
|
+
end
|
438
|
+
|
439
|
+
gon.sourcable_id = @business.sourcable_id
|
440
|
+
elsif @business.sourcable_type.present?
|
441
|
+
gon.sourcable = [{value: @business.sourcable_type, name: @business.sourcable_type}]
|
442
|
+
gon.sourcable_id = @business.sourcable_type
|
453
443
|
else
|
454
|
-
gon.
|
455
|
-
gon.
|
444
|
+
gon.sourcable = []
|
445
|
+
gon.sourcable_id = ''
|
456
446
|
end
|
447
|
+
gon.sourcable_type = @business.sourcable_type
|
448
|
+
gon.source_way = @business.source_way
|
449
|
+
|
457
450
|
|
458
451
|
render layout: false
|
459
452
|
end
|
@@ -480,10 +473,23 @@ module EducodeSales
|
|
480
473
|
end
|
481
474
|
end
|
482
475
|
end
|
476
|
+
if params[:sourcable_type].present?
|
477
|
+
if params[:source_way] == '会议活动'
|
478
|
+
params[:sourcable_type] = 'EducodeSales::Activity'
|
479
|
+
elsif params[:source_way] == '渠道代理'
|
480
|
+
params[:sourcable_type] = 'EducodeSales::Place'
|
481
|
+
elsif params[:source_way] == '客户'
|
482
|
+
params[:sourcable_type] = 'EducodeSales::Department'
|
483
|
+
else
|
484
|
+
params[:sourcable_id] = ""
|
485
|
+
end
|
486
|
+
end
|
487
|
+
if params[:sourcable_type].blank?
|
488
|
+
params[:sourcable_id] = ""
|
489
|
+
end
|
483
490
|
|
484
491
|
if business.update(name: params[:name], department_id: department.id, source: params[:source], school_id: department.school_id,
|
485
|
-
|
486
|
-
company_source: params[:company_source], phone: params[:phone], email: params[:email], partner: params[:partner], invite_info: params[:invite_info], friend: params[:friend]
|
492
|
+
sourcable_type: params[:sourcable_type], sourcable_id: params[:sourcable_id], source_way: params[:source_way]
|
487
493
|
)
|
488
494
|
if params[:merge_business_ids].present?
|
489
495
|
merge_business = Business.where(id: params[:merge_business_ids].split(","))
|
@@ -514,7 +514,7 @@ module EducodeSales
|
|
514
514
|
end
|
515
515
|
|
516
516
|
def sales_detail_params
|
517
|
-
params.permit(:amount, :price, :total_price, :custom_clazz, :delivery_date, :product_catalog_id, :business_id)
|
517
|
+
params.permit(:amount, :price, :total_price, :custom_clazz, :delivery_date, :product_catalog_id, :business_id, :proprietorship)
|
518
518
|
end
|
519
519
|
|
520
520
|
end
|
@@ -98,11 +98,17 @@ module EducodeSales
|
|
98
98
|
end
|
99
99
|
|
100
100
|
def search_customer
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
101
|
+
if params[:type] == 'customer'
|
102
|
+
part_a_ids = EducodeSales::CustomerFollow.all.pluck(:school_id)
|
103
|
+
part_b_ids = EducodeSales::Business.pluck(:school_id)
|
104
|
+
school_ids = (part_a_ids + part_b_ids + EducodeSales::CustomerAdd.all.pluck(:school_id)).uniq
|
105
|
+
@data = Department.joins(:school).where("schools.name like ?", "%#{params[:q]}%").where("schools.id in (?)", school_ids).limit(20)
|
106
|
+
elsif params[:type] == 'active'
|
107
|
+
@data = Activity.where("name like ?", "%#{params[:q]}%").limit(20)
|
108
|
+
elsif params[:type] == 'place'
|
109
|
+
@data = EducodeSales::Place
|
110
|
+
@data = @data.where("name like :q", q: "%#{params[:q].strip}%").limit(20)
|
111
|
+
end
|
106
112
|
end
|
107
113
|
|
108
114
|
end
|
@@ -9,7 +9,13 @@ module EducodeSales
|
|
9
9
|
render_success
|
10
10
|
end
|
11
11
|
|
12
|
-
|
12
|
+
def restore_follow_up
|
13
|
+
@recycle = Recycle.find(params[:id])
|
14
|
+
report_id = @recycle.source_id
|
15
|
+
EducodeSales::FollowUp.unscoped.find(report_id).update(deleted_at: nil)
|
16
|
+
@recycle.destroy
|
17
|
+
render_success
|
18
|
+
end
|
13
19
|
|
14
20
|
def restore_reports
|
15
21
|
@recycle = Recycle.find(params[:id])
|
@@ -52,6 +58,16 @@ module EducodeSales
|
|
52
58
|
@businesses = @businesses.page(params[:page]).per(params[:limit])
|
53
59
|
end
|
54
60
|
|
61
|
+
def follow_up
|
62
|
+
@data = Recycle.where(source_type:"EducodeSales::FollowUp")
|
63
|
+
if params[:sort].present? && params[:sort][:field]
|
64
|
+
@data = @data.order("created_at #{params[:sort][:order]}")
|
65
|
+
else
|
66
|
+
@data = @data.order("educode_sales_recycles.created_at desc")
|
67
|
+
end
|
68
|
+
@data = @data.page(params[:page]).per(params[:limit])
|
69
|
+
end
|
70
|
+
|
55
71
|
def weekly
|
56
72
|
@weekly = Recycle.where(source_type:"EducodeSales::SaleReport").order(created_at: :desc).page(params[:page]).per(params[:limit])
|
57
73
|
if params[:sort].present? && params[:sort][:field]
|
@@ -138,14 +138,15 @@ module EducodeSales
|
|
138
138
|
rows.times do |r| #行数
|
139
139
|
next unless ods.row(r+2)[0]
|
140
140
|
business = EducodeSales::Business.find_by(number: ods.row(r+2)[0].to_s.strip)
|
141
|
-
product_catalog = EducodeSales::ProductCatalog.find_by(
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
141
|
+
product_catalog = EducodeSales::ProductCatalog.find_by(name: ods.row(r+2)[5].to_s.strip,
|
142
|
+
item_clazz: ods.row(r+2)[6].to_s.strip,
|
143
|
+
brand: ods.row(r+2)[7].to_s.strip,
|
144
|
+
specification: ods.row(r+2)[8].to_s.strip,
|
145
|
+
unit: ods.row(r+2)[9].to_s.strip,
|
146
|
+
source_method: ods.row(r+2)[13].to_s.strip,
|
147
|
+
supplier: ods.row(r+2)[15].to_s.strip)
|
147
148
|
if business.present? && product_catalog.present?
|
148
|
-
SalesDetail.create(staff_id: @current_admin.id, business_id: business.id, product_catalog_id: product_catalog.id, price: ods.row(r+2)[
|
149
|
+
SalesDetail.create(staff_id: @current_admin.id, business_id: business.id, product_catalog_id: product_catalog.id, price: ods.row(r+2)[11].to_s.strip, amount: ods.row(r+2)[10].to_s.strip, total_price: ods.row(r+2)[12].to_s.strip, custom_clazz: ods.row(r+2)[14].to_s.strip, delivery_date: ods.row(r+2)[16].to_s.strip, proprietorship: ods.row(r+2)[17].to_s.strip)
|
149
150
|
end
|
150
151
|
end
|
151
152
|
|
@@ -46,7 +46,7 @@ module EducodeSales
|
|
46
46
|
{
|
47
47
|
type: type,
|
48
48
|
label: select,
|
49
|
-
data: data,
|
49
|
+
data: data.map { |d| d.round(2)},
|
50
50
|
backgroundColor:
|
51
51
|
backgroundColor,
|
52
52
|
borderColor:
|
@@ -114,7 +114,7 @@ module EducodeSales
|
|
114
114
|
{
|
115
115
|
type: type,
|
116
116
|
label: select,
|
117
|
-
data: data,
|
117
|
+
data: data.map { |d| d.round(2)},
|
118
118
|
backgroundColor:
|
119
119
|
backgroundColor,
|
120
120
|
borderColor:
|
@@ -179,7 +179,7 @@ module EducodeSales
|
|
179
179
|
{
|
180
180
|
type: type,
|
181
181
|
label: select,
|
182
|
-
data: data,
|
182
|
+
data: data.map { |d| d.round(2)},
|
183
183
|
backgroundColor:
|
184
184
|
backgroundColor,
|
185
185
|
borderColor:
|
@@ -228,7 +228,7 @@ module EducodeSales
|
|
228
228
|
{
|
229
229
|
type: type,
|
230
230
|
label: select,
|
231
|
-
data: data,
|
231
|
+
data: data.map { |d| d.round(2)},
|
232
232
|
backgroundColor:
|
233
233
|
backgroundColor,
|
234
234
|
borderColor:
|
@@ -12,10 +12,6 @@ module EducodeSales
|
|
12
12
|
belongs_to :p_sale_staff, class_name: 'Staff', optional: true
|
13
13
|
belongs_to :p_deleter, class_name: 'Staff', optional: true
|
14
14
|
|
15
|
-
belongs_to :place, class_name: 'Place', optional: true
|
16
|
-
belongs_to :customer, class_name: 'Department', optional: true
|
17
|
-
belongs_to :activity, class_name: 'Activity', optional: true
|
18
|
-
|
19
15
|
has_many :sale_plans
|
20
16
|
has_many :follow_ups
|
21
17
|
has_many :business_clazz_changes
|
@@ -23,8 +19,12 @@ module EducodeSales
|
|
23
19
|
has_many :business_watches, dependent: :destroy
|
24
20
|
has_many :business_histories, dependent: :destroy
|
25
21
|
|
22
|
+
belongs_to :sourcable, :polymorphic => true, optional: true
|
23
|
+
|
26
24
|
has_many :assign_staffs, as: :sourcable, dependent: :destroy # 售后人员
|
27
25
|
|
26
|
+
enum source_way: ['会议活动', '公司资源', '400电话', '商务邮箱', '渠道代理', '合作伙伴', '招标信息', '客户', '朋友']
|
27
|
+
|
28
28
|
# 关联关注
|
29
29
|
has_many :users, :class_name => 'EducodeSales::BusinessRelationShip', foreign_key: 'business_id', :dependent => :destroy
|
30
30
|
|
@@ -109,6 +109,87 @@ module EducodeSales
|
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
112
|
+
def table_3
|
113
|
+
users = {'1' => [0, 0, 0], '2-5' => [0, 0, 0], '6-10' => [0, 0, 0], '11-20' => [0, 0, 0], '21-50' => [0, 0, 0], '51-100' => [0, 0, 0] }
|
114
|
+
signed_users = {'1' => [0, 0, 0], '2-5' => [0, 0, 0], '6-10' => [0, 0, 0], '11-20' => [0, 0, 0], '21-50' => [0, 0, 0], '51-100' => [0, 0, 0] }
|
115
|
+
schools(0).each do |d|
|
116
|
+
if d[1] == 1
|
117
|
+
users['1'][0] += 1
|
118
|
+
elsif d[1] <= 5
|
119
|
+
users['2-5'][0] += 1
|
120
|
+
elsif d[1] <= 10
|
121
|
+
users['6-10'][0] += 1
|
122
|
+
elsif d[1] <= 20
|
123
|
+
users['11-20'][0] += 1
|
124
|
+
elsif d[1] <= 50
|
125
|
+
users['21-50'][0] += 1
|
126
|
+
elsif d[1] <= 100
|
127
|
+
users['51-100'][0] += 1
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
departments(0).each do |d|
|
132
|
+
if d[1] == 1
|
133
|
+
users['1'][1] += 1
|
134
|
+
elsif d[1] <= 5
|
135
|
+
users['2-5'][1] += 1
|
136
|
+
elsif d[1] <= 10
|
137
|
+
users['6-10'][1] += 1
|
138
|
+
elsif d[1] <= 20
|
139
|
+
users['11-20'][1] += 1
|
140
|
+
elsif d[1] <= 50
|
141
|
+
users['21-50'][1] += 1
|
142
|
+
elsif d[1] <= 100
|
143
|
+
users['51-100'][1] += 1
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
signed_schools(0).each do |d|
|
148
|
+
if d[1] == 1
|
149
|
+
signed_users['1'][0] += 1
|
150
|
+
elsif d[1] <= 5
|
151
|
+
signed_users['2-5'][0] += 1
|
152
|
+
elsif d[1] <= 10
|
153
|
+
signed_users['6-10'][0] += 1
|
154
|
+
elsif d[1] <= 20
|
155
|
+
signed_users['11-20'][0] += 1
|
156
|
+
elsif d[1] <= 50
|
157
|
+
signed_users['21-50'][0] += 1
|
158
|
+
elsif d[1] <= 100
|
159
|
+
signed_users['51-100'][0] += 1
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
signed_departments(0).each do |d|
|
164
|
+
if d[1] == 1
|
165
|
+
signed_users['1'][1] += 1
|
166
|
+
elsif d[1] <= 5
|
167
|
+
signed_users['2-5'][1] += 1
|
168
|
+
elsif d[1] <= 10
|
169
|
+
p "----#{d}"
|
170
|
+
signed_users['6-10'][1] += 1
|
171
|
+
elsif d[1] <= 20
|
172
|
+
signed_users['11-20'][1] += 1
|
173
|
+
elsif d[1] <= 50
|
174
|
+
signed_users['21-50'][1] += 1
|
175
|
+
elsif d[1] <= 100
|
176
|
+
signed_users['51-100'][1] += 1
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
|
181
|
+
['1', '2-5', '6-10', '11-20', '21-50', '51-100'].map do |d|
|
182
|
+
{
|
183
|
+
'num' => d,
|
184
|
+
'schools' => users[d][0],
|
185
|
+
'departments' => users[d][1],
|
186
|
+
'majors' => 0,
|
187
|
+
'signed_schools' => signed_users[d][0],
|
188
|
+
'signed_departments' => signed_users[d][1],
|
189
|
+
'signed_majors' => 0,
|
190
|
+
}
|
191
|
+
end
|
192
|
+
end
|
112
193
|
|
113
194
|
def public_user
|
114
195
|
UserExtension.where(school_id: @school_ids).
|
@@ -17,67 +17,14 @@
|
|
17
17
|
<br>
|
18
18
|
<div class="layui-inline" style="padding-top: 20px">
|
19
19
|
<label class="layui-form-label required">商机来源</label>
|
20
|
-
<
|
21
|
-
|
22
|
-
<div class="layui-inline" style="padding-top: 20px">
|
23
|
-
<p style="padding-left: 40px">请填写提供本商机的人名(如‘张明’);如果为非头歌用户,请增加单位信息(如‘张明,华为公司’)</p>
|
24
|
-
</div>
|
25
|
-
<div class="layui-form-item" style="padding-top: 20px">
|
26
|
-
<label class="layui-form-label">会议活动</label>
|
27
|
-
<div class="layui-input-inline" style="line-height: 38px;">
|
28
|
-
<div id="activity" style="width: 300px"></div>
|
29
|
-
</div>
|
30
|
-
</div>
|
31
|
-
<div class="layui-form-item">
|
32
|
-
<label class="layui-form-label">渠道代理:</label>
|
33
|
-
<div class="layui-input-inline" style="line-height: 38px;">
|
34
|
-
<div id="place" style="width: 300px"></div>
|
35
|
-
</div>
|
36
|
-
</div>
|
37
|
-
<div class="layui-form-item">
|
38
|
-
<label class="layui-form-label">客户</label>
|
39
|
-
<div class="layui-input-inline" style="line-height: 38px;">
|
40
|
-
<div id="customer" style="width: 300px"></div>
|
41
|
-
</div>
|
42
|
-
</div>
|
43
|
-
<div class="layui-inline">
|
44
|
-
<label class="layui-form-label">公司资源</label>
|
45
|
-
<div class="layui-input-block">
|
46
|
-
<input type="text" name="company_source" autocomplete="off" class="layui-input" value="<%= @business.company_source %>">
|
47
|
-
</div>
|
48
|
-
</div>
|
49
|
-
<div class="layui-inline">
|
50
|
-
<label class="layui-form-label">400电话</label>
|
51
|
-
<div class="layui-input-block">
|
52
|
-
<input type="text" name="phone" autocomplete="off" class="layui-input" value="<%= @business.phone %>">
|
53
|
-
</div>
|
54
|
-
</div>
|
55
|
-
<div class="layui-inline">
|
56
|
-
<label class="layui-form-label">商务邮箱</label>
|
57
|
-
<div class="layui-input-block">
|
58
|
-
<input type="text" name="email" autocomplete="off" class="layui-input" value="<%= @business.email %>">
|
59
|
-
</div>
|
60
|
-
</div>
|
61
|
-
|
62
|
-
<div class="layui-inline">
|
63
|
-
<label class="layui-form-label">合作伙伴</label>
|
64
|
-
<div class="layui-input-block">
|
65
|
-
<input type="text" name="partner" autocomplete="off" class="layui-input" value="<%= @business.partner %>">
|
20
|
+
<div class="layui-inline">
|
21
|
+
<%= select_tag "source_way", options_for_select(EducodeSales::Business.source_ways.keys, @business.source_way), { include_blank: true, "lay-filter": 'source_id', "lay-verify": "required" } %>
|
66
22
|
</div>
|
67
|
-
|
68
|
-
|
69
|
-
<label class="layui-form-label">招标信息</label>
|
70
|
-
<div class="layui-input-block">
|
71
|
-
<input type="text" name="invite_info" autocomplete="off" class="layui-input" value="<%= @business.invite_info %>">
|
23
|
+
<div class="layui-inline" style="line-height: 38px;" id="source_wraper">
|
24
|
+
<div id="customer_id" style="width: 360px"></div>
|
72
25
|
</div>
|
73
26
|
</div>
|
74
27
|
|
75
|
-
<div class="layui-inline">
|
76
|
-
<label class="layui-form-label">朋友</label>
|
77
|
-
<div class="layui-input-block">
|
78
|
-
<input type="text" name="friend" autocomplete="off" class="layui-input" value="<%= @business.friend %>">
|
79
|
-
</div>
|
80
|
-
</div>
|
81
28
|
<% if can?(:merge_business, EducodeSales::Business) %>
|
82
29
|
<div class="layui-inline-block" style="padding-top: 20px">
|
83
30
|
<label class="layui-form-label ">合并商机</label>
|
@@ -149,6 +96,46 @@
|
|
149
96
|
if (gon.is_secret) {
|
150
97
|
$("#watch_ids_wraper").removeClass("layui-hide")
|
151
98
|
}
|
99
|
+
var source_way = gon.source_way;
|
100
|
+
form.on('select(source_id)', function(data){
|
101
|
+
source_way = data.value;
|
102
|
+
setSourceWay(data.value);
|
103
|
+
$("#" + customer_select._input)[0].value = "";
|
104
|
+
});
|
105
|
+
|
106
|
+
|
107
|
+
function setSourceWay(value) {
|
108
|
+
if (value == '400电话' || value == '商务邮箱') {
|
109
|
+
$("#source_wraper").hide()
|
110
|
+
} else {
|
111
|
+
$("#source_wraper").show()
|
112
|
+
var text = "";
|
113
|
+
switch (value) {
|
114
|
+
case '会议活动':
|
115
|
+
text = "请选择活动运营";
|
116
|
+
break;
|
117
|
+
case '公司资源':
|
118
|
+
text = "请填写公司领导、部门其他同事姓名";
|
119
|
+
break;
|
120
|
+
case '渠道代理':
|
121
|
+
text = "请选择渠道";
|
122
|
+
break;
|
123
|
+
case '合作伙伴':
|
124
|
+
text = "请填写合作伙伴公司名称";
|
125
|
+
break;
|
126
|
+
case '招标信息':
|
127
|
+
text = "请填写招标信息";
|
128
|
+
break;
|
129
|
+
case '客户':
|
130
|
+
text = "请选择客户";
|
131
|
+
break;
|
132
|
+
case '朋友':
|
133
|
+
text = "请填写姓名";
|
134
|
+
break;
|
135
|
+
}
|
136
|
+
$("#" + customer_select._input)[0].placeholder = text;
|
137
|
+
}
|
138
|
+
}
|
152
139
|
|
153
140
|
form.render();
|
154
141
|
var department_id = gon.value;
|
@@ -172,6 +159,7 @@
|
|
172
159
|
request.get('missions/search?type=department&q=' + value, {}, function (res) {
|
173
160
|
return cb(res)
|
174
161
|
})
|
162
|
+
|
175
163
|
}
|
176
164
|
});
|
177
165
|
|
@@ -189,90 +177,47 @@
|
|
189
177
|
data: []
|
190
178
|
})
|
191
179
|
|
192
|
-
var activity_id = gon.activity_id;
|
193
|
-
var activity_select = selectInput.render({
|
194
|
-
elem: '#activity',
|
195
|
-
name: 'activity_id', // 渲染的input的name值
|
196
|
-
layFilter: 'test', //同layui form参数lay-filter
|
197
|
-
// layVerify: 'required', //同layui form参数lay-verify
|
198
|
-
layVerType: 'tips', // 同layui form参数lay-verType
|
199
|
-
layReqText: '请填写文本', //同layui form参数lay-ReqText
|
200
|
-
initValue: gon.activity_id, // 渲染初始化默认值
|
201
|
-
hasSelectIcon: false,
|
202
|
-
placeholder: '请输入会议活动', // 渲染的inputplaceholder值
|
203
|
-
data: gon.activity,
|
204
|
-
remoteSearch: true, // 是否启用远程搜索 默认是false,和远程搜索回调保存同步
|
205
|
-
remoteMethod: function (value, cb) { // 远程搜索的回调函数
|
206
|
-
if (!value) {
|
207
|
-
activity_id = "";
|
208
|
-
return cb([]);
|
209
|
-
}
|
210
|
-
request.get('missions/search_activity?q=' + value, {}, function (res) {
|
211
|
-
if (res.data.length == 0) {
|
212
|
-
activity_select.emptyValue();
|
213
|
-
return cb([])
|
214
|
-
}
|
215
|
-
return cb(res)
|
216
|
-
})
|
217
|
-
}
|
218
|
-
});
|
219
180
|
|
220
|
-
|
221
|
-
var place_select = selectInput.render({
|
222
|
-
elem: '#place',
|
223
|
-
name: 'place_id', // 渲染的input的name值
|
224
|
-
layFilter: 'test', //同layui form参数lay-filter
|
225
|
-
// layVerify: 'required', //同layui form参数lay-verify
|
226
|
-
layVerType: 'tips', // 同layui form参数lay-verType
|
227
|
-
layReqText: '请填写文本', //同layui form参数lay-ReqText
|
228
|
-
initValue: gon.place_id, // 渲染初始化默认值
|
229
|
-
hasSelectIcon: false,
|
230
|
-
placeholder: '请输入渠道代理', // 渲染的inputplaceholder值
|
231
|
-
data: gon.place,
|
232
|
-
remoteSearch: true, // 是否启用远程搜索 默认是false,和远程搜索回调保存同步
|
233
|
-
remoteMethod: function (value, cb) { // 远程搜索的回调函数
|
234
|
-
if (!value) {
|
235
|
-
place_id = "";
|
236
|
-
return cb([]);
|
237
|
-
}
|
238
|
-
request.get('missions/sales_place?q=' + value, {}, function (res) {
|
239
|
-
if (res.data.length == 0) {
|
240
|
-
place_select.emptyValue();
|
241
|
-
return cb([])
|
242
|
-
}
|
243
|
-
return cb(res)
|
244
|
-
})
|
245
|
-
}
|
246
|
-
});
|
247
|
-
|
248
|
-
var customer_id = gon.customer_id;
|
181
|
+
var sourcable_id = gon.sourcable_id;
|
249
182
|
var customer_select = selectInput.render({
|
250
|
-
elem: '#
|
251
|
-
name: '
|
183
|
+
elem: '#customer_id',
|
184
|
+
name: 'sourcable_type', // 渲染的input的name值
|
252
185
|
layFilter: 'test', //同layui form参数lay-filter
|
253
186
|
// layVerify: 'required', //同layui form参数lay-verify
|
254
187
|
layVerType: 'tips', // 同layui form参数lay-verType
|
255
188
|
layReqText: '请填写文本', //同layui form参数lay-ReqText
|
256
|
-
initValue: gon.
|
189
|
+
initValue: gon.sourcable_id, // 渲染初始化默认值
|
257
190
|
hasSelectIcon: false,
|
258
|
-
placeholder: '
|
259
|
-
data: gon.
|
191
|
+
placeholder: '请输入商机来源', // 渲染的inputplaceholder值
|
192
|
+
data: gon.sourcable,
|
260
193
|
remoteSearch: true, // 是否启用远程搜索 默认是false,和远程搜索回调保存同步
|
261
194
|
remoteMethod: function (value, cb) { // 远程搜索的回调函数
|
262
195
|
if (!value) {
|
263
|
-
|
196
|
+
sourcable_id = "";
|
264
197
|
return cb([]);
|
265
198
|
}
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
199
|
+
if (['会议活动', '渠道代理', '客户'].includes(source_way)) {
|
200
|
+
var type = "";
|
201
|
+
if (source_way == '客户') {
|
202
|
+
type = 'customer';
|
203
|
+
} else if (source_way == '渠道代理') {
|
204
|
+
type = 'place';
|
205
|
+
} else if (source_way == '会议活动') {
|
206
|
+
type = 'active';
|
270
207
|
}
|
271
|
-
|
272
|
-
|
208
|
+
request.get('missions/search_customer?q=' + value + "&type=" + type, {}, function (res) {
|
209
|
+
if (res.data.length == 0) {
|
210
|
+
customer_select.emptyValue();
|
211
|
+
return cb([])
|
212
|
+
}
|
213
|
+
return cb(res)
|
214
|
+
})
|
215
|
+
}
|
273
216
|
}
|
274
217
|
});
|
275
218
|
|
219
|
+
setSourceWay(source_way);
|
220
|
+
|
276
221
|
// 当前弹出层,防止ID被覆盖
|
277
222
|
var parentIndex = layer.index;
|
278
223
|
|
@@ -285,9 +230,7 @@
|
|
285
230
|
var field = data.field;
|
286
231
|
field.department_id = department.getValue() || department_id;
|
287
232
|
field.merge_business_ids = data.field.merge_business_ids;
|
288
|
-
field.
|
289
|
-
field.place_id = place_select.getValue() || place_id;
|
290
|
-
field.customer_id = customer_select.getValue() || customer_id;
|
233
|
+
field.sourcable_id = customer_select.getValue() || sourcable_id;
|
291
234
|
request.authPut("missions/businesses/" + parent.id, field, function (res) {
|
292
235
|
if (res.success == false) {
|
293
236
|
layer.alert(res.msg)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
json.data do
|
2
2
|
json.array! @business do |d|
|
3
3
|
json.value d.id
|
4
|
-
|
4
|
+
staff_manage = d.last_follow_up&.assign_follow_ups.present? ? (d.last_follow_up.assign_follow_ups.map{ |d| d.staff.user.real_name}.join("、")) : d.staff&.user&.real_name
|
5
|
+
json.name d.name + " " + staff_manage + " " + d.created_at.to_s
|
5
6
|
end
|
6
7
|
end
|
@@ -44,6 +44,12 @@
|
|
44
44
|
<input type="text" name="delivery_date" value="" class="layui-input" lay-verify="required" id="delivery_date">
|
45
45
|
</div>
|
46
46
|
</div>
|
47
|
+
<div class="layui-inline">
|
48
|
+
<label class="layui-form-label required">知识产权归属:</label>
|
49
|
+
<div class="layui-input-inline">
|
50
|
+
<%= select_tag "proprietorship", options_for_select(EducodeSales::SalesDetail.proprietorships.keys), { 'lay-filter': 'proprietorship', 'lay-verify': "required", include_blank: true, "lay-search": "" } %>
|
51
|
+
</div>
|
52
|
+
</div>
|
47
53
|
</div>
|
48
54
|
<div class="layui-form-item">
|
49
55
|
<div class="layui-input-block">
|
@@ -1,7 +1,12 @@
|
|
1
1
|
json.data do
|
2
2
|
json.array! @data do |d|
|
3
|
-
|
4
|
-
|
3
|
+
if params[:type] == 'customer'
|
4
|
+
json.value d.id
|
5
|
+
json.name "#{d.school.name} #{d.name}"
|
6
|
+
else
|
7
|
+
json.value d.id
|
8
|
+
json.name d.name
|
9
|
+
end
|
5
10
|
end
|
6
11
|
end
|
7
12
|
json.code 0
|
@@ -0,0 +1,143 @@
|
|
1
|
+
<script type="text/html" id="toolbarfollowup">
|
2
|
+
<div class="layui-btn-container">
|
3
|
+
<span class="table-label">商机跟进列表</span>
|
4
|
+
</div>
|
5
|
+
</script>
|
6
|
+
|
7
|
+
<table class="layui-hide" id="follow_up" lay-filter="follow_up"></table>
|
8
|
+
|
9
|
+
<script type="text/html" id="currentTable_followup">
|
10
|
+
<%# if can? :update, EducodeSales::business %>
|
11
|
+
<a class="layui-btn layui-btn-normal layui-btn-xs data-count-edit" lay-event="restore">还原</a>
|
12
|
+
<%# end %>
|
13
|
+
<%# if can? :destroy, EducodeSales::business %>
|
14
|
+
<a class="layui-btn layui-btn-xs layui-btn-danger data-count-delete" lay-event="delete">删除</a>
|
15
|
+
<%# end %>
|
16
|
+
</script>
|
17
|
+
|
18
|
+
<script type="text/html" id="showchance">
|
19
|
+
<a href="/missions/businesses" class="layui-table-link">{{ d.chance }}</a>
|
20
|
+
</script>
|
21
|
+
|
22
|
+
<script>
|
23
|
+
layui.use(['form', 'table', 'miniPage', 'element', 'request'], function () {
|
24
|
+
var $ = layui.jquery,
|
25
|
+
form = layui.form,
|
26
|
+
table = layui.table,
|
27
|
+
request = layui.request,
|
28
|
+
miniPage = layui.miniPage;
|
29
|
+
|
30
|
+
table.render({
|
31
|
+
elem: '#follow_up',
|
32
|
+
url: '/missions/recycles/follow_up',
|
33
|
+
toolbar: '#toolbarfollowup',
|
34
|
+
totalRow:true,
|
35
|
+
defaultToolbar: [],
|
36
|
+
cols: [
|
37
|
+
[
|
38
|
+
{
|
39
|
+
field: 'id',
|
40
|
+
title:'序号',type: 'numbers',
|
41
|
+
},
|
42
|
+
{
|
43
|
+
field: 'name',
|
44
|
+
width: 180,
|
45
|
+
title: '商机名称'
|
46
|
+
},
|
47
|
+
{
|
48
|
+
field: 'follow_up_content',
|
49
|
+
width: 180,
|
50
|
+
title: '内容'
|
51
|
+
},
|
52
|
+
{
|
53
|
+
field: 'clazz',
|
54
|
+
title: '商机类型'
|
55
|
+
},
|
56
|
+
{
|
57
|
+
field: 'stage',
|
58
|
+
title: '阶段'
|
59
|
+
},
|
60
|
+
{
|
61
|
+
field: 'staff_manages',
|
62
|
+
width: 150,
|
63
|
+
title: '销售经理'
|
64
|
+
},
|
65
|
+
{
|
66
|
+
field: 'school',
|
67
|
+
title: '单位'
|
68
|
+
},
|
69
|
+
{
|
70
|
+
field: 'department',
|
71
|
+
title: '部门'
|
72
|
+
},
|
73
|
+
{
|
74
|
+
field: 'last_follow_person',
|
75
|
+
width: 150,
|
76
|
+
title: '最新跟进人'
|
77
|
+
},
|
78
|
+
{
|
79
|
+
field: 'latest_time',
|
80
|
+
title: '最新跟进时间',
|
81
|
+
width: 150,
|
82
|
+
},
|
83
|
+
{
|
84
|
+
field: 'deleter',
|
85
|
+
width: 90,
|
86
|
+
title: '删除人',
|
87
|
+
},
|
88
|
+
{
|
89
|
+
field: 'delete_time',
|
90
|
+
title: '删除时间',
|
91
|
+
width: 150,
|
92
|
+
sort: true,
|
93
|
+
|
94
|
+
},
|
95
|
+
{
|
96
|
+
title: '操作',
|
97
|
+
width: 120,
|
98
|
+
toolbar: '#currentTable_followup',
|
99
|
+
align: "center"
|
100
|
+
}
|
101
|
+
]
|
102
|
+
],
|
103
|
+
limit: 20,
|
104
|
+
limits: [10,15,20,30,40,50,60,70,80,90],
|
105
|
+
page: true
|
106
|
+
});
|
107
|
+
|
108
|
+
var sort = {}, search = {};
|
109
|
+
table.on('sort(follow_up)', function (obj) {
|
110
|
+
sort.field = obj.field;
|
111
|
+
sort.order = obj.type;
|
112
|
+
table.reload('follow_up', {
|
113
|
+
initSort: obj,
|
114
|
+
where: {
|
115
|
+
sort: sort,
|
116
|
+
q: search
|
117
|
+
}
|
118
|
+
});
|
119
|
+
})
|
120
|
+
|
121
|
+
|
122
|
+
table.on('tool(follow_up)', function (obj) {
|
123
|
+
var data = obj.data;
|
124
|
+
var id = data.id
|
125
|
+
if (obj.event === 'restore') {
|
126
|
+
layer.confirm('确定恢复' + data.name, function (index) {
|
127
|
+
request.get('missions/recycles/' + data.id + '/restore_follow_up', {}, function (res) {
|
128
|
+
layer.close(index);
|
129
|
+
table.reload("follow_up")
|
130
|
+
})
|
131
|
+
});
|
132
|
+
} else if (obj.event === 'delete') {
|
133
|
+
layer.confirm('确定删除' + data.name, function (index) {
|
134
|
+
request.delete('missions/recycles/' + data.id, {}, function (res) {
|
135
|
+
layer.close(index);
|
136
|
+
table.reload("follow_up")
|
137
|
+
})
|
138
|
+
});
|
139
|
+
}
|
140
|
+
});
|
141
|
+
|
142
|
+
});
|
143
|
+
</script>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
json.data do
|
2
|
+
json.array! @data do |d|
|
3
|
+
follow_up = EducodeSales::FollowUp.unscoped.find(d.source_id)
|
4
|
+
business = EducodeSales::Business.unscoped.find(follow_up.business_id)
|
5
|
+
json.id d.id
|
6
|
+
json.name business&.name
|
7
|
+
json.clazz business.clazz&.name
|
8
|
+
json.staff_manages follow_up.assign_follow_ups.present? ? (follow_up.assign_follow_ups.map{ |s| s.staff.user&.real_name}.join("、")) : business.staff&.user&.real_name
|
9
|
+
json.follow_up_content follow_up.description
|
10
|
+
json.school business.department&.school&.name
|
11
|
+
json.department business.department&.name
|
12
|
+
json.last_follow_person follow_up.staff.user&.real_name
|
13
|
+
json.latest_time follow_up.created_at.to_s
|
14
|
+
json.deleter EducodeSales::Staff.find(d.deleter_id).user&.real_name
|
15
|
+
json.delete_time d.created_at.to_s
|
16
|
+
json.stage follow_up.stage&.name
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
json.code 0
|
21
|
+
json.count @data.total_count
|
@@ -1,6 +1,7 @@
|
|
1
1
|
<div class="layui-tab" lay-filter="sale_tab">
|
2
2
|
<ul class="layui-tab-title">
|
3
3
|
<li class="layui-this" data="business">商机</li>
|
4
|
+
<li data="follow_up">商机跟进</li>
|
4
5
|
<li data="week">周计划</li>
|
5
6
|
<li data="weekly">周报</li>
|
6
7
|
<li data="month">月计划</li>
|
@@ -11,6 +12,9 @@
|
|
11
12
|
<div class="layui-tab-item layui-show">
|
12
13
|
<%= render 'business' %>
|
13
14
|
</div>
|
15
|
+
<div class="layui-tab-item">
|
16
|
+
<%= render 'follow_up' %>
|
17
|
+
</div>
|
14
18
|
<div class="layui-tab-item">
|
15
19
|
<%= render 'weekPlan' %>
|
16
20
|
</div>
|
@@ -25,7 +25,6 @@
|
|
25
25
|
align: 'center',
|
26
26
|
width: 150,
|
27
27
|
rowspan: 2,
|
28
|
-
totalRowText:'合计',
|
29
28
|
}
|
30
29
|
, {
|
31
30
|
title: '公有云',
|
@@ -47,59 +46,49 @@
|
|
47
46
|
title: '用户数',
|
48
47
|
align: 'center',
|
49
48
|
width: 110,
|
50
|
-
totalRow: '{{ parseInt(d.TOTAL_NUMS) }}',
|
51
49
|
}, {
|
52
50
|
field: 'school_1',
|
53
51
|
title: '学校数',
|
54
52
|
align: 'center',
|
55
53
|
width: 110,
|
56
|
-
totalRow: '{{ parseInt(d.TOTAL_NUMS) }}',
|
57
54
|
}, {
|
58
55
|
field: 'department_1',
|
59
56
|
title: '学院数',
|
60
57
|
align: 'center',
|
61
58
|
width: 110,
|
62
|
-
totalRow: '{{ parseInt(d.TOTAL_NUMS) }}',
|
63
59
|
},{
|
64
60
|
field: 'user_2',
|
65
61
|
title: '用户数',
|
66
62
|
align: 'center',
|
67
63
|
width: 110,
|
68
|
-
totalRow: '{{ parseInt(d.TOTAL_NUMS) }}',
|
69
64
|
}, {
|
70
65
|
field: 'school_2',
|
71
66
|
title: '学校数',
|
72
67
|
align: 'center',
|
73
68
|
width: 110,
|
74
|
-
totalRow: '{{ parseInt(d.TOTAL_NUMS) }}',
|
75
69
|
}, {
|
76
70
|
field: 'department_2',
|
77
71
|
align: 'center',
|
78
72
|
title: '学院数',
|
79
73
|
width: 110,
|
80
|
-
totalRow: '{{ parseInt(d.TOTAL_NUMS) }}',
|
81
74
|
},{
|
82
75
|
field: 'user_2',
|
83
76
|
title: '用户数',
|
84
77
|
align: 'center',
|
85
78
|
width: 110,
|
86
|
-
totalRow: '{{ parseInt(d.TOTAL_NUMS) }}',
|
87
79
|
}, {
|
88
80
|
field: 'school_2',
|
89
81
|
title: '学校数',
|
90
82
|
align: 'center',
|
91
83
|
width: 110,
|
92
|
-
totalRow: '{{ parseInt(d.TOTAL_NUMS) }}',
|
93
84
|
}, {
|
94
85
|
field: 'department_2',
|
95
86
|
align: 'center',
|
96
87
|
title: '学院数',
|
97
88
|
width: 110,
|
98
|
-
totalRow: '{{ parseInt(d.TOTAL_NUMS) }}',
|
99
89
|
}]
|
100
90
|
],
|
101
91
|
data: gon.table_1,
|
102
|
-
totalRow: true,
|
103
92
|
page: false
|
104
93
|
});
|
105
94
|
|
@@ -151,14 +151,20 @@
|
|
151
151
|
field: 'majors',
|
152
152
|
width: 150,
|
153
153
|
title: '专业',
|
154
|
+
hide: true
|
154
155
|
}, {
|
155
156
|
field: 'signed_department',
|
156
157
|
title: '签约单位',
|
157
158
|
width: 280,
|
159
|
+
hide: true
|
158
160
|
}, {
|
159
161
|
field: 'actual_amount',
|
160
162
|
width: 120,
|
161
163
|
title: '合同金额',
|
164
|
+
}, {
|
165
|
+
field: 'project_name',
|
166
|
+
width: 100,
|
167
|
+
title: '产品名称',
|
162
168
|
}, {
|
163
169
|
field: 'item_clazz',
|
164
170
|
width: 100,
|
@@ -204,7 +210,10 @@
|
|
204
210
|
field: 'delivery_date',
|
205
211
|
width: 120,
|
206
212
|
title: '交货时间',
|
207
|
-
|
213
|
+
}, {
|
214
|
+
field: 'proprietorship',
|
215
|
+
width: 120,
|
216
|
+
title: '知识产权归属',
|
208
217
|
}, {
|
209
218
|
title: '操作',
|
210
219
|
minWidth: 350,
|
data/config/routes.rb
CHANGED
@@ -185,11 +185,13 @@ EducodeSales::Engine.routes.draw do
|
|
185
185
|
get :weekPlan
|
186
186
|
get :business
|
187
187
|
get :yearPlan
|
188
|
+
get :follow_up
|
188
189
|
end
|
189
190
|
member do
|
190
191
|
get :restore_plans
|
191
192
|
get :restore_reports
|
192
193
|
get :restore_businesses
|
194
|
+
get :restore_follow_up
|
193
195
|
end
|
194
196
|
end
|
195
197
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class AddProprietorshipEducodeSalesSalesDetails < ActiveRecord::Migration[5.2]
|
2
|
+
def change
|
3
|
+
add_column :educode_sales_sales_details, :proprietorship, :integer
|
4
|
+
add_column :educode_sales_businesses, :source_way, :integer
|
5
|
+
add_column :educode_sales_businesses, :sourcable_type, :string
|
6
|
+
add_column :educode_sales_businesses, :sourcable_id, :integer
|
7
|
+
|
8
|
+
remove_column :educode_sales_businesses, :activity_id, :integer
|
9
|
+
remove_column :educode_sales_businesses, :place_id, :integer
|
10
|
+
remove_column :educode_sales_businesses, :customer_id, :integer
|
11
|
+
remove_column :educode_sales_businesses, :company_source, :string
|
12
|
+
remove_column :educode_sales_businesses, :phone, :string
|
13
|
+
remove_column :educode_sales_businesses, :email, :string
|
14
|
+
remove_column :educode_sales_businesses, :partner, :string
|
15
|
+
remove_column :educode_sales_businesses, :invite_info, :string
|
16
|
+
remove_column :educode_sales_businesses, :friend, :string
|
17
|
+
end
|
18
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: educode_sales
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- anke1460
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-05-
|
11
|
+
date: 2023-05-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -495,12 +495,14 @@ files:
|
|
495
495
|
- app/views/educode_sales/projects/index.html.erb
|
496
496
|
- app/views/educode_sales/projects/index.json.jbuilder
|
497
497
|
- app/views/educode_sales/recycles/_business.html.erb
|
498
|
+
- app/views/educode_sales/recycles/_follow_up.html.erb
|
498
499
|
- app/views/educode_sales/recycles/_monthPlan.html.erb
|
499
500
|
- app/views/educode_sales/recycles/_monthly.html.erb
|
500
501
|
- app/views/educode_sales/recycles/_weekPlan.html.erb
|
501
502
|
- app/views/educode_sales/recycles/_weekly.html.erb
|
502
503
|
- app/views/educode_sales/recycles/_yearPlan.html.erb
|
503
504
|
- app/views/educode_sales/recycles/business.json.jbuilder
|
505
|
+
- app/views/educode_sales/recycles/follow_up.json.jbuilder
|
504
506
|
- app/views/educode_sales/recycles/index.html.erb
|
505
507
|
- app/views/educode_sales/recycles/monthPlan.json.jbuilder
|
506
508
|
- app/views/educode_sales/recycles/monthly.json.jbuilder
|
@@ -682,6 +684,7 @@ files:
|
|
682
684
|
- db/migrate/20230502142912_create_educode_sales_product_catalogs.rb
|
683
685
|
- db/migrate/20230510144317_create_educode_sales_sales_details.rb
|
684
686
|
- db/migrate/20230520023902_add_activity_educode_sales_business.rb
|
687
|
+
- db/migrate/20230523115007_add_proprietorship_educode_sales_sales_details.rb
|
685
688
|
- lib/educode_sales.rb
|
686
689
|
- lib/educode_sales/engine.rb
|
687
690
|
- lib/educode_sales/version.rb
|