X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=SL%2FPresenter%2FPart.pm;h=8f13aeeb9ed4b778c66761f85fbb787b09f60251;hb=d38565357c95d74fb29772d4f8a35d9727623a8b;hp=5ec55503a0d7911c0d3b95dea3d292a3350a7a7a;hpb=862bc8ce30cd40b67d2856ac7f1d11d5e4322f09;p=kivitendo-erp.git
diff --git a/SL/Presenter/Part.pm b/SL/Presenter/Part.pm
index 5ec55503a..8f13aeeb9 100644
--- a/SL/Presenter/Part.pm
+++ b/SL/Presenter/Part.pm
@@ -3,9 +3,11 @@ 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 part);
+our @EXPORT = qw(part_picker part select_classification classification_abbreviation type_abbreviation separate_abbreviation typeclass_abbreviation);
use Carp;
@@ -17,7 +19,7 @@ sub part {
croak "Unknown display type '$params{display}'" unless $params{display} =~ m/^(?:inline|table-cell)$/;
my $text = join '', (
- $params{no_link} ? '' : '',
+ $params{no_link} ? '' : '',
$self->escape($part->partnumber),
$params{no_link} ? '' : '',
);
@@ -28,24 +30,91 @@ sub part_picker {
my ($self, $name, $value, %params) = @_;
$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 $id = $params{id} || $self->name_to_id($name);
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 => "@classes", type => 'hidden', id => $id) .
- join('', map { $params{$_} ? $self->input_tag("", delete $params{$_}, id => "${id}_${_}", type => 'hidden') : '' } qw(part_type unit convertible_unit)) .
+ $self->input_tag($name, (ref $value && $value->can('id') ? $value->id : ''), class => "@classes", type => 'hidden', id => $id,
+ 'data-part-picker-data' => JSON::to_json(\%params),
+ ) .
$self->input_tag("", ref $value ? $value->displayable_name : '', id => "${id}_name", %params);
- $::request->layout->add_javascripts('autocomplete_part.js');
+ $::request->layout->add_javascripts('kivi.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 $classification_type_filter = delete $attributes{type} // [];
+
+ my $collection = SL::DB::Manager::PartClassification->get_all_sorted( where => $classification_type_filter );
+ $_->description($::locale->text($_->description)) for @{ $collection };
+ return $self->select_tag( $name, $collection, %attributes );
+}
+
1;
__END__
@@ -59,7 +128,7 @@ SL::Presenter::Part - Part related presenter stuff
=head1 SYNOPSIS
# Create an html link for editing/opening a part/service/assembly
- my $object = my $object = SL::DB::Manager::Part->get_first;
+ my $object = SL::DB::Manager::Part->get_first;
my $html = SL::Presenter->get->part($object, display => 'inline');
see also L
@@ -93,6 +162,40 @@ to the corresponding 'edit' action.
=over 2
+=item C
+
+Returns the shortcut of the classification
+
+=back
+
+=over 2
+
+=item C
+
+Returns the shortcut of the classification if the classification has the separate flag set.
+
+=back
+
+=over 2
+
+=item C
+
+Returns an 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
@@ -121,10 +224,47 @@ 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
+rendering. If you write a standard controller that only calls 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.
+include C yourself.
+
+On pressing the picker will try to commit the current selection,
+resulting in one of the following events, whose corresponding callbacks can be
+set in C:
+
+=over 4
+
+=item * C
+
+If exactly one element matches the input, the internal id will be set to this
+id, the internal state will be set to C and the C event on the
+picker will be fired. Additionally, if C contains C a
+special event C will be fired which is guaranteed to
+contain a complete JSON representation of the part.
+
+After that the action C will be executed, which defaults to
+clicking a button with id C for backward compatibility reasons.
+
+=item * C
+
+If more than one element matches the input, the internal state will be set to
+undefined.
+
+After that the action C will be executed, which defaults to
+opening a popup dialog for graphical interaction. If C contains
+C an alternative popup will be opened, allowing multiple items to be
+selected. Note however that this requires an additional callback
+C to work.
+
+=item * C
+
+If no element matches the input, the internal state will be set to undefined.
+
+If an action for C exists, it will be called with the picker
+object and current term. The caller can then implement creation of new parts.
+
+=back
=back
@@ -169,6 +309,14 @@ Should not require a feedback/check loop in the common case
Should not be constrained to exact matches
+=item *
+
+Must be atomic
+
+=item *
+
+Action should be overridable
+
=back
The implementation consists of the following parts which will be referenced later:
@@ -214,4 +362,6 @@ None atm :)
Sven Schöling Es.schoeling@linet-services.deE
+Martin Helmling Emartin.helmling@opendynamic.deE
+
=cut