mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	support: Extract PlanData as a dataclass.
This avoids monkey-patching `CustomerPlan` and other related information onto the `Realm` object by having a separate dictionary with the realm id as the key, each corresponds to a `PlandData` dataclass. This is a part of the django-stubs refactorings. Signed-off-by: Zixuan James Li <p359101898@gmail.com>
This commit is contained in:
		
				
					committed by
					
						
						Tim Abbott
					
				
			
			
				
	
			
			
			
						parent
						
							74f59bd8d0
						
					
				
				
					commit
					0d93257111
				
			@@ -1,4 +1,5 @@
 | 
			
		||||
import urllib
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
from datetime import timedelta
 | 
			
		||||
from decimal import Decimal
 | 
			
		||||
from typing import Any, Dict, Iterable, List, Optional
 | 
			
		||||
@@ -16,6 +17,7 @@ from django.utils.translation import gettext as _
 | 
			
		||||
 | 
			
		||||
from confirmation.models import Confirmation, confirmation_url
 | 
			
		||||
from confirmation.settings import STATUS_ACTIVE
 | 
			
		||||
from corporate.models import Customer, CustomerPlan
 | 
			
		||||
from zerver.actions.create_realm import do_change_realm_subdomain
 | 
			
		||||
from zerver.actions.realm_settings import (
 | 
			
		||||
    do_change_realm_org_type,
 | 
			
		||||
@@ -129,6 +131,14 @@ VALID_BILLING_METHODS = [
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@dataclass
 | 
			
		||||
class PlanData:
 | 
			
		||||
    customer: Optional[Customer] = None
 | 
			
		||||
    current_plan: Optional[CustomerPlan] = None
 | 
			
		||||
    licenses: Optional[int] = None
 | 
			
		||||
    licenses_used: Optional[int] = None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@require_server_admin
 | 
			
		||||
@has_request_variables
 | 
			
		||||
def support(
 | 
			
		||||
@@ -277,27 +287,30 @@ def support(
 | 
			
		||||
            except ValidationError:
 | 
			
		||||
                users.update(UserProfile.objects.filter(full_name__iexact=key_word))
 | 
			
		||||
 | 
			
		||||
        plan_data: Dict[int, PlanData] = {}
 | 
			
		||||
        for realm in realms:
 | 
			
		||||
            realm.customer = get_customer_by_realm(realm)
 | 
			
		||||
 | 
			
		||||
            current_plan = get_current_plan_by_realm(realm)
 | 
			
		||||
            plan_data[realm.id] = PlanData(
 | 
			
		||||
                customer=get_customer_by_realm(realm),
 | 
			
		||||
                current_plan=current_plan,
 | 
			
		||||
            )
 | 
			
		||||
            if current_plan is not None:
 | 
			
		||||
                new_plan, last_ledger_entry = make_end_of_cycle_updates_if_needed(
 | 
			
		||||
                    current_plan, timezone_now()
 | 
			
		||||
                )
 | 
			
		||||
                if last_ledger_entry is not None:
 | 
			
		||||
                    if new_plan is not None:
 | 
			
		||||
                        realm.current_plan = new_plan
 | 
			
		||||
                        plan_data[realm.id].current_plan = new_plan
 | 
			
		||||
                    else:
 | 
			
		||||
                        realm.current_plan = current_plan
 | 
			
		||||
                    realm.current_plan.licenses = last_ledger_entry.licenses
 | 
			
		||||
                    realm.current_plan.licenses_used = get_latest_seat_count(realm)
 | 
			
		||||
 | 
			
		||||
                        plan_data[realm.id].current_plan = current_plan
 | 
			
		||||
                    plan_data[realm.id].licenses = last_ledger_entry.licenses
 | 
			
		||||
                    plan_data[realm.id].licenses_used = get_latest_seat_count(realm)
 | 
			
		||||
        # full_names can have , in them
 | 
			
		||||
        users.update(UserProfile.objects.filter(full_name__iexact=query))
 | 
			
		||||
 | 
			
		||||
        context["users"] = users
 | 
			
		||||
        context["realms"] = realms
 | 
			
		||||
        context["plan_data"] = plan_data
 | 
			
		||||
 | 
			
		||||
        confirmations: List[Dict[str, Any]] = []
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -80,13 +80,13 @@
 | 
			
		||||
    {{ csrf_input }}
 | 
			
		||||
    <input type="hidden" name="realm_id" value="{{ realm.id }}" />
 | 
			
		||||
    <select name="sponsorship_pending">
 | 
			
		||||
        <option value="true" {% if realm.customer and realm.customer.sponsorship_pending %}selected{% endif %}>Yes</option>
 | 
			
		||||
        <option value="false" {% if not realm.customer or not realm.customer.sponsorship_pending %}selected{% endif %}>No</option>
 | 
			
		||||
        <option value="true" {% if plan_data[realm.id].customer and plan_data[realm.id].customer.sponsorship_pending %}selected{% endif %}>Yes</option>
 | 
			
		||||
        <option value="false" {% if not plan_data[realm.id].customer or not plan_data[realm.id].customer.sponsorship_pending %}selected{% endif %}>No</option>
 | 
			
		||||
    </select>
 | 
			
		||||
    <button type="submit" class="btn btn-default support-submit-button">Update</button>
 | 
			
		||||
</form>
 | 
			
		||||
 | 
			
		||||
{% if realm.customer and realm.customer.sponsorship_pending %}
 | 
			
		||||
{% if plan_data[realm.id].customer and plan_data[realm.id].customer.sponsorship_pending %}
 | 
			
		||||
<form method="POST" class="approve-sponsorship-form">
 | 
			
		||||
    {{ csrf_input }}
 | 
			
		||||
    <input type="hidden" name="realm_id" value="{{ realm.id }}" />
 | 
			
		||||
@@ -102,7 +102,7 @@
 | 
			
		||||
    <b>Discount (use 85 for nonprofits)</b>:<br />
 | 
			
		||||
    {{ csrf_input }}
 | 
			
		||||
    <input type="hidden" name="realm_id" value="{{ realm.id }}" />
 | 
			
		||||
    {% if realm.current_plan and realm.current_plan.fixed_price %}
 | 
			
		||||
    {% if plan_data[realm.id].current_plan and plan_data[realm.id].current_plan.fixed_price %}
 | 
			
		||||
    <input type="number" name="discount" value="{{ get_discount_for_realm(realm) }}" disabled />
 | 
			
		||||
    <button type="submit" class="btn btn-default support-submit-button" disabled>Update</button>
 | 
			
		||||
    {% else %}
 | 
			
		||||
@@ -110,19 +110,19 @@
 | 
			
		||||
    <button type="submit" class="btn btn-default support-submit-button">Update</button>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
</form>
 | 
			
		||||
{% if realm.current_plan %}
 | 
			
		||||
{% if plan_data[realm.id].current_plan %}
 | 
			
		||||
<div class="current-plan-details">
 | 
			
		||||
    <h3>📅 Current plan</h3>
 | 
			
		||||
    <b>Name</b>: {{ realm.current_plan.name }}<br />
 | 
			
		||||
    <b>Status</b>: {{realm.current_plan.get_plan_status_as_text()}}<br />
 | 
			
		||||
    <b>Billing schedule</b>: {% if realm.current_plan.billing_schedule == realm.current_plan.ANNUAL %}Annual{% else %}Monthly{% endif %}<br />
 | 
			
		||||
    <b>Licenses</b>: {{ realm.current_plan.licenses_used }}/{{ realm.current_plan.licenses }} ({% if realm.current_plan.automanage_licenses %}Automatic{% else %}Manual{% endif %})<br />
 | 
			
		||||
    {% if realm.current_plan.price_per_license %}
 | 
			
		||||
    <b>Price per license</b>: ${{ realm.current_plan.price_per_license/100 }}<br />
 | 
			
		||||
    <b>Name</b>: {{ plan_data[realm.id].current_plan.name }}<br />
 | 
			
		||||
    <b>Status</b>: {{plan_data[realm.id].current_plan.get_plan_status_as_text()}}<br />
 | 
			
		||||
    <b>Billing schedule</b>: {% if plan_data[realm.id].current_plan.billing_schedule == plan_data[realm.id].current_plan.ANNUAL %}Annual{% else %}Monthly{% endif %}<br />
 | 
			
		||||
    <b>Licenses</b>: {{ plan_data[realm.id].licenses_used }}/{{ plan_data[realm.id].licenses }} ({% if plan_data[realm.id].current_plan.automanage_licenses %}Automatic{% else %}Manual{% endif %})<br />
 | 
			
		||||
    {% if plan_data[realm.id].current_plan.price_per_license %}
 | 
			
		||||
    <b>Price per license</b>: ${{ plan_data[realm.id].current_plan.price_per_license/100 }}<br />
 | 
			
		||||
    {% else %}
 | 
			
		||||
    <b>Fixed price</b>: ${{ realm.current_plan.fixed_price/100 }}<br />
 | 
			
		||||
    <b>Fixed price</b>: ${{ plan_data[realm.id].current_plan.fixed_price/100 }}<br />
 | 
			
		||||
    {% endif %}
 | 
			
		||||
    <b>Next invoice date</b>: {{ realm.current_plan.next_invoice_date.strftime('%d %B %Y') }}<br />
 | 
			
		||||
    <b>Next invoice date</b>: {{ plan_data[realm.id].current_plan.next_invoice_date.strftime('%d %B %Y') }}<br />
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<form method="POST" class="billing-method-form">
 | 
			
		||||
@@ -131,8 +131,8 @@
 | 
			
		||||
    {{ csrf_input }}
 | 
			
		||||
    <input type="hidden" name="realm_id" value="{{ realm.id }}" />
 | 
			
		||||
    <select name="billing_method" class="billing-method-select" required>
 | 
			
		||||
        <option value="charge_automatically" {% if realm.current_plan.charge_automatically %}selected{% endif %}>Charge automatically</option>
 | 
			
		||||
        <option value="send_invoice" {% if not realm.current_plan.charge_automatically %}selected{% endif %}>Pay by invoice</option>
 | 
			
		||||
        <option value="charge_automatically" {% if plan_data[realm.id].current_plan.charge_automatically %}selected{% endif %}>Charge automatically</option>
 | 
			
		||||
        <option value="send_invoice" {% if not plan_data[realm.id].current_plan.charge_automatically %}selected{% endif %}>Pay by invoice</option>
 | 
			
		||||
    </select>
 | 
			
		||||
    <button type="submit" class="btn btn-default support-submit-button">Update</button>
 | 
			
		||||
</form>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user