--- /dev/null
+@import "../js/vendor/tabulator/css/tabulator_site.css";
+@import "../js/vendor/slimselect/slimselect.css";
+@import "../js/vendor/flatpickr/flatpickr.min.css";
+@import "../js/vendor/flatpickr/themes/airbnb.css";
+@import "icons.css";
+@import "theme.css";
\ No newline at end of file
</div>
<div class="container row">
<div class="cell" style="width: 600px;">
- <div class="" >
-
<label for="invoicebooking_description" class="label">Beschreibung</label>
<textarea class="input border data_invoicebooking richeditarea" style="height: 200px;" data-id="" data-column="description" data-table="bookings" id="invoicebooking_description" name="invoicebooking_description"></textarea>
- </div>
-
</div>
</div>
</div>
--- /dev/null
+<div id="dlgMailTemplate" class="modal" >
+ <div class="modal-content animate-opacity card-4" >
+ <header>
+ <div class="bar-item SubHeadTitle">Mail Vorlage</div>
+ <span onclick="myapp.closeDialog('MailTemplate');"
+ class="button display-topright">×</span>
+ </header>
+ <div class="container padding">
+ <form id="frm_mailtemplate">
+ <input type="hidden" data-id="" class="data_mailtemplate " data-column="id" data-table="mailtemplates" id="mailtemplates_id" name="ident_invoicebooking_id" value="">
+ <input type="hidden" data-id="" class="data_mailtemplate "data-column="id_addresses" data-table="mailtemplates" id="mailtemplates_id_addresses" name="mailtemplates_id_addresses" value="">
+ <div class="row">
+ <div class="cell" style="width: 600px;">
+ <div class="container row">
+ <div class="cell" style="width: 250px;">
+ <div class="">
+ <label for="mailtemplates_templatename" class="label">Name</label>
+ <input type="text" data-id="" data-column="quantity" data-table="mailtemplates" class="input data_mailtemplate border id="mailtemplates_quantity" name="mailtemplates_quantity"/>
+ </div>
+ </div>
+
+ </div>
+ <div class="container row">
+ <div class="cell" style="width: 600px;">
+ <div class="">
+ <label for="mailtemplates_subject" class="label">Betreff</label>
+
+ <input type="text" data-id="" data-column="subject" data-table="mailtemplates" class="input border text data_mailtemplate" id="mailtemplates_subject" name="mailtemplates_subject"/>
+
+ </div>
+
+ </div>
+ </div>
+ <div class="container row">
+ <div class="cell" style="width: 600px;">
+ <div class="" >
+
+ <label for="mailtemplates_body" class="label">Nachricht</label>
+ <textarea class="input border data_mailtemplate richeditarea" style="height: 300px;" data-id="" data-column="body" data-table="mailtemplates" id="mailtemplates_body" name="mailtemplates_body"></textarea>
+ </div>
+
+ </div>
+ </div>
+ </div>
+
+ </div>
+ </form>
+ </div>
+ <footer class="container right-align padding-16">
+ <button class="button theme-light margin-right border" onclick="myapp.closeDialog('MailTemplate');"><span class="icon-close" style="font-size: 16px;"></span>Abbrechen</button>
+ <button class="button moduletoolbar margin-right" id="btnCloseBooking" onclick="addresse.savemailTemplate();"><span class="icon-save" style="font-size: 16px;"></span>Speichern</button>
+ </footer>
+ </div>
+</div>
\ No newline at end of file
--- /dev/null
+<div style="display: none;">
+ <form id="frm_fileupload">
+ <input type="hidden" id="fileupload_folder" name="fileupload_folder" value=""/>
+ <input type="file" id="fileupload_file" name="fileupload_file" accept="" value=""/>
+ </form>
+</div>
\ No newline at end of file
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta content="width=device-width, initial-scale=1.0" name="viewport">
- <link href="js/vendor/tabulator/css/tabulator_site.css?v=6" rel="stylesheet">
- <link href="js/vendor/slimselect/slimselect.css?v=6" rel="stylesheet">
- <link href="js/vendor/flatpickr/flatpickr.min.css?v=6" rel="stylesheet">
- <link href="js/vendor/flatpickr/themes/airbnb.css?v=6" rel="stylesheet">
- <link href="css/icons.css?v=6" rel="stylesheet">
- <link href="css/theme.css?v=6" rel="stylesheet">
+ <link href="css/app.css?v=6" rel="stylesheet">
<title>
Invoice Journal
</title>
<div id="dialogs">
</div>
+
<script src="js/vendor/tabulator/js/tabulator.js?v=6" type="text/javascript"></script>
<script src="js/vendor/moment/moment-with-locales.min.js?v=6" type="text/javascript"></script>
<script src="js/vendor/slimselect/slimselect.min.js?v=6" type="text/javascript"></script>
<script src="js/global/renderer.js?v=6" type="text/javascript"></script>
<script src="js/global/sqlite.js?v=6" type="text/javascript"></script>
<script src="js/global/report.js?v=6" type="text/javascript"></script>
+ <script src="js/global/email.js?v=6" type="text/javascript"></script>
<script src="js/modules/addresses.js?v=6" type="text/javascript"></script>
<script src="js/modules/bookings.js?v=6" type="text/javascript"></script>
<script src="js/modules/booking.js?v=6" type="text/javascript"></script>
<script src="js/modules/transactions.js?v=6" type="text/javascript"></script>
<script src="js/modules/settings.js?v=6" type="text/javascript"></script>
<script src="js/modules/datasets.js?v=6" type="text/javascript"></script>
- <script src="js/modules/templates.js?v=6" type="text/javascript"></script>
+ <script src="js/modules/templates.js?v=6" type="text/javascript"></script>
</div>
</body>
</html>
--- /dev/null
+//let version=new Date().toISOString().substring(0,10);
+// require(__dirname + '/js/vendor/tabulator/js/tabulator.js');
+// require(__dirname + '/js/vendor/moment/moment-with-locales.min.js');
+// require(__dirname + '/js/vendor/slimselect/slimselect.min.js');
+// require(__dirname + '/js/vendor/flatpickr/flatpickr.min.js');
+// require(__dirname + '/js/vendor/flatpickr/l10n/de.js');
+// require(__dirname + '/js/vendor/tinymce/js/tinymce/tinymce.min.js');
+// require(__dirname + '/js/vendor/mustache/mustache.min.js');
+// require(__dirname + '/js/global/request.js');
+// require(__dirname + '/js/global/myapp.js');
+// require(__dirname + '/js/dataform.js');
+// require(__dirname + '/js/timecalc.js');
+// require(__dirname + '/js/global/renderer.js');
+// require(__dirname + '/js/global/sqlite.js');
+// require(__dirname + '/js/global/report.js');
+// require(__dirname + '/js/modules/addresses.js');
+// require(__dirname + '/js/modules/bookings.js');
+// require(__dirname + '/js/modules/booking.js');
+// require(__dirname + '/js/modules/index.js');
+// require(__dirname + '/js/modules/invoice.js');
+// require(__dirname + '/js/modules/invoices.js');
+// require(__dirname + '/js/modules/offer.js');
+// require(__dirname + '/js/modules/offers.js');
+// require(__dirname + '/js/modules/product.js');
+// require(__dirname + '/js/modules/products.js');
+// require(__dirname + '/js/modules/transaction.js');
+// require(__dirname + '/js/modules/transactions.js');
+// require(__dirname + '/js/modules/settings.js');
+// require(__dirname + '/js/modules/datasets.js');
+// require(__dirname + '/js/modules/templates.js');
\ No newline at end of file
// }
if (field.tagName == "TEXTAREA" ){
if (field.classList.contains("richeditarea")){
- flds[field.dataset.table][field.dataset.column] = tinymce.get(field.id).getContent();
+ flds[field.dataset.table][field.dataset.column] = tinymce.get(field.id).getContent().replace(/'/g,"''");
} else {
flds[field.dataset.table][field.dataset.column] = field.innerHTML;
}
var frm = document.querySelectorAll('.data_'+ dataclass);
//console.log("frmdata",frm);
if (data){
+
for (var f in frm){
var tblid = null;
- //console.log("ID",frm[f].id);
+ console.log("ID",frm[f].id);
if (frm[f].id){
tblid = frm[f].id.replace(dataclass + "_","");
frm[f].dataset.id=data['id'];
}
},
setNumber(numdata,decimals){
- console.log("Number in ",numdata);
+ //console.log("Number in ",numdata);
if (numdata == null || numdata == ''){
return "";
}
numdata = parseFloat(numdata).toFixed(decimals).toString();
}
numdata.toString().replace(/./,',');
- console.log("Number out ",numdata);
+ //console.log("Number out ",numdata);
return numdata;
},
fillselectlist: function(obj,listdata,vidcol,vvalcol){
openthunderbird: function(maildata){
let args =[];
let mailcfg =[]
- mailcfg.push("to='"+ data.to+"'");
- mailcfg.push("from='"+ data.from +"'");
- mailcfg.push("subject='"+ data.from +"'");
+ mailcfg.push("to='"+ maildata.to+"'");
+ mailcfg.push("from='"+ maildata.from +"'");
+ mailcfg.push("subject='"+ maildata.subject +"'");
mailcfg.push("format=1"); // format => 1=HTML, 2=text
- mailcfg.push("body='"+ data.body+"'");
- mailcfg.push("attachment='"+ data.attachments.join(',')+'"');
- args.push("-compose");
- args.push(mailcfg.join(","));
-
+ mailcfg.push("body='"+ maildata.body+"'");
+ mailcfg.push("attachment='"+ maildata.attachments.join(',').replace(/\//g,"\\")+"'");
+ args.push("-compose",mailcfg.join(","))
+ //);
+ //process.stderr.write("Email:\n-----\n"+preferences.global.mailapp + " " + args.join(" ")+"\n-----\n");
const mailappout = spawn(preferences.global.mailapp, args);
mailappout.stdout.on('data', (data) => {
mailappout.on('close', (code) => {
console.log(`pdfout: child process exited with code ${code}`);
- if (code == 0){
- console.log("Copy",report.tmpoutput,"to",report.output);
- if (fs.existsSync(report.output)){
- fs.unlinkSync(report.output);
- }
- fs.copyFileSync(report.tmpoutput,report.output);
- report.callback({"file":report.reportfile});
- }
+ // if (code == 0){
+ // console.log("Copy",report.tmpoutput,"to",report.output);
+ // if (fs.existsSync(report.output)){
+ // fs.unlinkSync(report.output);
+ // }
+ // fs.copyFileSync(report.tmpoutput,report.output);
+ // report.callback({"file":report.reportfile});
+ // }
});
}
if (multiselect == true){
props.push('multiSelections');
}
+ console.log(dialog);
+ //dialog.send('open-file-dialog');
return dialog.showOpenDialog({title: dlgtitle,defaultPath: lastpath, filters: filefilters, properties: props });
},
selectdir: function(dlgtitle,lastpath){
}
},
getApplicationPath: function(){
+ console.log(__dirname);
let apath = path.dirname(__dirname);
return apath;
+ },
+ backupfile: function(backupfile,backuppath){
+ let bname = path.basename(backupfile);
+ let ext = path.extname(backupfile);
+ let fname = bname.substring(0,bname.length - ext.length);
+ fs.copyFileSync(backupfile,backuppath + '/' + fname + '_' +moment().format('YYYYMMDDhhmm') + ext);
}
}
\ No newline at end of file
let db = {
dbh: null,
connect: function(dbfile){
+ if (fs.existsSync(dbfile)){
+ usersystem.backupfile(dbfile,path.dirname(dbfile) + '/backup')
+ }
if (db.dbh != null){
db.disconnect();
}
let addresses = {
tbl: null,
tblselector: null,
+ tblcontacts: null,
+ tblmailtemplates: null,
current_id: null,
viewpanel: function(){
this.gettbldata();
{title: "Name", field: "receipient", resizable: false},
]
});
+ addresses.tbl = new Tabulator("#tbl_addresses",{
+ headerFilterPlaceholder: "filter...",
+ height: "calc(100vh - 60px)",
+ layout: "fitDataStretch",
+ selectable: 1,
+ rowClick:function(e, row){
+ console.log("Filter selected");
+ let fsel = addresses.tbl.getSelectedData();
+ console.log(fsel);
+ addresses.current_id = fsel[0].id;
+ addresses.edit(fsel[0].id);
+ //invoices.getsums(fsel);
+ },
+ rowContext:function(e, row){ e.preventDefault(); },
+ columns: [
+ {title: "Name", field: "receipient", resizable: false},
+ ]
+ });
+ addresses.tblcontacts = new Tabulator("#tbl_contacts",{
+ //headerFilterPlaceholder: "filter...",
+ height: "400px",
+ layout: "fitColumns",
+ selectable: 1,
+ rowContext:function(e, row){ e.preventDefault(); },
+ columns: [
+ {title: "Surname", field: "surname"},
+ {title: "Prename", field: "prename"},
+ {title: "E-Mail", field: "email"},
+ {title: "Telefon", field: "phone"},
+ {title: "Position", field: "job"}
+ ]
+ });
+ addresses.tblmailtemplates = new Tabulator("#tbl_mailtemplates",{
+ //headerFilterPlaceholder: "filter...",
+ height: "calc(100vh - 560px)",
+ layout: "fitColumns",
+ selectable: 1,
+ rowContext:function(e, row){ e.preventDefault(); },
+ columns: [
+ {title: "Name", field: "templatename" ,width: 300},
+ {title: "Sender", field: "sendermail", width: 200},
+ {title: "Betreff", field: "subject"},
+ ]
+ });
if (addresses.tblselector == null){
- addresses.initSelector();
- }
+ if (document.getElementById("#tbl_addressselect")){
+ addresses.initSelector();
+ }
+ }
+ myapp.loaddialog("confirm").then(result => {
+
+ });
},
initSelector: function(){
+
addresses.tblselector = new Tabulator("#tbl_addressselect",{
headerFilterPlaceholder: "Filter...",
height: "400px",
selectable: 1,
rowContext:function(e, row){ e.preventDefault(); },
columns: [
- {title:"Name", field:"receipient",input: "editor"},
+ {title:"Name", field:"receipient",headerFilter:"input"},
{title: "Adresse",field: "address" },
{title: "PLZ", field: "zip" },
{title: "Ort",field: "city"},
]
});
},
- gettbldata: function(){
+ gettbldata: function(idsel){
+
db.queryarray("select id,receipient from addresses order by receipient").then(data => {
- addresses.tbl.setData(data);
+ addresses.tbl.setData(data).then(res => {
+ if (idsel){
+ addresses.tbl.selectRow(idsel);
+ }
+ });
});
// postData({ "get":"addresslist;","dbschema":"dks"}).then(data => {
},
edit: function (selid){
addresses.current_id = selid;
+ dataform.cleanform('addresses');
db.query("select * from addresses where id='"+selid+"';").then(data => {
- dataform.fillform('addresses',data,selid,null);
+ console.log("Address Data:",data);
+ dataform.fillform('addresses',{},data);
})
// postData({"get":"addresslist","dbschema":"dks","id":selid}).then(data => {
// });
},
- add:function(){
- let datafields = {"ins":"addresses"};
- postData({"fn":"add_address","dbschema":"dks"}).then(data => {
- addresses.gettbldata();
+ add:function(){
+ db.newuuid().then(newid => {
+ db.query("select count(*) as cnt from addresses").then(adrcnt => {
+ let clnum=moment().format('YYMM') + timecalc.lpad(adrcnt.cnt,4,'0');
+ console.log("New addresse ID",newid.id);
+ db.execAsync("INSERT INTO addresses (id,clientnumber,receipient) VALUES ('"+newid.id+"','"+ clnum+"','Neue Addresse');").then( res =>{
+ addresses.gettbldata(newid.id);
+ addresses.current_id = fsel[0].id;
+ addresses.edit(fsel[0].id);
+ });
+ });
});
},
confirmremove: function(){
var sel = addresses.tbl.getSelectedData();
- delcallback = addresses.remove;
+ //delcallback = ;
if (sel[0]) {
- addresses.current_id = sel[0].id;
- document.getElementById("dlgdeleterow").style.display = 'block';
+ myapp.confirm("Addresse löschen","Sind Sie Sicher dass Sie die Adresse löschen möchten?","Löschen","Abbrechen","addresses.remove();");
+ // document.getElementById("btndlgdeleterowok").setAttribute("onclick","invoices.remove();");
+ // document.getElementById("dlgdeleterow").style.display = 'block';
}
},
-
remove: function(data){
- req.reqdata({"del":"addresses","id":addresses.current_id},addresses.afterremove);
- //table.selection = null,
- delcallback = null;
-
- },
- afteremove: function(data){
- addresses.gettbldata();
- document.getElementById("dlgdeleterow").style.display = 'none';
+ var sel = addresses.tbl.getSelectedData();
+ db.execAsync("DELETE FROM addresses where id='"+sel[0].id+"';").then(res => {
+ addresses.tbl.deselectRow(sel[0].id);
+ addresses.gettbldata();
+ });
},
duplicate: function(){
viewpanel: function(){
myapp.viewpanel('bookings');
},
- inittable: function(){
+ init: function(){
bookings.tbl = new Tabulator("#tbl_bookings",{
headerFilterPlaceholder: "filter...",
height: "calc(100vh - 56px)",
{title: "Brutto", field: "grossamount",headerSort: false, formatter:"money",hozAlign:"right", formatterParams:{ decimal:",", thousand:".", symbol:"€", symbolAfter:"p", precision:2}},
]
});
+ bookings.gettbldata
},
gettbldata: function(){
// db.querryarray("SELECT bookings.id, id_invoices,id_products,producttype,sku, COALESCE(bookings.quantity, 1) AS quantity, COALESCE(bookings.unitamount, 0.0) AS unitamount, unit,name,description,taxpercent,taxpercent AS vatpercent,taxamount,netamount,bookings.netamount + bookings.taxamount AS grossamount, (('<span style=\"font-weight: bold\">' || COALESCE(name, '')) || '</span><br/>') || COALESCE(description, '') AS displayitem FROM bookings where id_invoice='"+ invoice.current_id+"';").then(data => {
+const { fstat } = require("fs");
+
let invoice = {
current_id: null,
bookingtbl: null,
db.query("SELECT inv.*,sum(bk.netamount) AS netamount,sum(bk.taxamount) AS vatamount,sum(bk.netamount + bk.taxamount) AS grossamount FROM invoices inv JOIN bookings bk ON (inv.id = bk.id_invoices) WHERE inv.id='"+id+"' GROUP BY inv.id;").then(data => {
console.log("invoicedata",data);
dataform.fillform('invoices',invoice.selects,data);
- invoice.hasPDF(data.pdffile);
+ if (data.pdffile){
+ invoice.hasPDF(data.pdffile);
+ }
invoice.getBookingData();
myapp.viewpanel('invoice');
dataform.setValue(document.getElementById("invoices_deadlinedays"),dldate.diff(invdate,'days'));
},
setReference(){
- let invtype = document.getElementById("invoices_invoicetype").value;
+ let invtype = invoice.selects["invoices_invoicetype"].selected();
if ((invtype == 'invoice-out') || (invtype == 'creditnote-out')){
- document.getElementById("invoices_reference").value = invoice.getNewReference(document.getElementById("invoices_invoicedate").value);
+ console.log('Set ref');
+ let newref= invoice.getNewReference(document.getElementById("invoices_invoicedate").value);
+ document.getElementById("invoices_reference").value = newref;
dataform.savefield(document.getElementById("invoices_reference"));
document.getElementById("invoices_businessyear").value=moment(document.getElementById("invoices_invoicedate").value).format("YYYY");
dataform.savefield(document.getElementById("invoices_businessyear"));
// }
},
getNewReference(strdate){
- preferences.defaultdata.invoicesequence = parseInt(preferences.defaultdata.invoicesequence) + 1;
- myapp.setpref('invoicesequence',preferences.defaultdata.invoicesequence);
- let newref = moment(strdate).format('YYYYMMDD') + '-' + timecalc.lpad(preferences.defaultdata.invoicesequence,4,'0');
- console.log(newref);
+ let newref=document.getElementById("invoices_reference").value;
+ let invtype=invoice.selects["invoices_invoicetype"].selected();
+ let invstatus=invoice.selects["invoices_status"].selected();
+ let re = /\d\d\d\d\d\d\d\d-\d\d\d\d/;
+ console.log("Reference",invtype,invstatus,newref);
+ if ((invtype == "invoice-out" || invtype == "creditnote-out") &&
+ (invstatus == "preparation" || invstatus == "planned")){
+ console.log("TEST",re.test(newref));
+ if (re.test(newref)){
+ newref=moment(strdate).format('YYYYMMDD') + '-' + newref.substring(newref.length - 4 ,newref.length);
+ } else {
+ preferences.defaultdata.invoicesequence = parseInt(preferences.defaultdata.invoicesequence) + 1;
+ myapp.setpref('invoicesequence',preferences.defaultdata.invoicesequence);
+ newref = moment(strdate).format('YYYYMMDD') + '-' + timecalc.lpad(preferences.defaultdata.invoicesequence,4,'0');
+ }
+ }
+
+ console.log("new Ref",newref);
return newref;
},
calculate: function(){
if (qu){ qu = parseFloat(qu);} else {qu = 1;}
let price = document.getElementById("invoicebooking_unitamount").value;
if (price){ price = parseFloat(price).toFixed(2);} else {price = 0.0;}
- let vatpercent = null;
let vatamount = null;
let grossamount = null;
console.log(qu + " * "+ price);
vatamount = ((price * (vatpercent/100)).toFixed(2) * qu).toFixed(2);
console.log("VAT:" + vatamount);
}
- if (invtype == "invoice-in"|| invtype == "creditnote-in"){
+ if (invtype != "invoice-out" && invtype != "creditnote-out"){
vatamount = document.getElementById("invoicebooking_taxamount").value;
+ console.log("vat as amount",vatamount)
if (vatamount){ vatamount = parseFloat(vatamount).toFixed(2);} else {vatamount = 0.0;}
}
dataform.setValue(document.getElementById("invoicebooking_taxamount"),vatamount);
if (obj.value == "payed" ){
console.log("Set invoice payed!");
//document.getElementById
+ document.getElementById("invoices_payedamount").value=invoice.getSumGrossAmount();
+ dataform.savefield(document.getElementById("invoices_payedamount"));
+ } else {
+ document.getElementById("invoices_payedamount").value="";
+ dataform.savefield(document.getElementById("invoices_payedamount"));
}
},
changedInvoicedate: function(){
- let direction = document.getElementById("invoices_direction" ).value
- if (direction == "out"){
+ let invtype = invoice.selects["invoices_invoicetype"].selected();
+ if (invoicetype == "invoice-out"){
console.log("Change Reference!");
}
},
changedType: function(isinit){
- let invtype = document.getElementById("invoices_invoicetype").value;
- let status = document.getElementById("invoices_status").value;
+ let invtype = invoice.selects["invoices_invoicetype"].selected();
+ let status = invoice.selects["invoices_status"].selected();
let restatus = /[planned|preparation]/;
console.log("Status valid:" +restatus.test(status));
+ if (invtype == "invoice-out" || invtype == "creditnote-out"){
+ document.getElementById("invoices_reference").value=invoice.getNewReference(document.getElementById("invoices_invoicedate").value);
+ document.getElementById("row_invoicetemplate").style.display = 'block';
+ } else {
+ document.getElementById("row_invoicetemplate").style.display = 'none';
+ }
if (invtype == "invoice-out"){
if (restatus.test(status)){
console.log("can create");
document.getElementById("btnSendEmail").style.display = 'none';
console.log("can not create");
}
- document.getElementById("bookings_taxpercent").style.display = 'block';
+ document.getElementById("invoicebooking_taxpercent").style.display = 'block';
//document.getElementById("bookings_vatamount").style.display = 'none';
- document.getElementById("btnAddProduct").style.display = 'block';
+ //document.getElementById("btnAddProduct").style.display = 'block';
//document.getElementById("pnlCatalog").style.display = 'block';
}
- if (direction == "invoice-in"){
+ if (invtype == "invoice-in"){
document.getElementById("btnCreateInvoice").style.display = 'none';
document.getElementById("btnSendEmail").style.display = 'none';
- document.getElementById("bookings_taxpercent").style.display = 'none';
+ document.getElementById("invoicebooking_taxpercent").style.display = 'none';
//document.getElementById("bookings_vatamount").style.display = 'block';
- document.getElementById("bookings_taxamount").style.display = 'block';
- document.getElementById("btnAddProduct").style.display = 'none';
+ document.getElementById("invoicebooking_taxamount").style.display = 'block';
+ //document.getElementById("btnAddProduct").style.display = 'none';
//document.getElementById("pnlCatalog").style.display = 'none';
}
console.log("Init or not" + isinit);
document.getElementById("invoices_businessyear").value;
console.log("invoice.openPDF", document.getElementById("invoices_pdffile").value);
report.open('invoice', document.getElementById("invoices_pdffile").value);
+
//location.href=api + 'report.cgi?open=' + encodeURIComponent(document.getElementById("invoices_pdffile").value);
}
},
sendEmail: function(){
-
+
+ email.openthunderbird()
},
importPDF: function(){
-
- document.getElementById("invfile_folder").value="invoices/"+document.getElementById("invoices_businessyear-").value;
- document.getElementById("invfile_file").click();
+ //document.getElementById("invfile_folder").value=;
+ // var file = ;
+ usersystem.selectfile("PDF importieren","",[{ name: 'PDF', extensions: ['pdf'] }]).then(file => {
+ console.log(file);
+ });
+ // console.log("imported file:",file);
+ // if (file){
+ // fs.copyFileSync(file,preferences.global.currentdataset.datapath + '/invoice/' + document.getElementById("invoices_businessyear").value + '/' + path.basename(file));
+ // document.getElementById("invoices_pdffile").value = document.getElementById("invoices_businessyear").value + '/' + path.basename(file);
+ // dataform.savefield(document.getElementById("invoices_pdffile"));
+ // invoice.hasPDF();
+ // }
+ //document.getElementById("invfile_file").click();
},
afterFileUpload: function(data){
console.log(data);
});
},
- confirmremoveBooking: function(){
+ confirmRemoveBooking: function(){
let sel = invoice.bookingtbl.getSelectedData();
if (sel[0]){
- myapp.confirm("Buchung löschen?","Sind Sie sicher dass sie die ausgewählte(n) Buchunge(n) löschen möchten?","Löschen","Abbrechen",'invoice.removeBookings();');
+ myapp.confirm("Buchung löschen?","Sind Sie sicher dass sie die ausgewählte(n) Buchunge(n) löschen möchten?","Löschen","Abbrechen",'invoice.removeBooking();');
}
},
removeBooking: function(){
},
sendEmail: function(){
+
+ db.query("select * from addresses where id='"+ document.getElementById("invoices_id_accounts").value +"';").then(data => {
+ let invref = document.getElementById("invoices_reference").value;
+ let mdata = {};
+ mdata["from"] = preferences.defaultdata.email;
+ mdata["to"] = data.email;
+ mdata["subject"] = 'Facture No.' + invref;
+ mdata["body"] = 'Bonjour,<br/><br/>en annexe vous trouvez la facture ' + invref;
+ mdata.attachments = [preferences.global.currentdataset.datapath + '/invoice/' + document.getElementById("invoices_pdffile").value]
+ email.openthunderbird(mdata);
+ });
+ },
+ getSumGrossAmount(){
+ let xd = invoice.bookingtbl.getData();
+ let sum=0;
+ for (var d in xd){
+ sum += xd[d].grossamount;
+ }
+ return sum.toFixed(2);
}
}
let cyear = moment(new Date()).format('YYYY');
invoices.tbl = new Tabulator("#tbl_invoices",{
initialHeaderFilter:[
- {field:"invoicedate", value: cyear}
+ {field:"invoicedate", value: cyear},
+ {field:"businessyear", value: cyear}
],
headerFilterPlaceholder: "filter...",
height: "calc(100vh - 60px)",
selectable: 1,
rowContext:function(e, row){ e.preventDefault(); },
columns: [
+ {title:"GJahr", field:"businessyear",headerFilter:"input",width: 80},
{title:"Datum", field:"invoicedate",headerFilter:"input",width: 100,formatter:"datetime",headerSort:true,formatterParams:{inputFormat:"YYYY-MM-DD",outputFormat:"DD.MM.YYYY",invalidPlaceholder:""}},
{title: "Typ", field: "invoicetype",headerFilter:"select",width: 180, headerFilterParams:{values:headerinvtypes},formatter:function(cell, formatterParams){ var value = cell.getValue(); if (value){ return "<span class="+ invtypes[value].class+">" + invtypes[value].text + "</span>" } return ""; } },
{title: "Konto", field: "accountname",headerFilter:"input",width: 300},
let appcfg
function createWindow () {
+ makeSingleInstance()
//appcfg = localcfg();
let ua = app.getName() + '/' + app.getVersion() + '-' + os.type() + '/' + os.release() + '/' + os.arch
mainWindow = new BrowserWindow({
icon: __dirname + '/img/invoicejournal.png',
minWidth: 1260,
minHeight: 720,
- title: "POT",
+ title: "Invoice Jounral",
backgroundColor: "#fff",
webPreferences: {
nodeIntegration: true,
worldSafeExecuteJavaScript: true,
defaultEncoding: 'UTF-8',
- enableRemoteModule: true,
+ //enableRemoteModule: true,
webviewTag: true
}
})
})
- mainWindow.loadFile(__dirname + "/index.html");
+ //mainWindow.loadFile(__dirname + "/index.html")
+ mainWindow.loadURL(path.join('file://', __dirname, '/index.html'))
mainWindow.setMenu(null)
mainWindow.maximize()
}
+
+function makeSingleInstance () {
+ if (process.mas) return
+
+ app.requestSingleInstanceLock()
+
+ app.on('second-instance', () => {
+ if (mainWindow) {
+ if (mainWindow.isMinimized()) mainWindow.restore()
+ mainWindow.focus()
+ }
+ })
+}
// function localcfg(){
// var data = null;
// if (os.platform() == "darwin"){
{
"name": "InvoiceJournal",
- "version": "1.0.0",
+ "version": "1.0.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
{
"name": "InvoiceJournal",
- "version":"1.0.1",
+ "version": "1.0.1",
"description": "Rechnungs Programm",
"main": "main.js",
"scripts": {
"author": "DKS S.à r.l.",
"license": "UNLICENSED",
"devDependencies": {
+ "asar": "^3.0.3",
"electron": "^10.1.1",
"electron-packager": "^15.1.0"
},
<button class="bar-item toolbarbtn" onclick="index.viewpanel();"><span class="icon-back" style="font-size: 16px;"></span>zurück</button>
<div class="bar-item PageHeadTitle">
Adressen
- </div><button class="bar-item toolbarbtn right" onclick="addresses.confirmremove();"><span class="icon-remove" style="font-size: 16px;"></span>löschen</button> <button class="bar-item toolbarbtn right" onclick=
+ </div><button class="bar-item toolbarbtn right" onclick="addresses.confirmremove();"><span class="icon-trash" style="font-size: 16px;"></span>löschen</button> <button class="bar-item toolbarbtn right" onclick=
"addresses.duplicate();"><span class="icon-duplicate" style="font-size: 16px;"></span>dupizieren</button> <!-- <button class="bar-item toolbarbtn right" onclick="addresses.edit();"><span class="icon-edit" style="font-size: 16px;"></span>
[% lbl.edit %]</button> -->
<button class="bar-item toolbarbtn right" onclick="addresses.add();"><span class="icon-add" style="font-size: 16px;"></span> neu</button>
<div id="tbl_addresses"></div>
</div>
<div class="cell">
- <div class="container">
- <form id="frm_addresses" name="frm_addresses">
- <div class="row">
- <div class="cell container" style="width: 200px;">
- <div class="">
- <label class="label" for="addresses_receipient">Name / Firma</label> <input class="input data_addresses border text" data-column="receipient" data-id="" data-table="addresses" id="addresses_receipient" name="addresses_receipient" onblur=
- "dataform.savefield(this);" type="text">
+ <div class="row" >
+ <div class="cell container" style="width: 400px; background-color: #e4e4e4; padding-bottom: 10px;">
+ <form id="frm_addresses" name="frm_addresses">
+ <div class="row">
+ <div class="cell container" style="width: 400px;">
+ <div class="">
+ <label class="label" for="addresses_receipient">Name / Firma</label> <input class="input data_addresses border text" data-column="receipient" data-id="" data-table="addresses" id="addresses_receipient" name="addresses_receipient" onblur=
+ "dataform.savefield(this);" type="text">
+ </div>
</div>
- </div>
- <div class="cell container" style="width: 120px;">
- <div class="">
- <label class="label" for="addresses_clientnumber">Kundern-Nr.</label> <input class="input data_addresses border text" data-column="clientnumber" data-id="" data-table="addresses" id="addresses_clientnumber" name="addresses_clientnumber"
- onblur="dataform.savefield(this);" placeholder="YYMMDDNNN" type="text">
+ <div class="cell container" style="width: 120px;">
+ <div class="">
+ <label class="label" for="addresses_clientnumber">Kundern-Nr.</label> <input class="input data_addresses border text" data-column="clientnumber" data-id="" data-table="addresses" id="addresses_clientnumber" name="addresses_clientnumber"
+ onblur="dataform.savefield(this);" placeholder="YYMMDDNNN" type="text">
+ </div>
</div>
</div>
- </div>
- <div class="row">
- <div class="cell" style="width: 60px;">
- <div class="">
- <label class="label" for="addresses_title">Titel</label> <input class="input border data_addresses text" data-column="title" data-id="" data-table="addresses" id="addresses_title" name="addresses_title" onblur="dataform.savefield(this);"
- type="text">
+ <div class="row">
+ <div class="cell" style="width: 60px;">
+ <div class="">
+ <label class="label" for="addresses_title">Titel</label> <input class="input border data_addresses text" data-column="title" data-id="" data-table="addresses" id="addresses_title" name="addresses_title" onblur="dataform.savefield(this);"
+ type="text">
+ </div>
</div>
- </div>
- <div class="cell" style="width: 300px;">
- <div class="">
- <label class="label" for="addresses_prename">Vorname</label> <input class="input border data_addresses text" data-column="prename" data-id="" data-table="addresses" id="addresses_prename" name="addresses_prename" onblur=
- "dataform.savefield(this);" type="text">
+ <div class="cell" style="width: 300px;">
+ <div class="">
+ <label class="label" for="addresses_prename">Vorname</label> <input class="input border data_addresses text" data-column="prename" data-id="" data-table="addresses" id="addresses_prename" name="addresses_prename" onblur=
+ "dataform.savefield(this);" type="text">
+ </div>
</div>
- </div>
- <div class="cell" style="width: 300px;">
- <div class="">
- <label class="label" for="addresses_surname">Nachname</label> <input class="input border data_addresses text" data-column="surname" data-id="" data-table="addresses" id="addresses_surname" name="addresses_surname" onblur=
- "dataform.savefield(this);" type="text">
+ <div class="cell" style="width: 300px;">
+ <div class="">
+ <label class="label" for="addresses_surname">Nachname</label> <input class="input border data_addresses text" data-column="surname" data-id="" data-table="addresses" id="addresses_surname" name="addresses_surname" onblur=
+ "dataform.savefield(this);" type="text">
+ </div>
</div>
</div>
- </div>
- <div class="row">
- <div class="cell container" style="width: 660px;">
- <div class="">
- <label class="label" for="addresses_address">Adresse</label> <input class="input border data_addresses text" data-column="address" data-id="" data-table="addresses" id="addresses_address" name="addresses_address" onblur=
- "dataform.savefield(this);" type="text">
+ <div class="row">
+ <div class="cell container" style="width: 660px;">
+ <div class="">
+ <label class="label" for="addresses_address">Adresse</label> <input class="input border data_addresses text" data-column="address" data-id="" data-table="addresses" id="addresses_address" name="addresses_address" onblur=
+ "dataform.savefield(this);" type="text">
+ </div>
</div>
</div>
- </div>
- <div class="row">
- <div class="cell container" style="width: 60px;">
- <div class="">
- <label class="label" for="addresses_country">Land</label> <input class="input border data_addresses text" data-column="country" data-id="" data-table="addresses" id="addresses_country" name="addresses_country" onblur=
- "dataform.savefield(this);" type="text">
+ <div class="row">
+ <div class="cell container" style="width: 60px;">
+ <div class="">
+ <label class="label" for="addresses_country">Land</label> <input class="input border data_addresses text" data-column="country" data-id="" data-table="addresses" id="addresses_country" name="addresses_country" onblur=
+ "dataform.savefield(this);" type="text">
+ </div>
</div>
- </div>
- <div class="cell container" style="width: 120px;">
- <div class="">
- <label class="label" for="addresses_zip">PLZ</label> <input class="input border data_addresses text" data-column="zip" data-id="" data-table="addresses" id="addresses_zip" name="addresses_zip" onblur="dataform.savefield(this);" type=
- "text">
+ <div class="cell container" style="width: 120px;">
+ <div class="">
+ <label class="label" for="addresses_zip">PLZ</label> <input class="input border data_addresses text" data-column="zip" data-id="" data-table="addresses" id="addresses_zip" name="addresses_zip" onblur="dataform.savefield(this);" type=
+ "text">
+ </div>
</div>
- </div>
- <div class="cell container" style="width: 480px;">
- <div class="">
- <label class="label" for="addresses_city">Ort</label> <input class="input data_addresses border text" data-column="city" data-id="" data-table="addresses" id="addresses_city" name="addresses_city" onblur="dataform.savefield(this);" type=
- "text">
+ <div class="cell container" style="width: 480px;">
+ <div class="">
+ <label class="label" for="addresses_city">Ort</label> <input class="input data_addresses border text" data-column="city" data-id="" data-table="addresses" id="addresses_city" name="addresses_city" onblur="dataform.savefield(this);" type=
+ "text">
+ </div>
</div>
</div>
- </div>
- <div class="row">
- <div class="cell container" style="width: 400px;">
- <div class="">
- <label class="label" for="addresses_email">E-mail</label> <input class="input data_addresses border text" data-column="email" data-id="" data-table="addresses" id="addresses_email" name="addresses_email" onblur="dataform.savefield(this);"
- type="text">
+ <div class="row">
+ <div class="cell container" style="width: 400px;">
+ <div class="">
+ <label class="label" for="addresses_email">E-mail</label> <input class="input data_addresses border text" data-column="email" data-id="" data-table="addresses" id="addresses_email" name="addresses_email" onblur="dataform.savefield(this);"
+ type="text">
+ </div>
</div>
</div>
- </div>
- <div class="row">
- <div class="cell container" style="width: 400px;">
- <div class="">
- <label class="label" for="addresses_phone">Telefon</label> <input class="input border text" data-column="phone" data-id="" data-table="addresses" id="addresses_phone" name="addresses_phone" onblur=
- "dataform.savefield(this);" type="text">
+ <div class="row">
+ <div class="cell container" style="width: 400px;">
+ <div class="">
+ <label class="label" for="addresses_phone">Telefon</label> <input class="input border text" data-column="phone" data-id="" data-table="addresses" id="addresses_phone" name="addresses_phone" onblur=
+ "dataform.savefield(this);" type="text">
+ </div>
</div>
</div>
- </div>
- <div class="row">
- <div class="cell container" style="width: 300px;">
- <div class="">
- <label class="label" for="addresses_iban">Kontonummer</label> <input class="input border text" data-column="iban" data-id="" data-table="addresses" id="addresses_iban" name="addresses_iban" onblur=
- "dataform.savefield(this);" type="text">
+ <div class="row">
+ <div class="cell container" style="width: 300px;">
+ <div class="">
+ <label class="label" for="addresses_iban">Kontonummer</label> <input class="input border text" data-column="iban" data-id="" data-table="addresses" id="addresses_iban" name="addresses_iban" onblur=
+ "dataform.savefield(this);" type="text">
+ </div>
</div>
- </div>
- <div class="cell container" style="width: 150px;">
- <div class="">
- <label class="label" for="addresses_bic">BIC</label> <input class="input border text" data-column="bic" data-id="" data-table="addresses" id="addresses_bic" name="addresses_bic" onblur="dataform.savefield(this);" type=
- "text">
+ <div class="cell container" style="width: 150px;">
+ <div class="">
+ <label class="label" for="addresses_bic">BIC</label> <input class="input border text" data-column="bic" data-id="" data-table="addresses" id="addresses_bic" name="addresses_bic" onblur="dataform.savefield(this);" type=
+ "text">
+ </div>
</div>
</div>
- </div>
- <div class="row">
- <div class="cell container" style="width: 200px;">
- <div class="">
- <label class="label" for="addresses_vatid">USt-Id</label> <input class="input border text" data-column="vatid" data-id="" data-table="addresses" id="addresses_vatid" name="addresses_vatid" onblur="dataform.savefield(this);"
- type="text">
+ <div class="row">
+ <div class="cell container" style="width: 200px;">
+ <div class="">
+ <label class="label" for="addresses_vatid">USt-Id</label> <input class="input border text" data-column="vatid" data-id="" data-table="addresses" id="addresses_vatid" name="addresses_vatid" onblur="dataform.savefield(this);"
+ type="text">
+ </div>
</div>
- </div>
- <div class="cell container" style="width: 200px;">
- <div class="">
- <label class="label" for="addresses_lang">Sprache</label> <input class="input border text" data-column="lang" data-id="" data-table="addresses" id="addresses_lang" name="addresses_lang" onblur="dataform.savefield(this);"
- type="text">
+ <div class="cell container" style="width: 200px;">
+ <div class="">
+ <label class="label" for="addresses_lang">Sprache</label> <input class="input border text" data-column="lang" data-id="" data-table="addresses" id="addresses_lang" name="addresses_lang" onblur="dataform.savefield(this);"
+ type="text">
+ </div>
</div>
</div>
+ </form>
+ </div>
+ <div class="cell" style="width: calc( 100vw - 800px);">
+ <div class="bar moduletoolbar">
+ <div class="bar-item PageHeadTitle">Kontakte</div>
+ <button class="bar-item toolbarbtn right text-red" onclick="addresses.confirmremoveContacts();"><span class="icon icon-trash" style="font-size: 16px;"></span>löschen</button>
+ <button class="bar-item toolbarbtn right" onclick="addresses.duplicateContacts();"><span class="icon icon-duplicate" style="font-size: 16px;"></span>dupl.</button>
+ <button class="bar-item toolbarbtn right" onclick="addresses.editContacts();"><span class="icon icon-edit" style="font-size: 16px;"></span>bearb.</button>
+ <button class="bar-item toolbarbtn right" onclick="addresses.addContacts();"><span class="icon icon-add" style="font-size: 16px;"></span>neu</button>
</div>
- </form>
+ <div id="tbl_contacts"></div>
+ </div>
+ </div>
+ <div class="row">
+ <div class="bar moduletoolbar">
+ <div class="bar-item PageHeadTitle">Mail Vorlagen</div>
+ <button class="bar-item toolbarbtn right text-red" onclick="addresses.confirmremoveMailTemplate();"><span class="icon icon-trash" style="font-size: 16px;"></span>löschen</button>
+ <button class="bar-item toolbarbtn right" onclick="addresses.duplicateMailtemplate();"><span class="icon icon-duplicate" style="font-size: 16px;"></span>dupl.</button>
+ <button class="bar-item toolbarbtn right" onclick="addresses.editMailTemplate();"><span class="icon icon-edit" style="font-size: 16px;"></span>bearb.</button>
+ <button class="bar-item toolbarbtn right" onclick="addresses.addMailTemplate();"><span class="icon icon-add" style="font-size: 16px;"></span>neu</button>
+ </div>
+ <div id="tbl_mailtemplates"></div>
+
</div>
</div>
+
</div>
</div>
\ No newline at end of file
-<div class="container bar toolbar">
+<div class="display-container bar toolbar">
<button class="bar-item toolbarbtn" onclick="index.viewpanel();"><span class="icon-back" style="font-size: 16px;"></span>zurück</button>
<div class="bar-item PageHeadTitle">
Buchungen
-<div class="container bar toolbar">
+<div class="display-container bar toolbar">
<button class="bar-item toolbarbtn" onclick="invoices.gettbldata();myapp.viewpanel('invoices');"><span class="icon-back" style="font-size: 16px;"></span>zurück</button>
<div class="bar-item PageHeadTitle">
Rechnung
</select>
</div>
</div>
- <div class="row">
+ <div class="row" id="row_invoicetemplate">
<div class="cell" style="width: 300px;">
- <label class="label" for="invoices_id_template">Vorlage</label> <select class="select border data_invoices" data-column="id_template" data-id="" data-selected="" data-table="invoices" id="invoices_id_template" name=
- "invoices_id_template" onchange="dataform.savefield(this);" value="">
+ <label class="label" for="invoices_id_template">Vorlage</label>
+ <select class="select border data_invoices" data-column="id_template" data-id="" data-selected="" data-table="invoices" id="invoices_id_template" name="invoices_id_template" onchange="dataform.savefield(this);" value="">
</select>
</div>
</div>
<div class="cell">
<div id="tbl_invoicebookings"></div>
</div>
-</div><!-- <iframe src="modules/index.html" id="moduleframe" ></iframe> -->
\ No newline at end of file
+</div>
\ No newline at end of file
<div class="display-container">
- <div class="container bar toolbar">
+ <div class="bar toolbar">
<button class="bar-item toolbarbtn" onclick="index.viewpanel();"><span class="icon-back" style="font-size: 16px;"></span>zurück</button>
<div class="bar-item PageHeadTitle">Rechnungen</div>
<button class="bar-item toolbarbtn right text-red" onclick="invoices.confirmremove();"><span class="icon icon-trash" style="font-size: 16px;"></span>löschen</button>
-<div class="container bar toolbar">
+<div class="display-container bar toolbar">
<button class="bar-item toolbarbtn" onclick="offers.gettbldata();myapp.viewpanel('offers');"><span class="icon-back" style="font-size: 16px;"></span>zurück</button>
<div class="bar-item PageHeadTitle">
Angebot
-<div class="container bar toolbar">
+<div class="display-container bar toolbar">
<button class="bar-item toolbarbtn" onclick="products.gettbldata();myapp.viewpanel('products');"><span class="icon-back" style="font-size: 16px;"></span>zurück</button>
<div class="bar-item PageHeadTitle">
Produkt
-<div class="container bar toolbar">
+<div class="display-container bar toolbar">
<button class="bar-item toolbarbtn" onclick="index.viewpanel();"><span class="icon-back" style="font-size: 16px;"></span>zurück</button>
<div class="bar-item PageHeadTitle">
Einstellungen
-<div class="container bar toolbar">
+<div class="display-container bar toolbar">
<button class="bar-item toolbarbtn" onclick="index.viewpanel();"><span class="icon-back" style="font-size: 16px;"></span>zurück</button>
<div class="bar-item PageHeadTitle">
Vorlagen
-<div class="container bar toolbar">
+<div class="display-container bar toolbar">
<button class="bar-item toolbarbtn" onclick="index.viewpanel();"><span class="icon-back" style="font-size: 16px;"></span>zurück</button>
<div class="bar-item PageHeadTitle">
Transaktionen
--- /dev/null
+@echo off
+cd %~dp0
+cd ..
+cd desktopapp
+call npm run package-win64 > ../tmpcompile.txt
+cd ..
+echo "%CD%"
+copy "%CD%\release-builds\invoicejournal-win32-x64\resources\app.asar" "%localappdata%\Programs\InvoiceJournal\resources\app.asar"
\ No newline at end of file
--- /dev/null
+
+> InvoiceJournal@1.0.1 package-win64 C:\Users\ksaff\Workspace\invoicejournal\desktopapp
+> electron-packager . invoicejournal --overwrite --platform=win32 --arch=x64 --asar --out=../release-builds --version-string.CompanyName=DKS --version-string.FileDescription=DKS --version-string.ProductName=InvoiceJournal --icon=img/invoicejournal.ico
+