1 package SL::Controller::ShopOrder;
5 use parent qw(SL::Controller::Base);
7 use SL::BackgroundJob::ShopOrderMassTransfer;
8 use SL::System::TaskServer;
10 use SL::DB::ShopOrderItem;
15 use SL::Helper::Flash;
16 use SL::Locale::String;
17 use SL::Controller::Helper::ParseFilter;
18 use Rose::Object::MakeMethods::Generic
20 'scalar --get_set_init' => [ qw(shop_order shops transferred js) ],
23 __PACKAGE__->run_before('check_auth');
24 __PACKAGE__->run_before('setup');
28 sub action_get_orders {
33 my $type = $::form->{type};
34 if ( $type eq "get_next" ) {
35 my $active_shops = SL::DB::Manager::Shop->get_all(query => [ obsolete => 0 ]);
36 foreach my $shop_config ( @{ $active_shops } ) {
37 my $shop = SL::Shop->new( config => $shop_config );
39 $new_orders = $shop->connector->get_new_orders;
40 push @{ $orders_fetched }, $new_orders ;
43 } elsif ( $type eq "get_one" ) {
44 my $shop_id = $::form->{shop_id};
45 my $shop_ordernumber = $::form->{shop_ordernumber};
47 if ( $shop_id && $shop_ordernumber ){
48 my $shop_config = SL::DB::Manager::Shop->get_first(query => [ id => $shop_id, obsolete => 0 ]);
49 my $shop = SL::Shop->new( config => $shop_config );
50 unless ( SL::DB::Manager::ShopOrder->get_all_count( query => [ shop_ordernumber => $shop_ordernumber, shop_id => $shop_id, obsolete => 'f' ] )) {
51 my $connect = $shop->check_connectivity;
52 $new_orders = $shop->connector->get_one_order($shop_ordernumber);
53 push @{ $orders_fetched }, $new_orders ;
55 flash_later('error', t8('Shoporder "#2" From Shop "#1" is already fetched', $shop->config->description, $shop_ordernumber));
58 flash_later('error', t8('Shop or ordernumber not selected.'));
62 foreach my $shop_fetched(@{ $orders_fetched }) {
63 if($shop_fetched->{error}){
64 flash_later('error', t8('From shop "#1" : #2 ', $shop_fetched->{shop_description}, $shop_fetched->{message},));
66 flash_later('info', t8('From shop #1 : #2 shoporders have been fetched.', $shop_fetched->{description}, $shop_fetched->{number_of_orders},));
70 $self->redirect_to(controller => "ShopOrder", action => 'list', filter => { 'transferred:eq_ignore_empty' => 0, obsolete => 0 });
76 my %filter = ($::form->{filter} ? parse_filter($::form->{filter}) : query => [ transferred => 0, obsolete => 0 ]);
77 my $transferred = $::form->{filter}->{transferred_eq_ignore_empty} ne '' ? $::form->{filter}->{transferred_eq_ignore_empty} : '';
78 my $sort_by = $::form->{sort_by} ? $::form->{sort_by} : 'order_date';
79 $sort_by .=$::form->{sort_dir} ? ' DESC' : ' ASC';
80 my $shop_orders = SL::DB::Manager::ShopOrder->get_all( %filter, sort_by => $sort_by,
81 with_objects => ['shop_order_items', 'kivi_customer', 'shop'],
84 foreach my $shop_order(@{ $shop_orders }){
85 $shop_order->{open_invoices} = $shop_order->check_for_open_invoices;
87 $self->_setup_list_action_bar;
88 $self->render('shop_order/list',
89 title => t8('ShopOrders'),
90 SHOPORDERS => $shop_orders,
97 my $id = $::form->{id} || {};
98 my $shop_order = SL::DB::ShopOrder->new( id => $id )->load( with => ['kivi_customer'] );
99 die "can't find shoporder with id $id" unless $shop_order;
101 my $proposals = $shop_order->check_for_existing_customers;
103 $self->render('shop_order/show',
104 title => t8('Shoporder'),
105 IMPORT => $shop_order,
106 PROPOSALS => $proposals,
111 sub action_customer_assign_to_shoporder {
114 $self->shop_order->assign_attributes( kivi_customer => $::form->{customer} );
115 $self->shop_order->save;
116 $self->redirect_to(controller => "ShopOrder", action => 'show', id => $self->shop_order->id);
119 sub action_delete_order {
122 $self->shop_order->obsolete(1);
123 $self->shop_order->save;
124 $self->redirect_to(controller => "ShopOrder", action => 'list', filter => { 'transferred:eq_ignore_empty' => 0 });
127 sub action_undelete_order {
130 $self->shop_order->obsolete(0);
131 $self->shop_order->save;
132 $self->redirect_to(controller => "ShopOrder", action => 'list', filter => { 'transferred:eq_ignore_empty' => 0, obsolete => 0 });
135 sub action_transfer {
138 my $customer = SL::DB::Manager::Customer->find_by(id => $::form->{customer});
139 die "Can't find customer" unless $customer;
140 my $employee = SL::DB::Manager::Employee->current;
141 die "Can't find employee" unless $employee;
143 die "Can't load shop_order form form->import_id" unless $self->shop_order;
144 my $order = $self->shop_order->convert_to_sales_order(customer => $customer, employee => $employee);
146 if ($order->{error}){
147 flash_later('error',@{$order->{errors}});
148 $self->redirect_to(controller => "ShopOrder", action => 'show', id => $self->shop_order->id);
150 $order->db->with_transaction( sub {
151 $order->calculate_prices_and_taxes;
154 my $snumbers = "ordernumber_" . $order->ordnumber;
155 SL::DB::History->new(
156 trans_id => $order->id,
157 snumbers => $snumbers,
158 employee_id => SL::DB::Manager::Employee->current->id,
160 what_done => 'Shopimport -> Order',
162 foreach my $item(@{ $order->orderitems }){
163 $item->parse_custom_variable_values->save;
164 $item->{custom_variables} = \@{ $item->cvars_by_config };
168 $self->shop_order->transferred(1);
169 $self->shop_order->transfer_date(DateTime->now_local);
170 $self->shop_order->save;
171 $self->shop_order->link_to_record($order);
172 }) || die $order->db->error;
173 my $order_controller = $::instance_conf->get_feature_experimental_order ? 'Order' :'oe.pl';
174 $self->redirect_to(controller => $order_controller, action => 'edit', type => 'sales_order', vc => 'customer', id => $order->id);
178 sub action_mass_transfer {
180 my @shop_orders = @{ $::form->{id} || [] };
182 my $job = SL::DB::BackgroundJob->new(
185 package_name => 'ShopOrderMassTransfer',
187 shop_order_record_ids => [ @shop_orders ],
188 num_order_created => 0,
189 num_order_failed => 0,
190 num_delivery_order_created => 0,
191 status => SL::BackgroundJob::ShopOrderMassTransfer->WAITING_FOR_EXECUTION(),
192 conversion_errors => [],
193 )->update_next_run_at;
195 SL::System::TaskServer->new->wake_up;
197 my $html = $self->render('shop_order/_transfer_status', { output => 0 }, job => $job);
200 ->html('#status_mass_transfer', $html)
201 ->run('kivi.ShopOrder.massTransferStarted')
205 sub action_transfer_status {
207 my $job = SL::DB::BackgroundJob->new(id => $::form->{job_id})->load;
208 my $html = $self->render('shop_order/_transfer_status', { output => 0 }, job => $job);
210 $self->js->html('#status_mass_transfer', $html);
211 $self->js->run('kivi.ShopOrder.massTransferFinished') if $job->data_as_hash->{status} == SL::BackgroundJob::ShopOrderMassTransfer->DONE();
216 sub action_apply_customer {
217 my ( $self, %params ) = @_;
218 my $shop = SL::DB::Manager::Shop->find_by( id => $self->shop_order->shop_id );
219 my $what = $::form->{create_customer}; # new from billing, customer or delivery address
220 my %address = ( 'name' => $::form->{$what.'_name'},
221 'department_1' => $::form->{$what.'_company'},
222 'department_2' => $::form->{$what.'_department'},
223 'street' => $::form->{$what.'_street'},
224 'zipcode' => $::form->{$what.'_zipcode'},
225 'city' => $::form->{$what.'_city'},
226 'email' => $::form->{$what.'_email'},
227 'country' => $::form->{$what.'_country'},
228 'phone' => $::form->{$what.'_phone'},
229 'email' => $::form->{$what.'_email'},
230 'greeting' => $::form->{$what.'_greeting'},
231 'taxincluded_checked' => $shop->pricetype eq "brutto" ? 1 : 0,
232 'taxincluded' => $shop->pricetype eq "brutto" ? 1 : 0,
233 'pricegroup_id' => (split '\/',$shop->price_source)[0] eq "pricegroup" ? (split '\/',$shop->price_source)[1] : undef,
234 'taxzone_id' => $shop->taxzone_id,
235 'currency' => $::instance_conf->get_currency_id,
236 #'payment_id' => 7345,# TODO hardcoded
239 if($::form->{cv_id}){
240 $customer = SL::DB::Customer->new(id => $::form->{cv_id})->load;
241 $customer->assign_attributes(%address);
244 $customer = SL::DB::Customer->new(%address);
247 my $snumbers = "customernumber_" . $customer->customernumber;
248 SL::DB::History->new(
249 trans_id => $customer->id,
250 snumbers => $snumbers,
251 employee_id => SL::DB::Manager::Employee->current->id,
253 what_done => 'Shopimport',
256 $self->redirect_to(action => 'show', id => $::form->{import_id});
261 $::auth->assert('shop_part_edit');
262 $::request->layout->use_javascript("${_}.js") for qw(kivi.ShopOrder);
266 $::auth->assert('shop_part_edit');
272 sub init_shop_order {
274 return SL::DB::ShopOrder->new(id => $::form->{import_id})->load if $::form->{import_id};
277 sub init_transferred {
278 [ { title => t8("all"), value => '' },
279 { title => t8("transferred"), value => 1 },
280 { title => t8("not transferred"), value => 0 }, ]
284 SL::DB::Shop->shops_dd;
287 sub _setup_list_action_bar {
290 for my $bar ($::request->layout->get('actionbar')) {
294 submit => [ '#shoporders', { action => "ShopOrder/list" } ],
299 call => [ 'kivi.ShopOrder.get_orders_next' ],
300 tooltip => t8('New shop orders'),
304 call => [ 'kivi.ShopOrder.get_one_order_setup', id => "get_one" ],
305 tooltip => t8('Get one order by shopordernumber'),
311 call => [ 'kivi.ShopOrder.setup', id => "mass_transfer" ],
312 tooltip => t8('Transfer all marked'),
326 SL::Controller::ShopOrder - Shoporder CRUD Controller
330 Fetches the shoporders and transfers them to orders.
332 Relations for shoporders
336 =item shop_order_items
348 =item C<action_get_orders>
350 Fetches the shoporders with the shopconnector class
354 List the shoporders by different filters.
355 From the List you can transfer shoporders into orders in batch where it is possible or one by one.
359 Shows one order. From here you can apply/change/select customer data and transfer the shoporder to an order.
361 =item C<action_delete>
363 Marks the shoporder as obsolete. It's for shoporders you don't want to transfer.
365 =item C<action_undelete>
367 Marks the shoporder obsolete = false
369 =item C<action_transfer>
371 Transfers one shoporder to an order.
373 =item C<action_apply_customer>
375 Applys a new customer from the shoporder.
379 =head1 TASKSERVER ACTIONS
383 =item C<action_mass_transfer>
385 Transfers more shoporders by backgroundjob called from the taskserver to orders.
387 =item C<action_transfer_status>
389 Shows the backgroundjobdata for the popup status window
405 =item C<init_shoporder>
407 =item C<init_transfered>
409 Transferstatuses for the filter dropdown
413 Filter dropdown Shops
419 Implements different payments, pricesources and pricegroups. Till now not needed.
427 W. Hahn E<lt>wh@futureworldsearch.netE<gt>