Browse Source

Relacionar con crm pedidos y presupuesto

sebastian 5 năm trước cách đây
commit
520c33a1ad
11 tập tin đã thay đổi với 194 bổ sung0 xóa
  1. 4 0
      __init__.py
  2. BIN
      __init__.pyc
  3. 31 0
      __openerp__.py
  4. 89 0
      sale_crm.py
  5. BIN
      sale_crm.pyc
  6. 45 0
      sale_crm_view.xml
  7. BIN
      static/description/icon.png
  8. 3 0
      wizard/__init__.py
  9. BIN
      wizard/__init__.pyc
  10. 22 0
      wizard/crm_make_sale.py
  11. BIN
      wizard/crm_make_sale.pyc

+ 4 - 0
__init__.py

@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+
+from . import sale_crm
+from . import wizard

BIN
__init__.pyc


+ 31 - 0
__openerp__.py

@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+# © 2016 Akretion (http://www.akretion.com)
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+# @author Alexis de Lattre <alexis.delattre@akretion.com>
+
+{
+    'name': 'Sale CRM Usability',
+    'version': '8.0.1.0.0',
+    'category': 'Customer Relationship Management',
+    'license': 'AGPL-3',
+    'summary': 'Link between opportunities and sale orders',
+    'description': """
+Sale CRM Usability
+==================
+
+This module adds a One2many link from opportunities to sale orders.
+
+When a sale order linked to an opportunity is confirmed, the opportunity
+is automatically moved to the *Won* step.
+
+When you click on the button *Mark as lost* on an opportunity, the related quotations (*draft* or *sent* state) are automatically cancelled.
+
+This module has been written by Alexis de Lattre from Akretion
+<alexis.delattre@akretion.com>.
+    """,
+    'author': 'Akretion',
+    'website': 'http://www.akretion.com',
+    'depends': ['sale_crm'],
+    'data': ['sale_crm_view.xml'],
+    'installable': True,
+}

+ 89 - 0
sale_crm.py

@@ -0,0 +1,89 @@
+# -*- coding: utf-8 -*-
+# © 2016 Akretion (http://www.akretion.com)
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+# @author Alexis de Lattre <alexis.delattre@akretion.com>
+
+from openerp import models, fields, api, _, workflow
+from openerp.exceptions import Warning as UserError
+
+
+class SaleOrder(models.Model):
+    _inherit = 'sale.order'
+
+    lead_id = fields.Many2one(
+        'crm.lead', string='Opportunity')
+
+    @api.multi
+    def action_button_confirm(self):
+        res = super(SaleOrder, self).action_button_confirm()
+        won_stage = self.env.ref('crm.stage_lead6')
+        for order in self:
+            if order.lead_id:
+                order.lead_id.stage_id = won_stage
+                order.lead_id.message_post(_(
+                    "Stage automatically updated to <i>Won</i> upon "
+                    "confirmation of the quotation <b>%s</b>" % order.name))
+        return res
+
+
+class CrmLead(models.Model):
+    _inherit = 'crm.lead'
+
+    sale_ids = fields.One2many(
+        'sale.order', 'lead_id', string='Quotations', readonly=True)
+
+    @api.multi
+    def view_sale_orders(self):
+        self.ensure_one()
+        if self.sale_ids:
+            action = {
+                'name': _('Quotations'),
+                'type': 'ir.actions.act_window',
+                'res_model': 'sale.order',
+                'target': 'current',
+                'context':
+                "{'default_partner_id': %s, 'default_lead_id': %s}" % (
+                    self.partner_id.id or False, self[0].id),
+                }
+            if len(self.sale_ids) == 1:
+                action.update({
+                    'view_mode': 'form,tree,calendar,graph',
+                    'res_id': self.sale_ids[0].id,
+                    })
+            else:
+                action.update({
+                    'view_mode': 'tree,form,calendar,graph',
+                    'domain': "[('id', 'in', %s)]" % self.sale_ids.ids,
+                    })
+            return action
+        else:
+            raise UserError(_(
+                'There are no quotations linked to this opportunity'))
+
+    @api.model
+    def create(self, vals):
+        if vals is None:
+            vals = {}
+        if self._context.get('usability_default_stage_xmlid'):
+            stage = self.env.ref(self._context['usability_default_stage_xmlid'])
+            vals['stage_id'] = stage.id
+        return super(CrmLead, self).create(vals)
+
+    @api.multi
+    def case_mark_lost(self):
+        """When opportunity is marked as lost, cancel the related quotations
+        I don't inherit the write but the button, because it leaves a waty to
+        mask lead as lost and not cancel the quotations
+        """
+        res = super(CrmLead, self).case_mark_lost()
+        sales = self.env['sale.order'].search([
+            ('lead_id', 'in', self.ids),
+            ('state', 'in', ('draft', 'sent'))])
+        for so in sales:
+            workflow.trg_validate(
+                self._uid, 'sale.order', so.id, 'cancel', self._cr)
+            so.message_post(_(
+                'The related opportunity has been marked as lost, '
+                'therefore this quotation has been automatically cancelled.'))
+        return res
+

BIN
sale_crm.pyc


+ 45 - 0
sale_crm_view.xml

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+   Copyright (C) 2016 Akretion (http://www.akretion.com/)
+   @author: Alexis de Lattre <alexis.delattre@akretion.com>
+   The licence is in the file __openerp__.py
+-->
+
+<openerp>
+<data>
+
+<record id="view_order_form" model="ir.ui.view">
+    <field name="name">sale_crm_usability.sale.order.form</field>
+    <field name="model">sale.order</field>
+    <field name="inherit_id" ref="sale.view_order_form"/>
+    <field name="arch" type="xml">
+        <field name="pricelist_id" position="after">
+            <field name="lead_id"
+                domain="[('type', '=', 'opportunity'), ('partner_id', '=', partner_id)]"
+                context="{'default_type': 'opportunity', 'default_partner_id': partner_id, 'default_user_id': uid, 'stage_type': 'opportunity', 'usability_default_stage_xmlid': 'crm.stage_lead4'}"/>
+        </field>
+    </field>
+</record>
+
+<record id="crm_case_form_view_oppor" model="ir.ui.view">
+    <field name="name">sale_crm_usability.opportunity.form</field>
+    <field name="model">crm.lead</field>
+    <field name="inherit_id" ref="sale_crm.crm_case_form_view_oppor"/>
+    <field name="priority">100</field>
+    <!-- priority so that the button "View Quotations" is the last button -->
+    <field name="arch" type="xml">
+        <field name="stage_id" position="before">
+            <button name="view_sale_orders" type="object" string="View Quotations"
+                attrs="{'invisible': [('sale_ids', '=', False)]}"/>
+        </field>
+        <notebook position="inside">
+            <page name="sale_orders" string="Sale Orders">
+                <field name="sale_ids" nolabel="1"/>
+            </page>
+        </notebook>
+    </field>
+</record>
+
+
+</data>
+</openerp>

BIN
static/description/icon.png


+ 3 - 0
wizard/__init__.py

@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+from . import crm_make_sale

BIN
wizard/__init__.pyc


+ 22 - 0
wizard/crm_make_sale.py

@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# © 2016 Akretion (http://www.akretion.com)
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+# @author Alexis de Lattre <alexis.delattre@akretion.com>
+
+from openerp import models, api
+
+
+class CrmMakeSale(models.TransientModel):
+    _inherit = 'crm.make.sale'
+
+    @api.multi
+    def makeOrder(self):
+        # the button to start this wizard is only available in form view
+        # This code should be updated when we will have a _prepare method
+        # in the create of the sale order
+        self.ensure_one()
+        value = super(CrmMakeSale, self).makeOrder()
+        if value.get('res_model') == 'sale.order' and value.get('res_id'):
+            so = self.env['sale.order'].browse(value['res_id'])
+            so.lead_id = self._context.get('active_id')
+        return value

BIN
wizard/crm_make_sale.pyc