From b86e37a9793430b083d09959c5b27bf466c40952 Mon Sep 17 00:00:00 2001 From: Aman Agrawal Date: Sat, 30 Mar 2024 03:59:59 +0000 Subject: [PATCH] stripe: Add period information for generated invoices. Invoices need to have period to avoid charges being marked as point-in-time revenue rather than monthly revenue. --- corporate/lib/stripe.py | 54 ++++++++++++++---- .../upgrade_by_card--Charge.list.1.json | Bin 3512 -> 3512 bytes .../upgrade_by_card--Customer.modify.1.json | Bin 745 -> 745 bytes .../upgrade_by_card--Customer.retrieve.2.json | Bin 1874 -> 1874 bytes .../upgrade_by_card--Customer.retrieve.3.json | Bin 1874 -> 1874 bytes .../upgrade_by_card--Customer.retrieve.4.json | Bin 1874 -> 1874 bytes .../upgrade_by_card--Customer.retrieve.5.json | Bin 1874 -> 1874 bytes .../upgrade_by_card--Customer.retrieve.6.json | Bin 1876 -> 1876 bytes .../upgrade_by_card--Event.list.1.json | Bin 6419 -> 6621 bytes .../upgrade_by_card--Event.list.2.json | Bin 1620 -> 1620 bytes .../upgrade_by_card--Event.list.3.json | Bin 36996 -> 32719 bytes .../upgrade_by_card--Event.list.4.json | Bin 19999 -> 19999 bytes .../upgrade_by_card--Invoice.create.1.json | Bin 4386 -> 4386 bytes ...e_by_card--Invoice.finalize_invoice.1.json | Bin 4751 -> 4751 bytes .../upgrade_by_card--Invoice.list.2.json | Bin 5542 -> 5542 bytes .../upgrade_by_card--Invoice.pay.1.json | Bin 4780 -> 4780 bytes ...upgrade_by_card--InvoiceItem.create.1.json | Bin 1098 -> 1098 bytes ...upgrade_by_card--SetupIntent.create.1.json | Bin 930 -> 930 bytes .../upgrade_by_card--SetupIntent.list.1.json | Bin 1116 -> 1116 bytes ...grade_by_card--SetupIntent.retrieve.1.json | Bin 930 -> 930 bytes ...de_by_card--checkout.Session.create.1.json | Bin 2366 -> 2366 bytes ...rade_by_card--checkout.Session.list.1.json | Bin 2776 -> 2776 bytes .../upgrade_by_invoice--Event.list.1.json | Bin 6442 -> 6621 bytes .../upgrade_by_invoice--Event.list.2.json | Bin 36609 -> 33211 bytes .../upgrade_by_invoice--Event.list.3.json | Bin 9954 -> 13351 bytes .../upgrade_by_invoice--Invoice.create.1.json | Bin 4392 -> 4392 bytes ...y_invoice--Invoice.finalize_invoice.1.json | Bin 4757 -> 4757 bytes .../upgrade_by_invoice--Invoice.list.1.json | Bin 5499 -> 5499 bytes .../upgrade_by_invoice--Invoice.pay.1.json | Bin 4737 -> 4737 bytes ...rade_by_invoice--InvoiceItem.create.1.json | Bin 1101 -> 1101 bytes corporate/tests/test_stripe.py | 8 +++ 31 files changed, 51 insertions(+), 11 deletions(-) diff --git a/corporate/lib/stripe.py b/corporate/lib/stripe.py index 09be7b36d6..bc8a18fd75 100644 --- a/corporate/lib/stripe.py +++ b/corporate/lib/stripe.py @@ -866,6 +866,7 @@ class BillingSession(ABC): plan_tier: int, billing_schedule: int, charge_automatically: bool, + invoice_period: Dict[str, int], license_management: Optional[str] = None, ) -> stripe.Invoice: plan_name = CustomerPlan.name_from_tier(plan_tier) @@ -887,6 +888,7 @@ class BillingSession(ABC): customer=customer.stripe_customer_id, description=plan_name, discountable=False, + period=invoice_period, **price_args, ) @@ -903,6 +905,7 @@ class BillingSession(ABC): description=f"${cents_to_dollar_string(customer.flat_discount)}/month new customer discount", # Negative value to apply discount. amount=(-1 * discount), + period=invoice_period, ) if charge_automatically: @@ -1162,6 +1165,7 @@ class BillingSession(ABC): metadata["billing_schedule"], charge_automatically=charge_automatically, license_management=metadata["license_management"], + invoice_period=metadata["invoice_period"], ) assert stripe_invoice.id is not None invoice = Invoice.objects.create( @@ -1595,14 +1599,34 @@ class BillingSession(ABC): "type": "upgrade", "plan_tier": plan_tier, } + discount_for_plan = customer.get_discount_for_plan_tier(plan_tier) + ( + invoice_period_start, + _, + invoice_period_end, + price_per_license, + ) = compute_plan_parameters( + plan_tier, + billing_schedule, + discount_for_plan, + # TODO: Use the correct value for free_trial when we switch behaviour to send invoice + # at the start of free trial. + False, + None, + not isinstance(self, RealmBillingSession), + ) if fixed_price_plan_offer is None: - discount_for_plan = customer.get_discount_for_plan_tier(plan_tier) - price_per_license = get_price_per_license( - plan_tier, billing_schedule, discount_for_plan - ) general_metadata["price_per_license"] = price_per_license else: general_metadata["fixed_price"] = fixed_price_plan_offer.fixed_price + invoice_period_end = add_months( + invoice_period_start, CustomerPlan.FIXED_PRICE_PLAN_DURATION_MONTHS + ) + + general_metadata["invoice_period"] = { + "start": datetime_to_timestamp(invoice_period_start), + "end": datetime_to_timestamp(invoice_period_end), + } updated_metadata = self.update_data_for_checkout_session_and_invoice_payment( general_metadata ) @@ -1778,9 +1802,10 @@ class BillingSession(ABC): # Manual license management is not available for fixed price plan. assert automanage_licenses is True plan_params["fixed_price"] = fixed_price_plan_offer.fixed_price - plan_params["end_date"] = add_months( + period_end = add_months( billing_cycle_anchor, CustomerPlan.FIXED_PRICE_PLAN_DURATION_MONTHS ) + plan_params["end_date"] = period_end fixed_price_plan_offer.status = CustomerPlanOffer.PROCESSED fixed_price_plan_offer.save(update_fields=["status"]) @@ -1841,6 +1866,10 @@ class BillingSession(ABC): plan_tier=plan.tier, billing_schedule=billing_schedule, charge_automatically=False, + invoice_period={ + "start": datetime_to_timestamp(billing_cycle_anchor), + "end": datetime_to_timestamp(period_end), + }, ) def do_upgrade(self, upgrade_request: UpgradeRequest) -> Dict[str, Any]: @@ -2834,6 +2863,7 @@ class BillingSession(ABC): invoiced_through_id = plan.invoiced_through.id invoice_item_created = False + invoice_period = None for ledger_entry in LicenseLedger.objects.filter( plan=plan, id__gt=invoiced_through_id, event_time__lte=event_time ).order_by("id"): @@ -2887,17 +2917,18 @@ class BillingSession(ABC): plan.invoicing_status = CustomerPlan.INVOICING_STATUS_STARTED plan.save(update_fields=["invoicing_status", "invoiced_through"]) assert plan.customer.stripe_customer_id is not None + invoice_period = { + "start": datetime_to_timestamp(ledger_entry.event_time), + "end": datetime_to_timestamp( + get_plan_renewal_or_end_date(plan, ledger_entry.event_time) + ), + } stripe.InvoiceItem.create( currency="usd", customer=plan.customer.stripe_customer_id, description=description, discountable=False, - period={ - "start": datetime_to_timestamp(ledger_entry.event_time), - "end": datetime_to_timestamp( - get_plan_renewal_or_end_date(plan, ledger_entry.event_time) - ), - }, + period=invoice_period, idempotency_key=get_idempotency_key(ledger_entry), **price_args, ) @@ -2923,6 +2954,7 @@ class BillingSession(ABC): description=f"${cents_to_dollar_string(flat_discount)}/month new customer discount", # Negative value to apply discount. amount=(-1 * discount), + period=invoice_period, ) if plan.charge_automatically: diff --git a/corporate/tests/stripe_fixtures/upgrade_by_card--Charge.list.1.json b/corporate/tests/stripe_fixtures/upgrade_by_card--Charge.list.1.json index 483485f6e8130a3209283086056c0792c80b0575..62344ffb94df84db2468adfd5e7693f13c5beed3 100644 GIT binary patch delta 124 zcmdlXy+eA#KUT4-;u3ck*TBT0{6d$k;?jzY2#?@^h{<TxN(vA3$%ybZ_Xy5)54G?psLH7bN-}ZsF?EmhDXc6ps7x*LN-d8p c^fPt$s`3xakI%}BcS^T3EKJ#)&+W+s0N;N-Rjq^7eBHDKE?_$TA3u@+vF~2q-VIFiMYf_pr!tcaC!QC=8A) cFDVOg@$o1L^33)3ObK!}G0WJT&+W+s0JN4WcmMzZ diff --git a/corporate/tests/stripe_fixtures/upgrade_by_card--Customer.modify.1.json b/corporate/tests/stripe_fixtures/upgrade_by_card--Customer.modify.1.json index 96d5fc9c5563182277ebf0c1de782cce725ddbd7..80a4faa8695fdb53414ddbb37450c83cfcec8855 100644 GIT binary patch delta 35 qcmaFK`jT}+52ILBaf!Q&YhYqgexXZNacM diff --git a/corporate/tests/stripe_fixtures/upgrade_by_card--Event.list.1.json b/corporate/tests/stripe_fixtures/upgrade_by_card--Event.list.1.json index 4e30bdb77401a858d77b2a661f0a225c098a3274..9deef4277b0a8ac3c9e7652bead65defb050dbb6 100644 GIT binary patch delta 663 zcmb_aOKTHR6lU^hGKryyHj`Sgse=?m12^-^#Emp0A&aKL*aqunxS6?TCd^DH^RR6e zbs?f#Jxg&}7ZyRBjX%IY;93e@xUEp|2be)9RdnaseCKdJ&g(nC9rGWOR7{W|O)Vz` z86jAuuERR@9H#kPp2faTEXOArduPRW1306u!Lw`umSZ2|tg6Eqy$UBWWHc)iHZJ9s}@UGV}{B}9YIi@l!~SjEf$ delta 494 zcmca>JlSXiDN9FUI!CFNFEn6H7``a|=o)J2Ht){>>;b zIax?>vMkfa$tn_plYcOY@)W1$rNn3EmE~t9r*2kcE?}CxkyT>yV%9fKQMs0ZVc`{3 zey#;RA%=eCfq6MusiAI_p)NU5$)Q2{fnkA_!8xHuJ}$21zAlbNej(W=zK#Y)1_r+2 zg=XeanU0e$vaP0uG5grxvVnbNFgcM^c=BNmabzwlkJ4ljP8BW%U4^35ywvi51ZgVEUo>T*<=VJVzJTz{H~bLYJ)KjDmC{i%M4$B^|EGcLn4pZ*z7Ks*<@3NKy04V1m#{d8T delta 103 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 xbX|=kF7m`oQ}I4W#m4O^{|Ri3(`c~VqGg z7O*dw9H7HDdA%~*jG#0hQUXqC@+sd?0G-_`H2?qr delta 870 zcmbO~hjIQK#tDIphMVt7zGs>kz_t0Bj0>|u;b)3fPu*iHB=}2aW9yBMuu;)EFb6O394n2A1I4V?&rD2XtepG zngq94VQ`+Wi)&zFQGTIIR&ij7VOn@)SkPp7qopdTDHax%DXHeVmgY&Ox+clVrn;7i zhGx2{#wJGQ#zrZYDHchSVGG%AyMjQxgX@cic5oaG(Qh?aaj TBhynXo$@P42_vP+r+h;JvauH) diff --git a/corporate/tests/stripe_fixtures/upgrade_by_card--Invoice.create.1.json b/corporate/tests/stripe_fixtures/upgrade_by_card--Invoice.create.1.json index fb8ade5770c8b15cd48b2bb13d2d820d364da034..550b9fcb0726985acdbbec9634f582c036ef13bf 100644 GIT binary patch delta 69 zcmZ3av`A?KHxrAYfezQ?i|pc?)tDZ!a2lJM8(5lJn3zr$WEbN!HZnCaH#PzC4A`eK Y8JJBz&R)!DIN6$GC!^u!uN=A@0BtW49RL6T delta 71 zcmZ3av`A?KHxrA2g$~!`i|pc?)tDZ!a2mkCWI=W@B%T5LR3<}%$;a7?C-<=NOm^c~ M$7rp0Z=O}kKv#`+6swAU)!*G`j zr_^vi!!X0p%J7JwG9MS$a^Ec93f~YI=ZphN>#lf>Ng$`FGB=cwFtqo`azpU5mX z=VT*K(-c>~++_EhOdl85a$grmBfpSrQ(s2|BLjmB-?YF;Uq_G0uUTeO!I;e_SeuzN z3}8TqO92j)ic1oUN|dY=3}LbclP7SCPVV4nU@|nA%*9ze`8+$% z($vDlbaEf36sNI~sfoF<36Qsub1jpB+2lqp;mI4=WhVD?1x)_H$~E~V*9k_$&6~Kt GZ~_3Knxxqd#8S#HkBMxLfA zu70`6?m3x0F0SRiE{;ZiA=#$B(JyD4uQ=Fxu0?Z0P^QW?*IS* diff --git a/corporate/tests/stripe_fixtures/upgrade_by_card--Invoice.pay.1.json b/corporate/tests/stripe_fixtures/upgrade_by_card--Invoice.pay.1.json index c30d61fe729c61c2fa404bb7530aace779713ada..a3feb53be9e012cc173d12f7f038a7da48e3f935 100644 GIT binary patch delta 230 zcmZ3Zx<++_GSg%QPPWaOOf#6AlHD@Q!omuwBC`#hqukxh!a_rToH*fl_fvVo`~bm4czMk*SHfv5AT4WJhkX$qPB^nGDP(D{&T2-oVZ?c_HUI LM#IekTrnH~FV#e{ delta 229 zcmZ3Zx<++_G82=5#b#BeIZRGbxt2kR2CgQFx#^W51_jPhx#>nxxqd#8S#HkBMxLfA zu70`6?m3x0F0SRiE{;ZiA=#$Bfd)nf1|}83xdBd2j+2>LXH&tL%@0_cnKTSwK!-~K x4wQ;Z5{pWdtP~7kvIdhKxy2?g56^7L_PjDHs|XnVOgzo0ynRE@UiZGBBI` UgfWrPaIzcIR7S(icbM`R0Y8cnxBvhE delta 66 zcmX@baf)MuKckWX4Crtv0D)3*Nn%lnl9hrXOx$2{A!8wvp~2)QjERg!liir6G8%2Z I!<5Ge05NqDVgLXD diff --git a/corporate/tests/stripe_fixtures/upgrade_by_card--SetupIntent.create.1.json b/corporate/tests/stripe_fixtures/upgrade_by_card--SetupIntent.create.1.json index 30672ba9b1f33290ca7cfef1ef0092308f5bfb0f..b748d0663d37a9fa714bfb114357ba898da351b2 100644 GIT binary patch delta 153 zcmZ3)zKDH7g>6-FiMxwyU}8~zp-Wb=NtJP>t7)lcd~s@WQEEwiKtV)RX>z2$SxI`8 zxk+wlcu0Dpi$`*9L}{g0pm+JitxaOs4Vdi9Xp1K0XINh8VO~-?c>&`hG^x^xj0lh5 LfQZczOkRut^Bp&_ delta 153 zcmZ3)zKDH7g>7MQo|}tnU}8~zp-WbAx}j@oP-R+pd~s@WQEEwiKw5radb(qFK$20O zMTKFmr*Bb|WlCmfRJlu4N}m73txaOs4Vdi9Xp1Ig&`hkd!OJTGzl_ OZ;MdBsLc^fUW@>v$~D^n diff --git a/corporate/tests/stripe_fixtures/upgrade_by_card--SetupIntent.list.1.json b/corporate/tests/stripe_fixtures/upgrade_by_card--SetupIntent.list.1.json index e8a95b5e04dc9cbd36e69a56f50f34db1f7ad0cc..0bf4c68aa91b65a7c0f45585372101444d51c408 100644 GIT binary patch delta 104 zcmcb^aff5VEZeH$5;qsuz{H~bLYJ)K(kKhRWYe^e_~O*$qSTW3fP#psQj;pryojWL ojN&X`SBuO-=d8pmKT9uDOQW2L*JT+ECw{FE!*0svX2zRL03eel{Qv*} delta 104 zcmcb^aff5VEZf51JXaUjz{H~bLYJ&!H`Dw|pKQaZ_~O*$qSTW3fVBL;oGi1lN>5{t oz;aiw;zHBpj51^6A`=fYmqg=<*JT-vCVs6D!*0svX2zRL0P&M1E&u=k diff --git a/corporate/tests/stripe_fixtures/upgrade_by_card--SetupIntent.retrieve.1.json b/corporate/tests/stripe_fixtures/upgrade_by_card--SetupIntent.retrieve.1.json index 30672ba9b1f33290ca7cfef1ef0092308f5bfb0f..b748d0663d37a9fa714bfb114357ba898da351b2 100644 GIT binary patch delta 153 zcmZ3)zKDH7g>6-FiMxwyU}8~zp-Wb=NtJP>t7)lcd~s@WQEEwiKtV)RX>z2$SxI`8 zxk+wlcu0Dpi$`*9L}{g0pm+JitxaOs4Vdi9Xp1K0XINh8VO~-?c>&`hG^x^xj0lh5 LfQZczOkRut^Bp&_ delta 153 zcmZ3)zKDH7g>7MQo|}tnU}8~zp-WbAx}j@oP-R+pd~s@WQEEwiKw5radb(qFK$20O zMTKFmr*Bb|WlCmfRJlu4N}m73txaOs4Vdi9Xp1Ig&`hkd!OJTGzl_ OZ;MdBsLc^fUW@>v$~D^n diff --git a/corporate/tests/stripe_fixtures/upgrade_by_card--checkout.Session.create.1.json b/corporate/tests/stripe_fixtures/upgrade_by_card--checkout.Session.create.1.json index a532314f2297baa75480b9fd7aaa49080cf8a118..09366365551a5d2bceef0e2a3d6bd9cdadb6d9a0 100644 GIT binary patch delta 145 zcmdldv`=WmB}PWW&6gPknDmlOa?FxKQ__8l1F|fQe1a@X6T?z+gNjScGfhkKT?mquCmC7Y&&Y+lLM$4H`ilT$fv F0ssOQF>L?< delta 145 zcmdldv`=WmB}PW0&6gPknDk6DBa$*Q469NDL&6Nh@=DxtqAHUjf-MT&LtF}jOr6|4 zLvl?^gMtl=vopLMHw&^fF^Lrh=efGL1|}Be7rJB>yP4)!`eYkMZC=UN$4H`ilT$fv F0s!n2Fy;UN diff --git a/corporate/tests/stripe_fixtures/upgrade_by_card--checkout.Session.list.1.json b/corporate/tests/stripe_fixtures/upgrade_by_card--checkout.Session.list.1.json index 150a47b63cf7a650fd88891038ded64be667a4b5..9a83b1c505b17a52c6205120dbf65210d2135037 100644 GIT binary patch delta 146 zcmca1dP8)B3KOH@W>uyPCcR{n9J8d*lyu+XfGkTRpCHT9#ITgypyCqqOw*El*Mih^ zQ-5;{r>H`sd^6AT&AVAXF^N?bm$mquCmC7Y&&Y(C7si;-0GR&(ky F0st~^F~R@< delta 146 zcmca1dP8)B3KOHzW>uyPCOy;4h@^}R!>ZK4kTAoryb`yZsLG^>V2eWc5SPLrQzv)N zkX+N!pkM>z>yP4)!`eYkMZ9dGti;-0GR&(ky F0stHIF*^VN diff --git a/corporate/tests/stripe_fixtures/upgrade_by_invoice--Event.list.1.json b/corporate/tests/stripe_fixtures/upgrade_by_invoice--Event.list.1.json index 041fccf74619c08c6172ead6c256553e55aae01c..9b546ad56e3aedbd89efae4d7c55214e24ac0682 100644 GIT binary patch delta 605 zcmZ2wbk}$TDkfzUllyqsHV1J2W@R+n?8|?Qu^!303JOX|nK?O` zdFk=R$r-6Br8%iUe=8X(A%_W2QBG!ZYF=?_d~RZ1VtQ(BYF-IQSz>8Per{q(W-<=t z#UMpy=#tt6If;4kC7G#3Sgk58PA!Vh1O>m6p~2(}0#cI|1;r=3@CZ!y6U=4?M#<*A zg7M5O1&Ns{lNCfKPG%Jrn|x4oDJW_)#WX?GR54!=^;FCcM45@tm8>c*@po|zOf1ST zbjd0%_fD;hD)G+*I&AU;9{I`K63r?`md55OsTM}MX=X|0x+ZB!sk)ZQX+W+)vRSgZ hVX~=llHue{5=#69iIpJl#}}6-C#R;SOujAQ4*=NQvrYg2 delta 483 zcmca>yvk?;DN9FUI!CFNFEn6H7``a|=o)J2Ht){>>;b zIax?>vMkfa$tn_pn}0A(XLgFpwG8ri3v)@#wRA}~b}9=A$*2eoi;7G!&WQ@o%gIg2 z@k&h1%`x(EaV__CaWwMFaxC`?G%zwS@HQ;*caO+0oP3dOH8qUc$NrWL?0AF8iJZcd z4|9kkb6I(mCW~+i=sBjOWR_&+=OyMSt5KezHFg+vEkjteac-I~ga>!tK~Q4yMpp63KLxWUH**SZ zE*1)6X2~x|&6|8ubmC+aVd2TeVvE3mEH17Irk%un!SqCNKQR4Je6D0+a9)&)YhYqg zexXZNad~iQW^lHjmy!tyZ(w0}7H4K% zL6jP73W`SaA9`tQnx==QYGdZmLz`BUwrSHgrb&}tni^9NO^m6YJhV;wW)azL(*upS zzQbnUd;k02_kaKQ|8LG*Dfwuj3U&4)Epse1sWZ7* zA&Y}SxOw3_NybkxQCe~tOS?h8#ims>hTv9O-Qbt}0YB1J0 z%5ogstsoiP*a!>Fn`?AUN=T_BCg5}|Y1n}N=7tiMf=5d(Lg^-;xAp8&Qkk3;u7)L? zJWdEL=MTc=WeOfIH#vwgxjm^Qu?$z+nkW=MRAyxfu8lUrZ(a8J1Ys?! zsjGVhqI#M_WRQr&Eb*R5V`CzdXKW?zLMpB7J`v2?0o_1GR=4;`Cv}|&fhrL0DT3u; zg#*UKI@nxU2Y)nFHBDnxw#*7WQ$$uo1aP;7s-?0z8qX_2!{o1+!X(>bYXci4C7E6; zNnJj~dAtHcN>VRVv#Au^UEJpOA(3GPuSom6oJ{k)#M6Gkuh5uddC@O19>33j0jQ1Y8w9y;VYy)dCUu~ZTfZH`#ZhFV@XR#u<)bq8YU(jKg8Lwdeh3 z;KsbZx4qQv@%os6*UuAD9b4c|+HUu7Uf$>7$;zYj7d9SlIO^e{BWq*9R#gl8)2(o2 z;|;hzUJcb%<>nN(!D02lPKvNfN`; rq-pb{jFC(u(mrUfh&a|K1p){OtF0NXUZlzmEsF_9F1;S^U#$NNR0caN delta 1925 zcmd^9O-y4|7|m;Gr4>d%iwq=KI-NKaF5dV5-eh1Xw1q-jsHIS3XiH05+MzSX z)W1X)#_;W23~@2DaVA0E%D8Z8Oo-0Ph2vt3i3{V_l`~@743ac1#IW-wH+T1)^PPLn z`SKl8?Y8Noca7P;T>>0Zw-KQ&1niqh$lvIPtE>%f=iJ7%frqB4WLA7N9>`}`vYAXW zyBvtDh;ca+SYNHCt5KY;#8y};MyazQpT83Jd8x>T_eR)@DU9bUGiq>WF$}i`KRtsn z#`;U+W)MakFp;tXy3%38#|K`Sya<1|J|TGcY1{$(P8Up$FTtbfbI|3o!WH-T&}Z*} z?}plq$MS9)91Kh5Qehiv(?f0bSA&|x0gE0RBr@g)&Ykv+u-W_VDDCJQ}g+wQX#kH z+bHUDiBdYG(BQ@I)wwv`G^R*i6cxl`NIpKL-`QEs2Fs^M zK3wjC_wBL0qz!h~$u zd9kkK9XGF2I>%xeQMxQ6Mx!_+v5baP4fDFBa5^jCzyEKPjQ?L%Oj(U;@MogMlnFjR zbA7&4IK7nhC_I%CQn>-+DD>99ip6CMMB{I_upkprVQE`AC5yvlxgGQ$$ppz8B3?&M*j2SE+8}qfs9x&MFF;cnDiAJ?LoK9D1Ywy2nT0o^%O*klf9Z{q@=qh_Vv~raECV+6iA3)*6LtTq+W#24Cf*j>=>_ zlnsRAO}-!Bbh;H**F{=kkRr=EVi?RJLDD#cX;s2H&1)@VdzcMehr6r`G!yTw8y- diff --git a/corporate/tests/stripe_fixtures/upgrade_by_invoice--Event.list.3.json b/corporate/tests/stripe_fixtures/upgrade_by_invoice--Event.list.3.json index e22ecc4c73df52119e35a412b986c471cdf5102a..e9fcaf5706e73b9c249671a43965b554e8f7e764 100644 GIT binary patch delta 754 zcmaFlyF6n;>*j;J^O+beHYW-MF*_x@Wtb&}o0=wiIJpGoy5$Gux`hU18wRH2IhLnn zIl23J_yvVzdxiSAxR(27`BwObc$)Y-8WdQ#9!hVqX}4CTe56&78BoO87a=m6U3D!-;&%o zxsnsi-@Hg_G7FQj(quVq@y&knj%;F8#U=SJu7Qa~`Gqc7#V*-?d1>x$UX$Z^iYH5` z8L60sq9xrs|renHifJCMG5tr&>-9WS5%Up(Z@Jlf7c| z0p0}^g`QtIDD+bNEz`n6f`iEpJyc_86M8CaleI*-CcofTnQYC^FH%xenySO400&A1 ziJ6ld`9&wsk{6lW$}c#1pS%#WQbFcq0TFe+;*!LY(qbhm1*QCg)V#^pl#C|FDsu_s zmFDCi8Bse~kw+aAMR|xQ^71GQ@HGs}AUTToGV{vvGm}&GN()jFOHwCKR`Uk{+kE8$ delta 1756 zcmb_dOK%%h6qd1@IW**Kw z;xq_Rgjk@q66%p)TaXY7HmxEdwyX&PHi#|!fKtSY9e2iw6C1IDyO{Ak_ndRj`M&Rr zzpVdO{`kXzx*(ZI#1V>brt2YRL88Sgvl+ON*7;-ChdTcaYgIv2MG5=Mu7HaVPGeg@aMXM2e%! z!f7paLzR&!z`}HV>|f68dkxr2Qc;>dbubObCRer^fuSH(a?j2iz3w>9y`HS@daWi_ zY(X;QR$JALVuzx zGw?jo3*RLs2Nl(5x;U6fLU_`b%!H9s~&UUG7 z^U}f};Yi<^pBp}Kwr$i69l?`V>7G_cZe>?mxh%J!7Rcn8?$#5b9&S*Puv8b#9V8QH z)-&{2-1$JpZIi&@KiE3>9^*PI|L2cb;Av2TBvlX_MZWkE!vJ(tcER%XvZV_ zi%b+E!6A4U39TYsCgu(x8KOK-A)?eZPGow{U&%O@xZ`=6i2SUnh=EjWCcanIQE7Qi zG>yH|U8|~z+4WT}M?&Gr#5g>Ntp#*PRpCYK@?@?iOYB@RpJwNjVtS6ta_M;qp)@ZS zikz55^Q^4E)9l!&HRv=MB@?_W4&mm<_Z%ETZ(HR9(^w0Ruph2KL7 zI1UU4m~&bTF)~uIzUL6Z!~3%oL-v+LbY){hcL6?hRNSDiY9DW=u1WDzp zCSV!v4@HJs8zSlUr5;5K)6p?TM+dfm^?d_Nh)kthEE$+*i1_0J4N?*^ z$%jx-4M|jCja1zq3BspI3d8^n*P}zeK6plr0C1D=eIRm5n{q~5gRO2ZZS3d&6Kw-+ z+MI?=_&VB((|&)xMb1&hKkHxG){5(!D-CT+Q`K$lt(D4FakHkb;I|KV57*e;W_2sa zS9$sMJEi4jxwObv?k*mb7g?TVZ#Qqsx9+`JhA{or|B&YBFZwk<*o5Rqq22(Q9254q zDD(~_;KAf)z5+Z8jlzqN^SFX@$=h@;QmmOEr#&p7A$C48LSo{|35? BAQS)q diff --git a/corporate/tests/stripe_fixtures/upgrade_by_invoice--Invoice.create.1.json b/corporate/tests/stripe_fixtures/upgrade_by_invoice--Invoice.create.1.json index a3709fcc03c74c361e155752b58e16efc499bbbb..2c62012cb8fc7fb5fbe4cb1f8f75b88d93d579c9 100644 GIT binary patch delta 84 zcmZ3Xv_feED-*MY4%g&(R`Jd9Os`lpj7`lAEKMy;Om(;v;6SOkB(bPO$x6Y{*vQnx h+}Om#bh07)G)9xjC)kS_4JX@h>|`|D{Efqi0{~pl6(s-w delta 77 zcmZ3Xv_feED-*Ms4%g&(R`Jd9Os`lbckuE`D?ou#aYJ_ Wd-3F6HlE4u9P1d3Hh<$V;s5{)3>4M? diff --git a/corporate/tests/stripe_fixtures/upgrade_by_invoice--Invoice.finalize_invoice.1.json b/corporate/tests/stripe_fixtures/upgrade_by_invoice--Invoice.finalize_invoice.1.json index 2598f9e58d2b128779876674c144cb3ace6cbda2..9839256ca086ac890fc4cceb8687fafca1157d3b 100644 GIT binary patch delta 225 zcmbQLI#qQ8D-)x|W;UipOisye8D>f0rlyG=PA-ADZuvpEZlOWhhJh)0j^!y?PVRml zenBDGUZFlNuI0X2z7@V9o+f^Q21W)3e(63YmcCI=lV7pSrh+k>kF&NiX&9TD8(5lJ zn3(EtDZqhJaYGZkdr)*;RoC+2z6E zrbfX=DIPv9uI0Wijz)f2j^+M=21W)3MTw=Ud1byvlV7pSrh+k>kF&NiX&AtO4wnKP wC>56^7L_PjDHy_J4JJ?I7Mzbta>Z}}0BQk6g#Z8m diff --git a/corporate/tests/stripe_fixtures/upgrade_by_invoice--Invoice.list.1.json b/corporate/tests/stripe_fixtures/upgrade_by_invoice--Invoice.list.1.json index 7d7143dcfb9e4448d04a2a85568b452a9859e75c..83c684e9657a17b58a6d9886318d876e07657fba 100644 GIT binary patch delta 235 zcmeyZ^;>I04imG54%g&~?DCuYm~JvTCA(#qC54-sCVDuz1m?Qs2j#kj24x!trsO%6 zr(`*~`+4{Ug=Bk$`nb53`)2u8_=b3z_y-yo85ral7-m%EIE7AL$-0;d#%%6md&s0? zY-(;`X=-6&s>7v#0+fnN5{pWdtP~85jZ96{0HNDTl0 delta 224 zcmeyZ^;>I04imGP4%g&~?DCuYm~JvTMdexsg}N2whUezwMCFFL`Gs4CCgr$gMpk84 z1sY_R2Zx&)1skP!__(;1`?@$9`DHm)_@)~e85sC^<%Opdc=}IX$-0;d#%%6md&o3d zMOau;0SuIiOA?Dpl&lmC4Paoh08l`nVo47lT)%=hFMa$scE8zlS^Q(TYgZkTWC8m0nVo47lT%c#Wl*SFL2h_%PEJ&An44d?WoS~4TV`Zcc2%H3c6o5P zsZp>|iieMjYq_tBqmf^hV}-AyfsuiMce#6tXJvrz56^7L_PjDHs|XnVOgzo0ynRE@CWVG@1OA TF_F=5vOCjMM#If_nF<&IGA0p| delta 65 zcmX@hah7940Hcxt4Crtv0D)3*Nn%lnl9hrXOx$2{5n~af`Q)dJiHt^*-I=B`8g0JI HRKN%TB=ZqP diff --git a/corporate/tests/test_stripe.py b/corporate/tests/test_stripe.py index 0bf9c42e43..16ecc665e8 100644 --- a/corporate/tests/test_stripe.py +++ b/corporate/tests/test_stripe.py @@ -884,6 +884,10 @@ class StripeTest(StripeTestCase): "plan": None, "proration": False, "quantity": self.seat_count, + "period": { + "start": datetime_to_timestamp(self.now), + "end": datetime_to_timestamp(add_months(self.now, 12)), + }, } for key, value in line_item_params.items(): self.assertEqual(item0.get(key), value) @@ -1022,6 +1026,10 @@ class StripeTest(StripeTestCase): "plan": None, "proration": False, "quantity": 123, + "period": { + "start": datetime_to_timestamp(self.now), + "end": datetime_to_timestamp(add_months(self.now, 12)), + }, } for key, value in line_item_params.items(): self.assertEqual(item.get(key), value)