-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Registrationsevent.registration
@@ -285,12 +313,18 @@
-
-
-
+
+
-
+
+
+
+
+
+
+
+
@@ -308,86 +342,6 @@
name="Registrations"
id="menu_action_registration" parent="menu_event_main"
action="action_registration"/>
-
-
-
- report.event.registration.tree
- report.event.registration
- tree
-
-
-
-
-
-
-
-
-
-
-
-
-
- report.event.registration.graph
- report.event.registration
- graph
-
-
-
-
-
-
-
-
-
-
-
- Events On Registrations
- report.event.registration
- form
- tree,graph
-
-
-
-
-
-
-
-
- report.event.type.registration.tree
- report.event.type.registration
- tree
-
-
-
-
-
-
-
-
-
-
-
- report.event.type.registration.graph
- report.event.type.registration
- graph
-
-
-
-
-
-
-
-
-
-
- Registration By Event Types
- report.event.type.registration
- form
- graph,tree
-
-
-
-
diff --git a/addons/event/report/__init__.py b/addons/event/report/__init__.py
new file mode 100644
index 00000000000..1c60e2715df
--- /dev/null
+++ b/addons/event/report/__init__.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+import report_event_registration
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
diff --git a/addons/event/report/report_event_registration.py b/addons/event/report/report_event_registration.py
new file mode 100644
index 00000000000..d9232136c3a
--- /dev/null
+++ b/addons/event/report/report_event_registration.py
@@ -0,0 +1,83 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+from osv import fields, osv
+import tools
+
+class report_event_registration(osv.osv):
+
+ _name = "report.event.registration"
+ _description = "Events on registrations and Events on type"
+ _auto = False
+ _rec_name = 'date'
+ _columns = {
+ 'date': fields.date('Date', readonly=True),
+ 'year': fields.char('Year', size=4, readonly=True),
+ 'month':fields.selection([('01','January'), ('02','February'), ('03','March'), ('04','April'),
+ ('05','May'), ('06','June'), ('07','July'), ('08','August'), ('09','September'),
+ ('10','October'), ('11','November'), ('12','December')], 'Month',readonly=True),
+ 'day': fields.char('Day', size=128, readonly=True),
+ 'event_id': fields.many2one('event.event', 'Event Related', required=True),
+ 'draft_state': fields.integer(' # No of draft Registration.', size=20),
+ 'confirm_state': fields.integer(' # No of Confirm Registration', size=20),
+ 'register_max': fields.integer('Maximum Registrations'),
+ 'nbevent': fields.integer('Number Of Events'),
+ 'type': fields.many2one('event.type', 'Event Type'),
+ 'state': fields.selection([('draft', 'Draft'), ('confirm', 'Confirmed'), ('done', 'Done'), ('cancel', 'Cancelled')], 'State', readonly=True, required=True),
+ 'user_id':fields.many2one('res.users', 'Responsible', readonly=True),
+ }
+ _order = 'date desc'
+ def init(self, cr):
+ """
+ initialize the sql view for the event registration
+ cr -- the cursor
+ """
+ cr.execute("""
+ create or replace view report_event_registration as (
+ select
+ e.id as id,
+ c.event_id as event_id,
+ e.date_begin as date,
+ e.user_id as user_id,
+ to_char(e.date_begin, 'YYYY') as year,
+ to_char(e.date_begin, 'MM') as month,
+ to_char(e.date_begin, 'YYYY-MM-DD') as day,
+ count(t.id) as nbevent,
+ t.id as type,
+ (SELECT sum(c.nb_register) FROM event_registration c WHERE c.event_id=e.id and t.id=e.type and state in ('draft')) as draft_state,
+ (SELECT sum(c.nb_register) FROM event_registration c WHERE c.event_id=e.id and t.id=e.type and state in ('open')) as confirm_state,
+ e.register_max as register_max,
+ e.state as state
+ from
+ event_event e
+ inner join
+ event_registration c on (e.id=c.event_id)
+ inner join
+ event_type t on (e.type=t.id)
+ group by
+ to_char(e.date_begin, 'YYYY'),
+ to_char(e.date_begin, 'MM'),
+ t.id, e.id, e.date_begin,
+ e.register_max, e.type, e.state, c.event_id, e.user_id,
+ to_char(e.date_begin, 'YYYY-MM-DD')
+ )""")
+
+report_event_registration()
diff --git a/addons/event/report/report_event_registration_view.xml b/addons/event/report/report_event_registration_view.xml
new file mode 100644
index 00000000000..f7a2009020c
--- /dev/null
+++ b/addons/event/report/report_event_registration_view.xml
@@ -0,0 +1,117 @@
+
+
+
+
+
+ report.event.registration.tree
+ report.event.registration
+ tree
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ report.event.registration.graph
+ report.event.registration
+ graph
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ .search
+ report.event.registration
+ search
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Events On Registrations
+ report.event.registration
+ form
+ tree,graph
+
+ {"search_default_user":1,"search_default_month":1,'group_by_no_leaf':1,'group_by':[]}
+
+
+
+
+
+
+
+
diff --git a/addons/event/security/ir.model.access.csv b/addons/event/security/ir.model.access.csv
index 9eccb065448..6a5f00e2846 100644
--- a/addons/event/security/ir.model.access.csv
+++ b/addons/event/security/ir.model.access.csv
@@ -4,7 +4,6 @@
"access_event_event","event.event","model_event_event","crm.group_crm_user",1,1,1,1
"access_event_registration","event.registration","model_event_registration","crm.group_crm_user",1,1,1,1
"access_report_event_registration","report.event.registration","model_report_event_registration","crm.group_crm_user",1,0,0,0
-"access_report_event_type_registration","report.event.type.registration","model_report_event_type_registration","crm.group_crm_user",1,0,0,0
"access_event_confirm_registration","event.confirm.registration","model_event_confirm_registration","crm.group_crm_user",1,0,0,0
"access_event_confirm_registration_manager","event.confirm.registration manager","model_event_confirm_registration","crm.group_crm_manager",1,1,1,1
"access_event_make_invoice","event.make.invoice","model_event_make_invoice","crm.group_crm_user",1,1,1,1
diff --git a/addons/event/test/test_event.yml b/addons/event/test/test_event.yml
new file mode 100644
index 00000000000..4cf9438cb3d
--- /dev/null
+++ b/addons/event/test/test_event.yml
@@ -0,0 +1,239 @@
+- |
+ In order to test the 'event' module in OpenERP, we create a new event.
+
+- |
+ Given that I have product "Ticket for Concert".
+-
+ !record {model: product.product, id: product_product_ticketforconcert0}:
+ categ_id: product.cat1
+ cost_method: standard
+ list_price: 68.0
+ mes_type: fixed
+ name: Ticket for Concert
+ procure_method: make_to_stock
+ standard_price: 15.0
+ supply_method: buy
+ type: product
+ uom_id: product.product_uom_unit
+ uom_po_id: product.product_uom_unit
+ volume: 0.0
+ warranty: 0.0
+ weight: 0.0
+ weight_net: 0.0
+
+- |
+ Given that I have also Event type "Conference".
+-
+ !record {model: event.type, id: event_type_conference0}:
+ name: Conference
+- |
+ I create partner "Mark Johnson" and and I provide an address to this
+ new customer, as well as an email "info@mycustomer.com".
+-
+ !record {model: res.partner, id: res_partner_markjohnson0}:
+ address:
+ - city: Bruxelles
+ country_id: base.be
+ job_ids:
+ - contact_id: base_contact.res_partner_contact_jacot0
+ function: CTO
+ name: base.res_partner_maxtor
+ sequence_partner: 0.0
+ state: current
+ street: Rue des Palais 51, bte 33
+ type: default
+ zip: '1000'
+ email: 'info@mycustomer.com'
+ credit_limit: 0.0
+ lang: en_US
+ name: Mark Johnson
+ property_account_payable: account.a_pay
+ property_account_receivable: account.a_recv
+
+- |
+ we create it with a "Conference on ERP Buisness" event and provide "Beginning date", "Ending Date", "Product" as Concert Ticket.
+-
+ !record {model: event.event, id: event_event_conference0}:
+ code: C/004
+ date_begin: '2010-06-07 13:39:00'
+ date_end: '2010-06-10 13:39:00'
+ name: Conference on ERP Buisness
+ parent_id: event.case_section_event
+ product_id: 'product_product_ticketforconcert0'
+ register_max: 0.0
+ register_min: 0.0
+ state: draft
+ type: 'event_type_conference0'
+
+- |
+ we set the limit of registrations to this event using "Minimum Registrations" 2 and "Maximum Registrations" 10
+-
+ !python {model: event.event}: |
+ self.write(cr, uid, [ref('event_event_conference0')], {'register_max': 10, 'register_min': 2})
+
+- |
+ We Check that the event is in "Draft" state.
+-
+ !assert {model: event.event, id: event_event_conference0}:
+ - state == 'draft'
+
+- |
+ Then we confirm it press on "Confirm Event" button.
+-
+ !python {model: event.event}: |
+ self.button_confirm(cr, uid, [ref("event_event_conference0")], {"active_ids": [ref("event.menu_event_event")]})
+
+- |
+ Check that Event is "confirmed" or not.
+-
+ !assert {model: event.event, id: event_event_conference0}:
+ - state == 'confirm'
+
+- |
+ person "Mark Johnson" want to confirm their registrations. for that
+ I create New Registration for "Conference on ERP Buisness" event.
+-
+ !record {model: event.registration, id: event_registration_registrationjacot0}:
+ badge_name: Jacot
+ badge_partner: Mark Johnson
+ badge_title: M.
+ contact_id: base_contact.res_partner_contact_jacot0
+ date_deadline: '2010-06-07 13:39:00'
+ event_id: event.event_event_conference0
+ invoice_label: Ticket for Concert
+ name: 'Registration: Jacot'
+ partner_id: 'res_partner_markjohnson0'
+ partner_invoice_id: 'res_partner_markjohnson0'
+ unit_price: 68.0
+- |
+ I check that "Number of registration" is less than "Maximum registration" defined in "Conference on ERP Buisness" event.
+ if not then confirmation will fail because its greater then the Maximum registration.
+-
+ !python {model: event.event}: |
+ obj_register = self.pool.get('event.registration')
+ event_id1 = self.browse(cr, uid, [ref('event_event_conference0')])[0]
+ register_ids = obj_register.search(cr, uid, [('event_id', '=', event_id1.id)])
+ register_id = obj_register.browse(cr, uid, register_ids)[0]
+ assert register_id.nb_register <= event_id1.register_max
+
+- |
+ And Confirm that Registration by click on "Confirm Registration" button of Registraion form.
+-
+ !python {model: event.registration}: |
+ self.check_confirm(cr, uid, [ref("event_registration_registrationjacot0")], {"active_ids": [ref("event.menu_action_registration")]})
+
+- |
+ one other Person "Zen" also want to confirm their Registraions. so
+ They create New registraion for This event.
+-
+ !record {model: event.registration, id: event_registration_registrationzen0}:
+ badge_name: Zen
+ badge_partner: China Export
+ contact_id: base_contact.res_partner_contact_zen0
+ date_deadline: '2010-06-07 13:39:00'
+ event_id: event.event_event_conference0
+ invoice_label: Ticket for Concert
+ name: 'Registration: Zen'
+ partner_id: base.res_partner_3
+ partner_invoice_id: base.res_partner_3
+ unit_price: 68.0
+
+- |
+ And Confirm that Registration by click on "Confirm Registration" button of Registraion form.
+-
+ !python {model: event.registration}: |
+ self.check_confirm(cr, uid, [ref("event_registration_registrationzen0")], {"active_ids": [ref("event.menu_action_registration")]})
+
+- |
+ Third person create New Registration for "Conference on ERP Business" event.
+-
+ !record {model: event.registration, id: event_registration_registrationpassot0}:
+ badge_name: Passot
+ badge_partner: Mediapole SPRL
+ badge_title: M.
+ contact_id: base_contact.res_partner_contact_passot0
+ date_deadline: '2010-06-07 13:39:00'
+ email_from: info@mediapole.net
+ event_id: 'event_event_conference0'
+ invoice_label: Ticket for Concert
+ name: 'Registration: Passot'
+ partner_id: base.res_partner_8
+ partner_invoice_id: base.res_partner_8
+ unit_price: 68.0
+- |
+ This person cannot Confirm their registration.so I check that state is "Unconfirmed".
+-
+ !assert {model: event.registration, id: event_registration_registrationpassot0}:
+ - state == 'draft'
+
+- |
+ I Check that the total number of confirmed is 2 and unconfirmed registrations 1.
+-
+ !python {model: event.event}: |
+ obj_event = self.browse(cr, uid, [ref('event_event_conference0')])[0]
+ assert obj_event.register_current == '2'
+ assert obj_event.register_prospect == '1'
+
+- |
+ We check all registered partners to this event using the wizard "List Register Partners".
+-
+ !record {model: event.partners.list, id: event_partners_list_0}:
+ {}
+-
+ I click on "Open Partners" button of "List Register Partners" wizard.
+-
+ !python {model: event.partners.list}: |
+ self.list_partners(cr, uid, [ref("event_partners_list_0")], {"active_ids":
+ [ref("event.event_event_conference0")]})
+
+- |
+ We check all registrations on current event using the wizard "Registrations"
+-
+ !record {model: event.registration.list, id: event_registration_list_0}:
+ {}
+- |
+ I click on "Open Registrations" button of "Registrations" wizard.
+-
+ !python {model: event.registration.list}: |
+ self.open_registration(cr, uid, [ref("event_registration_list_0")], {"active_ids": [ref("event.event_event_conference0")]})
+
+- |
+ This event is finished by click on "Event Done" button of this event form.
+-
+ !python {model: event.event}: |
+ self.button_done(cr, uid, [ref("event.event_event_conference0")], {"active_ids": [ref("event.menu_event_event")] })
+- |
+ We can create invoice if the registration is in "Open" state otherwise it gives the warning to the user.
+ so I check that Registration is in "Open" state before click on "Make Invoices."
+-
+ !assert {model: event.registration, id: event_registration_registrationjacot0}:
+ - state == 'open'
+- |
+ Now, I will invoice the participant who have address using "Make Invoices". This wizard will also give the number of invoices are created and rejected.
+ Create invoice will be linked to Invoice Field available on Payments tab of registrations
+-
+ !record {model: event.make.invoice, id: event_make_invoice_0}:
+ inv_created: '0'
+ inv_rej_reason: 'ID 1: Registration already has an invoice linked. \n'
+ inv_rejected: '1'
+- |
+ I click on "Open" button of this "Make Invoices" wizard.
+-
+ !python {model: event.make.invoice}: |
+ self.confirm(cr, uid, [ref("event_make_invoice_0")], {"active_ids": [ref("event_registration_registrationjacot0")]})
+- |
+ I check that Invoice for this partner is create or not.
+-
+ !python {model: event.registration}: |
+ obj_event_reg = self.pool.get('event.registration')
+ obj_lines = self.pool.get('account.invoice.line')
+ inv_obj = self.pool.get('account.invoice')
+ data_event_reg = obj_event_reg.browse(cr, uid, [ref('event_registration_registrationzen0')], context=context)[0]
+ invoice_ids = inv_obj.search(cr, uid, [('partner_id', '=', data_event_reg.partner_invoice_id.id)])
+ invoice_id = inv_obj.browse(cr, uid, invoice_ids)
+ if invoice_id:
+ line_ids = obj_lines.search(cr, uid, [('product_id', '=', data_event_reg.event_id.product_id), ('invoice_id', '=', invoice_id.id), ('price_unit', '=', data_event_reg.unit_price)])
+ line_id = obj_lines.browse(cr, uid, line_ids)[0]
+ assert line_id.product_id == data_event_reg.product_id
+ assert data_event_reg.partner_id == invoice_id.partner_id
+ assert invoice_id.address_invoice_id == data_event_reg.partner_address_id
diff --git a/addons/event/wizard/event_confirm_registration_view.xml b/addons/event/wizard/event_confirm_registration_view.xml
index 03733d2045d..049d4f5bb7f 100644
--- a/addons/event/wizard/event_confirm_registration_view.xml
+++ b/addons/event/wizard/event_confirm_registration_view.xml
@@ -2,32 +2,32 @@
-
+ Registration Confirmationevent.confirm.registrationform
-
-
+
+
-
-
+
+
-
+
-
+
-
+ Registrationsir.actions.act_windowevent.confirm.registrationformform
- {'record_id' : active_id}
+ {'record_id' : active_id}new
-
+
-
\ No newline at end of file
+
diff --git a/addons/event/wizard/event_make_invoice.py b/addons/event/wizard/event_make_invoice.py
index e4eacf99d3c..7a8bcfb489b 100644
--- a/addons/event/wizard/event_make_invoice.py
+++ b/addons/event/wizard/event_make_invoice.py
@@ -27,13 +27,21 @@ class event_make_invoice(osv.osv_memory):
_name = "event.make.invoice"
_description = "Event Make Invoice"
_columns = {
- 'inv_created': fields.char('Invoice Created', size=32, readonly=True),
- 'inv_rejected': fields.char('Invoice Rejected', size=32, readonly=True),
- 'inv_rej_reason': fields.text('Error Messages', readonly=True),
+ 'inv_created': fields.char('Invoice Created', size=32, readonly=True),
+ 'inv_rejected': fields.char('Invoice Rejected', size=32, readonly=True),
+ 'inv_rej_reason': fields.text('Error Messages', readonly=True),
# 'invoice_ids': fields.char('Invoice Ids', size=128), # Improve me
}
def _makeInvoices(self, cr, uid, context={}):
+ """
+ Get default value for fields
+ @param cr: the current row, from the database cursor,
+ @param uid: the current user’s ID for security checks,
+ @param context: A standard dictionary for contextual values
+ @return: Dictionary of value
+ """
+
invoices = {}
invoice_ids = []
create_ids=[]
@@ -45,7 +53,7 @@ class event_make_invoice(osv.osv_memory):
obj_event_reg = self.pool.get('event.registration')
obj_lines = self.pool.get('account.invoice.line')
inv_obj = self.pool.get('account.invoice')
- data_event_reg = obj_event_reg.browse(cr,uid, context['active_ids'], context=context)
+ data_event_reg = obj_event_reg.browse(cr, uid, context['active_ids'], context=context)
for reg in data_event_reg:
if reg.state=='draft':
@@ -79,27 +87,27 @@ class event_make_invoice(osv.osv_memory):
continue
inv_create = inv_create + 1
- value = obj_lines.product_id_change(cr, uid, [], reg.event_id.product_id.id,uom =False, partner_id=reg.partner_invoice_id.id, fposition_id=reg.partner_invoice_id.property_account_position.id)
- data_product = self.pool.get('product.product').browse(cr,uid,[reg.event_id.product_id.id])
+ value = obj_lines.product_id_change(cr, uid, [], reg.event_id.product_id.id, uom =False, partner_id=reg.partner_invoice_id.id, fposition_id=reg.partner_invoice_id.property_account_position.id)
+ data_product = self.pool.get('product.product').browse(cr, uid, [reg.event_id.product_id.id])
for tax in data_product[0].taxes_id:
tax_ids.append(tax.id)
vals = value['value']
c_name = reg.contact_id and ('-' + self.pool.get('res.partner.contact').name_get(cr, uid, [reg.contact_id.id])[0][1]) or ''
vals.update({
- 'name': reg.invoice_label + '-' + c_name,
- 'price_unit': reg.unit_price,
- 'quantity': reg.nb_register,
- 'product_id':reg.event_id.product_id.id,
- 'invoice_line_tax_id': [(6, 0, tax_ids)],
+ 'name': reg.invoice_label + '-' + c_name,
+ 'price_unit': reg.unit_price,
+ 'quantity': reg.nb_register,
+ 'product_id':reg.event_id.product_id.id,
+ 'invoice_line_tax_id': [(6, 0, tax_ids)],
})
inv_line_ids = obj_event_reg._create_invoice_lines(cr, uid, [reg.id], vals)
val_invoice['value'].update({
- 'origin': reg.invoice_label,
- 'reference': False,
- 'invoice_line': [(6,0,[inv_line_ids])],
- 'comment': "",
+ 'origin': reg.invoice_label,
+ 'reference': False,
+ 'invoice_line': [(6, 0, [inv_line_ids])],
+ 'comment': "",
})
inv_id = inv_obj.create(cr, uid, val_invoice['value'])
@@ -108,7 +116,7 @@ class event_make_invoice(osv.osv_memory):
obj_event_reg._history(cr, uid, [reg.id], 'Invoiced', history=True)
# {'inv_created' : str(inv_create) , 'inv_rejected' : str(inv_reject), 'invoice_ids': str(list_inv), 'inv_rej_reason': inv_rej_reason}
- return {'inv_created' : str(inv_create) , 'inv_rejected' : str(inv_reject), 'inv_rej_reason': inv_rej_reason}
+ return {'inv_created': str(inv_create), 'inv_rejected': str(inv_reject), 'inv_rej_reason': inv_rej_reason}
def default_get(self, cr, uid, fields_list, context=None):
res = super(event_make_invoice, self).default_get(cr, uid, fields_list, context)
@@ -116,18 +124,26 @@ class event_make_invoice(osv.osv_memory):
return res
def confirm(self, cr, uid, ids, context={}):
+ """
+ Open Account invoice form.
+ @param cr: the current row, from the database cursor,
+ @param uid: the current user’s ID for security checks,
+ @param ids: List of event make invoice's Id.
+ @param context: A standard dictionary for contextual values
+ @return: Dictionary of value
+ """
obj_model = self.pool.get('ir.model.data')
data_inv = self.read(cr, uid, ids, [], context)[0]
- model_data_ids = obj_model.search(cr,uid,[('model','=','ir.ui.view'),('name','=','invoice_form')])
- resource_id = obj_model.read(cr,uid,model_data_ids,fields=['res_id'])[0]['res_id']
+ model_data_ids = obj_model.search(cr, uid, [('model', '=', 'ir.ui.view'), ('name', '=', 'invoice_form')])
+ resource_id = obj_model.read(cr, uid, model_data_ids, fields=['res_id'])[0]['res_id']
return {
# 'domain': "[('id','in', ["+','.join(map(str,data_inv['invoice_ids']))+"])]",
- 'name': 'Invoices',
- 'view_type': 'form',
- 'view_mode': 'tree,form',
- 'res_model': 'account.invoice',
- 'views': [(False,'tree'),(resource_id,'form')],
- 'context': "{'type':'out_invoice'}",
+ 'name': 'Invoices',
+ 'view_type': 'form',
+ 'view_mode': 'tree,form',
+ 'res_model': 'account.invoice',
+ 'views': [(False, 'tree'), (resource_id, 'form')],
+ 'context': "{'type':'out_invoice'}",
'type': 'ir.actions.act_window'
}
diff --git a/addons/event/wizard/event_registration.py b/addons/event/wizard/event_registration.py
index 4803d118610..7640f040a99 100644
--- a/addons/event/wizard/event_registration.py
+++ b/addons/event/wizard/event_registration.py
@@ -23,10 +23,20 @@ from osv import fields, osv
class event_registration_list(osv.osv_memory):
""" List Event Registration """
+
_name = "event.registration.list"
_description = "List Event Registrations"
def open_registration(self, cr, uid, ids, context={}):
+ """
+ Open Event Registration form
+ @param cr: the current row, from the database cursor,
+ @param uid: the current user’s ID for security checks,
+ @param ids: List of Event registration list's IDs
+ @param context: A standard dictionary for contextual values
+ @return: Dictionary value which open Event registration form.
+ """
+
if not context.get('active_id', None):
return {
'name': 'Event Registrations',
@@ -37,7 +47,7 @@ class event_registration_list(osv.osv_memory):
}
return {
- 'domain': [('section_id', '=', context['active_id'])],
+ 'domain': [('event_id', '=', context['active_id'])],
'name': 'Event Registrations',
'view_type': 'form',
'view_mode': 'tree,form',
diff --git a/addons/event/wizard/event_registration_view.xml b/addons/event/wizard/event_registration_view.xml
index 5afe437bc0f..7a89628f219 100644
--- a/addons/event/wizard/event_registration_view.xml
+++ b/addons/event/wizard/event_registration_view.xml
@@ -2,30 +2,33 @@
-
+ List Event Registrationsevent.registration.listform
-
-
-
-
+
+
+
+
+
+
+
-
+
-
+ Registrationsir.actions.act_windowevent.registration.listformform
- {'record_id' : active_id}
+ {'record_id' : active_id}new
-
+
-
+ Event Registrations
@@ -36,4 +39,4 @@
-
\ No newline at end of file
+
diff --git a/addons/event/wizard/event_registrations_partner.py b/addons/event/wizard/event_registrations_partner.py
index e8fe43f97e0..5c443e39c1b 100644
--- a/addons/event/wizard/event_registrations_partner.py
+++ b/addons/event/wizard/event_registrations_partner.py
@@ -23,10 +23,19 @@ from tools.translate import _
class event_partners_list(osv.osv_memory):
""" Event Partners """
+
_name = "event.partners.list"
_description = "List Event Partners"
def list_partners(self, cr, uid, ids, context={}):
+ """
+ Open Event Partner
+ @param cr: the current row, from the database cursor,
+ @param uid: the current user’s ID for security checks,
+ @param ids: List of Event partners list's IDs
+ @param context: A standard dictionary for contextual values
+ @return: Dictionary value which open Partner form.
+ """
obj_reg = self.pool.get('event.registration')
mod_obj = self.pool.get('ir.model.data')
list_partner = []
diff --git a/addons/event/wizard/event_registrations_partner.xml b/addons/event/wizard/event_registrations_partner.xml
index c700bde11f9..bc982757435 100644
--- a/addons/event/wizard/event_registrations_partner.xml
+++ b/addons/event/wizard/event_registrations_partner.xml
@@ -2,30 +2,33 @@
-
+ Event Partnersevent.partners.listform
-
-
-
-
+
+
+
+
+
+
+
-
+
-
+ List Register Partnersir.actions.act_windowevent.partners.listformform
- {'record_id' : active_id}
+ {'record_id' : active_id}new
-
+
-
+ Event Partners
@@ -36,4 +39,4 @@
-
\ No newline at end of file
+
From ccd09bcef30411410f4de3d500a2ae0987d86cfc Mon Sep 17 00:00:00 2001
From: "atp (OpenERP)" <>
Date: Wed, 9 Jun 2010 20:30:54 +0530
Subject: [PATCH 6/9] [IMP] membership: improvment
bzr revid: hmo@tinyerp.com-20100609150054-8wqicowhoczpp5d0
---
addons/membership/__init__.py | 1 +
addons/membership/__openerp__.py | 2 +
addons/membership/membership.py | 245 +++---------------
addons/membership/membership_view.xml | 227 ++--------------
.../wizard/membership_unpaid_invoice.py | 4 +-
5 files changed, 62 insertions(+), 417 deletions(-)
diff --git a/addons/membership/__init__.py b/addons/membership/__init__.py
index 4ae17c80e71..7e377bcdace 100644
--- a/addons/membership/__init__.py
+++ b/addons/membership/__init__.py
@@ -21,5 +21,6 @@
import membership
import wizard
+import report
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/membership/__openerp__.py b/addons/membership/__openerp__.py
index 49297bc010d..1de648ff8e8 100644
--- a/addons/membership/__openerp__.py
+++ b/addons/membership/__openerp__.py
@@ -43,10 +43,12 @@ invoice and send propositions for membership renewal.
'security/ir.model.access.csv',
'wizard/membership_invoice_view.xml',
'membership_view.xml',
+ 'report/report_membership_view.xml',
'wizard/membership_unpaid_invoice_view.xml',
'process/membership_process.xml'
],
'demo_xml': ['membership_demo.xml'],
+ 'test': ['test/test_membership.yml'],
'installable': True,
'active': False,
'certificate': '0042907796381',
diff --git a/addons/membership/membership.py b/addons/membership/membership.py
index 23f9cd19275..af70c174519 100644
--- a/addons/membership/membership.py
+++ b/addons/membership/membership.py
@@ -221,6 +221,7 @@ class Partner(osv.osv):
_inherit = 'res.partner'
def _get_partner_id(self, cr, uid, ids, context=None):
+
data_inv = self.pool.get('membership.membership_line').browse(cr, uid, ids, context)
list_partner = []
for data in data_inv:
@@ -298,55 +299,47 @@ class Partner(osv.osv):
res_state = self._membership_state(cr, uid, [partner_data.associate_member.id], name, args, context)
res[id] = res_state[partner_data.associate_member.id]
return res
-
- def _membership_start(self, cr, uid, ids, name, args, context=None):
- '''Return the start date of membership'''
+
+ def _membership_date(self, cr, uid, ids, name, args, context=None):
+
+ '''Return date of membership'''
+
+ name = name[0]
res = {}
member_line_obj = self.pool.get('membership.membership_line')
+
for partner in self.browse(cr, uid, ids):
+
if partner.associate_member:
- partner_id = partner.associate_member.id
+ partner_id = partner.associate_member.id
else:
- partner_id = partner.id
- line_id = member_line_obj.search(cr, uid, [('partner', '=', partner_id)],
- limit=1, order='date_from')
- if line_id:
- res[partner.id] = member_line_obj.read(cr, uid, line_id[0],
- ['date_from'])['date_from']
- else:
- res[partner.id] = False
- return res
-
- def _membership_stop(self, cr, uid, ids, name, args, context=None):
- '''Return the stop date of membership'''
- res = {}
- member_line_obj = self.pool.get('membership.membership_line')
- for partner in self.browse(cr, uid, ids):
- cr.execute('select membership_state from res_partner where id=%s', (partner.id,))
- data_state = cr.fetchall()
- if partner.associate_member:
- partner_id = partner.associate_member.id
- else:
- partner_id = partner.id
- line_id = member_line_obj.search(cr, uid, [('partner', '=', partner_id)],
- limit=1, order='date_to desc')
- if line_id:
- res[partner.id] = member_line_obj.read(cr, uid, line_id[0],
- ['date_to'])['date_to']
- else:
- res[partner.id] = False
- return res
-
- def _membership_cancel(self, cr, uid, ids, name, args, context=None):
- '''Return the cancel date of membership'''
- res = {}
- member_line_obj = self.pool.get('membership.membership_line')
- for partner in self.browse(cr, uid, ids, context=context):
- res[partner.id] = False
- if partner.membership_state == 'canceled':
- line_id = member_line_obj.search(cr, uid, [('partner', '=', partner.id)],limit=1, order='date_cancel')
+ partner_id = partner.id
+
+ res[partner.id]={
+ 'membership_start': False,
+ 'membership_stop': False,
+ 'membership_cancel': False
+ }
+
+ if name == 'membership_start':
+ line_id = member_line_obj.search(cr, uid, [('partner', '=', partner_id)],
+ limit=1, order='date_from')
if line_id:
- res[partner.id] = member_line_obj.read(cr, uid, line_id[0],['date_cancel'])['date_cancel']
+ res[partner.id]['membership_start'] = member_line_obj.read(cr, uid, line_id[0],
+ ['date_from'])['date_from']
+
+ if name == 'membership_stop':
+ line_id1 = member_line_obj.search(cr, uid, [('partner', '=', partner_id)],
+ limit=1, order='date_to desc')
+ if line_id1:
+ res[partner.id]['membership_stop'] = member_line_obj.read(cr, uid, line_id1[0],
+ ['date_to'])['date_to']
+ if name == 'membership_cancel':
+ if partner.membership_state == 'canceled':
+ line_id2 = member_line_obj.search(cr, uid, [('partner', '=', partner.id)],limit=1, order='date_cancel')
+ if line_id2:
+ res[partner.id]['membership_cancel'] = member_line_obj.read(cr, uid, line_id2[0],['date_cancel'])['date_cancel']
+
return res
def _get_partners(self, cr, uid, ids, context={}):
@@ -376,17 +369,17 @@ class Partner(osv.osv):
}
),
'membership_start': fields.function(
- _membership_start, method=True,
+ _membership_date, method=True, multi='membeship_start',
string = 'Start membership date', type = 'date',
store = {
'account.invoice':(_get_invoice_partner,['state'], 10),
- 'membership.membership_line':(_get_partner_id,['state'], 10),
+ 'membership.membership_line':(_get_partner_id,['state'], 10, ),
'res.partner':(lambda self,cr,uid,ids,c={}:ids, ['free_member'], 10)
}
),
'membership_stop': fields.function(
- _membership_stop, method = True,
- string = 'Stop membership date', type = 'date',
+ _membership_date, method = True,
+ string = 'Stop membership date', type = 'date', multi='membership_stop',
store = {
'account.invoice':(_get_invoice_partner,['state'], 10),
'membership.membership_line':(_get_partner_id,['state'], 10),
@@ -395,8 +388,8 @@ class Partner(osv.osv):
),
'membership_cancel': fields.function(
- _membership_cancel, method = True,
- string = 'Cancel membership date', type='date',
+ _membership_date, method = True,
+ string = 'Cancel membership date', type='date', multi='membership_cancel',
store = {
'account.invoice':(_get_invoice_partner,['state'], 11),
'membership.membership_line':(_get_partner_id,['state'], 10),
@@ -490,160 +483,6 @@ class Invoice(osv.osv):
return super(Invoice, self).action_cancel(cr, uid, ids, context)
Invoice()
-
-class ReportPartnerMemberYear(osv.osv):
- '''Membership by Years'''
-
- _name = 'report.partner_member.year'
- _description = __doc__
- _auto = False
- _rec_name = 'year'
- _columns = {
- 'year': fields.char('Year', size='4', readonly=True, select=1),
- 'canceled_number': fields.integer('Canceled', readonly=True),
- 'waiting_number': fields.integer('Waiting', readonly=True),
- 'invoiced_number': fields.integer('Invoiced', readonly=True),
- 'paid_number': fields.integer('Paid', readonly=True),
- 'canceled_amount': fields.float('Canceled', digits=(16, 2), readonly=True),
- 'waiting_amount': fields.float('Waiting', digits=(16, 2), readonly=True),
- 'invoiced_amount': fields.float('Invoiced', digits=(16, 2), readonly=True),
- 'paid_amount': fields.float('Paid', digits=(16, 2), readonly=True),
- 'currency': fields.many2one('res.currency', 'Currency', readonly=True,
- select=2),
- }
-
- def init(self, cr):
- '''Create the view'''
- cr.execute("""
- CREATE OR REPLACE VIEW report_partner_member_year AS (
- SELECT
- MIN(id) AS id,
- COUNT(ncanceled) as canceled_number,
- COUNT(npaid) as paid_number,
- COUNT(ninvoiced) as invoiced_number,
- COUNT(nwaiting) as waiting_number,
- SUM(acanceled) as canceled_amount,
- SUM(apaid) as paid_amount,
- SUM(ainvoiced) as invoiced_amount,
- SUM(awaiting) as waiting_amount,
- year,
- currency
- FROM (SELECT
- CASE WHEN ai.state = 'cancel' THEN ml.id END AS ncanceled,
- CASE WHEN ai.state = 'paid' THEN ml.id END AS npaid,
- CASE WHEN ai.state = 'open' THEN ml.id END AS ninvoiced,
- CASE WHEN (ai.state = 'draft' OR ai.state = 'proforma')
- THEN ml.id END AS nwaiting,
- CASE WHEN ai.state = 'cancel'
- THEN SUM(ail.price_unit * ail.quantity * (1 - ail.discount / 100))
- ELSE 0 END AS acanceled,
- CASE WHEN ai.state = 'paid'
- THEN SUM(ail.price_unit * ail.quantity * (1 - ail.discount / 100))
- ELSE 0 END AS apaid,
- CASE WHEN ai.state = 'open'
- THEN SUM(ail.price_unit * ail.quantity * (1 - ail.discount / 100))
- ELSE 0 END AS ainvoiced,
- CASE WHEN (ai.state = 'draft' OR ai.state = 'proforma')
- THEN SUM(ail.price_unit * ail.quantity * (1 - ail.discount / 100))
- ELSE 0 END AS awaiting,
- TO_CHAR(ml.date_from, 'YYYY') AS year,
- ai.currency_id AS currency,
- MIN(ml.id) AS id
- FROM membership_membership_line ml
- JOIN (account_invoice_line ail
- LEFT JOIN account_invoice ai
- ON (ail.invoice_id = ai.id))
- ON (ml.account_invoice_line = ail.id)
- JOIN res_partner p
- ON (ml.partner = p.id)
- GROUP BY TO_CHAR(ml.date_from, 'YYYY'), ai.state,
- ai.currency_id, ml.id) AS foo
- GROUP BY year, currency)
- """)
-
-ReportPartnerMemberYear()
-
-
-class ReportPartnerMemberYearNew(osv.osv):
- '''New Membership by Years'''
-
- _name = 'report.partner_member.year_new'
- _description = __doc__
- _auto = False
- _rec_name = 'year'
- _columns = {
- 'year': fields.char('Year', size='4', readonly=True, select=1),
- 'canceled_number': fields.integer('Canceled', readonly=True),
- 'waiting_number': fields.integer('Waiting', readonly=True),
- 'invoiced_number': fields.integer('Invoiced', readonly=True),
- 'paid_number': fields.integer('Paid', readonly=True),
- 'canceled_amount': fields.float('Canceled', digits=(16, 2), readonly=True),
- 'waiting_amount': fields.float('Waiting', digits=(16, 2), readonly=True),
- 'invoiced_amount': fields.float('Invoiced', digits=(16, 2), readonly=True),
- 'paid_amount': fields.float('Paid', digits=(16, 2), readonly=True),
- 'currency': fields.many2one('res.currency', 'Currency', readonly=True,
- select=2),
- }
-
- def init(self, cursor):
- '''Create the view'''
- cursor.execute("""
- CREATE OR REPLACE VIEW report_partner_member_year_new AS (
- SELECT
- MIN(id) AS id,
- COUNT(ncanceled) AS canceled_number,
- COUNT(npaid) AS paid_number,
- COUNT(ninvoiced) AS invoiced_number,
- COUNT(nwaiting) AS waiting_number,
- SUM(acanceled) AS canceled_amount,
- SUM(apaid) AS paid_amount,
- SUM(ainvoiced) AS invoiced_amount,
- SUM(awaiting) AS waiting_amount,
- year,
- currency
- FROM (SELECT
- CASE WHEN ai.state = 'cancel' THEN ml2.id END AS ncanceled,
- CASE WHEN ai.state = 'paid' THEN ml2.id END AS npaid,
- CASE WHEN ai.state = 'open' THEN ml2.id END AS ninvoiced,
- CASE WHEN (ai.state = 'draft' OR ai.state = 'proforma')
- THEN ml2.id END AS nwaiting,
- CASE WHEN ai.state = 'cancel'
- THEN SUM(ail.price_unit * ail.quantity * (1 - ail.discount / 100))
- ELSE 0 END AS acanceled,
- CASE WHEN ai.state = 'paid'
- THEN SUM(ail.price_unit * ail.quantity * (1 - ail.discount / 100))
- ELSE 0 END AS apaid,
- CASE WHEN ai.state = 'open'
- THEN SUM(ail.price_unit * ail.quantity * (1 - ail.discount / 100))
- ELSE 0 END AS ainvoiced,
- CASE WHEN (ai.state = 'draft' OR ai.state = 'proforma')
- THEN SUM(ail.price_unit * ail.quantity * (1 - ail.discount / 100))
- ELSE 0 END AS awaiting,
- TO_CHAR(ml2.date_from, 'YYYY') AS year,
- ai.currency_id AS currency,
- MIN(ml2.id) AS id
- FROM (SELECT
- partner AS id,
- MIN(date_from) AS date_from
- FROM membership_membership_line
- GROUP BY partner
- ) AS ml1
- JOIN membership_membership_line ml2
- JOIN (account_invoice_line ail
- LEFT JOIN account_invoice ai
- ON (ail.invoice_id = ai.id))
- ON (ml2.account_invoice_line = ail.id)
- ON (ml1.id = ml2.partner AND ml1.date_from = ml2.date_from)
- JOIN res_partner p
- ON (ml2.partner = p.id)
- GROUP BY TO_CHAR(ml2.date_from, 'YYYY'), ai.state,
- ai.currency_id, ml2.id) AS foo
- GROUP BY year, currency
- )
- """)
-
-ReportPartnerMemberYearNew()
-
class account_invoice_line(osv.osv):
_inherit='account.invoice.line'
diff --git a/addons/membership/membership_view.xml b/addons/membership/membership_view.xml
index 2ba81d2c1ee..3b1009963cb 100644
--- a/addons/membership/membership_view.xml
+++ b/addons/membership/membership_view.xml
@@ -39,7 +39,8 @@
-
+
+
@@ -110,20 +111,28 @@
+
res.partner.selectres.partnersearch
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
Members
@@ -199,7 +208,6 @@
-
@@ -208,211 +216,6 @@
sequence="2"
id="menu_reporting"/>
-
-
-
-
- report.partner_member.year.tree
- report.partner_member.year
- tree
-
-
-
-
-
-
-
-
-
-
-
-
-
- report.partner_member.year.tree
- report.partner_member.year
- tree
-
-
-
-
-
-
-
-
-
-
-
-
-
- report.partner_member.year.graph1
- report.partner_member.year
- graph
-
-
-
-
-
-
-
-
-
-
-
-
- report.partner_member.year.graph2
- report.partner_member.year
- graph
-
-
-
-
-
-
-
-
-
-
-
-
- report.partner_member.year
- form
-
-
-
-
- tree
-
-
-
-
-
-
-
- tree
-
-
-
-
-
-
- graph
-
-
-
-
-
-
- graph
-
-
-
-
-
-
-
-
-
-
-
-
- report.partner_member.year_new.tree
- report.partner_member.year_new
- tree
-
-
-
-
-
-
-
-
-
-
-
-
- report.partner_member.year_new.tree
- report.partner_member.year_new
- tree
-
-
-
-
-
-
-
-
-
-
-
-
-
- report.partner_member.year_new.graph1
- report.partner_member.year_new
- graph
-
-
-
-
-
-
-
-
-
-
-
-
- report.partner_member.year_new.graph2
- report.partner_member.year_new
- graph
-
-
-
-
-
-
-
-
-
-
-
-
- report.partner_member.year_new
- form
-
-
-
-
- tree
-
-
-
-
-
-
- tree
-
-
-
-
-
-
- graph
-
-
-
-
-
-
- graph
-
-
-
-
-
diff --git a/addons/membership/wizard/membership_unpaid_invoice.py b/addons/membership/wizard/membership_unpaid_invoice.py
index 1b9a6ac3464..f403e78c81d 100644
--- a/addons/membership/wizard/membership_unpaid_invoice.py
+++ b/addons/membership/wizard/membership_unpaid_invoice.py
@@ -29,7 +29,7 @@ class member_unpaid_invoice(osv.osv_memory):
'product': fields.many2one('product.product','Membership product', size=64,required=True, help='Select Membership product'),
}
- def _invoice_membership(self, cr, uid, ids, context):
+ def invoice_membership(self, cr, uid, ids, context):
model_obj = self.pool.get('ir.model.data')
partners = []
result = model_obj._get_id(cr, uid, 'base', 'view_res_partner_filter')
@@ -56,4 +56,4 @@ class member_unpaid_invoice(osv.osv_memory):
member_unpaid_invoice()
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
From ff1681b22f7b237cb51050aa1b034d55edc4449c Mon Sep 17 00:00:00 2001
From: "atp (OpenERP)" <>
Date: Wed, 9 Jun 2010 20:40:36 +0530
Subject: [PATCH 7/9] [IMP] membership: report, yml
bzr revid: hmo@tinyerp.com-20100609151036-9ynxz71j28y71yb9
---
addons/membership/report/__init__.py | 22 ++
addons/membership/report/report_membership.py | 175 +++++++++++++++
.../report/report_membership_view.xml | 211 ++++++++++++++++++
addons/membership/test/test_membership.yml | 115 ++++++++++
4 files changed, 523 insertions(+)
create mode 100644 addons/membership/report/__init__.py
create mode 100644 addons/membership/report/report_membership.py
create mode 100644 addons/membership/report/report_membership_view.xml
create mode 100644 addons/membership/test/test_membership.yml
diff --git a/addons/membership/report/__init__.py b/addons/membership/report/__init__.py
new file mode 100644
index 00000000000..dd247c52f3a
--- /dev/null
+++ b/addons/membership/report/__init__.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+import report_membership
diff --git a/addons/membership/report/report_membership.py b/addons/membership/report/report_membership.py
new file mode 100644
index 00000000000..50273fbace4
--- /dev/null
+++ b/addons/membership/report/report_membership.py
@@ -0,0 +1,175 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+from osv import fields, osv
+import tools
+
+
+class ReportPartnerMemberYear(osv.osv):
+ '''Membership by Years'''
+
+ _name = 'report.partner_member.year'
+ _description = __doc__
+ _auto = False
+ _rec_name = 'year'
+ _columns = {
+ 'year': fields.char('Year', size='4', readonly=True, select=1),
+ 'canceled_number': fields.integer('Canceled', readonly=True),
+ 'waiting_number': fields.integer('Waiting', readonly=True),
+ 'invoiced_number': fields.integer('Invoiced', readonly=True),
+ 'paid_number': fields.integer('Paid', readonly=True),
+ 'canceled_amount': fields.float('Canceled', digits=(16, 2), readonly=True),
+ 'waiting_amount': fields.float('Waiting', digits=(16, 2), readonly=True),
+ 'invoiced_amount': fields.float('Invoiced', digits=(16, 2), readonly=True),
+ 'paid_amount': fields.float('Paid', digits=(16, 2), readonly=True),
+ 'currency': fields.many2one('res.currency', 'Currency', readonly=True,
+ select=2),
+ }
+
+ def init(self, cr):
+ '''Create the view'''
+ cr.execute("""
+ CREATE OR REPLACE VIEW report_partner_member_year AS (
+ SELECT
+ MIN(id) AS id,
+ COUNT(ncanceled) as canceled_number,
+ COUNT(npaid) as paid_number,
+ COUNT(ninvoiced) as invoiced_number,
+ COUNT(nwaiting) as waiting_number,
+ SUM(acanceled) as canceled_amount,
+ SUM(apaid) as paid_amount,
+ SUM(ainvoiced) as invoiced_amount,
+ SUM(awaiting) as waiting_amount,
+ year,
+ currency
+ FROM (SELECT
+ CASE WHEN ai.state = 'cancel' THEN ml.id END AS ncanceled,
+ CASE WHEN ai.state = 'paid' THEN ml.id END AS npaid,
+ CASE WHEN ai.state = 'open' THEN ml.id END AS ninvoiced,
+ CASE WHEN (ai.state = 'draft' OR ai.state = 'proforma')
+ THEN ml.id END AS nwaiting,
+ CASE WHEN ai.state = 'cancel'
+ THEN SUM(ail.price_unit * ail.quantity * (1 - ail.discount / 100))
+ ELSE 0 END AS acanceled,
+ CASE WHEN ai.state = 'paid'
+ THEN SUM(ail.price_unit * ail.quantity * (1 - ail.discount / 100))
+ ELSE 0 END AS apaid,
+ CASE WHEN ai.state = 'open'
+ THEN SUM(ail.price_unit * ail.quantity * (1 - ail.discount / 100))
+ ELSE 0 END AS ainvoiced,
+ CASE WHEN (ai.state = 'draft' OR ai.state = 'proforma')
+ THEN SUM(ail.price_unit * ail.quantity * (1 - ail.discount / 100))
+ ELSE 0 END AS awaiting,
+ TO_CHAR(ml.date_from, 'YYYY') AS year,
+ ai.currency_id AS currency,
+ MIN(ml.id) AS id
+ FROM membership_membership_line ml
+ JOIN (account_invoice_line ail
+ LEFT JOIN account_invoice ai
+ ON (ail.invoice_id = ai.id))
+ ON (ml.account_invoice_line = ail.id)
+ JOIN res_partner p
+ ON (ml.partner = p.id)
+ GROUP BY TO_CHAR(ml.date_from, 'YYYY'), ai.state,
+ ai.currency_id, ml.id) AS foo
+ GROUP BY year, currency)
+ """)
+ReportPartnerMemberYear()
+
+class ReportPartnerMemberYearNew(osv.osv):
+ '''New Membership by Years'''
+
+ _name = 'report.partner_member.year_new'
+ _description = __doc__
+ _auto = False
+ _rec_name = 'year'
+ _columns = {
+ 'year': fields.char('Year', size='4', readonly=True, select=1),
+ 'canceled_number': fields.integer('Canceled', readonly=True),
+ 'waiting_number': fields.integer('Waiting', readonly=True),
+ 'invoiced_number': fields.integer('Invoiced', readonly=True),
+ 'paid_number': fields.integer('Paid', readonly=True),
+ 'canceled_amount': fields.float('Canceled', digits=(16, 2), readonly=True),
+ 'waiting_amount': fields.float('Waiting', digits=(16, 2), readonly=True),
+ 'invoiced_amount': fields.float('Invoiced', digits=(16, 2), readonly=True),
+ 'paid_amount': fields.float('Paid', digits=(16, 2), readonly=True),
+ 'currency': fields.many2one('res.currency', 'Currency', readonly=True,
+ select=2),
+ }
+
+ def init(self, cursor):
+ '''Create the view'''
+ cursor.execute("""
+ CREATE OR REPLACE VIEW report_partner_member_year_new AS (
+ SELECT
+ MIN(id) AS id,
+ COUNT(ncanceled) AS canceled_number,
+ COUNT(npaid) AS paid_number,
+ COUNT(ninvoiced) AS invoiced_number,
+ COUNT(nwaiting) AS waiting_number,
+ SUM(acanceled) AS canceled_amount,
+ SUM(apaid) AS paid_amount,
+ SUM(ainvoiced) AS invoiced_amount,
+ SUM(awaiting) AS waiting_amount,
+ year,
+ currency
+ FROM (SELECT
+ CASE WHEN ai.state = 'cancel' THEN ml2.id END AS ncanceled,
+ CASE WHEN ai.state = 'paid' THEN ml2.id END AS npaid,
+ CASE WHEN ai.state = 'open' THEN ml2.id END AS ninvoiced,
+ CASE WHEN (ai.state = 'draft' OR ai.state = 'proforma')
+ THEN ml2.id END AS nwaiting,
+ CASE WHEN ai.state = 'cancel'
+ THEN SUM(ail.price_unit * ail.quantity * (1 - ail.discount / 100))
+ ELSE 0 END AS acanceled,
+ CASE WHEN ai.state = 'paid'
+ THEN SUM(ail.price_unit * ail.quantity * (1 - ail.discount / 100))
+ ELSE 0 END AS apaid,
+ CASE WHEN ai.state = 'open'
+ THEN SUM(ail.price_unit * ail.quantity * (1 - ail.discount / 100))
+ ELSE 0 END AS ainvoiced,
+ CASE WHEN (ai.state = 'draft' OR ai.state = 'proforma')
+ THEN SUM(ail.price_unit * ail.quantity * (1 - ail.discount / 100))
+ ELSE 0 END AS awaiting,
+ TO_CHAR(ml2.date_from, 'YYYY') AS year,
+ ai.currency_id AS currency,
+ MIN(ml2.id) AS id
+ FROM (SELECT
+ partner AS id,
+ MIN(date_from) AS date_from
+ FROM membership_membership_line
+ GROUP BY partner
+ ) AS ml1
+ JOIN membership_membership_line ml2
+ JOIN (account_invoice_line ail
+ LEFT JOIN account_invoice ai
+ ON (ail.invoice_id = ai.id))
+ ON (ml2.account_invoice_line = ail.id)
+ ON (ml1.id = ml2.partner AND ml1.date_from = ml2.date_from)
+ JOIN res_partner p
+ ON (ml2.partner = p.id)
+ GROUP BY TO_CHAR(ml2.date_from, 'YYYY'), ai.state,
+ ai.currency_id, ml2.id) AS foo
+ GROUP BY year, currency
+ )
+ """)
+
+ReportPartnerMemberYearNew()
\ No newline at end of file
diff --git a/addons/membership/report/report_membership_view.xml b/addons/membership/report/report_membership_view.xml
new file mode 100644
index 00000000000..6f15636847b
--- /dev/null
+++ b/addons/membership/report/report_membership_view.xml
@@ -0,0 +1,211 @@
+
+
+
+
+
+
+
+ report.partner_member.year.tree
+ report.partner_member.year
+ tree
+
+
+
+
+
+
+
+
+
+
+
+
+
+ report.partner_member.year.tree
+ report.partner_member.year
+ tree
+
+
+
+
+
+
+
+
+
+
+
+
+
+ report.partner_member.year.graph1
+ report.partner_member.year
+ graph
+
+
+
+
+
+
+
+
+
+
+
+
+ report.partner_member.year.graph2
+ report.partner_member.year
+ graph
+
+
+
+
+
+
+
+
+
+
+
+
+ report.partner_member.year
+ form
+
+
+
+
+ tree
+
+
+
+
+
+
+
+ tree
+
+
+
+
+
+
+ graph
+
+
+
+
+
+
+ graph
+
+
+
+
+
+
+
+
+
+
+
+
+ report.partner_member.year_new.tree
+ report.partner_member.year_new
+ tree
+
+
+
+
+
+
+
+
+
+
+
+
+ report.partner_member.year_new.tree
+ report.partner_member.year_new
+ tree
+
+
+
+
+
+
+
+
+
+
+
+
+
+ report.partner_member.year_new.graph1
+ report.partner_member.year_new
+ graph
+
+
+
+
+
+
+
+
+
+
+
+
+ report.partner_member.year_new.graph2
+ report.partner_member.year_new
+ graph
+
+
+
+
+
+
+
+
+
+
+
+
+ report.partner_member.year_new
+ form
+
+
+
+
+ tree
+
+
+
+
+
+
+ tree
+
+
+
+
+
+
+ graph
+
+
+
+
+
+
+ graph
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/addons/membership/test/test_membership.yml b/addons/membership/test/test_membership.yml
new file mode 100644
index 00000000000..5a67ea7f476
--- /dev/null
+++ b/addons/membership/test/test_membership.yml
@@ -0,0 +1,115 @@
+- |
+ In Order to test the Membership in OpenERP, which allows us to manage all operations for managing memberships.
+- |
+ We have to create "Membership Products" to make it available for partner or customer to make membership with it.
+ select product type to "service" type and membership field is ticked to visible this product while creating membership for the partner.
+-
+ !record {model: product.product, id: product_product_membershipproduct0}:
+ categ_id: product.cat1
+ membership: 1
+ membership_date_from: '2009-06-01'
+ membership_date_to: '2010-06-01'
+ name: Membership Products
+ type: service
+ list_price: 80.00
+
+- |
+ I create new member "Mark Johnson" and I provide an address to this
+ new customer, as well as an email "info@mycustomer.com".
+-
+ !record {model: res.partner, id: res_partner_markjohnson0}:
+ address:
+ - city: paris
+ country_id: base.fr
+ name: Arthur Grosbonnet
+ street: 1 rue Rockfeller
+ title: M.
+ type: default
+ zip: '75016'
+ credit_limit: 0.0
+ membership_amount: 0.0
+ name: Mark Johnson
+ property_account_payable: account.a_pay
+ property_account_receivable: account.a_recv
+
+- |
+ I check that "Current membership state" is set to "Non Member".
+-
+ !assert {model: res.partner, id: res_partner_markjohnson0}:
+ - membership_state == 'none'
+- |
+ I can make it a Free member by selecting the "Free member" check box.
+-
+ !record {model: res.partner, id: membership.res_partner_markjohnson0}:
+ free_member: 1
+- |
+ Now, I create Membership Invoices using wizard available on partner and Select Membership Product.
+-
+ !record {model: membership.invoice, id: membership_invoice_0}:
+ product_id: membership.product_product_membershipproduct0
+- |
+ I check that address is defined or not for this Member.
+-
+ !python {model: membership.invoice}: |
+ partner_ids = [ref('res_partner_markjohnson0')]
+ addre_obj = self.pool.get('res.partner.address')
+ ids = addre_obj.search(cr, uid, [('partner_id', '=', partner_ids)])
+
+ addre_id = addre_obj.browse(cr, uid, ids)[0]
+ assert addre_id.partner_id
+ assert addre_id.id
+ assert addre_id.type
+
+- |
+ I click on "Confirm" button of this wizard.
+-
+ !python {model: membership.invoice}: |
+ self.membership_invoice(cr, uid, [ref("membership_invoice_0")], {"active_ids": [ref("membership.res_partner_markjohnson0")]})
+
+- |
+ I check that Invoice is created for this members.
+-
+ !python {model: res.partner}: |
+ invoice_obj = self.pool.get('account.invoice')
+ partner_obj = self.pool.get('res.partner')
+ product_obj = self.pool.get('product.product')
+ invoice_line_obj = self.pool.get(('account.invoice.line'))
+
+ partner_id = self.browse(cr, uid, [ref('res_partner_markjohnson0')])[0]
+ ids = invoice_obj.search(cr, uid, [('partner_id', '=', partner_id.id), ('account_id', '=', partner_id.property_account_receivable.id)])
+ invoice_id = invoice_obj.browse(cr, uid, ids)[0]
+
+ product = product_obj.browse(cr, uid, [ref('product_product_membershipproduct0')], context=context)[0]
+ line_ids = invoice_line_obj.search(cr, uid, [('product_id', '=', product.id), ('invoice_id', '=', invoice_id.id)])
+ line_id = invoice_line_obj.browse(cr, uid, line_ids)[0]
+
+ assert line_id.product_id.id == product.id
+ assert invoice_id.partner_id.id == partner_id.id
+
+- |
+ I check that the "Current membership state" will remain same untill opening the invoice.
+-
+ !assert {model: res.partner, id: res_partner_markjohnson0}:
+ - membership_state == 'free'
+
+- |
+ "Current membership state" of any member depends on the state of invoice.
+ So, I check that invoice is in draft state then the "membership state" of a member is "Waiting member".
+-
+ !python {model: membership.membership_line}: |
+ partner_id = self.pool.get('res.partner').browse(cr, uid, [ref('res_partner_markjohnson0')])[0]
+ ids = self.search(cr, uid, [('partner', '=', partner_id.id)])
+ current_id = self.browse(cr, uid, ids)[0]
+
+ partner_obj = self.pool.get('res.partner')
+ inv_obj = self.pool.get('account.invoice')
+
+ ids = inv_obj.search(cr, uid, [('partner_id', '=', partner_id.id), ('account_id', '=', partner_id.property_account_receivable.id)])
+ inv_id = inv_obj.browse(cr, uid, ids)[0]
+ if inv_id.state == 'draft':
+ assert current_id == 'waiting'
+- |
+ When the invoice is in open state it become Invoiced Member, When the invoice is in paid state the same "Current membership state" changed to Paid Member.
+ Now, If we cancel the invoice "Current membership state" changed to Cancel Member.
+
+
\ No newline at end of file
From 89000304744c2d1fa7b0410029d55331aa087c30 Mon Sep 17 00:00:00 2001
From: "Harry (OpenERP)"
Date: Wed, 9 Jun 2010 21:00:30 +0530
Subject: [PATCH 8/9] [IMP]sale_crm: convert make sale order winzard into
osv_memory
bzr revid: hmo@tinyerp.com-20100609153030-mhp8hzp9f0ennmuv
---
addons/sale_crm/__openerp__.py | 2 +-
addons/sale_crm/sale_crm_view.xml | 2 +-
addons/sale_crm/sale_crm_wizard.xml | 14 --
addons/sale_crm/wizard/__init__.py | 2 +-
addons/sale_crm/wizard/crm_make_sale.py | 180 ++++++++++++++++++
addons/sale_crm/wizard/crm_make_sale_view.xml | 43 +++++
addons/sale_crm/wizard/makesale.py | 179 -----------------
7 files changed, 226 insertions(+), 196 deletions(-)
delete mode 100644 addons/sale_crm/sale_crm_wizard.xml
create mode 100644 addons/sale_crm/wizard/crm_make_sale.py
create mode 100644 addons/sale_crm/wizard/crm_make_sale_view.xml
delete mode 100644 addons/sale_crm/wizard/makesale.py
diff --git a/addons/sale_crm/__openerp__.py b/addons/sale_crm/__openerp__.py
index 9464db91b6f..49f867ee79d 100644
--- a/addons/sale_crm/__openerp__.py
+++ b/addons/sale_crm/__openerp__.py
@@ -38,7 +38,7 @@ crm modules.
'website': 'http://www.openerp.com',
'depends': ['sale', 'crm'],
'init_xml': [],
- 'update_xml': ['sale_crm_wizard.xml',
+ 'update_xml': ['wizard/crm_make_sale_view.xml',
'sale_crm_view.xml',
'process/sale_crm_process.xml',
'security/sale_crm_security.xml',
diff --git a/addons/sale_crm/sale_crm_view.xml b/addons/sale_crm/sale_crm_view.xml
index bf5f1aaac52..ad7b1e2485a 100644
--- a/addons/sale_crm/sale_crm_view.xml
+++ b/addons/sale_crm/sale_crm_view.xml
@@ -9,7 +9,7 @@
-
+
diff --git a/addons/sale_crm/sale_crm_wizard.xml b/addons/sale_crm/sale_crm_wizard.xml
deleted file mode 100644
index 74dcf06e901..00000000000
--- a/addons/sale_crm/sale_crm_wizard.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/addons/sale_crm/wizard/__init__.py b/addons/sale_crm/wizard/__init__.py
index 87048a13fc4..04f40c92207 100644
--- a/addons/sale_crm/wizard/__init__.py
+++ b/addons/sale_crm/wizard/__init__.py
@@ -19,7 +19,7 @@
#
##############################################################################
-import makesale
+import crm_make_sale
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/sale_crm/wizard/crm_make_sale.py b/addons/sale_crm/wizard/crm_make_sale.py
new file mode 100644
index 00000000000..f53ce3d24d5
--- /dev/null
+++ b/addons/sale_crm/wizard/crm_make_sale.py
@@ -0,0 +1,180 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+from osv import fields, osv
+from tools.translate import _
+from mx.DateTime import now
+
+
+class crm_make_sale(osv.osv_memory):
+ """ Make sale order for crm """
+
+ _name = "crm.make.sale"
+ _description = "Make sale"
+
+ def _selectPartner(self, cr, uid, context=None):
+ """
+ This function gets default value for partner_id field.
+ @param self: The object pointer
+ @param cr: the current row, from the database cursor,
+ @param uid: the current user’s ID for security checks,
+ @param context: A standard dictionary for contextual values
+ @return : default value of partner_id field.
+ """
+ if not context:
+ context = {}
+
+ data = context and context.get('active_ids', []) or []
+ case_obj = self.pool.get('crm.lead')
+ case = case_obj.read(cr, uid, data, ['partner_id'])
+ return case[0]['partner_id']
+
+ def makeOrder(self, cr, uid, ids, context=None):
+ """
+ This function create Quotation on given case.
+ @param self: The object pointer
+ @param cr: the current row, from the database cursor,
+ @param uid: the current user’s ID for security checks,
+ @param ids: List of crm make sale' ids
+ @param context: A standard dictionary for contextual values
+ @return : Dictionary value of created sale order.
+ """
+ if not context:
+ context = {}
+
+ mod_obj = self.pool.get('ir.model.data')
+
+
+ result = mod_obj._get_id(cr, uid, 'sale', 'view_sales_order_filter')
+ id = mod_obj.read(cr, uid, result, ['res_id'])
+
+ case_obj = self.pool.get('crm.lead')
+ sale_obj = self.pool.get('sale.order')
+ partner_obj = self.pool.get('res.partner')
+ sale_line_obj = self.pool.get('sale.order.line')
+
+ data = context and context.get('active_ids', []) or []
+
+ for make in self.browse(cr, uid, ids):
+ default_partner_addr = partner_obj.address_get(cr, uid, [make.partner_id.id],
+ ['invoice', 'delivery', 'contact'])
+ default_pricelist = partner_obj.browse(cr, uid, make.partner_id.id,
+ context).property_product_pricelist.id
+ fpos_data = partner_obj.browse(cr, uid, make.partner_id.id, context).property_account_position
+ new_ids = []
+
+ for case in case_obj.browse(cr, uid, data):
+ if case.partner_id and case.partner_id.id:
+ partner_id = case.partner_id.id
+ fpos = case.partner_id.property_account_position and case.partner_id.property_account_position.id or False
+ partner_addr = partner_obj.address_get(cr, uid, [case.partner_id.id],
+ ['invoice', 'delivery', 'contact'])
+ pricelist = partner_obj.browse(cr, uid, case.partner_id.id,
+ context).property_product_pricelist.id
+ else:
+ partner_id = make.partner_id.id
+ fpos = fpos_data and fpos_data.id or False
+ partner_addr = default_partner_addr
+ pricelist = default_pricelist
+
+ if False in partner_addr.values():
+ raise osv.except_osv(_('Data Insufficient!'),_('Customer has no addresses defined!'))
+
+ vals = {
+ 'origin': 'CRM-Opportunity:%s' % str(case.id),
+ 'section_id': case.section_id and case.section_id.id or False,
+ 'picking_policy': make.picking_policy,
+ 'shop_id': make.shop_id.id,
+ 'partner_id': partner_id,
+ 'pricelist_id': pricelist,
+ 'partner_invoice_id': partner_addr['invoice'],
+ 'partner_order_id': partner_addr['contact'],
+ 'partner_shipping_id': partner_addr['delivery'],
+ 'order_policy': 'manual',
+ 'date_order': now(),
+ 'fiscal_position': fpos,
+ }
+
+ if partner_id:
+ partner = partner_obj.browse(cr, uid, partner_id, context=context)
+ vals['user_id'] = partner.user_id and partner.user_id.id or uid
+
+ if make.analytic_account.id:
+ vals['project_id'] = make.analytic_account.id
+ new_id = sale_obj.create(cr, uid, vals)
+ for product_id in make.product_ids:
+ value = sale_line_obj.product_id_change(cr, uid, [], pricelist,
+ product_id.id, qty=1, partner_id=partner_id, fiscal_position=fpos)['value']
+ value['product_id'] = product_id.id
+ value['order_id'] = new_id
+ value['tax_id'] = [(6,0,value['tax_id'])]
+ sale_line_obj.create(cr, uid, value)
+
+ case_obj.write(cr, uid, [case.id], {'ref': 'sale.order,%s' % new_id})
+ new_ids.append(new_id)
+
+ if make.close:
+ case_obj.case_close(cr, uid, data)
+
+ if not new_ids:
+ return {}
+ if len(new_ids)<=1:
+ value = {
+ 'domain': str([('id', 'in', new_ids)]),
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': 'sale.order',
+ 'view_id': False,
+ 'type': 'ir.actions.act_window',
+ 'res_id': new_ids and new_ids[0]
+
+ }
+
+
+ else:
+ value = {
+ 'domain': str([('id', 'in', new_ids)]),
+ 'view_type': 'form',
+ 'view_mode': 'tree,form',
+ 'res_model': 'sale.order',
+ 'view_id': False,
+ 'type': 'ir.actions.act_window',
+ 'res_id':new_ids
+ }
+ return value
+
+ _columns = {
+ 'shop_id': fields.many2one('sale.shop', 'Shop', required = True),
+ 'partner_id': fields.many2one('res.partner', 'Customer', required = True, help = 'Use this partner if there is no partner on the case'),
+ 'picking_policy': fields.selection([('direct','Partial Delivery'),
+ ('one','Complete Delivery')], 'Picking Policy', required = True),
+ 'product_ids': fields.many2many('product.product', 'product_sale_rel',\
+ 'sale_id', 'product_id', 'Products'),
+ 'analytic_account': fields.many2one('account.analytic.account', 'Analytic Account'),
+ 'close': fields.boolean('Close Case', help = 'Check this to close the case after having created the sale order.'),
+ }
+ _defaults = {
+ 'partner_id': _selectPartner,
+ 'close': lambda *a: 1
+ }
+
+crm_make_sale()
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/sale_crm/wizard/crm_make_sale_view.xml b/addons/sale_crm/wizard/crm_make_sale_view.xml
new file mode 100644
index 00000000000..fd41bfde9ff
--- /dev/null
+++ b/addons/sale_crm/wizard/crm_make_sale_view.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+ crm.make.sale.form
+ crm.make.sale
+ form
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Make Quotation
+ ir.actions.act_window
+ crm.make.sale
+ form
+ form
+ new
+
+
+
+
diff --git a/addons/sale_crm/wizard/makesale.py b/addons/sale_crm/wizard/makesale.py
deleted file mode 100644
index e4aacce1044..00000000000
--- a/addons/sale_crm/wizard/makesale.py
+++ /dev/null
@@ -1,179 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL ().
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-#
-##############################################################################
-
-from mx.DateTime import now
-
-import wizard
-import netsvc
-import ir
-import pooler
-from tools.translate import _
-
-sale_form = """
-