Add entity address/contact tables and CRUD for entity resources
This commit is contained in:
89
README.md
89
README.md
@@ -187,6 +187,78 @@ Company-scoped brands. Auth via `resolveCompanyAccess`.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## `customergroup`
|
||||||
|
|
||||||
|
Company-scoped customer groups. Auth via `resolveCompanyAccess`.
|
||||||
|
|
||||||
|
| Method | Signature | Returns |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `list` | `(googleAuthId, companyId)` | `{ id, name }[]` |
|
||||||
|
| `create` | `(googleAuthId, companyId, { name })` | `{ id, name }` |
|
||||||
|
| `update` | `(googleAuthId, companyId, id, { name })` | `{ id, name }` |
|
||||||
|
| `delete` | `(googleAuthId, companyId, id)` | `void` |
|
||||||
|
|
||||||
|
Empty name → `Name required`. Deleting the POS group (or any group still referenced with `NO ACTION`) → `Customer group in use`. Cascades entities when the group is deleted. Errors: `Company not found`, `Not authorized`, `Name required`, `Customer group not found`, `Customer group in use`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `entity`
|
||||||
|
|
||||||
|
Entities belong to a `customergroup` of the company. Auth via `resolveCompanyAccess`.
|
||||||
|
|
||||||
|
| Method | Signature | Returns |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `list` | `(googleAuthId, companyId, { customergroupId? })` | `Entity[]` |
|
||||||
|
| `getById` | `(googleAuthId, companyId, id)` | `Entity` |
|
||||||
|
| `create` | `(googleAuthId, companyId, { customergroupId, name, firstName? })` | `Entity` |
|
||||||
|
| `update` | `(googleAuthId, companyId, id, { name?, firstName? })` | `Entity` |
|
||||||
|
| `delete` | `(googleAuthId, companyId, id)` | `void` |
|
||||||
|
|
||||||
|
```ts
|
||||||
|
type Entity = {
|
||||||
|
id: number,
|
||||||
|
customergroupId: number,
|
||||||
|
firstName: string | null,
|
||||||
|
name: string,
|
||||||
|
createdAt: Date,
|
||||||
|
updatedAt: Date,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`create` / `update` write `entityhistory` (`Erstellt`, or name/firstName change lines). `customergroupId` must belong to the company. Errors: `Company not found`, `Not authorized`, `Name required`, `Customer group not found`, `Entity not found`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `entityaddress`
|
||||||
|
|
||||||
|
Addresses for an entity. Auth via company + entity ownership.
|
||||||
|
|
||||||
|
| Method | Signature | Returns |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `list` | `(googleAuthId, companyId, entityId)` | `EntityAddress[]` |
|
||||||
|
| `create` | `(googleAuthId, companyId, entityId, { addressType, firstName?, name?, street?, streetNumber?, zip?, city?, county? })` | `EntityAddress` |
|
||||||
|
| `update` | `(googleAuthId, companyId, entityId, id, patch)` | `EntityAddress` |
|
||||||
|
| `delete` | `(googleAuthId, companyId, entityId, id)` | `void` |
|
||||||
|
|
||||||
|
`addressType` required. Errors: `Company not found`, `Not authorized`, `Entity not found`, `Address type required`, `Address not found`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `entitycontact`
|
||||||
|
|
||||||
|
Contacts for an entity (`contactType` e.g. `email`, `phone`). Auth via company + entity ownership.
|
||||||
|
|
||||||
|
| Method | Signature | Returns |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `list` | `(googleAuthId, companyId, entityId)` | `{ id, entityId, contactType, contact }[]` |
|
||||||
|
| `create` | `(googleAuthId, companyId, entityId, { contactType, contact })` | row |
|
||||||
|
| `update` | `(googleAuthId, companyId, entityId, id, { contactType?, contact? })` | row |
|
||||||
|
| `delete` | `(googleAuthId, companyId, entityId, id)` | `void` |
|
||||||
|
|
||||||
|
Errors: `Company not found`, `Not authorized`, `Entity not found`, `Contact required`, `Contact not found`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## `supplier`
|
## `supplier`
|
||||||
|
|
||||||
Suppliers are `entity` rows in the company `customergroup` named `Lieferanten` (created implicitly on first supplier). Auth via `resolveCompanyAccess`.
|
Suppliers are `entity` rows in the company `customergroup` named `Lieferanten` (created implicitly on first supplier). Auth via `resolveCompanyAccess`.
|
||||||
@@ -519,6 +591,23 @@ res.set('Content-Type', thumb.contentType).send(thumb.buffer);
|
|||||||
| `GET /api/brand` | `brand.list(googleAuthId, companyId)` |
|
| `GET /api/brand` | `brand.list(googleAuthId, companyId)` |
|
||||||
| `PUT /api/brand` | `brand.upsert(googleAuthId, companyId, { name, gsprpinfo? })` |
|
| `PUT /api/brand` | `brand.upsert(googleAuthId, companyId, { name, gsprpinfo? })` |
|
||||||
| `DELETE /api/brand/:id` | `brand.delete(googleAuthId, companyId, id)` |
|
| `DELETE /api/brand/:id` | `brand.delete(googleAuthId, companyId, id)` |
|
||||||
|
| `GET /api/customergroup` | `customergroup.list(googleAuthId, companyId)` |
|
||||||
|
| `POST /api/customergroup` | `customergroup.create(googleAuthId, companyId, { name })` |
|
||||||
|
| `PATCH /api/customergroup/:id` | `customergroup.update(googleAuthId, companyId, id, { name })` |
|
||||||
|
| `DELETE /api/customergroup/:id` | `customergroup.delete(googleAuthId, companyId, id)` |
|
||||||
|
| `GET /api/entity` | `entity.list(googleAuthId, companyId, { customergroupId? })` |
|
||||||
|
| `GET /api/entity/:id` | `entity.getById(googleAuthId, companyId, id)` |
|
||||||
|
| `POST /api/entity` | `entity.create(googleAuthId, companyId, { customergroupId, name, firstName? })` |
|
||||||
|
| `PATCH /api/entity/:id` | `entity.update(googleAuthId, companyId, id, { name?, firstName? })` |
|
||||||
|
| `DELETE /api/entity/:id` | `entity.delete(googleAuthId, companyId, id)` |
|
||||||
|
| `GET /api/entity/:entityId/address` | `entityaddress.list(googleAuthId, companyId, entityId)` |
|
||||||
|
| `POST /api/entity/:entityId/address` | `entityaddress.create(googleAuthId, companyId, entityId, { addressType, … })` |
|
||||||
|
| `PATCH /api/entity/:entityId/address/:id` | `entityaddress.update(googleAuthId, companyId, entityId, id, patch)` |
|
||||||
|
| `DELETE /api/entity/:entityId/address/:id` | `entityaddress.delete(googleAuthId, companyId, entityId, id)` |
|
||||||
|
| `GET /api/entity/:entityId/contact` | `entitycontact.list(googleAuthId, companyId, entityId)` |
|
||||||
|
| `POST /api/entity/:entityId/contact` | `entitycontact.create(googleAuthId, companyId, entityId, { contactType, contact })` |
|
||||||
|
| `PATCH /api/entity/:entityId/contact/:id` | `entitycontact.update(googleAuthId, companyId, entityId, id, patch)` |
|
||||||
|
| `DELETE /api/entity/:entityId/contact/:id` | `entitycontact.delete(googleAuthId, companyId, entityId, id)` |
|
||||||
| `GET /api/supplier` | `supplier.list(googleAuthId, companyId)` |
|
| `GET /api/supplier` | `supplier.list(googleAuthId, companyId)` |
|
||||||
| `POST /api/supplier` | `supplier.create(googleAuthId, companyId, { name })` |
|
| `POST /api/supplier` | `supplier.create(googleAuthId, companyId, { name })` |
|
||||||
| `PATCH /api/supplier/:id` | `supplier.update(googleAuthId, companyId, id, { name })` |
|
| `PATCH /api/supplier/:id` | `supplier.update(googleAuthId, companyId, id, { name })` |
|
||||||
|
|||||||
@@ -275,6 +275,8 @@ const CLUSTERS = [
|
|||||||
'customergroup',
|
'customergroup',
|
||||||
'entity',
|
'entity',
|
||||||
'entityhistory',
|
'entityhistory',
|
||||||
|
'entityaddress',
|
||||||
|
'entitycontact',
|
||||||
'numbers',
|
'numbers',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
108
schema-graph.dot
108
schema-graph.dot
@@ -10,14 +10,16 @@ digraph schema {
|
|||||||
style="rounded,filled"; fillcolor="#ffffff60"; color="#a0aec0";
|
style="rounded,filled"; fillcolor="#ffffff60"; color="#a0aec0";
|
||||||
fontcolor="#1a365d"; margin=14;
|
fontcolor="#1a365d"; margin=14;
|
||||||
customergroup [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="1" BORDER="1"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD PORT="in0" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in1" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in2" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD></TR><TR><TD COLSPAN="3" ALIGN="CENTER" CELLPADDING="3"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>customergroup</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="company_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>company_id</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="name" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">name</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
customergroup [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="1" BORDER="1"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD PORT="in0" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in1" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in2" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD></TR><TR><TD COLSPAN="3" ALIGN="CENTER" CELLPADDING="3"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>customergroup</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="company_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>company_id</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="name" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">name</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
|
entityaddress [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>entityaddress</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="entity_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>entity_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="first_name" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">first_name?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="name" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">name?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="street" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">street?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="streetnumber" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">streetnumber?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(50)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="zip" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">zip?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(50)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="city" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">city?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="county" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">county?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="addresstype" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">addresstype</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(50)</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
numbers [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>numbers</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="company_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>company_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="type" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">type</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(100)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="prefix" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">prefix</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(50)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="padding" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">padding</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="next" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">next</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
numbers [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>numbers</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="company_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>company_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="type" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">type</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(100)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="prefix" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">prefix</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(50)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="padding" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">padding</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="next" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">next</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
|
entity [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="1" BORDER="1"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD PORT="in0" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in1" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in2" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in3" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD></TR><TR><TD COLSPAN="4" ALIGN="CENTER" CELLPADDING="3"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>entity</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="customergroup_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>customergroup_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="first_name" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">first_name?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="name" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">name</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="created_at" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">created_at</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">DATETIME2</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="updated_at" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">updated_at</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">DATETIME2</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
company [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="1" BORDER="1"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD PORT="in0" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in1" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in2" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in3" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in4" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in5" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in6" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in7" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in8" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in9" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD></TR><TR><TD COLSPAN="10" ALIGN="CENTER" CELLPADDING="3"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>company</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="default_language_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>default_language_id</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="root_category_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>root_category_id</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="poscustomergroup_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>poscustomergroup_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="taxrate" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>taxrate</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="reducedtaxrate" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>reducedtaxrate</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="taxfreerate" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>taxfreerate</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="name" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">name</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
company [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="1" BORDER="1"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD PORT="in0" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in1" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in2" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in3" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in4" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in5" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in6" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in7" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in8" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in9" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD></TR><TR><TD COLSPAN="10" ALIGN="CENTER" CELLPADDING="3"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>company</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="default_language_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>default_language_id</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="root_category_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>root_category_id</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="poscustomergroup_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>poscustomergroup_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="taxrate" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>taxrate</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="reducedtaxrate" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>reducedtaxrate</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="taxfreerate" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>taxfreerate</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="name" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">name</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
entity [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="1" BORDER="1"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD PORT="in0" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in1" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD></TR><TR><TD COLSPAN="2" ALIGN="CENTER" CELLPADDING="3"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>entity</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="customergroup_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>customergroup_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="first_name" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">first_name?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="name" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">name</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="created_at" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">created_at</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">DATETIME2</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="updated_at" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">updated_at</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">DATETIME2</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
|
||||||
syncpos [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>syncpos</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="company_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>company_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="paircode" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">paircode</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(50)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="token" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">token?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
syncpos [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>syncpos</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="company_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>company_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="paircode" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">paircode</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(50)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="token" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">token?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
|
entitycontact [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>entitycontact</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="entity_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>entity_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="contacttype" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">contacttype</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(50)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="contact" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">contact</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
meta [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>meta</B></FONT></TD></TR><TR><TD PORT="key" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">key</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="value" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">value</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(MAX)</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
meta [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>meta</B></FONT></TD></TR><TR><TD PORT="key" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">key</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="value" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">value</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(MAX)</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
|
companysetting [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>companysetting</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="company_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>company_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="key" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">key</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="value" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">value</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(MAX)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="frontend" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">frontend</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">BIT</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
entityhistory [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>entityhistory</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="entity_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>entity_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="companyuser_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>companyuser_id</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="date" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">date</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">DATETIME2</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="text" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">text</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(MAX)</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
entityhistory [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>entityhistory</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="entity_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>entity_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="companyuser_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>companyuser_id</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="date" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">date</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">DATETIME2</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="text" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">text</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(MAX)</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
companyuser [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="1" BORDER="1"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD PORT="in0" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in1" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD></TR><TR><TD COLSPAN="2" ALIGN="CENTER" CELLPADDING="3"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>companyuser</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="company_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>company_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="google_auth_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>google_auth_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
companyuser [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="1" BORDER="1"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD PORT="in0" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in1" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD></TR><TR><TD COLSPAN="2" ALIGN="CENTER" CELLPADDING="3"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>companyuser</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="company_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>company_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="google_auth_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>google_auth_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
companysetting [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>companysetting</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="company_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>company_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="key" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">key</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="value" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">value</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(MAX)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="frontend" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">frontend</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">BIT</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
|
||||||
google_auth [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="1" BORDER="1"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD PORT="in0" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD></TR><TR><TD COLSPAN="1" ALIGN="CENTER" CELLPADDING="3"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>google_auth</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="selected_company" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>selected_company</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="email" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">email</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(320)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="picture" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">picture?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(2048)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="picturebinary" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">picturebinary?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">VARBINARY(MAX)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="sub" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">sub?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="created_at" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">created_at</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">DATETIME2</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
google_auth [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="1" BORDER="1"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD PORT="in0" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD></TR><TR><TD COLSPAN="1" ALIGN="CENTER" CELLPADDING="3"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>google_auth</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="selected_company" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>selected_company</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="email" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">email</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(320)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="picture" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">picture?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(2048)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="picturebinary" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">picturebinary?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">VARBINARY(MAX)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="sub" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">sub?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(255)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="created_at" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">created_at</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">DATETIME2</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
}
|
}
|
||||||
subgraph cluster_i18n {
|
subgraph cluster_i18n {
|
||||||
@@ -58,9 +60,9 @@ digraph schema {
|
|||||||
style="rounded,filled"; fillcolor="#ffffff60"; color="#a0aec0";
|
style="rounded,filled"; fillcolor="#ffffff60"; color="#a0aec0";
|
||||||
fontcolor="#1a365d"; margin=14;
|
fontcolor="#1a365d"; margin=14;
|
||||||
tax [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="1" BORDER="1"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD PORT="in0" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in1" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in2" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in3" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in4" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD></TR><TR><TD COLSPAN="5" ALIGN="CENTER" CELLPADDING="3"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>tax</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="rate" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">rate</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">DECIMAL(18,4)</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
tax [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="1" BORDER="1"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD PORT="in0" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in1" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in2" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in3" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD><TD PORT="in4" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD></TR><TR><TD COLSPAN="5" ALIGN="CENTER" CELLPADDING="3"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>tax</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="rate" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">rate</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">DECIMAL(18,4)</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
manifest [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="1" BORDER="1"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD PORT="in0" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD></TR><TR><TD COLSPAN="1" ALIGN="CENTER" CELLPADDING="3"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>manifest</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="company_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>company_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="entity_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>entity_id</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="number" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">number</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(100)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="type" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">type</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(100)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="date" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">date</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">DATETIME2</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
|
||||||
manifestarticle [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>manifestarticle</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="article_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>article_id</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="tax_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>tax_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="manifest_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>manifest_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="amount" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">amount</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">FLOAT</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="net" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">net</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">FLOAT</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="transactedamount" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">transactedamount</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">FLOAT</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="comment" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">comment?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(MAX)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="rebate" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">rebate</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">FLOAT</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
|
||||||
price [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>price</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="article_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>article_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="customergroup_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>customergroup_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="tax_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>tax_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="minmultiplier" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">minmultiplier</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">DECIMAL(18,4)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="net" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">net</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">FLOAT</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
price [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>price</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="article_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>article_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="customergroup_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>customergroup_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="tax_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>tax_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="minmultiplier" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">minmultiplier</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">DECIMAL(18,4)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="net" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">net</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">FLOAT</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
|
manifest [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="1" BORDER="1"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD PORT="in0" BGCOLOR="#bee3f8" BORDER="0" WIDTH="10" HEIGHT="4" CELLPADDING="0"></TD></TR><TR><TD COLSPAN="1" ALIGN="CENTER" CELLPADDING="3"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>manifest</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="entity_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>entity_id</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="company_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>company_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="number" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">number</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(100)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="type" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">type</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(100)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="date" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">date</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">DATETIME2</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
|
manifestarticle [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4" COLOR="#a0aec0"><TR><TD COLSPAN="2" BGCOLOR="#bee3f8" ALIGN="CENTER" CELLPADDING="4" BORDER="1"><FONT COLOR="#1a365d" POINT-SIZE="12"><B>manifestarticle</B></FONT></TD></TR><TR><TD PORT="id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>PK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="article_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>article_id</B>?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="tax_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>tax_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="manifest_id" COLSPAN="2" BGCOLOR="#ebf8ff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748"><B>manifest_id</B></FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">INT <B>FK</B></FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="amount" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">amount</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">FLOAT</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="net" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">net</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">FLOAT</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="transactedamount" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">transactedamount</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">FLOAT</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="comment" COLSPAN="2" BGCOLOR="#f7fafc" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">comment?</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">NVARCHAR(MAX)</FONT></TD></TR></TABLE></TD></TR><TR><TD PORT="rebate" COLSPAN="2" BGCOLOR="#ffffff" BORDER="1" CELLPADDING="0"><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" FIXEDSIZE="FALSE"><TR><TD ALIGN="LEFT" CELLPADDING="4"><FONT COLOR="#2d3748">rebate</FONT></TD><TD ALIGN="RIGHT" CELLPADDING="4"><FONT COLOR="#718096" POINT-SIZE="9">FLOAT</FONT></TD></TR></TABLE></TD></TR></TABLE>>];
|
||||||
}
|
}
|
||||||
subgraph cluster_units {
|
subgraph cluster_units {
|
||||||
label="Units"; labeljust="l"; fontsize=15;
|
label="Units"; labeljust="l"; fontsize=15;
|
||||||
@@ -81,52 +83,54 @@ digraph schema {
|
|||||||
company:reducedtaxrate:e -> tax:in0:n [color="#c05621", fontcolor="#c05621", tooltip="FK_company_reducedtaxrate"];
|
company:reducedtaxrate:e -> tax:in0:n [color="#c05621", fontcolor="#c05621", tooltip="FK_company_reducedtaxrate"];
|
||||||
company:taxfreerate:e -> tax:in1:n [color="#319795", fontcolor="#319795", tooltip="FK_company_taxfreerate"];
|
company:taxfreerate:e -> tax:in1:n [color="#319795", fontcolor="#319795", tooltip="FK_company_taxfreerate"];
|
||||||
customergroup:company_id:se -> company:in3:n [color="#97266d", fontcolor="#97266d", tooltip="FK_customergroup_company"];
|
customergroup:company_id:se -> company:in3:n [color="#97266d", fontcolor="#97266d", tooltip="FK_customergroup_company"];
|
||||||
company:poscustomergroup_id:nw -> customergroup:in0:n [color="#4c51bf", fontcolor="#4c51bf", tooltip="FK_company_poscustomergroup"];
|
company:poscustomergroup_id:nw -> customergroup:in1:n [color="#4c51bf", fontcolor="#4c51bf", tooltip="FK_company_poscustomergroup"];
|
||||||
entity:customergroup_id:sw -> customergroup:in1:n [color="#276749", fontcolor="#276749", tooltip="FK_entity_customergroup"];
|
entity:customergroup_id:sw -> customergroup:in0:n [color="#276749", fontcolor="#276749", tooltip="FK_entity_customergroup"];
|
||||||
entityhistory:entity_id:sw -> entity:in0:n [color="#9c4221", fontcolor="#9c4221", tooltip="FK_entityhistory_entity"];
|
entityaddress:entity_id:se -> entity:in0:n [color="#9c4221", fontcolor="#9c4221", tooltip="FK_entityaddress_entity"];
|
||||||
entityhistory:companyuser_id:se -> companyuser:in1:n [color="#0987a0", fontcolor="#0987a0", tooltip="FK_entityhistory_companyuser"];
|
entitycontact:entity_id:sw -> entity:in1:n [color="#0987a0", fontcolor="#0987a0", tooltip="FK_entitycontact_entity"];
|
||||||
unit:company_id:e -> company:in0:n [color="#553c9a", fontcolor="#553c9a", tooltip="FK_unit_company"];
|
entityhistory:entity_id:sw -> entity:in2:n [color="#553c9a", fontcolor="#553c9a", tooltip="FK_entityhistory_entity"];
|
||||||
unittext:unit_id:se -> unit:in0:n [color="#742a2a", fontcolor="#742a2a", tooltip="FK_unittext_unit"];
|
entityhistory:companyuser_id:se -> companyuser:in1:n [color="#742a2a", fontcolor="#742a2a", tooltip="FK_entityhistory_companyuser"];
|
||||||
unittext:language_id:se -> language:in0:n [color="#22543d", fontcolor="#22543d", tooltip="FK_unittext_language"];
|
unit:company_id:e -> company:in0:n [color="#22543d", fontcolor="#22543d", tooltip="FK_unit_company"];
|
||||||
brand:company_id:e -> company:in1:n [color="#1a365d", fontcolor="#1a365d", tooltip="FK_brand_company"];
|
unittext:unit_id:se -> unit:in0:n [color="#1a365d", fontcolor="#1a365d", tooltip="FK_unittext_unit"];
|
||||||
article:unit_id:sw -> unit:in1:n [color="#702459", fontcolor="#702459", tooltip="FK_article_unit"];
|
unittext:language_id:se -> language:in0:n [color="#702459", fontcolor="#702459", tooltip="FK_unittext_language"];
|
||||||
article:brand_id:e -> brand:in0:n [color="#744210", fontcolor="#744210", tooltip="FK_article_brand"];
|
brand:company_id:e -> company:in1:n [color="#744210", fontcolor="#744210", tooltip="FK_brand_company"];
|
||||||
article:articlelist_id:sw -> articlelist:in1:n [color="#285e61", fontcolor="#285e61", tooltip="FK_article_articlelist"];
|
article:unit_id:sw -> unit:in1:n [color="#285e61", fontcolor="#285e61", tooltip="FK_article_unit"];
|
||||||
article:optionslist_id:se -> optionslist:in0:n [color="#d53f8c", fontcolor="#d53f8c", tooltip="FK_article_optionslist"];
|
article:brand_id:e -> brand:in0:n [color="#d53f8c", fontcolor="#d53f8c", tooltip="FK_article_brand"];
|
||||||
article:fatherarticle_id:e -> article:id:e [color="#dd6b20", fontcolor="#dd6b20", tooltip="FK_article_fatherarticle"];
|
article:articlelist_id:sw -> articlelist:in1:n [color="#dd6b20", fontcolor="#dd6b20", tooltip="FK_article_articlelist"];
|
||||||
articlehistory:article_id:w -> article:in5:n [color="#38a169", fontcolor="#38a169", tooltip="FK_articlehistory_article"];
|
article:optionslist_id:se -> optionslist:in0:n [color="#38a169", fontcolor="#38a169", tooltip="FK_article_optionslist"];
|
||||||
articlehistory:companyuser_id:e -> companyuser:in0:n [color="#3182ce", fontcolor="#3182ce", tooltip="FK_articlehistory_companyuser"];
|
article:fatherarticle_id:e -> article:id:e [color="#3182ce", fontcolor="#3182ce", tooltip="FK_article_fatherarticle"];
|
||||||
articleean:article_id:sw -> article:in3:n [color="#805ad5", fontcolor="#805ad5", tooltip="FK_articleean_article"];
|
articlehistory:article_id:w -> article:in5:n [color="#805ad5", fontcolor="#805ad5", tooltip="FK_articlehistory_article"];
|
||||||
articlepic:article_id:w -> article:in7:n [color="#c53030", fontcolor="#c53030", tooltip="FK_articlepic_article"];
|
articlehistory:companyuser_id:e -> companyuser:in0:n [color="#c53030", fontcolor="#c53030", tooltip="FK_articlehistory_companyuser"];
|
||||||
articlepic:pic_id:se -> pic:in1:n [color="#2f855a", fontcolor="#2f855a", tooltip="FK_articlepic_pic"];
|
articleean:article_id:sw -> article:in3:n [color="#2f855a", fontcolor="#2f855a", tooltip="FK_articleean_article"];
|
||||||
brandpic:brand_id:w -> brand:in1:n [color="#2b6cb0", fontcolor="#2b6cb0", tooltip="FK_brandpic_brand"];
|
articlepic:article_id:w -> article:in7:n [color="#2b6cb0", fontcolor="#2b6cb0", tooltip="FK_articlepic_article"];
|
||||||
brandpic:pic_id:se -> pic:in0:n [color="#b7791f", fontcolor="#b7791f", tooltip="FK_brandpic_pic"];
|
articlepic:pic_id:se -> pic:in1:n [color="#b7791f", fontcolor="#b7791f", tooltip="FK_articlepic_pic"];
|
||||||
articlelistarticle:articlelist_id:se -> articlelist:in0:n [color="#6b46c1", fontcolor="#6b46c1", tooltip="FK_articlelistarticle_articlelist"];
|
brandpic:brand_id:w -> brand:in1:n [color="#6b46c1", fontcolor="#6b46c1", tooltip="FK_brandpic_brand"];
|
||||||
articlelistarticle:article_id:se -> article:in1:n [color="#c05621", fontcolor="#c05621", tooltip="FK_articlelistarticle_article"];
|
brandpic:pic_id:se -> pic:in0:n [color="#c05621", fontcolor="#c05621", tooltip="FK_brandpic_pic"];
|
||||||
optionslistarticle:optionslist_id:sw -> optionslist:in1:n [color="#319795", fontcolor="#319795", tooltip="FK_optionslistarticle_optionslist"];
|
articlelistarticle:articlelist_id:se -> articlelist:in0:n [color="#319795", fontcolor="#319795", tooltip="FK_articlelistarticle_articlelist"];
|
||||||
optionslistarticle:article_id:sw -> article:in4:n [color="#97266d", fontcolor="#97266d", tooltip="FK_optionslistarticle_article"];
|
articlelistarticle:article_id:se -> article:in1:n [color="#97266d", fontcolor="#97266d", tooltip="FK_articlelistarticle_article"];
|
||||||
categoryarticle:category_id:sw -> category:in2:n [color="#4c51bf", fontcolor="#4c51bf", tooltip="FK_categoryarticle_category"];
|
optionslistarticle:optionslist_id:sw -> optionslist:in1:n [color="#4c51bf", fontcolor="#4c51bf", tooltip="FK_optionslistarticle_optionslist"];
|
||||||
categoryarticle:article_id:w -> article:in6:n [color="#276749", fontcolor="#276749", tooltip="FK_categoryarticle_article"];
|
optionslistarticle:article_id:sw -> article:in4:n [color="#276749", fontcolor="#276749", tooltip="FK_optionslistarticle_article"];
|
||||||
categorypic:category_id:sw -> category:in4:n [color="#9c4221", fontcolor="#9c4221", tooltip="FK_categorypic_category"];
|
categoryarticle:category_id:sw -> category:in2:n [color="#9c4221", fontcolor="#9c4221", tooltip="FK_categoryarticle_category"];
|
||||||
categorypic:pic_id:sw -> pic:in2:n [color="#0987a0", fontcolor="#0987a0", tooltip="FK_categorypic_pic"];
|
categoryarticle:article_id:w -> article:in6:n [color="#0987a0", fontcolor="#0987a0", tooltip="FK_categoryarticle_article"];
|
||||||
categorytext:category_id:e -> category:in0:n [color="#553c9a", fontcolor="#553c9a", tooltip="FK_categorytext_category"];
|
categorypic:category_id:sw -> category:in4:n [color="#553c9a", fontcolor="#553c9a", tooltip="FK_categorypic_category"];
|
||||||
categorytext:language_id:sw -> language:in1:n [color="#742a2a", fontcolor="#742a2a", tooltip="FK_categorytext_language"];
|
categorypic:pic_id:sw -> pic:in2:n [color="#742a2a", fontcolor="#742a2a", tooltip="FK_categorypic_pic"];
|
||||||
articletext:article_id:e -> article:in0:n [color="#22543d", fontcolor="#22543d", tooltip="FK_articletext_article"];
|
categorytext:category_id:e -> category:in0:n [color="#22543d", fontcolor="#22543d", tooltip="FK_categorytext_category"];
|
||||||
articletext:language_id:sw -> language:in2:n [color="#1a365d", fontcolor="#1a365d", tooltip="FK_articletext_language"];
|
categorytext:language_id:sw -> language:in1:n [color="#1a365d", fontcolor="#1a365d", tooltip="FK_categorytext_language"];
|
||||||
price:tax_id:sw -> tax:in4:n [color="#702459", fontcolor="#702459", tooltip="FK_price_tax"];
|
articletext:article_id:e -> article:in0:n [color="#702459", fontcolor="#702459", tooltip="FK_articletext_article"];
|
||||||
price:article_id:w -> article:in9:n [color="#744210", fontcolor="#744210", tooltip="FK_price_article"];
|
articletext:language_id:sw -> language:in2:n [color="#744210", fontcolor="#744210", tooltip="FK_articletext_language"];
|
||||||
price:customergroup_id:w -> customergroup:in2:n [color="#285e61", fontcolor="#285e61", tooltip="FK_price_customergroup"];
|
price:tax_id:sw -> tax:in3:n [color="#285e61", fontcolor="#285e61", tooltip="FK_price_tax"];
|
||||||
manifest:company_id:sw -> company:in9:n [color="#d53f8c", fontcolor="#d53f8c", tooltip="FK_manifest_company"];
|
price:article_id:w -> article:in8:n [color="#d53f8c", fontcolor="#d53f8c", tooltip="FK_price_article"];
|
||||||
manifest:entity_id:w -> entity:in1:n [color="#dd6b20", fontcolor="#dd6b20", tooltip="FK_manifest_entity"];
|
price:customergroup_id:w -> customergroup:in2:n [color="#dd6b20", fontcolor="#dd6b20", tooltip="FK_price_customergroup"];
|
||||||
manifestarticle:manifest_id:sw -> manifest:in0:n [color="#38a169", fontcolor="#38a169", tooltip="FK_manifestarticle_manifest"];
|
manifest:company_id:sw -> company:in9:n [color="#38a169", fontcolor="#38a169", tooltip="FK_manifest_company"];
|
||||||
manifestarticle:article_id:w -> article:in8:n [color="#3182ce", fontcolor="#3182ce", tooltip="FK_manifestarticle_article"];
|
manifest:entity_id:w -> entity:in3:n [color="#3182ce", fontcolor="#3182ce", tooltip="FK_manifest_entity"];
|
||||||
manifestarticle:tax_id:sw -> tax:in3:n [color="#805ad5", fontcolor="#805ad5", tooltip="FK_manifestarticle_tax"];
|
manifestarticle:manifest_id:sw -> manifest:in0:n [color="#805ad5", fontcolor="#805ad5", tooltip="FK_manifestarticle_manifest"];
|
||||||
numbers:company_id:se -> company:in4:n [color="#c53030", fontcolor="#c53030", tooltip="FK_numbers_company"];
|
manifestarticle:article_id:w -> article:in9:n [color="#c53030", fontcolor="#c53030", tooltip="FK_manifestarticle_article"];
|
||||||
companyuser:google_auth_id:se -> google_auth:in0:n [color="#2f855a", fontcolor="#2f855a", tooltip="FK_companyuser_google_auth"];
|
manifestarticle:tax_id:sw -> tax:in4:n [color="#2f855a", fontcolor="#2f855a", tooltip="FK_manifestarticle_tax"];
|
||||||
companyuser:company_id:sw -> company:in6:n [color="#2b6cb0", fontcolor="#2b6cb0", tooltip="FK_companyuser_company"];
|
numbers:company_id:se -> company:in4:n [color="#2b6cb0", fontcolor="#2b6cb0", tooltip="FK_numbers_company"];
|
||||||
syncpos:company_id:sw -> company:in5:n [color="#b7791f", fontcolor="#b7791f", tooltip="FK_syncpos_company"];
|
companyuser:google_auth_id:se -> google_auth:in0:n [color="#b7791f", fontcolor="#b7791f", tooltip="FK_companyuser_google_auth"];
|
||||||
companysetting:company_id:sw -> company:in7:n [color="#6b46c1", fontcolor="#6b46c1", tooltip="FK_companysetting_company"];
|
companyuser:company_id:sw -> company:in7:n [color="#6b46c1", fontcolor="#6b46c1", tooltip="FK_companyuser_company"];
|
||||||
posterminal:company_id:e -> company:in2:n [color="#c05621", fontcolor="#c05621", tooltip="FK_posterminal_company"];
|
syncpos:company_id:sw -> company:in5:n [color="#c05621", fontcolor="#c05621", tooltip="FK_syncpos_company"];
|
||||||
posterminalcategory:posterminal_id:se -> posterminal:in0:n [color="#319795", fontcolor="#319795", tooltip="FK_posterminalcategory_posterminal"];
|
companysetting:company_id:sw -> company:in6:n [color="#319795", fontcolor="#319795", tooltip="FK_companysetting_company"];
|
||||||
posterminalcategory:category_id:sw -> category:in3:n [color="#97266d", fontcolor="#97266d", tooltip="FK_posterminalcategory_category"];
|
posterminal:company_id:e -> company:in2:n [color="#97266d", fontcolor="#97266d", tooltip="FK_posterminal_company"];
|
||||||
|
posterminalcategory:posterminal_id:se -> posterminal:in0:n [color="#4c51bf", fontcolor="#4c51bf", tooltip="FK_posterminalcategory_posterminal"];
|
||||||
|
posterminalcategory:category_id:sw -> category:in3:n [color="#276749", fontcolor="#276749", tooltip="FK_posterminalcategory_category"];
|
||||||
}
|
}
|
||||||
2706
schema-graph.svg
2706
schema-graph.svg
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 170 KiB After Width: | Height: | Size: 180 KiB |
@@ -158,6 +158,43 @@ const MENU = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
customergroup: {
|
||||||
|
label: 'customergroup',
|
||||||
|
items: [
|
||||||
|
{ value: 'customergroup.list', label: 'list', hint: 'googleAuthId, companyId → rows' },
|
||||||
|
{ value: 'customergroup.create', label: 'create', hint: 'googleAuthId, companyId, name → row' },
|
||||||
|
{ value: 'customergroup.update', label: 'update', hint: 'googleAuthId, companyId, id, name → row' },
|
||||||
|
{ value: 'customergroup.delete', label: 'delete', hint: 'googleAuthId, companyId, id' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
entity: {
|
||||||
|
label: 'entity',
|
||||||
|
items: [
|
||||||
|
{ value: 'entity.list', label: 'list', hint: 'googleAuthId, companyId, customergroupId? → rows' },
|
||||||
|
{ value: 'entity.getById', label: 'getById', hint: 'googleAuthId, companyId, id → row' },
|
||||||
|
{ value: 'entity.create', label: 'create', hint: 'googleAuthId, companyId, JSON → row' },
|
||||||
|
{ value: 'entity.update', label: 'update', hint: 'googleAuthId, companyId, id, JSON → row' },
|
||||||
|
{ value: 'entity.delete', label: 'delete', hint: 'googleAuthId, companyId, id' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
entityaddress: {
|
||||||
|
label: 'entityaddress',
|
||||||
|
items: [
|
||||||
|
{ value: 'entityaddress.list', label: 'list', hint: 'googleAuthId, companyId, entityId → rows' },
|
||||||
|
{ value: 'entityaddress.create', label: 'create', hint: 'googleAuthId, companyId, entityId, JSON → row' },
|
||||||
|
{ value: 'entityaddress.update', label: 'update', hint: 'googleAuthId, companyId, entityId, id, JSON → row' },
|
||||||
|
{ value: 'entityaddress.delete', label: 'delete', hint: 'googleAuthId, companyId, entityId, id' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
entitycontact: {
|
||||||
|
label: 'entitycontact',
|
||||||
|
items: [
|
||||||
|
{ value: 'entitycontact.list', label: 'list', hint: 'googleAuthId, companyId, entityId → rows' },
|
||||||
|
{ value: 'entitycontact.create', label: 'create', hint: 'googleAuthId, companyId, entityId, JSON → row' },
|
||||||
|
{ value: 'entitycontact.update', label: 'update', hint: 'googleAuthId, companyId, entityId, id, JSON → row' },
|
||||||
|
{ value: 'entitycontact.delete', label: 'delete', hint: 'googleAuthId, companyId, entityId, id' },
|
||||||
|
],
|
||||||
|
},
|
||||||
supplier: {
|
supplier: {
|
||||||
label: 'supplier',
|
label: 'supplier',
|
||||||
items: [
|
items: [
|
||||||
@@ -681,6 +718,362 @@ async function runMethod(client, action) {
|
|||||||
await client.brand.delete(Number(googleAuthId), Number(companyId), id);
|
await client.brand.delete(Number(googleAuthId), Number(companyId), id);
|
||||||
return ['ok', true];
|
return ['ok', true];
|
||||||
}
|
}
|
||||||
|
case 'customergroup.list': {
|
||||||
|
const googleAuthId = await askInt('google_auth id');
|
||||||
|
if (googleAuthId == null) return;
|
||||||
|
const companyId = await askInt('company id');
|
||||||
|
if (companyId == null) return;
|
||||||
|
return [
|
||||||
|
'result[]',
|
||||||
|
await client.customergroup.list(Number(googleAuthId), Number(companyId)),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
case 'customergroup.create': {
|
||||||
|
const googleAuthId = await askInt('google_auth id');
|
||||||
|
if (googleAuthId == null) return;
|
||||||
|
const companyId = await askInt('company id');
|
||||||
|
if (companyId == null) return;
|
||||||
|
const name = await askText('name', {
|
||||||
|
validate: (v) => (!v?.trim() ? 'Required' : undefined),
|
||||||
|
});
|
||||||
|
if (name == null) return;
|
||||||
|
return [
|
||||||
|
'result',
|
||||||
|
await client.customergroup.create(Number(googleAuthId), Number(companyId), {
|
||||||
|
name,
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
case 'customergroup.update': {
|
||||||
|
const googleAuthId = await askInt('google_auth id');
|
||||||
|
if (googleAuthId == null) return;
|
||||||
|
const companyId = await askInt('company id');
|
||||||
|
if (companyId == null) return;
|
||||||
|
const id = await askInt('customergroup id');
|
||||||
|
if (id == null) return;
|
||||||
|
const name = await askText('name', {
|
||||||
|
validate: (v) => (!v?.trim() ? 'Required' : undefined),
|
||||||
|
});
|
||||||
|
if (name == null) return;
|
||||||
|
return [
|
||||||
|
'result',
|
||||||
|
await client.customergroup.update(
|
||||||
|
Number(googleAuthId),
|
||||||
|
Number(companyId),
|
||||||
|
Number(id),
|
||||||
|
{ name },
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
case 'customergroup.delete': {
|
||||||
|
const googleAuthId = await askInt('google_auth id');
|
||||||
|
if (googleAuthId == null) return;
|
||||||
|
const companyId = await askInt('company id');
|
||||||
|
if (companyId == null) return;
|
||||||
|
const id = await askInt('customergroup id');
|
||||||
|
if (id == null) return;
|
||||||
|
await client.customergroup.delete(
|
||||||
|
Number(googleAuthId),
|
||||||
|
Number(companyId),
|
||||||
|
Number(id),
|
||||||
|
);
|
||||||
|
return ['ok', true];
|
||||||
|
}
|
||||||
|
case 'entity.list': {
|
||||||
|
const googleAuthId = await askInt('google_auth id');
|
||||||
|
if (googleAuthId == null) return;
|
||||||
|
const companyId = await askInt('company id');
|
||||||
|
if (companyId == null) return;
|
||||||
|
const groupRaw = await askText('customergroup id (empty = all)', {
|
||||||
|
placeholder: '',
|
||||||
|
validate: (v) =>
|
||||||
|
v?.trim() && !/^\d+$/.test(v.trim()) ? 'Integer or empty' : undefined,
|
||||||
|
});
|
||||||
|
if (groupRaw == null) return;
|
||||||
|
const customergroupId = groupRaw.trim()
|
||||||
|
? Number(groupRaw.trim())
|
||||||
|
: undefined;
|
||||||
|
return [
|
||||||
|
'result[]',
|
||||||
|
await client.entity.list(Number(googleAuthId), Number(companyId), {
|
||||||
|
customergroupId,
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
case 'entity.getById': {
|
||||||
|
const googleAuthId = await askInt('google_auth id');
|
||||||
|
if (googleAuthId == null) return;
|
||||||
|
const companyId = await askInt('company id');
|
||||||
|
if (companyId == null) return;
|
||||||
|
const id = await askInt('entity id');
|
||||||
|
if (id == null) return;
|
||||||
|
return [
|
||||||
|
'result',
|
||||||
|
await client.entity.getById(
|
||||||
|
Number(googleAuthId),
|
||||||
|
Number(companyId),
|
||||||
|
Number(id),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
case 'entity.create': {
|
||||||
|
const googleAuthId = await askInt('google_auth id');
|
||||||
|
if (googleAuthId == null) return;
|
||||||
|
const companyId = await askInt('company id');
|
||||||
|
if (companyId == null) return;
|
||||||
|
const bodyJson = await askText('entity JSON', {
|
||||||
|
placeholder: '{"customergroupId":1,"name":"Acme","firstName":null}',
|
||||||
|
validate: (v) => {
|
||||||
|
if (!v?.trim()) return 'Required';
|
||||||
|
try {
|
||||||
|
JSON.parse(v);
|
||||||
|
} catch {
|
||||||
|
return 'Invalid JSON';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (bodyJson == null) return;
|
||||||
|
return [
|
||||||
|
'result',
|
||||||
|
await client.entity.create(
|
||||||
|
Number(googleAuthId),
|
||||||
|
Number(companyId),
|
||||||
|
JSON.parse(bodyJson),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
case 'entity.update': {
|
||||||
|
const googleAuthId = await askInt('google_auth id');
|
||||||
|
if (googleAuthId == null) return;
|
||||||
|
const companyId = await askInt('company id');
|
||||||
|
if (companyId == null) return;
|
||||||
|
const id = await askInt('entity id');
|
||||||
|
if (id == null) return;
|
||||||
|
const patchJson = await askText('patch JSON', {
|
||||||
|
placeholder: '{"name":"Acme","firstName":"Ada"}',
|
||||||
|
validate: (v) => {
|
||||||
|
if (!v?.trim()) return 'Required';
|
||||||
|
try {
|
||||||
|
JSON.parse(v);
|
||||||
|
} catch {
|
||||||
|
return 'Invalid JSON';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (patchJson == null) return;
|
||||||
|
return [
|
||||||
|
'result',
|
||||||
|
await client.entity.update(
|
||||||
|
Number(googleAuthId),
|
||||||
|
Number(companyId),
|
||||||
|
Number(id),
|
||||||
|
JSON.parse(patchJson),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
case 'entity.delete': {
|
||||||
|
const googleAuthId = await askInt('google_auth id');
|
||||||
|
if (googleAuthId == null) return;
|
||||||
|
const companyId = await askInt('company id');
|
||||||
|
if (companyId == null) return;
|
||||||
|
const id = await askInt('entity id');
|
||||||
|
if (id == null) return;
|
||||||
|
await client.entity.delete(
|
||||||
|
Number(googleAuthId),
|
||||||
|
Number(companyId),
|
||||||
|
Number(id),
|
||||||
|
);
|
||||||
|
return ['ok', true];
|
||||||
|
}
|
||||||
|
case 'entityaddress.list': {
|
||||||
|
const googleAuthId = await askInt('google_auth id');
|
||||||
|
if (googleAuthId == null) return;
|
||||||
|
const companyId = await askInt('company id');
|
||||||
|
if (companyId == null) return;
|
||||||
|
const entityId = await askInt('entity id');
|
||||||
|
if (entityId == null) return;
|
||||||
|
return [
|
||||||
|
'result[]',
|
||||||
|
await client.entityaddress.list(
|
||||||
|
Number(googleAuthId),
|
||||||
|
Number(companyId),
|
||||||
|
Number(entityId),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
case 'entityaddress.create': {
|
||||||
|
const googleAuthId = await askInt('google_auth id');
|
||||||
|
if (googleAuthId == null) return;
|
||||||
|
const companyId = await askInt('company id');
|
||||||
|
if (companyId == null) return;
|
||||||
|
const entityId = await askInt('entity id');
|
||||||
|
if (entityId == null) return;
|
||||||
|
const bodyJson = await askText('address JSON', {
|
||||||
|
placeholder:
|
||||||
|
'{"addressType":"billing","street":"Main","streetNumber":"1","zip":"1010","city":"Wien"}',
|
||||||
|
validate: (v) => {
|
||||||
|
if (!v?.trim()) return 'Required';
|
||||||
|
try {
|
||||||
|
JSON.parse(v);
|
||||||
|
} catch {
|
||||||
|
return 'Invalid JSON';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (bodyJson == null) return;
|
||||||
|
return [
|
||||||
|
'result',
|
||||||
|
await client.entityaddress.create(
|
||||||
|
Number(googleAuthId),
|
||||||
|
Number(companyId),
|
||||||
|
Number(entityId),
|
||||||
|
JSON.parse(bodyJson),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
case 'entityaddress.update': {
|
||||||
|
const googleAuthId = await askInt('google_auth id');
|
||||||
|
if (googleAuthId == null) return;
|
||||||
|
const companyId = await askInt('company id');
|
||||||
|
if (companyId == null) return;
|
||||||
|
const entityId = await askInt('entity id');
|
||||||
|
if (entityId == null) return;
|
||||||
|
const id = await askInt('address id');
|
||||||
|
if (id == null) return;
|
||||||
|
const patchJson = await askText('patch JSON', {
|
||||||
|
placeholder: '{"city":"Graz"}',
|
||||||
|
validate: (v) => {
|
||||||
|
if (!v?.trim()) return 'Required';
|
||||||
|
try {
|
||||||
|
JSON.parse(v);
|
||||||
|
} catch {
|
||||||
|
return 'Invalid JSON';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (patchJson == null) return;
|
||||||
|
return [
|
||||||
|
'result',
|
||||||
|
await client.entityaddress.update(
|
||||||
|
Number(googleAuthId),
|
||||||
|
Number(companyId),
|
||||||
|
Number(entityId),
|
||||||
|
Number(id),
|
||||||
|
JSON.parse(patchJson),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
case 'entityaddress.delete': {
|
||||||
|
const googleAuthId = await askInt('google_auth id');
|
||||||
|
if (googleAuthId == null) return;
|
||||||
|
const companyId = await askInt('company id');
|
||||||
|
if (companyId == null) return;
|
||||||
|
const entityId = await askInt('entity id');
|
||||||
|
if (entityId == null) return;
|
||||||
|
const id = await askInt('address id');
|
||||||
|
if (id == null) return;
|
||||||
|
await client.entityaddress.delete(
|
||||||
|
Number(googleAuthId),
|
||||||
|
Number(companyId),
|
||||||
|
Number(entityId),
|
||||||
|
Number(id),
|
||||||
|
);
|
||||||
|
return ['ok', true];
|
||||||
|
}
|
||||||
|
case 'entitycontact.list': {
|
||||||
|
const googleAuthId = await askInt('google_auth id');
|
||||||
|
if (googleAuthId == null) return;
|
||||||
|
const companyId = await askInt('company id');
|
||||||
|
if (companyId == null) return;
|
||||||
|
const entityId = await askInt('entity id');
|
||||||
|
if (entityId == null) return;
|
||||||
|
return [
|
||||||
|
'result[]',
|
||||||
|
await client.entitycontact.list(
|
||||||
|
Number(googleAuthId),
|
||||||
|
Number(companyId),
|
||||||
|
Number(entityId),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
case 'entitycontact.create': {
|
||||||
|
const googleAuthId = await askInt('google_auth id');
|
||||||
|
if (googleAuthId == null) return;
|
||||||
|
const companyId = await askInt('company id');
|
||||||
|
if (companyId == null) return;
|
||||||
|
const entityId = await askInt('entity id');
|
||||||
|
if (entityId == null) return;
|
||||||
|
const bodyJson = await askText('contact JSON', {
|
||||||
|
placeholder: '{"contactType":"email","contact":"a@b.c"}',
|
||||||
|
validate: (v) => {
|
||||||
|
if (!v?.trim()) return 'Required';
|
||||||
|
try {
|
||||||
|
JSON.parse(v);
|
||||||
|
} catch {
|
||||||
|
return 'Invalid JSON';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (bodyJson == null) return;
|
||||||
|
return [
|
||||||
|
'result',
|
||||||
|
await client.entitycontact.create(
|
||||||
|
Number(googleAuthId),
|
||||||
|
Number(companyId),
|
||||||
|
Number(entityId),
|
||||||
|
JSON.parse(bodyJson),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
case 'entitycontact.update': {
|
||||||
|
const googleAuthId = await askInt('google_auth id');
|
||||||
|
if (googleAuthId == null) return;
|
||||||
|
const companyId = await askInt('company id');
|
||||||
|
if (companyId == null) return;
|
||||||
|
const entityId = await askInt('entity id');
|
||||||
|
if (entityId == null) return;
|
||||||
|
const id = await askInt('contact id');
|
||||||
|
if (id == null) return;
|
||||||
|
const patchJson = await askText('patch JSON', {
|
||||||
|
placeholder: '{"contact":"b@c.d"}',
|
||||||
|
validate: (v) => {
|
||||||
|
if (!v?.trim()) return 'Required';
|
||||||
|
try {
|
||||||
|
JSON.parse(v);
|
||||||
|
} catch {
|
||||||
|
return 'Invalid JSON';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (patchJson == null) return;
|
||||||
|
return [
|
||||||
|
'result',
|
||||||
|
await client.entitycontact.update(
|
||||||
|
Number(googleAuthId),
|
||||||
|
Number(companyId),
|
||||||
|
Number(entityId),
|
||||||
|
Number(id),
|
||||||
|
JSON.parse(patchJson),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
case 'entitycontact.delete': {
|
||||||
|
const googleAuthId = await askInt('google_auth id');
|
||||||
|
if (googleAuthId == null) return;
|
||||||
|
const companyId = await askInt('company id');
|
||||||
|
if (companyId == null) return;
|
||||||
|
const entityId = await askInt('entity id');
|
||||||
|
if (entityId == null) return;
|
||||||
|
const id = await askInt('contact id');
|
||||||
|
if (id == null) return;
|
||||||
|
await client.entitycontact.delete(
|
||||||
|
Number(googleAuthId),
|
||||||
|
Number(companyId),
|
||||||
|
Number(entityId),
|
||||||
|
Number(id),
|
||||||
|
);
|
||||||
|
return ['ok', true];
|
||||||
|
}
|
||||||
case 'supplier.list': {
|
case 'supplier.list': {
|
||||||
const googleAuthId = await askInt('google_auth id');
|
const googleAuthId = await askInt('google_auth id');
|
||||||
if (googleAuthId == null) return;
|
if (googleAuthId == null) return;
|
||||||
|
|||||||
46
src/index.js
46
src/index.js
@@ -39,6 +39,23 @@ import companysettingDelete from './store/companysetting/delete.js';
|
|||||||
import brandList from './store/brand/list.js';
|
import brandList from './store/brand/list.js';
|
||||||
import brandUpsert from './store/brand/upsert.js';
|
import brandUpsert from './store/brand/upsert.js';
|
||||||
import brandDelete from './store/brand/delete.js';
|
import brandDelete from './store/brand/delete.js';
|
||||||
|
import customergroupList from './store/customergroup/list.js';
|
||||||
|
import customergroupCreate from './store/customergroup/create.js';
|
||||||
|
import customergroupUpdate from './store/customergroup/update.js';
|
||||||
|
import customergroupDelete from './store/customergroup/delete.js';
|
||||||
|
import entityList from './store/entity/list.js';
|
||||||
|
import entityGetById from './store/entity/getById.js';
|
||||||
|
import entityCreate from './store/entity/create.js';
|
||||||
|
import entityUpdate from './store/entity/update.js';
|
||||||
|
import entityDelete from './store/entity/delete.js';
|
||||||
|
import entityaddressList from './store/entityaddress/list.js';
|
||||||
|
import entityaddressCreate from './store/entityaddress/create.js';
|
||||||
|
import entityaddressUpdate from './store/entityaddress/update.js';
|
||||||
|
import entityaddressDelete from './store/entityaddress/delete.js';
|
||||||
|
import entitycontactList from './store/entitycontact/list.js';
|
||||||
|
import entitycontactCreate from './store/entitycontact/create.js';
|
||||||
|
import entitycontactUpdate from './store/entitycontact/update.js';
|
||||||
|
import entitycontactDelete from './store/entitycontact/delete.js';
|
||||||
import supplierList from './store/supplier/list.js';
|
import supplierList from './store/supplier/list.js';
|
||||||
import supplierCreate from './store/supplier/create.js';
|
import supplierCreate from './store/supplier/create.js';
|
||||||
import supplierUpdate from './store/supplier/update.js';
|
import supplierUpdate from './store/supplier/update.js';
|
||||||
@@ -158,6 +175,35 @@ export default class LibDashStore {
|
|||||||
delete: brandDelete(pool),
|
delete: brandDelete(pool),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.customergroup = {
|
||||||
|
list: customergroupList(pool),
|
||||||
|
create: customergroupCreate(pool),
|
||||||
|
update: customergroupUpdate(pool),
|
||||||
|
delete: customergroupDelete(pool),
|
||||||
|
};
|
||||||
|
|
||||||
|
this.entity = {
|
||||||
|
list: entityList(pool),
|
||||||
|
getById: entityGetById(pool),
|
||||||
|
create: entityCreate(pool),
|
||||||
|
update: entityUpdate(pool),
|
||||||
|
delete: entityDelete(pool),
|
||||||
|
};
|
||||||
|
|
||||||
|
this.entityaddress = {
|
||||||
|
list: entityaddressList(pool),
|
||||||
|
create: entityaddressCreate(pool),
|
||||||
|
update: entityaddressUpdate(pool),
|
||||||
|
delete: entityaddressDelete(pool),
|
||||||
|
};
|
||||||
|
|
||||||
|
this.entitycontact = {
|
||||||
|
list: entitycontactList(pool),
|
||||||
|
create: entitycontactCreate(pool),
|
||||||
|
update: entitycontactUpdate(pool),
|
||||||
|
delete: entitycontactDelete(pool),
|
||||||
|
};
|
||||||
|
|
||||||
this.supplier = {
|
this.supplier = {
|
||||||
list: supplierList(pool),
|
list: supplierList(pool),
|
||||||
create: supplierCreate(pool),
|
create: supplierCreate(pool),
|
||||||
|
|||||||
@@ -164,6 +164,38 @@ BEGIN
|
|||||||
END
|
END
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const INIT_ENTITYADDRESS = `
|
||||||
|
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'entityaddress')
|
||||||
|
BEGIN
|
||||||
|
CREATE TABLE entityaddress (
|
||||||
|
id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
entity_id INT NOT NULL,
|
||||||
|
first_name NVARCHAR(255) NULL,
|
||||||
|
name NVARCHAR(255) NULL,
|
||||||
|
street NVARCHAR(255) NULL,
|
||||||
|
streetnumber NVARCHAR(50) NULL,
|
||||||
|
zip NVARCHAR(50) NULL,
|
||||||
|
city NVARCHAR(255) NULL,
|
||||||
|
county NVARCHAR(255) NULL,
|
||||||
|
addresstype NVARCHAR(50) NOT NULL,
|
||||||
|
CONSTRAINT FK_entityaddress_entity FOREIGN KEY (entity_id) REFERENCES entity(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
END
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const INIT_ENTITYCONTACT = `
|
||||||
|
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'entitycontact')
|
||||||
|
BEGIN
|
||||||
|
CREATE TABLE entitycontact (
|
||||||
|
id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
entity_id INT NOT NULL,
|
||||||
|
contacttype NVARCHAR(50) NOT NULL,
|
||||||
|
contact NVARCHAR(255) NOT NULL,
|
||||||
|
CONSTRAINT FK_entitycontact_entity FOREIGN KEY (entity_id) REFERENCES entity(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
END
|
||||||
|
`;
|
||||||
|
|
||||||
export const INIT_ENTITYHISTORY = `
|
export const INIT_ENTITYHISTORY = `
|
||||||
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'entityhistory')
|
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'entityhistory')
|
||||||
BEGIN
|
BEGIN
|
||||||
@@ -636,6 +668,8 @@ export const SCHEMA_SCRIPTS = [
|
|||||||
INIT_CUSTOMERGROUP,
|
INIT_CUSTOMERGROUP,
|
||||||
INIT_COMPANY_POS_CUSTOMERGROUP_FK,
|
INIT_COMPANY_POS_CUSTOMERGROUP_FK,
|
||||||
INIT_ENTITY,
|
INIT_ENTITY,
|
||||||
|
INIT_ENTITYADDRESS,
|
||||||
|
INIT_ENTITYCONTACT,
|
||||||
INIT_UNIT,
|
INIT_UNIT,
|
||||||
INIT_UNITTEXT,
|
INIT_UNITTEXT,
|
||||||
INIT_OPTIONSLIST,
|
INIT_OPTIONSLIST,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
export const CREATE = `
|
export const CREATE = `
|
||||||
INSERT INTO customergroup (name, company_id)
|
INSERT INTO customergroup (name, company_id)
|
||||||
OUTPUT INSERTED.id
|
OUTPUT INSERTED.id, INSERTED.name
|
||||||
VALUES (@name, @companyId)
|
VALUES (@name, @companyId)
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -17,7 +17,32 @@ WHERE id = @id
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const GET_BY_COMPANY_AND_NAME = `
|
export const GET_BY_COMPANY_AND_NAME = `
|
||||||
SELECT id
|
SELECT id, name
|
||||||
FROM customergroup
|
FROM customergroup
|
||||||
WHERE company_id = @companyId AND name = @name
|
WHERE company_id = @companyId AND name = @name
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const LIST_BY_COMPANY = `
|
||||||
|
SELECT id, name
|
||||||
|
FROM customergroup
|
||||||
|
WHERE company_id = @companyId
|
||||||
|
ORDER BY name, id
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const GET_BY_COMPANY_AND_ID = `
|
||||||
|
SELECT id, name
|
||||||
|
FROM customergroup
|
||||||
|
WHERE id = @id AND company_id = @companyId
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const UPDATE_NAME = `
|
||||||
|
UPDATE customergroup
|
||||||
|
SET name = @name
|
||||||
|
OUTPUT INSERTED.id, INSERTED.name
|
||||||
|
WHERE id = @id AND company_id = @companyId
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const DELETE_BY_COMPANY_AND_ID = `
|
||||||
|
DELETE FROM customergroup
|
||||||
|
WHERE id = @id AND company_id = @companyId
|
||||||
|
`;
|
||||||
|
|||||||
@@ -1,5 +1,42 @@
|
|||||||
export const SUPPLIER_GROUP_NAME = 'Lieferanten';
|
export const SUPPLIER_GROUP_NAME = 'Lieferanten';
|
||||||
|
|
||||||
|
export const ENTITY_COLUMNS = `
|
||||||
|
e.id,
|
||||||
|
e.customergroup_id AS customergroupId,
|
||||||
|
e.first_name AS firstName,
|
||||||
|
e.name,
|
||||||
|
e.created_at AS createdAt,
|
||||||
|
e.updated_at AS updatedAt
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const LIST_BY_COMPANY = `
|
||||||
|
SELECT
|
||||||
|
${ENTITY_COLUMNS}
|
||||||
|
FROM entity e
|
||||||
|
INNER JOIN customergroup cg ON cg.id = e.customergroup_id
|
||||||
|
WHERE cg.company_id = @companyId
|
||||||
|
ORDER BY e.name, e.id
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const LIST_BY_COMPANY_AND_GROUP = `
|
||||||
|
SELECT
|
||||||
|
${ENTITY_COLUMNS}
|
||||||
|
FROM entity e
|
||||||
|
INNER JOIN customergroup cg ON cg.id = e.customergroup_id
|
||||||
|
WHERE cg.company_id = @companyId
|
||||||
|
AND e.customergroup_id = @customergroupId
|
||||||
|
ORDER BY e.name, e.id
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const GET_BY_COMPANY_AND_ID = `
|
||||||
|
SELECT
|
||||||
|
${ENTITY_COLUMNS}
|
||||||
|
FROM entity e
|
||||||
|
INNER JOIN customergroup cg ON cg.id = e.customergroup_id
|
||||||
|
WHERE e.id = @id
|
||||||
|
AND cg.company_id = @companyId
|
||||||
|
`;
|
||||||
|
|
||||||
export const LIST_SUPPLIERS_BY_COMPANY = `
|
export const LIST_SUPPLIERS_BY_COMPANY = `
|
||||||
SELECT
|
SELECT
|
||||||
e.id,
|
e.id,
|
||||||
@@ -27,9 +64,31 @@ WHERE e.id = @id
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const CREATE = `
|
export const CREATE = `
|
||||||
INSERT INTO entity (customergroup_id, name)
|
INSERT INTO entity (customergroup_id, first_name, name)
|
||||||
OUTPUT INSERTED.id, INSERTED.name, INSERTED.created_at AS createdAt, INSERTED.updated_at AS updatedAt
|
OUTPUT
|
||||||
VALUES (@customergroupId, @name)
|
INSERTED.id,
|
||||||
|
INSERTED.customergroup_id AS customergroupId,
|
||||||
|
INSERTED.first_name AS firstName,
|
||||||
|
INSERTED.name,
|
||||||
|
INSERTED.created_at AS createdAt,
|
||||||
|
INSERTED.updated_at AS updatedAt
|
||||||
|
VALUES (@customergroupId, @firstName, @name)
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const UPDATE = `
|
||||||
|
UPDATE entity
|
||||||
|
SET
|
||||||
|
first_name = @firstName,
|
||||||
|
name = @name,
|
||||||
|
updated_at = SYSUTCDATETIME()
|
||||||
|
OUTPUT
|
||||||
|
INSERTED.id,
|
||||||
|
INSERTED.customergroup_id AS customergroupId,
|
||||||
|
INSERTED.first_name AS firstName,
|
||||||
|
INSERTED.name,
|
||||||
|
INSERTED.created_at AS createdAt,
|
||||||
|
INSERTED.updated_at AS updatedAt
|
||||||
|
WHERE id = @id
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const UPDATE_NAME = `
|
export const UPDATE_NAME = `
|
||||||
@@ -40,6 +99,14 @@ WHERE id = @id
|
|||||||
AND customergroup_id = @customergroupId
|
AND customergroup_id = @customergroupId
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const DELETE_BY_COMPANY_AND_ID = `
|
||||||
|
DELETE e
|
||||||
|
FROM entity e
|
||||||
|
INNER JOIN customergroup cg ON cg.id = e.customergroup_id
|
||||||
|
WHERE e.id = @id
|
||||||
|
AND cg.company_id = @companyId
|
||||||
|
`;
|
||||||
|
|
||||||
export const DELETE_BY_ID = `
|
export const DELETE_BY_ID = `
|
||||||
DELETE e
|
DELETE e
|
||||||
FROM entity e
|
FROM entity e
|
||||||
|
|||||||
93
src/sql/entityaddress.js
Normal file
93
src/sql/entityaddress.js
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
export const ADDRESS_COLUMNS = `
|
||||||
|
id,
|
||||||
|
entity_id AS entityId,
|
||||||
|
first_name AS firstName,
|
||||||
|
name,
|
||||||
|
street,
|
||||||
|
streetnumber AS streetNumber,
|
||||||
|
zip,
|
||||||
|
city,
|
||||||
|
county,
|
||||||
|
addresstype AS addressType
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const LIST_BY_ENTITY = `
|
||||||
|
SELECT
|
||||||
|
${ADDRESS_COLUMNS}
|
||||||
|
FROM entityaddress
|
||||||
|
WHERE entity_id = @entityId
|
||||||
|
ORDER BY id
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const GET_BY_ENTITY_AND_ID = `
|
||||||
|
SELECT
|
||||||
|
${ADDRESS_COLUMNS}
|
||||||
|
FROM entityaddress
|
||||||
|
WHERE id = @id AND entity_id = @entityId
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const CREATE = `
|
||||||
|
INSERT INTO entityaddress (
|
||||||
|
entity_id,
|
||||||
|
first_name,
|
||||||
|
name,
|
||||||
|
street,
|
||||||
|
streetnumber,
|
||||||
|
zip,
|
||||||
|
city,
|
||||||
|
county,
|
||||||
|
addresstype
|
||||||
|
)
|
||||||
|
OUTPUT
|
||||||
|
INSERTED.id,
|
||||||
|
INSERTED.entity_id AS entityId,
|
||||||
|
INSERTED.first_name AS firstName,
|
||||||
|
INSERTED.name,
|
||||||
|
INSERTED.street,
|
||||||
|
INSERTED.streetnumber AS streetNumber,
|
||||||
|
INSERTED.zip,
|
||||||
|
INSERTED.city,
|
||||||
|
INSERTED.county,
|
||||||
|
INSERTED.addresstype AS addressType
|
||||||
|
VALUES (
|
||||||
|
@entityId,
|
||||||
|
@firstName,
|
||||||
|
@name,
|
||||||
|
@street,
|
||||||
|
@streetNumber,
|
||||||
|
@zip,
|
||||||
|
@city,
|
||||||
|
@county,
|
||||||
|
@addressType
|
||||||
|
)
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const UPDATE = `
|
||||||
|
UPDATE entityaddress
|
||||||
|
SET
|
||||||
|
first_name = @firstName,
|
||||||
|
name = @name,
|
||||||
|
street = @street,
|
||||||
|
streetnumber = @streetNumber,
|
||||||
|
zip = @zip,
|
||||||
|
city = @city,
|
||||||
|
county = @county,
|
||||||
|
addresstype = @addressType
|
||||||
|
OUTPUT
|
||||||
|
INSERTED.id,
|
||||||
|
INSERTED.entity_id AS entityId,
|
||||||
|
INSERTED.first_name AS firstName,
|
||||||
|
INSERTED.name,
|
||||||
|
INSERTED.street,
|
||||||
|
INSERTED.streetnumber AS streetNumber,
|
||||||
|
INSERTED.zip,
|
||||||
|
INSERTED.city,
|
||||||
|
INSERTED.county,
|
||||||
|
INSERTED.addresstype AS addressType
|
||||||
|
WHERE id = @id AND entity_id = @entityId
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const DELETE_BY_ENTITY_AND_ID = `
|
||||||
|
DELETE FROM entityaddress
|
||||||
|
WHERE id = @id AND entity_id = @entityId
|
||||||
|
`;
|
||||||
47
src/sql/entitycontact.js
Normal file
47
src/sql/entitycontact.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
export const CONTACT_COLUMNS = `
|
||||||
|
id,
|
||||||
|
entity_id AS entityId,
|
||||||
|
contacttype AS contactType,
|
||||||
|
contact
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const LIST_BY_ENTITY = `
|
||||||
|
SELECT
|
||||||
|
${CONTACT_COLUMNS}
|
||||||
|
FROM entitycontact
|
||||||
|
WHERE entity_id = @entityId
|
||||||
|
ORDER BY id
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const GET_BY_ENTITY_AND_ID = `
|
||||||
|
SELECT
|
||||||
|
${CONTACT_COLUMNS}
|
||||||
|
FROM entitycontact
|
||||||
|
WHERE id = @id AND entity_id = @entityId
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const CREATE = `
|
||||||
|
INSERT INTO entitycontact (entity_id, contacttype, contact)
|
||||||
|
OUTPUT
|
||||||
|
INSERTED.id,
|
||||||
|
INSERTED.entity_id AS entityId,
|
||||||
|
INSERTED.contacttype AS contactType,
|
||||||
|
INSERTED.contact
|
||||||
|
VALUES (@entityId, @contactType, @contact)
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const UPDATE = `
|
||||||
|
UPDATE entitycontact
|
||||||
|
SET contacttype = @contactType, contact = @contact
|
||||||
|
OUTPUT
|
||||||
|
INSERTED.id,
|
||||||
|
INSERTED.entity_id AS entityId,
|
||||||
|
INSERTED.contacttype AS contactType,
|
||||||
|
INSERTED.contact
|
||||||
|
WHERE id = @id AND entity_id = @entityId
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const DELETE_BY_ENTITY_AND_ID = `
|
||||||
|
DELETE FROM entitycontact
|
||||||
|
WHERE id = @id AND entity_id = @entityId
|
||||||
|
`;
|
||||||
@@ -20,6 +20,8 @@ export const TABLES = [
|
|||||||
'articleean',
|
'articleean',
|
||||||
'articlehistory',
|
'articlehistory',
|
||||||
'entityhistory',
|
'entityhistory',
|
||||||
|
'entityaddress',
|
||||||
|
'entitycontact',
|
||||||
'article',
|
'article',
|
||||||
'brand',
|
'brand',
|
||||||
'articlelist',
|
'articlelist',
|
||||||
|
|||||||
24
src/store/customergroup/create.js
Normal file
24
src/store/customergroup/create.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import { CREATE } from '../../sql/customergroup.js';
|
||||||
|
import resolveCompanyAccess from '../companyuser/resolveCompanyAccess.js';
|
||||||
|
|
||||||
|
export default function create(pool) {
|
||||||
|
const access = resolveCompanyAccess(pool);
|
||||||
|
|
||||||
|
return async (googleAuthId, companyId, { name } = {}) => {
|
||||||
|
const cleaned = name?.trim();
|
||||||
|
if (!cleaned) {
|
||||||
|
throw new Error('Name required');
|
||||||
|
}
|
||||||
|
|
||||||
|
await access(googleAuthId, companyId);
|
||||||
|
|
||||||
|
const result = await pool
|
||||||
|
.request()
|
||||||
|
.input('companyId', companyId)
|
||||||
|
.input('name', cleaned)
|
||||||
|
.query(CREATE);
|
||||||
|
|
||||||
|
const row = result.recordset[0];
|
||||||
|
return { id: row.id, name: row.name };
|
||||||
|
};
|
||||||
|
}
|
||||||
31
src/store/customergroup/delete.js
Normal file
31
src/store/customergroup/delete.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { DELETE_BY_COMPANY_AND_ID } from '../../sql/customergroup.js';
|
||||||
|
import resolveCompanyAccess from '../companyuser/resolveCompanyAccess.js';
|
||||||
|
|
||||||
|
export default function del(pool) {
|
||||||
|
const access = resolveCompanyAccess(pool);
|
||||||
|
|
||||||
|
return async (googleAuthId, companyId, id) => {
|
||||||
|
if (!Number.isFinite(id)) {
|
||||||
|
throw new Error('Customer group not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
await access(googleAuthId, companyId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await pool
|
||||||
|
.request()
|
||||||
|
.input('id', id)
|
||||||
|
.input('companyId', companyId)
|
||||||
|
.query(DELETE_BY_COMPANY_AND_ID);
|
||||||
|
|
||||||
|
if (!result.rowsAffected[0]) {
|
||||||
|
throw new Error('Customer group not found');
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
if (err.number === 547) {
|
||||||
|
throw new Error('Customer group in use');
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
20
src/store/customergroup/list.js
Normal file
20
src/store/customergroup/list.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { LIST_BY_COMPANY } from '../../sql/customergroup.js';
|
||||||
|
import resolveCompanyAccess from '../companyuser/resolveCompanyAccess.js';
|
||||||
|
|
||||||
|
export default function list(pool) {
|
||||||
|
const access = resolveCompanyAccess(pool);
|
||||||
|
|
||||||
|
return async (googleAuthId, companyId) => {
|
||||||
|
await access(googleAuthId, companyId);
|
||||||
|
|
||||||
|
const result = await pool
|
||||||
|
.request()
|
||||||
|
.input('companyId', companyId)
|
||||||
|
.query(LIST_BY_COMPANY);
|
||||||
|
|
||||||
|
return result.recordset.map((row) => ({
|
||||||
|
id: row.id,
|
||||||
|
name: row.name,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
}
|
||||||
22
src/store/customergroup/resolveCustomerGroupAccess.js
Normal file
22
src/store/customergroup/resolveCustomerGroupAccess.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { GET_BY_COMPANY_AND_ID } from '../../sql/customergroup.js';
|
||||||
|
import request from '../request.js';
|
||||||
|
|
||||||
|
/** Ensure customergroup belongs to company. Throws Customer group not found. */
|
||||||
|
export default function resolveCustomerGroupAccess(pool) {
|
||||||
|
return async (companyId, customergroupId, tx) => {
|
||||||
|
if (!Number.isFinite(customergroupId)) {
|
||||||
|
throw new Error('Customer group not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await request(pool, tx)
|
||||||
|
.input('id', customergroupId)
|
||||||
|
.input('companyId', companyId)
|
||||||
|
.query(GET_BY_COMPANY_AND_ID);
|
||||||
|
|
||||||
|
const row = result.recordset[0];
|
||||||
|
if (!row) {
|
||||||
|
throw new Error('Customer group not found');
|
||||||
|
}
|
||||||
|
return row;
|
||||||
|
};
|
||||||
|
}
|
||||||
32
src/store/customergroup/update.js
Normal file
32
src/store/customergroup/update.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { UPDATE_NAME } from '../../sql/customergroup.js';
|
||||||
|
import resolveCompanyAccess from '../companyuser/resolveCompanyAccess.js';
|
||||||
|
|
||||||
|
export default function update(pool) {
|
||||||
|
const access = resolveCompanyAccess(pool);
|
||||||
|
|
||||||
|
return async (googleAuthId, companyId, id, { name } = {}) => {
|
||||||
|
if (!Number.isFinite(id)) {
|
||||||
|
throw new Error('Customer group not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const cleaned = name?.trim();
|
||||||
|
if (!cleaned) {
|
||||||
|
throw new Error('Name required');
|
||||||
|
}
|
||||||
|
|
||||||
|
await access(googleAuthId, companyId);
|
||||||
|
|
||||||
|
const result = await pool
|
||||||
|
.request()
|
||||||
|
.input('id', id)
|
||||||
|
.input('companyId', companyId)
|
||||||
|
.input('name', cleaned)
|
||||||
|
.query(UPDATE_NAME);
|
||||||
|
|
||||||
|
const row = result.recordset[0];
|
||||||
|
if (!row) {
|
||||||
|
throw new Error('Customer group not found');
|
||||||
|
}
|
||||||
|
return { id: row.id, name: row.name };
|
||||||
|
};
|
||||||
|
}
|
||||||
69
src/store/entity/create.js
Normal file
69
src/store/entity/create.js
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import { CREATE } from '../../sql/entity.js';
|
||||||
|
import { INSERT as INSERT_HISTORY } from '../../sql/entityhistory.js';
|
||||||
|
import request from '../request.js';
|
||||||
|
import resolveCompanyAccess from '../companyuser/resolveCompanyAccess.js';
|
||||||
|
import resolveCustomerGroupAccess from '../customergroup/resolveCustomerGroupAccess.js';
|
||||||
|
|
||||||
|
function shape(row) {
|
||||||
|
return {
|
||||||
|
id: row.id,
|
||||||
|
customergroupId: row.customergroupId,
|
||||||
|
firstName: row.firstName ?? null,
|
||||||
|
name: row.name,
|
||||||
|
createdAt: row.createdAt,
|
||||||
|
updatedAt: row.updatedAt,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function create(pool) {
|
||||||
|
const access = resolveCompanyAccess(pool);
|
||||||
|
const groupAccess = resolveCustomerGroupAccess(pool);
|
||||||
|
|
||||||
|
return async (
|
||||||
|
googleAuthId,
|
||||||
|
companyId,
|
||||||
|
{ customergroupId, name, firstName = null } = {},
|
||||||
|
) => {
|
||||||
|
const cleaned = name?.trim();
|
||||||
|
if (!cleaned) {
|
||||||
|
throw new Error('Name required');
|
||||||
|
}
|
||||||
|
|
||||||
|
const first =
|
||||||
|
firstName == null || firstName === ''
|
||||||
|
? null
|
||||||
|
: String(firstName).trim() || null;
|
||||||
|
|
||||||
|
const { companyuserId } = await access(googleAuthId, companyId);
|
||||||
|
await groupAccess(companyId, customergroupId);
|
||||||
|
|
||||||
|
const tx = pool.transaction();
|
||||||
|
await tx.begin();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const created = await request(pool, tx)
|
||||||
|
.input('customergroupId', customergroupId)
|
||||||
|
.input('firstName', first)
|
||||||
|
.input('name', cleaned)
|
||||||
|
.query(CREATE);
|
||||||
|
|
||||||
|
const row = created.recordset[0];
|
||||||
|
|
||||||
|
await request(pool, tx)
|
||||||
|
.input('entityId', row.id)
|
||||||
|
.input('companyuserId', companyuserId)
|
||||||
|
.input('text', 'Erstellt')
|
||||||
|
.query(INSERT_HISTORY);
|
||||||
|
|
||||||
|
await tx.commit();
|
||||||
|
return shape(row);
|
||||||
|
} catch (err) {
|
||||||
|
try {
|
||||||
|
await tx.rollback();
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
24
src/store/entity/delete.js
Normal file
24
src/store/entity/delete.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import { DELETE_BY_COMPANY_AND_ID } from '../../sql/entity.js';
|
||||||
|
import resolveCompanyAccess from '../companyuser/resolveCompanyAccess.js';
|
||||||
|
|
||||||
|
export default function del(pool) {
|
||||||
|
const access = resolveCompanyAccess(pool);
|
||||||
|
|
||||||
|
return async (googleAuthId, companyId, id) => {
|
||||||
|
if (!Number.isFinite(id)) {
|
||||||
|
throw new Error('Entity not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
await access(googleAuthId, companyId);
|
||||||
|
|
||||||
|
const result = await pool
|
||||||
|
.request()
|
||||||
|
.input('id', id)
|
||||||
|
.input('companyId', companyId)
|
||||||
|
.query(DELETE_BY_COMPANY_AND_ID);
|
||||||
|
|
||||||
|
if (!result.rowsAffected[0]) {
|
||||||
|
throw new Error('Entity not found');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
37
src/store/entity/getById.js
Normal file
37
src/store/entity/getById.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { GET_BY_COMPANY_AND_ID } from '../../sql/entity.js';
|
||||||
|
import resolveCompanyAccess from '../companyuser/resolveCompanyAccess.js';
|
||||||
|
|
||||||
|
function shape(row) {
|
||||||
|
return {
|
||||||
|
id: row.id,
|
||||||
|
customergroupId: row.customergroupId,
|
||||||
|
firstName: row.firstName ?? null,
|
||||||
|
name: row.name,
|
||||||
|
createdAt: row.createdAt,
|
||||||
|
updatedAt: row.updatedAt,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function getById(pool) {
|
||||||
|
const access = resolveCompanyAccess(pool);
|
||||||
|
|
||||||
|
return async (googleAuthId, companyId, id) => {
|
||||||
|
if (!Number.isFinite(id)) {
|
||||||
|
throw new Error('Entity not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
await access(googleAuthId, companyId);
|
||||||
|
|
||||||
|
const result = await pool
|
||||||
|
.request()
|
||||||
|
.input('id', id)
|
||||||
|
.input('companyId', companyId)
|
||||||
|
.query(GET_BY_COMPANY_AND_ID);
|
||||||
|
|
||||||
|
const row = result.recordset[0];
|
||||||
|
if (!row) {
|
||||||
|
throw new Error('Entity not found');
|
||||||
|
}
|
||||||
|
return shape(row);
|
||||||
|
};
|
||||||
|
}
|
||||||
43
src/store/entity/list.js
Normal file
43
src/store/entity/list.js
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import {
|
||||||
|
LIST_BY_COMPANY,
|
||||||
|
LIST_BY_COMPANY_AND_GROUP,
|
||||||
|
} from '../../sql/entity.js';
|
||||||
|
import resolveCompanyAccess from '../companyuser/resolveCompanyAccess.js';
|
||||||
|
import resolveCustomerGroupAccess from '../customergroup/resolveCustomerGroupAccess.js';
|
||||||
|
|
||||||
|
function shape(row) {
|
||||||
|
return {
|
||||||
|
id: row.id,
|
||||||
|
customergroupId: row.customergroupId,
|
||||||
|
firstName: row.firstName ?? null,
|
||||||
|
name: row.name,
|
||||||
|
createdAt: row.createdAt,
|
||||||
|
updatedAt: row.updatedAt,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function list(pool) {
|
||||||
|
const access = resolveCompanyAccess(pool);
|
||||||
|
const groupAccess = resolveCustomerGroupAccess(pool);
|
||||||
|
|
||||||
|
return async (googleAuthId, companyId, { customergroupId } = {}) => {
|
||||||
|
await access(googleAuthId, companyId);
|
||||||
|
|
||||||
|
if (customergroupId != null) {
|
||||||
|
await groupAccess(companyId, customergroupId);
|
||||||
|
const result = await pool
|
||||||
|
.request()
|
||||||
|
.input('companyId', companyId)
|
||||||
|
.input('customergroupId', customergroupId)
|
||||||
|
.query(LIST_BY_COMPANY_AND_GROUP);
|
||||||
|
return result.recordset.map(shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await pool
|
||||||
|
.request()
|
||||||
|
.input('companyId', companyId)
|
||||||
|
.query(LIST_BY_COMPANY);
|
||||||
|
|
||||||
|
return result.recordset.map(shape);
|
||||||
|
};
|
||||||
|
}
|
||||||
22
src/store/entity/resolveEntityAccess.js
Normal file
22
src/store/entity/resolveEntityAccess.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { GET_BY_COMPANY_AND_ID } from '../../sql/entity.js';
|
||||||
|
import request from '../request.js';
|
||||||
|
|
||||||
|
/** Ensure entity belongs to company. Throws Entity not found. */
|
||||||
|
export default function resolveEntityAccess(pool) {
|
||||||
|
return async (companyId, entityId, tx) => {
|
||||||
|
if (!Number.isFinite(entityId)) {
|
||||||
|
throw new Error('Entity not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await request(pool, tx)
|
||||||
|
.input('id', entityId)
|
||||||
|
.input('companyId', companyId)
|
||||||
|
.query(GET_BY_COMPANY_AND_ID);
|
||||||
|
|
||||||
|
const row = result.recordset[0];
|
||||||
|
if (!row) {
|
||||||
|
throw new Error('Entity not found');
|
||||||
|
}
|
||||||
|
return row;
|
||||||
|
};
|
||||||
|
}
|
||||||
110
src/store/entity/update.js
Normal file
110
src/store/entity/update.js
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
import { GET_BY_COMPANY_AND_ID, UPDATE } from '../../sql/entity.js';
|
||||||
|
import { INSERT as INSERT_HISTORY } from '../../sql/entityhistory.js';
|
||||||
|
import request from '../request.js';
|
||||||
|
import resolveCompanyAccess from '../companyuser/resolveCompanyAccess.js';
|
||||||
|
|
||||||
|
function shape(row) {
|
||||||
|
return {
|
||||||
|
id: row.id,
|
||||||
|
customergroupId: row.customergroupId,
|
||||||
|
firstName: row.firstName ?? null,
|
||||||
|
name: row.name,
|
||||||
|
createdAt: row.createdAt,
|
||||||
|
updatedAt: row.updatedAt,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function update(pool) {
|
||||||
|
const access = resolveCompanyAccess(pool);
|
||||||
|
|
||||||
|
return async (googleAuthId, companyId, id, patch = {}) => {
|
||||||
|
if (!Number.isFinite(id)) {
|
||||||
|
throw new Error('Entity not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasName = Object.prototype.hasOwnProperty.call(patch, 'name');
|
||||||
|
const hasFirstName = Object.prototype.hasOwnProperty.call(patch, 'firstName');
|
||||||
|
if (!hasName && !hasFirstName) {
|
||||||
|
throw new Error('Name required');
|
||||||
|
}
|
||||||
|
|
||||||
|
const { companyuserId } = await access(googleAuthId, companyId);
|
||||||
|
|
||||||
|
const existing = await pool
|
||||||
|
.request()
|
||||||
|
.input('id', id)
|
||||||
|
.input('companyId', companyId)
|
||||||
|
.query(GET_BY_COMPANY_AND_ID);
|
||||||
|
|
||||||
|
const current = existing.recordset[0];
|
||||||
|
if (!current) {
|
||||||
|
throw new Error('Entity not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = current.name;
|
||||||
|
if (hasName) {
|
||||||
|
name = patch.name?.trim();
|
||||||
|
if (!name) {
|
||||||
|
throw new Error('Name required');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let firstName = current.firstName ?? null;
|
||||||
|
if (hasFirstName) {
|
||||||
|
firstName =
|
||||||
|
patch.firstName == null || patch.firstName === ''
|
||||||
|
? null
|
||||||
|
: String(patch.firstName).trim() || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const historyLines = [];
|
||||||
|
const oldFirst = current.firstName ?? '';
|
||||||
|
const newFirst = firstName ?? '';
|
||||||
|
if (oldFirst !== newFirst) {
|
||||||
|
historyLines.push(
|
||||||
|
`Vorname geändert von "${oldFirst}" auf "${newFirst}"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (current.name !== name) {
|
||||||
|
historyLines.push(
|
||||||
|
`Name geändert von "${current.name}" auf "${name}"`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!historyLines.length) {
|
||||||
|
return shape(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
const tx = pool.transaction();
|
||||||
|
await tx.begin();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const updated = await request(pool, tx)
|
||||||
|
.input('id', id)
|
||||||
|
.input('firstName', firstName)
|
||||||
|
.input('name', name)
|
||||||
|
.query(UPDATE);
|
||||||
|
|
||||||
|
const row = updated.recordset[0];
|
||||||
|
if (!row) {
|
||||||
|
throw new Error('Entity not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
await request(pool, tx)
|
||||||
|
.input('entityId', id)
|
||||||
|
.input('companyuserId', companyuserId)
|
||||||
|
.input('text', historyLines.join('\n'))
|
||||||
|
.query(INSERT_HISTORY);
|
||||||
|
|
||||||
|
await tx.commit();
|
||||||
|
return shape(row);
|
||||||
|
} catch (err) {
|
||||||
|
try {
|
||||||
|
await tx.rollback();
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
56
src/store/entityaddress/create.js
Normal file
56
src/store/entityaddress/create.js
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import { CREATE } from '../../sql/entityaddress.js';
|
||||||
|
import resolveCompanyAccess from '../companyuser/resolveCompanyAccess.js';
|
||||||
|
import resolveEntityAccess from '../entity/resolveEntityAccess.js';
|
||||||
|
|
||||||
|
function shape(row) {
|
||||||
|
return {
|
||||||
|
id: row.id,
|
||||||
|
entityId: row.entityId,
|
||||||
|
firstName: row.firstName ?? null,
|
||||||
|
name: row.name ?? null,
|
||||||
|
street: row.street ?? null,
|
||||||
|
streetNumber: row.streetNumber ?? null,
|
||||||
|
zip: row.zip ?? null,
|
||||||
|
city: row.city ?? null,
|
||||||
|
county: row.county ?? null,
|
||||||
|
addressType: row.addressType,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function optionalString(value) {
|
||||||
|
if (value == null || value === '') return null;
|
||||||
|
const s = String(value).trim();
|
||||||
|
return s || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function create(pool) {
|
||||||
|
const access = resolveCompanyAccess(pool);
|
||||||
|
const entityAccess = resolveEntityAccess(pool);
|
||||||
|
|
||||||
|
return async (googleAuthId, companyId, entityId, input = {}) => {
|
||||||
|
const addressType = input.addressType?.trim?.()
|
||||||
|
? input.addressType.trim()
|
||||||
|
: null;
|
||||||
|
if (!addressType) {
|
||||||
|
throw new Error('Address type required');
|
||||||
|
}
|
||||||
|
|
||||||
|
await access(googleAuthId, companyId);
|
||||||
|
await entityAccess(companyId, entityId);
|
||||||
|
|
||||||
|
const result = await pool
|
||||||
|
.request()
|
||||||
|
.input('entityId', entityId)
|
||||||
|
.input('firstName', optionalString(input.firstName))
|
||||||
|
.input('name', optionalString(input.name))
|
||||||
|
.input('street', optionalString(input.street))
|
||||||
|
.input('streetNumber', optionalString(input.streetNumber))
|
||||||
|
.input('zip', optionalString(input.zip))
|
||||||
|
.input('city', optionalString(input.city))
|
||||||
|
.input('county', optionalString(input.county))
|
||||||
|
.input('addressType', addressType)
|
||||||
|
.query(CREATE);
|
||||||
|
|
||||||
|
return shape(result.recordset[0]);
|
||||||
|
};
|
||||||
|
}
|
||||||
27
src/store/entityaddress/delete.js
Normal file
27
src/store/entityaddress/delete.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { DELETE_BY_ENTITY_AND_ID } from '../../sql/entityaddress.js';
|
||||||
|
import resolveCompanyAccess from '../companyuser/resolveCompanyAccess.js';
|
||||||
|
import resolveEntityAccess from '../entity/resolveEntityAccess.js';
|
||||||
|
|
||||||
|
export default function del(pool) {
|
||||||
|
const access = resolveCompanyAccess(pool);
|
||||||
|
const entityAccess = resolveEntityAccess(pool);
|
||||||
|
|
||||||
|
return async (googleAuthId, companyId, entityId, id) => {
|
||||||
|
if (!Number.isFinite(id)) {
|
||||||
|
throw new Error('Address not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
await access(googleAuthId, companyId);
|
||||||
|
await entityAccess(companyId, entityId);
|
||||||
|
|
||||||
|
const result = await pool
|
||||||
|
.request()
|
||||||
|
.input('id', id)
|
||||||
|
.input('entityId', entityId)
|
||||||
|
.query(DELETE_BY_ENTITY_AND_ID);
|
||||||
|
|
||||||
|
if (!result.rowsAffected[0]) {
|
||||||
|
throw new Error('Address not found');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
35
src/store/entityaddress/list.js
Normal file
35
src/store/entityaddress/list.js
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import { LIST_BY_ENTITY } from '../../sql/entityaddress.js';
|
||||||
|
import resolveCompanyAccess from '../companyuser/resolveCompanyAccess.js';
|
||||||
|
import resolveEntityAccess from '../entity/resolveEntityAccess.js';
|
||||||
|
|
||||||
|
function shape(row) {
|
||||||
|
return {
|
||||||
|
id: row.id,
|
||||||
|
entityId: row.entityId,
|
||||||
|
firstName: row.firstName ?? null,
|
||||||
|
name: row.name ?? null,
|
||||||
|
street: row.street ?? null,
|
||||||
|
streetNumber: row.streetNumber ?? null,
|
||||||
|
zip: row.zip ?? null,
|
||||||
|
city: row.city ?? null,
|
||||||
|
county: row.county ?? null,
|
||||||
|
addressType: row.addressType,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function list(pool) {
|
||||||
|
const access = resolveCompanyAccess(pool);
|
||||||
|
const entityAccess = resolveEntityAccess(pool);
|
||||||
|
|
||||||
|
return async (googleAuthId, companyId, entityId) => {
|
||||||
|
await access(googleAuthId, companyId);
|
||||||
|
await entityAccess(companyId, entityId);
|
||||||
|
|
||||||
|
const result = await pool
|
||||||
|
.request()
|
||||||
|
.input('entityId', entityId)
|
||||||
|
.query(LIST_BY_ENTITY);
|
||||||
|
|
||||||
|
return result.recordset.map(shape);
|
||||||
|
};
|
||||||
|
}
|
||||||
104
src/store/entityaddress/update.js
Normal file
104
src/store/entityaddress/update.js
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
import { GET_BY_ENTITY_AND_ID, UPDATE } from '../../sql/entityaddress.js';
|
||||||
|
import resolveCompanyAccess from '../companyuser/resolveCompanyAccess.js';
|
||||||
|
import resolveEntityAccess from '../entity/resolveEntityAccess.js';
|
||||||
|
|
||||||
|
function shape(row) {
|
||||||
|
return {
|
||||||
|
id: row.id,
|
||||||
|
entityId: row.entityId,
|
||||||
|
firstName: row.firstName ?? null,
|
||||||
|
name: row.name ?? null,
|
||||||
|
street: row.street ?? null,
|
||||||
|
streetNumber: row.streetNumber ?? null,
|
||||||
|
zip: row.zip ?? null,
|
||||||
|
city: row.city ?? null,
|
||||||
|
county: row.county ?? null,
|
||||||
|
addressType: row.addressType,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function optionalString(value) {
|
||||||
|
if (value == null || value === '') return null;
|
||||||
|
const s = String(value).trim();
|
||||||
|
return s || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function update(pool) {
|
||||||
|
const access = resolveCompanyAccess(pool);
|
||||||
|
const entityAccess = resolveEntityAccess(pool);
|
||||||
|
|
||||||
|
return async (googleAuthId, companyId, entityId, id, patch = {}) => {
|
||||||
|
if (!Number.isFinite(id)) {
|
||||||
|
throw new Error('Address not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
await access(googleAuthId, companyId);
|
||||||
|
await entityAccess(companyId, entityId);
|
||||||
|
|
||||||
|
const existing = await pool
|
||||||
|
.request()
|
||||||
|
.input('id', id)
|
||||||
|
.input('entityId', entityId)
|
||||||
|
.query(GET_BY_ENTITY_AND_ID);
|
||||||
|
|
||||||
|
const current = existing.recordset[0];
|
||||||
|
if (!current) {
|
||||||
|
throw new Error('Address not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstName = Object.prototype.hasOwnProperty.call(patch, 'firstName')
|
||||||
|
? optionalString(patch.firstName)
|
||||||
|
: current.firstName ?? null;
|
||||||
|
const name = Object.prototype.hasOwnProperty.call(patch, 'name')
|
||||||
|
? optionalString(patch.name)
|
||||||
|
: current.name ?? null;
|
||||||
|
const street = Object.prototype.hasOwnProperty.call(patch, 'street')
|
||||||
|
? optionalString(patch.street)
|
||||||
|
: current.street ?? null;
|
||||||
|
const streetNumber = Object.prototype.hasOwnProperty.call(
|
||||||
|
patch,
|
||||||
|
'streetNumber',
|
||||||
|
)
|
||||||
|
? optionalString(patch.streetNumber)
|
||||||
|
: current.streetNumber ?? null;
|
||||||
|
const zip = Object.prototype.hasOwnProperty.call(patch, 'zip')
|
||||||
|
? optionalString(patch.zip)
|
||||||
|
: current.zip ?? null;
|
||||||
|
const city = Object.prototype.hasOwnProperty.call(patch, 'city')
|
||||||
|
? optionalString(patch.city)
|
||||||
|
: current.city ?? null;
|
||||||
|
const county = Object.prototype.hasOwnProperty.call(patch, 'county')
|
||||||
|
? optionalString(patch.county)
|
||||||
|
: current.county ?? null;
|
||||||
|
|
||||||
|
let addressType = current.addressType;
|
||||||
|
if (Object.prototype.hasOwnProperty.call(patch, 'addressType')) {
|
||||||
|
addressType = patch.addressType?.trim?.()
|
||||||
|
? patch.addressType.trim()
|
||||||
|
: null;
|
||||||
|
if (!addressType) {
|
||||||
|
throw new Error('Address type required');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await pool
|
||||||
|
.request()
|
||||||
|
.input('id', id)
|
||||||
|
.input('entityId', entityId)
|
||||||
|
.input('firstName', firstName)
|
||||||
|
.input('name', name)
|
||||||
|
.input('street', street)
|
||||||
|
.input('streetNumber', streetNumber)
|
||||||
|
.input('zip', zip)
|
||||||
|
.input('city', city)
|
||||||
|
.input('county', county)
|
||||||
|
.input('addressType', addressType)
|
||||||
|
.query(UPDATE);
|
||||||
|
|
||||||
|
const row = result.recordset[0];
|
||||||
|
if (!row) {
|
||||||
|
throw new Error('Address not found');
|
||||||
|
}
|
||||||
|
return shape(row);
|
||||||
|
};
|
||||||
|
}
|
||||||
39
src/store/entitycontact/create.js
Normal file
39
src/store/entitycontact/create.js
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import { CREATE } from '../../sql/entitycontact.js';
|
||||||
|
import resolveCompanyAccess from '../companyuser/resolveCompanyAccess.js';
|
||||||
|
import resolveEntityAccess from '../entity/resolveEntityAccess.js';
|
||||||
|
|
||||||
|
function shape(row) {
|
||||||
|
return {
|
||||||
|
id: row.id,
|
||||||
|
entityId: row.entityId,
|
||||||
|
contactType: row.contactType,
|
||||||
|
contact: row.contact,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function create(pool) {
|
||||||
|
const access = resolveCompanyAccess(pool);
|
||||||
|
const entityAccess = resolveEntityAccess(pool);
|
||||||
|
|
||||||
|
return async (googleAuthId, companyId, entityId, input = {}) => {
|
||||||
|
const contactType = input.contactType?.trim?.()
|
||||||
|
? input.contactType.trim()
|
||||||
|
: null;
|
||||||
|
const contact = input.contact?.trim?.() ? input.contact.trim() : null;
|
||||||
|
if (!contactType || !contact) {
|
||||||
|
throw new Error('Contact required');
|
||||||
|
}
|
||||||
|
|
||||||
|
await access(googleAuthId, companyId);
|
||||||
|
await entityAccess(companyId, entityId);
|
||||||
|
|
||||||
|
const result = await pool
|
||||||
|
.request()
|
||||||
|
.input('entityId', entityId)
|
||||||
|
.input('contactType', contactType)
|
||||||
|
.input('contact', contact)
|
||||||
|
.query(CREATE);
|
||||||
|
|
||||||
|
return shape(result.recordset[0]);
|
||||||
|
};
|
||||||
|
}
|
||||||
27
src/store/entitycontact/delete.js
Normal file
27
src/store/entitycontact/delete.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { DELETE_BY_ENTITY_AND_ID } from '../../sql/entitycontact.js';
|
||||||
|
import resolveCompanyAccess from '../companyuser/resolveCompanyAccess.js';
|
||||||
|
import resolveEntityAccess from '../entity/resolveEntityAccess.js';
|
||||||
|
|
||||||
|
export default function del(pool) {
|
||||||
|
const access = resolveCompanyAccess(pool);
|
||||||
|
const entityAccess = resolveEntityAccess(pool);
|
||||||
|
|
||||||
|
return async (googleAuthId, companyId, entityId, id) => {
|
||||||
|
if (!Number.isFinite(id)) {
|
||||||
|
throw new Error('Contact not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
await access(googleAuthId, companyId);
|
||||||
|
await entityAccess(companyId, entityId);
|
||||||
|
|
||||||
|
const result = await pool
|
||||||
|
.request()
|
||||||
|
.input('id', id)
|
||||||
|
.input('entityId', entityId)
|
||||||
|
.query(DELETE_BY_ENTITY_AND_ID);
|
||||||
|
|
||||||
|
if (!result.rowsAffected[0]) {
|
||||||
|
throw new Error('Contact not found');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
29
src/store/entitycontact/list.js
Normal file
29
src/store/entitycontact/list.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { LIST_BY_ENTITY } from '../../sql/entitycontact.js';
|
||||||
|
import resolveCompanyAccess from '../companyuser/resolveCompanyAccess.js';
|
||||||
|
import resolveEntityAccess from '../entity/resolveEntityAccess.js';
|
||||||
|
|
||||||
|
function shape(row) {
|
||||||
|
return {
|
||||||
|
id: row.id,
|
||||||
|
entityId: row.entityId,
|
||||||
|
contactType: row.contactType,
|
||||||
|
contact: row.contact,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function list(pool) {
|
||||||
|
const access = resolveCompanyAccess(pool);
|
||||||
|
const entityAccess = resolveEntityAccess(pool);
|
||||||
|
|
||||||
|
return async (googleAuthId, companyId, entityId) => {
|
||||||
|
await access(googleAuthId, companyId);
|
||||||
|
await entityAccess(companyId, entityId);
|
||||||
|
|
||||||
|
const result = await pool
|
||||||
|
.request()
|
||||||
|
.input('entityId', entityId)
|
||||||
|
.query(LIST_BY_ENTITY);
|
||||||
|
|
||||||
|
return result.recordset.map(shape);
|
||||||
|
};
|
||||||
|
}
|
||||||
67
src/store/entitycontact/update.js
Normal file
67
src/store/entitycontact/update.js
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import { GET_BY_ENTITY_AND_ID, UPDATE } from '../../sql/entitycontact.js';
|
||||||
|
import resolveCompanyAccess from '../companyuser/resolveCompanyAccess.js';
|
||||||
|
import resolveEntityAccess from '../entity/resolveEntityAccess.js';
|
||||||
|
|
||||||
|
function shape(row) {
|
||||||
|
return {
|
||||||
|
id: row.id,
|
||||||
|
entityId: row.entityId,
|
||||||
|
contactType: row.contactType,
|
||||||
|
contact: row.contact,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function update(pool) {
|
||||||
|
const access = resolveCompanyAccess(pool);
|
||||||
|
const entityAccess = resolveEntityAccess(pool);
|
||||||
|
|
||||||
|
return async (googleAuthId, companyId, entityId, id, patch = {}) => {
|
||||||
|
if (!Number.isFinite(id)) {
|
||||||
|
throw new Error('Contact not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
await access(googleAuthId, companyId);
|
||||||
|
await entityAccess(companyId, entityId);
|
||||||
|
|
||||||
|
const existing = await pool
|
||||||
|
.request()
|
||||||
|
.input('id', id)
|
||||||
|
.input('entityId', entityId)
|
||||||
|
.query(GET_BY_ENTITY_AND_ID);
|
||||||
|
|
||||||
|
const current = existing.recordset[0];
|
||||||
|
if (!current) {
|
||||||
|
throw new Error('Contact not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
let contactType = current.contactType;
|
||||||
|
if (Object.prototype.hasOwnProperty.call(patch, 'contactType')) {
|
||||||
|
contactType = patch.contactType?.trim?.()
|
||||||
|
? patch.contactType.trim()
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let contact = current.contact;
|
||||||
|
if (Object.prototype.hasOwnProperty.call(patch, 'contact')) {
|
||||||
|
contact = patch.contact?.trim?.() ? patch.contact.trim() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!contactType || !contact) {
|
||||||
|
throw new Error('Contact required');
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await pool
|
||||||
|
.request()
|
||||||
|
.input('id', id)
|
||||||
|
.input('entityId', entityId)
|
||||||
|
.input('contactType', contactType)
|
||||||
|
.input('contact', contact)
|
||||||
|
.query(UPDATE);
|
||||||
|
|
||||||
|
const row = result.recordset[0];
|
||||||
|
if (!row) {
|
||||||
|
throw new Error('Contact not found');
|
||||||
|
}
|
||||||
|
return shape(row);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -23,6 +23,7 @@ export default function create(pool) {
|
|||||||
|
|
||||||
const created = await request(pool, tx)
|
const created = await request(pool, tx)
|
||||||
.input('customergroupId', customergroupId)
|
.input('customergroupId', customergroupId)
|
||||||
|
.input('firstName', null)
|
||||||
.input('name', cleaned)
|
.input('name', cleaned)
|
||||||
.query(CREATE);
|
.query(CREATE);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user