@ -1,4 +1,5 @@
package service ;
import Common ;
import tink . core . Error ;
@ -6,10 +7,8 @@ import tink.core.Error;
* Order Service
* @ author web - wizard , fbarbut
* /
class OrderService
{
static function canHaveFloatQt ( product : db . Product ) : Bool {
class OrderService {
static function canHaveFloatQt ( product : db . Product ) : Bool {
return product . hasFloatQt || product . wholesale || product . variablePrice ;
}
@ -20,42 +19,45 @@ class OrderService
* @ param productId
* /
public static function make ( user : db . User , quantity : Float , product : db . Product , ? distribId : Int , ? paid : Bool , ? user2 : db . User , ? invert : Bool ) : db . UserContract {
var t = sugoi . i18n . Locale . texts ;
if ( product . contract . type == db . Contract . TYPE_VARORDER && distribId == null ) throw " Y o u h a v e t o p r o v i d e a d i s t r i b I d " ;
if ( quantity == null ) throw " Q u a n t i t y i s n u l l " ;
if ( product . contract . type == db . Contract . TYPE_VARORDER && distribId == null )
throw " Y o u h a v e t o p r o v i d e a d i s t r i b I d " ;
if ( quantity == null )
throw " Q u a n t i t y i s n u l l " ;
//quantity
if ( ! canHaveFloatQt ( product ) ) {
if ( ! tools . FloatTool . isInt ( quantity ) ) {
throw new tink . core . Error ( t . _ ( " E r r o r : p r o d u c t \" : : p r o d u c t : : \" q u a n t i t y s h o u l d b e i n t e g e r " , { product : product . name } ) ) ;
// quantity
if ( ! canHaveFloatQt ( product ) ) {
if ( ! tools . FloatTool . isInt ( quantity ) ) {
throw new tink . core . Error ( t . _ ( " E r r o r : p r o d u c t \" : : p r o d u c t : : \" q u a n t i t y s h o u l d b e i n t e g e r " , { product : product . name } ) ) ;
}
}
//multiweight : make one row per product
if ( product . multiWeight && quantity > 1.0 ) {
if ( product . multiWeight && quantity != Math . abs ( quantity ) ) throw t . _ ( " m u l t i - w e i g h i n g p r o d u c t s s h o u l d b e o r d e r e d o n l y w i t h i n t e g e r q u a n t i t i e s " ) ;
// multiweight : make one row per product
if ( product . multiWeight && quantity > 1.0 ) {
if ( product . multiWeight && quantity != Math . abs ( quantity ) )
throw t . _ ( " m u l t i - w e i g h i n g p r o d u c t s s h o u l d b e o r d e r e d o n l y w i t h i n t e g e r q u a n t i t i e s " ) ;
var o = null ;
for ( i in 0 ... Math . round ( quantity ) ) {
for ( i in 0 ... Math . round ( quantity ) ) {
o = make ( user , 1 , product , distribId , paid , user2 , invert ) ;
}
}
return o ;
}
//checks
if ( quantity <= 0 ) return null ;
//check for previous orders on the same distrib
// checks
if ( quantity <= 0 )
return null ;
// check for previous orders on the same distrib
var prevOrders = new List < db . UserContract > ( ) ;
if ( distribId == null ) {
prevOrders = db . UserContract . manager . search ( $product == product && $user == user , true ) ;
} e lse {
prevOrders = db . UserContract . manager . search ( $product == product && $user == user && $distributionId == distribId , true ) ;
prevOrders = db . UserContract . manager . search ( $product == product && $user == user , true ) ;
} e lse {
prevOrders = db . UserContract . manager . search ( $product == product && $user == user && $distributionId == distribId , true ) ;
}
//Create order object
// Create order object
var o = new db . UserContract ( ) ;
o . product = product ;
o . quantity = quantity ;
@ -66,214 +68,214 @@ class OrderService
o . user = user ;
if ( user2 != null ) {
o . user2 = user2 ;
if ( invert != null ) o . flags . set ( InvertSharedOrder ) ;
if ( invert != null )
o . flags . set ( InvertSharedOrder ) ;
}
if ( paid != null ) o . paid = paid ;
if ( distribId != null ) o . distribution = db . Distribution . manager . get ( distribId ) ;
//cumulate quantities if there is a similar previous order
if ( paid != null )
o . paid = paid ;
if ( distribId != null )
o . distribution = db . Distribution . manager . get ( distribId ) ;
// cumulate quantities if there is a similar previous order
if ( prevOrders . length > 0 && ! product . multiWeight ) {
for ( prevOrder in prevOrders ) {
//if (!prevOrder.paid) {
o . quantity += prevOrder . quantity ;
prevOrder . delete ( ) ;
//}
// if (!prevOrder.paid) {
o . quantity += prevOrder . quantity ;
prevOrder . delete ( ) ;
// }
}
}
//create a basket object
if ( distribId != null ) {
// create a basket object
if ( distribId != null ) {
var dist = o . distribution ;
var basket = db . Basket . getOrCreate ( user , dist . place , dist . date ) ;
o . basket = basket ;
var basket = db . Basket . getOrCreate ( user , dist . place , dist . date ) ;
o . basket = basket ;
}
o . insert ( ) ;
//Stocks
// Stocks
if ( o . product . stock != null ) {
var c = o . product . contract ;
if ( c . hasStockManagement ( ) ) {
//trace("stock for "+quantity+" x "+product.name);
// trace("stock for "+quantity+" x "+product.name);
if ( o . product . stock == 0 ) {
if ( App . current . session != null ) {
App . current . session . addMessage ( t . _ ( " T h e r e i s n o m o r e ' : : p r o d u c t N a m e : : ' i n s t o c k , w e r e m o v e d i t f r o m y o u r o r d e r " , { productName : o . product . name } ) , true ) ;
App . current . session . addMessage ( t . _ ( " T h e r e i s n o m o r e ' : : p r o d u c t N a m e : : ' i n s t o c k , w e r e m o v e d i t f r o m y o u r o r d e r " ,
{ productName : o . product . name } ) , true ) ;
}
o . quantity -= quantity ;
if ( o . quantity <= 0 ) {
if ( o . quantity <= 0 ) {
o . delete ( ) ;
return null ;
return null ;
}
} e lse if ( o . product . stock - quantity < 0 ) {
} e lse if ( o . product . stock - quantity < 0 ) {
var canceled = quantity - o . product . stock ;
o . quantity -= canceled ;
o . update ( ) ;
if ( App . current . session != null ) {
var msg = t . _ ( " W e r e d u c e d y o u r o r d e r o f ' : : p r o d u c t N a m e : : ' t o q u a n t i t y : : o Q u a n t i t y : : b e c a u s e t h e r e i s n o a v a i l a b l e p r o d u c t s a n y m o r e " , { productName : o . product . name , oQuantity : o . quantity } ) ;
var msg = t . _ ( " W e r e d u c e d y o u r o r d e r o f ' : : p r o d u c t N a m e : : ' t o q u a n t i t y : : o Q u a n t i t y : : b e c a u s e t h e r e i s n o a v a i l a b l e p r o d u c t s a n y m o r e " ,
{ productName : o . product . name , oQuantity : o . quantity } ) ;
App . current . session . addMessage ( msg , true ) ;
}
o . product . lock ( ) ;
o . product . stock = 0 ;
o . product . update ( ) ;
App . current . event ( StockMove ( { product : o . product , move : 0 - ( quantity - canceled ) } ) ) ;
} e lse {
App . current . event ( StockMove ( { product : o . product , move : 0 - ( quantity - canceled ) } ) ) ;
} e lse {
o . product . lock ( ) ;
o . product . stock -= quantity ;
o . product . update ( ) ;
App . current . event ( StockMove ( { product : o . product , move : 0 - quantity } ) ) ;
o . product . update ( ) ;
App . current . event ( StockMove ( { product : o . product , move : 0 - quantity } ) ) ;
}
}
}
}
return o ;
}
/ * *
* Edit an existing order ( quantity )
* /
public static function edit ( order : db . UserContract , newquantity : Float , ? paid : Bool , ? user2 : db . User , ? invert : Bool ) {
public static function edit ( order : db . UserContract , newquantity : Float , ? paid : Bool , ? user2 : db . User , ? invert : Bool ) {
var t = sugoi . i18n . Locale . texts ;
order . lock ( ) ;
//quantity
if ( newquantity == null ) newquantity = 0 ;
if ( ! canHaveFloatQt ( order . product ) ) {
if ( ! tools . FloatTool . isInt ( newquantity ) ) {
throw new tink . core . Error ( t . _ ( " E r r o r : p r o d u c t \" : : p r o d u c t : : \" q u a n t i t y s h o u l d b e i n t e g e r " , { product : order . product . name } ) ) ;
// quantity
if ( newquantity == null )
newquantity = 0 ;
if ( ! canHaveFloatQt ( order . product ) ) {
if ( ! tools . FloatTool . isInt ( newquantity ) ) {
throw new tink . core . Error ( t . _ ( " E r r o r : p r o d u c t \" : : p r o d u c t : : \" q u a n t i t y s h o u l d b e i n t e g e r " , { product : order . product . name } ) ) ;
}
}
//paid
// paid
if ( paid != null ) {
order . paid = paid ;
} e lse {
if ( order . quantity < newquantity ) order . paid = false ;
} e lse {
if ( order . quantity < newquantity )
order . paid = false ;
}
//shared order
if ( user2 != null ) {
order . user2 = user2 ;
if ( invert == true ) order . flags . set ( InvertSharedOrder ) ;
if ( invert == false ) order . flags . unset ( InvertSharedOrder ) ;
} e lse {
// shared order
if ( user2 != null ) {
order . user2 = user2 ;
if ( invert == true )
order . flags . set ( InvertSharedOrder ) ;
if ( invert == false )
order . flags . unset ( InvertSharedOrder ) ;
} e lse {
order . user2 = null ;
order . flags . unset ( InvertSharedOrder ) ;
}
//stocks
var e : Event = null ;
// stocks
var e: Event = null ;
if ( order . product . stock != null ) {
var c = order . product . contract ;
if ( c . hasStockManagement ( ) ) {
if ( newquantity < order . quantity ) {
//on commande moins que prévu : incrément de stock
// on commande moins que prévu : incrément de stock
order . product . lock ( ) ;
order . product . stock += ( order . quantity - newquantity ) ;
e = StockMove ( { product : order . product , move : 0 - ( order . quantity - newquantity ) } ) ;
} e lse {
//on commande plus que prévu : décrément de stock
order . product . stock += ( order . quantity - newquantity ) ;
e = StockMove ( { product : order . product , move : 0 - ( order . quantity - newquantity ) } ) ;
} e lse {
// on commande plus que prévu : décrément de stock
var addedquantity = newquantity - order . quantity ;
if ( order . product . stock - addedquantity < 0 ) {
//stock is not enough, reduce order
// stock is not enough, reduce order
newquantity = order . quantity + order . product . stock ;
if ( App . current . session != null ) App . current . session . addMessage ( t . _ ( " W e r e d u c e d y o u r o r d e r o f ' : : p r o d u c t N a m e : : ' t o q u a n t i t y : : o Q u a n t i t y : : b e c a u s e t h e r e i s n o a v a i l a b l e p r o d u c t s a n y m o r e " , { productName : order . product . name , oQuantity : newquantity } ) , true ) ;
e = StockMove ( { product : order . product , move : 0 - order . product . stock } ) ;
if ( App . current . session != null )
App . current . session . addMessage ( t . _ ( " W e r e d u c e d y o u r o r d e r o f ' : : p r o d u c t N a m e : : ' t o q u a n t i t y : : o Q u a n t i t y : : b e c a u s e t h e r e i s n o a v a i l a b l e p r o d u c t s a n y m o r e " ,
{
productName : order . product . name ,
oQuantity : newquantity
} ) , true ) ;
e = StockMove ( { product : order . product , move : 0 - order . product . stock } ) ;
order . product . lock ( ) ;
order . product . stock = 0 ;
} e lse {
//stock is big enough
} e lse {
// stock is big enough
order . product . lock ( ) ;
order . product . stock -= addedquantity ;
e = StockMove ( { product : order . product , move : 0 - addedquantity } ) ;
}
}
order . product . update ( ) ;
}
e = StockMove ( { product : order . product , move : 0 - addedquantity } ) ;
}
}
order . product . update ( ) ;
}
}
//update order
// update order
if ( newquantity == 0 ) {
order . quantity = 0 ;
order . quantity = 0 ;
order . paid = true ;
order . update ( ) ;
} e lse {
} e lse {
order . quantity = newquantity ;
order . update ( ) ;
}
order . update ( ) ;
}
App . current . event ( e ) ;
App . current . event ( e ) ;
return order ;
}
/ * *
* Delete an order
* /
public static function delete ( order : db . UserContract ) {
var t = sugoi . i18n . Locale . texts ;
if ( order == null ) throw new Error ( t . _ ( " T h i s o r d e r h a s a l r e a d y b e e n d e l e t e d . " ) ) ;
if ( order == null )
throw new Error ( t . _ ( " T h i s o r d e r h a s a l r e a d y b e e n d e l e t e d . " ) ) ;
order . lock ( ) ;
if ( order . quantity == 0 ) {
if ( order . quantity == 0 ) {
var contract = order . product . contract ;
var user = order . user ;
//Amap Contract
if ( contract . type == db . Contract . TYPE_CONSTORDERS ) {
// Amap Contract
if ( contract . type == db . Contract . TYPE_CONSTORDERS ) {
order . delete ( ) ;
if ( contract . amap . hasPayments ( ) ) {
if ( contract . amap . hasPayments ( ) ) {
var orders = contract . getUserOrders ( user ) ;
if ( orders . length == 0 ) {
if ( orders . length == 0 ) {
var operation = db . Operation . findCOrderTransactionFor ( contract , user ) ;
if ( operation != null ) operation . delete ( ) ;
if ( operation != null )
operation . delete ( ) ;
}
}
}
e lse { //Variable orders contract
//Get the basket for this user
} e lse { // Variable orders contract
// Get the basket for this user
var place = order . distribution . place ;
var basket = db . Basket . get ( user , place , order . distribution . date ) ;
if ( contract . amap . hasPayments ( ) ) {
if ( contract . amap . hasPayments ( ) ) {
var orders = basket . getOrders ( ) ;
//Check if it is the last order, if yes then delete the related operation
if ( orders . length == 1 && orders . first ( ) . id == order . id ) {
// Check if it is the last order, if yes then delete the related operation
if ( orders . length == 1 && orders . first ( ) . id == order . id ) {
var operation = db . Operation . findVOrderTransactionFor ( order . distribution . getKey ( ) , user , place . amap ) ;
if ( operation != null ) operation . delete ( ) ;
if ( operation != null )
operation . delete ( ) ;
}
}
order . delete ( ) ;
}
}
e lse {
} e lse {
throw new Error ( t . _ ( " D e l e t i o n n o t p o s s i b l e : q u a n t i t y i s n o t z e r o . " ) ) ;
}
}
/ * *
@ -285,21 +287,20 @@ class OrderService
var view = App . current . view ;
var t = sugoi . i18n . Locale . texts ;
for ( o in orders ) {
var x : UserOrder = cast { } ;
var x: UserOrder = cast { } ;
x . id = o . id ;
x . userId = o . user . id ;
x . userName = o . user . getCoupleName ( ) ;
x . userEmail = o . user . email ;
//shared order
if ( o . user2 != null ) {
// shared order
if ( o . user2 != null ) {
x . userId2 = o . user2 . id ;
x . userName2 = o . user2 . getCoupleName ( ) ;
x . userEmail2 = o . user2 . email ;
}
//deprecated
// deprecated
x . productId = o . product . id ;
x . productRef = o . product . ref ;
x . productQt = o . product . qt ;
@ -308,161 +309,160 @@ class OrderService
x . productImage = o . product . getImage ( ) ;
x . productHasFloatQt = o . product . hasFloatQt ;
x . productHasVariablePrice = o . product . variablePrice ;
//new way
// new way
x . product = o . product . infos ( ) ;
x . product . price = o . productPrice ; //do not use current price, but price of the order
x . product . price = o . productPrice ; // do not use current price, but price of the order
x . quantity = o . quantity ;
//smartQt
if ( x . quantity == 0.0 ) {
// smartQt
if ( x . quantity == 0.0 ) {
x . smartQt = t . _ ( " C a n c e l e d " ) ;
} e lse if ( x . productHasFloatQt || x . productHasVariablePrice || o . product . wholesale ) {
} e lse if ( x . productHasFloatQt || x . productHasVariablePrice || o . product . wholesale ) {
x . smartQt = view . smartQt ( x . quantity , x . productQt , x . productUnit ) ;
} e lse {
} e lse {
x . smartQt = Std . string ( x . quantity ) ;
}
//product name.
if ( x . productHasVariablePrice || x . productQt == null || x . productUnit == null ) {
x . productName = o . product . name ;
} e lse {
x . productName = o . product . name + " " + view . formatNum ( x . productQt ) + " " + view . unit ( x . productUnit , x . productQt > 1 ) ;
// product name.
if ( x . productHasVariablePrice || x . productQt == null || x . productUnit == null ) {
x . productName = o . product . name ;
} e lse {
x . productName = o . product . name + " " + view . formatNum ( x . productQt ) + " " + view . unit ( x . productUnit , x . productQt > 1 ) ;
}
x . subTotal = o . quantity * o . productPrice ;
var c = o . product . contract ;
if ( o . feesRate != 0 ) {
x . fees = x . subTotal * ( o . feesRate / 100 ) ;
if ( o . feesRate != 0 ) {
x . fees = x . subTotal * ( o . feesRate / 100 ) ;
x . percentageName = c . percentageName ;
x . percentageValue = o . feesRate ;
x . total = x . subTotal + x . fees ;
} e lse {
} e lse {
x . total = x . subTotal ;
}
//flags
// flags
x . paid = o . paid ;
x . invertSharedOrder = o . flags . has ( InvertSharedOrder ) ;
x . contractId = c . id ;
x . contractName = c . name ;
x . canModify = o . canModify ( ) ;
x . canModify = o . canModify ( ) ;
out . push ( x ) ;
}
return sort ( out ) ;
}
/ * *
* Confirms an order : create real orders from tmp orders in session
* @ param order
* /
public static function confirmSessionOrder ( tmpOrder : OrderInSession ) {
public static function confirmSessionOrder ( tmpOrder : OrderInSession ) {
var orders = [ ] ;
var user = db . User . manager . get ( tmpOrder . userId ) ;
for ( o in tmpOrder . products ) {
for ( o in tmpOrder . products ) {
o . product = db . Product . manager . get ( o . productId ) ;
orders . push ( make ( user , o . quantity , o . product , o . distributionId ) ) ;
orders . push ( make ( user , o . quantity , o . product , o . distributionId ) ) ;
}
App . current . event ( MakeOrder ( orders ) ) ;
App . current . session . data . order = null ;
App . current . session . data . order = null ;
return orders ;
}
/ * *
* Send an order - by - products report to the coordinator
* /
public static function sendOrdersByProductReport ( d : db . Distribution ) {
public static function sendOrdersByProductReport ( d : db . Distribution ) {
var t = sugoi . i18n . Locale . texts ;
var m = new sugoi . mail . Mail ( ) ;
m . addRecipient ( d . contract . contact . email , d . contract . contact . getName ( ) ) ;
m . setSender ( App . config . get ( " d e f a u l t _ e m a i l " ) , " C a g e t t e . n e t " ) ;
m . addRecipient ( d . contract . contact . email , d . contract . contact . getName ( ) ) ;
m . setSender ( App . config . get ( " d e f a u l t _ e m a i l " ) , t . _ ( " C a g e t t e . n e t " ) ) ;
m . setSubject ( ' [ ${ d . contract . amap . name } ] D i s t r i b u t i o n d u ${ App . current . view . dDate ( d . date ) } ( ${ d . contract . name } ) ' ) ;
var orders = service . ReportService . getOrdersByProduct ( d ) ;
var html = App . current . processTemplate ( " m a i l / o r d e r s B y P r o d u c t . m t t " , {
contract : d . contract ,
distribution : d ,
orders : orders ,
formatNum : App . current . view . formatNum ,
currency : App . current . view . currency ,
dDate : App . current . view . dDate ,
hHour : App . current . view . hHour ,
group : d . contract . amap
} ) ;
m . setHtmlBody ( html ) ;
App . sendMail ( m ) ;
var html = App . current . processTemplate ( " m a i l / o r d e r s B y P r o d u c t . m t t " , {
contract : d . contract ,
distribution : d ,
orders : orders ,
formatNum : App . current . view . formatNum ,
currency : App . current . view . currency ,
dDate : App . current . view . dDate ,
hHour : App . current . view . hHour ,
group : d . contract . amap
} ) ;
m . setHtmlBody ( html ) ;
App . sendMail ( m ) ;
}
/ * *
* Order summary for a m e m b e r
* WARNING : its for o n e d i s t r i b , n o t f o r a w h o l e b a s k e t !
* /
public static function sendOrderSummaryToMembers ( d : db . Distribution ) {
public static function sendOrderSummaryToMembers ( d : db . Distribution ) {
var t = sugoi . i18n . Locale . texts ;
var title = ' [ ${ d . contract . amap . name } ] V o t r e c o m m a n d e p o u r l e ${ App . current . view . dDate ( d . date ) } ( ${ d . contract . name } ) ' ;
for ( user in d . getUsers ( ) ) {
for ( user in d . getUsers ( ) ) {
var m = new sugoi . mail . Mail ( ) ;
m . addRecipient ( user . email , user . getName ( ) , user . id ) ;
if ( user . email2 != null ) m . addRecipient ( user . email2 , user . getName ( ) , user . id ) ;
m . setSender ( App . config . get ( " d e f a u l t _ e m a i l " ) , " C a g e t t e . n e t " ) ;
m . addRecipient ( user . email , user . getName ( ) , user . id ) ;
if ( user . email2 != null )
m . addRecipient ( user . email2 , user . getName ( ) , user . id ) ;
m . setSender ( App . config . get ( " d e f a u l t _ e m a i l " ) , t . _ ( " C a g e t t e . n e t " ) ) ;
m . setSubject ( title ) ;
var orders = prepare ( d . contract . getUserOrders ( user , d ) ) ;
var html = App . current . processTemplate ( " m a i l / o r d e r S u m m a r y F o r M e m b e r . m t t " , {
contract : d . contract ,
distribution : d ,
orders : orders ,
formatNum : App . current . view . formatNum ,
currency : App . current . view . currency ,
dDate : App . current . view . dDate ,
hHour : App . current . view . hHour ,
group : d . contract . amap
} ) ;
var orders = prepare ( d . contract . getUserOrders ( user , d ) ) ;
var html = App . current . processTemplate ( " m a i l / o r d e r S u m m a r y F o r M e m b e r . m t t " , {
contract : d . contract ,
distribution : d ,
orders : orders ,
formatNum : App . current . view . formatNum ,
currency : App . current . view . currency ,
dDate : App . current . view . dDate ,
hHour : App . current . view . hHour ,
group : d . contract . amap
} ) ;
m . setHtmlBody ( html ) ;
App . sendMail ( m ) ;
}
}
public static function sort ( orders : Array < UserOrder > ) {
//order by lastname (+lastname2 if exists), then contract
public static function sort ( orders : Array < UserOrder > ) {
// order by lastname (+lastname2 if exists), then contract
orders . sort ( function ( a , b ) {
if ( a . userName + a . userId + a . userName2 + a . userId2 + a . contractId > b . userName + b . userId + b . userName2 + b . userId2 + b . contractId ) {
if ( a . userName
+ a . userId
+ a . userName2
+ a . userId2
+ a . contractId > b . userName
+ b . userId
+ b . userName2
+ b . userId2
+ b . contractId ) {
return 1 ;
}
if ( a . userName + a . userId + a . userName2 + a . userId2 + a . contractId < b . userName + b . userId + b . userName2 + b . userId2 + b . contractId ) {
if ( a . userName
+ a . userId
+ a . userName2
+ a . userId2
+ a . contractId < b . userName
+ b . userId
+ b . userName2
+ b . userId2
+ b . contractId ) {
return - 1 ;
}
return 0 ;
} ) ;
return orders ;
}
}
}