summaryrefslogtreecommitdiff
path: root/lib/super_good/solidus_taxjar/api_params.rb
blob: 645801872ba8bf9bba3187b48a8aedcb0ebb0f42 (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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
module SuperGood
  module SolidusTaxJar
    module APIParams
      class << self
        def order_params(order)
          {}
            .merge(customer_params(order))
            .merge(order_address_params(order.tax_address))
            .merge(line_items_params(order.line_items))
            .merge(shipping: order.shipment_total)
            .merge(SuperGood::SolidusTaxJar.custom_order_params.(order))
            .tap do |params|
              next unless SuperGood::SolidusTaxJar.logging_enabled

              Rails.logger.info(
                "TaxJar params for #{order.number}: #{params.inspect}"
              )
            end
        end

        def address_params(address)
          [
            address.zipcode,
            {
              street: address.address1,
              city: address.city,
              state: address&.state&.abbr || address.state_name,
              country: address.country.iso
            }
          ]
        end

        def tax_rate_address_params(address)
          {
            amount: 100,
            shipping: 0,
          }.merge(order_address_params(address))
        end

        def transaction_params(order)
          {}
            .merge(customer_params(order))
            .merge(order_address_params(order.tax_address))
            .merge(transaction_line_items_params(order.line_items))
            .merge(
              transaction_id: order.number,
              transaction_date: order.completed_at.to_formatted_s(:iso8601),
              amount: [order.total - order.additional_tax_total, 0].max,
              shipping: shipping(order),
              sales_tax: sales_tax(order)
            )
        end

        def refund_params(reimbursement)
          additional_taxes = reimbursement.return_items.sum(&:additional_tax_total)

          {}
            .merge(order_address_params(reimbursement.order.tax_address))
            .merge(
              transaction_id: reimbursement.number,
              transaction_reference_id: reimbursement.order.number,
              transaction_date: reimbursement.order.completed_at.to_formatted_s(:iso8601),
              amount: reimbursement.total - additional_taxes,
              shipping: 0,
              sales_tax: additional_taxes
            )
        end

        private

        def customer_params(order)
          return {} unless order.user_id

          { customer_id: order.user_id.to_s }
        end

        def order_address_params(address)
          {
            to_country: address.country.iso,
            to_zip: address.zipcode,
            to_city: address.city,
            to_state: address&.state&.abbr || address.state_name,
            to_street: address.address1,
          }
        end

        def line_items_params(line_items)
          {
            line_items: valid_line_items(line_items).map do |line_item|
              {
                id: line_item.id,
                quantity: line_item.quantity,
                unit_price: line_item.price,
                discount: discount(line_item),
                product_tax_code: line_item.tax_category&.tax_code
              }
            end
          }
        end

        def transaction_line_items_params(line_items)
          {
            line_items: valid_line_items(line_items).map do |line_item|
              {
                id: line_item.id,
                quantity: line_item.quantity,
                product_identifier: line_item.sku,
                product_tax_code: line_item.tax_category&.tax_code,
                unit_price: line_item.price,
                discount: discount(line_item),
                sales_tax: line_item_sales_tax(line_item)
              }
            end
          }
        end

        def valid_line_items(line_items)
          # The API appears to error when sent line items with no quantity...
          # but why would you do that anyway.
          line_items.reject do |line_item|
            line_item.quantity.zero?
          end
        end

        def discount(line_item)
          ::SuperGood::SolidusTaxJar.discount_calculator.new(line_item).discount
        end

        def shipping(order)
          SuperGood::SolidusTaxJar.shipping_calculator.(order)
        end

        def sales_tax(order)
          return 0 if order.total.zero?

          order.additional_tax_total
        end

        def line_item_sales_tax(line_item)
          return 0 if line_item.order.total.zero?

          line_item.additional_tax_total
        end
      end
    end
  end
end