DataUtils.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Reflection;
  6. using System.Windows.Forms;
  7. using Comal.Classes;
  8. using InABox.Clients;
  9. using InABox.Configuration;
  10. using InABox.Core;
  11. using InABox.Database;
  12. using InABox.Database.SQLite;
  13. using InABox.DynamicGrid;
  14. using InABox.WPF;
  15. using MessageBox = System.Windows.MessageBox;
  16. namespace PRSDesktop
  17. {
  18. public class Utility
  19. {
  20. //private void UpgradeShipmentLinks(Entity[] notifications)
  21. //{
  22. // int i = 1;
  23. // foreach (DeliveryNotification notification in notifications)
  24. // {
  25. // Progress.SetMessage(String.Format("Converting Delivery Notifications {0} / {1}", i, notifications.Length));
  26. // notification.ShipmentLink = new ShipmentLink();
  27. // if (notification.Shipment != null)
  28. // {
  29. // notification.ShipmentLink.ID = notification.Shipment.ID;
  30. // notification.Shipment = null;
  31. // }
  32. // i++;
  33. // }
  34. //}
  35. private static bool HasDocumentLinks<T>()
  36. {
  37. var props = typeof(T).GetProperties().Where(x =>
  38. x.PropertyType.Equals(typeof(DocumentLink)) || x.PropertyType.Equals(typeof(ImageDocumentLink)) ||
  39. x.PropertyType.Equals(typeof(PDFDocumentLink)));
  40. return props.Any();
  41. }
  42. private static Guid[] GetDocuments<T>(T entity)
  43. {
  44. var result = new List<Guid>();
  45. var props = typeof(T).GetProperties().Where(x =>
  46. x.PropertyType.Equals(typeof(DocumentLink)) || x.PropertyType.Equals(typeof(ImageDocumentLink)) ||
  47. x.PropertyType.Equals(typeof(PDFDocumentLink)));
  48. foreach (var prop in props)
  49. {
  50. var link = (IEntityLink)prop.GetValue(entity);
  51. if (link.IsValid())
  52. result.Add(link.ID);
  53. }
  54. return result.ToArray();
  55. }
  56. //private static bool CopyType<T>(int typeno, int typecount, IProvider source, IProvider target) where T : Entity, new()
  57. //{
  58. // String name = typeof(T).EntityName().Split('.').Last();
  59. // //if (!HasDocumentLinks<T>())
  60. // // return false;
  61. // Progress.SetMessage(String.Format("[{0}/{1}] {2}: Loading Source Items..", typeno, typecount, name));
  62. // var sourceitems = source.Load<T>();
  63. // Progress.SetMessage(String.Format("[{0}/{1}] {2}: Loading Target Items..", typeno, typecount, name));
  64. // var targetitems = target.Load<T>();
  65. // //if (sourceitems.Count() == targetitems.Count())
  66. // // return false;
  67. // //Progress.SetMessage(String.Format("[{0}/{1}] {2}: Deleting Target Items..", typeno, typecount, name));
  68. // //foreach (var targetitem in targetitems)
  69. // // target.Delete(targetitem);
  70. // for (int i=0; i<sourceitems.Length; i++)
  71. // {
  72. // Progress.SetMessage(String.Format("[{0}/{1}] {2}: Copying Items ({3:F2}% complete)..", typeno, typecount, name, (double)i * 100.0F / (double)sourceitems.Length));
  73. // var sourceitem = sourceitems[i];
  74. // if (ClientFactory.IsSupported<AuditTrail>())
  75. // {
  76. // var audits = source.Load<AuditTrail>(new Filter<AuditTrail>(x => x.EntityID).IsEqualTo(sourceitem.ID));
  77. // foreach (var audit in audits)
  78. // target.Save(audit);
  79. // }
  80. // if (sourceitem is IEntityDocument)
  81. // {
  82. // var entdoc = (IEntityDocument)sourceitem;
  83. // if (entdoc.DocumentLink.ID != Guid.Empty)
  84. // {
  85. // var doc = source.Load(new Filter<Document>(x => x.ID).IsEqualTo(entdoc.DocumentLink.ID)).FirstOrDefault();
  86. // if (doc != null)
  87. // target.Save(doc);
  88. // else
  89. // entdoc.DocumentLink.ID = Guid.Empty;
  90. // }
  91. // }
  92. // Guid[] docids = GetDocuments<T>(sourceitem);
  93. // foreach (var docid in docids)
  94. // {
  95. // var doc = source.Load(new Filter<Document>(x => x.ID).IsEqualTo(docid)).FirstOrDefault();
  96. // if (doc != null)
  97. // target.Save(doc);
  98. // }
  99. // target.Delete(sourceitem);
  100. // target.Save(sourceitem);
  101. // }
  102. // target.CommitTransaction();
  103. // return true;
  104. // #region oldcode
  105. // //open.Invoke(target, new object[] { "Duplicate", true });
  106. // ////if (items.Length != orig.Count)
  107. // //{
  108. // // Progress.SetMessage(string.Format("{0}/{1} {2}: Clearing..", t + 1, types.Count, type.Name));
  109. // // for (int i = 0; i < orig.Count; i++)
  110. // // {
  111. // // //Progress.SetMessage(string.Format("{0}/{1} {2}: Resetting ({3:F2}% complete)..", t + 1, types.Length, type.Name, (double)i * 100.0F / (double)orig.Count));
  112. // // delete.Invoke(target, new object[] { orig[i] });
  113. // // }
  114. // // Progress.SetMessage(string.Format("{0}/{1} {2}: Rebuilding..", t + 1, types.Count, type.Name));
  115. // // for (int i = 0; i < items.Count; i++)
  116. // // {
  117. // // //if (i > 10)
  118. // // // return;
  119. // // var item = items[i];
  120. // // //double progress = (double)i * 100.0F / (double)items.Length;
  121. // // ////Progress.SetMessage(string.Format("{0}/{1} {2}: Copying ({3:F2}% complete)..", t + 1, types.Length, type.Name, progress));
  122. // // //// Check and copy source document if required
  123. // // //if (item is IEntityDocument)
  124. // // //{
  125. // // // var entdoc = (IEntityDocument)item;
  126. // // // var doccli = new RemoteClient<Document>(URL, Port);
  127. // // // doccli.UserID = "FROGSOFTWARE";
  128. // // // doccli.Password = "FROGSOFTWARE";
  129. // // // //Progress.SetMessage(string.Format("{0}/{1} {2}: Copying (Documents)", t + 1, types.Length, type.Name));
  130. // // // var docfilter = new Filter<Document>(x => x.ID).IsEqualTo(entdoc.DocumentLink.ID);
  131. // // // var document = doccli.Load(docfilter).FirstOrDefault(); ;
  132. // // // if (document != null)
  133. // // // target.Save(document);
  134. // // //}
  135. // // //Progress.SetMessage(string.Format("{0}/{1} {2}: Copying ({3:F2}% complete).. (Saving)", t + 1, types.Length, type.Name, progress));
  136. // // save.Invoke(target, new object[] { item });
  137. // // //Dictionary<String, Object> values = item.GetValues(true);
  138. // // //var member = CoreUtils.GetMemberExpression(type, "ID");
  139. // // //var filter = Activator.CreateInstance(typeof(Filter<>).MakeGenericType(type));
  140. // // //CoreUtils.SetPropertyValue(filter, "Expression", member);
  141. // // //CoreUtils.SetPropertyValue(filter, "Operator", Operator.IsEqualTo);
  142. // // //CoreUtils.SetPropertyValue(filter, "Value", item.ID);
  143. // // //BaseObject[] compare = (BaseObject[])(load.Invoke(provider, new object[] { filter, null }));
  144. // // //BaseObject newitem = compare.FirstOrDefault();
  145. // // //if (newitem != null)
  146. // // //{
  147. // // // var changes = newitem.Compare(values);
  148. // // // if (changes.Any())
  149. // // // throw new Exception(String.Format("Object Values have changed!\n\n{0}", String.Join("\n", changes)));
  150. // // //}
  151. // // }
  152. // //}
  153. // //target.CommitTransaction();
  154. // //close.Invoke(target, new object[] { "Duplicate", true });
  155. // #endregion
  156. //}
  157. private static List<string> CompareType<T>(int typeno, int typecount, IProvider source, IProvider target) where T : Entity, new()
  158. {
  159. var result = new List<string>();
  160. var name = typeof(T).EntityName().Split('.').Last();
  161. Progress.SetMessage(string.Format("[{0}/{1}] {2}: Reloading Source Table..", typeno, typecount, name));
  162. //var items = local.Load();
  163. var sourcetable = source.Query<T>();
  164. Progress.SetMessage(string.Format("[{0}/{1}] {2}: Reloading Target Table..", typeno, typecount, name));
  165. var targettable = target.Query<T>();
  166. for (var i = 0; i < sourcetable.Rows.Count; i++)
  167. {
  168. Progress.SetMessage(string.Format("[{0}/{1}] {2}: Comparing Values ({3:F2}% complete)..", typeno, typecount, name,
  169. (double)i * 100.0F / sourcetable.Rows.Count));
  170. var sourcerow = sourcetable.Rows[i];
  171. var id = sourcerow.Get<Guid>("ID");
  172. var targetrow = targettable.Rows.FirstOrDefault(r => r.Get<Guid>("ID").Equals(id));
  173. if (targetrow == null)
  174. result.Add(string.Format("{0}: Row [{1}] is missing in target database", name, id));
  175. else
  176. foreach (var col in targettable.Columns)
  177. {
  178. var targetvalue = targetrow[col.ColumnName];
  179. var sourcevalue = sourcerow[col.ColumnName];
  180. if (targetvalue == null)
  181. {
  182. if (sourcevalue != null)
  183. result.Add(string.Format("{0}: Row [{1}].{2} is null in target, but [{3}] in source", name, id, col.ColumnName,
  184. sourcevalue));
  185. }
  186. else if (!targetvalue.Equals(sourcevalue))
  187. {
  188. result.Add(string.Format("{0}: Row [{1}].{2} is [{3}] in target, but [{4}] in source", name, id, col.ColumnName,
  189. targetvalue,
  190. sourcevalue));
  191. }
  192. }
  193. }
  194. return result;
  195. }
  196. private static void LoadType(Type type, List<Type> into, Type[] exclude)
  197. {
  198. if (exclude.Contains(type) || into.Contains(type))
  199. return;
  200. var props = type.GetProperties().Where(x => x.PropertyType.GetInterfaces().Contains(typeof(IEntityLink)));
  201. if (!props.Any())
  202. {
  203. into.Insert(0, type);
  204. }
  205. else
  206. {
  207. foreach (var prop in props)
  208. {
  209. var subtype = prop.PropertyType.BaseType.GetGenericArguments().First();
  210. if (subtype != type)
  211. LoadType(subtype, into, exclude);
  212. }
  213. into.Add(type);
  214. }
  215. }
  216. public static void DuplicateDatabase()
  217. {
  218. using (var ofd = new OpenFileDialog())
  219. {
  220. ofd.Filter = "SQLite Database Files (*.dbs)|*.dbs";
  221. ofd.DefaultExt = "dbs";
  222. ofd.InitialDirectory = Path.GetDirectoryName(DbFactory.Provider.URL);
  223. ofd.FileName = "";
  224. ofd.Multiselect = false;
  225. ofd.CheckFileExists = true;
  226. var result = ofd.ShowDialog();
  227. if (result != DialogResult.OK || string.IsNullOrWhiteSpace(ofd.FileName))
  228. return;
  229. BaseObject.GlobalObserving = false;
  230. IProvider source = new SQLiteProvider(ofd.FileName);
  231. Progress.Show("Opening Source Database");
  232. source.Types = DbFactory.Provider.Types;
  233. source.Start();
  234. try
  235. {
  236. var types = CoreUtils.TypeList(
  237. AppDomain.CurrentDomain.GetAssemblies(),
  238. x =>
  239. x.IsClass
  240. && !x.IsGenericType
  241. && x.IsSubclassOf(typeof(Entity))
  242. && !x.Equals(typeof(AuditTrail))
  243. && x.Equals(typeof(Setout))
  244. && x.GetInterfaces().Contains(typeof(IRemotable))
  245. );
  246. var orderedtypes = new List<Type>();
  247. foreach (var type in types)
  248. LoadType(type, orderedtypes,
  249. new[] { typeof(Document), /* typeof(Comal.Classes.Calendar), */ typeof(Email), typeof(GPSTrackerLocation) });
  250. var results = new List<string>();
  251. orderedtypes = orderedtypes.Where(x => x.Equals(typeof(Setout))).ToList();
  252. for (var i = 0; i < orderedtypes.Count; i++)
  253. {
  254. var type = orderedtypes[i];
  255. var copy = typeof(Utility).GetMethod("CopyType", BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(type);
  256. var copied = (bool)copy.Invoke(null, new object[] { i, orderedtypes.Count, source, DbFactory.Provider });
  257. if (copied)
  258. {
  259. var compare = typeof(Utility).GetMethod("CompareType", BindingFlags.Static | BindingFlags.NonPublic)
  260. .MakeGenericMethod(type);
  261. compare.Invoke(null, new object[] { i, orderedtypes.Count, source, DbFactory.Provider });
  262. }
  263. }
  264. File.WriteAllText("compare.text", string.Join("\n", results));
  265. Progress.Close();
  266. MessageBox.Show("All Done");
  267. }
  268. catch (Exception e)
  269. {
  270. Progress.Close();
  271. MessageBox.Show("Import Failed!\n\n" + e.Message + "\n\n" + e.StackTrace);
  272. }
  273. BaseObject.GlobalObserving = true;
  274. }
  275. }
  276. private static void EmptyStores(params Type[] entities)
  277. {
  278. foreach (var entity in entities)
  279. {
  280. var client = ClientFactory.CreateClient(entity);
  281. try
  282. {
  283. var items = client.Load();
  284. if (items != null)
  285. foreach (var item in items)
  286. client.Delete(item, "Emptying Store");
  287. }
  288. catch (Exception e)
  289. {
  290. throw new Exception(string.Format("{1}\nType: {0}", entity.Name, e.Message));
  291. }
  292. }
  293. }
  294. private static void EmptyStores()
  295. {
  296. var entities = CoreUtils.TypeList(
  297. new[]
  298. {
  299. typeof(Setout).Assembly
  300. },
  301. myType =>
  302. myType.IsClass
  303. && !myType.IsAbstract
  304. && !myType.IsGenericType
  305. && myType.IsSubclassOf(typeof(Entity))
  306. && myType.GetInterfaces().Contains(typeof(IPersistent))
  307. ).ToArray();
  308. EmptyStores(entities);
  309. }
  310. public static string[] ProcessNotes(string[] notes, string description)
  311. {
  312. var Notes = notes != null ? notes.ToList() : new List<string>();
  313. if (!string.IsNullOrWhiteSpace(description) && !description.Equals("Enter Description of Task Here"))
  314. {
  315. var bFound = false;
  316. for (var i = 0; i < Notes.Count; i++)
  317. if (!string.IsNullOrWhiteSpace(Notes[i]) && Notes[i].Contains(description))
  318. {
  319. Notes[i] = description;
  320. bFound = true;
  321. }
  322. if (!bFound)
  323. Notes.Insert(0, description);
  324. }
  325. return Notes.Select(x => CoreUtils.StripHTML(x)).ToArray();
  326. }
  327. public static void SetupColumns()
  328. {
  329. var usercolumns = new DynamicGridColumns
  330. {
  331. new() { ColumnName = "UserID", Width = 0, Caption = "User ID" },
  332. new() { ColumnName = "Password", Width = 0, Caption = "Password" }
  333. };
  334. new GlobalConfiguration<DynamicGridColumns>(typeof(User).Name).Save(usercolumns);
  335. var empcolumns = new DynamicGridColumns
  336. {
  337. new() { ColumnName = "Code", Width = 200, Caption = "Code" },
  338. new() { ColumnName = "Name", Width = 0, Caption = "Name" },
  339. new() { ColumnName = "CanAllocateTasks", Width = 40, Caption = "Tasks?" },
  340. new() { ColumnName = "PayrollID", Width = 200, Caption = "Payroll ID" }
  341. };
  342. new GlobalConfiguration<DynamicGridColumns>(typeof(Employee).Name).Save(empcolumns);
  343. var jobcolumns = new DynamicGridColumns
  344. {
  345. new() { ColumnName = "Number", Width = 50, Caption = " Job #", /* Type = typeof(int), */ Alignment = Alignment.MiddleCenter },
  346. new() { ColumnName = "Name", Width = 0, Caption = " Name" /* , Type = typeof(String) */ }
  347. };
  348. new GlobalConfiguration<DynamicGridColumns>(typeof(Job).Name).Save(jobcolumns);
  349. var setoutcolumns = new DynamicGridColumns
  350. {
  351. new() { ColumnName = "Number", Width = 80 /* , Type = typeof(String) */ },
  352. new() { ColumnName = "Title", Width = 200 /* , Type = typeof(String) */ },
  353. new() { ColumnName = "Description", Width = 0 /* , Type = typeof(String) */ },
  354. new() { ColumnName = "Quantity", Width = 50, /* Type=typeof(int), */ Caption = "Qty", Alignment = Alignment.MiddleCenter },
  355. new() { ColumnName = "Status", Width = 0 /* , Type = typeof(String) */ },
  356. new() { ColumnName = "DueDate", Width = 60, /* Type = typeof(DateTime), */ Format = "dd/MM/yy", Alignment = Alignment.MiddleCenter },
  357. new()
  358. {
  359. ColumnName = "Forecast.ManufacturingDate", Width = 60, /* Type = typeof(DateTime), */ Caption = "Est Date", Format = "dd/MM/yy",
  360. Alignment = Alignment.MiddleCenter
  361. }
  362. };
  363. new GlobalConfiguration<DynamicGridColumns>(typeof(Setout).Name).Save(setoutcolumns);
  364. var deliverycolumns = new DynamicGridColumns
  365. {
  366. new() { ColumnName = "Barcode", Width = 100 /* , Type = typeof(String) */ },
  367. new() { ColumnName = "Setout.Job.Name", Width = 200 /* , Type = typeof(String) */ },
  368. new() { ColumnName = "Title", Width = 0 /* , Type = typeof(String) */ },
  369. new() { ColumnName = "Setout.Quantity", Width = 50, /* Type=typeof(int), */ Caption = "Qty", Alignment = Alignment.MiddleCenter },
  370. new() { ColumnName = "Setout.Description", Width = 0 /* , Type = typeof(String) */ },
  371. new()
  372. {
  373. ColumnName = "DueDate", Width = 60, /* Type = typeof(DateTime), */ Caption = "Due Date", Format = "dd/MM/yy",
  374. Alignment = Alignment.MiddleCenter
  375. },
  376. new()
  377. {
  378. ColumnName = "Setout.Forecast.ManufacturingDate", Width = 60, /* Type = typeof(DateTime), */ Caption = "Est Date",
  379. Format = "dd/MM/yy", Alignment = Alignment.MiddleCenter
  380. },
  381. new()
  382. {
  383. ColumnName = "ManufacturedDate", Width = 60, /* Type = typeof(DateTime), */ Caption = "Ready", Format = "dd/MM/yy",
  384. Alignment = Alignment.MiddleCenter
  385. },
  386. new() { ColumnName = "Setout.Status", Width = 150 /* , Type = typeof(String) */ }
  387. };
  388. new GlobalConfiguration<DynamicGridColumns>(typeof(DeliveryItem).Name).Save(deliverycolumns);
  389. var shipmentcolumns = new DynamicGridColumns
  390. {
  391. new() { ColumnName = "Code", Width = 80, /* Type = typeof(String), */ Alignment = Alignment.MiddleCenter },
  392. new() { ColumnName = "Description", Width = 0 /* , Type = typeof(String) */ }
  393. };
  394. new GlobalConfiguration<DynamicGridColumns>(typeof(Shipment).Name).Save(shipmentcolumns);
  395. var employeecolumns = new DynamicGridColumns
  396. {
  397. new() { ColumnName = "Code", Width = 120 /* , Type = typeof(String) */ },
  398. new() { ColumnName = "Name", Width = 0 /* , Type = typeof(String) */ },
  399. new() { ColumnName = "Address.Street", Width = 0 /* , Type = typeof(String) */ },
  400. new() { ColumnName = "Address.City", Width = 150 /* , Type = typeof(String) */ },
  401. new() { ColumnName = "Type.Name", Width = 120 /* , Type = typeof(String) */ },
  402. new()
  403. {
  404. ColumnName = "StartDate", Width = 60, /* Type = typeof(DateTime), */ Caption = "Started", Format = "dd/MM/yy",
  405. Alignment = Alignment.MiddleCenter
  406. },
  407. new()
  408. {
  409. ColumnName = "FinishDate", Width = 60, /* Type = typeof(DateTime), */ Caption = "Finished", Format = "dd/MM/yy",
  410. Alignment = Alignment.MiddleCenter
  411. }
  412. };
  413. new GlobalConfiguration<DynamicGridColumns>(typeof(Employee).Name).Save(employeecolumns);
  414. var customercolumns = new DynamicGridColumns
  415. {
  416. new() { ColumnName = "Code", Width = 200 /* , Type = typeof(String) */ },
  417. new() { ColumnName = "Name", Width = 0 /* , Type = typeof(String) */ },
  418. new() { ColumnName = "Delivery.Street", Width = 0 /* , Type = typeof(String) */ },
  419. new() { ColumnName = "Delivery.City", Width = 150 /* , Type = typeof(String) */ }
  420. };
  421. new GlobalConfiguration<DynamicGridColumns>(typeof(Customer).Name).Save(customercolumns);
  422. var gpstrackercolumns = new DynamicGridColumns
  423. {
  424. new() { ColumnName = "DeviceID", Width = 200 /* , Type = typeof(String) */ },
  425. new() { ColumnName = "Description", Width = 0 /* , Type = typeof(String) */ },
  426. new()
  427. {
  428. ColumnName = "Location.Latitude", Width = 100, /* Type = typeof(double), */ Caption = "Latitude", Format = "F6",
  429. Alignment = Alignment.MiddleCenter
  430. },
  431. new()
  432. {
  433. ColumnName = "Location.Longitude", Width = 100, /* Type = typeof(double), */ Caption = "Longitude", Format = "F6",
  434. Alignment = Alignment.MiddleCenter
  435. },
  436. new()
  437. {
  438. ColumnName = "Location.Timestamp", Width = 100, /* Type = typeof(DateTime), */ Caption = "Last Update",
  439. Format = "dd/MM/yy HH:mm",
  440. Alignment = Alignment.MiddleCenter
  441. }
  442. };
  443. new GlobalConfiguration<DynamicGridColumns>(typeof(GPSTracker).Name).Save(gpstrackercolumns);
  444. }
  445. public static void CalculateInvoice(Invoice invoice, bool Summarise)
  446. {
  447. double fEx = 0.00f;
  448. double fTax = 0.00f;
  449. double fInc = 0.00f;
  450. var oldlines = new Client<InvoiceLine>().Load(new Filter<InvoiceLine>(x => x.InvoiceLink.ID).IsEqualTo(invoice.ID));
  451. foreach (var oldline in oldlines)
  452. {
  453. new Client<InvoiceLine>().Delete(oldline, "Recalculating Invoice from Time and Materials");
  454. fEx += oldline.ExTax;
  455. fTax += oldline.Tax;
  456. fInc += oldline.IncTax;
  457. }
  458. if (invoice.ExTax != 0.00 || invoice.Tax != 0.00 || invoice.IncTax != 0.00)
  459. {
  460. invoice.ExTax = 0.00;
  461. invoice.Tax = 0.00;
  462. invoice.IncTax = 0.00F;
  463. new Client<Invoice>().Save(invoice, "Adjusting Invoice Total back to zero");
  464. }
  465. var timelines = new Dictionary<Guid, InvoiceLine>();
  466. var activities = new Client<Activity>().Load();
  467. var customerrates =
  468. new Client<CustomerActivity>().Load(new Filter<CustomerActivity>(x => x.CustomerLink.ID).IsEqualTo(invoice.CustomerLink.ID));
  469. foreach (var customerrate in customerrates)
  470. {
  471. var activity = activities.FirstOrDefault(x => x.ID.Equals(customerrate.ActivityLink.ID));
  472. if (activity != null)
  473. activity.ChargeRate = customerrate.ChargeRate;
  474. }
  475. var timesheets = new Client<TimeSheet>().Load(new Filter<TimeSheet>(x => x.InvoiceLink.ID).IsEqualTo(invoice.ID)).OrderBy(x => x.Date)
  476. .ToArray();
  477. foreach (var timesheet in timesheets)
  478. {
  479. var id = Summarise ? timesheet.ActivityLink.ID : timesheet.ID;
  480. var activity = activities.FirstOrDefault(x => x.ID.Equals(timesheet.ActivityLink.ID));
  481. var totalHours = Math.Round(timesheet.ApprovedDuration.TotalHours * 4.0F + 0.49F, 0, MidpointRounding.AwayFromZero) / 4.0F;
  482. var desc = Summarise
  483. ? activity != null ? activity.Description : "Unknown Activity"
  484. : string.Format("{0:dd MMM yy} - {1}", timesheet.Date, timesheet.Notes);
  485. if (!timelines.ContainsKey(id))
  486. {
  487. timelines[id] = new InvoiceLine();
  488. timelines[id].InvoiceLink.ID = invoice.ID;
  489. if (activity != null)
  490. {
  491. timelines[id].TaxCode.ID = activity.TaxCode.ID;
  492. timelines[id].TaxCode.Code = activity.TaxCode.Code;
  493. timelines[id].TaxCode.Description = activity.TaxCode.Description;
  494. timelines[id].TaxCode.Rate = activity.TaxCode.Rate;
  495. }
  496. }
  497. timelines[id].ExTax += totalHours * (activity != null ? activity.ChargeRate : 0.00F);
  498. timelines[id].Description = desc;
  499. }
  500. if (timelines.Any())
  501. new Client<InvoiceLine>().Save(timelines.Select(x => x.Value), "Recalculating Invoice from Time and Materials");
  502. var partlines = new Dictionary<Guid, InvoiceLine>();
  503. var costcentres = new Client<CostCentre>().Load();
  504. var items = new Client<DeliveryItem>().Load(new Filter<DeliveryItem>(x => x.InvoiceLink.ID).IsEqualTo(invoice.ID));
  505. foreach (var item in items)
  506. {
  507. var id = Summarise ? item.CostCentreLink.ID : item.ID;
  508. var costcentre = costcentres.FirstOrDefault(x => x.ID.Equals(item.CostCentreLink.ID));
  509. var desc = Summarise ? item.CostCentreLink.Description : item.Description;
  510. if (!partlines.ContainsKey(id))
  511. {
  512. partlines[id] = new InvoiceLine();
  513. partlines[id].InvoiceLink.ID = invoice.ID;
  514. if (costcentre != null)
  515. {
  516. timelines[id].TaxCode.ID = costcentre.TaxCode.ID;
  517. timelines[id].TaxCode.Code = costcentre.TaxCode.Code;
  518. timelines[id].TaxCode.Description = costcentre.TaxCode.Description;
  519. timelines[id].TaxCode.Rate = costcentre.TaxCode.Rate;
  520. }
  521. }
  522. partlines[id].Description = desc;
  523. partlines[id].ExTax += 0.00; // Need to implement chargeout here..
  524. }
  525. if (partlines.Any())
  526. new Client<InvoiceLine>().Save(partlines.Select(x => x.Value), "Recalculating Invoice from Time and Materials");
  527. }
  528. //public void InvoiceTimeSheets()
  529. //{
  530. // TimeSheet[] times = new Client<TimeSheet>().Load(
  531. // new Filter<TimeSheet>(x => x.Processed).IsEqualTo(DateTime.MinValue).And(x => x.Approved).IsNotEqualTo(DateTime.MinValue).And(x => x.InvoiceLink.ID).IsEqualTo(Guid.Empty).And(x => x.JobLink.ID).IsNotEqualTo(Guid.Empty)
  532. // );
  533. // List<Job> jobs = new List<Job>();
  534. // foreach (var time in times)
  535. // {
  536. // if (!jobs.Contains(time.JobLink.ID))
  537. // jobs.Add(time.JobLink.ID);
  538. // }
  539. // foreach (Guid jobid in jobs)
  540. // {
  541. // Invoice invoice = new Invoice();
  542. // invoice.JobLink.ID = jobid;
  543. // }
  544. //}
  545. }
  546. }