package io.konik.csv.converter;
import com.neovisionaries.i18n.CurrencyCode;
import io.konik.csv.Rows;
import io.konik.csv.model.Row;
import io.konik.zugferd.Invoice;
import io.konik.zugferd.entity.TaxRegistration;
import io.konik.zugferd.entity.TradeParty;
import io.konik.zugferd.entity.trade.MonetarySummation;
import io.konik.zugferd.entity.trade.item.Item;
import io.konik.zugferd.profile.ConformanceLevel;
import io.konik.zugferd.unece.codes.DocumentCode;
import io.konik.zugferd.unece.codes.TaxCategory;
import io.konik.zugferd.unece.codes.TaxCode;
import org.assertj.core.api.Condition;
import org.assertj.core.data.Index;
import org.junit.Before;
import org.junit.Test;
import java.math.BigDecimal;
import java.math.RoundingMode;
import static org.assertj.core.api.Assertions.assertThat;
public class RowToInvoiceConverterTest {
private Invoice invoice;
private Row row;
@Before
public void setup() {
row = Rows.row1;
invoice = RowToInvoiceConverter.convert(row);
}
@Test
public void shouldConvertInvoiceWithConformanceLevelBasic() {
assertThat(invoice.getContext().getGuideline().getConformanceLevel()).isEqualTo(ConformanceLevel.EXTENDED);
}
@Test
public void shouldConvertInvoiceHeaderNumber() {
assertThat(invoice.getHeader().getInvoiceNumber()).isEqualTo(row.getHeader().getInvoiceNumber());
}
@Test
public void shouldConvertInvoiceHeaderName() {
assertThat(invoice.getHeader().getName()).isEqualTo(row.getHeader().getType());
}
@Test
public void shouldConvertDocumentCode() {
assertThat(invoice.getHeader().getCode()).isEqualTo(DocumentCode._380);
}
@Test
public void shouldConvertNote() {
assertThat(invoice.getHeader().getNotes()).hasSize(1);
assertThat(invoice.getHeader().getNotes().get(0).getContents()).hasSize(1).contains("This is simple note in two separate lines", Index.atIndex(0));
}
@Test
public void shouldConvertIssueDate() {
assertThat(invoice.getHeader().getIssued()).isEqualToIgnoringHours(row.getHeader().getIssued());
}
@Test
public void shouldConvertDueDate() {
assertThat(invoice.getHeader().getContractualDueDate()).isEqualToIgnoringHours(row.getHeader().getDueDate());
}
@Test
public void shouldConvertBuyer() {
assertThat(invoice.getTrade().getAgreement().getBuyer()).is(equalToRowTradeParty(row.getRecipient()));
}
@Test
public void shouldConvertBuyerTaxInformation() {
assertThat(invoice.getTrade().getAgreement().getBuyer().getTaxRegistrations()).hasSize(2);
assertThat(invoice.getTrade().getAgreement().getBuyer().getTaxRegistrations().get(0)).is(equalToRowTradePartyTaxInfo(row.getRecipient().getTaxes().get(0)));
assertThat(invoice.getTrade().getAgreement().getBuyer().getTaxRegistrations().get(1)).is(equalToRowTradePartyTaxInfo(row.getRecipient().getTaxes().get(1)));
}
@Test
public void shouldConvertSeller() {
assertThat(invoice.getTrade().getAgreement().getSeller()).is(equalToRowTradeParty(row.getIssuer()));
}
@Test
public void shouldConvertSellerTaxInformation() {
assertThat(invoice.getTrade().getAgreement().getSeller().getTaxRegistrations()).hasSize(1);
assertThat(invoice.getTrade().getAgreement().getSeller().getTaxRegistrations().get(0)).is(equalToRowTradePartyTaxInfo(row.getIssuer().getTaxes().get(0)));
}
@Test
public void shouldConvertCustomerNumber() {
assertThat(invoice.getTrade().getAgreement().getBuyer().getId()).isEqualTo(row.getHeader().getCustomerNumber());
}
@Test
public void shouldConvertItems() {
assertThat(invoice.getTrade().getItems()).hasSize(2);
for (int i = 0; i < row.getItems().size(); i++) {
assertThat(invoice.getTrade().getItems().get(i)).is(equalToRowItem(row.getItems().get(i), row.getHeader().getCurrency()));
}
}
@Test
public void shouldConvertMonetarySummation() {
BigDecimal lineTotal = BigDecimal.valueOf(79).add(BigDecimal.valueOf(9.99));
BigDecimal percent = BigDecimal.valueOf(19);
BigDecimal taxAmount = lineTotal.multiply(percent.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
CurrencyCode currency = row.getHeader().getCurrency();
MonetarySummation summation = invoice.getTrade().getSettlement().getMonetarySummation();
assertThat(summation.getLineTotal().getCurrency()).isEqualTo(currency);
assertThat(summation.getLineTotal().getValue()).isEqualTo(lineTotal);
assertThat(summation.getGrandTotal().getCurrency()).isEqualTo(currency);
assertThat(summation.getGrandTotal().getValue()).isEqualTo(lineTotal.add(taxAmount));
assertThat(summation.getTaxBasisTotal().getCurrency()).isEqualTo(currency);
assertThat(summation.getTaxBasisTotal().getValue()).isEqualTo(lineTotal);
assertThat(summation.getTaxTotal().getCurrency()).isEqualTo(currency);
assertThat(summation.getTaxTotal().getValue()).isEqualTo(taxAmount);
}
private Condition<TradeParty> equalToRowTradeParty(final Row.TradeParty rowTradeParty) {
return new Condition<TradeParty>() {
@Override
public boolean matches(TradeParty tradeParty) {
return tradeParty.getName().equals(rowTradeParty.getName()) &&
tradeParty.getContact().getName().equals(rowTradeParty.getContactName()) &&
tradeParty.getContact().getEmail().equals(rowTradeParty.getEmail()) &&
tradeParty.getAddress().getLineOne().equals(rowTradeParty.getAddressLine1()) &&
tradeParty.getAddress().getLineTwo().equals(rowTradeParty.getAddressLine2()) &&
tradeParty.getAddress().getCity().equals(rowTradeParty.getCity()) &&
tradeParty.getAddress().getPostcode().equals(rowTradeParty.getPostcode()) &&
tradeParty.getAddress().getCountry().equals(rowTradeParty.getCountryCode());
}
};
}
private Condition<TaxRegistration> equalToRowTradePartyTaxInfo(final Row.Tax tax) {
return new Condition<TaxRegistration>() {
@Override
public boolean matches(TaxRegistration taxRegistration) {
return taxRegistration.getTaxNumber().equals(tax.getNumber()) &&
taxRegistration.getType().equals(tax.getType());
}
};
}
private Condition<Item> equalToRowItem(final Row.Item rowItem, final CurrencyCode currencyCode) {
return new Condition<Item>() {
@Override
public boolean matches(Item item) {
BigDecimal lineTotal = rowItem.getQuantity().multiply(rowItem.getUnitPrice());
return item.getProduct().getName().equals(rowItem.getName()) &&
item.getDelivery().getBilled().getUnit().equals(rowItem.getUnit()) &&
item.getDelivery().getBilled().getValue().equals(rowItem.getQuantity()) &&
item.getDelivery().getBilled().getUnitCode().equals(rowItem.getUnit().getCode()) &&
item.getAgreement().getNetPrice().getChargeAmount().getValue().equals(rowItem.getUnitPrice()) &&
item.getAgreement().getNetPrice().getChargeAmount().getCurrency().equals(currencyCode) &&
item.getAgreement().getGrossPrice().getChargeAmount().getValue().equals(rowItem.getUnitPrice()) &&
item.getAgreement().getGrossPrice().getChargeAmount().getCurrency().equals(currencyCode) &&
item.getSettlement().getTradeTax().size() == 1 &&
item.getSettlement().getTradeTax().get(0).getPercentage().equals(rowItem.getTaxPercent()) &&
item.getSettlement().getTradeTax().get(0).getCategory().equals(TaxCategory.S) &&
item.getSettlement().getTradeTax().get(0).getType().equals(TaxCode.VAT) &&
item.getSettlement().getMonetarySummation().getLineTotal().getCurrency().equals(currencyCode) &&
item.getSettlement().getMonetarySummation().getLineTotal().getValue().equals(lineTotal);
}
};
}
}