}>();
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: []
};
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");
// 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");
}
}
// 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);
}
// 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) {
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: []
};
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);
}
}
}
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
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)});
text += "
";
text += t._("The following suppliers are involved :");
text += "
";
for (v in u.vendors) {
text += "- " + v + "
";
}
text += "
";
} 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._("Your products to collect :") + "
";
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") + " ";
if (u.user == p.user)
text += p.user2.getCoupleName();
else
text += p.user.getCoupleName();
}
text += "
";
}
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 {
var m = new Mail();
m.setSender(App.config.get("default_email"), t._("Cagette.net"));
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
}
}
}
}
}
/**
* Check if there is a multi-distrib to validate.
*
* Autovalidate it after 10 days
*/
function distribValidationNotif() {
var now = Date.now();
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) {
ds.remove(d);
} else if (!d.contract.amap.hasPayments()) {
ds.remove(d);
}
}
var ds = tools.ObjectListTool.deduplicateDistribsByKey(ds);
var view = App.current.view;
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 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});
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) {
ds.remove(d);
} else if (!d.contract.amap.hasPayments()) {
ds.remove(d);
}
}
var ds = tools.ObjectListTool.deduplicateDistribsByKey(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 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});
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);
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) {
ds.remove(d);
} else if (!d.contract.amap.hasPayments()) {
ds.remove(d);
}
}
for (d in ds) {
print(d.toString());
service.PaymentService.validateDistribution(d);
}
// email
var ds = tools.ObjectListTool.deduplicateDistribsByKey(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)
});
App.quickMail(d.contract.amap.contact.email, subj, html);
}
}
/**
* Send emails from buffer.
*
* Warning, if the cron is executed each minute,
* 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() {
App.log("Send Emails from Buffer");
// send
for (e in sugoi.db.BufferedMail.manager.search($sdate == null, {limit: 50, orderBy: -cdate}, false)) {
e.lock();
if (e.isSent())
continue;
App.log('Send Email id=#${e.id} - title=${e.title}');
e.finallySend();
Sys.sleep(0.1);
}
// 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);
}
e.delete();
}
}
/**
* Email product report when orders close
**/
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)) {
service.OrderService.sendOrdersByProductReport(d);
}
}
function print(text) {
Sys.println(text + "
");
}
}