diff --git a/README.md b/README.md index 489ddef..c5094e6 100644 --- a/README.md +++ b/README.md @@ -369,6 +369,25 @@ Paddle::Notification.replay(id: "ntf_abc123") Paddle::Notification.logs(id: "ntf_abc123") ``` +### Reports + +```ruby +# List all reports +Paddle::Report.list + +# Retrieve a report +Paddle::Report.retrieve(id: "rpt_abc123") + +# Get CSV download link for a report +# Returns a raw URL. This URL is not permanent and will expire. +# https://developer.paddle.com/api-reference/reports/get-report-csv +Paddle::Report.csv(id: "rpt_abc123") + +# Create a Report +# https://developer.paddle.com/api-reference/reports/create-report +Paddle::Report.create type: "transactions", filters: [{name: "updated_at", operator: "lt", value: "2024-04 +-30"}, {name: "updated_at", operator: "gte", value: "2024-04-01"}] +``` ## Classic API diff --git a/lib/paddle.rb b/lib/paddle.rb index 3afdf67..750cfa4 100644 --- a/lib/paddle.rb +++ b/lib/paddle.rb @@ -39,6 +39,7 @@ def self.config autoload :Event, "paddle/models/event" autoload :NotificationSetting, "paddle/models/notification_setting" autoload :Notification, "paddle/models/notification" + autoload :Report, "paddle/models/report" autoload :NotificationLog, "paddle/models/notification_log" autoload :CreditBalance, "paddle/models/credit_balance" diff --git a/lib/paddle/models/report.rb b/lib/paddle/models/report.rb new file mode 100644 index 0000000..3a0a5f2 --- /dev/null +++ b/lib/paddle/models/report.rb @@ -0,0 +1,32 @@ +module Paddle + class Report < Object + + class << self + + def list(**params) + response = Client.get_request("reports", params: params) + Collection.from_response(response, type: Report) + end + + def create(type:, filters:, **params) + attrs = {type: type, filters: filters} + response = Client.post_request("reports", body: attrs.merge(params)) + Report.new(response.body["data"]) + end + + def retrieve(id:) + response = Client.get_request("reports/#{id}") + Report.new(response.body["data"]) + end + + def csv(id:) + response = Client.get_request("reports/#{id}/download-url") + if response.success? + return response.body["data"]["url"] + end + end + + end + + end +end diff --git a/test/paddle/models/report_test.rb b/test/paddle/models/report_test.rb new file mode 100644 index 0000000..d6107b7 --- /dev/null +++ b/test/paddle/models/report_test.rb @@ -0,0 +1,40 @@ +require "test_helper" + +class ReportTest < Minitest::Test + + def test_report_list + reports = Paddle::Report.list + + assert_equal Paddle::Collection, reports.class + assert_equal Paddle::Report, reports.data.first.class + assert_equal "rep_01hw8a1mg788ffxetyzs77vk3n", reports.data.first.id + end + + def test_report_retrieve + report = Paddle::Report.retrieve(id: "rep_01hw8a1mg788ffxetyzs77vk3n") + + assert_equal Paddle::Report, report.class + assert_equal "rep_01hw8a1mg788ffxetyzs77vk3n", report.id + assert_equal "transactions", report.type + end + + def test_report_csv + csv = Paddle::Report.csv(id: "rep_01hw8a1mg788ffxetyzs77vk3n") + + assert_match (/sandbox-reports/), csv + end + + def test_report_create + report = Paddle::Report.create( + type: "transactions", + filters: [ + {name: "updated_at", operator: "lt", value: "2024-04-30"}, + {name: "updated_at", operator: "gte", value: "2024-04-01"} + ] + ) + + assert_equal Paddle::Report, report.class + assert_equal "transactions", report.type + end + +end diff --git a/test/vcr_cassettes/test_report_create.yml b/test/vcr_cassettes/test_report_create.yml new file mode 100644 index 0000000..624def4 --- /dev/null +++ b/test/vcr_cassettes/test_report_create.yml @@ -0,0 +1,69 @@ +--- +http_interactions: +- request: + method: post + uri: https://sandbox-api.paddle.com/reports + body: + encoding: UTF-8 + string: '{"type":"transactions","filters":[{"name":"updated_at","operator":"lt","value":"2024-04-30"},{"name":"updated_at","operator":"gte","value":"2024-04-01"}]}' + headers: + User-Agent: + - paddle/v2.1.4 (github.com/deanpcmad/paddle) + Paddle-Version: + - '1' + Authorization: + - Bearer + Content-Type: + - application/json + response: + status: + code: 201 + message: Created + headers: + date: + - Wed, 24 Apr 2024 15:09:51 GMT + content-type: + - application/json + content-length: + - '391' + connection: + - keep-alive + cache-control: + - no-store, max-age=0 + content-security-policy: + - default-src 'none'; frame-ancestors 'none'; base-uri 'none' + cross-origin-embedder-policy: + - require-corp + cross-origin-opener-policy: + - same-origin + cross-origin-resource-policy: + - same-site + permissions-policy: + - accelerometer=(),ambient-light-sensor=(),autoplay=(),battery=(),camera=(),display-capture=(),document-domain=(),encrypted-media=(),fullscreen=(),gamepad=(),geolocation=(),gyroscope=(),layout-animations=(self),legacy-image-formats=(self),magnetometer=(),microphone=(),midi=(),oversized-images=(self),payment=(),picture-in-picture=(),publickey-credentials-get=(),screen-wake-lock=(),speaker-selection=(),sync-xhr=(self),unoptimized-images=(self),unsized-media=(self),usb=(),web-share=(),xr-spatial-tracking=() + pragma: + - no-cache + referrer-policy: + - no-referrer + request-id: + - '096ac151-4714-483a-99de-3169c9b8723c' + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + x-content-type-options: + - nosniff + x-frame-options: + - deny + x-permitted-cross-domain-policies: + - none + x-robots-tag: + - noindex, nofollow + cf-cache-status: + - DYNAMIC + server: + - cloudflare + cf-ray: + - 8797044a1c729407-LHR + body: + encoding: UTF-8 + string: '{"data":{"id":"rep_01hw8aftshkm8myc5nk6w2edmf","type":"transactions","rows":null,"status":"pending","filters":[{"name":"updated_at","value":"2024-04-30","operator":"lt"},{"name":"updated_at","value":"2024-04-01","operator":"gte"}],"expires_at":null,"created_at":"2024-04-24T15:09:51.281Z","updated_at":"2024-04-24T15:09:51.281Z"},"meta":{"request_id":"096ac151-4714-483a-99de-3169c9b8723c"}}' + recorded_at: Wed, 24 Apr 2024 15:09:52 GMT +recorded_with: VCR 6.2.0 diff --git a/test/vcr_cassettes/test_report_csv.yml b/test/vcr_cassettes/test_report_csv.yml new file mode 100644 index 0000000..e51e619 --- /dev/null +++ b/test/vcr_cassettes/test_report_csv.yml @@ -0,0 +1,69 @@ +--- +http_interactions: +- request: + method: get + uri: https://sandbox-api.paddle.com/reports/rep_01hw8a1mg788ffxetyzs77vk3n/download-url + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - paddle/v2.1.4 (github.com/deanpcmad/paddle) + Paddle-Version: + - '1' + Authorization: + - Bearer + response: + status: + code: 200 + message: OK + headers: + date: + - Wed, 24 Apr 2024 15:10:29 GMT + content-type: + - application/json + transfer-encoding: + - chunked + connection: + - keep-alive + cache-control: + - no-store, max-age=0 + content-security-policy: + - default-src 'none'; frame-ancestors 'none'; base-uri 'none' + cross-origin-embedder-policy: + - require-corp + cross-origin-opener-policy: + - same-origin + cross-origin-resource-policy: + - same-site + permissions-policy: + - accelerometer=(),ambient-light-sensor=(),autoplay=(),battery=(),camera=(),display-capture=(),document-domain=(),encrypted-media=(),fullscreen=(),gamepad=(),geolocation=(),gyroscope=(),layout-animations=(self),legacy-image-formats=(self),magnetometer=(),microphone=(),midi=(),oversized-images=(self),payment=(),picture-in-picture=(),publickey-credentials-get=(),screen-wake-lock=(),speaker-selection=(),sync-xhr=(self),unoptimized-images=(self),unsized-media=(self),usb=(),web-share=(),xr-spatial-tracking=() + pragma: + - no-cache + referrer-policy: + - no-referrer + request-id: + - 35aa36e6-c5bf-48f1-9fcc-34f55ec32db8 + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + x-content-type-options: + - nosniff + x-frame-options: + - deny + x-permitted-cross-domain-policies: + - none + x-robots-tag: + - noindex, nofollow + cf-cache-status: + - DYNAMIC + server: + - cloudflare + cf-ray: + - 879705383fb4772b-LHR + content-encoding: + - gzip + body: + encoding: ASCII-8BIT + string: '{"data":{"url":"https://sandbox-reports.paddle.com/transactions-13826-2024-04-24-15-02-07.csv?X-Amz-Algorithm=AWS4-HMAC-SHA256\u0026X-Amz-Credential=ASIAZWZYLIX3FYAWATXP%2F20240424%2Feu-west-1%2Fs3%2Faws4_request\u0026X-Amz-Date=20240424T151029Z\u0026X-Amz-Expires=180\u0026X-Amz-Security-Token=IQoJb3JpZ2luX2VjEEcaCXVzLWVhc3QtMSJHMEUCIGPIFmLqw2doSKfluNqJR%2B98CBG2rMG7N1i76LIjuSPiAiEAuZ%2B6%2FDCJepQn2tzcA5V%2F6GwiWccRJY8B53KVoDq2S%2BMqjAQIkP%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FARADGgw2Njc0NDg3MjI5MzQiDJdZlb%2BlDQafPlj8AirgA2yEY8T85icCF7Kn3tBI67wNWSFy%2Bii0SxeAVrS9Fsc%2FpSJq54Q5adJA6jro%2B3xeWbhdZhceeMta28UkwG1pYxWMsPG%2F2bCjJcRYNTJWx16hpzfcSaDNyB7HGLbKPe1rKuzbJhJaKZJpLpys5Or6%2FuL4sAUWuk%2B9hi%2BKWqev7zLxeTvdg6s7yC%2B3MMoS4IMEM%2F71RBcDkoSSlhkG4xi6vg0DpyXegki%2FtpyD1qR1Sp5kkZ9XCR4r5nIG9Ry9M6TihfNwY9lEYq6XgbKLXNw8bR3drj6WnJpP0fZa70wwcn6FBhgrWXIzNaML4eMpZ%2FOrweD3XCgmHCKM8UUE%2BYlnFPVZQabtKMuafJh19oFZ0KbvYhPyk5Fl%2FMNX4XYwKJkHiEPZ7ZT08wzC3ERNx8YttVkiP%2BMyB%2Bt8M3%2FdBNI%2FxHLERmL12BLNGdqXaBgcosvx%2FIq%2BPz0G54PqXzKUtQg7G43vLX9%2BneiMOU0y2r3KGl%2FT75EflD10xlgbWF7u1XJ5ALyGPbtw%2F%2BBGjcj0yENZTHQeHN43t7s%2FmwUP7jHDBtfHi1l6FFRqaD%2ByRDnih3q4I%2BgD8ZG6zjFUYQwnrTOQMtQBxQmcWZw4nbcCQlK%2BaX%2BNsfN%2Bti50OswrmpxLDOh2CDDQvKSxBjqlAadDDNC3uCcMwYEDNTgDPXHfLjHyS%2BZ2eDztskXcSVjJLKuXb2vL7fLR31G81%2Fx2dgvbVCs1psh9k6HHPA%2BpX%2B6waYM3G7oBjCfeJCCzl%2FBKaorARQV5z7%2Fu3pGIzCDszLco%2BsRS7nalCH2tu0RbsOMNCl8tP8y4FC851iFYMcWxGLvSbpH7bTB11gPjNrz0KxIrEuQHVE20Q9RTlhpj%2BisMuYQhOA%3D%3D\u0026X-Amz-SignedHeaders=host\u0026x-id=GetObject\u0026X-Amz-Signature=8d694a98f92247fb73ee66aba2513f0ea06140130980499af9dc19a0da6fe79f"},"meta":{"request_id":"35aa36e6-c5bf-48f1-9fcc-34f55ec32db8"}}' + recorded_at: Wed, 24 Apr 2024 15:10:30 GMT +recorded_with: VCR 6.2.0 diff --git a/test/vcr_cassettes/test_report_list.yml b/test/vcr_cassettes/test_report_list.yml new file mode 100644 index 0000000..ecd79d1 --- /dev/null +++ b/test/vcr_cassettes/test_report_list.yml @@ -0,0 +1,69 @@ +--- +http_interactions: +- request: + method: get + uri: https://sandbox-api.paddle.com/reports + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - paddle/v2.1.4 (github.com/deanpcmad/paddle) + Paddle-Version: + - '1' + Authorization: + - Bearer + response: + status: + code: 200 + message: OK + headers: + date: + - Wed, 24 Apr 2024 15:07:42 GMT + content-type: + - application/json + transfer-encoding: + - chunked + connection: + - keep-alive + cache-control: + - no-store, max-age=0 + content-security-policy: + - default-src 'none'; frame-ancestors 'none'; base-uri 'none' + cross-origin-embedder-policy: + - require-corp + cross-origin-opener-policy: + - same-origin + cross-origin-resource-policy: + - same-site + permissions-policy: + - accelerometer=(),ambient-light-sensor=(),autoplay=(),battery=(),camera=(),display-capture=(),document-domain=(),encrypted-media=(),fullscreen=(),gamepad=(),geolocation=(),gyroscope=(),layout-animations=(self),legacy-image-formats=(self),magnetometer=(),microphone=(),midi=(),oversized-images=(self),payment=(),picture-in-picture=(),publickey-credentials-get=(),screen-wake-lock=(),speaker-selection=(),sync-xhr=(self),unoptimized-images=(self),unsized-media=(self),usb=(),web-share=(),xr-spatial-tracking=() + pragma: + - no-cache + referrer-policy: + - no-referrer + request-id: + - c4267046-98dc-4e9a-b328-722948354cdd + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + x-content-type-options: + - nosniff + x-frame-options: + - deny + x-permitted-cross-domain-policies: + - none + x-robots-tag: + - noindex, nofollow + cf-cache-status: + - DYNAMIC + server: + - cloudflare + cf-ray: + - 879701283e8423e2-LHR + content-encoding: + - gzip + body: + encoding: ASCII-8BIT + string: '{"data":[{"id":"rep_01hw8a1mg788ffxetyzs77vk3n","type":"transactions","rows":9,"status":"ready","filters":[{"name":"updated_at","value":"2024-04-30","operator":"lt"},{"name":"updated_at","value":"2024-04-01","operator":"gte"}],"expires_at":"2024-05-08T15:02:20.027106Z","created_at":"2024-04-24T15:02:06.087Z","updated_at":"2024-04-24T15:02:20.027111Z"}],"meta":{"request_id":"c4267046-98dc-4e9a-b328-722948354cdd","pagination":{"per_page":50,"next":"https://sandbox-api.paddle.com/reports?after=rep_01hw8a1mg788ffxetyzs77vk3n","has_more":false,"estimated_total":1}}}' + recorded_at: Wed, 24 Apr 2024 15:07:43 GMT +recorded_with: VCR 6.2.0 diff --git a/test/vcr_cassettes/test_report_retrieve.yml b/test/vcr_cassettes/test_report_retrieve.yml new file mode 100644 index 0000000..89b5e8c --- /dev/null +++ b/test/vcr_cassettes/test_report_retrieve.yml @@ -0,0 +1,69 @@ +--- +http_interactions: +- request: + method: get + uri: https://sandbox-api.paddle.com/reports/rep_01hw8a1mg788ffxetyzs77vk3n + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - paddle/v2.1.4 (github.com/deanpcmad/paddle) + Paddle-Version: + - '1' + Authorization: + - Bearer + response: + status: + code: 200 + message: OK + headers: + date: + - Wed, 24 Apr 2024 15:09:51 GMT + content-type: + - application/json + transfer-encoding: + - chunked + connection: + - keep-alive + cache-control: + - no-store, max-age=0 + content-security-policy: + - default-src 'none'; frame-ancestors 'none'; base-uri 'none' + cross-origin-embedder-policy: + - require-corp + cross-origin-opener-policy: + - same-origin + cross-origin-resource-policy: + - same-site + permissions-policy: + - accelerometer=(),ambient-light-sensor=(),autoplay=(),battery=(),camera=(),display-capture=(),document-domain=(),encrypted-media=(),fullscreen=(),gamepad=(),geolocation=(),gyroscope=(),layout-animations=(self),legacy-image-formats=(self),magnetometer=(),microphone=(),midi=(),oversized-images=(self),payment=(),picture-in-picture=(),publickey-credentials-get=(),screen-wake-lock=(),speaker-selection=(),sync-xhr=(self),unoptimized-images=(self),unsized-media=(self),usb=(),web-share=(),xr-spatial-tracking=() + pragma: + - no-cache + referrer-policy: + - no-referrer + request-id: + - 50258c08-f3db-455c-83e3-0d4f63f82b45 + strict-transport-security: + - max-age=31536000; includeSubDomains; preload + x-content-type-options: + - nosniff + x-frame-options: + - deny + x-permitted-cross-domain-policies: + - none + x-robots-tag: + - noindex, nofollow + cf-cache-status: + - DYNAMIC + server: + - cloudflare + cf-ray: + - 8797044c3de53693-LHR + content-encoding: + - gzip + body: + encoding: ASCII-8BIT + string: '{"data":{"id":"rep_01hw8a1mg788ffxetyzs77vk3n","type":"transactions","rows":9,"status":"ready","filters":[{"name":"updated_at","value":"2024-04-30","operator":"lt"},{"name":"updated_at","value":"2024-04-01","operator":"gte"}],"expires_at":"2024-05-08T15:02:20.027106Z","created_at":"2024-04-24T15:02:06.087Z","updated_at":"2024-04-24T15:02:20.027111Z"},"meta":{"request_id":"50258c08-f3db-455c-83e3-0d4f63f82b45"}}' + recorded_at: Wed, 24 Apr 2024 15:09:52 GMT +recorded_with: VCR 6.2.0