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
george = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="George")
hank = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="Hank")
ringo = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="Ringo")
peggy = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="Peggy")
paul = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="Paul")
john = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="John")
bill = m.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="Bill")

# Set objective function
m.setObjective(5*george + 5*hank + 9*ringo + 2*peggy + 1*paul + 2*john + 5*bill, gp.GRB.MINIMIZE)

# Add productivity constraints
m.addConstr(3 * peggy + 5 * john >= 28)
m.addConstr(10 * george + 3 * peggy >= 28)
m.addConstr(7 * paul + 4 * bill >= 39)
m.addConstr(13 * hank + 4 * bill >= 29)
m.addConstr(2 * ringo + 3 * peggy >= 36)
m.addConstr(10 * george + 2 * ringo >= 41)
m.addConstr(2 * ringo + 4 * bill >= 20)
m.addConstr(3 * peggy + 4 * bill >= 25)
m.addConstr(10 * george + 13 * hank + 2 * ringo + 3 * peggy + 7 * paul + 5 * john + 4 * bill >= 25)

# Add computer competence constraints
m.addConstr(7 * paul + 15 * john >= 17)
m.addConstr(8 * hank + 5 * bill >= 15)
m.addConstr(12 * peggy + 7 * paul >= 20)
m.addConstr(12 * peggy + 15 * john >= 16)
m.addConstr(8 * hank + 15 * john >= 11)
m.addConstr(19 * george + 7 * paul >= 16)
m.addConstr(8 * hank + 12 * peggy >= 15)
m.addConstr(3 * ringo + 15 * john >= 21)
m.addConstr(19 * george + 3 * ringo >= 21)
m.addConstr(19*george + 3*ringo + 15*john >= 27) # Example using the highest lower bound for this combination
m.addConstr(10*george + 13*hank + 2*ringo + 3*peggy + 7*paul + 5*john + 4*bill >= 27)

# Add work quality constraints
m.addConstr(3 * peggy + 13 * paul >= 27)
m.addConstr(3 * peggy + 12 * bill >= 26)
m.addConstr(13 * john + 12 * bill >= 19)
m.addConstr(1 * ringo + 13 * paul >= 12)
m.addConstr(3 * hank + 13 * john >= 22)
m.addConstr(3 * hank + 3 * peggy >= 33)
m.addConstr(1 * ringo + 13 * john >= 26)
m.addConstr(6 * george + 3 * hank >= 14)
m.addConstr(1 * ringo + 12 * bill >= 36)
m.addConstr(13 * paul + 12 * bill >= 33)
m.addConstr(6 * george + 1 * ringo >= 18)
m.addConstr(3 * hank + 13 * paul >= 27)
m.addConstr(3*peggy + 13*paul + 13*john >= 31) # Example using the highest lower bound for this combination
m.addConstr(6*george + 3*hank + 1*ringo + 3*peggy + 13*paul + 13*john + 12*bill >= 31)


# Add other constraints
m.addConstr(-4 * peggy + 3 * paul >= 0)
m.addConstr(9 * george - 1 * bill >= 0)


# Add resource upper bound constraints
productivity = {'George': 10, 'Hank': 13, 'Ringo': 2, 'Peggy': 3, 'Paul': 7, 'John': 5, 'Bill': 4}
computer_competence = {'George': 19, 'Hank': 8, 'Ringo': 3, 'Peggy': 12, 'Paul': 7, 'John': 15, 'Bill': 5}
work_quality = {'George': 6, 'Hank': 3, 'Ringo': 1, 'Peggy': 3, 'Paul': 13, 'John': 13, 'Bill': 12}

m.addConstr(sum(productivity[name] * vars()[name.lower()] for name in productivity) <= 334)
m.addConstr(sum(computer_competence[name] * vars()[name.lower()] for name in computer_competence) <= 195)
m.addConstr(sum(work_quality[name] * vars()[name.lower()] for name in work_quality) <= 262)



# Optimize model
m.optimize()

# Print results
if m.status == gp.GRB.OPTIMAL:
    print('Obj: %g' % m.objVal)
    for v in m.getVars():
        print('%s %g' % (v.varName, v.x))
elif m.status == gp.GRB.INFEASIBLE:
    print('Model is infeasible')
else:
    print('Optimization ended with status %d' % m.status)
```