[MERGE]
bzr revid: mra@mra-laptop-20100702111708-ooy6m8zcy8ztf10i bzr revid: mra@mra-laptop-20100702123926-t6veq32zgxkw7d8y bzr revid: mra@mra-laptop-20100702133729-8h08p75fo3ra9mcu
This commit is contained in:
@@ -50,15 +50,17 @@ def get_recurrent_dates(rrulestring, exdate, startdate=None, exrule=None):
|
||||
|
||||
if not startdate:
|
||||
startdate = datetime.now()
|
||||
rset1 = rrule.rrulestr(rrulestring, dtstart=startdate, forceset=True)
|
||||
if not exdate:
|
||||
exdate = []
|
||||
rset1 = rrule.rrulestr(str(rrulestring), dtstart=startdate, forceset=True)
|
||||
|
||||
for date in exdate:
|
||||
datetime_obj = todate(date)
|
||||
rset1._exdate.append(datetime_obj)
|
||||
if exrule:
|
||||
rset1.exrule(rrule.rrulestr(str(exrule), dtstart=startdate))
|
||||
re_dates = map(lambda x:x.strftime('%Y-%m-%d %H:%M:%S'), rset1._iter())
|
||||
return re_dates
|
||||
|
||||
return rset1._iter()
|
||||
|
||||
def base_calendar_id2real_id(base_calendar_id=None, with_date=False):
|
||||
"""
|
||||
@@ -791,61 +793,98 @@ class calendar_alarm(osv.osv):
|
||||
@param use_new_cursor: False or the dbname
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
if not context:
|
||||
context = {}
|
||||
current_datetime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
cr.execute("select alarm.id as id \
|
||||
from calendar_alarm alarm \
|
||||
where alarm.state = %s and alarm.trigger_date <= %s", ('run', current_datetime))
|
||||
res = cr.dictfetchall()
|
||||
alarm_ids = map(lambda x: x['id'], res)
|
||||
#attendee_obj = self.pool.get('calendar.attendee')
|
||||
current_datetime = datetime.now()
|
||||
request_obj = self.pool.get('res.request')
|
||||
alarm_ids = self.search(cr, uid, [('state', '!=', 'done')], context=context)
|
||||
|
||||
mail_to = []
|
||||
for alarm in self.browse(cr, uid, alarm_ids):
|
||||
if alarm.action == 'display':
|
||||
value = {
|
||||
'name': alarm.name,
|
||||
'act_from': alarm.user_id.id,
|
||||
'act_to': alarm.user_id.id,
|
||||
'body': alarm.description,
|
||||
'trigger_date': alarm.trigger_date,
|
||||
'ref_doc1': '%s,%s' % (alarm.model_id.model, alarm.res_id)
|
||||
}
|
||||
request_id = request_obj.create(cr, uid, value)
|
||||
request_ids = [request_id]
|
||||
for attendee in alarm.attendee_ids:
|
||||
if attendee.user_id:
|
||||
value['act_to'] = attendee.user_id.id
|
||||
request_id = request_obj.create(cr, uid, value)
|
||||
request_ids.append(request_id)
|
||||
request_obj.request_send(cr, uid, request_ids)
|
||||
|
||||
if alarm.action == 'email':
|
||||
sub = '[Openobject Remainder] %s' % (alarm.name)
|
||||
body = """
|
||||
Name: %s
|
||||
Date: %s
|
||||
Description: %s
|
||||
for alarm in self.browse(cr, uid, alarm_ids, context=context):
|
||||
next_trigger_date = None
|
||||
update_vals = {}
|
||||
model_obj = self.pool.get(alarm.model_id.model)
|
||||
res_obj = model_obj.browse(cr, uid, alarm.res_id, context=context)
|
||||
re_dates = []
|
||||
|
||||
From:
|
||||
%s
|
||||
%s
|
||||
if res_obj.rrule:
|
||||
event_date = datetime.strptime(res_obj.date, '%Y-%m-%d %H:%M:%S')
|
||||
recurrent_dates = get_recurrent_dates(res_obj.rrule, res_obj.exdate, event_date, res_obj.exrule)
|
||||
|
||||
""" % (alarm.name, alarm.trigger_date, alarm.description, \
|
||||
alarm.user_id.name, alarm.user_id.signature)
|
||||
mail_to = [alarm.user_id.address_id.email]
|
||||
for att in alarm.attendee_ids:
|
||||
mail_to.append(att.user_id.address_id.email)
|
||||
if mail_to:
|
||||
tools.email_send(
|
||||
tools.config.get('email_from', False),
|
||||
mail_to,
|
||||
sub,
|
||||
body
|
||||
)
|
||||
self.write(cr, uid, [alarm.id], {'state':'done'})
|
||||
trigger_interval = alarm.trigger_interval
|
||||
if trigger_interval == 'days':
|
||||
delta = timedelta(days=alarm.trigger_duration)
|
||||
if trigger_interval == 'hours':
|
||||
delta = timedelta(hours=alarm.trigger_duration)
|
||||
if trigger_interval == 'minutes':
|
||||
delta = timedelta(minutes=alarm.trigger_duration)
|
||||
delta = alarm.trigger_occurs == 'after' and delta or -delta
|
||||
|
||||
for rdate in recurrent_dates:
|
||||
if rdate + delta <= current_datetime:
|
||||
re_dates.append(rdate.strftime("%Y-%m-%d %H:%M:%S"))
|
||||
rest_dates = recurrent_dates[len(re_dates):]
|
||||
next_trigger_date = rest_dates and rest_dates[0] or None
|
||||
|
||||
else:
|
||||
re_dates = [alarm.trigger_date]
|
||||
|
||||
for r_date in re_dates:
|
||||
ref = alarm.model_id.model + ',' + str(alarm.res_id)
|
||||
|
||||
# search for alreay sent requests
|
||||
if request_obj.search(cr, uid, [('trigger_date', '=', r_date), ('ref_doc1', '=', ref)], context=context):
|
||||
continue
|
||||
|
||||
if alarm.action == 'display':
|
||||
value = {
|
||||
'name': alarm.name,
|
||||
'act_from': alarm.user_id.id,
|
||||
'act_to': alarm.user_id.id,
|
||||
'body': alarm.description,
|
||||
'trigger_date': r_date,
|
||||
'ref_doc1': ref
|
||||
}
|
||||
request_id = request_obj.create(cr, uid, value)
|
||||
request_ids = [request_id]
|
||||
for attendee in res_obj.attendee_ids:
|
||||
if attendee.user_id:
|
||||
value['act_to'] = attendee.user_id.id
|
||||
request_id = request_obj.create(cr, uid, value)
|
||||
request_ids.append(request_id)
|
||||
request_obj.request_send(cr, uid, request_ids)
|
||||
|
||||
if alarm.action == 'email':
|
||||
sub = '[Openobject Reminder] %s' % (alarm.name)
|
||||
body = """
|
||||
Event: %s
|
||||
Event Date: %s
|
||||
Description: %s
|
||||
|
||||
From:
|
||||
%s
|
||||
|
||||
----
|
||||
%s
|
||||
|
||||
""" % (alarm.name, alarm.trigger_date, alarm.description, \
|
||||
alarm.user_id.name, alarm.user_id.signature)
|
||||
mail_to = [alarm.user_id.address_id.email]
|
||||
for att in alarm.attendee_ids:
|
||||
mail_to.append(att.user_id.address_id.email)
|
||||
if mail_to:
|
||||
tools.email_send(
|
||||
tools.config.get('email_from', False),
|
||||
mail_to,
|
||||
sub,
|
||||
body
|
||||
)
|
||||
if next_trigger_date:
|
||||
update_vals.update({'trigger_date': next_trigger_date})
|
||||
else:
|
||||
update_vals.update({'state': 'done'})
|
||||
self.write(cr, uid, [alarm.id], update_vals)
|
||||
return True
|
||||
|
||||
calendar_alarm()
|
||||
@@ -1273,13 +1312,12 @@ true, it will allow you to hide the event alarm information without removing it.
|
||||
new_rrule_str.append(new_rule)
|
||||
new_rrule_str = ';'.join(new_rrule_str)
|
||||
rdates = get_recurrent_dates(str(new_rrule_str), exdate, start_date, data['exrule'])
|
||||
for rdate in rdates:
|
||||
r_date = datetime.strptime(rdate, "%Y-%m-%d %H:%M:%S")
|
||||
for r_date in rdates:
|
||||
if start_date and r_date < start_date:
|
||||
continue
|
||||
if until_date and r_date > until_date:
|
||||
continue
|
||||
idval = real_id2base_calendar_id(data['id'], rdate)
|
||||
idval = real_id2base_calendar_id(data['id'], r_date.strftime("%Y-%m-%d %H:%M:%S"))
|
||||
result.append(idval)
|
||||
count += 1
|
||||
if result:
|
||||
@@ -1413,9 +1451,10 @@ true, it will allow you to hide the event alarm information without removing it.
|
||||
new_ids.append(event_id)
|
||||
|
||||
res = super(calendar_event, self).write(cr, uid, new_ids, vals, context=context)
|
||||
if vals.has_key('alarm_id') or vals.has_key('base_calendar_alarm_id'):
|
||||
if (vals.has_key('alarm_id') or vals.has_key('base_calendar_alarm_id'))\
|
||||
or (vals.has_key('date') or vals.has_key('duration') or vals.has_key('date_deadline')):
|
||||
# change alarm details
|
||||
alarm_obj = self.pool.get('res.alarm')
|
||||
context.update({'alarm_id': vals.get('alarm_id')})
|
||||
alarm_obj.do_alarm_create(cr, uid, new_ids, self._name, 'date', \
|
||||
context=context)
|
||||
return res
|
||||
|
||||
@@ -84,12 +84,12 @@ class marketing_campaign(osv.osv):
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', size=64, required=True),
|
||||
'object_id': fields.many2one('ir.model', 'Object', required=True,
|
||||
help="Choose the Object on which you want \
|
||||
'object_id': fields.many2one('ir.model', 'Model', required=True,
|
||||
help="Choose the model on which you want \
|
||||
this campaign to be run"),
|
||||
'partner_field_id': fields.many2one('ir.model.fields', 'Partner Field',
|
||||
domain="[('model_id', '=', object_id), ('ttype', '=', 'many2one'), ('relation', '=', 'res.partner')]",
|
||||
help="The generated workitems will be linked to the partner related to the record"),
|
||||
help="The generated workitems will be linked to the partner related to the record. If the record is the partner itself left this field empty."),
|
||||
'mode':fields.selection([('test', 'Test Directly'),
|
||||
('test_realtime', 'Test in Realtime'),
|
||||
('manual', 'With Manual Confirmation'),
|
||||
@@ -115,6 +115,7 @@ you required for the campaign"),
|
||||
}
|
||||
|
||||
def state_running_set(self, cr, uid, ids, *args):
|
||||
# TODO check that all subcampaigns are running
|
||||
campaign = self.browse(cr, uid, ids[0])
|
||||
if not campaign.activity_ids :
|
||||
raise osv.except_osv("Error", "There is no activitity in the campaign")
|
||||
@@ -135,6 +136,7 @@ you required for the campaign"),
|
||||
return True
|
||||
|
||||
def state_done_set(self, cr, uid, ids, *args):
|
||||
# TODO check that this campaign is not a subcampaign in running mode.
|
||||
segment_ids = self.pool.get('marketing.campaign.segment').search(cr, uid,
|
||||
[('campaign_id', 'in', ids),
|
||||
('state', '=', 'running')])
|
||||
@@ -144,6 +146,7 @@ you required for the campaign"),
|
||||
return True
|
||||
|
||||
def state_cancel_set(self, cr, uid, ids, *args):
|
||||
# TODO check that this campaign is not a subcampaign in running mode.
|
||||
self.write(cr, uid, ids, {'state': 'cancelled'})
|
||||
return True
|
||||
|
||||
@@ -265,10 +268,14 @@ class marketing_campaign_segment(osv.osv):
|
||||
'state': 'todo',
|
||||
'res_id': o_ids.id
|
||||
}
|
||||
|
||||
partner = None
|
||||
if partner_field:
|
||||
partner = getattr(o_ids, partner_field)
|
||||
if partner:
|
||||
wi_vals['partner_id'] = partner.id
|
||||
elif model_obj._name == 'res.partner':
|
||||
partner = o_ids
|
||||
if partner:
|
||||
wi_vals['partner_id'] = partner.id
|
||||
|
||||
for act_id in act_ids:
|
||||
wi_vals['activity_id'] = act_id
|
||||
@@ -284,8 +291,18 @@ class marketing_campaign_activity(osv.osv):
|
||||
_name = "marketing.campaign.activity"
|
||||
_description = "Campaign Activity"
|
||||
|
||||
_actions_type = [('email', 'E-mail'), ('paper', 'Paper'), ('action', 'Action'),
|
||||
('subcampaign', 'Sub-Campaign')]
|
||||
_action_types = [
|
||||
('email', 'E-mail'),
|
||||
('paper', 'Paper'),
|
||||
('action', 'Action'),
|
||||
# TODO implement the subcampaigns. The segment_id on woritems must be
|
||||
# optional (thus campaign_id must be a real many2one, and a constraint
|
||||
# must be set).
|
||||
# TODO implement the subcampaign out. disallow out transitions from
|
||||
# subcampaign activities ?
|
||||
#('subcampaign', 'Sub-Campaign'),
|
||||
]
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', size=128, required=True),
|
||||
'campaign_id': fields.many2one('marketing.campaign', 'Campaign',
|
||||
@@ -296,8 +313,7 @@ class marketing_campaign_activity(osv.osv):
|
||||
'start': fields.boolean('Start',help= "This activity is launched when the campaign starts."),
|
||||
'condition': fields.char('Condition', size=256, required=True,
|
||||
help="Python condition to know if the activity can be launched"),
|
||||
'type': fields.selection(_actions_type,
|
||||
'Type', required=True,
|
||||
'type': fields.selection(_action_types, 'Type', required=True,
|
||||
help="Describe type of action to be performed on the Activity.Eg : Send email,Send paper.."),
|
||||
'email_template_id': fields.many2one('email.template','Email Template'),
|
||||
'report_id': fields.many2one('ir.actions.report.xml', 'Reports', ),
|
||||
@@ -312,9 +328,8 @@ class marketing_campaign_activity(osv.osv):
|
||||
'from_ids': fields.one2many('marketing.campaign.transition',
|
||||
'activity_to_id',
|
||||
'Previous Activities'),
|
||||
'subcampaign_id': fields.many2one('marketing.campaign', 'Sub-Campaign'),
|
||||
'subcampaign_segment_id': fields.many2one('marketing.campaign.segment',
|
||||
'Sub Campaign Segment'),
|
||||
#'subcampaign_id': fields.many2one('marketing.campaign', 'Sub-Campaign',
|
||||
# domain="[('object_id', '=', object_id)]"),
|
||||
'variable_cost': fields.float('Variable Cost'),
|
||||
'revenue': fields.float('Revenue'),
|
||||
'signal': fields.char('Signal', size=128,
|
||||
@@ -341,14 +356,6 @@ class marketing_campaign_activity(osv.osv):
|
||||
),
|
||||
]
|
||||
|
||||
def __init__(self, *args):
|
||||
# FIXME use self._process_wi_<type>
|
||||
self._actions = {'paper' : self.process_wi_report,
|
||||
'email' : self.process_wi_email,
|
||||
'action' : self.process_wi_action,
|
||||
}
|
||||
return super(marketing_campaign_activity, self).__init__(*args)
|
||||
|
||||
def search(self, cr, uid, args, offset=0, limit=None, order=None,
|
||||
context=None, count=False):
|
||||
if context == None:
|
||||
@@ -363,7 +370,7 @@ class marketing_campaign_activity(osv.osv):
|
||||
return super(marketing_campaign_activity, self).search(cr, uid, args,
|
||||
offset, limit, order, context, count)
|
||||
|
||||
def process_wi_report(self, cr, uid, activity, workitem, context={}):
|
||||
def _process_wi_paper(self, cr, uid, activity, workitem, context=None):
|
||||
service = netsvc.LocalService('report.%s'%activity.report_id.report_name)
|
||||
(report_data, format) = service.create(cr, uid, [], {}, {})
|
||||
attach_vals = {
|
||||
@@ -378,24 +385,36 @@ class marketing_campaign_activity(osv.osv):
|
||||
self.pool.get('ir.attachment').create(cr, uid, attach_vals)
|
||||
return True
|
||||
|
||||
def process_wi_email(self, cr, uid, activity, workitem, context=None):
|
||||
def _process_wi_email(self, cr, uid, activity, workitem, context=None):
|
||||
return self.pool.get('email.template').generate_mail(cr, uid,
|
||||
activity.email_template_id.id,
|
||||
[workitem.res_id], context=context)
|
||||
|
||||
def process_wi_action(self, cr, uid, activity, workitem, context={}):
|
||||
context = {}
|
||||
def _process_wi_action(self, cr, uid, activity, workitem, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
server_obj = self.pool.get('ir.actions.server')
|
||||
context['active_id'] = workitem.res_id
|
||||
res = server_obj.run(cr, uid, [activity.server_action_id.id], context)
|
||||
#server action return False if the action is perfomed except client_action,other and python code
|
||||
return res==False and True or res
|
||||
|
||||
def process(self, cr, uid, act_id, wi_id, context={}):
|
||||
activity = self.browse(cr, uid, act_id)
|
||||
action_context = dict(context,
|
||||
active_id=workitem.res_id,
|
||||
active_ids=[workitem.res_id],
|
||||
active_model=workitem.object_id.model)
|
||||
res = server_obj.run(cr, uid, [activity.server_action_id.id],
|
||||
context=action_context)
|
||||
# server action return False if the action is perfomed
|
||||
# except client_action, other and python code
|
||||
return res == False and True or res
|
||||
|
||||
def process(self, cr, uid, act_id, wi_id, context=None):
|
||||
activity = self.browse(cr, uid, act_id, context=context)
|
||||
method = '_process_wi_%s' % (activity.type,)
|
||||
action = getattr(self, method, None)
|
||||
if not action:
|
||||
raise NotImplementedError('method %r in not implemented on %r object' % (method, self))
|
||||
|
||||
workitem_obj = self.pool.get('marketing.campaign.workitem')
|
||||
workitem = workitem_obj.browse(cr, uid, wi_id, context=context)
|
||||
return self._actions[activity.type](cr, uid, activity, workitem, context)
|
||||
return action(cr, uid, activity, workitem, context)
|
||||
|
||||
marketing_campaign_activity()
|
||||
|
||||
@@ -587,13 +606,12 @@ class marketing_campaign_workitem(osv.osv):
|
||||
# test test_realtime manual normal (active)
|
||||
# time Y N N N
|
||||
# signal N N N N
|
||||
# auto Y Y N Y
|
||||
# auto Y Y Y Y
|
||||
#
|
||||
|
||||
run = False
|
||||
if transition.trigger != 'signal' and campaign_mode != 'manual':
|
||||
if transition.trigger == 'auto' or campaign_mode == 'test':
|
||||
run = True
|
||||
run = transition.trigger == 'auto' \
|
||||
or (transition.trigger == 'time' \
|
||||
and campaign_mode == 'test')
|
||||
if run:
|
||||
new_wi = self.browse(cr, uid, wi_id, context)
|
||||
self._process_one(cr, uid, new_wi, context)
|
||||
|
||||
@@ -241,10 +241,11 @@
|
||||
<group attrs="{'invisible':[('type','!=','action')]}" >
|
||||
<field name="server_action_id" attrs="{'required':[('type','=','action')]}" domain="[('model_id','=',object_id)]" />
|
||||
</group>
|
||||
<!--
|
||||
<group attrs="{'invisible':[('type','!=','subcampaign')]}" >
|
||||
<field name="subcampaign_id" attrs="{'required':[('type','=','subcampaign')]}" />
|
||||
<field name="subcampaign_segment_id" attrs="{'required':[('type','=','subcampaign')]}" />
|
||||
</group>
|
||||
-->
|
||||
</group>
|
||||
</group>
|
||||
<newline/>
|
||||
|
||||
@@ -22,11 +22,9 @@ import urllib
|
||||
import urllib2
|
||||
import simplejson as json
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
from osv import fields, osv
|
||||
from marketing_campaign.marketing_campaign import _intervalTypes
|
||||
|
||||
mailchimp_url = 'http://%s.api.mailchimp.com/1.2'
|
||||
|
||||
class mailchimp_account(osv.osv):
|
||||
@@ -150,7 +148,7 @@ class marketing_campaign_activity(osv.osv):
|
||||
return {}
|
||||
return {'value':{}}
|
||||
|
||||
def process_wi_mailchimp(self, cr, uid, activity, workitem, context={}):
|
||||
def _process_wi_mailchimp(self, cr, uid, activity, workitem, context=None):
|
||||
mailchimp_account_id = activity.mailchimp_account_id.id
|
||||
list_name = activity.mailchimp_list
|
||||
mc_acc_obj = self.pool.get('mailchimp.account')
|
||||
@@ -193,18 +191,15 @@ class marketing_campaign_activity(osv.osv):
|
||||
'merge_vars[address][city]' : model_obj.city and model_obj.city or '',
|
||||
'merge_vars[phone]' : model_obj.phone and model_obj.phone or '',
|
||||
})
|
||||
res = mc_acc_obj.get_response(cr, uid, mailchimp_account_id, 'listSubscribe', params)
|
||||
# handle mailchimp error
|
||||
mc_acc_obj.get_response(cr, uid, mailchimp_account_id, 'listSubscribe', params)
|
||||
# TODO handle mailchimp error
|
||||
return True
|
||||
else :
|
||||
else :
|
||||
return {'error_msg' : "Invalid Email Address"}
|
||||
|
||||
|
||||
def __init__(self, *args):
|
||||
res = super(marketing_campaign_activity, self).__init__(*args)
|
||||
self._actions.update({'mailchimp' : self.process_wi_mailchimp})
|
||||
self._actions_type.append(('mailchimp', 'Mailchimp'))
|
||||
return res
|
||||
|
||||
super(marketing_campaign_activity, self).__init__(*args)
|
||||
self._action_types.append(('mailchimp', 'Mailchimp'))
|
||||
|
||||
marketing_campaign_activity()
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -35,12 +35,13 @@
|
||||
<form string="My Board">
|
||||
<hpaned>
|
||||
<child1>
|
||||
<action colspan="4" height="220" name="%(purchase_draft)d" string="Draft Purchase Order" width="510"/>
|
||||
<action colspan="4" height="220" name="%(purchase_waiting)d" string="Purchase Order in Waiting" width="510"/>
|
||||
<action colspan="4" height="220" name="%(purchase.action_current_purchases)d" string="Current purchases" width="510"/>
|
||||
<action colspan="4" height="220" name="%(purchase.action_po_per_month_tree)d" string="Purchase order per month" width="510"/>
|
||||
</child1>
|
||||
<child2>
|
||||
<action colspan="4" height="220" name="%(purchase.action_purchase_order_report_all)d" string="Total Qty and Amount by month" />
|
||||
<action colspan="4" height="220" name="%(purchase.action_stock_move_report_po)d" string="Total Orders by User per month" />
|
||||
<action colspan="4" height="220" name="%(purchase.action_purchase_by_supplier)d" string="Purchase by supplier" />
|
||||
<action colspan="4" height="220" name="%(purchase.action_total_price_by_product_by_state)d" string="Total price by product by state" />
|
||||
<action colspan="4" height="220" name="%(purchase.action_qty_per_product)d" string="Total Quantity per product" />
|
||||
</child2>
|
||||
</hpaned>
|
||||
</form>
|
||||
|
||||
@@ -34,16 +34,14 @@ class purchase_report(osv.osv):
|
||||
'date': fields.date('Order Date', readonly=True),
|
||||
'name': fields.char('Year',size=64,required=False, readonly=True),
|
||||
'day': fields.char('Day', size=128, readonly=True),
|
||||
'state': fields.selection([
|
||||
('draft','Quotation'),
|
||||
('waiting_date','Waiting Schedule'),
|
||||
('manual','Manual in progress'),
|
||||
('progress','In progress'),
|
||||
('shipping_except','Shipping Exception'),
|
||||
('invoice_except','Invoice Exception'),
|
||||
('done','Done'),
|
||||
('cancel','Cancel')
|
||||
], 'Order State', readonly=True),
|
||||
'state': fields.selection([('draft', 'Request for Quotation'),
|
||||
('wait', 'Waiting'),
|
||||
('confirmed', 'Waiting Supplier Ack'),
|
||||
('approved', 'Approved'),
|
||||
('except_picking', 'Shipping Exception'),
|
||||
('except_invoice', 'Invoice Exception'),
|
||||
('done', 'Done'),
|
||||
('cancel', 'Cancelled')],'Order State', readonly=True),
|
||||
'product_id':fields.many2one('product.product', 'Product', readonly=True),
|
||||
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', readonly=True),
|
||||
'location_id': fields.many2one('stock.location', 'Destination', readonly=True),
|
||||
|
||||
@@ -176,6 +176,98 @@
|
||||
</record>
|
||||
<menuitem action="action_stock_move_report_po" id="menu_action_stock_move_report_po" parent="base.next_id_73" sequence="8"/>
|
||||
|
||||
<record model="ir.ui.view" id="view_purchase_by_supplier_graph">
|
||||
<field name="name">purchase.by.supplier.graph</field>
|
||||
<field name="model">purchase.report</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Purchase by supplier" >
|
||||
<field name="partner_id"/>
|
||||
<field name="nbr" operator="+"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="action_purchase_by_supplier" model="ir.actions.act_window">
|
||||
<field name="name">Purchase by supplier</field>
|
||||
<field name="res_model">purchase.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="domain">[('state','=','done'),('date','>',(datetime.date.today()-datetime.timedelta(days=30)).strftime('%Y-%m-%d'))]</field>
|
||||
<field name="context">{'group_by_no_leaf':1,'group_by':['partner_id']}</field>
|
||||
<field name="view_id" ref="view_purchase_by_supplier_graph"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_total_price_by_product_by_state_graph">
|
||||
<field name="name">total.price.by.product.by.state.graph</field>
|
||||
<field name="model">purchase.report</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Total price by product by state" >
|
||||
<field name="product_id"/>
|
||||
<field name="price_total" operator="+"/>
|
||||
<field name="state" group="True"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="action_total_price_by_product_by_state" model="ir.actions.act_window">
|
||||
<field name="name">Total price by product by state</field>
|
||||
<field name="res_model">purchase.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,graph</field>
|
||||
<field name="context">{'group_by_no_leaf':1,'group_by':['product_id','state']}</field>
|
||||
<field name="view_id" ref="view_total_price_by_product_by_state_graph"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_qty_per_product_graph">
|
||||
<field name="name">qty.per.product.graph</field>
|
||||
<field name="model">purchase.report</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Qty. per product" >
|
||||
<field name="product_id"/>
|
||||
<field name="quantity" operator="+"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="action_qty_per_product" model="ir.actions.act_window">
|
||||
<field name="name">Qty. per product</field>
|
||||
<field name="res_model">purchase.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="domain">[('state','=','done')]</field>
|
||||
<field name="context">{'group_by_no_leaf':1,'group_by':['product_id']}</field>
|
||||
<field name="view_id" ref="view_qty_per_product_graph"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_po_per_month_tree">
|
||||
<field name="name">qty.per.product.tree</field>
|
||||
<field name="model">purchase.report</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Purchase order per month" >
|
||||
<field name="month"/>
|
||||
<field name="product_id" invisible="1"/>
|
||||
<field name="nbr" operator="+"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="action_po_per_month_tree" model="ir.actions.act_window">
|
||||
<field name="name">Purchase order per month</field>
|
||||
<field name="res_model">purchase.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="domain">[('date','>',time.strftime('%Y-01-01 00:00:00')),('date','<',time.strftime('%Y-12-31 23:59:59')),('state','=','done')]</field>
|
||||
<field name="context">{'group_by_no_leaf':1,'group_by':['month','product_id']}</field>
|
||||
<field name="view_id" ref="view_po_per_month_tree"/>
|
||||
</record>
|
||||
|
||||
<record id="action_current_purchases" model="ir.actions.act_window">
|
||||
<field name="name">Current purchases</field>
|
||||
<field name="res_model">purchase.order</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('state','in',('draft','confirmed'))]</field>
|
||||
<field name="view_id" ref="purchase.purchase_order_tree"/>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
Reference in New Issue
Block a user