Skip to content
Draft
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
21 changes: 21 additions & 0 deletions db/migrations/062_geo_programs.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

Sequel.migration do
up do
create_table(:map_locations) do
primary_key :id
numeric :lat, null: false
numeric :lng, null: false
unique [:lat, :lng]
end
create_join_table(
{map_location_id: :map_locations, offering_id: :commerce_offerings},
name: :map_locations_commerce_offerings,
)
end

down do
drop_table(:map_locations)
drop_table(:map_locations_commerce_offerings)
end
end
5 changes: 5 additions & 0 deletions lib/suma/api/entities.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ class ImageEntity < BaseEntity
expose :url, &self.delegate_to(:uploaded_file, :absolute_url)
end

class MapLocationEntity < BaseEntity
expose :lat
expose :lng
end

class PaymentInstrumentEntity < BaseEntity
expose :id
expose :created_at
Expand Down
11 changes: 0 additions & 11 deletions lib/suma/api/me.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
require "grape"

require "suma/api"
require "suma/member/dashboard"

class Suma::API::Me < Suma::API::V1
include Suma::API::Entities
Expand Down Expand Up @@ -46,11 +45,6 @@ class Suma::API::Me < Suma::API::V1
present member, with: CurrentMemberEntity, env:
end

get :dashboard do
d = Suma::Member::Dashboard.new(current_member, at: current_time)
present d, with: DashboardEntity
end

params do
requires :language, values: ["en", "es"]
end
Expand All @@ -63,9 +57,4 @@ class Suma::API::Me < Suma::API::V1
present member, with: CurrentMemberEntity, env:
end
end

class DashboardEntity < BaseEntity
expose :cash_balance, with: Suma::API::Entities::MoneyEntity
expose :program_enrollments, as: :programs, with: Suma::API::Entities::ProgramEnrollmentEntity
end
end
22 changes: 18 additions & 4 deletions lib/suma/api/mobility.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,16 @@ class Suma::API::Mobility < Suma::API::V1
requires :ne, type: Array[BigDecimal], coerce_with: DecimalLocation
end
get :map_features do
current_member
me = current_member
min_lat, min_lng = params[:sw]
max_lat, max_lng = params[:ne]
ds = Suma::Mobility::RestrictedArea.intersecting(ne: [max_lat, max_lng], sw: [min_lat, min_lng])
ds = ds.order(:id)
result = {restrictions: ds.all}
restrictions_ds = Suma::Mobility::RestrictedArea.intersecting(ne: [max_lat, max_lng], sw: [min_lat, min_lng])
offerings_ds = Suma::Commerce::Offering.
for_map_display_to(me, as_of: current_time, min_lat:, min_lng:, max_lat:, max_lng:)
result = {
restrictions: restrictions_ds.order(:id).all,
commerce_offerings: offerings_ds.all,
}
present result, with: MobilityMapFeaturesEntity
end

Expand Down Expand Up @@ -174,8 +178,18 @@ class MobilityMapRestrictionEntity < BaseEntity
expose :bounds_numeric, as: :bounds
end

class MobilityMapProgramEntity < BaseEntity
expose :id
expose_translated :description
expose :period_end, as: :closes_at
expose :image, with: Suma::API::Entities::ImageEntity, &self.delegate_to(:images?, :first)
expose :rel_app_link, as: :app_link
expose :map_locations, with: Suma::API::Entities::MapLocationEntity
end

class MobilityMapFeaturesEntity < BaseEntity
expose :restrictions, with: MobilityMapRestrictionEntity
expose :programs, with: MobilityMapProgramEntity
end

class MobilityVehicleEntity < BaseEntity
Expand Down
17 changes: 11 additions & 6 deletions lib/suma/commerce/offering.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,14 @@ class Suma::Commerce::Offering < Suma::Postgres::Model(:commerce_offerings)
plugin :translated_text, :fulfillment_confirmation, Suma::TranslatedText
plugin :translated_text, :fulfillment_instructions, Suma::TranslatedText

many_to_many :programs,
class: "Suma::Program",
join_table: :programs_commerce_offerings,
left_key: :offering_id,
right_key: :program_id

one_to_many :fulfillment_options, class: "Suma::Commerce::OfferingFulfillmentOption"
one_to_many :offering_products, class: "Suma::Commerce::OfferingProduct"
one_to_many :carts, class: "Suma::Commerce::Cart"
many_to_many :map_locations,
class: "Suma::MapLocation",
join_table: :map_locations_commerce_offerings,
left_key: :offering_id,
right_key: :map_location_id

many_to_many :programs,
class: "Suma::Program",
Expand Down Expand Up @@ -156,6 +155,12 @@ def total_ordered_items = total_ordered_items_by_member.values.sum
def available_at(t)
return self.where(Sequel.pg_range(:period).contains(Sequel.cast(t, :timestamptz)))
end

def for_map_display_to(member, as_of:, min_lat:, min_lng:, max_lat:, max_lng:)
ds = self.available_at(as_of).eligible_to(member, as_of:)
map_locs_ds = Suma::MapLocation.search(min_lat:, min_lng:, max_lat:, max_lng:)
return ds.where(map_locations: map_locs_ds)
end
end

# @!attribute max_ordered_items_cumulative
Expand Down
20 changes: 20 additions & 0 deletions lib/suma/fixtures/map_locations.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

require "suma/fixtures"
require "suma/map_location"

module Suma::Fixtures::MapLocations
extend Suma::Fixtures

fixtured_class Suma::MapLocation

base :map_location do
self.lat ||= Faker::Number.between(from: -90.0, to: 90.0)
self.lng ||= Faker::Number.between(from: -180.0, to: 180.0)
end

decorator :at do |lat, lng|
self.lat = lat
self.lng = lng
end
end
4 changes: 4 additions & 0 deletions lib/suma/fixtures/offerings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,8 @@ module Suma::Fixtures::Offerings
decorator :with_programs, presave: true do |*programs|
programs.each { |p| self.add_program(p) }
end

decorator :located, presave: true do |lat, lng|
self.add_map_location(lat:, lng:)
end
end
25 changes: 25 additions & 0 deletions lib/suma/map_location.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

require "suma/postgres/model"

class Suma::MapLocation < Suma::Postgres::Model(:map_locations)
many_to_many :commerce_offerings,
class: "Suma::Commerce::Offering",
join_table: :map_locations_commerce_offerings,
right_key: :offering_id

class << self
def search_expr(min_lat:, min_lng:, max_lat:, max_lng:, lat_col: :lat, lng_col: :lng)
return (Sequel[lat_col] >= min_lat) &
(Sequel[lat_col] <= max_lat) &
(Sequel[lng_col] >= min_lng) &
(Sequel[lng_col] <= max_lng)
end
end

dataset_module do
def search(min_lat:, min_lng:, max_lat:, max_lng:)
return self.where(Suma::MapLocation.search_expr(min_lat:, min_lng:, max_lat:, max_lng:))
end
end
end
20 changes: 0 additions & 20 deletions lib/suma/member/dashboard.rb

This file was deleted.

1 change: 1 addition & 0 deletions lib/suma/postgres.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ def self.check_transaction(db, error_msg)
"suma/commerce/product_inventory",
"suma/external_credential",
"suma/image",
"suma/map_location",
"suma/member",
"suma/member/activity",
"suma/member/referral",
Expand Down
17 changes: 0 additions & 17 deletions spec/suma/api/me_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -136,21 +136,4 @@
expect(member.refresh.message_preferences).to have_attributes(preferred_language: "es")
end
end

describe "GET /v1/me/dashboard" do
it "returns the dashboard" do
led = Suma::Payment.ensure_cash_ledger(Suma::Fixtures.payment_account.create(member:))
Suma::Fixtures.book_transaction.to(led).create(amount: money("$10"))
Suma::Fixtures.program_enrollment.create(member:)

get "/v1/me/dashboard"

expect(last_response).to have_status(200)
expect(last_response).to have_json_body.
that_includes(
cash_balance: include(cents: 1000),
programs: have_length(1),
)
end
end
end
16 changes: 14 additions & 2 deletions spec/suma/api/mobility_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,10 @@ def get_same_location_vehicles(amount)

describe "GET /v1/mobility/map_features" do
it "returns the location of restricted areas within the given bounds" do
ra1 = Suma::Fixtures.mobility_restricted_area.
inbounds = Suma::Fixtures.mobility_restricted_area.
latlng_bounds(sw: [20, 120], ne: [50, 150]).
create(restriction: "do-not-park-or-ride")
ra2 = Suma::Fixtures.mobility_restricted_area.
outofbounds = Suma::Fixtures.mobility_restricted_area.
latlng_bounds(sw: [30, 130], ne: [50, 150]).
create(restriction: "do-not-park")

Expand Down Expand Up @@ -266,6 +266,18 @@ def get_same_location_vehicles(amount)
)
end

it "returns the offerings within the given bounds" do
inbounds = Suma::Fixtures.offering.located(20, 120).create
outbounds = Suma::Fixtures.offering.located(20, 130).create
not_located = Suma::Fixtures.offering.create

get "/v1/mobility/map_features", sw: [15, 110], ne: [25, 125]

expect(last_response).to have_status(200)
expect(last_response).to have_json_body.
that_includes(commerce_offerings: have_same_ids_as(inbounds))
end

it "401s if not logged in" do
logout
get "/v1/mobility/map_features", sw: [15, 110], ne: [25, 125]
Expand Down
22 changes: 22 additions & 0 deletions spec/suma/commerce/offering_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,28 @@
expect(with_program).to be_eligible_to(member_in_program, as_of:)
expect(with_program).to_not be_eligible_to(member_unapproved, as_of:)
end

it "can find offerings for display on the map" do
as_of = Time.now
program = Suma::Fixtures.program.create
member = Suma::Fixtures.member.create
Suma::Fixtures.program_enrollment(member:, program:).create

in_loc = Suma::Fixtures.map_location.at(20, 120).create
out_loc = Suma::Fixtures.map_location.at(50, 120).create

other_program = Suma::Fixtures.offering.with_programs(Suma::Fixtures.program.create).create
other_program.add_map_location(in_loc)
in_program = Suma::Fixtures.offering.with_programs(program).create
in_program.add_map_location(in_loc)
bad_loc_program = Suma::Fixtures.offering.with_programs(program).create
bad_loc_program.add_map_location(out_loc)
unavailable = Suma::Fixtures.offering.with_programs(program).closed.create
unavailable.add_map_location(in_loc)

ds = described_class.for_map_display_to(member, as_of:, min_lat: 15, max_lat: 25, min_lng: 110, max_lng: 130)
expect(ds.all).to have_same_ids_as(in_program)
end
end

describe "#begin_order_fulfillment" do
Expand Down
34 changes: 0 additions & 34 deletions spec/suma/member/dashboard_spec.rb

This file was deleted.

Loading