diff --git a/back/app/contract/models.py b/back/app/contract/models.py
index 21f8f2ad..cfc78bc8 100644
--- a/back/app/contract/models.py
+++ b/back/app/contract/models.py
@@ -1,16 +1,9 @@
-from datetime import datetime
-from typing import List
+from typing import List, Literal
from enum import Enum
from pydantic import BaseModel, Field
-from beanie import Document
-from ..entity.models import Entity
-
-
-class ContractType(str, Enum):
- employment = 'employment'
- location = 'location'
+from ..core.models import CrudDocument, RichtextSingleline, RichtextMultiline, DictionaryEntry
class ContractStatus(str, Enum):
@@ -20,21 +13,54 @@ class ContractStatus(str, Enum):
executed = 'executed'
+class ContractDraftStatus(str, Enum):
+ draft = 'draft'
+ created = 'created'
+
+
class Party(BaseModel):
- entity: Entity
+ entity_id: str = Field(
+ foreignKey={
+ "reference": {
+ "resource": "entity",
+ "schema": "Entity",
+ }
+ }
+ )
part: str
-class Clause(BaseModel):
+class ProvisionGenuine(BaseModel):
+ type: Literal['genuine'] = 'genuine'
+ title: str = RichtextSingleline(props={"parametrized": True})
+ body: str = RichtextMultiline(props={"parametrized": True})
+
+
+class ContractProvisionTemplateReference(BaseModel):
+ type: Literal['template'] = 'template'
+ provision_template_id: str = Field(
+ foreignKey={
+ "reference": {
+ "resource": "template/provision",
+ "schema": "ProvisionTemplate",
+ "displayedFields": ['title', 'body']
+ },
+ },
+ props={"parametrized": True}
+ )
+
+
+class DraftProvision(BaseModel):
+ provision: ContractProvisionTemplateReference | ProvisionGenuine = Field(..., discriminator='type')
+
+
+class ContractDraft(CrudDocument):
name: str
- body: str
-
-
-class Contract(Document):
- _id: str
- type: ContractType
+ title: str
parties: List[Party]
- clauses: List[Clause]
- status: ContractStatus = Field(default=ContractStatus.new)
- created_at: datetime = Field(default=datetime.utcnow(), nullable=False)
- updated_at: datetime = Field(default_factory=datetime.utcnow, nullable=False)
+ provisions: List[DraftProvision]
+ variables: List[DictionaryEntry] = Field(
+ default=[],
+ format="dictionary",
+ )
+ status: ContractDraftStatus = Field(default=ContractDraftStatus.draft)
diff --git a/back/app/contract/routes.py b/back/app/contract/routes.py
index 707a7909..54acb83a 100644
--- a/back/app/contract/routes.py
+++ b/back/app/contract/routes.py
@@ -1,5 +1,5 @@
from ..core.routes import get_crud_router
-from .models import Contract
-from .schemas import ContractCreate, ContractRead, ContractUpdate
+from .models import ContractDraft
+from .schemas import ContractDraftCreate, ContractDraftRead, ContractDraftUpdate
-router = get_crud_router(Contract, ContractCreate, ContractRead, ContractUpdate)
+router = get_crud_router(ContractDraft, ContractDraftCreate, ContractDraftRead, ContractDraftUpdate)
diff --git a/back/app/contract/schemas.py b/back/app/contract/schemas.py
index 1f1699e5..733764ff 100644
--- a/back/app/contract/schemas.py
+++ b/back/app/contract/schemas.py
@@ -1,36 +1,36 @@
-import uuid
-from datetime import datetime
+
from typing import List
-from pydantic import BaseModel, validator
+from pydantic import Field
-from beanie import PydanticObjectId
+from .models import ContractDraft, DraftProvision, Party
-from .models import Contract, ContractType, Clause
from ..entity.models import Entity
from ..core.schemas import Writer
+from ..core.models import DictionaryEntry
-class ContractRead(Contract):
+class ContractDraftRead(ContractDraft):
pass
-class PartyCreate(BaseModel):
- entity: PydanticObjectId
- part: str
-
-
-class ContractCreate(Writer):
- type: ContractType
- parties: List[PartyCreate]
- clauses: List[Clause]
+class ContractDraftCreate(Writer):
+ name: str
+ title: str
+ parties: List[Party]
+ provisions: List[DraftProvision]
+ variables: List[DictionaryEntry] = Field(
+ default=[],
+ format="dictionary",
+ )
async def validate_foreign_key(self):
+ return
for p in self.parties:
p.entity = await Entity.get(p.entity)
if p.entity is None:
raise ValueError
-class ContractUpdate(BaseModel):
- status: str
+class ContractDraftUpdate(ContractDraftCreate):
+ pass
diff --git a/back/app/db.py b/back/app/db.py
index bdc7ee2d..8b987433 100644
--- a/back/app/db.py
+++ b/back/app/db.py
@@ -6,7 +6,7 @@ from .user import User, AccessToken
from .entity.models import Entity
from .template.models import ContractTemplate, ProvisionTemplate
from .order.models import Order
-from .contract.models import Contract
+from .contract.models import ContractDraft
DATABASE_URL = "mongodb://root:example@mongo:27017/"
@@ -17,5 +17,5 @@ async def init_db():
)
await init_beanie(database=client.db_name,
- document_models=[User, AccessToken, Entity, ContractTemplate, ProvisionTemplate, Order, Contract, ],
+ document_models=[User, AccessToken, Entity, ContractTemplate, ProvisionTemplate, ContractDraft, ],
allow_index_dropping=True)
diff --git a/back/app/main.py b/back/app/main.py
index 2eb25bd4..1e51f1e7 100644
--- a/back/app/main.py
+++ b/back/app/main.py
@@ -25,7 +25,7 @@ app.include_router(user_router, prefix="/users", tags=["users"], )
app.include_router(entity_router, prefix="/entity", tags=["entity"], )
app.include_router(order_router, prefix="/order", tags=["order"], )
app.include_router(template_router, prefix="/template", tags=["template"], )
-app.include_router(contract_router, prefix="/contract", tags=["contract"], )
+app.include_router(contract_router, prefix="/contract-draft", tags=["contract-draft"], )
if __name__ == '__main__':
import uvicorn
diff --git a/front/app/src/app/app-routing.module.ts b/front/app/src/app/app-routing.module.ts
index 82fa9221..4873a96a 100644
--- a/front/app/src/app/app-routing.module.ts
+++ b/front/app/src/app/app-routing.module.ts
@@ -1,5 +1,6 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
+import {ContractsModule} from "./views/contracts/contracts.module";
const routes: Routes = [
{
@@ -29,6 +30,11 @@ const routes: Routes = [
loadChildren: () =>
import('./views/templates/templates.module').then((m) => m.TemplatesModule)
},
+ {
+ path: 'contract-drafts',
+ loadChildren: () =>
+ import('./views/contracts/contracts.module').then((m) => m.ContractsModule)
+ },
]
}
];
diff --git a/front/app/src/app/layout/sidenav/sidenav.component.ts b/front/app/src/app/layout/sidenav/sidenav.component.ts
index f7288471..f066ac82 100644
--- a/front/app/src/app/layout/sidenav/sidenav.component.ts
+++ b/front/app/src/app/layout/sidenav/sidenav.component.ts
@@ -31,6 +31,11 @@ export class SidenavComponent {
link: "/templates/contracts",
icon: IconNamesEnum.FileCodeFill
},
+ {
+ title: "Contracts Drafts",
+ link: "/contract-drafts",
+ icon: IconNamesEnum.PencilSquare
+ },
]
}
diff --git a/front/app/src/app/views/contracts/contracts-routing.module.ts b/front/app/src/app/views/contracts/contracts-routing.module.ts
new file mode 100644
index 00000000..4214b29e
--- /dev/null
+++ b/front/app/src/app/views/contracts/contracts-routing.module.ts
@@ -0,0 +1,44 @@
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+
+import { DraftCardComponent, DraftListComponent, DraftNewComponent } from "./drafts.component";
+
+
+const routes: Routes = [
+ {
+ path: '',
+ data: {
+ title: 'Entities',
+ },
+ children: [
+ { path: '', redirectTo: 'list', pathMatch: 'full' },
+ {
+ path: 'list',
+ component: DraftListComponent,
+ data: {
+ title: 'List',
+ },
+ },
+ {
+ path: 'new',
+ component: DraftNewComponent,
+ data: {
+ title: 'New',
+ },
+ },
+ {
+ path: ':id',
+ component: DraftCardComponent,
+ data: {
+ title: 'Card',
+ },
+ },
+ ],
+ },
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule]
+})
+export class ContractsRoutingModule {}
diff --git a/front/app/src/app/views/contracts/contracts.module.ts b/front/app/src/app/views/contracts/contracts.module.ts
new file mode 100644
index 00000000..d060407c
--- /dev/null
+++ b/front/app/src/app/views/contracts/contracts.module.ts
@@ -0,0 +1,23 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+
+import { ContractsRoutingModule } from './contracts-routing.module';
+import { CrudModule } from '@common/crud/crud.module'
+import { DraftCardComponent, DraftListComponent, DraftNewComponent } from "./drafts.component";
+
+
+
+@NgModule({
+ imports: [
+ CommonModule,
+ CrudModule,
+ ContractsRoutingModule
+ ],
+ declarations: [
+ DraftListComponent,
+ DraftNewComponent,
+ DraftCardComponent,
+ ]
+})
+export class ContractsModule {
+}
diff --git a/front/app/src/app/views/contracts/drafts.component.ts b/front/app/src/app/views/contracts/drafts.component.ts
new file mode 100644
index 00000000..1ffb742a
--- /dev/null
+++ b/front/app/src/app/views/contracts/drafts.component.ts
@@ -0,0 +1,39 @@
+import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute, ParamMap } from '@angular/router';
+
+
+export class BaseEntitiesComponent {
+ protected resource: string = "contract-draft";
+ protected schema: string = "ContractDraft";
+}
+
+@Component({
+ template: ''
+})
+export class DraftListComponent extends BaseEntitiesComponent {
+ columns = ['label', 'address', 'entity_data.type']
+}
+
+@Component({
+ template: ''
+})
+export class DraftNewComponent extends BaseEntitiesComponent {
+}
+
+@Component({
+ template: ''
+})
+export class DraftCardComponent extends BaseEntitiesComponent implements OnInit {
+
+ resource_id: string | null = null;
+
+ constructor(private route: ActivatedRoute,) {
+ super();
+ }
+
+ ngOnInit(): void {
+ this.route.paramMap.subscribe((params: ParamMap) => {
+ this.resource_id = params.get('id')
+ })
+ }
+}
\ No newline at end of file