@objectql/create 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +28 -0
- package/dist/bin.js +125 -0
- package/package.json +27 -0
- package/templates/enterprise/CHANGELOG.md +140 -0
- package/templates/enterprise/README.md +352 -0
- package/templates/enterprise/__tests__/data-api.test.ts +546 -0
- package/templates/enterprise/__tests__/data-api.test.ts.backup +526 -0
- package/templates/enterprise/__tests__/metadata-api.test.ts +307 -0
- package/templates/enterprise/__tests__/metadata-loading.test.ts +250 -0
- package/templates/enterprise/jest.config.js +22 -0
- package/templates/enterprise/package.json +51 -0
- package/templates/enterprise/src/apps/erp.app.yml +4 -0
- package/templates/enterprise/src/core/attachment.object.yml +57 -0
- package/templates/enterprise/src/core/i18n/en/core.json +60 -0
- package/templates/enterprise/src/core/i18n/zh-CN/core.json +60 -0
- package/templates/enterprise/src/core/index.ts +24 -0
- package/templates/enterprise/src/core/organization.object.yml +78 -0
- package/templates/enterprise/src/core/user.object.yml +80 -0
- package/templates/enterprise/src/extensions/README.md +56 -0
- package/templates/enterprise/src/extensions/user.extension.object.yml +42 -0
- package/templates/enterprise/src/extensions/user.ts +26 -0
- package/templates/enterprise/src/index.ts +47 -0
- package/templates/enterprise/src/modules/crm/README.md +99 -0
- package/templates/enterprise/src/modules/crm/crm_account.object.yml +105 -0
- package/templates/enterprise/src/modules/crm/crm_contact.object.yml +103 -0
- package/templates/enterprise/src/modules/crm/crm_lead.object.yml +148 -0
- package/templates/enterprise/src/modules/crm/crm_opportunity.object.yml +128 -0
- package/templates/enterprise/src/modules/crm/i18n/en/crm.json +61 -0
- package/templates/enterprise/src/modules/crm/i18n/zh-CN/crm.json +61 -0
- package/templates/enterprise/src/modules/crm/index.ts +29 -0
- package/templates/enterprise/src/modules/finance/README.md +112 -0
- package/templates/enterprise/src/modules/finance/finance_budget.object.yml +108 -0
- package/templates/enterprise/src/modules/finance/finance_expense.object.yml +151 -0
- package/templates/enterprise/src/modules/finance/finance_invoice.object.yml +143 -0
- package/templates/enterprise/src/modules/finance/finance_payment.object.yml +96 -0
- package/templates/enterprise/src/modules/finance/index.ts +26 -0
- package/templates/enterprise/src/modules/hr/README.md +95 -0
- package/templates/enterprise/src/modules/hr/hr_department.object.yml +59 -0
- package/templates/enterprise/src/modules/hr/hr_employee.object.yml +137 -0
- package/templates/enterprise/src/modules/hr/hr_position.object.yml +79 -0
- package/templates/enterprise/src/modules/hr/hr_timesheet.object.yml +114 -0
- package/templates/enterprise/src/modules/hr/index.ts +26 -0
- package/templates/enterprise/src/modules/project/README.md +132 -0
- package/templates/enterprise/src/modules/project/index.ts +26 -0
- package/templates/enterprise/src/modules/project/project_milestone.object.yml +70 -0
- package/templates/enterprise/src/modules/project/project_project.object.yml +135 -0
- package/templates/enterprise/src/modules/project/project_task.object.yml +121 -0
- package/templates/enterprise/src/modules/project/project_timesheet_entry.object.yml +95 -0
- package/templates/enterprise/src/plugins/audit/audit.plugin.ts +23 -0
- package/templates/enterprise/src/plugins/audit/index.ts +6 -0
- package/templates/enterprise/src/plugins/audit/note.object.yml +3 -0
- package/templates/enterprise/src/shared/constants.ts +30 -0
- package/templates/enterprise/src/shared/utils.ts +54 -0
- package/templates/enterprise/src/shared/validators.ts +47 -0
- package/templates/enterprise/src/types/attachment.ts +41 -0
- package/templates/enterprise/src/types/crm_account.ts +61 -0
- package/templates/enterprise/src/types/crm_contact.ts +61 -0
- package/templates/enterprise/src/types/crm_lead.ts +77 -0
- package/templates/enterprise/src/types/crm_opportunity.ts +53 -0
- package/templates/enterprise/src/types/finance_budget.ts +61 -0
- package/templates/enterprise/src/types/finance_expense.ts +65 -0
- package/templates/enterprise/src/types/finance_invoice.ts +69 -0
- package/templates/enterprise/src/types/finance_payment.ts +49 -0
- package/templates/enterprise/src/types/hr_department.ts +37 -0
- package/templates/enterprise/src/types/hr_employee.ts +85 -0
- package/templates/enterprise/src/types/hr_position.ts +49 -0
- package/templates/enterprise/src/types/hr_timesheet.ts +57 -0
- package/templates/enterprise/src/types/index.ts +20 -0
- package/templates/enterprise/src/types/note.ts +9 -0
- package/templates/enterprise/src/types/organization.ts +53 -0
- package/templates/enterprise/src/types/project_milestone.ts +41 -0
- package/templates/enterprise/src/types/project_project.ts +69 -0
- package/templates/enterprise/src/types/project_task.ts +57 -0
- package/templates/enterprise/src/types/project_timesheet_entry.ts +45 -0
- package/templates/enterprise/src/types/user.ts +65 -0
- package/templates/enterprise/tsconfig.json +10 -0
- package/templates/enterprise/tsconfig.tsbuildinfo +1 -0
- package/templates/hello-world/CHANGELOG.md +33 -0
- package/templates/hello-world/README.md +29 -0
- package/templates/hello-world/package.json +24 -0
- package/templates/hello-world/src/index.ts +58 -0
- package/templates/hello-world/tsconfig.json +10 -0
- package/templates/starter/CHANGELOG.md +191 -0
- package/templates/starter/README.md +17 -0
- package/templates/starter/__tests__/projects-hooks-actions.test.ts +490 -0
- package/templates/starter/jest.config.js +22 -0
- package/templates/starter/package.json +51 -0
- package/templates/starter/src/README.pages.md +110 -0
- package/templates/starter/src/demo.app.yml +4 -0
- package/templates/starter/src/i18n/zh-CN/projects.json +22 -0
- package/templates/starter/src/index.ts +55 -0
- package/templates/starter/src/modules/kitchen-sink/kitchen_sink.data.yml +18 -0
- package/templates/starter/src/modules/kitchen-sink/kitchen_sink.object.yml +156 -0
- package/templates/starter/src/modules/projects/project_approval.workflow.yml +51 -0
- package/templates/starter/src/modules/projects/projects.action.ts +472 -0
- package/templates/starter/src/modules/projects/projects.data.yml +13 -0
- package/templates/starter/src/modules/projects/projects.hook.ts +339 -0
- package/templates/starter/src/modules/projects/projects.object.yml +148 -0
- package/templates/starter/src/modules/projects/projects.permission.yml +141 -0
- package/templates/starter/src/modules/projects/projects.validation.yml +37 -0
- package/templates/starter/src/modules/tasks/tasks.data.yml +23 -0
- package/templates/starter/src/modules/tasks/tasks.object.yml +34 -0
- package/templates/starter/src/modules/tasks/tasks.permission.yml +167 -0
- package/templates/starter/src/types/index.ts +3 -0
- package/templates/starter/src/types/kitchen_sink.ts +101 -0
- package/templates/starter/src/types/projects.ts +49 -0
- package/templates/starter/src/types/tasks.ts +33 -0
- package/templates/starter/tsconfig.json +11 -0
- package/templates/starter/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"user": {
|
|
3
|
+
"label": "User",
|
|
4
|
+
"fields": {
|
|
5
|
+
"name": "Full Name",
|
|
6
|
+
"email": "Email Address",
|
|
7
|
+
"username": "Username",
|
|
8
|
+
"mobile": "Mobile Phone",
|
|
9
|
+
"avatar": "Profile Picture",
|
|
10
|
+
"status": "Status",
|
|
11
|
+
"role": "Role",
|
|
12
|
+
"last_login_at": "Last Login Time",
|
|
13
|
+
"locale": "Preferred Language",
|
|
14
|
+
"timezone": "Timezone"
|
|
15
|
+
},
|
|
16
|
+
"options": {
|
|
17
|
+
"status": {
|
|
18
|
+
"active": "Active",
|
|
19
|
+
"inactive": "Inactive",
|
|
20
|
+
"suspended": "Suspended"
|
|
21
|
+
},
|
|
22
|
+
"role": {
|
|
23
|
+
"admin": "Administrator",
|
|
24
|
+
"user": "User",
|
|
25
|
+
"guest": "Guest"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"organization": {
|
|
30
|
+
"label": "Organization",
|
|
31
|
+
"fields": {
|
|
32
|
+
"name": "Organization Name",
|
|
33
|
+
"code": "Organization Code",
|
|
34
|
+
"type": "Type",
|
|
35
|
+
"parent": "Parent Organization",
|
|
36
|
+
"manager": "Manager",
|
|
37
|
+
"description": "Description",
|
|
38
|
+
"logo": "Logo",
|
|
39
|
+
"address": "Address",
|
|
40
|
+
"website": "Website",
|
|
41
|
+
"phone": "Phone Number",
|
|
42
|
+
"email": "Contact Email",
|
|
43
|
+
"status": "Status"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"attachment": {
|
|
47
|
+
"label": "Attachment",
|
|
48
|
+
"fields": {
|
|
49
|
+
"name": "File Name",
|
|
50
|
+
"file_url": "File URL",
|
|
51
|
+
"file_size": "File Size",
|
|
52
|
+
"file_type": "MIME Type",
|
|
53
|
+
"related_to": "Related Object",
|
|
54
|
+
"related_id": "Related Record ID",
|
|
55
|
+
"uploaded_by": "Uploaded By",
|
|
56
|
+
"description": "Description",
|
|
57
|
+
"tags": "Tags"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"user": {
|
|
3
|
+
"label": "用户",
|
|
4
|
+
"fields": {
|
|
5
|
+
"name": "全名",
|
|
6
|
+
"email": "电子邮件地址",
|
|
7
|
+
"username": "用户名",
|
|
8
|
+
"mobile": "手机号码",
|
|
9
|
+
"avatar": "头像",
|
|
10
|
+
"status": "状态",
|
|
11
|
+
"role": "角色",
|
|
12
|
+
"last_login_at": "最后登录时间",
|
|
13
|
+
"locale": "首选语言",
|
|
14
|
+
"timezone": "时区"
|
|
15
|
+
},
|
|
16
|
+
"options": {
|
|
17
|
+
"status": {
|
|
18
|
+
"active": "活跃",
|
|
19
|
+
"inactive": "未活跃",
|
|
20
|
+
"suspended": "已暂停"
|
|
21
|
+
},
|
|
22
|
+
"role": {
|
|
23
|
+
"admin": "管理员",
|
|
24
|
+
"user": "用户",
|
|
25
|
+
"guest": "访客"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"organization": {
|
|
30
|
+
"label": "组织",
|
|
31
|
+
"fields": {
|
|
32
|
+
"name": "组织名称",
|
|
33
|
+
"code": "组织代码",
|
|
34
|
+
"type": "类型",
|
|
35
|
+
"parent": "上级组织",
|
|
36
|
+
"manager": "管理者",
|
|
37
|
+
"description": "描述",
|
|
38
|
+
"logo": "标志",
|
|
39
|
+
"address": "地址",
|
|
40
|
+
"website": "网站",
|
|
41
|
+
"phone": "电话号码",
|
|
42
|
+
"email": "联系邮箱",
|
|
43
|
+
"status": "状态"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"attachment": {
|
|
47
|
+
"label": "附件",
|
|
48
|
+
"fields": {
|
|
49
|
+
"name": "文件名",
|
|
50
|
+
"file_url": "文件URL",
|
|
51
|
+
"file_size": "文件大小",
|
|
52
|
+
"file_type": "MIME类型",
|
|
53
|
+
"related_to": "关联对象",
|
|
54
|
+
"related_id": "关联记录ID",
|
|
55
|
+
"uploaded_by": "上传者",
|
|
56
|
+
"description": "描述",
|
|
57
|
+
"tags": "标签"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core Module - Foundation Objects
|
|
3
|
+
*
|
|
4
|
+
* Exports all core/shared objects
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const CORE_OBJECTS = [
|
|
8
|
+
'user',
|
|
9
|
+
'organization',
|
|
10
|
+
'attachment',
|
|
11
|
+
] as const;
|
|
12
|
+
|
|
13
|
+
export type CoreObject = typeof CORE_OBJECTS[number];
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Module metadata
|
|
17
|
+
*/
|
|
18
|
+
export const CORE_MODULE = {
|
|
19
|
+
name: 'core',
|
|
20
|
+
label: 'Core Objects',
|
|
21
|
+
description: 'Foundation objects used across all modules',
|
|
22
|
+
version: '1.0.0',
|
|
23
|
+
objects: CORE_OBJECTS,
|
|
24
|
+
} as const;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
name: organization
|
|
2
|
+
label: Organization
|
|
3
|
+
description: Company or organization entity
|
|
4
|
+
icon: building-line
|
|
5
|
+
|
|
6
|
+
fields:
|
|
7
|
+
name:
|
|
8
|
+
type: text
|
|
9
|
+
required: true
|
|
10
|
+
label: Organization Name
|
|
11
|
+
index: true
|
|
12
|
+
|
|
13
|
+
code:
|
|
14
|
+
type: text
|
|
15
|
+
label: Organization Code
|
|
16
|
+
unique: true
|
|
17
|
+
index: true
|
|
18
|
+
|
|
19
|
+
type:
|
|
20
|
+
type: select
|
|
21
|
+
options:
|
|
22
|
+
- enterprise
|
|
23
|
+
- department
|
|
24
|
+
- team
|
|
25
|
+
defaultValue: enterprise
|
|
26
|
+
index: true
|
|
27
|
+
|
|
28
|
+
parent:
|
|
29
|
+
type: lookup
|
|
30
|
+
reference_to: organization
|
|
31
|
+
label: Parent Organization
|
|
32
|
+
index: true
|
|
33
|
+
|
|
34
|
+
manager:
|
|
35
|
+
type: lookup
|
|
36
|
+
reference_to: user
|
|
37
|
+
label: Manager
|
|
38
|
+
|
|
39
|
+
description:
|
|
40
|
+
type: textarea
|
|
41
|
+
label: Description
|
|
42
|
+
|
|
43
|
+
logo:
|
|
44
|
+
type: image
|
|
45
|
+
label: Organization Logo
|
|
46
|
+
|
|
47
|
+
address:
|
|
48
|
+
type: textarea
|
|
49
|
+
label: Address
|
|
50
|
+
|
|
51
|
+
website:
|
|
52
|
+
type: url
|
|
53
|
+
label: Website
|
|
54
|
+
|
|
55
|
+
phone:
|
|
56
|
+
type: text
|
|
57
|
+
label: Phone Number
|
|
58
|
+
|
|
59
|
+
email:
|
|
60
|
+
type: text
|
|
61
|
+
label: Contact Email
|
|
62
|
+
|
|
63
|
+
status:
|
|
64
|
+
type: select
|
|
65
|
+
options:
|
|
66
|
+
- active
|
|
67
|
+
- inactive
|
|
68
|
+
defaultValue: active
|
|
69
|
+
index: true
|
|
70
|
+
|
|
71
|
+
indexes:
|
|
72
|
+
# For org tree queries
|
|
73
|
+
parent_type_idx:
|
|
74
|
+
fields: [parent, type]
|
|
75
|
+
|
|
76
|
+
# For active org lookup
|
|
77
|
+
status_name_idx:
|
|
78
|
+
fields: [status, name]
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
name: user
|
|
2
|
+
label: User
|
|
3
|
+
description: System user with authentication and profile
|
|
4
|
+
icon: user-line
|
|
5
|
+
|
|
6
|
+
fields:
|
|
7
|
+
name:
|
|
8
|
+
type: text
|
|
9
|
+
required: true
|
|
10
|
+
label: Full Name
|
|
11
|
+
index: true
|
|
12
|
+
|
|
13
|
+
email:
|
|
14
|
+
type: text
|
|
15
|
+
required: true
|
|
16
|
+
label: Email Address
|
|
17
|
+
unique: true
|
|
18
|
+
index: true
|
|
19
|
+
|
|
20
|
+
username:
|
|
21
|
+
type: text
|
|
22
|
+
label: Username
|
|
23
|
+
unique: true
|
|
24
|
+
index: true
|
|
25
|
+
|
|
26
|
+
mobile:
|
|
27
|
+
type: text
|
|
28
|
+
label: Mobile Phone
|
|
29
|
+
|
|
30
|
+
avatar:
|
|
31
|
+
type: image
|
|
32
|
+
label: Profile Picture
|
|
33
|
+
multiple: false
|
|
34
|
+
max_size: 1048576 # 1MB
|
|
35
|
+
|
|
36
|
+
status:
|
|
37
|
+
type: select
|
|
38
|
+
options:
|
|
39
|
+
- active
|
|
40
|
+
- inactive
|
|
41
|
+
- suspended
|
|
42
|
+
defaultValue: active
|
|
43
|
+
index: true
|
|
44
|
+
|
|
45
|
+
role:
|
|
46
|
+
type: select
|
|
47
|
+
options:
|
|
48
|
+
- admin
|
|
49
|
+
- user
|
|
50
|
+
- guest
|
|
51
|
+
defaultValue: user
|
|
52
|
+
index: true
|
|
53
|
+
|
|
54
|
+
last_login_at:
|
|
55
|
+
type: datetime
|
|
56
|
+
label: Last Login Time
|
|
57
|
+
|
|
58
|
+
locale:
|
|
59
|
+
type: select
|
|
60
|
+
options:
|
|
61
|
+
- en
|
|
62
|
+
- zh-CN
|
|
63
|
+
- ja
|
|
64
|
+
- es
|
|
65
|
+
defaultValue: en
|
|
66
|
+
label: Preferred Language
|
|
67
|
+
|
|
68
|
+
timezone:
|
|
69
|
+
type: text
|
|
70
|
+
defaultValue: UTC
|
|
71
|
+
label: Timezone
|
|
72
|
+
|
|
73
|
+
indexes:
|
|
74
|
+
# For query: active users sorted by name
|
|
75
|
+
status_name_idx:
|
|
76
|
+
fields: [status, name]
|
|
77
|
+
|
|
78
|
+
# For authentication lookup
|
|
79
|
+
email_status_idx:
|
|
80
|
+
fields: [email, status]
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Extensions Directory
|
|
2
|
+
|
|
3
|
+
This directory contains object **extensions** - modifications and additions to objects defined elsewhere (either in the `core/` layer or external plugins).
|
|
4
|
+
|
|
5
|
+
## How Extensions Work
|
|
6
|
+
|
|
7
|
+
Extensions use ObjectQL's **Schema Merging** feature. When you define an object with the same `name` as an existing object, ObjectQL merges the definitions together.
|
|
8
|
+
|
|
9
|
+
## Example: Extending the User Object
|
|
10
|
+
|
|
11
|
+
The `user.extension.object.yml` file extends the core `user` object with company-specific customizations:
|
|
12
|
+
|
|
13
|
+
1. **Adding fields** - Links to employee record, office location
|
|
14
|
+
2. **Overriding properties** - Making email required and unique
|
|
15
|
+
3. **Business logic** - Two-factor authentication flag
|
|
16
|
+
|
|
17
|
+
## When to Use Extensions
|
|
18
|
+
|
|
19
|
+
✅ **Good Use Cases:**
|
|
20
|
+
- Adding company-specific fields to standard objects
|
|
21
|
+
- Customizing field properties (making fields required, adding validation)
|
|
22
|
+
- Regional variations (GDPR compliance fields for EU)
|
|
23
|
+
- Customer-specific customizations in SaaS products
|
|
24
|
+
|
|
25
|
+
❌ **Avoid Extensions For:**
|
|
26
|
+
- Core business logic (put in the original object definition)
|
|
27
|
+
- Frequently changing fields (causes merge complexity)
|
|
28
|
+
- Breaking changes (removing required fields)
|
|
29
|
+
|
|
30
|
+
## File Naming Convention
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
[object_name].extension.object.yml
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Examples:
|
|
37
|
+
- `user.extension.object.yml` - Extends the `user` object
|
|
38
|
+
- `organization.extension.object.yml` - Extends the `organization` object
|
|
39
|
+
|
|
40
|
+
## Loading Order
|
|
41
|
+
|
|
42
|
+
ObjectQL loads objects in this order:
|
|
43
|
+
1. External plugins
|
|
44
|
+
2. Core layer (`core/objects/`)
|
|
45
|
+
3. Module layers (`modules/*/objects/`)
|
|
46
|
+
4. Extensions (`extensions/`)
|
|
47
|
+
|
|
48
|
+
Later definitions override earlier ones for conflicting properties, and merge for nested structures like fields.
|
|
49
|
+
|
|
50
|
+
## Testing Extensions
|
|
51
|
+
|
|
52
|
+
Always test that your extensions:
|
|
53
|
+
1. Don't break existing functionality
|
|
54
|
+
2. Merge correctly with the base definition
|
|
55
|
+
3. Have appropriate indexes for new fields
|
|
56
|
+
4. Include i18n translations for new labels
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: user
|
|
2
|
+
# This extends the core user object with company-specific fields
|
|
3
|
+
label: System User (Extended)
|
|
4
|
+
|
|
5
|
+
fields:
|
|
6
|
+
# Add employee link
|
|
7
|
+
employee:
|
|
8
|
+
type: lookup
|
|
9
|
+
reference_to: hr_employee
|
|
10
|
+
label: Employee Record
|
|
11
|
+
unique: true
|
|
12
|
+
|
|
13
|
+
# Override email to make it required and unique
|
|
14
|
+
email:
|
|
15
|
+
required: true
|
|
16
|
+
unique: true
|
|
17
|
+
|
|
18
|
+
# Add custom fields
|
|
19
|
+
employee_id:
|
|
20
|
+
type: text
|
|
21
|
+
label: Employee ID
|
|
22
|
+
unique: true
|
|
23
|
+
index: true
|
|
24
|
+
|
|
25
|
+
department:
|
|
26
|
+
type: lookup
|
|
27
|
+
reference_to: hr_department
|
|
28
|
+
label: Department
|
|
29
|
+
|
|
30
|
+
office_location:
|
|
31
|
+
type: select
|
|
32
|
+
options:
|
|
33
|
+
- headquarters
|
|
34
|
+
- branch_office_a
|
|
35
|
+
- branch_office_b
|
|
36
|
+
- remote
|
|
37
|
+
label: Office Location
|
|
38
|
+
|
|
39
|
+
two_factor_enabled:
|
|
40
|
+
type: boolean
|
|
41
|
+
defaultValue: false
|
|
42
|
+
label: Two-Factor Auth Enabled
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Auto-generated by ObjectQL. DO NOT EDIT.
|
|
2
|
+
import { ObjectDoc } from '@objectql/types';
|
|
3
|
+
|
|
4
|
+
export interface User extends ObjectDoc {
|
|
5
|
+
/**
|
|
6
|
+
* Employee Record
|
|
7
|
+
*/
|
|
8
|
+
employee?: string | number;
|
|
9
|
+
email: any;
|
|
10
|
+
/**
|
|
11
|
+
* Employee ID
|
|
12
|
+
*/
|
|
13
|
+
employee_id?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Department
|
|
16
|
+
*/
|
|
17
|
+
department?: string | number;
|
|
18
|
+
/**
|
|
19
|
+
* Office Location
|
|
20
|
+
*/
|
|
21
|
+
office_location?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Two-Factor Auth Enabled
|
|
24
|
+
*/
|
|
25
|
+
two_factor_enabled?: boolean;
|
|
26
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ObjectQL } from '@objectql/core';
|
|
2
|
+
import { SqlDriver } from '@objectql/driver-sql';
|
|
3
|
+
import { ObjectLoader } from '@objectql/platform-node';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import { AuditLogPlugin } from './plugins/audit/audit.plugin';
|
|
6
|
+
|
|
7
|
+
async function main() {
|
|
8
|
+
console.log("🚀 Starting Enterprise ERP Showcase...");
|
|
9
|
+
|
|
10
|
+
const app = new ObjectQL({
|
|
11
|
+
datasources: {
|
|
12
|
+
default: new SqlDriver({
|
|
13
|
+
client: 'sqlite3',
|
|
14
|
+
connection: { filename: ':memory:' },
|
|
15
|
+
useNullAsDefault: true
|
|
16
|
+
})
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// Register Plugin
|
|
21
|
+
app.use(new AuditLogPlugin());
|
|
22
|
+
|
|
23
|
+
const loader = new ObjectLoader(app.metadata);
|
|
24
|
+
await loader.load(path.join(__dirname));
|
|
25
|
+
|
|
26
|
+
await app.init();
|
|
27
|
+
console.log("✅ Enterprise Engine Booted");
|
|
28
|
+
|
|
29
|
+
const ctx = app.createContext({ isSystem: true });
|
|
30
|
+
|
|
31
|
+
// Business Logic
|
|
32
|
+
console.log("Creating Employee...");
|
|
33
|
+
const emp = await ctx.object('employees').create({
|
|
34
|
+
first_name: 'John',
|
|
35
|
+
last_name: 'Doe',
|
|
36
|
+
email: 'john.doe@corp.com',
|
|
37
|
+
department: 'Engineering'
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
console.log(`Created Employee: ${emp.first_name} ${emp.last_name}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (require.main === module) {
|
|
44
|
+
main().catch(console.error);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export * from './types';
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# CRM Module
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
The Customer Relationship Management (CRM) module handles all customer-facing business processes including lead management, account management, contact management, and opportunity tracking.
|
|
5
|
+
|
|
6
|
+
## Objects
|
|
7
|
+
|
|
8
|
+
### crm_account
|
|
9
|
+
Company or organization customers. Stores company information, industry classification, and revenue data.
|
|
10
|
+
|
|
11
|
+
**Key Features:**
|
|
12
|
+
- Hierarchical account structure (parent-child accounts)
|
|
13
|
+
- Industry classification
|
|
14
|
+
- Revenue tracking
|
|
15
|
+
- AI-powered search on company name and description
|
|
16
|
+
|
|
17
|
+
### crm_contact
|
|
18
|
+
Individual contacts associated with accounts.
|
|
19
|
+
|
|
20
|
+
**Key Features:**
|
|
21
|
+
- Linked to accounts
|
|
22
|
+
- Lead source tracking
|
|
23
|
+
- Full name formula field
|
|
24
|
+
- AI-powered search
|
|
25
|
+
|
|
26
|
+
### crm_opportunity
|
|
27
|
+
Sales opportunities and deals.
|
|
28
|
+
|
|
29
|
+
**Key Features:**
|
|
30
|
+
- Stage-based pipeline management
|
|
31
|
+
- Probability and amount tracking
|
|
32
|
+
- Custom actions for won/lost marking
|
|
33
|
+
- Forecasting support via indexes
|
|
34
|
+
|
|
35
|
+
### crm_lead
|
|
36
|
+
Potential sales leads before conversion.
|
|
37
|
+
|
|
38
|
+
**Key Features:**
|
|
39
|
+
- Lead qualification workflow
|
|
40
|
+
- Rating system (hot/warm/cold)
|
|
41
|
+
- Convert action to create Account, Contact, and Opportunity
|
|
42
|
+
- Lead source attribution
|
|
43
|
+
|
|
44
|
+
## Relationships
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
Lead --converts to--> Account + Contact + Opportunity
|
|
48
|
+
Account <--has many-- Contact
|
|
49
|
+
Account <--has many-- Opportunity
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Team Ownership
|
|
53
|
+
**Owner:** Sales Team
|
|
54
|
+
**Primary Contact:** sales-team@example.com
|
|
55
|
+
|
|
56
|
+
## Dependencies
|
|
57
|
+
- **Core Objects:** `user` (for ownership tracking)
|
|
58
|
+
- **External:** None
|
|
59
|
+
|
|
60
|
+
## Custom Actions
|
|
61
|
+
- `Lead.convert` - Convert lead to account/contact/opportunity
|
|
62
|
+
- `Opportunity.mark_won` - Mark opportunity as won
|
|
63
|
+
- `Opportunity.mark_lost` - Mark opportunity as lost
|
|
64
|
+
|
|
65
|
+
## Indexes Strategy
|
|
66
|
+
- Composite indexes on `owner + status` for sales rep dashboards
|
|
67
|
+
- Date-based indexes for pipeline reporting
|
|
68
|
+
- Industry indexes for market analysis
|
|
69
|
+
|
|
70
|
+
## Usage Examples
|
|
71
|
+
|
|
72
|
+
### Find hot leads for a sales rep
|
|
73
|
+
```typescript
|
|
74
|
+
const leads = await app.find({
|
|
75
|
+
object: 'crm_lead',
|
|
76
|
+
filters: [
|
|
77
|
+
['owner', '=', userId],
|
|
78
|
+
'and',
|
|
79
|
+
['rating', '=', 'hot'],
|
|
80
|
+
'and',
|
|
81
|
+
['status', '!=', 'converted']
|
|
82
|
+
]
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Pipeline report for current quarter
|
|
87
|
+
```typescript
|
|
88
|
+
const opportunities = await app.find({
|
|
89
|
+
object: 'crm_opportunity',
|
|
90
|
+
filters: [
|
|
91
|
+
['close_date', '>=', quarterStart],
|
|
92
|
+
'and',
|
|
93
|
+
['close_date', '<=', quarterEnd],
|
|
94
|
+
'and',
|
|
95
|
+
['stage', 'not in', ['closed_won', 'closed_lost']]
|
|
96
|
+
],
|
|
97
|
+
sort: [['amount', 'desc']]
|
|
98
|
+
});
|
|
99
|
+
```
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
label: Account
|
|
2
|
+
description: Customer company or organization
|
|
3
|
+
icon: briefcase-line
|
|
4
|
+
|
|
5
|
+
fields:
|
|
6
|
+
name:
|
|
7
|
+
type: text
|
|
8
|
+
required: true
|
|
9
|
+
label: Account Name
|
|
10
|
+
index: true
|
|
11
|
+
|
|
12
|
+
account_number:
|
|
13
|
+
type: text
|
|
14
|
+
label: Account Number
|
|
15
|
+
unique: true
|
|
16
|
+
index: true
|
|
17
|
+
|
|
18
|
+
type:
|
|
19
|
+
type: select
|
|
20
|
+
options:
|
|
21
|
+
- customer
|
|
22
|
+
- prospect
|
|
23
|
+
- partner
|
|
24
|
+
- competitor
|
|
25
|
+
defaultValue: prospect
|
|
26
|
+
index: true
|
|
27
|
+
|
|
28
|
+
industry:
|
|
29
|
+
type: select
|
|
30
|
+
options:
|
|
31
|
+
- technology
|
|
32
|
+
- finance
|
|
33
|
+
- healthcare
|
|
34
|
+
- manufacturing
|
|
35
|
+
- retail
|
|
36
|
+
- education
|
|
37
|
+
- other
|
|
38
|
+
label: Industry
|
|
39
|
+
index: true
|
|
40
|
+
|
|
41
|
+
annual_revenue:
|
|
42
|
+
type: currency
|
|
43
|
+
label: Annual Revenue
|
|
44
|
+
|
|
45
|
+
employees:
|
|
46
|
+
type: number
|
|
47
|
+
label: Number of Employees
|
|
48
|
+
|
|
49
|
+
website:
|
|
50
|
+
type: url
|
|
51
|
+
label: Website
|
|
52
|
+
|
|
53
|
+
phone:
|
|
54
|
+
type: text
|
|
55
|
+
label: Phone
|
|
56
|
+
|
|
57
|
+
billing_address:
|
|
58
|
+
type: textarea
|
|
59
|
+
label: Billing Address
|
|
60
|
+
|
|
61
|
+
shipping_address:
|
|
62
|
+
type: textarea
|
|
63
|
+
label: Shipping Address
|
|
64
|
+
|
|
65
|
+
owner:
|
|
66
|
+
type: lookup
|
|
67
|
+
reference_to: user
|
|
68
|
+
label: Account Owner
|
|
69
|
+
index: true
|
|
70
|
+
|
|
71
|
+
parent_account:
|
|
72
|
+
type: lookup
|
|
73
|
+
reference_to: crm_account
|
|
74
|
+
label: Parent Account
|
|
75
|
+
|
|
76
|
+
description:
|
|
77
|
+
type: textarea
|
|
78
|
+
label: Description
|
|
79
|
+
|
|
80
|
+
status:
|
|
81
|
+
type: select
|
|
82
|
+
options:
|
|
83
|
+
- active
|
|
84
|
+
- inactive
|
|
85
|
+
defaultValue: active
|
|
86
|
+
index: true
|
|
87
|
+
|
|
88
|
+
indexes:
|
|
89
|
+
# For account owner queries
|
|
90
|
+
owner_type_idx:
|
|
91
|
+
fields: [owner, type]
|
|
92
|
+
|
|
93
|
+
# For industry analysis
|
|
94
|
+
industry_revenue_idx:
|
|
95
|
+
fields: [industry, annual_revenue]
|
|
96
|
+
|
|
97
|
+
# For status reporting
|
|
98
|
+
status_created_idx:
|
|
99
|
+
fields: [status, created_at]
|
|
100
|
+
|
|
101
|
+
ai:
|
|
102
|
+
search:
|
|
103
|
+
enabled: true
|
|
104
|
+
fields: [name, description, website]
|
|
105
|
+
model: text-embedding-3-small
|