diff --git a/account_invoice_label_certisys/__init__.py b/account_invoice_label_certisys/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/account_invoice_label_certisys/__openerp__.py b/account_invoice_label_certisys/__openerp__.py new file mode 100644 index 0000000..8fa9f38 --- /dev/null +++ b/account_invoice_label_certisys/__openerp__.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (C) 2013-2016 Open Architects Consulting SPRL. +# +# 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 . +# +############################################################################## +{ + 'name': 'Account Invoice label certisys', + 'description': 'Add certisys label on invoices', + 'category': 'Invoice', + 'version': '9.0.1.0', + 'author': 'Coop IT Easy SCRLfs', + 'depends': [ + 'account', + ], + 'data': [ + 'reports/invoice_template.xml' + ], + 'installable': True, +} diff --git a/account_invoice_label_certisys/reports/invoice_template.xml b/account_invoice_label_certisys/reports/invoice_template.xml new file mode 100644 index 0000000..bc1a369 --- /dev/null +++ b/account_invoice_label_certisys/reports/invoice_template.xml @@ -0,0 +1,16 @@ + + + + + + + + \ No newline at end of file diff --git a/mrp_brewing/static/img/EU_Organic_Logo.jpg b/account_invoice_label_certisys/static/img/EU_Organic_Logo.jpg similarity index 100% rename from mrp_brewing/static/img/EU_Organic_Logo.jpg rename to account_invoice_label_certisys/static/img/EU_Organic_Logo.jpg diff --git a/account_journal_items_default_number_lines/__init__.py b/account_journal_items_default_number_lines/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/account_journal_items_default_number_lines/__openerp__.py b/account_journal_items_default_number_lines/__openerp__.py new file mode 100644 index 0000000..da9766f --- /dev/null +++ b/account_journal_items_default_number_lines/__openerp__.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Copyright 2019 Coop IT Easy SCRLfs +# Nicolas Jamoulle, +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +{ + "name": "Default number of lines in journal items", + "version": "9.0.1.0", + "depends": [ + 'account', + ], + "author": "Coop IT Easy SCRLfs", + "license": "AGPL-3", + "website": "www.coopiteasy.be", + "description": """ + Allow to change d efault number of lines in journal items + """, + "data": [ + 'views/account_journal_view.xml', + ], + 'installable': True, +} diff --git a/account_journal_items_default_number_lines/views/account_journal_view.xml b/account_journal_items_default_number_lines/views/account_journal_view.xml new file mode 100644 index 0000000..fe42970 --- /dev/null +++ b/account_journal_items_default_number_lines/views/account_journal_view.xml @@ -0,0 +1,7 @@ + + + + 200 + + + diff --git a/foodhub_custom/__init__.py b/foodhub_custom/__init__.py new file mode 100644 index 0000000..cde864b --- /dev/null +++ b/foodhub_custom/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import models diff --git a/foodhub_custom/__openerp__.py b/foodhub_custom/__openerp__.py new file mode 100644 index 0000000..82302a2 --- /dev/null +++ b/foodhub_custom/__openerp__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2019 Coop IT Easy SCRLfs +# Robin Keunen +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +{ + 'name': "Foodhub Custom", + 'version': '9.0.1.0.0', + 'description': """ + Foodhub customizations""", + + 'author': "Coop IT Easy SCRL fs", + 'website': "http://www.coopiteasy.be", + 'license': 'AGPL-3', + 'category': 'Account', + 'depends': [ + 'sale_stock', + ], + + 'data': [ + 'reports/report_deliveryslip.xml', + ], +} diff --git a/foodhub_custom/models/__init__.py b/foodhub_custom/models/__init__.py new file mode 100644 index 0000000..b857415 --- /dev/null +++ b/foodhub_custom/models/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import stock diff --git a/foodhub_custom/models/stock.py b/foodhub_custom/models/stock.py new file mode 100644 index 0000000..1dfc118 --- /dev/null +++ b/foodhub_custom/models/stock.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- + +from openerp import models, fields, api + + +class StockMove(models.Model): + _inherit = 'stock.move' + + order_line_id = fields.Many2one( + comodel_name='sale.order.line', + string='Related Sale Line', + compute='_compute_related_order_line', + ) + + currency_id = fields.Many2one( + related='order_line_id.currency_id') + price_subtotal = fields.Monetary( + string='Subtotal', + related='order_line_id.price_subtotal') + price_taxes = fields.Monetary( + string='Taxes', + related='order_line_id.price_tax') + price_total = fields.Monetary( + string='Total', + related='order_line_id.price_total') + + @api.multi + @api.depends('picking_id.origin') + def _compute_related_order_line(self): + for move in self: + origin = move.picking_id.origin + sale_order = ( + self.env['sale.order'] + .search([('name', '=', origin)]) + ) + order_line = ( + sale_order.order_line + .filtered( + lambda line: line.product_id == move.product_id) + ) + move.order_line_id = order_line + + +class StockPackOperation(models.Model): + _inherit = 'stock.pack.operation' + + order_line_id = fields.Many2one( + comodel_name='sale.order.line', + string='Related Move Line', + compute='_compute_related_order_line', + ) + + currency_id = fields.Many2one( + related='order_line_id.currency_id') + price_subtotal = fields.Monetary( + string='Subtotal', + related='order_line_id.price_subtotal') + price_taxes = fields.Monetary( + string='Taxes', + related='order_line_id.price_tax') + price_total = fields.Monetary( + string='Total', + related='order_line_id.price_total') + + @api.multi + @api.depends('picking_id.origin') + def _compute_related_order_line(self): + for operation in self: + origin = operation.picking_id.origin + sale_order = ( + self.env['sale.order'] + .search([('name', '=', origin)]) + ) + order_line = ( + sale_order.order_line + .filtered( + lambda line: line.product_id == operation.product_id) + ) + operation.order_line_id = order_line diff --git a/foodhub_custom/reports/report_deliveryslip.xml b/foodhub_custom/reports/report_deliveryslip.xml new file mode 100644 index 0000000..36f9521 --- /dev/null +++ b/foodhub_custom/reports/report_deliveryslip.xml @@ -0,0 +1,34 @@ + + + + + + diff --git a/hw_printer_network/README.rst b/hw_printer_network/README.rst new file mode 100644 index 0000000..6946cc1 --- /dev/null +++ b/hw_printer_network/README.rst @@ -0,0 +1,30 @@ +.. image:: https://img.shields.io/badge/license-LGPL--3-blue.png + :target: https://www.gnu.org/licenses/lgpl + :alt: License: LGPL-3 + +========================== + Hardware Network Printer +========================== + +Hardware Driver for Network pinters. + +When print an order, the PosBox receives the network printer IP address and the receipt from client's POS. +If the IP address is not empty, it will be connected to the network printer by using this address, which in turn prints the receipt. + +Credits +======= + +Contributors +------------ +* Dinar Gabbasov +* Tom Blauwendraat + +Sponsors +-------- +* `IT-Projects LLC `__ + +Maintainers +----------- +* `IT-Projects LLC `__ + + diff --git a/hw_printer_network/__init__.py b/hw_printer_network/__init__.py new file mode 100644 index 0000000..e8cd64c --- /dev/null +++ b/hw_printer_network/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +def post_load(): + from . import controllers diff --git a/hw_printer_network/__openerp__.py b/hw_printer_network/__openerp__.py new file mode 100644 index 0000000..108b0f3 --- /dev/null +++ b/hw_printer_network/__openerp__.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +# Copyright 2017-2018 Dinar Gabbasov +# Copyright 2018 Ivan Yelizariev +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +{ + "name": """Hardware Network Printer""", + "summary": """Hardware Driver for Network Printers""", + "category": "Point of Sale", + "images": [], + "version": "10.0.2.0.1", + "application": False, + + "author": "IT-Projects LLC, Dinar Gabbasov", + "support": "apps@it-projects.info", + "website": "https://twitter.com/gabbasov_dinar", + "license": "LGPL-3", + "price": 59.00, + "currency": "EUR", + + "depends": [ + "hw_escpos", + ], + "external_dependencies": {"python": [], "bin": []}, + "data": [ + ], + "qweb": [ + ], + "demo": [], + + "post_load": "post_load", + "pre_init_hook": None, + "post_init_hook": None, + + "auto_install": False, + "installable": True, +} diff --git a/hw_printer_network/controllers/__init__.py b/hw_printer_network/controllers/__init__.py new file mode 100644 index 0000000..483a879 --- /dev/null +++ b/hw_printer_network/controllers/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +from . import hw_printer_network_controller diff --git a/hw_printer_network/controllers/hw_printer_network_controller.py b/hw_printer_network/controllers/hw_printer_network_controller.py new file mode 100644 index 0000000..10e8566 --- /dev/null +++ b/hw_printer_network/controllers/hw_printer_network_controller.py @@ -0,0 +1,188 @@ +# -*- coding: utf-8 -*- +# Copyright 2017-2018 Dinar Gabbasov +# Copyright 2018 Tom Blauwendraat +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +from openerp import http +import logging +import time +import socket +import subprocess +import threading +import traceback + + +_logger = logging.getLogger(__name__) + + +try: + from openerp.addons.hw_escpos.escpos import escpos + from openerp.addons.hw_escpos.controllers.main import EscposProxy + from openerp.addons.hw_escpos.controllers.main import EscposDriver + from openerp.addons.hw_escpos.escpos.printer import Network + import openerp.addons.hw_proxy.controllers.main as hw_proxy +except ImportError: + EscposProxy = object + EscposDriver = object + + +class PingProcess(threading.Thread): + def __init__(self, ip): + self.stdout = None + self.stderr = None + threading.Thread.__init__(self) + self.status = 'offline' + self.ip = ip + self.stop = False + + def run(self): + while not self.stop: + child = subprocess.Popen( + ["ping", "-c1", "-w5", self.ip], + shell=False, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE + ) + child.communicate() + self.status = 'offline' if child.returncode else 'online' + time.sleep(1) + + def get_status(self): + return self.status + + def __del__(self): + self.stop = True + + +class EscposNetworkDriver(EscposDriver): + + def __init__(self): + self.network_printers = [] + self.ping_processes = {} + self.printer_objects = {} + super(EscposNetworkDriver, self).__init__() + + def get_network_printer(self, ip, name=None): + found_printer = False + for printer in self.network_printers: + if printer['ip'] == ip: + found_printer = True + if name: + printer['name'] = name + if printer['status'] == 'online': + printer_object = self.printer_objects.get(ip, None) + if not printer_object: + try: + printer_object = Network(ip) + self.printer_objects[ip] = printer_object + except socket.error: + pass + return printer + if not found_printer: + self.add_network_printer(ip, name) + return None + + def add_network_printer(self, ip, name=None): + printer = dict( + ip=ip, + status='offline', + name=name or 'Unnamed printer' + ) + self.network_printers.append(printer) # dont return because offline + self.start_pinging(ip) + + def start_pinging(self, ip): + pinger = PingProcess(ip) + self.ping_processes[ip] = pinger + pinger.start() + + def update_driver_status(self): + count = len([p for p in self.network_printers if p.get('status', None) == 'online']) + if count: + self.set_status('connected', '{} printer(s) Connected'.format(count)) + else: + self.set_status('disconnected', 'Disconnected') + + def run(self): + if not escpos: + _logger.error('ESC/POS cannot initialize, please verify system dependencies.') + return + while True: + try: + error = True + timestamp, task, data = self.queue.get(True) + if task == 'xml_receipt': + error = False + if timestamp >= (time.time() - 1 * 60 * 60): + receipt, network_printer_ip = data + printer_info = self.get_network_printer(network_printer_ip) + printer = self.printer_objects.get(network_printer_ip, None) + if printer_info and printer_info['status'] == 'online' and printer: + _logger.info('Printing XML receipt on printer %s...', network_printer_ip) + try: + printer.receipt(receipt) + except socket.error: + printer.open() + printer.receipt(receipt) + _logger.info('Done printing XML receipt on printer %s', network_printer_ip) + else: + _logger.error('xml_receipt: printer offline!') + # add a missed order to queue + time.sleep(3) + self.queue.put((timestamp, task, data)) + elif task == 'printstatus': + pass + elif task == 'status': + error = False + for printer in self.network_printers: + ip = printer['ip'] + pinger = self.ping_processes.get(ip, None) + if pinger and pinger.isAlive(): + status = pinger.get_status() + if status != printer['status']: + # todo: use a lock? + printer['status'] = status + self.update_driver_status() + else: + self.start_pinging(ip) + error = False + except Exception as e: + self.set_status('error', str(e)) + errmsg = str(e) + '\n' + '-'*60+'\n' + traceback.format_exc() + '-'*60 + '\n' + _logger.error(errmsg) + finally: + if error: + self.queue.put((timestamp, task, data)) + + +# Separate instance, mainloop and queue for network printers +# original driver runs in parallel and deals with USB printers +network_driver = EscposNetworkDriver() + +hw_proxy.drivers['escpos_network'] = network_driver + +# this will also start the message handling loop +network_driver.push_task('printstatus') + + +class UpdatedEscposProxy(EscposProxy): + @http.route('/hw_proxy/print_xml_receipt', type='json', auth='none', cors='*') + def print_xml_receipt(self, receipt, proxy=None): + if proxy: + network_driver.push_task('xml_receipt', (receipt, proxy)) + else: + super(UpdatedEscposProxy, self).print_xml_receipt(receipt) + + @http.route('/hw_proxy/network_printers', type='json', auth='none', cors='*') + def network_printers(self, network_printers=None): + for printer in network_printers: + network_driver.get_network_printer(printer['ip'], name=printer['name']) + + @http.route('/hw_proxy/status_network_printers', type='json', auth='none', cors='*') + def network_printers_status(self): + return network_driver.network_printers + + @http.route('/hw_proxy/without_usb', type='http', auth='none', cors='*') + def without_usb(self): + """ Old pos_printer_network module expects this to work """ + return "ping" diff --git a/hw_printer_network/doc/changelog.rst b/hw_printer_network/doc/changelog.rst new file mode 100644 index 0000000..90c6320 --- /dev/null +++ b/hw_printer_network/doc/changelog.rst @@ -0,0 +1,14 @@ +`2.0.1` +------- + +- **FIX:** Orders sent to print are not missed after the connection to Network Printer is lost. + +`2.0.0` +------- + +- **IMP:** Asynchroneous checking of network status to speed it up when there are more than one network printer in the system. Also, there is no need to modify code of posbox anymore. + +`1.0.0` +------- + +- Init version diff --git a/hw_printer_network/doc/index.rst b/hw_printer_network/doc/index.rst new file mode 100644 index 0000000..6b188f5 --- /dev/null +++ b/hw_printer_network/doc/index.rst @@ -0,0 +1,16 @@ +========================== + Hardware Network Printer +========================== + +Installation +============ + +In PosBox +--------- + +* add ``hw_printer_network`` module to *server wide modules*. Detailed instruction is here: https://odoo-development.readthedocs.io/en/latest/admin/posbox/administrate-posbox.html#how-to-update-odoo-command-line-options + +Usage +===== + +Use the module together with `Pos Network Printer `__ diff --git a/hw_printer_network/static/description/icon.png b/hw_printer_network/static/description/icon.png new file mode 100644 index 0000000..8a05828 Binary files /dev/null and b/hw_printer_network/static/description/icon.png differ diff --git a/hw_printer_network/static/description/index.html b/hw_printer_network/static/description/index.html new file mode 100644 index 0000000..a3e81ce --- /dev/null +++ b/hw_printer_network/static/description/index.html @@ -0,0 +1,46 @@ +
+
+
+

Network Printer support for PosBox

+

Driver for Network printers

+
+
+
+ +
+
+
+

+

+ + It is a technical module and used for Pos Network Printer. +

+

+ Note: see the Documentation tab for installation instructions. +

+
+
+
+
+ +
+
+

Free Support

+

You will get free support and assistance in case of any issues

+
+
+ +
+
+
+
+

Need our service?

+

Contact us by email or fill out request form

+ +
+
+
+
diff --git a/mrp_brewing/__openerp__.py b/mrp_brewing/__openerp__.py index 391ebe8..13d03c6 100644 --- a/mrp_brewing/__openerp__.py +++ b/mrp_brewing/__openerp__.py @@ -22,7 +22,7 @@ 'description': 'Allows to print traceability reports on the stock moves', 'category': 'Stock', 'version': '1.0', - 'author': 'Open Architects Consulting sprl', + 'author': 'Coop IT Easy SCRLfs', 'depends': ['base', 'mrp_byproduct', 'stock', @@ -44,7 +44,6 @@ 'views/mrp_view.xml', 'views/brew_view.xml', 'views/stock_view.xml', - 'views/invoice_template.xml', 'views/sale_view.xml', 'views/sale_order_report.xml', 'views/partner_view.xml', diff --git a/mrp_brewing/models/stock.py b/mrp_brewing/models/stock.py index 001abf6..0325b69 100644 --- a/mrp_brewing/models/stock.py +++ b/mrp_brewing/models/stock.py @@ -25,8 +25,7 @@ def get_on_hand(self): readonly=True) is_internal = fields.Boolean( string="Is Internal", - compute="_compute_is_internal", - ) + compute="_compute_is_internal") @api.multi @api.depends('location_id', 'location_dest_id') @@ -38,13 +37,35 @@ def _compute_is_internal(self): and move.location_dest_id.usage == 'internal' ) + @api.model + def _compute_product_domain(self, is_internal): + if is_internal: + domain = [('type', 'in', ['product', 'consu']), + ('sale_ok', '=', True)] + else: + domain = [('type', 'in', ['product', 'consu'])] + + return domain + @api.onchange('is_internal') def onchange_is_internal(self): - if self.is_internal: - domain = {'product_id': [('sale_ok', '=', True)]} - else: - domain = {'product_id': []} - return {'value': [], 'domain': domain} + domain = self._compute_product_domain(self.is_internal) + return {'value': [], 'domain': {'product_id': domain}} + + @api.model + def fields_view_get(self, view_id=None, view_type='form', + toolbar=False, submenu=False): + result = ( + super(StockMove, self) + .fields_view_get(view_id, view_type, + toolbar=toolbar, submenu=submenu) + ) + if 'fields' in result and 'product_id' in result['fields']: + result['fields']['product_id']['domain'] = ( + self._compute_product_domain( + result['fields'].get('is_internal', False)) + ) + return result class StockWarehouseOrderpoint(models.Model): diff --git a/mrp_brewing/views/invoice_template.xml b/mrp_brewing/views/invoice_template.xml deleted file mode 100644 index b8fd24e..0000000 --- a/mrp_brewing/views/invoice_template.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/mrp_brewing/views/stock_view.xml b/mrp_brewing/views/stock_view.xml index 16b5f29..00b2d8d 100644 --- a/mrp_brewing/views/stock_view.xml +++ b/mrp_brewing/views/stock_view.xml @@ -87,5 +87,16 @@ + + + stock.move.form + stock.move + + + + + + + - \ No newline at end of file + diff --git a/product_subscription/models/invoice.py b/product_subscription/models/invoice.py index 795c44e..f7975ff 100644 --- a/product_subscription/models/invoice.py +++ b/product_subscription/models/invoice.py @@ -2,16 +2,20 @@ from datetime import datetime from openerp import models, fields, api + class AccountInvoice(models.Model): _inherit = "account.invoice" - + subscription = fields.Boolean(string="Subscription") - product_subscription_request = fields.One2many('product.subscription.request','invoice', string="Product subscription") + product_subscription_request = fields.One2many( + 'product.subscription.request', + 'invoice', + string="Product subscription") - def process_subscription(self,effective_date): + def process_subscription(self, effective_date): # set the subscription request to paid - req_vals = {'state':'paid', - 'payment_date':effective_date} + req_vals = {'state': 'paid', + 'payment_date': effective_date} sub_req = self.product_subscription_request sub_template = sub_req.subscription_template @@ -22,8 +26,8 @@ def process_subscription(self,effective_date): if len(subscriber.subscriptions) > 0: # there is an existing subscription subscription = subscriber.subscriptions[0] - sub_vals = {'state':'ongoing', - 'counter':subscription.counter + sub_template.product_qty} + sub_vals = {'state': 'ongoing', + 'counter': subscription.counter + sub_template.product_qty} subscription.write(sub_vals) req_vals['subscription'] = subscription.id else: @@ -31,14 +35,14 @@ def process_subscription(self,effective_date): prod_sub_seq = self.env.ref('product_subscription.sequence_product_subscription', False) prod_sub_num = prod_sub_seq.next_by_id() - sub_vals = {'name':prod_sub_num, - 'subscriber':subscriber.id, - 'subscribed_on':effective_date, - 'counter':sub_template.product_qty, - 'state':'ongoing'} + sub_vals = {'name': prod_sub_num, + 'subscriber': subscriber.id, + 'subscribed_on': effective_date, + 'counter': sub_template.product_qty, + 'state': 'ongoing'} subscription = self.env['product.subscription.object'].create(sub_vals) req_vals['subscription'] = subscription.id - subscriber.write({'subscriber':True,'old_subscriber':False}) + subscriber.write({'subscriber': True, 'old_subscriber': False}) sub_req.write(req_vals) # Send confirmation email self.send_confirm_paid_email() @@ -48,14 +52,16 @@ def process_subscription(self,effective_date): def confirm_paid(self): for invoice in self: super(AccountInvoice, invoice).confirm_paid() - # we check if there is an open refund for this invoice. in this case we - # don't run the process_subscription function as the invoice has been - # reconciled with a refund and not a payment. - refund = self.search([('type','=','out_refund'),('origin','=',invoice.move_name)]) - + # we check if there is an open refund for this invoice. in this + # case we don't run the process_subscription function as the + # invoice has been reconciled with a refund and not a payment. + refund = self.search([('type', '=', 'out_refund'), + ('origin', '=', invoice.move_name)]) + if invoice.subscription and invoice.type == 'out_invoice' and not refund: effective_date = datetime.now().strftime("%d/%m/%Y") - #take the effective date from the payment. by default the confirmation date is the payment date + # take the effective date from the payment. + # by default the confirmation date is the payment date if invoice.payment_move_line_ids: move_line = invoice.payment_move_line_ids[0] effective_date = move_line.date @@ -70,6 +76,5 @@ def send_confirm_paid_email(self): 'product_subscription' '.subscription_payment_confirmation_email_template' ) - (self.env['mail.template'] - .browse(conf_email_template.id) - .send_mail(self.id)) + for invoice in self: + conf_email_template.send_mail(invoice.id) diff --git a/purchase_custom_search_product/__init__.py b/purchase_custom_search_product/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/purchase_custom_search_product/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/purchase_custom_search_product/__openerp__.py b/purchase_custom_search_product/__openerp__.py new file mode 100644 index 0000000..dc735c7 --- /dev/null +++ b/purchase_custom_search_product/__openerp__.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Copyright 2019 Coop IT Easy SCRLfs +# Nicolas Jamoulle, +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +{ + "name": "Custom search product for purchase lines", + "version": "1.0", + "depends": [ + 'purchase', + ], + "author": "Coop IT Easy SCRLfs", + "license": "AGPL-3", + "website": "www.coopiteasy.be", + "description": """ + Do not allow to add product mark as 'Cannot be buy' + """, + "data": [ + 'views/purchase_view.xml', + ], + 'installable': True, +} diff --git a/purchase_custom_search_product/models/__init__.py b/purchase_custom_search_product/models/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/purchase_custom_search_product/models/__init__.py @@ -0,0 +1 @@ + diff --git a/purchase_custom_search_product/views/purchase_view.xml b/purchase_custom_search_product/views/purchase_view.xml new file mode 100644 index 0000000..3823f22 --- /dev/null +++ b/purchase_custom_search_product/views/purchase_view.xml @@ -0,0 +1,16 @@ + + + + + purchase.order.form.inherit + purchase.order + + + + [('purchase_ok', '=', True)] + + + + + diff --git a/stock_product_weight_on_receipt/__init__.py b/stock_product_weight_on_receipt/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/stock_product_weight_on_receipt/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/stock_product_weight_on_receipt/__openerp__.py b/stock_product_weight_on_receipt/__openerp__.py new file mode 100644 index 0000000..19f7ac6 --- /dev/null +++ b/stock_product_weight_on_receipt/__openerp__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# Copyright 2019 Coop IT Easy SCRLfs +# Nicolas Jamoulle, +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +{ + "name": "Weight product on receipt", + "version": "9.0.1.0", + "depends": [ + 'stock', + 'beesdoo_product', + ], + "author": "Coop IT Easy SCRLfs", + "license": "AGPL-3", + "website": "www.coopiteasy.be", + "description": """ + Show product weight and unit weight on each line of a receipt + """, + "data": [ + 'views/stock_view.xml', + 'reports/report_deliveryslip.xml', + ], + 'installable': True, +} diff --git a/stock_product_weight_on_receipt/i18n/fr.po b/stock_product_weight_on_receipt/i18n/fr.po new file mode 100644 index 0000000..a746816 --- /dev/null +++ b/stock_product_weight_on_receipt/i18n/fr.po @@ -0,0 +1,41 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_product_weight_on_receipt +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 9.0c\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-02-18 13:46+0000\n" +"PO-Revision-Date: 2019-02-18 13:46+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: stock_product_weight_on_receipt +#: model:ir.ui.view,arch_db:stock_product_weight_on_receipt.report_receipt_weight +msgid "Weight" +msgstr "Poids/unité" + +#. module: stock_product_weight_on_receipt +#: model:ir.model,name:stock_product_weight_on_receipt.model_stock_pack_operation +msgid "Packing Operation" +msgstr "Colisage" + +#. module: stock_product_weight_on_receipt +#: model:ir.model,name:stock_product_weight_on_receipt.model_purchase_order_line +msgid "Purchase Order Line" +msgstr "Ligne de commande d'achat" + +#. module: stock_product_weight_on_receipt +#: model:ir.model.fields,field_description:stock_product_weight_on_receipt.field_stock_pack_operation_display_weight +msgid "Weight" +msgstr "Poids" + +#. module: stock_product_weight_on_receipt +#: model:ir.model.fields,field_description:stock_product_weight_on_receipt.field_stock_pack_operation_display_unit +msgid "Weight Unit" +msgstr "Unité de poids" diff --git a/stock_product_weight_on_receipt/models/__init__.py b/stock_product_weight_on_receipt/models/__init__.py new file mode 100644 index 0000000..12bab77 --- /dev/null +++ b/stock_product_weight_on_receipt/models/__init__.py @@ -0,0 +1 @@ +from . import stock diff --git a/stock_product_weight_on_receipt/models/stock.py b/stock_product_weight_on_receipt/models/stock.py new file mode 100644 index 0000000..f5a77cc --- /dev/null +++ b/stock_product_weight_on_receipt/models/stock.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +from openerp import api, fields, models + + +class StockPackOperation(models.Model): + _inherit = 'stock.pack.operation' + + display_weight = fields.Float(string='Weight', + related='product_id.display_weight') + + display_unit = fields.Many2one( + 'product.uom', + 'Weight Unit', + related='product_id.display_unit' + ) diff --git a/stock_product_weight_on_receipt/reports/report_deliveryslip.xml b/stock_product_weight_on_receipt/reports/report_deliveryslip.xml new file mode 100644 index 0000000..4753ca9 --- /dev/null +++ b/stock_product_weight_on_receipt/reports/report_deliveryslip.xml @@ -0,0 +1,23 @@ + + + + + + diff --git a/stock_product_weight_on_receipt/views/stock_view.xml b/stock_product_weight_on_receipt/views/stock_view.xml new file mode 100644 index 0000000..81d91af --- /dev/null +++ b/stock_product_weight_on_receipt/views/stock_view.xml @@ -0,0 +1,17 @@ + + + + + stock.picking.form.inherit + stock.picking + + + + + + + + + + diff --git a/stock_provider_ref_on_receipt/__init__.py b/stock_provider_ref_on_receipt/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/stock_provider_ref_on_receipt/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/stock_provider_ref_on_receipt/__openerp__.py b/stock_provider_ref_on_receipt/__openerp__.py new file mode 100644 index 0000000..ebdfcc5 --- /dev/null +++ b/stock_provider_ref_on_receipt/__openerp__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2019 Coop IT Easy SCRLfs +# Nicolas Jamoulle, +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +{ + "name": "Provider reference on receipt", + "version": "9.0.1.0", + "depends": [ + 'stock', + ], + "author": "Coop IT Easy SCRLfs", + "license": "AGPL-3", + "website": "www.coopiteasy.be", + "description": """ + Show provider reference on each line of a receipt + """, + "data": [ + 'views/stock_view.xml', + 'reports/report_deliveryslip.xml' + ], + 'installable': True, +} diff --git a/stock_provider_ref_on_receipt/i18n/fr.po b/stock_provider_ref_on_receipt/i18n/fr.po new file mode 100644 index 0000000..948d3f7 --- /dev/null +++ b/stock_provider_ref_on_receipt/i18n/fr.po @@ -0,0 +1,41 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * stock_provider_ref_on_receipt +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 9.0c\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-02-14 08:34+0000\n" +"PO-Revision-Date: 2019-02-14 08:34+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: stock_provider_ref_on_receipt +#: model:ir.ui.view,arch_db:stock_provider_ref_on_receipt.report_receipt_provider_ref +msgid "Provider ref." +msgstr "Ref. fournisseur" + +#. module: stock_provider_ref_on_receipt +#: model:ir.model,name:stock_provider_ref_on_receipt.model_stock_inventory_line +msgid "Inventory Line" +msgstr "Ligne d'inventaire" + +#. module: stock_provider_ref_on_receipt +#: model:ir.model,name:stock_provider_ref_on_receipt.model_stock_pack_operation +msgid "Packing Operation" +msgstr "Colisage" + +#. module: stock_provider_ref_on_receipt +#: model:ir.model.fields,field_description:stock_provider_ref_on_receipt.field_stock_pack_operation_provider_ref +msgid "Provider Reference" +msgstr "Ref. fournisseur" + +#. module: stock_provider_ref_on_receipt +#: model:ir.model,name:stock_provider_ref_on_receipt.model_stock_picking +msgid "Transfer" +msgstr "Transfert" diff --git a/stock_provider_ref_on_receipt/models/__init__.py b/stock_provider_ref_on_receipt/models/__init__.py new file mode 100644 index 0000000..12bab77 --- /dev/null +++ b/stock_provider_ref_on_receipt/models/__init__.py @@ -0,0 +1 @@ +from . import stock diff --git a/stock_provider_ref_on_receipt/models/stock.py b/stock_provider_ref_on_receipt/models/stock.py new file mode 100644 index 0000000..8ce3a97 --- /dev/null +++ b/stock_provider_ref_on_receipt/models/stock.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +from openerp import api, fields, models + + +class Product(models.Model): + _inherit = 'stock.pack.operation' + + provider_ref = fields.Char(string="Provider Reference", + compute="_compute_product_code") + + @api.multi + @api.depends('provider_ref') + def _compute_product_code(self): + for product in self: + product_supplier = self.env['product.supplierinfo'].search( + [('product_tmpl_id', '=', product.product_id.product_tmpl_id.id)]) + if product_supplier: + product.provider_ref = product_supplier[0].product_code diff --git a/stock_provider_ref_on_receipt/reports/report_deliveryslip.xml b/stock_provider_ref_on_receipt/reports/report_deliveryslip.xml new file mode 100644 index 0000000..32408cb --- /dev/null +++ b/stock_provider_ref_on_receipt/reports/report_deliveryslip.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/stock_provider_ref_on_receipt/views/stock_view.xml b/stock_provider_ref_on_receipt/views/stock_view.xml new file mode 100644 index 0000000..3811713 --- /dev/null +++ b/stock_provider_ref_on_receipt/views/stock_view.xml @@ -0,0 +1,15 @@ + + + + + stock.picking.form.inherit + stock.picking + + + + + + + + + diff --git a/website_product_subscription/controllers/main.py b/website_product_subscription/controllers/main.py index afd078a..b053fc8 100644 --- a/website_product_subscription/controllers/main.py +++ b/website_product_subscription/controllers/main.py @@ -1,12 +1,5 @@ # -*- coding: utf-8 -*- -import base64 -import datetime -import re - -import werkzeug -import werkzeug.urls - -from openerp import http, SUPERUSER_ID +from openerp import http from openerp.http import request from openerp.tools.translate import _ @@ -15,18 +8,27 @@ class WebsiteProductSubscription(http.Controller): - @http.route(['/page/login_subscriber','/login_subscriber'], type='http', auth="user", website=True) + @http.route(['/page/login_subscriber', + '/login_subscriber'], + type='http', + auth="user", + website=True) def login_subscriber(self, **kwargs): return request.redirect("/page/become_subscriber") - @http.route(['/page/become_subscriber','/become_subscriber'], type='http', auth="public", website=True) + @http.route(['/page/become_subscriber', + '/become_subscriber'], + type='http', + auth="public", + website=True) def display_subscription_page(self, **kwargs): values = {} values = self.fill_values(values, True) - for field in ['email','firstname','lastname','address','city','zip_code','country_id','error_msg']: + for field in ['email', 'firstname', 'lastname', 'address', 'city', + 'zip_code', 'country_id', 'error_msg']: if kwargs.get(field): values[field] = kwargs.pop(field) @@ -34,6 +36,7 @@ def display_subscription_page(self, **kwargs): return request.website.render("website_product_subscription.becomesubscriber", values) def fill_values(self, values, load_from_user=False): + sub_temp_obj = request.env['product.subscription.template'] if load_from_user: # the subscriber is connected if request.env.user.login != 'public': @@ -49,9 +52,9 @@ def fill_values(self, values, load_from_user=False): if partner.parent_id: values['company'] = partner.parent_id.display_name - if not values.get('product_subscription_id',False): + if not values.get('product_subscription_id', False): values['product_subscription_id'] = 0 - values['subscriptions'] = request.env['product.subscription.template'].sudo().search([('publish','=',True)]) + values['subscriptions'] = sub_temp_obj.sudo().search([('publish', '=', True)]) values['countries'] = self.get_countries() if not values.get('country_id'): @@ -64,21 +67,22 @@ def get_countries(self): return countries def get_address(self, kwargs): - vals = {'zip':kwargs.get("zip_code"), - 'city':kwargs.get("city"), - 'country_id':kwargs.get("country_id")} - address = kwargs.get("street") +', ' + kwargs.get("street_number") + vals = {'zip': kwargs.get("zip_code"), + 'city': kwargs.get("city"), + 'country_id': kwargs.get("country_id")} + address = kwargs.get("street") + ', ' + kwargs.get("street_number") if kwargs.get("box").strip() != '': address = address + ', ' + kwargs.get("box").strip() vals['street'] = address return vals def get_receiver(self, kwargs): - vals = {'email': kwargs.get("subscriber_email"),'out_inv_comm_type':'bba', - 'out_inv_comm_algorithm':'random'} + vals = {'email': kwargs.get("subscriber_email"), + 'out_inv_comm_type': 'bba', + 'out_inv_comm_algorithm': 'random'} firstname = kwargs.get("subscriber_firstname").title() lastname = kwargs.get("subscriber_lastname").upper() - vals['name'] = firstname + ' ' + lastname + vals['name'] = firstname + ' ' + lastname vals['firstname'] = firstname vals['lastname'] = lastname vals["customer"] = True @@ -92,14 +96,15 @@ def product_subscription(self, **kwargs): values = {} redirect = "website_product_subscription.becomesubscriber" - if not kwargs.has_key('g-recaptcha-response') or not request.website.is_captcha_valid(kwargs['g-recaptcha-response']): - values = self.fill_values(values) - values.update(kwargs) - values["error_msg"] = "the captcha has not been validated, please fill in the captcha" + if 'g-recaptcha-response' not in kwargs or not request.website.is_captcha_valid(kwargs['g-recaptcha-response']): + values = self.fill_values(values) + values.update(kwargs) + values["error_msg"] = _("the captcha has not been validated, " + "please fill in the captcha") - return request.website.render(redirect, values) + return request.website.render(redirect, values) - logged = kwargs.get("logged")=='on' + logged = kwargs.get("logged") == 'on' gift = kwargs.get("gift") == 'on' if not logged and kwargs.get("email") != kwargs.get("email_confirmation"): @@ -108,14 +113,16 @@ def product_subscription(self, **kwargs): values["error_msg"] = "email and confirmation email doesn't match" return request.website.render(redirect, values) - if not logged and kwargs.has_key('email'): - user = user_obj.sudo().search([('login','=',kwargs.get("email"))]) - if user: - values = self.fill_values(values) - values.update(kwargs) - values["error_msg"] = "There is an existing account for this mail address. Please login before fill in the form" + if not logged and 'email' in kwargs: + user = user_obj.sudo().search([('login', '=', kwargs.get("email"))]) + if user: + values = self.fill_values(values) + values.update(kwargs) + values["error_msg"] = _("There is an existing account for " + "this mail address. Please login " + "before fill in the form") - return request.website.render(redirect, values) + return request.website.render(redirect, values) if gift: values["gift"] = gift @@ -124,14 +131,14 @@ def product_subscription(self, **kwargs): sponsor = False subscriber_vals = {} if logged: - subscriber = request.env.user.partner_id - address = self.get_address(kwargs) - if gift: - sponsor = request.env.user.partner_id - subscriber_vals.update(self.get_receiver(kwargs)) - subscriber_vals.update(address) - subscriber = partner_obj.sudo().create(subscriber_vals) - else: + subscriber = request.env.user.partner_id + address = self.get_address(kwargs) + if gift: + sponsor = request.env.user.partner_id + subscriber_vals.update(self.get_receiver(kwargs)) + subscriber_vals.update(address) + subscriber = partner_obj.sudo().create(subscriber_vals) + else: subscriber.sudo().write(address) else: lastname = kwargs.get("lastname").upper() @@ -155,7 +162,7 @@ def product_subscription(self, **kwargs): subscriber = partner_obj.sudo().create(subscriber_vals) values['subscriber'] = subscriber.id - user_values={'partner_id': subscriber.id, 'login':subscriber.email} + user_values = {'partner_id': subscriber.id, 'login': subscriber.email} if sponsor: values['sponsor'] = sponsor.id user_values['partner_id'] = sponsor.id @@ -188,7 +195,8 @@ def product_subscription(self, **kwargs): values['error_msg'] = ve.name return request.website.render(redirect, values) - # create user last to avoid creating a user when an error occurs + # create user last to avoid creating a user when + # an error occurs user_id = user_obj.sudo()._signup_create_user(user_values) user = user_obj.browse(user_id) user.sudo().with_context({'create_user': True}).action_reset_password()