Revision f63af42d
Von Moritz Bunkus vor mehr als 9 Jahren hinzugefügt
SL/DB/DeliveryOrder.pm | ||
---|---|---|
9 | 9 |
use SL::DB::MetaSetup::DeliveryOrder; |
10 | 10 |
use SL::DB::Manager::DeliveryOrder; |
11 | 11 |
use SL::DB::Helper::AttrHTML; |
12 |
use SL::DB::Helper::AttrSorted; |
|
12 | 13 |
use SL::DB::Helper::FlattenToForm; |
13 | 14 |
use SL::DB::Helper::LinkedRecords; |
14 | 15 |
use SL::DB::Helper::TransNumberGenerator; |
... | ... | |
31 | 32 |
__PACKAGE__->meta->initialize; |
32 | 33 |
|
33 | 34 |
__PACKAGE__->attr_html('notes'); |
35 |
__PACKAGE__->attr_sorted('items'); |
|
34 | 36 |
|
35 | 37 |
__PACKAGE__->before_save('_before_save_set_donumber'); |
36 | 38 |
|
... | ... | |
49 | 51 |
sub items { goto &orderitems; } |
50 | 52 |
sub add_items { goto &add_orderitems; } |
51 | 53 |
|
52 |
sub items_sorted { |
|
53 |
my ($self) = @_; |
|
54 |
|
|
55 |
return [ sort {$a->position <=> $b->position } @{ $self->items } ]; |
|
56 |
} |
|
57 |
|
|
58 | 54 |
sub sales_order { |
59 | 55 |
my $self = shift; |
60 | 56 |
my %params = @_; |
... | ... | |
208 | 204 |
An alias for C<deliver_orer_items> for compatibility with other |
209 | 205 |
sales/purchase models. |
210 | 206 |
|
211 |
=item C<items_sorted> |
|
212 |
|
|
213 |
Returns the delivery order items sorted by their ID (same order they |
|
214 |
appear in the frontend delivery order masks). |
|
215 |
|
|
216 | 207 |
=item C<new_from $source, %params> |
217 | 208 |
|
218 | 209 |
Creates a new C<SL::DB::DeliveryOrder> instance and copies as much |
SL/DB/Helper/AttrSorted.pm | ||
---|---|---|
1 |
package SL::DB::Helper::AttrSorted; |
|
2 |
|
|
3 |
use Carp; |
|
4 |
use List::Util qw(max); |
|
5 |
|
|
6 |
use strict; |
|
7 |
|
|
8 |
use parent qw(Exporter); |
|
9 |
our @EXPORT = qw(attr_sorted); |
|
10 |
|
|
11 |
sub attr_sorted { |
|
12 |
my ($package, @attributes) = @_; |
|
13 |
|
|
14 |
_make_sorted($package, $_) for @attributes; |
|
15 |
} |
|
16 |
|
|
17 |
sub _make_sorted { |
|
18 |
my ($package, $attribute) = @_; |
|
19 |
|
|
20 |
my %params = ref($attribute) eq 'HASH' ? %{ $attribute } : ( unsorted => $attribute ); |
|
21 |
my $unsorted_sub = $params{unsorted}; |
|
22 |
my $sorted_sub = $params{sorted} // $params{unsorted} . '_sorted'; |
|
23 |
my $position_sub = $params{position} // 'position'; |
|
24 |
|
|
25 |
no strict 'refs'; |
|
26 |
|
|
27 |
*{ $package . '::' . $sorted_sub } = sub { |
|
28 |
my ($self) = @_; |
|
29 |
|
|
30 |
croak 'not an accessor' if @_ > 1; |
|
31 |
|
|
32 |
my $next_position = (max map { $_->$position_sub // 0 } @{ $self->$unsorted_sub }) + 1; |
|
33 |
return [ |
|
34 |
map { $_->[1] } |
|
35 |
sort { $a->[0] <=> $b->[0] } |
|
36 |
map { [ $_->$position_sub // ($next_position++), $_ ] } |
|
37 |
@{ $self->$unsorted_sub } |
|
38 |
]; |
|
39 |
}; |
|
40 |
} |
|
41 |
|
|
42 |
1; |
|
43 |
__END__ |
|
44 |
|
|
45 |
=pod |
|
46 |
|
|
47 |
=encoding utf8 |
|
48 |
|
|
49 |
=head1 NAME |
|
50 |
|
|
51 |
SL::DB::Helper::AttrSorted - Attribute helper for sorting to-many |
|
52 |
relationships by a positional attribute |
|
53 |
|
|
54 |
=head1 SYNOPSIS |
|
55 |
|
|
56 |
# In a Rose model: |
|
57 |
use SL::DB::Helper::AttrSorted; |
|
58 |
__PACKAGE__->attr_sorted('items'); |
|
59 |
|
|
60 |
# Use in controller or whereever: |
|
61 |
my $items = @{ $invoice->items_sorted }; |
|
62 |
|
|
63 |
=head1 OVERVIEW |
|
64 |
|
|
65 |
Creates a function that returns a sorted relationship. Requires that |
|
66 |
the linked objects have some kind of positional column. |
|
67 |
|
|
68 |
Items for which no position has been set (e.g. because they haven't |
|
69 |
been saved yet) are sorted last but kept in the order they appear in |
|
70 |
the unsorted list. |
|
71 |
|
|
72 |
=head1 FUNCTIONS |
|
73 |
|
|
74 |
=over 4 |
|
75 |
|
|
76 |
=item C<attr_sorted @attributes> |
|
77 |
|
|
78 |
Package method. Call with the names of the attributes for which the |
|
79 |
helper methods should be created. Each attribute name can be either a |
|
80 |
scalar or a hash reference if you need custom options. |
|
81 |
|
|
82 |
If it's a hash reference then the following keys are supported: |
|
83 |
|
|
84 |
=over 2 |
|
85 |
|
|
86 |
=item * C<unsorted> is the name of the relationship accessor that |
|
87 |
returns the list to be sorted. This is required, and if only a scalar |
|
88 |
is given instead of a hash reference then that scalar value is |
|
89 |
interpreted as C<unsorted>. |
|
90 |
|
|
91 |
=item * C<sorted> is the name of the new function to create. It |
|
92 |
defaults to the unsorted name postfixed with C<_sorted>. |
|
93 |
|
|
94 |
=item * C<position> must be a function name to be called on the |
|
95 |
objects to be sorted. It is supposed to return either C<undef> (no |
|
96 |
position has been set yet) or a numeric value. Defaults to C<position>. |
|
97 |
|
|
98 |
=back |
|
99 |
|
|
100 |
=back |
|
101 |
|
|
102 |
=head1 BUGS |
|
103 |
|
|
104 |
Nothing here yet. |
|
105 |
|
|
106 |
=head1 AUTHOR |
|
107 |
|
|
108 |
Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt> |
|
109 |
|
|
110 |
=cut |
SL/DB/Invoice.pm | ||
---|---|---|
1 |
# This file has been auto-generated only because it didn't exist. |
|
2 |
# Feel free to modify it at will; it will not be overwritten automatically. |
|
3 |
|
|
4 | 1 |
package SL::DB::Invoice; |
5 | 2 |
|
6 | 3 |
use strict; |
... | ... | |
13 | 10 |
use SL::DB::MetaSetup::Invoice; |
14 | 11 |
use SL::DB::Manager::Invoice; |
15 | 12 |
use SL::DB::Helper::AttrHTML; |
13 |
use SL::DB::Helper::AttrSorted; |
|
16 | 14 |
use SL::DB::Helper::FlattenToForm; |
17 | 15 |
use SL::DB::Helper::LinkedRecords; |
18 | 16 |
use SL::DB::Helper::PriceTaxCalculator; |
... | ... | |
60 | 58 |
__PACKAGE__->meta->initialize; |
61 | 59 |
|
62 | 60 |
__PACKAGE__->attr_html('notes'); |
61 |
__PACKAGE__->attr_sorted('items'); |
|
63 | 62 |
|
64 | 63 |
__PACKAGE__->before_save('_before_save_set_invnumber'); |
65 | 64 |
|
... | ... | |
78 | 77 |
sub items { goto &invoiceitems; } |
79 | 78 |
sub add_items { goto &add_invoiceitems; } |
80 | 79 |
|
81 |
sub items_sorted { |
|
82 |
my ($self) = @_; |
|
83 |
|
|
84 |
return [ sort {$a->position <=> $b->position } @{ $self->items } ]; |
|
85 |
} |
|
86 |
|
|
87 | 80 |
sub is_sales { |
88 | 81 |
# For compatibility with Order, DeliveryOrder |
89 | 82 |
croak 'not an accessor' if @_ > 1; |
SL/DB/Order.pm | ||
---|---|---|
10 | 10 |
use SL::DB::MetaSetup::Order; |
11 | 11 |
use SL::DB::Manager::Order; |
12 | 12 |
use SL::DB::Helper::AttrHTML; |
13 |
use SL::DB::Helper::AttrSorted; |
|
13 | 14 |
use SL::DB::Helper::FlattenToForm; |
14 | 15 |
use SL::DB::Helper::LinkedRecords; |
15 | 16 |
use SL::DB::Helper::PriceTaxCalculator; |
... | ... | |
43 | 44 |
__PACKAGE__->meta->initialize; |
44 | 45 |
|
45 | 46 |
__PACKAGE__->attr_html('notes'); |
47 |
__PACKAGE__->attr_sorted('items'); |
|
46 | 48 |
|
47 | 49 |
__PACKAGE__->before_save('_before_save_set_ord_quo_number'); |
48 | 50 |
|
... | ... | |
66 | 68 |
sub items { goto &orderitems; } |
67 | 69 |
sub add_items { goto &add_orderitems; } |
68 | 70 |
|
69 |
sub items_sorted { |
|
70 |
my ($self) = @_; |
|
71 |
|
|
72 |
return [ sort {$a->position <=> $b->position } @{ $self->items } ]; |
|
73 |
} |
|
74 |
|
|
75 | 71 |
sub type { |
76 | 72 |
my $self = shift; |
77 | 73 |
|
SL/DB/PurchaseInvoice.pm | ||
---|---|---|
7 | 7 |
use SL::DB::MetaSetup::PurchaseInvoice; |
8 | 8 |
use SL::DB::Manager::PurchaseInvoice; |
9 | 9 |
use SL::DB::Helper::AttrHTML; |
10 |
use SL::DB::Helper::AttrSorted; |
|
10 | 11 |
use SL::DB::Helper::LinkedRecords; |
11 | 12 |
use SL::Locale::String qw(t8); |
12 | 13 |
|
... | ... | |
44 | 45 |
__PACKAGE__->meta->initialize; |
45 | 46 |
|
46 | 47 |
__PACKAGE__->attr_html('notes'); |
48 |
__PACKAGE__->attr_sorted('items'); |
|
47 | 49 |
|
48 | 50 |
sub items { goto &invoiceitems; } |
49 | 51 |
sub add_items { goto &add_invoiceitems; } |
50 | 52 |
|
51 |
sub items_sorted { |
|
52 |
my ($self) = @_; |
|
53 |
|
|
54 |
return [ sort {$a->position <=> $b->position } @{ $self->items } ]; |
|
55 |
} |
|
56 |
|
|
57 | 53 |
sub is_sales { |
58 | 54 |
# For compatibility with Order, DeliveryOrder |
59 | 55 |
croak 'not an accessor' if @_ > 1; |
Auch abrufbar als: Unified diff
Beleg-Rose-Objekte: items_sorted für nicht gespeicherte Items gefixt
Die bisherigen items_sorted-Routinen verlangen, dass die Positionsspalte
gesetzt ist. Das ist bei noch nicht gespeicherten Belegen oder bei
gerade hinzugefügten Positionen aber noch nicht der Fall.
Diese neuen Positionen werden nun stabil ans Ende sortiert.