]> wagnertech.de Git - mfinanz.git/blob - SL/DB/Helper/RecordLink.pm
date error in mapping
[mfinanz.git] / SL / DB / Helper / RecordLink.pm
1 package SL::DB::Helper::RecordLink;
2
3 use strict;
4 use parent qw(Exporter);
5
6 use Carp qw(croak);
7
8 use SL::MoreCommon qw(listify);
9
10 use constant RECORD_ID            => 'converted_from_record_id';
11 use constant RECORD_TYPE_REF      => 'converted_from_record_type_ref';
12 use constant RECORD_ITEM_ID       => 'converted_from_record_item_id';
13 use constant RECORD_ITEM_TYPE_REF => 'converted_from_record_item_type_ref';
14
15 our @EXPORT_OK = qw(RECORD_ID RECORD_TYPE_REF RECORD_ITEM_ID RECORD_ITEM_TYPE_REF set_record_link_conversions);
16
17 sub link_records {
18   my ($self, $allowed_linked_records, $allowed_linked_record_items) = @_;
19
20   my %allowed_linked_records = map {$_ => 1} @$allowed_linked_records;
21   my %allowed_linked_record_items = map {$_ => 1} @$allowed_linked_record_items;
22
23   return 1 unless my $from_record_ids = $self->{RECORD_ID()};
24   my @from_record_ids = split / /, $from_record_ids;
25
26   my $from_record_type = $self->{RECORD_TYPE_REF()};
27   unless ($allowed_linked_records{$from_record_type}) {
28     croak("Not allowed @{[ RECORD_TYPE_REF ]}: $from_record_type");
29   }
30
31   for my $id (@from_record_ids) {
32     my $from_record = $from_record_type->new(id => $id)->load;
33     $from_record->link_to_record($self);
34   }
35
36   #clear converted_from;
37   delete $self->{$_} for RECORD_ID, RECORD_TYPE_REF;
38
39   for my $item (@{ $self->items_sorted }) {
40     link_record_item($self, $item, \%allowed_linked_record_items);
41   }
42
43   1;
44 }
45
46 sub link_record_item {
47   my ($self, $record_item, $allowed_linked_record_items) = @_;
48
49   return 1 unless my $from_item_id = $record_item->{RECORD_ITEM_ID()};
50
51   my $from_item_type = $record_item->{RECORD_ITEM_TYPE_REF()};
52   unless ($allowed_linked_record_items->{$from_item_type}) {
53     croak("Not allowed @{[ RECORD_ITEM_TYPE_REF() ]}: $from_item_type");
54   }
55
56   $from_item_type->new(id => $from_item_id)->load
57     ->link_to_record($record_item);
58
59   #clear converted_from;
60   delete $record_item->{$_} for RECORD_ITEM_ID, RECORD_ITEM_TYPE_REF;
61 }
62
63
64 sub set_record_link_conversions {
65   my ($record, $from_type, $from_ids, $item_types, $item_ids) = @_;
66
67   return unless listify($from_ids);
68
69   $record->{ RECORD_TYPE_REF() } = $from_type;
70   $record->{ RECORD_ID() } = $from_ids;
71
72   my $idx = 0;
73   my $items = $record->items_sorted;
74
75   $item_ids ||= [];
76   croak "more item ids than items in record" if @$item_ids > @$items;
77
78   for my $idx (0..$#$item_ids) {
79     my $item = $items->[$idx];
80
81     $item->{ RECORD_ITEM_TYPE_REF() } = $item_types->[$idx];
82     $item->{ RECORD_ITEM_ID() }       = $item_ids->[$idx];
83   }
84 }
85
86
87 1;
88
89 __END__
90
91 =encoding utf-8
92
93 =head1 NAME
94
95 SL::DB::Helper::RecordLink - creates record links that are stored in the gived objects
96
97 =head1 SYNOPSIS
98
99     # in the consuming class
100     __PACKAGE__->after_save_hook("link_records_hook");
101
102     sub link_records_hook {
103       my ($self) = @_;
104       SL::DB::Helper::RecordLink::link_records(
105         $self,
106         [ qw(SL::DB::Order) ],        # list of allowed record sources
107         [ qw(SL::DB::OrderItem) ],    # list of allowed record item sources
108       )
109     }
110
111     # set conversion data in record
112     sub prepare_linked_records {
113       my @converted_from_ids      = @{ $::form->{converted_from_oe_ids} };
114       my @converted_from_item_ids = @{ $::form->{converted_from_orderitem_ids} };
115
116       set_record_link_conversion(
117         $self->order,                                     # the record to modify
118         'SL::DB::Order'     => \@converted_from_ids,      # singular or multiple source record ids
119         'SL::DB::OrderItem' => \@converted_from_item_ids  # ids of items, each item will get one id
120       );
121     }
122
123 =head1 DESCRIPTION
124
125 This module implements reusable after save hooks for dealing with record links for records created from other records.
126
127 It reacts to non-rose attributes set in the underlying hashes of the given record:
128
129 =over 4
130
131 =item * C<converted_from_record_id>
132
133 =item * C<converted_from_record_type_ref>
134
135 =item * C<converted_from_record_item_id>
136
137 =item * C<converted_from_record_item_type_ref>
138
139 =back
140
141 If a typeref is given that is not explicitely whitelisted, an error will be thrown.
142
143 The older C<converted_from_oe_ids> etc forms can be converted with TODO
144
145 =head1 FUNCTIONS
146
147 =over 4
148
149 =item * C<set_record_link_conversions> $record, $record_type => \@ids, $item_type => \@item_ids
150
151 Register the given ids in the object to be linked after saving.
152
153 Item ids will be assigned one by one to sorted_items.
154
155 This function can be exported on demand to the calling package.
156
157 =item * C<link_records> $record, \@allowed_record_types, \@allowed_item_types
158
159 Intended as a post-save hook.
160 Evaluates the stored ids from L </set_record_link_conversions>
161 and links the creating objects to the given one.
162
163 =back
164
165 =head1 CONSTANTS
166
167 Aöll of these can be exported on demand if the calling code wants to set or read the markers in a record manually.
168
169 =over 4
170
171 =item * C<RECORD_ID> = C<converted_from_record_id>
172
173 =item * C<RECORD_TYPE_REF> = C<converted_from_record_type_ref>
174
175 =item * C<RECORD_ITEM_ID> = C<converted_from_record_item_id>
176
177 =item * C<RECORD_ITEM_TYPE_REF> = C<converted_from_record_item_type_ref>
178
179 =back
180
181 =head1 BUGS
182
183 None yet. :)
184
185 =head1 AUTHOR
186
187 Sven Schöling $<lt>s.schoeling@googlemail.comE<gt>
188
189 =cut