From d12082f8edcc9d85f1582f95ca743f3444fa99be Mon Sep 17 00:00:00 2001 From: Martin Kamerbeek Date: Mon, 25 Apr 2005 22:26:30 +0000 Subject: [PATCH] Adding the productmanager --- lib/WebGUI/Commerce/Item/Product.pm | 77 ++++ lib/WebGUI/Help/ProductManager.pm | 63 +++ lib/WebGUI/Macro/Product.pm | 62 +++ lib/WebGUI/Operation/ProductManager.pm | 571 +++++++++++++++++++++++++ lib/WebGUI/Product.pm | 420 ++++++++++++++++++ 5 files changed, 1193 insertions(+) create mode 100755 lib/WebGUI/Commerce/Item/Product.pm create mode 100644 lib/WebGUI/Help/ProductManager.pm create mode 100644 lib/WebGUI/Macro/Product.pm create mode 100755 lib/WebGUI/Operation/ProductManager.pm create mode 100755 lib/WebGUI/Product.pm diff --git a/lib/WebGUI/Commerce/Item/Product.pm b/lib/WebGUI/Commerce/Item/Product.pm new file mode 100755 index 000000000..2cd218b2c --- /dev/null +++ b/lib/WebGUI/Commerce/Item/Product.pm @@ -0,0 +1,77 @@ +package WebGUI::Commerce::Item::Product; + +use strict; +#use WebGUI::SQL; +use WebGUI::Product; + +our @ISA = qw(WebGUI::Commerce::Item); + +#------------------------------------------------------------------- +sub available { + return $_[0]->{_variant}->{available}; +} + +#------------------------------------------------------------------- +sub description { + return $_[0]->{_product}->get('description'); +} + +#------------------------------------------------------------------- +#sub duration { +# + +#------------------------------------------------------------------- +#sub handler { +#} + +#------------------------------------------------------------------- +sub id { + return $_[0]->{_variant}->{variantId}; +} + +#------------------------------------------------------------------- +sub isRecurring { + return 0; +} + +#------------------------------------------------------------------- +sub name { + return $_[0]->{_product}->get('title').' ('.$_[0]->{_composition}.')'; +} + +#------------------------------------------------------------------- +sub new { + my ($class, $sku, $product, $variantId); + $class = shift; + $variantId = shift; + + $product = WebGUI::Product->getByVariantId($variantId); +my $variant = $product->getVariant($variantId); +my %parameters = map {split(/\./, $_)} split(/,/, $variant->{composition}); +my $composition = join(', ',map {$product->getParameter($_)->{name} .': '. $product->getOption($parameters{$_})->{value}} keys (%parameters)); + + bless {_product => $product, _composition => $composition, _variant => $variant}, $class; +} + +#------------------------------------------------------------------- +sub needsShipping { + return 1; +} + +#------------------------------------------------------------------- +sub price { + return $_[0]->{_variant}->{price}; +} + +#------------------------------------------------------------------- +sub type { + return 'Product'; +} + +#------------------------------------------------------------------- +sub weight { + return $_[0]->{_variant}->{weight}; +} + +1; + diff --git a/lib/WebGUI/Help/ProductManager.pm b/lib/WebGUI/Help/ProductManager.pm new file mode 100644 index 000000000..d6051336a --- /dev/null +++ b/lib/WebGUI/Help/ProductManager.pm @@ -0,0 +1,63 @@ +package WebGUI::Help::ProductManager; + +our $HELP = { + 'list products' => { + title => 'help list products title', + body => 'help list products body', + related => [ + ] + }, + + 'manage product' => { + title => 'help manage product title', + body => 'help manage product body', + related => [ + ] + }, + + 'edit product' => { + title => 'help edit product title', + body => 'help edit product body', + related => [ + { + tag => 'template language', + namespace => 'Asset_Template' + }, + ] + }, + + 'edit parameter' => { + title => 'help edit parameter title', + body => 'help edit parameter body', + related => [ + ] + }, + 'edit option' => { + title => 'help edit option title', + body => 'help edit option body', + related => [ + ] + }, + 'list variants' => { + title => 'help list variants title', + body => 'help list variants body', + related => [ + ] + }, + 'edit variant' => { + title => 'help edit variant title', + body => 'help edit variant body', + related => [ + ] + }, + 'edit sku template' => { + title => 'help edit sku template title', + body => 'help edit sku template body', + related => [ + ] + }, + +}; + +1; + diff --git a/lib/WebGUI/Macro/Product.pm b/lib/WebGUI/Macro/Product.pm new file mode 100644 index 000000000..d2766980b --- /dev/null +++ b/lib/WebGUI/Macro/Product.pm @@ -0,0 +1,62 @@ +package WebGUI::Macro::Product; + +use strict; +use WebGUI::Session; +use WebGUI::Macro; +use WebGUI::Product; +use WebGUI::Asset::Template; +use WebGUI::SQL; +use WebGUI::International; + +sub process { + my (@param, $productId, $variantId, $product, $variant, $output, $templateId, @variantLoop, %var); + + @param = WebGUI::Macro::getParams(@_); + + return 'No SKU or productId passed' unless ($_[0]); + + ($productId, $variantId) = WebGUI::SQL->quickArray("select productId, variantId from productVariants where sku=".quote($_[0])); + ($productId) = WebGUI::SQL->quickArray("select productId from products where sku=".quote($_[0])) unless ($productId); + ($productId) = WebGUI::SQL->quickArray("select productId from products where productId=".quote($_[0])) unless ($productId); + + return 'Cannot find product' unless ($productId); + + $product = WebGUI::Product->new($productId); + + if ($variantId) { + $variant = [ $product->getVariant($variantId) ]; + } else { + $variant = $product->getVariant; + }; + + foreach (@$variant) { + my @compositionLoop; + foreach (split(/,/,$_->{composition})) { + my ($parameterId, $optionId) = split(/\./, $_); + push(@compositionLoop, { + parameter => $product->getParameter($parameterId)->{name}, + value => $product->getOption($optionId)->{value} + }); + } + + push (@variantLoop, { + 'variant.variantId' => $_->{variantId}, + 'variant.price' => $_->{price}, + 'variant.weight' => $_->{weight}, + 'variant.sku' => $_->{sku}, + 'variant.compositionLoop' => \@compositionLoop, + 'variant.addToCart.url' => WebGUI::URL::page('op=addToCart&itemType=Product&itemId='.$_->{variantId}), + 'variant.addToCart.label' => WebGUI::International::get('add to cart', 'Macro_Product'), + }) if ($_->{available}); + } + + %var = %{$product->get}; + $var{variantLoop} = \@variantLoop; + $var{'variants.message'} = WebGUI::International::get('available product configurations', 'Macro_Product'); + $templateId = $_[1] || $product->get('templateId'); + + return WebGUI::Asset::Template->new($templateId)->process(\%var); +} + +1; + diff --git a/lib/WebGUI/Operation/ProductManager.pm b/lib/WebGUI/Operation/ProductManager.pm new file mode 100755 index 000000000..2b6357ef5 --- /dev/null +++ b/lib/WebGUI/Operation/ProductManager.pm @@ -0,0 +1,571 @@ +package WebGUI::Operation::ProductManager; + +use strict; +use WebGUI::Session; +use WebGUI::SQL; +use WebGUI::HTMLForm; +use WebGUI::Form; +use WebGUI::Id; +use WebGUI::International; +use WebGUI::AdminConsole; +use Tie::IxHash; +use WebGUI::Product; +use WebGUI::Icon; +use WebGUI::HTML; +use WebGUI::Privilege; +use WebGUI::Grouping; + +#------------------------------------------------------------------- +sub _submenu { + my $i18n = WebGUI::International->new("ProductManager"); + + my $workarea = shift; + my $title = shift; + $title = $i18n->get($title) if ($title); + my $help = shift; + my $ac = WebGUI::AdminConsole->new("productManager"); + if ($help) { + $ac->setHelp($help, 'ProductManager'); + } + + my $productId = $session{form}{productId} || WebGUI::Session::getScratch('managingProduct'); + undef $productId if ($productId eq 'new'); + $ac->addSubmenuItem(WebGUI::URL::page('op=editProduct&productId=new'), $i18n->get('add product')); + $ac->addSubmenuItem(WebGUI::URL::page('op=listProducts'), $i18n->get('list products')); + $ac->addSubmenuItem(WebGUI::URL::page('op=manageProduct&productId='.$productId), $i18n->get('manage product')) if ($productId); + $ac->addSubmenuItem(WebGUI::URL::page('op=listProductVariants&productId='.$productId), $i18n->get('list variants')) if ($productId); + + return $ac->render($workarea, $title); +} + +#------------------------------------------------------------------- +sub www_deleteProductParameterOption { + my $optionId = $session{form}{optionId}; + + return WebGUI::Privilege::insufficient unless (WebGUI::Grouping::isInGroup(14)); + + WebGUI::Product->getByOptionId($optionId)->deleteOption($optionId); + + return WebGUI::Operation::execute('manageProduct'); +} + +#------------------------------------------------------------------- +sub www_deleteProductParameter { + my $parameterId = $session{form}{parameterId}; + + return WebGUI::Privilege::insufficient unless (WebGUI::Grouping::isInGroup(14)); + + WebGUI::Product->getByParameterId($parameterId)->deleteParameter($parameterId); + + return WebGUI::Operation::execute('manageProduct'); +} + +#------------------------------------------------------------------- +sub www_deleteProduct { + my $productId = $session{form}{productId}; + + return WebGUI::Privilege::insufficient unless (WebGUI::Grouping::isInGroup(14)); + + WebGUI::Product->new($productId)->delete; + + return WebGUI::Operation::execute('listProducts'); +} + +#------------------------------------------------------------------- +sub www_editProduct { + my ($productId, $product, $f, $i18n); + + return WebGUI::Privilege::insufficient unless (WebGUI::Grouping::isInGroup(14)); + + $i18n = WebGUI::International->new('ProductManager'); + $productId = $session{form}{productId}; + + unless ($productId eq 'new') { + $product = WebGUI::Product->new($productId)->get; + } + + $f = WebGUI::HTMLForm->new; + $f->hidden('op', 'editProductSave'); + $f->hidden('productId', $productId); + $f->text( + -name => 'title', + -label => $i18n->get('title'), + -value => $session{form}{title} || $product->{title}, + -maxlength => 255, + ); + $f->textarea( + -name => 'description', + -label => $i18n->get('description'), + -value => $session{form}{decsription} || $product->{description}, + ); + $f->float( + -name => 'price', + -label => $i18n->get('price'), + -value => $session{form}{price} || $product->{price}, + -maxlength => 13, + ); + $f->float( + -name => 'weight', + -label => $i18n->get('weight'), + -value => $session{form}{weight} || $product->{weight}, + -maxlength => 9, + ); + $f->text( + -name => 'sku', + -label => $i18n->get('sku'), + -value => $session{form}{sku} || $product->{SKU}, + -maxlength => 64, + ); + $f->template( + -name => 'templateId', + -label => $i18n->get('template'), + -value => $session{form}{templateId} || $product->{templateId}, + -namespace => 'Commerce/Product', + ); + $f->text( + -name => 'skuTemplate', + -label => $i18n->get('sku template'), + -value => $session{form}{skuTemplate} || $product->{skuTemplate}, + -maxlength => 255, + ); + $f->submit; + + return _submenu($f->print, 'edit product', 'edit product'); +} + +#------------------------------------------------------------------- +sub www_editProductSave { + my ($self, @error, $productId, $product, $i18n); + + return WebGUI::Privilege::insufficient unless (WebGUI::Grouping::isInGroup(14)); + + $i18n = WebGUI::International->new('ProductManager'); + + push(@error, $i18n->get('edit product title error')) unless $session{form}{title}; + push(@error, $i18n->get('edit product price error')) unless ($session{form}{price} && $session{form}{price} =~ /^\d+(\.\d+)?$/); + push(@error, $i18n->get('edit product weight error')) unless (defined $session{form}{weight} && $session{form}{price} =~ /^\d+(\.\d+)?$/); + push(@error, $i18n->get('edit product title error')) unless ($session{form}{sku}); + + return '
'.WebGUI::Operation::execute('editProduct') if (@error); + + $productId = $session{form}{productId}; + $product = WebGUI::Product->new($productId); + $product->set({ + title => $session{form}{title}, + description => $session{form}{description}, + price => $session{form}{price}, + weight => $session{form}{weight}, + sku => $session{form}{sku}, + templateId => $session{form}{templateId}, + skuTemplate => $session{form}{skuTemplate}, + }); + + $session{form}{productId} = $product->get('productId'); + return WebGUI::Operation::execute('manageProduct'); +} + +#------------------------------------------------------------------- +sub www_editProductParameter { + my ($parameterId, $product, $productId, $parameter, $f, $i18n); + + return WebGUI::Privilege::insufficient unless (WebGUI::Grouping::isInGroup(14)); + + $i18n = WebGUI::International->new('ProductManager'); + + $parameterId = $session{form}{parameterId}; + $productId = $session{form}{productId}; + + unless ($parameterId eq 'new') { + $product = WebGUI::Product->getByParameterId($parameterId); + $parameter = $product->getParameter($parameterId); + $productId = $product->get('productId'); + } + + $f = WebGUI::HTMLForm->new; + $f->hidden('op', 'editProductParameterSave'); + $f->hidden('parameterId', $parameterId); + $f->hidden('productId', $productId); + $f->readOnly( + -label => 'parameterId', + -value => $parameterId, + ); + $f->text( + -name => 'name', + -label => $i18n->get('edit parameter name'), + -value => $session{form}{name} || $parameter->{name}, + -maxlength => 64, + ); + $f->submit; + + return _submenu($f->print, 'edit parameter', 'edit parameter'); +} + +#------------------------------------------------------------------- +sub www_editProductParameterSave { + my (@error, $parameterId, $product, $i18n, $skuTemplate, $oldName, $newName); + + return WebGUI::Privilege::insufficient unless (WebGUI::Grouping::isInGroup(14)); + + $i18n = WebGUI::International->new('ProductManager'); + + $parameterId = $session{form}{parameterId}; + + push (@error, $i18n->get('edit parameter error name')) unless $session{form}{name}; + push (@error, $i18n->get('edit parameter productId error')) unless $session{form}{productId}; + + return "".WebGUI::Operation::execute('editProductParameter') if (@error); + + $product = WebGUI::Product->new($session{form}{productId}); + $skuTemplate = $product->get('skuTemplate'); + + if ($parameterId eq 'new') { + $parameterId = $product->addParameter; + } else { + ($oldName = $product->getParameter($parameterId)->{name}) =~ s/[ ><]/\./g; + ($newName = $session{form}{name}) =~ s/[ ><]/\./g; + $skuTemplate = $product->get('skuTemplate'); + $skuTemplate =~ s/< *?tmpl_var *?param\.$oldName *?>//i; + $product->set({ + skuTemplate => $skuTemplate + }); + } + + $product->setParameter($parameterId, { + name => $session{form}{name} + }); + + return WebGUI::Operation::execute('editSkuTemplate') if ($session{form}{parameterId} eq 'new'); + return WebGUI::Operation::execute('manageProduct'); +} + +#------------------------------------------------------------------- +sub www_editProductParameterOption { + my ($self, $optionId, $option, $f, $i18n); + + return WebGUI::Privilege::insufficient unless (WebGUI::Grouping::isInGroup(14)); + + $i18n = WebGUI::International->new('ProductManager'); + + $optionId = $session{form}{optionId}; + unless ($optionId eq 'new') { + $option = WebGUI::Product->getByOptionId($optionId)->getOption($optionId); + } + + $f = WebGUI::HTMLForm->new; + $f->hidden('op', 'editProductParameterOptionSave'); + $f->hidden('optionId', $optionId); + $f->hidden('parameterId', $session{form}{parameterId}); + $f->readOnly( + -label => 'optionId', + -value => $optionId + ); + $f->text( + -name => 'value', + -label => $i18n->get('edit option value'), + -value => $session{form}{value} || $option->{value}, + -maxlength => 64, + ); + $f->float( + -name => 'priceModifier', + -label => $i18n->get('edit option price modifier'), + -value => $session{form}{priceModifier} || $option->{priceModifier}, + -maxlength => 11, + ); + $f->float( + -name => 'weightModifier', + -label => $i18n->get('edit option weight modifier'), + -value => $session{form}{weightModifier} || $option->{weightModifier}, + -maxlength => 7, + ); + $f->text( + -name => 'skuModifier', + -label => $i18n->get('edit option sku modifier'), + -value => $session{form}{skuModifier} || $option->{skuModifier}, + -maxlength => 64, + ); + $f->submit; + + return _submenu($f->print, 'edit option', 'edit option'); +} + +#------------------------------------------------------------------- +sub www_editProductParameterOptionSave { + my ($self, @error, $optionId, $product, $i18n); + + return WebGUI::Privilege::insufficient unless (WebGUI::Grouping::isInGroup(14)); + + $i18n = WebGUI::International->new('ProductManager'); + + push (@error, $i18n->get('edit option value error')) unless ($session{form}{value}); + push (@error, $i18n->get('edit option parameterId error')) unless ($session{form}{parameterId}); + + return '
'.WebGUI::Operation::execute('editProduct') if (@error); + + $product = WebGUI::Product->getByParameterId($session{form}{parameterId}); + $optionId = $session{form}{optionId}; + $optionId = $product->addOptionToParameter($session{form}{parameterId}) if ($optionId eq 'new'); + $product->setOption($optionId, { + value => $session{form}{value}, + priceModifier => $session{form}{priceModifier}, + weightModifier => $session{form}{weightModifier}, + skuModifier => $session{form}{skuModifier} + }); + + return WebGUI::Operation::execute('manageProduct'); +} + +#------------------------------------------------------------------- +sub www_editProductVariant { + my ($variantId, $variant, $f, $i18n); + + return WebGUI::Privilege::insufficient unless (WebGUI::Grouping::isInGroup(14)); + + $i18n = WebGUI::International->new("ProductManager"); + + $variantId = $session{form}{variantId}; + $variant = WebGUI::Product->getByVariantId($variantId)->getVariant($variantId); + + $f = WebGUI::HTMLForm->new; + $f->hidden('op', 'editProductVariantSave'); + $f->hidden('variantId', $variantId); + $f->readOnly( + -label => 'varaiantId', + -value => $variant->{variantId} + ); + $f->float( + -name => 'price', + -label => $i18n->get('price override'), + -value => $variant->{priceOverride} ? $variant->{price} : '' + ); + $f->float( + -name => 'weight', + -label => $i18n->get('weight override'), + -value => $variant->{weightOverride} ? $variant->{weight} : '' + ); + $f->text( + -name => 'sku', + -label => $i18n->get('sku override'), + -value => $variant->{skuOverride} ? $variant->{sku} : '' + ); + $f->yesNo( + -name => 'available', + -label => $i18n->get('available'), + -value => $variant->{available} + ); + $f->submit; + + return _submenu($f->print, 'edit variant', 'edit variant'); +} + +#------------------------------------------------------------------- +sub www_editProductVariantSave { +my $variantId = $session{form}{variantId}; + + return WebGUI::Privilege::insufficient unless (WebGUI::Grouping::isInGroup(14)); + + WebGUI::Product->getByVariantId($variantId)->setVariant($variantId, $session{form}); + + return WebGUI::Operation::execute('listProductVariants'); +} + +#------------------------------------------------------------------- +sub www_editSkuTemplate { + my ($product, $productId, $output, $f, $name, $i18n); + + return WebGUI::Privilege::insufficient unless (WebGUI::Grouping::isInGroup(14)); + + $i18n = WebGUI::International->new("ProductManager"); + + $productId = $session{form}{productId}; + $product = WebGUI::Product->new($productId); + + $output .= "Available are:
\n"; + $output .= "
"; + + $f = WebGUI::HTMLForm->new; + $f->hidden('op', 'editSkuTemplateSave'); + $f->hidden('productId', $productId); + $f->text( + -name => 'skuTemplate', + -value => $product->get('skuTemplate'), + -label => $i18n->get('sku template'), + ); + $f->submit; + $output .= $f->print; + + return _submenu($output, 'edit sku composition label', 'edit sku template'); +} + +#------------------------------------------------------------------- +sub www_editSkuTemplateSave { + my ($productId) = $session{form}{productId}; + + return WebGUI::Privilege::insufficient unless (WebGUI::Grouping::isInGroup(14)); + + WebGUI::Product->new($productId)->set({ + skuTemplate => $session{form}{skuTemplate}, + }); + + return WebGUI::Operation::execute('manageProduct'); +} + +#------------------------------------------------------------------- +sub www_listProducts { + my ($self, $sth, $output, $row, $i18n); + + return WebGUI::Privilege::insufficient unless (WebGUI::Grouping::isInGroup(14)); + + $i18n = WebGUI::International->new('ProductManager'); + + WebGUI::Session::setScratch('managingProduct', '-delete-'); + + $sth = WebGUI::SQL->read('select * from products order by title'); + + $output .= ''; + while ($row = $sth->hashRef) { + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + } + $output .= '
'; + $output .= deleteIcon('op=deleteProduct&productId='.$row->{productId}); + $output .= editIcon('op=manageProduct&productId='.$row->{productId}); + $output .= ''.$row->{title}.'
'; + + return _submenu($output, 'list products', 'list products'); +} + +#------------------------------------------------------------------- +sub www_listProductVariants { + my ($productId, $product, @variants, %parameters, %options, $output, %composition, $i18n); + + return WebGUI::Privilege::insufficient unless (WebGUI::Grouping::isInGroup(14)); + + $i18n = WebGUI::International->new("ProductManager"); + + $productId = $session{form}{productId} || WebGUI::Session::getScratch('managingProduct'); + + return WebGUI::Operation::execute('listProducts') if ($productId eq 'new' || !$productId); + + $product = WebGUI::Product->new($productId); + + @variants = sort {$a->{composition} cmp $b->{composition}} @{$product->getVariant}; + tie %parameters, "Tie::IxHash"; + %parameters = map {$_->{parameterId} => $_->{name}} sort {$a->{name} <=> $b->{name}} @{$product->getParameter}; + %options = map {$_->{optionId} => $_->{value}} @{$product->getOption}; + + $output = WebGUI::Form::formHeader; + $output .= WebGUI::Form::hidden({ + name => 'op', + value => 'listProductVariantsSave', + }); + $output .= WebGUI::Form::hidden({ + name => 'productId', + value => $productId, + }); + $output .= ''; + $output .= "" if (%parameters); + $output .= ''. + ''. + ''. + ''; + $output .= ""; + foreach (@variants) { + $output .= ""; + %composition = map {split(/\./, $_)} split(/,/, $_->{composition}); + foreach (keys(%parameters)) { + $output .= ''; + } + $output .= '"; + $output .= ""; + $output .= ""; + } + $output .= "
".join('', values(%parameters))."'.$i18n->get('sku').''.$i18n->get('price').''.$i18n->get('weight').''.$i18n->get('available').'
'.$options{$composition{$_}}.''.$_->{sku}.""; + $output .= '*' if ($_->{skuOverride}); + $output .= ''.$_->{price}.""; + $output .= '*'if ($_->{priceOverride}); + $output .= ''.$_->{weight}.""; + $output .= '*' if ($_->{weightOverride}); + $output .= "".WebGUI::Form::checkbox({ + name => 'available', + value => $_->{variantId}, + checked => $_->{available}, + }).editIcon('op=editProductVariant&variantId='.$_->{variantId})."
"; + $output .= WebGUI::Form::submit; + $output .= WebGUI::Form::formFooter; + + return _submenu($output, 'list variants label', 'list variants'); +} + +#------------------------------------------------------------------- +sub www_listProductVariantsSave { + + return WebGUI::Privilege::insufficient unless (WebGUI::Grouping::isInGroup(14)); + + my %availableVariants = map {$_ => 1} $session{cgi}->param('available'); + + my $product = WebGUI::Product->new($session{form}{productId}); + my @variants = @{$product->getVariant}; + + foreach (@variants) { + $product->setVariant($_->{variantId}, { + available => $availableVariants{$_->{variantId}} ? '1' : '0'}); + } + + return WebGUI::Operation::execute('listProductVariants'); +} + +#------------------------------------------------------------------- +sub www_manageProduct { + my ($productId, $product, $output, $parameter, $option, $optionId, $i18n); + + return WebGUI::Privilege::insufficient unless (WebGUI::Grouping::isInGroup(14)); + + $i18n = WebGUI::International->new("ProductManager"); + + $productId = $session{form}{productId} || WebGUI::Session::getScratch('managingProduct'); + return WebGUI::Operation::execute('listProducts') if ($productId eq 'new' || !$productId); + WebGUI::Session::setScratch('managingProduct', $productId); + + $product = WebGUI::Product->new($productId); + + $output .= "

".$product->get('title')."

"; + $output .= "

".$i18n->get('properties').editIcon('op=editProduct&productId='.$productId)."

"; + $output .= ""; + $output .= ""; + $output .= ""; + $output .= ""; + $output .= ""; + $output .= ""; + $output .= "
".$i18n->get('price')."".$product->get('price')."
".$i18n->get('weight')."".$product->get('weight')."
".$i18n->get('sku')."".$product->get('sku')."
".$i18n->get('description')."".$product->get('description')."
".$i18n->get('sku template')."".WebGUI::HTML::format($product->get('skuTemplate'), 'text')."
"; + + $output .= "

Parameters

"; + $output .= ''. + $i18n->get('add parameter').'
'; + foreach $parameter (@{$product->getParameter}) { + $output .= deleteIcon('op=deleteProductParameter¶meterId='.$parameter->{parameterId}). + editIcon('op=editProductParameter¶meterId='.$parameter->{parameterId}); + $output .= ''.$parameter->{name}.'
'; + $output .= ''. + $i18n->get('add option').'
'; + foreach $optionId (@{$parameter->{options}}) { + $option = $product->getOption($optionId); + $output .= ''. + deleteIcon('op=deleteProductParameterOption&optionId='.$option->{optionId}). + editIcon('op=editProductParameterOption¶meterId='.$parameter->{parameterId}.'&optionId='.$option->{optionId}).$option->{value}.'
'; + } + $output .= '
'; + } + + return _submenu($output, 'manage product', 'manage product'); +} + +1; + diff --git a/lib/WebGUI/Product.pm b/lib/WebGUI/Product.pm new file mode 100755 index 000000000..9c75f8a6a --- /dev/null +++ b/lib/WebGUI/Product.pm @@ -0,0 +1,420 @@ +package WebGUI::Product; + +use strict; +use WebGUI::SQL; +use WebGUI::Id; +use WebGUI::Asset::Template; + +#------------------------------------------------------------------- +sub _permute { + my ($currentSet, @permutations, $permutation, $value, @result); + $currentSet = shift; + + @permutations = (@_) ? _permute(@_) : []; + foreach $permutation (@permutations) { + foreach $value (@$currentSet) { + push(@result, [$value, @{$permutation}]); + } + } + + return @result; +} + +#------------------------------------------------------------------- +sub addOptionToParameter { + my ($self, $parameterId, $properties, $optionId); + $self = shift; + $parameterId = shift; + $properties = shift || {}; + + $optionId = WebGUI::Id::generate; + + WebGUI::SQL->write("insert into productParameterOptions ". + "(optionId, parameterId) values ". + "(".quote($optionId).", ".quote($parameterId).")"); + + $self->{_options}->{$optionId} = { + %$properties, + parameterId => $parameterId, + optionId => $optionId, + }; + push(@{$self->{_parameters}->{$parameterId}->{options}}, $optionId); + + $self->updateVariants; + + return $optionId; +} + +#------------------------------------------------------------------- +sub addParameter { + my ($self, $properties, $parameterId); + + $self = shift; + $properties = shift; + + $parameterId = WebGUI::Id::generate; + + WebGUI::SQL->write("insert into productParameters (parameterId, productId) values ". + "(".quote($parameterId).", ".quote($self->get('productId')).")"); + + $self->{_parameters}->{$parameterId}->{parameterId} = $parameterId; + $self->{_parameters}->{$parameterId}->{options} = []; + + return $parameterId; +} + +#------------------------------------------------------------------- +sub delete { + my ($self) = shift; + + foreach (@{$self->getParameter}) { + WebGUI::SQL->write("delete from productParameterOptions where parameterId=".quote($_->{parameterId})); + } + + WebGUI::SQL->write("delete from productParameters where productId=".quote($self->get('productId'))); + WebGUI::SQL->write("delete from productVariants where productId=".quote($self->get('productId'))); + WebGUI::SQL->write("delete from products where productId=".quote($self->get('productId'))); + + return undef; +} + +#------------------------------------------------------------------- +sub deleteParameter { + my ($self, $parameterId); + $self = shift; + $parameterId = shift; + + WebGUI::SQL->write("delete from productParameterOptions where parameterId=".quote($parameterId)); + WebGUI::SQL->write("delete from productParameters where parameterId=".quote($parameterId)); + + $self->updateVariants; + + return undef; +} + +#------------------------------------------------------------------- +sub deleteOption { + my ($self, $optionId, @options, $parameterId); + $self = shift; + $optionId = shift; + + WebGUI::SQL->write("delete from productParameterOptions where optionId=".quote($optionId)); + + $parameterId = $self->{_options}->{$optionId}->{parameterId}; + + delete($self->{_options}->{$optionId}); + + foreach (@{$self->{_parameters}->{$parameterId}->{options}}) { + push(@options, $_) unless ($_ eq $optionId); + } + + $self->{_parameters}->{$parameterId}->{options} = \@options; + + $self->updateVariants; + + return undef; +} + +#------------------------------------------------------------------- +sub get { + my ($self, $property); + $self = shift; + $property = shift; + + return $self->{_properties}->{$property} if ($property); + + return $self->{_properties}; +} + +#------------------------------------------------------------------- +sub getByOptionId { + my ($class, $optionId, $productId); + + $class = shift; + $optionId = shift; + + + ($productId) = WebGUI::SQL->quickArray("select productId from productParameters as t1, productParameterOptions as t2 ". + "where t1.parameterId=t2.parameterId and t2.optionId=".quote($optionId)); + + return undef unless ($productId); + + return WebGUI::Product->new($productId); +} + +#------------------------------------------------------------------- +sub getByParameterId { + my ($class, $parameterId, $productId); + $class = shift; + $parameterId = shift; + + ($productId) = WebGUI::SQL->quickArray("select productId from productParameters where parameterId=".quote($parameterId)); + + return WebGUI::Product->new($productId); +} + +#------------------------------------------------------------------- +sub getByVariantId { + my ($class, $productId, $variantId); + $class = shift; + $variantId = shift; + + ($productId) = WebGUI::SQL->quickArray("select productId from productVariants where variantId=".quote($variantId)); + + return WebGUI::Product->new($productId); +} + +#------------------------------------------------------------------- +sub getOption { + my ($self, $optionId); + $self = shift; + $optionId = shift; + + return $self->{_options}->{$optionId} if ($optionId); + + return [ values %{$self->{_options}} ]; +} + +#------------------------------------------------------------------- +sub getParameter { + my ($self, $parameterId); + $self = shift; + $parameterId = shift; + + return $self->{_parameters}->{$parameterId} if ($parameterId); + + return [ values %{$self->{_parameters}} ]; +} + +#------------------------------------------------------------------- +sub getVariant { + my ($self, $variantId); + $self = shift; + $variantId = shift; + + return $self->{_variants}->{$variantId} if ($variantId); + + return [ values %{$self->{_variants}} ]; +} + +#------------------------------------------------------------------- +sub new { + my ($class, $productId, $properties, $parameters, $variants, $options, $sth, %row, $option, $new); + $class = shift; + $productId = shift; + + WebGUI::ErrorHandler::fatal('no productId') unless ($productId); + + $parameters = {}; + $variants = {}; + $options = {}; + + if ($productId eq 'new') { + $productId = WebGUI::Id::generate; + $properties = {productId => $productId}; + WebGUI::SQL->write("insert into products (productId) values (".quote($productId).")"); + } else { + $properties = WebGUI::SQL->quickHashRef("select * from products where productId=".quote($productId)); + + # fetch parameters and options + $sth = WebGUI::SQL->read("select opt.*, param.* from productParameters as param left join productParameterOptions as opt ". + "on param.parameterId=opt.parameterId where param.productId=".quote($productId)); + while (%row = $sth->hash) { + $parameters->{$row{parameterId}} = { + name => $row{name}, + parameterId => $row{parameterId}, + options => [], + } unless (defined $parameters->{$row{parameterId}}); + if ($row{value}) { + $option = { + value => $row{value}, + optionId => $row{optionId}, + parameterId => $row{parameterId}, + priceModifier => $row{priceModifier}, + weightModifier => $row{weightModifier}, + skuModifier => $row{skuModifier} + }; + push(@{$parameters->{$row{parameterId}}->{options}}, $row{optionId}); + $options->{$row{optionId}} = $option; + } + } + + # fetch variants + $sth = WebGUI::SQL->read("select * from productVariants where productId=".quote($productId)); + while (%row = $sth->hash) { + $variants->{$row{variantId}} = {%row}; + } + + $new = 0; + } + + bless {_properties => $properties, _parameters => $parameters, _options => $options, _variants => $variants, _new => $new}, $class; +} + +#------------------------------------------------------------------- +sub set { + my ($self, $properties); + $self = shift; + $properties = shift; + + WebGUI::SQL->write("update products set ".join(', ', map {$_."=".quote($properties->{$_})} keys(%$properties)). + " where productId=".quote($self->get('productId'))); + + foreach (keys(%$properties)) { + $self->{_properties}->{$_} = $properties->{$_}; + } + + $self->updateVariants; +} + +#------------------------------------------------------------------- +sub setParameter { + my ($self, $parameterId, $properties); + $self = shift; + $parameterId = shift; + $properties = shift; + + WebGUI::SQL->write("update productParameters set ".join(', ', map {$_."=".quote($properties->{$_})} keys(%$properties)). + " where parameterId=".quote($parameterId)); + + map {$self->{_parameter}->{$parameterId}->{$_} = $properties->{$_}} keys %$properties; +} + +#------------------------------------------------------------------- +sub setOption { + my ($self, $optionId, $properties); + $self = shift; + $optionId = shift; + $properties = shift; + + WebGUI::SQL->write("update productParameterOptions set ".join(', ', map {$_."=".quote($properties->{$_})} keys(%$properties)). + " where optionId=".quote($optionId)); + + foreach (keys(%$properties)) { + $self->{_options}->{$optionId}->{$_} = $properties->{$_}; + } + + $self->updateVariants; +} + +#------------------------------------------------------------------- +sub setVariant { + my ($self, $variantId, $properties, @pairs, $original, %sku, $parameterName); + $self = shift; + $variantId = shift; + $properties = shift; + +my %pairs = map {split(/\./, $_)} split(/,/, $self->getVariant($variantId)->{composition}); + + $original->{price} = $self->get('price'); + $original->{weight} = $self->get('weight'); + $sku{base} = $self->get('sku'); + + foreach (values(%pairs)) { +my $currentOption = $self->getOption($_); + $original->{price} += $currentOption->{priceModifier}; + $original->{weight} += $currentOption->{weightModifier}; + ($parameterName = $self->{_parameters}->{$currentOption->{parameterId}}->{name}) =~ s/ //g; + $sku{'param.'.$parameterName} = $currentOption->{skuModifier}; + } + $original->{sku} = WebGUI::Asset::Template->processRaw($self->get('skuTemplate'), \%sku ); + + if (defined $properties->{price}) { + if ($properties->{price} ne '') { + push(@pairs, 'price='.quote($properties->{price}).', priceOverride=1'); + } else { + push(@pairs, 'price='.quote($original->{price}).', priceOverride=0'); + } + } + if (defined $properties->{weight}) { + if ($properties->{weight} ne '') { + push(@pairs, 'weight='.quote($properties->{weight}).', weightOverride=1'); + } else { + push(@pairs, 'weight='.quote($original->{weight}).', weightOverride=0'); + } + } + if (defined $properties->{sku}) { + if ($properties->{sku} ne '') { + push(@pairs, 'sku='.quote($properties->{sku}).', skuOverride=1'); + } else { + push(@pairs, 'sku='.quote($original->{sku}).', skuOverride=0'); + } + } + + push(@pairs, 'available='.quote($properties->{available})) if (defined $properties->{available}); + + WebGUI::SQL->write("update productVariants set ".join(', ', @pairs)." where variantId=".quote($variantId)) if (@pairs); + + $self->{_variants}->{$variantId} = {%{$self->{_variants}->{$variantId}}, %$properties}; +} + +#------------------------------------------------------------------- +sub updateVariants { + my ($self, %variants, @optionSets, @variants, $variant, %var, @composition, $option, @newVariants, $parameterName); + $self = shift; + + foreach (@{$self->getVariant}) { + $variants{$_->{composition}} = $_; + } + + # group options per parameter so they can be permuted + foreach my $parameter (@{$self->getParameter}) { + push (@optionSets, [ map {$self->{_options}->{$_}} @{$parameter->{options}} ] ) if (@{$parameter->{options}}); + } + + @variants = _permute(@optionSets); + + @variants = ([]) unless (@variants); + my %newVariants; + foreach $variant (@variants) { + my %sku; + + $var{productId} = $self->get('productId'); + $var{price} = $self->get('price'); + $var{weight} = $self->get('weight'); + $var{sku} = $self->get('sku'); + $sku{base} = $self->get('sku'); + @composition = (); + + foreach $option (@{$variant}) { + $var{price} += $option->{priceModifier}; + $var{weight} += $option->{weightModifier}; + $var{sku} .= $option->{skuModifier}; + ($parameterName = $self->{_parameters}->{$option->{parameterId}}->{name}) =~ s/ //g; + $sku{'param.'.$parameterName} = $option->{skuModifier}; + $var{description} .= $option->{value}; + push (@composition, $option->{parameterId}.".".$option->{optionId}); + } + + $var{composition} = join(',', sort @composition); + $var{available} = 1; + $var{sku} = WebGUI::Asset::Template->processRaw($self->get('skuTemplate'), \%sku ) || $self->get('sku'); + + if (defined $variants{$var{composition}}) { + $var{price} = $variants{$var{composition}}{price} if ($variants{$var{composition}}{priceOverride}); + $var{weight} = $variants{$var{composition}}{weight} if ($variants{$var{composition}}{weightOverride}); + $var{sku} = $variants{$var{composition}}{sku} if ($variants{$var{composition}}{skuOverride}); + $var{available} = 0 unless ($variants{$var{composition}}{available}); + } + + if (exists $variants{$var{composition}}) { + $var{variantId} = $variants{$var{composition}}{variantId}, + } else { + $var{variantId} = WebGUI::Id::generate; + } + + push (@newVariants, {%var}); + $newVariants{$var{variantId}} = {%var}; + } + + WebGUI::SQL->write("delete from productVariants where productId=".quote($self->get('productId'))); + foreach (values %newVariants) { + WebGUI::SQL->write("insert into productVariants (variantId, productId, composition, price, weight, sku, available) values ". + "(".quote($_->{variantId}).", ".quote($_->{productId}).", ".quote($_->{composition}).", ".quote($_->{price}). + ", ".quote($_->{weight}).", ".quote($_->{sku}).", ".quote($_->{available}).")"); + } + + $self->{_variants} = \%newVariants; +} + +1;