Bug 32950: Fix moving subfield losing values for repeatable fields

Moving one subfield to another was failing for repeatable fields where
the field to be moved doesn't exist in the first instance. When moving
subfields within the same field type (e.g. 020$z to 020$a), existing
subfield values in fields that didn't contain the source subfield were
being overwritten with values from other fields.

This patch fixes the issue by determining which fields actually contain
the source subfield and only updating those corresponding target fields,
preserving existing values in fields that don't have the source subfield.

The fix adds logic to _copy_move_subfield to:
1. Use field_exists() to identify which fields have the source subfield
2. Pass these field numbers to _update_subfield for targeted updates
3. Preserve all existing functionality while fixing the data loss bug

Test plan:
1. Create a MARC modification template to move 020$z to 020$a
2. Create a record with multiple 020 fields:
   - Some with existing $a values
   - Some with $z values to be moved
3. Apply the template
4. Verify existing $a values are preserved
5. Verify $z values are moved to $a only in appropriate fields
6. Verify $z subfields are removed after the move

Signed-off-by: Bernard Scaife <bernard.scaife@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This commit is contained in:
Martin Renvoize 2025-09-23 10:49:15 +01:00 committed by Lucas Gass
parent daa661f86c
commit 346dd2073a
No known key found for this signature in database
GPG Key ID: 60B447398B0D36CA
1 changed files with 22 additions and 2 deletions

View File

@ -671,10 +671,30 @@ sub _copy_move_subfield {
}
_modify_values( { values => \@values, regex => $regex } );
my $dont_erase = $action eq 'copy' ? 1 : 0;
# Find which source fields actually have the subfield to determine target field numbers
my @target_field_numbers;
if ( $fromFieldName eq $toFieldName && @values ) {
# For same-field operations, find fields that have the source subfield
@target_field_numbers =
@{ field_exists( { record => $record, field => $fromFieldName, subfield => $fromSubfieldName } ) };
if (@$field_numbers) {
# If specific field numbers were requested, intersect them with fields that have the subfield
my %requested = map { $_ => 1 } @$field_numbers;
@target_field_numbers = grep { $requested{$_} } @target_field_numbers;
}
}
_update_subfield(
{
record => $record, field => $toFieldName, subfield => $toSubfieldName, values => \@values,
dont_erase => $dont_erase
record => $record,
field => $toFieldName,
subfield => $toSubfieldName,
values => \@values,
dont_erase => $dont_erase,
field_numbers => @target_field_numbers ? \@target_field_numbers : $field_numbers
}
);