/* * * (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.Api.Documents; 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.MessagingSystem; using ASC.Web.Api.Routing; 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 FileWrapperHelper _fileWrapperHelper; private readonly PdfCreator _pdfCreator; private readonly SettingsManager _settingsManager; private readonly ApiDateTimeHelper _apiDateTimeHelper; private readonly ApiContext _apiContext; private readonly MessageService _messageService; private readonly MessageTarget _messageTarget; public InvoicesController(CRMSecurity crmSecurity, DaoFactory daoFactory, ApiContext apiContext, MessageTarget messageTarget, MessageService messageService, ApiDateTimeHelper apiDateTimeHelper, SettingsManager settingsManager, FileWrapperHelper fileWrapperHelper, PdfCreator pdfCreator, Global global, PdfQueueWorker pdfQueueWorker, IMapper mapper) : base(daoFactory, crmSecurity, mapper) { _apiContext = apiContext; _messageTarget = messageTarget; _messageService = messageService; _apiDateTimeHelper = apiDateTimeHelper; _settingsManager = settingsManager; _pdfCreator = pdfCreator; _fileWrapperHelper = fileWrapperHelper; _global = global; _pdfQueueWorker = pdfQueueWorker; _mapper = mapper; } /// /// Returns the detailed information about the invoice with the ID specified in the request /// /// Invoice ID /// Get invoice by ID /// Invoices /// Invoice [Read(@"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 [Read(@"invoice/sample")] public InvoiceDto GetInvoiceSample() { var defaultCurrency = _settingsManager.Load().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 [Read(@"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 [Read(@"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.Compare(entityType, "contact", true) == 0 || String.Compare(entityType, "opportunity", true) == 0 || String.Compare(entityType, "case", true) == 0)) 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 [Read(@"{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 [Update(@"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 [Delete(@"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 [Delete(@"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 /// /// /// [Create(@"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 /// /// /// [Update(@"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 [Read(@"invoice/{invoiceid:int}/pdf")] public FileWrapper GetInvoicePdfExistOrCreate(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 _fileWrapperHelper.Get(GetInvoicePdfExistingOrCreate(invoice)); } private ASC.Files.Core.File GetInvoicePdfExistingOrCreate(ASC.CRM.Core.Entities.Invoice invoice) { var existingFile = invoice.GetInvoiceFile(_daoFactory); if (existingFile != null) { return existingFile; } else { var newFile = _pdfCreator.CreateFile(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 [Create(@"invoice/converter/data")] public ConverterData GetInvoiceConverterData(int invoiceId, string storageUrl, string 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 converterData; } if (string.IsNullOrEmpty(storageUrl) || string.IsNullOrEmpty(revisionId)) { return _pdfCreator.StartCreationFileAsync(invoice); } else { var convertedFile = _pdfCreator.GetConvertedFile(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 [Read(@"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 [Read(@"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 [Read(@"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 [Read(@"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 [Create(@"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 [Update(@"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 [Delete(@"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 [Create(@"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 [Update(@"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 [Delete(@"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 [Delete(@"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 [Read(@"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 [Create(@"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 [Update(@"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 [Delete(@"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 [Read(@"invoice/settings")] public InvoiceSetting GetSettings() { return _daoFactory.GetInvoiceDao().GetSettings(); } /// /// Save default invoice number /// /// Is autogenerated /// Prefix /// Number /// Save default invoice number /// Invoices /// InvoiceSetting [Update(@"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 [Update(@"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 [Update(@"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 [Update(@"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; } } }