Bug 40287: Fix untranslatable strings in more statistics wizards

This patch makes some updates to the acquisitions, patrons, and catalog
statistics wizards in order to make more information translatable.

To test apply the patch and go to Reports.

- Under "Statistics wizards," test the acquisitions, patrons,
  circulation, and catalog statistics reports:
  - Test setting some or all options in the "Filter column" and running
    the report.
  - At the top of the results there should be a list of the filter
    options you selected and their values.
  - All the filter labels should be correct, and the filter values
    should be in their full/description form rather than in code form
    (e.g. library, item type, collection code, sorting field, etc.)

Sponsored-by: Athens County Public Libraries
Signed-off-by: David Nind <david@davidnind.com>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This commit is contained in:
Owen Leonard 2025-07-17 13:12:34 +00:00 committed by Lucas Gass
parent fdc57489a1
commit 676b220687
No known key found for this signature in database
GPG Key ID: 60B447398B0D36CA
6 changed files with 200 additions and 57 deletions

View File

@ -1,5 +1,9 @@
[% USE raw %]
[% USE Koha %]
[% USE Branches %]
[% USE ItemTypes %]
[% USE KohaDates %]
[% USE AuthorisedValues %]
[% PROCESS 'i18n.inc' %]
[% SET footerjs = 1 %]
[% INCLUDE 'doc-head-open.inc' %]
@ -46,38 +50,51 @@
[% IF ( do_it ) %]
[% FOREACH mainloo IN mainloop %]
[% IF ( mainloo.loopfilter.size ) %]
<p><strong>Filtered on:</strong></p>
[% FOREACH loopfilte IN mainloo.loopfilter %]
<p>
[% SWITCH loopfilte.crit %]
[% CASE '0' %]
<span>Placed on (from)</span>
[% CASE '1' %]
<span>Placed on (to)</span>
[% CASE '2' %]
<span>Received on (from)</span>
[% CASE '3' %]
<span>Received on (to)</span>
[% CASE '4' %]
<span>Vendor</span>
[% CASE '5' %]
<span>Home library</span>
[% CASE '6' %]
<span>Collection</span>
[% CASE '7' %]
<span>Item type</span>
[% CASE '8' %]
<span>Fund</span>
[% CASE '9' %]
<span>Sort1</span>
[% CASE '10' %]
<span>Sort2</span>
[% CASE %]
<span>Unknown filter</span>
[% END %]
: [% loopfilte.filter | html %]
</p>
[% END %]
<h2>Filtered on:</h2>
<ul>
[% FOREACH loopfilte IN mainloo.loopfilter %]
<li>
[% SWITCH loopfilte.crit %]
[% CASE '0' %]
<strong>Placed on (from): </strong>
[% loopfilte.filter | $KohaDates %]
[% CASE '1' %]
<strong>Placed on (to): </strong>
[% loopfilte.filter | $KohaDates %]
[% CASE '2' %]
<strong>Received on (from): </strong>
[% loopfilte.filter | html %]
[% CASE '3' %]
<strong>Received on (to): </strong>
[% loopfilte.filter | html %]
[% CASE '4' %]
<strong>Vendor: </strong>
[% loopfilte.filter | html %]
[% CASE '5' %]
<strong>Home library: </strong>
[% Branches.GetName( loopfilte.filter ) | html %]
[% CASE '6' %]
<strong>Collection: </strong>
[% AuthorisedValues.GetByCode( 'CCODE', loopfilte.filter ) | html %]
[% CASE '7' %]
<strong>Item type: </strong>
[% ItemTypes.GetDescription( loopfilte.filter ) | html %]
[% CASE '8' %]
<strong>Fund: </strong>
[% loopfilte.filter | html %]
[% CASE '9' %]
<strong>Sort1: </strong>
[% loopfilte.filter | html %]
[% CASE '10' %]
<strong>Sort2: </strong>
[% loopfilte.filter | html %]
[% CASE %]
<strong>Unknown filter: </strong>
[% loopfilte.filter | html %]
[% END %]
</li>
[% END %]
</ul>
[% END %]
<div class="page-section">
<table>

View File

@ -2,6 +2,10 @@
[% USE Branches %]
[% USE Koha %]
[% USE Asset %]
[% USE Categories %]
[% USE KohaDates %]
[% USE AuthorisedValues %]
[% USE ExtendedAttributeTypes %]
[% PROCESS 'i18n.inc' %]
[% SET footerjs = 1 %]
[% INCLUDE 'doc-head-open.inc' %]
@ -56,11 +60,75 @@
<h1>Patrons statistics</h1>
[% IF ( do_it ) %]
[% FOREACH mainloo IN mainloop %]
[% IF ( mainloo.loopfilter.size>0 ) %]
<p>Filtered on:</p>
[% FOREACH loopfilte IN mainloo.loopfilter %]
<p> [% loopfilte.crit | html %] = [% loopfilte.filter | html %] </p>
[% END %]
[% IF ( mainloo.loopfilter.size > 0 ) %]
<h2>Filtered on:</h2>
<ul>
[% FOREACH loopfilte IN mainloo.loopfilter %]
<li>
[% SWITCH loopfilte.crit %]
[% CASE 'Cat code' %]
<strong>Patron category:</strong>
[% Categories.GetName( loopfilte.filter ) | html %]
[% CASE 'ZIP/Postal code' %]
<strong>ZIP/Postal code: </strong>
[% loopfilte.filter | html %]
[% CASE 'Branch code' %]
<strong>Library: </strong>
[% Branches.GetName( loopfilte.filter ) | html %]
[% CASE 'Date of birth1' %]
<strong>Date of birth > </strong>
[% loopfilte.filter | html %]
[% CASE 'Date of birth2' %]
<strong>Date of birth < </strong>
[% loopfilte.filter | html %]
[% CASE 'Sex' %]
<strong>Gender: </strong>
[% SWITCH ( loopfilte.filter ) %]
[% CASE 'F' %]
<span>Female</span>
[% CASE 'M' %]
<span>Male</span>
[% CASE 'O' %]
<span>Other</span>
[% CASE %]
<span>None specified</span>
[% END %]
[% CASE 'Sort1' %]
<strong>Patron sort1:</strong> [% AuthorisedValues.GetByCode('Bsort1', loopfilte.filter ) | html %]
[% CASE 'Sort2' %]
<strong>Patron sort2:</strong> [% AuthorisedValues.GetByCode('Bsort2', loopfilte.filter ) | html %]
[% CASE 'Status' %]
<strong>Status: </strong>
[% SWITCH loopfilte.filter %]
[% CASE 'debarred' %]
<span>Restricted</span>
[% CASE 'gonenoaddress' %]
<span>Gone no address</span>
[% CASE 'lost' %]
<span>Lost card</span>
[% CASE %]
[% loopfilte.filter | html %]
[% END %]
[% CASE 'Activity' %]
<strong>Activity: </strong>
[% SWITCH loopfilte.filter %]
[% CASE 'active' %]
<span>Active</span>
[% CASE 'nonactive' %]
<span>Inactive</span>
[% CASE %]
[% loopfilte.filter | html %]
[% END %]
[% CASE "PA_CLASS" %]
<strong>[% loopfilte.label | html %]:</strong>
[% loopfilte.filter | html %]
[% CASE %]
<strong>[% loopfilte.crit | html %]: </strong>
[% loopfilte.filter | html %]
[% END %]
</li>
[% END %]
</ul>
[% END %]
<div class="page-section">
<table>
@ -227,7 +295,7 @@
<select id="sort1" name="Filter">
<option value="" />
[% FOREACH SORT1_LOO IN SORT1_LOOP %]
<option value="[% SORT1_LOO.authorized_value | html %]">[% SORT1_LOO.lib | html %]</option>
<option value="[% SORT1_LOO.authorised_value | html %]">[% SORT1_LOO.lib | html %]</option>
[% END %]
</select>
</td>
@ -244,7 +312,7 @@
<select id="sort2" name="Filter">
<option value="" />
[% FOREACH SORT2_LOO IN SORT2_LOOP %]
<option value="[% SORT2_LOO.value | html %]">[% SORT2_LOO.value | html %]</option>
<option value="[% SORT2_LOO.value | html %]">[% AuthorisedValues.GetByCode('Bsort2', SORT2_LOO.value ) | html %]</option>
[% END %]
</select>
</td>

View File

@ -1,6 +1,8 @@
[% USE raw %]
[% USE Koha %]
[% USE Branches %]
[% USE ItemTypes %]
[% USE AuthorisedValues %]
[% PROCESS 'i18n.inc' %]
[% SET footerjs = 1 %]
[% INCLUDE 'doc-head-open.inc' %]
@ -46,12 +48,52 @@
<h1>Catalog statistics</h1>
[% IF ( do_it ) %]
[% FOREACH mainloo IN mainloop %]
[% IF ( mainloo.loopfilter ) %]
<p>Filtered on:</p>
<h2>Filtered on:</h2>
<ul>
[% FOREACH loopfilte IN mainloo.loopfilter %]
<p>[% loopfilte.crit | html %] =[% loopfilte.filter | html %]</p>
<li>
[% SWITCH loopfilte.crit %]
[% CASE "Item CallNumber From" %]
<strong>Item call number from:</strong> [% loopfilte.filter | html %]
[% CASE "Item CallNumber To" %]
<strong>Item call number to:</strong> [% loopfilte.filter | html %]
[% CASE "Item type" %]
<strong>Item type:</strong> [% ItemTypes.GetDescription( loopfilte.filter ) | html %]
[% CASE "Publisher" %]
<strong>Publisher:</strong> [% loopfilte.filter | html %]
[% CASE "Publication year From" %]
<strong>Publication year from:</strong> [% loopfilte.filter | html %]
[% CASE "Publication year To" %]
<strong>Publication year to:</strong> [% loopfilte.filter | html %]
[% CASE "Library" %]
<strong>Library:</strong> [% Branches.GetName( loopfilte.filter ) | html %]
[% CASE "Shelving Location" %]
<strong>Location:</strong> [% AuthorisedValues.GetByCode( 'LOC', loopfilte.filter ) | html %]
[% CASE "Collection Code" %]
<strong>Collection:</strong> [% AuthorisedValues.GetByCode( 'CCODE', loopfilte.filter ) | html %]
[% CASE "Status" %]
<strong>Not for loan:</strong> [% AuthorisedValues.GetByCode( 'NOT_LOAN', loopfilte.filter ) | html %]
[% CASE "Materials" %]
<strong>Materials specified:</strong> [% loopfilte.filter | html %]
[% CASE "Barcode (not like)" %]
<strong>Barcode (not like):</strong> [% loopfilte.filter | html %]
[% CASE "Barcode (like)" %]
<strong>Barcode (like):</strong> [% loopfilte.filter | html %]
[% CASE "Date acquired (item) from" %]
<strong>Date acquired (item) from:</strong> [% loopfilte.filter | html %]
[% CASE "Date acquired (item) to" %]
<strong>Date acquired (item) to:</strong> [% loopfilte.filter | html %]
[% CASE "Date deleted (item) from" %]
<strong>Date deleted (item) from:</strong> [% loopfilte.filter | html %]
[% CASE "Date deleted (item) to" %]
<strong>Date deleted (item) to:</strong> [% loopfilte.filter | html %]
[% CASE %]
<strong>[% loopfilte.crit | html %]:</strong>
[% loopfilte.filter | html %]
[% END %]
</li>
[% END %]
[% END %]
</ul>
<div class="page-section">
<table id="catalogue_stats">

View File

@ -3,7 +3,9 @@
[% USE Branches %]
[% USE Categories %]
[% USE ItemTypes %]
[% USE KohaDates %]
[% USE AuthorisedValues %]
[% USE ExtendedAttributeTypes %]
[% PROCESS 'i18n.inc' %]
[% SET footerjs = 1 %]
[% INCLUDE 'doc-head-open.inc' %]
@ -55,7 +57,7 @@
[% IF ( do_it ) %]
[% FOREACH mainloo IN mainloop %]
[% IF ( mainloo.loopfilter ) %]
<p>Filtered on:</p>
<h2>Filtered on:</h2>
<ul>
[% FOREACH loopfilte IN mainloo.loopfilter %]
[% SET li_class = '' %]
@ -127,8 +129,11 @@
[% CASE "4" %]
<span>Hour</span>
[% END %]
[% CASE "PA_CLASS" %]
<strong>[% loopfilte.label | html %]:</strong>
[% loopfilte.filter | html %]
[% CASE %]
[% loopfilte.crit | html %]:
<strong>[% loopfilte.crit | html %]:</strong>
[% loopfilte.filter | html %]
[% END %]
</li>

View File

@ -193,22 +193,25 @@ sub calculate {
foreach my $i ( 0 .. scalar @$filters ) {
my %cell;
if ( @$filters[$i] ) {
if ( $i == 0 ) { $cell{crit} = "Cat code"; $cell{filter} = @$filters[$i]; }
elsif ( $i == 1 ) { $cell{crit} = "ZIP/Postal code"; $cell{filter} = @$filters[$i]; }
elsif ( $i == 2 ) { $cell{crit} = "Branch code"; $cell{filter} = @$filters[$i]; }
elsif ( $i == 3 || $i == 4 ) { $cell{crit} = "Date of birth"; $cell{filter} = @$filters[$i]; }
elsif ( $i == 5 ) { $cell{crit} = "Sex"; $cell{filter} = @$filters[$i]; }
elsif ( $i == 6 ) { $cell{crit} = "Sort1"; $cell{filter} = @$filters[$i]; }
elsif ( $i == 7 ) { $cell{crit} = "Sort2"; $cell{filter} = @$filters[$i]; }
else { $cell{crit} = "Unknown"; }
if ( $i == 0 ) { $cell{crit} = "Cat code"; $cell{filter} = @$filters[$i]; }
elsif ( $i == 1 ) { $cell{crit} = "ZIP/Postal code"; $cell{filter} = @$filters[$i]; }
elsif ( $i == 2 ) { $cell{crit} = "Branch code"; $cell{filter} = @$filters[$i]; }
elsif ( $i == 3 ) { $cell{crit} = "Date of birth1"; $cell{filter} = @$filters[$i]; }
elsif ( $i == 4 ) { $cell{crit} = "Date of birth2"; $cell{filter} = @$filters[$i]; }
elsif ( $i == 5 ) { $cell{crit} = "Sex"; $cell{filter} = @$filters[$i]; }
elsif ( $i == 6 ) { $cell{crit} = "Sort1"; $cell{filter} = @$filters[$i]; }
elsif ( $i == 7 ) { $cell{crit} = "Sort2"; $cell{filter} = @$filters[$i]; }
else { $cell{crit} = "Unknown"; }
push @loopfilter, \%cell;
}
}
foreach my $type ( keys %$attr_filters ) {
if ( $attr_filters->{$type} ) {
my $patron_attribute_type = Koha::Patron::Attribute::Types->find($type);
push @loopfilter, {
crit => "Attribute $type",
crit => "PA_CLASS",
label => $patron_attribute_type->description,
filter => $attr_filters->{$type}
};
}

View File

@ -230,10 +230,18 @@ sub calculate {
push @loopfilter, \%cell;
}
foreach ( keys %$attribute_filters ) {
next unless $attribute_filters->{$_};
push @loopfilter, { crit => "$_ =", filter => $attribute_filters->{$_} };
foreach my $type ( keys %$attribute_filters ) {
if ( $attribute_filters->{$type} ) {
my $patron_attribute_type = Koha::Patron::Attribute::Types->find($type);
push @loopfilter, {
crit => "PA_CLASS",
label => $patron_attribute_type->description,
filter => $attribute_filters->{$type}
};
}
}
push @loopfilter, { crit => "Event", filter => $type };
push @loopfilter, { crit => "Display by", filter => $dsp } if ($dsp);
push @loopfilter, { crit => "Select Day", filter => $daysel } if ($daysel);