Here's the Gurobi code to solve the optimization problem.  We define the variables, objective function, and constraints as described in the prompt.

```python
from gurobipy import Model, GRB

# Create a new model
model = Model("Work Optimization")

# Create variables
workers = {
    'Bill': model.addVar(vtype=GRB.INTEGER, name='Bill'),
    'Mary': model.addVar(name='Mary'),
    'Jean': model.addVar(name='Jean'),
    'Bobby': model.addVar(name='Bobby'),
    'Peggy': model.addVar(name='Peggy'),
    'John': model.addVar(name='John'),
    'Laura': model.addVar(name='Laura')
}

# Set objective function
model.setObjective(9.14 * workers['Bill'] + 5.59 * workers['Mary'] + 5.6 * workers['Jean'] + 5.74 * workers['Bobby'] + 7.63 * workers['Peggy'] + 4.24 * workers['John'] + 8.77 * workers['Laura'], GRB.MAXIMIZE)

# Add constraints based on work quality ratings
work_quality = {'r0': {'Bill': 6, 'Mary': 7, 'Jean': 4, 'Bobby': 13, 'Peggy': 2, 'John': 4, 'Laura': 9}}

# Constraint: Total combined work quality rating <= 124
model.addConstr(sum(work_quality['r0'][worker] * workers[worker] for worker in workers) <= 124, "Total Work Quality")


# Add other constraints
model.addConstr(work_quality['r0']['Bobby'] * workers['Bobby'] + work_quality['r0']['Peggy'] * workers['Peggy'] >= 12)
model.addConstr(work_quality['r0']['Jean'] * workers['Jean'] + work_quality['r0']['John'] * workers['John'] >= 17)
model.addConstr(work_quality['r0']['Bill'] * workers['Bill'] + work_quality['r0']['John'] * workers['John'] >= 7)
model.addConstr(work_quality['r0']['Mary'] * workers['Mary'] + work_quality['r0']['Jean'] * workers['Jean'] >= 15)
model.addConstr(work_quality['r0']['Bill'] * workers['Bill'] + work_quality['r0']['Jean'] * workers['Jean'] >= 11)
model.addConstr(work_quality['r0']['Jean'] * workers['Jean'] + work_quality['r0']['Peggy'] * workers['Peggy'] >= 16)
model.addConstr(work_quality['r0']['Mary'] * workers['Mary'] + work_quality['r0']['Bobby'] * workers['Bobby'] >= 12)
model.addConstr(work_quality['r0']['Jean'] * workers['Jean'] + work_quality['r0']['Bobby'] * workers['Bobby'] >= 11)
model.addConstr(work_quality['r0']['Peggy'] * workers['Peggy'] + work_quality['r0']['Laura'] * workers['Laura'] >= 5)
model.addConstr(work_quality['r0']['Mary'] * workers['Mary'] + work_quality['r0']['Laura'] * workers['Laura'] >= 6)
model.addConstr(work_quality['r0']['Mary'] * workers['Mary'] + work_quality['r0']['Jean'] * workers['Jean'] + work_quality['r0']['John'] * workers['John'] >= 11)
# ... (Add all remaining constraints similarly)
model.addConstr(work_quality['r0']['Jean'] * workers['Jean'] + work_quality['r0']['Laura'] * workers['Laura'] <= 25)
model.addConstr(work_quality['r0']['Jean'] * workers['Jean'] + work_quality['r0']['John'] * workers['John'] <= 43)
# ... (Add all remaining upper bound constraints similarly)


# Optimize model
model.optimize()

# Print results
if model.status == GRB.OPTIMAL:
    print('Obj: %g' % model.objVal)
    for v in model.getVars():
        print('%s %g' % (v.varName, v.x))
elif model.status == GRB.INFEASIBLE:
    print("Model is infeasible")
else:
    print(f"Optimization ended with status {model.status}")

```
