Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. from datetime import date, datetime
  2. from calendar import monthrange
  3. import re
  4. from django import forms
  5. from oscar.services import import_module
  6. address_models = import_module('address.models', ['Country'])
  7. order_models = import_module('order.models', ['BillingAddress'])
  8. payment_models = import_module('payment.models', ['Bankcard'])
  9. VISA, MASTERCARD, AMEX, MAESTRO, DISCOVER = ('Visa', 'Mastercard', 'American Express', 'Maestro', 'Discover')
  10. def bankcard_type(number):
  11. number = str(number)
  12. if len(number) == 13:
  13. if number[0] == "4":
  14. return VISA
  15. elif len(number) == 14:
  16. if number[:2] == "36":
  17. return MASTERCARD
  18. elif len(number) == 15:
  19. if number[:2] in ("34", "37"):
  20. return AMEX
  21. elif len(number) == 16:
  22. if number[:4] == "6011":
  23. return DISCOVER
  24. if number[:2] in ("51", "52", "53", "54", "55"):
  25. return MASTERCARD
  26. if number[0] == "4":
  27. return VISA
  28. return None
  29. class BankcardField(forms.CharField):
  30. def clean(self, value):
  31. """Check if given CC number is valid and one of the
  32. card types we accept"""
  33. non_decimal = re.compile(r'\D+')
  34. value = non_decimal.sub('', value.strip())
  35. if value and (len(value) < 13 or len(value) > 16):
  36. raise forms.ValidationError("Please enter a valid credit card number.")
  37. return super(BankcardField, self).clean(value)
  38. class BankcardMonthWidget(forms.MultiWidget):
  39. """
  40. Widget containing two select boxes for selecting the month and year
  41. """
  42. def decompress(self, value):
  43. return [value.month, value.year] if value else [None, None]
  44. def format_output(self, rendered_widgets):
  45. html = u' '.join(rendered_widgets)
  46. return u'<span style="white-space: nowrap">%s</span>' % html
  47. class BankcardMonthField(forms.MultiValueField):
  48. """
  49. A modified version of the snippet: http://djangosnippets.org/snippets/907/
  50. """
  51. default_error_messages = {
  52. 'invalid_month': u'Enter a valid month.',
  53. 'invalid_year': u'Enter a valid year.',
  54. }
  55. def __init__(self, *args, **kwargs):
  56. errors = self.default_error_messages.copy()
  57. if 'error_messages' in kwargs:
  58. errors.update(kwargs['error_messages'])
  59. fields = (
  60. forms.ChoiceField(choices=self.month_choices(),
  61. error_messages={'invalid': errors['invalid_month']}),
  62. forms.ChoiceField(choices=self.year_choices(),
  63. error_messages={'invalid': errors['invalid_year']}),
  64. )
  65. super(BankcardMonthField, self).__init__(fields, *args, **kwargs)
  66. self.widget = BankcardMonthWidget(widgets = [fields[0].widget, fields[1].widget])
  67. def month_choices(self):
  68. return []
  69. def year_choices(self):
  70. return []
  71. class BankcardExpiryMonthField(BankcardMonthField):
  72. """
  73. Expiry month
  74. """
  75. def month_choices(self):
  76. return [("%.2d" % x, "%.2d" % x) for x in xrange(1, 13)]
  77. def year_choices(self):
  78. return [(x, x) for x in xrange( date.today().year, date.today().year+5)]
  79. def clean(self, value):
  80. expiry_date = super(BankcardExpiryMonthField, self).clean(value)
  81. if date.today() > expiry_date:
  82. raise forms.ValidationError("The expiration date you entered is in the past.")
  83. return expiry_date
  84. def compress(self, data_list):
  85. if data_list:
  86. if data_list[1] in forms.fields.EMPTY_VALUES:
  87. error = self.error_messages['invalid_year']
  88. raise forms.ValidationError(error)
  89. if data_list[0] in forms.fields.EMPTY_VALUES:
  90. error = self.error_messages['invalid_month']
  91. raise forms.ValidationError(error)
  92. year = int(data_list[1])
  93. month = int(data_list[0])
  94. # find last day of the month
  95. day = monthrange(year, month)[1]
  96. return date(year, month, day)
  97. return None
  98. class BankcardStartingMonthField(BankcardMonthField):
  99. """
  100. Starting month
  101. """
  102. def month_choices(self):
  103. months = [("%.2d" % x, "%.2d" % x) for x in xrange(1, 13)]
  104. months.insert(0, ("", "--"))
  105. return months
  106. def year_choices(self):
  107. years = [(x, x) for x in xrange( date.today().year - 5, date.today().year)]
  108. years.insert(0, ("", "--"))
  109. return years
  110. def clean(self, value):
  111. starting_date = super(BankcardMonthField, self).clean(value)
  112. if starting_date and date.today() < starting_date:
  113. raise forms.ValidationError("The starting date you entered is in the future.")
  114. return starting_date
  115. def compress(self, data_list):
  116. if data_list:
  117. if data_list[1] in forms.fields.EMPTY_VALUES:
  118. error = self.error_messages['invalid_year']
  119. raise forms.ValidationError(error)
  120. if data_list[0] in forms.fields.EMPTY_VALUES:
  121. error = self.error_messages['invalid_month']
  122. raise forms.ValidationError(error)
  123. year = int(data_list[1])
  124. month = int(data_list[0])
  125. return date(year, month, 1)
  126. return None
  127. class BankcardForm(forms.ModelForm):
  128. number = BankcardField(max_length=20, widget=forms.TextInput(attrs={'autocomplete':'off'}), label="Card number")
  129. name = forms.CharField(max_length=128, label="Name on card")
  130. ccv_number = forms.IntegerField(required=True, label="CCV Number",
  131. max_value = 9999, widget=forms.TextInput(attrs={'size': '4'}))
  132. start_month = BankcardStartingMonthField(label="Valid from", required=False)
  133. expiry_month = BankcardExpiryMonthField(required=True, label = "Valid to")
  134. class Meta:
  135. model = payment_models.Bankcard
  136. exclude = ('user', 'partner_reference')
  137. fields = ('number', 'name', 'start_month', 'expiry_month', 'ccv_number')
  138. class BillingAddressForm(forms.ModelForm):
  139. def __init__(self, *args, **kwargs):
  140. super(BillingAddressForm,self ).__init__(*args, **kwargs)
  141. self.set_country_queryset()
  142. def set_country_queryset(self):
  143. self.fields['country'].queryset = address_models.Country._default_manager.all()
  144. class Meta:
  145. model = order_models.BillingAddress