paypal_tran_id varchar(255) null,
+ freight_tracking varchar(255) not null default '',
+
primary key (id),
index order_cchash(ccNumberHash),
index order_userId(userId, orderDate)
use Carp 'confess';
@ISA = qw(BSE::DB);
-our $VERSION = "1.000";
+our $VERSION = "1.001";
use vars qw($VERSION $MAX_CONNECTION_AGE);
Orders => 'select * from orders',
getOrderByPkey => 'select * from orders where id = ?',
getOrderItemByOrderId => 'select * from order_item where orderId = ?',
- addOrder => 'insert orders values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
- replaceOrder => 'replace orders values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
+ addOrder => 'insert orders values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
+ replaceOrder => 'replace orders values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
addOrderItem => 'insert order_item values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
replaceOrderItem => 'replace order_item values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
getOrderByUserId => 'select * from orders where userId = ?',
require BSE::TB::AuditLog;
- $opts{actor} ||= $self->user;
+ $opts{actor} ||= $self->user || "U";
return BSE::TB::AuditLog->log(%opts);
}
@ISA = qw/Squirrel::Row/;
use Carp 'confess';
-our $VERSION = "1.001";
+our $VERSION = "1.002";
sub columns {
return qw/id
ccStatus2 ccTranId complete delivOrganization billOrganization
delivStreet2 billStreet2 purchase_order shipping_method
shipping_name shipping_trace
- paypal_token paypal_tran_id/;
+ paypal_token paypal_tran_id freight_tracking/;
}
sub defaults {
shipping_method => '',
shipping_name => '',
shipping_trace => undef,
+ freight_tracking => "",
);
}
@ISA = qw(Squirrel::Table);
use BSE::TB::Order;
-our $VERSION = "1.000";
+our $VERSION = "1.002";
sub rowClass {
return 'BSE::TB::Order';
}
+# shipping methods when we don't automate shipping
+sub dummy_shipping_methods {
+ my $cfg = BSE::Cfg->single;
+
+ my %ship = $cfg->entriesCS("dummy shipping methods");
+ my @ship;
+ for my $key (sort { $ship{$a} cmp $ship{$b} } keys %ship) {
+ my $name = $key;
+ $ship{$key} =~ /,(.*)/ and $name = $1;
+
+ push @ship, { id => $key, name => $name };
+ }
+
+ unshift @ship,
+ {
+ id => "",
+ name => "(None selected)",
+ };
+
+ return @ship;
+}
+
1;
use BSE::TB::Images;
use Articles;
use BSE::Sort;
-use BSE::Util::Tags qw(tag_hash);
+use BSE::Util::Tags qw(tag_hash tag_error_img);
use BSE::Util::Iterate;
use BSE::WebUtil 'refresh_to_admin';
use BSE::Util::HTML qw(:default popup_menu);
use BSE::Arrows;
use BSE::Shop::Util qw(:payment order_item_opts nice_options);
-our $VERSION = "1.001";
+our $VERSION = "1.004";
my %actions =
(
order_filled => 'shop_order_filled',
order_paid => 'shop_order_paid',
order_unpaid => 'shop_order_unpaid',
+ order_save => 'shop_order_save',
product_detail => '',
product_list => '',
paypal_refund => 'bse_shop_order_refund_paypal',
return escape_html($value);
}
+sub tag_shipping_method_select {
+ my ($self, $order) = @_;
+
+ my @methods = BSE::TB::Orders->dummy_shipping_methods;
+
+ return popup_menu
+ (
+ -name => "shipping_name",
+ -values => [ map $_->{id}, @methods ],
+ -labels => { map { $_->{id} => $_->{name} } @methods },
+ -id => "shipping_name",
+ -default => $order->shipping_name,
+ );
+}
+
sub req_order_detail {
- my ($class, $req, $message) = @_;
+ my ($class, $req, $errors) = @_;
my $cgi = $req->cgi;
my $id = $cgi->param('id');
if ($id and
my $order = BSE::TB::Orders->getByPkey($id)) {
- $message ||= $cgi->param('m') || '';
+ my $message = $req->message($errors);
my @lines = $order->items;
my @products = map { Products->getByPkey($_->{productId}) } @lines;
my $line_index = -1;
my @options;
my $option_index = -1;
my $siteuser;
+ my $it = BSE::Util::Iterate->new;
+
my %acts;
%acts =
(
- BSE::Util::Tags->basic(\%acts, $cgi, $req->cfg),
- BSE::Util::Tags->admin(\%acts, $req->cfg),
- BSE::Util::Tags->secure($req),
+ $req->admin_tags,
item => sub { escape_html($lines[$line_index]{$_[0]}) },
iterate_items_reset => sub { $line_index = -1 },
iterate_items =>
option => sub { escape_html($options[$option_index]{$_[0]}) },
ifOptions => sub { @options },
options => sub { nice_options(@options) },
- message => sub { $message },
+ message => $message,
+ error_img => [ \&tag_error_img, $errors ],
siteuser => [ \&tag_siteuser, $order, \$siteuser, ],
+ $it->make
+ (
+ single => "shipping_method",
+ plural => "shipping_methods",
+ code => [ dummy_shipping_methods => "BSE::TB::Orders" ],
+ ),
+ shipping_method_select =>
+ [ tag_shipping_method_select => $class, $order ],
);
return $req->dyn_response('admin/order_detail', \%acts);
}
}
+=item order_save
+
+Make changes to an order, only a limited set of fields can be changed.
+
+Parameters:
+
+=over
+
+=item *
+
+id - id of the order. Required.
+
+=item *
+
+shipping_method - if automated shipping calculations are disabled, the
+id of the dummy shipping method to set for the order.
+
+=item *
+
+freight_tracking - the freight tracking code for the shipment.
+
+=back
+
+Requires csrfp token C<shop_order_save>.
+
+=cut
+
+sub req_order_save {
+ my ($self, $req) = @_;
+
+ $req->check_csrf("shop_order_save")
+ or return $self->req_product_list($req, "Bad or missing csrf token: " . $req->csrf_error);
+
+ my $cgi = $req->cgi;
+ my $id = $cgi->param("id");
+ $id && $id =~ /^[0-9]+$/
+ or return $self->req_product_list($req, "No order id supplied");
+
+ my $order = BSE::TB::Orders->getByPkey($id)
+ or return $self->req_product_list($req, "No such order id");
+
+ my %errors;
+ my $save = 0;
+
+ my $new_freight_tracking = 0;
+ my $code = $cgi->param("freight_tracking");
+ if (defined $code && $code ne $order->freight_tracking) {
+ $order->set_freight_tracking($code);
+ ++$new_freight_tracking;
+ ++$save;
+ }
+
+ my $new_shipping_name = 0;
+ unless ($req->cfg->entry("shop", "shipping", 0)) {
+ my $shipping_name = $cgi->param("shipping_name");
+ if (defined $shipping_name
+ && $shipping_name ne $order->shipping_name) {
+ my @ship = BSE::TB::Orders->dummy_shipping_methods();
+ my ($entry) = grep $_->{id} eq $shipping_name, @ship;
+ if ($entry) {
+ $order->set_shipping_name($entry->{id});
+ $order->set_shipping_method($entry->{name});
+ ++$new_shipping_name;
+ ++$save;
+ }
+ else {
+ $errors{shipping_method} = "msg:bse/admin/shop/saveorder/badmethod:$shipping_name";
+ }
+ }
+ }
+
+ keys %errors
+ and return $self->req_order_detail($req, \%errors);
+
+ if ($save) {
+ $order->save;
+ $req->flash("msg:bse/admin/shop/saveorder/saved");
+
+ if ($new_freight_tracking) {
+ $req->audit
+ (
+ component => "shopadmin:orders:saveorder",
+ object => $order,
+ msg => "New freight tracking code set: '" . $order->freight_tracking . "'",
+ level => "info",
+ );
+ }
+ if ($new_shipping_name) {
+ $req->audit
+ (
+ component => "shopadmin:orders:saveorder",
+ object => $order,
+ msg => "New shippping method set: '" . $order->shipping_name . "/" . $order->shipping_method . "'",
+ level => "info",
+ );
+ }
+ }
+ else {
+ $req->flash("msg:bse/admin/shop/saveorder/nochanges");
+ }
+
+ my $url = $cgi->param("r") || $req->url("shopadmin", { a_order_detail => 1, id => $order->id });
+
+ return $req->get_refresh($url);
+}
+
#####################
# utilities
# perhaps some of these belong in a class...
id: bse/admin/edit/uplabelsect
description: label in parent list to make article a section
+id: bse/admin/shop/
+description: Shop Administration
+
+id: bse/admin/shop/saveorder/
+description: Save changes to an order
+
+id: bse/admin/shop/saveorder/saved
+description: Displayed on a successful save with some changes
+
+id: bse/admin/shop/saveorder/nochanges
+description: Displayed on a save that makes no changes
+
+id: bse/admin/shop/saveorder/badmethod
+description: Invalid shipping method
+
id: test/
description: <<TEXT
Test category
---
-# VERSION=1.000
+# VERSION=1.001
# defaults for the following
language_code: en
priority: 0
id: bse/admin/message/badmultiline
message: Message $1:s may contain only a single line of text
+id: bse/admin/shop/saveorder/saved
+message: Order saved successfully
+
+id: bse/admin/shop/saveorder/nochanges
+message: No changes to save
+
+id: bse/admin/shop/saveorder/badmethod
+message: Unknown shipping method '$1:s'
+
id: bse/shop/cart/empty
message: Cart emptied
</tr>
<:iterator begin items:>
<tr>
- <td width="100%"><:ifOr [ifEq [item productId] -1] [ifEq [product id] ""]:><:item title:> (product deleted)<:or:><a href="<:script:>?product_detail=1&id=<:product id:>"><:product
+ <td width="100%"><:ifOr [ifEq [item productId] -1] [ifEq [product id] ""]:><:item title:> (product deleted)<:or:><a href="<:adminurl shopadmin product_detail 1 id [product id]:>"><:product
title:></a><:eif:> <:options:></td>
<td align=center nowrap><:item units:></td>
<td align=right nowrap><:money item price:></td>
<td align=right nowrap><:extension gst:></td>
</tr>
<:iterator end items:>
+<:if Cfg shop shipping:>
<:if Order shipping_name:>
<tr>
- <td colspan=3 align=right>
+ <td colspan=3>
<:if Eq [order shipping_name] "contact":>
<b>Contact customer to make shipping arrangements</b>
<:or Eq:>
-Shipping via <:order shipping_method:>:
-<:eif Eq:>
+Shipping via <:order shipping_method:>
+<:eif Eq:>,
+ <form method="post" action="<:adminurl shopadmin a_order_save 1:>">
+ <input type="hidden" name="id" value="<:order id:>" />
+ <:csrfp shop_order_save hidden:>
+ <label>tracking code: <input type="text" name="freight_tracking" value="<:order freight_tracking:>" /></label>
+ <input type="submit" name="a_order_save" value="Save" />
+ </form>
+
</td>
<td align=right nowrap><:money order shipping_cost:></td>
<td> </td>
<td align=right nowrap></td>
</tr>
<:or Order:><:eif Order:>
+<:or Cfg:>
+<:eif Cfg:>
<tr bgcolor="#FFFFFF">
<td colspan=3 align=right>Total:</td>
<td align=right nowrap><:money order total:></td>
<td> </td>
<td align=right nowrap><:money order gst:></td>
</tr>
+<:if Cfg shop shipping:><:or Cfg:>
+<tr>
+ <td colspan="3">
+ <form method="post" action="<:adminurl shopadmin a_order_save 1:>">
+ <input type="hidden" name="id" value="<:order id:>" />
+ <:csrfp shop_order_save hidden:>
+ <label>Shipping method: <:shipping_method_select:></label>
+ <label>tracking code: <input type="text" name="freight_tracking" value="<:order freight_tracking:>" /></label>
+ <input type="submit" name="a_order_save" value="Save" />
+ </form>
+ </td>
+ <td colspan="5"></td>
+</tr>
+<:eif Cfg:>
</table>
<:switch:>
<:case Eq [order paidFor] "0":>
Column shipping_trace;text;YES;NULL;
Column paypal_token;varchar(255);YES;NULL;
Column paypal_tran_id;varchar(255);YES;NULL;
+Column freight_tracking;varchar(255);NO;;
Index PRIMARY;1;[id]
Index order_cchash;0;[ccNumberHash]
Index order_userId;0;[userId;orderDate]