shnaider_carproj 0.1.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/Gemfile +10 -0
- data/Gemfile.lock +71 -0
- data/diagrams/add_owner.jpg +0 -0
- data/diagrams/delete_owner.jpg +0 -0
- data/diagrams/er.png +0 -0
- data/diagrams/owner.jpg +0 -0
- data/diagrams/owner.sai2 +0 -0
- data/diagrams/start.jpg +0 -0
- data/lib/car/controllers/publisher_input_form_controller_create.rb +44 -0
- data/lib/car/controllers/publisher_input_form_controller_edit.rb +52 -0
- data/lib/car/controllers/publisher_list_controller.rb +99 -0
- data/lib/car/tenant_db_data_source.rb +63 -0
- data/lib/car/ui/tenant_input_form.rb +69 -0
- data/lib/car/ui/tenant_list_view.rb +168 -0
- data/lib/controllers/tab_students_controller.rb +43 -0
- data/lib/data_sources/car_db_data_source.rb +43 -0
- data/lib/data_sources/db_client.rb +34 -0
- data/lib/db_config/carshering_config.yaml +5 -0
- data/lib/db_config/config.yaml +5 -0
- data/lib/db_config/migrations/create_db.sql +3 -0
- data/lib/db_config/migrations/create_tables.sql +29 -0
- data/lib/db_config/mock_data/mock_data.sql +55 -0
- data/lib/models/car.rb +31 -0
- data/lib/models/owner.rb +32 -0
- data/lib/models/student.rb +102 -0
- data/lib/models/student_base.rb +100 -0
- data/lib/models/student_short.rb +50 -0
- data/lib/models/tenant.rb +40 -0
- data/lib/owner/controllers/owner_input_form_controller_create.rb +44 -0
- data/lib/owner/controllers/owner_input_form_controller_edit.rb +53 -0
- data/lib/owner/controllers/owner_list_controller.rb +107 -0
- data/lib/owner/owner_db_data_source.rb +70 -0
- data/lib/owner/ui/owner_input_form.rb +69 -0
- data/lib/owner/ui/owner_list_view.rb +169 -0
- data/lib/repositories/adapters/db_source_adapter.rb +54 -0
- data/lib/repositories/adapters/file_source_adapter.rb +37 -0
- data/lib/repositories/containers/data_list.rb +74 -0
- data/lib/repositories/containers/data_list_student_short.rb +18 -0
- data/lib/repositories/containers/data_table.rb +35 -0
- data/lib/repositories/data_sources/db_data_source.rb +32 -0
- data/lib/repositories/data_sources/file_data_source.rb +75 -0
- data/lib/repositories/data_sources/transformers/data_transformer_base.rb +15 -0
- data/lib/repositories/data_sources/transformers/data_transformer_json.rb +16 -0
- data/lib/repositories/data_sources/transformers/data_transformer_yaml.rb +16 -0
- data/lib/repositories/student_repository.rb +32 -0
- data/lib/state_holders/list_state_notifier.rb +62 -0
- data/lib/tenant/controllers/tenant_input_form_controller_create.rb +44 -0
- data/lib/tenant/controllers/tenant_input_form_controller_edit.rb +53 -0
- data/lib/tenant/controllers/tenant_list_controller.rb +107 -0
- data/lib/tenant/tenant_db_data_source.rb +90 -0
- data/lib/tenant/ui/tenant_input_form.rb +69 -0
- data/lib/tenant/ui/tenant_list_view.rb +169 -0
- data/lib/views/main_window.rb +25 -0
- data/lib/views/tab_students.rb +148 -0
- data/requirements.docx +0 -0
- data/shnaider_carproj.gemspec +15 -0
- data/test/car_test.rb +33 -0
- data/test/logger.rb +27 -0
- data/test/main.rb +5 -0
- data/test/owner_test.rb +48 -0
- data/test/state_notifier_test.rb +80 -0
- data/test/tenant_test.rb +48 -0
- metadata +118 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require './models/student'
|
4
|
+
require './models/student_short'
|
5
|
+
require './repositories/containers/data_list_student_short'
|
6
|
+
|
7
|
+
class FileDataSource
|
8
|
+
attr_writer :data_transformer
|
9
|
+
|
10
|
+
def initialize(data_transformer)
|
11
|
+
self.students = []
|
12
|
+
self.seq_id = 1
|
13
|
+
self.data_transformer = data_transformer
|
14
|
+
end
|
15
|
+
|
16
|
+
def load_from_file(file_path)
|
17
|
+
hash_list = data_transformer.str_to_hash_list(File.read(file_path))
|
18
|
+
self.students = hash_list.map { |h| Student.from_hash(h) }
|
19
|
+
update_seq_id
|
20
|
+
end
|
21
|
+
|
22
|
+
def save_to_file(file_path)
|
23
|
+
hash_list = students.map(&:to_hash)
|
24
|
+
File.write(file_path, data_transformer.hash_list_to_str(hash_list))
|
25
|
+
end
|
26
|
+
|
27
|
+
def student_by_id(student_id)
|
28
|
+
students.detect { |s| s.id == student_id }
|
29
|
+
end
|
30
|
+
|
31
|
+
# Получить page по счету count элементов (страница начинается с 1)
|
32
|
+
def paginated_short_students(page, count, existing_data_list = nil)
|
33
|
+
offset = (page - 1) * count
|
34
|
+
slice = students[offset, count].map { |s| StudentShort.from_student(s) }
|
35
|
+
|
36
|
+
return DataListStudentShort.new(slice) if existing_data_list.nil?
|
37
|
+
|
38
|
+
existing_data_list.replace_objects(slice)
|
39
|
+
existing_data_list
|
40
|
+
end
|
41
|
+
|
42
|
+
def sorted
|
43
|
+
students.sort_by(&:last_name_and_initials)
|
44
|
+
end
|
45
|
+
|
46
|
+
def add_student(student)
|
47
|
+
student.id = seq_id
|
48
|
+
students << student
|
49
|
+
self.seq_id += 1
|
50
|
+
student.id
|
51
|
+
end
|
52
|
+
|
53
|
+
def replace_student(student_id, student)
|
54
|
+
idx = students.find_index { |s| s.id == student_id }
|
55
|
+
students[idx] = student
|
56
|
+
end
|
57
|
+
|
58
|
+
def remove_student(student_id)
|
59
|
+
students.reject! { |s| s.id == student_id }
|
60
|
+
end
|
61
|
+
|
62
|
+
def student_count
|
63
|
+
students.count
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
# Метод для актуализации seq_id
|
69
|
+
def update_seq_id
|
70
|
+
self.seq_id = students.max_by(&:id).id + 1
|
71
|
+
end
|
72
|
+
|
73
|
+
attr_reader :data_transformer
|
74
|
+
attr_accessor :students, :seq_id
|
75
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class DataTransformerBase
|
4
|
+
private_class_method :new
|
5
|
+
|
6
|
+
protected
|
7
|
+
|
8
|
+
def str_to_hash_list(str)
|
9
|
+
raise NotImplementedError('Should be implemented in child')
|
10
|
+
end
|
11
|
+
|
12
|
+
def hash_list_to_str(hash_list)
|
13
|
+
raise NotImplementedError('Should be implemented in child')
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'data_transformer_base'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
class DataTransformerJSON < DataTransformerBase
|
7
|
+
public_class_method :new
|
8
|
+
|
9
|
+
def str_to_hash_list(str)
|
10
|
+
JSON.parse(str, { symbolize_names: true })
|
11
|
+
end
|
12
|
+
|
13
|
+
def hash_list_to_str(hash_list)
|
14
|
+
JSON.pretty_generate(hash_list)
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'data_transformer_base'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
class DataTransformerYAML < DataTransformerBase
|
7
|
+
public_class_method :new
|
8
|
+
|
9
|
+
def str_to_hash_list(str)
|
10
|
+
YAML.safe_load(str).map { |h| h.transform_keys(&:to_sym) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def hash_list_to_str(hash_list)
|
14
|
+
hash_list.map { |h| h.transform_keys(&:to_s) }.to_yaml
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class StudentRepository
|
4
|
+
def initialize(data_source_adapter)
|
5
|
+
@data_source_adapter = data_source_adapter
|
6
|
+
end
|
7
|
+
|
8
|
+
def student_by_id(student_id)
|
9
|
+
@data_source_adapter.student_by_id(student_id)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Получить page по счету count элементов (страница начинается с 1)
|
13
|
+
def paginated_short_students(page, count, existing_data_list = nil)
|
14
|
+
@data_source_adapter.paginated_short_students(page, count, existing_data_list)
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_student(student)
|
18
|
+
@data_source_adapter.add_student(student)
|
19
|
+
end
|
20
|
+
|
21
|
+
def replace_student(student_id, student)
|
22
|
+
@data_source_adapter.replace_student(student_id, student)
|
23
|
+
end
|
24
|
+
|
25
|
+
def remove_student(student_id)
|
26
|
+
@data_source_adapter.remove_student(student_id)
|
27
|
+
end
|
28
|
+
|
29
|
+
def student_count
|
30
|
+
@data_source_adapter.student_count
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
|
2
|
+
require './logger'
|
3
|
+
class ListStateNotifier
|
4
|
+
attr_reader :items
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@items = []
|
8
|
+
@listeners = []
|
9
|
+
end
|
10
|
+
|
11
|
+
# устанавливает новое значение для items и уведомляет всех слушателей.
|
12
|
+
def set_all(objects)
|
13
|
+
LoggerHolder.instance.debug('ListStateNotifier: set_all')
|
14
|
+
@items = objects
|
15
|
+
notify_listeners
|
16
|
+
end
|
17
|
+
|
18
|
+
# добавляет объект в массив items и уведомляет всех слушателей.
|
19
|
+
def add(object)
|
20
|
+
LoggerHolder.instance.debug('ListStateNotifier: add')
|
21
|
+
@items << object
|
22
|
+
notify_listeners
|
23
|
+
end
|
24
|
+
# возвращает объект из массива items по индексу.
|
25
|
+
def get(number)
|
26
|
+
LoggerHolder.instance.debug('ListStateNotifier: get')
|
27
|
+
@items[number]
|
28
|
+
end
|
29
|
+
|
30
|
+
# удаляет объект из массива items и уведомляет всех слушателей.
|
31
|
+
def delete(object)
|
32
|
+
LoggerHolder.instance.debug('ListStateNotifier: delete')
|
33
|
+
@items.delete(object)
|
34
|
+
notify_listeners
|
35
|
+
end
|
36
|
+
|
37
|
+
# заменяет объект в массиве items на новый объект и уведомляет всех слушателей.
|
38
|
+
def replace(object, new_object)
|
39
|
+
LoggerHolder.instance.debug('ListStateNotifier: replace')
|
40
|
+
index = @items.index(object)
|
41
|
+
@items[index] = new_object
|
42
|
+
notify_listeners
|
43
|
+
end
|
44
|
+
# добавляет нового слушателя в массив listeners.
|
45
|
+
def add_listener(listener)
|
46
|
+
LoggerHolder.instance.debug('ListStateNotifier: add_listener')
|
47
|
+
@listeners << listener
|
48
|
+
end
|
49
|
+
# удаляет слушателя из массива listeners.
|
50
|
+
def delete_listener(listener)
|
51
|
+
LoggerHolder.instance.debug('ListStateNotifier: delete_listener')
|
52
|
+
@listeners.delete(listener)
|
53
|
+
end
|
54
|
+
|
55
|
+
# уведомляет всех слушателей о изменении массива items.
|
56
|
+
def notify_listeners
|
57
|
+
LoggerHolder.instance.debug('notify_listeners')
|
58
|
+
@listeners.each do |listener|
|
59
|
+
listener.update(@items)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'win32api'
|
4
|
+
|
5
|
+
class TenantInputFormControllerCreate
|
6
|
+
def initialize(parent_controller)
|
7
|
+
@parent_controller = parent_controller
|
8
|
+
@tenant_rep = TenantDbDataSource.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 = Tenant.new(-1, *fields.values)
|
27
|
+
puts item
|
28
|
+
item = @tenant_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 TenantInputFormControllerEdit
|
6
|
+
def initialize(parent_controller, item)
|
7
|
+
@parent_controller = parent_controller
|
8
|
+
@item = item
|
9
|
+
@tenant_rep = TenantDbDataSource.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 = @tenant_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(:phone, item.phone)
|
32
|
+
end
|
33
|
+
|
34
|
+
def process_fields(fields)
|
35
|
+
begin
|
36
|
+
item = Tenant.new(@item.tenant_id, *fields.values)
|
37
|
+
item = @tenant_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,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require './state_holders/list_state_notifier'
|
4
|
+
require_relative '../ui/tenant_input_form'
|
5
|
+
require_relative 'tenant_input_form_controller_create'
|
6
|
+
require_relative 'tenant_input_form_controller_edit'
|
7
|
+
require_relative '../tenant_db_data_source'
|
8
|
+
require 'win32api'
|
9
|
+
|
10
|
+
# Класс TenantListController отвечает за управление списком
|
11
|
+
# авторов, используя различные методы для обновления данных и
|
12
|
+
# взаимодействия с пользовательским интерфейсом.
|
13
|
+
class TenantListController
|
14
|
+
|
15
|
+
attr_reader :state_notifier
|
16
|
+
|
17
|
+
def initialize(view)
|
18
|
+
LoggerHolder.instance.debug('TenantListController: initialize')
|
19
|
+
@view = view
|
20
|
+
@state_notifier = ListStateNotifier.new
|
21
|
+
@state_notifier.add_listener(@view)
|
22
|
+
@tenant_rep = TenantDbDataSource.new
|
23
|
+
|
24
|
+
@sort_columns = %w[TenantID FirstName LastName Phone]
|
25
|
+
@sort_by = @sort_columns.first
|
26
|
+
|
27
|
+
@phone_filter_columns = [nil, true, false]
|
28
|
+
@phone_filter = @phone_filter_columns.first
|
29
|
+
end
|
30
|
+
|
31
|
+
def on_view_created
|
32
|
+
# begin
|
33
|
+
# @student_rep = StudentRepository.new(DBSourceAdapter.new)
|
34
|
+
# rescue Mysql2::Error::ConnectionError
|
35
|
+
# on_db_conn_error
|
36
|
+
# end
|
37
|
+
end
|
38
|
+
|
39
|
+
def show_view
|
40
|
+
@view.create.show
|
41
|
+
end
|
42
|
+
|
43
|
+
def show_modal_add
|
44
|
+
LoggerHolder.instance.debug('TenantListController: show_modal_add')
|
45
|
+
controller = TenantInputFormControllerCreate.new(self)
|
46
|
+
view = TenantInputForm.new(controller)
|
47
|
+
controller.set_view(view)
|
48
|
+
view.create.show
|
49
|
+
end
|
50
|
+
|
51
|
+
# метод, который создает контроллер TenantInputFormControllerEdit, представление OwnerInputForm, устанавливает связи между ними и показывает модальное окно.
|
52
|
+
def show_modal_edit(current_page, per_page, selected_row)
|
53
|
+
LoggerHolder.instance.debug('TenantListController: show_modal_edit')
|
54
|
+
# item_num = (current_page - 1) * per_page + selected_row
|
55
|
+
|
56
|
+
item = @state_notifier.get(selected_row)
|
57
|
+
|
58
|
+
controller = TenantInputFormControllerEdit.new(self, item)
|
59
|
+
view = TenantInputForm.new(controller)
|
60
|
+
controller.set_view(view)
|
61
|
+
view.create.show
|
62
|
+
end
|
63
|
+
|
64
|
+
# метод, который получает выбранный элемент из state_notifier, удаляет его из базы данных и из state_notifier
|
65
|
+
def delete_selected(current_page, per_page, selected_row)
|
66
|
+
LoggerHolder.instance.debug('TenantListController: delete_selected')
|
67
|
+
begin
|
68
|
+
item = @state_notifier.get(selected_row)
|
69
|
+
@tenant_rep.delete(item.tenant_id)
|
70
|
+
@state_notifier.delete(item)
|
71
|
+
rescue
|
72
|
+
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
73
|
+
api.call(0, "You cannot delete the tenant because he is associated with some car", "Error", 0)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# етод, который получает список авторов из базы данных, устанавливает их в state_notifier и обновляет пользовательский интерфейс
|
78
|
+
def refresh_data(page, per_page)
|
79
|
+
# begin
|
80
|
+
# @data_list = @student_rep.paginated_short_students(page, per_page, @data_list)
|
81
|
+
# @view.update_student_count(@student_rep.student_count)
|
82
|
+
# rescue
|
83
|
+
# on_db_conn_error
|
84
|
+
# end
|
85
|
+
items = @tenant_rep.get_list(per_page, page, @sort_by, 'ASC', @phone_filter)
|
86
|
+
@state_notifier.set_all(items)
|
87
|
+
@view.update_count(@tenant_rep.count)
|
88
|
+
end
|
89
|
+
|
90
|
+
def sort(page, per_page, sort_index)
|
91
|
+
@sort_by = @sort_columns[sort_index]
|
92
|
+
refresh_data(page, per_page)
|
93
|
+
end
|
94
|
+
|
95
|
+
def filter_phone(page, per_page, filter_index)
|
96
|
+
@phone_filter = @phone_filter_columns[filter_index]
|
97
|
+
refresh_data(page, per_page)
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def on_db_conn_error
|
103
|
+
api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
|
104
|
+
api.call(0, "No connection to DB", "Error", 0)
|
105
|
+
exit(false)
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'mysql2'
|
2
|
+
require_relative '../lib/data_sources/lient'
|
3
|
+
|
4
|
+
class TenantDbDataSource
|
5
|
+
def initialize
|
6
|
+
@client = DBClient.instance
|
7
|
+
end
|
8
|
+
|
9
|
+
# def add(tenant)
|
10
|
+
# query = "INSERT INTO Owner (FirstName, LastName, FatherName) VALUES ('#{tenant.first_name}', '#{tenant.last_name}', #{tenant.father_name.nil? ? 'NULL' : "'#{tenant.father_name}'"})"
|
11
|
+
# @client.query(query)
|
12
|
+
# end
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
# добавляет нового автора в базу данных, возвращает созданную запись.
|
17
|
+
def add(tenant)
|
18
|
+
query = "INSERT INTO Tenant (FirstName, LastName, FatherName) VALUES ('#{tenant.first_name}', '#{tenant.last_name}', #{tenant.phone.nil? ? 'NULL' : "'#{tenant.phone}'"})"
|
19
|
+
@client.query(query)
|
20
|
+
tenant_id = @client.last_id
|
21
|
+
get(tenant_id)
|
22
|
+
end
|
23
|
+
|
24
|
+
# изменяет данные об авторе в базе данных, возвращает измененную запись.
|
25
|
+
def change(tenant)
|
26
|
+
query = "UPDATE Tenant SET FirstName='#{tenant.first_name}', LastName='#{tenant.last_name}', Phone=#{tenant.phone.nil? ? 'NULL' : "'#{tenant.phone}'"} WHERE tenantID=#{tenant.tenant_id}"
|
27
|
+
@client.query(query)
|
28
|
+
get(tenant.tenant_id)
|
29
|
+
end
|
30
|
+
|
31
|
+
# удаляет запись об авторе из базы данных.
|
32
|
+
def delete(id)
|
33
|
+
query = "DELETE FROM Tenant WHERE tenantID=#{id}"
|
34
|
+
@client.query(query)
|
35
|
+
end
|
36
|
+
|
37
|
+
# возвращает запись об авторе по заданному id.
|
38
|
+
def get(id)
|
39
|
+
query = "SELECT * FROM Tenant WHERE tenantID=#{id}"
|
40
|
+
result = @client.query(query).first
|
41
|
+
if result
|
42
|
+
Tenant.new(result[:'TenantID'], result[:'FirstName'], result[:'LastName'], result[:'Phone'])
|
43
|
+
else
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# def get_list(page_size, page_num, sort_field, sort_direction)
|
49
|
+
# offset = (page_num - 1) * page_size
|
50
|
+
# query = "SELECT * FROM Owner ORDER BY #{sort_field} #{sort_direction} LIMIT #{page_size} OFFSET #{offset}"
|
51
|
+
# results = @client.query(query)
|
52
|
+
#
|
53
|
+
# tenants = []
|
54
|
+
# results.each do |result|
|
55
|
+
# tenants << Owner.new(result[:'tenantID'], result[:'FirstName'], result[:'LastName'], result[:'FatherName'])
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# tenants
|
59
|
+
# end
|
60
|
+
|
61
|
+
# возвращает список авторов с учетом фильтра по наличию отчества и сортировки, позволяет задавать количество элементов на странице и номер страницы.
|
62
|
+
def get_list(page_size, page_num, sort_field, sort_direction, has_phone = nil)
|
63
|
+
offset = (page_num - 1) * page_size
|
64
|
+
query = "SELECT * FROM Tenant"
|
65
|
+
|
66
|
+
if has_phone == true
|
67
|
+
query += " WHERE Phone IS NOT NULL"
|
68
|
+
elsif has_phone == false
|
69
|
+
query += " WHERE Phone IS NULL"
|
70
|
+
end
|
71
|
+
|
72
|
+
query += " ORDER BY #{sort_field} #{sort_direction} LIMIT #{page_size} OFFSET #{offset}"
|
73
|
+
results = @client.query(query)
|
74
|
+
|
75
|
+
tenants = []
|
76
|
+
results.each do |result|
|
77
|
+
tenants << Tenant.new(result[:'TenantID'], result[:'FirstName'], result[:'LastName'], result[:'Phone'])
|
78
|
+
end
|
79
|
+
|
80
|
+
tenants
|
81
|
+
end
|
82
|
+
|
83
|
+
# возвращает количество записей об авторах в базе данных.
|
84
|
+
def count
|
85
|
+
query = "SELECT COUNT(*) FROM Tenant"
|
86
|
+
result = @client.query(query).first
|
87
|
+
|
88
|
+
result[:'COUNT(*)']
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'glimmer-dsl-libui'
|
4
|
+
require_relative '../controllers/tenant_input_form_controller_create'
|
5
|
+
require './models/tenant'
|
6
|
+
require 'win32api'
|
7
|
+
|
8
|
+
class TenantInputForm
|
9
|
+
include Glimmer
|
10
|
+
|
11
|
+
def initialize(controller, existing_student = nil)
|
12
|
+
@item = existing_student.to_hash unless existing_student.nil?
|
13
|
+
@controller = controller
|
14
|
+
@entries = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def on_create
|
18
|
+
@controller.on_view_created
|
19
|
+
end
|
20
|
+
|
21
|
+
def create
|
22
|
+
@root_container = window('Арендатор', 300, 70) {
|
23
|
+
resizable false
|
24
|
+
|
25
|
+
vertical_box {
|
26
|
+
@student_form = form {
|
27
|
+
stretchy false
|
28
|
+
|
29
|
+
fields = [[:first_name, 'Имя арендатора'], [:last_name, 'Фамилия арендатора'], [:phone, 'Номер телефона']]
|
30
|
+
|
31
|
+
fields.each do |field|
|
32
|
+
@entries[field[0]] = entry {
|
33
|
+
label field[1]
|
34
|
+
}
|
35
|
+
end
|
36
|
+
}
|
37
|
+
|
38
|
+
button('Сохранить') {
|
39
|
+
stretchy false
|
40
|
+
|
41
|
+
on_clicked {
|
42
|
+
values = @entries.transform_values { |v| v.text.force_encoding("utf-8").strip }
|
43
|
+
values.transform_values! { |v| v.empty? ? nil : v}
|
44
|
+
|
45
|
+
@controller.process_fields(values)
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
49
|
+
}
|
50
|
+
on_create
|
51
|
+
@root_container
|
52
|
+
end
|
53
|
+
|
54
|
+
def set_value(field, value)
|
55
|
+
return unless @entries.include?(field)
|
56
|
+
|
57
|
+
@entries[field].text = value
|
58
|
+
end
|
59
|
+
|
60
|
+
def make_readonly(*fields)
|
61
|
+
fields.each do |field|
|
62
|
+
@entries[field].read_only = true
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def close
|
67
|
+
@root_container.destroy
|
68
|
+
end
|
69
|
+
end
|