summaryrefslogtreecommitdiff
path: root/app/services/solidus_subscriptions/subscription_generator.rb
blob: 9f619353e63d19673379baf53888eef6a040debf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# frozen_string_literal: true

# This module is responsible for taking SolidusSubscriptions::LineItem
# objects and creating SolidusSubscriptions::Subscription Objects
module SolidusSubscriptions
  module SubscriptionGenerator
    extend self

    SubscriptionConfiguration = Struct.new(:interval_length, :interval_units, :end_date)

    # Create and persist a subscription for a collection of subscription
    #   line items
    #
    # @param subscription_line_items [Array<SolidusSubscriptions::LineItem>] The
    #   subscription_line_items to be activated
    #
    # @return [SolidusSubscriptions::Subscription]
    def activate(subscription_line_items)
      return if subscription_line_items.empty?

      order = subscription_line_items.first.order
      configuration = subscription_configuration(subscription_line_items.first)

      subscription_attributes = {
        user: order.user,
        line_items: subscription_line_items,
        store: order.store,
        shipping_address: order.ship_address,
        billing_address: order.bill_address,
        payment_source: order.payments.valid.last&.payment_source,
        payment_method: order.payments.valid.last&.payment_method,
        **configuration.to_h
      }

      subscription = Subscription.create!(subscription_attributes) do |sub|
        sub.actionable_date = sub.next_actionable_date
      end
      order.update!(subscription: subscription)

      subscription
    end

    # Group a collection of line items by common subscription configuration
    # options. Grouped subscription_line_items can belong to a single
    # subscription.
    #
    # @param subscription_line_items [Array<SolidusSubscriptions::LineItem>] The
    #   subscription_line_items to be grouped.
    #
    # @return [Array<Array<SolidusSubscriptions::LineItem>>]
    def group(subscription_line_items)
      subscription_line_items.group_by do |li|
        subscription_configuration(li)
      end.
        values
    end

    private

    def subscription_configuration(subscription_line_item)
      SubscriptionConfiguration.new(
        subscription_line_item.interval_length,
        subscription_line_item.interval_units,
        subscription_line_item.end_date
      )
    end
  end
end