To solve this problem, we need to define variables and constraints that capture the time limitations for weighing and packaging, as well as the profit objective. Let's denote:

- \(x\) as the number of bottles of pills.
- \(y\) as the number of bottles of cream.

The pharmacy has two main constraints:
1. Weighing time constraint: Each bottle of pills takes 20 minutes to weigh, and each bottle of cream takes 15 minutes to weigh. The total weighing time available is 4000 minutes.
2. Packaging time constraint: Each bottle of pills takes 10 minutes to package, and each bottle of cream takes 15 minutes to package. The total packaging time available is 3000 minutes.

The profit per bottle of pills is $50, and the profit per bottle of cream is $60. We want to maximize the total profit, which can be represented as \(50x + 60y\).

Here are the constraints in symbolic form:
1. Weighing constraint: \(20x + 15y \leq 4000\)
2. Packaging constraint: \(10x + 15y \leq 3000\)

Since we cannot produce a negative number of bottles, both \(x\) and \(y\) must be non-negative:
3. Non-negativity constraints: \(x \geq 0\), \(y \geq 0\)

Now, let's translate this problem into Gurobi code in Python:

```python
from gurobipy import *

# Create a new model
m = Model("Pharmacy_Optimization")

# Define variables
x = m.addVar(name="bottles_of_pills", vtype=GRB.CONTINUOUS, lb=0)
y = m.addVar(name="bottles_of_cream", vtype=GRB.CONTINUOUS, lb=0)

# Define the objective function (maximize profit)
m.setObjective(50*x + 60*y, GRB.MAXIMIZE)

# Add constraints
m.addConstr(20*x + 15*y <= 4000, name="weighing_time_constraint")
m.addConstr(10*x + 15*y <= 3000, name="packaging_time_constraint")

# Optimize the model
m.optimize()

# Print the results
if m.status == GRB.OPTIMAL:
    print("Optimal solution found:")
    print(f"Number of bottles of pills: {x.x}")
    print(f"Number of bottles of cream: {y.x}")
    print(f"Maximum profit: ${50*x.x + 60*y.x:.2f}")
else:
    print("No optimal solution found")

```