Update documentation

pull/211/head
JamesRamm 2018-12-31 16:09:12 +01:00
rodzic f71948b9cd
commit 3741dc5234
24 zmienionych plików z 369 dodań i 422 usunięć

Wyświetl plik

@ -14,7 +14,7 @@ Checkout the [demo site](https://github.com/JamesRamm/longclaw_demo) and [docume
<a href="https://www.buymeacoffee.com/pHtXDM748" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: auto !important;width: auto !important;" ></a>
![Image of the dashboard](docs/images/dashboard.png)
![Image of the dashboard](docs/assets/dashboard.png)
## Quickstart
@ -42,7 +42,7 @@ Setup a Longclaw project
### Screenshots
![Order Detail](docs/images/order_detail.png)
![Order Detail](docs/assets/order_detail.png)
## Support

Wyświetl plik

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 90 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 90 KiB

Wyświetl plik

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 69 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 69 KiB

Wyświetl plik

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 58 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 58 KiB

Wyświetl plik

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 99 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 99 KiB

Wyświetl plik

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 108 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 108 KiB

Wyświetl plik

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 56 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 56 KiB

Wyświetl plik

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 76 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 76 KiB

Wyświetl plik

Przed

Szerokość:  |  Wysokość:  |  Rozmiar: 73 KiB

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 73 KiB

Wyświetl plik

@ -1,7 +0,0 @@
---
id: doc2
title: document number 2
---
This is a link to [another document.](doc3.md)
This is a link to an [external page.](http://www.example.com)

Wyświetl plik

@ -1,13 +0,0 @@
---
id: doc3
title: This is document number 3
---
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In ac euismod odio, eu consequat dui. Nullam molestie consectetur risus id imperdiet. Proin sodales ornare turpis, non mollis massa ultricies id. Nam at nibh scelerisque, feugiat ante non, dapibus tortor. Vivamus volutpat diam quis tellus elementum bibendum. Praesent semper gravida velit quis aliquam. Etiam in cursus neque. Nam lectus ligula, malesuada et mauris a, bibendum faucibus mi. Phasellus ut interdum felis. Phasellus in odio pulvinar, porttitor urna eget, fringilla lectus. Aliquam sollicitudin est eros. Mauris consectetur quam vitae mauris interdum hendrerit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Duis et egestas libero, imperdiet faucibus ipsum. Sed posuere eget urna vel feugiat. Vivamus a arcu sagittis, fermentum urna dapibus, congue lectus. Fusce vulputate porttitor nisl, ac cursus elit volutpat vitae. Nullam vitae ipsum egestas, convallis quam non, porta nibh. Morbi gravida erat nec neque bibendum, eu pellentesque velit posuere. Fusce aliquam erat eu massa eleifend tristique.
Sed consequat sollicitudin ipsum eget tempus. Integer a aliquet velit. In justo nibh, pellentesque non suscipit eget, gravida vel lacus. Donec odio ante, malesuada in massa quis, pharetra tristique ligula. Donec eros est, tristique eget finibus quis, semper non nisl. Vivamus et elit nec enim ornare placerat. Sed posuere odio a elit cursus sagittis.
Phasellus feugiat purus eu tortor ultrices finibus. Ut libero nibh, lobortis et libero nec, dapibus posuere eros. Sed sagittis euismod justo at consectetur. Nulla finibus libero placerat, cursus sapien at, eleifend ligula. Vivamus elit nisl, hendrerit ac nibh eu, ultrices tempus dui. Nam tellus neque, commodo non rhoncus eu, gravida in risus. Nullam id iaculis tortor.
Nullam at odio in sem varius tempor sit amet vel lorem. Etiam eu hendrerit nisl. Fusce nibh mauris, vulputate sit amet ex vitae, congue rhoncus nisl. Sed eget tellus purus. Nullam tempus commodo erat ut tristique. Cras accumsan massa sit amet justo consequat eleifend. Integer scelerisque vitae tellus id consectetur.

Wyświetl plik

@ -1,6 +0,0 @@
---
id: doc4
title: Other Document
---
this is another document

Wyświetl plik

@ -1,6 +0,0 @@
---
id: doc5
title: Fifth Document
---
Another one

Wyświetl plik

@ -3,91 +3,96 @@ title: API Client
sidebar_label: API Client
---
Using the API client
=====================
Longclaw comes with a handy API javascript client to simplify making HTTP requests.
To load the client into your HTML templates, you can use the template tags:
.. code-block:: django
```django
{% load longclawcore_tags %}
{% longclaw_vendors_bundle %}
{% longclaw_client_bundle %}
```
This will render the ``<script>`` tags necessary to load the javascript. The api client
will be available as a global object called ``longclawclient``.
You can access the methods by calling the request name (e.g. ``basketList``) and the desired method::
This will render the `<script>` tags necessary to load the javascript. The api client
will be available as a global object called `longclawclient`.
You can access the methods by calling the request name (e.g. `basketList`) and the desired method::
longclawclient.basketList.get({ ... })
longclawclient.basketList.post({ ... })
API Reference
-------------
## API Reference
:orderDetail:
supports GET methods. Requires an ``id`` url parameter
``longclawclient.orderDetail.get({ urlParams: { id: ... } })``
:fulfillOrder:
supports POST methods. Requires an ``id`` url param.
``longclawclient.fulfillOrder.post({ urlParams: { id: ... } })``
:checkout:
supports POST method. requires JSON data.
``longclawclient.checkout.post({ data: { ... } })``
:checkoutToken:
supports GET method.
:basketList:
supports GET and POST methods
:basketListCount:
supports GET methods
:basketDetailCount:
supports GET method. Requires ``id`` url param.
:basketDetail:
supports DEL method. Requires ``id`` url param.
:shippingCost:
supports GET method. requires ``country_code`` query param
``longclawclient.shippingCost.get({ queryParams: { country_code: 'gb' } })``
:shippingCountries:
supports GET method
:addressList:
supports GET and POST methods
:addressDetail:
supports GET, PUT, DEL methods
### orderDetail
supports GET methods. Requires an `id` url parameter
`longclawclient.orderDetail.get({ urlParams: { id: ... } })`
All methods take a ``config`` object of options which can optionally contain:
### fulfillOrder
supports POST methods. Requires an `id` url param.
`longclawclient.fulfillOrder.post({ urlParams: { id: ... } })`
:config.url: - Completely override the URL to use
:config.prefix: - Use a different prefix or host for calling the endpoint.
:config.urlParams: - replacement parameters for the endpoint.
for example, if the endpoint is specified as `booking/{id}/`, urlParams should
be an object containing an `id` key and the string to replace it with, e.g:
{ id: '123' } would result in the endpoint being modified to `booking/123/`
### checkout
supports POST method. requires JSON data.
`longclawclient.checkout.post({ data: { ... } })`
:config.queryParams: - An object containing key-value pairs which
will be mapped to a query string. E.g.
{
first_name: 'John',
last_name: 'Smith'
}
would result in the endpoint being modified to `booking/123/?first_name=John&last_name=Smith`
### checkoutToken
supports GET method.
:config.data: - Data object to send with the POST/PUT request. Will be converted to JSON.
### basketList
supports GET and POST methods
It is important to note the ``config.prefix`` option. You will almost always need to specify this
to match the ``API_URL_PREFIX`` setting in your django settings. This can be done by including it in
your template view as e.g. a data attribute on a element and then accessing it through the ``dataset``
attribute in javascript, e.g.::
### basketListCount
supports GET methods
### basketDetailCount
supports GET method. Requires `id` url param.
### basketDetail
supports DEL method. Requires `id` url param.
### shippingCost
supports GET method. requires `country_code` query param
`longclawclient.shippingCost.get({ queryParams: { country_code: 'gb' } })`
### shippingCountries
supports GET method
### addressList
supports GET and POST methods
### addressDetail
supports GET, PUT, DEL methods
All methods take a `config` object of options which can optionally contain:
| Parameter | Description
|:-----------:|----------------
| url | Completely override the URL to use
| prefix | Use a different prefix or host for calling the endpoint.
| urlParams | replacement parameters for the endpoint. for example, if the endpoint is specified as `booking/{id}/`, urlParams should be an object containing an `id` key and the string to replace it with, e.g: `{ id: '123' }` would result in the endpoint being modified to `booking/123/`
| queryParams | An object containing key-value pairs which will be mapped to a query string. E.g. `{ first_name: 'John', last_name: 'Smith' }` would result in the endpoint being modified to `booking/123/?first_name=John&last_name=Smith`
| data | Data object to send with the POST/PUT request. Will be converted to JSON.
It is important to note the `config.prefix` option. You will almost always need to specify this
to match the `API_URL_PREFIX` setting in your django settings. This can be done by including it in
your template view as e.g. a data attribute on a element and then accessing it through the `dataset`
attribute in javascript, e.g:
```javascript
document.getElementById('my-element').dataset.apiUrlPrefix
```
Usage with ES6 modules
----------------------
To use the client with other ES6+ modules, install the client library from npm::
### Usage with ES6 modules
To use the client with other ES6+ modules, install the client library from npm:
```bash
npm i longclawclient --save
Then import the api library::
import api from 'longclawclient'
```
Then import the api library:
```bash
import api from 'longclawclient'
```

Wyświetl plik

@ -3,27 +3,26 @@ title: Basket
sidebar_label: Basket
---
The basket (or 'shopping cart') is a collection of ``BasketItem`` objects, tied to the django session and as such, expires when the session expires.
The basket (or 'shopping cart') is a collection of `BasketItem` objects, tied to the django session and as such, expires when the session expires.
Each ``BasketItem`` has a ``basket_id`` allowing items to be grouped together in a 'basket'.
Each `BasketItem` has a `basket_id` allowing items to be grouped together in a 'basket'.
Fetching the basket
-------------------
## Fetching the basket
The function ``longclaw.basket.utils.get_basket_items`` will return all ``BasketItem`` for the current
session. This accepts a django ``request`` object and uses ``longclaw.basket.utils.basket_id`` to
fetch the underlying ``basket_id`` on which to filter the ``BasketItem`` objects.
On the front end, you can use the API endpoint ``<api_prefix>/basket/`` or the django view ``basket/``. You should
provide a template for the view title ``basket.html``. ``basket`` is also the name of the context variable
The function `longclaw.basket.utils.get_basket_items` will return all `BasketItem` for the current
session. This accepts a django `request` object and uses `longclaw.basket.utils.basket_id` to
fetch the underlying `basket_id` on which to filter the `BasketItem` objects.
On the front end, you can use the API endpoint `<api_prefix>/basket/` or the django view `basket/`. You should
provide a template for the view title `basket.html`. `basket` is also the name of the context variable
containing all basket items.
A ``BasketItem`` has two fields of importance; ``quantity`` and ``variant``. The latter is a foreign key to the
``ProductVariant`` model.
A `BasketItem` has two fields of importance; `quantity` and `variant`. The latter is a foreign key to the
`ProductVariant` model.
In a django template, you can iterate over the basket items like so:
.. code-block:: django
```javascript
{% for item in basket %}
{{ item.quantity }}
{{ item.variant.price }}
@ -32,10 +31,10 @@ In a django template, you can iterate over the basket items like so:
{{ item.variant.product.title }}
{{ item.variant.product.description }}
{% endfor %}
```
The API JSON response will contain all fields of the `ProductVariant` and `Product`:
The API JSON response will contain all fields of the ``ProductVariant`` and ``Product``:
.. code-block:: json
```javascript
{
quantity,
@ -51,31 +50,31 @@ The API JSON response will contain all fields of the ``ProductVariant`` and ``Pr
}
}
}
```
## Adding and Removing items
Adding and Removing items
-------------------------
Items can be added or removed via the RESTful api:
POST to ``<api_prefix>/basket/`` to add an item and DELETE to ``<api_prefix>/basket/<variant_id>/`` to remove an item
POST to `<api_prefix>/basket/` to add an item and DELETE to `<api_prefix>/basket/<variant_id>/` to remove an item
When adding an item, provide the ``variant_id`` in the request data. For both endpoints, you can optionally provide the ``quantity`` in
When adding an item, provide the `variant_id` in the request data. For both endpoints, you can optionally provide the `quantity` in
the request data.
There is currently no django view for addition/deletion of basket items.
Other API endpoints:
## Other API Endpoints
``<api_prefix>/basket/<variant_id>/count/``
get the quantity of a single item in the basket. Requires ``variant_id`` in the request data
### `basket/:variant_id/count/`
get the quantity of a single item in the basket. Requires `variant_id` in the request data
``<api_prefix>/basket/count/``
### `basket/count/`
get total number of items in the basket
All basket items can be deleted using the ``longclaw.basket.utils.destroy_basket`` function.
All basket items can be deleted using the `longclaw.basket.utils.destroy_basket` function.
When an order is successfully placed, the basket will be automatically destroyed.
.. note:: Longclaw does not automatically clean up abandoned baskets. This can occur when a session ends
with items still in the basket (i.e the customer did not place an order). This allows you to provide checkout recovery,
with the caveat that you will need to do your own cleanup of rogue ``BasketItem`` objects when required.
> Longclaw does not automatically clean up abandoned baskets. This can occur when a session ends
with items still in the basket (i.e the customer did not place an order). This allows you to provide checkout recovery,
with the caveat that you will need to do your own cleanup of rogue `BasketItem` objects when required.

Wyświetl plik

@ -4,37 +4,37 @@ sidebar_label: Checkout
---
Longclaw provides a simple, single checkout view.
The URL for the checkout is ``'checkout/'``.
After a successful checkout, it is redirected to ``checkout/success/``.
The URL for the checkout is `'checkout/'`.
After a successful checkout, it is redirected to `checkout/success/`.
To implement the checkout, simply provide ``'checkout/checkout.html'`` and
``'checkout/success.html'`` templates. (Empty templates will have been created if
To implement the checkout, simply provide `'checkout/checkout.html'` and
`'checkout/success.html'` templates. (Empty templates will have been created if
you ran the longclaw CLI to start your project)
There are three forms provided in the checkout view:
:checkout_form:
### checkout_form
Captures the email address and optionally the shipping option for the checkout.
Also captures a boolean indicating whether a different billing address should be used
:shipping_form:
### shipping_form
Captures shipping information.
:billing_form:
### billing_form
A second address form for capturing alternate billing information. If you do not submit this form
(e.g. by not rendering it on the template), the billing and shipping addresses are assumed to be the same.
Generally, you may need to use a little javascript to optionally render the form if the user selects
'different billing address'.
Shipping Options and Javascript
--------------------------------
## Shipping Options and Javascript
The shipping option dropdown has no options by default - this is because it is dependent on the shipping country.
The checkout form includes the necessary javascript to do this - you just need to include it on the page.
You will typically also need to include your chosen payment gateways' client javascript:
..code-block:: django
```django
{% gateway_client_js as scripts %}
{% for js in scripts %}
@ -46,31 +46,31 @@ You will typically also need to include your chosen payment gateways' client jav
<script type="text/javascript">
initShippingOption('{% longclaw_api_url_prefix %}');
</script>
```
The first half uses the ``gateway_client_js`` template tag to load all the payment gateway javascript. There may be one or more.
The first half uses the `gateway_client_js` template tag to load all the payment gateway javascript. There may be one or more.
The second half has three parts to it:
1. ``{% longclaw_client_bundle %}`` loads the longclaw client API, which is required by the checkout form javascript.
2. ``{{ checkout_form.media }}`` loads the javascript required by the checkout form.
1. `{% longclaw_client_bundle %}` loads the longclaw client API, which is required by the checkout form javascript.
2. `{{ checkout_form.media }}` loads the javascript required by the checkout form.
3. The last script initializes the checkout javascript. It requires the longclaw API url prefix (which you can customise in your settings)
to be passed in - there is a template tag to do this for you. You can also optionally specify the ``shippingCountrySelectId`` and ``shippingOptionSelectId``.
to be passed in - there is a template tag to do this for you. You can also optionally specify the `shippingCountrySelectId` and `shippingOptionSelectId`.
These are the ID's of the select element. You would only need to pass these in if you are going to change them from the defaults.
After this, when you change the shipping country, the shipping option should change appropriately.
..note:: We will hopefully improve this in future releases - any ideas and PR's are welcome!
> We will hopefully improve this in future releases - any ideas and PR's are welcome!
Payment forms
-------------
## Payment forms
It is up to you to render a payment form and then pass the token in the POST data.
Normally, the payment gateway chosen will have a javascript integration to render a form for you
and tokenize the payment method (e.g. braintrees 'hosted fields')
Longclaws' payment gateways provide some helpful utilities to load client javascript and generate tokens.
Loading ``longclawcheckout_tags`` in your template will allow you to retrieve the gateways' javascript libraries
as script tags (``{% gateway_client_js %}`` and generate a client token (``{% gateway_token %}``).
Loading `longclawcheckout_tags` in your template will allow you to retrieve the gateways' javascript libraries
as script tags (`{% gateway_client_js %}` and generate a client token (`{% gateway_token %}`).
A little javascript is then required to setup your form and ask the gateway to tokenize the payment method for you.
You should then add this token to the request POST data (e.g. with a hidden input field).

Wyświetl plik

@ -15,8 +15,8 @@ In the front end, you should:
The first two are relatively simple to achieve. Longclaw provides some utilities to help with the rest.
Payment Capture
===============
## Payment Capture
With Longclaw you can either tokenize the customers payment method (e.g. credit card) and
send this to the server for the payment to be captured, or you can use a service such as paypal
express checkout, which captures the payment directly and returns a token representing the transaction
@ -27,111 +27,106 @@ The second option is often easiest to integrate since the user is redirected to
The first option offers tightest integration with the look and feel of your site, but invariable involves more
front end work and validation.
Tokenizing the Payment
+++++++++++++++++++++++
### Tokenizing the Payment
To capture the payment with a 3rd party service, you will include some external javascript on your page
and often designate a button or ``div`` to initialise the popup/redirect. You will also specify a submit
and often designate a button or `div` to initialise the popup/redirect. You will also specify a submit
handler to receive the token representing the transaction.
For example, the braintree javascript client allows express checkout using Paypal. Full details of how
to setup are `here <https://developers.braintreepayments.com/guides/paypal/checkout-with-paypal/javascript/v3>`_.
to setup are [here](https://developers.braintreepayments.com/guides/paypal/checkout-with-paypal/javascript/v3).
Other providers such as Stripe offer similar services.
Once you have received this token, you should submit it, along with the shipping address, billing address,
email and shipping rate to the ``api/checkout/prepaid/`` endpoint.
email and shipping rate to the `api/checkout/prepaid/` endpoint.
.. note:: The ``api/`` prefix can be configured in your django settings under ``API_URL_PREFIX``.
For example, if you want to distinguish the longclaw API from your own, you could set ``API_URL_PREFIX="api/longclaw/"``
The checkout url would then be ``api/longclaw/checkout/prepaid/``
> The `api/` prefix can be configured in your django settings under `API_URL_PREFIX`.
For example, if you want to distinguish the longclaw API from your own, you could set `API_URL_PREFIX="api/longclaw/"`
The checkout url would then be `api/longclaw/checkout/prepaid/`
The JSON request data would look like:
.. code-block:: json
```json
{
transaction_id: "...",
shipping_rate: 0.0,
email: "john@smith.com",
address: {
shipping_name: "john smith",
shipping_address_line_1": "...",
shipping_address_city: "",
shipping_address_zip: "",
shipping_address_country: "",
billing_name: "john smith",
billing_address_line_1: "...",
billing_address_city: "",
billing_address_zip: "",
billing_address_country: "",
"transaction_id": "...",
"shipping_rate": 0.0,
"email": "john@smith.com",
"address": {
"shipping_name": "john smith",
"shipping_address_line_1": "...",
"shipping_address_city": "",
"shipping_address_zip": "",
"shipping_address_country": "",
"billing_name": "john smith",
"billing_address_line_1": "...",
"billing_address_city": "",
"billing_address_zip": "",
"billing_address_country": "",
}
}
```
`transaction_id` is the token returned from the payment processor e.g. paypal
transaction_id
The token returned from e.g. paypal
When using this method, you do not need to define the `PAYMENT_GATEWAY` setting.
When using this method, you do not need to define the ``PAYMENT_GATEWAY`` setting.
Tokenizing the Payment method
+++++++++++++++++++++++++++++
### Tokenizing the Payment method
Alternatively, you can pass the payment method for Longclaw to manually capture the payment.
Longclaw expects the payment details (i.e. credit card) to be passed as some kind of token in
a POST request to ``api/checkout/``.
Longclaw will then use the payment gateway defined by the ``PAYMENT_GATEWAY`` setting to capture
a POST request to `api/checkout/`.
Longclaw will then use the payment gateway defined by the `PAYMENT_GATEWAY` setting to capture
the payment.
To create the initial token representing the customers payment information, you may be able to use
the ``api/checkout/token/`` endpoint, passing the card information in the request data. This is dependent
the `api/checkout/token/` endpoint, passing the card information in the request data. This is dependent
upon the backend and it may be preferable to use client javascript libraries provided by your payment
gateway (e.g. ``stripe.js`` or ``braintree-web`` ) to generate a token.
gateway (e.g. `stripe.js` or `braintree-web` ) to generate a token.
Once the token is generated, the request data to send to ``api/checkout/`` is very similar to that for
``api/checkout/prepaid/``:
Once the token is generated, the request data to send to `api/checkout/` is very similar to that for
`api/checkout/prepaid/`:
.. code-block:: json
```json
{
token: "...",
shipping_rate: 0.0,
email: "john@smith.com",
address: {
shipping_name: "john smith",
shipping_address_line_1: "...",
shipping_address_city: "",
shipping_address_zip: "",
shipping_address_country: "",
billing_name: "john smith",
billing_address_line_1: "...",
billing_address_city: "",
billing_address_zip: "",
billing_address_country: "",
"token": "...",
"shipping_rate": 0.0,
"email": "john@smith.com",
"address": {
"shipping_name": "john smith",
"shipping_address_line_1": "...",
"shipping_address_city": "",
"shipping_address_zip": "",
"shipping_address_country": "",
"billing_name": "john smith",
"billing_address_line_1": "...",
"billing_address_city": "",
"billing_address_zip": "",
"billing_address_country": "",
}
}
```
token
The token for customer details. The key name is dependent on the backend ("token" for stripe, "payment_method_nonce" for braintree)
| Parameter | Description
|:-------------:|------------------
| token | The token for customer details. The key name is dependent on the backend ("token" for stripe, "payment_method_nonce" for braintree)
| shipping_rate | Number or string representation of a number (will be cast to float). The shipping costs
| email | The customers' email
shipping_rate
Number or string representation of a number (will be cast to float). The shipping costs
> The `"token"` key is dependent upon the payment backend and may be named differently.
email
The customers' email
Both `api/checkout/` and `api/checkout/prepaid/` return a 201 response with `order_id` in the JSON data.
If the payment fails, `api/checkout/` will return a 400 response with `order_id` and `message` in the JSON data.
.. note:: The ``"token"`` key is dependent upon the payment backend and may be named differently.
## Calculating Shipping Costs
Both ``api/checkout/`` and ``api/checkout/prepaid/`` return a 201 response with ``order_id`` in the JSON data.
If the payment fails, ``api/checkout/`` will return a 400 response with ``order_id`` and ``message`` in the JSON data.
Calculating Shipping Costs
==========================
You will have noticed the need to send ``shipping_rate`` with the checkout. If you are using Longclaws' shipping
settings, you can easily calculate the shipping cost either in python or by using the ``api/shipping/cost/`` endpoint.
You will have noticed the need to send `shipping_rate` with the checkout. If you are using Longclaws' shipping
settings, you can easily calculate the shipping cost either in python or by using the `api/shipping/cost/` endpoint.
Python example:
.. code-block:: python
```python
from longclaw.shipping import utils
from longclaw.configuration.models import Configuration
@ -148,12 +143,13 @@ Python example:
# but the supplied option doesnt match any
pass
except InvalidShippingCountry:
# A shipping rate for this country does not exist and ``default_shipping_enabled``
# is set to ``False`` in the longclaw admin settings
# A shipping rate for this country does not exist and `default_shipping_enabled`
# is set to `False` in the longclaw admin settings
```
Javascript example:
.. code-block:: javascript
```javascript
fetch(
"api/shipping/cost/",
@ -170,7 +166,4 @@ Javascript example:
})
}
).then(response => {...})
```

Wyświetl plik

@ -4,36 +4,36 @@ sidebar_label: Product Requests
---
This module allows customers to 'request' products which are otherwise out of stock.
The request date and product variant are stored, with the customer email optionally being stored (The ``ProductRequest`` model
The request date and product variant are stored, with the customer email optionally being stored (The `ProductRequest` model
contains a field for this, but template tags by default do not collect this information - it is up to you to store it.)
To install, add it to your ``INSTALLED_APPS`` after other longclaw modules:
To install, add it to your `INSTALLED_APPS` after other longclaw modules:
.. code-block:: python
```python
INSTALLED_APPS = (
...,
"longclaw.contrib.productrequests"
)
```
To show a 'request' button, you can use the following template tag on your product page:
.. code-block:: django
```django
{% load productrequests_tags %}
{% for variant in page.variants.all %}
{% make_request_btn variant_id=variant.id %}
{% endfor %}
```
You can also pass ``btn_class`` and ``btn_text`` to change the CSS class and text of the resulting ``button`` element.
By default they are ``btn btn-default`` and ``Request Product``.
You can also pass `btn_class` and `btn_text` to change the CSS class and text of the resulting `button` element.
By default they are `btn btn-default` and `Request Product`.
This template tag will take care of making the AJAX call to register a request against the product variant.
In order to collect further information - i.e the customer email, you will need to create the button and necessary javascript
yourself. You can use the API client function ``requestList`` to post the collected data.
yourself. You can use the API client function `requestList` to post the collected data.
You can view all requests in the admin index page for your product collections. When hovering over a product, alongside
the usual `Edit`, `View Live` and `Add Child Page` buttons is a new `View Requests` button. This will take you to a page

Wyświetl plik

@ -3,60 +3,52 @@ title: Payment Backends
sidebar_label: Integrations
---
Payment Backends
==================
Longclaw supports payment capture through Stripe, Braintree and Paypal (Using the Braintree VZero SDK).
To select the payment gateway to use, you must specify the ``PAYMENT_GATEWAY`` attribute in your ``settings.py``.
To select the payment gateway to use, you must specify the `PAYMENT_GATEWAY` attribute in your `settings.py`.
The options are:
- ``longclaw.checkout.gateways.base.BasePayment``. A do-nothing base implementation
- ``longclaw.checkout.gateways.stripe.StripePayment``. Capture payments using Stripe.
- ``longclaw.checkout.gateways.braintree.BraintreePayment``. Capture payments using Braintree.
- ``longclaw.checkout.gateways.braintree.PaypalVZeroPayment``. Capture Paypal payments using the braintree v.zero SDK.
- `longclaw.checkout.gateways.base.BasePayment`. A do-nothing base implementation
- `longclaw.checkout.gateways.stripe.StripePayment`. Capture payments using Stripe.
- `longclaw.checkout.gateways.braintree.BraintreePayment`. Capture payments using Braintree.
- `longclaw.checkout.gateways.braintree.PaypalVZeroPayment`. Capture Paypal payments using the braintree v.zero SDK.
Additional Settings and dependencies
------------------------------------
## Additional Settings and dependencies
To use payment gateways it is necessary to specify API keys and install client SDK's for the chosen payment provider.
:Stripe:
``STRIPE_PUBLISHABLE`` - Your public api key
``STRIPE_SECRET`` - Your secret api key
You will need to install the stripe python sdk (``pip install stripe``)
## Stripe
`STRIPE_PUBLISHABLE` - Your public api key
`STRIPE_SECRET` - Your secret api key
You will need to install the stripe python sdk (`pip install stripe`)
:Braintree:
``BRAINTREE_MERCHANT_ID`` - Your braintree merchant account ID.
``BRAINTREE_PUBLIC_KEY`` - Your public api key
``BRAINTREE_PRIVATE_KEY`` - Your secret api key
## Braintree
`BRAINTREE_MERCHANT_ID` - Your braintree merchant account ID.
`BRAINTREE_PUBLIC_KEY` - Your public api key
`BRAINTREE_PRIVATE_KEY` - Your secret api key
:Paypal:
``VZERO_ACCESS_TOKEN`` - Your access token for the v.zero SDK.
## Paypal
`VZERO_ACCESS_TOKEN` - Your access token for the v.zero SDK.
Paypal and braintree require the braintree python SDK (``pip install braintree``)
Paypal and braintree require the braintree python SDK (`pip install braintree`)
.. _custom-integrations:
Custom Integrations
===================
## Custom Integrations
To implement your own payment integration, you must implement the payment gateway interface. This is simple:
- Inherit from ``longclaw.checkout.gateways.base.BasePayment``
- Implement ``create_payment``. This should take a ``request`` object, an ``amount`` and optionally a ``description``.
- Inherit from `longclaw.checkout.gateways.base.BasePayment`
- Implement `create_payment`. This should take a `request` object, an `amount` and optionally a `description`.
It should use these to capture the payment using your chosen provider. For examples see the implementations in
``longclaw.checkout.gateways``
- Implement the ``get_token`` method. This method should generate tokens used by the payment provider. It accepts a ``request``
object containing post data (``request.data``). Tokens returned may represent different things depending on the
`longclaw.checkout.gateways`
- Implement the `get_token` method. This method should generate tokens used by the payment provider. It accepts a `request`
object containing post data (`request.data`). Tokens returned may represent different things depending on the
payment provider - e.g. it may be used to tokenize payment details or generate authentication tokens.
You can define your own requirements for the request data to be submitted to the functions.
``create_payment`` is called in a POST request to the ``checkout/`` api. ``get_token`` is similarly called
in a POST request to the ``checkout/token/`` api.
`create_payment` is called in a POST request to the `checkout/` api. `get_token` is similarly called
in a POST request to the `checkout/token/` api.
Longclaw aims to be as minimal as possible in order to get the job done. This is why longclaw currently only offers the barest minimum
support necessary to directly create payments with the backend payment provider.

Wyświetl plik

@ -3,59 +3,55 @@ title: Configuring Payment
sidebar_label: Payment
---
Checkout with Braintree
============================
Longclaw offers integration with a few payment gateways and it is also fairly easy to integrate your own.
For this tutorial, we will use Braintree to process payments.
Settings and Dependencies
-------------------------
## Settings and Dependencies
The payment gateway to use must be set in the settings file:
.. code-block:: python
PAYMENT_GATEWAY = 'longclaw.checkout.gateways.braintree.BraintreePayment'
```python
PAYMENT_GATEWAY = 'longclaw.checkout.gateways.braintree.BraintreePayment'
```
We also need to define settings for access tokens;
.. code-block:: python
```python
BRAINTREE_SANDBOX = False
BRAINTREE_MERCHANT_ID = os.environ['BRAINTREE_MERCHANT_ID']
BRAINTREE_PUBLIC_KEY = os.environ['BRAINTREE_PUBLIC_KEY']
BRAINTREE_PRIVATE_KEY = os.environ['BRAINTREE_PRIVATE_KEY']
```
We will need to install this SDK as it is not an explicit dependency of longclaw::
We will need to install this SDK as it is not an explicit dependency of longclaw:
pip install braintree
```bash
pip install braintree
```
That is all we need to do to configure our backend!
Front end integration
---------------------
## Front end integration
We will first show how to setup a checkout page using the Checkout view provided by longclaw.
The code shown here is very similar to the implementation of the checkout page here: `Ramshackle Audio<https://github.com/JamesRamm/ramshacklerecording>`_
The code shown here is very similar to the implementation of the checkout page here: [Ramshackle Audio](https://github.com/JamesRamm/ramshacklerecording)
First, we should load some templatetags which will help us:
.. code-block:: django
```django
{% load longclawcheckout_tags longclawcore_tags %}
```
{% load longclawcheckout_tags longclawcore_tags %}
As an aside - you may wish to display the items in the basket on our checkout page. The basket items queryset is available as ``basket``
As an aside - you may wish to display the items in the basket on our checkout page. The basket items queryset is available as `basket`
in the views' context.
Next, we need to setup the forms to gather customer information. There are 2 forms in the context. We will
display and submit them as a single form. Here is an example layout:
.. code-block:: django
<form action="." method="post" id="checkout-form">
```django
<form action="." method="post" id="checkout-form">
{% csrf_token %}
{% for field in shipping_form %}
{% if field.is_hidden %}
@ -96,20 +92,21 @@ display and submit them as a single form. Here is an example layout:
</div>
{% endif %}
{% endfor %}
```
You may wish to layout the form differently. We have purposefully ignored the ``different_billing_address`` field
You may wish to layout the form differently. We have purposefully ignored the `different_billing_address` field
since the Braintree dropin-ui will collect a billing postcode anyway, for its' own security checks.
Before we close our `<form>` element, there are 3 further items to add:
.. code-block:: django
<!-- hidden field for submitting the token back to the server. Name will vary depending on integration-->
<input type="hidden" id="payment_method_nonce" name="payment_method_nonce"></input>
<h4 class="ui dividing header">Payment Details</h4>
<div id="dropin-container"></div>
<input type="submit" id="submit-button" value="Place Order" class="ui button submit" />
</form>
```django
<!-- hidden field for submitting the token back to the server. Name will vary depending on integration-->
<input type="hidden" id="payment_method_nonce" name="payment_method_nonce"></input>
<h4 class="ui dividing header">Payment Details</h4>
<div id="dropin-container"></div>
<input type="submit" id="submit-button" value="Place Order" class="ui button submit" />
</form>
```
We add a hidden field. This field will contain a token (string of characters) given by braintree which represents the payment method.
Most payment gateways require something like this, although the name of the field will change between backends.
@ -120,16 +117,14 @@ most integrations offer some sort of 'dropin' which are increasingly customisabl
Finally, we add a submit button.
The Javascript
***************
### The Javascript
OK, so now we have hidden elements, empty containers....we need to get this stuff populated!
Each payment gateway integration provides the necessary javascript libraries to interact with the gateway.
They are made available via a template tag.
Add them like this:
.. code-block:: django
```django
<!--Load any client javascript provided by the payment gateway.
I have chosen braintree as my gateway so the template tag below
should give me a list of script tags which load the braintree
@ -142,13 +137,13 @@ Add them like this:
<!--Finally add the media from the checkout form.-->
{{ checkout_form.media }}
```
The checkout form also provides a little javascript to initialise shipping options (when the user selects a shipping country).
Finally, we need to add a little of our own javascript to create the braintree dropin:
.. code-block:: django
```django
<script type="text/javascript">
//Initialize shipping options - this function is from the
@ -183,12 +178,13 @@ Finally, we need to add a little of our own javascript to create the braintree d
});
});
</script>
```
Two things are happening in the above code. First, we initialise the shipping options. Note we are using a template tag
to pass the longclaw API url prefix, since this is customisable in your settings.py
Secondly, we initialise the braintree dropin. Again, we use a template tag to get a token for the gateway.
All payment backends provide the ``gateway_token`` template tag, although it is not always necessary.
All payment backends provide the `gateway_token` template tag, although it is not always necessary.
You may wish to only show the braintree payment form if the user has anything in their basket. In which case you might qualify
the above javascript with ``{% if basket.count > 0 %}`` in your template.
@ -199,8 +195,8 @@ for v0.2, but welcome any suggestions on how to make it easier!
If you wish to forego the templatetags & forms (e.g. if making a fully React-based frontend), read on. Otherwise, that is the end of the tutorial!
Javascript-Only integration
----------------------------
## Javascript-Only integration
Below is a walkthrough of integrating a payment gateway (PayPal) without the aid of templatetags etc..
@ -219,21 +215,19 @@ We therefore have three things we need to do in our client-side javascript:
1. Call the longclaw API to generate a token
.. code-block:: javascript
$.get({
url: 'api/checkout/token/',
success: function(response){
...
}
})
2. Following this, configure the paypal express checkout functionality. This actually has two steps.
```javascript
$.get({
url: 'api/checkout/token/',
success: function(response){
...
}
})
```
1. Following this, configure the paypal express checkout functionality. This actually has two steps.
We must first create a braintree `client` using our new token. We then use this to create a braintree
`paypal` instance.
.. code-block:: javascript
```javascript
braintree.client.create({
authorization: token
}, (err, client) => {
@ -251,14 +245,14 @@ We therefore have three things we need to do in our client-side javascript:
console.log("Paypal instance": paypalInstance);
});
});
```
3. Once paypal has created the `nonce` for the entered payment details, we must submit this
1. Once paypal has created the `nonce` for the entered payment details, we must submit this
to our server so longclaw can capture the payment.
To do this, we must have a button which we want to use to launch the paypal express checkout window.
We 'attach' the paypal instance we just created to the button like so:
.. code-block:: javascript
```javascript
paypalButton.addEventListener(
'click',
function (){
@ -279,14 +273,13 @@ We therefore have three things we need to do in our client-side javascript:
}
});
});
```
In this example `paypalButton` is a DOM node referring to the button element we wish to attach paypal to and ``handleSubmit``
is a function which will actually POST the payload to the longclaw api endpoint (``api/checkout/``)
We can make all these nested API calls simpler if we use ES6 Promises and the fetch API:
.. code-block:: javascript
```javascript
// Wrap braintree js functions as promises
function braintreeClientCreate(token){
return new Promise(function(resolve, reject){
@ -414,6 +407,7 @@ We can make all these nested API calls simpler if we use ES6 Promises and the fe
function parseJSON(response) {
return response.json();
}
```
The total amount, shipping address, shipping rate and email address of the customer are passed into the setup function;
it is up to the front end developer to create the necessary forms to gather these.

Wyświetl plik

@ -10,16 +10,20 @@ Now we have created products and configured our shipping, we can start thinking
Longclaw provides a REST API endpoint for retrieving basket data and a django view.
To use the django view, we must provide a template titled ``basket/basket.html``.
It is common to provide a link to the basket page in the header. We can use the ``url`` tag in
our site header to provide the link::
To use the django view, we must provide a template titled `basket/basket.html`.
It is common to provide a link to the basket page in the header. We can use the `url` tag in
our site header to provide the link:
{% url 'longclaw-basket' %}
```
{% url 'longclaw-basket' %}
```
In the basket template, we have access to all basket items under the ``basket`` context::
In the basket template, we have access to all basket items under the `basket` context:
{% for item in basket %}
...
{% endfor %}
```
{% for item in basket %}
...
{% endfor %}
```
For the full implementation of the basket template, take a look at the `longclaw demo repository <https://github.com/JamesRamm/longclaw_demo/blob/master/longclaw_demo/templates/basket/basket.html>`_
For the full implementation of the basket template, take a look at the [longclaw demo repository](https://github.com/JamesRamm/longclaw_demo/blob/master/longclaw_demo/templates/basket/basket.html)

Wyświetl plik

@ -6,119 +6,115 @@ sidebar_label: Adding Products
Longclaw makes as few assumptions as possible when it comes to modelling your products, since the
requirements of different shops can be wide and varied.
It is required that you create a ``ProductVariant`` model (it can be called anything) and implement
It is required that you create a `ProductVariant` model (it can be called anything) and implement
a small number of fields Longclaw expects.
The easiest way to do this is by inheriting from ``longclaw.products.ProductVariantBase``.
Longclaws' project template will have setup a ``products`` app for you, with a ``ProductVariant`` model.
The easiest way to do this is by inheriting from `longclaw.products.ProductVariantBase`.
Longclaws' project template will have setup a `products` app for you, with a `ProductVariant` model.
You will also notice that the settings file has ``PRODUCT_VARIANT_MODEL`` set to the ``ProductVariant`` model.
You will also notice that the settings file has `PRODUCT_VARIANT_MODEL` set to the `ProductVariant` model.
The project template has also created a ``ProductIndex`` and ``Product`` model.
``Product`` is a regular Wagtail ``Page`` which ``ProductVariant`` is an line model of.
The project template has also created a `ProductIndex` and `Product` model.
`Product` is a regular Wagtail `Page` which `ProductVariant` is an line model of.
.. note::
This is just one way of modelling yor catalogue but you are not bound to it. ``ProductVariant`` is the only model
> This is just one way of modelling yor catalogue but you are not bound to it. `ProductVariant` is the only model
required by Longclaw and precisely what this represents is up to your (e.g. it could be the product itself, or, as the name
suggests, a variant of a product). You could create multiple 'index' pages, perhaps representing different lines
aswell as multiple 'product' type pages, or do away with ``Product`` completely.
aswell as multiple 'product' type pages, or do away with `Product` completely.
Creating the Product Index
--------------------------
Wagtails' ``Page`` models are organized in a tree structure. All our ``Product`` pages will therefore
need a parent. This is provided by the ``ProductIndex`` model.
## Creating the Product Index
.. note::
Read more about Wagtail pages in the `Wagtail docs <http://docs.wagtail.io/en/v1.9/topics/pages.html>`_
Wagtails' `Page` models are organized in a tree structure. All our `Product` pages will therefore
need a parent. This is provided by the `ProductIndex` model.
> Read more about Wagtail pages in the [Wagtail docs](http://docs.wagtail.io/en/v1.9/topics/pages.html)
To add a product index page:
- Navigate to the admin and log in
- Select the homepage from the explorer menu
- Select ``add child page``
- Select ``Product index`` and enter the title (e.g. `Products`)
- Select `add child page`
- Select `Product index` and enter the title (e.g. `Products`)
.. figure:: ../_static/images/product_index.png
![Image of the product list](assets/product_index.png)
We can now add ``Product`` models as children of ``ProductIndex``. Only pages of type ``Product`` can be created under ``ProductIndex``.
We can now add `Product` models as children of `ProductIndex`. Only pages of type `Product` can be created under `ProductIndex`.
Adding a Product
----------------
### Adding a Product
Under the explorer homepage, we should now see our newly created ``ProductIndex``. We can select ``Add child page`` to add our first
``Product``. The ``Product`` model is fairly minimal. It has:
Under the explorer homepage, we should now see our newly created `ProductIndex`. We can select `Add child page` to add our first
`Product`. The `Product` model is fairly minimal. It has:
- A title
- A description
- One or more ``ProductVariant``s
- One or more `ProductVariant`s
- Optionally some images and tags
.. figure:: ../_static/images/product.png
![Image of the product](assets/product.png)
Customising
------------
As mentioned above, we can customise the ``ProductIndex`` and ``Product`` model completely - they
are not strict requirements for longclaw to operate. We reccomend using something similar to
the project layout so that ``Product``'s will appear in the Wagtail admin page explorer.
### Customising
``ProductVariant`` can be customised, as long as we inherit from ``ProductVariantBase`` in order to ensure
As mentioned above, we can customise the `ProductIndex` and `Product` model completely - they
are not strict requirements for longclaw to operate. We recommend using something similar to
the project layout so that `Product`'s will appear in the Wagtail admin page explorer.
`ProductVariant` can be customised, as long as we inherit from `ProductVariantBase` in order to ensure
the fields longclaw expects are present.
``ProductVariantBase`` provides the ``price``, ``ref`` and ``slug`` fields.
`ProductVariantBase` provides the `price`, `ref` and `slug` fields.
The ``ref`` field is intended to be used as a short description or sub-title to help distinguish a particular variant.
The ``slug`` field is autogenerated from the ``ref`` and the parent ``Product`` title.
The `ref` field is intended to be used as a short description or sub-title to help distinguish a particular variant.
The `slug` field is autogenerated from the `ref` and the parent `Product` title.
As we are creating a music shop, we are going to add a ``music_format`` field to the model. We will also
remove the ``description`` field as we dont have any real need for it at the moment:
As we are creating a music shop, we are going to add a `music_format` field to the model. We will also
remove the `description` field as we dont have any real need for it at the moment:
.. code-block:: python
```python
class ProductVariant(ProductVariantBase):
_MUSIC_FORMAT_CHOICES = (
(1, 'CD'),
(2, 'Vinyl'),
)
class ProductVariant(ProductVariantBase):
_MUSIC_FORMAT_CHOICES = (
(1, 'CD'),
(2, 'Vinyl'),
)
music_format = models.IntegerField(max_length=3, choices=_MUSIC_FORMAT_CHOICES)
music_format = models.IntegerField(max_length=3, choices=_MUSIC_FORMAT_CHOICES)
```
After making and running migrations, we can now select the format for each variant:
.. figure:: ../_static/images/product_variant.png
![Product variant](assets/product_variant.png)
The actual model used for the product variant can be changed by changing the ``PRODUCT_VARIANT_MODEL`` setting in your ``settings.py``
The actual model used for the product variant can be changed by changing the `PRODUCT_VARIANT_MODEL` setting in your `settings.py`
Creating the Front End
=======================
## Creating the Front End
Since ``ProductIndex`` and ``Product`` are Wagtail pages, we write templates for them just like any other page.
The Wagtail documentation already comprehensively covers `writing templates <http://docs.wagtail.io/en/v1.9/topics/writing_templates.html>`_.
Our template project already has some basic templates for ``ProductIndex`` and ``Product``:
Since `ProductIndex` and `Product` are Wagtail pages, we write templates for them just like any other page.
The Wagtail documentation already comprehensively covers [writing templates](http://docs.wagtail.io/en/v1.9/topics/writing_templates.html).
- ``my_shop/my_shop/templates/products/product_index.html``
- ``my_shop/my_shop/templates/products/product.html``
Our template project already has some basic templates for `ProductIndex` and `Product`:
- `my_shop/my_shop/templates/products/product_index.html`
- `my_shop/my_shop/templates/products/product.html`
They contain just enough information to demonstrate how to traverse the products and their fields.
For a more complete template, take a look at the `demo project <https://github.com/JamesRamm/longclaw_demo>`_.
For a more complete template, take a look at the [demo project](https://github.com/JamesRamm/longclaw_demo).
Adding Products to the Basket
-----------------------------
### Adding Products to the Basket
Longclaw offers a helpful template tag to create an ``Add To Basket`` button for your products.
In your template, load the basket tags::
.. code-block:: django
Longclaw offers a helpful template tag to create an `Add To Basket` button for your products.
In your template, load the basket tags:
```django
{% load basket_tags %}
```
You can now use the tag to render a button for each product variant:
.. code-block:: django
```django
{% add_to_basket_btn variant.id btn_text="Add To Basket" btn_class="btn btn-default" %}
```
If you wish to create a button manually, you can handle the click event by making an AJAX call to the longclaw API.
Situations where you would prefer this over the tempaltetag might be to support non-button elements, such as
@ -127,8 +123,7 @@ dropdown buttons, or for React-based frontends.
Here is an example with a single button whose 'variant id' will change depending on the selection in a dropdown box.
We can acheive the drop down like this:
.. code-block:: django
```django
<dl>
<dt>Format</dt>
<dd>
@ -141,16 +136,18 @@ We can acheive the drop down like this:
</div>
</dd>
</dl>
```
Add a button:
.. code-block:: django
```django
<button id="add-button">Add To Basket</button>
```
We can then write a jquery function to handle the click event:
.. code-block:: javascript
```javascript
$('#add-button').click(function () {
// Selected variant
@ -159,8 +156,9 @@ We can then write a jquery function to handle the click event:
// Add to the basket
$.post("api/add_to_basket/", { variant_id: variant_id });
});
```
This is a basic example of integrating with the basket. You will likely need to incorporate more
complex designs such as displaying a count of items in the basket, allowing the user to increase/decrease
quantity and so on. The :ref:`basket API <basket>` allows all such interactions and all front end design decisions such as these are left up to the developer.
quantity and so on. The [basket API](#basket) allows all such interactions and all front end design decisions such as these are left up to the developer.
It is worthwhile looking at the longclaw demo source code to see how e.g. a basket & item count in the page header is implemented.

Wyświetl plik

@ -3,50 +3,44 @@ title: Configuring Shipping
sidebar_label: Shipping
---
Configuring Shipping
====================
Now we can display products and add them to the basket, we must configure our shipping rates
before setting up the checkout process.
Per Country Rates
------------------
## Per Country Rates
Shipping rates are set on a per-country basis via the ``Shipping`` page in the wagtail admin.
Shipping rates are set on a per-country basis via the `Shipping` page in the wagtail admin.
Initially, no countries will be available - Longclaw comes with a set of country data which can be loaded into the database
using the ``loadcountries`` command:
using the `loadcountries` command:
.. code-block:: bash
```bash
python manage.py loadcountries
```
In the image below, we set a standard rate for the UK. It is possible to select multiple countries
for a rate to apply to. We can also create more than one shipping rate for the same country.
.. figure:: ../_static/images/shipping.png
![Shipping](assets/shipping.png)
Default Shipping Rate
---------------------
## Default Shipping Rate
We can configure a default shipping rate to apply to all countries we have not explicitly specified.
.. note:: By enabling default shipping, you imply that you ship to *all* countries. If you do not wish this
> By enabling default shipping, you imply that you ship to *all* countries. If you do not wish this
you should *not* enable default shipping.
To enable default shipping:
- Select ``settings`` from the wagtail admin menu
- Select ``Longclaw Settings``
- Fill in ``Default Shipping Rate`` and ``Default Shipping Carrier``
- Ensure ``Enable Default Shipping`` is checked.
- Select `settings` from the wagtail admin menu
- Select `Longclaw Settings`
- Fill in `Default Shipping Rate` and `Default Shipping Carrier`
- Ensure `Enable Default Shipping` is checked.
.. figure:: ../_static/images/default_shipping.png
![Default shipping](assets/default_shipping.png)
Currency
********
### Currency
You can also define the currency in ``Longclaw Settings``. This applies site wide. It is mostly semantic -
You can also define the currency in `Longclaw Settings`. This applies site wide. It is mostly semantic -
Longclaw assumes all calculations & prices are in the same currency - however some payment gateways require the
currency to be specified.

Wyświetl plik

@ -77,7 +77,7 @@ const siteConfig = {
highlight: {
// Highlight.js theme to use for syntax highlighting in code blocks.
theme: 'default',
theme: 'atom-one-dark',
},
// Add custom scripts here that would be placed in <script> tags.
@ -89,8 +89,8 @@ const siteConfig = {
cleanUrl: true,
// Open Graph and Twitter card images.
ogImage: 'img/docusaurus.png',
twitterImage: 'img/docusaurus.png',
ogImage: 'img/shop.png',
twitterImage: 'img/shop.png',
// Show documentation's last contributor's name.
// enableUpdateBy: true,