[MERGE] forward port of branch 8.0 up to 7d01029

This commit is contained in:
Christophe Simonis
2015-06-30 15:29:03 +02:00
79 changed files with 643 additions and 230 deletions
+1
View File
@@ -10,6 +10,7 @@ recursive-include openerp *.jpg
recursive-include openerp *.js
recursive-include openerp *.less
recursive-include openerp *.md
recursive-include openerp *.mp3
recursive-include openerp *.png
recursive-include openerp *.po
recursive-include openerp *.rml
+7 -3
View File
@@ -1166,13 +1166,15 @@ class account_move(osv.osv):
_order = 'id desc'
def account_assert_balanced(self, cr, uid, context=None):
obj_precision = self.pool.get('decimal.precision')
prec = obj_precision.precision_get(cr, uid, 'Account')
cr.execute("""\
SELECT move_id
FROM account_move_line
WHERE state = 'valid'
GROUP BY move_id
HAVING abs(sum(debit) - sum(credit)) > 0.00001
""")
HAVING abs(sum(debit) - sum(credit)) >= %s
""" % (10 ** (-max(5, prec))))
assert len(cr.fetchall()) == 0, \
"For all Journal Items, the state is valid implies that the sum " \
"of credits equals the sum of debits"
@@ -1533,6 +1535,8 @@ class account_move(osv.osv):
valid_moves = [] #Maintains a list of moves which can be responsible to create analytic entries
obj_analytic_line = self.pool.get('account.analytic.line')
obj_move_line = self.pool.get('account.move.line')
obj_precision = self.pool.get('decimal.precision')
prec = obj_precision.precision_get(cr, uid, 'Account')
for move in self.browse(cr, uid, ids, context):
journal = move.journal_id
amount = 0
@@ -1556,7 +1560,7 @@ class account_move(osv.osv):
if line.account_id.currency_id.id != line.currency_id.id and (line.account_id.currency_id.id != line.account_id.company_id.currency_id.id):
raise UserError(_("""Cannot create move with currency different from ..""") % (line.account_id.code, line.account_id.name))
if abs(amount) < 10 ** -4:
if round(abs(amount), prec) < 10 ** (-max(5, prec)):
# If the move is balanced
# Add to the list of valid moves
# (analytic lines will be created later for valid moves)
+4 -1
View File
@@ -910,7 +910,10 @@ class account_invoice(models.Model):
i[2]['period_id'] = period.id
ctx['invoice'] = inv
move = account_move.with_context(ctx).create(move_vals)
ctx_nolang = ctx.copy()
ctx_nolang.pop('lang', None)
move = account_move.with_context(ctx_nolang).create(move_vals)
# make the invoice point to that move
vals = {
'move_id': move.id,
+2 -2
View File
@@ -225,7 +225,7 @@ class account_move_line(osv.osv):
'journal_id': obj_line.journal_id.analytic_journal_id.id,
'ref': obj_line.ref,
'move_id': obj_line.id,
'user_id': uid,
'user_id': obj_line.invoice.user_id.id or uid,
}
def create_analytic_lines(self, cr, uid, ids, context=None):
@@ -995,7 +995,7 @@ class account_move_line(osv.osv):
if context is None:
context = {}
company_list = []
for line in self.browse(cr, uid, ids, context=context):
for line in lines:
if company_list and not line.company_id.id in company_list:
raise UserError(_('To reconcile the entries company should be the same for all entries.'))
company_list.append(line.company_id.id)
+1 -3
View File
@@ -5,7 +5,6 @@
company_id: base.main_company
name: Accountant
login: acc
password: acc
email: accountuser@yourcompany.com
-
I added groups for Accountant.
@@ -21,7 +20,6 @@
company_id: base.main_company
name: Financial Manager
login: fm
password: fm
email: accountmanager@yourcompany.com
-
I added groups for Financial Manager.
@@ -29,4 +27,4 @@
!record {model: res.users, id: res_users_account_manager}:
groups_id:
- account.group_account_manager
- base.group_partner_manager
- base.group_partner_manager
+2
View File
@@ -119,10 +119,12 @@ class crossovered_budget_lines(osv.osv):
result = 0.0
if context is None:
context = {}
account_obj = self.pool.get('account.account')
for line in self.browse(cr, uid, ids, context=context):
acc_ids = [x.id for x in line.general_budget_id.account_ids]
if not acc_ids:
raise UserError(_("The Budget '%s' has no accounts!") % ustr(line.general_budget_id.name))
acc_ids = account_obj._get_children_and_consol(cr, uid, acc_ids, context=context)
date_to = line.date_to
date_from = line.date_from
if line.analytic_account_id.id:
+1 -1
View File
@@ -227,8 +227,8 @@ class account_voucher(osv.osv):
if not ids: return {}
currency_obj = self.pool.get('res.currency')
res = {}
debit = credit = 0.0
for voucher in self.browse(cr, uid, ids, context=context):
debit = credit = 0.0
sign = voucher.type == 'payment' and -1 or 1
for l in voucher.line_dr_ids:
debit += l.amount
@@ -5,7 +5,6 @@
company_id: base.main_company
name: Voucher Accountant
login: vacc
password: acc
email: accountant@yourcompany.com
-
I added groups to Accountant for account voucher.
@@ -21,7 +20,6 @@
company_id: base.main_company
name: Financial Manager for voucher
login: fmv
password: fmv
email: finmanager@yourcompany.com
-
I added groups to Financial Manager for account voucher.
-2
View File
@@ -6,8 +6,6 @@
<record id="default_template_user" model="res.users">
<field name="name">Template User</field>
<field name="login">portaltemplate</field>
<!-- No password: this template user doesn't need to log in -->
<field name="password"></field>
<field name="active" eval="False"/>
<!-- Avoid auto-including this user in any default group, just like a typical portal member -->
<field name="groups_id" eval="[(6, 0, [ref('base.group_portal')])]"/>
+1 -1
View File
@@ -265,7 +265,7 @@ class res_users(osv.Model):
if not user_ids:
user_ids = self.search(cr, uid, [('email', '=', login)], context=context)
if len(user_ids) != 1:
raise Exception('Reset password: invalid username or email')
raise Exception(_('Reset password: invalid username or email'))
return self.action_reset_password(cr, uid, user_ids, context=context)
def action_reset_password(self, cr, uid, ids, context=None):
@@ -5,7 +5,6 @@
company_id: base.main_company
name: Crm Sales manager
login: csm
password: csm
email: crmmanager@yourcompany.com
-
I added groups for Crm Salesmanager.
@@ -20,7 +19,6 @@
company_id: base.main_company
name: Crm Salesman
login: csu
password: csu
email: crmuser@yourcompany.com
-
I added groups for Crm Salesman.
@@ -4,22 +4,18 @@
!record {model: res.users, id: test_res_user_01}:
name: 'Test user A'
login: 'tua@example.com'
new_password: 'tua'
-
!record {model: res.users, id: test_res_user_02}:
name: 'Test user B'
login: 'tub@example.com'
new_password: 'tub'
-
!record {model: res.users, id: test_res_user_03}:
name: 'Test user C'
login: 'tuc@example.com'
new_password: 'tuc'
-
!record {model: res.users, id: test_res_user_04}:
name: 'Test user D'
login: 'tud@example.com'
new_password: 'tud'
-
Salesman also creates lead so giving access rights of salesman.
-
+3 -4
View File
@@ -113,12 +113,11 @@ class delivery_carrier(osv.osv):
# not using advanced pricing per destination: override grid
grid_id = grid_pool.search(cr, uid, [('carrier_id', '=', record.id)], context=context)
if grid_id and not (record.normal_price or record.free_if_more_than):
if grid_id and not (record.normal_price is not False or record.free_if_more_than):
grid_pool.unlink(cr, uid, grid_id, context=context)
grid_id = None
# Check that float, else 0.0 is False
if not (isinstance(record.normal_price,float) or record.free_if_more_than):
if not (record.normal_price is not False or record.free_if_more_than):
continue
if not grid_id:
@@ -145,7 +144,7 @@ class delivery_carrier(osv.osv):
'list_price': 0.0,
}
grid_line_pool.create(cr, uid, line_data, context=context)
if isinstance(record.normal_price,float):
if record.normal_price is not False:
line_data = {
'grid_id': grid_id and grid_id[0],
'name': _('Default price'),
+4 -1
View File
@@ -67,6 +67,7 @@ class sale_order(osv.Model):
acc_fp_obj = self.pool.get('account.fiscal.position')
self._delivery_unset(cr, uid, ids, context=context)
currency_obj = self.pool.get('res.currency')
line_ids = []
for order in self.browse(cr, uid, ids, context=context):
grid_id = carrier_obj.grid_get(cr, uid, [order.carrier_id.id], order.partner_shipping_id.id)
if not grid_id:
@@ -85,7 +86,7 @@ class sale_order(osv.Model):
price_unit = currency_obj.compute(cr, uid, order.company_id.currency_id.id, order.pricelist_id.currency_id.id,
price_unit, context=dict(context or {}, date=order.date_order))
#create the sale order line
line_obj.create(cr, uid, {
line_id = line_obj.create(cr, uid, {
'order_id': order.id,
'name': grid.carrier_id.name,
'product_uom_qty': 1,
@@ -95,3 +96,5 @@ class sale_order(osv.Model):
'tax_id': [(6, 0, taxes_ids)],
'is_delivery': True
}, context=context)
line_ids.append(line_id)
return line_ids
-2
View File
@@ -5,7 +5,6 @@
company_id: base.main_company
name: Event manager
login: em
password: em
email: eventmanager@yourcompany.com
-
I added groups for Event manager.
@@ -20,7 +19,6 @@
company_id: base.main_company
name: User
login: eu
password: eu
email: eventuser@yourcompany.com
-
I added groups for Event user.
+5 -4
View File
@@ -202,6 +202,8 @@ class google_calendar(osv.AbstractModel):
_name = 'google.%s' % STR_SERVICE
def generate_data(self, cr, uid, event, isCreating=False, context=None):
if not context:
context = {}
if event.allday:
start_date = fields.datetime.context_timestamp(cr, uid, datetime.strptime(event.start, tools.DEFAULT_SERVER_DATETIME_FORMAT), context=context).isoformat('T').split('T')[0]
final_date = fields.datetime.context_timestamp(cr, uid, datetime.strptime(event.start, tools.DEFAULT_SERVER_DATETIME_FORMAT) + timedelta(hours=event.duration) + timedelta(days=isCreating and 1 or 0), context=context).isoformat('T').split('T')[0]
@@ -226,19 +228,18 @@ class google_calendar(osv.AbstractModel):
"method": "email" if alarm.type == "email" else "popup",
"minutes": alarm.duration_minutes
})
data = {
"summary": event.name or '',
"description": event.description or '',
"start": {
type: start_date,
vstype: None,
'timeZone': 'UTC'
'timeZone': context.get('tz', 'UTC'),
},
"end": {
type: final_date,
vstype: None,
'timeZone': 'UTC'
'timeZone': context.get('tz', 'UTC'),
},
"attendees": attendee_list,
"reminders": {
@@ -365,7 +366,7 @@ class google_calendar(osv.AbstractModel):
url = "/calendar/v3/calendars/%s/events/%s?fields=%s&access_token=%s" % ('primary', google_event['id'], 'id,updated', self.get_token(cr, uid, context))
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
data = self.generate_data(cr, uid, oe_event, context)
data = self.generate_data(cr, uid, oe_event, context=context)
data['sequence'] = google_event.get('sequence', 0)
data_json = simplejson.dumps(data)
-3
View File
@@ -5,7 +5,6 @@
company_id: base.main_company
name: HR manager
login: hrm
password: hrm
-
I added groups for HR Manager.
-
@@ -19,7 +18,6 @@
company_id: base.main_company
name: HR Officer
login: hro
password: hro
email: hro@example.com
-
I added groups for HR Officer.
@@ -34,7 +32,6 @@
company_id: base.main_company
name: Employee
login: emp
password: emp
-
I added groups for Employee.
-
@@ -5,7 +5,6 @@
company_id: base.main_company
name: HR Officer
login: ao
password: ao
-
I added groups for HR Attendance Officer.
-
+1 -1
View File
@@ -31,7 +31,7 @@ class hr_grant_badge_wizard(osv.TransientModel):
'employee_id': fields.many2one("hr.employee", string='Employee', required=True),
'user_id': fields.related("employee_id", "user_id",
type="many2one", relation="res.users",
store=True, string='User', required=True)
store=True, string='User')
}
def action_grant_badge(self, cr, uid, ids, context=None):
@@ -5,7 +5,6 @@
company_id: base.main_company
name: HR Recruitment Officer
login: hrro
password: hrro
email: hrofcr@yourcompany.com
-
I added groups for HR Recruitment Officer.
@@ -5,7 +5,6 @@
company_id: base.main_company
name: HR timesheet manager
login: hrtm
password: hrtm
-
I added groups for HR timesheet Manager.
-
@@ -19,7 +18,6 @@
company_id: base.main_company
name: HR timesheet Officer
login: hrto
password: hrto
-
I added groups for HR timesheet Officer.
-
@@ -33,7 +31,6 @@
company_id: base.main_company
name: Timesheet Employee
login: empt
password: empt
-
I added groups for Timesheet Employee.
-
@@ -108,7 +108,7 @@
</page>
<page string="Details">
<field context="{'employee_id': employee_id, 'user_id':user_id, 'timesheet_date_from': date_from, 'timesheet_date_to': date_to}" name="timesheet_ids" nolabel="1">
<tree editable="top" string="Timesheet Activities">
<tree editable="bottom" string="Timesheet Activities">
<field name="date"/>
<field domain="[('type','in',['normal', 'contract']), ('state', '&lt;&gt;', 'close'),('invoice_on_timesheets','=',1)]" name="account_id" on_change="on_change_account_id(account_id, user_id)" context="{'default_use_timesheets': 1}"/>
<field name="name"/>
+3
View File
@@ -3589,6 +3589,7 @@
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_payable"/>
<field ref="a44" name="parent_id"/>
<field name="financial_report_ids" eval="[(4,ref('account_financial_report_fournisseurs4'))]"/>
</record>
<record id="a446" model="account.account.template">
<field name="name">Acomptes reçus</field>
@@ -3596,6 +3597,7 @@
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_payable"/>
<field ref="a44" name="parent_id"/>
<field name="financial_report_ids" eval="[(4,ref('account_financial_report_fournisseurs4'))]"/>
</record>
<record id="a448" model="account.account.template">
<field name="name">Compensations fournisseurs</field>
@@ -3603,6 +3605,7 @@
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_payable"/>
<field ref="a44" name="parent_id"/>
<field name="financial_report_ids" eval="[(4,ref('account_financial_report_fournisseurs4'))]"/>
</record>
<record id="a45" model="account.account.template">
<field name="name">DETTES FISCALES, SALARIALES ET SOCIALES</field>
+264 -39
View File
@@ -12,17 +12,17 @@
<field name="parent_id" ref="vat_code_balance_net"/>
</record>
<record model="account.tax.code.template" id="vat_code_due_tva80">
<field name="name">TVA due a 8.0% (TN)</field>
<field name="name">TVA due a 8.0%</field>
<field name="code">301b</field>
<field name="parent_id" ref="vat_code_due_tva"/>
</record>
<record model="account.tax.code.template" id="vat_code_due_tva25">
<field name="name">TVA due a 2.5% (TR)</field>
<field name="name">TVA due a 2.5%</field>
<field name="code">311b</field>
<field name="parent_id" ref="vat_code_due_tva"/>
</record>
<record model="account.tax.code.template" id="vat_code_due_tva38">
<field name="name">TVA due a 3.8% (TS)</field>
<field name="name">TVA due a 3.8%</field>
<field name="code">341b</field>
<field name="parent_id" ref="vat_code_due_tva"/>
</record>
@@ -57,22 +57,22 @@
<field name="parent_id" ref="vat_code_base_ca_total"/>
</record>
<record model="account.tax.code.template" id="vat_code_due_80">
<field name="name">Chiffre d'affaires imposable a 8.0% (TN)</field>
<field name="name">Chiffre d'affaires imposable a 8.0%</field>
<field name="code">301a</field>
<field name="parent_id" ref="vat_code_base_due"/>
</record>
<record model="account.tax.code.template" id="vat_code_due_25">
<field name="name">Chiffre d'affaires imposable a 2.5% (TR)</field>
<field name="name">Chiffre d'affaires imposable a 2.5%</field>
<field name="code">311a</field>
<field name="parent_id" ref="vat_code_base_due"/>
</record>
<record model="account.tax.code.template" id="vat_code_due_38">
<field name="name">Chiffre d'affaires imposable a 3.8% (TS)</field>
<field name="name">Chiffre d'affaires imposable a 3.8%</field>
<field name="code">341a</field>
<field name="parent_id" ref="vat_code_base_due"/>
</record>
<record model="account.tax.code.template" id="vat_code_due_0">
<field name="name">Chiffre d'affaires imposable a 0% (export)</field>
<field name="name">Exportations</field>
<field name="code">200-220</field>
<field name="parent_id" ref="vat_code_base_ca_total"/>
</record>
@@ -82,52 +82,57 @@
<field name="parent_id" ref="vat_code_base_ca_total"/>
</record>
<record model="account.tax.code.template" id="vat_code_receivable_net">
<field name="name">Acquisition - total</field>
<field name="name">Acquisitions - total</field>
<field name="code"/>
<field name="parent_id" ref="vat_code_base_net"/>
</record>
<record model="account.tax.code.template" id="vat_code_receivable_base">
<field name="name">Acquisition de biens et services</field>
<field name="name">Acquisitions de biens et services</field>
<field name="code"/>
<field name="parent_id" ref="vat_code_receivable_net"/>
</record>
<record model="account.tax.code.template" id="vat_code_receivable_base_0">
<field name="name">Acquisition de biens et services a 0%</field>
<field name="code">Babs0</field>
<field name="parent_id" ref="vat_code_receivable_base"/>
<field name="name">Importations</field>
<field name="code">imp</field>
<field name="parent_id" ref="vat_code_receivable_net"/>
</record>
<record model="account.tax.code.template" id="vat_code_receivable_base_excl">
<field name="name">Acquisitions non soumise à TVA (exclue)</field>
<field name="code">Bexcl</field>
<field name="parent_id" ref="vat_code_receivable_net"/>
</record>
<record model="account.tax.code.template" id="vat_code_receivable_base_80">
<field name="name">Acquisition de biens et services a 8.0% (TN)</field>
<field name="name">Acquisitions de biens et services a 8.0%</field>
<field name="code">Babs8</field>
<field name="parent_id" ref="vat_code_receivable_base"/>
</record>
<record model="account.tax.code.template" id="vat_code_receivable_base_25">
<field name="name">Acquisition de biens et services a 2.5% (TR)</field>
<field name="name">Acquisitions de biens et services a 2.5%</field>
<field name="code">Babs25</field>
<field name="parent_id" ref="vat_code_receivable_base"/>
</record>
<record model="account.tax.code.template" id="vat_code_receivable_base_38">
<field name="name">Acquisition de biens et services a 3.8% (TS)</field>
<field name="name">Acquisitions de biens et services a 3.8%</field>
<field name="code">Babs38</field>
<field name="parent_id" ref="vat_code_receivable_base"/>
</record>
<record model="account.tax.code.template" id="vat_code_receivable_base_invest">
<field name="name">Acquisition de biens d'invest. et autres charges</field>
<field name="name">Acquisitions de biens d'invest. et autres charges</field>
<field name="code"/>
<field name="parent_id" ref="vat_code_receivable_net"/>
</record>
<record model="account.tax.code.template" id="vat_code_receivable_base_invest80">
<field name="name">Acquisition de biens d'invest. et autres charges a 8.0% (TN)</field>
<field name="name">Acquisitions de biens d'invest. et autres charges a 8.0%</field>
<field name="code">Binv8</field>
<field name="parent_id" ref="vat_code_receivable_base_invest"/>
</record>
<record model="account.tax.code.template" id="vat_code_receivable_base_invest25">
<field name="name">Acquisition de biens d'invest. et autres charges a 2.5% (TR)</field>
<field name="name">Acquisitions de biens d'invest. et autres charges a 2.5%</field>
<field name="code">Binv25</field>
<field name="parent_id" ref="vat_code_receivable_base_invest"/>
</record>
<record model="account.tax.code.template" id="vat_code_receivable_base_invest38">
<field name="name">Acquisition de biens d'invest. et autres charges a 3.8% (TS)</field>
<field name="name">Acquisitions de biens d'invest. et autres charges a 3.8%</field>
<field name="code">Binv38</field>
<field name="parent_id" ref="vat_code_receivable_base_invest"/>
</record>
@@ -135,7 +140,7 @@
# TVA - Taxe sur la Valeur Ajoutée
-->
<record model="account.tax.template" id="vat_25">
<field name="name">TVA due a 2.5% (TR)</field>
<field name="name">TVA due a 2.5%</field>
<field name="description">2.5%</field>
<field name="amount" eval="0.025"/>
<field name="type">percent</field>
@@ -152,8 +157,27 @@
<field name="account_paid_id" ref="ch_coa_2200"/>
<field name="type_tax_use">sale</field>
</record>
<record model="account.tax.template" id="vat_25_ttc">
<field name="name">TVA due a 2.5% TTC</field>
<field name="description">2.5% TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="0.025"/>
<field name="type">percent</field>
<field name="base_code_id" ref="vat_code_due_25"/>
<field name="tax_code_id" ref="vat_code_due_tva25"/>
<field name="ref_base_code_id" ref="vat_code_due_25"/>
<field name="ref_tax_code_id" ref="vat_code_due_tva25"/>
<field name="base_sign" eval="1.0"/>
<field name="tax_sign" eval="1.0"/>
<field name="ref_base_sign" eval="-1.0"/>
<field name="ref_tax_sign" eval="-1.0"/>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="account_collected_id" ref="ch_coa_2200"/>
<field name="account_paid_id" ref="ch_coa_2200"/>
<field name="type_tax_use">sale</field>
</record>
<record model="account.tax.template" id="vat_25_purchase">
<field name="name">TVA 2.5% sur achat B&amp;S (TR)</field>
<field name="name">TVA 2.5% sur achats, biens et services</field>
<field name="description">2.5% achat</field>
<field name="amount" eval="0.025"/>
<field name="type">percent</field>
@@ -171,9 +195,30 @@
<field name="type_tax_use">purchase</field>
<field name="account_collected_id" ref="ch_coa_1170"/>
<field name="account_paid_id" ref="ch_coa_1170"/>
</record>
</record>
<record model="account.tax.template" id="vat_25_purchase_ttc">
<field name="name">TVA 2.5% sur achats, biens et services TTC</field>
<field name="description">2.5% achat TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="0.025"/>
<field name="type">percent</field>
<field name="base_code_id" ref="vat_code_receivable_base_25"/>
<field name="tax_code_id" ref="vat_code_payable_bs"/>
<field name="ref_base_code_id" ref="vat_code_receivable_base_25"/>
<field name="ref_tax_code_id" ref="vat_code_payable_bs"/>
<field name="python_compute">result = round((price_unit * 0.025) / 0.05) * 0.05</field>
<field name="python_compute_inv">result = round((price_unit * ( 1 - (1 / 1.025))) /0.05) * 0.05</field>
<field name="base_sign" eval="-1.0"/>
<field name="tax_sign" eval="-1.0"/>
<field name="ref_base_sign" eval="1.0"/>
<field name="ref_tax_sign" eval="1.0"/>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">purchase</field>
<field name="account_collected_id" ref="ch_coa_1170"/>
<field name="account_paid_id" ref="ch_coa_1170"/>
</record>
<record model="account.tax.template" id="vat_25_invest">
<field name="name">TVA 2.5% sur invest. et autres ch. (TR)</field>
<field name="name">TVA 2.5% sur invest. et autres ch.</field>
<field name="description">2.5% invest.</field>
<field name="amount" eval="0.025"/>
<field name="type">percent</field>
@@ -192,9 +237,29 @@
<field name="account_collected_id" ref="ch_coa_1171"/>
<field name="account_paid_id" ref="ch_coa_1171"/>
</record>
<record model="account.tax.template" id="vat_25_invest_ttc">
<field name="name">TVA 2.5% sur invest. et autres ch. TTC</field>
<field name="description">2.5% invest.TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="0.025"/>
<field name="type">percent</field>
<field name="base_code_id" ref="vat_code_receivable_base_invest25"/>
<field name="tax_code_id" ref="vat_code_payable_invest"/>
<field name="ref_base_code_id" ref="vat_code_receivable_base_invest25"/>
<field name="ref_tax_code_id" ref="vat_code_payable_invest"/>
<field name="python_compute">result = round((price_unit * 0.025) / 0.05) * 0.05</field>
<field name="python_compute_inv">result = round((price_unit * ( 1 - (1 / 1.025))) /0.05) * 0.05</field>
<field name="base_sign" eval="-1.0"/>
<field name="tax_sign" eval="-1.0"/>
<field name="ref_base_sign" eval="1.0"/>
<field name="ref_tax_sign" eval="1.0"/>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">purchase</field>
<field name="account_collected_id" ref="ch_coa_1171"/>
<field name="account_paid_id" ref="ch_coa_1171"/>
</record>
<record model="account.tax.template" id="vat_38">
<field name="name">TVA due a 3.8% (TS)</field>
<field name="name">TVA due a 3.8%</field>
<field name="description">3.8%</field>
<field name="amount" eval="0.038"/>
<field name="type">percent</field>
@@ -213,8 +278,29 @@
<field name="account_collected_id" ref="ch_coa_2200"/>
<field name="account_paid_id" ref="ch_coa_2200"/>
</record>
<record model="account.tax.template" id="vat_38_ttc">
<field name="name">TVA due a 3.8% TTC</field>
<field name="description">3.8% TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="0.038"/>
<field name="type">percent</field>
<field name="base_code_id" ref="vat_code_due_38"/>
<field name="tax_code_id" ref="vat_code_due_tva38"/>
<field name="ref_base_code_id" ref="vat_code_due_38"/>
<field name="ref_tax_code_id" ref="vat_code_due_tva38"/>
<field name="python_compute">result = round((price_unit * 0.038) / 0.05) * 0.05</field>
<field name="python_compute_inv">result = round((price_unit * ( 1 - (1 / 1.038))) /0.05) * 0.05</field>
<field name="base_sign" eval="1.0"/>
<field name="tax_sign" eval="1.0"/>
<field name="ref_base_sign" eval="-1.0"/>
<field name="ref_tax_sign" eval="-1.0"/>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">sale</field>
<field name="account_collected_id" ref="ch_coa_2200"/>
<field name="account_paid_id" ref="ch_coa_2200"/>
</record>
<record model="account.tax.template" id="vat_38_purchase">
<field name="name">TVA 3.8% sur achat B&amp;S (TS)</field>
<field name="name">TVA 3.8% sur achats, biens et services</field>
<field name="description">3.8% achat</field>
<field name="amount" eval="0.038"/>
<field name="type">percent</field>
@@ -233,8 +319,29 @@
<field name="account_collected_id" ref="ch_coa_1170"/>
<field name="account_paid_id" ref="ch_coa_1170"/>
</record>
<record model="account.tax.template" id="vat_38_purchase_ttc">
<field name="name">TVA 3.8% sur achats, biens et services TTC</field>
<field name="description">3.8% achat TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="0.038"/>
<field name="type">percent</field>
<field name="base_code_id" ref="vat_code_receivable_base_38"/>
<field name="tax_code_id" ref="vat_code_payable_bs"/>
<field name="ref_base_code_id" ref="vat_code_receivable_base_38"/>
<field name="ref_tax_code_id" ref="vat_code_payable_bs"/>
<field name="python_compute">result = round((price_unit * 0.038) / 0.05) * 0.05</field>
<field name="python_compute_inv">result = round((price_unit * ( 1 - (1 / 1.038))) /0.05) * 0.05</field>
<field name="base_sign" eval="-1.0"/>
<field name="tax_sign" eval="-1.0"/>
<field name="ref_base_sign" eval="1.0"/>
<field name="ref_tax_sign" eval="1.0"/>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">purchase</field>
<field name="account_collected_id" ref="ch_coa_1170"/>
<field name="account_paid_id" ref="ch_coa_1170"/>
</record>
<record model="account.tax.template" id="vat_38_invest">
<field name="name">TVA 3.8% sur invest. et autres ch. (TS)</field>
<field name="name">TVA 3.8% sur invest. et autres ch.</field>
<field name="description">3.8% invest</field>
<field name="amount" eval="0.038"/>
<field name="type">percent</field>
@@ -253,8 +360,29 @@
<field name="account_collected_id" ref="ch_coa_1171"/>
<field name="account_paid_id" ref="ch_coa_1171"/>
</record>
<record model="account.tax.template" id="vat_38_invest_ttc">
<field name="name">TVA 3.8% sur invest. et autres ch. TTC</field>
<field name="description">3.8% invest TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="0.038"/>
<field name="type">percent</field>
<field name="base_code_id" ref="vat_code_receivable_base_invest38"/>
<field name="tax_code_id" ref="vat_code_payable_invest"/>
<field name="ref_base_code_id" ref="vat_code_receivable_base_invest38"/>
<field name="ref_tax_code_id" ref="vat_code_payable_invest"/>
<field name="python_compute">result = round((price_unit * 0.038) / 0.05) * 0.05</field>
<field name="python_compute_inv">result = round((price_unit * ( 1 - (1 / 1.038))) /0.05) * 0.05</field>
<field name="base_sign" eval="-1.0"/>
<field name="tax_sign" eval="-1.0"/>
<field name="ref_base_sign" eval="1.0"/>
<field name="ref_tax_sign" eval="1.0"/>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">purchase</field>
<field name="account_collected_id" ref="ch_coa_1171"/>
<field name="account_paid_id" ref="ch_coa_1171"/>
</record>
<record model="account.tax.template" id="vat_80">
<field name="name">TVA due a 8.0% (TN)</field>
<field name="name">TVA due a 8.0%</field>
<field name="description">8.0%</field>
<field name="amount" eval="0.080"/>
<field name="sequence" eval="0"/>
@@ -275,7 +403,7 @@
<field name="account_paid_id" ref="ch_coa_2200"/>
</record>
<record model="account.tax.template" id="vat_80_purchase">
<field name="name">TVA 8.0% sur achat B&amp;S (TN)</field>
<field name="name">TVA 8.0% sur achats, biens et services</field>
<field name="description">8.0% achat</field>
<field name="amount" eval="0.080"/>
<field name="type">percent</field>
@@ -294,9 +422,52 @@
<field name="type_tax_use">purchase</field>
<field name="account_collected_id" ref="ch_coa_1170"/>
<field name="account_paid_id" ref="ch_coa_1170"/>
</record>
</record>
<record model="account.tax.template" id="vat_80_ttc">
<field name="name">TVA due a 8.0% TTC</field>
<field name="description">8.0% TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="0.080"/>
<field name="type">percent</field>
<field name="base_code_id" ref="vat_code_due_80"/>
<field name="tax_code_id" ref="vat_code_due_tva80"/>
<field name="ref_base_code_id" ref="vat_code_due_80"/>
<field name="ref_tax_code_id" ref="vat_code_due_tva80"/>
<field name="python_compute">result = round((price_unit * 0.080) / 0.05) * 0.05</field>
<field name="python_compute_inv">result = round((price_unit * ( 1 - (1 / 1.080))) /0.05) * 0.05</field>
<field name="base_sign" eval="1.0"/>
<field name="tax_sign" eval="1.0"/>
<field name="ref_base_sign" eval="-1.0"/>
<field name="ref_tax_sign" eval="-1.0"/>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">sale</field>
<field name="account_collected_id" ref="ch_coa_2200"/>
<field name="account_paid_id" ref="ch_coa_2200"/>
</record>
<record model="account.tax.template" id="vat_80_purchase_ttc">
<field name="name">TVA 8.0% sur achats, biens et services TTC</field>
<field name="description">8.0% achat TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="0.080"/>
<field name="type">percent</field>
<field name="base_code_id" ref="vat_code_receivable_base_80"/>
<field name="tax_code_id" ref="vat_code_payable_bs"/>
<field name="ref_base_code_id" ref="vat_code_receivable_base_80"/>
<field name="ref_tax_code_id" ref="vat_code_payable_bs"/>
<field name="python_compute">result = round((price_unit * 0.080) / 0.05) * 0.05</field>
<field name="python_compute_inv">result = round((price_unit * ( 1 - (1 / 1.080))) /0.05) * 0.05</field>
<field name="base_sign" eval="-1.0"/>
<field name="tax_sign" eval="-1.0"/>
<field name="ref_base_sign" eval="1.0"/>
<field name="ref_tax_sign" eval="1.0"/>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">purchase</field>
<field name="account_collected_id" ref="ch_coa_1170"/>
<field name="account_paid_id" ref="ch_coa_1170"/>
</record>
<record model="account.tax.template" id="vat_80_invest">
<field name="name">TVA 8.0% sur invest. et autres ch. (TN)</field>
<field name="name">TVA 8.0% sur invest. et autres ch.</field>
<field name="description">8.0% invest.</field>
<field name="amount" eval="0.080"/>
<field name="type">percent</field>
@@ -315,6 +486,27 @@
<field name="account_collected_id" ref="ch_coa_1171"/>
<field name="account_paid_id" ref="ch_coa_1171"/>
</record>
<record model="account.tax.template" id="vat_80_invest_ttc">
<field name="name">TVA 8.0% sur invest. et autres ch.TTC</field>
<field name="description">8.0% invest.TTC</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="0.080"/>
<field name="type">percent</field>
<field name="base_code_id" ref="vat_code_receivable_base_invest80"/>
<field name="tax_code_id" ref="vat_code_payable_invest"/>
<field name="ref_base_code_id" ref="vat_code_receivable_base_invest80"/>
<field name="ref_tax_code_id" ref="vat_code_payable_invest"/>
<field name="python_compute">result = round((price_unit * 0.080) / 0.05) * 0.05</field>
<field name="python_compute_inv">result = round((price_unit * ( 1 - (1 / 1.080))) /0.05) * 0.05</field>
<field name="base_sign" eval="-1.0"/>
<field name="tax_sign" eval="-1.0"/>
<field name="ref_base_sign" eval="1.0"/>
<field name="ref_tax_sign" eval="1.0"/>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">purchase</field>
<field name="account_collected_id" ref="ch_coa_1171"/>
<field name="account_paid_id" ref="ch_coa_1171"/>
</record>
<record model="account.tax.template" id="vat_XO">
<field name="name">TVA due a 0% (Exportations)</field>
<field name="amount" eval="0.00"/>
@@ -334,8 +526,8 @@
<field name="account_paid_id" ref="ch_coa_2200"/>
</record>
<record model="account.tax.template" id="vat_O_exclude">
<field name="name">TVA 0% exclue</field>
<field name="description">0% excl.</field>
<field name="name">TVA exclue/ventes</field>
<field name="description">exclue</field>
<field name="amount" eval="0.00"/>
<field name="type">percent</field>
<field name="base_code_id" ref="vat_code_due_0_exclu"/>
@@ -351,8 +543,24 @@
<field name="account_collected_id" ref="ch_coa_2200"/>
<field name="account_paid_id" ref="ch_coa_2200"/>
</record>
<record model="account.tax.template" id="vat_O_exclude_purch">
<field name="name">TVA exclue/achats</field>
<field name="description">0% excl.ach.</field>
<field name="amount" eval="0.00"/>
<field name="type">percent</field>
<field name="base_code_id" ref="vat_code_receivable_base_excl"/>
<field name="ref_base_code_id" ref="vat_code_receivable_base_excl"/>
<field name="base_sign" eval="-1.0"/>
<field name="tax_sign" eval="-1.0"/>
<field name="ref_base_sign" eval="1.0"/>
<field name="ref_tax_sign" eval="1.0"/>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">purchase</field>
<field name="account_collected_id" ref="ch_coa_1170"/>
<field name="account_paid_id" ref="ch_coa_1170"/>
</record>
<record model="account.tax.template" id="vat_O_import">
<field name="name">TVA 0% Importations de biens et services</field>
<field name="name">TVA 0% Importations</field>
<field name="description">0% import.</field>
<field name="amount" eval="0.00"/>
<field name="type">percent</field>
@@ -371,8 +579,25 @@
</record>
<!--# 100% on import !! the tax percentage is 00-->
<record model="account.tax.template" id="vat_100_import">
<field name="name">100% dédouanement TVA</field>
<field name="description">100% imp.</field>
<field name="name">100% dédouanement TVA sur invest. et autres ch.</field>
<field name="description">100% imp.invest.</field>
<field name="amount" eval="0.0"/>
<field name="type">percent</field>
<field name="base_code_id" ref="vat_code_payable_invest"/>
<field name="ref_base_code_id" ref="vat_code_payable_invest"/>
<field name="base_sign" eval="1.0"/>
<field name="tax_sign" eval="1.0"/>
<field name="ref_base_sign" eval="-1.0"/>
<field name="ref_tax_sign" eval="-1.0"/>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">purchase</field>
<field name="account_collected_id" ref="ch_coa_1171"/>
<field name="account_paid_id" ref="ch_coa_1171"/>
</record>
<!--# 100% on import !! the tax percentage is 00-->
<record model="account.tax.template" id="vat_100_import_abs8">
<field name="name">100% dédouanement TVA sur achats, biens et services </field>
<field name="description">100% imp.abs.</field>
<field name="amount" eval="0.0"/>
<field name="type">percent</field>
<field name="base_code_id" ref="vat_code_payable_bs"/>
@@ -383,8 +608,8 @@
<field name="ref_tax_sign" eval="-1.0"/>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">purchase</field>
<field name="account_collected_id" ref="ch_coa_1171"/>
<field name="account_paid_id" ref="ch_coa_1171"/>
</record>
<field name="account_collected_id" ref="ch_coa_1170"/>
<field name="account_paid_id" ref="ch_coa_1170"/>
</record>
</data>
</openerp>
+24 -11
View File
@@ -446,6 +446,9 @@ class mail_thread(osv.AbstractModel):
cascaded, because link is done through (res_model, res_id). """
msg_obj = self.pool.get('mail.message')
fol_obj = self.pool.get('mail.followers')
if isinstance(ids, (int, long)):
ids = [ids]
# delete messages and notifications
msg_ids = msg_obj.search(cr, uid, [('model', '=', self._name), ('res_id', 'in', ids)], context=context)
msg_obj.unlink(cr, uid, msg_ids, context=context)
@@ -837,7 +840,7 @@ class mail_thread(osv.AbstractModel):
if not message_dict.get('parent_id'):
raise ValueError('Routing: posting a message without model should be with a parent_id (private mesage).')
_warn('posting a message without model should be with a parent_id (private mesage), skipping')
return ()
return False
# Existing Document: check if exists; if not, fallback on create if allowed
if thread_id and not model_pool.exists(cr, uid, thread_id):
@@ -848,7 +851,7 @@ class mail_thread(osv.AbstractModel):
assert model_pool.exists(cr, uid, thread_id), 'Routing: reply to missing document (%s,%s)' % (model, thread_id)
else:
_warn('reply to missing document (%s,%s), skipping' % (model, thread_id))
return ()
return False
# Existing Document: check model accepts the mailgateway
if thread_id and model and not hasattr(model_pool, 'message_update'):
@@ -859,7 +862,7 @@ class mail_thread(osv.AbstractModel):
assert hasattr(model_pool, 'message_update'), 'Routing: model %s does not accept document update, crashing' % model
else:
_warn('model %s does not accept document update, skipping' % model)
return ()
return False
# New Document: check model accepts the mailgateway
if not thread_id and model and not hasattr(model_pool, 'message_new'):
@@ -869,7 +872,7 @@ class mail_thread(osv.AbstractModel):
'Model %s does not accept document creation, crashing' % model
)
_warn('model %s does not accept document creation, skipping' % model)
return ()
return False
# Update message author if asked
# We do it now because we need it for aliases (contact settings)
@@ -888,16 +891,16 @@ class mail_thread(osv.AbstractModel):
if not author_id or not author_id in [fol.id for fol in obj.message_follower_ids]:
_warn('alias %s restricted to internal followers, skipping' % alias.alias_name)
_create_bounce_email()
return ()
return False
elif alias and alias.alias_contact == 'partners' and not author_id:
_warn('alias %s does not accept unknown author, skipping' % alias.alias_name)
_create_bounce_email()
return ()
return False
if not model and not thread_id and not alias and not allow_private:
return ()
return (model, thread_id, route[2], route[3], route[4])
return (model, thread_id, route[2], route[3], None if context.get('drop_alias', False) else route[4])
def message_route(self, cr, uid, message, message_dict, model=None, thread_id=None,
custom_values=None, context=None):
@@ -937,6 +940,7 @@ class mail_thread(osv.AbstractModel):
if not isinstance(message, Message):
raise TypeError('message must be an email.message.Message at this point')
mail_msg_obj = self.pool['mail.message']
mail_alias = self.pool.get('mail.alias')
fallback_model = model
# Get email.message.Message variables for future processing
@@ -964,15 +968,21 @@ class mail_thread(osv.AbstractModel):
if ref_match and mail_message_ids:
original_msg = mail_msg_obj.browse(cr, SUPERUSER_ID, mail_message_ids[0], context=context)
model, thread_id = original_msg.model, original_msg.res_id
alias_ids = mail_alias.search(cr, uid, [('alias_name', '=', (tools.email_split(email_to) or [''])[0].split('@', 1)[0].lower())])
alias = None
if alias_ids:
alias = mail_alias.browse(cr, uid, [alias_ids[0]], context=context)
route = self.message_route_verify(
cr, uid, message, message_dict,
(model, thread_id, custom_values, uid, None),
update_author=True, assert_model=False, create_fallback=True, context=context)
(model, thread_id, custom_values, uid, alias),
update_author=True, assert_model=False, create_fallback=True, context=dict(context, drop_alias=True))
if route:
_logger.info(
'Routing mail from %s to %s with Message-Id %s: direct reply to msg: model: %s, thread_id: %s, custom_values: %s, uid: %s',
email_from, email_to, message_id, model, thread_id, custom_values, uid)
return [route]
elif route is False:
return []
# 2. message is a reply to an existign thread (6.1 compatibility)
if ref_match:
@@ -1001,6 +1011,8 @@ class mail_thread(osv.AbstractModel):
'Routing mail from %s to %s with Message-Id %s: direct thread reply (compat-mode) to model: %s, thread_id: %s, custom_values: %s, uid: %s',
email_from, email_to, message_id, model, thread_id, custom_values, uid)
return [route]
elif route is False:
return []
# 3. Reply to a private message
if in_reply_to:
@@ -1018,6 +1030,8 @@ class mail_thread(osv.AbstractModel):
'Routing mail from %s to %s with Message-Id %s: direct reply to a private message: %s, custom_values: %s, uid: %s',
email_from, email_to, message_id, mail_message.id, custom_values, uid)
return [route]
elif route is False:
return []
# 4. Look for a matching mail.alias entry
# Delivered-To is a safe bet in most modern MTAs, but we have to fallback on To + Cc values
@@ -1030,7 +1044,6 @@ class mail_thread(osv.AbstractModel):
decode_header(message, 'Resent-Cc')])
local_parts = [e.split('@')[0] for e in tools.email_split(rcpt_tos)]
if local_parts:
mail_alias = self.pool.get('mail.alias')
alias_ids = mail_alias.search(cr, uid, [('alias_name', 'in', local_parts)])
if alias_ids:
routes = []
@@ -1085,7 +1098,7 @@ class mail_thread(osv.AbstractModel):
context = dict(context or {})
partner_ids = message_dict.pop('partner_ids', [])
thread_id = False
for model, thread_id, custom_values, user_id, alias in routes:
for model, thread_id, custom_values, user_id, alias in routes or ():
if self._name == 'mail.thread':
context['thread_model'] = model
if model:
+2 -2
View File
@@ -100,7 +100,7 @@ class TestMail(common.SavepointCase):
'login': 'raoul',
'alias_name': 'raoul',
'groups_id': [(6, 0, [cls.group_employee_id])]
})
}, {'no_reset_password': True})
cls.user_bert_id = cls.res_users.create(cr, uid, {
'name': 'Bert Tartignole',
'signature': 'SignBert',
@@ -108,7 +108,7 @@ class TestMail(common.SavepointCase):
'login': 'bert',
'alias_name': 'bert',
'groups_id': [(6, 0, [])]
})
}, {'no_reset_password': True})
cls.user_raoul = cls.res_users.browse(cr, uid, cls.user_raoul_id)
cls.user_bert = cls.res_users.browse(cr, uid, cls.user_bert_id)
cls.user_admin = cls.res_users.browse(cr, uid, uid)
+40 -40
View File
@@ -28,6 +28,46 @@ class MassMailingTag(osv.Model):
}
class MassMailingList(osv.Model):
"""Model of a contact list. """
_name = 'mail.mass_mailing.list'
_order = 'name'
_description = 'Mailing List'
def _get_contact_nbr(self, cr, uid, ids, name, arg, context=None):
result = dict.fromkeys(ids, 0)
Contacts = self.pool.get('mail.mass_mailing.contact')
for group in Contacts.read_group(cr, uid, [('list_id', 'in', ids), ('opt_out', '!=', True)], ['list_id'], ['list_id'], context=context):
result[group['list_id'][0]] = group['list_id_count']
return result
_columns = {
'name': fields.char('Mailing List', required=True),
'create_date': fields.datetime('Creation Date'),
'contact_nbr': fields.function(
_get_contact_nbr, type='integer',
string='Number of Contacts',
),
'popup_content': fields.html("Website Popup Content", translate=True, required=True, sanitize=False),
'popup_redirect_url': fields.char("Website Popup Redirect URL"),
}
def _get_default_popup_content(self, cr, uid, context=None):
return """<div class="o_popup_modal_header text-center">
<h3 class="o_popup_modal_title mt8">Odoo Presents</h3>
</div>
<div class="o_popup_message">
<font>7</font>
<strong>Business Hacks</strong>
<span> to<br/>boost your marketing</span>
</div>
<p class="o_message_paragraph">Join our Marketing newsletter and get <strong>this white paper instantly</strong></p>"""
_defaults = {
'popup_content': _get_default_popup_content,
}
class MassMailingContact(osv.Model):
"""Model of a contact. This model is different from the partner model
because it holds only some basic information: name, email. The purpose is to
@@ -108,46 +148,6 @@ class MassMailingContact(osv.Model):
self.write(cr, uid, [obj.id], {'message_bounce': obj.message_bounce + 1}, context=context)
class MassMailingList(osv.Model):
"""Model of a contact list. """
_name = 'mail.mass_mailing.list'
_order = 'name'
_description = 'Mailing List'
def _get_contact_nbr(self, cr, uid, ids, name, arg, context=None):
result = dict.fromkeys(ids, 0)
Contacts = self.pool.get('mail.mass_mailing.contact')
for group in Contacts.read_group(cr, uid, [('list_id', 'in', ids), ('opt_out', '!=', True)], ['list_id'], ['list_id'], context=context):
result[group['list_id'][0]] = group['list_id_count']
return result
_columns = {
'name': fields.char('Mailing List', required=True),
'create_date': fields.datetime('Creation Date'),
'contact_nbr': fields.function(
_get_contact_nbr, type='integer',
string='Number of Contacts',
),
'popup_content': fields.html("Website Popup Content", translate=True, required=True, sanitize=False),
'popup_redirect_url': fields.char("Website Popup Redirect URL"),
}
def _get_default_popup_content(self, cr, uid, context=None):
return """<div class="o_popup_modal_header text-center">
<h3 class="o_popup_modal_title mt8">Odoo Presents</h3>
</div>
<div class="o_popup_message">
<font>7</font>
<strong>Business Hacks</strong>
<span> to<br/>boost your marketing</span>
</div>
<p class="o_message_paragraph">Join our Marketing newsletter and get <strong>this white paper instantly</strong></p>"""
_defaults = {
'popup_content': _get_default_popup_content,
}
class MassMailingStage(osv.Model):
"""Stage for mass mailing campaigns. """
_name = 'mail.mass_mailing.stage'
+16 -13
View File
@@ -25,17 +25,16 @@
<field name="mail_mail_id_int"/>
<field name="message_id"/>
<field name="mass_mailing_id"/>
<filter help="Sent" domain="[('sent', '!=', False)]"/>
<filter help="Opened" domain="[('opened', '!=', False)]"/>
<filter help="Replied" domain="[('replied', '!=', False)]"/>
<filter help="Bounced" domain="[('bounced', '!=', False)]"/>
<filter string="Received" name="filter_received" domain="[('sent', '!=', False), ('bounced', '=', False)]"/>
<filter string="Opened" name="filter_opened" domain="[('opened', '!=', False)]"/>
<filter string="Replied" name="filter_replied" domain="[('replied', '!=', False)]"/>
<filter string="Bounced" name="filter_bounced" domain="[('bounced', '!=', False)]"/>
<group expand="0" string="Group By">
<filter string="State" domain="[]"
context="{'group_by':'state'}"/>
<filter string="Last State Update" domain="[]"
context="{'group_by':'state_update'}"/>
<filter string="Mass Mailing" domain="[]"
context="{'group_by':'mass_mailing_id'}"/>
<filter string="State" domain="[]" context="{'group_by':'state'}"/>
<filter string="Open Date" name="group_open_date" context="{'group_by': 'opened:day'}"/>
<filter string="Reply Date" name="group_reply_date" context="{'group_by': 'replied:day'}"/>
<filter string="Last State Update" domain="[]" context="{'group_by':'state_update'}"/>
<filter string="Mass Mailing" domain="[]" context="{'group_by':'mass_mailing_id'}"/>
</group>
</search>
</field>
@@ -400,15 +399,18 @@
<field name="sent" string="Emails Sent" widget="statinfo"/>
</button>
<button name="%(action_view_mail_mail_statistics_mailing)d"
type="action" class="oe_stat_button">
context="{'search_default_filter_received': True}"
type="action" class="oe_stat_button">
<field name="received_ratio" string="Received" widget="percentpie"/>
</button>
<button name="%(action_view_mail_mail_statistics_mailing)d"
type="action" class="oe_stat_button">
context="{'search_default_filter_opened': True}"
type="action" class="oe_stat_button">
<field name="opened_ratio" string="Opened" widget="percentpie"/>
</button>
<button name="%(action_view_mail_mail_statistics_mailing)d"
type="action" class="oe_stat_button">
context="{'search_default_filter_replied': True}"
type="action" class="oe_stat_button">
<field name="replied_ratio" string="Replied" widget="percentpie"/>
</button>
<button name="%(action_view_mass_mailing_links_statistics)d"
@@ -416,6 +418,7 @@
<field name="clicks_ratio" string="Clicks" widget="percentpie"/>
</button>
<button name="%(action_view_mail_mail_statistics_mailing)d"
context="{'search_default_filter_bounced': True}"
type="action" class="oe_stat_button">
<field name="bounced_ratio" string="Bounced" widget="percentpie"/>
</button>
+14 -2
View File
@@ -507,6 +507,12 @@ class mrp_production(osv.osv):
result[prod.id]['cycle_total'] += wc.cycle
return result
def _get_workcenter_line(self, cr, uid, ids, context=None):
result = {}
for line in self.pool['mrp.production.workcenter.line'].browse(cr, uid, ids, context=context):
result[line.production_id.id] = True
return result.keys()
def _src_id_default(self, cr, uid, ids, context=None):
try:
location_model, location_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'stock_location_stock')
@@ -605,8 +611,14 @@ class mrp_production(osv.osv):
If the stock is available then the status is set to 'Ready to Produce'.\n\
When the production gets started then the status is set to 'In Production'.\n\
When the production is over, the status is set to 'Done'."),
'hour_total': fields.function(_production_calc, type='float', string='Total Hours', multi='workorder', store=True),
'cycle_total': fields.function(_production_calc, type='float', string='Total Cycles', multi='workorder', store=True),
'hour_total': fields.function(_production_calc, type='float', string='Total Hours', multi='workorder', store={
_name: (lambda self, cr, uid, ids, c={}: ids, ['workcenter_lines'], 40),
'mrp.production.workcenter.line': (_get_workcenter_line, ['hour', 'cycle'], 40),
}),
'cycle_total': fields.function(_production_calc, type='float', string='Total Cycles', multi='workorder', store={
_name: (lambda self, cr, uid, ids, c={}: ids, ['workcenter_lines'], 40),
'mrp.production.workcenter.line': (_get_workcenter_line, ['hour', 'cycle'], 40),
}),
'user_id': fields.many2one('res.users', 'Responsible'),
'company_id': fields.many2one('res.company', 'Company', required=True),
'ready_production': fields.function(_moves_assigned, type='boolean', string="Ready for production", store={'stock.move': (_mrp_from_move, ['state'], 10)}),
+1 -3
View File
@@ -5,7 +5,6 @@
company_id: base.main_company
name: MRP Manager
login: mam
password: mam
email: mrp_manager@yourcompany.com
-
I added groups for MRP Manager.
@@ -21,11 +20,10 @@
company_id: base.main_company
name: MRP User
login: mau
password: mau
email: mrp_user@yourcompany.com
-
I added groups for MRP User.
-
!record {model: res.users, id: res_users_mrp_user}:
groups_id:
- mrp.group_mrp_user
- mrp.group_mrp_user
@@ -5,7 +5,6 @@
company_id: base.main_company
name: MRP User
login: maou
password: maou
email: mrp_operation_user@yourcompany.com
-
I added groups for MRP User.
+1 -3
View File
@@ -5,7 +5,6 @@
company_id: base.main_company
name: MRP Manager
login: marm
password: marm
email: mrp_repair_manager@yourcompany.com
-
I added groups for MRP Repair Manager.
@@ -20,11 +19,10 @@
company_id: base.main_company
name: MRP User
login: maru
password: maru
email: mrp_repair_user@yourcompany.com
-
I added groups for MRP Repair User.
-
!record {model: res.users, id: res_mrp_repair_user}:
groups_id:
- mrp.group_mrp_user
- mrp.group_mrp_user
+2 -1
View File
@@ -7,6 +7,7 @@ from lxml import etree, objectify
from openerp.tools.translate import _
from pprint import pformat
import time
from datetime import datetime
from urllib import urlencode
import urllib2
import urlparse
@@ -289,7 +290,7 @@ class PaymentTxOgone(osv.Model):
if status in self._ogone_valid_tx_status:
tx.write({
'state': 'done',
'date_validate': data['TRXDATE'],
'date_validate': datetime.strptime(data['TRXDATE'],'%m/%d/%y').strftime(DEFAULT_SERVER_DATE_FORMAT),
'acquirer_reference': data['PAYID'],
})
return True
+6 -2
View File
@@ -708,7 +708,8 @@ class pos_order(osv.osv):
val1 += self._amount_line_tax(cr, uid, line, context=context)
val2 += line.price_subtotal
res[order.id]['amount_tax'] = cur_obj.round(cr, uid, cur, val1)
res[order.id]['amount_total'] = cur_obj.round(cr, uid, cur, val1+val2)
amount_untaxed = cur_obj.round(cr, uid, cur, val2)
res[order.id]['amount_total'] = res[order.id]['amount_tax'] + amount_untaxed
return res
_columns = {
@@ -1009,7 +1010,6 @@ class pos_order(osv.osv):
'invoice_id': inv_id,
'product_id': line.product_id.id,
'quantity': line.qty,
'account_analytic_id': self._prepare_analytic_account(cr, uid, line, context=context),
}
inv_name = product_obj.name_get(cr, uid, [line.product_id.id], context=context)[0][1]
inv_line.update(inv_line_ref.product_id_change(cr, uid, [],
@@ -1017,6 +1017,10 @@ class pos_order(osv.osv):
line.product_id.uom_id.id,
line.qty, partner_id = order.partner_id.id,
fposition_id=order.partner_id.property_account_position.id)['value'])
if not inv_line.get('account_analytic_id', False):
inv_line['account_analytic_id'] = \
self._prepare_analytic_account(cr, uid, line,
context=context)
inv_line['price_unit'] = line.price_unit
inv_line['discount'] = line.discount
inv_line['name'] = inv_name
+1 -1
View File
@@ -380,7 +380,7 @@ openerp.point_of_sale.load_db = function load_db(instance, module){
search_product_in_category: function(category_id, query){
try {
query = query.replace(/[\[\]\(\)\+\*\?\.\-\!\&\^\$\|\~\_\{\}\:\,\\\/]/g,'.');
query = query.replace(' ','.+');
query = query.replace(/ /g,'.+');
var re = RegExp("([0-9]+):.*?"+query,"gi");
}catch(e){
return [];
+2 -3
View File
@@ -1176,6 +1176,7 @@ openerp.point_of_sale.load_models = function load_models(instance, module){ //mo
taxtotal += tax.amount;
taxdetail[tax.id] = tax.amount;
});
totalNoTax = round_pr(totalNoTax, this.pos.currency.rounding);
return {
"priceWithTax": totalTax,
@@ -1651,9 +1652,7 @@ openerp.point_of_sale.load_models = function load_models(instance, module){ //mo
}), 0), this.pos.currency.rounding);
},
get_total_with_tax: function() {
return round_pr(this.orderlines.reduce((function(sum, orderLine) {
return sum + orderLine.get_price_with_tax();
}), 0), this.pos.currency.rounding);
return this.get_total_without_tax() + this.get_total_tax();
},
get_total_without_tax: function() {
return round_pr(this.orderlines.reduce((function(sum, orderLine) {
+6 -1
View File
@@ -35,7 +35,12 @@ class test_portal(TestMail):
cls.group_portal_id = cls.env.ref('base.group_portal').id
# Create Chell (portal user)
cls.user_chell_id = cls.res_users.create(cr, uid, {'name': 'Chell Gladys', 'login': 'chell', 'email': 'chell@gladys.portal', 'groups_id': [(6, 0, [cls.group_portal_id])]})
cls.user_chell_id = cls.res_users.create(cr, uid, {
'name': 'Chell Gladys',
'login': 'chell',
'email': 'chell@gladys.portal',
'groups_id': [(6, 0, [cls.group_portal_id])]
}, {'no_reset_password': True})
cls.user_chell = cls.res_users.browse(cr, uid, cls.user_chell_id)
cls.partner_chell_id = cls.user_chell.partner_id.id
@@ -45,19 +45,19 @@ class TestPortalProjectBase(TestProjectBase):
'login': 'chell',
'alias_name': 'chell',
'groups_id': [(6, 0, [self.group_portal_id])]
})
}, {'no_reset_password': True})
self.user_public_id = self.res_users.create(cr, uid, {
'name': 'Donovan Public',
'login': 'donovan',
'alias_name': 'donovan',
'groups_id': [(6, 0, [self.group_public_id])]
})
}, {'no_reset_password': True})
self.user_manager_id = self.res_users.create(cr, uid, {
'name': 'Eustache Manager',
'login': 'eustache',
'alias_name': 'eustache',
'groups_id': [(6, 0, [self.group_project_manager_id])]
})
}, {'no_reset_password': True})
# Test 'Pigs' project
self.project_pigs_id = self.project_project.create(cr, uid, {
+6 -6
View File
@@ -721,7 +721,7 @@ class product_template(osv.osv):
# unlink or inactive product
for variant_id in map(int,variants_inactive):
try:
with cr.savepoint():
with cr.savepoint(), tools.mute_logger('openerp.sql_db'):
product_obj.unlink(cr, uid, [variant_id], context=ctx)
#We catch all kind of exception to be sure that the operation doesn't fail.
except (psycopg2.Error, except_orm):
@@ -937,12 +937,12 @@ class product_product(osv.osv):
def _set_image_variant(self, cr, uid, id, name, value, args, context=None):
image = tools.image_resize_image_big(value)
res = self.write(cr, uid, [id], {'image_variant': image}, context=context)
product = self.browse(cr, uid, id, context=context)
if not product.product_tmpl_id.image:
product.write({'image_variant': None})
product.product_tmpl_id.write({'image': image})
return res
if product.product_tmpl_id.image:
product.image_variant = image
else:
product.product_tmpl_id.image = image
def _get_price_extra(self, cr, uid, ids, name, args, context=None):
result = dict.fromkeys(ids, False)
+3 -3
View File
@@ -57,21 +57,21 @@ class TestProjectBase(TestMail):
'alias_name': 'armande',
'email': 'armande.projectuser@example.com',
'groups_id': [(6, 0, [cls.group_employee_id, cls.group_project_user_id])]
})
}, {'no_reset_password': True})
cls.user_projectmanager_id = cls.res_users.create(cr, uid, {
'name': 'Bastien ProjectManager',
'login': 'bastien',
'alias_name': 'bastien',
'email': 'bastien.projectmanager@example.com',
'groups_id': [(6, 0, [cls.group_employee_id, cls.group_project_manager_id])]
})
}, {'no_reset_password': True})
cls.user_none_id = cls.res_users.create(cr, uid, {
'name': 'Charlie Avotbonkeur',
'login': 'charlie',
'alias_name': 'charlie',
'email': 'charlie.noone@example.com',
'groups_id': [(6, 0, [])]
})
}, {'no_reset_password': True})
cls.user_projectuser = cls.res_users.browse(cr, uid, cls.user_projectuser_id)
cls.user_projectmanager = cls.res_users.browse(cr, uid, cls.user_projectmanager_id)
cls.partner_projectuser_id = cls.user_projectuser.partner_id.id
+1 -3
View File
@@ -5,7 +5,6 @@
company_id: base.main_company
name: Project Manager
login: prim
password: prim
email: issuemanager@yourcompany.com
-
I added groups for Project manager.
@@ -20,11 +19,10 @@
company_id: base.main_company
name: Project User
login: priu
password: priu
email: issueuser@yourcompany.com
-
I added groups for Project user.
-
!record {model: res.users, id: res_users_project_issue_user}:
groups_id:
- project.group_project_user
- project.group_project_user
@@ -5,7 +5,6 @@
company_id: base.main_company
name: HR Manager
login: hr
password: hr
groups_id:
- base.group_hr_manager
-
+3 -1
View File
@@ -863,6 +863,7 @@ class purchase_order(osv.osv):
}
picking_id = self.pool.get('stock.picking').create(cr, uid, picking_vals, context=context)
self._create_stock_moves(cr, uid, order, order.order_line, picking_id, context=context)
return picking_id
def picking_done(self, cr, uid, ids, context=None):
self.write(cr, uid, ids, {'shipped':1,'state':'approved'}, context=context)
@@ -1704,7 +1705,8 @@ class account_invoice(osv.Model):
not all(picking.invoice_state in ['invoiced'] for picking in order.picking_ids)):
shipped = False
for po_line in order.order_line:
if all(line.invoice_id.state not in ['draft', 'cancel'] for line in po_line.invoice_lines):
if (po_line.invoice_lines and
all(line.invoice_id.state not in ['draft', 'cancel'] for line in po_line.invoice_lines)):
invoiced.append(po_line.id)
if invoiced and shipped:
self.pool['purchase.order.line'].write(cr, user_id, invoiced, {'invoiced': True})
+9 -2
View File
@@ -94,9 +94,12 @@ class stock_move(osv.osv):
return invoice_line_id
def _get_master_data(self, cr, uid, move, company, context=None):
if context.get('inv_type') in ('in_invoice', 'in_refund') and move.purchase_line_id:
if context.get('inv_type') == 'in_invoice' and move.purchase_line_id:
purchase_order = move.purchase_line_id.order_id
return purchase_order.partner_id, purchase_order.create_uid.id, purchase_order.currency_id.id
if context.get('inv_type') == 'in_refund' and move.origin_returned_move_id.purchase_line_id:
purchase_order = move.origin_returned_move_id.purchase_line_id.order_id
return purchase_order.partner_id, purchase_order.create_uid.id, purchase_order.currency_id.id
elif context.get('inv_type') in ('in_invoice', 'in_refund') and move.picking_id:
# In case of an extra move, it is better to use the data from the original moves
for purchase_move in move.picking_id.move_lines:
@@ -114,10 +117,14 @@ class stock_move(osv.osv):
def _get_invoice_line_vals(self, cr, uid, move, partner, inv_type, context=None):
res = super(stock_move, self)._get_invoice_line_vals(cr, uid, move, partner, inv_type, context=context)
if inv_type in ('in_invoice', 'in_refund') and move.purchase_line_id:
if inv_type == 'in_invoice' and move.purchase_line_id:
purchase_line = move.purchase_line_id
res['invoice_line_tax_id'] = [(6, 0, [x.id for x in purchase_line.taxes_id])]
res['price_unit'] = purchase_line.price_unit
elif inv_type == 'in_refund' and move.origin_returned_move_id.purchase_line_id:
purchase_line = move.origin_returned_move_id.purchase_line_id
res['invoice_line_tax_id'] = [(6, 0, [x.id for x in purchase_line.taxes_id])]
res['price_unit'] = purchase_line.price_unit
return res
def _get_moves_taxes(self, cr, uid, moves, inv_type, context=None):
@@ -5,7 +5,6 @@
company_id: base.main_company
name: Purchase Manager
login: pm
password: pm
email: purchasemanager@yourcompany.com
-
I added groups for Purchase manager.
@@ -20,7 +19,6 @@
company_id: base.main_company
name: Purchase User
login: pu
password: pu
email: purchaseuser@yourcompany.com
-
I added groups for Purchase user.
@@ -5,7 +5,6 @@
company_id: base.main_company
name: Purchase requisition Manager
login: prm
password: prm
email: requisition_manager@yourcompany.com
-
I added groups for Purchase Requisition Manager.
@@ -20,11 +19,10 @@
company_id: base.main_company
name: Purchase requisition User
login: pru
password: pru
email: requisition_user@yourcompany.com
-
I added groups for Purchase Requisition User.
-
!record {model: res.users, id: res_users_purchase_requisition_user}:
groups_id:
- purchase_requisition.group_purchase_requisition_user
- purchase_requisition.group_purchase_requisition_user
+3
View File
@@ -40,6 +40,9 @@
.table-condensed > thead > tr > th {
border-bottom: 1px solid black !important;
}
.table-condensed > tbody > tr {
page-break-inside: avoid !important;
}
.zero_min_height {
min-height: 0px !important;
}
+1 -1
View File
@@ -40,7 +40,7 @@ class sale_order(osv.osv):
_description = "Sales Order"
_track = {
'state': {
'sale.mt_order_confirmed': lambda self, cr, uid, obj, ctx=None: obj.state in ['manual'],
'sale.mt_order_confirmed': lambda self, cr, uid, obj, ctx=None: obj.state in ['manual', 'progress'],
'sale.mt_order_sent': lambda self, cr, uid, obj, ctx=None: obj.state in ['sent']
},
}
-2
View File
@@ -5,7 +5,6 @@
company_id: base.main_company
name: Sales manager
login: sm
password: sm
email: salesmanager@yourcompany.com
-
I added groups for Salesmanager.
@@ -20,7 +19,6 @@
company_id: base.main_company
name: Salesman
login: su
password: su
email: salesman@yourcompany.com
-
I added groups for Salesman.
@@ -9,6 +9,7 @@
!record {model: product.product, id: product_onchange1}:
name: 'Devil Worship Book'
list_price: 66.6
default_code: 'DWB00001'
-
In sale order to test process of onchange of Sale Order with access rights of saleman.
-
@@ -28,5 +29,5 @@
!python {model: sale.order}: |
from openerp.tools import float_compare
order_line = self.browse(cr, uid, ref('sale_order_onchange1')).order_line
assert order_line[0].name == u'Devil Worship Book', "The onchange function of product was not correctly triggered"
assert order_line[0].name == u'[DWB00001] Devil Worship Book', "The onchange function of product was not correctly triggered"
assert float_compare(order_line[0].price_unit, 66.6, precision_digits=2) == 0, "The onchange function of product was not correctly triggered"
@@ -5,7 +5,6 @@
company_id: base.main_company
name: Stock Sales manager
login: ssm
password: ssm
email: ss_salesmanager@yourcompany.com
-
I added groups for Salesmanager.
@@ -20,7 +19,6 @@
company_id: base.main_company
name: Stock Salesman
login: ssu
password: ssu
email: ss_salesman@yourcompany.com
-
I added groups for Stock Salesman.
@@ -36,7 +34,6 @@
company_id: base.main_company
name: Stock User
login: sau
password: sau
email: stock_user@yourcompany.com
-
I added groups for Stock User.
@@ -51,8 +48,6 @@
company_id: base.main_company
name: Stock Manager
login: sam
password: sam
email: admin@portal.example.com
email: stock_manager@yourcompany.com
-
I added groups for Stock Manager.
+3 -3
View File
@@ -82,10 +82,10 @@ This installs the module product_expiry."""),
'group_uom': fields.boolean("Manage different units of measure for products",
implied_group='product.group_uom',
help="""Allows you to select and maintain different units of measure for products."""),
'group_uos': fields.boolean("Invoice products in a different unit of measure than the sales order",
'group_uos': fields.boolean("Store products in a different unit of measure than the sales order",
implied_group='product.group_uos',
help='Allows you to sell units of a product, but invoice based on a different unit of measure.\n'
'For instance, you can sell pieces of meat that you invoice based on their weight.'),
help='Allows you to store units of a product, but sell and invoice based on a different unit of measure.\n'
'For instance, you can store pieces of meat that you sell and invoice based on their weight.'),
'group_stock_packaging': fields.boolean("Allow to define several packaging methods on products",
implied_group='product.group_stock_packaging',
help="""Allows you to create and manage your packaging dimensions and types you want to be maintained in your system."""),
+13 -4
View File
@@ -759,6 +759,13 @@ class stock_picking(osv.osv):
res.add(move.picking_id.id)
return list(res)
def _get_pickings_dates_priority(self, cr, uid, ids, context=None):
res = set()
for move in self.browse(cr, uid, ids, context=context):
if move.picking_id and (not (move.picking_id.min_date < move.date_expected < move.picking_id.max_date) or move.priority > move.picking_id.priority):
res.add(move.picking_id.id)
return list(res)
def _get_pack_operation_exist(self, cr, uid, ids, field_name, arg, context=None):
res = {}
for pick in self.browse(cr, uid, ids, context=context):
@@ -819,12 +826,12 @@ class stock_picking(osv.osv):
* Cancelled: has been cancelled, can't be confirmed anymore"""
),
'priority': fields.function(get_min_max_date, multi="min_max_date", fnct_inv=_set_priority, type='selection', selection=procurement.PROCUREMENT_PRIORITIES, string='Priority',
store={'stock.move': (_get_pickings, ['priority', 'picking_id'], 20)}, states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, select=1, help="Priority for this picking. Setting manually a value here would set it as priority for all the moves",
store={'stock.move': (_get_pickings_dates_priority, ['priority', 'picking_id'], 20)}, states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, select=1, help="Priority for this picking. Setting manually a value here would set it as priority for all the moves",
track_visibility='onchange', required=True),
'min_date': fields.function(get_min_max_date, multi="min_max_date", fnct_inv=_set_min_date,
store={'stock.move': (_get_pickings, ['date_expected', 'picking_id'], 20)}, type='datetime', states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, string='Scheduled Date', select=1, help="Scheduled time for the first part of the shipment to be processed. Setting manually a value here would set it as expected date for all the stock moves.", track_visibility='onchange'),
store={'stock.move': (_get_pickings_dates_priority, ['date_expected', 'picking_id'], 20)}, type='datetime', states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, string='Scheduled Date', select=1, help="Scheduled time for the first part of the shipment to be processed. Setting manually a value here would set it as expected date for all the stock moves.", track_visibility='onchange'),
'max_date': fields.function(get_min_max_date, multi="min_max_date",
store={'stock.move': (_get_pickings, ['date_expected', 'picking_id'], 20)}, type='datetime', string='Max. Expected Date', select=2, help="Scheduled time for the last part of the shipment to be processed"),
store={'stock.move': (_get_pickings_dates_priority, ['date_expected', 'picking_id'], 20)}, type='datetime', string='Max. Expected Date', select=2, help="Scheduled time for the last part of the shipment to be processed"),
'date': fields.datetime('Creation Date', help="Creation Date, usually the time of the order", select=True, states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, track_visibility='onchange'),
'date_done': fields.datetime('Date of Transfer', help="Date of Completion", states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, copy=False),
'move_lines': fields.one2many('stock.move', 'picking_id', 'Internal Moves', states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, copy=True),
@@ -1800,7 +1807,9 @@ class stock_move(osv.osv):
'date': fields.datetime('Date', required=True, select=True, help="Move date: scheduled date until move is done, then date of actual move processing", states={'done': [('readonly', True)]}),
'date_expected': fields.datetime('Expected Date', states={'done': [('readonly', True)]}, required=True, select=True, help="Scheduled date for the processing of this move"),
'product_id': fields.many2one('product.product', 'Product', required=True, select=True, domain=[('type', '<>', 'service')], states={'done': [('readonly', True)]}),
'product_qty': fields.function(_quantity_normalize, fnct_inv=_set_product_qty, type='float', digits=0, store=True, string='Quantity',
'product_qty': fields.function(_quantity_normalize, fnct_inv=_set_product_qty, type='float', digits=0, store={
_name: (lambda self, cr, uid, ids, c={}: ids, ['product_id', 'product_uom', 'product_uom_qty'], 10),
}, string='Quantity',
help='Quantity in the default UoM of the product'),
'product_uom_qty': fields.float('Quantity', digits_compute=dp.get_precision('Product Unit of Measure'),
required=True, states={'done': [('readonly', True)]},
-2
View File
@@ -5,7 +5,6 @@
company_id: base.main_company
name: Stock Manager
login: sam
password: sam
email: stockmanager@yourcompany.com
-
I added groups for Stock Manager.
@@ -20,7 +19,6 @@
company_id: base.main_company
name: Stock User
login: sau
password: sau
email: stockuser@yourcompany.com
-
I added groups for Stock User.
+1 -1
View File
@@ -200,7 +200,7 @@ class stock_picking(osv.osv):
def __get_picking_move(self, cr, uid, ids, context={}):
res = []
for move in self.pool.get('stock.move').browse(cr, uid, ids, context=context):
if move.picking_id:
if move.picking_id and move.invoice_state != move.picking_id.invoice_state:
res.append(move.picking_id.id)
return res
+1 -1
View File
@@ -753,7 +753,7 @@ instance.web.DataSetStatic = instance.web.DataSet.extend({
var offset = options.offset || 0,
limit = options.limit || false;
var end_pos = limit && limit !== -1 ? offset + limit : this.ids.length;
return this.read_ids(this.ids.slice(offset, end_pos), fields);
return this.read_ids(this.ids.slice(offset, end_pos), fields, options);
},
set_ids: function (ids) {
this.ids = ids;
+5 -1
View File
@@ -4383,8 +4383,12 @@ instance.web.form.One2ManyViewManager = instance.web.ViewManager.extend({
});
instance.web.form.One2ManyDataSet = instance.web.BufferedDataSet.extend({
get_context: function() {
get_context: function(extra_context) {
this.context = this.o2m.build_context();
if(extra_context)
{
this.context.add(extra_context);
}
return this.context;
}
});
+4 -2
View File
@@ -2312,7 +2312,7 @@ instance.web.list.Binary = instance.web.list.Column.extend({
* @private
*/
_format: function (row_data, options) {
var text = _t("Download");
var text = _t("Download"), filename=_t('Binary file');
var value = row_data[this.id].value;
if (!value) {
return options.value_if_empty || '';
@@ -2330,11 +2330,13 @@ instance.web.list.Binary = instance.web.list.Column.extend({
if (this.filename && row_data[this.filename]) {
text = _.str.sprintf(_t("Download \"%s\""), instance.web.format_value(
row_data[this.filename].value, {type: 'char'}));
filename = row_data[this.filename].value;
}
return _.template('<a href="<%-href%>"><%-text%></a> (<%-size%>)')({
return _.template('<a download="<%-download%>" href="<%-href%>"><%-text%></a> (<%-size%>)')({
text: text,
href: download_url,
size: instance.web.binary_to_binsize(value),
download: filename,
});
}
});
+4 -3
View File
@@ -933,17 +933,18 @@ class website_sale(http.Controller):
for line in order_lines:
ret.append({
'id': line.order_id and line.order_id.id,
'name': line.product_id.categ_id and line.product_id.categ_id.name or '-',
'sku': line.product_id.id,
'quantity': line.product_uom_qty,
'name': line.product_id.name or '-',
'category': line.product_id.categ_id and line.product_id.categ_id.name or '-',
'price': line.price_unit,
'quantity': line.product_uom_qty,
})
return ret
@http.route(['/shop/tracking_last_order'], type='json', auth="public")
def tracking_cart(self, **post):
""" return data about order in JSON needed for google analytics"""
cr, uid, context = request.cr, request.uid, request.context
cr, context = request.cr, request.context
ret = {}
sale_order_id = request.session.get('sale_last_order_id')
if sale_order_id:
+16
View File
@@ -0,0 +1,16 @@
Georgia, 2015-06-30
Delta Comm LLC agrees to the terms of the Odoo Corporate Contributor License
Agreement v1.0.
I declare that I am authorized and able to make this agreement and sign this
declaration.
Signed,
Karlo Matitaishvili kmatitaishvili@delta-comm.ge https://github.com/kmatitaishvili
List of contributors:
Temur Vibliani tvibliani@delta-comm.ge https://github.com/tvibliani
Mikheil Tutberidze mtutberidze@delta-comm.ge https://github.com/mtutberidze
+15
View File
@@ -0,0 +1,15 @@
France, 2015 June 25
META-IT agrees to the terms of the Odoo Corporate Contributor License
Agreement v1.0.
I declare that I am authorized and able to make this agreement and sign this
declaration.
Signed,
Robin Lucbenet robin@meta-it.fr https://github.com/n1b0r
List of contributors:
Guillaume Masson guillaume.masson@meta-it.fr
+15
View File
@@ -0,0 +1,15 @@
Canada, 25-06-2015
OERP Canada agrees to the terms of the Odoo Corporate Contributor License
Agreement v1.0.
I declare that I am authorized and able to make this agreement and sign this
declaration.
Signed,
Daniel Dico ddico@oerp.ca https://github.com/ddico
List of contributors:
Daniel Dico ddico@oerp.ca https://github.com/ddico
+13
View File
@@ -0,0 +1,13 @@
Brazil, 2015-06-25
Uhlig & Korovsky Tecnologia Ltda - ME agrees to the terms of the Odoo Corporate Contributor License Agreement v1.0.
I declare that I am authorized and able to make this agreement and sign this declaration.
Signed,
Carlos Alberto Cipriano Korovsky contato@uktech.com.br https://github.com/uktechbr
List of contributors:
Carlos Alberto Cipriano Korovsky carlos.korovsky@uktech.com.br https://github.com/carlos-korovsky
+13
View File
@@ -0,0 +1,13 @@
Lithuania, 2015-06-29
Via laurea agrees to the terms of the Odoo Corporate Contributor License Agreement v1.0.
I declare that I am authorized and able to make this agreement and sign this declaration.
Signed,
Saulius Zilys saulius@vialaurea.lt https://github.com/realsaiko
List of contributors:
Saulius Zilys saulius@vialaurea.lt https://github.com/realsaiko
+11
View File
@@ -0,0 +1,11 @@
Germany, 2015-06-12
I hereby agree to the terms of the Odoo Individual Contributor License
Agreement v1.0.
I declare that I am authorized and able to make this agreement and sign this
declaration.
Signed,
Max Hellwig max.hellwig@datenbetrieb.de https://github.com/Ichag
+11
View File
@@ -0,0 +1,11 @@
Australia, 17 May 2015
I hereby agree to the terms of the Odoo Individual Contributor License
Agreement v1.0.
I declare that I am authorized and able to make this agreement and sign this
declaration.
Signed,
Bevan Weiss bevan.weiss@gmail.com https://github.com/bevanweiss
+11
View File
@@ -0,0 +1,11 @@
Spain, 2015-06-24
I hereby agree to the terms of the Odoo Individual Contributor License
Agreement v1.0.
I declare that I am authorized and able to make this agreement and sign this
declaration.
Signed,
Endika Iglesias endika2@gmail.com https://github.com/endika
+11
View File
@@ -0,0 +1,11 @@
France, 2015-06-29
I hereby agree to the terms of the Odoo Individual Contributor License
Agreement v1.0.
I declare that I am authorized and able to make this agreement and sign this
declaration.
Signed,
Florent THOMAS florent.thomas@mind-and-go.com https://github.com/flotho
+11
View File
@@ -0,0 +1,11 @@
Poland, 2015-05-25
I hereby agree to the terms of the Odoo Individual Contributor License
Agreement v1.0.
I declare that I am authorized and able to make this agreement and sign this
declaration.
Signed,
Ludwik Trammer ludwik@gmail.com https://github.com/ludwiktrammer
+1 -1
View File
@@ -8,4 +8,4 @@ declaration.
Signed,
Nicolas Bustillos nicolas.bustillos@poiesisconsulting.com https://github.com/nicobustillos
Nicolas Bustillos nicobustillos@users.noreply.github.com https://github.com/nicobustillos
+1 -1
View File
@@ -8,4 +8,4 @@ declaration.
Signed,
Nicolas Piganeau nicolas.piganeau@ndp-systemes.fr https://github.com/npiganeau
Nicolas Piganeau npi@m4x.org https://github.com/npiganeau
+11
View File
@@ -0,0 +1,11 @@
Vietnam, 2015-05-27
I hereby agree to the terms of the Odoo Individual Contributor License
Agreement v1.0.
I declare that I am authorized and able to make this agreement and sign this
declaration.
Signed,
Tam Vu vumhtam@gmail.com https://github.com/vuamitom
+2 -2
View File
@@ -266,7 +266,7 @@ class view(osv.osv):
# Sanity checks: the view should not break anything upon rendering!
# Any exception raised below will cause a transaction rollback.
for view in self.browse(cr, uid, ids, context):
view_def = self.read_combined(cr, uid, view.id, None, context=context)
view_def = self.read_combined(cr, uid, view.id, ['arch'], context=context)
view_arch_utf8 = view_def['arch']
if view.type != 'qweb':
view_doc = etree.fromstring(view_arch_utf8)
@@ -595,7 +595,7 @@ class view(osv.osv):
# arch and model fields are always returned
if fields:
fields = list(set(fields) | set(['arch', 'model']))
fields = list({'arch', 'model'}.union(fields))
# read the view arch
[view] = self.read(cr, uid, [root_id], fields=fields, context=context)
@@ -428,6 +428,7 @@
<field name="name">Finland</field>
<field name="code">fi</field>
<field name="image" type="base64" file="base/static/img/country_flags/fi.png"></field>
<field name="address_format" eval="'%(street)s\n%(street2)s\n%(zip)s %(city)s\n%(country_name)s'" />
<field name="currency_id" ref="EUR"/>
</record>
<record id="fj" model="res.country">
+7
View File
@@ -61,6 +61,13 @@ class Start(Command):
if '--db-filter' not in cmdargs:
cmdargs.append('--db-filter=^%s$' % args.db_name)
# Remove --path /-p options from the command arguments
def to_remove(i, l):
return l[i] == '-p' or l[i].startswith('--path') or \
(i > 0 and l[i-1] in ['-p', '--path'])
cmdargs = [v for i, v in enumerate(cmdargs)
if not to_remove(i, cmdargs)]
main(cmdargs)
def die(message, code=1):
+5 -2
View File
@@ -1194,8 +1194,11 @@ class BaseModel(object):
type = 'warning' if isinstance(exception, Warning) else 'error'
# logs the logical (not human-readable) field name for automated
# processing of response, but injects human readable in message
record = dict(base, type=type, field=field,
message=unicode(exception.args[0]) % base)
# Before applying string substitution, we need to escape all '%'
# characters that are not part of substitutable reference.
regex = '%%(?!\((%s)\)s)' % '|'.join(base.keys())
message = unicode(re.sub(regex, '%%', exception.args[0])) % base
record = dict(base, type=type, field=field, message=message)
if len(exception.args) > 1 and exception.args[1]:
record.update(exception.args[1])
log(record)
+2
View File
@@ -1591,6 +1591,8 @@ class sparse(function):
"""
if self._type == 'many2many':
if not value:
return []
assert value[0][0] == 6, 'Unsupported m2m value for sparse field: %s' % value
return value[0][2]
+5 -7
View File
@@ -129,16 +129,14 @@ def image_save_for_web(image, fp=None, format=None):
opt = dict(format=image.format or format)
if image.format == 'PNG':
opt.update(optimize=True)
alpha = False
if image.mode in ('RGBA', 'LA') or (image.mode == 'P' and 'transparency' in image.info):
alpha = image.convert('RGBA').split()[-1]
if image.mode != 'P':
# Get the alpha band
alpha = image.split()[-1]
# Floyd Steinberg dithering by default
image = image.convert('RGBA').convert('P', palette=Image.WEB, colors=256)
# Set all pixel values below 128 to 255 and the rest to 0
mask = Image.eval(alpha, lambda a: 255 if a <=128 else 0)
# Paste the color of index 255 and use alpha as a mask
image.paste(255, mask)
opt.update(transparency=255)
if alpha:
image.putalpha(alpha)
elif image.format == 'JPEG':
opt.update(optimize=True, quality=80)
if fp:
+3 -3
View File
@@ -316,10 +316,10 @@ class YamlInterpreter(object):
if not self._coerce_bool(record.forcecreate):
return None
#context = self.get_context(record, self.eval_context)
#TOFIX: record.context like {'withoutemployee':True} should pass from self.eval_context. example: test_project.yml in project module
context = record.context
# FIXME: record.context like {'withoutemployee':True} should pass from self.eval_context. example: test_project.yml in project module
# TODO: cleaner way to avoid resetting password in auth_signup (makes user creation costly)
context = dict(record.context or {}, no_reset_password=True)
view_info = False
if view_id:
varg = view_id