Base.Net classes & Accounts module added
This commit is contained in:
@@ -8,6 +8,8 @@
|
||||
* Base class library. .Net Standard 2.1. C#.
|
||||
* SACS Standard Dbas
|
||||
* Base database interface library. .Net Standard 2.1. C#.
|
||||
* SACS Standard Accounts
|
||||
* Base Acounts system interface library. .Net Standard 2.1. C#.
|
||||
* SACS Standard Mob
|
||||
* Base Mobile application library. .Net Standard 2.1. C#.
|
||||
* SACS Core Web
|
||||
|
||||
@@ -18,6 +18,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution files", "Solution
|
||||
ReadMe.md = ReadMe.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SacsStandardAccounts", "SacsStandardAccounts\SacsStandardAccounts.csproj", "{C62999E2-1947-4EB7-82D2-A0EDB67D2F10}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -44,6 +46,10 @@ Global
|
||||
{70F1302F-E8F2-49CB-A09D-889DA59681DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{70F1302F-E8F2-49CB-A09D-889DA59681DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{70F1302F-E8F2-49CB-A09D-889DA59681DD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C62999E2-1947-4EB7-82D2-A0EDB67D2F10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C62999E2-1947-4EB7-82D2-A0EDB67D2F10}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C62999E2-1947-4EB7-82D2-A0EDB67D2F10}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C62999E2-1947-4EB7-82D2-A0EDB67D2F10}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -16,8 +16,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SacsStandardAccounts\SacsStandardAccounts.csproj" />
|
||||
<ProjectReference Include="..\SacsStandardBase\SacsStandardBase.csproj" />
|
||||
<ProjectReference Include="..\SacsStandardDbas\SacsStandardDbas.csproj" />
|
||||
<ProjectReference Include="..\SacsStandardMob\SacsStandardMob.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Sarand.Net.Standard.Accounts.OpenAuth
|
||||
{
|
||||
//=======================================================================
|
||||
internal class SaOpenAuth
|
||||
{
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Sarand.Net.Standard.Accounts.QuickBooks.App
|
||||
{
|
||||
//=======================================================================
|
||||
public static class Qbk
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// QuickBooks version.
|
||||
public enum Version
|
||||
{
|
||||
Unknown = 0,
|
||||
Local2008 = 2008
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
public enum ConnectionType
|
||||
{
|
||||
Unknown = 0,
|
||||
/// <summary>Local QuickBooks</summary>
|
||||
LocalQBD = 1,
|
||||
/// <summary>RDS connection</summary>
|
||||
RemoteQBD = 2,
|
||||
/// <summary>SDK application launched QuickBooks in interactive mode</summary>
|
||||
LocalQBDLaunchUI = 3,
|
||||
/// <summary>Online edition</summary>
|
||||
RemoteQBOE = 4,
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Jul2016 Online configuration.
|
||||
public enum OnlineInstance
|
||||
{
|
||||
Unknown = 0,
|
||||
Sandbox = 10,
|
||||
Production = 20,
|
||||
};
|
||||
public enum OnlineProduct
|
||||
{
|
||||
Unknown = 0,
|
||||
Accounts,
|
||||
Payments,
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// QBooks Online.
|
||||
public enum OnlineRequestType
|
||||
{
|
||||
Unknown = 0,
|
||||
Query,
|
||||
CompanyInfo,
|
||||
Vendor,
|
||||
Customer,
|
||||
Item,
|
||||
Invoice,
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// QBooks reference types.
|
||||
public enum ReferenceDataType
|
||||
{
|
||||
Unknown = 0,
|
||||
CustomerType = 10,
|
||||
ShipMethod,
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// QBooks item types.
|
||||
public enum EntityType
|
||||
{
|
||||
Unknown = 0,
|
||||
// Reference data types.
|
||||
CustomerType = 100,
|
||||
// Primary data types.
|
||||
Company = 200,
|
||||
Account,
|
||||
Vendor,
|
||||
Customer,
|
||||
Item,
|
||||
PurchaseOrder,
|
||||
SalesOrder,
|
||||
Invoice_Product,
|
||||
Invoice_Service,
|
||||
// Internal.
|
||||
Invoice_Header,
|
||||
Invoice_Line,
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Financial year.
|
||||
public enum FinancialYear
|
||||
{
|
||||
Current,
|
||||
Prior1,
|
||||
Prior2,
|
||||
Prior3,
|
||||
Prior4,
|
||||
Prior5
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
using Sarand.Net.Standard.Accounts.QuickBooks.Base;
|
||||
using Sarand.Net.Standard.Accounts.QuickBooks.Local;
|
||||
using Sarand.Net.Standard.Accounts.QuickBooks.Online;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
|
||||
namespace Sarand.Net.Standard.Accounts.QuickBooks.App
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaQuickBooksConsole : SaErrorStateItem
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private static readonly List<TypeCodeDesc> qbkEntityTypes = new List<TypeCodeDesc>();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Static initialisation.
|
||||
static SaQuickBooksConsole ()
|
||||
{
|
||||
// QuickBooks data types:
|
||||
qbkEntityTypes.Add(Qbk.EntityType.Account, "ACCNT", "Account");
|
||||
qbkEntityTypes.Add(Qbk.EntityType.Vendor, "VEND", "Vendor");
|
||||
qbkEntityTypes.Add(Qbk.EntityType.Customer, "CUST", "Customer");
|
||||
qbkEntityTypes.Add(Qbk.EntityType.Item, "ITEM", "Item");
|
||||
qbkEntityTypes.Add(Qbk.EntityType.PurchaseOrder, "PURO", "Purchase order");
|
||||
qbkEntityTypes.Add(Qbk.EntityType.SalesOrder, "SALO", "Sales order");
|
||||
qbkEntityTypes.Add(Qbk.EntityType.Invoice_Product, "INVPRD", "Product invoice");
|
||||
qbkEntityTypes.Add(Qbk.EntityType.Invoice_Service, "INVSRV", "Service invoice");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
protected SaQuickBooksConsole ()
|
||||
{
|
||||
}
|
||||
public static SaQuickBooksConsole CreateConsole ()
|
||||
{
|
||||
return new SaQuickBooksConsole();
|
||||
}
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public static List<TypeCodeDesc> EntityTypeCodes { get { return new List<TypeCodeDesc>(qbkEntityTypes); } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// QuickBooks API.
|
||||
public SaQuickBooksApiConsole CreateApiConsole (SaQuickBooksParams prmQbk)
|
||||
{
|
||||
ClearErrorState();
|
||||
if (prmQbk.ConnectionType == Qbk.ConnectionType.LocalQBD)
|
||||
{
|
||||
if (!HasErrorState() && StringUtil.IsEmpty(prmQbk.CompanyFilePath)) SetErrorState("QuickBooks company file must be specified.");
|
||||
if (!HasErrorState() && !FileUtil.IsFile(prmQbk.CompanyFilePath)) SetErrorState("QuickBooks company file does not exist.");
|
||||
if (!HasErrorState())
|
||||
return new SaQuickBooksApiConsole_Local(prmQbk);
|
||||
}
|
||||
else if (prmQbk.ConnectionType == Qbk.ConnectionType.RemoteQBOE)
|
||||
{
|
||||
if (!HasErrorState() && (int)prmQbk.OnlineInstance < 1) SetErrorState("QuickBooks instance must be specified.");
|
||||
//if (!HasErrorState() && StringUtil.IsEmpty(prmQbk.CompanyId)) SetErrorState("QuickBooks company Id must be specified.");
|
||||
if (!HasErrorState())
|
||||
return new SaQuickBooksApiConsole_Online(prmQbk);
|
||||
}
|
||||
else
|
||||
{
|
||||
String sMsg = "Unsupported connection type: "+prmQbk.ConnectionType.ToString();
|
||||
SetErrorState(sMsg);
|
||||
if (SacsSystem.DebugMode)
|
||||
SaLogger.Debug(GetType().Name + ".CreateApiConsole " + sMsg);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// QuickBooks API.
|
||||
public bool TestInterface (SaQuickBooksParams prmQbk)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Sarand.Net.Standard.Accounts.QuickBooks.App
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaQuickBooksParams
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaQuickBooksParams ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
/// <summary>LocalQBD, RemoteQBD etc.</summary>
|
||||
public Qbk.ConnectionType ConnectionType { get; set; } = Qbk.ConnectionType.Unknown;
|
||||
public String AppId { get; set; } = "";
|
||||
public String AppName { get; set; } = "";
|
||||
public String CompanyFilePath { get; set; } = "";
|
||||
public String Username { get; set; } = "";
|
||||
public String Password { get; set; } = "";
|
||||
/// <summary>QBFileMode: qbFileOpenSingleUser, qbFileOpen, qbFileOpenDoNotCare</summary>
|
||||
public int OpenFileMode { get; set; } = 0;
|
||||
// Jul2016 Online configuration.
|
||||
public Qbk.OnlineInstance OnlineInstance { get; set; } = Qbk.OnlineInstance.Unknown;
|
||||
public DateTime OnlineAuthorisedOn { get; set; } = DateTime.MinValue;
|
||||
public String CompanyId { get; set; } = "";
|
||||
public String AppToken { get; set; } = "";
|
||||
public String AppTokenSecret { get; set; } = "";
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using Sarand.Net.Standard.Accounts.QuickBooks.App;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Sarand.Net.Standard.Accounts.QuickBooks.Base
|
||||
{
|
||||
//=======================================================================
|
||||
public abstract class SaQuickBooksApiConsole : SaErrorStateItem
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private readonly SaQuickBooksParams prmQbk;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Static initialisation.
|
||||
static SaQuickBooksApiConsole ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
protected SaQuickBooksApiConsole (SaQuickBooksParams prmQbk)
|
||||
{
|
||||
this.prmQbk = prmQbk;
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// D a t a I t e m s
|
||||
//-------------------------------------------------------------------
|
||||
public abstract SaQuickBooksDataItem CreateDataItem (Qbk.EntityType entityType);
|
||||
/// <summary>Create data item iterator (to retrieve list of data items of specific type).</summary>
|
||||
public abstract SaQuickBooksDataItem.Iterator CreateItemIterator (Qbk.EntityType entityType);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
using Sarand.Net.Standard.Accounts.QuickBooks.App;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Sarand.Net.Standard.Accounts.QuickBooks.Base
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaQuickBooksDataItem : SacsDisposable
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private readonly NamedValue.Map values = new NamedValue.Map();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Static initialisation.
|
||||
static SaQuickBooksDataItem ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
protected SaQuickBooksDataItem (Qbk.EntityType entityType)
|
||||
{
|
||||
EntityType = entityType;
|
||||
}
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public Qbk.EntityType EntityType { get; }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Field values.
|
||||
public bool HasValue (String name)
|
||||
{
|
||||
return values.HasValue(name);
|
||||
}
|
||||
public DataValue.DataType GetValueType (String name)
|
||||
{
|
||||
DataValue value = GetValue(name);
|
||||
return value?.GetDataType() ?? DataValue.DataType.Unknown;
|
||||
}
|
||||
public DataValue GetValue (String name)
|
||||
{
|
||||
return values.GetValue(name);
|
||||
}
|
||||
public NamedValue.Map GetValues ()
|
||||
{
|
||||
return new NamedValue.Map(values.Values);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Update attributes.
|
||||
public bool SetValue (String name, DataValue value)
|
||||
{
|
||||
return values.AddValue(name, value);
|
||||
}
|
||||
public bool SetValue (String name, String value)
|
||||
{
|
||||
return SetValue(name, new DataValue(value));
|
||||
}
|
||||
public bool SetValue (String name, bool value)
|
||||
{
|
||||
return SetValue(name, new DataValue(value));
|
||||
}
|
||||
public bool SetValue (String name, long value)
|
||||
{
|
||||
return SetValue(name, new DataValue(value));
|
||||
}
|
||||
public bool SetValue (String name, double value)
|
||||
{
|
||||
return SetValue(name, new DataValue(value));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// P a r a m e t e r s
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>Data item parameters.</summary>
|
||||
public class Params
|
||||
{
|
||||
/// <summary>Online: EntityId.</summary>
|
||||
public String EntityListId { get; set; } = "";
|
||||
/// <summary>Item identifier (ListId etc, partial = 'starts with').</summary>
|
||||
public String ItemId { get; set; } = "";
|
||||
/// <summary>Item identifier (ListId etc, partial = 'starts with').</summary>
|
||||
public String ItemIdPartial { get; set; } = "";
|
||||
public String EntityCode { get; set; } = "";
|
||||
/// <summary>Item name or description (partial = 'starts with').</summary>
|
||||
public String EntityName { get; set; } = "";
|
||||
/// <summary>Item name or description (partial = 'starts with').</summary>
|
||||
public String EntityNamePartial { get; set; } = "";
|
||||
/// <summary>FOB (invoice) filter.</summary>
|
||||
public String Fob { get; set; } = "";
|
||||
/// <summary>Avoid processing older items (orders etc.).</summary>
|
||||
public DateTime EarliestDate { get; set; } = DateTime.MinValue;
|
||||
public int MaxItems { get; set; } = 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// I t e r a t o r
|
||||
//-------------------------------------------------------------------
|
||||
public abstract class Iterator : SaErrorStateItem
|
||||
{
|
||||
//---------------------------------------------------------------
|
||||
// Data members.
|
||||
private SaQuickBooksDataItem.Params prmQbk;
|
||||
private int itemCount = 0;
|
||||
//---------------------------------------------------------------
|
||||
// Construction.
|
||||
protected Iterator (Qbk.EntityType entityType)
|
||||
{
|
||||
EntityType = entityType;
|
||||
}
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// Properties.
|
||||
public Qbk.EntityType EntityType { get; }
|
||||
public SaQuickBooksDataItem.Params Params { get { return prmQbk; } }
|
||||
public static int PageLengthDefault { get; } = 20;
|
||||
public int ItemsFound { get; protected set; }
|
||||
public bool AtStart { get; protected set; }
|
||||
//---------------------------------------------------------------
|
||||
// Data items.
|
||||
/// <summary>Total number of items (do this after GotoStart).</summary>
|
||||
public virtual int GetItemCount ()
|
||||
{
|
||||
ClearErrorState();
|
||||
if (itemCount < 0 && AtStart)
|
||||
{
|
||||
// Retrieve and discard the first item in the list.
|
||||
SaQuickBooksDataItem item = GetNextItem();
|
||||
if (item != null) item.Dispose();
|
||||
// Reset to start of list.
|
||||
ItemsFound = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/// <summary>Reset the item iteration.</summary>
|
||||
public virtual void GotoStart (SaQuickBooksDataItem.Params prmQbk)
|
||||
{
|
||||
ClearErrorState();
|
||||
this.prmQbk = prmQbk;
|
||||
AtStart = true;
|
||||
ItemsFound = 0;
|
||||
}
|
||||
public abstract SaQuickBooksDataItem GetNextItem ();
|
||||
/// <summary>Retrieve specific item (exception if more than one found).</summary>
|
||||
public SaQuickBooksDataItem GetItem (SaQuickBooksDataItem.Params prmQbk)
|
||||
{
|
||||
ClearErrorState();
|
||||
Iterator iterator = Clone();
|
||||
iterator.GotoStart(prmQbk);
|
||||
SaQuickBooksDataItem item1 = iterator.GetNextItem();
|
||||
SaQuickBooksDataItem item2 = iterator.GetNextItem();
|
||||
if (item2 != null)
|
||||
{
|
||||
// Only 1 item expected.
|
||||
if (item1 != null) item1.Dispose(); item1 = null;
|
||||
if (item2 != null) item2.Dispose(); item2 = null;
|
||||
SetErrorState("Multiple items found");
|
||||
}
|
||||
return item1;
|
||||
}
|
||||
/// <summary>List of matching items (use where volume is limited).</summary>
|
||||
public List<SaQuickBooksDataItem> GetItems (SaQuickBooksDataItem.Params prmQbk)
|
||||
{
|
||||
ClearErrorState();
|
||||
List<SaQuickBooksDataItem> items = new List<SaQuickBooksDataItem>();
|
||||
Iterator iterator = Clone();
|
||||
iterator.GotoStart(prmQbk);
|
||||
SaQuickBooksDataItem item = null;
|
||||
while ((item = iterator.GetNextItem()) != null)
|
||||
items.Add(item);
|
||||
return items;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// Utilities.
|
||||
protected abstract Iterator Clone ();
|
||||
//---------------------------------------------------------------
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,82 @@
|
||||
using Sarand.Net.Standard.Accounts.QuickBooks.App;
|
||||
using Sarand.Net.Standard.Accounts.QuickBooks.Base;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Sarand.Net.Standard.Accounts.QuickBooks.Internal
|
||||
{
|
||||
//=======================================================================
|
||||
public abstract class SaQuickBooksDataItem_Internal : SaQuickBooksDataItem
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
protected SaQuickBooksDataItem_Internal (Qbk.EntityType entityType) : base(entityType)
|
||||
{
|
||||
}
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// I t e r a t o r
|
||||
//-------------------------------------------------------------------
|
||||
public new abstract class Iterator : SaQuickBooksDataItem.Iterator
|
||||
{
|
||||
//---------------------------------------------------------------
|
||||
// Data members.
|
||||
//---------------------------------------------------------------
|
||||
// Construction.
|
||||
protected Iterator (Qbk.EntityType entityType) : base(entityType)
|
||||
{
|
||||
}
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// Properties.
|
||||
//---------------------------------------------------------------
|
||||
// Database.
|
||||
protected String GetPrimaryTableName ()
|
||||
{
|
||||
// ToDo return dfnDb.GetTableName(GetPrimaryTable());
|
||||
return "";
|
||||
}
|
||||
/*
|
||||
protected eQBooksDbTable GetPrimaryTable (Qbk.EntityType entityType)
|
||||
{
|
||||
switch (entityType)
|
||||
{
|
||||
// Contacts:
|
||||
case Qbk.EntityType.Vendor: return eQBooksDbTblVendor;
|
||||
case Qbk.EntityType.Customer: return eQBooksDbTblCustomer;
|
||||
case Qbk.EntityType.Item: return eQBooksDbTblItem;
|
||||
}
|
||||
return eQBooksDbTblUnknown;
|
||||
}
|
||||
*/
|
||||
//---------------------------------------------------------------
|
||||
// Utilities.
|
||||
//---------------------------------------------------------------
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using Sarand.Net.Standard.Accounts.QuickBooks.App;
|
||||
using Sarand.Net.Standard.Accounts.QuickBooks.Base;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Sarand.Net.Standard.Accounts.QuickBooks.Local
|
||||
{
|
||||
//=======================================================================
|
||||
internal class SaQuickBooksApiConsole_Local : SaQuickBooksApiConsole
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Static initialisation.
|
||||
static SaQuickBooksApiConsole_Local ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
internal SaQuickBooksApiConsole_Local (SaQuickBooksParams prmQbk) :base(prmQbk)
|
||||
{
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// D a t a I t e m s
|
||||
//-------------------------------------------------------------------
|
||||
public override SaQuickBooksDataItem CreateDataItem (Qbk.EntityType entityType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
/// <summary>Create data item iterator (to retrieve list of data items of specific type).</summary>
|
||||
public override SaQuickBooksDataItem.Iterator CreateItemIterator (Qbk.EntityType entityType)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
using Sarand.Net.Standard.Accounts.QuickBooks.App;
|
||||
using Sarand.Net.Standard.Accounts.QuickBooks.Base;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Sarand.Net.Standard.Accounts.QuickBooks.Online
|
||||
{
|
||||
//=======================================================================
|
||||
internal class SaQuickBooksApiConsole_Online : SaQuickBooksApiConsole
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// D e f i n i t i o n s
|
||||
//-------------------------------------------------------------------
|
||||
// Keys.
|
||||
// Sarand Sandbox company:
|
||||
// CompanyId 193514292338962
|
||||
// AppToken lvprdXEkhkqdCXgTfYJxhwFj1CdB3fXIeTs5eGx8TE8U7qGy
|
||||
// AppTokenSecret U8IgODOQa4Rl9KEMbQhgimoQi5nbgLi4XlQU4xiB
|
||||
// BPE Live Company
|
||||
// CompanyId 193514324299222
|
||||
// AppToken qyprdb7VvoOivRV7mARrb5I0VVT1caG0f1c0AVVgbhxt36bv
|
||||
// AppTokenSecret boGLa6B5RwayoYs1KlDEGk64Rjl0UUsF6By7rvBR
|
||||
private static String kpcAppToken_Dev = "0c7f73fdb65efb4033b8a12b61fb01aa3ce9";
|
||||
private static String kpcConsumerKey_Dev = "lvprd9HvNstK5yTszldscZ2PBgNGMu";
|
||||
private static String kpcConsumerSecret_Dev = "F6IQwnEhJqpoOdTmfXBgt1iq6SDWJ40clxl1xvQR";
|
||||
private static String kpcAppToken_Prod = "c0d15b4fbcad2b4cfcb96f9bcdbd2bf7b03d";
|
||||
private static String kpcConsumerKey_Prod = "lvprdwLCQdAhuiLtueFpZ7LVG4R6Ir";
|
||||
private static String kpcConsumerSecret_Prod = "9j1RBTaHbpTZEA0yUlDINYoAhX8Mt6PfOdAl2YIz";
|
||||
|
||||
// Online API.
|
||||
// Intuit Developer: https://developer.intuit.com/
|
||||
private static String kpcServer_QBD_Prod = "quickbooks.api.intuit.com"; // QuickBooks Desktop Rest Service - production.
|
||||
private static String kpcServer_QBO_Prod = "quickbooks.api.intuit.com"; // QuickBooks Online Rest Service - production.
|
||||
private static String kpcServer_QBO_Sand = "sandbox-quickbooks.api.intuit.com"; // QuickBooks Online Rest Service - sandbox.
|
||||
private static String kpcServer_IPP_Prod = "appcenter.intuit.com"; // Platform Rest Service - production.
|
||||
private static String kpcBaseUrl_QBD = "https://quickbooks.api.intuit.com/"; // QuickBooks Desktop Rest Service.
|
||||
private static String kpcBaseUrl_QBO = "https://quickbooks.api.intuit.com/"; // QuickBooks Online Rest Service.
|
||||
private static String kpcBaseUrl_IPP = "https://appcenter.intuit.com/api/"; // Platform Rest Service.
|
||||
private static String kpcUrlAccounting_Production = "https://quickbooks.api.intuit.com/"; // Accounting API base URL to use with production keys.
|
||||
private static String kpcUrlAccounting_Sandbox = "https://sandbox-quickbooks.api.intuit.com/"; // Accounting API—Sandbox base URL to use with development keys.
|
||||
private static String kpcUrlPayments_Production = "https://api.intuit.com/"; // Payments API base URL to use with production keys.
|
||||
private static String kpcUrlPayments_Sandbox = "https://sandbox.api.intuit.com/"; // Payments API—Sandbox base URL to use with development keys.
|
||||
|
||||
// Core constants.
|
||||
private static String kpcSlash = "/"; // Slash character.
|
||||
private static String kpcVersion = "v3"; // Intuit Services Version.
|
||||
private static String kpcResource = "resource";
|
||||
private static String kpcUrlVersionCompany = "v3/company/";
|
||||
// Content types.
|
||||
private static String kpcContentType_TextAny = "text/*";
|
||||
private static String kpcContentType_TextHtml = "text/html";
|
||||
private static String kpcContentType_TextXml = "text/xml";
|
||||
private static String kpcContentType_TextPlain = "text/plain";
|
||||
private static String kpcContentType_ApplicationText = "application/text";
|
||||
private static String kpcContentType_ApplicationXml = "application/xml";
|
||||
private static String kpcContentType_ApplicationJson = "application/json";
|
||||
private static String kpcContentType_UrlFormEncoded = "application/x-www-form-urlencoded";
|
||||
private static String kpcContentType_OctetStream = "application/octet-stream";
|
||||
private static String kpcContentType_ApplicationPdf = "application/pdf";
|
||||
// Parameter names.
|
||||
private static String kpcParam_Id = "Id";
|
||||
private static String kpcParam_SyncToken = "SyncToken";
|
||||
private static String kpcParam_Domain = "domain";
|
||||
private static String kpcParam_MetaData = "MetaData";
|
||||
private static String kpcParam_Sparse = "sparse";
|
||||
private static String kpcParam_Status = "status";
|
||||
private static String kpcParam_IdDomainQuery = "?idDomain=";
|
||||
private static String kpcAUTHORIZATIONSTRING_FORHEADER = "Authorization"; // Authorization String For Header.
|
||||
private static String kpcREQUESTFILENAME_FORMAT = "{0}{1}Request-{2}.txt"; // Request File Name Format.
|
||||
private static String kpcRESPONSEFILENAME_FORMAT = "{0}{1}Response-{2}.txt"; // Response File Name Format.
|
||||
private static String kpcERRORRESPONSEFILENAME_FORMAT = "{0}{1}Error-Response-{2}.txt"; // Error Response File Name Format.
|
||||
private static String kpcCONTENTENCODING = "Content-Encoding"; // The Compression format of the request data.
|
||||
private static String kpcACCEPTENCODING = "Accept-Encoding"; // The Compression format of the response data.
|
||||
private static String kpcUSERAGENT = "V3PHPSDK2.4.1"; // The Request source header value.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Static initialisation.
|
||||
static SaQuickBooksApiConsole_Online ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
internal SaQuickBooksApiConsole_Online (SaQuickBooksParams prmQbk) : base(prmQbk)
|
||||
{
|
||||
}
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// D a t a I t e m s
|
||||
//-------------------------------------------------------------------
|
||||
public override SaQuickBooksDataItem CreateDataItem (Qbk.EntityType entityType)
|
||||
{
|
||||
return new SaQuickBooksDataItem_Online(entityType);
|
||||
}
|
||||
/// <summary>Create data item iterator (to retrieve list of data items of specific type).</summary>
|
||||
public override SaQuickBooksDataItem.Iterator CreateItemIterator (Qbk.EntityType entityType)
|
||||
{
|
||||
return new SaQuickBooksDataItem_Online.Iterator(this, entityType);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Online Authorisation.
|
||||
public SaQuickBooksRequest_Online.AuthorisationData DoQBooksOnlineAuthorisation ()
|
||||
{
|
||||
SaQuickBooksRequest_Online.AuthorisationData authData = new SaQuickBooksRequest_Online.AuthorisationData();
|
||||
return authData;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// QBO interface.
|
||||
public bool DoQBooksRequest (SaQuickBooksRequest_Online qboRequest)
|
||||
{
|
||||
ClearErrorState();
|
||||
|
||||
return !HasErrorState();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,510 @@
|
||||
using Sarand.Net.Standard.Accounts.QuickBooks.App;
|
||||
using Sarand.Net.Standard.Accounts.QuickBooks.Base;
|
||||
using Sarand.Net.Standard.Accounts.QuickBooks.Dbas;
|
||||
using Sarand.Net.Standard.Accounts.QuickBooks.Internal;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Xml;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
|
||||
namespace Sarand.Net.Standard.Accounts.QuickBooks.Online
|
||||
{
|
||||
//=======================================================================
|
||||
public class SaQuickBooksDataItem_Online : SaQuickBooksDataItem_Internal
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Static initialisation.
|
||||
static SaQuickBooksDataItem_Online ()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
public SaQuickBooksDataItem_Online (Qbk.EntityType entityType) : base(entityType)
|
||||
{
|
||||
}
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// I t e r a t o r
|
||||
//-------------------------------------------------------------------
|
||||
public new class Iterator : SaQuickBooksDataItem_Internal.Iterator
|
||||
{
|
||||
//---------------------------------------------------------------
|
||||
// Data members.
|
||||
SaQuickBooksApiConsole_Online qbkConsole;
|
||||
internal class NextItemData
|
||||
{
|
||||
public int EntityCount { get; set; } = -1;
|
||||
public int PageLength { get; set; } = PageLengthDefault;
|
||||
public int PageNumber { get; set; } = 1;
|
||||
public XDocument QueryResponseDoc { get; set; }
|
||||
public XElement QueryResponseNode { get; set; }
|
||||
public XElement EntityNode { get; set; }
|
||||
}
|
||||
private readonly NextItemData nextItem = new NextItemData ();
|
||||
//---------------------------------------------------------------
|
||||
// Construction.
|
||||
internal Iterator (SaQuickBooksApiConsole_Online qbkConsole, Qbk.EntityType entityType) : base(entityType)
|
||||
{
|
||||
this.qbkConsole = qbkConsole;
|
||||
}
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
qbkConsole = null;
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// Properties.
|
||||
//---------------------------------------------------------------
|
||||
// Utilities.
|
||||
protected override SaQuickBooksDataItem.Iterator Clone ()
|
||||
{
|
||||
return new Iterator(qbkConsole, EntityType);
|
||||
}
|
||||
public String GetWhereClause ()
|
||||
{
|
||||
List<String> whereClauses = new List<string>();
|
||||
SaQuickBooksDataItem_Internal.Params prm = Params;
|
||||
if (EntityType == Qbk.EntityType.Vendor)
|
||||
{
|
||||
if (!StringUtil.IsEmpty(prm.EntityListId))
|
||||
whereClauses.Add("Id='" + prm.EntityListId + "'");
|
||||
}
|
||||
else if (EntityType == Qbk.EntityType.Customer)
|
||||
{
|
||||
if (!StringUtil.IsEmpty(prm.EntityListId))
|
||||
whereClauses.Add("Id='" + prm.EntityListId + "'");
|
||||
}
|
||||
else if (EntityType == Qbk.EntityType.Item)
|
||||
{
|
||||
if (!StringUtil.IsEmpty(prm.EntityListId))
|
||||
whereClauses.Add("Id='" + prm.EntityListId + "'");
|
||||
if (!StringUtil.IsEmpty(prm.EntityCode))
|
||||
whereClauses.Add("Sku='" + prm.EntityCode + "'");
|
||||
}
|
||||
return (!whereClauses.IsEmpty() ? " Where " : "") + whereClauses.Concat(" And ");
|
||||
}
|
||||
|
||||
String GetOrderByClause ()
|
||||
{
|
||||
String orderBy = "";
|
||||
return (!orderBy.IsEmpty() ? " OrderBy " : "") + orderBy;
|
||||
}
|
||||
|
||||
bool IsPaginationCompleted (bool incrementPageNumber)
|
||||
{
|
||||
if (incrementPageNumber)
|
||||
nextItem.PageNumber++;
|
||||
// Last page of data?
|
||||
GetItemCount(); // Force count.
|
||||
return (nextItem.PageNumber - 1) * nextItem.PageLength >= nextItem.EntityCount;
|
||||
}
|
||||
|
||||
String GetPaginationClause ()
|
||||
{
|
||||
String sPagination = "";
|
||||
if (nextItem.EntityCount > nextItem.PageLength)
|
||||
{
|
||||
sPagination = " StartPosition " + (((nextItem.PageNumber - 1) * nextItem.PageLength) + 1).ToString() + " MaxResults " + (nextItem.PageLength).ToString();
|
||||
}
|
||||
return sPagination;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// Data items.
|
||||
/// <summary>Total number of items (do this after GotoStart).</summary>
|
||||
public override int GetItemCount ()
|
||||
{
|
||||
ClearErrorState();
|
||||
if (nextItem.EntityCount < 0)
|
||||
{
|
||||
SaQuickBooksDataItem_Internal.Params prm = Params;
|
||||
SaQuickBooksRequest_Online qboRequest = new SaQuickBooksRequest_Online();
|
||||
bool validRequest = false;
|
||||
if (EntityType == Qbk.EntityType.Vendor)
|
||||
{
|
||||
qboRequest.RequestType = Qbk.OnlineRequestType.Query;
|
||||
qboRequest.DataQuery = "Select Count(*) From Vendor" + GetWhereClause();
|
||||
validRequest = true;
|
||||
}
|
||||
else if (EntityType == Qbk.EntityType.Customer)
|
||||
{
|
||||
qboRequest.RequestType = Qbk.OnlineRequestType.Query;
|
||||
qboRequest.DataQuery = "Select Count(*) From Customer" + GetWhereClause();
|
||||
validRequest = true;
|
||||
}
|
||||
else if (EntityType == Qbk.EntityType.Item)
|
||||
{
|
||||
qboRequest.RequestType = Qbk.OnlineRequestType.Query;
|
||||
qboRequest.DataQuery = "Select Count(*) From Item" + GetWhereClause();
|
||||
validRequest = true;
|
||||
}
|
||||
if (validRequest)
|
||||
{
|
||||
// <IntuitResponse xmlns="http://schema.intuit.com/finance/v3" time="2016-11-12T06:53:41.666-08:00">
|
||||
// <QueryResponse totalCount="29" />
|
||||
// </IntuitResponse>
|
||||
if (qbkConsole.DoQBooksRequest(qboRequest))
|
||||
{
|
||||
// Retrieve company info.
|
||||
XElement nodeRoot = qboRequest.ResponseDoc.Root;
|
||||
XElement nodeQueryResponse = nodeRoot.GetFirstChildElement("QueryResponse");
|
||||
nextItem.EntityCount = StringUtil.ToInt(nodeQueryResponse.GetAttributeValue("totalCount"));
|
||||
}
|
||||
}
|
||||
}
|
||||
return nextItem.EntityCount;
|
||||
}
|
||||
public override void GotoStart (SaQuickBooksDataItem_Internal.Params prmQbk)
|
||||
{
|
||||
base.GotoStart(prmQbk);
|
||||
// Reset next item.
|
||||
nextItem.EntityNode = null;
|
||||
nextItem.QueryResponseNode = null;
|
||||
nextItem.QueryResponseDoc = null;
|
||||
nextItem.EntityCount = -1;
|
||||
nextItem.PageLength = PageLengthDefault;
|
||||
nextItem.PageNumber = 1;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// N e x t I t e m
|
||||
//---------------------------------------------------------------
|
||||
// QuickBooks reference.
|
||||
// Case
|
||||
// In the query language, reserved words, entity names, and property names
|
||||
// are case insensitive. However, property values are case sensitive.
|
||||
// Maximum number of entities in a response
|
||||
// The maximum number of entities that can be returned in a response is 1000.
|
||||
// If the result size is not specified, the default number is 100.
|
||||
// If a query returns many entities, fetch the entities in chunks, as described in Pagination.
|
||||
// To determine the number of entities that a particular query returns,
|
||||
// probe by using the COUNT keyword in the query. See Count for details.
|
||||
// Escape Character
|
||||
// Use backslash (\) to escape special characters like apostrophe (').
|
||||
// For example, to find a Cuatomer object whose company name is "Adam's Candy Shop", submit the following query:
|
||||
// SELECT * FROM Customer WHERE CompanyName= ‘Adam\’s Candy Shop’
|
||||
// Filters
|
||||
// The filter in the WHERE clause determines which entities are returned by a query.
|
||||
// The filter criteria is based on the value of a property.
|
||||
// Multiple filters are AND'd together. The OR operation is not supported.
|
||||
// For example:
|
||||
// SELECT * FROM Customer WHERE Active IN (true, false)
|
||||
// SELECT * FROM Customer WHERE active = true
|
||||
// SELECT * FROM Customer WHERE GivenName LIKE 'K%h' AND FamilyName LIKE 'Palm%'
|
||||
// SELECT * FROM Invoice WHERE CustomerRef = '123'
|
||||
// SELECT * FROM Invoice WHERE CustomerId IN ('12')
|
||||
// SELECT * FROM Invoice WHERE TotalAmt > '1000.0'
|
||||
// SELECT * FROM Invoice WHERE TxnDate > '2011-01-01' AND TxnDate <= CURRENT_DATE
|
||||
// Sorting
|
||||
// To sort the results of a query, include the ORDERBY clause, specifying a property as the sort field.
|
||||
// Note that not all properties can be used for sorting.
|
||||
// To see which properties can be sorted on, go to the entity's reference page and check the Sort Support column of the Properties table.
|
||||
// The default sort order is ascending. To indicate descending sort order, include DESC.
|
||||
// For example:
|
||||
// SELECT * FROM Customer ORDERBY FamilyName
|
||||
// SELECT * FROM Customer ORDERBY FamilyName DESC
|
||||
// Pagination
|
||||
// To page through the results, specify STARTPOSITION (position of the entity in the query results) and MAXRESULTS (maximum number of entities in the result).
|
||||
// For example, suppose you have 25 invoices. The following queries each get 10 invoices per page:
|
||||
// SELECT * FROM Invoice STARTPOSITION 1 MAXRESULTS 10
|
||||
// SELECT * FROM Invoice STARTPOSITION 11 MAXRESULTS 10
|
||||
// SELECT * FROM Invoice STARTPOSITION 21 MAXRESULTS 10
|
||||
// Count
|
||||
// To find out how many entites will be returned by a query, specify the COUNT keyword.
|
||||
// The number of entities is returned in the totalCount attribute of the <QueryResponse> element.
|
||||
// The QuickBooks Online data objects, such as Customer, are not in the response.
|
||||
// SELECT COUNT(*)FROM Customer
|
||||
//---------------------------------------------------------------
|
||||
public override SaQuickBooksDataItem GetNextItem ()
|
||||
{
|
||||
SaQuickBooksDataItem_Internal.Params prm = Params;
|
||||
if (AtStart || (nextItem.EntityNode == null && !IsPaginationCompleted(true)))
|
||||
{
|
||||
// Construct request.
|
||||
SaQuickBooksRequest_Online qboRequest = new SaQuickBooksRequest_Online(Qbk.OnlineRequestType.Query);
|
||||
bool validRequest = false;
|
||||
if (EntityType == Qbk.EntityType.Vendor)
|
||||
{
|
||||
qboRequest.DataQuery = "Select * From Vendor" + GetWhereClause() + GetOrderByClause() + GetPaginationClause();
|
||||
validRequest = true;
|
||||
}
|
||||
else if (EntityType == Qbk.EntityType.Customer)
|
||||
{
|
||||
qboRequest.DataQuery = "Select * From Customer" + GetWhereClause() + GetOrderByClause() + GetPaginationClause();
|
||||
validRequest = true;
|
||||
}
|
||||
else if (EntityType == Qbk.EntityType.Item)
|
||||
{
|
||||
qboRequest.DataQuery = "Select * From Item" + GetWhereClause() + GetOrderByClause() + GetPaginationClause();
|
||||
validRequest = true;
|
||||
}
|
||||
if (validRequest)
|
||||
{
|
||||
// <IntuitResponse xmlns="http://schema.intuit.com/finance/v3" time="2016-11-12T06:53:41.666-08:00">
|
||||
// <QueryResponse totalCount="29" />
|
||||
// </IntuitResponse>
|
||||
if (qbkConsole.DoQBooksRequest(qboRequest))
|
||||
{
|
||||
nextItem.QueryResponseDoc = qboRequest.ResponseDoc;
|
||||
XElement nodeRoot = nextItem.QueryResponseDoc.Root;
|
||||
nextItem.QueryResponseNode = nodeRoot.GetFirstChildElement("QueryResponse");
|
||||
nextItem.EntityNode = nextItem.QueryResponseNode.GetFirstChildElement(GetPrimaryTableName());
|
||||
}
|
||||
}
|
||||
AtStart = false;
|
||||
}
|
||||
// Retrieve info for next company.
|
||||
SaQuickBooksDataItem_Online item = null;
|
||||
if (nextItem.EntityNode != null)
|
||||
{
|
||||
if (EntityType == Qbk.EntityType.Vendor)
|
||||
{
|
||||
item = GetVendorFrom(nextItem.EntityNode);
|
||||
}
|
||||
else if (EntityType == Qbk.EntityType.Customer)
|
||||
{
|
||||
item = GetCustomerFrom(nextItem.EntityNode);
|
||||
}
|
||||
else if (EntityType == Qbk.EntityType.Item)
|
||||
{
|
||||
item = GetItemFrom(nextItem.EntityNode);
|
||||
}
|
||||
// Move to next item.
|
||||
nextItem.EntityNode = nextItem.EntityNode.GetNextSiblingElement(GetPrimaryTableName());
|
||||
}
|
||||
if (item == null || nextItem.EntityNode == null)
|
||||
{
|
||||
// Clear next item info.
|
||||
nextItem.EntityNode = null;
|
||||
nextItem.QueryResponseNode = null;
|
||||
nextItem.QueryResponseDoc = null;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// E x t r a c t V e n d o r
|
||||
//---------------------------------------------------------------
|
||||
SaQuickBooksDataItem_Online GetVendorFrom (XElement nodeVendor)
|
||||
{
|
||||
if (nodeVendor == null || !nodeVendor.GetLocalName().EqualsCI("Vendor")) return null;
|
||||
SaQuickBooksDataItem_Online vendorItem = new SaQuickBooksDataItem_Online(Qbk.EntityType.Vendor);
|
||||
|
||||
// Vendor attributes.
|
||||
vendorItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_ListID), nodeVendor.GetChildText("Id"));
|
||||
|
||||
// Company name.
|
||||
String sFullName = nodeVendor.GetChildText("FullName");
|
||||
String sCompanyName = nodeVendor.GetChildText("CompanyName");
|
||||
String sDisplayName = nodeVendor.GetChildText("DisplayName");
|
||||
if (sCompanyName.IsEmpty())
|
||||
sCompanyName = sDisplayName;
|
||||
if (!sCompanyName.IsEmpty())
|
||||
{
|
||||
vendorItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_Name), sCompanyName);
|
||||
vendorItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_CompanyName), sCompanyName);
|
||||
//pVendor.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_FullName),sCompanyName);
|
||||
}
|
||||
if (!sDisplayName.IsEmpty())
|
||||
vendorItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_Name), sDisplayName);
|
||||
//if (!sFullName.IsEmpty())
|
||||
// pVendor.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_FullName),sFullName);
|
||||
|
||||
// Only populate attributes if present in data.
|
||||
// Active.
|
||||
XElement nodeActive = nodeVendor.GetFirstChildElement("Active");
|
||||
if (nodeActive != null)
|
||||
vendorItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_IsActive), nodeActive.Value.ToBool());
|
||||
// Balance
|
||||
XElement nodeBalance = nodeVendor.GetFirstChildElement("Balance");
|
||||
if (nodeBalance == null)
|
||||
vendorItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_Balance), nodeBalance.Value.ToDouble());
|
||||
// Credit limit.
|
||||
XElement nodeCreditLimit = nodeVendor.GetFirstChildElement("CreditLimit");
|
||||
if (nodeCreditLimit == null)
|
||||
vendorItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_CreditLimit), nodeCreditLimit.Value.ToDouble());
|
||||
// Phone numbers and email address.
|
||||
XElement nodePrimaryPhone = nodeVendor.GetFirstChildElement("PrimaryPhone");
|
||||
if (nodePrimaryPhone == null)
|
||||
vendorItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_Phone), nodePrimaryPhone.GetChildText("FreeFormNumber"));
|
||||
XElement nodeAlternatePhone = nodeVendor.GetFirstChildElement("AlternatePhone");
|
||||
if (nodeAlternatePhone == null)
|
||||
vendorItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_AltPhone), nodeAlternatePhone.GetChildText("FreeFormNumber"));
|
||||
XElement nodePrimaryEmailAddr = nodeVendor.GetFirstChildElement("PrimaryEmailAddr");
|
||||
if (nodePrimaryEmailAddr == null)
|
||||
vendorItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_Email), nodePrimaryEmailAddr.GetChildText("Address"));
|
||||
// Vendor address.
|
||||
XElement nodeVendorAddr = nodeVendor.GetFirstChildElement("VendorAddr");
|
||||
if (nodeVendorAddr == null)
|
||||
{
|
||||
vendorItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_VendorAddressAddr1), nodeVendorAddr.GetChildText("Line1"));
|
||||
vendorItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_VendorAddressAddr2), nodeVendorAddr.GetChildText("Line2"));
|
||||
vendorItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_VendorAddressAddr3), nodeVendorAddr.GetChildText("Line3"));
|
||||
vendorItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_VendorAddressAddr4), nodeVendorAddr.GetChildText("Line4"));
|
||||
vendorItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_VendorAddressAddr5), nodeVendorAddr.GetChildText("Line5"));
|
||||
vendorItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_VendorAddressCity), nodeVendorAddr.GetChildText("City"));
|
||||
vendorItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_VendorAddressCounty), nodeVendorAddr.GetChildText("CountrySubDivisionCode"));
|
||||
vendorItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_VendorAddressPostalCode), nodeVendorAddr.GetChildText("PostalCode"));
|
||||
vendorItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_VendorAddressCountry), nodeVendorAddr.GetChildText("Country"));
|
||||
vendorItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Vendor_VendorAddressNote), nodeVendorAddr.GetChildText("Note"));
|
||||
}
|
||||
return vendorItem;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// E x t r a c t C u s t o m e r
|
||||
//===========================================================================
|
||||
SaQuickBooksDataItem_Online GetCustomerFrom (XElement nodeCustomer)
|
||||
{
|
||||
if (nodeCustomer == null || !nodeCustomer.GetLocalName().EqualsCI("Customer")) return null;
|
||||
SaQuickBooksDataItem_Online customerItem = new SaQuickBooksDataItem_Online(Qbk.EntityType.Customer);
|
||||
|
||||
// Customer attributes.
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_ListID), nodeCustomer.GetChildText("Id"));
|
||||
|
||||
// Company name.
|
||||
String sFullName = nodeCustomer.GetChildText("FullName");
|
||||
String sCompanyName = nodeCustomer.GetChildText("CompanyName");
|
||||
String sDisplayName = nodeCustomer.GetChildText("DisplayName");
|
||||
if (sCompanyName.IsEmpty())
|
||||
sCompanyName = sDisplayName;
|
||||
if (!sCompanyName.IsEmpty())
|
||||
{
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_Name), sCompanyName);
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_CompanyName), sCompanyName);
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_FullName), sCompanyName);
|
||||
}
|
||||
if (!sDisplayName.IsEmpty())
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_Name), sDisplayName);
|
||||
if (!sFullName.IsEmpty())
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_FullName), sFullName);
|
||||
|
||||
// Only populate attributes if present in data.
|
||||
// Active.
|
||||
XElement nodeActive = nodeCustomer.GetFirstChildElement("Active");
|
||||
if (nodeActive == null)
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_IsActive), nodeActive.Value.ToBool());
|
||||
// Balance.
|
||||
XElement nodeBalance = nodeCustomer.GetFirstChildElement("Balance");
|
||||
if (nodeBalance == null)
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_Balance), nodeBalance.Value.ToDouble());
|
||||
// Credit limit.
|
||||
XElement nodeCreditLimit = nodeCustomer.GetFirstChildElement("CreditLimit");
|
||||
if (nodeCreditLimit == null)
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_CreditLimit), nodeCreditLimit.Value.ToDouble());
|
||||
// Phone numbers and email address.
|
||||
XElement nodePrimaryPhone = nodeCustomer.GetFirstChildElement("PrimaryPhone");
|
||||
if (nodePrimaryPhone == null)
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_Phone), nodePrimaryPhone.GetChildText("FreeFormNumber"));
|
||||
XElement nodeAlternatePhone = nodeCustomer.GetFirstChildElement("AlternatePhone");
|
||||
if (nodeAlternatePhone == null)
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_AltPhone), nodeAlternatePhone.GetChildText("FreeFormNumber"));
|
||||
XElement nodePrimaryEmailAddr = nodeCustomer.GetFirstChildElement("PrimaryEmailAddr");
|
||||
if (nodePrimaryEmailAddr == null)
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_Email), nodePrimaryEmailAddr.GetChildText("Address"));
|
||||
// Billing address.
|
||||
XElement nodeBillAddr = nodeCustomer.GetFirstChildElement("BillAddr");
|
||||
if (nodeBillAddr == null)
|
||||
{
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_BillAddressAddr1), nodeBillAddr.GetChildText("Line1"));
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_BillAddressAddr2), nodeBillAddr.GetChildText("Line2"));
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_BillAddressAddr3), nodeBillAddr.GetChildText("Line3"));
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_BillAddressAddr4), nodeBillAddr.GetChildText("Line4"));
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_BillAddressAddr5), nodeBillAddr.GetChildText("Line5"));
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_BillAddressCity), nodeBillAddr.GetChildText("City"));
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_BillAddressCounty), nodeBillAddr.GetChildText("CountrySubDivisionCode"));
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_BillAddressPostalCode), nodeBillAddr.GetChildText("PostalCode"));
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_BillAddressCountry), nodeBillAddr.GetChildText("Country"));
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_BillAddressNote), nodeBillAddr.GetChildText("Note"));
|
||||
}
|
||||
// Shipping address.
|
||||
XElement nodeShipAddr = nodeCustomer.GetFirstChildElement("ShipAddr");
|
||||
if (nodeShipAddr == null)
|
||||
{
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_ShipAddressAddr1), nodeShipAddr.GetChildText("Line1"));
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_ShipAddressAddr2), nodeShipAddr.GetChildText("Line2"));
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_ShipAddressAddr3), nodeShipAddr.GetChildText("Line3"));
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_ShipAddressAddr4), nodeShipAddr.GetChildText("Line4"));
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_ShipAddressAddr5), nodeShipAddr.GetChildText("Line5"));
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_ShipAddressCity), nodeShipAddr.GetChildText("City"));
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_ShipAddressCounty), nodeShipAddr.GetChildText("CountrySubDivisionCode"));
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_ShipAddressPostalCode), nodeShipAddr.GetChildText("PostalCode"));
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_ShipAddressCountry), nodeShipAddr.GetChildText("Country"));
|
||||
customerItem.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Customer_ShipAddressNote), nodeShipAddr.GetChildText("Note"));
|
||||
}
|
||||
|
||||
return customerItem;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// E x t r a c t I t e m
|
||||
//===========================================================================
|
||||
SaQuickBooksDataItem_Online GetItemFrom (XElement nodeItem)
|
||||
{
|
||||
if (nodeItem == null || !nodeItem.GetLocalName().EqualsCI("Item")) return null;
|
||||
SaQuickBooksDataItem_Online item = new SaQuickBooksDataItem_Online(Qbk.EntityType.Item);
|
||||
// Item attributes.
|
||||
item.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Item_ListID), nodeItem.GetChildText("Id"));
|
||||
// Active.
|
||||
XElement nodeActive = nodeItem.GetFirstChildElement("Active");
|
||||
if (nodeActive == null)
|
||||
item.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Item_IsActive), nodeActive.Value.ToBool());
|
||||
// Name.
|
||||
XElement nodeName = nodeItem.GetFirstChildElement("Name");
|
||||
if (nodeName == null)
|
||||
item.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Item_Name), nodeName.Value);
|
||||
// Description - use name as default.
|
||||
XElement nodeDescription = nodeItem.GetFirstChildElement("Description");
|
||||
if (nodeDescription == null)
|
||||
item.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Item_Description), nodeDescription.Value);
|
||||
else if (nodeName == null)
|
||||
item.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Item_Description), nodeName.Value);
|
||||
//#######################################################################
|
||||
// Sku - Use 'Name' field for now (until SKU available in schema).
|
||||
XElement nodeSku = nodeItem.GetFirstChildElement("Sku");
|
||||
if (nodeSku == null)
|
||||
item.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Item_Name), nodeSku.Value);
|
||||
// Unit price.
|
||||
XElement nodeUnitPrice = nodeItem.GetFirstChildElement("UnitPrice");
|
||||
if (nodeUnitPrice == null)
|
||||
item.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Item_SalesPrice), nodeUnitPrice.Value.ToDouble());
|
||||
// Purchase code.
|
||||
XElement nodePurchaseCost = nodeItem.GetFirstChildElement("PurchaseCost");
|
||||
if (nodePurchaseCost == null)
|
||||
item.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Item_PurchaseCost), nodePurchaseCost.Value.ToDouble());
|
||||
// Sales tax code ref.
|
||||
XElement nodeSalesTaxCodeRef = nodeItem.GetFirstChildElement("SalesTaxCodeRef");
|
||||
if (nodeSalesTaxCodeRef == null)
|
||||
{
|
||||
item.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Item_SalesTaxCodeRefListID), nodeSalesTaxCodeRef.Value.ToLong());
|
||||
item.SetValue(QBooksDbDfn.GetColumnName(QBooksDbDfn.ColumnIdx.Item_SalesTaxCodeRefFullName), nodeSalesTaxCodeRef.GetAttributeValue("name"));
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using Sarand.Net.Standard.Accounts.QuickBooks.App;
|
||||
using Sarand.Net.Standard.Accounts.QuickBooks.Base;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Sarand.Net.Standard.Accounts.QuickBooks.Online
|
||||
{
|
||||
//=======================================================================
|
||||
internal class SaQuickBooksRequest_Online : SaErrorStateItem
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
internal class AuthorisationData
|
||||
{
|
||||
public String CompanyId { get; set; } = "";
|
||||
public String AppToken { get; set; } = "";
|
||||
public String AppTokenSecret { get; set; } = "";
|
||||
public String DataSource { get; set; } = "";
|
||||
public bool Success { get; set; } = false;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Construction.
|
||||
internal SaQuickBooksRequest_Online (Qbk.OnlineRequestType requestType = Qbk.OnlineRequestType.Unknown)
|
||||
{
|
||||
RequestType = requestType;
|
||||
}
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public Qbk.OnlineRequestType RequestType { get; set; }
|
||||
// Request parameters.
|
||||
public bool Debug { get; set; } = false;
|
||||
/// <summary>For error messages.</summary>
|
||||
public String RequestTypeDesc { get; set; } = "request";
|
||||
public int MinorVersion { get; set; } = 4;
|
||||
public String EntityId { get; set; } = "";
|
||||
public String DataQuery { get; set; } = "";
|
||||
public String IntuitTid { get; set; } = "";
|
||||
public String FileData { get; set; } = "";
|
||||
// Response.
|
||||
public bool ValidResponse { get; set; } = false;
|
||||
public long HttpStatus { get; set; } = 0;
|
||||
public String FileResponse { get; set; } = "";
|
||||
public XDocument ResponseDoc { get; set; } = null;
|
||||
// Fault response.
|
||||
public String ResponseFaultType { get; set; } = "";
|
||||
public String ResponseErrorCode { get; set; } = "";
|
||||
public String ResponseErrorElement { get; set; } = "";
|
||||
public String ResponseErrorMessage { get; set; } = "";
|
||||
public String ResponseErrorDetail { get; set; } = "";
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Sarand.Net.Standard.Accounts.Sage.App
|
||||
{
|
||||
//=======================================================================
|
||||
public static class Sage
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Sage database version.
|
||||
public enum DbVersion
|
||||
{
|
||||
Unknown = 0,
|
||||
// Line 50.
|
||||
Line50V08 = 508,
|
||||
Line50V09 = 509,
|
||||
Line50V10 = 510,
|
||||
Line50V11 = 511,
|
||||
Line50V12 = 512,
|
||||
Line50V13 = 513,
|
||||
/// <summary>Sage Line 50 v14, 2008</summary>
|
||||
Line50V14 = 514,
|
||||
/// <summary>Sage Line 50 v15, 2009</summary>
|
||||
Line50V15 = 515,
|
||||
/// <summary>Sage Line 50 v16, 2010</summary>
|
||||
Line50V16 = 516,
|
||||
/// <summary>Sage Line 50 v17, 2011</summary>
|
||||
Line50V17 = 517,
|
||||
/// <summary>Sage Line 50 v18, 2012</summary>
|
||||
Line50V18 = 518,
|
||||
/// <summary>Sage Line 50 v19, 2013</summary>
|
||||
Line50V19 = 519,
|
||||
/// <summary>Sage Line 50 v20, 2014</summary>
|
||||
Line50V20 = 520,
|
||||
/// <summary>Sage Line 50 v21, 2015</summary>
|
||||
Line50V21 = 521,
|
||||
/// <summary>Sage Line 50 v22, 2016</summary>
|
||||
Line50V22 = 522,
|
||||
/// <summary>Sage Line 50 v23, 2017</summary>
|
||||
Line50V23 = 523,
|
||||
/// <summary>Sage Line 50 v24, 2018</summary>
|
||||
Line50V24 = 524,
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Sage reference types.
|
||||
public enum ReferenceDataType
|
||||
{
|
||||
Unknown = 0,
|
||||
Department = 1,
|
||||
Country,
|
||||
Currency,
|
||||
TaxCode,
|
||||
StockCategory,
|
||||
FixedAssetCategory,
|
||||
AccountStatus,
|
||||
DisputeReason,
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Sage item types.
|
||||
public enum ItemType
|
||||
{
|
||||
Unknown = 0,
|
||||
/// <summary>Sales Ledger</summary>
|
||||
Customer = 10,
|
||||
SalesDeliveryAddress,
|
||||
/// <summary>Purchase Ledger</summary>
|
||||
Supplier,
|
||||
/// <summary>Stock</summary>
|
||||
Product = 20,
|
||||
/// <summary>Current stock level</summary>
|
||||
StockLevel,
|
||||
/// <summary>Latest stock take on Stock record</summary>
|
||||
StockTake,
|
||||
StockBom,
|
||||
StockCategory,
|
||||
StockTransfer,
|
||||
PriceList,
|
||||
Price,
|
||||
/// <summary>Purchase Order</summary>
|
||||
PurchaseOrder = 30,
|
||||
/// <summary>POP Item</summary>
|
||||
PurchaseOrderItem,
|
||||
/// <summary>POP Item movement</summary>
|
||||
PopItemAllocation,
|
||||
/// <summary>Sales Order</summary>
|
||||
SalesOrder = 40,
|
||||
/// <summary>SOP Item</summary>
|
||||
SalesOrderItem,
|
||||
/// <summary>SOP Item movement</summary>
|
||||
SopItemAllocation,
|
||||
/// <summary>Invoice type 0</summary>
|
||||
Invoice_Product = 50,
|
||||
/// <summary>No sales order available - must be allocated directly</summary>
|
||||
Invoice_Product_Allocation,
|
||||
/// <summary>Invoice type 1</summary>
|
||||
Invoice_SalesOrder,
|
||||
/// <summary>Invoice type 2</summary>
|
||||
Invoice_Service,
|
||||
/// <summary>No sales order available - must be allocated directly</summary>
|
||||
Invoice_Service_Allocation,
|
||||
InvoiceItem,
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Sage invoice types.
|
||||
public enum InvoiceType
|
||||
{
|
||||
Unknown = -1,
|
||||
Product = 0, // Invoice
|
||||
ProductFromSalesOrder = 1, // Invoice
|
||||
Service = 2, // Invoice
|
||||
ProductCreditNote = 3, // Credit note
|
||||
ServiceCreditNote = 4, // Credit note
|
||||
ProductProForma = 5, // Pro-forma
|
||||
ProductQuote = 6, // Quote
|
||||
ServiceProForma = 7, // Pro-forma
|
||||
ServiceQuote = 8, // Quote
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Sage Reserved Stock codes.
|
||||
public enum StockCode
|
||||
{
|
||||
Unknown = 0,
|
||||
/// <summary>"M"</summary>
|
||||
Memo,
|
||||
/// <summary>"S1"</summary>
|
||||
PrdTax,
|
||||
/// <summary>"S2"</summary>
|
||||
PrdZero,
|
||||
/// <summary>"S3"</summary>
|
||||
SrvTax,
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Financial year.
|
||||
public enum FinancialYear
|
||||
{
|
||||
Unknown = 0,
|
||||
Current,
|
||||
Prior1,
|
||||
Prior2,
|
||||
Prior3,
|
||||
Prior4,
|
||||
Prior5
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Sarand.Net.Standard.Accounts.Sage.App
|
||||
{
|
||||
//=======================================================================
|
||||
public static class SageConsole
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private static readonly List<TypeCodeDesc> sageItemTypes = new List<TypeCodeDesc>();
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Static initialisation.
|
||||
static SageConsole ()
|
||||
{
|
||||
// Sage item types.
|
||||
// NB Don't change the codes - these are used on the database:
|
||||
sageItemTypes.Add(Sage.ItemType.Customer, "CUST", "Customers");
|
||||
sageItemTypes.Add(Sage.ItemType.Supplier, "SUPP", "Suppliers");
|
||||
sageItemTypes.Add(Sage.ItemType.Product, "PROD", "Products");
|
||||
sageItemTypes.Add(Sage.ItemType.PriceList, "PRCLST", "Pricing");
|
||||
sageItemTypes.Add(Sage.ItemType.StockLevel, "STKLVL", "Stock levels");
|
||||
sageItemTypes.Add(Sage.ItemType.StockTake, "STKTAK", "Stock takes");
|
||||
sageItemTypes.Add(Sage.ItemType.StockBom, "STKBOM", "Stock BOM");
|
||||
sageItemTypes.Add(Sage.ItemType.StockCategory, "STKCAT", "Stock categories");
|
||||
sageItemTypes.Add(Sage.ItemType.StockTransfer, "STKTRA", "Stock transfers");
|
||||
sageItemTypes.Add(Sage.ItemType.PurchaseOrder, "PURO", "Purchase orders");
|
||||
sageItemTypes.Add(Sage.ItemType.PopItemAllocation, "PURALL", "POP allocations");
|
||||
sageItemTypes.Add(Sage.ItemType.SalesOrder, "SALO", "Sales orders");
|
||||
sageItemTypes.Add(Sage.ItemType.SopItemAllocation, "SALALL", "SOP allocations");
|
||||
sageItemTypes.Add(Sage.ItemType.Invoice_Product, "INVPRD", "Product invoice");
|
||||
sageItemTypes.Add(Sage.ItemType.Invoice_Product_Allocation, "PRIALL", "Product invoice allocation");
|
||||
sageItemTypes.Add(Sage.ItemType.Invoice_SalesOrder, "INVSAL", "Sales order invoice");
|
||||
sageItemTypes.Add(Sage.ItemType.Invoice_Service, "INVSRV", "Service invoice");
|
||||
sageItemTypes.Add(Sage.ItemType.Invoice_Service_Allocation, "SRIALL", "Service invoice allocation");
|
||||
sageItemTypes.Add(Sage.ItemType.InvoiceItem, "INVITM", "Invoice item");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public static List<TypeCodeDesc> ItemTypeCodes { get { return new List<TypeCodeDesc>(sageItemTypes); } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,12 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<RootNamespace>Sarand.Net.Standard</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SacsStandardBase\SacsStandardBase.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,246 @@
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Tasks;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sarand.Net.Standard.Base.Net
|
||||
{
|
||||
//=======================================================================
|
||||
public class SacsHttpRequestData : SacsTaskData
|
||||
{
|
||||
public SacsHttpRequestData (CancellationToken? cancellationToken) : base(cancellationToken) { }
|
||||
/// <summary>URL to send request to.</summary>
|
||||
public String Url { get; set; }
|
||||
/// <summary>
|
||||
/// Request timeout. Default: 5 secs.
|
||||
/// <para>NB Not currently supported as can only be changed when static HTTP Client not in use.</para>
|
||||
/// </summary>
|
||||
public int TimeoutSecs { get; set; } = SacsHttpClient.RequestTimeoutSecs_Default;
|
||||
/// <summary>
|
||||
/// Headers to send with request.
|
||||
/// <para>Accept, Accept-Charset, Accept-Encoding, Accept-Language, User-Agent, Transfer-Encoding, Pragma, Expect etc.</para>
|
||||
/// </summary>
|
||||
public Dictionary<String, List<String>> RequestHeaders { get; } = new Dictionary<String, List<String>>();
|
||||
/// <summary>
|
||||
/// Content Headers to send with request.
|
||||
/// <para>Content-Length (bytes), Content-Type (media type), Content-Encoding (compression algorithm), Content-Language etc.</para>
|
||||
/// <para>Content-Type header is defaulted for POST request if not specified.</para>
|
||||
/// </summary>
|
||||
public Dictionary<String, List<String>> ContentHeaders { get; } = new Dictionary<String, List<String>>();
|
||||
/// <summary>
|
||||
/// Form values to post as 'URL Encoded'.
|
||||
/// <para>Content-Type defaults to 'application/x-www-form-urlencoded; charset=utf-8'.</para>
|
||||
/// </summary>
|
||||
public List<KeyValuePair<string, string>> FormData { get; } = new List<KeyValuePair<string, string>>();
|
||||
/// <summary>
|
||||
/// Data to POST. Ignored if FormData populated.
|
||||
/// <para>Content-Type defaults to 'text/plain; charset=utf-8'.</para>
|
||||
/// </summary>
|
||||
public String PostData { get; set; }
|
||||
/// <summary>Use POST request rather than GET even if no data to post.</summary>
|
||||
public bool ForcePost { get; set; }
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
public class SacsHttpResponseData
|
||||
{
|
||||
public DateTime RequestStarted { get; set; }
|
||||
public DateTime RequestCompleted { get; set; }
|
||||
/// <summary>Response headers.</summary>
|
||||
public Dictionary<String, IEnumerable<String>> ResponseHeaders { get; } = new Dictionary<String, IEnumerable<String>>();
|
||||
/// <summary>Response content headers.</summary>
|
||||
public Dictionary<String, IEnumerable<String>> ContentHeaders { get; } = new Dictionary<String, IEnumerable<String>>();
|
||||
/// <summary>Indicates whether Status Code represents success.</summary>
|
||||
public bool Success { get; set; }
|
||||
/// <summary>HTTP Status Code.</summary>
|
||||
public HttpStatusCode StatusCode { get; set; }
|
||||
/// <summary>HTTP Reason Code.</summary>
|
||||
public String ReasonPhrase { get; set; } = "";
|
||||
/// <summary>Response data.</summary>
|
||||
public String Data { get; set; } = "";
|
||||
/// <summary>Elapsed time for request.</summary>
|
||||
public TimeSpan Elapsed { get; set; }
|
||||
/// <summary>Exception thrown during handling of request.</summary>
|
||||
public Exception Exception { get; set; }
|
||||
/// <summary>Error state message - generally exception type and message.</summary>
|
||||
public String ErrorStateMessage { get; set; }
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
public static class SacsHttpClient
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
private static readonly HttpClient client;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Static initialisation.
|
||||
static SacsHttpClient ()
|
||||
{
|
||||
// Configure client.
|
||||
client = new HttpClient();
|
||||
client.Timeout = new TimeSpan(0, 0, RequestTimeoutSecs_Default);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
public static int RequestTimeoutSecs_Default { get; } = 5;
|
||||
public static String HeaderName_ContentType { get; } = "Content-Type";
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
public static async Task<SacsHttpResponseData> DoRequest (SacsHttpRequestData requestData)
|
||||
{
|
||||
String fn = "SacsHttpClient.DoRequest";
|
||||
SacsHttpResponseData responseData = new SacsHttpResponseData();
|
||||
requestData.ThrowIfCancellationRequested();
|
||||
|
||||
// Construct content to post.
|
||||
HttpContent postContent = null;
|
||||
if (requestData.FormData.Count > 0)
|
||||
{
|
||||
postContent = new FormUrlEncodedContent(requestData.FormData);
|
||||
if (!requestData.ContentHeaders.ContainsKey(HeaderName_ContentType))
|
||||
requestData.ContentHeaders.Add(HeaderName_ContentType,"application/x-www-form-urlencoded; charset=utf-8");
|
||||
}
|
||||
else if (!StringUtil.IsEmpty(requestData.PostData) || requestData.ForcePost)
|
||||
{
|
||||
postContent = new StringContent(StringUtil.EmptyOnNull(requestData.PostData), Encoding.UTF8);
|
||||
if (!requestData.ContentHeaders.ContainsKey(HeaderName_ContentType))
|
||||
requestData.ContentHeaders.Add(HeaderName_ContentType,"text/plain; charset=utf-8");
|
||||
}
|
||||
requestData.ThrowIfCancellationRequested();
|
||||
|
||||
// Make request.
|
||||
DateTime startedAt = DateTime.Now;
|
||||
try
|
||||
{
|
||||
// Request.
|
||||
using (HttpRequestMessage request = new HttpRequestMessage())
|
||||
{
|
||||
request.RequestUri = new Uri(requestData.Url);
|
||||
|
||||
// Request headers.
|
||||
foreach (String headerName in requestData.RequestHeaders.Keys)
|
||||
{
|
||||
if (request.Headers.Contains(headerName))
|
||||
request.Headers.Remove(headerName);
|
||||
request.Headers.Add(headerName, requestData.RequestHeaders[headerName]);
|
||||
}
|
||||
|
||||
// Default request headers.
|
||||
if (client.DefaultRequestHeaders.Accept.Count == 0 && request.Headers.Accept.Count == 0)
|
||||
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/*"));
|
||||
|
||||
// Configure request.
|
||||
HttpResponseMessage response = null;
|
||||
// Send request.
|
||||
if (postContent != null)
|
||||
{
|
||||
// POST.
|
||||
request.Method = HttpMethod.Post;
|
||||
request.Content = postContent;
|
||||
// Content headers.
|
||||
foreach (String headerName in requestData.ContentHeaders.Keys)
|
||||
{
|
||||
if (request.Content.Headers.Contains(headerName))
|
||||
request.Content.Headers.Remove(headerName);
|
||||
request.Content.Headers.Add(headerName, requestData.ContentHeaders[headerName]);
|
||||
}
|
||||
// Send request.
|
||||
responseData.RequestStarted = DateTime.Now;
|
||||
response = await client.SendAsync(request, requestData.CancellationToken);
|
||||
responseData.RequestCompleted = DateTime.Now;
|
||||
}
|
||||
else
|
||||
{
|
||||
// GET.
|
||||
request.Method = HttpMethod.Get;
|
||||
responseData.RequestStarted = DateTime.Now;
|
||||
response = await client.SendAsync(request, requestData.CancellationToken);
|
||||
responseData.RequestCompleted = DateTime.Now;
|
||||
}
|
||||
|
||||
// Extract resopnse data.
|
||||
responseData.Success = response.IsSuccessStatusCode;
|
||||
responseData.StatusCode = response.StatusCode;
|
||||
responseData.ReasonPhrase = response.ReasonPhrase;
|
||||
if (response.Headers != null)
|
||||
{
|
||||
foreach (var header in response.Headers)
|
||||
responseData.ResponseHeaders[header.Key] = new List<String>(header.Value);
|
||||
}
|
||||
if (response.Content != null && response.Content.Headers != null)
|
||||
{
|
||||
foreach (var header in response.Content.Headers)
|
||||
responseData.ContentHeaders[header.Key] = new List<String>(header.Value);
|
||||
}
|
||||
responseData.Data = await response.Content.ReadAsStringAsync();
|
||||
if (response != null) response.Dispose();
|
||||
}
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
// Ignore if task has been cancelled.
|
||||
if (requestData.IsCancellationRequested) throw exc;
|
||||
// Record exception.
|
||||
responseData.Exception = exc;
|
||||
if (exc.InnerException != null)
|
||||
{
|
||||
exc = exc.InnerException;
|
||||
}
|
||||
String msg = exc.GetType().Name + ": " + exc.Message;
|
||||
SaLogger.Warn(fn + " " + msg + ExceptionUtil.GetStackEntries(exc, 6).Concat("", "\n\t"));
|
||||
responseData.ErrorStateMessage = msg;
|
||||
}
|
||||
requestData.ThrowIfCancellationRequested();
|
||||
|
||||
// Complete response data.
|
||||
responseData.Elapsed = DateTime.Now - startedAt;
|
||||
return responseData;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// R e s p o n s e S t a t u s D e s c r i p t i o n
|
||||
//-------------------------------------------------------------------
|
||||
public static String GetResponseStatusDescription (HttpStatusCode httpStatus)
|
||||
{
|
||||
// Ref. https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
||||
switch (httpStatus)
|
||||
{
|
||||
// 1xx: Informational - Request received, continuing process.
|
||||
case HttpStatusCode.Continue: return "Continue";
|
||||
// 2xx: Success - The action was successfully received, understood, and accepted.
|
||||
case HttpStatusCode.OK: return "OK";
|
||||
case HttpStatusCode.Created: return "Created";
|
||||
case HttpStatusCode.Accepted: return "Accepted";
|
||||
// 3xx: Redirection - Further action must be taken in order to complete the request.
|
||||
case HttpStatusCode.MultipleChoices: return "Multiple choices";
|
||||
case HttpStatusCode.MovedPermanently: return "Moved permanently";
|
||||
case HttpStatusCode.Found: return "Found";
|
||||
// 4xx: Client Error -The request contains bad syntax or cannot be fulfilled.
|
||||
case HttpStatusCode.BadRequest: return "Bad request";
|
||||
case HttpStatusCode.Unauthorized: return "Unauthorized";
|
||||
case HttpStatusCode.PaymentRequired: return "Payment required";
|
||||
case HttpStatusCode.Forbidden: return "Forbidden";
|
||||
case HttpStatusCode.NotFound: return "Not found";
|
||||
case HttpStatusCode.MethodNotAllowed: return "Method not allowed";
|
||||
case HttpStatusCode.NotAcceptable: return "Not acceptable";
|
||||
// 5xx: Server Error -The server failed to fulfill an apparently valid request.
|
||||
case HttpStatusCode.InternalServerError: return "Internal server error";
|
||||
}
|
||||
return httpStatus.ToString();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using Sarand.Net.Standard.Base.Core;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace Sarand.Net.Standard.Base.Net
|
||||
{
|
||||
public static class WebUtil
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// H T M L E n c o d i n g
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>Converts a string to an HTML-encoded string.</summary>
|
||||
public static String HtmlEncode (this String value)
|
||||
{
|
||||
if (StringUtil.IsEmpty(value)) return value;
|
||||
return WebUtility.HtmlEncode(value);
|
||||
}
|
||||
/// <summary>Converts a string that has been HTML-encoded for HTTP transmission into a decoded string.</summary>
|
||||
public static String HtmlDecode (this String value)
|
||||
{
|
||||
if (StringUtil.IsEmpty(value)) return value;
|
||||
return WebUtility.HtmlDecode(value);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// U R L E n c o d i n g
|
||||
//-------------------------------------------------------------------
|
||||
/// <summary>Converts a string to an HTML-encoded string.</summary>
|
||||
public static String UrlEncode (this String value)
|
||||
{
|
||||
if (StringUtil.IsEmpty(value)) return value;
|
||||
return WebUtility.UrlEncode(value);
|
||||
}
|
||||
/// <summary>Converts a string that has been HTML-encoded for HTTP transmission into a decoded string.</summary>
|
||||
public static String UrlDecode (this String value)
|
||||
{
|
||||
if (StringUtil.IsEmpty(value)) return value;
|
||||
return WebUtility.UrlDecode(value);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user