Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 29, 2026

Description

Migrated three core business objects from YAML to TypeScript following @objectstack/spec v0.6.1, establishing type-safe object definitions with comprehensive field schemas, validation rules, and AI enhancement fields.

Type of Change

  • New feature (non-breaking change which adds functionality)
  • Documentation update

Changes Made

Activity Object (packages/crm/src/activity.object.ts)

  • 10 activity types with type-specific fields (Call: duration/result, Email: from/to/body, SMS: content/phone)
  • Who/What polymorphic relationships: Who → Contact|Lead, What → Account|Opportunity|Contract|Case
  • Recurring task engine: Pattern (Daily/Weekly/Monthly/Yearly), interval, end date
  • Field check-in: GPS coordinates for location-based activities
  • AI fields: Transcription, action items extraction, sentiment analysis, key points, next steps
  • 9 validation rules: Activity-type constraints, date logic, recurrence validation
  • 9 list views: My Activities, Today, This Week, Upcoming, Overdue, Team Calendar, etc.

Quote Object (packages/products/src/quote.object.ts)

  • CPQ workflow: Configure-Price-Quote with line items, pricing calculations (subtotal → discount → tax → shipping → total)
  • Multi-currency: 7 currencies (USD, EUR, GBP, JPY, CNY, AUD, CAD) with exchange rates
  • Quote versioning: Previous/Latest version tracking, primary quote designation
  • Approval workflow: Multi-level approval based on discount thresholds, rejection tracking with reasons
  • Customer acceptance: Date, signer, signature capture
  • AI fields: Product bundle recommendations, optimal discount, win probability, pricing analysis, upsells
  • 8 validation rules: Date constraints, approval requirements, pricing bounds
  • 10 list views: Draft, Pending Approval, Sent, Accepted/Declined, Expiring Soon, High Value

Case Object (packages/support/src/case.object.ts)

  • 8 origin channels: Email, Web, Phone, WeChat, Chat Bot, Mobile App, Walk-in, Other
  • SLA engine: 5 levels (Platinum → Standard), auto-calculated response/resolution due dates, violation tracking
  • Priority/Severity matrix: 4 priority levels × 4 severity levels (S1-S4)
  • Escalation tracking: Level counter, escalation chain, reason documentation
  • CSAT tracking: 5-point satisfaction scale, feedback, survey timestamps
  • AI-powered routing: Auto-categorization, suggested assignee, knowledge article matching, solution recommendations, urgency scoring (0-100), keyword extraction
  • 7 validation rules: Resolution requirements, closed case immutability, escalation constraints
  • 11 list views: My Cases, Team Queue, High Priority, Escalated, SLA Violations, Unassigned, etc.

Technical Implementation

// Export pattern uses named exports for tree-shaking
export { default as Activity } from './activity.object';
export { default as Quote } from './quote.object';
export { default as Case } from './case.object';

// Usage with full type safety
import { Activity, Quote, Case } from '@hotcrm/{package}';
console.log(Activity.fields.WhoId.reference); // ['Contact', 'Lead']

Backward Compatibility

  • YAML files retained at original paths
  • No breaking changes to existing code
  • Migration path documented in MIGRATION_NOTES.md

Testing

  • Unit tests pass (npm test)
  • Linting passes (npm run lint)
  • Build succeeds (npm run build)
  • Manual testing completed
  • New tests added (if applicable)

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published

Additional Notes

Validation Rule Corrections Applied:

  • Activity: Recurrence end date and due date logic (trigger on invalid, not valid)
  • Quote: Approval workflow allows "Pending" and "In Review" states during discount approval
  • Case: Closed case immutability includes NOT(ISNEW()) guard

CodeQL Security Scan: 0 vulnerabilities detected

Statistics: 1,985 lines added across 10 files (3 object definitions, 3 index exports, 3 READMEs, 1 migration guide)

Original prompt

第一阶段:基础增强(第1-4周)- 优先级最高

目标:完成核心CRM对象和关键业务逻辑

1.1 关键对象迁移(第1-2周)

Activity对象迁移 ⭐ 最高优先级

迁移 Activity.object.yml → activity.object.ts
实现全面的活动跟踪:
类型:电话、邮件、会议、任务、备注、短信
状态跟踪及完成日期
优先级管理
相关对象关联(Who/What模式)
重复任务支持
添加验证规则:
基于活动类型的必填字段
日期/时间约束
分配验证
创建活动视图:
我的活动(今天、本周、逾期)
团队日历
活动时间线
Quote对象迁移 ⭐ 高优先级

迁移 Quote.object.yml → quote.object.ts
实现CPQ(配置-定价-报价)基础:
带产品引用的报价行项目
折扣管理(行级和报价级)
税金计算框架
多币种支持
报价版本管理
报价模板
添加审批工作流钩子:
折扣审批阈值
经理审批路由
审批历史跟踪
创建报价视图:
草稿报价
待审批
已发送给客户
已接受/已拒绝
Case对象迁移 ⭐ 高优先级

迁移 Case.object.yml → case.object.ts
实现服务管理:
多渠道工单创建(邮件、电话、Web、聊天、微信)
SLA管理与自动计算
升级规则和路由
优先级和严重程度级别
工单状态工作流
客户满意度(CSAT)跟踪
添加自动化钩子:
基于技能/可用性的自动分配
SLA违规通知
自动升级
客户通知
创建工单视图:
我的工单
团队队列
已升级工单
SLA违规中
今日已关闭


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@vercel
Copy link

vercel bot commented Jan 29, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
hotcrm Ready Ready Preview, Comment Jan 29, 2026 2:04am

Request Review

Copilot AI and others added 3 commits January 29, 2026 01:53
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
…ode review

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
@github-actions github-actions bot added the documentation Improvements or additions to documentation label Jan 29, 2026
Copilot AI changed the title [WIP] Migrate Activity and Quote objects for CRM Migrate Activity, Quote, and Case objects to TypeScript (Phase 1) Jan 29, 2026
Copilot AI requested a review from hotlong January 29, 2026 02:02
@hotlong hotlong marked this pull request as ready for review January 29, 2026 02:05
Copilot AI review requested due to automatic review settings January 29, 2026 02:05
@hotlong hotlong merged commit 7b75a36 into main Jan 29, 2026
7 checks passed
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates three core business objects (Activity, Quote, and Case) from YAML to TypeScript format following the @objectstack/spec v0.6.1 protocol. The migration establishes type-safe object definitions with comprehensive field schemas, validation rules, list views, and AI enhancement capabilities.

Changes:

  • Migrated Activity, Quote, and Case objects to TypeScript with 10 activity types, CPQ workflow, and multi-channel case management respectively
  • Fixed export pattern from export * to export { default as ... } for proper default export re-export in all three packages
  • Updated package READMEs and created comprehensive MIGRATION_NOTES.md documenting features, breaking changes, and migration path

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
packages/crm/src/activity.object.ts New TypeScript definition for Activity with 10 types, Who/What polymorphic relationships, recurring tasks, check-in GPS, AI transcription/sentiment, and 9 validation rules
packages/crm/src/index.ts Fixed export pattern from export * to export { default as Activity } and updated for all objects
packages/crm/README.md Updated to reflect Activity migration and corrected import examples
packages/products/src/quote.object.ts New TypeScript definition for Quote with CPQ workflow, multi-currency support, approval workflow, quote versioning, PDF generation, and AI pricing analysis
packages/products/src/index.ts Added Quote export using corrected pattern export { default as Quote }
packages/products/README.md Updated documentation showing Quote as TypeScript definition with usage examples
packages/support/src/case.object.ts New TypeScript definition for Case with 8 origin channels, SLA engine, priority/severity matrix, escalation tracking, CSAT, AI routing, and 7 validation rules
packages/support/src/index.ts Added Case export using pattern export { default as Case }
packages/support/README.md Updated to document Case migration from YAML to TypeScript
MIGRATION_NOTES.md Comprehensive migration documentation with features, validation rules, list views, breaking changes, and next steps

{
name: 'ContactMustBelongToAccount',
errorMessage: 'Contact must belong to the selected Account',
formula: 'AND(NOT(ISBLANK(ContactId)), NOT(ISBLANK(AccountId)))'
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This validation rule formula does not actually validate that the Contact belongs to the selected Account. The current formula 'AND(NOT(ISBLANK(ContactId)), NOT(ISBLANK(AccountId)))' only checks that both fields are populated, but doesn't verify the relationship between them.

To properly validate the relationship, you would need to use a formula like 'AND(NOT(ISBLANK(ContactId)), NOT(ISBLANK(AccountId)), Contact.AccountId != AccountId)' or rely on a backend validation hook that can perform cross-object queries. If this type of reference validation is not supported in the validation rule formula language, consider removing this validation rule and implementing it in a hook instead.

Suggested change
formula: 'AND(NOT(ISBLANK(ContactId)), NOT(ISBLANK(AccountId)))'
formula: 'AND(NOT(ISBLANK(ContactId)), NOT(ISBLANK(AccountId)), Contact.AccountId != AccountId)'

Copilot uses AI. Check for mistakes.
Comment on lines +543 to +547
name: 'PrimaryQuoteUnique',
errorMessage: 'Only one primary quote allowed per opportunity',
formula: 'AND(IsPrimaryQuote = true, OpportunityId != null)'
},
{
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This validation rule does not enforce uniqueness of primary quotes per opportunity. The formula 'AND(IsPrimaryQuote = true, OpportunityId != null)' will trigger for EVERY primary quote that has an opportunity, not just when there's a duplicate.

To properly enforce "only one primary quote per opportunity", you would need a formula that can count other primary quotes for the same opportunity, or implement this as a unique constraint at the database level or in a hook. Consider either:

  1. Implementing this validation in a before-save hook that queries for existing primary quotes on the same opportunity
  2. Using a database unique constraint on (OpportunityId, IsPrimaryQuote) where IsPrimaryQuote = true
  3. Removing this validation rule if the enforcement mechanism is not supported
Suggested change
name: 'PrimaryQuoteUnique',
errorMessage: 'Only one primary quote allowed per opportunity',
formula: 'AND(IsPrimaryQuote = true, OpportunityId != null)'
},
{

Copilot uses AI. Check for mistakes.
{
name: 'AcceptedQuoteReadOnly',
errorMessage: 'Accepted quotes cannot be modified',
formula: 'AND(Status = "Accepted", ISCHANGED(Status) = false)'
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This validation rule has inverted logic. The formula 'AND(Status = "Accepted", ISCHANGED(Status) = false)' triggers when the Status is "Accepted" AND the Status field has NOT changed, which means it would fire when you modify other fields on an already-accepted quote but NOT when you modify the status itself.

The intention appears to be preventing ANY modifications to accepted quotes. The formula should be 'AND(PRIORVALUE(Status) = "Accepted", NOT(ISNEW()))' to trigger when trying to modify a record that was previously in Accepted status, similar to the ClosedCaseReadOnly validation rule in the Case object (line 534).

Suggested change
formula: 'AND(Status = "Accepted", ISCHANGED(Status) = false)'
formula: 'AND(PRIORVALUE(Status) = "Accepted", NOT(ISNEW()))'

Copilot uses AI. Check for mistakes.
},
{
name: 'ClosedCaseReadOnly',
errorMessage: 'Closed cases cannot be modified',
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This validation rule only prevents changing the Status FROM "Closed" to another value, but doesn't prevent modifying other fields on a case that remains in Closed status. The error message "Closed cases cannot be modified" suggests broader immutability.

If the intent is to make closed cases completely read-only (no field modifications), the formula should be 'AND(PRIORVALUE(Status) = "Closed", NOT(ISNEW()))' which would trigger on any modification attempt to a previously-closed record. If the current behavior (only preventing status changes) is intentional, consider updating the error message to be more specific, such as "Cannot change status of a closed case".

Suggested change
errorMessage: 'Closed cases cannot be modified',
errorMessage: 'Cannot change status of a closed case',

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants