webgui/lib/WebGUI/Product.pm
2006-11-03 04:36:13 +00:00

432 lines
14 KiB
Perl
Executable file

package WebGUI::Product;
use strict;
use WebGUI::Asset::Template;
#-------------------------------------------------------------------
sub _permute {
my ($currentSet, @permutations, @result);
$currentSet = shift;
@permutations = (@_) ? _permute(@_) : [];
foreach my $permutation (@permutations) {
foreach my $value (@$currentSet) {
push(@result, [$value, @{$permutation}]);
}
}
return @result;
}
#-------------------------------------------------------------------
sub addOptionToParameter {
my ($self, $parameterId, $properties, $optionId);
$self = shift;
$parameterId = shift;
$properties = shift || {};
$optionId = $self->session->id->generate;
$self->session->db->write("insert into productParameterOptions ".
"(optionId, parameterId) values ".
"(".$self->session->db->quote($optionId).", ".$self->session->db->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 = $self->session->id->generate;
$self->session->db->write("insert into productParameters (parameterId, productId) values ".
"(".$self->session->db->quote($parameterId).", ".$self->session->db->quote($self->get('productId')).")");
$self->{_parameters}->{$parameterId}->{parameterId} = $parameterId;
$self->{_parameters}->{$parameterId}->{options} = [];
return $parameterId;
}
#-------------------------------------------------------------------
sub delete {
my ($self) = shift;
foreach (@{$self->getParameter}) {
$self->session->db->write("delete from productParameterOptions where parameterId=".$self->session->db->quote($_->{parameterId}));
}
$self->session->db->write("delete from productParameters where productId=".$self->session->db->quote($self->get('productId')));
$self->session->db->write("delete from productVariants where productId=".$self->session->db->quote($self->get('productId')));
$self->session->db->write("delete from products where productId=".$self->session->db->quote($self->get('productId')));
return undef;
}
#-------------------------------------------------------------------
sub deleteParameter {
my ($self, $parameterId);
$self = shift;
$parameterId = shift;
$self->session->db->write("delete from productParameterOptions where parameterId=".$self->session->db->quote($parameterId));
$self->session->db->write("delete from productParameters where parameterId=".$self->session->db->quote($parameterId));
$self->updateVariants;
return undef;
}
#-------------------------------------------------------------------
sub deleteOption {
my ($self, $optionId, @options, $parameterId);
$self = shift;
$optionId = shift;
$self->session->db->write("delete from productParameterOptions where optionId=".$self->session->db->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;
my $session = shift;
$optionId = shift;
($productId) = $session->db->quickArray("select productId from productParameters as t1, productParameterOptions as t2 ".
"where t1.parameterId=t2.parameterId and t2.optionId=".$session->db->quote($optionId));
return undef unless ($productId);
return WebGUI::Product->new($session,$productId);
}
#-------------------------------------------------------------------
sub getByParameterId {
my ($class, $parameterId, $productId);
$class = shift;
my $session = shift;
$parameterId = shift;
($productId) = $session->db->quickArray("select productId from productParameters where parameterId=".$session->db->quote($parameterId));
return WebGUI::Product->new($session,$productId);
}
#-------------------------------------------------------------------
sub getByVariantId {
my ($class, $productId, $variantId);
$class = shift;
my $session = shift;
$variantId = shift;
($productId) = $session->db->quickArray("select productId from productVariants where variantId=".$session->db->quote($variantId));
return WebGUI::Product->new($session,$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;
my $session = shift;
$productId = shift;
$session->errorHandler->fatal('no productId') unless ($productId);
$parameters = {};
$variants = {};
$options = {};
if ($productId eq 'new') {
$productId = $session->id->generate;
$properties = {productId => $productId};
$session->db->write("insert into products (productId) values (".$session->db->quote($productId).")");
} else {
$properties = $session->db->quickHashRef("select * from products where productId=".$session->db->quote($productId));
# fetch parameters and options
$sth = $session->db->read("select opt.*, param.* from productParameters as param left join productParameterOptions as opt ".
"on param.parameterId=opt.parameterId where param.productId=".$session->db->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 = $session->db->read("select * from productVariants where productId=".$session->db->quote($productId));
while (%row = $sth->hash) {
$variants->{$row{variantId}} = {%row};
}
$new = 0;
}
bless {_session=> $session, _properties => $properties, _parameters => $parameters, _options => $options, _variants => $variants, _new => $new}, $class;
}
#-------------------------------------------------------------------
=head2 session ( )
Returns a reference to the session.
=cut
sub session {
my $self = shift;
return $self->{_session};
}
#-------------------------------------------------------------------
sub set {
my ($self, $properties);
$self = shift;
$properties = shift;
$self->session->db->write("update products set ".join(', ', map {$_."=".$self->session->db->quote($properties->{$_})} keys(%$properties)).
" where productId=".$self->session->db->quote($self->get('productId')));
foreach (keys(%$properties)) {
$self->{_properties}->{$_} = $properties->{$_};
}
$self->updateVariants;
}
#-------------------------------------------------------------------
sub setParameter {
my ($self, $parameterId, $properties);
$self = shift;
$parameterId = shift;
$properties = shift;
$self->session->db->write("update productParameters set ".join(', ', map {$_."=".$self->session->db->quote($properties->{$_})} keys(%$properties)).
" where parameterId=".$self->session->db->quote($parameterId));
map {$self->{_parameter}->{$parameterId}->{$_} = $properties->{$_}} keys %$properties;
}
#-------------------------------------------------------------------
sub setOption {
my ($self, $optionId, $properties);
$self = shift;
$optionId = shift;
$properties = shift;
$self->session->db->write("update productParameterOptions set ".join(', ', map {$_."=".$self->session->db->quote($properties->{$_})} keys(%$properties)).
" where optionId=".$self->session->db->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->session, $self->get('skuTemplate'), \%sku );
if (defined $properties->{price}) {
if ($properties->{price} ne '') {
push(@pairs, 'price='.$self->session->db->quote($properties->{price}).', priceOverride=1');
} else {
push(@pairs, 'price='.$self->session->db->quote($original->{price}).', priceOverride=0');
}
}
if (defined $properties->{weight}) {
if ($properties->{weight} ne '') {
push(@pairs, 'weight='.$self->session->db->quote($properties->{weight}).', weightOverride=1');
} else {
push(@pairs, 'weight='.$self->session->db->quote($original->{weight}).', weightOverride=0');
}
}
if (defined $properties->{sku}) {
if ($properties->{sku} ne '') {
push(@pairs, 'sku='.$self->session->db->quote($properties->{sku}).', skuOverride=1');
} else {
push(@pairs, 'sku='.$self->session->db->quote($original->{sku}).', skuOverride=0');
}
}
push(@pairs, 'available='.$self->session->db->quote($properties->{available})) if (defined $properties->{available});
$self->session->db->write("update productVariants set ".join(', ', @pairs)." where variantId=".$self->session->db->quote($variantId)) if (@pairs);
$self->{_variants}->{$variantId} = {%{$self->{_variants}->{$variantId}}, %$properties};
}
#-------------------------------------------------------------------
sub updateVariants {
my ($self, %variants, @optionSets, @variants, %var, @composition, @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 my $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 my $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->session, $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} = $self->session->id->generate;
}
push (@newVariants, {%var});
$newVariants{$var{variantId}} = {%var};
}
$self->session->db->write("delete from productVariants where productId=".$self->session->db->quote($self->get('productId')));
foreach (values %newVariants) {
$self->session->db->write("insert into productVariants (variantId, productId, composition, price, weight, sku, available) values ".
"(".$self->session->db->quote($_->{variantId}).", ".$self->session->db->quote($_->{productId}).", ".$self->session->db->quote($_->{composition}).", ".$self->session->db->quote($_->{price}).
", ".$self->session->db->quote($_->{weight}).", ".$self->session->db->quote($_->{sku}).", ".$self->session->db->quote($_->{available}).")");
}
$self->{_variants} = \%newVariants;
}
1;