Skip to content
This repository was archived by the owner on Apr 6, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
e9a57c7
CustomerInvoice Location
traventusAY Jul 5, 2022
25c81d2
Merge branch 'dev' of https://github.com/angoyd/Visma.Net into dev
traventusAY Jul 5, 2022
06a435c
Added GetAllItemClasses
traventusAY Jul 6, 2022
cd55dfd
Added Overrideseries to SalesOrder
traventusAY Aug 18, 2022
872aac9
Fix for salesorder line
traventusAY Aug 18, 2022
a88afe4
Added fields to Inventory
traventusAY Sep 23, 2022
5fb6598
Added supplier payment
traventusAY Oct 4, 2022
87ad8fc
FIx for packaging
traventusAY Oct 4, 2022
2e9d457
Removed Id from subaccount dto
traventusAY Oct 4, 2022
d6c9111
Added currency to SupplierPayment
traventusAY Oct 7, 2022
6112f96
Added cashAccount supplierInvoice
traventusAY Dec 13, 2022
742f5e3
Merge
traventusAY Dec 13, 2022
c6e4906
Added InventoryUnits
traventusAY Dec 13, 2022
647d0e5
Fixes for BAccount in location.
traventusAY Dec 19, 2022
f21d7ef
Fix subaccount problem with test
traventusAY Dec 19, 2022
7a8634d
Fixes for test after changes and additions
traventusAY Dec 19, 2022
38813cf
Fixes for tests
traventusAY Dec 19, 2022
2932554
Added helperfunction to get token from Visma connect
traventusAY Dec 22, 2022
e7efb92
Merge branch 'main' into dev
omelhus Feb 15, 2023
cc55c1b
Inital version with salesorder V3
traventusAY Mar 7, 2023
84de0af
Merge branch 'dev' of https://github.com/angoyd/Visma.Net into dev
traventusAY Mar 7, 2023
a2d7f67
Added aktive to Subaccount
traventusAY Aug 21, 2023
0a9253b
Split of SalesOrderV3 to own project
traventusAY Sep 25, 2023
f84b027
Fixes for OrderV3 client
traventusAY Sep 29, 2023
673495f
Fix for asyncs
traventusAY Oct 26, 2023
1af0f73
4.2.1.9
traventusAY Oct 26, 2023
838dac5
Added fields to CustomerINvoiceLine
traventusAY Oct 27, 2023
2281610
Merge branch 'main' into dev
traventusAY Oct 31, 2023
0f7c9d5
Added fields to invoice
traventusAY Nov 16, 2023
2a400e4
Merge branch 'dev' of https://github.com/angoyd/Visma.Net into dev
traventusAY Nov 16, 2023
a4423b0
Fix for token
traventusAY Dec 27, 2023
d668977
More fix
traventusAY Dec 27, 2023
cae2b69
Scope check fix
traventusAY Dec 27, 2023
00df39b
Scopes again
traventusAY Dec 27, 2023
0a669df
Update Etag for OrderV3 and addAttchmentInventory
traventusAY Feb 8, 2024
4d8b7d9
Fixed to customer
traventusAY Apr 8, 2024
167dc7f
Kititem and supplieraccount
traventusAY Apr 10, 2024
0aa0768
Added rot/rut salesorder V3
traventusAY May 20, 2024
f2fc4ef
Version bump
traventusAY May 20, 2024
0d8607c
Fixes to inventory
traventusAY May 23, 2024
a96a85d
Updated SalesOrderNG
traventusAY Feb 5, 2025
70d732d
Upgrade of depencencies
traventusAY Feb 11, 2025
8fa00e1
Make exchange rate nullable
traventusAY Mar 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
278 changes: 278 additions & 0 deletions Visma.Net.SalesOrderNG/ClientSalesOrderV3.Extensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
using Visma.Net.SalesOrderNG.Exceptions;
using Visma.Net.SalesOrderNG.Models;
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using Visma.Net.SalesOrderNG.Lib;
using System.Reflection;
using Newtonsoft.Json.Linq;
using System.IdentityModel.Tokens.Jwt;

namespace Visma.Net.SalesOrderNG
{
public partial class ClientSalesOrderV3
{
Helpers.VismaNetAuthorization _authorization;

public static string Version { get; private set; }
/// <summary>
/// Provide a name for your application. This will make it easier for Visma to identify your integration in their logs.
/// </summary>
public static string _ApplicationName { get; set; }

private static int maxConcurrentRequests;
/// <summary>
/// Gets or sets the maximum number of concurrent requests sent to the API. Min: 1, Max: 8.
/// </summary>
public static int MaxConcurrentRequests
{
get
{
var requestLimit = maxConcurrentRequests > 0 ? maxConcurrentRequests : 8;
return requestLimit > 8 ? 8 : requestLimit;
}

set => maxConcurrentRequests = value > 0 ? value : maxConcurrentRequests;
}

private static int maxRetries;
/// <summary>
/// Gets or sets the maximum number of retries sent to the API. Min: 1, Max: 5, Default: 5.
/// </summary>
public static int MaxRetries
{
get { return maxRetries > 0 ? maxRetries : 5; }
set => maxRetries = (value > 0 && value < 6) ? value : 5;
}

public ClientSalesOrderV3(Helpers.VismaNetAuthorization auth, string ApplicationName) : this()
{
_authorization = auth;
_ApplicationName = ApplicationName;
Version = Assembly.GetExecutingAssembly().GetName().Version.ToString();

}

partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder)
{
urlBuilder.Insert(0, VismaNetControllers.SalesOrderV3BaseUrl);
AddVismaNetAuth(request);

JwtSecurityToken jwtToken = null;
if (!string.IsNullOrEmpty(_authorization.Token))
{
jwtToken = new JwtSecurityToken(_authorization.Token);
}
else if (!string.IsNullOrEmpty(_authorization.VismaConnectToken))
{
jwtToken = new JwtSecurityToken(_authorization.VismaConnectToken);
}
else
{
throw new VismaConnectException("No token found");
}


if (!_authorization.VismaConnectScopes.Contains("visma.net.erp.salesorder") && !jwtToken.Claims.Any(c => c.Value.Contains("visma.net.erp.salesorder")))
{
throw new VismaConnectException("Scope has to contain visma.net.erp.salesorder scopes to use SalesOrderV3");
}

}

private void AddVismaNetAuth(HttpRequestMessage request)
{
if (_authorization.VismaConnectClientId != null) // new auth via Visma Connect
{
// Check for token expired ( 5 minutes grace )
if (_authorization.VismaConnectToken == null || _authorization.VismaConnectTokenExpire.AddMinutes(-5) < DateTimeOffset.UtcNow)
{
var vToken = VismaNetApiHelper.GetTokenFromVismaConnect(_authorization.VismaConnectClientId, _authorization.VismaConnectClientSecret, _authorization.VismaConnectTenantId, _authorization.VismaConnectScopes).Result;
_authorization.VismaConnectToken = vToken.access_token;
_authorization.VismaConnectTokenExpire = vToken.expires_on;
}
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _authorization.VismaConnectToken);
}
else if (!string.IsNullOrEmpty(_authorization.Token))
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _authorization.Token);
}
else
{
throw new VismaNetExceptionClientIdMissing();
}
}

public async Task<IEnumerable<CustomerDto>> getAllCustomer(string filter = null)
{
int InitialPageSize = 100;
var firstPage = await Customers_GetList_Async(filter, InitialPageSize, 0);
var rsp = new List<CustomerDto>();
if (firstPage == null)
return rsp;

rsp.AddRange(firstPage.Result.Value);
var count = firstPage.Result.Value.Count();
if (firstPage.Result.TotalCount > count && count > 0)
{
var totalCount = (int)firstPage.Result.TotalCount;
var pageSize = count;
var pageCount = totalCount / pageSize;
var semaphore = new SemaphoreSlim(ClientSalesOrderV3.MaxConcurrentRequests);
var taskList = new List<Task<SwaggerResponse<CustomerDtoPagedResult>>>();
foreach (var page in Enumerable.Range(1, pageCount))
{
await semaphore.WaitAsync();
taskList.Add(Task.Run(async () =>
{
try
{
return await Customers_GetList_Async(filter, pageSize, page);
}
finally
{
semaphore.Release();
}
}));
}
var tasks = await Task.WhenAll(taskList);
rsp.AddRange(tasks.SelectMany(x => x.Result.Value));
}
return rsp;
}

public async Task<IEnumerable<SalesOrderListDto>> getAllSalesOrder(string customerId = null, string status = null, DateTimeOffset? modifiedSince = null, string orderBy = null, string filter = null)
{
int InitialPageSize = 100;
var firstPage = await SalesOrders_GetList_Async(customerId, status, modifiedSince, InitialPageSize, 0, orderBy, filter);
var rsp = new List<SalesOrderListDto>();
if (firstPage == null)
return rsp;

rsp.AddRange(firstPage.Result.Value);
var count = firstPage.Result.Value.Count();
if (firstPage.Result.TotalCount > count && count > 0)
{
var totalCount = (int)firstPage.Result.TotalCount;
var pageSize = count;
var pageCount = totalCount / pageSize;
var semaphore = new SemaphoreSlim(ClientSalesOrderV3.MaxConcurrentRequests);
var taskList = new List<Task<SwaggerResponse<SalesOrderListDtoPagedResult>>>();
foreach (var page in Enumerable.Range(1, pageCount))
{
await semaphore.WaitAsync();
taskList.Add(Task.Run(async () =>
{
try
{
return await SalesOrders_GetList_Async(customerId, status, modifiedSince, pageSize, page, orderBy, filter);
}
finally
{
semaphore.Release();
}
}));
}
var tasks = await Task.WhenAll(taskList);
rsp.AddRange(tasks.SelectMany(x => x.Result.Value));
}
return rsp;
}

public async Task<IEnumerable<SalesOrderListDto>> getAllSalesOrderOfType(string type, string customerId = null, string status = null, DateTimeOffset? modifiedSince = null, string orderBy = null, string filter = null)
{
int InitialPageSize = 100;
var firstPage = await SalesOrders_GetList_typeAsync(type,customerId, status, modifiedSince, InitialPageSize, 0, orderBy, filter);
var rsp = new List<SalesOrderListDto>();
if (firstPage == null)
return rsp;

rsp.AddRange(firstPage.Result.Value);
var count = firstPage.Result.Value.Count();
if (firstPage.Result.TotalCount > count && count > 0)
{
var totalCount = (int)firstPage.Result.TotalCount;
var pageSize = count;
var pageCount = totalCount / pageSize;
var semaphore = new SemaphoreSlim(ClientSalesOrderV3.MaxConcurrentRequests);
var taskList = new List<Task<SwaggerResponse<SalesOrderListDtoPagedResult>>>();
foreach (var page in Enumerable.Range(1, pageCount))
{
await semaphore.WaitAsync();
taskList.Add(Task.Run(async () =>
{
try
{
return await SalesOrders_GetList_typeAsync(type, customerId, status, modifiedSince, pageSize, page, orderBy, filter);
}
finally
{
semaphore.Release();
}
}));
}
var tasks = await Task.WhenAll(taskList);
rsp.AddRange(tasks.SelectMany(x => x.Result.Value));
}
return rsp;
}

public async Task<IEnumerable<SalesOrderLineDto>> getAllSalesOrderLine(string type = null, string orderId = null)
{
int InitialPageSize = 100;
var firstPage = await SalesOrders_GetItemLines_typeorderIdlinesAsync(type, orderId, InitialPageSize, 0);
var rsp = new List<SalesOrderLineDto>();
if (firstPage == null)
return rsp;

rsp.AddRange(firstPage.Result.Value);
var count = firstPage.Result.Value.Count();
if (firstPage.Result.TotalCount > count && count > 0)
{
var totalCount = (int)firstPage.Result.TotalCount;
var pageSize = count;
var pageCount = totalCount / pageSize;
var semaphore = new SemaphoreSlim(ClientSalesOrderV3.MaxConcurrentRequests);
var taskList = new List<Task<SwaggerResponse<SalesOrderLineDtoPagedResult>>>();
foreach (var page in Enumerable.Range(1, pageCount))
{
await semaphore.WaitAsync();
taskList.Add(Task.Run(async () =>
{
try
{
return await SalesOrders_GetItemLines_typeorderIdlinesAsync(type, orderId, InitialPageSize, 0);
}
finally
{
semaphore.Release();
}
}));
}
var tasks = await Task.WhenAll(taskList);
rsp.AddRange(tasks.SelectMany(x => x.Result.Value));
}
return rsp;
}

public async Task<SalesOrderDto> createNewSalesOrder(NewSalesOrderCommand newSalesOrder, IEnumerable<SalesOrderExpansions> expansions = null)
{
var resp = await SalesOrders_CreateNewItem_Async(newSalesOrder);
// https://salesorder.visma.net/api/v3/SalesOrders/SO/000223
var uri = resp.Headers.FirstOrDefault(h => h.Key == "Location").Value.First();
Uri uri1 = new Uri(uri);
var ordno = uri1.Segments[uri1.Segments.Length - 1].Replace("/", "");
var type = uri1.Segments[uri1.Segments.Length - 2].Replace("/","");
var ord = await SalesOrders_GetItemAsync_typeorderIdAsync(type, ordno,expansions);
return ord.Result;
}

}
}
Loading
Loading