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.
 
 
 
 
 
 

385 lines
10 KiB

package;
import Common;
using tools.ObjectListTool;
using Lambda;
using tools.ObjectListTool;
/**
* MultiDistrib represents many db.Distribution
which happen on the same day + same place.
*
* @author fbarbut
*/
class MultiDistrib
{
public var distributions : Array<db.Distribution>;
public var contracts : Array<db.Contract>;
//public var actions : Array<Link>;
public var extraHtml : String;
public var type : Null<Int>; //contract type, both contract types cannot be mixed in a same multidistrib.
public function new(){
distributions = [];
contracts = [];
extraHtml = "";
//actions = [];
}
public static function get(date:Date, place:db.Place,contractType:Int){
var m = new MultiDistrib();
var start = tools.DateTool.setHourMinute(date, 0, 0);
var end = tools.DateTool.setHourMinute(date, 23, 59);
var contracts = place.amap.getContracts().array();
//filter by type
if(contractType==db.Contract.TYPE_VARORDER){
for(c in contracts.copy() ){
if(c.type!=db.Contract.TYPE_VARORDER) contracts.remove(c);
}
}else if(contractType==db.Contract.TYPE_CONSTORDERS){
for(c in contracts.copy() ){
if(c.type!=db.Contract.TYPE_CONSTORDERS) contracts.remove(c);
}
}
var cids = contracts.getIds();
m.distributions = db.Distribution.manager.search(($contractId in cids) && ($date >= start) && ($date <= end) && $place==place, { orderBy:date }, false).array();
m.type = contractType;
return m;
}
/**
Get multidistribs from a time range + place + type
**/
public static function getFromTimeRange(group:db.Amap,from:Date,to:Date,?contractType:Int):Array<MultiDistrib>{
var multidistribs = [];
var start = tools.DateTool.setHourMinute(from, 0, 0);
var end = tools.DateTool.setHourMinute(to, 23, 59);
var cids = group.getContracts().getIds();
var distributions = db.Distribution.manager.search(($contractId in cids) && ($date >= start) && ($date <= end) , { orderBy:date }, false).array();
//sort by day-place-type
var multidistribs = new Map<String,MultiDistrib>();
for ( d in distributions){
//filter by contractType
if(contractType!=null){
if(d.contract.type!=contractType) continue;
}
var key = d.getKey() + "-" + d.contract.type;
if(multidistribs[key]==null){
var m = new MultiDistrib();
m.distributions.push(d);
m.type = d.contract.type;
multidistribs[key] = m;
}else{
multidistribs[key].distributions.push(d);
}
}
var multidistribs = Lambda.array(multidistribs);
//trigger event
for(md in multidistribs) App.current.event(MultiDistribEvent(md));
//sort by date desc
multidistribs.sort(function(x,y){
return Math.round( x.getDate().getTime()/1000 ) - Math.round(y.getDate().getTime()/1000 );
});
return multidistribs;
}
/**
* TODO : refacto this to use getFromTimeRange();
*/
/*public static function getNextMultiDeliveries(group:db.Amap){
var out = new Map < String, {
place:db.Place, //common delivery place
startDate:Date, //global delivery start
endDate:Date, //global delivery stop
orderStartDate:Date, //global orders opening date
orderEndDate:Date, //global orders closing date
active:Bool,
products:Array<ProductInfo>, //available products ( if no order )
myOrders:Array<{distrib:db.Distribution,orders:Array<UserOrder>}> //my orders
}>();
var n = Date.now();
var now = new Date(n.getFullYear(), n.getMonth(), n.getDate(), 0, 0, 0);
var contracts = db.Contract.getActiveContracts(group);
var cids = Lambda.map(contracts, function(p) return p.id);
//var pids = Lambda.map(db.Product.manager.search($contractId in cids,false), function(x) return x.id);
//var out = UserContract.manager.search(($userId == id || $userId2 == id) && $productId in pids, lock);
//available deliveries
var inSixMonth = DateTools.delta(now, 1000.0 * 60 * 60 * 24 * 30 * 6);
var distribs = db.Distribution.manager.search(($contractId in cids) && $date >= now && $date <= inSixMonth , { orderBy:date }, false);
for (d in distribs) {
//we had the distribution key ( place+date ) and the contract type in order to separate constant and varying contracts
var key = d.getKey() + "|" + d.contract.type;
var o = out.get(key);
if (o == null) o = {place:d.place, startDate:d.date, active:null, endDate:d.end, products:[], myOrders:[], orderStartDate:null,orderEndDate:null};
//user orders
var orders = [];
if(App.current.user!=null) orders = d.contract.getUserOrders(App.current.user,d);
if (orders.length > 0){
o.myOrders.push({distrib:d,orders:service.OrderService.prepare(orders)});
}else{
//no "order block" if no shop mode
if (!group.hasShopMode() ) {
continue;
}
//if its a constant order contract, skip this delivery
if (d.contract.type == db.Contract.TYPE_CONSTORDERS){
continue;
}
//products preview if no orders
for ( p in d.contract.getProductsPreview(9)){
o.products.push( p.infos(null,false) );
}
}
if (d.contract.type == db.Contract.TYPE_VARORDER){
//old distribs may have an empty orderStartDate
if (d.orderStartDate == null) {
continue;
}
//if order opening is more far than 1 month, skip it
// if (d.orderStartDate.getTime() > inOneMonth.getTime() ){
// continue;
// }
//display closest opening date
if (o.orderStartDate == null){
o.orderStartDate = d.orderStartDate;
}else if (o.orderStartDate.getTime() > d.orderStartDate.getTime()){
o.orderStartDate = d.orderStartDate;
}
//display most far closing date
if (o.orderEndDate == null){
o.orderEndDate = d.orderEndDate;
}else if (o.orderEndDate.getTime() < d.orderEndDate.getTime()){
o.orderEndDate = d.orderEndDate;
}
out.set(key, o);
}else{
//in constant orders, add block only if there is an order
if(o.myOrders.length>0) out.set(key, o);
}
}
//shuffle and limit product lists
for ( o in out){
o.products = thx.Arrays.shuffle(o.products);
o.products = o.products.slice(0, 9);
}
//decide if active or not
var now = Date.now();
for( o in out){
if (o.orderStartDate == null) continue; //constant orders
if (now.getTime() >= o.orderStartDate.getTime() && now.getTime() <= o.orderEndDate.getTime() ){
//order currently open
o.active = true;
}else {
o.active = false;
}
}
return Lambda.array(out);
}*/
public function getPlace(){
if(distributions.length==0) throw "This multidistrib is empty";
return distributions[0].place;
}
public function getDate(){
if(distributions.length==0) throw "This multidistrib is empty";
return distributions[0].date;
}
public function getEndDate(){
if(distributions.length==0) throw "This multidistrib is empty";
return distributions[0].end;
}
public function getProductsExcerpt():Array<ProductInfo>{
var key = "productsExcerpt-"+getKey();
var cache:Array<Int> = sugoi.db.Cache.get(key);
if(cache!=null){
var out = [];
//try{
for( pid in cache.array()){
var p = db.Product.manager.get(pid,false);
if(p!=null) out.push(p.infos());
}
//}catch(e:Dynamic){
// sugoi.db.Cache.destroy(key);
// }
return out;
}
var products = [];
for( d in distributions){
for ( p in d.contract.getProductsPreview(9)){
products.push( p.infos(null,false) );
}
}
products = thx.Arrays.shuffle(products);
products = products.slice(0, 9);
sugoi.db.Cache.set(key, products.map(function(p)return p.id).array(), 3600 );
return products;
}
public function userHasOrders(user:db.User):Bool{
if(user==null) return false;
for ( d in distributions){
if(d.getUserOrders(user).length>0) return true;
}
return false;
}
/**
orders currently open ?
**/
public function isActive(){
if (getOrdersStartDate() == null) return false; //constant orders
var now = Date.now();
if (now.getTime() >= getOrdersStartDate().getTime() && now.getTime() <= getOrdersEndDate().getTime() ){
return true;
}else {
return false;
}
}
public function getOrdersStartDate(){
var date = null;
for( d in distributions ){
if(d.orderStartDate==null) continue;
//display closest opening date
if (date == null){
date = d.orderStartDate;
}else if (date.getTime() > d.orderStartDate.getTime()){
date = d.orderStartDate;
}
}
return date;
}
/*public function hasOnlyConstantOrders(){
for(d in distributions){
if( d.contract.type==db.Contract.TYPE_VARORDER ) {
return false;
}
}
return true;
}*/
public function getOrdersEndDate(){
var date = null;
for( d in distributions ){
if(d.orderEndDate==null) continue;
//display most far closing date
if (date == null){
date = d.orderEndDate;
}else if (date.getTime() < d.orderEndDate.getTime()){
date = d.orderEndDate;
}
}
return date;
}
/**
* Get all orders involved in this multidistrib
*/
public function getOrders(){
var out = [];
for ( d in distributions){
out = out.concat(d.getOrders().array());
}
return out;
}
/**
* Get orders for a user in this multidistrib
* @param user
*/
public function getUserOrders(user:db.User){
var out = [];
for ( d in distributions){
var pids = Lambda.map( d.contract.getProducts(false), function(x) return x.id);
var userOrders = db.UserContract.manager.search( $userId == user.id && $distributionId==d.id && $productId in pids , false);
for( o in userOrders ){
out.push(o);
}
}
return out;
}
public function getUsers(){
var users = [];
for ( o in getOrders()) users.push(o.user);
return users.deduplicate();
}
public function isConfirmed():Bool{
//cannot be in future
if(getDate().getTime()>Date.now().getTime()) return false;
return Lambda.count( distributions, function(d) return d.validated) == distributions.length;
}
public function checkConfirmed():Bool{
var orders = getOrders();
var c = Lambda.count( orders, function(d) return d.paid) == orders.length;
if (c){
for ( d in distributions){
if (!d.validated){
d.lock();
d.validated = true;
d.update();
}
}
}
return c;
}
//get key by date-place-type
public function getKey(){
return distributions[0].getKey() + "-" + distributions[0].contract.type;
}
}