You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

595 lines
18 KiB

package controller;
import db.UserContract;
import sugoi.form.Form;
import sugoi.form.elements.HourDropDowns;
using tools.DateTool;
import Common;
class Distribution extends Controller
{
/**
* Attendance sheet by user-product (single distrib)
*/
@tpl('distribution/list.mtt')
function doList(d:db.Distribution) {
view.distrib = d;
view.place = d.place;
view.contract = d.contract;
view.orders = service.OrderService.prepare(d.getOrders());
}
/**
* Attendance sheet by product-user (single distrib)
*/
@tpl('distribution/listByProductUser.mtt')
function doListByProductUser(d:db.Distribution) {
view.distrib = d;
view.place = d.place;
view.contract = d.contract;
// view.orders = UserContract.prepare(d.getOrders());
//make a 2 dimensons table : data[userId][productId]
//WARNING : BUGS WILL APPEAR if there is many Order line for the same product
var data = new Map<Int,Map<Int,UserOrder>>();
var products = [];
var uo = d.getOrders();
for(o in uo){
products.push(o.product);
}
for ( o in service.OrderService.prepare(uo)) {
var user = data[o.userId];
if (user == null) user = new Map();
user[o.productId] = o;
data[o.userId] = user;
}
//products
var products = tools.ObjectListTool.deduplicate(products);
products.sort(function(b, a) {
return (a.name < b.name)?1:-1;
});
view.products = products;
//users
var users = Lambda.array(d.getUsers());
// var usersMap = tools.ObjectListTool.toIdMap(users);
users.sort(function(b, a) {
return (a.lastName < b.lastName)?1:-1;
});
view.users = users;
// view.usersMap = usersMap;
view.orders = data;
//total to pay by user
view.totalByUser = function(uid:Int){
var total = 0.0;
for( o in data[uid]) total+= o.total;
return total;
}
//total qty of product
view.totalByProduct = function(pid:Int){
var total = 0.0;
for( uid in data.keys()){
var x = data[uid][pid];
if(x!=null) total+= x.quantity;
}
return total;
}
}
function getUser(uid:Int):db.User {
return db.User.manager.get(uid, false);
}
function getBasket(userId, placeId, date){
var user = getUser(userId);
var place = db.Place.manager.get(placeId, false);
return db.Basket.getOrCreate(user, place, date);
}
/**
* Attendance sheet to print ( mutidistrib )
*/
@tpl('distribution/listByDate.mtt')
function doListByDate(date:Date,place:db.Place, ?type:String, ?fontSize:String) {
if (!app.user.isContractManager()) throw Error('/', t._("Forbidden action"));
view.place = place;
if (type == null) {
//display form
var f = new sugoi.form.Form("listBydate", null, sugoi.form.Form.FormMethod.GET);
f.addElement(new sugoi.form.elements.RadioGroup("type", "Affichage", [
{ value:"one", label:t._("One person per page") },
{ value:"contract", label:t._("One person per page sorted by contract") },
{ value:"all", label:t._("All") },
{ value:"allshort", label:t._("All but without prices and totals") },
],"all"));
f.addElement(new sugoi.form.elements.RadioGroup("fontSize", "Taille de police", [
{ value:"S" , label:"S" },
{ value:"M" , label:"M" },
{ value:"L" , label:"L" },
{ value:"XL", label:"XL" },
], "S", "S", false));
view.form = f;
app.setTemplate("form.mtt");
if (f.checkToken()) {
var suburl = f.getValueOf("type")+"/"+f.getValueOf("fontSize");
var url = '/distribution/listByDate/' + date.toString().substr(0, 10)+"/"+place.id+"/"+suburl;
throw Redirect( url );
}
return;
}else {
view.date = date;
view.fontRatio = switch(fontSize){
case "M" : 125; //100x1.25
case "L" : 156; //125x1.25
case "XL": 195; //156x1.25
default : 100;
};
switch(type) {
case "one":
app.setTemplate("distribution/listByDateOnePage.mtt");
case "allshort" :
app.setTemplate("distribution/listByDateShort.mtt");
case "contract" :
app.setTemplate("distribution/listByDateOnePageContract.mtt");
}
var d1 = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
var d2 = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59);
var contracts = app.user.amap.getActiveContracts(true);
//var cids = Lambda.map(contracts, function(c) return c.id);
var cconst = [];
var cvar = [];
for ( c in contracts) {
if (c.type == db.Contract.TYPE_CONSTORDERS) cconst.push(c.id);
if (c.type == db.Contract.TYPE_VARORDER) cvar.push(c.id);
}
//commandes variables
var distribs = db.Distribution.manager.search(($contractId in cvar) && $date >= d1 && $date <= d2 && $place==place, false);
var orders = db.UserContract.manager.search($distributionId in Lambda.map(distribs, function(d) return d.id) , { orderBy:userId } );
//commandes fixes
var distribs = db.Distribution.manager.search(($contractId in cconst) && $date >= d1 && $date <= d2 && $place==place, false);
var orders = Lambda.array(orders);
for ( d in distribs) {
var orders2 = db.UserContract.manager.search($productId in Lambda.map(d.contract.getProducts(), function(d) return d.id) , { orderBy:userId } );
orders = orders.concat(Lambda.array(orders2));
}
var orders3 = service.OrderService.prepare(Lambda.list(orders));
view.orders = orders3;
if (type == "csv") {
var data = new Array<Dynamic>();
for (o in orders3) {
var basket = getBasket(o.userId,view.place.id,view.date);
data.push( {
"NUM": basket.num,
"ADHERENT":o.userName,
"PRODUIT":o.productName,
"QTÉ":o.quantity,
// "price":view.formatNum(o.productPrice),
// "fees":view.formatNum(o.fees),
// "total":view.formatNum(o.total),
// "paid":o.paid
});
}
sugoi.tools.Csv.printCsvDataFromObjects(data, ["NUM","ADHERENT", "PRODUIT", "QTÉ"],"Export-commandes-"+date.toString().substr(0,10)+"-Cagette");
//sugoi.tools.Csv.printCsvDataFromObjects(data, ["NUM","ADHERENT", "PRODUIT", "QTÉ","price","fees","total","paid"],"Export-commandes-"+date.toString().substr(0,10)+"-Cagette");
//sugoi.tools.Csv.printCsvDataFromObjects(data, ["NUM","ADHERENT", "PRODUIT", "price", "quantity","fees","total", "paid"],"Export-commandes-"+date.toString().substr(0,10)+"-Cagette");
return;
}
}
}
function doDelete(d:db.Distribution) {
if (!app.user.isContractManager(d.contract)) throw Error('/', t._("Forbidden action"));
var contractId = d.contract.id;
try {
service.DistributionService.delete(d);
}
catch(e:tink.core.Error){
throw Error("/contractAdmin/distributions/" + contractId, e.message);
}
throw Ok("/contractAdmin/distributions/" + contractId, t._("the delivery has been deleted"));
}
/**
* Edit a distribution
*/
@tpl('form.mtt')
function doEdit(d:db.Distribution) {
if (!app.user.isContractManager(d.contract)) throw Error('/', t._('Forbidden action') );
var contract = d.contract;
var form = sugoi.form.Form.fromSpod(d);
form.removeElement(form.getElement("contractId"));
form.removeElement(form.getElement("end"));
form.removeElement(form.getElement("distributionCycleId"));
var x = new sugoi.form.elements.HourDropDowns("end", t._("End time") ,d.end,true);
form.addElement(x, 3);
if (d.contract.type == db.Contract.TYPE_VARORDER ) {
form.addElement(new sugoi.form.elements.DatePicker("orderStartDate", t._("Orders opening date"), d.orderStartDate));
form.addElement(new sugoi.form.elements.DatePicker("orderEndDate", t._("Orders closing date"), d.orderEndDate));
}
if (form.isValid()) {
var orderStartDate = null;
var orderEndDate = null;
try{
if (d.contract.type == db.Contract.TYPE_VARORDER ) {
orderStartDate = form.getValueOf("orderStartDate");
orderEndDate = form.getValueOf("orderEndDate");
}
d = service.DistributionService.edit(d,
form.getValueOf("date"),
form.getValueOf("end"),
form.getValueOf("placeId"),
form.getValueOf("distributor1Id"),
form.getValueOf("distributor2Id"),
form.getValueOf("distributor3Id"),
form.getValueOf("distributor4Id"),
orderStartDate,
orderEndDate);
}
catch(e:tink.core.Error){
throw Error('/contractAdmin/distributions/' + contract.id,e.message);
}
if (d.date == null) {
var msg = t._("The distribution has been proposed to the supplier, please wait for its validation");
throw Ok('/contractAdmin/distributions/'+contract.id, msg );
}
else {
throw Ok('/contractAdmin/distributions/'+contract.id, t._("The distribution has been recorded") );
}
}
else {
app.event(PreEditDistrib(d));
}
view.form = form;
view.title = t._("Edit a distribution");
}
@tpl('form.mtt')
function doEditCycle(d:db.DistributionCycle) {
if (!app.user.isContractManager(d.contract)) throw Error('/', 'Action interdite');
var form = sugoi.form.Form.fromSpod(d);
form.removeElement(form.getElement("contractId"));
if (form.isValid()) {
form.toSpod(d); //update model
d.update();
throw Ok('/contractAdmin/distributions/'+d.contract.id, t._("The delivery is now up to date"));
}
view.form = form;
view.title = t._("Modify a delivery");
}
@tpl("form.mtt")
public function doInsert(contract:db.Contract) {
if (!app.user.isContractManager(contract)) throw Error('/', t._('Forbidden action') );
var d = new db.Distribution();
d.place = contract.amap.getMainPlace();
var form = sugoi.form.Form.fromSpod(d);
form.removeElement(form.getElement("contractId"));
form.removeElement(form.getElement("distributionCycleId"));
form.removeElement(form.getElement("end"));
var x = new sugoi.form.elements.HourDropDowns("end", t._("End time") );
form.addElement(x, 3);
//default values
form.getElement("date").value = DateTool.now().deltaDays(30).setHourMinute(19, 0);
form.getElement("end").value = DateTool.now().deltaDays(30).setHourMinute(20, 0);
if (contract.type == db.Contract.TYPE_VARORDER ) {
form.addElement(new sugoi.form.elements.DatePicker("orderStartDate", t._("Orders opening date"),DateTool.now().deltaDays(10).setHourMinute(8, 0)));
form.addElement(new sugoi.form.elements.DatePicker("orderEndDate", t._("Orders closing date"),DateTool.now().deltaDays(20).setHourMinute(23, 59)));
}
if (form.isValid()) {
var createdDistrib = null;
var orderStartDate = null;
var orderEndDate = null;
try {
if (contract.type == db.Contract.TYPE_VARORDER ) {
orderStartDate = form.getValueOf("orderStartDate");
orderEndDate = form.getValueOf("orderEndDate");
}
createdDistrib = service.DistributionService.create(
contract,
form.getValueOf("date"),
form.getValueOf("end"),
form.getValueOf("placeId"),
form.getValueOf("distributor1Id"),
form.getValueOf("distributor2Id"),
form.getValueOf("distributor3Id"),
form.getValueOf("distributor4Id"),
orderStartDate,
orderEndDate);
}
catch(e:tink.core.Error){
throw Error('/contractAdmin/distributions/' + contract.id,e.message);
}
if (createdDistrib.date == null) {
var html = t._("Your request for a delivery has been sent to <b>::supplierName::</b>.<br/>Be patient, you will receive an e-mail indicating if the request has been validated or refused.", {supplierName:contract.vendor.name});
var btn = "<a href='/contractAdmin/distributions/" + contract.id + "' class='btn btn-primary'>OK</a>";
App.current.view.extraNotifBlock = App.current.processTemplate("block/modal.mtt",{html:html,title:t._("Distribution request sent"),btn:btn} );
} else {
throw Ok('/contractAdmin/distributions/'+ createdDistrib.contract.id , t._("The distribution has been recorded") );
}
}else{
//event
app.event(PreNewDistrib(contract));
}
view.form = form;
view.title = t._("Create a distribution");
}
/**
* create a distribution cycle for a contract
*/
@tpl("form.mtt")
public function doInsertCycle(contract:db.Contract) {
if (!app.user.isContractManager(contract)) throw Error('/', t._("Forbidden action"));
var dc = new db.DistributionCycle();
dc.place = contract.amap.getMainPlace();
var form = sugoi.form.Form.fromSpod(dc);
form.removeElementByName("contractId");
form.getElement("startDate").value = DateTool.now();
form.getElement("endDate").value = DateTool.now().deltaDays(30);
//start hour
form.removeElementByName("startHour");
var x = new HourDropDowns("startHour", t._("Start time"), DateTool.now().setHourMinute( 19, 0) , true);
form.addElement(x, 5);
//end hour
form.removeElement(form.getElement("endHour"));
var x = new HourDropDowns("endHour", t._("End time"), DateTool.now().setHourMinute(20, 0), true);
form.addElement(x, 6);
if (contract.type == db.Contract.TYPE_VARORDER){
form.getElement("daysBeforeOrderStart").value = 10;
form.getElement("daysBeforeOrderStart").required = true;
form.removeElementByName("openingHour");
var x = new HourDropDowns("openingHour", t._("Opening time"), DateTool.now().setHourMinute(8, 0) , true);
form.addElement(x, 8);
form.getElement("daysBeforeOrderEnd").value = 2;
form.getElement("daysBeforeOrderEnd").required = true;
form.removeElementByName("closingHour");
var x = new HourDropDowns("closingHour", t._("Closing time"), DateTool.now().setHourMinute(23, 0) , true);
form.addElement(x, 10);
}else{
form.removeElementByName("daysBeforeOrderStart");
form.removeElementByName("daysBeforeOrderEnd");
form.removeElementByName("openingHour");
form.removeElementByName("closingHour");
}
if (form.isValid()) {
var createdDistribCycle = null;
var daysBeforeOrderStart = null;
var daysBeforeOrderEnd = null;
var openingHour = null;
var closingHour = null;
try{
if (contract.type == db.Contract.TYPE_VARORDER) {
daysBeforeOrderStart = form.getValueOf("daysBeforeOrderStart");
daysBeforeOrderEnd = form.getValueOf("daysBeforeOrderEnd");
openingHour = form.getValueOf("openingHour");
closingHour = form.getValueOf("closingHour");
}
createdDistribCycle = service.DistributionService.createCycle(
contract,
form.getElement("cycleType").getValue(),
form.getValueOf("startDate"),
form.getValueOf("endDate"),
form.getValueOf("startHour"),
form.getValueOf("endHour"),
daysBeforeOrderStart,
daysBeforeOrderEnd,
openingHour,
closingHour,
form.getValueOf("placeId"));
}
catch(e:tink.core.Error){
throw Error('/contractAdmin/distributions/' + contract.id,e.message);
}
if (createdDistribCycle != null) {
throw Ok('/contractAdmin/distributions/'+ contract.id, t._("The delivery has been saved"));
}
}
else{
dc.contract = contract;
app.event(PreNewDistribCycle(dc));
}
view.form = form;
view.title = t._("Schedule a recurrent delivery");
}
/**
* Delete a distribution cycle
*/
public function doDeleteCycle(cycle:db.DistributionCycle){
if (!app.user.isContractManager(cycle.contract)) throw Error('/', t._("Forbidden action"));
var contractId = cycle.contract.id;
var messages = service.DistributionService.deleteCycleDistribs(cycle);
if (messages.length > 0){
App.current.session.addMessage( messages.join("<br/>"),true);
}
throw Ok("/contractAdmin/distributions/" + contractId, t._("Recurrent deliveries deleted"));
}
/**
* Doodle-like participation planning
*/
@tpl("distribution/planning.mtt")
public function doPlanning(contract:db.Contract) {
view.contract = contract;
var doodle = new Map<Int,{user:db.User,planning:Map<Int,Bool>}>();
var distribs = contract.getDistribs(true, 150);
for ( d in distribs ) {
for (u in [d.distributor1, d.distributor2, d.distributor3, d.distributor4]) {
if (u != null) {
var udoodle = doodle.get(u.id);
if (udoodle == null) udoodle = { user:u, planning:new Map<Int,Bool>() };
udoodle.planning.set(d.id, true);
doodle.set(u.id, udoodle);
}
}
}
view.distribs = distribs;
view.doodle = doodle;
}
/**
* Ajax service for doPlanning()
*/
public function doRegister(args: { register:Bool, distrib:db.Distribution } ) {
if (args != null) {
var d = args.distrib;
d.lock();
if (args.register) {
if (d.distributor1 == null) d.distributor1 = app.user;
else if (d.distributor2 == null) d.distributor2 = app.user;
else if (d.distributor3 == null) d.distributor3 = app.user;
else if (d.distributor4 == null) d.distributor4 = app.user;
}else {
if (d.distributor1 == app.user) d.distributor1 = null;
else if (d.distributor2 == app.user) d.distributor2 = null;
else if (d.distributor3 == app.user) d.distributor3 = null;
else if (d.distributor4 == app.user) d.distributor4 = null;
}
d.update();
}
}
/**
* Validate a multi-distrib
* @param date
* @param place
*/
@tpl('distribution/validate.mtt')
public function doValidate(date:Date, place:db.Place){
if (!app.user.isAmapManager()) throw t._("Forbidden access");
var md = MultiDistrib.get(date, place, db.Contract.TYPE_VARORDER);
view.confirmed = md.checkConfirmed();
view.users = md.getUsers();
view.date = date;
view.place = place;
}
/**
* Admin can autovalidate a multidistrib
*/
@admin
public function doAutovalidate(date:Date,place:db.Place){
var md = MultiDistrib.get(date,place,db.Contract.TYPE_VARORDER);
for ( d in md.distributions){
if(d.validated) continue;
service.PaymentService.validateDistribution(d);
}
throw Ok("/contractAdmin",t._("This distribution have been validated"));
}
@admin
public function doUnvalidate(date:Date,place:db.Place){
var md = MultiDistrib.get(date,place,db.Contract.TYPE_VARORDER);
for ( d in md.distributions){
if(!d.validated) continue;
service.PaymentService.unvalidateDistribution(d);
}
throw Ok("/contractAdmin",t._("This distribution have been Unvalidated"));
}
}