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.
264 lines
7.3 KiB
264 lines
7.3 KiB
package controller;
|
|
import Common;
|
|
import tools.ArrayTool;
|
|
import service.OrderService;
|
|
|
|
class Shop extends Controller
|
|
{
|
|
|
|
var distribs : List<db.Distribution>;
|
|
var contracts : List<db.Contract>;
|
|
|
|
@tpl('shop/default.mtt')
|
|
public function doDefault(place:db.Place,date:Date) {
|
|
var products = getProducts(place,date);
|
|
view.products = products;
|
|
view.place = place;
|
|
view.date = date;
|
|
view.group = place.amap;
|
|
view.infos = ArrayTool.groupByDate(Lambda.array(distribs), "orderEndDate");
|
|
|
|
//message if phone is required
|
|
if(app.user!=null && app.user.amap.flags.has(db.Amap.AmapFlags.PhoneRequired) && app.user.phone==null){
|
|
app.session.addMessage(t._("Members of this group should provide a phone number. <a href='/account/edit'>Please click here to update your account</a>."),true);
|
|
}
|
|
|
|
//event for additionnal blocks on home page
|
|
var e = Blocks([], "shop");
|
|
app.event(e);
|
|
view.blocks = e.getParameters()[0];
|
|
}
|
|
|
|
/**
|
|
* prints the full product list and current cart in JSON
|
|
*/
|
|
public function doInit(place:db.Place,date:Date) {
|
|
|
|
//init order serverside if needed
|
|
var order :OrderInSession = app.session.data.order;
|
|
if ( order == null) {
|
|
app.session.data.order = order = cast {products:[]};
|
|
}
|
|
|
|
var products = [];
|
|
var categs = new Array<{name:String,pinned:Bool,categs:Array<CategoryInfo>}>();
|
|
|
|
if (place.amap.flags.has(db.Amap.AmapFlags.ShopCategoriesFromTaxonomy)){
|
|
|
|
//TAXO CATEGORIES
|
|
products = getProducts(place, date, true);
|
|
}else{
|
|
|
|
//CUSTOM CATEGORIES
|
|
products = getProducts(place, date, false);
|
|
}
|
|
|
|
categs = place.amap.getCategoryGroups();
|
|
|
|
//clean
|
|
for ( p in order.products){
|
|
p.product = null;
|
|
}
|
|
Sys.print( haxe.Serializer.run( {products:products,categories:categs,order:order} ) );
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Get the available products list
|
|
*/
|
|
private function getProducts(place,date,?categsFromTaxo=false):Array<ProductInfo> {
|
|
|
|
contracts = db.Contract.getActiveContracts(app.getCurrentGroup());
|
|
|
|
for (c in Lambda.array(contracts)) {
|
|
//only varying orders
|
|
if (c.type != db.Contract.TYPE_VARORDER) {
|
|
contracts.remove(c);
|
|
}
|
|
|
|
if (!c.isVisibleInShop()) {
|
|
contracts.remove(c);
|
|
}
|
|
|
|
}
|
|
|
|
view.contracts = contracts;
|
|
|
|
var now = Date.now();
|
|
var cids = Lambda.map(contracts, function(c) return c.id);
|
|
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);
|
|
|
|
//distribs open to orders, and where distribDate is in the date given as parameter
|
|
distribs = db.Distribution.manager.search(($contractId in cids) && $orderStartDate <= now && $orderEndDate >= now && $date > d1 && $end < d2 && $place == place, false);
|
|
var products = [];
|
|
for ( d in distribs){
|
|
for (p in d.contract.getProducts(true)){
|
|
products.push( p.infos(categsFromTaxo,null,d) );
|
|
}
|
|
}
|
|
return products;
|
|
|
|
/*var cids = Lambda.map(distribs, function(d) return d.contract.id);
|
|
var products = db.Product.manager.search(($contractId in cids) && $active==true, { orderBy:name }, false);
|
|
|
|
return Lambda.array(Lambda.map(products, function(p) return p.infos(categsFromTaxo)));*/
|
|
}
|
|
|
|
/**
|
|
* Overlay window loaded by Ajax for product Infos
|
|
*/
|
|
@tpl('shop/productInfo.mtt')
|
|
public function doProductInfo(p:db.Product,?args:{distribution:db.Distribution}) {
|
|
var d = args!=null && args.distribution!=null ? args.distribution : null;
|
|
view.p = p.infos(null,null,d);
|
|
view.product = p;
|
|
view.vendor = p.contract.vendor;
|
|
}
|
|
|
|
/**
|
|
* receive cart
|
|
*/
|
|
public function doSubmit() {
|
|
|
|
var order : OrderInSession = haxe.Json.parse(app.params.get("data"));
|
|
app.session.data.order = order;
|
|
|
|
}
|
|
|
|
/**
|
|
* add a product to the cart
|
|
*/
|
|
public function doAdd(productId:Int, quantity:Int) {
|
|
|
|
var order : OrderInSession = app.session.data.order;
|
|
if ( order == null) order = cast { products:[] };
|
|
order.products.push( { productId:productId, quantity:quantity } );
|
|
Sys.print( haxe.Json.stringify( {success:true} ) );
|
|
|
|
}
|
|
|
|
/**
|
|
* remove a product from cart
|
|
*/
|
|
public function doRemove(pid:Int) {
|
|
|
|
var order:OrderInSession = app.session.data.order;
|
|
if ( order == null) return;
|
|
|
|
for ( p in order.products.copy()) {
|
|
if (p.productId == pid) {
|
|
order.products.remove(p);
|
|
}
|
|
}
|
|
|
|
Sys.print( haxe.Json.stringify( { success:true } ) );
|
|
}
|
|
|
|
|
|
/**
|
|
* validate the order
|
|
*/
|
|
@tpl('shop/needLogin.mtt')
|
|
public function doValidate(place:db.Place, date:Date){
|
|
|
|
//login is needed : display a loginbox
|
|
if (app.user == null) {
|
|
view.redirect = "/shop/validate/" + place.id + "/" + date.toString().substr(0, 10);
|
|
view.group = place.amap;
|
|
view.register = true;
|
|
view.message = t._("In order to confirm your order, You need to authenticate.");
|
|
return;
|
|
}
|
|
|
|
//add the user to this group if needed
|
|
if (place.amap.regOption == db.Amap.RegOption.Open && db.UserAmap.get(app.user, place.amap) == null){
|
|
app.user.makeMemberOf(place.amap);
|
|
}
|
|
|
|
var order : OrderInSession = app.session.data.order;
|
|
if (order == null || order.products == null || order.products.length == 0) {
|
|
throw Error("/", t._("Your order is empty") );
|
|
}
|
|
|
|
if (place == null) throw "place cannot be empty";
|
|
if (date == null) throw "date cannot be empty";
|
|
|
|
var products = getProducts(place, date);
|
|
|
|
var errors = [];
|
|
order.total = 0.0;
|
|
|
|
//cleaning
|
|
for (o in order.products.copy()) {
|
|
|
|
var p = db.Product.manager.get(o.productId, false);
|
|
|
|
//check that the products are from this group (we never know...)
|
|
if (p.contract.amap.id != app.user.amap.id){
|
|
app.session.data.order = null;
|
|
throw Error("/", t._("This cart is invalid") );
|
|
}
|
|
|
|
//check if the product is available
|
|
if (Lambda.find(products, function(x) return x.id == o.productId) == null) {
|
|
errors.push( t._("This distribution does not supply the product <b>::pname::</b>",{pname:p.name}) );
|
|
order.products.remove(o);
|
|
continue;
|
|
}else{
|
|
o.product = p;
|
|
}
|
|
|
|
//find distrib
|
|
var d = Lambda.find(distribs, function(d) return d.contract.id == p.contract.id);
|
|
if ( d == null ){
|
|
errors.push( t._("This distribution does not supply the product <b>::pname::</b>",{pname:p.name}) );
|
|
order.products.remove(o);
|
|
continue;
|
|
}else{
|
|
o.distributionId = d.id;
|
|
}
|
|
|
|
//moderate order according available stocks
|
|
if (p.stock != null && p.contract.hasStockManagement() ) {
|
|
if (p.stock - o.quantity < 0) {
|
|
var canceled = o.quantity - p.stock;
|
|
o.quantity -= canceled;
|
|
errors.push(t._("Order of ::pname:: reduced to ::oquantity:: to match remaining stock", {pname:p.name, oquantity:o.quantity}));
|
|
}
|
|
}
|
|
|
|
order.total += p.getPrice() * o.quantity;
|
|
}
|
|
|
|
order.userId = app.user.id;
|
|
|
|
if (errors.length > 0) {
|
|
app.session.addMessage(errors.join("<br/>"), true);
|
|
}
|
|
|
|
//store cart in session
|
|
app.session.data.order = order;
|
|
|
|
//debug
|
|
for ( p in order.products){
|
|
if (p.distributionId == null){
|
|
App.current.logError(place.amap.name + " : panier sans distrib Id : " + Std.string(order) );
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (app.user.amap.hasPayments()){
|
|
//Go to payments page
|
|
throw Redirect("/transaction/pay/");
|
|
}else{
|
|
//no payments, confirm direclty
|
|
OrderService.confirmSessionOrder(order);
|
|
throw Ok("/contract", t._("Your order has been confirmed") );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|