add visible field to form
This commit is contained in:
@@ -21,6 +21,8 @@
|
||||
- check products
|
||||
- Publish
|
||||
|
||||
## Only show productors / products / forms for referent of type
|
||||
|
||||
## Footer
|
||||
|
||||
### Legal
|
||||
|
||||
33
backend/alembic/versions/e777ed5729ce_message.py
Normal file
33
backend/alembic/versions/e777ed5729ce_message.py
Normal file
@@ -0,0 +1,33 @@
|
||||
"""message
|
||||
|
||||
Revision ID: e777ed5729ce
|
||||
Revises: 7854064278ce
|
||||
Create Date: 2026-02-23 13:53:09.999893
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
import sqlmodel.sql.sqltypes
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = 'e777ed5729ce'
|
||||
down_revision: Union[str, Sequence[str], None] = '7854064278ce'
|
||||
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('form', sa.Column('visible', sa.Boolean(), nullable=False, default=False, server_default="False"))
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_column('form', 'visible')
|
||||
# ### end Alembic commands ###
|
||||
@@ -13,10 +13,20 @@ async def get_forms(
|
||||
seasons: list[str] = Query([]),
|
||||
productors: list[str] = Query([]),
|
||||
current_season: bool = False,
|
||||
session: Session = Depends(get_session)
|
||||
session: Session = Depends(get_session),
|
||||
):
|
||||
return service.get_all(session, seasons, productors, current_season)
|
||||
|
||||
@router.get('/referents', response_model=list[models.FormPublic])
|
||||
async def get_forms_filtered(
|
||||
seasons: list[str] = Query([]),
|
||||
productors: list[str] = Query([]),
|
||||
current_season: bool = False,
|
||||
session: Session = Depends(get_session),
|
||||
user: models.User = Depends(get_current_user)
|
||||
):
|
||||
return service.get_all(session, seasons, productors, current_season, user)
|
||||
|
||||
@router.get('/{id}', response_model=models.FormPublic)
|
||||
async def get_form(id: int, session: Session = Depends(get_session)):
|
||||
result = service.get_one(session, id)
|
||||
|
||||
@@ -7,12 +7,20 @@ def get_all(
|
||||
seasons: list[str],
|
||||
productors: list[str],
|
||||
current_season: bool,
|
||||
user: models.User = None
|
||||
) -> list[models.FormPublic]:
|
||||
statement = select(models.Form)
|
||||
if user:
|
||||
statement = statement\
|
||||
.join(models.Productor, models.Form.productor_id == models.Productor.id)\
|
||||
.where(models.Productor.type.in_([r.name for r in user.roles]))\
|
||||
.distinct()
|
||||
if len(seasons) > 0:
|
||||
statement = statement.where(models.Form.season.in_(seasons))
|
||||
if len(productors) > 0:
|
||||
statement = statement.join(models.Productor).where(models.Productor.name.in_(productors))
|
||||
if not user:
|
||||
statement = statement.where(models.Form.visible == True)
|
||||
if current_season:
|
||||
subquery = (
|
||||
select(
|
||||
@@ -29,6 +37,8 @@ def get_all(
|
||||
(models.Productor.type == subquery.c.type) &
|
||||
(models.Form.start == subquery.c.max_start)
|
||||
)
|
||||
if not user:
|
||||
statement = statement.where(models.Form.visible == True)
|
||||
return session.exec(statement.order_by(models.Form.name)).all()
|
||||
return session.exec(statement.order_by(models.Form.name)).all()
|
||||
|
||||
|
||||
@@ -136,6 +136,7 @@ class FormBase(SQLModel):
|
||||
start: datetime.date
|
||||
end: datetime.date
|
||||
minimum_shipment_value: float | None
|
||||
visible: bool
|
||||
|
||||
class FormPublic(FormBase):
|
||||
id: int
|
||||
@@ -167,6 +168,7 @@ class FormUpdate(SQLModel):
|
||||
start: datetime.date | None
|
||||
end: datetime.date | None
|
||||
minimum_shipment_value: float | None
|
||||
visible: bool | None
|
||||
|
||||
class FormCreate(FormBase):
|
||||
pass
|
||||
|
||||
@@ -15,7 +15,7 @@ def get_productors(
|
||||
user: models.User = Depends(get_current_user),
|
||||
session: Session = Depends(get_session)
|
||||
):
|
||||
return service.get_all(session, names, types)
|
||||
return service.get_all(session, user, names, types)
|
||||
|
||||
@router.get('/{id}', response_model=models.ProductorPublic)
|
||||
def get_productor(
|
||||
|
||||
@@ -3,10 +3,13 @@ import src.models as models
|
||||
|
||||
def get_all(
|
||||
session: Session,
|
||||
user: models.User,
|
||||
names: list[str],
|
||||
types: list[str]
|
||||
) -> list[models.ProductorPublic]:
|
||||
statement = select(models.Productor)
|
||||
statement = select(models.Productor)\
|
||||
.where(models.Productor.type.in_([r.name for r in user.roles]))\
|
||||
.distinct()
|
||||
if len(names) > 0:
|
||||
statement = statement.where(models.Productor.name.in_(names))
|
||||
if len(types) > 0:
|
||||
|
||||
@@ -17,6 +17,7 @@ def get_products(
|
||||
):
|
||||
return service.get_all(
|
||||
session,
|
||||
user,
|
||||
names,
|
||||
productors,
|
||||
types,
|
||||
|
||||
@@ -3,11 +3,15 @@ import src.models as models
|
||||
|
||||
def get_all(
|
||||
session: Session,
|
||||
user: models.User,
|
||||
names: list[str],
|
||||
productors: list[str],
|
||||
types: list[str],
|
||||
) -> list[models.ProductPublic]:
|
||||
statement = select(models.Product)
|
||||
statement = select(models.Product)\
|
||||
.join(models.Productor, models.Product.productor_id == models.Productor.id)\
|
||||
.where(models.Productor.type.in_([r.name for r in user.roles]))\
|
||||
.distinct()
|
||||
if len(names) > 0:
|
||||
statement = statement.where(models.Product.name.in_(names))
|
||||
if len(productors) > 0:
|
||||
|
||||
@@ -3,11 +3,16 @@ import src.models as models
|
||||
|
||||
def get_all(
|
||||
session: Session,
|
||||
user: models.User,
|
||||
names: list[str],
|
||||
dates: list[str],
|
||||
forms: list[int]
|
||||
) -> list[models.ShipmentPublic]:
|
||||
statement = select(models.Shipment)
|
||||
statement = select(models.Shipment)\
|
||||
.join(models.Form, models.Shipment.form_id == models.Form.id)\
|
||||
.join(models.Productor, models.Form.productor_id == models.Productor.id)\
|
||||
.where(models.Productor.type.in_([r.name for r in user.roles]))\
|
||||
.distinct()
|
||||
if len(names) > 0:
|
||||
statement = statement.where(models.Shipment.name.in_(names))
|
||||
if len(dates) > 0:
|
||||
|
||||
@@ -11,12 +11,14 @@ router = APIRouter(prefix='/shipments')
|
||||
@router.get('', response_model=list[models.ShipmentPublic], )
|
||||
def get_shipments(
|
||||
session: Session = Depends(get_session),
|
||||
user: models.User = Depends(get_current_user),
|
||||
names: list[str] = Query([]),
|
||||
dates: list[str] = Query([]),
|
||||
forms: list[str] = Query([]),
|
||||
):
|
||||
return service.get_all(
|
||||
session,
|
||||
user,
|
||||
names,
|
||||
dates,
|
||||
forms,
|
||||
|
||||
@@ -82,7 +82,10 @@
|
||||
"you can download all contracts for your form using the export all": "you can download all contracts for your form using the export all",
|
||||
"in the same corner you can download a recap by clicking on the button": "in the same corner you can download a recap by clicking on the",
|
||||
"once all contracts downloaded, you can delete the form (to avoid new submissions) and hide it from the home page": "once all contracts downloaded, you can delete the form (to avoid new submissions) and hide it from the home page",
|
||||
"by checking this option the form will be accessible publicly on the home page, only check it if everything is fine with your form": "by checking this option the form will be accessible publicly on the home page, only check it if everything is fine with your form",
|
||||
"contracts": "contracts",
|
||||
"hidden": "hidden",
|
||||
"visible": "visible",
|
||||
"minimum price for this shipment should be at least": "minimum price for this shipment should be at least",
|
||||
"there is": "there is",
|
||||
"for this contract": "for this contract.",
|
||||
|
||||
@@ -73,7 +73,10 @@
|
||||
"shipment products is necessary only for occasional products (if all products are recurrent leave empty)": "il est nécessaire de configurer les produits pour la livraison uniquement si il y a des produits occasionnels (laisser vide si tous les produits sont récurents).",
|
||||
"recurrent product is for all shipments, occasional product is for a specific shipment (see shipment form)": "les produits récurrents sont pour toutes les livraisons, les produits occasionnels sont pour une livraison particulière (voir formulaire de création de livraison).",
|
||||
"some contracts require a minimum value per shipment, ignore this field if it's not the case": "certains contrats nécessitent une valeur minimum par livraison. Ce champ peut être ignoré s’il ne s’applique pas à votre contrat.",
|
||||
"by checking this option the form will be accessible publicly on the home page, only check it if everything is fine with your form": "en cochant cette option le formulaire sera accessible publiquement sur la page d'accueil, cochez cette option uniquement si tout est prêt avec votre formulaire.",
|
||||
"contracts": "contrats",
|
||||
"hidden": "caché",
|
||||
"visible": "visible",
|
||||
"minimum price for this shipment should be at least": "le prix minimum d'une livraison doit être au moins de",
|
||||
"there is": "il y a",
|
||||
"for this contract": "pour ce contrat.",
|
||||
@@ -166,7 +169,7 @@
|
||||
"with cheque and transfer": "avec chèques et virements configuré pour le producteur",
|
||||
"mililiter": "mililitres (ml)",
|
||||
"this field is optionnal a product can have a quantity if configured inside the product it will be shown inside the form": "ce champ est optionnel dans la configuration d'un produit, il représente la quantité d'un produit (poids d'une tranche de foie, poids d'un panier, taille d'un bocal...). Si ce champs est renseigné il sera affiché dans le formulaire à destination des amapiens.",
|
||||
"this field is also optionnal if a product have a quantity you can select the correct unit (metric system). It will be shown next to product quantity inside the form": "ce champs est optionnel dans la configuation d'un produit, il représente l'unité de mesure associé à la quantité d'un produit (g, kg, ml, L). Si ce champs est renseigné il sera affiché dans le formulaire à destination des amapiens à coté de la quantité du produit.",
|
||||
"this field is also optionnal if a product have a quantity you can select the correct unit (metric system). It will be shown next to product quantity inside the form": "ce champs est optionnel dans la configuation d'un produit, il représente l'unité de mesure associée à la quantité d'un produit (g, kg, ml, L). Si ce champs est renseigné il sera affiché dans le formulaire à destination des amapiens à coté de la quantité du produit.",
|
||||
"with 150 set as quantity and g as quantity unit in product": "avec \"150\" en quantité de produit et \"grammes\" selectionné dans l'unité de quantité du produit",
|
||||
"all shipments should be recreated for each form creation": "les livraisons étant liées à un formulaire elles doivent être recréés pour chaque nouveau formulaire.",
|
||||
"a productor can be edited if its informations change, it should not be recreated for each contracts": "un(e) producteur·trice peut être édité si ses informations changent, il/elle ne doit pas être recréé pour chaque nouveau contrat.",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
Group,
|
||||
Modal,
|
||||
NumberInput,
|
||||
@@ -33,6 +34,7 @@ export default function FormModal({ opened, onClose, currentForm, handleSubmit }
|
||||
productor_id: currentForm?.productor?.id.toString() ?? "",
|
||||
referer_id: currentForm?.referer?.id.toString() ?? "",
|
||||
minimum_shipment_value: currentForm?.minimum_shipment_value ?? null,
|
||||
visible: currentForm?.visible ?? false
|
||||
},
|
||||
validate: {
|
||||
name: (value) =>
|
||||
@@ -136,6 +138,11 @@ export default function FormModal({ opened, onClose, currentForm, handleSubmit }
|
||||
radius="sm"
|
||||
{...form.getInputProps("minimum_shipment_value")}
|
||||
/>
|
||||
<Checkbox mt="lg"
|
||||
label={t("visible", {capfirst: true})}
|
||||
description={t("by checking this option the form will be accessible publicly on the home page, only check it if everything is fine with your form", {capfirst: true})}
|
||||
{...form.getInputProps("visible", {type: "checkbox"})}
|
||||
/>
|
||||
<Group mt="sm" justify="space-between">
|
||||
<Button
|
||||
variant="filled"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ActionIcon, Table, Tooltip } from "@mantine/core";
|
||||
import { ActionIcon, Badge, Table, Tooltip } from "@mantine/core";
|
||||
import { useNavigate, useSearchParams } from "react-router";
|
||||
import { useDeleteForm } from "@/services/api";
|
||||
import { IconEdit, IconX } from "@tabler/icons-react";
|
||||
@@ -16,6 +16,12 @@ export default function FormRow({ form }: FormRowProps) {
|
||||
|
||||
return (
|
||||
<Table.Tr key={form.id}>
|
||||
<Table.Td>
|
||||
{form.visible ?
|
||||
<Badge color="green">{t("visible", {capfirst: true})}</Badge> :
|
||||
<Badge color="red">{t("hidden", {capfirst: true})}</Badge>
|
||||
}
|
||||
</Table.Td>
|
||||
<Table.Td>{form.name}</Table.Td>
|
||||
<Table.Td>{form.season}</Table.Td>
|
||||
<Table.Td>{form.start}</Table.Td>
|
||||
|
||||
@@ -13,7 +13,7 @@ import { IconCancel, IconEdit, IconPlus } from "@tabler/icons-react";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { useMemo } from "react";
|
||||
import { type Shipment, type ShipmentInputs } from "@/services/resources/shipments";
|
||||
import { useGetForms, useGetProductors, useGetProducts } from "@/services/api";
|
||||
import { useGetReferentForms, useGetProductors, useGetProducts } from "@/services/api";
|
||||
|
||||
export type ShipmentModalProps = ModalBaseProps & {
|
||||
currentShipment?: Shipment;
|
||||
@@ -43,7 +43,7 @@ export default function ShipmentModal({
|
||||
},
|
||||
});
|
||||
|
||||
const { data: allForms } = useGetForms();
|
||||
const { data: allForms } = useGetReferentForms();
|
||||
const { data: allProducts } = useGetProducts(new URLSearchParams("types=1"));
|
||||
const { data: allProductors } = useGetProductors();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Stack, Loader, Title, Group, ActionIcon, Tooltip, Table, ScrollArea } from "@mantine/core";
|
||||
import { useCreateForm, useEditForm, useGetForm, useGetForms } from "@/services/api";
|
||||
import { useCreateForm, useEditForm, useGetForm, useGetReferentForms } from "@/services/api";
|
||||
import { t } from "@/config/i18n";
|
||||
import { useLocation, useNavigate, useSearchParams } from "react-router";
|
||||
import { IconPlus } from "@tabler/icons-react";
|
||||
@@ -28,12 +28,12 @@ export function Forms() {
|
||||
navigate(`/dashboard/forms${searchParams ? `?${searchParams.toString()}` : ""}`);
|
||||
}, [navigate, searchParams]);
|
||||
|
||||
const { isPending, data } = useGetForms(searchParams);
|
||||
const { isPending, data } = useGetReferentForms(searchParams);
|
||||
const { data: currentForm } = useGetForm(Number(editId), {
|
||||
enabled: !!editId,
|
||||
});
|
||||
|
||||
const { data: allForms } = useGetForms();
|
||||
const { data: allForms } = useGetReferentForms();
|
||||
|
||||
const seasons = useMemo(() => {
|
||||
return allForms
|
||||
@@ -148,6 +148,7 @@ export function Forms() {
|
||||
<Table striped>
|
||||
<Table.Thead>
|
||||
<Table.Tr>
|
||||
<Table.Th>{t("visible", { capfirst: true })}</Table.Th>
|
||||
<Table.Th>{t("name", { capfirst: true })}</Table.Th>
|
||||
<Table.Th>{t("type", { capfirst: true })}</Table.Th>
|
||||
<Table.Th>{t("start", { capfirst: true })}</Table.Th>
|
||||
|
||||
@@ -330,6 +330,15 @@ export function useGetForms(filters?: URLSearchParams): UseQueryResult<Form[], E
|
||||
});
|
||||
}
|
||||
|
||||
export function useGetReferentForms(filters?: URLSearchParams): UseQueryResult<Form[], Error> {
|
||||
const queryString = filters?.toString();
|
||||
return useQuery<Form[]>({
|
||||
queryKey: ["forms", queryString],
|
||||
queryFn: () =>
|
||||
fetchWithAuth(`${Config.backend_uri}/forms/referents${filters ? `?${queryString}` : ""}`).then((res) => res.json()),
|
||||
});
|
||||
}
|
||||
|
||||
export function useCreateForm() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
@@ -711,7 +720,6 @@ export function useGetContractFile() {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export function useGetContractFileTemplate() {
|
||||
return useMutation({
|
||||
mutationFn: async (form_id: number) => {
|
||||
|
||||
@@ -12,6 +12,7 @@ export type Form = {
|
||||
referer: User;
|
||||
shipments: Shipment[];
|
||||
minimum_shipment_value: number | null;
|
||||
visible: boolean;
|
||||
};
|
||||
|
||||
export type FormCreate = {
|
||||
@@ -22,6 +23,7 @@ export type FormCreate = {
|
||||
productor_id: number;
|
||||
referer_id: number;
|
||||
minimum_shipment_value: number | null;
|
||||
visible: boolean;
|
||||
};
|
||||
|
||||
export type FormEdit = {
|
||||
@@ -32,6 +34,7 @@ export type FormEdit = {
|
||||
productor_id?: number | null;
|
||||
referer_id?: number | null;
|
||||
minimum_shipment_value: number | null;
|
||||
visible: boolean;
|
||||
};
|
||||
|
||||
export type FormEditPayload = {
|
||||
@@ -47,4 +50,5 @@ export type FormInputs = {
|
||||
productor_id: string;
|
||||
referer_id: string;
|
||||
minimum_shipment_value: number | string | null;
|
||||
visible: boolean;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user