X-Git-Url: http://wagnertech.de/gitweb/gitweb.cgi/mfinanz.git/blobdiff_plain/9aaadfdc06efbfb31f70c32cdf6aacf2f8a136f2..99d0bd2b810d7d4268c104d0a0ea8e67a63b55d2:/SL/Presenter/Part.pm diff --git a/SL/Presenter/Part.pm b/SL/Presenter/Part.pm index 25d682037..4bd45ca41 100644 --- a/SL/Presenter/Part.pm +++ b/SL/Presenter/Part.pm @@ -2,22 +2,116 @@ package SL::Presenter::Part; use strict; +use SL::DB::Part; +use SL::DB::PartClassification; +use SL::Locale::String qw(t8); + use Exporter qw(import); -our @EXPORT = qw(part_picker); +our @EXPORT = qw(part_picker part select_classification classification_abbreviation type_abbreviation separate_abbreviation typeclass_abbreviation); + +use Carp; + +sub part { + my ($self, $part, %params) = @_; + + $params{display} ||= 'inline'; + + croak "Unknown display type '$params{display}'" unless $params{display} =~ m/^(?:inline|table-cell)$/; + + my $text = join '', ( + $params{no_link} ? '' : '', + $self->escape($part->partnumber), + $params{no_link} ? '' : '', + ); + return $self->escaped_text($text); +} sub part_picker { my ($self, $name, $value, %params) = @_; - my $name_e = $self->escape($name); + + $value = SL::DB::Manager::Part->find_by(id => $value) if $value && !ref $value; + my $id = delete($params{id}) || $self->name_to_id($name); + my $fat_set_item = delete $params{fat_set_item}; + + my @classes = $params{class} ? ($params{class}) : (); + push @classes, 'part_autocomplete'; + push @classes, 'partpicker_fat_set_item' if $fat_set_item; my $ret = - $self->input_tag($name, (ref $value && $value->can('id') ? $value->id : ''), class => 'part_autocomplete', type => 'hidden') . - $self->input_tag("", delete $params{type}, id => $self->name_to_id("$name_e\_type"), type => 'hidden') . - $self->input_tag("", (ref $value && $value->can('description')) ? $value->description : '', id => $self->name_to_id("$name_e\_name"), %params) . - $self->input_tag("", delete $params{column}, id => $self->name_to_id("$name_e\_column"), type => 'hidden'); + $self->input_tag($name, (ref $value && $value->can('id') ? $value->id : ''), class => "@classes", type => 'hidden', id => $id) . + join('', map { $params{$_} ? $self->input_tag("", delete $params{$_}, id => "${id}_${_}", type => 'hidden') : '' } qw(part_type classification_id unit convertible_unit)) . + $self->input_tag("", ref $value ? $value->displayable_name : '', id => "${id}_name", %params); + + $::request->layout->add_javascripts('autocomplete_part.js'); + $::request->presenter->need_reinit_widgets($id); $self->html_tag('span', $ret, class => 'part_picker'); } +# +# shortcut for article type +# +sub type_abbreviation { + my ($self, $part_type) = @_; + return $::locale->text('Assembly (typeabbreviation)') if $part_type eq 'assembly'; + return $::locale->text('Part (typeabbreviation)') if $part_type eq 'part'; + return $::locale->text('Assortment (typeabbreviation)') if $part_type eq 'assortment'; + return $::locale->text('Service (typeabbreviation)'); +} + +# +# Translations for Abbreviations: +# +# $::locale->text('None (typeabbreviation)') +# $::locale->text('Purchase (typeabbreviation)') +# $::locale->text('Sales (typeabbreviation)') +# $::locale->text('Merchandise (typeabbreviation)') +# $::locale->text('Production (typeabbreviation)') +# +# and for descriptions +# $::locale->text('Purchase') +# $::locale->text('Sales') +# $::locale->text('Merchandise') +# $::locale->text('Production') + +# +# shortcut for article type +# +sub classification_abbreviation { + my ($self, $id) = @_; + SL::DB::Manager::PartClassification->cache_all(); + my $obj = SL::DB::PartClassification->load_cached($id); + $obj && $obj->abbreviation ? t8($obj->abbreviation) : ''; +} + +sub typeclass_abbreviation { + my ($self, $part) = @_; + return '' if !$part || !$part->isa('SL::DB::Part'); + return $self->type_abbreviation($part->part_type).$self->classification_abbreviation($part->classification_id); +} + +# +# shortcut for article type +# +sub separate_abbreviation { + my ($self, $id) = @_; + SL::DB::Manager::PartClassification->cache_all(); + my $obj = SL::DB::PartClassification->load_cached($id); + $obj && $obj->abbreviation && $obj->report_separate ? t8($obj->abbreviation) : ''; +} + +# +# generate selection tag +# +sub select_classification { + my ($self, $name, %attributes) = @_; + $attributes{value_key} = 'id'; + $attributes{title_key} = 'description'; + my $collection = SL::DB::Manager::PartClassification->get_all_sorted(); + $_->description($::locale->text($_->description)) for @{ $collection }; + return $self->select_tag( $name, $collection, %attributes ); +} + 1; __END__ @@ -26,11 +120,15 @@ __END__ =head1 NAME -SL::Presenter::Part - Part lelated presenter stuff +SL::Presenter::Part - Part related presenter stuff =head1 SYNOPSIS -see L + # Create an html link for editing/opening a part/service/assembly + my $object = my $object = SL::DB::Manager::Part->get_first; + my $html = SL::Presenter->get->part($object, display => 'inline'); + +see also L =head1 DESCRIPTION @@ -38,28 +136,184 @@ see L =head1 FUNCTIONS +=over 2 + +=item C + +Returns a rendered version (actually an instance of +L) of the part object C<$object> + +C<%params> can include: + +=over 4 + +=item * display + +Either C (the default) or C. At the moment both +representations are identical and produce the part's name linked +to the corresponding 'edit' action. + +=back + +=back + +=over 2 + +=item C + +Returns the shortcut of the classification + +=back + +=over 2 + +=item C + +Returns the shortcut of the classification if the classifiaction has the separate flag set. + +=back + +=over 2 + +=item C + +Returns a HTML Select Tag with all available Classifications + +C<%params> can include: + +=over 4 + +=item * default + +The Id of the selected item . + +=back + +=back + +=over 2 + +=item C + +All-in-one picker widget for parts. The name will be both id and name +of the resulting hidden C input field (but the ID can be +overwritten with C<$params{id}>). + +An additional dummy input will be generated which is used to find +parts. For a detailed description of its behaviour, see section +C. + +C<$value> can be a parts id or a C instance. + +If C<%params> contains C only parts of this type will be used +for autocompletion. You may comma separate multiple types as in +C. + +If C<%params> contains C only parts with this unit will be used +for autocompletion. You may comma separate multiple units as in +C. + +If C<%params> contains C only parts with a unit +that's convertible to unit will be used for autocompletion. + +Obsolete parts will by default not be displayed for selection. However they are +accepted as default values and can persist during updates. As with other +selectors though, they are not selectable once overridden. + +C will register it's javascript for inclusion in the next header +rendering. If you write a standard controller that only call C once, it +will just work. In case the header is generated in a different render call +(multiple blocks, ajax, old C style controllers) you need to +include C yourself. + +=back + +=head1 PART PICKER SPECIFICATION + +The following list of design goals were applied: + +=over 4 + +=item * + +Parts should not be perceived by the user as distinct inputs of partnumber and +description but as a single object + +=item * + +Easy to use without documentation for novice users + +=item * + +Fast to use with keyboard for experienced users + +=item * + +Possible to use without any keyboard interaction for mouse (or touchscreen) +users + +=item * + +Must not leave the current page in event of ambiguity (cf. current select_item +mechanism) + +=item * + +Should be useable with hand scanners or similar alternative keyboard devices + +=item * + +Should not require a feedback/check loop in the common case + +=item * + +Should not be constrained to exact matches + +=back + +The implementation consists of the following parts which will be referenced later: + =over 4 -=item C +=item 1 + +A hidden input (id input), used to hold the id of the selected part. The only +input that gets submitted + +=item 2 -All-in-one picker widget for parts. The name will be both id and name of the -resulting hidden C input field. An additional dummy input will be generated -which is used to find parts. For a detailed description of it's behaviour, see -section C. +An input (dummy input) containing a description of the currently selected part, +also used by the user to search for parts -C can be an id or C instance. +=item 3 -If C contains C only parts of this type will be used for autocompletion. +A jquery.autocomplete mechanism attached to the dummy field +=item 4 + +A popup layer for both feedback and input of additional data in case of +ambiguity. + +=item 5 + +An internal status of the part picker, indicating whether id input and dummy +input are consistent. After leaving the dummy input the part picker must +place itself in a consistent status. + +=item 6 + +A clickable icon (popup trigger) attached to the dummy input, which triggers the popup layer. =back =head1 BUGS -None yet :) +None atm :) =head1 AUTHOR Sven Schöling Es.schoeling@linet-services.deE +Martin Helmling Emartin.helmling@opendynamic.deE + =cut