예제 #1
0
        private static void InstanceBridgeExport()
        {
            string dir     = Path.GetDirectoryName(_path);
            string extract = CodeBase.ODFileUtils.CombinePaths(dir, "extract.xml");

            CheckCreatedFile(extract);
            double linesProcessedCount = 0;
            string licenseKey          = ProgramProperties.GetPropVal(Programs.GetProgramNum(ProgramName.DemandForce), "Enter your DemandForce license key (required)");
            string versionCur          = new Version(Application.ProductVersion).ToString();
            string extractDateTime     = DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffK");
            Dictionary <long, DateTime>            dateLastVisit  = Appointments.GetDateLastVisit();
            Dictionary <long, List <Appointment> > allPatApts     = Appointments.GetAptsForPats(DateTime.Now.ToUniversalTime(), DateTime.Now.AddDays(210).ToUniversalTime()); //appointments from todays date forward 210 days
            Dictionary <long, List <long> >        allAptProcNums = Appointments.GetCodeNumsAllApts();

            long[]             arrayPatNums = Patients.GetAllPatNums(false);
            Patient            patient;
            Appointment        apt;
            List <Appointment> listApts;
            List <long>        listProcNums;
            double             totalLines = CalculateTotalLinesOfCode(arrayPatNums, allAptProcNums, allPatApts);

            while (!_formProg.IsHandleCreated)
            {
            }                                                //Wait for the form to show the first time, or else the Invoke calls will cause an exception.
            _formProg.Invoke(new PassProgressDelegate(PassPercentProgressToDialog), new object[] { linesProcessedCount,
                                                                                                   Lan.g(_formProg, "Executing the bridge to DemandForce"),
                                                                                                   100.0, "" });
            Thread.Sleep(1000);            //Wait 1 second so the user can see the progress bar popup.
            try {
                StringBuilder     strb     = new StringBuilder();
                XmlWriterSettings settings = new XmlWriterSettings();
                settings.Encoding           = Encoding.UTF8;
                settings.Indent             = true;
                settings.IndentChars        = "   ";
                settings.NewLineChars       = "\r\n";
                settings.OmitXmlDeclaration = true;
                XmlWriter writer = XmlWriter.Create(strb, settings);
                writer.WriteRaw("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n");
                writer.WriteStartElement("DemandForce");
                writer.WriteAttributeString("licenseKey", licenseKey);
                writer.WriteAttributeString("scope", "full");
                writer.WriteStartElement("Business");
                writer.WriteStartElement("Extract");
                writer.WriteAttributeString("extractDateTime", extractDateTime);
                writer.WriteAttributeString("managementSystemName", "Open Dental");
                writer.WriteAttributeString("managementSystemVersion", versionCur);
                writer.WriteEndElement();                //Extract
                for (int i = 0; i < arrayPatNums.Length; i++)
                {
                    patient = Patients.GetPat(arrayPatNums[i]);
                    writer.WriteStartElement("Customer");
                    writer.WriteAttributeString("id", patient.PatNum.ToString());
                    if (patient.ChartNumber != "")
                    {
                        writer.WriteAttributeString("chartId", patient.ChartNumber);
                    }
                    if (dateLastVisit.ContainsKey(patient.PatNum))                     //Need input. Will it ever be null? Or will it check empty string?
                    {
                        writer.WriteAttributeString("lastVisit", dateLastVisit[patient.PatNum].ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffK"));
                    }
                    else
                    {
                        writer.WriteAttributeString("lastVisit", PIn.DateT("0001-01-01 00:00:00").ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffK"));
                    }
                    writer.WriteStartElement("Demographics");
                    if (patient.FName != "")
                    {
                        writer.WriteAttributeString("firstName", patient.FName);
                    }
                    else
                    {
                        writer.WriteAttributeString("firstName", "X");                       //need input on what to do with patients who don't have a FName.
                    }
                    writer.WriteAttributeString("lastName", patient.LName);
                    if (patient.Gender.ToString() == "Female")
                    {
                        writer.WriteAttributeString("gender", "Female");
                    }
                    else
                    {
                        writer.WriteAttributeString("gender", "Male");
                    }
                    if (patient.Birthdate.Year > 1880)
                    {
                        writer.WriteAttributeString("birthday", patient.Birthdate.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffK"));
                    }
                    if (patient.Address != "")
                    {
                        writer.WriteAttributeString("address1", patient.Address);
                    }
                    if (patient.City != "")
                    {
                        writer.WriteAttributeString("city", patient.City);
                    }
                    if (patient.State != "")
                    {
                        writer.WriteAttributeString("State", patient.State);
                    }
                    if (patient.Zip != "")
                    {
                        writer.WriteAttributeString("Zip", patient.Zip);
                    }
                    if (patient.Email != "")
                    {
                        writer.WriteAttributeString("Email", patient.Email);
                    }
                    writer.WriteEndElement();                    //Demographics
                    if (allPatApts.ContainsKey(patient.PatNum))
                    {
                        listApts = allPatApts[patient.PatNum];
                        for (int j = 0; j < listApts.Count; j++)
                        {
                            apt = listApts[j];
                            writer.WriteStartElement("Appointment");
                            writer.WriteAttributeString("id", apt.AptNum.ToString());
                            if (apt.AptStatus.ToString() == "Complete")
                            {
                                writer.WriteAttributeString("status", "1");
                            }
                            else
                            {
                                writer.WriteAttributeString("status", "3");
                            }
                            if (Defs.GetDef(DefCat.ApptConfirmed, apt.Confirmed).ItemName.ToLower() == "unconfirmed")
                            {
                                writer.WriteAttributeString("confirmed", "0");
                            }
                            else
                            {
                                writer.WriteAttributeString("confirmed", "1");
                            }
                            writer.WriteAttributeString("date", apt.AptDateTime.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffK"));
                            writer.WriteAttributeString("duration", (apt.Pattern.Length * 5).ToString());
                            if (allAptProcNums.ContainsKey(apt.AptNum))
                            {
                                listProcNums = allAptProcNums[apt.AptNum];
                                string codes = "";
                                for (int k = 0; k < listProcNums.Count; k++)
                                {
                                    codes += ProcedureCodes.GetStringProcCode(listProcNums[k]);
                                    if (k < listProcNums.Count - 1)
                                    {
                                        codes += ", ";
                                    }
                                    if (linesProcessedCount < totalLines)                                   //this avoids setting progress bar to max, which would close the dialog.
                                    {
                                        _formProg.Invoke(new PassProgressDelegate(PassPercentProgressToDialog), new object[] { (linesProcessedCount / totalLines * 100),
                                                                                                                               Lan.g(_formProg, "Creating export file: ?currentVal % of ?maxVal % completed"),
                                                                                                                               100.0, "" });
                                    }
                                    linesProcessedCount += 2;
                                }
                                if (codes != "")
                                {
                                    writer.WriteAttributeString("code", codes);
                                }
                            }
                            writer.WriteEndElement();                            //Appointment
                            if (linesProcessedCount < totalLines)                //this avoids setting progress bar to max, which would close the dialog.
                            {
                                _formProg.Invoke(new PassProgressDelegate(PassPercentProgressToDialog), new object[] { (linesProcessedCount / totalLines * 100),
                                                                                                                       Lan.g(_formProg, "Creating export file: ?currentVal % of ?maxVal % completed"),
                                                                                                                       100.0, "" });
                            }
                            linesProcessedCount += 12;
                        }
                    }
                    writer.WriteEndElement();                    //Customer
                    if (linesProcessedCount < totalLines)        //this avoids setting progress bar to max, which would close the dialog.
                    {
                        _formProg.Invoke(new PassProgressDelegate(PassPercentProgressToDialog), new object[] { (linesProcessedCount / totalLines * 100),
                                                                                                               Lan.g(_formProg, "Creating export file: ?currentVal % of ?maxVal % completed"),
                                                                                                               100.0, "" });
                    }
                    linesProcessedCount += 20;
                }
                writer.WriteEndElement();                //Business
                writer.WriteEndElement();                //DemandForce
                writer.Flush();
                writer.Close();
                ODFileUtils.WriteAllText(extract, strb.ToString());
            }
            catch {
                MessageBox.Show(Lan.g("DemandForce", "Export file creation failed") + ". " + Lan.g("DemandForce", "User may not have sufficient permissions") + ".");
            }
            if (linesProcessedCount >= totalLines)           //this avoids setting progress bar to max, which would close the dialog.
            {
                _formProg.DisplayText = "Creating export file: 100 % of 100 % completed";
            }
            Thread.Sleep(600);            //Wait a little bit so the user can see that it got to 100% complete.
            //force dialog to close even if no files copied or calculation was slightly off.
            _formProg.Invoke(new PassProgressDelegate(PassPercentProgressToDialog), new object[] { 0, "", 0, "" });
        }
예제 #2
0
        ///<summary>Surround with try catch.  The "data" is the previously constructed xml.  If the internet connection is lost or unavailable, then the exception thrown will be a 404 error similar to the following: "The remote server returned an error: (404) Not Found"</summary>
        public static void Send(string data, long clinicNum)
        {
            //Validate the structure of the XML before sending.
            StringReader sr = new StringReader(data);

            try {
                XmlReader xmlr = XmlReader.Create(sr);
                while (xmlr.Read())                  //Read every node an ensure that there are no exceptions thrown.
                {
                }
            }
            catch (Exception ex) {
                throw new ApplicationException("Invalid XML in statement batch: " + ex.Message);
            }
            finally {
                sr.Dispose();
            }
            string strHistoryFile = "";

            if (PrefC.GetBool(PrefName.BillingElectSaveHistory))
            {
                string strHistoryDir = CodeBase.ODFileUtils.CombinePaths(ImageStore.GetPreferredAtoZpath(), "EHG_History");
                if (!Directory.Exists(strHistoryDir))
                {
                    Directory.CreateDirectory(strHistoryDir);
                }
                strHistoryFile = CodeBase.ODFileUtils.CreateRandomFile(strHistoryDir, ".txt");
                ODFileUtils.WriteAllText(strHistoryFile, data);
            }
            //Step 1: Post authentication request:
            Version        myVersion = new Version(Application.ProductVersion);
            HttpWebRequest webReq;
            WebResponse    response;
            StreamReader   readStream;
            string         str;

            string[] responseParams;
            string   status             = "";
            string   group              = "";
            string   userid             = "";
            string   authid             = "";
            string   errormsg           = "";
            string   alertmsg           = "";
            string   curParam           = "";
            string   serverName         = "https://claimconnect.dentalxchange.com/dci/upload.svl";//live URL for claims (According to phone call with Dentalxchange)
            string   serverNameOverride = PrefC.GetString(PrefName.BillingElectStmtUploadURL);

            if (!string.IsNullOrEmpty(serverNameOverride))
            {
                serverName = serverNameOverride;
            }
#if DEBUG
            //serverName="https://prelive.dentalxchange.com/dci/upload.svl";      //test URL for claims
            //serverName="https://claimconnect.dentalxchange.com/dci/upload.svl"; //live URL for claims
            //serverName="https://prelive.dentalxchange.com/dci/upload.svl";      //test URL for Stmts
            //serverName="https://billconnect.dentalxchange.com/dci/upload.svl";  //live URL for Stmts; probably the correct one to use.
#endif
            webReq = (HttpWebRequest)WebRequest.Create(serverName);
            Ebill  ebillDefault    = Ebills.GetForClinic(0);
            string billingUserName = ebillDefault.ElectUserName;
            string billingPassword = ebillDefault.ElectPassword;
            if (PrefC.HasClinicsEnabled && clinicNum != 0)
            {
                Ebill eBill = Ebills.GetForClinic(clinicNum);
                if (eBill != null)               //eBill entry exists, check the fields for overrides.
                {
                    if (eBill.ElectUserName != "")
                    {
                        billingUserName = eBill.ElectUserName;
                    }
                    if (eBill.ElectPassword != "")
                    {
                        billingPassword = eBill.ElectPassword;
                    }
                }
            }
            string postData =
                "Function=Auth"                                                                                                          //CONSTANT; signifies that this is an authentication request
                + "&Source=STM"                                                                                                          //CONSTANT; file format
                + "&UploaderName=OpenDental"                                                                                             //CONSTANT
                + "&UploaderVersion=" + myVersion.Major.ToString() + "." + myVersion.Minor.ToString() + "." + myVersion.Build.ToString() //eg 12.3.24
                + "&Username="******"&Password="******"POST";
            webReq.ContentType   = "application/x-www-form-urlencoded";
            webReq.ContentLength = postData.Length;
            ASCIIEncoding encoding  = new ASCIIEncoding();
            byte[]        bytes     = encoding.GetBytes(postData);
            Stream        streamOut = webReq.GetRequestStream();
            streamOut.Write(bytes, 0, bytes.Length);
            streamOut.Close();
            response = webReq.GetResponse();
            //Process the authentication response:
            readStream = new StreamReader(response.GetResponseStream(), Encoding.ASCII);
            str        = readStream.ReadToEnd();
            readStream.Close();
            if (strHistoryFile != "")           //Tack the response onto the end of the saved history file if one was created above.
            {
                File.AppendAllText(strHistoryFile, "\r\n\r\nCONNECTION REQUEST: postData.Length=" + postData.Length + " bytes.Length=" + bytes.Length + "==============\r\n"
                                   + " RESPONSE TO CONNECTION REQUEST================================================================\r\n" + str);
            }
            //Debug.WriteLine(str);
            //MessageBox.Show(str);
            responseParams = str.Split('&');
            for (int i = 0; i < responseParams.Length; i++)
            {
                curParam = GetParam(responseParams[i]);
                switch (curParam)
                {
                case "Status":
                    status = GetParamValue(responseParams[i]);
                    break;

                case "GROUP":
                    group = GetParamValue(responseParams[i]);
                    break;

                case "UserID":
                    userid = GetParamValue(responseParams[i]);
                    break;

                case "AuthenticationID":
                    authid = GetParamValue(responseParams[i]);
                    break;

                case "ErrorMessage":
                    errormsg = GetParamValue(responseParams[i]);
                    break;

                case "AlertMessage":
                    alertmsg = GetParamValue(responseParams[i]);
                    break;

                default:
                    throw new Exception("Unexpected parameter: " + curParam);
                }
            }
            //Process response for errors:
            if (alertmsg != "")
            {
                MessageBox.Show(alertmsg);
            }
            switch (status)
            {
            case "0":
                //MessageBox.Show("Authentication successful.");
                break;

            case "1":
                throw new Exception("Authentication failed. " + errormsg);

            case "2":
                throw new Exception("Cannot authenticate at this time. " + errormsg);

            case "3":
                throw new Exception("Invalid authentication request. " + errormsg);

            case "4":
                throw new Exception("Invalid program version. " + errormsg);

            case "5":
                throw new Exception("No customer contract. " + errormsg);

            default:                    //some as-yet-undefined error
                throw new Exception("Error " + status + ". " + errormsg);
            }
            //Step 2: Post upload request:
            //string fileName=Directory.GetFiles(clearhouse.ExportPath)[0];
            string boundary = "------------7d13e425b00d0";
            postData =
                "--" + boundary + "\r\n"
                + "Content-Disposition: form-data; name=\"Function\"\r\n"
                + "\r\n"
                + "Upload\r\n"
                + "--" + boundary + "\r\n"
                + "Content-Disposition: form-data; name=\"Source\"\r\n"
                + "\r\n"
                + "STM\r\n"
                + "--" + boundary + "\r\n"
                + "Content-Disposition: form-data; name=\"AuthenticationID\"\r\n"
                + "\r\n"
                + authid + "\r\n"
                + "--" + boundary + "\r\n"
                + "Content-Disposition: form-data; name=\"File\"; filename=\"" + "stmt.xml" + "\"\r\n"
                + "Content-Type: text/plain\r\n"
                + "\r\n"
                //using(StreamReader sr=new StreamReader(fileName)) {
                //	postData+=sr.ReadToEnd()+"\r\n"
                + data + "\r\n"
                + "--" + boundary + "--";
            //}
            //Debug.WriteLine(postData);
            //MessageBox.Show(postData);
            webReq = (HttpWebRequest)WebRequest.Create(serverName);
            //Timeout documentation: https://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.timeout(v=vs.110).aspx.
            //Timeout: "Gets or sets the time-out value in milliseconds for the GetResponse and GetRequestStream methods."
            //Timeout default is 100 seconds, which should be sufficient in waiting for a reply from dentalxchange, since the reply is small.
            //ReadWriteTimeout documentation: https://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.readwritetimeout%28v=vs.110%29.aspx
            //ReadWriteTimeout: "Gets or sets a time-out in milliseconds when writing to or reading from a stream."
            //ReadWriteTimeout default is 300 seconds (5 minutes).
            //Our message box that tells the user to wait up to 10 minutes for bills to send, therefore we need at least a 10 minute ReadWriteTimeout.
            //The user sees progress in the UI when sending.  We can increase timeouts as much as we want without making the program look like it crashed.
            webReq.ReadWriteTimeout = 600000;          //10 minutes = 10*60 seconds = 600 seconds = 600*1000 milliseconds = 600,000 milliseconds.
            webReq.KeepAlive        = false;
            webReq.Method           = "POST";
            webReq.ContentType      = "multipart/form-data; boundary=" + boundary;
            webReq.ContentLength    = postData.Length;
            bytes     = encoding.GetBytes(postData);
            streamOut = webReq.GetRequestStream();
            streamOut.Write(bytes, 0, bytes.Length);
            streamOut.Close();
            response = webReq.GetResponse();
            //Process the response
            readStream = new StreamReader(response.GetResponseStream(), Encoding.ASCII);
            str        = readStream.ReadToEnd();
            readStream.Close();
            if (strHistoryFile != "")           //Tack the response onto the end of the saved history file if one was created above.
            {
                File.AppendAllText(strHistoryFile, "\r\n\r\nUPLOAD REQUEST: postData.Length=" + postData.Length + " bytes.Length=" + bytes.Length + "==============\r\n"
                                   + " RESPONSE TO DATA UPLOAD================================================================\r\n" + str);
            }
            errormsg = "";
            status   = "";
            str      = str.Replace("\r\n", "");
            //Debug.Write(str);
            if (str.Length > 300)
            {
                throw new Exception("Unknown lengthy error message received.");
            }
            responseParams = str.Split('&');
            for (int i = 0; i < responseParams.Length; i++)
            {
                curParam = GetParam(responseParams[i]);
                switch (curParam)
                {
                case "Status":
                    status = GetParamValue(responseParams[i]);
                    break;

                case "Error Message":
                case "ErrorMessage":
                    errormsg = GetParamValue(responseParams[i]);
                    break;

                case "Filename":
                case "Timestamp":
                    break;

                case "":                        //errorMessage blank
                    break;

                default:
                    throw new Exception(str);                            //"Unexpected parameter: "+str);//curParam+"*");
                }
            }
            switch (status)
            {
            case "0":
                //MessageBox.Show("Upload successful.");
                break;

            case "1":
                throw new Exception("Authentication failed. " + errormsg);

            case "2":
                throw new Exception("Cannot upload at this time. " + errormsg);
            }
        }