Skip to content

Commit

Permalink
Progress on app/services/lightspeed_import. Failing with woocommerce_…
Browse files Browse the repository at this point in the history
…api URI.encode.
  • Loading branch information
jcwatson11 committed Dec 15, 2024
1 parent 193c78a commit 5ea0921
Show file tree
Hide file tree
Showing 18 changed files with 325 additions and 3 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ gem "salesforce_bulk_api"
gem "sidekiq"
gem "sidekiq-cron"
gem "woocommerce_api"
gem "httparty"

group :development, :test do
gem "bundler-audit"
Expand Down
1 change: 1 addition & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ DEPENDENCIES
dogstatsd-ruby (~> 5.3)
dotenv-rails
factory_bot_rails
httparty
importmap-rails
lightspeed_pos!
lograge
Expand Down
14 changes: 14 additions & 0 deletions app/controllers/lightspeedauth_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class LightspeedauthController < ApplicationController
def index
# Get the code from the request
code = params[:code]
# Get the access token
token = Lightspeed::Auth.get_access_token(code)
# write the current response to the file system at APP_ROOT/lightspeed_auth.json
File.open("#{Rails.root}/lightspeed_auth.json", 'w') do |f|
f.write(token.to_json)
end
# Redirect to the home page
redirect_to root_path
end
end
10 changes: 10 additions & 0 deletions app/controllers/lightspeedinit_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class LightspeedinitController < ApplicationController
# Redirect to lightspeed auth login page
LIGHTSPEED_AUTH_REQUEST_URL = ENV['LIGHTSPEED_AUTH_REQUEST_URL']

def index
url = LIGHTSPEED_AUTH_REQUEST_URL.dup
url.sub! 'CLIENT_ID', ENV['LIGHTSPEED_CLIENT_ID']
redirect_to url
end
end
2 changes: 2 additions & 0 deletions app/helpers/lightspeedauth_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module LightspeedauthHelper
end
2 changes: 2 additions & 0 deletions app/helpers/lightspeedinit_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module LightspeedinitHelper
end
106 changes: 103 additions & 3 deletions app/services/lightspeed_import.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,109 @@
require 'woocommerce_api'

class LightspeedImport

@ls_client = nil
@ls_account = nil
@woo = nil

def initialize
@client = Lightspeed::Client.new
@ls_client = Lightspeed::Client.new(oauth_token_holder: LightspeedTokenHolder.new)
@ls_account = @ls_client.accounts.all.first
@woo = WooCommerce::API.new(
ENV['WOO_API_URL'].to_s,
ENV['WOO_API_KEY'].to_s,
ENV['WOO_API_SECRET'].to_s,
{
version: "v3"
}
)
end

def ls_client
@ls_client
end

def ls_account
@ls_account
end

def woo
@woo
end

def get_shops
shops = @ls_account.shops.all
shops
end

def get_products_from_woo(limit = 0)
query = {
status:'publish',
}
if limit > 0
query[:limit] = limit
end
response = @woo.get("products", query)
if response.code != 200
puts "Error getting products from WooCommerce"
puts response
return []
end
response.parsed_response
end

def new_job(shop_id, start_date, end_date)
shop = @ls_account.shops.find(shop_id)
context = {
shop_id: shop_id,
start_date: start_date,
end_date: end_date,
event_code: shop.Contact['custom']
}
# eventually save this in the job table
context
end

def get_sales(shop_id, start_date, end_date)
# /Account/27010/Sale.json?
# sort=completeTime
# &completed=true
# &load_relations=all
# &shopID=16
# &completed=true
# &completeTime=><,2020-01-01,2020-01-31
params = {
shopID: shop_id,
load_relations: 'all',
completed: 'true',
completeTime: "><,#{start_date},#{end_date}",
}
count = @ls_account.sales.size(params: params)
sales = @ls_account.sales.all(params: params)
sales
end

def process_job(job_id)
# TODO
# Process the job
# 1. Get job record from the jobs table
# 2. Update the job status to PROCESSING
# Get the job context
# Get list of all sales for the shop_id between start_date and end_date (paging included)
# Optimize sales data to remove extreneous data from the Object
# Save the sales data to the context object
# Log messageg "Sales retrived from Lightspeed
end

def complete_job(job_id)
# TODO
# Get job record from the jobs table
# Update the job status to COMPLETED
end

def extract
@client.get('/products.json')
def start_jobs
# TODO
# Poll the jobs table for any job in CREATED status
# If found, start the job
end
end
70 changes: 70 additions & 0 deletions app/services/lightspeed_token_holder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
require 'httparty'
require 'dotenv'
# Load .env.local instead of .env
Dotenv.overload('.env.local')

class LightspeedTokenHolder

@token = nil
@refresh_token = nil
@expires_in = nil
@token_type = nil

def token
@token
end

def refresh_token
@refresh_token
end

def expires_in
@expires_in
end

def token_type
@token_type
end

LIGHTSPEED_API_AUTH_ROOT = ENV['LIGHTSPEED_API_AUTH_ROOT']
LIGHTSPEED_CLIENT_ID = ENV['LIGHTSPEED_CLIENT_ID']
LIGHTSPEED_CLIENT_SECRET = ENV['LIGHTSPEED_CLIENT_SECRET']

def initialize(token: nil, refresh_token: nil)
File.open(Rails.root.join('lightspeed_auth.json').to_s, 'r') do |f|
auth = JSON.parse(f.read)
@token = auth['access_token']
@refresh_token = auth['refresh_token']
end
@expires_in = 3600
@token_type = "Bearer"
end

def oauth_token
@token
end

def refresh_oauth_token
puts "Refreshing Lightspeed API token..."
url = LIGHTSPEED_API_AUTH_ROOT.dup
# use httparty to make a post request to the lightspeed auth endpoint
response = HTTParty.post(url, body: { client_id: LIGHTSPEED_CLIENT_ID, client_secret: LIGHTSPEED_CLIENT_SECRET, grant_type: 'refresh_token', refresh_token: @refresh_token })
if response.code == 200
puts "Token refreshed successfully - #{response.body}"
# write the refreshed response to the file
File.open(Rails.root.join('lightspeed_auth.json').to_s, 'w') do |f|
f.write(response.body)
end
# parse the response and return the new access_token
auth = JSON.parse(response.body)
@token = auth['access_token']
@refresh_token = auth['refresh_token']
@token
else
# log the error
Rails.logger.error("Error refreshing token: #{response.code} - #{response.body}")
false
end
@refresh_token
end
end
1 change: 1 addition & 0 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,4 @@ class Application < Rails::Application
config.generators.system_tests = nil
end
end

14 changes: 14 additions & 0 deletions config/initializers/woocommerce_api_patch.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# require 'woocommerce_api/lib/woocommerce_api'
# require 'uri'
#
# module WooCommerce
# class API.class_eval do
# def add_query_params endpoint, data
# return endpoint if data.nil? || data.empty?
#
# endpoint += "?" unless endpoint.include? "?"
# endpoint += "&" unless endpoint.end_with? "?"
# endpoint + URI.escape(flatten_hash(data).join("&"))
# end
# end
# end
17 changes: 17 additions & 0 deletions db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions lightspeed_auth.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"token_type":"Bearer","expires_in":3600,"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IlJUX09BVVRIMl8yMDI0XzA3XzIyIn0.eyJqdGkiOiJkODcyNDk2ZGNiZWFmMzhmNTYyY2RmYWEwMTY5NTAxNzI0ZjMzZmY5YmU3MzI1MTQ0Nzk3MmQzZjU1OTgwNTE4ZjQ3MjcyMjM5ZjczNTk4YiIsImlzcyI6Imh0dHBzOi8vY2xvdWQubGlnaHRzcGVlZGFwcC5jb20iLCJhdWQiOiI4Zjg1OTM0MTJlOWM1ZWFjNjEwZjRhZjQ0NTk0NTdjNGM0MjkxYWZhOTlmZDRhNjNkZDQxNTNiODk0ODQxMjk5Iiwic3ViIjoiMTU5NTMzNiIsImFjY3QiOiIyNzAxMCIsInNjb3BlIjoiZW1wbG95ZWU6YWxsIiwiaWF0IjoxNzM0MjMzNTA1LjA3NDQyOCwibmJmIjoxNzM0MjMzNTA1LjA3NDQyOCwiZXhwIjoxNzM0MjM3MTA1LjA1NzM4NX0.nxTZKqgbL1_TiqYj_Q7_me-VmiC8ND3R-bBP076kPGQX_32cxbDVBJrYuKvFIZV83ACSM6Eq9uyQmAZLeFjpi36PQsgBWeSFvKMnUklpqZmCc32m7Kqwf2SaXWbnpFef9oisYBKCrtyEdIh5e-sFNRTeqh69lZfcKfLj7fymVmRBAorJ_uKItIywoDn-B5nRBmt2LIhIxjfbI0YwOKrNULn8rSqEK--gofB-yTePO2EUTYhAEDoZ0ZVF4WnJtJhJJCDSEC-YgjYcQZQLldkmJ356SM919It2McymzmAxxua7TMxygV9A5BizTvalCqZ6ZuEazTu3jeXist0lQxE5_Q","refresh_token":"def5020001018fbd81ae4fa4906bd82049698ad469b821b3962ed1e2b3808495343b30ec64cbf01d1a4498dc257a7a78cbf3d5d127b9debbdf10b9f4fbed696581395a30af062638f4d60bde3f328fca0aac4c2e3d44741d97ea0453bb06028fa6285bc79ac5d8d493ab0ed979659be8a7451a8a1f2698b75fa27e9aa63fffc338489c7cd5b60fccd6920353560bf64a073f97cf56a3e0147fee523711cb90494a1b2e8136bbaca88edbb06eeead27ac862218bffadbc3c51b3cb56b0ef880eee83e8e33506dd83afba798d86309a19287751516705aab0f9c94dcfbb1f0027884fec9da6cbc631c6b71992fee42dab5c24a601f137d3eba55e09322bde9a0ad53ed7a75dbbdacaa3e2eafb48ff8470b5129696e3550f304ff4e6ed239d8757a2b10835f6f2d80e9d6a1702a966d829777eff9513f3cbcd198a367aa037dc090e6d3f7495f1232098b96f19cf688a0280eaff1c74634fa5a3c313a6d1f24d8e2b499c91811456d4eb80688762b49f05c8278bebb0bf7e5c89ef32bcd1a81b2f60d7fe59064170e8f2ee4873254f1bb981f82531385daa2929f15a2769346def0955fe7d1f0e76b5239e762d6ae0015f0db1f3833532f"}
15 changes: 15 additions & 0 deletions spec/helpers/lightspeedauth_helper_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require 'rails_helper'

# Specs in this file have access to a helper object that includes
# the LightspeedauthHelper. For example:
#
# describe LightspeedauthHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# expect(helper.concat_strings("this","that")).to eq("this that")
# end
# end
# end
RSpec.describe LightspeedauthHelper, type: :helper do
pending "add some examples to (or delete) #{__FILE__}"
end
15 changes: 15 additions & 0 deletions spec/helpers/lightspeedinit_helper_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require 'rails_helper'

# Specs in this file have access to a helper object that includes
# the LightspeedinitHelper. For example:
#
# describe LightspeedinitHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# expect(helper.concat_strings("this","that")).to eq("this that")
# end
# end
# end
RSpec.describe LightspeedinitHelper, type: :helper do
pending "add some examples to (or delete) #{__FILE__}"
end
7 changes: 7 additions & 0 deletions spec/requests/lightspeedauth_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require 'rails_helper'

RSpec.describe "Lightspeedauths", type: :request do
describe "GET /index" do
pending "add some examples (or delete) #{__FILE__}"
end
end
7 changes: 7 additions & 0 deletions spec/requests/lightspeedinit_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require 'rails_helper'

RSpec.describe "Lightspeedinits", type: :request do
describe "GET /index" do
pending "add some examples (or delete) #{__FILE__}"
end
end
25 changes: 25 additions & 0 deletions spec/services/lightspeed_import_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,30 @@
require 'rails_helper'

describe LightspeedImport do
# set global lightspeed import service
lsi = LightspeedImport.new

it('should initialize with a token holder') do
expect(lsi.ls_client.oauth_token).not_to be_nil
end

it('should get a list of shops') do
shops = lsi.get_shops
expect(shops.count).to be > 0
end

it('should initialize a new job') do
context = lsi.new_job 16, '2024-12-01', '2024-12-31'
expect(context[:event_code]).not_to be_nil
end

it('should get sales') do
sales = lsi.get_sales 16, '2024-12-06', '2024-12-07'
expect(sales.count).to be == 18
end

it('should get woo products') do
products = lsi.get_products_from_woo 1
expect(products.count).to be > 0
end
end
20 changes: 20 additions & 0 deletions spec/services/lightspeed_token_holder_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require 'rails_helper'

describe LightspeedTokenHolder do

it('should initialize with a token and refresh token') do
token_holder = LightspeedTokenHolder.new
expect(token_holder.token).not_to be_nil
expect(token_holder.refresh_token).not_to be_nil
end

it('should refresh the token') do
token_holder = LightspeedTokenHolder.new
old_token = token_holder.token
token_holder.refresh_oauth_token
expect(token_holder.token).not_to eq(old_token)
puts "Old token: #{old_token}"
puts "New token: #{token_holder.token}"
end

end

0 comments on commit 5ea0921

Please sign in to comment.