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
7 changes: 7 additions & 0 deletions app/controllers/audits_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
class AuditsController < ApplicationController
before_action :authorize_admin
before_action :set_audit, only: %i(show edit update destroy finalize)
before_action :ensure_audit_is_editable, only: %i(finalize update)

def index
@selected_location = filter_params[:at_location]
Expand Down Expand Up @@ -80,6 +81,12 @@ def destroy

private

def ensure_audit_is_editable
if @audit.reload.finalized?
redirect_to audit_path(@audit), error: "This audit has been finalized and cannot be edited."
end
end

def handle_audit_errors
error_message = @audit.errors.uniq(&:attribute).map do |error|
attr = (error.attribute.to_s == 'base') ? '' : error.attribute.capitalize
Expand Down
14 changes: 14 additions & 0 deletions app/models/account_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class AccountRequest < ApplicationRecord

validate :email_not_already_used_by_organization
validate :email_not_already_used_by_user
validate :cannot_change_status_once_rejected,
:cannot_change_status_once_closed, on: :update

belongs_to :ndbn_member, class_name: 'NDBNMember', optional: true

Expand Down Expand Up @@ -100,4 +102,16 @@ def email_not_already_used_by_user
errors.add(:email, 'already used by an existing User')
end
end

def cannot_change_status_once_rejected
if status_changed? && status_was == "rejected"
errors.add(:status, "cannot be changed once rejected")
end
end

def cannot_change_status_once_closed
if status_changed? && status_was == "admin_closed"
errors.add(:status, "cannot be changed once closed by an admin")
end
end
end
7 changes: 7 additions & 0 deletions app/models/audit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class Audit < ApplicationRecord
validate :line_items_quantity_is_not_negative
validate :line_items_unique_by_item_id
validate :user_is_organization_admin_of_the_organization
validate :cannot_change_status_once_finalized, on: :update

def self.finalized_since?(itemizable, *location_ids)
item_ids = itemizable.line_items.pluck(:item_id)
Expand Down Expand Up @@ -86,4 +87,10 @@ def line_items_unique_by_item_id
def line_items_quantity_is_not_negative
line_items_quantity_is_at_least(0)
end

def cannot_change_status_once_finalized
if status_changed? && status_was == "finalized"
errors.add(:status, "cannot be changed once finalized")
end
end
end
24 changes: 24 additions & 0 deletions spec/models/account_request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,30 @@
end
end

describe '#status' do
it "does not regress from rejected to another status" do
rejected_request = create(:account_request, status: 'rejected')

expect { rejected_request.confirm! }
.to raise_error(ActiveRecord::RecordInvalid, /cannot be changed once rejected/)
end

it "does not regress from admin_closed to another status" do
rejected_request = create(:account_request, status: 'admin_closed')

expect { rejected_request.confirm! }
.to raise_error(ActiveRecord::RecordInvalid, /cannot be changed once closed by an admin/)
end

it "allows normal transitions" do
started_request = create(:account_request, status: 'started')
user_confirmed_request = create(:account_request, status: 'user_confirmed')

expect { started_request.confirm! }.not_to raise_error
expect { user_confirmed_request.reject!('rejectable request') }.not_to raise_error
end
end

describe '.get_by_identity_token' do
subject { described_class.get_by_identity_token(identity_token) }

Expand Down
17 changes: 17 additions & 0 deletions spec/models/audit_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,23 @@

expect(audit.save).to be_truthy
end

describe '#status' do
it "does not regress from finalized to another status" do
finalized_audit = create(:audit, organization:, status: :finalized)

expect { finalized_audit.update!(status: :confirmed) }
.to raise_error(ActiveRecord::RecordInvalid, /cannot be changed once finalized/)
end

it "allows normal transitions" do
in_progress_audit = create(:audit, organization:, status: :in_progress)
confirmed_audit = create(:audit, organization:, status: :confirmed)

expect { in_progress_audit.update!(status: :confirmed) }.not_to raise_error
expect { confirmed_audit.update!(status: :finalized) }.not_to raise_error
end
end
end

context "Scopes >" do
Expand Down
54 changes: 50 additions & 4 deletions spec/requests/audits_requests_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,22 @@
{
organization_id: organization.id,
storage_location_id: storage_location.id,
user_id: create(:organization_admin, organization: organization).id
user_id: organization_admin.id
}
end

let(:invalid_storage_location_attributes) do
{
organization_id: organization.id,
storage_location_id: nil,
user_id: create(:organization_admin, organization: organization).id
user_id: organization_admin.id
}
end

let(:invalid_attributes) do
{ organization_id: nil }
end

let(:valid_session) { {} }

describe "while signed in as an organization admin" do
before do
sign_in(organization_admin)
Expand Down Expand Up @@ -109,6 +107,40 @@
end
end

describe "PUT #update" do
it "confirms the updated audit and redirects to the audit" do
audit = create(:audit, organization: organization, status: :in_progress)
item = create(:item)
audit.line_items << create(:line_item, quantity: 3, item: item)

put audit_path(id: audit.to_param, audit: {
storage_location_id: storage_location.id,
line_items_attributes: {"0" => {"item_id" => item.id, "quantity" => "4"}}
})

expect(response).to redirect_to(audit_path(audit))
expect(flash[:notice]).to include("Audit is confirmed.")
expect(audit.reload).to be_confirmed
end

context "when the audit has already been finalized" do
it "does not allow updates and redirects to the finalized audit" do
finalized_audit = create(:audit, organization: organization, status: :finalized)
item = create(:item)
finalized_audit.line_items << create(:line_item, quantity: 3, item: item)

put audit_path(id: finalized_audit.to_param, audit: {
storage_location_id: storage_location.id,
line_items_attributes: {"0" => {"item_id" => item.id, "quantity" => "4"}}
})

expect(response).to redirect_to(audit_path(finalized_audit))
expect(flash[:error]).to include("This audit has been finalized and cannot be edited.")
expect(finalized_audit.line_items.first.quantity).to eq(3)
end
end
end

describe "POST #create" do
context "with valid params" do
it "creates a new Audit" do
Expand All @@ -121,6 +153,7 @@
expect do
post audits_path(audit: valid_attributes, save_progress: '')
expect(Audit.last.in_progress?).to be_truthy
expect(flash[:notice]).to include("Audit's progress was successfully saved.")
end.to change(Audit.in_progress, :count).by(1)
end

Expand Down Expand Up @@ -170,6 +203,19 @@
expect(audit.reload).to be_finalized
expect(AuditEvent.count).to eq(1)
end

context "when the audit has already been finalized" do
it "does not create a new AuditEvent and redirects to the finalized audit" do
finalized_audit = create(:audit, organization: organization, status: :finalized)

expect do
post audit_finalize_path(audit_id: finalized_audit.to_param)
end.not_to change(AuditEvent, :count)

expect(response).to redirect_to(audit_path(finalized_audit))
expect(flash[:error]).to include("This audit has been finalized and cannot be edited.")
end
end
end

describe "DELETE #destroy" do
Expand Down
Loading