Просмотр исходного кода

Merge pull request #2697 from overleaf/pr-add-vat-number

Add VAT number and company name to the payment form

GitOrigin-RevId: 9ba2d7345f6f3cef1f7372e17c04243ab285e0bd
Paulo Jorge Reis 6 лет назад
Родитель
Сommit
7f13e258bb

+ 39 - 9
services/web/app/src/Features/Subscription/RecurlyWrapper.js

@@ -86,7 +86,7 @@ module.exports = RecurlyWrapper = {
 
       let address
       try {
-        address = getAddressFromSubscriptionDetails(subscriptionDetails)
+        address = getAddressFromSubscriptionDetails(subscriptionDetails, false)
       } catch (error) {
         return next(error)
       }
@@ -173,25 +173,36 @@ module.exports = RecurlyWrapper = {
       )
     },
 
-    setAddress(cache, next) {
+    setAddressAndCompanyBillingInfo(cache, next) {
       const { user } = cache
       const { subscriptionDetails } = cache
-      logger.log({ user_id: user._id }, 'setting billing address in recurly')
+      logger.log(
+        { user_id: user._id },
+        'setting billing address and company info in recurly'
+      )
       const accountCode = __guard__(
         cache != null ? cache.account : undefined,
         x1 => x1.account_code
       )
       if (!accountCode) {
-        return next(new Error('no account code at setAddress stage'))
+        return next(
+          new Error('no account code at setAddressAndCompanyBillingInfo stage')
+        )
       }
 
-      let address
+      let addressAndCompanyBillingInfo
       try {
-        address = getAddressFromSubscriptionDetails(subscriptionDetails)
+        addressAndCompanyBillingInfo = getAddressFromSubscriptionDetails(
+          subscriptionDetails,
+          true
+        )
       } catch (error) {
         return next(error)
       }
-      const requestBody = RecurlyWrapper._buildXml('billing_info', address)
+      const requestBody = RecurlyWrapper._buildXml(
+        'billing_info',
+        addressAndCompanyBillingInfo
+      )
 
       return RecurlyWrapper.apiRequest(
         {
@@ -296,7 +307,7 @@ module.exports = RecurlyWrapper = {
         Async.apply(RecurlyWrapper._paypal.checkAccountExists, cache),
         RecurlyWrapper._paypal.createAccount,
         RecurlyWrapper._paypal.createBillingInfo,
-        RecurlyWrapper._paypal.setAddress,
+        RecurlyWrapper._paypal.setAddressAndCompanyBillingInfo,
         RecurlyWrapper._paypal.createSubscription
       ],
       function(err, result) {
@@ -1048,8 +1059,12 @@ function getCustomFieldsFromSubscriptionDetails(subscriptionDetails) {
   return { custom_field: customFields }
 }
 
-function getAddressFromSubscriptionDetails(subscriptionDetails) {
+function getAddressFromSubscriptionDetails(
+  subscriptionDetails,
+  includeCompanyInfo
+) {
   const { address } = subscriptionDetails
+
   if (!address || !address.country) {
     throw new Errors.InvalidError({
       message: 'Invalid country',
@@ -1070,6 +1085,21 @@ function getAddressFromSubscriptionDetails(subscriptionDetails) {
     country: address.country
   }
 
+  if (
+    includeCompanyInfo &&
+    subscriptionDetails.billing_info &&
+    subscriptionDetails.billing_info.company &&
+    subscriptionDetails.billing_info.company !== ''
+  ) {
+    addressObject.company = subscriptionDetails.billing_info.company
+    if (
+      subscriptionDetails.billing_info.vat_number &&
+      subscriptionDetails.billing_info.vat_number !== ''
+    ) {
+      addressObject.vat_number = subscriptionDetails.billing_info.vat_number
+    }
+  }
+
   return addressObject
 }
 

+ 1 - 0
services/web/app/views/subscriptions/dashboard/_personal_subscription_recurly.pug

@@ -8,6 +8,7 @@ div(ng-controller="RecurlySubscriptionController")
 		case personalSubscription.recurly.state
 			when "active"
 				p !{translate("currently_subscribed_to_plan", {planName:"<strong>" + personalSubscription.plan.name + "</strong>"})}
+					|
 					a(href, ng-click="switchToChangePlanView()", ng-if="showChangePlanButton") !{translate("change_plan")}.
 				-if (personalSubscription.recurly.trialEndsAtFormatted && personalSubscription.recurly.trial_ends_at > Date.now())
 					p You're on a free trial which ends on <strong ng-non-bindable>#{personalSubscription.recurly.trialEndsAtFormatted}</strong>

+ 41 - 14
services/web/app/views/subscriptions/new.pug

@@ -62,7 +62,6 @@ block content
 										novalidate
 									)
 
-
 										div.payment-method-toggle
 											a.payment-method-toggle-switch(
 												href
@@ -165,22 +164,42 @@ block content
 													ng-model="data.country"
 													name="country"
 													ng-change="updateCountry()"
-													required,
 													ng-selected="{{country.code == data.country}}"
+													ng-model-options="{ debounce: 200 }"
+													required
 												)
 													option(value='', disabled) #{translate("country")}
 													option(value='-', disabled) --------------
 													option(ng-repeat="country in countries" ng-bind-html="country.name" value="{{country.code}}")
 												span.input-feedback-message {{ simpleCCForm.country.$error.required ? 'This field is required' : '' }}
 
-											if (showVatField)
-												.form-group
-													label(for="vat-no") #{translate('vat_number')}
-													input#vat-no.form-control(
-														type="text"
-														ng-blur="applyVatNumber()"
-														ng-model="data.vat_number"
-													)
+											.form-group
+												.checkbox
+													label
+														input(
+															type="checkbox"
+															ng-model="ui.addCompanyDetails"
+														)
+														|
+														| #{translate("add_company_details")}
+
+											.form-group(ng-show="ui.addCompanyDetails")
+												label(for="company-name") #{translate("company_name")}
+												input#company-name.form-control(
+													type="text"
+													name="companyName"
+													ng-model="data.company"
+												)
+
+											.form-group(ng-show="ui.addCompanyDetails && price.taxes.length")
+												label(for="vat-number") #{translate("vat_number")}
+												input#vat-number.form-control(
+													type="text"
+													name="vatNumber"
+													ng-model="data.vat_number"
+													ng-blur="applyVatNumber()"
+												)
+
 											if (showCouponField)
 												.form-group
 													label(for="coupon-code") #{translate('coupon_code')}
@@ -192,11 +211,19 @@ block content
 
 											p(ng-if="paymentMethod.value === 'paypal'") #{translate("paypal_upgrade")}
 
-											div.price-breakdown(ng-if="price.next.tax !== '0.00'")
+											div.price-breakdown(
+												ng-show="price.taxes.length"
+											)
 												hr.thin
-												span Total:
-												strong {{availableCurrencies[currencyCode]['symbol']}}{{price.next.total}}
-												span ({{availableCurrencies[currencyCode]['symbol']}}{{price.next.subtotal}} + {{availableCurrencies[currencyCode]['symbol']}}{{price.next.tax}} tax)
+												span 
+													| Total:
+													|
+												strong 
+													| {{availableCurrencies[currencyCode]['symbol']}}{{price.next.total}}
+													|
+												span 
+													| ({{availableCurrencies[currencyCode]['symbol']}}{{price.next.subtotal}} + {{availableCurrencies[currencyCode]['symbol']}}{{price.next.tax}} tax)
+													|
 												span(ng-if="monthlyBilling") #{translate("every")} #{translate("month")}
 												span(ng-if="!monthlyBilling") #{translate("every")} #{translate("year")}
 												hr.thin

+ 31 - 5
services/web/frontend/js/main/new-subscription.js

@@ -17,6 +17,10 @@ define(['../base', '../directives/creditCards'], App =>
       return
     }
 
+    $scope.ui = {
+      addCompanyDetails: false
+    }
+
     $scope.recurlyLoadError = false
     $scope.currencyCode = MultiCurrencyPricing.currencyCode
     $scope.allCurrencies = MultiCurrencyPricing.plans
@@ -58,6 +62,8 @@ define(['../base', '../directives/creditCards'], App =>
       address2: '',
       state: '',
       city: '',
+      company: '',
+      vat_number: '',
       country: window.countryCode,
       coupon: window.couponCode
     }
@@ -99,7 +105,9 @@ define(['../base', '../directives/creditCards'], App =>
 
     pricing
       .plan(window.plan_code, { quantity: 1 })
-      .address({ country: $scope.data.country })
+      .address({
+        country: $scope.data.country
+      })
       .tax({ tax_code: 'digital', vat_number: '' })
       .currency($scope.currencyCode)
       .coupon($scope.data.coupon)
@@ -219,7 +227,6 @@ define(['../base', '../directives/creditCards'], App =>
             coupon_code: pricing.items.coupon ? pricing.items.coupon.code : '',
             first_name: $scope.data.first_name,
             last_name: $scope.data.last_name,
-
             isPaypal: $scope.paymentMethod.value === 'paypal',
             address: {
               address1: $scope.data.address1,
@@ -233,6 +240,21 @@ define(['../base', '../directives/creditCards'], App =>
           }
         }
 
+        if (
+          postData.subscriptionDetails.isPaypal &&
+          $scope.ui.addCompanyDetails
+        ) {
+          postData.subscriptionDetails.billing_info = {}
+          if ($scope.data.company && $scope.data.company !== '') {
+            postData.subscriptionDetails.billing_info.company =
+              $scope.data.company
+          }
+          if ($scope.data.vat_number && $scope.data.vat_number !== '') {
+            postData.subscriptionDetails.billing_info.vat_number =
+              $scope.data.vat_number
+          }
+        }
+
         eventTracking.sendMB('subscription-form-submitted', {
           currencyCode: postData.subscriptionDetails.currencyCode,
           plan_code: postData.subscriptionDetails.plan_code,
@@ -244,7 +266,6 @@ define(['../base', '../directives/creditCards'], App =>
           'subscription-form-submitted',
           postData.subscriptionDetails.plan_code
         )
-
         return $http
           .post('/user/subscription/create', postData)
           .then(function() {
@@ -274,9 +295,14 @@ define(['../base', '../directives/creditCards'], App =>
       $scope.processing = true
       if ($scope.paymentMethod.value === 'paypal') {
         const opts = { description: $scope.planName }
-        return recurly.paypal(opts, completeSubscription)
+        recurly.paypal(opts, completeSubscription)
       } else {
-        return recurly.token($scope.data, completeSubscription)
+        const tokenData = _.cloneDeep($scope.data)
+        if (!$scope.ui.addCompanyDetails) {
+          delete tokenData.company
+          delete tokenData.vat_number
+        }
+        recurly.token(tokenData, completeSubscription)
       }
     }
 

+ 13 - 7
services/web/test/unit/src/Subscription/RecurlyWrapperTests.js

@@ -862,7 +862,10 @@ describe('RecurlyWrapper', function() {
         this.RecurlyWrapper._paypal,
         'createBillingInfo'
       )
-      this.setAddress = sinon.stub(this.RecurlyWrapper._paypal, 'setAddress')
+      this.setAddressAndCompanyBillingInfo = sinon.stub(
+        this.RecurlyWrapper._paypal,
+        'setAddressAndCompanyBillingInfo'
+      )
       this.createSubscription = sinon.stub(
         this.RecurlyWrapper._paypal,
         'createSubscription'
@@ -917,7 +920,7 @@ describe('RecurlyWrapper', function() {
         account: { accountCode: 'xx' },
         billingInfo: { token_id: 'abc' }
       })
-      this.setAddress.callsArgWith(1, null, {
+      this.setAddressAndCompanyBillingInfo.callsArgWith(1, null, {
         user,
         subscriptionDetails,
         recurlyTokenIds,
@@ -949,7 +952,7 @@ describe('RecurlyWrapper', function() {
       this.checkAccountExists.restore()
       this.createAccount.restore()
       this.createBillingInfo.restore()
-      this.setAddress.restore()
+      this.setAddressAndCompanyBillingInfo.restore()
       return this.createSubscription.restore()
     })
 
@@ -973,7 +976,7 @@ describe('RecurlyWrapper', function() {
         this.checkAccountExists.callCount.should.equal(1)
         this.createAccount.callCount.should.equal(1)
         this.createBillingInfo.callCount.should.equal(1)
-        this.setAddress.callCount.should.equal(1)
+        this.setAddressAndCompanyBillingInfo.callCount.should.equal(1)
         this.createSubscription.callCount.should.equal(1)
         return done()
       })
@@ -996,7 +999,7 @@ describe('RecurlyWrapper', function() {
           this.checkAccountExists.callCount.should.equal(1)
           this.createAccount.callCount.should.equal(1)
           this.createBillingInfo.callCount.should.equal(0)
-          this.setAddress.callCount.should.equal(0)
+          this.setAddressAndCompanyBillingInfo.callCount.should.equal(0)
           this.createSubscription.callCount.should.equal(0)
           return done()
         })
@@ -1414,12 +1417,15 @@ describe('RecurlyWrapper', function() {
       })
     })
 
-    describe('_paypal.setAddress', function() {
+    describe('_paypal.setAddressAndCompanyBillingInfo', function() {
       beforeEach(function() {
         this.cache.account = { account_code: 'abc' }
         this.cache.billingInfo = {}
         return (this.call = callback => {
-          return this.RecurlyWrapper._paypal.setAddress(this.cache, callback)
+          return this.RecurlyWrapper._paypal.setAddressAndCompanyBillingInfo(
+            this.cache,
+            callback
+          )
         })
       })