From b33c2d5b3828095f5205fb6c5b5202caf47400e2 Mon Sep 17 00:00:00 2001 From: spen Date: Mon, 13 Oct 2014 14:27:01 +0800 Subject: [PATCH] Excel Import Members --- Gemfile | 5 + app/views/admin/members/_side_bar.html.erb | 1 + .../admin/members/download_export.xlsx.axlsx | 160 ++++++++++++++++++ .../admin/members/import_error_msg.html.erb | 14 ++ .../admin/members/import_members.html.erb | 45 +++++ config/environment.rb | 159 ++++++++++++++++- config/locales/en.yml | 9 + config/locales/zh_tw.yml | 9 + config/routes.rb | 5 +- 9 files changed, 405 insertions(+), 2 deletions(-) create mode 100644 app/views/admin/members/download_export.xlsx.axlsx create mode 100644 app/views/admin/members/import_error_msg.html.erb create mode 100644 app/views/admin/members/import_members.html.erb diff --git a/Gemfile b/Gemfile index e8522d1..9bef8cc 100644 --- a/Gemfile +++ b/Gemfile @@ -46,6 +46,11 @@ gem 'zhconv' gem 'execjs' gem 'therubyracer' +#excel +gem 'axlsx_rails' +gem 'spreadsheet' +gem 'rubyXL' + #form helpers gem 'dynamic_form' diff --git a/app/views/admin/members/_side_bar.html.erb b/app/views/admin/members/_side_bar.html.erb index e03ed7f..c5de6cb 100644 --- a/app/views/admin/members/_side_bar.html.erb +++ b/app/views/admin/members/_side_bar.html.erb @@ -32,6 +32,7 @@ <%= content_tag :li, link_to((content_tag(:span, t(:add_member))), new_admin_member_path), :class => active_for_action('members', 'new') if (current_user.is_admin? rescue nil) %> <%= content_tag :li, link_to((content_tag(:span, t(:member_role))),admin_roles_path ), :class => active_for_action('roles', 'index') if (current_user.is_admin? rescue nil) %> <%= content_tag :li, link_to((content_tag(:span, t(:member_info))), admin_member_infos_path), :class => active_for_action('member_infos', 'index') if (current_user.is_admin? rescue nil) %> + <%= content_tag :li, link_to((content_tag(:span, t("site.import_member_data.import_members"))), admin_members_import_members_path), :class => active_for_action('import_members', 'index') if (current_user.is_admin? rescue nil) %> <%= content_tag :li, link_to((content_tag(:span, t(:unapproved_members) + " (" + User.unapproved.count.to_s + ")")), admin_members_unapproved_members_path), :class => active_for_action('members', 'unapproved_members') if (current_user.is_admin? rescue nil) %> <% end -%> diff --git a/app/views/admin/members/download_export.xlsx.axlsx b/app/views/admin/members/download_export.xlsx.axlsx new file mode 100644 index 0000000..ac01ea3 --- /dev/null +++ b/app/views/admin/members/download_export.xlsx.axlsx @@ -0,0 +1,160 @@ +# encoding: utf-8 + +wb = xlsx_package.workbook +wb.add_worksheet(name: "Member") do |sheet| + + row = [ "user_id", "password" ] + row2 = ["#{t("users.user_id")}(#{t("users.user_id_note")})", "#{t("users.new_password")}(#{t("users.new_password_note")})"] + row3 = ["text", "text"] + + @site_in_use_locales.each_with_index do |locale, i| + row << "first_name(#{locale})" + row2 << "#{t("users.first_name")}(#{I18n.t(locale)})" + row3 << "text" + end + + @site_in_use_locales.each_with_index do |locale, i| + row << "last_name(#{locale})" + row2 << "#{t("users.last_name")}(#{I18n.t(locale)})" + row3 << "text" + end + + row << "email" + row2 << "#{t('users.email')}" + row3 << "text" + + row << "sid" + row2 << "#{t('users.sid')}" + row3 << "text" + + row << "office_tel" + row2 << "#{t('users.office_tel')}" + row3 << "text" + + row << "sex" + row2 << "#{t('users.sex')}(male, female, unknown)" + row3 << "radio" + + row << "birthday" + row2 << "#{t('users.birthday')}(yyyy/MM/dd)" + row3 << "date" + + @site_in_use_locales.each_with_index do |locale, i| + row << "address(#{locale})" + row2 << "#{t("users.address")}(#{I18n.t(locale)})" + row3 << "text_area" + end + + @site_in_use_locales.each_with_index do |locale, i| + row << "autobiography(#{locale})" + row2 << "#{t("users.autobiography")}(#{I18n.t(locale)})" + row3 << "text_area" + end + + @field_type = {'text_field' => 'typeA', 'select' => 'typeB', 'date' => 'typeC', 'text_area' => 'typeD', 'radio_button' => 'typeE', 'checkbox' => 'typeE', 'address' => ''} + + @date_type = {'format1' => 'yyyy/MM/dd hh:mm', 'format2' => 'yyyy/MM/dd', 'format3' => 'yyyy/MM', 'format4' => 'yyyy'} + + + @infos = MemberInfo.all + @infos.each do |info| + + info.member_profile_fields.each do |member_profile_field| + if member_profile_field.markup == 'text_field' or member_profile_field.markup == 'text_area' + if member_profile_field[@field_type[member_profile_field.markup]]['cross_lang'] == 'true' + row << "#{info.key}-#{member_profile_field.key}" + row2 << "#{info.title}-#{member_profile_field.title}" + row3 << member_profile_field.markup + else + @site_in_use_locales.each_with_index do |locale, i| + row << "#{info.key}-#{member_profile_field.key}(#{locale})" + row2 << "#{info.title}-#{member_profile_field.title}(#{I18n.t(locale)})" + row3 << member_profile_field.markup + end + end + elsif member_profile_field.markup == 'date' + row << "#{info.key}-#{member_profile_field.key}" + row2 << "#{info.title}-#{member_profile_field.title}(#{@date_type[member_profile_field['typeC']['format']]})" + row3 << member_profile_field.markup + elsif member_profile_field.markup == 'select' or member_profile_field.markup == 'radio_button' or member_profile_field.markup == 'checkbox' + @option_list = member_profile_field[@field_type[member_profile_field.markup]]['option_list'] + if !@option_list.blank? + @opdata = @option_list.collect{|p| "#{p[0]}=>#{p[1][I18n.locale.to_s]}"} + end + row << "#{info.key}-#{member_profile_field.key}" + row2 << "#{info.title}-#{member_profile_field.title}(#{@opdata.join(',')})" + elsif member_profile_field.markup == 'address' + @site_in_use_locales.each_with_index do |locale, i| + row << "#{info.key}-#{member_profile_field.key}(#{locale})" + row2 << "#{info.title}-#{member_profile_field.title}(#{I18n.t(locale)})" + row3 << member_profile_field.markup + end + else + row << "#{info.key}-#{member_profile_field.key}" + row2 << "#{info.title}-#{member_profile_field.title}" + row3 << member_profile_field.markup + end + end + + end + + @roles = Role.any_in(:key => @member_roles) + @roles.each do |role| + + role_statuses = RoleStatus.where(role_id: role.id, :disable=> false).asc(:_id) + if !role_statuses.blank? + @statusdata = role_statuses.collect{|a,i| "#{a.key}=>#{a.title}"} + + row << "#{role.key}-status" + row2 << "#{role.title}-#{t(:status)}(#{@statusdata.join(',')})" + row3 << "checkbox" + end + + role.attribute_fields.asc(:created_at).each do |attribute_field| + + if attribute_field.markup == 'text_field' or attribute_field.markup == 'text_area' + if attribute_field[@field_type[attribute_field.markup]]['cross_lang'] == 'true' + row << "#{role.key}-#{attribute_field.key}" + row2 << "#{role.title}-#{attribute_field.title}" + row3 << attribute_field.markup + else + @site_in_use_locales.each_with_index do |locale, i| + row << "#{role.key}-#{attribute_field.key}(#{locale})" + row2 << "#{role.title}-#{attribute_field.title}(#{I18n.t(locale)})" + row3 << attribute_field.markup + end + end + elsif attribute_field.markup == 'date' + row << "#{role.key}-#{attribute_field.key}" + row2 << "#{role.title}-#{attribute_field.title}(#{@date_type[attribute_field['typeC']['format']]})" + row3 << attribute_field.markup + elsif attribute_field.markup == 'select' or attribute_field.markup == 'radio_button' or attribute_field.markup == 'checkbox' + @option_list = attribute_field[@field_type[attribute_field.markup]]['option_list'] + if !@option_list.blank? + @opdata = @option_list.collect{|p| "#{p[0]}=>#{p[1][I18n.locale.to_s]}"} + end + row << "#{role.key}-#{attribute_field.key}" + row2 << "#{role.title}-#{attribute_field.title}(#{@opdata.join(',')})" + row3 << attribute_field.markup + elsif attribute_field.markup == 'address' + @site_in_use_locales.each_with_index do |locale, i| + row << "#{role.key}-#{attribute_field.key}(#{locale})" + row2 << "#{role.title}-#{attribute_field.title}(#{I18n.t(locale)})" + row3 << attribute_field.markup + end + else + row << "#{role.key}-#{attribute_field.key}" + row2 << "#{role.title}-#{attribute_field.title}" + row3 << attribute_field.markup + end + + end + + end + + sheet.add_row row + sheet.add_row row3 + sheet.add_row row2 + +end + diff --git a/app/views/admin/members/import_error_msg.html.erb b/app/views/admin/members/import_error_msg.html.erb new file mode 100644 index 0000000..2f76f09 --- /dev/null +++ b/app/views/admin/members/import_error_msg.html.erb @@ -0,0 +1,14 @@ + +

<%= t('site.import_member_data.import_error')%>

+ + + + +<%= link_to t('back'), admin_members_import_members_path, :class => 'btn' %> \ No newline at end of file diff --git a/app/views/admin/members/import_members.html.erb b/app/views/admin/members/import_members.html.erb new file mode 100644 index 0000000..1f6403f --- /dev/null +++ b/app/views/admin/members/import_members.html.erb @@ -0,0 +1,45 @@ +<% content_for :page_specific_css do -%> + <%= stylesheet_link_tag "lib/main-forms.css" %> +<% end -%> + +<%= form_tag download_export_admin_members_path(format: "xlsx"), :multipart => true , :class=>"form-horizontal main-forms", :id=>"user-forms" do %> + +
+
+
+
+

<%= t("site.import_member_data.download_doc") %>

+
+ + <% Role.where(:disabled => false).each_with_index do |role, i| %> + + <% end %> +
+
+
+ <%= submit_tag t(:download) , :class=>"btn btn-default" %> +
+
+ +<% end -%> + +<%= form_tag admin_members_import_members_path, :multipart => true , :class=>"form-horizontal main-forms", :id=>"user-forms" do %> + +
+
+
+
+

<%= t("site.import_member_data.import_member_data") %>

+
+ <%= file_field_tag :file %> +
+
+
+ <%= submit_tag t('site.import') , :class=>"btn btn-default" %> +
+
+ +<% end -%> + diff --git a/config/environment.rb b/config/environment.rb index bdb525d..dfc0f8f 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -74,6 +74,162 @@ if Workgroup.count == 0 end end +if Role.count==0 + + #teacher + role = Role.new + role.key = 'teacher' + role.title_translations = {:en=>'Teacher', :zh_tw=>'老師'} + role.save + + role_status = RoleStatus.new + role_status.key = 'Full-Time' + role_status.role_id = role.id + role_status.title_translations = {:en=>'Full-Time', :zh_tw=>'專任'} + role_status.save + + role_status = RoleStatus.new + role_status.key = 'Adjunct' + role_status.role_id = role.id + role_status.title_translations = {:en=>'Adjunct', :zh_tw=>'兼任'} + role_status.save + + role_status = RoleStatus.new + role_status.key = 'appointment' + role_status.role_id = role.id + role_status.title_translations = {:en=>'appointment', :zh_tw=>'合聘'} + role_status.save + + attribute_field = AttributeField.new + attribute_field.key = 'Job_Title' + attribute_field.role_id = role.id + attribute_field.title_translations = {:en=>'Job Title', :zh_tw=>'職稱'} + attribute_field.markup = 'select' + attribute_field.option_list = { + "0" => { "zh_tw" => "教授兼系主任", + "en" => "Professor and Chairman" }, + "1" => { "zh_tw" => "教授", + "en" => "Professor" }, + "2" => { "zh_tw" => "副教授", + "en" => "Associate Professor" }, + "3" => { "zh_tw" => "助理教授", + "en" => "Assistant Professor" }, + "4" => { "zh_tw" => "講師", + "en" => "Lecturer" } + } + + attribute_field.typeB = { + "initial" => { "zh_tw" => "", + "en" => "" }, + "option_list" => { + "0" => { "zh_tw" => "教授兼系主任", + "en" => "Professor and Chairman" }, + "1" => { "zh_tw" => "教授", + "en" => "Professor" }, + "2" => { "zh_tw" => "副教授", + "en" => "Associate Professor" }, + "3" => { "zh_tw" => "助理教授", + "en" => "Assistant Professor" }, + "4" => { "zh_tw" => "講師", + "en" => "Lecturer" } + } } + + attribute_field.save + + attribute_field = AttributeField.new + attribute_field.key = 'Research_Expertise' + attribute_field.role_id = role.id + attribute_field.title_translations = {:en=>'Research Expertise', :zh_tw=>'研究專長'} + attribute_field.markup = 'text_area' + attribute_field.save + + attribute_field = AttributeField.new + attribute_field.key = 'Teaching_Field' + attribute_field.role_id = role.id + attribute_field.title_translations = {:en=>'Teaching Field', :zh_tw=>'授課領域'} + attribute_field.markup = 'text_area' + attribute_field.save + + #satff + role = Role.new + role.key = 'staff' + role.title_translations = {:en=>'Staff', :zh_tw=>'行政人員'} + role.save + + role_status = RoleStatus.new + role_status.key = 'Full-Time' + role_status.role_id = role.id + role_status.title_translations = {:en=>'Full-Time', :zh_tw=>'全職'} + role_status.save + + role_status = RoleStatus.new + role_status.key = 'Part-time' + role_status.role_id = role.id + role_status.title_translations = {:en=>'Part-time', :zh_tw=>'兼職'} + role_status.save + + role_status = RoleStatus.new + role_status.key = 'Contracted' + role_status.role_id = role.id + role_status.title_translations = {:en=>'Contracted', :zh_tw=>'約聘'} + role_status.save + + attribute_field = AttributeField.new + attribute_field.key = 'Job_Title' + attribute_field.role_id = role.id + attribute_field.title_translations = {:en=>'Job Title', :zh_tw=>'職稱'} + attribute_field.markup = 'select' + attribute_field.option_list = { + "0" => { "zh_tw" => "組長", + "en" => "Group Leader" }, + "1" => { "zh_tw" => "編審", + "en" => "Editor" }, + "2" => { "zh_tw" => "技士", + "en" => "Technician" }, + "3" => { "zh_tw" => "幹事", + "en" => "Assistant" }, + "4" => { "zh_tw" => "組員", + "en" => "Clerk" } , + "5" => { "zh_tw" => "工讀", + "en" => "Work-study" } + } + + attribute_field.typeB = { + "initial" => { "zh_tw" => "", + "en" => "" }, + "option_list" => { + "0" => { "zh_tw" => "組長", + "en" => "Group Leader" }, + "1" => { "zh_tw" => "編審", + "en" => "Editor" }, + "2" => { "zh_tw" => "技士", + "en" => "Technician" }, + "3" => { "zh_tw" => "幹事", + "en" => "Assistant" }, + "4" => { "zh_tw" => "組員", + "en" => "Clerk" } , + "5" => { "zh_tw" => "工讀", + "en" => "Work-study" } + } } + + attribute_field.save + + attribute_field = AttributeField.new + attribute_field.key = 'Duties' + attribute_field.role_id = role.id + attribute_field.title_translations = {:en=>'Duties', :zh_tw=>'承辦業務'} + attribute_field.markup = 'text_area' + attribute_field.save + + attribute_field = AttributeField.new + attribute_field.key = 'Deputy' + attribute_field.role_id = role.id + attribute_field.title_translations = {:en=>'Deputy', :zh_tw=>'代理人'} + attribute_field.markup = 'text_area' + attribute_field.save + +end + if User.count==0 group = Workgroup.where(:key=>'admin').first profile = MemberProfile.new @@ -86,7 +242,8 @@ if User.count==0 user.workgroup = group user.member_profile = profile user.user_name = "rulingcom" - user.password = "bjo4xjp6" + user.password = "Ab-5508881" user.email = "orbit@rulingcom.com" + user.approved = true user.save end \ No newline at end of file diff --git a/config/locales/en.yml b/config/locales/en.yml index 9e6e6df..c45c6e3 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -488,7 +488,16 @@ en: frontend_open: Frontend Open disable_personal_desktop: Disable Personal Desktop header: Site header + import: Import import_rss2: Import RSS2 + import_member_data: + import_error: Import Error + import_members: Import Members + import_member_data: Import Member Data + download_doc: Download Importation Format + import_error_id: "%{field} The Account field is already there" + import_error_type: "%{field} Field format incompatible" + import_error_date: "%{field} Date field format incompatible" info: Site information keywords: Site keywords keywords_help: Keyword Guide diff --git a/config/locales/zh_tw.yml b/config/locales/zh_tw.yml index 86f93c7..c501af4 100644 --- a/config/locales/zh_tw.yml +++ b/config/locales/zh_tw.yml @@ -495,7 +495,16 @@ zh_tw: footer: 網站頁尾 footer_help: 網站頁尾說明 header: 網站頁首 + import: 匯入 import_rss2: 匯入RSS2 + import_member_data: + import_error: 匯入錯誤 + import_members: 批次匯入會員 + import_member_data: 匯入會員資料 + download_doc: 下載匯入格式 + import_error_id: "%{field}欄位帳號已存在。" + import_error_type: "%{field}欄位格式不符。" + import_error_date: "%{field}欄位日期格式不符。" info: 網站資訊 keywords: 搜尋關鍵字 keywords_help: 關鍵字說明 diff --git a/config/routes.rb b/config/routes.rb index f64c939..d58c675 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -90,7 +90,8 @@ Orbit::Application.routes.draw do end get "members/get_role_fields/:id" => "members#get_role_fields", :as => :get_role_fields - get "members/unapproved_members" => "members#unapproved_members" + get "members/import_members" => "members#import_members" + get "members/unapproved_members" => "members#unapproved_members" resources :members do collection do @@ -98,6 +99,8 @@ Orbit::Application.routes.draw do get 'edit_order_list' post 'update_order_card' post 'update_order_list' + post 'import_members' + post 'download_export' end match "setting_account" => "members#setting_account" ,:as => :setting_account, via: [:get, :post] match "edit_passwd" => "members#edit_passwd" ,:as => :edit_passwd, via: [:get, :post]