- Added Cashier/Point of Sale mode for the Shop.

- Added the notion of a default address to the Shop's address book.
This commit is contained in:
JT Smith 2008-11-15 01:26:16 +00:00
parent 47419b9602
commit 16bd779fd4
9 changed files with 263 additions and 24 deletions

View file

@ -2,6 +2,8 @@
- Brand new Survey system. Make sure to export your old results as they will
not be imported, only the surveys themselves.
- Made syndicated content asset use cache.
- Added Cashier/Point of Sale mode for the Shop.
- Added the notion of a default address to the Shop's address book.
- fixed #8837: When you move an asset to a new version, only the current version is moved, instead of all of them.
- Added version tag modes: multiple tags per user, single tag per user, site wide version tag and auto commit (thanks to Long Term Results B.V.)
- fixed #9076: Thingy broken in latest beta, Save and Close buttons missing

View file

@ -32,10 +32,29 @@ my $session = start(); # this line required
migrateSurvey($session);
addVersionTagMode($session);
addPosMode($session);
finish($session); # this line required
#----------------------------------------------------------------------------
sub addPosMode {
my $session = shift;
print qq{\tAdding Point of Sale mode to the Shop...} if !$quiet;
my $db = $session->db();
my $setting = $session->setting();
$setting->add("groupIdCashier","3");
$db->write(q{ALTER TABLE cart drop column couponId});
$db->write(q{ALTER TABLE cart add column posUserId char(22) binary});
$db->write(q{ALTER TABLE transaction add column cashierUserId char(22) binary});
$db->write(q{update transaction set cashierUserId=userId});
$db->write(q{ALTER TABLE addressBook add column defaultAddressId char(22) binary});
print qq{Finished\n} if !$quiet;
}
#----------------------------------------------------------------------------
# This method add support for versionTagMode
@ -43,7 +62,7 @@ finish($session); # this line required
sub addVersionTagMode {
my $session = shift;
print q{Adding support for versionTagMode...} if !$quiet;
print qq{\tAdding support for versionTagMode...} if !$quiet;
my $db = $session->db();
my $setting = $session->setting();
@ -75,12 +94,11 @@ sub addVersionTagMode {
#
sub migrateSurvey{
my $session = shift;
print "Migrating surveys to new survey system..." unless $quiet;
print "\tMigrating surveys to new survey system..." unless $quiet;
_moveOldSurveyTables($session);
_addSurveyTables($session);
print "\n";
my $surveys = $session->db->buildArrayRefOfHashRefs(
"SELECT * FROM Survey_old s

View file

@ -114,6 +114,18 @@ our $HELP = {
name => "shippingAddress",
description => "shippingAddress help",
},
{
name => "isCashier",
},
{
name => "posLookupForm",
},
{
name => "posUsername",
},
{
name => "posUserId",
},
],
},
{
@ -226,6 +238,11 @@ our $HELP = {
description => "editButton help",
required => 1,
},
{
name => "defaultButton",
description => "defaultButton help",
required => 1,
},
{
name => "deleteButton",
description => "deleteButton help",
@ -278,6 +295,10 @@ our $HELP = {
name => "state",
description => "state help",
},
{
name => "organization",
description => "organization help",
},
{
name => "city",
description => "city help",

View file

@ -174,6 +174,34 @@ sub getAddresses {
#-------------------------------------------------------------------
=head2 getDefaultAddress ()
Returns the default address for this address book if there is one. Otherwise throws a WebGUI::Error::ObjectNotFound exception.
=cut
sub getDefaultAddress {
my ($self) = @_;
my $id = $self->get('defaultAddressId');
if ($id ne '') {
my $address = eval { $self->getAddress($id) };
my $e;
if ($e = WebGUI::Error->caught('WebGUI::Error::ObjectNotFound')) {
$self->update({defaultAddressId=>''});
$e->rethrow;
}
elsif ($e = WebGUI::Error->caught) {
$e->rethrow;
}
else {
return $address;
}
}
return undef;
}
#-------------------------------------------------------------------
=head2 getId ()
Returns the unique id for this cart.
@ -288,12 +316,16 @@ Assign the user that owns this address book.
Assign the session, by id, that owns this address book. Will automatically be set to "" if a user owns it.
=head4 defaultAddressId
The id of the address to be made the default for this address book.
=cut
sub update {
my ($self, $newProperties) = @_;
my $id = id $self;
foreach my $field (qw(userId sessionId)) {
foreach my $field (qw(userId sessionId defaultAddressId)) {
$properties{$id}{$field} = (exists $newProperties->{$field}) ? $newProperties->{$field} : $properties{$id}{$field};
}
##Having both a userId and sessionId will confuse create.
@ -319,6 +351,20 @@ sub www_deleteAddress {
#-------------------------------------------------------------------
=head2 www_defaultAddress ( )
Makes an address be the default.
=cut
sub www_defaultAddress {
my $self = shift;
$self->update({defaultAddressId=>$self->session->form->get("addressId")});
return $self->www_view;
}
#-------------------------------------------------------------------
=head2 www_editAddress ()
Allows a user to edit an address in their address book.
@ -467,6 +513,7 @@ sub www_view {
push(@addresses, {
%{$address->get},
address => $address->getHtmlFormatted,
isDefault => ($self->get('defaultAddressId') eq $address->getId),
deleteButton => WebGUI::Form::formHeader($session)
.WebGUI::Form::hidden($session, {name=>"shop", value=>"address"})
.WebGUI::Form::hidden($session, {name=>"method", value=>"deleteAddress"})
@ -481,6 +528,13 @@ sub www_view {
.$self->formatCallbackForm($form->get('callback'))
.WebGUI::Form::submit($session, {value=>$i18n->get("edit")})
.WebGUI::Form::formFooter($session),
defaultButton => WebGUI::Form::formHeader($session)
.WebGUI::Form::hidden($session, {name=>"shop", value=>"address"})
.WebGUI::Form::hidden($session, {name=>"method", value=>"defaultAddress"})
.WebGUI::Form::hidden($session, {name=>"addressId", value=>$address->getId})
.$self->formatCallbackForm($form->get('callback'))
.WebGUI::Form::submit($session, {value=>$i18n->get("default")})
.WebGUI::Form::formFooter($session),
useButton => WebGUI::Form::formHeader($session,{action=>$callback->{url}})
.$callbackForm
.WebGUI::Form::hidden($session, {name=>"addressId", value=>$address->getId})

View file

@ -74,6 +74,24 @@ sub getAdminConsole {
#-------------------------------------------------------------------
=head2 isCashier ( [ $user ] )
Determine whether or not a user is a cashier
=head3 $user
An optional WebGUI::User object. If this is not used, it uses the current session user object.
=cut
sub isCashier {
my $self = shift;
my $user = shift || $self->session->user;
return $user->isInGroup( $self->session->setting->get('groupIdCashier'));
}
#-------------------------------------------------------------------
=head2 new ( session )
Constructor.
@ -127,6 +145,12 @@ sub www_editSettings {
label => $i18n->get('who can manage'),
hoverHelp => $i18n->get('who can manage help'),
);
$form->group(
name => "groupIdCashier",
value => $setting->get("groupIdCashier"),
label => $i18n->get('who is a cashier'),
hoverHelp => $i18n->get('who is a cashier help'),
);
$form->template(
name => "shopCartTemplateId",
value => $setting->get("shopCartTemplateId"),
@ -182,7 +206,9 @@ sub www_editSettingsSave {
shopCartTemplateId shopAddressBookTemplateId shopAddressTemplateId)) {
$setting->set($template, $form->get($template, "template"));
}
$setting->set("groupIdAdminCommerce", $form->get("groupIdAdminCommerce", "group"));
foreach my $group (qw(groupIdCashier groupIdAdminCommerce)) {
$setting->set($group, $form->get($group, "group"));
}
return $self->www_editSettings();
}

View file

@ -13,6 +13,7 @@ use WebGUI::Shop::CartItem;
use WebGUI::Shop::Credit;
use WebGUI::Shop::Ship;
use WebGUI::Shop::Tax;
use WebGUI::User;
=head1 NAME
@ -83,7 +84,7 @@ sub calculateShopCreditDeduction {
unless (defined $total) {
$total = $self->calculateTotal
}
return $self->formatCurrency(WebGUI::Shop::Credit->new($self->session)->calculateDeduction($total));
return $self->formatCurrency(WebGUI::Shop::Credit->new($self->session, $self->get('posUserId'))->calculateDeduction($total));
}
#-------------------------------------------------------------------
@ -344,6 +345,22 @@ sub getItemsByAssetId {
#-------------------------------------------------------------------
=head2 getPosUser
Returns the userId of the user making a purchase. If there is a cashier and the cashier has specified a user, then that user will be returned. Otherwise, if it's a direct sale then $session->user will be returned.
=cut
sub getPosUser {
my $self = shift;
if ($self->get('posUserId') ne "") {
return WebGUI::User->new($self->session, $self->get('posUserId'));
}
return $self->session->user;
}
#-------------------------------------------------------------------
=head2 getShipper ()
Returns the WebGUI::Shop::ShipDriver object that is attached to this cart for shipping.
@ -365,7 +382,13 @@ Returns the WebGUI::Shop::Address object that is attached to this cart for shipp
sub getShippingAddress {
my $self = shift;
return $self->getAddressBook->getAddress($self->get("shippingAddressId"));
my $book = $self->getAddressBook;
if ($self->get("shippingAddressId")) {
return $book->getAddress($self->get("shippingAddressId"));
}
my $address = $book->getDefaultAddress;
$self->update({shippingAddressId=>$address->getId});
return $address;
}
#-------------------------------------------------------------------
@ -533,6 +556,10 @@ The unique id for a shipping address attached to this cart.
The unique id of the configured shipping driver that will be used to ship these goods.
=head4 posUserId
The ID of a user being checked out, if they're being checked out by a cashier.
=cut
sub update {
@ -541,7 +568,7 @@ sub update {
WebGUI::Error::InvalidParam->throw(error=>"Need a properties hash ref.");
}
my $id = id $self;
foreach my $field (qw(shippingAddressId shipperId)) {
foreach my $field (qw(shippingAddressId posUserId shipperId)) {
$properties{$id}{$field} = (exists $newProperties->{$field}) ? $newProperties->{$field} : $properties{$id}{$field};
}
$self->session->db->setRow("cart","cartId",$properties{$id});
@ -616,6 +643,31 @@ sub www_continueShopping {
#-------------------------------------------------------------------
=head2 www_lookupPosUser ( )
Adds a Point of Sale user to the cart.
=cut
sub www_lookupPosUser {
my $self = shift;
my $session = $self->session;
my $email = $session->form->get('posEmail','email');
my $user = WebGUI::User->newByEmail($session, $email);
unless (defined $user) {
$user = WebGUI::User->newByUsername($session, $email);
unless (defined $user) {
$user = WebGUI::User->new($session, "new");
$user->username($email);
$user->profileField('email', $email);
}
}
$self->update({posUserId=>$user->userId});
return $self->www_view;
}
#-------------------------------------------------------------------
=head2 www_removeItem ( )
Remove an item from the cart and then display the cart again.
@ -756,7 +808,7 @@ sub www_view {
my $address = eval { $self->getShippingAddress };
if (WebGUI::Error->caught("WebGUI::Error::ObjectNotFound")) {
# choose another address cuz we've got a problem
$self->update({shippingAddressId=>""});
$self->update({shippingAddressId=>''});
}
# if there is no shipping address we can't check out
@ -782,13 +834,22 @@ sub www_view {
$var{shippingPrice} = $self->formatCurrency($var{shippingPrice});
}
# POS variables
$var{isCashier} = WebGUI::Shop::Admin->new($session)->isCashier;
$var{posLookupForm} = WebGUI::Form::email($session, {name=>"posEmail"})
.WebGUI::Form::submit($session, {value=>$i18n->get('search for email'),
extras=>q|onclick="this.form.method.value='lookupPosUser';this.form.submit;"|});
my $posUser = $self->getPosUser;
$var{posUsername} = $posUser->username;
$var{posUserId} = $posUser->userId;
# calculate price adjusted for in-store credit
$var{totalPrice} = $var{subtotalPrice} + $var{shippingPrice} + $var{tax};
my $credit = WebGUI::Shop::Credit->new($session);
my $credit = WebGUI::Shop::Credit->new($session, $posUser->userId);
$var{inShopCreditAvailable} = $credit->getSum;
$var{inShopCreditDeduction} = $credit->calculateDeduction($var{totalPrice});
$var{totalPrice} = $self->formatCurrency($var{totalPrice} + $var{inShopCreditDeduction});
$var{totalPrice} = $self->formatCurrency($var{totalPrice} + $var{inShopCreditDeduction});
# render the cart
my $template = WebGUI::Asset::Template->new($session, $session->setting->get("shopCartTemplateId"));
return $session->style->userStyle($template->process(\%var));

View file

@ -105,7 +105,18 @@ Optionally supply this variable which will set the payment address to this addre
sub www_getCredentials {
my ($self, $addressId) = @_;
my $session = $self->session;
$addressId = $session->form->process('addressId') if ($addressId eq "");
# Process address from address book if passed
$addressId = $session->form->process( 'addressId' );
my $address;
if ( $addressId ) {
$address = eval{ $self->getAddress( $addressId ) };
}
else {
$address = $self->getCart->getShippingAddress;
}
my $billingAddressHtml = $address->getHtmlFormatted;
# Generate the json string that defines where the address book posts the selected address
my $callbackParams = {
url => $session->url->page,
@ -126,18 +137,11 @@ sub www_getCredentials {
. WebGUI::Form::submit( $session, { value => 'Choose billing address' } )
. WebGUI::Form::formFooter( $session);
# Get billing address
my $billingAddress = eval { $self->getAddress($addressId) };
my $billingAddressHtml;
if ($billingAddress) {
$billingAddressHtml = $billingAddress->getHtmlFormatted;
}
# Generate 'Proceed' button
my $proceedButton = WebGUI::Form::formHeader( $session )
. $self->getDoFormTags('pay')
. WebGUI::Form::hidden($session, {name=>"addressId", value=>$addressId})
. WebGUI::Form::hidden($session, {name=>"addressId", value=>$address->getId})
. WebGUI::Form::submit( $session, { value => 'Pay' } )
. WebGUI::Form::formFooter( $session);

View file

@ -15,6 +15,7 @@ use WebGUI::Shop::AddressBook;
use WebGUI::Shop::Credit;
use WebGUI::Shop::TransactionItem;
use WebGUI::Shop::Pay;
use WebGUI::User;
=head1 NAME
@ -154,8 +155,14 @@ sub create {
WebGUI::Error::InvalidObject->throw(expected=>"WebGUI::Session", got=>(ref $session), error=>"Need a session.");
}
my $transactionId = $session->id->generate;
$session->db->write('insert into transaction (transactionId, userId, username, dateOfPurchase) values (?,?,?,now())',
[$transactionId, $session->user->userId, $session->user->username]);
my $cashier = $session->user;
my $posUser = $cashier;
my $cart = $properties->{cart};
if (defined $cart) {
$posUser = $cart->getPosUser;
}
$session->db->write('insert into transaction (transactionId, userId, username, cashierUserId, dateOfPurchase) values (?,?,?,?,now())',
[$transactionId, $posUser->userId, $posUser->username, $cashier->userId]);
my $self = $class->new($session, $transactionId);
$self->update($properties);
return $self;
@ -917,6 +924,7 @@ sub www_view {
}
$output .= q{</div>};
}
my $cashier = WebGUI::User->new($session, $transaction->get('cashierUserId'));
$output .= q{
<table class="transactionDetail">
<tr>
@ -931,6 +939,9 @@ sub www_view {
<tr>
<th>}. $i18n->get("username") .q{</th><td><a href="}.$url->page('op=editUser;uid='.$transaction->get('userId')).q{">}. $transaction->get('username') .q{</a></td>
</tr>
<tr>
<th>}. $i18n->get("cashier") .q{</th><td><a href="}.$url->page('op=editUser;uid='.$cashier->userId).q{">}. $cashier->username .q{</a></td>
</tr>
<tr>
<th>}. $i18n->get("amount") .q{</th><td><b>}. sprintf("%.2f", $transaction->get('amount')) .q{</b></td>
</tr>
@ -1121,7 +1132,7 @@ sub www_viewMy {
unless (defined $transaction) {
$transaction = $class->new($session, $session->form->get('transactionId'));
}
return $session->insufficient unless ($transaction->get('userId') eq $session->user->userId);
return $session->privilege->insufficient unless ($transaction->get('userId') eq $session->user->userId || WebGUI::Shop::Admin->new($session)->isCashier);
my $i18n = WebGUI::International->new($session, 'Shop');
my ($style, $url) = $session->quick(qw(style url));
my %var = (

View file

@ -9,6 +9,36 @@ our $I18N = {
context => q|vendor label|,
},
'cashier' => {
message => q|Cashier|,
lastUpdated => 0,
context => q|transaction label|,
},
'order for' => {
message => q|Order For|,
lastUpdated => 0,
context => q|cart label, as in "This is an order for John Smith"|,
},
'search for email' => {
message => q|Search for Email Address|,
lastUpdated => 0,
context => q|cart button label|,
},
'who is a cashier' => {
message => q|Who is a cashier?|,
lastUpdated => 0,
context => q|shop admin setting|,
},
'who is a cashier help' => {
message => q|Cashiers are able to make purchases on behalf of another user by typing the email address of the user into the cart.|,
lastUpdated => 0,
context => q|help for shop admin setting|,
},
'organization' => {
message => q|Organization|,
lastUpdated => 0,
@ -309,6 +339,12 @@ our $I18N = {
context => q|a help description|,
},
'defaultButton help' => {
message => q|A button that will allow the user to set an address as a default.|,
lastUpdated => 0,
context => q|a help description|,
},
'deleteButton help' => {
message => q|A button that will allow the user to delete an existing address.|,
lastUpdated => 0,
@ -765,6 +801,12 @@ our $I18N = {
context => q|a button in the address book|
},
'default' => {
message => q|Set Default|,
lastUpdated => 0,
context => q|a button in the address book|
},
'edit' => {
message => q|Edit|,
lastUpdated => 0,