Compare commits
1 Commits
master
...
fix/firm_i
| Author | SHA1 | Date | |
|---|---|---|---|
| 2ff15cdef4 |
@@ -3,7 +3,6 @@ import os
|
|||||||
import base64
|
import base64
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
from beanie import PydanticObjectId
|
|
||||||
from fastapi import APIRouter, HTTPException, Request, Depends
|
from fastapi import APIRouter, HTTPException, Request, Depends
|
||||||
from fastapi.responses import HTMLResponse, FileResponse
|
from fastapi.responses import HTMLResponse, FileResponse
|
||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
@@ -19,22 +18,24 @@ from firm.template.models import ProvisionTemplate
|
|||||||
from firm.contract.models import ContractDraft, Contract, ContractStatus, replace_variables_in_value
|
from firm.contract.models import ContractDraft, Contract, ContractStatus, replace_variables_in_value
|
||||||
|
|
||||||
|
|
||||||
async def build_model(db, model):
|
async def build_model(model):
|
||||||
parties = []
|
parties = []
|
||||||
for p in model.parties:
|
for p in model.parties:
|
||||||
party = {
|
party = {
|
||||||
"entity": await Entity.get(db, p.entity_id),
|
"entity": await Entity.get(p.entity_id),
|
||||||
"part": p.part
|
"part": p.part
|
||||||
}
|
}
|
||||||
if p.representative_id:
|
if p.representative_id:
|
||||||
party['representative'] = await Entity.get(db, p.representative_id)
|
party['representative'] = await Entity.get(p.representative_id)
|
||||||
|
|
||||||
parties.append(party)
|
parties.append(party)
|
||||||
|
|
||||||
|
model.parties = parties
|
||||||
|
|
||||||
provisions = []
|
provisions = []
|
||||||
for p in model.provisions:
|
for p in model.provisions:
|
||||||
if p.provision.type == "template":
|
if p.provision.type == "template":
|
||||||
provision = await ProvisionTemplate.get(db, p.provision.provision_template_id)
|
provision = await ProvisionTemplate.get(p.provision.provision_template_id)
|
||||||
else:
|
else:
|
||||||
provision = p.provision
|
provision = p.provision
|
||||||
|
|
||||||
@@ -42,16 +43,16 @@ async def build_model(db, model):
|
|||||||
provision.body = replace_variables_in_value(model.variables, provision.body)
|
provision.body = replace_variables_in_value(model.variables, provision.body)
|
||||||
provisions.append(provision)
|
provisions.append(provision)
|
||||||
|
|
||||||
model_dict = model.dict()
|
model.provisions = provisions
|
||||||
model_dict['parties'] = parties
|
|
||||||
model_dict['provisions'] = provisions
|
model = model.dict()
|
||||||
model_dict['location'] = "Los Santos, SA"
|
model['location'] = "Los Santos, SA"
|
||||||
model_dict['date'] = datetime.date(1970, 1, 1)
|
model['date'] = datetime.date(1970, 1, 1)
|
||||||
model_dict['lawyer'] = {'entity_data': {
|
model['lawyer'] = {'entity_data': {
|
||||||
"firstname": "prénom avocat",
|
"firstname": "prénom avocat",
|
||||||
"lastname": "nom avocat",
|
"lastname": "nom avocat",
|
||||||
}}
|
}}
|
||||||
return model_dict
|
return model
|
||||||
|
|
||||||
|
|
||||||
BASE_PATH = Path(__file__).resolve().parent
|
BASE_PATH = Path(__file__).resolve().parent
|
||||||
@@ -86,14 +87,8 @@ def retrieve_signature_png(filepath):
|
|||||||
|
|
||||||
preview_router = APIRouter()
|
preview_router = APIRouter()
|
||||||
@preview_router.get("/draft/{draft_id}", response_class=HTMLResponse, tags=["Contract Draft"])
|
@preview_router.get("/draft/{draft_id}", response_class=HTMLResponse, tags=["Contract Draft"])
|
||||||
async def preview_draft(draft_id: PydanticObjectId, reg=Depends(get_tenant_registry)) -> str:
|
async def preview_draft(draft_id: str, reg=Depends(get_tenant_registry)) -> str:
|
||||||
record = await ContractDraft.get(reg.db, draft_id)
|
draft = await build_model(await ContractDraft.get(reg.db, draft_id))
|
||||||
if not record:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=404,
|
|
||||||
detail=f"Contract Draft record not found!"
|
|
||||||
)
|
|
||||||
draft = await build_model(reg.db, record)
|
|
||||||
|
|
||||||
return await render_print('', draft)
|
return await render_print('', draft)
|
||||||
|
|
||||||
@@ -109,7 +104,7 @@ async def preview_contract_by_signature(signature_id: UUID, reg=Depends(get_tena
|
|||||||
|
|
||||||
|
|
||||||
@preview_router.get("/{contract_id}", response_class=HTMLResponse, tags=["Contract"])
|
@preview_router.get("/{contract_id}", response_class=HTMLResponse, tags=["Contract"])
|
||||||
async def preview_contract(contract_id: PydanticObjectId, reg=Depends(get_tenant_registry)) -> str:
|
async def preview_contract(contract_id: str, reg=Depends(get_tenant_registry)) -> str:
|
||||||
contract = await Contract.get(reg.db, contract_id)
|
contract = await Contract.get(reg.db, contract_id)
|
||||||
for p in contract.parties:
|
for p in contract.parties:
|
||||||
if p.signature_affixed:
|
if p.signature_affixed:
|
||||||
@@ -120,7 +115,7 @@ async def preview_contract(contract_id: PydanticObjectId, reg=Depends(get_tenant
|
|||||||
|
|
||||||
print_router = APIRouter()
|
print_router = APIRouter()
|
||||||
@print_router.get("/pdf/{contract_id}", response_class=FileResponse, tags=["Contract"])
|
@print_router.get("/pdf/{contract_id}", response_class=FileResponse, tags=["Contract"])
|
||||||
async def create_pdf(contract_id: PydanticObjectId, reg=Depends(get_tenant_registry)) -> str:
|
async def create_pdf(contract_id: str, reg=Depends(get_tenant_registry)) -> str:
|
||||||
contract = await Contract.get(reg.db, contract_id)
|
contract = await Contract.get(reg.db, contract_id)
|
||||||
contract_path = "media/contracts/{}.pdf".format(contract_id)
|
contract_path = "media/contracts/{}.pdf".format(contract_id)
|
||||||
if not os.path.isfile(contract_path):
|
if not os.path.isfile(contract_path):
|
||||||
@@ -147,7 +142,7 @@ async def create_pdf(contract_id: PydanticObjectId, reg=Depends(get_tenant_regis
|
|||||||
|
|
||||||
|
|
||||||
@print_router.get("/opengraph/{signature_id}", response_class=HTMLResponse, tags=["Signature"])
|
@print_router.get("/opengraph/{signature_id}", response_class=HTMLResponse, tags=["Signature"])
|
||||||
async def get_signature_opengraph(signature_id: UUID, request: Request, reg=Depends(get_tenant_registry)) -> str:
|
async def get_signature_opengraph(signature_id: str, request: Request, reg=Depends(get_tenant_registry)) -> str:
|
||||||
contract = await Contract.find_by_signature_id(reg.db, signature_id)
|
contract = await Contract.find_by_signature_id(reg.db, signature_id)
|
||||||
signature = contract.get_signature(signature_id)
|
signature = contract.get_signature(signature_id)
|
||||||
template = templates.get_template("opengraph.html")
|
template = templates.get_template("opengraph.html")
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
<div class="footer">
|
<div class="footer">
|
||||||
<hr/>
|
<hr/>
|
||||||
<p>À {{ contract.location }} le {{ contract.date.strftime('%d/%m/%Y') }}</p>
|
<p>À {{ contract.location }} le {{ contract.date.strftime('%d/%m/%Y') }}</p>
|
||||||
<p class="mention">(Signatures précédées de la mention « Lu et approuvé »)</p>
|
<p class="mention">(Signatures précédée de la mention « Lu et approuvé »)</p>
|
||||||
<table class="signatures">
|
<table class="signatures">
|
||||||
<tr>
|
<tr>
|
||||||
{% for party in contract.parties %}
|
{% for party in contract.parties %}
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { getDefaultRegistry } from "@rjsf/core";
|
import { getDefaultRegistry } from "@rjsf/core";
|
||||||
import { FormContextType, RJSFSchema, WidgetProps } from "@rjsf/utils";
|
import { FormContextType, RJSFSchema, WidgetProps } from "@rjsf/utils";
|
||||||
import { Button, InputAdornment } from "@mui/material";
|
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import TextField from "@mui/material/TextField";
|
|
||||||
import CopyAllIcon from '@mui/icons-material/CopyAll';
|
|
||||||
|
|
||||||
import ForeignKeyWidget from "./foreign-key";
|
import ForeignKeyWidget from "./foreign-key";
|
||||||
import RichtextWidget from "./richtext";
|
import RichtextWidget from "./richtext";
|
||||||
@@ -21,37 +18,8 @@ export default function CrudTextWidget<T = any, S extends CrudTextRJSFSchema = C
|
|||||||
return <Typography >{schema.const as string}</Typography>;
|
return <Typography >{schema.const as string}</Typography>;
|
||||||
} else if (schema.props?.hasOwnProperty("richtext")) {
|
} else if (schema.props?.hasOwnProperty("richtext")) {
|
||||||
return <RichtextWidget {...props} />;
|
return <RichtextWidget {...props} />;
|
||||||
} else if (schema.props?.hasOwnProperty("display") && schema.props.display == "signature-link") {
|
|
||||||
return <SignatureLink {...props} />
|
|
||||||
} else {
|
} else {
|
||||||
const { widgets: { TextWidget } } = getDefaultRegistry<T,S,F>();
|
const { widgets: { TextWidget } } = getDefaultRegistry<T,S,F>();
|
||||||
return <TextWidget {...props} />;
|
return <TextWidget {...props} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const SignatureLink = <T = any, S extends CrudTextRJSFSchema = CrudTextRJSFSchema, F extends FormContextType = any>(props: WidgetProps<T, S, F> )=> {
|
|
||||||
const { label, value } = props;
|
|
||||||
const basePath = "/contracts/signature/";
|
|
||||||
const url = location.origin + basePath + value
|
|
||||||
|
|
||||||
return <TextField
|
|
||||||
label={ label }
|
|
||||||
variant="outlined"
|
|
||||||
disabled={true}
|
|
||||||
value={url}
|
|
||||||
slotProps={{
|
|
||||||
input: {
|
|
||||||
endAdornment: (
|
|
||||||
<InputAdornment position="end">
|
|
||||||
<Button
|
|
||||||
variant="outlined"
|
|
||||||
onClick={() => navigator.clipboard.writeText(url)}
|
|
||||||
color="primary"
|
|
||||||
>
|
|
||||||
<CopyAllIcon />
|
|
||||||
</Button>
|
|
||||||
</InputAdornment>),
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export function useResourceSchema(schemaName: string, type: ResourceSchemaType)
|
|||||||
let resourceSchema
|
let resourceSchema
|
||||||
if (type == "create") {
|
if (type == "create") {
|
||||||
resourceSchema = await jsonschemaProvider.getCreateResourceSchema(schemaName);
|
resourceSchema = await jsonschemaProvider.getCreateResourceSchema(schemaName);
|
||||||
} else if (type == "card") {
|
} else if (type == "update") {
|
||||||
resourceSchema = await jsonschemaProvider.getCardResourceSchema(schemaName);
|
resourceSchema = await jsonschemaProvider.getCardResourceSchema(schemaName);
|
||||||
} else {
|
} else {
|
||||||
resourceSchema = await jsonschemaProvider.getUpdateResourceSchema(schemaName);
|
resourceSchema = await jsonschemaProvider.getUpdateResourceSchema(schemaName);
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
import dayjs from "dayjs";
|
|
||||||
import React, { useContext, useState } from "react";
|
|
||||||
import { Navigate, Route, Routes, useParams } from "react-router";
|
import { Navigate, Route, Routes, useParams } from "react-router";
|
||||||
import { Box, Button, CircularProgress, Container, DialogContent, Modal, Paper } from "@mui/material";
|
import { CircularProgress } from "@mui/material";
|
||||||
import Stack from "@mui/material/Stack";
|
import React, { useContext, useState } from "react";
|
||||||
import PreviewIcon from '@mui/icons-material/Preview';
|
|
||||||
import { useOne, useTranslation } from "@refinedev/core";
|
import { useOne, useTranslation } from "@refinedev/core";
|
||||||
import { BaseForm } from "../../lib/crud/components/base-form";
|
import { BaseForm } from "../../lib/crud/components/base-form";
|
||||||
import { ForeignKeyReference, ForeignKeySchema } from "../../lib/crud/components/widgets/foreign-key";
|
import { ForeignKeyReference, ForeignKeySchema } from "../../lib/crud/components/widgets/foreign-key";
|
||||||
@@ -13,6 +10,7 @@ import List from "./base-page/List";
|
|||||||
import Edit from "./base-page/Edit";
|
import Edit from "./base-page/Edit";
|
||||||
import New from "./base-page/New";
|
import New from "./base-page/New";
|
||||||
import { Contract } from "./ContractRoutes";
|
import { Contract } from "./ContractRoutes";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
type Draft = {
|
type Draft = {
|
||||||
id: string,
|
id: string,
|
||||||
@@ -52,7 +50,7 @@ const EditDraft = () => {
|
|||||||
return <CircularProgress />
|
return <CircularProgress />
|
||||||
}
|
}
|
||||||
|
|
||||||
if (record_id == undefined || !data?.data) {
|
if (!data?.data) {
|
||||||
return <Navigate to="../" />
|
return <Navigate to="../" />
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,56 +63,12 @@ const EditDraft = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DraftPreview resourceBasePath={resourceBasePath} recordId={record_id}/>
|
|
||||||
<Edit<Draft> resource={"contracts/drafts"} schemaName={"ContractDraft"} uiSchema={uiSchema} />
|
<Edit<Draft> resource={"contracts/drafts"} schemaName={"ContractDraft"} uiSchema={uiSchema} />
|
||||||
<ContractCreate draft={draft}></ContractCreate>
|
<ContractCreate draft={draft}></ContractCreate>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const DraftPreview = (props: {resourceBasePath: string, recordId: string}) => {
|
|
||||||
const { resourceBasePath, recordId } = props
|
|
||||||
const [openPreviewModal, setOpenPreviewModal] = React.useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Button variant="outlined" onClick={() => setOpenPreviewModal(true)} color="primary" >
|
|
||||||
<PreviewIcon />Preview
|
|
||||||
</Button>
|
|
||||||
<Modal
|
|
||||||
open={openPreviewModal}
|
|
||||||
onClose={() => setOpenPreviewModal(false)}
|
|
||||||
aria-labelledby="modal-modal-title"
|
|
||||||
aria-describedby="modal-modal-description"
|
|
||||||
>
|
|
||||||
<DialogContent>
|
|
||||||
<Container>
|
|
||||||
<Paper>
|
|
||||||
<Stack
|
|
||||||
direction={"row"}
|
|
||||||
spacing={2}
|
|
||||||
sx={{
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box padding={"45px"}>
|
|
||||||
<iframe
|
|
||||||
src={`/api/v1/${resourceBasePath}/contracts/preview/draft/${recordId}`}
|
|
||||||
width="675px"
|
|
||||||
height="955px"
|
|
||||||
style={{ backgroundColor: "white", border: "1px solid black" }}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Stack>
|
|
||||||
</Paper>
|
|
||||||
</Container>
|
|
||||||
</DialogContent>
|
|
||||||
</Modal>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const ContractCreate = (props: { draft: any}) => {
|
const ContractCreate = (props: { draft: any}) => {
|
||||||
const { translate: t } = useTranslation();
|
const { translate: t } = useTranslation();
|
||||||
const { draft } = props;
|
const { draft } = props;
|
||||||
|
|||||||
Reference in New Issue
Block a user