From b283ebaf81a4ca74663b3d6816f3287a3c92a9b1 Mon Sep 17 00:00:00 2001 From: Colin Kuskie Date: Tue, 27 May 2008 00:32:25 +0000 Subject: [PATCH] begin work on importing products --- lib/WebGUI/Shop/Products.pm | 118 ++++++++++++++++++++++++++++++++++++ t/Shop/Products.t | 78 ++++++++++++++++++++++++ 2 files changed, 196 insertions(+) create mode 100644 lib/WebGUI/Shop/Products.pm create mode 100644 t/Shop/Products.t diff --git a/lib/WebGUI/Shop/Products.pm b/lib/WebGUI/Shop/Products.pm new file mode 100644 index 000000000..1f6d1d5ac --- /dev/null +++ b/lib/WebGUI/Shop/Products.pm @@ -0,0 +1,118 @@ +package WebGUI::Shop::Products; + +use strict; + +use WebGUI::Text; +use WebGUI::Storage; +use WebGUI::Exception::Shop; +use WebGUI::Shop::Admin; +use WebGUI::Asset::Sku::Product; + +=head1 NAME + +Package WebGUI::Shop::Products + +=head1 DESCRIPTION + +This package handles importing and exporting products into the Shop system, mainly +to be compatible with third-party systems, such as inventory control. If you want to +export your Products into another WebGUI site, please use the Asset Export system +instead. + +=head1 METHODS + +These subroutines are available from this package: + +=cut + +#------------------------------------------------------------------- + +=head2 importProducts ( $session, $filePath ) + +Import products into the WebGUI system. If the master sku of a product +exists in the system, it will be updated. If master skus do not exist, +they will be added. + +The first line of the file should contain only the name of the columns, +in any order. It may not contain comments. + +These are the column names, each is required: + +=over 4 + +=item * + +mastersku + +=item * + +sku + +=item * + +title + +=item * + +shortdescription + +=item * + +price + +=item * + +weight + +=item * + +quantity + +=back + + +The following lines will contain product information. Blank +lines and anything following a '#' sign will be ignored from +the second line of the file, on to the end. + +Returns 1 if the import has taken place. This is to help you know +if old data has been deleted and new has been inserted. + +=cut + +sub importProducts { + my $session = shift; + my $filePath = shift; + WebGUI::Error::InvalidParam->throw(error => q{Must provide the path to a file}) + unless $filePath; + WebGUI::Error::InvalidFile->throw(error => qq{File could not be found}, brokenFile => $filePath) + unless -e $filePath; + WebGUI::Error::InvalidFile->throw(error => qq{File is not readable}, brokenFile => $filePath) + unless -r $filePath; + open my $table, '<', $filePath or + WebGUI::Error->throw(error => qq{Unable to open $filePath for reading: $!\n}); + my $headers; + $headers = <$table>; + chomp $headers; + my @headers = WebGUI::Text::splitCSV($headers); + WebGUI::Error::InvalidFile->throw(error => qq{Bad header found in the CSV file}, brokenFile => $filePath) + unless (join(q{-}, sort @headers) eq 'city-code-country-state-taxRate') + and (scalar @headers == 5); + my @productData = (); + my $line = 1; + while (my $productRow = <$table>) { + chomp $productRow; + $productRow =~ s/\s*#.+$//; + next unless $productRow; + local $_; + my @productRow = map { tr/|/,/; $_; } WebGUI::Text::splitCSV($productRow); + WebGUI::Error::InvalidFile->throw(error => qq{Error found in the CSV file}, brokenFile => $filePath, brokenLine => $line) + unless scalar @productRow == 5; + push @productData, [ @productRow ]; + } + ##Okay, if we got this far, then the data looks fine. + return unless scalar @productData; + return 1; +} + +1; diff --git a/t/Shop/Products.t b/t/Shop/Products.t new file mode 100644 index 000000000..a2f186812 --- /dev/null +++ b/t/Shop/Products.t @@ -0,0 +1,78 @@ +# vim:syntax=perl +#------------------------------------------------------------------- +# WebGUI is Copyright 2001-2008 Plain Black Corporation. +#------------------------------------------------------------------- +# Please read the legal notices (docs/legal.txt) and the license +# (docs/license.txt) that came with this distribution before using +# this software. +#------------------------------------------------------------------ +# http://www.plainblack.com info@plainblack.com +#------------------------------------------------------------------ + +# Write a little about what this script tests. +# +# + +use FindBin; +use strict; +use lib "$FindBin::Bin/../lib"; +use Test::More; +use Test::Deep; +use Exception::Class; +use Data::Dumper; + +use WebGUI::Test; # Must use this before any other WebGUI modules +use WebGUI::Session; +use WebGUI::Text; + +#---------------------------------------------------------------------------- +# Init +my $session = WebGUI::Test->session; + +#---------------------------------------------------------------------------- +# Tests + +my $tests = 5; +plan tests => 1 + $tests; + +#---------------------------------------------------------------------------- +# put your tests here + +my $loaded = use_ok('WebGUI::Shop::Products'); + +my $storage; +my $e; + +SKIP: { + + skip 'Unable to load module WebGUI::Shop::Products', $tests unless $loaded; + + ####################################################################### + # + # import + # + ####################################################################### + + eval { WebGUI::Shop::Products::importProducts($session); }; + $e = Exception::Class->caught(); + isa_ok($e, 'WebGUI::Error::InvalidParam', 'importProducts: error handling for an undefined path to file'); + is($e->error, 'Must provide the path to a file', 'importProducts: error handling for an undefined path to file'); + + eval { WebGUI::Shop::Products::importProducts($session, '/path/to/nowhere'); }; + $e = Exception::Class->caught(); + isa_ok($e, 'WebGUI::Error::InvalidFile', 'importProducts: error handling for file that does not exist in the filesystem'); + is($e->error, 'File could not be found', 'importProducts: error handling for file that does not exist in the filesystem'); + cmp_deeply( + $e, + methods( + brokenFile => '/path/to/nowhere', + ), + 'importTaxData: error handling for file that does not exist in the filesystem', + ); + +} + +#---------------------------------------------------------------------------- +# Cleanup +END { +}