public JObject getProductCategories(JObject request) { // Get request arguments request.TryGetValue("columns", out JToken requestColumns); request.TryGetValue("criteria", out JToken requestCriteria); request.TryGetValue("language", out JToken requestLanguages); request.TryGetValue("start", out JToken requestRangeStart); request.TryGetValue("amount", out JToken requestRangeAmount); MySqlConditionBuilder condition = null; // Verify the types of the arguments List <string> failedVerifications = new List <string>(); if (requestColumns != null && (requestColumns.Type != JTokenType.Array || requestColumns.Any(x => x.Type != JTokenType.String))) { failedVerifications.Add("colums"); } if (requestCriteria != null) { try { Misc.CreateCondition((JObject)requestCriteria, condition); } catch (Exception) { failedVerifications.Add("criteria"); } } if (requestLanguages != null && (requestLanguages.Type != JTokenType.Array || requestLanguages.Any(x => x.Type != JTokenType.String))) { failedVerifications.Add("language"); } if (requestRangeStart != null && (requestRangeStart.Type != JTokenType.Integer)) { failedVerifications.Add("start"); } if (requestRangeAmount != null && (requestRangeAmount.Type != JTokenType.Integer)) { failedVerifications.Add("amount"); } if (failedVerifications.Any()) { return(Templates.InvalidArguments(failedVerifications.ToArray())); } //Create base response var responseData = new JArray(); JObject response = new JObject() { { "reason", null }, { "responseData", responseData } }; // Prepare values for database call (ulong, ulong)range = (requestRangeStart?.ToObject <ulong>() ?? 0, requestRangeAmount?.ToObject <ulong>() ?? ulong.MaxValue); if (requestColumns == null || requestColumns.Count() == 0) { requestColumns = new JArray(ProductCategory.metadata.Select(x => x.Column)); } else if (requestLanguages != null && !requestColumns.Contains("name")) { ((JArray)requestColumns).Add("name"); } // Remove unknown language columns requestLanguages = new JArray(requestLanguages.Where(x => LanguageItem.metadata.Select(y => y.Column).Contains(x.ToString()))); // Request category data from database List <object[]> categoryData = Connection.Select <ProductCategory>(requestColumns.ToObject <string[]>(), condition, range).ToList(); // Add all categories as dictionaries to responseData foreach (var data in categoryData) { var item = new JObject(); for (int i = 0; i < requestColumns.Count(); i++) { item[(string)requestColumns[i]] = new JValue(data[i]); } responseData.Add(item); } // Add translations if specified in the arguments if (requestLanguages != null) { List <string> nameIds = responseData.Select(x => x["name"].ToString()).ToList(); // Build a condition to get all language items in one query bool first = true; var nameCondition = new MySqlConditionBuilder(); foreach (var name in nameIds) { if (!first) { nameCondition.Or(); } nameCondition.Column("id"); nameCondition.Equals(name, MySql.Data.MySqlClient.MySqlDbType.String); first = false; } // Get the specified translations var languageColumns = requestLanguages.ToObject <List <string> >(); if (languageColumns.Count == 0) { languageColumns.Add("*"); } else { languageColumns.Insert(0, "id"); } List <object[]> names = Connection.Select <LanguageItem>(languageColumns.ToArray(), nameCondition).ToList(); for (int i = 0; i < responseData.Count; i++) { var nameData = names.First(x => x[0].Equals(nameIds[i])); var translations = new JObject(); for (int j = 1; j < languageColumns.Count; j++) { if (nameData[j] != null) { translations[languageColumns[j]] = new JValue(nameData[j]); } } responseData[i]["name"] = translations; } } return(response); }
public JObject deleteProductItems(JObject request) { //Get arguments request.TryGetValue("productID", out JToken requestProductId); request.TryGetValue("count", out JToken requestCount); // Verify presence of arguments var failedVerifications = new List <string>(); if (requestProductId == null) { failedVerifications.Add("productID"); } if (requestCount == null) { failedVerifications.Add("count"); } if (failedVerifications.Any()) { return(Templates.MissingArguments(failedVerifications.ToArray())); } // Verify arguments if (requestProductId.Type != JTokenType.String) { failedVerifications.Add("productId"); } if (requestCount.Type != JTokenType.Integer || ((int)requestCount) < 0) { failedVerifications.Add("count"); } if (failedVerifications.Any()) { return(Templates.InvalidArguments(failedVerifications.ToArray())); } // Get all productItems var condition = new MySqlConditionBuilder("product", MySqlDbType.String, requestProductId.ToString()); var productItems = Connection.Select <ProductItem>(condition).ToArray(); // Return bare response if no items exist if (!productItems.Any()) { return(new JObject() { { "reason", null }, { "responseData", new JObject() { { "deleted", 0 }, { "ignored", 0 } } } }); } // Get all aquired loans that have yet to end condition = new MySqlConditionBuilder("product_item", MySqlDbType.Int32, productItems.Select(x => x.Id).Cast <object>().ToArray()); condition.And() .Column("end") .GreaterThanOrEqual() .Operand(DateTime.Now, MySqlDbType.DateTime); condition.And() .Column("is_item_acquired") .Equals().True(); var loans = Connection.Select <LoanItem>(condition).ToArray(); // Create function to track how many product items were ignored and how many weren't int ignored = 0; int notIgnored = 0; bool shouldIgnoreLoanedItem(ProductItem item) { bool b = loans.FirstOrDefault(x => x.ProductItem == item.Id) != null; if (notIgnored != (int)requestCount) { if (b) { ignored++; } else { notIgnored++; } } return(b); } // Filter out items that are loaned out var deletableItems = productItems.Where(x => !shouldIgnoreLoanedItem(x)).Take((int)requestCount).ToArray(); // Delete all items foreach (var item in deletableItems) { Connection.Delete(item); } //Create base response return(new JObject() { { "reason", null }, { "responseData", new JObject() { { "deleted", notIgnored }, { "ignored", ignored } } } }); }
public JObject getUnavailableDates(JObject request) { // Get arguments request.TryGetValue("productId", out JToken requestProductId); request.TryGetValue("start", out JToken requestStart); request.TryGetValue("end", out JToken requestEnd); // Verify arguments List <string> failedVerifications = new List <string>(); if (requestProductId == null || requestProductId.Type != JTokenType.String) { return(Templates.InvalidArgument("productId")); } if (requestStart == null) { return(Templates.InvalidArgument("start")); } if (requestEnd == null) { return(Templates.InvalidArgument("end")); } if (failedVerifications.Any()) { return(Templates.InvalidArguments(failedVerifications.ToArray())); } // Parse arguments DateTime start; DateTime end; try { start = requestStart == null ? new DateTime() : DateTime.Parse(requestStart.ToString()); } catch (Exception) { return(Templates.InvalidArgument("Unable to parse 'start'")); } try { end = requestEnd == null ? new DateTime() : DateTime.Parse(requestEnd.ToString()); } catch (Exception) { return(Templates.InvalidArgument("Unable to parse 'end'")); } var range = new DateTimeSpan(start, end); if (range.Duration.Days > 122) { return(Templates.InvalidArgument("start and end may not be more than 122 days apart.")); } // Get all items var condition = new MySqlConditionBuilder("product", MySqlDbType.String, requestProductId.ToString()); var productItems = Connection.Select <ProductItem>(condition).ToArray(); // Return empty response if no items were found if (!productItems.Any()) { return new JObject() { { "reason", null }, { "responseData", new JArray() } } } ; // Get all loans within the specified range condition = new MySqlConditionBuilder("product_item", MySqlDbType.Int32, productItems.Select(x => x.Id).Cast <object>().ToArray()); condition.And() .Column("end") .GreaterThanOrEqual() .Operand(range.Start, MySqlDbType.DateTime); condition.And() .Column("start") .LessThanOrEqual() .Operand(range.End, MySqlDbType.DateTime); var loanItems = Connection.Select <LoanItem>(condition).ToArray(); // No idea if this is the most efficient way, but it basically iterates // through all dates of a loan and slaps them in a cache. If the cache // already contains the date, it increases the counter. // If the counter is larger or equal to the total amount of items, we // consider that date unavailable. var dateCache = new Dictionary <DateTime, int>(); foreach (var loan in loanItems) { while (loan.Start < loan.End) { if (loan.Start < range.Start) { loan.Start = loan.Start.AddDays(1); continue; } if (loan.End > range.End) { break; } if (dateCache.ContainsKey(loan.Start)) { dateCache[loan.Start]++; } else { dateCache[loan.Start] = 1; } loan.Start = loan.Start.AddDays(1); } } // Build base response var responseData = new JArray(); JObject response = new JObject() { { "reason", null }, { "responseData", responseData } }; // Add all dates with an amount of loans greater or equal to the max available items foreach ((DateTime date, int count) in dateCache) { if (count >= productItems.Length) { responseData.Add((long)(date.ToUniversalTime() - Epoch).TotalMilliseconds); } } return(response); } }
public JObject deleteProduct(JObject request) { //Get arguments request.TryGetValue("productID", out JToken idValue); if (idValue == null || idValue.Type != JTokenType.String) { return(Templates.MissingArguments("productID")); } // Prepare values string productID = idValue.ToString(); //Check if product exists Product product = GetObject <Product>(productID); if (product == null) { return(Templates.NoSuchProduct(productID)); } // Check if items or acquired loans exist var condition = new MySqlConditionBuilder("product", MySqlDbType.String, productID); var items = Connection.Select <ProductItem>(condition).ToList(); // Check for associated loans if any items exist if (items.Any()) { // Get associated loans that are acquired and end after today condition = new MySqlConditionBuilder("product_item", MySqlDbType.Int32, items.Select(x => x.Id).Cast <object>().ToArray()); condition.And() .Column("end") .GreaterThanOrEqual() .Operand(DateTime.Now, MySqlDbType.DateTime); condition.And() .Column("is_item_acquired") .Equals().True(); List <bool> loans_isAcquired = Connection.Select <LoanItem>(new string[] { "is_item_acquired" }, condition).Select(x => (bool)x[0]).ToList(); // If any active loans are aquired, respond with CannotDelete if (loans_isAcquired.Any()) { return(Templates.CannotDelete("This product still has active loans.")); } } // Delete image if it isnt the default image product.Delete(Connection); if (product.Image != "default") { product.GetImage(Connection)?.Delete(Connection); } // Delete name languageItem if it isnt the default languageItem if (product.Name != "0") { product.GetName(Connection)?.Delete(Connection); } // Delete description languageItem if it isnt the default languageItem if (product.Description != "0") { product.GetDescription(Connection)?.Delete(Connection); } //Create base response return(new JObject() { { "reason", null }, }); }