Shop module provides basic functionality, but is very hackable that allows to greatly extend features and appearance of module

For user

Shop module have some basic elements

Orders
Orders usually includes few items, some shipping type and have current status
Items
Items can be of different categories (item can be placed only in one category) and be accompanied with some attributes
Categories
Categories are main way to group set of items in one place, category defines which attributes are available to items in it
Attributes
Attributes are used to describe characteristics of items in category and is used in searching and filtering of items
Shipping types
Shipping types are used to differentiate shipping cost and time
Order statuses
There can be different order statuses of different types. Types are predefined

IMPORTANT: After installation you have no Orders, Items, Categories, Attributes, Shipping types or Order statuses. You have to create them, preferably starting from the end of list moving to the beginning because items at the beginning of the list depends on items at the end.

There are no payment types except Cash out of the box, so Cash assumed by default. However, new payment types will appear in interface as soon as third party module that implements this functionality will be installed (there can be multiple modules for different payment types)

For developer

This section will describe how developer can extend Shop module to make it unique and implement necessary functionality that is not available out of the box.

Appearance

All user-side elements are WebComponents, Polymer elements. This means that you can extend elements using patched Polymer that comes with CleverStyle CMS easily:

	
		<polymer-element name="cs-shop-category" extends="cs-shop-category">
			<template>
				//Whatever here
			</template>
			<script>
				// Whatever here
			</script>
		</polymer-element>
	
API

There are 2 APIs: one for administration, another for user-side. Usually you'll need user-side API, which is simple and will give you all information you may see on user-side pages and even more.

API is especially useful for customizing appearance, because sometimes you may need more that actually present in HTML markup, so you can easily load it on demand.

Possible API calls for user-side:

GET api/Shop/cart?items={items}&shipping_type={shipping_type}
{items} - Array in form of [id => units]
{shipping_type} - Shipping type id
Returns:
[
	'items'    => $items,   // Array of array elements [id => item_id, units => units, price => total_price]
	'shipping' => $shipping // Array in form [type => shipping_type_id, price => shipping_type_price]
]
Is used to calculate prices of items and shipping (possibly including discounts and something else)
GET api/Shop/settings
Returns:
{
	"price_formatting"                    : "$%s USD",
	"items_per_page"                      : 20,
	"items_per_page_admin"                : 50,
	"automatically_reduce_in_stock_value" : 1,
	"default_order_status"                : 2,
	"default_paid_order_status"           : 3,
	"allow_guests_orders"                 : 1
}
GET api/Shop/attributes/{id}
{id} - Attribute id
Returns:
{"id"                : "1",
	"type"           : "5",
	"title"          : "Title",
	"title_internal" : "Internal title",
	"value"          : ""
}
GET api/Shop/attributes?ids={id},{id}
{id},{id} - coma-separated list of ids
Returns:
[
	{
		"id"             : "1",
		"type"           : "5",
		"title"          : "Title",
		"title_internal" : "Internal title",
		"value"          : ""
	},
	{
		"id"             : "3",
		"type"           : "1",
		"title"          : "Int set",
		"title_internal" : "Int set",
		"value"          : [
			"1",
			"2",
			"3",
			"4"
		]
	}
]
GET api/Shop/attributes/types
Returns:
{
	"1" : "Integer set",
	"2" : "Fractional set",
	"3" : "Integer range",
	"4" : "Fractional range",
	"5" : "String",
	"6" : "String set",
	"7" : "Text",
	"8" : "Yes\/no switch",
	"9" : "Color set"
}
GET api/Shop/categories
Includes only visible categories
Returns:
[
	{
		"id"                    : "1",
		"parent"                : "0",
		"title"                 : "First category",
		"description"           : "Long category description",
		"title_attribute"       : "2",
		"description_attribute" : "6",
		"image"                 : "",
		"visible"               : "1",
		"attributes"            : [
			"2",
			"6"
		]
	},
	{
		"id"                    : "2",
		"parent"                : "1",
		"title"                 : "Second category (nested)",
		"description"           : "Long description",
		"title_attribute"       : "2",
		"description_attribute" : "6",
		"image"                 : "",
		"visible"               : "1",
		"attributes"            : [
			"2",
			"3",
			"6"
		]
	},
	{
		"id"                    : "3",
		"parent"                : "1",
		"title"                 : "Third category (nested)",
		"description"           : "Long description",
		"title_attribute"       : "1",
		"description_attribute" : "0",
		"image"                 : "",
		"visible"               : "1",
		"attributes"            : []
	},
	{
		"id"                    : "6",
		"parent"                : "0",
		"title"                 : "Category with image",
		"description"           : "This is the first category with image",
		"title_attribute"       : "1",
		"description_attribute" : "0",
		"image"                 : "http:\/\/cscms.org\/storage\/public\/Plupload\/2014-12-15\/20\/2_3905548f2ac9b2d5f.jpg",
		"visible"               : "1",
		"attributes"            : [
			"1",
			"2",
			"3",
			"6"
		]
	}
]
GET api/Shop/categories?ids={id},{id}
{id},{id} - coma-separated list of ids
Returns:
[
	{
		"id"                    : "1",
		"parent"                : "0",
		"title"                 : "First category",
		"description"           : "Long category description",
		"title_attribute"       : "2",
		"description_attribute" : "6",
		"image"                 : "",
		"visible"               : "1",
		"attributes"            : [
			"2",
			"6"
		]
	},
	{
		"id"                    : "6",
		"parent"                : "0",
		"title"                 : "Category with image",
		"description"           : "This is the first category with image",
		"title_attribute"       : "1",
		"description_attribute" : "0",
		"image"                 : "http:\/\/cscms.org\/storage\/public\/Plupload\/2014-12-15\/20\/2_3905548f2ac9b2d5f.jpg",
		"visible"               : "1",
		"attributes"            : [
			"1",
			"2",
			"3",
			"6"
		]
	}
]
GET api/Shop/categories/{id}
{id} - Category id
Returns:
{
	"id"                    : "6",
	"parent"                : "0",
	"title"                 : "Category with image",
	"description"           : "This is the first category with image",
	"title_attribute"       : "1",
	"description_attribute" : "0",
	"image"                 : "http:\/\/cscms.org\/storage\/public\/Plupload\/2014-12-15\/20\/2_3905548f2ac9b2d5f.jpg",
	"visible"               : "1",
	"attributes"            : [
		"1",
		"2",
		"3",
		"6"
	]
}
GET api/Shop/items?ids={id},{id}
{id},{id} - coma-separated list of items ids
Returns:
[
	{
		"id"                    : "1",
		"parent"                : "0",
		"title"                 : "First category",
		"description"           : "Long category description",
		"title_attribute"       : "2",
		"description_attribute" : "6",
		"image"                 : "",
		"visible"               : "1",
		"attributes"            : [
			"2",
			"6"
		]
	},
	{
		"id"                    : "6",
		"parent"                : "0",
		"title"                 : "Category with image",
		"description"           : "This is the first category with image",
		"title_attribute"       : "1",
		"description_attribute" : "0",
		"image"                 : "http:\/\/cscms.org\/storage\/public\/Plupload\/2014-12-15\/20\/2_3905548f2ac9b2d5f.jpg",
		"visible"               : "1",
		"attributes"            : [
			"1",
			"2",
			"3",
			"6"
		]
	}
]
GET api/Shop/orders
Returns:
[
	{
		"id"                : "1",
		"user"              : "2",
		"date"              : "1420929764",
		"shipping_type"     : "0",
		"shipping_cost"     : "0",
		"shipping_username" : "Назар",
		"shipping_phone"    : "+380000000000",
		"shipping_address"  : "Kyiv\nUkraine",
		"payment_method"    : "shop:test",
		"paid"              : "0",
		"status"            : "2",
		"comment"           : "Long comment from user\nin two lines",
		"for_payment"       : 20
	},
	{
		"id"                : "1",
		"user"              : "2",
		"date"              : "1419939973",
		"shipping_type"     : "2",
		"shipping_cost"     : "5",
		"shipping_username" : "Nazar",
		"shipping_phone"    : "+380000000000",
		"shipping_address"  : "Kyiv\nUkraine",
		"payment_method"    : "shop:cash",
		"paid"              : "1",
		"status"            : "3",
		"comment"           : "Comment for paid order",
		"for_payment"       : 25
	}
]
POST api/Shop/orders
{
	"shipping_type"     : "1",
	"shipping_username" : "Назар",
	"shipping_phone"    : "+380000000000",
	"shipping_address"  : "Kyiv\nUkraine",
	"payment_method"    : "shop:cash",
	"comment"           : "Huge comment)",
	"items"             : {
		"2" : 1,
		"3" : 5
	}
}
items - contains array in form [id => units]
Returns:
"http:\/\/cscms.org\/api\/Shop\/orders\/20"
Status code: 201 Created
GET api/Shop/orders/{id}
{id} - Order id
Returns:
{
	"id"                : "20",
	"user"              : "2",
	"date"              : "1422918620",
	"shipping_type"     : "1",
	"shipping_cost"     : "0",
	"shipping_username" : "Назар",
	"shipping_phone"    : "+380000000000",
	"shipping_address"  : "Kyiv\nUkraine",
	"payment_method"    : "shop:cash",
	"paid"              : "0",
	"status"            : "2",
	"comment"           : "Huge comment)",
	"for_payment"       : 0
}
GET api/Shop/orders/{id}/items
{id} - Order id
Returns:
[
	{
		"id"         : "20",
		"item"       : "2",
		"units"      : "1",
		"price"      : "30",
		"unit_price" : "30"
	},
	{
		"id"         : "20",
		"item"       : "3",
		"units"      : "5",
		"price"      : "10",
		"unit_price" : "2"
	}
]
GET api/Shop/orders/{id}/statuses
{id} - Order id
Returns:
[
	{
		"id"      : "20",
		"date"    : "1422918620",
		"status"  : "2",
		"comment" : "Order created"
	}
]
GET api/Shop/payment_methods
Returns:
{
	"shop:cash" : {
		"title"       : "Cash",
		"description" : ""
	}
}
Backend events

Backend events greatly extends customizations and functionality - they allow to apply discounts, special offers, limit access to specific items for specific users and so on.

Shop module dispatches such own events:

Details about how to use them you can find at their declaration in source code, it is pretty simple.

Also Shop module dispatches some other events that might be useful for implementing additional payment methods and payment processing:

System/payment/methods
[
	'methods'  => &$payment_methods,
	'currency' => {currency}
]
To implement payment method its name should be added into array $payment_method. Payment method should look like shop:cash, where shop identifies module name and cash payment method itself, {currency} is 3-4 capital letters short code of currency (might be regular currency or cryptocurrency).
System/payment/execute
[
	'amount'         => {amount},
	'currency'       => {currency},
	'user'           => {user_id},
	'payment_method' => {payment_method},
	'module'         => Shop,
	'purpose'        => orders/{order_id},
	'description'    => {description}
]
Module that implements payment method should be subscribed to this event, and if {payment_method} corresponds to specified in System/payment/methods - payment should be processed, {currency} is 3-4 capital letters short code of currency (might be regular currency or cryptocurrency).
After payment processing System/payment/success or System/payment/error event should be dispatched.

Shop module is subscribed to events that corresponds to payments processing, which can be done by third-party modules:

System/payment/success
[
	'module'   => Shop,
	'purpose'  => orders/{order_id},
	'callback' => &$callback
]
First two parameters are the same as in System/payment/execute, callback will contain Page where user can be redirected after successful payment.
System/payment/error
[
	'module'   => Shop,
	'purpose'  => orders/{order_id},
	'callback' => &$callback
]
First two parameters are the same as in System/payment/execute, callback will contain Page where user can be redirected after failed payment.