EvShop Plugin
=============

This is a basic checkout plugin. It is designed in a way which allows the functionality to be EXTENDED WITHOUT EDITING THE ORIGINAL PLUGIN. This will allow for easy bug fixing as the whole plugin can be overridden. 

Feature Set: 
	- Add Items to cart
	- View cart 
	- Remove items from cart
	- Checkout 
		- As registered user or guest
	- On site payments using sagepay Direct
	- Offsite payments using sagepay server, stripe, etc...
	- Admin
		- View orders in the admin 
		- Update order statuses
			- Including adding new custom statuses
	- Send email confirmations 

Working Examples: 

	Galactic Fireworks.

Upgrading Versions: 

	Most upgrades will not break exisiting functionality but if it does then a readme should be added to the repository in the format of "1.3.x to 1.4.x" specifying the procedure for upgrades, including any database changes and migrations which need to be applied.


§ Installation

	The following plugins are required for EvShop to run. If you are using Composer for install the dependencies will be added
	automattically when you run "Console/cake composer.c require evoluted/shop"
		- EvShop
		- EvCheckout
		- SearchIndex
		- EvCategory
		- EvRelatedItems
		- CakeDC/Migrations 

	bootstrap.php 

		CakePlugin::load('EvShop', array(
			'routes' => true,
			'bootstrap' => true
		));

		Configure::write('enableSSL', true); // If your site uses onsite payments SSL is needed

	Add the following helpers 

		'EvShop.Product'

	Setup the database 

		- This plugin has been setup to use the CakeDC Migrations plugin. This allows for easy setup of the database schema and allows for painless migration when database changes are made during an upgrade. 

		- To run the migrations and setup the database run 

			"Console/cake Migrations.migration run all --plugin EvShop"

			Side Note: Migrations will also need to be run for the other required plugins

	Attach event listeners (see wiki for complete details)

		// First make sure the ClassRegistry is loaded
		App::uses('ClassRegistry', 'Utility');
		 
		// Next initiate an Order object so that we can attach the event listeners
		$Order = ClassRegistry::init('EvCheckout.Order');
		 
		// Load the event listeners (you can override these in your app by creating new listeners)
		App::uses('DeliveryCalculatorListener', 'EvCheckout.Event');
		App::uses('OrderEmailListener', 'EvCheckout.Event');
		 
		// Now attach the event listeners to our Order object
		$Order->getEventManager()->attach(new DeliveryCalculatorListener());
		$Order->getEventManager()->attach(new OrderEmailListener());

		// Attach global event listeners like the CustomerAuthListener (this will clear the basket
		// on logout)
		App::uses('CustomerAuthListener', 'EvCheckout.Event');
		CakeEventManager::instance()->attach(new CustomerAuthListener());


§ Customers

The Customer model extends the app's User model. It is possible for guest users to checkout. For these users a user record will still be generated, but will not have a password for logging in with. As a result the plugin needs to remove the unique index from users.email and alters the validation rule used on the email field via the Customer model. This may need taking into account elsewhere in your app.

In order for Auth to continue working there must only be one record per email address with a password (a registered user); guest users do not have a password and are a one-use only account. This is to prevent someone from being able to edit a guest user account with just knowledge of the email address (otherwise it would be possible to overwrite fields like name and phone number).

The Customer model has a uniqueEmail validation rule that checks for duplicate registered accounts on validation. If validating the email address the is_guest_user field *must* be present in the data.


§ Adding an item to the basket

	You can add an item to the basket using:
		
		$this->Order->addToBasket($params); 

	There following params can be passed: 

		'model' => '', 			//Full model path including plugin prefix
		'model_id' => '', 		// UUID of the model
		'order_id' => '', 		// Order to add the item to, if not set then it will get the cart from the session
		'name' => '', 			// Name of the product as it should show in the basket
		'description' => '', 	// Description which should include product options summary etc. 
		'unit_cost' => 0,		// Cost for one item EXCLUDING VAT
		'quantity' => 1,		// Quantity
		'subtotal' => false,	// Subtotal if left blank will be calculated from unit cost and quantity
		'vat' => false,			// VAT of the item, if not set will be calculated from the vat_rate_id 
		'total' => false,		// Total of order item including VAT, if not set will be calculated automattically 
		'is_virtual' => false,	// Indicates whether the item has shipping or not
		'vat_rate_id' => '',	// The VAT rate applicable to the line item 

Summary of Session and Configuration Variables 

	SESSIONS USED 

		Order.cart_id - Corresponds to EvCheckout.Order::id
		EvCheckout.lastListingPage - Stores the URL of the last product listing page the user visited, used for continue shopping buttons

	DISPATCHED EVENTS 

		Model.Order.updateOrderStatus - called whenever an order changes status 
		Model.Order.updateOrderTotal - called when the basket total is been calculated, discount and voucher systems should link on here
		Model.Order.addToBasket - called whenever an item is added to the basket, a good place to hook on any offer systems that add an extra item to the basket when you add X of one item etc.
		Model.Order.calculateTaxes - called when adding an item to the basket to allow overridding of VAT



	CONFIGURATION SETTINGS USED

		EvCheckout.CheckoutAsGuest - Indicates whether guest checkout is enabled - NOT CURRENTLY IMPLEMENTED but shouldn't be too much work for the luck volunteer
		EvCheckout.BlindCopyEmail -  Sets an email address to copy into all order emails, if using multiple seperate by a comma e.g. info@evoluted.net,sam@evoluted.net

		Configure::write('enableSSL', true); - Turns SSL on for on site payments

	SITE SETTINGS AVAILABLE 

		Any that are not set will be ignored

		SiteSetting.free_delivery_threshold - Price after which free delivery applies  } If using the evoluted/delivery-bands plugin these should be left blank
		SiteSetting.fixed_delivery_cost - Delivery cost before free delivery kicks in  }
		SiteSetting.delivery_info - Information about delivery, shown on the basket and confirmation screens
		
		SiteSetting.registration_intro - Shown above the registration form on the checkout to explain why people should signup instead of guest checkout 

		SiteSetting.orders_email - Email to send all order notifications


§ Notes

	Columns that exclude VAT in the database tables such as unit_price and subtotals are set to 6 decimal points delibaretly to avoid rounding issues that can occur when working out VAT for small values. 20% VAT on 1p for example can cause issues if the precision is not high enough.


§ Abandoned Carts

	Abandoned carts can be viewed via the admin listings page using the 'In basket' filter. Only orders associated with a customer containing items will show when using this filter.

	To clear out abandoned orders call:-

		Console/cake EvCheckout.order expire {days}

	Where days is to be replaced by the number of days an order expires after. For example, to expire all orders not edited in the last month call:-

		Console/cake EvCheckout.order expire 30
	
	By default it will not remove abandoned orders associated with a customer containing items (so that an admin can still view these for marketing 
	purposes). To remove them as well pass 'all' as the second argument:-
	
		Console/cake EvCheckout.order expire 30 all