432 lines
14 KiB
Perl
Executable file
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;
|