using System; using Yavsc; using System.Web.Mvc; using System.Web; using System.Text.RegularExpressions; using System.IO; using Yavsc.Controllers; using System.Collections.Generic; using Yavsc.Model; using Yavsc.Model.WorkFlow; using System.Web.Security; using System.Threading; using Yavsc.Model.FrontOffice; using Yavsc.Model.FileSystem; using Yavsc.Model.Calendar; using System.Configuration; using Yavsc.Helpers; using Yavsc.Model.FrontOffice.Catalog; using Yavsc.Model.Skill; using System.Web.Profile; using Yavsc.Model.Google.Api; using System.Net; using System.Linq; using System.ComponentModel.DataAnnotations; using Yavsc.Model.Circles; namespace Yavsc.Controllers { /// /// Front office controller. /// Access granted to all /// public class FrontOfficeController : Controller { /// /// Index this instance. /// public ActionResult Index () { return View (); } /// /// Pub the Event /// /// The pub. /// Model. public ActionResult EventPub (EventPub model) { return View (model); } /// /// Estimates released to this client /// [Authorize] public ActionResult YourEstimates (string client) { var u = Membership.GetUser (); if (u == null) // There was no redirection to any login page throw new ConfigurationErrorsException ("no redirection to any login page"); string username = u.UserName; Estimate[] estims = WorkFlowManager.GetUserEstimates (username); ViewData ["UserName"] = username; ViewData ["ResponsibleCount"] = Array.FindAll ( estims, x => x.Responsible == username).Length; ViewData ["ClientCount"] = Array.FindAll ( estims, x => x.Client == username).Length; return View (estims); } /// /// Estimate wearing the specified id. /// /// Estim Identifier. public ActionResult Get (long id) { Estimate f = WorkFlowManager.GetEstimate (id); if (f == null) { ModelState.AddModelError ("Id", "Wrong Id"); return View (new Estimate () { Id = id }); } return View (f); } /// /// Estimate the specified model and submit. /// /// Model. /// Submit. [Authorize] public ActionResult DoAnEstimate (Estimate model, string submit) { string username = Membership.GetUser ().UserName; // Obsolete, set in master page ViewData ["WebApiBase"] = Url.Content (Yavsc.WebApiConfig.UrlPrefixRelative); ViewData ["WABASEWF"] = ViewData ["WebApiBase"] + "/WorkFlow"; if (submit == null) { if (model.Id > 0) { Estimate f = WorkFlowManager.GetEstimate (model.Id); if (f == null) { ModelState.AddModelError ("Id", "Wrong Id"); return View (model); } model = f; ModelState.Clear (); if (username != model.Responsible && username != model.Client && !Roles.IsUserInRole ("FrontOffice")) throw new UnauthorizedAccessException ("You're not allowed to view this estimate"); } else if (model.Id == 0) { if (string.IsNullOrWhiteSpace (model.Responsible)) model.Responsible = username; } } else { if (model.Id == 0) // if (submit == "Create") if (string.IsNullOrWhiteSpace (model.Responsible)) model.Responsible = username; if (username != model.Responsible && !Roles.IsUserInRole ("FrontOffice")) throw new UnauthorizedAccessException ("You're not allowed to modify this estimate"); if (ModelState.IsValid) { if (model.Id == 0) model = WorkFlowManager.CreateEstimate ( username, model.Client, model.Title, model.Description); else { WorkFlowManager.UpdateEstimate (model); model = WorkFlowManager.GetEstimate (model.Id); } } } return View (model); } /// /// Catalog this instance. /// [AcceptVerbs ("GET")] public ActionResult Catalog () { return View ( CatalogManager.GetCatalog () ); } /// /// Catalog this instance. /// [AcceptVerbs ("GET")] public ActionResult Brand (string brandid) { Catalog c = CatalogManager.GetCatalog (); ViewData ["BrandName"] = brandid; return View (c.GetBrand (brandid)); } /// /// get the product category /// /// The category object. /// Brand id. /// Product category Id. [AcceptVerbs ("GET")] public ActionResult ProductCategory (string brandid, string pcid) { ViewData ["BrandId"] = brandid; ViewData ["ProductCategoryId"] = pcid; var cat = CatalogManager.GetCatalog (); if (cat == null) throw new Exception ("No catalog"); var brand = cat.GetBrand (brandid); if (brand == null) throw new Exception ("Not a brand id: " + brandid); var pcat = brand.GetProductCategory (pcid); if (pcat == null) throw new Exception ("Not a product category id in this brand: " + pcid); return View (pcat); } /// /// Product the specified id, pc and pref. /// /// Brand Identifier. /// Production catalog reference. /// Preference. [AcceptVerbs ("GET")] public ActionResult Product (string id, string pc, string pref) { Product p = null; ViewData ["BrandName"] = id; ViewData ["ProdCatRef"] = pc; ViewData ["ProdRef"] = pref; Catalog cat = CatalogManager.GetCatalog (); if (cat == null) { YavscHelpers.Notify (ViewData, "Catalog introuvable"); ViewData ["RefType"] = "Catalog"; return View ("ReferenceNotFound"); } Brand b = cat.GetBrand (id); if (b == null) { ViewData ["RefType"] = "Brand"; return View ("ReferenceNotFound"); } ProductCategory pcat = b.GetProductCategory (pc); if (pcat == null) { ViewData ["RefType"] = "ProductCategory"; return View ("ReferenceNotFound"); } ViewData ["ProdCatName"] = pcat.Name; p = pcat.GetProduct (pref); if (p.CommandForm == null) p.CommandForm = b.DefaultForm; return View ((p is Service) ? "Service" : "Product", p); } /// /// Basket this instance. /// [Authorize] public ActionResult Basket () { return View (WorkFlowManager.GetCommands (Membership.GetUser ().UserName)); } /// /// Command the specified collection. /// /// Collection. [HttpPost] [Authorize] public ActionResult DoCommand (FormCollection collection) { try { // Add specified product command to the basket, // saves it in db // // * check the validity of this request // by finding the "type" parameter between // the allowed command types // * instanciate the given command type, passing it the form data // * Make the workflow register this command // * Render the resulting basket var cmd = Command.CreateCommand (collection, HttpContext.Request.Files); ViewData["Commanded"] = cmd; YavscHelpers.Notify (ViewData, LocalizedText.Item_added_to_basket); return View ("Basket",WorkFlowManager.GetCommands (User.Identity.Name)); } catch (Exception e) { YavscHelpers.Notify (ViewData, "Exception:" + e.Message); return View (collection); } } /// /// Booking the specified model. /// /// Model. public ActionResult EavyBooking (BookingQuery model) { return View (model); } private void SetMEACodeViewData(string MEACode) { var activities = WorkFlowManager.FindActivity ("%", false); var items = new List (); foreach (var a in activities) { items.Add(new SelectListItem() { Selected = MEACode == a.Id, Text = string.Format("{1} : {0}",a.Title,a.Id), Value = a.Id }); } ViewData ["MEACode"] = items; } /// /// Skills the specified model. /// [Authorize (Roles = "Admin")] public ActionResult SiteSkills (string MEACode) { SetMEACodeViewData (MEACode); var skills = SkillManager.FindSkill ("%",MEACode); return View (skills); } /// /// Performers on this MEA. /// fr /// Liste des prestataires dont /// l'activité principale est celle spécifiée /// /// Identifiant APE de l'activité. public ActionResult Performers (string id) { throw new NotImplementedException (); } /// /// Activities the specified search and toPower. /// /// Search. /// If set to true to power. public ActionResult Activities (string id, bool toPower = false) { if (id == null) id = "%"; var activities = WorkFlowManager.FindActivity (id, !toPower); return View (activities); } /// /// Activity at the specified id. /// /// Identifier. public ActionResult Activity (string MEACode) { return View (WorkFlowManager.GetActivity (MEACode)); } /// /// Display and should /// offer Ajax edition of /// user's skills. /// /// the User name. [Authorize ()] public ActionResult UserSkills (string id) { if (id == null) id = User.Identity.Name; // TODO or not to do, handle a skills profile update, // actually performed via the Web API :-° // else if (ModelState.IsValid) {} var usp = SkillManager.GetUserSkills (id); var mea = usp.MEACode; // TODO add a route parameter to the profile method, // named "fs" (standing for fieldset) // That filters the view in order to only edit the given fieldset if (mea == "none") YavscHelpers.Notify (ViewData, "Vous devez choisir une activité avant de pouvoir déclarer vos compétences " + "(Editez la rubrique Informations publiques votre profile)"); var skills = SkillManager.FindSkill ("%",usp.MEACode); ViewData ["SiteSkills"] = skills; return View (usp); } /// /// Dates the query. /// /// The query. /// Model. [Authorize,HttpPost] public ActionResult Book (BookingQuery model) { DateTime mindate = DateTime.Now; if (model.StartDate.Date < mindate.Date) { ModelState.AddModelError ("StartDate", LocalizedText.FillInAFutureDate); } if (model.EndDate < model.StartDate) ModelState.AddModelError ("EndDate", LocalizedText.StartDateAfterEndDate); if (ModelState.IsValid) { var result = new List (); foreach (string meacode in model.MEACodes) { foreach (PerformerProfile profile in WorkFlowManager.FindPerformer(meacode,null)) { if (profile.HasCalendar()) try { var events = ProfileBase.Create (profile.UserName).GetEvents (model.StartDate, model.EndDate); if (events.items.Length == 0) result.Add (profile); } catch (WebException ex) { string response; using (var stream = ex.Response.GetResponseStream ()) { using (var reader = new StreamReader (stream)) { response = reader.ReadToEnd (); stream.Close (); } YavscHelpers.Notify (ViewData, string.Format ( "Google calendar API exception {0} : {1}
{2}
", ex.Status.ToString (), ex.Message, response)); } } } } return View ("Performers", result.ToArray ()); } return View (model); } /// /// Booking the specified model. /// /// Model. public ActionResult Booking (SimpleBookingQuery model) { // assert (model.MEACode!=null), since it's the required part of the route data var needs = SkillManager.FindSkill ("%", model.MEACode); ViewBag.Activity = WorkFlowManager.GetActivity (model.MEACode); var specification = new List (); ViewData ["Needs"] = needs; if (model.Need != null) { if (model.Need != "none") foreach (string specitem in model.Need.Split(',')) { string[] specvals = specitem.Split (' '); specification.Add (new SkillRating () { Id = long.Parse (specvals [0]), Rate = int.Parse (specvals [1]) }); } } // In order to present this form // with no need selected and without // validation error display, // we only check the need here, not at validation time. // Although, the need is indeed cruxial requirement, // but we already have got a MEA code if (ModelState.IsValid && model.Need!=null) { var result = new List (); foreach (PerformerProfile profile in WorkFlowManager.FindPerformer(model.MEACode,specification.ToArray())) if (profile.HasCalendar ()) { try { var events = ProfileBase.Create (profile.UserName).GetEvents ( model.PreferedDate.Date, model.PreferedDate.AddDays (1).Date); // TODO replace (events.items.Length == 0) // with a descent computing of dates and times claims, calendar, // AND performer preferences, perhaps also client preferences result.Add (profile.CreateAvailability (model.PreferedDate, (events.items.Length == 0))); } catch (WebException ex) { HandleWebException (ex, "Google Calendar Api"); } } else result.Add (profile.CreateAvailability (model.PreferedDate, false)); ViewData["Circles"] = CircleManager.ListAvailableCircles(); return View ("Performers", result.ToArray ()); } if (model.Need==null) { // A first Get, or no skill available model.Need = string.Join(",", needs.Select (x => string.Format ("{0}:{1}", x.Id, x.Rate)).ToArray ()); if (string.IsNullOrWhiteSpace (model.Need)) model.Need = "none"; } var activity = WorkFlowManager.GetActivity (model.MEACode); ViewData ["Activity"] = activity; ViewData ["Title"] = activity.Title; ViewData ["Comment"] = activity.Comment; ViewData ["Photo"] = activity.Photo; if (model.PreferedDate < DateTime.Now) model.PreferedDate = DateTime.Now; return View (model); } private void HandleWebException (WebException ex, string context) { string response = ""; using (var stream = ex.Response.GetResponseStream ()) { if (stream.CanRead) { var reader = new StreamReader (stream); response = reader.ReadToEnd (); reader.Close (); reader.DiscardBufferedData (); reader.Dispose (); } stream.Close (); stream.Dispose (); } YavscHelpers.Notify (ViewData, string.Format ( "{3} exception {0} : {1}
{2}
", ex.Status.ToString (), ex.Message, response, context )); } } }