← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~sinzui/launchpad/entitlement-1 into lp:launchpad

 

Curtis Hovey has proposed merging lp:~sinzui/launchpad/entitlement-1 into lp:launchpad with lp:~sinzui/launchpad/pre-entitlement-1 as a prerequisite.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #951151 in Launchpad itself: "give proprietary projects a complimentary commercial subscription"
  https://bugs.launchpad.net/launchpad/+bug/951151

For more details, see:
https://code.launchpad.net/~sinzui/launchpad/entitlement-1/+merge/96835

Give proprietary projects a complimentary commercial subscriptions.

    Pre-implementation: StevenK

We want to give proprietary projects complimentary commercial subscriptions
to ensure that projects can be configured setup to no disclose information
from the start. This solves two outstanding issues.

1. There is often a delay of hours from the the moment Lp tell a
maintainer how to purchase and commercial subscription and the time one
is applied. This affects Canonical staff that need to find someone who
can apply to commercial subscription so that proprietary features can be
enabled. We do not want to accidentally disclose proprietary information
while project setup is incomplete.

2. We commonly enable proprietary features for prospective commercial
customers, and leave notes on pages to prevent the project from being
disabled during the trial. We would prefer that users be able to try
proprietary without getting the assistance of staff via email and IRC.

This is an incremental change just issues the complimentary
commercial subscription.

--------------------------------------------------------------------

RULES

    THIS BRANCH
    * When a OTHER/PROPRIETARY license is added to a project, and the
      project does not have any commercial subscriptions add a commercial
      subscription that expires in 4 weeks.
      * We check for previous active and expired commercial subscriptions
        to ensure that users cannot get extra time by reconfiguring their
        project.
        * Product._setLicenses()
      * Use StevenK's example from the LaunchpadFactory to create a
        commercial subscription without a voucher.

    FUTURE BRANCHES
    * The UI and an email is sent to inform the user of the complimentary
      commercial subscription and it will explain when it expires and how
      to active the proprietary features. There is a link to purchase a
      full subscription.
      * This email probably replaces the existing email that explain Lp's
        licensing and purchasing rules.
    * At 4 weeks and 1 weeks before a commercial subscription expires, a
      reminder is sent to purchase a commercial subscription.
      * the email also explain that the project will be deactivated if the
        subscription is not renewed and the project is still proprietary
        to ensure proprietary is not added added.
      * Users can choose an Open source license. Branches and bugs will
        remain proprietary because we understand that confidential information
        can never be disclosed, but new bugs and branches will be public...
        the project's focus of development must be set to a public branch.
    * Bonus points if there is a clear way to identify a Canonical owned
      project and set the commercial subscription to expire in 10 years.


QA

    * Visit https://qastaging.launchpad.net/projects/+new and create a
      non-proprietary project.
    * Verify it does not have a commercial subscription
    * Use Change details to set the license to proprietary.
    * Verify it has a commercial subscription that expires in one month.
    * Verify a notice explains the situation and how to configure proprietary
      features.
    * Verify an email was sent to the maintainer explaining how to
      purchase a commercial subscription and how to configure a proprietary
      project.

    * Visit https://qastaging.launchpad.net/projects/+new and create a
      proprietary project.
    * Verify it has a commercial subscription that expires in one month.
    * Verify a notice explains the situation and how to configure proprietary
      features.
    * Verify an email was sent to the maintainer explaining how to
      purchase a commercial subscription and how to configure a proprietary
      project.
    * Set default private_bugs and branches default forbidden.
    * Set a branch as the development focus.

    * Remove the proprietary license using Change details.
    * Verify that the default private_bugs is still enabled.
    * Verify that branches default forbidden is still true

    * Force the license of both test projects to expire in less then a week.
    * Verify an email was sent to the maintainer of both projects explaining
      the situation.

    * Force the license to expire.
    * Verify the open project's default private bugs is False and that
      you cannot set the value to True.
    * Verify that default forbidden branches is False and that the project's
      focus of development branch is unset.
    * Set the open project project's license to proprietary
    * Verify that a commercial subscription was not given to the project.

    * Verify that the first project that was left as proprietary was
      deactivated.


LINT

    lib/lp/registry/model/product.py
    lib/lp/registry/tests/test_product.py


TEST

    ./bin/test -vv -t ProductLicensingTestCase lp.registry.tests.test_product


IMPLEMENTATION

Updated the _setLicense() method to create a 30 day complimentary commercial
subscription if the project has a proprietary license and does not already
have a commercial_subscription. As was demonstrated by the factory method
that creates a CommercialSubscription for tests, Lp does not require a real
id that matches a voucher in the sales system, and there is no code that uses
the string we place in field. We can put any information we want to store
in the field that helps us identify how the commercial subscription was
authorised.
    lib/lp/registry/model/product.py
    lib/lp/registry/tests/test_product.py
-- 
https://code.launchpad.net/~sinzui/launchpad/entitlement-1/+merge/96835
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~sinzui/launchpad/entitlement-1 into lp:launchpad.
=== modified file 'lib/lp/registry/model/product.py'
--- lib/lp/registry/model/product.py	2012-03-09 21:30:28 +0000
+++ lib/lp/registry/model/product.py	2012-03-09 21:30:28 +0000
@@ -771,6 +771,18 @@
         for license in licenses.difference(old_licenses):
             ProductLicense(product=self, license=license)
         get_property_cache(self)._cached_licenses = tuple(sorted(licenses))
+        if (License.OTHER_PROPRIETARY in licenses
+            and self.commercial_subscription is None):
+            lp_janitor = getUtility(ILaunchpadCelebrities).janitor
+            now = datetime.datetime.now(pytz.UTC)
+            date_expires = now + datetime.timedelta(days=30)
+            sales_system_id = 'complimentary-30-day-%s' % now
+            whiteboard = "Complimentary 30 day subscription."
+            subscription = CommercialSubscription(
+                product=self, date_starts=now, date_expires=date_expires,
+                registrant=lp_janitor, purchaser=lp_janitor,
+                sales_system_id=sales_system_id, whiteboard=whiteboard)
+            get_property_cache(self).commercial_subscription = subscription
 
     licenses = property(_getLicenses, _setLicenses)
 

=== modified file 'lib/lp/registry/tests/test_product.py'
--- lib/lp/registry/tests/test_product.py	2012-03-09 21:30:28 +0000
+++ lib/lp/registry/tests/test_product.py	2012-03-09 21:30:28 +0000
@@ -10,6 +10,7 @@
 import pytz
 from testtools.matchers import MatchesAll
 import transaction
+from zope.component import getUtility
 from zope.security.interfaces import Unauthorized
 from zope.security.proxy import removeSecurityProxy
 
@@ -19,6 +20,7 @@
     IHasIcon,
     IHasLogo,
     IHasMugshot,
+    ILaunchpadCelebrities,
     ILaunchpadUsage,
     IServiceUsage,
     )
@@ -35,6 +37,7 @@
     )
 from lp.registry.interfaces.product import (
     IProduct,
+    IProductSet,
     License,
     )
 from lp.registry.interfaces.series import SeriesStatus
@@ -503,6 +506,69 @@
             self.assertRaises(
                 ValueError, setattr, product, 'licenses', ['bogus'])
 
+    def test_setLicense_non_proprietary(self):
+        # Non-proprietary projects are not given a complimentary
+        # commercial subscription.
+        product = self.factory.makeProduct(licenses=[License.MIT])
+        self.assertIsNone(product.commercial_subscription)
+
+    def test_setLicense_proprietary_with_commercial_subscription(self):
+        # Proprietary projects with existing commercial subscriptions are not
+        # given a complimentary commercial subscription.
+        product = self.factory.makeProduct()
+        self.factory.makeCommercialSubscription(product)
+        with celebrity_logged_in('admin'):
+            product.commercial_subscription.sales_system_id = 'testing'
+            date_expires = product.commercial_subscription.date_expires
+        with person_logged_in(product.owner):
+            product.licenses = [License.OTHER_PROPRIETARY]
+        with celebrity_logged_in('admin'):
+            self.assertEqual(
+                'testing', product.commercial_subscription.sales_system_id)
+            self.assertEqual(
+                date_expires, product.commercial_subscription.date_expires)
+
+    def test_setLicense_proprietary_without_commercial_subscription(self):
+        # Proprietary projects without a commercial subscriptions are
+        # given a complimentary 30 day commercial subscription.
+        product = self.factory.makeProduct()
+        with person_logged_in(product.owner):
+            product.licenses = [License.OTHER_PROPRIETARY]
+        with celebrity_logged_in('admin'):
+            cs = product.commercial_subscription
+            self.assertIsNotNone(cs)
+            self.assertIn('complimentary-30-day', cs.sales_system_id)
+            now = datetime.datetime.now(pytz.UTC)
+            self.assertTrue(now >= cs.date_starts)
+            future_30_days = now + datetime.timedelta(days=30)
+            self.assertTrue(future_30_days >= cs.date_expires)
+            self.assertEqual(
+                "Complimentary 30 day subscription.", cs.whiteboard)
+            lp_janitor = getUtility(ILaunchpadCelebrities).janitor
+            self.assertEqual(lp_janitor, cs.registrant)
+            self.assertEqual(lp_janitor, cs.purchaser)
+
+    def test_new_proprietary_has_commercial_subscription(self):
+        # New proprietary projects are given a complimentary 30 day
+        # commercial subscription.
+        owner = self.factory.makePerson()
+        product = getUtility(IProductSet).createProduct(
+            owner, 'fnord', 'Fnord', 'Fnord', 'test 1', 'test 2',
+            licenses=[License.OTHER_PROPRIETARY])
+        with celebrity_logged_in('admin'):
+            cs = product.commercial_subscription
+            self.assertIsNotNone(cs)
+            self.assertIn('complimentary-30-day', cs.sales_system_id)
+            now = datetime.datetime.now(pytz.UTC)
+            self.assertTrue(now >= cs.date_starts)
+            future_30_days = now + datetime.timedelta(days=30)
+            self.assertTrue(future_30_days >= cs.date_expires)
+            self.assertEqual(
+                "Complimentary 30 day subscription.", cs.whiteboard)
+            lp_janitor = getUtility(ILaunchpadCelebrities).janitor
+            self.assertEqual(lp_janitor, cs.registrant)
+            self.assertEqual(lp_janitor, cs.purchaser)
+
 
 class ProductSnapshotTestCase(TestCaseWithFactory):
     """Test product snapshots.