Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for SwedishCompanyRegistrationNumber #12

Open
PeterOrneholm opened this issue Oct 12, 2018 · 6 comments
Open

Add support for SwedishCompanyRegistrationNumber #12

PeterOrneholm opened this issue Oct 12, 2018 · 6 comments

Comments

@PeterOrneholm
Copy link
Collaborator

PeterOrneholm commented Oct 12, 2018

Swedish companies all have a unique number (Organisationsnummer), called company registration number, that is used for taxes and similiar places when you need to identify a company.

As it's a common usecase and an implementation would be very similar to a PersonalIdentityNumber we aim to implement this.

Info and definitions:

@viktorvan
Copy link
Collaborator

viktorvan commented Feb 14, 2019

I would like to get started on this, so we need to put some thought into the api.
I think we should follow as closely to the PersonalIdentityNumber api as we can.

Individual firms

One special usecase is numbers for “enskild firma” (individual firm/enterprise/ sole proprietor?) where the number is the same as the individual’s personal identity number.
If our validation accepts these type of numbers by default, I feel that it may be too blunt, too allowing. We would open up for false positives where someone enters their personal identity number by mistake? Or am I wrong, is that the expected behavior?
So should we have something like:
ParseCompany(string input) {...}`` that only accepts company registration numbers and ParseIndividualFirm(string input) {...}which could delegate toSwedishIdentityNumber.Parse()andParse(string input) {...}that accepts both? But maybeParseCompanyshould be the default, and we should use another name forParse`?

12 digit numbers

What’s the deal with these? We need to be able to parse them? Is there a clear 1 to 1 relationship between 12- and 10-digit numbers? Are we guaranteed to be able to map between them?

Hints

I am ok to leave these out-of-scope for the first version.

Unified api

I.e. an additional parse-method that returns a PersonalIdentityNumber or a CompanyRegistrationNumber could be useful, but should probably be discussed in its’ own issue.

@viktorvan
Copy link
Collaborator

viktorvan commented Feb 19, 2019

After some offline discussions we reached the following conclusions:

  • Parsing individual firms
    In v1 we will have a single .Parse(string input) function that allows for company registration numbers, individual numbers (i.e. personal identity numbers) and VAT-numbers.
    We can later add overloads with options to only allow parsing a subset of numbers.

  • 10- and 12-digit numbers. We need to investigate if we can map a 10-digit number to a 12-digit numbers in all cases. E.g. can we know to use 16 or 11 as the first digits.

  • Provide a .ToVATString() function to convert a company organisation numbers to a VAT-number (i.e. prefix SE, suffix 01).

  • Hints will be considered out-of-scope for v1.

  • Separate issues will be created for External validation(External validation of company registration number #76) and Unified api (Unified api for PersonalIdentityNumber, CompanyRegistrationNumber, etc. #75) .

@PeterOrneholm
Copy link
Collaborator Author

Here is a proposed class structure. Almost identitcal as for personal identity number, but with the addition of ToVatString():

public class SwedishCompanyRegistrationNumber
{
    public SwedishCompanyRegistrationNumber(int x, int y, int z, int q, int checksum) { }

    public int X { get; set; } //TODO: Find proper name
    public int Y { get; set; } //TODO: Find proper name
    public int Z { get; set; } //TODO: Find proper name
    public int Q { get; set; } //TODO: Find proper name
    public int Checksum { get; set; }


    public SwedishCompanyRegistrationNumber ParseInSpecificYear(string s, int year) { }
    public SwedishCompanyRegistrationNumber Parse(string s) { }

    public bool TryParseInSpecificYear(string s, int year, out SwedishCompanyRegistrationNumber parseResult) { }
    public bool TryParse(string s, out SwedishCompanyRegistrationNumber parseResult) { }

    public string To10DigitStringInSpecificYear(int serializationYear) { }
    public string To10DigitString() { }
    public string To12DigitString() { }
    public string ToVatString() { }
    public string ToString() { }

    public bool Equals(object b) { }
    public int GetHashCode() { }
    public static bool operator ==(SwedishCompanyRegistrationNumber a, SwedishCompanyRegistrationNumber b) { }
}

We need to decide what the indivudual parts should be named. Year/Month/Day/Birthnumber only applies for "enksild firma", so that is not correct.

Also, we need to figure out if an "Enskild firma" ever can contain a + as delmiter. I have not so far been able to find any info on this subject. A full 12 digit version of the SwedishCompanyRegistrationNumber will contain the full year, so then it's not a problem, but when displayed as 10 digit or parsed as 10 digit it can be.

@PeterOrneholm
Copy link
Collaborator Author

PeterOrneholm commented Feb 23, 2019

Some findings that we (probably) have to handle:

  1. A Swedish coordination number can be a valid organizational number, we should therefore probably implement that first.

  2. An organizational number can contain letters, see the last section Search by registration number
    . Never heard of thit before and haven't found any spec on it yet. Example from the link OC34875.

  3. If a person using his or hers personal identity number for the firm, and has mulltiple enteprises, they should be suffixed with a number saying which one it is. Example 001, 002 etc. Full should then be: 19123456-7890001

@viktorvan
Copy link
Collaborator

viktorvan commented Feb 23, 2019

All texts I find for “Enskild firma” states that you use the owner’s personal identity number. Therefore I draw the conclusion that the same rules must apply, i.e. plus is a valid delimiter, however unlikely that situation might be.

I realize that we will need the ...InSpecificYear overloads but I do not like them.
They are for only required for “enskild firma” and only solve the use case when parsing before and after the year a person turns 100. Or am I missing something.
It is such a small subset of company registration numbers where that would apply. In reality I am guessing zero, unless an estate(?) (dödsbo) can keep using a personal identity number after a persons death?

If would like to propose an alternative api for that use case:
We remove the InSpecificYear-overloads and instead provide an option to create a CompanyRegistrationNumber from a PersonalIdentityNumber (a constructor or factory-method). And also the other way around a method .ToPersonalIdentityNumber() which you then can call .ToXXDigitStringInSpecificYear() on.
Then the use case is fulfilled (in a somewhat roundabout way) but we keep the api on CompanyRegistrationNumber free from SpecificYear-stuff which I find is definitely the hardest thing to explain to a user of our library.

@viktorvan
Copy link
Collaborator

viktorvan commented Feb 23, 2019

I have seen the suffixes before could not figure out what they meant. Great find! We should support this. But I think we should treat them as suffixes and still name our methods to12digitstring and let it return a 12digitstring + suffix. If a number has a suffix it is invalid to return it without a suffix.
Possibly we could use a flag to indicate if you want to hide the suffix if it is 001, not sure about this yet though.

I agree we need to do Coordination number first now.

We need to find more information on letters in registration numbers. The number in your link: OC34875 looks like another type of number completely.

@PeterOrneholm PeterOrneholm modified the milestones: 2.2.0, 3.0.0 Nov 11, 2019
@PeterOrneholm PeterOrneholm removed this from the 3.0.0 milestone May 6, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants