Lash up a command to suspend subscriptions
This commit is contained in:
parent
15c9fbfe6f
commit
6102d39759
1 changed files with 76 additions and 2 deletions
|
@ -44,15 +44,18 @@ def main():
|
||||||
transactions = get_all_transactions(access_token, args.start_date, args.end_date)
|
transactions = get_all_transactions(access_token, args.start_date, args.end_date)
|
||||||
if args.report == 'profiles':
|
if args.report == 'profiles':
|
||||||
report_on_unique_profiles(transactions)
|
report_on_unique_profiles(transactions)
|
||||||
else:
|
elif args.report == 'transactions':
|
||||||
report_on_transactions(transactions)
|
report_on_transactions(transactions)
|
||||||
|
else:
|
||||||
|
suspend_subscriptions_interactively(transactions, args.pattern, access_token)
|
||||||
|
|
||||||
|
|
||||||
def parse_args():
|
def parse_args():
|
||||||
parser = argparse.ArgumentParser(description='Download PayPal subscriber info.')
|
parser = argparse.ArgumentParser(description='Download PayPal subscriber info.')
|
||||||
parser.add_argument('report', help='report to run"', choices=['profiles', 'transactions'])
|
parser.add_argument('report', help='report to run"', choices=['profiles', 'transactions', 'suspend'])
|
||||||
parser.add_argument('start_date', help='start date inclusive (eg. 2021-11-01T00:00:00-07:00)', type=parse_iso_time)
|
parser.add_argument('start_date', help='start date inclusive (eg. 2021-11-01T00:00:00-07:00)', type=parse_iso_time)
|
||||||
parser.add_argument('end_date', help='end date inclusive (eg. 2021-11-30T23:59:59-07:00)', type=parse_iso_time)
|
parser.add_argument('end_date', help='end date inclusive (eg. 2021-11-30T23:59:59-07:00)', type=parse_iso_time)
|
||||||
|
parser.add_argument('pattern')
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
@ -153,6 +156,23 @@ def report_on_unique_profiles(transactions):
|
||||||
print(f'Reference IDs with changing subject: {dupes}', file=sys.stderr)
|
print(f'Reference IDs with changing subject: {dupes}', file=sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
|
def get_subscriptions_matching_subject(transactions, pattern):
|
||||||
|
records = set()
|
||||||
|
for t in transactions:
|
||||||
|
transaction_info = t['transaction_info']
|
||||||
|
if 'paypal_reference_id' in transaction_info and pattern.lower() in transaction_info.get('transaction_subject', 'CANT MATCH ME').lower():
|
||||||
|
records.add(
|
||||||
|
(
|
||||||
|
transaction_info['paypal_reference_id'],
|
||||||
|
transaction_info.get('transaction_subject', 'NO TRANSACTION SUBJECT'),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# print(f'Skipping transaction {transaction_info["transaction_id"]} with no PayPal Reference ID.', file=sys.stderr)
|
||||||
|
pass
|
||||||
|
return records
|
||||||
|
|
||||||
|
|
||||||
def report_on_transactions(transactions):
|
def report_on_transactions(transactions):
|
||||||
"""Print a formatted list of transactions."""
|
"""Print a formatted list of transactions."""
|
||||||
for t in transactions:
|
for t in transactions:
|
||||||
|
@ -164,5 +184,59 @@ def report_on_transactions(transactions):
|
||||||
print(f'Skipping transaction {transaction_info["transaction_id"]} with no PayPal Reference ID.', file=sys.stderr)
|
print(f'Skipping transaction {transaction_info["transaction_id"]} with no PayPal Reference ID.', file=sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
|
def suspend_subscriptions_interactively(transactions, pattern, access_token):
|
||||||
|
subscriptions = get_subscriptions_matching_subject(transactions, pattern)
|
||||||
|
for (id, subject) in subscriptions:
|
||||||
|
sub_before = paypal_request(f'https://api.paypal.com/v1/billing/subscriptions/{id}', access_token)
|
||||||
|
status_before = sub_before['status']
|
||||||
|
|
||||||
|
# Donor name / total donations / last donation / donation amount / FULL text of the profile Memo description / profile-id " with "Should I cancel this one? (y/n)"
|
||||||
|
given_name = sub_before['subscriber'].get('name', {}).get('given_name', '')
|
||||||
|
surname = sub_before['subscriber'].get('name', {}).get('surname', '')
|
||||||
|
name = ' '.join(filter(bool, [given_name, surname]))
|
||||||
|
payments = sub_before['billing_info']['cycle_executions'][0]['cycles_completed']
|
||||||
|
last_payment = sub_before['billing_info']['last_payment']
|
||||||
|
last_payment_total = last_payment['amount']['value']
|
||||||
|
last_payment_currency = last_payment['amount']['currency_code']
|
||||||
|
last_payment_time = last_payment['time']
|
||||||
|
print(f'Subscriber {id} {subject} {status_before}: {name}, {payments} payments with last payment {last_payment_time}, {last_payment_total} {last_payment_currency}')
|
||||||
|
if status_before == 'ACTIVE':
|
||||||
|
url = f'https://api.paypal.com/v1/billing/subscriptions/{id}/suspend'
|
||||||
|
if input('Cancel this one? (y/n) ') == 'y':
|
||||||
|
response = paypal_post_request(url, access_token)
|
||||||
|
print(f'PayPal said: {response.text}')
|
||||||
|
sub_after = paypal_request(f'https://api.paypal.com/v1/billing/subscriptions/{id}', access_token)
|
||||||
|
status_after = sub_after['status']
|
||||||
|
print(f'Subscriber {id} status after: {status_after}')
|
||||||
|
else:
|
||||||
|
print(' ignoring inactive status')
|
||||||
|
|
||||||
|
|
||||||
|
def paypal_request(url, access_token):
|
||||||
|
response = requests.get(
|
||||||
|
url,
|
||||||
|
headers={
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': f'Bearer {access_token}',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
data = response.json()
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def paypal_post_request(url, access_token):
|
||||||
|
response = requests.post(
|
||||||
|
url,
|
||||||
|
headers={
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': f'Bearer {access_token}',
|
||||||
|
},
|
||||||
|
json={
|
||||||
|
'reason': 'suspended',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
Loading…
Reference in a new issue