Skip to content

Commit

Permalink
Filter sales data by dates
Browse files Browse the repository at this point in the history
  • Loading branch information
mkllnk committed Aug 30, 2024
1 parent 1016656 commit d52134d
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,27 @@
module DfcProvider
# Aggregates anonymised sales data for a research project.
class AffiliateSalesDataController < DfcProvider::ApplicationController
rescue_from Date::Error, with: -> { head :bad_request }

def show
person = AffiliateSalesDataBuilder.person(current_user)
person = AffiliateSalesDataBuilder.person(current_user, filter_params)

render json: DfcIo.export(person)
end

private

def filter_params
{
start_date: parse_date(params[:startDate]),
end_date: parse_date(params[:endDate]),
}
end

def parse_date(string)
return if string.blank?

Date.parse(string)
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@

class AffiliateSalesDataBuilder < DfcBuilder
class << self
def person(user)
def person(user, filters = {})
data = AffiliateSalesQuery.data(user.affiliate_enterprises, **filters)
suppliers = data.map do |row|
AffiliateSalesDataRowBuilder.new(row).build_supplier
end

DataFoodConsortium::Connector::Person.new(
urls.affiliate_sales_data_url,
affiliatedOrganizations: enterprises(user.affiliate_enterprises)
affiliatedOrganizations: suppliers,
)
end

def enterprises(enterprises)
AffiliateSalesQuery.data(enterprises).map do |row|
AffiliateSalesDataRowBuilder.new(row).build_supplier
end
end
end
end
9 changes: 7 additions & 2 deletions engines/dfc_provider/app/services/affiliate_sales_query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@

class AffiliateSalesQuery
class << self
def data(enterprises)
def data(enterprises, start_date: nil, end_date: nil)
end_date = end_date&.end_of_day # Include the whole end date.

Spree::LineItem
.joins(tables)
.where(
spree_orders: { state: "complete", distributor_id: enterprises },
spree_orders: {
state: "complete", distributor_id: enterprises,
completed_at: [start_date..end_date],
},
)
.group(key_fields)
.pluck(fields)
Expand Down
49 changes: 43 additions & 6 deletions engines/dfc_provider/spec/requests/affiliate_sales_data_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,53 @@
before { login_as user }

path "/api/dfc/affiliate_sales_data" do
parameter name: :startDate, in: :query, type: :string
parameter name: :endDate, in: :query, type: :string

get "Show sales data of person's affiliate enterprises" do
produces "application/json"

response "200", "successful" do
run_test! do
expect(json_response).to include(
"@id" => "http://test.host/api/dfc/affiliate_sales_data",
"@type" => "dfc-b:Person",
)
response "200", "successful", feature: :affiliate_sales_data do
let(:startDate) { Date.yesterday }
let(:endDate) { Time.zone.today }

before do
order = create(:order_with_totals_and_distribution, :completed)
ConnectedApps::AffiliateSalesData.new(
enterprise: order.distributor
).connect({})
end

context "with date filters" do
let(:startDate) { Date.tomorrow }
let(:endDate) { Date.tomorrow }

run_test! do
expect(json_response).to include(
"@id" => "http://test.host/api/dfc/affiliate_sales_data",
"@type" => "dfc-b:Person",
)

expect(json_response["dfc-b:affiliates"]).to eq nil
end
end

context "not filtered" do
run_test! do
expect(json_response).to include(
"@id" => "http://test.host/api/dfc/affiliate_sales_data",
"@type" => "dfc-b:Person",
)
expect(json_response["dfc-b:affiliates"]).to be_present
end
end
end

response "400", "bad request" do
let(:startDate) { "yesterday" }
let(:endDate) { "tomorrow" }

run_test!
end
end
end
Expand Down
37 changes: 37 additions & 0 deletions engines/dfc_provider/spec/services/affiliate_sales_query_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,43 @@
RSpec.describe AffiliateSalesQuery do
subject(:query) { described_class }

describe ".data" do
let(:order) { create(:order_with_totals_and_distribution, :completed) }
let(:today) { Time.zone.today }
let(:yesterday) { Time.zone.yesterday }
let(:tomorrow) { Time.zone.tomorrow }

it "returns data" do
# Test data creation takes time.
# So I'm executing more tests in one `it` block here.
# And make it simpler to call the subject many times:
count_rows = lambda do |**args|
query.data(order.distributor, **args).count
end

# Without any filters:
expect(count_rows.call).to eq 1

# From today:
expect(count_rows.call(start_date: today)).to eq 1

# Until today:
expect(count_rows.call(end_date: today)).to eq 1

# Just today:
expect(count_rows.call(start_date: today, end_date: today)).to eq 1

# Yesterday:
expect(count_rows.call(start_date: yesterday, end_date: yesterday)).to eq 0

# Until yesterday:
expect(count_rows.call(end_date: yesterday)).to eq 0

# From tomorrow:
expect(count_rows.call(start_date: tomorrow)).to eq 0
end
end

describe ".label_row" do
it "converts an array to a hash" do
row = [
Expand Down
74 changes: 74 additions & 0 deletions swagger/dfc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ paths:
'404':
description: not found
"/api/dfc/affiliate_sales_data":
parameters:
- name: startDate
in: query
schema:
type: string
- name: endDate
in: query
schema:
type: string
get:
summary: Show sales data of person's affiliate enterprises
tags:
Expand All @@ -88,6 +97,71 @@ paths:
dfc-b:logo: ''
dfc-b:firstName: ''
dfc-b:familyName: ''
dfc-b:affiliates:
"@type": dfc-b:Enterprise
dfc-b:hasAddress:
"@type": dfc-b:Address
dfc-b:hasStreet: ''
dfc-b:hasPostalCode: '20170'
dfc-b:hasCity: ''
dfc-b:hasCountry: ''
dfc-b:latitude: 0.0
dfc-b:longitude: 0.0
dfc-b:region: ''
dfc-b:logo: ''
dfc-b:name: ''
dfc-b:hasDescription: ''
dfc-b:VATnumber: ''
dfc-b:supplies:
"@type": dfc-b:SuppliedProduct
dfc-b:name: 'Product #3 - 7198'
dfc-b:description: ''
dfc-b:hasQuantity:
"@type": dfc-b:QuantitativeValue
dfc-b:hasUnit: dfc-m:Gram
dfc-b:value: 1.0
dfc-b:alcoholPercentage: 0.0
dfc-b:lifetime: ''
dfc-b:usageOrStorageCondition: ''
dfc-b:totalTheoreticalStock: 0.0
dfc-b:concernedBy:
"@type": dfc-b:OrderLine
dfc-b:description: ''
dfc-b:quantity:
"@type": dfc-b:QuantitativeValue
dfc-b:hasUnit: dfc-m:Piece
dfc-b:value: 1.0
dfc-b:hasPrice:
"@type": dfc-b:QuantitativeValue
dfc-b:value: 10.0
dfc-b:partOf:
"@type": dfc-b:Order
dfc-b:orderNumber: ''
dfc-b:date: ''
dfc-b:belongsTo:
"@type": dfc-b:SaleSession
dfc-b:beginDate: ''
dfc-b:endDate: ''
dfc-b:quantity: 0.0
dfc-b:objectOf:
"@type": dfc-b:Coordination
dfc-b:coordinatedBy:
"@type": dfc-b:Enterprise
dfc-b:hasAddress:
"@type": dfc-b:Address
dfc-b:hasStreet: ''
dfc-b:hasPostalCode: '20170'
dfc-b:hasCity: ''
dfc-b:hasCountry: ''
dfc-b:latitude: 0.0
dfc-b:longitude: 0.0
dfc-b:region: ''
dfc-b:logo: ''
dfc-b:name: ''
dfc-b:hasDescription: ''
dfc-b:VATnumber: ''
'400':
description: bad request
"/api/dfc/enterprises/{enterprise_id}/catalog_items":
parameters:
- name: enterprise_id
Expand Down

0 comments on commit d52134d

Please sign in to comment.