Program: 42586
Project: 42586
Buggy source:
/** 
 * Calculates   {@link MonetarySummation} for given {@link Invoice} basing on line {@link Item}s and global   {@link io.konik.zugferd.entity.AllowanceCharge} and {@link LogisticsServiceCharge}
 * @param invoice
 * @return
 */
public static RecalculationResult recalculate(final Invoice invoice){
  assertNotNull(invoice);
  CurrencyCode currency=getCurrency(invoice);
  List<Item> items=Items.purchasableItemsOnly(invoice.getTrade().getItems());
  Settlement settlement=invoice.getTrade().getSettlement();
  TaxAggregator taxAggregator=new TaxAggregator();
  if (items.isEmpty()) {
    return new RecalculationResult(MonetarySummations.newMonetarySummation(settlement.getMonetarySummation()),taxAggregator);
  }
  MonetarySummation monetarySummation=MonetarySummations.newMonetarySummation(currency);
  monetarySummation.setAllowanceTotal(new InvoiceAllowanceTotalCalculator().apply(settlement));
  monetarySummation.setChargeTotal(new InvoiceChargeTotalCalculator().apply(settlement));
  log.debug("String_Node_Str",items.size());
  int itemsCounter=0;
  for (  Item item : items) {
    log.debug("String_Node_Str",++itemsCounter);
    log.debug("String_Node_Str",item.getProduct().getName());
    Amount lineTotal=new ItemLineTotalCalculator().apply(item);
    ItemTax itemTax=new ItemTaxExtractor().apply(item);
    log.debug("String_Node_Str",lineTotal);
    log.debug("String_Node_Str",itemTax.getPercentage());
    taxAggregator.add(itemTax,lineTotal != null ? lineTotal.getValue() : BigDecimal.ZERO);
    monetarySummation.setLineTotal(Amounts.add(monetarySummation.getLineTotal(),lineTotal));
    log.debug("String_Node_Str",monetarySummation.getLineTotal());
  }
  log.debug("String_Node_Str");
  log.debug("String_Node_Str");
  appendTaxFromInvoiceAllowanceCharge(settlement,taxAggregator);
  appendTaxFromInvoiceServiceCharge(settlement,taxAggregator);
  monetarySummation.setTaxBasisTotal(new Amount(taxAggregator.calculateTaxBasis(),currency));
  monetarySummation.setTaxTotal(new Amount(taxAggregator.calculateTaxTotal(),currency));
  monetarySummation.setGrandTotal(Amounts.add(monetarySummation.getTaxBasisTotal(),monetarySummation.getTaxTotal()));
  log.debug("String_Node_Str",monetarySummation.getGrandTotal());
  if (settlement.getMonetarySummation() != null && settlement.getMonetarySummation().getTotalPrepaid() != null) {
    monetarySummation.setTotalPrepaid(settlement.getMonetarySummation().getTotalPrepaid());
  }
  monetarySummation.setDuePayable(Amounts.add(monetarySummation.getGrandTotal(),Amounts.negate(monetarySummation.getTotalPrepaid())));
  MonetarySummation result=MonetarySummations.precise(monetarySummation,2,RoundingMode.HALF_UP);
  log.debug("String_Node_Str");
  log.debug("String_Node_Str",result);
  log.debug("String_Node_Str");
  return new RecalculationResult(result,taxAggregator);
}

Fixed version (ground truth):
/** 
 * Calculates   {@link MonetarySummation} for given {@link Invoice} basing on line {@link Item}s and global   {@link io.konik.zugferd.entity.AllowanceCharge} and {@link LogisticsServiceCharge}
 * @param invoice
 * @return
 */
public static RecalculationResult recalculate(final Invoice invoice){
  assertNotNull(invoice);
  CurrencyCode currency=getCurrency(invoice);
  List<Item> items=Items.purchasableItemsOnly(invoice.getTrade().getItems());
  Settlement settlement=invoice.getTrade().getSettlement();
  TaxAggregator taxAggregator=new TaxAggregator();
  if (items.isEmpty()) {
    return new RecalculationResult(MonetarySummations.newMonetarySummation(settlement.getMonetarySummation()),taxAggregator);
  }
  MonetarySummation monetarySummation=MonetarySummations.newMonetarySummation(currency);
  monetarySummation.setAllowanceTotal(new InvoiceAllowanceTotalCalculator().apply(settlement));
  monetarySummation.setChargeTotal(new InvoiceChargeTotalCalculator().apply(settlement));
  log.debug("String_Node_Str",items.size());
  int itemsCounter=0;
  for (  Item item : items) {
    log.debug("String_Node_Str",++itemsCounter);
    log.debug("String_Node_Str",item.getProduct() != null ? item.getProduct().getName() : "String_Node_Str");
    Amount lineTotal=new ItemLineTotalCalculator().apply(item);
    ItemTax itemTax=new ItemTaxExtractor().apply(item);
    log.debug("String_Node_Str",lineTotal);
    log.debug("String_Node_Str",itemTax.getPercentage());
    taxAggregator.add(itemTax,lineTotal != null ? lineTotal.getValue() : BigDecimal.ZERO);
    monetarySummation.setLineTotal(Amounts.add(monetarySummation.getLineTotal(),lineTotal));
    log.debug("String_Node_Str",monetarySummation.getLineTotal());
  }
  log.debug("String_Node_Str");
  log.debug("String_Node_Str");
  appendTaxFromInvoiceAllowanceCharge(settlement,taxAggregator);
  appendTaxFromInvoiceServiceCharge(settlement,taxAggregator);
  monetarySummation.setTaxBasisTotal(new Amount(taxAggregator.calculateTaxBasis(),currency));
  monetarySummation.setTaxTotal(new Amount(taxAggregator.calculateTaxTotal(),currency));
  monetarySummation.setGrandTotal(Amounts.add(monetarySummation.getTaxBasisTotal(),monetarySummation.getTaxTotal()));
  log.debug("String_Node_Str",monetarySummation.getGrandTotal());
  if (settlement.getMonetarySummation() != null && settlement.getMonetarySummation().getTotalPrepaid() != null) {
    monetarySummation.setTotalPrepaid(settlement.getMonetarySummation().getTotalPrepaid());
  }
  monetarySummation.setDuePayable(Amounts.add(monetarySummation.getGrandTotal(),Amounts.negate(monetarySummation.getTotalPrepaid())));
  MonetarySummation result=MonetarySummations.precise(monetarySummation,2,RoundingMode.HALF_UP);
  log.debug("String_Node_Str");
  log.debug("String_Node_Str",result);
  log.debug("String_Node_Str");
  return new RecalculationResult(result,taxAggregator);
}