Skip to content

Commit

Permalink
chore: prepare for new release
Browse files Browse the repository at this point in the history
  • Loading branch information
moxvallix committed Dec 13, 2023
1 parent 72e29f1 commit 685c9b1
Show file tree
Hide file tree
Showing 9 changed files with 171 additions and 32 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
## [0.1.1] - 2023-12-11
### Added
- Scope for Lago payment methods with a given provider.
- Method to find a Lago payment method by provider, and provider id.
- Added `pull!` and `push!` methods to billable, and payment method, to better control syncing with Lago.
- Method to retrieve a payment method on billable.

### Changed
- Dependency `lago-ruby-client` was upgraded to version 0.52.2.pre.beta.
- Improved API for adding a payment method to billable.
- Method `subscription` on subscription can be passed `reload: true` to reload the subscription data.

## [0.1.0] - 2023-10-23
- Initial release
7 changes: 2 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,6 @@ for direct use of the [Lago API](https://docs.getlago.com/api-reference/intro).

The client instance can be accessed from `Pay::Lago.client`.

#### Please Note:
For any API calls that would use a GET, the external_id must be [URI encoded](https://ruby-doc.org/current/stdlibs/uri/URI.html#method-c-encode_www_form_component), as the lago-ruby-client gem does not currently do this itself. See [this issue](https://github.com/getlago/lago-ruby-client/issues/136).

## Development

After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
Expand All @@ -74,12 +71,12 @@ To install this gem onto your local machine, run `bundle exec rake install`. To

## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/pay-lago. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/pay-lago/blob/master/CODE_OF_CONDUCT.md).
Bug reports and pull requests are welcome on GitHub at https://github.com/demingfactor/pay-lago. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/demingfactor/pay-lago/blob/master/CODE_OF_CONDUCT.md).

## License

The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).

## Code of Conduct

Everyone interacting in the Pay::Lago project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/pay-lago/blob/master/CODE_OF_CONDUCT.md).
Everyone interacting in the Pay::Lago project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/demingfactor/pay-lago/blob/master/CODE_OF_CONDUCT.md).
6 changes: 6 additions & 0 deletions app/models/concerns/pay/lago/pay_payment_method_extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ module PayPaymentMethodExtensions
scope :with_provider, ->(provider) { where("pay_payment_methods.data->>'payment_provider' = ?", provider) }
end

def provider
data["payment_provider"].to_sym
rescue
nil
end

class_methods do
def find_by_lago_provider_and_id(provider, provider_id)
with_provider(provider).find_by_processor_and_id(:lago, provider_id)
Expand Down
40 changes: 40 additions & 0 deletions docs/4_payment_methods.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Payment Methods

## Adding a Payment Method to a Customer

Lago uses the default method of payment for a given customer. As such, Payment Methods in this gem actually
store customer information of the given provider, rather than the payment method itself.

```ruby
# Adding a Stripe customer as a Payment Method
customer = Pay::Customer.find(1234)
customer.add_payment_method(:stripe, "cus_1234")
```

```ruby
# Adding a Stripe customer as a Payment Method, but make it not the default.
customer = Pay::Customer.find(1234)
customer.add_payment_method(:stripe, "cus_1234", default: false)
```

```ruby
# Adding a Stripe customer as a Payment Method, but make it not sync with Lago.
# NOTE: Syncing with Lago will only work anyways if default is true (which it is by default).
customer = Pay::Customer.find(1234)
customer.add_payment_method(:stripe, "cus_1234", sync: false)
```

## Retrieving a Payment Method

```ruby
# Retrieve a Payment Method with a given ID.
customer = Pay::Customer.find(1234)
customer.get_payment_method(:stripe, "cus_1234")
```

```ruby
# If no Payment Method ID is given, it will return either the first Payment Method
# for the customer with the given provider, or the default Payment Method (if provider matches).
customer = Pay::Customer.find(1234)
customer.get_payment_method(:stripe)
```
File renamed without changes.
4 changes: 0 additions & 4 deletions lib/pay/lago.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ module Webhooks
autoload :SubscriptionTerminated, "pay/lago/webhooks/subscription_terminated"
end

module Providers
autoload :Stripe, "pay/lago/providers/stripe"
end

extend Pay::Env

class << self
Expand Down
12 changes: 5 additions & 7 deletions lib/pay/lago/billable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,9 @@ def subscribe(name: Pay.default_product_name, plan: Pay.default_plan_name, **opt

def get_payment_method(provider, provider_id = nil)
raise Pay::Lago::Error.new("Invalid provider!") unless Pay::Lago::PaymentMethod.valid_provider?(provider)
if provider_id.present?
Pay::PaymentMethod.find_by_lago_provider_and_id(provider, provider_id)
else
Pay::PaymentMethod.with_provider(provider).first
end
return Pay::PaymentMethod.find_by_lago_provider_and_id(provider, provider_id) if provider_id.present?
return pay_customer.default_payment_method if pay_customer.default_payment_method&.provider == provider
Pay::PaymentMethod.with_provider(provider).first
end

def add_payment_method(provider, provider_id, default: true, sync: true, options: {})
Expand All @@ -134,8 +132,8 @@ def add_payment_method(provider, provider_id, default: true, sync: true, options
customer: pay_customer, data: options.merge(payment_provider: provider, provider_customer_id: provider_id)
)

payment_method.make_default! if default || sync
payment_method.payment_processor.push! if sync
payment_method.make_default! if default
payment_method.payment_processor.push! if sync && default

payment_method
end
Expand Down
93 changes: 93 additions & 0 deletions test/dummy/db/migrate/1_create_pay_tables.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
class CreatePayTables < ActiveRecord::Migration[6.0]
def change
primary_key_type, foreign_key_type = primary_and_foreign_key_types

create_table :pay_customers, id: primary_key_type do |t|
t.belongs_to :owner, polymorphic: true, index: false, type: foreign_key_type
t.string :processor, null: false
t.string :processor_id
t.boolean :default
t.public_send Pay::Adapter.json_column_type, :data
t.datetime :deleted_at
t.string :stripe_account
t.timestamps
end
add_index :pay_customers, [:owner_type, :owner_id, :deleted_at], name: :pay_customer_owner_index, unique: true
add_index :pay_customers, [:processor, :processor_id], unique: true

create_table :pay_merchants, id: primary_key_type do |t|
t.belongs_to :owner, polymorphic: true, index: false, type: foreign_key_type
t.string :processor, null: false
t.string :processor_id
t.boolean :default
t.public_send Pay::Adapter.json_column_type, :data
t.timestamps
end
add_index :pay_merchants, [:owner_type, :owner_id, :processor]

create_table :pay_payment_methods, id: primary_key_type do |t|
t.belongs_to :customer, foreign_key: {to_table: :pay_customers}, null: false, index: false, type: foreign_key_type
t.string :processor_id, null: false
t.boolean :default
t.string :type
t.public_send Pay::Adapter.json_column_type, :data
t.timestamps
end
add_index :pay_payment_methods, [:customer_id, :processor_id], unique: true

create_table :pay_subscriptions, id: primary_key_type do |t|
t.belongs_to :customer, foreign_key: {to_table: :pay_customers}, null: false, index: false, type: foreign_key_type
t.string :name, null: false
t.string :processor_id, null: false
t.string :processor_plan, null: false
t.integer :quantity, default: 1, null: false
t.string :status, null: false
t.datetime :current_period_start
t.datetime :current_period_end
t.datetime :trial_ends_at
t.datetime :ends_at
t.boolean :metered
t.string :pause_behavior
t.datetime :pause_starts_at
t.datetime :pause_resumes_at
t.decimal :application_fee_percent, precision: 8, scale: 2
t.public_send Pay::Adapter.json_column_type, :metadata
t.public_send Pay::Adapter.json_column_type, :data
t.timestamps
end
add_index :pay_subscriptions, [:customer_id, :processor_id], unique: true
add_index :pay_subscriptions, [:metered]
add_index :pay_subscriptions, [:pause_starts_at]

create_table :pay_charges, id: primary_key_type do |t|
t.belongs_to :customer, foreign_key: {to_table: :pay_customers}, null: false, index: false, type: foreign_key_type
t.belongs_to :subscription, foreign_key: {to_table: :pay_subscriptions}, null: true, type: foreign_key_type
t.string :processor_id, null: false
t.integer :amount, null: false
t.string :currency
t.integer :application_fee_amount
t.integer :amount_refunded
t.public_send Pay::Adapter.json_column_type, :metadata
t.public_send Pay::Adapter.json_column_type, :data
t.timestamps
end
add_index :pay_charges, [:customer_id, :processor_id], unique: true

create_table :pay_webhooks, id: primary_key_type do |t|
t.string :processor
t.string :event_type
t.public_send Pay::Adapter.json_column_type, :event
t.timestamps
end
end

private

def primary_and_foreign_key_types
config = Rails.configuration.generators
setting = config.options[config.orm][:primary_key_type]
primary_key_type = setting || :primary_key
foreign_key_type = setting || :bigint
[primary_key_type, foreign_key_type]
end
end
33 changes: 17 additions & 16 deletions test/dummy/db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.1].define(version: 2022_08_31_153001) do
ActiveRecord::Schema[7.1].define(version: 2017_02_05_000000) do
create_table "accounts", force: :cascade do |t|
t.string "email"
t.string "merchant_processor"
t.string "pay_data"
end

create_table "pay_charges", force: :cascade do |t|
t.integer "customer_id", null: false
t.integer "subscription_id"
t.bigint "customer_id", null: false
t.bigint "subscription_id"
t.string "processor_id", null: false
t.integer "amount", null: false
t.string "currency"
Expand All @@ -40,10 +40,11 @@
t.string "processor_id"
t.boolean "default"
t.json "data"
t.datetime "deleted_at"
t.datetime "deleted_at", precision: nil
t.string "stripe_account"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["owner_type", "owner_id", "deleted_at", "default"], name: "pay_customer_owner_index"
t.index ["owner_type", "owner_id", "deleted_at"], name: "pay_customer_owner_index", unique: true
t.index ["processor", "processor_id"], name: "index_pay_customers_on_processor_and_processor_id", unique: true
end

Expand All @@ -60,7 +61,7 @@
end

create_table "pay_payment_methods", force: :cascade do |t|
t.integer "customer_id", null: false
t.bigint "customer_id", null: false
t.string "processor_id", null: false
t.boolean "default"
t.string "type"
Expand All @@ -71,25 +72,25 @@
end

create_table "pay_subscriptions", force: :cascade do |t|
t.integer "customer_id", null: false
t.bigint "customer_id", null: false
t.string "name", null: false
t.string "processor_id", null: false
t.string "processor_plan", null: false
t.integer "quantity", default: 1, null: false
t.string "status", null: false
t.datetime "current_period_start"
t.datetime "current_period_end"
t.datetime "trial_ends_at"
t.datetime "ends_at"
t.datetime "current_period_start", precision: nil
t.datetime "current_period_end", precision: nil
t.datetime "trial_ends_at", precision: nil
t.datetime "ends_at", precision: nil
t.boolean "metered"
t.string "pause_behavior"
t.datetime "pause_starts_at", precision: nil
t.datetime "pause_resumes_at", precision: nil
t.decimal "application_fee_percent", precision: 8, scale: 2
t.json "metadata"
t.json "data"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "metered"
t.string "pause_behavior"
t.datetime "pause_starts_at"
t.datetime "pause_resumes_at"
t.index ["customer_id", "processor_id"], name: "index_pay_subscriptions_on_customer_id_and_processor_id", unique: true
t.index ["metered"], name: "index_pay_subscriptions_on_metered"
t.index ["pause_starts_at"], name: "index_pay_subscriptions_on_pause_starts_at"
Expand All @@ -107,7 +108,7 @@
t.string "email"
t.string "name"
t.string "owner_type"
t.bigint "owner_id"
t.integer "owner_id"
t.index ["owner_type", "owner_id"], name: "index_teams_on_owner_type_and_owner_id"
end

Expand Down

0 comments on commit 685c9b1

Please sign in to comment.