cub-e.net

just coding...

Top 5 features in Microsoft Dynamics CRM 2015

The Microsoft Dynamics CRM 2015 release has many new and improved features, which presents great improvements in how we can utilize the platform better. The updates will enable marketers to plan and execute marketing campaigns better, track impact, and strengthen collaborations with the sales process.

Customers today have higher expectations from businesses and to meet these needs, it’s mandatory to collaborate and bring in solutions which will help to reduce the gap between divisions which work towards customer satisfaction.

Microsoft Dynamics CRM 2015 is set to release in Q4 2014 (December). And as we studied the new release, we realized there are a few features which will bring about a change, in the good sense, for all users.

Product Families

  • Suggestions: Cross – selling or up- selling requires related product linkages, or formation of product families. Opportunity and customer records can help sales professionals bring in better conversion/customer when products are correctly categorized
  • Bundling: Products can be bundled and offered as packages, for discounts and offers
  • Regional pricelist: Products can be bundled and offered as packages, based on regional requirements and assessments
  • Product properties: Increased number of parameters for a product. Though these can be achieved through customizations in Dynamics CRM 2013, product properties will give more flexibility in various in-house processes
  • Import/Export products: Configuration migration tool, introduced in Dynamics CRM 2013 has been improved to support product migrations in Dynamics CRM 2015

Guided Sales Process

  • Further improves the business processes introduced in Dynamics CRM 2013 to enable organization implement complex business processes
  • Conditional branching has brought about more specificity to business processes
  • As compared to the wizard in Dynamics CRM 2013, Dynamics CRM 2015 offers custom programming options bringing in the possibility of implementing complex business logics

Mobile Enhancements

  • Offline draft capabilities on mobile devices which are synced when the user is back online
  • All dashboards are available on tablets

Case Management

  • Different Service Level Agreements (SLAs) to bring in flexible support and service requirements
  • Pause and Resume SLAs to track time efficiently through system settings
  • Track and analyze each key metrics and individual SLA

Search

  • With the new release, search within Dynamics CRM 2015 will be simpler and will allow for the usage of asterisks as wildcard characters
  • Search is customizable and configurable. The search can be across multiple record types.
  • Search can be configured on specific fields of preferred entities, improving search performance

One of the smaller (for now), enhancement which has been brought in, is Cortana on Windows Phone 8.1 devices, using which, users will be able to talk to the customer relationship management suite. Setting up meetings/reminders, searching contacts, accounts or activities, creating new records, etc. will be a breeze using Cortana.

Satışlarınız Düşmesin Yükselsin

Acikakademi.com sponsorlugunda gerceklestirecegimiz bu online etkinlikte Dynamics CRM 2013 SP1 uzerinde bir satis senaryosunun nasil gerceklestirilecegi anlatilacaktir. 09.10.2014 tarihinde Turkiye saatiyle 20:00 da etkinlik baslayacaktir. Internet uzerinden online olarak izleyebileceginiz etkinlik hakkinda daha fazla bilgiye buraya tiklayarak ulasabilirsiniz.

Sektörünün önde gelen firmalarından Contoso, satışlarını artıramamaktan yakınıyor, firma sahibi Ahmet Bey ise sorunun nereden kaynaklandığını tam teşhis edemiyordu. Satış ekipleri mi mevcut potansiyelin farkında olamıyor, yoksa potansiyellerini bildikleri halde işleri rakiplerine mi kaptırıyorlardı? Ahmet Bey’in bu sorunu çözebilmesi için daha ayrıntılı bilgiye sahip olması gerekiyor, ancak satış ekiplerinden daha fazla bilgi toplamak için girişimde bulunduğunda, tepki alıyordu. Dışa dönük ve satışa odaklanmış bu ekipler, sistemle uğraşmaya ve bilgi girişi yapmaya direniyorlar; tüm zamanlarını satışa ayırmak istiyorlardı. Satış ekiplerinden her görüşmelerini, her teklifi, teklif sonrası her takip adımını sisteme girmelerini istemek hiç de kolay değildi.

Pazarlama bölümü ise ürünlerini etkin tanıtamıyordu. Doğru müşteriye doğru iletişim kanalı ile ulaşmak ve bunu yaparken ekibinin aktivitelerini de denetleyerek, kampanyanın maliyetini düşürmek istiyorlardı. Tabii ki ürün ve pazarlama performanslarının etkin bir şekilde raporlanması da gerekiyordu.

İşte firmasındaki bütün bu sorunlara cevap arayan Ahmet Bey, araştırmasında Microsoft’un Dynamics CRM İş Platformunun, esnek ve genişleyebilir yapısı ile çok iyi bir ürün olduğunu gördü. Satış ve pazarlama bölümündeki sorunları giderebildiği gibi, servis talepleri ile çağrıları yönetebileceğini, servis aktiviteleri ile sahadaki personelin iş yükünü yönetebileceğini öğrendi. Üstelik iş akışları ile sistem otomatik olarak kendisine verilmiş işleri yapmaktaydı. İş akışları sayesinde bir olay ya da değişiklik olduğunda sistem bunu algılayıp gerekli işlemleri yerine getirebilmekteydi. Ayrıca bu sisteme tümleşik olan Web Portalı sayesinde kullanıcılar kendi servis taleplerini açmanın yanında, kendisiyle ilgilenen teknik servis personelinin boş olduğu saatlere randevu da alabiliyordu. Sahadaki teknik servis personeli sistemle entegre tablet ve akıllı cep telefonu arabirimi sayesinde şirket sistemine bağlanabilmekte, böylece müşteri bilgilerine ulaşabilmekte ve üzerlerindeki işleri, servis taleplerini çevrimiçi olarak görebilmekteydiler. Üstelik esnek raporlama arayüzü ile herkes kendi anlayabildiği şekilde raporlar alarak sistemi en yüksek verimle kullanabilmekteydi. 

Mobile Development Helper Code for Dynamics CRM

Technologies

Web Services, OData, Dynamics CRM, SOAP
OData, Microsoft Dynamics CRM Modern app SOAP endpoint, Dynamics CRM web services
Desktop, Phone, Windows RT
en-US
9/8/2014

Introduction

The Microsoft.Crm.Sdk.Mobile source code sample is a partial re-implementation of the Microsoft Dynamics CRM SDK classes written as a Portable Class Library to facilitate development of store apps for Windows 8.1 desktop, tablets, and phones. The code makes use of the SOAP and OData protocols to issue web service method calls. An organization web service proxy and most of the message response/request classes in the CRM SDK have been implemented. When writing apps that use this code, you don’t have to link to the CRM SDK assemblies to access the organization web service.

This code can also be used when you develop apps using Xamarin. However, you must comment out the EnableProxyTypes method in Microsoft.Xrm.Sdk.Samples.cs when developing iOS or Android apps using Xamarin because that method contains code that is specific to Windows Store. An alternative is to comment out the relevant code as shown here.

 

Copy code
C#
Edit|Remove
public async Task EnableProxyTypes()
{
    List<TypeInfo> typeList = new List<TypeInfo>();
    //// Obtain folder of executing application.
    //var folder = Package.Current.InstalledLocation;
    //foreach (var file in await folder.GetFilesAsync())
    //{
    //    // Not only .dll but .exe also contains types.
    //    if (file.FileType == ".dll" || file.FileType == ".exe")
    //    {
    //        var assemblyName = new AssemblyName(file.DisplayName);
    //        var assembly = Assembly.Load(assemblyName);
    //        foreach (TypeInfo type in assembly.DefinedTypes)
    //        {
    //            // Store only CRM entities.
    //            if (type.BaseType == typeof(Entity))
    //                typeList.Add(type);
    //        }
    //    }
    //}
    typeList.Add(typeof(ActivityParty).GetTypeInfo());
    typeList.Add(typeof(SavedQuery).GetTypeInfo());
    typeList.Add(typeof(Privilege).GetTypeInfo());
    typeList.Add(typeof(SystemUser).GetTypeInfo());
    typeList.Add(typeof(Annotation).GetTypeInfo());
    typeList.Add(typeof(TimeZoneDefinition).GetTypeInfo());
    types = typeList.ToArray();
}
 

 

Building the Sample

Your development computer must have an internet connection to build the library as a NuGet package named Json.NET will be automatically downloaded during the build.

To build the Microsoft.Crm.Sdk.Mobile.dll assembly, follow these steps.

  1. In Visual Studio 2013, with update 2 or later installed, load the Microsoft.Crm.Sdk.Mobile.sln file.
  2. Press F6.

 

Description

The Microsoft Dynamics CRM 2013 SDK (and earlier releases) support client and server side code development for Dynamics CRM. However, the SDK assemblies cannot be used to develop mobile and store applications as the Windows run-time (WinRT) is not supported. To provide support for mobile apps, including cross platform iOS and Android apps, the Dynamics CRM server now supports client access to the organization web service using industry standard protocols such as OAuth (for authentication), plus SOAP and OData for sending web service requests. The problem is that while these protocols are supported, they are difficult to use. The solution is to layer a framework on top of the protocols to make app programming easier. For developing mobile and store apps, you can use the Microsoft Azure Active Directory Library (ADAL) for authentication, and this sample helper code library for web service requests and early-bound type support. 


What is included in the library

This library contains the following key components:

 

  Web Service Proxy

This library provides most methods that the OrganizationServiceProxy class in the CRM SDK does - Create, Update, Assign, Execute, and so on. The class supports early-bound development by providing an EnableProxyTypes method. SOAP implementations of these methods use the same name as are used in the CRM SDK while the OData-based methods have names that begin with “Rest” for example RestCreate.

 

  SDK classes and enumerations

This library supports most common CRM SDK classes and enumerations. With the addition of early-bound type support, you can use Visual Studio IntelliSense when writing your apps.

 

  Organization web service messages

This library includes request/response classes for over 200 messages. It covers both data operations, for example Create, and metadata operations, for example RetrieveMetadataChanges.

 

What isn't included in the library

Several functional areas that the library doesn’t cover are as follows:

Authentication

Since this sample code library targets multiple platforms, and each platform has its unique way to authenticate the user, the library doesn’t provide any authentication mechanism. You must obtain an OAuth access token and pass it to an OrganizationDataWebServiceProxy object to access the organization web service. It’s recommended that you use the Microsoft Azure Active Directory Authentication Library (ADAL) for identity authentication. This library is referenced in the CRM SDK documentation and sample code. There is an open source implementation of ADAL available for iOS and Android. There is a Windows 8.1 version available for the desktop, tablets, and phones.

For more information on ADAL see http://www.cloudidentity.com/blog/2014/06/16/adal-for-windows-phone-8-1-deep-dive.

A sample code file named CRMHelpers.cs is provided to demonstrate how to authenticate a universal app. The file is not included in the build of the library.

DiscoveryService, DeploymentService, OrganizationServiceContext

This library doesn’t provide support for the discovery or deployment web services. It also doesn’t support the OrganizationServiceContext class.

How to write apps that use this library

You can build Microsoft.Crm.Sdk.Mobile.dll using the supplied Visual Studio 2013 solution and add a reference for it in your app’s project or you can add the library’s C# sample code files to your project.

In your app, add code to authenticate the user and obtain a security access token. The method used varies depending on platform as mentioned previously. Next, instantiate the OrganizationDataWebServiceProxy class.

Copy code
C#
Edit|Remove
OrganizationDataWebServiceProxy _proxy = new OrganizationDataWebServiceProxy();
 

Set the access token and web server URL in the OrganizationDataWebServiceProxy object.

Copy code
C#
Edit|Remove
_proxy.ServiceUrl = "<your CRM server URL goes here>";
_proxy.AccessToken = "<access token>";
 

Call EnableProxyTypes to use early-bound types and optionally assign a service time-out interval.

Copy code
C#
Edit|Remove
await _proxy.EnableProxyTypes();

_proxy.Timeout = 600;

Send a message request to the web service by using an async/await pattern.

Copy code
C#
Edit|Remove
WhoAmIResponse whoAmIResponse = (WhoAmIResponse)await _proxy.Execute(new WhoAmIRequest());

// Retrieve User Info

SystemUser user = (SystemUser)await _proxy.Retrieve(SystemUser.EntityLogicalName, whoAmIResponse.UserId, new ColumnSet(true));
 

How to update existing application code

If you want to use existing application code that was written for the CRM SDK with this library, make the following code changes.

1. Add the async keyword to methods.

2. Add await before the call to a proxy method.

3. When accessing the property of a web service response, do so as shown here.

 

Original CRM SDK code

Copy code
C#
Edit|Remove
_proxy.RetrieveMultiple(new QueryExpression(“account”, new Columns(true)).Entities)
 

Modified code

Copy code
C#
Edit|Remove
(await _proxy.RetrieveMultiple(new QueryExpression(“account”, new Columns(true))).Entities)
 

Important notes

  • The sample files are not intended to be used in a production environment. You should deploy this sample to a test environment and examine it for interaction or interference with other parts of the system.
  • Before you deploy this sample to a production environment, make sure that you consider the existing customizations you may have implemented in Microsoft Dynamics CRM 2013.
  • This library was written by Kenichiro Nakamura at Microsoft.

Source code for the CrmSvcMobileUtil program is provided in a separate sample. Use that program to generate any custom or customized entity types in your organization for inclusion in your application.

Source Code Files

  • Microsoft.Xrm.Sdk.Utility.Samples.cs - This file implementes a utility class that provides methods used by the other code files. There is no equivalent for this functionality in the CRM 2013 SDK.


More Information

For more information on Dynamics CRM authentication and app development, see Write mobile and modern apps.

download the code : View this sample online

CRM Service Utility for Mobile Development

Technologies

Dynamics CRM
Code Generation, Dynamics CRM metadata access
Desktop, Phone, Windows RT
en-US
9/8/2014

Introduction

This sample is a custom extension to the CrmSvcUtil.exe program that ships in the Dynamics CRM 2013 SDK. The purpose of this program is to generate C# or VB source code containing early-bound entity types and option set types from the metadata of your CRM server. This code can then be included in your mobile app projects. This enables you to make use of both out-of-box and any custom or customized entities in your code.

 

Building the Sample

To build the program, follow these steps.

  1. Obtain the CrmSvcUtil.exe program and the Microsoft.Xrm.Sdk.dll assembly from the Bin folder of the CRM 2013 SDK. You can download the SDK from http://msdn.microsoft.com/en-us/dynamics/crm/dn467921.aspx.
  2. Load the CrmSvcMobileUtil.sln solution file into Visual Studio 2013.
  3. Add references to CrmSvcUtil.exe and Microsoft.Xrm.Sdk.dll in the project.
  4. Press F6 to build the program.

 

Running the Program

For information on how to run the program, see the SDK topic: Create early bound entity classes with the code generation tool (CrmSvcUtil.exe).

 

Important Notes

    • The sample files are not intended to be used in a production environment. You should deploy this sample to a test environment and examine it for interaction or interference with other parts of the system.
    • This program was written by Kenichiro Nakamura at Microsoft.

       

      More Information

      For more information about writing an extension to the CrmSvcUtil program, see Create extensions for the code generation tool.

      You can download code:

      CRM Service Utility for Mobile Development.zip (48.2KB)

      Microsoft Dynamics CRM 2015 – Vega

      Microsoft today has shared some information on Microsoft Dynamics CRM Fall Wave release – codenamed Vega as part of the Microsoft Dynamics roadmap 2014/2015. There are 3 other releases as part of CRM 2015 (Q4 2014) Fall wave release. These are: 1) code name Hydra: Microsoft Social Listening, 2) Electra: Microsoft Dynamics Marketing and 3) Phoenix: Parature (Dynamics CRM Integration with Parature) as shown in the below Microsoft Dynamics CRM road map (for 2014 and 2015).


      Microsoft Dynamics CRM 2014/2015 Roadmap

      More details about these 3 other releases will be in future posts.

      As for Dynamics CRM Vega, this is a release focusing on Microsoft Dynamics CRM Core product. The Fall Wave release Vega applies to both CRM Online and CRM On-Premise.

      So Vega is apparently going to be officially named: CRM 2015. It will be released before end of this year (Q4 2014). It is expected to include some core product features in Dynamics CRM that many have been waiting for!
      New features and enhancements in Vega Dynamics CRM 2015 are:

      Business Process Improvements:

      • Rule-based branching
      • Single Edit experience
      • Support for multiple entity loops
      • Programmability through Client API
      • Active processes
      • Change of currently active process
      • Move Stages
      • Stage selection and Changing of currently active stage

      User Experience Improvements:

      • Multi Entity Search Capability (horraayy!)
      • A new Advanced Search Button
      • Nested Quick Create forms

      Mobility Features:

      • The addition of 29 new Languages
      • More Dashboards and new concept of Home-pages
      • Support of “Any Device”
      • Ability to have offline drafts

      Enterprise Sales Features:

      • Entity Hierarchy
      • Cross-sell and Up-sell capabilities (also know as Next Buy Actions)
      • External Pricing features
      • Attribute Inheritance
      • Product Relationship
      • Bundles

      XRM and Development Advances:

      • Complex calculations (Calculated Fields & Roll-up of values) (Yes!)
      • Hierarchical Relationship Property
      • Ability to query multiple entities
      • Hierarchical Security Models
      • Field Level Security for system fields (out of the box fields)

      Analytics and Business Intelligence Enhancements:

      • Power BI in CRM Web client
      • Transactional reporting of CRM on Windows Mobile Client Application
      • Roll up on different fields across hierarchie

      Specific for CRM Online (Microsoft’s Online First motto):

      • Self-Service
      • Sign up process Simplification
      • Global Expansion from 42 to 61 Markets (Latin America data centre)
      • Multi-Geographical tenants
      • Scaling out Organisation Synchronisation
      • Minimal downtime Upgrades
      • Addition of Load balancing

      Supported OS and Software Requirements:

      • Windows Server –2012 & 2012 R2
      • Windows Client – Vista, Windows 7 & Windows 8
      • ADFS – 2.0, 2.1, 2.2
      • SQL Server – 2012
      • Exchange Server –2010 & 2013
      • Outlook – 2010 & 2013

      Software and OS no longe supported:

      • Windows Server 2008 & 2008 R2
      • SQL server 2008 & 2008R2
      • Windows Small Business Server ( all version )
      • 2008 Series Terminal Servers
      • Windows Vista
      • SharePoint 2007
      • Exchange 2007
      • IE 8, IE 9
      • Office 2007

      This post has content from this Dynamics Community post

      Our new product : MawensEdu School Management System

      MawensEdu has been developed over Microsoft Dynamics CRM 2013 and it is a school management system which uses Dynamics CRM’s advanced sales and marketing capabilities. 

      With MawensEdu, you can organize SMS and e-mail campaigns, and you can easily follow your campaign budget as well as your campaign goals. 

      During the sales process, you can create offers for more than one section/school and you can supervise the activities of your worldwide vendors.  

      Inside the School, Student/Teacher, and Classroom – Extracurricular activities can be planned, timetables and attendance charts also can be managed. MawensEdu is an independent platform.

      It’s compatible with Mac, Windows and Tablets (iPad, Android). You can manage your business from any device and anywhere you want because it’s web-based application.

      You do not need any additional software for your device to use its all features. 

      Create suitable Campaign Objectives with powerful analysis tools

      You can easily analyse your data and start e-mail and SMS campaigns for your leads after entering their data obtained from fairs or promotional events. In this way, with minimum cost, you will reach maximum audience who will respond your campaign.

      Also, advanced reporting tools can keep under control your campaign at any time. Objective/cost reports will guarantee the success of your campaign.

      Ensure the sales team to achieve their objectives

      MawensEdu, provides you great tools that makes you able to keep under control the whole process of prospective student, from the first encounter until the sale ends.

      When a registration occurs or updated over MawensEdu, you can obtain results according to each case through the triggered workflow mechanism. 

      For example, a visitor visited your website and filled out the information form. Through the workflow mechanism, this information will fall in front of a dealer and this sale activity can be followed on the system. The system will keep record of all the conversation happened via email, phone or face-to-face between the student and the dealer. 

      The software wizard can help you to give suitable offers for the correct students. In addition, after the completion of sale, the system will take care of placement of the relevant student - payment tracking and, if necessary, picking up from the airport and the accommodation and all these relevant stages can also be followed up through the system.   

      Manage your own school…

      After the sales progress, you can keep track of any course registered by your students and the lectures included in the courses, also your student’s attendance status can be followed. 

      System allows you to save all the course contents and the topics of the current lessons. By this way, you can keep track which teacher and student had what lecture in which classroom on what day/what time; also which materials and study methods had been used. 

      Also system can report about each student, what is the aim of the course and how successful students are at assignments and examinations.  

      System is flexible so it allows you to make changes quickly about the content of a course or urgent teacher replacements.

      The system will allow you to manage school equipment and their planned repair / maintenance activities.

      Timetables and content of Diploma and Certificate programmes can also be planned on the system.

      360 degree view will enable you to keep track of a student on a single screen - starting from the sales process until accommodation, attendance, exam notes, payment tracking and control of the assignments.

      Inside the School, Student/Teacher, and Classroom – Extracurricular activities can be planned, timetables and attendance charts also can be managed. 

      Apart from all these, you can plan inspection dates performed by the external institutions and you can manage the documents you need to submit during these inspections. These activities can be planned under management and teacher role, also can follow up if task have been completed. 

      You can use application online or on-promise.

      Login screen :


      Sample Course Program :

      Sample Schema of Work:

      Sample Lesson Plan:

      iPad Screen 1:

      iPad Screen 2:

      iPad Screen 3:

      Dynamics CRM 2013 and Microsoft Dynamics CRM Online nedir?

      Microsoft Dynamics CRM 2013 ve Microsoft Dynamics CRM Online güçlü ve gelişmiş bir iş platformu deneyimini kullanıcılarına sunmaktadır. Dynamics CRM içerisine entegre edilmiş gelişmiş uygulama altyapısı sayesinde sadece uygulamayı kullanmakla kalmıyor aynı zamanda onun istediğimiz yerlerini işimize uygun halde yeniden programlayarak hem kendi içinde hem de dış uygulamalarla konuşabilen kendi iş çözümümüzü oluşturabiliyoruz. Bu şekilde genişlemeye biz xRM adını vermekteyiz. Yani herşeyin yönetilebildiği bir platform.


      Dynamics CRM Microsoft tarafından çeşitli zamanlarda çıkartılan çeşitli service pack ve rollup paketleriyle genişlemekte ve yeni özellikler kazandırılmaktadır.

      Dynamics CRM mevcutta üç farklı çeşitte paketlenmektedir;

      • Microsoft Dynamics CRM 2013 on-premises deployment
      • Microsoft Dynamics CRM 2013 Internet-facing deployment (IFD)
      • Microsoft Dynamics CRM Online

      Bu üç çeşitte de aşağıdaki şekillerde son kullanıcı arabirimi sunmaktadır;

      • Microsoft Dynamics CRM Web client
      • Microsoft Dynamics CRM for Microsoft Office Outlook
      • Microsoft Dynamics CRM for Microsoft Office Outlook with Offline Access
      • Microsoft Dynamics CRM for phones and tablets

      Yani siz Dynamics CRM’i şirketiniz için kullanmaya başladıktan sonra isterseniz Internet Explorer, Chrome, Safari gibi browserlardan sisteme girebilir isterseniz de cep telefonu ya da Outlook üzerinden de kullanabilirsiniz.

      Oluşturduğunuz uygulamaları Dynamics CRM ile Web Servisleri aracılığıyla entegre edebilirsiniz. Bu web servisleri arka tarafta Dynamics CRM’in kalbi olan xRM platform katmanı ile iletişim halinde bulunmaktadır.

      Bu katmanda güvenlik gibi genel kısımları içermektedir ve bir uygulamanın çalışması için gerekli olan yapı taşlarını içerir fakat kendisi ilgili nesnelerinin bir koleksiyonun başka bir şey değildir. Nesneler arasındaki iletişimi sağlar ve tekliften siparişe, siparişten faturaya gibi fiyatlandırma mantığı gibi daha genişletilebilir bir mantığı uygulamak için kullanılır.

      XRM platformu ayrıca, güvenlik yoluyla verilere ve veritabanına erişimi denetler. Ayrıca iş akışı ve özel iş mantığı uygulamaları (plugins) için süreçlerinin tetiklenmesini denetler. Bu katman Microsoft Exchange Server üzerinden gelen ve giden e-posta işleme alır.

      Microsoft Dynamics CRM 2013 'de FetchXML ile Aggregate(Toplama Sorguları) İşlemleri

      Bir önceki makalede FetchXML ile neler yapabileceğimize değindik. (Buraya tıklayarak o makaleye ulaşabilirsiniz) Eğer istersek FetchXML ile grouping ve aggregate işlemlerini de yapabilmekteyiz. FetchXML ile aşağıdaki işlemler desteklenmektedir;

      ·         sum

      ·         avg

      ·         min

      ·         max

      ·         count(*)

      ·         count(attribute name)

       

      Aggregate yapabileceğimiz sorgu örneği standart olarak bildiğimiz fetchXML kurgusundan farklı değil burada sadece attribute kısmında aggregate ile ilgili keyword yer almakta. Aggregate=true diyerek bu şekilde bir sorgulama yapacağımızı sisteme söylüyoruz. Sonrasında ise sırasıyla hangi alan üzerinden işlem yapılacağını, alias yani etiketin ne olacağını ve aggregate türümüzün ne olacağını sisteme söylüyoruz.

      <fetch distinct='false' mapping='logical' aggregate='true'>

        <entity name='opportunity'>

          <attribute name='name' alias='opportunity_count' aggregate='count'/>

        </entity>

      </fetch>

      Bu şekilde oluşturduğumuz bir sorgu ile aslında şunu demek istiyoruz : “select count('name') as opportunity_count from opportunity” yani standart bir count işleminden fazlası değil yaptığımız.

       

      Bu fetchXML’i çalıştırmak için ise aşağıdaki gibi bir kod hazırladım;

       

      string opportunity_count = @" <fetch distinct='false' mapping='logical' aggregate='true'>

                                                      <entity name='opportunity'>

                                                          <attribute name='name' alias='opportunity_count' aggregate='count'/>

                                                      </entity>

                                                    </fetch>";

       

                      EntityCollection opportunity_count_result = ServiseBaglan().RetrieveMultiple(new FetchExpression(opportunity_count));

       

                      foreach (var c in opportunity_count_result.Entities)

                      {

                          Int32 aggregate2 = (Int32)((AliasedValue)c["opportunity_count"]).Value;

                          System.Console.WriteLine("Count of all opportunities: " + aggregate2);

                      }

       

      Burada dikkat edilmesi gereken nokta geriye EntityCollection döndürmesi. Bir önceki makalemden hatırlarsanız normalde bu tarz sorgulama ile biz geriye account, contact gibi sitem içerisindeki nesnelerden oluşmuş bir dizi alıyoruz. FetchXML yapısı gereği tek bir metod kullanıyoruz ve bu metod sonucunda yukarıdaki örnekte olduğu gibi tek bir satır dahi dönecek olsa bile yine sonucu bir collection içerisinde almaktayız. Bu nedenle mecbur foreach içerisinde dönüyoruz ya da collection’un 0. üyesini alıyoruz. Ben örneğimde foreach ile collection içinde döndüm ve gördüğünüz gibi değeri aldım.

       

      Yine bir önceki makalemde ileri düzey sorgular bölümünde anlattığım gibi eğer nesne üzerinden direkt bir değer döndürmeyeceksek sonuç her zaman AliasedValue olarak gelmekte. işte bu nedenden dolayı şu şekilde bir convert işlemi yapıyoruz;

       

      Int32 aggregate2 = (Int32)((AliasedValue)c["opportunity_count"]).Value

       

      Bu işlem sonucunda bu koddan aşağıdaki gibi çıktımızı alabiliyoruz.

       

       

      Eğer distinct yapmak istersek de fetchXML içerisine yerleştireceğimiz bir distinct=”true” ifadesiyle ile sisteme bunu beliretebiliriz.

      Aşağıda ise distinct yapılmış bir kod örneği bulunmakta;

       

      <fetch distinct='false' mapping='logical' aggregate='true'>

        <entity name='opportunity'>

          <attribute name='name' alias='opportunity_distcount' aggregate='countcolumn' distinct='true'/>

        </entity>

      </fetch>

       

      Bu FetxhXML’i de aşağıdaki kodla çalıştırabiliriz.

       

                      string opportunity_distcount = @"

                                                 <fetch distinct='false' mapping='logical' aggregate='true'>

                                                     <entity name='opportunity'>

                                                        <attribute name='name' alias='opportunity_distcount' aggregate='countcolumn' distinct='true'/>

                                                     </entity>

                                                 </fetch>";

       

                      EntityCollection opportunity_distcount_result = ServiseBaglan().RetrieveMultiple(new FetchExpression(opportunity_distcount));

       

                      foreach (var c in opportunity_distcount_result.Entities)

                      {

                          Int32 aggregate4 = (Int32)((AliasedValue)c["opportunity_distcount"]).Value;

                          System.Console.WriteLine("Distinct name count of all opportunities: " + aggregate4);

                      }

       

                      Console.ReadLine();

       

      Bu kod sonucunda da aşağıdaki gibi bir cevap alabiliriz sistemden;


       

      Gelin olayı biraz renklendirelim. Bu sefer de bir sorgu içerisinde birden fazla aggregate seçeneğinin cevabını isteyelim. Böyle bir işlem için standart fetchXML’in içerisinde sırasıyla hangi özelliklerin bize geri döneceğini belirtiyoruz tabii unutulmaması gereken nokta ise hepsi için ayrı birer alias olması gerektiğidir.

       

      <fetch distinct='false' mapping='logical' aggregate='true'>

        <entity name='opportunity'>

          <attribute name='opportunityid' alias='opportunity_count' aggregate='count'/>

          <attribute name='estimatedvalue' alias='estimatedvalue_sum' aggregate='sum'/>

          <attribute name='estimatedvalue' alias='estimatedvalue_avg' aggregate='avg'/>

        </entity>

      </fetch>

       

      Bu sorgu için ise aşağıdaki kodu hazırladım;

       

                      string estimatedvalue_avg2 = @"

                                          <fetch distinct='false' mapping='logical' aggregate='true'>

                                              <entity name='opportunity'>

                                                 <attribute name='opportunityid' alias='opportunity_count' aggregate='count'/>

                                                 <attribute name='estimatedvalue' alias='estimatedvalue_sum' aggregate='sum'/>

                                                 <attribute name='estimatedvalue' alias='estimatedvalue_avg' aggregate='avg'/>

                                              </entity>

                                          </fetch>";

       

                      EntityCollection estimatedvalue_avg2_result = ServiseBaglan().RetrieveMultiple(new FetchExpression(estimatedvalue_avg2));

       

                      foreach (var c in estimatedvalue_avg2_result.Entities)

                      {

                          Int32 aggregate8a = (Int32)((AliasedValue)c["opportunity_count"]).Value;

                          System.Console.WriteLine("Count of all opportunities: " + aggregate8a);

                          decimal aggregate8b = ((Money)((AliasedValue)c["estimatedvalue_sum"]).Value).Value;

                          System.Console.WriteLine("Sum of estimated value of all opportunities: " + aggregate8b);

                          decimal aggregate8c = ((Money)((AliasedValue)c["estimatedvalue_avg"]).Value).Value;

                          System.Console.WriteLine("Average of estimated value of all opportunities: " + aggregate8c);

       

                      }

       

                      Console.ReadLine();

       

      İşte bu şekilde aynı anda count, sum ve avg işlemlerini yapabilmekteyim. Sonuç ise aşağıdaki gibi;

       

       

      Bu iki makalede FetchXML’ler üzerinde konuştuk. Umarım faydalı olmuştur.

      Microsoft Dynamics CRM 2013 İle Veri Sorgulama Yöntemleri

      Giriş
      Bu yazı dizimizde sizlere Dynamics CRM’den veri çekmek için kullanabileceğiniz yapıları anlatacağım. FetchXML ile veri çekmek bence şu anda kullanılabilecek en pratik yöntem ama bunun haricinde .Net Language-Integrated Query(LINQ) ile early ve late binding türler üzerinden veri çekebileceğiniz gibi Dynamics CRM’in Query Expression mimarisini kullanarak da veri çekebilirsiniz.

      Bu üçü haricinde OData ve Filtered View’ları kullanarak da veri çekebilirsiniz. OData(Open Data Protocol) Rest tabanlı servisler için protokol görevi gören bir veritabanı sorgulama yapısıdır. Filtered View’lar ise standart SQL ile SQL Server üzerinden direkt veri çekmek için kullanabileceğimiz yapılar ama Filtered View ve OData ile geriye CRM obje sınıflarıyla veri döndürememekteyiz. Yani SQL ile bir veri çektiğinizde DataSet ya da DataTable gibi yapılara veriyi çekebiliriz ama FetchXML ile CRM entity sınıfından geriye dönüş alırız bu yüzden kullanım açısından ilk yöntem daha kullanışlıdır.

      LINQ ile veriler üzerinde işlem yapabilmek için Organization Service Context sınıfını türetip projeye eklemek gerekmektedir.

      Benzerliklerini bir tablo üzerinde karşılaştırırsak;

      Sorgu Biçimi

      Özellikleri

      FetchXML

      QueryExpression'ın bütün özelliklerine destek verdiği gibi matematiksel işlemler ve gruplamaya da destek verir. Sorgular XML standartlarına göre yazılır.

      QueryExpression

      Sorgular bir obje modeli üzerinde icra edilir.

      LINQ

      QueryExpression'ın limitleriyle sınırlıdır.

       

      Yetenekleri bakımından karşılaştırırsak;

       

      Odata

      QueryExpression

      FetchXML

      LINQ

      Filtered Views

      Create, Update, Delete desteği

      X

       

       

      X

       

      Sorgu sonucu kayıtları döndürme

      X

      X

      X

      X

      X

      Rapor yaparken kullanılabilirlik

       

       

      X

       

      X

      Sorgu sonucu birden fazla türde kayıt döndürme

      X

      X

      X

      X

      X

      outer joins yapabilme

      X

       

      X

       

      X

      Çalışma zamanında doğrulama

       

      X

       

      X

       

      İlişkisiz nesneleri bağlama (Union)

       

       

       

      X

      X

      Matematiksel İşlemleri destekleme

      X (Sınırlı)

       

      X

      X

      X

       

      FetchXML

      FetchXML en güzel tarafı Dynamics CRM içerisinde Gelişmiş Ara (Advanced Find) ile oluşturduğumuz sorguların da bu şekilde sistemde kaydedilmesi. Ayrıca bu şekilde oluşturduğumuz sorguları da .xml olarak CRM’den alabiliyoruz böylece yazdığımız uygulama ya da rapor içerisinde de kullanabilmekteyiz. Böylece uzun uzun FecthXML hazırlamak yerine sistemin nimetlerinden yararlanarak sorgumuzu hazırlayabilmekteyiz. Bunun için gelişmiş bul içerisinde Fetch XML indir düğmesine tıklıyoruz.



      CRM’de de bu kullanıcı sorguları userquery, organizasyon sorguları ise savedquery içerisinde saklanmaktadır.

      IOrganizationService.RetrieveMultiple methodu ile FetchXML sorgulaması yapabilmekteyiz bunun için FetchXMLToQueryExpressionRequest mesajını kullanmak gerekmektedir. Ayrıca daha önce de belirttiğim gibi aggregations yani sum, max, min, count gibi matematiksel işlemleri de FetchXML ile yapabilmekteyiz.

      Bu makaledeki örneklerde CRM Servisini çağırmak daha önceki Singleton Tasarım Deseni üzerinden geliştirdiğim servise bağlanma metodunu kullanıyorum. Sözünü ettiğim makaleye buradan ulaşabilirsiniz.  Bu noktayı siz de kendinize uygun olarak değiştirebilirsiniz.

      Sorguyu Hazırlama

      Bu noktada örnek bir fetchXML’i inceleyelim;

      <fetch mapping='logical'>

        <entity name='account'>

          <all-attributes/>

        </entity>

      </fetch>

      FetchXML mutalaka “fetch” kelimeleri arasında yer almalı. Sonrasında ise “entity” kelimesi ile geri dönecek nesnenin türünü söylüyoruz. Sonrasında ise hangi alanların geri döneceğini ve nasıl koşullar olacağını belirtiyoruz. Tabii yukarıdaki örnekte bunlar yok “all-attributes” ile biz bütün alanları geri döndür diyoruz.

      Size bu sorguyu SQL ile anlatmam gerekirse : “select * from account” şeklinde olacak. Şimdi işi biraz daha renklendirelim;

       

      <fetch mapping='logical'>

        <entity name='contact'>

          <attribute name='fullname'/>

          <attribute name='createdon'/>

          <filter type='and'>

            <condition attribute='jobtitle' operator='eq' value='Purchasing Assistant'/>

          </filter>

        </entity>

      </fetch>

       

      Bu sorguda ise geriye contact yani ilgili kişi nesnesi geri dönecek ama sadece “fullname” ve “createdon” alanları ile. Ayrıca burada bir kriterimiz de var “jobtitle” alanı “Purchasing Assistant” olacak kayıtları alıyoruz. Yani yine SQL ile anlatırsam : “select fullname, createdon from contact where jobtitle='Purchasing Assistant'” Burada dikkat ettiyseniz operatör diye bir ifade yer almakta. Sorgulama yaparken değerlerin nasıl koşullarda alınması gerektiğini burada belirtiyoruz. Yani aşağıdaki tabloda da görebileceğiniz üzere sorgu ifadeleri kısmında "Koşul İfadesi" kısmında yazan değerler bizim normal sql cümlesinde kullandığımız ifadelere benzemektedir. Tek fark "=","<",">" gibi ifadelerin yerlerine "eq","gt","lt"gibi text bazlı ifadelerin gelmiş olmasıdır. 

       

      Koşul

      Koşul İfadesi

      Değer

      equals x

      eq

      x

      does not equal x

      ne

      x

      is greater than x

      gt

      x

      is greater than or equal to x

      ge

      x

      is less than x

      lt

      x

      is less than or equal to x

      le

      x

      begins with x

      like

      x%

      does not begin with x

      not-like

      x%

      ends with x

      like

      %x

      does not end with x

      not-like

      %x

      contains x

      like

      %x%

      does not contain x

      not-like

      %x%

      exists

      not-null

       

      does not exist

      null

       

      anytime

      not-null

       

      yesterday

      yesterday

       

      today

      today

       

      tomorrow

      tomorrow

       

      in next 7 days

      next-seven-days

       

      in last 7 days

      last-seven-days

       

      next week

      next-week

       

      last week

      last-week

       

      this week

      this-week

       

      this month

      this-month

       

      last month

      last-month

       

      next month

      next-month

       

      this year

      this-year

       

      next year

      next-year

       

      last year

      last-year

       

      on x

      on

      x

      on or after x

      on-or-after

      x

      on or before x

      on-or-before

      x

      in between

      between

       

      not between

      not-between

       

      in

      in

       

      not in

      not-in

       

      equals user id

      eq-userid

       

      does not equal user id

      ne-userid

       

      equals business id

      eq-businessid

       

      does not equal business id

      ne-businessid

       

       

       

      Sorguyu Çalıştırma

       

      Bu  sorguyu çalıştırcak metod ise RetrieveMultiple metodudur ve servisi örneklediğimizde karşımıza çaıkmaktadır. Bu metod makalenin başında bahsettiğim QueryExpression sınıfını da alarak işlem yapabilmektedir. Bu metodun bir de kardeşi vardır ve hazır yeri gelmişken bundan da bahsedeyim.

       

      Retrieve Metodu ID’si verilen entity nesnesinin bildirdiğiniz sütünlarını bize geri döndürür.  Kullanımı çok basit olan bu metod geriye Entity türünden bir nesne döndürür. Bu nesne zaten bizim parametre olarak verdiğimiz nesne adının kendisidir ve bizim belirttiğimiz sutünları doldurarak getirir. Bu metod aslında sql cümlesi olarak bakarsak “ select alanisimleri from (nesne)entity where entityid = '...' ” işlemini yerine getirmektedir.

      Aşağıdaki örnekle devam edelim;

      Entity slead = servis.Retrieve("lead", new Guid("7bE545CCD3-9A3A-E011-BA8B-78E7D1623F9D"), new ColumnSet(new string [] { "fullname", "companyname" }));

       

      foreach (var item in slead.Attributes)

      {

          Console.WriteLine(item.Key + ":" + item.Value);

      }

       

      Eğer entity’nin bütün alanlarını geri döndürmek istiyorsak new ColumnSet(true) komutunu ColumnSet yerine vermemiz gerekmektedir. Yani eğer siz sorgulayacağımız nesnenin GUID türünden idsini biliyorsanız ve join gibi işlemlerle işiniz yoksa düz mantıkta bir sorgulama yapmak için bu metodu kullanabilirsiniz.

       

      RetrieveMultiple Metodu ise gerçek anlamda karışık sorguları yapmamıza olanak tanır. Ama burada tamamen object oriented bir mimari söz konusudur yani temelde bir sorgulama cümlesi olmadan QueryExpression ya da QueryByAttribute sınıflarının örnekleri üzerinden sorgulama işlemi yapılmasına da olanak sağlar.

       

      Bizim odak konumuz ise fetchXML olduğu için konuyu fazla dağıtmadan devam edelim.

      Bu fetchXML sorgusunu çalıştırmak için ise şu şekilde bir kod yazdım;

       

      string fetchXml = @"<fetch mapping='logical'>

                                       <entity name='contact'>

                                          <attribute name='fullname'/>

                                          <attribute name='createdon'/>

                                           <filter type='and'>

                                              <condition attribute='jobtitle' operator='eq' value='Purchasing Assistant'/>

                                           </filter>

                                       </entity>

                                   </fetch>";

       

       

                      EntityCollection contactlist = (EntityCollection)ServiseBaglan().RetrieveMultiple(new FetchExpression(fetchXml));

                      foreach (var cnt in contactlist.Entities)

                      {

                          Console.WriteLine(cnt.Attributes["fullname"].ToString() + ":" + cnt.Attributes["createdon"].ToString());

                      }

       

                      Console.ReadLine();

       

      Sorgu Sonucu

       

      İşte biraz önce bahsettiğim RetrieveMultiple metoduna fetchXML’i veriyorum. Dönüşte ise sistem bana EntityCollection içerisinde talep ettğim entity’i vermekte. Bu noktadan sonra foreach ile bütün kayıtar içinde dolaşabilir ve Attributes ile alanlara ulaşabilirim.

       

      Bu kodu çalıştırınca da aşağıdaki gibi sonucu almaktayım;

       

      İleri Seviye Sorgular

       

      Yukarıda temel bilgileri verdikten sonra ileri seviye bilgilerle buradan devam edebiliriz.

       

      <fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>

        <entity name='lead'>

          <attribute name='fullname' />

          <attribute name='createdon' />

          <filter type='and'>

            <condition attribute='ownerid' operator='eq-userid' />

            <condition attribute='statecode' operator='eq' value='0' />

          </filter>

        </entity>

      </fetch>

       

      Bu sorguda ise “lead” türünden nesneleri geri döndürmekteyiz. “fullname” ve “createdon” alanlarını istemekteyiz sorgu ile ama “ownerid” yani kayıtların sahibi “eq-userid” diyerek servise kim bağlandıysa onun kayıtları olacak ve durumları da aktif olacak.

       

      Düz mantıktaki tek bir nesne üzerinden sorgular işte bu şekilde yapılmakta ama sistem bundan daha fazlasına izin verebilmekte yani biz eğer istersek inner ya da outer join yaparak başka nesneler ile de ilişki içerisindeki kayıtları da geriye döndürebiliriz. Aşağıdaki örnek üzerinden açıklamaya çalışayım;

       

      <fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>

        <entity name='account'>

          <attribute name='name' />

          <attribute name='address1_city' />

          <attribute name='telephone1' />

          <order attribute='name' descending='true' />

          <filter type='and'>

            <condition attribute='name' operator='like' value='{0}%' />

          </filter>

          <link-entity name='contact' from='contactid' to='primarycontactid' alias='kisi'>

            <attribute name='emailaddress1' />

            <filter type='and'>

              <condition attribute='firstname' operator='like' value='{0}%' />

            </filter>

          </link-entity>

          <link-entity name='systemuser' from='systemuserid' to='createdby' visible='false' link-type='outer' alias='kullanici'>

            <attribute name='firstname' />

          </link-entity>

        </entity>

      </fetch>

       

      Burada temelde yine bir nesne üzerinde yani “account” nesnesi üzerinden hareket ediyor gibi gözüksek de “link-entity” düğümleriyle işi genişletiyoruz. Örnekte görebileceğiniz üzere “contact” ve “systemuser” nesneleri üzerinden de geriye alan döndürdüğümüz gibi bunlar üzerinden de sorgulama yapabilmekteyiz. “link-entity” içerisinde sisteme hangi nesne ile link yapacağımızı ve bu nesnelerin hangi alanlar üzerinde birbirleriyle ilişki içerisinde olduklarını söylemekteyiz. Ayrıca “alias” vererek de kodun ilerleyen kısımlarında buradan gelecek alanlar için bir tanımlayıcı da oluşturabilmekteyiz.

       

      Burada ben “link-type” olarak “outer” kullandım ama siz isterseniz “inner join” yapmak için “inner” de kullanabilirsiniz.

       

      Bu arada belirtmeliyim ki “order” komutu ile de belli bir alan üzerinden kayıtların “ascending” ya da “descending” olarak sıralanmasını da sağlayabilmekteyiz.

       

      Örnekte ben firma adı ve kişi adı için konsoldan parametre almaktayım bu yüzden orada “{0}” ifadesini görmektesiniz.

       

      Bu sorguyu daha raht anlamanız için SQL cümlesine çevirecek olursam;

       

      select name, address1_city, telephone1, kisi.emailaddress1, kullanici.firstname from account inner join contact kisi on kisi.contactid = account.primarycontactid

      inner join systemuser kullanici on kullanici.systemuserid = account.createdby

      where account.name like '%%' and kisi.firstname like '%%'

      order by account.name desc

       

      Böyle bir sorgu yazmamız gerekirdi. Bu kodu çalıştıracak örnek uygulama ise şu şekilde;

       

      string fetch = @"

                                         <fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>

                                        <entity name='account'>

                                          <attribute name='name' />

                                          <attribute name='address1_city' />

                                          <attribute name='telephone1' />

                                          <order attribute='name' descending='true' />

                                          <filter type='and'>

                                            <condition attribute='name' operator='like' value='{0}%' />

                                          </filter>

                                          <link-entity name='contact' from='contactid' to='primarycontactid' alias='kisi'>

                                            <attribute name='emailaddress1' />

                                            <filter type='and'>

                                              <condition attribute='firstname' operator='like' value='{0}%' />

                                            </filter>

                                          </link-entity>

                                          <link-entity name='systemuser' from='systemuserid' to='createdby' visible='false' link-type='outer' alias='kullanici'>

                                            <attribute name='firstname' />

                                          </link-entity>

                                        </entity>

                                      </fetch>";

       

                      Console.WriteLine("bir karakter yazın:");

                      fetch = string.Format(fetch, Console.ReadLine());

       

                      EntityCollection groupby1_result = ServiseBaglan().RetrieveMultiple(new FetchExpression(fetch));

       

                      foreach (var c in groupby1_result.Entities)

                      {

                          Console.WriteLine("ad:" + c["name"].ToString());

                          Console.WriteLine("sehir:" + c["address1_city"].ToString());

                          Console.WriteLine("telefon:" + c["telephone1"].ToString());

                          Console.WriteLine("kisi eposta:" + ((AliasedValue)c["kisi.emailaddress1"]).Value.ToString());

                          Console.WriteLine("kullanici:" + ((AliasedValue)c["kullanici.firstname"]).Value.ToString());

                          Console.WriteLine("\n");

                      }

       

       

                      Console.ReadLine();

      Burada bir noktanın üzerinde durmamız gerekmekte. Kişi ve Kullanıcı üzerindeki alanlardan veri alabilmek için “kisi” ve “kullanici” isimli alias’ları kullanmıştık. İşte bu alanlardan veri okuyacağımız zaman şu şekilde bir kullanıma ihtiyacımız bulunmakta;

       

      ((AliasedValue)c["kullanici.firstname"]).Value.ToString()

       

      Yani gelen değeri önce “AliasedValue”’e parse etmemiz sonrasında ise “Value” üzerinden değerini almalıyız.

       

      Çıktımız ise şu şekilde. Yani adı “a” ile başlayan bir firma ve ona adı “a” ile başlayan birinci ilgili kişi kaydı olarak eklenmiş bir kayıt bulunmakta.

       


       

      Eğer XSD dosyalarını okumayı biliyorsanız fetchXML üzerinde nereye hangi değerlerin nasıl gelebileceğini anlayabilirsiniz. Ayrıca bunu dosya haline getirerek Visual Studio’ya tanıtırsanız fetchXML yazarken denetleme yaparak size hataları da gösterecektir. Ama şu anda en güzel fetchXML oluşturma yöntemi daha önce de belirttiğim gibi Gelişmiş Ara aracını kullanmaktır.

       

      <?xml version="1.0" encoding="utf-8" ?>

      <xs:schema id="fetch" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"

      xmlns:mstns="http://tempuri.org/fetch/unique">

        <xs:annotation>

          <xs:documentation>Schema name: fetch-schema</xs:documentation>

        </xs:annotation>

        <!--

       

      condition element - used for capturing entity and link-entity

      "where" clause criteria

       

      -->

        <!-- [XDR-XSD] "value" element  -->

        <xs:element name="value" type="xs:string"></xs:element>

        <!-- [XDR-XSD] "condition" element  -->

        <xs:element name="condition">

          <xs:complexType>

            <xs:choice minOccurs="0" maxOccurs="unbounded">

              <!-- -->

              <!--

      The attribute "value" is used for all operators that compare to a single value (for example, eq).

      The element "value" is used for operators that compare to multiple values (for example, in).

      Some operators require neither the attribute "value" or the element "value" (for example, null).

      -->

              <xs:element name="value" minOccurs="0" maxOccurs="unbounded">

                <xs:complexType>

                  <xs:simpleContent>

                    <xs:extension base="xs:string">

                      <xs:attribute name="uiname" type="xs:string" />

                      <xs:attribute name="uitype" type="xs:string" />

                    </xs:extension>

                  </xs:simpleContent>

                </xs:complexType>

              </xs:element>

            </xs:choice>

            <!-- -->

            <xs:attribute name="column" type="xs:string" />

            <xs:attribute name="attribute" type="xs:string"></xs:attribute>

            <xs:attribute name="entityname" type="xs:string"></xs:attribute>

            <xs:attribute name="operator" use="required" type="operator"></xs:attribute>

            <!--

      The attribute "value" is used for all operators that compare to a single value (for example, eq).

      The element "value" is used for operators that compare to multiple values (for example, in).

      Some operators require neither the attribute "value" or the element "value" (for example, null).

      -->

            <xs:attribute name="value" type="xs:string"></xs:attribute>

            <xs:attribute name="aggregate" type="AggregateType"></xs:attribute>

            <xs:attribute name="alias" type="xs:string"></xs:attribute>

            <xs:attribute name="uiname" />

            <xs:attribute name="uitype" />

            <xs:attribute name="uihidden" type="TrueFalse01Type" />

          </xs:complexType>

        </xs:element>

        <!--

       

      filter element - used for constructing complex conditionals

       legal on entity and link-entity

       

      -->

        <!-- [XDR-XSD] "filter" element  -->

        <xs:element name="filter">

          <xs:complexType>

            <xs:choice minOccurs="0" maxOccurs="unbounded">

              <!-- -->

              <xs:element ref="condition" minOccurs="0" maxOccurs="500" />

              <xs:element ref="filter" minOccurs="0" maxOccurs="unbounded" />

            </xs:choice>

            <!-- -->

            <xs:attribute name="type" default="and">

              <xs:simpleType>

                <xs:restriction base="xs:NMTOKEN">

                  <xs:enumeration value="and" />

                  <xs:enumeration value="or" />

                </xs:restriction>

              </xs:simpleType>

            </xs:attribute>

            <xs:attribute name="isquickfindfields" type="xs:boolean" />

          </xs:complexType>

        </xs:element>

        <!--

       

      attribute elements - used for selecting attributes from the

       surrounding entity / link-entity, these

       values are returned as part of the fetch

       

      -->

        <!-- [XDR-XSD] "all-attributes" element  -->

        <xs:element name="all-attributes">

          <xs:complexType></xs:complexType>

        </xs:element>

        <!-- [XDR-XSD] "attribute" element  -->

        <xs:complexType name="FetchAttributeType">

          <xs:attribute name="name" use="required" type="xs:string"></xs:attribute>

          <xs:attribute name="build" type="build"></xs:attribute>

          <xs:attribute name="addedby" type="xs:string" />

          <xs:attribute name="alias" type="xs:string"></xs:attribute>

          <xs:attribute name="aggregate" type="AggregateType"></xs:attribute>

          <xs:attribute name="groupby" type="FetchBoolType"></xs:attribute>

          <xs:attribute name="dategrouping" type="DateGroupingType"></xs:attribute>

          <xs:attribute name="usertimezone" type="FetchBoolType"></xs:attribute>

        </xs:complexType>

        <!--

       

      order element - used to specify a sort order

       

      -->

        <!-- [XDR-XSD] "order" element  -->

        <xs:complexType name="FetchOrderType">

          <xs:choice minOccurs="0" maxOccurs="unbounded">

            <!-- -->

          </xs:choice>

          <!-- -->

          <xs:attribute name="attribute" type="xs:string"></xs:attribute>

          <xs:attribute name="alias" type="xs:string"></xs:attribute>

          <xs:attribute name="descending" default="false" type="xs:boolean"></xs:attribute>

        </xs:complexType>

        <!--

       

      link-entity element - used for joining one entity to its "parent"

       

      -->

        <!-- [XDR-XSD] "link-entity" element  -->

        <xs:complexType name="FetchLinkEntityType">

          <xs:choice minOccurs="0" maxOccurs="unbounded">

            <!-- -->

            <xs:element ref="all-attributes" minOccurs="0" />

            <xs:element name="attribute" type="FetchAttributeType" minOccurs="0" maxOccurs="unbounded" />

            <xs:element name="order" type="FetchOrderType" minOccurs="0" maxOccurs="1" />

            <xs:element ref="filter" minOccurs="0" />

            <xs:element name="link-entity" type="FetchLinkEntityType" />

          </xs:choice>

          <!-- -->

          <xs:attribute name="name" use="required" type="xs:string"></xs:attribute>

          <xs:attribute name="to" type="xs:string"></xs:attribute>

          <xs:attribute name="from" type="xs:string"></xs:attribute>

          <xs:attribute name="alias" type="xs:string"></xs:attribute>

          <xs:attribute name="link-type" type="xs:string"></xs:attribute>

          <xs:attribute name="visible" type="xs:boolean"></xs:attribute>

          <xs:attribute name="intersect" type="xs:boolean"></xs:attribute>

        </xs:complexType>

        <!--

       

      entity element - used for specifying the root element for a fetch, only

       one root entity is allowed in a given fetch, all others

       are dependent on this entity and are marked as

       link-entity

       

      -->

        <!-- [XDR-XSD] "entity" element  -->

        <xs:complexType name="FetchEntityType">

          <xs:choice minOccurs="0" maxOccurs="unbounded">

            <!-- -->

            <xs:element ref="all-attributes" minOccurs="0" />

            <xs:element name="attribute" type="FetchAttributeType" minOccurs="0" maxOccurs="unbounded" />

            <xs:element name="order" type="FetchOrderType" minOccurs="0" maxOccurs="unbounded" />

            <xs:element name="link-entity" type="FetchLinkEntityType" />

            <xs:element ref="filter" minOccurs="0" />

          </xs:choice>

          <!-- -->

          <xs:attribute name="name" use="required" type="xs:string"></xs:attribute>

        </xs:complexType>

        <!--

       

      fetch element - root element for the query

       

      -->

        <!-- [XDR-XSD] "fetch" element  -->

        <xs:element name="fetch" type="FetchType"/>

        <xs:complexType name="FetchType">

          <xs:choice minOccurs="0" maxOccurs="unbounded">

            <!-- -->

            <xs:element name="entity" type="FetchEntityType" />

            <!-- This is for the Reports view only -->

            <xs:element name="order" type="FetchOrderType" minOccurs="1" maxOccurs="1" />

          </xs:choice>

          <!-- -->

          <xs:attribute name="version"/>

          <xs:attribute name="count" type="xs:integer"/>

          <xs:attribute name="page" type="xs:integer"/>

          <xs:attribute name="paging-cookie" type="xs:string"/>

          <xs:attribute name="utc-offset" type="IntOrEmpty"/>

          <xs:attribute name="aggregate" type="xs:boolean"/>

          <xs:attribute name="distinct" type="xs:boolean"/>

          <xs:attribute name="top" type="xs:integer"/>

          <xs:attribute name="mapping">

            <xs:simpleType>

              <xs:restriction base="xs:NMTOKEN">

                <xs:enumeration value="internal" />

                <xs:enumeration value="logical" />

              </xs:restriction>

            </xs:simpleType>

          </