Skip to content

Commit

Permalink
sponsorship metrics dashboard
Browse files Browse the repository at this point in the history
  • Loading branch information
mekarpeles committed Nov 8, 2019
1 parent 1aa0812 commit 4d62dbd
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 3 deletions.
51 changes: 48 additions & 3 deletions openlibrary/core/sponsorships.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ def eligibility_check(edition):
return False

logger = logging.getLogger("openlibrary.sponsorship")

SETUP_COST_CENTS = 300
PAGE_COST_CENTS = 12

def get_sponsored_editions(user):
"""
Expand Down Expand Up @@ -137,8 +138,6 @@ def qualifies_for_sponsorship(edition):
if dwwi:
bwb_price = get_betterworldbooks_metadata(edition.isbn).get('price_amt')
if bwb_price:
SETUP_COST_CENTS = 300
PAGE_COST_CENTS = 12
num_pages = int(edition_data['number_of_pages'])
scan_price_cents = SETUP_COST_CENTS + (PAGE_COST_CENTS * num_pages)
book_cost_cents = int(float(bwb_price) * 100)
Expand Down Expand Up @@ -171,3 +170,49 @@ def qualifies_for_sponsorship(edition):
})
})
return resp

def summary():
from internetarchive import search_items
params = {'page': 1, 'rows': 500}
fields = ['identifier','est_book_price','est_scan_price', 'scan_price',
'book_price', 'repub_state', 'imagecount', 'title']
q = 'collection:openlibraryscanningteam'
config = dict(general=dict(secure=False))
s = search_items(q, fields=fields, params=params, config=config)
items = list(s)
statuses = {}
for i, book in enumerate(items):
if not book.get('book_price'):
items[i]['status'] = 0
statuses[0] = statuses.get(0, 1) + 1
elif int(book.get('repub_state', -1)) == -1:
items[i]['status'] = 1
statuses[1] = statuses.get(1, 1) + 1
elif int(book.get('repub_state', 0)) < 14:
items[i]['status'] = 2
statuses[2] = statuses.get(2, 0) + 1
else:
items[i]['status'] = 3
statuses[3] = statuses.get(3, 0) + 1

total_pages_scanned = sum(int(i.get('imagecount', 0)) for i in items)
total_unscanned_books = len([i for i in items if not i.get('imagecount', 0)])
total_cost_cents = sum(int(i.get('est_book_price', 0)) + int(i.get('est_scan_price', 0))
for i in items)
book_cost_cents = sum(int(i.get('book_price', 0)) for i in items)
est_book_cost_cents = sum(int(i.get('est_book_price', 0)) for i in items)
scan_cost_cents = (PAGE_COST_CENTS * total_pages_scanned) + (SETUP_COST_CENTS * len(items))
est_scan_cost_cents = sum(int(i.get('est_scan_price', 0)) for i in items)
return {
'books': items,
'statuses': statuses,
'total_pages_scanned': total_pages_scanned,
'total_unscanned_books': total_unscanned_books,
'total_cost_cents': total_cost_cents,
'book_cost_cents': book_cost_cents,
'est_book_cost_cents': est_book_cost_cents,
'delta_book_cost_cents': est_book_cost_cents - book_cost_cents,
'scan_cost_cents': scan_cost_cents,
'est_scan_cost_cents': est_scan_cost_cents,
'delta_scan_cost_cents': est_scan_cost_cents - scan_cost_cents,
}
1 change: 1 addition & 0 deletions openlibrary/plugins/openlibrary/home.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ def get_homepage():

def get_cached_homepage():
five_minutes = 5 * dateutil.MINUTE_SECS
return get_homepage()
return cache.memcache_memoize(
get_homepage, "home.homepage", timeout=five_minutes)()

Expand Down
142 changes: 142 additions & 0 deletions openlibrary/templates/admin/sponsorship.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
$def with (summary)

$ _x = ctx.setdefault('bodyid', 'admin')
$ _x = ctx.setdefault('usergroup', 'admin')

$ statuses = {0: 'Needs purchasing', 1: 'Needs digitizing', 2: 'Needs republishing', 3: 'Complete'}

<style type="text/css">
.status--0 { color: red; }
.status--1 { color: orange; }
.status--2 { color: blue; }
.status--3 { color: green; }
.earnings--profit { color: green; }
.earnings--loss { color: red; }
.table th {
background-color: #fafafa;
padding: 5px;
border-bottom: 1px solid #ccc;
text-transform: uppercase;
font-size: .65em;
font-weight: bold;
}
</style>

<div id="contentHead">
<h1>Book Sponsorship</h1>
</div>

<div id="contentBody">
<p>We've sponsored <strong>$len(summary['books'])</strong> books</p>

<table class="table">
<tr>
$for status in range(4):
<th>$statuses[status]</th>
<td>$summary['statuses'].get(status, 0)</td>
</tr>
</table>

<hr>

<table class="table">
<tr>
<th>Internet Archive Revenue</th>
<td class="earnings--profit">\$$('{:,.2f}'.format(summary['total_cost_cents'] / 100.))</td>
<th>Better World Books Revenue</th>
<td class="earnings--profit">\$$('{:,.2f}'.format(summary['book_cost_cents'] / 100.))</td>
</tr>
<tr>
<th>Book Costs</th>
<td>\$$('{:,.2f}'.format(summary['book_cost_cents'] / 100.))</td>
<th>Est. Book Costs</th>
<td>\$$('{:,.2f}'.format(summary['est_book_cost_cents'] / 100.))</td>
<th>Δ Book Costs</th>
<td class="earnings--$('loss' if summary['delta_book_cost_cents'] < 0 else 'profit')">\$$('{:,.2f}'.format(summary['delta_book_cost_cents'] / 100.))</td>
</tr>
<tr>
<th>Scanning Costs</th>
<td>\$$('{:,.2f}'.format(summary['scan_cost_cents'] / 100.))</td>
<th>Est. Scanning Costs</th>
<td>\$$('{:,.2f}'.format(summary['est_scan_cost_cents'] / 100.))</td>
<th>Δ Scanning Costs</th>
<td class="earnings--$('loss' if summary['delta_scan_cost_cents'] < 0 else 'profit')">\$$('{:,.2f}'.format(summary['delta_scan_cost_cents'] / 100.))</td>
</tr>
<tr>
<th>Profit/Loss</th>
$ profit_loss = (summary['total_cost_cents'] - summary['book_cost_cents'] - summary['scan_cost_cents'])
<td class="earnings--$('loss' if profit_loss < 0 else 'profit')">\$$(profit_loss / 100.)</td>
</tr>
</table>

<hr>

<table class="table">
<tr>
<th>Total Unscanned Books</th>
<td>$summary['total_unscanned_books']</td>
</tr>
<tr>
<th>Average Scan Cost</th>
$ num_total_books = len(summary['books'])
$ num_scanned_books = num_total_books - summary['total_unscanned_books']
$ avg_scan_cost = summary['scan_cost_cents'] / num_scanned_books
<td>\$$('{:,.2f}'.format(avg_scan_cost / 100.))</td>
</tr>
<tr>
<th>Est. Remaining Scanning Liability</th>
$ scan_cost_liability = avg_scan_cost * summary['total_unscanned_books']
<td class="earnings--$('loss' if scan_cost_liability > 0 else 'profit')">\$$('{:,.2f}'.format(scan_cost_liability / 100.))</td>
</tr>
<tr>
<th>Projected Profit/Loss</th>
$ adj_profit_loss = profit_loss - scan_cost_liability
<td class="earnings--$('loss' if adj_profit_loss < 0 else 'profit')">\$$(adj_profit_loss / 100.)</td>
</tr>
</table>

<hr>

<table class="table">
<thead>
<tr>
<th>#</th>
<th>Cover</th>
<th>ID</th>
<th>Title</th>
<th>Status</th>
</tr>
</thead>
<tbody>
$ i = 1
$for status in range(4):
$for book in summary['books']:
$if book.get('status') == status:
<tr>
<td>
<div class="id--$i"></div>
$i
</td>
<td>
<div class="cover--$i"></div>
<img width="50" height="75"
src="https://archive.org/services/img/$book['identifier']">
</td>
<td>
<div class="$book['identifier']"></div>
<a href="https://archive.org/details/$book['identifier']">$book['identifier']</a>
</td>
<td>
<div class="$book['title']"></div>
<a href="https://archive.org/details/$book['identifier']">$book['title']</a>
</td>
<td class="status--$(book.get('status'))">
<div class="$(book.get('status'))"></div>
$statuses[book.get('status')]
</td>
</tr>
$ i += 1
</tbody>
</table>

</div>
8 changes: 8 additions & 0 deletions openlibrary/views/loanstats.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,14 @@ class lending_stats(app.view):
def GET(self, key, value):
raise web.seeother("/")

class sponsorship_stats(app.view):
path = '/stats/sponsorship'

def GET(self):
from openlibrary.core.sponsorships import summary
return app.render_template("admin/sponsorship", summary())



class readinglog_stats(app.view):
path = "/stats/readinglog"
Expand Down

0 comments on commit 4d62dbd

Please sign in to comment.