Skip to content

Commit

Permalink
Neuer Backgroundjob zum Massen-generieren von Shop Artikeln aus Artikeln
Browse files Browse the repository at this point in the history
x
  • Loading branch information
rebootl committed Feb 28, 2024
1 parent 6e00af5 commit 178b73d
Showing 1 changed file with 240 additions and 0 deletions.
240 changes: 240 additions & 0 deletions SL/BackgroundJob/ShopPartMassCreate.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
package SL::BackgroundJob::ShopPartMassCreate;

use strict;

use parent qw(SL::BackgroundJob::Base);

use List::Util qw(first);
use File::MimeInfo::Magic; # for mimetype
use File::Slurp; # for read_file

use SL::Shop;
use SL::DB::Part;
use SL::DB::ShopPart;
use SL::DB::File;
use SL::CVar;
use SL::File;

use Data::Dumper;

sub recurse_categories {
my ($categories, $categories_by_names) = @_;
foreach my $category (@{ $categories }) {
${ $categories_by_names }{$category->{name}} = $category->{id};
recurse_categories($category->{children}, $categories_by_names);
}
}

sub get_shop_part {
my ($part_id, $shop_id) = @_;
my $exists = SL::DB::Manager::ShopPart->find_by( part_id => $part_id, shop_id => $shop_id );
if ($exists) {
return $exists;
}
return SL::DB::ShopPart->new( part_id => $part_id, shop_id => $shop_id );
}

sub get_shop_categories {
my ($cvar_categories, $categories_by_names) = @_;
# split on the pipe character
my @categories_names = split(/\|/, $cvar_categories);

my @shop_categories;
foreach my $category_name (@categories_names) {
# if the category exists in the shop
if (exists $categories_by_names->{$category_name}) {
push @shop_categories, [
$categories_by_names->{$category_name},
$category_name
];
}
}
return \@shop_categories;
}

sub warn {
my ($messages, $message) = @_;
$main::lxdebug->message(LXDEBUG::WARN(), $message);
push @$messages, $message;
}

sub run {
my ($self, $db_obj) = @_;
my $data = $db_obj->data_as_hash;

# get parameters
my $shop_id = $data->{shop_id} || 1;
my $images_import_path = $data->{images_import_path} || 'shopimages/product/';
my $cvar_categories = $data->{cvar_categories} || 'vm_product_categories';

my @messages;

# initialize shop
my $shop_config = SL::DB::Manager::Shop->get_first( query => [ id => $shop_id ] );
my $shop = SL::Shop->new( config => $shop_config );

# get the categories from the shop
my $connect = $shop->check_connectivity;
if (!$connect->{success}) {
return 'Error: could not connect to shop';
}
my $categories_shopdata = $shop->connector->get_categories();
if (!$categories_shopdata) {
return 'Error: could not get categories from shop';
}

# generate a hash of the category names and their ids
my %categories_by_names;
recurse_categories($categories_shopdata, \%categories_by_names);

# get all the parts from the database, that are marked as shop parts
my $parts = SL::DB::Manager::Part->get_all(query => [ shop => 1 ]);

# for every part
for my $part (@{ $parts }) {

# check if shop part already exists
my $shop_part = get_shop_part($part->id, $shop_id);

# get the custom variables from the part
my $cvars = CVar->get_custom_variables(module => 'IC', trans_id => $part->id);
my $cvar_categories = first { $_->{name} eq $cvar_categories } @{ $cvars };

# assign categories
my $shop_categories = get_shop_categories($cvar_categories->{value}, \%categories_by_names);

$shop_part->assign_attributes(
shop_description => '',
front_page => '',
active => 1,
shop_category => $shop_categories,
active_price_source => 'master_data/sellprice',
metatag_keywords => '',
metatag_description => '',
metatag_title => '',
);

$shop_part->save;
$main::lxdebug->message(LXDebug->DEBUG1(), 'Shop part saved: ' . $shop_part->id);

if (!$shop_part->id) {
warn(\@messages, 'Warning: shop part not saved, part id: ' . $part->id . ' part number: ' . $part->partnumber);
next;
}

# handle the images,
# the file names are under part->image

if (!$part->image) {
# go to next part if no images are found
next;
}

# get existing images from shop part
my $image_files = SL::DB::Manager::File->get_all( where => [ object_id => $part->id, object_type => 'shop_image' ] );

my %images_by_names = map { $_->{file_name} => $_ } @{ $image_files };

for my $image_name (split '\|', $part->image) {

my $fileobj;
if (exists $images_by_names{$image_name}) {
# I tried updating the file, but it didn't work right away
# so instead I delete the file and create a new one
# (this is also the way it is done in the UI, there's only a delete button,
# no update button)
$images_by_names{$image_name}->delete;
}

my $image_path = $images_import_path . $image_name;

# uses File::MimeInfo::Magic
my $mime_type = mimetype($image_path);

# read file data into memory
my $file_data = File::Slurp::read_file($image_path);

$fileobj = SL::File->save(
object_id => $part->id,
object_type => 'shop_image',
mime_type => $mime_type,
source => 'uploaded',
file_type => 'image',
file_name => $image_name,
title => substr($part->description, 0, 45),
description => '',
file_contents => $file_data,
file_path => $image_path,
);
if (!$fileobj) {
warn(\@messages, 'Warning: file not saved for part: ' . $part->id . ' file: ' . $image_name);
}
}
}

if (@messages) {
return join("\n", @messages);
}
return 'Shop parts created successfully';
}

1;

__END__
=encoding utf8
=head1 NAME
SL::BackgroundJob::ShopPartMassCreateRevamp - Background job to create shop
parts for all parts in the database that are marked as shop parts.
=head1 SYNOPSIS
This background job provides the basic functionality to create shop parts for
all parts in the database that are marked as shop parts.
It can also import images from a directory and assign them to the respective
shop parts. See configuration below.
It also assigns categories to the shop parts based on a custom variable of the
part.
The script may need individual adjustments to fit your specific use case.
=head1 CONFIGURATION
Accepts the following parameters:
=over 4
=item C<shop_id>
The id of the shop to create the shop parts in, defaults to 1
=item C<images_import_path>
The path to the images to import, defaults to 'shopimages/product/'
The file names of the images should be present in the 'image' field of the part,
in the following format:
image1.jpg|image2.png|image3.gif
The images themselves should be present in the images_import_path.
=item C<cvar_categories>
The name of the custom variable that contains the categories, defaults to 'vm_product_categories'
Expects the Categories to be set in the custom variable of the part in the following format:
Category1|Category2|Category3
Categories should be present in the shop under the same names.
=back
=head1 AUTHOR
Cem Aydin E<lt>[email protected]E<gt>
=cut

0 comments on commit 178b73d

Please sign in to comment.