zoukankan      html  css  js  c++  java
  • XAF 写一个正式的CRM应用程序<DC翻译博客七>

    XCRM: Writing real-world CRM application(写一个正式的CRM应用程序)

    I'm starting to write a generic CRM application, to try the new domain component (DC) technology and decide what classes should be included in our Domain Component technology. This application should be suitable for small business and extendable to support specific markets. While writing, I'm sure to find bottlenecks in XAF that we will have to fix.
    我开始写一个一般的CRM应用程序,试着用新的领域构件(DC)技术,决定我们的领域构件技术包括什么类。这个应用程序应当适合少业务,支持特定市场扩展。在写,我相信能找到XAF中瓶颈,修复它。

    In general, a CRM application should be able to manage the following things:
    通常,一个CRM应用程序能管理以下事情:

    • Contacts (联系人)
    • Accounts (客户经过核实过客户信息的客户,就转为客户)
    • Leads (销售线索,没有经过验证的,有待核实的销售消息)
    • Opportunities (销售机会:经过核实、确认的线索,并且需要进入销售跟踪,即转为机会。销售线索向销售机会的转换需要质量评估和筛选的过程。业务员也可以对明确的购买需求直接建立销售机会。)
    • Products (产品)
    • Appointments/Calendar/Tasks (约会、日程、任务)
    • Service Requests (服务请求)
    • Marketing Campaigns (营销活动)

    In addition, even a basic CRM system should have a security system that is aware of organization structure.
    另外,即是一个基本的CRM系统应当有一个组织架构形式的安全系统。

    To emphasize the most interesting design parts, I won't detail every domain class. I will create most classes in brief form, and then extend them as required. In the first iteration, I will focus on class relationships.
    强调最有趣的设计部分,我不会详述每个领域类。我将以简短形式建立大部分类,然后根据需求扩展他们。在第一次迭代,我将重点关注类关系。

    Contact. Can belong to an Account. So, it has the Account property.
    联系人能属于一个客户,因此,它有客户的属性。

    Account. Can belong to another Account. So, it has the ParentAccount and Subaccounts properties. In addition, it should have a Contacts list, and a PrimaryContact, which may not belong to the Contacts list.
    客户能属于其他客户,因此,他有父客户和子客户属性。另外,它应当有一个联系人列表,一个主要联系人,可能不属于联系人列表。

    I’m using TDD, so I will capture this knowledge in unit tests. 我用TDD,因此我获取单元测试知识。

    Unit tests for Domain Components(为领域构件单元测试)

    To write tests for domain components, I think I will need a DC infrastructure to be able to generate components from interfaces and business logic. I won't use the entire XAF – I will need only small parts of its services. Here is an example of a test:
    写领域构件测试,我想我需要一个DC基础架构能从接口和业务逻辑生成构件。我不用整个XAF—只需要他的一小部分功能。这里是一个测试例子:

    [Domain Component]

    public interface IBasicTestThing {

        string Name { get; set; }

    }

    [TestFixture]

    public class BasicTests : BaseTest {

        [Test]

        public void TestBasicThing() {

            RegisterDC<IBasicTestThing>();

            Generate();

            IBasicTestThing thing1 = ObjectSpace.CreateObject<IBasicTestThing>();

            thing1.Name = "abc";

            ObjectSpace.CommitChanges();

            IBasicTestThing thing2 = ObjectSpace.FindObject<IBasicTestThing>(null);

            Assert.AreEqual("abc", thing2.Name);

        }

    }

    In all my tests, I'll register and generate domain components, and use an ObjectSpace object. So, all my tests will be inherited from the BaseTest class that will provide the required services. Look how it's implemented now:
    在我的所有测试中,我注册和生成了领域构件,并用ObjectSpace对象。因此,所有测试都继承BaseTest类,将提供需求的服务。看,现在,它是如何实现?

    public class BaseTest {

        private IObjectSpace objectSpace;

        private IObjectSpaceProvider osProvider;

        [SetUp]

        public virtual void SetUp() {

            XafTypesInfo.Reset();

            osProvider = new ObjectSpaceProvider(new MemoryDataStoreProvider());

            objectSpace = osProvider.CreateObjectSpace();

        }

        public void RegisterDC<T>() {

            if (typeof(T).IsInterface) {

                XafTypesInfo.Instance.AddEntityToGenerate(typeof(T).Name, typeof(T));

            } else {

                XafTypesInfo.Instance.RegisterEntity(typeof(T));

            }

        }

        public IObjectSpace ObjectSpace {

            get { return objectSpace; }

        }

        public void Generate() {

            XafTypesInfo.Instance.GenerateEntities();

        }

    }

    The SetUp method cleans up the current type information, and creates an Object Space using a newly created Object Space Provider (using in-memory data store). The RegisterDC and Generate methods work with the XafTypesInfo system, like it's performed in XAF.
    SetUp
    方法清除当前类型信息,用新建对象Object Space Provider创建一个Object Space.XafTypesInfo系统1注册DC并生成方法工作,像它在XAF中执行。

    Capturing domain knowledge in unit tests(获取领域知识用单元测试)

    I’m ready to write a test for the Contact - Account relationship:
    我准备写一个联系人的单元测试客户关系:

    [Test]

    public void ContactAccountRelationships() {

        RegisterDC<IContact>();

        RegisterDC<IAccount>();

        Generate();

        IContact roman = ObjectSpace.CreateObject<IContact>();

        roman.FirstName = "Roman";

        roman.LastName = "Eremin";

        IAccount dx = ObjectSpace.CreateObject<IAccount>();

        dx.Name = "DevExpress";

     

        dx.PrimaryContact = roman;

        Assert.IsNull(roman.Account);

     

        dx.Contacts.Add(roman);

        Assert.AreEqual(dx, roman.Account);

     

        IAccount xafTeam = ObjectSpace.CreateObject<IAccount>();

        xafTeam.ParentAccount = dx;

        Assert.IsTrue(Enumerator.Exists<IAccount>(dx.Subaccounts, xafTeam));

    }

    Enumerator is a helper class from the DevExpress.ExpressApp.Utils.dll assembly. It provides utility methods for the IEnumerable interface (similar extension methods already exist in .net 3.0).
    Enumerator
    是一个帮助类来自DevExpress.ExpressApp.Utils.dll程序集。它为Ienumerable接口提供实用方法。

    Here is the code that makes this test pass (remember – I’m focused on relationships, so don’t tell me that the IContact should contain the IPerson interface) :
    下面代码测试通过:

    [DomainComponent]
    public interface IAccount {
        string Name { get; set; }
     
        IAccount ParentAccount { get; set; }
        IList<IAccount> Subaccounts { get; }
     
        IContact PrimaryContact { get; set; }
        IList<IContact> Contacts { get; }
    }
    [DomainComponent]
    public interface IContact {
        IAccount Account { get; set; }
    }

    No logic is required, because the XpoBuilder automatically generates the correct associations and XPO manages them. So, when I add roman to the dx.Contacts list, the roman.Account property is initialized automatically.
    没有逻辑需求,因为XpoBuilder自动生成对应关联,XPO管理他们。因此,当我给dx.Contacts列表添加roman,roman.Account属性自动初始化。

     

     

    参考信息:

    • Prospect(潜在客户:没有经过验证的,有待核实的客户信息)

    通俗的解释
    lead:线索,一般来说客户意向不是很明确的情况下,我们把他定义为线索;
    opportunity
    :机会,客户意向比较明确,作为销售来说,也比较确定要投入力度去跟进的项目,可称为机会。
    pipeline
    :机会管线(销售漏斗),机会由建立到最终成交这个过程中各种机会阶段的汇总。

     

    在需求讨论过程中,大家对销售线索与销售机会、客户与潜在客户的划分进行了讨论。

    销售线索(lead):没有经过验证的,有待核实的销售消息

    销售机会(opportunity):经过核实、确认的线索,并且需要进入销售跟踪,即转为机会。销售线索向销售机会的转换需要质量评估和筛选的过程。业务员也可以对明确的购买需求直接建立销售机会。

    潜在客户(prospect):没有经过验证的,有待核实的客户信息

    客户(account):经过核实过客户信息的客户,就转为客户



    案例分析

    案例一:购买行业客户数据库

    1)客户数据属于潜在客户

    2)当市场人员(如Call Center人员)通过呼出电话对客户信息进行验证后,该潜在客户即转为客户;

    3)如果该客户有模糊的购意向,则产生销售线索,这些线索统一转发给地区经理,再由地区经理将这些销售线索分配给合适的业务员;

    4)收到分配的销售线索的业务员,根据实际情况判断该客户是否有明确的购买需求。如果有,则将此销售线索转化为销售机会进行跟踪。

    案例二:客户通过400热线电话或在市场活动时主动进行产品咨询

    1)虽然客户信息可能比较确定,但由于客户信息未经验证,因此属于潜在客户(prospect

    2)客户看似有明显的购买意向,但此意向并未经过确认,因此仍属于销售线索

    3)销售线索转发给地区经理,由地区经理将销售线索分配给合适的业务员

    4)业务员对该线索进行确认,并判断是否将此销售线索转化为销售机会进行跟踪

    案例三:客户直接联系业务员

    1)业务员对客户信息进行确认,直接建立客户(account

    2)业务员可直接建立销售机会
    1)销售线索和潜在用户,销售机会与客户,状态相对是对应的,这样利于管理。同样,对统计客户类型就比较有用

    2)只有验证之后或者确定有意向之后,再转换为客户,这样客户的转化率就可以作为一个指标。市场部和销售部的考核也可以区分,潜在客户的数量和转化率,是市场部的业务质量;客户的数量和成功订单率是销售部的业务指标

     

    欢迎转载,转载请注明出处:http://www.cnblogs.com/Tonyyang/

  • 相关阅读:
    ComboBoxEdit 数据绑定 使用模板
    ObservableCollection
    ListView.MouseDoubleClick
    Style 的查找 FindResource
    OpenFileDialog
    ItemsControl
    下拉框比较符
    ListView 控件与 内容
    测试oracle数据库连接
    MySQL ERROR 1300 (HY000): Invalid utf8 character string
  • 原文地址:https://www.cnblogs.com/Tonyyang/p/1943649.html
Copyright © 2011-2022 走看看