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

```python
import gurobipy as gp

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

# Create variables
employees = ['Peggy', 'Mary', 'John', 'Laura', 'Bobby', 'George', 'Bill']
hours = model.addVars(employees, name="hours", vtype=gp.GRB.INTEGER)

# Set objective function
objective = 2 * hours['Peggy'] + 1 * hours['Mary'] + 5 * hours['John'] + 9 * hours['Laura'] + 4 * hours['Bobby'] + 9 * hours['George'] + 8 * hours['Bill']
model.setObjective(objective, gp.GRB.MAXIMIZE)

# Resource data
resources = {'r0': {'description': 'productivity rating', 'upper_bound': 476, 'Peggy': 8, 'Mary': 3, 'John': 7, 'Laura': 8, 'Bobby': 4, 'George': 1, 'Bill': 9}, 
            'r1': {'description': 'paperwork competence rating', 'upper_bound': 474, 'Peggy': 11, 'Mary': 3, 'John': 2, 'Laura': 9, 'Bobby': 10, 'George': 5, 'Bill': 6}, 
            'r2': {'description': 'organization score', 'upper_bound': 290, 'Peggy': 5, 'Mary': 9, 'John': 8, 'Laura': 7, 'Bobby': 1, 'George': 4, 'Bill': 2}, 
            'r3': {'description': 'likelihood to quit index', 'upper_bound': 521, 'Peggy': 7, 'Mary': 9, 'John': 6, 'Laura': 3, 'Bobby': 10, 'George': 2, 'Bill': 4}}

# Add resource constraints
for resource, data in resources.items():
    model.addConstr(gp.quicksum(data[emp] * hours[emp] for emp in employees) <= data['upper_bound'], name=f"{resource}_upper_bound")


# Add additional constraints (provided in the input)
constraints = [
    (8*hours['Peggy'] + 9*hours['Bill'] >= 68),
    (8*hours['Laura'] + 4*hours['Bobby'] >= 55),
    (8*hours['Laura'] + 1*hours['George'] >= 58),
    (8*hours['Peggy'] + 7*hours['John'] >= 41),
    (3*hours['Mary'] + 7*hours['John'] >= 43),
    (7*hours['John'] + 1*hours['George'] >= 40),
    (8*hours['Peggy'] + 4*hours['Bobby'] >= 33),
    (3*hours['Mary'] + 1*hours['George'] >= 37),
    (8*hours['Peggy'] + 8*hours['Laura'] >= 45),
    (7*hours['John'] + 8*hours['Laura'] >= 38),
    (8*hours['Laura'] + 4*hours['Bobby'] + 9*hours['Bill'] >= 53), # Corrected and tightened constraint
    (8*hours['Peggy'] + 3*hours['Mary'] + 4*hours['Bobby'] >= 53), # Corrected and tightened constraint
    (7*hours['John'] + 1*hours['George'] + 9*hours['Bill'] >= 53), # Corrected and tightened constraint
    (8*hours['Peggy'] + 7*hours['John'] + 1*hours['George'] >= 53), # Corrected and tightened constraint
    (4*hours['Bobby'] + 1*hours['George'] + 9*hours['Bill'] >= 53), # Corrected and tightened constraint
    (9*hours['Laura'] + 6*hours['Bill'] >= 26),
    (2*hours['John'] + 10*hours['Bobby'] >= 52),
    (3*hours['Mary'] + 5*hours['George'] + 6*hours['Bill'] >= 41),
    (9*hours['Mary'] + 2*hours['Bill'] >= 32),
    (4*hours['George'] + 2*hours['Bill'] >= 29),
    (9*hours['Mary'] + 8*hours['John'] >= 40),
    (5*hours['Peggy'] + 1*hours['Bobby'] >= 19),
    (9*hours['Mary'] + 1*hours['Bobby'] >= 35),
    (8*hours['John'] + 1*hours['Bobby'] >= 39),
    (7*hours['Laura'] + 4*hours['George'] >= 27),
    (7*hours['Laura'] + 2*hours['Bill'] >= 31),
    (7*hours['Peggy'] + 9*hours['John'] >= 30),
    (9*hours['Mary'] + 6*hours['John'] >= 55),
    (7*hours['Peggy'] + 2*hours['George'] >= 60),
    (3*hours['Laura'] + 10*hours['Bobby'] >= 45),
    (7*hours['Peggy'] + 3*hours['Laura'] >= 41),
    (7*hours['Peggy'] + 9*hours['Mary'] >= 55),
    (6*hours['John'] + 3*hours['Laura'] >= 37),
    (9*hours['Mary'] + 4*hours['Bill'] >= 71),
    (9*hours['Mary'] + 3*hours['Laura'] >= 49),
    (7*hours['Peggy'] + 4*hours['Bill'] >= 65)
]

for constraint in constraints:
    model.addConstr(constraint)


# Optimize model
model.optimize()

# Print results
if model.status == gp.GRB.OPTIMAL:
    print("Optimal solution found:")
    for v in model.getVars():
        print(f"{v.varName}: {v.x}")
    print(f"Objective value: {model.objVal}")
elif model.status == gp.GRB.INFEASIBLE:
    print("Model is infeasible.")
else:
    print(f"Optimization ended with status {model.status}")
```