savoirfairelinux-openerp team mailing list archive
-
savoirfairelinux-openerp team
-
Mailing list archive
-
Message #00020
[Merge] lp:~extra-addons-commiter/e-commerce-addons/trunk into lp:e-commerce-addons
Sébastien BEAU - http://www.akretion.com has proposed merging lp:~extra-addons-commiter/e-commerce-addons/trunk into lp:e-commerce-addons.
Requested reviews:
extra-addons-commiter (extra-addons-commiter)
For more details, see:
https://code.launchpad.net/~extra-addons-commiter/e-commerce-addons/trunk/+merge/142952
this was the previous trunk branch and as some module have been ported we should merge it in stable
--
https://code.launchpad.net/~extra-addons-commiter/e-commerce-addons/trunk/+merge/142952
Your team extra-addons-commiter is requested to review the proposed merge of lp:~extra-addons-commiter/e-commerce-addons/trunk into lp:e-commerce-addons.
=== modified file 'base_sale_export_partner/__openerp__.py'
--- base_sale_export_partner/__openerp__.py 2012-11-21 13:48:17 +0000
+++ base_sale_export_partner/__openerp__.py 2013-01-11 17:08:20 +0000
@@ -36,6 +36,6 @@
'wizard/export_partner.xml',
],
'demo_xml': [],
- 'installable': True,
+ 'installable': False,
'active': False,
}
=== modified file 'base_sale_export_product/__openerp__.py'
--- base_sale_export_product/__openerp__.py 2012-11-21 13:48:17 +0000
+++ base_sale_export_product/__openerp__.py 2013-01-11 17:08:20 +0000
@@ -36,6 +36,6 @@
'wizard/export_product.xml',
],
'demo_xml': [],
- 'installable': True,
+ 'installable': False,
'active': False,
}
=== modified file 'base_sale_multichannels/__openerp__.py'
--- base_sale_multichannels/__openerp__.py 2012-11-30 12:02:42 +0000
+++ base_sale_multichannels/__openerp__.py 2013-01-11 17:08:20 +0000
@@ -72,7 +72,7 @@
'account_view.xml',
],
'demo_xml': [],
- 'installable': True,
+ 'installable': False,
'certificate': '',
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'base_sale_multichannels/connector.py'
--- base_sale_multichannels/connector.py 1970-01-01 00:00:00 +0000
+++ base_sale_multichannels/connector.py 2013-01-11 17:08:20 +0000
@@ -0,0 +1,37 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+# #
+# product_custom_attributes for OpenERP #
+# Copyright (C) 2012 Camptocamp Alexandre Fayolle <alexandre.fayolle@xxxxxxxxxxxxxx> #
+# Copyright (C) 2012 Akretion Sebastien Beau <sebastien.beau@xxxxxxxxxxxx> #
+# #
+# 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 <http://www.gnu.org/licenses/>. #
+# #
+###############################################################################
+
+from base_external_referentials.connector import AbstractConnector
+
+class BaseConnector(AbstractConnector):
+ def _get_import_defaults_res_partner(self, cr, uid, context=None):
+ pass
+ def _get_import_defaults_res_partner(self, cr, uid, context=None):
+ pass
+ def _get_import_defaults_external_shop_group(self, cr, uid, context=None):
+ pass
+
+ def _get_import_defaults_sale_order(self, cr, uid, context=None):
+ pass
+
+ def _record_one_sale_order(self, cr, uid, res_obj, resource, defaults, context):
+ pass
=== modified file 'base_sale_multichannels/partner.py'
--- base_sale_multichannels/partner.py 2012-10-24 20:17:59 +0000
+++ base_sale_multichannels/partner.py 2013-01-11 17:08:20 +0000
@@ -32,6 +32,7 @@
'shop_ids': fields.many2many('sale.shop', 'sale_shop_res_partner_rel', 'shop_id', 'partner_id', 'Present in Shops', readonly=True, help="List of shops in which this customer exists."),
}
+ # xxx move to BaseConnector _get_import_defaults_res_partner
def _get_default_import_values(self, cr, uid, external_session, mapping_id=None, defaults=None, context=None):
if external_session.sync_from_object._name == 'sale.shop':
shop = external_session.sync_from_object
=== modified file 'base_sale_multichannels/sale.py'
--- base_sale_multichannels/sale.py 2013-01-03 10:08:13 +0000
+++ base_sale_multichannels/sale.py 2013-01-11 17:08:20 +0000
@@ -63,7 +63,7 @@
'shop_ids': fields.one2many('sale.shop', 'shop_group_id', 'Sale Shops'),
}
-
+ # xxx move to BaseConnector _get_import_defaults_external_shop_group
def _get_default_import_values(self, cr, uid, external_session, **kwargs):
return {'referential_id' : external_session.referential_id.id}
@@ -539,6 +539,7 @@
vals['update_state_date'] = datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT)
return super(sale_order, self).write(cr, uid, ids, vals, context=context)
+ # xxx move to BaseConnector _get_import_defaults_sale_order
def _get_default_import_values(self, cr, uid, external_session, mapping_id=None, defaults=None, context=None):
shop = False
if external_session.sync_from_object._name == 'sale.shop':
@@ -597,6 +598,7 @@
return False
+ # xxx a deplacer dans BaseConnector sale_order
@catch_error_in_report
def _record_one_external_resource(self, cr, uid, external_session, resource, defaults=None,
mapping=None, mapping_id=None, context=None):
=== modified file 'base_sale_report_synchronizer/__openerp__.py'
--- base_sale_report_synchronizer/__openerp__.py 2012-11-21 13:48:17 +0000
+++ base_sale_report_synchronizer/__openerp__.py 2013-01-11 17:08:20 +0000
@@ -41,7 +41,7 @@
'sale_view.xml',
],
'demo_xml': [],
- 'installable': True,
+ 'installable': False,
'active': False,
}
=== modified file 'product_custom_attributes_shop/__openerp__.py'
--- product_custom_attributes_shop/__openerp__.py 2012-12-07 12:44:57 +0000
+++ product_custom_attributes_shop/__openerp__.py 2013-01-11 17:08:20 +0000
@@ -46,7 +46,7 @@
'security/ir.model.access.csv',
],
'demo_xml': [],
- 'installable': True,
+ 'installable': False,
'active': False,
}
=== modified file 'product_images_sync/__openerp__.py'
--- product_images_sync/__openerp__.py 2012-12-07 12:44:57 +0000
+++ product_images_sync/__openerp__.py 2013-01-11 17:08:20 +0000
@@ -42,6 +42,6 @@
'update_xml': [
],
'demo_xml': [],
- 'installable': True,
+ 'installable': False,
'active': False,
}
=== modified file 'product_links/__openerp__.py'
--- product_links/__openerp__.py 2012-11-21 13:48:17 +0000
+++ product_links/__openerp__.py 2013-01-11 17:08:20 +0000
@@ -40,6 +40,6 @@
'product_links_view.xml',
],
'demo_xml': [],
- 'installable': True,
+ 'installable': False,
'active': False,
}
=== modified file 'product_links_goodies/__openerp__.py'
--- product_links_goodies/__openerp__.py 2012-11-21 13:48:17 +0000
+++ product_links_goodies/__openerp__.py 2013-01-11 17:08:20 +0000
@@ -38,7 +38,7 @@
'product_goodies_data.xml',
],
'demo_xml': [],
- 'installable': True,
+ 'installable': False,
'active': False,
}
=== modified file 'product_links_sync/__openerp__.py'
--- product_links_sync/__openerp__.py 2012-11-21 13:48:17 +0000
+++ product_links_sync/__openerp__.py 2013-01-11 17:08:20 +0000
@@ -38,7 +38,7 @@
'sale_view.xml',
],
'demo_xml': [],
- 'installable': True,
+ 'installable': False,
'active': False,
}
=== modified file 'sale_automatic_workflow/__init__.py'
--- sale_automatic_workflow/__init__.py 2012-04-22 12:49:21 +0000
+++ sale_automatic_workflow/__init__.py 2013-01-11 17:08:20 +0000
@@ -24,7 +24,8 @@
import sale_workflow_process
import payment_method
import automatic_workflow_job
-
+import invoice
+import stock
=== modified file 'sale_automatic_workflow/__openerp__.py'
--- sale_automatic_workflow/__openerp__.py 2012-11-21 13:48:17 +0000
+++ sale_automatic_workflow/__openerp__.py 2013-01-11 17:08:20 +0000
@@ -22,13 +22,17 @@
{
'name': 'sale_automatic_workflow',
- 'version': '6.1.1',
+ 'version': '0.1',
'category': 'Generic Modules/Others',
'license': 'AGPL-3',
'description': """empty""",
'author': 'Akretion',
'website': 'http://www.akretion.com/',
- 'depends': ['sale_quick_payment', 'framework_helpers'],
+ 'depends': [
+ 'sale_quick_payment',
+ 'framework_helpers',
+ 'stock',
+ ],
'init_xml': [],
'update_xml': [
'sale_view.xml',
=== modified file 'sale_automatic_workflow/automatic_workflow_job.py'
--- sale_automatic_workflow/automatic_workflow_job.py 2012-11-21 12:46:53 +0000
+++ sale_automatic_workflow/automatic_workflow_job.py 2013-01-11 17:08:20 +0000
@@ -72,7 +72,7 @@
with commit_now(cr, logger) as cr:
invoice_obj.reconcile_invoice(cr, uid, [invoice_id], context=context)
- picking_obj = self.pool.get('stock.picking')
+ picking_obj = self.pool.get('stock.picking.out')
picking_ids = picking_obj.search(cr, uid, [('state', 'in', ['draft', 'confirmed', 'assigned']), ('workflow_process_id.validate_picking', '=',True)], context=context)
if picking_ids:
logger.debug(_('start to validate pickings : %s') %picking_ids)
=== added file 'sale_automatic_workflow/invoice.py'
--- sale_automatic_workflow/invoice.py 1970-01-01 00:00:00 +0000
+++ sale_automatic_workflow/invoice.py 2013-01-11 17:08:20 +0000
@@ -0,0 +1,112 @@
+# -*- coding: utf-8 -*-
+###############################################################################
+#
+# sale_automatic_workflow for OpenERP
+# Copyright (C) 2011-TODAY Akretion <http://www.akretion.com>.
+# All Rights Reserved
+# @author Sébastien BEAU <sebastien.beau@xxxxxxxxxxxx>
+# 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 <http://www.gnu.org/licenses/>.
+#
+###############################################################################
+from openerp.osv.orm import Model
+from openerp.osv import fields
+
+class account_invoice(Model):
+ _inherit = "account.invoice"
+ _columns = {
+ 'workflow_process_id':fields.many2one('sale.workflow.process', 'Sale Workflow Process'),
+ #TODO propose a merge to add this field by default in acount module
+ 'sale_ids': fields.many2many('sale.order', 'sale_order_invoice_rel', 'invoice_id', 'order_id', 'Sale Orders')
+ }
+
+ def _can_be_reconciled(self, cr, uid, invoice, context=None):
+ if not (invoice.sale_ids and invoice.sale_ids[0].payment_ids and invoice.move_id):
+ return False
+ #Check currency
+ for payment in invoice.sale_ids[0].payment_ids:
+ for move in payment.move_ids:
+ if (move.currency_id.id or invoice.company_id.currency_id.id) != invoice.currency_id.id:
+ return False
+ return True
+
+ def _get_sum_invoice_move_line(self, cr, uid, move_lines, context=None):
+ return self._get_sum_move_line(cr, uid, move_lines, 'debit', context=None)
+
+ def _get_sum_payment_move_line(self, cr, uid, move_lines, context=None):
+ return self._get_sum_move_line(cr, uid, move_lines, 'credit', context=None)
+
+ def _get_sum_move_line(self, cr, uid, move_lines, line_type, context=None):
+ res = {
+ 'max_date': False,
+ 'line_ids': [],
+ 'total_amount': 0,
+ 'total_amount_currency': 0,
+ }
+ for move_line in move_lines:
+ if move_line[line_type] > 0:
+ if move_line.date > res['max_date']:
+ res['max_date'] = move_line.date
+ res['line_ids'].append(move_line.id)
+ res['total_amount'] += move_line[line_type]
+ res['total_amount_currency'] += move_line.amount_currency
+ return res
+
+ def _prepare_write_off(self, cr, uid, invoice, res_invoice, res_payment, context=None):
+ if not context:
+ context = {}
+ ctx = context.copy()
+ if res_invoice['total_amount'] - res_payment['total_amount'] > 0:
+ writeoff_type = 'expense'
+ else:
+ writeoff_type = 'income'
+ account_id, journal_id = invoice.company_id.\
+ get_write_off_information('exchange', writeoff_type, context=context)
+ max_date = max(res_invoice['max_date'], res_payment['max_date'])
+ ctx['p_date'] = max_date
+ period_id = self.pool.get('account.period').find(cr, uid, max_date, context=context)[0]
+ return {
+ 'type': 'auto',
+ 'writeoff_acc_id': account_id,
+ 'writeoff_period_id': period_id,
+ 'writeoff_journal_id': journal_id,
+ 'context': ctx,
+ }
+
+ def reconcile_invoice(self, cr, uid, ids, context=None):
+ """
+ Simple method to reconcile the invoice with the payment generated on the sale order
+ """
+ if not context:
+ context={}
+ precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')
+ obj_move_line = self.pool.get('account.move.line')
+ for invoice in self.browse(cr, uid, ids, context=context):
+ use_currency = invoice.currency_id.id != invoice.company_id.currency_id.id
+ if self._can_be_reconciled(cr, uid, invoice, context=context):
+ payment_move_line = []
+ for payment in invoice.sale_ids[0].payment_ids:
+ payment_move_line += payment.move_ids
+ res_payment = self._get_sum_payment_move_line(cr, uid, payment_move_line, context=context)
+ res_invoice = self._get_sum_invoice_move_line(cr, uid, invoice.move_id.line_id, context=context)
+ line_ids = res_invoice['line_ids'] + res_payment['line_ids']
+ if not use_currency:
+ balance = abs(res_invoice['total_amount']-res_payment['total_amount'])
+ if line_ids and not round(balance, precision):
+ obj_move_line.reconcile(cr, uid, line_ids, context=context)
+ else:
+ balance = abs(res_invoice['total_amount_currency']-res_payment['total_amount_currency'])
+ if line_ids and not round(balance, precision):
+ kwargs = self._prepare_write_off(cr, uid, invoice, res_invoice, res_payment, context=context)
+ obj_move_line.reconcile(cr, uid, line_ids, **kwargs)
+ return True
=== modified file 'sale_automatic_workflow/sale.py'
--- sale_automatic_workflow/sale.py 2012-09-19 13:24:46 +0000
+++ sale_automatic_workflow/sale.py 2013-01-11 17:08:20 +0000
@@ -1,4 +1,4 @@
- # -*- encoding: utf-8 -*-
+# -*- encoding: utf-8 -*-
#################################################################################
# #
# sale_automatic_workflow for OpenERP #
@@ -39,77 +39,3 @@
picking_vals = super(sale_order, self)._prepare_order_picking(cr, uid, order, context=context)
picking_vals['workflow_process_id'] = order.workflow_process_id.id
return picking_vals
-
-class stock_picking(Model):
- _inherit = "stock.picking"
- _columns = {
- 'workflow_process_id':fields.many2one('sale.workflow.process', 'Sale Workflow Process'),
- }
-
- def _prepare_invoice(self, cr, uid, picking, partner, inv_type, journal_id, context=None):
- invoice_vals = super(stock_picking, self)._prepare_invoice(cr, uid, picking, partner, \
- inv_type, journal_id, context=context)
- invoice_vals['workflow_process_id'] = picking.workflow_process_id.id
- if picking.workflow_process_id.invoice_date_is_order_date:
- invoice_vals['date_invoice'] = picking.sale_id.date_order
- return invoice_vals
-
- def validate_picking(self, cr, uid, ids, context=None):
- for picking in self.browse(cr, uid, ids, context=context):
- self.force_assign(cr, uid, [picking.id])
- partial_data = {}
- for move in picking.move_lines:
- partial_data["move" + str(move.id)] = {'product_qty': move.product_qty,
- 'product_uom': move.product_uom.id}
- self.do_partial(cr, uid, [picking.id], partial_data)
- return True
-
-#TODO reimplement me
-# def validate_manufactoring_order(self, cr, uid, origin, context=None): #we do not create class mrp.production to avoid dependence with the module mrp
-# if context is None:
-# context = {}
-# wf_service = netsvc.LocalService("workflow")
-# mrp_prod_obj = self.pool.get('mrp.production')
-# mrp_product_produce_obj = self.pool.get('mrp.product.produce')
-# production_ids = mrp_prod_obj.search(cr, uid, [('origin', 'ilike', origin)])
-# for production in mrp_prod_obj.browse(cr, uid, production_ids):
-# mrp_prod_obj.force_production(cr, uid, [production.id])
-# wf_service.trg_validate(uid, 'mrp.production', production.id, 'button_produce', cr)
-# context.update({'active_model': 'mrp.production', 'active_ids': [production.id], 'search_default_ready': 1, 'active_id': production.id})
-# produce = mrp_product_produce_obj.create(cr, uid, {'mode': 'consume_produce', 'product_qty': production.product_qty}, context)
-# mrp_product_produce_obj.do_produce(cr, uid, [produce], context)
-# self.validate_manufactoring_order(cr, uid, production.name, context)
-# return True
-#
-
-class account_invoice(Model):
- _inherit = "account.invoice"
- _columns = {
- 'workflow_process_id':fields.many2one('sale.workflow.process', 'Sale Workflow Process'),
- #TODO propose a merge to add this field by default in acount module
- 'sale_ids': fields.many2many('sale.order', 'sale_order_invoice_rel', 'invoice_id', 'order_id', 'Sale Orders')
- }
-
- def reconcile_invoice(self, cr, uid, ids, context=None):
- """
- Simple method to reconcile the invoice with the payment generated on the sale order
- """
- obj_move_line = self.pool.get('account.move.line')
- for invoice in self.browse(cr, uid, ids, context=context):
- line_ids = []
- payment_amount = 0
- invoice_amount = 0
- if invoice.sale_ids and invoice.sale_ids[0].payment_id and invoice.move_id:
- for move in invoice.sale_ids[0].payment_id.move_ids:
- if move.credit > 0 and not move.reconcile_id:
- line_ids.append(move.id)
- payment_amount += move.credit
- for move in invoice.move_id.line_id:
- if move.debit > 0 and not move.reconcile_id:
- line_ids.append(move.id)
- invoice_amount += move.debit
- balance = abs(payment_amount-invoice_amount)
- precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')
- if line_ids and not round(balance, precision):
- obj_move_line.reconcile(cr, uid, line_ids, context=context)
- return True
=== added file 'sale_automatic_workflow/stock.py'
--- sale_automatic_workflow/stock.py 1970-01-01 00:00:00 +0000
+++ sale_automatic_workflow/stock.py 2013-01-11 17:08:20 +0000
@@ -0,0 +1,65 @@
+# -*- coding: utf-8 -*-
+###############################################################################
+#
+# sale_automatic_workflow for OpenERP
+# Copyright (C) 2011-TODAY Akretion <http://www.akretion.com>.
+# All Rights Reserved
+# @author Sébastien BEAU <sebastien.beau@xxxxxxxxxxxx>
+# 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 <http://www.gnu.org/licenses/>.
+#
+###############################################################################
+from openerp.osv.orm import Model
+from openerp.osv import fields
+
+class stock_picking_out(Model):
+ _inherit = "stock.picking.out"
+ _columns = {
+ 'workflow_process_id':fields.many2one('sale.workflow.process', 'Sale Workflow Process'),
+ }
+
+ def _prepare_invoice(self, cr, uid, picking, partner, inv_type, journal_id, context=None):
+ invoice_vals = super(stock_picking_out, self)._prepare_invoice(cr, uid, picking, partner, \
+ inv_type, journal_id, context=context)
+ invoice_vals['workflow_process_id'] = picking.workflow_process_id.id
+ if picking.workflow_process_id.invoice_date_is_order_date:
+ invoice_vals['date_invoice'] = picking.sale_id.date_order
+ return invoice_vals
+
+ def validate_picking(self, cr, uid, ids, context=None):
+ for picking in self.browse(cr, uid, ids, context=context):
+ self.force_assign(cr, uid, [picking.id])
+ partial_data = {}
+ for move in picking.move_lines:
+ partial_data["move" + str(move.id)] = {'product_qty': move.product_qty,
+ 'product_uom': move.product_uom.id}
+ self.do_partial(cr, uid, [picking.id], partial_data)
+ return True
+
+#TODO reimplement me
+# def validate_manufactoring_order(self, cr, uid, origin, context=None): #we do not create class mrp.production to avoid dependence with the module mrp
+# if context is None:
+# context = {}
+# wf_service = netsvc.LocalService("workflow")
+# mrp_prod_obj = self.pool.get('mrp.production')
+# mrp_product_produce_obj = self.pool.get('mrp.product.produce')
+# production_ids = mrp_prod_obj.search(cr, uid, [('origin', 'ilike', origin)])
+# for production in mrp_prod_obj.browse(cr, uid, production_ids):
+# mrp_prod_obj.force_production(cr, uid, [production.id])
+# wf_service.trg_validate(uid, 'mrp.production', production.id, 'button_produce', cr)
+# context.update({'active_model': 'mrp.production', 'active_ids': [production.id], 'search_default_ready': 1, 'active_id': production.id})
+# produce = mrp_product_produce_obj.create(cr, uid, {'mode': 'consume_produce', 'product_qty': production.product_qty}, context)
+# mrp_product_produce_obj.do_produce(cr, uid, [produce], context)
+# self.validate_manufactoring_order(cr, uid, production.name, context)
+# return True
+#
=== modified file 'sale_exceptions/__openerp__.py'
--- sale_exceptions/__openerp__.py 2012-11-21 13:48:17 +0000
+++ sale_exceptions/__openerp__.py 2013-01-11 17:08:20 +0000
@@ -25,7 +25,7 @@
{
'name': 'Sale Exceptions',
- 'version': '6.1.0',
+ 'version': '0.1',
'category': 'Generic Modules/Sale',
'description': """
This module allows you attach several customizable exceptions to your sale order in a way that you can filter orders by exceptions type and fix them.
=== modified file 'sale_exceptions/sale.py'
--- sale_exceptions/sale.py 2012-12-07 14:11:56 +0000
+++ sale_exceptions/sale.py 2013-01-11 17:08:20 +0000
@@ -33,6 +33,7 @@
class sale_exception(Model):
_name = "sale.exception"
_description = "Sale Exceptions"
+ _order="active desc, sequence asc"
_columns = {
'name': fields.char('Exception Name', size=64, required=True, translate=True),
'description': fields.text('Description', translate=True),
@@ -106,6 +107,7 @@
view_id = model_data_obj.get_object_reference(
cr, uid, 'sale_exceptions', 'view_sale_exception_confirm')[1]
action = {
+ 'name': _("Exceptions On Sale Order"),
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
@@ -117,14 +119,12 @@
}
return action
- def button_order_confirm(self, cr, uid, ids, context=None):
+ def action_button_confirm(self, cr, uid, ids, context=None):
exception_ids = self.detect_exceptions(cr, uid, ids, context=context)
if exception_ids:
return self._popup_exceptions(cr, uid, ids[0], context=context)
else:
- wf_service = netsvc.LocalService("workflow")
- wf_service.trg_validate(uid, 'sale.order', ids[0], 'order_confirm', cr)
- return True
+ return super(sale_order, self).action_button_confirm(cr, uid, ids, context=context)
def test_exceptions(self, cr, uid, ids, context=None):
"""
=== modified file 'sale_exceptions/sale_view.xml'
--- sale_exceptions/sale_view.xml 2012-10-22 14:39:18 +0000
+++ sale_exceptions/sale_view.xml 2013-01-11 17:08:20 +0000
@@ -2,29 +2,13 @@
<openerp>
<data>
- <record id="view_sale_exception_search" model="ir.ui.view">
- <field name="name">sale.exception.view.search</field>
- <field name="model">sale.exception</field>
- <field name="type">search</field>
- <field name="arch" type="xml">
- <search string="Search Sale Exceptions">
- <group>
- <filter name="all" icon="gtk-fullscreen" string="See All" domain="['|', ('active','=', False), ('active','=', True)]" help="See all rule active or unactive"/>
- </group>
- <newline/>
- <group>
- <field name="name"/>
- </group>
- </search>
- </field>
- </record>
-
<record id="view_sale_exception_tree" model="ir.ui.view">
<field name="name">sale.exception.tree</field>
<field name="model">sale.exception</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Sale Exception">
+ <field name="active"/>
<field name="name"/>
<field name="description"/>
<field name="model"/>
@@ -66,7 +50,7 @@
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_sale_exception_tree"/>
- <field name="search_view_id" ref="view_sale_exception_search"/>
+ <field name="context">{'active_test': False}</field>
</record>
<menuitem action="action_sale_test_tree" id="menu_sale_test" parent="base.menu_sale_config_sales" />
@@ -79,28 +63,17 @@
<field name="priority">100</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
- <xpath expr="/form/notebook/page[@string='Sales Order']/group/field[@name='state']"
- position="after">
+ <field name="name" position="after">
<field name="main_exception_id" nolabel="1"
attrs="{'invisible':[('main_exception_id','=', False)]}"/>
- </xpath>
- <xpath expr="/form/notebook/page[@string='Other Information']/separator[@string='Notes']"
- position="before">
+ </field>
+ <xpath expr="//page[@string='Other Information']/group"
+ position="inside">
<group name="exception" colspan="2" col="2">
<separator string="Exception" colspan="2"/>
<field name="exceptions_ids" colspan="2" nolabel="1"/>
</group>
- <group name="notes" colspan="2" col="2">
- <separator colspan="2" string="Notes"/>
- <field colspan="2" name="note" nolabel="1"/>
- </group>
</xpath>
- <xpath expr="/form/notebook/page[@string='Other Information']/separator[@string='Notes']" position="replace"/>
- <xpath expr="/form/notebook/page[@string='Other Information']/field[@name='note']" position="replace"/>
- <button name="order_confirm" position="attributes">
- <attribute name="name">button_order_confirm</attribute>
- <attribute name="type">object</attribute>
- </button>
</field>
</record>
=== modified file 'sale_exceptions/wizard/sale_exception_confirm_view.xml'
--- sale_exceptions/wizard/sale_exception_confirm_view.xml 2012-03-23 14:41:24 +0000
+++ sale_exceptions/wizard/sale_exception_confirm_view.xml 2013-01-11 17:08:20 +0000
@@ -7,26 +7,25 @@
<field name="model">sale.exception.confirm</field>
<field name="type">form</field>
<field name="arch" type="xml">
- <form string="Sale Exceptions">
- <separator colspan="4" string="Exceptions on the sale order" />
- <field name="exception_ids" nolabel="1" colspan="4">
- <form string="Sale Exception">
- <field name="name" colspan="4"/>
- <field name="description" colspan="4"/>
- </form>
- <tree string="Sale Exceptions">
- <field name="name"/>
- <field name="description"/>
- </tree>
- </field>
- <newline/>
- <field name="ignore" groups='base.group_sale_manager'/>
- <newline/>
- <separator colspan="4"/>
- <group col="2" colspan="4">
+ <form string="Sale Exceptions On Sale Order" version="7.0">
+ <group>
+ <field name="exception_ids" nolabel="1" colspan="4">
+ <form string="Sale Exception">
+ <field name="name" colspan="4"/>
+ <field name="description" colspan="4"/>
+ </form>
+ <tree string="Sale Exceptions">
+ <field name="name"/>
+ <field name="description"/>
+ </tree>
+ </field>
+ <newline/>
+ <field name="ignore" groups='base.group_sale_manager'/>
+ </group>
+ <footer>
<button name="action_confirm" string="_Ok"
colspan="1" type="object" icon="gtk-ok" />
- </group>
+ </footer>
</form>
</field>
</record>
=== modified file 'sale_quick_payment/__init__.py'
--- sale_quick_payment/__init__.py 2012-05-18 09:00:34 +0000
+++ sale_quick_payment/__init__.py 2013-01-11 17:08:20 +0000
@@ -23,6 +23,4 @@
import sale
import payment_method
import wizard
-import company
-
-
+import account_voucher
=== modified file 'sale_quick_payment/__openerp__.py'
--- sale_quick_payment/__openerp__.py 2012-12-07 12:44:57 +0000
+++ sale_quick_payment/__openerp__.py 2013-01-11 17:08:20 +0000
@@ -22,7 +22,7 @@
{
'name': 'sale_quick_payment',
- 'version': '6.1.0',
+ 'version': '0.1',
'category': 'Generic Modules/Others',
'license': 'AGPL-3',
'description': """
@@ -36,16 +36,16 @@
'author': 'Akretion',
'website': 'http://www.akretion.com/',
'depends': [
- 'sale',
+ 'sale_exceptions',
'account_voucher',
],
'init_xml': [],
- 'update_xml': [
+ 'update_xml': [
+ 'wizard/pay_sale_order.xml',
'sale_view.xml',
'payment_method_view.xml',
- 'wizard/pay_sale_order.xml',
- 'company_view.xml',
'security/ir.model.access.csv',
+ 'settings/sale.exception.csv',
],
'demo_xml': [],
'installable': True,
=== added file 'sale_quick_payment/account_voucher.py'
--- sale_quick_payment/account_voucher.py 1970-01-01 00:00:00 +0000
+++ sale_quick_payment/account_voucher.py 2013-01-11 17:08:20 +0000
@@ -0,0 +1,33 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+#
+# sale_quick_payment for OpenERP
+# Copyright (C) 2012-TODAY Akretion <http://www.akretion.com>.
+# All Rights Reserved
+# @author Sébastien BEAU <sebastien.beau@xxxxxxxxxxxx>
+# 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 <http://www.gnu.org/licenses/>.
+#
+###############################################################################
+
+from openerp.osv.orm import Model
+from openerp.osv import fields
+
+class payment_method(Model):
+ _inherit = "account.voucher"
+
+ _columns = {
+ 'order_ids': fields.many2many('sale.order', string='Sale Order'),
+ }
+
+
=== removed file 'sale_quick_payment/company.py'
--- sale_quick_payment/company.py 2012-08-21 13:57:44 +0000
+++ sale_quick_payment/company.py 1970-01-01 00:00:00 +0000
@@ -1,33 +0,0 @@
-# -*- encoding: utf-8 -*-
-#################################################################################
-# #
-# sale_quick_payment for OpenERP #
-# Copyright (C) 2011 Akretion Sébastien BEAU <sebastien.beau@xxxxxxxxxxxx> #
-# #
-# 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 <http://www.gnu.org/licenses/>. #
-# #
-#################################################################################
-
-from openerp.osv.orm import Model
-from openerp.osv import fields
-from tools.translate import _
-
-class res_company(Model):
- """Override company to add payment configuration"""
- _inherit = "res.company"
- _columns = {
- 'sale_order_must_be_paid':fields.boolean('Sale Order Must Be Paid',
- help='If this option is check an order can not be validaded without payment'
- ),
- }
=== removed file 'sale_quick_payment/company_view.xml'
--- sale_quick_payment/company_view.xml 2012-05-18 09:00:34 +0000
+++ sale_quick_payment/company_view.xml 1970-01-01 00:00:00 +0000
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- sale_quick_payment for OpenERP
- Copyright (C) 2012 Akretion Sébastien BEAU <sebastien.beau@xxxxxxxxxxxx>
- The licence is in the file __openerp__.py
--->
-
-
-<openerp>
- <data>
- <record model="ir.ui.view" id="view_company_form">
- <field name="name">sale_quick_payment.view_company_form</field>
- <field name="model">res.company</field>
- <field name="inherit_id" ref="base.view_company_form"/>
- <field name="type">form</field>
- <field name="arch" type="xml">
- <page string="Configuration" position="inside">
- <separator string="Sale Configuration" colspan="4"/>
- <field name="sale_order_must_be_paid"/>
- </page>
- </field>
- </record>
- </data>
-</openerp>
-
=== added directory 'sale_quick_payment/migrations'
=== added directory 'sale_quick_payment/migrations/0.1'
=== added file 'sale_quick_payment/migrations/0.1/post-migration.py'
--- sale_quick_payment/migrations/0.1/post-migration.py 1970-01-01 00:00:00 +0000
+++ sale_quick_payment/migrations/0.1/post-migration.py 2013-01-11 17:08:20 +0000
@@ -0,0 +1,35 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+#
+# sale_quick_payment for OpenERP
+# Copyright (C) 2012-TODAY Akretion <http://www.akretion.com>.
+# All Rights Reserved
+# @author Sébastien BEAU <sebastien.beau@xxxxxxxxxxxx>
+# 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 <http://www.gnu.org/licenses/>.
+#
+###############################################################################
+
+""" r0.1: Migration 6.1 => 7.0.0.1
+ migrate the field payment_id from one2many to payment_ids many2many
+"""
+__name__ = ("sale.order:: V7 change/rename the field payment_id into a"
+ "many2many with the name payment_ids")
+
+def migrate(cr, version):
+ cr.execute("INSERT INTO account_voucher_sale_order_rel"
+ "(sale_order_id, account_voucher_id) "
+ "(SELECT id, payment_id FROM "
+ " sale_order "
+ "WHERE payment_id IS NOT NULL )")
+
=== modified file 'sale_quick_payment/sale.py'
--- sale_quick_payment/sale.py 2012-12-07 12:44:57 +0000
+++ sale_quick_payment/sale.py 2013-01-11 17:08:20 +0000
@@ -25,20 +25,48 @@
import netsvc
from collections import Iterable
from openerp.tools.translate import _
+import decimal_precision as dp
class sale_order(Model):
_inherit = "sale.order"
+ def _get_order_from_voucher(self, cr, uid, ids, context=None):
+ result = []
+ for voucher in self.pool.get('account.voucher').browse(cr, uid, ids, context=context):
+ for order in voucher.order_ids:
+ result.append(order.id)
+ return list(set(result))
+
+ def _get_order_from_line(self, cr, uid, ids, context=None):
+ return self.pool.get('sale.order')._get_order(cr, uid, ids, context=context)
+
+ def _amount_residual(self, cr, uid, ids, field_name, args, context=None):
+ res = {}
+ #TODO add here the support of multi-currency payment if need
+ for order in self.browse(cr, uid, ids, context=context):
+ res[order.id] = order.amount_total
+ for payment in order.payment_ids:
+ if payment.state == 'posted':
+ res[order.id] -= payment.amount
+ return res
+
_columns = {
- 'payment_id': fields.many2one('account.voucher', 'Payment'),
+ 'payment_ids': fields.many2many('account.voucher', string='Payments'),
'payment_method_id': fields.many2one('payment.method', 'Payment Method'),
+ 'residual': fields.function(_amount_residual, digits_compute=dp.get_precision('Account'), string='Balance',
+ store = {
+ 'sale.order': (lambda self, cr, uid, ids, c={}: ids, ['order_line', 'payment_ids'], 10),
+ 'sale.order.line': (_get_order_from_line, ['price_unit', 'tax_id', 'discount', 'product_uom_qty'], 20),
+ 'account.voucher': (_get_order_from_voucher, ['amount'], 30),
+ },
+ ),
}
def copy(self, cr, uid, id, default=None, context=None):
if not default:
default = {}
default.update({
- 'payment_id': False,
+ 'payment_ids': False,
})
return super(sale_order, self).copy(cr, uid, id, default, context=context)
@@ -132,14 +160,6 @@
wf_service = netsvc.LocalService("workflow")
wf_service.trg_validate(
uid, 'account.voucher', voucher_id, 'proforma_voucher', cr)
- sale.write({'payment_id': voucher_id}, context=context)
+ sale.write({'payment_ids': [(4,voucher_id)]}, context=context)
return True
- def button_order_confirm(self, cr, uid, ids, context=None):
- for order in self.browse(cr, uid, ids, context=context):
- if order.company_id.sale_order_must_be_paid and not order.payment_id:
- raise except_osv(_('User Error!'),
- _('The sale Order %s Must be paid before validation') % (order.name))
- return super(sale_order, self).button_order_confirm(cr, uid, ids, context=context)
-
-
=== modified file 'sale_quick_payment/sale_view.xml'
--- sale_quick_payment/sale_view.xml 2012-05-24 20:44:25 +0000
+++ sale_quick_payment/sale_view.xml 2013-01-11 17:08:20 +0000
@@ -17,15 +17,23 @@
<field eval="16" name="priority"/>
<field name="type">form</field>
<field name="arch" type="xml">
+ <button name="print_quotation" position="after">
+ <button name="%(open_pay_sale_order)d" string="Register Payments" type="action" states="draft,sent"/>
+ </button>
<page string="Other Information" position="after">
<page name="automation_information" string="Automation Information">
<group name="payment_information" colspan="4">
- <separator string="Payment Information" colspan="4"/>
<field name="payment_method_id" />
- <field name="payment_id" />
+ <group name="payments" colspan="4">
+ <separator string="Payments" colspan="4"/>
+ <field name="payment_ids" nolabel="1" />
+ </group>
</group>
</page>
</page>
+ <field name="amount_total" position="after">
+ <field name="residual" invisible="1"/>
+ </field>
</field>
</record>
=== added directory 'sale_quick_payment/settings'
=== added file 'sale_quick_payment/settings/sale.exception.csv'
--- sale_quick_payment/settings/sale.exception.csv 1970-01-01 00:00:00 +0000
+++ sale_quick_payment/settings/sale.exception.csv 2013-01-11 17:08:20 +0000
@@ -0,0 +1,3 @@
+id,name,description,sequence,model,code
+must_be_paid,Sale order must be paid before validation,The sale order must be paid before the validation. Please fix it,50,sale.order,"if order.residual > 0:
+ failed = True"
=== modified file 'sale_quick_payment/wizard/pay_sale_order.py'
--- sale_quick_payment/wizard/pay_sale_order.py 2012-08-21 13:57:44 +0000
+++ sale_quick_payment/wizard/pay_sale_order.py 2013-01-11 17:08:20 +0000
@@ -25,6 +25,8 @@
import decimal_precision as dp
from datetime import datetime
+#TODO add button on sale_form header instead of more button
+
class pay_sale_order(TransientModel):
_name = 'pay.sale.order'
_description = 'Wizard to generate a payment from the sale order'
@@ -35,15 +37,21 @@
'date': fields.datetime('Payment Date'),
}
- def _get_journal_id(self, cr, uid, args):
- if args.get('payment_method_id'):
- payment_method = self.pool.get('payment.method').browse(cr, uid, args['payment_method_id'])
- return payment_method.journal_id.id
+ def _get_journal_id(self, cr, uid, context=None):
+ if context is None:
+ context = {}
+ if context.get('active_id'):
+ order = self.pool.get('sale.order').browse(cr, uid, context['active_id'], context=context)
+ if order.payment_method_id:
+ return order.payment_method_id.journal_id.id
return False
- def _get_amount(self, cr, uid, args):
- if args.get('amount_total'):
- return args['amount_total']
+ def _get_amount(self, cr, uid, context=None):
+ if context is None:
+ context = {}
+ if context.get('active_id'):
+ order = self.pool.get('sale.order').browse(cr, uid, context['active_id'], context=context)
+ return order.residual
return False
_defaults = {
@@ -60,6 +68,18 @@
@param ids: List of account chart’s IDs
@return: dictionary of Product list window for a given attributs set
"""
- for wizard in self.browse(cr, uid, ids, context=context):
- self.pool.get('sale.order').pay_sale_order(cr, uid, context['active_id'], wizard.journal_id.id, wizard.amount, wizard.date, context=context)
+ wizard = self.browse(cr, uid, ids[0], context=context)
+ self.pool.get('sale.order').pay_sale_order(cr, uid, context['active_id'], wizard.journal_id.id, wizard.amount, wizard.date, context=context)
return {'type': 'ir.actions.act_window_close'}
+
+ def pay_sale_order_and_confirm(self, cr, uid, ids, context=None):
+ """
+ Pay the sale order
+ @param cr: the current row, from the database cursor,
+ @param uid: the current user’s ID for security checks,
+ @param ids: List of account chart’s IDs
+ @return: dictionary of Product list window for a given attributs set
+ """
+ self.pay_sale_order(cr, uid, ids, context=context)
+ return self.pool.get('sale.order').action_button_confirm(cr, uid, [context['active_id']], context=context)
+
=== modified file 'sale_quick_payment/wizard/pay_sale_order.xml'
--- sale_quick_payment/wizard/pay_sale_order.xml 2012-04-22 12:48:34 +0000
+++ sale_quick_payment/wizard/pay_sale_order.xml 2013-01-11 17:08:20 +0000
@@ -6,14 +6,19 @@
<field name="model">pay.sale.order</field>
<field name="type">form</field>
<field name="arch" type="xml">
- <form string="Pay Sale Order">
- <field name="journal_id" colspan="4"/>
- <field name="amount" colspan="4"/>
- <field name="date" colspan="4"/>
- <group colspan="4">
- <button icon="gtk-cancel" special="cancel" string="Cancel"/>
- <button icon="gtk-ok" name="pay_sale_order" string="Pay" type="object"/>
+ <form string="Pay Sale Order" version="7.0">
+ <group>
+ <field name="journal_id" string="Journal"/>
+ <field name="amount" string="Paid Amount"/>
+ <field name="date" string="Date"/>
</group>
+ <footer>
+ <button string="Pay" name="pay_sale_order" type="object" class="oe_highlight"/>
+ or
+ <button string="Pay And Confirm Order" name="pay_sale_order_and_confirm" type="object" class="oe_highlight"/>
+ or
+ <button string="Cancel" class="oe_link" special="cancel"/>
+ </footer>
</form>
</field>
</record>
@@ -26,13 +31,5 @@
<field name="target">new</field>
<field name="view_id" ref="pay_sale_order_view"/>
</record>
-
- <record id="ir_action_open_pay_sale_order" model="ir.values">
- <field name="key2">client_action_multi</field>
- <field name="model">sale.order</field>
- <field name="name">Sale.Order</field>
- <field eval="'ir.actions.act_window,%d'%open_pay_sale_order" name="value"/>
- <field eval="True" name="object"/>
- </record>
</data>
</openerp>
Follow ups