Sure! Let's break down the requirements for the problem and then create a test case generator. Here's the breakdown of the input:

1. **N**: Number of towns (1 ≤ N ≤ 50).
2. **M**: Number of product types (1 ≤ M ≤ 50).
3. **W**: Maximum weight Rabbit can carry (1 ≤ W ≤ 10^3).
4. **T**: Total time Rabbit has (1 ≤ T ≤ 10^4).

For each product type:
- **Si**: Name of the product (a string).
- **Vi**: Weight per unit of the product (1 ≤ Vi ≤ 10^3).
- **Pi**: Selling price per unit of the product (1 ≤ Pi ≤ 10^4).

For each town:
- **Li**: Number of product types sold in the town (1 ≤ Li ≤ M).
- **Xi**: x-coordinate of the town (|Xi| ≤ 10^3).
- **Yi**: y-coordinate of the town (|Yi| ≤ 10^3).

For each product type in a town:
- **Rij**: Index of the product type (1 ≤ Rij ≤ M).
- **Qij**: Selling price in the town (1 ≤ Qij ≤ 10^4).

Here's a Python function to generate test cases based on these constraints:

```python
import random
import string

def random_string(length=5):
    letters = string.ascii_lowercase
    return ''.join(random.choice(letters) for _ in range(length))

def tcgen():
    N = random.randint(1, 50)
    M = random.randint(1, 50)
    W = random.randint(1, 1000)
    T = random.randint(1, 10000)
    
    products = []
    for _ in range(M):
        Si = random_string()
        Vi = random.randint(1, 1000)
        Pi = random.randint(1, 10000)
        products.append((Si, Vi, Pi))
    
    towns = []
    for _ in range(N):
        Li = random.randint(1, M)
        Xi = random.randint(-1000, 1000)
        Yi = random.randint(-1000, 1000)
        town_products = []
        for _ in range(Li):
            Rij = random.randint(1, M)
            Qij = random.randint(1, 10000)
            town_products.append((Rij, Qij))
        towns.append((Li, Xi, Yi, town_products))
    
    # Output the test case
    output = f"{N} {M} {W} {T}\n"
    for Si, Vi, Pi in products:
        output += f"{Si} {Vi} {Pi}\n"
    for Li, Xi, Yi, town_products in towns:
        output += f"{Li} {Xi} {Yi}\n"
        for Rij, Qij in town_products:
            output += f"{Rij} {Qij}\n"
    return output

# Example usage
test_case = tcgen()
print(test_case)
```

### Explanation:
1. **random_string(length=5)**: Generates a random string of lowercase letters of length 5, used for product names.
2. **tcgen()**:
   - Randomly determines the number of towns \( N \) and product types \( M \), as well as \( W \) and \( T \).
   - Generates random products with names, weights, and selling prices.
   - For each town, generates random coordinates and then lists the products sold there with their respective selling prices.
   - Constructs the output string in the required format.

You can call this function to generate a test case as shown in the example usage. This output can be used directly in a competitive programming environment to test the solution to the problem.