6
6
7
7
import { injectable , inject } from "inversify" ;
8
8
import { ChargebeeProvider } from "./chargebee-provider" ;
9
+ import { Chargebee as chargebee } from "./chargebee-types" ;
9
10
import { LogContext , log } from "@gitpod/gitpod-protocol/lib/util/logging" ;
10
11
11
12
@injectable ( )
@@ -22,24 +23,75 @@ export class UpgradeHelper {
22
23
* @param description
23
24
* @param upgradeTimestamp
24
25
*/
25
- async chargeForUpgrade ( userId : string , chargebeeSubscriptionId : string , amountInCents : number , description : string , upgradeTimestamp : string ) {
26
+ async chargeForUpgrade (
27
+ userId : string ,
28
+ chargebeeSubscriptionId : string ,
29
+ amountInCents : number ,
30
+ description : string ,
31
+ upgradeTimestamp : string ,
32
+ ) {
26
33
const logContext : LogContext = { userId } ;
27
- const logPayload = { chargebeeSubscriptionId : chargebeeSubscriptionId , amountInCents, description, upgradeTimestamp } ;
34
+ const logPayload = {
35
+ chargebeeSubscriptionId : chargebeeSubscriptionId ,
36
+ amountInCents,
37
+ description,
38
+ upgradeTimestamp,
39
+ } ;
28
40
29
41
await new Promise < void > ( ( resolve , reject ) => {
30
- log . info ( logContext , 'Charge on Upgrade: Upgrade detected.' , logPayload ) ;
31
- this . chargebeeProvider . subscription . add_charge_at_term_end ( chargebeeSubscriptionId , {
32
- amount : amountInCents ,
33
- description
34
- } ) . request ( function ( error : any , result : any ) {
35
- if ( error ) {
36
- log . error ( logContext , 'Charge on Upgrade: error' , error , logPayload ) ;
37
- reject ( error ) ;
38
- } else {
39
- log . info ( logContext , 'Charge on Upgrade: successful' , logPayload ) ;
40
- resolve ( ) ;
41
- }
42
- } ) ;
42
+ log . info ( logContext , "Charge on Upgrade: Upgrade detected." , logPayload ) ;
43
+ this . chargebeeProvider . subscription
44
+ . add_charge_at_term_end ( chargebeeSubscriptionId , {
45
+ amount : amountInCents ,
46
+ description,
47
+ } )
48
+ . request ( function ( error : any , result : any ) {
49
+ if ( error ) {
50
+ log . error ( logContext , "Charge on Upgrade: error" , error , logPayload ) ;
51
+ reject ( error ) ;
52
+ } else {
53
+ log . info ( logContext , "Charge on Upgrade: successful" , logPayload ) ;
54
+ resolve ( ) ;
55
+ }
56
+ } ) ;
43
57
} ) ;
44
58
}
45
- }
59
+
60
+ // Returns a ratio between 0 and 1:
61
+ // 0 means we've just finished the term
62
+ // 1 means we still have the entire term left
63
+ getCurrentTermRemainingRatio ( chargebeeSubscription : chargebee . Subscription ) : number {
64
+ if ( ! chargebeeSubscription . next_billing_at ) {
65
+ throw new Error ( "subscription.next_billing_at must be set." ) ;
66
+ }
67
+ const now = new Date ( ) ;
68
+ const nextBilling = new Date ( chargebeeSubscription . next_billing_at * 1000 ) ;
69
+ const remainingMs = nextBilling . getTime ( ) - now . getTime ( ) ;
70
+
71
+ const getBillingCycleMs = ( unit : chargebee . BillingPeriodUnit ) : number => {
72
+ const previousBilling = new Date ( nextBilling . getTime ( ) ) ;
73
+ switch ( unit ) {
74
+ case "day" :
75
+ previousBilling . setDate ( nextBilling . getDate ( ) - 1 ) ;
76
+ break ;
77
+ case "week" :
78
+ previousBilling . setDate ( nextBilling . getDate ( ) - 7 ) ;
79
+ break ;
80
+ case "month" :
81
+ previousBilling . setMonth ( nextBilling . getMonth ( ) - 1 ) ;
82
+ break ;
83
+ case "year" :
84
+ previousBilling . setFullYear ( nextBilling . getFullYear ( ) - 1 ) ;
85
+ break ;
86
+ }
87
+ return nextBilling . getTime ( ) - previousBilling . getTime ( ) ;
88
+ } ;
89
+
90
+ const billingCycleMs =
91
+ typeof chargebeeSubscription . billing_period === "number" && chargebeeSubscription . billing_period_unit
92
+ ? chargebeeSubscription . billing_period * getBillingCycleMs ( chargebeeSubscription . billing_period_unit )
93
+ : 1 * getBillingCycleMs ( "month" ) ;
94
+
95
+ return remainingMs / billingCycleMs ;
96
+ }
97
+ }
0 commit comments