diff --git a/lib/stripe-force/constants.rb b/lib/stripe-force/constants.rb
index fbf555e76c..9cf0f71899 100644
--- a/lib/stripe-force/constants.rb
+++ b/lib/stripe-force/constants.rb
@@ -21,7 +21,9 @@ module Constants
SF_CONSUMPTION_RATE = 'ConsumptionRate'
SF_CONTRACT = 'Contract'
SF_STRIPE_COUPON = 'Stripe_Coupon_Beta__c'
+ SF_STRIPE_COUPON_SERIALIZED = 'Stripe_Coupon_Beta_Serialized__c'
SF_STRIPE_COUPON_QUOTE_LINE_ASSOCIATION = 'Stripe_Coupon_Beta_Quote_Line_Associatio__c'
+ SF_STRIPE_COUPON_ORDER_ITEM_ASSOCIATION = 'Stripe_Coupon_Beta_Order_Item_Associatio__c'
SF_ID = 'Id'
SF_LAST_MODIFIED_DATE = 'LastModifiedDate'
diff --git a/lib/stripe-force/translate/coupon.rb b/lib/stripe-force/translate/coupon.rb
index 5dfff16ecf..90b34e1cdf 100644
--- a/lib/stripe-force/translate/coupon.rb
+++ b/lib/stripe-force/translate/coupon.rb
@@ -13,4 +13,24 @@ def translate_coupon(sf_coupon)
coupon
end
+
+ def self.get_salesforce_stripe_coupons_associated_to_order_line(sf_client:, sf_order_line_id:)
+ order_item_associations = sf_client.query("Select Id from #{SF_STRIPE_COUPON_ORDER_ITEM_ASSOCIATION} where Order_Item__c = '#{sf_order_line_id}'")
+
+ if !order_item_associations || order_item_associations.size == 0
+ log.info "no stripe coupon order line associations related to this order line", salesforce_object: sf_order_line_id
+ return
+ end
+
+ # there could be multiple coupons associated with a single order line
+ coupons = order_item_associations.map do |order_item_association|
+ association = sf_client.find(SF_STRIPE_COUPON_ORDER_ITEM_ASSOCIATION, order_item_association.Id)
+ coupon = sf_client.query("Select Id from #{SF_STRIPE_COUPON_SERIALIZED} where Id = '#{association.Stripe_Coupon__c}'")
+
+ # return the coupon object
+ sf_client.find(SF_STRIPE_COUPON_SERIALIZED, coupon.first.Id)
+ end
+
+ coupons
+ end
end
diff --git a/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Order_Item_Associatio__c/Stripe_Coupon_Beta_Order_Item_Associatio__c.object-meta.xml b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Order_Item_Associatio__c/Stripe_Coupon_Beta_Order_Item_Associatio__c.object-meta.xml
new file mode 100644
index 0000000000..46fc0f1c12
--- /dev/null
+++ b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Order_Item_Associatio__c/Stripe_Coupon_Beta_Order_Item_Associatio__c.object-meta.xml
@@ -0,0 +1,174 @@
+
+
+
+ Accept
+ Default
+
+
+ Accept
+ Large
+ Default
+
+
+ Accept
+ Small
+ Default
+
+
+ CancelEdit
+ Default
+
+
+ CancelEdit
+ Large
+ Default
+
+
+ CancelEdit
+ Small
+ Default
+
+
+ Clone
+ Default
+
+
+ Clone
+ Large
+ Default
+
+
+ Clone
+ Small
+ Default
+
+
+ Delete
+ Default
+
+
+ Delete
+ Large
+ Default
+
+
+ Delete
+ Small
+ Default
+
+
+ Edit
+ Default
+
+
+ Edit
+ Large
+ Default
+
+
+ Edit
+ Small
+ Default
+
+
+ List
+ Default
+
+
+ List
+ Large
+ Default
+
+
+ List
+ Small
+ Default
+
+
+ New
+ Default
+
+
+ New
+ Large
+ Default
+
+
+ New
+ Small
+ Default
+
+
+ SaveEdit
+ Default
+
+
+ SaveEdit
+ Large
+ Default
+
+
+ SaveEdit
+ Small
+ Default
+
+
+ Tab
+ Default
+
+
+ Tab
+ Large
+ Default
+
+
+ Tab
+ Small
+ Default
+
+
+ View
+ Default
+
+
+ View
+ Large
+ Default
+
+
+ View
+ Small
+ Default
+
+ false
+ SYSTEM
+ Deployed
+ Custom junction object linking a Stripe Coupon and an Order Line.
+ false
+ true
+ false
+ false
+ false
+ false
+ false
+ true
+ true
+ ControlledByParent
+
+
+ {0000}
+ Quot
+ AutoNumber
+
+ Stripe Coupon Beta Order Items
+
+ ControlledByParent
+
+ Order_Item_Field_Must_Be_Set
+ Order_Item__c is a required field.
+ true
+ ISBLANK(Order_Item__c)
+ Order_Item__c is a required field.
+
+ Public
+
diff --git a/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Order_Item_Associatio__c/fields/Order_Item__c.field-meta.xml b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Order_Item_Associatio__c/fields/Order_Item__c.field-meta.xml
new file mode 100644
index 0000000000..6a3a5965a3
--- /dev/null
+++ b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Order_Item_Associatio__c/fields/Order_Item__c.field-meta.xml
@@ -0,0 +1,12 @@
+
+
+ Order_Item__c
+ false
+
+ OrderItem
+ Stripe Coupon Beta Order Item Connection
+ Stripe_Coupon_Beta_Order_Item_Connection
+ false
+ false
+ Lookup
+
diff --git a/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Order_Item_Associatio__c/fields/Stripe_Coupon__c.field-meta.xml b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Order_Item_Associatio__c/fields/Stripe_Coupon__c.field-meta.xml
new file mode 100644
index 0000000000..75bdc3bbd1
--- /dev/null
+++ b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Order_Item_Associatio__c/fields/Stripe_Coupon__c.field-meta.xml
@@ -0,0 +1,14 @@
+
+
+ Stripe_Coupon__c
+ false
+
+ Stripe_Coupon_Beta_Serialized__c
+ Stripe Coupon Beta Order Item Link
+ Stripe_Coupon_Beta_Order_Item_Link
+ 0
+ false
+ false
+ MasterDetail
+ true
+
\ No newline at end of file
diff --git a/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/Stripe_Coupon_Beta_Serialized__c.object-meta.xml b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/Stripe_Coupon_Beta_Serialized__c.object-meta.xml
new file mode 100644
index 0000000000..4f381077e2
--- /dev/null
+++ b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/Stripe_Coupon_Beta_Serialized__c.object-meta.xml
@@ -0,0 +1,167 @@
+
+
+
+ Accept
+ Default
+
+
+ Accept
+ Large
+ Default
+
+
+ Accept
+ Small
+ Default
+
+
+ CancelEdit
+ Default
+
+
+ CancelEdit
+ Large
+ Default
+
+
+ CancelEdit
+ Small
+ Default
+
+
+ Clone
+ Default
+
+
+ Clone
+ Large
+ Default
+
+
+ Clone
+ Small
+ Default
+
+
+ Delete
+ Default
+
+
+ Delete
+ Large
+ Default
+
+
+ Delete
+ Small
+ Default
+
+
+ Edit
+ Default
+
+
+ Edit
+ Large
+ Default
+
+
+ Edit
+ Small
+ Default
+
+
+ List
+ Default
+
+
+ List
+ Large
+ Default
+
+
+ List
+ Small
+ Default
+
+
+ New
+ Default
+
+
+ New
+ Large
+ Default
+
+
+ New
+ Small
+ Default
+
+
+ SaveEdit
+ Default
+
+
+ SaveEdit
+ Large
+ Default
+
+
+ SaveEdit
+ Small
+ Default
+
+
+ Tab
+ Default
+
+
+ Tab
+ Large
+ Default
+
+
+ Tab
+ Small
+ Default
+
+
+ View
+ Default
+
+
+ View
+ Large
+ Default
+
+
+ View
+ Small
+ Default
+
+ false
+ SYSTEM
+ Deployed
+ Custom object representing a Stripe Coupon that has been translated.
+ false
+ true
+ false
+ false
+ false
+ false
+ true
+ true
+ true
+ Private
+
+
+ {0000}
+
+ AutoNumber
+
+ Stripe Coupons Beta Serialized
+
+ ReadWrite
+ Public
+
diff --git a/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/fields/Amount_Off__c.field-meta.xml b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/fields/Amount_Off__c.field-meta.xml
new file mode 100644
index 0000000000..644a7e8aa5
--- /dev/null
+++ b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/fields/Amount_Off__c.field-meta.xml
@@ -0,0 +1,13 @@
+
+
+ Amount_Off__c
+ The amount that is taken off the subtotal for the duration of the coupon.
+ false
+
+ 18
+ false
+ 0
+ false
+ Number
+ false
+
diff --git a/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/fields/Duration_In_Months__c.field-meta.xml b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/fields/Duration_In_Months__c.field-meta.xml
new file mode 100644
index 0000000000..0d679c199c
--- /dev/null
+++ b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/fields/Duration_In_Months__c.field-meta.xml
@@ -0,0 +1,12 @@
+
+
+ Duration_In_Months__c
+ false
+
+ 18
+ false
+ 0
+ false
+ Number
+ false
+
diff --git a/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/fields/Duration__c.field-meta.xml b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/fields/Duration__c.field-meta.xml
new file mode 100644
index 0000000000..e3393d4ba8
--- /dev/null
+++ b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/fields/Duration__c.field-meta.xml
@@ -0,0 +1,31 @@
+
+
+ Duration__c
+ Indicates how long the coupon is valid for. Values include once, forever, or repeating.
+ false
+
+ true
+ false
+ Picklist
+
+ true
+
+ false
+
+ once
+ true
+
+
+
+ repeating
+ false
+
+
+
+ forever
+ false
+
+
+
+
+
diff --git a/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/fields/Max_Redemptions__c.field-meta.xml b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/fields/Max_Redemptions__c.field-meta.xml
new file mode 100644
index 0000000000..7792a88589
--- /dev/null
+++ b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/fields/Max_Redemptions__c.field-meta.xml
@@ -0,0 +1,13 @@
+
+
+ Max_Redemptions__c
+ Maximum number of times a coupon can be redeemed across all customers.
+ false
+
+ 18
+ false
+ 0
+ false
+ Number
+ false
+
diff --git a/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/fields/Name__c.field-meta.xml b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/fields/Name__c.field-meta.xml
new file mode 100644
index 0000000000..86b3c34c9c
--- /dev/null
+++ b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/fields/Name__c.field-meta.xml
@@ -0,0 +1,12 @@
+
+
+ Name__c
+ The name of the Stripe coupon.
+ false
+
+ 40
+ false
+ false
+ Text
+ false
+
diff --git a/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/fields/Original_Stripe_Coupon_Beta_Id__c.field-meta.xml b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/fields/Original_Stripe_Coupon_Beta_Id__c.field-meta.xml
new file mode 100644
index 0000000000..8ace061f24
--- /dev/null
+++ b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/fields/Original_Stripe_Coupon_Beta_Id__c.field-meta.xml
@@ -0,0 +1,12 @@
+
+
+ Original_Stripe_Coupon_Beta_Id__c
+ The unique identifier for the initial coupon this coupon was duplicated from.
+ false
+
+ 255
+ true
+ false
+ Text
+ false
+
diff --git a/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/fields/Percent_Off__c.field-meta.xml b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/fields/Percent_Off__c.field-meta.xml
new file mode 100644
index 0000000000..cefade4314
--- /dev/null
+++ b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta_Serialized__c/fields/Percent_Off__c.field-meta.xml
@@ -0,0 +1,13 @@
+
+
+ Percent_Off__c
+ The percentage off that is taken off the subtotal for the duration of the coupon.
+ false
+
+ 18
+ false
+ 2
+ false
+ Number
+ false
+
diff --git a/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta__c/fields/Amount_Off__c.field-meta.xml b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta__c/fields/Amount_Off__c.field-meta.xml
index 1040c36bd5..644a7e8aa5 100644
--- a/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta__c/fields/Amount_Off__c.field-meta.xml
+++ b/sfdx/force-app/main/default/objects/Stripe_Coupon_Beta__c/fields/Amount_Off__c.field-meta.xml
@@ -6,7 +6,7 @@
18
false
- 2
+ 0
false
Number
false
diff --git a/sfdx/force-app/main/default/permissionsets/Stripe_Connector_Integration_User.permissionset-meta.xml b/sfdx/force-app/main/default/permissionsets/Stripe_Connector_Integration_User.permissionset-meta.xml
index 9720aaffbb..d1121b840f 100644
--- a/sfdx/force-app/main/default/permissionsets/Stripe_Connector_Integration_User.permissionset-meta.xml
+++ b/sfdx/force-app/main/default/permissionsets/Stripe_Connector_Integration_User.permissionset-meta.xml
@@ -340,6 +340,36 @@
Stripe_Coupon_Beta__c.Stripe_ID__c
true
+
+ true
+ Stripe_Coupon_Beta_Serialized__c.Amount_Off__c
+ true
+
+
+ true
+ Stripe_Coupon_Beta_Serialized__c.Duration_In_Months__c
+ true
+
+
+ true
+ Stripe_Coupon_Beta_Serialized__c.Max_Redemptions__c
+ true
+
+
+ true
+ Stripe_Coupon_Beta_Serialized__c.Name__c
+ true
+
+
+ true
+ Stripe_Coupon_Beta_Serialized__c.Percent_Off__c
+ true
+
+
+ true
+ Stripe_Coupon_Beta_Order_Item_Associatio__c.Order_Item__c
+ true
+
false
@@ -377,6 +407,20 @@
true
+
+ true
+ true
+
+ true
+
+
+ true
+ true
+ true
+ true
+
+ true
+
setup
true
diff --git a/sfdx/force-app/main/default/permissionsets/Stripe_Connector_Sync_Management_User.permissionset-meta.xml b/sfdx/force-app/main/default/permissionsets/Stripe_Connector_Sync_Management_User.permissionset-meta.xml
index 9c1b0f0e8c..378bf54e34 100644
--- a/sfdx/force-app/main/default/permissionsets/Stripe_Connector_Sync_Management_User.permissionset-meta.xml
+++ b/sfdx/force-app/main/default/permissionsets/Stripe_Connector_Sync_Management_User.permissionset-meta.xml
@@ -193,6 +193,36 @@
true
Stripe_Coupon_Beta__c.Percent_Off__c
true
+
+
+ true
+ Stripe_Coupon_Beta_Serialized__c.Amount_Off__c
+ true
+
+
+ true
+ Stripe_Coupon_Beta_Serialized__c.Duration_In_Months__c
+ true
+
+
+ true
+ Stripe_Coupon_Beta_Serialized__c.Max_Redemptions__c
+ true
+
+
+ true
+ Stripe_Coupon_Beta_Serialized__c.Name__c
+ true
+
+
+ true
+ Stripe_Coupon_Beta_Serialized__c.Percent_Off__c
+ true
+
+
+ true
+ Stripe_Coupon_Beta_Order_Item_Associatio__c.Order_Item__c
+ true
false
@@ -222,6 +252,20 @@
false
+
+ true
+ true
+
+ true
+
+
+ true
+ true
+ true
+ true
+
+ true
+
Error_Log__c
Visible
diff --git a/sfdx/force-app/main/default/profiles/Admin.profile-meta.xml b/sfdx/force-app/main/default/profiles/Admin.profile-meta.xml
index bccd343aa6..5f638f8628 100644
--- a/sfdx/force-app/main/default/profiles/Admin.profile-meta.xml
+++ b/sfdx/force-app/main/default/profiles/Admin.profile-meta.xml
@@ -242,6 +242,41 @@
Stripe_Coupon_Beta__c.Percent_Off__c
true
+
+ true
+ Stripe_Coupon_Beta__c.Stripe_ID__c
+ true
+
+
+ true
+ Stripe_Coupon_Beta_Serialized__c.Amount_Off__c
+ true
+
+
+ true
+ Stripe_Coupon_Beta_Serialized__c.Duration_In_Months__c
+ true
+
+
+ true
+ Stripe_Coupon_Beta_Serialized__c.Max_Redemptions__c
+ true
+
+
+ true
+ Stripe_Coupon_Beta_Serialized__c.Name__c
+ true
+
+
+ true
+ Stripe_Coupon_Beta_Serialized__c.Percent_Off__c
+ true
+
+
+ true
+ Stripe_Coupon_Beta_Order_Item_Associatio__c.Order_Item__c
+ true
+
Error_Log__c-Error Log Layout
@@ -289,6 +324,20 @@
true
+
+ true
+ true
+
+ true
+
+
+ true
+ true
+ true
+ true
+
+ true
+
setup
true
diff --git a/sfdx/force-app/main/default/triggers/updateOrderLineCoupons.trigger b/sfdx/force-app/main/default/triggers/updateOrderLineCoupons.trigger
new file mode 100644
index 0000000000..4308e73534
--- /dev/null
+++ b/sfdx/force-app/main/default/triggers/updateOrderLineCoupons.trigger
@@ -0,0 +1,76 @@
+trigger updateOrderLineCoupons on SBQQ__Quote__c (after update) {
+ try {
+ // for all newly ordered quotes, check if the quote lines have coupon and duplicate to the corresponbding order lines
+ for(SBQQ__Quote__c quote : Trigger.new) {
+ if (quote.SBQQ__Ordered__c == true && Trigger.oldMap.get(quote.Id).SBQQ__Ordered__c == false) {
+ // fetch the related quote lines
+ List quoteLines = [
+ SELECT Id
+ FROM SBQQ__QuoteLine__c
+ WHERE SBQQ__Quote__c = :quote.Id
+ ];
+
+ for (SBQQ__QuoteLine__c quoteLine : quoteLines) {
+ // get the corresponding order line for this quote line
+ List orderItem = [
+ SELECT Id
+ FROM OrderItem
+ WHERE SBQQ__QuoteLine__c = :quoteLine.Id
+ ];
+
+ if (orderItem == null || orderItem.size() == 0)
+ {
+ continue;
+ }
+ Id orderItemId = orderItem.get(0).Id;
+
+ // fetch the Stripe Coupon Quote Line Associations for this quote line
+ List stripeCouponQuoteLineAssociations = [
+ SELECT Id, Stripe_Coupon__c
+ FROM Stripe_Coupon_Beta_Quote_Line_Associatio__c
+ WHERE Quote_Line__c = :quoteLine.Id
+ ];
+
+ if (stripeCouponQuoteLineAssociations == null)
+ {
+ continue;
+ }
+
+ // for each Stripe Coupon Quote Line Association
+ for (Stripe_Coupon_Beta_Quote_Line_Associatio__c stripeCouponQuoteLineAssociation: stripeCouponQuoteLineAssociations)
+ {
+ Stripe_Coupon_Beta__c quoteLineCoupon = [
+ SELECT Amount_Off__c, Duration__c, Duration_In_Months__c, Max_Redemptions__c, Name__c, Percent_Off__c
+ FROM Stripe_Coupon_Beta__c
+ WHERE Id = :stripeCouponQuoteLineAssociation.Stripe_Coupon__c
+ ].get(0);
+
+ // clone the Stripe Coupon on the quote line, it will have a different Id
+ Stripe_Coupon_Beta_Serialized__c clonedCoupon = new Stripe_Coupon_Beta_Serialized__c(
+ Amount_Off__c = quoteLineCoupon.Amount_Off__c,
+ Duration__c = quoteLineCoupon.Duration__c,
+ Duration_In_Months__c = quoteLineCoupon.Duration_In_Months__c,
+ Max_Redemptions__c = quoteLineCoupon.Max_Redemptions__c,
+ Name__c = quoteLineCoupon.Name__c,
+ Percent_Off__c = quoteLineCoupon.Percent_Off__c,
+ Original_Stripe_Coupon_Beta_Id__c = quoteLineCoupon.Id
+ );
+ // insert the cloned Stripe coupon
+ Database.insertImmediate((sObject)clonedCoupon);
+
+ // create a Stripe Coupon Order Line Association
+ Stripe_Coupon_Beta_Order_Item_Associatio__c orderLineStripeCouponAssociation = new Stripe_Coupon_Beta_Order_Item_Associatio__c(
+ Stripe_Coupon__c = clonedCoupon.Id,
+ Order_Item__c = orderItemId
+ );
+
+ // insert this record
+ Database.insertImmediate((sObject)orderLineStripeCouponAssociation);
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ errorLogger.create('updateOrderLineCouponsTrigger', e);
+ }
+}
\ No newline at end of file
diff --git a/sfdx/force-app/main/default/triggers/updateOrderLineCoupons.trigger-meta.xml b/sfdx/force-app/main/default/triggers/updateOrderLineCoupons.trigger-meta.xml
new file mode 100644
index 0000000000..f502e4bf01
--- /dev/null
+++ b/sfdx/force-app/main/default/triggers/updateOrderLineCoupons.trigger-meta.xml
@@ -0,0 +1,5 @@
+
+
+ 54.0
+ Active
+
diff --git a/test/integration/translate/test_coupon.rb b/test/integration/translate/test_coupon.rb
index 124b162ad8..e57a781707 100644
--- a/test/integration/translate/test_coupon.rb
+++ b/test/integration/translate/test_coupon.rb
@@ -85,6 +85,51 @@ class Critic::CouponTranslation < Critic::FunctionalTest
assert(25, coupon_1.Percent_Off__c)
end
+ it 'coupons are copied to order lines when a quote is ordered' do
+ # setup
+ PRODUCT_PRICE = 100
+ sf_account_id = create_salesforce_account
+ sf_product_id, _sf_pricebook_id = salesforce_recurring_product_with_price(price: PRODUCT_PRICE)
+
+ # create a SF CPQ quote
+ sf_quote_id = create_salesforce_quote(sf_account_id: sf_account_id, additional_quote_fields: {
+ CPQ_QUOTE_SUBSCRIPTION_START_DATE => now_time_formatted_for_salesforce,
+ CPQ_QUOTE_SUBSCRIPTION_TERM => 12.0,
+ })
+
+ # create a quote with a product
+ quote_with_product = add_product_to_cpq_quote(sf_quote_id, sf_product_id: sf_product_id)
+ sf_quote_id = calculate_and_save_cpq_quote(quote_with_product)
+
+ # retrieve the quote line
+ quote_lines = sf_get_related(sf_quote_id, CPQ_QUOTE_LINE)
+ assert_equal(1, quote_lines.size)
+ quote_line_id = quote_lines.first.Id
+
+ # create a coupon and attach to the quote line
+ sf_stripe_coupon = create_salesforce_stripe_coupon(additional_fields: {
+ SalesforceStripeCouponFields::NAME => 'Special 50% off coupon',
+ SalesforceStripeCouponFields::PERCENT_OFF => 50,
+ })
+
+ # create the association object to map the coupon to the quote line
+ create_salesforce_stripe_coupon_quote_line_association(sf_quote_line_id: quote_line_id, sf_stripe_coupon_id: sf_stripe_coupon)
+
+ sf_order = create_order_from_cpq_quote(sf_quote_id)
+
+ # query for the association objects that have a reference to this order line
+ sf_order_line_items = sf_get_related(sf_order, SF_ORDER_ITEM)
+ assert_equal(1, sf_order_line_items.count)
+
+ sf_order_item_id = sf_order_line_items.first.Id
+ associated_coupons = StripeForce::Translate.get_salesforce_stripe_coupons_associated_to_order_line(sf_client: @user.sf_client, sf_order_line_id: sf_order_item_id)
+ assert_equal(1, associated_coupons.size)
+
+ order_line_coupon = associated_coupons.first
+ assert_equal('Special 50% off coupon', order_line_coupon.Name__c)
+ assert_equal(50, order_line_coupon.Percent_Off__c)
+ end
+
it 'translate order with coupon' do
# TODO https://jira.corp.stripe.com/browse/PLATINT-1952
end