/*
*
* (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 System.Threading.Tasks;
using ASC.Api.Core;
using ASC.Api.CRM;
using ASC.Common.Web;
using ASC.Core.Common.Settings;
using ASC.CRM.ApiModels;
using ASC.CRM.Classes;
using ASC.CRM.Core;
using ASC.CRM.Core.Dao;
using ASC.CRM.Core.Entities;
using ASC.CRM.Core.Enums;
using ASC.CRM.Resources;
using ASC.Files.Core.ApiModels.ResponseDto;
using ASC.MessagingSystem.Core;
using ASC.MessagingSystem.Models;
using ASC.Web.CRM.Classes;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
namespace ASC.CRM.Api
{
public class InvoicesController : BaseApiController
{
private readonly PdfQueueWorker _pdfQueueWorker;
private readonly Global _global;
private readonly FileDtoHelper _fileDtoHelper;
private readonly PdfCreator _pdfCreator;
private readonly SettingsManager _settingsManager;
private readonly ApiDateTimeHelper _apiDateTimeHelper;
private readonly ApiContext _apiContext;
private readonly MessageService _messageService;
private readonly MessageTarget _messageTarget;
private readonly CurrencyProvider _currencyProvider;
public InvoicesController(CrmSecurity crmSecurity,
DaoFactory daoFactory,
ApiContext apiContext,
MessageTarget messageTarget,
MessageService messageService,
ApiDateTimeHelper apiDateTimeHelper,
SettingsManager settingsManager,
FileDtoHelper fileDtoHelper,
PdfCreator pdfCreator,
Global global,
PdfQueueWorker pdfQueueWorker,
CurrencyProvider currencyProvider,
IMapper mapper)
: base(daoFactory, crmSecurity, mapper)
{
_apiContext = apiContext;
_messageTarget = messageTarget;
_messageService = messageService;
_apiDateTimeHelper = apiDateTimeHelper;
_settingsManager = settingsManager;
_pdfCreator = pdfCreator;
_fileDtoHelper = fileDtoHelper;
_global = global;
_pdfQueueWorker = pdfQueueWorker;
_mapper = mapper;
_currencyProvider = currencyProvider;
}
///
/// Returns the detailed information about the invoice with the ID specified in the request
///
/// Invoice ID
/// Get invoice by ID
/// Invoices
/// Invoice
[HttpGet(@"invoice/{invoiceid:int}")]
public InvoiceDto GetInvoiceByID(int invoiceid)
{
if (invoiceid <= 0) throw new ArgumentException();
var invoice = _daoFactory.GetInvoiceDao().GetByID(invoiceid);
if (invoice == null) throw new ItemNotFoundException();
if (!_crmSecurity.CanAccessTo(invoice))
{
throw _crmSecurity.CreateSecurityException();
}
return _mapper.Map(invoice);
}
///
/// Returns the detailed information about the invoice sample
///
/// Get invoice sample
/// Invoices
/// Invoice
[HttpGet(@"invoice/sample")]
public InvoiceDto GetInvoiceSample()
{
var crmSettings = _settingsManager.Load();
var defaultCurrency = _currencyProvider.Get(crmSettings.DefaultCurrency);
var sample = InvoiceDto.GetSample();
sample.Number = _daoFactory.GetInvoiceDao().GetNewInvoicesNumber();
sample.Terms = _daoFactory.GetInvoiceDao().GetSettings().Terms ?? string.Empty;
sample.IssueDate = _apiDateTimeHelper.Get(DateTime.UtcNow);
sample.DueDate = _apiDateTimeHelper.Get(DateTime.UtcNow.AddDays(30));
sample.CreateOn = _apiDateTimeHelper.Get(DateTime.UtcNow);
sample.Currency = _mapper.Map(defaultCurrency);
sample.InvoiceLines.First().Quantity = 1;
return sample;
}
///
/// Returns the json data of the invoice with the ID specified in the request
///
/// Invoice ID
/// Get invoice json data
/// Invoices
/// Json Data
[HttpGet(@"invoice/jsondata/{invoiceid:int}")]
public string GetInvoiceJsonData(int invoiceid)
{
var invoice = _daoFactory.GetInvoiceDao().GetByID(invoiceid);
if (invoice == null) throw new ItemNotFoundException();
if (!_crmSecurity.CanAccessTo(invoice))
{
throw _crmSecurity.CreateSecurityException();
}
return invoice.JsonData;
}
///
/// Returns the list of invoices matching the creteria specified in the request
///
/// Invoice status
/// Invoice issue date from
/// Invoice issue date to
/// Invoice due date from
/// Invoice due date to
/// Invoice entity type
/// Invoice entity ID
/// Invoice currency
/// Get invoice list
/// Invoices
/// Invoice list
[HttpGet(@"invoice/filter")]
public IEnumerable GetInvoices(
InvoiceStatus? status,
ApiDateTime issueDateFrom,
ApiDateTime issueDateTo,
ApiDateTime dueDateFrom,
ApiDateTime dueDateTo,
String entityType,
int entityid,
String currency
)
{
if (!String.IsNullOrEmpty(entityType) && !(
string.Equals(entityType, "contact", StringComparison.CurrentCultureIgnoreCase) ||
string.Equals(entityType, "opportunity", StringComparison.CurrentCultureIgnoreCase) ||
string.Equals(entityType, "case", StringComparison.CurrentCultureIgnoreCase)))
throw new ArgumentException();
IEnumerable result;
InvoiceSortedByType sortBy;
OrderBy invoiceOrderBy;
var searchString = _apiContext.FilterValue;
if (InvoiceSortedByType.TryParse(_apiContext.SortBy, true, out sortBy))
{
invoiceOrderBy = new OrderBy(sortBy, !_apiContext.SortDescending);
}
else if (String.IsNullOrEmpty(_apiContext.SortBy))
{
invoiceOrderBy = new OrderBy(InvoiceSortedByType.Number, true);
}
else
{
invoiceOrderBy = null;
}
var fromIndex = (int)_apiContext.StartIndex;
var count = (int)_apiContext.Count;
if (invoiceOrderBy != null)
{
result = ToListInvoiceBaseDtos(
_daoFactory.GetInvoiceDao().GetInvoices(
searchString,
status,
issueDateFrom, issueDateTo,
dueDateFrom, dueDateTo,
ToEntityType(entityType), entityid,
currency,
fromIndex, count,
invoiceOrderBy));
_apiContext.SetDataPaginated();
_apiContext.SetDataFiltered();
_apiContext.SetDataSorted();
}
else
{
result = ToListInvoiceBaseDtos(
_daoFactory.GetInvoiceDao().GetInvoices(
searchString,
status,
issueDateFrom, issueDateTo,
dueDateFrom, dueDateTo,
ToEntityType(entityType), entityid,
currency,
0,
0,
null));
}
int totalCount;
if (result.Count() < count)
{
totalCount = fromIndex + result.Count();
}
else
{
totalCount = _daoFactory.GetInvoiceDao().GetInvoicesCount(
searchString,
status,
issueDateFrom, issueDateTo,
dueDateFrom, dueDateTo,
ToEntityType(entityType), entityid,
currency);
}
_apiContext.SetTotalCount(totalCount);
return result;
}
///
/// Returns the list of all invoices associated with the entity with the ID and type specified in the request
///
/// Invoice entity type
/// Invoice entity ID
/// Get entity invoices
/// Invoices
/// Invoice list
[HttpGet(@"{entityType:regex(contact|person|company|opportunity)}/invoicelist/{entityid:int}")]
public IEnumerable GetEntityInvoices(String entityType, int entityid)
{
if (String.IsNullOrEmpty(entityType) || entityid <= 0) throw new ArgumentException();
return ToListInvoiceBaseDtos(_daoFactory.GetInvoiceDao().GetEntityInvoices(ToEntityType(entityType), entityid));
}
///
/// Updates the status of invoices with the IDs specified in the request
///
/// Invoice ID list
/// Status
/// Update invoice group status
/// Invoices
/// KeyValuePair of Invoices and InvoiceItems
[HttpPut(@"invoice/status/{status:int}")]
public KeyValuePair, IEnumerable> UpdateInvoiceBatchStatus(
int[] invoiceids,
InvoiceStatus status
)
{
if (invoiceids == null || !invoiceids.Any()) throw new ArgumentException();
var oldInvoices = _daoFactory.GetInvoiceDao().GetByID(invoiceids).Where(_crmSecurity.CanAccessTo).ToList();
var updatedInvoices = _daoFactory.GetInvoiceDao().UpdateInvoiceBatchStatus(oldInvoices.ToList().Select(i => i.ID).ToArray(), status);
// detect what really changed
var realUpdatedInvoices = updatedInvoices
.Select(t => oldInvoices.FirstOrDefault(x => x.ID == t.ID && x.Status != t.Status))
.Where(inv => inv != null)
.ToList();
if (realUpdatedInvoices.Any())
{
_messageService.Send(MessageAction.InvoicesUpdatedStatus, _messageTarget.Create(realUpdatedInvoices.Select(x => x.ID)), realUpdatedInvoices.Select(x => x.Number), status.ToLocalizedString());
}
var invoiceItemsUpdated = new List();
if (status == InvoiceStatus.Sent || status == InvoiceStatus.Rejected)
{
var invoiceItemsAll = _daoFactory.GetInvoiceItemDao().GetAll();
var invoiceItemsWithTrackInventory = invoiceItemsAll.Where(item => item.TrackInventory).ToList();
if (status == InvoiceStatus.Sent && invoiceItemsWithTrackInventory != null && invoiceItemsWithTrackInventory.Count != 0)
{
foreach (var inv in updatedInvoices)
{
if (inv.Status == InvoiceStatus.Sent)
{
//could be changed
var oldInv = oldInvoices.FirstOrDefault(i => i.ID == inv.ID);
if (oldInv != null && oldInv.Status == InvoiceStatus.Draft)
{
//was changed to Sent
var invoiceLines = _daoFactory.GetInvoiceLineDao().GetInvoiceLines(inv.ID);
foreach (var line in invoiceLines)
{
var item = invoiceItemsWithTrackInventory.FirstOrDefault(ii => ii.ID == line.InvoiceItemID);
if (item != null)
{
item.StockQuantity -= line.Quantity;
_daoFactory.GetInvoiceItemDao().SaveOrUpdateInvoiceItem(item);
var oldItem = invoiceItemsUpdated.Find(i => i.ID == item.ID);
if (oldItem != null)
{
invoiceItemsUpdated.Remove(oldItem);
}
invoiceItemsUpdated.Add(item);
}
}
}
}
}
}
if (status == InvoiceStatus.Rejected && invoiceItemsWithTrackInventory != null && invoiceItemsWithTrackInventory.Count != 0)
{
foreach (var inv in updatedInvoices)
{
if (inv.Status == InvoiceStatus.Rejected)
{
//could be changed
var oldInv = oldInvoices.FirstOrDefault(i => i.ID == inv.ID);
if (oldInv != null && oldInv.Status == InvoiceStatus.Sent)
{
//was changed from Sent to Rejectes
var invoiceLines = _daoFactory.GetInvoiceLineDao().GetInvoiceLines(inv.ID);
foreach (var line in invoiceLines)
{
var item = invoiceItemsWithTrackInventory.FirstOrDefault(ii => ii.ID == line.InvoiceItemID);
if (item != null)
{
item.StockQuantity += line.Quantity;
_daoFactory.GetInvoiceItemDao().SaveOrUpdateInvoiceItem(item);
var oldItem = invoiceItemsUpdated.Find(i => i.ID == item.ID);
if (oldItem != null)
{
invoiceItemsUpdated.Remove(oldItem);
}
invoiceItemsUpdated.Add(item);
}
}
}
}
}
}
}
var listInvoiceBaseDtos = ToListInvoiceBaseDtos(updatedInvoices);
return new KeyValuePair, IEnumerable>(
listInvoiceBaseDtos,
_mapper.Map, List>(invoiceItemsUpdated));
}
///
/// Delete the invoice with the ID specified in the request
///
/// Invoice ID
/// Delete invoice
/// Invoices
/// Invoice
[HttpDelete(@"invoice/{invoiceid:int}")]
public InvoiceBaseDto DeleteInvoice(int invoiceid)
{
if (invoiceid <= 0) throw new ArgumentException();
var invoice = _daoFactory.GetInvoiceDao().DeleteInvoice(invoiceid);
if (invoice == null) throw new ItemNotFoundException();
_messageService.Send(MessageAction.InvoiceDeleted, _messageTarget.Create(invoice.ID), invoice.Number);
return _mapper.Map(invoice);
}
///
/// Deletes the group of invoices with the IDs specified in the request
///
/// Invoice ID list
/// Delete invoice group
/// Invoices
/// Invoice list
[HttpDelete(@"invoice")]
public IEnumerable DeleteBatchInvoices(IEnumerable invoiceids)
{
if (invoiceids == null || !invoiceids.Any()) throw new ArgumentException();
var invoices = _daoFactory.GetInvoiceDao().DeleteBatchInvoices(invoiceids.ToArray());
_messageService.Send(MessageAction.InvoicesDeleted, _messageTarget.Create(invoices.Select(x => x.ID)), invoices.Select(x => x.Number));
return ToListInvoiceBaseDtos(invoices);
}
///
/// Creates the invoice with the parameters (contactId, consigneeId, etc.) specified in the request
///
/// Invoice number
/// Invoice issue date
/// Invoice template type
/// Invoice contact ID
/// Invoice consignee ID
/// Invoice entity ID
/// Invoice billing address ID
/// Invoice delivery address ID
/// Invoice due date
/// Invoice language
/// Invoice currency
/// Invoice exchange rate
/// Invoice purchase order number
/// Invoice terms
/// Invoice description
/// Invoice lines list
/// Create invoice
/// Invoices
/// Invoice
///
///
///
[HttpPost(@"invoice")]
public InvoiceDto CreateInvoice(
CreateOrUpdateInvoiceRequestDto inDto
)
{
string number = inDto.Number;
ApiDateTime issueDate = inDto.IssueDate;
int templateType = inDto.TemplateType;
int contactId = inDto.ContactId;
int consigneeId = inDto.ConsigneeId;
int entityId = inDto.EntityId;
int billingAddressID = inDto.BillingAddressID;
int deliveryAddressID = inDto.DeliveryAddressID;
ApiDateTime dueDate = inDto.DueDate;
string language = inDto.Language;
string currency = inDto.Currency;
decimal exchangeRate = inDto.ExchangeRate;
string purchaseOrderNumber = inDto.PurchaseOrderNumber;
string terms = inDto.Terms;
string description = inDto.Description;
IEnumerable invoiceLines = inDto.InvoiceLines;
var invoiceLinesList = invoiceLines != null ? invoiceLines.ToList() : new List();
if (!invoiceLinesList.Any() || !IsLinesForInvoiceCorrect(invoiceLinesList)) throw new ArgumentException();
var invoice = new Invoice
{
Status = InvoiceStatus.Draft,
Number = number,
IssueDate = issueDate,
TemplateType = (InvoiceTemplateType)templateType,
ContactID = contactId,
ConsigneeID = consigneeId,
EntityType = EntityType.Opportunity,
EntityID = entityId,
DueDate = dueDate,
Language = language,
Currency = !String.IsNullOrEmpty(currency) ? currency.ToUpper() : null,
ExchangeRate = exchangeRate,
PurchaseOrderNumber = purchaseOrderNumber,
Terms = terms,
Description = description
};
_crmSecurity.DemandCreateOrUpdate(invoice);
if (billingAddressID > 0)
{
var address = _daoFactory.GetContactInfoDao().GetByID(billingAddressID);
if (address == null || address.InfoType != ContactInfoType.Address || address.Category != (int)AddressCategory.Billing || address.ContactID != contactId)
throw new ArgumentException();
}
if (deliveryAddressID > 0)
{
var address = _daoFactory.GetContactInfoDao().GetByID(deliveryAddressID);
if (address == null || address.InfoType != ContactInfoType.Address || address.Category != (int)AddressCategory.Postal || address.ContactID != consigneeId)
throw new ArgumentException();
}
invoice.ID = _daoFactory.GetInvoiceDao().SaveOrUpdateInvoice(invoice);
CreateInvoiceLines(invoiceLinesList, invoice);
_daoFactory.GetInvoiceDao().UpdateInvoiceJsonData(invoice, billingAddressID, deliveryAddressID);
return _mapper.Map(invoice);
}
private bool IsLinesForInvoiceCorrect(List invoiceLines)
{
foreach (var line in invoiceLines)
{
if (line.InvoiceItemID <= 0 ||
line.Quantity < 0 || line.Price < 0 ||
line.Discount < 0 || line.Discount > 100 ||
line.InvoiceTax1ID < 0 || line.InvoiceTax2ID < 0)
return false;
if (!_daoFactory.GetInvoiceItemDao().IsExist(line.InvoiceItemID))
return false;
if (line.InvoiceTax1ID > 0 && !_daoFactory.GetInvoiceTaxDao().IsExist(line.InvoiceTax1ID))
return false;
if (line.InvoiceTax2ID > 0 && !_daoFactory.GetInvoiceTaxDao().IsExist(line.InvoiceTax2ID))
return false;
}
return true;
}
private List CreateInvoiceLines(List invoiceLines, Invoice invoice)
{
var result = new List();
for (var i = 0; i < invoiceLines.Count; i++)
{
var line = new InvoiceLine
{
ID = 0,
InvoiceID = invoice.ID,
InvoiceItemID = invoiceLines[i].InvoiceItemID,
InvoiceTax1ID = invoiceLines[i].InvoiceTax1ID,
InvoiceTax2ID = invoiceLines[i].InvoiceTax2ID,
SortOrder = i,
Description = invoiceLines[i].Description,
Quantity = invoiceLines[i].Quantity,
Price = invoiceLines[i].Price,
Discount = Convert.ToInt32(invoiceLines[i].Discount)
};
line.ID = _daoFactory.GetInvoiceLineDao().SaveOrUpdateInvoiceLine(line);
result.Add(line);
}
return result;
}
///
/// Updates the selected invoice with the parameters (contactId, consigneeId, etc.) specified in the request
///
/// Invoice ID
/// Invoice issue date
/// Invoice template type
/// Invoice contact ID
/// Invoice consignee ID
/// Invoice entity ID
/// Invoice billing address ID
/// Invoice delivery address ID
/// Invoice due date
/// Invoice language
/// Invoice currency
/// Invoice exchange rate
/// Invoice purchase order number
/// Invoice terms
/// Invoice description
/// Invoice lines list
/// Update invoice
/// Invoices
/// Invoice
///
///
///
[HttpPut(@"invoice/{id:int}")]
public InvoiceDto UpdateInvoice(
int id,
CreateOrUpdateInvoiceRequestDto inDto)
{
ApiDateTime issueDate = inDto.IssueDate;
int templateType = inDto.TemplateType;
int contactId = inDto.ContactId;
int consigneeId = inDto.ConsigneeId;
int entityId = inDto.EntityId;
int billingAddressID = inDto.BillingAddressID;
int deliveryAddressID = inDto.DeliveryAddressID;
ApiDateTime dueDate = inDto.DueDate;
string language = inDto.Language;
string currency = inDto.Currency;
decimal exchangeRate = inDto.ExchangeRate;
string purchaseOrderNumber = inDto.PurchaseOrderNumber;
string terms = inDto.Terms;
string description = inDto.Description;
IEnumerable invoiceLines = inDto.InvoiceLines;
var invoiceLinesList = invoiceLines != null ? invoiceLines.ToList() : new List();
if (!invoiceLinesList.Any() || !IsLinesForInvoiceCorrect(invoiceLinesList)) throw new ArgumentException();
var invoice = _daoFactory.GetInvoiceDao().GetByID(id);
if (invoice == null || !_crmSecurity.CanEdit(invoice)) throw new ItemNotFoundException();
invoice.IssueDate = issueDate;
invoice.TemplateType = (InvoiceTemplateType)templateType;
invoice.ContactID = contactId;
invoice.ConsigneeID = consigneeId;
invoice.EntityType = EntityType.Opportunity;
invoice.EntityID = entityId;
invoice.DueDate = dueDate;
invoice.Language = language;
invoice.Currency = !String.IsNullOrEmpty(currency) ? currency.ToUpper() : null; ;
invoice.ExchangeRate = exchangeRate;
invoice.PurchaseOrderNumber = purchaseOrderNumber;
invoice.Terms = terms;
invoice.Description = description;
invoice.JsonData = null;
_crmSecurity.DemandCreateOrUpdate(invoice);
if (billingAddressID > 0)
{
var address = _daoFactory.GetContactInfoDao().GetByID(billingAddressID);
if (address == null || address.InfoType != ContactInfoType.Address || address.Category != (int)AddressCategory.Billing || address.ContactID != contactId)
throw new ArgumentException();
}
if (deliveryAddressID > 0)
{
var address = _daoFactory.GetContactInfoDao().GetByID(deliveryAddressID);
if (address == null || address.InfoType != ContactInfoType.Address || address.Category != (int)AddressCategory.Postal || address.ContactID != consigneeId)
throw new ArgumentException();
}
_daoFactory.GetInvoiceDao().SaveOrUpdateInvoice(invoice);
_daoFactory.GetInvoiceLineDao().DeleteInvoiceLines(invoice.ID);
CreateInvoiceLines(invoiceLinesList, invoice);
_daoFactory.GetInvoiceDao().UpdateInvoiceJsonData(invoice, billingAddressID, deliveryAddressID);
if (_global.CanDownloadInvoices)
{
_pdfQueueWorker.StartTask(invoice.ID);
}
return _mapper.Map(invoice);
}
///
/// Returns the pdf file associated with the invoice with the ID specified in the request
///
/// Invoice ID
/// Get invoice pdf file
/// Invoices
/// File
[HttpGet(@"invoice/{invoiceid:int}/pdf")]
public Task> GetInvoicePdfExistOrCreateAsync(int invoiceid)
{
if (invoiceid <= 0) throw new ArgumentException();
var invoice = _daoFactory.GetInvoiceDao().GetByID(invoiceid);
if (invoice == null) throw new ItemNotFoundException();
if (!_crmSecurity.CanAccessTo(invoice))
{
throw _crmSecurity.CreateSecurityException();
}
return internalGetInvoicePdfExistOrCreateAsync(invoice);
}
private async Task> internalGetInvoicePdfExistOrCreateAsync(Invoice invoice)
{
return await _fileDtoHelper.GetAsync(await GetInvoicePdfExistingOrCreateAsync(invoice));
}
private async Task> GetInvoicePdfExistingOrCreateAsync(ASC.CRM.Core.Entities.Invoice invoice)
{
var existingFile = invoice.GetInvoiceFile(_daoFactory);
if (existingFile != null)
{
return existingFile;
}
else
{
var newFile = await _pdfCreator.CreateFileAsync(invoice, _daoFactory);
invoice.FileID = Int32.Parse(newFile.Id.ToString());
_daoFactory.GetInvoiceDao().UpdateInvoiceFileID(invoice.ID, invoice.FileID);
_daoFactory.GetRelationshipEventDao().AttachFiles(invoice.ContactID, invoice.EntityType, invoice.EntityID, new[] { invoice.FileID });
return newFile;
}
}
///
/// Returns information about the generation of the pdf file of the invoice
///
/// Invoice ID
/// Storage Url
/// Revision ID
/// Check invoice pdf file
/// Invoices
/// ConverterData
[HttpPost(@"invoice/converter/data")]
public Task CreateInvoiceConverterDataAsync(
[FromBody] CreateInvoiceConverterDataRequestDto inDto)
{
var invoiceId = inDto.InvoiceId;
var storageUrl = inDto.StorageUrl;
var revisionId = inDto.RevisionId;
if (invoiceId <= 0) throw new ArgumentException();
var invoice = _daoFactory.GetInvoiceDao().GetByID(invoiceId);
if (invoice == null) throw new ItemNotFoundException();
if (!_crmSecurity.CanAccessTo(invoice))
{
throw _crmSecurity.CreateSecurityException();
}
var converterData = new ConverterData
{
StorageUrl = storageUrl,
RevisionId = revisionId,
InvoiceId = invoiceId
};
var existingFile = invoice.GetInvoiceFile(_daoFactory);
if (existingFile != null)
{
converterData.FileId = invoice.FileID;
return System.Threading.Tasks.Task.FromResult(converterData);
}
return InternalCreateInvoiceConverterDataAsync(converterData, invoice);
}
private async Task InternalCreateInvoiceConverterDataAsync(ConverterData converterData, Invoice invoice)
{
var storageUrl = converterData.StorageUrl;
var revisionId = converterData.RevisionId;
if (string.IsNullOrEmpty(storageUrl) || string.IsNullOrEmpty(revisionId))
{
return await _pdfCreator.StartCreationFileAsync(invoice);
}
else
{
var convertedFile = await _pdfCreator.GetConvertedFileAsync(converterData, _daoFactory);
if (convertedFile != null)
{
invoice.FileID = Int32.Parse(convertedFile.Id.ToString());
_daoFactory.GetInvoiceDao().UpdateInvoiceFileID(invoice.ID, invoice.FileID);
_daoFactory.GetRelationshipEventDao().AttachFiles(invoice.ContactID, invoice.EntityType, invoice.EntityID, new[] { invoice.FileID });
converterData.FileId = invoice.FileID;
return converterData;
}
else
{
return converterData;
}
}
}
///
/// Returns the existence of the invoice with the Number specified in the request
///
/// Invoice number
/// Check invoice existence by number
/// Invoices
/// IsExist
[HttpGet(@"invoice/bynumber/exist")]
public Boolean GetInvoiceByNumberExistence(string number)
{
if (String.IsNullOrEmpty(number)) throw new ArgumentException();
return _daoFactory.GetInvoiceDao().IsExist(number);
}
///
/// Returns the detailed information about the invoice with the Number specified in the request
///
/// Invoice number
/// Get invoice by number
/// Invoices
/// Invoice
[HttpGet(@"invoice/bynumber")]
public InvoiceDto GetInvoiceByNumber(string number)
{
if (String.IsNullOrEmpty(number)) throw new ArgumentException();
var invoice = _daoFactory.GetInvoiceDao().GetByNumber(number);
if (invoice == null) throw new ItemNotFoundException();
if (!_crmSecurity.CanAccessTo(invoice))
{
throw _crmSecurity.CreateSecurityException();
}
return _mapper.Map(invoice);
}
///
/// Returns the list of invoice items matching the creteria specified in the request
///
/// Status
/// InventoryStock
/// Get invoice item list
/// Invoices
/// InvoiceItem list
[HttpGet(@"invoiceitem/filter")]
public IEnumerable GetInvoiceItems(int status, bool? inventoryStock)
{
IEnumerable result;
InvoiceItemSortedByType sortBy;
OrderBy invoiceOrderBy;
var searchString = _apiContext.FilterValue;
if (InvoiceItemSortedByType.TryParse(_apiContext.SortBy, true, out sortBy))
{
invoiceOrderBy = new OrderBy(sortBy, !_apiContext.SortDescending);
}
else if (String.IsNullOrEmpty(_apiContext.SortBy))
{
invoiceOrderBy = new OrderBy(InvoiceItemSortedByType.Name, true);
}
else
{
invoiceOrderBy = null;
}
var fromIndex = (int)_apiContext.StartIndex;
var count = (int)_apiContext.Count;
if (invoiceOrderBy != null)
{
var resultFromDao = _daoFactory.GetInvoiceItemDao().GetInvoiceItems(
searchString,
status,
inventoryStock,
fromIndex, count,
invoiceOrderBy);
result = _mapper.Map, List>(resultFromDao);
_apiContext.SetDataPaginated();
_apiContext.SetDataFiltered();
_apiContext.SetDataSorted();
}
else
{
var resultFromDao = _daoFactory.GetInvoiceItemDao().GetInvoiceItems(
searchString,
status,
inventoryStock,
0, 0,
null);
result = _mapper.Map, List>(resultFromDao);
}
int totalCount;
if (result.Count() < count)
{
totalCount = fromIndex + result.Count();
}
else
{
totalCount = _daoFactory.GetInvoiceItemDao().GetInvoiceItemsCount(
searchString,
status,
inventoryStock);
}
_apiContext.SetTotalCount(totalCount);
return result;
}
///
/// Returns the detailed information about the invoice item with the ID specified in the request
///
/// Invoice Item ID
/// Get invoice item by ID
/// Invoices
/// Invoice Item
[HttpGet(@"invoiceitem/{invoiceitemid:int}")]
public InvoiceItemDto GetInvoiceItemByID(int invoiceitemid)
{
if (invoiceitemid <= 0) throw new ArgumentException();
var invoiceItem = _daoFactory.GetInvoiceItemDao().GetByID(invoiceitemid);
if (invoiceItem == null) throw new ItemNotFoundException();
return _mapper.Map(invoiceItem);
}
///
/// Creates the invoice line with the parameters (invoiceId, invoiceItemId, etc.) specified in the request
///
/// Invoice ID
/// Invoice item ID
/// First invoice tax ID
/// Second invoice tax ID
/// Sort Order
/// Description
/// Quantity
/// Price
/// Discount
/// Create invoice line
/// Invoices
/// InvoiceLine
[HttpPost(@"invoiceline")]
public InvoiceLineDto CreateInvoiceLine(
CreateOrUpdateInvoiceLineRequestDto inDto
)
{
int invoiceId = inDto.InvoiceId;
int invoiceItemId = inDto.InvoiceItemId;
int invoiceTax1Id = inDto.InvoiceTax1Id;
int invoiceTax2Id = inDto.InvoiceTax2Id;
int sortOrder = inDto.SortOrder;
string description = inDto.Description;
int quantity = inDto.Quantity;
decimal price = inDto.Price;
int discount = inDto.Discount;
var invoiceLine = new InvoiceLine
{
InvoiceID = invoiceId,
InvoiceItemID = invoiceItemId,
InvoiceTax1ID = invoiceTax1Id,
InvoiceTax2ID = invoiceTax2Id,
SortOrder = sortOrder,
Description = description,
Quantity = quantity,
Price = price,
Discount = discount
};
if (invoiceId <= 0)
throw new ArgumentException();
var invoice = _daoFactory.GetInvoiceDao().GetByID(invoiceId);
_crmSecurity.DemandCreateOrUpdate(invoiceLine, invoice);
invoiceLine.ID = _daoFactory.GetInvoiceLineDao().SaveOrUpdateInvoiceLine(invoiceLine);
_daoFactory.GetInvoiceDao().UpdateInvoiceJsonDataAfterLinesUpdated(invoice);
if (_global.CanDownloadInvoices)
{
_pdfQueueWorker.StartTask(invoice.ID);
}
return _mapper.Map(invoiceLine);
}
///
/// Updates the selected invoice line with the parameters (invoiceId, invoiceItemId, etc.) specified in the request
///
/// Line ID
/// Invoice ID
/// Invoice item ID
/// First invoice tax ID
/// Second invoice tax ID
/// Sort Order
/// Description
/// Quantity
/// Price
/// Discount
/// Update invoice line
/// Invoices
/// InvoiceLine
[HttpPut(@"invoiceline/{id:int}")]
public InvoiceLineDto UpdateInvoiceLine(int id, CreateOrUpdateInvoiceLineRequestDto inDto)
{
int invoiceId = inDto.InvoiceId;
int invoiceItemId = inDto.InvoiceItemId;
int invoiceTax1Id = inDto.InvoiceTax1Id;
int invoiceTax2Id = inDto.InvoiceTax2Id;
int sortOrder = inDto.SortOrder;
string description = inDto.Description;
int quantity = inDto.Quantity;
decimal price = inDto.Price;
int discount = inDto.Discount;
if (invoiceId <= 0)
throw new ArgumentException();
var invoiceLine = _daoFactory.GetInvoiceLineDao().GetByID(id);
if (invoiceLine == null || invoiceLine.InvoiceID != invoiceId) throw new ItemNotFoundException();
invoiceLine.InvoiceID = invoiceId;
invoiceLine.InvoiceItemID = invoiceItemId;
invoiceLine.InvoiceTax1ID = invoiceTax1Id;
invoiceLine.InvoiceTax2ID = invoiceTax2Id;
invoiceLine.SortOrder = sortOrder;
invoiceLine.Description = description;
invoiceLine.Quantity = quantity;
invoiceLine.Price = price;
invoiceLine.Discount = discount;
var invoice = _daoFactory.GetInvoiceDao().GetByID(invoiceId);
_crmSecurity.DemandCreateOrUpdate(invoiceLine, invoice);
_daoFactory.GetInvoiceLineDao().SaveOrUpdateInvoiceLine(invoiceLine);
_daoFactory.GetInvoiceDao().UpdateInvoiceJsonDataAfterLinesUpdated(invoice);
if (_global.CanDownloadInvoices)
{
_pdfQueueWorker.StartTask(invoice.ID);
}
return _mapper.Map(invoiceLine);
}
///
/// Deletes the invoice line with the ID specified in the request
///
/// Line ID
/// Delete invoice line
/// Invoices
/// Line ID
[HttpDelete(@"invoiceline/{id:int}")]
public int DeleteInvoiceLine(int id)
{
var invoiceLine = _daoFactory.GetInvoiceLineDao().GetByID(id);
if (invoiceLine == null) throw new ItemNotFoundException();
if (!_daoFactory.GetInvoiceLineDao().CanDelete(invoiceLine.ID)) throw new Exception("Can't delete invoice line");
var invoice = _daoFactory.GetInvoiceDao().GetByID(invoiceLine.InvoiceID);
if (invoice == null) throw new ItemNotFoundException();
if (!_crmSecurity.CanEdit(invoice)) throw _crmSecurity.CreateSecurityException();
_daoFactory.GetInvoiceLineDao().DeleteInvoiceLine(id);
_daoFactory.GetInvoiceDao().UpdateInvoiceJsonDataAfterLinesUpdated(invoice);
if (_global.CanDownloadInvoices)
{
_pdfQueueWorker.StartTask(invoice.ID);
}
return id;
}
///
/// Creates the invoice item with the parameters (title, description, price, etc.) specified in the request
///
/// Item title
/// Item description
/// Item price
/// Item stock keeping unit
/// Item quantity
/// Item stock quantity
/// Track inventory
/// Item first invoice tax ID
/// Item second invoice tax ID
/// Create invoice item
/// Invoices
/// InvoiceItem
[HttpPost(@"invoiceitem")]
public InvoiceItemDto CreateInvoiceItem(
CreateOrUpdateInvoiceItemRequestDto inDto
)
{
string title = inDto.Title;
string description = inDto.Description;
decimal price = inDto.Price;
string sku = inDto.Sku;
int quantity = inDto.Quantity;
int stockQuantity = inDto.StockQuantity;
bool trackInventory = inDto.TrackInventory;
int invoiceTax1id = inDto.InvoiceTax1id;
int invoiceTax2id = inDto.InvoiceTax2id;
if (!_crmSecurity.IsAdmin)
{
throw _crmSecurity.CreateSecurityException();
}
if (String.IsNullOrEmpty(title) || price <= 0) throw new ArgumentException();
var invoiceItem = new InvoiceItem
{
Title = title,
Description = description,
Price = price,
StockKeepingUnit = sku,
StockQuantity = stockQuantity,
TrackInventory = trackInventory,
InvoiceTax1ID = invoiceTax1id,
InvoiceTax2ID = invoiceTax2id
};
invoiceItem = _daoFactory.GetInvoiceItemDao().SaveOrUpdateInvoiceItem(invoiceItem);
_messageService.Send(MessageAction.InvoiceItemCreated, _messageTarget.Create(invoiceItem.ID), invoiceItem.Title);
return _mapper.Map(invoiceItem);
}
///
/// Updates the selected invoice item with the parameters (title, description, price, etc.) specified in the request
///
/// Item ID
/// Item title
/// Item description
/// Item price
/// Item stock keeping unit
/// Item quantity
/// Item stock quantity
/// Track inventory
/// Item first invoice tax ID
/// Item second invoice tax ID
/// Update invoice item
/// Invoices
/// InvoiceItem
[HttpPut(@"invoiceitem/{id:int}")]
public InvoiceItemDto UpdateInvoiceItem(int id,
CreateOrUpdateInvoiceItemRequestDto inDto
)
{
string title = inDto.Title;
string description = inDto.Description;
decimal price = inDto.Price;
string sku = inDto.Sku;
int quantity = inDto.Quantity;
int stockQuantity = inDto.StockQuantity;
bool trackInventory = inDto.TrackInventory;
int invoiceTax1id = inDto.InvoiceTax1id;
int invoiceTax2id = inDto.InvoiceTax2id;
if (!_crmSecurity.IsAdmin)
{
throw _crmSecurity.CreateSecurityException();
}
if (id <= 0 || String.IsNullOrEmpty(title) || price <= 0) throw new ArgumentException();
if (!_daoFactory.GetInvoiceItemDao().IsExist(id)) throw new ItemNotFoundException();
var invoiceItem = new InvoiceItem
{
ID = id,
Title = title,
Description = description,
Price = price,
StockKeepingUnit = sku,
StockQuantity = stockQuantity,
TrackInventory = trackInventory,
InvoiceTax1ID = invoiceTax1id,
InvoiceTax2ID = invoiceTax2id
};
invoiceItem = _daoFactory.GetInvoiceItemDao().SaveOrUpdateInvoiceItem(invoiceItem);
_messageService.Send(MessageAction.InvoiceItemUpdated, _messageTarget.Create(invoiceItem.ID), invoiceItem.Title);
return _mapper.Map(invoiceItem);
}
///
/// Deletes the invoice item with the ID specified in the request
///
/// Item ID
/// Delete invoice item
/// Invoices
/// InvoiceItem
[HttpDelete(@"invoiceitem/{id:int}")]
public InvoiceItemDto DeleteInvoiceItem(int id)
{
if (!_crmSecurity.IsAdmin)
{
throw _crmSecurity.CreateSecurityException();
}
if (id <= 0) throw new ArgumentException();
var invoiceItem = _daoFactory.GetInvoiceItemDao().DeleteInvoiceItem(id);
if (invoiceItem == null) throw new ItemNotFoundException();
_messageService.Send(MessageAction.InvoiceItemDeleted, _messageTarget.Create(invoiceItem.ID), invoiceItem.Title);
return _mapper.Map(invoiceItem);
}
///
/// Deletes the group of invoice items with the IDs specified in the request
///
/// Item ID list
/// Delete Invoice item group
/// Invoices
/// InvoiceItem list
[HttpDelete(@"invoiceitem")]
public IEnumerable DeleteBatchItems(IEnumerable ids)
{
if (!_crmSecurity.IsAdmin)
{
throw _crmSecurity.CreateSecurityException();
}
if (ids == null) throw new ArgumentException();
ids = ids.Distinct();
var items = _daoFactory.GetInvoiceItemDao().DeleteBatchInvoiceItems(ids.ToArray());
_messageService.Send(MessageAction.InvoiceItemsDeleted, _messageTarget.Create(ids), items.Select(x => x.Title));
return _mapper.Map, List>(items);
}
///
/// Returns the list of invoice taxes
///
/// Get invoice taxes list
/// Invoices
/// InvoiceTax list
[HttpGet(@"invoice/tax")]
public IEnumerable GetInvoiceTaxes()
{
var responceFromDao = _daoFactory.GetInvoiceTaxDao().GetAll();
return _mapper.Map, List>(responceFromDao);
}
///
/// Creates the invoice tax with the parameters (name, description, rate) specified in the request
///
/// Tax name
/// Tax description
/// Tax rate
/// Create invoice tax
/// Invoices
/// InvoiceTax
[HttpPost(@"invoice/tax")]
public InvoiceTaxDto CreateInvoiceTax(
[FromBody] CreateOrUpdateInvoiceTaxRequestDto inDto)
{
string name = inDto.Name;
string description = inDto.Description;
decimal rate = inDto.Rate;
if (!_crmSecurity.IsAdmin)
{
throw _crmSecurity.CreateSecurityException();
}
if (String.IsNullOrEmpty(name)) throw new ArgumentException(CRMInvoiceResource.EmptyTaxNameError);
if (_daoFactory.GetInvoiceTaxDao().IsExist(name)) throw new ArgumentException(CRMInvoiceResource.ExistTaxNameError);
var invoiceTax = new InvoiceTax
{
Name = name,
Description = description,
Rate = rate
};
invoiceTax = _daoFactory.GetInvoiceTaxDao().SaveOrUpdateInvoiceTax(invoiceTax);
_messageService.Send(MessageAction.InvoiceTaxCreated, _messageTarget.Create(invoiceTax.ID), invoiceTax.Name);
return _mapper.Map(invoiceTax);
}
///
/// Updates the selected invoice tax with the parameters (name, description, rate) specified in the request
///
/// Tax ID
/// Tax name
/// Tax description
/// Tax rate
/// Update invoice tax
/// Invoices
/// InvoiceTax
[HttpPut(@"invoice/tax/{id:int}")]
public InvoiceTaxDto UpdateInvoiceTax(
int id,
CreateOrUpdateInvoiceTaxRequestDto inDto)
{
string name = inDto.Name;
string description = inDto.Description;
decimal rate = inDto.Rate;
if (!_crmSecurity.IsAdmin)
{
throw _crmSecurity.CreateSecurityException();
}
if (id <= 0 || String.IsNullOrEmpty(name)) throw new ArgumentException(CRMInvoiceResource.EmptyTaxNameError);
if (!_daoFactory.GetInvoiceTaxDao().IsExist(id)) throw new ItemNotFoundException();
var invoiceTax = new InvoiceTax
{
ID = id,
Name = name,
Description = description,
Rate = rate
};
invoiceTax = _daoFactory.GetInvoiceTaxDao().SaveOrUpdateInvoiceTax(invoiceTax);
_messageService.Send(MessageAction.InvoiceTaxUpdated, _messageTarget.Create(invoiceTax.ID), invoiceTax.Name);
return _mapper.Map(invoiceTax);
}
///
/// Delete the invoice tax with the ID specified in the request
///
/// Tax ID
/// Delete invoice tax
/// Invoices
/// InvoiceTax
[HttpDelete(@"invoice/tax/{id:int}")]
public InvoiceTaxDto DeleteInvoiceTax(int id)
{
if (!_crmSecurity.IsAdmin)
{
throw _crmSecurity.CreateSecurityException();
}
if (id <= 0) throw new ArgumentException();
var invoiceTax = _daoFactory.GetInvoiceTaxDao().DeleteInvoiceTax(id);
if (invoiceTax == null) throw new ItemNotFoundException();
_messageService.Send(MessageAction.InvoiceTaxDeleted, _messageTarget.Create(invoiceTax.ID), invoiceTax.Name);
return _mapper.Map(invoiceTax);
}
///
/// Get default invoice settings
///
/// Get default invoice settings
/// Invoices
/// InvoiceSetting
[HttpGet(@"invoice/settings")]
public InvoiceSetting GetSettings()
{
return _daoFactory.GetInvoiceDao().GetSettings();
}
///
/// Save default invoice number
///
/// Is autogenerated
/// Prefix
/// Number
/// Save default invoice number
/// Invoices
/// InvoiceSetting
[HttpPut(@"invoice/settings/name")]
public InvoiceSetting SaveNumberSettings(
SaveNumberSettingsRequestDto inDto
)
{
var autogenerated = inDto.AutoGenerated;
var number = inDto.Number;
var prefix = inDto.Prefix;
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
if (autogenerated && string.IsNullOrEmpty(number))
throw new ArgumentException();
if (autogenerated && _daoFactory.GetInvoiceDao().IsExist(prefix + number))
throw new ArgumentException();
var invoiceSetting = GetSettings();
invoiceSetting.Autogenerated = autogenerated;
invoiceSetting.Prefix = prefix;
invoiceSetting.Number = number;
var settings = _daoFactory.GetInvoiceDao().SaveInvoiceSettings(invoiceSetting);
_messageService.Send(MessageAction.InvoiceNumberFormatUpdated);
return settings;
}
///
/// Save default invoice terms
///
/// Terms
/// Save default invoice terms
/// Invoices
/// InvoiceSetting
[HttpPut(@"invoice/settings/terms")]
public InvoiceSetting SaveTermsSettings(string terms)
{
if (!_crmSecurity.IsAdmin) throw _crmSecurity.CreateSecurityException();
var invoiceSetting = GetSettings();
invoiceSetting.Terms = terms;
var result = _daoFactory.GetInvoiceDao().SaveInvoiceSettings(invoiceSetting);
_messageService.Send(MessageAction.InvoiceDefaultTermsUpdated);
return result;
}
/// false
[HttpPut(@"invoice/{invoiceid:int}/creationdate")]
public void SetInvoiceCreationDate(int invoiceid, ApiDateTime creationDate)
{
var dao = _daoFactory.GetInvoiceDao();
var invoice = dao.GetByID(invoiceid);
if (invoice == null || !_crmSecurity.CanAccessTo(invoice))
throw new ItemNotFoundException();
dao.SetInvoiceCreationDate(invoiceid, creationDate);
}
/// false
[HttpPut(@"invoice/{invoiceid:int}/lastmodifeddate")]
public void SetInvoiceLastModifedDate(int invoiceid, ApiDateTime lastModifedDate)
{
var dao = _daoFactory.GetInvoiceDao();
var invoice = dao.GetByID(invoiceid);
if (invoice == null || !_crmSecurity.CanAccessTo(invoice))
{
throw new ItemNotFoundException();
}
dao.SetInvoiceLastModifedDate(invoiceid, lastModifedDate);
}
private IEnumerable ToListInvoiceBaseDtos(ICollection items)
{
if (items == null || items.Count == 0) return new List();
var result = new List();
var contactIDs = items.Select(item => item.ContactID);
contactIDs.ToList().AddRange(items.Select(item => item.ConsigneeID));
var contacts = _daoFactory.GetContactDao().GetContacts(contactIDs.Distinct().ToArray())
.ToDictionary(item => item.ID, x => _mapper.Map(x));
foreach (var invoice in items)
{
var invoiceDto = _mapper.Map(invoice);
if (contacts.ContainsKey(invoice.ContactID))
{
invoiceDto.Contact = contacts[invoice.ContactID];
}
if (contacts.ContainsKey(invoice.ConsigneeID))
{
invoiceDto.Consignee = contacts[invoice.ContactID];
}
if (invoice.EntityID > 0)
{
invoiceDto.Entity = ToEntityDto(invoice.EntityType, invoice.EntityID); //Need to optimize
}
invoiceDto.Cost = invoice.GetInvoiceCost(_daoFactory);
result.Add(invoiceDto);
}
return result;
}
private EntityDto ToEntityDto(EntityType entityType, int entityID)
{
if (entityID == 0) return null;
var result = new EntityDto
{
EntityId = entityID
};
switch (entityType)
{
case EntityType.Case:
var caseObj = _daoFactory.GetCasesDao().GetByID(entityID);
if (caseObj == null)
return null;
result.EntityType = "case";
result.EntityTitle = caseObj.Title;
break;
case EntityType.Opportunity:
var dealObj = _daoFactory.GetDealDao().GetByID(entityID);
if (dealObj == null)
return null;
result.EntityType = "opportunity";
result.EntityTitle = dealObj.Title;
break;
default:
return null;
}
return result;
}
}
}