Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GCW-3407 Gogox Gem Integration and Transport APIs #1195

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 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
6 changes: 6 additions & 0 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,9 @@ STOCKIT_API_TOKEN=

SLACK_API_TOKEN=
SLACK_PIN_CHANNEL=

GOGOX_CLIENT_ID=
GOGOX_CLIENT_SECRET=
GOGOX_GRANT_TYPE=
GOGOX_HOST=
GOGOX_PAYMENT_METHOD=
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
GIT
remote: [email protected]:crossroads/go_go_van_api.git
revision: 3cbc5590e2a11a7903483de276bc668be88843cb
revision: 9e50b4261aef81edbfbebcd333b513d94b115b41
branch: master
specs:
go_go_van_api (0.0.1)
Expand Down
71 changes: 71 additions & 0 deletions app/controllers/api/v1/transports_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
module Api
module V1
class TransportsController < Api::V1::ApiController

skip_authorization_check
swatijadhav marked this conversation as resolved.
Show resolved Hide resolved

api :GET, '/v1/transports/providers', "List all GoodCity Tranports Options."
def providers
render json: TransportProvider.all.cached_json
end

api :POST, '/v1/transports/quotation', "Get provider quotation"
param :provider, String, desc: "Provider selected for transport"
param :vehicle_type, String, desc: "Transport vehicle-type"
param :offer_id, String, desc: "Id of the offer"
swatijadhav marked this conversation as resolved.
Show resolved Hide resolved
param :schedule_at, String, desc: "Scheduled time for delivery"
param :district_id, String, desc: "Id of the district"
def quotation
order_price = TransportService.new(transport_params.to_h).quotation
render json: order_price.to_json
end

api :POST, '/v1/transports/book', "Book transport"
param :provider, String, desc: "Provider selected for transport"
param :vehicle_type, String, desc: "Transport vehicle-type"
param :offer_id, String, desc: "Id of the offer"
param :schedule_at, String, desc: "Scheduled time for delivery"
param :district_id, String, desc: "Id of the district"
param :pickup_contact_name, String, desc: "Contact Person Name"
param :pickup_contact_phone, String, desc: "Contact Person Mobile"
param :pickup_street_address, String, desc: "Pickup Address"
def book
order_info = TransportService.new(transport_params.to_h).book
swatijadhav marked this conversation as resolved.
Show resolved Hide resolved
render json: order_info.to_json
swatijadhav marked this conversation as resolved.
Show resolved Hide resolved
end

api :GET, '/v1/transports/:id/order_details', "Get GoodCity Tranport order details."
def order_details
order_info = TransportService.new({booking_id: params[:id]}).status
render json: order_info.to_json
end

api :POST, '/v1/transports/:id/cancel_order', "Cancel GoodCity Tranport order."
def cancel_order
order_info = TransportService.new({booking_id: params[:id]}).cancel
render json: order_info.to_json
end

api :POST, '/v1/transports/update_gogox_order', "Webhook to update GOGOX order status"
def update_gogox_order
# setup ngrok and inspect response
# response details are not yet available from Gogox Provider
end

private

def transport_params
set_district_id unless params["district_id"].presence
params.permit([
"scheduled_at", "district_id", "offer_id", "provider", "vehicle_type",
"pickup_street_address", "pickup_contact_name", "pickup_contact_phone"
])
end

def set_district_id
params["district_id"] = User.current_user.address.district_id
end

end
end
end
3 changes: 3 additions & 0 deletions app/models/transport_provider.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class TransportProvider < ApplicationRecord
include CacheableJson
end
2 changes: 2 additions & 0 deletions app/models/transport_provider_order.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class TransportProviderOrder < ApplicationRecord
swatijadhav marked this conversation as resolved.
Show resolved Hide resolved
end
5 changes: 5 additions & 0 deletions app/serializers/api/v1/transport_provider_serializer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module Api::V1
class TransportProviderSerializer < ApplicationSerializer
attributes :id, :name, :logo, :description, :metadata
end
end
127 changes: 127 additions & 0 deletions app/services/gogox.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
class Gogox
swatijadhav marked this conversation as resolved.
Show resolved Hide resolved

attr_accessor :params, :time, :vehicle, :district_id

VEHICLE_TYPES = ["van", "mudou", "mudou9"]

def initialize(options = {})
@params = options
@time = parse_pickup_time(options[:scheduled_at])
@vehicle = options[:vehicle_type]
@district_id = options[:district_id]
swatijadhav marked this conversation as resolved.
Show resolved Hide resolved
end

# Rsponse
# {
# "uuid" => "2f859363-5c43-4fe2-9b91-6c6c43d610d2",
# "status" => "pending",
# "vehicle_type" => "van",
# "payment_method" => "prepaid_wallet",
# "courier" => {},
# "pickup" => {
# "name" => "Swati J",
# "street_address" => "123",
# "floor_or_unit_number" => nil,
# "schedule_at" => 1609242940,
# "location" => {"lat" => 22.5029632, "lng" => 114.1277213},
# "contact" => {
# "name" => "Swati J",
# "phone_number" => "+85251111113",
# "phone_extension" => nil
# }
# },
# "destinations" => [{
# "name" => "GCAdmin User",
# "street_address" => "Santa Peak Road",
# "floor_or_unit_number" => nil,
# "location" => {"lat" => 32.3700365, "lng" => 120.9930016},
# "contact" => {
# "name" => "GCAdmin User",
# "phone_number" => "+85251111111"
# }
# }],
# "note_to_courier" => nil,
# "price" => {"amount" => 15000, "currency" => "HKD"},
# "price_breakdown" => [{"key" => "fee", "amount" => 15000}]
# }
def book
GogoxApi::Transport.new(order_attributes).order
end

# Response:
# {
# "vehicle_type" => "van",
# "estimated_price" => {"amount" => 15000, "currency" => "HKD"},
# "estimated_price_breakdown" => [{"key" => "fee", "amount" => 15000}]
# }
def quotation
GogoxApi::Transport.new(quotation_attributes).quotation
end

class << self

def transport_status(booking_id)
GogoxApi::Transport.new.status(booking_id)
end

# Response
# Response is nil on successful cancellation of GOGOX transport
def cancel_order(booking_id)
response = GogoxApi::Transport.new.cancel(booking_id)
if !response
{
order_uuid: booking_id,
status: "cancelled"
}
end
end

end

private

def order_attributes
{
'vehicle_type': vehicle_type,
"pickup_location": params[:pickup_location],
"pickup_street_address": params[:pickup_street_address],
"scheduled_at": parse_time,
"pickup_contact_name": params[:pickup_contact_name],
"pickup_contact_phone": params[:pickup_contact_phone],
"destination_location": params[:destination_location],
"destination_street_address": params[:destination_street_address],
"destination_contact_name": params[:destination_contact_name],
"destination_contact_phone": params[:destination_contact_phone]
}
end

def quotation_attributes
{
'vehicle_type': vehicle_type,
"scheduled_at": parse_time,
"pickup_location": params[:pickup_location],
"destination_location": params[:destination_location]
}
end

def vehicle_type
if vehicle.blank? || !VEHICLE_TYPES.include?(vehicle)
raise(ValueError, "vehicle should be from #{VEHICLE_TYPES.join(', ')}")
end
vehicle
end

def parse_pickup_time(time = nil)
return time if time.present?

# next available date within next 5 days
next_available_date = DateSet.new(5, 1).available_dates.first
(next_available_date.beginning_of_day + 12.hours)
end

def parse_time
DateTime.parse(@time.to_s).to_i
end

class ValueError < StandardError; end
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of just value error defining here, create a error in errors.rb
something like TransportationServiceError

end
124 changes: 124 additions & 0 deletions app/services/transport_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
class TransportService

attr_accessor :provider_name, :params, :provider, :booking_id, :user, :district_id

def initialize(options={})
@params = options
@provider_name = options && options["provider"]
@provider ||= Object::const_get(provider_name)
swatijadhav marked this conversation as resolved.
Show resolved Hide resolved
@booking_id = options && options["booking_id"]

fetch_user
fetch_district_id
end

def quotation
@provider.new(quotation_attributes).quotation
end

def book
response = @provider.new(order_attributes).book
storeOrderDetails(response)
end

def cancel
response = @provider.cancel_order(booking_id)
if response
updateOrderDetails({
status: "cancelled",
order_uuid: booking_id
})
end
end

def status
response = @provider.transport_status(booking_id)
if response
updateOrderDetails({
status: response["status"],
order_uuid: booking_id,
metadata: response
})
end
end

private

def storeOrderDetails(response)
swatijadhav marked this conversation as resolved.
Show resolved Hide resolved
TransportProviderOrder.create(
transport_provider_id: TransportProvider.find_by(name: provider_name).try(:id),
order_uuid: response["uuid"],
status: response["status"],
schedule_at: response["pickup"]["schedule_at"],
metadata: response,
offer_id: @params["offer_id"]
)
end

def updateOrderDetails(response)
order = TransportProviderOrder.find_by(order_uuid: response["order_uuid"])
order.update_attributes(response)
end

def quotation_attributes
{
'vehicle_type': @params["vehicle_type"],
"scheduled_at": @params["scheduled_at"],
"pickup_location": pickup_location,
"destination_location": destination_location
}
end

def pickup_location
pickup_district = District.find(@district_id)
[pickup_district.latitude, pickup_district.longitude]
end

# TODO: Update crossroads geolocation values
def destination_location
[32.3790365, 120.9001416]
end

# TODO: Change
def destination_street_address
"Santa Peak Road"
end

# TODO: Change
def destination_contact_name
"GCAdmin User"
end

# TODO: Change
def destination_contact_phone
"+85251111111"
end

def order_attributes
{
'vehicle_type': @params["vehicle_type"],
"pickup_location": pickup_location,
"pickup_street_address": params[:pickup_street_address],
"scheduled_at": params[:schedule_at],
"pickup_contact_name": params[:pickup_contact_name] || @user.full_name,
"pickup_contact_phone": params[:pickup_contact_phone] || @user.mobile,
"destination_location": destination_location,
"destination_street_address": destination_street_address,
"destination_contact_name": destination_contact_name,
"destination_contact_phone": destination_contact_phone
}
end

def fetch_user
@user ||= if @params["user_id"].present?
User.find_by(id: @params["user_id"])
else
User.current_user
end
end

def fetch_district_id
@district_id ||= @params["district_id"].presence || @user.address.district_id
end

end
9 changes: 8 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
resources :users do
get :me, on: :collection
end

resources :shareables, only: [:show, :index, :create, :destroy, :update] do
collection do
delete :unshare
Expand Down Expand Up @@ -215,6 +215,13 @@
resources :printers_users, only: [:create, :update]
resources :processing_destinations, only: :index

get "transports/providers", to: "transports#providers"
swatijadhav marked this conversation as resolved.
Show resolved Hide resolved
post "transports/quotation", to: "transports#quotation"
post "transports/book", to: "transports#book"
get "transports/:id/order_details", to: "transports#order_details"
post "transports/:id/cancel_order", to: "transports#cancel_order"
post "transports/update_gogox_order", to: "transports#update_gogox_order"

# routes used in stock app
get "designations", to: "orders#index"
get "designations/:id", to: "orders#show"
Expand Down
12 changes: 12 additions & 0 deletions db/migrate/20201210092143_create_transport_providers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class CreateTransportProviders < ActiveRecord::Migration[5.2]
def change
create_table :transport_providers do |t|
t.string :name
t.string :logo
t.text :description
t.jsonb :metadata, default: '{}'

t.timestamps
end
end
end
Loading