Coverage for functions \ flipdare \ payments \ core \ stripe_invoice_prefix.py: 92%
36 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-05-08 12:22 +1000
« prev ^ index » next coverage.py v7.13.0, created at 2026-05-08 12:22 +1000
1#!/usr/bin/env python
2# Copyright (c) 2026 Flipdare Pty Ltd. All rights reserved.
3#
4# This file is part of Flipdare's proprietary software and contains
5# confidential and copyrighted material. Unauthorised copying,
6# modification, distribution, or use of this file is strictly
7# prohibited without prior written permission from Flipdare Pty Ltd.
8#
9# This software includes third-party components licensed under MIT,
10# BSD, and Apache 2.0 licences. See THIRD_PARTY_NOTICES for details.
11#
13import re
14from typing import Self
15from flipdare.app_globals import is_text_present
16from flipdare.constants import (
17 STRIPE_FALLBACK_LAST_STR,
18 STRIPE_FALLBACK_PREFIX_STR,
19 STRIPE_INVOICE_PREFIX_LENGTH,
20)
21from flipdare.payments.core.stripe_util import StripeUtil
23__all__ = ["StripeInvoicePrefix"]
26class StripeInvoicePrefix:
27 __slots__ = (
28 "_tokens",
29 "_uid",
30 )
32 def __init__(
33 self,
34 *,
35 _internal: bool,
36 uid: str,
37 tokens: tuple[str, str],
38 ) -> None:
39 if not _internal:
40 raise ValueError("Use .from_name or .from_tokens to create StripeInvoicePrefix")
42 self._uid = uid
43 self._tokens = tokens
45 @classmethod
46 def create(
47 cls,
48 uid: str,
49 name: str,
50 email: str,
51 name_tokens: tuple[str, str] | None = None,
52 ) -> Self:
53 return (
54 cls.from_tokens(uid=uid, tokens=name_tokens)
55 if name_tokens
56 else cls.from_name(uid=uid, name=name, email=email)
57 )
59 @classmethod
60 def from_name(
61 cls,
62 uid: str,
63 name: str,
64 email: str,
65 ) -> Self:
66 name_tokens = StripeUtil.get_name_tokens(name=name, email=email)
67 return cls(
68 _internal=True,
69 uid=uid,
70 tokens=name_tokens,
71 )
73 @classmethod
74 def from_tokens(
75 cls,
76 uid: str,
77 tokens: tuple[str, str],
78 ) -> Self:
79 return cls(
80 _internal=True,
81 uid=uid,
82 tokens=tokens,
83 )
85 @property
86 def prefix(self) -> str:
87 uid = self._uid
88 tokens = self._tokens
90 # That is the spirit!
91 # If your app reaches the point where you're hitting 1-in-3.6-quadrillion collisions,
92 # you'll have a massive engineering team and a very healthy bank account to solve it.
93 # and then you can check the invoice ID store in stripe settings!
94 first_name, last_name = tokens
96 if not is_text_present(first_name):
97 first_name = STRIPE_FALLBACK_PREFIX_STR
98 if not is_text_present(last_name):
99 last_name = STRIPE_FALLBACK_LAST_STR
101 # 1. Get Initials (e.g., "John", "Doe" -> "JD")
102 initials = (first_name[:1] + last_name[:1]).upper()
104 # 2. Clean UID (Remove symbols like '-' or '_', make uppercase)
105 clean_uid = re.sub(r"[^A-Z0-9]", "", uid.upper())
107 # 3. Take the last 10 characters of the UID to fill the 12-char limit
108 # This provides ~3.6 quadrillion possible combinations
109 suffix = clean_uid[-10:]
110 return (initials + suffix)[:STRIPE_INVOICE_PREFIX_LENGTH]