Skip to content

Commit

Permalink
Work on shop.
Browse files Browse the repository at this point in the history
  • Loading branch information
Arjan Scherpenisse committed Dec 20, 2011
1 parent f857b02 commit 7d1e645
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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").
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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").
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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").
Expand Down
31 changes: 31 additions & 0 deletions actions/action_shop_update_cart_amount.erl
Original file line number Diff line number Diff line change
@@ -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.

3 changes: 3 additions & 0 deletions dispatch/dispatch
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[
{shop_order_status, ["shop", "order", id], resource_template, [{template, "shop_order_status.tpl"}]}
].
17 changes: 16 additions & 1 deletion include/mod_shop.hrl
Original file line number Diff line number Diff line change
@@ -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
}).
88 changes: 77 additions & 11 deletions mod_shop.erl
Original file line number Diff line number Diff line change
Expand Up @@ -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) ->
Expand All @@ -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) ->
Expand All @@ -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).

20 changes: 17 additions & 3 deletions models/m_shoppingcart.erl
Original file line number Diff line number Diff line change
Expand Up @@ -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
]).
Expand All @@ -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},
Expand All @@ -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 ->
Expand All @@ -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).
12 changes: 12 additions & 0 deletions templates/shop_order_status.tpl
Original file line number Diff line number Diff line change
@@ -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.