hatio-core 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +28 -0
  4. data/Rakefile +6 -0
  5. data/lib/generators/hatio/bundle/USAGE +68 -0
  6. data/lib/generators/hatio/bundle/bundle_generator.rb +100 -0
  7. data/lib/generators/hatio/bundle/templates/04_seed_entities.rb +9 -0
  8. data/lib/generators/hatio/bundle/templates/05_seed_common_codes.rb +8 -0
  9. data/lib/generators/hatio/bundle/templates/06_seed_menus.rb +6 -0
  10. data/lib/generators/hatio/bundle/templates/Controller.js +24 -0
  11. data/lib/generators/hatio/bundle/templates/Gemfile +4 -0
  12. data/lib/generators/hatio/bundle/templates/LICENSE.txt +22 -0
  13. data/lib/generators/hatio/bundle/templates/README.md +29 -0
  14. data/lib/generators/hatio/bundle/templates/Rakefile +1 -0
  15. data/lib/generators/hatio/bundle/templates/engine.rb +7 -0
  16. data/lib/generators/hatio/bundle/templates/gemspec +19 -0
  17. data/lib/generators/hatio/bundle/templates/index.js +14 -0
  18. data/lib/generators/hatio/bundle/templates/init.rb +1 -0
  19. data/lib/generators/hatio/bundle/templates/lib_bundle.rb +12 -0
  20. data/lib/generators/hatio/bundle/templates/locale.js +13 -0
  21. data/lib/generators/hatio/bundle/templates/locales.yml +27 -0
  22. data/lib/generators/hatio/bundle/templates/pluggable_spot.rb +3 -0
  23. data/lib/generators/hatio/bundle/templates/routes.rb +3 -0
  24. data/lib/generators/hatio/bundle/templates/seeds.rb +4 -0
  25. data/lib/generators/hatio/bundle/templates/task.rake +4 -0
  26. data/lib/generators/hatio/bundle/templates/test.rb +8 -0
  27. data/lib/generators/hatio/bundle/templates/test_helper.rb +3 -0
  28. data/lib/generators/hatio/bundle/templates/version.rb +3 -0
  29. data/lib/generators/hatio/resource_api/resource_api_generator.rb +92 -0
  30. data/lib/generators/hatio/resource_api/templates/controller.rb +7 -0
  31. data/lib/generators/hatio/resource_api/templates/create.json.jbuilder +1 -0
  32. data/lib/generators/hatio/resource_api/templates/destroy.json.jbuilder +1 -0
  33. data/lib/generators/hatio/resource_api/templates/index.json.jbuilder +1 -0
  34. data/lib/generators/hatio/resource_api/templates/migration.rb +1 -0
  35. data/lib/generators/hatio/resource_api/templates/model.rb +3 -0
  36. data/lib/generators/hatio/resource_api/templates/show.json.jbuilder +3 -0
  37. data/lib/generators/hatio/resource_api/templates/update.json.jbuilder +2 -0
  38. data/lib/generators/hatio/resource_model/resource_model_generator.rb +52 -0
  39. data/lib/generators/hatio/resource_model/templates/migration.rb +1 -0
  40. data/lib/generators/hatio/resource_model/templates/model.rb +3 -0
  41. data/lib/generators/hatio/resource_view/USAGE +16 -0
  42. data/lib/generators/hatio/resource_view/resource_view_generator.rb +154 -0
  43. data/lib/generators/hatio/resource_view/templates/Model.js +19 -0
  44. data/lib/generators/hatio/resource_view/templates/Store.js +34 -0
  45. data/lib/generators/hatio/resource_view/templates/detail/Controller.js +81 -0
  46. data/lib/generators/hatio/resource_view/templates/detail/DetailForm.js +17 -0
  47. data/lib/generators/hatio/resource_view/templates/detail/DetailMain.js +26 -0
  48. data/lib/generators/hatio/resource_view/templates/detail/DetailPopup.js +25 -0
  49. data/lib/generators/hatio/resource_view/templates/detail/PopupController.js +90 -0
  50. data/lib/generators/hatio/resource_view/templates/detail/ViewController.js +78 -0
  51. data/lib/generators/hatio/resource_view/templates/item/Controller.js +81 -0
  52. data/lib/generators/hatio/resource_view/templates/item/ItemForm.js +19 -0
  53. data/lib/generators/hatio/resource_view/templates/item/ItemMain.js +18 -0
  54. data/lib/generators/hatio/resource_view/templates/item/ItemPopup.js +25 -0
  55. data/lib/generators/hatio/resource_view/templates/item/PopupController.js +90 -0
  56. data/lib/generators/hatio/resource_view/templates/item/ViewController.js +47 -0
  57. data/lib/generators/hatio/resource_view/templates/list/Controller.js +36 -0
  58. data/lib/generators/hatio/resource_view/templates/list/ListGrid.js +10 -0
  59. data/lib/generators/hatio/resource_view/templates/list/ListMain.js +20 -0
  60. data/lib/generators/hatio/resource_view/templates/list/ListSearch.js +9 -0
  61. data/lib/generators/hatio/resource_view/templates/report/Controller.js +53 -0
  62. data/lib/generators/hatio/resource_view/templates/report/ReportList.js +27 -0
  63. data/lib/generators/hatio/resource_view/templates/report/ReportMain.js +18 -0
  64. data/lib/generators/hatio/resource_view/templates/report/ReportSearch.js +9 -0
  65. data/lib/generators/hatio/util/api_util.rb +97 -0
  66. data/lib/generators/hatio/util/migration_util.rb +178 -0
  67. data/lib/generators/hatio/util/model_util.rb +77 -0
  68. data/lib/generators/hatio/util/report_view_util.rb +32 -0
  69. data/lib/generators/hatio/util/resource_view_util.rb +383 -0
  70. data/lib/generators/hatio/util/view_util.rb +214 -0
  71. data/lib/hatio-core.rb +33 -0
  72. data/lib/hatio-core/action_controller/search_helper.rb +332 -0
  73. data/lib/hatio-core/active_record/extension_logic.rb +36 -0
  74. data/lib/hatio-core/active_record/rem_tracker.rb +35 -0
  75. data/lib/hatio-core/active_record/stringified_id.rb +75 -0
  76. data/lib/hatio-core/active_record/stripper.rb +37 -0
  77. data/lib/hatio-core/active_record/userstamp.rb +48 -0
  78. data/lib/hatio-core/birt/birt_report.rb +42 -0
  79. data/lib/hatio-core/bundle/hatio_bundle.rb +37 -0
  80. data/lib/hatio-core/engine.rb +5 -0
  81. data/lib/hatio-core/exception/exceptions.rb +33 -0
  82. data/lib/hatio-core/patch/actionpack_hatio_patch.rb +28 -0
  83. data/lib/hatio-core/patch/date.rb +11 -0
  84. data/lib/hatio-core/patch/string_key.rb +56 -0
  85. data/lib/hatio-core/pluggable/pluggable_spot.rb +22 -0
  86. data/lib/hatio-core/util/hatio_util.rb +106 -0
  87. data/lib/hatio-core/version.rb +3 -0
  88. data/lib/tasks/hatiocore_tasks.rake +75 -0
  89. data/lib/utils/detect_invalid_js_format.rb +0 -0
  90. data/lib/utils/detect_mismatch_tags.rb +57 -0
  91. data/lib/utils/update_license.rb +5 -0
  92. data/lib/utils/upload_locale.rb +67 -0
  93. metadata +148 -0
@@ -0,0 +1,214 @@
1
+ module Hatio
2
+ module Generators
3
+ class ViewUtil
4
+
5
+ #
6
+ # columns 정보로 부터 그리드를 생성
7
+ #
8
+ def self.generate_grid(singularName, columns, options, indent)
9
+ output = "columns : [\n"
10
+ indent = "\t\t" unless indent
11
+
12
+ output << "#{indent}{ dataIndex : '_cud_flag_', hidden : true, value : '' },\n"
13
+
14
+ columns.each do |col|
15
+ if(col.name == 'id')
16
+ output << "#{indent}{ header : T('label.id'), dataIndex : 'id', hidden : true },\n"
17
+ elsif(col.name == 'name')
18
+ output << "#{indent}{ header : T('label.name'), dataIndex : 'name', editor : { xtype : 'textfield', allowBlank : false } },\n"
19
+ elsif(col.name == 'description')
20
+ output << "#{indent}{ header : T('label.description'), dataIndex : 'description', editor : { xtype : 'textfield', allowBlank : true } },\n"
21
+ elsif(col.name == 'domain_id' || col.name == 'creator_id' || col.name == 'updater_id')
22
+ output << "#{indent}{ dataIndex : '#{col.name}', hidden : true },\n"
23
+ elsif(col.name == 'created_at' || col.name == 'updated_at')
24
+ output << "#{indent}{ header : T('label.#{col.name}'), dataIndex : '#{col.name}', xtype : 'datecolumn', disabled : true, format : T('format.datetime') },\n"
25
+ else
26
+ if(col.type == :string)
27
+ output << "#{indent}{ header : T('label.#{col.name}'), dataIndex : '#{col.name}', editor : { xtype : 'textfield' } },\n"
28
+ elsif(col.type == :text)
29
+ output << "#{indent}{ header : T('label.#{col.name}'), dataIndex : '#{col.name}', editor : { xtype : 'textareafield' } },\n"
30
+ elsif(col.type == :boolean)
31
+ output << "#{indent}{ header : T('label.#{col.name}'), dataIndex : '#{col.name}', xtype : 'checkcolumn' },\n"
32
+ elsif(col.type == :date)
33
+ output << "#{indent}{ header : T('label.#{col.name}'), dataIndex : '#{col.name}', editor : { xtype : 'datefield', format : T('format.date') } },\n"
34
+ elsif(col.type == :datetime)
35
+ output << "#{indent}{ header : T('label.#{col.name}'), dataIndex : '#{col.name}', editor : { xtype : 'datefield', format : T('format.datetime') } },\n"
36
+ elsif(col.type == :integer || col.type == :float || col.type == :long || col.type == :double)
37
+ output << "#{indent}{ header : T('label.#{col.name}'), dataIndex : '#{col.name}', editor : { xtype : 'numberfield' } },\n"
38
+ else
39
+ end
40
+ end
41
+ end
42
+
43
+ output << "#{indent}],\n"
44
+ output
45
+ end
46
+
47
+ #
48
+ # resource의 columns로 부터 form 정보를 생성하여 리턴
49
+ #
50
+ def self.generate_form(resourceName, columns, options, indent)
51
+ output = ""
52
+ indent = "\t\t" unless indent
53
+
54
+ columns.each do |col|
55
+
56
+ if(col.name == 'id')
57
+ output << "#{indent}{ name : 'id', fieldLabel : T('label.id'), hidden : true },\n"
58
+ elsif(col.name == 'domain_id')
59
+ output << "#{indent}{ name : 'domain_id', value : login.current_domain_id, hidden : true },\n"
60
+ elsif(col.name == 'creator_id' || col.name == 'updater_id')
61
+ # skip
62
+ elsif(col.name == 'created_at' || col.name == 'updated_at')
63
+ output << "#{indent}{ xtype : 'datefield', name : '#{col.name}', disabled : true, fieldLabel : T('label.#{col.name}'), format : T('format.datetime') },\n"
64
+ elsif(col.name == 'image_data')
65
+ output << "#{indent}{ id : '#{resourceName}-image-upload', itemId : '#{resourceName}-image-upload', xtype : 'fileuploadfield', inputType : 'file', name : 'image_upload', fieldLabel : T('label.image') }, \n"
66
+ output << "#{indent}{ xtype : 'textareafield', name : '#{col.name}', fieldLabel : T('label.data'), rows : 16, readOnly : true }, \n"
67
+ else
68
+ if(col.type == :string)
69
+ output << "#{indent}{ name : '#{col.name}', fieldLabel : T('label.#{col.name}') },\n"
70
+ elsif(col.type == :text)
71
+ output << "#{indent}{ xtype : 'textareafield', name : '#{col.name}', fieldLabel : T('label.#{col.name}') }, \n"
72
+ elsif(col.type == :boolean)
73
+ output << "#{indent}{ name : '#{col.name}', fieldLabel : T('label.#{col.name}'), xtype : 'checkboxfield', inputValue : true },\n"
74
+ elsif(col.type == :date)
75
+ output << "#{indent}{ xtype : 'datefield', name : '#{col.name}', disabled : true, fieldLabel : T('label.#{col.name}'), format : T('format.date') },\n"
76
+ elsif(col.type == :datetime)
77
+ output << "#{indent}{ xtype : 'datefield', name : '#{col.name}', disabled : true, fieldLabel : T('label.#{col.name}'), format : T('format.datetime') },\n"
78
+ elsif(col.type == :integer || col.type == :float || col.type == :long || col.type == :double)
79
+ output << "#{indent}{ name : '#{col.name}', fieldLabel : T('label.#{col.name}'), xtype : 'numberfield' },\n"
80
+ else
81
+ end
82
+ end
83
+ end
84
+
85
+ output
86
+ end
87
+
88
+ #
89
+ # columns 정보로 부터 search condition items를 생성
90
+ #
91
+ def self.generate_search_items(resourceName, columns, options, indent)
92
+ output = "items : [ \n"
93
+ indent = "\t\t" unless indent
94
+
95
+ columns.each do |col|
96
+ if(col.name == 'id' || col.name == 'domain_id' || col.name == 'creator_id' || col.name == 'updater_id')
97
+ elsif(col.name == 'created_at' || col.name == 'updated_at')
98
+ #output << "#{indent}{ fieldLabel : T('label.#{col.name}_from'), name : '#{col.name}-gte', xtype : 'datefield', format : T('format.date') },\n"
99
+ #output << "#{indent}{ fieldLabel : T('label.#{col.name}_to'), name : '#{col.name}-lte', xtype : 'datefield', format : T('format.date') },\n"
100
+ else
101
+ if(col.type == :string || col.type == :text)
102
+ output << "#{indent}{ fieldLabel : T('label.#{col.name}'), name : '#{col.name}-like' },\n"
103
+ elsif(col.type == :boolean)
104
+ output << "#{indent}{ fieldLabel : T('label.#{col.name}'), name : '#{col.name}-eq', inputValue : true, xtype : 'checkboxfield', inputValue : true },\n"
105
+ elsif(col.type == :date)
106
+ output << "#{indent}{ fieldLabel : T('label.#{col.name}_from'), name : '#{col.name}-gte', xtype : 'datefield', format : T('format.date') },\n"
107
+ output << "#{indent}{ fieldLabel : T('label.#{col.name}_to'), name : '#{col.name}-lte', xtype : 'datefield', format : T('format.date') },\n"
108
+ elsif(col.type == :datetime)
109
+ output << "#{indent}{ fieldLabel : T('label.#{col.name}_from'), name : '#{col.name}-gte', xtype : 'datefield', format : T('format.datetime') },\n"
110
+ output << "#{indent}{ fieldLabel : T('label.#{col.name}_to'), name : '#{col.name}-lte', xtype : 'datefield', format : T('format.datetime') },\n"
111
+ elsif(col.type == :integer || col.type == :float || col.type == :long || col.type == :double)
112
+ output << "#{indent}{ fieldLabel : T('label.#{col.name}'), name : '#{col.name}-eq', xtype : 'numberfield' },\n"
113
+ else
114
+ end
115
+ end
116
+ end
117
+
118
+ output << "#{indent}],\n"
119
+ output
120
+ end
121
+
122
+ #
123
+ # columns 정보로 부터 store filter 코드 생성
124
+ #
125
+ def self.generateStoreFilter(resourceName, columns, options, indent)
126
+ indent = "\t\t" unless indent
127
+ output = "store.filter([ {\n"
128
+ output << "#{indent}#{indent}property : 'domain_id-eq',\n"
129
+ output << "#{indent}#{indent}value : login.current_domain_id\n"
130
+ output << "#{indent}}, \n"
131
+
132
+ columns.each do |col|
133
+ if(col.name == 'id' || col.name == 'domain_id' || col.name == 'creator_id' || col.name == 'updater_id' || col.name == 'created_at' || col.name == 'updated_at')
134
+ elsif(col.name.end_with?('_id'))
135
+ output << "#{indent}{ \n"
136
+ output << "#{indent}#{indent}property : '#{col.name}-eq',\n"
137
+ output << "#{indent}#{indent}value : this.findItem(' \##{col.name}_filter').getValue()\n"
138
+ output << "#{indent}},\n"
139
+ else
140
+ if(col.type == :string || col.type == :text)
141
+ output << "#{indent}{ \n"
142
+ output << "#{indent}#{indent}property : '#{col.name}-like',\n"
143
+ output << "#{indent}#{indent}value : this.findItem(' \##{col.name}_filter').getValue()\n"
144
+ output << "#{indent}},\n"
145
+ elsif(col.type == :date || col.type == :datetime)
146
+ output << "#{indent}{ \n"
147
+ output << "#{indent}#{indent}property : '#{col.name}-gte',\n"
148
+ output << "#{indent}#{indent}value : this.findItem(' \##{col.name}_from_filter').getValue()\n"
149
+ output << "#{indent}},\n"
150
+ output << "#{indent}{ \n"
151
+ output << "#{indent}#{indent}property : '#{col.name}-lte',\n"
152
+ output << "#{indent}#{indent}value : this.findItem(' \##{col.name}_to_filter').getValue()\n"
153
+ output << "#{indent}},\n"
154
+ elsif(col.type == :boolean || col.type == :integer || col.type == :float || col.type == :long || col.type == :double)
155
+ output << "#{indent}{ \n"
156
+ output << "#{indent}#{indent}property : '#{col.name}-eq',\n"
157
+ output << "#{indent}#{indent}value : this.findItem(' \##{col.name}_filter').getValue()\n"
158
+ output << "#{indent}},\n"
159
+ else
160
+ end
161
+ end
162
+ end
163
+
164
+ output << "#{indent}]);\n"
165
+ output
166
+ end
167
+
168
+ #
169
+ # columns 정보로 부터 search filter를 리셋
170
+ #
171
+ def self.generateResetFilters(resourceName, columns, options, indent)
172
+ indent = "\t\t" unless indent
173
+ output = ""
174
+
175
+ columns.each do |col|
176
+ if(col.name == 'id' || col.name == 'domain_id' || col.name == 'creator_id' || col.name == 'updater_id' || col.name == 'created_at' || col.name == 'updated_at')
177
+ else
178
+ if(col.type == :string || col.type == :text)
179
+ output << "#{indent}this.findItem(' \##{col.name}_filter').setValue('');\n";
180
+ elsif(col.type == :date || col.type == :datetime)
181
+ output << "#{indent}this.findItem(' \##{col.name}_filter').setValue('');\n";
182
+ elsif(col.type == :boolean || col.type == :integer || col.type == :float || col.type == :long || col.type == :double)
183
+ output << "#{indent}this.findItem(' \##{col.name}_filter').setValue(false);\n";
184
+ else
185
+ end
186
+ end
187
+ end
188
+
189
+ output
190
+ end
191
+
192
+ #
193
+ # 새로운 model 생성
194
+ #
195
+ def self.generateNewModel(resourceName, columns, options, indent)
196
+ indent = "\t" unless indent
197
+ output = "data = data || {\n"
198
+ output << "#{indent}#{indent}#{indent}domain_id : login.current_domain_id,\n"
199
+
200
+ columns.each do |col|
201
+ if(col.name == 'domain_id' || col.name == 'creator_id' || col.name == 'updater_id' || col.name == 'created_at' || col.name == 'updated_at')
202
+ else
203
+ output << "#{indent}#{indent}#{indent}#{col.name} : '',\n"
204
+ end
205
+ end
206
+ output << "#{indent}#{indent}#{indent}_cud_flag_ : 'c'};\n"
207
+ output << "#{indent}#{indent}return Ext.create('#{options.bundle}.model.#{resourceName}', data);"
208
+ output
209
+ end
210
+
211
+ end
212
+
213
+ end
214
+ end
data/lib/hatio-core.rb ADDED
@@ -0,0 +1,33 @@
1
+ require 'hatio-core/engine'
2
+ require 'hatio-core/version'
3
+ require 'hatio-core/engine'
4
+
5
+ require 'hatio-core/pluggable/pluggable_spot'
6
+ require 'hatio-core/action_controller/search_helper'
7
+ require 'hatio-core/patch/string_key'
8
+ require 'hatio-core/patch/actionpack_hatio_patch'
9
+ require 'hatio-core/patch/date'
10
+ require 'hatio-core/active_record/stripper'
11
+ require 'hatio-core/active_record/stringified_id'
12
+ require 'hatio-core/active_record/userstamp'
13
+ require 'hatio-core/active_record/rem_tracker'
14
+ require 'hatio-core/active_record/extension_logic'
15
+ require 'hatio-core/util/hatio_util'
16
+ require 'hatio-core/bundle/hatio_bundle'
17
+ require 'hatio-core/exception/exceptions'
18
+ # require 'hatio-core/birt/birt_report'
19
+
20
+ include Hatio::Util::HatioUtil
21
+
22
+ ActiveRecord::Base.send :include, Hatio::Stripper
23
+ ActiveRecord::Base.send :include, Hatio::StringfiedID
24
+ ActiveRecord::Base.send :include, Hatio::Userstamp
25
+ ActiveRecord::Base.send :include, Hatio::RemTracker
26
+ ActiveRecord::Base.send :include, Hatio::ExtensionLogic
27
+ ActionController::Base.send :include, Hatio::SearchHelper
28
+
29
+ puts "Things Framework Loaded!"
30
+
31
+ Hatio::Bundle.new 'hatio-core', HatioCore::VERSION do |bundle|
32
+ bundle.dependencies = []
33
+ end
@@ -0,0 +1,332 @@
1
+ module Hatio
2
+ module SearchHelper
3
+
4
+ #
5
+ # 검색 조건, 소트 조건, Pagination 조건을 분석하여 검색을 구현
6
+ #
7
+ def search_filter resource, options = {}
8
+ # pagination 정보는 넘어온 page, limit 정보를 이용
9
+ page, limit, offset = find_pagination_info
10
+ search_param_type, search_params = nil, nil
11
+
12
+ # search parameter는 filter or _q 파라미터를 이용
13
+ if(!params[:_q].blank?)
14
+ search_param_type, search_params = 1, params[:_q]
15
+ elsif(!params[:filter].blank?)
16
+ search_param_type, search_params = 2, params[:filter]
17
+ else
18
+ search_param_type, search_params = 1, params
19
+ end
20
+
21
+ # sort parameter는 sort or _o 파라미터를 이용
22
+ sort_type, sort_params, order_result = nil, nil, ""
23
+ if(!params[:_o].blank?)
24
+ sort_type, sort_params = 1, params[:_o]
25
+ elsif(!params[:sort].blank?)
26
+ sort_type, sort_params = 2, params[:sort]
27
+ end
28
+
29
+ # table name을 찾고 where 조건의 컬럼명 앞에 table_name.을 붙인다. Join 쿼리를 사용 할 경우 애매한 열 정의를 없애기 위함
30
+ table_name = options.key?(:table_name) ? options[:table_name] : resource.table_name
31
+ entity = Entity.find_by_name(resource.to_s)
32
+ if(entity)
33
+ columns = entity.columns_for_search
34
+ # select fields는 select parameter가 있으면 select parameter를, 없으면 select *
35
+ list_columns = find_select_columns(columns)
36
+
37
+ if(search_param_type == 1)
38
+ conditions = build_conditions_by_search_params(table_name, search_params, columns)
39
+ elsif(search_param_type == 2)
40
+ conditions = build_conditions_by_filters(table_name, search_params, columns)
41
+ end
42
+
43
+ # select parameter로 association이 있는 부분을 찾아서 ...
44
+ include_arr = find_association_list(resource, list_columns, options)
45
+ order_result = (sort_type == 1) ? build_orders_by_sort_params(sort_params) : build_orders_by_sorters(sort_params) if(sort_type)
46
+ return conditions, include_arr, order_result, limit, offset
47
+ else
48
+ debug_print "Not found Entity of resource [#{resource.to_s}]"
49
+ return "", [], "", limit, offset
50
+ end
51
+ end
52
+
53
+ #
54
+ # select fields를 찾는다. select 파라미터가 넘어오면 해당 필드만, 그렇지 않으면 모든 필드가 select 대상이다.
55
+ #
56
+ def find_select_columns(columns)
57
+ select_columns = (!params[:_s] || params[:_s].blank?) ? [] : params[:_s]
58
+ return select_columns.empty? ?
59
+ columns :
60
+ columns.select{ |c| select_columns.include?(c.name) || select_columns.include?(c.name.sub(/_id$/, '')) }
61
+ end
62
+
63
+ #
64
+ # 필드 타입 정보를 바탕으로 검색 조건 값을 sql에 맞게 변환한다.
65
+ #
66
+ def convert_value_by_col_type(filter_value, column)
67
+ if(column.col_type == 'time' || column.col_type == 'datetime' || column.col_type == 'timestamp')
68
+ return (filter_value.size <= 10) ? parse_date(filter_value) : parse_time_to_db(filter_value)
69
+ elsif(column.col_type == 'date')
70
+ return parse_date(filter_value)
71
+ elsif(column.col_type == 'boolean')
72
+ return (filter_value.to_s =~ /^(t|true|on|y|yes)$/i) == 0 ? true : false
73
+ else
74
+ return filter_value
75
+ end
76
+ end
77
+
78
+ #
79
+ # like 타입 검색 조건이면 like 검색을 위해서 검색 조건 값을 like문에 맞게 변환한다.
80
+ #
81
+ def convert_like_type_condition_value(operator, value)
82
+ return value unless like_type_operator?(operator)
83
+ value = value.strip
84
+
85
+ case operator
86
+ when 'like' # like
87
+ return "%#{value}%"
88
+ when 'contains' # equals to like
89
+ return "%#{value}%"
90
+ when 'nlike' # not like
91
+ return "%#{value}%"
92
+ when 'sw' # starts with
93
+ return "#{value}%"
94
+ when 'dnsw' # does not start with
95
+ return "#{value}%"
96
+ when 'ew' # ends with
97
+ return "%#{value}"
98
+ when 'dnew' # does not end with
99
+ return "%#{value}"
100
+ when 'in'
101
+ val_arr = value.split(",")
102
+ return val_arr;
103
+ when 'notin'
104
+ val_arr = value.split(",")
105
+ return val_arr;
106
+ end
107
+ end
108
+
109
+ #
110
+ # 검색 조건 중에 검색 조건 값이 필요 없는 검색 조건인지 판단한다.
111
+ #
112
+ def none_value_operator?(operator)
113
+ ['is_null', 'is_not_null', 'is_true', 'is_false', 'is_present', 'is_blank'].include?(operator)
114
+ end
115
+
116
+ #
117
+ # 검색 조건 중에 like 타입의 조건인지를 판단한다.
118
+ #
119
+ def like_type_operator?(operator)
120
+ ['like', 'contains', 'nlike', 'sw', 'dnsw', 'ew', 'dnew', 'in', 'notin'].include?(operator)
121
+ end
122
+
123
+ #
124
+ # 검색 조건 타입에 따라 sql where 문을 작성한다.
125
+ #
126
+ def get_condition_str(table_name, column_name, operator)
127
+ case operator
128
+ when 'eq' # equal
129
+ return " #{table_name}.#{column_name} = ?"
130
+ when 'noteq' # not equal
131
+ return " #{table_name}.#{column_name} != ?"
132
+ when 'in' # in
133
+ return " #{table_name}.#{column_name} in (?)"
134
+ when 'notin' # not in
135
+ return " #{table_name}.#{column_name} not in (?)"
136
+ when 'like', 'contains', 'sw', 'ew' # like
137
+ return " lower(#{table_name}.#{column_name}) like lower(?)"
138
+ when 'nlike', 'dnsw', 'dnew' # not like
139
+ return " lower(#{table_name}.#{column_name}) not like lower(?)"
140
+ when 'gt' # greater than
141
+ return " #{table_name}.#{column_name} > ?"
142
+ when 'gte' # greater than equal
143
+ return " #{table_name}.#{column_name} >= ?"
144
+ when 'lt' # less than
145
+ return " #{table_name}.#{column_name} < ?"
146
+ when 'lte' # less than equal
147
+ return " #{table_name}.#{column_name} <= ?"
148
+
149
+ when 'dt_eq' # date equal
150
+ return " #{GlobalConfig.to_date_db_func}(#{table_name}.#{column_name}) = ?"
151
+ when 'dt_noteq' # date not equal
152
+ return " #{GlobalConfig.to_date_db_func}(#{table_name}.#{column_name}) != ?"
153
+ when 'dt_gt' # date greater than
154
+ return " #{GlobalConfig.to_date_db_func}(#{table_name}.#{column_name}) > ?"
155
+ when 'dt_gte' # date greater than equal
156
+ return " #{GlobalConfig.to_date_db_func}(#{table_name}.#{column_name}) >= ?"
157
+ when 'dt_lt' # date less than
158
+ return " #{GlobalConfig.to_date_db_func}(#{table_name}.#{column_name}) < ?"
159
+ when 'dt_lte' # date less than equal
160
+ return " #{GlobalConfig.to_date_db_func}(#{table_name}.#{column_name}) <= ?"
161
+
162
+ when 'is_null' # is null
163
+ return " #{table_name}.#{column_name} is null"
164
+ when 'is_not_null' # is not null
165
+ return " #{table_name}.#{column_name} is not null"
166
+ when 'is_true' # is true
167
+ return " #{table_name}.#{column_name} = true"
168
+ when 'is_false' # is false
169
+ return " #{table_name}.#{column_name} = false"
170
+ when 'is_present' # not null or not empty string
171
+ return " (#{table_name}.#{column_name} is not null and #{table_name}.#{column_name} != '')"
172
+ when 'is_blank' # null or empty string
173
+ return " (#{table_name}.#{column_name} is null or #{table_name}.#{column_name} = '')"
174
+ end
175
+ return "";
176
+ end
177
+
178
+ #
179
+ # filter로 search condition 정보 생성
180
+ #
181
+ def build_conditions_by_filters(table_name, filter_str, columns)
182
+ # filter_str을 파싱하여 filter 오브젝트로 변환
183
+ filters, where_sql_arr, conditions = JSON.parse(filter_str), ["#{table_name}.id is not null"], []
184
+ filters.each do |filter|
185
+ # filter의 name, value으로 validation check
186
+ filter_name, filter_value, operator = validate_filter_info(columns, filter['property'], filter['value'])
187
+ # valid 하지 않으면 처리하지 않는다.
188
+ next unless filter_name
189
+ # 검색조건 필드명이 entity_column에 등록되어 있는 경우에는 entity_column에서 필드 타입을 찾아 알맞은 타입으로 조건 값을 변경
190
+ entity_column = columns.find { |c| c.name == filter_name } if columns
191
+ filter_value = convert_value_by_col_type(filter_value, entity_column) if entity_column
192
+ # like 타입이라면 검색 조건이라면 like문에 맞게 값에 조건문을 수정한다. (like, not like)
193
+ where_sql_arr << get_condition_str(table_name, filter_name, operator)
194
+ # like 타입이라면 검색 조건이라면 like문에 맞게 값에 %를 붙인다. ('%찾을 문자열%', '%찾을 문자열', '찾을 문자열%')
195
+ filter_value = convert_like_type_condition_value(operator, filter_value)
196
+ #debug_print("Filter : #{filter_name}, Value : #{filter_value}, Operator : #{operator}")
197
+ # 하나의 필드에 대한 조건 값을 conditions 배열에 추가한다.
198
+ conditions.push(filter_value) unless none_value_operator?(operator)
199
+ end
200
+ # 최종적으로 만들어진 sql where문을 conditions 배열 맨 앞쪽에 추가한다.
201
+ conditions.insert(0, where_sql_arr.join(" and "))
202
+ end
203
+
204
+ #
205
+ # search params로 search condition 정보 생성
206
+ #
207
+ def build_conditions_by_search_params(table_name, search_params, columns)
208
+ where_sql_arr, conditions = ["#{table_name}.id is not null"], []
209
+ # 넘어온 검색 조건 값을 - 로 구분하여 앞 부분은 검색 조건 필드명으로, 뒷 부분은 검색을 위한 operator로 사용햔다.
210
+ search_params.each do |param_name, param_value|
211
+ # filter의 name, value으로 validation check
212
+ filter_name, filter_value, operator = validate_filter_info(columns, param_name, param_value)
213
+ # valid 하지 않으면 처리하지 않는다.
214
+ next unless filter_name
215
+ # 검색조건 필드명이 entity_column에 등록되어 있는 경우에는 entity_column에서 필드 타입을 찾아 알맞은 타입으로 조건 값을 변경
216
+ entity_column = columns.find { |c| c.name == filter_name } if columns
217
+ filter_value = convert_value_by_col_type(filter_value, entity_column) if entity_column
218
+ # like 타입이라면 검색 조건이라면 like문에 맞게 값에 조건문을 수정한다. (like, not like)
219
+ where_sql_arr << get_condition_str(table_name, filter_name, operator)
220
+ # like 타입이라면 검색 조건이라면 like문에 맞게 값에 %를 붙인다. ('%찾을 문자열%', '%찾을 문자열', '찾을 문자열%')
221
+ filter_value = convert_like_type_condition_value(operator, filter_value)
222
+ #debug_print("Filter : #{filter_name}, Value : #{filter_value}, Operator : #{operator}")
223
+ # 하나의 필드에 대한 조건 값을 conditions 배열에 추가한다.
224
+ conditions.push(filter_value) unless none_value_operator?(operator)
225
+ end
226
+ conditions.insert(0, where_sql_arr.join(" and "))
227
+ end
228
+
229
+ #
230
+ # filter 정보를 validation한다.
231
+ #
232
+ def validate_filter_info(columns, filter_name, filter_value)
233
+ # filter_name이 domain_id라면 스킵
234
+ return false if(filter_name.start_with?('domain_id'))
235
+ gubunIndex = filter_name.rindex('-')
236
+ filter_name_length = filter_name.length
237
+ # - 로 구분된 문자열이 없다면 조건 검색을 위한 용도가 아니라고 판단
238
+ return false unless gubunIndex
239
+ # operator는 무조건 두 글자 이상이어야 한다.
240
+ return false unless (filter_name_length - gubunIndex > 1)
241
+ # 넘어온 검색 조건 값을 - 로 구분하여 앞 부분은 검색 조건 필드명으로, 뒷 부분은 검색을 위한 operator로 사용햔다.
242
+ column_name, operator = filter_name[0 .. (gubunIndex - 1)], filter_name[(gubunIndex + 1) .. (filter_name_length - 1)]
243
+ # resource.name-eq 형식으로 넘어온 경우는 Resource.find_by_name으로 검색하고 파라미터 명은 resource_id-eq형식으로 변환한다.
244
+ column_name, filter_value, operator = convert_reference_filter(column_name, filter_value, operator)
245
+ # 값이 비어 있고 조건 값이 필요없는 경우 ('is_null', 'is_not_null', 'is_true', 'is_false', 'is_present', 'is_blank')가 아니면 스킵
246
+ return false if (filter_value.blank? && !none_value_operator?(operator))
247
+ return false unless (include_entity_column?(columns, column_name))
248
+ return column_name, filter_value, operator
249
+ end
250
+
251
+ #
252
+ # filter name이 entity column내에 속해 있는지 확인한다.
253
+ #
254
+ def include_entity_column?(columns, filter_name)
255
+ fc = columns.find { |column| column.name == filter_name }
256
+ return !fc.nil?
257
+ end
258
+
259
+ #
260
+ # resource.name-eq 형식으로 넘어온 파라미터는 Resource.find_by_name(파라미터 값)으로 검색하여 id를 찾아 값을 대치하고 파라미터 명도 resource_id-eq로 대치
261
+ # TODO operator가 like 였을 경우 join query가 되어야 하고 파라미터 값은 join table의 검색 조건으로 변경되어야 한다.
262
+ #
263
+ def convert_reference_filter(column_name, filter_value, operator)
264
+ column_name_arr = column_name.split('.')
265
+ return column_name, filter_value, operator if(column_name_arr.size <= 1 || filter_value.blank?)
266
+
267
+ # 새로운 컬럼명 : {entityname}_id
268
+ new_column_name = "#{column_name_arr[0]}_id"
269
+ if(column_name_arr[1] == 'id')
270
+ return new_column_name, filter_value, operator
271
+ else
272
+ resource = column_name_arr[0].camelcase.constantize
273
+ conds = { column_name_arr[1].to_sym => filter_value }
274
+ #conds[:domain_id] = @domain.id if(@domain.respond_to?(resource.name.pluralize.to_sym))
275
+ instance = resource.where(conds).first
276
+ return new_column_name, (instance ? instance.id : ''), operator
277
+ end
278
+ end
279
+
280
+ #
281
+ # 넘어온 sort 정보로 부터 sort정보를 추출 - "[{"property":"name","direction":"DESC"}]"
282
+ #
283
+ def build_orders_by_sort_params(orders)
284
+ return (orders && !orders.empty?) ? orders.collect { |name, direction| "#{name} #{direction}"}.join(",") : ""
285
+ end
286
+
287
+ #
288
+ # 넘어온 sort parameter 정보로 부터 sort정보를 추출
289
+ #
290
+ def build_orders_by_sorters(sorter_str)
291
+ order_result = ""
292
+ if(sorter_str && !sorter_str.blank?)
293
+ sorters = JSON.parse(sorter_str)
294
+ order_result = sorters.collect { |sorter| "#{sorter['property']} #{sorter['direction']}" }.join(",")
295
+ end
296
+ return order_result
297
+ end
298
+
299
+ #
300
+ # params로 부터 pagination을 위한 정보를 추출한다.
301
+ #
302
+ def find_pagination_info
303
+ page = (params[:page] || 1).to_i
304
+ limit = (params[:limit] || GlobalConfig.default_page_size).to_i
305
+ offset = (page - 1) * limit
306
+ return page, limit, offset
307
+ end
308
+
309
+ #
310
+ # resource의 entity_columns 정보 중 select 필드를 바탕으로 관계 정보를 추출한다.
311
+ #
312
+ def find_association_list(resource, columns, options = {})
313
+ ref_columns = columns.select { |c| c.name != "domain_id" && c.ref_type == "Entity" && c.ref_name }
314
+ return ref_columns.collect do |column|
315
+ association_symbol = column.name.sub(/_id$/, '').to_sym
316
+ association = resource.reflect_on_association association_symbol
317
+ if association
318
+ association_symbol unless association.options[:polymorphic] == true
319
+ else
320
+ association = resource.reflect_on_all_associations.detect { |a| a.options[:foreign_key] == column.name.to_sym }
321
+ if association
322
+ association.name.to_sym
323
+ else
324
+ association = resource.reflect_on_all_associations.detect { |a| a.options[:class_name] == column.ref_name }
325
+ association.name.to_sym if association
326
+ end
327
+ end
328
+ end.compact
329
+ end
330
+
331
+ end
332
+ end