diff --git a/README.md b/README.md index 9134834df5f52e225585d15da6736246dfa8cd6b..ae38611452e0cb2543250ffa398f5cf09e181de9 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,8 @@ This repo contains all the custom code related to the loan management in LinkAhead. It is to be checked out as a custom-directory and needs to be specified in your profile.yml. + + +## Integration tests +Run `pytest .` in the integration tests folder + diff --git a/integrationtests/basic_test.py b/integrationtests/basic_test.py index a4becb2c39664e22364cd122e8f9e877c0a2ff8c..511c1876987a428a660cbb6f3bb79dd300b4d677 100644 --- a/integrationtests/basic_test.py +++ b/integrationtests/basic_test.py @@ -26,26 +26,40 @@ import linkahead as db import re from tempfile import NamedTemporaryFile from linkahead.utils.server_side_scripting import run_server_side_script -from box_loan import (BORROWER, BOX, COMMENT, DESTINATION, EXHAUST_CONTENTS, - EXPECTED_RETURN, F_BOX, F_COMMENT, F_DESTINATION,PERSON, - F_EMAIL, F_EXHAUST_CONTENTS, F_EXPECTED_RETURN_DATE, EMAIL, - F_FIRST_NAME, F_LAST_NAME, FIRST_NAME, LAST_NAME, LOAN, LOCATION, - LOAN_REQUESTED, assert_date_in_future, - assert_key_in_data, get_box, insert_or_update_person, main, +from box_loan import (BORROWER, BOX, COMMENT, DESTINATION, EXHAUST_CONTENTS, LENT, + F_CURRENT_LOCATION, + EXPECTED_RETURN, F_BOX, F_COMMENT, F_DESTINATION,PERSON, LOAN_ACCEPTED, + F_EMAIL, F_EXHAUST_CONTENTS, F_EXPECTED_RETURN_DATE, EMAIL, F_LOAN, + F_FIRST_NAME, F_LAST_NAME, FIRST_NAME, LAST_NAME, LOAN, LOCATION, RETURNED, + RETURN_ACCEPTED, + LOAN_REQUESTED, assert_date_in_future, CONTENT, RETURNLOCATION, + assert_key_in_data, get_box, insert_or_update_person, main, RETURN_REQUESTED, send_loan_request_mail) TESTLOANCOMMENT = 'This is a test' +TESTRETURNCOMMENT = 'This is a return test' TESTBOXNUMBER = '0123 TEST' TESTDESTINATION = 'TEST DEST' +TESTCURRENTDESTINATION = 'TEST CUR DEST' TESTBORROWEREMAIL = 'test@example.com' +TESTRETURNDATE="2025-03-04" TESTFN = "Alice" TESTLN = "Wunderland" + +def save_dict_to_jsonfile(data): + tmp = NamedTemporaryFile(delete=False, suffix=".json") + tmp.close() + with open(tmp.name, "w") as fi: + json.dump(data, fi) + return tmp.name + def delete_stuff(): to_be_deleted = db.Container() to_be_deleted.extend(db.execute_query(f"FIND loan with {COMMENT.name}='{TESTLOANCOMMENT}'")) to_be_deleted.extend(db.execute_query(f"FIND '{TESTDESTINATION}'")) + to_be_deleted.extend(db.execute_query(f"FIND '{TESTCURRENTDESTINATION}'")) to_be_deleted.extend(db.execute_query(f"FIND '{TESTBOXNUMBER}'")) to_be_deleted.extend(db.execute_query(f"FIND person with {EMAIL.name}='{TESTBORROWEREMAIL}'")) if len(to_be_deleted)>0: @@ -56,6 +70,7 @@ def prepare(): delete_stuff() db.Record(name=TESTBOXNUMBER).add_parent(BOX.name).insert() db.Record(name=TESTDESTINATION).add_parent(LOCATION.name).insert() + db.Record(name=TESTCURRENTDESTINATION).add_parent(LOCATION.name).insert() (db.Record().add_parent(PERSON.name).add_property(EMAIL.name, TESTBORROWEREMAIL) .add_property(FIRST_NAME.name, TESTFN) .add_property(LAST_NAME.name, TESTLN).insert()) @@ -64,6 +79,8 @@ def prepare(): def test_request_loan(): + + ##### request loan ##### data = {} data[F_EXHAUST_CONTENTS] = False data[F_EXPECTED_RETURN_DATE]= "2042-02-02" @@ -74,15 +91,10 @@ def test_request_loan(): data[F_LAST_NAME]=TESTLN data[F_FIRST_NAME]=TESTFN - fi = NamedTemporaryFile(delete=False, suffix=".json") - fi.close() - with open(fi.name, "w") as f: - json.dump(data, f) - response = run_server_side_script("loan_management/request_loan.py", #"pos0", #option1="val1", - files={"-p0": fi.name}, + files={"-p0": save_dict_to_jsonfile(data)}, **{"auth-token":db.get_connection()._authenticator.auth_token}) assert response.stderr is None assert response.code == 0 @@ -94,3 +106,87 @@ def test_request_loan(): assert loan.get_property(f"{EXPECTED_RETURN.name}").value == data[F_EXPECTED_RETURN_DATE] assert loan.get_property(f"{EXHAUST_CONTENTS.name}").value == data[F_EXHAUST_CONTENTS] assert loan.get_property(f"{DESTINATION.name}").value == data[F_DESTINATION] + assert loan.get_property(f"{LOAN_ACCEPTED.name}") is None + assert loan.get_property(f"{LENT.name}") is None + + ##### accept loan ##### + data = {} + data[F_LOAN] = loan.id + response = run_server_side_script("loan_management/accept_loan_request.py", + #"pos0", + #option1="val1", + files={"-p0": save_dict_to_jsonfile(data)}, + **{"auth-token":db.get_connection()._authenticator.auth_token}) + assert response.stderr is None + assert response.code == 0 + loan = db.execute_query(f"FIND loan with {COMMENT.name}='{TESTLOANCOMMENT}'", unique=True) + assert loan.get_property(f"{LOAN_ACCEPTED.name}").value.startswith("20") + assert loan.get_property(f"{LENT.name}") is None + assert loan.get_property(f"{RETURN_REQUESTED.name}") is None + + ##### confirm loan ##### + data = {} + data[F_LOAN] = loan.id + response = run_server_side_script("loan_management/confirm_loan.py", + #"pos0", + #option1="val1", + files={"-p0": save_dict_to_jsonfile(data)}, + **{"auth-token":db.get_connection()._authenticator.auth_token}) + assert response.stderr is None + assert response.code == 0 + loan = db.execute_query(f"FIND loan with {COMMENT.name}='{TESTLOANCOMMENT}'", unique=True) + assert loan.get_property(f"{LENT.name}").value.startswith("20") + + ##### request return ##### + data = {} + data[F_LOAN] = loan.id + # TODO: this is writen in the content field. Change name? + data[F_COMMENT] = TESTRETURNCOMMENT + # TODO: this is written in RETURNLOCATION. Change name? + data[F_CURRENT_LOCATION]=db.utils.get_entity.get_entity_by_name(TESTCURRENTDESTINATION).id + data[F_EXPECTED_RETURN_DATE] = TESTRETURNDATE + data[F_EMAIL]=TESTBORROWEREMAIL + data[F_LAST_NAME]=TESTLN + data[F_FIRST_NAME]=TESTFN + response = run_server_side_script("loan_management/request_return.py", + #"pos0", + #option1="val1", + files={"-p0": save_dict_to_jsonfile(data)}, + **{"auth-token":db.get_connection()._authenticator.auth_token}) + assert response.stderr is None + assert response.code == 0 + loan = db.execute_query(f"FIND loan with {COMMENT.name}='{TESTLOANCOMMENT}'", unique=True) + assert loan.get_property(f"{LOAN_ACCEPTED.name}").value.startswith("20") + assert loan.get_property(f"{CONTENT.name}").value == TESTRETURNCOMMENT + assert loan.get_property(f"{EXPECTED_RETURN.name}").value == TESTRETURNDATE + assert loan.get_property(f"{RETURNLOCATION.name}").value == db.utils.get_entity.get_entity_by_name(TESTCURRENTDESTINATION).id + assert loan.get_property(f"{RETURN_REQUESTED.name}").value.startswith("20") + assert loan.get_property(f"{RETURN_ACCEPTED.name}") is None + # TODO test change of borrower + + # accept return + data = {} + data[F_LOAN] = loan.id + response = run_server_side_script("loan_management/accept_return_request.py", + #"pos0", + #option1="val1", + files={"-p0": save_dict_to_jsonfile(data)}, + **{"auth-token":db.get_connection()._authenticator.auth_token}) + assert response.stderr is None + assert response.code == 0 + loan = db.execute_query(f"FIND loan with {COMMENT.name}='{TESTLOANCOMMENT}'", unique=True) + assert loan.get_property(f"{RETURN_ACCEPTED.name}").value.startswith("20") + assert loan.get_property(f"{RETURNED.name}") is None + + # manual return + data = {} + data[F_LOAN] = loan.id + response = run_server_side_script("loan_management/manual_return.py", + #"pos0", + #option1="val1", + files={"-p0": save_dict_to_jsonfile(data)}, + **{"auth-token":db.get_connection()._authenticator.auth_token}) + assert response.stderr is None + assert response.code == 0 + loan = db.execute_query(f"FIND loan with {COMMENT.name}='{TESTLOANCOMMENT}'", unique=True) + assert loan.get_property(f"{RETURNED.name}").value.startswith("20") diff --git a/loan-custom/caosdb-server/scripting/bin/loan_management/box_loan.py b/loan-custom/caosdb-server/scripting/bin/loan_management/box_loan.py index 227b0e5c7b59a806fe23110717d7039069862b81..7027e98e969a688bbec139ba5a6f5bbef0ef1f1c 100644 --- a/loan-custom/caosdb-server/scripting/bin/loan_management/box_loan.py +++ b/loan-custom/caosdb-server/scripting/bin/loan_management/box_loan.py @@ -206,10 +206,10 @@ def get_box(box): return get_record_by_id(BOX.name, box) -def get_loan(loan): +def get_loan(loan_id): """ Retrieve a loan record by id. """ - return get_record_by_id(LOAN.name, loan) + return get_record_by_id(LOAN.name, loan_id) def get_loan_state(loan): diff --git a/loan-custom/caosdb-server/scripting/bin/loan_management/manual_return.py b/loan-custom/caosdb-server/scripting/bin/loan_management/manual_return.py index 9aa7e83c3f3210ad719d41a0b1aa00896e7e5aca..1f6e8e634b6c45198373ea8b1cd08f0613630cf4 100755 --- a/loan-custom/caosdb-server/scripting/bin/loan_management/manual_return.py +++ b/loan-custom/caosdb-server/scripting/bin/loan_management/manual_return.py @@ -61,6 +61,7 @@ def _manual_return(data): assert_loan_state(loan, S_RETURN_ACCEPTED) # This changes the state from "return_accepted" to "returned". + # TODO why twice???? set_property(loan, RETURNED, get_timestamp()) set_property(loan, RETURNED, get_timestamp()) diff --git a/loan-custom/caosdb-server/scripting/bin/test/loan_management/test_box_loan.py b/loan-custom/caosdb-server/scripting/bin/test/loan_management/test_box_loan.py index 6dfb9ab7759bc1b2b44477ee050bd711a957f01d..ff40b78cbe29cec66699b9513bfd48ffda43ce63 100644 --- a/loan-custom/caosdb-server/scripting/bin/test/loan_management/test_box_loan.py +++ b/loan-custom/caosdb-server/scripting/bin/test/loan_management/test_box_loan.py @@ -17,7 +17,7 @@ def test_caller(): args = [get_data_example()] def test_func(data): - assert data["box"] == [2345], "should contain the data from json" + assert data["box"] == 2345, "should contain the data from json" return 1337 assert _caller(test_func, args) == 1337 diff --git a/notes b/notes index 313cea340989b90d16db5cc85e5d0dcc604694f3..d59de74242e0e3c7a4f372064a06f3577ae2fc20 100644 --- a/notes +++ b/notes @@ -13,3 +13,6 @@ Soll die Email Adress wirklich on the fly mit geändert werden? Alternative Introduce a single loan.py file with argparse (`loan.py accept a b c`, etc) Person without first or lastname seem to be a problem. + + +Warum wird der Borrower beim Return verändert? Nur anbieten email anzupassen?