# -*- coding: utf-8 -*- ############################################################################## # # datenpol gmbh # Copyright (C) 2013-TODAY datenpol gmbh () # # 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 . # ############################################################################## 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', '
') 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') ]