2 # An object to handle checkin status
5 package C4::SIP::ILS::Transaction::Checkin;
10 # use POSIX qw(strftime);
12 use C4::SIP::ILS::Transaction;
14 use C4::Circulation qw( AddReturn LostItem );
15 use C4::Items qw( ModItemTransfer );
16 use C4::Reserves qw( ModReserve ModReserveAffect );
17 use Koha::DateUtils qw( dt_from_string );
20 use parent qw(C4::SIP::ILS::Transaction);
25 collection_code => undef,
28 destination_loc => undef,
29 alert_type => undef, # 00,01,02,03,04 or 99
30 hold_patron_id => undef,
31 hold_patron_name => "",
37 my $self = $class->SUPER::new(); # start with an ILS::Transaction object
39 foreach (keys %fields) {
40 $self->{_permitted}->{$_} = $fields{$_}; # overlaying _permitted
43 @{$self}{keys %fields} = values %fields; # copying defaults into object
44 return bless $self, $class;
50 my $return_date = shift;
53 my $checked_in_ok = $account->{checked_in_ok};
54 my $cv_triggers_alert = $account->{cv_triggers_alert};
55 my $holds_block_checkin = $account->{holds_block_checkin};
60 my $barcode = $self->{item}->id;
63 $return_date = substr( $return_date, 0, 4 )
65 . substr( $return_date, 4, 2 )
67 . substr( $return_date, 6, 2 )
69 . substr( $return_date, 12, 2 )
71 . substr( $return_date, 14, 2 )
73 . substr( $return_date, 16, 2 );
74 $return_date = dt_from_string($return_date);
77 my ( $return, $messages, $issue, $borrower );
79 my $item = Koha::Items->find( { barcode => $barcode } );
81 my $human_required = 0;
82 if ( C4::Context->preference("CircConfirmItemParts")
87 $messages->{additional_materials} = 1;
90 my $checkin_blocked_by_holds = $holds_block_checkin && $item->biblio->holds->count;
92 ( $return, $messages, $issue, $borrower ) =
93 AddReturn( $barcode, $branch, undef, $return_date )
94 unless $human_required || $checkin_blocked_by_holds;
96 if ( $checked_in_ok ) {
97 delete $messages->{ItemLocationUpdated};
98 delete $messages->{NotIssued};
99 delete $messages->{LocalUse};
100 $return = 1 unless keys %$messages;
103 # biblionumber, biblioitemnumber, itemnumber
104 # borrowernumber, reservedate, branchcode
105 # cancellationdate, found, reservenotes, priority, timestamp
106 if ($messages->{additional_materials}) {
107 $self->alert_type('99');
109 if( $messages->{DataCorrupted} ) {
110 $self->alert_type('98');
112 if ($messages->{BadBarcode}) {
113 $self->alert_type('99');
115 if ($messages->{withdrawn}) {
116 $self->alert_type('99');
118 if ($messages->{WasLost}) {
119 $self->alert_type('99') if C4::Context->preference("BlockReturnOfLostItems");
121 if ($messages->{Wrongbranch}) {
122 $self->{item}->destination_loc($messages->{Wrongbranch}->{Rightbranch});
123 $self->alert_type('04'); # send to other branch
125 if ($messages->{WrongTransfer}) {
126 $self->{item}->destination_loc($messages->{WrongTransfer});
127 $self->alert_type('04'); # send to other branch
129 if ($messages->{NeedsTransfer}) {
130 $self->{item}->destination_loc($messages->{NeedsTransfer});
131 $self->alert_type('04'); # send to other branch
133 if ($messages->{WasTransfered}) { # set into transit so tell unit
134 $self->{item}->destination_loc($item->homebranch);
135 $self->alert_type('04'); # send to other branch
137 if ($messages->{ResFound} || $checkin_blocked_by_holds ) {
138 if ($checkin_blocked_by_holds) {
139 $self->alert_type('99');
141 } elsif ($branch eq $messages->{ResFound}->{branchcode}) {
142 $self->hold($messages->{ResFound});
143 $self->alert_type('01');
144 ModReserveAffect( $messages->{ResFound}->{itemnumber},
145 $messages->{ResFound}->{borrowernumber}, 0, $messages->{ResFound}->{reserve_id});
148 $self->hold($messages->{ResFound});
149 $self->alert_type('02');
150 ModReserveAffect( $item->itemnumber,
151 $messages->{ResFound}->{borrowernumber}, 1, $messages->{ResFound}->{reserve_id});
152 ModItemTransfer( $item->itemnumber,
154 $messages->{ResFound}->{branchcode},
159 $self->{item}->hold_patron_id( $messages->{ResFound}->{borrowernumber} );
160 $self->{item}->destination_loc( $messages->{ResFound}->{branchcode} );
162 # ignoring messages: NotIssued, WasTransfered
164 if ($cv_triggers_alert) {
165 $self->alert( defined $self->alert_type ); # Overwrites existing alert value, should set to 0 if there is no alert type
168 $self->alert( !$return || defined $self->alert_type );
171 # Set sort bin based on info in the item associated with the issue, and the
172 # mapping from SIP2SortBinMapping
173 $self->sort_bin( _get_sort_bin( $item, $branch ) );
177 return { messages => $messages };
182 unless ($self->{item}) {
183 warn "resensitize(): no item found in object to resensitize";
186 return !$self->{item}->magnetic_media;
191 unless ($self->{patron}) {
192 warn "patron_id(): no patron found in object";
195 return $self->{patron}->id;
200 Takes a Koha::Item object and the return branch branchcode as arguments.
202 Uses the contents of the SIP2SortBinMapping syspref to determine the sort_bin
203 value that should be returned for an item checked in via SIP2.
205 The mapping should be:
207 <branchcode>:<item field>:<comparator>:<item field value>:<sort bin number>
212 CPL:location:eq:OFFICE:2
213 CPL:classmark:<:339.6:3
219 =item * sort_bin = "1" for items at the CPL branch with an itemtype of BOOK
221 =item * sort_bin = "2" for items at the CPL branch with a location of OFFICE
223 =item * sort_bin = "3" for items at the CPL branch with a classmark less than 339.6
227 Returns the ID of the appropriate sort_bin, if there is one, or undef.
233 # We should get an item represented as a hashref here
234 my ( $item, $branch ) = @_;
237 # Get the mapping and split on newlines
238 my $raw_map = C4::Context->preference('SIP2SortBinMapping');
239 return unless $raw_map;
240 my @lines = split /\r\n/, $raw_map;
242 # Iterate over the mapping. The first hit wins.
244 foreach my $line (@lines) {
246 # Split the line into fields
247 my ( $branchcode, $item_property, $comparator, $value, $sort_bin ) =
249 if ( $value =~ s/^\$// ) {
250 $value = $item->$value;
252 # Check the fields against values in the item
253 if ( $branch eq $branchcode ) {
254 my $property = $item->$item_property;
255 if ( ( $comparator eq 'eq' || $comparator eq '=' ) && ( $property eq $value ) ) {
258 if ( ( $comparator eq 'ne' || $comparator eq '!=' ) && ( $property ne $value ) ) {
261 if ( ( $comparator eq '<' ) && ( $property < $value ) ) {
264 if ( ( $comparator eq '>' ) && ( $property > $value ) ) {
267 if ( ( $comparator eq '<=' ) && ( $property <= $value ) ) {
270 if ( ( $comparator eq '>=' ) && ( $property >= $value ) ) {
276 # Return undef if no hits were found