Bug 30708: Duplicate/copy items to an opened train
Sponsored-by: BULAC - http://www.bulac.fr/ Signed-off-by: BULAC - http://www.bulac.fr/ Signed-off-by: Heather Hernandez <heather_hernandez@nps.gov> Signed-off-by: Laurence Rault <laurence.rault@biblibre.com> Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl> Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
This commit is contained in:
parent
4819f89b43
commit
eae94108e7
|
|
@ -56,35 +56,42 @@ sub default_processing {
|
|||
|
||||
Add item to this train
|
||||
|
||||
my $train_item = $train->add_item({item_id => $itemnumber, processing_id => $processing_id});
|
||||
my $train_item = $train->add_item({barcode => $barcode, processing_id => $processing_id});
|
||||
my $train_item = $train->add_item({item_id => $itemnumber, processing_id => $processing_id}, { skip_waiting_list_check => 0|1 });
|
||||
my $train_item = $train->add_item({barcode => $barcode, processing_id => $processing_id, { skip_waiting_list_check => 0|1 });
|
||||
|
||||
skip_waitin_list_check can be set to true if the item can be added to the train even if the item is not in the waiting list.
|
||||
|
||||
=cut
|
||||
|
||||
sub add_item {
|
||||
my ( $self, $train_item ) = @_;
|
||||
my ( $self, $train_item, $params ) = @_;
|
||||
|
||||
my $skip_waiting_list_check = $params->{skip_waiting_list_check} || 0;
|
||||
|
||||
my $not_for_loan = C4::Context->preference('PreservationNotForLoanWaitingListIn');
|
||||
|
||||
my $key = exists $train_item->{item_id} ? 'itemnumber' : 'barcode';
|
||||
my $item = Koha::Items->find( { $key => $train_item->{item_id} || $train_item->{barcode} } );
|
||||
Koha::Exceptions::Preservation::ItemNotFound->throw unless $item;
|
||||
Koha::Exceptions::Preservation::ItemNotInWaitingList->throw if $item->notforloan != $not_for_loan;
|
||||
|
||||
Koha::Exceptions::Preservation::ItemNotInWaitingList->throw
|
||||
if !$skip_waiting_list_check && $item->notforloan != $not_for_loan;
|
||||
|
||||
# FIXME We need a LOCK here
|
||||
# Not important for now as we have add_items
|
||||
# Note that there are several other places in Koha with this max+1 problem
|
||||
my $max = $self->items->search->_resultset->get_column("user_train_item_id")->max || 0;
|
||||
my $train_item_rs = $self->_result->add_to_preservation_trains_items(
|
||||
my $train_item_object = Koha::Preservation::Train::Item->new(
|
||||
{
|
||||
train_id => $self->train_id,
|
||||
item_id => $item->itemnumber,
|
||||
processing_id => $train_item->{processing_id} || $self->default_processing_id,
|
||||
user_train_item_id => $max + 1,
|
||||
added_on => \'NOW()',
|
||||
}
|
||||
);
|
||||
)->store;
|
||||
$item->notforloan( $self->not_for_loan )->store;
|
||||
return Koha::Preservation::Train::Item->_new_from_dbic($train_item_rs);
|
||||
return $train_item_object->get_from_storage;
|
||||
}
|
||||
|
||||
=head3 add_items
|
||||
|
|
|
|||
|
|
@ -389,6 +389,98 @@ sub add_item {
|
|||
};
|
||||
}
|
||||
|
||||
=head3 copy_item
|
||||
|
||||
=cut
|
||||
|
||||
sub copy_item {
|
||||
my $c = shift->openapi->valid_input or return;
|
||||
|
||||
my $train_id = $c->validation->param('train_id');
|
||||
my $train = Koha::Preservation::Trains->find( $train_id );
|
||||
|
||||
unless ($train) {
|
||||
return $c->render(
|
||||
status => 404,
|
||||
openapi => { error => "Train not found" }
|
||||
);
|
||||
}
|
||||
|
||||
my $train_item_id = $c->validation->param('train_item_id');
|
||||
|
||||
my $train_item = Koha::Preservation::Train::Items->search({ train_item_id => $train_item_id, train_id => $train_id })->single;
|
||||
|
||||
unless ($train_item) {
|
||||
return $c->render(
|
||||
status => 404,
|
||||
openapi => { error => "Item not found" }
|
||||
);
|
||||
}
|
||||
|
||||
my $body = $c->validation->param('body');
|
||||
return try {
|
||||
Koha::Database->new->schema->txn_do(
|
||||
sub {
|
||||
my $new_train_id = delete $body->{train_id};
|
||||
my $new_train = Koha::Preservation::Trains->find( $new_train_id );
|
||||
unless ($train) {
|
||||
return $c->render(
|
||||
status => 404,
|
||||
openapi => { error => "Train not found" }
|
||||
);
|
||||
}
|
||||
my $new_train_item = $new_train->add_item(
|
||||
{
|
||||
item_id => $train_item->item_id,
|
||||
processing_id => $train_item->processing_id
|
||||
},
|
||||
{
|
||||
skip_waiting_list_check => 1,
|
||||
},
|
||||
);
|
||||
my $attributes = [
|
||||
map {
|
||||
{
|
||||
processing_attribute_id => $_->processing_attribute_id,
|
||||
train_item_id => $new_train_item->train_item_id,
|
||||
value => $_->value
|
||||
}
|
||||
} $train_item->attributes->as_list
|
||||
];
|
||||
$new_train_item->attributes($attributes);
|
||||
return $c->render( status => 201, openapi => $train_item );
|
||||
}
|
||||
);
|
||||
}
|
||||
catch {
|
||||
if ( blessed $_ ) {
|
||||
if ( $_->isa('Koha::Exceptions::Preservation::MissingSettings') ) {
|
||||
return $c->render(
|
||||
status => 400,
|
||||
openapi => { error => "MissingSettings", parameter => $_->parameter }
|
||||
);
|
||||
} elsif ( $_->isa('Koha::Exceptions::Preservation::ItemNotFound') ) {
|
||||
return $c->render(
|
||||
status => 404,
|
||||
openapi => { error => "Item not found" }
|
||||
);
|
||||
} elsif ( $_->isa('Koha::Exceptions::Object::DuplicateID') ) {
|
||||
return $c->render(
|
||||
status => 409,
|
||||
openapi => { error => $_->error, conflict => $_->duplicate_id }
|
||||
);
|
||||
} elsif ( $_->isa('Koha::Exceptions::Preservation::ItemNotInWaitingList') ) {
|
||||
return $c->render(
|
||||
status => 400,
|
||||
openapi => { error => 'Item not in waiting list' }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$c->unhandled_exception($_);
|
||||
};
|
||||
}
|
||||
|
||||
=head3 update_item
|
||||
|
||||
Controller function that handles updating an item from a train
|
||||
|
|
|
|||
|
|
@ -619,3 +619,78 @@
|
|||
x-koha-authorization:
|
||||
permissions:
|
||||
preservation: 1
|
||||
|
||||
"/preservation/trains/{train_id}/items/{train_item_id}/copy":
|
||||
post:
|
||||
x-mojo-to: Preservation::Trains#copy_item
|
||||
operationId: copyItemToAnotherTrain
|
||||
tags:
|
||||
- preservation_train
|
||||
summary: Copy an item to an other train
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- $ref: "../swagger.yaml#/parameters/preservation_train_id_pp"
|
||||
- $ref: "../swagger.yaml#/parameters/preservation_train_item_id_pp"
|
||||
- description: The train_id of the new train
|
||||
in: body
|
||||
name: body
|
||||
required: true
|
||||
schema:
|
||||
type: object
|
||||
responses:
|
||||
201:
|
||||
description: A successfully copied item
|
||||
schema:
|
||||
type: object
|
||||
400:
|
||||
description: Bad parameter
|
||||
schema:
|
||||
$ref: "../swagger.yaml#/definitions/error"
|
||||
401:
|
||||
description: Authentication required
|
||||
schema:
|
||||
$ref: "../swagger.yaml#/definitions/error"
|
||||
403:
|
||||
description: Access forbidden
|
||||
schema:
|
||||
$ref: "../swagger.yaml#/definitions/error"
|
||||
404:
|
||||
description: Ressource not found
|
||||
schema:
|
||||
$ref: "../swagger.yaml#/definitions/error"
|
||||
409:
|
||||
description: Conflict in creating resource
|
||||
schema:
|
||||
$ref: "../swagger.yaml#/definitions/error"
|
||||
413:
|
||||
description: Payload too large
|
||||
schema:
|
||||
$ref: "../swagger.yaml#/definitions/error"
|
||||
500:
|
||||
description: |-
|
||||
Internal server error. Possible `error_code` attribute values:
|
||||
* `internal_server_error`
|
||||
schema:
|
||||
$ref: "../swagger.yaml#/definitions/error"
|
||||
503:
|
||||
description: Under maintenance
|
||||
schema:
|
||||
$ref: "../swagger.yaml#/definitions/error"
|
||||
x-koha-authorization:
|
||||
permissions:
|
||||
preservation: 1
|
||||
description: |-
|
||||
Internal server error. Possible `error_code` attribute values:
|
||||
* `internal_server_error`
|
||||
schema:
|
||||
$ref: "../swagger.yaml#/definitions/error"
|
||||
503:
|
||||
description: Under maintenance
|
||||
schema:
|
||||
$ref: "../swagger.yaml#/definitions/error"
|
||||
x-koha-authorization:
|
||||
permissions:
|
||||
preservation: 1
|
||||
|
|
|
|||
|
|
@ -347,6 +347,8 @@ paths:
|
|||
$ref: "./paths/preservation_trains.yaml#/~1preservation~1trains~1{train_id}~1items~1batch"
|
||||
"/preservation/trains/{train_id}/items/{train_item_id}":
|
||||
$ref: "./paths/preservation_trains.yaml#/~1preservation~1trains~1{train_id}~1items~1{train_item_id}"
|
||||
"/preservation/trains/{train_id}/items/{train_item_id}/copy":
|
||||
$ref: "./paths/preservation_trains.yaml#/~1preservation~1trains~1{train_id}~1items~1{train_item_id}~1copy"
|
||||
/preservation/processings:
|
||||
$ref: ./paths/preservation_processings.yaml#/~1preservation~1processings
|
||||
"/preservation/processings/{processing_id}":
|
||||
|
|
|
|||
|
|
@ -410,34 +410,18 @@ export default {
|
|||
copyItem(event) {
|
||||
event.preventDefault()
|
||||
const client = APIClient.preservation
|
||||
let new_train_item = {}
|
||||
client.train_items
|
||||
.get(this.train.train_id, this.train_item_id_to_copy)
|
||||
.then(train_item => {
|
||||
new_train_item = {
|
||||
attributes: train_item.attributes.map(attr => {
|
||||
return {
|
||||
processing_attribute_id:
|
||||
attr.processing_attribute_id,
|
||||
value: attr.value,
|
||||
}
|
||||
}),
|
||||
item_id: train_item.item_id,
|
||||
processing_id: train_item.processing_id,
|
||||
}
|
||||
})
|
||||
.then(() =>
|
||||
client.train_items
|
||||
.create(new_train_item, this.train_id_selected_for_copy)
|
||||
.then(
|
||||
success => {
|
||||
this.setMessage(
|
||||
this.$__("Item copied successfully.")
|
||||
)
|
||||
this.show_modal = false
|
||||
},
|
||||
error => {}
|
||||
)
|
||||
.copy(
|
||||
this.train_id_selected_for_copy,
|
||||
this.train.train_id,
|
||||
this.train_item_id_to_copy
|
||||
)
|
||||
.then(
|
||||
success => {
|
||||
this.setMessage(this.$__("Item copied successfully."))
|
||||
this.show_modal = false
|
||||
},
|
||||
error => {}
|
||||
)
|
||||
},
|
||||
build_datatable: function () {
|
||||
|
|
|
|||
|
|
@ -121,6 +121,11 @@ export class PreservationAPIClient extends HttpClient {
|
|||
endpoint: "trains/" + train_id + "/items/batch",
|
||||
body: train_items,
|
||||
}),
|
||||
copy: (new_train_id, train_id, id) =>
|
||||
this.post({
|
||||
endpoint: "trains/" + train_id + "/items/" + id + "/copy",
|
||||
body: { train_id: new_train_id },
|
||||
}),
|
||||
update: (train_item, train_id, id) =>
|
||||
this.put({
|
||||
endpoint: "trains/" + train_id + "/items/" + id,
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ subtest 'default_processing' => sub {
|
|||
};
|
||||
|
||||
subtest 'add_items & items' => sub {
|
||||
plan tests => 9;
|
||||
plan tests => 12;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
|
|
@ -98,5 +98,11 @@ subtest 'add_items & items' => sub {
|
|||
is( $item_2->get_from_storage->notforloan, 0 );
|
||||
is( $item_3->get_from_storage->notforloan, $not_for_loan_train_in );
|
||||
|
||||
warning_is {
|
||||
$train->add_item( { item_id => $item_2->itemnumber }, { skip_waiting_list_check => 1 } );
|
||||
} '';
|
||||
is( $train->items->count, 3, 'the item has been added to the train' );
|
||||
is( $item_2->get_from_storage->notforloan, $not_for_loan_train_in );
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue