move Product/s modules to more appropriate location
authorAdrian Oldham <adriann@visualthought.com.au>
Mon, 1 Sep 2014 00:40:49 +0000 (10:40 +1000)
committerAdrian Oldham <adriann@visualthought.com.au>
Mon, 1 Sep 2014 11:34:10 +0000 (21:34 +1000)
35 files changed:
MANIFEST
site/cgi-bin/modules/BSE/API.pm
site/cgi-bin/modules/BSE/Cart.pm
site/cgi-bin/modules/BSE/Dynamic/Product.pm
site/cgi-bin/modules/BSE/Edit/Product.pm
site/cgi-bin/modules/BSE/Generate/Catalog.pm
site/cgi-bin/modules/BSE/Generate/Product.pm
site/cgi-bin/modules/BSE/Importer/Target/Article.pm
site/cgi-bin/modules/BSE/Importer/Target/Product.pm
site/cgi-bin/modules/BSE/ProductImportXLS.pm
site/cgi-bin/modules/BSE/Shipping.pm
site/cgi-bin/modules/BSE/Shop/Util.pm
site/cgi-bin/modules/BSE/TB/Article.pm
site/cgi-bin/modules/BSE/TB/Order.pm
site/cgi-bin/modules/BSE/TB/OrderItem.pm
site/cgi-bin/modules/BSE/TB/Product.pm [new file with mode: 0644]
site/cgi-bin/modules/BSE/TB/Products.pm [new file with mode: 0644]
site/cgi-bin/modules/BSE/TB/Seminar.pm
site/cgi-bin/modules/BSE/TB/SiteCommon.pm
site/cgi-bin/modules/BSE/TB/Subscription.pm
site/cgi-bin/modules/BSE/UI/AdminShop.pm
site/cgi-bin/modules/BSE/UI/Shop.pm
site/cgi-bin/modules/BSE/UI/User.pm
site/cgi-bin/modules/BSE/UserReg.pm
site/cgi-bin/modules/BSE/Util/DynamicTags.pm
site/cgi-bin/modules/BSE/Variables.pm
site/cgi-bin/modules/Product.pm [deleted file]
site/cgi-bin/modules/Products.pm [deleted file]
site/cgi-bin/modules/SiteUser.pm
site/templates/admin/edit_prodopts.tmpl
site/util/getpcode.pl
site/util/update_title_summary.pl
t/050-local/040-catalog.t
t/050-local/050-dyncat.t
t/data/known_pod_issues.txt

index b62ca94..1a19797 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -349,8 +349,8 @@ site/cgi-bin/modules/BSE/Generate/Product.pm
 site/cgi-bin/modules/BSE/Generate/Subscription.pm
 site/cgi-bin/modules/OtherParent.pm
 site/cgi-bin/modules/OtherParents.pm
-site/cgi-bin/modules/Product.pm
-site/cgi-bin/modules/Products.pm
+site/cgi-bin/modules/BSE/TB/Product.pm
+site/cgi-bin/modules/BSE/TB/Products.pm
 site/cgi-bin/modules/SiteUser.pm
 site/cgi-bin/modules/SiteUsers.pm
 site/cgi-bin/modules/Squirrel/GPG.pm
index f5cd75a..1d1ec50 100644 (file)
@@ -10,7 +10,7 @@ use Carp qw(confess croak);
 use Fcntl qw(:seek);
 use Cwd;
 
-our $VERSION = "1.009";
+our $VERSION = "1.010";
 
 =head1 NAME
 
@@ -182,7 +182,7 @@ sub bse_make_product {
   my $cfg = delete $opts{cfg}
     or confess "cfg option missing";
 
-  require Products;
+  require BSE::TB::Products;
 
   defined $opts{title} && length $opts{title}
     or confess "Missing title option\n";
@@ -204,9 +204,9 @@ sub bse_make_product {
 
   _set_dynamic($cfg, \%opts);
 
-  my @cols = Product->columns;
+  my @cols = BSE::TB::Product->columns;
   shift @cols;
-  my $product = Products->add(@opts{@cols});
+  my $product = BSE::TB::Products->add(@opts{@cols});
 
   require BSE::Edit::Product;
   _finalize_article($cfg, $product, 'BSE::Edit::Product');
index 89b288c..74468f8 100644 (file)
@@ -2,7 +2,7 @@ package BSE::Cart;
 use strict;
 use Scalar::Util;
 
-our $VERSION = "1.009";
+our $VERSION = "1.010";
 
 =head1 NAME
 
@@ -723,8 +723,8 @@ sub _product {
 
   my $product = $self->{products}{$id};
   unless ($product) {
-    require Products;
-    $product = Products->getByPkey($id)
+    require BSE::TB::Products;
+    $product = BSE::TB::Products->getByPkey($id)
       or die "No product $id\n";
     # FIXME
     if ($product->generator ne "BSE::Generate::Product") {
@@ -997,8 +997,8 @@ sub AUTOLOAD {
   our $AUTOLOAD;
   (my $name = $AUTOLOAD) =~ s/^.*:://;
   unless (%product_keys) {
-    require Products;
-    %product_keys = map { $_ => 1 } Product->columns;
+    require BSE::TB::Products;
+    %product_keys = map { $_ => 1 } BSE::TB::Product->columns;
   }
 
   if ($product_keys{$name}) {
index 8238b34..4ebda62 100644 (file)
@@ -1,14 +1,14 @@
 package BSE::Dynamic::Product;
 use strict;
 use base 'BSE::Dynamic::Article';
-use Products;
+use BSE::TB::Products;
 
-our $VERSION = "1.000";
+our $VERSION = "1.001";
 
 sub get_real_article {
   my ($self, $article) = @_;
 
-  Products->getByPkey($article->{id});
+  BSE::TB::Products->getByPkey($article->{id});
 }
 
 sub tags {
index 1640dd1..2deead0 100644 (file)
@@ -1,7 +1,7 @@
 package BSE::Edit::Product;
 use strict;
 use base 'BSE::Edit::Article';
-use Products;
+use BSE::TB::Products;
 use HTML::Entities;
 use BSE::Template;
 use BSE::Util::Iterate;
@@ -10,7 +10,7 @@ use BSE::CfgInfo 'product_options';
 use BSE::Util::Tags qw(tag_hash tag_article);
 use constant PRODUCT_CUSTOM_FIELDS_CFG => "product custom fields";
 
-our $VERSION = "1.014";
+our $VERSION = "1.015";
 
 =head1 NAME
 
@@ -187,7 +187,7 @@ sub _save_price_tiers {
   $req->user_can('edit_field_edit_retailPrice', $article)
     or return;
 
-  my @tiers = Products->pricing_tiers;
+  my @tiers = BSE::TB::Products->pricing_tiers;
   my %prices;
   for my $tier (@tiers) {
     my $key = "tier_price_" . $tier->id;
@@ -202,7 +202,7 @@ sub save_columns {
   my ($self, $table_object) = @_;
 
   my @cols = $self->SUPER::save_columns($table_object);
-  my @tiers = Products->pricing_tiers;
+  my @tiers = BSE::TB::Products->pricing_tiers;
   if (@tiers) {
     push @cols, "save_pricing_tiers";
     push @cols, map { "tier_price_" . $_->id } @tiers;
@@ -334,7 +334,7 @@ sub low_edit_tags {
      (
       single => "price_tier",
       plural => "price_tiers",
-      code => [ pricing_tiers => "Products" ],
+      code => [ pricing_tiers => "BSE::TB::Products" ],
       data => \@tiers,
       store => \$price_tier,
      ),
@@ -425,7 +425,7 @@ sub _validate_common {
   }
 
   if ($data->{save_pricing_tiers}) {
-    my @tiers = Products->pricing_tiers;
+    my @tiers = BSE::TB::Products->pricing_tiers;
     for my $tier (@tiers) {
       my $key = "tier_price_" . $tier->id;
       my $value = $data->{$key};
@@ -492,13 +492,13 @@ sub possible_parents {
 sub table_object {
   my ($self, $articles) = @_;
 
-  'Products';
+  'BSE::TB::Products';
 }
 
 sub get_article {
   my ($self, $articles, $article) = @_;
 
-  return Products->getByPkey($article->{id});
+  return BSE::TB::Products->getByPkey($article->{id});
 }
 
 sub default_link_path {
index 571a4b6..79544ac 100644 (file)
@@ -1,10 +1,10 @@
 package BSE::Generate::Catalog;
 
-our $VERSION = "1.005";
+our $VERSION = "1.006";
 
 use strict;
 use BSE::Generate;
-use Products;
+use BSE::TB::Products;
 use base 'BSE::Generate::Article';
 use BSE::Template;
 use Constants qw($CGI_URI $ADMIN_URI);
@@ -117,7 +117,7 @@ sub tag_ifAnyProductOptions {
 sub baseActs {
   my ($self, $articles, $acts, $article, $embedded) = @_;
 
-  my $products = Products->new;
+  my $products = BSE::TB::Products->new;
   my @products = sort { $b->{displayOrder} <=> $a->{displayOrder} }
     grep $_->{listed} && $_->{parentid} == $article->{id}, $products->all;
   my $product_index = -1;
@@ -139,8 +139,8 @@ sub baseActs {
   my @allprods = grep UNIVERSAL::isa($_->{generator}, 'BSE::Generate::Product'), 
     @allkids;
   for (@allprods) {
-    unless ($_->isa('Product')) {
-      $_ = Products->getByPkey($_->{id});
+    unless ($_->isa('BSE::TB::Product')) {
+      $_ = BSE::TB::Products->getByPkey($_->{id});
     }
   }
   my @allcats = grep UNIVERSAL::isa($_->{generator}, 'BSE::Generate::Catalog'), 
index 170196e..c57ec21 100644 (file)
@@ -1,7 +1,7 @@
 package BSE::Generate::Product;
 use strict;
 use BSE::Generate::Article;
-use Products;
+use BSE::TB::Products;
 use BSE::TB::Images;
 use base qw(BSE::Generate::Article);
 use Constants qw(:shop $CGI_URI $ADMIN_URI);
@@ -9,7 +9,7 @@ use Carp qw(confess);
 use BSE::Util::HTML;
 use BSE::Util::Tags qw(tag_article);
 
-our $VERSION = "1.002";
+our $VERSION = "1.003";
 
 sub edit_link {
   my ($self, $id) = @_;
@@ -19,7 +19,7 @@ sub edit_link {
 sub generate {
   my ($self, $article, $articles) = @_;
 
-  my $product = Products->getByPkey($article->{id});
+  my $product = BSE::TB::Products->getByPkey($article->{id});
   return $self->SUPER::generate($product, $articles);
 }
 
@@ -48,8 +48,8 @@ HTML
 sub baseActs {
   my ($self, $articles, $acts, $product, $embedded) = @_;
 
-  unless ($product->isa('Product')) {
-    $product = Products->getByPkey($product->{id});
+  unless ($product->isa('BSE::TB::Product')) {
+    $product = BSE::TB::Products->getByPkey($product->{id});
   }
 
   my @stepcats = $product->step_parents();
@@ -99,7 +99,7 @@ sub visible {
 sub get_real_article {
   my ($self, $article) = @_;
 
-  return Products->getByPkey($article->{id});
+  return BSE::TB::Products->getByPkey($article->{id});
 }
 
 1;
index e3fd37f..7f8962d 100644 (file)
@@ -3,10 +3,10 @@ use strict;
 use base 'BSE::Importer::Target::Base';
 use BSE::API qw(bse_make_article bse_add_image bse_add_step_parent);
 use BSE::TB::Articles;
-use Products;
+use BSE::TB::Products;
 use OtherParents;
 
-our $VERSION = "1.009";
+our $VERSION = "1.010";
 
 =head1 NAME
 
index e83037f..f49e27f 100644 (file)
@@ -3,12 +3,12 @@ use strict;
 use base 'BSE::Importer::Target::Article';
 use BSE::API qw(bse_make_product bse_make_catalog bse_add_image);
 use BSE::TB::Articles;
-use Products;
+use BSE::TB::Products;
 use BSE::TB::ProductOptions;
 use BSE::TB::ProductOptionValues;
 use BSE::TB::PriceTiers;
 
-our $VERSION = "1.007";
+our $VERSION = "1.008";
 
 =head1 NAME
 
@@ -30,7 +30,7 @@ BSE::Importer::Target::Product - import target for products
   reset_prodopts=1
 
   # done by the importer
-  my $target = BSE::Importer::Target::Product->new
+  my $target = BSE::Importer::Target::BSE::TB::Product->new
      (importer => $importer, opts => \%opts)
   ...
   $target->start($imp);
@@ -209,10 +209,10 @@ sub find_leaf {
 
   my $leaf;
   if ($self->{code_field} eq "id") {
-    $leaf = Products->getByPkey($leaf_id);
+    $leaf = BSE::TB::Products->getByPkey($leaf_id);
   }
   else {
-    ($leaf) = Products->getBy($self->{code_field}, $leaf_id)
+    ($leaf) = BSE::TB::Products->getBy($self->{code_field}, $leaf_id)
       or return;
   }
 
@@ -332,7 +332,7 @@ sub validate_make_leaf {
   my ($self, $importer, $entry) = @_;
 
   if (defined $entry->{product_code} && $entry->{product_code} ne '') {
-    my $other = Products->getBy(product_code => $entry->{product_code});
+    my $other = BSE::TB::Products->getBy(product_code => $entry->{product_code});
     $other
       and die "Duplicate product_code with product ", $other->id, "\n";
   }
index d4c39f9..3d2a615 100644 (file)
@@ -3,10 +3,10 @@ use strict;
 use Spreadsheet::ParseExcel;
 use BSE::API qw(bse_make_product bse_make_catalog bse_add_image);
 use BSE::TB::Articles;
-use Products;
+use BSE::TB::Products;
 use Config;
 
-our $VERSION = "1.002";
+our $VERSION = "1.003";
 
 sub new {
   my ($class, $cfg, $profile, %opts) = @_;
@@ -177,7 +177,7 @@ sub process {
       $entry{parentid} = $self->_find_cat(\%cat_cache, $callback, $self->{parent}, @cats);
       my $product;
       if ($self->{codes}) {
-       $product = Products->getBy(product_code => $entry{product_code});
+       $product = BSE::TB::Products->getBy(product_code => $entry{product_code});
       }
       if ($product) {
        @{$product}{keys %entry} = values %entry;
index 81325b5..5dad253 100644 (file)
@@ -3,7 +3,7 @@ use strict;
 use Carp qw(confess);
 use BSE::CfgInfo qw(load_class);
 
-our $VERSION = "1.002";
+our $VERSION = "1.003";
 
 sub get_couriers {
     my ($class, $cfg, $wanted) = @_;
@@ -35,13 +35,13 @@ sub get_couriers {
 sub package_order {
     my ($class, $cfg, $order, $items) = @_;
 
-    require Products;
+    require BSE::TB::Products;
     my $total_weight = 0;
     my $total_length = 0;
     my $total_width = 0;
     my $total_height = 0;
     foreach my $item (@$items) {
-        my $product = Products->getByPkey($item->{productId});
+        my $product = BSE::TB::Products->getByPkey($item->{productId});
         my $number = $item->{units};
 
         my $weight = $product->{weight};
index a2ceb32..a6b1f12 100644 (file)
@@ -7,7 +7,7 @@ use vars qw(@ISA @EXPORT_OK);
                 payment_types order_item_opts
  PAYMENT_CC PAYMENT_CHEQUE PAYMENT_CALLME PAYMENT_MANUAL PAYMENT_PAYPAL/;
 
-our $VERSION = "1.010";
+our $VERSION = "1.011";
 
 our %EXPORT_TAGS =
   (
@@ -257,7 +257,7 @@ sub load_order_fields {
   my @products;
   my $today = now_sqldate();
   for my $item (@cart) {
-    my $product = Products->getByPkey($item->{productId});
+    my $product = BSE::TB::Products->getByPkey($item->{productId});
     # double check that it's still a valid product
     if (!$product) {
       $$error = "Product $item->{productId} not found";
index 8740819..2edcbb7 100644 (file)
@@ -8,7 +8,7 @@ use vars qw/@ISA/;
 @ISA = qw/Squirrel::Row BSE::TB::SiteCommon BSE::TB::TagOwner/;
 use Carp 'confess';
 
-our $VERSION = "1.024";
+our $VERSION = "1.025";
 
 =head1 NAME
 
@@ -198,8 +198,8 @@ sub update_dynamic {
   my $dynamic = $cfg->entry('basic', 'all_dynamic', 0) ? 1 : 0;
 
   if (!$dynamic && $self->generator =~ /\bCatalog\b/) {
-    require Products;
-    my @tiers = Products->pricing_tiers;
+    require BSE::TB::Products;
+    my @tiers = BSE::TB::Products->pricing_tiers;
     @tiers and $dynamic = 1;
   }
 
index 3395026..d28d1f4 100644 (file)
@@ -7,7 +7,7 @@ use vars qw/@ISA/;
 use Carp 'confess';
 use BSE::Shop::PaymentTypes;
 
-our $VERSION = "1.024";
+our $VERSION = "1.025";
 
 sub columns {
   return qw/id
@@ -206,8 +206,8 @@ sub paid_files {
 sub products {
   my ($self) = @_;
 
-  require Products;
-  Products->getSpecial(orderProducts=>$self->{id});
+  require BSE::TB::Products;
+  BSE::TB::Products->getSpecial(orderProducts=>$self->{id});
 }
 
 sub valid_fields {
@@ -521,9 +521,9 @@ sub _tags {
        $current_item
         or return '* only usable in items *';
 
-       require Products;
+       require BSE::TB::Products;
        my $id = $current_item->productId;
-       $products{$id} ||= Products->getByPkey($id);
+       $products{$id} ||= BSE::TB::Products->getByPkey($id);
 
        my $product = $products{$id}
         or return '';
@@ -545,9 +545,9 @@ sub _tags {
        $current_item
         or return '* only usable in items *';
 
-       require Products;
+       require BSE::TB::Products;
        my $id = $current_item->productId;
-       $products{$id} ||= Products->getByPkey($id);
+       $products{$id} ||= BSE::TB::Products->getByPkey($id);
 
        my $product = $products{$id}
         or return '';
index 492212a..5a309cc 100644 (file)
@@ -5,7 +5,7 @@ use Squirrel::Row;
 use vars qw/@ISA/;
 @ISA = qw/Squirrel::Row/;
 
-our $VERSION = "1.003";
+our $VERSION = "1.004";
 
 sub columns {
   return qw/id productId orderId units price wholesalePrice gst options
@@ -41,8 +41,8 @@ sub product {
 
   $self->productId == -1
     and return;
-  require Products;
-  return Products->getByPkey($self->productId);
+  require BSE::TB::Products;
+  return BSE::TB::Products->getByPkey($self->productId);
 }
 
 sub option_hashes {
diff --git a/site/cgi-bin/modules/BSE/TB/Product.pm b/site/cgi-bin/modules/BSE/TB/Product.pm
new file mode 100644 (file)
index 0000000..988f03a
--- /dev/null
@@ -0,0 +1,294 @@
+package BSE::TB::Product;
+use strict;
+# represents a product from the database
+use BSE::TB::Articles;
+use vars qw/@ISA/;
+@ISA = qw/BSE::TB::Article/;
+
+our $VERSION = "1.005";
+
+# subscription_usage values
+use constant SUBUSAGE_START_ONLY => 1;
+use constant SUBUSAGE_RENEW_ONLY => 2;
+use constant SUBUSAGE_EITHER => 3;
+
+sub columns {
+  return ($_[0]->SUPER::columns(), 
+         qw/articleId description leadTime retailPrice wholesalePrice gst options
+             subscription_id subscription_period subscription_usage
+             subscription_required product_code weight length height width/ );
+}
+
+sub bases {
+  return { articleId=>{ class=>'BSE::TB::Article'} };
+}
+
+sub subscription_required {
+  my ($self) = @_;
+
+  my $id = $self->{subscription_required};
+  return if $id == -1;
+
+  require BSE::TB::Subscriptions;
+  return BSE::TB::Subscriptions->getByPkey($id);
+}
+
+sub subscription {
+  my ($self) = @_;
+
+  my $id = $self->{subscription_id};
+  return if $id == -1;
+
+  require BSE::TB::Subscriptions;
+  return BSE::TB::Subscriptions->getByPkey($id);
+}
+
+sub is_renew_sub_only {
+  my ($self) = @_;
+
+  $self->{subscription_usage} == SUBUSAGE_RENEW_ONLY;
+}
+
+sub is_start_sub_only {
+  my ($self) = @_;
+
+  $self->{subscription_usage} == SUBUSAGE_START_ONLY;
+}
+
+sub _get_cfg_options {
+  my ($cfg) = @_;
+
+  require BSE::CfgInfo;
+  my $avail_options = BSE::CfgInfo::product_options($cfg);
+  my @options;
+  for my $name (keys %$avail_options) {
+    my $rawopt = $avail_options->{$name};
+    my %opt =
+      (
+       id => $name,
+       name => $rawopt->{desc},
+       default => $rawopt->{default} || '',
+      );
+    my @values;
+    for my $value (@{$rawopt->{values}}) {
+      my $label = $rawopt->{labels}{$value} || $value;
+      push @values,
+       bless
+         {
+          id => $value,
+          value => $label,
+         }, "BSE::CfgProductOptionValue";
+    }
+    $opt{values} = \@values;
+    push @options, bless \%opt, "BSE::CfgProductOption";
+  }
+
+  return @options;
+}
+
+sub _get_prod_options {
+  my ($product, $cfg, @values) = @_;
+
+  my %all_cfg_opts = map { $_->id => $_ } _get_cfg_options($cfg);
+  my @opt_names = split /,/, $product->{options};
+
+  my @cfg_opts = map $all_cfg_opts{$_}, @opt_names;
+  my @db_opts = grep $_->enabled, $product->db_options;
+  my @all_options = ( @cfg_opts, @db_opts );
+
+  push @values, '' while @values < @all_options;
+
+  my $index = 0;
+  my @sem_options;
+  for my $opt (@all_options) {
+    my @opt_values = $opt->values;
+    my %opt_values = map { $_->id => $_->value } @opt_values;
+    my $result_opt = 
+      {
+       id => $opt->key,
+       name => $opt->key,
+       desc => $opt->name,
+       value => $values[$index],
+       type => $opt->type,
+       labels => \%opt_values,
+       default => $opt->default_value,
+      };
+    my $value = $values[$index];
+    if (defined $value) {
+      $result_opt->{values} = [ map $_->id, @opt_values ],
+      $result_opt->{display} = $opt_values{$values[$index]};
+    }
+    push @sem_options, $result_opt;
+    ++$index;
+  }
+
+  return @sem_options;
+}
+
+sub option_descs {
+  my ($self, $cfg, $rvalues) = @_;
+
+  $rvalues or $rvalues = [ ];
+
+  return $self->_get_prod_options($cfg, @$rvalues);
+}
+
+sub db_options {
+  my ($self) = @_;
+
+  require BSE::TB::ProductOptions;
+  return BSE::TB::ProductOptions->getBy2
+    (
+     [ product_id => $self->{id} ],
+     { order => "display_order" }
+    );
+}
+
+sub remove {
+  my ($self, $cfg) = @_;
+
+  # remove any product options
+  for my $opt ($self->db_options) {
+    $opt->remove;
+  }
+
+  # mark any order line items to "anonymize" them
+  BSE::DB->run(bseMarkProductOrderItemsAnon => $self->id);
+
+  # remove any wishlist items
+  BSE::DB->run(bseRemoveProductFromWishlists => $self->id);
+
+  # remove any tiered prices
+  BSE::DB->run(bseRemoveProductPrices => $self->id);
+
+  return $self->SUPER::remove($cfg);
+}
+
+sub has_sale_files {
+  my ($self) = @_;
+
+  my ($row) = BSE::DB->query(bseProductHasSaleFiles => $self->{id});
+
+  return $row->{have_sale_files};
+}
+
+sub prices {
+  my ($self) = @_;
+
+  require BSE::TB::PriceTierPrices;
+  my @prices = BSE::TB::PriceTierPrices->getBy(product_id => $self->id);
+}
+
+=item set_prices($prices)
+
+Set tiered pricing for the product.
+
+I<$prices> is a hashref mapping tier ids to prices in cents.
+
+If a tier doesn't have a price in I<$prices> it's removed from the
+product.
+
+=cut
+
+sub set_prices {
+  my ($self, $prices) = @_;
+
+  my %current = map { $_->tier_id => $_ } $self->prices;
+  for my $tier_id (keys %$prices) {
+    my $current = delete $current{$tier_id};
+    if ($current) {
+      $current->set_retailPrice($prices->{$tier_id});
+      $current->save;
+    }
+    else {
+      BSE::TB::PriceTierPrices->make
+         (
+          tier_id => $tier_id,
+          product_id => $self->id,
+          retailPrice => $prices->{$tier_id},
+         );
+    }
+  }
+
+  # remove any spares
+  for my $price (values %current) {
+    $price->remove;
+  }
+}
+
+=item price(user => $user, date => $sql_date)
+
+=item price(user => $user)
+
+Return the retail price depending on the user and date
+and optionally the tier object (in list context).
+
+If no tier matches then the undef is returned at the tier object.
+
+=cut
+
+sub price {
+  my ($self, %opts) = @_;
+
+  my $user = delete $opts{user};
+  my $date = delete $opts{date} || BSE::Util::SQL::now_sqldate();
+  my @tiers = BSE::TB::Products->pricing_tiers;
+  my %prices = map { $_->tier_id => $_ } $self->prices;
+
+  my $price;
+  my $found_tier;
+  for my $tier (@tiers) {
+    if ($prices{$tier->id}
+       && $tier->match($user, $date)) {
+      $price = $prices{$tier->id}->retailPrice;
+      $found_tier = $tier;
+      last;
+    }
+  }
+
+  defined $price or $price = $self->retailPrice;
+
+  return wantarray ? ( $price, $found_tier ) : $price;
+}
+
+sub update_dynamic {
+  my ($self, $cfg) = @_;
+
+  my @tiers = BSE::TB::Products->pricing_tiers;
+  if (@tiers) {
+    $self->set_cached_dynamic(1);
+    return;
+  }
+
+  return $self->SUPER::update_dynamic($cfg);
+}
+
+sub tableClass {
+  return "BSE::TB::Products";
+}
+
+package BSE::CfgProductOption;
+use strict;
+
+sub id { $_[0]{id} }
+
+sub key {$_[0]{id} } # same as id for config options
+
+sub type { "select" }
+
+sub name { $_[0]{name} }
+
+sub values {
+  @{$_[0]{values}}
+}
+
+sub default_value { $_[0]{default} }
+
+package BSE::CfgProductOptionValue;
+use strict;
+
+sub id { $_[0]{id} }
+
+sub value { $_[0]{value} }
+
+1;
diff --git a/site/cgi-bin/modules/BSE/TB/Products.pm b/site/cgi-bin/modules/BSE/TB/Products.pm
new file mode 100644 (file)
index 0000000..135e902
--- /dev/null
@@ -0,0 +1,81 @@
+package BSE::TB::Products;
+use strict;
+use Squirrel::Table;
+use vars qw(@ISA $VERSION);
+@ISA = qw(Squirrel::Table BSE::TB::TagOwners);
+use BSE::TB::Product;
+
+our $VERSION = "1.004";
+
+sub rowClass {
+  return 'BSE::TB::Product';
+}
+
+sub all_visible_children {
+  my ($self, $id) = @_;
+
+  require OtherParents;
+  my @normal_prods = BSE::TB::Products->visible_children($id);
+  my @step_prods = BSE::TB::Products->visible_step_children($id);
+  
+  my %order =
+    (
+     ( map { $_->{id} => $_->{displayOrder} } @normal_prods ),
+     ( map 
+       { 
+        $_->{childId} => $_->{parentDisplayOrder}
+       } OtherParents->getBy(parentId => $id)
+     )
+    );
+
+  my %kids = map { $_->{id} => $_ } @step_prods, @normal_prods;
+
+  return @kids{ sort { $order{$b} <=> $order{$a} } keys %kids };
+}
+
+sub all_visible_product_tags {
+  my ($self, $id) = @_;
+
+  require BSE::TB::Tags;
+  require BSE::TB::TagMembers;
+  return
+    {
+     tags => [ BSE::TB::Tags->getSpecial(allprods => $id, $id) ],
+     members => [ BSE::TB::TagMembers->getSpecial(allprods => $id, $id) ],
+    };
+}
+
+*all_visible_products = \&all_visible_children;
+
+sub visible_children {
+  my ($class, $id) = @_;
+
+  use BSE::Util::SQL qw/now_sqldate/;
+  my $today = now_sqldate();
+  
+  return BSE::TB::Products->getSpecial(visible_children_of => $id, $today);
+}
+
+sub visible_step_children {
+  my ($class, $id) = @_;
+
+  use BSE::Util::SQL qw/now_sqldate/;
+  my $today = now_sqldate();
+  
+  return BSE::TB::Products->getSpecial(visibleStep => $id, $today);
+}
+
+{
+  my $tiers;
+  sub pricing_tiers {
+    unless ($tiers) {
+      require BSE::TB::PriceTiers;
+      $tiers = [ sort { $a->display_order <=> $b->display_order }
+                BSE::TB::PriceTiers->all ];
+    }
+
+    return @$tiers;
+  }
+}
+
+1;
index 30e9274..7fd6ffb 100644 (file)
@@ -1,12 +1,12 @@
 package BSE::TB::Seminar;
 use strict;
 # represents a seminar from the database
-use Product;
+use BSE::TB::Product;
 use vars qw/@ISA/;
-@ISA = qw/Product/;
+@ISA = qw/BSE::TB::Product/;
 use BSE::Util::SQL qw(now_sqldatetime);
 
-our $VERSION = "1.000";
+our $VERSION = "1.001";
 
 sub columns {
   return ($_[0]->SUPER::columns(), 
@@ -14,7 +14,7 @@ sub columns {
 }
 
 sub bases {
-  return { seminar_id=>{ class=>'Product'} };
+  return { seminar_id=>{ class=>'BSE::TB::Product'} };
 }
 
 sub sessions {
index 185cfec..508ead6 100644 (file)
@@ -2,7 +2,7 @@ package BSE::TB::SiteCommon;
 use strict;
 use Carp qw(confess);
 
-our $VERSION = "1.020";
+our $VERSION = "1.021";
 
 =head1 NAME
 
@@ -55,9 +55,9 @@ sub visible_stepkids {
   my $today = now_sqldate();
 
   if ($self->{generator} eq 'BSE::Generate::Catalog') {
-    require 'Products.pm';
+    require BSE::TB::Products;
 
-    return Products->getSpecial('visibleStep', $self->{id}, $today);
+    return BSE::TB::Products->getSpecial('visibleStep', $self->{id}, $today);
   }
   else {
     return BSE::TB::Articles->getSpecial('visibleStepKids', $self->{id}, $today);
@@ -102,15 +102,15 @@ sub all_visible_kid_tags {
 sub all_visible_products {
   my ($self) = @_;
 
-  require Products;
-  Products->all_visible_children($self->{id});
+  require BSE::TB::Products;
+  BSE::TB::Products->all_visible_children($self->{id});
 }
 
 sub all_visible_product_tags {
   my ($self) = @_;
 
-  require Products;
-  Products->all_visible_product_tags($self->{id});
+  require BSE::TB::Products;
+  BSE::TB::Products->all_visible_product_tags($self->{id});
 }
 
 sub all_visible_catalogs {
index 5835f93..0a4180a 100644 (file)
@@ -4,7 +4,7 @@ use Squirrel::Row;
 use vars qw/@ISA/;
 @ISA = qw/Squirrel::Row/;
 
-our $VERSION = "1.000";
+our $VERSION = "1.001";
 
 sub columns {
   return qw/subscription_id text_id title description max_lapsed/;
@@ -84,8 +84,8 @@ sub order_item_count {
 sub dependent_products {
   my ($self) = @_;
 
-  require Products;
-  Products->getSpecial(subscriptionDependent => $self->{subscription_id}, 
+  require BSE::TB::Products;
+  BSE::TB::Products->getSpecial(subscriptionDependent => $self->{subscription_id}, 
                       $self->{subscription_id});
 }
 
index ba22a15..f9119c8 100644 (file)
@@ -1,8 +1,8 @@
 package BSE::UI::AdminShop;
 use strict;
 use base 'BSE::UI::AdminDispatch';
-use Products;
-use Product;
+use BSE::TB::Products;
+use BSE::TB::Product;
 use BSE::TB::Orders;
 use BSE::TB::OrderItems;
 use BSE::Template;
@@ -21,7 +21,7 @@ use BSE::CfgInfo qw(cfg_dist_image_uri);
 use BSE::Util::SQL qw/now_sqldate sql_to_date date_to_sql sql_date sql_datetime/;
 use BSE::Util::Valid qw/valid_date/;
 
-our $VERSION = "1.026";
+our $VERSION = "1.027";
 
 my %actions =
   (
@@ -82,7 +82,7 @@ sub embedded_catalog {
 
   my $session = $req->session;
   use POSIX 'strftime';
-  my $products = Products->new;
+  my $products = BSE::TB::Products->new;
   my @list;
   if ($session->{showstepkids}) {
     my @allkids = $catalog->allkids;
@@ -215,7 +215,7 @@ sub req_product_list {
     $session->{showstepkids} = $cgi->param('showstepkids');
   }
   exists $session->{showstepkids} or $session->{showstepkids} = 1;
-  my $products = Products->new;
+  my $products = BSE::TB::Products->new;
   my @products = sort { $b->{displayOrder} <=> $a->{displayOrder} }
     $products->getBy(parentid => $shopid);
   my $product_index;
@@ -308,7 +308,7 @@ sub req_product_detail {
   my $cgi = $req->cgi;
   my $id = $cgi->param('id');
   if ($id and
-      my $product = Products->getByPkey($id)) {
+      my $product = BSE::TB::Products->getByPkey($id)) {
     return product_form($req, $product, '', '', 'admin/product_detail');
   }
   else {
@@ -360,7 +360,7 @@ sub product_form {
   use OtherParents;
   # ugh
   my $realproduct;
-  $realproduct = UNIVERSAL::isa($product, 'Product') ? $product : Products->getByPkey($product->{id});
+  $realproduct = UNIVERSAL::isa($product, 'BSE::TB::Product') ? $product : BSE::TB::Products->getByPkey($product->{id});
   my @stepcats;
   @stepcats = OtherParents->getBy(childId=>$product->{id}) 
     if $product->{id};
@@ -806,7 +806,7 @@ sub req_order_detail {
       my $order = BSE::TB::Orders->getByPkey($id)) {
     my $message = $req->message($errors);
     my @lines = $order->items;
-    my @products = map { Products->getByPkey($_->{productId}) } @lines;
+    my @products = map { BSE::TB::Products->getByPkey($_->{productId}) } @lines;
     my $line_index = -1;
     my $product;
     my @options;
index 9922288..e8083bd 100644 (file)
@@ -9,7 +9,7 @@ use BSE::CfgInfo qw(custom_class credit_card_class bse_default_country);
 use BSE::TB::Orders;
 use BSE::TB::OrderItems;
 use BSE::Util::Tags qw(tag_error_img tag_hash tag_article);
-use Products;
+use BSE::TB::Products;
 use BSE::TB::Seminars;
 use DevHelp::Validate qw(dh_validate dh_validate_hash);
 use Digest::MD5 'md5_hex';
@@ -18,7 +18,7 @@ use BSE::Countries qw(bse_country_code);
 use BSE::Util::Secure qw(make_secret);
 use BSE::Template;
 
-our $VERSION = "1.045";
+our $VERSION = "1.046";
 
 =head1 NAME
 
@@ -758,7 +758,7 @@ sub req_remove_item {
   my @cart = @{$req->session->{cart}};
   if ($index >= 0 && $index < @cart) {
     my ($item) = splice(@cart, $index, 1);
-    my $product = Products->getByPkey($item->{productId});
+    my $product = BSE::TB::Products->getByPkey($item->{productId});
     $req->flash_notice("msg:bse/shop/cart/remove", [ $product ]);
   }
   $req->session->{cart} = \@cart;
@@ -1360,10 +1360,10 @@ sub req_orderdone {
   my $order = BSE::TB::Orders->getByPkey($id)
     or return $class->req_cart($req);
   my @items = $order->items;
-  my @products = map { Products->getByPkey($_->{productId}) } @items;
+  my @products = map { BSE::TB::Products->getByPkey($_->{productId}) } @items;
 
   my @item_cols = BSE::TB::OrderItem->columns;
-  my %copy_cols = map { $_ => 1 } Product->columns;
+  my %copy_cols = map { $_ => 1 } BSE::TB::Product->columns;
   delete @copy_cols{@item_cols};
   my @copy_cols = keys %copy_cols;
   my @showitems;
@@ -1786,7 +1786,7 @@ sub _build_items {
   my @cart = @{$req->session->{cart}}
     or return;
   my @items;
-  my @prodcols = Product->columns;
+  my @prodcols = BSE::TB::Product->columns;
   my @newcart;
   my $today = now_sqldate();
   for my $item ($cart->items) {
@@ -1983,7 +1983,7 @@ sub _validate_add_by_id {
   my $product;
   if ($addid) {
     $product = BSE::TB::Seminars->getByPkey($addid);
-    $product ||= Products->getByPkey($addid);
+    $product ||= BSE::TB::Products->getByPkey($addid);
   }
   unless ($product) {
     $$error = "Cannot find product $addid";
@@ -1999,7 +1999,7 @@ sub _validate_add_by_code {
   my $product;
   if (defined $code) {
     $product = BSE::TB::Seminars->getBy(product_code => $code);
-    $product ||= Products->getBy(product_code => $code);
+    $product ||= BSE::TB::Products->getBy(product_code => $code);
   }
   unless ($product) {
     $$error = "Cannot find product code $code";
@@ -2312,7 +2312,7 @@ sub _refresh_cart {
 
   for my $item (@$cart) {
     if (!$item->{user} || $item->{user} != $user->id) {
-      my $product = Products->getByPkey($item->{productId})
+      my $product = BSE::TB::Products->getByPkey($item->{productId})
        or next;
       my ($price, $tier) = $product->price(user => $user);
       $item->{price} = $price;
index 56e4afa..f33c4e2 100644 (file)
@@ -8,7 +8,7 @@ use BSE::Util::SQL qw/now_datetime/;
 use DevHelp::Date qw(dh_strftime_sql_datetime);
 use base 'BSE::UI::UserCommon';
 
-our $VERSION = "1.000";
+our $VERSION = "1.001";
 
 my %actions =
   (
@@ -88,8 +88,8 @@ sub req_info {
                             'orderfile', 'orderfiles', \$file_index),
      product =>
      sub {
-       require Products;
-       $product = Products->getByPkey($items[$item_index]{productId})
+       require BSE::TB::Products;
+       $product = BSE::TB::Products->getByPkey($items[$item_index]{productId})
         unless $product && $product->{id} == $items[$item_index]{productId};
        return tag_article($product, $cfg, $_[0]);
      },
@@ -791,8 +791,8 @@ sub _wishlist_product {
     $$rresult = $self->req_userpage($req, "Missing or invalid product id");
     return;
   }
-  require Products;
-  my $product = Products->getByPkey($product_id);
+  require BSE::TB::Products;
+  my $product = BSE::TB::Products->getByPkey($product_id);
   unless ($product) {
     $$rresult = $self->req_userpage($req, "Unknown product id");
     return;
index 2c8288e..35b51ec 100644 (file)
@@ -18,7 +18,7 @@ use BSE::Util::Iterate;
 use base 'BSE::UI::UserCommon';
 use Carp qw(confess);
 
-our $VERSION = "1.032";
+our $VERSION = "1.033";
 
 use constant MAX_UNACKED_CONF_MSGS => 3;
 use constant MIN_UNACKED_CONF_GAP => 2 * 24 * 60 * 60;
@@ -1301,8 +1301,8 @@ sub tag_order_item_options {
   my @options;
   if ($item->{options}) {
     # old order
-    require Products;
-    my $product = Products->getByPkey($item->{productId});
+    require BSE::TB::Products;
+    my $product = BSE::TB::Products->getByPkey($item->{productId});
 
     @options = order_item_opts($req, $item, $product);
   }
index 4877db8..e8eb83e 100644 (file)
@@ -7,7 +7,7 @@ use base 'BSE::TagFormats';
 use BSE::CfgInfo qw(custom_class);
 use BSE::Cart;
 
-our $VERSION = "1.027";
+our $VERSION = "1.028";
 
 =head1 NAME
 
@@ -1179,8 +1179,8 @@ sub tag_price {
 
   my $work;
   if ($id =~ /^[0-9]+$/) {
-    require Products;
-    $work = Products->getByPkey($id)
+    require BSE::TB::Products;
+    $work = BSE::TB::Products->getByPkey($id)
       or return "** unknown product $id **";
   }
   else {
@@ -1212,8 +1212,8 @@ Conditional to check if there's tiered pricing.
 =cut
 
 sub tag_ifTieredPricing {
-  require Products;
-  my @tiers = Products->pricing_tiers;
+  require BSE::TB::Products;
+  my @tiers = BSE::TB::Products->pricing_tiers;
 
   return scalar @tiers;
 }
@@ -1955,8 +1955,8 @@ sub _cart {
   my $total_cost = 0;
   my $total_units = 0;
   for my $item (@$cart) {
-    require Products;
-    my $product = Products->getByPkey($item->{productId});
+    require BSE::TB::Products;
+    my $product = BSE::TB::Products->getByPkey($item->{productId});
     my $extended = $product->price(user => scalar $self->{req}->siteuser) 
       * $item->{units};
     my $link = $product->link;
index 9b0c81b..3b178b7 100644 (file)
@@ -4,7 +4,7 @@ use Scalar::Util qw(blessed);
 use BSE::TB::Site;
 use BSE::Util::HTML;
 
-our $VERSION = "1.020";
+our $VERSION = "1.021";
 
 sub _base_variables {
   my ($self, %opts) = @_;
@@ -216,8 +216,8 @@ sub _variable_class {
   my $products;
   sub _products {
     unless ($products) {
-      require Products;
-      $products = _variable_class("Products");
+      require BSE::TB::Products;
+      $products = _variable_class("BSE::TB::Products");
     }
 
     return $products;
diff --git a/site/cgi-bin/modules/Product.pm b/site/cgi-bin/modules/Product.pm
deleted file mode 100644 (file)
index b3d0426..0000000
+++ /dev/null
@@ -1,294 +0,0 @@
-package Product;
-use strict;
-# represents a product from the database
-use BSE::TB::Articles;
-use vars qw/@ISA/;
-@ISA = qw/BSE::TB::Article/;
-
-our $VERSION = "1.004";
-
-# subscription_usage values
-use constant SUBUSAGE_START_ONLY => 1;
-use constant SUBUSAGE_RENEW_ONLY => 2;
-use constant SUBUSAGE_EITHER => 3;
-
-sub columns {
-  return ($_[0]->SUPER::columns(), 
-         qw/articleId description leadTime retailPrice wholesalePrice gst options
-             subscription_id subscription_period subscription_usage
-             subscription_required product_code weight length height width/ );
-}
-
-sub bases {
-  return { articleId=>{ class=>'BSE::TB::Article'} };
-}
-
-sub subscription_required {
-  my ($self) = @_;
-
-  my $id = $self->{subscription_required};
-  return if $id == -1;
-
-  require BSE::TB::Subscriptions;
-  return BSE::TB::Subscriptions->getByPkey($id);
-}
-
-sub subscription {
-  my ($self) = @_;
-
-  my $id = $self->{subscription_id};
-  return if $id == -1;
-
-  require BSE::TB::Subscriptions;
-  return BSE::TB::Subscriptions->getByPkey($id);
-}
-
-sub is_renew_sub_only {
-  my ($self) = @_;
-
-  $self->{subscription_usage} == SUBUSAGE_RENEW_ONLY;
-}
-
-sub is_start_sub_only {
-  my ($self) = @_;
-
-  $self->{subscription_usage} == SUBUSAGE_START_ONLY;
-}
-
-sub _get_cfg_options {
-  my ($cfg) = @_;
-
-  require BSE::CfgInfo;
-  my $avail_options = BSE::CfgInfo::product_options($cfg);
-  my @options;
-  for my $name (keys %$avail_options) {
-    my $rawopt = $avail_options->{$name};
-    my %opt =
-      (
-       id => $name,
-       name => $rawopt->{desc},
-       default => $rawopt->{default} || '',
-      );
-    my @values;
-    for my $value (@{$rawopt->{values}}) {
-      my $label = $rawopt->{labels}{$value} || $value;
-      push @values,
-       bless
-         {
-          id => $value,
-          value => $label,
-         }, "BSE::CfgProductOptionValue";
-    }
-    $opt{values} = \@values;
-    push @options, bless \%opt, "BSE::CfgProductOption";
-  }
-
-  return @options;
-}
-
-sub _get_prod_options {
-  my ($product, $cfg, @values) = @_;
-
-  my %all_cfg_opts = map { $_->id => $_ } _get_cfg_options($cfg);
-  my @opt_names = split /,/, $product->{options};
-
-  my @cfg_opts = map $all_cfg_opts{$_}, @opt_names;
-  my @db_opts = grep $_->enabled, $product->db_options;
-  my @all_options = ( @cfg_opts, @db_opts );
-
-  push @values, '' while @values < @all_options;
-
-  my $index = 0;
-  my @sem_options;
-  for my $opt (@all_options) {
-    my @opt_values = $opt->values;
-    my %opt_values = map { $_->id => $_->value } @opt_values;
-    my $result_opt = 
-      {
-       id => $opt->key,
-       name => $opt->key,
-       desc => $opt->name,
-       value => $values[$index],
-       type => $opt->type,
-       labels => \%opt_values,
-       default => $opt->default_value,
-      };
-    my $value = $values[$index];
-    if (defined $value) {
-      $result_opt->{values} = [ map $_->id, @opt_values ],
-      $result_opt->{display} = $opt_values{$values[$index]};
-    }
-    push @sem_options, $result_opt;
-    ++$index;
-  }
-
-  return @sem_options;
-}
-
-sub option_descs {
-  my ($self, $cfg, $rvalues) = @_;
-
-  $rvalues or $rvalues = [ ];
-
-  return $self->_get_prod_options($cfg, @$rvalues);
-}
-
-sub db_options {
-  my ($self) = @_;
-
-  require BSE::TB::ProductOptions;
-  return BSE::TB::ProductOptions->getBy2
-    (
-     [ product_id => $self->{id} ],
-     { order => "display_order" }
-    );
-}
-
-sub remove {
-  my ($self, $cfg) = @_;
-
-  # remove any product options
-  for my $opt ($self->db_options) {
-    $opt->remove;
-  }
-
-  # mark any order line items to "anonymize" them
-  BSE::DB->run(bseMarkProductOrderItemsAnon => $self->id);
-
-  # remove any wishlist items
-  BSE::DB->run(bseRemoveProductFromWishlists => $self->id);
-
-  # remove any tiered prices
-  BSE::DB->run(bseRemoveProductPrices => $self->id);
-
-  return $self->SUPER::remove($cfg);
-}
-
-sub has_sale_files {
-  my ($self) = @_;
-
-  my ($row) = BSE::DB->query(bseProductHasSaleFiles => $self->{id});
-
-  return $row->{have_sale_files};
-}
-
-sub prices {
-  my ($self) = @_;
-
-  require BSE::TB::PriceTierPrices;
-  my @prices = BSE::TB::PriceTierPrices->getBy(product_id => $self->id);
-}
-
-=item set_prices($prices)
-
-Set tiered pricing for the product.
-
-I<$prices> is a hashref mapping tier ids to prices in cents.
-
-If a tier doesn't have a price in I<$prices> it's removed from the
-product.
-
-=cut
-
-sub set_prices {
-  my ($self, $prices) = @_;
-
-  my %current = map { $_->tier_id => $_ } $self->prices;
-  for my $tier_id (keys %$prices) {
-    my $current = delete $current{$tier_id};
-    if ($current) {
-      $current->set_retailPrice($prices->{$tier_id});
-      $current->save;
-    }
-    else {
-      BSE::TB::PriceTierPrices->make
-         (
-          tier_id => $tier_id,
-          product_id => $self->id,
-          retailPrice => $prices->{$tier_id},
-         );
-    }
-  }
-
-  # remove any spares
-  for my $price (values %current) {
-    $price->remove;
-  }
-}
-
-=item price(user => $user, date => $sql_date)
-
-=item price(user => $user)
-
-Return the retail price depending on the user and date
-and optionally the tier object (in list context).
-
-If no tier matches then the undef is returned at the tier object.
-
-=cut
-
-sub price {
-  my ($self, %opts) = @_;
-
-  my $user = delete $opts{user};
-  my $date = delete $opts{date} || BSE::Util::SQL::now_sqldate();
-  my @tiers = Products->pricing_tiers;
-  my %prices = map { $_->tier_id => $_ } $self->prices;
-
-  my $price;
-  my $found_tier;
-  for my $tier (@tiers) {
-    if ($prices{$tier->id}
-       && $tier->match($user, $date)) {
-      $price = $prices{$tier->id}->retailPrice;
-      $found_tier = $tier;
-      last;
-    }
-  }
-
-  defined $price or $price = $self->retailPrice;
-
-  return wantarray ? ( $price, $found_tier ) : $price;
-}
-
-sub update_dynamic {
-  my ($self, $cfg) = @_;
-
-  my @tiers = Products->pricing_tiers;
-  if (@tiers) {
-    $self->set_cached_dynamic(1);
-    return;
-  }
-
-  return $self->SUPER::update_dynamic($cfg);
-}
-
-sub tableClass {
-  return "Products";
-}
-
-package BSE::CfgProductOption;
-use strict;
-
-sub id { $_[0]{id} }
-
-sub key {$_[0]{id} } # same as id for config options
-
-sub type { "select" }
-
-sub name { $_[0]{name} }
-
-sub values {
-  @{$_[0]{values}}
-}
-
-sub default_value { $_[0]{default} }
-
-package BSE::CfgProductOptionValue;
-use strict;
-
-sub id { $_[0]{id} }
-
-sub value { $_[0]{value} }
-
-1;
diff --git a/site/cgi-bin/modules/Products.pm b/site/cgi-bin/modules/Products.pm
deleted file mode 100644 (file)
index af2d438..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-package Products;
-use strict;
-use Squirrel::Table;
-use vars qw(@ISA $VERSION);
-@ISA = qw(Squirrel::Table BSE::TB::TagOwners);
-use Product;
-
-our $VERSION = "1.003";
-
-sub rowClass {
-  return 'Product';
-}
-
-sub all_visible_children {
-  my ($self, $id) = @_;
-
-  require OtherParents;
-  my @normal_prods = Products->visible_children($id);
-  my @step_prods = Products->visible_step_children($id);
-  
-  my %order =
-    (
-     ( map { $_->{id} => $_->{displayOrder} } @normal_prods ),
-     ( map 
-       { 
-        $_->{childId} => $_->{parentDisplayOrder}
-       } OtherParents->getBy(parentId => $id)
-     )
-    );
-
-  my %kids = map { $_->{id} => $_ } @step_prods, @normal_prods;
-
-  return @kids{ sort { $order{$b} <=> $order{$a} } keys %kids };
-}
-
-sub all_visible_product_tags {
-  my ($self, $id) = @_;
-
-  require BSE::TB::Tags;
-  require BSE::TB::TagMembers;
-  return
-    {
-     tags => [ BSE::TB::Tags->getSpecial(allprods => $id, $id) ],
-     members => [ BSE::TB::TagMembers->getSpecial(allprods => $id, $id) ],
-    };
-}
-
-*all_visible_products = \&all_visible_children;
-
-sub visible_children {
-  my ($class, $id) = @_;
-
-  use BSE::Util::SQL qw/now_sqldate/;
-  my $today = now_sqldate();
-  
-  return Products->getSpecial(visible_children_of => $id, $today);
-}
-
-sub visible_step_children {
-  my ($class, $id) = @_;
-
-  use BSE::Util::SQL qw/now_sqldate/;
-  my $today = now_sqldate();
-  
-  return Products->getSpecial(visibleStep => $id, $today);
-}
-
-{
-  my $tiers;
-  sub pricing_tiers {
-    unless ($tiers) {
-      require BSE::TB::PriceTiers;
-      $tiers = [ sort { $a->display_order <=> $b->display_order }
-                BSE::TB::PriceTiers->all ];
-    }
-
-    return @$tiers;
-  }
-}
-
-1;
index f62cbfc..8bf42bf 100644 (file)
@@ -18,7 +18,7 @@ SiteUser - represent a site user (or member)
 
 =cut
 
-our $VERSION = "1.014";
+our $VERSION = "1.015";
 
 use constant MAX_UNACKED_CONF_MSGS => 3;
 use constant MIN_UNACKED_CONF_GAP => 2 * 24 * 60 * 60;
@@ -548,8 +548,8 @@ return the user's wishlist products.
 
 sub wishlist {
   my $self = shift;
-  require Products;
-  return Products->getSpecial(userWishlist => $self->{id});
+  require BSE::TB::Products;
+  return BSE::TB::Products->getSpecial(userWishlist => $self->{id});
 }
 
 sub wishlist_order {
index 2b2b192..4a25160 100644 (file)
@@ -6,8 +6,8 @@
 <h2>Product options</h2>
 <:if UserCan bse_edit_prodopt_move:article:>
 <div id="prodoptmenu">All options:
-<a id="sortoptions" href="<:script:>?a_option_reorder=1&amp;_t=prodopts&amp;id=<:article id:>&amp;_csrfp=<:csrfp admin_move_option:>&amp;option_ids=<:arithmetic join ",", map $_->{id}, sort { lc $a->{name} cmp lc $b->{name} } Products->getByPkey([article id])->db_options:>">Sort</a>
-<a id="reverseoptions" href="<:script:>?a_option_reorder=1&amp;_t=prodopts&amp;id=<:article id:>&amp;_csrfp=<:csrfp admin_move_option:>&amp;option_ids=<:arithmetic join ",", map $_->{id}, reverse Products->getByPkey([article id])->db_options:>">Reverse</a>
+<a id="sortoptions" href="<:script:>?a_option_reorder=1&amp;_t=prodopts&amp;id=<:article id:>&amp;_csrfp=<:csrfp admin_move_option:>&amp;option_ids=<:arithmetic join ",", map $_->{id}, sort { lc $a->{name} cmp lc $b->{name} } BSE::TB::Products->getByPkey([article id])->db_options:>">Sort</a>
+<a id="reverseoptions" href="<:script:>?a_option_reorder=1&amp;_t=prodopts&amp;id=<:article id:>&amp;_csrfp=<:csrfp admin_move_option:>&amp;option_ids=<:arithmetic join ",", map $_->{id}, reverse BSE::TB::Products->getByPkey([article id])->db_options:>">Reverse</a>
 <img src="/images/admin/busy.gif" id="busy_img" style="visibility: hidden" alt="busy" />
 </div>
 <:or UserCan:><:eif UserCan:>
index 29954a8..506435e 100644 (file)
@@ -4,12 +4,12 @@ use Getopt::Long;
 use FindBin;
 use lib "$FindBin::Bin/../cgi-bin/modules";
 use BSE::Cfg;
-use Products;
+use BSE::TB::Products;
 
 chdir "$FindBin::Bin/../cgi-bin"
   or warn "Could not change to cgi-bin directory: $!\n";
 
-my @products = Products->all;
+my @products = BSE::TB::Products->all;
 for my $product (@products) {
   if ($product->{body} =~ s/\bpcode:\s*(\S+)//) {
     $product->{product_code} = $1;
index 1f878d8..9bc557f 100644 (file)
@@ -5,7 +5,7 @@ use FindBin;
 use lib "$FindBin::Bin/../cgi-bin/modules";
 use BSE::API qw(bse_init bse_cfg);
 use BSE::TB::Orders;
-use Products;
+use BSE::TB::Products;
 
 bse_init("../cgi-bin");
 
@@ -14,7 +14,7 @@ my %products;
 for my $order (@orders) {
   my @items = $order->items;
   for my $item (@items) {
-    $products{$item->{productId}} = Products->getByPkey($item->{productId});
+    $products{$item->{productId}} = BSE::TB::Products->getByPkey($item->{productId});
     my $product = $products{$item->{productId}};
     unless ($product) {
       print STDERR "Product $item->{productId} not found for order $order->{id}\n";
index 0f797b1..fbb1389 100644 (file)
@@ -12,7 +12,7 @@ BEGIN {
 #ok(chdir $cgidir, "switch to CGI directory");
 # create some articles to test with
 use BSE::TB::Articles;
-use Products;
+use BSE::TB::Products;
 use BSE::API qw/bse_cfg bse_init bse_make_catalog bse_make_product bse_add_step_child/;
 
 bse_init($cgidir);
index 39251cb..aa621b5 100644 (file)
@@ -11,7 +11,7 @@ require BSE::Cfg;
 my $cfg = BSE::Cfg->new;
 # create some articles to test with
 require BSE::TB::Articles;
-require Products;
+require BSE::TB::Products;
 require BSE::TB::ProductOptions;
 require BSE::TB::ProductOptionValues;
 require BSE::API;
index 729f150..c52bb8a 100644 (file)
@@ -41,6 +41,7 @@ site/cgi-bin/modules/BSE/TB/Images.pm =item without previous =over    1
 site/cgi-bin/modules/BSE/TB/Order.pm   =item without previous =over    1
 site/cgi-bin/modules/BSE/TB/Orders.pm  =item without previous =over    1
 site/cgi-bin/modules/BSE/TB/PriceTier.pm       =item without previous =over    1
+site/cgi-bin/modules/BSE/TB/Product.pm =item without previous =over    1
 site/cgi-bin/modules/BSE/TB/Tags.pm    =item without previous =over    1
 site/cgi-bin/modules/BSE/UI/AdminImageClean.pm No argument for =item   2
 site/cgi-bin/modules/BSE/UI/AdminModules.pm    =item without previous =over    1
@@ -76,7 +77,6 @@ site/cgi-bin/modules/DevHelp/Validate.pm      multiple occurrence of link target 'int
 site/cgi-bin/modules/DevHelp/Validate.pm       multiple occurrence of link target 'required'   1
 site/cgi-bin/modules/DevHelp/Validate.pm       multiple occurrence of link target 'rules'      1
 site/cgi-bin/modules/DevHelp/Validate.pm       multiple occurrence of link target 'time'       1
-site/cgi-bin/modules/Product.pm        =item without previous =over    1
 site/cgi-bin/modules/Squirrel/GPG.pm   Verbatim paragraph in NAME section      1
 site/cgi-bin/modules/Squirrel/PGP5.pm  Verbatim paragraph in NAME section      1
 site/cgi-bin/modules/Squirrel/PGP6.pm  Verbatim paragraph in NAME section      1