Skip to content

Commit

Permalink
Merge pull request #43 from kmee/recopi
Browse files Browse the repository at this point in the history
[ADD] Recopi validation - Issue #28
  • Loading branch information
mileo authored May 22, 2023
2 parents 3a5edbf + 9d1c3ce commit 29c9178
Show file tree
Hide file tree
Showing 2 changed files with 200 additions and 0 deletions.
162 changes: 162 additions & 0 deletions src/erpbrasil/base/fiscal/recopi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
# coding=utf-8
# Copyright (C) 2023 Daniel Venancio - KMEE
# License MIT - See https://opensource.org/license/mit
import datetime as dt

CURRENT_YEAR = dt.date.today().year
CURRENT_MONTH = dt.date.today().month
CURRENT_DAY = dt.date.today().day
VERIFICATION_DIGIT_WEIGHT = [
19,
18,
17,
16,
15,
14,
13,
12,
11,
10,
9,
8,
7,
6,
5,
4,
3,
2,
1,
]


def is_valid_recopi(recopi):
if _check_recopi_size(recopi):
if _check_recopi_format(recopi):
return True
return False


def generate_valid_recopi():
recopi_date = _generate_recopi_date()
recopi_hour = _generate_recopi_hour()
recopi_four_digits = _generate_recopi_four_digits()
recopi_verification_digits = _generate_recopi_verification_digits(
recopi_date + recopi_hour + recopi_four_digits
)
recopi = recopi_date + recopi_hour + recopi_four_digits + recopi_verification_digits
return recopi


def _check_recopi_size(recopi):
if len(recopi) == 20:
return True
return False


def _check_recopi_format(recopi):
return (
_check_recopi_date(recopi)
and _check_recopi_time(recopi)
and _check_recopi_verification_digits(recopi)
)


def _check_recopi_date(recopi):
recopi_year, recopi_month, recopi_day = get_recopi_date(recopi)
try:
dt.date(
year=recopi_year, month=recopi_month, day=recopi_day
) # _check if it's a calendar date
if recopi_year > CURRENT_YEAR:
return True
elif recopi_year == CURRENT_YEAR and recopi_month > CURRENT_MONTH:
return True
elif recopi_year < 2013:
return True

return False
except Exception:
return False


def get_recopi_date(recopi):
recopi_year = int(recopi[0:4])
recopi_month = int(recopi[4:6])
recopi_day = int(recopi[6:8])
return recopi_year, recopi_month, recopi_day


def _check_recopi_time(recopi):
recopi_hour, recopi_minute, recopi_second = get_recopi_time(recopi)
try:
dt.datetime(
year=2003,
month=4,
day=21,
hour=recopi_hour,
minute=recopi_minute,
second=recopi_second,
)
return True
except Exception:
return False


def get_recopi_time(recopi):
recopi_hour = int(recopi[8:10])
recopi_minute = int(recopi[10:12])
recopi_second = int(recopi[12:14])
return recopi_hour, recopi_minute, recopi_second


def _check_recopi_verification_digits(recopi):
return _check_recopi_first_verification_digit(
recopi
) and _check_recopi_second_verification_digit(recopi)


def _check_recopi_first_verification_digit(recopi):
if calculate_first_verification_digit(recopi) == int(recopi[18]):
return True
return False


def calculate_first_verification_digit(recopi):
sum = 0
for count in range(0, 18):
sum = sum + (int(recopi[count]) * VERIFICATION_DIGIT_WEIGHT[count + 1])
return 11 - (sum % 11)


def _check_recopi_second_verification_digit(recopi):
if calculate_second_verification_digit(recopi) == int(recopi[19]):
return True
return False


def calculate_second_verification_digit(recopi):
sum = 0
for count in range(0, 19):
sum = sum + (int(recopi[count]) * VERIFICATION_DIGIT_WEIGHT[count])
return 11 - (sum % 11)


def _generate_recopi_date():
return str(CURRENT_YEAR + 1) + "0101"


def _generate_recopi_hour():
return "080000"


def _generate_recopi_four_digits():
return "1234"


def _generate_recopi_verification_digits(inicial_digits):
first_verification_digit = str(calculate_first_verification_digit(inicial_digits))
second_verification_digit = str(
calculate_second_verification_digit(inicial_digits + first_verification_digit)
)

return first_verification_digit + second_verification_digit
38 changes: 38 additions & 0 deletions tests/test_base_fiscal_recopi_validation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# coding=utf-8
# Copyright (C) 2023 Daniel Venancio - KMEE
# License MIT - See https://opensource.org/license/mit
from unittest import TestCase

from erpbrasil.base.fiscal import recopi


class RecopiValidation(TestCase):
def setUp(self):
self.valid_recopi = recopi.generate_valid_recopi()
self.invalid_recopi_date = "20220229114609734393"
self.invalid_recopi_no_calendar = "20250229114609734393"
self.invalid_recopi_time = "20240229274609734393"
self.invalid_recopi_verification_digit1 = "20231106114609734372"
self.invalid_recopi_verification_digit2 = "20231106114609734343"

def test_validate_recopi(self):
test_result = recopi.is_valid_recopi(self.valid_recopi)
self.assertEqual(True, test_result)

def test_validate_recopi_date(self):
test_result = recopi.is_valid_recopi(self.invalid_recopi_date)
self.assertEqual(False, test_result)

test_result = recopi.is_valid_recopi(self.invalid_recopi_no_calendar)
self.assertEqual(False, test_result)

def test_validate_recopi_time(self):
test_result = recopi.is_valid_recopi(self.invalid_recopi_time)
self.assertEqual(False, test_result)

def test_validate_recopi_verification_digits(self):
test_result = recopi.is_valid_recopi(self.invalid_recopi_verification_digit1)
self.assertEqual(False, test_result)

test_result = recopi.is_valid_recopi(self.invalid_recopi_verification_digit2)
self.assertEqual(False, test_result)

0 comments on commit 29c9178

Please sign in to comment.