diff --git a/.gitignore b/.gitignore index 1bd36c2..8e8e1f4 100755 --- a/.gitignore +++ b/.gitignore @@ -30,8 +30,8 @@ www/file/* www/js/app.js www/js/libs.js - www/css/.sass-cache www/css/*.css !www/css/bootstrap.min.css +config-dev.xml diff --git a/src/App.hx b/src/App.hx index 32f3683..24fb6f8 100755 --- a/src/App.hx +++ b/src/App.hx @@ -77,10 +77,10 @@ class App extends sugoi.BaseApp { } public static function log(t:Dynamic, ?infos:haxe.PosInfos) { - if (App.config.DEBUG) { - // neko.Web.logMessage(Std.string(t)); // write in Apache error log - neko.Web.logMessage('[${infos.fileName}:${infos.lineNumber} ${infos.className}#${infos.methodName}] ' + Std.string(t)); - } + // if (App.config.DEBUG) { + // neko.Web.logMessage(Std.string(t)); // write in Apache error log + // } + neko.Web.logMessage('[${infos.fileName}:${infos.lineNumber} ${infos.className}#${infos.methodName}] ' + Std.string(t)); } public function event(e:Event) { @@ -263,10 +263,14 @@ class App extends sugoi.BaseApp { var params = group == null ? null : {remoteId: group.id}; + App.log('about to send email with subject=<${m.getSubject()}> ...'); getMailer().send(m, params, function(o) {}); + App.log('email from=<${m.getSender().email}>, subject=<${m.getSubject()}> successfully sent'); } public static function quickMail(to:String, subject:String, html:String, ?group:db.Amap) { + App.log('quickMail subject=$subject'); + var e = new sugoi.mail.Mail(); e.setSubject(subject); e.setRecipient(to); diff --git a/src/controller/Cron.hx b/src/controller/Cron.hx index 2eea8b0..4f8070a 100755 --- a/src/controller/Cron.hx +++ b/src/controller/Cron.hx @@ -1,144 +1,137 @@ package controller; + import sugoi.db.Cache; import sugoi.Web; import sugoi.mail.Mail; import Common; + using Lambda; using tools.DateTool; -class Cron extends Controller -{ +class Cron extends Controller { + public function doDefault() {} - public function doDefault() - { - - } - /** * CLI only en prod */ function canRun() { - if (App.current.user != null && App.current.user.isAdmin()){ + if (App.current.user != null && App.current.user.isAdmin()) { return true; - }else if (App.config.DEBUG) { + } else if (App.config.DEBUG) { return true; - }else { - + } else { if (Web.isModNeko) { Sys.print("only CLI."); return false; - }else { + } else { return true; } } } - - public function doMinute() { + public function doMinute() { print("Cron.doMinute is called"); - if (!canRun()) return; - + if (!canRun()) + return; + app.event(MinutelyCron); sendEmailsfromBuffer(); - } - + /** * Hourly Cron * * this function can be locally tested with `neko index.n cron/hour > cron.log` */ public function doHour() { - app.event(HourlyCron); - - distribNotif(4,db.User.UserFlags.HasEmailNotif4h); //4h before - distribNotif(24,db.User.UserFlags.HasEmailNotif24h); //24h before - distribNotif(0, db.User.UserFlags.HasEmailNotifOuverture); //on command open - + + distribNotif(4, db.User.UserFlags.HasEmailNotif4h); // 4h before + distribNotif(24, db.User.UserFlags.HasEmailNotif24h); // 24h before + distribNotif(0, db.User.UserFlags.HasEmailNotifOuverture); // on command open + distribValidationNotif(); - //sendOrdersByProductWhenOrdersClose(); + // sendOrdersByProductWhenOrdersClose(); } - - + public function doDaily() { - if (!canRun()) return; - + if (!canRun()) + return; + app.event(DailyCron); - - //ERRORS MONITORING + + // ERRORS MONITORING var n = Date.now(); var yest24h = new Date(n.getFullYear(), n.getMonth(), n.getDate(), 0, 0, 0); var yest0h = DateTools.delta(yest24h, -1000 * 60 * 60 * 24); - - var errors = sugoi.db.Error.manager.search( $date < yest24h && $date > yest0h ); + + var errors = sugoi.db.Error.manager.search($date < yest24h && $date > yest0h); if (errors.length > 0) { var report = new StringBuf(); report.add("

" + App.config.NAME + " : ERRORS

"); for (e in errors) { - report.add("
"+e.error + " at URL " + e.url + " ( user : " + (e.user!=null?e.user.toString():"none") + ", IP : " + e.ip + ")

"); + report.add("
" + e.error + " at URL " + e.url + " ( user : " + (e.user != null ? e.user.toString() : "none") + ", IP : " + e.ip
+					+ ")

"); } - + var m = new Mail(); - m.setSender(App.config.get("default_email"),"Cagette.net"); + m.setSender(App.config.get("default_email"), "Cagette.net"); m.addRecipient(App.config.get("webmaster_email")); - m.setSubject(App.config.NAME+" Errors"); - m.setHtmlBody( app.processTemplate("mail/message.mtt", { text:report.toString() } ) ); + m.setSubject(App.config.NAME + " Errors"); + m.setHtmlBody(app.processTemplate("mail/message.mtt", {text: report.toString()})); App.sendMail(m); } - - - //DEMO CONTRATS deletion after 7 days ( see controller.Group.doCreate() ) - db.Contract.manager.delete($name == "Contrat AMAP Maraîcher Exemple" && $startDate < DateTools.delta(Date.now(), -1000.0 * 60 * 60 * 24 * 7)); - db.Contract.manager.delete($name == "Contrat Poulet Exemple" && $startDate < DateTools.delta(Date.now(), -1000.0 * 60 * 60 * 24 * 7)); - - - //Old Messages cleaning + + // DEMO CONTRATS deletion after 7 days ( see controller.Group.doCreate() ) + db.Contract.manager.delete($name == "Contrat AMAP Maraîcher Exemple" + && $startDate < DateTools.delta(Date.now(), -1000.0 * 60 * 60 * 24 * 7)); + db.Contract.manager.delete($name == "Contrat Poulet Exemple" + && $startDate < DateTools.delta(Date.now(), -1000.0 * 60 * 60 * 24 * 7)); + + // Old Messages cleaning db.Message.manager.delete($date < DateTools.delta(Date.now(), -1000.0 * 60 * 60 * 24 * 30 * 6)); - - //DB cleaning : I dont know how, but some people have empty string emails... + + // DB cleaning : I dont know how, but some people have empty string emails... /*for ( u in db.User.manager.search($email == "", true)){ - u.email = Std.random(9999) + "@cagette.net"; - u.update(); - } - for ( u in db.User.manager.search($email2 == "", true)){ - u.email2 = null; - u.update(); + u.email = Std.random(9999) + "@cagette.net"; + u.update(); + } + for ( u in db.User.manager.search($email2 == "", true)){ + u.email2 = null; + u.update(); }*/ - - } - + /** * Send email notifications to users before a distribution * @param hour * @param flag */ function distribNotif(hour:Int, flag:db.User.UserFlags) { - - //trouve les distrib qui commencent dans le nombre d'heures demandé - //on recherche celles qui commencent jusqu'à une heure avant pour ne pas en rater - var from = DateTools.delta(Date.now(), 1000.0 * 60 * 60 * (hour-1)); - var to = DateTools.delta(Date.now(), 1000.0 * 60 * 60 * hour); - - //if (App.config.DEBUG) from = DateTools.delta(from, 1000.0 * 60 * 60 * 24 * -30); - + // trouve les distrib qui commencent dans le nombre d'heures demandé + // on recherche celles qui commencent jusqu'à une heure avant pour ne pas en rater + var from = DateTools.delta(Date.now(), 1000.0 * 60 * 60 * (hour - 1)); + var to = DateTools.delta(Date.now(), 1000.0 * 60 * 60 * hour); + + // if (App.config.DEBUG) from = DateTools.delta(from, 1000.0 * 60 * 60 * 24 * -30); + // dans le cas HasEmailNotifOuverture la date à prendre est le orderStartDate // et non pas date qui est la date de la distribution var distribs; - if ( db.User.UserFlags.HasEmailNotifOuverture == flag ) - distribs = db.Distribution.manager.search( $orderStartDate >= from && $orderStartDate <= to , false); + if (db.User.UserFlags.HasEmailNotifOuverture == flag) + distribs = db.Distribution.manager.search($orderStartDate >= from && $orderStartDate <= to, false); else - distribs = db.Distribution.manager.search( $date >= from && $date <= to , false); - - //Sys.print("distribNotif "+hour+" from "+from+" to "+to+"
\n"); - - //on s'arrete immédiatement si aucune distibution trouvée - if (distribs.length == 0) return; - - //cherche plus tard si on a pas une "grappe" de distrib + distribs = db.Distribution.manager.search($date >= from && $date <= to, false); + + // Sys.print("distribNotif "+hour+" from "+from+" to "+to+"
\n"); + + // on s'arrete immédiatement si aucune distibution trouvée + if (distribs.length == 0) + return; + + // cherche plus tard si on a pas une "grappe" de distrib /*while (true) { var extraDistribs ; if ( db.User.UserFlags.HasEmailNotifOuverture != flag ) @@ -154,10 +147,10 @@ class Cron extends Controller break; } }*/ - - //on vérifie dans le cache du jour que ces distrib n'ont pas deja été traitées lors d'un cron précédent - var cacheId = Date.now().toString().substr(0, 10)+Std.string(flag); - var dist :Array = sugoi.db.Cache.get(cacheId); + + // on vérifie dans le cache du jour que ces distrib n'ont pas deja été traitées lors d'un cron précédent + var cacheId = Date.now().toString().substr(0, 10) + Std.string(flag); + var dist:Array = sugoi.db.Cache.get(cacheId); if (dist != null) { for (d in Lambda.array(distribs)) { if (Lambda.exists(dist, function(x) return x == d.id)) { @@ -165,115 +158,135 @@ class Cron extends Controller distribs.remove(d); } } - }else { + } else { dist = []; } - - //toutes les distribs trouvées ont deja été traitées - if (distribs.length == 0) return; - - //stocke cache - for (d in distribs) dist.push(d.id); + + // toutes les distribs trouvées ont deja été traitées + if (distribs.length == 0) + return; + + // stocke cache + for (d in distribs) + dist.push(d.id); Cache.set(cacheId, dist, 24 * 60 * 60); - - //We have now the distribs we want to notify about. - var distribsByContractId = new Map(); - for (d in distribs) { - if (d == null || d.contract==null) continue; + + // We have now the distribs we want to notify about. + var distribsByContractId = new Map(); + for (d in distribs) { + if (d == null || d.contract == null) + continue; distribsByContractId.set(d.contract.id, d); } - //Boucle sur les distributions pour gerer le cas de plusieurs distributions le même jour sur le même contrat - var orders = []; - for (d in distribs) { - if (d == null || d.contract==null) continue; - //get orders for both type of contracts - for ( x in d.contract.getOrders(d)) orders.push(x); + // Boucle sur les distributions pour gerer le cas de plusieurs distributions le même jour sur le même contrat + var orders = []; + for (d in distribs) { + if (d == null || d.contract == null) + continue; + // get orders for both type of contracts + for (x in d.contract.getOrders(d)) + orders.push(x); } - + /* * Group orders by users-group to receive separate emails by groups for the same user. * Map key is $userId-$groupId - */ - var users = new Map , - vendors:Array + vendors:Array }>(); - + for (o in orders) { - - var x = users.get(o.user.id+"-"+o.product.contract.amap.id); - if (x == null) x = {user:o.user,distrib:null,products:[],vendors:[]}; + var x = users.get(o.user.id + "-" + o.product.contract.amap.id); + if (x == null) + x = { + user: o.user, + distrib: null, + products: [], + vendors: [] + }; x.distrib = distribsByContractId.get(o.product.contract.id); - x.products.push(o); - users.set(o.user.id+"-"+o.product.contract.amap.id, x); - //trace (o.userId+"-"+o.product.contract.amap.id, x);Sys.print("
\n"); - + x.products.push(o); + users.set(o.user.id + "-" + o.product.contract.amap.id, x); + // trace (o.userId+"-"+o.product.contract.amap.id, x);Sys.print("
\n"); + // Prévenir également le deuxième user en cas des commandes alternées - if (o.user2 != null) { - var x = users.get(o.user2.id+"-"+o.product.contract.amap.id); - if (x == null) x = {user:o.user2,distrib:null,products:[],vendors:[]}; - x.distrib = distribsByContractId.get(o.product.contract.id); - x.products.push(o); - users.set(o.user2.id+"-"+o.product.contract.amap.id, x); - //trace (o.user2.id+"-"+o.product.contract.amap.id, x);Sys.print("
\n"); - } + if (o.user2 != null) { + var x = users.get(o.user2.id + "-" + o.product.contract.amap.id); + if (x == null) + x = { + user: o.user2, + distrib: null, + products: [], + vendors: [] + }; + x.distrib = distribsByContractId.get(o.product.contract.id); + x.products.push(o); + users.set(o.user2.id + "-" + o.product.contract.amap.id, x); + // trace (o.user2.id+"-"+o.product.contract.amap.id, x);Sys.print("
\n"); + } } - //remove zero qt orders - for( k in users.keys()){ + // remove zero qt orders + for (k in users.keys()) { var x = users.get(k); var total = 0.0; - for( o in x.products) total += o.quantity; - if(total==0.0) users.remove(k); + for (o in x.products) + total += o.quantity; + if (total == 0.0) + users.remove(k); } - + // Dans le cas de l'ouverture de commande, ce sont tous les users qu'il faut intégrer - if ( db.User.UserFlags.HasEmailNotifOuverture == flag ) - { - for (d in distribs) { + if (db.User.UserFlags.HasEmailNotifOuverture == flag) { + for (d in distribs) { var memberList = d.contract.amap.getMembers(); for (u in memberList) { - var x = users.get(u.id+"-"+d.contract.amap.id); - if (x == null) x = {user:u,distrib:null,products:[],vendors:[]}; + var x = users.get(u.id + "-" + d.contract.amap.id); + if (x == null) + x = { + user: u, + distrib: null, + products: [], + vendors: [] + }; x.distrib = distribsByContractId.get(d.contract.id); x.vendors.push(d.contract.vendor); - users.set(u.id+"-"+d.contract.amap.id, x); - //print(u.id+"-"+d.contract.amap.id, x); + users.set(u.id + "-" + d.contract.amap.id, x); + // print(u.id+"-"+d.contract.amap.id, x); } } } - for ( u in users) { - - if (u.user.flags.has(flag) ) { - + for (u in users) { + if (u.user.flags.has(flag)) { if (u.user.email != null) { var group = u.distrib.contract.amap; - this.t = sugoi.i18n.Locale.init(u.user.lang); //switch to the user language + this.t = sugoi.i18n.Locale.init(u.user.lang); // switch to the user language var text; - if ( db.User.UserFlags.HasEmailNotifOuverture == flag ) - { - //order opening notif - text = t._("Opening of orders for the delivery of ::date::", {date:view.hDate(u.distrib.date)}); + if (db.User.UserFlags.HasEmailNotifOuverture == flag) { + // order opening notif + text = t._("Opening of orders for the delivery of ::date::", {date: view.hDate(u.distrib.date)}); text += "
"; text += t._("The following suppliers are involved :"); text += "
    "; - for ( v in u.vendors) { + for (v in u.vendors) { text += "
  • " + v + "
  • "; } text += "
"; - - }else{ - //Distribution notif to the users + } else { + // Distribution notif to the users var d = u.distrib; - text = t._("Do not forget the delivery on ::day:: from ::from:: to ::to::
", {day:view.dDate(d.date),from:view.hHour(d.date),to:view.hHour(d.end)}); + text = t._("Do not forget the delivery on ::day:: from ::from:: to ::to::
", + {day: view.dDate(d.date), from: view.hHour(d.date), to: view.hHour(d.end)}); text += t._("Your products to collect :") + "
    "; - for ( p in u.products) { - text += "
  • "+p.quantity+" x "+p.product.getName(); + for (p in u.products) { + text += "
  • " + p.quantity + " x " + p.product.getName(); // Gerer le cas des contrats en alternance if (p.user2 != null) { text += " " + t._("alternated with") + " "; @@ -286,141 +299,142 @@ class Cron extends Controller } text += "
"; } - + if (u.distrib.isDistributor(u.user)) { text += t._("Warning: you are in charge of the delivery ! Do not forget to print the attendance sheet."); } - - try{ + + try { var m = new Mail(); m.setSender(App.config.get("default_email"), "Cagette.net"); - if(group.contact!=null) m.setReplyTo(group.contact.email, group.name); + if (group.contact != null) + m.setReplyTo(group.contact.email, group.name); m.addRecipient(u.user.email, u.user.getName()); - if (u.user.email2 != null) m.addRecipient(u.user.email2); - m.setSubject( group.name+" : "+t._("Distribution on ::date::",{date:app.view.hDate(u.distrib.date)}) ); - m.setHtmlBody( app.processTemplate("mail/message.mtt", { text:text,group:group } ) ); - App.sendMail(m , u.distrib.contract.amap); - }catch (e:Dynamic){ - app.logError(e); //email could be invalid + if (u.user.email2 != null) + m.addRecipient(u.user.email2); + m.setSubject(group.name + " : " + t._("Distribution on ::date::", {date: app.view.hDate(u.distrib.date)})); + m.setHtmlBody(app.processTemplate("mail/message.mtt", {text: text, group: group})); + App.sendMail(m, u.distrib.contract.amap); + } catch (e:Dynamic) { + app.logError(e); // email could be invalid } - } } } } - - + /** * Check if there is a multi-distrib to validate. * * Autovalidate it after 10 days */ - function distribValidationNotif(){ - + function distribValidationNotif() { var now = Date.now(); - var from = now.setHourMinute( now.getHours(), 0 ); - var to = now.setHourMinute( now.getHours()+1 , 0); - + var from = now.setHourMinute(now.getHours(), 0); + var to = now.setHourMinute(now.getHours() + 1, 0); + var explain = t._("

This step is important in order to:

"); explain += t._("
  • Update orders if delivered quantities are different from ordered quantities
  • "); explain += t._("
  • Confirm the reception of payments (checks, cash, transfers) in order to mark orders as 'paid'
"); - + /* * warn administrator if a distribution just ended - */ - var ds = db.Distribution.manager.search( !$validated && ($end >= from) && ($end < to) , false); - - for ( d in Lambda.array(ds)){ - if ( d.contract.type != db.Contract.TYPE_VARORDER ){ + */ + var ds = db.Distribution.manager.search(!$validated && ($end >= from) && ($end < to), false); + + for (d in Lambda.array(ds)) { + if (d.contract.type != db.Contract.TYPE_VARORDER) { ds.remove(d); - }else if ( !d.contract.amap.hasPayments() ){ + } else if (!d.contract.amap.hasPayments()) { ds.remove(d); } } - + var ds = tools.ObjectListTool.deduplicateDistribsByKey(ds); var view = App.current.view; - - for ( d in ds ){ + + for (d in ds) { // var subj = "["+d.contract.amap.name+"] " + t._("Validation of the ::date:: distribution",{date:view.hDate(d.date)}); - var subj = t._("[::group::] Validation of the ::date:: distribution",{group : d.contract.amap.name , date : view.hDate(d.date)}); - - var url = "http://" + App.config.HOST + "/distribution/validate/"+d.date.toString().substr(0,10)+"/"+d.place.id; - + var subj = t._("[::group::] Validation of the ::date:: distribution", {group: d.contract.amap.name, date: view.hDate(d.date)}); + + var url = "http://" + App.config.HOST + "/distribution/validate/" + d.date.toString().substr(0, 10) + "/" + d.place.id; + var html = t._("

Your distribution just finished, don't forget to validate it

"); html += explain; - html += t._("

Click here to validate the distribution (You must be connected to your group Cagette)", {distriburl:url}); - + html += t._("

Click here to validate the distribution (You must be connected to your group Cagette)", + {distriburl: url}); + App.quickMail(d.contract.amap.contact.email, subj, html); } - + /* * warn administrator if a distribution ended 3 days ago - */ - - var from = now.setHourMinute( now.getHours() , 0 ).deltaDays(-3); - var to = now.setHourMinute( now.getHours()+1 , 0).deltaDays(-3); - - //warn administrator if a distribution just ended - var ds = db.Distribution.manager.search( !$validated && ($end >= from) && ($end < to) , false); - - for ( d in Lambda.array(ds)){ - if ( d.contract.type != db.Contract.TYPE_VARORDER ){ + */ + + var from = now.setHourMinute(now.getHours(), 0).deltaDays(-3); + var to = now.setHourMinute(now.getHours() + 1, 0).deltaDays(-3); + + // warn administrator if a distribution just ended + var ds = db.Distribution.manager.search(!$validated && ($end >= from) && ($end < to), false); + + for (d in Lambda.array(ds)) { + if (d.contract.type != db.Contract.TYPE_VARORDER) { ds.remove(d); - }else if ( !d.contract.amap.hasPayments() ){ + } else if (!d.contract.amap.hasPayments()) { ds.remove(d); } } - + var ds = tools.ObjectListTool.deduplicateDistribsByKey(ds); - - for ( d in ds ){ + + for (d in ds) { // var subj = d.contract.amap.name + t._(": Validation of the delivery of the ") + App.current.view.hDate(d.date); - var subj = t._("[::group::] Validation of the ::date:: distribution",{group : d.contract.amap.name , date : view.hDate(d.date)}); - - var url = "http://" + App.config.HOST + "/distribution/validate/"+d.date.toString().substr(0,10)+"/"+d.place.id; - + var subj = t._("[::group::] Validation of the ::date:: distribution", {group: d.contract.amap.name, date: view.hDate(d.date)}); + + var url = "http://" + App.config.HOST + "/distribution/validate/" + d.date.toString().substr(0, 10) + "/" + d.place.id; + var html = t._("

Reminder: you have a delivery to validate.

"); html += explain; - html += t._("

Click here to validate the delivery (You must be connected to your Cagette group)", {distriburl:url}); - + html += t._("

Click here to validate the delivery (You must be connected to your Cagette group)", + {distriburl: url}); + App.quickMail(d.contract.amap.contact.email, subj, html); } - - + /* * Autovalidate unvalidated distributions after 10 days - */ - var from = now.setHourMinute( now.getHours() , 0 ).deltaDays( 0 - db.Distribution.DISTRIBUTION_VALIDATION_LIMIT ); - var to = now.setHourMinute( now.getHours() + 1 , 0).deltaDays( 0 - db.Distribution.DISTRIBUTION_VALIDATION_LIMIT ); + */ + var from = now.setHourMinute(now.getHours(), 0).deltaDays(0 - db.Distribution.DISTRIBUTION_VALIDATION_LIMIT); + var to = now.setHourMinute(now.getHours() + 1, 0).deltaDays(0 - db.Distribution.DISTRIBUTION_VALIDATION_LIMIT); print('AUTOVALIDATION'); print('Find distributions from $from to $to'); - var ds = db.Distribution.manager.search( !$validated && ($end >= from) && ($end < to) , true); - for ( d in Lambda.array(ds)){ - if ( d.contract.type != db.Contract.TYPE_VARORDER ){ + var ds = db.Distribution.manager.search(!$validated && ($end >= from) && ($end < to), true); + for (d in Lambda.array(ds)) { + if (d.contract.type != db.Contract.TYPE_VARORDER) { ds.remove(d); - }else if ( !d.contract.amap.hasPayments() ){ + } else if (!d.contract.amap.hasPayments()) { ds.remove(d); } } - for ( d in ds){ + for (d in ds) { print(d.toString()); - + service.PaymentService.validateDistribution(d); - } - //email + // email var ds = tools.ObjectListTool.deduplicateDistribsByKey(ds); - for ( d in ds ){ + for (d in ds) { // var subj = d.contract.amap.name + t._(": Validation of the distribution of the ") + App.current.view.hDate(d.date); - var subj = t._("[::group::] Validation of the ::date:: distribution",{group : d.contract.amap.name , date : view.hDate(d.date)}); - var html = t._("

As you did not validate it manually after 10 days,
the delivery of the ::deliveryDate:: has been validated automatically

", {deliveryDate:App.current.view.hDate(d.date)}); + var subj = t._("[::group::] Validation of the ::date:: distribution", {group: d.contract.amap.name, date: view.hDate(d.date)}); + var html = t._("

As you did not validate it manually after 10 days,
the delivery of the ::deliveryDate:: has been validated automatically

", + { + deliveryDate: App.current.view.hDate(d.date) + }); App.quickMail(d.contract.amap.contact.email, subj, html); } - } - + /** * Send emails from buffer. * @@ -428,50 +442,50 @@ class Cron extends Controller * you should consider the right amount of emails to send each minute in order to avoid overlaping and getting in concurrency problems. * (like "SELECT * FROM BufferedMail WHERE sdate IS NULL ORDER BY cdate DESC LIMIT 100 FOR UPDATE Lock wait timeout exceeded; try restarting transaction") */ - function sendEmailsfromBuffer(){ + function sendEmailsfromBuffer() { + App.log("Send Emails from Buffer"); print("

Send Emails from Buffer

"); - - //send - for( e in sugoi.db.BufferedMail.manager.search($sdate==null,{limit:50,orderBy:-cdate},false) ){ + + // send + for (e in sugoi.db.BufferedMail.manager.search($sdate == null, {limit: 50, orderBy: -cdate}, false)) { e.lock(); - if(e.isSent()) continue; - + if (e.isSent()) + continue; + + App.log('Send Email id=${e.id} - title=${e.title}'); print('#${e.id} - ${e.title}'); e.finallySend(); Sys.sleep(0.1); } - //delete old emails - var threeMonthsAgo = DateTools.delta(Date.now(), -1000.0*60*60*24*30*3); + // delete old emails + var threeMonthsAgo = DateTools.delta(Date.now(), -1000.0 * 60 * 60 * 24 * 30 * 3); sugoi.db.BufferedMail.manager.delete($cdate < threeMonthsAgo); - //emails that cannot be sent - for( e in sugoi.db.BufferedMail.manager.search($tries>100,{limit:50,orderBy:-cdate},true) ){ - if(e.sender.email != App.config.get("default_email")){ - var str = t._("Sorry, the email entitled ::title:: could not be sent.",{title:e.title}); - App.quickMail(e.sender.email,t._("Email not sent"),str); - } + // emails that cannot be sent + for (e in sugoi.db.BufferedMail.manager.search($tries > 100, {limit: 50, orderBy: -cdate}, true)) { + if (e.sender.email != App.config.get("default_email")) { + var str = t._("Sorry, the email entitled ::title:: could not be sent.", {title: e.title}); + App.quickMail(e.sender.email, t._("Email not sent"), str); + } e.delete(); - } + } } /** * Email product report when orders close - **/ - function sendOrdersByProductWhenOrdersClose(){ - + **/ + function sendOrdersByProductWhenOrdersClose() { var range = tools.DateTool.getLastHourRange(); // Sys.println("Time is "+Date.now()+"
"); // Sys.println('Find all distributions that have closed in the last hour from ${range.from} to ${range.to} \n
'); - - for ( d in db.Distribution.manager.search($orderEndDate >= range.from && $orderEndDate < range.to, false)){ + + for (d in db.Distribution.manager.search($orderEndDate >= range.from && $orderEndDate < range.to, false)) { service.OrderService.sendOrdersByProductReport(d); } - } - - - function print(text){ - Sys.println( text + "
" ); + + function print(text) { + Sys.println(text + "
"); } } diff --git a/src/controller/Messages.hx b/src/controller/Messages.hx index cff5eae..8d3ba56 100755 --- a/src/controller/Messages.hx +++ b/src/controller/Messages.hx @@ -1,211 +1,208 @@ package controller; + import db.Message; import db.UserContract; import sugoi.form.ListData; import sugoi.form.elements.*; import sugoi.form.Form; -class Messages extends Controller -{ - - public function new() - { +class Messages extends Controller { + public function new() { super(); - if (!app.user.canAccessMessages()) throw Redirect("/"); + if (!app.user.canAccessMessages()) + throw Redirect("/"); } - + @tpl("messages/default.mtt") function doDefault() { - - var form = new Form("msg"); - + var form = new Form("msg"); + var senderName = ""; var senderMail = ""; - + if (App.current.session.data.whichUser == 1 && app.user.email2 != null) { senderMail = app.user.email2; senderName = app.user.firstName2 + " " + app.user.lastName2; - - }else { + } else { senderMail = app.user.email; senderName = app.user.firstName + " " + app.user.lastName; } - + var lists = getLists(); - form.addElement( new StringInput("senderName", t._("Sender name"),senderName,true)); - form.addElement( new StringInput("senderMail", t._("Sender E-Mail"),senderMail,true)); - form.addElement( new StringSelect("list", t._("Recipients"),lists,"1", true,null,"style='width:500px;'")); - form.addElement( new StringInput("subject", t._("Subject:"),"",false,null,"style='width:500px;'") ); - form.addElement( new TextArea("text", t._("Message:"), "", false, null, "style='width:500px;height:350px;'") ); - + form.addElement(new StringInput("senderName", t._("Sender name"), senderName, true)); + form.addElement(new StringInput("senderMail", t._("Sender E-Mail"), senderMail, true)); + form.addElement(new StringSelect("list", t._("Recipients"), lists, "1", true, null, "style='width:500px;'")); + form.addElement(new StringInput("subject", t._("Subject:"), "", false, null, "style='width:500px;'")); + form.addElement(new TextArea("text", t._("Message:"), "", false, null, "style='width:500px;height:350px;'")); + if (form.checkToken()) { - var listId = form.getElement("list").value; var dest = getSelection(listId); + + App.log('about to send emails to listId=<$listId> to destination=${dest.length}'); + var mails = []; - for ( d in dest) { - if (d.email != null) mails.push(d.email); - if (d.email2 != null) mails.push(d.email2); + for (d in dest) { + if (d.email != null) + mails.push(d.email); + if (d.email2 != null) + mails.push(d.email2); } - - //send mail confirmation link - var e = new sugoi.mail.Mail(); + + // send mail confirmation link + var e = new sugoi.mail.Mail(); e.setSubject(form.getValueOf("subject")); - for ( x in mails) e.addRecipient(x); - - e.setSender(App.config.get("default_email"),form.getValueOf("senderName")); - e.setReplyTo(form.getValueOf("senderMail"),form.getValueOf("senderName")); - //sender : default email ( explicitly tells that the server send an email on behalf of the user ) - //e.setHeader("Sender", App.config.get("default_email")); - var text :String = form.getValueOf("text"); - var html = app.processTemplate("mail/message.mtt", { text:text,group:app.user.amap,list:getListName(listId) }); + for (x in mails) + e.addRecipient(x); + + e.setSender(App.config.get("default_email"), form.getValueOf("senderName")); + e.setReplyTo(form.getValueOf("senderMail"), form.getValueOf("senderName")); + + App.log('add CC header to message: ${e.getSubject()}'); + e.setHeader("CC", "pvincent@comptoirduvrac.re"); + + // sender : default email ( explicitly tells that the server send an email on behalf of the user ) + // e.setHeader("Sender", App.config.get("default_email")); + var text:String = form.getValueOf("text"); + var html = app.processTemplate("mail/message.mtt", {text: text, group: app.user.amap, list: getListName(listId)}); e.setHtmlBody(html); - - App.sendMail(e,app.user.getAmap(),listId,app.user); - - //store message + + App.sendMail(e, app.user.getAmap(), listId, app.user); + + // store message var lm = new db.Message(); - lm.amap = app.user.amap; + lm.amap = app.user.amap; lm.recipients = Lambda.array(Lambda.map(e.getRecipients(), function(x) return x.email)); lm.title = e.getSubject(); lm.date = Date.now(); lm.body = e.getHtmlBody(); - if (listId != null) lm.recipientListId = listId; + if (listId != null) + lm.recipientListId = listId; lm.sender = app.user; lm.insert(); - throw Ok("/messages", t._("The message has been sent")); } - + view.form = form; - + if (app.user.isAmapManager()) { - view.sentMessages = Message.manager.search($amap == app.user.amap && $recipientListId!=null, {orderBy:-date,limit:20}, false); - }else { - view.sentMessages = Message.manager.search($sender == app.user && $recipientListId!=null && $amap == app.user.amap , {orderBy:-date,limit:20}, false); + view.sentMessages = Message.manager.search($amap == app.user.amap && $recipientListId != null, {orderBy: -date, limit: 20}, false); + } else { + view.sentMessages = Message.manager.search($sender == app.user && $recipientListId != null && $amap == app.user.amap, {orderBy: -date, limit: 20}, + false); } - } - + @tpl("messages/message.mtt") public function doMessage(msg:Message) { - - if (!app.user.isAmapManager() && msg.sender.id != app.user.id) throw Error("/", t._("Non authorized access")); - + if (!app.user.isAmapManager() && msg.sender.id != app.user.id) + throw Error("/", t._("Non authorized access")); + view.list = getListName(msg.recipientListId); view.msg = msg; - - //make status easier to display - var s = new Array<{email:String,success:String,failure:String}>(); + + // make status easier to display + var s = new Array<{email:String, success:String, failure:String}>(); /*if (msg.status != null){ for ( k in msg.status.keys()) { var r = msg.getMailerResultMessage(k); s.push({email:k,success:r.success,failure:r.failure}); } }*/ - + view.status = s; - } - - function getLists() :FormData{ + + function getLists():FormData { var out = [ - {value:'1', label: t._("Everyone")}, - {value:'2', label: t._("The board: persons in charge + contracts + memberships")}, + {value: '1', label: t._("Everyone")}, + {value: '2', label: t._("The board: persons in charge + contracts + memberships")}, ]; - - out.push( { value:'3', label: t._("TEST: me + spouse") } ); - out.push( { value:'4', label: t._("Members without contract/order") } ); - if(app.user.amap.hasMembership()) out.push( { value:'5', label:t._("Memberships to be renewed")} ); - - - var contracts = db.Contract.getActiveContracts(app.user.amap,true); - for ( c in contracts) { - var label = t._("Subscribers") + " " + c.toString(); - out.push({value:'c'+c.id,label:label}); + + out.push({value: '3', label: t._("TEST: me + spouse")}); + out.push({value: '4', label: t._("Members without contract/order")}); + if (app.user.amap.hasMembership()) + out.push({value: '5', label: t._("Memberships to be renewed")}); + + var contracts = db.Contract.getActiveContracts(app.user.amap, true); + for (c in contracts) { + var label = t._("Subscribers") + " " + c.toString(); + out.push({value: 'c' + c.id, label: label}); } - return out ; - + return out; } - + /** * get list name from id * @param listId */ function getListName(listId:String) { var l = getLists(); - + for (ll in l) { - if (ll.value == listId) return ll.label; + if (ll.value == listId) + return ll.label; } - + return null; - } - + function getSelection(listId:String) { if (listId.substr(0, 1) == "c") { - //contrats + // contrats var contract = Std.parseInt(listId.substr(1)); - + var pids = db.Product.manager.search($contractId == contract, false); var pids = Lambda.map(pids, function(x) return x.id); var up = db.UserContract.manager.search($productId in pids, false); - - + var users = []; - for ( order in up) { + for (order in up) { if (!Lambda.has(users, order.user)) { - users.push(order.user); + users.push(order.user); } if (order.user2 != null && !Lambda.has(users, order.user2)) { users.push(order.user2); - } + } } return users; - - }else { + } else { var out = []; - switch(listId) { - case "1": - //tout le monde - out = Lambda.array(app.user.amap.getMembers()); - - case "2": - var users = []; - users.push(app.user.amap.contact); - for ( c in db.Contract.manager.search($amap == app.user.amap)) { - if (!Lambda.has(users, c.contact)) { - users.push(c.contact); + switch (listId) { + case "1": + // tout le monde + out = Lambda.array(app.user.amap.getMembers()); + + case "2": + var users = []; + users.push(app.user.amap.contact); + for (c in db.Contract.manager.search($amap == app.user.amap)) { + if (!Lambda.has(users, c.contact)) { + users.push(c.contact); + } } - } - - //ajouter les autres personnes ayant les droits Admin ou Gestion Adhérents ou Gestion Contrats - for (ua in Lambda.array(db.UserAmap.manager.search($rights != null && $amap == app.user.amap, false))) { - if (ua.hasRight(GroupAdmin) || ua.hasRight(Membership) || ua.hasRight(ContractAdmin())) { - if (!Lambda.has(users, ua.user)) users.push(ua.user); - } - } - - out = users; - - case "3": - //moi - return [app.user]; - case "4": - return Lambda.array(db.User.getUsers_NoContracts()); - case "5": - return Lambda.array(db.User.getUsers_NoMembership()); + + // ajouter les autres personnes ayant les droits Admin ou Gestion Adhérents ou Gestion Contrats + for (ua in Lambda.array(db.UserAmap.manager.search($rights != null && $amap == app.user.amap, false))) { + if (ua.hasRight(GroupAdmin) || ua.hasRight(Membership) || ua.hasRight(ContractAdmin())) { + if (!Lambda.has(users, ua.user)) + users.push(ua.user); + } + } + + out = users; + + case "3": + // moi + return [app.user]; + case "4": + return Lambda.array(db.User.getUsers_NoContracts()); + case "5": + return Lambda.array(db.User.getUsers_NoMembership()); } - + return out; - } } - - - - - -} \ No newline at end of file +}