xpost 0.1.4 → 0.1.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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