Skip to content
Merged
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
15 changes: 4 additions & 11 deletions app/models/adjustment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,11 @@ def split_difference
[increasing_adjustment, decreasing_adjustment]
end

def self.csv_export_headers
["Created", "Organization", "Storage Location", "Comment", "Changes"]
end
def self.generate_csv(adjustments)
return nil if adjustments.empty?

def csv_export_attributes
[
created_at.strftime("%F"),
organization.name,
storage_location.name,
comment,
line_items.count
]
Exports::ExportAdjustmentsCSVService
.generate_csv(adjustments, adjustments.first.organization)
end

private
Expand Down
48 changes: 48 additions & 0 deletions app/services/exports/export_adjustments_csv_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
module Exports
module ExportAdjustmentsCSVService
class << self
def generate_csv(adjustments, organization)
CSV.generate(headers: true) do |csv|
generate_csv_data(adjustments, organization).each { |row| csv << row }
end
end

def generate_csv_data(adjustments, organization)
item_names = get_item_names(organization)
headers = [
"Created date", "Storage Area",
"Comment", "# of changes"
] + item_names

[headers] + adjustments.map { |adjustment| build_row(adjustment, item_names) }
end

private

def get_item_names(organization)
organization.items.order(:name).pluck(:name).uniq
end

def build_row(adjustment, item_names)
row = [
adjustment.created_at.strftime("%F"),
adjustment.storage_location.name,
adjustment.comment,
adjustment.line_items.count { |item| !item.quantity.eql?(0) }
]

item_quantities = Hash.new(0)

adjustment.line_items.each do |line_item|
item_quantities[line_item.item.name] += line_item.quantity
end

item_names.each do |item_name|
row << item_quantities[item_name]
end

row
end
end
end
end
7 changes: 4 additions & 3 deletions docs/user_guide/bank/exports.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ The exports available include (in alphabetical order):
Click "Inventory", then "Inventory Adjustments" in the left-hand menu. Then click "Export Adjustments",

### Contents of adjustment export
Creation date, Organization, Storage Area, Comment, # of changes.

[! NOTE] We have improving the adjustments export to include the changes made in each adjustment on our todo list. We'll also remove the organization as redundant information. Please reach out if this is a priority for you.
- Creation date
- Storage Area, Comment
- # of changes
- the quantity of each of your organization's Items in the adjustments

## Annual Survey
### Navigating to export annual survey
Expand Down
57 changes: 55 additions & 2 deletions spec/requests/adjustments_requests_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,63 @@

context "csv" do
let(:response_format) { 'csv' }
let(:storage_location) { create(:storage_location, organization: organization) }
let(:item1) { create(:item, name: "Item One", organization: organization) }
let(:item2) { create(:item, name: "Item Two", organization: organization) }

let!(:adjustment1) do
adj = create(:adjustment,
organization: organization,
storage_location: storage_location,
comment: "First adjustment",
created_at: 1.day.ago)
adj.line_items << build(:line_item, quantity: 10, item: item1, itemizable: adj)
adj.line_items << build(:line_item, quantity: 5, item: item2, itemizable: adj)
adj
end

let!(:adjustment2) do
adj = create(:adjustment,
organization: organization,
storage_location: storage_location,
comment: "Second adjustment",
created_at: 5.days.ago)
adj.line_items << build(:line_item, quantity: -5, item: item1, itemizable: adj)
adj
end

before { adjustment }
before { get adjustments_path(format: 'csv') }

it { is_expected.to be_successful }
it "returns a CSV file" do
expect(response).to be_successful
expect(response.header['Content-Type']).to include 'text/csv'
end

it "includes appropriate headers and data" do
csv = <<~CSV
Created date,Storage Area,Comment,# of changes,#{item1.name},#{item2.name}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We know the name, can we put the hardcoded value in here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, let me quickly change that :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dorner should I squash this and the last change to a single commit and then force push? to not create too much commit noise

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cyang-el no, that's what merge commits are for. 😄 Force push causes havoc with existing comments.

2019-06-30,Smithsonian Conservation Center,First adjustment,2,10,5
2019-06-26,Smithsonian Conservation Center,Second adjustment,1,-5,0
CSV

expect(response.body).to eq(csv)
end

context "when filtering by date" do
it "returns adjustments filtered by date range" do
start_date = 3.days.ago.to_fs(:date_picker)
end_date = Time.zone.today.to_fs(:date_picker)

get adjustments_path, params: { filters: { date_range: "#{start_date} - #{end_date}" }, format: 'csv' }

csv = <<~CSV
Created date,Storage Area,Comment,# of changes,Item One,Item Two
2019-06-30,Smithsonian Conservation Center,First adjustment,2,10,5
CSV

expect(response.body).to eq(csv)
end
end
end
end

Expand Down
93 changes: 93 additions & 0 deletions spec/services/exports/export_adjustments_csv_service_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
RSpec.describe Exports::ExportAdjustmentsCSVService do
# Create organization after items to ensure proper associations
let!(:item1) { create(:item, name: "item1") }
let!(:item2) { create(:item, name: "item2") }
let!(:item3) { create(:item, name: "item3") }
let!(:item4) { create(:item, name: "item4") }
let!(:item5) { create(:item, :inactive, name: "item5") }

# Now create organization and associate items with it
let(:organization) do
org = create(:organization)
[item1, item2, item3, item4, item5].each do |item|
item.update!(organization_id: org.id)
end
org
end

let(:sorted_item_names) do
[item1, item2, item3, item4, item5].map(&:name).sort
end

let(:storage_location) { create(:storage_location, organization: organization) }
let(:user) { create(:user, organization: organization) }

around do |example|
travel_to Time.zone.local(2024, 12, 25)
example.run
travel_back
end

describe "#generate_csv_data" do
subject { described_class.generate_csv(adjustments, organization) }

context "with multiple adjustments and items" do
let(:adjustments) do
[
# 1st adjustment with 2 items
create(:adjustment,
user_id: user.id,
storage_location: storage_location,
organization: organization,
comment: "adjustment 1",
line_items_attributes: [
{item_id: item1.id, quantity: 10},
{item_id: item2.id, quantity: -5}
]),

# 2nd adjustment with 1 item
create(:adjustment,
user_id: user.id,
storage_location: storage_location,
organization: organization,
comment: "adjustment 2",
line_items_attributes: [
{item_id: item3.id, quantity: 3}
]),

# 3rd adjustment with the :with_items trait
create(:adjustment, :with_items,
user_id: user.id,
storage_location: storage_location,
organization: organization,
comment: "adjustment 3",
item: item1,
item_quantity: 7)
]
end

it "should include the correct adjustment data" do
csv = <<~CSV
Created date,Storage Area,Comment,# of changes,item1,item2,item3,item4,item5
2024-12-25,Smithsonian Conservation Center,adjustment 1,2,10,-5,0,0,0
2024-12-25,Smithsonian Conservation Center,adjustment 2,1,0,0,3,0,0
2024-12-25,Smithsonian Conservation Center,adjustment 3,1,7,0,0,0,0
CSV

expect(subject).to eq(csv)
end
end

context "when there are no adjustments" do
let(:adjustments) { [] }

it "returns only headers row" do
csv = <<~CSV
Created date,Storage Area,Comment,# of changes,item1,item2,item3,item4,item5
CSV

expect(subject).to eq(csv)
end
end
end
end