825 |
825 |
}
|
826 |
826 |
|
827 |
827 |
# workflow from sales order to sales quotation
|
828 |
|
sub action_sales_quotation {
|
829 |
|
$_[0]->workflow_sales_or_request_for_quotation();
|
|
828 |
sub action_save_and_sales_quotation {
|
|
829 |
$_[0]->save_and_redirect_to(
|
|
830 |
action => 'sales_or_request_for_quotation',
|
|
831 |
type => $_[0]->type,
|
|
832 |
);
|
830 |
833 |
}
|
831 |
834 |
|
832 |
835 |
# workflow from sales order to sales quotation
|
833 |
|
sub action_request_for_quotation {
|
834 |
|
$_[0]->workflow_sales_or_request_for_quotation();
|
|
836 |
sub action_save_and_request_for_quotation {
|
|
837 |
$_[0]->save_and_redirect_to(
|
|
838 |
action => 'sales_or_request_for_quotation',
|
|
839 |
type => $_[0]->type,
|
|
840 |
);
|
835 |
841 |
}
|
836 |
842 |
|
837 |
843 |
# workflow from sales quotation to sales order
|
838 |
|
sub action_sales_order {
|
839 |
|
$_[0]->workflow_sales_or_purchase_order();
|
|
844 |
sub action_save_and_sales_order {
|
|
845 |
$_[0]->save_and_redirect_to(
|
|
846 |
action => 'sales_or_purchase_order',
|
|
847 |
type => $_[0]->type,
|
|
848 |
use_shipto => $::form->{use_shipto},
|
|
849 |
);
|
840 |
850 |
}
|
841 |
851 |
|
842 |
852 |
# workflow from rfq to purchase order
|
843 |
|
sub action_purchase_order {
|
844 |
|
$_[0]->workflow_sales_or_purchase_order();
|
|
853 |
sub action_save_and_purchase_order {
|
|
854 |
$_[0]->save_and_redirect_to(
|
|
855 |
action => 'sales_or_purchase_order',
|
|
856 |
type => $_[0]->type,
|
|
857 |
use_shipto => $::form->{use_shipto},
|
|
858 |
);
|
845 |
859 |
}
|
846 |
860 |
|
847 |
861 |
# workflow from purchase order to ap transaction
|
... | ... | |
854 |
868 |
);
|
855 |
869 |
}
|
856 |
870 |
|
|
871 |
sub action_sales_or_purchase_order {
|
|
872 |
my ($self) = @_;
|
|
873 |
|
|
874 |
$self->load_order;
|
|
875 |
|
|
876 |
my $destination_type = $::form->{type} eq sales_quotation_type() ? sales_order_type()
|
|
877 |
: $::form->{type} eq request_quotation_type() ? purchase_order_type()
|
|
878 |
: $::form->{type} eq purchase_order_type() ? sales_order_type()
|
|
879 |
: $::form->{type} eq sales_order_type() ? purchase_order_type()
|
|
880 |
: '';
|
|
881 |
|
|
882 |
# check for direct delivery
|
|
883 |
# copy shipto in custom shipto (custom shipto will be copied by new_from() in case)
|
|
884 |
my $custom_shipto;
|
|
885 |
if ( $::form->{type} eq sales_order_type() && $destination_type eq purchase_order_type()
|
|
886 |
&& $::form->{use_shipto} && $self->order->shipto) {
|
|
887 |
$custom_shipto = $self->order->shipto->clone('SL::DB::Order');
|
|
888 |
}
|
|
889 |
|
|
890 |
$self->order(SL::DB::Order->new_from($self->order, destination_type => $destination_type));
|
|
891 |
$self->{converted_from_oe_id} = delete $::form->{id};
|
|
892 |
|
|
893 |
# set item ids to new fake id, to identify them as new items
|
|
894 |
foreach my $item (@{$self->order->items_sorted}) {
|
|
895 |
$item->{new_fake_id} = join('_', 'new', Time::HiRes::gettimeofday(), int rand 1000000000000);
|
|
896 |
}
|
|
897 |
|
|
898 |
if ($::form->{type} eq sales_order_type() && $destination_type eq purchase_order_type()) {
|
|
899 |
if ($::form->{use_shipto}) {
|
|
900 |
$self->order->custom_shipto($custom_shipto) if $custom_shipto;
|
|
901 |
} else {
|
|
902 |
# remove any custom shipto if not wanted
|
|
903 |
$self->order->custom_shipto(SL::DB::Shipto->new(module => 'OE', custom_variables => []));
|
|
904 |
}
|
|
905 |
}
|
|
906 |
|
|
907 |
# change form type
|
|
908 |
$::form->{type} = $destination_type;
|
|
909 |
$self->type($self->init_type);
|
|
910 |
$self->cv ($self->init_cv);
|
|
911 |
$self->check_auth;
|
|
912 |
|
|
913 |
$self->recalc();
|
|
914 |
$self->get_unalterable_data();
|
|
915 |
$self->pre_render();
|
|
916 |
|
|
917 |
# trigger rendering values for second row as hidden, because they
|
|
918 |
# are loaded only on demand. So we need to keep the values from the
|
|
919 |
# source.
|
|
920 |
$_->{render_second_row} = 1 for @{ $self->order->items_sorted };
|
|
921 |
|
|
922 |
$self->render(
|
|
923 |
'order/form',
|
|
924 |
title => $self->get_title_for('edit'),
|
|
925 |
%{$self->{template_args}}
|
|
926 |
);
|
|
927 |
}
|
|
928 |
|
|
929 |
sub action_sales_or_request_for_quotation {
|
|
930 |
my ($self) = @_;
|
|
931 |
|
|
932 |
$self->load_order;
|
|
933 |
|
|
934 |
my $destination_type = $::form->{type} eq sales_order_type() ? sales_quotation_type() : request_quotation_type();
|
|
935 |
|
|
936 |
$self->order(SL::DB::Order->new_from($self->order, destination_type => $destination_type));
|
|
937 |
delete $::form->{id};
|
|
938 |
|
|
939 |
# no linked records from order to quotations
|
|
940 |
delete $::form->{$_} for qw(converted_from_oe_id converted_from_orderitems_ids);
|
|
941 |
|
|
942 |
# set item ids to new fake id, to identify them as new items
|
|
943 |
foreach my $item (@{$self->order->items_sorted}) {
|
|
944 |
$item->{new_fake_id} = join('_', 'new', Time::HiRes::gettimeofday(), int rand 1000000000000);
|
|
945 |
}
|
|
946 |
|
|
947 |
# change form type
|
|
948 |
$::form->{type} = $destination_type;
|
|
949 |
$self->type($self->init_type);
|
|
950 |
$self->cv ($self->init_cv);
|
|
951 |
$self->check_auth;
|
|
952 |
|
|
953 |
$self->recalc();
|
|
954 |
$self->get_unalterable_data();
|
|
955 |
$self->pre_render();
|
|
956 |
|
|
957 |
# trigger rendering values for second row as hidden, because they
|
|
958 |
# are loaded only on demand. So we need to keep the values from the
|
|
959 |
# source.
|
|
960 |
$_->{render_second_row} = 1 for @{ $self->order->items_sorted };
|
|
961 |
|
|
962 |
$self->render(
|
|
963 |
'order/form',
|
|
964 |
title => $self->get_title_for('edit'),
|
|
965 |
%{$self->{template_args}}
|
|
966 |
);
|
|
967 |
}
|
|
968 |
|
857 |
969 |
# set form elements in respect to a changed customer or vendor
|
858 |
970 |
#
|
859 |
971 |
# This action is called on an change of the customer/vendor picker.
|
... | ... | |
2071 |
2183 |
return $errors;
|
2072 |
2184 |
}
|
2073 |
2185 |
|
2074 |
|
sub workflow_sales_or_request_for_quotation {
|
2075 |
|
my ($self) = @_;
|
2076 |
|
|
2077 |
|
# always save
|
2078 |
|
my $errors = $self->save();
|
2079 |
|
|
2080 |
|
if (scalar @{ $errors }) {
|
2081 |
|
$self->js->flash('error', $_) for @{ $errors };
|
2082 |
|
return $self->js->render();
|
2083 |
|
}
|
2084 |
|
|
2085 |
|
my $destination_type = $::form->{type} eq sales_order_type() ? sales_quotation_type() : request_quotation_type();
|
2086 |
|
|
2087 |
|
$self->order(SL::DB::Order->new_from($self->order, destination_type => $destination_type));
|
2088 |
|
delete $::form->{id};
|
2089 |
|
|
2090 |
|
# no linked records from order to quotations
|
2091 |
|
delete $::form->{$_} for qw(converted_from_oe_id converted_from_orderitems_ids);
|
2092 |
|
|
2093 |
|
# set item ids to new fake id, to identify them as new items
|
2094 |
|
foreach my $item (@{$self->order->items_sorted}) {
|
2095 |
|
$item->{new_fake_id} = join('_', 'new', Time::HiRes::gettimeofday(), int rand 1000000000000);
|
2096 |
|
}
|
2097 |
|
|
2098 |
|
# change form type
|
2099 |
|
$::form->{type} = $destination_type;
|
2100 |
|
$self->type($self->init_type);
|
2101 |
|
$self->cv ($self->init_cv);
|
2102 |
|
$self->check_auth;
|
2103 |
|
|
2104 |
|
$self->recalc();
|
2105 |
|
$self->get_unalterable_data();
|
2106 |
|
$self->pre_render();
|
2107 |
|
|
2108 |
|
# trigger rendering values for second row as hidden, because they
|
2109 |
|
# are loaded only on demand. So we need to keep the values from the
|
2110 |
|
# source.
|
2111 |
|
$_->{render_second_row} = 1 for @{ $self->order->items_sorted };
|
2112 |
|
|
2113 |
|
$self->render(
|
2114 |
|
'order/form',
|
2115 |
|
title => $self->get_title_for('edit'),
|
2116 |
|
%{$self->{template_args}}
|
2117 |
|
);
|
2118 |
|
}
|
2119 |
|
|
2120 |
|
sub workflow_sales_or_purchase_order {
|
2121 |
|
my ($self) = @_;
|
2122 |
|
|
2123 |
|
# always save
|
2124 |
|
my $errors = $self->save();
|
2125 |
|
|
2126 |
|
if (scalar @{ $errors }) {
|
2127 |
|
$self->js->flash('error', $_) foreach @{ $errors };
|
2128 |
|
return $self->js->render();
|
2129 |
|
}
|
2130 |
|
|
2131 |
|
my $destination_type = $::form->{type} eq sales_quotation_type() ? sales_order_type()
|
2132 |
|
: $::form->{type} eq request_quotation_type() ? purchase_order_type()
|
2133 |
|
: $::form->{type} eq purchase_order_type() ? sales_order_type()
|
2134 |
|
: $::form->{type} eq sales_order_type() ? purchase_order_type()
|
2135 |
|
: '';
|
2136 |
|
|
2137 |
|
# check for direct delivery
|
2138 |
|
# copy shipto in custom shipto (custom shipto will be copied by new_from() in case)
|
2139 |
|
my $custom_shipto;
|
2140 |
|
if ( $::form->{type} eq sales_order_type() && $destination_type eq purchase_order_type()
|
2141 |
|
&& $::form->{use_shipto} && $self->order->shipto) {
|
2142 |
|
$custom_shipto = $self->order->shipto->clone('SL::DB::Order');
|
2143 |
|
}
|
2144 |
|
|
2145 |
|
$self->order(SL::DB::Order->new_from($self->order, destination_type => $destination_type));
|
2146 |
|
$self->{converted_from_oe_id} = delete $::form->{id};
|
2147 |
|
|
2148 |
|
# set item ids to new fake id, to identify them as new items
|
2149 |
|
foreach my $item (@{$self->order->items_sorted}) {
|
2150 |
|
$item->{new_fake_id} = join('_', 'new', Time::HiRes::gettimeofday(), int rand 1000000000000);
|
2151 |
|
}
|
2152 |
|
|
2153 |
|
if ($::form->{type} eq sales_order_type() && $destination_type eq purchase_order_type()) {
|
2154 |
|
if ($::form->{use_shipto}) {
|
2155 |
|
$self->order->custom_shipto($custom_shipto) if $custom_shipto;
|
2156 |
|
} else {
|
2157 |
|
# remove any custom shipto if not wanted
|
2158 |
|
$self->order->custom_shipto(SL::DB::Shipto->new(module => 'OE', custom_variables => []));
|
2159 |
|
}
|
2160 |
|
}
|
2161 |
|
|
2162 |
|
# change form type
|
2163 |
|
$::form->{type} = $destination_type;
|
2164 |
|
$self->type($self->init_type);
|
2165 |
|
$self->cv ($self->init_cv);
|
2166 |
|
$self->check_auth;
|
2167 |
|
|
2168 |
|
$self->recalc();
|
2169 |
|
$self->get_unalterable_data();
|
2170 |
|
$self->pre_render();
|
2171 |
|
|
2172 |
|
# trigger rendering values for second row as hidden, because they
|
2173 |
|
# are loaded only on demand. So we need to keep the values from the
|
2174 |
|
# source.
|
2175 |
|
$_->{render_second_row} = 1 for @{ $self->order->items_sorted };
|
2176 |
|
|
2177 |
|
$self->render(
|
2178 |
|
'order/form',
|
2179 |
|
title => $self->get_title_for('edit'),
|
2180 |
|
%{$self->{template_args}}
|
2181 |
|
);
|
2182 |
|
}
|
2183 |
|
|
2184 |
|
|
2185 |
2186 |
sub pre_render {
|
2186 |
2187 |
my ($self) = @_;
|
2187 |
2188 |
|
... | ... | |
2343 |
2344 |
],
|
2344 |
2345 |
action => [
|
2345 |
2346 |
t8('Save and Quotation'),
|
2346 |
|
submit => [ '#order_form', { action => "Order/sales_quotation" } ],
|
|
2347 |
call => [ 'kivi.submit_ajax_form', $self->url_for(action => "save_and_sales_quotation"), '#order_form' ],
|
2347 |
2348 |
checks => [ @req_trans_cost_art, @req_cusordnumber ],
|
2348 |
2349 |
only_if => (any { $self->type eq $_ } (sales_order_type())),
|
2349 |
2350 |
disabled => !$may_edit_create ? t8('You do not have the permissions to access this function.') : undef,
|
2350 |
2351 |
],
|
2351 |
2352 |
action => [
|
2352 |
2353 |
t8('Save and RFQ'),
|
2353 |
|
submit => [ '#order_form', { action => "Order/request_for_quotation" } ],
|
|
2354 |
call => [ 'kivi.submit_ajax_form', $self->url_for(action => "save_and_request_for_quotation"), '#order_form' ],
|
2354 |
2355 |
only_if => (any { $self->type eq $_ } (purchase_order_type())),
|
2355 |
2356 |
disabled => !$may_edit_create ? t8('You do not have the permissions to access this function.') : undef,
|
2356 |
2357 |
],
|
2357 |
2358 |
action => [
|
2358 |
2359 |
t8('Save and Sales Order'),
|
2359 |
|
submit => [ '#order_form', { action => "Order/sales_order" } ],
|
|
2360 |
call => [ 'kivi.submit_ajax_form', $self->url_for(action => "save_and_sales_order"), '#order_form' ],
|
2360 |
2361 |
checks => [ @req_trans_cost_art ],
|
2361 |
2362 |
only_if => (any { $self->type eq $_ } (sales_quotation_type(), purchase_order_type())),
|
2362 |
2363 |
disabled => !$may_edit_create ? t8('You do not have the permissions to access this function.') : undef,
|
Auftrags-Controller: Workflows: Fehlermeldung beim Speichern richtig anzeigen
Workflows von und zum Auftrags-Controller wurden mit einem submit aufgerufen
(bis auf die Workflows zu Angeboten - hier wurde ein ajax-Call verwendet,
der dann aber wiederum ein submit gemacht hat).
Da Fehler beim Speichern aber per js->flash ausgegeben wurden, wurden hier
im Browser nur die json-Daten angezeigt.
Nun wird in einer action zuerst gespeichert und dann ein redirect auf die
Workflow-actions ausgeführt, so wie bei den Workflows zu anderen Controllern
auch.