mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-18 04:39:14 +00:00
Filter sales data by dates
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -2,17 +2,16 @@
|
||||
|
||||
class AffiliateSalesDataBuilder < DfcBuilder
|
||||
class << self
|
||||
def person(user)
|
||||
DataFoodConsortium::Connector::Person.new(
|
||||
urls.affiliate_sales_data_url,
|
||||
affiliatedOrganizations: enterprises(user.affiliate_enterprises)
|
||||
)
|
||||
end
|
||||
|
||||
def enterprises(enterprises)
|
||||
AffiliateSalesQuery.data(enterprises).map do |row|
|
||||
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: suppliers,
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -8,16 +8,53 @@ RSpec.describe "AffiliateSalesData", swagger_doc: "dfc.yaml", rswag_autodoc: tru
|
||||
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
|
||||
|
||||
@@ -5,6 +5,43 @@ require_relative "../spec_helper"
|
||||
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 = [
|
||||
|
||||
@@ -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:
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user