package io.codearte.jfairy.producer.company.locale.sv;
import io.codearte.jfairy.producer.BaseProducer;
import io.codearte.jfairy.producer.DateProducer;
import io.codearte.jfairy.producer.VATIdentificationNumberProvider;
import io.codearte.jfairy.producer.person.NationalIdentificationNumberFactory;
import io.codearte.jfairy.producer.person.NationalIdentificationNumberProvider;
import org.joda.time.DateTime;
import javax.inject.Inject;
import static io.codearte.jfairy.producer.person.NationalIdentificationNumberProperties.dateOfBirth;
import static io.codearte.jfairy.producer.person.locale.sv.SvNationalIdentificationNumberProvider.calculateChecksum;
import static java.lang.String.valueOf;
import static org.apache.commons.lang3.RandomStringUtils.randomNumeric;
import static org.apache.commons.lang3.StringUtils.leftPad;
/**
* Swedish VAT Identification Number (known as Momsnummer in Sweden)
* <p>
* https://en.wikipedia.org/wiki/VAT_identification_number
*/
public class SvVATIdentificationNumberProvider implements VATIdentificationNumberProvider {
private static final int VAT_IDENTIFICATION_NUMBER_LENGTH = 14;
private static final int SOLE_TRADER_UPPER_AGE_LIMIT = 16;
private static final int SOLE_TRADER_LOWER_AGE_LIMIT = 100;
private static final String SE = "SE";
private final BaseProducer baseProducer;
private final DateProducer dateProducer;
private final NationalIdentificationNumberFactory nationalIdentificationNumberFactory;
@Inject
public SvVATIdentificationNumberProvider(BaseProducer baseProducer, DateProducer dateProducer,
NationalIdentificationNumberFactory nationalIdentificationNumberFactory) {
this.baseProducer = baseProducer;
this.dateProducer = dateProducer;
this.nationalIdentificationNumberFactory = nationalIdentificationNumberFactory;
}
@Override
public String get() {
boolean isSoleTrader = baseProducer.trueOrFalse(); // Approximately 50% probablilty of a company to be of type sole trader (enskild firma)
if (isSoleTrader) {
return generateVatNumberForSoleTrader();
}
int randomGroupNumber = baseProducer.randomElement(GroupNumber.class).getValue();
String randomNumericBetween20And99 = leftPad(valueOf(baseProducer.randomBetween(20, 99)), 2, "0");
String organizationNumberWithoutChecksum = randomGroupNumber + randomNumeric(1) + randomNumericBetween20And99 + randomNumeric(5);
String organizationNumber = organizationNumberWithoutChecksum + calculateChecksum(organizationNumberWithoutChecksum);
return SE + organizationNumber + "01";
}
private String generateVatNumberForSoleTrader() {
DateTime lowerAgeLimit = DateTime.now().minusYears(SOLE_TRADER_LOWER_AGE_LIMIT);
DateTime upperAgeLimit = DateTime.now().minusYears(SOLE_TRADER_UPPER_AGE_LIMIT);
DateTime dateOfBirth = dateProducer.randomDateBetweenTwoDates(lowerAgeLimit, upperAgeLimit);
NationalIdentificationNumberProvider nationalIdentificationNumberProvider = nationalIdentificationNumberFactory.produceNationalIdentificationNumberProvider(
dateOfBirth(dateOfBirth));
String personalIdentityNumber = nationalIdentificationNumberProvider.get().getValue();
return SE + personalIdentityNumber.replace("-", "") + "01";
}
/**
* @param vatIdentificationNumber Swedish VAT Identification Number
* @return vatIdentificationNumber validity
*/
public static boolean isValid(String vatIdentificationNumber) {
int length = vatIdentificationNumber.length();
if (length != VAT_IDENTIFICATION_NUMBER_LENGTH) {
return false;
}
int checksum = Integer.valueOf(Character.toString(vatIdentificationNumber.charAt(length - 3)));
int checkDigit = calculateChecksum(vatIdentificationNumber.substring(2, vatIdentificationNumber.length() - 2));
return checkDigit == checksum;
}
/**
* Group number used to determine the first numer in a swedish organization number
* Enum is translated from swedish wiki https://sv.wikipedia.org/wiki/Organisationsnummer
*/
private enum GroupNumber {
ESTATE(1), // Dödsbon
STATE_OR_COUNTY_OR_MUNICIPALITY_OR_PARISH(2), // Stat, landsting, kommuner, församlingar
FOREIGN_COMPANY(3), // Utländska företag som bedriver näringsverksamhet eller äger fastigheter i Sverige
LIMITED_COMPANY(5), // Aktiebolag
PARTNERSHIP(6), // Enkelt bolag
ECONOMIC_ASSOCIATION(7), // Ekonomiska föreningar
NON_PROFIT_ASSOCIATION_OR_FOUNDATION(8), // Ideella föreningar och stiftelser
TRADING_COMPANY_OR_LIMITED_COMPANY_OR_PARTNERSHIP(9); // Handelsbolag, kommanditbolag och enkla bolag
private final int value;
GroupNumber(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
}