* Estimates as Tex or Pdf

* Estimate edition [mix Mvc&Ajax]
* Billable&Bankable properties on profiles
vnext
Paul Schneider 10 years ago
parent 2ac2338939
commit b39a444cf0
31 changed files with 1101 additions and 218 deletions

@ -41,13 +41,13 @@
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\WorkFlowProvider\WorkFlowProvider.csproj">
<Project>{821FF72D-9F4B-4A2C-B95C-7B965291F119}</Project>
<Name>WorkFlowProvider</Name>
</ProjectReference>
<ProjectReference Include="..\yavscModel\YavscModel.csproj"> <ProjectReference Include="..\yavscModel\YavscModel.csproj">
<Project>{68F5B80A-616E-4C3C-91A0-828AA40000BD}</Project> <Project>{68F5B80A-616E-4C3C-91A0-828AA40000BD}</Project>
<Name>YavscModel</Name> <Name>YavscModel</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\WorkFlowProvider\NpgsqlWorkflow.csproj">
<Project>{821FF72D-9F4B-4A2C-B95C-7B965291F119}</Project>
<Name>NpgsqlWorkflow</Name>
</ProjectReference>
</ItemGroup> </ItemGroup>
</Project> </Project>

@ -12,91 +12,54 @@ namespace WorkFlowProvider
{ {
public class NpgsqlContentProvider: ProviderBase, IContentProvider public class NpgsqlContentProvider: ProviderBase, IContentProvider
{ {
public void Install (System.Data.IDbConnection cnx) public StatusChange[] GetWrittingStatuses (long wrid)
{
throw new NotImplementedException ();
}
public void Uninstall (System.Data.IDbConnection cnx, bool removeConfig)
{
throw new NotImplementedException ();
}
public Estimate[] GetEstimates (string client)
{
throw new NotImplementedException ();
}
public void Install ()
{
throw new NotImplementedException ();
}
public void Uninstall ()
{
throw new NotImplementedException ();
}
public ConfigurationSection DefaultConfig (string appName, string cnxStr)
{ {
throw new NotImplementedException (); throw new NotImplementedException ();
} }
public StatusChange[] GetEstimateStatuses (long estid)
public bool Active {
get {
throw new NotImplementedException ();
}
set {
throw new NotImplementedException ();
}
}
public StatusChange[] GetWrittingStatuses (long wrid)
{ {
throw new NotImplementedException (); throw new NotImplementedException ();
} }
public void TagWritting (long wrid, string tag)
public StatusChange[] GetEstimateStatuses (long estid)
{ {
throw new NotImplementedException (); throw new NotImplementedException ();
} }
public void DropTagWritting (long wrid, string tag) public void DropTagWritting (long wrid, string tag)
{ {
throw new NotImplementedException (); throw new NotImplementedException ();
} }
public void SetWrittingStatus (long wrtid, int status, string username) public void SetWrittingStatus (long wrtid, int status, string username)
{ {
throw new NotImplementedException (); throw new NotImplementedException ();
} }
public void SetEstimateStatus (long estid, int status, string username) public void SetEstimateStatus (long estid, int status, string username)
{ {
throw new NotImplementedException (); throw new NotImplementedException ();
} }
public void Dispose ()
public void TagWritting (long wrid, string tag)
{ {
throw new NotImplementedException (); throw new NotImplementedException ();
} }
public void Install (System.Data.IDbConnection cnx)
public string Order (IWFOrder c)
{ {
throw new NotImplementedException (); throw new NotImplementedException ();
} }
public void Uninstall (System.Data.IDbConnection cnx, bool removeConfig)
public IContent GetBlob (string orderId)
{ {
throw new NotImplementedException (); throw new NotImplementedException ();
} }
public ConfigurationSection DefaultConfig (string appName, string cnxStr)
public int GetStatus (string orderId)
{ {
throw new NotImplementedException (); throw new NotImplementedException ();
} }
public bool Active {
get {
throw new NotImplementedException ();
}
set {
throw new NotImplementedException ();
}
}
public string[] Statuses { public string[] Statuses {
get { get {
@ -108,6 +71,24 @@ namespace WorkFlowProvider
return new bool[] { false, false, true, true }; return new bool[] { false, false, true, true };
} }
} }
public Estimate[] GetEstimates (string client)
{
using (NpgsqlConnection cnx = CreateConnection ()) {
using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText =
"select _id from estimate where client = @clid";
cmd.Parameters.Add ("@clid", client);
cnx.Open ();
List<Estimate> ests = new List<Estimate> ();
using (NpgsqlDataReader rdr = cmd.ExecuteReader ()) {
while (rdr.Read ()) {
ests.Add(GetEstimate(rdr.GetInt64(0)));
}
}
return ests.ToArray();
}
}
}
public void DropWritting (long wrid) public void DropWritting (long wrid)
{ {
@ -143,7 +124,7 @@ namespace WorkFlowProvider
using (NpgsqlConnection cnx = CreateConnection ()) { using (NpgsqlConnection cnx = CreateConnection ()) {
using (NpgsqlCommand cmd = cnx.CreateCommand ()) { using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = cmd.CommandText =
"select title,username from estimate where _id = @estid"; "select title,username,client,description from estimate where _id = @estid";
cmd.Parameters.Add ("@estid", estimid); cmd.Parameters.Add ("@estid", estimid);
cnx.Open (); cnx.Open ();
@ -155,8 +136,13 @@ namespace WorkFlowProvider
est = new Estimate (); est = new Estimate ();
est.Title = rdr.GetString( est.Title = rdr.GetString(
rdr.GetOrdinal("title")); rdr.GetOrdinal("title"));
est.Owner = rdr.GetString( est.Responsible = rdr.GetString(
rdr.GetOrdinal("username")); rdr.GetOrdinal("username"));
est.Client = rdr.GetString (
rdr.GetOrdinal ("client"));
int index = rdr.GetOrdinal ("description");
if (!rdr.IsDBNull (index))
est.Description = rdr.GetString (index);
est.Id = estimid; est.Id = estimid;
using (NpgsqlCommand cmdw = new NpgsqlCommand ("select _id, productid, ucost, count, description from writtings where estimid = @estid", cnx)) { using (NpgsqlCommand cmdw = new NpgsqlCommand ("select _id, productid, ucost, count, description from writtings where estimid = @estid", cnx)) {
cmdw.Parameters.Add("@estid", estimid); cmdw.Parameters.Add("@estid", estimid);
@ -166,8 +152,9 @@ namespace WorkFlowProvider
lw = new List<Writting> (); lw = new List<Writting> ();
while (rdrw.Read ()) { while (rdrw.Read ()) {
Writting w = new Writting (); Writting w = new Writting ();
w.Description = rdrw.GetString ( int dei = rdrw.GetOrdinal ("description");
rdrw.GetOrdinal ("description")); if (!rdrw.IsDBNull (dei))
w.Description = rdrw.GetString (dei);
int opi = rdrw.GetOrdinal ("productid"); int opi = rdrw.GetOrdinal ("productid");
if (!rdrw.IsDBNull (opi)) if (!rdrw.IsDBNull (opi))
w.ProductReference = rdrw.GetString(opi); w.ProductReference = rdrw.GetString(opi);
@ -217,14 +204,18 @@ namespace WorkFlowProvider
} }
} }
public void SetTitle (long estid, string newTitle) public void UpdateEstimate (Estimate estim)
{ {
using (NpgsqlConnection cnx = CreateConnection ()) { using (NpgsqlConnection cnx = CreateConnection ()) {
using (NpgsqlCommand cmd = cnx.CreateCommand ()) { using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = cmd.CommandText =
"update estimate set title = @tit where _id = @estid"; "update estimate set title = @tit, username = @un, " +
cmd.Parameters.Add ("@tit", newTitle); "description = @descr, client = @cli where _id = @estid";
cmd.Parameters.Add ("@estid", estid); cmd.Parameters.Add ("@tit", estim.Title);
cmd.Parameters.Add ("@un", estim.Responsible);
cmd.Parameters.Add ("@descr", estim.Description);
cmd.Parameters.Add ("@cli", estim.Client);
cmd.Parameters.Add ("@estid", estim.Id);
cnx.Open (); cnx.Open ();
cmd.ExecuteNonQuery (); cmd.ExecuteNonQuery ();
cnx.Close (); cnx.Close ();
@ -272,20 +263,27 @@ namespace WorkFlowProvider
} }
public long CreateEstimate (string client, string title) public Estimate CreateEstimate (string responsible, string client, string title, string description)
{ {
using (NpgsqlConnection cnx = CreateConnection ()) { using (NpgsqlConnection cnx = CreateConnection ()) {
using (NpgsqlCommand cmd = cnx.CreateCommand ()) { using (NpgsqlCommand cmd = cnx.CreateCommand ()) {
cmd.CommandText = cmd.CommandText =
"insert into estimate (title,username,applicationname) " + "insert into estimate (title,description,username,client,applicationname) " +
"values (@tit,@un,@app) returning _id"; "values (@tit,@descr,@resp,@un,@app) returning _id";
cmd.Parameters.Add ("@tit", title); cmd.Parameters.Add ("@tit", title);
cmd.Parameters.Add ("@un", client); cmd.Parameters.Add ("@un", client);
cmd.Parameters.Add ("@resp", responsible);
cmd.Parameters.Add ("@descr", description);
cmd.Parameters.Add("@app", ApplicationName); cmd.Parameters.Add("@app", ApplicationName);
cnx.Open (); cnx.Open ();
long res = (long)cmd.ExecuteScalar (); Estimate created = new Estimate ();
created.Id = (long)cmd.ExecuteScalar ();
cnx.Close (); cnx.Close ();
return res; created.Title = title;
created.Description = description;
created.Client = client;
created.Responsible = responsible;
return created;
} }
} }
} }
@ -319,12 +317,6 @@ namespace WorkFlowProvider
{ {
return new NpgsqlConnection (cnxstr); return new NpgsqlConnection (cnxstr);
} }
#region IDisposable implementation
public void Dispose ()
{
}
#endregion
} }
} }

@ -11,7 +11,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SalesCatalog", "SalesCatalo
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YavscModel", "yavscModel\YavscModel.csproj", "{68F5B80A-616E-4C3C-91A0-828AA40000BD}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YavscModel", "yavscModel\YavscModel.csproj", "{68F5B80A-616E-4C3C-91A0-828AA40000BD}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkFlowProvider", "WorkFlowProvider\WorkFlowProvider.csproj", "{821FF72D-9F4B-4A2C-B95C-7B965291F119}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NpgsqlWorkflow", "WorkFlowProvider\NpgsqlWorkflow.csproj", "{821FF72D-9F4B-4A2C-B95C-7B965291F119}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YavscClient", "yavscclient\YavscClient.csproj", "{EEFCECE6-3B7F-4BBE-B7AF-69377AF3CF39}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YavscClient", "yavscclient\YavscClient.csproj", "{EEFCECE6-3B7F-4BBE-B7AF-69377AF3CF39}"
EndProject EndProject

@ -43,13 +43,7 @@ namespace Yavsc.Controllers
return new Profile (ProfileBase.Create (user)); return new Profile (ProfileBase.Create (user));
} }
[Authorize]
public ActionResult Profile(Profile model)
{
ViewData ["UserName"] = Membership.GetUser ().UserName;
model = GetProfile ((string)ViewData ["UserName"]);
return View (model);
}
// TODO [ValidateAntiForgeryToken] // TODO [ValidateAntiForgeryToken]
public ActionResult DoLogin (LoginModel model, string returnUrl) public ActionResult DoLogin (LoginModel model, string returnUrl)
{ {
@ -200,14 +194,22 @@ namespace Yavsc.Controllers
} }
[Authorize]
[HttpGet]
public ActionResult Profile(Profile model)
{
ViewData ["UserName"] = Membership.GetUser ().UserName;
model = GetProfile ((string) ViewData ["UserName"]);
return View (model);
}
[Authorize] [Authorize]
[HttpPost] [HttpPost]
//public ActionResult UpdateProfile(HttpPostedFileBase Avatar, string Address, string CityAndState, string ZipCode, string Country, string WebSite) //public ActionResult UpdateProfile(HttpPostedFileBase Avatar, string Address, string CityAndState, string ZipCode, string Country, string WebSite)
public ActionResult UpdateProfile(Profile model, HttpPostedFileBase AvatarFile) public ActionResult Profile(Profile model, HttpPostedFileBase AvatarFile)
{ {
string username = Membership.GetUser ().UserName; string username = Membership.GetUser ().UserName;
ViewData ["UserName"] = username;
if (AvatarFile != null) { if (AvatarFile != null) {
if (AvatarFile.ContentType == "image/png") { if (AvatarFile.ContentType == "image/png") {
@ -233,14 +235,36 @@ namespace Yavsc.Controllers
"BlogVisible", model.BlogVisible); "BlogVisible", model.BlogVisible);
HttpContext.Profile.SetPropertyValue ( HttpContext.Profile.SetPropertyValue (
"CityAndState", model.CityAndState); "CityAndState", model.CityAndState);
HttpContext.Profile.SetPropertyValue (
"ZipCode", model.ZipCode);
HttpContext.Profile.SetPropertyValue ( HttpContext.Profile.SetPropertyValue (
"Country", model.Country); "Country", model.Country);
HttpContext.Profile.SetPropertyValue ( HttpContext.Profile.SetPropertyValue (
"WebSite", model.WebSite); "WebSite", model.WebSite);
HttpContext.Profile.SetPropertyValue (
"Name", model.Name);
HttpContext.Profile.SetPropertyValue (
"Phone", model.Phone);
HttpContext.Profile.SetPropertyValue (
"Mobile", model.Mobile);
HttpContext.Profile.SetPropertyValue (
"BankCode", model.BankCode);
HttpContext.Profile.SetPropertyValue (
"WicketCode", model.WicketCode);
HttpContext.Profile.SetPropertyValue (
"AccountNumber", model.AccountNumber);
HttpContext.Profile.SetPropertyValue (
"BankedKey", model.BankedKey);
HttpContext.Profile.SetPropertyValue (
"BIC", model.BIC);
HttpContext.Profile.SetPropertyValue (
"IBAN", model.IBAN);
HttpContext.Profile.Save ();
ViewData ["Message"] = "Profile enregistré.";
} }
// HttpContext.Profile.SetPropertyValue("Avatar",Avatar); // HttpContext.Profile.SetPropertyValue("Avatar",Avatar);
return RedirectToAction ("Profile"); return View (model);
} }
[Authorize] [Authorize]

@ -225,7 +225,7 @@ namespace Yavsc.Controllers
return UserPost (model.PostId); return UserPost (model.PostId);
} }
} }
return View (model); return UserPost (model.PostId);
} }
string defaultAvatar; string defaultAvatar;

@ -14,12 +14,20 @@ using System.Net;
using WorkFlowProvider; using WorkFlowProvider;
using System.Web.Security; using System.Web.Security;
using Yavsc.Model.WorkFlow; using Yavsc.Model.WorkFlow;
using System.Reflection;
using System.Collections.Generic;
using Yavsc.Model.RolesAndMembers;
using Yavsc.Controllers;
using Yavsc.Formatters;
using System.Text;
using System.Web.Profile;
namespace Yavsc.ApiControllers namespace Yavsc.ApiControllers
{ {
public class FrontOfficeController : ApiController public class FrontOfficeController : ApiController
{ {
[AcceptVerbs("GET")] [AcceptVerbs("GET")]
public Catalog Catalog () public Catalog Catalog ()
{ {
@ -77,6 +85,52 @@ namespace Yavsc.ApiControllers
return est; return est;
} }
[AcceptVerbs("GET")]
public HttpResponseMessage GetTexEstim(long estimid)
{
return new HttpResponseMessage () {
Content = new ObjectContent (typeof(string),
getTexEstim (estimid),
new TexFormatter ())
};
}
private string getTexEstim(long estimid)
{
Yavsc.templates.Estim tmpe = new Yavsc.templates.Estim();
Estimate e = WorkFlowManager.GetEstimate (estimid);
tmpe.Session = new Dictionary<string,object>();
tmpe.Session.Add ("estim", e);
Profile pr = AccountController.GetProfile (e.Responsible);
tmpe.Session.Add ("from", pr);
tmpe.Session.Add ("to", pr);
tmpe.Init ();
return tmpe.TransformText ();
}
/// <summary>
/// Gets the estimate in pdf format from tex generation.
/// </summary>
/// <returns>The estim pdf.</returns>
/// <param name="estimid">Estimid.</param>
public HttpResponseMessage GetEstimPdf(long estimid)
{
Estimate estim = WorkFlowManager.GetEstimate (estimid);
Profile prpro = new Profile(ProfileBase.Create(estim.Responsible));
if (!prpro.IsBankable)
throw new Exception ("NotBankable:"+estim.Responsible);
Profile prcli = new Profile(ProfileBase.Create(estim.Client));
if (!prcli.IsBillable)
throw new Exception ("NotBillable:"+estim.Client);
return new HttpResponseMessage () {
Content = new ObjectContent (
typeof(Estimate),
estim,
new EstimToPdfFormatter ())
};
}
} }
} }

@ -20,39 +20,54 @@ namespace Yavsc.Controllers
/// </summary> /// </summary>
public class FrontOfficeController : Controller public class FrontOfficeController : Controller
{ {
[Authorize]
public ActionResult Estimates ()
{
string username = Membership.GetUser ().UserName;
return View(WorkFlowManager.GetEstimates (username));
}
[Authorize] [Authorize]
public ActionResult Estimate(Estimate model,string submit) public ActionResult Estimate(Estimate model,string submit)
{ {
if (ModelState.IsValid) { if (submit == null) {
ViewData ["WebApiUrl"] = "http://"+ Request.Url.Authority + "/api/WorkFlow";
string username = HttpContext.User.Identity.Name;
if (model.Id > 0) { if (model.Id > 0) {
Estimate f = WorkFlowManager.GetEstimate (model.Id); Estimate f = WorkFlowManager.GetEstimate (model.Id);
if (f == null) { if (f == null) {
ModelState.AddModelError ("Id", "Wrong Id"); ModelState.AddModelError ("Id", "Wrong Id");
return View (model); return View (model);
} }
if (username != f.Owner) model = f;
if (!Roles.IsUserInRole ("FrontOffice")) ModelState.Clear ();
throw new UnauthorizedAccessException ("You're not allowed to view/modify this estimate"); string username = HttpContext.User.Identity.Name;
if (submit == "Update") { if (username != model.Responsible
if (model != f) { && username != model.Client
WorkFlowManager.SetTitle (model.Id, model.Title); && !Roles.IsUserInRole ("FrontOffice"))
} throw new UnauthorizedAccessException ("You're not allowed to view this estimate");
} else if (submit == null) {
model = f; }
} } else if (ModelState.IsValid) {
ViewData ["WebApiUrl"] = "http://" + Request.Url.Authority + "/api/WorkFlow";
string username = HttpContext.User.Identity.Name;
if (username != model.Responsible
&& username != model.Client
&& !Roles.IsUserInRole ("FrontOffice"))
throw new UnauthorizedAccessException ("You're not allowed to modify this estimate");
if (model.Id == 0)
model = WorkFlowManager.CreateEstimate (
username,
model.Client, model.Title, model.Description);
else
WorkFlowManager.UpdateEstimate (model);
} else if (model.Id == 0 && submit=="Create") {
// Create the estimate
model.Id=WorkFlowManager.CreateEstimate (username,
model.Title);
model.Owner = username;
}
} }
return View(model); return View(model);
} }
[AcceptVerbs("GET")] [AcceptVerbs("GET")]
public ActionResult Catalog () public ActionResult Catalog ()
{ {

@ -26,10 +26,10 @@ namespace Yavsc.ApiControllers
[HttpGet] [HttpGet]
[Authorize] [Authorize]
public long CreateEstimate (string title) public Estimate CreateEstimate (string title,string client,string description)
{ {
return WorkFlowManager.CreateEstimate ( return WorkFlowManager.CreateEstimate (
Membership.GetUser().UserName,title); Membership.GetUser().UserName,client,title,description);
} }
[HttpGet] [HttpGet]

@ -0,0 +1,112 @@
//
// EstimToPdfFormatter.cs
//
// Author:
// Paul Schneider <paulschneider@free.fr>
//
// Copyright (c) 2014 Paul Schneider
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http.Headers;
using System.Net.Http.Formatting;
using Yavsc.Model.WorkFlow;
using Yavsc.Model.RolesAndMembers;
using System.Web.Profile;
using System.Web;
using System.Diagnostics;
namespace Yavsc.Formatters
{
public class EstimToPdfFormatter: BufferedMediaTypeFormatter
{
public EstimToPdfFormatter ()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/pdf"));
}
public override bool CanReadType(Type type)
{
return false;
}
public override bool CanWriteType(System.Type type)
{
if (type == typeof(Estimate))
{
return true;
}
else
{
Type enumerableType = typeof(IEnumerable<Estimate>);
return enumerableType.IsAssignableFrom(type);
}
}
public override void WriteToStream (Type type, object value, Stream stream, HttpContentHeaders contentHeaders)
{
// TODO create a type containing generation parameters, including a template path, and generate from them
Yavsc.templates.Estim tmpe = new Yavsc.templates.Estim();
tmpe.Session = new Dictionary<string,object>();
Estimate e = value as Estimate;
tmpe.Session.Add ("estim", e);
Profile prpro = new Profile (ProfileBase.Create (e.Responsible));
var pbc = ProfileBase.Create (e.Client);
Profile prcli = new Profile (pbc);
if (!prpro.IsBankable)
throw new Exception ("This provider is not bankable.");
tmpe.Session.Add ("from", prpro);
tmpe.Session.Add ("to", prcli);
tmpe.Init ();
string content = tmpe.TransformText ();
string name = string.Format ("tmpestimtex{0}", e.Id);
string fullname = Path.Combine (
HttpRuntime.CodegenDir, name);
FileInfo fi = new FileInfo(fullname + ".tex");
FileInfo fo = new FileInfo(fullname + ".pdf");
using (StreamWriter sw = new StreamWriter (fi.FullName))
{
sw.Write (content);
}
using (Process p = new Process ()) {
p.StartInfo.WorkingDirectory = HttpRuntime.CodegenDir;
p.StartInfo = new ProcessStartInfo ();
p.StartInfo.UseShellExecute = false;
p.StartInfo.FileName = "/usr/bin/texi2pdf";
p.StartInfo.Arguments =
string.Format ("--batch -o {0} {1}",
fo.FullName,
fi.FullName);
p.Start ();
p.WaitForExit ();
}
using (StreamReader sr = new StreamReader (fo.FullName)) {
byte[] buffer = File.ReadAllBytes (fo.FullName);
stream.Write(buffer,0,buffer.Length);
}
fi.Delete();
fo.Delete();
}
}
}

@ -0,0 +1,68 @@
//
// TexFormatter.cs
//
// Author:
// Paul Schneider <paulschneider@free.fr>
//
// Copyright (c) 2014 Paul Schneider
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
namespace Yavsc.Formatters
{
public class TexFormatter : BufferedMediaTypeFormatter
{
public TexFormatter ()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/x-tex"));
}
public override bool CanWriteType(System.Type type)
{
if (type == typeof(string))
{
return true;
}
else
{
Type enumerableType = typeof(IEnumerable<string>);
return enumerableType.IsAssignableFrom(type);
}
}
public override bool CanReadType(Type type)
{
return false;
}
public override void WriteToStream (Type type, object value, Stream stream, HttpContentHeaders contentHeaders)
{
// TODO create a type containing T4 parameters, and generate from them
using (var writer = new StreamWriter(stream))
{
string doc = value as string;
writer.Write (doc);
}
}
}
}

@ -7,6 +7,7 @@ using System.Web;
using System.Web.Mvc; using System.Web.Mvc;
using System.Web.Routing; using System.Web.Routing;
using System.Web.Http; using System.Web.Http;
using Yavsc.Formatters;
namespace Yavsc namespace Yavsc
{ {
@ -43,7 +44,7 @@ namespace Yavsc
protected void Application_Start () protected void Application_Start ()
{ {
AreaRegistration.RegisterAllAreas (); AreaRegistration.RegisterAllAreas ();
GlobalConfiguration.Configuration.Formatters.Add (new TexFormatter ());
GlobalConfiguration.Configuration.Routes.MapHttpRoute( GlobalConfiguration.Configuration.Routes.MapHttpRoute(
name: "DefaultApi", name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{*id}", routeTemplate: "api/{controller}/{action}/{*id}",

@ -39,3 +39,6 @@ table.tablesorter thead tr .headerSortDown {
table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp { table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp {
background-color: #123; background-color: #123;
} }
tr.selected td {
background-color:#102010;
}

@ -5,14 +5,25 @@
</asp:Content> </asp:Content>
<asp:Content ID="MainContentContent" ContentPlaceHolderID="MainContent" runat="server"> <asp:Content ID="MainContentContent" ContentPlaceHolderID="MainContent" runat="server">
<%= Html.ActionLink("Changer de mot de passe","ChangePassword", "Account")%>
<%= Html.ValidationSummary() %> <%= Html.ValidationSummary() %>
<% using(Html.BeginForm("UpdateProfile", "Account", FormMethod.Post, new { enctype = "multipart/form-data" })) %> <% using(Html.BeginForm("Profile", "Account", FormMethod.Post, new { enctype = "multipart/form-data" })) %>
<% { %> <% { %>
<h2>Informations générales</h2>
<table class="layout"> <table class="layout">
<tr><td align="right"> <tr><td align="right">
<%= Html.LabelFor(model => model.Name) %></td><td>
<%= Html.TextBox("Name") %>
<%= Html.ValidationMessage("Name", "*") %></td></tr>
<tr><td align="right">
<%= Html.LabelFor(model => model.Phone) %></td><td>
<%= Html.TextBox("Phone") %>
<%= Html.ValidationMessage("Phone", "*") %></td></tr>
<tr><td align="right">
<%= Html.LabelFor(model => model.Mobile) %></td><td>
<%= Html.TextBox("Mobile") %>
<%= Html.ValidationMessage("Mobile", "*") %></td></tr>
<tr><td align="right">
<%= Html.LabelFor(model => model.Address) %></td><td> <%= Html.LabelFor(model => model.Address) %></td><td>
<%= Html.TextBox("Address") %> <%= Html.TextBox("Address") %>
<%= Html.ValidationMessage("Address", "*") %></td></tr> <%= Html.ValidationMessage("Address", "*") %></td></tr>
@ -21,6 +32,10 @@
<%= Html.TextBox("CityAndState") %> <%= Html.TextBox("CityAndState") %>
<%= Html.ValidationMessage("CityAndState", "*") %></td></tr> <%= Html.ValidationMessage("CityAndState", "*") %></td></tr>
<tr><td align="right"> <tr><td align="right">
<%= Html.LabelFor(model => model.ZipCode) %></td><td>
<%= Html.TextBox("ZipCode") %>
<%= Html.ValidationMessage("ZipCode", "*") %></td></tr>
<tr><td align="right">
<%= Html.LabelFor(model => model.Country) %></td><td> <%= Html.LabelFor(model => model.Country) %></td><td>
<%= Html.TextBox("Country") %> <%= Html.TextBox("Country") %>
<%= Html.ValidationMessage("Country", "*") %></td></tr> <%= Html.ValidationMessage("Country", "*") %></td></tr>
@ -42,6 +57,74 @@ Avatar </td><td> <img class="avatar" src="/Blogs/Avatar?user=<%=ViewData["User
<%= Html.ValidationMessage("AvatarFile", "*") %></td></tr> <%= Html.ValidationMessage("AvatarFile", "*") %></td></tr>
</table> </table>
<h2>Informations de facturation</h2>
<table class="layout">
<tr>
<td align="right">
<%= Html.LabelFor(model => model.BankCode) %>
</td>
<td>
<%= Html.TextBox("BankCode") %>
<%= Html.ValidationMessage("BankCode", "*") %>
</td>
</tr>
<tr>
<td align="right">
<%= Html.LabelFor(model => model.WicketCode) %></td>
<td>
<%= Html.TextBox("WicketCode") %>
<%= Html.ValidationMessage("WicketCode", "*") %>
</td>
</tr>
<tr>
<td align="right">
<%= Html.LabelFor(model => model.AccountNumber) %></td>
<td>
<%= Html.TextBox("AccountNumber") %>
<%= Html.ValidationMessage("AccountNumber", "*") %>
</td>
</tr>
<tr>
<td align="right">
<%= Html.LabelFor(model => model.BankedKey) %></td>
<td>
<%= Html.TextBox("BankedKey") %>
<%= Html.ValidationMessage("BankedKey", "*") %>
</td>
</tr>
<tr>
<td align="right">
<%= Html.LabelFor(model => model.BIC) %></td>
<td>
<%= Html.TextBox("BIC") %>
<%= Html.ValidationMessage("BIC", "*") %>
</td>
</tr>
<tr>
<td align="right">
<%= Html.LabelFor(model => model.IBAN) %></td>
<td>
<%= Html.TextBox("IBAN") %>
<%= Html.ValidationMessage("IBAN", "*") %>
</td>
</tr>
</table>
<input type="submit"/> <input type="submit"/>
<% } %> <% } %>
</asp:Content> </asp:Content>
<asp:Content ID="MASC1" ContentPlaceHolderID="MASContent" runat="server">
<%= Html.ActionLink("Changer de mot de passe","ChangePassword", "Account")%>
</asp:Content>

@ -13,12 +13,16 @@
<% using (Html.BeginForm("Estimate","FrontOffice")) { %> <% using (Html.BeginForm("Estimate","FrontOffice")) { %>
<%= Html.LabelFor(model => model.Title) %>:<%= Html.TextBox( "Title" ) %> <%= Html.LabelFor(model => model.Title) %>:<%= Html.TextBox( "Title" ) %>
<%= Html.ValidationMessage("Title", "*") %> <%= Html.ValidationMessage("Title", "*") %>
<% if (Model.Id > 0) { %>
<br/> <br/>
<%= Html.LabelFor(model => model.Owner) %>:<%=Model.Owner%> <%= Html.LabelFor(model => model.Responsible) %>:<%=Model.Responsible%>
<%= Html.ValidationMessage("Owner", "*") %> <%= Html.Hidden ("Responsible") %>
<%= Html.ValidationMessage("Responsible", "*") %>
<br/> <br/>
<%= Html.LabelFor(model => model.Ciffer) %>:<%=Model.Ciffer%> <%= Html.LabelFor(model => model.Client) %>:<%=Html.TextBox( "Client" ) %>
<%= Html.ValidationMessage("Client", "*") %>
<br/>
<%= Html.LabelFor(model => model.Description) %>:<%=Html.TextArea( "Description") %>
<%= Html.ValidationMessage("Description", "*") %>
<br/> <br/>
<%= Html.LabelFor(model => model.Id) %>:<%=Model.Id%> <%= Html.LabelFor(model => model.Id) %>:<%=Model.Id%>
<%= Html.Hidden( "Id" ) %> <%= Html.Hidden( "Id" ) %>
@ -31,7 +35,7 @@
<% } %> <% } %>
<% if (Model.Id>0) { %>
<table class="tablesorter"> <table class="tablesorter">
<thead> <thead>
@ -76,12 +80,14 @@
<form id="writeform"> <form id="writeform">
<input type="button" id="btndtl" value="+"/> <input type="button" id="btndtl" value="+"/>
<div id="writearea" style="display:none;">
<div id="writearea" style="display:none;">
<input type="button" id="btnnew" value="Nouvelle écriture"/>
<input type="hidden" name="estid" id="estid" value="<%=Model.Id%>"/> <input type="hidden" name="estid" id="estid" value="<%=Model.Id%>"/>
<label for="Description">Description:</label> <label for="Description">Description:</label>
<input type="text" name="Description" id="Description" /> <input type="text" name="Description" id="Description" />
<label for="UnitaryCost">Prix unitaire:</label> <label for="UnitaryCost">Prix unitaire:</label>
<input type="number" name="UnitaryCost" id="UnitaryCost"/> <input type="number" name="UnitaryCost" id="UnitaryCost" step="0.01"/>
<label for="Count">Quantité:</label> <label for="Count">Quantité:</label>
<input type="number" name="Count" id="Count"/> <input type="number" name="Count" id="Count"/>
<label for="ProductReference">Référence du produit:</label> <label for="ProductReference">Référence du produit:</label>
@ -94,9 +100,11 @@
<tt id="msg" class="message"></tt> <tt id="msg" class="message"></tt>
<style> <style>
.row { cursor:pointer; } .row { cursor:pointer; }
table.tablesorter td:hover { background-color: rgb(64,0,0); } table.tablesorter td:hover { background-color: rgba(0,64,0,0.5); }
.hidden { display:none; } .hidden { display:none; }
</style> .selected *, .odd .selected { font-size-adjust: +1; background-color: rgb(0,64,0); }
</style>
<script> <script>
jQuery.support.cors = true; jQuery.support.cors = true;
@ -112,7 +120,11 @@
function wredit(pwrid) function wredit(pwrid)
{ {
$("#wr"+wrid.value).removeClass("selected");
$("#wrid").val(pwrid); $("#wrid").val(pwrid);
if (wrid.value!=0)
$("#wr"+wrid.value).addClass("selected");
if (pwrid>0) { if (pwrid>0) {
$("#btncreate").addClass("hidden"); $("#btncreate").addClass("hidden");
$("#btnmodify").removeClass("hidden"); $("#btnmodify").removeClass("hidden");
@ -123,11 +135,8 @@
$("#btndrop").addClass("hidden"); $("#btndrop").addClass("hidden");
} }
} }
$(document).ready(function () { function delRow() {
// bug at no row: $(".tablesorter").tablesorter( {sortList: [[0,0], [1,0]]} );
function delRow() {
$.ajax({ $.ajax({
url: "<%=ViewData["WebApiUrl"]+"/DropWritting"%>", url: "<%=ViewData["WebApiUrl"]+"/DropWritting"%>",
type: "Get", type: "Get",
@ -148,6 +157,7 @@
}); });
} }
function setRow() { function setRow() {
var wrt = GetWritting(); var wrt = GetWritting();
@ -167,9 +177,9 @@
$("#msg").text(xhr.status+" : "+xhr.responseText);} $("#msg").text(xhr.status+" : "+xhr.responseText);}
}); });
} }
//data: {estid: estid, wr: { Id: 0, UnitaryCost: wrt.UnitaryCost, Count: wrt.Count, ProductReference: wrt.ProductReference, Description: wrt.Description}},
function addRow(){ function addRow(){
var wrt = GetWritting(); var wrt = GetWritting();
var estid = parseInt($("#Id").val()); var estid = parseInt($("#Id").val());
$.ajax({ $.ajax({
@ -181,35 +191,47 @@
success: function (data) { success: function (data) {
wrt.Id = Number(data); wrt.Id = Number(data);
wredit(wrt.Id); wredit(wrt.Id);
$("<tr class=\"row\" id=\"wr"+wrt.Id+"\"><td>"+wrt.Description+"</td><td>"+wrt.ProductReference+"</td><td>"+wrt.Count+"</td><td>"+wrt.UnitaryCost+"</td></tr>").appendTo("#wrts") $("<tr class=\"row\" id=\"wr"+wrt.Id+"\"><td>"+wrt.Description+"</td><td>"+wrt.ProductReference+"</td><td>"+wrt.Count+"</td><td>"+wrt.UnitaryCost+"</td></tr>").appendTo("#wrts");
}, },
error: function (xhr, ajaxOptions, thrownError) { error: function (xhr, ajaxOptions, thrownError) {
$("#msg").text(xhr.status+" : "+xhr.responseText);} $("#msg").text(xhr.status+" : "+xhr.responseText);}
}); });
$(".wr"+wrt.Id).click(onEditRow(e));
} }
$("#btncreate").click(addRow);
$("#btnmodify").click(setRow);
$("#btndrop").click(delRow);
function ShowDtl(val) function ShowDtl(val)
{ {
document.getElementById("writearea").style.display = val ? "block" : "none"; document.getElementById("writearea").style.display = val ? "block" : "none";
document.getElementById("btndtl").value = val ? "-" : "+"; document.getElementById("btndtl").value = val ? "-" : "+";
} }
$("#btndtl").click(function(){ShowDtl(document.getElementById("writearea").style.display != "block");}); function onEditRow(e) {
$(".row").click(function (e) {
ShowDtl(true); ShowDtl(true);
var cells = e.delegateTarget.getElementsByTagName("TD"); var cells = e.delegateTarget.getElementsByTagName("TD");
var wrid = Number(e.delegateTarget.id.substr(2)); var hid=e.delegateTarget.id;
wredit(wrid); var vwrid = Number(hid.substr(2));
wredit(vwrid);
$("#Description").val(cells[0].innerHTML); $("#Description").val(cells[0].innerHTML);
$("#ProductReference").val(cells[1].innerHTML); $("#ProductReference").val(cells[1].innerHTML);
$("#Count").val(cells[2].innerHTML); $("#Count").val(cells[2].innerHTML);
$("#UnitaryCost").val(Number(cells[3].innerHTML.replace(",","."))); $("#UnitaryCost").val(Number(cells[3].innerHTML.replace(",",".")));
}); }
$(document).ready(function () {
// bug when no row: $(".tablesorter").tablesorter( {sortList: [[0,0], [1,0]]} );
$("#btncreate").click(addRow);
$("#btnmodify").click(setRow);
$("#btndrop").click(delRow);
$("#btndtl").click(function(){ShowDtl(document.getElementById("writearea").style.display != "block");});
$(".row").click(function (e) {onEditRow(e);});
$("#btnnew").click(function () {
wredit(0);
$("#Description").val("");
$("#ProductReference").val("");
$("#Count").val(1);
$("#UnitaryCost").val(0);
});
}); });
</script> </script>
</div> </div>

@ -0,0 +1,8 @@
<%@ Page Title="My estimates" Language="C#" MasterPageFile="~/Models/App.master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<Estimate>>" %>
<asp:Content ID="MainContentContent" ContentPlaceHolderID="MainContent" runat="server">
<% foreach (Estimate estim in Model) { %>
<%= Html.ActionLink(estim.Id.ToString(),"Estimate",new {Id=estim.Id}) %>
<% } %>
</asp:Content>
<asp:Content ID="MASContentContent" ContentPlaceHolderID="MASContent" runat="server">
</asp:Content>

@ -140,6 +140,15 @@ http://msdn2.microsoft.com/en-us/library/b5ysx397.aspx
<add name="ZipCode" /> <add name="ZipCode" />
<add name="WebSite" /> <add name="WebSite" />
<add name="Country" /> <add name="Country" />
<add name="Name" />
<add name="Phone" />
<add name="Mobile" />
<add name="BankCode" />
<add name="IBAN" />
<add name="BIC" />
<add name="WicketCode" />
<add name="AccountNumber" />
<add name="BankedKey" />
</properties> </properties>
</profile> </profile>
<blog defaultProvider="NpgsqlBlogProvider"> <blog defaultProvider="NpgsqlBlogProvider">

@ -116,6 +116,9 @@
<Folder Include="Theme\green\" /> <Folder Include="Theme\green\" />
<Folder Include="Theme\blue\" /> <Folder Include="Theme\blue\" />
<Folder Include="Theme\dark\" /> <Folder Include="Theme\dark\" />
<Folder Include="templates\" />
<Folder Include="Formatters\" />
<Folder Include="install\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Controllers\HomeController.cs" /> <Compile Include="Controllers\HomeController.cs" />
@ -148,6 +151,12 @@
<Compile Include="Controllers\BlogsApiController.cs" /> <Compile Include="Controllers\BlogsApiController.cs" />
<Compile Include="Controllers\AdminController.cs" /> <Compile Include="Controllers\AdminController.cs" />
<Compile Include="Helpers\T.cs" /> <Compile Include="Helpers\T.cs" />
<Compile Include="templates\Estim.cs">
<DependentUpon>Estim.tt</DependentUpon>
</Compile>
<Compile Include="templates\TexEstimInit.cs" />
<Compile Include="Formatters\TexFormatter.cs" />
<Compile Include="Formatters\EstimToPdfFormatter.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="Views\Web.config" /> <Content Include="Views\Web.config" />
@ -225,6 +234,7 @@
<Content Include="Theme\dark\bg.gif" /> <Content Include="Theme\dark\bg.gif" />
<Content Include="Theme\dark\desc.gif" /> <Content Include="Theme\dark\desc.gif" />
<Content Include="Theme\dark\style.css" /> <Content Include="Theme\dark\style.css" />
<Content Include="Views\FrontOffice\Estimates.aspx" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" /> <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
@ -246,6 +256,11 @@
<None Include="instdbws.sql" /> <None Include="instdbws.sql" />
<None Include="RegistrationMail.txt" /> <None Include="RegistrationMail.txt" />
<None Include="Catalog.xml" /> <None Include="Catalog.xml" />
<None Include="templates\Estim.tt">
<Generator>TextTemplatingFilePreprocessor</Generator>
<LastGenOutput>Estim.cs</LastGenOutput>
</None>
<None Include="install\instdb.sql" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\NpgsqlMRPProviders\NpgsqlMRPProviders.csproj"> <ProjectReference Include="..\NpgsqlMRPProviders\NpgsqlMRPProviders.csproj">
@ -260,10 +275,6 @@
<Project>{90BF2234-7252-4CD5-B2A4-17501B19279B}</Project> <Project>{90BF2234-7252-4CD5-B2A4-17501B19279B}</Project>
<Name>SalesCatalog</Name> <Name>SalesCatalog</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\WorkFlowProvider\WorkFlowProvider.csproj">
<Project>{821FF72D-9F4B-4A2C-B95C-7B965291F119}</Project>
<Name>WorkFlowProvider</Name>
</ProjectReference>
<ProjectReference Include="..\WebControls\WebControls.csproj"> <ProjectReference Include="..\WebControls\WebControls.csproj">
<Project>{59E1DF7B-FFA0-4DEB-B5F3-76EBD98D5356}</Project> <Project>{59E1DF7B-FFA0-4DEB-B5F3-76EBD98D5356}</Project>
<Name>WebControls</Name> <Name>WebControls</Name>
@ -276,5 +287,9 @@
<Project>{68F5B80A-616E-4C3C-91A0-828AA40000BD}</Project> <Project>{68F5B80A-616E-4C3C-91A0-828AA40000BD}</Project>
<Name>YavscModel</Name> <Name>YavscModel</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\WorkFlowProvider\NpgsqlWorkflow.csproj">
<Project>{821FF72D-9F4B-4A2C-B95C-7B965291F119}</Project>
<Name>NpgsqlWorkflow</Name>
</ProjectReference>
</ItemGroup> </ItemGroup>
</Project> </Project>

@ -0,0 +1,167 @@
\documentclass[french,11pt]{article}
\usepackage{babel}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[a4paper]{geometry}
\usepackage{units}
\usepackage{bera}
\usepackage{graphicx}
\usepackage{fancyhdr}
\usepackage{fp}
\def\TVA{20} % Taux de la TVA
\def\TotalHT{0}
\def\TotalTVA{0}
\newcommand{\AjouterService}[2]{% Arguments : Désignation, prix
\FPround{\montant}{#2}{2}
\FPadd{\TotalHT}{\TotalHT}{\montant}
\eaddto\ListeProduits{#1 & \montant \cr}
}
\newcommand{\AfficheResultat}{%
\ListeProduits
\FPeval{\TotalTVA}{\TotalHT * \TVA / 100}
\FPadd{\TotalTTC}{\TotalHT}{\TotalTVA}
\FPround{\TotalHT}{\TotalHT}{2}
\FPround{\TotalTVA}{\TotalTVA}{2}
\FPround{\TotalTTC}{\TotalTTC}{2}
\global\let\TotalHT\TotalHT
\global\let\TotalTVA\TotalTVA
\global\let\TotalTTC\TotalTTC
\cr
\hline
\textbf{Total} & & & \TotalHT
}
\newcommand*\eaddto[2]{% version développée de \addto
\edef\tmp{#2}%
\expandafter\addto
\expandafter#1%
\expandafter{\tmp}%
}
\newcommand{\ListeProduits}{}
%%%%%%%%%%%%%%%%%%%%% A MODIFIER DANS LA FACTURE %%%%%%%%%%%%%%%%%%%%%
\def\FactureNum {<none>} % Numéro de facture
\def\FactureAcquittee {non} % Facture acquittée : oui/non
\def\FactureLieu {Suresnes} % Lieu de l'édition de la facture
\def\FactureObjet {Facture} % Objet du document
% Description de la facture
\def\FactureDescr {%
Cette facture concerne la prestation de coiffure a domicile du Mardi 23 Septembre 2014 à Meudon, 6 rue de la Verrerie.
}
% Infos Client
\def\ClientNom{M. Dupont} % Nom du client
\def\ClientAdresse{% % Adresse du client
Zenosphere : Anthony Courtois (DG)\\
6 rue de la Verrerie\\
92190 MEUDON\\
Mobile: 06 47 60 25 50
}
% Liste des produits facturés : Désignation, prix
\AjouterService {Forfait Coiffure} {75}
%\AjouterService {Frais de déplacement} {0.84}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\geometry{verbose,tmargin=4em,bmargin=8em,lmargin=6em,rmargin=6em}
\setlength{\parindent}{0pt}
\setlength{\parskip}{1ex plus 0.5ex minus 0.2ex}
\thispagestyle{fancy}
\pagestyle{fancy}
\setlength{\parindent}{0pt}
\renewcommand{\headrulewidth}{0pt}
\cfoot{
Soraya Coiffure - 2 boulevard Aristide Briand - 92150 SURESNES \newline
\small{
E-mail: soraya.boudjouraf@free.fr\\
Téléphone mobile: +33(0)6 37 57 42 74\\
Téléphone fixe: +33(0)9 80 90 36 42
}
}
\begin{document}
% Logo de la société
%\includegraphics{logo.jpg}
% Nom et adresse de la société
Soraya Schneider\\
2 boulevard Aristide Briand\\
Bat V\\
92150 SURESNES\\
Facture n°\FactureNum
{\addtolength{\leftskip}{10.5cm} %in ERT
\textbf{\ClientNom} \\
\ClientAdresse \\
} %in ERT
\hspace*{10.5cm}
\FactureLieu, le \today
~\\~\\
\textbf{Objet : \FactureObjet \\}
\textnormal{\FactureDescr}
~\\
\begin{center}
\begin{tabular}{lrrr}
\textbf{Désignation ~~~~~~} & \textbf{Montant (EUR)} \\
\hline
\AfficheResultat{}
\end{tabular}
\end{center}
\begin{flushright}
\textit{Auto entreprise en franchise de TVA}\\
\end{flushright}
~\\
\ifthenelse{\equal{\FactureAcquittee}{oui}}{
Facture acquittée.
}{
À régler par chèque ou par virement bancaire :
\begin{center}
\begin{tabular}{|c c c c|}
\hline \textbf{Code banque} & \textbf{Code guichet} & \textbf{N° de Compte} & \textbf{Clé RIB} \\
20041 & 00001 & 1225647F020 & 05 \\
\hline \textbf{IBAN N°} & \multicolumn{3}{|l|}{ FR 91 20041 00001 1225647F020 05 } \\
\hline \textbf{Code BIC} & \multicolumn{3}{|l|}{ PSSTFRPPPAR } \\
\hline
\end{tabular}
\end{center}
}
\end{document}

@ -0,0 +1,188 @@
<#@ template language="C#" #>
<#@ output extension=".tex" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="$(SolutionDir)/web/bin/YavscModel.dll" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="Yavsc.Model.WorkFlow" #>
<#@ import namespace="Yavsc.Model.RolesAndMembers" #>
<#@ parameter type="Estimate" name="estim" #>
<#@ parameter type="Profile" name="from" #>
<#@ parameter type="Profile" name="to" #>
\documentclass[french,11pt]{article}
\usepackage{babel}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[a4paper]{geometry}
\usepackage{units}
\usepackage{bera}
\usepackage{graphicx}
\usepackage{fancyhdr}
\usepackage{fp}
\def\TVA{20} % Taux de la TVA
\def\TotalHT{0}
\def\TotalTVA{0}
\newcommand{\AjouterService}[2]{% Arguments : Désignation, prix
\FPround{\montant}{#2}{2}
\FPadd{\TotalHT}{\TotalHT}{\montant}
\eaddto\ListeProduits{#1 & \montant \cr}
}
\newcommand{\AfficheResultat}{%
\ListeProduits
\FPeval{\TotalTVA}{\TotalHT * \TVA / 100}
\FPadd{\TotalTTC}{\TotalHT}{\TotalTVA}
\FPround{\TotalHT}{\TotalHT}{2}
\FPround{\TotalTVA}{\TotalTVA}{2}
\FPround{\TotalTTC}{\TotalTTC}{2}
\global\let\TotalHT\TotalHT
\global\let\TotalTVA\TotalTVA
\global\let\TotalTTC\TotalTTC
\cr
\hline
\textbf{Total} & & & \TotalHT
}
\newcommand*\eaddto[2]{% version développée de \addto
\edef\tmp{#2}%
\expandafter\addto
\expandafter#1%
\expandafter{\tmp}%
}
\newcommand{\ListeProduits}{}
%%%%%%%%%%%%%%%%%%%%% A MODIFIER DANS LA FACTURE %%%%%%%%%%%%%%%%%%%%%
\def\FactureNum {<#= estim.Id.ToString() #>} % Numéro de facture
\def\FactureAcquittee {non} % Facture acquittée : oui/non
\def\FactureLieu {<#= from.CityAndState #>} % Lieu de l'édition de la facture
\def\FactureObjet {Facture} % Objet du document
% Description de la facture
\def\FactureDescr {%
<#= estim.Title #>
}
% Infos Client
\def\ClientNom{<#= to.Name #>} % Nom du client
\def\ClientAdresse{% % Adresse du client
<#= to.Address #>\\
<#= to.ZipCode #> <#= to.CityAndState #>\\
<# if (!string.IsNullOrWhiteSpace(to.Phone)) { #>
Téléphone fixe: <#= to.Phone #>\\
<# } #>
<# if (!string.IsNullOrWhiteSpace(to.Mobile)) { #>
Mobile: <#= to.Mobile #>\\
<# } #>
E-mail: <#= to.Email #>
}
% Liste des produits facturés : Désignation, prix
<# foreach (Writting wr in estim.Lines) { #>
\AjouterService {<#=wr.Description#> <# if (!string.IsNullOrWhiteSpace(wr.ProductReference)) { #>
(<#=wr.ProductReference#>)<# } #>} {<#=wr.UnitaryCost*wr.Count#>}
<# } #>
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\geometry{verbose,tmargin=4em,bmargin=8em,lmargin=6em,rmargin=6em}
\setlength{\parindent}{0pt}
\setlength{\parskip}{1ex plus 0.5ex minus 0.2ex}
\thispagestyle{fancy}
\pagestyle{fancy}
\setlength{\parindent}{0pt}
\renewcommand{\headrulewidth}{0pt}
\cfoot{
<#=from.Name#> - <#=from.Address #> - <#= from.CityAndState #> \newline
\small{
E-mail: <#= from.Email #>
<# if (!string.IsNullOrWhiteSpace(from.Mobile)) { #> - Téléphone mobile: <#= from.Mobile #><# } #>
<# if (!string.IsNullOrWhiteSpace(from.Phone)) { #> - Téléphone fixe: <#= from.Phone #><# } #>
}
}
\begin{document}
% Logo de la société
%\includegraphics{logo.jpg}
% Nom et adresse de la société
<#= from.Name #>\\
<#= from.Address #>\\
<#=from.ZipCode #> <#=from.CityAndState#>\\
Facture n°\FactureNum
{\addtolength{\leftskip}{10.5cm} %in ERT
\textbf{\ClientNom} \\
\ClientAdresse \\
} %in ERT
\hspace*{10.5cm}
\FactureLieu, le \today
~\\~\\
\textbf{Objet : \FactureObjet \\}
\textnormal{\FactureDescr}
~\\
\begin{center}
\begin{tabular}{lrrr}
\textbf{Désignation ~~~~~~} & \textbf{Montant (EUR)} \\
\hline
\AfficheResultat{}
\end{tabular}
\end{center}
\begin{flushright}
\textit{Auto entreprise en franchise de TVA}\\
\end{flushright}
~\\
\ifthenelse{\equal{\FactureAcquittee}{oui}}{
Facture acquittée.
}{
À régler par chèque ou par virement bancaire :
\begin{center}
\begin{tabular}{|c c c c|}
\hline \textbf{Code banque} & \textbf{Code guichet} & \textbf{N° de Compte} & \textbf{Clé RIB} \\
<#= from.BankCode #> & <#= from.WicketCode #> & <#=from.AccountNumber #> & <#=from.BankedKey#> \\
\hline \textbf{IBAN N°} & \multicolumn{3}{|l|}{ <#= from.IBAN #> } \\
\hline \textbf{Code BIC} & \multicolumn{3}{|l|}{ <#= from.BIC #> } \\
\hline
\end{tabular}
\end{center}
}
\end{document}

@ -0,0 +1,33 @@
//
// TexEstimInit.cs
//
// Author:
// Paul Schneider <paulschneider@free.fr>
//
// Copyright (c) 2014 Paul Schneider
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
namespace Yavsc.templates
{
public partial class Estim
{
public void Init ()
{
this.Initialize();
}
}
}

@ -2,63 +2,158 @@ using System;
using System.ComponentModel; using System.ComponentModel;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Web.Profile; using System.Web.Profile;
using System.Web.Security;
namespace Yavsc.Model.RolesAndMembers namespace Yavsc.Model.RolesAndMembers
{ {
public class Profile public class Profile
{ {
[DisplayName("Adresse")] [DisplayName ("Nom complet")]
[StringLength(2047)] [StringLength (1024)]
public string Name { get; set; }
[DisplayName ("Adresse")]
[StringLength (2047)]
public string Address { get; set; } public string Address { get; set; }
[DisplayName("Ville")] [DisplayName ("Ville")]
[StringLength(255)] [StringLength (255)]
public string CityAndState { get; set; } public string CityAndState { get; set; }
[DisplayName("Code Postal")] [DisplayName ("Code Postal")]
[StringLength(9)] [StringLength (9)]
public string ZipCode { get; set; } public string ZipCode { get; set; }
[DisplayName("Pays")] [DisplayName ("Pays")]
[StringLength(99)] [StringLength (99)]
public string Country { get; set; } public string Country { get; set; }
[DisplayName("Site Web")] [DisplayName ("Site Web")]
[StringLength(255)] [StringLength (255)]
public string WebSite { get; set; } public string WebSite { get; set; }
[DisplayName("Blog visible")] [DisplayName ("Blog visible")]
public bool BlogVisible { get; set; } public bool BlogVisible { get; set; }
[DisplayName("Titre du blog")] [DisplayName ("Titre du blog")]
[StringLength (255)]
public string BlogTitle { get; set; } public string BlogTitle { get; set; }
public Profile():base() [DisplayName ("Téléphone fixe")]
[StringLength (15)]
public string Phone { get; set; }
[DisplayName ("Portable")]
[StringLength (15)]
public string Mobile { get; set; }
[DisplayName ("E-mail")]
[StringLength (1024)]
public string Email { get; set; }
[DisplayName ("Code BIC")]
[StringLength (15)]
public string BIC { get; set; }
[DisplayName ("Code IBAN")]
[StringLength (33)]
public string IBAN { get; set; }
[DisplayName ("Code Banque")]
[StringLength (5)]
public string BankCode { get; set; }
[DisplayName ("Code Guichet")]
[StringLength (5)]
public string WicketCode { get; set; }
[DisplayName ("Numéro de compte")]
[StringLength (15)]
public string AccountNumber { get; set; }
[DisplayName ("Clé RIB")]
public int BankedKey { get; set; }
public bool IsBankable { get {
return IsBillable
&& !string.IsNullOrWhiteSpace (BankCode)
&& !string.IsNullOrWhiteSpace (BIC)
&& !string.IsNullOrWhiteSpace (IBAN)
&& !string.IsNullOrWhiteSpace (BankCode)
&& !string.IsNullOrWhiteSpace (WicketCode)
&& !string.IsNullOrWhiteSpace (AccountNumber)
&& BankedKey != 0; } }
public bool IsBillable {
get {
return !string.IsNullOrWhiteSpace (Name)
&& !string.IsNullOrWhiteSpace (Address)
&& !string.IsNullOrWhiteSpace (CityAndState)
&& !string.IsNullOrWhiteSpace (ZipCode)
&& !string.IsNullOrWhiteSpace (Email)
&& !(string.IsNullOrWhiteSpace (Phone) &&
string.IsNullOrWhiteSpace (Mobile));
}
}
public Profile () : base ()
{ {
} }
public Profile(ProfileBase profile) public Profile (ProfileBase profile)
{ {
object b = profile.GetPropertyValue ("BlogVisible"); object b = profile.GetPropertyValue ("BlogVisible");
BlogVisible = (b is DBNull) ? true : (bool)b; BlogVisible = (b == null) ? true : (bool)b;
object s = profile.GetPropertyValue ("BlogTitle");
BlogTitle = (s is DBNull) ? null : (string)s;
s = profile.GetPropertyValue ("Address");
Address = (s is DBNull) ? null : (string)s;
object s = profile.GetPropertyValue ("BlogTitle"); s = profile.GetPropertyValue ("CityAndState");
BlogTitle = (s is DBNull) ? null : (string)s; CityAndState = (s is DBNull) ? null : (string)s;
s = profile.GetPropertyValue ("Country");
Country = (s is DBNull) ? null : (string)s;
s = profile.GetPropertyValue ("ZipCode");
ZipCode = (s is DBNull) ? null : (string)s;
s = profile.GetPropertyValue("Address"); s = profile.GetPropertyValue ("WebSite");
Address = (s is DBNull)?null:(string)s; WebSite = (s is DBNull) ? null : (string)s;
s = profile.GetPropertyValue ("Name");
Name = (s is DBNull) ? null : (string)s;
s = profile.GetPropertyValue ("Phone");
Phone = (s is DBNull) ? null : (string)s;
s = profile.GetPropertyValue ("Mobile");
Mobile = (s is DBNull) ? null : (string)s;
MembershipUser u = Membership.GetUser (profile.UserName);
Email = u.Email;
s = profile.GetPropertyValue ("BankCode");
BankCode = (s is DBNull) ? null : (string)s;
s = profile.GetPropertyValue ("IBAN");
IBAN = (s is DBNull) ? null : (string)s;
s = profile.GetPropertyValue ("BIC");
BIC = (s is DBNull) ? null : (string)s;
s = profile.GetPropertyValue ("WicketCode");
WicketCode = (s is DBNull) ? null : (string)s;
s = profile.GetPropertyValue("CityAndState"); s = profile.GetPropertyValue ("AccountNumber");
CityAndState = (s is DBNull)?null:(string)s; this.AccountNumber = (s is DBNull) ? null : (string)s;
s = profile.GetPropertyValue("Country"); s = profile.GetPropertyValue ("BankedKey");
Country = (s is DBNull)?null:(string)s; BankedKey = (s == null) ? 0 : (int)s;
s = profile.GetPropertyValue("ZipCode");
ZipCode = (s is DBNull)?null:(string)s;
s = profile.GetPropertyValue ("WebSite");
WebSite = (s is DBNull) ? null : (string)s;
} }
} }
} }

@ -1,15 +1,30 @@
using System; using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
namespace Yavsc.Model.WorkFlow namespace Yavsc.Model.WorkFlow
{ {
public class Estimate [Serializable]
public class Estimate
{ {
public Estimate () public Estimate ()
{ {
} }
[Required]
[DisplayName("Titre")]
public string Title { get; set; } public string Title { get; set; }
public string Owner { get; set; } [Required]
[DisplayName("Description")]
public string Description { get; set; }
[Required]
[DisplayName("Responsable")]
public string Responsible { get; set; }
[Required]
[DisplayName("Client")]
public string Client { get; set; }
public long Id { get; set; } public long Id { get; set; }
[DisplayName("Chiffre")]
public decimal Ciffer { public decimal Ciffer {
get { get {
decimal total = 0; decimal total = 0;
@ -20,6 +35,7 @@ namespace Yavsc.Model.WorkFlow
return total; return total;
} }
} }
public Writting[] Lines { get; set; } public Writting[] Lines { get; set; }
} }
} }

@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
namespace Yavsc.Model.WorkFlow
{
public interface IContent
{
object Data { get; set; }
string MimeType { get; set; }
}
}

@ -42,7 +42,7 @@ namespace Yavsc.Model.WorkFlow
/// <returns>The estimate.</returns> /// <returns>The estimate.</returns>
/// <param name="client">Client.</param> /// <param name="client">Client.</param>
/// <param name="title">Title.</param> /// <param name="title">Title.</param>
long CreateEstimate (string client, string title); Estimate CreateEstimate (string responsible, string client, string title, string description);
/// <summary> /// <summary>
/// Add a line to the specified estimate by id, /// Add a line to the specified estimate by id,
/// using the specified desc, ucost, count and productid. /// using the specified desc, ucost, count and productid.
@ -97,13 +97,7 @@ namespace Yavsc.Model.WorkFlow
/// </summary> /// </summary>
/// <param name="estid">Estid.</param> /// <param name="estid">Estid.</param>
/// <param name="newTitle">New title.</param> /// <param name="newTitle">New title.</param>
void SetTitle (long estid, string newTitle); void UpdateEstimate (Estimate estim);
/// <summary>
/// Sets the descripton for a writting.
/// </summary>
/// <param name="writid">Writid.</param>
/// <param name="newDesc">New desc.</param>
void SetDesc (long writid, string newDesc);
/// <summary> /// <summary>
/// Sets the writting status. /// Sets the writting status.
/// </summary> /// </summary>

@ -8,19 +8,11 @@ namespace Yavsc.Model.WorkFlow
{ {
public class NewEstimateEvenArgs: EventArgs public class NewEstimateEvenArgs: EventArgs
{ {
private string clientName; private Estimate data=null;
private string estimateTitle; public Estimate Data{ get { return data; } }
private long eid; public NewEstimateEvenArgs(Estimate created)
public string ClientName{ get { return clientName; } }
public string EstimateTitle { get { return estimateTitle; } }
public long EstimateId { get { return eid; } }
public NewEstimateEvenArgs(long estid, string client, string title)
{ {
clientName = client; data = created;
estimateTitle = title;
eid = estid;
} }
} }

@ -17,9 +17,9 @@ namespace Yavsc.Model.WorkFlow
public static Catalog Catalog { get; set; } public static Catalog Catalog { get; set; }
public static void SetTitle (long id, string title) public static void UpdateEstimate (Estimate estim)
{ {
ContentProvider.SetTitle (id, title); ContentProvider.UpdateEstimate (estim);
} }
public static event EventHandler NewOrder; public static event EventHandler NewOrder;
@ -95,12 +95,13 @@ namespace Yavsc.Model.WorkFlow
/// </summary> /// </summary>
/// <returns>The estimate identifier.</returns> /// <returns>The estimate identifier.</returns>
/// <param name="title">Title.</param> /// <param name="title">Title.</param>
public static long CreateEstimate(string client, string title)
public static Estimate CreateEstimate(string responsible, string client, string title, string description)
{ {
long estid = ContentProvider.CreateEstimate (client, title); Estimate created = ContentProvider.CreateEstimate (responsible, client, title, description);
if (NewOrder != null) if (NewOrder != null)
NewOrder.Invoke(ContentProvider, new NewEstimateEvenArgs(estid,client,title)); NewOrder.Invoke(ContentProvider, new NewEstimateEvenArgs(created));
return estid; return created;
} }
public static long Write(long estid, string desc, decimal ucost, int count, string productid) public static long Write(long estid, string desc, decimal ucost, int count, string productid)

@ -7,6 +7,7 @@ namespace Yavsc.Model.WorkFlow
/// A Writting. /// A Writting.
/// Une ligne d'écriture dans un devis ou une facture /// Une ligne d'écriture dans un devis ou une facture
/// </summary> /// </summary>
[Serializable]
public class Writting public class Writting
{ {
/// <summary> /// <summary>

@ -35,6 +35,7 @@
<Reference Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> <Reference Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<Reference Include="System.Configuration" /> <Reference Include="System.Configuration" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Web.ApplicationServices" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
@ -53,7 +54,6 @@
<Compile Include="WorkFlow\Writting.cs" /> <Compile Include="WorkFlow\Writting.cs" />
<Compile Include="WorkFlow\Estimate.cs" /> <Compile Include="WorkFlow\Estimate.cs" />
<Compile Include="WorkFlow\WFOrder.cs" /> <Compile Include="WorkFlow\WFOrder.cs" />
<Compile Include="WorkFlow\IContent.cs" />
<Compile Include="WorkFlow\IContentProvider.cs" /> <Compile Include="WorkFlow\IContentProvider.cs" />
<Compile Include="WorkFlow\IWFModule.cs" /> <Compile Include="WorkFlow\IWFModule.cs" />
<Compile Include="WorkFlow\IWFOrder.cs" /> <Compile Include="WorkFlow\IWFOrder.cs" />

Loading…