partner.py 5.85 KB
from sqlite3 import DatabaseError

from odoo import api, fields, models, _
from psycopg2 import sql, DatabaseError
import logging

_logger = logging.getLogger(__name__)


class ResPartner(models.Model):
    _inherit = 'res.partner'
    supplier_rank = fields.Integer(default=0)
    customer_rank = fields.Integer(default=0)
    company_id = fields.Many2one('res.company', string="Company",
                                 default=lambda self: self.env.company.id
                                 if not self.company_id else False
                                 )
    country_id = fields.Many2one('res.country', string="Country",
                                 default=lambda self: self.env.company.country_id
                                 if not self.country_id else False
                                 )
    state_id = fields.Many2one('res.country.state', string="State",
                               domain="[('country_id', '=?', country_id)]",
                               default=lambda self: self.env.company.state_id
                               if not self.state_id else False
                               )
    district_id = fields.Many2one('res.district', string="Kabupaten/Kota",
                                  ondelete='restrict',
                                  domain="[('state_id', '=?', state_id)]",
                                  default=lambda self: self.env.company.district_id
                                  if not self.district_id else False
                                  )
    sub_district_id = fields.Many2one('res.district.sub', string="Kecamatan",
                                      ondelete='restrict',
                                      domain="[('district_id', '=?', district_id)]"
                                      )
    village_id = fields.Many2one('res.district.village', string="Desa/Kelurahan",
                                 ondelete='restrict',
                                 domain="[('sub_district_id', '=?', sub_district_id)]"
                                 )

    type = fields.Selection(
        selection_add=[('op', 'Objek Pajak'),
                       ('wp', 'Wajib Pajak'),
                       ],
        ondelete={
            'op': 'cascade',
            'wp': 'cascade',
        })

    @api.onchange('parent_id')
    def onchange_parent_id(self):
        # return values in result, as this method is used by _fields_sync()
        if not self.parent_id:
            return
        result = {}
        partner = self._origin
        if partner.parent_id and partner.parent_id != self.parent_id and self.type != 'op':
            result['warning'] = {
                'title': _('Warning'),
                'message': _('Changing the company of a contact should only be done if it '
                             'was never correctly set. If an existing contact starts working for a new '
                             'company then a new contact should be created under that new '
                             'company. You can use the "Discard" button to abandon this change.')
            }
        if partner.type == 'contact' or self.type == 'contact':
            # for contacts: copy the parent address, if set (aka, at least one
            # value is set in the address: otherwise, keep the one from the
            # contact)
            address_fields = self._address_fields()
            if any(self.parent_id[key] for key in address_fields):
                def convert(value):
                    return value.id if isinstance(value, models.BaseModel) else value

                result['value'] = {key: convert(self.parent_id[key]) for key in address_fields}
        return result

    # def _get_name_search_order_by_fields(self):
    #     res = super()._get_name_search_order_by_fields()
    #     partner_search_mode = self.env.context.get('res_partner_search_mode')
    #     if not partner_search_mode in ('customer', 'supplier'):
    #         return res
    #     order_by_field = 'COALESCE(res_partner.%s, 0) DESC,'
    #     if partner_search_mode == 'customer':
    #         field = 'customer_rank'
    #     else:
    #         field = 'supplier_rank'
    #
    #     order_by_field = order_by_field % field
    #     return '%s, %s' % (res, order_by_field % field) if res else order_by_field

    @api.model_create_multi
    def create(self, vals_list):
        search_partner_mode = self.env.context.get('res_partner_search_mode')
        is_customer = search_partner_mode == 'customer'
        is_supplier = search_partner_mode == 'supplier'
        if search_partner_mode:
            for vals in vals_list:
                if is_customer and 'customer_rank' not in vals:
                    vals['customer_rank'] = 1
                elif is_supplier and 'supplier_rank' not in vals:
                    vals['supplier_rank'] = 1
        return super().create(vals_list)

    def _increase_rank(self, field, n=1):
        if self.ids and field in ['customer_rank', 'supplier_rank']:
            try:
                with self.env.cr.savepoint(flush=False):
                    query = sql.SQL("""
                        SELECT {field} FROM res_partner WHERE ID IN %(partner_ids)s FOR UPDATE NOWAIT;
                        UPDATE res_partner SET {field} = {field} + %(n)s
                        WHERE id IN %(partner_ids)s
                    """).format(field=sql.Identifier(field))
                    self.env.cr.execute(query, {'partner_ids': tuple(self.ids), 'n': n})
                    for partner in self:
                        self.env.cache.remove(partner, partner._fields[field])
            except DatabaseError as e:
                if e.pgcode == '55P03':
                    _logger.debug('Another transaction already locked partner rows. Cannot update partner ranks.')
                else:
                    raise e