DocSpace-client/products/ASC.CRM/Server/Api/DealsController.cs

983 lines
43 KiB
C#

/*
*
* (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 System;
using System.Collections.Generic;
using System.Linq;
using ASC.Api.Core;
using ASC.Api.CRM;
using ASC.Common.Web;
using ASC.Core;
using ASC.Core.Users;
using ASC.CRM.ApiModels;
using ASC.CRM.Core;
using ASC.CRM.Core.Dao;
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.Core.Users;
using ASC.Web.CRM.Classes;
using ASC.Web.CRM.Services.NotifyService;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
namespace ASC.CRM.Api
{
public class DealsController : BaseApiController
{
private readonly DisplayUserSettingsHelper _displayUserSettingsHelper;
private readonly NotifyClient _notifyClient;
private readonly ApiContext _apiContext;
private readonly MessageService _messageService;
private readonly MessageTarget _messageTarget;
private readonly SecurityContext _securityContext;
private readonly CurrencyProvider _currencyProvider;
private readonly UserManager _userManager;
private readonly EmployeeWraperHelper _employeeWraperHelper;
public DealsController(CrmSecurity crmSecurity,
DaoFactory daoFactory,
ApiContext apiContext,
MessageTarget messageTarget,
MessageService messageService,
NotifyClient notifyClient,
CurrencyProvider currencyProvider,
UserManager userManager,
EmployeeWraperHelper employeeWraperHelper,
DisplayUserSettingsHelper displayUserSettingsHelper,
SecurityContext securityContext,
IMapper mapper)
: base(daoFactory, crmSecurity, mapper)
{
_apiContext = apiContext;
_messageTarget = messageTarget;
_messageService = messageService;
_notifyClient = notifyClient;
_currencyProvider = currencyProvider;
_userManager = userManager;
_employeeWraperHelper = employeeWraperHelper;
_displayUserSettingsHelper = displayUserSettingsHelper;
_securityContext = securityContext;
}
/// <summary>
/// Returns the detailed information about the opportunity with the ID specified in the request
/// </summary>
/// <param name="opportunityid">Opportunity ID</param>
/// <returns>
/// Opportunity
/// </returns>
/// <short>Get opportunity by ID</short>
/// <category>Opportunities</category>
///<exception cref="ArgumentException"></exception>
///<exception cref="ItemNotFoundException"></exception>
[Read(@"opportunity/{opportunityid:int}")]
public OpportunityDto 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 _mapper.Map<OpportunityDto>(deal);
}
/// <summary>
/// Updates the selected opportunity to the stage with the ID specified in the request
/// </summary>
/// <param name="opportunityid">Opportunity ID</param>
/// <param name="stageid">Opportunity stage ID</param>
/// <returns>
/// Opportunity
/// </returns>
/// <short>Update opportunity stage</short>
/// <category>Opportunities</category>
///<exception cref="ArgumentException"></exception>
///<exception cref="ItemNotFoundException"></exception>
[Update(@"opportunity/{opportunityid:int}/stage/{id:int}")]
public OpportunityDto 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 _mapper.Map<OpportunityDto>(deal);
}
/// <summary>
/// Sets access rights for the selected opportunity with the parameters specified in the request
/// </summary>
/// <param name="opportunityid">Opportunity ID</param>
/// <param name="isPrivate">Opportunity privacy: private or not</param>
/// <param name="accessList">List of users with access</param>
/// <short>Set rights to opportunity</short>
/// <category>Opportunities</category>
///<exception cref="ArgumentException"></exception>
///<exception cref="ItemNotFoundException"></exception>
/// <returns>
/// Opportunity
/// </returns>
[Update(@"opportunity/{opportunityid:int}/access")]
public OpportunityDto SetAccessToDeal(int opportunityid, bool isPrivate, IEnumerable<Guid> 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 OpportunityDto SetAccessToDeal(Deal deal, bool isPrivate, IEnumerable<Guid> accessList, bool isNotify, bool isMessageServicSende)
{
var accessListLocal = accessList != null ? accessList.Distinct().ToList() : new List<Guid>();
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 = _userManager.GetUsers().Where(x => accessListLocal.Contains(x.ID));
_messageService.Send(MessageAction.OpportunityRestrictedAccess, _messageTarget.Create(deal.ID), deal.Title, users.Select(x => x.DisplayUserName(false, _displayUserSettingsHelper)));
}
}
else
{
_crmSecurity.MakePublic(deal);
if (isMessageServicSende)
{
_messageService.Send(MessageAction.OpportunityOpenedAccess, _messageTarget.Create(deal.ID), deal.Title);
}
}
return _mapper.Map<OpportunityDto>(deal);
}
/// <summary>
/// Sets access rights for other users to the list of all opportunities matching the parameters specified in the request
/// </summary>
/// <param optional="true" name="responsibleid">Opportunity responsible</param>
/// <param optional="true" name="opportunityStagesid">Opportunity stage ID</param>
/// <param optional="true" name="tags">Tags</param>
/// <param optional="true" name="contactid">Contact ID</param>
/// <param optional="true" name="contactAlsoIsParticipant">Participation status: take into account opportunities where the contact is a participant or not</param>
/// <param optional="true" name="fromDate">Start date</param>
/// <param optional="true" name="toDate">End date</param>
/// <param optional="true" name="stageType" remark="Allowed values: {Open, ClosedAndWon, ClosedAndLost}">Opportunity stage type</param>
/// <param name="isPrivate">Opportunity privacy: private or not</param>
/// <param name="accessList">List of users with access</param>
/// <short>Set opportunity access rights</short>
/// <category>Opportunities</category>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="ItemNotFoundException"></exception>
/// <returns>
/// Opportunity list
/// </returns>
[Update(@"opportunity/filter/access")]
public IEnumerable<OpportunityDto> SetAccessToBatchDeal([FromForm] SetAccessToBatchDealByFilterRequestDto inDto)
{
var responsibleid = inDto.Responsibleid;
var opportunityStagesid = inDto.OpportunityStagesid;
var contactid = inDto.Contactid;
var tags = inDto.Tags;
var stageType = inDto.StageType;
var contactAlsoIsParticipant = inDto.ContactAlsoIsParticipant;
var fromDate = inDto.FromDate;
var toDate = inDto.ToDate;
var isPrivate = inDto.isPrivate;
var accessList = inDto.AccessList;
var result = new List<Deal>();
var deals = _daoFactory.GetDealDao()
.GetDeals(_apiContext.FilterValue,
responsibleid,
opportunityStagesid,
tags,
contactid,
stageType,
contactAlsoIsParticipant,
fromDate, toDate, 0, 0, null);
if (!deals.Any()) return Enumerable.Empty<OpportunityDto>();
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 ToListOpportunityDto(result);
}
/// <summary>
/// Sets access rights for other users to the list of opportunities with the IDs specified in the request
/// </summary>
/// <param name="opportunityid">Opportunity ID list</param>
/// <param name="isPrivate">Opportunity privacy: private or not</param>
/// <param name="accessList">List of users with access</param>
/// <short>Set opportunity access rights</short>
/// <category>Opportunities</category>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="ItemNotFoundException"></exception>
/// <returns>
/// Opportunity list
/// </returns>
[Update(@"opportunity/access")]
public IEnumerable<OpportunityDto> SetAccessToBatchDeal(SetAccessToBatchDealRequestDto inDto)
{
var opportunityid = inDto.Opportunityid;
var isPrivate = inDto.isPrivate;
var accessList = inDto.AccessList;
if (opportunityid == null) throw new ArgumentException();
var result = new List<Deal>();
var deals = _daoFactory.GetDealDao().GetDeals(opportunityid.ToArray());
if (!deals.Any()) return new List<OpportunityDto>();
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 ToListOpportunityDto(result);
}
/// <summary>
/// Deletes the group of opportunities with the IDs specified in the request
/// </summary>
/// <param name="opportunityids">Opportunity ID list</param>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="ItemNotFoundException"></exception>
/// <short>Delete opportunity group</short>
/// <category>Opportunities</category>
/// <returns>
/// Opportunity list
/// </returns>
[Update(@"opportunity")]
public IEnumerable<OpportunityDto> DeleteBatchDeals(IEnumerable<int> 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 ToListOpportunityDto(opportunities);
}
/// <summary>
/// Deletes the list of all opportunities matching the parameters specified in the request
/// </summary>
/// <param optional="true" name="responsibleid">Opportunity responsible</param>
/// <param optional="true" name="opportunityStagesid">Opportunity stage ID</param>
/// <param optional="true" name="tags">Tags</param>
/// <param optional="true" name="contactid">Contact ID</param>
/// <param optional="true" name="contactAlsoIsParticipant">Participation status: take into account opportunities where the contact is a participant or not</param>
/// <param optional="true" name="fromDate">Start date</param>
/// <param optional="true" name="toDate">End date</param>
/// <param optional="true" name="stageType" remark="Allowed values: {Open, ClosedAndWon, ClosedAndLost}">Opportunity stage type</param>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="ItemNotFoundException"></exception>
/// <short>Delete opportunity group</short>
/// <category>Opportunities</category>
/// <returns>
/// Opportunity list
/// </returns>
[Delete(@"opportunity/filter")]
public IEnumerable<OpportunityDto> DeleteBatchDeals(
Guid responsibleid,
int opportunityStagesid,
IEnumerable<string> 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<OpportunityDto>();
deals = _daoFactory.GetDealDao().DeleteBatchDeals(deals);
_messageService.Send(MessageAction.OpportunitiesDeleted, _messageTarget.Create(deals.Select(x => x.ID)), deals.Select(d => d.Title));
return ToListOpportunityDto(deals);
}
/// <summary>
/// Returns the list of all opportunities matching the parameters specified in the request
/// </summary>
/// <param optional="true" name="responsibleid">Opportunity responsible</param>
/// <param optional="true" name="opportunityStagesid">Opportunity stage ID</param>
/// <param optional="true" name="tags">Tags</param>
/// <param optional="true" name="contactid">Contact ID</param>
/// <param optional="true" name="contactAlsoIsParticipant">Participation status: take into account opportunities where the contact is a participant or not</param>
/// <param optional="true" name="fromDate">Start date</param>
/// <param optional="true" name="toDate">End date</param>
/// <param optional="true" name="stageType" remark="Allowed values: {Open, ClosedAndWon, ClosedAndLost}">Opportunity stage type</param>
/// <short>Get opportunity list</short>
/// <category>Opportunities</category>
/// <returns>
/// Opportunity list
/// </returns>
[Read(@"opportunity/filter")]
public IEnumerable<OpportunityDto> GetDeals(
[FromQuery] Guid responsibleid,
[FromQuery] int opportunityStagesid,
[FromQuery] IEnumerable<string> tags,
[FromQuery] int contactid,
[FromQuery] DealMilestoneStatus? stageType,
[FromQuery] bool? contactAlsoIsParticipant,
[FromQuery] ApiDateTime fromDate,
[FromQuery] ApiDateTime toDate)
{
DealSortedByType dealSortedByType;
IEnumerable<OpportunityDto> result;
var searchString = _apiContext.FilterValue;
OrderBy dealsOrderBy;
if (ASC.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 = ToListOpportunityDto(_daoFactory.GetDealDao().GetDeals(
searchString,
responsibleid,
opportunityStagesid,
tags,
contactid,
stageType,
contactAlsoIsParticipant,
fromDate,
toDate,
fromIndex,
count,
dealsOrderBy)).ToList();
_apiContext.SetDataPaginated();
_apiContext.SetDataFiltered();
_apiContext.SetDataSorted();
}
else
{
result = ToListOpportunityDto(_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
.GetDealDao()
.GetDealsCount(searchString,
responsibleid,
opportunityStagesid,
tags,
contactid,
stageType,
contactAlsoIsParticipant,
fromDate,
toDate);
}
_apiContext.SetTotalCount(totalCount);
return result;
}
/// <summary>
/// Deletes the opportunity with the ID specified in the request
/// </summary>
/// <param name="opportunityid">Opportunity ID</param>
/// <short>Delete opportunity</short>
/// <category>Opportunities</category>
///<exception cref="ArgumentException"></exception>
///<exception cref="ItemNotFoundException"></exception>
/// <returns>
/// Opportunity
/// </returns>
[Delete(@"opportunity/{opportunityid:int}")]
public OpportunityDto 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 _mapper.Map<OpportunityDto>(deal);
}
/// <summary>
/// Creates the opportunity with the parameters specified in the request
/// </summary>
/// <short>Create opportunity</short>
/// <param name="contactid">Opportunity primary contact</param>
/// <param optional="true" name="members">Participants</param>
/// <param name="title">Opportunity title</param>
/// <param optional="true" name="description">Opportunity description</param>
/// <param name="responsibleid">Opportunity responsible</param>
/// <param name="bidType" remark="Allowed values: FixedBid, PerHour, PerDay,PerWeek, PerMonth, PerYear">Bid</param>
/// <param optional="true" name="bidValue">Amount of transaction</param>
/// <param name="bidCurrencyAbbr">Currency (Abbreviation)</param>
/// <param name="perPeriodValue">Period</param>
/// <param name="stageid">Stage ID</param>
/// <param optional="true" name="successProbability">Opportunity success probability</param>
/// <param optional="true" name="actualCloseDate">Actual opportunity closure date</param>
/// <param optional="true" name="expectedCloseDate">Expected opportunity closure date</param>
/// <param optional="true" name="customFieldList">User field list</param>
/// <param name="isPrivate">Opportunity privacy: private or not</param>
/// <param optional="true" name="accessList">List of users with access to the opportunity</param>
/// <param name="isNotify" optional="true">Notify users in accessList about the opportunity</param>
/// <category>Opportunities</category>
/// <returns>
/// Opportunity
/// </returns>
///<exception cref="ArgumentException"></exception>
[Create(@"opportunity")]
public OpportunityDto CreateDeal(CreateOrUpdateDealRequestDto inDto)
{
var title = inDto.Title;
var description = inDto.Description;
var responsibleid = inDto.Responsibleid;
var bidType = inDto.BidType;
var bidValue = inDto.BidValue;
var perPeriodValue = inDto.PerPeriodValue;
var stageid = inDto.Stageid;
var successProbability = inDto.SuccessProbability;
var contactid = inDto.Contactid;
var actualCloseDate = inDto.ActualCloseDate;
var expectedCloseDate = inDto.ExpectedCloseDate;
var bidCurrencyAbbr = inDto.BidCurrencyAbbr;
var isPrivate = inDto.isPrivate;
var isNotify = inDto.isNotify;
var accessList = inDto.AccessList;
var customFieldList = inDto.CustomFieldList;
var members = inDto.Members;
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<int>();
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 _mapper.Map<OpportunityDto>(deal);
}
/// <summary>
/// Updates the selected opportunity with the parameters specified in the request
/// </summary>
/// <short>Update opportunity</short>
///<param name="opportunityid">Opportunity ID</param>
///<param name="contactid">Opportunity primary contact</param>
/// <param optional="true" name="members">Participants</param>
/// <param name="title">Opportunity title</param>
/// <param optional="true" name="description">Opportunity description</param>
/// <param name="responsibleid">Opportunity responsible</param>
/// <param name="bidType" remark="Allowed values: FixedBid, PerHour, PerDay,PerWeek, PerMonth, PerYear">Bid</param>
/// <param optional="true" name="bidValue">Amount of transaction</param>
/// <param optional="true" name="bidCurrencyAbbr">Currency (Abbreviation)</param>
/// <param name="perPeriodValue">Period</param>
/// <param name="stageid">Stage ID</param>
/// <param optional="true" name="successProbability">Opportunity success probability</param>
/// <param optional="true" name="actualCloseDate">Actual opportunity closure date</param>
/// <param optional="true" name="expectedCloseDate">Expected opportunity closure date</param>
/// <param optional="true" name="customFieldList">User field list</param>
/// <param name="isPrivate">Opportunity privacy: private or not</param>
/// <param optional="true" name="accessList">List of users with access to the opportunity</param>
/// <param name="isNotify" optional="true">Notify users in accessList about the opportunity</param>
/// <category>Opportunities</category>
/// <returns>
/// Opportunity
/// </returns>
///<exception cref="ArgumentException"></exception>
[Update(@"opportunity/{opportunityid:int}")]
public OpportunityDto UpdateDeal(
int opportunityid, CreateOrUpdateDealRequestDto inDto)
{
var title = inDto.Title;
var description = inDto.Description;
var responsibleid = inDto.Responsibleid;
var bidType = inDto.BidType;
var bidValue = inDto.BidValue;
var perPeriodValue = inDto.PerPeriodValue;
var stageid = inDto.Stageid;
var successProbability = inDto.SuccessProbability;
var contactid = inDto.Contactid;
var actualCloseDate = inDto.ActualCloseDate;
var expectedCloseDate = inDto.ExpectedCloseDate;
var bidCurrencyAbbr = inDto.BidCurrencyAbbr;
var isPrivate = inDto.isPrivate;
var isNotify = inDto.isNotify;
var accessList = inDto.AccessList;
var customFieldList = inDto.CustomFieldList;
var members = inDto.Members;
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<int>();
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 _mapper.Map<OpportunityDto>(deal);
}
/// <summary>
/// Returns the list of all contacts associated with the opportunity with the ID specified in the request
/// </summary>
/// <param name="opportunityid">Opportunity ID</param>
/// <short>Get all opportunity contacts</short>
/// <category>Opportunities</category>
/// <returns>Contact list</returns>
///<exception cref="ArgumentException"></exception>
///<exception cref="ItemNotFoundException"></exception>
[Read(@"opportunity/{opportunityid:int}/contact")]
public IEnumerable<ContactDto> 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 List<ContactDto>();
var contacts = _daoFactory.GetContactDao().GetContacts(contactIDs);
var result = _mapper.Map<List<Core.Entities.Contact>, List<ContactDto>>(contacts);
result.ForEach(item => { if (item.Id == opportunity.ContactID) item.CanEdit = false; });
return result;
}
/// <summary>
/// Adds the selected contact to the opportunity with the ID specified in the request
/// </summary>
/// <param name="opportunityid">Opportunity ID</param>
/// <param name="contactid">Contact ID</param>
/// <short>Add opportunity contact</short>
/// <category>Opportunities</category>
/// <exception cref="ArgumentException"></exception>
/// <returns>
/// Participant
/// </returns>
[Create(@"opportunity/{opportunityid:int}/contact/{contactid:int}")]
public ContactDto AddMemberToDeal([FromRoute] int opportunityid, [FromRoute] 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 = _mapper.Map<ContactDto>(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;
}
/// <summary>
/// Deletes the selected contact from the opportunity with the ID specified in the request
/// </summary>
/// <param name="opportunityid">Opportunity ID</param>
/// <param name="contactid">Contact ID</param>
/// <short>Delete opportunity contact</short>
/// <category>Opportunities</category>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="ItemNotFoundException"></exception>
/// <returns>
/// Participant
/// </returns>
[Delete(@"opportunity/{opportunityid:int}/contact/{contactid:int}")]
public ContactDto 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 = _mapper.Map<ContactDto>(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;
}
/// <summary>
/// Returns the list of 30 opportunities in the CRM module with prefix
/// </summary>
/// <param optional="true" name="prefix"></param>
/// <param optional="true" name="contactID"></param>
/// <param optional="true" name="internalSearch"></param>
/// <category>Opportunities</category>
/// <returns>
/// Opportunities list
/// </returns>
/// <visible>false</visible>
[Read(@"opportunity/byprefix")]
public IEnumerable<OpportunityDto> GetDealsByPrefix(string prefix, int contactID, bool internalSearch = true)
{
var result = new List<OpportunityDto>();
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(_mapper.Map<OpportunityDto>(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(_mapper.Map<OpportunityDto>(item));
}
}
return result;
}
/// <summary>
/// Returns the list of all contact opportunities
/// </summary>
/// <param optional="true" name="contactid">Contact ID</param>
/// <short>Get opportunity list</short>
/// <category>Opportunities</category>
/// <returns>
/// Opportunity list
/// </returns>
[Read(@"opportunity/bycontact/{contactid:int}")]
public IEnumerable<OpportunityDto> GetDeals(int contactid)
{
var deals = _daoFactory.GetDealDao().GetDealsByContactID(contactid);
return ToListOpportunityDto(deals);
}
/// <visible>false</visible>
[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);
}
/// <visible>false</visible>
[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<OpportunityDto> ToListOpportunityDto(ICollection<Deal> deals)
{
if (deals == null || deals.Count == 0) return new List<OpportunityDto>();
var result = new List<OpportunityDto>();
var contactIDs = new List<int>();
var dealIDs = new List<int>();
var dealMilestoneIDs = new List<int>();
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<int, ContactBaseDto>();
var customFields = _daoFactory.GetCustomFieldDao().GetEnityFields(EntityType.Opportunity, dealIDs.ToArray())
.GroupBy(item => item.EntityID)
.ToDictionary(item => item.Key, item => item.Select(x => _mapper.Map<CustomFieldBaseDto>(x)));
var dealMilestones = _daoFactory.GetDealMilestoneDao().GetAll(dealMilestoneIDs.ToArray())
.ToDictionary(item => item.ID, item => new DealMilestoneBaseDto(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, _mapper.Map<ContactBaseDto>(item));
});
}
foreach (var deal in deals)
{
var dealDto = _mapper.Map<OpportunityDto>(deal);
if (contacts.ContainsKey(deal.ContactID))
{
dealDto.Contact = contacts[deal.ContactID];
}
dealDto.CustomFields = customFields.ContainsKey(deal.ID)
? customFields[deal.ID]
: new List<CustomFieldBaseDto>();
dealDto.Members = dealMembers.ContainsKey(dealDto.Id)
? dealMembers[dealDto.Id].Where(contacts.ContainsKey).Select(item => contacts[item])
: new List<ContactBaseDto>();
if (dealMilestones.ContainsKey(deal.DealMilestoneID))
{
dealDto.Stage = dealMilestones[deal.DealMilestoneID];
}
dealDto.IsPrivate = _crmSecurity.IsPrivate(deal);
if (dealDto.IsPrivate)
{
dealDto.AccessList = _crmSecurity.GetAccessSubjectTo(deal).Select(item => _employeeWraperHelper.Get(item.Key));
}
if (!string.IsNullOrEmpty(deal.BidCurrency))
{
dealDto.BidCurrency = _mapper.Map<CurrencyInfoDto>(_currencyProvider.Get(deal.BidCurrency));
}
result.Add(dealDto);
}
return result;
}
}
}