From: Harishankar Date: Wed, 1 Apr 2020 09:45:34 +0000 (+0530) Subject: Generate raised bills functionality completed X-Git-Url: https://harishankar.org/repos/?a=commitdiff_plain;h=ebe8c5c1a1ff2d63aca4d844887f39d763272eac;p=habeas.git Generate raised bills functionality completed Completed the basic functionality for generating bill in flat ODT format based on the template. --- diff --git a/src/habeas/GenerateRaisedBillsDialog.form b/src/habeas/GenerateRaisedBillsDialog.form new file mode 100644 index 0000000..3fc7e02 --- /dev/null +++ b/src/habeas/GenerateRaisedBillsDialog.form @@ -0,0 +1,97 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/habeas/GenerateRaisedBillsDialog.java b/src/habeas/GenerateRaisedBillsDialog.java new file mode 100644 index 0000000..2273353 --- /dev/null +++ b/src/habeas/GenerateRaisedBillsDialog.java @@ -0,0 +1,205 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package habeas; + +import java.util.ArrayList; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.filechooser.FileFilter; +import javax.swing.filechooser.FileNameExtensionFilter; + +/** + * + * @author hari + */ +public class GenerateRaisedBillsDialog extends javax.swing.JDialog { + + /** + * Creates new form GenerateRaisedBillsDialog + */ + public GenerateRaisedBillsDialog(java.awt.Frame parent, boolean modal) { + super(parent, modal); + initComponents(); + populateFields (); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jLabel1 = new javax.swing.JLabel(); + comboClients = new javax.swing.JComboBox<>(); + buttonGenerate = new javax.swing.JButton(); + buttonClose = new javax.swing.JButton(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + setTitle("Generate Raised Bills"); + setLocationByPlatform(true); + + jLabel1.setText("For client"); + + buttonGenerate.setMnemonic('g'); + buttonGenerate.setText("Generate"); + buttonGenerate.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonGenerateActionPerformed(evt); + } + }); + + buttonClose.setMnemonic('C'); + buttonClose.setText("Close"); + buttonClose.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonCloseActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 113, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(comboClients, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(buttonGenerate, javax.swing.GroupLayout.PREFERRED_SIZE, 121, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 28, Short.MAX_VALUE) + .addComponent(buttonClose, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(13, 13, 13) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1) + .addComponent(comboClients, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 45, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonGenerate) + .addComponent(buttonClose)) + .addContainerGap()) + ); + + pack(); + }// //GEN-END:initComponents + + private void buttonCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonCloseActionPerformed + // TODO add your handling code here: + dispose (); + }//GEN-LAST:event_buttonCloseActionPerformed + + private void buttonGenerateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonGenerateActionPerformed + // TODO add your handling code here: + DBItem selitem = (DBItem)comboClients.getSelectedItem(); + if (selitem == null) return; + ArrayList client = Utility.getClientDetails(selitem.getKey()); + if (client == null) { + JOptionPane.showMessageDialog(this, ERROR_CLIENT_DETAILS); + return; + } else if (client.isEmpty()) { + JOptionPane.showMessageDialog(this, ERROR_CLIENT_DETAILS); + return; + } + ArrayList bills = Utility.getRaisedBills(selitem.getKey()); + if (bills == null) { + JOptionPane.showMessageDialog(this, ERROR_RAISED_BILLS); + return; + } else if (bills.isEmpty()) { + JOptionPane.showMessageDialog(this, ERROR_RAISED_BILLS); + return; + } + + JFileChooser chooser = new JFileChooser (); + FileFilter filter = new FileNameExtensionFilter("Flat OpenDocument text", "fodt"); + chooser.setFileFilter(filter); + int r = chooser.showSaveDialog(this); + if (r == JFileChooser.APPROVE_OPTION) { + String filename = chooser.getSelectedFile().getAbsolutePath(); + if (!filename.endsWith(".fodt")) + filename = filename.concat(".fodt"); + + boolean rt = Utility.generateRaisedNoticesBill(filename, (String)client.get(0), + (String)client.get(1), (String)client.get(2), bills); + if (rt == false) + JOptionPane.showMessageDialog(this, ERROR_WRITING_FILE); + else + JOptionPane.showMessageDialog(this, SUCCESSFULLY_GENERATED_BILL); + } + }//GEN-LAST:event_buttonGenerateActionPerformed + private static final String ERROR_WRITING_FILE = "Error writing file"; + private static final String SUCCESSFULLY_GENERATED_BILL = "Successfully generated bill"; + private static final String ERROR_RAISED_BILLS = "Error getting raised " + + "bills or no raised bills found for this client"; + private static final String ERROR_CLIENT_DETAILS = "Error getting client details"; + + /** + * @param args the command line arguments + */ + public static void main(String args[]) { + /* Set the Nimbus look and feel */ + // + /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel. + * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html + */ + try { + for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { + if ("Nimbus".equals(info.getName())) { + javax.swing.UIManager.setLookAndFeel(info.getClassName()); + break; + } + } + } catch (ClassNotFoundException ex) { + java.util.logging.Logger.getLogger(GenerateRaisedBillsDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); + } catch (InstantiationException ex) { + java.util.logging.Logger.getLogger(GenerateRaisedBillsDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); + } catch (IllegalAccessException ex) { + java.util.logging.Logger.getLogger(GenerateRaisedBillsDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); + } catch (javax.swing.UnsupportedLookAndFeelException ex) { + java.util.logging.Logger.getLogger(GenerateRaisedBillsDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); + } + // + + /* Create and display the dialog */ + java.awt.EventQueue.invokeLater(new Runnable() { + public void run() { + GenerateRaisedBillsDialog dialog = new GenerateRaisedBillsDialog(new javax.swing.JFrame(), true); + dialog.addWindowListener(new java.awt.event.WindowAdapter() { + @Override + public void windowClosing(java.awt.event.WindowEvent e) { + System.exit(0); + } + }); + dialog.setVisible(true); + } + }); + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton buttonClose; + private javax.swing.JButton buttonGenerate; + private javax.swing.JComboBox comboClients; + private javax.swing.JLabel jLabel1; + // End of variables declaration//GEN-END:variables + + private void populateFields() { + comboClients.removeAllItems();; + ArrayList clients = Utility.getClientsNameAndId(); + if (clients == null) return; + for (int i = 0; i < clients.size(); i +=2) { + comboClients.addItem(new DBItem ((int)clients.get(i), (String)clients.get(i+1))); + } + + } +} diff --git a/src/habeas/Habeas.java b/src/habeas/Habeas.java index 6c24189..2bfb038 100644 --- a/src/habeas/Habeas.java +++ b/src/habeas/Habeas.java @@ -25,7 +25,7 @@ public class Habeas { Utility.retrieveStationerySettings(); try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { Logger.getLogger(Habeas.class.getName()).log(Level.SEVERE, null, ex); } diff --git a/src/habeas/MainFrame.form b/src/habeas/MainFrame.form index 0847aae..4545146 100644 --- a/src/habeas/MainFrame.form +++ b/src/habeas/MainFrame.form @@ -45,6 +45,17 @@ + + + + + + + + + + + diff --git a/src/habeas/MainFrame.java b/src/habeas/MainFrame.java index 865a403..f20df55 100644 --- a/src/habeas/MainFrame.java +++ b/src/habeas/MainFrame.java @@ -5,11 +5,11 @@ */ package habeas; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.logging.Level; -import java.util.logging.Logger; +import java.util.ArrayList; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.filechooser.FileFilter; +import javax.swing.filechooser.FileNameExtensionFilter; /** * @@ -39,6 +39,8 @@ public class MainFrame extends javax.swing.JFrame { menuLawyerNotices = new javax.swing.JMenu(); menuCreateNotice = new javax.swing.JMenuItem(); menuManageNotices = new javax.swing.JMenuItem(); + jSeparator1 = new javax.swing.JPopupMenu.Separator(); + menuGenerateRaisedBills = new javax.swing.JMenuItem(); menuSettings = new javax.swing.JMenu(); menuDatabaseSettings = new javax.swing.JMenuItem(); menuStationery = new javax.swing.JMenuItem(); @@ -81,6 +83,16 @@ public class MainFrame extends javax.swing.JFrame { } }); menuLawyerNotices.add(menuManageNotices); + menuLawyerNotices.add(jSeparator1); + + menuGenerateRaisedBills.setMnemonic('G'); + menuGenerateRaisedBills.setText("Generate Raised Bills..."); + menuGenerateRaisedBills.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + menuGenerateRaisedBillsActionPerformed(evt); + } + }); + menuLawyerNotices.add(menuGenerateRaisedBills); jMenuBar1.add(menuLawyerNotices); @@ -153,6 +165,18 @@ public class MainFrame extends javax.swing.JFrame { frm.setVisible(true); }//GEN-LAST:event_menuStationeryActionPerformed + private void menuGenerateRaisedBillsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuGenerateRaisedBillsActionPerformed + // TODO add your handling code here: + GenerateRaisedBillsDialog frm = new GenerateRaisedBillsDialog(this, true); + frm.setVisible(true); + + }//GEN-LAST:event_menuGenerateRaisedBillsActionPerformed + private static final String ERROR_RETRIEVING_RAISED_BILLS = "Error retrieving bills" + + " or no bills are raised at this time."; + private static final String FODT_EXT = "fodt"; + private static final String FLAT_OPENDOCUMENT_TEXT = "Flat OpenDocument text"; + private static final String ERROR_GENERATING = "Error generating"; + /** * @param args the command line arguments */ @@ -190,9 +214,11 @@ public class MainFrame extends javax.swing.JFrame { // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JMenuBar jMenuBar1; + private javax.swing.JPopupMenu.Separator jSeparator1; private javax.swing.JMenuItem menuClientMaster; private javax.swing.JMenuItem menuCreateNotice; private javax.swing.JMenuItem menuDatabaseSettings; + private javax.swing.JMenuItem menuGenerateRaisedBills; private javax.swing.JMenu menuLawyerNotices; private javax.swing.JMenuItem menuManageNotices; private javax.swing.JMenu menuMaster; diff --git a/src/habeas/Utility.java b/src/habeas/Utility.java index 0dc4235..bc99932 100644 --- a/src/habeas/Utility.java +++ b/src/habeas/Utility.java @@ -5,11 +5,20 @@ */ package habeas; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.prefs.Preferences; import java.sql.*; +import java.text.DateFormat; +import java.text.MessageFormat; +import java.text.SimpleDateFormat; +import java.util.Arrays; import java.util.logging.Level; import java.util.logging.Logger; +import jdk.dynalink.linker.support.Guards; /** * @@ -22,20 +31,23 @@ public class Utility { leftLetterHeader = left_header; rightLetterHeader = right_header; signatoryName = signatory; - Preferences.userRoot().put ("LeftHeader", left_header); - Preferences.userRoot().put ("RightHeader", right_header); - Preferences.userRoot().put ("Signatory", signatory); + Preferences myPrefs = Preferences.userRoot().node("org/harishankar/Habeas"); + myPrefs.put ("LeftHeader", left_header); + myPrefs.put ("RightHeader", right_header); + myPrefs.put ("Signatory", signatory); } static void retrieveStationerySettings () { - leftLetterHeader = Preferences.userRoot().get("LeftHeader", "Left Header"); - rightLetterHeader = Preferences.userRoot().get ("RightHeader", "Right Header"); - signatoryName = Preferences.userRoot().get ("Signatory", "Signatory Name"); + Preferences myPrefs = Preferences.userRoot().node ("org/harishankar/Habeas"); + leftLetterHeader = myPrefs.get("LeftHeader", "Left Header"); + rightLetterHeader = myPrefs.get ("RightHeader", "Right Header"); + signatoryName = myPrefs.get ("Signatory", "Signatory Name"); } static void saveConnectionURL(String text) { connectionURL = text; - Preferences.userRoot().put("ConnectionURL", text); + Preferences myPrefs = Preferences.userRoot().node ("org/harishankar/Habeas"); + myPrefs.put("ConnectionURL", text); } static ArrayList getClientDetails(int r) { @@ -391,6 +403,85 @@ public class Utility { } } + + static ArrayList getRaisedBills (int client_id) { + try { + Connection conn = DriverManager.getConnection(JDBC + connectionURL); + PreparedStatement st = conn.prepareStatement("SELECT ReferenceNumber, " + + "Description, BillDate, BillAmount" + + " FROM legalnotices WHERE BillStatus='RAISED' AND ClientId=?;"); + st.setInt (1, client_id); + + ResultSet rs = st.executeQuery (); + ArrayList bills = new ArrayList<>(); + while (rs.next()) { + bills.add (rs.getString("ReferenceNumber")); + bills.add (rs.getString("Description")); + bills.add (getValidDate(rs, "BillDate")); + bills.add (rs.getInt("BillAmount")); + } + conn.close(); + return bills; + + } catch (SQLException ex) { + Logger.getLogger(Utility.class.getName()).log(Level.SEVERE, null, ex); + return null; + } + + } + + static boolean generateRaisedNoticesBill(String fileName, String clientName, + String clientAddress, String contactPerson, ArrayList bills) { + if (bills == null) + return false; + try { + InputStream templ = Utility.class.getClassLoader().getResourceAsStream("resources/noticebill.template.fodt"); + if (templ == null) + return false; + DateFormat fmt = new SimpleDateFormat("dd MMM yyyy"); + String templateMain = new String (templ.readAllBytes()); + // this is for openoffice ODT - replace normal line breaks with the XML equivalent + String left = leftLetterHeader.replaceAll("\n", ""); + String right = rightLetterHeader.replaceAll("\n", ""); + String client_address = clientAddress.replaceAll ("\n", ""); + String rows = generateBillRows (bills); + System.out.println (rows); + + String strMain = MessageFormat.format(templateMain, + left, right, + fmt.format(new Date(System.currentTimeMillis())), + clientName, client_address, contactPerson, signatoryName, rows); + + FileOutputStream f = new FileOutputStream (fileName); + f.write (strMain.getBytes()); + f.close(); + return true; + } catch (IOException ex) { + Logger.getLogger(Utility.class.getName()).log(Level.SEVERE, null, ex); + return false; + } + } + + private static String generateBillRows(ArrayList bills) { + try { + InputStream tmpl = Utility.class.getClassLoader().getResourceAsStream("resources/tablerow.template.xml"); + String rowtpl = new String(tmpl.readAllBytes()); + + DateFormat fmt = new SimpleDateFormat("dd/MM/yyyy"); + + StringBuilder bldr = new StringBuilder (); + for (int i = 0; i < bills.size(); i += 4) { + String row = MessageFormat.format (rowtpl, (String)bills.get(i), + (String)bills.get(i+1), fmt.format((java.util.Date)bills.get(i+2)), + (int)bills.get(i+3)); + bldr.append(row); + } + return (bldr.toString()); + } catch (IOException ex) { + Logger.getLogger(Utility.class.getName()).log(Level.SEVERE, null, ex); + return null; + } + } public Utility () { } @@ -423,7 +514,8 @@ public class Utility { } public static void retrieveConnectionURL () { - connectionURL = Preferences.userRoot().get("ConnectionURL", "legaldb"); + Preferences myPrefs = Preferences.userRoot().node("org/harishankar/Habeas"); + connectionURL = myPrefs.get("ConnectionURL", "legaldb"); } } diff --git a/src/resources/noticebill.template.fodt b/src/resources/noticebill.template.fodt index 7ee76ac..255a001 100644 --- a/src/resources/noticebill.template.fodt +++ b/src/resources/noticebill.template.fodt @@ -1,28 +1,28 @@ - Harishankar2020-03-31T18:10:42.145558520LibreOffice/6.4.2.2$Linux_X86_64 LibreOffice_project/40$Build-22020-03-31T20:20:34.290574090HarishankarPT26M56S4 + Harishankar2020-04-01T12:35:54.6084487192020-04-01T15:03:02.307392512HarishankarPT9M49S9LibreOffice/6.4.2.2$Linux_X86_64 LibreOffice_project/40$Build-2 - 2727 + 4071 0 - 24211 - 8922 + 26074 + 10402 true false view2 - 3655 - 10012 + 18230 + 9294 0 - 2727 - 24209 - 11647 + 4071 + 26072 + 14471 0 1 false - 140 + 130 false false @@ -79,7 +79,7 @@ true true - 1334322 + 2162407 true false @@ -110,7 +110,7 @@ false false false - 1229947 + 1737415 false false false @@ -132,15 +132,15 @@ - + - + @@ -183,21 +183,15 @@ - + - - - - - - - - + + @@ -254,6 +248,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -262,6 +322,9 @@ + + + @@ -271,69 +334,115 @@ + + + - - + + - + - + - + - + + + + - + + + - + + + - + + + - + + + - + - + - - + - + - - + + + - - + + + - - + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + - + @@ -342,13 +451,14 @@ - + + - {Left Header} + {0} - {Right Header} + {1} @@ -366,39 +476,38 @@ - {Date} + {2} To: - {Client Name}{Client Address} - Sir/Madam, - SUB: PENDING BILLS FOR LEGAL NOTICES - With reference to the above, please find below the details of the pending bills: - + {5}{3}{4} + Sir/Madam, + SUB: BILLS FOR LEGAL NOTICES + - + - Reference Number + Reference No - Description + Description - Bill Date + Bill Date - Amount + Bill Amount - {Bill Table Row} + {7} - - Attaching the copies of the notices along with postal acknowledgement. I request you to kindly clear the same at your earliest convenience. - Thanking you, - Yours Truly, - - {Signatory Name} + + I request you to kindly clear the same at your earliest convenience. Copy of the referred notices with the postal acknowledgement/POD are attached for your kind reference. + Thanking you, + Yours Truly, + + {6} \ No newline at end of file diff --git a/src/resources/tablerow.template.xml b/src/resources/tablerow.template.xml index 62f9ec8..55364ce 100644 --- a/src/resources/tablerow.template.xml +++ b/src/resources/tablerow.template.xml @@ -1,14 +1,14 @@ - + - {Reference Number} + {0} - {Description} + {1} - {Bill Date} + {2} - {Bill Amount} + {3} - + \ No newline at end of file