/* * * (c) Copyright Ascensio System Limited 2010-2018 * * This program is freeware. You can redistribute it and/or modify it under the terms of the GNU * General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html). * In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that * Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights. * * THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html * * You can contact Ascensio System SIA by email at sales@onlyoffice.com * * The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display * Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3. * * Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains * relevant author attributions when distributing the software. If the display of the logo in its graphic * form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE" * in every copy of the program you distribute. * Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks. * */ using ASC.Api.Collections; using ASC.Api.Core; using ASC.Api.CRM.Wrappers; using ASC.Common.Web; using ASC.Core; using ASC.Core.Users; using ASC.CRM.Core; using ASC.CRM.Core.Entities; using ASC.CRM.Core.Enums; using ASC.MessagingSystem; using ASC.Web.Api.Models; using ASC.Web.Api.Routing; using ASC.Web.CRM.Classes; using ASC.Web.Files.Services.WCFService; using System; using System.Collections.Generic; using System.Linq; namespace ASC.Api.CRM { public partial class CRMController { /// /// Returns the detailed information about the opportunity with the ID specified in the request /// /// Opportunity ID /// /// Opportunity /// /// Get opportunity by ID /// Opportunities /// /// [Read(@"opportunity/{opportunityid:int}")] public OpportunityWrapper GetDealByID(int opportunityid) { if (opportunityid <= 0) throw new ArgumentException(); var deal = DaoFactory.GetDealDao().GetByID(opportunityid); if (deal == null || !CRMSecurity.CanAccessTo(deal)) throw new ItemNotFoundException(); return ToOpportunityWrapper(deal); } /// /// Updates the selected opportunity to the stage with the ID specified in the request /// /// Opportunity ID /// Opportunity stage ID /// /// Opportunity /// /// Update opportunity stage /// Opportunities /// /// [Update(@"opportunity/{opportunityid:int}/stage/{id:int}")] public OpportunityWrapper UpdateToDealMilestone(int opportunityid, int stageid) { if (opportunityid <= 0 || stageid <= 0) throw new ArgumentException(); var deal = DaoFactory.GetDealDao().GetByID(opportunityid); if (deal == null || !CRMSecurity.CanEdit(deal)) throw new ItemNotFoundException(); var stage = DaoFactory.GetDealMilestoneDao().GetByID(stageid); if (stage == null) throw new ItemNotFoundException(); deal.DealMilestoneID = stageid; deal.DealMilestoneProbability = stage.Probability; deal.ActualCloseDate = stage.Status != DealMilestoneStatus.Open ? DateTime.UtcNow : DateTime.MinValue; DaoFactory.GetDealDao().EditDeal(deal); MessageService.Send( MessageAction.OpportunityUpdatedStage, MessageTarget.Create(deal.ID), deal.Title); return ToOpportunityWrapper(deal); } /// /// Sets access rights for the selected opportunity with the parameters specified in the request /// /// Opportunity ID /// Opportunity privacy: private or not /// List of users with access /// Set rights to opportunity /// Opportunities /// /// /// /// Opportunity /// [Update(@"opportunity/{opportunityid:int}/access")] public OpportunityWrapper SetAccessToDeal(int opportunityid, bool isPrivate, IEnumerable accessList) { if (opportunityid <= 0) throw new ArgumentException(); var deal = DaoFactory.GetDealDao().GetByID(opportunityid); if (deal == null) throw new ItemNotFoundException(); if (!(CRMSecurity.IsAdmin || deal.CreateBy == SecurityContext.CurrentAccount.ID)) throw CRMSecurity.CreateSecurityException(); return SetAccessToDeal(deal, isPrivate, accessList, false, true); } private OpportunityWrapper SetAccessToDeal(Deal deal, bool isPrivate, IEnumerable accessList, bool isNotify, bool isMessageServicSende) { var accessListLocal = accessList != null ? accessList.Distinct().ToList() : new List(); if (isPrivate && accessListLocal.Count > 0) { if (isNotify) { accessListLocal = accessListLocal.Where(u => u != SecurityContext.CurrentAccount.ID).ToList(); NotifyClient.SendAboutSetAccess(EntityType.Opportunity, deal.ID, DaoFactory, accessListLocal.ToArray()); } if (!accessListLocal.Contains(SecurityContext.CurrentAccount.ID)) { accessListLocal.Add(SecurityContext.CurrentAccount.ID); } CRMSecurity.SetAccessTo(deal, accessListLocal); if (isMessageServicSende) { var users = GetUsersByIdList(accessListLocal); MessageService.Send( MessageAction.OpportunityRestrictedAccess, MessageTarget.Create(deal.ID), deal.Title, users.Select(x => x.DisplayUserName(false))); } } else { CRMSecurity.MakePublic(deal); if (isMessageServicSende) { MessageService.Send( MessageAction.OpportunityOpenedAccess, MessageTarget.Create(deal.ID), deal.Title); } } return ToOpportunityWrapper(deal); } /// /// Sets access rights for other users to the list of all opportunities matching the parameters specified in the request /// /// Opportunity responsible /// Opportunity stage ID /// Tags /// Contact ID /// Participation status: take into account opportunities where the contact is a participant or not /// Start date /// End date /// Opportunity stage type /// Opportunity privacy: private or not /// List of users with access /// Set opportunity access rights /// Opportunities /// /// /// /// Opportunity list /// [Update(@"opportunity/filter/access")] public IEnumerable SetAccessToBatchDeal( Guid responsibleid, int opportunityStagesid, IEnumerable tags, int contactid, DealMilestoneStatus? stageType, bool? contactAlsoIsParticipant, ApiDateTime fromDate, ApiDateTime toDate, bool isPrivate, IEnumerable accessList ) { var result = new List(); var deals = DaoFactory.GetDealDao() .GetDeals(ApiContext.FilterValue, responsibleid, opportunityStagesid, tags, contactid, stageType, contactAlsoIsParticipant, fromDate, toDate, 0, 0, null); if (!deals.Any()) return Enumerable.Empty(); foreach (var deal in deals) { if (deal == null) throw new ItemNotFoundException(); if (!(CRMSecurity.IsAdmin || deal.CreateBy == SecurityContext.CurrentAccount.ID)) continue; SetAccessToDeal(deal.ID, isPrivate, accessList); result.Add(deal); } return ToListOpportunityWrapper(result); } /// /// Sets access rights for other users to the list of opportunities with the IDs specified in the request /// /// Opportunity ID list /// Opportunity privacy: private or not /// List of users with access /// Set opportunity access rights /// Opportunities /// /// /// /// Opportunity list /// [Update(@"opportunity/access")] public IEnumerable SetAccessToBatchDeal(IEnumerable opportunityid, bool isPrivate, IEnumerable accessList) { if(opportunityid == null) throw new ArgumentException(); var result = new List(); var deals = DaoFactory.GetDealDao().GetDeals(opportunityid.ToArray()); if (!deals.Any()) return new List(); foreach (var d in deals) { if (d == null) throw new ItemNotFoundException(); if (!(CRMSecurity.IsAdmin || d.CreateBy == SecurityContext.CurrentAccount.ID)) continue; SetAccessToDeal(d, isPrivate, accessList, false, true); result.Add(d); } return ToListOpportunityWrapper(result); } /// /// Deletes the group of opportunities with the IDs specified in the request /// /// Opportunity ID list /// /// /// Delete opportunity group /// Opportunities /// /// Opportunity list /// [Update(@"opportunity")] public IEnumerable DeleteBatchDeals(IEnumerable opportunityids) { if (opportunityids == null || !opportunityids.Any()) throw new ArgumentException(); var opportunities = DaoFactory.GetDealDao().DeleteBatchDeals(opportunityids.ToArray()); MessageService.Send( MessageAction.OpportunitiesDeleted, MessageTarget.Create(opportunityids), opportunities.Select(o => o.Title)); return ToListOpportunityWrapper(opportunities); } /// /// Deletes the list of all opportunities matching the parameters specified in the request /// /// Opportunity responsible /// Opportunity stage ID /// Tags /// Contact ID /// Participation status: take into account opportunities where the contact is a participant or not /// Start date /// End date /// Opportunity stage type /// /// /// Delete opportunity group /// Opportunities /// /// Opportunity list /// [Delete(@"opportunity/filter")] public IEnumerable DeleteBatchDeals( Guid responsibleid, int opportunityStagesid, IEnumerable tags, int contactid, DealMilestoneStatus? stageType, bool? contactAlsoIsParticipant, ApiDateTime fromDate, ApiDateTime toDate) { var deals = DaoFactory.GetDealDao().GetDeals(ApiContext.FilterValue, responsibleid, opportunityStagesid, tags, contactid, stageType, contactAlsoIsParticipant, fromDate, toDate, 0, 0, null); if (!deals.Any()) return Enumerable.Empty(); deals = DaoFactory.GetDealDao().DeleteBatchDeals(deals); MessageService.Send( MessageAction.OpportunitiesDeleted, MessageTarget.Create(deals.Select(x => x.ID)), deals.Select(d => d.Title)); return ToListOpportunityWrapper(deals); } /// /// Returns the list of all opportunities matching the parameters specified in the request /// /// Opportunity responsible /// Opportunity stage ID /// Tags /// Contact ID /// Participation status: take into account opportunities where the contact is a participant or not /// Start date /// End date /// Opportunity stage type /// Get opportunity list /// Opportunities /// /// Opportunity list /// [Read(@"opportunity/filter")] public IEnumerable GetDeals( Guid responsibleid, int opportunityStagesid, IEnumerable tags, int contactid, DealMilestoneStatus? stageType, bool? contactAlsoIsParticipant, ApiDateTime fromDate, ApiDateTime toDate) { DealSortedByType dealSortedByType; IEnumerable result; var searchString = ApiContext.FilterValue; OrderBy dealsOrderBy; if (Web.CRM.Classes.EnumExtension.TryParse(ApiContext.SortBy, true, out dealSortedByType)) { dealsOrderBy = new OrderBy(dealSortedByType, !ApiContext.SortDescending); } else if (string.IsNullOrEmpty(ApiContext.SortBy)) { dealsOrderBy = new OrderBy(DealSortedByType.Stage, true); } else { dealsOrderBy = null; } var fromIndex = (int)ApiContext.StartIndex; var count = (int)ApiContext.Count; if (dealsOrderBy != null) { result = ToListOpportunityWrapper(DaoFactory.GetDealDao().GetDeals( searchString, responsibleid, opportunityStagesid, tags, contactid, stageType, contactAlsoIsParticipant, fromDate, toDate, fromIndex, count, dealsOrderBy)).ToList(); ApiContext.SetDataPaginated(); ApiContext.SetDataFiltered(); ApiContext.SetDataSorted(); } else { result = ToListOpportunityWrapper(DaoFactory.GetDealDao().GetDeals( searchString, responsibleid, opportunityStagesid, tags, contactid, stageType, contactAlsoIsParticipant, fromDate, toDate, 0, 0, null)).ToList(); } int totalCount; if (result.Count() < count) { totalCount = fromIndex + result.Count(); } else { totalCount = DaoFactory .DealDao .GetDealsCount(searchString, responsibleid, opportunityStagesid, tags, contactid, stageType, contactAlsoIsParticipant, fromDate, toDate); } ApiContext.SetTotalCount(totalCount); return result.ToSmartList(); } /// /// Deletes the opportunity with the ID specified in the request /// /// Opportunity ID /// Delete opportunity /// Opportunities /// /// /// /// Opportunity /// [Delete(@"opportunity/{opportunityid:int}")] public OpportunityWrapper DeleteDeal(int opportunityid) { if (opportunityid <= 0) throw new ArgumentException(); var deal = DaoFactory.GetDealDao().DeleteDeal(opportunityid); if (deal == null) throw new ItemNotFoundException(); MessageService.Send( MessageAction.OpportunityDeleted, MessageTarget.Create(deal.ID), deal.Title); return ToOpportunityWrapper(deal); } /// /// Creates the opportunity with the parameters specified in the request /// /// Create opportunity /// Opportunity primary contact /// Participants /// Opportunity title /// Opportunity description /// Opportunity responsible /// Bid /// Amount of transaction /// Currency (Abbreviation) /// Period /// Stage ID /// Opportunity success probability /// Actual opportunity closure date /// Expected opportunity closure date /// User field list /// Opportunity privacy: private or not /// List of users with access to the opportunity /// Notify users in accessList about the opportunity /// Opportunities /// /// Opportunity /// /// [Create(@"opportunity")] public OpportunityWrapper CreateDeal( int contactid, IEnumerable members, string title, string description, Guid responsibleid, BidType bidType, decimal bidValue, string bidCurrencyAbbr, int perPeriodValue, int stageid, int successProbability, ApiDateTime actualCloseDate, ApiDateTime expectedCloseDate, IEnumerable> customFieldList, bool isPrivate, IEnumerable accessList, bool isNotify) { var deal = new Deal { Title = title, Description = description, ResponsibleID = responsibleid, BidType = bidType, BidValue = bidValue, PerPeriodValue = perPeriodValue, DealMilestoneID = stageid, DealMilestoneProbability = successProbability < 0 ? 0 : (successProbability > 100 ? 100 : successProbability), ContactID = contactid, ActualCloseDate = actualCloseDate, ExpectedCloseDate = expectedCloseDate, BidCurrency = !String.IsNullOrEmpty(bidCurrencyAbbr) ? bidCurrencyAbbr.ToUpper() : null, }; CRMSecurity.DemandCreateOrUpdate(deal); deal.ID = DaoFactory.GetDealDao().CreateNewDeal(deal); deal.CreateBy = SecurityContext.CurrentAccount.ID; deal.CreateOn = DateTime.UtcNow; SetAccessToDeal(deal, isPrivate, accessList, isNotify, false); var membersList = members != null ? members.ToList() : new List(); if (deal.ContactID > 0) membersList.Add(deal.ContactID); if (membersList.Any()) { var contacts = DaoFactory.GetContactDao().GetContacts(membersList.ToArray()).Where(CRMSecurity.CanAccessTo).ToList(); membersList = contacts.Select(m => m.ID).ToList(); DaoFactory.GetDealDao().SetMembers(deal.ID, membersList.ToArray()); } if (customFieldList != null) { var existingCustomFieldList = DaoFactory.GetCustomFieldDao().GetFieldsDescription(EntityType.Opportunity).Select(fd => fd.ID).ToList(); foreach (var field in customFieldList) { if (string.IsNullOrEmpty(field.Value) || !existingCustomFieldList.Contains(field.Key)) continue; DaoFactory.GetCustomFieldDao().SetFieldValue(EntityType.Opportunity, deal.ID, field.Key, field.Value); } } return ToOpportunityWrapper(deal); } /// /// Updates the selected opportunity with the parameters specified in the request /// /// Update opportunity ///Opportunity ID ///Opportunity primary contact /// Participants /// Opportunity title /// Opportunity description /// Opportunity responsible /// Bid /// Amount of transaction /// Currency (Abbreviation) /// Period /// Stage ID /// Opportunity success probability /// Actual opportunity closure date /// Expected opportunity closure date /// User field list /// Opportunity privacy: private or not /// List of users with access to the opportunity /// Notify users in accessList about the opportunity /// Opportunities /// /// Opportunity /// /// [Update(@"opportunity/{opportunityid:int}")] public OpportunityWrapper UpdateDeal( int opportunityid, int contactid, IEnumerable members, string title, string description, Guid responsibleid, BidType bidType, decimal bidValue, string bidCurrencyAbbr, int perPeriodValue, int stageid, int successProbability, ApiDateTime actualCloseDate, ApiDateTime expectedCloseDate, IEnumerable> customFieldList, bool isPrivate, IEnumerable accessList, bool isNotify) { var deal = DaoFactory.GetDealDao().GetByID(opportunityid); if (deal == null) throw new ItemNotFoundException(); deal.Title = title; deal.Description = description; deal.ResponsibleID = responsibleid; deal.BidType = bidType; deal.BidValue = bidValue; deal.PerPeriodValue = perPeriodValue; deal.DealMilestoneID = stageid; deal.DealMilestoneProbability = successProbability < 0 ? 0 : (successProbability > 100 ? 100 : successProbability); deal.ContactID = contactid; deal.ActualCloseDate = actualCloseDate; deal.ExpectedCloseDate = expectedCloseDate; deal.BidCurrency = !String.IsNullOrEmpty(bidCurrencyAbbr) ? bidCurrencyAbbr.ToUpper() : null; CRMSecurity.DemandCreateOrUpdate(deal); DaoFactory.GetDealDao().EditDeal(deal); deal = DaoFactory.GetDealDao().GetByID(opportunityid); var membersList = members != null ? members.ToList() : new List(); if (membersList.Any()) { var contacts = DaoFactory.GetContactDao().GetContacts(membersList.ToArray()).Where(CRMSecurity.CanAccessTo).ToList(); membersList = contacts.Select(m => m.ID).ToList(); DaoFactory.GetDealDao().SetMembers(deal.ID, membersList.ToArray()); } if (CRMSecurity.IsAdmin || deal.CreateBy == SecurityContext.CurrentAccount.ID) { SetAccessToDeal(deal, isPrivate, accessList, isNotify, false); } if (customFieldList != null) { var existingCustomFieldList = DaoFactory.GetCustomFieldDao().GetFieldsDescription(EntityType.Opportunity).Select(fd => fd.ID).ToList(); foreach (var field in customFieldList) { if (string.IsNullOrEmpty(field.Value) || !existingCustomFieldList.Contains(field.Key)) continue; DaoFactory.GetCustomFieldDao().SetFieldValue(EntityType.Opportunity, deal.ID, field.Key, field.Value); } } return ToOpportunityWrapper(deal); } /// /// Returns the list of all contacts associated with the opportunity with the ID specified in the request /// /// Opportunity ID /// Get all opportunity contacts /// Opportunities /// Contact list /// /// [Read(@"opportunity/{opportunityid:int}/contact")] public IEnumerable GetDealMembers(int opportunityid) { var opportunity = DaoFactory.GetDealDao().GetByID(opportunityid); if (opportunity == null || !CRMSecurity.CanAccessTo(opportunity)) throw new ItemNotFoundException(); var contactIDs = DaoFactory.GetDealDao().GetMembers(opportunityid); if (contactIDs == null) return new ItemList(); var result = ToListContactWrapper(DaoFactory.GetContactDao().GetContacts(contactIDs)).ToList(); result.ForEach(item => { if (item.ID == opportunity.ContactID) item.CanEdit = false; }); return result; } /// /// Adds the selected contact to the opportunity with the ID specified in the request /// /// Opportunity ID /// Contact ID /// Add opportunity contact /// Opportunities /// /// /// Participant /// [Create(@"opportunity/{opportunityid:int}/contact/{contactid:int}")] public ContactWrapper AddMemberToDeal(int opportunityid, int contactid) { if (opportunityid <= 0 || contactid <= 0) throw new ArgumentException(); var opportunity = DaoFactory.GetDealDao().GetByID(opportunityid); if (opportunity == null || !CRMSecurity.CanAccessTo(opportunity)) throw new ItemNotFoundException(); var contact = DaoFactory.GetContactDao().GetByID(contactid); if (contact == null || !CRMSecurity.CanAccessTo(contact)) throw new ItemNotFoundException(); var result = ToContactWrapper(contact); DaoFactory.GetDealDao().AddMember(opportunityid, contactid); var messageAction = contact is Company ? MessageAction.OpportunityLinkedCompany : MessageAction.OpportunityLinkedPerson; MessageService.Send( messageAction, MessageTarget.Create(opportunity.ID), opportunity.Title, contact.GetTitle()); return result; } /// /// Deletes the selected contact from the opportunity with the ID specified in the request /// /// Opportunity ID /// Contact ID /// Delete opportunity contact /// Opportunities /// /// /// /// Participant /// [Delete(@"opportunity/{opportunityid:int}/contact/{contactid:int}")] public ContactWrapper DeleteMemberFromDeal(int opportunityid, int contactid) { if ((opportunityid <= 0) || (contactid <= 0)) throw new ArgumentException(); var opportunity = DaoFactory.GetDealDao().GetByID(opportunityid); if (opportunity == null || !CRMSecurity.CanAccessTo(opportunity)) throw new ItemNotFoundException(); var contact = DaoFactory.GetContactDao().GetByID(contactid); if (contact == null || !CRMSecurity.CanAccessTo(contact)) throw new ItemNotFoundException(); var result = ToContactWrapper(contact); DaoFactory.GetDealDao().RemoveMember(opportunityid, contactid); var messageAction = contact is Company ? MessageAction.OpportunityUnlinkedCompany : MessageAction.OpportunityUnlinkedPerson; MessageService.Send( messageAction, MessageTarget.Create(opportunity.ID), opportunity.Title, contact.GetTitle()); return result; } /// /// Returns the list of 30 opportunities in the CRM module with prefix /// /// /// /// /// Opportunities /// /// Opportunities list /// /// false [Read(@"opportunity/byprefix")] public IEnumerable GetDealsByPrefix(string prefix, int contactID, bool internalSearch = true) { var result = new List(); if (contactID > 0 && internalSearch) { var findedDeals = DaoFactory.GetDealDao().GetDealsByContactID(contactID); foreach (var item in findedDeals) { if (item.Title.IndexOf(prefix, StringComparison.Ordinal) != -1) { result.Add(ToOpportunityWrapper(item)); } } ApiContext.SetTotalCount(result.Count); } else { const int maxItemCount = 30; var findedDeals = DaoFactory.GetDealDao().GetDealsByPrefix(prefix, 0, maxItemCount, contactID, internalSearch); foreach (var item in findedDeals) { result.Add(ToOpportunityWrapper(item)); } } return result; } /// /// Returns the list of all contact opportunities /// /// Contact ID /// Get opportunity list /// Opportunities /// /// Opportunity list /// [Read(@"opportunity/bycontact/{contactid:int}")] public IEnumerable GetDeals(int contactid) { var deals = DaoFactory.GetDealDao().GetDealsByContactID(contactid); return ToListOpportunityWrapper(deals); } /// false [Update(@"opportunity/{opportunityid:int}/creationdate")] public void SetDealCreationDate(int opportunityid, ApiDateTime creationDate) { var dao = DaoFactory.GetDealDao(); var opportunity = dao.GetByID(opportunityid); if (opportunity == null || !CRMSecurity.CanAccessTo(opportunity)) throw new ItemNotFoundException(); dao.SetDealCreationDate(opportunityid, creationDate); } /// false [Update(@"opportunity/{opportunityid:int}/lastmodifeddate")] public void SetDealLastModifedDate(int opportunityid, ApiDateTime lastModifedDate) { var dao = DaoFactory.GetDealDao(); var opportunity = dao.GetByID(opportunityid); if (opportunity == null || !CRMSecurity.CanAccessTo(opportunity)) throw new ItemNotFoundException(); dao.SetDealLastModifedDate(opportunityid, lastModifedDate); } private IEnumerable ToListOpportunityWrapper(ICollection deals) { if (deals == null || deals.Count == 0) return new List(); var result = new List(); var contactIDs = new List(); var dealIDs = new List(); var dealMilestoneIDs = new List(); foreach (var deal in deals) { contactIDs.Add(deal.ContactID); dealIDs.Add(deal.ID); dealMilestoneIDs.Add(deal.DealMilestoneID); } dealMilestoneIDs = dealMilestoneIDs.Distinct().ToList(); var contacts = new Dictionary(); var customFields = DaoFactory.GetCustomFieldDao().GetEnityFields(EntityType.Opportunity, dealIDs.ToArray()) .GroupBy(item => item.EntityID) .ToDictionary(item => item.Key, item => item.Select(ToCustomFieldBaseWrapper)); var dealMilestones = DaoFactory.GetDealMilestoneDao().GetAll(dealMilestoneIDs.ToArray()) .ToDictionary(item => item.ID, item => new DealMilestoneBaseWrapper(item)); var dealMembers = DaoFactory.GetDealDao().GetMembers(dealIDs.ToArray()); foreach (var value in dealMembers.Values) { contactIDs.AddRange(value); } contactIDs = contactIDs.Distinct().ToList(); if (contactIDs.Count > 0) { DaoFactory.GetContactDao().GetContacts(contactIDs.ToArray()).ForEach(item => { if (item == null) return; contacts.Add(item.ID, ToContactBaseWrapper(item)); }); } foreach (var deal in deals) { var dealWrapper = new OpportunityWrapper(deal); if (contacts.ContainsKey(deal.ContactID)) { dealWrapper.Contact = contacts[deal.ContactID]; } dealWrapper.CustomFields = customFields.ContainsKey(deal.ID) ? customFields[deal.ID] : new List(); dealWrapper.Members = dealMembers.ContainsKey(dealWrapper.ID) ? dealMembers[dealWrapper.ID].Where(contacts.ContainsKey).Select(item => contacts[item]) : new List(); if (dealMilestones.ContainsKey(deal.DealMilestoneID)) { dealWrapper.Stage = dealMilestones[deal.DealMilestoneID]; } dealWrapper.IsPrivate = CRMSecurity.IsPrivate(deal); if (dealWrapper.IsPrivate) { dealWrapper.AccessList = CRMSecurity.GetAccessSubjectTo(deal).Select(item => EmployeeWraper.Get(item.Key)).ToItemList(); } if (!string.IsNullOrEmpty(deal.BidCurrency)) { dealWrapper.BidCurrency = ToCurrencyInfoWrapper(CurrencyProvider.Get(deal.BidCurrency)); } result.Add(dealWrapper); } return result; } private OpportunityWrapper ToOpportunityWrapper(Deal deal) { var dealWrapper = new OpportunityWrapper(deal); if (deal.ContactID > 0) dealWrapper.Contact = ToContactBaseWrapper(DaoFactory.GetContactDao().GetByID(deal.ContactID)); if (deal.DealMilestoneID > 0) { var dealMilestone = DaoFactory.GetDealMilestoneDao().GetByID(deal.DealMilestoneID); if (dealMilestone == null) throw new ItemNotFoundException(); dealWrapper.Stage = new DealMilestoneBaseWrapper(dealMilestone); } dealWrapper.AccessList = CRMSecurity.GetAccessSubjectTo(deal) .Select(item => EmployeeWraper.Get(item.Key)).ToItemList(); dealWrapper.IsPrivate = CRMSecurity.IsPrivate(deal); if (!string.IsNullOrEmpty(deal.BidCurrency)) dealWrapper.BidCurrency = ToCurrencyInfoWrapper(CurrencyProvider.Get(deal.BidCurrency)); dealWrapper.CustomFields = DaoFactory.GetCustomFieldDao().GetEnityFields(EntityType.Opportunity, deal.ID, false).ConvertAll(item => new CustomFieldBaseWrapper(item)).ToSmartList(); dealWrapper.Members = new List(); var memberIDs = DaoFactory.GetDealDao().GetMembers(deal.ID); var membersList = DaoFactory.GetContactDao().GetContacts(memberIDs); var membersWrapperList = new List(); foreach (var member in membersList) { if (member == null) continue; membersWrapperList.Add(ToContactBaseWrapper(member)); } dealWrapper.Members = membersWrapperList; return dealWrapper; } } }