add max payment method for cheque
All checks were successful
Deploy Amap / deploy (push) Successful in 34s

This commit is contained in:
Julien Aldon
2026-02-20 17:36:32 +01:00
parent 72f8005fbd
commit 85a70da07d
10 changed files with 75 additions and 32 deletions

View File

@@ -2,10 +2,11 @@
## backend\src\contracts\contracts.py ## backend\src\contracts\contracts.py
- Send contract to referer
- Extract recap - Extract recap
- Extract all contracts
- store total price ## Payment method max cheque number
## Link products to a form
## Wording ## Wording
@@ -28,14 +29,4 @@
### Contact ### Contact
## Migrations ## Update contract after (without registration)
- use alembic for migration management
## Filter forms in home view
## Only show current season (if multiple form, only show the one with latest start date)
## Update contract after register
## Default filter

View File

@@ -0,0 +1,33 @@
"""message
Revision ID: 7854064278ce
Revises: c0b1073a8394
Create Date: 2026-02-20 17:17:25.739406
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import sqlmodel.sql.sqltypes
# revision identifiers, used by Alembic.
revision: str = '7854064278ce'
down_revision: Union[str, Sequence[str], None] = 'c0b1073a8394'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
"""Upgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('paymentmethod', sa.Column('max', sa.Integer(), nullable=True))
# ### end Alembic commands ###
def downgrade() -> None:
"""Downgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('paymentmethod', 'max')
# ### end Alembic commands ###

View File

@@ -36,6 +36,7 @@ class UserCreate(UserBase):
class PaymentMethodBase(SQLModel): class PaymentMethodBase(SQLModel):
name: str name: str
details: str details: str
max: int | None
class PaymentMethod(PaymentMethodBase, table=True): class PaymentMethod(PaymentMethodBase, table=True):
id: int | None = Field(default=None, primary_key=True) id: int | None = Field(default=None, primary_key=True)

View File

@@ -47,7 +47,8 @@ def update_one(session: Session, id: int, productor: models.ProductorUpdate) ->
models.PaymentMethod( models.PaymentMethod(
name=pm["name"], name=pm["name"],
details=pm["details"], details=pm["details"],
productor_id=id productor_id=id,
max=pm["max"]
) )
) )
del productor_updates["payment_methods"] del productor_updates["payment_methods"]

View File

@@ -92,6 +92,8 @@
"templates": "templates", "templates": "templates",
"users": "users", "users": "users",
"forms": "contract forms", "forms": "contract forms",
"max cheque number": "max cheque number",
"can be empty default to 3": "can be empty default to 3",
"form": "contract form", "form": "contract form",
"select a form": "select a form", "select a form": "select a form",
"download contracts": "download contracts", "download contracts": "download contracts",

View File

@@ -94,6 +94,8 @@
"by selecting a form here you can download all contracts of your form": "en selectionnant un formulaire, vous téléchargez tous les contrats pour un formulaire donné.", "by selecting a form here you can download all contracts of your form": "en selectionnant un formulaire, vous téléchargez tous les contrats pour un formulaire donné.",
"edit user": "modifier l'utilisateur·trice", "edit user": "modifier l'utilisateur·trice",
"remove user": "supprimer l'utilisateur·trice", "remove user": "supprimer l'utilisateur·trice",
"max cheque number": "numbre maximum de cheques possible",
"can be empty default to 3": "optionnel, la valeur par défaut est à 3 cheques",
"all forms": "tous les formulaires de contrat", "all forms": "tous les formulaires de contrat",
"create new form": "créer un nouveau formulaire de contrat", "create new form": "créer un nouveau formulaire de contrat",
"actions": "actions", "actions": "actions",

View File

@@ -1,13 +1,14 @@
import { t } from "@/config/i18n"; import { t } from "@/config/i18n";
import type { ContractInputs } from "@/services/resources/contracts"; import type { ContractInputs } from "@/services/resources/contracts";
import { Group, NumberInput, Stack, Text, TextInput, Title } from "@mantine/core"; import type { Productor } from "@/services/resources/productors";
import { Group, NumberInput, Stack, TextInput, Title } from "@mantine/core";
import type { UseFormReturnType } from "@mantine/form"; import type { UseFormReturnType } from "@mantine/form";
import { useEffect } from "react"; import { useEffect, useMemo } from "react";
export type ContractChequeProps = { export type ContractChequeProps = {
inputForm: UseFormReturnType<ContractInputs>; inputForm: UseFormReturnType<ContractInputs>;
price: number; price: number;
chequeOrder: string; productor: Productor;
}; };
export type Cheque = { export type Cheque = {
@@ -15,7 +16,7 @@ export type Cheque = {
value: string; value: string;
}; };
export function ContractCheque({ inputForm, price, chequeOrder }: ContractChequeProps) { export function ContractCheque({ inputForm, price, productor }: ContractChequeProps) {
useEffect(() => { useEffect(() => {
if (!inputForm.values.payment_method.includes("cheque")) { if (!inputForm.values.payment_method.includes("cheque")) {
return; return;
@@ -41,9 +42,13 @@ export function ContractCheque({ inputForm, price, chequeOrder }: ContractCheque
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [inputForm.values.cheque_quantity, price, inputForm.values.cheques]); }, [inputForm.values.cheque_quantity, price, inputForm.values.cheques]);
const paymentMethod = useMemo(() => {
return productor?.payment_methods.find((el) => el.name === "cheque")
}, [productor]);
return ( return (
<Stack> <Stack>
<Title order={4}>{`${t("order name")} : ${chequeOrder}`}</Title> <Title order={4}>{`${t("order name")} : ${paymentMethod?.details}`}</Title>
<NumberInput <NumberInput
label={t("cheque quantity", { capfirst: true })} label={t("cheque quantity", { capfirst: true })}
placeholder={t("enter cheque quantity", { capfirst: true })} placeholder={t("enter cheque quantity", { capfirst: true })}
@@ -52,7 +57,7 @@ export function ContractCheque({ inputForm, price, chequeOrder }: ContractCheque
{ capfirst: true }, { capfirst: true },
)} )}
min={1} min={1}
max={3} max={paymentMethod?.max || 3}
{...inputForm.getInputProps(`cheque_quantity`)} {...inputForm.getInputProps(`cheque_quantity`)}
/> />
<Group grow> <Group grow>
@@ -64,7 +69,7 @@ export function ContractCheque({ inputForm, price, chequeOrder }: ContractCheque
{...inputForm.getInputProps(`cheques.${index}.name`)} {...inputForm.getInputProps(`cheques.${index}.name`)}
error={ error={
cheque.name == "" ? cheque.name == "" ?
<Text size="sm" c="red">{inputForm?.errors.cheques}</Text> : inputForm?.errors.cheques :
null null
} }
/> />

View File

@@ -3,7 +3,9 @@ import {
Group, Group,
Modal, Modal,
MultiSelect, MultiSelect,
NumberInput,
Select, Select,
Stack,
TextInput, TextInput,
Title, Title,
type ModalBaseProps, type ModalBaseProps,
@@ -107,6 +109,7 @@ export function ProductorModal({
existing ?? { existing ?? {
name, name,
details: "", details: "",
max: null,
} }
); );
}), }),
@@ -115,12 +118,19 @@ export function ProductorModal({
/> />
{form.values.payment_methods.map((method, index) => {form.values.payment_methods.map((method, index) =>
method.name === "cheque" ? ( method.name === "cheque" ? (
<Stack key={index}>
<TextInput <TextInput
key={index}
label={t("order name", { capfirst: true })} label={t("order name", { capfirst: true })}
placeholder={t("order name", { capfirst: true })} placeholder={t("order name", { capfirst: true })}
{...form.getInputProps(`payment_methods.${index}.details`)} {...form.getInputProps(`payment_methods.${index}.details`)}
/> />
<NumberInput
label={t("max cheque number", { capfirst: true })}
placeholder={t("max cheque number", { capfirst: true })}
description={t("can be empty default to 3", {capfirst: true})}
{...form.getInputProps(`payment_methods.${index}.max`)}
/>
</Stack>
) : null, ) : null,
)} )}
<Group mt="sm" justify="space-between"> <Group mt="sm" justify="space-between">

View File

@@ -286,10 +286,7 @@ export function Contract() {
/> />
{inputForm.values.payment_method === "cheque" ? ( {inputForm.values.payment_method === "cheque" ? (
<ContractCheque <ContractCheque
chequeOrder={ productor={form?.productor}
form?.productor?.payment_methods.find((el) => el.name === "cheque")
?.details || ""
}
price={price} price={price}
inputForm={inputForm} inputForm={inputForm}
/> />

View File

@@ -9,6 +9,7 @@ export const PaymentMethods = [
export type PaymentMethod = { export type PaymentMethod = {
name: string; name: string;
details: string; details: string;
max: number | null;
}; };
export type Productor = { export type Productor = {