0.15_07 commit r0_15_07
authorTony Cook <tony@develop-help.com>
Tue, 25 Jan 2005 04:33:53 +0000 (04:33 +0000)
committertony <tony@45cb6cf1-00bc-42d2-bb5a-07f51df49f94>
Tue, 25 Jan 2005 04:33:53 +0000 (04:33 +0000)
17 files changed:
MANIFEST
Makefile
schema/bse.sql
site/cgi-bin/admin/shopadmin.pl
site/cgi-bin/modules/BSE/DB/Mysql.pm
site/cgi-bin/modules/BSE/Edit/Article.pm
site/cgi-bin/modules/BSE/Formatter.pm
site/cgi-bin/modules/BSE/Shop/Util.pm
site/cgi-bin/modules/BSE/TB/Order.pm
site/cgi-bin/modules/BSE/UI/Shop.pm
site/cgi-bin/modules/BSE/Util/Tags.pm
site/cgi-bin/modules/Generate.pm
site/cgi-bin/modules/Generate/Article.pm
site/docs/bse.pod
site/templates/admin/order_detail.tmpl
site/templates/admin/order_list_incomplete.tmpl [new file with mode: 0644]
test.cfg

index 7f00c2d..fe42ad9 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -264,6 +264,7 @@ site/templates/admin/interestemail.tmpl
 site/templates/admin/order_detail.tmpl
 site/templates/admin/order_list.tmpl
 site/templates/admin/order_list_filled.tmpl
+site/templates/admin/order_list_incomplete.tmpl
 site/templates/admin/order_list_unfilled.tmpl
 # site/templates/admin/product_custom.tmpl
 site/templates/admin/product_detail.tmpl
index 77b6889..cad01e3 100755 (executable)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-VERSION=0.15_06
+VERSION=0.15_07
 DISTNAME=bse-$(VERSION)
 DISTBUILD=$(DISTNAME)
 DISTTAR=../$(DISTNAME).tar
index beafa94..2cdf6e1 100644 (file)
@@ -261,6 +261,9 @@ create table orders (
   -- the ORDER_NUMBER for Inpho
   ccTranId varchar(40) not null default '',
 
+  -- order was completed by the customer
+  complete integer not null default 1,
+
   primary key (id),
   index order_cchash(ccNumberHash),
   index order_userId(userId, orderDate)
index 3c87aab..bfc4a6b 100755 (executable)
@@ -44,6 +44,7 @@ my %what_to_do =
    order_list_filled=>\&order_list_filled,
    order_list_unfilled=>\&order_list_unfilled,
    order_list_unpaid => \&order_list_unpaid,
+   order_list_incomplete => \&order_list_incomplete,
    order_detail=>\&order_detail,
    order_filled=>\&order_filled,
    product_detail=>\&product_detail,
@@ -526,7 +527,8 @@ sub order_list {
     or return product_list($req, "You don't have access to the order list");
     
   my $orders = BSE::TB::Orders->new;
-  my @orders = sort { $b->{orderDate} cmp $a->{orderDate} } $orders->all;
+  my @orders = sort { $b->{orderDate} cmp $a->{orderDate} } 
+    grep $_->{complete}, $orders->all;
   my $template = $req->cgi->param('template');
   unless (defined $template && $template =~ /^\w+$/) {
     $template = 'order_list';
@@ -543,7 +545,7 @@ sub order_list_filled {
 
   my $orders = BSE::TB::Orders->new;
   my @orders = sort { $b->{orderDate} cmp $a->{orderDate} } 
-    grep $_->{filled} && $_->{paidFor}, $orders->all;
+    grep $_->{complete} && $_->{filled} && $_->{paidFor}, $orders->all;
 
   order_list_low($req, 'order_list_filled', 'Order list - Filled orders', @orders);
 }
@@ -556,7 +558,7 @@ sub order_list_unfilled {
 
   my $orders = BSE::TB::Orders->new;
   my @orders = sort { $b->{orderDate} cmp $a->{orderDate} } 
-    grep !$_->{filled} && $_->{paidFor}, $orders->all;
+    grep $_->{complete} && !$_->{filled} && $_->{paidFor}, $orders->all;
 
   order_list_low($req, 'order_list_unfilled', 'Order list - Unfilled orders', 
                 @orders);
@@ -570,12 +572,26 @@ sub order_list_unpaid {
 
   my $orders = BSE::TB::Orders->new;
   my @orders = sort { $b->{orderDate} cmp $a->{orderDate} } 
-    grep !$_->{paidFor}, $orders->all;
+    grep $_->{complete} && !$_->{paidFor}, $orders->all;
 
   order_list_low($req, 'order_list_unpaid', 'Order list - Incomplete orders', 
                 @orders);
 }
 
+sub order_list_incomplete {
+  my ($req) = @_;
+
+  $req->user_can('shop_order_list')
+    or return product_list($req, "You don't have access to the order list");
+
+  my $orders = BSE::TB::Orders->new;
+  my @orders = sort { $b->{orderDate} cmp $a->{orderDate} } 
+    grep !$_->{complete}, $orders->all;
+
+  order_list_low($req, 'order_list_incomplete', 'Order list - Incomplete orders', 
+                @orders);
+}
+
 sub cart_item_opts {
   my ($cart_item, $product) = @_;
 
index e6f1f1a..94c7744 100644 (file)
@@ -84,10 +84,11 @@ SQL
    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,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
    getOrderByUserId => 'select * from orders where userId = ?',
+   deleteOrdersItems => 'delete from order_item where orderId = ?',
 
    getOrderItemByProductId => 'select * from order_item where productId = ?',
 
index 863ba07..4c3ce67 100644 (file)
@@ -2663,6 +2663,7 @@ my %defaults =
    expire => $Constants::D_99,
    listed => 1,
    keyword => '',
+   body => '<maximum of 64Kb>',
   );
 
 sub default_value {
@@ -2696,7 +2697,7 @@ sub default_value {
   }
   
   if ($col eq 'summaryLength') {
-    my $parent = $article->{parentid} != -1 
+    my $parent = defined $article->{parentid} && $article->{parentid} != -1 
       && Articles->getByPkey($article->{parentid}); 
 
     $parent and return $parent->{summaryLength};
index 8764ce7..b3a8e90 100644 (file)
@@ -6,7 +6,7 @@ use Carp 'confess';
 use base 'DevHelp::Formatter';
 
 sub new {
-  my ($class, $gen, $acts, $articles, $abs_urls, $rauto_images, $images) = @_;
+  my ($class, $gen, $acts, $articles, $abs_urls, $rauto_images, $images, $templater) = @_;
 
   my $self = $class->SUPER::new;
 
@@ -16,6 +16,7 @@ sub new {
   $self->{abs_urls} = $abs_urls;
   $self->{auto_images} = $rauto_images;
   $self->{images} = $images;
+  $self->{templater} = $templater;
   #$self->{level} = $level;
 
   my $cfg = $gen->{cfg};
@@ -106,7 +107,7 @@ sub embed {
   my ($self, $name, $templateid, $maxdepth) = @_;
 
   $self->{gen}->_embed_low($self->{acts}, $self->{articles}, $name,
-                          $templateid, $maxdepth);
+                          $templateid, $maxdepth, $self->{templater});
 }
 
 sub _get_article {
index c7e2d93..592e1f0 100644 (file)
@@ -65,7 +65,7 @@ sub shop_cart_tags {
      ifOptions => sub { @options },
      options => sub { nice_options(@options) },
      custom_class($cfg)
-     ->checkout_actions($acts, $cart, $cart_prods, $session->{custom}, $q),
+     ->checkout_actions($acts, $cart, $cart_prods, $session->{custom}, $q, $cfg),
     );  
 }
 
index da7915a..8825dc0 100644 (file)
@@ -4,6 +4,7 @@ use strict;
 use Squirrel::Row;
 use vars qw/@ISA/;
 @ISA = qw/Squirrel::Row/;
+use Carp 'confess';
 
 sub columns {
   return qw/id
@@ -22,7 +23,7 @@ sub columns {
            siteuser_id affiliate_code shipping_cost
            delivMobile billMobile
            ccOnline ccSuccess ccReceipt ccStatus ccStatusText
-           ccStatus2 ccTranId/;
+           ccStatus2 ccTranId complete/;
 }
 
 =item siteuser
@@ -150,4 +151,13 @@ sub valid_payment_rules {
   return;
 }
 
+sub clear_items {
+  my ($self) = @_;
+
+  confess "Attempt to clear items on completed order $self->{id}"
+    if $self->{complete};
+  
+  BSE::DB->run(deleteOrdersItems => $self->{id});
+}
+
 1;
index ae88cf6..dadc2c6 100644 (file)
@@ -3,7 +3,8 @@ use strict;
 use base 'BSE::UI::Dispatch';
 use DevHelp::HTML;
 use BSE::Util::SQL qw(now_sqldate now_sqldatetime);
-use BSE::Shop::Util qw(need_logon shop_cart_tags payment_types nice_options cart_item_opts basic_tags);
+use BSE::Shop::Util qw(need_logon shop_cart_tags payment_types nice_options 
+                       cart_item_opts basic_tags);
 use BSE::CfgInfo qw(custom_class credit_card_class);
 use BSE::TB::Orders;
 use BSE::TB::OrderItems;
@@ -529,8 +530,24 @@ sub req_payment {
 
   my @data = @{$order_values}{@columns};
   shift @data;
-  my $order = BSE::TB::Orders->add(@data)
-    or die "Cannot add order";
+
+  my $order;
+  if ($session->{order_work}) {
+    $order = BSE::TB::Orders->getByPkey($session->{order_work});
+  }
+  if ($order) {
+    print STDERR "Recycling order $order->{id}\n";
+
+    my @allbutid = @columns;
+    shift @allbutid;
+    @{$order}{@allbutid} = @data;
+
+    $order->clear_items;
+  }
+  else {
+    $order = BSE::TB::Orders->add(@data)
+      or die "Cannot add order";
+  }
 
   my @dbitems;
   my %subscribing_to;
@@ -554,6 +571,8 @@ sub req_payment {
       $subscribing_to{$sub->{text_id}} = $sub;
     }
   }
+
+  $order->{ccOnline} = 0;
   
   my $ccprocessor = $cfg->entry('shop', 'cardprocessor');
   if ($paymentType == PAYMENT_CC && $ccprocessor) {
@@ -597,9 +616,12 @@ sub req_payment {
     $order->{ccStatusText}  = '';
     $order->{ccTranId}     = $result->{transactionid};
     $order->{paidFor}      = 1;
-    $order->save;
   }
 
+  # order complete
+  $order->{complete} = 1;
+  $order->save;
+
   # set the order displayed by orderdone
   $session->{order_completed} = $order->{id};
   $session->{order_completed_at} = time;
index e56ce61..3b7f5ad 100644 (file)
@@ -125,7 +125,7 @@ sub static {
        require Generate;
        my $gen = Generate->new(cfg=>$cfg);
        return $gen->format_body($acts, 'Articles', $value, 'tr',
-                               1, 0);
+                               1, 0, $templater);
      },
      nobodytext => [\&tag_nobodytext, $cfg ],
      ifEq =>
index d39bbe9..87d7c3c 100644 (file)
@@ -168,7 +168,7 @@ sub _make_html {
 }
 
 sub _embed_low {
-  my ($self, $acts, $articles, $what, $template, $maxdepth) = @_;
+  my ($self, $acts, $articles, $what, $template, $maxdepth, $templater) = @_;
 
   $maxdepth = $self->{maxdepth} 
     if !$maxdepth || $maxdepth > $self->{maxdepth};
@@ -187,7 +187,7 @@ sub _embed_low {
   my $id;
   if ($what !~ /^\d+$/) {
     # not an article id, assume there's an article here we can use
-    $id = $acts->{$what} && $acts->{$what}->('id');
+    $id = $acts->{$what} && $templater->perform($acts, $what, 'id');
     unless ($id && $id =~ /^\d+$/) {
       # save it for later
       defined $template or $template = "-";
@@ -279,7 +279,7 @@ sub _make_img {
 # replace markup, insert img tags
 sub format_body {
   my ($self, $acts, $articles, $body, $imagePos, $abs_urls, 
-      $auto_images, @images)  = @_;
+      $auto_images, $templater, @images)  = @_;
 
   return substr($body, 6) if $body =~ /^<html>/i;
 
@@ -287,7 +287,7 @@ sub format_body {
 
   my $formatter = BSE::Formatter->new($self, $acts, $articles,
                                      $abs_urls, \$auto_images,
-                                     \@images);
+                                     \@images, $templater);
 
   $body = $formatter->format($body);
 
@@ -434,9 +434,10 @@ sub baseActs {
      # for embedding the content from children and other sources
      ifEmbedded=> sub { $embedded },
      embed => sub {
-       my ($what, $template, $maxdepth) = split ' ', $_[0];
+       my ($args, $acts, $name, $templater) = @_;
+       my ($what, $template, $maxdepth) = split ' ', $args;
        undef $maxdepth if defined $maxdepth && $maxdepth !~ /^\d+/;
-       return $self->_embed_low($acts, $articles, $what, $template, $maxdepth);
+       return $self->_embed_low($acts, $articles, $what, $template, $maxdepth, $templater);
      },
      ifCanEmbed=> sub { $self->{depth} <= $self->{maxdepth} },
 
index 1bf6b63..39e0560 100644 (file)
@@ -32,13 +32,6 @@ sub edit_link {
   return "$CGI_URI/admin/add.pl?id=$id";
 }
 
-# sub make_article_body {
-#   my ($self, $acts, $articles, $article, $auto_images, @images) = @_;
-
-#   return $self->format_body($acts, $articles, $abs_urls, 
-#                          $auto_images, @images);
-# }
-
 sub link_to_form {
   my ($self, $link, $text, $target) = @_;
 
@@ -332,9 +325,10 @@ sub baseActs {
 
      # transform the article or response body (entities, images)
      body=>sub {
+       my ($args, $acts, $funcname, $templater) = @_;
        return $self->format_body($acts, $articles, $article->{body},
                                 $article->{imagePos}, $abs_urls,
-                                !$had_image_tags, @images);
+                                !$had_image_tags, $templater, @images);
      },
 
      # used to display a navigation path of parent sections
index c896e7b..39f5090 100644 (file)
@@ -10,6 +10,50 @@ Maybe I'll add some other bits here.
 
 =head1 CHANGES
 
+=head2 0.15_07
+
+This release adds a new column to the orders table.  You will need to
+run the upgrade_mysql.pl script on existing installations.
+
+=over
+
+=item *
+
+product information is now available from the item tag on the final
+checkout page
+
+=item *
+
+another field has been added to the orders table to track the
+difference between an order that's been created for payment
+processing, and an order where it's been completed.
+
+The existing order lists filter out the incomplete orders.
+
+=item *
+
+if a user attempts and fails online credit card processing on an
+order, that order record (and hence number) is now re-used for the
+next attempt.  Note: if a user abandons an order after a failed
+attempt at online credit card processing then an incomplete order is
+left in the database.
+
+=item *
+
+added an order_list_incomplete target which lists only incomplete
+orders (for completeness...)
+
+=item *
+
+the order_detail template now flags incomplete orders and attempts to
+display credit card processing information.
+
+=item *
+
+the embed tag and embed[] markup didn't support newer style tags
+
+=back
+
 =head2 0.15_06
 
 Interim release with some minor fixes while I fiddle with trying to
index c6df8d4..ba0e215 100644 (file)
@@ -11,6 +11,7 @@
 <a href="/cgi-bin/admin/siteusers.pl?a_edit=1&amp;id=<:siteuser id:>&amp;_t=orders">Other member orders</a> |<:or:><:eif:>
 </p>
 <h2>Order details - No: #<:order id:></h2>
+<:ifOrder complete:><:or:><p><b><font size="+1">This order is incomplete and should not be filled.</font></b></p><:eif:>
 <table cellpadding="6" cellspacing="1" border="0">
   <tr> 
     <td align="left"><b>E-mail:</b></td>
 </td>
 </tr>
 </table>
-<:ifEq [order paymentType] "0":><p>Payment made by credit card.</p><:or:><:eif:>
-<:ifEq [order paymentType] "1":><p>Payment will be made by cheque.</p><:or:><:eif:>
-<:ifEq [order paymentType] "2":><p>Contact the customer to arrange for payment.</p><:or:><:eif:>
+<:switch:>
+<:case order ccOnline:>
+<p>This was processed as an online credit card transaction.</p>
+<:if Order ccSuccess:>
+<p>This transaction was <b>SUCCESSFUL</b>.</p>
+<table>
+<tr><th>Receipt Number:</th><td><:order ccReceipt:></td></tr>
+<:ifOrder ccTranId:>
+<tr><th>Transaction Id:</th><td><:order ccTranId:></td></tr>
+<:or:><:eif:>
+</table>
+<:or Order:>
+<p>This transaction <b>FAILED</b>.</p>
+<table>
+<tr><th>Status:</th><td><:order ccStatus:></td>
+<tr><th>Error:</th><td><:order ccStatusText:></td>
+<:ifOrder ccStatus2:>
+<tr><th>More status</th><td><:order ccStatus2:></td>
+<:or:><:eif:>
+</table>
+<:eif Order:>
+<:case Eq [order paymentType] "0":><p>Payment made by credit card.  Credit card details can be found in the encrypted email you received when the customer made the order.</p>
+<:case Eq [order paymentType] "1":><p>Payment will be made by cheque.</p>
+<:case Eq [order paymentType] "2":><p>Contact the customer to arrange for payment.</p>
+<:endswitch:>
 <:include custom/order_detail_payment.include optional:>
 <:if Order filled:>
 <p>This order was filled on <:date order whenFilled:> by <:order whoFilled:>.</p>
 <:or Order:>
-<p>This order hasn't been filled yet.  <a href="/cgi-bin/admin/shopadmin.pl?id=<:order id:>&order_filled=Yep&filled=1&detail=1">Mark order filled</a>.</p>
+<:ifOrder complete:>
+<p>This order hasn't been filled yet.  <a href="/cgi-bin/admin/shopadmin.pl?id=<:order id:>&order_filled=Yep&filled=1&detail=1">Mark order filled</a>.</p><:or:><:eif:>
 <:eif Order:>
 </body></html>
diff --git a/site/templates/admin/order_list_incomplete.tmpl b/site/templates/admin/order_list_incomplete.tmpl
new file mode 100644 (file)
index 0000000..7193012
--- /dev/null
@@ -0,0 +1,59 @@
+<html><head><title>Incomplete order list - Shop administration</title>
+<link rel="stylesheet" href="/css/admin.css">
+</head>
+<body>
+<h1>Shop Administration</h1>
+<p>| <a href="/cgi-bin/admin/menu.pl">Admin menu</a> | <a href="<:script:>">Manage catalogs</a> 
+  | <a href="<:script:>?order_list=1&template=order_list_filled">Filled orders</a> [ <:order_count filter= filled!=0:> ]
+  | <a href="<:script:>?order_list=1">All orders</a>  [ <:order_count filter= id!=0:> ] |</p>
+<h2>Order list - Incomplete orders</h2>
+
+<p><b>These orders had failures during online credit card processing
+and the user did not go back to fix the problem.  These orders should
+not be processes and are visible only for completeness.</b></p>
+
+<table bgcolor="#000000" cellpadding="0" cellspacing="0" border="0" width="100%" class="table">
+  <tr>
+<td>
+      <table border=0 cellpadding="6" cellspacing="1" width="100%">
+        <tr bgcolor="#FFFFFF"> 
+          <th>Id</th>
+          <th width="100%">Name</th>
+          <th>Date</th>
+          <th>Total</th>
+          <th>GST</th>
+          <th>Details</th>
+        </tr>
+        <tr bgcolor="#FFFFFF"> 
+          <td colspan="6"> 
+            <form action="<:script:>" method="POST">
+              <input type="hidden" name="order_list2" value="1">
+              <input type="hidden" name="template2" value="order_list_incomplete">
+              From date: 
+              <input type="text" size="10" name="from2" value="<:cgi from:>">
+              To date: 
+              <input type="text" size="10" name="to2" value="<:cgi to:>">
+              <input type=submit value="Filter orders" name="submit2">
+            </form>
+          </td>
+        </tr>
+        <:iterator begin orders filter= filled==0 :> 
+        <tr bgcolor="#FFFFFF"> 
+          <td align="center" nowrap><a href="<:script:>?id=<:order id:>&order_detail=1"><:order 
+            id:></a></td>
+          <td width="100%"><:order delivFirstName:> <:order delivLastName:> <:ifOrder 
+            userId:><font color="#CCCCCC">&#8212; (logged in)</font><:or:><:eif:></td>
+          <td nowrap><:date order orderDate:></td>
+          <td align=right nowrap>$<:money order total:></td>
+          <td align=right nowrap>$<:money order gst:></td>
+          <td nowrap> <a href="<:script:>?id=<:order id:>&order_detail=1">Order 
+            details </a></td>
+        </tr>
+        <:iterator end orders:> 
+      </table>
+</td>
+</tr>
+</table>
+<p><font size="-1">BSE Release <:release:></font></p>
+</body>
+</html>
index d3f528a..66af458 100644 (file)
--- a/test.cfg
+++ b/test.cfg
@@ -103,13 +103,13 @@ test formmail validation.company_description=Organization
 test formmail validation.company_required=0
 
 site.secureadmin=1
-article defaults.title=<set the article title>
-article defaults.body=<set the body>
-product defaults.title=<set the product title>
-catalog defaults.title=<set the catalog title>
+#article defaults.title=<set the article title>
+#article defaults.body=<set the body>
+#product defaults.title=<set the product title>
+#catalog defaults.title=<set the catalog title>
 
-#shop.cardprocessor=DevHelp::Payments::Test
-shop.cardprocessor=DevHelp::Payments::Inpho
+shop.cardprocessor=DevHelp::Payments::Test
+#shop.cardprocessor=DevHelp::Payments::Inpho
 inpho.user=theowww
 inpho.password=s1tz^^mD1
 inpho.test=1