Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 75b1036d

Von Werner Hahn vor mehr als 6 Jahren hinzugefügt

  • ID 75b1036d62695266c3670a2dfd4370c2265549fb
  • Vorgänger d6de8b23
  • Nachfolger 50dba889

Shopmodul: ShopPart: Artikel hochladen und Anzeigen

Webshop:: ShopPart

Webshop:: ShopPart

WebShop: ShopPart - Formatierungen ShopPart
Meldung bei Bildern wenn der Artikel noch keinem Shop zugeordnet ist

Conflicts:
templates/webpages/ic/tabs/_shop.html

Webshop: ShopPart Backgroundjob Upload

Conflicts:
SL/BackgroundJob/ShopPartMassUpload.pm
SL/ShopConnector/Shopware.pm
menus/user/10-shopimport.yaml
templates/webpages/shop_part/_list_articles.html
templates/webpages/shop_part/_transfer_status.html
templates/webpages/shop_part/_upload_status.html

Webshop: ShopPart - Webpart Filter nach Anbauer und Shop Anfang

Conflicts:
SL/Controller/ShopPart.pm

Webshop: ShopPart Menu

Conflicts:
menus/user/10-shopimport.yaml

Webshop: ShopPart

Webshop: ShopPart - Mergefehler in templates/webpages/ic/tabs/_shop.html

Conflicts:
templates/webpages/ic/tabs/_shop.html

Webshop: ShopPart

Conflicts:
templates/webpages/shop_part/_filter.html

WebShop: ShopPart - Unterschiedliche Uploadmöglichkeiten (Alles, Nur Preis, Nur Bestand, Bestand und Preis)

Conflicts:
menus/user/10-shopimport.yaml

Conflicts:
SL/Controller/ShopPart.pm
SL/ShopConnector/Shopware.pm
templates/webpages/shop_part/_list_articles.html

WebShop: ShopPart - Shopartikelliste Aktiv grafik

Conflicts:
SL/Controller/ShopPart.pm
SL/ShopConnector/Shopware.pm
js/kivi.shop_part.js
t/background_job/known_jobs.t

Conflicts:
SL/Controller/ShopPart.pm
SL/DB/ShopPart.pm
templates/webpages/ic/tabs/_shop.html

Unterschiede anzeigen:

SL/BackgroundJob/ShopPartMassUpload.pm
1
package SL::BackgroundJob::ShopPartMassUpload;
2
#ShopPartMassUpload
3
use strict;
4
use warnings;
5

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

  
8
use SL::DBUtils;
9
use SL::DB::ShopPart;
10
      use SL::Shop;
11

  
12
use constant WAITING_FOR_EXECUTION        => 0;
13
use constant UPLOAD_TO_WEBSHOP            => 1;
14
use constant DONE                         => 2;
15

  
16
# Data format:
17
# my $data                  = {
18
#     shop_part_record_ids       => [ 603, 604, 605],
19
#     num_order_created           => 0,
20
#     orders_ids                  => [1,2,3]
21
#     conversation_errors         => [ { id => 603 , item => 2, message => "Out of stock"}, ],
22
# };
23

  
24
sub update_webarticles {
25
  my ( $self ) = @_;
26

  
27
  my $job_obj = $self->{job_obj};
28
  my $db      = $job_obj->db;
29

  
30
  $job_obj->set_data(UPLOAD_TO_WEBSHOP())->save;
31

  
32
  foreach my $shop_part_id (@{ $job_obj->data_as_hash->{shop_part_record_ids} }) {
33
    my $data  = $job_obj->data_as_hash;
34
    eval {
35
      my $shop_part = SL::DB::Manager::ShopPart->find_by(id => $shop_part_id);
36
      unless($shop_part){
37
        push @{ $data->{conversion_errors} }, { id => $shop_part_id, number => '', message => 'Shoppart not found' };
38
      }
39

  
40
      my $shop = SL::Shop->new( config => $shop_part->shop );
41

  
42
      my $part_hash = $shop_part->part->as_tree;
43
      require SL::JSON;
44

  
45
      my $json      = SL::JSON::to_json($part_hash);
46
      my $return    = $shop->connector->update_part($shop_part, $json, $data->{todo});
47
      if ( $return == 1 ) {
48
        my $now = DateTime->now;
49
        my $attributes->{last_update} = $now;
50
        $shop_part->assign_attributes(%{ $attributes });
51
        $shop_part->save;
52
      }else{
53
      push @{ $data->{conversion_errors} }, { id => $shop_part_id, number => '', message => $return };
54
      }
55
      1;
56
    } or do {
57
      push @{ $data->{conversion_errors} }, { id => $shop_part_id, number => '', message => $@ };
58
    };
59

  
60
    $job_obj->update_attributes(data_as_hash => $data);
61
  }
62
}
63

  
64
sub run {
65
  my ($self, $job_obj) = @_;
66

  
67
  $self->{job_obj}         = $job_obj;
68
  $self->update_webarticles;
69

  
70
  $job_obj->set_data(status => DONE())->save;
71

  
72
  return 1;
73
}
74
1;
SL/Controller/ShopPart.pm
5 5

  
6 6
use parent qw(SL::Controller::Base);
7 7

  
8
use SL::BackgroundJob::ShopPartMassUpload;
9
use SL::System::TaskServer;
8 10
use Data::Dumper;
9 11
use SL::Locale::String qw(t8);
10 12
use SL::DB::ShopPart;
......
12 14
use SL::Controller::FileUploader;
13 15
use SL::DB::Default;
14 16
use SL::Helper::Flash;
17
use MIME::Base64;
15 18

  
16 19
use Rose::Object::MakeMethods::Generic
17 20
(
18 21
   scalar                 => [ qw(price_sources) ],
19
  'scalar --get_set_init' => [ qw(shop_part file) ],
22
  'scalar --get_set_init' => [ qw(shop_part file shops producers) ],
20 23
);
21 24

  
22 25
__PACKAGE__->run_before('check_auth');
23
__PACKAGE__->run_before('add_javascripts', only => [ qw(edit_popup) ]);
26
__PACKAGE__->run_before('add_javascripts', only => [ qw(edit_popup list_articles) ]);
24 27
__PACKAGE__->run_before('load_pricesources',    only => [ qw(create_or_edit_popup) ]);
25 28

  
26 29
#
......
31 34
  my ($self) = @_;
32 35

  
33 36
  $self->render_shop_part_edit_dialog();
34
};
37
}
35 38

  
36 39
sub action_update_shop {
37 40
  my ($self, %params) = @_;
38 41

  
39 42
  my $shop_part = SL::DB::Manager::ShopPart->find_by(id => $::form->{shop_part_id});
40 43
  die unless $shop_part;
44

  
41 45
  require SL::Shop;
42 46
  my $shop = SL::Shop->new( config => $shop_part->shop );
43 47

  
44
  # data to upload to shop. Goes to SL::Connector::XXXConnector.
45 48
  my $part_hash = $shop_part->part->as_tree;
46 49
  my $json      = SL::JSON::to_json($part_hash);
47
  my $return    = $shop->connector->update_part($self->shop_part, $json);
50
  my $return    = $shop->connector->update_part($self->shop_part, $json,'all');
48 51

  
49 52
  # the connector deals with parsing/result verification, just needs to return success or failure
50 53
  if ( $return == 1 ) {
......
59 62
    $self->js->flash('error', t8('The shop part wasn\'t updated.'))->render;
60 63
  };
61 64

  
62
};
65
}
63 66

  
64 67
sub action_show_files {
65 68
  my ($self) = @_;
66 69

  
67
  require SL::DB::File;
68 70
  my $images = SL::DB::Manager::File->get_all_sorted( where => [ trans_id => $::form->{id}, modul => $::form->{modul}, file_content_type => { like => 'image/%' } ], sort_by => 'position' );
69 71

  
70 72
  $self->render('shop_part/_list_images', { header => 0 }, IMAGES => $images);
......
114 116
  my @file_errors = $self->file->validate if $attributes->{file_content};;
115 117
  push @errors,@file_errors if @file_errors;
116 118

  
117

  
118 119
  return $self->js->error(@errors)->render($self) if @errors;
119 120

  
120 121
  $self->file->file_update_type_and_dimensions if $attributes->{file_content};
......
153 154
  $self->js->render;
154 155
}
155 156

  
156
# old:
157
# sub action_edit {
158
#   my ($self) = @_;
159
#
160
#   $self->render('shop_part/edit'); #, { output => 0 }); #, price_source => $price_source)
161
# }
162
#
163
# used when saving existing ShopPart
164

  
165 157
sub action_update {
166 158
  my ($self) = @_;
167 159

  
......
173 165

  
174 166
  my ( $price, $price_src_str ) = $self->get_price_n_pricesource($::form->{pricesource});
175 167

  
176
  #TODO Price must be formatted. $price_src_str must be translated
177
  $self->js->html('#price_' . $self->shop_part->id, $price)
168
  $self->js->html('#price_' . $self->shop_part->id, $::form->format_amount(\%::myconfig,$price,2))
178 169
           ->html('#active_price_source_' . $self->shop_part->id, $price_src_str)
179 170
           ->render;
180 171
}
181 172

  
182 173
sub action_show_stock {
183 174
  my ($self) = @_;
184
  my ( $stock_local, $stock_onlineshop );
175
  my ( $stock_local, $stock_onlineshop, $active_online );
185 176

  
186 177
  require SL::Shop;
187 178
  my $shop = SL::Shop->new( config => $self->shop_part->shop );
188
  my $shop_article = $shop->connector->get_article($self->shop_part->part->partnumber);
179

  
180
  if($self->shop_part->last_update) {
181
    my $shop_article = $shop->connector->get_article($self->shop_part->part->partnumber);
182
    $stock_onlineshop = $shop_article->{data}->{mainDetail}->{inStock};
183
    $active_online = $shop_article->{data}->{active};
184
    #}
189 185

  
190 186
  $stock_local = $self->shop_part->part->onhand;
191
  $stock_onlineshop = $shop_article->{data}->{mainDetail}->{inStock};
192 187

  
193
  $self->js->html('#stock_' . $self->shop_part->id, $stock_local."/".$stock_onlineshop)
188
  $self->js->html('#stock_' . $self->shop_part->id, $::form->format_amount(\%::myconfig,$stock_local,0)."/".$::form->format_amount(\%::myconfig,$stock_onlineshop,0))
189
           ->html('#toogle_' . $self->shop_part->id,$active_online)
194 190
           ->render;
195 191
}
196 192

  
193
sub action_get_n_write_categories {
194
  my ($self) = @_;
195

  
196
  my @shop_parts =  @{ $::form->{shop_parts_ids} || [] };
197
  foreach my $part(@shop_parts){
198

  
199
    my $shop_part = SL::DB::Manager::ShopPart->get_all( where => [id => $part], with_objects => ['part', 'shop'])->[0];
200
    require SL::DB::Shop;
201
    my $shop = SL::Shop->new( config => $shop_part->shop );
202
    my $online_article = $shop->connector->get_article($shop_part->part->partnumber);
203
    my $online_cat = $online_article->{data}->{categories};
204
    my @cat = ();
205
    for(keys %$online_cat){
206
    # The ShopwareConnector works with the CategoryID @categories[x][0] in others/new Connectors it must be tested
207
    # Each assigned categorie is saved with id,categorie_name an multidimensional array and could be expanded with categoriepath or what is needed
208
      my @cattmp;
209
      push( @cattmp,$online_cat->{$_}->{id} );
210
      push( @cattmp,$online_cat->{$_}->{name} );
211
      push( @cat,\@cattmp );
212
    }
213
    my $attributes->{shop_category} = \@cat;
214
    my $active->{active} = $online_article->{data}->{active};
215
    $shop_part->assign_attributes(%{$attributes}, %{$active});
216
    $shop_part->save;
217
  }
218
  $self->redirect_to( action => 'list_articles' );
219
}
197 220

  
198 221
sub create_or_update {
199 222
  my ($self) = @_;
......
214 237
  # $self->js->val('#partnumber', 'ladida');
215 238
  $self->js->html('#shop_part_description_' . $self->shop_part->id, $self->shop_part->shop_description)
216 239
           ->html('#shop_part_active_' . $self->shop_part->id, $self->shop_part->active)
217
           ->html('#price_' . $self->shop_part->id, $price)
240
           ->html('#price_' . $self->shop_part->id, $::form->format_amount(\%::myconfig,$price,2))
218 241
           ->html('#active_price_source_' . $self->shop_part->id, $price_src_str)
219 242
           ->run('kivi.shop_part.close_dialog')
220 243
           ->flash('info', t8("Updated shop part"))
......
241 264
  my ($self) = @_;
242 265

  
243 266
  my @categories =  @{ $::form->{categories} || [] };
244
  $main::lxdebug->dump(0, 'WH: KATEGORIEN: ', \@categories);
245
  my @cat = ();
246
  foreach my $cat ( @categories) {
247
    # TODO das koma macht Probleme z.B kategorie "Feldsalat, Rapunzel"
248
    my @temp = [split(/,/,$cat)];
249
    push( @cat, @temp );
250
  }
251
  $main::lxdebug->dump(0, 'WH: KAT2:',\@cat);
267

  
268
    # The ShopwareConnector works with the CategoryID @categories[x][0] in others/new Connectors it must be tested
269
    # Each assigned categorie is saved with id,categorie_name an multidimensional array and could be expanded with categoriepath or what is needed
270
    my @cat = ();
271
    foreach my $cat ( @categories) {
272
      my @cattmp;
273
      push( @cattmp,$cat );
274
      push( @cattmp,$::form->{"cat_id_${cat}"} );
275
      push( @cat,\@cattmp );
276
    }
252 277

  
253 278
  my $categories->{shop_category} = \@cat;
254 279

  
......
268 293

  
269 294
sub action_reorder {
270 295
  my ($self) = @_;
271
$main::lxdebug->message(0, "WH:REORDER ");
296

  
272 297
  require SL::DB::File;
273 298
  SL::DB::File->reorder_list(@{ $::form->{image_id} || [] });
274
  $main::lxdebug->message(0, "WH:REORDER II ");
275 299

  
276 300
  $self->render(\'', { type => 'json' });
277 301
}
278 302

  
303
sub action_list_articles {
304
  my ($self) = @_;
305

  
306
  my %filter = ($::form->{filter} ? parse_filter($::form->{filter}) : query => [ transferred => 0 ]);
307
  my $transferred = $::form->{filter}->{transferred_eq_ignore_empty} ne '' ? $::form->{filter}->{transferred_eq_ignore_empty} : '';
308
  my $sort_by = $::form->{sort_by} ? $::form->{sort_by} : 'part.partnumber';
309
  $sort_by .=$::form->{sort_dir} ? ' DESC' : ' ASC';
310
$main::lxdebug->message(0, "WH:LA ");
311

  
312
  my $articles = SL::DB::Manager::ShopPart->get_all(where => [ 'shop.obsolete' => 0 ],with_objects => [ 'part','shop' ], sort_by => $sort_by );
313

  
314
  foreach my $article (@{ $articles}) {
315
    my $images = SL::DB::Manager::File->get_all_count( where => [ trans_id => $article->part->id, modul => 'shop_part', file_content_type => { like => 'image/%' } ], sort_by => 'position' );
316
    $article->{images} = $images;
317
  }
318
  $main::lxdebug->dump(0, 'WH:ARTIKEL ',\$articles);
319

  
320
  $self->render('shop_part/_list_articles', title => t8('Webshops articles'), SHOP_PARTS => $articles);
321
}
322

  
323
sub action_upload_status {
324
  my ($self) = @_;
325
  my $job     = SL::DB::BackgroundJob->new(id => $::form->{job_id})->load;
326
  my $html    = $self->render('shop_part/_upload_status', { output => 0 }, job => $job);
327

  
328
  $self->js->html('#status_mass_upload', $html);
329
  $self->js->run('kivi.shop_part.massUploadFinished') if $job->data_as_hash->{status} == SL::BackgroundJob::ShopPartMassUpload->DONE();
330
  $self->js->render;
331
}
332

  
333
sub action_mass_upload {
334
  my ($self) = @_;
335
$main::lxdebug->message(0, "WH:MA ");
336

  
337
  my @shop_parts =  @{ $::form->{shop_parts_ids} || [] };
338

  
339
  my $job                   = SL::DB::BackgroundJob->new(
340
    type                    => 'once',
341
    active                  => 1,
342
    package_name            => 'ShopPartMassUpload',
343
  )->set_data(
344
     shop_part_record_ids         => [ @shop_parts ],
345
     todo                         => $::form->{upload_todo},
346
     status                       => SL::BackgroundJob::ShopPartMassUpload->WAITING_FOR_EXECUTION(),
347
     conversation_errors          => [ ],
348
   )->update_next_run_at;
349
$main::lxdebug->dump(0, 'WH:MA JOB ',\$job);
350

  
351
   SL::System::TaskServer->new->wake_up;
352
$main::lxdebug->dump(0, 'WH:MA JOB 2',\$job);
353

  
354
   my $html = $self->render('shop_part/_transfer_status', { output => 0 }, job => $job);
355

  
356
   $self->js
357
      ->html('#status_mass_upload', $html)
358
      ->run('kivi.shop_part.massUploadStarted')
359
      ->render;
360
}
361

  
279 362
#
280 363
# internal stuff
281 364
#
......
338 421
  };
339 422
}
340 423

  
424
sub init_file {
425
  $main::lxdebug->message(0, "WH:INIT_FILES ");
426
  my $file = $::form->{id} ? SL::DB::File->new(id => $::form->{id})->load : SL::DB::File->new;
427
  $main::lxdebug->dump(0, 'WH: INITFILE: ',\file);
428

  
429
  return $file;
430
}
431

  
432
sub init_shops {
433
  # data for drop down filter options
434
  $main::lxdebug->message(0, "WH:INIT_SHOPS ");
435

  
436
  require SL::DB::Shop;
437
  my @shops_dd = [ { title => t8("all") ,   value =>'' } ];
438
  my $shops = SL::DB::Mangager::Shop->get_all( where => [ obsolete => 0 ] );
439
   my @tmp = map { { title => $_->{description}, value => $_->{id} } } @{ $shops } ;
440
 $main::lxdebug->dump(0, 'WH:SHOPS ',\@tmp);
441
 return @shops_dd;
442

  
443
}
444

  
445
sub init_producers {
446
  # data for drop down filter options
447
  $main::lxdebug->message(0, "WH:INIT_PRODUCERS ");
448

  
449
  my @producers_dd = [ { title => t8("all") ,   value =>'' } ];
450
 return @producers_dd;
451

  
452
}
453

  
341 454
1;
342 455

  
343 456
__END__
......
361 474

  
362 475
=item C<action_update_shop>
363 476

  
364
  To be called from the "Update" button, for manually syncing a part with its shop. Generates a  Calls some ClientJS functions to modifiy original page.
477
  To be called from the "Update" button of the shoppart, for manually syncing/upload one part with its shop. Generates a  Calls some ClientJS functions to modifiy original page.
478

  
479
=item C<action_get_n_write_categories>
365 480

  
481
  Can be used to sync the categories of a shoppart with the categories from online.
366 482

  
367 483
=head1 AUTHORS
368 484

  
......
370 486
  W. Hahn E<lt>wh@futureworldsearch.netE<gt>
371 487

  
372 488
=cut
373

  
374
=cut
375
1;
SL/DB/ShopPart.pm
2 2
# Feel free to modify it at will; it will not be overwritten automatically.
3 3

  
4 4
package SL::DB::ShopPart;
5
#package SL::DB::ShopPart;
6 5

  
7 6
use strict;
8 7

  
SL/ShopConnector/Shopware.pm
12 12
use LWP::Authen::Digest;
13 13
use SL::DB::ShopOrder;
14 14
use SL::DB::ShopOrderItem;
15
use SL::DB::History;
16
use SL::DB::File;
15 17
use Data::Dumper;
16 18
use Sort::Naturally ();
17 19
use SL::Helper::Flash;
......
126 128
        $pos_insert->save;
127 129
        $position++;
128 130
      }
129
      $shop_order->{positions} = $position;
131
      $shop_order->{positions} = $position-1;
130 132

  
131 133
      # Only Customers which are not found will be applied
132 134
      my $proposals = SL::DB::Manager::Customer->get_all_count(
......
158 160
                        'fax'                   => $shop_order->billing_fax,
159 161
                        'phone'                 => $shop_order->billing_phone,
160 162
                        'ustid'                 => $shop_order->billing_vat,
161
                        'taxincluded_checked'   => 1,   # TODO hardcoded
162
                        'taxincluded'           => 1,   # TODO hardcoded
163
                        'klass'                 => 908, # TODO hardcoded
164
                        'taxzone_id'            => 4,   # TODO hardcoded, use default taxzone instead
163
                        'taxincluded_checked'   => $self->config->pricetype eq "brutto" ? 1 : 0,
164
                        'taxincluded'           => $self->config->pricetype eq "brutto" ? 1 : 0,
165
                        'klass'                 => (split '\/',$self->config->price_source)[1],
166
                        'taxzone_id'            => $self->config->taxzone_id,
165 167
                        'currency'              => 1,   # TODO hardcoded
166 168
                        'payment_id'            => 7345,# TODO hardcoded
167 169
                      );
......
203 205
        $shipping_pos_insert->save;
204 206

  
205 207
      }
206
        my $attributes->{last_order_number} = $ordnumber;
207
        $self->config->assign_attributes( %{ $attributes } );
208
        $self->config->save;
209
        $ordnumber++;
210 208
      # EOT Versandkosten DF
209
      my $attributes->{last_order_number} = $ordnumber;
210
      $self->config->assign_attributes( %{ $attributes } );
211
      $self->config->save;
212
      $ordnumber++;
211 213
    }
212 214
  }
213 215
    my $shop = $self->config->description;
......
238 240
}
239 241

  
240 242
sub update_part {
241
  my ($self, $shop_part, $json) = @_;
243
  my ($self, $shop_part, $json, $todo) = @_;
242 244

  
243 245
  #shop_part is passed as a param
244 246
  die unless ref($shop_part) eq 'SL::DB::ShopPart';
......
303 305
  $taxrate = @$rate[0]->{taxrate}*100;
304 306

  
305 307
  # mapping to shopware still missing attributes,metatags
306
  my %shop_data =  (  name              => $part->{description},
307
                      tax               => $taxrate,
308
                      mainDetail        => { number   => $part->{partnumber},
309
                                         inStock  => $part->{onhand},
310
                                         prices   =>  [ {          from   => 1,
311
                                                                   price  => $price,
312
                                                        customerGroupKey  => 'EK',
313
                                                      },
314
                                                    ],
315
                                       },
316
                      supplier          => $cvars->{freifeld_7}->{value},
317
                      descriptionLong   => $shop_part->{shop_description},
318
                      active            => $shop_part->active,
319
                      images            => [ @upload_img ],
320
                      __options_images  => { replace => 1, },
321
                      categories        => [ @cat ],
322
                      description       => $shop_part->{shop_description},
323
                      active            => $shop_part->active,
324
                      images            => [ @upload_img ],
325
                      __options_images  => { replace => 1, },
326
                      categories        => [ @cat ], #{ path => 'Deutsch|test2' }, ], #[ $categories ],
327

  
328
                    )
329
                  ;
308
  my %shop_data;
309
  $main::lxdebug->dump(0, 'WH:TODO ',\$todo);
310

  
311
  if($todo eq "price"){
312
    %shop_data = ( mainDetail => { number   => $part->{partnumber},
313
                                   prices   =>  [ { from             => 1,
314
                                                    price            => $price,
315
                                                    customerGroupKey => 'EK',
316
                                                  },
317
                                                ],
318
                                  },
319
                 );
320
  }elsif($todo eq "stock"){
321
    %shop_data = ( mainDetail => { number   => $part->{partnumber},
322
                                   inStock  => $part->{onhand},
323
                                 },
324
                 );
325
  }elsif($todo eq "price_stock"){
326
    %shop_data =  ( mainDetail => { number   => $part->{partnumber},
327
                                    inStock  => $part->{onhand},
328
                                    prices   =>  [ { from             => 1,
329
                                                     price            => $price,
330
                                                     customerGroupKey => 'EK',
331
                                                   },
332
                                                 ],
333
                                   },
334
                   );
335
  }elsif($todo eq "active"){
336
    %shop_data =  ( mainDetail => { number   => $part->{partnumber},
337
                                   },
338
                    active => ($part->{partnumber} == 1 ? 0 : 1),
339
                   );
340
  }elsif($todo eq "all"){
341
  # mapping to shopware still missing attributes,metatags
342
    %shop_data =  (  name              => $part->{description},
343
                     tax               => $taxrate,
344
                     mainDetail        => { number   => $part->{partnumber},
345
                                            inStock  => $part->{onhand},
346
                                            active   => $shop_part->active,
347
                                            prices   =>  [ { from              => 1,
348
                                                             price             => $price,
349
                                                             customerGroupKey  => 'EK',
350
                                                           },
351
                                                         ],
352
                                          },
353
                     supplier          => $cvars->{freifeld_7}->{value},
354
                     descriptionLong   => $shop_part->{shop_description},
355
                     active            => $shop_part->active,
356
                     images            => [ @upload_img ],
357
                     __options_images  => { replace => 1, },
358
                     categories        => [ @cat ],
359
                     description       => $shop_part->{shop_description},
360
                     active            => $shop_part->active,
361
                     images            => [ @upload_img ],
362
                     __options_images  => { replace => 1, },
363
                     categories        => [ @cat ],
364
                   );
365
  }else{
366
    my %shop_data =  ( mainDetail => { number   => $part->{partnumber}, });
367
  }
368
  $main::lxdebug->dump(0, 'WH:SHOPDATA ',\%shop_data);
369

  
330 370
  my $dataString = SL::JSON::to_json(\%shop_data);
331 371
  $dataString = encode_utf8($dataString);
332 372

  
......
338 378
    #update
339 379
    my $partnumber = $::form->escape($part->{partnumber});#shopware dosn't accept / in articlenumber
340 380
    my $upload = $self->connector->put("http://$url/api/articles/$partnumber?useNumberAsId=true",Content => $dataString);
381
    $main::lxdebug->dump(0, 'WH:iUPLOAD ',\$upload);
382

  
341 383
    my $data_json = $upload->content;
342 384
    $upload_content = SL::JSON::decode_json($data_json);
343 385
  }else{
......
346 388
    my $data_json = $upload->content;
347 389
    $upload_content = SL::JSON::decode_json($data_json);
348 390
  }
391
  # Don't know if this is needed
349 392
  if(@upload_img) {
350 393
    my $partnumber = $::form->escape($part->{partnumber});#shopware don't accept / in articlenumber
351 394
    $self->connector->put("http://$url/api/generateArticleImages/$partnumber?useNumberAsId=true");
menus/user/10-shopimport.yaml
9 9
    action: ShopOrder/list
10 10
    db: shop_orders
11 11
    sort_by: shop_ordernumber
12
- parent: webshop
13
  id: webshop_articles
14
  name: Webshop articles
15
  params:
16
    action: ShopPart/list_articles
17
    db: shop_parts
18
    sort_by: part.onhand
19
#ShopPart
templates/webpages/ic/tabs/_shop.html
18 18
   <th>[% LxERP.t8("Action") %]</th>
19 19
  </tr>
20 20
  </thead>
21

  
21 22
  [%- FOREACH shop_part = SHOP_PARTS %]
22 23
  <tr class="listrow">
23 24
   <td>[% HTML.escape( shop_part.shop.description ) %]</td>
......
44 45
   <td></td>
45 46
   <td></td>
46 47
   <td></td>
48
   <td></td>
49
   <td></td>
50
   <td></td>
47 51
   <td>[% L.button_tag("kivi.shop_part.create_shop_part(" _ id _ ", " _ shop.id _ ")", LxERP.t8("Add"))  %]</td>
48 52
   <td></td>
49 53
  </tr>
......
73 77
   </p>
74 78
  </div>
75 79
  [%- END %]
76
  <script type="text/javascript">
77
    $(function() {
78
      kivi.shop_part.show_images([% shop_part.part_id %]);
79
    });
80
  </script>
81
  <div id="shop_images" border=1 >
82
  </div>
83

  
84
<div id="shop_variables">
85
[% LxERP.t8("Active shops:") %]
86
 <table>
87
  <thead>
88
  <tr>
89
   <th>[% LxERP.t8("Shop") %]</th>
90
   <th>[% LxERP.t8("Active") %]</th>
91
   <th>[% LxERP.t8("Shop part") %]</th>
92
   <th>[% LxERP.t8("Last update") %]</th>
93
   <th>[% LxERP.t8("Action") %]</th>
94
   <th>[% LxERP.t8("Action") %]</th>
95
  </tr>
96
  </thead>
97
  [%- FOREACH shop_part = SHOP_PARTS %]
98
  <tr>
99
   <td>[% HTML.escape( shop_part.shop.description ) %]</td>
100
   <td>[% L.html_tag('span', shop_part.active, id => 'shop_part_active_' _ shop_part.id ) %]</td>
101
   <td>[% L.html_tag('span', shop_part.shop_description, id => 'shop_part_description_' _ shop_part.id ) %]</td>
102
   <td>[% L.html_tag('span', shop_part.last_update.to_kivitendo('precision' => 'minute'), id => 'shop_part_last_update_' _ shop_part.id ) %]</td>
103
   <td>[% L.button_tag("kivi.shop_part.edit_shop_part(" _ shop_part.id _ ")", LxERP.t8("Edit"))  %]</td>
104
   <td>[% L.button_tag("kivi.shop_part.update_shop_part(" _ shop_part.id _ ")", LxERP.t8("Update"))  %]</td>
105
   <td>[% L.button_tag("kivi.shop_part.get_all_categories(" _ shop_part.id _ ")", LxERP.t8("Shopcategories"))  %]</td>
106
  </tr>
107
  [%- END %]
108
  [%- FOREACH shop = SHOPS_NOT_ASSIGNED %]
109
  <tr>
110
   <td>[% HTML.escape( shop.description ) %]</td>
111
   <td></td>
112
   <td></td>
113
   <td></td>
114
   <td>[% L.button_tag("kivi.shop_part.create_shop_part(" _ id _ ", " _ shop.id _ ")", LxERP.t8("Add"))  %]</td>
115
   <td></td>
116
  </tr>
117
  [%- END %]
118
</table>
119

  
120

  
121
[% # L.dump(shop_part) %]
122
<hr>
123
  [%- IF CUSTOM_VARIABLES.size %]
124
  <div id="shop_custom_variables">
125
   <p>
126
    <table>
127
     [%- FOREACH var = CUSTOM_VARIABLES %]
128
      [%- IF var.name.match('^shop_') %]
129
       <tr>
130
        [%- IF !var.partsgroup_filtered %]
131
          <td align="right" valign="top">[% HTML.escape(var.description) %]</td>
132
        [%- END %]
133
        <td valign="top">[% var.HTML_CODE %]</td>
134
       </tr>
135
      [%- END %]
136
     [%- END %]
137
    </table>
138
   </p>
139
  </div>
80
  [%- IF shop_part.part_id %]
81
    <script type="text/javascript">
82
      $(function() {
83
        kivi.shop_part.show_images([% shop_part.part_id %]);
84
      });
85
    </script>
86
    <div id="shop_images" border=1 ></div>
87
  [%- ELSE %]
88
    <div id="shop_images" border=1 >[% LxERP.t8('To upload images: Please create shoppart first') %]</div>
140 89
  [%- END %]
141
  <script type="text/javascript">
142
    function show_images() {
143
      var url = 'controller.pl?action=ShopPart/show_files&modul=shop_part&id=[% shop_part.part_id %]';
144
      $('#shop_images').load(url);
145
    }
146

  
147
$(window).load(function() {
148
        show_images();
149
});
150
  </script>
151
  <div id="shop_images" border=1 >
152
  </div>
153 90
</div>
154 91

  
templates/webpages/shop_part/_filter.html
1
[%- USE T8 %]
2
[%- USE L %]
3
[%- USE LxERP %]
4
[%- USE HTML %]
5
<!-- ShopOrder -->
6
<form action='controller.pl' method='post' id="shop_part_filter">
7
 <table id='filter_table'>
8

  
9
    <tr>
10
     <th align="right">[% 'Shop' | $T8 %]</th>
11
     <td>[% L.select_tag('filter.transferred:eq_ignore_empty', SELF.shop, value_key = 'value', title_key = 'title', default=SHOPS) %]</td>
12
    </tr>
13

  
14
    <tr>
15
     <th align="right">[% 'Producer' | $T8 %]</th>
16
     <td>[% L.select_tag('filter.transferred:eq_ignore_empty', SELF.producer, value_key = 'value', title_key = 'title', default=PRODUCERS) %]</td>
17
    </tr>
18

  
19
   <!--  <tr>
20
     <th align="right">[% 'from' | $T8 %]</th>
21
     <td>[% # L.date_tag('filter.order_date:date::ge', filter.order_date_date__ge) %]</td>
22
    </tr>
23

  
24
    <tr>
25
     <th align="right">[% 'to' | $T8 %]</th>
26
     <td>[% # L.date_tag('filter.order_date:date::le', filter.order_date_date__le) %]</td>
27
    </tr> -->
28

  
29
 </table>
30

  
31

  
32
<a href='#' onClick='javascript:$("#filter_table input").val("");$("#filter_table input[type=checkbox]").prop("checked", 0);'>[% 'Reset' | $T8 %]</a>
33
<br>
34

  
35
 [% L.hidden_tag('action', 'ShopPart/dispatch') %]
36
 [% L.submit_tag('action_list_articles',LxERP.t8('renew')) %]
37

  
38
</form>
templates/webpages/shop_part/_list_articles.html
1
[%- USE HTML -%][%- USE LxERP -%][%- USE L -%][%- USE T8 -%]
2
[% USE Dumper %]
3
<!-- ShopPart -->
4
<!-- ShopPart -->
5
<!-- ShopPart -->
6
<h1>[% title %]</h1>
7
[%- PROCESS 'shop_part/_filter.html' filter=SELF.models.filtered.laundered %]
8
<hr>
9
<form method="post" action="controller.pl" name="shop_parts" id="shopparts">
10
  <div class="data_count">[% 'Number of Data: ' | $T8 %][% SHOP_PARTS.size %]</div>
11
  <table id="shoplist" width="100%" >
12
    <thead>
13
      <tr class="listheading">
14
      <th>[% L.checkbox_tag('check_all') %]</th>
15
    <th>[% IF FORM.sort_by == 'shop.description' %]
16
      <a href ="controller.pl?action=ShopPart/list_articles&sort_by=shop.description&sort_dir=[% 1 - FORM.sort_dir %]" class="sort_link">
17
        [% 'Shop Host/Connector' | $T8 %][% IF FORM.sort_dir == 0 %]<img border="0" src="image/down.png">[% ELSE %]<img border="0" src="image/up.png">[% END %]</a>
18
    [% ELSE %]
19
      <a href ="controller.pl?action=ShopPart/list_articles&sort_by=shop.description&sort_dir=0" class="sort_link">
20
        [% 'Shop Host/Connector' | $T8 %]</a>
21
    [% END %]
22
    </th>
23
    <th>[% IF FORM.sort_by == 'part.partnumber' %]
24
      <a href ="controller.pl?action=ShopPart/list_articles&sort_by=part.partnumber&sort_dir=[% 1 - FORM.sort_dir %]" class="sort_link">
25
        [% 'Partnumber' | $T8 %][% IF FORM.sort_dir == 0 %]<img border="0" src="image/down.png">[% ELSE %]<img border="0" src="image/up.png">[% END %]</a>
26
    [% ELSE %]
27
      <a href ="controller.pl?action=ShopPart/list_articles&sort_by=part.partnumber&sort_dir=0" class="sort_link">
28
        [% 'Partnumber' | $T8 %]</a>
29
    [% END %]
30
    </th>
31
    <th>[% IF FORM.sort_by == 'part.description' %]
32
      <a href ="controller.pl?action=ShopPart/list_articles&sort_by=part.description&sort_dir=[% 1 - FORM.sort_dir %]" class="sort_link">
33
        [% 'Description' | $T8 %][% IF FORM.sort_dir == 0 %]<img border="0" src="image/down.png">[% ELSE %]<img border="0" src="image/up.png">[% END %]</a>
34
    [% ELSE %]
35
      <a href ="controller.pl?action=ShopPart/list_articles&sort_by=part.description&sort_dir=0" class="sort_link">
36
        [% 'Description' | $T8 %]</a>
37
    [% END %]
38
    </th>
39
      <th>[% 'Info' | $T8 %]</th>
40
      <th>[% 'Active' | $T8 %]</th>
41
      <th>[% 'Price source' | $T8 %]</th>
42
      <th>[% 'Price' | $T8 %]</th>
43
    <th>[% IF FORM.sort_by == 'part.onhand' %]
44
      <a href ="controller.pl?action=ShopPart/list_articles&sort_by=part.onhand&sort_dir=[% 1 - FORM.sort_dir %]" class="sort_link">
45
        [% 'Stock Local/Shop' | $T8 %][% IF FORM.sort_dir == 0 %]<img border="0" src="image/down.png">[% ELSE %]<img border="0" src="image/up.png">[% END %]</a>
46
    [% ELSE %]
47
      <a href ="controller.pl?action=ShopPart/list_articles&sort_by=part.onhand&sort_dir=0" class="sort_link">
48
        [% 'Stock Local/Shop' | $T8 %]</a>
49
    [% END %]
50
    </th>
51
      <th>[% 'Last update' | $T8 %]</th>
52
      <th>[% 'Images' | $T8 %]</th>
53
    <th>[% IF FORM.sort_by == 'part.partsgroup_id' %]
54
      <a href ="controller.pl?action=ShopPart/list_articles&sort_by=part.partsgroup_id&sort_dir=[% 1 - FORM.sort_dir %]" class="sort_link">
55
        [% 'Category' %][% IF FORM.sort_dir == 0 %]<img border="0" src="image/down.png">[% ELSE %]<img border="0" src="image/up.png">[% END %]</a>
56
    [% ELSE %]
57
      <a href ="controller.pl?action=ShopPart/list_articles&sort_by=part.partsgroup_id&sort_dir=0" class="sort_link">
58
        [% 'Category' | $T8 %]</a>
59
    [% END %]
60
    </th>
61
    <th>[% IF FORM.sort_by == 'part.microfiche' %]
62
      <a href ="controller.pl?action=ShopPart/list_articles&sort_by=part.microfiche&sort_dir=[% 1 - FORM.sort_dir %]" class="sort_link">
63
        [% 'Producer' | $T8 %][% IF FORM.sort_dir == 0 %]<img border="0" src="image/down.png">[% ELSE %]<img border="0" src="image/up.png">[% END %]</a>
64
    [% ELSE %]
65
      <a href ="controller.pl?action=ShopPart/list_articles&sort_by=part.microfiche&sort_dir=0" class="sort_link">
66
        [% 'Producer' | $T8 %]</a>
67
    [% END %]
68
    </th>
69
      <th>[% 'Action' | $T8 %]</th>
70
    </tr>
71
  </thead>
72
  [%- FOREACH shop_part = SHOP_PARTS %]
73
  [%- # IF shop_part.shop.obsolete %]
74
    <tr class="listrow">
75
      <td>[% L.checkbox_tag('shop_parts_ids[]', checked=0, value=shop_part.id) %]</td>
76
      <td>[% HTML.escape( shop_part.shop.description ) %]/[% HTML.escape( shop_part.shop.connector ) %]</td>
77
      <td>[% HTML.escape( shop_part.part.partnumber ) %]</td>
78
      <td><a href="ic.pl?id=[% shop_part.part.id %]&action=edit&callback=[% HTML.url('controller.pl?action=ShopPart/list_articles') %]#shop_variables">[% HTML.escape( shop_part.part.description ) %]</a></td>
79
      <td>
80
        [% IF shop_part.shop_description %]
81
          [% 'Info' | $T8 %]
82
        [% ELSE %]
83
          [% 'No Shopdescription' | $T8 %]
84
        [% END %]
85
      </td>
86
      <td style="vertical-align:middle;text-align:center;">
87
        [% IF shop_part.active %]
88
        <div id="toogle_[% shop_part.id %]" style="background-image:url(image/gruener_punkt.gif);background-repeat:no-repeat;witdh:15px;height:15px;" onclick="kivi.shop_part.part_toggle_active([% shop_part.id %] ,[% shop_part.active %]);" onMouseOver="this.style.cursor='pointer'">&nbsp; </div>
89
        [% ELSE %]
90
        <div id="toogle_[% shop_part.id %]" style="background-image:url(image/roter_punkt.gif);background-repeat:no-repeat;witdh:15px;height:15px;" onclick="kivi.shop_part.part_toggle_active([% shop_part.id %] ,[% shop_part.active %]);" onMouseOver="this.style.cursor='pointer'">&nbsp; </div>
91
        [% END %]
92
      </td>
93
      <td>[% L.html_tag('span',LxERP.t8(), id => 'active_price_source_' _ shop_part.id) %] </td>
94
      <td>[% L.html_tag('span','Price', id => 'price_' _ shop_part.id) %]</td>
95
      <td>[% L.html_tag('span','Stock', id => 'stock_' _ shop_part.id) %]</td>
96
      <td>[% L.html_tag('span', shop_part.last_update.to_kivitendo('precision' => 'minute'), id => 'shop_part_last_update_' _ shop_part.id ) %]</td>
97
      <td>
98
        [% IF shop_part.images %]
99
          [% shop_part.images %]
100
        [% ELSE %]
101
          [% 'No Shopimages' | $T8 %]
102
        [% END %]
103
      </td>
104
      <td>
105
        [% IF shop_part.shop_category %]
106
          [% IF shop_part.shop_category.1.size > 1%]
107
            [% FOREACH cat = shop_part.shop_category %]
108
              [% HTML.escape(cat.1) %]<br>
109
            [% END %]
110
          [% ELSE %]
111
            [% HTML.escape(shop_part.shop_category.1) %]<br>
112
          [% END %]
113
        [% END %]
114
      </td>
115
      <td>[% HTML.escape( shop_part.part.microfiche ) %]</td>
116
      <td></td>
117
    <script type="text/javascript">
118
      $(function() {
119
         kivi.shop_part.update_price_n_price_source([% shop_part.id %],'[% shop_part.active_price_source %]');
120
         kivi.shop_part.update_stock([% shop_part.id %]);
121
      });
122
    </script>
123
    </tr>
124
    [%- # END %]
125
  [%- END %]
126
</table>
127

  
128
  <hr>
129
  <div>
130
    [% L.radio_button_tag('upload_todo', value='all', label= LxERP.t8('All Data')) %]
131
    [% L.radio_button_tag('upload_todo', value='price', label= LxERP.t8('Only Price')) %]
132
    [% L.radio_button_tag('upload_todo', value='stock', label= LxERP.t8('Only Stock')) %]
133
    [% L.radio_button_tag('upload_todo', value='price_stock', checked=1, label= LxERP.t8('Price and Stock')) %]
134
    [% L.button_tag("kivi.shop_part.setup();", LxERP.t8("Upload all marked"), id="mass_transfer") %]
135
  </div>
136
  <div id="status_mass_upload" style="display: none;">
137
    [%- INCLUDE 'shop_part/_upload_status.html' %]
138
  </div>
139
</form>
140
<hr>
141
<script type="text/javascript">
142
<!--
143

  
144
$(function() {
145
  $('#check_all').checkall('INPUT[name^="shop_parts_ids"]');
146
});
147
-->
148
</script>
templates/webpages/shop_part/_transfer_status.html
1
[%- USE LxERP -%][%- USE L -%][%- USE HTML -%]
2
[%- USE Dumper -%]
3
[% SET data = job.data_as_hash %]
4

  
5
<!-- ShopOrder BGJ -->
6
<h2>[% LxERP.t8("Watch status") %]</h2>
7

  
8
[% L.hidden_tag('', job.id, id="smu_job_id") %]
9

  
10
JOBID: [% job.id %] <p>
11
 [% LxERP.t8("This status output will be refreshed every five seconds.") %]
12
</p>
13
<p>
14
 <table>
15
  <tr>
16
   <th valign="top" align="left">[% LxERP.t8("Current status:") %]</th>
17
   <td valign="top">
18
    [% IF !data.status %]
19
     [% LxERP.t8("waiting for job to be started") %]
20
    [% ELSIF data.status == 1 %]
21
     [% LxERP.t8("Creating orders") %]
22
    [% ELSE %]
23
     [% LxERP.t8("Done.") %]
24
    [% END %]
25
   </td>
26
  </tr>
27
  <tr>
28
   <th valign="top" align="left">[% LxERP.t8("Number of orders created:") %]</th>
29
   <td valign="top">[% IF data.status > 0 %][% HTML.escape(data.num_created) %] / [% HTML.escape(data.record_ids.size) %][% ELSE %]–[% END %]</td>
30
  </tr>
31

  
32
  <tr>
33
   <th valign="top" align="left">[% LxERP.t8("Errors during conversion:") %]</th>
34
   <td valign="top">
35
[% IF !data.status %]
36
37
[% ELSIF !data.conversion_errors.size %]
38
 [% LxERP.t8("No errors have occurred.") %]
39
[% ELSE %]
40
    <table>
41
     <tr class="listheader">
42
      <th>[% LxERP.t8("Shop Order") %]</th>
43
      <th>[% LxERP.t8("Error") %]</th>
44
     </tr>
45

  
46
 [% FOREACH error = data.conversion_errors %]
47
     <tr>
48
      <td valign="top">[% IF error.id %][% L.link(SELF.url_for(controller='ShopOrder', action='show', id=error.id), HTML.escape(error.number), target="_blank") %][% ELSE %]–[% END %]</td>
49
      <td valign="top">[% HTML.escape(error.message) %]</td>
50
     </tr>
51
 [% END %]
52
    </table>
53
 [% END %]
54
 </table>
55
</p>
templates/webpages/shop_part/_upload_status.html
1
[%- USE LxERP -%][%- USE L -%][%- USE HTML -%]
2
[%- USE Dumper -%]
3
[% SET data = job.data_as_hash %]
4

  
5

  
6
<!-- ShopPart BGJ -->
7
<h2>[% LxERP.t8("Watch status") %]</h2>
8

  
9
[% L.hidden_tag('', job.id, id="smu_job_id") %]
10

  
11
JOBID: [% job.id %] <p>
12
 [% LxERP.t8("This status output will be refreshed every five seconds.") %]
13
</p>
14
<p>
15
 <table>
16
  <tr>
17
   <th valign="top" align="left">[% LxERP.t8("Current status:") %]</th>
18
   <td valign="top">
19
    [% IF !data.status %]
20
     [% LxERP.t8("waiting for job to be started") %]
21
    [% ELSIF data.status == 1 %]
22
     [% LxERP.t8("Creating orders") %]
23
    [% ELSE %]
24
     [% LxERP.t8("Done.") %]
25
    [% END %]
26
   </td>
27
  </tr>
28
  <tr>
29
   <th valign="top" align="left">[% LxERP.t8("Number of orders created:") %]</th>
30
   <td valign="top">[% IF data.status > 0 %][% HTML.escape(data.num_created) %] / [% HTML.escape(data.record_ids.size) %][% ELSE %]–[% END %]</td>
31
  </tr>
32

  
33
  <tr>
34
   <th valign="top" align="left">[% LxERP.t8("Errors during conversion:") %]</th>
35
   <td valign="top">
36
[% IF !data.status %]
37
38
[% ELSIF !data.conversion_errors.size %]
39
 [% LxERP.t8("No errors have occurred.") %]
40
[% ELSE %]
41
    <table>
42
     <tr class="listheader">
43
      <th>[% LxERP.t8("Shop Order") %]</th>
44
      <th>[% LxERP.t8("Error") %]</th>
45
     </tr>
46

  
47
 [% FOREACH error = data.conversion_errors %]
48
     <tr>
49
      <td valign="top">[% IF error.id %][% L.link(SELF.url_for(controller='ShopOrder', action='show', id=error.id), HTML.escape(error.number), target="_blank") %][% ELSE %]–[% END %]</td>
50
      <td valign="top">[% HTML.escape(error.message) %]</td>
51
     </tr>
52
 [% END %]
53
    </table>
54
 [% END %]
55
 </table>
56
</p>
templates/webpages/shop_part/categories.html
4 4
[%- USE P -%]
5 5
[%- USE LxERP -%]
6 6
[%- USE Dumper -%]
7

  
7
<!-- ShopPart -->
8 8
[%  LxERP.t8("Part") %]: [% HTML.escape(SELF.shop_part.part.displayable_name) %]<br>
9 9
[%  LxERP.t8("Shop") %]: [% HTML.escape(SELF.shop_part.shop.description) %]
10 10
<br>
templates/webpages/shop_part/edit.html
5 5
[%- USE LxERP -%]
6 6
[%- USE Dumper -%]
7 7

  
8
<!-- ShopPart -->
9
<!-- ShopPart -->
8 10
[% LxERP.t8("Part") %]: [% HTML.escape(SELF.shop_part.part.displayable_name) %]<br>
9 11
[% LxERP.t8("Shop") %]: [% HTML.escape(SELF.shop_part.shop.description) %]
10 12
[% Dumper.dump_html(SELF) %]

Auch abrufbar als: Unified diff