Add README, customization snapshot, and snapshot/restore tooling

Provisioning now restores all GUI customizations on reset+reprovision:

- create_pod_espocrm.sh: deploy the version-controlled espocrm-custom/ tree
  (CTag entity, layouts, i18n, clientDefs, custom views, custom CSS) into the
  pod, then chown www-data and rebuild. Replaces the earlier inline CSS-only
  step. Adds a live-phase cache rebuild so customizations and the client
  cacheTimestamp are refreshed on every run.
- espocrm-custom/: snapshot of custom/ and client/custom/ (source of truth).
- snapshot_espocrm_custom.sh: refresh the snapshot from a running pod.
- readme.md: usage, first-time host setup, image-update and reset workflows.
- Include the task/instruction notes and plan.md for reference.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
mkt
2026-06-06 16:51:02 +02:00
parent 79ea236da0
commit cebe829dcd
79 changed files with 2064 additions and 45 deletions

View File

@@ -0,0 +1,14 @@
/**
* Variable column widths for Markdown tables in text fields.
*
* EspoCRM core CSS forces `table-layout: fixed; width: 100%` on
* `.complex-text table`, which makes all columns equally wide.
* `auto` lets columns size to content instead.
*
* Registered via custom/Espo/Custom/Resources/metadata/app/client.json (cssList).
*/
.complex-text table {
table-layout: auto !important;
width: auto !important;
max-width: 100% !important;
}

View File

@@ -0,0 +1 @@
dummy

View File

@@ -0,0 +1,24 @@
define('custom:views/preferences/fields/signature',
['views/preferences/fields/signature'], (SignatureFieldView) => {
return class extends SignatureFieldView {
setupToolbar() {
// Build the reduced signature toolbar first …
super.setupToolbar();
// … then re-add the image button next to the link button.
this.toolbar = (this.toolbar || []).map(group => {
if (Array.isArray(group) && group[0] === 'table') {
const buttons = group[1] || [];
if (!buttons.includes('espoImage')) {
return ['table', [...buttons, 'espoImage']];
}
}
return group;
});
}
};
});

View File

@@ -0,0 +1,28 @@
define('custom:views/record/row-actions/tags-unlink-only',
['views/record/row-actions/relationship'], (RelationshipRowActionsView) => {
return class extends RelationshipRowActionsView {
getActionList() {
const list = [];
// Keep only the "Unlink" action (German UI: "Link entfernen").
// View / Edit / Remove are intentionally omitted.
if (!this.options.unlinkDisabled) {
list.push({
action: 'unlinkRelated',
label: 'Unlink',
data: {
id: this.model.id,
},
groupIndex: 0,
});
}
// Preserve any explicitly configured extra row actions (none by default).
this.getAdditionalActionList().forEach(item => list.push(item));
return list;
}
};
});

View File

@@ -0,0 +1,2 @@
Order Deny,Allow
Deny from all

View File

@@ -0,0 +1,7 @@
<?php
namespace Espo\Custom\Controllers;
class CTag extends \Espo\Core\Templates\Controllers\Base
{
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "إنشاء {الكيانTypeTranslated}"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Създаване на Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Vytvořit Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Opret Tag "
}
}

View File

@@ -0,0 +1,10 @@
{
"fields": {
"cAgentur": "Agentur",
"cTags": "Tags"
},
"links": {
"cAgentur": "Agentur",
"cTags": "Tags"
}
}

View File

@@ -0,0 +1,15 @@
{
"labels": {
"Create CTag": "Tag erstellen"
},
"fields": {
"verkaufschancen": "Verkaufschancen",
"kontakte": "Kontakte",
"firmen": "Firmen"
},
"links": {
"verkaufschancen": "Verkaufschancen",
"kontakte": "Kontakte",
"firmen": "Firmen"
}
}

View File

@@ -0,0 +1,8 @@
{
"fields": {
"cTags": "Tags"
},
"links": {
"cTags": "Tags"
}
}

View File

@@ -0,0 +1,60 @@
{
"options": {
"stage": {
"Interessant": "Interessant",
"Abgelehnt": "Abgelehnt",
"Angefragt": "Angefragt",
"Agentur prüft": "Agentur prüft",
"Kunde prüft": "Kunde prüft",
"Identifiziert": "Identifiziert",
"Brief versendet": "Brief versendet",
"Anruf-Wiedervorlage": "Anruf-Wiedervorlage",
"Angerufen": "Angerufen",
"Ersttermin vereinbart": "Ersttermin vereinbart",
"Ersttermin durchgeführt": "Ersttermin durchgeführt",
"Angebot": "Angebot",
"Verhandlung": "Verhandlung",
"Unterschriftsreif": "Unterschriftsreif",
"Gewonnen": "Gewonnen",
"In Durchführung": "In Durchführung",
"Abgeschl. / Bestandsk.": "Abgeschl. / Bestandsk.",
"Verloren": "Verloren",
"Ghosted": "Ghosted"
},
"cLeadQuelle": {
"Inbound Agentur": "Inbound Agentur",
"Inbound Plattform-Lead": "Inbound Plattform-Lead",
"Aktive Plattform-Suche": "Aktive Plattform-Suche",
"Aktive Akquise": "Aktive Akquise",
"Empfehlung / Netzwerk": "Empfehlung / Netzwerk",
"Sonstiges": "Sonstiges"
},
"cVerlustgrund": {
"Agentur Absage": "Agentur Absage",
"Kunde Absage": "Kunde Absage",
"Keine Einigung": "Keine Einigung",
"Eigene Absage": "Eigene Absage",
"Sonstiges": "Sonstiges",
"Agentur Ghosted": "Agentur Ghosted",
"Kunde Ghosted": "Kunde Ghosted"
},
"cVerguetungsmodell": {
"Agentur Honorar": "Agentur Honorar",
"Direkt Festpreis": "Direkt Festpreis",
"Direkt Honorar": "Direkt Honorar",
"Direkt Nutzenbasiert": "Direkt Nutzenbasiert"
}
},
"fields": {
"cLeadQuelle": "Lead-Quelle",
"cVerlustgrund": "Verlustgrund",
"cProjektlink": "Projektlink",
"cVerguetungsmodell": "Vergütungsmodell",
"cAccount1": "Über Agentur",
"cTags": "Tags"
},
"links": {
"cAccount1": "Über Agentur",
"cTags": "Tags"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Δημιουργία Tag"
}
}

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1,10 @@
{
"fields": {
"cAgentur": "Agentur",
"cTags": "Tags"
},
"links": {
"cAgentur": "Agentur",
"cTags": "Tags"
}
}

View File

@@ -0,0 +1,15 @@
{
"labels": {
"Create CTag": "Create Tag"
},
"fields": {
"verkaufschancen": "Verkaufschancen",
"kontakte": "Kontakte",
"firmen": "Firmen"
},
"links": {
"verkaufschancen": "Verkaufschancen",
"kontakte": "Kontakte",
"firmen": "Firmen"
}
}

View File

@@ -0,0 +1,8 @@
{
"fields": {
"cTags": "Tags"
},
"links": {
"cTags": "Tags"
}
}

View File

@@ -0,0 +1,8 @@
{
"scopeNames": {
"CTag": "Tag"
},
"scopeNamesPlural": {
"CTag": "Tags"
}
}

View File

@@ -0,0 +1,39 @@
{
"fields": {
"cLeadQuelle": "Lead-Quelle",
"cVerlustgrund": "Verlustgrund",
"cProjektlink": "Projektlink",
"cVerguetungsmodell": "Vergütungsmodell",
"cAccount1": "Über Agentur",
"cTags": "Tags"
},
"options": {
"cLeadQuelle": {
"Inbound Agentur": "Inbound Agentur",
"Inbound Plattform-Lead": "Inbound Plattform-Lead",
"Aktive Plattform-Suche": "Aktive Plattform-Suche",
"Aktive Akquise": "Aktive Akquise",
"Empfehlung / Netzwerk": "Empfehlung / Netzwerk",
"Sonstiges": "Sonstiges"
},
"cVerlustgrund": {
"Agentur Absage": "Agentur Absage",
"Kunde Absage": "Kunde Absage",
"Keine Einigung": "Keine Einigung",
"Eigene Absage": "Eigene Absage",
"Sonstiges": "Sonstiges",
"Agentur Ghosted": "Agentur Ghosted",
"Kunde Ghosted": "Kunde Ghosted"
},
"cVerguetungsmodell": {
"Agentur Honorar": "Agentur Honorar",
"Direkt Festpreis": "Direkt Festpreis",
"Direkt Honorar": "Direkt Honorar",
"Direkt Nutzenbasiert": "Direkt Nutzenbasiert"
}
},
"links": {
"cAccount1": "Über Agentur",
"cTags": "Tags"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Crear Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Crear Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "ایجاد Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Créer un Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Napravi Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "{EntityTypeTranslated} létrehozása"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Buat Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Crea Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Tag を作成する"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Sukurti Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Izveidot Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Opprett Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Creëer Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Utwórz Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Criar Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Criar Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Creare Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Создать Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Vytvoriť Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Ustvari Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Napravi Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Skapa Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "สร้าง Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Tag oluştur"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Створити Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "{entityTypetranslated} بنائیں"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "Tạo Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "创建 Tag"
}
}

View File

@@ -0,0 +1,5 @@
{
"labels": {
"Create CTag": "建立Tag"
}
}

View File

@@ -0,0 +1,45 @@
{
"activities": {
"disabled": true
},
"history": {
"disabled": true
},
"_delimiter_": {
"disabled": true
},
"_tabBreak_0": {
"index": 0,
"tabBreak": true,
"tabLabel": "$Stream"
},
"stream": {
"sticked": false,
"index": 1
},
"_tabBreak_1": {
"index": 2,
"tabBreak": true,
"tabLabel": "$Account"
},
"contacts": {
"index": 3
},
"opportunities": {
"index": 4
},
"documents": {
"index": 5
},
"_tabBreak_2": {
"index": 6,
"tabBreak": true,
"tabLabel": "$Support"
},
"cases": {
"index": 7
},
"cTags": {
"index": 8
}
}

View File

@@ -0,0 +1,14 @@
{
"_delimiter_": {
"disabled": true
},
"firmen": {
"index": 0
},
"kontakte": {
"index": 1
},
"verkaufschancen": {
"index": 2
}
}

View File

@@ -0,0 +1,27 @@
{
"activities": {
"disabled": true
},
"history": {
"disabled": true
},
"_delimiter_": {
"disabled": true
},
"stream": {
"sticked": false,
"index": 0
},
"opportunities": {
"index": 1
},
"cases": {
"index": 2
},
"targetLists": {
"index": 3
},
"cTags": {
"index": 4
}
}

View File

@@ -0,0 +1,21 @@
{
"activities": {
"disabled": true
},
"history": {
"disabled": true
},
"_delimiter_": {
"disabled": true
},
"stream": {
"sticked": false,
"index": 0
},
"documents": {
"index": 1
},
"cTags": {
"index": 2
}
}

View File

@@ -0,0 +1,89 @@
[
{
"rows": [
[
{
"name": "name"
}
],
[
{
"name": "stage"
},
{
"name": "cLeadQuelle"
}
],
[
{
"name": "cVerguetungsmodell"
},
{
"name": "amount"
}
],
[
{
"name": "closeDate"
},
{
"name": "cVerlustgrund"
}
]
],
"dynamicLogicVisible": null,
"style": "default",
"dynamicLogicStyled": null,
"tabBreak": false,
"hidden": false,
"noteText": null,
"customLabel": "Vorgang"
},
{
"rows": [
[
{
"name": "account"
},
{
"name": "cAccount1"
}
],
[
{
"name": "contacts"
},
false
]
],
"dynamicLogicVisible": null,
"style": "default",
"tabBreak": false,
"hidden": false,
"noteText": null,
"noteStyle": "info",
"customLabel": "Beteiligte"
},
{
"rows": [
[
{
"name": "description"
}
],
[
{
"name": "cProjektlink"
}
]
],
"dynamicLogicVisible": null,
"style": "default",
"tabBreak": false,
"tabLabel": null,
"hidden": false,
"noteText": null,
"noteStyle": "info",
"customLabel": "Projekt"
}
]

View File

@@ -0,0 +1,17 @@
[
{
"name": "name",
"link": true
},
{
"name": "account"
},
{
"name": "amount",
"align": "right",
"isLarge": true
},
{
"name": "cLeadQuelle"
}
]

View File

@@ -0,0 +1,40 @@
[
{
"name": "name",
"link": true
},
{
"name": "cAccount1",
"width": 13
},
{
"name": "account",
"width": 13
},
{
"name": "stage",
"width": 12
},
{
"name": "cLeadQuelle",
"width": 11
},
{
"name": "amount",
"width": 9,
"align": "right"
},
{
"name": "cVerguetungsmodell",
"width": 13
},
{
"name": "closeDate",
"width": 9,
"hidden": true
},
{
"name": "assignedUser",
"width": 9
}
]

View File

@@ -0,0 +1,6 @@
{
"cssList": [
"__APPEND__",
"client/custom/css/table-var-col.css"
]
}

View File

@@ -0,0 +1,20 @@
{
"relationshipPanels": {
"agentur": {
"layout": null,
"selectPrimaryFilterName": null
},
"cAgentur": {
"layout": null,
"selectPrimaryFilterName": null
},
"tags": {
"layout": null,
"selectPrimaryFilterName": null
},
"cTags": {
"create": false,
"rowActionsView": "custom:views/record/row-actions/tags-unlink-only"
}
}
}

View File

@@ -0,0 +1,20 @@
{
"controller": "controllers/record",
"boolFilterList": [
"onlyMy"
],
"relationshipPanels": {
"verkaufschancen": {
"layout": null,
"selectPrimaryFilterName": null
},
"kontakte": {
"layout": null,
"selectPrimaryFilterName": null
},
"firmen": {
"layout": null,
"selectPrimaryFilterName": null
}
}
}

View File

@@ -0,0 +1,12 @@
{
"relationshipPanels": {
"tags": {
"layout": null,
"selectPrimaryFilterName": null
},
"cTags": {
"create": false,
"rowActionsView": "custom:views/record/row-actions/tags-unlink-only"
}
}
}

View File

@@ -0,0 +1,24 @@
{
"relationshipPanels": {
"account1": {
"layout": null,
"selectPrimaryFilterName": null
},
"cAccount1": {
"layout": null,
"selectPrimaryFilterName": null
},
"verkaufschancen": {
"layout": null,
"selectPrimaryFilterName": null
},
"tags": {
"layout": null,
"selectPrimaryFilterName": null
},
"cTags": {
"create": false,
"rowActionsView": "custom:views/record/row-actions/tags-unlink-only"
}
}
}

View File

@@ -0,0 +1,19 @@
{
"links": {
"cAgentur": {
"type": "hasMany",
"foreign": "cAccount1",
"entity": "Opportunity",
"audited": false,
"isCustom": true
},
"cTags": {
"type": "hasMany",
"relationName": "cAccountTag",
"foreign": "firmen",
"entity": "CTag",
"audited": false,
"isCustom": true
}
}
}

View File

@@ -0,0 +1,113 @@
{
"fields": {
"name": {
"type": "varchar",
"required": true,
"pattern": "$noBadCharacters"
},
"description": {
"type": "text"
},
"createdAt": {
"type": "datetime",
"readOnly": true
},
"modifiedAt": {
"type": "datetime",
"readOnly": true
},
"createdBy": {
"type": "link",
"readOnly": true,
"view": "views/fields/user"
},
"modifiedBy": {
"type": "link",
"readOnly": true,
"view": "views/fields/user"
},
"assignedUser": {
"type": "link",
"required": false,
"view": "views/fields/assigned-user"
},
"teams": {
"type": "linkMultiple",
"view": "views/fields/teams"
}
},
"links": {
"createdBy": {
"type": "belongsTo",
"entity": "User"
},
"modifiedBy": {
"type": "belongsTo",
"entity": "User"
},
"assignedUser": {
"type": "belongsTo",
"entity": "User"
},
"teams": {
"type": "hasMany",
"entity": "Team",
"relationName": "entityTeam",
"layoutRelationshipsDisabled": true
},
"verkaufschancen": {
"type": "hasMany",
"relationName": "cOpportunityTag",
"foreign": "cTags",
"entity": "Opportunity",
"audited": false,
"isCustom": true
},
"kontakte": {
"type": "hasMany",
"relationName": "cContactTag",
"foreign": "cTags",
"entity": "Contact",
"audited": false,
"isCustom": true
},
"firmen": {
"type": "hasMany",
"relationName": "cAccountTag",
"foreign": "cTags",
"entity": "Account",
"audited": false,
"isCustom": true
}
},
"collection": {
"orderBy": "createdAt",
"order": "desc"
},
"indexes": {
"name": {
"columns": [
"name",
"deleted"
]
},
"assignedUser": {
"columns": [
"assignedUserId",
"deleted"
]
},
"createdAt": {
"columns": [
"createdAt"
]
},
"createdAtId": {
"unique": true,
"columns": [
"createdAt",
"id"
]
}
}
}

View File

@@ -0,0 +1,12 @@
{
"links": {
"cTags": {
"type": "hasMany",
"relationName": "cContactTag",
"foreign": "kontakte",
"entity": "CTag",
"audited": false,
"isCustom": true
}
}
}

View File

@@ -0,0 +1,167 @@
{
"fields": {
"stage": {
"options": [
"Interessant",
"Abgelehnt",
"Angefragt",
"Agentur prüft",
"Kunde prüft",
"Identifiziert",
"Brief versendet",
"Anruf-Wiedervorlage",
"Angerufen",
"Ersttermin vereinbart",
"Ersttermin durchgeführt",
"Angebot",
"Verhandlung",
"Unterschriftsreif",
"Gewonnen",
"In Durchführung",
"Abgeschl. / Bestandsk.",
"Verloren",
"Ghosted"
],
"default": "Interessant",
"probabilityMap": {
"Interessant": 5,
"Abgelehnt": 0,
"Angefragt": 15,
"Agentur prüft": 20,
"Kunde prüft": 30,
"Identifiziert": 5,
"Brief versendet": 8,
"Anruf-Wiedervorlage": 10,
"Angerufen": 12,
"Ersttermin vereinbart": 20,
"Ersttermin durchgeführt": 30,
"Angebot": 40,
"Verhandlung": 60,
"Unterschriftsreif": 80,
"Gewonnen": 100,
"In Durchführung": 100,
"Abgeschl. / Bestandsk.": 100,
"Verloren": 0,
"Ghosted": 0
},
"style": {
"Interessant": null,
"Abgelehnt": "info",
"Angefragt": null,
"Agentur prüft": null,
"Kunde prüft": null,
"Identifiziert": null,
"Brief versendet": "warning",
"Anruf-Wiedervorlage": "warning",
"Angerufen": "warning",
"Ersttermin vereinbart": "warning",
"Ersttermin durchgeführt": "warning",
"Angebot": null,
"Verhandlung": null,
"Unterschriftsreif": null,
"Gewonnen": "success",
"In Durchführung": "primary",
"Abgeschl. / Bestandsk.": "info",
"Verloren": "danger",
"Ghosted": "info"
}
},
"cLeadQuelle": {
"type": "enum",
"required": true,
"options": [
"Inbound Agentur",
"Inbound Plattform-Lead",
"Aktive Plattform-Suche",
"Aktive Akquise",
"Empfehlung / Netzwerk",
"Sonstiges"
],
"style": {
"Inbound Agentur": null,
"Inbound Plattform-Lead": null,
"Aktive Plattform-Suche": null,
"Aktive Akquise": null,
"Empfehlung / Netzwerk": null,
"Sonstiges": null
},
"default": "Inbound Agentur",
"maxLength": 100,
"isCustom": true,
"displayAsLabel": true
},
"cVerlustgrund": {
"type": "enum",
"options": [
"Agentur Absage",
"Kunde Absage",
"Keine Einigung",
"Eigene Absage",
"Sonstiges",
"Agentur Ghosted",
"Kunde Ghosted"
],
"style": {
"Agentur Absage": null,
"Kunde Absage": null,
"Keine Einigung": null,
"Eigene Absage": null,
"Sonstiges": null,
"Agentur Ghosted": null,
"Kunde Ghosted": null
},
"default": "Kunde Absage",
"maxLength": 100,
"isCustom": true
},
"cProjektlink": {
"type": "url",
"isCustom": true
},
"cVerguetungsmodell": {
"type": "enum",
"options": [
"Agentur Honorar",
"Direkt Festpreis",
"Direkt Honorar",
"Direkt Nutzenbasiert"
],
"style": {
"Agentur Honorar": null,
"Direkt Festpreis": null,
"Direkt Honorar": null,
"Direkt Nutzenbasiert": null
},
"default": "Agentur Honorar",
"displayAsLabel": true,
"maxLength": 100,
"isCustom": true
},
"cAccount1": {
"type": "link"
},
"amount": {
"required": false
},
"closeDate": {
"required": false
}
},
"links": {
"cAccount1": {
"type": "belongsTo",
"foreign": "cAgentur",
"entity": "Account",
"audited": false,
"isCustom": true
},
"cTags": {
"type": "hasMany",
"relationName": "cOpportunityTag",
"foreign": "verkaufschancen",
"entity": "CTag",
"audited": false,
"isCustom": true
}
}
}

View File

@@ -0,0 +1,7 @@
{
"fields": {
"signature": {
"view": "custom:views/preferences/fields/signature"
}
}
}

View File

@@ -0,0 +1,47 @@
{
"fields": {
"cVerlustgrund": {
"visible": {
"conditionGroup": [
{
"type": "in",
"attribute": "stage",
"value": [
"Abgelehnt",
"Verloren",
"Ghosted"
]
}
]
},
"required": {
"conditionGroup": [
{
"type": "in",
"attribute": "stage",
"value": [
"Abgelehnt",
"Verloren",
"Ghosted"
]
}
]
}
},
"amount": {
"required": {
"conditionGroup": [
{
"type": "in",
"attribute": "stage",
"value": [
"Gewonnen",
"In Durchführung",
"Abgeschl. / Bestandsk."
]
}
]
}
}
}
}

View File

@@ -0,0 +1,3 @@
{
"duplicateWhereBuilderClassName": "Espo\\Classes\\DuplicateWhereBuilders\\General"
}

View File

@@ -0,0 +1,23 @@
{
"entity": true,
"layouts": true,
"tab": true,
"acl": true,
"aclPortal": true,
"aclPortalLevelList": [
"all",
"account",
"contact",
"own",
"no"
],
"customizable": true,
"importable": true,
"notifications": true,
"stream": false,
"disabled": false,
"type": "Base",
"module": "Custom",
"object": true,
"isCustom": true
}

View File

@@ -0,0 +1,2 @@
Order Deny,Allow
Deny from all