Commit 0237e36f by Renzo Lucioni

Merge pull request #622 from edx/renzo/kill-docs

Indicate that docs have moved to the ICR guide
parents 37477204 dcc14151
......@@ -16,10 +16,10 @@ Prerequisites
Documentation |ReadtheDocs|_
----------------------------
.. |ReadtheDocs| image:: https://readthedocs.org/projects/open-edx-ecommerce-guide/badge/?version=latest
.. _ReadtheDocs: https://open-edx-ecommerce-guide.readthedocs.org/en/latest/
.. |ReadtheDocs| image:: https://readthedocs.org/projects/edx/badge/?version=latest
.. _ReadtheDocs: http://edx.readthedocs.org/projects/edx-installing-configuring-and-running/en/latest/ecommerce/index.html
`Documentation <https://open-edx-ecommerce-guide.readthedocs.org/en/latest/>`_ is hosted on Read the Docs.
`Documentation <http://edx.readthedocs.org/projects/edx-installing-configuring-and-running/en/latest/ecommerce/index.html>`_ is hosted on Read the Docs. To contribute, please open a PR against https://github.com/edx/edx-documentation.
License
-------
......
Asset Pipeline
==============
Static files are managed via `django-compressor`_. `RequireJS`_ and r.js are used to manage JavaScript dependencies.
django-compressor compiles SASS, minifies JavaScript, and handles naming files to facilitate cache busting during deployment.
.. _django-compressor: http://django-compressor.readthedocs.org/
.. _RequireJS: http://requirejs.org/
Both tools should operate seamlessly in a local development environment. When deploying to production, call
``make static`` to compile all static assets and move them to the proper location to be served.
When creating new pages that utilize RequireJS dependencies, remember new modules to ``build.js``.
NOTE: The static file directories are setup such that the build output directory of ``r.js`` is read before checking
for assets in ``ecommerce\static\``. If you run ``make static`` or ``r.js`` locally (which you should not need to),
make sure you delete ``ecommerce/static/build`` or run ``make static`` before continuing with development. If you do not
all changes made to static files will be ignored.
Feature Toggling
================
All new features/functionality should be released behind a feature gate. This allows us to release
new features in a controlled manner and easily disable features in the event that an issue is discovered
in production. This project uses the `Waffle <http://waffle.readthedocs.org/en/latest/>`_ library
for feature gating.
Waffle supports three types of feature gates, listed below.
Flag
Enable a feature for specific users, groups, users meeting certain criteria (e.g. authenticated or staff),
or a certain percentage of visitors.
Switch
Simple boolean, toggling a feature for all users.
Sample
Toggle the feature for a specified percentage of the time.
For information on creating or updating features, refer to the
`Waffle documentation <http://waffle.readthedocs.org/en/latest/>`_.
Available Feature Gates
-----------------------
Waffle-based feature gates can be managed via the Django admin. The following feature gates exist:
============================= ====== ===============================================================================
Name Type Purpose
============================= ====== ===============================================================================
user_enrollments_on_dashboard Switch Display a user's current enrollments on the dashboard user detail page
publish_course_modes_to_lms Switch Publish prices and SKUs to the LMS after every course modification
async_order_fulfillment Sample Determines what percentage of orders are fulfilled asynchronously.
ENABLE_CREDIT_APP Switch Enable the credit checkout page, from which students can purchase credit course
ENABLE_NOTIFICATIONS Switch Enable email notifications for a variety of user actions (e.g., order placed)
PAYPAL_RETRY_ATTEMPTS Switch Enable retry mechanism for failed PayPal payment executions
============================= ====== ===============================================================================
Toggling Payment Processors
---------------------------
Payment processors sometimes experience temporary outages. When these outages occur, you can use Waffle switches to disable the faulty payment processor(s), then re-enable them after the outage is over.
The names of these switches are prefixed with the value of the setting ``PAYMENT_PROCESSOR_SWITCH_PREFIX``. By default, this value is ``payment_processor_active_``. The table below lists valid switches and the payment processors they control.
================= ==================================== =============
Payment Processor Switch Name Default Value
================= ==================================== =============
PayPal payment_processor_active_paypal True
CyberSource payment_processor_active_cybersource True
================= ==================================== =============
The LMS is equipped to deal with the unlikely event that all payment processors are disabled.
Business Intelligence (Analytics)
---------------------------------
We use `Segment <https://segment.com/>`_ to collect business intelligence data. Specify a value for ``SEGMENT_KEY`` in settings to emit events to the corresponding Segment project.
Permanent Feature Rollout
-------------------------
Over time some features may become permanent and no longer need a feature gate around them. In such instances, the
relevant code and tests should be updated to remove the feature gate. Once the code is released, the feature flag/switch
should be deleted.
======================
Order Fulfillment
======================
Since ``django-oscar`` doesn't offer a lot of specific functionality in this area, we have put together our own framework for handling fulfillment. Since all of our current products are digital, we need to be able to be able to correctly fulfill these orders in code.
---------------------
Fulfillment API
---------------------
In order to address this, we will be hooking into ``order.processing.EventHandler#handler_shipping_event()``, which will make calls to ``fulfillment_api.fulfill(order)``.
The Fulfillment API will then be responsible for delegating fulfillment of the individual order items to the appropriate Fulfillment Modules.
---------------------
Fulfillment Modules
---------------------
There will be a base fulfillment module that has the following interface::
fulfill_product(product)
revoke_product(product)
For each ``ProductType`` that we develop, there will be a corresponding module that will extend this interface and be responsible for fulfilling order items of that particular ``ProductType``. The mapping between each ``ProductType`` and the corresponding fulfillment module will be configured in ``settings.py`` as a simple dictionary.
``fulfill_product`` will fulfill the given product (i.e., enroll a student in a course, upgrade the student to a verified certificate).
``revoke_product`` will do the opposite (i.e., unenroll students from courses, downgrade people from veriied).
Both of these methods will return a JSON-serializable dictionary containing both the status and any important status notes.
For example, a success would return something like ``{'status': 'success'}`` and a failure would return something like ``{'status': 'failure', 'error_type': 'Connection Refused'}``.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Enrollment Fulfillment
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Most of the products that edX supports involve modifications to enrollments.
The modules that are responsible for fulfillment of enrollment-related products will interface with the `LMS-provided Enrollment API <http://edx-enrollment-api.readthedocs.org/>`_. This process will be synchronous.
------------------------------
Error Recovery in Fulfillment
------------------------------
For a variety of reasons, fulfillment of a product may fail. In order to handle these situations, we will record a status after payment has been received and before the order has been fulfilled. We can create a new ``Order Status`` via ``order.abstract_models.AbstractOrder`` to track this failed fulfillment attempt. A celery task -- or some other sort of queueing mechanism -- will be responsible for re-attempting to fulfill orders that failed to be fulfilled the first time around.
Getting Started
===============
If you have not already done so, create/activate a `virtualenv`_. Unless otherwise stated, assume all terminal code
below is executed within the virtualenv.
.. _virtualenv: https://virtualenvwrapper.readthedocs.org/en/latest/
Install dependencies
--------------------
Dependencies can be installed via the command below.
.. code-block:: bash
$ make requirements
Local/Private Settings
----------------------
When developing locally, it may be useful to have settings overrides that you do not wish to commit to the repository.
If you need such overrides, create a file :file:`ecommerce/settings/private.py`. This file's values are
read by :file:`ecommerce/settings/local.py`, but ignored by Git.
Configure edX OpenID Connect (OIDC)
-----------------------------------
This service relies on the edX OIDC (`OpenID Connect`_) authentication provider for login. Note that OIDC is built atop
OAuth 2.0, and this document may use the terms interchangeably. Under our current architecture the LMS serves as our
authentication provider.
Configuring E-Commerce Service to work with OIDC requires registering a new client with the authentication
provider and updating the Django settings for this project with the client credentials.
.. _OpenID Connect: http://openid.net/specs/openid-connect-core-1_0.html
A new OAuth 2.0 client can be created at ``http://127.0.0.1:8000/admin/oauth2/client/``.
1. Click the :guilabel:`Add client` button.
2. Leave the user field blank.
3. Specify the name of this service, ``E-Commerce Service``, as the client name.
4. Set the :guilabel:`URL` to the root path of this service: ``http://localhost:8002/``.
5. Set the :guilabel:`Redirect URL` to the OIDC client endpoint: ``https://localhost:8002/complete/edx-oidc/``.
6. Copy the :guilabel:`Client ID` and :guilabel:`Client Secret` values. They will be used later.
7. Select :guilabel:`Confidential (Web applications)` as the client type.
8. Click :guilabel:`Save`.
Your newly-created client must also be designated as trusted. Trusted clients bypass the user consent form typically displayed after validating the user's credentials. Create a new trusted client at ``http://127.0.0.1:8000/admin/oauth2_provider/trustedclient/add/``.
1. Select your newly-created client's redirect URL from the dropdown.
2. Click ``Save``.
Now that you have the client credentials, you can update your settings (ideally in
:file:`ecommerce/settings/local.py`). The table below describes the relevant settings.
+-----------------------------------------------------+----------------------------------------------------------------------------+--------------------------------------------------------------------------+
| Setting | Description | Value |
+=====================================================+============================================================================+==========================================================================+
| SOCIAL_AUTH_EDX_OIDC_KEY | OAuth 2.0 client key | (This should be set to the value generated when the client was created.) |
+-----------------------------------------------------+----------------------------------------------------------------------------+--------------------------------------------------------------------------+
| SOCIAL_AUTH_EDX_OIDC_SECRET | OAuth 2.0 client secret | (This should be set to the value generated when the client was created.) |
+-----------------------------------------------------+----------------------------------------------------------------------------+--------------------------------------------------------------------------+
| SOCIAL_AUTH_EDX_OIDC_URL_ROOT | OAuth 2.0 authentication URL | http://127.0.0.1:8000/oauth2 |
+-----------------------------------------------------+----------------------------------------------------------------------------+--------------------------------------------------------------------------+
| SOCIAL_AUTH_EDX_OIDC_ID_TOKEN_DECRYPTION_KEY | OIDC ID token decryption key. This value is used to validate the ID token. | (This should be the same value as SOCIAL_AUTH_EDX_OIDC_SECRET.) |
+-----------------------------------------------------+----------------------------------------------------------------------------+--------------------------------------------------------------------------+
Run migrations
--------------
Local installations use SQLite by default. If you choose to use another database backend, make sure you have updated
your settings and created the database (if necessary). Migrations can be run with `Django's migrate command`_.
.. code-block:: bash
$ make migrate
.. _Django's migrate command: https://docs.djangoproject.com/en/1.8/ref/django-admin/#django-admin-migrate
Run the server
--------------
The server can be run with `Django's runserver command`_. If you opt to run on a different port, make sure you update
OIDC client via LMS admin.
.. code-block:: bash
$ python manage.py runserver 8002
.. _Django's runserver command: https://docs.djangoproject.com/en/1.8/ref/django-admin/#runserver-port-or-address-port
Create a course mode with the course admin tool
-----------------------------------------------
If you're using `devstack`_, the ecommerce and edx-platform servers
already have the correct configuration defaults to communicate with
one another. To configure course modes for a course, do the following:
1. In the ecommerce and LMS configuration files (``/edx/etc/ecommerce.yml`` and
``/edx/app/edxapp/lms.auth.json``, respectively), verify the following:
* LMS's ``EDX_API_KEY`` should match ecommerce's ``EDX_API_KEY``
* LMS's ``ECOMMERCE_API_SIGNING_KEY`` should match ecommerce's ``JWT_SECRET_KEY``
If they don't match, you should update them so that they do.
2. On `devstack`_, bring up the ecommerce server on port 8002, and the LMS on port 8000.
3. On the ecommerce server, set up a `SiteConfiguration`_ in the django admin.
4. Head over to the courses page on the ecommerce server: http://localhost:8002/courses.
5. Click "Add New Course".
From there, you should be able to enter in the course id and desired course mode
for the course you'd like to configure.
.. _SiteConfiguration: http://open-edx-ecommerce-guide.readthedocs.org/en/latest/partner_config.html#site-configuration-model-django-admin
Development outside devstack
----------------------------
If you are using `devstack`_ for platform development, you may still wish to install and run this service on your host
operating system. One simple way to achieve this is setting up a reverse port-forward, such as the following:
.. code-block:: bash
$ vagrant ssh -- -R 8002:127.0.0.1:8002 # run on the vm host, not the guest.
This will allow your LMS process inside devstack to make calls to your ecommerce server running on the host, via
'127.0.0.1:8002', simplifying URL configuration in the LMS.
.. _devstack: https://github.com/edx/configuration/wiki/edX-Developer-Stack
......@@ -3,27 +3,7 @@
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Documentation for the edX E-Commerce Service
============================================
edX E-Commerce Service
======================
These are the developer docs for the edX E-Commerce Service.
.. toctree::
:maxdepth: 2
getting_started
asset_pipeline
testing
features
partner_config
fulfillment
coupons
notifications
internationalization
maintenance
TODO
- Oscar Dashboard
- Payment processors
- API
- Course Administration Tool
These docs have moved to the `Open edX Installing, Configuring, and Running (ICR) guide <http://edx.readthedocs.org/projects/edx-installing-configuring-and-running/en/latest/ecommerce/index.html>`_. To contribute, please open a PR against https://github.com/edx/edx-documentation.
Internationalization
====================
All user-facing text content should be marked for translation. Even if this application is only run in English, our
open source users may choose to use another language. Marking content for translation ensures our users have
this choice.
Follow the `internationalization coding guidelines`_ in the edX Developer's Guide when developing new features.
.. _internationalization coding guidelines: http://edx.readthedocs.org/projects/edx-developer-guide/en/latest/internationalization/i18n.html
Updating Translations
~~~~~~~~~~~~~~~~~~~~~
This project uses `Transifex`_ to translate content. After new features are developed the translation source files
should be pushed to Transifex. Our translation community will translate the content, after which we can retrieve the
translations.
.. _Transifex: https://www.transifex.com/
Pushing source translation files to Transifex requires access to the edx-platform. Request access from the Open Source
Team if you will be pushing translation files. You should also `configure the Transifex client`_ if you have not done so
already.
.. _configure the Transifex client: http://docs.transifex.com/client/config/
The `make` targets listed below can be used to push or pull translations.
.. list-table::
:widths: 25 75
:header-rows: 1
* - Target
- Description
* - pull_translations
- Pull translations from Transifex
* - push_translations
- Push source translation files to Transifex
Fake Translations
~~~~~~~~~~~~~~~~~
As you develop features it may be helpful to know which strings have been marked for translation, and which are not.
Use the `fake_translations` make target for this purpose. This target will extract all strings marked for translation,
generate fake translations in the Esperanto (eo) language directory, and compile the translations.
You can trigger the display of the translations by setting your browser's language to Esperanto (eo), and navigating to
a page on the site. Instead of plain English strings, you should see specially-accented English strings that look like this:
Thé Fütüré øf Ønlïné Édüçätïøn Ⱡσяєм ι# Før änýøné, änýwhéré, änýtïmé Ⱡσяєм #
Maintenance
===========
Most installations should not require any maintenance beyond patching; however, there are a few exceptions.
Baskets
~~~~~~~
As more baskets and orders are created, the baskets table can grow pretty large. Depending on your database backend, a
large table can become difficult to manage and migrate. Once an order is placed, the corresponding basket doesn't hold
much value and can be deleted. The `delete_ordered_baskets` management command performs this action.
.. code-block:: bash
# Display number of baskets eligible for deletion
$ ./manage.py delete_ordered_baskets
# Delete all baskets that have been ordered
$ ./manage.py delete_ordered_baskets --commit
Prior to our adding multi-tenancy support, baskets were not associated with a Site. If you have baskets in such a state
the `add_site_to_baskets` management command can be used to update them. The command requires that a Site ID be
specified with the `-s` option.
.. code-block:: bash
# Display number of baskets to be updated
$ ./manage.py add_site_to_baskets -s <site-id>
# Update baskets
$ ./manage.py add_site_to_baskets -s <site-id> --commit
Notifications
=============
We use Oscar's `Communications API <http://django-oscar.readthedocs.org/en/latest/howto/how_to_customise_oscar_communications.html#communications-api>`_ to create and send email notifications. If you've enabled the feature, you may define arbitrary "Communication Type Codes" used to refer to particular types of notification. For example, the Communication Type Code corresponding to the purchase of a course seat might be ``COURSE_SEAT_PURCHASED``.
Each email requires the presence of three files: an HTML template, a plain text file containing the email's subject line, and a plain text file containing the email's body. The files should be placed in ``ecommerce/ecommerce/templates/customer/emails/``. You should adhere to the following naming convention: ``commtype_{Communication Type Code}_body.html``. For example, an email related to the purchase of a course seat should have template file named ``commtype_course_seat_purchased_body.html``, ``commtype_course_seat_purchased_body.txt``, and ``commtype_course_seat_purchased_subject.txt``. The HTML template should extend ``email_base.html``. Override ``block body`` to add a custom email body and, optionally, ``block footer`` to add a custom footer.
To actually send emails, use the method ``send_notification(user, commtype_code, context)``, implemented in ``ecommerce/ecommerce/notifications/notifications.py``.
======================
Partner Configuration
======================
This additional configuration in the ``Partner`` model allows users to specify a short code that serves as a unique identifier for that partner.
This required configuration creates a new **Partner** object that will be used throughout the platform, such as in the ``SiteConfiguration`` model for specific theming.
---------------------------------------------
Partner Configuration Model | Django Admin
---------------------------------------------
``Partners`` can be created or modified in the Django administration site located at http://localhost:8002/admin/partner/partner/.
The following image shows the ``Partner`` model in the Django administration panel for a configured partner.
.. image:: _static/images/partner_configuration.png
:width: 600px
:alt: Populated partner model
.. note:: The **Short code** field must be unique across all partners. This value is presently used as the order number prefix (e.g. "EDX" in EDX-1000).
======================
Site Configuration
======================
This is a custom functionality since ``django-oscar`` doesn't offer this kind of configuration.
We have extended the `Django sites framework <https://docs.djangoproject.com/en/1.8/ref/contrib/sites/>`_ in order to add site-specific configuration.
The site's framework allows for the mapping of domains to a **Site** object which consists of an ID and a name.
The multi-tenant implementation has one site per partner.
---------------------------------------------
Site Configuration Model | Django Admin
---------------------------------------------
To add and update a custom site's configurations, including the basic theming and payment processor, use the ``SiteConfiguration`` model in the `Django administration panel <http://localhost:8002/admin/core/siteconfiguration/add>`_.
This panel is located at http://localhost:8002/admin/core/siteconfiguration/.
The following image shows the ``SiteConfiguration`` model in the Django administration panel for a configured site.
If you're running devstack, you can use the default ``example.com`` in the Site field,
and your LMS base should be ``localhost:8000``. The path to custom site theme field
cannot be left blank, but if you don't have one, you can provide dummy text.
.. image:: _static/images/site_configuration.png
:width: 600px
:alt: Populated site configuration model
.. note:: There is a **unique together** constraint on the **site** and **partner** fields for the ``SiteConfiguration`` model.
This means that there can be only one entry per site per partner.
Please make sure that there is only one partner per site.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment