From 2b44e58de3cd3c6b8f0c5c9e724f2f810adb382b Mon Sep 17 00:00:00 2001
From: Agnibho Mondal <mondal@agnibho.com>
Date: Sun, 10 Sep 2023 01:06:41 +0530
Subject: [PATCH] Added medical certificate

---
 config.py                     |   5 +-
 config/config.json            |   3 +-
 data/template/cert/index.html |  66 ++++++++++++++++
 data/template/cert/style.css  | 140 ++++++++++++++++++++++++++++++++++
 preset.py                     |   7 +-
 window.py                     |  29 ++++++-
 6 files changed, 244 insertions(+), 6 deletions(-)
 create mode 100644 data/template/cert/index.html
 create mode 100644 data/template/cert/style.css

diff --git a/config.py b/config.py
index 5179435..c2f70c1 100644
--- a/config.py
+++ b/config.py
@@ -29,9 +29,10 @@ default = {
         "prescriber_directory": "prescriber",
         "prescriber": "prescriber",
         "template_directory": "template",
-        "template": "default",
+        "template": "default_prescription",
         "preset_directory": "preset",
-        "preset_newline": "True"
+        "preset_newline": "True",
+        "preset_delimiter": ","
         }
 
 with open(config_file) as conf:
diff --git a/config/config.json b/config/config.json
index c18be77..73edfd2 100644
--- a/config/config.json
+++ b/config/config.json
@@ -7,5 +7,6 @@
     "template_directory": "template",
     "template": "default",
     "preset_directory": "preset",
-    "preset_newline": "True"
+    "preset_newline": "True",
+    "preset_delimiter": ","
 }
diff --git a/data/template/cert/index.html b/data/template/cert/index.html
new file mode 100644
index 0000000..347055b
--- /dev/null
+++ b/data/template/cert/index.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Prescription</title>
+    <link rel="stylesheet" href="style.css">
+  </head>
+  <body>
+    <div class="container">
+      <div class="header" style="position:fixed;top:0">
+        <table class="w100">
+          <tr>
+            <td class="w60">
+              <h1>{{prescriber.name}}</h1>
+              <h2>{{prescriber.qualification}}</h2>
+              <h3>{{prescriber.registration}}</h3>
+            </td>
+            <td class="w40">
+              <p class="formatted">{{prescriber.address}}</p>
+              <p>{% if prescriber.contact %}Contact: {{prescriber.contact}}{% endif %}</p>
+              <p class="formatted">{{prescriber.extra}}</p>
+            </td>
+          </tr>
+        </table>
+      </div>
+      <div class="content">
+        <table>
+          <thead><tr><td><div class="header-space"></div></td></tr></thead>
+          <tbody>
+            <tr>
+              <td>
+                <table class="patient">
+                  <tr>
+                    <td class="rtxt" colspan="3"><small>{% if id %}ID: {{id}}{% endif %}</small></td>
+                  </tr>
+                  <tr>
+                    <td><p><strong>Name:</strong> {{name}}</p></td>
+                    <td><p><strong>Age:</strong> {{age}}</p></td>
+                    <td><p><strong>Sex:</strong> {{sex}}</p></td>
+                  </tr>
+                  <tr>
+                    <td colspan="3"><small>{% if address %}Address: {{address}}{% endif %} {% if contact %}Contact: {{contact}}{% endif %}</small></td>
+                  </tr>
+                </table>
+                <table>
+                  <tr>
+                    <td>{% if diagnosis %}<strong>Provisional Diagnosis: {{diagnosis}}</strong>{% endif %}</td>
+                  </tr>
+                  <tr>
+                    <td><p class="formatted jtxt">{{extra}}</p></td>
+                  </tr>
+                </table>
+              </td>
+            </tr>
+          </tbody>
+          <tfoot><tr><td><div class="footer-space"></div></td></tr></tfoot>
+        </table>
+      </div>
+      <div class="footer">
+        <table class="w100">
+          <tr><td class="w75">{% if mode %}Consultation: {{mode}}{% endif %}<br>{% if daw %}Dispense as written{% endif %}</td><td class="w25"><br><br></td></tr>
+          <tr><td><p>{{date.strftime("%B %d, %Y %I:%M %p")}}</p></td><td class="sign"><p>Signature</p></td></tr>
+        </table>
+      </div>
+    </div>
+  </body>
+</html>
diff --git a/data/template/cert/style.css b/data/template/cert/style.css
new file mode 100644
index 0000000..03581b1
--- /dev/null
+++ b/data/template/cert/style.css
@@ -0,0 +1,140 @@
+table {
+	width: 100%;
+	border-collapse: collapse;
+}
+
+td {
+	vertical-align: top;
+}
+
+.container {
+	width: 95%;
+	margin-left: auto;
+	margin-right: auto;
+}
+
+.header, .footer {
+	width: 95%;
+	position: fixed;
+	left: 50%;
+	transform: translateX(-50%);
+	background: white;
+}
+.header {
+	top: 0;
+	border-bottom: 2px solid black;
+}
+
+.footer {
+	bottom: 0;
+	border-top: 2px solid black;
+}
+
+.header, .header-space {
+	height: 200px;
+}
+
+.footer, .footer-space {
+	height: 100px;
+}
+
+.patient {
+	border-bottom: 2px solid black;
+}
+
+.sign {
+	border-top: 2px solid black;
+}
+
+.formatted {
+	white-space: pre-wrap;
+	padding: 2px;
+}
+
+.ltxt {
+	text-align: left;
+}
+
+.rtxt {
+	text-align: right;
+}
+
+.ctxt {
+	text-align: center;
+}
+
+.jtxt {
+	text-align: justify;
+}
+
+.bordered {
+	border: 2px solid black;
+}
+
+.lbordered {
+	border-left: 2px dotted black;
+}
+
+.rbordered {
+	border-right: 2px dotted black;
+}
+
+.tbordered {
+	border-top: 2px solid black;
+}
+
+.bbordered {
+	border-bottom: 2px solid black;
+}
+
+.w0 {
+	width: 0%;
+}
+
+.w10 {
+	width: 10%;
+}
+
+.w20 {
+	width: 20%;
+}
+
+.w25 {
+	width: 25%;
+}
+
+.w30 {
+	width: 30%;
+}
+
+.w40 {
+	width: 40%;
+}
+
+.w50 {
+	width: 50%;
+}
+
+.w60 {
+	width: 60%;
+}
+
+.w70 {
+	width: 70%;
+}
+
+.w75 {
+	width: 75%;
+}
+
+.w80 {
+	width: 80%;
+}
+
+.w90 {
+	width: 90%;
+}
+
+.w100 {
+	width: 100%;
+}
diff --git a/preset.py b/preset.py
index e5e1f38..33fbdc3 100644
--- a/preset.py
+++ b/preset.py
@@ -6,6 +6,7 @@
 # You should have received a copy of the GNU General Public License along with MedScript. If not, see <https://www.gnu.org/licenses/>.
 
 import csv
+from config import config
 
 class Preset():
 
@@ -21,7 +22,7 @@ class Preset():
         try:
             buf={}
             with open(self.file, "r") as f:
-                reader=csv.reader(f)
+                reader=csv.reader(f, delimiter=config["preset_delimiter"])
                 if skip_first:
                     next(reader)
                 for row in reader:
@@ -30,4 +31,6 @@ class Preset():
                         buf[row[1].strip()]=row[1]
             self.data = buf | self.data
         except FileNotFoundError as e:
-            print(e)
+            print(self.file, e)
+        except IndexError as e:
+            print(self.file, e)
diff --git a/window.py b/window.py
index 1d40b81..b93b3be 100644
--- a/window.py
+++ b/window.py
@@ -116,6 +116,16 @@ class MainWindow(QMainWindow):
         self.viewbox.open(os.path.join(config["resource"], "help.html"))
         self.viewbox.show()
 
+    def insert_preset_extra(self):
+        try:
+            self.input_extra.insertPlainText(self.preset_extra.data[self.input_extra_preset.currentText()])
+        except KeyError:
+            self.input_extra.insertPlainText(self.input_extra_preset.currentText())
+        finally:
+            self.input_extra_preset.setCurrentIndex(-1)
+            if config["preset_newline"]:
+                self.input_extra.insertPlainText("\n")
+
     def insert_preset_note(self):
         try:
             self.input_note.insertPlainText(self.preset_note.data[self.input_note_preset.currentText()])
@@ -306,6 +316,7 @@ class MainWindow(QMainWindow):
         icon_render=QIcon(os.path.join(config["resource"], "icon_render.svg"))
         icon_refresh=QIcon(os.path.join(config["resource"], "icon_refresh.svg"))
 
+        self.preset_extra=Preset(os.path.join(config["preset_directory"], "certify.csv"))
         self.preset_note=Preset(os.path.join(config["preset_directory"], "note.csv"))
         self.preset_report=Preset(os.path.join(config["preset_directory"], "report.csv"))
         self.preset_advice=Preset(os.path.join(config["preset_directory"], "advice.csv"))
@@ -368,7 +379,10 @@ class MainWindow(QMainWindow):
         toolbar.addAction(action_render2)
         toolbar.addSeparator()
         self.input_template=QComboBox(self)
-        self.input_template.addItems(os.listdir(config["template_directory"]))
+        templates=os.listdir(config["template_directory"])
+        templates.remove(os.path.basename(config["template"]))
+        templates.insert(0, os.path.basename(config["template"]))
+        self.input_template.addItems(templates)
         toolbar.addWidget(self.input_template)
         spacer=QWidget(self)
         spacer.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
@@ -380,6 +394,7 @@ class MainWindow(QMainWindow):
 
         tab_info=QWidget(self)
         layout_info=QFormLayout(tab_info)
+        layout_info2=QHBoxLayout()
         self.input_date=QDateTimeEdit(self)
         self.input_date.setDisplayFormat("MMMM dd, yyyy hh:mm a")
         layout_info.addRow("Date", self.input_date)
@@ -400,6 +415,18 @@ class MainWindow(QMainWindow):
         self.input_diagnosis=QLineEdit(self)
         layout_info.addRow("Diagnosis", self.input_diagnosis)
         self.input_extra=QTextEdit(self)
+        self.input_extra_preset=QComboBox(self)
+        self.input_extra_preset.addItems(self.preset_extra.data.keys())
+        self.input_extra_preset.setCurrentIndex(-1)
+        self.input_extra_preset.setEditable(True)
+        self.input_extra_preset.completer().setCompletionMode(QCompleter.CompletionMode.PopupCompletion)
+        self.input_extra_preset.completer().setFilterMode(Qt.MatchFlag.MatchContains)
+        self.input_extra_preset.setPlaceholderText("Select a preset")
+        input_extra_preset_btn=QPushButton("Insert")
+        input_extra_preset_btn.clicked.connect(self.insert_preset_extra)
+        layout_info2.addWidget(self.input_extra_preset, 2)
+        layout_info2.addWidget(input_extra_preset_btn, 1)
+        layout_info.addRow("Certify", layout_info2)
         layout_info.addRow("Extra", self.input_extra)
         self.input_mode=QComboBox(self)
         self.input_mode.addItems(["In-Person", "Tele-Consultation", "Other"])
-- 
2.39.5