Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions app/controllers/admin/urn_lists_controller.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
class Admin::UrnListsController < AdminController
before_action :find_latest_list, only: %i[index]

def index
@urn_lists = UrnList.order(created_at: :desc).page(params[:page])
@urn_lists = UrnList.order(created_at: :desc).page(params[:active_page]).per(25)
@inactive_customer_imports = InactiveCustomerImport.order(created_at: :desc).page(params[:inactive_page]).per(25)

respond_to do |format|
format.html
format.js
end
end

def new
Expand All @@ -27,10 +31,6 @@ def urn_list_params
params.require(:urn_list).permit(:excel_file)
end

def find_latest_list
@latest_urn_list = UrnList.where(source: 'manual_upload', aasm_state: 'processed').order(created_at: :desc).first
end

def s3_client
@s3_client ||= Aws::S3::Client.new(region: ENV['AWS_S3_REGION'])
end
Expand Down
17 changes: 16 additions & 1 deletion app/jobs/inactive_urn_list_api_sync_job.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
class InactiveUrnListApiSyncJob < ApplicationJob
def perform
inactive_customer_import = InactiveCustomerImport.create!(aasm_state: :pending)

rows = UrnLists::ApiClient.new.fetch_inactive_rows
count = UrnLists::ImportInactiveCustomers.new(rows: rows).call

inactive_customer_import.update!(
aasm_state: :processed,
records_count: count,
completed_at: Time.current
)
rescue StandardError => e
inactive_customer_import&.update!(
aasm_state: :failed,
completed_at: Time.current,
records_count: count || 0
)

UrnLists::ImportInactiveCustomers.new(rows: rows).call
raise e
end
end
9 changes: 9 additions & 0 deletions app/models/inactive_customer_import.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class InactiveCustomerImport < ApplicationRecord
include AASM

aasm do
state :pending, initial: true
state :processed
state :failed
end
end
2 changes: 2 additions & 0 deletions app/services/urn_lists/import_inactive_customers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ def call
unique_by: :index_inactive_customers_on_inactive_urn
)
end

rows.count
end
# rubocop:enable Rails/SkipsModelValidations

Expand Down
17 changes: 17 additions & 0 deletions app/views/admin/urn_lists/_active_urn_lists.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
%table.govuk-table{:class => 'govuk-!-margin-top-7'}
%thead.govuk-table__head
%tr.govuk-table__row
%th.govuk-table__header Source
%th.govuk-table__header Filename
%th.govuk-table__header Upload Date
%th.govuk-table__header Status
%tbody.govuk-table__body
- @urn_lists.each do |list|
%tr.govuk-table__row
%td.govuk-table__cell= list.source.humanize
%td.govuk-table__cell= list.excel_file.filename || '-'
%td.govuk-table__cell= list.created_at
%td.govuk-table__cell= list.aasm_state
%nav.pagination.ccs-pagination{"aria-label" => "Pagination", :role => "navigation"}
#active_audit_log_pagination_summary.ccs-pagination__summary= page_entries_info @urn_lists, entry_name: "URN list"
#active_audit_log_pagination= paginate @urn_lists, :param_name => "active_page", remote: true
13 changes: 13 additions & 0 deletions app/views/admin/urn_lists/_inactive_customer_imports.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
%table.govuk-table{:class => 'govuk-!-margin-top-7'}
%thead.govuk-table__head
%tr.govuk-table__row
%th.govuk-table__header Sync Datetime
%th.govuk-table__header Status
%tbody.govuk-table__body
- @inactive_customer_imports.each do |import|
%tr.govuk-table__row
%td.govuk-table__cell= import.created_at
%td.govuk-table__cell= import.aasm_state
%nav.pagination.ccs-pagination{"aria-label" => "Pagination", :role => "navigation"}
#inactive_audit_log_pagination_summary.ccs-pagination__summary= page_entries_info @inactive_customer_imports, entry_name: "import"
#inactive_audit_log_pagination= paginate @inactive_customer_imports, :param_name => "inactive_page", remote: true
36 changes: 17 additions & 19 deletions app/views/admin/urn_lists/index.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,25 @@
%h2#page-actions-title.govuk-heading-s{"aria-label" => "Page actions"} Actions
%ul.govuk-page-actions--actions
%li.govuk-page-actions--action
= link_to 'Add a new URN list', new_admin_urn_list_path
= link_to 'Add a new Active URN list', new_admin_urn_list_path
%li.govuk-page-actions--action
= link_to 'View Active URN list', admin_urns_path

.govuk-grid-row
.govuk-grid-column-full
- if @urn_lists.present?
%table.govuk-table{:class => 'govuk-!-margin-top-7'}
%thead.govuk-table__head
%tr.govuk-table__row
%th.govuk-table__header Source
%th.govuk-table__header Filename
%th.govuk-table__header Upload Date
%th.govuk-table__header Status
%tbody.govuk-table__body
- @urn_lists.each do |list|
%tr.govuk-table__row
%td.govuk-table__cell= list.source.humanize
%td.govuk-table__cell= list.excel_file.filename || '-'
%td.govuk-table__cell= list.created_at
%td.govuk-table__cell= list.aasm_state
= paginate @urn_lists


.govuk-tabs{"data-module" => "govuk-tabs"}
%h2.govuk-tabs__title
Contents
%ul.govuk-tabs__list
%li.govuk-tabs__list-item.govuk-tabs__list-item--selected
%a.govuk-tabs__tab{href: "#active"}
Active
%li.govuk-tabs__list-item
%a.govuk-tabs__tab{href: "#inactive"}
Inactive
#active.govuk-tabs__panel
- if @urn_lists.present?
.results{id: 'active-urn-lists-table'}= render 'active_urn_lists', urn_lists: @urn_lists
#inactive.govuk-tabs__panel
- if @inactive_customer_imports.present?
.results{id: 'inactive-customer-imports-table'}= render 'inactive_customer_imports', imports: @inactive_customer_imports
8 changes: 8 additions & 0 deletions app/views/admin/urn_lists/index.js.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-if params[:active_page]
$('#active-urn-lists-table').html("#{j (render partial: 'active_urn_lists', locals: {urn_lists: @urn_lists})}")
$('#active_audit_log_pagination').html("#{j (paginate(@urn_lists, :param_name => "active_page", :remote => true).to_s)}");
$('#active_audit_log_pagination_summary').html("#{j (page_entries_info(@urn_lists, entry_name: "URN list").to_s)}");
-if params[:inactive_page]
$('#inactive-customer-imports-table').html("#{j (render partial: 'inactive_customer_imports', locals: {imports: @inactive_customer_imports})}")
$('#inactive_audit_log_pagination').html("#{j (paginate(@inactive_customer_imports, :param_name => "inactive_page", :remote => true).to_s)}");
$('#inactive_audit_log_pagination_summary').html("#{j (page_entries_info(@inactive_customer_imports, entry_name: "import").to_s)}");
1 change: 1 addition & 0 deletions config/sidekiq_schedule.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ inactive_urn_list_importer:
cron: '0 20 * * * Europe/London'
class: InactiveUrnListApiSyncJob
queue: default
active_job: true
11 changes: 11 additions & 0 deletions db/migrate/20260605131714_create_inactive_customer_imports.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class CreateInactiveCustomerImports < ActiveRecord::Migration[8.1]
def change
create_table :inactive_customer_imports, id: :uuid do |t|
t.string :aasm_state
t.integer :records_count
t.datetime :completed_at

t.timestamps
end
end
end
10 changes: 9 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[8.1].define(version: 2026_05_18_115711) do
ActiveRecord::Schema[8.1].define(version: 2026_06_05_131714) do
# These are extensions that must be enabled in order to support this database
enable_extension "citext"
enable_extension "pg_catalog.plpgsql"
Expand Down Expand Up @@ -162,6 +162,14 @@
t.index ["short_name"], name: "index_frameworks_on_short_name", unique: true
end

create_table "inactive_customer_imports", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.string "aasm_state"
t.datetime "completed_at"
t.datetime "created_at", null: false
t.integer "records_count"
t.datetime "updated_at", null: false
end

create_table "inactive_customers", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.datetime "created_at", null: false
t.date "date_made_inactive"
Expand Down
19 changes: 19 additions & 0 deletions spec/factories/inactive_customer_imports.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FactoryBot.define do
factory :inactive_customer_import do
aasm_state { :pending }
records_count { 0 }
completed_at { nil }

trait :processed do
aasm_state { :processed }
records_count { 100 }
completed_at { Time.current }
end

trait :failed do
aasm_state { :failed }
records_count { 0 }
completed_at { Time.current }
end
end
end
2 changes: 1 addition & 1 deletion spec/features/admin_can_upload_urn_list_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

scenario 'uploading a URN list' do
visit admin_urn_lists_path
click_link 'Add a new URN list'
click_link 'Add a new Active URN list'

expect(page).to have_text 'Upload a new URN list'

Expand Down
32 changes: 0 additions & 32 deletions spec/jobs/inactive_urn_list_api_sync_job.rb

This file was deleted.

77 changes: 77 additions & 0 deletions spec/jobs/inactive_urn_list_api_sync_job_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
require 'rails_helper'

RSpec.describe InactiveUrnListApiSyncJob do
describe '#perform' do
let(:rows) do
[
{
'InactiveURN' => '10009655',
'InactiveCustomerName' => 'Government Commercial Agency',
'DateMadeInactive' => '2024-01-01',
'ReplacementURN' => '10009656',
'ReplacementName' => 'Another Organisation',
'ReplacementPostCode' => 'AB1 2CD',
'ReplacementStatus' => 'active'
}
]
end

let(:api_client_service) do
double('UrnLists::ApiClient', fetch_inactive_rows: rows)
end

let(:import_inactive_customers_service) do
double('UrnLists::ImportInactiveCustomers', call: rows.count)
end

before do
allow(UrnLists::ApiClient).to receive(:new).and_return(api_client_service)
allow(UrnLists::ImportInactiveCustomers)
.to receive(:new).with(rows: rows)
.and_return(import_inactive_customers_service)
end

it 'creates a pending inactive customer import, imports the rows, and marks it as processed' do
expect do
described_class.perform_now
end.to change(InactiveCustomerImport, :count).by(1)

expect(api_client_service).to have_received(:fetch_inactive_rows)
expect(import_inactive_customers_service).to have_received(:call)

inactive_customer_import = InactiveCustomerImport.last

expect(inactive_customer_import.aasm_state).to eq('processed')
expect(inactive_customer_import.records_count).to eq(rows.count)
expect(inactive_customer_import.completed_at).not_to be_nil
end

it 'handles errors during the import process and marks the import as failed' do
allow(api_client_service).to receive(:fetch_inactive_rows).and_raise(StandardError.new('API error'))

expect do
described_class.perform_now
end.to raise_error(StandardError, 'API error')

inactive_customer_import = InactiveCustomerImport.last

expect(inactive_customer_import.aasm_state).to eq('failed')
expect(inactive_customer_import.records_count).to eq(0)
expect(inactive_customer_import.completed_at).not_to be_nil
end

it 'marks the import as failed when the import fails after rows are fetched' do
allow(import_inactive_customers_service).to receive(:call).and_raise(StandardError.new('Import error'))

expect do
described_class.perform_now
end.to raise_error(StandardError, 'Import error')

inactive_customer_import = InactiveCustomerImport.last

expect(inactive_customer_import.aasm_state).to eq('failed')
expect(inactive_customer_import.records_count).to eq(0)
expect(inactive_customer_import.completed_at).not_to be_nil
end
end
end
8 changes: 7 additions & 1 deletion spec/services/urn_lists/import_inactive_customers_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@
end

it 'imports inactive customers into the database' do
result = nil

expect do
described_class.new(rows: rows).call
result = described_class.new(rows: rows).call
end.to change(InactiveCustomer, :count).by(1)

expect(result).to eq(rows.count)

inactive_customer = InactiveCustomer.last
expect(inactive_customer.inactive_urn).to eq(10009655)
expect(inactive_customer.inactive_customer_name).to eq('Government Commercial Agency')
Expand All @@ -45,6 +49,8 @@
expect do
described_class.new(rows: rows).call
end.not_to change(InactiveCustomer, :count)

expect(described_class.new(rows: rows).call).to eq(rows.count)
end
end
end
Loading