[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 *.js
recursive-include openerp *.less recursive-include openerp *.less
recursive-include openerp *.md recursive-include openerp *.md
recursive-include openerp *.mp3
recursive-include openerp *.png recursive-include openerp *.png
recursive-include openerp *.po recursive-include openerp *.po
recursive-include openerp *.rml recursive-include openerp *.rml
+7 -3
View File
@@ -1166,13 +1166,15 @@ class account_move(osv.osv):
_order = 'id desc' _order = 'id desc'
def account_assert_balanced(self, cr, uid, context=None): 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("""\ cr.execute("""\
SELECT move_id SELECT move_id
FROM account_move_line FROM account_move_line
WHERE state = 'valid' WHERE state = 'valid'
GROUP BY move_id 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, \ assert len(cr.fetchall()) == 0, \
"For all Journal Items, the state is valid implies that the sum " \ "For all Journal Items, the state is valid implies that the sum " \
"of credits equals the sum of debits" "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 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_analytic_line = self.pool.get('account.analytic.line')
obj_move_line = self.pool.get('account.move.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): for move in self.browse(cr, uid, ids, context):
journal = move.journal_id journal = move.journal_id
amount = 0 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): 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)) 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 # If the move is balanced
# Add to the list of valid moves # Add to the list of valid moves
# (analytic lines will be created later for 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 i[2]['period_id'] = period.id
ctx['invoice'] = inv 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 # make the invoice point to that move
vals = { vals = {
'move_id': move.id, '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, 'journal_id': obj_line.journal_id.analytic_journal_id.id,
'ref': obj_line.ref, 'ref': obj_line.ref,
'move_id': obj_line.id, '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): def create_analytic_lines(self, cr, uid, ids, context=None):
@@ -995,7 +995,7 @@ class account_move_line(osv.osv):
if context is None: if context is None:
context = {} context = {}
company_list = [] 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: 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.')) raise UserError(_('To reconcile the entries company should be the same for all entries.'))
company_list.append(line.company_id.id) company_list.append(line.company_id.id)
+1 -3
View File
@@ -5,7 +5,6 @@
company_id: base.main_company company_id: base.main_company
name: Accountant name: Accountant
login: acc login: acc
password: acc
email: accountuser@yourcompany.com email: accountuser@yourcompany.com
- -
I added groups for Accountant. I added groups for Accountant.
@@ -21,7 +20,6 @@
company_id: base.main_company company_id: base.main_company
name: Financial Manager name: Financial Manager
login: fm login: fm
password: fm
email: accountmanager@yourcompany.com email: accountmanager@yourcompany.com
- -
I added groups for Financial Manager. I added groups for Financial Manager.
@@ -29,4 +27,4 @@
!record {model: res.users, id: res_users_account_manager}: !record {model: res.users, id: res_users_account_manager}:
groups_id: groups_id:
- account.group_account_manager - 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 result = 0.0
if context is None: if context is None:
context = {} context = {}
account_obj = self.pool.get('account.account')
for line in self.browse(cr, uid, ids, context=context): for line in self.browse(cr, uid, ids, context=context):
acc_ids = [x.id for x in line.general_budget_id.account_ids] acc_ids = [x.id for x in line.general_budget_id.account_ids]
if not acc_ids: if not acc_ids:
raise UserError(_("The Budget '%s' has no accounts!") % ustr(line.general_budget_id.name)) 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_to = line.date_to
date_from = line.date_from date_from = line.date_from
if line.analytic_account_id.id: if line.analytic_account_id.id:
+1 -1
View File
@@ -227,8 +227,8 @@ class account_voucher(osv.osv):
if not ids: return {} if not ids: return {}
currency_obj = self.pool.get('res.currency') currency_obj = self.pool.get('res.currency')
res = {} res = {}
debit = credit = 0.0
for voucher in self.browse(cr, uid, ids, context=context): for voucher in self.browse(cr, uid, ids, context=context):
debit = credit = 0.0
sign = voucher.type == 'payment' and -1 or 1 sign = voucher.type == 'payment' and -1 or 1
for l in voucher.line_dr_ids: for l in voucher.line_dr_ids:
debit += l.amount debit += l.amount
@@ -5,7 +5,6 @@
company_id: base.main_company company_id: base.main_company
name: Voucher Accountant name: Voucher Accountant
login: vacc login: vacc
password: acc
email: accountant@yourcompany.com email: accountant@yourcompany.com
- -
I added groups to Accountant for account voucher. I added groups to Accountant for account voucher.
@@ -21,7 +20,6 @@
company_id: base.main_company company_id: base.main_company
name: Financial Manager for voucher name: Financial Manager for voucher
login: fmv login: fmv
password: fmv
email: finmanager@yourcompany.com email: finmanager@yourcompany.com
- -
I added groups to Financial Manager for account voucher. I added groups to Financial Manager for account voucher.
-2
View File
@@ -6,8 +6,6 @@
<record id="default_template_user" model="res.users"> <record id="default_template_user" model="res.users">
<field name="name">Template User</field> <field name="name">Template User</field>
<field name="login">portaltemplate</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"/> <field name="active" eval="False"/>
<!-- Avoid auto-including this user in any default group, just like a typical portal member --> <!-- 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')])]"/> <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: if not user_ids:
user_ids = self.search(cr, uid, [('email', '=', login)], context=context) user_ids = self.search(cr, uid, [('email', '=', login)], context=context)
if len(user_ids) != 1: 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) return self.action_reset_password(cr, uid, user_ids, context=context)
def action_reset_password(self, cr, uid, ids, context=None): def action_reset_password(self, cr, uid, ids, context=None):
@@ -5,7 +5,6 @@
company_id: base.main_company company_id: base.main_company
name: Crm Sales manager name: Crm Sales manager
login: csm login: csm
password: csm
email: crmmanager@yourcompany.com email: crmmanager@yourcompany.com
- -
I added groups for Crm Salesmanager. I added groups for Crm Salesmanager.
@@ -20,7 +19,6 @@
company_id: base.main_company company_id: base.main_company
name: Crm Salesman name: Crm Salesman
login: csu login: csu
password: csu
email: crmuser@yourcompany.com email: crmuser@yourcompany.com
- -
I added groups for Crm Salesman. I added groups for Crm Salesman.
@@ -4,22 +4,18 @@
!record {model: res.users, id: test_res_user_01}: !record {model: res.users, id: test_res_user_01}:
name: 'Test user A' name: 'Test user A'
login: 'tua@example.com' login: 'tua@example.com'
new_password: 'tua'
- -
!record {model: res.users, id: test_res_user_02}: !record {model: res.users, id: test_res_user_02}:
name: 'Test user B' name: 'Test user B'
login: 'tub@example.com' login: 'tub@example.com'
new_password: 'tub'
- -
!record {model: res.users, id: test_res_user_03}: !record {model: res.users, id: test_res_user_03}:
name: 'Test user C' name: 'Test user C'
login: 'tuc@example.com' login: 'tuc@example.com'
new_password: 'tuc'
- -
!record {model: res.users, id: test_res_user_04}: !record {model: res.users, id: test_res_user_04}:
name: 'Test user D' name: 'Test user D'
login: 'tud@example.com' login: 'tud@example.com'
new_password: 'tud'
- -
Salesman also creates lead so giving access rights of salesman. 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 # not using advanced pricing per destination: override grid
grid_id = grid_pool.search(cr, uid, [('carrier_id', '=', record.id)], context=context) 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_pool.unlink(cr, uid, grid_id, context=context)
grid_id = None grid_id = None
# Check that float, else 0.0 is False if not (record.normal_price is not False or record.free_if_more_than):
if not (isinstance(record.normal_price,float) or record.free_if_more_than):
continue continue
if not grid_id: if not grid_id:
@@ -145,7 +144,7 @@ class delivery_carrier(osv.osv):
'list_price': 0.0, 'list_price': 0.0,
} }
grid_line_pool.create(cr, uid, line_data, context=context) 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 = { line_data = {
'grid_id': grid_id and grid_id[0], 'grid_id': grid_id and grid_id[0],
'name': _('Default price'), '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') acc_fp_obj = self.pool.get('account.fiscal.position')
self._delivery_unset(cr, uid, ids, context=context) self._delivery_unset(cr, uid, ids, context=context)
currency_obj = self.pool.get('res.currency') currency_obj = self.pool.get('res.currency')
line_ids = []
for order in self.browse(cr, uid, ids, context=context): 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) grid_id = carrier_obj.grid_get(cr, uid, [order.carrier_id.id], order.partner_shipping_id.id)
if not grid_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 = 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)) price_unit, context=dict(context or {}, date=order.date_order))
#create the sale order line #create the sale order line
line_obj.create(cr, uid, { line_id = line_obj.create(cr, uid, {
'order_id': order.id, 'order_id': order.id,
'name': grid.carrier_id.name, 'name': grid.carrier_id.name,
'product_uom_qty': 1, 'product_uom_qty': 1,
@@ -95,3 +96,5 @@ class sale_order(osv.Model):
'tax_id': [(6, 0, taxes_ids)], 'tax_id': [(6, 0, taxes_ids)],
'is_delivery': True 'is_delivery': True
}, context=context) }, context=context)
line_ids.append(line_id)
return line_ids
-2
View File
@@ -5,7 +5,6 @@
company_id: base.main_company company_id: base.main_company
name: Event manager name: Event manager
login: em login: em
password: em
email: eventmanager@yourcompany.com email: eventmanager@yourcompany.com
- -
I added groups for Event manager. I added groups for Event manager.
@@ -20,7 +19,6 @@
company_id: base.main_company company_id: base.main_company
name: User name: User
login: eu login: eu
password: eu
email: eventuser@yourcompany.com email: eventuser@yourcompany.com
- -
I added groups for Event user. I added groups for Event user.
+5 -4
View File
@@ -202,6 +202,8 @@ class google_calendar(osv.AbstractModel):
_name = 'google.%s' % STR_SERVICE _name = 'google.%s' % STR_SERVICE
def generate_data(self, cr, uid, event, isCreating=False, context=None): def generate_data(self, cr, uid, event, isCreating=False, context=None):
if not context:
context = {}
if event.allday: 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] 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] 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", "method": "email" if alarm.type == "email" else "popup",
"minutes": alarm.duration_minutes "minutes": alarm.duration_minutes
}) })
data = { data = {
"summary": event.name or '', "summary": event.name or '',
"description": event.description or '', "description": event.description or '',
"start": { "start": {
type: start_date, type: start_date,
vstype: None, vstype: None,
'timeZone': 'UTC' 'timeZone': context.get('tz', 'UTC'),
}, },
"end": { "end": {
type: final_date, type: final_date,
vstype: None, vstype: None,
'timeZone': 'UTC' 'timeZone': context.get('tz', 'UTC'),
}, },
"attendees": attendee_list, "attendees": attendee_list,
"reminders": { "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)) 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'} 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['sequence'] = google_event.get('sequence', 0)
data_json = simplejson.dumps(data) data_json = simplejson.dumps(data)
-3
View File
@@ -5,7 +5,6 @@
company_id: base.main_company company_id: base.main_company
name: HR manager name: HR manager
login: hrm login: hrm
password: hrm
- -
I added groups for HR Manager. I added groups for HR Manager.
- -
@@ -19,7 +18,6 @@
company_id: base.main_company company_id: base.main_company
name: HR Officer name: HR Officer
login: hro login: hro
password: hro
email: hro@example.com email: hro@example.com
- -
I added groups for HR Officer. I added groups for HR Officer.
@@ -34,7 +32,6 @@
company_id: base.main_company company_id: base.main_company
name: Employee name: Employee
login: emp login: emp
password: emp
- -
I added groups for Employee. I added groups for Employee.
- -
@@ -5,7 +5,6 @@
company_id: base.main_company company_id: base.main_company
name: HR Officer name: HR Officer
login: ao login: ao
password: ao
- -
I added groups for HR Attendance Officer. 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), 'employee_id': fields.many2one("hr.employee", string='Employee', required=True),
'user_id': fields.related("employee_id", "user_id", 'user_id': fields.related("employee_id", "user_id",
type="many2one", relation="res.users", 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): def action_grant_badge(self, cr, uid, ids, context=None):
@@ -5,7 +5,6 @@
company_id: base.main_company company_id: base.main_company
name: HR Recruitment Officer name: HR Recruitment Officer
login: hrro login: hrro
password: hrro
email: hrofcr@yourcompany.com email: hrofcr@yourcompany.com
- -
I added groups for HR Recruitment Officer. I added groups for HR Recruitment Officer.
@@ -5,7 +5,6 @@
company_id: base.main_company company_id: base.main_company
name: HR timesheet manager name: HR timesheet manager
login: hrtm login: hrtm
password: hrtm
- -
I added groups for HR timesheet Manager. I added groups for HR timesheet Manager.
- -
@@ -19,7 +18,6 @@
company_id: base.main_company company_id: base.main_company
name: HR timesheet Officer name: HR timesheet Officer
login: hrto login: hrto
password: hrto
- -
I added groups for HR timesheet Officer. I added groups for HR timesheet Officer.
- -
@@ -33,7 +31,6 @@
company_id: base.main_company company_id: base.main_company
name: Timesheet Employee name: Timesheet Employee
login: empt login: empt
password: empt
- -
I added groups for Timesheet Employee. I added groups for Timesheet Employee.
- -
@@ -108,7 +108,7 @@
</page> </page>
<page string="Details"> <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"> <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 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 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"/> <field name="name"/>
+3
View File
@@ -3589,6 +3589,7 @@
<field name="type">other</field> <field name="type">other</field>
<field name="user_type" ref="account.data_account_type_payable"/> <field name="user_type" ref="account.data_account_type_payable"/>
<field ref="a44" name="parent_id"/> <field ref="a44" name="parent_id"/>
<field name="financial_report_ids" eval="[(4,ref('account_financial_report_fournisseurs4'))]"/>
</record> </record>
<record id="a446" model="account.account.template"> <record id="a446" model="account.account.template">
<field name="name">Acomptes reçus</field> <field name="name">Acomptes reçus</field>
@@ -3596,6 +3597,7 @@
<field name="type">other</field> <field name="type">other</field>
<field name="user_type" ref="account.data_account_type_payable"/> <field name="user_type" ref="account.data_account_type_payable"/>
<field ref="a44" name="parent_id"/> <field ref="a44" name="parent_id"/>
<field name="financial_report_ids" eval="[(4,ref('account_financial_report_fournisseurs4'))]"/>
</record> </record>
<record id="a448" model="account.account.template"> <record id="a448" model="account.account.template">
<field name="name">Compensations fournisseurs</field> <field name="name">Compensations fournisseurs</field>
@@ -3603,6 +3605,7 @@
<field name="type">other</field> <field name="type">other</field>
<field name="user_type" ref="account.data_account_type_payable"/> <field name="user_type" ref="account.data_account_type_payable"/>
<field ref="a44" name="parent_id"/> <field ref="a44" name="parent_id"/>
<field name="financial_report_ids" eval="[(4,ref('account_financial_report_fournisseurs4'))]"/>
</record> </record>
<record id="a45" model="account.account.template"> <record id="a45" model="account.account.template">
<field name="name">DETTES FISCALES, SALARIALES ET SOCIALES</field> <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"/> <field name="parent_id" ref="vat_code_balance_net"/>
</record> </record>
<record model="account.tax.code.template" id="vat_code_due_tva80"> <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="code">301b</field>
<field name="parent_id" ref="vat_code_due_tva"/> <field name="parent_id" ref="vat_code_due_tva"/>
</record> </record>
<record model="account.tax.code.template" id="vat_code_due_tva25"> <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="code">311b</field>
<field name="parent_id" ref="vat_code_due_tva"/> <field name="parent_id" ref="vat_code_due_tva"/>
</record> </record>
<record model="account.tax.code.template" id="vat_code_due_tva38"> <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="code">341b</field>
<field name="parent_id" ref="vat_code_due_tva"/> <field name="parent_id" ref="vat_code_due_tva"/>
</record> </record>
@@ -57,22 +57,22 @@
<field name="parent_id" ref="vat_code_base_ca_total"/> <field name="parent_id" ref="vat_code_base_ca_total"/>
</record> </record>
<record model="account.tax.code.template" id="vat_code_due_80"> <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="code">301a</field>
<field name="parent_id" ref="vat_code_base_due"/> <field name="parent_id" ref="vat_code_base_due"/>
</record> </record>
<record model="account.tax.code.template" id="vat_code_due_25"> <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="code">311a</field>
<field name="parent_id" ref="vat_code_base_due"/> <field name="parent_id" ref="vat_code_base_due"/>
</record> </record>
<record model="account.tax.code.template" id="vat_code_due_38"> <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="code">341a</field>
<field name="parent_id" ref="vat_code_base_due"/> <field name="parent_id" ref="vat_code_base_due"/>
</record> </record>
<record model="account.tax.code.template" id="vat_code_due_0"> <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="code">200-220</field>
<field name="parent_id" ref="vat_code_base_ca_total"/> <field name="parent_id" ref="vat_code_base_ca_total"/>
</record> </record>
@@ -82,52 +82,57 @@
<field name="parent_id" ref="vat_code_base_ca_total"/> <field name="parent_id" ref="vat_code_base_ca_total"/>
</record> </record>
<record model="account.tax.code.template" id="vat_code_receivable_net"> <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="code"/>
<field name="parent_id" ref="vat_code_base_net"/> <field name="parent_id" ref="vat_code_base_net"/>
</record> </record>
<record model="account.tax.code.template" id="vat_code_receivable_base"> <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="code"/>
<field name="parent_id" ref="vat_code_receivable_net"/> <field name="parent_id" ref="vat_code_receivable_net"/>
</record> </record>
<record model="account.tax.code.template" id="vat_code_receivable_base_0"> <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="name">Importations</field>
<field name="code">Babs0</field> <field name="code">imp</field>
<field name="parent_id" ref="vat_code_receivable_base"/> <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>
<record model="account.tax.code.template" id="vat_code_receivable_base_80"> <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="code">Babs8</field>
<field name="parent_id" ref="vat_code_receivable_base"/> <field name="parent_id" ref="vat_code_receivable_base"/>
</record> </record>
<record model="account.tax.code.template" id="vat_code_receivable_base_25"> <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="code">Babs25</field>
<field name="parent_id" ref="vat_code_receivable_base"/> <field name="parent_id" ref="vat_code_receivable_base"/>
</record> </record>
<record model="account.tax.code.template" id="vat_code_receivable_base_38"> <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="code">Babs38</field>
<field name="parent_id" ref="vat_code_receivable_base"/> <field name="parent_id" ref="vat_code_receivable_base"/>
</record> </record>
<record model="account.tax.code.template" id="vat_code_receivable_base_invest"> <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="code"/>
<field name="parent_id" ref="vat_code_receivable_net"/> <field name="parent_id" ref="vat_code_receivable_net"/>
</record> </record>
<record model="account.tax.code.template" id="vat_code_receivable_base_invest80"> <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="code">Binv8</field>
<field name="parent_id" ref="vat_code_receivable_base_invest"/> <field name="parent_id" ref="vat_code_receivable_base_invest"/>
</record> </record>
<record model="account.tax.code.template" id="vat_code_receivable_base_invest25"> <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="code">Binv25</field>
<field name="parent_id" ref="vat_code_receivable_base_invest"/> <field name="parent_id" ref="vat_code_receivable_base_invest"/>
</record> </record>
<record model="account.tax.code.template" id="vat_code_receivable_base_invest38"> <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="code">Binv38</field>
<field name="parent_id" ref="vat_code_receivable_base_invest"/> <field name="parent_id" ref="vat_code_receivable_base_invest"/>
</record> </record>
@@ -135,7 +140,7 @@
# TVA - Taxe sur la Valeur Ajoutée # TVA - Taxe sur la Valeur Ajoutée
--> -->
<record model="account.tax.template" id="vat_25"> <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="description">2.5%</field>
<field name="amount" eval="0.025"/> <field name="amount" eval="0.025"/>
<field name="type">percent</field> <field name="type">percent</field>
@@ -152,8 +157,27 @@
<field name="account_paid_id" ref="ch_coa_2200"/> <field name="account_paid_id" ref="ch_coa_2200"/>
<field name="type_tax_use">sale</field> <field name="type_tax_use">sale</field>
</record> </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"> <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="description">2.5% achat</field>
<field name="amount" eval="0.025"/> <field name="amount" eval="0.025"/>
<field name="type">percent</field> <field name="type">percent</field>
@@ -171,9 +195,30 @@
<field name="type_tax_use">purchase</field> <field name="type_tax_use">purchase</field>
<field name="account_collected_id" ref="ch_coa_1170"/> <field name="account_collected_id" ref="ch_coa_1170"/>
<field name="account_paid_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"> <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="description">2.5% invest.</field>
<field name="amount" eval="0.025"/> <field name="amount" eval="0.025"/>
<field name="type">percent</field> <field name="type">percent</field>
@@ -192,9 +237,29 @@
<field name="account_collected_id" ref="ch_coa_1171"/> <field name="account_collected_id" ref="ch_coa_1171"/>
<field name="account_paid_id" ref="ch_coa_1171"/> <field name="account_paid_id" ref="ch_coa_1171"/>
</record> </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"> <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="description">3.8%</field>
<field name="amount" eval="0.038"/> <field name="amount" eval="0.038"/>
<field name="type">percent</field> <field name="type">percent</field>
@@ -213,8 +278,29 @@
<field name="account_collected_id" ref="ch_coa_2200"/> <field name="account_collected_id" ref="ch_coa_2200"/>
<field name="account_paid_id" ref="ch_coa_2200"/> <field name="account_paid_id" ref="ch_coa_2200"/>
</record> </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"> <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="description">3.8% achat</field>
<field name="amount" eval="0.038"/> <field name="amount" eval="0.038"/>
<field name="type">percent</field> <field name="type">percent</field>
@@ -233,8 +319,29 @@
<field name="account_collected_id" ref="ch_coa_1170"/> <field name="account_collected_id" ref="ch_coa_1170"/>
<field name="account_paid_id" ref="ch_coa_1170"/> <field name="account_paid_id" ref="ch_coa_1170"/>
</record> </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"> <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="description">3.8% invest</field>
<field name="amount" eval="0.038"/> <field name="amount" eval="0.038"/>
<field name="type">percent</field> <field name="type">percent</field>
@@ -253,8 +360,29 @@
<field name="account_collected_id" ref="ch_coa_1171"/> <field name="account_collected_id" ref="ch_coa_1171"/>
<field name="account_paid_id" ref="ch_coa_1171"/> <field name="account_paid_id" ref="ch_coa_1171"/>
</record> </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"> <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="description">8.0%</field>
<field name="amount" eval="0.080"/> <field name="amount" eval="0.080"/>
<field name="sequence" eval="0"/> <field name="sequence" eval="0"/>
@@ -275,7 +403,7 @@
<field name="account_paid_id" ref="ch_coa_2200"/> <field name="account_paid_id" ref="ch_coa_2200"/>
</record> </record>
<record model="account.tax.template" id="vat_80_purchase"> <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="description">8.0% achat</field>
<field name="amount" eval="0.080"/> <field name="amount" eval="0.080"/>
<field name="type">percent</field> <field name="type">percent</field>
@@ -294,9 +422,52 @@
<field name="type_tax_use">purchase</field> <field name="type_tax_use">purchase</field>
<field name="account_collected_id" ref="ch_coa_1170"/> <field name="account_collected_id" ref="ch_coa_1170"/>
<field name="account_paid_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"> <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="description">8.0% invest.</field>
<field name="amount" eval="0.080"/> <field name="amount" eval="0.080"/>
<field name="type">percent</field> <field name="type">percent</field>
@@ -315,6 +486,27 @@
<field name="account_collected_id" ref="ch_coa_1171"/> <field name="account_collected_id" ref="ch_coa_1171"/>
<field name="account_paid_id" ref="ch_coa_1171"/> <field name="account_paid_id" ref="ch_coa_1171"/>
</record> </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"> <record model="account.tax.template" id="vat_XO">
<field name="name">TVA due a 0% (Exportations)</field> <field name="name">TVA due a 0% (Exportations)</field>
<field name="amount" eval="0.00"/> <field name="amount" eval="0.00"/>
@@ -334,8 +526,8 @@
<field name="account_paid_id" ref="ch_coa_2200"/> <field name="account_paid_id" ref="ch_coa_2200"/>
</record> </record>
<record model="account.tax.template" id="vat_O_exclude"> <record model="account.tax.template" id="vat_O_exclude">
<field name="name">TVA 0% exclue</field> <field name="name">TVA exclue/ventes</field>
<field name="description">0% excl.</field> <field name="description">exclue</field>
<field name="amount" eval="0.00"/> <field name="amount" eval="0.00"/>
<field name="type">percent</field> <field name="type">percent</field>
<field name="base_code_id" ref="vat_code_due_0_exclu"/> <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_collected_id" ref="ch_coa_2200"/>
<field name="account_paid_id" ref="ch_coa_2200"/> <field name="account_paid_id" ref="ch_coa_2200"/>
</record> </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"> <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="description">0% import.</field>
<field name="amount" eval="0.00"/> <field name="amount" eval="0.00"/>
<field name="type">percent</field> <field name="type">percent</field>
@@ -371,8 +579,25 @@
</record> </record>
<!--# 100% on import !! the tax percentage is 00--> <!--# 100% on import !! the tax percentage is 00-->
<record model="account.tax.template" id="vat_100_import"> <record model="account.tax.template" id="vat_100_import">
<field name="name">100% dédouanement TVA</field> <field name="name">100% dédouanement TVA sur invest. et autres ch.</field>
<field name="description">100% imp.</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="amount" eval="0.0"/>
<field name="type">percent</field> <field name="type">percent</field>
<field name="base_code_id" ref="vat_code_payable_bs"/> <field name="base_code_id" ref="vat_code_payable_bs"/>
@@ -383,8 +608,8 @@
<field name="ref_tax_sign" eval="-1.0"/> <field name="ref_tax_sign" eval="-1.0"/>
<field name="chart_template_id" ref="l10nch_chart_template"/> <field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">purchase</field> <field name="type_tax_use">purchase</field>
<field name="account_collected_id" ref="ch_coa_1171"/> <field name="account_collected_id" ref="ch_coa_1170"/>
<field name="account_paid_id" ref="ch_coa_1171"/> <field name="account_paid_id" ref="ch_coa_1170"/>
</record> </record>
</data> </data>
</openerp> </openerp>
+24 -11
View File
@@ -446,6 +446,9 @@ class mail_thread(osv.AbstractModel):
cascaded, because link is done through (res_model, res_id). """ cascaded, because link is done through (res_model, res_id). """
msg_obj = self.pool.get('mail.message') msg_obj = self.pool.get('mail.message')
fol_obj = self.pool.get('mail.followers') fol_obj = self.pool.get('mail.followers')
if isinstance(ids, (int, long)):
ids = [ids]
# delete messages and notifications # delete messages and notifications
msg_ids = msg_obj.search(cr, uid, [('model', '=', self._name), ('res_id', 'in', ids)], context=context) 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) 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'): if not message_dict.get('parent_id'):
raise ValueError('Routing: posting a message without model should be with a parent_id (private mesage).') 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') _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 # Existing Document: check if exists; if not, fallback on create if allowed
if thread_id and not model_pool.exists(cr, uid, thread_id): 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) assert model_pool.exists(cr, uid, thread_id), 'Routing: reply to missing document (%s,%s)' % (model, thread_id)
else: else:
_warn('reply to missing document (%s,%s), skipping' % (model, thread_id)) _warn('reply to missing document (%s,%s), skipping' % (model, thread_id))
return () return False
# Existing Document: check model accepts the mailgateway # Existing Document: check model accepts the mailgateway
if thread_id and model and not hasattr(model_pool, 'message_update'): 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 assert hasattr(model_pool, 'message_update'), 'Routing: model %s does not accept document update, crashing' % model
else: else:
_warn('model %s does not accept document update, skipping' % model) _warn('model %s does not accept document update, skipping' % model)
return () return False
# New Document: check model accepts the mailgateway # New Document: check model accepts the mailgateway
if not thread_id and model and not hasattr(model_pool, 'message_new'): 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 'Model %s does not accept document creation, crashing' % model
) )
_warn('model %s does not accept document creation, skipping' % model) _warn('model %s does not accept document creation, skipping' % model)
return () return False
# Update message author if asked # Update message author if asked
# We do it now because we need it for aliases (contact settings) # 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]: 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) _warn('alias %s restricted to internal followers, skipping' % alias.alias_name)
_create_bounce_email() _create_bounce_email()
return () return False
elif alias and alias.alias_contact == 'partners' and not author_id: elif alias and alias.alias_contact == 'partners' and not author_id:
_warn('alias %s does not accept unknown author, skipping' % alias.alias_name) _warn('alias %s does not accept unknown author, skipping' % alias.alias_name)
_create_bounce_email() _create_bounce_email()
return () return False
if not model and not thread_id and not alias and not allow_private: if not model and not thread_id and not alias and not allow_private:
return () 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, def message_route(self, cr, uid, message, message_dict, model=None, thread_id=None,
custom_values=None, context=None): custom_values=None, context=None):
@@ -937,6 +940,7 @@ class mail_thread(osv.AbstractModel):
if not isinstance(message, Message): if not isinstance(message, Message):
raise TypeError('message must be an email.message.Message at this point') raise TypeError('message must be an email.message.Message at this point')
mail_msg_obj = self.pool['mail.message'] mail_msg_obj = self.pool['mail.message']
mail_alias = self.pool.get('mail.alias')
fallback_model = model fallback_model = model
# Get email.message.Message variables for future processing # Get email.message.Message variables for future processing
@@ -964,15 +968,21 @@ class mail_thread(osv.AbstractModel):
if ref_match and mail_message_ids: if ref_match and mail_message_ids:
original_msg = mail_msg_obj.browse(cr, SUPERUSER_ID, mail_message_ids[0], context=context) 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 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( route = self.message_route_verify(
cr, uid, message, message_dict, cr, uid, message, message_dict,
(model, thread_id, custom_values, uid, None), (model, thread_id, custom_values, uid, alias),
update_author=True, assert_model=False, create_fallback=True, context=context) update_author=True, assert_model=False, create_fallback=True, context=dict(context, drop_alias=True))
if route: if route:
_logger.info( _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', '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) email_from, email_to, message_id, model, thread_id, custom_values, uid)
return [route] return [route]
elif route is False:
return []
# 2. message is a reply to an existign thread (6.1 compatibility) # 2. message is a reply to an existign thread (6.1 compatibility)
if ref_match: 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', '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) email_from, email_to, message_id, model, thread_id, custom_values, uid)
return [route] return [route]
elif route is False:
return []
# 3. Reply to a private message # 3. Reply to a private message
if in_reply_to: 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', '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) email_from, email_to, message_id, mail_message.id, custom_values, uid)
return [route] return [route]
elif route is False:
return []
# 4. Look for a matching mail.alias entry # 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 # 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')]) decode_header(message, 'Resent-Cc')])
local_parts = [e.split('@')[0] for e in tools.email_split(rcpt_tos)] local_parts = [e.split('@')[0] for e in tools.email_split(rcpt_tos)]
if local_parts: if local_parts:
mail_alias = self.pool.get('mail.alias')
alias_ids = mail_alias.search(cr, uid, [('alias_name', 'in', local_parts)]) alias_ids = mail_alias.search(cr, uid, [('alias_name', 'in', local_parts)])
if alias_ids: if alias_ids:
routes = [] routes = []
@@ -1085,7 +1098,7 @@ class mail_thread(osv.AbstractModel):
context = dict(context or {}) context = dict(context or {})
partner_ids = message_dict.pop('partner_ids', []) partner_ids = message_dict.pop('partner_ids', [])
thread_id = False 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': if self._name == 'mail.thread':
context['thread_model'] = model context['thread_model'] = model
if model: if model:
+2 -2
View File
@@ -100,7 +100,7 @@ class TestMail(common.SavepointCase):
'login': 'raoul', 'login': 'raoul',
'alias_name': 'raoul', 'alias_name': 'raoul',
'groups_id': [(6, 0, [cls.group_employee_id])] 'groups_id': [(6, 0, [cls.group_employee_id])]
}) }, {'no_reset_password': True})
cls.user_bert_id = cls.res_users.create(cr, uid, { cls.user_bert_id = cls.res_users.create(cr, uid, {
'name': 'Bert Tartignole', 'name': 'Bert Tartignole',
'signature': 'SignBert', 'signature': 'SignBert',
@@ -108,7 +108,7 @@ class TestMail(common.SavepointCase):
'login': 'bert', 'login': 'bert',
'alias_name': 'bert', 'alias_name': 'bert',
'groups_id': [(6, 0, [])] 'groups_id': [(6, 0, [])]
}) }, {'no_reset_password': True})
cls.user_raoul = cls.res_users.browse(cr, uid, cls.user_raoul_id) 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_bert = cls.res_users.browse(cr, uid, cls.user_bert_id)
cls.user_admin = cls.res_users.browse(cr, uid, uid) 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): class MassMailingContact(osv.Model):
"""Model of a contact. This model is different from the partner 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 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) 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): class MassMailingStage(osv.Model):
"""Stage for mass mailing campaigns. """ """Stage for mass mailing campaigns. """
_name = 'mail.mass_mailing.stage' _name = 'mail.mass_mailing.stage'
+16 -13
View File
@@ -25,17 +25,16 @@
<field name="mail_mail_id_int"/> <field name="mail_mail_id_int"/>
<field name="message_id"/> <field name="message_id"/>
<field name="mass_mailing_id"/> <field name="mass_mailing_id"/>
<filter help="Sent" domain="[('sent', '!=', False)]"/> <filter string="Received" name="filter_received" domain="[('sent', '!=', False), ('bounced', '=', False)]"/>
<filter help="Opened" domain="[('opened', '!=', False)]"/> <filter string="Opened" name="filter_opened" domain="[('opened', '!=', False)]"/>
<filter help="Replied" domain="[('replied', '!=', False)]"/> <filter string="Replied" name="filter_replied" domain="[('replied', '!=', False)]"/>
<filter help="Bounced" domain="[('bounced', '!=', False)]"/> <filter string="Bounced" name="filter_bounced" domain="[('bounced', '!=', False)]"/>
<group expand="0" string="Group By"> <group expand="0" string="Group By">
<filter string="State" domain="[]" <filter string="State" domain="[]" context="{'group_by':'state'}"/>
context="{'group_by':'state'}"/> <filter string="Open Date" name="group_open_date" context="{'group_by': 'opened:day'}"/>
<filter string="Last State Update" domain="[]" <filter string="Reply Date" name="group_reply_date" context="{'group_by': 'replied:day'}"/>
context="{'group_by':'state_update'}"/> <filter string="Last State Update" domain="[]" context="{'group_by':'state_update'}"/>
<filter string="Mass Mailing" domain="[]" <filter string="Mass Mailing" domain="[]" context="{'group_by':'mass_mailing_id'}"/>
context="{'group_by':'mass_mailing_id'}"/>
</group> </group>
</search> </search>
</field> </field>
@@ -400,15 +399,18 @@
<field name="sent" string="Emails Sent" widget="statinfo"/> <field name="sent" string="Emails Sent" widget="statinfo"/>
</button> </button>
<button name="%(action_view_mail_mail_statistics_mailing)d" <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"/> <field name="received_ratio" string="Received" widget="percentpie"/>
</button> </button>
<button name="%(action_view_mail_mail_statistics_mailing)d" <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"/> <field name="opened_ratio" string="Opened" widget="percentpie"/>
</button> </button>
<button name="%(action_view_mail_mail_statistics_mailing)d" <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"/> <field name="replied_ratio" string="Replied" widget="percentpie"/>
</button> </button>
<button name="%(action_view_mass_mailing_links_statistics)d" <button name="%(action_view_mass_mailing_links_statistics)d"
@@ -416,6 +418,7 @@
<field name="clicks_ratio" string="Clicks" widget="percentpie"/> <field name="clicks_ratio" string="Clicks" widget="percentpie"/>
</button> </button>
<button name="%(action_view_mail_mail_statistics_mailing)d" <button name="%(action_view_mail_mail_statistics_mailing)d"
context="{'search_default_filter_bounced': True}"
type="action" class="oe_stat_button"> type="action" class="oe_stat_button">
<field name="bounced_ratio" string="Bounced" widget="percentpie"/> <field name="bounced_ratio" string="Bounced" widget="percentpie"/>
</button> </button>
+14 -2
View File
@@ -507,6 +507,12 @@ class mrp_production(osv.osv):
result[prod.id]['cycle_total'] += wc.cycle result[prod.id]['cycle_total'] += wc.cycle
return result 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): def _src_id_default(self, cr, uid, ids, context=None):
try: try:
location_model, location_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'stock_location_stock') 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\ 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 gets started then the status is set to 'In Production'.\n\
When the production is over, the status is set to 'Done'."), 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), 'hour_total': fields.function(_production_calc, type='float', string='Total Hours', multi='workorder', store={
'cycle_total': fields.function(_production_calc, type='float', string='Total Cycles', multi='workorder', store=True), _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'), 'user_id': fields.many2one('res.users', 'Responsible'),
'company_id': fields.many2one('res.company', 'Company', required=True), '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)}), '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 company_id: base.main_company
name: MRP Manager name: MRP Manager
login: mam login: mam
password: mam
email: mrp_manager@yourcompany.com email: mrp_manager@yourcompany.com
- -
I added groups for MRP Manager. I added groups for MRP Manager.
@@ -21,11 +20,10 @@
company_id: base.main_company company_id: base.main_company
name: MRP User name: MRP User
login: mau login: mau
password: mau
email: mrp_user@yourcompany.com email: mrp_user@yourcompany.com
- -
I added groups for MRP User. I added groups for MRP User.
- -
!record {model: res.users, id: res_users_mrp_user}: !record {model: res.users, id: res_users_mrp_user}:
groups_id: groups_id:
- mrp.group_mrp_user - mrp.group_mrp_user
@@ -5,7 +5,6 @@
company_id: base.main_company company_id: base.main_company
name: MRP User name: MRP User
login: maou login: maou
password: maou
email: mrp_operation_user@yourcompany.com email: mrp_operation_user@yourcompany.com
- -
I added groups for MRP User. I added groups for MRP User.
+1 -3
View File
@@ -5,7 +5,6 @@
company_id: base.main_company company_id: base.main_company
name: MRP Manager name: MRP Manager
login: marm login: marm
password: marm
email: mrp_repair_manager@yourcompany.com email: mrp_repair_manager@yourcompany.com
- -
I added groups for MRP Repair Manager. I added groups for MRP Repair Manager.
@@ -20,11 +19,10 @@
company_id: base.main_company company_id: base.main_company
name: MRP User name: MRP User
login: maru login: maru
password: maru
email: mrp_repair_user@yourcompany.com email: mrp_repair_user@yourcompany.com
- -
I added groups for MRP Repair User. I added groups for MRP Repair User.
- -
!record {model: res.users, id: res_mrp_repair_user}: !record {model: res.users, id: res_mrp_repair_user}:
groups_id: 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 openerp.tools.translate import _
from pprint import pformat from pprint import pformat
import time import time
from datetime import datetime
from urllib import urlencode from urllib import urlencode
import urllib2 import urllib2
import urlparse import urlparse
@@ -289,7 +290,7 @@ class PaymentTxOgone(osv.Model):
if status in self._ogone_valid_tx_status: if status in self._ogone_valid_tx_status:
tx.write({ tx.write({
'state': 'done', 'state': 'done',
'date_validate': data['TRXDATE'], 'date_validate': datetime.strptime(data['TRXDATE'],'%m/%d/%y').strftime(DEFAULT_SERVER_DATE_FORMAT),
'acquirer_reference': data['PAYID'], 'acquirer_reference': data['PAYID'],
}) })
return True 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) val1 += self._amount_line_tax(cr, uid, line, context=context)
val2 += line.price_subtotal val2 += line.price_subtotal
res[order.id]['amount_tax'] = cur_obj.round(cr, uid, cur, val1) 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 return res
_columns = { _columns = {
@@ -1009,7 +1010,6 @@ class pos_order(osv.osv):
'invoice_id': inv_id, 'invoice_id': inv_id,
'product_id': line.product_id.id, 'product_id': line.product_id.id,
'quantity': line.qty, '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_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, [], 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.product_id.uom_id.id,
line.qty, partner_id = order.partner_id.id, line.qty, partner_id = order.partner_id.id,
fposition_id=order.partner_id.property_account_position.id)['value']) 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['price_unit'] = line.price_unit
inv_line['discount'] = line.discount inv_line['discount'] = line.discount
inv_line['name'] = inv_name 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){ search_product_in_category: function(category_id, query){
try { try {
query = query.replace(/[\[\]\(\)\+\*\?\.\-\!\&\^\$\|\~\_\{\}\:\,\\\/]/g,'.'); query = query.replace(/[\[\]\(\)\+\*\?\.\-\!\&\^\$\|\~\_\{\}\:\,\\\/]/g,'.');
query = query.replace(' ','.+'); query = query.replace(/ /g,'.+');
var re = RegExp("([0-9]+):.*?"+query,"gi"); var re = RegExp("([0-9]+):.*?"+query,"gi");
}catch(e){ }catch(e){
return []; return [];
+2 -3
View File
@@ -1176,6 +1176,7 @@ openerp.point_of_sale.load_models = function load_models(instance, module){ //mo
taxtotal += tax.amount; taxtotal += tax.amount;
taxdetail[tax.id] = tax.amount; taxdetail[tax.id] = tax.amount;
}); });
totalNoTax = round_pr(totalNoTax, this.pos.currency.rounding);
return { return {
"priceWithTax": totalTax, "priceWithTax": totalTax,
@@ -1651,9 +1652,7 @@ openerp.point_of_sale.load_models = function load_models(instance, module){ //mo
}), 0), this.pos.currency.rounding); }), 0), this.pos.currency.rounding);
}, },
get_total_with_tax: function() { get_total_with_tax: function() {
return round_pr(this.orderlines.reduce((function(sum, orderLine) { return this.get_total_without_tax() + this.get_total_tax();
return sum + orderLine.get_price_with_tax();
}), 0), this.pos.currency.rounding);
}, },
get_total_without_tax: function() { get_total_without_tax: function() {
return round_pr(this.orderlines.reduce((function(sum, orderLine) { 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 cls.group_portal_id = cls.env.ref('base.group_portal').id
# Create Chell (portal user) # 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.user_chell = cls.res_users.browse(cr, uid, cls.user_chell_id)
cls.partner_chell_id = cls.user_chell.partner_id.id cls.partner_chell_id = cls.user_chell.partner_id.id
@@ -45,19 +45,19 @@ class TestPortalProjectBase(TestProjectBase):
'login': 'chell', 'login': 'chell',
'alias_name': 'chell', 'alias_name': 'chell',
'groups_id': [(6, 0, [self.group_portal_id])] 'groups_id': [(6, 0, [self.group_portal_id])]
}) }, {'no_reset_password': True})
self.user_public_id = self.res_users.create(cr, uid, { self.user_public_id = self.res_users.create(cr, uid, {
'name': 'Donovan Public', 'name': 'Donovan Public',
'login': 'donovan', 'login': 'donovan',
'alias_name': 'donovan', 'alias_name': 'donovan',
'groups_id': [(6, 0, [self.group_public_id])] 'groups_id': [(6, 0, [self.group_public_id])]
}) }, {'no_reset_password': True})
self.user_manager_id = self.res_users.create(cr, uid, { self.user_manager_id = self.res_users.create(cr, uid, {
'name': 'Eustache Manager', 'name': 'Eustache Manager',
'login': 'eustache', 'login': 'eustache',
'alias_name': 'eustache', 'alias_name': 'eustache',
'groups_id': [(6, 0, [self.group_project_manager_id])] 'groups_id': [(6, 0, [self.group_project_manager_id])]
}) }, {'no_reset_password': True})
# Test 'Pigs' project # Test 'Pigs' project
self.project_pigs_id = self.project_project.create(cr, uid, { 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 # unlink or inactive product
for variant_id in map(int,variants_inactive): for variant_id in map(int,variants_inactive):
try: try:
with cr.savepoint(): with cr.savepoint(), tools.mute_logger('openerp.sql_db'):
product_obj.unlink(cr, uid, [variant_id], context=ctx) product_obj.unlink(cr, uid, [variant_id], context=ctx)
#We catch all kind of exception to be sure that the operation doesn't fail. #We catch all kind of exception to be sure that the operation doesn't fail.
except (psycopg2.Error, except_orm): 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): def _set_image_variant(self, cr, uid, id, name, value, args, context=None):
image = tools.image_resize_image_big(value) 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) product = self.browse(cr, uid, id, context=context)
if not product.product_tmpl_id.image: if product.product_tmpl_id.image:
product.write({'image_variant': None}) product.image_variant = image
product.product_tmpl_id.write({'image': image}) else:
return res product.product_tmpl_id.image = image
def _get_price_extra(self, cr, uid, ids, name, args, context=None): def _get_price_extra(self, cr, uid, ids, name, args, context=None):
result = dict.fromkeys(ids, False) result = dict.fromkeys(ids, False)
+3 -3
View File
@@ -57,21 +57,21 @@ class TestProjectBase(TestMail):
'alias_name': 'armande', 'alias_name': 'armande',
'email': 'armande.projectuser@example.com', 'email': 'armande.projectuser@example.com',
'groups_id': [(6, 0, [cls.group_employee_id, cls.group_project_user_id])] '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, { cls.user_projectmanager_id = cls.res_users.create(cr, uid, {
'name': 'Bastien ProjectManager', 'name': 'Bastien ProjectManager',
'login': 'bastien', 'login': 'bastien',
'alias_name': 'bastien', 'alias_name': 'bastien',
'email': 'bastien.projectmanager@example.com', 'email': 'bastien.projectmanager@example.com',
'groups_id': [(6, 0, [cls.group_employee_id, cls.group_project_manager_id])] '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, { cls.user_none_id = cls.res_users.create(cr, uid, {
'name': 'Charlie Avotbonkeur', 'name': 'Charlie Avotbonkeur',
'login': 'charlie', 'login': 'charlie',
'alias_name': 'charlie', 'alias_name': 'charlie',
'email': 'charlie.noone@example.com', 'email': 'charlie.noone@example.com',
'groups_id': [(6, 0, [])] 'groups_id': [(6, 0, [])]
}) }, {'no_reset_password': True})
cls.user_projectuser = cls.res_users.browse(cr, uid, cls.user_projectuser_id) 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.user_projectmanager = cls.res_users.browse(cr, uid, cls.user_projectmanager_id)
cls.partner_projectuser_id = cls.user_projectuser.partner_id.id cls.partner_projectuser_id = cls.user_projectuser.partner_id.id
+1 -3
View File
@@ -5,7 +5,6 @@
company_id: base.main_company company_id: base.main_company
name: Project Manager name: Project Manager
login: prim login: prim
password: prim
email: issuemanager@yourcompany.com email: issuemanager@yourcompany.com
- -
I added groups for Project manager. I added groups for Project manager.
@@ -20,11 +19,10 @@
company_id: base.main_company company_id: base.main_company
name: Project User name: Project User
login: priu login: priu
password: priu
email: issueuser@yourcompany.com email: issueuser@yourcompany.com
- -
I added groups for Project user. I added groups for Project user.
- -
!record {model: res.users, id: res_users_project_issue_user}: !record {model: res.users, id: res_users_project_issue_user}:
groups_id: groups_id:
- project.group_project_user - project.group_project_user
@@ -5,7 +5,6 @@
company_id: base.main_company company_id: base.main_company
name: HR Manager name: HR Manager
login: hr login: hr
password: hr
groups_id: groups_id:
- base.group_hr_manager - 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) 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) 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): def picking_done(self, cr, uid, ids, context=None):
self.write(cr, uid, ids, {'shipped':1,'state':'approved'}, context=context) 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)): not all(picking.invoice_state in ['invoiced'] for picking in order.picking_ids)):
shipped = False shipped = False
for po_line in order.order_line: 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) invoiced.append(po_line.id)
if invoiced and shipped: if invoiced and shipped:
self.pool['purchase.order.line'].write(cr, user_id, invoiced, {'invoiced': True}) 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 return invoice_line_id
def _get_master_data(self, cr, uid, move, company, context=None): 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 purchase_order = move.purchase_line_id.order_id
return purchase_order.partner_id, purchase_order.create_uid.id, purchase_order.currency_id.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: 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 # 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: 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): 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) 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 purchase_line = move.purchase_line_id
res['invoice_line_tax_id'] = [(6, 0, [x.id for x in purchase_line.taxes_id])] res['invoice_line_tax_id'] = [(6, 0, [x.id for x in purchase_line.taxes_id])]
res['price_unit'] = purchase_line.price_unit 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 return res
def _get_moves_taxes(self, cr, uid, moves, inv_type, context=None): def _get_moves_taxes(self, cr, uid, moves, inv_type, context=None):
@@ -5,7 +5,6 @@
company_id: base.main_company company_id: base.main_company
name: Purchase Manager name: Purchase Manager
login: pm login: pm
password: pm
email: purchasemanager@yourcompany.com email: purchasemanager@yourcompany.com
- -
I added groups for Purchase manager. I added groups for Purchase manager.
@@ -20,7 +19,6 @@
company_id: base.main_company company_id: base.main_company
name: Purchase User name: Purchase User
login: pu login: pu
password: pu
email: purchaseuser@yourcompany.com email: purchaseuser@yourcompany.com
- -
I added groups for Purchase user. I added groups for Purchase user.
@@ -5,7 +5,6 @@
company_id: base.main_company company_id: base.main_company
name: Purchase requisition Manager name: Purchase requisition Manager
login: prm login: prm
password: prm
email: requisition_manager@yourcompany.com email: requisition_manager@yourcompany.com
- -
I added groups for Purchase Requisition Manager. I added groups for Purchase Requisition Manager.
@@ -20,11 +19,10 @@
company_id: base.main_company company_id: base.main_company
name: Purchase requisition User name: Purchase requisition User
login: pru login: pru
password: pru
email: requisition_user@yourcompany.com email: requisition_user@yourcompany.com
- -
I added groups for Purchase Requisition User. I added groups for Purchase Requisition User.
- -
!record {model: res.users, id: res_users_purchase_requisition_user}: !record {model: res.users, id: res_users_purchase_requisition_user}:
groups_id: 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 { .table-condensed > thead > tr > th {
border-bottom: 1px solid black !important; border-bottom: 1px solid black !important;
} }
.table-condensed > tbody > tr {
page-break-inside: avoid !important;
}
.zero_min_height { .zero_min_height {
min-height: 0px !important; min-height: 0px !important;
} }
+1 -1
View File
@@ -40,7 +40,7 @@ class sale_order(osv.osv):
_description = "Sales Order" _description = "Sales Order"
_track = { _track = {
'state': { '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'] '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 company_id: base.main_company
name: Sales manager name: Sales manager
login: sm login: sm
password: sm
email: salesmanager@yourcompany.com email: salesmanager@yourcompany.com
- -
I added groups for Salesmanager. I added groups for Salesmanager.
@@ -20,7 +19,6 @@
company_id: base.main_company company_id: base.main_company
name: Salesman name: Salesman
login: su login: su
password: su
email: salesman@yourcompany.com email: salesman@yourcompany.com
- -
I added groups for Salesman. I added groups for Salesman.
@@ -9,6 +9,7 @@
!record {model: product.product, id: product_onchange1}: !record {model: product.product, id: product_onchange1}:
name: 'Devil Worship Book' name: 'Devil Worship Book'
list_price: 66.6 list_price: 66.6
default_code: 'DWB00001'
- -
In sale order to test process of onchange of Sale Order with access rights of saleman. In sale order to test process of onchange of Sale Order with access rights of saleman.
- -
@@ -28,5 +29,5 @@
!python {model: sale.order}: | !python {model: sale.order}: |
from openerp.tools import float_compare from openerp.tools import float_compare
order_line = self.browse(cr, uid, ref('sale_order_onchange1')).order_line 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" 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 company_id: base.main_company
name: Stock Sales manager name: Stock Sales manager
login: ssm login: ssm
password: ssm
email: ss_salesmanager@yourcompany.com email: ss_salesmanager@yourcompany.com
- -
I added groups for Salesmanager. I added groups for Salesmanager.
@@ -20,7 +19,6 @@
company_id: base.main_company company_id: base.main_company
name: Stock Salesman name: Stock Salesman
login: ssu login: ssu
password: ssu
email: ss_salesman@yourcompany.com email: ss_salesman@yourcompany.com
- -
I added groups for Stock Salesman. I added groups for Stock Salesman.
@@ -36,7 +34,6 @@
company_id: base.main_company company_id: base.main_company
name: Stock User name: Stock User
login: sau login: sau
password: sau
email: stock_user@yourcompany.com email: stock_user@yourcompany.com
- -
I added groups for Stock User. I added groups for Stock User.
@@ -51,8 +48,6 @@
company_id: base.main_company company_id: base.main_company
name: Stock Manager name: Stock Manager
login: sam login: sam
password: sam
email: admin@portal.example.com
email: stock_manager@yourcompany.com email: stock_manager@yourcompany.com
- -
I added groups for Stock Manager. 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", 'group_uom': fields.boolean("Manage different units of measure for products",
implied_group='product.group_uom', implied_group='product.group_uom',
help="""Allows you to select and maintain different units of measure for products."""), 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', implied_group='product.group_uos',
help='Allows you to sell units of a product, but invoice based on a different unit of measure.\n' 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 sell pieces of meat that you invoice based on their weight.'), '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", 'group_stock_packaging': fields.boolean("Allow to define several packaging methods on products",
implied_group='product.group_stock_packaging', 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."""), 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) res.add(move.picking_id.id)
return list(res) 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): def _get_pack_operation_exist(self, cr, uid, ids, field_name, arg, context=None):
res = {} res = {}
for pick in self.browse(cr, uid, ids, context=context): 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""" * 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', '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), track_visibility='onchange', required=True),
'min_date': fields.function(get_min_max_date, multi="min_max_date", fnct_inv=_set_min_date, '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", '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': 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), '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), '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': 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"), '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_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'), help='Quantity in the default UoM of the product'),
'product_uom_qty': fields.float('Quantity', digits_compute=dp.get_precision('Product Unit of Measure'), 'product_uom_qty': fields.float('Quantity', digits_compute=dp.get_precision('Product Unit of Measure'),
required=True, states={'done': [('readonly', True)]}, required=True, states={'done': [('readonly', True)]},
-2
View File
@@ -5,7 +5,6 @@
company_id: base.main_company company_id: base.main_company
name: Stock Manager name: Stock Manager
login: sam login: sam
password: sam
email: stockmanager@yourcompany.com email: stockmanager@yourcompany.com
- -
I added groups for Stock Manager. I added groups for Stock Manager.
@@ -20,7 +19,6 @@
company_id: base.main_company company_id: base.main_company
name: Stock User name: Stock User
login: sau login: sau
password: sau
email: stockuser@yourcompany.com email: stockuser@yourcompany.com
- -
I added groups for Stock User. 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={}): def __get_picking_move(self, cr, uid, ids, context={}):
res = [] res = []
for move in self.pool.get('stock.move').browse(cr, uid, ids, context=context): 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) res.append(move.picking_id.id)
return res return res
+1 -1
View File
@@ -753,7 +753,7 @@ instance.web.DataSetStatic = instance.web.DataSet.extend({
var offset = options.offset || 0, var offset = options.offset || 0,
limit = options.limit || false; limit = options.limit || false;
var end_pos = limit && limit !== -1 ? offset + limit : this.ids.length; 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) { set_ids: function (ids) {
this.ids = 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({ instance.web.form.One2ManyDataSet = instance.web.BufferedDataSet.extend({
get_context: function() { get_context: function(extra_context) {
this.context = this.o2m.build_context(); this.context = this.o2m.build_context();
if(extra_context)
{
this.context.add(extra_context);
}
return this.context; return this.context;
} }
}); });
+4 -2
View File
@@ -2312,7 +2312,7 @@ instance.web.list.Binary = instance.web.list.Column.extend({
* @private * @private
*/ */
_format: function (row_data, options) { _format: function (row_data, options) {
var text = _t("Download"); var text = _t("Download"), filename=_t('Binary file');
var value = row_data[this.id].value; var value = row_data[this.id].value;
if (!value) { if (!value) {
return options.value_if_empty || ''; 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]) { if (this.filename && row_data[this.filename]) {
text = _.str.sprintf(_t("Download \"%s\""), instance.web.format_value( text = _.str.sprintf(_t("Download \"%s\""), instance.web.format_value(
row_data[this.filename].value, {type: 'char'})); 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, text: text,
href: download_url, href: download_url,
size: instance.web.binary_to_binsize(value), 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: for line in order_lines:
ret.append({ ret.append({
'id': line.order_id and line.order_id.id, '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, '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, 'price': line.price_unit,
'quantity': line.product_uom_qty,
}) })
return ret return ret
@http.route(['/shop/tracking_last_order'], type='json', auth="public") @http.route(['/shop/tracking_last_order'], type='json', auth="public")
def tracking_cart(self, **post): def tracking_cart(self, **post):
""" return data about order in JSON needed for google analytics""" """ 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 = {} ret = {}
sale_order_id = request.session.get('sale_last_order_id') sale_order_id = request.session.get('sale_last_order_id')
if sale_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, 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, 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! # Sanity checks: the view should not break anything upon rendering!
# Any exception raised below will cause a transaction rollback. # Any exception raised below will cause a transaction rollback.
for view in self.browse(cr, uid, ids, context): 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'] view_arch_utf8 = view_def['arch']
if view.type != 'qweb': if view.type != 'qweb':
view_doc = etree.fromstring(view_arch_utf8) view_doc = etree.fromstring(view_arch_utf8)
@@ -595,7 +595,7 @@ class view(osv.osv):
# arch and model fields are always returned # arch and model fields are always returned
if fields: if fields:
fields = list(set(fields) | set(['arch', 'model'])) fields = list({'arch', 'model'}.union(fields))
# read the view arch # read the view arch
[view] = self.read(cr, uid, [root_id], fields=fields, context=context) [view] = self.read(cr, uid, [root_id], fields=fields, context=context)
@@ -428,6 +428,7 @@
<field name="name">Finland</field> <field name="name">Finland</field>
<field name="code">fi</field> <field name="code">fi</field>
<field name="image" type="base64" file="base/static/img/country_flags/fi.png"></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"/> <field name="currency_id" ref="EUR"/>
</record> </record>
<record id="fj" model="res.country"> <record id="fj" model="res.country">
+7
View File
@@ -61,6 +61,13 @@ class Start(Command):
if '--db-filter' not in cmdargs: if '--db-filter' not in cmdargs:
cmdargs.append('--db-filter=^%s$' % args.db_name) 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) main(cmdargs)
def die(message, code=1): def die(message, code=1):
+5 -2
View File
@@ -1194,8 +1194,11 @@ class BaseModel(object):
type = 'warning' if isinstance(exception, Warning) else 'error' type = 'warning' if isinstance(exception, Warning) else 'error'
# logs the logical (not human-readable) field name for automated # logs the logical (not human-readable) field name for automated
# processing of response, but injects human readable in message # processing of response, but injects human readable in message
record = dict(base, type=type, field=field, # Before applying string substitution, we need to escape all '%'
message=unicode(exception.args[0]) % base) # 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]: if len(exception.args) > 1 and exception.args[1]:
record.update(exception.args[1]) record.update(exception.args[1])
log(record) log(record)
+2
View File
@@ -1591,6 +1591,8 @@ class sparse(function):
""" """
if self._type == 'many2many': if self._type == 'many2many':
if not value:
return []
assert value[0][0] == 6, 'Unsupported m2m value for sparse field: %s' % value assert value[0][0] == 6, 'Unsupported m2m value for sparse field: %s' % value
return value[0][2] 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) opt = dict(format=image.format or format)
if image.format == 'PNG': if image.format == 'PNG':
opt.update(optimize=True) 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': if image.mode != 'P':
# Get the alpha band
alpha = image.split()[-1]
# Floyd Steinberg dithering by default # Floyd Steinberg dithering by default
image = image.convert('RGBA').convert('P', palette=Image.WEB, colors=256) image = image.convert('RGBA').convert('P', palette=Image.WEB, colors=256)
# Set all pixel values below 128 to 255 and the rest to 0 if alpha:
mask = Image.eval(alpha, lambda a: 255 if a <=128 else 0) image.putalpha(alpha)
# Paste the color of index 255 and use alpha as a mask
image.paste(255, mask)
opt.update(transparency=255)
elif image.format == 'JPEG': elif image.format == 'JPEG':
opt.update(optimize=True, quality=80) opt.update(optimize=True, quality=80)
if fp: if fp:
+3 -3
View File
@@ -316,10 +316,10 @@ class YamlInterpreter(object):
if not self._coerce_bool(record.forcecreate): if not self._coerce_bool(record.forcecreate):
return None return None
#context = self.get_context(record, self.eval_context) #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 # FIXME: record.context like {'withoutemployee':True} should pass from self.eval_context. example: test_project.yml in project module
context = record.context # 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 view_info = False
if view_id: if view_id:
varg = view_id varg = view_id