xpost 0.1.4 → 0.1.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +5 -5
  2. data/.DS_Store +0 -0
  3. data/.gitignore +1 -2
  4. data/.rspec +0 -0
  5. data/Gemfile +0 -0
  6. data/LICENSE +0 -0
  7. data/README.md +0 -0
  8. data/TODO.md +1 -28
  9. data/lib/xpost.rb +6 -8
  10. data/lib/xpost/authentication.rb +0 -5
  11. data/lib/xpost/configuration.rb +0 -15
  12. data/lib/xpost/models.rb +5 -0
  13. data/lib/xpost/models/address.rb +38 -0
  14. data/lib/xpost/models/item.rb +31 -0
  15. data/lib/xpost/models/order.rb +54 -0
  16. data/lib/xpost/orders.rb +16 -57
  17. data/lib/xpost/version.rb +1 -1
  18. data/spec/{order/address/address_spec.rb → address_spec.rb} +0 -0
  19. data/spec/factories/addresses.rb +28 -46
  20. data/spec/factories/items.rb +10 -10
  21. data/spec/factories/orders.rb +16 -39
  22. data/spec/helpers.rb +0 -0
  23. data/spec/{order/items/item_spec.rb → item_spec.rb} +5 -5
  24. data/spec/line_item_spec.rb +16 -0
  25. data/spec/orders/order_create_spec.rb +46 -0
  26. data/spec/orders/order_for_pickup_spec.rb +17 -0
  27. data/spec/orders/{find_spec.rb → orders_find_spec.rb} +2 -3
  28. data/spec/orders/{track_spec.rb → orders_track_spec.rb} +2 -2
  29. data/spec/spec_helper.rb +0 -1
  30. data/spec/xpost_spec.rb +0 -27
  31. data/xpost.gemspec +2 -6
  32. metadata +17 -68
  33. data/lib/.DS_Store +0 -0
  34. data/lib/xpost/.DS_Store +0 -0
  35. data/lib/xpost/address.rb +0 -77
  36. data/lib/xpost/item.rb +0 -44
  37. data/lib/xpost/order.rb +0 -135
  38. data/lib/xpost/statuses.rb +0 -29
  39. data/sample/sample_essential_order_details.json +0 -63
  40. data/sample/sample_xpost_order-confirmed.json +0 -317
  41. data/sample/sample_xpost_order-for-pickup.json +0 -379
  42. data/sample/sample_xpost_order-pending.json +0 -306
  43. data/sample/webhook_sample.json +0 -105
  44. data/spec/order/cancel_spec.rb +0 -37
  45. data/spec/order/confirm_spec.rb +0 -38
  46. data/spec/order/create_spec.rb +0 -97
  47. data/spec/order/for_pickup_spec.rb +0 -42
  48. data/spec/order/get_shipping_label_spec.rb +0 -60
  49. data/spec/order/order_spec.rb +0 -96
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: e06c6e03fdd2dbef18cf861380df0b90a6566030c302d7f938f414e6e9ef6e5b
4
- data.tar.gz: f85c2920686b2dadbe01dd025a72639c0bed6031764ff1ca377d1d1c41b88e12
2
+ SHA1:
3
+ metadata.gz: daeea5bd3cf6a8f61328026b19276b5775e590b3
4
+ data.tar.gz: 852c2e8c12ef2eceb7d87dc456d5a8f13aeb12c4
5
5
  SHA512:
6
- metadata.gz: c8f23db4ed6dbcb26752f326da4cb1129f252283aa54e2f879d57e6ad8143d8e366de14c25b3b25ab830c244fc6ae27a1e6d045e4c2a76cc187bb564a8ea4d0c
7
- data.tar.gz: 1b4a3b4f3ae573e07ab3402165b785e02c6b7972aa35832bb61141a710c5bf450b7b42f5f56fcc6ffcc17319fd77d29cce7d4a76675ae1ad785ce08c7bb670a8
6
+ metadata.gz: 84bf7d5da6a979326ddbe82bc78976542d8dba1fe834ad6b22740e3c38acf469f1f961eab491626ca6c1ac1633bcdd0f308aa3d9981049a136bc96c7cfff99d3
7
+ data.tar.gz: e09a5977510ea684ec0c51d0bf2b0a1a5a76712756305276f91d2d790cca8d93849776cb1a8fabe1bcd1419ff61cc68829b64616e7f597a4b6a602c2a54031cd
data/.DS_Store CHANGED
File without changes
data/.gitignore CHANGED
@@ -7,5 +7,4 @@ gemfiles/vendor/*
7
7
  tmp/
8
8
  spec/reports/
9
9
 
10
- .rspec_status
11
- .env
10
+ .rspec_status
data/.rspec CHANGED
File without changes
data/Gemfile CHANGED
File without changes
data/LICENSE CHANGED
File without changes
data/README.md CHANGED
File without changes
data/TODO.md CHANGED
@@ -1,32 +1,5 @@
1
1
 
2
- # xpost To-Do's
3
-
4
- - it should be able to track order statuses on Orders.all (???)
5
-
6
- # Bonus To-Do's
7
2
 
8
- - it should find a way to remove the (@auth_token) requirement from all the methods
9
- - and error out if an @auth_token is missing from the config
10
- - OR
11
- - it should just generate auth_tokens all the time since the api_key + secret_keys should be present
12
- - and it should make sure that any method call will error out if a config isnt present
13
-
14
- - it should accept shopify order data
3
+ # xpost To-Do's
15
4
 
16
- # xpost Done
17
5
 
18
- - it returns the shipping labels for a single order
19
- - it returns all the shipping labels for an array of tracking numbers (no need to check for for-pickup)
20
- - link: orders/download/awb/zebra
21
- - return S3 link of AWB (airwaybills)
22
- - return S3 link of POD (proof of deliveries)
23
- - it should be able to mark an order for_pickup
24
- - it should be able to cancel an existing order
25
- - it should view an existing order
26
- - it should be able to confirm an existing order
27
- - it should be able to create an order
28
- - figure out line per line why the json file isn't reading the sub array
29
- - Xpost::Order.to_json
30
- - base details
31
- - delivery address
32
- - items
data/lib/xpost.rb CHANGED
@@ -1,15 +1,13 @@
1
-
2
1
  module Xpost
3
2
  autoload :Configuration, 'xpost/configuration'
4
3
  autoload :Authentication, 'xpost/authentication'
5
- autoload :Statuses, 'xpost/statuses'
4
+ autoload :Orders, 'xpost/orders'
6
5
 
7
- autoload :Orders, 'xpost/orders' # Generic xpost order methods (find, track, etc.)
8
- autoload :Order, 'xpost/order' # ActiveModel-type of Order class (Order.create, etc.)
9
- # autoload :OrderSerializer, 'serializers/order_serializer'
10
-
11
- autoload :Address, 'xpost/address'
12
- autoload :Item, 'xpost/item'
6
+ module Models
7
+ autoload :Address, 'xpost/models/address'
8
+ autoload :Item, 'xpost/models/item'
9
+ autoload :Order, 'xpost/models/order'
10
+ end
13
11
 
14
12
  class << self
15
13
  attr_accessor :configuration
@@ -10,11 +10,6 @@ module Xpost
10
10
  token = "#{header}.#{payload}.#{signature}"
11
11
  end
12
12
 
13
- def self.sample_auth_token
14
- config = Xpost::Configuration.sample_configuration
15
- Xpost::Authentication.authenticate(config.api_key, config.secret_key)
16
- end
17
-
18
13
  private
19
14
 
20
15
  def self.header
@@ -8,20 +8,5 @@ module Xpost
8
8
  @staging_url
9
9
  @production_url
10
10
  end
11
-
12
- def self.sample_configuration
13
- api_key_line = File.readlines('.env').first.chomp
14
- secret_key_line = File.readlines('.env').last.chomp
15
- api_key = api_key_line.split('=').last
16
- secret_key = secret_key_line.split('=').last
17
-
18
- sample_configuration = Xpost.configure do |config|
19
- config.api_key = api_key
20
- config.secret_key = secret_key
21
- config.staging_url = "https://api.staging.lbcx.ph/v1"
22
- config.production_url = "https://api.lbcx.ph/v1"
23
- end
24
- Xpost.configuration
25
- end
26
11
  end
27
12
  end
@@ -0,0 +1,5 @@
1
+ module Xpost
2
+ module Models
3
+
4
+ end
5
+ end
@@ -0,0 +1,38 @@
1
+ require 'active_model'
2
+ require 'set'
3
+
4
+ module Xpost
5
+ module Models
6
+ class Address
7
+ include ActiveModel::Model
8
+
9
+ REQUIRED_ADDRESS_PARAMETERS = Set[:name, :shipment, :line_1, :city, :state, :postal_code, :country]
10
+ OPTIONAL_ADDRESS_PARAMETERS = Set[:company, :title, :email, :phone_number, :mobile_number, :fax_number,
11
+ :district, :line_2, :remarks]
12
+
13
+ attr_accessor :name, :shipment, :line_1, :city, :state, :postal_code, :country
14
+ attr_accessor :company, :title, :email, :phone_number, :mobile_number, :fax_number, :district, :line_2, :remarks
15
+
16
+ validates_presence_of :name, :shipment, :line_1, :city, :state, :postal_code, :country
17
+
18
+ def initialize(options = {})
19
+ @shipment = options[:shipment]
20
+ @name = options[:name]
21
+ @email = options[:email]
22
+ @phone_number = options[:phone_number]
23
+ @mobile_number = options[:mobile_number]
24
+ @fax_number = options[:fax_number]
25
+ @company = options[:company]
26
+ @title = options[:title]
27
+ @line_1 = options[:line_1]
28
+ @line_2 = options[:line_2]
29
+ @city = options[:city]
30
+ @district = options[:district]
31
+ @state = options[:state]
32
+ @postal_code = options[:postal_code]
33
+ @country = options[:country]
34
+ @remarks = options[:remarks]
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,31 @@
1
+ require 'active_model'
2
+ require 'set'
3
+
4
+ module Xpost
5
+ module Models
6
+ class Item
7
+ include ActiveModel::Model
8
+
9
+ ITEM_TYPES = Set[:product, :shipping, :tax, :fee, :insurance, :discount]
10
+
11
+ attr_accessor :type, :description, :amount, :quantity, :metadata
12
+
13
+ validates_presence_of :type, :description, :amount
14
+ validate :check_item_type
15
+
16
+ def initialize(options = {})
17
+ @type = options[:type]
18
+ @description = options[:description]
19
+ @amount = options[:amount]
20
+ @quantity = options[:quantity]
21
+ @metadata = options[:metadata]
22
+ end
23
+
24
+ def check_item_type
25
+ if self.type.present? && !ITEM_TYPES.include?(self.type.to_sym)
26
+ errors.add(:type, "wrong item type")
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,54 @@
1
+ require 'active_model'
2
+ require 'set'
3
+
4
+ module Xpost
5
+ module Models
6
+ class Order
7
+ include ActiveModel::Model
8
+
9
+ CONFIRMABLE_PARAMETERS = Set[:status, :email, :buyer_name, :contact_number, :delivery_address, :items,
10
+ :shipment, :total, :currency, :payment_method, :payment_provider]
11
+ FOR_PICKUP_PARAMETERS = Set[:pickup_address, :pickup_at]
12
+
13
+ attr_accessor :email, :buyer_name, :contact_number
14
+ attr_accessor :total, :currency, :payment_method, :payment_provider
15
+ attr_accessor :delivery_address, :pickup_address
16
+ attr_accessor :status, :items, :shipment
17
+
18
+ validates_presence_of :email, :buyer_name, :contact_number
19
+ validates_presence_of :delivery_address
20
+
21
+ def initialize(options = {})
22
+ @status = options[:status]
23
+ @email = options[:email]
24
+ @buyer_name = options[:buyer_name]
25
+ @contact_number = options[:contact_number]
26
+ @delivery_address = options[:delivery_address]
27
+ @items = options[:items]
28
+ @shipment = options[:shipment]
29
+ @total = options[:total]
30
+ @currency = options[:currency]
31
+ @payment_method = options[:payment_method]
32
+ @payment_provider = options[:payment_provider]
33
+ @pickup_address = options[:pickup_address]
34
+ @pickup_at = options[:pickup_at]
35
+ end
36
+
37
+ def confirmable?
38
+ self.valid? && self.delivery_address.present?
39
+ end
40
+
41
+ # https://docs.quadx.xyz/#5f38afd0-66bb-468f-ab4e-993d4745a257
42
+ # Sets the order status to canceled. An order can be canceled provided they have not passed the cutoff date and time as specified in the contract.
43
+ def cancellable?
44
+ true
45
+ end
46
+
47
+ # https://docs.quadx.xyz/#c831dc25-2de4-36c5-c321-8e9db0fc2105
48
+ # The following fields can be updated provided they have not passed the cutoff date and time as specified in the contract.
49
+ def updatable?
50
+ true
51
+ end
52
+ end
53
+ end
54
+ end
data/lib/xpost/orders.rb CHANGED
@@ -6,28 +6,17 @@ require 'typhoeus'
6
6
  # order = Order.create({...})
7
7
  # order.confirm / order.cancel
8
8
  # order.for_pickup(pickup_address, pickup_date)
9
+ # order.update({...})
9
10
 
10
11
  module Xpost
11
12
  class Orders
12
13
  # cant actually get all orders since its paginated
13
- def self.all(auth_token, status = nil)
14
- valid_xpost_statuses = ["pending", "confirmed", "for_pickup", "picked_up",
15
- "failed_pickup", "failed_delivery", "claimed",
16
- "return_in_transit", "returned", "failed_return",
17
- "out_for_delivery", "for_consolidation", "consolidated",
18
- "for_dropoff", "dropped_off", "for_transfer", "for_acceptance",
19
- "accepted", "canceled", "in_transit", "delivered"]
20
-
21
- if valid_xpost_statuses.include?(status)
22
- all_orders_url = "orders?status=#{status}"
23
- else
24
- all_orders_url = "orders"
25
- end
14
+ def self.all(auth_token)
15
+ all_orders_url = "orders"
26
16
 
27
17
  get_url(all_orders_url, headers: auth_header(auth_token))
28
18
  end
29
19
 
30
- # gets all the details of an order
31
20
  def self.find(auth_token, tracking_number)
32
21
  find_order_url = "orders/#{tracking_number}"
33
22
 
@@ -35,7 +24,6 @@ module Xpost
35
24
  res = res[:message] == "Not Found" ? "Not Found" : res
36
25
  end
37
26
 
38
- # only gets the order tat (turnaround time) info
39
27
  def self.track(auth_token, tracking_number)
40
28
  track_order_url = "orders/#{tracking_number}"
41
29
 
@@ -43,66 +31,37 @@ module Xpost
43
31
  res = res[:message] == "Not Found" ? "Not Found" : { timeline: res[:tat], events: res[:events] }
44
32
  end
45
33
 
46
- def self.exists?(auth_token, tracking_number)
47
- find_order_url = "orders/#{tracking_number}"
48
- res = get_url(find_order_url, headers: auth_header(auth_token))
49
- res[:status] != 404 && res[:message] != "Not Found"
50
- end
51
-
52
- def self.create(auth_token, order = nil, shipment = nil, reference_id = nil)
53
- raise "Missing order data" if order.nil?
54
- raise "Missing shipment data" if shipment.nil?
55
-
56
- order.shipment = shipment
57
- order.reference_id = reference_id
34
+ def self.create(auth_token, options = {})
35
+ raise "Missing order data" if options[:order_data].empty?
58
36
 
59
- res = post_url("orders", data: order, headers: auth_header(auth_token))
37
+ create_order_url = "orders"
38
+ order_data = options[:order_data]
39
+
40
+ res = post_url(create_order_url, data: order_data, headers: auth_header(auth_token))
60
41
  end
61
42
 
62
- def self.confirm(auth_token, tracking_number, payment_reference_id = nil)
63
- # TODO: these checks are expensive (potentially three back and forth requests)
64
- raise "Order not found" unless Xpost::Orders.exists?(auth_token, tracking_number)
65
- raise "Order isn't pending" if Xpost::Orders.find(auth_token, tracking_number)[:status] != "pending"
66
-
43
+ def self.confirm(auth_token, tracking_number, payment_reference_id)
67
44
  confirm_order_url = "orders/#{tracking_number}/confirm"
68
45
 
69
46
  res = put_url(confirm_order_url, data: payment_reference_id, headers: auth_header(auth_token))
70
47
  res = res[:message] == "Not Found" ? "Not Found" : res
71
48
  end
72
49
 
73
- def self.for_pickup(auth_token, tracking_number, pickup_address)
74
- raise "Order isn't confirmed" if Xpost::Orders.find(auth_token, tracking_number)[:status] != "confirmed"
75
- for_pickup_url = "orders/#{tracking_number}/for-pickup"
76
-
77
- raise "Missing pickup address" if pickup_address.nil?
78
- raise "Invalid pickup address" unless pickup_address.valid?
79
- pickup_address = { pickup_address: pickup_address.attributes }
80
-
81
- res = put_url(for_pickup_url, data: pickup_address, headers: auth_header(auth_token))
82
- res = res[:message] == "Not Found" ? "Not Found" : res
83
- end
84
-
85
50
  def self.cancel(auth_token, tracking_number)
86
51
  cancel_order_url = "orders/#{tracking_number}/cancel"
87
- raise "Order isn't pending" if Xpost::Orders.find(auth_token, tracking_number)[:status] != "pending"
88
52
 
89
53
  res = put_url(cancel_order_url, headers: auth_header(auth_token))
90
54
  res = res[:message] == "Not Found" ? "Not Found" : res
91
55
  end
92
56
 
93
- def self.get_shipping_labels(auth_token, tracking_number)
94
- if tracking_number.kind_of?(Array)
95
- shipping_labels_url = "orders/download/awb/zebra"
57
+ def self.for_pickup(auth_token, tracking_number, pickup_address)
58
+ pickup_address = Xpost::Models::Address.new(pickup_address)
59
+ for_pickup_url = "orders/#{tracking_number}/for-pickup"
96
60
 
97
- res = post_url(shipping_labels_url, data: tracking_number, headers: auth_header(auth_token))
98
- res = res[:message] == "Not Found" ? "Not Found" : res
99
- else
100
- raise "Order isn't for_pickup" if Xpost::Orders.find(auth_token, tracking_number)[:status] != "for_pickup"
101
- shipping_label_url = "orders/#{tracking_number}/awb?type=zebra"
61
+ raise "Invalid address" unless pickup_address.valid?
102
62
 
103
- res = get_url(shipping_label_url, headers: auth_header(auth_token))
104
- res = res[:message] == "Not Found" ? "Not Found" : res
105
- end
63
+ res = put_url(for_pickup_url, data: pickup_address, headers: auth_header(auth_token))
64
+ res = res[:message] == "Not Found" ? "Not Found" : res
106
65
  end
107
66
 
108
67
  private
data/lib/xpost/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Xpost
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.21"
3
3
  end
@@ -1,56 +1,38 @@
1
1
  FactoryBot.define do
2
- factory :address, class: Xpost::Address do
3
- name { "Bobby Axelrod" }
4
- line_1 { "Axe Capital" }
2
+ factory :address, class: Xpost::Models::Address do
3
+ name "Bobby Axelrod"
4
+ line_1 "Axe Capital"
5
5
  end
6
6
 
7
- factory :required_address, class: Xpost::Address do
8
- name { "Bobby Axelrod" }
9
- line_1 { "BGC Corporate Centre" }
10
- city { "Taguig" }
11
- state { "Metro Manila" }
12
- postal_code { "1634" }
13
- country { "PH" }
7
+ factory :required_address, class: Xpost::Models::Address do
8
+ name "Bobby Axelrod"
9
+ shipment "small-pouch"
10
+ line_1 "855 Sixth Avenue"
11
+ city "New York"
12
+ state "NY"
13
+ postal_code 10001
14
+ country "US"
14
15
 
15
16
  initialize_with { new(attributes) }
16
17
  end
17
18
 
18
- factory :complete_address, class: Xpost::Address do
19
- name { "Bobby Axelrod" }
20
- line_1 { "BGC Corporate Centre" }
21
- line_2 { "5th floor" }
22
- city { "Taguig" }
23
- state { "Metro Manila" }
24
- postal_code { "1634" }
25
- country { "PH" }
26
- company { "Axe Capital" }
27
- title { "CEO" }
28
- email { "bobby@axe.com" }
29
- phone_number { "12345678" }
30
- mobile_number { "091712345678" }
31
- fax_number { "12345678" }
32
- district { "BGC" }
33
- remarks { "Send ASAP" }
34
-
35
- initialize_with { new(attributes) }
36
- end
37
-
38
- factory :complete_address_pickup, class: Xpost::Address do
39
- name { "Taylor Mason" }
40
- line_1 { "BGC Corporate Centre" }
41
- line_2 { "7th floor" }
42
- city { "Taguig" }
43
- state { "Metro Manila" }
44
- postal_code { "1634" }
45
- country { "PH" }
46
- company { "Taylor Mason Capital" }
47
- title { "CEO" }
48
- email { "taylor@tmcapital.com" }
49
- phone_number { "12345678" }
50
- mobile_number { "091712345678" }
51
- fax_number { "12345678" }
52
- district { "BGC" }
53
- remarks { "" }
19
+ factory :complete_address, class: Xpost::Models::Address do
20
+ name "Bobby Axelrod"
21
+ shipment "small-pouch"
22
+ line_1 "855 Sixth Avenue"
23
+ city "New York"
24
+ state "NY"
25
+ postal_code 10001
26
+ country "US"
27
+ company "Axe Capital"
28
+ title "CEO"
29
+ email "bobby@axe.com"
30
+ phone_number "12345678"
31
+ mobile_number "091712345678"
32
+ fax_number "12345678"
33
+ district "Manhattan"
34
+ line_2 "5th floor"
35
+ remarks "Send ASAP"
54
36
 
55
37
  initialize_with { new(attributes) }
56
38
  end