#!/usr/bin/env python import glob import os import sys import time import datetime import msvcrt # This script automatically generates a short table of the number of apps # and total sales amounts from Apple's daily and weekly reports. It can # be operated by simply double-clicking it or from a command line. By default # with no arguments, it scans for daily reports from the day before current # date, or last week's report when doing a weekly summary. A specific date # can be specified using command-line arguments. # Command line arguments: # r.py [d|w] [date] # [d|w] - (optional) specifies whether to do daily or weekly reports. # [date] - (optional) specifies the date to use to look for reports. For # weekly reports, the last Sunday on or before this date will be # found. # These are the control variables. The primary report currency # specifies specifies the currency to use for items in the report; # the fallback currency specifies what currency to use if there # have been no sales in the primary currency. Note that in general, # each product needs to be sold at least once in the primary currency # for the script to determine its price. # # REPORTS_PREFIX specifies the prefix for your daily reports. The # weekly reports filename will be generated automatically from it. # # DO_WEEKLY specifies whether to do weekly or daily reports. REPORTS_PREFIX = 'S_D_XXXXXXXX_XXXXXX_' # <-- Replace this with your own reports numerical prefix. PRIMARY_REPORT_CURRENCY = 'USD' FALLBACK_CURRENCY = 'CAD' DO_WEEKLY = False # Or True for generating weekly reports. MAX_NAME_LEN = 10 ############################################################################### class Item: def __init__(self, name): self.Name = name self.Currency = PRIMARY_REPORT_CURRENCY self.AbbrevName = name if len(self.AbbrevName) > MAX_NAME_LEN: idx1 = name.find("-") idx2 = name.find("(") if idx2 >= 0 and idx2 < idx1: idx1 = idx2 name_to_parse = name if idx1 > 0: name_to_parse = name[0:idx1] if len(name_to_parse) > MAX_NAME_LEN: split_name = name_to_parse.split(" ") self.AbbrevName = "" for str in split_name: if len(str) > 0: self.AbbrevName += str[0] else: self.AbbrevName = name_to_parse self.Units = 0 self.Price = -1.0 def __cmp__(self, other): return cmp(self.Units, other.Units)*-1 ############################################################################### def findPrice(lines, repCurrency, prodName, iCurrencyIdx, iPriceIdx, iNameIdx): foundZeroPrice = False for i in range(1, len(lines)): split_line = lines[i].split('\t') if not split_line[iNameIdx] == prodName: continue if float(split_line[iPriceIdx]) <= 0: foundZeroPrice = True continue if not split_line[iCurrencyIdx] == repCurrency: continue return float(split_line[iPriceIdx]) if foundZeroPrice: return 0.0 else: return -1.0 ############################################################################### def getInfo(filename): f = open(filename, "r") fc = f.readlines() f.close() final_rep = {} # The first line contains the headers headers = fc[0].split('\t') iNameIdx = headers.index('Title / Episode / Season') iRoyalCurrencyIdx = headers.index('Royalty Currency') iCopiesIdx = headers.index('Units') iRoyaltyPriceIdx = headers.index('Royalty Price') # Go over each line and see how much we have for i in range(1, len(fc)): split_line = fc[i].split('\t') prodName = split_line[iNameIdx] if not prodName in final_rep: final_rep[prodName] = Item(prodName) final_rep[prodName].Price = findPrice(fc, PRIMARY_REPORT_CURRENCY, prodName, iRoyalCurrencyIdx, iRoyaltyPriceIdx, iNameIdx) final_rep[prodName].Currency = PRIMARY_REPORT_CURRENCY if final_rep[prodName].Price < 0.0: final_rep[prodName].Price = findPrice(fc, FALLBACK_CURRENCY, prodName, iRoyalCurrencyIdx, iRoyaltyPriceIdx, iNameIdx) final_rep[prodName].Currency = FALLBACK_CURRENCY # Now, increment everything if float(split_line[iRoyaltyPriceIdx]) > 0: final_rep[prodName].Units += int(split_line[iCopiesIdx]) # Print the results total_num_copies = 0 total_earned = 0 # Make it into a list and sort it prt_list = [] for e in final_rep: prt_list.append(final_rep[e]) prt_list.sort() for e in prt_list: item = e if item.Price <= 0: continue total_num_copies += item.Units total_earned += item.Price*item.Units currency = "" tabs = "\t" if item.Currency != PRIMARY_REPORT_CURRENCY: currency = " " + FALLBACK_CURRENCY if len(item.AbbrevName) < 8: tabs = "\t\t" print item.AbbrevName + tabs + str(item.Units) + "\t" + str(item.Price*item.Units) + currency print "---" print "Total\t\t" + str(total_num_copies) + "\t" + str(total_earned) + " " + PRIMARY_REPORT_CURRENCY ############################################################################### def findLastSunday(init_date): res_date = init_date one_day = datetime.timedelta(days=1) while 1: if res_date.weekday() == 6: return res_date res_date = res_date - one_day ############################################################################### # Get the right file. The date is in the yyyy-mm-dd format. one_day = datetime.timedelta(days=1) today = datetime.date.today() yesterday = today - one_day if len(sys.argv) > 2: temp_str = sys.argv[2].replace("-", "") if len(temp_str) == 8: yesterday = datetime.date(int(temp_str[:4]), int(temp_str[4:6]), int(temp_str[6:8])) date_string = str(yesterday) date_string = date_string.replace("-", "") last_sunday = findLastSunday(yesterday) rep_type = "D" if (len(sys.argv) > 1 and (sys.argv[1]).lower() == "w") or DO_WEEKLY: rep_type = "W" date_string = str(last_sunday) date_string = date_string.replace("-", "") REPORTS_PREFIX = REPORTS_PREFIX[:2] + rep_type + REPORTS_PREFIX[3:] filename_begin = REPORTS_PREFIX + date_string + "*.txt" matches = glob.glob(filename_begin) if len(matches) > 0: print print "Date\t\t" + date_string print getInfo(matches[0]) else: if rep_type == "D": print "No daily reports found for " + date_string else: print "No weekly reports found for " + date_string # Wait for a user keypress print print "Press any key to close this window..." char = '' while not char: char = msvcrt.getch() ###############################################################################