View | Details | Raw Unified | Return to bug 11023
Collapse All | Expand All

(-)a/C4/Items.pm (-1 / +95 lines)
Lines 35-40 use DateTime::Format::MySQL; Link Here
35
use Data::Dumper; # used as part of logging item record changes, not just for
35
use Data::Dumper; # used as part of logging item record changes, not just for
36
                  # debugging; so please don't remove this
36
                  # debugging; so please don't remove this
37
use Koha::DateUtils qw/dt_from_string/;
37
use Koha::DateUtils qw/dt_from_string/;
38
use Koha::Database;
38
39
39
use Koha::Database;
40
use Koha::Database;
40
41
Lines 470-475 sub _build_default_values_for_mod_marc { Link Here
470
        location                 => undef,
471
        location                 => undef,
471
        permanent_location       => undef,
472
        permanent_location       => undef,
472
        materials                => undef,
473
        materials                => undef,
474
        new                      => undef,
473
        notforloan               => 0,
475
        notforloan               => 0,
474
        # paidfor => undef, # commented, see bug 12817
476
        # paidfor => undef, # commented, see bug 12817
475
        price                    => undef,
477
        price                    => undef,
Lines 2164-2170 sub _koha_new_item { Link Here
2164
            enumchron           = ?,
2166
            enumchron           = ?,
2165
            more_subfields_xml  = ?,
2167
            more_subfields_xml  = ?,
2166
            copynumber          = ?,
2168
            copynumber          = ?,
2167
            stocknumber         = ?
2169
            stocknumber         = ?,
2170
            new                 = ?
2168
          ";
2171
          ";
2169
    my $sth = $dbh->prepare($query);
2172
    my $sth = $dbh->prepare($query);
2170
    my $today = C4::Dates->today('iso');
2173
    my $today = C4::Dates->today('iso');
Lines 2207-2212 sub _koha_new_item { Link Here
2207
            $item->{'more_subfields_xml'},
2210
            $item->{'more_subfields_xml'},
2208
            $item->{'copynumber'},
2211
            $item->{'copynumber'},
2209
            $item->{'stocknumber'},
2212
            $item->{'stocknumber'},
2213
            $item->{'new'},
2210
    );
2214
    );
2211
2215
2212
    my $itemnumber;
2216
    my $itemnumber;
Lines 3056-3059 sub PrepareItemrecordDisplay { Link Here
3056
    };
3060
    };
3057
}
3061
}
3058
3062
3063
=head2 columns
3064
3065
  my @columns = C4::Items::columns();
3066
3067
Returns an array of items' table columns on success,
3068
and an empty array on failure.
3069
3070
=cut
3071
3072
sub columns {
3073
    my $rs = Koha::Database->new->schema->resultset('Item');
3074
    return $rs->result_source->columns;
3075
}
3076
3077
=head2 biblioitems_columns
3078
3079
  my @columns = C4::Items::biblioitems_columns();
3080
3081
Returns an array of biblioitems' table columns on success,
3082
and an empty array on failure.
3083
3084
=cut
3085
3086
sub biblioitems_columns {
3087
    my $rs = Koha::Database->new->schema->resultset('Biblioitem');
3088
    return $rs->result_source->columns;
3089
}
3090
3091
sub ToggleNewStatus {
3092
    my ( $params ) = @_;
3093
    my @rules = @{ $params->{rules} };
3094
    my $report_only = $params->{report_only};
3095
3096
    my $dbh = C4::Context->dbh;
3097
    my @errors;
3098
    my @item_columns = map { "items.$_" } C4::Items::columns;
3099
    my @biblioitem_columns = map { "biblioitems.$_" } C4::Items::biblioitems_columns;
3100
    my $report;
3101
    for my $rule ( @rules ) {
3102
        my $age = $rule->{age};
3103
        my $conditions = $rule->{conditions};
3104
        my $substitutions = $rule->{substitutions};
3105
        my @params;
3106
3107
        my $query = q|
3108
            SELECT items.biblionumber, items.itemnumber
3109
            FROM items
3110
            LEFT JOIN biblioitems ON biblioitems.biblionumber = items.biblionumber
3111
            WHERE 1
3112
        |;
3113
        for my $condition ( @$conditions ) {
3114
            if (
3115
                 grep {/^$condition->{field}$/} @item_columns
3116
              or grep {/^$condition->{field}$/} @biblioitem_columns
3117
            ) {
3118
                if ( $condition->{value} =~ /\|/ ) {
3119
                    my @values = split /\|/, $condition->{value};
3120
                    $query .= qq| AND $condition->{field} IN (|
3121
                        . join( ',', ('?') x scalar @values )
3122
                        . q|)|;
3123
                    push @params, @values;
3124
                } else {
3125
                    $query .= qq| AND $condition->{field} = ?|;
3126
                    push @params, $condition->{value};
3127
                }
3128
            }
3129
        }
3130
        if ( defined $age ) {
3131
            $query .= q| AND TO_DAYS(NOW()) - TO_DAYS(dateaccessioned) >= ? |;
3132
            push @params, $age;
3133
        }
3134
        my $sth = $dbh->prepare($query);
3135
        $sth->execute( @params );
3136
        while ( my $values = $sth->fetchrow_hashref ) {
3137
            my $biblionumber = $values->{biblionumber};
3138
            my $itemnumber = $values->{itemnumber};
3139
            my $item = C4::Items::GetItem( $itemnumber );
3140
            for my $substitution ( @$substitutions ) {
3141
                next unless $substitution->{field};
3142
                C4::Items::ModItem( {$substitution->{field} => $substitution->{value}}, $biblionumber, $itemnumber )
3143
                    unless $report_only;
3144
                push @{ $report->{$itemnumber} }, $substitution;
3145
            }
3146
        }
3147
    }
3148
3149
    return $report;
3150
}
3151
3152
3059
1;
3153
1;
(-)a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css (+29 lines)
Lines 2764-2766 span.onsite_checkout { Link Here
2764
    border-radius: 4px;
2764
    border-radius: 4px;
2765
    border : 1px solid #FFF2CE;
2765
    border : 1px solid #FFF2CE;
2766
}
2766
}
2767
2768
/* Tools > automatic_item_modification_by_age */
2769
div.rules {
2770
    display: block;
2771
}
2772
div#new_rule, div.rule {
2773
    background-color: #F4F8F9;
2774
    border: 2px solid #B9D8D9;
2775
    border-radius: 5px;
2776
    margin: .3em;
2777
    padding: .3em;
2778
}
2779
2780
div.duration, div.blocks {
2781
    border: 2px solid #B9D8D9;
2782
    border-radius: 5px 5px 5px 5px;
2783
    margin: .3em;
2784
    padding: 0 .3em .3em .3em;
2785
}
2786
2787
div.duration h5, div.blocks h5 {
2788
    padding-bottom: 4px;
2789
    padding-left: 0.2em;
2790
    background-color: #E6F0F2;
2791
    border-radius: 1px;
2792
}
2793
div.duration span, div.blocks div {
2794
    display:block;
2795
}
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/help/tools/automatic_item_modification_by_age.tt (+45 lines)
Line 0 Link Here
1
[% INCLUDE 'help-top.inc' %]
2
<h1>Automatic item modifications by age configuration</h1>
3
4
<p>This configuration page allows to configure the rules for the automatic item modifications by age cronjob script.</p>
5
6
<p>Libraries can manage the 'new' status for items. With this script, it will be possible to:<p>
7
<ul>
8
  <li>know easily what are the new items in the catalogue.</li>
9
  <li>display an icon in the search results for new items.</li>
10
  <li>configure issuing rules depending the 'new' status.</li>
11
  <li>get a RSS/Atom feeds on these new items.</li>
12
</ul>
13
14
<h3>How to work the configuration page?</h3>
15
<p>There are 3 values to define:</p>
16
<h4>The duration</h4>
17
<p>This value corresponds to the duration an item is considered as new.</p>
18
<h4>The conditions</h4>
19
<p>Conditions should be defined if you want to test some values before to substitute fields in the items.</p>
20
<p>They are cumulatives but you can separate with a pipe '|' for a field with several values.</p>
21
<h4>The substitutions</h4>
22
<p>Substitutions are changes to apply to the matching items.</p>
23
<p>At least one substitution must be defined, else there is no sense to launch the script.</p>
24
<p>If the value is an empty string, the field will be deleted.</p>
25
<h3>Examples</h3>
26
<p>You want to remove the items.new value for items created 10 days ago:</p>
27
<ul>
28
  <li>Duration: 10 days</li>
29
  <li>No condition</li>
30
  <li>Substitution: items.new = '' (no value in the input)</li>
31
</ul>
32
33
<p>You want to change the items.ccode=1 to items.ccode=2 for items created 7 days ago.
34
<ul>
35
  <li>Duration: 7 days</li>
36
  <li>Condition: items.ccode = 1</li>
37
  <li>Substitution: items.ccode = 2</li>
38
</ul>
39
40
<h3>How to execute the cronjob script?</h3>
41
<p>The cronjob script is misc/cronjobs/automatic_item_modification_by_age.pl.</p>
42
<p>Try the -h parameter in order to see the help.</p>
43
<p>Without any parameter, the script will be launched in a dry-run mode. If the -c (or --confirm) flag is given, the script will apply the changes.</p>
44
45
[% INCLUDE 'help-bottom.inc' %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/automatic_item_modification_by_age.tt (+294 lines)
Line 0 Link Here
1
[% INCLUDE 'doc-head-open.inc' %]
2
<title>Koha &rsaquo; Tools &rsaquo; Automatic item modifications by age</title>
3
[% INCLUDE 'doc-head-close.inc' %]
4
<script type="text/javascript">//<![CDATA[
5
  function clear_inputs(node, new_node) {
6
    var selects = $(node).find("select");
7
    $(selects).each(function(i) {
8
      var select = this;
9
      $(new_node).find("select").eq(i).val($(select).val());
10
    });
11
    var inputs = $(node).find("input");
12
    $(inputs).each(function(i) {
13
      var input = this;
14
      $(new_node).find("input").eq(i).val($(input).val());
15
    });
16
  }
17
18
  function remove_block_action( link ) {
19
    var blocks = $(link).parent().parent();
20
    if( $(blocks).find(".block").length > 2 ) {
21
      $(blocks).find("a.remove_block").show();
22
    } else {
23
      $(blocks).find("a.remove_block").hide();
24
    }
25
    $(link).parent().remove();
26
  }
27
28
  function remove_rule_action( link ) {
29
    if( $("#rules").find("div.rule").length < 2 ) {
30
        $("#rules").hide();
31
        $("#norules").show();
32
    }
33
    $(link).parent().remove();
34
  }
35
36
  function clone_block(block) {
37
    var new_block = $(block).clone(1);
38
    clear_inputs(block, new_block);
39
    $(new_block).find('a.remove_block').show();
40
    var blocks = $(block).parent();
41
    $(blocks).append(new_block);
42
    $(blocks).find('a.remove_block').click(function(){
43
      remove_block_action($(this));
44
    }).show();
45
  }
46
47
  $(document).ready(function() {
48
    $("#new_rule a.remove_rule").hide();
49
    $("#new_rule a.remove_block").hide();
50
    $("#rules a.remove_block").click(function(){
51
      remove_block_action($(this));
52
    });
53
    $("#rules a.remove_rule").click(function(){
54
      remove_rule_action($(this));
55
    });
56
57
    var unique_id = $("div.rule").length + 1;
58
    $("a.add_rule").click(function(){
59
      var rule = $("#new_rule");
60
      var new_rule = $(rule).clone(1);
61
      $(new_rule).removeAttr('id');
62
      $(new_rule).attr('class', 'rule');
63
      clear_inputs(rule, new_rule);
64
      $(new_rule).find("select[name='condition_field']").attr('name', 'condition_field_' + unique_id);
65
      $(new_rule).find("select[name='substitution_field']").attr('name', 'substitution_field_' + unique_id);
66
      $(new_rule).find("input[name='condition_value']").attr('name', 'condition_value_' + unique_id);
67
      $(new_rule).find("input[name='substitution_value']").attr('name', 'substitution_value_' + unique_id);
68
      $(new_rule).find("input[name='age']").attr('name', 'age_' + unique_id);
69
      $(new_rule).find("input[name='unique_id']").val(unique_id);
70
71
      $("#rules").append(new_rule);
72
73
      if( $("#rules").find("div.rule").length > 0 ) {
74
          $("#rules").show();
75
          $("#norules").hide();
76
      }
77
      if( $("#rules").find(".conditions > .condition").length > 1 ) {
78
79
      }
80
      if( $("#rules").find(".conditions > .condition").length > 1 ) {
81
82
      }
83
      $(new_rule).find('a.remove_rule').click(function(){
84
        remove_rule_action( $(this) );
85
      }).show();
86
      $(new_rule).find('a.add_rule').remove();
87
      unique_id++;
88
    });
89
90
    $("a.add_block").click(function(){
91
      clone_block( $(this).parent() );
92
    });
93
94
    if( $("#rules").find("div.rule").length < 1 ) {
95
        $("#rules").hide();
96
        $("#norules").show();
97
    }
98
99
    $("#rules .rule .blocks").each(function(){
100
      if ( $(this).find(".block").length == 1 ) {
101
        $(this).find("a.remove_block").hide();
102
      }
103
    });
104
105
    [% IF op == 'edit_form' %]
106
      [% IF rules.size > 0 %]
107
        $("#norules").hide();
108
      [% ELSE %]
109
        $("#rules").show();
110
      [% END %]
111
    [% END %]
112
  });
113
//]]>
114
</script>
115
</head>
116
<body id="tools_automatic_item_modification_by_age" class="tools">
117
[% INCLUDE 'header.inc' %]
118
[% INCLUDE 'cat-search.inc' %]
119
<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/tools/tools-home.pl">Tools</a> &rsaquo; <a href="/cgi-bin/koha/tools/automatic_item_modification_by_age.pl">Automatic item modifications by age</a></div>
120
121
<div id="doc3" class="yui-t2">
122
  <div id="bd">
123
    <div id="yui-main">
124
      <div class="yui-b">
125
        <h3>Automatic item modifications by age</h3>
126
        <div id="toolbar" class="btn-toolbar">
127
          <a class="btn btn-small" id="newentry" href="/cgi-bin/koha/tools/automatic_item_modification_by_age.pl?op=edit_form"><i class="icon-plus"></i> Edit</a>
128
        </div>
129
        [% FOR message IN messages %]
130
          [% IF message.type == "error" %]
131
            <div class="dialog error">
132
          [% END %]
133
          [% IF message.code == "unable_to_load_configuration" %]
134
            An error occurs: Unable to load the configuration.
135
          [% END %]
136
          </div>
137
        [% END %]
138
139
        [% IF op == 'edit_form' %]
140
          <form method="post" action="/cgi-bin/koha/tools/automatic_item_modification_by_age.pl">
141
            <div id="edit_rules">
142
              <h4>List of rules</h4>
143
                <div id="rules">
144
                [% FOR rule IN rules %]
145
                  [% SET id = loop.count %]
146
                  <div class="rule">
147
                    <input type="hidden" name="unique_id" value="[% loop.count %]" /> <!-- FIXME on update, the unique_id should be filled -->
148
                    <div class="age">
149
                      <h5>Age</h5>
150
                      <input type="number" value="[% rule.age %]" name="age_[% id %]" /> days
151
                    </div>
152
                    <div class="blocks">
153
                      <h5>Conditions</h5>
154
                      [% FOR condition IN rule.conditions %]
155
                        <div class="block">
156
                          <select name="condition_field_[% id %]">
157
                            <option value="">Choose a field name</option>
158
                            [% FOR field IN condition_fields %]
159
                              [% IF condition.field == field %]
160
                                <option value="[% field %]" selected="selected">[% field %]</option>
161
                              [% ELSE %]
162
                                <option value="[% field %]">[% field %]</option>
163
                              [% END %]
164
                            [% END %]
165
                          </select>
166
                          =
167
                          <input type="text" value="[% condition.value %]" name="condition_value_[% id%]" />
168
                          <a class="add_block" style="cursor:pointer"><i class="icon-plus"></i></a>
169
                          <a class="remove_block" style="cursor:pointer"><i class="icon-remove"></i></a>
170
                        </div>
171
                      [% END %]
172
                    </div>
173
                    <div class="blocks">
174
                      <h5>Substitutions</h5>
175
                      [% FOR substitution IN rule.substitutions %]
176
                        <div class="block">
177
                          <select name="substitution_field_[% id %]">
178
                            <option value="">Choose a field name</option>
179
                            [% FOR field IN substitution_fields %]
180
                              [% IF substitution.field == field %]
181
                                <option value="[% field %]" selected="selected">[% field %]</option>
182
                              [% ELSE %]
183
                                <option value="[% field %]">[% field %]</option>
184
                              [% END %]
185
                            [% END %]
186
                          </select>
187
                          =
188
                          <input type="text" value="[% substitution.value %]" name="substitution_value_[% id %]" />
189
                          <a class="add_block" style="cursor:pointer"><i class="icon-plus"></i></a>
190
                          <a class="remove_block" style="cursor:pointer"><i class="icon-remove"></i></a>
191
                        </div>
192
                      [% END %]
193
                    </div>
194
                    <a class="remove_rule" style="cursor:pointer">Remove this rule</a>
195
                  </div>
196
                [% END %]
197
                </div>
198
                <div id="norules">
199
                  There is no rule defined.
200
                </div>
201
              <fieldset class="action">
202
                <input type="hidden" name="op" value="update" />
203
                <a class="cancel" href="/cgi-bin/koha/tools/automatic_item_modification_by_age.pl">Cancel</a>
204
                <input type="submit" value="Submit theses rules" />
205
              </fieldset>
206
            </div>
207
          </form>
208
          <h4>Add a new rule</h4>
209
          <div id="new_rule">
210
            <input type="hidden" name="unique_id" />
211
            <div class="age">
212
              <h5>Age</h5>
213
              <input type="number" value="" name="age" /> days
214
            </div>
215
            <div class="blocks">
216
              <h5>Conditions</h5>
217
              <div class="block">
218
                <select name="condition_field">
219
                  <option value="">Choose a field name</option>
220
                  [% FOR field IN condition_fields %]
221
                    <option value="[% field %]">[% field %]</option>
222
                  [% END %]
223
                </select>
224
                =
225
                <input type="text" value="" name="condition_value" />
226
                <a class="add_block" style="cursor:pointer"><i class="icon-plus"></i></a>
227
                <a class="remove_block" style="cursor:pointer"><i class="icon-remove"></i></a>
228
              </div>
229
            </div>
230
            <div class="blocks">
231
              <h5>Substitutions</h5>
232
              <div class="block">
233
                <select name="substitution_field">
234
                  <option value="">Choose a field name</option>
235
                  [% FOR field IN substitution_fields %]
236
                    <option value="[% field %]">[% field %]</option>
237
                  [% END %]
238
                </select>
239
                =
240
                <input type="text" value="" name="substitution_value" />
241
                <a class="add_block" style="cursor:pointer"><i class="icon-plus"></i></a>
242
                <a class="remove_block" style="cursor:pointer"><i class="icon-remove"></i></a>
243
              </div>
244
            </div>
245
          <a class="add_rule" style="cursor:pointer">Add this rule</a>
246
          <a class="remove_rule" style="cursor:pointer">Remove this rule</a>
247
          </div>
248
        [% ELSIF rules and op == 'show' %]
249
          <div id="rules">
250
            <h4>List of rules</h4>
251
            [% FOR rule IN rules %]
252
              <div class="rule">
253
                <div class="age">
254
                  <h5>Age</h5>
255
                  [% IF rule.age.defined and rule.age.length > 0 %]
256
                    [% rule.age %] days
257
                  [% ELSE %]
258
                    There is no age for this rule.
259
                  [% END %]
260
                </div>
261
                <div class="blocks">
262
                  <h5>Conditions</h5>
263
                  [% FOR condition IN rule.conditions %]
264
                    [% IF condition.field %]
265
                      <div class="block">
266
                        [% condition.field %] = [% condition.value %]
267
                      </div>
268
                    [% ELSE %]
269
                      There is no condition for this rule.
270
                    [% END %]
271
                  [% END %]
272
                </div>
273
                <div class="blocks">
274
                  <h5>Substitutions</h5>
275
                  [% FOR substitution IN rule.substitutions %]
276
                    <div class="block">
277
                      [% substitution.field %] = [% substitution.value %]
278
                    </div>
279
                  [% END %]
280
                </div>
281
              </div>
282
            [% END %]
283
          </div>
284
        [% ELSE %]
285
          There is no rule defined. Please click on the edit button.
286
        [% END %]
287
288
      </div>
289
    </div>
290
  <div class="yui-b noprint">
291
    [% INCLUDE 'tools-menu.inc' %]
292
  </div>
293
</div>
294
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/tools-home.tt (+5 lines)
Lines 127-132 Link Here
127
      <dd>Delete a batch of records (bibliographic or authority)</dd>
127
      <dd>Delete a batch of records (bibliographic or authority)</dd>
128
    [% END %]
128
    [% END %]
129
129
130
    [% IF ( CAN_user_tools_items_batchmod ) %]
131
      <dt><a href="/cgi-bin/koha/tools/automatic_item_modification_by_age.pl">Automatic item modifications by age</a></dt>
132
      <dd>Define rules to modify items by age</dd>
133
    [% END %]
134
130
    [% IF ( CAN_user_tools_export_catalog ) %]
135
    [% IF ( CAN_user_tools_export_catalog ) %]
131
    <dt><a href="/cgi-bin/koha/tools/export.pl">Export data</a></dt>
136
    <dt><a href="/cgi-bin/koha/tools/export.pl">Export data</a></dt>
132
    <dd>Export bibliographic, holdings, and authority records</dd>
137
    <dd>Export bibliographic, holdings, and authority records</dd>
(-)a/misc/cronjobs/automatic_item_modification_by_age.pl (+106 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
use Modern::Perl;
4
5
use Getopt::Long;
6
use Pod::Usage;
7
use JSON;
8
9
use C4::Context;
10
use C4::Items;
11
12
# Getting options
13
my ( $verbose, $help, $confirm );
14
my $result = GetOptions(
15
    'h|help'    => \$help,
16
    'v|verbose' => \$verbose,
17
    'c|confirm' => \$confirm,
18
);
19
20
pod2usage(1) if $help;
21
$verbose = 1 unless $confirm;
22
23
# Load configuration from the syspref
24
my $syspref_content = C4::Context->preference('automatic_item_modification_by_age_configuration');
25
my $rules = eval { JSON::from_json( $syspref_content ) };
26
pod2usage({ -message => "Unable to load the configuration : $@", -exitval => 1 })
27
    if $@;
28
29
my $report = C4::Items::ToggleNewStatus( { rules => $rules, report_only => not $confirm } );
30
31
if ( $verbose ) {
32
    if ( $report ) {
33
        say "Item to modify:";
34
        while ( my ( $itemnumber, $substitutions ) = each %$report ) {
35
            for my $substitution ( @$substitutions ) {
36
                if ( defined $substitution->{value} and $substitution->{value} ne q|| ) {
37
                   say "\titemnumber $itemnumber: $substitution->{field}=$substitution->{value}";
38
                } else {
39
                   say "\titemnumber $itemnumber: field $substitution->{field} to delete";
40
                }
41
            }
42
        }
43
    } else {
44
        say "There is no item to modify";
45
    }
46
}
47
48
exit(0);
49
50
__END__
51
52
=head1 NAME
53
54
automatic_item_modification_by_age.pl
55
56
=head1 SYNOPSIS
57
58
./automatic_item_modification_by_age.pl -h
59
60
Toggle recent acquisitions status.
61
Use this script to delete "new" status for items.
62
63
=head1 OPTIONS
64
65
=over 8
66
67
=item B<-h|--help>
68
69
Prints this help message.
70
71
=item B<-v|--verbose>
72
73
Set the verbose flag.
74
75
=item B<-c|--confirm>
76
77
The script will modify the items.
78
79
=back
80
81
=head1 AUTHOR
82
83
Jonathan Druart <jonathan.druart@biblibre.com>
84
85
=head1 COPYRIGHT
86
87
Copyright 2013 BibLibre
88
89
=head1 LICENSE
90
91
This file is part of Koha.
92
93
Koha is free software; you can redistribute it and/or modify it
94
under the terms of the GNU General Public License as published by
95
the Free Software Foundation; either version 3 of the License, or
96
(at your option) any later version.
97
98
Koha is distributed in the hope that it will be useful, but
99
WITHOUT ANY WARRANTY; without even the implied warranty of
100
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
101
GNU General Public License for more details.
102
103
You should have received a copy of the GNU General Public License
104
along with Koha; if not, see <http://www.gnu.org/licenses>.
105
106
=cut
(-)a/t/db_dependent/Items/AutomaticItemModificationByAge.t (+283 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
use Modern::Perl;
4
use Test::More tests => 16;
5
use MARC::Record;
6
use MARC::Field;
7
use DateTime;
8
use DateTime::Duration;
9
10
use C4::Biblio;
11
use C4::Context;
12
use C4::Items;
13
use Koha::DateUtils;
14
15
my $dbh = C4::Context->dbh;
16
$dbh->{AutoCommit} = 0;
17
$dbh->{RaiseError} = 1;
18
19
$dbh->do(q|
20
    DELETE FROM marc_subfield_structure
21
    WHERE kohafield = 'items.new' OR kohafield = 'items.stocknumber'
22
|);
23
24
my $new_tagfield = 'i';
25
$dbh->do(qq|
26
    INSERT INTO marc_subfield_structure(tagfield, tagsubfield, kohafield, frameworkcode)
27
    VALUES ( 952, '$new_tagfield', 'items.new', '' )
28
|);
29
30
my $record = MARC::Record->new();
31
$record->append_fields(
32
    MARC::Field->new('100', ' ', ' ', a => 'Moffat, Steven'),
33
    MARC::Field->new('245', ' ', ' ', a => 'Silence in the library'),
34
    MARC::Field->new('942', ' ', ' ', c => 'ITEMTYPE_T'),
35
);
36
my ($biblionumber, undef) = C4::Biblio::AddBiblio($record, '');
37
38
my ($item_bibnum, $item_bibitemnum, $itemnumber) = C4::Items::AddItem(
39
    {
40
        homebranch => 'CPL',
41
        holdingbranch => 'CPL',
42
        new => 'new_value',
43
        ccode => 'FIC',
44
    },
45
    $biblionumber
46
);
47
48
my $item = C4::Items::GetItem( $itemnumber );
49
is ( $item->{new}, 'new_value', q|AddItem insert the 'new' field| );
50
51
my ( $tagfield, undef ) = GetMarcFromKohaField('items.itemnumber', '');
52
my $marc_item = C4::Items::GetMarcItem( $biblionumber, $itemnumber );
53
is( $marc_item->subfield($tagfield, $new_tagfield), 'new_value', q|Koha mapping is correct|);
54
55
# Update the items.new field if items.ccode eq 'FIC' => should be updated
56
my @rules = (
57
    {
58
        conditions => [
59
            {
60
                field => 'items.ccode',
61
                value => 'FIC',
62
            },
63
        ],
64
        substitutions => [
65
            {
66
                field => 'items.new',
67
                value => 'updated_value',
68
             },
69
        ],
70
        age => '0',
71
    },
72
);
73
74
C4::Items::ToggleNewStatus( { rules => \@rules } );
75
76
my $modified_item = C4::Items::GetItem( $itemnumber );
77
is( $modified_item->{new}, 'updated_value', q|ToggleNewStatus: The new value is updated|);
78
$marc_item = C4::Items::GetMarcItem( $biblionumber, $itemnumber );
79
is( $marc_item->subfield($tagfield, $new_tagfield), 'updated_value', q|ToggleNewStatus: The new value is updated| );
80
81
# Update the items.new field if items.ccode eq 'DONT_EXIST' => should not be updated
82
@rules = (
83
    {
84
        conditions => [
85
            {
86
                field => 'items.ccode',
87
                value => 'DONT_EXIST',
88
            },
89
        ],
90
        substitutions => [
91
            {
92
                field => 'items.new',
93
                value => 'new_updated_value',
94
             },
95
        ],
96
        age => '0',
97
    },
98
);
99
100
C4::Items::ToggleNewStatus( { rules => \@rules } );
101
102
$modified_item = C4::Items::GetItem( $itemnumber );
103
is( $modified_item->{new}, 'updated_value', q|ToggleNewStatus: The new value is not updated|);
104
$marc_item = C4::Items::GetMarcItem( $biblionumber, $itemnumber );
105
is( $marc_item->subfield($tagfield, $new_tagfield), 'updated_value', q|ToggleNewStatus: The new value is not updated| );
106
107
# Play with age
108
$item = C4::Items::GetItem( $itemnumber );
109
my $dt_today = dt_from_string;
110
my $days5ago = $dt_today->add_duration( DateTime::Duration->new( days => -5 ) );
111
112
C4::Items::ModItem( { dateaccessioned => $days5ago }, $biblionumber, $itemnumber );
113
$item = C4::Items::GetItem( $itemnumber );
114
115
@rules = (
116
    {
117
        conditions => [
118
            {
119
                field => 'items.ccode',
120
                value => 'FIC',
121
            },
122
        ],
123
        substitutions => [
124
            {
125
                field => 'items.new',
126
                value => 'new_updated_value',
127
             },
128
        ],
129
        age => '10',
130
    },
131
);
132
C4::Items::ToggleNewStatus( { rules => \@rules } );
133
$modified_item = C4::Items::GetItem( $itemnumber );
134
is( $modified_item->{new}, 'updated_value', q|ToggleNewStatus: Age = 10 : The new value is not updated|);
135
136
$rules[0]->{age} = 5;
137
$rules[0]->{substitutions}[0]{value} = 'new_updated_value5';
138
C4::Items::ToggleNewStatus( { rules => \@rules } );
139
$modified_item = C4::Items::GetItem( $itemnumber );
140
is( $modified_item->{new}, 'new_updated_value5', q|ToggleNewStatus: Age = 5 : The new value is updated|);
141
142
$rules[0]->{age} = '';
143
$rules[0]->{substitutions}[0]{value} = 'new_updated_value_empty_string';
144
C4::Items::ToggleNewStatus( { rules => \@rules } );
145
$modified_item = C4::Items::GetItem( $itemnumber );
146
is( $modified_item->{new}, 'new_updated_value_empty_string', q|ToggleNewStatus: Age = '' : The new value is updated|);
147
148
$rules[0]->{age} = undef;
149
$rules[0]->{substitutions}[0]{value} = 'new_updated_value_undef';
150
C4::Items::ToggleNewStatus( { rules => \@rules } );
151
$modified_item = C4::Items::GetItem( $itemnumber );
152
is( $modified_item->{new}, 'new_updated_value_undef', q|ToggleNewStatus: Age = undef : The new value is updated|);
153
154
# Field deletion
155
@rules = (
156
    {
157
        conditions => [
158
            {
159
                field => 'items.ccode',
160
                value => 'FIC',
161
            },
162
        ],
163
        substitutions => [
164
            {
165
                field => 'items.new',
166
                value => '',
167
             },
168
        ],
169
        age => '0',
170
    },
171
);
172
173
C4::Items::ToggleNewStatus( { rules => \@rules } );
174
175
$modified_item = C4::Items::GetItem( $itemnumber );
176
is( $modified_item->{new}, '', q|ToggleNewStatus: The new value is empty|);
177
$marc_item = C4::Items::GetMarcItem( $biblionumber, $itemnumber );
178
is( $marc_item->subfield($tagfield, $new_tagfield), undef, q|ToggleNewStatus: The new field is removed from the item marc| );
179
180
# conditions multiple
181
@rules = (
182
    {
183
        conditions => [
184
            {
185
                field => 'items.ccode',
186
                value => 'FIC',
187
            },
188
            {
189
                field => 'items.homebranch',
190
                value => 'CPL',
191
            },
192
        ],
193
        substitutions => [
194
            {
195
                field => 'items.new',
196
                value => 'new_value',
197
             },
198
        ],
199
        age => '0',
200
    },
201
);
202
203
C4::Items::ToggleNewStatus( { rules => \@rules } );
204
205
$modified_item = C4::Items::GetItem( $itemnumber );
206
is( $modified_item->{new}, 'new_value', q|ToggleNewStatus: conditions multiple: all match, the new value is updated|);
207
208
@rules = (
209
    {
210
        conditions => [
211
            {
212
                field => 'items.ccode',
213
                value => 'FIC',
214
            },
215
            {
216
                field => 'items.homebranch',
217
                value => 'DONT_EXIST',
218
            },
219
        ],
220
        substitutions => [
221
            {
222
                field => 'items.new',
223
                value => 'new_updated_value',
224
             },
225
        ],
226
        age => '0',
227
    },
228
);
229
230
C4::Items::ToggleNewStatus( { rules => \@rules } );
231
232
$modified_item = C4::Items::GetItem( $itemnumber );
233
is( $modified_item->{new}, 'new_value', q|ToggleNewStatus: conditions multiple: at least 1 condition does not match, the new value is not updated|);
234
235
@rules = (
236
    {
237
        conditions => [
238
            {
239
                field => 'items.ccode',
240
                value => 'FIC|NFIC',
241
            },
242
            {
243
                field => 'items.homebranch',
244
                value => 'MPL|CPL',
245
            },
246
        ],
247
        substitutions => [
248
            {
249
                field => 'items.new',
250
                value => 'new_updated_value',
251
             },
252
        ],
253
        age => '0',
254
    },
255
);
256
257
C4::Items::ToggleNewStatus( { rules => \@rules } );
258
259
$modified_item = C4::Items::GetItem( $itemnumber );
260
is( $modified_item->{new}, 'new_updated_value', q|ToggleNewStatus: conditions multiple: the 2 conditions match, the new value is updated|);
261
262
@rules = (
263
    {
264
        conditions => [
265
            {
266
                field => 'biblioitems.itemtype',
267
                value => 'ITEMTYPE_T',
268
            },
269
        ],
270
        substitutions => [
271
            {
272
                field => 'items.new',
273
                value => 'another_new_updated_value',
274
             },
275
        ],
276
        age => '0',
277
    },
278
);
279
280
C4::Items::ToggleNewStatus( { rules => \@rules } );
281
282
$modified_item = C4::Items::GetItem( $itemnumber );
283
is( $modified_item->{new}, 'another_new_updated_value', q|ToggleNewStatus: conditions on biblioitems|);
(-)a/tools/automatic_item_modification_by_age.pl (-1 / +119 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# This file is part of Koha.
4
#
5
# Copyright 2013 BibLibre
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
=head1 NAME
21
22
automatic_item_modification_by_age.pl: Update new status for items.
23
24
=cut
25
26
=head1 DESCRIPTION
27
28
This script allows a user to update the new status for items.
29
30
=cut
31
32
use Modern::Perl;
33
34
use CGI;
35
use JSON qw( to_json from_json );
36
37
use C4::Auth;
38
use C4::Context;
39
use C4::Items;
40
use C4::Output;
41
use C4::Koha;
42
43
my $cgi = new CGI;
44
45
# open template
46
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
47
    {
48
        template_name   => "tools/automatic_item_modification_by_age.tt",
49
        query           => $cgi,
50
        type            => "intranet",
51
        authnotrequired => 0,
52
        flagsrequired   => { tools => 'items_batchmod' },
53
    }
54
);
55
56
my $op = $cgi->param('op') // 'show';
57
58
my $syspref_name = q|automatic_item_modification_by_age_configuration|;
59
if ( $op eq 'update' ) {
60
    my @rules;
61
    my @unique_ids = $cgi->param('unique_id');
62
    for my $unique_id ( @unique_ids ) {
63
        my @substitution_fields = $cgi->param("substitution_field_$unique_id");
64
        my @substitution_values = $cgi->param("substitution_value_$unique_id");
65
        my @condition_fields = $cgi->param("condition_field_$unique_id");
66
        my @condition_values = $cgi->param("condition_value_$unique_id");
67
        my $rule = {
68
            substitutions => [],
69
            conditions => [],
70
        };
71
        for my $value ( @substitution_values ) {
72
            my $field = shift @substitution_fields;
73
            last unless $field;
74
            push @{ $rule->{substitutions} }, { field => $field, value => $value };
75
        }
76
        push @{ $rule->{substitutions} }, {}
77
            unless @{ $rule->{substitutions} };
78
        for my $value ( @condition_values ) {
79
            my $field = shift @condition_fields;
80
            last unless $field;
81
            push @{ $rule->{conditions} }, { field => $field, value => $value };
82
        }
83
        push @{ $rule->{conditions} }, {}
84
            unless @{ $rule->{conditions} };
85
        $rule->{age} = $cgi->param("age_$unique_id");
86
        push @rules, $rule;
87
    }
88
    my $syspref_content = to_json( \@rules );
89
    C4::Context->set_preference($syspref_name, $syspref_content);
90
91
    $op = 'show';
92
}
93
94
my @messages;
95
my $syspref_content = C4::Context->preference($syspref_name);
96
my $rules;
97
$rules = eval { JSON::from_json( $syspref_content ) }
98
    if $syspref_content;
99
if ( $@ ) {
100
    push @messages, {
101
        type => 'error',
102
        code => 'unable_to_load_configuration'
103
    };
104
    $template->param( messages => \@messages );
105
    output_html_with_http_headers $cgi, $cookie, $template->output;
106
    exit;
107
}
108
109
my @item_fields = map { "items.$_" } C4::Items::columns;
110
my @biblioitem_fields = map { "biblioitems.$_" } C4::Items::biblioitems_columns;
111
$template->param(
112
    op => $op,
113
    messages => \@messages,
114
    condition_fields => [ @item_fields, @biblioitem_fields ],
115
    substitution_fields => \@item_fields,
116
    rules => $rules,
117
);
118
119
output_html_with_http_headers $cgi, $cookie, $template->output;

Return to bug 11023