Revision 391 (by ahitrov, 2013/10/30 12:19:06) add_wishlist() method
package webshop::Keeper;

use strict;
use warnings 'all';
use base qw(Contenido::Keeper);

use Data::Dumper;
use Contenido::Globals;
use webshop::Basket;
use webshop::SQL::Basket;

sub add_item {
  my $self = shift;
  my $object = shift;
  my (%options) = @_;

  return	unless ref $object;
  return	unless $object->item_id && $object->number;
  return	unless $object->uid || $object->session;


  my %opts;
  if ( $object->uid ) {
	$opts{uid} = $object->uid;
  } elsif ( $object->session ) {
	$opts{session} = $object->session;
  }
  my @items = $keeper->get_documents (
		class	=> 'webshop::Basket',
		status	=> [0,1],
		order_id=> 0,
		%opts,
	);
  my $total = 0;
  my $sum = 0;
  my $found = 0;
  if ( @items ) {
	foreach my $item ( @items ) {
		if ( $object->item_id == $item->item_id && $object->color_id == $item->color_id && $object->size_id == $item->size_id ) {
			$item->number($item->number + $object->number);
			$item->status(1);
			$item->store;
			$found = 1;
		}
		$total += $item->number;
		$sum += $item->number * $item->price;
	}
  }
  unless ( $found ) {
	$total += $object->number;
	$sum += $object->number * $object->price;
	$object->order_id(0);
	$object->store;
  }
  my @plugins = split (/[\ |\t]+/, $state->{plugins});
  if ( grep { $_ eq 'session' } @plugins && ref $session ) {
	$session->set ( basket_total => $total, basket_sum => $sum );
  }
  return ($total, $sum);
}

sub add_wishlist {
  my $self = shift;
  my $object = shift;
  my (%options) = @_;

  return	unless ref $object;
  return	unless $object->item_id && $object->number;
  return	unless $object->uid || $object->session;


  my %opts;
  if ( $object->uid ) {
	$opts{uid} = $object->uid;
  } elsif ( $object->session ) {
	$opts{session} = $object->session;
  }
  my @items = $keeper->get_documents (
		class	=> 'webshop::Basket',
		status	=> 0,
		order_id=> 0,
		%opts,
	);
  my $total = 0;
  my $sum = 0;
  my $found = 0;
  if ( @items ) {
	foreach my $item ( @items ) {
		if ( $object->item_id == $item->item_id && $object->color_id == $item->color_id && ($object->size_id == $item->size_id || $object->size eq $item->size) ) {
			$item->number($item->number + $object->number);
			$item->store;
			$found = 1;
		}
		$total += $item->number;
		$sum += $item->number * $item->price;
	}
  }
  unless ( $found ) {
	$total += $object->number;
	$sum += $object->number * $object->price;
	$object->order_id(0);
	$object->store;
  }
  return ($total, $sum);
}

### Метод приведения корзины для пользователя в момент логина
#############################################################
sub merge_basket {
  my $self = shift;
  my (%opts) = @_;

  warn "Merge begin: ".Dumper(\%opts)."\n"		if $DEBUG;
  return	unless $opts{uid} && $opts{session};

  my @items = $keeper->get_documents (
		class	=> 'webshop::Basket',
		status	=> [1,0],
		order_id=> 0,
		session	=> $opts{session},
	);
  foreach my $item ( @items ) {
	$item->session(undef);
	$item->uid( $opts{uid} );
	$item->store;
  }
  @items = $keeper->get_documents (
		class	=> 'webshop::Basket',
		status	=> 1,
		order_id=> 0,
		uid	=> $opts{uid},
	);
  my $total = 0;
  my $sum = 0;
  foreach my $item ( @items ) {
	$total += $item->number;
	$sum += $item->number * $item->price;
  }
  my @plugins = split (/[\ |\t]+/, $state->{plugins});
  if ( grep { $_ eq 'session' } @plugins && ref $session ) {
	$session->set ( basket_total => $total, basket_sum => $sum );
  }
  warn "Merge end\n"		if $DEBUG;
  return ($total, $sum);
}


sub get_basket {
  my $self = shift;
  my (%opts) = @_;

  return	unless $opts{uid} || $opts{session} || $opts{order_id};

  my $uid = delete $opts{uid};
  my $session_id = delete $opts{session};
  unless ( exists $opts{order_id} && $opts{order_id} ) {
	$opts{order_id} = 0;
	if ( $uid ) {
		$opts{uid} = $uid;
	} elsif ( $session_id ) {
		$opts{session} = $session_id;
	}
  }
  $opts{status} = 1	unless exists $opts{status} && defined $opts{status};
  my @items = $keeper->get_documents (
		class	=> 'webshop::Basket',
		%opts,
	);
  my $total = 0;
  my $sum = 0;
  foreach my $item ( @items ) {
	if ( $item->status == 1 ) {
		$total += $item->number;
		$sum += $item->number * $item->price;
	}
  }
  my @plugins = split (/[\ |\t]+/, $state->{plugins});
  if ( grep { $_ eq 'session' } @plugins && ref $session ) {
	$session->set ( basket_total => $total, basket_sum => $sum );
  }
  return \@items;
}


sub basket_count {
    my $self = shift;
    my $basket = shift;
    return (0,0)	unless ref $basket eq 'ARRAY' && @$basket;

    my $total = 0;
    my $sum = 0;
    foreach my $item ( @$basket ) {
	if ( $item->status == 1 ) {
		$total += $item->number;
		$sum += $item->number * $item->price;
	}
    }
    return ($total, $sum);
}


sub clear_basket {
  my $self = shift;
  my (%opts) = @_;

  return	unless exists $opts{uid} || exists $opts{session};

  my $table_name = webshop::SQL::Basket->db_table;
  my $request = "delete from $table_name where order_id = 0 AND status = 1 AND";
  my $dbh = $keeper->SQL;
  my @vals;
  if ( exists $opts{uid} && $opts{uid} ) {
	$request .= " uid in (?)";
	push @vals, $opts{uid};
  } elsif ( exists $opts{session} ) {
	$request .= " session in (?)";
	push @vals, $opts{session};
  }
  warn "CLEAR: [$request]. VALS: [".join(',',@vals)."]\n"	if $DEBUG;
  my $statement = $dbh->prepare ($request);
  $statement->execute( @vals ) || $log->error("DBI execute error on $request\n"."\ncalled with opts:\n".Data::Dumper::Dumper(\%opts));;
  $statement->finish;

  my @plugins = split (/[\ |\t]+/, $state->{plugins});
  if ( grep { $_ eq 'session' } @plugins && ref $session ) {
	$session->set ( basket_total => 0, basket_sum => 0 );
  }
}


sub clear_wishlist {
  my $self = shift;
  my (%opts) = @_;

  return	unless exists $opts{uid} || exists $opts{session};

  my $table_name = webshop::SQL::Basket->db_table;
  my $request = "delete from $table_name where order_id = 0 AND status = 0 AND";
  my $dbh = $keeper->SQL;
  my @vals;
  if ( exists $opts{uid} ) {
	$request .= " uid in (?)";
	push @vals, $opts{uid};
  } elsif ( exists $opts{session} ) {
	$request .= " session in (?)";
	push @vals, $opts{session};
  }
  my $statement = $dbh->prepare ($request);
  $statement->execute( @vals ) || $log->error("DBI execute error on $request\n"."\ncalled with opts:\n".Data::Dumper::Dumper(\%opts));;
  $statement->finish;
}


### Метод пересчета корзины
# Принимает на вход параметры:
#	session		=> session_id пользователя
#	uid		=> UID пользователя
#	delete		=> массив или отдельный item_id
#	renumber	=> ссылка на хеш вида item => number
#############################################################
sub recount {
  my $self = shift;
  my (%opts) = @_;

  warn "Recount Started!!!\n"			if $DEBUG;
  return	unless exists $opts{uid} || exists $opts{session} || exists $opts{order_id};
  my $basket = $self->get_basket ( %opts );
  return	unless ref $basket eq 'ARRAY' && @$basket;

  warn Dumper(\%opts)				if $DEBUG;

  my $total = 0;
  my $sum = 0;
  my @new_basket;
  my $session_no_store = delete $opts{session_no_store};
  foreach my $item ( @$basket ) {
	my $delete = 0;
	if ( exists $opts{renumber} && ref $opts{renumber} eq 'HASH' && exists $opts{renumber}{$item->id} && int($opts{renumber}{$item->id}) == 0 ) {
		$delete = 1;
	} elsif ( exists $opts{delete} && ref $opts{delete} eq 'ARRAY' ) {
		$delete = 1	if grep { $_ == $item->id } @{ $opts{delete} };
	} elsif ( exists $opts{delete} && $opts{delete} ) {
		$delete = 1	if $item->id == $opts{delete};
	}
	if ( $delete ) {
		warn "Item ID=".$item->id." DELETE\n"	if $DEBUG;
		$item->delete();
		next;
	} else {
		my $store = 0;
		if ( exists $opts{renumber} && ref $opts{renumber} eq 'HASH' && exists $opts{renumber}{$item->id} && $opts{renumber}{$item->id} != $item->number ) {
			$item->number( $opts{renumber}{$item->id} );
			$store = 1;
		}
		if ( exists $opts{price} && ref $opts{price} eq 'HASH' && exists $opts{price}{$item->id} && $opts{price}{$item->id} != $item->price ) {
			$item->price( $opts{price}{$item->id} );
			$store = 1;
		}
		$item->store	if $store;
		$total += $item->number;
		$sum += $item->number * $item->price;
		push @new_basket, $item;
	}
  }
  my @plugins = split (/[\ |\t]+/, $state->{plugins});
  if ( !$session_no_store && grep { $_ eq 'session' } @plugins && ref $session ) {
	$session->set ( basket_total => $total, basket_sum => $sum );
  }
  return ($total, $sum, \@new_basket);
}


sub get_orders {
  my $self = shift;
  my (%opts) = @_;

  my $list = delete $opts{list};
  $opts{order_by} ||= 'status';
  my @items = $keeper->get_documents (
		class	=> 'webshop::Order',
		%opts,
	);
  if ( exists $opts{id} && defined $opts{id} && !ref $opts{id} ) {
	if ( $list ) {
		$items[0]->{list} = $self->get_order_list( order_id => $opts{id} );
	}
	return $items[0];
  } else {
	if ( $list ) {
		map { $_->{list} = $self->get_order_list( order_id => $_->id ) } @items;
	}
	return \@items;
  }
}


sub get_order_list {
  my $self = shift;
  my (%opts) = @_;

  return	unless $opts{order_id};

  $opts{status} = 1;
  my @items = $keeper->get_documents (
		class	=> 'webshop::Basket',
		%opts,
	);
  my $total = 0;
  my $sum = 0;
  foreach my $item ( @items ) {
	my $Item = $item->class->new( $keeper, $item->id );
	$item->{item} = $Item;
	if ( $item->status == 1 ) {
		$total += $item->number;
		$sum += $item->number * $item->price;
	}
  }
  return \@items;
}


### Метод приведения купонов для пользователя в момент логина
#############################################################
sub merge_coupons {
    my $self = shift;
    my (%opts) = @_;

    warn "Merge (coupons) begin: ".Dumper(\%opts)."\n"		if $DEBUG;
    return	unless $opts{uid} && $opts{session};

    my @items = $keeper->get_links (
		class	=> 'webshop::OrderCouponLink',
		session	=> $opts{session},
		source_id	=> 0,
	);
    my %merge_to = $keeper->get_links (
		class	=> 'webshop::OrderCouponLink',
		uid	=> $opts{uid},
		source_id	=> 0,
		return_mode	=> 'hash',
		hash_by		=> 'dest_id',
	);
    foreach my $item ( @items ) {
	if ( exists $merge_to{$item->dest_id} ) {
		$item->delete;
	} else {
		$item->session( undef );
		$item->uid( $opts{uid} );
		$item->store;
	}
    }
}



sub price_format {
	my $self = shift;
	my $price = shift;

	$price = reverse $price;
	$price =~ s/(\d{3})/$1\ /g;
	$price = reverse $price;

	return $price;
}


1;