Metadata-Version: 2.4
Name: omkarbhosale-upi-qr
Version: 3.0.0
Summary: Generate UPI QR codes with specified amounts, transaction splitting, and schema validation
Home-page: https://github.com/0mkarBhosale07/python-upi-qr
Author: Omkar Bhosale
Author-email: omkarbhosale5484@email.com
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: qrcode[pil]>=7.4.2
Requires-Dist: pydantic>=2.0.0
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# UPI QR Python Version 3.0.0

Python package to generate UPI payment QR codes with specified amounts, automatic transaction splitting (`splitTransactionQR`), runtime schema validation, and precision paise arithmetic.

---

## What's New in v3.0.0

- ✂️ **Transaction Splitting (`splitTransactionQR`)**: Automatically breaks transactions above ₹2,000 into ₹1,999 intervals (e.g., ₹5,000 becomes ₹1,999 + ₹1,999 + ₹1,002).
- 🛡️ **Pydantic Validation**: Robust runtime schema validation equivalent to Zod, checking UPI IDs, transaction boundaries, and parameters.
- 🏷️ **Optional Transaction Metadata**: Support for payee name (`name`), transaction note (`note`), and currency (`currency`, defaults to `INR`).
- ⚡ **Precision Math**: Uses paise-level integer arithmetic (`round(amount * 100)`) to prevent floating-point rounding errors.
- 📦 **Dual Import & Flexible Signatures**: Full support for keyword arguments, dictionary payloads, Pydantic models, and positional parameters.

---

## Installation

```bash
pip install omkarbhosale-upi-qr
```

---

## 1. `splitTransactionQR(params)`

Splits large transactions exceeding a threshold (default ₹2,000) into ₹1,999 intervals and generates a QR code for each chunk concurrently.

### Why Split at ₹1,999?
Under NPCI guidelines, transactions $\le$ ₹2,000 often bypass merchant interchange fees on PPI wallets and qualify for streamlined processing. Splitting larger payments into ₹1,999 chunks ensures each transaction remains under the ₹2,000 threshold.

### Parameters (`SplitQRParams`)

| Parameter | Type | Required | Default | Description |
| :--- | :--- | :---: | :---: | :--- |
| `UPI_ID` | `str` | **Yes** | — | Valid UPI ID (e.g., `merchant@okhdfcbank`, `user@upi`). |
| `AMOUNT` | `float` | **Yes** | — | Total transaction amount (positive number up to ₹10,00,000). |
| `splitInterval` | `float` | No | `1999` | Maximum amount per split chunk. |
| `threshold` | `float` | No | `2000` | Amount above which splitting is triggered. If `AMOUNT <= threshold`, only 1 QR is generated. |
| `name` | `str` | No | `None` | Payee name (`pn`). |
| `note` | `str` | No | `None` | Transaction note (`tn`). Each chunk automatically appends `(Part X/Y)`. |
| `currency` | `str` | No | `"INR"` | Currency code. |

### Return Value (`List[SplitQRItem]`)

A list of `SplitQRItem` objects (which support both attribute access and dictionary indexing):

| Property | Type | Description |
| :--- | :--- | :--- |
| `id` | `str` | Unique UUID (`v4`) for this specific split QR. |
| `amount` | `int \| float` | The split portion amount. |
| `image` | `str` | Base64-encoded Data URL of the generated QR code (`data:image/png;base64,...`). |

---

### Code Examples

#### Basic Split (₹5,000)
```python
from omkarbhosale_upi_qr import splitTransactionQR

splits = splitTransactionQR({
    "UPI_ID": "store@upi",
    "AMOUNT": 5000,
    "name": "Omkar Store",
    "note": "Order #12345"
})

for item in splits:
    print(f"ID: {item.id} | Amount: Rs. {item.amount}")
    print(f"QR Data URL: {item.image[:40]}...\n")
```

**Output:**
```json
[
  {
    "id": "4a236fad-ebc5-471f-86ab-86a4f9e621e7",
    "amount": 1999,
    "image": "data:image/png;base64,iVBORw0KGgo..."
  },
  {
    "id": "c19ba6ae-664a-47d7-9948-bf3558fefb6d",
    "amount": 1999,
    "image": "data:image/png;base64,iVBORw0KGgo..."
  },
  {
    "id": "3c44b4ad-44e7-414f-86c4-60ae9f228ec6",
    "amount": 1002,
    "image": "data:image/png;base64,iVBORw0KGgo..."
  }
]
```

#### Custom Split Interval & Threshold
```python
splits = splitTransactionQR(
    UPI_ID="store@upi",
    AMOUNT=1000,
    threshold=500,     # Split anything above ₹500
    splitInterval=400, # Chunk in ₹400 intervals
    name="Omkar Store",
    note="Order #12345"
)
# Returns 3 QRs: ₹400 + ₹400 + ₹200
```

#### Amounts Within Threshold ($\le$ ₹2,000)
```python
splits = splitTransactionQR(UPI_ID="store@upi", AMOUNT=1500)
# Returns 1 QR: [SplitQRItem(id="...", amount=1500, image="data:image/png;base64,...")]
```

---

## 2. `generateQR(params)`

Generates a single UPI QR code as a base64 Data URL.

### Parameters (`QRParams`)

| Parameter | Type | Required | Default | Description |
| :--- | :--- | :---: | :---: | :--- |
| `UPI_ID` | `str` | **Yes** | — | Valid UPI ID handle. |
| `AMOUNT` | `float` | **Yes** | — | Amount to receive (positive number $\le$ ₹1,00,000). |
| `name` | `str` | No | `None` | Payee Name (`pn`). |
| `note` | `str` | No | `None` | Transaction note (`tn`). |
| `currency` | `str` | No | `"INR"` | Currency code. |

### Example

```python
from omkarbhosale_upi_qr import generateQR

qr_data_url = generateQR(
    UPI_ID="omkar@upi",
    AMOUNT=750,
    name="Omkar Bhosale",
    note="Coffee bill"
)

print(qr_data_url) # data:image/png;base64,iVBORw0KGgo...
```

---

## 3. Schema Pre-validation

Exported schemas provide runtime validation with `.safeParse(...)` and `.parse(...)` methods directly mirroring Zod:

```python
from omkarbhosale_upi_qr import upiIdSchema

# Validate a UPI ID directly
result = upiIdSchema.safeParse("invalid-upi")
if not result.success:
    print(result.error.issues[0].message)
    # "Invalid UPI ID format. Expected format: username@bank"
```

### Exported Schemas & Models
- `upiIdSchema` / `UPIIdSchema`
- `qrParamsSchema` / `QRParams`
- `splitQRParamsSchema` / `SplitQRParams`
- `splitQRItemSchema` / `SplitQRItem`

### Validation Rules
- **UPI ID**: Matches regex `^[\w.-]+@[\w.-]+$`, 3 to 50 characters, trimmed of whitespace.
- **Single QR Amount**: Positive finite number $\le$ ₹1,00,000.
- **Split QR Amount**: Positive finite number $\le$ ₹10,00,000.
- **Error Handling**: Raises `UPIValidationError` (inherits from `ValueError`) with format: `Validation error: field: message`.

---

## 4. Import Compatibility

`omkarbhosale_upi_qr` supports named imports, pythonic snake_case aliases, and callable default style:

```python
# Named imports
from omkarbhosale_upi_qr import generateQR, splitTransactionQR

# Callable default object (JS-style parity)
from omkarbhosale_upi_qr import upiqr

single = upiqr(UPI_ID="user@upi", AMOUNT=500)
splits = upiqr.splitTransactionQR(UPI_ID="user@upi", AMOUNT=5000)
```

---

## License

MIT License.
