Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef31c26525 | ||
|
|
ed931b7b2c | ||
|
|
089f137636 | ||
|
|
0426a175aa | ||
|
|
59b7c48a89 | ||
|
|
d13c85be61 | ||
|
|
2714f44b44 | ||
|
|
04cb4343ad | ||
|
|
e94c4eae67 | ||
|
|
47abd95962 | ||
|
|
c346584d46 | ||
|
|
bbeea934e4 | ||
|
|
3c8a2507d9 | ||
|
|
6c0e632ef2 | ||
|
|
f94e005a91 |
+3
-3
@@ -1,7 +1,7 @@
|
||||
*.n
|
||||
*.php
|
||||
config.xml
|
||||
/package-lock.json
|
||||
package-lock.json
|
||||
www/plugin/*
|
||||
tmp/*
|
||||
*node_modules*
|
||||
@@ -30,9 +30,9 @@ 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
|
||||
config-prod.xml
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1.7.0
|
||||
1.8.2
|
||||
|
||||
@@ -26,9 +26,6 @@ install_dev:
|
||||
#template tools
|
||||
haxelib run templo
|
||||
sudo mv temploc2 /usr/bin
|
||||
#extra plugins
|
||||
@if [ $(PLUGINS) = 1 ]; then \
|
||||
fi
|
||||
#install npm dependencies
|
||||
npm install
|
||||
npm run libs:dev
|
||||
@@ -77,6 +74,7 @@ templates:
|
||||
@make LANG=fr ctemplates
|
||||
msgfmt www/lang/texts_fr.po -o www/lang/texts_fr.mo
|
||||
chown www-data:www-data -R www
|
||||
chown www-data:www-data -R lang
|
||||
|
||||
ctemplates:
|
||||
(cd lang/$(LANG)/tpl; temploc2 -macros macros.mtt -output ../tmp/ *.mtt */*.mtt */*/*.mtt)
|
||||
|
||||
@@ -9,7 +9,7 @@ j'ai repris sur la base d'un existant pour adapter au marché local réunionnais
|
||||
## INSTALL FROM SCRATCH (debian-buster)
|
||||
|
||||
* apt install -y curl
|
||||
* curl -sL https://deb.nodesource.com/setup_8.x | bash -
|
||||
* curl -L https://deb.nodesource.com/setup_8.x | bash -
|
||||
* apt install -y nodejs=8.17.0-1nodesource1
|
||||
* apt install -y sudo haxe apache2 make git imagemagick gettext libapache2-mod-neko mariadb-server
|
||||
* mysql -u root <<EOF
|
||||
@@ -28,6 +28,8 @@ EOF
|
||||
ServerName cagettepei
|
||||
DirectoryIndex index.n
|
||||
DocumentRoot /var/www/cagettepei/www/
|
||||
|
||||
|
||||
</VirtualHost>
|
||||
```
|
||||
* sed -i '/<Directory \/var\/www\/>/,/<\/Directory>/ s/AllowOverride None/AllowOverride All/' /etc/apache2/apache2.conf
|
||||
|
||||
Generated
-6188
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -47,5 +47,5 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/bablukid/cagette/issues"
|
||||
},
|
||||
"version": "1.7.0"
|
||||
"version": "1.8.2"
|
||||
}
|
||||
|
||||
+113
-117
@@ -1,110 +1,109 @@
|
||||
import db.User;
|
||||
import thx.semver.Version;
|
||||
import Common;
|
||||
|
||||
class App extends sugoi.BaseApp {
|
||||
|
||||
public static var current : App = null;
|
||||
public static var t : sugoi.i18n.translator.ITranslator;
|
||||
class App extends sugoi.BaseApp {
|
||||
public static var current:App = null;
|
||||
public static var t:sugoi.i18n.translator.ITranslator;
|
||||
public static var config = sugoi.BaseApp.config;
|
||||
|
||||
public var eventDispatcher :hxevents.Dispatcher<Event>;
|
||||
public var plugins : Array<sugoi.plugin.IPlugIn>;
|
||||
|
||||
|
||||
public var eventDispatcher:hxevents.Dispatcher<Event>;
|
||||
public var plugins:Array<sugoi.plugin.IPlugIn>;
|
||||
|
||||
/**
|
||||
* Version management
|
||||
* @doc https://github.com/fponticelli/thx.semver
|
||||
*/
|
||||
//public static var VERSION = ([0,9,2] : Version).withPre("july");
|
||||
//public static var VERSION = ([0,9,2] : Version).withPre(MyMacros.getGitShortSHA(), MyMacros.getGitCommitDate());
|
||||
*/
|
||||
// public static var VERSION = ([0,9,2] : Version).withPre("july");
|
||||
// public static var VERSION = ([0,9,2] : Version).withPre(MyMacros.getGitShortSHA(), MyMacros.getGitCommitDate());
|
||||
public static var VERSION = "cagette-péi " + MyMacros.getGitCommitDate();
|
||||
|
||||
public function new(){
|
||||
|
||||
public function new() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
public static function main() {
|
||||
|
||||
App.t = sugoi.form.Form.translator = new sugoi.i18n.translator.TMap(getTranslationArray(), "fr");
|
||||
sugoi.BaseApp.main();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Init plugins and event dispatcher just before launching the app
|
||||
*/
|
||||
override public function mainLoop() {
|
||||
eventDispatcher = new hxevents.Dispatcher<Event>();
|
||||
plugins = [];
|
||||
//internal plugins
|
||||
// internal plugins
|
||||
plugins.push(new plugin.Tutorial());
|
||||
|
||||
//optionnal plugins
|
||||
|
||||
// optionnal plugins
|
||||
#if plugins
|
||||
plugins.push( new hosted.HostedPlugIn() );
|
||||
plugins.push( new pro.ProPlugIn() );
|
||||
plugins.push( new connector.ConnectorPlugIn() );
|
||||
plugins.push( new pro.LemonwayEC() );
|
||||
plugins.push( new who.WhoPlugIn() );
|
||||
plugins.push(new hosted.HostedPlugIn());
|
||||
plugins.push(new pro.ProPlugIn());
|
||||
plugins.push(new connector.ConnectorPlugIn());
|
||||
plugins.push(new pro.LemonwayEC());
|
||||
plugins.push(new who.WhoPlugIn());
|
||||
#end
|
||||
|
||||
|
||||
super.mainLoop();
|
||||
}
|
||||
|
||||
public function getCurrentGroup(){
|
||||
if (session == null) return null;
|
||||
if (session.data == null ) return null;
|
||||
|
||||
public function getCurrentGroup() {
|
||||
if (session == null)
|
||||
return null;
|
||||
if (session.data == null)
|
||||
return null;
|
||||
var a = session.data.amapId;
|
||||
if (a == null) {
|
||||
return null;
|
||||
}else {
|
||||
return db.Amap.manager.get(a,false);
|
||||
} else {
|
||||
return db.Amap.manager.get(a, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override function beforeDispatch() {
|
||||
|
||||
//send "current page" event
|
||||
event( Page(this.uri) );
|
||||
|
||||
// send "current page" event
|
||||
event(Page(this.uri));
|
||||
|
||||
super.beforeDispatch();
|
||||
}
|
||||
|
||||
|
||||
public function getPlugin(name:String):sugoi.plugin.IPlugIn {
|
||||
for (p in plugins) {
|
||||
if (p.getName() == name) return p;
|
||||
if (p.getName() == name)
|
||||
return p;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function log(t:Dynamic) {
|
||||
if(App.config.DEBUG) {
|
||||
neko.Web.logMessage(Std.string(t)); //write in Apache error log
|
||||
#if weblog
|
||||
Weblog.log(t); //write en Weblog console (https://lib.haxe.org/p/weblog/)
|
||||
#end
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
public function event(e:Event) {
|
||||
if(e==null) return null;
|
||||
if (e == null)
|
||||
return null;
|
||||
this.eventDispatcher.dispatch(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Translate DB objects fields in forms
|
||||
*/
|
||||
public static function getTranslationArray() {
|
||||
//var t = sugoi.i18n.Locale.texts;
|
||||
var out = new Map<String,String>();
|
||||
//out.set("firstName", t._("First name") );
|
||||
//out.set("lastName", t._("Last name"));
|
||||
// var t = sugoi.i18n.Locale.texts;
|
||||
var out = new Map<String, String>();
|
||||
// out.set("firstName", t._("First name") );
|
||||
// out.set("lastName", t._("Last name"));
|
||||
out.set("firstName2", "Prénom du conjoint");
|
||||
out.set("lastName2", "Nom du conjoint");
|
||||
out.set("email2", "e-mail du conjoint");
|
||||
//out.set("pass", t._("Password") );
|
||||
//out.set("address1", t._("address") );
|
||||
//out.set("address2", t._("address") );
|
||||
// out.set("pass", t._("Password") );
|
||||
// out.set("address1", t._("address") );
|
||||
// out.set("address2", t._("address") );
|
||||
out.set("zipCode", "code postal");
|
||||
out.set("city", "commune");
|
||||
out.set("phone", "téléphone");
|
||||
@@ -123,24 +122,24 @@ class App extends sugoi.BaseApp {
|
||||
out.set("txtHome", "Texte en page d'accueil pour les adhérents connectés");
|
||||
out.set("txtDistrib", "Texte à faire figurer sur les listes d'émargement lors des distributions");
|
||||
out.set("extUrl", "URL du site du groupe.");
|
||||
|
||||
|
||||
out.set("distributor1", "Distributeur 1");
|
||||
out.set("distributor2", "Distributeur 2");
|
||||
out.set("distributor3", "Distributeur 3");
|
||||
out.set("distributor4", "Distributeur 4");
|
||||
out.set("distributorNum", "Nbre de distributeurs nécessaires (de 0 à 4)");
|
||||
|
||||
|
||||
out.set("startDate", "Date de début");
|
||||
out.set("endDate", "Date de fin");
|
||||
|
||||
|
||||
out.set("orderStartDate", "Date ouverture des commandes");
|
||||
out.set("orderEndDate", "Date fermeture des commandes");
|
||||
out.set("openingHour", "Heure d'ouverture");
|
||||
out.set("closingHour", "Heure de fermeture");
|
||||
|
||||
out.set("date", "Date de distribution");
|
||||
out.set("active", "actif");
|
||||
|
||||
out.set("orderEndDate", "Date fermeture des commandes");
|
||||
out.set("openingHour", "Heure d'ouverture");
|
||||
out.set("closingHour", "Heure de fermeture");
|
||||
|
||||
out.set("date", "Date de distribution");
|
||||
out.set("active", "actif");
|
||||
|
||||
out.set("contact", "Reponsable");
|
||||
out.set("vendor", "Producteur");
|
||||
out.set("text", "Texte");
|
||||
@@ -170,7 +169,7 @@ class App extends sugoi.BaseApp {
|
||||
out.set("pname", "Produit");
|
||||
out.set("organic", "Agriculture biologique");
|
||||
out.set("hasFloatQt", "Autoriser quantités \"à virgule\"");
|
||||
|
||||
|
||||
out.set("membershipRenewalDate", "Adhésions : Date de renouvellement");
|
||||
out.set("membershipPrice", "Adhésions : Coût de l'adhésion");
|
||||
out.set("UsersCanOrder", "Les adhérents peuvent saisir leur commande en ligne");
|
||||
@@ -193,12 +192,12 @@ class App extends sugoi.BaseApp {
|
||||
out.set("ref", "Référence");
|
||||
out.set("linkText", "Intitulé du lien");
|
||||
out.set("linkUrl", "URL du lien");
|
||||
|
||||
|
||||
out.set("Amap", "AMAP");
|
||||
out.set("GroupedOrders", "Groupement d'achat");
|
||||
out.set("ProducerDrive", "Collectif de producteurs");
|
||||
out.set("FarmShop", "Vente à la ferme");
|
||||
|
||||
|
||||
out.set("regOption", "Inscription de nouveaux adhérents");
|
||||
out.set("Closed", "Fermé : Le coordinateur ajoute les nouveaux adhérents");
|
||||
out.set("WaitingList", "Liste d'attente");
|
||||
@@ -206,102 +205,99 @@ class App extends sugoi.BaseApp {
|
||||
out.set("Full", "Complet : Le groupe n'accepte plus de nouveaux adhérents");
|
||||
out.set("percent", "Pourcentage");
|
||||
out.set("pinned", "Mets en avant les produits");
|
||||
|
||||
|
||||
out.set("CagetteNetwork", "Me lister dans l'annuaire des groupes Cagette.net");
|
||||
out.set("unitType", "Unité");
|
||||
out.set("qt", "Quantité");
|
||||
out.set("Unit", "Pièce");
|
||||
out.set("Kilogram", "Kilogrammes");
|
||||
out.set("Gram", "Grammes");
|
||||
out.set("Litre", "Litres");
|
||||
out.set("Litre", "Litres");
|
||||
out.set("htPrice", "Prix H.T");
|
||||
out.set("amount", "Montant");
|
||||
|
||||
|
||||
out.set("HasPayments", "Gestion des paiements");
|
||||
|
||||
|
||||
out.set("byMember", "Par adhérent");
|
||||
out.set("byProduct", "Par produit");
|
||||
|
||||
|
||||
out.set("variablePrice", "Variable price based on weight");
|
||||
return out;
|
||||
}
|
||||
|
||||
public function populateAmapMembers() {
|
||||
|
||||
public function populateAmapMembers() {
|
||||
return user.amap.getMembersFormElementData();
|
||||
}
|
||||
|
||||
public static function getMailer():sugoi.mail.IMailer {
|
||||
|
||||
var mailer : sugoi.mail.IMailer = new sugoi.mail.BufferedMailer();
|
||||
|
||||
if(App.config.DEBUG){
|
||||
|
||||
//Dev env : emails are written to tmp folder
|
||||
public static function getMailer():sugoi.mail.IMailer {
|
||||
var mailer:sugoi.mail.IMailer = new sugoi.mail.BufferedMailer();
|
||||
|
||||
if (App.config.DEBUG) {
|
||||
App.log("DEBUGEmailer enabled => emails are written to tmp folder");
|
||||
mailer = new sugoi.mail.DebugMailer();
|
||||
}else{
|
||||
|
||||
if (sugoi.db.Variable.get("mailer") == null){
|
||||
} else {
|
||||
if (sugoi.db.Variable.get("mailer") == null) {
|
||||
var msg = sugoi.i18n.Locale.texts._("Please configure the email settings in a <href='/admin/emails'>this section</a>");
|
||||
throw sugoi.ControllerAction.ErrorAction("/",msg);
|
||||
throw sugoi.ControllerAction.ErrorAction("/", msg);
|
||||
}
|
||||
|
||||
if (sugoi.db.Variable.get("mailer") == "mandrill"){
|
||||
//Buffered emails with Mandrill
|
||||
untyped mailer.defineFinalMailer("mandrill");
|
||||
}else{
|
||||
//Buffered emails with SMTP
|
||||
if (sugoi.db.Variable.get("mailer") == "mandrill") {
|
||||
// Buffered emails with Mandrill
|
||||
untyped mailer.defineFinalMailer("mandrill");
|
||||
} else {
|
||||
// Buffered emails with SMTP
|
||||
untyped mailer.defineFinalMailer("smtp");
|
||||
}
|
||||
}
|
||||
return mailer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send an email
|
||||
*/
|
||||
public static function sendMail(m:sugoi.mail.Mail, ?group:db.Amap, ?listId:String, ?sender:db.User){
|
||||
|
||||
if (group == null) group = App.current.user == null ? null:App.current.user.getAmap();
|
||||
|
||||
current.event(SendEmail(m));
|
||||
|
||||
var params = group==null ? null : {remoteId:group.id};
|
||||
public static function sendMail(m:sugoi.mail.Mail, ?group:db.Amap, ?listId:String, ?sender:db.User) {
|
||||
if (group == null)
|
||||
group = App.current.user == null ? null : App.current.user.getAmap();
|
||||
|
||||
getMailer().send(m,params,function(o){});
|
||||
|
||||
current.event(SendEmail(m));
|
||||
|
||||
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){
|
||||
var e = new sugoi.mail.Mail();
|
||||
|
||||
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);
|
||||
e.setSender(App.config.get("default_email"),"Cagette.net");
|
||||
var html = App.current.processTemplate("mail/message.mtt", {text:html,group:group});
|
||||
e.setRecipient(to);
|
||||
e.setSender(App.config.get("default_email"), "Cagette.net");
|
||||
var html = App.current.processTemplate("mail/message.mtt", {text: html, group: group});
|
||||
e.setHtmlBody(html);
|
||||
App.sendMail(e);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* process a template and returns the generated string
|
||||
* @param tpl
|
||||
* @param ctx
|
||||
*/
|
||||
public function processTemplate(tpl:String, ctx:Dynamic):String {
|
||||
|
||||
Reflect.setField(ctx, 'HOST', App.config.HOST);
|
||||
Reflect.setField(ctx, 'hDate', App.current.view.hDate);
|
||||
//i18n functions
|
||||
// i18n functions
|
||||
ctx._ = App.current.view._;
|
||||
ctx.__ = App.current.view.__;
|
||||
|
||||
|
||||
var tpl = loadTemplate(tpl);
|
||||
var html = tpl.execute(ctx);
|
||||
var html = tpl.execute(ctx);
|
||||
#if php
|
||||
if ( html.substr(0, 4) == "null") html = html.substr(4);
|
||||
if (html.substr(0, 4) == "null")
|
||||
html = html.substr(4);
|
||||
#end
|
||||
return html;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+529
-523
File diff suppressed because it is too large
Load Diff
+256
-242
@@ -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("<h1>" + App.config.NAME + " : ERRORS</h1>");
|
||||
for (e in errors) {
|
||||
report.add("<div><pre>"+e.error + " at URL " + e.url + " ( user : " + (e.user!=null?e.user.toString():"none") + ", IP : " + e.ip + ")</pre></div><hr/>");
|
||||
report.add("<div><pre>" + e.error + " at URL " + e.url + " ( user : " + (e.user != null ? e.user.toString() : "none") + ", IP : " + e.ip
|
||||
+ ")</pre></div><hr/>");
|
||||
}
|
||||
|
||||
|
||||
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+"<br/>\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+"<br/>\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<Int> = 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<Int> = 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<Int,db.Distribution>();
|
||||
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<Int, db.Distribution>();
|
||||
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 <String,{
|
||||
*/
|
||||
var users = new Map<String, {
|
||||
user:db.User,
|
||||
distrib:db.Distribution,
|
||||
products:Array<db.UserContract>,
|
||||
vendors:Array<db.Vendor>
|
||||
vendors:Array<db.Vendor>
|
||||
}>();
|
||||
|
||||
|
||||
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("<br/>\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("<br/>\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("<br/>\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("<br/>\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 <b>::date::</b>", {date:view.hDate(u.distrib.date)});
|
||||
if (db.User.UserFlags.HasEmailNotifOuverture == flag) {
|
||||
// order opening notif
|
||||
text = t._("Opening of orders for the delivery of <b>::date::</b>", {date: view.hDate(u.distrib.date)});
|
||||
text += "<br/>";
|
||||
text += t._("The following suppliers are involved :");
|
||||
text += "<br/><ul>";
|
||||
for ( v in u.vendors) {
|
||||
for (v in u.vendors) {
|
||||
text += "<li>" + v + "</li>";
|
||||
}
|
||||
text += "</ul>";
|
||||
|
||||
}else{
|
||||
//Distribution notif to the users
|
||||
} else {
|
||||
// Distribution notif to the users
|
||||
var d = u.distrib;
|
||||
text = t._("Do not forget the delivery on <b>::day::</b> from ::from:: to ::to::<br/>", {day:view.dDate(d.date),from:view.hHour(d.date),to:view.hHour(d.end)});
|
||||
text = t._("Do not forget the delivery on <b>::day::</b> from ::from:: to ::to::<br/>",
|
||||
{day: view.dDate(d.date), from: view.hHour(d.date), to: view.hHour(d.end)});
|
||||
text += t._("Your products to collect :") + "<br/><ul>";
|
||||
for ( p in u.products) {
|
||||
text += "<li>"+p.quantity+" x "+p.product.getName();
|
||||
for (p in u.products) {
|
||||
text += "<li>" + 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 += "</ul>";
|
||||
}
|
||||
|
||||
|
||||
if (u.distrib.isDistributor(u.user)) {
|
||||
text += t._("<b>Warning: you are in charge of the delivery ! Do not forget to print the attendance sheet.</b>");
|
||||
}
|
||||
|
||||
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._("<p>This step is important in order to:</p>");
|
||||
explain += t._("<ul><li>Update orders if delivered quantities are different from ordered quantities</li>");
|
||||
explain += t._("<li>Confirm the reception of payments (checks, cash, transfers) in order to mark orders as 'paid'</li></ul>");
|
||||
|
||||
|
||||
/*
|
||||
* 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._("<p>Your distribution just finished, don't forget to <b>validate</b> it</p>");
|
||||
html += explain;
|
||||
html += t._("<p><a href='::distriburl::'>Click here to validate the distribution</a> (You must be connected to your group Cagette)", {distriburl:url});
|
||||
|
||||
html += t._("<p><a href='::distriburl::'>Click here to validate the distribution</a> (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._("<p>Reminder: you have a delivery to validate.</p>");
|
||||
html += explain;
|
||||
html += t._("<p><a href='::distriburl::'>Click here to validate the delivery</a> (You must be connected to your Cagette group)", {distriburl:url});
|
||||
|
||||
html += t._("<p><a href='::distriburl::'>Click here to validate the delivery</a> (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._("<p>As you did not validate it manually after 10 days, <br/>the delivery of the ::deliveryDate:: has been validated automatically</p>", {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._("<p>As you did not validate it manually after 10 days, <br/>the delivery of the ::deliveryDate:: has been validated automatically</p>",
|
||||
{
|
||||
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("<h3>Send Emails from Buffer</h3>");
|
||||
|
||||
//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 <b>::title::</b> 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 <b>::title::</b> 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()+"<br/>");
|
||||
// Sys.println('Find all distributions that have closed in the last hour from ${range.from} to ${range.to} \n<br/>');
|
||||
|
||||
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 + "<br/>" );
|
||||
|
||||
function print(text) {
|
||||
Sys.println(text + "<br/>");
|
||||
}
|
||||
}
|
||||
|
||||
+148
-127
@@ -1,211 +1,232 @@
|
||||
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);
|
||||
var subject = form.getValueOf("subject");
|
||||
|
||||
App.log('about to send email <$subject> to listId=<$listId> to ${dest.length} recipient(s)');
|
||||
// Sys.command("sh", [
|
||||
// "-c",
|
||||
// "sendemail -f no-reply@comptoirduvrac.re -s mail1.zourit.net:587 -t pvincent@comptoirduvrac.re -bcc 'pvincent974@gmail.com, pvincent974@laposte.net' -u TEST -m coucou -xu postmaster@comptoirduvrac.re -xp QqQeAPT6EpoK"
|
||||
// ]);
|
||||
|
||||
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();
|
||||
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) });
|
||||
|
||||
// send mail confirmation link
|
||||
var e = new sugoi.mail.Mail();
|
||||
e.setSender(App.config.get("default_email"));
|
||||
e.setSubject(subject);
|
||||
|
||||
var replyTo = form.getValueOf("senderMail");
|
||||
var replyToName = form.getValueOf("senderName");
|
||||
if (replyTo != null)
|
||||
e.setReplyTo(replyTo, replyToName);
|
||||
|
||||
if (mails.length > 1) {
|
||||
var cc = mails.join(",");
|
||||
App.log('add header Cc: $cc');
|
||||
e.setHeader("CC:", cc);
|
||||
// for (x in mails)
|
||||
// e.addRecipient(x);
|
||||
e.addRecipient(e.getSender().email);
|
||||
} else {
|
||||
App.log('no header');
|
||||
e.addRecipient(mails[0]);
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// Sys.command("sendemail", [
|
||||
// "-f", "no-reply@comptoirduvrac.re", "-s", "mail1.zourit.net:587", "-t", "pvincent@comptoirduvrac.re", "-bcc",
|
||||
// "pvincent974@gmail.com,pvincent974@laposte.net", "-u", subject, "-m", "alors tout va bien", "-xu", "postmaster@comptoirduvrac.re", "-xp",
|
||||
// "QqQeAPT6EpoK"
|
||||
// ]);
|
||||
|
||||
sys.io.File.saveContent('/tmp/my_file.json', "CONTENT");
|
||||
|
||||
// store message
|
||||
var lm = new db.Message();
|
||||
lm.amap = app.user.amap;
|
||||
lm.recipients = Lambda.array(Lambda.map(e.getRecipients(), function(x) return x.email));
|
||||
lm.amap = app.user.amap;
|
||||
// lm.recipients = Lambda.array(Lambda.map(e.getRecipients(), function(x) return x.email));
|
||||
lm.recipients = mails;
|
||||
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<String>{
|
||||
|
||||
function getLists():FormData<String> {
|
||||
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;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user