jewerly_system 1.0.0
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 +7 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +21 -0
- data/README.md +1 -0
- data/jewelry_system.gemspec +17 -0
- data/lib/jewerly_system/version.rb +5 -0
- data/lib/jewerly_system.rb +10 -0
- data/lib/source/customer/controllers/customer_input_form_controller_create.rb +44 -0
- data/lib/source/customer/controllers/customer_input_form_controller_edit.rb +52 -0
- data/lib/source/customer/controllers/customer_list_controller.rb +104 -0
- data/lib/source/customer/customer_db_data_source.rb +63 -0
- data/lib/source/customer/ui/customer_input_form.rb +70 -0
- data/lib/source/customer/ui/customer_list_view.rb +159 -0
- data/lib/source/master/controllers/master_controller.rb +57 -0
- data/lib/source/master/controllers/master_input_form_controller_create.rb +44 -0
- data/lib/source/master/controllers/master_input_form_controller_edit.rb +53 -0
- data/lib/source/master/controllers/master_list_controller.rb +101 -0
- data/lib/source/master/master_db_data_source.rb +65 -0
- data/lib/source/master/ui/master_input_form.rb +72 -0
- data/lib/source/master/ui/master_list_view.rb +163 -0
- data/lib/source/models/customer.rb +37 -0
- data/lib/source/models/master.rb +32 -0
- data/lib/source/models/product.rb +31 -0
- data/lib/source/models/student.rb +102 -0
- data/lib/source/models/student_base.rb +100 -0
- data/lib/source/models/student_short.rb +50 -0
- data/lib/source/state_holders/list_state_notifier.rb +47 -0
- data/lib/source/util/logger_holder.rb +24 -0
- data/sig/jewerly_system.rbs +4 -0
- metadata +86 -0
@@ -0,0 +1,57 @@
|
|
1
|
+
# # frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# require './jew/views/main_window'
|
4
|
+
# require './jew/repositories/student_repository'
|
5
|
+
# require './jew/repositories/adapters/db_source_adapter'
|
6
|
+
# require './jew/repositories/containers/data_list_student_short'
|
7
|
+
# require './jew/state_holders/list_state_notifier'
|
8
|
+
# require_relative '../author_db_data_source'
|
9
|
+
# require 'win32api'
|
10
|
+
#
|
11
|
+
# class AuthorController
|
12
|
+
#
|
13
|
+
#
|
14
|
+
# def initialize(view)
|
15
|
+
# @view = view
|
16
|
+
# @state_notifier = ListStateNotifier.new
|
17
|
+
# @state_notifier.add_listener(@view)
|
18
|
+
# @author_rep = AuthorDBDataSource.new
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# def edit (number)
|
22
|
+
# master = @state_notifier.get(number)
|
23
|
+
# puts master.id
|
24
|
+
# # @view.show_edit_dialog(master)
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# def add (number)
|
28
|
+
# master = @state_notifier.get(number)
|
29
|
+
# puts master
|
30
|
+
# # @view.show_add_dialog(master)
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
#
|
34
|
+
# def remove (number)
|
35
|
+
# master = @state_notifier.get(number)
|
36
|
+
# puts master
|
37
|
+
# # @view.show_remove_dialog(master)
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# def refresh_data(page, per_page)
|
41
|
+
# items = @author_rep.get_list(per_page, page, 'FirstName', 'ASC' )
|
42
|
+
# @state_notifier.set_all(items)
|
43
|
+
# @view.update_student_count(@author_rep.count)
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# def refresh()
|
47
|
+
# items = @author_rep.get_list(per_page, page, 'FirstName', 'ASC' )
|
48
|
+
# @state_notifier.set_all(items)
|
49
|
+
# @view.update_student_count(@author_rep.count)
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# def on_db_conn_error
|
53
|
+
# api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
54
|
+
# api.call(0, "No connection to DB", "Error", 0)
|
55
|
+
# exit(false)
|
56
|
+
# end
|
57
|
+
# end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'win32api'
|
4
|
+
|
5
|
+
class MasterInputFormControllerCreate
|
6
|
+
def initialize(parent_controller)
|
7
|
+
@parent_controller = parent_controller
|
8
|
+
@author_rep = MasterDBDataSource.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def set_view(view)
|
12
|
+
@view = view
|
13
|
+
end
|
14
|
+
|
15
|
+
def on_view_created
|
16
|
+
# begin
|
17
|
+
# @student_rep = StudentRepository.new(DBSourceAdapter.new)
|
18
|
+
# rescue Mysql2::Error::ConnectionError
|
19
|
+
# on_db_conn_error
|
20
|
+
# end
|
21
|
+
end
|
22
|
+
|
23
|
+
def process_fields(fields)
|
24
|
+
begin
|
25
|
+
puts fields
|
26
|
+
item = Master.new(-1, *fields.values)
|
27
|
+
puts item
|
28
|
+
item = @author_rep.add(item)
|
29
|
+
@parent_controller.state_notifier.add(item)
|
30
|
+
@view.close
|
31
|
+
rescue ArgumentError => e
|
32
|
+
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
33
|
+
api.call(0, e.message, 'Error', 0)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def on_db_conn_error
|
40
|
+
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
41
|
+
api.call(0, "No connection to DB", "Error", 0)
|
42
|
+
@view.close
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'win32api'
|
4
|
+
|
5
|
+
class MasterInputFormControllerEdit
|
6
|
+
def initialize(parent_controller, item)
|
7
|
+
@parent_controller = parent_controller
|
8
|
+
@item = item
|
9
|
+
@author_rep = MasterDBDataSource.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def set_view(view)
|
13
|
+
@view = view
|
14
|
+
end
|
15
|
+
|
16
|
+
def on_view_created
|
17
|
+
# begin
|
18
|
+
# @student_rep = StudentRepository.new(DBSourceAdapter.new)
|
19
|
+
# rescue Mysql2::Error::ConnectionError
|
20
|
+
# on_db_conn_error
|
21
|
+
# end
|
22
|
+
|
23
|
+
# @item = @author_rep.get(@item_id)
|
24
|
+
# @view.make_readonly(:git, :telegram, :email, :phone)
|
25
|
+
populate_fields(@item)
|
26
|
+
end
|
27
|
+
|
28
|
+
def populate_fields(item)
|
29
|
+
@view.set_value(:first_name, item.first_name)
|
30
|
+
@view.set_value(:last_name, item.last_name)
|
31
|
+
@view.set_value(:father_name, item.father_name)
|
32
|
+
end
|
33
|
+
|
34
|
+
def process_fields(fields)
|
35
|
+
begin
|
36
|
+
item = Master.new(@item.master_id, *fields.values)
|
37
|
+
item = @author_rep.change(item)
|
38
|
+
@parent_controller.state_notifier.replace(@item, item)
|
39
|
+
@view.close
|
40
|
+
rescue ArgumentError => e
|
41
|
+
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
42
|
+
api.call(0, e.message, 'Error', 0)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def on_db_conn_error
|
49
|
+
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
50
|
+
api.call(0, "No connection to DB", "Error", 0)
|
51
|
+
@view.close
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require './jew/state_holders/list_state_notifier'
|
4
|
+
require_relative '../ui/master_input_form'
|
5
|
+
require_relative 'master_input_form_controller_create'
|
6
|
+
require_relative 'master_input_form_controller_edit'
|
7
|
+
require_relative '../master_db_data_source'
|
8
|
+
require 'win32api'
|
9
|
+
|
10
|
+
class MasterListController
|
11
|
+
|
12
|
+
attr_reader :state_notifier;
|
13
|
+
def initialize(view)
|
14
|
+
LoggerHolder.instance.debug('MasterListController: init start')
|
15
|
+
@view = view
|
16
|
+
@state_notifier = ListStateNotifier.new
|
17
|
+
@state_notifier.add_listener(@view)
|
18
|
+
@author_rep = MasterDBDataSource.new
|
19
|
+
|
20
|
+
@sort_columns = %w[MasterID FirstName LastName FatherName]
|
21
|
+
@sort_by = @sort_columns.first
|
22
|
+
|
23
|
+
@father_name_filter_columns = [nil, true, false]
|
24
|
+
@father_name_filter = @father_name_filter_columns.first
|
25
|
+
LoggerHolder.instance.debug('MasterListController: init done')
|
26
|
+
end
|
27
|
+
|
28
|
+
def on_view_created
|
29
|
+
# begin
|
30
|
+
# @student_rep = StudentRepository.new(DBSourceAdapter.new)
|
31
|
+
# rescue Mysql2::Error::ConnectionError
|
32
|
+
# on_db_conn_error
|
33
|
+
# end
|
34
|
+
end
|
35
|
+
|
36
|
+
def show_view
|
37
|
+
@view.create.show
|
38
|
+
end
|
39
|
+
|
40
|
+
def show_modal_add
|
41
|
+
LoggerHolder.instance.debug('MasterListController: showing modal (add)')
|
42
|
+
controller = MasterInputFormControllerCreate.new(self)
|
43
|
+
view = MasterInputForm.new(controller)
|
44
|
+
controller.set_view(view)
|
45
|
+
view.create.show
|
46
|
+
end
|
47
|
+
|
48
|
+
def show_modal_edit(current_page, per_page, selected_row)
|
49
|
+
# item_num = (current_page - 1) * per_page + selected_row
|
50
|
+
|
51
|
+
item = @state_notifier.get(selected_row)
|
52
|
+
|
53
|
+
controller = MasterInputFormControllerEdit.new(self, item)
|
54
|
+
view = MasterInputForm.new(controller)
|
55
|
+
controller.set_view(view)
|
56
|
+
view.create.show
|
57
|
+
end
|
58
|
+
|
59
|
+
def delete_selected(current_page, per_page, selected_row)
|
60
|
+
begin
|
61
|
+
LoggerHolder.instance.debug('MasterListController: deleting selected master')
|
62
|
+
item = @state_notifier.get(selected_row)
|
63
|
+
@author_rep.delete(item.master_id)
|
64
|
+
@state_notifier.delete(item)
|
65
|
+
rescue
|
66
|
+
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
67
|
+
api.call(0, "You cannot delete the master because it is associated with some product", "Error", 0)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def refresh_data(page, per_page)
|
72
|
+
LoggerHolder.instance.debug('MasterListController: refreshing data...')
|
73
|
+
items = @author_rep.get_list(per_page, page, @sort_by, 'ASC', @father_name_filter)
|
74
|
+
@state_notifier.set_all(items)
|
75
|
+
@view.update_student_count(@author_rep.count)
|
76
|
+
end
|
77
|
+
|
78
|
+
def sort(page, per_page, sort_index)
|
79
|
+
LoggerHolder.instance.debug('MasterListController: filter start...')
|
80
|
+
@sort_by = @sort_columns[sort_index]
|
81
|
+
refresh_data(page, per_page)
|
82
|
+
LoggerHolder.instance.debug('MasterListController: filter end.')
|
83
|
+
end
|
84
|
+
|
85
|
+
def filter_father_name(page, per_page, filter_index)
|
86
|
+
LoggerHolder.instance.debug('MasterListController: filter start...')
|
87
|
+
@father_name_filter = @father_name_filter_columns[filter_index]
|
88
|
+
LoggerHolder.instance.debug('MasterListController: filter end.')
|
89
|
+
refresh_data(page, per_page)
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def on_db_conn_error(error)
|
95
|
+
LoggerHolder.instance.error('MasterListController: DB connection error:')
|
96
|
+
LoggerHolder.instance.error(error.message)
|
97
|
+
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
98
|
+
api.call(0, "No connection to DB", "Error", 0)
|
99
|
+
exit(false)
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'mysql2'
|
2
|
+
require_relative '../data_sources/db_client'
|
3
|
+
|
4
|
+
class MasterDBDataSource
|
5
|
+
def initialize
|
6
|
+
@client = DBClient.instance
|
7
|
+
end
|
8
|
+
|
9
|
+
def add(master)
|
10
|
+
query = "INSERT INTO Master (FirstName, LastName, FatherName) VALUES ('#{master.first_name}', '#{master.last_name}', #{master.father_name.nil? ? 'NULL' : "'#{master.father_name}'"})"
|
11
|
+
@client.query(query)
|
12
|
+
master_id = @client.last_id
|
13
|
+
get(master_id)
|
14
|
+
end
|
15
|
+
|
16
|
+
def change(master)
|
17
|
+
query = "UPDATE Master SET FirstName='#{master.first_name}', LastName='#{master.last_name}', FatherName=#{master.father_name.nil? ? 'NULL' : "'#{master.father_name}'"} WHERE MasterID=#{master.master_id}"
|
18
|
+
@client.query(query)
|
19
|
+
get(master.master_id)
|
20
|
+
end
|
21
|
+
|
22
|
+
def delete(id)
|
23
|
+
query = "DELETE FROM Master WHERE MasterID=#{id}"
|
24
|
+
@client.query(query)
|
25
|
+
end
|
26
|
+
|
27
|
+
def get(id)
|
28
|
+
query = "SELECT * FROM Master WHERE MasterID=#{id}"
|
29
|
+
result = @client.query(query).first
|
30
|
+
if result
|
31
|
+
Master.new(result[:'MasterID'], result[:'FirstName'], result[:'LastName'], result[:'FatherName'])
|
32
|
+
else
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def get_list(page_size, page_num, sort_field, sort_direction, has_father_name = nil)
|
38
|
+
offset = (page_num - 1) * page_size
|
39
|
+
query = "SELECT * FROM Master"
|
40
|
+
|
41
|
+
if has_father_name == true
|
42
|
+
query += " WHERE FatherName IS NOT NULL"
|
43
|
+
elsif has_father_name == false
|
44
|
+
query += " WHERE FatherName IS NULL"
|
45
|
+
end
|
46
|
+
|
47
|
+
query += " ORDER BY #{sort_field} #{sort_direction} LIMIT #{page_size} OFFSET #{offset}"
|
48
|
+
results = @client.query(query)
|
49
|
+
|
50
|
+
masters = []
|
51
|
+
results.each do |result|
|
52
|
+
masters << Master.new(result[:'MasterID'], result[:'FirstName'], result[:'LastName'], result[:'FatherName'])
|
53
|
+
end
|
54
|
+
|
55
|
+
masters
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
def count
|
60
|
+
query = "SELECT COUNT(*) FROM Master"
|
61
|
+
result = @client.query(query).first
|
62
|
+
|
63
|
+
result[:'COUNT(*)']
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'glimmer-dsl-libui'
|
4
|
+
require_relative '../controllers/master_input_form_controller_create'
|
5
|
+
require './jew/models/master'
|
6
|
+
require './jew/util/logger_holder'
|
7
|
+
require 'win32api'
|
8
|
+
|
9
|
+
class MasterInputForm
|
10
|
+
include Glimmer
|
11
|
+
|
12
|
+
def initialize(controller, existing_student = nil)
|
13
|
+
@item = existing_student.to_hash unless existing_student.nil?
|
14
|
+
@controller = controller
|
15
|
+
@entries = {}
|
16
|
+
LoggerHolder.instance.debug('MasterInputForm: initialized')
|
17
|
+
end
|
18
|
+
|
19
|
+
def on_create
|
20
|
+
@controller.on_view_created
|
21
|
+
end
|
22
|
+
|
23
|
+
def create
|
24
|
+
@root_container = window('Мастер', 300, 70) {
|
25
|
+
resizable false
|
26
|
+
|
27
|
+
vertical_box {
|
28
|
+
@student_form = form {
|
29
|
+
stretchy false
|
30
|
+
|
31
|
+
fields = [[:first_name, 'Имя мастера'], [:last_name, 'Фамилия мастера'], [:father_name, 'Отчество мастера']]
|
32
|
+
|
33
|
+
fields.each do |field|
|
34
|
+
@entries[field[0]] = entry {
|
35
|
+
label field[1]
|
36
|
+
}
|
37
|
+
end
|
38
|
+
}
|
39
|
+
|
40
|
+
button('Сохранить') {
|
41
|
+
stretchy false
|
42
|
+
|
43
|
+
on_clicked {
|
44
|
+
values = @entries.transform_values { |v| v.text.force_encoding("utf-8").strip }
|
45
|
+
values.transform_values! { |v| v.empty? ? nil : v}
|
46
|
+
|
47
|
+
@controller.process_fields(values)
|
48
|
+
LoggerHolder.instance.debug('MasterInputForm: adding/edit master to DB')
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
52
|
+
}
|
53
|
+
on_create
|
54
|
+
@root_container
|
55
|
+
end
|
56
|
+
|
57
|
+
def set_value(field, value)
|
58
|
+
return unless @entries.include?(field)
|
59
|
+
|
60
|
+
@entries[field].text = value
|
61
|
+
end
|
62
|
+
|
63
|
+
def make_readonly(*fields)
|
64
|
+
fields.each do |field|
|
65
|
+
@entries[field].read_only = true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def close
|
70
|
+
@root_container.destroy
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'glimmer-dsl-libui'
|
4
|
+
require_relative '../controllers/master_list_controller'
|
5
|
+
require_relative '../controllers/master_controller'
|
6
|
+
require_relative 'master_input_form'
|
7
|
+
require './jew/util/logger_holder'
|
8
|
+
|
9
|
+
class MasterListView
|
10
|
+
include Glimmer
|
11
|
+
|
12
|
+
PAGE_SIZE = 20
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@controller = MasterListController.new(self)
|
16
|
+
@current_page = 1
|
17
|
+
@total_count = 0
|
18
|
+
LoggerHolder.instance.debug('MasterListView: initialize')
|
19
|
+
end
|
20
|
+
|
21
|
+
def on_create
|
22
|
+
@controller.on_view_created
|
23
|
+
@controller.refresh_data(@current_page, PAGE_SIZE)
|
24
|
+
end
|
25
|
+
|
26
|
+
def update(masters)
|
27
|
+
@items = []
|
28
|
+
|
29
|
+
i = 0
|
30
|
+
item_num = 0
|
31
|
+
masters.each do |author|
|
32
|
+
i += 1
|
33
|
+
item_num = ((@current_page - 1) * PAGE_SIZE) + i
|
34
|
+
@items << Struct.new(:№, :id, :имя_мастера, :фамилия_мастера, :отчество_мастера).new(item_num, author.master_id, author.first_name, author.last_name, author.father_name)
|
35
|
+
end
|
36
|
+
|
37
|
+
@table.model_array = @items
|
38
|
+
@page_label.text = "#{@current_page} / #{(@total_count / PAGE_SIZE.to_f).ceil}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def update_student_count(new_cnt)
|
42
|
+
@total_count = new_cnt
|
43
|
+
@page_label.text = "#{@current_page} / #{(@total_count / PAGE_SIZE.to_f).ceil}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def create
|
47
|
+
|
48
|
+
root_container = horizontal_box {
|
49
|
+
# Секция 1
|
50
|
+
vertical_box {
|
51
|
+
stretchy false
|
52
|
+
|
53
|
+
vertical_box {
|
54
|
+
stretchy false
|
55
|
+
|
56
|
+
label {
|
57
|
+
text 'Отчество'
|
58
|
+
}
|
59
|
+
combobox { |c|
|
60
|
+
items ['Не важно','Есть','Нет']
|
61
|
+
selected 0
|
62
|
+
on_selected do
|
63
|
+
@controller.filter_father_name(@current_page, PAGE_SIZE, c.selected)
|
64
|
+
end
|
65
|
+
}
|
66
|
+
|
67
|
+
label {
|
68
|
+
text 'Сортировка'
|
69
|
+
}
|
70
|
+
combobox { |c|
|
71
|
+
items ['ID','Имя мастера','Фамилия мастера', 'Отчество мастера']
|
72
|
+
selected 0
|
73
|
+
on_selected do
|
74
|
+
@controller.sort(@current_page, PAGE_SIZE, c.selected)
|
75
|
+
end
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
|
80
|
+
}
|
81
|
+
|
82
|
+
# Секция 2
|
83
|
+
vertical_box {
|
84
|
+
@table = refined_table(
|
85
|
+
table_editable: false,
|
86
|
+
filter: lambda do |row_hash, query|
|
87
|
+
utf8_query = query.force_encoding("utf-8")
|
88
|
+
row_hash['Имя мастера'].include?(utf8_query)
|
89
|
+
end,
|
90
|
+
table_columns: {
|
91
|
+
'№' => :text,
|
92
|
+
'ID' => :text,
|
93
|
+
'Имя мастера' => :text,
|
94
|
+
'Фамилия мастера' => :text,
|
95
|
+
'Отчество мастера' => :text,
|
96
|
+
},
|
97
|
+
per_page: PAGE_SIZE,
|
98
|
+
|
99
|
+
)
|
100
|
+
|
101
|
+
@pages = horizontal_box {
|
102
|
+
stretchy false
|
103
|
+
|
104
|
+
button("<") {
|
105
|
+
stretchy true
|
106
|
+
|
107
|
+
on_clicked do
|
108
|
+
@current_page = [@current_page - 1, 1].max
|
109
|
+
@controller.refresh_data(@current_page, PAGE_SIZE)
|
110
|
+
end
|
111
|
+
|
112
|
+
}
|
113
|
+
@page_label = label("...") { stretchy false }
|
114
|
+
button(">") {
|
115
|
+
stretchy true
|
116
|
+
|
117
|
+
on_clicked do
|
118
|
+
@current_page = [@current_page + 1, (@total_count / PAGE_SIZE.to_f).ceil].min
|
119
|
+
@controller.refresh_data(@current_page, PAGE_SIZE)
|
120
|
+
end
|
121
|
+
}
|
122
|
+
}
|
123
|
+
}
|
124
|
+
|
125
|
+
# Секция 3
|
126
|
+
vertical_box {
|
127
|
+
stretchy false
|
128
|
+
|
129
|
+
button('Добавить') {
|
130
|
+
stretchy false
|
131
|
+
|
132
|
+
on_clicked {
|
133
|
+
@controller.show_modal_add
|
134
|
+
}
|
135
|
+
}
|
136
|
+
button('Изменить') {
|
137
|
+
stretchy false
|
138
|
+
|
139
|
+
on_clicked {
|
140
|
+
@controller.show_modal_edit(@current_page, PAGE_SIZE, @table.selection) unless @table.selection.nil?
|
141
|
+
}
|
142
|
+
}
|
143
|
+
button('Удалить') {
|
144
|
+
stretchy false
|
145
|
+
|
146
|
+
on_clicked {
|
147
|
+
@controller.delete_selected(@current_page, PAGE_SIZE, @table.selection) unless @table.selection.nil?
|
148
|
+
@controller.refresh_data(@current_page, PAGE_SIZE)
|
149
|
+
}
|
150
|
+
}
|
151
|
+
button('Обновить') {
|
152
|
+
stretchy false
|
153
|
+
|
154
|
+
on_clicked {
|
155
|
+
@controller.refresh_data(@current_page, PAGE_SIZE)
|
156
|
+
}
|
157
|
+
}
|
158
|
+
}
|
159
|
+
}
|
160
|
+
on_create
|
161
|
+
root_container
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Customer
|
2
|
+
EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
|
3
|
+
|
4
|
+
attr_reader :customer_id, :name, :email
|
5
|
+
|
6
|
+
def initialize(customer_id, name, email = nil)
|
7
|
+
validate_null('customer_id', customer_id)
|
8
|
+
validate_null('name', name)
|
9
|
+
|
10
|
+
validate_name_length(name)
|
11
|
+
validate_email(email)
|
12
|
+
|
13
|
+
@customer_id = customer_id
|
14
|
+
@name = name
|
15
|
+
@email = email
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def validate_null(name, value)
|
21
|
+
if value.nil?
|
22
|
+
raise ArgumentError, "The argument '#{name}' cannot be null"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def validate_name_length(name)
|
27
|
+
if name.length > 100
|
28
|
+
raise ArgumentError, "The number of characters in the name exceeds 100: #{name}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def validate_email(email)
|
33
|
+
if email && !email.match?(EMAIL_REGEX)
|
34
|
+
raise ArgumentError, "Invalid email format: #{email}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Master
|
2
|
+
attr_reader :master_id, :first_name, :last_name, :father_name
|
3
|
+
|
4
|
+
def initialize(master_id, first_name, last_name, father_name = nil)
|
5
|
+
validate_null('master_id', master_id)
|
6
|
+
validate_null('first_name', first_name)
|
7
|
+
validate_null('last_name', last_name)
|
8
|
+
|
9
|
+
validate_name_length(first_name, last_name, father_name)
|
10
|
+
|
11
|
+
@master_id = master_id
|
12
|
+
@first_name = first_name
|
13
|
+
@last_name = last_name
|
14
|
+
@father_name = father_name
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def validate_null(name, value)
|
20
|
+
if value.nil?
|
21
|
+
raise ArgumentError, "The argument '#{name}' cannot be null"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def validate_name_length(first_name, last_name, father_name)
|
26
|
+
[first_name, last_name, father_name].each do |name|
|
27
|
+
if name && name.length > 50
|
28
|
+
raise ArgumentError, "The number of characters in the name exceeds 50: #{name}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class Product
|
2
|
+
attr_reader :product_id, :title, :master_id, :customer_id
|
3
|
+
|
4
|
+
def initialize(product_id, title, master_id, customer_id)
|
5
|
+
validate_null('product_id', product_id)
|
6
|
+
validate_null('title', title)
|
7
|
+
validate_null('master_id', master_id)
|
8
|
+
validate_null('customer_id', customer_id)
|
9
|
+
|
10
|
+
validate_title_length(title)
|
11
|
+
|
12
|
+
@product_id = product_id
|
13
|
+
@title = title
|
14
|
+
@master_id = master_id
|
15
|
+
@customer_id = customer_id
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def validate_null(name, value)
|
21
|
+
if value.nil?
|
22
|
+
raise ArgumentError, "Argument '#{name}' cannot be null"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def validate_title_length(title)
|
27
|
+
if title.length > 255
|
28
|
+
raise ArgumentError, "The title contains more than 255 characters: #{title}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|