V6ProjectImport.xaml.cs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.Linq;
  5. using System.Threading.Tasks;
  6. using System.Windows;
  7. using System.Windows.Media.Imaging;
  8. using Comal.Classes;
  9. using InABox.Clients;
  10. using InABox.Core;
  11. using InABox.DynamicGrid;
  12. using InABox.Wpf;
  13. using InABox.WPF;
  14. using NPOI.OpenXmlFormats.Wordprocessing;
  15. namespace PRSDesktop;
  16. public class V6ProjectImportGrid : DynamicItemsListGrid<V6Quote>
  17. {
  18. private static BitmapImage Quotation => PRSDesktop.Resources.quotation.AsBitmapImage();
  19. private static BitmapImage Revision => PRSDesktop.Resources.revision.AsBitmapImage();
  20. public V6ProjectImportGrid()
  21. {
  22. ActionColumns.Add(new DynamicImageColumn(StatusImage) { Position = DynamicActionColumnPosition.Start});
  23. }
  24. private BitmapImage? StatusImage(CoreRow? row)
  25. {
  26. return row == null
  27. ? Quotation
  28. : string.IsNullOrWhiteSpace(row.Get<V6Quote, string>(x => x.Variation))
  29. ? Quotation
  30. : Revision;
  31. }
  32. protected override void DoReconfigure(DynamicGridOptions options)
  33. {
  34. base.DoReconfigure(options);
  35. options.FilterRows = true;
  36. options.HideDatabaseFilters = true;
  37. }
  38. }
  39. public partial class V6ProjectImport : Window
  40. {
  41. private readonly V6Client _client;
  42. public V6ProjectImport()
  43. {
  44. InitializeComponent();
  45. _client = new V6Client();
  46. ImportCosts.SelectedValue = _client.Settings.ImportCosts;
  47. ImportDesigns.SelectedValue = _client.Settings.ImportDesigns;
  48. if (_client.Connect())
  49. {
  50. Task<List<V6Quote>> v6Task = Task.Run(() =>
  51. {
  52. var _quotes = _client.IsConnected
  53. ? _client?.GetQuotes()?.ToList()
  54. : null;
  55. return _quotes ?? new List<V6Quote>();
  56. });
  57. Task<List<JobScope>> prsTask = Task.Run(() => Client.Query<JobScope>(null,
  58. Columns.None<JobScope>().Add(x => x.Job.ID).Add(x => x.Job.JobNumber).Add(x=>x.Job.SourceRef).Add(x=>x.Job.DefaultScope.ID).Add(x=>x.ID).Add(x=>x.Number).Add(x=>x.SourceRef)
  59. ).ToObjects<JobScope>().ToList());
  60. Task.WaitAll(v6Task,prsTask);
  61. var quotes = v6Task.Result;
  62. var scopes = prsTask.Result;
  63. Projects.Items = quotes
  64. .Where(q => string.IsNullOrWhiteSpace(q.Variation)
  65. ? !scopes.Any(x=>string.Equals(x.Job.DefaultScope.SourceRef, $"{q.Number}"))
  66. : !scopes.Any(x=> string.Equals(x.SourceRef,$"{q.Number}")))
  67. .ToList();
  68. }
  69. else
  70. {
  71. MessageWindow.ShowMessage("Cannot connect to V6!","Error");
  72. Projects.Items = new List<V6Quote>();
  73. }
  74. Projects.Refresh(true,true);
  75. }
  76. private void OK_Click(object sender, RoutedEventArgs e)
  77. {
  78. var _project = Projects.LoadItem(Projects.SelectedRows.First());
  79. var _importCosts = (V6ImportCosts)ImportCosts.SelectedValue;
  80. var _importDesigns = (V6ImportDesigns)ImportDesigns.SelectedValue;
  81. JobStatus? _statusCode = new();
  82. TaxCode? _taxCode = new();
  83. ProductDimensionUnit? _profileUom = new();
  84. ProductDimensionUnit? _componentUom = new();
  85. ProductDimensionUnit? _glassUom = new();
  86. ManufacturingTemplate? _template = new ManufacturingTemplate();
  87. ManufacturingTemplateStage[] _stages = [];
  88. MultiQuery query = new MultiQuery();
  89. query.Add(
  90. new Filter<JobStatus>(x=>x.Code).IsEqualTo(_client.Settings.JobStatus),
  91. Columns.All<JobStatus>().Add(x=>x.ID)
  92. );
  93. query.Add(
  94. new Filter<TaxCode>(x=>x.Code).IsEqualTo(_client.Settings.TaxCode),
  95. Columns.All<TaxCode>()
  96. );
  97. if (_importCosts != V6ImportCosts.None)
  98. {
  99. query.Add(
  100. new Filter<ProductDimensionUnit>(x => x.Code).InList(new string[]
  101. { _client.Settings.ProfileUom, _client.Settings.ComponentUom, _client.Settings.GlassUom }),
  102. Columns.All<ProductDimensionUnit>()
  103. );
  104. }
  105. if (_importDesigns == V6ImportDesigns.ToManufacturing)
  106. {
  107. query.Add(new Filter<ManufacturingTemplate>(x => x.Code).IsEqualTo(_client.Settings.PacketTemplate));
  108. query.Add(new Filter<ManufacturingTemplateStage>(x => x.Template.Code).IsEqualTo(_client.Settings.PacketTemplate));
  109. }
  110. query.Query();
  111. _statusCode = query.Get<JobStatus>().Rows.FirstOrDefault()?.ToObject<JobStatus>();
  112. if (_statusCode == null)
  113. {
  114. MessageWindow.ShowMessage(
  115. "Job Status setting has not been configured correctly!\nPlease correct this and try again.", "Error");
  116. return;
  117. }
  118. _taxCode = query.Get<TaxCode>().Rows.FirstOrDefault()?.ToObject<TaxCode>();
  119. if (_taxCode == null)
  120. {
  121. MessageWindow.ShowMessage(
  122. "Tax Code setting has not been configured correctly!\nPlease correct this and try again.", "Error");
  123. return;
  124. }
  125. if (_importDesigns == V6ImportDesigns.ToManufacturing)
  126. {
  127. _template = query.Get<ManufacturingTemplate>().Rows.FirstOrDefault()?.ToObject<ManufacturingTemplate>();
  128. _stages = query.Get<ManufacturingTemplateStage>().ToObjects<ManufacturingTemplateStage>().ToArray();
  129. }
  130. if (_importCosts != V6ImportCosts.None)
  131. {
  132. var _uoms = query.Get<ProductDimensionUnit>().ToObjects<ProductDimensionUnit>().ToList();
  133. _profileUom = _uoms.FirstOrDefault(x => string.Equals(x.Code, _client.Settings.ProfileUom));
  134. _componentUom = _uoms.FirstOrDefault(x => string.Equals(x.Code, _client.Settings.ComponentUom));
  135. _glassUom = _uoms.FirstOrDefault(x => string.Equals(x.Code, _client.Settings.GlassUom));
  136. }
  137. if (_profileUom == null)
  138. {
  139. MessageWindow.ShowMessage(
  140. "Profile UOM setting has not been configured correctly!\nPlease correct this and try again.", "Error");
  141. return;
  142. }
  143. if (_componentUom == null)
  144. {
  145. MessageWindow.ShowMessage(
  146. "Component UOM settings has not been configured correctly!\nPlease correct this and try again.", "Error");
  147. return;
  148. }
  149. if (_glassUom == null)
  150. {
  151. MessageWindow.ShowMessage(
  152. "Glass UOM setting has not been configured correctly!\nPlease correct this and try again.", "Error");
  153. return;
  154. }
  155. if (_template == null)
  156. {
  157. MessageWindow.ShowMessage(
  158. "Packet Template setting has not been configured correctly!\nPlease correct this and try again.", "Error");
  159. return;
  160. }
  161. List<string> _finishes = new();
  162. List<V6Profile> _profiles = new();
  163. List<V6Component> _components = new();
  164. List<V6Glass> _glass = new();
  165. List<V6Labour> _labour = new();
  166. List<ProductStyle> _styles = new();
  167. List<Product> _products = new();
  168. List<Activity> _activities = new();
  169. Dictionary<V6Elevation, V6Drawings> _designs = new();
  170. List<V6Profile> _missingProfiles = new();
  171. List<V6Component> _missingComponents = new();
  172. List<V6Glass> _missingGlass = new();
  173. List<V6Labour> _missingLabour = new();
  174. List<string> _missingFinishes = new();
  175. string exception = null;
  176. if (_importCosts != V6ImportCosts.None)
  177. {
  178. Progress.ShowModal("Checking Products", progress =>
  179. {
  180. try
  181. {
  182. progress.Report("Loading Profiles");
  183. _profiles = _client.GetProfiles(_project.Number, _project.Variation);
  184. }
  185. catch (Exception _exception)
  186. {
  187. exception = $"Error retrieving Profiles : {_exception.Message}";
  188. return;
  189. }
  190. try
  191. {
  192. progress.Report("Loading Components");
  193. _components = _client.GetComponents(_project.Number, _project.Variation);
  194. }
  195. catch (Exception _exception)
  196. {
  197. exception = $"Error retrieving Components : {_exception.Message}";
  198. return;
  199. }
  200. try
  201. {
  202. progress.Report("Loading Glass");
  203. _glass = _client.GetGlass(_project.Number, _project.Variation);
  204. }
  205. catch (Exception _exception)
  206. {
  207. exception = $"Error retrieving Glass : {_exception.Message}";
  208. return;
  209. }
  210. progress.Report("Checking PRS Codes");
  211. MultiQuery query = new MultiQuery();
  212. var _productStyles = _profiles.Select(x => x.Finish)
  213. .Union(_glass.Select(x => x.Treatment))
  214. .Distinct()
  215. .ToArray();
  216. query.Add(
  217. new Filter<ProductStyle>(x => x.Code).InList(_productStyles),
  218. Columns.None<ProductStyle>().Add(x => x.ID).Add(x => x.Code)
  219. );
  220. var _productcodes = _profiles.Select(x => x.Code)
  221. .Union(_components.Select(x => x.Code))
  222. .Union(_glass.Select(x => x.Code))
  223. .Distinct()
  224. .ToArray();
  225. query.Add(
  226. new Filter<Product>(x => x.Code).InList(_productcodes),
  227. Columns.None<Product>()
  228. .Add(x => x.ID)
  229. .Add(x => x.Code)
  230. .Add(x => x.Name)
  231. .Add(x => x.UnitOfMeasure.ID)
  232. .Add(x => x.UnitOfMeasure.Code)
  233. .Add(x => x.UnitOfMeasure.Description)
  234. .Add(x => x.UnitOfMeasure.HasQuantity)
  235. .Add(x => x.UnitOfMeasure.HasLength)
  236. .Add(x => x.UnitOfMeasure.HasWidth)
  237. .Add(x => x.UnitOfMeasure.HasHeight)
  238. .Add(x => x.UnitOfMeasure.Format)
  239. .Add(x => x.UnitOfMeasure.Formula)
  240. .Add(x => x.TaxCode.ID)
  241. .Add(x => x.TaxCode.Code)
  242. );
  243. query.Query();
  244. _styles = query.Get<ProductStyle>().ToObjects<ProductStyle>().ToList();
  245. _products = query.Get<Product>().ToObjects<Product>().ToList();
  246. _missingFinishes.AddRange(_productStyles.Where(c => !string.IsNullOrWhiteSpace(c) && !_styles.Any(p => string.Equals(p.Code, c))));
  247. var _missingCodes = _productcodes.Where(c => !_products.Any(p => string.Equals(p.Code, c))).ToArray();
  248. _missingProfiles.AddRange(_profiles.Where(x => _missingCodes.Contains(x.Code)));
  249. _missingComponents.AddRange(_components.Where(x => _missingCodes.Contains(x.Code)));
  250. _missingGlass.AddRange(_glass.Where(x => _missingCodes.Contains(x.Code)));
  251. });
  252. if (!string.IsNullOrWhiteSpace(exception))
  253. {
  254. MessageWindow.ShowMessage(exception,"V6 Error",PRSDesktop.Resources.warning.AsBitmapImage());
  255. return;
  256. }
  257. if (_missingProfiles.Any() || _missingComponents.Any() || _missingGlass.Any())
  258. {
  259. if (!MessageWindow.ShowYesNo(
  260. $"The following products do not exist in PRS\n" +
  261. $"- {string.Join("\n- ", _missingProfiles.Select(x => x.Code)
  262. .Union(_missingComponents.Select(x => x.Code))
  263. .Union(_missingGlass.Select(x => x.Code))
  264. .Distinct().OrderBy(x => x))}\n\n" +
  265. $"Do you wish to create them now?",
  266. "Create Missing Products"))
  267. return;
  268. }
  269. if (_missingFinishes.Any())
  270. {
  271. if (!MessageWindow.ShowYesNo(
  272. $"The following styles do not exist in PRS\n" +
  273. $"- {string.Join("\n- ", _missingFinishes
  274. .Distinct().OrderBy(x => x))}\n\n" +
  275. $"Do you wish to create them now?",
  276. "Create Missing Styles"))
  277. return;
  278. }
  279. Progress.ShowModal("Checking Labour", progress =>
  280. {
  281. progress.Report("Loading Labour");
  282. _labour = _client.GetLabour(_project.Number, _project.Variation);
  283. var _labourcodes = _labour.Select(x => x.Code).Distinct().ToArray();
  284. _activities = Client.Query(
  285. new Filter<Activity>(x => x.Code).InList(_labourcodes),
  286. Columns.None<Activity>()
  287. .Add(x => x.ID)
  288. .Add(x => x.Code)
  289. .Add(x => x.Description)
  290. ).ToObjects<Activity>().ToList();
  291. var _missingCodes = _labourcodes.Where(l => !_activities.Any(a => string.Equals(a.Code, l))).ToArray();
  292. _missingLabour.AddRange(_labour.Where(x => _missingCodes.Contains(x.Code)));
  293. });
  294. if (_missingLabour.Any())
  295. {
  296. if (!MessageWindow.ShowOKCancel(
  297. $"The following products do not exist in PRS\n" +
  298. $"- {string.Join("\n- ", _missingLabour.Select(x => x.Code).Distinct().OrderBy(x => x))}\n\n" +
  299. $"Do you wish to create them?",
  300. "Create Missing Activities"))
  301. return;
  302. }
  303. }
  304. List<String> designExceptions = new();
  305. if (_importDesigns != V6ImportDesigns.None)
  306. {
  307. List<V6Elevation> _designlist = new();
  308. Progress.ShowModal("Checking Designs", progress =>
  309. {
  310. try
  311. {
  312. _designlist = _client.GetItems(_project.Number, _project.Variation);
  313. }
  314. catch (Exception _exception)
  315. {
  316. designExceptions.Add($"Error retrieving designs : {_exception.Message}");
  317. return;
  318. }
  319. foreach (var _design in _designlist)
  320. {
  321. try
  322. {
  323. _designs[_design] = new V6Drawings();
  324. }
  325. catch (Exception _exception)
  326. {
  327. designExceptions.Add($"Error retrieving design [{_design.Description}]: {_exception.Message}");
  328. }
  329. }
  330. });
  331. }
  332. if (designExceptions.Any())
  333. {
  334. MessageWindow.ShowMessage(string.Join("\n",designExceptions),"V6 Error",PRSDesktop.Resources.warning.AsBitmapImage());
  335. return;
  336. }
  337. string createException = "";
  338. Progress.ShowModal("Creating Job", progress =>
  339. {
  340. try
  341. {
  342. var _scope = CreateJob(_project, _statusCode, _taxCode);
  343. if (_importCosts != V6ImportCosts.None)
  344. {
  345. CreateMissingStyles(_missingFinishes, _styles);
  346. CreateMissingProducts<V6Profile>(_profileUom, _taxCode, _missingProfiles, _products);
  347. CreateMissingProducts<V6Component>(_componentUom, _taxCode, _missingComponents, _products);
  348. CreateMissingProducts<V6Glass>(_glassUom, _taxCode, _missingGlass, _products);
  349. CreateMissingLabour(_missingLabour, _activities);
  350. progress.Report("Creating Bill of Materials");
  351. var bom = CreateBillofMaterials(_project, _scope,
  352. _profiles, _profileUom,
  353. _components, _componentUom,
  354. _glass, _glassUom,
  355. _products, _styles);
  356. if (_importCosts == V6ImportCosts.Requisitions)
  357. {
  358. // Convert BOM to Requisition
  359. }
  360. progress.Report("Creating Labour Budget");
  361. CreateActivities(_project, _scope, _labour, _activities);
  362. }
  363. if (_importDesigns != V6ImportDesigns.None)
  364. {
  365. progress.Report("Loading Drawings");
  366. foreach (var _key in _designs.Keys)
  367. {
  368. progress.Report($"Loading Drawing: {_key.Description}");
  369. _designs[_key] = _client.GetDrawings(_key.ID);
  370. }
  371. if (_importDesigns == V6ImportDesigns.ForApproval)
  372. CreateStagedSetouts(_project, _scope, _designs, _template, _stages);
  373. else
  374. CreateManufacturingPackets(_project, _scope, _designs, _template, _stages);
  375. }
  376. }
  377. catch (Exception _exception)
  378. {
  379. createException = $"Error Creating Job: {_exception.Message}\n{_exception.StackTrace}";
  380. }
  381. });
  382. if (!string.IsNullOrWhiteSpace(createException))
  383. {
  384. MessageWindow.ShowMessage(createException,"PRS Error",PRSDesktop.Resources.warning.AsBitmapImage());
  385. return;
  386. }
  387. List<String> _missing = new();
  388. _missing.AddRange(_missingLabour.Select(x => $"- Activity {x.Code}: {x.Description}").Distinct().OrderBy(x => x));
  389. _missing.AddRange(_missingFinishes.Select(x => $"- Style {x}").Distinct().OrderBy(x => x));
  390. _missing.AddRange(_missingProfiles.Select(x => $"- Product {x.Code}: {x.Description}")
  391. .Union(_missingComponents.Select(x => $"- Product {x.Code}: {x.Description}"))
  392. .Union(_missingGlass.Select(x => $"- Product {x.Code}: {x.Description}"))
  393. .Distinct()
  394. .OrderBy(x => x));
  395. if (_missing.Any())
  396. MessageWindow.ShowMessage($"The following items were auto-created and should be manually checked:\n{String.Join("\n",_missing)}","Results");
  397. DialogResult = true;
  398. }
  399. private static void CreateMissingLabour(List<V6Labour> missinglabour, List<Activity> activitylist)
  400. {
  401. List<Activity> _updates = new();
  402. foreach (var _missing in missinglabour)
  403. {
  404. if (!_updates.Any(x => String.Equals(x.Code, _missing.Code)))
  405. {
  406. var _activity = new Activity();
  407. _activity.Code = _missing.Code;
  408. _activity.Description = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(_missing.Code.ToLower());
  409. _activity.Problem = new ManagedProblem() { Notes = new string[] { "Created by V6 Import" } };
  410. _updates.Add(_activity);
  411. }
  412. }
  413. Client.Save(_updates, "Created by V6 Import");
  414. activitylist.AddRange(_updates);
  415. }
  416. private static void CreateMissingStyles( List<string> missingitems, List<ProductStyle> styleList)
  417. {
  418. List<ProductStyle> _updates = new();
  419. foreach (var _missingitem in missingitems)
  420. {
  421. if (!_updates.Any(x => String.Equals(x.Code, _missingitem)))
  422. {
  423. var _productstyle = new ProductStyle();
  424. _productstyle.Code = _missingitem;
  425. _productstyle.Description = _missingitem;
  426. _productstyle.Problem = new ManagedProblem() { Notes = new string[] { "Created by V6 Import" } };
  427. _updates.Add(_productstyle);
  428. }
  429. }
  430. Client.Save(_updates, "Created by V6 Import");
  431. styleList.AddRange(_updates);
  432. }
  433. private static void CreateMissingProducts<T>(ProductDimensionUnit uom, TaxCode tax, List<T> missingitems, List<Product> productlist) where T : V6BOMItem
  434. {
  435. List<Product> _updates = new();
  436. foreach (var _missingitem in missingitems)
  437. {
  438. if (!_updates.Any(x => String.Equals(x.Code, _missingitem.Code)))
  439. {
  440. var _product = new Product();
  441. _product.UnitOfMeasure.CopyFrom(uom);
  442. _product.Code = _missingitem.Code;
  443. _product.Name = _missingitem.Description;
  444. _product.Problem = new ManagedProblem() { Notes = new string[] { "Created by V6 Import" } };
  445. _product.TaxCode.CopyFrom(tax);
  446. _updates.Add(_product);
  447. }
  448. }
  449. Client.Save(_updates, "Created by V6 Import");
  450. productlist.AddRange(_updates);
  451. }
  452. private static JobScope CreateJob(V6Quote quote, JobStatus status, TaxCode tax)
  453. {
  454. var _jobno = $"V{quote.Number}";
  455. MultiQuery query = new MultiQuery();
  456. query.Add(
  457. new Filter<Job>(x=>x.JobNumber).IsEqualTo(_jobno),
  458. Columns.Required<Job>().Add(x=>x.DefaultScope.ID)
  459. );
  460. if (!string.IsNullOrWhiteSpace(quote.ClientID))
  461. {
  462. query.Add(
  463. new Filter<Customer>(x => x.Code).IsEqualTo(quote.ClientID),
  464. Columns.Required<Customer>()
  465. );
  466. }
  467. query.Query();
  468. var _scope = new JobScope();
  469. var _job = query.Get<Job>().ToObjects<Job>().FirstOrDefault();
  470. var _customer = !string.IsNullOrWhiteSpace(quote.ClientID)
  471. ? query.Get<Customer>().ToObjects<Customer>().FirstOrDefault()
  472. : null;
  473. if (_job == null)
  474. {
  475. if (!string.IsNullOrWhiteSpace(quote.ClientID) && _customer == null)
  476. {
  477. _customer = new Customer();
  478. _customer.Code = quote.ClientID;
  479. _customer.Name = quote.ClientName;
  480. _customer.Delivery.Street = quote.Street;
  481. _customer.Delivery.City = quote.City;
  482. _customer.Delivery.State = quote.State;
  483. _customer.Delivery.PostCode = quote.PostCode;
  484. Client.Save(_customer,"Imported From V6");
  485. }
  486. _job = new Job();
  487. _job.JobNumber = _jobno;
  488. _job.Name = quote.Title;
  489. _job.JobStatus.CopyFrom(status);
  490. if (_customer != null)
  491. {
  492. _job.Customer.CopyFrom(_customer);
  493. _job.Account.CopyFrom(_customer);
  494. }
  495. _job.SiteAddress.Street = quote.Street;
  496. _job.SiteAddress.City = quote.City;
  497. _job.SiteAddress.State = quote.State;
  498. _job.SiteAddress.PostCode = quote.PostCode;
  499. Client.Save(_job,"Imported From V6");
  500. _scope.ID = _job.DefaultScope.ID;
  501. _scope.CommitChanges();
  502. }
  503. _scope.Job.ID = _job.ID;
  504. _scope.Number = quote.Variation;
  505. _scope.SourceRef = $"{quote.ID}.{quote.Revision}";
  506. _scope.Description = string.IsNullOrWhiteSpace(quote.Variation)
  507. ? "Main Job"
  508. : quote.Title;
  509. _scope.ExTax = quote.SellPrice;
  510. _scope.TaxCode.CopyFrom(tax);
  511. _scope.Type = string.IsNullOrWhiteSpace(quote.Variation)
  512. ? JobScopeType.Contract
  513. : JobScopeType.Variation;
  514. Client.Save(_scope, "Imported From V6");
  515. return _scope;
  516. }
  517. private JobBillOfMaterials CreateBillofMaterials(V6Quote quote,
  518. JobScope scope,
  519. List<V6Profile> profiles, ProductDimensionUnit profileUOM,
  520. List<V6Component> components, ProductDimensionUnit componentUOM,
  521. List<V6Glass> glass, ProductDimensionUnit glassUOM,
  522. List<Product> _products, List<ProductStyle> _styles)
  523. {
  524. var _bom = new JobBillOfMaterials();
  525. _bom.Job.ID = scope.Job.ID;
  526. _bom.Description = string.IsNullOrWhiteSpace(quote.Variation)
  527. ? "Main Job"
  528. : $"{quote.Variation}";
  529. Client.Save(_bom,"Imported From V6");
  530. List<JobBillOfMaterialsItem> _bomitems = new();
  531. foreach (var _profile in profiles)
  532. {
  533. var _bomitem = new JobBillOfMaterialsItem();
  534. _bomitem.BillOfMaterials.ID = _bom.ID;
  535. _bomitem.Job.ID = scope.Job.ID;
  536. _bomitem.Scope.ID = scope.ID;
  537. if (_products.FirstOrDefault(x => x.Code == _profile.Code) is { } _p)
  538. {
  539. _bomitem.Product.CopyFrom(_p);
  540. _bomitem.Dimensions.Unit.CopyFrom(profileUOM);
  541. _bomitem.Dimensions.Length = _profile.Length;
  542. }
  543. else
  544. _bomitem.Problem = new ManagedProblem() { Notes = new string[] { $"Unable to Locate Product: {_profile.Quantity} x {_profile.Code}: {_profile.Description} ({_profile.Length})" } };
  545. if (!string.IsNullOrWhiteSpace(_profile.Finish))
  546. {
  547. if (_styles.FirstOrDefault(x => x.Code == _profile.Finish) is { } _s)
  548. _bomitem.Style.CopyFrom(_s);
  549. else
  550. _bomitem.Problem = new ManagedProblem() { Notes = new string[] { $"Unable to Locate Style: {_profile.Finish}" } };
  551. }
  552. _bomitem.Quantity = _profile.Quantity;
  553. _bomitem.UnitCost = _profile.Cost;
  554. _bomitems.Add(_bomitem);
  555. }
  556. foreach (var _component in components)
  557. {
  558. var _bomitem = new JobBillOfMaterialsItem();
  559. _bomitem.BillOfMaterials.ID = _bom.ID;
  560. _bomitem.Job.ID = scope.Job.ID;
  561. _bomitem.Scope.ID = scope.ID;
  562. if (_products.FirstOrDefault(x => x.Code == _component.Code) is { } _s)
  563. {
  564. _bomitem.Product.CopyFrom(_s);
  565. _bomitem.Dimensions.Unit.CopyFrom(componentUOM);
  566. _bomitem.Dimensions.Quantity = 1;
  567. _bomitems.Add(_bomitem);
  568. }
  569. else
  570. _bomitem.Problem = new ManagedProblem() { Notes = new string[] { $"Unable to Locate Product: {_component.Quantity} x {_component.Code}: {_component.Description} ({_component.PackSize})" } };
  571. _bomitem.Quantity = _component.Quantity * _component.PackSize;
  572. _bomitem.UnitCost = _component.Cost;
  573. }
  574. foreach (var _glass in glass)
  575. {
  576. var _bomitem = new JobBillOfMaterialsItem();
  577. _bomitem.BillOfMaterials.ID = _bom.ID;
  578. _bomitem.Job.ID = scope.Job.ID;
  579. _bomitem.Scope.ID = scope.ID;
  580. if (_products.FirstOrDefault(x => x.Code == _glass.Code) is { } _p)
  581. {
  582. _bomitem.Product.CopyFrom(_p);
  583. _bomitem.Dimensions.Unit.CopyFrom(glassUOM);
  584. _bomitem.Dimensions.Height = _glass.Height * 25.4;
  585. _bomitem.Dimensions.Width = _glass.Width * 25.4;
  586. _bomitems.Add(_bomitem);
  587. }
  588. else
  589. _bomitem.Problem = new ManagedProblem() { Notes = new string[] {
  590. $"Unable to Locate Product: {_glass.Code}: {_glass.Description} ({_glass.Height} x {_glass.Width})" } };
  591. if (!string.IsNullOrWhiteSpace(_glass.Treatment))
  592. {
  593. if (_styles.FirstOrDefault(x => x.Code == _glass.Treatment) is { } _s)
  594. _bomitem.Style.CopyFrom(_s);
  595. else
  596. _bomitem.Problem = new ManagedProblem() { Notes = new string[] { $"Unable to Locate Style: {_glass.Treatment})" } };
  597. }
  598. _bomitem.Quantity = _glass.Quantity;
  599. _bomitem.UnitCost = _glass.Cost;
  600. }
  601. Client.Save(_bomitems,"Imported From V6");
  602. return _bom;
  603. }
  604. private void CreateActivities(V6Quote project, JobScope scope, List<V6Labour> labour, List<Activity> activities)
  605. {
  606. var _jobactivities = Client.Query(
  607. new Filter<JobActivity>(x => x.JobLink.ID).IsEqualTo(scope.Job.ID),
  608. Columns.Required<JobActivity>()
  609. .Add(x => x.JobLink.ID)
  610. .Add(x => x.ActivityLink.ID)
  611. .Add(x => x.Budget)
  612. ).ToObjects<JobActivity>().ToList();
  613. List<JobActivity> _updates = new List<JobActivity>();
  614. foreach (var _labour in labour)
  615. {
  616. var _activity = activities.FirstOrDefault(x => string.Equals(x.Code, _labour.Code)) ?? new Activity();
  617. var _jobactivity = _jobactivities.FirstOrDefault(x => x.ActivityLink.ID == _activity.ID) ?? new JobActivity();
  618. _jobactivity.JobLink.ID = scope.Job.ID;
  619. _jobactivity.ActivityLink.CopyFrom(_activity);
  620. _jobactivity.Budget += TimeSpan.FromMinutes(_labour.Minutes);
  621. _updates.Add(_jobactivity);
  622. }
  623. Client.Save(_updates,"Imported From V6");
  624. }
  625. private void CreateManufacturingPackets(V6Quote project, JobScope scope, Dictionary<V6Elevation, V6Drawings> designs, ManufacturingTemplate template, ManufacturingTemplateStage[] stages)
  626. {
  627. foreach (var _design in designs)
  628. {
  629. var _setout = new Setout();
  630. _setout.JobLink.ID = scope.Job.ID;
  631. _setout.Description = _design.Key.Description;
  632. _setout.Number = _design.Key.Description;
  633. Client.Save(_setout,"Imported From V6");
  634. var _drawings = _client.DecodeDrawings(_design.Value.Drawings, new string[] { "FrameDrawing" });
  635. List<Document> _documents = new();
  636. foreach (var _drawing in _drawings)
  637. {
  638. var _document = new Document();
  639. _document.FileName = System.IO.Path.ChangeExtension(_drawing.FileName, ".pdf");
  640. _document.Data = ImageUtils.BitmapToPdf(_drawing.Data);
  641. _documents.Add(_document);
  642. }
  643. if (_documents.Any())
  644. Client.Save(_documents, "Imported From V6");
  645. List<SetoutDocument> _setoutdocuments = new();
  646. foreach (var _document in _documents)
  647. {
  648. var _setoutdocument = new SetoutDocument();
  649. _setoutdocument.EntityLink.CopyFrom(_setout);
  650. _setoutdocument.DocumentLink.CopyFrom(_document);
  651. _setoutdocument.Thumbnail = ImageUtils.GetPDFThumbnail(_document.Data, 256, 256);
  652. _setoutdocuments.Add(_setoutdocument);
  653. }
  654. if (_setoutdocuments.Any())
  655. Client.Save(_setoutdocuments, "Imported From V6");
  656. var _packet = new ManufacturingPacket();
  657. _packet.SetoutLink.ID = _setout.ID;
  658. _packet.ManufacturingTemplateLink.CopyFrom(template);
  659. _packet.Title = _setout.Description;
  660. _packet.Quantity = _design.Key.Quantity;
  661. Client.Save(_packet,"Imported From V6");
  662. List<ManufacturingPacketStage> _packetstages = new();
  663. foreach (var _templatestage in stages)
  664. {
  665. var _packetstage = new ManufacturingPacketStage
  666. {
  667. Time = _templatestage.Time,
  668. SequenceType = _templatestage.SequenceType,
  669. Sequence = _templatestage.Sequence
  670. };
  671. _packetstage.Parent.ID = _packet.ID;
  672. _packetstage.ManufacturingSectionLink.ID = _templatestage.Section.ID;
  673. _packetstage.ManufacturingSectionLink.Name = _templatestage.Section.Name;
  674. _packetstages.Add(_packetstage);
  675. }
  676. if (_packetstages.Any())
  677. Client.Save(_packetstages,"Imported from V6");
  678. }
  679. }
  680. private void CreateStagedSetouts(V6Quote project, JobScope scope, Dictionary<V6Elevation, V6Drawings> designs, ManufacturingTemplate template, ManufacturingTemplateStage[] stages)
  681. {
  682. foreach (var _design in designs)
  683. {
  684. var _setout = new StagingSetout();
  685. _setout.JobLink.ID = scope.Job.ID;
  686. _setout.Number = _design.Key.Description;
  687. Client.Save(_setout,"Imported From V6");
  688. var _drawings = _client.DecodeDrawings(_design.Value.Drawings, new string[] { "FrameDrawing" });
  689. List<Document> _documents = new();
  690. foreach (var _drawing in _drawings)
  691. {
  692. var _document = new Document();
  693. _document.FileName = System.IO.Path.ChangeExtension(_drawing.FileName, ".pdf");
  694. _document.Data = ImageUtils.BitmapToPdf(_drawing.Data);
  695. _documents.Add(_document);
  696. }
  697. if (_documents.Any())
  698. Client.Save(_documents, "Imported From V6");
  699. List<StagingSetoutDocument> _setoutdocuments = new();
  700. foreach (var _document in _documents)
  701. {
  702. var _setoutdocument = new StagingSetoutDocument();
  703. _setoutdocument.EntityLink.CopyFrom(_setout);
  704. _setoutdocument.DocumentLink.CopyFrom(_document);
  705. _setoutdocument.Thumbnail = ImageUtils.GetPDFThumbnail(_document.Data, 256, 256);
  706. _setoutdocuments.Add(_setoutdocument);
  707. }
  708. if (_setoutdocuments.Any())
  709. Client.Save(_setoutdocuments, "Imported From V6");
  710. var _packet = new StagingManufacturingPacket();
  711. _packet.StagingSetout.ID = _setout.ID;
  712. _packet.Template.CopyFrom(template);
  713. _packet.Title = _setout.Number;
  714. _packet.Quantity = _design.Key.Quantity;
  715. Client.Save(_packet,"Imported From V6");
  716. List<StagingManufacturingPacketStage> _packetstages = new();
  717. foreach (var _templatestage in stages)
  718. {
  719. var _packetstage = new StagingManufacturingPacketStage
  720. {
  721. Time = _templatestage.Time,
  722. SequenceType = _templatestage.SequenceType,
  723. Sequence = _templatestage.Sequence
  724. };
  725. _packetstage.Packet.ID = _packet.ID;
  726. _packetstage.Section.ID = _templatestage.Section.ID;
  727. _packetstage.Section.Name = _templatestage.Section.Name;
  728. _packetstages.Add(_packetstage);
  729. }
  730. if (_packetstages.Any())
  731. Client.Save(_packetstages,"Imported from V6");
  732. }
  733. }
  734. private void Cancel_Click(object sender, RoutedEventArgs e)
  735. {
  736. DialogResult = false;
  737. }
  738. private void Projects_OnOnSelectItem(object sender, DynamicGridSelectionEventArgs e)
  739. {
  740. Ok.IsEnabled = Projects.SelectedRows.Any();
  741. }
  742. }