Login

ABN and ACN Form Fields

Author:
julan
Posted:
April 19, 2009
Language:
Python
Version:
1.0
Tags:
fields forms abn acn
Score:
0 (after 0 ratings)

ACNField - Australian Company Number Form Field

ABNField - Australian Business Number Form Field

Any feedback / Improvements Appreciated.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
import re

from django import forms
from django.forms.fields import Field, EMPTY_VALUES
from django.forms.util import smart_unicode

ABN_DIGITS_RE = re.compile(r'^(\d{11})$')

class ABNField(Field):
    default_error_messages = {
        'invalid': u'Australian Business Numbers must contain 11 digits.',
    }
    weights = [10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
    
    def clean(self, value):
        super(ABNField, self).clean(value)
        if value in EMPTY_VALUES:
            return u''
        
        # remove spaces from value
        value = re.sub('(\s+)', '', smart_unicode(value))
        abn_match = ABN_DIGITS_RE.search(value)
        if abn_match:
            abn = u'%s' % abn_match.group(1)
            return self.validate_abn(abn)
        raise ValidationError(self.error_messages['invalid'])
        
    def validate_abn(self, value):
        # http://www.ato.gov.au/businesses/content.asp?doc=/content/13187.htm&pc=001/003/021/002/001&mnu=610&mfp=001/003&st=&cy=1
        
        # convert to list of integers
        values = [int(i) for i in value]
        
        # subtract 1 from the first digit
        values[0] = values[0] - 1
        
        # multiple by weights
        for index, digit in enumerate(values):
            values[index] = digit * self.weights[index]
        
        # sum together 
        total_value = sum(values)
        
        # check if we can divide by 89 and have no remainder
        remainder = total_value % 89
        
        if remainder != 0:
            raise forms.ValidationError(self.error_messages['invalid'])
            
        return value


ACN_DIGITS_RE = re.compile(r'^(\d{9})$')


class ACNField(Field):
    default_error_messages = {
        'invalid': u'Australian Company Numbers must contain 9 digits.',
    }
    weights = [8, 7, 6, 5, 4, 3, 2, 1]

    def clean(self, value):
        super(ACNField, self).clean(value)
        
        if value in EMPTY_VALUES:
            return u''

        # remove spaces from value
        value = re.sub('(\s+)', '', smart_unicode(value))
        acn_match = ACN_DIGITS_RE.search(value)
        if acn_match:
            acn = u'%s' % acn_match.group(1)
            return self.validate_acn(acn)
        raise ValidationError(self.error_messages['invalid'])

    def validate_acn(self, value):
        # http://www.asic.gov.au/asic/asic.nsf/byheadline/Australian+Company+Number+(ACN)+Check+Digit
        # modified modulus 10 calculation

        # convert to list of integers
        values = [int(i) for i in value]

        # this must equal our check digit
        last_digit = values.pop(8)
        
        # multiple by weights
        for index, digit in enumerate(values):
            values[index] = digit * self.weights[index]

        # sum together 
        total_value = sum(values)

        # get the remainder of dividing by 10
        remainder = total_value % 10
        
        # subtract the remainder from 10
        check_digit = 10 - remainder
        
        if last_digit != check_digit:
            raise forms.ValidationError(self.error_messages['invalid'])

        return value

More like this

  1. "Ukrainian telephone number" model and form fields. by I159 3 years, 5 months ago
  2. UKPhoneNumberField by nathan-reynolds 6 years, 4 months ago
  3. UKPhoneNumberField GB v2 by g1smd 2 years, 6 months ago
  4. Spanish National Identification Number Field (DNI) by cues7a 3 years, 9 months ago
  5. Extended Form Wizard with ability to go backwards by mtsyganov 5 years, 11 months ago

Comments

Please login first before commenting.