diff --git a/ext/custom-addons/dp_custom/models/material_type.py b/ext/custom-addons/dp_custom/models/material_type.py index 6f95d4bd..7f1ae414 100644 --- a/ext/custom-addons/dp_custom/models/material_type.py +++ b/ext/custom-addons/dp_custom/models/material_type.py @@ -28,6 +28,8 @@ class MaterialType(models.Model): name = fields.Char(string='Bezeichnung', required=True) print_default_code = fields.Boolean(string='Drucke Artikelnummer', required=True, help='Definiert, ob die Artikelnummer gedruckt wird') + print_sales_pic = fields.Boolean(string='Drucke Artikelbild', default=True, required=False, help='Definiert, ob ein Artikelbild gedruckt wird (Angebot/Auftrag)') + print_production_pic = fields.Boolean(string='Drucke Produktionsbild', default=False, required=False, help='Definiert, ob ein Produktionsbild gedruckt wird (Produktionsauftrag)') _sql_constraints = [ ('name_uniq', 'unique(name)', 'Die Bezeichnung muss eindeutig sein') diff --git a/ext/custom-addons/dp_custom/models/res_partner.py b/ext/custom-addons/dp_custom/models/res_partner.py index e9a99530..119f6269 100644 --- a/ext/custom-addons/dp_custom/models/res_partner.py +++ b/ext/custom-addons/dp_custom/models/res_partner.py @@ -67,6 +67,7 @@ class Partner(models.Model): 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') + partner_flash = fields.Char() _sql_constraints = [ ('ref_uniq', 'unique(ref)', 'Die Interne Referenz muss eindeutig sein'), @@ -281,7 +282,7 @@ class Partner(models.Model): common_list.extend( ['name', 'ref', 'partner_sector_id', 'info_uid', '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']) + 'is_retailer', 'name2', 'carrier_id', 'collective_bill', 'fiscal_position', 'partner_flash']) return common_list elif self.env.context.get('sst_14', False): common_list = ['firstname', 'lastname', 'midname', 'email', 'company_odoo_id', 'portal_id', 'opt_out'] diff --git a/ext/custom-addons/dp_custom/models/sale.py b/ext/custom-addons/dp_custom/models/sale.py index d8932ca1..bbe0677f 100644 --- a/ext/custom-addons/dp_custom/models/sale.py +++ b/ext/custom-addons/dp_custom/models/sale.py @@ -65,6 +65,8 @@ class SaleOrder(models.Model): # pg9_call = fields.Char(string='PG9-Auftrag', compute='_pg9_call', store=False) pg9_call_D = fields.Char(string='PG9-Auftrag_D', compute='_pg9_call', store=False) pg9_call_T = fields.Char(string='PG9-Auftrag_T', compute='_pg9_call', store=False) + partner_flash = fields.Text(compute='_get_partner_flash', store=False) +# partner_flash = fields.Char(store=False) @api.multi def _reset_sequence(self): @@ -87,10 +89,16 @@ class SaleOrder(models.Model): # end def _pg9_call + @api.multi + def _get_partner_flash(self): + for record in self: + record.partner_flash = record.partner_id.partner_flash + @api.multi @api.onchange('partner_invoice_id') def _onchange_partner_invoice_id(self): for record in self: +# record.partner_flash = record.partner_id.partner_flash if record.partner_invoice_id.is_retailer: record.payment_term_id = record.partner_invoice_id.property_payment_term_id @@ -452,6 +460,9 @@ class SaleOrder(models.Model): @api.multi @api.onchange('partner_id') def onchange_partner_id(self): + # for record in self: + # record.partner_flash = record.partner_id.partner_flash + if not self.partner_id: self.update({ 'partner_invoice_id': False, @@ -472,6 +483,10 @@ class SaleOrder(models.Model): if self.partner_id.team_id: values['team_id'] = self.partner_id.team_id.id + + if self.partner_id: + values['partner_flash'] = self.partner_id.partner_flash + self.update(values) @api.multi @@ -504,6 +519,14 @@ class SaleOrderLine(models.Model): weight = fields.Float(string='Gewicht', compute='_compute_weight') intrastat_id = fields.Many2one(comodel_name='report.intrastat.code', string='Intrastat Code') sequence = fields.Integer(string='Sequence', default=9999) + item_notes = fields.Text(string='Notes', related='lot_id.notes', store=False) + item_warn = fields.Boolean(string='Notes!!!', compute='_compute_item_warn', store=False) + + @api.multi + def _compute_item_warn(self): + for record in self: + iNote = str(record.lot_id.notes) + record.item_warn = True if iNote.startswith('!') else False @api.multi @api.onchange('product_id') diff --git a/ext/custom-addons/dp_custom/models/stock.py b/ext/custom-addons/dp_custom/models/stock.py index 3ca1c36e..ceb356cd 100644 --- a/ext/custom-addons/dp_custom/models/stock.py +++ b/ext/custom-addons/dp_custom/models/stock.py @@ -19,7 +19,9 @@ # ############################################################################## -from odoo import fields, models, api, tools +from odoo import fields, models, api, tools, _ +from odoo.exceptions import ValidationError +from odoo.tools.float_utils import float_compare, float_is_zero class StockProductionLot(models.Model): @@ -60,3 +62,67 @@ class StockPicking(models.Model): 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) diff --git a/ext/custom-addons/dp_custom/views/material_type_views.xml b/ext/custom-addons/dp_custom/views/material_type_views.xml index adb1fc84..bf239aea 100644 --- a/ext/custom-addons/dp_custom/views/material_type_views.xml +++ b/ext/custom-addons/dp_custom/views/material_type_views.xml @@ -9,6 +9,8 @@ + + @@ -21,6 +23,8 @@ + + diff --git a/ext/custom-addons/dp_custom/views/res_partner_views.xml b/ext/custom-addons/dp_custom/views/res_partner_views.xml index 971457b9..19448302 100644 --- a/ext/custom-addons/dp_custom/views/res_partner_views.xml +++ b/ext/custom-addons/dp_custom/views/res_partner_views.xml @@ -31,6 +31,9 @@ + + +
diff --git a/ext/custom-addons/dp_custom/views/sale_views.xml b/ext/custom-addons/dp_custom/views/sale_views.xml index 006131c6..f1915e35 100644 --- a/ext/custom-addons/dp_custom/views/sale_views.xml +++ b/ext/custom-addons/dp_custom/views/sale_views.xml @@ -6,12 +6,20 @@ sale.order + + + item_warn +
+ + +
+ @@ -66,9 +74,29 @@ - + + + + +
@@ -41,6 +46,11 @@
+
+
+ Tel: + +
@@ -101,6 +111,7 @@ + + + + @@ -161,10 +176,14 @@ Product - + + Lot/Serial Number + Weight + + Ordered Quantity - - + + @@ -213,6 +229,16 @@ +
- - - - + - + + + + + + + + + + : + + + + + + + + + + diff --git a/ext/custom-addons/tz_reports_production/security/ir.model.access.csv b/ext/custom-addons/tz_reports_production/security/ir.model.access.csv new file mode 100644 index 00000000..0343f29f --- /dev/null +++ b/ext/custom-addons/tz_reports_production/security/ir.model.access.csv @@ -0,0 +1 @@ +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" diff --git a/ext/custom-addons/tz_reports_production/static/description/icon.png b/ext/custom-addons/tz_reports_production/static/description/icon.png new file mode 100644 index 00000000..32c1481d Binary files /dev/null and b/ext/custom-addons/tz_reports_production/static/description/icon.png differ diff --git a/ext/custom-addons/tz_reports_production/static/src/img/favicon.ico b/ext/custom-addons/tz_reports_production/static/src/img/favicon.ico new file mode 100644 index 00000000..90f1e91c Binary files /dev/null and b/ext/custom-addons/tz_reports_production/static/src/img/favicon.ico differ diff --git a/ext/custom-addons/web_tree_dynamic_colored_field/README.rst b/ext/custom-addons/web_tree_dynamic_colored_field/README.rst new file mode 100644 index 00000000..2b647f42 --- /dev/null +++ b/ext/custom-addons/web_tree_dynamic_colored_field/README.rst @@ -0,0 +1,108 @@ +.. image:: https://img.shields.io/badge/license-LGPL--3-blue.svg + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 + +============================ +Colorize field in tree views +============================ + +This module aims to add support for dynamically coloring fields in tree view +according to data in the record. + +It provides attributes on fields with the similar syntax as the ``colors`` attribute +in tree tags. + +Further, it provides a ``color_field`` attribute on tree tags's ``colors`` to use +a field's value as color. + +Features +======== + +* Add attribute ``bg_color`` on field's ``options`` to color background of a cell in tree view +* Add attribute ``fg_color`` on field's ``options`` to change text color of a cell in tree view +* Add attribute ``color_field`` on the tree element's ``colors`` to use as color + +Usage +===== + +* In the tree view declaration, put ``options='{"bg_color": "red: customer==True"}`` attribute in the ``field`` tag:: + + ... + + + ... + + ... + + + ... + + With this example, column which renders 'name' field will have its background colored in red. + +* In the tree view declaration, put ``options='{"fg_color": "white:customer == True"}'`` attribute in the ``field`` tag:: + + ... + + + ... + + ... + + + ... + + With this example, column which renders 'name' field will have its text colored in white on a customer records. + +* In the tree view declaration, use ``options='"color_field": "my_color"'`` attribute in the ``tree`` tag:: + + ... + + + ... + + ... + + + ... + + With this example, the content of the field named `my_color` will be used to + populate the `my_color` CSS value. Use a function field to return whichever + color you want depending on the other record values. Note that this + overrides the rest of `colors` attributes, and that you need the tree + to load your field in the first place by adding it as invisible field. + +**Note that you should always use single quotes for fields' ``options`` and wrap nested values in double quotes since ``options`` is a JSON object.** + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smash it by providing a detailed and welcomed feedback. + +Credits +======= + +Contributors +------------ + +* Damien Crier +* Holger Brunn +* Artem Kostyuk +* Guewen Baconnier + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit https://odoo-community.org. diff --git a/ext/custom-addons/web_tree_dynamic_colored_field/__init__.py b/ext/custom-addons/web_tree_dynamic_colored_field/__init__.py new file mode 100644 index 00000000..8945c43c --- /dev/null +++ b/ext/custom-addons/web_tree_dynamic_colored_field/__init__.py @@ -0,0 +1,2 @@ +# Copyright 2015-2018 Camptocamp SA, Damien Crier +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). diff --git a/ext/custom-addons/web_tree_dynamic_colored_field/__manifest__.py b/ext/custom-addons/web_tree_dynamic_colored_field/__manifest__.py new file mode 100644 index 00000000..146c30db --- /dev/null +++ b/ext/custom-addons/web_tree_dynamic_colored_field/__manifest__.py @@ -0,0 +1,19 @@ +# Copyright 2015-2018 Camptocamp SA, Damien Crier +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +{ + 'name': 'Colorize field in tree views', + 'summary': 'Allows you to dynamically color fields on tree views', + 'category': 'Hidden/Dependency', + 'version': '11.0.1.0.1', + 'depends': ['web'], + 'author': "Camptocamp, Therp BV, Odoo Community Association (OCA)", + 'license': 'AGPL-3', + 'website': 'https://github.com/OCA/web', + 'demo': [ + "demo/res_users.xml", + ], + 'data': [ + 'views/web_tree_dynamic_colored_field.xml', + ], + 'installable': True, +} diff --git a/ext/custom-addons/web_tree_dynamic_colored_field/static/description/icon.png b/ext/custom-addons/web_tree_dynamic_colored_field/static/description/icon.png new file mode 100644 index 00000000..3a0328b5 Binary files /dev/null and b/ext/custom-addons/web_tree_dynamic_colored_field/static/description/icon.png differ diff --git a/ext/custom-addons/web_tree_dynamic_colored_field/static/src/js/web_tree_dynamic_colored_field.js b/ext/custom-addons/web_tree_dynamic_colored_field/static/src/js/web_tree_dynamic_colored_field.js new file mode 100644 index 00000000..d9e14c11 --- /dev/null +++ b/ext/custom-addons/web_tree_dynamic_colored_field/static/src/js/web_tree_dynamic_colored_field.js @@ -0,0 +1,134 @@ +odoo.define('web_tree_dynamic_colored_field', function (require) { + 'use strict'; + + var ListRenderer = require('web.ListRenderer'); + var pyeval = require('web.pyeval'); + + ListRenderer.include({ + /** + * Look up for a `color_field` parameter in tree `colors` attribute + * + * @override + */ + _renderBody: function () { + if (this.arch.attrs.colors) { + var colorAttr = this.arch.attrs.colors.split(';') + .filter(color => color.trim().startsWith('color_field')); + if (colorAttr.length > 0) { + var colorField = colorAttr[0].split(':')[1].trim(); + // validate the presence of that field in tree view + var fieldNames = _(this.columns).map( + (value) => { return value.attrs.name; } + ); + if (fieldNames.indexOf(colorField) === -1) { + console.warn( + "No field named '" + colorField + "' present in view." + ); + } else { + this.colorField = colorField; + } + } + } + return this._super(); + }, + /** + * Colorize a cell during it's render + * + * @override + */ + _renderBodyCell: function (record, node, colIndex, options) { + var $td = this._super.apply(this, arguments); + var ctx = this.getEvalContext(record); + this.applyColorize($td, record, node, ctx); + return $td; + }, + + /** + * Colorize the current cell depending on expressions provided. + * + * @param {Query Node} $td a tag inside a table representing a list view + * @param {Object} node an XML node (must be a ) + */ + applyColorize: function ($td, record, node, ctx) { + // safely resolve value of `color_field` given in + var treeColor = record.data[this.colorField]; + if (treeColor) { + $td.css('color', treeColor); + } + // apply 's own `options` + if (!node.attrs.options) { return; } + if (node.tag !== 'field') { return; } + var nodeOptions = node.attrs.options; + if (!_.isObject(nodeOptions)) { + nodeOptions = pyeval.py_eval(nodeOptions); + } + this.applyColorizeHelper($td, nodeOptions, node, 'fg_color', 'color', ctx); + this.applyColorizeHelper($td, nodeOptions, node, 'bg_color', 'background-color', ctx); + }, + /** + * @param {Object} nodeOptions a mapping of nodeOptions parameters to the color itself + * @param {Object} node an XML node (must be a ) + * @param {string} nodeAttribute an attribute of a node to apply a style onto + * @param {string} cssAttribute a real CSS-compatible attribute + */ + applyColorizeHelper: function ($td, nodeOptions, node, nodeAttribute, cssAttribute, ctx) { + if (nodeOptions[nodeAttribute]) { + var colors = _(nodeOptions[nodeAttribute].split(';')) + .chain() + .map(this.pairColors) + .value() + .filter(function CheckUndefined(value, index, ar) { + return value !== undefined; + }); + for (var i=0, len=colors.length; i: ` forms to + * evaluatable expressions + * + * @param {string} pairColor `color: expression` pair + */ + pairColors: function (pairColor) { + if (pairColor !== "") { + var pairList = pairColor.split(':'), + color = pairList[0], + // if one passes a bare color instead of an expression, + // then we consider that color is to be shown in any case + expression = pairList[1]? pairList[1] : 'True'; + return [color, py.parse(py.tokenize(expression)), expression]; + } + return undefined; + }, + /** + * Construct domain evaluation context, mostly by passing + * record's fields's values to local scope. + * + * @param {Object} record a record to build a context from + */ + getEvalContext: function (record) { + var ctx = _.extend( + {}, + record.data, + pyeval.context() + ); + for (var key in ctx) { + var value = ctx[key]; + if (ctx[key] instanceof moment) { + // date/datetime fields are represented w/ Moment objects + // docs: https://momentjs.com/ + ctx[key] = value.format('YYYY-MM-DD hh:mm:ss'); + } + } + return ctx; + } + }); +}); diff --git a/ext/custom-addons/web_tree_dynamic_colored_field/views/web_tree_dynamic_colored_field.xml b/ext/custom-addons/web_tree_dynamic_colored_field/views/web_tree_dynamic_colored_field.xml new file mode 100644 index 00000000..ea8e1129 --- /dev/null +++ b/ext/custom-addons/web_tree_dynamic_colored_field/views/web_tree_dynamic_colored_field.xml @@ -0,0 +1,8 @@ + + + +