384 lines
17 KiB
Python
384 lines
17 KiB
Python
# -*- coding: utf-8 -*-
|
|
##############################################################################
|
|
#
|
|
# datenpol gmbh
|
|
# Copyright (C) 2013-TODAY datenpol gmbh (<http://www.datenpol.at/>)
|
|
#
|
|
# 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/>.
|
|
#
|
|
##############################################################################
|
|
import json
|
|
|
|
import requests
|
|
from odoo.addons.component.core import Component
|
|
from odoo.addons.queue_job.job import job
|
|
|
|
from odoo import tools, api, fields, models, _
|
|
from odoo.exceptions import ValidationError
|
|
|
|
|
|
class PartnerEventListener(Component):
|
|
_name = 'res.partner.listener'
|
|
_inherit = 'base.event.listener'
|
|
_apply_on = ['res.partner']
|
|
|
|
def on_record_write(self, record, fields=None):
|
|
if record.active and record.portal_id:
|
|
if 'company_type' in fields:
|
|
if record.company_type == 'company' and record.type != 'delivery':
|
|
self.env['res.partner'].with_delay().job_export_portal_price(record)
|
|
if 'property_product_pricelist' in fields:
|
|
for contact in record.child_ids:
|
|
if contact.type != 'delivery':
|
|
self.env['res.partner'].with_delay().job_export_portal_price(contact)
|
|
if 'parent_id' in fields:
|
|
if record.type != 'delivery':
|
|
self.env['res.partner'].with_delay().job_export_portal_price(record)
|
|
|
|
|
|
class Partner(models.Model):
|
|
_name = 'res.partner'
|
|
_inherit = ['res.partner', 'dp_custom.helper']
|
|
|
|
@api.model
|
|
def _default_country_id(self):
|
|
return self.env.ref('base.at')
|
|
|
|
name2 = fields.Char('Unternehmensname 2')
|
|
info_kundennr = fields.Char(string='Info-Kundennr.')
|
|
info_uid = fields.Char(string='Info-UID')
|
|
endkunde = fields.Boolean(string='Endkunde', help='Beschreibt, ob es ein Endkunde ist')
|
|
portal_pending = fields.Boolean('Erwarte Zuordnung', help='Wird vom Portal bei neuen Unternehmen gesetzt. '
|
|
'Sobald das Unternehmen manuell zugewiesen wurde, '
|
|
'wird das Flag wieder entfernt')
|
|
line_ids = fields.Many2many(comodel_name='res.line', string='Produktionslinien')
|
|
portal_id = fields.Char(string='Portal-ID')
|
|
partner_sector_id = fields.Many2one(comodel_name='res.partner.sector', string='Branche')
|
|
active = fields.Boolean(track_visibility='onchange')
|
|
portal_export_pending = fields.Boolean(string='Portal Export ausständig')
|
|
date_vat_check = fields.Date(string='Datum der letzten UID-Prüfung')
|
|
collective_bill = fields.Boolean(string='Sammelrechnung', default=True)
|
|
country_id = fields.Many2one('res.country', string='Country', ondelete='restrict', default=_default_country_id)
|
|
commission_account_ids = fields.Many2many(comodel_name='commission.account', string='Provisionsempfänger')
|
|
|
|
_sql_constraints = [
|
|
('ref_uniq', 'unique(ref)', 'Die Interne Referenz muss eindeutig sein'),
|
|
('portal_id_uniq', 'unique(portal_id)', 'Die Portal-ID muss eindeutig sein')
|
|
]
|
|
|
|
@api.multi
|
|
@api.constrains('is_company', 'vat')
|
|
def _check_unique_vat(self):
|
|
for record in self:
|
|
if not record.vat or (not record.is_company and record.parent_id):
|
|
continue
|
|
partners = self.search([('is_company', '=', True),
|
|
('vat', '=', self.vat),
|
|
('id', '!=', self.id)])
|
|
if partners:
|
|
raise ValidationError(_("UID-Exists: Es sind bereits folgende Unternehmen mit der selben USt. ID "
|
|
"vorhanden: %s") % [p.name for p in partners])
|
|
|
|
@api.model
|
|
def portal_create_company(self, vals):
|
|
"""
|
|
SST-01
|
|
:param vals:
|
|
:return:
|
|
"""
|
|
vals = self.with_context(sst_1=True).remove_not_specified_fields(vals)
|
|
vals = self.correct_values(vals)
|
|
if not vals.get('active', False):
|
|
vals['active'] = False
|
|
vals['is_company'] = True
|
|
vals['portal_pending'] = True
|
|
self.create(vals)
|
|
return True
|
|
|
|
@api.model
|
|
def portal_create_contact(self, vals):
|
|
"""
|
|
SST-14
|
|
:param vals:
|
|
:return:
|
|
"""
|
|
vals = self.with_context(sst_14=True).remove_not_specified_fields(vals)
|
|
vals = self.correct_values(vals)
|
|
return self.create(vals).id
|
|
|
|
@api.model
|
|
def pg_create_company(self, vals):
|
|
"""
|
|
SST-11
|
|
:param vals:
|
|
:return:
|
|
"""
|
|
vals = self.with_context(sst_11=True).remove_not_specified_fields(vals)
|
|
vals = self.correct_values(vals)
|
|
partner = self.with_context(active_test=False).search([('ref', '=', vals['ref'])])
|
|
if partner:
|
|
if not partner.is_company:
|
|
raise ValidationError(
|
|
_("Der Partner mit der Internen Referenz '%s' ist kein Unternehmen") % vals['ref'])
|
|
partner.write(vals)
|
|
else:
|
|
if not vals.get('is_company', False):
|
|
vals['is_company'] = True
|
|
partner = self.create(vals)
|
|
partner.property_account_fiscal_position = self.env['account.fiscal.position'].get_fiscal_position(
|
|
partner.id)
|
|
return True
|
|
|
|
@api.model
|
|
def correct_values(self, vals):
|
|
if vals.get('country_id', False):
|
|
country = self.env['res.country'].search([('code', '=', vals['country_id'])])
|
|
if country:
|
|
vals['country_id'] = country.id
|
|
else:
|
|
raise ValidationError(
|
|
_("Das Land mit dem ISO-Code \'%s\' kann nicht zugeordnet werden") % vals['country_id'])
|
|
|
|
if vals.get('line_ids', False):
|
|
line_ids = self.env['res.line'].search([('name', 'in', vals['line_ids'])])
|
|
if line_ids:
|
|
vals['line_ids'] = [(6, 0, line_ids.ids)]
|
|
else:
|
|
raise ValidationError(
|
|
_("Die Produktionslinie mit dem Code \'%s\' kann nicht zugeordnet werden") % vals['line_ids'])
|
|
|
|
if vals.get('lang', False):
|
|
temp = vals['lang']
|
|
vals['lang'] = False
|
|
for selection in self.fields_get('lang')['lang']['selection']:
|
|
if selection[0].startswith(temp):
|
|
vals['lang'] = selection[0]
|
|
break
|
|
if not vals['lang']:
|
|
raise ValidationError(_("Die Sprache mit dem Code \'%s\' kann nicht zugeordnet werden") % temp)
|
|
|
|
if vals.get('partner_sector_id', False):
|
|
branche = self.env['res.partner.sector'].search(
|
|
[('name', '=', vals['partner_sector_id'])])
|
|
if branche:
|
|
vals['partner_sector_id'] = branche.id
|
|
else:
|
|
raise ValidationError(_("Die Branche \'%s\' kann nicht zugeordnet werden") % vals['partner_sector_id'])
|
|
|
|
if vals.get('property_payment_term_id', False):
|
|
payment_term = self.env['account.payment.term'].search(
|
|
[('code', '=', vals['property_payment_term_id'])])
|
|
if payment_term:
|
|
vals['property_payment_term_id'] = payment_term.id
|
|
else:
|
|
raise ValidationError(
|
|
_("Die Zahlungsbedingung mit dem Code \'%s\' kann nicht zugeordnet werden") % vals[
|
|
'property_payment_term_id'])
|
|
|
|
if vals.get('property_product_pricelist', False):
|
|
product_pricelist = self.env['product.pricelist'].search(
|
|
[('currency_id.name', '=', vals['property_product_pricelist'])])
|
|
if product_pricelist:
|
|
vals['property_product_pricelist'] = product_pricelist[0].id
|
|
else:
|
|
raise ValidationError(_("Die Preisliste mit der Währung \'%s\' kann nicht zugeordnet werden") % vals[
|
|
'property_product_pricelist'])
|
|
|
|
if vals.get('retail_partner_id', False):
|
|
retail_partner = self.env['res.partner'].search(
|
|
[('ref', '=', vals['retail_partner_id'])])
|
|
if retail_partner:
|
|
vals['retail_partner_id'] = retail_partner.id
|
|
else:
|
|
raise ValidationError(
|
|
_("Der Händler mit der Internen Referenz \'%s\' kann nicht zugeordnet werden") % vals[
|
|
'retail_partner_id'])
|
|
|
|
if vals.get('incoterm', False):
|
|
incoterm = self.env['stock.incoterms'].search(
|
|
[('code', '=', vals['incoterm'])])
|
|
if incoterm:
|
|
vals['sale_incoterm_id'] = incoterm.id
|
|
del vals['incoterm']
|
|
else:
|
|
raise ValidationError(
|
|
_("Die Lieferbedingung mit dem Code \'%s\' kann nicht zugeordnet werden") % vals['incoterm'])
|
|
|
|
if vals.get('company_odoo_id', False):
|
|
parent_id = self.env['res.partner'].with_context(active_test=False).search(
|
|
[('id', '=', vals['company_odoo_id'])])
|
|
if parent_id:
|
|
vals['parent_id'] = parent_id.id
|
|
vals['street'] = parent_id.street
|
|
vals['street2'] = parent_id.street2
|
|
vals['city'] = parent_id.city
|
|
vals['zip'] = parent_id.zip
|
|
vals['country_id'] = parent_id.country_id.id
|
|
vals['supplier'] = parent_id.supplier
|
|
vals['customer'] = parent_id.customer
|
|
vals['lang'] = parent_id.lang
|
|
del vals['company_odoo_id']
|
|
else:
|
|
raise ValidationError(_("Unternehmen mit Odoo-ID \'%s\' existiert nicht") % vals['company_odoo_id'])
|
|
|
|
if vals.get('carrier_id', False):
|
|
carrier_id = self.env['delivery.carrier'].search([('name', '=', vals['carrier_id'])])
|
|
if carrier_id:
|
|
vals['property_delivery_carrier_id'] = carrier_id.id
|
|
del vals['carrier_id']
|
|
else:
|
|
raise ValidationError(
|
|
_("Die Auslieferungsmethode mit dem Namen \'%s\' existiert nicht") % vals['carrier_id'])
|
|
|
|
if 'fiscal_position' in vals:
|
|
if not vals.get('fiscal_position', False):
|
|
vals['property_account_position_id'] = False
|
|
del vals['fiscal_position']
|
|
else:
|
|
property_account_position_id = self.env['account.fiscal.position'].search(
|
|
[('name', '=', vals['fiscal_position'])])
|
|
if property_account_position_id:
|
|
vals['property_account_position_id'] = property_account_position_id.id
|
|
del vals['fiscal_position']
|
|
else:
|
|
raise ValidationError(
|
|
_("Steuerzuorndung \'%s\' kann nicht zugeordnet werden") % vals['fiscal_position'])
|
|
|
|
return vals
|
|
|
|
@api.model
|
|
def _get_specified_fields(self):
|
|
common_list = ['street', 'street2', 'zip', 'city', 'country_id', 'fax', 'phone', 'mobile',
|
|
'endkunde', 'line_ids', 'lang', 'portal_id', 'email', 'opt_out']
|
|
if self.env.context.get('sst_1', False):
|
|
common_list.extend(['name', 'name2', 'info_kundennr', 'info_uid', 'comment', 'retail_partner_id'])
|
|
return common_list
|
|
elif self.env.context.get('sst_11', False):
|
|
common_list.extend(['name', 'ref', 'partner_sector_id', 'comment', 'vat', 'property_payment_term_id',
|
|
'date_vat_check', 'active', 'property_product_pricelist', 'retail_partner_id',
|
|
'is_retailer', 'name2', 'carrier_id', 'collective_bill', 'fiscal_position'])
|
|
return common_list
|
|
elif self.env.context.get('sst_14', False):
|
|
common_list = ['firstname', 'lastname', 'midname', 'email', 'company_odoo_id', 'portal_id', 'opt_out']
|
|
return common_list
|
|
elif self.env.context.get('delivery_partner', False):
|
|
common_list = ['firstname', 'lastname', 'midname', 'street', 'street2', 'zip', 'city', 'country_id', 'fax',
|
|
'phone', 'mobile', 'email', 'portal_id']
|
|
return common_list
|
|
else:
|
|
return super(Partner, self)._get_specified_fields()
|
|
|
|
@api.model
|
|
def cron_export_portal_prices(self):
|
|
partners = self.search([('portal_export_pending', '=', True), ('company_id', '=', self.env.user.company_id.id)])
|
|
for partner in partners:
|
|
if partner.type != 'delivery':
|
|
self.with_delay().job_export_portal_price(partner)
|
|
partner.portal_export_pending = False
|
|
|
|
@api.multi
|
|
@job
|
|
def job_export_portal_price(self, partner_id):
|
|
if not partner_id.portal_id:
|
|
raise ValidationError(_("Der Partner mit der ID %s hat keine Portal-ID") % partner_id.id)
|
|
pricelist = partner_id.property_product_pricelist
|
|
data = []
|
|
for item in pricelist.item_ids:
|
|
if item.compute_price == 'percentage' and item.applied_on in ['3_global', '2_product_category',
|
|
'1_product']:
|
|
code = False
|
|
if item.applied_on == '2_product_category':
|
|
code = item.categ_id.code
|
|
if item.applied_on == '1_product':
|
|
code = item.product_tmpl_id.default_code
|
|
data.append({
|
|
'customer_id': partner_id.portal_id,
|
|
'code': code,
|
|
'discount': 1 - (item.percent_price / 100)
|
|
})
|
|
portal_url = tools.config.get('portal_url')
|
|
application_id = tools.config.get('portal_secret')
|
|
response = requests.post(portal_url + '/api/v1/set-discounts/?secret=' + application_id,
|
|
data=json.dumps(data))
|
|
if response.status_code != 200:
|
|
raise ValidationError(_('Rabatt konnte nicht gesetzt werden. '
|
|
'Status Code: %s, Reason: %s') % (response.status_code, response.reason))
|
|
|
|
@api.multi
|
|
def write(self, vals):
|
|
fields_to_check = ['ref', 'portal_id']
|
|
for field in fields_to_check:
|
|
if field in vals and vals[field] == '':
|
|
vals[field] = False
|
|
return super(Partner, self).write(vals)
|
|
|
|
@api.multi
|
|
def name_get(self):
|
|
res = []
|
|
for partner in self:
|
|
name = partner.name or ''
|
|
if partner.name2:
|
|
name += " " + partner.name2
|
|
|
|
if partner.company_name or partner.parent_id:
|
|
if not name and partner.type in ['invoice', 'delivery', 'other']:
|
|
name = dict(self.fields_get(['type'])['type']['selection'])[partner.type]
|
|
if not partner.is_company:
|
|
name = "%s, %s" % (partner.commercial_company_name or partner.parent_id.name, name)
|
|
if self._context.get('show_address_only'):
|
|
name = partner._display_address(without_company=True)
|
|
if self._context.get('show_address'):
|
|
name = name + "\n" + partner._display_address(without_company=True)
|
|
name = name.replace('\n\n', '\n')
|
|
name = name.replace('\n\n', '\n')
|
|
if self._context.get('show_email') and partner.email:
|
|
name = "%s <%s>" % (name, partner.email)
|
|
if self._context.get('html_format'):
|
|
name = name.replace('\n', '<br/>')
|
|
res.append((partner.id, name))
|
|
return res
|
|
|
|
@api.depends('company_name', 'parent_id.is_company', 'commercial_partner_id.name')
|
|
def _compute_commercial_company_name(self):
|
|
res = super(Partner, self)._compute_commercial_company_name()
|
|
for partner in self:
|
|
p = partner.commercial_partner_id
|
|
if p.is_company and p.name2:
|
|
partner.commercial_company_name += " " + p.name2
|
|
return res
|
|
|
|
@api.multi
|
|
def _needsRef(self, vals=None):
|
|
return True
|
|
|
|
@api.model
|
|
def _commercial_fields(self):
|
|
res = super(Partner, self)._commercial_fields()
|
|
if 'ref' in res:
|
|
del res[res.index('ref')]
|
|
return res
|
|
|
|
|
|
class PartnerSector(models.Model):
|
|
_name = 'res.partner.sector'
|
|
_description = 'Branche'
|
|
_order = 'id,name'
|
|
|
|
name = fields.Char(string='Bezeichnung', required=True)
|
|
sequence = fields.Integer(string='Sequenz')
|
|
|
|
_sql_constraints = [
|
|
('name_uniq', 'unique(name)', 'Die Bezeichnung muss eindeutig sein')
|
|
]
|