[MERGE]merge with trunk
bzr revid: kbh@tinyerp.com-20120925052119-z1wd5wpdsno7sa63
This commit is contained in:
commit
62245f48c8
|
@ -63,6 +63,8 @@ for a particular financial year and for preparation of vouchers there is a modul
|
||||||
'wizard/account_use_model_view.xml',
|
'wizard/account_use_model_view.xml',
|
||||||
'account_installer.xml',
|
'account_installer.xml',
|
||||||
'wizard/account_period_close_view.xml',
|
'wizard/account_period_close_view.xml',
|
||||||
|
'wizard/account_reconcile_view.xml',
|
||||||
|
'wizard/account_unreconcile_view.xml',
|
||||||
'account_view.xml',
|
'account_view.xml',
|
||||||
'account_report.xml',
|
'account_report.xml',
|
||||||
'account_financial_report_data.xml',
|
'account_financial_report_data.xml',
|
||||||
|
@ -85,14 +87,12 @@ for a particular financial year and for preparation of vouchers there is a modul
|
||||||
'wizard/account_journal_select_view.xml',
|
'wizard/account_journal_select_view.xml',
|
||||||
'wizard/account_change_currency_view.xml',
|
'wizard/account_change_currency_view.xml',
|
||||||
'wizard/account_validate_move_view.xml',
|
'wizard/account_validate_move_view.xml',
|
||||||
'wizard/account_unreconcile_view.xml',
|
|
||||||
'wizard/account_report_general_ledger_view.xml',
|
'wizard/account_report_general_ledger_view.xml',
|
||||||
'wizard/account_invoice_state_view.xml',
|
'wizard/account_invoice_state_view.xml',
|
||||||
'wizard/account_report_partner_balance_view.xml',
|
'wizard/account_report_partner_balance_view.xml',
|
||||||
'wizard/account_report_account_balance_view.xml',
|
'wizard/account_report_account_balance_view.xml',
|
||||||
'wizard/account_report_aged_partner_balance_view.xml',
|
'wizard/account_report_aged_partner_balance_view.xml',
|
||||||
'wizard/account_report_partner_ledger_view.xml',
|
'wizard/account_report_partner_ledger_view.xml',
|
||||||
'wizard/account_reconcile_view.xml',
|
|
||||||
'wizard/account_reconcile_partner_process_view.xml',
|
'wizard/account_reconcile_partner_process_view.xml',
|
||||||
'wizard/account_automatic_reconcile_view.xml',
|
'wizard/account_automatic_reconcile_view.xml',
|
||||||
'wizard/account_financial_report_view.xml',
|
'wizard/account_financial_report_view.xml',
|
||||||
|
@ -126,6 +126,14 @@ for a particular financial year and for preparation of vouchers there is a modul
|
||||||
'res_config_view.xml',
|
'res_config_view.xml',
|
||||||
'account_pre_install.yml'
|
'account_pre_install.yml'
|
||||||
],
|
],
|
||||||
|
'js': [
|
||||||
|
'static/src/js/account_move_reconciliation.js',
|
||||||
|
],
|
||||||
|
'qweb' : [
|
||||||
|
"static/src/xml/account_move_reconciliation.xml",
|
||||||
|
],
|
||||||
|
'css':['static/src/css/account_move_reconciliation.css'
|
||||||
|
],
|
||||||
'demo': [
|
'demo': [
|
||||||
'demo/account_demo.xml',
|
'demo/account_demo.xml',
|
||||||
'project/project_demo.xml',
|
'project/project_demo.xml',
|
||||||
|
|
|
@ -601,7 +601,7 @@ class account_account(osv.osv):
|
||||||
if not default:
|
if not default:
|
||||||
default = {}
|
default = {}
|
||||||
default = default.copy()
|
default = default.copy()
|
||||||
default['code'] = (account['code'] or '') + '(copy)'
|
default.update(code=_("%s (copy)") % (account['code'] or ''))
|
||||||
if not local:
|
if not local:
|
||||||
done_list = []
|
done_list = []
|
||||||
if account.id in done_list:
|
if account.id in done_list:
|
||||||
|
@ -782,9 +782,10 @@ class account_journal(osv.osv):
|
||||||
if not default:
|
if not default:
|
||||||
default = {}
|
default = {}
|
||||||
default = default.copy()
|
default = default.copy()
|
||||||
default['code'] = (journal['code'] or '') + '(copy)'
|
default.update(
|
||||||
default['name'] = (journal['name'] or '') + '(copy)'
|
code=_("%s (copy)") % (journal['code'] or ''),
|
||||||
default['sequence_id'] = False
|
name=_("%s (copy)") % (journal['name'] or ''),
|
||||||
|
sequence_id=False)
|
||||||
return super(account_journal, self).copy(cr, uid, id, default, context=context)
|
return super(account_journal, self).copy(cr, uid, id, default, context=context)
|
||||||
|
|
||||||
def write(self, cr, uid, ids, vals, context=None):
|
def write(self, cr, uid, ids, vals, context=None):
|
||||||
|
|
|
@ -485,7 +485,7 @@ class account_move_line(osv.osv):
|
||||||
'debit': fields.float('Debit', digits_compute=dp.get_precision('Account')),
|
'debit': fields.float('Debit', digits_compute=dp.get_precision('Account')),
|
||||||
'credit': fields.float('Credit', digits_compute=dp.get_precision('Account')),
|
'credit': fields.float('Credit', digits_compute=dp.get_precision('Account')),
|
||||||
'account_id': fields.many2one('account.account', 'Account', required=True, ondelete="cascade", domain=[('type','<>','view'), ('type', '<>', 'closed')], select=2),
|
'account_id': fields.many2one('account.account', 'Account', required=True, ondelete="cascade", domain=[('type','<>','view'), ('type', '<>', 'closed')], select=2),
|
||||||
'move_id': fields.many2one('account.move', 'Move', ondelete="cascade", help="The move of this entry line.", select=2, required=True),
|
'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'),
|
'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', size=64, store=True),
|
||||||
'statement_id': fields.many2one('account.bank.statement', 'Statement', help="The bank statement used for bank reconciliation", select=1),
|
'statement_id': fields.many2one('account.bank.statement', 'Statement', help="The bank statement used for bank reconciliation", select=1),
|
||||||
|
@ -708,7 +708,9 @@ class account_move_line(osv.osv):
|
||||||
context = {}
|
context = {}
|
||||||
if context and context.get('next_partner_only', False):
|
if context and context.get('next_partner_only', False):
|
||||||
if not context.get('partner_id', False):
|
if not context.get('partner_id', False):
|
||||||
partner = self.get_next_partner_only(cr, uid, offset, context)
|
partner = self.list_partners_to_reconcile(cr, uid, context=context)
|
||||||
|
if partner:
|
||||||
|
partner = partner[0]
|
||||||
else:
|
else:
|
||||||
partner = context.get('partner_id', False)
|
partner = context.get('partner_id', False)
|
||||||
if not partner:
|
if not partner:
|
||||||
|
@ -716,26 +718,26 @@ class account_move_line(osv.osv):
|
||||||
args.append(('partner_id', '=', partner[0]))
|
args.append(('partner_id', '=', partner[0]))
|
||||||
return super(account_move_line, self).search(cr, uid, args, offset, limit, order, context, count)
|
return super(account_move_line, self).search(cr, uid, args, offset, limit, order, context, count)
|
||||||
|
|
||||||
def get_next_partner_only(self, cr, uid, offset=0, context=None):
|
def list_partners_to_reconcile(self, cr, uid, context=None):
|
||||||
cr.execute(
|
cr.execute(
|
||||||
"""
|
"""
|
||||||
SELECT p.id
|
SELECT partner_id
|
||||||
FROM res_partner p
|
FROM (
|
||||||
RIGHT JOIN (
|
SELECT l.partner_id, p.last_reconciliation_date, SUM(l.debit) AS debit, SUM(l.credit) AS credit
|
||||||
SELECT l.partner_id AS partner_id, SUM(l.debit) AS debit, SUM(l.credit) AS credit
|
|
||||||
FROM account_move_line l
|
FROM account_move_line l
|
||||||
LEFT JOIN account_account a ON (a.id = l.account_id)
|
RIGHT JOIN account_account a ON (a.id = l.account_id)
|
||||||
LEFT JOIN res_partner p ON (l.partner_id = p.id)
|
RIGHT JOIN res_partner p ON (l.partner_id = p.id)
|
||||||
WHERE a.reconcile IS TRUE
|
WHERE a.reconcile IS TRUE
|
||||||
AND l.reconcile_id IS NULL
|
AND l.reconcile_id IS NULL
|
||||||
AND (p.last_reconciliation_date IS NULL OR l.date > p.last_reconciliation_date)
|
AND (p.last_reconciliation_date IS NULL OR l.date > p.last_reconciliation_date)
|
||||||
AND l.state <> 'draft'
|
AND l.state <> 'draft'
|
||||||
GROUP BY l.partner_id
|
GROUP BY l.partner_id, p.last_reconciliation_date
|
||||||
) AS s ON (p.id = s.partner_id)
|
) AS s
|
||||||
WHERE debit > 0 AND credit > 0
|
WHERE debit > 0 AND credit > 0
|
||||||
ORDER BY p.last_reconciliation_date LIMIT 1 OFFSET %s""", (offset, )
|
ORDER BY last_reconciliation_date""")
|
||||||
)
|
ids = cr.fetchall()
|
||||||
return cr.fetchone()
|
ids = len(ids) and [x[0] for x in ids] or []
|
||||||
|
return self.pool.get('res.partner').name_get(cr, uid, ids, context=context)
|
||||||
|
|
||||||
def reconcile_partial(self, cr, uid, ids, type='auto', context=None, writeoff_acc_id=False, writeoff_period_id=False, writeoff_journal_id=False):
|
def reconcile_partial(self, cr, uid, ids, type='auto', context=None, writeoff_acc_id=False, writeoff_period_id=False, writeoff_journal_id=False):
|
||||||
move_rec_obj = self.pool.get('account.move.reconcile')
|
move_rec_obj = self.pool.get('account.move.reconcile')
|
||||||
|
@ -915,8 +917,8 @@ class account_move_line(osv.osv):
|
||||||
|
|
||||||
if lines and lines[0]:
|
if lines and lines[0]:
|
||||||
partner_id = lines[0].partner_id and lines[0].partner_id.id or False
|
partner_id = lines[0].partner_id and lines[0].partner_id.id or False
|
||||||
if partner_id and context and context.get('stop_reconcile', False):
|
if not partner_obj.has_something_to_reconcile(cr, uid, partner_id, context=context):
|
||||||
partner_obj.write(cr, uid, [partner_id], {'last_reconciliation_date': time.strftime('%Y-%m-%d %H:%M:%S')})
|
partner_obj.mark_as_reconciled(cr, uid, [partner_id], context=context)
|
||||||
return r_id
|
return r_id
|
||||||
|
|
||||||
def view_header_get(self, cr, user, view_id, view_type, context=None):
|
def view_header_get(self, cr, user, view_id, view_type, context=None):
|
||||||
|
|
|
@ -101,29 +101,29 @@
|
||||||
<field name="model">account.period</field>
|
<field name="model">account.period</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Account Period" version="7.0">
|
<form string="Account Period" version="7.0">
|
||||||
<header>
|
<header>
|
||||||
<button string="Close Period" name="%(account.action_account_period_close)d" type="action" class="oe_highlight" states="draft"/>
|
<button string="Close Period" name="%(account.action_account_period_close)d" type="action" class="oe_highlight" states="draft"/>
|
||||||
<button name="action_draft" states="done" string="Set to Draft" type="object" groups="account.group_account_manager"/>
|
<button name="action_draft" states="done" string="Set to Draft" type="object" groups="account.group_account_manager"/>
|
||||||
<field name="state" widget="statusbar" nolabel="1"/>
|
<field name="state" widget="statusbar" nolabel="1"/>
|
||||||
</header>
|
</header>
|
||||||
<sheet>
|
<sheet>
|
||||||
<group>
|
<group>
|
||||||
<group>
|
<group>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="fiscalyear_id" widget="selection"/>
|
<field name="fiscalyear_id" widget="selection"/>
|
||||||
<label for="date_start" string="Duration"/>
|
<label for="date_start" string="Duration"/>
|
||||||
<div>
|
<div>
|
||||||
<field name="date_start" class="oe_inline" nolabel="1"/> -
|
<field name="date_start" class="oe_inline" nolabel="1"/> -
|
||||||
<field name="date_stop" nolabel="1" class="oe_inline"/>
|
<field name="date_stop" nolabel="1" class="oe_inline"/>
|
||||||
</div>
|
</div>
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="code"/>
|
<field name="code"/>
|
||||||
<field name="special"/>
|
<field name="special"/>
|
||||||
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
|
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
</sheet>
|
</sheet>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
@ -1039,7 +1039,26 @@
|
||||||
Entries lines
|
Entries lines
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<record id="view_move_line_tree" model="ir.ui.view">
|
<record id="view_move_line_tree_reconcile" model="ir.ui.view">
|
||||||
|
<field name="name">account.move.line.reconcile.tree</field>
|
||||||
|
<field name="model">account.move.line</field>
|
||||||
|
<field eval="24" name="priority"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<tree colors="red:state == 'draft';black:state == 'valid'" string="Journal Items to Reconcile" create="false">
|
||||||
|
<field name="date"/>
|
||||||
|
<field name="move_id"/>
|
||||||
|
<field name="ref"/>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="partner_id"/>
|
||||||
|
<field name="account_id"/>
|
||||||
|
<field name="reconcile_partial_id"/>
|
||||||
|
<field name="debit" sum="Total debit"/>
|
||||||
|
<field name="credit" sum="Total credit"/>
|
||||||
|
</tree>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="view_move_line_tree" model="ir.ui.view">
|
||||||
<field name="name">account.move.line.tree</field>
|
<field name="name">account.move.line.tree</field>
|
||||||
<field name="model">account.move.line</field>
|
<field name="model">account.move.line</field>
|
||||||
<field eval="4" name="priority"/>
|
<field eval="4" name="priority"/>
|
||||||
|
@ -1074,64 +1093,64 @@
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Journal Item" version="7.0">
|
<form string="Journal Item" version="7.0">
|
||||||
<sheet>
|
<sheet>
|
||||||
<group>
|
<group>
|
||||||
<group>
|
<group>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="ref"/>
|
<field name="ref"/>
|
||||||
<field name="partner_id" on_change="onchange_partner_id(False,partner_id,account_id,debit,credit,date)"/>
|
<field name="partner_id" on_change="onchange_partner_id(False,partner_id,account_id,debit,credit,date)"/>
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="journal_id"/>
|
<field name="journal_id"/>
|
||||||
<field name="period_id"/>
|
<field name="period_id"/>
|
||||||
<field name="company_id" required="1" groups="base.group_multi_company"/>
|
<field name="company_id" required="1" groups="base.group_multi_company"/>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
<notebook colspan="4">
|
<notebook colspan="4">
|
||||||
<page string="Information">
|
<page string="Information">
|
||||||
<group>
|
<group>
|
||||||
<group string="Amount">
|
<group string="Amount">
|
||||||
<field name="account_id" domain="[('company_id', '=', company_id), ('type','<>','view'), ('type','<>','consolidation')]"/>
|
<field name="account_id" domain="[('company_id', '=', company_id), ('type','<>','view'), ('type','<>','consolidation')]"/>
|
||||||
<field name="debit"/>
|
<field name="debit"/>
|
||||||
<field name="credit"/>
|
<field name="credit"/>
|
||||||
<field name="quantity"/>
|
<field name="quantity"/>
|
||||||
</group>
|
</group>
|
||||||
<group string="Accounting Documents">
|
<group string="Accounting Documents">
|
||||||
<field name="invoice" readonly="True"/>
|
<field name="invoice" readonly="True"/>
|
||||||
<field name="move_id" required="False"/>
|
<field name="move_id" required="False"/>
|
||||||
<field name="statement_id" readonly="True"/>
|
<field name="statement_id" readonly="True"/>
|
||||||
</group>
|
</group>
|
||||||
<group string="Dates">
|
<group string="Dates">
|
||||||
<field name="date"/>
|
<field name="date"/>
|
||||||
<field name="date_maturity"/>
|
<field name="date_maturity"/>
|
||||||
<field name="date_created" readonly="True"/>
|
<field name="date_created" readonly="True"/>
|
||||||
</group>
|
</group>
|
||||||
<group string="Taxes">
|
<group string="Taxes">
|
||||||
<field name="tax_code_id"/>
|
<field name="tax_code_id"/>
|
||||||
<field name="tax_amount"/>
|
<field name="tax_amount"/>
|
||||||
<field name="account_tax_id" domain="[('parent_id','=',False)]"/>
|
<field name="account_tax_id" domain="[('parent_id','=',False)]"/>
|
||||||
</group>
|
</group>
|
||||||
<group attrs="{'readonly':[('state','=','valid')]}" string="Currency" groups="base.group_multi_currency">
|
<group attrs="{'readonly':[('state','=','valid')]}" string="Currency" groups="base.group_multi_currency">
|
||||||
<field name="currency_id"/>
|
<field name="currency_id"/>
|
||||||
<field name="amount_currency"/>
|
<field name="amount_currency"/>
|
||||||
</group>
|
</group>
|
||||||
<group string="Reconciliation">
|
<group string="Reconciliation">
|
||||||
<field name="reconcile_id"/>
|
<field name="reconcile_id"/>
|
||||||
<field name="reconcile_partial_id"/>
|
<field name="reconcile_partial_id"/>
|
||||||
</group>
|
</group>
|
||||||
<group string="States">
|
<group string="States">
|
||||||
<field name="state"/>
|
<field name="state"/>
|
||||||
<field name="blocked"/>
|
<field name="blocked"/>
|
||||||
</group>
|
</group>
|
||||||
<group groups="analytic.group_analytic_accounting" string="Analytic">
|
<group groups="analytic.group_analytic_accounting" string="Analytic">
|
||||||
<field name="analytic_account_id" domain="[('parent_id','!=',False)]"/>
|
<field name="analytic_account_id" domain="[('parent_id','!=',False)]"/>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
<field name="narration" colspan="4" nolabel="1" placeholder="Add an internal note..."/>
|
<field name="narration" colspan="4" nolabel="1" placeholder="Add an internal note..."/>
|
||||||
</page>
|
</page>
|
||||||
<page string="Analytic Lines" groups="analytic.group_analytic_accounting">
|
<page string="Analytic Lines" groups="analytic.group_analytic_accounting">
|
||||||
<field name="analytic_lines" context="{'default_general_account_id':account_id, 'default_name': name, 'default_date':date, 'amount': (debit or 0.0)-(credit or 0.0)}"/>
|
<field name="analytic_lines" context="{'default_general_account_id':account_id, 'default_name': name, 'default_date':date, 'amount': (debit or 0.0)-(credit or 0.0)}"/>
|
||||||
</page>
|
</page>
|
||||||
</notebook>
|
</notebook>
|
||||||
</sheet>
|
</sheet>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
|
@ -1513,7 +1532,6 @@
|
||||||
|
|
||||||
<record id="action_move_line_search" model="ir.actions.act_window">
|
<record id="action_move_line_search" model="ir.actions.act_window">
|
||||||
<field name="name">Journal Items</field>
|
<field name="name">Journal Items</field>
|
||||||
<field name="type">ir.actions.act_window</field>
|
|
||||||
<field name="res_model">account.move.line</field>
|
<field name="res_model">account.move.line</field>
|
||||||
<field name="view_type">form</field>
|
<field name="view_type">form</field>
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
|
@ -1532,15 +1550,31 @@
|
||||||
<field name="act_window_id" ref="action_move_line_search"/>
|
<field name="act_window_id" ref="action_move_line_search"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<act_window
|
<record id="action_account_manual_reconcile" model="ir.actions.act_window">
|
||||||
context="{'search_default_next_partner':1,'view_mode':True}"
|
<field name="context">{'search_default_unreconciled': 1,'view_mode':True}</field>
|
||||||
id="action_account_manual_reconcile" name="Journal Items"
|
<field name="name">Journal Items to Reconcile</field>
|
||||||
res_model="account.move.line"
|
<field name="res_model">account.move.line</field>
|
||||||
view_id="view_move_line_tree"/>
|
<field name="view_id" ref="view_move_line_tree_reconcile"/>
|
||||||
|
<field name="view_type">form</field>
|
||||||
|
<field name="view_mode">account_reconciliation_list</field>
|
||||||
|
<field name="help" type="html">
|
||||||
|
<p>
|
||||||
|
Good job!
|
||||||
|
</p><p>
|
||||||
|
There is nothing to reconcile. All invoices and payments
|
||||||
|
have been reconciled, your partner balance is clean.
|
||||||
|
</p>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
<menuitem
|
||||||
|
name="Journal Items to Reconcile"
|
||||||
|
action="action_account_manual_reconcile"
|
||||||
|
id="menu_manual_reconcile_bank"
|
||||||
|
sequence="20"
|
||||||
|
parent="account.menu_finance_bank_and_cash"/>
|
||||||
|
|
||||||
<menuitem
|
<menuitem
|
||||||
name="Manual Reconciliation" icon="STOCK_EXECUTE"
|
name="Manual Reconciliation"
|
||||||
action="action_account_manual_reconcile"
|
action="action_account_manual_reconcile"
|
||||||
id="menu_manual_reconcile"
|
id="menu_manual_reconcile"
|
||||||
parent="account.periodical_processing_reconciliation"/>
|
parent="account.periodical_processing_reconciliation"/>
|
||||||
|
|
|
@ -122,6 +122,14 @@
|
||||||
<field name="type">other</field>
|
<field name="type">other</field>
|
||||||
<field name="user_type" ref="data_account_type_income"/>
|
<field name="user_type" ref="data_account_type_income"/>
|
||||||
</record>
|
</record>
|
||||||
|
<record id="usd_bnk" model="account.account">
|
||||||
|
<field name="code">X11007</field>
|
||||||
|
<field name="name">USD Bank Account - (test)</field>
|
||||||
|
<field ref="cas" name="parent_id"/>
|
||||||
|
<field name="type">liquidity</field>
|
||||||
|
<field name="user_type" ref="data_account_type_asset"/>
|
||||||
|
<field name="currency_id" ref="base.USD"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
<record model="account.account" id="liabilities_view">
|
<record model="account.account" id="liabilities_view">
|
||||||
<field name="name">Liabilities - (test)</field>
|
<field name="name">Liabilities - (test)</field>
|
||||||
|
@ -360,8 +368,8 @@
|
||||||
<field name="type">bank</field>
|
<field name="type">bank</field>
|
||||||
<field name="view_id" ref="account_journal_bank_view"/>
|
<field name="view_id" ref="account_journal_bank_view"/>
|
||||||
<field name="sequence_id" ref="sequence_bank_journal"/>
|
<field name="sequence_id" ref="sequence_bank_journal"/>
|
||||||
<field model="account.account" name="default_debit_account_id" ref="cash"/>
|
<field model="account.account" name="default_debit_account_id" ref="bnk"/>
|
||||||
<field model="account.account" name="default_credit_account_id" ref="cash"/>
|
<field model="account.account" name="default_credit_account_id" ref="bnk"/>
|
||||||
<field name="analytic_journal_id" ref="sit"/>
|
<field name="analytic_journal_id" ref="sit"/>
|
||||||
<field name="user_id" ref="base.user_root"/>
|
<field name="user_id" ref="base.user_root"/>
|
||||||
</record>
|
</record>
|
||||||
|
@ -412,6 +420,16 @@
|
||||||
<field eval="True" name="centralisation"/>
|
<field eval="True" name="centralisation"/>
|
||||||
<field name="user_id" ref="base.user_root"/>
|
<field name="user_id" ref="base.user_root"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<record id="bank_journal_usd" model="account.journal">
|
||||||
|
<field name="name">USD Bank Journal - (test)</field>
|
||||||
|
<field name="code">TUBK</field>
|
||||||
|
<field name="type">bank</field>
|
||||||
|
<field name="view_id" ref="account_journal_bank_view"/>
|
||||||
|
<field model="account.account" name="usd_debit_account_id" ref="usd_bnk"/>
|
||||||
|
<field model="account.account" name="usd_credit_account_id" ref="usd_bnk"/>
|
||||||
|
<field name="currency_id" ref="base.USD"/>
|
||||||
|
</record>
|
||||||
<!--
|
<!--
|
||||||
Product income and expense accounts, default parameters
|
Product income and expense accounts, default parameters
|
||||||
-->
|
-->
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
|
|
||||||
from osv import fields, osv
|
from osv import fields, osv
|
||||||
|
import time
|
||||||
|
|
||||||
class account_fiscal_position(osv.osv):
|
class account_fiscal_position(osv.osv):
|
||||||
_name = 'account.fiscal.position'
|
_name = 'account.fiscal.position'
|
||||||
|
@ -145,6 +145,29 @@ class res_partner(osv.osv):
|
||||||
def _debit_search(self, cr, uid, obj, name, args, context=None):
|
def _debit_search(self, cr, uid, obj, name, args, context=None):
|
||||||
return self._asset_difference_search(cr, uid, obj, name, 'payable', args, context=context)
|
return self._asset_difference_search(cr, uid, obj, name, 'payable', args, context=context)
|
||||||
|
|
||||||
|
def has_something_to_reconcile(self, cr, uid, partner_id, context=None):
|
||||||
|
'''
|
||||||
|
at least a debit, a credit and a line older than the last reconciliation date of the partner
|
||||||
|
'''
|
||||||
|
cr.execute('''
|
||||||
|
SELECT l.partner_id, SUM(l.debit) AS debit, SUM(l.credit) AS credit
|
||||||
|
FROM account_move_line l
|
||||||
|
RIGHT JOIN account_account a ON (a.id = l.account_id)
|
||||||
|
RIGHT JOIN res_partner p ON (l.partner_id = p.id)
|
||||||
|
WHERE a.reconcile IS TRUE
|
||||||
|
AND p.id = %s
|
||||||
|
AND l.reconcile_id IS NULL
|
||||||
|
AND (p.last_reconciliation_date IS NULL OR l.date > p.last_reconciliation_date)
|
||||||
|
AND l.state <> 'draft'
|
||||||
|
GROUP BY l.partner_id''', (partner_id,))
|
||||||
|
res = cr.dictfetchone()
|
||||||
|
if res:
|
||||||
|
return bool(res['debit'] and res['credit'])
|
||||||
|
return False
|
||||||
|
|
||||||
|
def mark_as_reconciled(self, cr, uid, ids, context=None):
|
||||||
|
return self.write(cr, uid, ids, {'last_reconciliation_date': time.strftime('%Y-%m-%d %H:%M:%S')}, context=context)
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
'credit': fields.function(_credit_debit_get,
|
'credit': fields.function(_credit_debit_get,
|
||||||
fnct_search=_credit_search, string='Total Receivable', multi='dc', help="Total amount this customer owes you."),
|
fnct_search=_credit_search, string='Total Receivable', multi='dc', help="Total amount this customer owes you."),
|
||||||
|
@ -185,7 +208,7 @@ class res_partner(osv.osv):
|
||||||
help="This payment term will be used instead of the default one for the current partner"),
|
help="This payment term will be used instead of the default one for the current partner"),
|
||||||
'ref_companies': fields.one2many('res.company', 'partner_id',
|
'ref_companies': fields.one2many('res.company', 'partner_id',
|
||||||
'Companies that refers to partner'),
|
'Companies that refers to partner'),
|
||||||
'last_reconciliation_date': fields.datetime('Latest Reconciliation Date', help='Date on which the partner accounting entries were reconciled last time')
|
'last_reconciliation_date': fields.datetime('Latest Reconciliation Date', help='Date on which the partner accounting entries were fully reconciled last time. It differs from the date of the last reconciliation made for this partner, as here we depict the fact that nothing more was to be reconciled at this date. This can be achieved in 2 ways: either the last debit/credit entry was reconciled, either the user pressed the button "Fully Reconciled" in the manual reconciliation process')
|
||||||
}
|
}
|
||||||
|
|
||||||
res_partner()
|
res_partner()
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<openerp><data>
|
<openerp>
|
||||||
|
<data>
|
||||||
|
|
||||||
<record id="group_account_invoice" model="res.groups">
|
<record id="group_account_invoice" model="res.groups">
|
||||||
<field name="name">Invoicing & Payments</field>
|
<field name="name">Invoicing & Payments</field>
|
||||||
|
@ -7,11 +8,13 @@
|
||||||
<field name="users" eval="[(4, ref('base.user_root'))]"/>
|
<field name="users" eval="[(4, ref('base.user_root'))]"/>
|
||||||
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
|
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="group_account_user" model="res.groups">
|
<record id="group_account_user" model="res.groups">
|
||||||
<field name="name">Accountant</field>
|
<field name="name">Accountant</field>
|
||||||
<field name="category_id" ref="base.module_category_accounting_and_finance"/>
|
<field name="category_id" ref="base.module_category_accounting_and_finance"/>
|
||||||
<field name="implied_ids" eval="[(4, ref('group_account_invoice'))]"/>
|
<field name="implied_ids" eval="[(4, ref('group_account_invoice'))]"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="group_account_manager" model="res.groups">
|
<record id="group_account_manager" model="res.groups">
|
||||||
<field name="name">Manager</field>
|
<field name="name">Manager</field>
|
||||||
<field name="category_id" ref="base.module_category_accounting_and_finance"/>
|
<field name="category_id" ref="base.module_category_accounting_and_finance"/>
|
||||||
|
@ -25,100 +28,107 @@
|
||||||
|
|
||||||
<record id="account_move_comp_rule" model="ir.rule">
|
<record id="account_move_comp_rule" model="ir.rule">
|
||||||
<field name="name">Account Entry</field>
|
<field name="name">Account Entry</field>
|
||||||
<field ref="model_account_move" name="model_id"/>
|
<field name="model_id" ref="model_account_move"/>
|
||||||
<field eval="True" name="global"/>
|
<field name="global" eval="True"/>
|
||||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="account_move_line_comp_rule" model="ir.rule">
|
<record id="account_move_line_comp_rule" model="ir.rule">
|
||||||
<field name="name">Entry lines</field>
|
<field name="name">Entry lines</field>
|
||||||
<field model="ir.model" name="model_id" ref="model_account_move_line"/>
|
<field name="model_id" ref="model_account_move_line"/>
|
||||||
<field eval="True" name="global"/>
|
<field name="global" eval="True"/>
|
||||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="journal_period_comp_rule" model="ir.rule">
|
<record id="journal_period_comp_rule" model="ir.rule">
|
||||||
<field name="name">Journal Period</field>
|
<field name="name">Journal Period</field>
|
||||||
<field model="ir.model" name="model_id" ref="model_account_journal_period"/>
|
<field name="model_id" ref="model_account_journal_period"/>
|
||||||
<field eval="True" name="global"/>
|
<field name="global" eval="True"/>
|
||||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
||||||
<record id="journal_comp_rule" model="ir.rule">
|
<record id="journal_comp_rule" model="ir.rule">
|
||||||
<field name="name">Journal multi-company</field>
|
<field name="name">Journal multi-company</field>
|
||||||
<field model="ir.model" name="model_id" ref="model_account_journal"/>
|
<field name="model_id" ref="model_account_journal"/>
|
||||||
<field eval="True" name="global"/>
|
<field name="global" eval="True"/>
|
||||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="analytic_journal_comp_rule" model="ir.rule">
|
<record id="analytic_journal_comp_rule" model="ir.rule">
|
||||||
<field name="name">Analytic journal multi-company</field>
|
<field name="name">Analytic journal multi-company</field>
|
||||||
<field model="ir.model" name="model_id" ref="model_account_analytic_journal"/>
|
<field name="model_id" ref="model_account_analytic_journal"/>
|
||||||
<field eval="True" name="global"/>
|
<field name="global" eval="True"/>
|
||||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="period_comp_rule" model="ir.rule">
|
<record id="period_comp_rule" model="ir.rule">
|
||||||
<field name="name">Period multi-company</field>
|
<field name="name">Period multi-company</field>
|
||||||
<field model="ir.model" name="model_id" ref="model_account_period"/>
|
<field name="model_id" ref="model_account_period"/>
|
||||||
<field eval="True" name="global"/>
|
<field name="global" eval="True"/>
|
||||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="fiscal_year_comp_rule" model="ir.rule">
|
<record id="fiscal_year_comp_rule" model="ir.rule">
|
||||||
<field name="name">Fiscal year multi-company</field>
|
<field name="name">Fiscal year multi-company</field>
|
||||||
<field model="ir.model" name="model_id" ref="model_account_fiscalyear"/>
|
<field name="model_id" ref="model_account_fiscalyear"/>
|
||||||
<field eval="True" name="global"/>
|
<field name="global" eval="True"/>
|
||||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="account_comp_rule" model="ir.rule">
|
<record id="account_comp_rule" model="ir.rule">
|
||||||
<field name="name">Account multi-company</field>
|
<field name="name">Account multi-company</field>
|
||||||
<field model="ir.model" name="model_id" ref="model_account_account"/>
|
<field name="model_id" ref="model_account_account"/>
|
||||||
<field eval="True" name="global"/>
|
<field name="global" eval="True"/>
|
||||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="tax_comp_rule" model="ir.rule">
|
<record id="tax_comp_rule" model="ir.rule">
|
||||||
<field name="name">Tax multi-company</field>
|
<field name="name">Tax multi-company</field>
|
||||||
<field model="ir.model" name="model_id" ref="model_account_tax"/>
|
<field name="model_id" ref="model_account_tax"/>
|
||||||
<field eval="True" name="global"/>
|
<field name="global" eval="True"/>
|
||||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="tax_code_comp_rule" model="ir.rule">
|
<record id="tax_code_comp_rule" model="ir.rule">
|
||||||
<field name="name">Tax code multi-company</field>
|
<field name="name">Tax code multi-company</field>
|
||||||
<field model="ir.model" name="model_id" ref="model_account_tax_code"/>
|
<field name="model_id" ref="model_account_tax_code"/>
|
||||||
<field eval="True" name="global"/>
|
<field name="global" eval="True"/>
|
||||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="invoice_comp_rule" model="ir.rule">
|
<record id="invoice_comp_rule" model="ir.rule">
|
||||||
<field name="name">Invoice multi-company</field>
|
<field name="name">Invoice multi-company</field>
|
||||||
<field model="ir.model" name="model_id" ref="model_account_invoice"/>
|
<field name="model_id" ref="model_account_invoice"/>
|
||||||
<field eval="True" name="global"/>
|
<field name="global" eval="True"/>
|
||||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="invoice_analysis_comp_rule" model="ir.rule">
|
<record id="invoice_analysis_comp_rule" model="ir.rule">
|
||||||
<field name="name">Invoice Analysis multi-company</field>
|
<field name="name">Invoice Analysis multi-company</field>
|
||||||
<field model="ir.model" name="model_id" ref="model_account_invoice_report"/>
|
<field name="model_id" ref="model_account_invoice_report"/>
|
||||||
<field eval="True" name="global"/>
|
<field name="global" eval="True"/>
|
||||||
|
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="entry_analysis_comp_rule" model="ir.rule">
|
||||||
|
<field name="name">Entries Analysis multi-company</field>
|
||||||
|
<field name="model_id" ref="model_account_entries_report"/>
|
||||||
|
<field name="global" eval="True"/>
|
||||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="account_fiscal_position_comp_rule" model="ir.rule">
|
<record id="account_fiscal_position_comp_rule" model="ir.rule">
|
||||||
<field name="name">Account fiscal Mapping company rule</field>
|
<field name="name">Account fiscal Mapping company rule</field>
|
||||||
<field model="ir.model" name="model_id" ref="model_account_fiscal_position"/>
|
<field name="model_id" ref="model_account_fiscal_position"/>
|
||||||
<field eval="True" name="global"/>
|
<field name="global" eval="True"/>
|
||||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="account_model_comp_rule" model="ir.rule">
|
<record id="account_model_comp_rule" model="ir.rule">
|
||||||
<field name="name">Account model company rule</field>
|
<field name="name">Account model company rule</field>
|
||||||
<field model="ir.model" name="model_id" ref="model_account_model"/>
|
<field name="model_id" ref="model_account_model"/>
|
||||||
<field eval="True" name="global"/>
|
<field name="global" eval="True"/>
|
||||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
@ -143,4 +153,5 @@
|
||||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</data></openerp>
|
</data>
|
||||||
|
</openerp>
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
.openerp .oe_account_reconciliation {
|
||||||
|
border-bottom: 1px solid #CACACA;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openerp .oe_account_reconciliation button {
|
||||||
|
margin: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openerp .oe_account_reconciliation>div {
|
||||||
|
display: table;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openerp .oe_account_reconciliation>div>div {
|
||||||
|
display: table-cell;
|
||||||
|
width: 50%:
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
openerp.account = function (instance) {
|
||||||
|
var _t = instance.web._t,
|
||||||
|
_lt = instance.web._lt;
|
||||||
|
var QWeb = instance.web.qweb;
|
||||||
|
|
||||||
|
instance.web.account = {};
|
||||||
|
|
||||||
|
instance.web.views.add('account_reconciliation_list', 'instance.web.account.ReconciliationListView');
|
||||||
|
instance.web.account.ReconciliationListView = instance.web.ListView.extend({
|
||||||
|
init: function() {
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
var self = this;
|
||||||
|
this.current_partner = null;
|
||||||
|
this.do_select.add(function() {
|
||||||
|
if (self.get_selected_ids().length === 0) {
|
||||||
|
self.$(".oe_account_recon_reconcile").attr("disabled", "");
|
||||||
|
} else {
|
||||||
|
self.$(".oe_account_recon_reconcile").removeAttr("disabled");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
on_loaded: function() {
|
||||||
|
var self = this;
|
||||||
|
var tmp = this._super.apply(this, arguments);
|
||||||
|
if (this.partners) {
|
||||||
|
this.$el.prepend(QWeb.render("AccountReconciliation", {widget: this}));
|
||||||
|
this.$(".oe_account_recon_previous").click(function() {
|
||||||
|
self.current_partner = (self.current_partner - 1) % self.partners.length;
|
||||||
|
self.search_by_partner();
|
||||||
|
});
|
||||||
|
this.$(".oe_account_recon_next").click(function() {
|
||||||
|
self.current_partner = (self.current_partner + 1) % self.partners.length;
|
||||||
|
self.search_by_partner();
|
||||||
|
});
|
||||||
|
this.$(".oe_account_recon_reconcile").click(function() {
|
||||||
|
self.reconcile();
|
||||||
|
});
|
||||||
|
this.$(".oe_account_recom_mark_as_reconciled").click(function() {
|
||||||
|
self.mark_as_reconciled();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
},
|
||||||
|
do_search: function(domain, context, group_by) {
|
||||||
|
var self = this;
|
||||||
|
this.last_domain = domain;
|
||||||
|
this.last_context = context;
|
||||||
|
this.last_group_by = group_by;
|
||||||
|
this.old_search = _.bind(this._super, this);
|
||||||
|
var mod = new instance.web.Model("account.move.line", context, domain);
|
||||||
|
return mod.call("list_partners_to_reconcile", []).pipe(function(result) {
|
||||||
|
var current = self.current_partner !== null ? self.partners[self.current_partner][0] : null;
|
||||||
|
self.partners = result;
|
||||||
|
var index = _.find(_.range(self.partners.length), function(el) {
|
||||||
|
if (current === self.partners[el][0])
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
if (index !== undefined)
|
||||||
|
self.current_partner = index;
|
||||||
|
else
|
||||||
|
self.current_partner = self.partners.length == 0 ? null : 0;
|
||||||
|
self.search_by_partner();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
search_by_partner: function() {
|
||||||
|
var self = this;
|
||||||
|
var fct = function() {
|
||||||
|
return self.old_search(new instance.web.CompoundDomain(self.last_domain,
|
||||||
|
[["partner_id", "in", self.current_partner === null ? [] :
|
||||||
|
[self.partners[self.current_partner][0]] ]]), self.last_context, self.last_group_by);
|
||||||
|
};
|
||||||
|
if (self.current_partner === null) {
|
||||||
|
self.last_reconciliation_date = _t("Never");
|
||||||
|
return fct();
|
||||||
|
} else {
|
||||||
|
return new instance.web.Model("res.partner").call("read",
|
||||||
|
[self.partners[self.current_partner][0], ["last_reconciliation_date"]]).pipe(function(res) {
|
||||||
|
self.last_reconciliation_date =
|
||||||
|
instance.web.format_value(res.last_reconciliation_date, {"type": "datetime"}, _t("Never"));
|
||||||
|
return fct();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
reconcile: function() {
|
||||||
|
var self = this;
|
||||||
|
var ids = this.get_selected_ids();
|
||||||
|
if (ids.length === 0) {
|
||||||
|
instance.web.dialog($("<div />").text(_t("You must choose at least one record.")), {
|
||||||
|
title: _t("Warning"),
|
||||||
|
modal: true
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
new instance.web.Model("ir.model.data").call("get_object_reference", ["account", "action_view_account_move_line_reconcile"]).pipe(function(result) {
|
||||||
|
var additional_context = _.extend({
|
||||||
|
active_id: ids[0],
|
||||||
|
active_ids: ids,
|
||||||
|
active_model: self.model
|
||||||
|
});
|
||||||
|
return self.rpc("/web/action/load", {
|
||||||
|
action_id: result[1],
|
||||||
|
context: additional_context
|
||||||
|
}, function (result) {
|
||||||
|
result = result.result;
|
||||||
|
result.context = _.extend(result.context || {}, additional_context);
|
||||||
|
result.flags = result.flags || {};
|
||||||
|
result.flags.new_window = true;
|
||||||
|
return self.do_action(result, function () {
|
||||||
|
self.do_search(self.last_domain, self.last_context, self.last_group_by);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
mark_as_reconciled: function() {
|
||||||
|
var self = this;
|
||||||
|
var id = self.partners[self.current_partner][0];
|
||||||
|
new instance.web.Model("res.partner").call("mark_as_reconciled", [[id]]).pipe(function() {
|
||||||
|
self.do_search(self.last_domain, self.last_context, self.last_group_by);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<templates id="template" xml:space="preserve">
|
||||||
|
|
||||||
|
<t t-name="AccountReconciliation">
|
||||||
|
<div class="oe_account_reconciliation">
|
||||||
|
<t t-if="widget.current_partner === null">
|
||||||
|
There is no pending reconciliation.
|
||||||
|
</t>
|
||||||
|
<t t-if="widget.current_partner !== null">
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<button class="oe_account_recon_previous oe_button" href="javascript:void(0)"><</button>
|
||||||
|
<t t-esc="'' + widget.partners[widget.current_partner][1] + ' (' + (widget.current_partner + 1) + '/' + widget.partners.length + ')'"/>
|
||||||
|
<button class="oe_account_recon_next oe_button" href="javascript:void(0)">></button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Last Reconciliation: <t t-esc="widget.last_reconciliation_date" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button class="oe_account_recon_reconcile oe_button oe_highlight" href="javascript:void(0)"
|
||||||
|
disabled="">Reconcile</button>
|
||||||
|
<button class="oe_account_recom_mark_as_reconciled oe_button" href="javascript:void(0)">Nothing to reconcile</button>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
</templates>
|
|
@ -86,19 +86,6 @@ class account_move_line_reconcile(osv.osv_memory):
|
||||||
ids = period_obj.find(cr, uid, dt=date, context=context)
|
ids = period_obj.find(cr, uid, dt=date, context=context)
|
||||||
if ids:
|
if ids:
|
||||||
period_id = ids[0]
|
period_id = ids[0]
|
||||||
#stop the reconciliation process by partner (manual reconciliation) only if there is nothing more to reconcile for this partner
|
|
||||||
if 'active_ids' in context and context['active_ids']:
|
|
||||||
tmp_ml_id = account_move_line_obj.browse(cr, uid, context['active_ids'], context)[0]
|
|
||||||
partner_id = tmp_ml_id.partner_id and tmp_ml_id.partner_id.id or False
|
|
||||||
debit_ml_ids = account_move_line_obj.search(cr, uid, [('partner_id', '=', partner_id), ('account_id.reconcile', '=', True), ('reconcile_id', '=', False), ('debit', '>', 0)], context=context)
|
|
||||||
credit_ml_ids = account_move_line_obj.search(cr, uid, [('partner_id', '=', partner_id), ('account_id.reconcile', '=', True), ('reconcile_id', '=', False), ('credit', '>', 0)], context=context)
|
|
||||||
for ml_id in context['active_ids']:
|
|
||||||
if ml_id in debit_ml_ids:
|
|
||||||
debit_ml_ids.remove(ml_id)
|
|
||||||
if ml_id in credit_ml_ids:
|
|
||||||
credit_ml_ids.remove(ml_id)
|
|
||||||
if not debit_ml_ids and credit_ml_ids:
|
|
||||||
context.update({'stop_reconcile': True})
|
|
||||||
account_move_line_obj.reconcile(cr, uid, context['active_ids'], 'manual', account_id,
|
account_move_line_obj.reconcile(cr, uid, context['active_ids'], 'manual', account_id,
|
||||||
period_id, journal_id, context=context)
|
period_id, journal_id, context=context)
|
||||||
return {'type': 'ir.actions.act_window_close'}
|
return {'type': 'ir.actions.act_window_close'}
|
||||||
|
@ -166,7 +153,6 @@ class account_move_line_reconcile_writeoff(osv.osv_memory):
|
||||||
if ids:
|
if ids:
|
||||||
period_id = ids[0]
|
period_id = ids[0]
|
||||||
|
|
||||||
context.update({'stop_reconcile': True})
|
|
||||||
account_move_line_obj.reconcile(cr, uid, context['active_ids'], 'manual', account_id,
|
account_move_line_obj.reconcile(cr, uid, context['active_ids'], 'manual', account_id,
|
||||||
period_id, journal_id, context=context)
|
period_id, journal_id, context=context)
|
||||||
return {'type': 'ir.actions.act_window_close'}
|
return {'type': 'ir.actions.act_window_close'}
|
||||||
|
|
|
@ -57,10 +57,10 @@ class account_partner_reconcile_process(osv.osv_memory):
|
||||||
def _get_partner(self, cr, uid, context=None):
|
def _get_partner(self, cr, uid, context=None):
|
||||||
move_line_obj = self.pool.get('account.move.line')
|
move_line_obj = self.pool.get('account.move.line')
|
||||||
|
|
||||||
partner = move_line_obj.get_next_partner_only(cr, uid, offset=1, context=context)
|
partner = move_line_obj.list_partners_to_reconcile(cr, uid, context=context)
|
||||||
if not partner:
|
if not partner:
|
||||||
return False
|
return False
|
||||||
return partner[0]
|
return partner[0][0]
|
||||||
|
|
||||||
def data_get(self, cr, uid, to_reconcile, today_reconciled, context=None):
|
def data_get(self, cr, uid, to_reconcile, today_reconciled, context=None):
|
||||||
return {'progress': (100 / (float(to_reconcile + today_reconciled) or 1.0)) * today_reconciled}
|
return {'progress': (100 / (float(to_reconcile + today_reconciled) or 1.0)) * today_reconciled}
|
||||||
|
@ -100,4 +100,4 @@ class account_partner_reconcile_process(osv.osv_memory):
|
||||||
|
|
||||||
account_partner_reconcile_process()
|
account_partner_reconcile_process()
|
||||||
|
|
||||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||||
|
|
|
@ -107,11 +107,12 @@ class coda_bank_account(osv.osv):
|
||||||
if not default:
|
if not default:
|
||||||
default = {}
|
default = {}
|
||||||
default = default.copy()
|
default = default.copy()
|
||||||
default.update({'journal_id': None})
|
default.update(
|
||||||
default['description1'] = cba['description1'] or ''
|
journal_id=None,
|
||||||
default['description2'] = cba['description2'] or ''
|
description1=cba['description1'] or '',
|
||||||
default['name'] = (cba['name'] or '') + ' (copy)'
|
description2=cba['description2'] or '',
|
||||||
default['state'] = cba['state']
|
name=_("%s (copy)") % (cba['name'] or ''),
|
||||||
|
state=cba['state'])
|
||||||
return super(coda_bank_account, self).copy(cr, uid, id, default, context)
|
return super(coda_bank_account, self).copy(cr, uid, id, default, context)
|
||||||
|
|
||||||
def onchange_state(self, cr, uid, ids, state):
|
def onchange_state(self, cr, uid, ids, state):
|
||||||
|
|
|
@ -140,7 +140,7 @@ class account_analytic_account(osv.osv):
|
||||||
'name': fields.char('Account/Contract Name', size=128, required=True),
|
'name': fields.char('Account/Contract Name', size=128, required=True),
|
||||||
'complete_name': fields.function(_complete_name_calc, type='char', string='Full Account Name'),
|
'complete_name': fields.function(_complete_name_calc, type='char', string='Full Account Name'),
|
||||||
'code': fields.char('Reference', size=24, select=True),
|
'code': fields.char('Reference', size=24, select=True),
|
||||||
'type': fields.selection([('view','Analytic View'), ('normal','Analytic Account'),('contract','Contract or Project'),('template','Template of Project')], 'Type of Account', required=True,
|
'type': fields.selection([('view','Analytic View'), ('normal','Analytic Account'),('contract','Contract or Project'),('template','Template of Project')], 'Type of Account', required=True,
|
||||||
help="If you select the View Type, it means you won\'t allow to create journal entries using that account.\n"\
|
help="If you select the View Type, it means you won\'t allow to create journal entries using that account.\n"\
|
||||||
"The type 'Analytic account' stands for usual accounts that you only want to use in accounting.\n"\
|
"The type 'Analytic account' stands for usual accounts that you only want to use in accounting.\n"\
|
||||||
"If you select Contract or Project, it offers you the possibility to manage the validity and the invoicing options for this account.\n"\
|
"If you select Contract or Project, it offers you the possibility to manage the validity and the invoicing options for this account.\n"\
|
||||||
|
@ -168,7 +168,7 @@ class account_analytic_account(osv.osv):
|
||||||
'res.company': (_get_analytic_account, ['currency_id'], 10),
|
'res.company': (_get_analytic_account, ['currency_id'], 10),
|
||||||
}, string='Currency', type='many2one', relation='res.currency'),
|
}, string='Currency', type='many2one', relation='res.currency'),
|
||||||
}
|
}
|
||||||
|
|
||||||
def on_change_template(self, cr, uid, ids, template_id, context=None):
|
def on_change_template(self, cr, uid, ids, template_id, context=None):
|
||||||
if not template_id:
|
if not template_id:
|
||||||
return {}
|
return {}
|
||||||
|
@ -179,7 +179,7 @@ class account_analytic_account(osv.osv):
|
||||||
res['value']['quantity_max'] = template.quantity_max
|
res['value']['quantity_max'] = template.quantity_max
|
||||||
res['value']['description'] = template.description
|
res['value']['description'] = template.description
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def on_change_partner_id(self, cr, uid, ids,partner_id, name, context={}):
|
def on_change_partner_id(self, cr, uid, ids,partner_id, name, context={}):
|
||||||
res={}
|
res={}
|
||||||
if partner_id:
|
if partner_id:
|
||||||
|
@ -222,8 +222,11 @@ class account_analytic_account(osv.osv):
|
||||||
def copy(self, cr, uid, id, default=None, context=None):
|
def copy(self, cr, uid, id, default=None, context=None):
|
||||||
if not default:
|
if not default:
|
||||||
default = {}
|
default = {}
|
||||||
default['code'] = False
|
analytic = self.browse(cr, uid, id, context=context)
|
||||||
default['line_ids'] = []
|
default.update(
|
||||||
|
code=False,
|
||||||
|
line_ids=[],
|
||||||
|
name=_("%s (copy)") % (analytic['name']))
|
||||||
return super(account_analytic_account, self).copy(cr, uid, id, default, context=context)
|
return super(account_analytic_account, self).copy(cr, uid, id, default, context=context)
|
||||||
|
|
||||||
def on_change_company(self, cr, uid, id, company_id):
|
def on_change_company(self, cr, uid, id, company_id):
|
||||||
|
|
|
@ -209,7 +209,7 @@ class document_file(osv.osv):
|
||||||
default = {}
|
default = {}
|
||||||
if 'name' not in default:
|
if 'name' not in default:
|
||||||
name = self.read(cr, uid, [id], ['name'])[0]['name']
|
name = self.read(cr, uid, [id], ['name'])[0]['name']
|
||||||
default.update({'name': name + " " + _("(copy)")})
|
default.update(name=_("%s (copy)") % (name))
|
||||||
return super(document_file, self).copy(cr, uid, id, default, context=context)
|
return super(document_file, self).copy(cr, uid, id, default, context=context)
|
||||||
|
|
||||||
def write(self, cr, uid, ids, vals, context=None):
|
def write(self, cr, uid, ids, vals, context=None):
|
||||||
|
|
|
@ -231,7 +231,7 @@ class document_directory(osv.osv):
|
||||||
if not default:
|
if not default:
|
||||||
default ={}
|
default ={}
|
||||||
name = self.read(cr, uid, [id])[0]['name']
|
name = self.read(cr, uid, [id])[0]['name']
|
||||||
default.update({'name': name+ " (copy)"})
|
default.update(name=_("%s (copy)") % (name))
|
||||||
return super(document_directory,self).copy(cr, uid, id, default, context=context)
|
return super(document_directory,self).copy(cr, uid, id, default, context=context)
|
||||||
|
|
||||||
def _check_duplication(self, cr, uid, vals, ids=[], op='create'):
|
def _check_duplication(self, cr, uid, vals, ids=[], op='create'):
|
||||||
|
|
|
@ -215,7 +215,10 @@ class email_template(osv.osv):
|
||||||
if default is None:
|
if default is None:
|
||||||
default = {}
|
default = {}
|
||||||
default = default.copy()
|
default = default.copy()
|
||||||
default['name'] = template.name + _('(copy)')
|
default.update(
|
||||||
|
name=_("%s (copy)") % (template.name),
|
||||||
|
ref_ir_act_window=False,
|
||||||
|
ref_ir_value=False)
|
||||||
return super(email_template, self).copy(cr, uid, id, default, context)
|
return super(email_template, self).copy(cr, uid, id, default, context)
|
||||||
|
|
||||||
def build_expression(self, field_name, sub_field_name, null_value):
|
def build_expression(self, field_name, sub_field_name, null_value):
|
||||||
|
@ -335,7 +338,7 @@ class email_template(osv.osv):
|
||||||
:param bool force_send: if True, the generated mail.message is
|
:param bool force_send: if True, the generated mail.message is
|
||||||
immediately sent after being created, as if the scheduler
|
immediately sent after being created, as if the scheduler
|
||||||
was executed for this message only.
|
was executed for this message only.
|
||||||
:returns: id of the mail.message that was created
|
:returns: id of the mail.message that was created
|
||||||
"""
|
"""
|
||||||
if context is None: context = {}
|
if context is None: context = {}
|
||||||
mail_mail = self.pool.get('mail.mail')
|
mail_mail = self.pool.get('mail.mail')
|
||||||
|
|
|
@ -38,7 +38,7 @@ when you confirm your sale order it will automatically create a registration for
|
||||||
this event.
|
this event.
|
||||||
""",
|
""",
|
||||||
'author': 'OpenERP SA',
|
'author': 'OpenERP SA',
|
||||||
'depends': ['event','sale','sale_crm'],
|
'depends': ['event', 'sale_crm'],
|
||||||
'data': ['event_sale_view.xml'],
|
'data': ['event_sale_view.xml'],
|
||||||
'demo': ['event_demo.xml'],
|
'demo': ['event_demo.xml'],
|
||||||
'test': ['test/confirm.yml'],
|
'test': ['test/confirm.yml'],
|
||||||
|
|
|
@ -81,10 +81,9 @@ class hr_payroll_structure(osv.osv):
|
||||||
"""
|
"""
|
||||||
if not default:
|
if not default:
|
||||||
default = {}
|
default = {}
|
||||||
default.update({
|
default.update(
|
||||||
'code': self.browse(cr, uid, id, context=context).code + "(copy)",
|
code=_("%s (copy)") % (self.browse(cr, uid, id, context=context).code),
|
||||||
'company_id': self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id
|
company_id=self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id)
|
||||||
})
|
|
||||||
return super(hr_payroll_structure, self).copy(cr, uid, id, default, context=context)
|
return super(hr_payroll_structure, self).copy(cr, uid, id, default, context=context)
|
||||||
|
|
||||||
def get_all_rules(self, cr, uid, structure_ids, context=None):
|
def get_all_rules(self, cr, uid, structure_ids, context=None):
|
||||||
|
@ -305,7 +304,7 @@ class hr_payslip(osv.osv):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
_constraints = [(_check_dates, "Payslip 'Date From' must be before 'Date To'.", ['date_from', 'date_to'])]
|
_constraints = [(_check_dates, "Payslip 'Date From' must be before 'Date To'.", ['date_from', 'date_to'])]
|
||||||
|
|
||||||
def copy(self, cr, uid, id, default=None, context=None):
|
def copy(self, cr, uid, id, default=None, context=None):
|
||||||
if not default:
|
if not default:
|
||||||
|
@ -851,7 +850,7 @@ result = rules.NET > categories.NET * 0.10''',
|
||||||
"""
|
"""
|
||||||
:param rule_id: id of rule to compute
|
:param rule_id: id of rule to compute
|
||||||
:param localdict: dictionary containing the environement in which to compute the rule
|
:param localdict: dictionary containing the environement in which to compute the rule
|
||||||
:return: returns a tuple build as the base/amount computed, the quantity and the rate
|
:return: returns a tuple build as the base/amount computed, the quantity and the rate
|
||||||
:rtype: (float, float, float)
|
:rtype: (float, float, float)
|
||||||
"""
|
"""
|
||||||
rule = self.browse(cr, uid, rule_id, context=context)
|
rule = self.browse(cr, uid, rule_id, context=context)
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
<field name="user_id" ref="base.user_root"/>
|
<field name="user_id" ref="base.user_root"/>
|
||||||
<field name="update_posted" eval="True" />
|
<field name="update_posted" eval="True" />
|
||||||
<field name="entry_posted" eval="True" />
|
<field name="entry_posted" eval="True" />
|
||||||
|
<field name="currency" model="res.currency" ref="base.CHF" />
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="bank_euro_journal" model="account.journal">
|
<record id="bank_euro_journal" model="account.journal">
|
||||||
|
|
|
@ -73,7 +73,7 @@ class res_users(osv.Model):
|
||||||
def create(self, cr, uid, data, context=None):
|
def create(self, cr, uid, data, context=None):
|
||||||
# create default alias same as the login
|
# create default alias same as the login
|
||||||
if not data.get('login', False):
|
if not data.get('login', False):
|
||||||
raise osv.except_osv(_('Invalid Action!'), _('You may not create a user.'))
|
raise osv.except_osv(_('Invalid Action!'), _('You may not create a user. To create new users, you should use the "Settings > Users" menu.'))
|
||||||
|
|
||||||
mail_alias = self.pool.get('mail.alias')
|
mail_alias = self.pool.get('mail.alias')
|
||||||
alias_id = mail_alias.create_unique_alias(cr, uid, {'alias_name': data['login']}, model_name=self._name, context=context)
|
alias_id = mail_alias.create_unique_alias(cr, uid, {'alias_name': data['login']}, model_name=self._name, context=context)
|
||||||
|
|
|
@ -356,7 +356,7 @@ class mrp_bom(osv.osv):
|
||||||
if default is None:
|
if default is None:
|
||||||
default = {}
|
default = {}
|
||||||
bom_data = self.read(cr, uid, id, [], context=context)
|
bom_data = self.read(cr, uid, id, [], context=context)
|
||||||
default.update({'name': bom_data['name'] + ' ' + _('Copy'), 'bom_id':False})
|
default.update(name=_("%s (copy)") % (bom_data['name']), bom_id=False)
|
||||||
return super(mrp_bom, self).copy_data(cr, uid, id, default, context=context)
|
return super(mrp_bom, self).copy_data(cr, uid, id, default, context=context)
|
||||||
|
|
||||||
def create(self, cr, uid, vals, context=None):
|
def create(self, cr, uid, vals, context=None):
|
||||||
|
|
|
@ -34,7 +34,7 @@ This module is the base module for other multi-company modules.
|
||||||
'website': 'http://www.openerp.com/',
|
'website': 'http://www.openerp.com/',
|
||||||
'depends': [
|
'depends': [
|
||||||
'base',
|
'base',
|
||||||
'sale',
|
'sale_stock',
|
||||||
'project',
|
'project',
|
||||||
],
|
],
|
||||||
'data': ['res_company_view.xml'],
|
'data': ['res_company_view.xml'],
|
||||||
|
|
|
@ -49,7 +49,7 @@ Main Features
|
||||||
""",
|
""",
|
||||||
'author': 'OpenERP SA',
|
'author': 'OpenERP SA',
|
||||||
'images': ['images/cash_registers.jpeg', 'images/pos_analysis.jpeg','images/register_analysis.jpeg','images/sale_order_pos.jpeg','images/product_pos.jpeg'],
|
'images': ['images/cash_registers.jpeg', 'images/pos_analysis.jpeg','images/register_analysis.jpeg','images/sale_order_pos.jpeg','images/product_pos.jpeg'],
|
||||||
'depends': ['sale'],
|
'depends': ['sale_stock'],
|
||||||
'data': [
|
'data': [
|
||||||
'security/point_of_sale_security.xml',
|
'security/point_of_sale_security.xml',
|
||||||
'security/ir.model.access.csv',
|
'security/ir.model.access.csv',
|
||||||
|
|
|
@ -30,7 +30,7 @@ This module adds sale menu and features to your portal if sale and portal are in
|
||||||
========================================================================================
|
========================================================================================
|
||||||
""",
|
""",
|
||||||
'author': 'OpenERP SA',
|
'author': 'OpenERP SA',
|
||||||
'depends': ['sale','portal'],
|
'depends': ['sale_stock','portal'],
|
||||||
'data': [
|
'data': [
|
||||||
'security/portal_security.xml',
|
'security/portal_security.xml',
|
||||||
'portal_sale_view.xml',
|
'portal_sale_view.xml',
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
<record id="portal_stock_picking_user_rule" model="ir.rule">
|
<record id="portal_stock_picking_user_rule" model="ir.rule">
|
||||||
<field name="name">Portal Personal Delivery Orders</field>
|
<field name="name">Portal Personal Delivery Orders</field>
|
||||||
<field ref="stock.model_stock_picking" name="model_id"/>
|
<field name="model_id" ref="stock.model_stock_picking"/>
|
||||||
<field name="domain_force">[('partner_id','child_of',[user.partner_id.id])]</field>
|
<field name="domain_force">[('partner_id','child_of',[user.partner_id.id])]</field>
|
||||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
|
@ -143,7 +143,7 @@ instance.web.ViewManager.include({
|
||||||
var image_node = nodes.kind == "subflow" ? "node-subflow" : "node";
|
var image_node = nodes.kind == "subflow" ? "node-subflow" : "node";
|
||||||
image_node = nodes.gray ? image_node + "-gray" : image_node;
|
image_node = nodes.gray ? image_node + "-gray" : image_node;
|
||||||
image_node = nodes.active ? 'node-current': image_node;
|
image_node = nodes.active ? 'node-current': image_node;
|
||||||
var img_src = '/web_process/static/src/img/'+ image_node + '.png';
|
var img_src = '/process/static/src/img/'+ image_node + '.png';
|
||||||
var image = r['image'](img_src, nodes.x-25, nodes.y,150, 100).attr({"cursor": "default"}) .mousedown(function() { return false; });
|
var image = r['image'](img_src, nodes.x-25, nodes.y,150, 100).attr({"cursor": "default"}) .mousedown(function() { return false; });
|
||||||
//For Node
|
//For Node
|
||||||
var process_node = r['rect'](nodes.x, nodes.y, 150, 150).attr({stroke: "none"});
|
var process_node = r['rect'](nodes.x, nodes.y, 150, 150).attr({stroke: "none"});
|
||||||
|
|
|
@ -60,7 +60,7 @@ depending on the product's configuration.
|
||||||
'demo': ['stock_orderpoint.xml'],
|
'demo': ['stock_orderpoint.xml'],
|
||||||
'test': ['test/procurement.yml'],
|
'test': ['test/procurement.yml'],
|
||||||
'installable': True,
|
'installable': True,
|
||||||
'auto_install': False,
|
'auto_install': True,
|
||||||
'certificate': '00954248826881074509',
|
'certificate': '00954248826881074509',
|
||||||
'images': ['images/compute_schedulers.jpeg','images/config_companies_sched.jpeg', 'images/minimum_stock_rules.jpeg'],
|
'images': ['images/compute_schedulers.jpeg','images/config_companies_sched.jpeg', 'images/minimum_stock_rules.jpeg'],
|
||||||
}
|
}
|
||||||
|
|
|
@ -511,7 +511,7 @@ class product_product(osv.osv):
|
||||||
for obj in self.browse(cr, uid, ids, context=context):
|
for obj in self.browse(cr, uid, ids, context=context):
|
||||||
result[obj.id] = tools.image_get_resized_images(obj.image, avoid_resize_medium=True)
|
result[obj.id] = tools.image_get_resized_images(obj.image, avoid_resize_medium=True)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _set_image(self, cr, uid, id, name, value, args, context=None):
|
def _set_image(self, cr, uid, id, name, value, args, context=None):
|
||||||
return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
|
return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
|
||||||
|
|
||||||
|
@ -609,7 +609,7 @@ class product_product(osv.osv):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
_constraints = [(_check_ean_key, 'You provided an invalid "EAN13 Barcode" reference. You may use the internal reference field instead.', ['ean13'])]
|
_constraints = [(_check_ean_key, 'You provided an invalid "EAN13 Barcode" reference. You may use the "Internal Reference" field instead.', ['ean13'])]
|
||||||
|
|
||||||
def on_order(self, cr, uid, ids, orderline, quantity):
|
def on_order(self, cr, uid, ids, orderline, quantity):
|
||||||
pass
|
pass
|
||||||
|
@ -727,7 +727,7 @@ class product_product(osv.osv):
|
||||||
context_wo_lang.pop('lang', None)
|
context_wo_lang.pop('lang', None)
|
||||||
product = self.read(cr, uid, id, ['name'], context=context_wo_lang)
|
product = self.read(cr, uid, id, ['name'], context=context_wo_lang)
|
||||||
default = default.copy()
|
default = default.copy()
|
||||||
default['name'] = product['name'] + ' (copy)'
|
default.update(name=_("%s (copy)") % (product['name']))
|
||||||
|
|
||||||
if context.get('variant',False):
|
if context.get('variant',False):
|
||||||
fields = ['product_tmpl_id', 'active', 'variants', 'default_code',
|
fields = ['product_tmpl_id', 'active', 'variants', 'default_code',
|
||||||
|
@ -897,4 +897,43 @@ class pricelist_partnerinfo(osv.osv):
|
||||||
}
|
}
|
||||||
_order = 'min_quantity asc'
|
_order = 'min_quantity asc'
|
||||||
pricelist_partnerinfo()
|
pricelist_partnerinfo()
|
||||||
|
|
||||||
|
class res_currency(osv.osv):
|
||||||
|
_inherit = 'res.currency'
|
||||||
|
|
||||||
|
def _check_main_currency_rounding(self, cr, uid, ids, context=None):
|
||||||
|
cr.execute('SELECT digits FROM decimal_precision WHERE name like %s',('Account',))
|
||||||
|
digits = cr.fetchone()
|
||||||
|
if digits and len(digits):
|
||||||
|
digits = digits[0]
|
||||||
|
main_currency = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id
|
||||||
|
for currency_id in ids:
|
||||||
|
if currency_id == main_currency.id:
|
||||||
|
if main_currency.rounding < 10 ** -digits:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
_constraints = [
|
||||||
|
(_check_main_currency_rounding, 'Error! You cannot define a rounding factor for the company\'s main currency that is smaller than the decimal precision of \'Account\'.', ['rounding']),
|
||||||
|
]
|
||||||
|
|
||||||
|
class decimal_precision(osv.osv):
|
||||||
|
_inherit = 'decimal.precision'
|
||||||
|
|
||||||
|
def _check_main_currency_rounding(self, cr, uid, ids, context=None):
|
||||||
|
cr.execute('SELECT id, digits FROM decimal_precision WHERE name like %s',('Account',))
|
||||||
|
res = cr.fetchone()
|
||||||
|
if res and len(res):
|
||||||
|
account_precision_id, digits = res
|
||||||
|
main_currency = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id
|
||||||
|
for decimal_precision in ids:
|
||||||
|
if decimal_precision == account_precision_id:
|
||||||
|
if main_currency.rounding < 10 ** -digits:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
_constraints = [
|
||||||
|
(_check_main_currency_rounding, 'Error! You cannot define the decimal precision of \'Account\' as greater than the rounding factor of the company\'s main currency', ['digits']),
|
||||||
|
]
|
||||||
|
|
||||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||||
|
|
|
@ -110,23 +110,25 @@
|
||||||
<field name="cost_method" groups="product.group_costing_method"/>
|
<field name="cost_method" groups="product.group_costing_method"/>
|
||||||
<field name="standard_price" attrs="{'readonly':[('cost_method','=','average')]}"/>
|
<field name="standard_price" attrs="{'readonly':[('cost_method','=','average')]}"/>
|
||||||
</group>
|
</group>
|
||||||
<group name="procurement_help" class="oe_grey" col="1">
|
<group name="procurement_help" class="oe_grey" col="1" groups="base.group_user">
|
||||||
<p attrs="{'invisible': [('type','<>','service'),('procure_method','<>','make_to_stock')]}">
|
<p attrs="{'invisible': [('type','<>','service'),('procure_method','<>','make_to_stock')]}">
|
||||||
When you sell this service, nothing special will be trigered
|
When you sell this service, nothing special will be trigered
|
||||||
to deliver the customer.
|
to deliver the customer, as you set the procurement method as
|
||||||
|
'Make to Stock'.
|
||||||
</p>
|
</p>
|
||||||
<p attrs="{'invisible': [('type','<>','product'),('procure_method','<>','make_to_stock')]}">
|
<p attrs="{'invisible': [('type','<>','product'),('procure_method','<>','make_to_stock')]}">
|
||||||
When you sell this product, OpenERP will <b>use the available inventory</b>
|
When you sell this product, OpenERP will <b>use the available
|
||||||
for the delivery order.
|
inventory</b> for the delivery order.
|
||||||
<br/>
|
<br/><br/>
|
||||||
If there are not enough quantities available, the delivery order
|
If there are not enough quantities available, the delivery order
|
||||||
will wait for new products. You should create others rules
|
will wait for new products. To fulfill the inventory, you should
|
||||||
(orderpoints, manual purchase orders) to fulfill the inventory.
|
create others rules like orderpoints.
|
||||||
</p>
|
</p>
|
||||||
<p attrs="{'invisible': [('type','<>','consu'),('procure_method','<>','make_to_stock')]}">
|
<p attrs="{'invisible': [('type','<>','consu'),('procure_method','<>','make_to_stock')]}">
|
||||||
When you sell this product, a delivery order will be created.
|
When you sell this product, a delivery order will be created.
|
||||||
OpenERP will consider that the <b>required quantities are always
|
OpenERP will consider that the <b>required quantities are always
|
||||||
available</b> as it's a consumable (the stock on hand may become negative).
|
available</b> as it's a consumable (as a result of this, the quantity
|
||||||
|
on hand may become negative).
|
||||||
</p>
|
</p>
|
||||||
</group>
|
</group>
|
||||||
<group groups="product.group_uom">
|
<group groups="product.group_uom">
|
||||||
|
|
|
@ -323,7 +323,7 @@ class project(osv.osv):
|
||||||
default.pop('alias_id', None)
|
default.pop('alias_id', None)
|
||||||
proj = self.browse(cr, uid, id, context=context)
|
proj = self.browse(cr, uid, id, context=context)
|
||||||
if not default.get('name', False):
|
if not default.get('name', False):
|
||||||
default['name'] = proj.name + _(' (copy)')
|
default.update(name=_("%s (copy)") % (proj.name))
|
||||||
res = super(project, self).copy(cr, uid, id, default, context)
|
res = super(project, self).copy(cr, uid, id, default, context)
|
||||||
self.map_tasks(cr,uid,id,res,context)
|
self.map_tasks(cr,uid,id,res,context)
|
||||||
return res
|
return res
|
||||||
|
@ -344,7 +344,7 @@ class project(osv.osv):
|
||||||
new_date_end = (datetime(*time.strptime(new_date_start,'%Y-%m-%d')[:3])+(end_date-start_date)).strftime('%Y-%m-%d')
|
new_date_end = (datetime(*time.strptime(new_date_start,'%Y-%m-%d')[:3])+(end_date-start_date)).strftime('%Y-%m-%d')
|
||||||
context.update({'copy':True})
|
context.update({'copy':True})
|
||||||
new_id = self.copy(cr, uid, proj.id, default = {
|
new_id = self.copy(cr, uid, proj.id, default = {
|
||||||
'name': proj.name +_(' (copy)'),
|
'name':_("%s (copy)") % (proj.name),
|
||||||
'state':'open',
|
'state':'open',
|
||||||
'date_start':new_date_start,
|
'date_start':new_date_start,
|
||||||
'date':new_date_end,
|
'date':new_date_end,
|
||||||
|
@ -694,7 +694,7 @@ class task(base_stage, osv.osv):
|
||||||
if not default.get('name', False):
|
if not default.get('name', False):
|
||||||
default['name'] = self.browse(cr, uid, id, context=context).name or ''
|
default['name'] = self.browse(cr, uid, id, context=context).name or ''
|
||||||
if not context.get('copy',False):
|
if not context.get('copy',False):
|
||||||
new_name = _("%s (copy)")%default.get('name','')
|
new_name = _("%s (copy)") % (default.get('name', ''))
|
||||||
default.update({'name':new_name})
|
default.update({'name':new_name})
|
||||||
return super(task, self).copy_data(cr, uid, id, default, context)
|
return super(task, self).copy_data(cr, uid, id, default, context)
|
||||||
|
|
||||||
|
|
|
@ -355,7 +355,7 @@ class project_issue(base_stage, osv.osv):
|
||||||
if not default:
|
if not default:
|
||||||
default = {}
|
default = {}
|
||||||
default = default.copy()
|
default = default.copy()
|
||||||
default['name'] = issue['name'] + _(' (copy)')
|
default.update(name=_('%s (copy)') % (issue['name']))
|
||||||
return super(project_issue, self).copy(cr, uid, id, default=default,
|
return super(project_issue, self).copy(cr, uid, id, default=default,
|
||||||
context=context)
|
context=context)
|
||||||
|
|
||||||
|
@ -534,7 +534,7 @@ class project(osv.osv):
|
||||||
|
|
||||||
def _get_alias_models(self, cr, uid, context=None):
|
def _get_alias_models(self, cr, uid, context=None):
|
||||||
return [('project.task', "Tasks"), ("project.issue", "Issues")]
|
return [('project.task', "Tasks"), ("project.issue", "Issues")]
|
||||||
|
|
||||||
def _issue_count(self, cr, uid, ids, field_name, arg, context=None):
|
def _issue_count(self, cr, uid, ids, field_name, arg, context=None):
|
||||||
res = dict.fromkeys(ids, 0)
|
res = dict.fromkeys(ids, 0)
|
||||||
issue_ids = self.pool.get('project.issue').search(cr, uid, [('project_id', 'in', ids)])
|
issue_ids = self.pool.get('project.issue').search(cr, uid, [('project_id', 'in', ids)])
|
||||||
|
@ -557,7 +557,7 @@ class project(osv.osv):
|
||||||
_constraints = [
|
_constraints = [
|
||||||
(_check_escalation, 'Error! You cannot assign escalation to the same project!', ['project_escalation_id'])
|
(_check_escalation, 'Error! You cannot assign escalation to the same project!', ['project_escalation_id'])
|
||||||
]
|
]
|
||||||
|
|
||||||
project()
|
project()
|
||||||
|
|
||||||
class account_analytic_account(osv.osv):
|
class account_analytic_account(osv.osv):
|
||||||
|
|
|
@ -138,7 +138,7 @@ class project_phase(osv.osv):
|
||||||
if default is None:
|
if default is None:
|
||||||
default = {}
|
default = {}
|
||||||
if not default.get('name', False):
|
if not default.get('name', False):
|
||||||
default['name'] = self.browse(cr, uid, id, context=context).name + _(' (copy)')
|
default.update(name=_('%s (copy)') % (self.browse(cr, uid, id, context=context).name))
|
||||||
return super(project_phase, self).copy(cr, uid, id, default, context)
|
return super(project_phase, self).copy(cr, uid, id, default, context)
|
||||||
|
|
||||||
def set_draft(self, cr, uid, ids, *args):
|
def set_draft(self, cr, uid, ids, *args):
|
||||||
|
@ -227,7 +227,7 @@ class project(osv.osv):
|
||||||
'phase_ids': fields.one2many('project.phase', 'project_id', "Project Phases"),
|
'phase_ids': fields.one2many('project.phase', 'project_id', "Project Phases"),
|
||||||
'phase_count': fields.function(_phase_count, type='integer', string="Open Phases"),
|
'phase_count': fields.function(_phase_count, type='integer', string="Open Phases"),
|
||||||
}
|
}
|
||||||
|
|
||||||
def schedule_phases(self, cr, uid, ids, context=None):
|
def schedule_phases(self, cr, uid, ids, context=None):
|
||||||
context = context or {}
|
context = context or {}
|
||||||
if type(ids) in (long, int,):
|
if type(ids) in (long, int,):
|
||||||
|
@ -250,7 +250,7 @@ class project(osv.osv):
|
||||||
# Maybe it's better to update than unlink/create if it already exists ?
|
# Maybe it's better to update than unlink/create if it already exists ?
|
||||||
p = getattr(project_gantt, 'Phase_%d' % (phase.id,))
|
p = getattr(project_gantt, 'Phase_%d' % (phase.id,))
|
||||||
|
|
||||||
self.pool.get('project.user.allocation').unlink(cr, uid,
|
self.pool.get('project.user.allocation').unlink(cr, uid,
|
||||||
[x.id for x in phase.user_ids],
|
[x.id for x in phase.user_ids],
|
||||||
context=context
|
context=context
|
||||||
)
|
)
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
<field eval=""""Procurement Task"""" name="name"/>
|
<field eval=""""Procurement Task"""" name="name"/>
|
||||||
<field eval=""""if product type is 'service' then it creates the task."""" name="note"/>
|
<field eval=""""if product type is 'service' then it creates the task."""" name="note"/>
|
||||||
<field model="process.node" name="target_node_id" ref="process_node_procuretasktask0"/>
|
<field model="process.node" name="target_node_id" ref="process_node_procuretasktask0"/>
|
||||||
<field model="process.node" name="source_node_id" ref="sale.process_node_saleprocurement0"/>
|
<field model="process.node" name="source_node_id" ref="sale_stock.process_node_saleprocurement0"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="process_transition_createtask0" model="process.transition">
|
<record id="process_transition_createtask0" model="process.transition">
|
||||||
|
|
|
@ -45,24 +45,24 @@ class resource_calendar(osv.osv):
|
||||||
def working_hours_on_day(self, cr, uid, resource_calendar_id, day, context=None):
|
def working_hours_on_day(self, cr, uid, resource_calendar_id, day, context=None):
|
||||||
"""Calculates the Working Total Hours based on Resource Calendar and
|
"""Calculates the Working Total Hours based on Resource Calendar and
|
||||||
given working day (datetime object).
|
given working day (datetime object).
|
||||||
|
|
||||||
@param resource_calendar_id: resource.calendar browse record
|
@param resource_calendar_id: resource.calendar browse record
|
||||||
@param day: datetime object
|
@param day: datetime object
|
||||||
|
|
||||||
@return: returns the working hours (as float) men should work on the given day if is in the attendance_ids of the resource_calendar_id (i.e if that day is a working day), returns 0.0 otherwise
|
@return: returns the working hours (as float) men should work on the given day if is in the attendance_ids of the resource_calendar_id (i.e if that day is a working day), returns 0.0 otherwise
|
||||||
"""
|
"""
|
||||||
res = 0.0
|
res = 0.0
|
||||||
for working_day in resource_calendar_id.attendance_ids:
|
for working_day in resource_calendar_id.attendance_ids:
|
||||||
if (int(working_day.dayofweek) + 1) == day.isoweekday():
|
if (int(working_day.dayofweek) + 1) == day.isoweekday():
|
||||||
res += working_day.hour_to - working_day.hour_from
|
res += working_day.hour_to - working_day.hour_from
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def _get_leaves(self, cr, uid, id, resource):
|
def _get_leaves(self, cr, uid, id, resource):
|
||||||
"""Private Method to Calculate resource Leaves days
|
"""Private Method to Calculate resource Leaves days
|
||||||
|
|
||||||
@param id: resource calendar id
|
@param id: resource calendar id
|
||||||
@param resource: resource id for which leaves will ew calculated
|
@param resource: resource id for which leaves will ew calculated
|
||||||
|
|
||||||
@return : returns the list of dates, where resource on leave in
|
@return : returns the list of dates, where resource on leave in
|
||||||
resource.calendar.leaves object (e.g.['%Y-%m-%d', '%Y-%m-%d'])
|
resource.calendar.leaves object (e.g.['%Y-%m-%d', '%Y-%m-%d'])
|
||||||
"""
|
"""
|
||||||
|
@ -85,9 +85,9 @@ class resource_calendar(osv.osv):
|
||||||
"""
|
"""
|
||||||
Calculates the working Schedule from supplied from date to till hours
|
Calculates the working Schedule from supplied from date to till hours
|
||||||
will be satisfied based or resource calendar id. If resource is also
|
will be satisfied based or resource calendar id. If resource is also
|
||||||
given then it will consider the resource leave also and than will
|
given then it will consider the resource leave also and than will
|
||||||
calculates resource working schedule
|
calculates resource working schedule
|
||||||
|
|
||||||
@param dt_from: datetime object, start of working scheduled
|
@param dt_from: datetime object, start of working scheduled
|
||||||
@param hours: float, total number working hours needed scheduled from
|
@param hours: float, total number working hours needed scheduled from
|
||||||
start date
|
start date
|
||||||
|
@ -187,29 +187,29 @@ class resource_calendar(osv.osv):
|
||||||
|
|
||||||
def interval_get(self, cr, uid, id, dt_from, hours, resource=False, byday=True):
|
def interval_get(self, cr, uid, id, dt_from, hours, resource=False, byday=True):
|
||||||
"""Calculates Resource Working Internal Timing Based on Resource Calendar.
|
"""Calculates Resource Working Internal Timing Based on Resource Calendar.
|
||||||
|
|
||||||
@param dt_from: start resource schedule calculation.
|
@param dt_from: start resource schedule calculation.
|
||||||
@param hours : total number of working hours to be scheduled.
|
@param hours : total number of working hours to be scheduled.
|
||||||
@param resource: optional resource id, If supplied it will take care of
|
@param resource: optional resource id, If supplied it will take care of
|
||||||
resource leave while scheduling.
|
resource leave while scheduling.
|
||||||
@param byday: boolean flag bit enforce day wise scheduling
|
@param byday: boolean flag bit enforce day wise scheduling
|
||||||
|
|
||||||
@return : list of scheduled working timing based on resource calendar.
|
@return : list of scheduled working timing based on resource calendar.
|
||||||
"""
|
"""
|
||||||
res = self.interval_get_multi(cr, uid, [(dt_from.strftime('%Y-%m-%d %H:%M:%S'), hours, id)], resource, byday)[(dt_from.strftime('%Y-%m-%d %H:%M:%S'), hours, id)]
|
res = self.interval_get_multi(cr, uid, [(dt_from.strftime('%Y-%m-%d %H:%M:%S'), hours, id)], resource, byday)[(dt_from.strftime('%Y-%m-%d %H:%M:%S'), hours, id)]
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def interval_hours_get(self, cr, uid, id, dt_from, dt_to, resource=False):
|
def interval_hours_get(self, cr, uid, id, dt_from, dt_to, resource=False):
|
||||||
""" Calculates the Total Working hours based on given start_date to
|
""" Calculates the Total Working hours based on given start_date to
|
||||||
end_date, If resource id is supplied that it will consider the source
|
end_date, If resource id is supplied that it will consider the source
|
||||||
leaves also in calculating the hours.
|
leaves also in calculating the hours.
|
||||||
|
|
||||||
@param dt_from : date start to calculate hours
|
@param dt_from : date start to calculate hours
|
||||||
@param dt_end : date end to calculate hours
|
@param dt_end : date end to calculate hours
|
||||||
@param resource: optional resource id, If given resource leave will be
|
@param resource: optional resource id, If given resource leave will be
|
||||||
considered.
|
considered.
|
||||||
|
|
||||||
@return : Total number of working hours based dt_from and dt_end and
|
@return : Total number of working hours based dt_from and dt_end and
|
||||||
resource if supplied.
|
resource if supplied.
|
||||||
"""
|
"""
|
||||||
if not id:
|
if not id:
|
||||||
|
@ -257,7 +257,7 @@ resource_calendar()
|
||||||
class resource_calendar_attendance(osv.osv):
|
class resource_calendar_attendance(osv.osv):
|
||||||
_name = "resource.calendar.attendance"
|
_name = "resource.calendar.attendance"
|
||||||
_description = "Work Detail"
|
_description = "Work Detail"
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
'name' : fields.char("Name", size=64, required=True),
|
'name' : fields.char("Name", size=64, required=True),
|
||||||
'dayofweek': fields.selection([('0','Monday'),('1','Tuesday'),('2','Wednesday'),('3','Thursday'),('4','Friday'),('5','Saturday'),('6','Sunday')], 'Day of Week', required=True, select=True),
|
'dayofweek': fields.selection([('0','Monday'),('1','Tuesday'),('2','Wednesday'),('3','Thursday'),('4','Friday'),('5','Saturday'),('6','Sunday')], 'Day of Week', required=True, select=True),
|
||||||
|
@ -266,9 +266,9 @@ class resource_calendar_attendance(osv.osv):
|
||||||
'hour_to' : fields.float("Work to", required=True),
|
'hour_to' : fields.float("Work to", required=True),
|
||||||
'calendar_id' : fields.many2one("resource.calendar", "Resource's Calendar", required=True),
|
'calendar_id' : fields.many2one("resource.calendar", "Resource's Calendar", required=True),
|
||||||
}
|
}
|
||||||
|
|
||||||
_order = 'dayofweek, hour_from'
|
_order = 'dayofweek, hour_from'
|
||||||
|
|
||||||
_defaults = {
|
_defaults = {
|
||||||
'dayofweek' : '0'
|
'dayofweek' : '0'
|
||||||
}
|
}
|
||||||
|
@ -302,12 +302,12 @@ class resource_resource(osv.osv):
|
||||||
'company_id': lambda self, cr, uid, context: self.pool.get('res.company')._company_default_get(cr, uid, 'resource.resource', context=context)
|
'company_id': lambda self, cr, uid, context: self.pool.get('res.company')._company_default_get(cr, uid, 'resource.resource', context=context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def copy(self, cr, uid, id, default=None, context=None):
|
def copy(self, cr, uid, id, default=None, context=None):
|
||||||
if default is None:
|
if default is None:
|
||||||
default = {}
|
default = {}
|
||||||
if not default.get('name', False):
|
if not default.get('name', False):
|
||||||
default['name'] = self.browse(cr, uid, id, context=context).name + _(' (copy)')
|
default.update(name=_('%s (copy)') % (self.browse(cr, uid, id, context=context).name))
|
||||||
return super(resource_resource, self).copy(cr, uid, id, default, context)
|
return super(resource_resource, self).copy(cr, uid, id, default, context)
|
||||||
|
|
||||||
def generate_resources(self, cr, uid, user_ids, calendar_id, context=None):
|
def generate_resources(self, cr, uid, user_ids, calendar_id, context=None):
|
||||||
|
@ -368,7 +368,7 @@ class resource_resource(osv.osv):
|
||||||
"""
|
"""
|
||||||
if not calendar_id:
|
if not calendar_id:
|
||||||
# Calendar is not specified: working days: 24/7
|
# Calendar is not specified: working days: 24/7
|
||||||
return [('fri', '8:0-12:0','13:0-17:0'), ('thu', '8:0-12:0','13:0-17:0'), ('wed', '8:0-12:0','13:0-17:0'),
|
return [('fri', '8:0-12:0','13:0-17:0'), ('thu', '8:0-12:0','13:0-17:0'), ('wed', '8:0-12:0','13:0-17:0'),
|
||||||
('mon', '8:0-12:0','13:0-17:0'), ('tue', '8:0-12:0','13:0-17:0')]
|
('mon', '8:0-12:0','13:0-17:0'), ('tue', '8:0-12:0','13:0-17:0')]
|
||||||
resource_attendance_pool = self.pool.get('resource.calendar.attendance')
|
resource_attendance_pool = self.pool.get('resource.calendar.attendance')
|
||||||
time_range = "8:00-8:00"
|
time_range = "8:00-8:00"
|
||||||
|
|
|
@ -24,11 +24,9 @@
|
||||||
#----------------------------------------------------------
|
#----------------------------------------------------------
|
||||||
|
|
||||||
import sale
|
import sale
|
||||||
import stock
|
|
||||||
import res_partner
|
import res_partner
|
||||||
import wizard
|
import wizard
|
||||||
import report
|
import report
|
||||||
import company
|
|
||||||
import edi
|
import edi
|
||||||
import res_config
|
import res_config
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,10 @@ It handles the full sales workflow:
|
||||||
|
|
||||||
* **Quotation** -> **Sales order** -> **Invoice**
|
* **Quotation** -> **Sales order** -> **Invoice**
|
||||||
|
|
||||||
Preferences
|
Preferences (only with Warehouse Management installed)
|
||||||
-----------
|
-----------
|
||||||
|
If you also installed the Warehouse Management, you can deal with the following preferences:
|
||||||
|
|
||||||
* Shipping: Choice of delivery at once or partial delivery
|
* Shipping: Choice of delivery at once or partial delivery
|
||||||
* Invoicing: choose how invoices will be paid
|
* Invoicing: choose how invoices will be paid
|
||||||
* Incoterms: International Commercial terms
|
* Incoterms: International Commercial terms
|
||||||
|
@ -55,15 +57,14 @@ The Dashboard for the Sales Manager will include
|
||||||
""",
|
""",
|
||||||
'author': 'OpenERP SA',
|
'author': 'OpenERP SA',
|
||||||
'website': 'http://www.openerp.com',
|
'website': 'http://www.openerp.com',
|
||||||
'images': ['images/deliveries_to_invoice.jpeg','images/sale_dashboard.jpeg','images/Sale_order_line_to_invoice.jpeg','images/sale_order.jpeg','images/sales_analysis.jpeg'],
|
'images': ['images/sale_dashboard.jpeg','images/Sale_order_line_to_invoice.jpeg','images/sale_order.jpeg','images/sales_analysis.jpeg'],
|
||||||
'depends': ['stock', 'procurement', 'board', 'account_voucher'],
|
'depends': ['account_voucher'],
|
||||||
'data': [
|
'data': [
|
||||||
'wizard/sale_make_invoice_advance.xml',
|
'wizard/sale_make_invoice_advance.xml',
|
||||||
'wizard/sale_line_invoice.xml',
|
'wizard/sale_line_invoice.xml',
|
||||||
'wizard/sale_make_invoice.xml',
|
'wizard/sale_make_invoice.xml',
|
||||||
'security/sale_security.xml',
|
'security/sale_security.xml',
|
||||||
'security/ir.model.access.csv',
|
'security/ir.model.access.csv',
|
||||||
'company_view.xml',
|
|
||||||
'sale_workflow.xml',
|
'sale_workflow.xml',
|
||||||
'sale_sequence.xml',
|
'sale_sequence.xml',
|
||||||
'sale_report.xml',
|
'sale_report.xml',
|
||||||
|
@ -71,7 +72,6 @@ The Dashboard for the Sales Manager will include
|
||||||
'sale_view.xml',
|
'sale_view.xml',
|
||||||
'res_partner_view.xml',
|
'res_partner_view.xml',
|
||||||
'report/sale_report_view.xml',
|
'report/sale_report_view.xml',
|
||||||
'stock_view.xml',
|
|
||||||
'process/sale_process.xml',
|
'process/sale_process.xml',
|
||||||
'board_sale_view.xml',
|
'board_sale_view.xml',
|
||||||
'edi/sale_order_action_data.xml',
|
'edi/sale_order_action_data.xml',
|
||||||
|
@ -80,9 +80,7 @@ The Dashboard for the Sales Manager will include
|
||||||
'demo': ['sale_demo.xml'],
|
'demo': ['sale_demo.xml'],
|
||||||
'test': [
|
'test': [
|
||||||
'test/sale_order_demo.yml',
|
'test/sale_order_demo.yml',
|
||||||
'test/picking_order_policy.yml',
|
|
||||||
'test/manual_order_policy.yml',
|
'test/manual_order_policy.yml',
|
||||||
'test/prepaid_order_policy.yml',
|
|
||||||
'test/cancel_order.yml',
|
'test/cancel_order.yml',
|
||||||
'test/delete_order.yml',
|
'test/delete_order.yml',
|
||||||
'test/edi_sale_order.yml',
|
'test/edi_sale_order.yml',
|
||||||
|
|
|
@ -185,16 +185,9 @@ class sale_order(osv.osv, EDIMixin):
|
||||||
|
|
||||||
order_lines = edi_document['order_line']
|
order_lines = edi_document['order_line']
|
||||||
for order_line in order_lines:
|
for order_line in order_lines:
|
||||||
self._edi_requires_attributes(('date_planned', 'product_id', 'product_uom', 'product_qty', 'price_unit'), order_line)
|
self._edi_requires_attributes(( 'product_id', 'product_uom', 'product_qty', 'price_unit'), order_line)
|
||||||
order_line['product_uom_qty'] = order_line['product_qty']
|
order_line['product_uom_qty'] = order_line['product_qty']
|
||||||
del order_line['product_qty']
|
del order_line['product_qty']
|
||||||
date_planned = order_line.pop('date_planned')
|
|
||||||
delay = 0
|
|
||||||
if date_order and date_planned:
|
|
||||||
# no security_days buffer, this is the promised date given by supplier
|
|
||||||
delay = (datetime.strptime(date_planned, DEFAULT_SERVER_DATE_FORMAT) - \
|
|
||||||
datetime.strptime(date_order, DEFAULT_SERVER_DATE_FORMAT)).days
|
|
||||||
order_line['delay'] = delay
|
|
||||||
|
|
||||||
# discard web preview fields, if present
|
# discard web preview fields, if present
|
||||||
order_line.pop('price_subtotal', None)
|
order_line.pop('price_subtotal', None)
|
||||||
|
@ -216,11 +209,6 @@ class sale_order_line(osv.osv, EDIMixin):
|
||||||
edi_doc.update(product_uom=line.product_uos,
|
edi_doc.update(product_uom=line.product_uos,
|
||||||
product_qty=line.product_uos_qty)
|
product_qty=line.product_uos_qty)
|
||||||
|
|
||||||
# company.security_days is for internal use, so customer should only
|
|
||||||
# see the expected date_planned based on line.delay
|
|
||||||
date_planned = datetime.strptime(line.order_id.date_order, DEFAULT_SERVER_DATE_FORMAT) + \
|
|
||||||
relativedelta(days=line.delay or 0.0)
|
|
||||||
edi_doc['date_planned'] = date_planned.strftime(DEFAULT_SERVER_DATE_FORMAT)
|
|
||||||
edi_doc_list.append(edi_doc)
|
edi_doc_list.append(edi_doc)
|
||||||
return edi_doc_list
|
return edi_doc_list
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,6 @@
|
||||||
<?xml version="1.0" ?>
|
<?xml version="1.0" ?>
|
||||||
<openerp>
|
<openerp>
|
||||||
<data>
|
<data>
|
||||||
<!-- EDI Export + Send email Action -->
|
|
||||||
<record id="ir_actions_server_edi_sale" model="ir.actions.server">
|
|
||||||
<field name="code">if not object.partner_id.opt_out: object.edi_export_and_email(template_ext_id='sale.email_template_edi_sale', context=context)</field>
|
|
||||||
<field name="state">code</field>
|
|
||||||
<field name="type">ir.actions.server</field>
|
|
||||||
<field name="model_id" ref="sale.model_sale_order"/>
|
|
||||||
<field name="condition">True</field>
|
|
||||||
<field name="name">Auto-email confirmed sale orders</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!-- EDI related Email Templates menu -->
|
<!-- EDI related Email Templates menu -->
|
||||||
<record model="ir.actions.act_window" id="action_email_templates">
|
<record model="ir.actions.act_window" id="action_email_templates">
|
||||||
|
@ -25,14 +16,9 @@
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
|
|
||||||
<!-- Mail template and workflow bindings are done in a NOUPDATE block
|
<!-- Mail template is done in a NOUPDATE block
|
||||||
so users can freely customize/delete them -->
|
so users can freely customize/delete them -->
|
||||||
<data noupdate="1">
|
<data noupdate="1">
|
||||||
<!-- bind the mailing server action to sale.order confirmed activity -->
|
|
||||||
<record id="sale.act_wait_ship" model="workflow.activity">
|
|
||||||
<field name="action_id" ref="ir_actions_server_edi_sale"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
|
|
||||||
<!--Email template -->
|
<!--Email template -->
|
||||||
<record id="email_template_edi_sale" model="email.template">
|
<record id="email_template_edi_sale" model="email.template">
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -28,18 +28,6 @@
|
||||||
<field eval="1" name="flow_start"/>
|
<field eval="1" name="flow_start"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="process_node_saleorderprocurement0" model="process.node">
|
|
||||||
<field name="menu_id" ref="sale.menu_sale_order"/>
|
|
||||||
<field name="model_id" ref="sale.model_sale_order"/>
|
|
||||||
<field eval=""""subflow"""" name="kind"/>
|
|
||||||
<field eval=""""Sales Order Requisition"""" name="name"/>
|
|
||||||
<field eval=""""Drives procurement orders for every sales order line."""" name="note"/>
|
|
||||||
<field name="subflow_id" ref="process_process_salesprocess0"/>
|
|
||||||
<field name="process_id" ref="procurement.process_process_procurementprocess0"/>
|
|
||||||
<field eval=""""object.state in ('draft', 'waiting_date', 'manual', 'progress', 'shipping_except', 'invoice_except', 'done', 'cancel')"""" name="model_states"/>
|
|
||||||
<field eval="1" name="flow_start"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="process_node_quotation0" model="process.node">
|
<record id="process_node_quotation0" model="process.node">
|
||||||
<field name="menu_id" ref="sale.menu_sale_order"/>
|
<field name="menu_id" ref="sale.menu_sale_order"/>
|
||||||
<field name="model_id" ref="sale.model_sale_order"/>
|
<field name="model_id" ref="sale.model_sale_order"/>
|
||||||
|
@ -62,38 +50,6 @@
|
||||||
<field eval="0" name="flow_start"/>
|
<field eval="0" name="flow_start"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="process_node_saleprocurement0" model="process.node">
|
|
||||||
<field name="menu_id" ref="procurement.menu_stock_procurement_action"/>
|
|
||||||
<field name="model_id" ref="procurement.model_procurement_order"/>
|
|
||||||
<field eval=""""subflow"""" name="kind"/>
|
|
||||||
<field eval=""""Procurement Order"""" name="name"/>
|
|
||||||
<field eval=""""One Procurement order for each sales order line and for each of the components."""" name="note"/>
|
|
||||||
<field name="subflow_id" ref="procurement.process_process_procurementprocess0"/>
|
|
||||||
<field name="process_id" ref="process_process_salesprocess0"/>
|
|
||||||
<field eval=""""object.state=='confirmed'"""" name="model_states"/>
|
|
||||||
<field eval="1" name="flow_start"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="process_node_packinglist0" model="process.node">
|
|
||||||
<field name="model_id" ref="stock.model_stock_picking"/>
|
|
||||||
<field eval=""""state"""" name="kind"/>
|
|
||||||
<field eval=""""Pick List"""" name="name"/>
|
|
||||||
<field eval=""""Document of the move to the output or to the customer."""" name="note"/>
|
|
||||||
<field name="process_id" ref="process_process_salesprocess0"/>
|
|
||||||
<field eval=""""object.state in ('assigned', 'confirmed')"""" name="model_states"/>
|
|
||||||
<field eval="0" name="flow_start"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="process_node_deliveryorder0" model="process.node">
|
|
||||||
<field name="model_id" ref="stock.model_stock_picking"/>
|
|
||||||
<field eval=""""state"""" name="kind"/>
|
|
||||||
<field eval=""""Delivery Order"""" name="name"/>
|
|
||||||
<field eval=""""Document of the move to the customer."""" name="note"/>
|
|
||||||
<field name="process_id" ref="process_process_salesprocess0"/>
|
|
||||||
<field eval=""""object.state in ('done', 'assigned')"""" name="model_states"/>
|
|
||||||
<field eval="0" name="flow_start"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="process_node_invoice0" model="process.node">
|
<record id="process_node_invoice0" model="process.node">
|
||||||
<field name="menu_id" ref="account.menu_action_invoice_tree1"/>
|
<field name="menu_id" ref="account.menu_action_invoice_tree1"/>
|
||||||
<field name="model_id" ref="account.model_account_invoice"/>
|
<field name="model_id" ref="account.model_account_invoice"/>
|
||||||
|
@ -106,29 +62,6 @@
|
||||||
<field eval="0" name="flow_start"/>
|
<field eval="0" name="flow_start"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="process_node_invoiceafterdelivery0" model="process.node">
|
|
||||||
<field name="menu_id" ref="account.menu_action_invoice_tree1"/>
|
|
||||||
<field name="model_id" ref="account.model_account_invoice"/>
|
|
||||||
<field eval=""""subflow"""" name="kind"/>
|
|
||||||
<field eval=""""Invoice"""" name="name"/>
|
|
||||||
<field eval=""""Based on the shipped or on the ordered quantities."""" name="note"/>
|
|
||||||
<field name="process_id" ref="process_process_salesprocess0"/>
|
|
||||||
<field name="subflow_id" ref="account.process_process_invoiceprocess0"/>
|
|
||||||
<field eval=""""object.state=='draft'"""" name="model_states"/>
|
|
||||||
<field eval="0" name="flow_start"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Process Condition
|
|
||||||
-->
|
|
||||||
|
|
||||||
<record id="process_condition_conditionafterdelivery0" model="process.condition">
|
|
||||||
<field name="model_id" ref="sale.model_sale_order"/>
|
|
||||||
<field name="node_id" ref="process_node_invoiceafterdelivery0"/>
|
|
||||||
<field eval=""""object.order_policy=='postpaid'"""" name="model_states"/>
|
|
||||||
<field eval=""""condition_after_delivery"""" name="name"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Process Transition
|
Process Transition
|
||||||
-->
|
-->
|
||||||
|
@ -142,29 +75,6 @@
|
||||||
<field eval="[(6,0,[ref('sale.trans_draft_router')])]" name="transition_ids"/>
|
<field eval="[(6,0,[ref('sale.trans_draft_router')])]" name="transition_ids"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="process_transition_saleprocurement0" model="process.transition">
|
|
||||||
<field eval="[(6,0,[])]" name="transition_ids"/>
|
|
||||||
<field eval=""""Create Procurement Order"""" name="name"/>
|
|
||||||
<field eval=""""A procurement order is automatically created as soon as a sales order is confirmed or as the invoice is paid. It drives the purchasing and the production of products regarding to the rules and to the sales order's parameters. """" name="note"/>
|
|
||||||
<field model="process.node" name="target_node_id" ref="process_node_saleprocurement0"/>
|
|
||||||
<field model="process.node" name="source_node_id" ref="process_node_saleorder0"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="process_transition_packing0" model="process.transition">
|
|
||||||
<field eval="[(6,0,[])]" name="transition_ids"/>
|
|
||||||
<field eval=""""Create Pick List"""" name="name"/>
|
|
||||||
<field eval=""""The Pick List form is created as soon as the sales order is confirmed, in the same time as the procurement order. It represents the assignment of parts to the sales order. There is 1 pick list by sales order line which evolves with the availability of parts."""" name="note"/>
|
|
||||||
<field model="process.node" name="target_node_id" ref="process_node_packinglist0"/>
|
|
||||||
<field model="process.node" name="source_node_id" ref="process_node_saleprocurement0"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="process_transition_deliver0" model="process.transition">
|
|
||||||
<field eval="[(6,0,[])]" name="transition_ids"/>
|
|
||||||
<field eval=""""Create Delivery Order"""" name="name"/>
|
|
||||||
<field eval=""""Depending on the configuration of the location Output, the move between the output area and the customer is done through the Delivery Order manually or automatically."""" name="note"/>
|
|
||||||
<field model="process.node" name="target_node_id" ref="process_node_deliveryorder0"/>
|
|
||||||
<field model="process.node" name="source_node_id" ref="process_node_packinglist0"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="process_transition_invoice0" model="process.transition">
|
<record id="process_transition_invoice0" model="process.transition">
|
||||||
<field eval="[(6,0,[])]" name="transition_ids"/>
|
<field eval="[(6,0,[])]" name="transition_ids"/>
|
||||||
|
@ -175,21 +85,6 @@
|
||||||
<field eval="[(6,0,[ref('sale.trans_wait_invoice_invoice_manual')])]" name="transition_ids"/>
|
<field eval="[(6,0,[ref('sale.trans_wait_invoice_invoice_manual')])]" name="transition_ids"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="process_transition_invoiceafterdelivery0" model="process.transition">
|
|
||||||
<field eval="[(6,0,[])]" name="transition_ids"/>
|
|
||||||
<field eval=""""Create Invoice"""" name="name"/>
|
|
||||||
<field eval=""""The invoice is created automatically if the shipping policy is 'Invoice from pick' or 'Invoice on order after delivery'."""" name="note"/>
|
|
||||||
<field model="process.node" name="target_node_id" ref="process_node_invoiceafterdelivery0"/>
|
|
||||||
<field model="process.node" name="source_node_id" ref="process_node_packinglist0"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="process_transition_saleorderprocurement0" model="process.transition">
|
|
||||||
<field eval="[(6,0,[])]" name="transition_ids"/>
|
|
||||||
<field eval=""""Procurement of sold material"""" name="name"/>
|
|
||||||
<field eval=""""For every sales order line, a procurement order is created to supply the sold product."""" name="note"/>
|
|
||||||
<field model="process.node" name="target_node_id" ref="procurement.process_node_procureproducts0"/>
|
|
||||||
<field model="process.node" name="source_node_id" ref="process_node_saleorderprocurement0"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="process_transition_saleinvoice0" model="process.transition">
|
<record id="process_transition_saleinvoice0" model="process.transition">
|
||||||
<field eval="[(6,0,[])]" name="transition_ids"/>
|
<field eval="[(6,0,[])]" name="transition_ids"/>
|
||||||
|
@ -216,49 +111,7 @@
|
||||||
<field eval=""""Cancel"""" name="name"/>
|
<field eval=""""Cancel"""" name="name"/>
|
||||||
<field name="transition_id" ref="process_transition_confirmquotation0"/>
|
<field name="transition_id" ref="process_transition_confirmquotation0"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="process_transition_action_assign0" model="process.transition.action">
|
|
||||||
<field eval=""""action_assign"""" name="action"/>
|
|
||||||
<field eval=""""object"""" name="state"/>
|
|
||||||
<field eval=""""Assign"""" name="name"/>
|
|
||||||
<field name="transition_id" ref="process_transition_packing0"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="process_transition_action_forceassignation0" model="process.transition.action">
|
|
||||||
<field eval=""""force_assign"""" name="action"/>
|
|
||||||
<field eval=""""object"""" name="state"/>
|
|
||||||
<field eval=""""Force Assignation"""" name="name"/>
|
|
||||||
<field name="transition_id" ref="process_transition_packing0"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="process_transition_action_cancel1" model="process.transition.action">
|
|
||||||
<field eval=""""action_cancel"""" name="action"/>
|
|
||||||
<field eval=""""object"""" name="state"/>
|
|
||||||
<field eval=""""Cancel"""" name="name"/>
|
|
||||||
<field name="transition_id" ref="process_transition_packing0"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="process_transition_action_cancelassignation0" model="process.transition.action">
|
|
||||||
<field eval=""""cancel_assign"""" name="action"/>
|
|
||||||
<field eval=""""object"""" name="state"/>
|
|
||||||
<field eval=""""Cancel Assignation"""" name="name"/>
|
|
||||||
<field name="transition_id" ref="process_transition_deliver0"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="process_transition_action_validate0" model="process.transition.action">
|
|
||||||
<field eval=""""test_finished"""" name="action"/>
|
|
||||||
<field eval=""""object"""" name="state"/>
|
|
||||||
<field eval=""""Validate"""" name="name"/>
|
|
||||||
<field name="transition_id" ref="process_transition_deliver0"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="process_transition_action_cancel2" model="process.transition.action">
|
|
||||||
<field eval=""""action_cancel"""" name="action"/>
|
|
||||||
<field eval=""""object"""" name="state"/>
|
|
||||||
<field eval=""""Cancel"""" name="name"/>
|
|
||||||
<field name="transition_id" ref="process_transition_deliver0"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="process_transition_action_createinvoice0" model="process.transition.action">
|
<record id="process_transition_action_createinvoice0" model="process.transition.action">
|
||||||
<field eval=""""action_invoice_create"""" name="action"/>
|
<field eval=""""action_invoice_create"""" name="action"/>
|
||||||
<field eval=""""object"""" name="state"/>
|
<field eval=""""object"""" name="state"/>
|
||||||
|
|
|
@ -30,8 +30,6 @@ class sale_report(osv.osv):
|
||||||
_columns = {
|
_columns = {
|
||||||
'date': fields.date('Date Order', readonly=True),
|
'date': fields.date('Date Order', readonly=True),
|
||||||
'date_confirm': fields.date('Date Confirm', readonly=True),
|
'date_confirm': fields.date('Date Confirm', readonly=True),
|
||||||
'shipped': fields.boolean('Shipped', readonly=True),
|
|
||||||
'shipped_qty_1': fields.integer('Shipped', readonly=True),
|
|
||||||
'year': fields.char('Year', size=4, readonly=True),
|
'year': fields.char('Year', size=4, readonly=True),
|
||||||
'month': fields.selection([('01', 'January'), ('02', 'February'), ('03', 'March'), ('04', 'April'),
|
'month': fields.selection([('01', 'January'), ('02', 'February'), ('03', 'March'), ('04', 'April'),
|
||||||
('05', 'May'), ('06', 'June'), ('07', 'July'), ('08', 'August'), ('09', 'September'),
|
('05', 'May'), ('06', 'June'), ('07', 'July'), ('08', 'August'), ('09', 'September'),
|
||||||
|
@ -54,7 +52,6 @@ class sale_report(osv.osv):
|
||||||
('waiting_date', 'Waiting Schedule'),
|
('waiting_date', 'Waiting Schedule'),
|
||||||
('manual', 'Manual In Progress'),
|
('manual', 'Manual In Progress'),
|
||||||
('progress', 'In Progress'),
|
('progress', 'In Progress'),
|
||||||
('shipping_except', 'Shipping Exception'),
|
|
||||||
('invoice_except', 'Invoice Exception'),
|
('invoice_except', 'Invoice Exception'),
|
||||||
('done', 'Done'),
|
('done', 'Done'),
|
||||||
('cancel', 'Cancelled')
|
('cancel', 'Cancelled')
|
||||||
|
@ -63,6 +60,7 @@ class sale_report(osv.osv):
|
||||||
'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account', readonly=True),
|
'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account', readonly=True),
|
||||||
}
|
}
|
||||||
_order = 'date desc'
|
_order = 'date desc'
|
||||||
|
|
||||||
def init(self, cr):
|
def init(self, cr):
|
||||||
tools.drop_view_if_exists(cr, 'sale_report')
|
tools.drop_view_if_exists(cr, 'sale_report')
|
||||||
cr.execute("""
|
cr.execute("""
|
||||||
|
@ -86,8 +84,6 @@ class sale_report(osv.osv):
|
||||||
extract(epoch from avg(date_trunc('day',s.date_confirm)-date_trunc('day',s.create_date)))/(24*60*60)::decimal(16,2) as delay,
|
extract(epoch from avg(date_trunc('day',s.date_confirm)-date_trunc('day',s.create_date)))/(24*60*60)::decimal(16,2) as delay,
|
||||||
s.state,
|
s.state,
|
||||||
t.categ_id as categ_id,
|
t.categ_id as categ_id,
|
||||||
s.shipped,
|
|
||||||
s.shipped::integer as shipped_qty_1,
|
|
||||||
s.pricelist_id as pricelist_id,
|
s.pricelist_id as pricelist_id,
|
||||||
s.project_id as analytic_account_id
|
s.project_id as analytic_account_id
|
||||||
from
|
from
|
||||||
|
@ -110,7 +106,6 @@ class sale_report(osv.osv):
|
||||||
s.shop_id,
|
s.shop_id,
|
||||||
s.company_id,
|
s.company_id,
|
||||||
s.state,
|
s.state,
|
||||||
s.shipped,
|
|
||||||
s.pricelist_id,
|
s.pricelist_id,
|
||||||
s.project_id
|
s.project_id
|
||||||
)
|
)
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
<field name="categ_id" invisible="1"/>
|
<field name="categ_id" invisible="1"/>
|
||||||
<field name="nbr" sum="# of Lines"/>
|
<field name="nbr" sum="# of Lines"/>
|
||||||
<field name="product_uom_qty" sum="# of Qty"/>
|
<field name="product_uom_qty" sum="# of Qty"/>
|
||||||
<field name="shipped_qty_1" sum="Shipped"/>
|
|
||||||
<field name="product_uom" invisible="not context.get('set_visible',False)"/>
|
<field name="product_uom" invisible="not context.get('set_visible',False)"/>
|
||||||
<field name="price_total" sum="Total Price"/>
|
<field name="price_total" sum="Total Price"/>
|
||||||
<field name="delay" sum="Commitment Delay"/>
|
<field name="delay" sum="Commitment Delay"/>
|
||||||
|
|
|
@ -27,17 +27,9 @@ class sale_configuration(osv.osv_memory):
|
||||||
_inherit = 'sale.config.settings'
|
_inherit = 'sale.config.settings'
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
'group_invoice_so_lines': fields.boolean('Generate invoices based on the sale order',
|
'group_invoice_so_lines': fields.boolean('Generate invoices based on the sale order lines',
|
||||||
implied_group='sale.group_invoice_so_lines',
|
implied_group='sale.group_invoice_so_lines',
|
||||||
help="To allow your salesman to make invoices for sale order lines using the menu 'Lines to Invoice'."),
|
help="To allow your salesman to make invoices for sale order lines using the menu 'Lines to Invoice'."),
|
||||||
'group_invoice_deli_orders': fields.boolean('Generate invoices after and based on delivery orders',
|
|
||||||
implied_group='sale.group_invoice_deli_orders',
|
|
||||||
help="To allow your salesman to make invoices for Delivery Orders using the menu 'Deliveries to Invoice'."),
|
|
||||||
'task_work': fields.boolean("Prepare invoices based on task's activities",
|
|
||||||
help="""Lets you transfer the entries under tasks defined for Project Management to
|
|
||||||
the Timesheet line entries for particular date and particular user with the effect of creating, editing and deleting either ways
|
|
||||||
and to automatically creates project tasks from procurement lines.
|
|
||||||
This installs the modules project_timesheet and project_mrp."""),
|
|
||||||
'timesheet': fields.boolean('Prepare invoices based on timesheets',
|
'timesheet': fields.boolean('Prepare invoices based on timesheets',
|
||||||
help = """For modifying account analytic view to show important data to project manager of services companies.
|
help = """For modifying account analytic view to show important data to project manager of services companies.
|
||||||
You can also view the report of account analytic summary user-wise as well as month wise.
|
You can also view the report of account analytic summary user-wise as well as month wise.
|
||||||
|
@ -48,17 +40,7 @@ class sale_configuration(osv.osv_memory):
|
||||||
(650€/day for a developer), the duration (one year support contract).
|
(650€/day for a developer), the duration (one year support contract).
|
||||||
You will be able to follow the progress of the contract and invoice automatically.
|
You will be able to follow the progress of the contract and invoice automatically.
|
||||||
It installs the account_analytic_analysis module."""),
|
It installs the account_analytic_analysis module."""),
|
||||||
'default_order_policy': fields.selection(
|
|
||||||
[('manual', 'Invoice based on sales orders'), ('picking', 'Invoice based on deliveries')],
|
|
||||||
'The default invoicing method is', default_model='sale.order',
|
|
||||||
help="You can generate invoices based on sales orders or based on shippings."),
|
|
||||||
'module_delivery': fields.boolean('Allow adding shipping costs',
|
|
||||||
help ="""Allows you to add delivery methods in sale orders and delivery orders.
|
|
||||||
You can define your own carrier and delivery grids for prices.
|
|
||||||
This installs the module delivery."""),
|
|
||||||
'time_unit': fields.many2one('product.uom', 'The default working time unit for services is'),
|
'time_unit': fields.many2one('product.uom', 'The default working time unit for services is'),
|
||||||
'default_picking_policy' : fields.boolean("Deliver all at once when all products are available.",
|
|
||||||
help = "Sales order by default will be configured to deliver all products at once instead of delivering each product when it is available. This may have an impact on the shipping price."),
|
|
||||||
'group_sale_pricelist':fields.boolean("Use pricelists to adapt your price per customers",
|
'group_sale_pricelist':fields.boolean("Use pricelists to adapt your price per customers",
|
||||||
implied_group='product.group_sale_pricelist',
|
implied_group='product.group_sale_pricelist',
|
||||||
help="""Allows to manage different prices based on rules per category of customers.
|
help="""Allows to manage different prices based on rules per category of customers.
|
||||||
|
@ -69,15 +51,9 @@ class sale_configuration(osv.osv_memory):
|
||||||
'group_sale_delivery_address': fields.boolean("Allow a different address for delivery and invoicing ",
|
'group_sale_delivery_address': fields.boolean("Allow a different address for delivery and invoicing ",
|
||||||
implied_group='sale.group_delivery_invoice_address',
|
implied_group='sale.group_delivery_invoice_address',
|
||||||
help="Allows you to specify different delivery and invoice addresses on a sale order."),
|
help="Allows you to specify different delivery and invoice addresses on a sale order."),
|
||||||
'group_mrp_properties': fields.boolean('Product properties on order lines',
|
|
||||||
implied_group='sale.group_mrp_properties',
|
|
||||||
help="Allows you to tag sale order lines with properties."),
|
|
||||||
'group_discount_per_so_line': fields.boolean("Allow setting a discount on the sale order lines",
|
'group_discount_per_so_line': fields.boolean("Allow setting a discount on the sale order lines",
|
||||||
implied_group='sale.group_discount_per_so_line',
|
implied_group='sale.group_discount_per_so_line',
|
||||||
help="Allows you to apply some discount per sale order line."),
|
help="Allows you to apply some discount per sale order line."),
|
||||||
'group_multiple_shops': fields.boolean("Manage multiple shops",
|
|
||||||
implied_group='stock.group_locations',
|
|
||||||
help="This allows to configure and use multiple shops."),
|
|
||||||
'module_warning': fields.boolean("Allow configuring alerts by customer or products",
|
'module_warning': fields.boolean("Allow configuring alerts by customer or products",
|
||||||
help="""Allow to configure warnings on products and trigger them when a user wants to sale a given product or a given customer.
|
help="""Allow to configure warnings on products and trigger them when a user wants to sale a given product or a given customer.
|
||||||
Example: Product: this product is deprecated, do not purchase more than 5.
|
Example: Product: this product is deprecated, do not purchase more than 5.
|
||||||
|
@ -95,16 +71,15 @@ class sale_configuration(osv.osv_memory):
|
||||||
This is mostly used when a user encodes his timesheet. The values are retrieved and the fields are auto-filled.
|
This is mostly used when a user encodes his timesheet. The values are retrieved and the fields are auto-filled.
|
||||||
But the possibility to change these values is still available.
|
But the possibility to change these values is still available.
|
||||||
This installs the module analytic_user_function."""),
|
This installs the module analytic_user_function."""),
|
||||||
'module_project_timesheet': fields.boolean("Project Timesheet"),
|
|
||||||
'module_project_mrp': fields.boolean("Project MRP"),
|
|
||||||
'module_project': fields.boolean("Project"),
|
'module_project': fields.boolean("Project"),
|
||||||
|
'module_sale_stock': fields.boolean("Sale and Warehouse Management",
|
||||||
|
help="""Allows you to Make Quotation, Sale Order using different Order policy and Manage Related Stock.
|
||||||
|
This installs the module sale_stock."""),
|
||||||
}
|
}
|
||||||
|
|
||||||
def default_get(self, cr, uid, fields, context=None):
|
def default_get(self, cr, uid, fields, context=None):
|
||||||
ir_model_data = self.pool.get('ir.model.data')
|
ir_model_data = self.pool.get('ir.model.data')
|
||||||
res = super(sale_configuration, self).default_get(cr, uid, fields, context)
|
res = super(sale_configuration, self).default_get(cr, uid, fields, context)
|
||||||
# task_work, time_unit depend on other fields
|
|
||||||
res['task_work'] = res.get('module_project_mrp') and res.get('module_project_timesheet')
|
|
||||||
if res.get('module_project'):
|
if res.get('module_project'):
|
||||||
user = self.pool.get('res.users').browse(cr, uid, uid, context)
|
user = self.pool.get('res.users').browse(cr, uid, uid, context)
|
||||||
res['time_unit'] = user.company_id.project_time_mode_id.id
|
res['time_unit'] = user.company_id.project_time_mode_id.id
|
||||||
|
@ -113,31 +88,18 @@ class sale_configuration(osv.osv_memory):
|
||||||
res['time_unit'] = product.uom_id.id
|
res['time_unit'] = product.uom_id.id
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def get_default_sale_config(self, cr, uid, ids, context=None):
|
|
||||||
ir_values = self.pool.get('ir.values')
|
|
||||||
default_picking_policy = ir_values.get_default(cr, uid, 'sale.order', 'picking_policy')
|
|
||||||
return {
|
|
||||||
'default_picking_policy': default_picking_policy == 'one',
|
|
||||||
}
|
|
||||||
|
|
||||||
def _get_default_time_unit(self, cr, uid, context=None):
|
def _get_default_time_unit(self, cr, uid, context=None):
|
||||||
ids = self.pool.get('product.uom').search(cr, uid, [('name', '=', _('Hour'))], context=context)
|
ids = self.pool.get('product.uom').search(cr, uid, [('name', '=', _('Hour'))], context=context)
|
||||||
return ids and ids[0] or False
|
return ids and ids[0] or False
|
||||||
|
|
||||||
_defaults = {
|
_defaults = {
|
||||||
'default_order_policy': 'manual',
|
|
||||||
'time_unit': _get_default_time_unit,
|
'time_unit': _get_default_time_unit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def set_sale_defaults(self, cr, uid, ids, context=None):
|
def set_sale_defaults(self, cr, uid, ids, context=None):
|
||||||
ir_values = self.pool.get('ir.values')
|
|
||||||
ir_model_data = self.pool.get('ir.model.data')
|
ir_model_data = self.pool.get('ir.model.data')
|
||||||
wizard = self.browse(cr, uid, ids)[0]
|
wizard = self.browse(cr, uid, ids)[0]
|
||||||
|
|
||||||
default_picking_policy = 'one' if wizard.default_picking_policy else 'direct'
|
|
||||||
ir_values.set_default(cr, uid, 'sale.order', 'picking_policy', default_picking_policy)
|
|
||||||
|
|
||||||
if wizard.time_unit:
|
if wizard.time_unit:
|
||||||
product = ir_model_data.get_object(cr, uid, 'product', 'product_product_consultant')
|
product = ir_model_data.get_object(cr, uid, 'product', 'product_product_consultant')
|
||||||
product.write({'uom_id': wizard.time_unit.id, 'uom_po_id': wizard.time_unit.id})
|
product.write({'uom_id': wizard.time_unit.id, 'uom_po_id': wizard.time_unit.id})
|
||||||
|
@ -145,14 +107,7 @@ class sale_configuration(osv.osv_memory):
|
||||||
if wizard.module_project and wizard.time_unit:
|
if wizard.module_project and wizard.time_unit:
|
||||||
user = self.pool.get('res.users').browse(cr, uid, uid, context)
|
user = self.pool.get('res.users').browse(cr, uid, uid, context)
|
||||||
user.company_id.write({'project_time_mode_id': wizard.time_unit.id})
|
user.company_id.write({'project_time_mode_id': wizard.time_unit.id})
|
||||||
|
|
||||||
return {}
|
|
||||||
|
|
||||||
def onchange_invoice_methods(self, cr, uid, ids, group_invoice_so_lines, group_invoice_deli_orders, context=None):
|
|
||||||
if not group_invoice_deli_orders:
|
|
||||||
return {'value': {'default_order_policy': 'manual'}}
|
|
||||||
if not group_invoice_so_lines:
|
|
||||||
return {'value': {'default_order_policy': 'picking'}}
|
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
def onchange_task_work(self, cr, uid, ids, task_work, context=None):
|
def onchange_task_work(self, cr, uid, ids, task_work, context=None):
|
||||||
|
@ -167,8 +122,6 @@ class sale_configuration(osv.osv_memory):
|
||||||
'module_account_analytic_analysis': timesheet,
|
'module_account_analytic_analysis': timesheet,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class account_config_settings(osv.osv_memory):
|
class account_config_settings(osv.osv_memory):
|
||||||
_inherit = 'account.config.settings'
|
_inherit = 'account.config.settings'
|
||||||
_columns = {
|
_columns = {
|
||||||
|
|
|
@ -16,39 +16,21 @@
|
||||||
<field name="group_invoice_so_lines" on_change="onchange_invoice_methods(group_invoice_so_lines, group_invoice_deli_orders)" class="oe_inline"/>
|
<field name="group_invoice_so_lines" on_change="onchange_invoice_methods(group_invoice_so_lines, group_invoice_deli_orders)" class="oe_inline"/>
|
||||||
<label for="group_invoice_so_lines"/>
|
<label for="group_invoice_so_lines"/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div name="timesheet">
|
||||||
<field name="group_invoice_deli_orders" class="oe_inline" on_change="onchange_invoice_methods(group_invoice_so_lines, group_invoice_deli_orders)"/>
|
|
||||||
<label for="group_invoice_deli_orders"/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<field name="task_work" class="oe_inline" on_change="onchange_task_work(task_work)"/>
|
|
||||||
<label for="task_work"/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<field name="timesheet" class="oe_inline" on_change="onchange_timesheet(timesheet)"/>
|
<field name="timesheet" class="oe_inline" on_change="onchange_timesheet(timesheet)"/>
|
||||||
<label for="timesheet"/>
|
<label for="timesheet"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group name='default_options'>
|
||||||
<label for="id" string="Default Options" attrs="{'invisible':['|',('group_invoice_so_lines','=',False),('group_invoice_deli_orders','=',False),('group_invoice_so_lines','=',False), ('group_invoice_deli_orders','=',False),('task_work','=',False), ('module_account_analytic_analysis','=',False)]}"/>
|
<label for="id" string="Default Options" attrs="{'invisible':[('module_account_analytic_analysis','=',False)]}"/>
|
||||||
<div>
|
<div>
|
||||||
<div attrs="{'invisible':['|',('group_invoice_so_lines','=',False),('group_invoice_deli_orders','=',False)],'required': ['|',('group_invoice_so_lines','=',True),('group_invoice_deli_orders','=',True)]}">
|
<div name='time_unit' attrs="{'invisible': [('module_account_analytic_analysis','=',False)],'required':[('module_account_analytic_analysis','=',True)]}">
|
||||||
<label for="default_order_policy"/>
|
|
||||||
<field name="default_order_policy" class="oe_inline"/>
|
|
||||||
</div>
|
|
||||||
<div attrs="{'invisible':[('group_invoice_so_lines','=',False), ('group_invoice_deli_orders','=',False)]}">
|
|
||||||
<field name="module_delivery" class="oe_inline"/>
|
|
||||||
<label for="module_delivery"/>
|
|
||||||
</div>
|
|
||||||
<div attrs="{'invisible': [('task_work','=',False), ('module_account_analytic_analysis','=',False)],'required': ['|', ('task_work','=',True), ('module_account_analytic_analysis','=',True)]}">
|
|
||||||
<label for="time_unit"/>
|
<label for="time_unit"/>
|
||||||
<field name="time_unit" domain="[('category_id.name','=','Working Time')]" class="oe_inline"/>
|
<field name="time_unit" domain="[('category_id.name','=','Working Time')]" class="oe_inline"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</group>
|
</group>
|
||||||
<field name="module_project_timesheet" invisible="1"/>
|
|
||||||
<field name="module_project_mrp" invisible="1"/>
|
|
||||||
</div>
|
</div>
|
||||||
<div name="Customer Features" position="inside">
|
<div name="Customer Features" position="inside">
|
||||||
<div>
|
<div>
|
||||||
|
@ -67,16 +49,12 @@
|
||||||
<group name="Sale" position="before">
|
<group name="Sale" position="before">
|
||||||
<group>
|
<group>
|
||||||
<label for="id" string="Warehouse Features"/>
|
<label for="id" string="Warehouse Features"/>
|
||||||
<div>
|
<div name="warehouse_features">
|
||||||
<div attrs="{'invisible':[('group_invoice_deli_orders','=',False)]}">
|
<div name='module_sale_stock'>
|
||||||
<field name="default_picking_policy" class="oe_inline"/>
|
<field name="module_sale_stock" class="oe_inline"/>
|
||||||
<label for="default_picking_policy"/>
|
<label for="module_sale_stock"/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div name='module_sale_journal'>
|
||||||
<field name="group_mrp_properties" class="oe_inline"/>
|
|
||||||
<label for="group_mrp_properties"/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<field name="module_sale_journal" class="oe_inline"/>
|
<field name="module_sale_journal" class="oe_inline"/>
|
||||||
<label for="module_sale_journal"/>
|
<label for="module_sale_journal"/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -99,10 +77,6 @@
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
<div name="Sale Features" position="inside">
|
<div name="Sale Features" position="inside">
|
||||||
<div>
|
|
||||||
<field name="group_multiple_shops" class="oe_inline"/>
|
|
||||||
<label for="group_multiple_shops"/>
|
|
||||||
</div>
|
|
||||||
<div name="module_sale_margin">
|
<div name="module_sale_margin">
|
||||||
<field name="module_sale_margin" class="oe_inline"/>
|
<field name="module_sale_margin" class="oe_inline"/>
|
||||||
<label for="module_sale_margin"/>
|
<label for="module_sale_margin"/>
|
||||||
|
|
|
@ -35,7 +35,6 @@ class sale_shop(osv.osv):
|
||||||
_columns = {
|
_columns = {
|
||||||
'name': fields.char('Shop Name', size=64, required=True),
|
'name': fields.char('Shop Name', size=64, required=True),
|
||||||
'payment_default_id': fields.many2one('account.payment.term', 'Default Payment Term', required=True),
|
'payment_default_id': fields.many2one('account.payment.term', 'Default Payment Term', required=True),
|
||||||
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse'),
|
|
||||||
'pricelist_id': fields.many2one('product.pricelist', 'Pricelist'),
|
'pricelist_id': fields.many2one('product.pricelist', 'Pricelist'),
|
||||||
'project_id': fields.many2one('account.analytic.account', 'Analytic Account', domain=[('parent_id', '!=', False)]),
|
'project_id': fields.many2one('account.analytic.account', 'Analytic Account', domain=[('parent_id', '!=', False)]),
|
||||||
'company_id': fields.many2one('res.company', 'Company', required=False),
|
'company_id': fields.many2one('res.company', 'Company', required=False),
|
||||||
|
@ -51,15 +50,12 @@ class sale_order(osv.osv):
|
||||||
_inherit = ['mail.thread', 'ir.needaction_mixin']
|
_inherit = ['mail.thread', 'ir.needaction_mixin']
|
||||||
_description = "Sales Order"
|
_description = "Sales Order"
|
||||||
|
|
||||||
|
|
||||||
def copy(self, cr, uid, id, default=None, context=None):
|
def copy(self, cr, uid, id, default=None, context=None):
|
||||||
if not default:
|
if not default:
|
||||||
default = {}
|
default = {}
|
||||||
default.update({
|
default.update({
|
||||||
'state': 'draft',
|
'state': 'draft',
|
||||||
'shipped': False,
|
|
||||||
'invoice_ids': [],
|
'invoice_ids': [],
|
||||||
'picking_ids': [],
|
|
||||||
'date_confirm': False,
|
'date_confirm': False,
|
||||||
'name': self.pool.get('ir.sequence').get(cr, uid, 'sale.order'),
|
'name': self.pool.get('ir.sequence').get(cr, uid, 'sale.order'),
|
||||||
})
|
})
|
||||||
|
@ -90,44 +86,6 @@ class sale_order(osv.osv):
|
||||||
res[order.id]['amount_total'] = res[order.id]['amount_untaxed'] + res[order.id]['amount_tax']
|
res[order.id]['amount_total'] = res[order.id]['amount_untaxed'] + res[order.id]['amount_tax']
|
||||||
return res
|
return res
|
||||||
|
|
||||||
# This is False
|
|
||||||
def _picked_rate(self, cr, uid, ids, name, arg, context=None):
|
|
||||||
if not ids:
|
|
||||||
return {}
|
|
||||||
res = {}
|
|
||||||
tmp = {}
|
|
||||||
for id in ids:
|
|
||||||
tmp[id] = {'picked': 0.0, 'total': 0.0}
|
|
||||||
cr.execute('''SELECT
|
|
||||||
p.sale_id as sale_order_id, sum(m.product_qty) as nbr, mp.state as procurement_state, m.state as move_state, p.type as picking_type
|
|
||||||
FROM
|
|
||||||
stock_move m
|
|
||||||
LEFT JOIN
|
|
||||||
stock_picking p on (p.id=m.picking_id)
|
|
||||||
LEFT JOIN
|
|
||||||
procurement_order mp on (mp.move_id=m.id)
|
|
||||||
WHERE
|
|
||||||
p.sale_id IN %s GROUP BY m.state, mp.state, p.sale_id, p.type''', (tuple(ids),))
|
|
||||||
|
|
||||||
for item in cr.dictfetchall():
|
|
||||||
if item['move_state'] == 'cancel':
|
|
||||||
continue
|
|
||||||
|
|
||||||
if item['picking_type'] == 'in':#this is a returned picking
|
|
||||||
tmp[item['sale_order_id']]['total'] -= item['nbr'] or 0.0 # Deducting the return picking qty
|
|
||||||
if item['procurement_state'] == 'done' or item['move_state'] == 'done':
|
|
||||||
tmp[item['sale_order_id']]['picked'] -= item['nbr'] or 0.0
|
|
||||||
else:
|
|
||||||
tmp[item['sale_order_id']]['total'] += item['nbr'] or 0.0
|
|
||||||
if item['procurement_state'] == 'done' or item['move_state'] == 'done':
|
|
||||||
tmp[item['sale_order_id']]['picked'] += item['nbr'] or 0.0
|
|
||||||
|
|
||||||
for order in self.browse(cr, uid, ids, context=context):
|
|
||||||
if order.shipped:
|
|
||||||
res[order.id] = 100.0
|
|
||||||
else:
|
|
||||||
res[order.id] = tmp[order.id]['total'] and (100.0 * tmp[order.id]['picked'] / tmp[order.id]['total']) or 0.0
|
|
||||||
return res
|
|
||||||
|
|
||||||
def _invoiced_rate(self, cursor, user, ids, name, arg, context=None):
|
def _invoiced_rate(self, cursor, user, ids, name, arg, context=None):
|
||||||
res = {}
|
res = {}
|
||||||
|
@ -217,10 +175,9 @@ class sale_order(osv.osv):
|
||||||
('waiting_date', 'Waiting Schedule'),
|
('waiting_date', 'Waiting Schedule'),
|
||||||
('progress', 'Sale Order'),
|
('progress', 'Sale Order'),
|
||||||
('manual', 'Sale to Invoice'),
|
('manual', 'Sale to Invoice'),
|
||||||
('shipping_except', 'Shipping Exception'),
|
|
||||||
('invoice_except', 'Invoice Exception'),
|
('invoice_except', 'Invoice Exception'),
|
||||||
('done', 'Done'),
|
('done', 'Done'),
|
||||||
], 'Status', readonly=True, help="Gives the state of the quotation or sales order. \nThe exception state is automatically set when a cancel operation occurs in the invoice validation (Invoice Exception) or in the picking list process (Shipping Exception). \nThe 'Waiting Schedule' state is set when the invoice is confirmed but waiting for the scheduler to run on the order date.", select=True),
|
], 'Status', readonly=True, help="Gives the state of the quotation or sales order. \nThe exception state is automatically set when a cancel operation occurs in the processing of a document linked to the sale order. \nThe 'Waiting Schedule' state is set when the invoice is confirmed but waiting for the scheduler to run on the order date.", select=True),
|
||||||
'date_order': fields.date('Date', required=True, readonly=True, select=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}),
|
'date_order': fields.date('Date', required=True, readonly=True, select=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}),
|
||||||
'create_date': fields.datetime('Creation Date', readonly=True, select=True, help="Date on which sales order is created."),
|
'create_date': fields.datetime('Creation Date', readonly=True, select=True, help="Date on which sales order is created."),
|
||||||
'date_confirm': fields.date('Confirmation Date', readonly=True, select=True, help="Date on which sales order is confirmed."),
|
'date_confirm': fields.date('Confirmation Date', readonly=True, select=True, help="Date on which sales order is confirmed."),
|
||||||
|
@ -228,28 +185,16 @@ class sale_order(osv.osv):
|
||||||
'partner_id': fields.many2one('res.partner', 'Customer', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, required=True, change_default=True, select=True),
|
'partner_id': fields.many2one('res.partner', 'Customer', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, required=True, change_default=True, select=True),
|
||||||
'partner_invoice_id': fields.many2one('res.partner', 'Invoice Address', readonly=True, required=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Invoice address for current sales order."),
|
'partner_invoice_id': fields.many2one('res.partner', 'Invoice Address', readonly=True, required=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Invoice address for current sales order."),
|
||||||
'partner_shipping_id': fields.many2one('res.partner', 'Shipping Address', readonly=True, required=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Shipping address for current sales order."),
|
'partner_shipping_id': fields.many2one('res.partner', 'Shipping Address', readonly=True, required=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Shipping address for current sales order."),
|
||||||
|
|
||||||
'incoterm': fields.many2one('stock.incoterms', 'Incoterm', help="Incoterm which stands for 'International Commercial terms' implies its a series of sales terms which are used in the commercial transaction."),
|
|
||||||
'picking_policy': fields.selection([('direct', 'Deliver each product when available'), ('one', 'Deliver all products at once')],
|
|
||||||
'Shipping Policy', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]},
|
|
||||||
help="""If you don't have enough stock available to deliver all at once, do you accept partial shipments or not?"""),
|
|
||||||
'order_policy': fields.selection([
|
'order_policy': fields.selection([
|
||||||
('manual', 'On Demand'),
|
('manual', 'On Demand'),
|
||||||
('picking', 'On Delivery Order'),
|
|
||||||
('prepaid', 'Before Delivery'),
|
|
||||||
], 'Create Invoice', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]},
|
], 'Create Invoice', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]},
|
||||||
help="""This field controls how invoice and delivery operations are synchronized.
|
help="""This field controls how invoice and delivery operations are synchronized.
|
||||||
- With 'On Demand', the invoice is created manually when needed.
|
|
||||||
- With 'On Delivery Order', a draft invoice is generated after all pickings have been processed.
|
|
||||||
- With 'Before Delivery', a draft invoice is created, and it must be paid before delivery."""),
|
- With 'Before Delivery', a draft invoice is created, and it must be paid before delivery."""),
|
||||||
'pricelist_id': fields.many2one('product.pricelist', 'Pricelist', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Pricelist for current sales order."),
|
'pricelist_id': fields.many2one('product.pricelist', 'Pricelist', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Pricelist for current sales order."),
|
||||||
'project_id': fields.many2one('account.analytic.account', 'Contract/Analytic Account', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="The analytic account related to a sales order."),
|
'project_id': fields.many2one('account.analytic.account', 'Contract/Analytic Account', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="The analytic account related to a sales order."),
|
||||||
|
|
||||||
'order_line': fields.one2many('sale.order.line', 'order_id', 'Order Lines', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}),
|
'order_line': fields.one2many('sale.order.line', 'order_id', 'Order Lines', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}),
|
||||||
'invoice_ids': fields.many2many('account.invoice', 'sale_order_invoice_rel', 'order_id', 'invoice_id', 'Invoices', readonly=True, help="This is the list of invoices that have been generated for this sales order. The same sales order may have been invoiced in several times (by line for example)."),
|
'invoice_ids': fields.many2many('account.invoice', 'sale_order_invoice_rel', 'order_id', 'invoice_id', 'Invoices', readonly=True, help="This is the list of invoices that have been generated for this sales order. The same sales order may have been invoiced in several times (by line for example)."),
|
||||||
'picking_ids': fields.one2many('stock.picking.out', 'sale_id', 'Related Picking', readonly=True, help="This is a list of delivery orders that has been generated for this sales order."),
|
|
||||||
'shipped': fields.boolean('Delivered', readonly=True, help="It indicates that the sales order has been delivered. This field is updated only after the scheduler(s) have been launched."),
|
|
||||||
'picked_rate': fields.function(_picked_rate, string='Picked', type='float'),
|
|
||||||
'invoiced_rate': fields.function(_invoiced_rate, string='Invoiced', type='float'),
|
'invoiced_rate': fields.function(_invoiced_rate, string='Invoiced', type='float'),
|
||||||
'invoiced': fields.function(_invoiced, string='Paid',
|
'invoiced': fields.function(_invoiced, string='Paid',
|
||||||
fnct_search=_invoiced_search, type='boolean', help="It indicates that an invoice has been paid."),
|
fnct_search=_invoiced_search, type='boolean', help="It indicates that an invoice has been paid."),
|
||||||
|
@ -276,13 +221,12 @@ class sale_order(osv.osv):
|
||||||
},
|
},
|
||||||
multi='sums', help="The total amount."),
|
multi='sums', help="The total amount."),
|
||||||
|
|
||||||
'invoice_quantity': fields.selection([('order', 'Ordered Quantities'), ('procurement', 'Shipped Quantities')], 'Invoice on', help="The sale order will automatically create the invoice proposition (draft invoice). Ordered and delivered quantities may not be the same. You have to choose if you want your invoice based on ordered or shipped quantities. If the product is a service, shipped quantities means hours spent on the associated tasks.", required=True, readonly=True, states={'draft': [('readonly', False)]}),
|
'invoice_quantity': fields.selection([('order', 'Ordered Quantities')], 'Invoice on', help="The sale order will automatically create the invoice proposition (draft invoice).", required=True, readonly=True, states={'draft': [('readonly', False)]}),
|
||||||
'payment_term': fields.many2one('account.payment.term', 'Payment Term'),
|
'payment_term': fields.many2one('account.payment.term', 'Payment Term'),
|
||||||
'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position'),
|
'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position'),
|
||||||
'company_id': fields.related('shop_id','company_id',type='many2one',relation='res.company',string='Company',store=True,readonly=True)
|
'company_id': fields.related('shop_id','company_id',type='many2one',relation='res.company',string='Company',store=True,readonly=True)
|
||||||
}
|
}
|
||||||
_defaults = {
|
_defaults = {
|
||||||
'picking_policy': 'direct',
|
|
||||||
'date_order': fields.date.context_today,
|
'date_order': fields.date.context_today,
|
||||||
'order_policy': 'manual',
|
'order_policy': 'manual',
|
||||||
'state': 'draft',
|
'state': 'draft',
|
||||||
|
@ -305,35 +249,10 @@ class sale_order(osv.osv):
|
||||||
if s['state'] in ['draft', 'cancel']:
|
if s['state'] in ['draft', 'cancel']:
|
||||||
unlink_ids.append(s['id'])
|
unlink_ids.append(s['id'])
|
||||||
else:
|
else:
|
||||||
raise osv.except_osv(_('Invalid Action!'), _('In order to delete a confirmed sales order, you must cancel it.\nTo do so, you must first cancel related picking for delivery orders.'))
|
raise osv.except_osv(_('Invalid Action!'), _('In order to delete a confirmed sale order, you must cancel it before !'))
|
||||||
|
|
||||||
return osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
|
return osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
|
||||||
|
|
||||||
def onchange_shop_id(self, cr, uid, ids, shop_id):
|
|
||||||
v = {}
|
|
||||||
if shop_id:
|
|
||||||
shop = self.pool.get('sale.shop').browse(cr, uid, shop_id)
|
|
||||||
v['project_id'] = shop.project_id.id
|
|
||||||
# Que faire si le client a une pricelist a lui ?
|
|
||||||
if shop.pricelist_id.id:
|
|
||||||
v['pricelist_id'] = shop.pricelist_id.id
|
|
||||||
return {'value': v}
|
|
||||||
|
|
||||||
def action_cancel_draft(self, cr, uid, ids, context=None):
|
|
||||||
if not len(ids):
|
|
||||||
return False
|
|
||||||
cr.execute('select id from sale_order_line where order_id IN %s and state=%s', (tuple(ids), 'cancel'))
|
|
||||||
line_ids = map(lambda x: x[0], cr.fetchall())
|
|
||||||
self.write(cr, uid, ids, {'state': 'draft', 'invoice_ids': [], 'shipped': 0})
|
|
||||||
self.pool.get('sale.order.line').write(cr, uid, line_ids, {'invoiced': False, 'state': 'draft', 'invoice_lines': [(6, 0, [])]})
|
|
||||||
wf_service = netsvc.LocalService("workflow")
|
|
||||||
for inv_id in ids:
|
|
||||||
# Deleting the existing instance of workflow for SO
|
|
||||||
wf_service.trg_delete(uid, 'sale.order', inv_id, cr)
|
|
||||||
wf_service.trg_create(uid, 'sale.order', inv_id, cr)
|
|
||||||
self.action_cancel_draft_send_note(cr, uid, ids, context=context)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def onchange_pricelist_id(self, cr, uid, ids, pricelist_id, order_lines, context={}):
|
def onchange_pricelist_id(self, cr, uid, ids, pricelist_id, order_lines, context={}):
|
||||||
if (not pricelist_id) or (not order_lines):
|
if (not pricelist_id) or (not order_lines):
|
||||||
return {}
|
return {}
|
||||||
|
@ -343,15 +262,6 @@ class sale_order(osv.osv):
|
||||||
}
|
}
|
||||||
return {'warning': warning}
|
return {'warning': warning}
|
||||||
|
|
||||||
def onchange_partner_order_id(self, cr, uid, ids, order_id, invoice_id=False, shipping_id=False, context={}):
|
|
||||||
if not order_id:
|
|
||||||
return {}
|
|
||||||
val = {}
|
|
||||||
if not invoice_id:
|
|
||||||
val['partner_invoice_id'] = order_id
|
|
||||||
if not shipping_id:
|
|
||||||
val['partner_shipping_id'] = order_id
|
|
||||||
return {'value': val}
|
|
||||||
|
|
||||||
def onchange_partner_id(self, cr, uid, ids, part):
|
def onchange_partner_id(self, cr, uid, ids, part):
|
||||||
if not part:
|
if not part:
|
||||||
|
@ -374,30 +284,7 @@ class sale_order(osv.osv):
|
||||||
val['pricelist_id'] = pricelist
|
val['pricelist_id'] = pricelist
|
||||||
return {'value': val}
|
return {'value': val}
|
||||||
|
|
||||||
def shipping_policy_change(self, cr, uid, ids, policy, context=None):
|
|
||||||
if not policy:
|
|
||||||
return {}
|
|
||||||
inv_qty = 'order'
|
|
||||||
if policy == 'prepaid':
|
|
||||||
inv_qty = 'order'
|
|
||||||
elif policy == 'picking':
|
|
||||||
inv_qty = 'procurement'
|
|
||||||
return {'value': {'invoice_quantity': inv_qty}}
|
|
||||||
|
|
||||||
def write(self, cr, uid, ids, vals, context=None):
|
|
||||||
if vals.get('order_policy', False):
|
|
||||||
if vals['order_policy'] == 'prepaid':
|
|
||||||
vals.update({'invoice_quantity': 'order'})
|
|
||||||
elif vals['order_policy'] == 'picking':
|
|
||||||
vals.update({'invoice_quantity': 'procurement'})
|
|
||||||
return super(sale_order, self).write(cr, uid, ids, vals, context=context)
|
|
||||||
|
|
||||||
def create(self, cr, uid, vals, context=None):
|
def create(self, cr, uid, vals, context=None):
|
||||||
if vals.get('order_policy', False):
|
|
||||||
if vals['order_policy'] == 'prepaid':
|
|
||||||
vals.update({'invoice_quantity': 'order'})
|
|
||||||
if vals['order_policy'] == 'picking':
|
|
||||||
vals.update({'invoice_quantity': 'procurement'})
|
|
||||||
order = super(sale_order, self).create(cr, uid, vals, context=context)
|
order = super(sale_order, self).create(cr, uid, vals, context=context)
|
||||||
if order:
|
if order:
|
||||||
self.create_send_note(cr, uid, [order], context=context)
|
self.create_send_note(cr, uid, [order], context=context)
|
||||||
|
@ -430,7 +317,6 @@ class sale_order(osv.osv):
|
||||||
if not journal_ids:
|
if not journal_ids:
|
||||||
raise osv.except_osv(_('Error!'),
|
raise osv.except_osv(_('Error!'),
|
||||||
_('Please define sales journal for this company: "%s" (id:%d).') % (order.company_id.name, order.company_id.id))
|
_('Please define sales journal for this company: "%s" (id:%d).') % (order.company_id.name, order.company_id.id))
|
||||||
|
|
||||||
invoice_vals = {
|
invoice_vals = {
|
||||||
'name': order.client_order_ref or '',
|
'name': order.client_order_ref or '',
|
||||||
'origin': order.name,
|
'origin': order.name,
|
||||||
|
@ -451,7 +337,6 @@ class sale_order(osv.osv):
|
||||||
|
|
||||||
# Care for deprecated _inv_get() hook - FIXME: to be removed after 6.1
|
# Care for deprecated _inv_get() hook - FIXME: to be removed after 6.1
|
||||||
invoice_vals.update(self._inv_get(cr, uid, order, context=context))
|
invoice_vals.update(self._inv_get(cr, uid, order, context=context))
|
||||||
|
|
||||||
return invoice_vals
|
return invoice_vals
|
||||||
|
|
||||||
def _make_invoice(self, cr, uid, order, lines, context=None):
|
def _make_invoice(self, cr, uid, order, lines, context=None):
|
||||||
|
@ -546,29 +431,6 @@ class sale_order(osv.osv):
|
||||||
result['res_id'] = inv_ids and inv_ids[0] or False
|
result['res_id'] = inv_ids and inv_ids[0] or False
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def action_view_delivery(self, cr, uid, ids, context=None):
|
|
||||||
'''
|
|
||||||
This function returns an action that display existing delivery orders of given sale order ids. It can either be a in a list or in a form view, if there is only one delivery order to show.
|
|
||||||
'''
|
|
||||||
mod_obj = self.pool.get('ir.model.data')
|
|
||||||
act_obj = self.pool.get('ir.actions.act_window')
|
|
||||||
|
|
||||||
result = mod_obj.get_object_reference(cr, uid, 'stock', 'action_picking_tree')
|
|
||||||
id = result and result[1] or False
|
|
||||||
result = act_obj.read(cr, uid, [id], context=context)[0]
|
|
||||||
#compute the number of delivery orders to display
|
|
||||||
pick_ids = []
|
|
||||||
for so in self.browse(cr, uid, ids, context=context):
|
|
||||||
pick_ids += [picking.id for picking in so.picking_ids]
|
|
||||||
#choose the view_mode accordingly
|
|
||||||
if len(pick_ids) > 1:
|
|
||||||
result['domain'] = "[('id','in',["+','.join(map(str, pick_ids))+"])]"
|
|
||||||
else:
|
|
||||||
res = mod_obj.get_object_reference(cr, uid, 'stock', 'view_picking_out_form')
|
|
||||||
result['views'] = [(res and res[1] or False, 'form')]
|
|
||||||
result['res_id'] = pick_ids and pick_ids[0] or False
|
|
||||||
return result
|
|
||||||
|
|
||||||
def test_no_product(self, cr, uid, order, context):
|
def test_no_product(self, cr, uid, order, context):
|
||||||
for line in order.order_line:
|
for line in order.order_line:
|
||||||
if line.product_id and (line.product_id.type<>'service'):
|
if line.product_id and (line.product_id.type<>'service'):
|
||||||
|
@ -579,7 +441,6 @@ class sale_order(osv.osv):
|
||||||
res = False
|
res = False
|
||||||
invoices = {}
|
invoices = {}
|
||||||
invoice_ids = []
|
invoice_ids = []
|
||||||
picking_obj = self.pool.get('stock.picking')
|
|
||||||
invoice = self.pool.get('account.invoice')
|
invoice = self.pool.get('account.invoice')
|
||||||
obj_sale_order_line = self.pool.get('sale.order.line')
|
obj_sale_order_line = self.pool.get('sale.order.line')
|
||||||
partner_currency = {}
|
partner_currency = {}
|
||||||
|
@ -618,8 +479,6 @@ class sale_order(osv.osv):
|
||||||
for o, l in val:
|
for o, l in val:
|
||||||
invoice_ref += o.name + '|'
|
invoice_ref += o.name + '|'
|
||||||
self.write(cr, uid, [o.id], {'state': 'progress'})
|
self.write(cr, uid, [o.id], {'state': 'progress'})
|
||||||
if o.order_policy == 'picking':
|
|
||||||
picking_obj.write(cr, uid, map(lambda x: x.id, o.picking_ids), {'invoice_state': 'invoiced'})
|
|
||||||
cr.execute('insert into sale_order_invoice_rel (order_id,invoice_id) values (%s,%s)', (o.id, res))
|
cr.execute('insert into sale_order_invoice_rel (order_id,invoice_id) values (%s,%s)', (o.id, res))
|
||||||
invoice.write(cr, uid, [res], {'origin': invoice_ref, 'name': invoice_ref})
|
invoice.write(cr, uid, [res], {'origin': invoice_ref, 'name': invoice_ref})
|
||||||
else:
|
else:
|
||||||
|
@ -627,8 +486,6 @@ class sale_order(osv.osv):
|
||||||
res = self._make_invoice(cr, uid, order, il, context=context)
|
res = self._make_invoice(cr, uid, order, il, context=context)
|
||||||
invoice_ids.append(res)
|
invoice_ids.append(res)
|
||||||
self.write(cr, uid, [order.id], {'state': 'progress'})
|
self.write(cr, uid, [order.id], {'state': 'progress'})
|
||||||
if order.order_policy == 'picking':
|
|
||||||
picking_obj.write(cr, uid, map(lambda x: x.id, order.picking_ids), {'invoice_state': 'invoiced'})
|
|
||||||
cr.execute('insert into sale_order_invoice_rel (order_id,invoice_id) values (%s,%s)', (order.id, res))
|
cr.execute('insert into sale_order_invoice_rel (order_id,invoice_id) values (%s,%s)', (order.id, res))
|
||||||
if res:
|
if res:
|
||||||
self.invoice_send_note(cr, uid, ids, res, context)
|
self.invoice_send_note(cr, uid, ids, res, context)
|
||||||
|
@ -683,6 +540,7 @@ class sale_order(osv.osv):
|
||||||
#
|
#
|
||||||
if order.state == 'invoice_except':
|
if order.state == 'invoice_except':
|
||||||
self.write(cr, uid, [order.id], {'state': 'progress'}, context=context)
|
self.write(cr, uid, [order.id], {'state': 'progress'}, context=context)
|
||||||
|
self.invoice_paid_send_note(cr, uid, [order.id], context=context)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def action_cancel(self, cr, uid, ids, context=None):
|
def action_cancel(self, cr, uid, ids, context=None):
|
||||||
|
@ -690,22 +548,7 @@ class sale_order(osv.osv):
|
||||||
if context is None:
|
if context is None:
|
||||||
context = {}
|
context = {}
|
||||||
sale_order_line_obj = self.pool.get('sale.order.line')
|
sale_order_line_obj = self.pool.get('sale.order.line')
|
||||||
proc_obj = self.pool.get('procurement.order')
|
|
||||||
for sale in self.browse(cr, uid, ids, context=context):
|
for sale in self.browse(cr, uid, ids, context=context):
|
||||||
for pick in sale.picking_ids:
|
|
||||||
if pick.state not in ('draft', 'cancel'):
|
|
||||||
raise osv.except_osv(
|
|
||||||
_('Cannot cancel sales order!'),
|
|
||||||
_('You must first cancel all delivery order(s) attached to this sales order.'))
|
|
||||||
if pick.state == 'cancel':
|
|
||||||
for mov in pick.move_lines:
|
|
||||||
proc_ids = proc_obj.search(cr, uid, [('move_id', '=', mov.id)])
|
|
||||||
if proc_ids:
|
|
||||||
for proc in proc_ids:
|
|
||||||
wf_service.trg_validate(uid, 'procurement.order', proc, 'button_check', cr)
|
|
||||||
for r in self.read(cr, uid, ids, ['picking_ids']):
|
|
||||||
for pick in r['picking_ids']:
|
|
||||||
wf_service.trg_validate(uid, 'stock.picking', pick, 'button_cancel', cr)
|
|
||||||
for inv in sale.invoice_ids:
|
for inv in sale.invoice_ids:
|
||||||
if inv.state not in ('draft', 'cancel'):
|
if inv.state not in ('draft', 'cancel'):
|
||||||
raise osv.except_osv(
|
raise osv.except_osv(
|
||||||
|
@ -745,8 +588,6 @@ class sale_order(osv.osv):
|
||||||
if not o.order_line:
|
if not o.order_line:
|
||||||
raise osv.except_osv(_('Error!'),_('You cannot confirm a sale order which has no line.'))
|
raise osv.except_osv(_('Error!'),_('You cannot confirm a sale order which has no line.'))
|
||||||
noprod = self.test_no_product(cr, uid, o, context)
|
noprod = self.test_no_product(cr, uid, o, context)
|
||||||
if noprod and o.order_policy=='picking':
|
|
||||||
self.write(cr, uid, [o.id], {'order_policy': 'manual'}, context=context)
|
|
||||||
if (o.order_policy == 'manual') or noprod:
|
if (o.order_policy == 'manual') or noprod:
|
||||||
self.write(cr, uid, [o.id], {'state': 'manual', 'date_confirm': fields.date.context_today(self, cr, uid, context=context)})
|
self.write(cr, uid, [o.id], {'state': 'manual', 'date_confirm': fields.date.context_today(self, cr, uid, context=context)})
|
||||||
else:
|
else:
|
||||||
|
@ -785,240 +626,9 @@ class sale_order(osv.osv):
|
||||||
'nodestroy': True,
|
'nodestroy': True,
|
||||||
}
|
}
|
||||||
|
|
||||||
def procurement_lines_get(self, cr, uid, ids, *args):
|
def action_done(self, cr, uid, ids, context=None):
|
||||||
res = []
|
self.done_send_note(cr, uid, ids, context=context)
|
||||||
for order in self.browse(cr, uid, ids, context={}):
|
return self.write(cr, uid, ids, {'state': 'done'}, context=context)
|
||||||
for line in order.order_line:
|
|
||||||
if line.procurement_id:
|
|
||||||
res.append(line.procurement_id.id)
|
|
||||||
return res
|
|
||||||
|
|
||||||
# if mode == 'finished':
|
|
||||||
# returns True if all lines are done, False otherwise
|
|
||||||
# if mode == 'canceled':
|
|
||||||
# returns True if there is at least one canceled line, False otherwise
|
|
||||||
def test_state(self, cr, uid, ids, mode, *args):
|
|
||||||
assert mode in ('finished', 'canceled'), _("invalid mode for test_state")
|
|
||||||
finished = True
|
|
||||||
canceled = False
|
|
||||||
notcanceled = False
|
|
||||||
write_done_ids = []
|
|
||||||
write_cancel_ids = []
|
|
||||||
for order in self.browse(cr, uid, ids, context={}):
|
|
||||||
for line in order.order_line:
|
|
||||||
if (not line.procurement_id) or (line.procurement_id.state=='done'):
|
|
||||||
if line.state != 'done':
|
|
||||||
write_done_ids.append(line.id)
|
|
||||||
else:
|
|
||||||
finished = False
|
|
||||||
if line.procurement_id:
|
|
||||||
if (line.procurement_id.state == 'cancel'):
|
|
||||||
canceled = True
|
|
||||||
if line.state != 'exception':
|
|
||||||
write_cancel_ids.append(line.id)
|
|
||||||
else:
|
|
||||||
notcanceled = True
|
|
||||||
if write_done_ids:
|
|
||||||
self.pool.get('sale.order.line').write(cr, uid, write_done_ids, {'state': 'done'})
|
|
||||||
if write_cancel_ids:
|
|
||||||
self.pool.get('sale.order.line').write(cr, uid, write_cancel_ids, {'state': 'exception'})
|
|
||||||
|
|
||||||
if mode == 'finished':
|
|
||||||
return finished
|
|
||||||
elif mode == 'canceled':
|
|
||||||
return canceled
|
|
||||||
if notcanceled:
|
|
||||||
return False
|
|
||||||
return canceled
|
|
||||||
|
|
||||||
def _prepare_order_line_procurement(self, cr, uid, order, line, move_id, date_planned, context=None):
|
|
||||||
return {
|
|
||||||
'name': line.name.split('\n')[0],
|
|
||||||
'origin': order.name,
|
|
||||||
'date_planned': date_planned,
|
|
||||||
'product_id': line.product_id.id,
|
|
||||||
'product_qty': line.product_uom_qty,
|
|
||||||
'product_uom': line.product_uom.id,
|
|
||||||
'product_uos_qty': (line.product_uos and line.product_uos_qty)\
|
|
||||||
or line.product_uom_qty,
|
|
||||||
'product_uos': (line.product_uos and line.product_uos.id)\
|
|
||||||
or line.product_uom.id,
|
|
||||||
'location_id': order.shop_id.warehouse_id.lot_stock_id.id,
|
|
||||||
'procure_method': line.type,
|
|
||||||
'move_id': move_id,
|
|
||||||
'company_id': order.company_id.id,
|
|
||||||
'note': '\n'.join(line.name.split('\n')[1:])
|
|
||||||
}
|
|
||||||
|
|
||||||
def _prepare_order_line_move(self, cr, uid, order, line, picking_id, date_planned, context=None):
|
|
||||||
location_id = order.shop_id.warehouse_id.lot_stock_id.id
|
|
||||||
output_id = order.shop_id.warehouse_id.lot_output_id.id
|
|
||||||
return {
|
|
||||||
'name': line.name.split('\n')[0][:250],
|
|
||||||
'picking_id': picking_id,
|
|
||||||
'product_id': line.product_id.id,
|
|
||||||
'date': date_planned,
|
|
||||||
'date_expected': date_planned,
|
|
||||||
'product_qty': line.product_uom_qty,
|
|
||||||
'product_uom': line.product_uom.id,
|
|
||||||
'product_uos_qty': (line.product_uos and line.product_uos_qty) or line.product_uom_qty,
|
|
||||||
'product_uos': (line.product_uos and line.product_uos.id)\
|
|
||||||
or line.product_uom.id,
|
|
||||||
'product_packaging': line.product_packaging.id,
|
|
||||||
'partner_id': line.address_allotment_id.id or order.partner_shipping_id.id,
|
|
||||||
'location_id': location_id,
|
|
||||||
'location_dest_id': output_id,
|
|
||||||
'sale_line_id': line.id,
|
|
||||||
'tracking_id': False,
|
|
||||||
'state': 'draft',
|
|
||||||
'type':'out',
|
|
||||||
#'state': 'waiting',
|
|
||||||
'note': '\n'.join(line.name.split('\n')[1:]),
|
|
||||||
'company_id': order.company_id.id,
|
|
||||||
'price_unit': line.product_id.standard_price or 0.0
|
|
||||||
}
|
|
||||||
|
|
||||||
def _prepare_order_picking(self, cr, uid, order, context=None):
|
|
||||||
pick_name = self.pool.get('ir.sequence').get(cr, uid, 'stock.picking.out')
|
|
||||||
return {
|
|
||||||
'name': pick_name,
|
|
||||||
'origin': order.name,
|
|
||||||
'date': order.date_order,
|
|
||||||
'type': 'out',
|
|
||||||
'state': 'auto',
|
|
||||||
'move_type': order.picking_policy,
|
|
||||||
'sale_id': order.id,
|
|
||||||
'partner_id': order.partner_shipping_id.id,
|
|
||||||
'note': order.note,
|
|
||||||
'invoice_state': (order.order_policy=='picking' and '2binvoiced') or 'none',
|
|
||||||
'company_id': order.company_id.id,
|
|
||||||
}
|
|
||||||
|
|
||||||
def ship_recreate(self, cr, uid, order, line, move_id, proc_id):
|
|
||||||
# FIXME: deals with potentially cancelled shipments, seems broken (specially if shipment has production lot)
|
|
||||||
"""
|
|
||||||
Define ship_recreate for process after shipping exception
|
|
||||||
param order: sale order to which the order lines belong
|
|
||||||
param line: sale order line records to procure
|
|
||||||
param move_id: the ID of stock move
|
|
||||||
param proc_id: the ID of procurement
|
|
||||||
"""
|
|
||||||
move_obj = self.pool.get('stock.move')
|
|
||||||
if order.state == 'shipping_except':
|
|
||||||
for pick in order.picking_ids:
|
|
||||||
for move in pick.move_lines:
|
|
||||||
if move.state == 'cancel':
|
|
||||||
mov_ids = move_obj.search(cr, uid, [('state', '=', 'cancel'),('sale_line_id', '=', line.id),('picking_id', '=', pick.id)])
|
|
||||||
if mov_ids:
|
|
||||||
for mov in move_obj.browse(cr, uid, mov_ids):
|
|
||||||
# FIXME: the following seems broken: what if move_id doesn't exist? What if there are several mov_ids? Shouldn't that be a sum?
|
|
||||||
move_obj.write(cr, uid, [move_id], {'product_qty': mov.product_qty, 'product_uos_qty': mov.product_uos_qty})
|
|
||||||
self.pool.get('procurement.order').write(cr, uid, [proc_id], {'product_qty': mov.product_qty, 'product_uos_qty': mov.product_uos_qty})
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _get_date_planned(self, cr, uid, order, line, start_date, context=None):
|
|
||||||
date_planned = datetime.strptime(start_date, DEFAULT_SERVER_DATE_FORMAT) + relativedelta(days=line.delay or 0.0)
|
|
||||||
date_planned = (date_planned - timedelta(days=order.company_id.security_lead)).strftime(DEFAULT_SERVER_DATETIME_FORMAT)
|
|
||||||
return date_planned
|
|
||||||
|
|
||||||
def _create_pickings_and_procurements(self, cr, uid, order, order_lines, picking_id=False, context=None):
|
|
||||||
"""Create the required procurements to supply sale order lines, also connecting
|
|
||||||
the procurements to appropriate stock moves in order to bring the goods to the
|
|
||||||
sale order's requested location.
|
|
||||||
|
|
||||||
If ``picking_id`` is provided, the stock moves will be added to it, otherwise
|
|
||||||
a standard outgoing picking will be created to wrap the stock moves, as returned
|
|
||||||
by :meth:`~._prepare_order_picking`.
|
|
||||||
|
|
||||||
Modules that wish to customize the procurements or partition the stock moves over
|
|
||||||
multiple stock pickings may override this method and call ``super()`` with
|
|
||||||
different subsets of ``order_lines`` and/or preset ``picking_id`` values.
|
|
||||||
|
|
||||||
:param browse_record order: sale order to which the order lines belong
|
|
||||||
:param list(browse_record) order_lines: sale order line records to procure
|
|
||||||
:param int picking_id: optional ID of a stock picking to which the created stock moves
|
|
||||||
will be added. A new picking will be created if ommitted.
|
|
||||||
:return: True
|
|
||||||
"""
|
|
||||||
move_obj = self.pool.get('stock.move')
|
|
||||||
picking_obj = self.pool.get('stock.picking')
|
|
||||||
procurement_obj = self.pool.get('procurement.order')
|
|
||||||
proc_ids = []
|
|
||||||
|
|
||||||
for line in order_lines:
|
|
||||||
if line.state == 'done':
|
|
||||||
continue
|
|
||||||
|
|
||||||
date_planned = self._get_date_planned(cr, uid, order, line, order.date_order, context=context)
|
|
||||||
|
|
||||||
if line.product_id:
|
|
||||||
if line.product_id.product_tmpl_id.type in ('product', 'consu'):
|
|
||||||
if not picking_id:
|
|
||||||
picking_id = picking_obj.create(cr, uid, self._prepare_order_picking(cr, uid, order, context=context))
|
|
||||||
move_id = move_obj.create(cr, uid, self._prepare_order_line_move(cr, uid, order, line, picking_id, date_planned, context=context))
|
|
||||||
else:
|
|
||||||
# a service has no stock move
|
|
||||||
move_id = False
|
|
||||||
|
|
||||||
proc_id = procurement_obj.create(cr, uid, self._prepare_order_line_procurement(cr, uid, order, line, move_id, date_planned, context=context))
|
|
||||||
proc_ids.append(proc_id)
|
|
||||||
line.write({'procurement_id': proc_id})
|
|
||||||
self.ship_recreate(cr, uid, order, line, move_id, proc_id)
|
|
||||||
|
|
||||||
wf_service = netsvc.LocalService("workflow")
|
|
||||||
if picking_id:
|
|
||||||
wf_service.trg_validate(uid, 'stock.picking', picking_id, 'button_confirm', cr)
|
|
||||||
self.delivery_send_note(cr, uid, [order.id], picking_id, context)
|
|
||||||
|
|
||||||
|
|
||||||
for proc_id in proc_ids:
|
|
||||||
wf_service.trg_validate(uid, 'procurement.order', proc_id, 'button_confirm', cr)
|
|
||||||
|
|
||||||
val = {}
|
|
||||||
if order.state == 'shipping_except':
|
|
||||||
val['state'] = 'progress'
|
|
||||||
val['shipped'] = False
|
|
||||||
|
|
||||||
if (order.order_policy == 'manual'):
|
|
||||||
for line in order.order_line:
|
|
||||||
if (not line.invoiced) and (line.state not in ('cancel', 'draft')):
|
|
||||||
val['state'] = 'manual'
|
|
||||||
break
|
|
||||||
order.write(val)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def action_ship_create(self, cr, uid, ids, context=None):
|
|
||||||
for order in self.browse(cr, uid, ids, context=context):
|
|
||||||
self._create_pickings_and_procurements(cr, uid, order, order.order_line, None, context=context)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def action_ship_end(self, cr, uid, ids, context=None):
|
|
||||||
for order in self.browse(cr, uid, ids, context=context):
|
|
||||||
val = {'shipped': True}
|
|
||||||
if order.state == 'shipping_except':
|
|
||||||
val['state'] = 'progress'
|
|
||||||
if (order.order_policy == 'manual'):
|
|
||||||
for line in order.order_line:
|
|
||||||
if (not line.invoiced) and (line.state not in ('cancel', 'draft')):
|
|
||||||
val['state'] = 'manual'
|
|
||||||
break
|
|
||||||
for line in order.order_line:
|
|
||||||
towrite = []
|
|
||||||
if line.state == 'exception':
|
|
||||||
towrite.append(line.id)
|
|
||||||
if towrite:
|
|
||||||
self.pool.get('sale.order.line').write(cr, uid, towrite, {'state': 'done'}, context=context)
|
|
||||||
res = self.write(cr, uid, [order.id], val)
|
|
||||||
if res:
|
|
||||||
self.delivery_end_send_note(cr, uid, [order.id], context=context)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def has_stockable_products(self, cr, uid, ids, *args):
|
|
||||||
for order in self.browse(cr, uid, ids):
|
|
||||||
for order_line in order.order_line:
|
|
||||||
if order_line.product_id and order_line.product_id.product_tmpl_id.type in ('product', 'consu'):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
# OpenChatter methods and notifications
|
# OpenChatter methods and notifications
|
||||||
|
@ -1038,18 +648,10 @@ class sale_order(osv.osv):
|
||||||
def cancel_send_note(self, cr, uid, ids, context=None):
|
def cancel_send_note(self, cr, uid, ids, context=None):
|
||||||
for obj in self.browse(cr, uid, ids, context=context):
|
for obj in self.browse(cr, uid, ids, context=context):
|
||||||
self.message_post(cr, uid, [obj.id], body=_("Sale Order for <em>%s</em> <b>cancelled</b>.") % (obj.partner_id.name), context=context)
|
self.message_post(cr, uid, [obj.id], body=_("Sale Order for <em>%s</em> <b>cancelled</b>.") % (obj.partner_id.name), context=context)
|
||||||
|
|
||||||
def delivery_send_note(self, cr, uid, ids, picking_id, context=None):
|
def done_send_note(self, cr, uid, ids, context=None):
|
||||||
for order in self.browse(cr, uid, ids, context=context):
|
for obj in self.browse(cr, uid, ids, context=context):
|
||||||
for picking in (pck for pck in order.picking_ids if pck.id == picking_id):
|
self.message_post(cr, uid, [obj.id], body=_("Sale Order for <em>%s</em> set to <b>Done</b>") % (obj.partner_id.name), context=context)
|
||||||
# convert datetime field to a datetime, using server format, then
|
|
||||||
# convert it to the user TZ and re-render it with %Z to add the timezone
|
|
||||||
picking_datetime = fields.DT.datetime.strptime(picking.min_date, DEFAULT_SERVER_DATETIME_FORMAT)
|
|
||||||
picking_date_str = fields.datetime.context_timestamp(cr, uid, picking_datetime, context=context).strftime(DATETIME_FORMATS_MAP['%+'] + " (%Z)")
|
|
||||||
self.message_post(cr, uid, [order.id], body=_("Delivery Order <em>%s</em> <b>scheduled</b> for %s.") % (picking.name, picking_date_str), context=context)
|
|
||||||
|
|
||||||
def delivery_end_send_note(self, cr, uid, ids, context=None):
|
|
||||||
self.message_post(cr, uid, ids, body=_("Order <b>delivered</b>."), context=context)
|
|
||||||
|
|
||||||
def invoice_paid_send_note(self, cr, uid, ids, context=None):
|
def invoice_paid_send_note(self, cr, uid, ids, context=None):
|
||||||
self.message_post(cr, uid, ids, body=_("Invoice <b>paid</b>."), context=context)
|
self.message_post(cr, uid, ids, body=_("Invoice <b>paid</b>."), context=context)
|
||||||
|
@ -1059,10 +661,6 @@ class sale_order(osv.osv):
|
||||||
for invoice in (inv for inv in order.invoice_ids if inv.id == invoice_id):
|
for invoice in (inv for inv in order.invoice_ids if inv.id == invoice_id):
|
||||||
self.message_post(cr, uid, [order.id], body=_("Draft Invoice of %s %s <b>waiting for validation</b>.") % (invoice.amount_total, invoice.currency_id.symbol), context=context)
|
self.message_post(cr, uid, [order.id], body=_("Draft Invoice of %s %s <b>waiting for validation</b>.") % (invoice.amount_total, invoice.currency_id.symbol), context=context)
|
||||||
|
|
||||||
def action_cancel_draft_send_note(self, cr, uid, ids, context=None):
|
|
||||||
return self.message_post(cr, uid, ids, body=_('Sale order set to draft.'), context=context)
|
|
||||||
|
|
||||||
|
|
||||||
sale_order()
|
sale_order()
|
||||||
|
|
||||||
# TODO add a field price_unit_uos
|
# TODO add a field price_unit_uos
|
||||||
|
@ -1083,15 +681,6 @@ class sale_order_line(osv.osv):
|
||||||
res[line.id] = cur_obj.round(cr, uid, cur, taxes['total'])
|
res[line.id] = cur_obj.round(cr, uid, cur, taxes['total'])
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def _number_packages(self, cr, uid, ids, field_name, arg, context=None):
|
|
||||||
res = {}
|
|
||||||
for line in self.browse(cr, uid, ids, context=context):
|
|
||||||
try:
|
|
||||||
res[line.id] = int((line.product_uom_qty+line.product_packaging.qty-0.0001) / line.product_packaging.qty)
|
|
||||||
except:
|
|
||||||
res[line.id] = 1
|
|
||||||
return res
|
|
||||||
|
|
||||||
def _get_uom_id(self, cr, uid, *args):
|
def _get_uom_id(self, cr, uid, *args):
|
||||||
try:
|
try:
|
||||||
proxy = self.pool.get('ir.model.data')
|
proxy = self.pool.get('ir.model.data')
|
||||||
|
@ -1106,26 +695,18 @@ class sale_order_line(osv.osv):
|
||||||
'order_id': fields.many2one('sale.order', 'Order Reference', required=True, ondelete='cascade', select=True, readonly=True, states={'draft':[('readonly',False)]}),
|
'order_id': fields.many2one('sale.order', 'Order Reference', required=True, ondelete='cascade', select=True, readonly=True, states={'draft':[('readonly',False)]}),
|
||||||
'name': fields.text('Product Description', size=256, required=True, select=True, readonly=True, states={'draft': [('readonly', False)]}),
|
'name': fields.text('Product Description', size=256, required=True, select=True, readonly=True, states={'draft': [('readonly', False)]}),
|
||||||
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of sales order lines."),
|
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of sales order lines."),
|
||||||
'delay': fields.float('Delivery Lead Time', required=True, help="Number of days between the order confirmation the shipping of the products to the customer", readonly=True, states={'draft': [('readonly', False)]}),
|
|
||||||
'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], change_default=True),
|
'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], change_default=True),
|
||||||
'invoice_lines': fields.many2many('account.invoice.line', 'sale_order_line_invoice_rel', 'order_line_id', 'invoice_id', 'Invoice Lines', readonly=True),
|
'invoice_lines': fields.many2many('account.invoice.line', 'sale_order_line_invoice_rel', 'order_line_id', 'invoice_id', 'Invoice Lines', readonly=True),
|
||||||
'invoiced': fields.boolean('Invoiced', readonly=True),
|
'invoiced': fields.boolean('Invoiced', readonly=True),
|
||||||
'procurement_id': fields.many2one('procurement.order', 'Procurement'),
|
|
||||||
'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Product Price'), readonly=True, states={'draft': [('readonly', False)]}),
|
'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Product Price'), readonly=True, states={'draft': [('readonly', False)]}),
|
||||||
'price_subtotal': fields.function(_amount_line, string='Subtotal', digits_compute= dp.get_precision('Account'), store=True),
|
'price_subtotal': fields.function(_amount_line, string='Subtotal', digits_compute= dp.get_precision('Account'), store=True),
|
||||||
'tax_id': fields.many2many('account.tax', 'sale_order_tax', 'order_line_id', 'tax_id', 'Taxes', readonly=True, states={'draft': [('readonly', False)]}),
|
'tax_id': fields.many2many('account.tax', 'sale_order_tax', 'order_line_id', 'tax_id', 'Taxes', readonly=True, states={'draft': [('readonly', False)]}),
|
||||||
'type': fields.selection([('make_to_stock', 'from stock'), ('make_to_order', 'on order')], 'Procurement Method', required=True, readonly=True, states={'draft': [('readonly', False)]},
|
|
||||||
help="If 'on order', it triggers a procurement when the sale order is confirmed to create a task, purchase order or manufacturing order linked to this sale order line."),
|
|
||||||
'property_ids': fields.many2many('mrp.property', 'sale_order_line_property_rel', 'order_id', 'property_id', 'Properties', readonly=True, states={'draft': [('readonly', False)]}),
|
|
||||||
'address_allotment_id': fields.many2one('res.partner', 'Allotment Partner'),
|
'address_allotment_id': fields.many2one('res.partner', 'Allotment Partner'),
|
||||||
'product_uom_qty': fields.float('Quantity', digits_compute= dp.get_precision('Product UoS'), required=True, readonly=True, states={'draft': [('readonly', False)]}),
|
'product_uom_qty': fields.float('Quantity', digits_compute= dp.get_precision('Product UoS'), required=True, readonly=True, states={'draft': [('readonly', False)]}),
|
||||||
'product_uom': fields.many2one('product.uom', 'Unit of Measure ', required=True, readonly=True, states={'draft': [('readonly', False)]}),
|
'product_uom': fields.many2one('product.uom', 'Unit of Measure ', required=True, readonly=True, states={'draft': [('readonly', False)]}),
|
||||||
'product_uos_qty': fields.float('Quantity (UoS)' ,digits_compute= dp.get_precision('Product UoS'), readonly=True, states={'draft': [('readonly', False)]}),
|
'product_uos_qty': fields.float('Quantity (UoS)' ,digits_compute= dp.get_precision('Product UoS'), readonly=True, states={'draft': [('readonly', False)]}),
|
||||||
'product_uos': fields.many2one('product.uom', 'Product UoS'),
|
'product_uos': fields.many2one('product.uom', 'Product UoS'),
|
||||||
'product_packaging': fields.many2one('product.packaging', 'Packaging'),
|
|
||||||
'move_ids': fields.one2many('stock.move', 'sale_line_id', 'Inventory Moves', readonly=True),
|
|
||||||
'discount': fields.float('Discount (%)', digits_compute= dp.get_precision('Discount'), readonly=True, states={'draft': [('readonly', False)]}),
|
'discount': fields.float('Discount (%)', digits_compute= dp.get_precision('Discount'), readonly=True, states={'draft': [('readonly', False)]}),
|
||||||
'number_packages': fields.function(_number_packages, type='integer', string='Number Packages'),
|
|
||||||
'th_weight': fields.float('Weight', readonly=True, states={'draft': [('readonly', False)]}),
|
'th_weight': fields.float('Weight', readonly=True, states={'draft': [('readonly', False)]}),
|
||||||
'state': fields.selection([('cancel', 'Cancelled'),('draft', 'Draft'),('confirmed', 'Confirmed'),('exception', 'Exception'),('done', 'Done')], 'Status', required=True, readonly=True,
|
'state': fields.selection([('cancel', 'Cancelled'),('draft', 'Draft'),('confirmed', 'Confirmed'),('exception', 'Exception'),('done', 'Done')], 'Status', required=True, readonly=True,
|
||||||
help='* The \'Draft\' state is set when the related sales order in draft state. \
|
help='* The \'Draft\' state is set when the related sales order in draft state. \
|
||||||
|
@ -1141,17 +722,26 @@ class sale_order_line(osv.osv):
|
||||||
_defaults = {
|
_defaults = {
|
||||||
'product_uom' : _get_uom_id,
|
'product_uom' : _get_uom_id,
|
||||||
'discount': 0.0,
|
'discount': 0.0,
|
||||||
'delay': 0.0,
|
|
||||||
'product_uom_qty': 1,
|
'product_uom_qty': 1,
|
||||||
'product_uos_qty': 1,
|
'product_uos_qty': 1,
|
||||||
'sequence': 10,
|
'sequence': 10,
|
||||||
'invoiced': 0,
|
'invoiced': 0,
|
||||||
'state': 'draft',
|
'state': 'draft',
|
||||||
'type': 'make_to_stock',
|
|
||||||
'product_packaging': False,
|
|
||||||
'price_unit': 0.0,
|
'price_unit': 0.0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def _get_line_qty(self, cr, uid, line, context=None):
|
||||||
|
if (line.order_id.invoice_quantity=='order'):
|
||||||
|
if line.product_uos:
|
||||||
|
return line.product_uos_qty or 0.0
|
||||||
|
return line.product_uom_qty
|
||||||
|
|
||||||
|
def _get_line_uom(self, cr, uid, line, context=None):
|
||||||
|
if (line.order_id.invoice_quantity=='order'):
|
||||||
|
if line.product_uos:
|
||||||
|
return line.product_uos.id
|
||||||
|
return line.product_uom.id
|
||||||
|
|
||||||
def _prepare_order_line_invoice_line(self, cr, uid, line, account_id=False, context=None):
|
def _prepare_order_line_invoice_line(self, cr, uid, line, account_id=False, context=None):
|
||||||
"""Prepare the dict of values to create the new invoice line for a
|
"""Prepare the dict of values to create the new invoice line for a
|
||||||
sale order line. This method may be overridden to implement custom
|
sale order line. This method may be overridden to implement custom
|
||||||
|
@ -1163,25 +753,7 @@ class sale_order_line(osv.osv):
|
||||||
(this is used for returning products including service)
|
(this is used for returning products including service)
|
||||||
:return: dict of values to create() the invoice line
|
:return: dict of values to create() the invoice line
|
||||||
"""
|
"""
|
||||||
|
res = {}
|
||||||
def _get_line_qty(line):
|
|
||||||
if (line.order_id.invoice_quantity=='order') or not line.procurement_id:
|
|
||||||
if line.product_uos:
|
|
||||||
return line.product_uos_qty or 0.0
|
|
||||||
return line.product_uom_qty
|
|
||||||
else:
|
|
||||||
return self.pool.get('procurement.order').quantity_get(cr, uid,
|
|
||||||
line.procurement_id.id, context=context)
|
|
||||||
|
|
||||||
def _get_line_uom(line):
|
|
||||||
if (line.order_id.invoice_quantity=='order') or not line.procurement_id:
|
|
||||||
if line.product_uos:
|
|
||||||
return line.product_uos.id
|
|
||||||
return line.product_uom.id
|
|
||||||
else:
|
|
||||||
return self.pool.get('procurement.order').uom_get(cr, uid,
|
|
||||||
line.procurement_id.id, context=context)
|
|
||||||
|
|
||||||
if not line.invoiced:
|
if not line.invoiced:
|
||||||
if not account_id:
|
if not account_id:
|
||||||
if line.product_id:
|
if line.product_id:
|
||||||
|
@ -1197,8 +769,8 @@ class sale_order_line(osv.osv):
|
||||||
'property_account_income_categ', 'product.category',
|
'property_account_income_categ', 'product.category',
|
||||||
context=context)
|
context=context)
|
||||||
account_id = prop and prop.id or False
|
account_id = prop and prop.id or False
|
||||||
uosqty = _get_line_qty(line)
|
uosqty = self._get_line_qty(cr, uid, line, context=context)
|
||||||
uos_id = _get_line_uom(line)
|
uos_id = self._get_line_uom(cr, uid, line, context=context)
|
||||||
pu = 0.0
|
pu = 0.0
|
||||||
if uosqty:
|
if uosqty:
|
||||||
pu = round(line.price_unit * line.product_uom_qty / uosqty,
|
pu = round(line.price_unit * line.product_uom_qty / uosqty,
|
||||||
|
@ -1208,7 +780,7 @@ class sale_order_line(osv.osv):
|
||||||
if not account_id:
|
if not account_id:
|
||||||
raise osv.except_osv(_('Error!'),
|
raise osv.except_osv(_('Error!'),
|
||||||
_('There is no Fiscal Position defined or Income category account defined for default properties of Product categories.'))
|
_('There is no Fiscal Position defined or Income category account defined for default properties of Product categories.'))
|
||||||
return {
|
res = {
|
||||||
'name': line.name,
|
'name': line.name,
|
||||||
'origin': line.order_id.name,
|
'origin': line.order_id.name,
|
||||||
'account_id': account_id,
|
'account_id': account_id,
|
||||||
|
@ -1221,7 +793,7 @@ class sale_order_line(osv.osv):
|
||||||
'account_analytic_id': line.order_id.project_id and line.order_id.project_id.id or False,
|
'account_analytic_id': line.order_id.project_id and line.order_id.project_id.id or False,
|
||||||
}
|
}
|
||||||
|
|
||||||
return False
|
return res
|
||||||
|
|
||||||
def invoice_line_create(self, cr, uid, ids, context=None):
|
def invoice_line_create(self, cr, uid, ids, context=None):
|
||||||
if context is None:
|
if context is None:
|
||||||
|
@ -1247,11 +819,6 @@ class sale_order_line(osv.osv):
|
||||||
for line in self.browse(cr, uid, ids, context=context):
|
for line in self.browse(cr, uid, ids, context=context):
|
||||||
if line.invoiced:
|
if line.invoiced:
|
||||||
raise osv.except_osv(_('Invalid Action!'), _('You cannot cancel a sale order line that has already been invoiced.'))
|
raise osv.except_osv(_('Invalid Action!'), _('You cannot cancel a sale order line that has already been invoiced.'))
|
||||||
for move_line in line.move_ids:
|
|
||||||
if move_line.state != 'cancel':
|
|
||||||
raise osv.except_osv(
|
|
||||||
_('Cannot cancel sales order line!'),
|
|
||||||
_('You must first cancel stock moves attached to this sales order line.'))
|
|
||||||
return self.write(cr, uid, ids, {'state': 'cancel'})
|
return self.write(cr, uid, ids, {'state': 'cancel'})
|
||||||
|
|
||||||
def button_confirm(self, cr, uid, ids, context=None):
|
def button_confirm(self, cr, uid, ids, context=None):
|
||||||
|
@ -1287,56 +854,9 @@ class sale_order_line(osv.osv):
|
||||||
def copy_data(self, cr, uid, id, default=None, context=None):
|
def copy_data(self, cr, uid, id, default=None, context=None):
|
||||||
if not default:
|
if not default:
|
||||||
default = {}
|
default = {}
|
||||||
default.update({'state': 'draft', 'move_ids': [], 'invoiced': False, 'invoice_lines': []})
|
default.update({'state': 'draft', 'invoiced': False, 'invoice_lines': []})
|
||||||
return super(sale_order_line, self).copy_data(cr, uid, id, default, context=context)
|
return super(sale_order_line, self).copy_data(cr, uid, id, default, context=context)
|
||||||
|
|
||||||
def product_packaging_change(self, cr, uid, ids, pricelist, product, qty=0, uom=False,
|
|
||||||
partner_id=False, packaging=False, flag=False, context=None):
|
|
||||||
if not product:
|
|
||||||
return {'value': {'product_packaging': False}}
|
|
||||||
product_obj = self.pool.get('product.product')
|
|
||||||
product_uom_obj = self.pool.get('product.uom')
|
|
||||||
pack_obj = self.pool.get('product.packaging')
|
|
||||||
warning = {}
|
|
||||||
result = {}
|
|
||||||
warning_msgs = ''
|
|
||||||
if flag:
|
|
||||||
res = self.product_id_change(cr, uid, ids, pricelist=pricelist,
|
|
||||||
product=product, qty=qty, uom=uom, partner_id=partner_id,
|
|
||||||
packaging=packaging, flag=False, context=context)
|
|
||||||
warning_msgs = res.get('warning') and res['warning']['message']
|
|
||||||
|
|
||||||
products = product_obj.browse(cr, uid, product, context=context)
|
|
||||||
if not products.packaging:
|
|
||||||
packaging = result['product_packaging'] = False
|
|
||||||
elif not packaging and products.packaging and not flag:
|
|
||||||
packaging = products.packaging[0].id
|
|
||||||
result['product_packaging'] = packaging
|
|
||||||
|
|
||||||
if packaging:
|
|
||||||
default_uom = products.uom_id and products.uom_id.id
|
|
||||||
pack = pack_obj.browse(cr, uid, packaging, context=context)
|
|
||||||
q = product_uom_obj._compute_qty(cr, uid, uom, pack.qty, default_uom)
|
|
||||||
# qty = qty - qty % q + q
|
|
||||||
if qty and (q and not (qty % q) == 0):
|
|
||||||
ean = pack.ean or _('(n/a)')
|
|
||||||
qty_pack = pack.qty
|
|
||||||
type_ul = pack.ul
|
|
||||||
if not warning_msgs:
|
|
||||||
warn_msg = _("You selected a quantity of %d Units.\n"
|
|
||||||
"But it's not compatible with the selected packaging.\n"
|
|
||||||
"Here is a proposition of quantities according to the packaging:\n"
|
|
||||||
"EAN: %s Quantity: %s Type of ul: %s") % \
|
|
||||||
(qty, ean, qty_pack, type_ul.name)
|
|
||||||
warning_msgs += _("Picking Information ! : ") + warn_msg + "\n\n"
|
|
||||||
warning = {
|
|
||||||
'title': _('Configuration Error!'),
|
|
||||||
'message': warning_msgs
|
|
||||||
}
|
|
||||||
result['product_uom_qty'] = qty
|
|
||||||
|
|
||||||
return {'value': result, 'warning': warning}
|
|
||||||
|
|
||||||
def product_id_change(self, cr, uid, ids, pricelist, product, qty=0,
|
def product_id_change(self, cr, uid, ids, pricelist, product, qty=0,
|
||||||
uom=False, qty_uos=0, uos=False, name='', partner_id=False,
|
uom=False, qty_uos=0, uos=False, name='', partner_id=False,
|
||||||
lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False, context=None):
|
lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False, context=None):
|
||||||
|
@ -1354,15 +874,14 @@ class sale_order_line(osv.osv):
|
||||||
context_partner = {'lang': lang, 'partner_id': partner_id}
|
context_partner = {'lang': lang, 'partner_id': partner_id}
|
||||||
|
|
||||||
if not product:
|
if not product:
|
||||||
return {'value': {'th_weight': 0, 'product_packaging': False,
|
return {'value': {'th_weight': 0,
|
||||||
'product_uos_qty': qty}, 'domain': {'product_uom': [],
|
'product_uos_qty': qty}, 'domain': {'product_uom': [],
|
||||||
'product_uos': []}}
|
'product_uos': []}}
|
||||||
if not date_order:
|
if not date_order:
|
||||||
date_order = time.strftime(DEFAULT_SERVER_DATE_FORMAT)
|
date_order = time.strftime(DEFAULT_SERVER_DATE_FORMAT)
|
||||||
|
#
|
||||||
res = self.product_packaging_change(cr, uid, ids, pricelist, product, qty, uom, partner_id, packaging, context=context)
|
result = {}
|
||||||
result = res.get('value', {})
|
warning_msgs = {}
|
||||||
warning_msgs = res.get('warning') and res['warning']['message'] or ''
|
|
||||||
product_obj = product_obj.browse(cr, uid, product, context=context)
|
product_obj = product_obj.browse(cr, uid, product, context=context)
|
||||||
|
|
||||||
uom2 = False
|
uom2 = False
|
||||||
|
@ -1379,7 +898,6 @@ class sale_order_line(osv.osv):
|
||||||
uos = False
|
uos = False
|
||||||
fpos = fiscal_position and self.pool.get('account.fiscal.position').browse(cr, uid, fiscal_position) or False
|
fpos = fiscal_position and self.pool.get('account.fiscal.position').browse(cr, uid, fiscal_position) or False
|
||||||
if update_tax: #The quantity only have changed
|
if update_tax: #The quantity only have changed
|
||||||
result['delay'] = (product_obj.sale_delay or 0.0)
|
|
||||||
result['tax_id'] = self.pool.get('account.fiscal.position').map_tax(cr, uid, fpos, product_obj.taxes_id)
|
result['tax_id'] = self.pool.get('account.fiscal.position').map_tax(cr, uid, fpos, product_obj.taxes_id)
|
||||||
result.update({'type': product_obj.procure_method})
|
result.update({'type': product_obj.procure_method})
|
||||||
|
|
||||||
|
@ -1420,14 +938,6 @@ class sale_order_line(osv.osv):
|
||||||
|
|
||||||
if not uom2:
|
if not uom2:
|
||||||
uom2 = product_obj.uom_id
|
uom2 = product_obj.uom_id
|
||||||
compare_qty = float_compare(product_obj.virtual_available * uom2.factor, qty * product_obj.uom_id.factor, precision_rounding=product_obj.uom_id.rounding)
|
|
||||||
if (product_obj.type=='product') and int(compare_qty) == -1 \
|
|
||||||
and (product_obj.procure_method=='make_to_stock'):
|
|
||||||
warn_msg = _('You plan to sell %.2f %s but you only have %.2f %s available !\nThe real stock is %.2f %s. (without reservations)') % \
|
|
||||||
(qty, uom2 and uom2.name or product_obj.uom_id.name,
|
|
||||||
max(0,product_obj.virtual_available), product_obj.uom_id.name,
|
|
||||||
max(0,product_obj.qty_available), product_obj.uom_id.name)
|
|
||||||
warning_msgs += _("Not enough stock ! : ") + warn_msg + "\n\n"
|
|
||||||
# get unit price
|
# get unit price
|
||||||
|
|
||||||
if not pricelist:
|
if not pricelist:
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
<!-- Resource: sale.shop -->
|
<!-- Resource: sale.shop -->
|
||||||
<record id="sale_shop_1" model="sale.shop">
|
<record id="sale_shop_1" model="sale.shop">
|
||||||
<field name="company_id" ref="base.main_company"/>
|
<field name="company_id" ref="base.main_company"/>
|
||||||
<field name="warehouse_id" ref="stock.warehouse0"/>
|
|
||||||
<field name="payment_default_id" ref="account.account_payment_term"/>
|
<field name="payment_default_id" ref="account.account_payment_term"/>
|
||||||
<field name="pricelist_id" ref="product.list0"/>
|
<field name="pricelist_id" ref="product.list0"/>
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
<field name="shop_id" ref="sale_shop_1"/>
|
<field name="shop_id" ref="sale_shop_1"/>
|
||||||
<field name="user_id" ref="base.user_demo"/>
|
<field name="user_id" ref="base.user_demo"/>
|
||||||
<field name="pricelist_id" ref="product.list0"/>
|
<field name="pricelist_id" ref="product.list0"/>
|
||||||
<field name="order_policy">prepaid</field>
|
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="sale_order_line_1" model="sale.order.line">
|
<record id="sale_order_line_1" model="sale.order.line">
|
||||||
|
@ -60,7 +59,6 @@
|
||||||
<field name="product_uos_qty">24</field>
|
<field name="product_uos_qty">24</field>
|
||||||
<field name="product_uom" ref="product.product_uom_hour"/>
|
<field name="product_uom" ref="product.product_uom_hour"/>
|
||||||
<field name="price_unit">75.00</field>
|
<field name="price_unit">75.00</field>
|
||||||
<field name="type">make_to_order</field>
|
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="sale_order_line_5" model="sale.order.line">
|
<record id="sale_order_line_5" model="sale.order.line">
|
||||||
|
@ -71,7 +69,6 @@
|
||||||
<field name="product_uos_qty">30</field>
|
<field name="product_uos_qty">30</field>
|
||||||
<field name="product_uom" ref="product.product_uom_hour"/>
|
<field name="product_uom" ref="product.product_uom_hour"/>
|
||||||
<field name="price_unit">38.25</field>
|
<field name="price_unit">38.25</field>
|
||||||
<field name="type">make_to_order</field>
|
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="sale_order_3" model="sale.order">
|
<record id="sale_order_3" model="sale.order">
|
||||||
|
@ -92,7 +89,6 @@
|
||||||
<field name="product_uos_qty">10</field>
|
<field name="product_uos_qty">10</field>
|
||||||
<field name="product_uom" ref="product.product_uom_hour"/>
|
<field name="product_uom" ref="product.product_uom_hour"/>
|
||||||
<field name="price_unit">30.75</field>
|
<field name="price_unit">30.75</field>
|
||||||
<field name="type">make_to_order</field>
|
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="sale_order_line_7" model="sale.order.line">
|
<record id="sale_order_line_7" model="sale.order.line">
|
||||||
|
@ -112,7 +108,6 @@
|
||||||
<field name="shop_id" ref="sale_shop_1"/>
|
<field name="shop_id" ref="sale_shop_1"/>
|
||||||
<field name="user_id" ref="base.user_root"/>
|
<field name="user_id" ref="base.user_root"/>
|
||||||
<field name="pricelist_id" ref="product.list0"/>
|
<field name="pricelist_id" ref="product.list0"/>
|
||||||
<field name="order_policy">prepaid</field>
|
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="sale_order_line_8" model="sale.order.line">
|
<record id="sale_order_line_8" model="sale.order.line">
|
||||||
|
@ -123,7 +118,6 @@
|
||||||
<field name="product_uos_qty">16</field>
|
<field name="product_uos_qty">16</field>
|
||||||
<field name="product_uom" ref="product.product_uom_hour"/>
|
<field name="product_uom" ref="product.product_uom_hour"/>
|
||||||
<field name="price_unit">75.00</field>
|
<field name="price_unit">75.00</field>
|
||||||
<field name="type">make_to_order</field>
|
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="sale_order_line_9" model="sale.order.line">
|
<record id="sale_order_line_9" model="sale.order.line">
|
||||||
|
@ -163,7 +157,6 @@
|
||||||
<field name="shop_id" ref="sale_shop_1"/>
|
<field name="shop_id" ref="sale_shop_1"/>
|
||||||
<field name="user_id" ref="base.user_demo"/>
|
<field name="user_id" ref="base.user_demo"/>
|
||||||
<field name="pricelist_id" ref="product.list0"/>
|
<field name="pricelist_id" ref="product.list0"/>
|
||||||
<field name="order_policy">picking</field>
|
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="sale_order_line_12" model="sale.order.line">
|
<record id="sale_order_line_12" model="sale.order.line">
|
||||||
|
@ -203,7 +196,6 @@
|
||||||
<field name="shop_id" ref="sale_shop_1"/>
|
<field name="shop_id" ref="sale_shop_1"/>
|
||||||
<field name="user_id" ref="base.user_root"/>
|
<field name="user_id" ref="base.user_root"/>
|
||||||
<field name="pricelist_id" ref="product.list0"/>
|
<field name="pricelist_id" ref="product.list0"/>
|
||||||
<field name="order_policy">picking</field>
|
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="sale_order_line_15" model="sale.order.line">
|
<record id="sale_order_line_15" model="sale.order.line">
|
||||||
|
@ -220,7 +212,6 @@
|
||||||
<field name="partner_id" ref="base.res_partner_11"/>
|
<field name="partner_id" ref="base.res_partner_11"/>
|
||||||
<field name="partner_invoice_id" ref="base.res_partner_address_20"/>
|
<field name="partner_invoice_id" ref="base.res_partner_address_20"/>
|
||||||
<field name="partner_shipping_id" ref="base.res_partner_address_20"/>
|
<field name="partner_shipping_id" ref="base.res_partner_address_20"/>
|
||||||
<field name="shop_id" ref="sale_shop_1"/>
|
|
||||||
<field name="user_id" ref="base.user_root"/>
|
<field name="user_id" ref="base.user_root"/>
|
||||||
<field name="pricelist_id" ref="product.list0"/>
|
<field name="pricelist_id" ref="product.list0"/>
|
||||||
<field name="order_policy">manual</field>
|
<field name="order_policy">manual</field>
|
||||||
|
@ -297,8 +288,6 @@
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- Confirm some Sale Orders-->
|
<!-- Confirm some Sale Orders-->
|
||||||
<workflow action="order_confirm" model="sale.order" ref="sale_order_1"/>
|
|
||||||
<workflow action="order_confirm" model="sale.order" ref="sale_order_5"/>
|
|
||||||
<workflow action="order_confirm" model="sale.order" ref="sale_order_7"/>
|
<workflow action="order_confirm" model="sale.order" ref="sale_order_7"/>
|
||||||
|
|
||||||
<record id="message_sale_1" model="mail.message">
|
<record id="message_sale_1" model="mail.message">
|
||||||
|
@ -352,9 +341,5 @@ Sales Department</field>
|
||||||
<field eval="[(4, ref('base.group_sale_salesman'))]" name="groups_id"/>
|
<field eval="[(4, ref('base.group_sale_salesman'))]" name="groups_id"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
||||||
<!-- Run all schedulers -->
|
|
||||||
<function model="procurement.order" name="run_scheduler"/>
|
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</openerp>
|
</openerp>
|
||||||
|
|
|
@ -21,9 +21,7 @@
|
||||||
<form string="Sales Shop" version="7.0">
|
<form string="Sales Shop" version="7.0">
|
||||||
<label for="name" class="oe_edit_only"/>
|
<label for="name" class="oe_edit_only"/>
|
||||||
<h1><field name="name"/></h1>
|
<h1><field name="name"/></h1>
|
||||||
<label for="warehouse_id" class="oe_edit_only"/>
|
<group name="shop">
|
||||||
<h2><field name="warehouse_id" required="1"/></h2>
|
|
||||||
<group>
|
|
||||||
<group>
|
<group>
|
||||||
<field name="payment_default_id"/>
|
<field name="payment_default_id"/>
|
||||||
<field domain="[('type','=','sale')]" name="pricelist_id" groups="product.group_sale_pricelist"/>
|
<field domain="[('type','=','sale')]" name="pricelist_id" groups="product.group_sale_pricelist"/>
|
||||||
|
@ -34,15 +32,15 @@
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="view_shop_tree" model="ir.ui.view">
|
<record id="view_shop_tree" model="ir.ui.view">
|
||||||
<field name="name">sale.shop</field>
|
<field name="name">sale.shop</field>
|
||||||
<field name="model">sale.shop</field>
|
<field name="model">sale.shop</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree string="Sales Shop">
|
<tree string="Sales Shop">
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="warehouse_id"/>
|
|
||||||
<field name="pricelist_id" groups="product.group_sale_pricelist"/>
|
<field name="pricelist_id" groups="product.group_sale_pricelist"/>
|
||||||
<field name="project_id" groups="analytic.group_analytic_accounting"/>
|
<field name="project_id" groups="analytic.group_analytic_accounting"/>
|
||||||
</tree>
|
</tree>
|
||||||
|
@ -67,8 +65,6 @@
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<menuitem action="action_shop_form" id="menu_action_shop_form" parent="base.menu_base_config" sequence="35"
|
|
||||||
groups="stock.group_locations"/>
|
|
||||||
|
|
||||||
<!-- Sale order Read/Unread actions -->
|
<!-- Sale order Read/Unread actions -->
|
||||||
<record id="actions_server_sale_order_unread" model="ir.actions.server">
|
<record id="actions_server_sale_order_unread" model="ir.actions.server">
|
||||||
|
@ -154,8 +150,6 @@
|
||||||
<span groups="base.group_user">
|
<span groups="base.group_user">
|
||||||
<button name="invoice_recreate" states="invoice_except" string="Recreate Invoice"/>
|
<button name="invoice_recreate" states="invoice_except" string="Recreate Invoice"/>
|
||||||
<button name="invoice_corrected" states="invoice_except" string="Ignore Exception"/>
|
<button name="invoice_corrected" states="invoice_except" string="Ignore Exception"/>
|
||||||
<button name="ship_recreate" states="shipping_except" string="Recreate Delivery Order"/>
|
|
||||||
<button name="ship_corrected" states="shipping_except" string="Ignore Exception"/>
|
|
||||||
<button name="action_quotation_send" string="Send by Mail" type="object" states="draft" class="oe_highlight"/>
|
<button name="action_quotation_send" string="Send by Mail" type="object" states="draft" class="oe_highlight"/>
|
||||||
<button name="action_quotation_send" string="Send by Mail" type="object" states="sent"/>
|
<button name="action_quotation_send" string="Send by Mail" type="object" states="sent"/>
|
||||||
<button name="print_quotation" string="Print" type="object" states="draft" class="oe_highlight"/>
|
<button name="print_quotation" string="Print" type="object" states="draft" class="oe_highlight"/>
|
||||||
|
@ -164,16 +158,13 @@
|
||||||
<button name="action_button_confirm" states="sent" string="Confirm" class="oe_highlight" type="object"/>
|
<button name="action_button_confirm" states="sent" string="Confirm" class="oe_highlight" type="object"/>
|
||||||
<button name="action_view_invoice" string="View Invoice" type="object" class="oe_highlight"
|
<button name="action_view_invoice" string="View Invoice" type="object" class="oe_highlight"
|
||||||
attrs="{'invisible': [('invoice_exists', '=', False)]}"/>
|
attrs="{'invisible': [('invoice_exists', '=', False)]}"/>
|
||||||
<button name="action_view_delivery" string="View Delivery Order" type="object" class="oe_highlight"
|
|
||||||
attrs="{'invisible': ['|','|','|',('picking_ids','=',False),('picking_ids','=',[]), ('state', 'not in', ('progress','manual')),('shipped','=',True)]}"/>
|
|
||||||
<button name="%(action_view_sale_advance_payment_inv)d" string="Create Invoice"
|
<button name="%(action_view_sale_advance_payment_inv)d" string="Create Invoice"
|
||||||
type="action" states="manual" class="oe_highlight"/>
|
type="action" states="manual" class="oe_highlight"/>
|
||||||
<button name="cancel" states="draft,sent" string="Cancel"/>
|
<button name="cancel" states="draft,sent" string="Cancel"/>
|
||||||
<button name="action_cancel" states="manual,progress" string="Cancel" type="object"/>
|
<button name="action_cancel" states="manual,progress" string="Cancel" type="object"/>
|
||||||
<button name="ship_cancel" states="shipping_except" string="Cancel"/>
|
|
||||||
<button name="invoice_cancel" states="invoice_except" string="Cancel"/>
|
<button name="invoice_cancel" states="invoice_except" string="Cancel"/>
|
||||||
</span>
|
</span>
|
||||||
<field name="state" widget="statusbar" statusbar_visible="draft,sent,progress,invoiced,done" statusbar_colors='{"shipping_except":"red","invoice_except":"red","waiting_date":"blue"}'/>
|
<field name="state" widget="statusbar" statusbar_visible="draft,sent,invoiced,done" statusbar_colors='{"invoice_except":"red","waiting_date":"blue"}'/>
|
||||||
</header>
|
</header>
|
||||||
<sheet>
|
<sheet>
|
||||||
<h1>
|
<h1>
|
||||||
|
@ -190,7 +181,7 @@
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="date_order"/>
|
<field name="date_order"/>
|
||||||
<field name="shop_id" on_change="onchange_shop_id(shop_id)" widget="selection" groups="stock.group_locations"/>
|
<field name="shop_id" invisible="1"/>
|
||||||
<field name="client_order_ref"/>
|
<field name="client_order_ref"/>
|
||||||
<field domain="[('type','=','sale')]" name="pricelist_id" groups="product.group_sale_pricelist" on_change="onchange_pricelist_id(pricelist_id,order_line)"/>
|
<field domain="[('type','=','sale')]" name="pricelist_id" groups="product.group_sale_pricelist" on_change="onchange_pricelist_id(pricelist_id,order_line)"/>
|
||||||
</group>
|
</group>
|
||||||
|
@ -209,14 +200,15 @@
|
||||||
<field name="product_id"
|
<field name="product_id"
|
||||||
context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'shop':parent.shop_id, 'uom':product_uom}"
|
context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'shop':parent.shop_id, 'uom':product_uom}"
|
||||||
groups="base.group_user"
|
groups="base.group_user"
|
||||||
on_change="product_id_change(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,product_uos,name,parent.partner_id, False, True, parent.date_order, product_packaging, parent.fiscal_position, False, context)"/>
|
on_change="product_id_change(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,product_uos,name,parent.partner_id, False, True, parent.date_order, False, parent.fiscal_position, False, context)"/>
|
||||||
<label for="product_uom_qty"/>
|
<label for="product_uom_qty"/>
|
||||||
<div>
|
<div>
|
||||||
<field
|
<field
|
||||||
context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'shop':parent.shop_id, 'uom':product_uom}"
|
context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'shop':parent.shop_id, 'uom':product_uom}"
|
||||||
name="product_uom_qty" class="oe_inline"
|
name="product_uom_qty" class="oe_inline"
|
||||||
on_change="product_id_change(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,product_uos,name,parent.partner_id, False, False, parent.date_order, product_packaging, parent.fiscal_position, True, context)"/>
|
on_change="product_id_change(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,product_uos,name,parent.partner_id, False, False, parent.date_order, False, parent.fiscal_position, True, context)"/>
|
||||||
<field name="product_uom" groups="product.group_uom" options='{"no_open": true}' class="oe_inline"
|
<field name="product_uom" groups="product.group_uom" class="oe_inline oe_no_button"
|
||||||
|
|
||||||
on_change="product_uom_change(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,product_uos,name,parent.partner_id, False, False, parent.date_order, context)"/>
|
on_change="product_uom_change(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,product_uos,name,parent.partner_id, False, False, parent.date_order, context)"/>
|
||||||
</div>
|
</div>
|
||||||
<label for="product_uos_qty" groups="product.group_uos"/>
|
<label for="product_uos_qty" groups="product.group_uos"/>
|
||||||
|
@ -231,22 +223,11 @@
|
||||||
</div>
|
</div>
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="product_packaging"
|
|
||||||
context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'shop':parent.shop_id, 'uom':product_uom}" on_change="product_packaging_change(parent.pricelist_id, product_id, product_uom_qty, product_uom, parent.partner_id, product_packaging, True, context)"
|
|
||||||
domain="[('product_id','=',product_id)]" groups="product.group_stock_packaging"
|
|
||||||
colspan="3"/>
|
|
||||||
<field name="tax_id" widget="many2many_tags" domain="[('parent_id','=',False),('type_tax_use','<>','purchase')]"/>
|
<field name="tax_id" widget="many2many_tags" domain="[('parent_id','=',False),('type_tax_use','<>','purchase')]"/>
|
||||||
<label for="delay"/>
|
|
||||||
<div>
|
|
||||||
<field name="delay" class="oe_inline"/> days
|
|
||||||
</div>
|
|
||||||
<field name="type"/>
|
|
||||||
<field name="th_weight"/>
|
<field name="th_weight"/>
|
||||||
|
|
||||||
<!-- we should put a config wizard for these two fields -->
|
<!-- we should put a config wizard for these two fields -->
|
||||||
<field name="address_allotment_id"/>
|
<field name="address_allotment_id"/>
|
||||||
<field name="property_ids" widget="many2many_tags"
|
|
||||||
groups="sale.group_mrp_properties"/>
|
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
<label for="name"/>
|
<label for="name"/>
|
||||||
|
@ -254,22 +235,17 @@
|
||||||
<div groups="base.group_no_one">
|
<div groups="base.group_no_one">
|
||||||
<label for="invoice_lines"/>
|
<label for="invoice_lines"/>
|
||||||
<field name="invoice_lines"/>
|
<field name="invoice_lines"/>
|
||||||
<label for="move_ids"/>
|
|
||||||
<field name="move_ids" widget="many2many"/>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<tree string="Sales Order Lines" editable="bottom">
|
<tree string="Sales Order Lines" editable="bottom">
|
||||||
<field name="sequence" widget="handle"/>
|
<field name="sequence" widget="handle"/>
|
||||||
<field name="state" invisible="1"/>
|
<field name="state" invisible="1"/>
|
||||||
<field name="delay" invisible="1"/>
|
|
||||||
<field name="th_weight" invisible="1"/>
|
<field name="th_weight" invisible="1"/>
|
||||||
<field name="product_packaging" invisible="1"/>
|
|
||||||
<field name="product_id"
|
<field name="product_id"
|
||||||
context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'shop':parent.shop_id, 'uom':product_uom}"
|
context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'shop':parent.shop_id, 'uom':product_uom}"
|
||||||
groups="base.group_user"
|
groups="base.group_user"
|
||||||
on_change="product_id_change(parent.pricelist_id, product_id, product_uom_qty, product_uom, product_uos_qty, product_uos, name, parent.partner_id, False, True, parent.date_order, False, parent.fiscal_position, False, context)"/>
|
on_change="product_id_change(parent.pricelist_id, product_id, product_uom_qty, product_uom, product_uos_qty, product_uos, name, parent.partner_id, False, True, parent.date_order, False, parent.fiscal_position, False, context)"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="type" invisible="1"/>
|
|
||||||
<field name="product_uom_qty"
|
<field name="product_uom_qty"
|
||||||
context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'shop':parent.shop_id, 'uom':product_uom}"
|
context="{'partner_id':parent.partner_id, 'quantity':product_uom_qty, 'pricelist':parent.pricelist_id, 'shop':parent.shop_id, 'uom':product_uom}"
|
||||||
on_change="product_id_change(parent.pricelist_id, product_id, product_uom_qty, product_uom, product_uos_qty, product_uos, name, parent.partner_id, False, False, parent.date_order, False, parent.fiscal_position, True, context)"/>
|
on_change="product_id_change(parent.pricelist_id, product_id, product_uom_qty, product_uom, product_uos_qty, product_uos, name, parent.partner_id, False, False, parent.date_order, False, parent.fiscal_position, True, context)"/>
|
||||||
|
@ -302,13 +278,7 @@
|
||||||
</page>
|
</page>
|
||||||
<page string="Other Information" groups="base.group_user">
|
<page string="Other Information" groups="base.group_user">
|
||||||
<group>
|
<group>
|
||||||
<group name="logistics">
|
<group name="sales_person" groups="base.group_user">
|
||||||
<field name="incoterm" widget="selection" groups="base.group_user"/>
|
|
||||||
<field name="picking_policy" required="True"/>
|
|
||||||
<field name="order_policy" on_change="shipping_policy_change(order_policy)"/>
|
|
||||||
<field name="invoice_quantity" invisible="True"/>
|
|
||||||
</group>
|
|
||||||
<group groups="base.group_user">
|
|
||||||
<field name="user_id"/>
|
<field name="user_id"/>
|
||||||
<field groups="base.group_no_one" name="origin"/>
|
<field groups="base.group_no_one" name="origin"/>
|
||||||
</group>
|
</group>
|
||||||
|
@ -319,7 +289,6 @@
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="invoiced"/>
|
<field name="invoiced"/>
|
||||||
<field name="shipped"/>
|
|
||||||
<field name="invoice_exists" invisible="1"/>
|
<field name="invoice_exists" invisible="1"/>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
|
@ -337,16 +306,6 @@
|
||||||
<field name="state"/>
|
<field name="state"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
<separator string="Delivery Orders"/>
|
|
||||||
<field name="picking_ids" context="{'default_type': 'out'}">
|
|
||||||
<tree colors="blue:state == 'draft';grey:state == 'cancel';red:state not in ('cancel', 'done') and min_date < current_date" string="Delivery Orders">
|
|
||||||
<field name="name"/>
|
|
||||||
<field name="partner_id" string="Customer"/>
|
|
||||||
<field name="min_date"/>
|
|
||||||
<field name="state"/>
|
|
||||||
<button name="action_process" states="assigned" string="Deliver" type="object" icon="gtk-go-forward" context="{'default_type': 'out'}"/>
|
|
||||||
</tree>
|
|
||||||
</field>
|
|
||||||
</page>
|
</page>
|
||||||
</notebook>
|
</notebook>
|
||||||
</sheet>
|
</sheet>
|
||||||
|
@ -515,9 +474,9 @@
|
||||||
<form string="Sales Order Lines" version="7.0">
|
<form string="Sales Order Lines" version="7.0">
|
||||||
<header>
|
<header>
|
||||||
<span groups="base.group_user">
|
<span groups="base.group_user">
|
||||||
<button name="button_cancel" string="Cancel" type="object" icon="gtk-cancel" states="confirmed,exception"/>
|
<button name="button_cancel" string="Cancel" type="object" states="confirmed,exception"/>
|
||||||
<button name="%(action_view_sale_order_line_make_invoice)d" string="Create Invoice" type="action" states="done" icon="gtk-go-forward" attrs="{'invisible': [('invoiced', '=', 1)]}" class="oe_highlight"/>
|
<button name="%(action_view_sale_order_line_make_invoice)d" string="Create Invoice" type="action" attrs="{'invisible': ['|',('invoiced', '=', 1), ('state', 'not in', ('confirmed', 'draft'))]}" class="oe_highlight"/>
|
||||||
<button name="button_done" string="Done" type="object" states="confirmed,exception" icon="gtk-go-forward" class="oe_highlight"/>
|
<button name="button_done" string="Done" type="object" attrs="{'invisible': ['|',('invoiced', '=', 0), ('state', 'not in', ('confirmed', 'exception'))]}" class="oe_highlight"/>
|
||||||
</span>
|
</span>
|
||||||
<field name="state" widget="statusbar" statusbar_visible="draft,confirmed,done" statusbar_colors='{"exception":"red","cancel":"red"}'/>
|
<field name="state" widget="statusbar" statusbar_visible="draft,confirmed,done" statusbar_colors='{"exception":"red","cancel":"red"}'/>
|
||||||
</header>
|
</header>
|
||||||
|
|
|
@ -13,12 +13,14 @@
|
||||||
<field name="flow_start">True</field>
|
<field name="flow_start">True</field>
|
||||||
<field name="name">draft</field>
|
<field name="name">draft</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="act_sent" model="workflow.activity">
|
<record id="act_sent" model="workflow.activity">
|
||||||
<field name="wkf_id" ref="wkf_sale"/>
|
<field name="wkf_id" ref="wkf_sale"/>
|
||||||
<field name="name">sent</field>
|
<field name="name">sent</field>
|
||||||
<field name="kind">function</field>
|
<field name="kind">function</field>
|
||||||
<field name="action">write({'state':'sent'})</field>
|
<field name="action">write({'state':'sent'})</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="act_router" model="workflow.activity">
|
<record id="act_router" model="workflow.activity">
|
||||||
<field name="wkf_id" ref="wkf_sale"/>
|
<field name="wkf_id" ref="wkf_sale"/>
|
||||||
<field name="name">router</field>
|
<field name="name">router</field>
|
||||||
|
@ -26,23 +28,21 @@
|
||||||
<field name="action">action_wait()</field>
|
<field name="action">action_wait()</field>
|
||||||
<field name="split_mode">OR</field>
|
<field name="split_mode">OR</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="act_wait_invoice" model="workflow.activity">
|
<record id="act_wait_invoice" model="workflow.activity">
|
||||||
<field name="wkf_id" ref="wkf_sale"/>
|
<field name="wkf_id" ref="wkf_sale"/>
|
||||||
<field name="name">wait_invoice</field>
|
<field name="name">wait_invoice</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="act_wait_ship" model="workflow.activity">
|
|
||||||
<field name="wkf_id" ref="wkf_sale"/>
|
|
||||||
<field name="name">wait_ship</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="act_done" model="workflow.activity">
|
<record id="act_done" model="workflow.activity">
|
||||||
<field name="wkf_id" ref="wkf_sale"/>
|
<field name="wkf_id" ref="wkf_sale"/>
|
||||||
<field name="name">done</field>
|
<field name="name">done</field>
|
||||||
<field name="flow_stop">True</field>
|
<field name="flow_stop">True</field>
|
||||||
<field name="kind">function</field>
|
<field name="kind">function</field>
|
||||||
<field name="action">write({'state':'done'})</field>
|
<field name="action">action_done()</field>
|
||||||
<field name="join_mode">AND</field>
|
<field name="join_mode">AND</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="act_cancel" model="workflow.activity">
|
<record id="act_cancel" model="workflow.activity">
|
||||||
<field name="wkf_id" ref="wkf_sale"/>
|
<field name="wkf_id" ref="wkf_sale"/>
|
||||||
<field name="name">cancel</field>
|
<field name="name">cancel</field>
|
||||||
|
@ -50,6 +50,7 @@
|
||||||
<field name="kind">stopall</field>
|
<field name="kind">stopall</field>
|
||||||
<field name="action">action_cancel()</field>
|
<field name="action">action_cancel()</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="act_cancel2" model="workflow.activity">
|
<record id="act_cancel2" model="workflow.activity">
|
||||||
<field name="wkf_id" ref="wkf_sale"/>
|
<field name="wkf_id" ref="wkf_sale"/>
|
||||||
<field name="name">cancel2</field>
|
<field name="name">cancel2</field>
|
||||||
|
@ -57,13 +58,7 @@
|
||||||
<field name="kind">stopall</field>
|
<field name="kind">stopall</field>
|
||||||
<field name="action">action_cancel()</field>
|
<field name="action">action_cancel()</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="act_cancel3" model="workflow.activity">
|
|
||||||
<field name="wkf_id" ref="wkf_sale"/>
|
|
||||||
<field name="name">cancel3</field>
|
|
||||||
<field name="flow_stop">True</field>
|
|
||||||
<field name="kind">stopall</field>
|
|
||||||
<field name="action">action_cancel()</field>
|
|
||||||
</record>
|
|
||||||
<record id="act_invoice" model="workflow.activity">
|
<record id="act_invoice" model="workflow.activity">
|
||||||
<field name="wkf_id" ref="wkf_sale"/>
|
<field name="wkf_id" ref="wkf_sale"/>
|
||||||
<field name="name">invoice</field>
|
<field name="name">invoice</field>
|
||||||
|
@ -90,121 +85,53 @@
|
||||||
<field name="kind">stopall</field>
|
<field name="kind">stopall</field>
|
||||||
<field name="action">action_cancel()</field>
|
<field name="action">action_cancel()</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="act_ship" model="workflow.activity">
|
|
||||||
<field name="wkf_id" ref="wkf_sale"/>
|
|
||||||
<field name="name">ship</field>
|
|
||||||
<field name="kind">function</field>
|
|
||||||
<field name="action">action_ship_create()</field>
|
|
||||||
</record>
|
|
||||||
<record id="act_ship_except" model="workflow.activity">
|
|
||||||
<field name="wkf_id" ref="wkf_sale"/>
|
|
||||||
<field name="name">ship_except</field>
|
|
||||||
<field name="kind">function</field>
|
|
||||||
<field name="action">write({'state':'shipping_except'})</field>
|
|
||||||
</record>
|
|
||||||
<record id="act_ship_end" model="workflow.activity">
|
|
||||||
<field name="wkf_id" ref="wkf_sale"/>
|
|
||||||
<field name="name">ship_end</field>
|
|
||||||
<field name="kind">function</field>
|
|
||||||
<field name="action">action_ship_end()</field>
|
|
||||||
</record>
|
|
||||||
<record id="act_ship_cancel" model="workflow.activity">
|
|
||||||
<field name="wkf_id" ref="wkf_sale"/>
|
|
||||||
<field name="name">ship_cancel</field>
|
|
||||||
<field name="flow_stop">True</field>
|
|
||||||
<field name="kind">stopall</field>
|
|
||||||
<field name="action">action_cancel()</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<!-- Transistion -->
|
<!-- Transistion -->
|
||||||
|
|
||||||
<record id="trans_invoice_end_done" model="workflow.transition">
|
|
||||||
<field name="act_from" ref="act_invoice_end"/>
|
|
||||||
<field name="act_to" ref="act_done"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="trans_draft_router" model="workflow.transition">
|
|
||||||
<field name="act_from" ref="act_draft"/>
|
|
||||||
<field name="act_to" ref="act_router"/>
|
|
||||||
<field name="signal">order_confirm</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="trans_draft_sent" model="workflow.transition">
|
<record id="trans_draft_sent" model="workflow.transition">
|
||||||
<field name="act_from" ref="act_draft"/>
|
<field name="act_from" ref="act_draft"/>
|
||||||
<field name="act_to" ref="act_sent"/>
|
<field name="act_to" ref="act_sent"/>
|
||||||
<field name="signal">quotation_sent</field>
|
<field name="signal">quotation_sent</field>
|
||||||
</record>
|
</record>
|
||||||
|
<record id="trans_draft_router" model="workflow.transition">
|
||||||
<record id="trans_sent_cancel" model="workflow.transition">
|
<field name="act_from" ref="act_draft"/>
|
||||||
<field name="act_from" ref="act_sent"/>
|
|
||||||
<field name="act_to" ref="act_cancel"/>
|
|
||||||
<field name="signal">cancel</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="trans_sent_router" model="workflow.transition">
|
|
||||||
<field name="act_from" ref="act_sent"/>
|
|
||||||
<field name="act_to" ref="act_router"/>
|
<field name="act_to" ref="act_router"/>
|
||||||
<field name="signal">order_confirm</field>
|
<field name="signal">order_confirm</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="trans_draft_cancel" model="workflow.transition">
|
<record id="trans_draft_cancel" model="workflow.transition">
|
||||||
<field name="act_from" ref="act_draft"/>
|
<field name="act_from" ref="act_draft"/>
|
||||||
<field name="act_to" ref="act_cancel"/>
|
<field name="act_to" ref="act_cancel"/>
|
||||||
<field name="signal">cancel</field>
|
<field name="signal">cancel</field>
|
||||||
</record>
|
</record>
|
||||||
|
<record id="trans_sent_router" model="workflow.transition">
|
||||||
|
<field name="act_from" ref="act_sent"/>
|
||||||
|
<field name="act_to" ref="act_router"/>
|
||||||
|
<field name="signal">order_confirm</field>
|
||||||
|
</record>
|
||||||
|
<record id="trans_sent_cancel" model="workflow.transition">
|
||||||
|
<field name="act_from" ref="act_sent"/>
|
||||||
|
<field name="act_to" ref="act_cancel"/>
|
||||||
|
<field name="signal">cancel</field>
|
||||||
|
</record>
|
||||||
|
<record id="trans_router_wait_invoice" model="workflow.transition">
|
||||||
|
<field name="act_from" ref="act_router"/>
|
||||||
|
<field name="act_to" ref="act_wait_invoice"/>
|
||||||
|
</record>
|
||||||
<record id="trans_wait_invoice_all_lines_invoiced" model="workflow.transition">
|
<record id="trans_wait_invoice_all_lines_invoiced" model="workflow.transition">
|
||||||
<field name="act_from" ref="act_wait_invoice"/>
|
<field name="act_from" ref="act_wait_invoice"/>
|
||||||
<field name="act_to" ref="act_invoice_end"/>
|
<field name="act_to" ref="act_invoice_end"/>
|
||||||
<field name="signal">all_lines</field>
|
<field name="signal">all_lines</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="trans_router_wait_invoice_shipping" model="workflow.transition">
|
|
||||||
<field name="act_from" ref="act_wait_invoice"/>
|
|
||||||
<field name="act_to" ref="act_invoice_end"/>
|
|
||||||
<field name="condition">(order_policy=='picking')</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="trans_router_wait_invoice" model="workflow.transition">
|
|
||||||
<field name="act_from" ref="act_router"/>
|
|
||||||
<field name="act_to" ref="act_wait_invoice"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="trans_router_wait_ship" model="workflow.transition">
|
|
||||||
<field name="act_from" ref="act_router"/>
|
|
||||||
<field name="act_to" ref="act_wait_ship"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="trans_wait_invoice_cancel2" model="workflow.transition">
|
<record id="trans_wait_invoice_cancel2" model="workflow.transition">
|
||||||
<field name="act_from" ref="act_wait_invoice"/>
|
<field name="act_from" ref="act_wait_invoice"/>
|
||||||
<field name="act_to" ref="act_cancel2"/>
|
<field name="act_to" ref="act_cancel2"/>
|
||||||
<field name="signal">cancel</field>
|
<field name="signal">cancel</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="trans_wait_ship_cancel3" model="workflow.transition">
|
|
||||||
<field name="act_from" ref="act_wait_ship"/>
|
|
||||||
<field name="act_to" ref="act_cancel3"/>
|
|
||||||
<field name="signal">cancel</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="trans_wait_ship_ship" model="workflow.transition">
|
|
||||||
<field name="act_from" ref="act_wait_ship"/>
|
|
||||||
<field name="act_to" ref="act_ship"/>
|
|
||||||
<field name="condition">(order_policy!='prepaid') or invoiced</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="trans_wait_invoice_invoice" model="workflow.transition">
|
|
||||||
<field name="act_from" ref="act_wait_invoice"/>
|
|
||||||
<field name="act_to" ref="act_invoice"/>
|
|
||||||
<field name="condition">order_policy=='prepaid'</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="trans_wait_invoice_invoice_manual" model="workflow.transition">
|
<record id="trans_wait_invoice_invoice_manual" model="workflow.transition">
|
||||||
<field name="act_from" ref="act_wait_invoice"/>
|
<field name="act_from" ref="act_wait_invoice"/>
|
||||||
<field name="act_to" ref="act_invoice"/>
|
<field name="act_to" ref="act_invoice"/>
|
||||||
<field name="signal">manual_invoice</field>
|
<field name="signal">manual_invoice</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="trans_invoice_invoice_end" model="workflow.transition">
|
<record id="trans_invoice_invoice_end" model="workflow.transition">
|
||||||
<field name="act_from" ref="act_invoice"/>
|
<field name="act_from" ref="act_invoice"/>
|
||||||
<field name="act_to" ref="act_invoice_end"/>
|
<field name="act_to" ref="act_invoice_end"/>
|
||||||
|
@ -230,38 +157,10 @@
|
||||||
<field name="act_to" ref="act_invoice_cancel"/>
|
<field name="act_to" ref="act_invoice_cancel"/>
|
||||||
<field name="signal">invoice_cancel</field>
|
<field name="signal">invoice_cancel</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="trans_ship_end_done" model="workflow.transition">
|
<record id="trans_invoice_end_done" model="workflow.transition">
|
||||||
<field name="act_from" ref="act_ship_end"/>
|
<field name="act_from" ref="act_invoice_end"/>
|
||||||
<field name="act_to" ref="act_done"/>
|
<field name="act_to" ref="act_done"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="trans_ship_ship_end" model="workflow.transition">
|
|
||||||
<field name="act_from" ref="act_ship"/>
|
|
||||||
<field name="act_to" ref="act_ship_end"/>
|
|
||||||
<field name="trigger_model">procurement.order</field>
|
|
||||||
<field name="trigger_expr_id">procurement_lines_get()</field>
|
|
||||||
<field name="condition">test_state('finished')</field>
|
|
||||||
</record>
|
|
||||||
<record id="trans_ship_ship_except" model="workflow.transition">
|
|
||||||
<field name="act_from" ref="act_ship"/>
|
|
||||||
<field name="act_to" ref="act_ship_except"/>
|
|
||||||
<field name="condition">test_state('canceled')</field>
|
|
||||||
</record>
|
|
||||||
<record id="trans_ship_except_ship" model="workflow.transition">
|
|
||||||
<field name="act_from" ref="act_ship_except"/>
|
|
||||||
<field name="act_to" ref="act_ship"/>
|
|
||||||
<field name="signal">ship_recreate</field>
|
|
||||||
</record>
|
|
||||||
<record id="trans_ship_except_ship_end" model="workflow.transition">
|
|
||||||
<field name="act_from" ref="act_ship_except"/>
|
|
||||||
<field name="act_to" ref="act_ship_end"/>
|
|
||||||
<field name="signal">ship_corrected</field>
|
|
||||||
</record>
|
|
||||||
<record id="trans_ship_except_ship_cancel" model="workflow.transition">
|
|
||||||
<field name="act_from" ref="act_ship_except"/>
|
|
||||||
<field name="act_to" ref="act_ship_cancel"/>
|
|
||||||
<field name="signal">ship_cancel</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</openerp>
|
</openerp>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue