Skip to content

Commit

Permalink
Fix inconsistent EAN checksums generation
Browse files Browse the repository at this point in the history
Fixes: #196
  • Loading branch information
WhyNotHugo committed Sep 20, 2023
1 parent c5fac0a commit d804837
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 12 deletions.
32 changes: 20 additions & 12 deletions barcode/ean.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,20 @@ class EuropeanArticleNumber13(Barcode):

digits = 12

@property
def ean(self) -> str:
"""The raw value, with the checksum appended, if applicable.
This helper exists mainly for backwards compatibility.
"""
ean = self._raw_value
# If no checksum
if self.no_checksum:
# Add a thirteen char if given in parameter,
# otherwise pad with zero
return f"{ean}{ean[self.digits] if len(ean) > self.digits else 0}"
return f"{ean}{self.calculate_checksum()}"

def __init__(self, ean, writer=None, no_checksum=False, guardbar=False) -> None:
ean = ean[: self.digits]
if not ean.isdigit():
Expand All @@ -51,14 +65,8 @@ def __init__(self, ean, writer=None, no_checksum=False, guardbar=False) -> None:
raise NumberOfDigitsError(
f"EAN must have {self.digits} digits, not {len(ean)}."
)
self.ean = ean
# If no checksum
if no_checksum:
# Add a thirteen char if given in parameter,
# otherwise pad with zero
self.ean = f"{ean}{ean[self.digits] if len(ean) > self.digits else 0}"
else:
self.ean = f"{ean}{self.calculate_checksum()}"
self._raw_value = ean
self.no_checksum = no_checksum

self.guardbar = guardbar
if guardbar:
Expand Down Expand Up @@ -86,8 +94,8 @@ def calculate_checksum(self) -> int:
def sum_(x, y):
return int(x) + int(y)

evensum = reduce(sum_, self.ean[-2::-2])
oddsum = reduce(sum_, self.ean[-1::-2])
evensum = reduce(sum_, self._raw_value[-2::-2])
oddsum = reduce(sum_, self._raw_value[-1::-2])
return (10 - ((evensum + oddsum * 3) % 10)) % 10

def build(self):
Expand Down Expand Up @@ -220,8 +228,8 @@ def calculate_checksum(self):
def sum_(x, y):
return int(x) + int(y)

evensum = reduce(sum_, self.ean[::2])
oddsum = reduce(sum_, self.ean[1::2])
evensum = reduce(sum_, self._raw_value[::2])
oddsum = reduce(sum_, self._raw_value[1::2])
return (10 - (((evensum * 3) + oddsum) % 10)) % 10


Expand Down
11 changes: 11 additions & 0 deletions tests/test_ean.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from __future__ import annotations

from barcode.ean import EAN13


def test_ean_checksum() -> None:
ean = EAN13("842169142322") # input has 12 digits
assert ean.calculate_checksum() == 0

ean = EAN13("8421691423220") # input has 13 digits
assert ean.calculate_checksum() == 0

0 comments on commit d804837

Please sign in to comment.