Misc cli changes #1
|
@ -61,26 +61,6 @@ class WorblehatCli(NumberedCmd):
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
|
|
||||||
def do_list_bookcases(self, _: str):
|
|
||||||
bookcase_shelfs = self.sql_session.scalars(
|
|
||||||
select(BookcaseShelf)
|
|
||||||
.join(Bookcase)
|
|
||||||
.order_by(
|
|
||||||
Bookcase.name,
|
|
||||||
BookcaseShelf.column,
|
|
||||||
BookcaseShelf.row,
|
|
||||||
)
|
|
||||||
).all()
|
|
||||||
|
|
||||||
bookcase_uid = None
|
|
||||||
for shelf in bookcase_shelfs:
|
|
||||||
if shelf.bookcase.uid != bookcase_uid:
|
|
||||||
print(shelf.bookcase.short_str())
|
|
||||||
bookcase_uid = shelf.bookcase.uid
|
|
||||||
|
|
||||||
print(f' {shelf.short_str()} - {sum(i.amount for i in shelf.items)} items')
|
|
||||||
|
|
||||||
|
|
||||||
def do_show_bookcase(self, arg: str):
|
def do_show_bookcase(self, arg: str):
|
||||||
bookcase_selector = InteractiveItemSelector(
|
bookcase_selector = InteractiveItemSelector(
|
||||||
cls = Bookcase,
|
cls = Bookcase,
|
||||||
|
@ -95,6 +75,35 @@ class WorblehatCli(NumberedCmd):
|
||||||
print(f' {item.name} - {item.amount} copies')
|
print(f' {item.name} - {item.amount} copies')
|
||||||
|
|
||||||
|
|
||||||
|
def do_show_borrowed_queued(self, _: str):
|
||||||
|
borrowed_items = self.sql_session.scalars(
|
||||||
|
select(BookcaseItemBorrowing)
|
||||||
|
.where(BookcaseItemBorrowing.delivered.is_(None))
|
||||||
|
.order_by(BookcaseItemBorrowing.end_time),
|
||||||
|
).all()
|
||||||
|
|
||||||
|
if len(borrowed_items) == 0:
|
||||||
|
print('No borrowed items found.')
|
||||||
|
else:
|
||||||
|
print('Borrowed items:')
|
||||||
|
for item in borrowed_items:
|
||||||
|
print(f'- {item.username} - {item.item.name} - to be delivered by {item.end_time.strftime("%Y-%m-%d")}')
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
queued_items = self.sql_session.scalars(
|
||||||
|
select(BookcaseItemBorrowingQueue)
|
||||||
|
.order_by(BookcaseItemBorrowingQueue.entered_queue_time),
|
||||||
|
).all()
|
||||||
|
|
||||||
|
if len(queued_items) == 0:
|
||||||
|
print('No queued items found.')
|
||||||
|
else:
|
||||||
|
print('Users in queue:')
|
||||||
|
for item in queued_items:
|
||||||
|
print(f'- {item.username} - {item.item.name} - entered queue at {item.entered_queue_time.strftime("%Y-%m-%d")}')
|
||||||
|
|
||||||
|
|
||||||
def _create_bookcase_item(self, isbn: str):
|
def _create_bookcase_item(self, isbn: str):
|
||||||
bookcase_item = create_bookcase_item_from_isbn(isbn, self.sql_session)
|
bookcase_item = create_bookcase_item_from_isbn(isbn, self.sql_session)
|
||||||
if bookcase_item is None:
|
if bookcase_item is None:
|
||||||
|
@ -149,6 +158,8 @@ class WorblehatCli(NumberedCmd):
|
||||||
if (existing_item := self.sql_session.scalars(
|
if (existing_item := self.sql_session.scalars(
|
||||||
select(BookcaseItem)
|
select(BookcaseItem)
|
||||||
.where(BookcaseItem.isbn == isbn)
|
.where(BookcaseItem.isbn == isbn)
|
||||||
|
.join(BookcaseItemBorrowing)
|
||||||
|
.join(BookcaseItemBorrowingQueue)
|
||||||
).one_or_none()) is not None:
|
).one_or_none()) is not None:
|
||||||
print(f'\nFound existing item for isbn "{isbn}"')
|
print(f'\nFound existing item for isbn "{isbn}"')
|
||||||
BookcaseItemCli(
|
BookcaseItemCli(
|
||||||
|
@ -185,11 +196,12 @@ class WorblehatCli(NumberedCmd):
|
||||||
).all()
|
).all()
|
||||||
|
|
||||||
if len(slubberter) == 0:
|
if len(slubberter) == 0:
|
||||||
print('No slubberts found. Yay!')
|
print('No slubberts found. Life is good.')
|
||||||
return
|
return
|
||||||
|
|
||||||
for slubbert in slubberter:
|
for slubbert in slubberter:
|
||||||
print(f'{slubbert.username} - {slubbert.item.name} - {slubbert.end_time.strftime("%Y-%m-%d")}')
|
print('Slubberter:')
|
||||||
|
print(f'- {slubbert.username} - {slubbert.item.name} - {slubbert.end_time.strftime("%Y-%m-%d")}')
|
||||||
|
|
||||||
|
|
||||||
def do_advanced(self, _: str):
|
def do_advanced(self, _: str):
|
||||||
|
@ -225,20 +237,20 @@ class WorblehatCli(NumberedCmd):
|
||||||
'doc': 'Choose / Add item with its ISBN',
|
'doc': 'Choose / Add item with its ISBN',
|
||||||
},
|
},
|
||||||
1: {
|
1: {
|
||||||
'f': do_list_bookcases,
|
|
||||||
'doc': 'List all bookcases',
|
|
||||||
},
|
|
||||||
2: {
|
|
||||||
'f': do_search,
|
'f': do_search,
|
||||||
'doc': 'Search',
|
'doc': 'Search',
|
||||||
},
|
},
|
||||||
3: {
|
2: {
|
||||||
'f': do_show_bookcase,
|
'f': do_show_bookcase,
|
||||||
'doc': 'Show a bookcase, and its items',
|
'doc': 'Show a bookcase, and its items',
|
||||||
},
|
},
|
||||||
|
3: {
|
||||||
|
'f': do_show_borrowed_queued,
|
||||||
|
'doc': 'Show borrowed/queued items',
|
||||||
|
},
|
||||||
4: {
|
4: {
|
||||||
'f': do_show_slabbedasker,
|
'f': do_show_slabbedasker,
|
||||||
'doc': 'Show a slabbedasker, and their wicked ways',
|
'doc': 'Show slabbedasker',
|
||||||
},
|
},
|
||||||
5: {
|
5: {
|
||||||
'f': do_save,
|
'f': do_save,
|
||||||
|
|
|
@ -58,6 +58,7 @@ class InteractiveItemSelector(Cmd):
|
||||||
self.execute_selection = execute_selection
|
self.execute_selection = execute_selection
|
||||||
self.complete_selection = complete_selection
|
self.complete_selection = complete_selection
|
||||||
self.default_item = default
|
self.default_item = default
|
||||||
|
self.result = None
|
||||||
|
|
||||||
if default is not None:
|
if default is not None:
|
||||||
self.prompt = f'Select {cls.__name__} [{default.name}]> '
|
self.prompt = f'Select {cls.__name__} [{default.name}]> '
|
||||||
|
@ -197,6 +198,7 @@ class NumberedItemSelector(NumberedCmd):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.items = items
|
self.items = items
|
||||||
self.stringify = stringify
|
self.stringify = stringify
|
||||||
|
self.result = None
|
||||||
self.funcs = {
|
self.funcs = {
|
||||||
i: {
|
i: {
|
||||||
'f': self._select_item,
|
'f': self._select_item,
|
||||||
|
|
|
@ -91,6 +91,26 @@ class AdvancedOptionsCli(NumberedCmd):
|
||||||
self.sql_session.flush()
|
self.sql_session.flush()
|
||||||
|
|
||||||
|
|
||||||
|
def do_list_bookcases(self, _: str):
|
||||||
|
bookcase_shelfs = self.sql_session.scalars(
|
||||||
|
select(BookcaseShelf)
|
||||||
|
.join(Bookcase)
|
||||||
|
.order_by(
|
||||||
|
Bookcase.name,
|
||||||
|
BookcaseShelf.column,
|
||||||
|
BookcaseShelf.row,
|
||||||
|
)
|
||||||
|
).all()
|
||||||
|
|
||||||
|
bookcase_uid = None
|
||||||
|
for shelf in bookcase_shelfs:
|
||||||
|
if shelf.bookcase.uid != bookcase_uid:
|
||||||
|
print(shelf.bookcase.short_str())
|
||||||
|
bookcase_uid = shelf.bookcase.uid
|
||||||
|
|
||||||
|
print(f' {shelf.short_str()} - {sum(i.amount for i in shelf.items)} items')
|
||||||
|
|
||||||
|
|
||||||
def do_done(self, _: str):
|
def do_done(self, _: str):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -104,6 +124,10 @@ class AdvancedOptionsCli(NumberedCmd):
|
||||||
'f': do_add_bookcase_shelf,
|
'f': do_add_bookcase_shelf,
|
||||||
'doc': 'Add bookcase shelf',
|
'doc': 'Add bookcase shelf',
|
||||||
},
|
},
|
||||||
|
3: {
|
||||||
|
'f': do_list_bookcases,
|
||||||
|
'doc': 'List all bookcases',
|
||||||
|
},
|
||||||
9: {
|
9: {
|
||||||
'f': do_done,
|
'f': do_done,
|
||||||
'doc': 'Done',
|
'doc': 'Done',
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
from textwrap import dedent
|
from textwrap import dedent
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ from sqlalchemy.orm import Session
|
||||||
from worblehat.cli.prompt_utils import (
|
from worblehat.cli.prompt_utils import (
|
||||||
InteractiveItemSelector,
|
InteractiveItemSelector,
|
||||||
NumberedCmd,
|
NumberedCmd,
|
||||||
|
NumberedItemSelector,
|
||||||
format_date,
|
format_date,
|
||||||
prompt_yes_no,
|
prompt_yes_no,
|
||||||
)
|
)
|
||||||
|
@ -22,6 +23,7 @@ from worblehat.services.bookcase_item import (
|
||||||
create_bookcase_item_from_isbn,
|
create_bookcase_item_from_isbn,
|
||||||
is_valid_isbn,
|
is_valid_isbn,
|
||||||
)
|
)
|
||||||
|
from worblehat.services.config import Config
|
||||||
|
|
||||||
from .bookcase_shelf_selector import select_bookcase_shelf
|
from .bookcase_shelf_selector import select_bookcase_shelf
|
||||||
|
|
||||||
|
@ -174,6 +176,50 @@ class BookcaseItemCli(NumberedCmd):
|
||||||
print(f'Successfully delivered the item for {borrowing.username}')
|
print(f'Successfully delivered the item for {borrowing.username}')
|
||||||
|
|
||||||
|
|
||||||
|
def do_extend_borrowing(self, _: str):
|
||||||
|
borrowings = self.sql_session.scalars(
|
||||||
|
select(BookcaseItemBorrowing)
|
||||||
|
.join(BookcaseItem, BookcaseItem.uid == BookcaseItemBorrowing.fk_bookcase_item_uid)
|
||||||
|
.where(BookcaseItem.isbn == self.bookcase_item.isbn)
|
||||||
|
.order_by(BookcaseItemBorrowing.username)
|
||||||
|
).all()
|
||||||
|
|
||||||
|
if len(borrowings) == 0:
|
||||||
|
print('No one seems to have borrowed this item')
|
||||||
|
return
|
||||||
|
|
||||||
|
borrowing_queue = self.sql_session.scalars(
|
||||||
|
select(BookcaseItemBorrowingQueue)
|
||||||
|
.where(
|
||||||
|
BookcaseItemBorrowingQueue.item == self.bookcase_item,
|
||||||
|
BookcaseItemBorrowingQueue.item_became_available_time == None,
|
||||||
|
)
|
||||||
|
.order_by(BookcaseItemBorrowingQueue.entered_queue_time)
|
||||||
|
).all()
|
||||||
|
|
||||||
|
if len(borrowing_queue) != 0:
|
||||||
|
print('Sorry, you cannot extend the borrowing because there are people waiting in the queue')
|
||||||
|
print('Borrowing queue:')
|
||||||
|
for i, b in enumerate(borrowing_queue):
|
||||||
|
print(f' {i + 1}) {b.username}')
|
||||||
|
return
|
||||||
|
|
||||||
|
print('Who are you?')
|
||||||
|
selector = NumberedItemSelector(
|
||||||
|
items = list(borrowings),
|
||||||
|
stringify = lambda b: f'{b.username} - Until {format_date(b.end_time)}',
|
||||||
|
)
|
||||||
|
selector.cmdloop()
|
||||||
|
if selector.result is None:
|
||||||
|
return
|
||||||
|
borrowing = selector.result
|
||||||
|
|
||||||
|
borrowing.end_time = datetime.now() + timedelta(days=int(Config['deadline_daemon.days_before_queue_position_expires']))
|
||||||
|
self.sql_session.flush()
|
||||||
|
|
||||||
|
print(f'Successfully extended the borrowing for {borrowing.username} until {format_date(borrowing.end_time)}')
|
||||||
|
|
||||||
|
|
||||||
def do_done(self, _: str):
|
def do_done(self, _: str):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -188,10 +234,14 @@ class BookcaseItemCli(NumberedCmd):
|
||||||
'doc': 'Deliver',
|
'doc': 'Deliver',
|
||||||
},
|
},
|
||||||
3: {
|
3: {
|
||||||
|
'f': do_extend_borrowing,
|
||||||
|
'doc': 'Extend borrowing',
|
||||||
|
},
|
||||||
|
4: {
|
||||||
'f': do_edit,
|
'f': do_edit,
|
||||||
'doc': 'Edit',
|
'doc': 'Edit',
|
||||||
},
|
},
|
||||||
4: {
|
5: {
|
||||||
'f': do_update_data,
|
'f': do_update_data,
|
||||||
'doc': 'Pull updated data from online databases',
|
'doc': 'Pull updated data from online databases',
|
||||||
},
|
},
|
||||||
|
|
|
@ -13,6 +13,7 @@ class SearchCli(NumberedCmd):
|
||||||
def __init__(self, sql_session: Session):
|
def __init__(self, sql_session: Session):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.sql_session = sql_session
|
self.sql_session = sql_session
|
||||||
|
self.result = None
|
||||||
|
|
||||||
|
|
||||||
def do_search_all(self, _: str):
|
def do_search_all(self, _: str):
|
||||||
|
@ -57,11 +58,11 @@ class SearchCli(NumberedCmd):
|
||||||
elif len(author) == 1:
|
elif len(author) == 1:
|
||||||
selected_author = author[0]
|
selected_author = author[0]
|
||||||
print('Found author:')
|
print('Found author:')
|
||||||
print(f" {selected_author.name} ({sum(item.amount for item in selected_author.books)} items)")
|
print(f" {selected_author.name} ({sum(item.amount for item in selected_author.items)} items)")
|
||||||
else:
|
else:
|
||||||
selector = NumberedItemSelector(
|
selector = NumberedItemSelector(
|
||||||
items = author,
|
items = author,
|
||||||
stringify = lambda author: f"{author.name} ({sum(item.amount for item in author.books)} items)",
|
stringify = lambda author: f"{author.name} ({sum(item.amount for item in author.items)} items)",
|
||||||
)
|
)
|
||||||
selector.cmdloop()
|
selector.cmdloop()
|
||||||
if selector.result is None:
|
if selector.result is None:
|
||||||
|
@ -69,7 +70,7 @@ class SearchCli(NumberedCmd):
|
||||||
selected_author = selector.result
|
selected_author = selector.result
|
||||||
|
|
||||||
selector = NumberedItemSelector(
|
selector = NumberedItemSelector(
|
||||||
items = selected_author.books,
|
items = list(selected_author.items),
|
||||||
stringify = lambda item: f"{item.name} ({item.isbn})",
|
stringify = lambda item: f"{item.name} ({item.isbn})",
|
||||||
)
|
)
|
||||||
selector.cmdloop()
|
selector.cmdloop()
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import csv
|
import csv
|
||||||
|
from datetime import datetime, timedelta
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
@ -6,7 +7,11 @@ from sqlalchemy.orm import Session
|
||||||
from worblehat.flaskapp.database import db
|
from worblehat.flaskapp.database import db
|
||||||
|
|
||||||
from ..models import (
|
from ..models import (
|
||||||
|
Author,
|
||||||
Bookcase,
|
Bookcase,
|
||||||
|
BookcaseItem,
|
||||||
|
BookcaseItemBorrowing,
|
||||||
|
BookcaseItemBorrowingQueue,
|
||||||
BookcaseShelf,
|
BookcaseShelf,
|
||||||
Language,
|
Language,
|
||||||
MediaType,
|
MediaType,
|
||||||
|
@ -117,6 +122,100 @@ def seed_data(sql_session: Session = db.session):
|
||||||
BookcaseShelf(row=0, column=4, bookcase=bookcases[4], description="Religion"),
|
BookcaseShelf(row=0, column=4, bookcase=bookcases[4], description="Religion"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
authors = [
|
||||||
|
Author(name="Donald E. Knuth"),
|
||||||
|
Author(name="J.K. Rowling"),
|
||||||
|
Author(name="J.R.R. Tolkien"),
|
||||||
|
Author(name="George R.R. Martin"),
|
||||||
|
Author(name="Stephen King"),
|
||||||
|
Author(name="Agatha Christie"),
|
||||||
|
]
|
||||||
|
|
||||||
|
book1 = BookcaseItem(
|
||||||
|
name = "The Art of Computer Programming",
|
||||||
|
isbn = "9780201896831",
|
||||||
|
)
|
||||||
|
book1.authors.add(authors[0])
|
||||||
|
book1.media_type = media_types[0]
|
||||||
|
book1.shelf = shelfs[59]
|
||||||
|
|
||||||
|
book2 = BookcaseItem(
|
||||||
|
name = "Harry Potter and the Philosopher's Stone",
|
||||||
|
isbn = "9780747532743",
|
||||||
|
)
|
||||||
|
book2.authors.add(authors[1])
|
||||||
|
book2.media_type = media_types[0]
|
||||||
|
book2.shelf = shelfs[-1]
|
||||||
|
|
||||||
|
book_owned_by_other_user = BookcaseItem(
|
||||||
|
name = "Book owned by other user",
|
||||||
|
isbn = "9780747532744",
|
||||||
|
)
|
||||||
|
|
||||||
|
book_owned_by_other_user.owner = "other_user"
|
||||||
|
book_owned_by_other_user.authors.add(authors[4])
|
||||||
|
book_owned_by_other_user.media_type = media_types[0]
|
||||||
|
book_owned_by_other_user.shelf = shelfs[-2]
|
||||||
|
|
||||||
|
borrowed_book_more_available = BookcaseItem(
|
||||||
|
name = "Borrowed book with more available",
|
||||||
|
isbn = "9780747532745",
|
||||||
|
)
|
||||||
|
borrowed_book_more_available.authors.add(authors[5])
|
||||||
|
borrowed_book_more_available.media_type = media_types[0]
|
||||||
|
borrowed_book_more_available.shelf = shelfs[-3]
|
||||||
|
borrowed_book_more_available.amount = 2
|
||||||
|
|
||||||
|
borrowed_book_no_more_available = BookcaseItem(
|
||||||
|
name = "Borrowed book with no more available",
|
||||||
|
isbn = "9780747532746",
|
||||||
|
)
|
||||||
|
borrowed_book_no_more_available.authors.add(authors[5])
|
||||||
|
borrowed_book_no_more_available.media_type = media_types[0]
|
||||||
|
borrowed_book_no_more_available.shelf = shelfs[-3]
|
||||||
|
|
||||||
|
borrowed_book_people_in_queue = BookcaseItem(
|
||||||
|
name = "Borrowed book with people in queue",
|
||||||
|
isbn = "9780747532747",
|
||||||
|
)
|
||||||
|
borrowed_book_people_in_queue.authors.add(authors[5])
|
||||||
|
borrowed_book_people_in_queue.media_type = media_types[0]
|
||||||
|
borrowed_book_people_in_queue.shelf = shelfs[-3]
|
||||||
|
|
||||||
|
borrowed_book_by_slabbedask = BookcaseItem(
|
||||||
|
name = "Borrowed book by slabbedask",
|
||||||
|
isbn = "9780747532748",
|
||||||
|
)
|
||||||
|
borrowed_book_by_slabbedask.authors.add(authors[5])
|
||||||
|
borrowed_book_by_slabbedask.media_type = media_types[0]
|
||||||
|
borrowed_book_by_slabbedask.shelf = shelfs[-3]
|
||||||
|
|
||||||
|
books = [
|
||||||
|
book1,
|
||||||
|
book2,
|
||||||
|
book_owned_by_other_user,
|
||||||
|
borrowed_book_more_available,
|
||||||
|
borrowed_book_no_more_available,
|
||||||
|
borrowed_book_people_in_queue,
|
||||||
|
]
|
||||||
|
|
||||||
|
slabbedask_borrowing = BookcaseItemBorrowing(
|
||||||
|
username="slabbedask",
|
||||||
|
item=borrowed_book_more_available,
|
||||||
|
)
|
||||||
|
slabbedask_borrowing.end_time = datetime.now() - timedelta(days=1)
|
||||||
|
|
||||||
|
borrowings = [
|
||||||
|
BookcaseItemBorrowing(username="user", item=borrowed_book_more_available),
|
||||||
|
BookcaseItemBorrowing(username="user", item=borrowed_book_no_more_available),
|
||||||
|
BookcaseItemBorrowing(username="user", item=borrowed_book_people_in_queue),
|
||||||
|
slabbedask_borrowing,
|
||||||
|
]
|
||||||
|
|
||||||
|
queue = [
|
||||||
|
BookcaseItemBorrowingQueue(username="user", item=borrowed_book_people_in_queue),
|
||||||
|
]
|
||||||
|
|
||||||
with open(Path(__file__).parent.parent.parent / 'data' / 'iso639_1.csv') as f:
|
with open(Path(__file__).parent.parent.parent / 'data' / 'iso639_1.csv') as f:
|
||||||
reader = csv.reader(f)
|
reader = csv.reader(f)
|
||||||
languages = [Language(name, code) for (code, name) in reader]
|
languages = [Language(name, code) for (code, name) in reader]
|
||||||
|
@ -125,5 +224,9 @@ def seed_data(sql_session: Session = db.session):
|
||||||
sql_session.add_all(bookcases)
|
sql_session.add_all(bookcases)
|
||||||
sql_session.add_all(shelfs)
|
sql_session.add_all(shelfs)
|
||||||
sql_session.add_all(languages)
|
sql_session.add_all(languages)
|
||||||
|
sql_session.add_all(authors)
|
||||||
|
sql_session.add_all(books)
|
||||||
|
sql_session.add_all(borrowings)
|
||||||
|
sql_session.add_all(queue)
|
||||||
sql_session.commit()
|
sql_session.commit()
|
||||||
print("Added test media types, bookcases and shelfs.")
|
print("Added test media types, bookcases and shelfs.")
|
Loading…
Reference in New Issue