# -*- 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 . # ############################################################################## from odoo import fields, models, api, tools, _ from odoo.exceptions import ValidationError from odoo.tools.float_utils import float_compare, float_is_zero import base64 class StockProductionLot(models.Model): _inherit = 'stock.production.lot' assembled = fields.Boolean(string='Zusammengebaut') notes = fields.Text() weight = fields.Float(string='Gewicht') intrastat_id = fields.Many2one(comodel_name='report.intrastat.code', string='Intrastat Nummer (Code)') image = fields.Binary("Produktbild", attachment=True, help="Wenn vorhanden, wird dieses Bild in den Angeboten/Aufträgen angedruckt") image_medium = fields.Binary("Produktbild (resized)", attachment=True, help="Produktbild 'resized' auf 128x128") short_text = fields.Text() @api.model def create(self, vals): if vals.get('image'): vals.update(tools.image_get_resized_images(vals['image'], return_big=True, return_medium=True, return_small=False)) return super(StockProductionLot, self).create(vals) @api.multi def write(self, vals): if vals.get('image'): vals.update(tools.image_get_resized_images(vals['image'], return_big=True, return_medium=True, return_small=False)) return super(StockProductionLot, self).write(vals) class StockPicking(models.Model): _inherit = 'stock.picking' dlv_partner_ref = fields.Text(compute='_get_partner_ref', store=False, string='Interne Referenz') picking_signature = fields.Binary(string='Customer Signature', default=None) shopping_cart_ref = fields.Text(compute='_get_shopping_cart_ref', store=True, string='Warenkorb') free_over = fields.Boolean(help="If the order total amount (shipping excluded) is above or equal to this value, the customer benefits from a free shipping \nIf this value = 0, no freight item is added to the order") show_to_sign = fields.Text( compute='_compute_show_to_sign', help='Technical field used to compute whether the to_sign should be shown.') @api.multi @api.depends('state', 'picking_signature') def _compute_show_to_sign(self): for picking in self: picking.show_to_sign = '' if picking.picking_signature == '' or picking.picking_signature == None or len(self['picking_signature']) == 3012: picking.show_to_sign = 'btn-primary' @api.multi def _add_delivery_cost_to_so(self): self.ensure_one() sale_order = self.sale_id if sale_order.invoice_shipping_on_delivery and not (self.carrier_id.free_over and self.carrier_id.amount < 0.001): sale_order._create_delivery_line(self.carrier_id, self.carrier_price) @api.multi def write(self, vals): if 'picking_signature' in vals: msg = '' prime_signature = "" if not vals['picking_signature'] or len(vals['picking_signature']) == 3012: if self['picking_signature'] or len(self['picking_signature']) == 3012: prime_signature = self['picking_signature'] msg='Unterschrift wurde entfernt' else: if not self['picking_signature'] or len(self['picking_signature']) == 3012: prime_signature = vals['picking_signature'] msg='Lieferschein wurde unterschrieben' elif vals['picking_signature'] != self['picking_signature'].decode(): prime_signature = vals['picking_signature'] msg='Unterschrift wurde geändert' if msg != '': # signature2attach = [] if isinstance(prime_signature,bytes): ps = prime_signature else: ps = prime_signature.encode('ascii') signature2attach = { "filename": r'Signature.jpg', "binary" : ps } self.create_attachment(signature2attach) self.message_post(body=msg) return super(StockPicking, self).write(vals) @api.model def create_attachment(self, vals): attachment_vals = { 'name': vals['filename'], 'datas': vals['binary'], 'datas_fname': vals['filename'], 'res_model': self._name, 'res_id': self.id, 'customer_signed' : True, } self.env['ir.attachment'].create(attachment_vals) @api.multi def _get_partner_ref(self): for record in self: record.dlv_partner_ref = record.partner_id.ref @api.multi def _get_shopping_cart_ref(self): for record in self: record.shopping_cart_ref = record.sale_id.origin @api.model def _formatLang(self, value): lang = self.partner_id.lang lang_objs = self.env['res.lang'].search([('code', '=', lang)]) if not lang_objs: lang_objs = self.env['res.lang'].search([], limit=1) lang_obj = lang_objs[0] res = lang_obj.format('%.' + str(2) + 'f', value, grouping=True, monetary=True) return res class StockMove(models.Model): _inherit = "stock.move" manu_lots_visible = fields.Boolean(compute='_compute_manu_lots_visible') @api.model def create(self, vals): res = super(StockMove, self).create(vals) for move in res: move.update({'sequence': move.sale_line_id.sequence,}) return res @api.multi def _prepare_move_line_vals(self, quantity=None, reserved_quant=None): self.ensure_one() vals = super(StockMove, self)._prepare_move_line_vals(quantity=quantity, reserved_quant=reserved_quant) if self.sale_line_id.lot_id and not self.sale_line_id.product_id.can_be_sold_unconfigured: move_lot = self.sale_line_id.lot_id.id vals.update({'lot_id': move_lot,}) return vals def _compute_manu_lots_visible(self): for move_line in self: if not move_line.product_id.can_be_sold_unconfigured: move_line.manu_lots_visible = True @api.multi def action_show_lot(self): self.ensure_one() action = self.env.ref('stock.action_production_lot_form').read()[0] action['res_id'] = self.move_line_ids.lot_id.id action['view_mode'] = 'form' action['views'] = [(False, 'form')] return action @api.depends('product_id', 'product_uom_qty', 'product_uom') def _cal_move_weight(self): for move in self: if move.sale_line_id.lot_id and not move.product_id.can_be_sold_unconfigured: move.weight += (move.product_qty * move.sale_line_id.lot_id.weight) else: move.weight += (move.product_qty * move.product_id.weight) # print(move.weight) class StockQuant(models.Model): _inherit = "stock.quant" @api.constrains('quantity') def check_quantity(self): info = '' for quant in self: if float_compare(quant.quantity, 1, precision_rounding=quant.product_uom_id.rounding) > 0 and quant.lot_id and quant.product_id.tracking == 'serial': smls = self.env['stock.move.line'].search([('lot_id', '=', quant.lot_id.id)]) for sml in smls: sm = self.env['stock.move'].search([('id', '=', sml.move_id.id)]) info += '\n %s; %s; %s: %s' % (sm.origin,sm.reference,sm.sequence,quant.lot_id.name) if info: raise ValidationError(_('A serial number should only be linked to a single product.') + info)