There is one gotcha when using loadByProperties with entityTypeManager. When normally loading entities like
$coupon = \Drupal::entityTypeManager()->getStorage('commerce_promotion_coupon')->load(3);
you get straight entity object in $coupon and you can set some value with $coupon->usage_limit->value = 10; and do $coupon->save(); but with loadByProperties you get an array
$coupon = \Drupal::entityTypeManager()->getStorage('commerce_promotion_coupon')-> loadByProperties(['id' => '3']);
so to do something with it you need to pick from array, so you either use php reset function to get first element
$coupon = reset(\Drupal::entityTypeManager()->getStorage('commerce_promotion_coupon')-> loadByProperties(['id' => '3']));
or us foreach loop on it and iterate over elements.
This is basic but when getting only one result easily overlooked.