dnsimple 8.6.0 → 8.7.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 644e524e7010bc680c34ba6abf09315fbe41e2a5ec63ee6c82e443df4f21326a
4
- data.tar.gz: aa84484bdf2a0b8b48ca45ad448dcea01c8c879acdf4b1c018f2cb8fb73ad7cf
3
+ metadata.gz: 71cf40738100b3388caeebb75622d78d73a3b1810711cfd9099b3f5fb97fbd43
4
+ data.tar.gz: 812bb20d76f731d08065dfa7703fd77a41e56cd9078f5a8f7c431f36df7d6a7d
5
5
  SHA512:
6
- metadata.gz: fa53931624fc7c23d8f91332c9d86379560fc3609fe0f351d6346b6e38fb5b9337bb04e0aa6120c639431b9931cbc100405bc7bca544e04ee805b1ef07e2d4cb
7
- data.tar.gz: 0032b9d9c4b3df0581e9037a5196bc8376c9f01dbb87ced552eb0372f6d30263a1121bdd86ba16e1a5a992974b64639cbdb81b9ba50e8442603bd0c6ab39f0b2
6
+ metadata.gz: fda1515e6b1d10f098f86c951d6f3d20af9bbbea762b062dd01ab4ebfa90f313c2fcf63718e93b016df05518101653edbb9d7cf0cd28e2d0870106ef9ee07e05
7
+ data.tar.gz: bfad72709061c258c83829366b7aa4fa5758fb3765eac93cc58748c737f644f8d4e35981d33d76104e6b4126f9b6ecb5cf28ea091b95c6e048f0fdbd8ac4738b
@@ -16,7 +16,7 @@ jobs:
16
16
  runs-on: ubuntu-latest
17
17
  steps:
18
18
  - name: Checkout Code
19
- uses: actions/checkout@v3
19
+ uses: actions/checkout@v4
20
20
  - name: Run markdownlint-cli
21
21
  uses: nosborn/github-action-markdown-cli@v3.3.0
22
22
  with:
@@ -37,7 +37,7 @@ jobs:
37
37
  - 'ruby-head'
38
38
  - 'truffleruby-head'
39
39
  steps:
40
- - uses: actions/checkout@v3
40
+ - uses: actions/checkout@v4
41
41
  - name: Set up Ruby
42
42
  uses: ruby/setup-ruby@v1
43
43
  with:
@@ -19,7 +19,7 @@ jobs:
19
19
  wait-interval: 10
20
20
  allowed-conclusions: success
21
21
 
22
- - uses: actions/checkout@v3
22
+ - uses: actions/checkout@v4
23
23
 
24
24
  - name: Release Gem
25
25
  uses: simplyqio/publish-rubygems-action@2.0.0
data/CHANGELOG.md CHANGED
@@ -4,6 +4,12 @@ This project uses [Semantic Versioning 2.0.0](http://semver.org/).
4
4
 
5
5
  ## main
6
6
 
7
+ ## 8.7.0
8
+
9
+ FEATURES:
10
+
11
+ - NEW: Added `Dnsimple::Client::Billing#charges` to retrieve the list of billing charges for an account. (dnsimple/dnsimple-ruby#365)
12
+
7
13
  ## 8.6.0
8
14
 
9
15
  FEATURES:
data/Gemfile CHANGED
@@ -5,7 +5,7 @@ source 'https://rubygems.org'
5
5
  gemspec
6
6
 
7
7
  gem 'coveralls', require: false
8
- gem 'rubocop', '1.56.2', require: false
9
- gem 'rubocop-performance', '1.19.0', require: false
8
+ gem 'rubocop', '1.57.1', require: false
9
+ gem 'rubocop-performance', '1.19.1', require: false
10
10
  gem 'rubocop-rake', '0.6.0', require: false
11
- gem 'rubocop-rspec', '2.23.2', require: false
11
+ gem 'rubocop-rspec', '2.24.1', require: false
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dnsimple
4
+ class Client
5
+ module Billing
6
+ # List the billing charges for the account.
7
+ #
8
+ # @see https://developer.dnsimple.com/v2/billing/#listCharges
9
+ #
10
+ # @example List charges in the first page
11
+ # client.charges.list(1010)
12
+ #
13
+ # @example List charges, provide a filter start date
14
+ # client.charges.list(1010, filter: { start_date: "2023-01-01" })
15
+ #
16
+ # @example List charges, provide a sorting policy
17
+ # client.charges.list(1010, sort: "invoiced:asc")
18
+ #
19
+ # @param [Integer] account_id the account ID
20
+ # @param [Hash] options the filtering and sorting options
21
+ # @option options [Integer] :page current page (pagination)
22
+ # @option options [Integer] :per_page number of entries to return (pagination)
23
+ # @option options [String] :sort sorting policy
24
+ # @return [Dnsimple::PaginatedResponse<Dnsimple::Struct::Charge>]
25
+ #
26
+ # @raise [Dnsimple::RequestError]
27
+ def charges(account_id, options = {})
28
+ response = client.get(Client.versioned("/%s/billing/charges" % [account_id]), Options::ListOptions.new(options))
29
+
30
+ Dnsimple::PaginatedResponse.new(response, response["data"].map { |r| Struct::Charge.new(r) })
31
+ end
32
+ alias list_charges charges
33
+ end
34
+ end
35
+ end
@@ -8,6 +8,11 @@ module Dnsimple
8
8
  @services[:accounts] ||= Client::AccountsService.new(self)
9
9
  end
10
10
 
11
+ # @return [Dnsimple::Client::BillingService] The billing-related API proxy.
12
+ def billing
13
+ @services[:billing] ||= Client::BillingService.new(self)
14
+ end
15
+
11
16
  # @return [Dnsimple::Client::CertificatesService] The certificate-related API proxy.
12
17
  def certificates
13
18
  @services[:certificates] ||= Client::CertificatesService.new(self)
@@ -115,6 +120,11 @@ module Dnsimple
115
120
  include Client::Accounts
116
121
  end
117
122
 
123
+ require_relative 'billing'
124
+
125
+ class BillingService < ClientService
126
+ include Client::Billing
127
+ end
118
128
 
119
129
  require_relative 'certificates'
120
130
 
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bigdecimal'
4
+
5
+ module Dnsimple
6
+ module Struct
7
+ class Charge < Base
8
+
9
+ class ChargeItem < Base
10
+ # @return [String] The description of the charge item.
11
+ attr_accessor :description
12
+
13
+ # @return [Float] The amount of the charge item.
14
+ attr_reader :amount
15
+
16
+ # @return [Integer] The ID of the product that was charged.
17
+ attr_accessor :product_id
18
+
19
+ # @return [String] The type of the product that was charged.
20
+ attr_accessor :product_type
21
+
22
+ # @return [String] A unique or representative reference.
23
+ attr_accessor :product_reference
24
+
25
+ # Converts amount to a Float and sets it.
26
+ #
27
+ # @param [String] amount
28
+ # @return [void]
29
+ def amount=(amount)
30
+ @amount = BigDecimal(amount)
31
+ end
32
+ end
33
+
34
+ # @return [String] The reference number of the invoice.
35
+ attr_accessor :reference
36
+
37
+ # @return [Float] The aggregate amount of all line items, that need to be paid.
38
+ attr_reader :total_amount
39
+
40
+ # @return [Float] The amount that was paid via wallet.
41
+ attr_reader :balance_amount
42
+
43
+ # @return [String] The state of the charge.
44
+ attr_accessor :state
45
+
46
+ # @return [DateTime] When the charge was invoiced.
47
+ attr_accessor :invoiced_at
48
+
49
+ # @return [Array<ChargeItems>] The charge items.
50
+ attr_reader :items
51
+
52
+ def initialize(*)
53
+ super
54
+ @items ||= []
55
+ end
56
+
57
+ # Converts items to an Array<Struct::Charge::ChargeItem> and sets it.
58
+ #
59
+ # @param [Array<Hash>] charge_items
60
+ # @return [void]
61
+ def items=(charge_items)
62
+ @items = charge_items.map do |charge_item|
63
+ Charge::ChargeItem.new(charge_item)
64
+ end
65
+ end
66
+
67
+ # Converts balance_amount to a Float and sets it.
68
+ #
69
+ # @param [String] balance_amount
70
+ # @return [void]
71
+ def balance_amount=(balance_amount)
72
+ @balance_amount = BigDecimal(balance_amount)
73
+ end
74
+
75
+ # Converts total_amount to a Float and sets it.
76
+ #
77
+ # @param [String] total_amount
78
+ # @return [void]
79
+ def total_amount=(total_amount)
80
+ @total_amount = BigDecimal(total_amount)
81
+ end
82
+ end
83
+
84
+ end
85
+ end
@@ -22,6 +22,7 @@ require_relative 'struct/certificate'
22
22
  require_relative 'struct/certificate_bundle'
23
23
  require_relative 'struct/certificate_purchase'
24
24
  require_relative 'struct/certificate_renewal'
25
+ require_relative 'struct/charge'
25
26
  require_relative 'struct/delegation_signer_record'
26
27
  require_relative 'struct/dnssec'
27
28
  require_relative 'struct/domain'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dnsimple
4
- VERSION = "8.6.0"
4
+ VERSION = "8.7.0"
5
5
  end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ require 'bigdecimal/util'
6
+
7
+ describe Dnsimple::Client, ".billing" do
8
+
9
+ subject { described_class.new(base_url: "https://api.dnsimple.test", access_token: "a1b2c3").billing }
10
+
11
+ describe "#charges" do
12
+ let(:account_id) { 1010 }
13
+
14
+ before do
15
+ stub_request(:get, %r{/v2/#{account_id}/billing/charges})
16
+ .to_return(read_http_fixture("listCharges/success.http"))
17
+ end
18
+
19
+ it "builds the correct request" do
20
+ subject.charges(account_id)
21
+
22
+ expect(WebMock).to have_requested(:get, "https://api.dnsimple.test/v2/#{account_id}/billing/charges")
23
+ .with(headers: { 'Accept' => 'application/json' })
24
+ end
25
+
26
+ it "exposes the pagination information" do
27
+ response = subject.charges(account_id)
28
+
29
+ expect(response.respond_to?(:page)).to be(true)
30
+ expect(response.page).to eq(1)
31
+ expect(response.per_page).to be_a(Integer)
32
+ expect(response.total_entries).to be_a(Integer)
33
+ expect(response.total_pages).to be_a(Integer)
34
+ end
35
+
36
+ it "returns the charges" do
37
+ response = subject.charges(account_id)
38
+
39
+ expect(response).to be_a(Dnsimple::PaginatedResponse)
40
+ expect(response.data).to be_a(Array)
41
+ expect(response.data.size).to eq(3)
42
+
43
+ response.data.each do |result|
44
+ expect(result).to be_a(Dnsimple::Struct::Charge)
45
+ expect(result.balance_amount).to be_a(BigDecimal)
46
+ expect(result.reference).to be_a(String)
47
+ expect(result.items).to be_a(Array)
48
+ expect(result.items[0]).to be_a(Dnsimple::Struct::Charge::ChargeItem)
49
+ end
50
+
51
+ expect(response.data[0].total_amount).to be_a(BigDecimal)
52
+ expect(response.data[0].total_amount.to_s("F")).to eq("14.5")
53
+ expect(response.data[0].items[0].amount).to be_a(BigDecimal)
54
+ expect(response.data[0].items[0].amount.to_s("F")).to eq("14.5")
55
+ end
56
+
57
+ it "supports filters" do
58
+ subject.charges(account_id, filter: { start_date: "2023-01-01", end_date: "2023-08-31" })
59
+
60
+ expect(WebMock).to have_requested(:get, "https://api.dnsimple.test/v2/#{account_id}/billing/charges?start_date=2023-01-01&end_date=2023-08-31")
61
+ end
62
+
63
+ it "supports pagination" do
64
+ subject.charges(account_id, page: 2)
65
+
66
+ expect(WebMock).to have_requested(:get, "https://api.dnsimple.test/v2/#{account_id}/billing/charges?page=2")
67
+ end
68
+
69
+ it "supports sorting" do
70
+ subject.charges(account_id, sort: "invoiced:asc")
71
+
72
+ expect(WebMock).to have_requested(:get, "https://api.dnsimple.test/v2/#{account_id}/billing/charges?sort=invoiced:asc")
73
+ end
74
+
75
+ context "when using a bad filter" do
76
+ before do
77
+ stub_request(:get, %r{/v2/#{account_id}/billing/charges})
78
+ .to_return(read_http_fixture("listCharges/fail-400-bad-filter.http"))
79
+ end
80
+
81
+ it "raises error" do
82
+ expect do
83
+ subject.charges(account_id, filter: { start_date: "01-01-2023" })
84
+ end.to raise_error(Dnsimple::RequestError, "Invalid date format must be ISO8601 (YYYY-MM-DD)")
85
+ end
86
+ end
87
+
88
+ context "when account is not authorized" do
89
+ before do
90
+ stub_request(:get, %r{/v2/#{account_id}/billing/charges})
91
+ .to_return(read_http_fixture("listCharges/fail-403.http"))
92
+ end
93
+
94
+ it "raises error" do
95
+ expect do
96
+ subject.charges(account_id)
97
+ end.to raise_error(Dnsimple::RequestError, "Permission Denied. Required Scope: billing:*:read")
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,14 @@
1
+ HTTP/1.1 400 Bad Request
2
+ Date: Tue, 24 Oct 2023 08:13:01 GMT
3
+ Connection: close
4
+ X-RateLimit-Limit: 2400
5
+ X-RateLimit-Remaining: 2392
6
+ X-RateLimit-Reset: 1698136677
7
+ Content-Type: application/json; charset=utf-8
8
+ X-WORK-WITH-US: Love automation? So do we! https://dnsimple.com/jobs
9
+ Cache-Control: no-cache
10
+ X-Request-Id: bdfbf3a7-d9dc-4018-9732-61502be989a3
11
+ X-Runtime: 0.455303
12
+ Transfer-Encoding: chunked
13
+
14
+ {"message":"Invalid date format must be ISO8601 (YYYY-MM-DD)"}
@@ -0,0 +1,14 @@
1
+ HTTP/1.1 403 Forbidden
2
+ Date: Tue, 24 Oct 2023 09:49:29 GMT
3
+ Connection: close
4
+ X-RateLimit-Limit: 2400
5
+ X-RateLimit-Remaining: 2398
6
+ X-RateLimit-Reset: 1698143967
7
+ Content-Type: application/json; charset=utf-8
8
+ X-WORK-WITH-US: Love automation? So do we! https://dnsimple.com/jobs
9
+ Cache-Control: no-cache
10
+ X-Request-Id: 5554e2d3-2652-4ca7-8c5e-92b4c35f28d6
11
+ X-Runtime: 0.035309
12
+ Transfer-Encoding: chunked
13
+
14
+ {"message":"Permission Denied. Required Scope: billing:*:read"}
@@ -0,0 +1,14 @@
1
+ HTTP/1.1 200 OK
2
+ Date: Tue, 24 Oct 2023 09:52:55 GMT
3
+ Connection: close
4
+ X-RateLimit-Limit: 2400
5
+ X-RateLimit-Remaining: 2397
6
+ X-RateLimit-Reset: 1698143967
7
+ Content-Type: application/json; charset=utf-8
8
+ X-WORK-WITH-US: Love automation? So do we! https://dnsimple.com/jobs
9
+ Cache-Control: no-store, must-revalidate, private, max-age=0
10
+ X-Request-Id: a57a87c8-626a-4361-9fb8-b55ca9be8e5d
11
+ X-Runtime: 0.060526
12
+ Transfer-Encoding: chunked
13
+
14
+ {"data":[{"invoiced_at":"2023-08-17T05:53:36Z","total_amount":"14.50","balance_amount":"0.00","reference":"1-2","state":"collected","items":[{"description":"Register bubble-registered.com","amount":"14.50","product_id":1,"product_type":"domain-registration","product_reference":"bubble-registered.com"}]},{"invoiced_at":"2023-08-17T05:57:53Z","total_amount":"14.50","balance_amount":"0.00","reference":"2-2","state":"refunded","items":[{"description":"Register example.com","amount":"14.50","product_id":2,"product_type":"domain-registration","product_reference":"example.com"}]},{"invoiced_at":"2023-10-24T07:49:05Z","total_amount":"1099999.99","balance_amount":"0.00","reference":"4-2","state":"collected","items":[{"description":"Test Line Item 1","amount":"99999.99","product_id":null,"product_type":"manual","product_reference":null},{"description":"Test Line Item 2","amount":"1000000.00","product_id":null,"product_type":"manual","product_reference":null}]}],"pagination":{"current_page":1,"per_page":30,"total_entries":3,"total_pages":1}}
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dnsimple
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.6.0
4
+ version: 8.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - DNSimple
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-08 00:00:00.000000000 Z
11
+ date: 2023-11-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -110,6 +110,7 @@ files:
110
110
  - lib/dnsimple.rb
111
111
  - lib/dnsimple/client.rb
112
112
  - lib/dnsimple/client/accounts.rb
113
+ - lib/dnsimple/client/billing.rb
113
114
  - lib/dnsimple/client/certificates.rb
114
115
  - lib/dnsimple/client/clients.rb
115
116
  - lib/dnsimple/client/contacts.rb
@@ -149,6 +150,7 @@ files:
149
150
  - lib/dnsimple/struct/certificate_bundle.rb
150
151
  - lib/dnsimple/struct/certificate_purchase.rb
151
152
  - lib/dnsimple/struct/certificate_renewal.rb
153
+ - lib/dnsimple/struct/charge.rb
152
154
  - lib/dnsimple/struct/collaborator.rb
153
155
  - lib/dnsimple/struct/contact.rb
154
156
  - lib/dnsimple/struct/delegation_signer_record.rb
@@ -183,6 +185,7 @@ files:
183
185
  - lib/dnsimple/struct/zone_record.rb
184
186
  - lib/dnsimple/version.rb
185
187
  - spec/dnsimple/client/accounts_spec.rb
188
+ - spec/dnsimple/client/billing_spec.rb
186
189
  - spec/dnsimple/client/certificates_spec.rb
187
190
  - spec/dnsimple/client/client_service_spec.rb
188
191
  - spec/dnsimple/client/contacts_spec.rb
@@ -317,6 +320,9 @@ files:
317
320
  - spec/fixtures.http/listAccounts/success-account.http
318
321
  - spec/fixtures.http/listAccounts/success-user.http
319
322
  - spec/fixtures.http/listCertificates/success.http
323
+ - spec/fixtures.http/listCharges/fail-400-bad-filter.http
324
+ - spec/fixtures.http/listCharges/fail-403.http
325
+ - spec/fixtures.http/listCharges/success.http
320
326
  - spec/fixtures.http/listCollaborators/success.http
321
327
  - spec/fixtures.http/listContacts/success.http
322
328
  - spec/fixtures.http/listDelegationSignerRecords/success.http