Browse files

Work on shop.

  • Loading branch information...
1 parent f857b02 commit 7d1e6453ec246fb29ae261350101168a5733b3f3 @arjan committed Dec 20, 2011
View
2 actions/action_shoppingcart_add_to_cart.erl → actions/action_shop_add_to_cart.erl
@@ -18,7 +18,7 @@
%% See the License for the specific language governing permissions and
%% limitations under the License.
--module(action_shoppingcart_add_to_cart).
+-module(action_shop_add_to_cart).
-author("Arjan Scherpenisse <arjan@scherpenisse.net>").
-include("action_postback.hrl").
View
2 actions/action_shoppingcart_empty_cart.erl → actions/action_shop_empty_cart.erl
@@ -18,7 +18,7 @@
%% See the License for the specific language governing permissions and
%% limitations under the License.
--module(action_shoppingcart_empty_cart).
+-module(action_shop_empty_cart).
-author("Arjan Scherpenisse <arjan@scherpenisse.net>").
-include("action_postback.hrl").
View
2 .../action_shoppingcart_remove_from_cart.erl → actions/action_shop_remove_from_cart.erl
@@ -18,7 +18,7 @@
%% See the License for the specific language governing permissions and
%% limitations under the License.
--module(action_shoppingcart_remove_from_cart).
+-module(action_shop_remove_from_cart).
-author("Arjan Scherpenisse <arjan@scherpenisse.net>").
-include("action_postback.hrl").
View
31 actions/action_shop_update_cart_amount.erl
@@ -0,0 +1,31 @@
+%% @author Arjan Scherpenisse <arjan@scherpenisse.net>
+%% @copyright 2011 Arjan Scherpenisse <arjan@scherpenisse.net>
+%% Date: 2011-12-05
+
+%% @doc Add a rsc id to the cart
+
+%% Copyright 2011 Arjan Scherpenisse
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+
+-module(action_shop_update_cart_amount).
+-author("Arjan Scherpenisse <arjan@scherpenisse.net>").
+
+-include("action_postback.hrl").
+
+postback(Args, Context) ->
+ {item, Item} = proplists:lookup(item, Args),
+ Amount = z_convert:to_integer(z_context:get_q("triggervalue", Context)),
+ m_shoppingcart:update_cart(Amount, Item, Context),
+ Context.
+
View
3 dispatch/dispatch
@@ -0,0 +1,3 @@
+[
+ {shop_order_status, ["shop", "order", id], resource_template, [{template, "shop_order_status.tpl"}]}
+].
View
17 include/mod_shop.hrl
@@ -1,4 +1,19 @@
-record(payment_provider,
- {name, module, action}).
+ {name, module, function}).
+-record(payment_status,
+ {status, order_id, details=[]}).
+
+-record(shop_order,
+ {cart=[], % the items
+ details=[], % address details
+
+ status,
+ id,
+ email,
+ shopper_ref,
+
+ price_ex_vat=0, % in cents
+ price_inc_vat=0 % in cents
+ }).
View
88 mod_shop.erl
@@ -29,7 +29,11 @@
-include_lib("include/zotonic.hrl").
-include_lib("include/mod_shop.hrl").
--export([manage_schema/2, event/2]).
+-export([
+ manage_schema/2,
+ event/2,
+ observe_payment_status/2
+ ]).
%% @doc Add an item to the shoppingcart.
event({submit, {add_to_cart, [{id, Id}, {variant_id, VariantId}]}, _, _}, Context) ->
@@ -43,20 +47,36 @@ event({submit, {add_to_cart, [{id, Id}, {variant_id, VariantId}]}, _, _}, Contex
%% @doc On submit of the checkout form.
event({submit, {checkout, []}, _, _}, Context) ->
+
+ %% Get the checkout details
FormValues = z_context:get_q_validated(
[firstname, lastname, address, postcode, city, phone, email], Context),
- ?DEBUG(FormValues),
- Pp = list_to_existing_atom(z_context:get_q("payment-provider", Context)),
- Provider = hd(lists:filter(fun(P) -> case P#payment_provider.module of Pp -> true; _ -> false end end,
- m_shop:get_payment_providers(Context))),
-
- ?DEBUG(Provider),
+ Cart = m_shoppingcart:get_cart(Context),
+ Order = order_from_cart(Cart, FormValues, Context),
+
+ %% Store the order
+ Order1 = store_order(Order, Context),
+
+ %% Do the payment
+ payment_redirect(Order1, Context).
+
+
+
+%% @doc A payment has been made. Redirect to a sane location.
+observe_payment_status(#payment_status{status=Status, order_id=OrderId, details=Details}, Context) ->
+ ContextAdmin = z_acl:sudo(Context),
- Context.
+ %% Add information to the order
+ m_rsc:update(OrderId, [{payment, Details}, {status, Status}], ContextAdmin),
+
+ %% Clear the cart
+ m_shoppingcart:empty_cart(Context),
+ %% Redirect
+ z_dispatcher:url_for(shop_order_status, [{id, OrderId}], Context).
manage_schema(install, _Context) ->
@@ -66,7 +86,53 @@ manage_schema(install, _Context) ->
],
resources=
[
- {page_shoppingcart, text, [{title, <<"Shopping cart">>}, {page_path, <<"/cart">>}]},
- {page_checkout, text, [{title, <<"Checkout">>}, {page_path, <<"/checkout">>}]}
- ]
+ {page_shoppingcart, text, [{title, <<"Shopping cart">>}, {page_path, <<"/cart">>}]},
+ {page_checkout, text, [{title, <<"Checkout">>}, {page_path, <<"/checkout">>}]}
+ ]
}.
+
+
+
+%% @doc Given a shopping cart, create an order record.
+order_from_cart(Cart, FormValues, Context) ->
+ Items = proplists:get_value(items, Cart),
+ Items1 = [[{amount, Amount} | Item] || {Item, Amount} <- Items],
+ Cart1 = z_utils:prop_replace(items, Items1, Cart),
+ Price = proplists:get_value(total, Cart1),
+ Order = #shop_order{
+ status = new,
+ cart = Cart1,
+ details = FormValues,
+ id = undefined,
+ email = proplists:get_value(email, FormValues),
+ shopper_ref = z_context:persistent_id(Context),
+ price_ex_vat = Price*100,
+ price_inc_vat = round(Price*1.19*100)},
+ Order.
+
+
+%% @doc Store the order in the database.
+store_order(Order=#shop_order{}, Context) ->
+ ContextAdmin = z_acl:sudo(Context),
+ Props = [{category, shop_order},
+ {title, ["Shop order on ", erlydtl_dateformat:format("j F Y, H:i", ContextAdmin)]},
+ {is_published, true},
+ {status, Order#shop_order.status},
+ {order, lists:zip(record_info(fields, shop_order), tl(tuple_to_list(Order)))},
+ {visible_for, ?ACL_VIS_USER}],
+ {ok, Id} = m_rsc:insert(Props, ContextAdmin),
+ ?DEBUG(Id),
+ Order#shop_order{id=Id}.
+
+
+%% @doc Handle the payment of the order based on the payment-provider POST value.
+payment_redirect(Order, Context) ->
+ %% Get the provider
+ Pp = list_to_existing_atom(z_context:get_q("payment-provider", Context)),
+ Provider = hd(lists:filter(fun(P) -> case P#payment_provider.module of Pp -> true; _ -> false end end,
+ m_shop:get_payment_providers(Context))),
+
+ Module = Provider#payment_provider.module,
+ Function = Provider#payment_provider.function,
+ Module:Function(Order, Context).
+
View
20 models/m_shoppingcart.erl
@@ -27,7 +27,9 @@
m_to_list/2,
m_value/2,
+ get_cart/1,
add_to_cart/3,
+ update_cart/3,
remove_from_cart/2,
empty_cart/1
]).
@@ -53,19 +55,20 @@ m_value(_, _Context) ->
undefined.
+%% @doc Get the cart from the sesion.
get_cart(Context) ->
z_context:get_session(m_shoppingcart, Context,
[{items, []},
{total, 0},
{count, 0}]).
+%% @doc Get only the items from the cart.
get_cart_items(Context) ->
proplists:get_value(items, get_cart(Context)).
+
%% @doc Set the shopping cart to its new contents.
set_cart(Items, Context) ->
-?DEBUG(Items),
-
Total = lists:foldl(fun({I, C}, X) -> proplists:get_value(price, I, 0)*C+X end, 0.0, Items),
Count = lists:sum([C || {_, C} <- Items]),
Cart = [{items, Items},
@@ -75,7 +78,8 @@ set_cart(Items, Context) ->
mod_signal:emit({shoppingcart_changed, [{cart, z_context:persistent_id(Context)}]}, Context).
-add_to_cart(Amount, Item, Context) ->
+%% @doc Add an item to the cart (one or more of the same)
+add_to_cart(Amount, Item, Context) when is_integer(Amount) andalso Amount > 0 ->
Items = get_cart_items(Context),
Items1 = case proplists:get_value(Item, Items) of
undefined ->
@@ -85,10 +89,20 @@ add_to_cart(Amount, Item, Context) ->
end,
set_cart(Items1, Context).
+%% @doc Update the amount of items in the cart
+update_cart(0, Item, Context) ->
+ remove_from_cart(Item, Context);
+update_cart(Amount, Item, Context) when is_integer(Amount) andalso Amount > 0 ->
+ Items = get_cart_items(Context),
+ Items1 =z_utils:prop_replace(Item, Amount, Items),
+ set_cart(Items1, Context).
+
+%% @doc Remove an item from the cart.
remove_from_cart(Item, Context) ->
set_cart(proplists:delete(Item, get_cart_items(Context)), Context).
+%% @doc Empty the shoppingcart.
empty_cart(Context) ->
set_cart([], Context).
View
12 templates/shop_order_status.tpl
@@ -0,0 +1,12 @@
+{% extends "page.tpl" %}
+
+{% block content %}
+{% with m.rsc[q.id] as r %}
+
+<h1>{{ r.title }}</h1>
+
+{% print r.status %}
+
+{% endwith %}
+
+{% endblock %}

0 comments on commit 7d1e645

Please sign in to comment.