Slightly improved logging when account assignments are missing or broken.
diff --git a/service/src/main/java/io/mifos/portfolio/service/internal/command/handler/ProductCommandHandler.java b/service/src/main/java/io/mifos/portfolio/service/internal/command/handler/ProductCommandHandler.java
index 7173e76..6693e03 100644
--- a/service/src/main/java/io/mifos/portfolio/service/internal/command/handler/ProductCommandHandler.java
+++ b/service/src/main/java/io/mifos/portfolio/service/internal/command/handler/ProductCommandHandler.java
@@ -145,11 +145,18 @@
               .map(ChargeDefinitionMapper::map)
               .collect(Collectors.toList());
 
-      if (!AccountingAdapter.accountAssignmentsCoverChargeDefinitions(accountAssignments, chargeDefinitions))
-        throw ServiceException.conflict("Not ready to enable product '" + changeEnablingOfProductCommand.getProductIdentifier() + "'. One or more of the charge definitions contains a designator for which no account assignment exists.");
+      final Set<String> accountAssignmentsRequiredButNotProvided
+          = AccountingAdapter.accountAssignmentsRequiredButNotProvided(accountAssignments, chargeDefinitions);
+      if (!accountAssignmentsRequiredButNotProvided.isEmpty())
+        throw ServiceException.conflict("Not ready to enable product ''{0}''. One or more of the charge definitions " +
+            "contains a designator for which no account assignment exists. Here are the unassigned designators ''{1}''",
+            changeEnablingOfProductCommand.getProductIdentifier(), accountAssignmentsRequiredButNotProvided);
 
-      if (!accountingAdapter.accountAssignmentsRepresentRealAccounts(accountAssignments))
-        throw ServiceException.conflict("Not ready to enable product '" + changeEnablingOfProductCommand.getProductIdentifier() + "'. One or more of the account assignments points to an account or ledger which does not exist.");
+      final Set<String> accountAssignmentsMappedToNonexistentAccounts = accountingAdapter.accountAssignmentsMappedToNonexistentAccounts(accountAssignments);
+      if (!accountAssignmentsMappedToNonexistentAccounts.isEmpty())
+        throw ServiceException.conflict("Not ready to enable product ''{0}''. The following account assignments point " +
+            "to an account or ledger which does not exist ''{1}''.", changeEnablingOfProductCommand.getProductIdentifier(),
+            accountAssignmentsMappedToNonexistentAccounts);
     }
 
     productEntity.setEnabled(changeEnablingOfProductCommand.getEnabled());
diff --git a/service/src/main/java/io/mifos/portfolio/service/internal/service/ProductService.java b/service/src/main/java/io/mifos/portfolio/service/internal/service/ProductService.java
index 7d8b475..5d0d92b 100644
--- a/service/src/main/java/io/mifos/portfolio/service/internal/service/ProductService.java
+++ b/service/src/main/java/io/mifos/portfolio/service/internal/service/ProductService.java
@@ -115,7 +115,7 @@
     final Product product = maybeProduct.get();
     final Set<AccountAssignment> accountAssignments = product.getAccountAssignments();
     final List<ChargeDefinition> chargeDefinitions = chargeDefinitionService.findAllEntities(identifier);
-    return AccountingAdapter.accountAssignmentsCoverChargeDefinitions(accountAssignments, chargeDefinitions);
+    return AccountingAdapter.accountAssignmentsRequiredButNotProvided(accountAssignments, chargeDefinitions).isEmpty();
   }
 
   public Set<AccountAssignment> getIncompleteAccountAssignments(final String identifier) {
diff --git a/service/src/main/java/io/mifos/portfolio/service/internal/util/AccountingAdapter.java b/service/src/main/java/io/mifos/portfolio/service/internal/util/AccountingAdapter.java
index 341d2d7..60b6cd8 100644
--- a/service/src/main/java/io/mifos/portfolio/service/internal/util/AccountingAdapter.java
+++ b/service/src/main/java/io/mifos/portfolio/service/internal/util/AccountingAdapter.java
@@ -192,14 +192,18 @@
   }
 
 
-  public static boolean accountAssignmentsCoverChargeDefinitions(
+  public static Set<String> accountAssignmentsRequiredButNotProvided(
           final Set<AccountAssignment> accountAssignments,
           final List<ChargeDefinition> chargeDefinitionEntities) {
     final Set<String> allAccountDesignatorsRequired = getRequiredAccountDesignators(chargeDefinitionEntities);
     final Set<String> allAccountDesignatorsDefined = accountAssignments.stream().map(AccountAssignment::getDesignator)
             .collect(Collectors.toSet());
-    return allAccountDesignatorsDefined.containsAll(allAccountDesignatorsRequired);
-
+    if (allAccountDesignatorsDefined.containsAll(allAccountDesignatorsRequired))
+      return Collections.emptySet();
+    else {
+      allAccountDesignatorsRequired.removeAll(allAccountDesignatorsDefined);
+      return allAccountDesignatorsRequired;
+    }
   }
 
   public static Set<String> getRequiredAccountDesignators(final Collection<ChargeDefinition> chargeDefinitionEntities) {
@@ -224,9 +228,12 @@
       retBuilder.add(accountDesignator);
   }
 
-  public boolean accountAssignmentsRepresentRealAccounts(final Set<AccountAssignment> accountAssignments)
+  public Set<String> accountAssignmentsMappedToNonexistentAccounts(final Set<AccountAssignment> accountAssignments)
   {
-    return accountAssignments.stream().allMatch(this::accountAssignmentRepresentsRealAccount);
+    return accountAssignments.stream()
+        .filter(x -> !accountAssignmentRepresentsRealAccount(x))
+        .map(AccountAssignment::getDesignator)
+        .collect(Collectors.toSet());
   }
 
   public boolean accountAssignmentRepresentsRealAccount(final AccountAssignment accountAssignment) {