Added support for setting signing order for Create Participant Action. Exposed Template Id, Workspace Id & Data Fields for contract models. Product quantity changed from int to decimal to support new functionality of fractured quantity. (#3687)
This commit is contained in:
Родитель
b99a5320e1
Коммит
efac621568
|
@ -195,6 +195,14 @@
|
|||
],
|
||||
"default": "Company"
|
||||
},
|
||||
{
|
||||
"name": "signing_order",
|
||||
"in": "header",
|
||||
"type": "number",
|
||||
"description": "Sign order of participant",
|
||||
"x-ms-visibility": "advanced",
|
||||
"x-ms-summary": "Signing order"
|
||||
},
|
||||
{
|
||||
"name": "party",
|
||||
"in": "body",
|
||||
|
@ -524,7 +532,48 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/contracts/{contract_id}/": {
|
||||
"/contracts/{contract_id}/": {
|
||||
"get": {
|
||||
"summary": "Get contract details",
|
||||
"description": "Retrieve the details of a contract by its ID.",
|
||||
"operationId": "GetContract",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "contract_id",
|
||||
"in": "path",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"x-ms-summary": "Contract Id",
|
||||
"description": "Contract Id"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Contract"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not Found",
|
||||
"schema": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"summary": "Delete a contract",
|
||||
"description": "Delete a specific contract by its ID.",
|
||||
|
@ -576,51 +625,10 @@
|
|||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"type": "object"
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"get": {
|
||||
"summary": "Get contract details",
|
||||
"description": "Retrieve the details of a contract by its ID.",
|
||||
"operationId": "GetContract",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "contract_id",
|
||||
"in": "path",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"x-ms-summary": "Contract Id",
|
||||
"description": "Contract Id"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Contract"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not Found",
|
||||
"schema": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/contracts/{contract_id}": {
|
||||
|
@ -1628,9 +1636,7 @@
|
|||
"workspace_id": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"description": "workspace_id",
|
||||
"x-ms-summary": "Workspace Id",
|
||||
"x-ms-visibility": "internal"
|
||||
"x-ms-summary": "Workspace Id"
|
||||
}
|
||||
},
|
||||
"description": "Contract _private attributes"
|
||||
|
@ -1645,9 +1651,7 @@
|
|||
"template_id": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"description": "template_id",
|
||||
"x-ms-summary": "Template Id",
|
||||
"x-ms-visibility": "internal"
|
||||
"x-ms-summary": "Template Id"
|
||||
},
|
||||
"template_type_id": {
|
||||
"type": "integer",
|
||||
|
@ -1761,61 +1765,62 @@
|
|||
"description": "Contract available_options attributes"
|
||||
},
|
||||
"data_fields": {
|
||||
"x-ms-visibility": "internal",
|
||||
"x-ms-summary": "Data Fields",
|
||||
"x-ms-summary": "Data field",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"_private_ownerside": {
|
||||
"x-ms-summary": "Private Ownerside (Data Fields)",
|
||||
"x-ms-summary": "private ownerside",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"created_time": {
|
||||
"type": "string",
|
||||
"description": "created_time",
|
||||
"x-ms-summary": "Created Time (Data Field)"
|
||||
"description": "Data field created_time",
|
||||
"x-ms-summary": "created time"
|
||||
},
|
||||
"custom_id": {
|
||||
"type": "string",
|
||||
"description": "custom_id",
|
||||
"x-ms-summary": "Custom Id (Data Field)"
|
||||
"description": "Data field custom_id",
|
||||
"x-ms-summary": "custom id"
|
||||
},
|
||||
"updated_time": {
|
||||
"type": "string",
|
||||
"description": "updated_time",
|
||||
"x-ms-summary": "Updated Time (Data Field)"
|
||||
"description": "Data field updated_time",
|
||||
"x-ms-summary": "Updated time"
|
||||
}
|
||||
},
|
||||
"description": "_private_ownerside"
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "description",
|
||||
"x-ms-summary": "Data Field Description"
|
||||
"description": "Data field description",
|
||||
"x-ms-summary": "description"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"description": "id",
|
||||
"x-ms-summary": "Data Field Id"
|
||||
"description": "Data field id",
|
||||
"x-ms-summary": "id"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "name",
|
||||
"x-ms-summary": "Data Field Name"
|
||||
"description": "Data field name",
|
||||
"x-ms-summary": "name"
|
||||
},
|
||||
"placeholder": {
|
||||
"type": "string",
|
||||
"description": "placeholder"
|
||||
"description": "Data field placeholder",
|
||||
"x-ms-summary": "placeholder"
|
||||
},
|
||||
"value": {
|
||||
"type": "string",
|
||||
"description": "value"
|
||||
"description": "Data field value",
|
||||
"x-ms-summary": "value"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "data_fields"
|
||||
"description": "Data fields collection"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer",
|
||||
|
@ -2416,8 +2421,7 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"amount": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"type": "number",
|
||||
"x-ms-summary": "amount"
|
||||
},
|
||||
"type": {
|
||||
|
@ -2524,8 +2528,7 @@
|
|||
"type": "object",
|
||||
"properties": {
|
||||
"amount": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"type": "number",
|
||||
"description": "Any positive number or 1/0 if the type is multiple_choice/single_choice",
|
||||
"x-ms-summary": "Amount"
|
||||
},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
public class Script : ScriptBase
|
||||
{
|
||||
#region fields & consctructors
|
||||
#region fields & constructors
|
||||
private readonly Dictionary<string, Func<IScriptContext, Task<HttpResponseMessage>>> _operationMappings;
|
||||
private readonly Dictionary<string, string> _schemaMappings;
|
||||
public Script()
|
||||
|
@ -180,7 +180,7 @@
|
|||
try
|
||||
{
|
||||
var req = ctx.Request;
|
||||
string contractId = GetHeaderStringValue(req.Headers, "contract_id");
|
||||
string contractId = GetHeaderStringValue(req.Headers, Constants.CreatePartyContractIdHeader);
|
||||
debugInfo.AppendLine($"contractId - {contractId}");
|
||||
|
||||
var inputPartyJson = await req.Content.ReadAsStringAsync();
|
||||
|
@ -188,71 +188,160 @@
|
|||
var inputParty = JsonConvert.DeserializeObject<Models.Party>(inputPartyJson);
|
||||
var selectedType = GetHeaderStringValue(req.Headers, Constants.ParticipantTypeHeader);
|
||||
debugInfo.AppendLine($"selectedType - {selectedType}");
|
||||
|
||||
int participantId = 0;
|
||||
HttpResponseMessage result = null;
|
||||
// for individual parties, just straight up create an individual participant.
|
||||
if (selectedType.Equals(Constants.PartyTypes.Individual, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
debugInfo.AppendLine("identified as individual. creating individual party.");
|
||||
return await CreateParty(req, contractId, inputParty, ctx);
|
||||
}
|
||||
|
||||
|
||||
// call getParties
|
||||
debugInfo.AppendLine("trying to get existing parties.");
|
||||
|
||||
var getPartiesRequest = new HttpRequestMessage(
|
||||
HttpMethod.Get,
|
||||
new Uri(string.Format(Constants.Requests.PartyEndpoint, req.RequestUri.Host, contractId)));
|
||||
|
||||
CopyHeaders(req, getPartiesRequest);
|
||||
|
||||
var getPartiesResponse = await ctx.SendAsync(getPartiesRequest, CancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (!getPartiesResponse.IsSuccessStatusCode)
|
||||
{
|
||||
return getPartiesResponse;
|
||||
}
|
||||
debugInfo.AppendLine("converting get party response.");
|
||||
var getPartiesResponseJson = await getPartiesResponse.Content.ReadAsStringAsync();
|
||||
|
||||
var existingParties = JsonConvert.DeserializeObject<Responses.GetPartiesResponse>(getPartiesResponseJson).data;
|
||||
int matchingPartyId = 0;
|
||||
|
||||
// if we need to create an ownserside participant, just find my_party and create a participant for it.
|
||||
if (selectedType.Equals(Constants.PartyTypes.Ownerside, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
matchingPartyId = existingParties.FirstOrDefault(x =>
|
||||
x.my_party.Value).id ??
|
||||
throw new ScriptException(HttpStatusCode.InternalServerError,
|
||||
$"Couldn't find ownerside party for contract {contractId}");
|
||||
|
||||
return await CreateParticipant(req, matchingPartyId, contractId, inputParty.participant, ctx);
|
||||
}
|
||||
|
||||
// process Company participants.
|
||||
debugInfo.AppendLine($"Input party - {Environment.NewLine + inputParty}");
|
||||
foreach (Models.Party existingParty in existingParties)
|
||||
{
|
||||
debugInfo.AppendLine($"Trying to match with party - {Environment.NewLine + existingParty}");
|
||||
if (existingParty.Equals(inputParty))
|
||||
result = await CreateParty(req, contractId, inputParty, ctx);
|
||||
if (!result.IsSuccessStatusCode)
|
||||
{
|
||||
debugInfo.AppendLine("match");
|
||||
matchingPartyId = existingParty.id.Value;
|
||||
break;
|
||||
return result;
|
||||
}
|
||||
debugInfo.AppendLine("not match");
|
||||
string responseStr = await result.Content.ReadAsStringAsync();
|
||||
JObject partyResponse = JObject.Parse(responseStr);
|
||||
participantId = partyResponse["participant"]["id"].ToObject<int>();
|
||||
}
|
||||
|
||||
debugInfo.Append($"matching party id: {Environment.NewLine + matchingPartyId}");
|
||||
if (matchingPartyId != default)
|
||||
else
|
||||
{
|
||||
debugInfo.AppendLine("Party found. creating participant.");
|
||||
return await CreateParticipant(req, matchingPartyId, contractId, inputParty.participant, ctx);
|
||||
// call getParties
|
||||
debugInfo.AppendLine("trying to get existing parties.");
|
||||
|
||||
var getPartiesRequest = new HttpRequestMessage(
|
||||
HttpMethod.Get,
|
||||
new Uri(string.Format(Constants.Requests.PartyEndpoint, req.RequestUri.Host, contractId)));
|
||||
|
||||
CopyHeaders(req, getPartiesRequest);
|
||||
|
||||
var getPartiesResponse = await ctx.SendAsync(getPartiesRequest, CancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (!getPartiesResponse.IsSuccessStatusCode)
|
||||
{
|
||||
return getPartiesResponse;
|
||||
}
|
||||
|
||||
debugInfo.AppendLine("converting get party response.");
|
||||
var getPartiesResponseJson = await getPartiesResponse.Content.ReadAsStringAsync();
|
||||
|
||||
var existingParties = JsonConvert.DeserializeObject<Responses.GetPartiesResponse>(getPartiesResponseJson).data;
|
||||
int matchingPartyId = 0;
|
||||
|
||||
// if we need to create an ownserside participant, just find my_party and create a participant for it.
|
||||
if (selectedType.Equals(Constants.PartyTypes.Ownerside, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
matchingPartyId = existingParties.FirstOrDefault(x =>
|
||||
x.my_party.Value).id ??
|
||||
throw new ScriptException(HttpStatusCode.InternalServerError,
|
||||
$"Couldn't find ownerside party for contract {contractId}");
|
||||
|
||||
result = await CreateParticipant(req, matchingPartyId, contractId, inputParty.participant, ctx);
|
||||
if (!result.IsSuccessStatusCode)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
string responseStr = await result.Content.ReadAsStringAsync();
|
||||
JObject partyResponse = JObject.Parse(responseStr);
|
||||
participantId = partyResponse["id"].ToObject<int>();
|
||||
}
|
||||
else
|
||||
{
|
||||
// process Company participants.
|
||||
debugInfo.AppendLine($"Input party - {Environment.NewLine + inputParty}");
|
||||
foreach (Models.Party existingParty in existingParties)
|
||||
{
|
||||
debugInfo.AppendLine($"Trying to match with party - {Environment.NewLine + existingParty}");
|
||||
if (existingParty.Equals(inputParty))
|
||||
{
|
||||
debugInfo.AppendLine("match");
|
||||
matchingPartyId = existingParty.id.Value;
|
||||
break;
|
||||
}
|
||||
debugInfo.AppendLine("not match");
|
||||
}
|
||||
|
||||
debugInfo.Append($"matching party id: {Environment.NewLine + matchingPartyId}");
|
||||
if (matchingPartyId != default)
|
||||
{
|
||||
debugInfo.AppendLine("Party found. creating participant.");
|
||||
result = await CreateParticipant(req, matchingPartyId, contractId, inputParty.participant, ctx);
|
||||
if (!result.IsSuccessStatusCode)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
string responseStr = await result.Content.ReadAsStringAsync();
|
||||
JObject partyResponse = JObject.Parse(responseStr);
|
||||
participantId = partyResponse["id"].ToObject<int>();
|
||||
}
|
||||
else
|
||||
{
|
||||
debugInfo.AppendLine("Party not found. creating new party.");
|
||||
result = await CreateParty(req, contractId, inputParty, ctx);
|
||||
if (!result.IsSuccessStatusCode)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
string responseStr = await result.Content.ReadAsStringAsync();
|
||||
JObject partyResponse = JObject.Parse(responseStr);
|
||||
participantId = partyResponse["participants"].ElementAt(0)["id"].ToObject<int>();
|
||||
}
|
||||
}
|
||||
}
|
||||
string signOrder = GetHeaderStringValue(req.Headers, Constants.SigningOrderHeader);
|
||||
if (!string.IsNullOrEmpty(signOrder) && Int32.TryParse(signOrder, out int orderInt) && participantId != default)
|
||||
{
|
||||
debugInfo.AppendLine($"setting sign order.");
|
||||
var getContractRequest = new HttpRequestMessage(
|
||||
HttpMethod.Get,
|
||||
new Uri(string.Format(Constants.Requests.ContractsEndpoint, req.RequestUri.Host, contractId)));
|
||||
|
||||
CopyHeaders(req, getContractRequest);
|
||||
|
||||
var getContractResponse = await ctx.SendAsync(getContractRequest, CancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
if (!getContractResponse.IsSuccessStatusCode) return getContractResponse;
|
||||
debugInfo.AppendLine($"retrieved contract");
|
||||
string responseStr = await getContractResponse.Content.ReadAsStringAsync();
|
||||
var contract = JsonConvert.DeserializeObject<Models.Contract>(responseStr);
|
||||
var participants = new List<Models.Participant>();
|
||||
|
||||
foreach (Models.Party party in contract.parties)
|
||||
{
|
||||
if (party.participants != null && party.participants.Any())
|
||||
{
|
||||
participants.AddRange(party.participants);
|
||||
}
|
||||
else if (party.participant != null)
|
||||
{
|
||||
participants.Add(party.participant);
|
||||
}
|
||||
}
|
||||
debugInfo.AppendLine($"extracted participants.");
|
||||
if (contract.sign_order != null && contract.sign_order.Any())
|
||||
{
|
||||
foreach (var participant in participants)
|
||||
{
|
||||
var signorderItem = contract.sign_order.FirstOrDefault(x => x.participant_id == participant.id.Value);
|
||||
if (signorderItem != null) participant.private_ownerside.signOrder = signorderItem.order;
|
||||
}
|
||||
debugInfo.AppendLine($"synced sign orders with participants.");
|
||||
}
|
||||
|
||||
debugInfo.AppendLine($"$Participants: {String.Join($"{Environment.NewLine},", participants.Select(x => JsonConvert.SerializeObject(x)))}");
|
||||
|
||||
participants = participants.OrderBy(x => x.private_ownerside.created_time).ToList();
|
||||
debugInfo.AppendLine($"sorted participants.");
|
||||
|
||||
|
||||
var signOrderResponse = await SetParticipantSignOrder(req, debugInfo, participants, contractId, participantId, orderInt, ctx);
|
||||
if (!signOrderResponse.IsSuccessStatusCode)
|
||||
{
|
||||
return signOrderResponse;
|
||||
}
|
||||
}
|
||||
|
||||
debugInfo.AppendLine("Party not found. creating new party.");
|
||||
return await CreateParty(req, contractId, inputParty, ctx);
|
||||
return result;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -260,6 +349,37 @@
|
|||
}
|
||||
}
|
||||
|
||||
private async Task<HttpResponseMessage> SetParticipantSignOrder(HttpRequestMessage initialRequest, StringBuilder debugInfo, List<Models.Participant> existingParticipants, string contractId, int participantId, int order, IScriptContext ctx)
|
||||
{
|
||||
string requestUrl = string.Format(Constants.Requests.ContractsEndpoint, initialRequest.RequestUri.Host, contractId);
|
||||
HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Put, new Uri(requestUrl));
|
||||
CopyHeaders(initialRequest, req);
|
||||
|
||||
var signOrder = new List<Models.SignOrderItem>();
|
||||
int counter = 1;
|
||||
foreach (var participant in existingParticipants)
|
||||
{
|
||||
var signOrderItem = new Models.SignOrderItem() { participant_id = participant.id.Value };
|
||||
debugInfo.AppendLine($"1");
|
||||
if (participant.private_ownerside.signOrder != default)
|
||||
{
|
||||
signOrderItem.order = participant.private_ownerside.signOrder; debugInfo.AppendLine($"2");
|
||||
}
|
||||
else if (participant.id == participantId) { signOrderItem.order = order; debugInfo.AppendLine($"3"); }
|
||||
else { signOrderItem.order = counter++; debugInfo.AppendLine($"4"); }
|
||||
signOrder.Add(signOrderItem);
|
||||
}
|
||||
debugInfo.AppendLine($"assigned sign order to every participant.");
|
||||
var bodyObj = new Models.Contract()
|
||||
{
|
||||
sign_order = signOrder
|
||||
};
|
||||
|
||||
var jsonBody = JsonConvert.SerializeObject(bodyObj);
|
||||
req.Content = new StringContent(jsonBody, Encoding.UTF8, "application/json");
|
||||
return await ctx.SendAsync(req, CancellationToken);
|
||||
}
|
||||
|
||||
private async Task<HttpResponseMessage> HandleGetTemplateTypeByTemplateId(IScriptContext ctx)
|
||||
{
|
||||
var req = ctx.Request;
|
||||
|
@ -430,6 +550,7 @@
|
|||
public const string ContractProductGroupsEndpoint = "https://{0}/v1/contracts/{1}/product_groups";
|
||||
public const string AddProductEndpoint = "https://{0}/v1/contracts/{1}/product_groups/{2}/products";
|
||||
public const string TemplatesEndpoint = "https://{0}/v1/templates/{1}";
|
||||
public const string ContractsEndpoint = "https://{0}/v1/contracts/{1}";
|
||||
}
|
||||
public static class PartyTypes
|
||||
{
|
||||
|
@ -440,7 +561,9 @@
|
|||
public const string GetTemplatesFilterHeader = "x-oneflow-workspace-id";
|
||||
public const string TemplateIdHeader = "x-oneflow-template-id";
|
||||
public const string SchemaIdHeader = "schema_id";
|
||||
public const string CreatePartyContractIdHeader = "contract_id";
|
||||
public const string ParticipantTypeHeader = "participant_type";
|
||||
public const string SigningOrderHeader = "signing_order";
|
||||
public const string UserEmailOverrideHeader = "x-oneflow-user-email-override";
|
||||
public const string UserEmailHeader = "x-oneflow-user-email";
|
||||
public const string ProductGroupIndexHeader = "x-ms-oneflow-product-group-index";
|
||||
|
@ -716,6 +839,7 @@
|
|||
}";
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class Models
|
||||
{
|
||||
public class Party
|
||||
|
@ -804,6 +928,7 @@
|
|||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public void AlignParticipants()
|
||||
{
|
||||
if (Constants.PartyTypes.Individual.Equals(type, StringComparison.OrdinalIgnoreCase)) return;
|
||||
|
@ -815,8 +940,20 @@
|
|||
}
|
||||
}
|
||||
|
||||
public class ParticipantPrivateOwnerside
|
||||
{
|
||||
//[JsonConverter(typeof(DateFormatConverter), "o")] // 2023-04-27T11:29:36+00:00
|
||||
public DateTime created_time { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public int signOrder { get; set; }
|
||||
}
|
||||
|
||||
public class Participant
|
||||
{
|
||||
[JsonProperty("_private_ownerside", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public ParticipantPrivateOwnerside private_ownerside { get; set; }
|
||||
|
||||
//workaround for Power Automate bug with a nested object in array element.
|
||||
[JsonProperty("_permissions/contract:update", NullValueHandling = NullValueHandling.Ignore)]
|
||||
bool? updatePermission { get; set; }
|
||||
|
@ -945,6 +1082,22 @@
|
|||
public TemplateType template_type { get; set; }
|
||||
}
|
||||
|
||||
public class Contract
|
||||
{
|
||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||
public IEnumerable<Party> parties { get; set; }
|
||||
|
||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||
public IEnumerable<SignOrderItem> sign_order { get; set; }
|
||||
}
|
||||
|
||||
public class SignOrderItem
|
||||
{
|
||||
public int participant_id { get; set; }
|
||||
|
||||
public int order { get; set; }
|
||||
}
|
||||
|
||||
public class TemplateType
|
||||
{
|
||||
public string extension_type { get; set; }
|
||||
|
@ -998,5 +1151,13 @@
|
|||
}
|
||||
}
|
||||
|
||||
public class DateFormatConverter : Newtonsoft.Json.Converters.IsoDateTimeConverter
|
||||
{
|
||||
public DateFormatConverter(string format)
|
||||
{
|
||||
DateTimeFormat = format;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче