Merge remote-tracking branch 'odoo/master' into master-sass-in-bundles-fme

This commit is contained in:
Fabien Meghazi 2014-06-27 19:40:02 +02:00
commit 9fa77980d7
641 changed files with 9354 additions and 27178 deletions

View File

@ -5,6 +5,6 @@ Contributing to Odoo
TL;DR
* Use the [template structure](https://raw.githubusercontent.com/odoo/odoo/master/doc/_templates/issue_template.md)
* Pull requests made against the [correct version](https://github.com/odoo/odoo/wiki/Contributing#against-which-version-should-i-submit-a-patch)
* Read the restrictions for [changes in stable](https://github.com/odoo/odoo/wiki/Contributing#what-does-stable-mean)
* Use this [template](https://raw.githubusercontent.com/odoo/odoo/master/doc/_templates/issue_template.md) when reporting issues, and please search for duplicates first!
* Pull requests must be made against the [correct version](https://github.com/odoo/odoo/wiki/Contributing#against-which-version-should-i-submit-a-patch)
* There are restrictions on the kind of [changes allowed in stable series](https://github.com/odoo/odoo/wiki/Contributing#what-does-stable-mean)

View File

@ -59,7 +59,7 @@ class account_payment_term(osv.osv):
_name = "account.payment.term"
_description = "Payment Term"
_columns = {
'name': fields.char('Payment Term', size=64, translate=True, required=True),
'name': fields.char('Payment Term', translate=True, required=True),
'active': fields.boolean('Active', help="If the active field is set to False, it will allow you to hide the payment term without removing it."),
'note': fields.text('Description', translate=True),
'line_ids': fields.one2many('account.payment.term.line', 'payment_id', 'Terms'),
@ -180,7 +180,7 @@ class account_account_type(osv.osv):
return obj_financial_report.write(cr, uid, [financial_report_ref[field_value].id], {'account_type_ids': [(4, account_type_id)]})
_columns = {
'name': fields.char('Account Type', size=64, required=True, translate=True),
'name': fields.char('Account Type', required=True, translate=True),
'code': fields.char('Code', size=32, required=True, select=True),
'close_method': fields.selection([('none', 'None'), ('balance', 'Balance'), ('detail', 'Detail'), ('unreconciled', 'Unreconciled')], 'Deferral Method', required=True, help="""Set here the method that will be used to generate the end of year journal entries for all the accounts of this type.
@ -444,7 +444,7 @@ class account_account(osv.osv):
return True
_columns = {
'name': fields.char('Name', size=256, required=True, select=True),
'name': fields.char('Name', required=True, select=True),
'currency_id': fields.many2one('res.currency', 'Secondary Currency', help="Forces all moves for this account to have this secondary currency."),
'code': fields.char('Code', size=64, required=True, select=1),
'type': fields.selection([
@ -715,7 +715,7 @@ class account_journal(osv.osv):
_description = "Journal"
_columns = {
'with_last_closing_balance' : fields.boolean('Opening With Last Closing Balance'),
'name': fields.char('Journal Name', size=64, required=True),
'name': fields.char('Journal Name', required=True),
'code': fields.char('Code', size=5, required=True, help="The code will be displayed on reports."),
'type': fields.selection([('sale', 'Sale'),('sale_refund','Sale Refund'), ('purchase', 'Purchase'), ('purchase_refund','Purchase Refund'), ('cash', 'Cash'), ('bank', 'Bank and Checks'), ('general', 'General'), ('situation', 'Opening/Closing Situation')], 'Type', size=32, required=True,
help="Select 'Sale' for customer invoices journals."\
@ -859,7 +859,7 @@ class account_fiscalyear(osv.osv):
_name = "account.fiscalyear"
_description = "Fiscal Year"
_columns = {
'name': fields.char('Fiscal Year', size=64, required=True),
'name': fields.char('Fiscal Year', required=True),
'code': fields.char('Code', size=6, required=True),
'company_id': fields.many2one('res.company', 'Company', required=True),
'date_start': fields.date('Start Date', required=True),
@ -952,10 +952,9 @@ class account_period(osv.osv):
_name = "account.period"
_description = "Account period"
_columns = {
'name': fields.char('Period Name', size=64, required=True),
'name': fields.char('Period Name', required=True),
'code': fields.char('Code', size=12),
'special': fields.boolean('Opening/Closing Period', size=12,
help="These periods can overlap."),
'special': fields.boolean('Opening/Closing Period',help="These periods can overlap."),
'date_start': fields.date('Start of Period', required=True, states={'done':[('readonly',True)]}),
'date_stop': fields.date('End of Period', required=True, states={'done':[('readonly',True)]}),
'fiscalyear_id': fields.many2one('account.fiscalyear', 'Fiscal Year', required=True, states={'done':[('readonly',True)]}, select=True),
@ -1092,10 +1091,10 @@ class account_journal_period(osv.osv):
return result
_columns = {
'name': fields.char('Journal-Period Name', size=64, required=True),
'name': fields.char('Journal-Period Name', required=True),
'journal_id': fields.many2one('account.journal', 'Journal', required=True, ondelete="cascade"),
'period_id': fields.many2one('account.period', 'Period', required=True, ondelete="cascade"),
'icon': fields.function(_icon_get, string='Icon', type='char', size=32),
'icon': fields.function(_icon_get, string='Icon', type='char'),
'active': fields.boolean('Active', help="If the active field is set to False, it will allow you to hide the journal period without removing it."),
'state': fields.selection([('draft','Draft'), ('printed','Printed'), ('done','Done')], 'Status', required=True, readonly=True,
help='When journal period is created. The status is \'Draft\'. If a report is printed it comes to \'Printed\' status. When all transactions are done, it comes in \'Done\' status.'),
@ -1235,8 +1234,8 @@ class account_move(osv.osv):
return [line.move_id.id for line in line_obj.browse(cr, uid, ids, context=context)]
_columns = {
'name': fields.char('Number', size=64, required=True),
'ref': fields.char('Reference', size=64),
'name': fields.char('Number', required=True),
'ref': fields.char('Reference'),
'period_id': fields.many2one('account.period', 'Period', required=True, states={'posted':[('readonly',True)]}),
'journal_id': fields.many2one('account.journal', 'Journal', required=True, states={'posted':[('readonly',True)]}),
'state': fields.selection([('draft','Unposted'), ('posted','Posted')], 'Status', required=True, readonly=True,
@ -1629,8 +1628,8 @@ class account_move_reconcile(osv.osv):
_name = "account.move.reconcile"
_description = "Account Reconciliation"
_columns = {
'name': fields.char('Name', size=64, required=True),
'type': fields.char('Type', size=16, required=True),
'name': fields.char('Name', required=True),
'type': fields.char('Type', required=True),
'line_id': fields.one2many('account.move.line', 'reconcile_id', 'Entry Lines'),
'line_partial_ids': fields.one2many('account.move.line', 'reconcile_partial_id', 'Partial Entry lines'),
'create_date': fields.date('Creation date', readonly=True),
@ -1787,7 +1786,7 @@ class account_tax_code(osv.osv):
_description = 'Tax Code'
_rec_name = 'code'
_columns = {
'name': fields.char('Tax Case Name', size=64, required=True, translate=True),
'name': fields.char('Tax Case Name', required=True, translate=True),
'code': fields.char('Case Code', size=64),
'info': fields.text('Description'),
'sum': fields.function(_sum_year, string="Year Sum"),
@ -1876,7 +1875,7 @@ class account_tax(osv.osv):
_name = 'account.tax'
_description = 'Tax'
_columns = {
'name': fields.char('Tax Name', size=64, required=True, translate=True, help="This name will be displayed on reports"),
'name': fields.char('Tax Name', required=True, translate=True, help="This name will be displayed on reports"),
'sequence': fields.integer('Sequence', required=True, help="The sequence field is used to order the tax lines from the lowest sequences to the higher ones. The order is important if you have a tax with several tax children. In this case, the evaluation order is important."),
'amount': fields.float('Amount', required=True, digits_compute=get_precision_tax(), help="For taxes of type percentage, enter % ratio between 0-1."),
'active': fields.boolean('Active', help="If the active field is set to False, it will allow you to hide the tax without removing it."),
@ -1884,7 +1883,7 @@ class account_tax(osv.osv):
help="The computation method for the tax amount."),
'applicable_type': fields.selection( [('true','Always'), ('code','Given by Python Code')], 'Applicability', required=True,
help="If not applicable (computed through a Python code), the tax won't appear on the invoice."),
'domain':fields.char('Domain', size=32, help="This field is only used if you develop your own module allowing developers to create specific taxes in a custom domain."),
'domain':fields.char('Domain', help="This field is only used if you develop your own module allowing developers to create specific taxes in a custom domain."),
'account_collected_id':fields.many2one('account.account', 'Invoice Tax Account', help="Set the account that will be set by default on invoice tax lines for invoices. Leave empty to use the expense account."),
'account_paid_id':fields.many2one('account.account', 'Refund Tax Account', help="Set the account that will be set by default on invoice tax lines for refunds. Leave empty to use the expense account."),
'account_analytic_collected_id':fields.many2one('account.analytic.account', 'Invoice Tax Analytic Account', help="Set the analytic account that will be used by default on the invoice tax lines for invoices. Leave empty if you don't want to use an analytic account on the invoice tax lines by default."),
@ -2267,7 +2266,7 @@ class account_model(osv.osv):
_name = "account.model"
_description = "Account Model"
_columns = {
'name': fields.char('Model Name', size=64, required=True, help="This is a model for recurring accounting entries"),
'name': fields.char('Model Name', required=True, help="This is a model for recurring accounting entries"),
'journal_id': fields.many2one('account.journal', 'Journal', required=True),
'company_id': fields.related('journal_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True),
'lines_id': fields.one2many('account.model.line', 'model_id', 'Model Entries'),
@ -2374,7 +2373,7 @@ class account_model_line(osv.osv):
_name = "account.model.line"
_description = "Account Model Entries"
_columns = {
'name': fields.char('Name', size=64, required=True),
'name': fields.char('Name', required=True),
'sequence': fields.integer('Sequence', required=True, help="The sequence field is used to order the resources from lower sequences to higher ones."),
'quantity': fields.float('Quantity', digits_compute=dp.get_precision('Account'), help="The optional quantity on entries."),
'debit': fields.float('Debit', digits_compute=dp.get_precision('Account')),
@ -2402,8 +2401,8 @@ class account_subscription(osv.osv):
_name = "account.subscription"
_description = "Account Subscription"
_columns = {
'name': fields.char('Name', size=64, required=True),
'ref': fields.char('Reference', size=16),
'name': fields.char('Name', required=True),
'ref': fields.char('Reference'),
'model_id': fields.many2one('account.model', 'Model', required=True),
'date_start': fields.date('Start Date', required=True),
'period_total': fields.integer('Number of Periods', required=True),
@ -2507,7 +2506,7 @@ class account_account_template(osv.osv):
_description ='Templates for Accounts'
_columns = {
'name': fields.char('Name', size=256, required=True, select=True),
'name': fields.char('Name', required=True, select=True),
'currency_id': fields.many2one('res.currency', 'Secondary Currency', help="Forces all moves for this account to have this secondary currency."),
'code': fields.char('Code', size=64, required=True, select=1),
'type': fields.selection([
@ -2688,7 +2687,7 @@ class account_tax_code_template(osv.osv):
_order = 'code'
_rec_name = 'code'
_columns = {
'name': fields.char('Tax Case Name', size=64, required=True),
'name': fields.char('Tax Case Name', required=True),
'code': fields.char('Case Code', size=64),
'info': fields.text('Description'),
'parent_id': fields.many2one('account.tax.code.template', 'Parent Code', select=True),
@ -2758,7 +2757,7 @@ class account_chart_template(osv.osv):
_description= "Templates for Account Chart"
_columns={
'name': fields.char('Name', size=64, required=True),
'name': fields.char('Name', required=True),
'parent_id': fields.many2one('account.chart.template', 'Parent Chart Template'),
'code_digits': fields.integer('# of Digits', required=True, help="No. of Digits to use for account code"),
'visible': fields.boolean('Can be Visible?', help="Set this to False if you don't want this template to be used actively in the wizard that generate Chart of Accounts from templates, this is useful when you want to generate accounts of this template only when loading its child template."),
@ -2792,12 +2791,12 @@ class account_tax_template(osv.osv):
_columns = {
'chart_template_id': fields.many2one('account.chart.template', 'Chart Template', required=True),
'name': fields.char('Tax Name', size=64, required=True),
'name': fields.char('Tax Name', required=True),
'sequence': fields.integer('Sequence', required=True, help="The sequence field is used to order the taxes lines from lower sequences to higher ones. The order is important if you have a tax that has several tax children. In this case, the evaluation order is important."),
'amount': fields.float('Amount', required=True, digits_compute=get_precision_tax(), help="For Tax Type percent enter % ratio between 0-1."),
'type': fields.selection( [('percent','Percent'), ('fixed','Fixed'), ('none','None'), ('code','Python Code'), ('balance','Balance')], 'Tax Type', required=True),
'applicable_type': fields.selection( [('true','True'), ('code','Python Code')], 'Applicable Type', required=True, help="If not applicable (computed through a Python code), the tax won't appear on the invoice."),
'domain':fields.char('Domain', size=32, help="This field is only used if you develop your own module allowing developers to create specific taxes in a custom domain."),
'domain':fields.char('Domain', help="This field is only used if you develop your own module allowing developers to create specific taxes in a custom domain."),
'account_collected_id':fields.many2one('account.account.template', 'Invoice Tax Account'),
'account_paid_id':fields.many2one('account.account.template', 'Refund Tax Account'),
'parent_id':fields.many2one('account.tax.template', 'Parent Tax Account', select=True),
@ -2921,7 +2920,7 @@ class account_fiscal_position_template(osv.osv):
_description = 'Template for Fiscal Position'
_columns = {
'name': fields.char('Fiscal Position Template', size=64, required=True),
'name': fields.char('Fiscal Position Template', required=True),
'chart_template_id': fields.many2one('account.chart.template', 'Chart Template', required=True),
'account_ids': fields.one2many('account.fiscal.position.account.template', 'position_id', 'Account Mapping'),
'tax_ids': fields.one2many('account.fiscal.position.tax.template', 'position_id', 'Tax Mapping'),
@ -3553,10 +3552,10 @@ class account_bank_accounts_wizard(osv.osv_memory):
_name='account.bank.accounts.wizard'
_columns = {
'acc_name': fields.char('Account Name.', size=64, required=True),
'acc_name': fields.char('Account Name.', required=True),
'bank_account_id': fields.many2one('wizard.multi.charts.accounts', 'Bank Account', required=True, ondelete='cascade'),
'currency_id': fields.many2one('res.currency', 'Secondary Currency', help="Forces all moves for this account to have this secondary currency."),
'account_type': fields.selection([('cash','Cash'), ('check','Check'), ('bank','Bank')], 'Account Type', size=32),
'account_type': fields.selection([('cash','Cash'), ('check','Check'), ('bank','Bank')], 'Account Type'),
}

View File

@ -33,7 +33,7 @@ class account_analytic_line(osv.osv):
'move_id': fields.many2one('account.move.line', 'Move Line', ondelete='cascade', select=True),
'journal_id': fields.many2one('account.analytic.journal', 'Analytic Journal', required=True, ondelete='restrict', select=True),
'code': fields.char('Code', size=8),
'ref': fields.char('Ref.', size=64),
'ref': fields.char('Ref.'),
'currency_id': fields.related('move_id', 'currency_id', type='many2one', relation='res.currency', string='Account Currency', store=True, help="The related account currency if not equal to the company one.", readonly=True),
'amount_currency': fields.related('move_id', 'amount_currency', type='float', string='Amount Currency', store=True, help="The amount expressed in the related account currency if not equal to the company one.", readonly=True),
}

View File

@ -114,7 +114,7 @@ class account_bank_statement(osv.osv):
_description = "Bank Statement"
_inherit = ['mail.thread']
_columns = {
'name': fields.char('Reference', size=64, states={'draft': [('readonly', False)]}, readonly=True, help='if you give the Name other then /, its created Accounting Entries Move will be with same name as statement name. This allows the statement entries to have the same references than the statement itself'), # readonly for account_cash_statement
'name': fields.char('Reference', states={'draft': [('readonly', False)]}, readonly=True, help='if you give the Name other then /, its created Accounting Entries Move will be with same name as statement name. This allows the statement entries to have the same references than the statement itself'), # readonly for account_cash_statement
'date': fields.date('Date', required=True, states={'confirm': [('readonly', True)]}, select=True),
'journal_id': fields.many2one('account.journal', 'Journal', required=True,
readonly=True, states={'draft':[('readonly',False)]}),
@ -448,15 +448,31 @@ class account_bank_statement_line(osv.osv):
""" Used to instanciate a batch of reconciliations in a single request """
# Build a list of reconciliations data
ret = []
statement_line_done = {}
mv_line_ids_selected = []
for st_line in self.browse(cr, uid, ids, context=context):
# look for structured communication first
exact_match_id = self.search_structured_com(cr, uid, st_line, context=context)
if exact_match_id:
reconciliation_data = {
'st_line': self.get_statement_line_for_reconciliation(cr, uid, st_line.id, context),
'reconciliation_proposition': self.make_counter_part_lines(cr, uid, st_line, [exact_match_id], context=context)
}
for mv_line in reconciliation_data['reconciliation_proposition']:
mv_line_ids_selected.append(mv_line['id'])
statement_line_done[st_line.id] = reconciliation_data
for st_line_id in ids:
reconciliation_data = {
'st_line': self.get_statement_line_for_reconciliation(cr, uid, st_line_id, context),
'reconciliation_proposition': self.get_reconciliation_proposition(cr, uid, st_line_id, mv_line_ids_selected, context)
}
for mv_line in reconciliation_data['reconciliation_proposition']:
mv_line_ids_selected.append(mv_line['id'])
ret.append(reconciliation_data)
if statement_line_done.get(st_line_id):
ret.append(statement_line_done.get(st_line_id))
else:
reconciliation_data = {
'st_line': self.get_statement_line_for_reconciliation(cr, uid, st_line_id, context),
'reconciliation_proposition': self.get_reconciliation_proposition(cr, uid, st_line_id, mv_line_ids_selected, context)
}
for mv_line in reconciliation_data['reconciliation_proposition']:
mv_line_ids_selected.append(mv_line['id'])
ret.append(reconciliation_data)
# Check if, now that 'candidate' move lines were selected, there are moves left for statement lines
#for reconciliation_data in ret:
@ -529,23 +545,19 @@ class account_bank_statement_line(osv.osv):
if st_line.amount < 0:
sign = -1
# look for structured communication
exact_match_id = self.search_structured_com(cr, uid, st_line, context=context)
if exact_match_id:
return self.make_counter_part_lines(cr, uid, st_line, [exact_match_id], count=False, context=context)
#we don't propose anything if there is no partner detected
if not st_line.partner_id.id:
return []
# look for exact match
exact_match_id = self.get_move_lines_counterparts(cr, uid, st_line, excluded_ids=excluded_ids, limit=1, additional_domain=[(amount_field, '=', (sign * st_line.amount))])
exact_match_id = self.get_move_lines_counterparts(cr, uid, st_line, excluded_ids=excluded_ids, additional_domain=[(amount_field, '=', (sign * st_line.amount))])
if exact_match_id:
return exact_match_id
return exact_match_id[0]
# select oldest move lines
if sign == -1:
mv_lines = self.get_move_lines_counterparts(cr, uid, st_line, excluded_ids=excluded_ids, limit=50, additional_domain=[(amount_field, '<', 0)])
mv_lines = self.get_move_lines_counterparts(cr, uid, st_line, excluded_ids=excluded_ids, additional_domain=[(amount_field, '<', 0)])
else:
mv_lines = self.get_move_lines_counterparts(cr, uid, st_line, excluded_ids=excluded_ids, limit=50, additional_domain=[(amount_field, '>', 0)])
mv_lines = self.get_move_lines_counterparts(cr, uid, st_line, excluded_ids=excluded_ids, additional_domain=[(amount_field, '>', 0)])
ret = []
total = 0
# get_move_lines_counterparts inverts debit and credit
@ -558,11 +570,11 @@ class account_bank_statement_line(osv.osv):
break
return ret
def get_move_lines_counterparts_id(self, cr, uid, st_line_id, excluded_ids=[], filter_str="", offset=0, limit=None, count=False, additional_domain=[], context=None):
def get_move_lines_counterparts_id(self, cr, uid, st_line_id, excluded_ids=[], additional_domain=[], count=False, context=None):
st_line = self.browse(cr, uid, st_line_id, context=context)
return self.get_move_lines_counterparts(cr, uid, st_line, excluded_ids, filter_str, offset, limit, count, additional_domain, context=context)
return self.get_move_lines_counterparts(cr, uid, st_line, excluded_ids, additional_domain, count, context=context)
def get_move_lines_counterparts(self, cr, uid, st_line, excluded_ids=[], filter_str="", offset=0, limit=None, count=False, additional_domain=[], context=None):
def get_move_lines_counterparts(self, cr, uid, st_line, excluded_ids=[], additional_domain=[], count=False, context=None):
""" Find the move lines that could be used to reconcile a statement line and returns the counterpart that could be created to reconcile them
If count is true, only returns the count.
@ -576,10 +588,7 @@ class account_bank_statement_line(osv.osv):
"""
mv_line_pool = self.pool.get('account.move.line')
domain = additional_domain + [
('reconcile_id', '=', False),
('state', '=', 'valid'),
]
domain = additional_domain + [('reconcile_id', '=', False),('state', '=', 'valid')]
if st_line.partner_id.id:
domain += [('partner_id', '=', st_line.partner_id.id),
'|', ('account_id.type', '=', 'receivable'),
@ -589,11 +598,7 @@ class account_bank_statement_line(osv.osv):
#domain += [('account_id.reconcile', '=', True), ('account_id.type', '=', 'other')]
if excluded_ids:
domain.append(('id', 'not in', excluded_ids))
if filter_str:
if not st_line.partner_id:
domain += [ '|', ('partner_id.name', 'ilike', filter_str)]
domain += ['|', ('move_id.name', 'ilike', filter_str), ('move_id.ref', 'ilike', filter_str)]
line_ids = mv_line_pool.search(cr, uid, domain, offset=offset, limit=limit, order="date_maturity asc, id asc", context=context)
line_ids = mv_line_pool.search(cr, uid, domain, order="date_maturity asc, id asc", context=context)
return self.make_counter_part_lines(cr, uid, st_line, line_ids, count=count, context=context)
def make_counter_part_lines(self, cr, uid, st_line, line_ids, count=False, context=None):

View File

@ -97,7 +97,7 @@ class account_financial_report(osv.osv):
return res
_columns = {
'name': fields.char('Report Name', size=128, required=True, translate=True),
'name': fields.char('Report Name', required=True, translate=True),
'parent_id': fields.many2one('account.financial.report', 'Parent'),
'children_ids': fields.one2many('account.financial.report', 'parent_id', 'Account Report'),
'sequence': fields.integer('Sequence'),

View File

@ -24,7 +24,7 @@ from lxml import etree
import openerp.addons.decimal_precision as dp
import openerp.exceptions
from openerp.osv import fields, osv, orm
from openerp.osv import fields, osv
from openerp.tools.translate import _
class account_invoice(osv.osv):
@ -226,8 +226,8 @@ class account_invoice(osv.osv):
},
}
_columns = {
'name': fields.char('Reference/Description', size=64, select=True, readonly=True, states={'draft':[('readonly',False)]}),
'origin': fields.char('Source Document', size=64, help="Reference of the document that produced this invoice.", readonly=True, states={'draft':[('readonly',False)]}),
'name': fields.char('Reference/Description', select=True, readonly=True, states={'draft':[('readonly',False)]}),
'origin': fields.char('Source Document', help="Reference of the document that produced this invoice.", readonly=True, states={'draft':[('readonly',False)]}),
'supplier_invoice_number': fields.char('Supplier Invoice Number', size=64, help="The reference of this invoice as provided by the supplier.", readonly=True, states={'draft':[('readonly',False)]}),
'type': fields.selection([
('out_invoice','Customer Invoice'),
@ -237,8 +237,8 @@ class account_invoice(osv.osv):
],'Type', readonly=True, select=True, change_default=True, track_visibility='always'),
'number': fields.related('move_id','name', type='char', readonly=True, size=64, relation='account.move', store=True, string='Number'),
'internal_number': fields.char('Invoice Number', size=32, readonly=True, help="Unique number of the invoice, computed automatically when the invoice is created."),
'reference': fields.char('Invoice Reference', size=64, help="The partner reference of this invoice."),
'internal_number': fields.char('Invoice Number', readonly=True, help="Unique number of the invoice, computed automatically when the invoice is created."),
'reference': fields.char('Invoice Reference', help="The partner reference of this invoice."),
'reference_type': fields.selection(_get_reference_type, 'Payment Reference',
required=True, readonly=True, states={'draft':[('readonly',False)]}),
'comment': fields.text('Additional Information'),
@ -318,7 +318,7 @@ class account_invoice(osv.osv):
},
help="Remaining amount due."),
'payment_ids': fields.function(_compute_lines, relation='account.move.line', type="many2many", string='Payments'),
'move_name': fields.char('Journal Entry', size=64, readonly=True, states={'draft':[('readonly',False)]}),
'move_name': fields.char('Journal Entry', readonly=True, states={'draft':[('readonly',False)]}),
'user_id': fields.many2one('res.users', 'Salesperson', readonly=True, track_visibility='onchange', states={'draft':[('readonly',False)]}),
'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position', readonly=True, states={'draft':[('readonly',False)]}),
'commercial_partner_id': fields.related('partner_id', 'commercial_partner_id', string='Commercial Entity', type='many2one',
@ -903,6 +903,7 @@ class account_invoice(osv.osv):
move_obj = self.pool.get('account.move')
if context is None:
context = {}
inv_date = {}
for inv in self.browse(cr, uid, ids, context=context):
if not inv.journal_id.sequence_id:
raise osv.except_osv(_('Error!'), _('Please define sequence on the journal related to this invoice.'))
@ -913,8 +914,8 @@ class account_invoice(osv.osv):
ctx = context.copy()
ctx.update({'lang': inv.partner_id.lang})
if not inv.date_invoice:
self.write(cr, uid, [inv.id], {'date_invoice': fields.date.context_today(self,cr,uid,context=context)}, context=ctx)
date_invoice = inv.date_invoice or fields.date.context_today(self,cr,uid,context=context)
inv_date = {'date_invoice': date_invoice}
company_currency = self.pool['res.company'].browse(cr, uid, inv.company_id.id).currency_id.id
# create the analytical lines
# one move line per invoice line
@ -944,17 +945,10 @@ class account_invoice(osv.osv):
# one move line per tax line
iml += ait_obj.move_line_get(cr, uid, inv.id)
entry_type = ''
if inv.type in ('in_invoice', 'in_refund'):
ref = inv.reference
entry_type = 'journal_pur_voucher'
if inv.type == 'in_refund':
entry_type = 'cont_voucher'
else:
ref = self._convert_ref(cr, uid, inv.number)
entry_type = 'journal_sale_vou'
if inv.type == 'out_refund':
entry_type = 'cont_voucher'
diff_currency_p = inv.currency_id.id <> company_currency
# create one move line for the total and possibly adjust the other lines amount
@ -967,11 +961,11 @@ class account_invoice(osv.osv):
totlines = False
if inv.payment_term:
totlines = payment_term_obj.compute(cr,
uid, inv.payment_term.id, total, inv.date_invoice or False, context=ctx)
uid, inv.payment_term.id, total, date_invoice or False, context=ctx)
if totlines:
res_amount_currency = total_currency
i = 0
ctx.update({'date': inv.date_invoice})
ctx.update({'date': date_invoice})
for t in totlines:
if inv.currency_id.id != company_currency:
amount_currency = cur_obj.compute(cr, uid, company_currency, inv.currency_id.id, t[1], context=ctx)
@ -1010,7 +1004,7 @@ class account_invoice(osv.osv):
'ref': ref
})
date = inv.date_invoice or time.strftime('%Y-%m-%d')
date = date_invoice or time.strftime('%Y-%m-%d')
part = self.pool.get("res.partner")._find_accounting_partner(inv.partner_id)
@ -1037,7 +1031,7 @@ class account_invoice(osv.osv):
period_id = inv.period_id and inv.period_id.id or False
ctx.update(company_id=inv.company_id.id)
if not period_id:
period_ids = period_obj.find(cr, uid, inv.date_invoice, context=ctx)
period_ids = period_obj.find(cr, uid, date_invoice, context=ctx)
period_id = period_ids and period_ids[0] or False
if period_id:
move['period_id'] = period_id
@ -1048,7 +1042,9 @@ class account_invoice(osv.osv):
move_id = move_obj.create(cr, uid, move, context=ctx)
new_move_name = move_obj.browse(cr, uid, move_id, context=ctx).name
# make the invoice point to that move
self.write(cr, uid, [inv.id], {'move_id': move_id,'period_id':period_id, 'move_name':new_move_name}, context=ctx)
vals = inv_date
vals.update(move_id=move_id, period_id=period_id, move_name=new_move_name)
self.write(cr, uid, [inv.id], vals, context=ctx)
# Pass invoice in context in method post: used if you want to get the same
# account move reference when creating the same invoice after a cancelled one:
move_obj.post(cr, uid, [move_id], context=ctx)
@ -1299,14 +1295,6 @@ class account_invoice(osv.osv):
amount_currency = False
currency_id = False
pay_journal = self.pool.get('account.journal').read(cr, uid, pay_journal_id, ['type'], context=context)
if invoice.type in ('in_invoice', 'out_invoice'):
if pay_journal['type'] == 'bank':
entry_type = 'bank_pay_voucher' # Bank payment
else:
entry_type = 'pay_voucher' # Cash payment
else:
entry_type = 'cont_voucher'
if invoice.type in ('in_invoice', 'in_refund'):
ref = invoice.reference
else:
@ -1414,7 +1402,7 @@ class account_invoice_line(osv.osv):
_order = "invoice_id,sequence,id"
_columns = {
'name': fields.text('Description', required=True),
'origin': fields.char('Source Document', size=256, help="Reference of the document that produced this invoice."),
'origin': fields.char('Source Document', help="Reference of the document that produced this invoice."),
'sequence': fields.integer('Sequence', help="Gives the sequence of this line when displaying the invoice."),
'invoice_id': fields.many2one('account.invoice', 'Invoice Reference', ondelete='cascade', select=True),
'uos_id': fields.many2one('product.uom', 'Unit of Measure', ondelete='set null', select=True),
@ -1535,7 +1523,6 @@ class account_invoice_line(osv.osv):
res_final['value']['price_unit'] = new_price
if result['uos_id'] and result['uos_id'] != res.uom_id.id:
selected_uom = self.pool.get('product.uom').browse(cr, uid, result['uos_id'], context=context)
new_price = self.pool.get('product.uom')._compute_price(cr, uid, res.uom_id.id, res_final['value']['price_unit'], result['uos_id'])
res_final['value']['price_unit'] = new_price
return res_final
@ -1659,7 +1646,7 @@ class account_invoice_tax(osv.osv):
_columns = {
'invoice_id': fields.many2one('account.invoice', 'Invoice Line', ondelete='cascade', select=True),
'name': fields.char('Tax Description', size=64, required=True),
'name': fields.char('Tax Description', required=True),
'account_id': fields.many2one('account.account', 'Tax Account', required=True, domain=[('type','<>','view'),('type','<>','income'), ('type', '<>', 'closed')]),
'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic account'),
'base': fields.float('Base', digits_compute=dp.get_precision('Account')),

View File

@ -445,7 +445,7 @@ class account_move_line(osv.osv):
_columns = {
'name': fields.char('Name', size=64, required=True),
'name': fields.char('Name', required=True),
'quantity': fields.float('Quantity', digits=(16,2), help="The optional quantity expressed by this line, eg: number of product sold. The quantity is not a legal requirement but is very useful for some reports."),
'product_uom_id': fields.many2one('product.uom', 'Unit of Measure'),
'product_id': fields.many2one('product.product', 'Product'),
@ -454,7 +454,7 @@ class account_move_line(osv.osv):
'account_id': fields.many2one('account.account', 'Account', required=True, ondelete="cascade", domain=[('type','<>','view'), ('type', '<>', 'closed')], select=2),
'move_id': fields.many2one('account.move', 'Journal Entry', ondelete="cascade", help="The move of this entry line.", select=2, required=True),
'narration': fields.related('move_id','narration', type='text', relation='account.move', string='Internal Note'),
'ref': fields.related('move_id', 'ref', string='Reference', type='char', size=64, store=True),
'ref': fields.related('move_id', 'ref', string='Reference', type='char', store=True),
'statement_id': fields.many2one('account.bank.statement', 'Statement', help="The bank statement used for bank reconciliation", select=1),
'reconcile_id': fields.many2one('account.move.reconcile', 'Reconcile', readonly=True, ondelete='set null', select=2),
'reconcile_partial_id': fields.many2one('account.move.reconcile', 'Partial Reconcile', readonly=True, ondelete='set null', select=2),

View File

@ -28,7 +28,7 @@ class account_fiscal_position(osv.osv):
_name = 'account.fiscal.position'
_description = 'Fiscal Position'
_columns = {
'name': fields.char('Fiscal Position', size=64, required=True),
'name': fields.char('Fiscal Position', required=True),
'active': fields.boolean('Active', help="By unchecking the active field, you may hide a fiscal position without deleting it."),
'company_id': fields.many2one('res.company', 'Company'),
'account_ids': fields.one2many('account.fiscal.position.account', 'position_id', 'Account Mapping'),

View File

@ -25,10 +25,10 @@ class account_analytic_journal(osv.osv):
_name = 'account.analytic.journal'
_description = 'Analytic Journal'
_columns = {
'name': fields.char('Journal Name', size=64, required=True),
'name': fields.char('Journal Name', required=True),
'code': fields.char('Journal Code', size=8),
'active': fields.boolean('Active', help="If the active field is set to False, it will allow you to hide the analytic journal without removing it."),
'type': fields.selection([('sale','Sale'), ('purchase','Purchase'), ('cash','Cash'), ('general','General'), ('situation','Situation')], 'Type', size=32, required=True, help="Gives the type of the analytic journal. When it needs for a document (eg: an invoice) to create analytic entries, OpenERP will look for a matching journal of the same type."),
'type': fields.selection([('sale','Sale'), ('purchase','Purchase'), ('cash','Cash'), ('general','General'), ('situation','Situation')], 'Type', required=True, help="Gives the type of the analytic journal. When it needs for a document (eg: an invoice) to create analytic entries, OpenERP will look for a matching journal of the same type."),
'line_ids': fields.one2many('account.analytic.line', 'journal_id', 'Lines'),
'company_id': fields.many2one('res.company', 'Company', required=True),
}

View File

@ -32,7 +32,7 @@ class account_entries_report(osv.osv):
'date': fields.date('Effective Date', readonly=True),
'date_created': fields.date('Date Created', readonly=True),
'date_maturity': fields.date('Date Maturity', readonly=True),
'ref': fields.char('Reference', size=64, readonly=True),
'ref': fields.char('Reference', readonly=True),
'nbr': fields.integer('# of Items', readonly=True),
'debit': fields.float('Debit', readonly=True),
'credit': fields.float('Credit', readonly=True),

View File

@ -73,7 +73,7 @@ class temp_range(osv.osv):
_description = 'A Temporary table used for Dashboard view'
_columns = {
'name': fields.char('Range',size=64)
'name': fields.char('Range')
}
@ -112,7 +112,7 @@ class report_aged_receivable(osv.osv):
return res
_columns = {
'name': fields.char('Month Range', size=7, readonly=True),
'name': fields.char('Month Range', size=24, readonly=True),
'balance': fields.function(_calc_bal, string='Balance', readonly=True),
}
@ -151,14 +151,14 @@ class report_invoice_created(osv.osv):
_description = "Report of Invoices Created within Last 15 days"
_auto = False
_columns = {
'name': fields.char('Description', size=64, readonly=True),
'name': fields.char('Description', readonly=True),
'type': fields.selection([
('out_invoice','Customer Invoice'),
('in_invoice','Supplier Invoice'),
('out_refund','Customer Refund'),
('in_refund','Supplier Refund'),
],'Type', readonly=True),
'number': fields.char('Invoice Number', size=32, readonly=True),
'number': fields.char('Invoice Number', readonly=True),
'partner_id': fields.many2one('res.partner', 'Partner', readonly=True),
'amount_untaxed': fields.float('Untaxed', readonly=True),
'amount_total': fields.float('Total', readonly=True),
@ -174,7 +174,7 @@ class report_invoice_created(osv.osv):
('paid','Done'),
('cancel','Cancelled')
],'Status', readonly=True),
'origin': fields.char('Source Document', size=64, readonly=True, help="Reference of the document that generated this invoice report."),
'origin': fields.char('Source Document', readonly=True, help="Reference of the document that generated this invoice report."),
'create_date': fields.datetime('Create Date', readonly=True)
}
_order = 'create_date'
@ -203,7 +203,7 @@ class report_account_type_sales(osv.osv):
_description = "Report of the Sales by Account Type"
_auto = False
_columns = {
'name': fields.char('Year', size=64, required=False, readonly=True),
'name': fields.char('Year', required=False, readonly=True),
'period_id': fields.many2one('account.period', 'Force Period', readonly=True),
'product_id': fields.many2one('product.product', 'Product', readonly=True),
'quantity': fields.float('Quantity', readonly=True),
@ -244,7 +244,7 @@ class report_account_sales(osv.osv):
_description = "Report of the Sales by Account"
_auto = False
_columns = {
'name': fields.char('Year', size=64, required=False, readonly=True, select=True),
'name': fields.char('Year', required=False, readonly=True, select=True),
'period_id': fields.many2one('account.period', 'Force Period', readonly=True),
'product_id': fields.many2one('product.product', 'Product', readonly=True),
'quantity': fields.float('Quantity', readonly=True),

View File

@ -139,6 +139,13 @@
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
</record>
<record id="account_subscription_line_comp_rule" model="ir.rule">
<field name="name">Account subscription line company rule</field>
<field name="model_id" ref="model_account_subscription_line"/>
<field name="global" eval="True"/>
<field name="domain_force">['|',('subscription_id.model_id.company_id','=',False),('subscription_id.model_id.company_id','child_of',[user.company_id.id])]</field>
</record>
<record model="ir.rule" id="account_invoice_line_comp_rule">
<field name="name">Invoice Line company rule</field>
<field name="model_id" ref="model_account_invoice_line"/>

View File

@ -37,7 +37,7 @@ openerp.account = function (instance) {
// We'll need to get the code of an account selected in a many2one (whose value is the id)
this.map_account_id_code = {};
// The same move line cannot be selected for multiple resolutions
this.excluded_move_lines_ids = {};
this.excluded_move_lines_ids = [];
// Description of the fields to initialize in the "create new line" form
// NB : for presets to work correctly, a field id must be the same string as a preset field
this.create_form_fields = {
@ -253,59 +253,34 @@ openerp.account = function (instance) {
});
}
},
// Adds move line ids to the list of move lines not to fetch for a given partner
// This is required because the same move line cannot be selected for multiple reconciliation
excludeMoveLines: function(source_child, partner_id, line_ids) {
excludeMoveLines: function(line_ids) {
var self = this;
var excluded_ids = this.excluded_move_lines_ids[partner_id];
var excluded_move_lines_changed = false;
_.each(line_ids, function(line_id){
if (excluded_ids.indexOf(line_id) === -1) {
excluded_ids.push(line_id);
excluded_move_lines_changed = true;
line_id = parseInt(line_id);
if (self.excluded_move_lines_ids.indexOf(line_id) === -1) {
self.excluded_move_lines_ids.push(line_id);
}
});
if (! excluded_move_lines_changed)
return;
// Function that finds if an array of line objects contains at least a line identified by its id
var contains_lines = function(lines_array, line_ids) {
for (var i = 0; i < lines_array.length; i++)
for (var j = 0; j < line_ids.length; j++)
if (lines_array[i].id === line_ids[j])
return true;
return false;
};
// Update children if needed
//update all children view
_.each(self.getChildren(), function(child){
if (child.partner_id === partner_id && child !== source_child) {
if (contains_lines(child.get("mv_lines_selected"), line_ids)) {
child.set("mv_lines_selected", _.filter(child.get("mv_lines_selected"), function(o){ return line_ids.indexOf(o.id) === -1 }));
} else if (contains_lines(child.mv_lines_deselected, line_ids)) {
child.mv_lines_deselected = _.filter(child.mv_lines_deselected, function(o){ return line_ids.indexOf(o.id) === -1 });
child.updateMatches();
} else if (contains_lines(child.get("mv_lines"), line_ids)) {
child.updateMatches();
}
}
child.render();
});
},
unexcludeMoveLines: function(source_child, partner_id, line_ids) {
unexcludeMoveLines: function(line_ids) {
var self = this;
var initial_excluded_lines_num = this.excluded_move_lines_ids[partner_id].length;
this.excluded_move_lines_ids[partner_id] = _.difference(this.excluded_move_lines_ids[partner_id], line_ids);
if (this.excluded_move_lines_ids[partner_id].length === initial_excluded_lines_num)
return;
// Update children if needed
var index = -1;
_.each(line_ids, function(line_id){
line_id = parseInt(line_id);
index = self.excluded_move_lines_ids.indexOf(line_id);
if (index > -1) {
self.excluded_move_lines_ids.splice(index,1);
}
});
//update all children view
_.each(self.getChildren(), function(child){
if (child.partner_id === partner_id && child !== source_child && (child.get("mode") === "match" || child.$el.hasClass("no_match")))
child.updateMatches();
child.render();
});
},
@ -490,9 +465,7 @@ openerp.account = function (instance) {
// Exclude selected move lines
var selected_line_ids = _(context.reconciliation_proposition).map(function(o){ return o.id });
if (this.getParent().excluded_move_lines_ids[this.partner_id] === undefined)
this.getParent().excluded_move_lines_ids[this.partner_id] = [];
this.getParent().excludeMoveLines(this, this.partner_id, selected_line_ids);
this.getParent().excludeMoveLines(selected_line_ids);
} else {
this.set("mv_lines_selected", []);
this.st_line = undefined;
@ -513,7 +486,6 @@ openerp.account = function (instance) {
this.presets = this.getParent().presets;
this.is_valid = true;
this.is_consistent = true; // Used to prevent bad server requests
this.total_move_lines_num = undefined; // Used for pagers
this.filter = "";
this.set("balance", undefined); // Debit is +, credit is -
@ -525,12 +497,14 @@ openerp.account = function (instance) {
// NB : mv_lines represent the counterpart that will be created to reconcile existing move lines, so debit and credit are inverted
this.set("mv_lines", []);
this.on("change:mv_lines", this, this.mvLinesChanged);
this.mv_lines_deselected = []; // deselected lines are displayed on top of the match table
this.on("change:mv_lines_selected", this, this.mvLinesSelectedChanged);
this.set("lines_created", []);
this.set("line_created_being_edited", [{'id': 0}]);
this.on("change:lines_created", this, this.createdLinesChanged);
this.on("change:line_created_being_edited", this, this.createdLinesChanged);
//all lines associated to current reconciliation
this.propositions_lines = undefined;
},
start: function() {
@ -553,9 +527,6 @@ openerp.account = function (instance) {
self.st_line = data;
self.decorateStatementLine(self.st_line);
self.partner_id = data.partner_id;
if (self.getParent().excluded_move_lines_ids[self.partner_id] === undefined)
self.getParent().excluded_move_lines_ids[self.partner_id] = [];
// load and display move lines
$.when(self.loadReconciliationProposition()).then(function(){
deferred_fetch_data.resolve();
});
@ -566,6 +537,15 @@ openerp.account = function (instance) {
// Display the widget
return $.when(deferred_fetch_data).then(function(){
//load all lines that can be usefull for counterparts
var deferred_total_move_lines_num = self.model_bank_statement_line
.call("get_move_lines_counterparts_id", [self.st_line.id, []])
.then(function(lines){
_(lines).each(self.decorateMoveLine.bind(self));
self.propositions_lines = lines;
});
return deferred_total_move_lines_num;
}).then(function(){
// Render template
var presets_array = [];
for (var id in self.presets)
@ -577,10 +557,9 @@ openerp.account = function (instance) {
self.$(".match").slideUp(0);
self.$(".create").slideUp(0);
if (self.st_line.no_match) self.$el.addClass("no_match");
if (self.context.mode !== "match") self.updateMatches();
if (self.context.mode !== "match") self.render();
self.bindPopoverTo(self.$(".line_info_button"));
self.createFormWidgets();
// Special case hack : no identified partner
if (self.st_line.has_no_partner) {
self.$el.css("opacity", "0");
@ -623,7 +602,7 @@ openerp.account = function (instance) {
_.each(self.getChildren(), function(o){ o.destroy() });
self.is_consistent = false;
return $.when(self.$el.animate({opacity: 0}, self.animation_speed)).then(function() {
self.getParent().unexcludeMoveLines(self, self.partner_id, _.map(self.get("mv_lines_selected"), function(o){ return o.id }));
self.getParent().unexcludeMoveLines(_.map(self.get("mv_lines_selected"), function(o){ return o.id }));
$.each(self.$(".bootstrap_popover"), function(){ $(this).popover('destroy') });
self.$el.empty();
self.$el.removeClass("no_partner");
@ -637,7 +616,6 @@ openerp.account = function (instance) {
self.set("pager_index", 0, {silent: true});
self.set("mv_lines", [], {silent: true});
self.set("mv_lines_selected", [], {silent: true});
self.mv_lines_deselected = [];
self.set("lines_created", [], {silent: true});
self.set("line_created_being_edited", [{'id': 0}], {silent: true});
// Rebirth
@ -836,68 +814,35 @@ openerp.account = function (instance) {
if (e.currentTarget.dataset.selected === "true") self.deselectMoveLine(e.currentTarget);
else self.selectMoveLine(e.currentTarget);
},
// Takes a move line from the match view and adds it to the mv_lines_selected array
selectMoveLine: function(mv_line) {
var self = this;
var line_id = mv_line.dataset.lineid;
// find the line in mv_lines or mv_lines_deselected
var line = _.find(self.get("mv_lines"), function(o){ return o.id == line_id });
if (! line) {
line = _.find(self.mv_lines_deselected, function(o){ return o.id == line_id });
self.mv_lines_deselected = _.filter(self.mv_lines_deselected, function(o) { return o.id != line_id });
}
// If no line found, the view is probably not up to date to the model (asynchronous fun)
if (! line) return;
// Warn the user if he's selecting lines from both a payable and a receivable account
var last_selected_line = _.last(self.get("mv_lines_selected"));
if (last_selected_line && last_selected_line.account_type != line.account_type) {
// TODO : web client API
alert(_.str.sprintf(_t("You are selecting transactions from both a payable and a receivable account.\n\nIn order to proceed, you first need to deselect the %s transactions."), last_selected_line.account_type));
return;
}
var line = _.find(self.propositions_lines, function(o){ return o.id == line_id});
$(mv_line).attr('data-selected','true');
self.getParent().excludeMoveLines([line_id]);
self.set("mv_lines_selected", self.get("mv_lines_selected").concat(line));
},
// Removes a move line from the mv_lines_selected array
deselectMoveLine: function(mv_line) {
var self = this;
var line_id = mv_line.dataset.lineid;
var line = _.find(self.get("mv_lines_selected"), function(o) { return o.id == line_id });
// If no line found, the view is probably not up to date to the model (asynchronous fun)
if (! line) return;
// add the line to mv_lines_deselected and remove it from mv_lines_selected
self.mv_lines_deselected.unshift(line);
var mv_lines_selected = _.filter(self.get("mv_lines_selected"), function(o) { return o.id != line_id });
// remove partial reconciliation stuff if necessary
if (line.partial_reconcile === true) self.unpartialReconcileLine(line);
if (line.propose_partial_reconcile === true) line.propose_partial_reconcile = false;
self.$el.removeClass("no_match");
self.set("mode", "match");
self.set("mv_lines_selected", mv_lines_selected);
var line = _.find(self.propositions_lines, function(o){ return o.id == line_id});
$(mv_line).attr('data-selected','false');
self.getParent().unexcludeMoveLines([line_id]);
self.set("mv_lines_selected",_.filter(self.get("mv_lines_selected"), function(o) { return o.id != line_id }));
},
/** Matches pagination */
pagerControlLeftHandler: function() {
var self = this;
if (self.$(".pager_control_left").hasClass("disabled")) { return; /* shouldn't happen, anyway*/ }
if (self.total_move_lines_num < 0) { return; }
self.set("pager_index", self.get("pager_index")-1 );
},
pagerControlRightHandler: function() {
var self = this;
var new_index = self.get("pager_index")+1;
if (self.$(".pager_control_right").hasClass("disabled")) { return; /* shouldn't happen, anyway*/ }
if ((new_index * self.max_move_lines_displayed) >= self.total_move_lines_num) { return; }
self.set("pager_index", new_index );
},
@ -905,11 +850,9 @@ openerp.account = function (instance) {
var self = this;
self.set("pager_index", 0);
self.filter = self.$(".filter").val();
window.clearTimeout(self.apply_filter_timeout);
self.apply_filter_timeout = window.setTimeout(self.proxy('updateMatches'), 200);
self.render();
},
/** Creating */
initializeCreateForm: function() {
@ -1041,20 +984,16 @@ openerp.account = function (instance) {
table.empty();
var slice_start = self.get("pager_index") * self.max_move_lines_displayed;
var slice_end = (self.get("pager_index")+1) * self.max_move_lines_displayed;
_( _.filter(self.mv_lines_deselected, function(o){
return o.q_label.indexOf(self.filter) !== -1 || (o.ref && o.ref.indexOf(self.filter) !== -1)
})
.slice(slice_start, slice_end)).each(function(line){
var $line = $(QWeb.render("bank_statement_reconciliation_move_line", {line: line, selected: false}));
self.bindPopoverTo($line.find(".line_info_button"));
table.append($line);
nothing_displayed = false;
});
var visible = 0
_(self.get("mv_lines")).each(function(line){
var $line = $(QWeb.render("bank_statement_reconciliation_move_line", {line: line, selected: false}));
self.bindPopoverTo($line.find(".line_info_button"));
table.append($line);
nothing_displayed = false;
if (visible >= slice_start && visible < slice_end) {
var $line = $(QWeb.render("bank_statement_reconciliation_move_line", {line: line, selected: false}));
self.bindPopoverTo($line.find(".line_info_button"));
table.append($line);
nothing_displayed = false;
}
visible = visible + 1;
});
if (nothing_displayed)
table.append(QWeb.render("filter_no_match", {filter_str: self.filter}));
@ -1066,7 +1005,7 @@ openerp.account = function (instance) {
self.$(".pager_control_left").addClass("disabled");
else
self.$(".pager_control_left").removeClass("disabled");
if (self.total_move_lines_num <= ((self.get("pager_index")+1) * self.max_move_lines_displayed))
if (self.get('mv_lines').length <= ((self.get("pager_index")+1) * self.max_move_lines_displayed))
self.$(".pager_control_right").addClass("disabled");
else
self.$(".pager_control_right").removeClass("disabled");
@ -1136,7 +1075,7 @@ openerp.account = function (instance) {
self.el.dataset.mode = "inactive";
} else if (self.get("mode") === "match") {
return $.when(self.updateMatches()).then(function() {
return $.when(self.render()).then(function() {
if (self.$el.hasClass("no_match")) {
self.set("mode", "inactive");
return;
@ -1156,18 +1095,14 @@ openerp.account = function (instance) {
pagerChanged: function() {
var self = this;
self.updateMatches();
self.render();
},
mvLinesChanged: function() {
var self = this;
// If pager_index is out of range, set it to display the last page
if (self.get("pager_index") !== 0 && self.total_move_lines_num <= (self.get("pager_index") * self.max_move_lines_displayed)) {
self.set("pager_index", Math.ceil(self.total_move_lines_num/self.max_move_lines_displayed)-1);
}
// If there is no match to display, disable match view and pass in mode inactive
if (self.total_move_lines_num + self.mv_lines_deselected.length === 0 && self.filter === "") {
if (self.get("mv_lines").length === 0 && self.filter === "") {
self.$el.addClass("no_match");
if (self.get("mode") === "match") {
self.set("mode", "inactive");
@ -1186,13 +1121,11 @@ openerp.account = function (instance) {
var added_lines_ids = _.map(_.difference(val.newValue, val.oldValue), function(o){ return o.id });
var removed_lines_ids = _.map(_.difference(val.oldValue, val.newValue), function(o){ return o.id });
self.getParent().excludeMoveLines(self, self.partner_id, added_lines_ids);
self.getParent().unexcludeMoveLines(self, self.partner_id, removed_lines_ids);
self.getParent().excludeMoveLines(added_lines_ids);
self.getParent().unexcludeMoveLines(removed_lines_ids);
$.when(self.updateMatches()).then(function(){
self.updateAccountingViewMatchedLines();
self.updateBalance();
});
self.updateAccountingViewMatchedLines();
self.updateBalance();
},
// Generic function for updating the line_created_being_edited
@ -1339,47 +1272,23 @@ openerp.account = function (instance) {
loadReconciliationProposition: function() {
var self = this;
return self.model_bank_statement_line
.call("get_reconciliation_proposition", [self.st_line.id, self.getParent().excluded_move_lines_ids[self.partner_id]])
.call("get_reconciliation_proposition", [self.st_line.id, self.getParent().excluded_move_lines_ids])
.then(function (lines) {
_(lines).each(self.decorateMoveLine.bind(self));
self.set("mv_lines_selected", self.get("mv_lines_selected").concat(lines));
});
},
// Loads move lines according to the widget's state
updateMatches: function() {
render: function() {
var self = this;
var deselected_lines_num = self.mv_lines_deselected.length;
var move_lines = {};
var move_lines_num = 0;
var offset = self.get("pager_index") * self.max_move_lines_displayed - deselected_lines_num;
if (offset < 0) offset = 0;
var limit = (self.get("pager_index")+1) * self.max_move_lines_displayed - deselected_lines_num;
if (limit > self.max_move_lines_displayed) limit = self.max_move_lines_displayed;
var excluded_ids = _.collect(self.get("mv_lines_selected").concat(self.mv_lines_deselected), function(o){ return o.id });
excluded_ids = excluded_ids.concat(self.getParent().excluded_move_lines_ids[self.partner_id]);
var deferred_move_lines;
if (limit > 0) {
// Load move lines
deferred_move_lines = self.model_bank_statement_line
.call("get_move_lines_counterparts_id", [self.st_line.id, excluded_ids, self.filter, offset, limit])
.then(function (lines) {
_(lines).each(self.decorateMoveLine.bind(self));
move_lines = lines;
});
}
// Fetch the number of move lines corresponding to this statement line and this filter
var deferred_total_move_lines_num = self.model_bank_statement_line
.call("get_move_lines_counterparts_id", [self.st_line.id, excluded_ids, self.filter, 0, undefined, true])
.then(function(num){
move_lines_num = num;
});
return $.when(deferred_move_lines, deferred_total_move_lines_num).then(function(){
self.total_move_lines_num = move_lines_num + deselected_lines_num;
self.set("mv_lines", move_lines);
var lines_to_show = [];
_.each(self.propositions_lines, function(line){
var filter = (line.q_label.toLowerCase().indexOf(self.filter.toLowerCase()) > -1 || line.account_code.toLowerCase().indexOf(self.filter.toLowerCase()) > -1);
if (self.getParent().excluded_move_lines_ids.indexOf(line.id) === -1 && filter) {
lines_to_show.push(line);
}
});
self.set("mv_lines", lines_to_show);
},
// Changes the partner_id of the statement_line in the DB and reloads the widget
@ -1439,8 +1348,6 @@ openerp.account = function (instance) {
var self = this;
if (! self.is_consistent) return;
self.getParent().unexcludeMoveLines(self, self.partner_id, _.map(self.get("mv_lines_selected"), function(o){ return o.id }));
// Prepare data
var mv_line_dicts = [];
_.each(self.get("mv_lines_selected"), function(o) { mv_line_dicts.push(self.prepareSelectedMoveLineForPersisting(o)) });

View File

@ -128,7 +128,7 @@
<td><span class="glyphicon glyphicon-add-remove"></span></td>
<td><t t-esc="line.account_code"/></td>
<td><t t-esc="line.q_due_date"/></td>
<td><t t-esc="line.q_label"/></td>
<td class="js_qlabel"><t t-esc="line.q_label"/></td>
<td><t t-if="line.debit !== 0">
<t t-if="line.propose_partial_reconcile" t-call="icon_do_partial_reconciliation"></t>

View File

@ -30,7 +30,7 @@ class accounting_report(osv.osv_memory):
_columns = {
'enable_filter': fields.boolean('Enable Comparison'),
'account_report_id': fields.many2one('account.financial.report', 'Account Reports', required=True),
'label_filter': fields.char('Column Label', size=32, help="This label will be displayed on report to show the balance computed for the given comparison filter."),
'label_filter': fields.char('Column Label', help="This label will be displayed on report to show the balance computed for the given comparison filter."),
'fiscalyear_id_cmp': fields.many2one('account.fiscalyear', 'Fiscal Year', help='Keep empty for all open fiscal year'),
'filter_cmp': fields.selection([('filter_no', 'No Filters'), ('filter_date', 'Date'), ('filter_period', 'Periods')], "Filter by", required=True),
'period_from_cmp': fields.many2one('account.period', 'Start Period'),

View File

@ -35,7 +35,7 @@ class account_fiscalyear_close(osv.osv_memory):
'New Fiscal Year', required=True),
'journal_id': fields.many2one('account.journal', 'Opening Entries Journal', domain="[('type','=','situation')]", required=True, help='The best practice here is to use a journal dedicated to contain the opening entries of all fiscal years. Note that you should define it with default debit/credit accounts, of type \'situation\' and with a centralized counterpart.'),
'period_id': fields.many2one('account.period', 'Opening Entries Period', required=True),
'report_name': fields.char('Name of new entries',size=64, required=True, help="Give name of the new entries"),
'report_name': fields.char('Name of new entries', required=True, help="Give name of the new entries"),
}
_defaults = {
'report_name': lambda self, cr, uid, context: _('End of Fiscal Year Entry'),

View File

@ -34,7 +34,7 @@ class account_invoice_refund(osv.osv_memory):
'date': fields.date('Date', help='This date will be used as the invoice date for credit note and period will be chosen accordingly!'),
'period': fields.many2one('account.period', 'Force period'),
'journal_id': fields.many2one('account.journal', 'Refund Journal', help='You can select here the journal to use for the credit note that will be created. If you leave that field empty, it will use the same journal as the current invoice.'),
'description': fields.char('Reason', size=128, required=True),
'description': fields.char('Reason', required=True),
'filter_refund': fields.selection([('refund', 'Create a draft refund'), ('cancel', 'Cancel: create refund and reconcile'),('modify', 'Modify: create refund, reconcile and create a new draft invoice')], "Refund Method", required=True, help='Refund base on this type. You can not Modify and Cancel if the invoice is already reconciled'),
}

View File

@ -107,7 +107,7 @@ class account_move_line_reconcile_writeoff(osv.osv_memory):
'journal_id': fields.many2one('account.journal','Write-Off Journal', required=True),
'writeoff_acc_id': fields.many2one('account.account','Write-Off account', required=True),
'date_p': fields.date('Date'),
'comment': fields.char('Comment', size= 64, required=True),
'comment': fields.char('Comment', required=True),
'analytic_id': fields.many2one('account.analytic.account', 'Analytic Account', domain=[('parent_id', '!=', False)]),
}
_defaults = {

View File

@ -36,11 +36,11 @@ class account_subscription_generate(osv.osv_memory):
def action_generate(self, cr, uid, ids, context=None):
mod_obj = self.pool.get('ir.model.data')
act_obj = self.pool.get('ir.actions.act_window')
sub_line_obj = self.pool.get('account.subscription.line')
moves_created=[]
for data in self.read(cr, uid, ids, context=context):
cr.execute('select id from account_subscription_line where date<%s and move_id is null', (data['date'],))
line_ids = map(lambda x: x[0], cr.fetchall())
moves = self.pool.get('account.subscription.line').move_create(cr, uid, line_ids, context=context)
line_ids = sub_line_obj.search(cr, uid, [('date', '<', data['date']), ('move_id', '=', False)], context=context)
moves = sub_line_obj.move_create(cr, uid, line_ids, context=context)
moves_created.extend(moves)
result = mod_obj.get_object_reference(cr, uid, 'account', 'action_move_line_form')
id = result and result[1] or False

View File

@ -5,7 +5,7 @@ from openerp.tools.translate import _
class CashBox(osv.osv_memory):
_register = False
_columns = {
'name' : fields.char('Reason', size=64, required=True),
'name' : fields.char('Reason', required=True),
# Attention, we don't set a domain, because there is a journal_type key
# in the context of the action
'amount' : fields.float('Amount',
@ -49,7 +49,7 @@ class CashBoxIn(CashBox):
_columns = CashBox._columns.copy()
_columns.update({
'ref' : fields.char('Reference', size=32),
'ref' : fields.char('Reference'),
})
def _compute_values_for_statement_line(self, cr, uid, box, record, context=None):

View File

@ -70,7 +70,7 @@ class account_analytic_plan(osv.osv):
_name = "account.analytic.plan"
_description = "Analytic Plan"
_columns = {
'name': fields.char('Analytic Plan', size=64, required=True, select=True),
'name': fields.char('Analytic Plan', required=True, select=True),
'plan_ids': fields.one2many('account.analytic.plan.line', 'plan_id', 'Analytic Plans'),
}
@ -81,7 +81,7 @@ class account_analytic_plan_line(osv.osv):
_order = "sequence, id"
_columns = {
'plan_id': fields.many2one('account.analytic.plan','Analytic Plan',required=True),
'name': fields.char('Axis Name', size=64, required=True, select=True),
'name': fields.char('Axis Name', required=True, select=True),
'sequence': fields.integer('Sequence'),
'root_analytic_id': fields.many2one('account.analytic.account', 'Root Account', help="Root account of this plan.", required=False),
'min_required': fields.float('Minimum Allowed (%)'),
@ -97,7 +97,7 @@ class account_analytic_plan_instance(osv.osv):
_name = "account.analytic.plan.instance"
_description = "Analytic Plan Instance"
_columns = {
'name': fields.char('Analytic Distribution', size=64),
'name': fields.char('Analytic Distribution'),
'code': fields.char('Distribution Code', size=16),
'journal_id': fields.many2one('account.analytic.journal', 'Analytic Journal' ),
'account_ids': fields.one2many('account.analytic.plan.instance.line', 'plan_id', 'Account Id'),

View File

@ -32,7 +32,7 @@ class account_asset_category(osv.osv):
_description = 'Asset category'
_columns = {
'name': fields.char('Name', size=64, required=True, select=1),
'name': fields.char('Name', required=True, select=1),
'note': fields.text('Note'),
'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic account'),
'account_asset_id': fields.many2one('account.account', 'Asset Account', required=True, domain=[('type','=','other')]),
@ -246,7 +246,7 @@ class account_asset_asset(osv.osv):
_columns = {
'account_move_line_ids': fields.one2many('account.move.line', 'asset_id', 'Entries', readonly=True, states={'draft':[('readonly',False)]}),
'entry_count': fields.function(_entry_count, string='# Asset Entries', type='integer'),
'name': fields.char('Asset Name', size=64, required=True, readonly=True, states={'draft':[('readonly',False)]}),
'name': fields.char('Asset Name', required=True, readonly=True, states={'draft':[('readonly',False)]}),
'code': fields.char('Reference', size=32, readonly=True, states={'draft':[('readonly',False)]}),
'purchase_value': fields.float('Gross Value', required=True, readonly=True, states={'draft':[('readonly',False)]}),
'currency_id': fields.many2one('res.currency','Currency',required=True, readonly=True, states={'draft':[('readonly',False)]}),
@ -379,7 +379,7 @@ class account_asset_depreciation_line(osv.osv):
return res
_columns = {
'name': fields.char('Depreciation Name', size=64, required=True, select=1),
'name': fields.char('Depreciation Name', required=True, select=1),
'sequence': fields.integer('Sequence', required=True),
'asset_id': fields.many2one('account.asset.asset', 'Asset', required=True, ondelete='cascade'),
'parent_state': fields.related('asset_id', 'state', type='char', string='State of Asset'),
@ -474,7 +474,7 @@ class account_asset_history(osv.osv):
_name = 'account.asset.history'
_description = 'Asset history'
_columns = {
'name': fields.char('History name', size=64, select=1),
'name': fields.char('History name', select=1),
'user_id': fields.many2one('res.users', 'User', required=True),
'date': fields.date('Date', required=True),
'asset_id': fields.many2one('account.asset.asset', 'Asset', required=True),

View File

@ -27,7 +27,7 @@ class asset_asset_report(osv.osv):
_description = "Assets Analysis"
_auto = False
_columns = {
'name': fields.char('Year', size=16, required=False, readonly=True),
'name': fields.char('Year', required=False, readonly=True),
'purchase_date': fields.date('Purchase Date', readonly=True),
'depreciation_date': fields.date('Depreciation Date', readonly=True),
'asset_id': fields.many2one('account.asset.asset', string='Asset', readonly=True),

View File

@ -28,7 +28,7 @@ class asset_modify(osv.osv_memory):
_description = 'Modify Asset'
_columns = {
'name': fields.char('Reason', size=64, required=True),
'name': fields.char('Reason', required=True),
'method_number': fields.integer('Number of Depreciations', required=True),
'method_period': fields.integer('Period Length'),
'method_end': fields.date('Ending date'),

View File

@ -62,7 +62,7 @@ class account_bank_statement_line_global(osv.osv):
_description = 'Batch Payment Info'
_columns = {
'name': fields.char('OBI', size=128, required=True, help="Originator to Beneficiary Information"),
'name': fields.char('OBI', required=True, help="Originator to Beneficiary Information"),
'code': fields.char('Code', size=64, required=True),
'parent_id': fields.many2one('account.bank.statement.line.global', 'Parent Code', ondelete='cascade'),
'child_ids': fields.one2many('account.bank.statement.line.global', 'parent_id', 'Child Codes'),

View File

@ -39,7 +39,7 @@ class account_budget_post(osv.osv):
_description = "Budgetary Position"
_columns = {
'code': fields.char('Code', size=64, required=True),
'name': fields.char('Name', size=256, required=True),
'name': fields.char('Name', required=True),
'account_ids': fields.many2many('account.account', 'account_budget_rel', 'budget_id', 'account_id', 'Accounts'),
'crossovered_budget_line': fields.one2many('crossovered.budget.lines', 'general_budget_id', 'Budget Lines'),
'company_id': fields.many2one('res.company', 'Company', required=True),
@ -56,7 +56,7 @@ class crossovered_budget(osv.osv):
_description = "Budget"
_columns = {
'name': fields.char('Name', size=64, required=True, states={'done':[('readonly',True)]}),
'name': fields.char('Name', required=True, states={'done':[('readonly',True)]}),
'code': fields.char('Code', size=16, required=True, states={'done':[('readonly',True)]}),
'creating_user_id': fields.many2one('res.users', 'Responsible User'),
'validating_user_id': fields.many2one('res.users', 'Validate User', readonly=True),

View File

@ -36,9 +36,9 @@ class account_voucher(osv.osv):
return journal_pool.search(cr, uid, [('type', '=', ttype)], limit=1)
_columns = {
'amount_in_word' : fields.char("Amount in Word" , size=128, readonly=True, states={'draft':[('readonly',False)]}),
'amount_in_word' : fields.char("Amount in Word", readonly=True, states={'draft':[('readonly',False)]}),
'allow_check' : fields.related('journal_id', 'allow_check_writing', type='boolean', string='Allow Check Writing'),
'number': fields.char('Number', size=32),
'number': fields.char('Number'),
}
def _amount_to_text(self, cr, uid, amount, currency_id, context=None):

View File

@ -49,7 +49,7 @@ class followup_line(osv.osv):
_name = 'account_followup.followup.line'
_description = 'Follow-up Criteria'
_columns = {
'name': fields.char('Follow-Up Action', size=64, required=True),
'name': fields.char('Follow-Up Action', required=True),
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of follow-up lines."),
'delay': fields.integer('Due Days', help="The number of days after the due date of the invoice to wait before sending the reminder. Could be negative if you want to send a polite alert beforehand.", required=True),
'followup_id': fields.many2one('account_followup.followup', 'Follow Ups', required=True, ondelete="cascade"),

View File

@ -30,7 +30,7 @@ class payment_mode(osv.osv):
_name= 'payment.mode'
_description= 'Payment Mode'
_columns = {
'name': fields.char('Name', size=64, required=True, help='Mode of Payment'),
'name': fields.char('Name', required=True, help='Mode of Payment'),
'bank_id': fields.many2one('res.partner.bank', "Bank account",
required=True,help='Bank Account for the Payment Mode'),
'journal': fields.many2one('account.journal', 'Journal', required=True,
@ -87,7 +87,7 @@ class payment_order(osv.osv):
_columns = {
'date_scheduled': fields.date('Scheduled Date', states={'done':[('readonly', True)]}, help='Select a date if you have chosen Preferred Date to be fixed.'),
'reference': fields.char('Reference', size=128, required=1, states={'done': [('readonly', True)]}),
'reference': fields.char('Reference', required=1, states={'done': [('readonly', True)]}),
'mode': fields.many2one('payment.mode', 'Payment Mode', select=True, required=1, states={'done': [('readonly', True)]}, help='Select the Payment Mode to be applied.'),
'state': fields.selection([
('draft', 'Draft'),
@ -303,9 +303,9 @@ class payment_line(osv.osv):
return res
_columns = {
'name': fields.char('Your Reference', size=64, required=True),
'communication': fields.char('Communication', size=64, required=True, help="Used as the message between ordering customer and current company. Depicts 'What do you want to say to the recipient about this order ?'"),
'communication2': fields.char('Communication 2', size=64, help='The successor message of Communication.'),
'name': fields.char('Your Reference', required=True),
'communication': fields.char('Communication', required=True, help="Used as the message between ordering customer and current company. Depicts 'What do you want to say to the recipient about this order ?'"),
'communication2': fields.char('Communication 2', help='The successor message of Communication.'),
'move_line_id': fields.many2one('account.move.line', 'Entry line', domain=[('reconcile_id', '=', False), ('account_id.type', '=', 'payable')], help='This Entry Line will be referred for the information of the ordering customer.'),
'amount_currency': fields.float('Amount in Partner Currency', digits=(16, 2),
required=True, help='Payment amount in the partner currency'),

View File

@ -26,7 +26,7 @@ class account_move(osv.osv):
_inherit = 'account.move'
_columns = {
'internal_sequence_number': fields.char('Internal Number', size=64, readonly=True, help='Internal Sequence Number'),
'internal_sequence_number': fields.char('Internal Number', readonly=True, help='Internal Sequence Number'),
}
def post(self, cr, uid, ids, context=None):

View File

@ -26,9 +26,9 @@ class account_sequence_installer(osv.osv_memory):
_inherit = 'res.config.installer'
_columns = {
'name': fields.char('Name',size=64, required=True),
'prefix': fields.char('Prefix',size=64, help="Prefix value of the record for the sequence"),
'suffix': fields.char('Suffix',size=64, help="Suffix value of the record for the sequence"),
'name': fields.char('Name', required=True),
'prefix': fields.char('Prefix', size=64, help="Prefix value of the record for the sequence"),
'suffix': fields.char('Suffix', size=64, help="Suffix value of the record for the sequence"),
'number_next': fields.integer('Next Number', required=True, help="Next number of this sequence"),
'number_increment': fields.integer('Increment Number', required=True, help="The next number of the sequence will be incremented by this number"),
'padding' : fields.integer('Number padding', required=True, help="OpenERP will automatically adds some '0' on the left of the 'Next Number' to get the required padding size."),

View File

@ -43,7 +43,7 @@ class accounting_assert_test(osv.osv):
_order = "sequence"
_columns = {
'name': fields.char('Test Name', size=256, required=True, select=True, translate=True),
'name': fields.char('Test Name', required=True, select=True, translate=True),
'desc': fields.text('Test Description', select=True, translate=True),
'code_exec': fields.text('Python code', required=True),
'active': fields.boolean('Active'),

View File

@ -333,7 +333,7 @@ class account_voucher(osv.osv):
('payment','Payment'),
('receipt','Receipt'),
],'Default Type', readonly=True, states={'draft':[('readonly',False)]}),
'name':fields.char('Memo', size=256, readonly=True, states={'draft':[('readonly',False)]}),
'name':fields.char('Memo', readonly=True, states={'draft':[('readonly',False)]}),
'date':fields.date('Date', readonly=True, select=True, states={'draft':[('readonly',False)]}, help="Effective date for accounting entries"),
'journal_id':fields.many2one('account.journal', 'Journal', required=True, readonly=True, states={'draft':[('readonly',False)]}),
'account_id':fields.many2one('account.account', 'Account', required=True, readonly=True, states={'draft':[('readonly',False)]}),
@ -351,15 +351,15 @@ class account_voucher(osv.osv):
('cancel','Cancelled'),
('proforma','Pro-forma'),
('posted','Posted')
], 'Status', readonly=True, size=32, track_visibility='onchange',
], 'Status', readonly=True, track_visibility='onchange',
help=' * The \'Draft\' status is used when a user is encoding a new and unconfirmed Voucher. \
\n* The \'Pro-forma\' when voucher is in Pro-forma status,voucher does not have an voucher number. \
\n* The \'Posted\' status is used when user create voucher,a voucher number is generated and voucher entries are created in account \
\n* The \'Cancelled\' status is used when user cancel voucher.'),
'amount': fields.float('Total', digits_compute=dp.get_precision('Account'), required=True, readonly=True, states={'draft':[('readonly',False)]}),
'tax_amount':fields.float('Tax Amount', digits_compute=dp.get_precision('Account'), readonly=True, states={'draft':[('readonly',False)]}),
'reference': fields.char('Ref #', size=64, readonly=True, states={'draft':[('readonly',False)]}, help="Transaction reference number."),
'number': fields.char('Number', size=32, readonly=True,),
'reference': fields.char('Ref #', readonly=True, states={'draft':[('readonly',False)]}, help="Transaction reference number."),
'number': fields.char('Number', readonly=True,),
'move_id':fields.many2one('account.move', 'Account Entry'),
'move_ids': fields.related('move_id','line_id', type='one2many', relation='account.move.line', string='Journal Items', readonly=True),
'partner_id':fields.many2one('res.partner', 'Partner', change_default=1, readonly=True, states={'draft':[('readonly',False)]}),
@ -377,7 +377,7 @@ class account_voucher(osv.osv):
('with_writeoff', 'Reconcile Payment Balance'),
], 'Payment Difference', required=True, readonly=True, states={'draft': [('readonly', False)]}, help="This field helps you to choose what you want to do with the eventual difference between the paid amount and the sum of allocated amounts. You can either choose to keep open this difference on the partner's account, or reconcile it with the payment(s)"),
'writeoff_acc_id': fields.many2one('account.account', 'Counterpart Account', readonly=True, states={'draft': [('readonly', False)]}),
'comment': fields.char('Counterpart Comment', size=64, required=True, readonly=True, states={'draft': [('readonly', False)]}),
'comment': fields.char('Counterpart Comment', required=True, readonly=True, states={'draft': [('readonly', False)]}),
'analytic_id': fields.many2one('account.analytic.account','Write-Off Analytic Account', readonly=True, states={'draft': [('readonly', False)]}),
'writeoff_amount': fields.function(_get_writeoff_amount, string='Difference Amount', type='float', readonly=True, help="Computed as the difference between the amount stated in the voucher and the sum of allocation on the voucher lines."),
'payment_rate_currency_id': fields.many2one('res.currency', 'Payment Rate Currency', required=True, readonly=True, states={'draft':[('readonly',False)]}),
@ -1482,7 +1482,7 @@ class account_voucher_line(osv.osv):
_columns = {
'voucher_id':fields.many2one('account.voucher', 'Voucher', required=1, ondelete='cascade'),
'name':fields.char('Description', size=256),
'name':fields.char('Description',),
'account_id':fields.many2one('account.account','Account', required=True),
'partner_id':fields.related('voucher_id', 'partner_id', type='many2one', relation='res.partner', string='Partner'),
'untax_amount':fields.float('Untax Amount'),

View File

@ -171,7 +171,7 @@ class account_analytic_account(osv.osv):
return result
_columns = {
'name': fields.char('Account/Contract Name', size=128, required=True, track_visibility='onchange'),
'name': fields.char('Account/Contract Name', required=True, track_visibility='onchange'),
'complete_name': fields.function(_get_full_name, type='char', string='Full Name'),
'code': fields.char('Reference', select=True, track_visibility='onchange'),
'type': fields.selection([('view','Analytic View'), ('normal','Analytic Account'),('contract','Contract or Project'),('template','Template of Contract')], 'Type of Account', required=True,
@ -314,7 +314,7 @@ class account_analytic_line(osv.osv):
_description = 'Analytic Line'
_columns = {
'name': fields.char('Description', size=256, required=True),
'name': fields.char('Description', required=True),
'date': fields.date('Date', required=True, select=True),
'amount': fields.float('Amount', required=True, help='Calculated by multiplying the quantity and the price given in the Product\'s cost price. Always expressed in the company main currency.', digits_compute=dp.get_precision('Account')),
'unit_amount': fields.float('Quantity', help='Specifies the amount of quantity to count.'),

View File

@ -54,9 +54,9 @@ class ir_model_fields_anonymization(osv.osv):
_rec_name = 'field_id'
_columns = {
'model_name': fields.char('Object Name', size=128, required=True),
'model_name': fields.char('Object Name', required=True),
'model_id': fields.many2one('ir.model', 'Object', ondelete='set null'),
'field_name': fields.char('Field Name', size=128, required=True),
'field_name': fields.char('Field Name', required=True),
'field_id': fields.many2one('ir.model.fields', 'Field', ondelete='set null'),
'state': fields.selection(selection=FIELD_STATES, String='Status', required=True, readonly=True),
}
@ -226,9 +226,9 @@ class ir_model_fields_anonymization_history(osv.osv):
'date': fields.datetime('Date', required=True, readonly=True),
'field_ids': fields.many2many('ir.model.fields.anonymization', 'anonymized_field_to_history_rel', 'field_id', 'history_id', 'Fields', readonly=True),
'state': fields.selection(selection=ANONYMIZATION_HISTORY_STATE, string='Status', required=True, readonly=True),
'direction': fields.selection(selection=ANONYMIZATION_DIRECTION, string='Direction', required=True, readonly=True),
'direction': fields.selection(selection=ANONYMIZATION_DIRECTION, string='Direction', size=20, required=True, readonly=True),
'msg': fields.text('Message', readonly=True),
'filepath': fields.char(string='File path', size=256, readonly=True),
'filepath': fields.char(string='File path', readonly=True),
}
@ -253,7 +253,7 @@ class ir_model_fields_anonymize_wizard(osv.osv_memory):
return res
_columns = {
'name': fields.char(size=64, string='File Name'),
'name': fields.char(string='File Name'),
'summary': fields.function(_get_summary, type='text', string='Summary'),
'file_export': fields.binary(string='Export'),
'file_import': fields.binary(string='Import', help="This is the file created by the anonymization process. It should have the '.pickle' extention."),

View File

@ -205,16 +205,16 @@ class CompanyLDAP(osv.osv):
'sequence': fields.integer('Sequence'),
'company': fields.many2one('res.company', 'Company', required=True,
ondelete='cascade'),
'ldap_server': fields.char('LDAP Server address', size=64, required=True),
'ldap_server': fields.char('LDAP Server address', required=True),
'ldap_server_port': fields.integer('LDAP Server port', required=True),
'ldap_binddn': fields.char('LDAP binddn', size=64,
'ldap_binddn': fields.char('LDAP binddn',
help=("The user account on the LDAP server that is used to query "
"the directory. Leave empty to connect anonymously.")),
'ldap_password': fields.char('LDAP password', size=64,
'ldap_password': fields.char('LDAP password',
help=("The password of the user account on the LDAP server that is "
"used to query the directory.")),
'ldap_filter': fields.char('LDAP filter', size=256, required=True),
'ldap_base': fields.char('LDAP base', size=64, required=True),
'ldap_filter': fields.char('LDAP filter', required=True),
'ldap_base': fields.char('LDAP base', required=True),
'user': fields.many2one('res.users', 'Template User',
help="User to copy when creating new users"),
'create_user': fields.boolean('Create user',

View File

@ -54,7 +54,7 @@ class base_action_rule(osv.osv):
_order = 'sequence'
_columns = {
'name': fields.char('Rule Name', size=64, required=True),
'name': fields.char('Rule Name', required=True),
'model_id': fields.many2one('ir.model', 'Related Document Model',
required=True, domain=[('osv_memory', '=', False)]),
'model': fields.related('model_id', 'model', type="char", size=256, string='Model'),
@ -156,13 +156,13 @@ class base_action_rule(osv.osv):
""" Return a wrapper around `old_create` calling both `old_create` and
`_process`, in that order.
"""
def create(cr, uid, vals, context=None):
def create(cr, uid, vals, context=None, **kwargs):
# avoid loops or cascading actions
if context and context.get('action'):
return old_create(cr, uid, vals, context=context)
context = dict(context or {}, action=True)
new_id = old_create(cr, uid, vals, context=context)
new_id = old_create(cr, uid, vals, context=context, **kwargs)
# retrieve the action rules to run on creation
action_dom = [('model', '=', model), ('kind', 'in', ['on_create', 'on_create_or_write'])]
@ -180,10 +180,10 @@ class base_action_rule(osv.osv):
""" Return a wrapper around `old_write` calling both `old_write` and
`_process`, in that order.
"""
def write(cr, uid, ids, vals, context=None):
def write(cr, uid, ids, vals, context=None, **kwargs):
# avoid loops or cascading actions
if context and context.get('action'):
return old_write(cr, uid, ids, vals, context=context)
return old_write(cr, uid, ids, vals, context=context, **kwargs)
context = dict(context or {}, action=True)
ids = [ids] if isinstance(ids, (int, long, str)) else ids
@ -199,7 +199,7 @@ class base_action_rule(osv.osv):
pre_ids[action] = self._filter(cr, uid, action, action.filter_pre_id, ids, context=context)
# execute write
old_write(cr, uid, ids, vals, context=context)
old_write(cr, uid, ids, vals, context=context, **kwargs)
# check postconditions, and execute actions on the records that satisfy them
for action in actions:

View File

@ -12,7 +12,7 @@ class lead_test(osv.Model):
_name = "base.action.rule.lead.test"
_columns = {
'name': fields.char('Subject', size=64, required=True, select=1),
'name': fields.char('Subject', required=True, select=1),
'user_id': fields.many2one('res.users', 'Responsible'),
'state': fields.selection(AVAILABLE_STATES, string="Status", readonly=True),
'active': fields.boolean('Active', required=False),

View File

@ -1,22 +1,53 @@
# -*- coding: utf-8 -*-
import openerp
from openerp import SUPERUSER_ID
from openerp.addons.web import http
from openerp.addons.web.http import request
from werkzeug.wrappers import BaseResponse as Response
import json
class website_gengo(http.Controller):
def get_gengo_key(self, cr):
icp = request.registry['ir.config_parameter']
return icp.get_param(cr, SUPERUSER_ID, request.registry['base.gengo.translations'].GENGO_KEY, default="")
@http.route('/website/gengo_callback', type='http', auth='none')
def gengo_callback(self,**post):
def gengo_callback(self, **post):
cr, uid, context = request.cr, openerp.SUPERUSER_ID, request.context
translation_pool = request.registry['ir.translation']
if post and post.get('job'):
job = json.loads(post['job'])
if post and post.get('job') and post.get('pgk'):
if post.get('pgk') != self.get_gengo_key(cr):
return Response("Bad authentication - 403/412", status=412)
job = json.loads(post['job'], 'utf-8')
tid = job.get('custom_data', False)
if (job.get('status') == 'approved') and tid:
term = translation_pool.browse(cr, uid, int(tid), context=context)
if term.job_id <> job.get('job_id'):
raise 'Error'
vals = {'state': 'translated', 'value': job.get('body_tgt')}
translation_pool.write(cr, uid, [int(tid)], vals, context=context)
if term.src != job.get('body_src'):
return Response("Text Altered - Not saved", status=100)
domain = [
'|',
('id', "=", int(tid)),
'&', '&', '&', '&', '&',
('state', '=', term.state),
('gengo_translation', '=', term.gengo_translation),
('src', "=", term.src),
('type', "=", term.type),
('name', "=", term.name),
('lang', "=", term.lang),
#('order_id', "=", term.order_id),
]
all_ir_tanslations = translation_pool.search(cr, uid, domain, context=context or {})
if all_ir_tanslations:
vals = {'state': 'translated', 'value': job.get('body_tgt')}
translation_pool.write(cr, uid, all_ir_tanslations, vals, context=context)
return Response("OK", status=200)
else:
return Response("No terms found", status=104)
return Response("Not saved", status=100)

View File

@ -8,6 +8,7 @@
<field name="interval_number">6</field>
<field name="interval_type">hours</field>
<field name="numbercall">-1</field>
<field name="doall">0</field>
<field eval="'base.gengo.translations'" name="model"></field>
<field eval="'_sync_response'" name="function"/>
<field eval="'(20,)'" name="args"/>
@ -20,6 +21,7 @@
<field name="interval_number">6</field>
<field name="interval_type">hours</field>
<field name="numbercall">-1</field>
<field name="doall">0</field>
<field eval="'base.gengo.translations'" name="model"></field>
<field eval="'_sync_request'" name="function"/>
<field eval="'(20,)'" name="args"/>

View File

@ -56,16 +56,18 @@ LANG_CODE_MAPPING = {
'fi_FI': ('fi', 'Finnish')
}
class ir_translation(osv.Model):
_name = "ir.translation"
_inherit = "ir.translation"
_columns = {
'gengo_comment': fields.text("Comments & Activity Linked to Gengo"),
'job_id': fields.char('Gengo Job ID', size=32),
'order_id': fields.char('Gengo Order ID', size=32),
"gengo_translation": fields.selection([('machine', 'Translation By Machine'),
('standard', 'Standard'),
('pro', 'Pro'),
('ultra', 'Ultra')], "Gengo Translation Service Level", help='You can select here the service level you want for an automatic translation using Gengo.'),
('standard', 'Standard'),
('pro', 'Pro'),
('ultra', 'Ultra')], "Gengo Translation Service Level", help='You can select here the service level you want for an automatic translation using Gengo.'),
}
def _get_all_supported_languages(self, cr, uid, context=None):
@ -83,3 +85,19 @@ class ir_translation(osv.Model):
def _get_gengo_corresponding_language(cr, lang):
return lang in LANG_CODE_MAPPING and LANG_CODE_MAPPING[lang][0] or lang
def _get_source_query(self, cr, uid, name, types, lang, source, res_id):
query, params = super(ir_translation, self)._get_source_query(cr, uid, name, types, lang, source, res_id)
query += """
ORDER BY
CASE
WHEN gengo_translation=%s then 10
WHEN gengo_translation=%s then 20
WHEN gengo_translation=%s then 30
WHEN gengo_translation=%s then 40
ELSE 0
END DESC
"""
params += ('machine', 'standard', 'ultra', 'pro',)
return (query, params)

View File

@ -19,12 +19,13 @@
#
##############################################################################
import uuid
import logging
import re
import time
from openerp.osv import osv, fields
from openerp import tools
from openerp import tools, SUPERUSER_ID
from openerp.tools.translate import _
_logger = logging.getLogger(__name__)
@ -36,7 +37,9 @@ except ImportError:
GENGO_DEFAULT_LIMIT = 20
class base_gengo_translations(osv.osv_memory):
GENGO_KEY = "Gengo.UUID"
_name = 'base.gengo.translations'
_columns = {
@ -46,9 +49,20 @@ class base_gengo_translations(osv.osv_memory):
'lang_id': fields.many2one('res.lang', 'Language', required=True),
'sync_limit': fields.integer("No. of terms to sync"),
}
_defaults = {'sync_type' : 'both',
'sync_limit' : 20
}
_defaults = {
'sync_type': 'both',
'sync_limit': 20
}
def init(self, cr):
icp = self.pool['ir.config_parameter']
if not icp.get_param(cr, SUPERUSER_ID, self.GENGO_KEY, default=None):
icp.set_param(cr, SUPERUSER_ID, self.GENGO_KEY, str(uuid.uuid4()), groups=['base.group_website_designer', 'base.group_website_publisher'])
def get_gengo_key(self, cr):
icp = self.pool['ir.config_parameter']
return icp.get_param(cr, SUPERUSER_ID, self.GENGO_KEY, default="Undefined")
def gengo_authentication(self, cr, uid, context=None):
'''
This method tries to open a connection with Gengo. For that, it uses the Public and Private
@ -113,48 +127,68 @@ class base_gengo_translations(osv.osv_memory):
_logger.warning("%s", gengo)
else:
offset = 0
all_translation_ids = translation_pool.search(cr, uid, [('state', '=', 'inprogress'), ('gengo_translation', 'in', ('machine', 'standard', 'pro', 'ultra')), ('job_id', "!=", False)], context=context)
all_translation_ids = translation_pool.search(cr, uid, [('state', '=', 'inprogress'), ('gengo_translation', 'in', ('machine', 'standard', 'pro', 'ultra')), ('order_id', "!=", False)], context=context)
while True:
translation_ids = all_translation_ids[offset:offset + limit]
offset += limit
if not translation_ids:
break
terms_progress = {
'gengo_order_ids': set(),
'ir_translation_ids': set(),
}
translation_terms = translation_pool.browse(cr, uid, translation_ids, context=context)
gengo_job_id = [term.job_id for term in translation_terms]
if gengo_job_id:
gengo_ids = ','.join(gengo_job_id)
for term in translation_terms:
terms_progress['gengo_order_ids'].add(term.order_id)
terms_progress['ir_translation_ids'].add(tools.ustr(term.id))
for order_id in terms_progress['gengo_order_ids']:
order_response = gengo.getTranslationOrderJobs(id=order_id)
jobs_approved = order_response.get('response', []).get('order', []).get('jobs_approved', [])
gengo_ids = ','.join(jobs_approved)
if gengo_ids: # Need to check, because getTranslationJobBatch don't catch this case and so call the getTranslationJobs because no ids in url
try:
job_response = gengo.getTranslationJobBatch(id=gengo_ids)
except:
continue
if job_response['opstat'] == 'ok':
for job in job_response['response'].get('jobs', []):
self._update_terms_job(cr, uid, job, context=context)
if job.get('custom_data') in terms_progress['ir_translation_ids']:
self._update_terms_job(cr, uid, job, context=context)
return True
def _update_terms_job(self, cr, uid, job, context=None):
translation_pool = self.pool.get('ir.translation')
tid = int(job['custom_data'])
vals = {}
if job.get('job_id', False):
vals['job_id'] = job['job_id']
if job.get('status', False) in ('queued', 'available', 'pending', 'reviewable'):
vals['state'] = 'inprogress'
if job.get('status', False) in ('queued','available','pending','reviewable'):
vals['state'] = 'inprogress'
if job.get('body_tgt', False) and job.get('status', False)=='approved':
if job.get('body_tgt', False) and job.get('status', False) == 'approved':
vals['value'] = job['body_tgt']
if job.get('status', False) in ('approved', 'canceled'):
vals['state'] = 'translated'
if vals:
translation_pool.write(cr, uid, [tid], vals, context=context)
def _update_terms(self, cr, uid, response, context=None):
def _update_terms(self, cr, uid, response, term_ids, context=None):
"""
Update the terms after their translation were requested to Gengo
"""
for jobs in response.get('jobs', []):
translation_pool = self.pool.get('ir.translation')
vals = {
'order_id': response.get('order_id', ''),
'state': 'inprogress'
}
translation_pool.write(cr, uid, term_ids, vals, context=context)
jobs = response.get('jobs', [])
if jobs:
for t_id, res in jobs.items():
self._update_terms_job(cr, uid, res, context=context)
return
def pack_jobs_request(self, cr, uid, term_ids, context=None):
@ -164,7 +198,7 @@ class base_gengo_translations(osv.osv_memory):
'term2.id': {...}
}
}'''
base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url')
translation_pool = self.pool.get('ir.translation')
jobs = {}
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
@ -173,7 +207,7 @@ class base_gengo_translations(osv.osv_memory):
if re.search(r"\w", term.src or ""):
comment = user.company_id.gengo_comment or ''
if term.gengo_comment:
comment+='\n' + term.gengo_comment
comment += '\n' + term.gengo_comment
jobs[time.strftime('%Y%m%d%H%M%S') + '-' + str(term.id)] = {
'type': 'text',
'slug': 'Single :: English to ' + term.lang,
@ -184,10 +218,9 @@ class base_gengo_translations(osv.osv_memory):
'lc_tgt': translation_pool._get_gengo_corresponding_language(term.lang),
'auto_approve': auto_approve,
'comment': comment,
'callback_url': self.pool.get('ir.config_parameter').get_param(cr, uid,'web.base.url') + '/website/gengo_callback'
'callback_url': "%s/website/gengo_callback?pgk=%s&db=%s" % (base_url, self.get_gengo_key(cr), cr.dbname)
}
return {'jobs': jobs, 'as_group': 1}
return {'jobs': jobs, 'as_group': 0}
def _send_translation_terms(self, cr, uid, term_ids, context=None):
"""
@ -200,7 +233,7 @@ class base_gengo_translations(osv.osv_memory):
if request['jobs']:
result = gengo.postTranslationJobs(jobs=request)
if result['opstat'] == 'ok':
self._update_terms(cr, uid, result['response'], context=context)
self._update_terms(cr, uid, result['response'], term_ids, context=context)
else:
_logger.error(gengo)
return True
@ -218,10 +251,10 @@ class base_gengo_translations(osv.osv_memory):
context = {}
language_pool = self.pool.get('res.lang')
translation_pool = self.pool.get('ir.translation')
domain = [('state', '=', 'to_translate'), ('gengo_translation', 'in', ('machine', 'standard', 'pro', 'ultra')), ('job_id', "=", False)]
domain = [('state', '=', 'to_translate'), ('gengo_translation', 'in', ('machine', 'standard', 'pro', 'ultra')), ('order_id', "=", False)]
if context.get('gengo_language', False):
lc = language_pool.browse(cr, uid, context['gengo_language'], context=context).code
domain.append( ('lang', '=', lc) )
domain.append(('lang', '=', lc))
all_term_ids = translation_pool.search(cr, uid, domain, context=context)
try:

View File

@ -22,11 +22,11 @@ class ir_import(orm.TransientModel):
_transient_max_hours = 12.0
_columns = {
'res_model': fields.char('Model', size=64),
'res_model': fields.char('Model'),
'file': fields.binary(
'File', help="File to check and/or import, raw binary (not base64)"),
'file_name': fields.char('File Name', size=None),
'file_type': fields.char('File Type', size=None),
'file_name': fields.char('File Name'),
'file_type': fields.char('File Type'),
}
def get_fields(self, cr, uid, model, context=None,

View File

@ -6,42 +6,42 @@ class char(orm.Model):
_name = name('char')
_columns = {
'value': fields.char('unknown', size=None)
'value': fields.char('unknown')
}
class char_required(orm.Model):
_name = name('char.required')
_columns = {
'value': fields.char('unknown', size=None, required=True)
'value': fields.char('unknown', required=True)
}
class char_readonly(orm.Model):
_name = name('char.readonly')
_columns = {
'value': fields.char('unknown', size=None, readonly=True)
'value': fields.char('unknown', readonly=True)
}
class char_states(orm.Model):
_name = name('char.states')
_columns = {
'value': fields.char('unknown', size=None, readonly=True, states={'draft': [('readonly', False)]})
'value': fields.char('unknown', readonly=True, states={'draft': [('readonly', False)]})
}
class char_noreadonly(orm.Model):
_name = name('char.noreadonly')
_columns = {
'value': fields.char('unknown', size=None, readonly=True, states={'draft': [('invisible', True)]})
'value': fields.char('unknown', readonly=True, states={'draft': [('invisible', True)]})
}
class char_stillreadonly(orm.Model):
_name = name('char.stillreadonly')
_columns = {
'value': fields.char('unknown', size=None, readonly=True, states={'draft': [('readonly', True)]})
'value': fields.char('unknown', readonly=True, states={'draft': [('readonly', True)]})
}
# TODO: complex field (m2m, o2m, m2o)
@ -95,7 +95,7 @@ class preview_model(orm.Model):
_name = name('preview')
_columns = {
'name': fields.char('Name', size=None),
'name': fields.char('Name'),
'somevalue': fields.integer('Some Value', required=True),
'othervalue': fields.integer('Other Variable'),
}

View File

@ -35,8 +35,8 @@ class base_report_designer_installer(osv.osv_memory):
return data
_columns = {
'name':fields.char('File name', size=34),
'plugin_file':fields.char('OpenObject Report Designer Plug-in', size=256, readonly=True, help="OpenObject Report Designer plug-in file. Save as this file and install this plug-in in OpenOffice."),
'name':fields.char('File name'),
'plugin_file':fields.char('OpenObject Report Designer Plug-in', readonly=True, help="OpenObject Report Designer plug-in file. Save as this file and install this plug-in in OpenOffice."),
'description':fields.text('Description', readonly=True)
}

View File

@ -81,8 +81,7 @@ class base_config_settings(osv.osv_memory):
return self.pool.get("res.font").font_scan(cr, uid, context=context)
# Preferences wizard for Sales & CRM.
# It is defined here because it is inherited independently in modules sale, crm,
# plugin_outlook and plugin_thunderbird.
# It is defined here because it is inherited independently in modules sale, crm.
class sale_config_settings(osv.osv_memory):
_name = 'sale.config.settings'
_inherit = 'res.config.settings'
@ -91,18 +90,6 @@ class sale_config_settings(osv.osv_memory):
help="""When you create a new contact (person or company), you will be able to load all the data from LinkedIn (photos, address, etc)."""),
'module_crm': fields.boolean('CRM'),
'module_sale' : fields.boolean('SALE'),
'module_plugin_thunderbird': fields.boolean('Enable Thunderbird plug-in',
help='The plugin allows you archive email and its attachments to the selected '
'OpenERP objects. You can select a partner, or a lead and '
'attach the selected mail as a .eml file in '
'the attachment of a selected record. You can create documents for CRM Lead, '
'Partner from the selected emails.\n'
'-This installs the module plugin_thunderbird.'),
'module_plugin_outlook': fields.boolean('Enable Outlook plug-in',
help='The Outlook plugin allows you to select an object that you would like to add '
'to your email and its attachments from MS Outlook. You can select a partner, '
'or a lead object and archive a selected email into an OpenERP mail message with attachments.\n'
'-This installs the module plugin_outlook.'),
'module_mass_mailing': fields.boolean(
'Manage mass mailing campaigns',
help='Get access to statistics with your mass mailing, manage campaigns.'),

View File

@ -159,26 +159,13 @@
<div name="config_sale">
<field name="module_crm" invisible="1"/>
<separator string="Emails Integration" attrs="{'invisible': [('module_crm','=',False)]}"/>
<p attrs="{'invisible': [('module_crm','=',False)]}">
<p name="config_email_integration" attrs="{'invisible': [('module_crm','=',False)]}">
OpenERP allows to automatically create leads (or others documents)
from incoming emails. You can automatically synchronize emails with OpenERP
using regular POP/IMAP accounts, using a direct email integration script for your
email server, or by manually pushing emails to OpenERP using specific
plugins for your preferred email application.
</p>
<group name="On Mail Client" attrs="{'invisible': [('module_crm','=',False)]}">
<label for="id" string="On Mail Client"/>
<div>
<div name="module_plugin_thunderbird" attrs="{'invisible': [('module_crm','=',False)]}" class="oe_inline">
<field name="module_plugin_thunderbird"/>
<label for="module_plugin_thunderbird"/>
</div>
<div name="module_plugin_outlook" attrs="{'invisible': [('module_crm','=',False)]}">
<field name="module_plugin_outlook" class="oe_inline"/>
<label for="module_plugin_outlook"/>
</div>
</div>
</group>
</div>
<div name="config_other"/>
</form>

View File

@ -168,7 +168,7 @@ class board_create(osv.osv_memory):
_description = "Board Creation"
_columns = {
'name': fields.char('Board Name', size=64, required=True),
'name': fields.char('Board Name', required=True),
'menu_parent_id': fields.many2one('ir.ui.menu', 'Parent Menu', required=True),
}

View File

@ -43,7 +43,6 @@ If you need to manage your meetings, you should install the CRM module.
'security/ir.model.access.csv',
'security/calendar_security.xml',
'calendar_view.xml',
'contacts_view.xml',
'calendar_data.xml',
'views/calendar.xml',
],

View File

@ -762,7 +762,6 @@ class calendar_event(osv.Model):
res[meeting_id][field] = meeting.start_date if meeting.allday else meeting.start_datetime
elif field == 'stop':
res[meeting_id][field] = meeting.stop_date if meeting.allday else meeting.stop_datetime
return res
def _get_rulestring(self, cr, uid, ids, name, arg, context=None):

View File

@ -1,31 +0,0 @@
<?xml version="1.0"?>
<openerp>
<data>
<record id="view_calendar_contacts" model="ir.ui.view">
<field name="name">My Coworkers</field>
<field name="model">calendar.contacts</field>
<field name="arch" type="xml">
<tree string="contacts" editable="bottom">
<field name="partner_id"/>
</tree>
</field>
</record>
<record id="action_calendar_contacts" model="ir.actions.act_window">
<field name="name">Calendar Contacts</field>
<field name="res_model">calendar.contacts</field>
<field name="view_type">form</field>
<field name="view_mode">tree</field>
<field name="domain">[('user_id','=',uid)]</field>
<field name="view_id" ref="view_calendar_contacts" />
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click on "<b>create</b>" to select colleagues you want to see meetings.
</p><p>
Your colleagues will appear in the right list to see them in the calendar view. You will easily manage collaboration and meeting with them.
</p>
</field>
</record>
</data>
</openerp>

View File

@ -72,3 +72,13 @@ span.no-wrap {
.cal_tab {
margin: 20 0 20 0;
}
.openerp .oe_remove_follower {
cursor: pointer;
position: absolute;
right: 0px;
line-height: 20px;
color: #D3D3D3;
}
.openerp .oe_add_input_box > div > input{
width: 200px;
}

View File

@ -1,9 +1,136 @@
openerp.calendar = function(instance) {
var _t = instance.web._t;
var _t = instance.web._t,
_lt = instance.web._lt;
var QWeb = instance.web.qweb;
instance.calendar = {};
function reload_favorite_list(result) {
var self = current = result;
if (result.view) {
self = result.view;
}
new instance.web.Model("res.users").query(["partner_id"]).filter([["id", "=",self.dataset.context.uid]]).first()
.done(
function(result) {
var sidebar_items = {};
var filter_value = result.partner_id[0];
var filter_item = {
value: filter_value,
label: result.partner_id[1] + _lt(" [Me]"),
color: self.get_color(filter_value),
avatar_model: self.avatar_model,
is_checked: true,
is_remove: false,
};
sidebar_items[0] = filter_item ;
filter_item = {
value: -1,
label: _lt("Everybody's calendars"),
color: self.get_color(-1),
avatar_model: self.avatar_model,
is_checked: false
};
sidebar_items[-1] = filter_item ;
//Get my coworkers/contacts
new instance.web.Model("calendar.contacts").query(["partner_id"]).filter([["user_id", "=",self.dataset.context.uid]]).all().then(function(result) {
_.each(result, function(item) {
filter_value = item.partner_id[0];
filter_item = {
value: filter_value,
label: item.partner_id[1],
color: self.get_color(filter_value),
avatar_model: self.avatar_model,
is_checked: true
};
sidebar_items[filter_value] = filter_item ;
});
self.all_filters = sidebar_items;
self.now_filter_ids = $.map(self.all_filters, function(o) { return o.value; });
self.sidebar.filter.events_loaded(self.all_filters);
self.sidebar.filter.set_filters();
self.sidebar.filter.set_distroy_filters();
self.sidebar.filter.addInputBox();
self.sidebar.filter.destroy_filter();
}).done(function () {
self.$calendar.fullCalendar('refetchEvents');
if (current.ir_model_m2o) {
current.ir_model_m2o.set_value(false);
}
});
});
}
instance.web_calendar.CalendarView.include({
extraSideBar: function(){
this._super();
if (this.useContacts){
new reload_favorite_list(this);
}
}
});
instance.web_calendar.SidebarFilter.include({
set_distroy_filters: function() {
var self = this;
// When mouse-enter the favorite list it will show the 'X' for removing partner from the favorite list.
if (self.view.useContacts){
self.$('.oe_calendar_all_responsibles').on('mouseenter mouseleave', function(e) {
self.$('.oe_remove_follower').toggleClass('hidden', e.type == 'mouseleave');
});
}
},
addInputBox: function() {
var self = this;
if (this.dfm)
return;
this.dfm = new instance.web.form.DefaultFieldManager(self);
this.dfm.extend_field_desc({
partner_id: {
relation: "res.partner",
},
});
this.ir_model_m2o = new instance.web.form.FieldMany2One(self.dfm, {
attrs: {
class: 'oe_add_input_box',
name: "partner_id",
type: "many2one",
options: '{"no_open": True}',
placeholder: _t("Select Favorite Calendar"),
},
});
this.ir_model_m2o.insertAfter($('div.oe_calendar_filter'));
this.ir_model_m2o.on('change:value', self, function() {
self.add_filter();
});
},
add_filter: function() {
var self = this;
new instance.web.Model("res.users").query(["partner_id"]).filter([["id", "=",this.view.dataset.context.uid]]).first().done(function(result){
$.map(self.ir_model_m2o.display_value, function(element,index) {
if (result.partner_id[0] != index){
self.ds_message = new instance.web.DataSetSearch(self, 'calendar.contacts');
self.ds_message.call("create", [{'partner_id': index}]);
}
});
});
new reload_favorite_list(this);
},
destroy_filter: function(e) {
var self= this;
this.$(".oe_remove_follower").on('click', function(e) {
self.ds_message = new instance.web.DataSetSearch(self, 'calendar.contacts');
if (! confirm(_t("Do you really want to delete this filter from favorite?"))) { return false; }
var id = $(e.currentTarget)[0].dataset.id;
self.ds_message.call('search', [[['partner_id', '=', parseInt(id)]]]).then(function(record){
return self.ds_message.unlink(record);
}).done(function() {
new reload_favorite_list(self);
});
});
},
});
instance.web.WebClient = instance.web.WebClient.extend({

View File

@ -73,4 +73,13 @@
</div>
</div>
</t>
<t t-extend="CalendarView.sidebar.responsible">
<t t-jquery="span#color_filter" t-operation="after">
<t t-if="(filters_value.value != -1) &amp;&amp; (filters_value.is_remove != false)">
<span class="oe_remove_follower oe_e hidden" title="Remove this favorite from the list" t-att-data-id="filters_value.value">X</span>
</t>
</t>
</t>
</template>

View File

@ -40,7 +40,7 @@ class crm_case_channel(osv.osv):
_description = "Channels"
_order = 'name'
_columns = {
'name': fields.char('Channel Name', size=64, required=True),
'name': fields.char('Channel Name', required=True),
'active': fields.boolean('Active'),
}
_defaults = {
@ -59,7 +59,7 @@ class crm_case_stage(osv.osv):
_order = "sequence"
_columns = {
'name': fields.char('Stage Name', size=64, required=True, translate=True),
'name': fields.char('Stage Name', required=True, translate=True),
'sequence': fields.integer('Sequence', help="Used to order stages. Lower is better."),
'probability': fields.float('Probability (%)', required=True, help="This percentage depicts the default/average probability of the Case for this stage to be a success"),
'on_change': fields.boolean('Change Probability Automatically', help="Setting this stage will change the probability automatically on the opportunity."),
@ -74,7 +74,7 @@ class crm_case_stage(osv.osv):
'type': fields.selection([('lead', 'Lead'),
('opportunity', 'Opportunity'),
('both', 'Both')],
string='Type', size=16, required=True,
string='Type', required=True,
help="This field is used to distinguish stages related to Leads from stages related to Opportunities, or to specify stages available for both types."),
}
@ -87,13 +87,12 @@ class crm_case_stage(osv.osv):
'case_default': True,
}
class crm_case_categ(osv.osv):
""" Category of Case """
_name = "crm.case.categ"
_description = "Category of Case"
_columns = {
'name': fields.char('Name', size=64, required=True, translate=True),
'name': fields.char('Name', required=True, translate=True),
'section_id': fields.many2one('crm.case.section', 'Sales Team'),
'object_id': fields.many2one('ir.model', 'Object Name'),
}
@ -113,7 +112,7 @@ class crm_case_resource_type(osv.osv):
_description = "Campaign"
_rec_name = "name"
_columns = {
'name': fields.char('Campaign Name', size=64, required=True, translate=True),
'name': fields.char('Campaign Name', required=True, translate=True),
'section_id': fields.many2one('crm.case.section', 'Sales Team'),
}
@ -122,7 +121,7 @@ class crm_payment_mode(osv.osv):
_name = "crm.payment.mode"
_description = "CRM Payment Mode"
_columns = {
'name': fields.char('Name', size=64, required=True),
'name': fields.char('Name', required=True),
'section_id': fields.many2one('crm.case.section', 'Sales Team'),
}

View File

@ -201,7 +201,7 @@ class crm_lead(format_address, osv.osv):
select=True, help="Linked partner (optional). Usually created when converting the lead."),
'id': fields.integer('ID', readonly=True),
'name': fields.char('Subject', size=64, required=True, select=1),
'name': fields.char('Subject', required=True, select=1),
'active': fields.boolean('Active', required=False),
'date_action_last': fields.datetime('Last Action', readonly=1),
'date_action_next': fields.datetime('Next Action', readonly=1),
@ -228,7 +228,7 @@ class crm_lead(format_address, osv.osv):
'stage_id': fields.many2one('crm.case.stage', 'Stage', track_visibility='onchange', select=True,
domain="['&', ('section_ids', '=', section_id), '|', ('type', '=', type), ('type', '=', 'both')]"),
'user_id': fields.many2one('res.users', 'Salesperson', select=True, track_visibility='onchange'),
'referred': fields.char('Referred By', size=64),
'referred': fields.char('Referred By'),
'date_open': fields.datetime('Assigned', readonly=True),
'day_open': fields.function(_compute_day, string='Days to Open', \
multi='day_open', type="float", store=True),
@ -246,7 +246,7 @@ class crm_lead(format_address, osv.osv):
'phone': fields.char("Phone", size=64),
'date_deadline': fields.date('Expected Closing', help="Estimate of the date on which the opportunity will be won."),
'date_action': fields.date('Next Action Date', select=True),
'title_action': fields.char('Next Action', size=64),
'title_action': fields.char('Next Action'),
'color': fields.integer('Color Index'),
'partner_address_name': fields.related('partner_id', 'name', type='char', string='Partner Contact Name', readonly=True),
'partner_address_email': fields.related('partner_id', 'email', type='char', string='Partner Contact Email', readonly=True),
@ -255,16 +255,16 @@ class crm_lead(format_address, osv.osv):
'user_login': fields.related('user_id', 'login', type='char', string='User Login', readonly=True),
# Fields for address, due to separation from crm and res.partner
'street': fields.char('Street', size=128),
'street2': fields.char('Street2', size=128),
'street': fields.char('Street'),
'street2': fields.char('Street2'),
'zip': fields.char('Zip', change_default=True, size=24),
'city': fields.char('City', size=128),
'city': fields.char('City'),
'state_id': fields.many2one("res.country.state", 'State'),
'country_id': fields.many2one('res.country', 'Country'),
'phone': fields.char('Phone', size=64),
'fax': fields.char('Fax', size=64),
'mobile': fields.char('Mobile', size=64),
'function': fields.char('Function', size=128),
'phone': fields.char('Phone'),
'fax': fields.char('Fax'),
'mobile': fields.char('Mobile'),
'function': fields.char('Function'),
'title': fields.many2one('res.partner.title', 'Title'),
'company_id': fields.many2one('res.company', 'Company', select=1),
'payment_mode': fields.many2one('crm.payment.mode', 'Payment Mode', \
@ -935,8 +935,10 @@ class crm_lead(format_address, osv.osv):
def message_get_reply_to(self, cr, uid, ids, context=None):
""" Override to get the reply_to of the parent project. """
return [lead.section_id.message_get_reply_to()[0] if lead.section_id else False
for lead in self.browse(cr, SUPERUSER_ID, ids, context=context)]
leads = self.browse(cr, SUPERUSER_ID, ids, context=context)
section_ids = set([lead.section_id.id for lead in leads if lead.section_id])
aliases = self.pool['crm.case.section'].message_get_reply_to(cr, uid, list(section_ids), context=context)
return dict((lead.id, aliases.get(lead.section_id and lead.section_id.id or 0, False)) for lead in leads)
def get_formview_id(self, cr, uid, id, context=None):
obj = self.browse(cr, uid, id, context=context)

View File

@ -54,14 +54,14 @@ class crm_phonecall(osv.osv):
'email_from': fields.char('Email', size=128, help="These people will receive email."),
'date_open': fields.datetime('Opened', readonly=True),
# phonecall fields
'name': fields.char('Call Summary', size=64, required=True),
'name': fields.char('Call Summary', required=True),
'active': fields.boolean('Active', required=False),
'duration': fields.float('Duration', help='Duration in minutes and seconds.'),
'categ_id': fields.many2one('crm.case.categ', 'Category', \
domain="['|',('section_id','=',section_id),('section_id','=',False),\
('object_id.model', '=', 'crm.phonecall')]"),
'partner_phone': fields.char('Phone', size=32),
'partner_mobile': fields.char('Mobile', size=32),
'partner_phone': fields.char('Phone'),
'partner_mobile': fields.char('Mobile'),
'priority': fields.selection([('0','Low'), ('1','Normal'), ('2','High')], 'Priority'),
'date_closed': fields.datetime('Closed', readonly=True),
'date': fields.datetime('Date'),

View File

@ -30,7 +30,7 @@ class crm_segmentation(osv.osv):
_description = "Partner Segmentation"
_columns = {
'name': fields.char('Name', size=64, required=True, help='The name of the segmentation.'),
'name': fields.char('Name', required=True, help='The name of the segmentation.'),
'description': fields.text('Description'),
'categ_id': fields.many2one('res.partner.category', 'Partner Category',\
required=True, help='The partner category that will be \
@ -115,10 +115,10 @@ class crm_segmentation_line(osv.osv):
_description = "Segmentation line"
_columns = {
'name': fields.char('Rule Name', size=64, required=True),
'name': fields.char('Rule Name', required=True),
'segmentation_id': fields.many2one('crm.segmentation', 'Segmentation'),
'expr_name': fields.selection([('sale','Sale Amount'),
('purchase','Purchase Amount')], 'Control Variable', size=64, required=True),
('purchase','Purchase Amount')], 'Control Variable', required=True),
'expr_operator': fields.selection([('<','<'),('=','='),('>','>')], 'Operator', required=True),
'expr_value': fields.float('Value', required=True),
'operator': fields.selection([('and','Mandatory Expression'),\

View File

@ -46,7 +46,7 @@ class crm_lead_report(osv.osv):
_rec_name = 'date_deadline'
_columns = {
'date_deadline': fields.date('Exp. Closing', size=10, readonly=True, help="Expected Closing"),
'date_deadline': fields.date('Exp. Closing', readonly=True, help="Expected Closing"),
'create_date': fields.datetime('Creation Date', readonly=True),
'opening_date': fields.date('Assignation Date', readonly=True),
'date_closed': fields.date('Close Date', readonly=True),

View File

@ -44,7 +44,7 @@ class crm_phonecall_report(osv.osv):
'section_id':fields.many2one('crm.case.section', 'Section', readonly=True),
'priority': fields.selection([('0','Low'), ('1','Normal'), ('2','High')], 'Priority'),
'nbr': fields.integer('# of Cases', readonly=True),
'state': fields.selection(AVAILABLE_STATES, 'Status', size=16, readonly=True),
'state': fields.selection(AVAILABLE_STATES, 'Status', readonly=True),
'create_date': fields.datetime('Create Date', readonly=True, select=True),
'delay_close': fields.float('Delay to close', digits=(16,2),readonly=True, group_operator="avg",help="Number of Days to close the case"),
'duration': fields.float('Duration', digits=(16,2),readonly=True, group_operator="avg"),

View File

@ -33,7 +33,7 @@
</div>
</group>
</div>
<xpath expr="//group[@name='On Mail Client']" position="before">
<xpath expr="//p[@name='config_email_integration']" position="after">
<group name="default_alias">
<label for="id" string="Leads Email Alias"/>
<div attrs="{'invisible': [('alias_domain', '=', False)]}">

View File

@ -29,10 +29,10 @@ class crm_phonecall2phonecall(osv.osv_memory):
_description = 'Phonecall To Phonecall'
_columns = {
'name' : fields.char('Call summary', size=64, required=True, select=1),
'name' : fields.char('Call summary', required=True, select=1),
'user_id' : fields.many2one('res.users',"Assign To"),
'contact_name':fields.char('Contact', size=64),
'phone':fields.char('Phone', size=64),
'contact_name':fields.char('Contact'),
'phone':fields.char('Phone'),
'categ_id': fields.many2one('crm.case.categ', 'Category', \
domain="['|',('section_id','=',False),('section_id','=',section_id),\
('object_id.model', '=', 'crm.phonecall')]"),

View File

@ -39,7 +39,7 @@ class crm_claim_stage(osv.osv):
_order = "sequence"
_columns = {
'name': fields.char('Stage Name', size=64, required=True, translate=True),
'name': fields.char('Stage Name', required=True, translate=True),
'sequence': fields.integer('Sequence', help="Used to order stages. Lower is better."),
'section_ids':fields.many2many('crm.case.section', 'section_claim_stage_rel', 'stage_id', 'section_id', string='Sections',
help="Link between stages and sales teams. When set, this limitate the current stage to the selected sales teams."),
@ -70,9 +70,9 @@ class crm_claim(osv.osv):
_columns = {
'id': fields.integer('ID', readonly=True),
'name': fields.char('Claim Subject', size=128, required=True),
'name': fields.char('Claim Subject', required=True),
'active': fields.boolean('Active'),
'action_next': fields.char('Next Action', size=200),
'action_next': fields.char('Next Action'),
'date_action_next': fields.datetime('Next Action Date'),
'description': fields.text('Description'),
'resolution': fields.text('Resolution'),
@ -87,8 +87,8 @@ class crm_claim(osv.osv):
('object_id.model', '=', 'crm.claim')]"),
'priority': fields.selection([('0','Low'), ('1','Normal'), ('2','High')], 'Priority'),
'type_action': fields.selection([('correction','Corrective Action'),('prevention','Preventive Action')], 'Action Type'),
'user_id': fields.many2one('res.users', 'Responsible'),
'user_fault': fields.char('Trouble Responsible', size=64),
'user_id': fields.many2one('res.users', 'Responsible', track_visibility='always'),
'user_fault': fields.char('Trouble Responsible'),
'section_id': fields.many2one('crm.case.section', 'Sales Team', \
select=True, help="Responsible sales team."\
" Define Responsible user and Email account for"\
@ -97,7 +97,7 @@ class crm_claim(osv.osv):
'partner_id': fields.many2one('res.partner', 'Partner'),
'email_cc': fields.text('Watchers Emails', size=252, help="These email addresses will be added to the CC field of all inbound and outbound emails for this record before being sent. Separate multiple email addresses with a comma"),
'email_from': fields.char('Email', size=128, help="Destination email for email gateway."),
'partner_phone': fields.char('Phone', size=32),
'partner_phone': fields.char('Phone'),
'stage_id': fields.many2one ('crm.claim.stage', 'Stage', track_visibility='onchange',
domain="['|', ('section_ids', '=', section_id), ('case_default', '=', True)]"),
'cause': fields.text('Root Cause'),
@ -161,6 +161,13 @@ class crm_claim(osv.osv):
# context: no_log, because subtype already handle this
return super(crm_claim, self).create(cr, uid, vals, context=context)
def copy(self, cr, uid, id, default=None, context=None):
claim = self.browse(cr, uid, id, context=context)
default = dict(default or {},
stage_id = self._get_default_stage_id(cr, uid, context=context),
name = _('%s (copy)') % claim.name)
return super(crm_claim, self).copy(cr, uid, id, default, context=context)
# -------------------------------------------------------
# Mail gateway
# -------------------------------------------------------

View File

@ -37,7 +37,7 @@ class crm_claim_report(osv.osv):
_description = "CRM Claim Report"
_columns = {
'name': fields.char('Year', size=64, required=False, readonly=True),
'name': fields.char('Year', required=False, readonly=True),
'user_id':fields.many2one('res.users', 'User', readonly=True),
'section_id':fields.many2one('crm.case.section', 'Section', readonly=True),
'nbr': fields.integer('# of Cases', readonly=True),

View File

@ -37,7 +37,7 @@ class crm_helpdesk(osv.osv):
_columns = {
'id': fields.integer('ID', readonly=True),
'name': fields.char('Name', size=128, required=True),
'name': fields.char('Name', required=True),
'active': fields.boolean('Active', required=False),
'date_action_last': fields.datetime('Last Action', readonly=1),
'date_action_next': fields.datetime('Next Action', readonly=1),
@ -70,7 +70,7 @@ class crm_helpdesk(osv.osv):
('open', 'In Progress'),
('pending', 'Pending'),
('done', 'Closed'),
('cancel', 'Cancelled')], 'Status', size=16, readonly=True, track_visibility='onchange',
('cancel', 'Cancelled')], 'Status', readonly=True, track_visibility='onchange',
help='The status is set to \'Draft\', when a case is created.\
\nIf the case is in progress the status is set to \'Open\'.\
\nWhen the case is over, the status is set to \'Done\'.\

View File

@ -39,11 +39,11 @@ class crm_helpdesk_report(osv.osv):
_auto = False
_columns = {
'name': fields.char('Year', size=64, required=False, readonly=True),
'name': fields.char('Year', required=False, readonly=True),
'user_id':fields.many2one('res.users', 'User', readonly=True),
'section_id':fields.many2one('crm.case.section', 'Section', readonly=True),
'nbr': fields.integer('# of Cases', readonly=True),
'state': fields.selection(AVAILABLE_STATES, 'Status', size=16, readonly=True),
'state': fields.selection(AVAILABLE_STATES, 'Status', readonly=True),
'month':fields.selection([('01', 'January'), ('02', 'February'), \
('03', 'March'), ('04', 'April'),\
('05', 'May'), ('06', 'June'), \

View File

@ -32,7 +32,7 @@ class res_partner_grade(osv.osv):
_columns = {
'sequence': fields.integer('Sequence'),
'active': fields.boolean('Active'),
'name': fields.char('Grade Name', size=32),
'name': fields.char('Grade Name'),
'partner_weight': fields.integer('Grade Weight',
help="Gives the probability to assign a lead to this partner. (0 means no assignation.)"),
}
@ -47,7 +47,7 @@ class res_partner_activation(osv.osv):
_columns = {
'sequence' : fields.integer('Sequence'),
'name' : fields.char('Name', size=32, required=True),
'name' : fields.char('Name', required=True),
}

View File

@ -48,7 +48,7 @@
<p>Thanks,</p>
<pre>
${ctx['partner_id'].user_id and ctx['partner_id'].user_id.signature or ''}
${ctx['partner_id'].user_id and ctx['partner_id'].user_id.signature | safe or ''}
</pre>
% if not ctx['partner_id'].user_id:
PS: It looks like you do not have an account manager assigned to you, please contact us.

View File

@ -55,7 +55,7 @@ class crm_lead_report_assign(osv.osv):
'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'),
'type':fields.selection([
('lead','Lead'),
('opportunity','Opportunity'),
('opportunity','Opportunity')
],'Type', help="Type is used to separate Leads and Opportunities"),
}
def init(self, cr):

View File

@ -146,7 +146,7 @@ class question(osv.osv):
_description= "Question"
_columns={
'name': fields.char("Question",size=128, required=True),
'name': fields.char("Question", required=True),
'answers_ids': fields.one2many("crm_profiling.answer","question_id","Avalaible Answers",),
}
@ -159,7 +159,7 @@ class questionnaire(osv.osv):
_description= "Questionnaire"
_columns = {
'name': fields.char("Questionnaire",size=128, required=True),
'name': fields.char("Questionnaire", required=True),
'description':fields.text("Description", required=True),
'questions_ids': fields.many2many('crm_profiling.question','profile_questionnaire_quest_rel',\
'questionnaire', 'question', "Questions"),
@ -171,7 +171,7 @@ class answer(osv.osv):
_name="crm_profiling.answer"
_description="Answer"
_columns={
"name": fields.char("Answer",size=128, required=True),
"name": fields.char("Answer", required=True),
"question_id": fields.many2one('crm_profiling.question',"Question"),
}

View File

@ -28,7 +28,7 @@ from openerp.modules.registry import RegistryManager
class decimal_precision(orm.Model):
_name = 'decimal.precision'
_columns = {
'name': fields.char('Usage', size=50, select=True, required=True),
'name': fields.char('Usage', select=True, required=True),
'digits': fields.integer('Digits', required=True),
}
_defaults = {

View File

@ -62,7 +62,7 @@ class delivery_carrier(osv.osv):
return res
_columns = {
'name': fields.char('Delivery Method', size=64, required=True),
'name': fields.char('Delivery Method', required=True),
'partner_id': fields.many2one('res.partner', 'Transport Company', required=True, help="The partner that is doing the delivery service."),
'product_id': fields.many2one('product.product', 'Delivery Product', required=True),
'grids_id': fields.one2many('delivery.grid', 'carrier_id', 'Delivery Grids'),
@ -171,8 +171,8 @@ class delivery_grid(osv.osv):
_name = "delivery.grid"
_description = "Delivery Grid"
_columns = {
'name': fields.char('Grid Name', size=64, required=True),
'sequence': fields.integer('Sequence', size=64, required=True, help="Gives the sequence order when displaying a list of delivery grid."),
'name': fields.char('Grid Name', required=True),
'sequence': fields.integer('Sequence', required=True, help="Gives the sequence order when displaying a list of delivery grid."),
'carrier_id': fields.many2one('delivery.carrier', 'Carrier', required=True, ondelete='cascade'),
'country_ids': fields.many2many('res.country', 'delivery_grid_country_rel', 'grid_id', 'country_id', 'Countries'),
'state_ids': fields.many2many('res.country.state', 'delivery_grid_state_rel', 'grid_id', 'state_id', 'States'),
@ -229,8 +229,8 @@ class delivery_grid_line(osv.osv):
_name = "delivery.grid.line"
_description = "Delivery Grid Line"
_columns = {
'name': fields.char('Name', size=64, required=True),
'sequence': fields.integer('Sequence', size=64, required=True, help="Gives the sequence order when calculating delivery grid."),
'name': fields.char('Name', required=True),
'sequence': fields.integer('Sequence', required=True, help="Gives the sequence order when calculating delivery grid."),
'grid_id': fields.many2one('delivery.grid', 'Grid',required=True, ondelete='cascade'),
'type': fields.selection([('weight','Weight'),('volume','Volume'),\
('wv','Weight * Volume'), ('price','Price'), ('quantity','Quantity')],\

View File

@ -64,7 +64,7 @@ class stock_picking(osv.osv):
'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['move_lines'], 20),
'stock.move': (_get_picking_line, ['product_id','product_qty','product_uom','product_uos_qty'], 20),
}),
'carrier_tracking_ref': fields.char('Carrier Tracking Ref', size=32),
'carrier_tracking_ref': fields.char('Carrier Tracking Ref'),
'number_of_packages': fields.integer('Number of Packages'),
'weight_uom_id': fields.many2one('product.uom', 'Unit of Measure', required=True,readonly="1",help="Unit of measurement for Weight",),
}

View File

@ -158,7 +158,7 @@ class document_directory(osv.osv):
_description = 'Directory'
_order = 'name'
_columns = {
'name': fields.char('Name', size=64, required=True, select=1),
'name': fields.char('Name', required=True, select=1),
'write_date': fields.datetime('Date Modified', readonly=True),
'write_uid': fields.many2one('res.users', 'Last Modification User', readonly=True),
'create_date': fields.datetime('Date Created', readonly=True),
@ -172,7 +172,7 @@ class document_directory(osv.osv):
'type': fields.selection([ ('directory','Static Directory'), ('ressource','Folders per resource'), ],
'Type', required=True, select=1, change_default=True,
help="Each directory can either have the type Static or be linked to another resource. A static directory, as with Operating Systems, is the classic directory that can contain a set of files. The directories linked to systems resources automatically possess sub-directories for each of resource types defined in the parent directory."),
'domain': fields.char('Domain', size=128, help="Use a domain if you want to apply an automatic filter on visible resources."),
'domain': fields.char('Domain', help="Use a domain if you want to apply an automatic filter on visible resources."),
'ressource_type_id': fields.many2one('ir.model', 'Resource model', change_default=True,
help="Select an object here and there will be one folder per record of that resource."),
'resource_field': fields.many2one('ir.model.fields', 'Name field', help='Field to be used as name on resource directories. If empty, the "name" will be used.'),
@ -370,8 +370,8 @@ class document_directory_dctx(osv.osv):
_description = 'Directory Dynamic Context'
_columns = {
'dir_id': fields.many2one('document.directory', 'Directory', required=True, ondelete="cascade"),
'field': fields.char('Field', size=20, required=True, select=1, help="The name of the field."),
'expr': fields.char('Expression', size=64, required=True, help="A python expression used to evaluate the field.\n" + \
'field': fields.char('Field', required=True, select=1, help="The name of the field."),
'expr': fields.char('Expression', required=True, help="A python expression used to evaluate the field.\n" + \
"You can use 'dir_id' for current dir, 'res_id', 'res_model' as a reference to the current record, in dynamic folders"),
}
@ -379,10 +379,10 @@ class document_directory_content_type(osv.osv):
_name = 'document.directory.content.type'
_description = 'Directory Content Type'
_columns = {
'name': fields.char('Content Type', size=64, required=True),
'name': fields.char('Content Type', required=True),
'code': fields.char('Extension', size=4),
'active': fields.boolean('Active'),
'mimetype': fields.char('Mime Type',size=32)
'mimetype': fields.char('Mime Type')
}
_defaults = {
'active': lambda *args: 1
@ -399,7 +399,7 @@ class document_directory_content(osv.osv):
return res
_columns = {
'name': fields.char('Content Name', size=64, required=True),
'name': fields.char('Content Name', required=True),
'sequence': fields.integer('Sequence', size=16),
'prefix': fields.char('Prefix', size=16),
'suffix': fields.char('Suffix', size=16),

View File

@ -253,14 +253,6 @@
</p>
</field>
</record>
<menuitem name="Documents" id="menu_document_doc" parent="knowledge.menu_document" sequence="0"/>
<menuitem
name="Documents"
action="action_document_file_form"
id="menu_document_files"
parent="menu_document_doc"
sequence="0"
/>
<record model="ir.actions.act_window" id="action_document_file_directory_form">
<field name="type">ir.actions.act_window</field>

View File

@ -71,7 +71,7 @@ class report_document_file(osv.osv):
_columns = {
'file_size': fields.integer('File Size', readonly=True),
'nbr':fields.integer('# of Files', readonly=True),
'month': fields.char('Month', size=24,readonly=True),
'month': fields.char('Month', size=24, readonly=True),
}
_order = "month"
def init(self, cr):

View File

@ -216,7 +216,7 @@ class email_template(osv.osv):
'name': fields.char('Name'),
'model_id': fields.many2one('ir.model', 'Applies to', help="The kind of document with with this template can be used"),
'model': fields.related('model_id', 'model', type='char', string='Related Document Model',
size=128, select=True, store=True, readonly=True),
select=True, store=True, readonly=True),
'lang': fields.char('Language',
help="Optional translation language (ISO code) to select when sending out an email. "
"If not set, the english version will be used. "

View File

@ -237,8 +237,8 @@ class test_message_compose(TestMail):
email_template.send_mail(cr, uid, email_template_id, self.group_pigs_id, force_send=True, context=context)
sent_emails = self._build_email_kwargs_list
email_to_lst = [
['b@b.b', 'c@c.c'], ['Administrator <admin@yourcompany.example.com>'],
['Raoul Grosbedon <raoul@raoul.fr>'], ['Bert Tartignole <bert@bert.fr>']]
['b@b.b', 'c@c.c'], ['"Administrator" <admin@yourcompany.example.com>'],
['"Raoul Grosbedon" <raoul@raoul.fr>'], ['"Bert Tartignole" <bert@bert.fr>']]
self.assertEqual(len(sent_emails), 4, 'email_template: send_mail: 3 valid email recipients + email_to -> should send 4 emails')
for email in sent_emails:
self.assertIn(email['email_to'], email_to_lst, 'email_template: send_mail: wrong email_recipients')

View File

@ -30,8 +30,8 @@ class event_type(osv.osv):
_name = 'event.type'
_description = __doc__
_columns = {
'name': fields.char('Event Type', size=64, required=True),
'default_reply_to': fields.char('Default Reply-To', size=64,help="The email address of the organizer which is put in the 'Reply-To' of all emails sent automatically at event or registrations confirmation. You can also put your email address of your mail gateway if you use one." ),
'name': fields.char('Event Type', required=True),
'default_reply_to': fields.char('Default Reply-To', size=64, help="The email address of the organizer which is put in the 'Reply-To' of all emails sent automatically at event or registrations confirmation. You can also put your email address of your mail gateway if you use one." ),
'default_email_event': fields.many2one('email.template','Event Confirmation Email', help="It will select this default confirmation event mail value when you choose this event"),
'default_email_registration': fields.many2one('email.template','Registration Confirmation Email', help="It will select this default confirmation registration mail value when you choose this event"),
'default_registration_min': fields.integer('Default Minimum Registration', help="It will select this default minimum value when you choose this event"),
@ -174,7 +174,7 @@ class event_event(osv.osv):
return [(x, x) for x in pytz.all_timezones]
_columns = {
'name': fields.char('Event Name', size=64, required=True, translate=True, readonly=False, states={'done': [('readonly', True)]}),
'name': fields.char('Event Name', required=True, translate=True, readonly=False, states={'done': [('readonly', True)]}),
'user_id': fields.many2one('res.users', 'Responsible User', readonly=False, states={'done': [('readonly', True)]}),
'type': fields.many2one('event.type', 'Type of Event', readonly=False, states={'done': [('readonly', True)]}),
'seats_max': fields.integer('Maximum Avalaible Seats', oldname='register_max', help="You can for each event define a maximum registration level. If you have too much registrations you are not able to confirm your event. (put 0 to ignore this rule )", readonly=True, states={'draft': [('readonly', False)]}),
@ -299,14 +299,14 @@ class event_registration(osv.osv):
_inherit = ['mail.thread', 'ir.needaction_mixin']
_columns = {
'id': fields.integer('ID'),
'origin': fields.char('Source Document', size=124,readonly=True,help="Reference of the sales order which created the registration"),
'origin': fields.char('Source Document', readonly=True,help="Reference of the sales order which created the registration"),
'nb_register': fields.integer('Number of Participants', required=True, readonly=True, states={'draft': [('readonly', False)]}),
'event_id': fields.many2one('event.event', 'Event', required=True, readonly=True, states={'draft': [('readonly', False)]}),
'partner_id': fields.many2one('res.partner', 'Partner', states={'done': [('readonly', True)]}),
'create_date': fields.datetime('Creation Date' , readonly=True),
'date_closed': fields.datetime('Attended Date', readonly=True),
'date_open': fields.datetime('Registration Date', readonly=True),
'reply_to': fields.related('event_id','reply_to',string='Reply-to Email', type='char', size=128, readonly=True,),
'reply_to': fields.related('event_id','reply_to',string='Reply-to Email', type='char', readonly=True,),
'log_ids': fields.one2many('mail.message', 'res_id', 'Logs', domain=[('model','=',_name)]),
'event_end_date': fields.related('event_id','date_end', type='datetime', string="Event End Date", readonly=True),
'event_begin_date': fields.related('event_id', 'date_begin', type='datetime', string="Event Start Date", readonly=True),
@ -316,10 +316,10 @@ class event_registration(osv.osv):
('cancel', 'Cancelled'),
('open', 'Confirmed'),
('done', 'Attended')], 'Status',
size=16, readonly=True),
readonly=True),
'email': fields.char('Email', size=64),
'phone': fields.char('Phone', size=64),
'name': fields.char('Name', size=128, select=True),
'name': fields.char('Name', select=True),
}
_defaults = {
'nb_register': 1,

View File

@ -208,7 +208,7 @@ class event_ticket(osv.osv):
_columns = {
'name': fields.char('Name', size=64, required=True, translate=True),
'name': fields.char('Name', required=True, translate=True),
'event_id': fields.many2one('event.event', "Event", required=True, ondelete='cascade'),
'product_id': fields.many2one('product.product', 'Product', required=True, domain=[("event_type_id", "!=", False)]),
'registration_ids': fields.one2many('event.registration', 'event_ticket_id', 'Registrations'),

View File

@ -47,13 +47,13 @@ class fetchmail_server(osv.osv):
_order = 'priority'
_columns = {
'name':fields.char('Name', size=256, required=True, readonly=False),
'name':fields.char('Name', required=True, readonly=False),
'active':fields.boolean('Active', required=False),
'state':fields.selection([
('draft', 'Not Confirmed'),
('done', 'Confirmed'),
], 'Status', select=True, readonly=True),
'server' : fields.char('Server Name', size=256, readonly=True, help="Hostname or IP of the mail server", states={'draft':[('readonly', False)]}),
'server' : fields.char('Server Name', readonly=True, help="Hostname or IP of the mail server", states={'draft':[('readonly', False)]}),
'port' : fields.integer('Port', readonly=True, states={'draft':[('readonly', False)]}),
'type':fields.selection([
('pop', 'POP Server'),
@ -66,8 +66,8 @@ class fetchmail_server(osv.osv):
'original':fields.boolean('Keep Original', help="Whether a full original copy of each email should be kept for reference"
"and attached to each processed message. This will usually double the size of your message database."),
'date': fields.datetime('Last Fetch Date', readonly=True),
'user' : fields.char('Username', size=256, readonly=True, states={'draft':[('readonly', False)]}),
'password' : fields.char('Password', size=1024, readonly=True, states={'draft':[('readonly', False)]}),
'user' : fields.char('Username', readonly=True, states={'draft':[('readonly', False)]}),
'password' : fields.char('Password', readonly=True, states={'draft':[('readonly', False)]}),
'action_id':fields.many2one('ir.actions.server', 'Server Action', help="Optional custom server action to trigger for each incoming mail, "
"on the record that was created or updated by this mail"),
'object_id': fields.many2one('ir.model', "Create a New Record", help="Process each incoming mail as part of a conversation "
@ -78,7 +78,7 @@ class fetchmail_server(osv.osv):
"lower values mean higher priority"),
'message_ids': fields.one2many('mail.mail', 'fetchmail_server_id', 'Messages', readonly=True),
'configuration' : fields.text('Configuration', readonly=True),
'script' : fields.char('Script', readonly=True, size=64),
'script' : fields.char('Script', readonly=True),
}
_defaults = {
'state': "draft",

View File

@ -145,7 +145,7 @@ class fleet_vehicle_model(osv.Model):
_columns = {
'name': fields.function(_model_name_get_fnc, type="char", string='Name', store=True),
'modelname': fields.char('Model name', size=32, required=True),
'modelname': fields.char('Model name', required=True),
'brand_id': fields.many2one('fleet.vehicle.model.brand', 'Model Brand', required=True, help='Brand of the vehicle'),
'vendors': fields.many2many('res.partner', 'fleet_vehicle_model_vendors', 'model_id', 'partner_id', string='Vendors'),
'image': fields.related('brand_id', 'image', type="binary", string="Logo"),
@ -170,7 +170,7 @@ class fleet_vehicle_model_brand(osv.Model):
return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
_columns = {
'name': fields.char('Brand Name', size=64, required=True),
'name': fields.char('Brand Name', required=True),
'image': fields.binary("Logo",
help="This field holds the image used as logo for the brand, limited to 1024x1024px."),
'image_medium': fields.function(_get_image, fnct_inv=_set_image,
@ -337,8 +337,8 @@ class fleet_vehicle(osv.Model):
_columns = {
'name': fields.function(_vehicle_name_get_fnc, type="char", string='Name', store=True),
'company_id': fields.many2one('res.company', 'Company'),
'license_plate': fields.char('License Plate', size=32, required=True, help='License plate number of the vehicle (ie: plate number for a car)'),
'vin_sn': fields.char('Chassis Number', size=32, help='Unique number written on the vehicle motor (VIN/SN number)'),
'license_plate': fields.char('License Plate', required=True, help='License plate number of the vehicle (ie: plate number for a car)'),
'vin_sn': fields.char('Chassis Number', help='Unique number written on the vehicle motor (VIN/SN number)'),
'driver_id': fields.many2one('res.partner', 'Driver', help='Driver of the vehicle'),
'model_id': fields.many2one('fleet.vehicle.model', 'Model', required=True, help='Model of the vehicle'),
'log_fuel': fields.one2many('fleet.vehicle.log.fuel', 'vehicle_id', 'Fuel Logs'),
@ -350,9 +350,9 @@ class fleet_vehicle(osv.Model):
'fuel_logs_count': fields.function(_count_all, type='integer', string='Fuel Logs', multi=True),
'odometer_count': fields.function(_count_all, type='integer', string='Odometer', multi=True),
'acquisition_date': fields.date('Acquisition Date', required=False, help='Date when the vehicle has been bought'),
'color': fields.char('Color', size=32, help='Color of the vehicle'),
'color': fields.char('Color', help='Color of the vehicle'),
'state_id': fields.many2one('fleet.vehicle.state', 'State', help='Current state of the vehicle', ondelete="set null"),
'location': fields.char('Location', size=128, help='Location of the vehicle (garage, ...)'),
'location': fields.char('Location', help='Location of the vehicle (garage, ...)'),
'seats': fields.integer('Seats Number', help='Number of seats of the vehicle'),
'doors': fields.integer('Doors Number', help='Number of doors of the vehicle'),
'tag_ids' :fields.many2many('fleet.vehicle.tag', 'fleet_vehicle_vehicle_tag_rel', 'vehicle_tag_id','tag_id', 'Tags'),
@ -607,7 +607,7 @@ class fleet_vehicle_log_services(osv.Model):
_description = 'Services for vehicles'
_columns = {
'purchaser_id': fields.many2one('res.partner', 'Purchaser', domain="['|',('customer','=',True),('employee','=',True)]"),
'inv_ref': fields.char('Invoice Reference', size=64),
'inv_ref': fields.char('Invoice Reference'),
'vendor_id': fields.many2one('res.partner', 'Supplier', domain="[('supplier','=',True)]"),
'cost_amount': fields.related('cost_id', 'amount', string='Amount', type='float', store=True), #we need to keep this field as a related with store=True because the graph view doesn't support (1) to address fields from inherited table and (2) fields that aren't stored in database
'notes': fields.text('Notes'),
@ -847,5 +847,5 @@ class fleet_contract_state(osv.Model):
_description = 'Contains the different possible status of a leasing contract'
_columns = {
'name':fields.char('Contract Status', size=64, required=True),
'name':fields.char('Contract Status', required=True),
}

View File

@ -280,4 +280,4 @@ class gamification_badge(osv.Model):
'badge_id': res_id,
}
badge_user_obj.create(cr, SUPERUSER_ID, values, context=context)
return True
return True

View File

@ -174,10 +174,10 @@ class google_service(osv.osv_memory):
return self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url', default='http://www.openerp.com?NoBaseUrl', context=context)
def get_client_id(self, cr, uid, service, context=None):
return self.pool.get('ir.config_parameter').get_param(cr, uid, 'google_%s_client_id' % (service,), default=False, context=context)
return self.pool.get('ir.config_parameter').get_param(cr, SUPERUSER_ID, 'google_%s_client_id' % (service,), default=False, context=context)
def get_client_secret(self, cr, uid, service, context=None):
return self.pool.get('ir.config_parameter').get_param(cr, uid, 'google_%s_client_secret' % (service,), default=False, context=context)
return self.pool.get('ir.config_parameter').get_param(cr, SUPERUSER_ID, 'google_%s_client_secret' % (service,), default=False, context=context)
def get_uri_oauth(self, a=''): # a = optional action
return "https://accounts.google.com/o/oauth2/%s" % (a,)

View File

@ -13,8 +13,8 @@ class calendar_config_settings(osv.TransientModel):
def set_calset(self,cr,uid,ids,context=None) :
params = self.pool['ir.config_parameter']
myself = self.browse(cr,uid,ids[0],context=context)
params.set_param(cr, uid, 'google_calendar_client_id', myself.cal_client_id or '', context=None)
params.set_param(cr, uid, 'google_calendar_client_secret', myself.cal_client_secret or '', context=None)
params.set_param(cr, uid, 'google_calendar_client_id', myself.cal_client_id or '', groups=['base.group_system'], context=None)
params.set_param(cr, uid, 'google_calendar_client_secret', myself.cal_client_secret or '', groups=['base.group_system'], context=None)
def get_default_all(self,cr,uid,ids,context=None):

View File

@ -192,14 +192,14 @@ class config(osv.Model):
return result
_columns = {
'name': fields.char('Template Name', required=True, size=1024),
'name': fields.char('Template Name', required=True),
'model_id': fields.many2one('ir.model', 'Model', ondelete='set null', required=True),
'model': fields.related('model_id', 'model', type='char', string='Model', readonly=True),
'filter_id': fields.many2one('ir.filters', 'Filter', domain="[('model_id', '=', model)]"),
'google_drive_template_url': fields.char('Template URL', required=True, size=1024),
'google_drive_resource_id': fields.function(_resource_get, type="char", string='Resource Id'),
'google_drive_client_id': fields.function(_client_id_get, type="char", string='Google Client '),
'name_template': fields.char('Google Drive Name Pattern', size=64, help='Choose how the new google drive will be named, on google side. Eg. gdoc_%(field_name)s', required=True),
'name_template': fields.char('Google Drive Name Pattern', help='Choose how the new google drive will be named, on google side. Eg. gdoc_%(field_name)s', required=True),
'active': fields.boolean('Active'),
}
@ -235,12 +235,12 @@ class base_config_settings(osv.TransientModel):
_inherit = "base.config.settings"
_columns = {
'google_drive_authorization_code': fields.char('Authorization Code', size=124),
'google_drive_authorization_code': fields.char('Authorization Code'),
'google_drive_uri': fields.char('URI', readonly=True, help="The URL to generate the authorization code from Google"),
}
_defaults = {
'google_drive_uri': lambda s, cr, uid, c: s.pool['google.service']._get_google_token_uri(cr, uid, 'drive', scope=s.pool['google.drive.config'].get_google_scope(), context=c),
'google_drive_authorization_code': lambda s, cr, uid, c: s.pool['ir.config_parameter'].get_param(cr, uid, 'google_drive_authorization_code', context=c),
'google_drive_authorization_code': lambda s, cr, uid, c: s.pool['ir.config_parameter'].get_param(cr, SUPERUSER_ID, 'google_drive_authorization_code', context=c),
}
def set_google_authorization_code(self, cr, uid, ids, context=None):
@ -249,5 +249,5 @@ class base_config_settings(osv.TransientModel):
auth_code = config.google_drive_authorization_code
if auth_code and auth_code != ir_config_param.get_param(cr, uid, 'google_drive_authorization_code', context=context):
refresh_token = self.pool['google.service'].generate_refresh_token(cr, uid, 'drive', config.google_drive_authorization_code, context=context)
ir_config_param.set_param(cr, uid, 'google_drive_authorization_code', auth_code)
ir_config_param.set_param(cr, uid, 'google_drive_refresh_token', refresh_token)
ir_config_param.set_param(cr, uid, 'google_drive_authorization_code', auth_code, groups=['base.group_system'])
ir_config_param.set_param(cr, uid, 'google_drive_refresh_token', refresh_token, groups=['base.group_system'])

View File

@ -5,11 +5,13 @@
<record id="config_google_drive_client_id" model="ir.config_parameter">
<field name="key">google_drive_client_id</field>
<field name="value">598905559630.apps.googleusercontent.com</field>
<field name="group_ids" eval="[(4, ref('base.group_user'))]" />
</record>
<record id="config_google_drive_client_secret" model="ir.config_parameter">
<field name="key">google_drive_client_secret</field>
<field name="value">vTmou73c-njP-1qCxm7qx7QE</field>
<field name="group_ids" eval="[(4, ref('base.group_system'))]" />
</record>
</data>

View File

@ -51,7 +51,7 @@ class hr_employee_category(osv.Model):
_name = "hr.employee.category"
_description = "Employee Category"
_columns = {
'name': fields.char("Employee Tag", size=64, required=True),
'name': fields.char("Employee Tag", required=True),
'complete_name': fields.function(_name_get_fnc, type="char", string='Name'),
'parent_id': fields.many2one('hr.employee.category', 'Parent Employee Tag', select=True),
'child_ids': fields.one2many('hr.employee.category', 'parent_id', 'Child Categories'),
@ -96,7 +96,7 @@ class hr_job(osv.Model):
_description = "Job Position"
_inherit = ['mail.thread', 'ir.needaction_mixin']
_columns = {
'name': fields.char('Job Name', size=128, required=True, select=True),
'name': fields.char('Job Name', required=True, select=True),
'expected_employees': fields.function(_get_nbr_employees, string='Total Forecasted Employees',
help='Expected number of employees for this job position after new recruitment.',
store = {
@ -192,20 +192,20 @@ class hr_employee(osv.osv):
'name_related': fields.related('resource_id', 'name', type='char', string='Name', readonly=True, store=True),
'country_id': fields.many2one('res.country', 'Nationality'),
'birthday': fields.date("Date of Birth"),
'ssnid': fields.char('SSN No', size=32, help='Social Security Number'),
'sinid': fields.char('SIN No', size=32, help="Social Insurance Number"),
'identification_id': fields.char('Identification No', size=32),
'otherid': fields.char('Other Id', size=64),
'ssnid': fields.char('SSN No', help='Social Security Number'),
'sinid': fields.char('SIN No', help="Social Insurance Number"),
'identification_id': fields.char('Identification No'),
'otherid': fields.char('Other Id'),
'gender': fields.selection([('male', 'Male'), ('female', 'Female')], 'Gender'),
'marital': fields.selection([('single', 'Single'), ('married', 'Married'), ('widower', 'Widower'), ('divorced', 'Divorced')], 'Marital Status'),
'department_id': fields.many2one('hr.department', 'Department'),
'address_id': fields.many2one('res.partner', 'Working Address'),
'address_home_id': fields.many2one('res.partner', 'Home Address'),
'bank_account_id': fields.many2one('res.partner.bank', 'Bank Account Number', domain="[('partner_id','=',address_home_id)]", help="Employee bank salary account"),
'work_phone': fields.char('Work Phone', size=32, readonly=False),
'mobile_phone': fields.char('Work Mobile', size=32, readonly=False),
'work_phone': fields.char('Work Phone', readonly=False),
'mobile_phone': fields.char('Work Mobile', readonly=False),
'work_email': fields.char('Work Email', size=240),
'work_location': fields.char('Office Location', size=32),
'work_location': fields.char('Office Location'),
'notes': fields.text('Notes'),
'parent_id': fields.many2one('hr.employee', 'Manager'),
'category_ids': fields.many2many('hr.employee.category', 'employee_category_rel', 'emp_id', 'category_id', 'Tags'),
@ -232,7 +232,7 @@ class hr_employee(osv.osv):
help="Small-sized photo of the employee. It is automatically "\
"resized as a 64x64px image, with aspect ratio preserved. "\
"Use this field anywhere a small image is required."),
'passport_id': fields.char('Passport No', size=64),
'passport_id': fields.char('Passport No'),
'color': fields.integer('Color Index'),
'city': fields.related('address_id', 'city', type='char', string='City'),
'login': fields.related('user_id', 'login', type='char', string='Login', readonly=1),
@ -384,7 +384,7 @@ class hr_department(osv.osv):
_name = "hr.department"
_columns = {
'name': fields.char('Department Name', size=64, required=True),
'name': fields.char('Department Name', required=True),
'complete_name': fields.function(_dept_name_get_fnc, type="char", string='Name'),
'company_id': fields.many2one('res.company', 'Company', select=True, required=False),
'parent_id': fields.many2one('hr.department', 'Parent Department', select=True),

View File

@ -16,8 +16,9 @@
<record model="ir.actions.act_window" id="hr_applicant_resumes">
<field name="name">Resumes and Letters</field>
<field name="res_model">ir.attachment</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="document.view_document_file_tree"/>
<field name="view_type">form</field>
<field name="view_mode">kanban,tree,form</field>
<field name="view_id" ref="mail.view_document_file_kanban"/>
<field name="domain">[('res_model','=','hr.applicant')]</field>
<field name="help" type="html">
<p>

View File

@ -30,7 +30,7 @@ class hr_action_reason(osv.osv):
_name = "hr.action.reason"
_description = "Action Reason"
_columns = {
'name': fields.char('Reason', size=64, required=True, help='Specifies the reason for Signing In/Signing Out.'),
'name': fields.char('Reason', required=True, help='Specifies the reason for Signing In/Signing Out.'),
'action_type': fields.selection([('sign_in', 'Sign in'), ('sign_out', 'Sign out')], "Action Type"),
}
_defaults = {

View File

@ -0,0 +1,3 @@
.oe_systray #oe_attendance_sign_in_out_icon {
font-color: white;
}

View File

@ -1,33 +0,0 @@
.openerp .oe_attendance_status {
height: 32px;
width: 32px;
display: inline-block;
}
.openerp .oe_attendance_signin {
float: right;
height: 32px;
width: 32px;
background: url(/hr_attendance/static/src/img/emp-out32.png);
cursor: pointer;
}
.openerp .oe_attendance_signin:hover {
background: url(/hr_attendance/static/src/img/emp-out-disable32.png);
}
.openerp .oe_attendance_status.oe_attendance_signed .oe_attendance_signin {
display: none;
}
.openerp .oe_attendance_signout {
float:right;
height: 32px;
width: 32px;
background: url(/hr_attendance/static/src/img/emp-in32.png);
cursor: pointer;
}
.openerp .oe_attendance_signout:hover {
background: url(/hr_attendance/static/src/img/emp-in-disable32.png);
}
.openerp .oe_attendance_status.oe_attendance_nosigned .oe_attendance_signout {
display: none;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -14,15 +14,14 @@ openerp.hr_attendance = function (instance) {
start: function() {
var self = this;
var tmp = function() {
this.$el.toggleClass("oe_attendance_nosigned", ! this.get("signed_in"));
this.$el.toggleClass("oe_attendance_signed", this.get("signed_in"));
var $sign_in_out_icon = this.$('#oe_attendance_sign_in_out_icon');
$sign_in_out_icon.toggleClass("fa-sign-in", ! this.get("signed_in"));
$sign_in_out_icon.toggleClass("fa-sign-out", this.get("signed_in"));
};
this.on("change:signed_in", this, tmp);
_.bind(tmp, this)();
this.$(".oe_attendance_signin").click(function() {
self.do_update_attendance();
});
this.$(".oe_attendance_signout").click(function() {
this.$(".oe_attendance_sign_in_out").click(function(ev) {
ev.preventDefault();
self.do_update_attendance();
});
this.$el.tooltip({

View File

@ -1,13 +1,9 @@
<template>
<t t-name="AttendanceSlider">
<div class="oe_attendance_status oe_attendance_nosigned" data-toggle="tooltip">
<div class="oe_attendance_signin"></div>
<div class="oe_attendance_signout"></div>
</div>
<li class="oe_attendance_status" data-toggle="tooltip">
<a href="#" class="oe_attendance_sign_in_out">
<i id="oe_attendance_sign_in_out_icon" class="fa fa-sign-in"/>
</a>
</li>
</t>
</template>

View File

@ -5,8 +5,8 @@
<data>
<template id="assets_backend" name="hr_attendance assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<link rel="stylesheet" href="/hr_attendance/static/src/css/slider.css"/>
<script type="text/javascript" src="/hr_attendance/static/src/js/attendance.js"></script>
<link rel="stylesheet" href="/hr_attendance/static/src/css/attendance.css"/>
</xpath>
</template>
</data>

Some files were not shown because too many files have changed in this diff Show More