---
# System prepended metadata

title: MailBoox design spec

---

# MailBoox design spec

# Application Synopsis
Enter the books that are in your bookshelf in order to make them visible to your community. Users can request to borrow books from each other and if possible the owner can put the book in his/her Mailbox in order to make it easily available for the borrower to pick-up. 


# Entry relationships schema

## Books zome
```mermaid
graph TD
  subgraph Books zome
    subgraph anchors
        all_groups
        all_groups 
        all_groups 
        all_genres
        all_genres 
    end
    subgraph Groups
        all_groups --> Alice_appartment_building
        all_groups --> Friends_of_Bob    
    end
    subgraph Genre
      all_genres --> Sci-fi 
      all_genres --> Anthropology 
    end
    subgraph Books
      Sci-fi --> Asimovs_foundation
      Anthropology --> Debt
    end
    subgraph Players
      Alice -.book_owner.-> Asimovs_foundation
      Asimovs_foundation --> Alice
      Bob -.book_owner.-> Debt
      Debt --> Bob
      Alice -.part_of_group.-> Alice_appartment_building
      Alice_appartment_building --> Alice
      Bob -.part_of_group.-> Friends_of_Bob
      Friends_of_Bob --> Bob
      
    end

  end
```

## Loans zome


```mermaid
graph TD
  subgraph Loans zome
     subgraph anchors
      all_loans
    end
    subgraph Loan_requests
      Loan_request1
      Loan_request2
    end
    subgraph Loans
      Loan_request1 -.informs.-> Loan1 
      Loan_request2 -.informs.-> Loan2
      all_loans --> Loan1
      all_loans --> Loan2
    end
    subgraph agents
        Loan1 -.lender.-> Alice
        Loan1 -.borrower.-> Bob
    end
    subgraph books
        Loan1 -.item_borrowed.- Book1
        Loan2 -.item_borrowed.- Book2
    end
  end
```

# Zome designs

## Books zome
```rust
#[derive(Serialize, Deserialize, Debug, DefaultJson)]
struct Book {
    name: String,
    author: String,
    genre: String,
    blurb: String,
    isbn: String,
    book_owner: Address
}

create_book: {
    inputs: |book: Book|,
    outputs: |result: ZomeApiResult<Address>|,
    handler: handle_create_book
}
get_book: {
    inputs: |address: Address|,
    outputs: |result: ZomeApiResult<GetEntryResult>|, // Another change request from guillem, this GetEntryResult type can be returned by using https://developer.holochain.org/api/latest/hdk/api/fn.get_entry_result.html
    handler: handle_get_book
}

get_my_books: {
    inputs: | |,
    outputs: |result: ZomeApiResult<Vec<ZomeApiResult<GetEntryResult>>>|,
    handler: handle_get_books
}

get_owner: {
    inputs: |address: Address|,
    outputs: |result: ZomeApiResult<Address>|,
    handler: handle_get_owner
}
```


## Loans zome


```rust
#[derive(Serialize, Deserialize, Debug, DefaultJson)]
struct LoanRequest {
    item_address: Address,
    borrower_address: Address,
    created_at: i64,
}

#[derive(Serialize, Deserialize, Debug, DefaultJson)]
struct Loan {
    item_address: Address,
    borrower_address: Option<Address>,
    started_at: Option<i64>
    finished_at: Option<i64>
    comment: Option<String>
    return_by: Option<i64>
}

// Create a loan request entry
// Called by the person who wants to borrow
request_to_borrow(item_address: Address, created_at: i64): -> ZomeApiResult<Address>


get_my_loan_requests() -> ZomeApiResult<Vec<ZomeApiResult<GetEntryResult>>>

// This assumes that the books zome has a way of getting all the items of an owner
get_item_loan_requests(item_address: Address) -> ZomeApiResult<Vec<ZomeApiResult<GetEntryResult>>>

// Create a loan entry
// Called by the person who owns the item
// Steps
// 1. Get the loan request
// 2. Get the loan entry
// 3. If the loan entry does not exist, create it only with item_address
// 4. Update the loan entry with the new information
// 5. Create a link from the borrower agent address to the address of the updated entry (not the original entry address)
// 6. Delete the loan request
create_loan(loan_request_address: Address, started_at: i64, return_by: i64) -> ZomeApiResult<Address>

// Remove a loan request
// Called by the person who owns the item
decline_loan(loan_request_address: Address) -> ZomeApiResult<()>

get_loan_history(item_address: Address) -> ZomeApiResult<Option<EntryHistory>>

get_loan_status(item_address: Address) -> ZomeApiResult<Option<Entry>>

// Has to be called by the borrower first and the by the lender
// If double signature, remove link between borrower agent address and loan
finish_loan(item_address: Address, finished_at: i64, comment: Option<String>) -> ZomeApiResult<()>

// Retrieve the loans throught the borrower->loans links
get_my_active_loans() -> ZomeApiResult<Vec<ZomeApiResult<GetEntryResult>>>
```


## Further implementations


```rust
#[derive(Serialize, Deserialize, Debug, DefaultJson)]
struct Collection {
    name: String,
}

#[derive(Serialize, Deserialize, Debug, DefaultJson)]
struct User {
    name: String,
    street: String,
    zip: String,
    city: String,
    country: String,
}

get_my_address: {
                inputs: | |,
                outputs: |result: JsonString|,
                handler: handle_get_my_address
            }
            
            create_collection: {
                inputs: |name: String|,
                outputs: |result: JsonString|,
                handler: handle_create_collection
            }
            create_user: {
                inputs: |name: String, street: String, zip: String, city: String, country: String|,
                outputs: |result: JsonString|,
                handler: handle_create_user
            }
            get_user_data: {
                inputs: |address: Address|,
                outputs: |result: JsonString|,
                handler: handle_get_user_data
            }
            add_book_to_collection: {
                inputs: |book_address: Address, collection_address: Address|,
                outputs: |result: JsonString|,
                handler: handle_add_book_to_collection
            }
            get_books_in_collection: {
                inputs: |collection_address: Address, tag: String|,
                outputs: |result: JsonString|,
                handler: handle_get_books_in_collection
            }
            get_collections_book_is_in: {
                inputs: |book_address: Address, tag: String|,
                outputs: |result: JsonString|,
                handler: handle_get_collections_book_is_in
            }
            //retrieve all books linked to the anchor shelf
            get_books: {
                inputs: |shelf_address: Address, tag: String|,
                outputs: |result: JsonString|,
                handler: handle_get_books
            }
            get_owners: {
                inputs: |book_address: Address, tag: String|,
                outputs: |result: JsonString|,
                handler: handle_get_owners
            }
            request_to_borrow: {
                inputs: |borrower_address: Address, book_address: Address|,
                outputs: |result: JsonString|,
                handler: handle_request_to_borrow
            }
            get_requests_by_user: {
                inputs: |borrower_address: Address|,
                outputs: |result: JsonString|,
                handler: handle_get_requests_by_user
            }
            get_book_requests: {
                inputs: |book_address: Address|,
                outputs: |result: JsonString|,
                handler: handle_get_book_requests
            }
            create_loan: {
                inputs: |book_address: Address, borrower_address: Address, return_by: String|,
                outputs: |result: JsonString|,
                handler: handle_create_loan
            }

```


