Passed
Push — main ( 52660c...ae658f )
by Jochen
04:31
created

CartItem.__post_init__()   A

Complexity

Conditions 2

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 4
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
ccs 4
cts 4
cp 1
crap 2
1
"""
2
byceps.services.shop.cart.models
3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
5
:Copyright: 2006-2021 Jochen Kupperschmidt
6
:License: Revised BSD (see `LICENSE` file for details)
7
"""
8
9 1
from __future__ import annotations
10 1
from dataclasses import dataclass, field
11 1
from decimal import Decimal
12
13 1
from ....util.instances import ReprBuilder
14
15 1
from ..article.transfer.models import Article
16
17
18 1
@dataclass(frozen=True)
19
class CartItem:
20
    """An article with a quantity."""
21 1
    article: Article
22 1
    quantity: int
23 1
    line_amount: Decimal = field(init=False)
24
25 1
    def __post_init__(self) -> None:
26 1
        if self.quantity < 1:
27 1
            raise ValueError('Quantity must be a positive number.')
28
29 1
        object.__setattr__(self, 'line_amount', self.article.price * self.quantity)
30
31
32 1
class Cart:
33
    """A shopping cart."""
34
35 1
    def __init__(self) -> None:
36 1
        self._items: list[CartItem] = []
37
38 1
    def add_item(self, article: Article, quantity: int) -> None:
39 1
        item = CartItem(article, quantity)
40 1
        self._items.append(item)
41
42 1
    def get_items(self) -> list[CartItem]:
43 1
        return self._items
44
45 1
    def calculate_total_amount(self) -> Decimal:
46 1
        return sum(item.line_amount for item in self._items)
47
48 1
    def is_empty(self) -> bool:
49 1
        return not self._items
50
51 1
    def __repr__(self) -> str:
52 1
        item_count = len(self._items)
53
54 1
        return ReprBuilder(self) \
55
            .add_custom(f'{item_count:d} items') \
56
            .build()
57