diff --git a/barcode_scanning_sale_purchase/README.rst b/barcode_scanning_sale_purchase/README.rst new file mode 100644 index 000000000..d07e76512 --- /dev/null +++ b/barcode_scanning_sale_purchase/README.rst @@ -0,0 +1,47 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--1-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +Barcode scanning support for sale and Purchase v13 +================================================== + +This module will help you to use barcode scanner in sales and purchase. + +Depends +======= +[sale_management] addon Odoo +[purchase] addon Odoo + +Configuration +============= +* No additional configurations needed + +Company +------- +* `Cybrosys Techno Solutions `__ + +Credits +------- +* Developer: Sreejith P @ cybrosys, Contact: odoo@cybrosys.com + Version 13: Vaishnavi B @cybrosys,Contact: odoo@cybrosys.com +Contacts +-------- +* Mail Contact : odoo@cybrosys.com +* Website : https://cybrosys.com + +Bug Tracker +----------- +Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. + +Maintainer +========== +.. image:: https://cybrosys.com/images/logo.png + :target: https://cybrosys.com + +This module is maintained by Cybrosys Technologies. + +For support and more information, please visit `Our Website `__ + +Further information +=================== +HTML Description: ``__ diff --git a/barcode_scanning_sale_purchase/__init__.py b/barcode_scanning_sale_purchase/__init__.py new file mode 100644 index 000000000..da16ad3c5 --- /dev/null +++ b/barcode_scanning_sale_purchase/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: Sreejith P (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from . import models diff --git a/barcode_scanning_sale_purchase/__manifest__.py b/barcode_scanning_sale_purchase/__manifest__.py new file mode 100644 index 000000000..029b33cd7 --- /dev/null +++ b/barcode_scanning_sale_purchase/__manifest__.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: Sreejith P (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +{ + 'name': 'Barcode scanning support for sale and Purchase', + 'version': '13.0.1.0.0', + 'category': 'Sales', + 'summary': 'This module will help you to use barcode scanner in sales and purchase.', + 'author': 'Cybrosys Techno solutions', + 'company': 'Cybrosys Techno Solutions', + 'website': 'https://www.cybrosys.com', + 'depends': ['purchase', 'sale_management'], + 'demo': [], + 'data': [ + 'views/sale_order_line.xml', + 'views/purchase_order_line.xml', + ], + 'installable': True, + 'application': False, + 'auto_install': False, + 'images': ['static/description/banner.jpg'], + 'qweb': [], + 'license': 'AGPL-3', +} diff --git a/barcode_scanning_sale_purchase/doc/RELEASE_NOTES.md b/barcode_scanning_sale_purchase/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..1a95cc26f --- /dev/null +++ b/barcode_scanning_sale_purchase/doc/RELEASE_NOTES.md @@ -0,0 +1,6 @@ +## Module + +#### 28.10.2019 +#### Version 13.0.1.0.0 +##### ADD +- Migrated to version 13 diff --git a/barcode_scanning_sale_purchase/models/__init__.py b/barcode_scanning_sale_purchase/models/__init__.py new file mode 100644 index 000000000..ba1911358 --- /dev/null +++ b/barcode_scanning_sale_purchase/models/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: Sreejith P () +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from . import sale_order +from . import purchase_order diff --git a/barcode_scanning_sale_purchase/models/purchase_order.py b/barcode_scanning_sale_purchase/models/purchase_order.py new file mode 100644 index 000000000..b335ad518 --- /dev/null +++ b/barcode_scanning_sale_purchase/models/purchase_order.py @@ -0,0 +1,16 @@ +from odoo import api, models, fields + + +class PurchaseOrderLines(models.Model): + _inherit = "purchase.order.line" + + barcode_scan = fields.Char(string='Product Barcode', help="Here you can provide the barcode for the product") + + @api.onchange('barcode_scan') + def _onchange_barcode_scan(self): + product_rec = self.env['product.product'] + if self.barcode_scan: + product = product_rec.search([('barcode', '=', self.barcode_scan)]) + self.product_id = product.id + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/barcode_scanning_sale_purchase/models/sale_order.py b/barcode_scanning_sale_purchase/models/sale_order.py new file mode 100644 index 000000000..98e246af9 --- /dev/null +++ b/barcode_scanning_sale_purchase/models/sale_order.py @@ -0,0 +1,16 @@ +from odoo import api, models, fields + + +class SaleOrderLines(models.Model): + _inherit = 'sale.order.line' + + barcode_scan = fields.Char(string='Product Barcode', help="Here you can provide the barcode for the product") + + @api.onchange('barcode_scan') + def _onchange_barcode_scan(self): + product_rec = self.env['product.product'] + if self.barcode_scan: + product = product_rec.search([('barcode', '=', self.barcode_scan)]) + self.product_id = product.id + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/barcode_scanning_sale_purchase/static/description/banner.jpg b/barcode_scanning_sale_purchase/static/description/banner.jpg new file mode 100644 index 000000000..529143e4e Binary files /dev/null and b/barcode_scanning_sale_purchase/static/description/banner.jpg differ diff --git a/barcode_scanning_sale_purchase/static/description/cybro_logo.png b/barcode_scanning_sale_purchase/static/description/cybro_logo.png new file mode 100644 index 000000000..bb309114c Binary files /dev/null and b/barcode_scanning_sale_purchase/static/description/cybro_logo.png differ diff --git a/barcode_scanning_sale_purchase/static/description/icon.png b/barcode_scanning_sale_purchase/static/description/icon.png new file mode 100644 index 000000000..a9ded8dbd Binary files /dev/null and b/barcode_scanning_sale_purchase/static/description/icon.png differ diff --git a/barcode_scanning_sale_purchase/static/description/index.html b/barcode_scanning_sale_purchase/static/description/index.html new file mode 100644 index 000000000..45261abb0 --- /dev/null +++ b/barcode_scanning_sale_purchase/static/description/index.html @@ -0,0 +1,305 @@ + +
+
+

+ Barcode scanning support for sale and Purchase +

+

+ This module will help you to use barcode scanner in sales and purchase module. +

+
+ Cybrosys Technologies +
+
+
+
+
+

+ Overview +

+

+ A module that can use in sales and purchase for barcode scanning. +

+
+
+
+
+

+ Features +

+

+ + Use barcode in Sales order +

+

+ + Use barcode in Purchase order +

+
+
+
+
+

+ Screenshots +

+

+ + Product Form +

+

+   Provide a barcode for the product.
+

+
+ +
+

+ + Sale Order +

+

+   Just click on the barcode field and scan the product now the item is added to the order line.
+

+
+ +
+

+ + >Purchase Order +

+

+   Just click on the barcode field and scan the product now the item is added to the order line.
+

+
+ +
+ +
+
+
+ +
+
+ +
+ +
+ +
\ No newline at end of file diff --git a/barcode_scanning_sale_purchase/static/description/product_barcode.png b/barcode_scanning_sale_purchase/static/description/product_barcode.png new file mode 100644 index 000000000..7c233b2a5 Binary files /dev/null and b/barcode_scanning_sale_purchase/static/description/product_barcode.png differ diff --git a/barcode_scanning_sale_purchase/static/description/purchase_order.png b/barcode_scanning_sale_purchase/static/description/purchase_order.png new file mode 100644 index 000000000..225ff7315 Binary files /dev/null and b/barcode_scanning_sale_purchase/static/description/purchase_order.png differ diff --git a/barcode_scanning_sale_purchase/static/description/sale_order.png b/barcode_scanning_sale_purchase/static/description/sale_order.png new file mode 100644 index 000000000..077c663a4 Binary files /dev/null and b/barcode_scanning_sale_purchase/static/description/sale_order.png differ diff --git a/barcode_scanning_sale_purchase/views/purchase_order_line.xml b/barcode_scanning_sale_purchase/views/purchase_order_line.xml new file mode 100644 index 000000000..1b4fc9519 --- /dev/null +++ b/barcode_scanning_sale_purchase/views/purchase_order_line.xml @@ -0,0 +1,15 @@ + + + + + purchase.order.form.inherit + purchase.order + + + + + + + + + \ No newline at end of file diff --git a/barcode_scanning_sale_purchase/views/sale_order_line.xml b/barcode_scanning_sale_purchase/views/sale_order_line.xml new file mode 100644 index 000000000..7c4872fc7 --- /dev/null +++ b/barcode_scanning_sale_purchase/views/sale_order_line.xml @@ -0,0 +1,15 @@ + + + + + sale.order.form.inherit + sale.order + + + + + + + + + diff --git a/laundry_management/README.rst b/laundry_management/README.rst new file mode 100755 index 000000000..fb850da7d --- /dev/null +++ b/laundry_management/README.rst @@ -0,0 +1,39 @@ +Laundry Management v13 +====================== +This module helps you to manage laundry service. + +Configuration +============= +* No additional configurations needed + +Company +------- +* `Cybrosys Techno Solutions `__ + +Credits +------- +* Developers: Jesni Banu@cybrosys + Nilmar Shereef@cybrosys + Version 13: Nimisha Murali@cybrosys + +Contacts +-------- +* Mail Contact : odoo@cybrosys.com +* Website : https://cybrosys.com + +Bug Tracker +----------- +Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. + +Maintainer +========== +.. image:: https://cybrosys.com/images/logo.png + :target: https://cybrosys.com + +This module is maintained by Cybrosys Technologies. + +For support and more information, please visit `Our Website `__ + +Further information +=================== +HTML Description: ``__ diff --git a/laundry_management/__init__.py b/laundry_management/__init__.py new file mode 100755 index 000000000..81be42017 --- /dev/null +++ b/laundry_management/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: Jesni Banu and Nilmar Shereef(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from . import models +from . import reports diff --git a/laundry_management/__manifest__.py b/laundry_management/__manifest__.py new file mode 100755 index 000000000..72643566f --- /dev/null +++ b/laundry_management/__manifest__.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: Jesni Banu and Nilmar Shereef(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +{ + 'name': 'Laundry Management', + 'version': '13.0.1.0.0', + 'summary': """Complete Laundry Service Management""", + 'description': 'This module is very useful to manage all process of laundry service', + "category": "Industries", + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'website': "https://www.cybrosys.com", + 'depends': ['base', 'mail', 'sale', 'account'], + 'data': [ + 'data/data.xml', + 'security/laundry_security.xml', + 'security/ir.model.access.csv', + 'views/laundry_view.xml', + 'views/washing_view.xml', + 'views/config_view.xml', + 'views/laundry_report.xml', + 'views/laundry_label.xml', + ], + 'images': ['static/description/banner.jpg'], + 'license': 'AGPL-3', + 'demo': [], + 'installable': True, + 'auto_install': False, + 'application': False, +} diff --git a/laundry_management/data/data.xml b/laundry_management/data/data.xml new file mode 100755 index 000000000..38b466b5d --- /dev/null +++ b/laundry_management/data/data.xml @@ -0,0 +1,7 @@ + + + + Laundry Service + service + + \ No newline at end of file diff --git a/laundry_management/doc/RELEASE_NOTES.md b/laundry_management/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..6bb35ea1b --- /dev/null +++ b/laundry_management/doc/RELEASE_NOTES.md @@ -0,0 +1,9 @@ +## Module + +#### 28.10.2019 +#### Version 13.0.1.0.0 +#### ADD +Initial commit for Laundry Management + + + diff --git a/laundry_management/models/__init__.py b/laundry_management/models/__init__.py new file mode 100755 index 000000000..6868859f5 --- /dev/null +++ b/laundry_management/models/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: Jesni Banu and Nilmar Shereef(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from . import laundry diff --git a/laundry_management/models/laundry.py b/laundry_management/models/laundry.py new file mode 100755 index 000000000..7c049471b --- /dev/null +++ b/laundry_management/models/laundry.py @@ -0,0 +1,438 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: Jesni Banu and Nilmar Shereef(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +import time +from datetime import datetime +from odoo import models, fields, api, _ +from odoo.exceptions import UserError + + +class LaundryManagement(models.Model): + _name = 'laundry.order' + _inherit = 'mail.thread' + _description = "Laundry Order" + _order = 'order_date desc, id desc' + + @api.model + def create(self, vals): + vals['name'] = self.env['ir.sequence'].next_by_code('laundry.order') + return super(LaundryManagement, self).create(vals) + + @api.depends('order_lines') + def get_total(self): + total = 0 + for obj in self: + for each in obj.order_lines: + total += each.amount + obj.total_amount = total + + def confirm_order(self): + self.state = 'order' + sale_obj = self.env['sale.order'].create({'partner_id': self.partner_id.id, + 'partner_invoice_id': self.partner_invoice_id.id, + 'partner_shipping_id': self.partner_shipping_id.id}) + self.sale_obj = sale_obj + product_id = self.env.ref('laundry_management.laundry_service') + self.env['sale.order.line'].create({'product_id': product_id.id, + 'name': 'Laundry Service', + 'price_unit': self.total_amount, + 'order_id': sale_obj.id + }) + for each in self: + for obj in each.order_lines: + self.env['washing.washing'].create({'name': obj.product_id.name + '-Washing', + 'user_id': obj.washing_type.assigned_person.id, + 'description': obj.description, + 'laundry_obj': obj.id, + 'state': 'draft', + 'washing_date': datetime.now().strftime('%Y-%m-%d %H:%M:%S')}) + + def create_invoice(self): + if self.sale_obj.state in ['draft', 'sent']: + self.sale_obj.action_confirm() + self.invoice_status = self.sale_obj.invoice_status + return { + 'name': 'Create Invoice', + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'sale.advance.payment.inv', + 'type': 'ir.actions.act_window', + 'context': {'laundry_sale_obj': self.sale_obj.id}, + 'target': 'new' + } + + def return_dress(self): + self.state = 'return' + + + def cancel_order(self): + self.state = 'cancel' + + + def _invoice_count(self): + wrk_ordr_ids = self.env['account.move'].search([('invoice_origin', '=', self.sale_obj.name)]) + self.invoice_count = len(wrk_ordr_ids) + + + def _work_count(self): + wrk_ordr_ids = self.env['washing.washing'].search([('laundry_obj.laundry_obj.id', '=', self.id)]) + self.work_count = len(wrk_ordr_ids) + + + def action_view_laundry_works(self): + + work_obj = self.env['washing.washing'].search([('laundry_obj.laundry_obj.id', '=', self.id)]) + print(work_obj) + work_ids = [] + for each in work_obj: + work_ids.append(each.id) + view_id = self.env.ref('laundry_management.washing_form_view').id + if work_ids: + if len(work_ids) <= 1: + value = { + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'washing.washing', + 'view_id': view_id, + 'type': 'ir.actions.act_window', + 'name': _('Works'), + 'res_id': work_ids and work_ids[0] + } + else: + value = { + 'domain': str([('id', 'in', work_ids)]), + 'view_type': 'form', + 'view_mode': 'tree,form', + 'res_model': 'washing.washing', + 'view_id': False, + 'type': 'ir.actions.act_window', + 'name': _('Works'), + 'res_id': work_ids + } + + return value + + + def action_view_invoice(self): + + inv_obj = self.env['account.move'].search([('invoice_origin', '=', self.sale_obj.name)]) + inv_ids = [] + for each in inv_obj: + inv_ids.append(each.id) + view_id = self.env.ref('account.view_move_form').id + if inv_ids: + if len(inv_ids) <= 1: + value = { + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'account.move', + 'view_id': view_id, + 'type': 'ir.actions.act_window', + 'name': _('Invoice'), + 'res_id': inv_ids and inv_ids[0] + } + else: + value = { + 'domain': str([('id', 'in', inv_ids)]), + 'view_type': 'form', + 'view_mode': 'tree,form', + 'res_model': 'account.move', + 'view_id': False, + 'type': 'ir.actions.act_window', + 'name': _('Invoice'), + 'res_id': inv_ids + } + + return value + + name = fields.Char(string="Label", copy=False) + invoice_status = fields.Selection([ + ('upselling', 'Upselling Opportunity'), + ('invoiced', 'Fully Invoiced'), + ('to invoice', 'To Invoice'), + ('no', 'Nothing to Invoice') + ], string='Invoice Status', invisible=1, related='sale_obj.invoice_status', store=True) + sale_obj = fields.Many2one('sale.order', invisible=1) + invoice_count = fields.Integer(compute='_invoice_count', string='# Invoice') + work_count = fields.Integer(compute='_work_count', string='# Works') + partner_id = fields.Many2one('res.partner', string='Customer', readonly=True, + states={'draft': [('readonly', False)], 'order': [('readonly', False)]}, required=True, + change_default=True, index=True, track_visibility='always') + partner_invoice_id = fields.Many2one('res.partner', string='Invoice Address', readonly=True, required=True, + states={'draft': [('readonly', False)], 'order': [('readonly', False)]}, + help="Invoice address for current sales order.") + partner_shipping_id = fields.Many2one('res.partner', string='Delivery Address', readonly=True, required=True, + states={'draft': [('readonly', False)], 'order': [('readonly', False)]}, + help="Delivery address for current sales order.") + order_date = fields.Datetime(string="Date", default=datetime.now().strftime('%Y-%m-%d %H:%M:%S')) + laundry_person = fields.Many2one('res.users', string='Laundry Person', required=1) + order_lines = fields.One2many('laundry.order.line', 'laundry_obj', required=1, ondelete='cascade') + total_amount = fields.Float(compute='get_total', string='Total', store=1) + currency_id = fields.Many2one("res.currency", string="Currency") + note = fields.Text(string='Terms and conditions') + state = fields.Selection([ + ('draft', 'Draft'), + ('order', 'Laundry Order'), + ('process', 'Processing'), + ('done', 'Done'), + ('return', 'Returned'), + ('cancel', 'Cancelled'), + ], string='Status', readonly=True, copy=False, index=True, track_visibility='onchange', default='draft') + + +class LaundryManagementLine(models.Model): + _name = 'laundry.order.line' + + @api.depends('washing_type', 'extra_work', 'qty') + def get_amount(self): + for obj in self: + total = obj.washing_type.amount*obj.qty + for each in obj.extra_work: + total += each.amount*obj.qty + obj.amount = total + + product_id = fields.Many2one('product.product', string='Dress', required=1) + qty = fields.Integer(string='No of items', required=1) + description = fields.Text(string='Description') + washing_type = fields.Many2one('washing.type', string='Washing Type', required=1) + extra_work = fields.Many2many('washing.work', string='Extra Work') + amount = fields.Float(compute='get_amount', string='Amount') + laundry_obj = fields.Many2one('laundry.order', invisible=1) + state = fields.Selection([ + ('draft', 'Draft'), + ('wash', 'Washing'), + ('extra_work', 'Make Over'), + ('done', 'Done'), + ('cancel', 'Cancelled'), + ], string='Status', readonly=True, copy=False, index=True, default='draft') + + +class WashingType(models.Model): + _name = 'washing.type' + + name = fields.Char(string='Name', required=1) + assigned_person = fields.Many2one('res.users', string='Assigned Person', required=1) + amount = fields.Float(string='Service Charge', required=1) + + +class ExtraWork(models.Model): + _name = 'washing.work' + + name = fields.Char(string='Name', required=1) + assigned_person = fields.Many2one('res.users', string='Assigned Person', required=1) + amount = fields.Float(string='Service Charge', required=1) + + + +class Washing(models.Model): + _name = 'washing.washing' + + + def start_wash(self): + if not self.laundry_works: + self.laundry_obj.state = 'wash' + self.laundry_obj.laundry_obj.state = 'process' + for each in self: + for obj in each.product_line: + self.env['sale.order.line'].create({'product_id': obj.product_id.id, + 'name': obj.name, + 'price_unit': obj.price_unit, + 'order_id': each.laundry_obj.laundry_obj.sale_obj.id, + 'product_uom_qty': obj.quantity, + 'product_uom': obj.uom_id.id, + }) + self.state = 'process' + + + def set_to_done(self): + self.state = 'done' + f = 0 + if not self.laundry_works: + if self.laundry_obj.extra_work: + for each in self.laundry_obj.extra_work: + self.create({'name': each.name, + 'user_id': each.assigned_person.id, + 'description': self.laundry_obj.description, + 'laundry_obj': self.laundry_obj.id, + 'state': 'draft', + 'laundry_works': True, + 'washing_date': datetime.now().strftime('%Y-%m-%d %H:%M:%S')}) + self.laundry_obj.state = 'extra_work' + laundry_obj = self.search([('laundry_obj.laundry_obj', '=', self.laundry_obj.laundry_obj.id)]) + for each in laundry_obj: + if each.state != 'done' or each.state == 'cancel': + f = 1 + break + if f == 0: + self.laundry_obj.laundry_obj.state = 'done' + laundry_obj1 = self.search([('laundry_obj', '=', self.laundry_obj.id)]) + f1 = 0 + for each in laundry_obj1: + if each.state != 'done' or each.state == 'cancel': + f1 = 1 + break + if f1 == 0: + self.laundry_obj.state = 'done' + + + @api.depends('product_line') + def get_total(self): + total = 0 + for obj in self: + for each in obj.product_line: + total += each.subtotal + obj.total_amount = total + + name = fields.Char(string='Work') + laundry_works = fields.Boolean(default=False, invisible=1) + user_id = fields.Many2one('res.users', string='Assigned Person') + washing_date = fields.Datetime(string='Date') + description = fields.Text(string='Description') + state = fields.Selection([ + ('draft', 'Draft'), + ('process', 'Process'), + ('done', 'Done'), + ('cancel', 'Cancelled'), + ], string='Status', readonly=True, copy=False, index=True, default='draft') + laundry_obj = fields.Many2one('laundry.order.line', invisible=1) + product_line = fields.One2many('wash.order.line', 'wash_obj', string='Products', ondelete='cascade') + total_amount = fields.Float(compute='get_total', string='Grand Total') + + +class SaleOrderInherit(models.Model): + _name = 'wash.order.line' + + @api.depends('price_unit', 'quantity') + def compute_amount(self): + total = 0 + for obj in self: + total += obj.price_unit * obj.quantity + obj.subtotal = total + + wash_obj = fields.Many2one('washing.washing', string='Order Reference', ondelete='cascade') + name = fields.Text(string='Description', required=True) + uom_id = fields.Many2one('product.uom', 'Unit of Measure ', required=True) + quantity = fields.Integer(string='Quantity') + product_id = fields.Many2one('product.product', string='Product') + price_unit = fields.Float('Unit Price', default=0.0, related='product_id.list_price') + subtotal = fields.Float(compute='compute_amount', string='Subtotal', readonly=True, store=True) + + +class LaundryManagementInvoice(models.TransientModel): + _inherit = 'sale.advance.payment.inv' + + + def create_invoices(self): + context = self._context + if context.get('laundry_sale_obj'): + sale_orders = self.env['sale.order'].browse(context.get('laundry_sale_obj')) + else: + sale_orders = self.env['sale.order'].browse(self._context.get('active_ids', [])) + if self.advance_payment_method == 'delivered': + sale_orders._create_invoices() + elif self.advance_payment_method == 'all': + sale_orders._create_invoices()(final=True) + else: + # Create deposit product if necessary + if not self.product_id: + vals = self._prepare_deposit_product() + self.product_id = self.env['product.product'].create(vals) + self.env['ir.values'].sudo().set_default('sale.config.settings', 'deposit_product_id_setting', + self.product_id.id) + + sale_line_obj = self.env['sale.order.line'] + for order in sale_orders: + if self.advance_payment_method == 'percentage': + amount = order.amount_untaxed * self.amount / 100 + else: + amount = self.amount + if self.product_id.invoice_policy != 'order': + raise UserError(_( + 'The product used to invoice a down payment should have an invoice policy set to "Ordered' + ' quantities". Please update your deposit product to be able to create a deposit invoice.')) + if self.product_id.type != 'service': + raise UserError(_( + "The product used to invoice a down payment should be of type 'Service'. Please use another " + "product or update this product.")) + taxes = self.product_id.taxes_id.filtered( + lambda r: not order.company_id or r.company_id == order.company_id) + if order.fiscal_position_id and taxes: + tax_ids = order.fiscal_position_id.map_tax(taxes).ids + else: + tax_ids = taxes.ids + so_line = sale_line_obj.create({ + 'name': _('Advance: %s') % (time.strftime('%m %Y'),), + 'price_unit': amount, + 'product_uom_qty': 0.0, + 'order_id': order.id, + 'discount': 0.0, + 'product_uom': self.product_id.uom_id.id, + 'product_id': self.product_id.id, + 'tax_id': [(6, 0, tax_ids)], + }) + self._create_invoice(order, so_line, amount) + if self._context.get('open_invoices', False): + return sale_orders.action_view_invoice() + return {'type': 'ir.actions.act_window_close'} + + def _create_invoice(self, order, so_line, amount): + if (self.advance_payment_method == 'percentage' and self.amount <= 0.00) or (self.advance_payment_method == 'fixed' and self.fixed_amount <= 0.00): + raise UserError(_('The value of the down payment amount must be positive.')) + if self.advance_payment_method == 'percentage': + amount = order.amount_untaxed * self.amount / 100 + name = _("Down payment of %s%%") % (self.amount,) + else: + amount = self.fixed_amount + name = _('Down Payment') + + invoice_vals = { + 'type': 'out_invoice', + 'invoice_origin': order.name, + 'invoice_user_id': order.user_id.id, + 'narration': order.note, + 'partner_id': order.partner_invoice_id.id, + 'fiscal_position_id': order.fiscal_position_id.id or order.partner_id.property_account_position_id.id, + 'partner_shipping_id': order.partner_shipping_id.id, + 'currency_id': order.pricelist_id.currency_id.id, + 'invoice_payment_ref': order.client_order_ref, + 'invoice_payment_term_id': order.payment_term_id.id, + 'team_id': order.team_id.id, + 'campaign_id': order.campaign_id.id, + 'medium_id': order.medium_id.id, + 'source_id': order.source_id.id, + 'invoice_line_ids': [(0, 0, { + 'name': name, + 'price_unit': amount, + 'quantity': 1.0, + 'product_id': self.product_id.id, + 'sale_line_ids': [(6, 0, [so_line.id])], + 'analytic_tag_ids': [(6, 0, so_line.analytic_tag_ids.ids)], + 'analytic_account_id': order.analytic_account_id.id or False, + })], + } + if order.fiscal_position_id: + invoice_vals['fiscal_position_id'] = order.fiscal_position_id.id + invoice = self.env['account.move'].create(invoice_vals) + invoice.message_post_with_view('mail.message_origin_link', + values={'self': invoice, 'origin': order}, + subtype_id=self.env.ref('mail.mt_note').id) + return invoice diff --git a/laundry_management/reports/__init__.py b/laundry_management/reports/__init__.py new file mode 100755 index 000000000..5deb7ab66 --- /dev/null +++ b/laundry_management/reports/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: Jesni Banu and Nilmar Shereef(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from . import laundry_report diff --git a/laundry_management/reports/laundry_report.py b/laundry_management/reports/laundry_report.py new file mode 100755 index 000000000..a90833dd6 --- /dev/null +++ b/laundry_management/reports/laundry_report.py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: Jesni Banu and Nilmar Shereef(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import models, fields, tools + + +class DifferedCheckHistory(models.Model): + _name = "report.laundry.order" + _description = "Laundry Order Analysis" + _auto = False + + name = fields.Char(string="Label") + invoice_status = fields.Selection([ + ('upselling', 'Upselling Opportunity'), + ('invoiced', 'Fully Invoiced'), + ('to invoice', 'To Invoice'), + ('no', 'Nothing to Invoice') + ], string='Invoice Status', store=True) + partner_id = fields.Many2one('res.partner', string='Customer') + partner_invoice_id = fields.Many2one('res.partner', string='Invoice Address') + partner_shipping_id = fields.Many2one('res.partner', string='Delivery Address') + order_date = fields.Datetime(string="Date") + laundry_person = fields.Many2one('res.users', string='Laundry Person') + total_amount = fields.Float(string='Total') + currency_id = fields.Many2one("res.currency", string="Currency") + state = fields.Selection([ + ('draft', 'Draft'), + ('order', 'Laundry Order'), + ('process', 'Processing'), + ('done', 'Done'), + ('return', 'Returned'), + ('cancel', 'Cancelled'), + ], string='Status') + + _order = 'name desc' + + def _select(self): + select_str = """ + SELECT + (select 1 ) AS nbr, + t.id as id, + t.name as name, + t.invoice_status as invoice_status, + t.partner_id as partner_id, + t.partner_invoice_id as partner_invoice_id, + t.partner_shipping_id as partner_shipping_id, + t.order_date as order_date, + t.laundry_person as laundry_person, + t.total_amount as total_amount, + t.currency_id as currency_id, + t.state as state + """ + return select_str + + def _group_by(self): + group_by_str = """ + GROUP BY + t.id, + name, + invoice_status, + partner_id, + partner_invoice_id, + partner_shipping_id, + order_date, + laundry_person, + total_amount, + currency_id, + state + """ + return group_by_str + + def init(self): + tools.sql.drop_view_if_exists(self._cr, 'report_laundry_order') + self._cr.execute(""" + CREATE view report_laundry_order as + %s + FROM laundry_order t + %s + """ % (self._select(), self._group_by())) diff --git a/laundry_management/security/ir.model.access.csv b/laundry_management/security/ir.model.access.csv new file mode 100755 index 000000000..2433d0414 --- /dev/null +++ b/laundry_management/security/ir.model.access.csv @@ -0,0 +1,19 @@ +id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink +laundry_model_access_right_user,laundry_model_access_right,model_laundry_order,laundry_group_user,1,1,0,0 +laundry_model_access_right_manager,laundry_model_access_right1,model_laundry_order,laundry_group_manager,1,1,1,1 +laundry_order_line_model_access_right_user,laundry_order_line_model_access_right,model_laundry_order_line,laundry_group_user,1,1,0,0 +laundry_order_line_model_access_right_manager,laundry_order_line_model_access_right1,model_laundry_order_line,laundry_group_manager,1,1,1,1 +laundry_washing_type_model_access_right_user,laundry_washing_type_model_access_right,model_washing_type,laundry_group_user,1,0,0,0 +laundry_washing_type_model_access_right_manager,laundry_washing_type_model_access_right1,model_washing_type,laundry_group_manager,1,1,1,1 +laundry_washing_work_model_access_right_user,laundry_model_washing_work_access_right,model_washing_work,laundry_group_user,1,0,0,0 +laundry_washing_work_model_access_right_manager,laundry_model_washing_work_access_right1,model_washing_work,laundry_group_manager,1,1,1,1 +laundry_washing_washing_model_access_right_user,laundry_model_washing_washing_access_right,model_washing_washing,laundry_group_user,1,1,1,0 +laundry_washing_washing_model_access_right_manager,laundry_model_washing_washing_access_right1,model_washing_washing,laundry_group_manager,1,1,1,1 +laundry_wash_order_line_model_access_right_user,laundry_model_wash_order_line_access_right,model_wash_order_line,laundry_group_user,1,1,1,0 +laundry_wash_order_line_model_access_right_manager,laundry_model_wash_order_line_access_right1,model_wash_order_line,laundry_group_manager,1,1,1,1 +laundry_report_laundry_order_model_access_right_user,laundry_model_report_laundry_order_access_right,model_report_laundry_order,laundry_group_user,1,0,0,0 +laundry_report_laundry_order_model_access_right_manager,laundry_model_report_laundry_order_access_right1,model_report_laundry_order,laundry_group_manager,1,1,1,1 +laundry_report_laundry_order_model_access_right_manager1,laundry_model_report_laundry_order_access_right11,sale.model_sale_order,laundry_group_manager,1,1,1,1 +laundry_report_laundry_order_model_access_right_manager12,laundry_model_report_laundry_order_access_right112,sale.model_sale_order_line,laundry_group_manager,1,1,1,1 +laundry_report_laundry_order_model_access_right_manager11,laundry_model_report_laundry_order_access_right111,sale.model_sale_order,laundry_group_user,1,1,1,1 +laundry_report_laundry_order_model_access_right_manager112,laundry_model_report_laundry_order_access_right1112,sale.model_sale_order_line,laundry_group_user,1,1,1,1 \ No newline at end of file diff --git a/laundry_management/security/laundry_security.xml b/laundry_management/security/laundry_security.xml new file mode 100755 index 000000000..143c83250 --- /dev/null +++ b/laundry_management/security/laundry_security.xml @@ -0,0 +1,27 @@ + + + + + + Laundry + 18 + + + User + + + + + Manager + + + + + + + + + + + + diff --git a/laundry_management/static/description/additional.png b/laundry_management/static/description/additional.png new file mode 100755 index 000000000..8242a16cf Binary files /dev/null and b/laundry_management/static/description/additional.png differ diff --git a/laundry_management/static/description/banner.jpg b/laundry_management/static/description/banner.jpg new file mode 100755 index 000000000..9231f382f Binary files /dev/null and b/laundry_management/static/description/banner.jpg differ diff --git a/laundry_management/static/description/cybro_logo.png b/laundry_management/static/description/cybro_logo.png new file mode 100755 index 000000000..bb309114c Binary files /dev/null and b/laundry_management/static/description/cybro_logo.png differ diff --git a/laundry_management/static/description/cybrosys-laundry-1.png b/laundry_management/static/description/cybrosys-laundry-1.png new file mode 100755 index 000000000..661cdee73 Binary files /dev/null and b/laundry_management/static/description/cybrosys-laundry-1.png differ diff --git a/laundry_management/static/description/cybrosys-laundry-10.png b/laundry_management/static/description/cybrosys-laundry-10.png new file mode 100755 index 000000000..f72161f71 Binary files /dev/null and b/laundry_management/static/description/cybrosys-laundry-10.png differ diff --git a/laundry_management/static/description/cybrosys-laundry-11.png b/laundry_management/static/description/cybrosys-laundry-11.png new file mode 100755 index 000000000..8242a16cf Binary files /dev/null and b/laundry_management/static/description/cybrosys-laundry-11.png differ diff --git a/laundry_management/static/description/cybrosys-laundry-12.png b/laundry_management/static/description/cybrosys-laundry-12.png new file mode 100755 index 000000000..dffa63253 Binary files /dev/null and b/laundry_management/static/description/cybrosys-laundry-12.png differ diff --git a/laundry_management/static/description/cybrosys-laundry-2.png b/laundry_management/static/description/cybrosys-laundry-2.png new file mode 100755 index 000000000..37f7d375e Binary files /dev/null and b/laundry_management/static/description/cybrosys-laundry-2.png differ diff --git a/laundry_management/static/description/cybrosys-laundry-3.png b/laundry_management/static/description/cybrosys-laundry-3.png new file mode 100755 index 000000000..1bc9965b0 Binary files /dev/null and b/laundry_management/static/description/cybrosys-laundry-3.png differ diff --git a/laundry_management/static/description/cybrosys-laundry-4.png b/laundry_management/static/description/cybrosys-laundry-4.png new file mode 100755 index 000000000..a710b34b7 Binary files /dev/null and b/laundry_management/static/description/cybrosys-laundry-4.png differ diff --git a/laundry_management/static/description/cybrosys-laundry-6.png b/laundry_management/static/description/cybrosys-laundry-6.png new file mode 100755 index 000000000..b1f0fc948 Binary files /dev/null and b/laundry_management/static/description/cybrosys-laundry-6.png differ diff --git a/laundry_management/static/description/cybrosys-laundry-7.png b/laundry_management/static/description/cybrosys-laundry-7.png new file mode 100755 index 000000000..c161f99c9 Binary files /dev/null and b/laundry_management/static/description/cybrosys-laundry-7.png differ diff --git a/laundry_management/static/description/cybrosys-laundry-8.png b/laundry_management/static/description/cybrosys-laundry-8.png new file mode 100755 index 000000000..5a99b424f Binary files /dev/null and b/laundry_management/static/description/cybrosys-laundry-8.png differ diff --git a/laundry_management/static/description/cybrosys-laundry-9.png b/laundry_management/static/description/cybrosys-laundry-9.png new file mode 100755 index 000000000..fc78f1088 Binary files /dev/null and b/laundry_management/static/description/cybrosys-laundry-9.png differ diff --git a/laundry_management/static/description/demo_work.png b/laundry_management/static/description/demo_work.png new file mode 100755 index 000000000..1bc9965b0 Binary files /dev/null and b/laundry_management/static/description/demo_work.png differ diff --git a/laundry_management/static/description/icon.png b/laundry_management/static/description/icon.png new file mode 100755 index 000000000..fbf1320b2 Binary files /dev/null and b/laundry_management/static/description/icon.png differ diff --git a/laundry_management/static/description/index.html b/laundry_management/static/description/index.html new file mode 100755 index 000000000..faaf24424 --- /dev/null +++ b/laundry_management/static/description/index.html @@ -0,0 +1,471 @@ +
+
+

+ Laundry Service Management +

+

+ Cybrosys Industrial Module Which Helps You To Manage Laundry Service +

+
+ Cybrosys Technologies +
+ +
+ cybrosys technologies +
+
+
+
+ +
+
+

+ Overview +

+

+ This is an industrial specific module by Cybrosys Technologies + for Laundry Management. It manages + the laundry process with assigning works to workers. +

+
+

+ Configuration +

+

+ Access Rights +
+ + Laundry Manager : Laundry manager have all the access across the fleet rental management
+ Laundry User : Laundry user can read, write and create the records. +

+
+
+
+
+

+ Features +

+

+ + Recording Laundry Order. +

+

+ + Assigning Works. +

+

+ + Make Invoices. +

+

+ + Separate View for Works. +

+

+ + Billing Facility for Extra Works. +

+

+ + Label Printing for Every Order. +

+

+ + Detailed Laundry Work Analysis Report. +

+

+ + Access Rights From Multiple Level. +

+

+ + Configuration for Washing Type. +

+

+ + Configuration for Extra Works (Ironing/Patching etc..). +

+ +
+
+
+
+

+ Screenshots +

+

+ + Recording Laundry Order +

+
+

Laundry Management -> Laundry Management -> Laundry Order

+
+ + When you install this module, an extra menu + Laundry Management will created in main menu. + Youcan see the different sub menus under the main menu. Here you + can create Laundry Order via clicking the 'Create' button. There you can specify the customer, laundry person, + order lines with washing type and Extra works for your order. + +
+ +
+ + When you confirm the Laundry Order the corresponding works will created under the + assigned person. There you can add extra products also. It will also add in Billing. + +
+ +
+ +
+

+ + Laundry Label +

+ + You can print label for each order from the print menu. + +
+ +
+

+ + Laundry Works +

+
+

Laundry Management -> Laundry Management -> Laundry Works

+
+ + This is the Separate Laundry Works Form. Here you can see the work status of Laundry Works. + +
+ +
+ + If there is any extra works , it will created as work When you finish the main work. Then we can see the + status of that order line is become 'Make Over'. + +
+ +
+

+ + Invoice +

+ + You can create Invoice via the button 'Create Invoice' when the order reaches to 'Done' state. + +
+ +
+ + You can see all the Invoice through the smart button "Invoices" from the Laundry Order form. + +
+ +
+

+ + Configuration +

+ + You can configure washing types from the menu Laundry Management -> Configuration -> Washing Type by + specifying the name, assigned person and service charge + +
+ +
+ + You can configure additional works from the menu Laundry Management -> Configuration -> Additional Works by + specifying the name, assigned person and service charge + +
+ +
+

+ + Laundry Work Analysis Report +

+ + You can also analyse your all Laundry Works from Laundry Management -> Report -> Laundry Order Analysis. + +
+ +
+
+
+
+
+

You Looking for a functional Documentation of this Application.?

+

Give a Request Mail to:    odoo@cybrosys.com

+
+
+
+ +
+
+ cybrosys technologies +
+
+
+
+

+ Our Services +

+
+ + + +
+ +
+ + + +
+

+ + Odoo Support +

+ +
+ +
+
+
+
+
+

+ Our Industries +

+
+
+ +
+
+ + Odoo Industry + +
+
+
+

+ + Trading + +

+

+ Easily procure and sell your products. +

+
+ +
+
+ +
+
+ + Odoo Industry + +
+
+
+

+ + Manufacturing +

+

+ Plan, track and schedule your operations. +

+
+ +
+
+ +
+
+ + Odoo Industry + +
+
+
+

+ + Restaurant +

+

+ Run your bar or restaurant methodical. +

+
+ +
+
+ +
+
+ + Odoo Industry + +
+
+
+

+ + POS +

+

+ Easy configuring and convivial selling. +

+
+ +
+
+ +
+
+ + Odoo Industry + +
+
+
+

+ + E-commerce & Website +

+

+ Mobile friendly, awe-inspiring product pages. +

+
+
+
+ +
+
+ + Odoo Industry + +
+
+
+

+ + Hotel Management +

+

+ An all-inclusive hotel management application. +

+
+
+
+ +
+
+ + Odoo Industry + +
+
+
+

+ + Education +

+

+ A Collaborative platform for educational management. +

+
+
+
+ +
+
+ + Odoo Industry + +
+
+
+

+ + Service Management +

+

+ Keep track of services and invoice accordingly. +

+
+
+
+
+
+
+ +
+ diff --git a/laundry_management/static/description/index.html~ b/laundry_management/static/description/index.html~ new file mode 100755 index 000000000..adca66f0f --- /dev/null +++ b/laundry_management/static/description/index.html~ @@ -0,0 +1,222 @@ +
+
+

Laundry Service Management

+

Cybrosys Industrial Module Which Helps You To Manage Laundry Service

+

Cybrosys Technologies

+
+
+

Features:

+
+ Recording Laundry Order.
+ Assigning Works.
+ Make Invoices.
+ Separate View for Works.
+ Billing Facility for Extra Works.
+ Label Printing for Every Order.
+ Detailed Laundry Work Analysis Report.
+ Access Rights From Multiple Level.
+ Configuration for Washing Type.
+ Configuration for Extra Works (Ironing/Patching etc..).
+
+
+
+ +
+
+
+

Overview

+

+ This is an industrial specific module by Cybrosys Technologies + for Laundry Management. It manages + the laundry process with assigning works to workers. +

+
+
+
+ +
+
+

Recording Laundry Order

+
+

+

Laundry Management -> Laundry Management -> Laundry Order

+

+ ☛ When you install this module, an extra menu + Laundry Management will created in main menu. You + can see the different sub menus under the main menu. Here you + can create Laundry Order via clicking the 'Create' button. There you can specify the customer, laundry person, + order lines with washing type and Extra works for your order. + +

+
+
+ +
+
+
+
+ ☛ When you confirm the Laundry Order the corresponding works will created under the + assigned person. There you can add extra products also. It will also add in Billing. +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+ +
+
+

Laundry Label

+
+
+ ☛ You can print label for each order from the print menu. +
+
+ +
+
+
+
+ +
+
+

Laundry Works

+
+
+

+

Laundry Management -> Laundry Management -> Laundry Works

+

+

+
+ ☛ This is the Separate Laundry Works Form. Here you can see the work status of Laundry Works. +
+
+ +
+
+ ☛ If there is any extra works , it will created as work When you finish the main work. Then we can see the + status of that order line is become 'Make Over'. +
+
+ +
+
+
+
+ +
+
+

Invoice

+
+ ☛ + You can create Invoice via the button 'Create Invoice' when the order reaches to 'Done' state. + +
+ +
+
+
+ ☛ + You can see all the Invoice through the smart button "Invoices" from the Laundry Order form. + +
+ +
+
+
+
+ +
+
+

Configuration

+
+ ☛ + You can configure washing types from the menu Laundry Management -> Configuration -> Washing Type by + specifying the name, assigned person and service charge + +
+ +
+
+
+ ☛ + You can configure additional works from the menu Laundry Management -> Configuration -> Additional Works by + specifying the name, assigned person and service charge + +
+ +
+
+
+
+ +
+
+

Laundry Work Analysis Report

+
+ ☛ + You can also analyse your all Laundry Works from Laundry Management -> Report -> Laundry Order Analysis. + +
+ +
+
+
+
+ +
+
+

Access Rights

+
+ ☛Laundry Manager :- Laundry manager have all the access across the fleet rental management
+ ☛Laundry User :- Laundry user can read, write and create the records. +
+
+
+ +
+
+

You Looking for a functional Documentation of this Application.?

+

Give a Request Mail to:    odoo@cybrosys.com

+
+
+
+ +
+

Need Any Help?

+ +
+ + + diff --git a/laundry_management/static/description/invoice.png b/laundry_management/static/description/invoice.png new file mode 100755 index 000000000..fc78f1088 Binary files /dev/null and b/laundry_management/static/description/invoice.png differ diff --git a/laundry_management/static/description/invoice1.png b/laundry_management/static/description/invoice1.png new file mode 100755 index 000000000..5a99b424f Binary files /dev/null and b/laundry_management/static/description/invoice1.png differ diff --git a/laundry_management/static/description/label.png b/laundry_management/static/description/label.png new file mode 100755 index 000000000..a710b34b7 Binary files /dev/null and b/laundry_management/static/description/label.png differ diff --git a/laundry_management/static/description/laundr_work.png b/laundry_management/static/description/laundr_work.png new file mode 100755 index 000000000..37f7d375e Binary files /dev/null and b/laundry_management/static/description/laundr_work.png differ diff --git a/laundry_management/static/description/laundry_order.png b/laundry_management/static/description/laundry_order.png new file mode 100755 index 000000000..661cdee73 Binary files /dev/null and b/laundry_management/static/description/laundry_order.png differ diff --git a/laundry_management/static/description/laundry_report.png b/laundry_management/static/description/laundry_report.png new file mode 100755 index 000000000..dffa63253 Binary files /dev/null and b/laundry_management/static/description/laundry_report.png differ diff --git a/laundry_management/static/description/makeover.png b/laundry_management/static/description/makeover.png new file mode 100755 index 000000000..c161f99c9 Binary files /dev/null and b/laundry_management/static/description/makeover.png differ diff --git a/laundry_management/static/description/order.png b/laundry_management/static/description/order.png new file mode 100755 index 000000000..b1f0fc948 Binary files /dev/null and b/laundry_management/static/description/order.png differ diff --git a/laundry_management/static/description/washing_type.png b/laundry_management/static/description/washing_type.png new file mode 100755 index 000000000..f72161f71 Binary files /dev/null and b/laundry_management/static/description/washing_type.png differ diff --git a/laundry_management/views/config_view.xml b/laundry_management/views/config_view.xml new file mode 100755 index 000000000..d0964cc70 --- /dev/null +++ b/laundry_management/views/config_view.xml @@ -0,0 +1,90 @@ + + + + + + washing.type.form + washing.type + +
+ + + + + + + + + + + +
+
+
+ + + washing.type.tree + washing.type + + + + + + + + + + + Washing Type + ir.actions.act_window + washing.type + tree,form + + + + washing.work.form + washing.work + +
+ + + + + + + + + + + +
+
+
+ + + washing.work.tree + washing.work + + + + + + + + + + + Additional Works + ir.actions.act_window + washing.work + tree,form + + + + + + + + +
+
\ No newline at end of file diff --git a/laundry_management/views/laundry_label.xml b/laundry_management/views/laundry_label.xml new file mode 100755 index 000000000..60b38cced --- /dev/null +++ b/laundry_management/views/laundry_label.xml @@ -0,0 +1,48 @@ + + + + + + + + + + diff --git a/laundry_management/views/laundry_report.xml b/laundry_management/views/laundry_report.xml new file mode 100755 index 000000000..f2086e03d --- /dev/null +++ b/laundry_management/views/laundry_report.xml @@ -0,0 +1,27 @@ + + + + + + report.laundry.order.pivot + report.laundry.order + + + + + + + + + Laundry Order Analysis + report.laundry.order + pivot + {'group_by_no_leaf':1,'group_by':[]} + This report allows you to analyse the performance of your Laundry Mangement. + + + + + + + \ No newline at end of file diff --git a/laundry_management/views/laundry_view.xml b/laundry_management/views/laundry_view.xml new file mode 100755 index 000000000..ba3985dbc --- /dev/null +++ b/laundry_management/views/laundry_view.xml @@ -0,0 +1,118 @@ + + + + + + Laundry Order Code + laundry.order + + LO + + + + laundry.order.form + laundry.order + +
+
+
+ +
+ + +
+
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + +
+ + + + + + laundry.order.tree + laundry.order + + + + + + + + + + + + + + Laundry Management + ir.actions.act_window + laundry.order + tree,form + [('laundry_person','=', uid)] + +

+ Click to create a New Order. +

+
+
+ + + + + + + \ No newline at end of file diff --git a/laundry_management/views/washing_view.xml b/laundry_management/views/washing_view.xml new file mode 100755 index 000000000..1a1c6b72a --- /dev/null +++ b/laundry_management/views/washing_view.xml @@ -0,0 +1,77 @@ + + + + + + washing.washing.form + washing.washing + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + washing.washing.tree + washing.washing + + + + + + + + + + + + Washing + ir.actions.act_window + washing.washing + tree,form + [('user_id','=', uid)] + + + + + + \ No newline at end of file diff --git a/sale_discount_total/README.rst b/sale_discount_total/README.rst new file mode 100644 index 000000000..6a9932e76 --- /dev/null +++ b/sale_discount_total/README.rst @@ -0,0 +1,40 @@ +Sale Discount on Total Amount +============================= +Discount on Total in Sale and Invoice With Discount Limit and Approval + +Configuration +============= +* No additional configurations needed + +Company +------- +* `Cybrosys Techno Solutions `__ + +Credits +------- +* Developer: Faslu Rahman@cybrosys + Version 13: Nimisha Murali@cybrosys + +Contacts +-------- +* Mail Contact : odoo@cybrosys.com +* Website : https://cybrosys.com + +Bug Tracker +----------- +Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. + +Maintainer +========== +.. image:: https://cybrosys.com/images/logo.png + :target: https://cybrosys.com + +This module is maintained by Cybrosys Technologies. + +For support and more information, please visit `Our Website `__ + +Further information +=================== +HTML Description: ``__ + + diff --git a/sale_discount_total/__init__.py b/sale_discount_total/__init__.py new file mode 100644 index 000000000..f53800003 --- /dev/null +++ b/sale_discount_total/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: Faslu Rahman(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# +from . import models +from . import reports + diff --git a/sale_discount_total/__manifest__.py b/sale_discount_total/__manifest__.py new file mode 100644 index 000000000..679fdd554 --- /dev/null +++ b/sale_discount_total/__manifest__.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: Faslu Rahman(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +{ + 'name': 'Sale Discount on Total Amount', + 'version': '13.0.1.0.0', + 'category': 'Sales Management', + 'summary': "Discount on Total in Sale and Invoice With Discount Limit and Approval", + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'website': 'http://www.cybrosys.com', + 'description': """ + +Sale Discount for Total Amount +======================= +Module to manage discount on total amount in Sale. + as an specific amount or percentage +""", + 'depends': ['sale', + 'account', 'delivery' + ], + 'data': [ + 'views/sale_view.xml', + 'views/account_invoice_view.xml', + 'views/invoice_report.xml', + 'views/sale_order_report.xml', + 'views/res_config_view.xml', + + ], + 'demo': [ + ], + 'images': ['static/description/banner.jpg'], + 'license': 'AGPL-3', + 'application': True, + 'installable': True, + 'auto_install': False, +} diff --git a/sale_discount_total/doc/RELEASE_NOTES.md b/sale_discount_total/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..a3f89e3b9 --- /dev/null +++ b/sale_discount_total/doc/RELEASE_NOTES.md @@ -0,0 +1,9 @@ +## Module + +#### 15.10.2019 +#### Version 13.0.1.0.0 +#### ADD +Initial commit for Sale Discount On Total Amount + + + diff --git a/sale_discount_total/models/__init__.py b/sale_discount_total/models/__init__.py new file mode 100644 index 000000000..695e03083 --- /dev/null +++ b/sale_discount_total/models/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: Faslu Rahman(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# +from . import sale +from . import account_invoice +from . import discount_approval + diff --git a/sale_discount_total/models/account_invoice.py b/sale_discount_total/models/account_invoice.py new file mode 100644 index 000000000..b083d8060 --- /dev/null +++ b/sale_discount_total/models/account_invoice.py @@ -0,0 +1,151 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: Faslu Rahman(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import api, fields, models + + +class AccountInvoice(models.Model): + _inherit = "account.move" + + @api.depends( + 'line_ids.debit', + 'line_ids.credit', + 'line_ids.amount_currency', + 'line_ids.amount_residual', + 'line_ids.amount_residual_currency', + 'line_ids.payment_id.state') + def _compute_amount(self): + + invoice_ids = [move.id for move in self if move.id and move.is_invoice(include_receipts=True)] + self.env['account.payment'].flush(['state']) + if invoice_ids: + self._cr.execute( + ''' + SELECT move.id + FROM account_move move + JOIN account_move_line line ON line.move_id = move.id + JOIN account_partial_reconcile part ON part.debit_move_id = line.id OR part.credit_move_id = line.id + JOIN account_move_line rec_line ON + (rec_line.id = part.credit_move_id AND line.id = part.debit_move_id) + OR + (rec_line.id = part.debit_move_id AND line.id = part.credit_move_id) + JOIN account_payment payment ON payment.id = rec_line.payment_id + JOIN account_journal journal ON journal.id = rec_line.journal_id + WHERE payment.state IN ('posted', 'sent') + AND journal.post_at = 'bank_rec' + AND move.id IN %s + ''', [tuple(invoice_ids)] + ) + in_payment_set = set(res[0] for res in self._cr.fetchall()) + else: + in_payment_set = {} + + for move in self: + total_untaxed = 0.0 + total_untaxed_currency = 0.0 + total_tax = 0.0 + total_tax_currency = 0.0 + total_residual = 0.0 + total_residual_currency = 0.0 + currencies = set() + + for line in move.line_ids: + if line.currency_id: + currencies.add(line.currency_id) + + # Untaxed amount. + if (move.is_invoice(include_receipts=True) and not line.exclude_from_invoice_tab) \ + or (move.type == 'entry' and line.debit and not line.tax_line_id): + total_untaxed += line.balance + total_untaxed_currency += line.amount_currency + + # Tax amount. + if line.tax_line_id: + total_tax += line.balance + total_tax_currency += line.amount_currency + + # Residual amount. + if move.type == 'entry' or line.account_id.user_type_id.type in ('receivable', 'payable'): + total_residual += line.amount_residual + total_residual_currency += line.amount_residual_currency + + total = total_untaxed + total_tax + total_currency = total_untaxed_currency + total_tax_currency + + if move.type == 'entry' or move.is_outbound(): + sign = 1 + else: + sign = -1 + move.amount_discount = sum((line.quantity * line.price_unit * line.discount)/100 for line in move.line_ids) + move.amount_untaxed = sign * (total_untaxed_currency if len(currencies) == 1 else total_untaxed) + move.amount_tax = sign * (total_tax_currency if len(currencies) == 1 else total_tax) + move.amount_total = sign * (total_currency if len(currencies) == 1 else total) + move.amount_residual = -sign * (total_residual_currency if len(currencies) == 1 else total_residual) + move.amount_untaxed_signed = -total_untaxed + move.amount_tax_signed = -total_tax + move.amount_total_signed = -total + move.amount_residual_signed = total_residual + + currency = len(currencies) == 1 and currencies.pop() or move.company_id.currency_id + is_paid = currency and currency.is_zero(move.amount_residual) or not move.amount_residual + + # Compute 'invoice_payment_state'. + if move.state == 'posted' and is_paid: + if move.id in in_payment_set: + move.invoice_payment_state = 'in_payment' + else: + move.invoice_payment_state = 'paid' + else: + move.invoice_payment_state = 'not_paid' + + discount_type = fields.Selection([('percent', 'Percentage'), ('amount', 'Amount')], string='Discount Type', + readonly=True, states={'draft': [('readonly', False)]}, default='percent') + discount_rate = fields.Float('Discount Amount', digits=(16, 2), readonly=True, states={'draft': [('readonly', False)]}) + amount_discount = fields.Monetary(string='Discount', store=True, readonly=True, compute='_compute_amount', + track_visibility='always') + + @api.onchange('discount_type', 'discount_rate', 'invoice_line_ids') + def supply_rate(self): + for inv in self: + if inv.discount_type == 'percent': + for line in inv.line_ids: + line.discount = inv.discount_rate + else: + total = discount = 0.0 + for line in inv.invoice_line_ids: + total += (line.quantity * line.price_unit) + if inv.discount_rate != 0: + discount = (inv.discount_rate / total) * 100 + else: + discount = inv.discount_rate + for line in inv.invoice_line_ids: + line.discount = discount + + + def button_dummy(self): + self.supply_rate() + return True + +class AccountInvoiceLine(models.Model): + _inherit = "account.move.line" + + discount = fields.Float(string='Discount (%)', digits=(16, 20), default=0.0) diff --git a/sale_discount_total/models/discount_approval.py b/sale_discount_total/models/discount_approval.py new file mode 100644 index 000000000..160d6ecb4 --- /dev/null +++ b/sale_discount_total/models/discount_approval.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: Faslu Rahman(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import api, fields, models + + +class sale_discount(models.Model): + _inherit = 'sale.order' + + state = fields.Selection([ + ('draft', 'Quotation'), + ('sent', 'Quotation Sent'), + ('waiting', 'Waiting Approval'), + ('sale', 'Sales Order'), + ('done', 'Locked'), + ('cancel', 'Cancelled'), + ], string='Status', readonly=True, copy=False, index=True, track_visibility='onchange', default='draft') + + + def action_confirm(self): + discnt = 0.0 + no_line = 0.0 + if self.company_id.so_double_validation == 'two_step': + for line in self.order_line: + no_line += 1 + discnt += line.discount + discnt = (discnt / no_line) + if self.company_id.so_double_validation_limit and discnt > self.company_id.so_double_validation_limit: + self.state = 'waiting' + return True + super(sale_discount, self).action_confirm() + + + def action_approve(self): + super(sale_discount, self).action_confirm() + return True + + +class Company(models.Model): + _inherit = 'res.company' + + so_double_validation = fields.Selection([ + ('one_step', 'Confirm sale orders in one step'), + ('two_step', 'Get 2 levels of approvals to confirm a sale order') + ], string="Levels of Approvals", default='one_step', + help="Provide a double validation mechanism for sales discount") + + so_double_validation_limit = fields.Float(string="Percentage of Discount that requires double validation'", + help="Minimum discount percentage for which a double validation is required") + + +class ResDiscountSettings(models.TransientModel): + _inherit = 'res.config.settings' + + so_order_approval = fields.Boolean("Sale Discount Approval", default=lambda self: self.env.user.company_id.so_double_validation == 'two_step') + + so_double_validation = fields.Selection(related='company_id.so_double_validation',string="Levels of Approvals *", readonly=False) + so_double_validation_limit = fields.Float(string="Discount limit requires approval in %", + related='company_id.so_double_validation_limit', readonly=False) + + def set_values(self): + super(ResDiscountSettings, self).set_values() + self.so_double_validation = 'two_step' if self.so_order_approval else 'one_step' diff --git a/sale_discount_total/models/sale.py b/sale_discount_total/models/sale.py new file mode 100644 index 000000000..31c6b8de3 --- /dev/null +++ b/sale_discount_total/models/sale.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: Faslu Rahman(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import api, fields, models +import odoo.addons.decimal_precision as dp + + +class SaleOrder(models.Model): + _inherit = "sale.order" + + @api.depends('order_line.price_total') + def _amount_all(self): + """ + Compute the total amounts of the SO. + """ + for order in self: + amount_untaxed = amount_tax = amount_discount = 0.0 + for line in order.order_line: + amount_untaxed += line.price_subtotal + amount_tax += line.price_tax + amount_discount += (line.product_uom_qty * line.price_unit * line.discount) / 100 + order.update({ + 'amount_untaxed': amount_untaxed, + 'amount_tax': amount_tax, + 'amount_discount': amount_discount, + 'amount_total': amount_untaxed + amount_tax, + }) + + + discount_type = fields.Selection([('percent', 'Percentage'), ('amount', 'Amount')], string='Discount type', + readonly=True,states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, + default='percent') + discount_rate = fields.Float('Discount Rate', digits=dp.get_precision('Account'), + readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}) + amount_untaxed = fields.Monetary(string='Untaxed Amount', store=True, readonly=True, compute='_amount_all', + track_visibility='always') + amount_tax = fields.Monetary(string='Taxes', store=True, readonly=True, compute='_amount_all', + track_visibility='always') + amount_total = fields.Monetary(string='Total', store=True, readonly=True, compute='_amount_all', + track_visibility='always') + amount_discount = fields.Monetary(string='Discount', store=True, readonly=True, compute='_amount_all', + digits=dp.get_precision('Account'), track_visibility='always') + + @api.onchange('discount_type', 'discount_rate', 'order_line') + def supply_rate(self): + + for order in self: + if order.discount_type == 'percent': + for line in order.order_line: + line.discount = order.discount_rate + else: + total = discount = 0.0 + for line in order.order_line: + total += round((line.product_uom_qty * line.price_unit)) + if order.discount_rate != 0: + discount = (order.discount_rate / total) * 100 + else: + discount = order.discount_rate + for line in order.order_line: + line.discount = discount + + def _prepare_invoice(self,): + invoice_vals = super(SaleOrder, self)._prepare_invoice() + invoice_vals.update({ + 'discount_type': self.discount_type, + 'discount_rate': self.discount_rate, + }) + return invoice_vals + + + + def button_dummy(self): + + self.supply_rate() + return True + + + + + +class SaleOrderLine(models.Model): + _inherit = "sale.order.line" + + discount = fields.Float(string='Discount (%)', digits=(16, 20), default=0.0) + diff --git a/sale_discount_total/reports/__init__.py b/sale_discount_total/reports/__init__.py new file mode 100644 index 000000000..119231c54 --- /dev/null +++ b/sale_discount_total/reports/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: Faslu Rahman(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# +from . import invoice_report +from . import sale_report diff --git a/sale_discount_total/reports/invoice_report.py b/sale_discount_total/reports/invoice_report.py new file mode 100644 index 000000000..17c1b865c --- /dev/null +++ b/sale_discount_total/reports/invoice_report.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: Faslu Rahman(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import fields, models + + +class AccountInvoiceReport(models.Model): + _inherit = 'account.invoice.report' + + discount = fields.Float('Discount', readonly=True) + + def _select(self): + res = super(AccountInvoiceReport,self)._select() + select_str = res + """, line.discount AS discount """ + return select_str + diff --git a/sale_discount_total/reports/sale_report.py b/sale_discount_total/reports/sale_report.py new file mode 100644 index 000000000..a9b9a4451 --- /dev/null +++ b/sale_discount_total/reports/sale_report.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: Faslu Rahman(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + + +from odoo import fields, models + + +class DiscountSaleReport(models.Model): + _inherit = 'sale.report' + + discount = fields.Float('Discount', readonly=True) + + def _select(self): + res = super(DiscountSaleReport,self)._select() + select_str = res+""",sum(l.product_uom_qty / u.factor * u2.factor * cr.rate * l.price_unit * l.discount / 100.0) + as discount""" + return select_str diff --git a/sale_discount_total/static/description/banner.jpg b/sale_discount_total/static/description/banner.jpg new file mode 100644 index 000000000..ccb8e1556 Binary files /dev/null and b/sale_discount_total/static/description/banner.jpg differ diff --git a/sale_discount_total/static/description/cybro_logo.png b/sale_discount_total/static/description/cybro_logo.png new file mode 100644 index 000000000..bb309114c Binary files /dev/null and b/sale_discount_total/static/description/cybro_logo.png differ diff --git a/sale_discount_total/static/description/cybrosys-sales-discount-1.png b/sale_discount_total/static/description/cybrosys-sales-discount-1.png new file mode 100644 index 000000000..edc60c470 Binary files /dev/null and b/sale_discount_total/static/description/cybrosys-sales-discount-1.png differ diff --git a/sale_discount_total/static/description/cybrosys-sales-discount-2.png b/sale_discount_total/static/description/cybrosys-sales-discount-2.png new file mode 100644 index 000000000..b23f38423 Binary files /dev/null and b/sale_discount_total/static/description/cybrosys-sales-discount-2.png differ diff --git a/sale_discount_total/static/description/cybrosys-sales-discount-3.png b/sale_discount_total/static/description/cybrosys-sales-discount-3.png new file mode 100644 index 000000000..8375dd990 Binary files /dev/null and b/sale_discount_total/static/description/cybrosys-sales-discount-3.png differ diff --git a/sale_discount_total/static/description/cybrosys-sales-discount-4.png b/sale_discount_total/static/description/cybrosys-sales-discount-4.png new file mode 100644 index 000000000..927d2e599 Binary files /dev/null and b/sale_discount_total/static/description/cybrosys-sales-discount-4.png differ diff --git a/sale_discount_total/static/description/icon.png b/sale_discount_total/static/description/icon.png new file mode 100644 index 000000000..6a1daaf65 Binary files /dev/null and b/sale_discount_total/static/description/icon.png differ diff --git a/sale_discount_total/static/description/index.html b/sale_discount_total/static/description/index.html new file mode 100644 index 000000000..a33f84d34 --- /dev/null +++ b/sale_discount_total/static/description/index.html @@ -0,0 +1,351 @@ +
+
+

+ Global Discount In Sale +

+

+ Global Discount In Sale +

+
+ Cybrosys Technologies +
+ +
+ cybrosys technologies +
+
+
+
+
+
+

+ Overview +

+

+ This module allows you to mention discount on Total of sale order and Total of Customer Invoice as percentage or as amount. +

+
+
+ +
+
+

+ Features +

+

+ + Select 'Percentage' from Discount type and give discount percentage as Discount rate. +

+

+ + Select 'Amount' from Discount type and give discount amount as Discount rate. +

+

+ + System will update the value of Discount and Total +

+
+
+
+
+

+ Screenshots +

+

+ + Sale Order +

+
+ +
+

+ + Customer Invoice +

+
+ +
+

+ + And the module also allows you to set a limit for total discount in percentage. Exceeding this limit + will require approval. +

+
+ +
+

+ + Manager level users can approve sale orders in 'Waiting Approval' stage. +

+
+ +
+
+
+ +
+
+ cybrosys technologies +
+
+
+
+

+ Our Services +

+
+ + + +
+ +
+ + + +
+

+ + Odoo Support +

+ +
+ +
+
+
+
+
+

+ Our Industries +

+
+
+ +
+
+ + Odoo Industry + +
+
+
+

+ + Trading + +

+

+ Easily procure and sell your products. +

+
+ +
+
+ +
+
+ + Odoo Industry + +
+
+
+

+ + Manufacturing +

+

+ Plan, track and schedule your operations. +

+
+ +
+
+ +
+
+ + Odoo Industry + +
+
+
+

+ + Restaurant +

+

+ Run your bar or restaurant methodical. +

+
+ +
+
+ +
+
+ + Odoo Industry + +
+
+
+

+ + POS +

+

+ Easy configuring and convivial selling. +

+
+ +
+
+ +
+
+ + Odoo Industry + +
+
+
+

+ + E-commerce & Website +

+

+ Mobile friendly, awe-inspiring product pages. +

+
+
+
+ +
+
+ + Odoo Industry + +
+
+
+

+ + Hotel Management +

+

+ An all-inclusive hotel management application. +

+
+
+
+ +
+
+ + Odoo Industry + +
+
+
+

+ + Education +

+

+ A Collaborative platform for educational management. +

+
+
+
+ +
+
+ + Odoo Industry + +
+
+
+

+ + Service Management +

+

+ Keep track of services and invoice accordingly. +

+
+
+
+
+
+
+ +
+ diff --git a/sale_discount_total/static/description/s_d_inv.png b/sale_discount_total/static/description/s_d_inv.png new file mode 100644 index 000000000..b23f38423 Binary files /dev/null and b/sale_discount_total/static/description/s_d_inv.png differ diff --git a/sale_discount_total/static/description/s_d_settings.png b/sale_discount_total/static/description/s_d_settings.png new file mode 100644 index 000000000..8375dd990 Binary files /dev/null and b/sale_discount_total/static/description/s_d_settings.png differ diff --git a/sale_discount_total/static/description/s_d_so.png b/sale_discount_total/static/description/s_d_so.png new file mode 100644 index 000000000..edc60c470 Binary files /dev/null and b/sale_discount_total/static/description/s_d_so.png differ diff --git a/sale_discount_total/static/description/s_d_state.png b/sale_discount_total/static/description/s_d_state.png new file mode 100644 index 000000000..927d2e599 Binary files /dev/null and b/sale_discount_total/static/description/s_d_state.png differ diff --git a/sale_discount_total/views/account_invoice_view.xml b/sale_discount_total/views/account_invoice_view.xml new file mode 100644 index 000000000..4a5af2d16 --- /dev/null +++ b/sale_discount_total/views/account_invoice_view.xml @@ -0,0 +1,41 @@ + + + + + + discount.account.invoice + account.move + + + + [16, 2] + + + + + +
+
+
+
+
+
+
+ + + + + + + + + + + + +
+
diff --git a/sale_discount_total/views/invoice_report.xml b/sale_discount_total/views/invoice_report.xml new file mode 100644 index 000000000..0f68f0c18 --- /dev/null +++ b/sale_discount_total/views/invoice_report.xml @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/sale_discount_total/views/res_config_view.xml b/sale_discount_total/views/res_config_view.xml new file mode 100644 index 000000000..c9f7d5fc8 --- /dev/null +++ b/sale_discount_total/views/res_config_view.xml @@ -0,0 +1,33 @@ + + + + res.config.settings.view.form.inherit.sale.discount + res.config.settings + + + + + +
+
+ +
+
+
+
+ +
+
+
+
diff --git a/sale_discount_total/views/sale_order_report.xml b/sale_discount_total/views/sale_order_report.xml new file mode 100644 index 000000000..2b3e3f526 --- /dev/null +++ b/sale_discount_total/views/sale_order_report.xml @@ -0,0 +1,21 @@ + + + + + + + + \ No newline at end of file diff --git a/sale_discount_total/views/sale_view.xml b/sale_discount_total/views/sale_view.xml new file mode 100644 index 000000000..3896de363 --- /dev/null +++ b/sale_discount_total/views/sale_view.xml @@ -0,0 +1,43 @@ + + + + + + discount.sale.order.form + sale.order + + + +
+ + + + + +
+ +
+
diff --git a/website_coupon/README.rst b/website_coupon/README.rst new file mode 100644 index 000000000..4ed619dd1 --- /dev/null +++ b/website_coupon/README.rst @@ -0,0 +1,38 @@ +Website Coupon Code v12 +======================= +Manage Website Coupon Codes for Products/Categories/All Products & Its Redeem Operations + +Configuration +============= +* No additional configurations needed + +Company +------- +* `Cybrosys Techno Solutions `__ + +Credits +------- +* Developer:v11- Linto CT @ cybrosys, odoo@cybrosys.com + Version12:Meera K@cybrosys,Contact: odoo@cybrosys.com + Version 13: Vaishnavi B@cybrosys,Contact: odoo@cybrosys.com +Contacts +-------- +* Mail Contact : odoo@cybrosys.com +* Website : https://cybrosys.com + +Bug Tracker +----------- +Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. + +Maintainer +========== +.. image:: https://cybrosys.com/images/logo.png + :target: https://cybrosys.com + +This module is maintained by Cybrosys Technologies. + +For support and more information, please visit Our Website `__ + +Further information +=================== +HTML Description: ``__ diff --git a/website_coupon/__init__.py b/website_coupon/__init__.py new file mode 100644 index 000000000..9b401b54f --- /dev/null +++ b/website_coupon/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. + +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: LINTO C T (odoo@cybrosys.com) +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. + +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. +# If not, see . +# +############################################################################## + +from . import models +from . import controllers + + diff --git a/website_coupon/__manifest__.py b/website_coupon/__manifest__.py new file mode 100644 index 000000000..c864c48be --- /dev/null +++ b/website_coupon/__manifest__.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: LINTO C T (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# +{ + 'name': 'Website Coupon Code', + 'version': '13.0.1.0.0', + 'summary': 'Manage Website Coupon Codes for Products/Categories/All Products & Its Redeem Operations', + 'category': 'Website', + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'depends': ['sale_management', 'website_sale'], + 'website': 'https://www.cybrosys.com', + 'data': [ + 'data/product_data.xml', + 'views/gift_voucher.xml', + 'views/applied_coupons.xml', + 'views/templates.xml', + 'security/ir.model.access.csv' + ], + 'images': ['static/description/banner.jpg'], + 'license': 'AGPL-3', + 'installable': True, + 'auto_install': False, + 'application': False, +} diff --git a/website_coupon/controllers/__init__.py b/website_coupon/controllers/__init__.py new file mode 100644 index 000000000..65a8c1201 --- /dev/null +++ b/website_coupon/controllers/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import main diff --git a/website_coupon/controllers/main.py b/website_coupon/controllers/main.py new file mode 100644 index 000000000..d165db804 --- /dev/null +++ b/website_coupon/controllers/main.py @@ -0,0 +1,155 @@ +# -*- coding: utf-8 -*- + +from datetime import datetime + +from odoo import fields, http, tools, _ +from odoo.http import request +from odoo.addons.website_sale.controllers.main import WebsiteSale + + +class WebsiteCoupon(WebsiteSale): + + @http.route(['/shop/cart'], type='http', auth="public", website=True) + def cart(self, access_token=None, revive='', **post): + + order = request.website.sale_get_order() + if order and order.state != 'draft': + request.session['sale_order_id'] = None + order = request.website.sale_get_order() + values = {} + + if order: + from_currency = order.company_id.currency_id + to_currency = order.pricelist_id.currency_id + compute_currency = lambda price: from_currency._convert( + price, to_currency, request.env.user.company_id, fields.Date.today()) + else: + compute_currency = lambda price: price + + values.update({ + 'website_sale_order': order, + 'compute_currency': compute_currency, + 'date': fields.Date.today(), + 'suggested_products': [], + }) + if order: + _order = order + if not request.env.context.get('pricelist'): + _order = order.with_context(pricelist=order.pricelist_id.id) + values['suggested_products'] = _order._cart_accessories() + + if post.get('type') == 'popover': + return request.render("website_sale.cart_popover", values, headers={'Cache-Control': 'no-cache'}) + if post.get('code_not_available'): + values['code_not_available'] = post.get('code_not_available') + elif post.get('coupon_not_available'): + values['coupon_not_available'] = post.get('coupon_not_available') + + return request.render("website_sale.cart", values) + + @http.route(['/shop/gift_coupon'], type='http', auth="public", website=True) + def gift_coupon(self, promo_voucher, **post): + """This function will be executed when we click the apply button of the voucher code in the website. + It will verify the validity and availability of that coupon. If it can be applied, the coupon will be applied + and coupon balance will also be updated""" + + curr_user = request.env.user + coupon = request.env['gift.coupon'].sudo().search([('code', '=', promo_voucher)], limit=1) + flag = True + if coupon and coupon.total_avail > 0: + applied_coupons = request.env['partner.coupon'].sudo().search([('coupon', '=', promo_voucher), + ('partner_id', '=', curr_user.partner_id.id)], limit=1) + + # checking voucher date and limit for each user for this coupon--------------------- + if coupon.partner_id: + if curr_user.partner_id.id != coupon.partner_id.id: + flag = False + today = datetime.now().date() + if flag and applied_coupons.number < coupon.limit and today <= coupon.voucher.expiry_date: + # checking coupon validity --------------------------- + # checking date of coupon ------------ + if coupon.start_date and coupon.end_date: + if today < coupon.start_date or today > coupon.end_date: + flag = False + elif coupon.start_date: + if today < coupon.start_date: + flag = False + elif coupon.end_date: + if today > coupon.end_date: + flag = False + else: + flag = False + else: + flag = False + if flag: + voucher_type = coupon.voucher.voucher_type + voucher_val = coupon.voucher_val + type = coupon.type + coupon_product = request.env['product.product'].sudo().search([('name', '=', 'Gift Coupon')], limit=1) + if coupon_product: + order = request.website.sale_get_order(force_create=1) + flag_product = False + for line in order.order_line: + if line.product_id.name == 'Gift Coupon': + flag = False + break + if flag and order.order_line: + if voucher_type == 'product': + # the voucher type is product ---------------------------- + categ_id = coupon.voucher.product_id + for line in order.order_line: + if line.product_id.name == categ_id.name: + flag_product = True + elif voucher_type == 'category': + # the voucher type is category ---------------------------- + product_id = coupon.voucher.product_categ + for line in order.order_line: + if line.product_id.categ_id.name == product_id.name: + flag_product = True + elif voucher_type == 'all': + # the voucher is applicable to all products ---------------------------- + flag_product = True + if flag_product: + # the voucher is applicable -------------------------------------- + if type == 'fixed': + # coupon type is 'fixed'-------------------------------------- + if voucher_val < order.amount_total: + coupon_product.product_tmpl_id.write({'list_price': -voucher_val}) + + else: + return request.redirect("/shop/cart?coupon_not_available=3") + elif type == 'percentage': + # coupon type is percentage ------------------------------------- + amount_final = 0 + if voucher_type == 'product': + for line in order.order_line: + if line.product_id.name == categ_id.name: + amount_final = (voucher_val / 100) * line.price_total + break + elif voucher_type == 'category': + for line in order.order_line: + if line.product_id.categ_id.name == product_id.name: + amount_final += (voucher_val / 100) * line.price_total + elif voucher_type == 'all': + amount_final = (voucher_val/100) * order.amount_total + coupon_product.product_tmpl_id.write({'list_price': -amount_final}) + order._cart_update(product_id=coupon_product.id, set_qty=1, add_qty=1) + # updating coupon balance-------------- + total = coupon.total_avail - 1 + coupon.write({'total_avail': total}) + # creating a record for this partner, i.e he is used this coupon once----------- + if not applied_coupons: + curr_user.partner_id.write({'applied_coupon': [(0, 0, {'partner_id': curr_user.partner_id.id, + 'coupon': coupon.code, + 'number': 1})]}) + else: + applied_coupons.write({'number': applied_coupons.number + 1}) + else: + return request.redirect("/shop/cart?coupon_not_available=1") + else: + return request.redirect("/shop/cart?coupon_not_available=2") + else: + + return request.redirect("/shop/cart?coupon_not_available=1") + + return request.redirect("/shop/cart") diff --git a/website_coupon/data/product_data.xml b/website_coupon/data/product_data.xml new file mode 100644 index 000000000..86681ee15 --- /dev/null +++ b/website_coupon/data/product_data.xml @@ -0,0 +1,6 @@ + + + + Gift Coupon + + diff --git a/website_coupon/doc/RELEASE_NOTES.md b/website_coupon/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..7e06636c6 --- /dev/null +++ b/website_coupon/doc/RELEASE_NOTES.md @@ -0,0 +1,6 @@ +## Module + +#### 28.10.2019 +#### Version 13.0.1.0.0 + +Initial Commit for Website Coupon. diff --git a/website_coupon/i18n/fr.po b/website_coupon/i18n/fr.po new file mode 100644 index 000000000..e689e4a20 --- /dev/null +++ b/website_coupon/i18n/fr.po @@ -0,0 +1,315 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * website_coupon +# +# Xavier Brochard , 2017. +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0-20171109\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-11-17 11:24+0000\n" +"PO-Revision-Date: 2017-11-17 15:04+0100\n" +"Last-Translator: Xavier Brochard \n" +"Language-Team: French <>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" +"Language: fr\n" +"X-Generator: Lokalize 2.0\n" + +#. module: website_coupon +#: model:ir.ui.view,arch_db:website_coupon.cart_lines_extended +msgid " Remove" +msgstr " Enlever" + +#. module: website_coupon +#: selection:gift.voucher,voucher_type:0 +msgid "All Products" +msgstr "Tous les articles" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_gift_voucher_voucher_type +msgid "Applicable on " +msgstr "Valable sur" + +#. module: website_coupon +#: model:ir.ui.view,arch_db:website_coupon.applied_coupons_view +msgid "Applied Coupons" +msgstr "" + +#. module: website_coupon +#: model:ir.ui.view,arch_db:website_coupon.voucher_code +msgid "Apply" +msgstr "Valider" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_gift_coupon_code +msgid "Code" +msgstr "" + +#. module: website_coupon +#: sql_constraint:gift.coupon:0 +msgid "Code already exists !" +msgstr "Ce code existe déjà!" + +#. module: website_coupon +#: model:ir.ui.view,arch_db:website_coupon.gift_coupon_form +msgid "Conditions" +msgstr "Restrictions obligatoires" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_partner_coupon_coupon +msgid "Coupon Applied" +msgstr "Code utilisé" + +#. module: website_coupon +#: model:ir.ui.menu,name:website_coupon.gift_coupon_history +msgid "Coupon History" +msgstr "Utilisation" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_res_partner_applied_coupon +#: model:ir.model.fields,field_description:website_coupon.field_res_users_applied_coupon +msgid "Coupons Applied" +msgstr "" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_gift_coupon_create_uid +#: model:ir.model.fields,field_description:website_coupon.field_gift_voucher_create_uid +#: model:ir.model.fields,field_description:website_coupon.field_partner_coupon_create_uid +msgid "Created by" +msgstr "" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_gift_coupon_create_date +#: model:ir.model.fields,field_description:website_coupon.field_gift_voucher_create_date +#: model:ir.model.fields,field_description:website_coupon.field_partner_coupon_create_date +msgid "Created on" +msgstr "" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_gift_coupon_display_name +#: model:ir.model.fields,field_description:website_coupon.field_gift_voucher_display_name +#: model:ir.model.fields,field_description:website_coupon.field_partner_coupon_display_name +msgid "Display Name" +msgstr "Nom affiché" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_gift_coupon_end_date +msgid "End Date" +msgstr "Finit le" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_gift_voucher_expiry_date +msgid "Expiry Date" +msgstr "Expire le" + +#. module: website_coupon +#: selection:gift.coupon,type:0 +msgid "Fixed Amount" +msgstr "Montant fixe" + +#. module: website_coupon +#: model:ir.actions.act_window,name:website_coupon.action_gift_coupon +msgid "Generate Gift Coupons" +msgstr "Créer des codes promotionnels" + +#. module: website_coupon +#: model:ir.ui.menu,name:website_coupon.gift_coupon +#: model:product.product,name:website_coupon.discount_product +#: model:product.template,name:website_coupon.discount_product_product_template +msgid "Gift Coupon" +msgstr "Code promotionel" + +#. module: website_coupon +#: model:ir.ui.menu,name:website_coupon.gift_coupon_main +msgid "Gift Coupons" +msgstr "Codes promo" + +#. module: website_coupon +#: model:ir.actions.act_window,name:website_coupon.action_gift_coupon_history +msgid "Gift Coupons History" +msgstr "Promotions utilisées" + +#. module: website_coupon +#: model:ir.ui.menu,name:website_coupon.gift_voucher +msgid "Gift Voucher" +msgstr "Promotions autorisées" + +#. module: website_coupon +#: model:ir.actions.act_window,name:website_coupon.action_gift_voucher +msgid "Gift Vouchers" +msgstr "Promotions autorisées" + +#. module: website_coupon +#: model:ir.ui.view,arch_db:website_coupon.voucher_code +msgid "Have a voucher code? Fill this field and apply." +msgstr "Vous avez un code de réduction ? Remplissez ce champ et validez." + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_gift_coupon_id +#: model:ir.model.fields,field_description:website_coupon.field_gift_voucher_id +#: model:ir.model.fields,field_description:website_coupon.field_partner_coupon_id +msgid "ID" +msgstr "" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_gift_coupon___last_update +#: model:ir.model.fields,field_description:website_coupon.field_gift_voucher___last_update +#: model:ir.model.fields,field_description:website_coupon.field_partner_coupon___last_update +msgid "Last Modified on" +msgstr "" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_gift_coupon_write_uid +#: model:ir.model.fields,field_description:website_coupon.field_gift_voucher_write_uid +#: model:ir.model.fields,field_description:website_coupon.field_partner_coupon_write_uid +msgid "Last Updated by" +msgstr "" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_gift_coupon_write_date +#: model:ir.model.fields,field_description:website_coupon.field_gift_voucher_write_date +#: model:ir.model.fields,field_description:website_coupon.field_partner_coupon_write_date +msgid "Last Updated on" +msgstr "" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_gift_coupon_partner_id +msgid "Limit to a Single Partner" +msgstr "Limiter au contact" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_gift_voucher_max_value +msgid "Maximum Voucher Value" +msgstr "Valeur de calcul maximum" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_gift_voucher_min_value +msgid "Minimum Voucher Value" +msgstr "Valeur de calcul minimum" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_gift_coupon_name +#: model:ir.model.fields,field_description:website_coupon.field_gift_voucher_name +#: model:ir.ui.view,arch_db:website_coupon.gift_coupon_form +msgid "Name" +msgstr "Nom" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_partner_coupon_number +msgid "Number of Times Used" +msgstr "Nombre de fois" + +#. module: website_coupon +#: model:ir.model,name:website_coupon.model_res_partner +#: model:ir.model.fields,field_description:website_coupon.field_partner_coupon_partner_id +msgid "Partner" +msgstr "Contact" + +#. module: website_coupon +#: selection:gift.coupon,type:0 +msgid "Percentage" +msgstr "Pourcentage" + +#. module: website_coupon +#: code:addons/website_coupon/models/gift_voucher.py:77 +#, python-format +msgid "Please check the voucher value" +msgstr "" + +#. module: website_coupon +#: model:ir.ui.view,arch_db:website_coupon.cart_lines_extended +msgid "Price" +msgstr "Prix" + +#. module: website_coupon +#: model:ir.ui.view,arch_db:website_coupon.gift_coupon_form +msgid "Pricing" +msgstr "Montant" + +#. module: website_coupon +#: selection:gift.voucher,voucher_type:0 +#: model:ir.model.fields,field_description:website_coupon.field_gift_voucher_product_id +#: model:ir.ui.view,arch_db:website_coupon.cart_lines_extended +msgid "Product" +msgstr "Article" + +#. module: website_coupon +#: selection:gift.voucher,voucher_type:0 +#: model:ir.model.fields,field_description:website_coupon.field_gift_voucher_product_categ +msgid "Product Category" +msgstr "Catégorie d'articles" + +#. module: website_coupon +#: model:ir.ui.view,arch_db:website_coupon.cart_lines_extended +msgid "Quantity" +msgstr "Quantité" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_gift_coupon_start_date +msgid "Start Date" +msgstr "Débute le" + +#. module: website_coupon +#: model:ir.ui.view,arch_db:website_coupon.voucher_code +msgid "The discount amount is too large" +msgstr "" + +#. module: website_coupon +#: model:ir.ui.view,arch_db:website_coupon.voucher_code +msgid "This gift code is not available" +msgstr "Ce code n'est pas valable" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_gift_coupon_total_avail +msgid "Total Available" +msgstr "Quantité totale disponible" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_gift_coupon_limit +msgid "Total Available For Each User" +msgstr "Quantité maxi par personne" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_gift_coupon_type +msgid "Type" +msgstr "" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_gift_coupon_voucher +msgid "Voucher" +msgstr "Autorisation" + +#. module: website_coupon +#: model:ir.ui.view,arch_db:website_coupon.voucher_code +msgid "Voucher Code" +msgstr "Code promo" + +#. module: website_coupon +#: model:ir.model.fields,field_description:website_coupon.field_gift_coupon_voucher_val +msgid "Voucher Value" +msgstr "Valeur de calcul" + +#. module: website_coupon +#: model:ir.ui.view,arch_db:website_coupon.voucher_code +msgid "code..." +msgstr "" + +#. module: website_coupon +#: model:ir.model,name:website_coupon.model_gift_coupon +msgid "gift.coupon" +msgstr "" + +#. module: website_coupon +#: model:ir.model,name:website_coupon.model_gift_voucher +msgid "gift.voucher" +msgstr "" + +#. module: website_coupon +#: model:ir.model,name:website_coupon.model_partner_coupon +msgid "partner.coupon" +msgstr "" + + diff --git a/website_coupon/models/__init__.py b/website_coupon/models/__init__.py new file mode 100644 index 000000000..290bf0968 --- /dev/null +++ b/website_coupon/models/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: LINTO C T (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# +from . import gift_voucher diff --git a/website_coupon/models/gift_voucher.py b/website_coupon/models/gift_voucher.py new file mode 100644 index 000000000..b082d405b --- /dev/null +++ b/website_coupon/models/gift_voucher.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2018-TODAY Cybrosys Technologies(). +# Author: LINTO C T() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. + +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. +# If not, see . +# +############################################################################## +import string +import random +from odoo import models, fields, api, _ +from datetime import datetime,date +from odoo.exceptions import UserError + + +class GiftVoucher(models.Model): + _name = 'gift.voucher' + + name = fields.Char(string="Name", required=True) + voucher_type = fields.Selection( + selection=[ + ('product', 'Product'), + ('category', 'Product Category'), + ('all', 'All Products'), + ], string="Applicable on ", default='product' + ) + product_id = fields.Many2one('product.product', string="Product") + product_categ = fields.Many2one('product.category', string="Product Category") + min_value = fields.Integer(string="Minimum Voucher Value", required=True) + max_value = fields.Integer(string="Maximum Voucher Value", required=True) + expiry_date = fields.Date(string="Expiry Date", required=True) + + +class GiftCoupon(models.Model): + _name = 'gift.coupon' + + def get_code(self): + size = 7 + chars = string.ascii_uppercase + string.digits + return ''.join(random.choice(chars) for _ in range(size)) + + _sql_constraints = [ + ('name_uniq', 'unique (code)', "Code already exists !"), + ] + + name = fields.Char(string="Name", required=True) + code = fields.Char(string="Code", default=get_code) + voucher = fields.Many2one('gift.voucher', string="Voucher", required=True) + start_date = fields.Date(string="Start Date") + end_date = fields.Date(string="End Date") + partner_id = fields.Many2one('res.partner', string="Limit to a Single Partner") + limit = fields.Integer(string="Total Available For Each User", default=1) + total_avail = fields.Integer(string="Total Available", default=1) + voucher_val = fields.Float(string="Voucher Value") + type = fields.Selection([ + ('fixed', 'Fixed Amount'), + ('percentage', 'Percentage'), + ], store=True, default='fixed') + + @api.onchange('voucher_val') + def check_val(self): + if self.voucher_val > self.voucher.max_value or self.voucher_val < self.voucher.min_value: + raise UserError(_("Please check the voucher value")) + + +class CouponPartner(models.Model): + _name = 'partner.coupon' + + partner_id = fields.Many2one('res.partner', string="Partner") + coupon = fields.Char(string="Coupon Applied") + number = fields.Integer(string="Number of Times Used") + + +class PartnerExtended(models.Model): + _inherit = 'res.partner' + + applied_coupon = fields.One2many('partner.coupon', 'partner_id', string="Coupons Applied") diff --git a/website_coupon/security/ir.model.access.csv b/website_coupon/security/ir.model.access.csv new file mode 100644 index 000000000..4012abf0e --- /dev/null +++ b/website_coupon/security/ir.model.access.csv @@ -0,0 +1,10 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_website_coupon_voucher,website_coupon_gift_voucher,model_gift_voucher,sales_team.group_sale_manager,1,1,1,1 +access_website_coupon_coupon,website_coupon_gift_coupon,model_gift_coupon,sales_team.group_sale_manager,1,1,1,1 +access_website_coupon_partner,website_coupon_partner_coupon,model_partner_coupon,sales_team.group_sale_manager,1,1,1,1 +access_website_voucher_user1,website_coupon_voucher_usr1,model_gift_voucher,sales_team.group_sale_salesman_all_leads,1,0,0,0 +access_website_coupon_usr1,website_gift_coupon_usr1,model_gift_coupon,sales_team.group_sale_salesman_all_leads,1,0,0,0 +access_website_coupon_partner_usr1,website_coupon_partner_usr1,model_partner_coupon,sales_team.group_sale_salesman_all_leads,1,0,0,0 +access_website_voucher_user2,website_coupon_voucher_usr2,model_gift_voucher,sales_team.group_sale_salesman,1,0,0,0 +access_website_coupon_usr2,website_gift_coupon_usr2,model_gift_coupon,sales_team.group_sale_salesman,1,0,0,0 +access_website_coupon_partner_usr2,website_coupon_partner_usr2,model_partner_coupon,sales_team.group_sale_salesman,1,0,0,0 diff --git a/website_coupon/static/description/apply_coupon.png b/website_coupon/static/description/apply_coupon.png new file mode 100644 index 000000000..4d8898cf9 Binary files /dev/null and b/website_coupon/static/description/apply_coupon.png differ diff --git a/website_coupon/static/description/banner.jpg b/website_coupon/static/description/banner.jpg new file mode 100644 index 000000000..32924c0a7 Binary files /dev/null and b/website_coupon/static/description/banner.jpg differ diff --git a/website_coupon/static/description/coupon.png b/website_coupon/static/description/coupon.png new file mode 100644 index 000000000..81d458a0e Binary files /dev/null and b/website_coupon/static/description/coupon.png differ diff --git a/website_coupon/static/description/cybro_logo.png b/website_coupon/static/description/cybro_logo.png new file mode 100644 index 000000000..bb309114c Binary files /dev/null and b/website_coupon/static/description/cybro_logo.png differ diff --git a/website_coupon/static/description/enable_voucher.png b/website_coupon/static/description/enable_voucher.png new file mode 100644 index 000000000..ae2e59dc1 Binary files /dev/null and b/website_coupon/static/description/enable_voucher.png differ diff --git a/website_coupon/static/description/history.png b/website_coupon/static/description/history.png new file mode 100644 index 000000000..495dad595 Binary files /dev/null and b/website_coupon/static/description/history.png differ diff --git a/website_coupon/static/description/icon.png b/website_coupon/static/description/icon.png new file mode 100644 index 000000000..434314a8a Binary files /dev/null and b/website_coupon/static/description/icon.png differ diff --git a/website_coupon/static/description/index.html b/website_coupon/static/description/index.html new file mode 100644 index 000000000..c386b4f33 --- /dev/null +++ b/website_coupon/static/description/index.html @@ -0,0 +1,361 @@ + +
+
+

+ Website Coupon +

+

+ ..Manage Your Coupons Simply.. +

+
+ Cybrosys Technologies +
+
+
+
+
+

+ Overview +

+

+ This module by Cybrosys Technologies allows us to manage our customers in a better way by providing + discount coupons to our special customers, and thereby increase the sales. +

+
+
+ +
+
+

+ Features +

+

+ + Create and configure vouchers for providing a discount based on product, product category or for all products. +

+

+ + Generate a unique code for each coupon. +

+ + Limit the usage of coupons by each user. +

+

+ + Provide a validity for the coupons.

+

+ + History of coupons used by each customer.

+
+
+
+
+

+ Enable the voucher option from the website. +

+

+ + When we added some product to our cart, under the 'Customize' menu, we can see the 'Voucher Code' option. +

+
+ +
+

+ Apply the coupon by providing the secret code. +

+

+ + After enabling the 'Voucher Code' option, we can enter our coupon code. If that code is valid, it will be applied to the order. The validation is based on the expiry date of the voucher, the voucher type, coupon code entered, coupon balance, etc. The total amount of an order can't be zero or less than, zero. +

+
+ +
+

+ + After we have entered the coupon code and pressed the apply button, the system will check the amount after applying the coupon specified is greater than zero or not. If not, we cannot apply this coupon to this order. In this case we will see a notification saying that this coupon is not applicable. +

+
+ +
+

+ Create and configure vouchers. +

+

+ + For creating a voucher, there are three options. We can create a voucher for a single product or a product category or for the complete products. For the first option, we need to specify a product, that means, this voucher will be applicable only if the customer has selected this product in his order. The minimum and maximum voucher values can be set here. The expiry date indicates the validity of this voucher. +

+
+ +
+ +

+ + For creating voucher for a product category, we need to select a category. In this case, this voucher will be applicable only if the cart contains products from this category. +

+
+ +
+

+ + The third option can be used to provide discounts for all the products.

+
+ +
+

+ Create and configure coupons and codes. +

+

+ + When we create the coupon, a unique, auto-generated and editable code will be there for each coupon. There are mainly + two types of coupons, fixed and percentage. The fixed type is used to deduct a fixed amount from the order. The + percentage type will deduct a certain percentage of amount from the order. + + The total number of available coupons + and the number of times one user can use this coupon can be set here. It is also possible to limit this coupon to a single customer, + i.e, only one customer can use this coupon. + +

+
+ +
+
+

+ Coupon History. +

+

+ + Under the 'Coupon History' menu, we can see the details of coupons used by all the customers.

+
+ +
+
+ + +
+ +
+
+ +
+ +
+ +
diff --git a/website_coupon/static/description/unable_to_update.png b/website_coupon/static/description/unable_to_update.png new file mode 100644 index 000000000..28bee8626 Binary files /dev/null and b/website_coupon/static/description/unable_to_update.png differ diff --git a/website_coupon/static/description/voucher_all.png b/website_coupon/static/description/voucher_all.png new file mode 100644 index 000000000..0c50df118 Binary files /dev/null and b/website_coupon/static/description/voucher_all.png differ diff --git a/website_coupon/static/description/voucher_category.png b/website_coupon/static/description/voucher_category.png new file mode 100644 index 000000000..221d5e544 Binary files /dev/null and b/website_coupon/static/description/voucher_category.png differ diff --git a/website_coupon/static/description/voucher_product.png b/website_coupon/static/description/voucher_product.png new file mode 100644 index 000000000..f3b6cc02d Binary files /dev/null and b/website_coupon/static/description/voucher_product.png differ diff --git a/website_coupon/static/src/img/icon.png b/website_coupon/static/src/img/icon.png new file mode 100644 index 000000000..6a55fc088 Binary files /dev/null and b/website_coupon/static/src/img/icon.png differ diff --git a/website_coupon/views/applied_coupons.xml b/website_coupon/views/applied_coupons.xml new file mode 100644 index 000000000..1b9eb69d0 --- /dev/null +++ b/website_coupon/views/applied_coupons.xml @@ -0,0 +1,46 @@ + + + + + applied_coupons_form + res.partner + + + + + + + + + + + + + + + + + + Gift Coupon History + partner.coupon + + + + + + + + + + + Gift Coupons History + partner.coupon + ir.actions.act_window + + + tree + + + + + \ No newline at end of file diff --git a/website_coupon/views/gift_voucher.xml b/website_coupon/views/gift_voucher.xml new file mode 100644 index 000000000..4ee4f1940 --- /dev/null +++ b/website_coupon/views/gift_voucher.xml @@ -0,0 +1,124 @@ + + + + + Gift Voucher + gift.voucher + +
+ + + + + + + + + + + + + +
+
+
+ + + Gift Voucher + gift.voucher + + + + + + + + + + + + + Gift Coupon + gift.coupon + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + Gift Coupon + gift.coupon + + + + + + + + + + + + + + + + Gift Vouchers + gift.voucher + ir.actions.act_window + + tree,form + + + + Generate Gift Coupons + gift.coupon + ir.actions.act_window + + tree,form + + + + + +
+
\ No newline at end of file diff --git a/website_coupon/views/templates.xml b/website_coupon/views/templates.xml new file mode 100644 index 000000000..7e96616a7 --- /dev/null +++ b/website_coupon/views/templates.xml @@ -0,0 +1,52 @@ + + + + + + \ No newline at end of file