diff --git a/app/controllers/admin/e_paper_subscribers_controller.rb b/app/controllers/admin/e_paper_subscribers_controller.rb index 4e3cd4c..44142ba 100644 --- a/app/controllers/admin/e_paper_subscribers_controller.rb +++ b/app/controllers/admin/e_paper_subscribers_controller.rb @@ -106,20 +106,42 @@ class Admin::EPaperSubscribersController < OrbitAdminController :status=>'Importing', 'all_count'=>all_count, 'current_count'=>current_count, - 'finish_percent'=>finish_percent + 'finish_percent'=>finish_percent, + 'pid'=>Process.pid } ) + # 修改點:迴圈外先準備一個陣列,收集匯入失敗的列,最後要回報給使用者 + failed_rows = [] + existing_subscribers = {} + EPaperSubscriber.all.each { |s| existing_subscribers[s.email] = s } + if subscribe_sheet subscribe_sheet.each_with_index do |row, i| next if i < 1 + next if row.nil? email = row.cells[0]&.value next if email.blank? - subscriber = EPaperSubscriber.where(:email=>email).first || EPaperSubscriber.new(:email=>email) - subscriber.subscribed = true - subscriber.language = row.cells[1]&.value.presence || I18n.locale.to_s - subscriber.save + # 修改點:查詢前先用跟 model 一樣的清洗規則處理 email,避免「查詢用原始字串、儲存用清洗後字串」不一致造成誤判成新資料 + fixed_email = email.to_s.gsub(/[ ]/,'').sub(/;$/, '').downcase + + if fixed_email.count('@') > 1 + failed_rows << { row: i + 1, email: email.to_s, reason: '一個欄位包含多個信箱,請拆成單獨一列後重新匯入' } + current_count += 1 + next + end + begin + # 修改點:改用記憶體 Hash 查詢,取代資料庫查詢 + subscriber = existing_subscribers[fixed_email] || EPaperSubscriber.new(:email=>fixed_email) + subscriber.subscribed = true + subscriber.language = row.cells[1]&.value.presence || I18n.locale.to_s + subscriber.save! + # 修改點:存檔成功後更新 Hash,避免同一份檔案裡後面重複出現的同一個email又找不到 + existing_subscribers[subscriber.email] = subscriber + rescue => e + failed_rows << { row: i + 1, email: email.to_s, reason: e.message } + end current_count += 1 if current_count % puts_every_count == 0 @@ -132,13 +154,32 @@ class Admin::EPaperSubscribersController < OrbitAdminController if unsubscribe_sheet unsubscribe_sheet.each_with_index do |row, i| next if i < 1 + # 修改點:對齊Subscribe那段,整列空白時row本身是nil,要先擋掉 + next if row.nil? email = row.cells[0]&.value next if email.blank? - subscriber = EPaperSubscriber.where(:email=>email).first || EPaperSubscriber.new(:email=>email) - subscriber.subscribed = false - subscriber.language = row.cells[1]&.value.presence || I18n.locale.to_s - subscriber.save + # 修改點:對齊Subscribe那段,查詢前先用同一套清洗規則處理email + fixed_email = email.to_s.gsub(/[ ]/,'').sub(/;$/, '').downcase + + # 修改點:對齊Subscribe那段,擋下一格塞多個信箱的資料 + if fixed_email.count('@') > 1 + failed_rows << { row: i + 1, email: email.to_s, reason: '一個欄位包含多個信箱,請拆成單獨一列後重新匯入' } + current_count += 1 + next + end + + # 修改點:對齊Subscribe那段,改用記憶體Hash查詢取代資料庫查詢 + # 修改點:save改save!並包begin/rescue,例外不再讓整條Thread死掉 + begin + subscriber = existing_subscribers[fixed_email] || EPaperSubscriber.new(:email=>fixed_email) + subscriber.subscribed = false + subscriber.language = row.cells[1]&.value.presence || I18n.locale.to_s + subscriber.save! + existing_subscribers[subscriber.email] = subscriber + rescue => e + failed_rows << { row: i + 1, email: email.to_s, reason: e.message } + end current_count += 1 if current_count % puts_every_count == 0 @@ -153,7 +194,8 @@ class Admin::EPaperSubscribersController < OrbitAdminController :status=>'finish', 'all_count'=>all_count, 'current_count'=>current_count, - 'finish_percent'=>100 + 'finish_percent'=>100, + 'failed_rows'=>failed_rows } ) end @@ -161,6 +203,19 @@ class Admin::EPaperSubscribersController < OrbitAdminController redirect_to admin_e_paper_subscribers_path(thread_id: thread.id) end + def last_import_result + thread = Multithread.where(:key=>'import_epaper_subscribers').first + stalled = false + if thread && thread.status['status'] == 'Importing' && thread.status['pid'] + begin + Process.kill(0, thread.status['pid']) + rescue Errno::ESRCH + stalled = true + end + end + render :partial => 'last_import_result', locals: { thread: thread, stalled: stalled } + end + def download_excel_format @subscribers = [] @unsubscribers = [] diff --git a/app/models/e_paper_subscriber.rb b/app/models/e_paper_subscriber.rb index 7b22ab9..95f9678 100755 --- a/app/models/e_paper_subscriber.rb +++ b/app/models/e_paper_subscriber.rb @@ -7,14 +7,19 @@ class EPaperSubscriber field :subscribed, type: Boolean, :default => true field :language field :last_paper_sent + before_save do self.fix_email - if self.class.where(:email=>self.email, :language=>self.language,:subscribed=>true).count != 0 - return false + # 修改點:用 throw(:abort) 取代 return false(Rails 5+ block 內不可用 return) + # 修改點:排除自己這筆(self.id.ne=>self.id),避免更新既有紀錄時把自己算成重複 + if self.class.where(:id.ne=>self.id, :email=>self.email, :language=>self.language, :subscribed=>true).count != 0 + throw(:abort) end end + def fix_email(save_flag=false) - self.email = self.email.to_s.gsub(/[ ]/,'').sub(/;$/, '') + # 修改點:加上 .downcase,統一大小寫,避免 ABC@Gmail.com 跟 abc@gmail.com 被當成兩筆 + self.email = self.email.to_s.gsub(/[ ]/,'').sub(/;$/, '').downcase self.save if save_flag end -end \ No newline at end of file +end diff --git a/app/views/admin/e_paper_subscribers/_index.html.erb b/app/views/admin/e_paper_subscribers/_index.html.erb index 5f13572..b96b048 100755 --- a/app/views/admin/e_paper_subscribers/_index.html.erb +++ b/app/views/admin/e_paper_subscribers/_index.html.erb @@ -53,9 +53,7 @@ content_tag(:div, link_to(t("e_paper.export"), admin_e_paper_subscribers_export_excel_path + '.xlsx', :class=>"btn btn-success"), class: "pull-right") %>