As Tom Martens noted, corrective alpha can show any overlap. The following alpha level:
ggplot(df2, aes(x = ManufacturingLocation, y = PowerSource, label = Model)) + geom_point(aes(size = Quantity, colour = Price, alpha=.02)) + geom_text(hjust = 1, size = 2) + scale_size(range = c(1,15)) + theme_bw()
leads to:

Using geom_jitter instead of a dot in combination with alpha:
ggplot(df2, aes(x = ManufacturingLocation, y = PowerSource, label = Model)) + geom_jitter(aes(size = Quantity, colour = Price, alpha=.02)) + geom_text(hjust = 1, size = 2) + scale_size(range = c(1,15)) + theme_bw()
produces the following:

EDIT: To avoid an artifact in the legend, alpha should be placed outside aes:
ggplot(df2, aes(x = ManufacturingLocation, y = PowerSource, label = Model)) + geom_point(aes(size = Quantity, colour = Price),alpha=.2) + geom_text(hjust = 1, size = 2) + scale_size(range = c(1,15)) + theme_bw()
as a result of:

and
ggplot(df2, aes(x = ManufacturingLocation, y = PowerSource, label = Model)) + geom_jitter(aes(size = Quantity, colour = Price),alpha=.2) + geom_text(hjust = 1, size = 2) + scale_size(range = c(1,15)) + theme_bw()
as a result of:

EDIT 2: So, it took a while to figure out.
I followed the example to which I referred in my comment. I have adjusted the code according to your needs. First of all, I created the jitter values ββoff the graph:
df2$JitCoOr <- jitter(as.numeric(factor(df2$ManufacturingLocation))) df2$JitCoOrPow <- jitter(as.numeric(factor(df2$PowerSource)))
Then I called these values ββin geom_point and geom_text x and y coordinates inside aes. This worked by flailing the bubbles and corresponding shortcuts to them. However, he messed up the x and y axis labels, so I replaced them, as you can see in scale_x_discrete and scale_y_discrete. Here is the chart code:
ggplot(df2, aes(x = ManufacturingLocation, y = PowerSource)) + geom_point(data=df2,aes(x=JitCoOr, y=JitCoOrPow,size = Quantity, colour = Price), alpha=.5)+ geom_text(data=df2,aes(x=JitCoOr, y=JitCoOrPow,label=Model)) + scale_size(range = c(1,50)) + scale_y_discrete(breaks =1:3 , labels=c("Low","High"," "), limits = c(1, 2))+ scale_x_discrete(breaks =1:4 , labels=c("Location A","Location B","Location C","Location D"), limits = c(1,2,3,4))+ theme_bw()
What gives this conclusion:

You can adjust the size of the bubbles using scale_size above. I exported this image with dimensions of 1000 * 800.
Regarding your request for adding borders, I think this is not necessary. This is very clear in this plot where there are bubbles, and I think the borders will make it a little ugly. However, if you still want boundaries, I will see what I can do.