diff --git a/README.md b/README.md index f4a2d9a..771774c 100644 --- a/README.md +++ b/README.md @@ -18,4 +18,9 @@ ### Contact +## Pagination + +## Confirmation modal on suppression +### Show on cascade deletion + ## Update contract after (without registration) diff --git a/backend/requirements.txt b/backend/requirements.txt index 1d352ae..e69de29 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -1,74 +0,0 @@ -alembic==1.18.4 -annotated-doc==0.0.4 -annotated-types==0.7.0 -anyio==4.12.1 -brotli==1.2.0 -certifi==2026.2.25 -cffi==2.0.0 -charset-normalizer==3.4.4 -click==8.3.1 -coverage==7.13.4 -cryptography==46.0.5 -cssselect2==0.9.0 -dnspython==2.8.0 -email-validator==2.3.0 -fastapi==0.133.1 -fastapi-cli==0.0.24 -fastapi-cloud-cli==0.14.0 -fastar==0.8.0 -fonttools==4.61.1 -greenlet==3.3.2 -h11==0.16.0 -httpcore==1.0.9 -httptools==0.7.1 -httpx==0.28.1 -idna==3.11 -iniconfig==2.3.0 -Jinja2==3.1.6 -lxml==6.0.2 -Mako==1.3.10 -markdown-it-py==4.0.0 -MarkupSafe==3.0.3 -mdurl==0.1.2 -odfdo==3.20.2 -packaging==26.0 -pillow==12.1.1 -pluggy==1.6.0 -psycopg2-binary==2.9.11 -pycparser==3.0 -pydantic==2.12.5 -pydantic-extra-types==2.11.0 -pydantic-settings==2.13.1 -pydantic_core==2.41.5 -pydyf==0.12.1 -Pygments==2.19.2 -PyJWT==2.11.0 -pyphen==0.17.2 -pytest==9.0.2 -pytest-cov==7.0.0 -pytest-mock==3.15.1 -python-dotenv==1.2.1 -python-multipart==0.0.22 -PyYAML==6.0.3 -requests==2.32.5 -rich==14.3.3 -rich-toolkit==0.19.7 -rignore==0.7.6 -sentry-sdk==2.53.0 -shellingham==1.5.4 -SQLAlchemy==2.0.47 -sqlmodel==0.0.37 -starlette==0.52.1 -tinycss2==1.5.1 -tinyhtml5==2.0.0 -typer==0.24.1 -typing-inspection==0.4.2 -typing_extensions==4.15.0 -urllib3==2.6.3 -uvicorn==0.41.0 -uvloop==0.22.1 -watchfiles==1.1.1 -weasyprint==68.1 -webencodings==0.5.1 -websockets==16.0 -zopfli==0.4.1 diff --git a/backend/tests/factories/contract_products.py b/backend/tests/factories/contract_products.py new file mode 100644 index 0000000..9836b17 --- /dev/null +++ b/backend/tests/factories/contract_products.py @@ -0,0 +1,59 @@ +import src.models as models +import tests.factories.contracts as contract_factory +import tests.factories.products as product_factory + +def contract_product_factory(**kwargs): + contract = contract_factory.contract_factory(id=1) + product = product_factory.product_public_factory(id=1, type=models.ProductType.RECCURENT) + data = dict( + product_id=1, + shipment_id=1, + quantity=1, + contract_id=1, + product=product, + contract=contract + ) + data.update(kwargs) + return models.ContractProduct(**data) + +def contract_product_public_factory(**kwargs): + contract = contract_factory.contract_factory(id=1) + product = product_factory.product_public_factory(id=1) + data = dict( + id=1, + product_id=1, + shipment_id=None, + contract=contract, + product=product, + shipment=None, + quantity=1 + ) + data.update(kwargs) + return models.ContractProductPublic(**data) + +def contract_product_create_factory(**kwargs): + data = dict( + product_id=1, + shipment_id=1, + quantity=1, + ) + data.update(kwargs) + return models.ContractProductCreate(**data) + +def contract_product_update_factory(**kwargs): + data = dict( + product_id=1, + shipment_id=1, + quantity=1, + ) + data.update(kwargs) + return models.ContractProductUpdate(**data) + +def contract_product_body_factory(**kwargs): + data = dict( + product_id=1, + shipment_id=1, + quantity=1, + ) + data.update(kwargs) + return data \ No newline at end of file diff --git a/backend/tests/factories/contracts.py b/backend/tests/factories/contracts.py index a315708..4454d8a 100644 --- a/backend/tests/factories/contracts.py +++ b/backend/tests/factories/contracts.py @@ -3,6 +3,7 @@ from .forms import form_factory def contract_factory(**kwargs): data = dict( + id=1, firstname="test", lastname="test", email="test@test.test", @@ -67,6 +68,9 @@ def contract_body_factory(**kwargs): phone="00000000", payment_method="cheque", cheque_quantity=1, + products=[], + cheques=[], + form_id=1 ) data.update(kwargs) return data \ No newline at end of file diff --git a/backend/tests/factories/forms.py b/backend/tests/factories/forms.py index bb2291e..2d01563 100644 --- a/backend/tests/factories/forms.py +++ b/backend/tests/factories/forms.py @@ -7,10 +7,10 @@ import datetime def form_factory(**kwargs): data = dict( id=1, - name="form 1", + name='form 1', productor_id=1, referer_id=1, - season="hiver-2026", + season='hiver-2026', start=datetime.date(2025, 10, 10), end=datetime.date(2025, 10, 10), minimum_shipment_value=0, @@ -25,12 +25,12 @@ def form_factory(**kwargs): def form_body_factory(**kwargs): data = dict( - name="form 1", + name='form 1', productor_id=1, referer_id=1, - season="hiver-2026", - start="2025-10-10", - end="2025-10-10", + season='hiver-2026', + start='2025-10-10', + end='2025-10-10', minimum_shipment_value=0, visible=True ) @@ -39,10 +39,10 @@ def form_body_factory(**kwargs): def form_create_factory(**kwargs): data = dict( - name="form 1", + name='form 1', productor_id=1, referer_id=1, - season="hiver-2026", + season='hiver-2026', start=datetime.date(2025, 10, 10), end=datetime.date(2025, 10, 10), minimum_shipment_value=0, @@ -53,10 +53,10 @@ def form_create_factory(**kwargs): def form_update_factory(**kwargs): data = dict( - name="form 1", + name='form 1', productor_id=1, referer_id=1, - season="hiver-2026", + season='hiver-2026', start=datetime.date(2025, 10, 10), end=datetime.date(2025, 10, 10), minimum_shipment_value=0, @@ -68,10 +68,10 @@ def form_update_factory(**kwargs): def form_public_factory(form=None, shipments=[],**kwargs): data = dict( id=1, - name="form 1", + name='form 1', productor_id=1, referer_id=1, - season="hiver-2026", + season='hiver-2026', start=datetime.date(2025, 10, 10), end=datetime.date(2025, 10, 10), minimum_shipment_value=0, diff --git a/backend/tests/routers/test_contracts.py b/backend/tests/routers/test_contracts.py index e71ea3d..393cadf 100644 --- a/backend/tests/routers/test_contracts.py +++ b/backend/tests/routers/test_contracts.py @@ -3,15 +3,17 @@ import src.models as models from src.main import app from src.auth.auth import get_current_user import tests.factories.contracts as contract_factory +import tests.factories.forms as form_factory +import tests.factories.contract_products as contract_products_factory from fastapi.exceptions import HTTPException class TestContracts: def test_get_all(self, client, mocker, mock_session, mock_user): mock_results = [ - contract_factory.contract_public_factory(name="test 1", id=1), - contract_factory.contract_public_factory(name="test 2", id=2), - contract_factory.contract_public_factory(name="test 3", id=3), + contract_factory.contract_public_factory(id=1), + contract_factory.contract_public_factory(id=2), + contract_factory.contract_public_factory(id=3), ] mock = mocker.patch.object( service, @@ -31,7 +33,7 @@ class TestContracts: ) def test_get_all_filters(self, client, mocker, mock_session, mock_user): mock_results = [ - contract_factory.contract_public_factory(name="test 2", id=2), + contract_factory.contract_public_factory(id=2), ] mock = mocker.patch.object( service, @@ -65,7 +67,7 @@ class TestContracts: app.dependency_overrides.clear() def test_get_one(self, client, mocker, mock_session, mock_user): - mock_result = contract_factory.contract_public_factory(name="test 2", id=2) + mock_result = contract_factory.contract_public_factory(id=2) mock = mocker.patch.object( service, @@ -123,10 +125,42 @@ class TestContracts: app.dependency_overrides.clear() def test_create_one(self, client, mocker, mock_session, mock_user): - pass + contract_body = contract_factory.contract_body_factory( + products=[ + contract_products_factory.contract_product_body_factory(product_id=1), + contract_products_factory.contract_product_body_factory(product_id=2), + contract_products_factory.contract_product_body_factory(product_id=3) + ], + cheques=[{'name': '123123', 'value': '100'}] + ) + contract_result = contract_factory.contract_factory( + products=[ + contract_products_factory.contract_product_factory(product_id=1), + contract_products_factory.contract_product_factory(product_id=2), + contract_products_factory.contract_product_factory(product_id=3) + ], + form=form_factory.form_factory(), + cheques=[models.Cheque(name='123123', value='100')] + ) + mock_create_one = mocker.patch.object( + service, + 'create_one', + return_value=contract_result + ) + mock_add_contract_file = mocker.patch.object( + service, + 'add_contract_file', + return_value=True + ) + mock_generate_html_contract = mocker.patch('src.contracts.generate_contract.generate_html_contract') + + response = client.post('/api/contracts', json=contract_body) + assert response.status_code == 200 + contract_id = 'test_test_test type_hiver-2026' + assert response.headers['Content-Disposition'] == f'attachment; filename=contract_{contract_id}.pdf' def test_delete_one(self, client, mocker, mock_session, mock_user): - contract_result = contract_factory.contract_public_factory(name='test contract delete') + contract_result = contract_factory.contract_public_factory() mock = mocker.patch.object( service, @@ -176,7 +210,7 @@ class TestContracts: def test_delete_one_unauthorized(self, client, mocker, mock_session, mock_user): def unauthorized(): raise HTTPException(status_code=401) - contract_body = contract_factory.contract_body_factory(name='test contract delete') + contract_body = contract_factory.contract_body_factory() app.dependency_overrides[get_current_user] = unauthorized