diff --git a/addons/account/partner.py b/addons/account/partner.py
index f582da6b765..a7df31b2f32 100644
--- a/addons/account/partner.py
+++ b/addons/account/partner.py
@@ -189,44 +189,34 @@ class res_partner(osv.osv):
'debit': fields.function(_credit_debit_get, fnct_search=_debit_search, string='Total Payable', multi='dc', help="Total amount you have to pay to this supplier."),
'debit_limit': fields.float('Payable Limit'),
'property_account_payable': fields.property(
- 'account.account',
type='many2one',
relation='account.account',
string="Account Payable",
- view_load=True,
domain="[('type', '=', 'payable')]",
help="This account will be used instead of the default one as the payable account for the current partner",
required=True),
'property_account_receivable': fields.property(
- 'account.account',
type='many2one',
relation='account.account',
string="Account Receivable",
- view_load=True,
domain="[('type', '=', 'receivable')]",
help="This account will be used instead of the default one as the receivable account for the current partner",
required=True),
'property_account_position': fields.property(
- 'account.fiscal.position',
type='many2one',
relation='account.fiscal.position',
string="Fiscal Position",
- view_load=True,
help="The fiscal position will determine taxes and accounts used for the partner.",
),
'property_payment_term': fields.property(
- 'account.payment.term',
type='many2one',
relation='account.payment.term',
string ='Customer Payment Term',
- view_load=True,
help="This payment term will be used instead of the default one for sale orders and customer invoices"),
'property_supplier_payment_term': fields.property(
- 'account.payment.term',
type='many2one',
relation='account.payment.term',
string ='Supplier Payment Term',
- view_load=True,
help="This payment term will be used instead of the default one for purchase orders and supplier invoices"),
'ref_companies': fields.one2many('res.company', 'partner_id',
'Companies that refers to partner'),
diff --git a/addons/account/product.py b/addons/account/product.py
index 3df3ad9bd17..b7bffee43a9 100644
--- a/addons/account/product.py
+++ b/addons/account/product.py
@@ -25,18 +25,14 @@ class product_category(osv.osv):
_inherit = "product.category"
_columns = {
'property_account_income_categ': fields.property(
- 'account.account',
type='many2one',
relation='account.account',
string="Income Account",
- view_load=True,
help="This account will be used for invoices to value sales."),
'property_account_expense_categ': fields.property(
- 'account.account',
type='many2one',
relation='account.account',
string="Expense Account",
- view_load=True,
help="This account will be used for invoices to value expenses."),
}
@@ -54,18 +50,14 @@ class product_template(osv.osv):
'product_supplier_taxes_rel', 'prod_id', 'tax_id',
'Supplier Taxes', domain=[('parent_id', '=', False),('type_tax_use','in',['purchase','all'])]),
'property_account_income': fields.property(
- 'account.account',
type='many2one',
relation='account.account',
string="Income Account",
- view_load=True,
help="This account will be used for invoices instead of the default one to value sales for the current product."),
'property_account_expense': fields.property(
- 'account.account',
type='many2one',
relation='account.account',
string="Expense Account",
- view_load=True,
help="This account will be used for invoices instead of the default one to value expenses for the current product."),
}
diff --git a/addons/account_anglo_saxon/__openerp__.py b/addons/account_anglo_saxon/__openerp__.py
index 7ac4bdbd71e..4fc15bba4f5 100644
--- a/addons/account_anglo_saxon/__openerp__.py
+++ b/addons/account_anglo_saxon/__openerp__.py
@@ -44,7 +44,7 @@ account.""",
'category': 'Accounting & Finance',
'demo': [],
'data': ['product_view.xml'],
- 'test': ['test/anglo_saxon.yml'],
+ 'test': ['test/anglo_saxon.yml', 'test/anglo_saxon_avg_fifo.yml'],
'auto_install': False,
'installable': True,
}
diff --git a/addons/account_anglo_saxon/invoice.py b/addons/account_anglo_saxon/invoice.py
index f27d9b3ae72..8b31a48b92b 100644
--- a/addons/account_anglo_saxon/invoice.py
+++ b/addons/account_anglo_saxon/invoice.py
@@ -117,21 +117,27 @@ class account_invoice_line(osv.osv):
for line in res:
if a == line['account_id'] and i_line.product_id.id == line['product_id']:
uom = i_line.product_id.uos_id or i_line.product_id.uom_id
- standard_price = self.pool.get('product.uom')._compute_price(cr, uid, uom.id, i_line.product_id.standard_price, i_line.uos_id.id)
- if standard_price != i_line.price_unit and line['price_unit'] == i_line.price_unit and acc:
- price_diff = i_line.price_unit - standard_price
- line.update({'price':standard_price * line['quantity']})
+ valuation_price_unit = self.pool.get('product.uom')._compute_price(cr, uid, uom.id, i_line.product_id.standard_price, i_line.uos_id.id)
+ if i_line.product_id.cost_method != 'standard' and i_line.purchase_line_id:
+ #for average/fifo/lifo costing method, fetch real cost price from incomming moves
+ stock_move_obj = self.pool.get('stock.move')
+ valuation_stock_move = stock_move_obj.search(cr, uid, [('purchase_line_id', '=', i_line.purchase_line_id.id)], limit=1, context=context)
+ if valuation_stock_move:
+ valuation_price_unit = stock_move_obj.browse(cr, uid, valuation_stock_move[0], context=context).price_unit
+ if valuation_price_unit != i_line.price_unit and line['price_unit'] == i_line.price_unit and acc:
+ price_diff = i_line.price_unit - valuation_price_unit
+ line.update({'price': valuation_price_unit * line['quantity']})
diff_res.append({
- 'type':'src',
+ 'type': 'src',
'name': i_line.name[:64],
- 'price_unit':price_diff,
- 'quantity':line['quantity'],
+ 'price_unit': price_diff,
+ 'quantity': line['quantity'],
'price': price_diff * line['quantity'],
- 'account_id':acc,
- 'product_id':line['product_id'],
- 'uos_id':line['uos_id'],
- 'account_analytic_id':line['account_analytic_id'],
- 'taxes':line.get('taxes',[]),
+ 'account_id': acc,
+ 'product_id': line['product_id'],
+ 'uos_id': line['uos_id'],
+ 'account_analytic_id': line['account_analytic_id'],
+ 'taxes': line.get('taxes', []),
})
res += diff_res
return res
diff --git a/addons/account_anglo_saxon/product.py b/addons/account_anglo_saxon/product.py
index b52d9ed3bbd..1c9e8ee3673 100644
--- a/addons/account_anglo_saxon/product.py
+++ b/addons/account_anglo_saxon/product.py
@@ -24,27 +24,21 @@ class product_category(osv.osv):
_inherit = "product.category"
_columns = {
'property_account_creditor_price_difference_categ': fields.property(
- 'account.account',
type='many2one',
relation='account.account',
string="Price Difference Account",
- view_load=True,
help="This account will be used to value price difference between purchase price and cost price."),
#Redefine fields to change help text for anglo saxon methodology.
'property_account_income_categ': fields.property(
- 'account.account',
type='many2one',
relation='account.account',
string="Income Account",
- view_load=True,
help="This account will be used to value outgoing stock using sale price."),
'property_account_expense_categ': fields.property(
- 'account.account',
type='many2one',
relation='account.account',
string="Expense Account",
- view_load=True,
help="This account will be used to value outgoing stock using cost price."),
}
@@ -53,27 +47,21 @@ class product_template(osv.osv):
_inherit = "product.template"
_columns = {
'property_account_creditor_price_difference': fields.property(
- 'account.account',
type='many2one',
relation='account.account',
string="Price Difference Account",
- view_load=True,
help="This account will be used to value price difference between purchase price and cost price."),
#Redefine fields to change help text for anglo saxon methodology.
'property_account_income': fields.property(
- 'account.account',
type='many2one',
relation='account.account',
string="Income Account",
- view_load=True,
help="This account will be used to value outgoing stock using sale price."),
'property_account_expense': fields.property(
- 'account.account',
type='many2one',
relation='account.account',
string="Expense Account",
- view_load=True,
help="This account will be used to value outgoing stock using cost price."),
}
diff --git a/addons/account_anglo_saxon/purchase.py b/addons/account_anglo_saxon/purchase.py
index c10a2a97d80..fc36dab41c2 100644
--- a/addons/account_anglo_saxon/purchase.py
+++ b/addons/account_anglo_saxon/purchase.py
@@ -26,16 +26,15 @@ class purchase_order(osv.osv):
_inherit = "purchase.order"
_description = "Purchase Order"
- def _prepare_inv_line(self, cr, uid, account_id, order_line, context=None):
- line = super(purchase_order, self)._prepare_inv_line(cr, uid, account_id, order_line, context=context)
+ def _choose_account_from_po_line(self, cr, uid, order_line, context=None):
+ account_id = super(purchase_order, self)._choose_account_from_po_line(cr, uid, order_line, context=context)
if order_line.product_id and not order_line.product_id.type == 'service':
acc_id = order_line.product_id.property_stock_account_input and order_line.product_id.property_stock_account_input.id
if not acc_id:
acc_id = order_line.product_id.categ_id.property_stock_account_input_categ and order_line.product_id.categ_id.property_stock_account_input_categ.id
if acc_id:
fpos = order_line.order_id.fiscal_position or False
- new_account_id = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, acc_id)
- line.update({'account_id': new_account_id})
- return line
+ account_id = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, acc_id)
+ return account_id
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/account_anglo_saxon/test/anglo_saxon.yml b/addons/account_anglo_saxon/test/anglo_saxon.yml
index 9e46aa52b12..6e9ebc0068e 100644
--- a/addons/account_anglo_saxon/test/anglo_saxon.yml
+++ b/addons/account_anglo_saxon/test/anglo_saxon.yml
@@ -109,7 +109,7 @@
-
!record {model: purchase.order, id: purchase_order_001}:
partner_id: base.res_partner_3
- location_id: stock.stock_location_3
+ location_id: stock.stock_location_stock
pricelist_id: 1
order_line:
- product_id: product.product_product_3
@@ -128,12 +128,12 @@
partial_id = self.create(cr, uid, {},context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
self.do_partial(cr, uid, [partial_id])
-
- I check the Stock Interim account (Received) is credit successfully.
+ I check the Stock Interim account (Received) is credited successfully.
-
!assert {model: account.account, id : account_anglo_stock_input, string : Stock Interim account (Received) is not credited successfully.}:
- credit == 9
-
- I check the Stock valuation account is debit sucessfully.
+ I check the Stock valuation account is debited sucessfully.
-
!assert {model: account.account, id : account_anglo_stock_valuation, string : Stock valuation account is not debited successfully.}:
- debit == 9
@@ -192,7 +192,7 @@
invoice_state: 2binvoiced
move_lines:
- company_id: base.main_company
- location_id: stock.stock_location_3
+ location_id: stock.stock_location_stock
product_id: product.product_product_3
product_qty: 1.0
product_uom: product.product_uom_unit
diff --git a/addons/account_anglo_saxon/test/anglo_saxon_avg_fifo.yml b/addons/account_anglo_saxon/test/anglo_saxon_avg_fifo.yml
new file mode 100644
index 00000000000..f7d52f4f5a8
--- /dev/null
+++ b/addons/account_anglo_saxon/test/anglo_saxon_avg_fifo.yml
@@ -0,0 +1,304 @@
+-
+ In order to test anglo_saxon Configure Different Accounts.
+-
+ !record {model: account.account, id: account_anglo_stock_valuation_fifo}:
+ code: X3000f
+ name: Stock Valuation Account- (test)
+ parent_id: account.cas
+ type: other
+ user_type: account.data_account_type_asset
+-
+ Configure Stock Interim account (Received).
+-
+ !record {model: account.account, id: account_anglo_stock_input_fifo}:
+ code: X2800f
+ name: Stock Interim account (Received)
+ parent_id: account.cos
+ type: other
+ user_type: account.data_account_type_expense
+-
+ Configure Stock Interim account (Delivered).
+-
+ !record {model: account.account, id: account_anglo_stock_output_fifo}:
+ code: X2801f
+ name: Stock Interim account (Delivered)
+ parent_id: account.rev
+ type: other
+ user_type: account.data_account_type_income
+-
+ Configure Price difference creditor Account.
+-
+ !record {model: account.account, id: account_anglo_price_difference_fifo}:
+ code: X7095f
+ name: Price difference creditor Account
+ parent_id: account.cos
+ type: other
+ user_type: account.data_account_type_expense
+-
+ Configure Cash Bank Account.
+-
+ !record {model: account.account, id: account_anglo_cash_fifo}:
+ code: X5000f
+ name: Cash/Bank Account
+ parent_id: account.cash
+ type: other
+ user_type: account.data_account_type_asset
+-
+ Configure Creditor Account Payable.
+-
+ !record {model: account.account, id: account_anglo_payable_fifo}:
+ code: X440001f
+ name: Creditor Account Payable
+ parent_id: account.a_pay
+ type: other
+ user_type: account.data_account_type_payable
+-
+ Configure Debtor Account Receivable.
+-
+ !record {model: account.account, id: account_anglo_receivable_fifo}:
+ code: X400001f
+ name: Debtor Account Receivable
+ parent_id: account.a_recv
+ type: other
+ user_type: account.data_account_type_receivable
+-
+ Configure Cost of Good sale Account.
+-
+ !record {model: account.account, id: account_anglo_cogs_fifo}:
+ code: X7000f
+ name: Cost of goods sale account
+ parent_id: account.o_expense
+ type: other
+ user_type: account.data_account_type_expense
+-
+ Configure Income Account.
+-
+ !record {model: account.account, id: account_anglo_income_fifo}:
+ code: X8000f
+ name: Income Account
+ parent_id: account.o_income
+ type: other
+ user_type: account.data_account_type_income
+-
+ I configure the account receivable of supplier
+-
+ !record {model: res.partner, id: base.res_partner_3}:
+ property_account_payable: account_anglo_payable_fifo
+ property_account_receivable: account_anglo_receivable_fifo
+-
+ I configure the account receivable of Customer.
+-
+ !record {model: res.partner, id: base.res_partner_13}:
+ property_account_payable: account_anglo_payable_fifo
+ property_account_receivable: account_anglo_receivable_fifo
+-
+ I configure the product category with stock valuation account.
+-
+ !record {model: product.category, id: product.product_category_4}:
+ property_stock_valuation_account_id: account_anglo_stock_valuation_fifo
+-
+ I create a product with required accounts, and cost method average (but same applies for fifo)
+-
+ !record {model: product.product, id: product_fifo_anglo_saxon}:
+ name: 'FIFO product for anglo saxon tests'
+ list_price: 20.00
+ standard_price: 0
+ categ_id: product.product_category_4
+ valuation: 'real_time'
+ property_account_income: account_anglo_income_fifo
+ property_account_expense: account_anglo_cogs_fifo
+ property_account_creditor_price_difference: account_anglo_price_difference_fifo
+ property_stock_account_input: account_anglo_stock_input_fifo
+ property_stock_account_output: account_anglo_stock_output_fifo
+ cost_method: 'average'
+-
+ I create a draft Purchase Order.
+-
+ !record {model: purchase.order, id: purchase_order_001_fifo}:
+ partner_id: base.res_partner_3
+ location_id: stock.stock_location_stock
+ pricelist_id: 1
+ order_line:
+ - product_id: product_fifo_anglo_saxon
+ product_qty: 1
+ price_unit: 9
+ date_planned: '2013-08-31'
+ taxes_id: []
+-
+ I confirm the purchase order.
+-
+ !workflow {model: purchase.order, ref: purchase_order_001_fifo, action: purchase_confirm}
+-
+ Reception is ready for process so now done the reception.
+-
+ !python {model: stock.partial.picking}: |
+ pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_001_fifo")).picking_ids
+ partial_id = self.create(cr, uid, {},context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
+ self.do_partial(cr, uid, [partial_id])
+-
+ I check the Stock Interim account (Received) is credit successfully.
+-
+ !assert {model: account.account, id : account_anglo_stock_input_fifo, string : Stock Interim account (Received) is not credited successfully.}:
+ - credit == 9
+-
+ I check the Stock valuation account is debit sucessfully.
+-
+ !assert {model: account.account, id : account_anglo_stock_valuation_fifo, string : Stock valuation account is not debited successfully.}:
+ - debit == 9
+-
+ I Validate Invoice of Purchase Order after having changed the price to 10.
+-
+ !python {model: purchase.order}: |
+ invoice_ids = [x.id for x in self.browse(cr, uid, ref("purchase_order_001_fifo")).invoice_ids]
+ line_ids = self.pool.get('account.invoice.line').search(cr, uid, [('invoice_id', 'in', invoice_ids)])
+ self.pool.get('account.invoice.line').write(cr, uid, line_ids, {'price_unit': 10})
+ self.pool.get('account.invoice').signal_invoice_open(cr, uid, invoice_ids)
+-
+ I check the Stock Interim account (Received) is debited sucessfully when Invoice validated.
+-
+ !assert {model: account.account, id : account_anglo_stock_input_fifo, string : Stock Interim account (Received) is not debited successfully.}:
+ - debit == 9
+-
+ I check the Price difference creditor Account is debited sucessfully when Invoice validated.
+-
+ !assert {model: account.account, id : account_anglo_price_difference_fifo, string : Price difference creditor Account is not debited successfully.}:
+ - debit == 1
+-
+ I check Payable(creditor) Account is Credited sucessfully when Invoice validated.
+-
+ !assert {model: account.account, id : account_anglo_payable_fifo, string : Payable(creditor) Account is not Credited successfully.}:
+ - credit == 10
+-
+ I pay the invoice.
+-
+ !python {model: purchase.order}: |
+ invoice_ids = self.browse(cr, uid, ref("purchase_order_001_fifo")).invoice_ids
+ order = self.browse(cr, uid, ref("purchase_order_001_fifo"))
+ journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', order.company_id.id)], limit=1)
+ for invoice in invoice_ids:
+ invoice.pay_and_reconcile(invoice.amount_total, ref('account_anglo_cash_fifo'), ref('account.period_8'), journal_ids[0], ref('account_anglo_cash_fifo'), ref('account.period_8'), journal_ids[0], name='test')
+-
+ I check Payable(Creditors) Account is Debited sucessfully after invoice paid.
+-
+ !assert {model: account.account, id : account_anglo_payable_fifo, string : Payable(Creditors) Account is not Debited successfully.}:
+ - debit == 10
+-
+ I check Bank/Cash account is credited sucessfully after invoice paid.
+-
+ !assert {model: account.account, id : account_anglo_cash_fifo, string: Bank/Cash account is not credited successfully.}:
+ - credit == 10
+-
+ I create an Outgoing Picking order
+-
+ !record {model: stock.picking, id: stock_picking_out001_fifo}:
+ partner_id: base.res_partner_13
+ invoice_state: 2binvoiced
+ move_lines:
+ - company_id: base.main_company
+ location_id: stock.stock_location_stock
+ product_id: product_fifo_anglo_saxon
+ product_qty: 1.0
+ location_dest_id: stock.stock_location_customers
+ move_type: direct
+ type: out
+-
+ I need to check the availability of the product, So I make my picking order for processing later.
+-
+ !python {model: stock.picking}: |
+ self.draft_force_assign(cr, uid, [ref("stock_picking_out001_fifo")], {"lang": "en_US", "search_default_available":
+ 1, "tz": False, "active_model": "ir.ui.menu", "contact_display": "partner",
+ "active_ids": [ref("stock.menu_action_picking_tree")], "active_id": ref("stock.menu_action_picking_tree"),
+ })
+-
+ I check the product availability, Product is available in the stock and ready to be sent.
+-
+ !python {model: stock.picking}: |
+ self.action_assign(cr, uid, [ref("stock_picking_out001_fifo")], {"lang": "en_US", "search_default_available":
+ 1, "tz": False, "active_model": "ir.ui.menu", "contact_display": "partner",
+ "active_ids": [ref("stock.menu_action_picking_tree")], "active_id": ref("stock.menu_action_picking_tree"),
+ })
+-
+ I process the delivery.
+-
+ !python {model: stock.partial.picking}: |
+ partial_id = self.create(cr, uid, {}, context={'active_model':'stock.picking','active_ids':[ref('stock_picking_out001_fifo')]})
+ self.do_partial(cr, uid, [partial_id])
+-
+ I check Stock Interim account (Delivery) is debited successfully.
+-
+ !assert {model: account.account, id : account_anglo_stock_output_fifo, string : Stock Interim account (Delivery) is not debited successfully.}:
+ - debit == 9
+-
+ I check the Stock valuation account is credited sucessfully.
+-
+ !assert {model: account.account, id : account_anglo_stock_valuation_fifo, string : Stock valuation account is not credited successfully.}:
+ - credit == 9
+-
+ As the Invoice state of the picking order is To be invoiced. I create invoice for my outgoing picking order.
+-
+ !python {model: stock.invoice.onshipping}: |
+ wiz_id = self.create(cr, uid, {'invoice_date': '2013-03-04', 'journal_id': ref('account.sales_journal')},
+ {'active_ids': [ref("stock_picking_out001_fifo")], "active_model": "stock.picking"})
+ self.create_invoice(cr, uid, [wiz_id], {"lang": "en_US",
+ "search_default_available": 1, "tz": False, "active_model": "stock.picking",
+ "contact_display": "partner", "active_ids": [ref("stock_picking_out001_fifo")], "active_id": ref("stock_picking_out001_fifo")})
+-
+ I check that the customer invoice is created successfully.
+-
+ !python {model: account.invoice}: |
+ partner_id = self.pool.get('stock.picking').browse(cr, uid, ref('stock_picking_out001_fifo')).partner_id.id
+ inv_ids = self.search(cr, uid, [('type','=','out_invoice'),('partner_id','=',partner_id)])
+ assert inv_ids, 'No Invoice is generated!'
+-
+ I open the Invoice.
+-
+ !python {model: stock.picking}: |
+ move_name = self.pool.get('stock.picking').browse(cr, uid, ref('stock_picking_out001_fifo')).name
+ account_invoice = self.pool.get('account.invoice').search(cr, uid, [('origin', '=', move_name)])
+ account_invoice_line = self.pool.get('account.invoice.line').search(cr, uid, [('invoice_id', 'in', account_invoice)])
+ self.pool.get('account.invoice.line').write(cr, uid, account_invoice_line, {'invoice_line_tax_id': [(6, 0, [])]})
+ self.pool.get('account.invoice').button_reset_taxes(cr, uid, account_invoice)
+ self.pool.get('account.invoice').signal_invoice_open(cr, uid, account_invoice)
+-
+ I check Income Account is Credited sucessfully when Invoice validated.
+-
+ !assert {model: account.account, id : account_anglo_income_fifo, string : Income Account is not Credited successfully.}:
+ - credit == 20
+-
+ I check Cost of goods sold account for debit.
+-
+ !assert {model: account.account, id : account_anglo_cogs_fifo, string : Cost of goods sale is not Debited successfully.}:
+ - debit == 9
+-
+ I check Stock Interim account (Delivery)
+-
+ !assert {model: account.account, id : account_anglo_stock_output_fifo, string : Stock Interim account (Delivery) is not credited successfully.}:
+ - credit == 9
+-
+ I check Receivable(Debtor) Account for debit.
+-
+ !assert {model: account.account, id : account_anglo_receivable_fifo, string : Receivable(Debtors) Account is not Debited successfully.}:
+ - debit == 20
+-
+ I pay the invoice.
+-
+ !python {model: account.invoice}: |
+ move_name = self.pool.get('stock.picking').browse(cr, uid, ref('stock_picking_out001_fifo')).name
+ account_invoice= self.pool.get('account.invoice').search(cr, uid, [('origin', '=', move_name)])
+ journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash')], limit=1)
+ pay = self.pay_and_reconcile(cr, uid, account_invoice,
+ 20.0, ref('account_anglo_cash_fifo'), ref('account.period_8'),
+ journal_ids[0], ref('account_anglo_cash_fifo'),
+ ref('account.period_8'), journal_ids[0],
+ name='Payment for test customer invoice')
+ assert (pay == True), "Incorrect Payment."
+-
+ I check Receivable(Debtor) Account for credit.
+-
+ !assert {model: account.account, id : account_anglo_receivable_fifo, string : Receivable(Debtors) Account is not Credited successfully.}:
+ - credit == 20
+-
+ I check Bank/Cash account is debited sucessfully after invoice paid.
+-
+ !assert {model: account.account, id : account_anglo_cash_fifo, string: Bank/Cash account is not successfully credited.}:
+ - debit == 20
diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py
index 62eb2e812cc..35a06871696 100644
--- a/addons/auth_oauth/controllers/main.py
+++ b/addons/auth_oauth/controllers/main.py
@@ -7,7 +7,8 @@ from werkzeug.exceptions import BadRequest
import openerp
from openerp import SUPERUSER_ID
-import openerp.addons.web.http as oeweb
+import openerp.addons.web.http as http
+from openerp.addons.web.http import request
from openerp.addons.web.controllers.main import db_monodb, set_cookie_and_redirect, login_and_redirect
from openerp.modules.registry import RegistryManager
@@ -18,7 +19,7 @@ _logger = logging.getLogger(__name__)
#----------------------------------------------------------
def fragment_to_query_string(func):
@functools.wraps(func)
- def wrapper(self, req, **kw):
+ def wrapper(self, **kw):
if not kw:
return """
"""
- return func(self, req, **kw)
+ return func(self, **kw)
return wrapper
#----------------------------------------------------------
# Controller
#----------------------------------------------------------
-class OAuthController(oeweb.Controller):
- _cp_path = '/auth_oauth'
+class OAuthController(http.Controller):
- @oeweb.jsonrequest
- def list_providers(self, req, dbname):
+ @http.route('/auth_oauth/list_providers', type='json', auth='none')
+ def list_providers(self, dbname):
try:
registry = RegistryManager.get(dbname)
with registry.cursor() as cr:
@@ -51,9 +51,9 @@ class OAuthController(oeweb.Controller):
l = []
return l
- @oeweb.httprequest
+ @http.route('/auth_oauth/signin', type='http', auth='none')
@fragment_to_query_string
- def signin(self, req, **kw):
+ def signin(self, **kw):
state = simplejson.loads(kw['state'])
dbname = state['d']
provider = state['p']
@@ -71,7 +71,7 @@ class OAuthController(oeweb.Controller):
url = '/#action=%s' % action
elif menu:
url = '/#menu_id=%s' % menu
- return login_and_redirect(req, *credentials, redirect_url=url)
+ return login_and_redirect(*credentials, redirect_url=url)
except AttributeError:
# auth_signup is not installed
_logger.error("auth_signup not installed on database %s: oauth sign up cancelled." % (dbname,))
@@ -88,14 +88,14 @@ class OAuthController(oeweb.Controller):
_logger.exception("OAuth2: %s" % str(e))
url = "/#action=login&oauth_error=2"
- return set_cookie_and_redirect(req, url)
+ return set_cookie_and_redirect(url)
- @oeweb.httprequest
- def oea(self, req, **kw):
+ @http.route('/auth_oauth/oea', type='http', auth='none')
+ def oea(self, **kw):
"""login user via OpenERP Account provider"""
dbname = kw.pop('db', None)
if not dbname:
- dbname = db_monodb(req)
+ dbname = db_monodb()
if not dbname:
return BadRequest()
@@ -105,7 +105,7 @@ class OAuthController(oeweb.Controller):
try:
model, provider_id = IMD.get_object_reference(cr, SUPERUSER_ID, 'auth_oauth', 'provider_openerp')
except ValueError:
- return set_cookie_and_redirect(req, '/?db=%s' % dbname)
+ return set_cookie_and_redirect('/?db=%s' % dbname)
assert model == 'auth.oauth.provider'
state = {
@@ -115,6 +115,6 @@ class OAuthController(oeweb.Controller):
}
kw['state'] = simplejson.dumps(state)
- return self.signin(req, **kw)
+ return self.signin(**kw)
# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py
index 924e1546862..8c61af1f03c 100644
--- a/addons/auth_signup/controllers/main.py
+++ b/addons/auth_signup/controllers/main.py
@@ -23,14 +23,15 @@ import logging
import openerp
from openerp.modules.registry import RegistryManager
from ..res_users import SignupError
+import openerp.addons.web.http as http
+from openerp.addons.web.http import request
_logger = logging.getLogger(__name__)
-class Controller(openerp.addons.web.http.Controller):
- _cp_path = '/auth_signup'
+class Controller(http.Controller):
- @openerp.addons.web.http.jsonrequest
- def get_config(self, req, dbname):
+ @http.route('/auth_signup/get_config', type='json', auth="none")
+ def get_config(self, dbname):
""" retrieve the module config (which features are enabled) for the login page """
registry = RegistryManager.get(dbname)
with registry.cursor() as cr:
@@ -41,8 +42,8 @@ class Controller(openerp.addons.web.http.Controller):
}
return config
- @openerp.addons.web.http.jsonrequest
- def retrieve(self, req, dbname, token):
+ @http.route('/auth_signup/retrieve', type='json', auth="user")
+ def retrieve(self, dbname, token):
""" retrieve the user info (name, login or email) corresponding to a signup token """
registry = RegistryManager.get(dbname)
with registry.cursor() as cr:
@@ -50,23 +51,23 @@ class Controller(openerp.addons.web.http.Controller):
user_info = res_partner.signup_retrieve_info(cr, openerp.SUPERUSER_ID, token)
return user_info
- @openerp.addons.web.http.jsonrequest
- def signup(self, req, dbname, token, **values):
+ @http.route('/auth_signup/signup', type='json', auth="user")
+ def signup(self, dbname, token, **values):
""" sign up a user (new or existing)"""
try:
- self._signup_with_values(req, dbname, token, values)
+ self._signup_with_values(dbname, token, values)
except SignupError, e:
return {'error': openerp.tools.exception_to_unicode(e)}
return {}
- def _signup_with_values(self, req, dbname, token, values):
+ def _signup_with_values(self, dbname, token, values):
registry = RegistryManager.get(dbname)
with registry.cursor() as cr:
res_users = registry.get('res.users')
res_users.signup(cr, openerp.SUPERUSER_ID, values, token)
- @openerp.addons.web.http.jsonrequest
- def reset_password(self, req, dbname, login):
+ @http.route('/auth_signup/reset_password', type='json', auth="user")
+ def reset_password(self, dbname, login):
""" retrieve user, and perform reset password """
registry = RegistryManager.get(dbname)
with registry.cursor() as cr:
diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py
index b8673e73927..44ada2ffcc0 100644
--- a/addons/crm/crm_lead.py
+++ b/addons/crm/crm_lead.py
@@ -719,7 +719,6 @@ class crm_lead(base_stage, format_address, osv.osv):
continue
vals = self._convert_opportunity_data(cr, uid, lead, customer, section_id, context=context)
self.write(cr, uid, [lead.id], vals, context=context)
- self.message_post(cr, uid, ids, body=_("Lead converted into an Opportunity "), subtype="crm.mt_lead_convert_to_opportunity", context=context)
if user_ids or section_id:
self.allocate_salesman(cr, uid, ids, user_ids, section_id, context=context)
diff --git a/addons/crm/crm_lead_data.xml b/addons/crm/crm_lead_data.xml
index 0979a94eb3f..92914542d9d 100644
--- a/addons/crm/crm_lead_data.xml
+++ b/addons/crm/crm_lead_data.xml
@@ -163,12 +163,6 @@
Opportunity created
-
- Lead to Opportunity
- crm.lead
-
- Lead converted into an opportunity
-
Stage Changed
crm.lead
@@ -195,13 +189,6 @@
section_id
-
- Lead to Opportunity
-
- crm.case.section
-
- section_id
-
Opportunity Stage Changed
crm.case.section
diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml
index 6ddd06c1c90..df6a4a07a8e 100644
--- a/addons/crm/crm_lead_view.xml
+++ b/addons/crm/crm_lead_view.xml
@@ -601,7 +601,9 @@
'default_email_to':'{$object.email or \'\'}',
'default_use_template': True,
'default_template_id': ref('crm.email_template_opportunity_mail'),
- }"/>
+ }"
+ groups="base.group_sale_salesman"
+ />
@@ -617,6 +619,7 @@
if context.get('active_model') == 'crm.lead' and context.get('active_ids'):
self.case_cancel(cr, uid, context['active_ids'], context=context)
+
diff --git a/addons/crm/i18n/hu.po b/addons/crm/i18n/hu.po
index 98313efb4f3..6673d2da235 100644
--- a/addons/crm/i18n/hu.po
+++ b/addons/crm/i18n/hu.po
@@ -7,14 +7,14 @@ msgstr ""
"Project-Id-Version: OpenERP Server 6.0dev\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-12-21 17:04+0000\n"
-"PO-Revision-Date: 2013-04-13 08:42+0000\n"
+"PO-Revision-Date: 2013-06-21 07:11+0000\n"
"Last-Translator: krnkris \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2013-04-14 05:12+0000\n"
-"X-Generator: Launchpad (build 16564)\n"
+"X-Launchpad-Export-Date: 2013-06-22 05:36+0000\n"
+"X-Generator: Launchpad (build 16677)\n"
#. module: crm
#: view:crm.lead.report:0
@@ -31,7 +31,7 @@ msgstr ""
"létrehozását a bejövő levelekből."
#. module: crm
-#: code:addons/crm/crm_lead.py:881
+#: code:addons/crm/crm_lead.py:898
#: selection:crm.case.stage,type:0
#: view:crm.lead:0
#: selection:crm.lead,type:0
@@ -192,8 +192,8 @@ msgstr ""
"direkt HTML formátumú ahhoz hogy beilleszthető legyen a kanban nézetekbe."
#. module: crm
-#: code:addons/crm/crm_lead.py:624
-#: code:addons/crm/crm_lead.py:744
+#: code:addons/crm/crm_lead.py:640
+#: code:addons/crm/crm_lead.py:761
#: code:addons/crm/crm_phonecall.py:280
#, python-format
msgid "Warning!"
@@ -304,7 +304,7 @@ msgid "Prospect Partner"
msgstr "Leendő partner"
#. module: crm
-#: code:addons/crm/crm_lead.py:982
+#: code:addons/crm/crm_lead.py:1002
#, python-format
msgid "No Subject"
msgstr "Nincs tárgy"
@@ -482,7 +482,7 @@ msgid "#Opportunities"
msgstr "Lehetőségek száma"
#. module: crm
-#: code:addons/crm/crm_lead.py:624
+#: code:addons/crm/crm_lead.py:640
#, python-format
msgid ""
"Please select more than one element (lead or opportunity) from the list view."
@@ -782,7 +782,7 @@ msgid "Statistics Dashboard"
msgstr "Statisztika vezérlőpult"
#. module: crm
-#: code:addons/crm/crm_lead.py:861
+#: code:addons/crm/crm_lead.py:878
#: model:crm.case.stage,name:crm.stage_lead2
#: selection:crm.case.stage,type:0
#: view:crm.lead:0
@@ -844,7 +844,7 @@ msgid "Exclusive"
msgstr "Kizárólagos"
#. module: crm
-#: code:addons/crm/crm_lead.py:584
+#: code:addons/crm/crm_lead.py:600
#, python-format
msgid "From %s : %s"
msgstr "Ettől %s : %s"
@@ -1016,7 +1016,7 @@ msgid "Next Action"
msgstr "Következő művelet"
#. module: crm
-#: code:addons/crm/crm_lead.py:763
+#: code:addons/crm/crm_lead.py:780
#, python-format
msgid "Partner set to %s ."
msgstr "Partner beállítva mint %s ."
@@ -1109,7 +1109,7 @@ msgid "Creation Date"
msgstr "Létrehozás dátuma"
#. module: crm
-#: code:addons/crm/crm_lead.py:698
+#: code:addons/crm/crm_lead.py:715
#, python-format
msgid "Lead converted into an Opportunity "
msgstr "Tervezet lehetőséggé átalakítva lehetőséggé "
@@ -1324,7 +1324,9 @@ msgid "Days to Close"
msgstr "Lezárásig hátralévő napok"
#. module: crm
+#: code:addons/crm/crm_lead.py:1057
#: field:crm.case.section,complete_name:0
+#, python-format
msgid "unknown"
msgstr "Ismeretlen"
@@ -1415,7 +1417,7 @@ msgid "Lead Description"
msgstr "Érdeklődés leírása"
#. module: crm
-#: code:addons/crm/crm_lead.py:565
+#: code:addons/crm/crm_lead.py:581
#, python-format
msgid "Merged opportunities"
msgstr "Lehetőségek összefésülése"
@@ -1989,7 +1991,7 @@ msgid "Leads"
msgstr "Érdeklődők"
#. module: crm
-#: code:addons/crm/crm_lead.py:563
+#: code:addons/crm/crm_lead.py:579
#, python-format
msgid "Merged leads"
msgstr "Össztefésült érdeklődések"
@@ -2085,7 +2087,6 @@ msgid "Global CC"
msgstr "Globális CC /másolat/"
#. module: crm
-#: view:crm.lead:0
#: view:crm.phonecall:0
#: model:ir.actions.act_window,name:crm.crm_case_categ_phone0
#: model:ir.ui.menu,name:crm.menu_crm_case_phone
@@ -2399,7 +2400,7 @@ msgstr "Érdeklődés átalakítva egy lehetőséggé"
#. module: crm
#: view:crm.lead:0
msgid "Unassigned Leads"
-msgstr "Nem iktatott rdeklődések"
+msgstr "Nem iktatott érdeklődések"
#. module: crm
#: model:mail.message.subtype,description:crm.mt_lead_won
@@ -3100,7 +3101,7 @@ msgid "Working Hours"
msgstr "Munkaórák"
#. module: crm
-#: code:addons/crm/crm_lead.py:968
+#: code:addons/crm/crm_lead.py:986
#: view:crm.lead:0
#: field:crm.lead2opportunity.partner,partner_id:0
#: field:crm.lead2opportunity.partner.mass,partner_id:0
diff --git a/addons/crm/wizard/crm_lead_to_opportunity_view.xml b/addons/crm/wizard/crm_lead_to_opportunity_view.xml
index 4093df910d0..9ddd1fc701f 100644
--- a/addons/crm/wizard/crm_lead_to_opportunity_view.xml
+++ b/addons/crm/wizard/crm_lead_to_opportunity_view.xml
@@ -102,7 +102,9 @@
res_model="crm.lead2opportunity.partner.mass" src_model="crm.lead"
view_mode="form" target="new" view_type="form"
context="{'mass_convert' : True}"
- view_id="view_crm_lead2opportunity_partner_mass"/>
+ view_id="view_crm_lead2opportunity_partner_mass"
+ groups="base.group_sale_salesman"
+ />
diff --git a/addons/crm/wizard/crm_merge_opportunities_view.xml b/addons/crm/wizard/crm_merge_opportunities_view.xml
index 919d83cb9a7..60693c13e19 100644
--- a/addons/crm/wizard/crm_merge_opportunities_view.xml
+++ b/addons/crm/wizard/crm_merge_opportunities_view.xml
@@ -45,7 +45,9 @@
multi="True"
key2="client_action_multi" name="Merge leads/opportunities"
res_model="crm.merge.opportunity" src_model="crm.lead"
- view_mode="form" target="new" view_type="form"/>
+ view_mode="form" target="new" view_type="form"
+ groups="base.group_sale_salesman"
+ />
diff --git a/addons/crm_partner_assign/__init__.py b/addons/crm_partner_assign/__init__.py
index bb4a3bb53be..6b1315cef07 100644
--- a/addons/crm_partner_assign/__init__.py
+++ b/addons/crm_partner_assign/__init__.py
@@ -20,6 +20,7 @@
##############################################################################
import crm_partner_assign
+import crm_lead
import wizard
import report
diff --git a/addons/crm_partner_assign/__openerp__.py b/addons/crm_partner_assign/__openerp__.py
index b9b21ca7a6a..37a8c5a3d6b 100644
--- a/addons/crm_partner_assign/__openerp__.py
+++ b/addons/crm_partner_assign/__openerp__.py
@@ -37,17 +37,23 @@ The most appropriate partner can be assigned.
You can also use the geolocalization without using the GPS coordinates.
""",
'author': 'OpenERP SA',
- 'depends': ['crm', 'account'],
+ 'depends': ['crm', 'account', 'portal'],
'demo': ['res_partner_demo.xml'],
'data': [
'security/ir.model.access.csv',
'res_partner_view.xml',
'wizard/crm_forward_to_partner_view.xml',
+ 'wizard/crm_channel_interested_view.xml',
'crm_lead_view.xml',
'crm_partner_assign_data.xml',
+ 'crm_portal_view.xml',
+ 'portal_data.xml',
'report/crm_lead_report_view.xml',
'report/crm_partner_report_view.xml',
],
+ 'js': [
+ 'static/src/js/next.js',
+ ],
'test': ['test/partner_assign.yml'],
'installable': True,
'auto_install': False,
diff --git a/addons/crm_partner_assign/crm_lead.py b/addons/crm_partner_assign/crm_lead.py
new file mode 100644
index 00000000000..37f4b9aedff
--- /dev/null
+++ b/addons/crm_partner_assign/crm_lead.py
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+from openerp.osv import osv
+from openerp.tools.translate import _
+
+
+class crm_lead(osv.osv):
+ _inherit = 'crm.lead'
+
+ def get_interested_action(self, cr, uid, interested, context=None):
+ try:
+ model, action_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'crm_partner_assign', 'crm_lead_channel_interested_act')
+ except ValueError:
+ raise osv.except_osv(_('Error!'), _("The CRM Channel Interested Action is missing"))
+ action = self.pool[model].read(cr, uid, action_id, context=context)
+ action_context = eval(action['context'])
+ action_context['interested'] = interested
+ action['context'] = str(action_context)
+ return action
+
+ def case_interested(self, cr, uid, ids, context=None):
+ return self.get_interested_action(cr, uid, True, context=context)
+
+ def case_disinterested(self, cr, uid, ids, context=None):
+ return self.get_interested_action(cr, uid, False, context=context)
diff --git a/addons/crm_partner_assign/crm_lead_view.xml b/addons/crm_partner_assign/crm_lead_view.xml
index 0d2837d6ca5..5c14680ee78 100644
--- a/addons/crm_partner_assign/crm_lead_view.xml
+++ b/addons/crm_partner_assign/crm_lead_view.xml
@@ -8,27 +8,33 @@
-
+
-
-
-
+
+
+
+
+ (
+
+ N
+ S
+
+ E
+ W
+ )
+
+
+
+
-
-
+ type="action"
+ context="{'default_composition_mode': 'forward','hide_forward_type': 1 , 'default_partner_ids': [partner_assigned_id]}"/>
-
-
-
-
-
-
@@ -43,7 +49,7 @@
-
+
@@ -55,41 +61,46 @@
-
-
+
-
+
crm.lead.lead.geo_assign.inherit
crm.lead
-
+
-
-
-
+
+
-
-
+ (
+
+ N
+ S
+
+ E
+ W
+ )
+
+
+
+
+
+
+ type="action"
+ context="{'default_composition_mode': 'forward','hide_forward_type': 1 , 'default_partner_ids': [partner_assigned_id]}"/>
-
-
-
-
-
-
@@ -104,7 +115,7 @@
-
+
@@ -116,12 +127,11 @@
-
-
+
diff --git a/addons/crm_partner_assign/crm_partner_assign.py b/addons/crm_partner_assign/crm_partner_assign.py
index b13a75a2591..daf3d844fe6 100644
--- a/addons/crm_partner_assign/crm_partner_assign.py
+++ b/addons/crm_partner_assign/crm_partner_assign.py
@@ -66,10 +66,13 @@ class res_partner_grade(osv.osv):
_columns = {
'sequence': fields.integer('Sequence'),
'active': fields.boolean('Active'),
- 'name': fields.char('Grade Name', size=32)
+ 'name': fields.char('Grade Name', size=32),
+ 'partner_weight': fields.integer('Grade Weight',
+ help="Gives the probability to assign a lead to this partner. (0 means no assignation.)"),
}
_defaults = {
- 'active': lambda *args: 1
+ 'active': lambda *args: 1,
+ 'partner_weight':1
}
class res_partner_activation(osv.osv):
@@ -88,11 +91,11 @@ class res_partner(osv.osv):
'partner_latitude': fields.float('Geo Latitude'),
'partner_longitude': fields.float('Geo Longitude'),
'date_localization': fields.date('Geo Localization Date'),
- 'partner_weight': fields.integer('Weight',
+ 'partner_weight': fields.integer('Grade Weight',
help="Gives the probability to assign a lead to this partner. (0 means no assignation.)"),
'opportunity_assigned_ids': fields.one2many('crm.lead', 'partner_assigned_id',\
'Assigned Opportunities'),
- 'grade_id': fields.many2one('res.partner.grade', 'Partner Level'),
+ 'grade_id': fields.many2one('res.partner.grade', 'Grade'),
'activation' : fields.many2one('res.partner.activation', 'Activation', select=1),
'date_partnership' : fields.date('Partnership Date'),
'date_review' : fields.date('Latest Partner Review'),
@@ -101,6 +104,13 @@ class res_partner(osv.osv):
_defaults = {
'partner_weight': lambda *args: 0
}
+
+ def onchange_grade_id(self, cr, uid, ids, grade_id, context=None):
+ res = {'value' :{'partner_weight':0}}
+ if grade_id:
+ partner_grade = self.pool.get('res.partner.grade').browse(cr, uid, grade_id)
+ res['value']['partner_weight'] = partner_grade.partner_weight
+ return res
def geo_localize(self, cr, uid, ids, context=None):
# Don't pass context to browse()! We need country names in english below
for partner in self.browse(cr, uid, ids):
@@ -124,7 +134,7 @@ class crm_lead(osv.osv):
_columns = {
'partner_latitude': fields.float('Geo Latitude'),
'partner_longitude': fields.float('Geo Longitude'),
- 'partner_assigned_id': fields.many2one('res.partner', 'Assigned Partner', help="Partner this case has been forwarded/assigned to.", select=True),
+ 'partner_assigned_id': fields.many2one('res.partner', 'Assigned Partner',track_visibility='onchange' , help="Partner this case has been forwarded/assigned to.", select=True),
'date_assign': fields.date('Assignation Date', help="Last date this case was forwarded/assigned to a partner"),
}
def _merge_data(self, cr, uid, ids, oldest, fields, context=None):
@@ -134,6 +144,7 @@ class crm_lead(osv.osv):
def onchange_assign_id(self, cr, uid, ids, partner_assigned_id, context=None):
"""This function updates the "assignation date" automatically, when manually assign a partner in the geo assign tab
"""
+
if not partner_assigned_id:
return {'value':{'date_assign': False}}
else:
@@ -261,4 +272,3 @@ class crm_lead(osv.osv):
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
diff --git a/addons/crm_partner_assign/crm_partner_assign_data.xml b/addons/crm_partner_assign/crm_partner_assign_data.xml
index dab50192641..b4347b1621b 100644
--- a/addons/crm_partner_assign/crm_partner_assign_data.xml
+++ b/addons/crm_partner_assign/crm_partner_assign_data.xml
@@ -1,44 +1,59 @@
-
+
-
- Lead forward
-
- Fwd: Lead: ${object.name}
-
-
-
+
+ Assigned
+
+
+
+ lead
+
+
+ To Recycle
+
+
+
+ lead
+
+
+ Lead Mass Mail
+
+ ${ctx['partner_id'].email}
+ ${user.email or ''}
+ Fwd: Lead: ${ctx['partner_id'].name}
-Here is a lead that might interest you.
-
-
-Please keep me informed about your actions about it so that I can keep an
-accurate follow-up of it and help you in the sale cycle.
-
-
-Your account manager,
-${object.user_id.name},
-${object.user_id.email}
-
+
+Hello,
-
-${ctx["mail_body"].replace('\n',' ') | safe}
-
-% if ctx["history_mode"] in ('whole'):
- % for message in object.message_ids:
- ---- Original Message (${message.date or ''}) ----
- ${message.body | safe}
- % endfor
+We have been contacted by those prospects that are in your region. Thus, the following leads have been assigned to ${ctx['partner_id'].name}:
+
+
+% for lead in ctx['partner_leads']:
+ ${lead.lead_id.name or 'Subject Undefined'} , ${lead.lead_id.contact_name or 'Contact Name Undefined'}, ${lead.lead_id.country_id and lead.lead_id.country_id.name or 'Country Undefined' }, ${lead.lead_id.email_from or 'Email Undefined'}, ${lead.lead_id.phone or ''}
+% endfor
+
+
+% if ctx.get('partner_in_portal'):
+Please connect to your Partner Portal to get details. On each lead are two buttons on the top left corner that you should press after having contacted the lead: "I'm interested" & "I'm not interested".
+% else:
+
+ You do not have yet a portal access to our database. Please contact
+ ${ctx['partner_id'].user_id and ctx['partner_id'].user_id.email and 'your account manager %s (%s)' % (ctx['partner_id'].user_id.name,ctx['partner_id'].user_id.email) or 'us'}.
+
% endif
-% if ctx['history_mode'] == 'latest':
- ---- Original Message (${object.message_ids[0].date or ''}) ----
- ${object.message_ids[0].body | safe}
+The lead will be sent to another partner if you do not contact the lead before 20 days.
+
+Thanks,
+
+
+${ctx['partner_id'].user_id and ctx['partner_id'].user_id.signature or ''}
+
+% if not ctx['partner_id'].user_id:
+PS: It looks like you do not have an account manager assigned to you, please contact us.
% endif
]]>
-
+
\ No newline at end of file
diff --git a/addons/crm_partner_assign/crm_portal_view.xml b/addons/crm_partner_assign/crm_portal_view.xml
new file mode 100644
index 00000000000..a8d342ebb94
--- /dev/null
+++ b/addons/crm_partner_assign/crm_portal_view.xml
@@ -0,0 +1,209 @@
+
+
+
+
+ partner lead
+ crm.lead
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ crm_portal_form
+ crm.lead
+
+
+
+
+
+
+
+ partner lead
+ crm.lead
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ crm_portal_form
+ crm.lead
+
+
+
+
+
+
+
+
+
+
+ Leads
+ crm.lead
+ tree,form
+
+ [('type','like','lead')]
+
+
+
+
+ tree
+
+
+
+
+
+
+ form
+
+
+
+
+
+
+
+ Opportunities
+ crm.lead
+ tree,form
+
+ [('type','like','opportunity')]
+
+
+
+
+ tree
+
+
+
+
+
+
+ form
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/crm_partner_assign/portal_data.xml b/addons/crm_partner_assign/portal_data.xml
new file mode 100644
index 00000000000..0d4a5b30abd
--- /dev/null
+++ b/addons/crm_partner_assign/portal_data.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+ openerp.portal.res.partner
+
+
+
+
+
+
+
+
+ openerp.portal.res.partner
+
+
+ [('id','child_of',user.commercial_partner_id.id)]
+
+
+ openerp.portal.res.partner.grade
+
+
+
+
+
+
+
+
+
+
+ openerp.portal.crm.lead
+
+
+ [('partner_assigned_id','child_of',user.commercial_partner_id.id)]
+
+
+ openerp.portal.crm.lead
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/crm_partner_assign/res_partner_view.xml b/addons/crm_partner_assign/res_partner_view.xml
index 9e70835a3f1..874d2a9f053 100644
--- a/addons/crm_partner_assign/res_partner_view.xml
+++ b/addons/crm_partner_assign/res_partner_view.xml
@@ -2,7 +2,7 @@
-
+
openerp_custom.res.partner.activation.form
@@ -33,145 +33,134 @@
tree,form
-
+
-
+
-
-
- res.partner.grade.tree
- res.partner.grade
-
-
-
-
-
-
-
-
- res.partner.grade.form
- res.partner.grade
-
-
-
-
-
- Partner Grade
- res.partner.grade
- form
-
-
-
-
-
- res.partner.geo.inherit.tree
- res.partner
-
-
-
-
-
-
+
+ res.partner.grade.tree
+ res.partner.grade
+
+
+
+
+
-
-
-
-
- res.partner.geo.inherit.search
- res.partner
-
-
-
-
-
-
-
-
-
-
-
-
- res.partner.geo.inherit
- res.partner
-
-
-
-
-
+
+
+ res.partner.grade.form
+ res.partner.grade
+
+
+
+
+
+ Partner Grade
+ res.partner.grade
+ form
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ res.partner.geo.inherit.tree
+ res.partner
+
+
+
+
+
+
+
+
+
+
+ res.partner.geo.inherit.search
+ res.partner
+
+
+
+
+
+
+
+
+
+
+
+
+ res.partner.geo.inherit
+ res.partner
+
+
+
+
+
+
+
+
+
+ (
+
+ N
+ S
+
+ E
+ W
+ )
+
+
+
+
+
+
+
+ Higher is the value, higher is the probability for this partner to get more leads.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/crm_partner_assign/security/ir.model.access.csv b/addons/crm_partner_assign/security/ir.model.access.csv
index 69b74ef6b3d..81d74bf43e3 100644
--- a/addons/crm_partner_assign/security/ir.model.access.csv
+++ b/addons/crm_partner_assign/security/ir.model.access.csv
@@ -5,3 +5,4 @@ access_crm_partner_report,crm.partner.report.assign.all,model_crm_partner_report
access_res_partner_grade,res.partner.grade,model_res_partner_grade,base.group_sale_salesman,1,1,1,0
access_res_partner_grade_manager,res.partner.grade.manager,model_res_partner_grade,base.group_sale_manager,1,1,1,1
"access_partner_activation_manager","res.partner.activation.manager","model_res_partner_activation","base.group_partner_manager",1,1,1,1
+partner_access_crm_lead,crm.lead,model_crm_lead,portal.group_portal,1,1,0,0
\ No newline at end of file
diff --git a/addons/crm_partner_assign/static/src/js/next.js b/addons/crm_partner_assign/static/src/js/next.js
new file mode 100644
index 00000000000..c40f104d6c6
--- /dev/null
+++ b/addons/crm_partner_assign/static/src/js/next.js
@@ -0,0 +1,13 @@
+openerp.crm_partner_assign = function (instance) {
+ instance.crm_partner_assign = instance.crm_partner_assign || {};
+ instance.crm_partner_assign.next_or_list = function(parent) {
+ var form = parent.inner_widget.views.form.controller;
+ form.dataset.remove_ids([form.dataset.ids[form.dataset.index]]);
+ form.reload();
+ if (!form.dataset.ids.length){
+ parent.inner_widget.switch_mode('list');
+ }
+ parent.do_action({ type: 'ir.actions.act_window_close' });
+ };
+ instance.web.client_actions.add("next_or_list", "instance.crm_partner_assign.next_or_list");
+}
\ No newline at end of file
diff --git a/addons/crm_partner_assign/wizard/__init__.py b/addons/crm_partner_assign/wizard/__init__.py
index 9224173145b..ab6c7b7f06a 100644
--- a/addons/crm_partner_assign/wizard/__init__.py
+++ b/addons/crm_partner_assign/wizard/__init__.py
@@ -20,3 +20,4 @@
##############################################################################
import crm_forward_to_partner
+import crm_channel_interested
\ No newline at end of file
diff --git a/addons/crm_partner_assign/wizard/crm_channel_interested.py b/addons/crm_partner_assign/wizard/crm_channel_interested.py
new file mode 100644
index 00000000000..57db36cb51f
--- /dev/null
+++ b/addons/crm_partner_assign/wizard/crm_channel_interested.py
@@ -0,0 +1,76 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+from openerp.osv import fields, osv
+from openerp.tools.translate import _
+from openerp import SUPERUSER_ID
+
+
+class crm_lead_forward_to_partner(osv.TransientModel):
+ """ Forward info history to partners. """
+ _name = 'crm.lead.channel.interested'
+ _columns = {
+ 'interested': fields.boolean('Interested by this lead'),
+ 'contacted': fields.boolean('Did you contact the lead?', help="The lead has been contacted"),
+ 'comment': fields.text('Comment', help="What are the elements that have led to this decision?", required=True),
+ }
+ _defaults = {
+ 'interested': lambda self, cr, uid, c: c.get('interested', True),
+ 'contacted': False,
+ }
+
+ def action_confirm(self, cr, uid, ids, context=None):
+ wizard = self.browse(cr, uid, ids[0], context=context)
+ if wizard.interested and not wizard.contacted:
+ raise osv.except_osv(_('Error!'), _("You must contact the lead before saying that you are interested"))
+ lead_obj = self.pool.get('crm.lead')
+ lead_obj.check_access_rights(cr, uid, 'write')
+ if wizard.interested:
+ message = _('I am interested by this lead.
')
+ values = {}
+ else:
+ stage = 'stage_portal_lead_recycle'
+ message = _('I am not interested by this lead. I %scontacted the lead.
') % (not wizard.contacted and 'have not ' or '')
+ values = {'partner_assigned_id': False}
+ user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
+ partner_ids = self.pool.get('res.partner').search(cr, SUPERUSER_ID, [('id', 'child_of', user.partner_id.commercial_partner_id.id)], context=context)
+ lead_obj.message_unsubscribe(cr, SUPERUSER_ID, context.get('active_ids'), partner_ids, context=None)
+ try:
+ stage_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'crm_partner_assign', stage)[1]
+ except ValueError:
+ stage_id = False
+ if stage_id:
+ values.update({'stage_id': stage_id})
+ if wizard.comment:
+ message += '%s
' % wizard.comment
+ lead_obj.message_post(cr, uid, context.get('active_ids'), body=message, context=context)
+ if values:
+ lead_obj.write(cr, SUPERUSER_ID, context.get('active_ids'), values)
+ if wizard.interested:
+ for lead in lead_obj.browse(cr, uid, context.get('active_ids'), context=context):
+ lead_obj.convert_opportunity(cr, SUPERUSER_ID, [lead.id], lead.partner_id and lead.partner_id.id or None, context=None)
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'next_or_list',
+ 'params': {
+ },
+ }
diff --git a/addons/crm_partner_assign/wizard/crm_channel_interested_view.xml b/addons/crm_partner_assign/wizard/crm_channel_interested_view.xml
new file mode 100644
index 00000000000..400e02cd48a
--- /dev/null
+++ b/addons/crm_partner_assign/wizard/crm_channel_interested_view.xml
@@ -0,0 +1,45 @@
+
+
+
+
+ crm_lead_channel_interested
+ crm.lead.channel.interested
+
+
+
+
+
+ Lead Feedback
+ crm.lead.channel.interested
+ form
+ form
+
+ new
+
+
+
\ No newline at end of file
diff --git a/addons/crm_partner_assign/wizard/crm_forward_to_partner.py b/addons/crm_partner_assign/wizard/crm_forward_to_partner.py
index 724102a84b1..80fa2f28b04 100644
--- a/addons/crm_partner_assign/wizard/crm_forward_to_partner.py
+++ b/addons/crm_partner_assign/wizard/crm_forward_to_partner.py
@@ -27,107 +27,182 @@ from openerp.tools.translate import _
class crm_lead_forward_to_partner(osv.TransientModel):
""" Forward info history to partners. """
_name = 'crm.lead.forward.to.partner'
- _inherit = "mail.compose.message"
- def _get_composition_mode_selection(self, cr, uid, context=None):
- composition_mode = super(crm_lead_forward_to_partner, self)._get_composition_mode_selection(cr, uid, context=context)
- composition_mode.append(('forward', 'Forward'))
- return composition_mode
-
- _columns = {
- 'partner_ids': fields.many2many('res.partner',
- 'lead_forward_to_partner_res_partner_rel',
- 'wizard_id', 'partner_id', 'Additional contacts'),
- 'attachment_ids': fields.many2many('ir.attachment',
- 'lead_forward_to_partner_attachment_rel',
- 'wizard_id', 'attachment_id', 'Attachments'),
- 'history_mode': fields.selection([('info', 'Internal notes'),
- ('latest', 'Latest email'), ('whole', 'Whole Story')],
- 'Send history', required=True),
- }
-
- _defaults = {
- 'history_mode': 'info',
- }
+ def _convert_to_assignation_line(self, cr, uid, lead, partner, context=None):
+ lead_location = []
+ partner_location = []
+ if lead.country_id:
+ lead_location.append(lead.country_id.name)
+ if lead.city:
+ lead_location.append(lead.city)
+ if partner:
+ if partner.country_id:
+ partner_location.append(partner.country_id.name)
+ if partner.city:
+ partner_location.append(partner.city)
+ return {'lead_id': lead.id,
+ 'lead_location': ", ".join(lead_location),
+ 'partner_assigned_id': partner and partner.id or False,
+ 'partner_location': ", ".join(partner_location),
+ 'lead_link': self.get_lead_portal_url(cr, uid, lead.id, lead.type, context=context),
+ }
def default_get(self, cr, uid, fields, context=None):
if context is None:
context = {}
- # set as comment, perform overrided document-like action that calls get_record_data
- old_mode = context.get('default_composition_mode', 'forward')
- context['default_composition_mode'] = 'comment'
+ lead_obj = self.pool.get('crm.lead')
+ email_template_obj = self.pool.get('email.template')
+ try:
+ template_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'crm_partner_assign', 'email_template_lead_forward_mail')[1]
+ except ValueError:
+ template_id = False
res = super(crm_lead_forward_to_partner, self).default_get(cr, uid, fields, context=context)
- # back to forward mode
- context['default_composition_mode'] = old_mode
- res['composition_mode'] = context['default_composition_mode']
+ active_ids = context.get('active_ids')
+ default_composition_mode = context.get('default_composition_mode')
+ res['assignation_lines'] = []
+ if template_id:
+ res['body'] = email_template_obj.get_email_template(cr, uid, template_id).body_html
+ if active_ids:
+ lead_ids = lead_obj.browse(cr, uid, active_ids, context=context)
+ if default_composition_mode == 'mass_mail':
+ partner_assigned_ids = lead_obj.search_geo_partner(cr, uid, active_ids, context=context)
+ else:
+ partner_assigned_ids = dict((lead.id, lead.partner_assigned_id and lead.partner_assigned_id.id or False) for lead in lead_ids)
+ res['partner_id'] = lead_ids[0].partner_assigned_id.id
+ for lead in lead_ids:
+ partner_id = partner_assigned_ids.get(lead.id) or False
+ partner = False
+ if partner_id:
+ partner = self.pool.get('res.partner').browse(cr, uid, partner_id, context=context)
+ res['assignation_lines'].append(self._convert_to_assignation_line(cr, uid, lead, partner))
return res
- def get_record_data(self, cr, uid, model, res_id, context=None):
- """ Override of mail.compose.message, to add default values coming
- form the related lead.
- """
- if context is None:
- context = {}
- res = super(crm_lead_forward_to_partner, self).get_record_data(cr, uid, model, res_id, context=context)
- if model not in ('crm.lead') or not res_id:
- return res
- template_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'crm_partner_assign', 'crm_partner_assign_email_template')[1]
- context['history_mode'] = context.get('history_mode','whole')
- mail_body_fields = ['partner_id', 'partner_name', 'title', 'function', 'street', 'street2', 'zip', 'city', 'country_id', 'state_id', 'email_from', 'phone', 'fax', 'mobile', 'description']
- lead = self.pool.get('crm.lead').browse(cr, uid, res_id, context=context)
- context['mail_body'] = self.pool.get('crm.lead')._mail_body(cr, uid, lead, mail_body_fields, context=context)
- template = self.generate_email_for_composer(cr, uid, template_id, res_id, context)
- res['subject'] = template['subject']
- res['body'] = template['body']
- return res
-
- def on_change_history_mode(self, cr, uid, ids, history_mode, model, res_id, context=None):
- """ Update body when changing history_mode """
- if context is None:
- context = {}
- if model and model == 'crm.lead' and res_id:
- lead = self.pool[model].browse(cr, uid, res_id, context=context)
- context['history_mode'] = history_mode
- body = self.get_record_data(cr, uid, 'crm.lead', res_id, context=context)['body']
- return {'value': {'body': body}}
-
- def create(self, cr, uid, values, context=None):
- """ TDE-HACK: remove 'type' from context, because when viewing an
- opportunity form view, a default_type is set and propagated
- to the wizard, that has a not matching type field. """
- default_type = context.pop('default_type', None)
- new_id = super(crm_lead_forward_to_partner, self).create(cr, uid, values, context=context)
- if default_type:
- context['default_type'] = default_type
- return new_id
-
def action_forward(self, cr, uid, ids, context=None):
- """ Forward the lead to a partner """
- if context is None:
+ lead_obj = self.pool.get('crm.lead')
+ record = self.browse(cr, uid, ids[0], context=context)
+ email_template_obj = self.pool.get('email.template')
+ try:
+ template_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'crm_partner_assign', 'email_template_lead_forward_mail')[1]
+ except ValueError:
+ raise osv.except_osv(_('Email Template Error'),
+ _('The Forward Email Template is not in the database'))
+ try:
+ portal_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'portal', 'group_portal')[1]
+ except ValueError:
+ raise osv.except_osv(_('Portal Group Error'),
+ _('The Portal group cannot be found'))
+
+ local_context = context.copy()
+ if not (record.forward_type == 'single'):
+ no_email = set()
+ for lead in record.assignation_lines:
+ if lead.partner_assigned_id and not lead.partner_assigned_id.email:
+ no_email.add(lead.partner_assigned_id.name)
+ if no_email:
+ raise osv.except_osv(_('Email Error'),
+ ('Set an email address for the partner(s): %s' % ", ".join(no_email)))
+ if record.forward_type == 'single' and not record.partner_id.email:
+ raise osv.except_osv(_('Email Error'),
+ ('Set an email address for the partner %s' % record.partner_id.name))
+
+ partners_leads = {}
+ for lead in record.assignation_lines:
+ partner = record.forward_type == 'single' and record.partner_id or lead.partner_assigned_id
+ lead_details = {
+ 'lead_link': lead.lead_link,
+ 'lead_id': lead.lead_id,
+ }
+ if partner:
+ partner_leads = partners_leads.get(partner.id)
+ if partner_leads:
+ partner_leads['leads'].append(lead_details)
+ else:
+ partners_leads[partner.id] = {'partner': partner, 'leads': [lead_details]}
+ stage_id = False
+ if record.assignation_lines and record.assignation_lines[0].lead_id.type == 'lead':
+ try:
+ stage_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'crm_partner_assign', 'stage_portal_lead_assigned')[1]
+ except ValueError:
+ pass
+
+ for partner_id, partner_leads in partners_leads.items():
+ in_portal = False
+ for contact in (partner.child_ids or [partner]):
+ if contact.user_ids:
+ in_portal = portal_id in [g.id for g in contact.user_ids[0].groups_id]
+
+ local_context['partner_id'] = partner_leads['partner']
+ local_context['partner_leads'] = partner_leads['leads']
+ local_context['partner_in_portal'] = in_portal
+ email_template_obj.send_mail(cr, uid, template_id, ids[0], context=local_context)
+ lead_ids = [lead['lead_id'].id for lead in partner_leads['leads']]
+ values = {'partner_assigned_id': partner_id, 'user_id': partner_leads['partner'].user_id.id}
+ if stage_id:
+ values['stage_id'] = stage_id
+ lead_obj.write(cr, uid, lead_ids, values)
+ self.pool.get('crm.lead').message_subscribe(cr, uid, lead_ids, [partner_id], context=context)
+ return True
+
+ def get_lead_portal_url(self, cr, uid, lead_id, type, context=None):
+ action = type == 'opportunity' and 'action_portal_opportunities' or 'action_portal_leads'
+ try:
+ action_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'crm_partner_assign', action)[1]
+ except ValueError:
+ action_id = False
+ portal_link = "%s/?db=%s#id=%s&action=%s&view_type=form" % (self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url'), cr.dbname, lead_id, action_id)
+ return portal_link
+
+ def get_portal_url(self, cr, uid, ids, context=None):
+ portal_link = "%s/?db=%s" % (self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url'), cr.dbname)
+ return portal_link
+
+ _columns = {
+ 'forward_type': fields.selection([('single', 'a single partner: manual selection of partner'), ('assigned', "several partners: automatic assignation, using GPS coordinates and partner's grades"), ], 'Forward selected leads to'),
+ 'partner_id': fields.many2one('res.partner', 'Forward Leads To'),
+ 'assignation_lines': fields.one2many('crm.lead.assignation', 'forward_id', 'Partner Assignation'),
+ 'body': fields.html('Contents', help='Automatically sanitized HTML contents'),
+ }
+
+ _defaults = {
+ 'forward_type': lambda self, cr, uid, c: c.get('forward_type') or 'single',
+ }
+
+
+class crm_lead_assignation (osv.TransientModel):
+ _name = 'crm.lead.assignation'
+ _columns = {
+ 'forward_id': fields.many2one('crm.lead.forward.to.partner', 'Partner Assignation'),
+ 'lead_id': fields.many2one('crm.lead', 'Lead'),
+ 'lead_location': fields.char('Lead Location', size=128),
+ 'partner_assigned_id': fields.many2one('res.partner', 'Assigned Partner'),
+ 'partner_location': fields.char('Partner Location', size=128),
+ 'lead_link': fields.char('Lead Single Links', size=128),
+ }
+
+ def on_change_lead_id(self, cr, uid, ids, lead_id, context=None):
+ if not context:
context = {}
- # TDE FIX in 7.0: force mass_mailing mode; this way, the message will be
- # send only to partners; default subtype of mass_mailing is indeed False
- # Chatter will show 'logged a note', but partner_ids (aka, the assigned partner)
- # will effectively receive the message if present in the composition window
- self.write(cr, uid, ids, {'composition_mode': 'mass_mail'}, context=context)
- res = {'type': 'ir.actions.act_window_close'}
- wizard = self.browse(cr, uid, ids[0], context=context)
- if wizard.model not in ('crm.lead'):
- return res
- if context.get('active_ids') is None:
- context['active_ids'] = [wizard.res_id]
+ if not lead_id:
+ return {'value': {'lead_location': False}}
+ lead = self.pool.get('crm.lead').browse(cr, uid, lead_id, context=context)
+ lead_location = []
+ if lead.country_id:
+ lead_location.append(lead.country_id.name)
+ if lead.city:
+ lead_location.append(lead.city)
+ return {'value': {'lead_location': ", ".join(lead_location)}}
- lead = self.pool[wizard.model]
- lead_ids = wizard.res_id and [wizard.res_id] or []
+ def on_change_partner_assigned_id(self, cr, uid, ids, partner_assigned_id, context=None):
+ if not context:
+ context = {}
+ if not partner_assigned_id:
+ return {'value': {'lead_location': False}}
+ partner = self.pool.get('res.partner').browse(cr, uid, partner_assigned_id, context=context)
+ partner_location = []
+ if partner.country_id:
+ partner_location.append(partner.country_id.name)
+ if partner.city:
+ partner_location.append(partner.city)
+ return {'value': {'partner_location': ", ".join(partner_location)}}
- if wizard.composition_mode == 'mass_mail':
- lead_ids = context and context.get('active_ids', []) or []
- value = self.default_get(cr, uid, ['body', 'email_to', 'email_cc', 'subject', 'history_mode'], context=context)
- value.pop('composition_mode')
- self.pool.get('crm.lead').message_subscribe(cr, uid, lead_ids, [partner.id for partner in wizard.partner_ids], context=context)
- self.write(cr, uid, ids, value, context=context)
-
- return self.send_mail(cr, uid, ids, context=context)
-
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+# # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/crm_partner_assign/wizard/crm_forward_to_partner_view.xml b/addons/crm_partner_assign/wizard/crm_forward_to_partner_view.xml
index 0fda8c8beaa..26ad08f1528 100644
--- a/addons/crm_partner_assign/wizard/crm_forward_to_partner_view.xml
+++ b/addons/crm_partner_assign/wizard/crm_forward_to_partner_view.xml
@@ -1,36 +1,38 @@
-
crm_lead_forward_to_partner
crm.lead.forward.to.partner
@@ -45,14 +47,11 @@
new
-
+
diff --git a/addons/delivery/partner.py b/addons/delivery/partner.py
index 477315dfc9b..226b5e493ab 100644
--- a/addons/delivery/partner.py
+++ b/addons/delivery/partner.py
@@ -25,11 +25,9 @@ class res_partner(osv.osv):
_inherit = 'res.partner'
_columns = {
'property_delivery_carrier': fields.property(
- 'delivery.carrier',
type='many2one',
relation='delivery.carrier',
string="Delivery Method",
- view_load=True,
help="This delivery method will be used when invoicing from picking."),
}
diff --git a/addons/hr_holidays/i18n/pl.po b/addons/hr_holidays/i18n/pl.po
index ebc13bc02d4..ad5730d2268 100644
--- a/addons/hr_holidays/i18n/pl.po
+++ b/addons/hr_holidays/i18n/pl.po
@@ -7,14 +7,14 @@ msgstr ""
"Project-Id-Version: OpenERP Server 6.0dev\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-12-21 17:04+0000\n"
-"PO-Revision-Date: 2012-12-14 12:51+0000\n"
-"Last-Translator: Grzegorz Grzelak (OpenGLOBE.pl) \n"
+"PO-Revision-Date: 2013-06-22 10:54+0000\n"
+"Last-Translator: Dariusz Kubiak \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2013-03-16 05:30+0000\n"
-"X-Generator: Launchpad (build 16532)\n"
+"X-Launchpad-Export-Date: 2013-06-23 05:13+0000\n"
+"X-Generator: Launchpad (build 16677)\n"
#. module: hr_holidays
#: selection:hr.holidays.status,color_name:0
@@ -32,7 +32,7 @@ msgid "Waiting Second Approval"
msgstr "Oczekuje na drugą aprobatę"
#. module: hr_holidays
-#: code:addons/hr_holidays/hr_holidays.py:298
+#: code:addons/hr_holidays/hr_holidays.py:309
#, python-format
msgid ""
"You cannot modify a leave request that has been approved. Contact a human "
@@ -109,11 +109,13 @@ msgid ""
"The default duration interval between the start date and the end date is 8 "
"hours. Feel free to adapt it to your needs."
msgstr ""
+"Domyślny odstęp między datą rozpoczęcia i data zakończenia jest 8 godzin. "
+"Zapraszam do dostosowania go do swoich potrzeb."
#. module: hr_holidays
#: model:mail.message.subtype,description:hr_holidays.mt_holidays_refused
msgid "Request refused"
-msgstr ""
+msgstr "Wniosek odrzucony"
#. module: hr_holidays
#: field:hr.holidays,number_of_days_temp:0
@@ -274,12 +276,12 @@ msgid ""
msgstr ""
#. module: hr_holidays
-#: code:addons/hr_holidays/hr_holidays.py:238
#: code:addons/hr_holidays/hr_holidays.py:249
-#: code:addons/hr_holidays/hr_holidays.py:274
-#: code:addons/hr_holidays/hr_holidays.py:298
-#: code:addons/hr_holidays/hr_holidays.py:421
-#: code:addons/hr_holidays/hr_holidays.py:471
+#: code:addons/hr_holidays/hr_holidays.py:260
+#: code:addons/hr_holidays/hr_holidays.py:285
+#: code:addons/hr_holidays/hr_holidays.py:309
+#: code:addons/hr_holidays/hr_holidays.py:432
+#: code:addons/hr_holidays/hr_holidays.py:482
#, python-format
msgid "Warning!"
msgstr "Ostrzeżenie !"
@@ -317,7 +319,7 @@ msgid "Sick Leaves"
msgstr "Zwolnienie lekarskie"
#. module: hr_holidays
-#: code:addons/hr_holidays/hr_holidays.py:478
+#: code:addons/hr_holidays/hr_holidays.py:489
#, python-format
msgid "Leave Request for %s"
msgstr "Wniosek urlopowy dla %s"
@@ -341,7 +343,7 @@ msgstr "Pozostało dni urlopu"
#. module: hr_holidays
#: field:hr.holidays,message_follower_ids:0
msgid "Followers"
-msgstr ""
+msgstr "Obserwatorzy"
#. module: hr_holidays
#: model:ir.model,name:hr_holidays.model_hr_holidays_remaining_leaves_user
@@ -388,7 +390,7 @@ msgid "Wheat"
msgstr "Pszenny"
#. module: hr_holidays
-#: code:addons/hr_holidays/hr_holidays.py:476
+#: code:addons/hr_holidays/hr_holidays.py:487
#, python-format
msgid "Allocation for %s"
msgstr "Przydział dla %s"
@@ -412,7 +414,7 @@ msgid "Number of Days"
msgstr "Liczba dni"
#. module: hr_holidays
-#: code:addons/hr_holidays/hr_holidays.py:471
+#: code:addons/hr_holidays/hr_holidays.py:482
#, python-format
msgid ""
"The feature behind the field 'Remaining Legal Leaves' can only be used when "
@@ -516,7 +518,7 @@ msgid "Start Date"
msgstr "Data początkowa"
#. module: hr_holidays
-#: code:addons/hr_holidays/hr_holidays.py:421
+#: code:addons/hr_holidays/hr_holidays.py:432
#, python-format
msgid ""
"There are not enough %s allocated for employee %s; please create an "
@@ -678,7 +680,7 @@ msgstr "Podsumowanie"
#. module: hr_holidays
#: model:hr.holidays.status,name:hr_holidays.holiday_status_unpaid
msgid "Unpaid"
-msgstr "Niezapłacone"
+msgstr "Bezpłatny"
#. module: hr_holidays
#: xsl:holidays.summary:0
@@ -741,7 +743,7 @@ msgstr "Różne"
#. module: hr_holidays
#: model:hr.holidays.status,name:hr_holidays.holiday_status_comp
msgid "Compensatory Days"
-msgstr ""
+msgstr "Urlop wyrównawczy"
#. module: hr_holidays
#: selection:hr.holidays.status,color_name:0
@@ -766,7 +768,7 @@ msgid "Validated"
msgstr "Zatwierdzony"
#. module: hr_holidays
-#: code:addons/hr_holidays/hr_holidays.py:238
+#: code:addons/hr_holidays/hr_holidays.py:249
#, python-format
msgid "You cannot delete a leave which is in %s state."
msgstr "Nie możesz usunąć nieobecności, która jest w stanie %s."
@@ -830,7 +832,7 @@ msgid "To Submit"
msgstr "Do wysłania"
#. module: hr_holidays
-#: code:addons/hr_holidays/hr_holidays.py:343
+#: code:addons/hr_holidays/hr_holidays.py:354
#: view:hr.holidays:0
#: selection:hr.holidays,type:0
#: field:resource.calendar.leaves,holiday_id:0
@@ -930,8 +932,8 @@ msgid "Messages and communication history"
msgstr "Wiadomości i historia komunikacji"
#. module: hr_holidays
-#: code:addons/hr_holidays/hr_holidays.py:249
-#: code:addons/hr_holidays/hr_holidays.py:274
+#: code:addons/hr_holidays/hr_holidays.py:260
+#: code:addons/hr_holidays/hr_holidays.py:285
#: sql_constraint:hr.holidays:0
#, python-format
msgid "The start date must be anterior to the end date."
diff --git a/addons/im/im.py b/addons/im/im.py
index cee1705ec35..4a867789cbc 100644
--- a/addons/im/im.py
+++ b/addons/im/im.py
@@ -22,6 +22,8 @@
import openerp
import openerp.tools.config
import openerp.modules.registry
+import openerp.addons.web.http as http
+from openerp.addons.web.http import request
from openerp.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
import datetime
from openerp.osv import osv, fields
@@ -90,36 +92,38 @@ POLL_TIMER = 30
DISCONNECTION_TIMER = POLL_TIMER + 5
WATCHER_ERROR_DELAY = 10
-class LongPollingController(openerp.addons.web.http.Controller):
- _cp_path = '/longpolling/im'
+class LongPollingController(http.Controller):
- @openerp.addons.web.http.jsonrequest
- def poll(self, req, last=None, users_watch=None, db=None, uid=None, password=None, uuid=None):
+ @http.route('/longpolling/im/poll', type="json", auth="none")
+ def poll(self, last=None, users_watch=None, db=None, uid=None, password=None, uuid=None):
assert_uuid(uuid)
if not openerp.evented:
raise Exception("Not usable in a server not running gevent")
from openerp.addons.im.watcher import ImWatcher
if db is not None:
- req.session._db = db
- req.session._uid = uid
- req.session._password = password
- req.session.model('im.user').im_connect(uuid=uuid, context=req.context)
- my_id = req.session.model('im.user').get_by_user_id(uuid or req.session._uid, req.context)["id"]
+ request.session.authenticate(db=db, uid=uid, password=password)
+ else:
+ request.session.authenticate(db=request.session._db, uid=request.session._uid, password=request.session._password)
+
+ with request.registry.cursor() as cr:
+ request.registry.get('im.user').im_connect(cr, request.uid, uuid=uuid, context=request.context)
+ my_id = request.registry.get('im.user').get_by_user_id(cr, request.uid, uuid or request.session._uid, request.context)["id"]
num = 0
while True:
- res = req.session.model('im.message').get_messages(last, users_watch, uuid=uuid, context=req.context)
+ with request.registry.cursor() as cr:
+ res = request.registry.get('im.message').get_messages(cr, request.uid, last, users_watch, uuid=uuid, context=request.context)
if num >= 1 or len(res["res"]) > 0:
return res
last = res["last"]
num += 1
ImWatcher.get_watcher(res["dbname"]).stop(my_id, users_watch or [], POLL_TIMER)
- @openerp.addons.web.http.jsonrequest
- def activated(self, req):
+ @http.route('/longpolling/im/activated', type="json", auth="none")
+ def activated(self):
return not not openerp.evented
- @openerp.addons.web.http.jsonrequest
- def gen_uuid(self, req):
+ @http.route('/longpolling/im/gen_uuid', type="json", auth="none")
+ def gen_uuid(self):
import uuid
return "%s" % uuid.uuid1()
diff --git a/addons/im_livechat/im_livechat.py b/addons/im_livechat/im_livechat.py
index 1ffb422fe6a..adceebc7cba 100644
--- a/addons/im_livechat/im_livechat.py
+++ b/addons/im_livechat/im_livechat.py
@@ -26,6 +26,8 @@ import random
import jinja2
from openerp.osv import osv, fields
from openerp import tools
+import openerp.addons.web.http as http
+from openerp.addons.web.http import request
env = jinja2.Environment(
loader=jinja2.PackageLoader('openerp.addons.im_livechat', "."),
@@ -33,48 +35,38 @@ env = jinja2.Environment(
)
env.filters["json"] = json.dumps
-class LiveChatController(openerp.addons.web.http.Controller):
- _cp_path = '/im_livechat'
+class LiveChatController(http.Controller):
- @openerp.addons.web.http.httprequest
- def loader(self, req, **kwargs):
+ @http.route('/im_livechat/loader')
+ def loader(self, **kwargs):
p = json.loads(kwargs["p"])
db = p["db"]
channel = p["channel"]
user_name = p.get("user_name", None)
- req.session._db = db
- req.session._uid = None
- req.session._login = "anonymous"
- req.session._password = "anonymous"
- info = req.session.model('im_livechat.channel').get_info_for_chat_src(channel)
+ request.session.authenticate(db=db, login="anonymous", password="anonymous")
+ info = request.session.model('im_livechat.channel').get_info_for_chat_src(channel)
info["db"] = db
info["channel"] = channel
info["userName"] = user_name
- return req.make_response(env.get_template("loader.js").render(info),
+ return request.make_response(env.get_template("loader.js").render(info),
headers=[('Content-Type', "text/javascript")])
- @openerp.addons.web.http.httprequest
- def web_page(self, req, **kwargs):
+ @http.route('/im_livechat/web_page')
+ def web_page(self, **kwargs):
p = json.loads(kwargs["p"])
db = p["db"]
channel = p["channel"]
- req.session._db = db
- req.session._uid = None
- req.session._login = "anonymous"
- req.session._password = "anonymous"
- script = req.session.model('im_livechat.channel').read(channel, ["script"])["script"]
- info = req.session.model('im_livechat.channel').get_info_for_chat_src(channel)
+ request.session.authenticate(db=db, login="anonymous", password="anonymous")
+ script = request.session.model('im_livechat.channel').read(channel, ["script"])["script"]
+ info = request.session.model('im_livechat.channel').get_info_for_chat_src(channel)
info["script"] = script
- return req.make_response(env.get_template("web_page.html").render(info),
+ return request.make_response(env.get_template("web_page.html").render(info),
headers=[('Content-Type', "text/html")])
- @openerp.addons.web.http.jsonrequest
- def available(self, req, db, channel):
- req.session._db = db
- req.session._uid = None
- req.session._login = "anonymous"
- req.session._password = "anonymous"
- return req.session.model('im_livechat.channel').get_available_user(channel) > 0
+ @http.route('/im_livechat/available', type='json')
+ def available(self, db, channel):
+ request.session.authenticate(db=db, login="anonymous", password="anonymous")
+ return request.session.model('im_livechat.channel').get_available_user(channel) > 0
class im_livechat_channel(osv.osv):
_name = 'im_livechat.channel'
diff --git a/addons/knowledge/i18n/th.po b/addons/knowledge/i18n/th.po
new file mode 100644
index 00000000000..3b5327841d8
--- /dev/null
+++ b/addons/knowledge/i18n/th.po
@@ -0,0 +1,118 @@
+# Thai translation for openobject-addons
+# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR , 2013.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME \n"
+"POT-Creation-Date: 2012-12-21 17:05+0000\n"
+"PO-Revision-Date: 2013-06-21 18:52+0000\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: Thai \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2013-06-22 05:36+0000\n"
+"X-Generator: Launchpad (build 16677)\n"
+
+#. module: knowledge
+#: view:knowledge.config.settings:0
+msgid "Documents"
+msgstr "เอกสาร"
+
+#. module: knowledge
+#: model:ir.model,name:knowledge.model_knowledge_config_settings
+msgid "knowledge.config.settings"
+msgstr ""
+
+#. module: knowledge
+#: help:knowledge.config.settings,module_document_webdav:0
+msgid ""
+"Access your documents in OpenERP through WebDAV.\n"
+" This installs the module document_webdav."
+msgstr ""
+
+#. module: knowledge
+#: help:knowledge.config.settings,module_document_page:0
+msgid "This installs the module document_page."
+msgstr ""
+
+#. module: knowledge
+#: model:ir.ui.menu,name:knowledge.menu_document2
+msgid "Collaborative Content"
+msgstr ""
+
+#. module: knowledge
+#: model:ir.actions.act_window,name:knowledge.action_knowledge_configuration
+#: view:knowledge.config.settings:0
+msgid "Configure Knowledge"
+msgstr ""
+
+#. module: knowledge
+#: view:knowledge.config.settings:0
+msgid "Knowledge and Documents Management"
+msgstr ""
+
+#. module: knowledge
+#: help:knowledge.config.settings,module_document:0
+msgid ""
+"This is a complete document management system, with: user authentication,\n"
+" full document search (but pptx and docx are not supported), "
+"and a document dashboard.\n"
+" This installs the module document."
+msgstr ""
+
+#. module: knowledge
+#: field:knowledge.config.settings,module_document_page:0
+msgid "Create static web pages"
+msgstr ""
+
+#. module: knowledge
+#: field:knowledge.config.settings,module_document_ftp:0
+msgid "Share repositories (FTP)"
+msgstr ""
+
+#. module: knowledge
+#: field:knowledge.config.settings,module_document:0
+msgid "Manage documents"
+msgstr ""
+
+#. module: knowledge
+#: view:knowledge.config.settings:0
+msgid "Cancel"
+msgstr ""
+
+#. module: knowledge
+#: view:knowledge.config.settings:0
+msgid "Apply"
+msgstr "ปรับใช้"
+
+#. module: knowledge
+#: model:ir.ui.menu,name:knowledge.menu_document_configuration
+msgid "Configuration"
+msgstr "ตั้งค่า"
+
+#. module: knowledge
+#: help:knowledge.config.settings,module_document_ftp:0
+msgid ""
+"Access your documents in OpenERP through an FTP interface.\n"
+" This installs the module document_ftp."
+msgstr ""
+
+#. module: knowledge
+#: view:knowledge.config.settings:0
+msgid "or"
+msgstr "หรือ"
+
+#. module: knowledge
+#: field:knowledge.config.settings,module_document_webdav:0
+msgid "Share repositories (WebDAV)"
+msgstr ""
+
+#. module: knowledge
+#: model:ir.ui.menu,name:knowledge.menu_document
+#: model:ir.ui.menu,name:knowledge.menu_knowledge_configuration
+msgid "Knowledge"
+msgstr "ความรู้"
diff --git a/addons/l10n_be_hr_payroll/i18n/zh_CN.po b/addons/l10n_be_hr_payroll/i18n/zh_CN.po
new file mode 100644
index 00000000000..e753e1e1bb2
--- /dev/null
+++ b/addons/l10n_be_hr_payroll/i18n/zh_CN.po
@@ -0,0 +1,148 @@
+# Chinese (Simplified) translation for openobject-addons
+# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR , 2013.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME \n"
+"POT-Creation-Date: 2012-11-24 02:53+0000\n"
+"PO-Revision-Date: 2013-06-23 05:44+0000\n"
+"Last-Translator: Calvin \n"
+"Language-Team: Chinese (Simplified) \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2013-06-24 04:43+0000\n"
+"X-Generator: Launchpad (build 16677)\n"
+
+#. module: l10n_be_hr_payroll
+#: help:hr.employee,disabled_spouse_bool:0
+msgid "if recipient spouse is declared disabled by law"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: help:hr.employee,disabled_children_bool:0
+msgid "if recipient children is/are declared disabled by law"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,misc_onss_deduction:0
+msgid "Miscellaneous exempt ONSS "
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: model:ir.model,name:l10n_be_hr_payroll.model_hr_employee
+msgid "Employee"
+msgstr "员工"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.employee,disabled_spouse_bool:0
+msgid "Disabled Spouse"
+msgstr "残疾人配偶"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,retained_net_amount:0
+msgid "Net retained "
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.employee,resident_bool:0
+msgid "Nonresident"
+msgstr "非常住人口"
+
+#. module: l10n_be_hr_payroll
+#: help:hr.employee,resident_bool:0
+msgid "if recipient lives in a foreign country"
+msgstr "如果接受者居住在国外"
+
+#. module: l10n_be_hr_payroll
+#: view:hr.employee:0
+msgid "if spouse has professionnel income or not"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,insurance_employee_deduction:0
+msgid "Insurance Group - by worker "
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: selection:hr.employee,spouse_fiscal_status:0
+msgid "With Income"
+msgstr "有收入"
+
+#. module: l10n_be_hr_payroll
+#: selection:hr.employee,spouse_fiscal_status:0
+msgid "Without Income"
+msgstr "无收入"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.employee,disabled_children_number:0
+msgid "Number of disabled children"
+msgstr "残疾儿童个数"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,additional_net_amount:0
+msgid "Net supplements"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,car_company_amount:0
+msgid "Company car employer"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,misc_advantage_amount:0
+msgid "Benefits of various nature "
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,car_employee_deduction:0
+msgid "Company Car Deduction for Worker"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.employee,disabled_children_bool:0
+msgid "Disabled Children"
+msgstr "残疾儿童"
+
+#. module: l10n_be_hr_payroll
+#: model:ir.model,name:l10n_be_hr_payroll.model_hr_contract
+msgid "Contract"
+msgstr "合约"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,meal_voucher_amount:0
+msgid "Check Value Meal "
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,travel_reimbursement_amount:0
+msgid "Reimbursement of travel expenses"
+msgstr "差旅花费补贴"
+
+#. module: l10n_be_hr_payroll
+#: constraint:hr.contract:0
+msgid "Error! Contract start-date must be less than contract end-date."
+msgstr "错误!联系人开始日期必须小于结束日期"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.employee,spouse_fiscal_status:0
+msgid "Tax status for spouse"
+msgstr "配偶缴税状态"
+
+#. module: l10n_be_hr_payroll
+#: view:hr.employee:0
+msgid "number of dependent children declared as disabled"
+msgstr ""
+
+#. module: l10n_be_hr_payroll
+#: constraint:hr.employee:0
+msgid "Error! You cannot create recursive hierarchy of Employee(s)."
+msgstr "错误!,你不能创建循环的员工层次"
+
+#. module: l10n_be_hr_payroll
+#: field:hr.contract,meal_voucher_employee_deduction:0
+msgid "Check Value Meal - by worker "
+msgstr ""
diff --git a/addons/portal_anonymous/i18n/en_AU.po b/addons/portal_anonymous/i18n/en_AU.po
new file mode 100644
index 00000000000..f5b491b2574
--- /dev/null
+++ b/addons/portal_anonymous/i18n/en_AU.po
@@ -0,0 +1,25 @@
+# English (Australia) translation for openobject-addons
+# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR , 2013.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME \n"
+"POT-Creation-Date: 2012-12-21 17:05+0000\n"
+"PO-Revision-Date: 2013-06-24 01:47+0000\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: English (Australia) \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2013-06-24 04:43+0000\n"
+"X-Generator: Launchpad (build 16677)\n"
+
+#. module: portal_anonymous
+#. openerp-web
+#: code:addons/portal_anonymous/static/src/xml/portal_anonymous.xml:8
+#, python-format
+msgid "Login"
+msgstr "Login"
diff --git a/addons/product/partner.py b/addons/product/partner.py
index fbfee76d0b2..d6b615ed88a 100644
--- a/addons/product/partner.py
+++ b/addons/product/partner.py
@@ -27,12 +27,10 @@ class res_partner(osv.osv):
_inherit = 'res.partner'
_columns = {
'property_product_pricelist': fields.property(
- 'product.pricelist',
type='many2one',
relation='product.pricelist',
domain=[('type','=','sale')],
string="Sale Pricelist",
- view_load=True,
help="This pricelist will be used, instead of the default one, for sales to the current partner"),
}
diff --git a/addons/product/product.py b/addons/product/product.py
index 656812bebbb..6e1128985aa 100644
--- a/addons/product/product.py
+++ b/addons/product/product.py
@@ -321,7 +321,7 @@ class product_template(osv.osv):
'uom_id': fields.many2one('product.uom', 'Unit of Measure', required=True, help="Default Unit of Measure used for all stock operation."),
'uom_po_id': fields.many2one('product.uom', 'Purchase Unit of Measure', required=True, help="Default Unit of Measure used for purchase orders. It must be in the same category than the default unit of measure."),
'uos_id' : fields.many2one('product.uom', 'Unit of Sale',
- help='Sepcify a unit of measure here if invoicing is made in another unit of measure than inventory. Keep empty to use the default unit of measure.'),
+ help='Specify a unit of measure here if invoicing is made in another unit of measure than inventory. Keep empty to use the default unit of measure.'),
'uos_coeff': fields.float('Unit of Measure -> UOS Coeff', digits_compute= dp.get_precision('Product UoS'),
help='Coefficient to convert default Unit of Measure to Unit of Sale\n'
' uos = uom * coeff'),
diff --git a/addons/purchase/partner.py b/addons/purchase/partner.py
index 5e5af0815e3..52c5d798eeb 100644
--- a/addons/purchase/partner.py
+++ b/addons/purchase/partner.py
@@ -48,12 +48,10 @@ class res_partner(osv.osv):
_columns = {
'property_product_pricelist_purchase': fields.property(
- 'product.pricelist',
type='many2one',
relation='product.pricelist',
domain=[('type','=','purchase')],
string="Purchase Pricelist",
- view_load=True,
help="This pricelist will be used, instead of the default one, for purchases from the current partner"),
'purchase_order_count': fields.function(_purchase_order_count, string='# of Purchase Order', type='integer'),
'purchase_order_ids': fields.one2many('purchase.order','partner_id','Purchase Order')
diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index 0ad39fca4f8..707012fc063 100644
--- a/addons/purchase/purchase.py
+++ b/addons/purchase/purchase.py
@@ -468,6 +468,20 @@ class purchase_order(osv.osv):
self.write(cr, uid, [id], {'state' : 'confirmed', 'validator' : uid})
return True
+ def _choose_account_from_po_line(self, cr, uid, po_line, context=None):
+ fiscal_obj = self.pool.get('account.fiscal.position')
+ property_obj = self.pool.get('ir.property')
+ if po_line.product_id:
+ acc_id = po_line.product_id.property_account_expense.id
+ if not acc_id:
+ acc_id = po_line.product_id.categ_id.property_account_expense_categ.id
+ if not acc_id:
+ raise osv.except_osv(_('Error!'), _('Define expense account for this company: "%s" (id:%d).') % (po_line.product_id.name, po_line.product_id.id,))
+ else:
+ acc_id = property_obj.get(cr, uid, 'property_account_expense_categ', 'product.category').id
+ fpos = po_line.order_id.fiscal_position or False
+ return fiscal_obj.map_account(cr, uid, fpos, acc_id)
+
def _prepare_inv_line(self, cr, uid, account_id, order_line, context=None):
"""Collects require data from purchase order line that is used to create invoice line
for that purchase order line
@@ -485,6 +499,7 @@ class purchase_order(osv.osv):
'uos_id': order_line.product_uom.id or False,
'invoice_line_tax_id': [(6, 0, [x.id for x in order_line.taxes_id])],
'account_analytic_id': order_line.account_analytic_id.id or False,
+ 'purchase_line_id': order_line.id,
}
def action_cancel_draft(self, cr, uid, ids, context=None):
@@ -508,8 +523,6 @@ class purchase_order(osv.osv):
journal_obj = self.pool.get('account.journal')
inv_obj = self.pool.get('account.invoice')
inv_line_obj = self.pool.get('account.invoice.line')
- fiscal_obj = self.pool.get('account.fiscal.position')
- property_obj = self.pool.get('ir.property')
for order in self.browse(cr, uid, ids, context=context):
pay_acc_id = order.partner_id.property_account_payable.id
@@ -521,17 +534,7 @@ class purchase_order(osv.osv):
# generate invoice line correspond to PO line and link that to created invoice (inv_id) and PO line
inv_lines = []
for po_line in order.order_line:
- if po_line.product_id:
- acc_id = po_line.product_id.property_account_expense.id
- if not acc_id:
- acc_id = po_line.product_id.categ_id.property_account_expense_categ.id
- if not acc_id:
- raise osv.except_osv(_('Error!'), _('Define expense account for this company: "%s" (id:%d).') % (po_line.product_id.name, po_line.product_id.id,))
- else:
- acc_id = property_obj.get(cr, uid, 'property_account_expense_categ', 'product.category').id
- fpos = order.fiscal_position or False
- acc_id = fiscal_obj.map_account(cr, uid, fpos, acc_id)
-
+ acc_id = self._choose_account_from_po_line(cr, uid, po_line, context=context)
inv_line_data = self._prepare_inv_line(cr, uid, acc_id, po_line, context=context)
inv_line_id = inv_line_obj.create(cr, uid, inv_line_data, context=context)
inv_lines.append(inv_line_id)
@@ -633,6 +636,7 @@ class purchase_order(osv.osv):
}
def _prepare_order_line_move(self, cr, uid, order, order_line, picking_id, context=None):
+ ''' prepare the stock move data from the PO line '''
return {
'name': order_line.name or '',
'product_id': order_line.product_id.id,
@@ -869,7 +873,7 @@ class purchase_order_line(osv.osv):
'invoice_lines': fields.many2many('account.invoice.line', 'purchase_order_line_invoice_rel', 'order_line_id', 'invoice_id', 'Invoice Lines', readonly=True),
'invoiced': fields.boolean('Invoiced', readonly=True),
'partner_id': fields.related('order_id','partner_id',string='Partner',readonly=True,type="many2one", relation="res.partner", store=True),
- 'date_order': fields.related('order_id','date_order',string='Order Date',readonly=True,type="date")
+ 'date_order': fields.related('order_id','date_order',string='Order Date',readonly=True,type="date"),
}
_defaults = {
@@ -1246,5 +1250,13 @@ class account_invoice(osv.Model):
purchase_order_obj.message_post(cr, uid, po_ids, body=_("Invoice paid"), context=context)
return res
+class account_invoice_line(osv.Model):
+ """ Override account_invoice_line to add the link to the purchase order line it is related to"""
+ _inherit = 'account.invoice.line'
+ _columns = {
+ 'purchase_line_id': fields.many2one('purchase.order.line',
+ 'Purchase Order Line', ondelete='set null', select=True,
+ readonly=True),
+ }
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/purchase/wizard/purchase_line_invoice.py b/addons/purchase/wizard/purchase_line_invoice.py
index b8ee4b69a32..33df515164b 100644
--- a/addons/purchase/wizard/purchase_line_invoice.py
+++ b/addons/purchase/wizard/purchase_line_invoice.py
@@ -48,12 +48,11 @@ class purchase_line_invoice(osv.osv_memory):
if record_ids:
res = False
invoices = {}
- invoice_obj=self.pool.get('account.invoice')
- purchase_line_obj=self.pool.get('purchase.order.line')
- property_obj=self.pool.get('ir.property')
- account_fiscal_obj=self.pool.get('account.fiscal.position')
- invoice_line_obj=self.pool.get('account.invoice.line')
- account_jrnl_obj=self.pool.get('account.journal')
+ invoice_obj = self.pool.get('account.invoice')
+ purchase_obj = self.pool.get('purchase.order')
+ purchase_line_obj = self.pool.get('purchase.order.line')
+ invoice_line_obj = self.pool.get('account.invoice.line')
+ account_jrnl_obj = self.pool.get('account.journal')
def multiple_order_invoice_notes(orders):
notes = ""
@@ -93,35 +92,14 @@ class purchase_line_invoice(osv.osv_memory):
order.write({'invoice_ids': [(4, inv_id)]})
return inv_id
- for line in purchase_line_obj.browse(cr,uid,record_ids):
- if (not line.invoiced) and (line.state not in ('draft','cancel')):
+ for line in purchase_line_obj.browse(cr, uid, record_ids, context=context):
+ if (not line.invoiced) and (line.state not in ('draft', 'cancel')):
if not line.partner_id.id in invoices:
invoices[line.partner_id.id] = []
- if line.product_id:
- a = line.product_id.property_account_expense.id
- if not a:
- a = line.product_id.categ_id.property_account_expense_categ.id
- if not a:
- raise osv.except_osv(_('Error!'),
- _('Define expense account for this product: "%s" (id:%d).') % \
- (line.product_id.name, line.product_id.id,))
- else:
- a = property_obj.get(cr, uid,
- 'property_account_expense_categ', 'product.category',
- context=context).id
- fpos = line.order_id.fiscal_position or False
- a = account_fiscal_obj.map_account(cr, uid, fpos, a)
- inv_id = invoice_line_obj.create(cr, uid, {
- 'name': line.name,
- 'origin': line.order_id.name,
- 'account_id': a,
- 'price_unit': line.price_unit,
- 'quantity': line.product_qty,
- 'uos_id': line.product_uom.id,
- 'product_id': line.product_id.id or False,
- 'invoice_line_tax_id': [(6, 0, [x.id for x in line.taxes_id])],
- 'account_analytic_id': line.account_analytic_id and line.account_analytic_id.id or False,
- })
+ acc_id = purchase_obj._choose_account_from_po_line(cr, uid, line, context=context)
+ inv_line_data = purchase_obj._prepare_inv_line(cr, uid, acc_id, line, context=context)
+ inv_line_data.update({'origin': line.order_id.name})
+ inv_id = invoice_line_obj.create(cr, uid, inv_line_data, context=context)
purchase_line_obj.write(cr, uid, [line.id], {'invoiced': True, 'invoice_lines': [(4, inv_id)]})
invoices[line.partner_id.id].append((line,inv_id))
diff --git a/addons/report_webkit/ir_report.py b/addons/report_webkit/ir_report.py
index cea2b4e8329..5a914cfbcf0 100644
--- a/addons/report_webkit/ir_report.py
+++ b/addons/report_webkit/ir_report.py
@@ -37,10 +37,10 @@ from webkit_report import WebKitParser
class ir_actions_report_xml(orm.Model):
_inherit = 'ir.actions.report.xml'
_columns = {
- 'webkit_header': fields.property('ir.header_webkit',
+ 'webkit_header': fields.property(
type='many2one', relation='ir.header_webkit',
string='Webkit Header', help="The header linked to the report",
- view_load=True, required=True),
+ required=True),
'webkit_debug': fields.boolean('Webkit debug',
help="Enable the webkit engine debugger"),
'report_webkit_data': fields.text('Webkit Template',
diff --git a/addons/sale_journal/sale_journal.py b/addons/sale_journal/sale_journal.py
index 9e10c826898..73fd5b672f1 100644
--- a/addons/sale_journal/sale_journal.py
+++ b/addons/sale_journal/sale_journal.py
@@ -43,11 +43,9 @@ class res_partner(osv.osv):
_inherit = 'res.partner'
_columns = {
'property_invoice_type': fields.property(
- 'sale_journal.invoice.type',
type = 'many2one',
relation = 'sale_journal.invoice.type',
string = "Invoicing Type",
- view_load = True,
group_name = "Accounting Properties",
help = "This invoicing type will be used, by default, to invoice the current partner."),
}
diff --git a/addons/stock/partner.py b/addons/stock/partner.py
index b8bad4faf95..3aaf1c663e5 100644
--- a/addons/stock/partner.py
+++ b/addons/stock/partner.py
@@ -25,19 +25,15 @@ class res_partner(osv.osv):
_inherit = 'res.partner'
_columns = {
'property_stock_customer': fields.property(
- 'stock.location',
type='many2one',
relation='stock.location',
string="Customer Location",
- view_load=True,
help="This stock location will be used, instead of the default one, as the destination location for goods you send to this partner"),
'property_stock_supplier': fields.property(
- 'stock.location',
type='many2one',
relation='stock.location',
string="Supplier Location",
- view_load=True,
help="This stock location will be used, instead of the default one, as the source location for goods you receive from the current partner"),
}
diff --git a/addons/stock/product.py b/addons/stock/product.py
index f31c2b21ef1..20fc660be0f 100644
--- a/addons/stock/product.py
+++ b/addons/stock/product.py
@@ -477,37 +477,33 @@ class product_template(osv.osv):
_inherit = 'product.template'
_columns = {
'property_stock_procurement': fields.property(
- 'stock.location',
type='many2one',
relation='stock.location',
string="Procurement Location",
- view_load=True,
domain=[('usage','like','procurement')],
help="This stock location will be used, instead of the default one, as the source location for stock moves generated by procurements."),
'property_stock_production': fields.property(
- 'stock.location',
type='many2one',
relation='stock.location',
string="Production Location",
- view_load=True,
domain=[('usage','like','production')],
help="This stock location will be used, instead of the default one, as the source location for stock moves generated by manufacturing orders."),
'property_stock_inventory': fields.property(
- 'stock.location',
type='many2one',
relation='stock.location',
string="Inventory Location",
- view_load=True,
domain=[('usage','like','inventory')],
help="This stock location will be used, instead of the default one, as the source location for stock moves generated when you do an inventory."),
- 'property_stock_account_input': fields.property('account.account',
- type='many2one', relation='account.account',
- string='Stock Input Account', view_load=True,
+ 'property_stock_account_input': fields.property(
+ type='many2one',
+ relation='account.account',
+ string='Stock Input Account',
help="When doing real-time inventory valuation, counterpart journal items for all incoming stock moves will be posted in this account, unless "
"there is a specific valuation account set on the source location. When not set on the product, the one from the product category is used."),
- 'property_stock_account_output': fields.property('account.account',
- type='many2one', relation='account.account',
- string='Stock Output Account', view_load=True,
+ 'property_stock_account_output': fields.property(
+ type='many2one',
+ relation='account.account',
+ string='Stock Output Account',
help="When doing real-time inventory valuation, counterpart journal items for all outgoing stock moves will be posted in this account, unless "
"there is a specific valuation account set on the destination location. When not set on the product, the one from the product category is used."),
'sale_delay': fields.float('Customer Lead Time', help="The average delay in days between the confirmation of the customer order and the delivery of the finished products. It's the time you promise to your customers."),
@@ -524,27 +520,29 @@ class product_category(osv.osv):
_inherit = 'product.category'
_columns = {
- 'property_stock_journal': fields.property('account.journal',
- relation='account.journal', type='many2one',
- string='Stock Journal', view_load=True,
+ 'property_stock_journal': fields.property(
+ relation='account.journal',
+ type='many2one',
+ string='Stock Journal',
help="When doing real-time inventory valuation, this is the Accounting Journal in which entries will be automatically posted when stock moves are processed."),
- 'property_stock_account_input_categ': fields.property('account.account',
- type='many2one', relation='account.account',
- string='Stock Input Account', view_load=True,
+ 'property_stock_account_input_categ': fields.property(
+ type='many2one',
+ relation='account.account',
+ string='Stock Input Account',
help="When doing real-time inventory valuation, counterpart journal items for all incoming stock moves will be posted in this account, unless "
"there is a specific valuation account set on the source location. This is the default value for all products in this category. It "
"can also directly be set on each product"),
- 'property_stock_account_output_categ': fields.property('account.account',
- type='many2one', relation='account.account',
- string='Stock Output Account', view_load=True,
+ 'property_stock_account_output_categ': fields.property(
+ type='many2one',
+ relation='account.account',
+ string='Stock Output Account',
help="When doing real-time inventory valuation, counterpart journal items for all outgoing stock moves will be posted in this account, unless "
"there is a specific valuation account set on the destination location. This is the default value for all products in this category. It "
"can also directly be set on each product"),
- 'property_stock_valuation_account_id': fields.property('account.account',
+ 'property_stock_valuation_account_id': fields.property(
type='many2one',
relation='account.account',
string="Stock Valuation Account",
- view_load=True,
help="When real-time inventory valuation is enabled on a product, this account will hold the current value of the products.",),
}
diff --git a/addons/stock_location/i18n/th.po b/addons/stock_location/i18n/th.po
index b2cee6e2936..7636c8142c8 100644
--- a/addons/stock_location/i18n/th.po
+++ b/addons/stock_location/i18n/th.po
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2013-06-21 05:36+0000\n"
+"X-Launchpad-Export-Date: 2013-06-22 05:36+0000\n"
"X-Generator: Launchpad (build 16677)\n"
#. module: stock_location