Skip to content

Commit

Permalink
views: add loans actions url rules
Browse files Browse the repository at this point in the history
- add view to handle loan actions with REST calls
- closes inveniosoftware#26

Co-authored-by: Zacharias Zacharodimos <zacharias.zacharodimos@cern.ch>
Co-authored-by: Christos Topaloudis <topless@gmail.com>
  • Loading branch information
3 people committed Jul 23, 2018
1 parent efcb26f commit a8e0414
Show file tree
Hide file tree
Showing 10 changed files with 240 additions and 161 deletions.
101 changes: 24 additions & 77 deletions invenio_circulation/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,71 +8,14 @@

"""Circulation API."""

import config
import warnings
from datetime import datetime

from flask import current_app
from invenio_records.api import Record
from transitions import Machine

DIAGRAM_ENABLED = True
try:
import pygraphviz
from transitions.extensions import GraphMachine
except ImportError:
DIAGRAM_ENABLED = False

STATES = [
'CREATED',
'PENDING',
'ITEM_ON_LOAN',
'ITEM_RETURNED',
'ITEM_IN_TRANSIT',
'ITEM_AT_DESK',
]

TRANSITIONS = [
{
'trigger': 'request',
'source': 'CREATED',
'dest': 'PENDING',
'before': 'set_request_parameters',
'conditions': 'is_request_valid',
},
{
'trigger': 'validate_request',
'source': 'PENDING',
'dest': 'ITEM_IN_TRANSIT',
'before': 'set_parameters',
'conditions': 'is_validate_request_valid',
'unless': 'is_pickup_at_same_library',
},
{
'trigger': 'validate_request',
'source': 'PENDING',
'dest': 'ITEM_AT_DESK',
'before': 'set_parameters',
'conditions': [
'is_validate_request_valid',
'is_pickup_at_same_library',
],
},
{
'trigger': 'checkout',
'source': 'CREATED',
'dest': 'ITEM_ON_LOAN',
'before': 'set_parameters',
'conditions': 'is_checkout_valid',
},
{
'trigger': 'checkin',
'source': 'ITEM_ON_LOAN',
'dest': 'ITEM_RETURNED',
'before': 'set_parameters',
'conditions': 'is_checkin_valid',
},
]


class Loan(Record):
"""Loan record class."""
Expand All @@ -97,25 +40,6 @@ def policies(self):
"""."""
return current_app.config.get('CIRCULATION_POLICIES')

@classmethod
def export_diagram(cls, output_file):
"""."""
if not DIAGRAM_ENABLED:
warnings.warn(
'dependency not found, please install pygraphviz to '
'export the circulation state diagram.'
)
return False
m = GraphMachine(
states=self.states,
transitions=self.transitions,
initial=self.states[0],
show_conditions=True,
title='Circulation State Diagram',
)
m.get_graph().draw(output_file, prog='dot')
return True

def set_request_parameters(self, event):
"""."""
self.set_parameters(event)
Expand Down Expand Up @@ -176,3 +100,26 @@ def is_request_valid(self, event):
def is_validate_request_valid(self, event):
"""."""
return self.policies['validate_request'](**event.kwargs)

@classmethod
def export_diagram(cls, output_file):
"""."""
from transitions.extensions import GraphMachine

try:
import pygraphviz
except ImportError:
warnings.warn('dependency not found, please install pygraphviz to '
'export the circulation state diagram.')
return False

# FIXME: replace config with current_app.config when CLI has appcontext
# states = current_app.config['CIRCULATION_LOAN_STATES']
# transitions = current_app.config['CIRCULATION_LOAN_TRANSITIONS']
states = config.CIRCULATION_LOAN_STATES
transitions = config.CIRCULATION_LOAN_TRANSITIONS
m = GraphMachine(states=states, transitions=transitions,
initial=states[0], show_conditions=True,
title='Circulation State Diagram')
m.get_graph().draw(output_file, prog='dot')
return True
85 changes: 48 additions & 37 deletions invenio_circulation/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,6 @@
from .utils import is_checkin_valid, is_checkout_valid, is_request_valid, \
is_request_validate_valid, item_location_retriever


CIRCULATION_LOAN_TRANSITIONS = [{
'trigger': 'request',
'source': 'CREATED',
'dest': 'PENDING',
'before': 'set_request_parameters'
}, {
'trigger': 'validate_request',
'source': 'PENDING',
'dest': 'ITEM_IN_TRANSIT',
'before': 'set_parameters',
'unless': 'is_pickup_at_same_library'
}, {
'trigger': 'validate_request',
'source': 'PENDING',
'dest': 'ITEM_AT_DESK',
'before': 'set_parameters',
'conditions': 'is_pickup_at_same_library'
}, {
'trigger': 'checkout',
'source': 'CREATED',
'dest': 'ITEM_ON_LOAN',
'before': 'set_parameters',
'conditions': 'is_checkout_valid'
}, {
'trigger': 'checkin',
'source': 'ITEM_ON_LOAN',
'dest': 'ITEM_RETURNED',
'before': 'set_parameters'
}]
"""."""

CIRCULATION_LOAN_STATES = [
'CREATED',
'PENDING',
Expand All @@ -52,6 +20,50 @@
'ITEM_IN_TRANSIT',
'ITEM_AT_DESK',
]
"""."""

CIRCULATION_LOAN_TRANSITIONS = [
{
'trigger': 'request',
'source': 'CREATED',
'dest': 'PENDING',
'before': 'set_request_parameters',
'conditions': 'is_request_valid',
},
{
'trigger': 'validate_request',
'source': 'PENDING',
'dest': 'ITEM_IN_TRANSIT',
'before': 'set_parameters',
'conditions': 'is_validate_request_valid',
'unless': 'is_pickup_at_same_library',
},
{
'trigger': 'validate_request',
'source': 'PENDING',
'dest': 'ITEM_AT_DESK',
'before': 'set_parameters',
'conditions': [
'is_validate_request_valid',
'is_pickup_at_same_library',
],
},
{
'trigger': 'checkout',
'source': 'CREATED',
'dest': 'ITEM_ON_LOAN',
'before': 'set_parameters',
'conditions': 'is_checkout_valid',
},
{
'trigger': 'checkin',
'source': 'ITEM_ON_LOAN',
'dest': 'ITEM_RETURNED',
'before': 'set_parameters',
'conditions': 'is_checkin_valid',
}
]
"""."""

CIRCULATION_ITEM_LOCATION_RETRIEVER = item_location_retriever
"""."""
Expand Down Expand Up @@ -82,17 +94,16 @@
CIRCULATION_LOAN_ITEM_ROUTE = '/circulation/loan/<pid(loanid):pid_value>'
"""."""



_Loan_PID = 'pid(loanid,record_class="invenio_circulation.api:Loan")'
CIRCULATION_REST_ENDPOINTS = dict(
loanid=dict(
pid_type=_CIRCULATION_LOAN_PID_TYPE,
pid_minter=_CIRCULATION_LOAN_MINTER,
pid_fetcher=_CIRCULATION_LOAN_FETCHER,
# search_class=RecordsSearch,
# indexer_class=RecordIndexer,
search_index=None,
search_type=None,
# search_index=None,
# search_type=None,
record_class=Loan,
record_serializers={
'application/json': ('invenio_records_rest.serializers'
Expand All @@ -103,7 +114,7 @@
':json_v1_search'),
},
list_route='/circulation/loan/',
item_route='/circulation/loan/<pid(loanid):pid_value>',
item_route='/circulation/loan/<{0}:pid_value>'.format(_Loan_PID),
default_media_type='application/json',
max_result_window=10000,
error_handlers=dict(),
Expand Down
13 changes: 13 additions & 0 deletions invenio_circulation/errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2018 CERN.
# Copyright (C) 2018 RERO.
#
# Invenio-Circulation is free software; you can redistribute it and/or modify
# it under the terms of the MIT License; see LICENSE file for more details.

"""Circulation exceptions."""


class LoanActionError(Exception):
"""Loan action error."""
11 changes: 5 additions & 6 deletions invenio_circulation/ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
from __future__ import absolute_import, print_function

from . import config
from .views import blueprint as bp, build_endpoints_from_trasitions
from .views import build_blueprint_with_loan_actions


class InvenioCirculation(object):
"""Invenio-Circulation extension."""
Expand All @@ -27,11 +28,9 @@ def init_app(self, app):
app.config.setdefault('RECORDS_REST_ENDPOINTS', {})
app.config['RECORDS_REST_ENDPOINTS'].update(
app.config['CIRCULATION_REST_ENDPOINTS'])
build_endpoints_from_trasitions(app)
app.register_blueprint(
bp,
url_prefix=app.config['CIRCULATION_LOAN_ITEM_ROUTE']
)

blueprint = build_blueprint_with_loan_actions(app)
app.register_blueprint(blueprint)
app.extensions['invenio-circulation'] = self

def init_config(self, app):
Expand Down
3 changes: 0 additions & 3 deletions invenio_circulation/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,3 @@ def is_request_validate_valid(
):
"""."""
return True



Loading

0 comments on commit a8e0414

Please sign in to comment.