tcat 0.1.5 → 0.1.7

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 (5) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +41 -14
  3. data/lib/tcat/query.rb +103 -24
  4. data/lib/tcat/version.rb +1 -1
  5. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 66a34a4165a334cea5fc3e1297f49265cff8cff2099aa8ea6ea0912d953798a1
4
- data.tar.gz: 72cd8a878a16a17829ffbb0dfbe6588c04828ed1e72de0799f3fe66460b9451b
3
+ metadata.gz: 30282cc204d33385f1c2ad59b0c48a46e1365b6094bc2d0673b1f75b95f4ee40
4
+ data.tar.gz: 02b5cc602a18a28411a89c330d99af2a62fc61cdb0b21db6c29c5ce9c6fafd58
5
5
  SHA512:
6
- metadata.gz: 96960dd54febe02718c8fb068206b3d1b0d23ca45ddb65b4097920cdf58d87b5bba346e2fce0bcc3ef11109b67d78c6a00d6ad84d8d1899358ee094e4245f863
7
- data.tar.gz: d5a1a0ee708bb6179d62b8596af30137ecd0965f146bb6f009a3ac9b834242fe61046e553f6620a457e215c99f13375306c13bddbb7b011bf217614b1683f961
6
+ metadata.gz: 0a319a1f8fb97586fffd1154107b0c3e75994a669301061afaf6f53a9aa065a8a2f522d2b3173d7391fc1cdadbb011549b6120a32f1b4bb004e2a29b4c850ed9
7
+ data.tar.gz: fc47408a9feeaddf3cf2ec956940bf3a0835f4824faa1c6ca0c41a315dcd4e04efb171e1fc05e9c84685a17f355d0db680e557c9806ce2370e984f38ab3526af
data/README.md CHANGED
@@ -50,30 +50,42 @@ end
50
50
  query = Tcat::Query.new('your_tracking_number')
51
51
 
52
52
  # Get shipment status
53
- status = query.perform
54
-
55
- # Status will be one of the following:
53
+ status = query.status_code
54
+ # Returns one of the following:
56
55
  # :done - Successfully delivered
57
56
  # :delivering - Out for delivery
58
57
  # :collected - Package collected
59
58
  # :in_transit - In transit
60
59
  # :unknown - Unknown status
61
- ```
62
60
 
63
- ### Error Handling
61
+ # Get latest status details
62
+ latest = query.latest_status
63
+ if latest
64
+ puts "Status: #{latest.status}" # e.g. "Successfully delivered"
65
+ puts "Status code: #{latest.status_code}" # e.g. :done
66
+ puts "Time: #{latest.time}" # Time object
67
+ puts "Office: #{latest.office}" # e.g. "Tainan office"
68
+ puts "Last update: #{latest.last_update}" # Time object
69
+ end
64
70
 
65
- ```ruby
66
- begin
67
- status = query.perform
68
- rescue Tcat::HttpClient::RequestError => e
69
- puts "Network request error: #{e.message}"
70
- rescue Tcat::EncryptionService::EncryptionError => e
71
- puts "Encryption error: #{e.message}"
72
- rescue StandardError => e
73
- puts "Other error: #{e.message}"
71
+ # Get full shipment history
72
+ history = query.history
73
+ history.each do |item|
74
+ puts "Status: #{item.status}"
75
+ puts "Time: #{item.time}"
76
+ puts "Office: #{item.office}"
77
+ puts "---"
74
78
  end
75
79
  ```
76
80
 
81
+ ### Status Code Explanation
82
+
83
+ - `:done` - Successfully delivered
84
+ - `:delivering` - Out for delivery
85
+ - `:collected` - Package collected
86
+ - `:in_transit` - In transit
87
+ - `:unknown` - Unknown status
88
+
77
89
  ## Development
78
90
 
79
91
  1. Fork the project
@@ -104,6 +116,21 @@ This gem is available as open source under the terms of the [MIT License](https:
104
116
 
105
117
  ## Changelog
106
118
 
119
+ ### 0.1.7
120
+
121
+ - Improved method naming, removed get_ prefix
122
+ - Added `latest_status` method to get latest status details
123
+ - Added `history` method to get full shipment history
124
+ - Used `DeliveryItem` struct to provide more complete shipment information
125
+ - Improved error handling and logging
126
+ - Supported UTF-8 encoding
127
+
128
+ ### 0.1.6
129
+
130
+ - Refactored query parsing method
131
+ - Improved error handling
132
+ - Added test coverage
133
+
107
134
  ### 0.1.5 (2024-01-11)
108
135
 
109
136
  - Refactored HTTP request handling with new HttpClient class
data/lib/tcat/query.rb CHANGED
@@ -9,6 +9,8 @@ require_relative 'encryption_service'
9
9
  module Tcat
10
10
  # Query class handles making requests to the Tcat system
11
11
  class Query
12
+ DeliveryItem = Struct.new(:status, :status_code, :time, :office, :last_update, keyword_init: true)
13
+
12
14
  def initialize(tracking_number)
13
15
  @secret_string = Tcat.configuration.secret_string
14
16
  @secret_key = Tcat.configuration.secret_key
@@ -19,14 +21,38 @@ module Tcat
19
21
  @encryption_service = EncryptionService.new(@secret_key)
20
22
  end
21
23
 
22
- def perform
24
+ # Get current delivery status code
25
+ # @return [Symbol] Status code (:done, :delivering, :collected, :in_transit, :unknown)
26
+ def status_code
23
27
  response_body = @http_client.post(data)
24
- parse_response(response_body) if response_body
28
+ parse_status_code(response_body) if response_body
25
29
  rescue HttpClient::RequestError => e
26
30
  # Log error or handle it appropriately
27
31
  nil
28
32
  end
29
33
 
34
+ # Get complete delivery history
35
+ # @return [Array<DeliveryItem>] Array of delivery status items, sorted by time (newest first)
36
+ def history
37
+ response_body = @http_client.post(data)
38
+ if response_body
39
+ result = Ox.load(response_body, mode: :hash, with_cdata: true)
40
+ return [] if result.dig(:Result, :Status) != '0'
41
+ extract_delivery_history(result)
42
+ end
43
+ rescue StandardError => e
44
+ Rails.logger.error("Error getting delivery history: #{e.message}")
45
+ []
46
+ end
47
+
48
+ # Get latest delivery status with details
49
+ # @return [DeliveryItem, nil] Latest delivery status or nil if no history
50
+ def latest_status
51
+ items = history
52
+ return nil if items.empty?
53
+ items.first
54
+ end
55
+
30
56
  private
31
57
 
32
58
  def validate_secrets!
@@ -63,34 +89,87 @@ module Tcat
63
89
  raise "Failed to generate secret: #{e.message}"
64
90
  end
65
91
 
66
- def parse_response(xml)
67
- result = Ox.load(xml, mode: :hash, with_cdata: true)
92
+ def parse_status_code(xml)
93
+ begin
94
+ result = Ox.load(xml, mode: :hash, with_cdata: true)
95
+ return :error unless result.dig(:Result, :Status) == '0'
68
96
 
69
- return if result[:Result][:Status] != '0'
97
+ delivery_items = result.dig(:Result, :Content, :Item)
98
+ delivery_statuses = extract_delivery_statuses(delivery_items)
99
+
100
+ parse_status_message(delivery_statuses.uniq)
101
+ rescue StandardError => e
102
+ Rails.logger.error("Error parsing T-Cat response: #{e.message}")
103
+ :error
104
+ end
105
+ end
70
106
 
71
- statuses =
72
- if result[:Result][:Content][:Item].is_a?(Hash)
73
- [result[:Result][:Content][:Item][:Status].force_encoding('UTF-8')]
74
- elsif result[:Result][:Content][:Item].is_a?(Array)
75
- result[:Result][:Content][:Item].map do |item|
76
- item[:Status].force_encoding('UTF-8')
77
- end
78
- end
79
- parse_status_message(statuses.uniq)
107
+ def extract_delivery_history(result)
108
+ items = result.dig(:Result, :Content, :Item)
109
+ case items
110
+ when Hash
111
+ [parse_delivery_item(items)]
112
+ when Array
113
+ items.map { |item| parse_delivery_item(item) }
114
+ else
115
+ []
116
+ end.compact.sort_by(&:time).reverse
117
+ rescue StandardError => e
118
+ Rails.logger.error("Error parsing delivery history: #{e.message}")
119
+ []
80
120
  end
81
121
 
82
- def parse_status_message(statuses)
83
- if statuses.include?('順利送達')
84
- :done
85
- elsif statuses.include?('配送中')
86
- :delivering
87
- elsif statuses.include?('已集貨')
88
- :collected
89
- elsif statuses.include?('轉運中')
90
- :in_transit
122
+ def parse_delivery_item(item)
123
+ return nil unless item[:Status] && item[:Time]
124
+
125
+ DeliveryItem.new(
126
+ status: item[:Status].to_s.force_encoding('UTF-8'),
127
+ status_code: parse_status_message([item[:Status].to_s.force_encoding('UTF-8')]),
128
+ time: parse_time(item[:Time]),
129
+ office: item[:Office].to_s.force_encoding('UTF-8'),
130
+ last_update: parse_last_update(item[:LastUPDateTime])
131
+ )
132
+ end
133
+
134
+ def parse_time(time_str)
135
+ return nil unless time_str
136
+
137
+ Time.strptime(time_str.to_s, '%Y/%m/%d %H:%M')
138
+ rescue
139
+ nil
140
+ end
141
+
142
+ def parse_last_update(datetime_str)
143
+ return nil unless datetime_str
144
+
145
+ Time.strptime(datetime_str.to_s, '%Y%m%d%H%M%S')
146
+ rescue
147
+ nil
148
+ end
149
+
150
+ def extract_delivery_statuses(items)
151
+ case items
152
+ when Hash
153
+ [items[:Status].force_encoding('UTF-8')]
154
+ when Array
155
+ items.map { |item| item[:Status].force_encoding('UTF-8') }
91
156
  else
92
- :unknown
157
+ []
158
+ end
159
+ end
160
+
161
+ STATUS_MAPPINGS = {
162
+ '順利送達' => :done,
163
+ '配送中' => :delivering,
164
+ '已集貨' => :collected,
165
+ '轉運中' => :in_transit
166
+ }.freeze
167
+
168
+ def parse_status_message(statuses)
169
+ STATUS_MAPPINGS.each do |status_text, status_symbol|
170
+ return status_symbol if statuses.include?(status_text)
93
171
  end
172
+ :unknown
94
173
  end
95
174
  end
96
175
  end
data/lib/tcat/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tcat
4
- VERSION = '0.1.5'
4
+ VERSION = '0.1.7'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tcat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zac