From: Sven Schöling Date: Tue, 11 Oct 2011 13:13:04 +0000 (+0200) Subject: Merge branch 'master' of vc.linet-services.de:public/lx-office-erp X-Git-Tag: release-2.7.0beta1~240 X-Git-Url: http://wagnertech.de/gitweb/gitweb.cgi/mfinanz.git/commitdiff_plain/8084ef359515031ec8429b49baf0ab09858f55d2?hp=3bde3a2889c30abd19e4f48fb4126b713faf75b7 Merge branch 'master' of vc.linet-services.de:public/lx-office-erp --- diff --git a/SL/CVar.pm b/SL/CVar.pm index 779bfc325..8b3cd8e27 100644 --- a/SL/CVar.pm +++ b/SL/CVar.pm @@ -240,6 +240,7 @@ sub get_custom_variables { $cvar->{value} = $cvar->{type} eq 'date' ? $act_var->{date_value} : $cvar->{type} eq 'timestamp' ? $act_var->{timestamp_value} : $cvar->{type} eq 'number' ? $act_var->{number_value} + : $cvar->{type} eq 'customer' ? $act_var->{number_value} : $cvar->{type} eq 'bool' ? $act_var->{bool_value} : $act_var->{text_value}; $cvar->{valid} = $valid; @@ -273,6 +274,9 @@ sub get_custom_variables { if ($cvar->{type} eq 'number') { $cvar->{value} = $form->format_amount($myconfig, $cvar->{value} * 1, $cvar->{precision}); + } elsif ($cvar->{type} eq 'customer') { + require SL::DB::Customer; + $cvar->{value} = SL::DB::Manager::Customer->find_by(id => $cvar->{value} * 1); } } @@ -334,6 +338,8 @@ sub save_custom_variables { } elsif ($config->{type} eq 'bool') { push @values, $value ? 't' : 'f', undef, undef, undef; + } elsif ($config->{type} eq 'customer') { + push @values, undef, undef, undef, $value * 1; } do_statement($form, $sth, $query, @values); @@ -489,6 +495,11 @@ sub build_filter_query { $not = 'NOT' if ($params{filter}->{$name} eq 'no'); push @sub_where, qq|COALESCE(cvar.bool_value, false) = TRUE|; + } elsif ($config->{type} eq 'customer') { + next unless $params{filter}->{$name}; + + push @sub_where, qq|cvar.number_value * 1 IN (SELECT id FROM customer WHERE name ILIKE ?)|; + push @sub_values, "%$params{filter}->{$name}%"; } if (@sub_where) { @@ -562,6 +573,7 @@ sub add_custom_variables_to_report { $cfg->{type} eq 'date' ? $ref->{date_value} : $cfg->{type} eq 'timestamp' ? $ref->{timestamp_value} : $cfg->{type} eq 'number' ? $form->format_amount($myconfig, $ref->{number_value} * 1, $cfg->{precision}) + : $cfg->{type} eq 'customer' ? SL::DB::Manager::Customer->find_by(id => 1* $ref->{number_value})->name : $cfg->{type} eq 'bool' ? ($ref->{bool_value} ? $locale->text('Yes') : $locale->text('No')) : $ref->{text_value}; } diff --git a/SL/Controller/Base.pm b/SL/Controller/Base.pm index f8eee88a6..42bf6bd6e 100644 --- a/SL/Controller/Base.pm +++ b/SL/Controller/Base.pm @@ -45,6 +45,9 @@ sub render { if ($options->{inline}) { $source = \$template; + } elsif($options->{raw}) { + $source = $template; + } else { $source = "templates/webpages/${template}." . $options->{type}; croak "Template file ${source} not found" unless -f $source; @@ -77,8 +80,12 @@ sub render { ); my $output; - my $parser = $self->_template_obj; - $parser->process($source, \%params, \$output) || croak $parser->error; + if (!$options->{raw}) { + my $parser = $self->_template_obj; + $parser->process($source, \%params, \$output) || croak $parser->error; + } else { + $output = $$source; + } print $output unless $options->{inline} || $options->{no_output}; @@ -322,6 +329,10 @@ containing the template code to interprete. Additionally the output will not be sent to the browser. Instead it is only returned to the caller. +If C<< $options->{raw}>> is trueish, the function will treat the input as +already parsed, and will not filter the input through Template. Unlike +C, the input is taked as a reference. + If C<< $options->{inline} >> is falsish then C<$template> is interpreted as the name of a template file. It is prefixed with "templates/webpages/" and postfixed with a file extension based on diff --git a/SL/Controller/Customer.pm b/SL/Controller/Customer.pm new file mode 100644 index 000000000..4358080fe --- /dev/null +++ b/SL/Controller/Customer.pm @@ -0,0 +1,27 @@ +package SL::Controller::Customer; + +use strict; +use parent qw(SL::Controller::Base); + +use SL::DB::Customer; + +# safety +__PACKAGE__->run_before(sub { $::auth->assert('customer_vendor_edit') }); + +sub action_ajax_autocomplete { + my ($self, %params) = @_; + + my $limit = $::form->{limit} || 20; + my $type = $::form->{type} || {}; + my $query = { ilike => "%$::form->{term}%" }; + my @filter; + push @filter, ($::form->{column}) + ? ($::form->{column} => $query) + : (or => [ customernumber => $query, name => $query ]); + + $self->{customers} = SL::DB::Manager::Customer->get_all(query => [ @filter ], limit => $limit); + $self->{value} = $::form->{column} || 'name'; + + $self->render('ct/ajax_autocomplete2', { no_layout => 1 }); +} + diff --git a/SL/Controller/Part.pm b/SL/Controller/Part.pm new file mode 100644 index 000000000..36859e71a --- /dev/null +++ b/SL/Controller/Part.pm @@ -0,0 +1,30 @@ +package SL::Controller::Part; + +use strict; +use parent qw(SL::Controller::Base); + +use SL::DB::Part; + +# safety +__PACKAGE__->run_before(sub { $::auth->assert('part_service_assembly_edit') }); + +sub action_ajax_autocomplete { + my ($self, %params) = @_; + + my $limit = $::form->{limit} || 20; + my $type = $::form->{type} || {}; + my $query = { ilike => "%$::form->{term}%" }; + my @filter; + push @filter, SL::DB::Manager::Part->type_filter($type); + push @filter, ($::form->{column}) + ? ($::form->{column} => $query) + : (or => [ partnumber => $query, description => $query ]); + + $self->{parts} = SL::DB::Manager::Part->get_all(query => [ @filter ], limit => $limit); + $self->{value} = $::form->{column} || 'description'; + + $self->render('part/ajax_autocomplete', { no_layout => 1 }); +} + + +1; diff --git a/SL/DB/Customer.pm b/SL/DB/Customer.pm index 0adffbddd..f9f890167 100644 --- a/SL/DB/Customer.pm +++ b/SL/DB/Customer.pm @@ -50,4 +50,10 @@ sub short_address { return join ', ', grep { $_ } $self->street, $self->zipcode, $self->city; } +sub displayable_name { + my $self = shift; + + return join ' ', grep $_, $self->customernumber, $self->name; +} + 1; diff --git a/SL/DB/Helper/Mappings.pm b/SL/DB/Helper/Mappings.pm index b1782716f..8382f1f7c 100644 --- a/SL/DB/Helper/Mappings.pm +++ b/SL/DB/Helper/Mappings.pm @@ -105,6 +105,7 @@ my %lxoffice_package_names = ( translation_payment_terms => 'translation_payment_term', units => 'unit', units_language => 'units_language', + vendor => 'vendor', vendortax => 'vendor_tax', ); diff --git a/SL/DB/Manager/Part.pm b/SL/DB/Manager/Part.pm index e6aca1f71..50219cb61 100644 --- a/SL/DB/Manager/Part.pm +++ b/SL/DB/Manager/Part.pm @@ -7,32 +7,36 @@ use base qw(SL::DB::Helper::Manager); use Carp; use SL::DBUtils; +use SL::MoreCommon qw(listify); sub object_class { 'SL::DB::Part' } __PACKAGE__->make_manager_methods; sub type_filter { - my $class = shift; - my $type = lc(shift || ''); - - if ($type =~ m/^part/) { - return (and => [ or => [ assembly => 0, assembly => undef ], - '!inventory_accno_id' => 0, - '!inventory_accno_id' => undef, - ]); - - } elsif ($type =~ m/^service/) { - return (and => [ or => [ assembly => 0, assembly => undef ], - or => [ inventory_accno_id => 0, inventory_accno_id => undef ], - ]); - - } elsif ($type =~ m/^assembl/) { - return (assembly => 1); - + my ($class, $type) = @_; + + return () unless $type; + + my @types = listify($type); + my @filter; + + for my $type (@types) { + if ($type =~ m/^part/) { + push @filter, (and => [ or => [ assembly => 0, assembly => undef ], + '!inventory_accno_id' => 0, + '!inventory_accno_id' => undef, + ]); + } elsif ($type =~ m/^service/) { + push @filter, (and => [ or => [ assembly => 0, assembly => undef ], + or => [ inventory_accno_id => 0, inventory_accno_id => undef ], + ]); + } elsif ($type =~ m/^assembl/) { + push @filter, (assembly => 1); + } } - return (); + return @filter ? (or => \@filter) : (); } sub get_ordered_qty { diff --git a/SL/DB/MetaSetup/Invoice.pm b/SL/DB/MetaSetup/Invoice.pm index be3466d60..d300a7e6a 100644 --- a/SL/DB/MetaSetup/Invoice.pm +++ b/SL/DB/MetaSetup/Invoice.pm @@ -10,51 +10,52 @@ __PACKAGE__->meta->setup( table => 'ar', columns => [ - id => { type => 'integer', not_null => 1, sequence => 'glid' }, - invnumber => { type => 'text', not_null => 1 }, - transdate => { type => 'date', default => 'now' }, - gldate => { type => 'date', default => 'now' }, - customer_id => { type => 'integer' }, - taxincluded => { type => 'boolean' }, - amount => { type => 'numeric', precision => 5, scale => 15 }, - netamount => { type => 'numeric', precision => 5, scale => 15 }, - paid => { type => 'numeric', precision => 5, scale => 15 }, - datepaid => { type => 'date' }, - duedate => { type => 'date' }, - deliverydate => { type => 'date' }, - invoice => { type => 'boolean', default => 'false' }, - shippingpoint => { type => 'text' }, - terms => { type => 'integer', default => '0' }, - notes => { type => 'text' }, - curr => { type => 'character', length => 3 }, - ordnumber => { type => 'text' }, - employee_id => { type => 'integer' }, - quonumber => { type => 'text' }, - cusordnumber => { type => 'text' }, - intnotes => { type => 'text' }, - department_id => { type => 'integer', default => '0' }, - shipvia => { type => 'text' }, - itime => { type => 'timestamp', default => 'now()' }, - mtime => { type => 'timestamp' }, - cp_id => { type => 'integer' }, - language_id => { type => 'integer' }, - payment_id => { type => 'integer' }, - delivery_customer_id => { type => 'integer' }, - delivery_vendor_id => { type => 'integer' }, - storno => { type => 'boolean', default => 'false' }, - taxzone_id => { type => 'integer' }, - shipto_id => { type => 'integer' }, - type => { type => 'text' }, - dunning_config_id => { type => 'integer' }, - orddate => { type => 'date' }, - quodate => { type => 'date' }, - globalproject_id => { type => 'integer' }, - salesman_id => { type => 'integer' }, - transaction_description => { type => 'text' }, - storno_id => { type => 'integer' }, - marge_total => { type => 'numeric', precision => 5, scale => 15 }, - marge_percent => { type => 'numeric', precision => 5, scale => 15 }, - donumber => { type => 'text' }, + id => { type => 'integer', not_null => 1, sequence => 'glid' }, + invnumber => { type => 'text', not_null => 1 }, + transdate => { type => 'date', default => 'now' }, + gldate => { type => 'date', default => 'now' }, + customer_id => { type => 'integer' }, + taxincluded => { type => 'boolean' }, + amount => { type => 'numeric', precision => 5, scale => 15 }, + netamount => { type => 'numeric', precision => 5, scale => 15 }, + paid => { type => 'numeric', precision => 5, scale => 15 }, + datepaid => { type => 'date' }, + duedate => { type => 'date' }, + deliverydate => { type => 'date' }, + invoice => { type => 'boolean', default => 'false' }, + shippingpoint => { type => 'text' }, + terms => { type => 'integer', default => '0' }, + notes => { type => 'text' }, + curr => { type => 'character', length => 3 }, + ordnumber => { type => 'text' }, + employee_id => { type => 'integer' }, + quonumber => { type => 'text' }, + cusordnumber => { type => 'text' }, + intnotes => { type => 'text' }, + department_id => { type => 'integer', default => '0' }, + shipvia => { type => 'text' }, + itime => { type => 'timestamp', default => 'now()' }, + mtime => { type => 'timestamp' }, + cp_id => { type => 'integer' }, + language_id => { type => 'integer' }, + payment_id => { type => 'integer' }, + delivery_customer_id => { type => 'integer' }, + delivery_vendor_id => { type => 'integer' }, + storno => { type => 'boolean', default => 'false' }, + taxzone_id => { type => 'integer' }, + shipto_id => { type => 'integer' }, + type => { type => 'text' }, + dunning_config_id => { type => 'integer' }, + orddate => { type => 'date' }, + quodate => { type => 'date' }, + globalproject_id => { type => 'integer' }, + salesman_id => { type => 'integer' }, + transaction_description => { type => 'text' }, + storno_id => { type => 'integer' }, + marge_total => { type => 'numeric', precision => 5, scale => 15 }, + marge_percent => { type => 'numeric', precision => 5, scale => 15 }, + donumber => { type => 'text' }, + invnumber_for_credit_note => { type => 'text' }, ], primary_key_columns => [ 'id' ], diff --git a/SL/DB/MetaSetup/Order.pm b/SL/DB/MetaSetup/Order.pm index e616aa3d0..3595026b0 100644 --- a/SL/DB/MetaSetup/Order.pm +++ b/SL/DB/MetaSetup/Order.pm @@ -53,6 +53,11 @@ __PACKAGE__->meta->setup( allow_inline_column_values => 1, foreign_keys => [ + customer => { + class => 'SL::DB::Customer', + key_columns => { customer_id => 'id' }, + }, + employee => { class => 'SL::DB::Employee', key_columns => { employee_id => 'id' }, @@ -67,6 +72,11 @@ __PACKAGE__->meta->setup( class => 'SL::DB::Employee', key_columns => { salesman_id => 'id' }, }, + + vendor => { + class => 'SL::DB::Vendor', + key_columns => { vendor_id => 'id' }, + }, ], ); diff --git a/SL/Form.pm b/SL/Form.pm index a23bb4337..b21f94c71 100644 --- a/SL/Form.pm +++ b/SL/Form.pm @@ -701,7 +701,9 @@ sub header { '', '', '', - ''; + '', + '', + ''; push @header, $self->{javascript} if $self->{javascript}; push @header, map { $_->show_javascript } @{ $self->{AJAX} || [] }; push @header, "" if $self->{fokus}; diff --git a/SL/Template/Plugin/JSON.pm b/SL/Template/Plugin/JSON.pm new file mode 100644 index 000000000..3709d8f0a --- /dev/null +++ b/SL/Template/Plugin/JSON.pm @@ -0,0 +1,51 @@ +package SL::Template::Plugin::JSON; + +use JSON (); +use Carp qw(croak); +use base qw(Template::Plugin); + +our $VERSION = "0.06"; + +sub new { + my ($class, $context, $args) = @_; + + my $self = bless {context => $context, json_args => $args }, $class; + + $context->define_vmethod($_, json => sub { $self->json(@_) }) for qw(hash list scalar); + + return $self; +} + +sub json_converter { + my ($self, %params) = @_; + + if (!$self->{json}) { + $self->{json} = JSON->new->allow_nonref(1); + + my $args = $self->{json_args}; + + for my $method (keys %$args) { + if ( $self->{json}->can($method) ) { + $self->{json}->$method( $args->{$method} ); + } + } + } + + return $self->{json}; +} + +sub json { + my ($self, $value) = @_; + + $self->json_converter->encode($value); +} + +sub json_decode { + my ( $self, $value ) = @_; + + $self->json_converter->decode($value); +} + +1; + +__END__ diff --git a/SL/Template/Plugin/L.pm b/SL/Template/Plugin/L.pm index 0ed2a8784..476b60a70 100644 --- a/SL/Template/Plugin/L.pm +++ b/SL/Template/Plugin/L.pm @@ -291,6 +291,40 @@ sub date_tag { ) : ''); } +sub customer_picker { + my ($self, $name, $value, %params) = @_; + my $name_e = _H($name); + + $self->hidden_tag($name, (ref $value && $value->can('id')) ? $value->id : '') . + $self->input_tag("$name_e\_name", (ref $value && $value->can('name')) ? $value->name : '', %params) . + $self->javascript(<{form}; my $value; - if (($get_array || @indices) && (ref $form->{TEMPLATE_ARRAYS} eq 'HASH') && (ref $form->{TEMPLATE_ARRAYS}->{$var} eq 'ARRAY')) { + if ($var =~ m/\./) { + $value = $form; + for my $part (split(m/\./, $var)) { + if (ref($value) =~ m/^(?:Form|HASH)$/) { + $value = $value->{$part}; + } elsif (blessed($value) && $value->can($part)) { + $value = $value->$part; + } else { + $value = ''; + last; + } + } + } elsif (($get_array || @indices) && (ref $form->{TEMPLATE_ARRAYS} eq 'HASH') && (ref $form->{TEMPLATE_ARRAYS}->{$var} eq 'ARRAY')) { $value = $form->{TEMPLATE_ARRAYS}->{$var}; } else { $value = $form->{$var}; diff --git a/bin/mozilla/amcvar.pl b/bin/mozilla/amcvar.pl index fc4f26f14..c0a0e88cc 100644 --- a/bin/mozilla/amcvar.pl +++ b/bin/mozilla/amcvar.pl @@ -54,9 +54,10 @@ our %translations = ('text' => $locale->text('Free-form text'), 'timestamp' => $locale->text('Timestamp'), 'bool' => $locale->text('Yes/No (Checkbox)'), 'select' => $locale->text('Selection'), + 'customer' => $locale->text('Customer'), ); -our @types = qw(text textfield number date bool select); # timestamp +our @types = qw(text textfield number date bool select customer); # timestamp our @modules = ({ module => 'CT', description => $locale->text('Customers and vendors') }, { module => 'IC', description => $locale->text('Parts, services and assemblies') }, diff --git a/sql/Pg-upgrade2/oe_customer_vendor_fkeys.sql b/sql/Pg-upgrade2/oe_customer_vendor_fkeys.sql new file mode 100644 index 000000000..0ac6c8bf1 --- /dev/null +++ b/sql/Pg-upgrade2/oe_customer_vendor_fkeys.sql @@ -0,0 +1,11 @@ +-- @tag: oe_customer_vendor_fkeys +-- @encoding: utf-8 +-- @description: Foreign Keys für customer und vendor in oe +-- @depends: release_2_6_3 +-- @timestamp: 1317380460 +UPDATE oe SET customer_id = NULL WHERE customer_id = 0; +UPDATE oe SET vendor_id = NULL WHERE vendor_id = 0; + + +ALTER TABLE oe ADD FOREIGN KEY (customer_id) REFERENCES customer(id); +ALTER TABLE oe ADD FOREIGN KEY (vendor_id) REFERENCES vendor(id); diff --git a/templates/webpages/amcvar/render_inputs.html b/templates/webpages/amcvar/render_inputs.html index 335a77c9f..ba350da2f 100644 --- a/templates/webpages/amcvar/render_inputs.html +++ b/templates/webpages/amcvar/render_inputs.html @@ -1,5 +1,6 @@ [%- USE T8 %] -[% USE HTML %] +[%- USE HTML %] +[%- USE L %] [%- SET var_name = HTML.escape(name_prefix) _ "cvar_" _ HTML.escape(var.name) _ HTML.escape(name_postfix) -%] @@ -33,6 +34,9 @@ [%- ELSIF var.type == 'timestamp' %] +[%- ELSIF var.type == 'customer' %] +[% L.customer_picker(var_name, var.value) %] + [%- ELSIF var.type == 'select' %] +[%- ELSIF cvar.var.type == 'customer' %] +[% render_input_blocks__cvar_name = PROCESS cvar_name %][% L.customer_picker(render_input_blocks__cvar_name, cvar.value) %] [%- ELSE %] [%- END %] diff --git a/templates/webpages/amcvar/search_filter.html b/templates/webpages/amcvar/search_filter.html index 0bf105e78..db37d08a7 100644 --- a/templates/webpages/amcvar/search_filter.html +++ b/templates/webpages/amcvar/search_filter.html @@ -46,6 +46,9 @@ + [%- ELSIF var.type == 'customer' %] + + [% ELSIF var.type == 'select' %]