One thing to remember with deploying to production. ALL of the testclasses have to be executed as part of the deployment. Your code looks pretty good from a SOQL standpoint, does need the DML moved outside the loop as was mentioned before), so it is probably a case where other test executions are putting you close to the limit, and your 1 soql is putting the entire transaction over the limit. Do a "Run All Tests" in production, and look at the resulting Debug log. At the very end, you should see a summary count of the SOQLs that were executed. You can then scan through the log for the SOQL summaries listed with each test that is executed, and use this to narrow down the offending code or test method.
Your debug statements are sucking the performance right out of your code. Never leave debug statements in production code. And I do mean never. Let me give you a trivial example.
Map<Integer, Integer> values = new Map<Integer, Integer>();
for(Integer i = 0; i < 7500; i++) {
values.put(i, i);
system.debug('item'+values);
}
This code tries to put 7,500 items into a map. It requires about 9.7 seconds to run:
Number of SOQL queries: 0 out of 100
Number of query rows: 0 out of 50000
Number of SOSL queries: 0 out of 20
Number of DML statements: 0 out of 150
Number of DML rows: 0 out of 10000
Maximum CPU time: 9714 out of 10000 ******* CLOSE TO LIMIT
Maximum heap size: 0 out of 6000000
Number of callouts: 0 out of 100
Number of Email Invocations: 0 out of 10
Number of future calls: 0 out of 50
Number of queueable jobs added to the queue: 0 out of 50
Number of Mobile Apex push calls: 0 out of 10
Now, we remove the debug statement:
Number of SOQL queries: 0 out of 100
Number of query rows: 0 out of 50000
Number of SOSL queries: 0 out of 20
Number of DML statements: 0 out of 150
Number of DML rows: 0 out of 10000
Maximum CPU time: 0 out of 10000
Maximum heap size: 0 out of 6000000
Number of callouts: 0 out of 100
Number of Email Invocations: 0 out of 10
Number of future calls: 0 out of 50
Number of queueable jobs added to the queue: 0 out of 50
Number of Mobile Apex push calls: 0 out of 10
The script took so little time it didn't even register in the governor limits. The exact same code minus debug statements. Now, I'm not saying that this will fix your issue, but considering that you're using debug statements in every single loop, I can pretty much guarantee it'll save at least 5 seconds of CPU time, if not more.
If you find yourself in a position where you need to debug, use checkpoints instead. They will give you a complete memory graph at any arbitrary point of execution, and when you're done, you can disable them so they don't take up tons of CPU time.
Best Answer
I find that updates in for loops is a dead giveaway as the number at the conclusion of the previous code is low and then it hits the limit during one code execution of a class or trigger.
Recursion - either directly or indirectly (Trigger updates a related object which fires a different trigger and updates another related object which fires a trigger and updates the original object... and so on and so forth) can add up quickly by the time you get to five levels deep. You only need 20 soql queries to get caught out that way.
In our org we have found that the biggest problem we inherited off the original dev team was that triggers fire and run 2 or 3 queries but due to business logic don't actually do anything. The solution we used was to 'hide' the queries inside an if statement and check the business logic first. The better solution is to move all logic to helper classes and only call the helper when the business rules (as far as can be determined without soql) need it.