diff --git a/addons/lunch/__openerp__.py b/addons/lunch/__openerp__.py index b00901492c8..b53e27baf76 100644 --- a/addons/lunch/__openerp__.py +++ b/addons/lunch/__openerp__.py @@ -32,7 +32,7 @@ The base module to manage lunch. keep track for the Lunch Order, Cash Moves and Product. Apply Different Category for the product. """, - 'data': ['security/groups.xml','lunch_view.xml','wizard/lunch_validation_view.xml','wizard/lunch_cancel_view.xml','lunch_report.xml', + 'data': ['security/groups.xml','lunch_view.xml','wizard/lunch_order_view.xml','wizard/lunch_validation_view.xml','wizard/lunch_cancel_view.xml','lunch_report.xml', 'report/report_lunch_order_view.xml', 'security/ir.model.access.csv',], 'css':['static/src/css/lunch.css'], diff --git a/addons/lunch/lunch.py b/addons/lunch/lunch.py index 677cea7f6bf..2087b89c948 100644 --- a/addons/lunch/lunch.py +++ b/addons/lunch/lunch.py @@ -20,12 +20,13 @@ # ############################################################################## +from xml.sax.saxutils import escape import pytz import time from osv import osv, fields from datetime import datetime, timedelta from lxml import etree - +from tools.translate import _ class lunch_order(osv.Model): """ lunch order """ @@ -38,19 +39,16 @@ class lunch_order(osv.Model): for order in self.browse(cr, uid, ids, context=context): value = 0.0 for orderline in order.order_line_ids: - if orderline.state != 'cancelled': - value += orderline.product_id.price - result[order.id]=value + value += orderline.product_id.price + result[order.id]=value return result def _compute_total(self, cr, uid, ids, name, context=None): """ compute total""" result= {} - value = 0.0 for order_line in self.browse(cr, uid, ids, context=context): - value+=order_line.price - result[order_line.order_id.id]=value - return result + result[order_line.order_id.id] = True + return result.keys() def add_preference(self, cr, uid, ids, pref_id, context=None): """ create a new order line based on the preference selected (pref_id)""" @@ -159,12 +157,19 @@ class lunch_order(osv.Model): order_line_ids= self.resolve_o2m_commands_to_record_dicts(cr, uid, "order_line_ids", order_line_ids, ["price"], context) if order_line_ids: tot = 0.0 + product_ref = self.pool.get("lunch.product") for prod in order_line_ids: - tot += prod['price'] + if 'product_id' in prod: + tot += product_ref.browse(cr,uid,prod['product_id'],context=context).price + else: + tot += prod['price'] res = {'value':{'total':tot}} return res + + def create(self, cr, uid, values, context=None): + print "CREATE" pref_ref = self.pool.get('lunch.preference') pref_ids = pref_ref.search(cr,uid,[],context=context) prod_ref = self.pool.get('lunch.product') @@ -176,15 +181,19 @@ class lunch_order(osv.Model): for pref in pref_ref.browse(cr,uid,pref_ids,context=context): if pref['product'].id == prods[2]['product_id']: if pref['note'] == prods[2]['note']: - if pref['price'] == prods[2]['price']: - already_exists = True + if 'price' in prods[2]: + if pref['price'] == prods[2]['price']: + already_exists = True + else: + if pref['price'] == prod_ref.browse(cr,uid,prods[2]['product_id'])['price']: + already_exists = True if already_exists == False: - new_pref = pref_ref.create(cr,uid,{'date':values['date'], 'color':0, 'order_id':new_id, 'user_id':values['user_id'], 'product': prods[2]['product_id'], 'product_name':prod_ref.browse(cr,uid,prods[2]['product_id'])['name'], 'note':prods[2]['note'], 'price':prods[2]['price']},context=context) + new_pref = pref_ref.create(cr,uid,{'date':values['date'], 'color':0, 'order_id':new_id, 'user_id':values['user_id'], 'product': prods[2]['product_id'], 'product_name':prod_ref.browse(cr,uid,prods[2]['product_id'])['name'], 'note':prods[2]['note'], 'price':prod_ref.browse(cr,uid,prods[2]['product_id'])['price']},context=context) return new_id def _default_preference_get(self,cr,uid,args,context=None): """ return a maximum of 15 last user preferences ordered by date""" - return self.pool.get('lunch.preference').search(cr,uid,[('user_id','=',uid)],order='date desc',limit=15,context=context) + return self.pool.get('lunch.preference').search(cr,uid,[('user_id','=',uid)],order='date desc',limit=25,context=context) def __getattr__(self, attr): """ this method catch unexisting method call and if starts with @@ -198,7 +207,7 @@ class lunch_order(osv.Model): return super(lunch_order,self).__getattr__(self,attr) def fields_view_get(self, cr, uid, view_id=None, view_type=False, context=None, toolbar=False, submenu=False): - #TODO: not reviewed + """ Add preferences in the form view of order.line """ res = super(lunch_order,self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu) if view_type == 'form': pref_ref = self.pool.get("lunch.preference") @@ -208,22 +217,37 @@ class lunch_order(osv.Model): pref_ids = pref_ref.search(cr,uid,[('user_id','=',uid)],context=context) order_ids = order_ref.search(cr,uid,[('user_id','=',uid)],context=context) - if len(order_ids)>0: + text_xml = "
" + if len(order_ids)==0: + text_xml+=""" +
+
%s
+
+ %s +
+ %s +
+ %s +
+ """ % (_("This is the first time you order a meal"), + _("Select a product and put your order comments on the note."), + _("Your favorite meals will be created based on your last orders."), + _("Don't forget the alerts displayed in the reddish area")) + else: preferences = pref_ref.browse(cr,uid,pref_ids,context=context) this_order = order_ref.browse(cr,uid,order_ids[0],context=context) currency = currency_obj.browse(cr, uid, this_order['currency_id'], context=context) categories = {} #store the different categories of products in preference - for pref in preferences: categories[pref['product']['category_id']['name']]=[] for pref in preferences: categories[pref['product']['category_id']['name']].append(pref) length = len(categories) - text_xml = """
""" + text_xml += """""" for key,value in categories.items(): text_xml+=""" -
-

%s

+
+

%s

""" % (key,) i = 0 for val in value: @@ -233,7 +257,7 @@ class lunch_order(osv.Model): text_xml+= '''
- +
@@ -245,15 +269,15 @@ class lunch_order(osv.Model): %s
- ''' % (function_name, function_name, val['product_name'], val['price'] or 0.0, currency['name'], val['note'] or '') - text_xml+= ('''
''') - text_xml+= ('''
''') - # ADD into ARCH xml - doc = etree.XML(res['arch']) - node = doc.xpath("//div[@name='preferences']") - to_add = etree.fromstring(text_xml) - node[0].append(to_add) - res['arch'] = etree.tostring(doc) + ''' % (function_name, function_name,_("Add"), escape(val['product_name']), val['price'] or 0.0, currency['name'], escape(val['note']) or '') + text_xml+= '''
''' + # ADD into ARCH xml + text_xml += "
" + doc = etree.XML(res['arch']) + node = doc.xpath("//div[@name='preferences']") + to_add = etree.fromstring(text_xml) + node[0].append(to_add) + res['arch'] = etree.tostring(doc) return res _columns = { @@ -261,7 +285,7 @@ class lunch_order(osv.Model): 'date': fields.date('Date', required=True,readonly=True, states={'new':[('readonly', False)]}), 'order_line_ids' : fields.one2many('lunch.order.line','order_id','Products',ondelete="cascade",readonly=True,states={'new':[('readonly', False)]}), #TODO: a good naming convention is to finish your field names with `_ids“ for *2many fields. BTW, the field name should reflect more it's nature: `order_line_ids“ for example 'total' : fields.function(_price_get, string="Total",store={ - 'lunch.order.line': (_compute_total, ['price'], 20), + 'lunch.order.line': (_compute_total, ['product_id','order_id'], 20), }), 'state': fields.selection([('new', 'New'),('confirmed','Confirmed'), ('cancelled','Cancelled'), ('partially','Partially Confirmed')],'Status', readonly=True, select=True), #TODO: parcially? #TODO: the labels are confusing. confirmed=='received' or 'delivered'... 'alerts': fields.function(_alerts_get, string="Alerts", type='text'), @@ -291,6 +315,16 @@ class lunch_order_line(osv.Model): return {'value': {'price': price}} return {'value': {'price': 0.0}} + def _price_get(self,cr,uid,ids,name,arg,context=None): + result={} + for orderLine in self.browse(cr,uid,ids,context=context): + result[orderLine.id]=orderLine.product_id.price + return result + + def order(self,cr,uid,ids,context=None): + for order_line in self.browse(cr,uid,ids,context=context): + self.write(cr,uid,[order_line.id],{'state':'ordered'},context) + return {} def confirm(self,cr,uid,ids,context=None): """ confirm one or more order line, update order status and create new cashmove """ @@ -342,8 +376,8 @@ class lunch_order_line(osv.Model): 'supplier' : fields.related('product_id','supplier',type='many2one',relation='res.partner',string="Supplier",readonly=True,store=True), 'user_id' : fields.related('order_id', 'user_id', type='many2one', relation='res.users', string='User', readonly=True, store=True), 'note' : fields.text('Note',size=256,required=False), - 'price': fields.float('Price'), - 'state': fields.selection([('new', 'New'),('confirmed','Confirmed'), ('cancelled','Cancelled')], \ + 'price' : fields.function(_price_get, type="float", string="Price",store=True), + 'state': fields.selection([('new', 'New'),('confirmed','Received'), ('ordered','Ordered'), ('cancelled','Cancelled')], \ 'Status', readonly=True, select=True), #new confirmed and cancelled are the convention 'cashmove': fields.one2many('lunch.cashmove','order_id','Cash Move',ondelete='cascade'), diff --git a/addons/lunch/lunch_view.xml b/addons/lunch/lunch_view.xml index d8ee3f614e5..8394308adfa 100644 --- a/addons/lunch/lunch_view.xml +++ b/addons/lunch/lunch_view.xml @@ -2,7 +2,7 @@ - + @@ -15,11 +15,13 @@ search + - - + + + @@ -29,6 +31,7 @@ lunch.order.line + @@ -45,6 +48,7 @@ search + @@ -57,6 +61,7 @@ search + @@ -69,6 +74,7 @@ search + @@ -93,8 +99,8 @@ Click to create a lunch order.

- Use lunch order if you need to order any food for your lunch. -

+ Select your favorite meals for today's lunch. +

@@ -108,7 +114,7 @@ {"search_default_is_mine":1}

- Here you can see your cash moves. There are your orders and refund. + Here you can see your cash moves.
A cash moves can be either an expense or a payment.

@@ -123,7 +129,7 @@ {"search_default_group_by_supplier":1, "search_default_today":1}

- Here you can see the orders of the day grouped by suppliers. + Here you can see today's orders grouped by suppliers.

@@ -138,7 +144,7 @@ {"search_default_group_by_date":1, "search_default_group_by_supplier":1}

- Here you can see the orders of the month grouped by suppliers. + Here you can see every orders grouped by suppliers and by date.

@@ -153,11 +159,12 @@ {"search_default_group_by_user":1}

- Click to create a transaction. + Click to create a new payment.

- The different cash moves are used to see the orders but also the - employees' refunds. + A cashmove can either be an expense or a payment.
+ An expense is automatically created at the order receipt.
+ A payment represents the employee reimbursement to the company.

@@ -176,7 +183,7 @@ Click to create a payment.

- Here you can see the employees' refund. + Here you can see the employees' payment.

@@ -192,7 +199,7 @@ Click to create a product for lunch.

- A product is defined by its name, category, price and supplier. + A product is defined by its name, category, price and supplier (the supplier must be a lunch supplier).

@@ -242,7 +249,8 @@ Click to create a lunch alert.

- Alerts are used to warn employee and user from possible issues about the lunch. + Alerts are used to warn employee from possible issues concerning the lunch orders.
+ To create a lunch alert you have to define its recurrency (A specific day of the year, every week or every day), the time interval during which the alert should be executed and the message to display.

@@ -262,7 +270,8 @@ -