Here's the Gurobi code to solve the optimization problem:

```python
import gurobipy as gp

# Create a new model
m = gp.Model("Work_Optimization")

# Create variables
bill_hours = m.addVar(vtype=gp.GRB.INTEGER, name="Bill_Hours")
george_hours = m.addVar(vtype=gp.GRB.INTEGER, name="George_Hours")
jean_hours = m.addVar(vtype=gp.GRB.INTEGER, name="Jean_Hours")

# Set objective function
m.setObjective(3.77 * bill_hours + 5.17 * george_hours + 8.77 * jean_hours, gp.GRB.MAXIMIZE)

# Add constraints
m.addConstr(3 * bill_hours + 10 * george_hours + 6 * jean_hours >= 11, "Productivity_Constraint1")
m.addConstr(13 * george_hours + 5 * jean_hours >= 10, "Organization_Constraint1")
m.addConstr(8 * bill_hours + 5 * jean_hours >= 18, "Organization_Constraint2")
m.addConstr(8 * bill_hours + 13 * george_hours >= 14, "Organization_Constraint3")
m.addConstr(3 * bill_hours + 10 * george_hours <= 14, "Productivity_Constraint2")
m.addConstr(3 * bill_hours + 6 * jean_hours <= 30, "Productivity_Constraint3")
m.addConstr(3 * bill_hours + 10 * george_hours + 6 * jean_hours <= 30, "Productivity_Constraint4")
m.addConstr(13 * george_hours + 5 * jean_hours <= 54, "Organization_Constraint4")
m.addConstr(8 * bill_hours + 13 * george_hours <= 20, "Organization_Constraint5")
m.addConstr(8 * bill_hours + 5 * jean_hours <= 29, "Organization_Constraint6")
m.addConstr(8 * bill_hours + 13 * george_hours + 5 * jean_hours <= 38, "Organization_Constraint7")


# Optimize model
m.optimize()

# Print results
if m.status == gp.GRB.OPTIMAL:
    print('Obj: %g' % m.objVal)
    print('Bill Hours: %g' % bill_hours.x)
    print('George Hours: %g' % george_hours.x)
    print('Jean Hours: %g' % jean_hours.x)
elif m.status == gp.GRB.INFEASIBLE:
    print('The model is infeasible.')
else:
    print('Optimization ended with status %d' % m.status)

```
