Revision 2b511d4d
Von Werner Hahn vor etwa 7 Jahren hinzugefügt
SL/Controller/Shop.pm | ||
---|---|---|
127 | 127 |
# whether the shop presents its prices as brutto or netto |
128 | 128 |
$self->price_types( [ { id => "brutto", name => t8('brutto')}, { id => "netto", name => t8('netto') } ] ); |
129 | 129 |
|
130 |
# the possible price sources to use for the shops: sellprice, lastcost, |
|
130 |
# the possible default price sources to use for the shops: sellprice, lastcost,
|
|
131 | 131 |
# listprice, or one of the pricegroups |
132 | 132 |
my $pricesources; |
133 |
push( @{ $pricesources } , { id => "sellprice", name => t8("Sellprice") },
|
|
134 |
{ id => "listprice", name => t8("Listprice") },
|
|
135 |
{ id => "lastcost", name => t8("Lastcost") }
|
|
133 |
push( @{ $pricesources } , { id => "master_data/sellprice", name => t8("Master Data")." - ".t8("Sellprice") },
|
|
134 |
{ id => "master_data/listprice", name => t8("Master Data")." - ".t8("Listprice") },
|
|
135 |
{ id => "master_data/lastcost", name => t8("Master Data")." - ".t8("Lastcost") }
|
|
136 | 136 |
); |
137 | 137 |
my $pricegroups = SL::DB::Manager::Pricegroup->get_all; |
138 | 138 |
foreach my $pg ( @$pricegroups ) { |
139 |
push( @{ $pricesources } , { id => $pg->id, name => $pg->pricegroup} );
|
|
139 |
push( @{ $pricesources } , { id => "pricegroup/".$pg->id, name => t8("Pricegroup") . " - " . $pg->pricegroup} );
|
|
140 | 140 |
}; |
141 | 141 |
|
142 | 142 |
$self->price_sources( $pricesources ); |
SL/Controller/ShopPart.pm | ||
---|---|---|
8 | 8 |
use Data::Dumper; |
9 | 9 |
use SL::Locale::String qw(t8); |
10 | 10 |
use SL::DB::ShopPart; |
11 |
use SL::DB::File; |
|
12 |
use SL::Controller::FileUploader; |
|
11 | 13 |
use SL::DB::Default; |
12 | 14 |
use SL::Helper::Flash; |
13 | 15 |
|
14 | 16 |
use Rose::Object::MakeMethods::Generic |
15 | 17 |
( |
16 |
'scalar --get_set_init' => [ qw(shop_part js) ], |
|
18 |
scalar => [ qw(price_sources) ], |
|
19 |
'scalar --get_set_init' => [ qw(shop_part file) ], |
|
17 | 20 |
); |
18 | 21 |
|
19 | 22 |
__PACKAGE__->run_before('check_auth'); |
20 | 23 |
__PACKAGE__->run_before('add_javascripts', only => [ qw(edit_popup) ]); |
24 |
__PACKAGE__->run_before('load_pricesources', only => [ qw(create_or_edit_popup) ]); |
|
25 |
|
|
21 | 26 |
# |
22 | 27 |
# actions |
23 | 28 |
# |
... | ... | |
36 | 41 |
require SL::Shop; |
37 | 42 |
my $shop = SL::Shop->new( config => $shop_part->shop ); |
38 | 43 |
|
39 |
# TODO: generate data to upload to shop
|
|
44 |
# data to upload to shop. Goes to SL::Connector::XXXConnector.
|
|
40 | 45 |
my $part_hash = $shop_part->part->as_tree; |
41 | 46 |
my $json = SL::JSON::to_json($part_hash); |
42 | 47 |
my $return = $shop->connector->update_part($self->shop_part, $json); |
43 | 48 |
|
44 | 49 |
# the connector deals with parsing/result verification, just needs to return success or failure |
45 | 50 |
if ( $return == 1 ) { |
46 |
# TODO: write update time to DB |
|
47 | 51 |
my $now = DateTime->now; |
52 |
my $attributes->{last_update} = $now; |
|
53 |
$self->shop_part->assign_attributes(%{ $attributes }); |
|
54 |
$self->shop_part->save; |
|
48 | 55 |
$self->js->html('#shop_part_last_update_' . $shop_part->id, $now->to_kivitendo('precision' => 'minute')) |
49 | 56 |
->flash('info', t8("Updated part [#1] in shop [#2] at #3", $shop_part->part->displayable_name, $shop_part->shop->description, $now->to_kivitendo('precision' => 'minute') ) ) |
50 | 57 |
->render; |
... | ... | |
61 | 68 |
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' ); |
62 | 69 |
|
63 | 70 |
$self->render('shop_part/_list_images', { header => 0 }, IMAGES => $images); |
71 |
} |
|
72 |
|
|
73 |
sub action_ajax_upload_file{ |
|
74 |
my ($self, %params) = @_; |
|
75 |
|
|
76 |
my $attributes = $::form->{ $::form->{form_prefix} } || die "Missing attributes"; |
|
77 |
|
|
78 |
$attributes->{filename} = ((($::form->{ATTACHMENTS} || {})->{ $::form->{form_prefix} } || {})->{file_content} || {})->{filename}; |
|
79 |
|
|
80 |
my @errors; |
|
81 |
my @file_errors = SL::DB::File->new(%{ $attributes })->validate; |
|
82 |
push @errors,@file_errors if @file_errors; |
|
83 |
|
|
84 |
my @type_error = SL::Controller::FileUploader->validate_filetype($attributes->{filename},$::form->{aft}); |
|
85 |
push @errors,@type_error if @type_error; |
|
86 |
|
|
87 |
return $self->js->error(@errors)->render($self) if @errors; |
|
88 |
|
|
89 |
$self->file->assign_attributes(%{ $attributes }); |
|
90 |
$self->file->file_update_type_and_dimensions; |
|
91 |
$self->file->save; |
|
92 |
|
|
93 |
$self->js |
|
94 |
->dialog->close('#jqueryui_popup_dialog') |
|
95 |
->run('kivi.shop_part.show_images',$self->file->trans_id) |
|
96 |
->render(); |
|
97 |
} |
|
98 |
|
|
99 |
sub action_ajax_update_file{ |
|
100 |
my ($self, %params) = @_; |
|
101 |
|
|
102 |
my $attributes = $::form->{ $::form->{form_prefix} } || die "Missing attributes"; |
|
103 |
|
|
104 |
if (!$attributes->{file_content}) { |
|
105 |
delete $attributes->{file_content}; |
|
106 |
} else { |
|
107 |
$attributes->{filename} = ((($::form->{ATTACHMENTS} || {})->{ $::form->{form_prefix} } || {})->{file_content} || {})->{filename}; |
|
108 |
} |
|
109 |
|
|
110 |
my @errors; |
|
111 |
my @type_error = SL::Controller::FileUploader->validate_filetype($attributes->{filename},$::form->{aft}); |
|
112 |
push @errors,@type_error if @type_error; |
|
113 |
$self->file->assign_attributes(%{ $attributes }); |
|
114 |
my @file_errors = $self->file->validate if $attributes->{file_content};; |
|
115 |
push @errors,@file_errors if @file_errors; |
|
116 |
|
|
117 |
|
|
118 |
return $self->js->error(@errors)->render($self) if @errors; |
|
119 |
|
|
120 |
$self->file->file_update_type_and_dimensions if $attributes->{file_content}; |
|
121 |
$self->file->save; |
|
122 |
|
|
123 |
$self->js |
|
124 |
->dialog->close('#jqueryui_popup_dialog') |
|
125 |
->run('kivi.shop_part.show_images',$self->file->trans_id) |
|
126 |
->render(); |
|
127 |
} |
|
128 |
|
|
129 |
sub action_ajax_delete_file { |
|
130 |
my ( $self ) = @_; |
|
131 |
$self->file->delete; |
|
64 | 132 |
|
133 |
$self->js |
|
134 |
->run('kivi.shop_part.show_images',$self->file->trans_id) |
|
135 |
->render(); |
|
65 | 136 |
} |
66 | 137 |
|
67 | 138 |
sub action_get_categories { |
68 | 139 |
my ($self) = @_; |
69 | 140 |
|
70 |
# my $shop_part = SL::DB::Manager::ShopPart->find_by(id => $::form->{shop_part_id}); |
|
71 |
# die unless $shop_part; |
|
72 | 141 |
require SL::Shop; |
73 | 142 |
my $shop = SL::Shop->new( config => $self->shop_part->shop ); |
74 | 143 |
my $categories = $shop->connector->get_categories; |
... | ... | |
77 | 146 |
->run( |
78 | 147 |
'kivi.shop_part.shop_part_dialog', |
79 | 148 |
t8('Shopcategories'), |
80 |
$self->render('shop_part/categories', { output => 0 }, CATEGORIES => $categories ) #, shop_part => $self->shop_part)
|
|
149 |
$self->render('shop_part/categories', { output => 0 }, CATEGORIES => $categories ) |
|
81 | 150 |
) |
82 | 151 |
->reinit_widgets; |
83 | 152 |
|
... | ... | |
99 | 168 |
$self->create_or_update; |
100 | 169 |
} |
101 | 170 |
|
171 |
sub action_show_price_n_pricesource { |
|
172 |
my ($self) = @_; |
|
173 |
|
|
174 |
my ( $price, $price_src_str ) = $self->get_price_n_pricesource($::form->{pricesource}); |
|
175 |
|
|
176 |
#TODO Price must be formatted. $price_src_str must be translated |
|
177 |
$self->js->html('#price_' . $self->shop_part->id, $price) |
|
178 |
->html('#active_price_source_' . $self->shop_part->id, $price_src_str) |
|
179 |
->render; |
|
180 |
} |
|
181 |
|
|
182 |
sub action_show_stock { |
|
183 |
my ($self) = @_; |
|
184 |
my ( $stock_local, $stock_onlineshop ); |
|
185 |
|
|
186 |
require SL::Shop; |
|
187 |
my $shop = SL::Shop->new( config => $self->shop_part->shop ); |
|
188 |
my $shop_article = $shop->connector->get_article($self->shop_part->part->partnumber); |
|
189 |
|
|
190 |
$stock_local = $self->shop_part->part->onhand; |
|
191 |
$stock_onlineshop = $shop_article->{data}->{mainDetail}->{inStock}; |
|
192 |
|
|
193 |
$self->js->html('#stock_' . $self->shop_part->id, $stock_local."/".$stock_onlineshop) |
|
194 |
->render; |
|
195 |
} |
|
196 |
|
|
197 |
|
|
102 | 198 |
sub create_or_update { |
103 | 199 |
my ($self) = @_; |
104 | 200 |
|
... | ... | |
111 | 207 |
|
112 | 208 |
$self->shop_part->save; |
113 | 209 |
|
210 |
my ( $price, $price_src_str ) = $self->get_price_n_pricesource($self->shop_part->active_price_source); |
|
211 |
|
|
212 |
#TODO Price must be formatted. $price_src_str must be translated |
|
114 | 213 |
flash('info', $is_new ? t8('The shop part has been created.') : t8('The shop part has been saved.')); |
115 | 214 |
# $self->js->val('#partnumber', 'ladida'); |
116 | 215 |
$self->js->html('#shop_part_description_' . $self->shop_part->id, $self->shop_part->shop_description) |
117 | 216 |
->html('#shop_part_active_' . $self->shop_part->id, $self->shop_part->active) |
217 |
->html('#price_' . $self->shop_part->id, $price) |
|
218 |
->html('#active_price_source_' . $self->shop_part->id, $price_src_str) |
|
118 | 219 |
->run('kivi.shop_part.close_dialog') |
119 | 220 |
->flash('info', t8("Updated shop part")) |
120 | 221 |
->render; |
... | ... | |
183 | 284 |
$::request->{layout}->add_javascripts(qw(kivi.shop_part.js)); |
184 | 285 |
} |
185 | 286 |
|
287 |
sub load_pricesources { |
|
288 |
my ($self) = @_; |
|
289 |
|
|
290 |
# the price sources to use for the article: sellprice, lastcost, |
|
291 |
# listprice, or one of the pricegroups. It overwrites the default pricesource from the shopconfig. |
|
292 |
# TODO: implement valid pricerules for the article |
|
293 |
my $pricesources; |
|
294 |
push( @{ $pricesources } , { id => "master_data/sellprice", name => t8("Master Data")." - ".t8("Sellprice") }, |
|
295 |
{ id => "master_data/listprice", name => t8("Master Data")." - ".t8("Listprice") }, |
|
296 |
{ id => "master_data/lastcost", name => t8("Master Data")." - ".t8("Lastcost") } |
|
297 |
); |
|
298 |
my $pricegroups = SL::DB::Manager::Pricegroup->get_all; |
|
299 |
foreach my $pg ( @$pricegroups ) { |
|
300 |
push( @{ $pricesources } , { id => "pricegroup/".$pg->id, name => t8("Pricegroup") . " - " . $pg->pricegroup} ); |
|
301 |
}; |
|
302 |
|
|
303 |
$self->price_sources( $pricesources ); |
|
304 |
} |
|
305 |
|
|
306 |
sub get_price_n_pricesource { |
|
307 |
my ($self,$pricesource) = @_; |
|
308 |
|
|
309 |
my ( $price_src_str, $price_src_id ) = split(/\//,$pricesource); |
|
310 |
|
|
311 |
require SL::DB::Pricegroup; |
|
312 |
require SL::DB::Part; |
|
313 |
#TODO Price must be formatted. Translations for $price_grp_str |
|
314 |
my $price; |
|
315 |
if ($price_src_str eq "master_data") { |
|
316 |
my $part = SL::DB::Manager::Part->get_all( where => [id => $self->shop_part->part_id], with_objects => ['prices'],limit => 1)->[0]; |
|
317 |
$price = $part->$price_src_id; |
|
318 |
$price_src_str = $price_src_id; |
|
319 |
}else{ |
|
320 |
my $part = SL::DB::Manager::Part->get_all( where => [id => $self->shop_part->part_id, 'prices.'.pricegroup_id => $price_src_id], with_objects => ['prices'],limit => 1)->[0]; |
|
321 |
my $pricegrp = SL::DB::Manager::Pricegroup->find_by( id => $price_src_id )->pricegroup; |
|
322 |
$price = $part->prices->[0]->price; |
|
323 |
$price_src_str = $pricegrp; |
|
324 |
} |
|
325 |
return($price,$price_src_str); |
|
326 |
} |
|
327 |
|
|
186 | 328 |
sub check_auth { |
187 | 329 |
return 1; # TODO: implement shop rights |
188 | 330 |
# $::auth->assert('shop'); |
SL/DB/MetaSetup/Shop.pm | ||
---|---|---|
10 | 10 |
__PACKAGE__->meta->table('shops'); |
11 | 11 |
|
12 | 12 |
__PACKAGE__->meta->columns( |
13 |
connector => { type => 'text' }, |
|
14 |
description => { type => 'text' }, |
|
15 |
id => { type => 'serial', not_null => 1 }, |
|
16 |
login => { type => 'text' }, |
|
17 |
obsolete => { type => 'boolean', default => 'false', not_null => 1 }, |
|
18 |
password => { type => 'text' }, |
|
19 |
port => { type => 'integer' }, |
|
20 |
price_source => { type => 'text' }, |
|
21 |
pricetype => { type => 'text' }, |
|
22 |
sortkey => { type => 'integer' }, |
|
23 |
url => { type => 'text' }, |
|
13 |
connector => { type => 'text' }, |
|
14 |
description => { type => 'text' }, |
|
15 |
id => { type => 'serial', not_null => 1 }, |
|
16 |
last_order_number => { type => 'integer' }, |
|
17 |
login => { type => 'text' }, |
|
18 |
obsolete => { type => 'boolean', default => 'false', not_null => 1 }, |
|
19 |
orders_to_fetch => { type => 'integer' }, |
|
20 |
password => { type => 'text' }, |
|
21 |
port => { type => 'integer' }, |
|
22 |
price_source => { type => 'text' }, |
|
23 |
pricetype => { type => 'text' }, |
|
24 |
sortkey => { type => 'integer' }, |
|
25 |
url => { type => 'text' }, |
|
24 | 26 |
); |
25 | 27 |
|
26 | 28 |
__PACKAGE__->meta->primary_key_columns([ 'id' ]); |
SL/ShopConnector/Base.pm | ||
---|---|---|
13 | 13 |
|
14 | 14 |
sub update_part { die 'update_part needs to be implemented' } |
15 | 15 |
|
16 |
sub get_article { die 'get_article needs to be implemented' } |
|
17 |
|
|
16 | 18 |
sub get_categories { die 'get_order needs to be implemented' } |
17 | 19 |
1; |
18 | 20 |
|
SL/ShopConnector/Shopware.pm | ||
---|---|---|
12 | 12 |
use SL::DB::ShopOrder; |
13 | 13 |
use SL::DB::ShopOrderItem; |
14 | 14 |
use Data::Dumper; |
15 |
use Sort::Naturally (); |
|
16 |
use Encode qw(encode_utf8); |
|
17 |
use SL::Controller::ShopPart; |
|
15 | 18 |
|
16 | 19 |
use Rose::Object::MakeMethods::Generic ( |
17 | 20 |
'scalar --get_set_init' => [ qw(connector url) ], |
... | ... | |
185 | 188 |
$main::lxdebug->dump(0, 'WH: UPDATE JSON: ', \$json); |
186 | 189 |
my $url = $self->url; |
187 | 190 |
my $part = SL::DB::Part->new(id => $shop_part->{part_id})->load; |
188 |
#my $part = $shop_part->part; |
|
189 |
$main::lxdebug->dump(0, 'WH: Part',\$part); |
|
191 |
$main::lxdebug->dump(0, 'WH: SHOPPART: ',\$part); |
|
190 | 192 |
|
191 |
# TODO: Prices (pricerules, pricegroups, |
|
193 |
# TODO: Prices (pricerules, pricegroups, multiple prices)
|
|
192 | 194 |
my $cvars = { map { ($_->config->name => { value => $_->value_as_text, is_valid => $_->is_valid }) } @{ $part->cvars_by_config } }; |
193 | 195 |
#my $categories = { map { ( name => $_) } @{ $shop_part->{shop_category} } }; |
194 | 196 |
my @cat = (); |
... | ... | |
199 | 201 |
$main::lxdebug->dump(0, 'WH: TEMP: ', \$temp); |
200 | 202 |
|
201 | 203 |
push ( @cat, $temp ); |
202 |
#push ( @cat, map { ( name => $_[1]) } @{ $row_cat } ); |
|
203 | 204 |
} |
204 |
$main::lxdebug->dump(0, 'WH: CATEGORIES',\@cat); |
|
205 |
|
|
205 | 206 |
my $images = SL::DB::Manager::File->get_all( where => [ modul => 'shop_part', trans_id => $part->{id} ]); |
206 |
$main::lxdebug->dump(0, 'WH: IMAGES',\@{ $images } ); |
|
207 |
my $images2 = { map { |
|
208 |
( link => 'data:' . $_->{file_content_type} . ';base64,' . MIME::Base64::encode($_->{file_content},''), |
|
209 |
description => $_->{title}, |
|
210 |
position => $_->{position}, |
|
211 |
extension => 'jpg', # muss $extionsion sein |
|
212 |
path => $_->{filename}, # muss $path sein |
|
213 |
) } @{ $images } }; |
|
214 |
$main::lxdebug->dump(0, 'WH: IMAGES 2 ',\$images2); |
|
215 |
|
|
216 |
my @images3 = (); |
|
207 |
my @upload_img = (); |
|
217 | 208 |
foreach my $img (@{ $images }) { |
218 | 209 |
$main::lxdebug->dump(0, 'WH: FOR: ', \$img); |
219 | 210 |
|
220 | 211 |
my ($path, $extension) = (split /\./, $img->{filename}); |
221 |
$main::lxdebug->message(0, "WH: PATH: $path Ext: $extension"); |
|
222 |
|
|
223 |
my $temp ={ |
|
224 |
( link => 'data:' . $img->{file_content_type} . ';base64,' . MIME::Base64::encode($img->{file_content},''), |
|
225 |
description => $img->{title}, |
|
226 |
position => $img->{position}, |
|
227 |
extension => $extension, |
|
228 |
path => $path, |
|
212 |
my $temp ={ ( link => 'data:' . $img->{file_content_type} . ';base64,' . MIME::Base64::encode($img->{file_content},''), |
|
213 |
description => $img->{title}, |
|
214 |
position => $img->{position}, |
|
215 |
extension => $extension, |
|
229 | 216 |
)} ; |
230 | 217 |
push( @images3, $temp); |
231 | 218 |
} |
... | ... | |
234 | 221 |
my $data = $self->connector->get("http://$url/api/articles/$part->{partnumber}?useNumberAsId=true"); |
235 | 222 |
my $data_json = $data->content; |
236 | 223 |
my $import = SL::JSON::decode_json($data_json); |
237 |
$main::lxdebug->dump(0, 'WH: IMPORT', \$import); |
|
238 |
$main::lxdebug->dump(0, 'WH: Active', $shop_part->active); |
|
239 |
|
|
240 | 224 |
|
241 |
my %shop_data = ( name => $part->{description}, |
|
242 |
taxId => 4, # TODO Hardcoded kann auch der taxwert sein zB. tax => 19.00 |
|
243 |
mainDetail => { number => $part->{partnumber}, |
|
225 |
# get the right price |
|
226 |
my ( $price_src_str, $price_src_id ) = split(/\//,$shop_part->active_price_source); |
|
227 |
require SL::DB::Part; |
|
228 |
my $price; |
|
229 |
if ($price_src_str eq "master_data") { |
|
230 |
my $part = SL::DB::Manager::Part->get_all( where => [id => $shop_part->part_id], with_objects => ['prices'],limit => 1)->[0]; |
|
231 |
$price = $part->$price_src_id; |
|
232 |
}else{ |
|
233 |
my $part = SL::DB::Manager::Part->get_all( where => [id => $shop_part->part_id, 'prices.'.pricegroup_id => $price_src_id], with_objects => ['prices'],limit => 1)->[0]; |
|
234 |
$price = $part->prices->[0]->price; |
|
235 |
} |
|
236 |
# mapping to shopware still missing attributes,metatags |
|
237 |
my %shop_data = ( name => $part->{description}, |
|
238 |
taxId => 4, # TODO Hardcoded kann auch der taxwert sein zB. tax => 19.00 |
|
239 |
mainDetail => { number => $part->{partnumber}, |
|
244 | 240 |
inStock => $part->{onhand}, |
245 | 241 |
prices => [ { from => 1, |
246 |
price => $part->{sellprice},
|
|
242 |
price => $price,
|
|
247 | 243 |
customerGroupKey => 'EK', |
248 | 244 |
}, |
249 | 245 |
], |
... | ... | |
257 | 253 |
|
258 | 254 |
) |
259 | 255 |
; |
260 |
$main::lxdebug->dump(0, 'WH: SHOPDATA', \%shop_data );
|
|
261 |
my $dataString = SL::JSON::to_json(\%shop_data);
|
|
262 |
$dataString = encode_utf8($dataString); |
|
263 |
$main::lxdebug->message(0, 'WH: JSONDATA2 '.$dataString);
|
|
256 |
my $dataString = SL::JSON::to_json(\%shop_data);
|
|
257 |
$dataString = encode_utf8($dataString);
|
|
258 |
|
|
259 |
my $upload_content;
|
|
264 | 260 |
if($import->{success}){ |
265 | 261 |
$main::lxdebug->message(0, "WH: if success: ". $import->{success}); |
266 | 262 |
my %del_img = ( images => [ {} ], ) ; |
... | ... | |
269 | 265 |
#update |
270 | 266 |
my $upload = $self->connector->put("http://$url/api/articles/$part->{partnumber}?useNumberAsId=true",Content => $dataString); |
271 | 267 |
my $data_json = $upload->content; |
272 |
my $upload_content = SL::JSON::decode_json($data_json); |
|
273 |
$main::lxdebug->dump(0, "WH:2 else success: ", \$upload); |
|
274 |
return $upload_content->{success}; |
|
268 |
$upload_content = SL::JSON::decode_json($data_json); |
|
275 | 269 |
}else{ |
276 | 270 |
#upload |
277 | 271 |
$main::lxdebug->message(0, "WH: else success: ". $import->{success}); |
278 | 272 |
my $upload = $self->connector->post("http://$url/api/articles/",Content => $dataString); |
279 | 273 |
my $data_json = $upload->content; |
280 |
my $upload_content = SL::JSON::decode_json($data_json); |
|
281 |
$main::lxdebug->dump(0, "WH:2 else success: ", \$upload); |
|
282 |
return $upload_content->{success}; |
|
274 |
$upload_content = SL::JSON::decode_json($data_json); |
|
275 |
} |
|
276 |
if(@upload_img) { |
|
277 |
$self->connector->put("http://$url/api/generateArticleImages/$part->{partnumber}?useNumberAsId=true"); |
|
278 |
#$self->connector->delete("http://$url/api/caches/"); |
|
283 | 279 |
} |
280 |
return $upload_content->{success}; |
|
281 |
} |
|
282 |
|
|
283 |
sub get_article { |
|
284 |
my ($self,$partnumber) = @_; |
|
284 | 285 |
|
285 |
>>>>>>> b616804... Kategorien werden mit ID und Name in die DB geschrieben. Ein Komma im Name erzeugt noch Fehler. Der Pfad muss noch gemacht werden |
|
286 |
my $url = $self->url; |
|
287 |
my $data = $self->connector->get("http://$url/api/articles/$partnumber?useNumberAsId=true"); |
|
288 |
my $data_json = $data->content; |
|
289 |
return SL::JSON::decode_json($data_json); |
|
286 | 290 |
} |
287 | 291 |
|
288 | 292 |
sub init_url { |
js/kivi.shop_part.js | ||
---|---|---|
102 | 102 |
if (discount_str) $('#discount_' + row).val(discount_str); |
103 | 103 |
$('#update_button').click(); |
104 | 104 |
} |
105 |
|
|
106 |
ns.show_images = function(id) { |
|
107 |
var url = 'controller.pl?action=ShopPart/show_files&modul=shop_part&id='+id; |
|
108 |
$('#shop_images').load(url); |
|
109 |
} |
|
110 |
|
|
111 |
//shows the Name and price in _shop.html. Pricerules not implemented yet, just master_data and pricegroups |
|
112 |
ns.update_price_n_price_source = function(shop_part_id,price_source) { |
|
113 |
$.post('controller.pl', { action: 'ShopPart/show_price_n_pricesource', shop_part_id: shop_part_id, pricesource: price_source }, function(data) { |
|
114 |
kivi.eval_json_result(data); |
|
115 |
}); |
|
116 |
} |
|
117 |
//shows the local and the online stock |
|
118 |
ns.update_stock = function(shop_part_id) { |
|
119 |
$.post('controller.pl', { action: 'ShopPart/show_stock', shop_part_id: shop_part_id }, function(data) { |
|
120 |
kivi.eval_json_result(data); |
|
121 |
}); |
|
122 |
} |
|
123 |
|
|
105 | 124 |
}); |
sql/Pg-upgrade2/shop_parts_4.sql | ||
---|---|---|
1 |
-- @tag: shop_parts_4 |
|
2 |
-- @description: Add tables for part information for shop |
|
3 |
-- @charset: UTF-8 |
|
4 |
-- @depends: release_3_3_0 shops |
|
5 |
-- @ignore: 0 |
|
6 |
ALTER TABLE shop_parts ADD COLUMN active_price_source text; |
|
7 |
ALTER TABLE shop_parts ADD COLUMN metatag_keywords text; |
|
8 |
ALTER TABLE shop_parts ADD COLUMN metatag_description text; |
|
9 |
ALTER TABLE shop_parts ADD COLUMN metatag_title text; |
|
10 |
ALTER TABLE shop_parts DROP COLUMN meta_tags; |
sql/Pg-upgrade2/shops2.sql | ||
---|---|---|
1 |
-- @tag: shops2 |
|
2 |
-- @description: Alter table shops more columns for configuration |
|
3 |
-- @charset: UTF-8 |
|
4 |
-- @depends: release_3_4_0 shops |
|
5 |
-- @ignore: 0 |
|
6 |
|
|
7 |
ALTER TABLE shops ADD COLUMN last_order_number integer; |
|
8 |
ALTER TABLE shops ADD COLUMN orders_to_fetch integer; |
templates/webpages/shop_part/edit.html | ||
---|---|---|
3 | 3 |
[%- USE L -%] |
4 | 4 |
[%- USE P -%] |
5 | 5 |
[%- USE LxERP -%] |
6 |
[%- USE Dumper -%] |
|
6 | 7 |
|
7 | 8 |
[% LxERP.t8("Part") %]: [% HTML.escape(SELF.shop_part.part.displayable_name) %]<br> |
8 | 9 |
[% LxERP.t8("Shop") %]: [% HTML.escape(SELF.shop_part.shop.description) %] |
9 |
|
|
10 |
[% Dumper.dump_html(SELF) %] |
|
10 | 11 |
<form action="controller.pl" method="post"> |
11 | 12 |
<div> |
12 | 13 |
[% IF SELF.shop_part.id %] |
... | ... | |
26 | 27 |
<td>[% LxERP.t8("Active") %]</td> |
27 | 28 |
<td>[% L.yes_no_tag("shop_part.active", SELF.shop_part.active) %]</td> |
28 | 29 |
</tr> |
30 |
<tr> |
|
31 |
<th align="right">[% 'Price Source' | $T8 %]</th> |
|
32 |
[% IF SELF.shop_part.active_price_source %] |
|
33 |
[% SET price_source = SELF.shop_part.active_price_source %] |
|
34 |
[% ELSE %] |
|
35 |
[% SET price_source = SELF.shop_part.shop.price_source %] |
|
36 |
[% END %] |
|
37 |
<td>[% L.select_tag('shop_part.active_price_source', SELF.price_sources, value_key = 'id', title_key = 'name', with_empty = 0, default = price_source, default_value_key='id' ) %]</td> |
|
38 |
</tr> |
|
29 | 39 |
<tr> |
30 | 40 |
<td>[% LxERP.t8("Sort order") %]</td> |
31 | 41 |
<td>[% L.input_tag("shop_part.sortorder", SELF.shop_part.sortorder, size=2) %]</td> |
... | ... | |
39 | 49 |
<td>[% L.yes_no_tag('shop_part.front_page', SELF.shop_part.front_page) %]</td> |
40 | 50 |
</tr> |
41 | 51 |
<tr> |
42 |
<td>[% LxERP.t8("Meta Tags") %]</td> |
|
43 |
<td>[% L.input_tag("shop_part.meta_tags", SELF.shop_part.meta_tags, size=2) %]</td> |
|
52 |
<td>[% LxERP.t8("Meta tag title") %]</td> |
|
53 |
<td>[% L.input_tag("shop_part.metatag_title", SELF.shop_part.metatag_title, size=12) %]</td> |
|
54 |
</tr> |
|
55 |
<tr> |
|
56 |
<td>[% LxERP.t8("Meta tag keywords") %]</td> |
|
57 |
<td>[% L.input_tag("shop_part.metatag_keywords", SELF.shop_part.metatag_keywords, size=22) %]</td> |
|
58 |
</tr> |
|
59 |
<tr> |
|
60 |
<td>[% LxERP.t8("Meta tag description") %]</td> |
|
61 |
<td>[% L.textarea_tag("shop_part.metatag_description", SELF.shop_part.metatag_description, rows=4) %]</td> |
|
44 | 62 |
</tr> |
45 | 63 |
</table> |
46 | 64 |
[% # L.dump(SELF.shop_part) %] |
templates/webpages/shops/form.html | ||
---|---|---|
1 | 1 |
[%- USE HTML -%][%- USE LxERP -%][%- USE L -%][%- USE P -%][%- USE T8 -%] |
2 |
[%- USE Dumper -%] |
|
2 | 3 |
|
3 | 4 |
[% SET style="width: 400px" %] |
4 | 5 |
[% SET size=34 %] |
5 | 6 |
|
6 | 7 |
<h1>[% HTML.escape(title) %]</h1> |
7 |
|
|
8 |
[% # Dumper.dump_html(SELF.shop) %] |
|
8 | 9 |
<form action="controller.pl" method="post"> |
9 | 10 |
|
10 | 11 |
[%- INCLUDE 'common/flash.html' %] |
... | ... | |
26 | 27 |
</tr> |
27 | 28 |
<tr> |
28 | 29 |
<th align="right">[% 'Price Source' | $T8 %]</th> |
29 |
<td>[% L.select_tag('shop.price_source', SELF.price_sources, value_key = 'id', title_key = 'name', with_empty = 1, default = SELF.shop.price_source, default_value_key='id' ) %]</td>
|
|
30 |
<td>[% L.select_tag('shop.price_source', SELF.price_sources, value_key = 'id', title_key = 'name', with_empty = 0, default = SELF.shop.price_source, default_value_key='id' ) %]</td>
|
|
30 | 31 |
</tr> |
31 | 32 |
<tr> |
32 | 33 |
<th align="right">[% 'URL' | $T8 %]</th> |
... | ... | |
39 | 40 |
<th align="right">[% 'User' | $T8 %]</th> |
40 | 41 |
<td>[%- L.input_tag("shop.login", SELF.shop.login, size=12) %]</td> |
41 | 42 |
</tr> |
42 |
<tr>
|
|
43 |
<tr> |
|
43 | 44 |
<th align="right">[% 'Password' | $T8 %]</th> |
44 | 45 |
<td>[%- L.input_tag("shop.password", SELF.shop.password, size=12) %]</td> |
45 | 46 |
</tr> |
46 |
</tr> |
|
47 |
<tr> |
|
48 |
<th align="right">[% 'Last ordernumber' | $T8 %]</th> |
|
49 |
<td>[%- L.input_tag("shop.last_order_number", SELF.shop.last_order_number, size=12) %]</td> |
|
50 |
</tr> |
|
51 |
<tr> |
|
52 |
<th align="right">[% 'Orders to fetch' | $T8 %]</th> |
|
53 |
<td>[%- L.input_tag("shop.orders_to_fetch", SELF.shop.orders_to_fetch, size=12) %]</td> |
|
54 |
</tr> |
|
47 | 55 |
<tr> |
48 | 56 |
<th align="right">[% 'Obsolete' | $T8 %]</th> |
49 | 57 |
<td>[% L.checkbox_tag('shop.obsolete', checked = SELF.shop.obsolete, for_submit=1) %]</td> |
Auch abrufbar als: Unified diff
Shopmodul: Shoppart - Alle Daten werden angezeigt (Lager Lokal/Shop, Preisquelle, Preis) Lastupload Zeit wird in DB geschrieben und auch angezeigt
Shoppart: Alle Daten werden angezeigt (Lager Lokal/Shop, Preisquelle, Preis) Lastupload Zeit wird in DB geschrieben und auch angezeigt.
Formatierungen in den js für Zahlen fehlen noch Kleinere TODOs
Conflicts:
SL/Controller/ShopPart.pm
SL/ShopConnector/Shopware.pm
templates/webpages/ic/tabs/_shop.html
Shoppart: Last Upload article is written in db
Conflicts:
SL/ShopConnector/Shopware.pm
Conflicts:
SL/Controller/ShopPart.pm
SL/ShopConnector/Shopware.pm
js/kivi.shop_part.js