using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace AyaNovaQBI { public partial class MainForm : Form { public MainForm() { InitializeComponent(); //InitDataSet(); Icon = AyaNovaQBI.Properties.Resources.logo; } async private void MainForm_Load(object sender, EventArgs e) { //Initialize StringBuilder initErrors = new StringBuilder(); if (await util.InitializeQBI(initErrors) == false) { if (initErrors.Length > 0) { if (util.LOG_AVAILABLE) await util.IntegrationLog(initErrors.ToString()); await Task.Run(() => MessageBox.Show($"AyaNova QBI was unable to start:\r\n{initErrors.ToString()}")); } Close(); return; } //Confirm main settings and set any that are missing: if (await util.ValidateSettings(false) == util.pfstat.Cancel) { await util.IntegrationLog("PFC: User settings not completed, user selected cancel"); Close(); return; } Text = "AyaNova QBI - " + util.QCompanyName; InitializeGrid(); //See if there are *any* data mappings, if not then we will prompt the user to start that process if (util.QBIntegration.Items.Count == 0) { //show message about mapping MessageBox.Show( "AyaNova QBI now needs you to map data between QuickBooks and AyaNova.", "Setup mapping", MessageBoxButtons.OK, MessageBoxIcon.Information); Map m = new Map(); if (m.ShowDialog() == DialogResult.Abort) Close(); } //Display billable workorders await InitInvoices(); grid.Visible = true; menuStrip1.Enabled = true; } private void grid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) { if (e.ColumnIndex == grid.Columns["Status"].Index && e.Value != null) { var isLinked = (bool)grid.Rows[e.RowIndex].Cells["linked"].Value; if (!isLinked) { grid.Rows[e.RowIndex].ErrorText = "Not invoiceable: use \"Invoice\" -> \"Fix problems\" to resolve"; } else { grid.Rows[e.RowIndex].ErrorText = null; } } } private void exitToolStripMenuItem_Click(object sender, EventArgs e) { Close(); } private void multipleWorkordersPerInvoiceToolStripMenuItem_Click(object sender, EventArgs e) { if (grid.SelectedRows.Count < 1) { MessageBox.Show("There are no rows selected, select one or more rows to invoice"); return; } MessageBox.Show($"STUB: MULTIPLEwoperinvoice {grid.SelectedRows.Count} rows selected"); } private void oneWorkOrderPerInvoiceToolStripMenuItem_Click(object sender, EventArgs e) { if (grid.SelectedRows.Count < 1) { MessageBox.Show("There are no rows selected, select one or more rows to invoice"); return; } MessageBox.Show($"STUB: onwoperinvoice {grid.SelectedRows.Count} rows selected"); } private void fixProblemsToolStripMenuItem_Click(object sender, EventArgs e) { MessageBox.Show("STUB: FIX PROBLEMS"); } private void refreshInvoicesToolStripMenuItem_Click(object sender, EventArgs e) { MessageBox.Show("STUB: REFRESH INVOICES"); } private async void preferencesToolStripMenuItem_Click(object sender, EventArgs e) { await util.ValidateSettings(true); } private async void mapAndImportToolStripMenuItem_Click(object sender, EventArgs e) { Map m = new Map(); if (m.ShowDialog() == DialogResult.Abort) Close(); else { m.Dispose(); await InitInvoices(); } } private void aboutToolStripMenuItem_Click(object sender, EventArgs e) { Assembly a = Assembly.GetExecutingAssembly(); string sVersion = "AyaNova QBI version " + util.DisplayVersion(a.GetName().Version) + "\r\n"; System.Diagnostics.FileVersionInfo fileVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(a.Location); if (fileVersion.FileBuildPart > 0) sVersion += " (Patch " + fileVersion.FileBuildPart.ToString() + ")\r\n"; sVersion += "Copyright 2000-2022 Ground Zero Tech-Works Inc.\r\n"; MessageBox.Show(sVersion, "About"); } private void onlineManualToolStripMenuItem_Click(object sender, EventArgs e) { util.OpenWebURL("https://ayanova.com/qbi/docs"); } private async void refreshCachedDataToolStripMenuItem_Click(object sender, EventArgs e) { await util.PopulateQBListCache(); await util.PopulateAyaListCache(); } private async void invoiceDescriptiveTextTemplateToolStripMenuItem_Click(object sender, EventArgs e) { InvoiceTemplateBuilder b = new InvoiceTemplateBuilder(); b.ShowDialog(); if (util.QDat.IsDirty) await util.SaveIntegrationObject(); b.Dispose(); } #region DataSet stuff //private DataSet dsInvoices; //private DataTable Invoices; //private DataColumn Client; //private DataColumn WorkingID; //private DataColumn Linked; //private DataColumn ClientID; //private DataTable Workorders; //private DataColumn InvoiceWorkingID; //private DataColumn WorkorderID; //private DataColumn wostatus; //private DataColumn ServiceNumber; //private DataColumn ServiceDate; //private DataColumn Project; //private DataColumn StatusARGB; //private DataColumn dataColumn1; //private void InitDataSet() //{ // dsInvoices = new DataSet(); // Invoices = new DataTable(); // Client = new DataColumn(); // WorkingID = new DataColumn(); // Linked = new DataColumn(); // ClientID = new DataColumn(); // Workorders = new DataTable(); // InvoiceWorkingID = new DataColumn(); // WorkorderID = new DataColumn(); // wostatus = new DataColumn(); // ServiceNumber = new DataColumn(); // ServiceDate = new DataColumn(); // Project = new DataColumn(); // StatusARGB = new DataColumn(); // dataColumn1 = new DataColumn(); // // // // dsInvoices // // // dsInvoices.DataSetName = "Invoices"; // dsInvoices.Locale = new System.Globalization.CultureInfo("en-US"); // dsInvoices.Relations.AddRange(new DataRelation[] { // new DataRelation("Relation1", "Invoices", "Workorders", new string[] { // "WorkingID"}, new string[] { // "InvoiceWorkingID"}, false)}); // dsInvoices.Tables.AddRange(new DataTable[] { // Invoices, // Workorders}); // // // // Invoices // // // Invoices.Columns.AddRange(new DataColumn[] { // Client, // WorkingID, // Linked, // ClientID}); // Invoices.Constraints.AddRange(new Constraint[] { // new UniqueConstraint("Constraint1", new string[] { // "WorkingID"}, true)}); // Invoices.PrimaryKey = new DataColumn[] { //WorkingID}; // Invoices.TableName = "Invoices"; // // // // Client // // // Client.ColumnName = "Client"; // // // // WorkingID // // // WorkingID.AllowDBNull = false; // WorkingID.AutoIncrement = true; // WorkingID.Caption = "WorkingID"; // WorkingID.ColumnName = "WorkingID"; // WorkingID.DataType = typeof(int); // WorkingID.ReadOnly = true; // // // // Linked // // // Linked.Caption = "Linked"; // Linked.ColumnName = "Linked"; // Linked.DataType = typeof(bool); // Linked.DefaultValue = false; // // // // ClientID // // // ClientID.Caption = "ClientID"; // ClientID.ColumnName = "ClientID"; // ClientID.DataType = typeof(System.Guid); // // // // Workorders // // // Workorders.Columns.AddRange(new DataColumn[] { // InvoiceWorkingID, // WorkorderID, // wostatus, // ServiceNumber, // ServiceDate, // Project, // StatusARGB, // dataColumn1}); // Workorders.Constraints.AddRange(new Constraint[] { // new UniqueConstraint("Constraint1", new string[] { // "WorkorderID"}, true), // new ForeignKeyConstraint("Relation1", "Invoices", new string[] { // "WorkingID"}, new string[] { // "InvoiceWorkingID"}, AcceptRejectRule.None, Rule.None, Rule.None)}); // Workorders.PrimaryKey = new DataColumn[] { //WorkorderID}; // Workorders.TableName = "Workorders"; // // // // InvoiceWorkingID // // // InvoiceWorkingID.Caption = "InvoiceWorkingID"; // InvoiceWorkingID.ColumnName = "InvoiceWorkingID"; // InvoiceWorkingID.DataType = typeof(int); // // // // WorkorderID // // // WorkorderID.AllowDBNull = false; // WorkorderID.Caption = "WorkorderID"; // WorkorderID.ColumnName = "WorkorderID"; // WorkorderID.DataType = typeof(System.Guid); // // // // wostatus // // // wostatus.Caption = "Status"; // wostatus.ColumnName = "Status"; // // // // ServiceNumber // // // ServiceNumber.Caption = "ServiceNumber"; // ServiceNumber.ColumnName = "ServiceNumber"; // ServiceNumber.DataType = typeof(int); // // // // ServiceDate // // // ServiceDate.Caption = "ServiceDate"; // ServiceDate.ColumnName = "ServiceDate"; // ServiceDate.DataType = typeof(object); // // // // Project // // // Project.Caption = "Project"; // Project.ColumnName = "Project"; // // // // StatusARGB // // // StatusARGB.Caption = "StatusARGB"; // StatusARGB.ColumnName = "StatusARGB"; // StatusARGB.DataType = typeof(int); // // // // dataColumn1 // // // dataColumn1.ColumnName = "Linked"; // dataColumn1.DataType = typeof(bool); // dataColumn1.DefaultValue = false; //} #endregion dataset stuff #region Main workorder grid /// /// Adjusts main form display to either show a list of billable workorders /// or a status indicating there are none and why /// private async Task SetState() { fixProblemsToolStripMenuItem.Enabled = _MisMatches.Count > 0; if (grid.Rows.Count > 0) { grid.Visible = true; lblStatus.Visible = false; } else { StringBuilder sb = new StringBuilder(); sb.Append("No invoiceable work orders found in AyaNova\r\n\r\n"); sb.Append("A work order is invoiceable and will be listed here if it has:\r\n"); sb.Append(" - \"Invoice number\" field empty\r\n"); if (util.QDat.PreWOStatus != 0) { sb.Append(" - \"Work order status\" field set to: "); var r = await util.GetAsync($"work-order-status/{util.QDat.PreWOStatus}"); var status = r.ObjectResponse["data"].ToObject(); if (status != null) sb.Append(status.Name); else sb.Append("UNKNOWN / MISSING STATUS - recently deleted?"); sb.Append("\r\n"); sb.Append(" (You can change this status under Tools->Preferences in the menu)"); } else sb.Append(" - any \"Locked\" type of Work order status set\r\n"); lblStatus.Text = sb.ToString(); grid.Visible = false; lblStatus.Visible = true; } } /* POST /api/v8.0/data-list {"offset":0,"limit":10,"dataListKey":"WorkOrderDataList","filterId":6,"clientTimeStamp":"2022-07-08T10:49:18.715-07:00"} data-list-column-view: {"userId":1,"listKey":"WorkOrderDataList","columns":"[\"WorkOrderSerialNumber\",\"Customer\",\"WorkOrderServiceDate\",\"WorkOrderCloseByDate\",\"WorkOrderStatus\",\"Project\",\"WorkOrderAge\",\"WorkOrderInvoiceNumber\"]","sort":"{\"WorkOrderSerialNumber\":\"-\"}"} data-list-filter filter "[{\"column\":\"WorkOrderInvoiceNumber\",\"any\":false,\"items\":[{\"op\":\"=\",\"value\":\"*NULL*\"}]}]" */ private List _WorkOrderGridListItems = new List(); private List _MisMatches = new List(); private List _PartPriceOverrides = new List(); /// /// Initialize invoices dataset /// from scratch. If a previous /// initialize was done, wipe it and /// repopulate from scratch /// private async Task InitInvoices() { Waiting w = new Waiting(); w.Show(); w.Ops = "Validating invoices..."; try { _MisMatches.Clear(); //[HttpGet("accounting-list-billable/{workOrderStatusId}")] var r = await util.GetAsync($"workorder/accounting-list-billable/{util.QDat.PreWOStatus}"); _WorkOrderGridListItems = r.ObjectResponse["data"] .ToObject>() .Select(z => new WorkOrderGridListItem { Color = z.Color, CustomerId = z.CustomerId, CustomerName = z.CustomerName, Id = z.Id, ProjectName = z.ProjectName, Serial = z.Serial, ServiceDate = z.ServiceDate, WorkorderStatusName = z.WorkorderStatusName }) .ToList(); foreach (WorkOrderGridListItem i in _WorkOrderGridListItems) { w.Step = "WO: " + i.Serial; i.Linked = util.ScanLinksOK(i.Id, _MisMatches, _PartPriceOverrides); //DataRow dri = InvoiceRowForClientID(i.ClientID); //if (dri == null) //{ // dri = dtInvoice.NewRow(); // dri["Client"] = i.Client; // dri["ClientID"] = i.ClientID; // dtInvoice.Rows.Add(dri); } //If any one single workorder is linked //then the invoice is flagged as linked because //you can invoice out anything under it that is linked and the //not linked items simply won't invoice //if (bLinked) // dri["Linked"] = true; //DataRow drw = dtWorkorder.NewRow(); //drw["InvoiceWorkingID"] = (int)dri["WorkingID"]; //drw["WorkorderID"] = i.ID; //drw["Status"] = i.Status; //drw["ServiceNumber"] = i.ServiceNumber; //drw["ServiceDate"] = i.ServiceDate; //drw["Project"] = i.Project; //drw["StatusARGB"] = i.StatusARGB; //drw["Linked"] = bLinked; //dtWorkorder.Rows.Add(drw); // grid.DisplayLayout.Rows.CollapseAll(false); //foreach (UltraGridRow r in grid.Rows) //{ // foreach (UltraGridRow rr in r.ChildBands[0].Rows) // { // if ((bool)rr.Cells["Linked"].Value == false) // r.Expanded = true; // } //} //grid.EndUpdate(); } finally { w.Close(); } await SetState(); } ///// ///// Helper for grouping workorders by client ///// ///// ///// null if not found else datarow containing invoice for client //private DataRow InvoiceRowForClientID(Guid ClientID) //{ // foreach (DataRow r in dsInvoices.Tables["Invoices"].Rows) // { // if ((Guid)r["ClientID"] == ClientID) // { // return r; // } // } // return null; //} private void InitializeGrid() { grid.DataSource = _WorkOrderGridListItems; //grid.Columns["WorkingID"].Visible = false; //grid.Columns["ClientID"].Visible = false; //grid.Columns["Linked"].Visible = false; //grid.Columns["Client"].Visible = false; //grid.Columns["InvoiceWorkingID"].Visible = false; //grid.Columns["WorkorderID"].Visible = false; //grid.Columns["StatusARGB"].Visible = false; //grid.Columns["WorkingID"].Visible = false; //string currentAssemblyDirectoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); //Load the grid layout from file //if (System.IO.File.Exists(currentAssemblyDirectoryName + "\\MainGrid.lyt")) // grid.DisplayLayout.Load(currentAssemblyDirectoryName + "\\MainGrid.lyt"); //grid.DisplayLayout.Bands[0].Columns["WorkingID"].Hidden = true; //grid.DisplayLayout.Bands[0].Columns["ClientID"].Hidden = true; //grid.DisplayLayout.Bands[0].Columns["Linked"].Hidden = true; //grid.DisplayLayout.Bands[0].Columns["Client"].Header.Caption = "Invoice"; //grid.DisplayLayout.Bands[1].Columns["InvoiceWorkingID"].Hidden = true; //grid.DisplayLayout.Bands[1].Columns["WorkorderID"].Hidden = true; //grid.DisplayLayout.Bands[1].Columns["StatusARGB"].Hidden = true; //grid.DisplayLayout.Bands[1].Columns["Linked"].Hidden = true; } //private void grid_InitializeRow(object sender, Infragistics.Win.UltraWinGrid.InitializeRowEventArgs e) //{ // if (e.Row.Band.Index == 0) // { // //Prepare invoice row // if ((bool)e.Row.Cells["Linked"].Value == true) // { // e.Row.Cells["Client"].Appearance.Image = Util.AyaImage("OK16");//Util.Image("OK16.png"); // } // else // { // e.Row.Cells["Client"].Appearance.Image = Util.AyaImage("Cancel16");//Util.Image("Cancel16.png"); // } // } // else // { // //prepare workorder row // //if backcolor==0 that means no color was set // int nColor = (int)e.Row.Cells["StatusARGB"].Value; // if (nColor != 0) // { // e.Row.Cells["Status"].Appearance.BackColor = Color.FromArgb(nColor); // e.Row.Cells["Status"].Appearance.ForeColor = Util.InvertColor(Color.FromArgb(nColor)); // } // //flag whether billable (linked) or not // if ((bool)e.Row.Cells["Linked"].Value == true) // { // e.Row.Cells["ServiceNumber"].Appearance.Image = Util.AyaImage("OK16"); // } // else // { // e.Row.Cells["ServiceNumber"].Appearance.Image = Util.AyaImage("Cancel16"); // } // } //} #endregion }//eoc }//eons