commit 91c3f62ca0ca729719e2f79044654ce8b9085da8 Author: cybroodoo Date: Wed May 10 15:35:31 2017 +0530 Internal Purpose diff --git a/account_pdc/__init__.py b/account_pdc/__init__.py new file mode 100644 index 000000000..55e11f5a1 --- /dev/null +++ b/account_pdc/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2017-TODAY Cybrosys Technologies(). +# Author: Cybrosys Technologies() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 models diff --git a/account_pdc/__manifest__.py b/account_pdc/__manifest__.py new file mode 100644 index 000000000..da56b10d3 --- /dev/null +++ b/account_pdc/__manifest__.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2017-TODAY Cybrosys Technologies(). +# Author: Cybrosys Technologies() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 . +# +############################################################################## +{ + 'name': 'PDC Management', + 'version': '10.0.1.0', + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'website': 'http://www.cybrosys.com', + 'category': 'Accounting', + 'summary': 'Extension on Cheques to handle Post Dated Cheques', + 'description': """ Extension on Cheques to handle Post Dated Cheques """, + 'depends': ['account_check_printing'], + 'data': [ + 'data/account_pdc_data.xml', + 'views/account_payment_view.xml', + ], + 'images': ['static/description/banner.jpg'], + 'license': 'LGPL-3', + 'installable': True, + 'auto_install': False, +} diff --git a/account_pdc/data/account_pdc_data.xml b/account_pdc/data/account_pdc_data.xml new file mode 100644 index 000000000..54ec4ca7f --- /dev/null +++ b/account_pdc/data/account_pdc_data.xml @@ -0,0 +1,19 @@ + + + + + + PDC + pdc + inbound + + + PDC + pdc + outbound + + + + + + \ No newline at end of file diff --git a/account_pdc/models/__init__.py b/account_pdc/models/__init__.py new file mode 100644 index 000000000..fdd64429b --- /dev/null +++ b/account_pdc/models/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2017-TODAY Cybrosys Technologies(). +# Author: Cybrosys Technologies() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 account_journal +import account_payment diff --git a/account_pdc/models/account_journal.py b/account_pdc/models/account_journal.py new file mode 100644 index 000000000..996a0f079 --- /dev/null +++ b/account_pdc/models/account_journal.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2017-TODAY Cybrosys Technologies(). +# Author: Cybrosys Technologies() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 odoo import models, api, _ + + +class AccountJournal(models.Model): + _inherit = "account.journal" + + @api.one + @api.depends('outbound_payment_method_ids') + def _compute_check_printing_payment_method_selected(self): + self.check_printing_payment_method_selected = any( + pm.code in ['check_printing', 'pdc'] for pm in self.outbound_payment_method_ids) + + @api.model + def _enable_pdc_on_bank_journals(self): + """ Enables check printing payment method and add a check sequence on bank journals. + Called upon module installation via data file. + """ + pdcin = self.env.ref('account_pdc.account_payment_method_pdc_in') + pdcout = self.env.ref('account_pdc.account_payment_method_pdc_out') + bank_journals = self.search([('type', '=', 'bank')]) + for bank_journal in bank_journals: + # bank_journal._create_check_sequence() + bank_journal.write({ + 'inbound_payment_method_ids': [(4, pdcin.id, None)], + 'outbound_payment_method_ids': [(4, pdcout.id, None)], + }) diff --git a/account_pdc/models/account_payment.py b/account_pdc/models/account_payment.py new file mode 100644 index 000000000..3d0e4d61e --- /dev/null +++ b/account_pdc/models/account_payment.py @@ -0,0 +1,110 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2017-TODAY Cybrosys Technologies(). +# Author: Cybrosys Technologies() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 odoo import models, fields, api, _ +from odoo.exceptions import UserError + + +class AccountRegisterPayments(models.TransientModel): + _inherit = "account.register.payments" + + bank_reference = fields.Char(copy=False) + cheque_reference = fields.Char(copy=False) + effective_date = fields.Date('Effective Date', help='Effective date of PDC', copy=False, default=False) + + def get_payment_vals(self): + res = super(AccountRegisterPayments, self).get_payment_vals() + if self.payment_method_id == self.env.ref('account_check_printing.account_payment_method_check'): + res.update({ + 'check_amount_in_words': self.check_amount_in_words, + 'check_manual_sequencing': self.check_manual_sequencing, + 'effective_date': self.effective_date, + }) + return res + + +class AccountPayment(models.Model): + _inherit = "account.payment" + + bank_reference = fields.Char(copy=False) + cheque_reference = fields.Char(copy=False) + effective_date = fields.Date('Effective Date', help='Effective date of PDC', copy=False, default=False) + + @api.multi + def print_checks(self): + """ Check that the recordset is valid, set the payments state to sent and call print_checks() """ + # Since this method can be called via a client_action_multi, we need to make sure the received records are what we expect + self = self.filtered(lambda r: r.payment_method_id.code in ['check_printing', 'pdc'] and r.state != 'reconciled') + + if len(self) == 0: + raise UserError(_("Payments to print as a checks must have 'Check' or 'PDC' selected as payment method and " + "not have already been reconciled")) + if any(payment.journal_id != self[0].journal_id for payment in self): + raise UserError(_("In order to print multiple checks at once, they must belong to the same bank journal.")) + + if not self[0].journal_id.check_manual_sequencing: + # The wizard asks for the number printed on the first pre-printed check + # so payments are attributed the number of the check the'll be printed on. + last_printed_check = self.search([ + ('journal_id', '=', self[0].journal_id.id), + ('check_number', '!=', 0)], order="check_number desc", limit=1) + next_check_number = last_printed_check and last_printed_check.check_number + 1 or 1 + return { + 'name': _('Print Pre-numbered Checks'), + 'type': 'ir.actions.act_window', + 'res_model': 'print.prenumbered.checks', + 'view_type': 'form', + 'view_mode': 'form', + 'target': 'new', + 'context': { + 'payment_ids': self.ids, + 'default_next_check_number': next_check_number, + } + } + else: + self.filtered(lambda r: r.state == 'draft').post() + self.write({'state': 'sent'}) + return self.do_print_checks() + + + def _get_move_vals(self, journal=None): + """ Return dict to create the payment move + """ + journal = journal or self.journal_id + if not journal.sequence_id: + raise UserError(_('Configuration Error !'), + _('The journal %s does not have a sequence, please specify one.') % journal.name) + if not journal.sequence_id.active: + raise UserError(_('Configuration Error !'), _('The sequence of journal %s is deactivated.') % journal.name) + name = self.move_name or journal.with_context(ir_sequence_date=self.payment_date).sequence_id.next_by_id() + if self.payment_method_code =='pdc': + date = self.effective_date + else: + date = self.payment_date + return { + 'name': name, + 'date': date, + 'ref': self.communication or '', + 'company_id': self.company_id.id, + 'journal_id': journal.id, + } diff --git a/account_pdc/static/description/banner.jpg b/account_pdc/static/description/banner.jpg new file mode 100644 index 000000000..a1a674866 Binary files /dev/null and b/account_pdc/static/description/banner.jpg differ diff --git a/account_pdc/static/description/cybro_logo.png b/account_pdc/static/description/cybro_logo.png new file mode 100644 index 000000000..bb309114c Binary files /dev/null and b/account_pdc/static/description/cybro_logo.png differ diff --git a/account_pdc/static/description/icon.png b/account_pdc/static/description/icon.png new file mode 100644 index 000000000..f47728351 Binary files /dev/null and b/account_pdc/static/description/icon.png differ diff --git a/account_pdc/static/description/index.html b/account_pdc/static/description/index.html new file mode 100644 index 000000000..48d9b1115 --- /dev/null +++ b/account_pdc/static/description/index.html @@ -0,0 +1,92 @@ +
+
+
+

PDC Management

+

...A simple way to handle Post Dated Checks...

+

Cybrosys Techno Solutions, www.cybrosys.com

+
+
+
+ +
+
+
+

Configuration

+
+
+
+ +
+
+
+

+

Select PDC:

+

As shown here, You have to select PDC to enable the PDC payment.This is only available with Journal of type 'Bank'

+

+
+
+
+ +
+
+
+

At The Time of Payment You Will Have

+
+
+
+ +
+
+
+

+

Payment form have two extra fields to put Bank and Check Detail.

+

+
+
+
+
+

+

When you select PDC, You have to put 'effective date' of PDC.

+

+
+
+
+ +
+
+
+
+ +
+

Need Any Help?

+ +
+ + + + + + + + diff --git a/account_pdc/static/description/pdc_config.png b/account_pdc/static/description/pdc_config.png new file mode 100644 index 000000000..c046b55c0 Binary files /dev/null and b/account_pdc/static/description/pdc_config.png differ diff --git a/account_pdc/static/description/pdc_payment.png b/account_pdc/static/description/pdc_payment.png new file mode 100644 index 000000000..39aa93b15 Binary files /dev/null and b/account_pdc/static/description/pdc_payment.png differ diff --git a/account_pdc/static/description/pdc_payment_eff.png b/account_pdc/static/description/pdc_payment_eff.png new file mode 100644 index 000000000..ff9b1eb04 Binary files /dev/null and b/account_pdc/static/description/pdc_payment_eff.png differ diff --git a/account_pdc/static/description/pdc_report.png b/account_pdc/static/description/pdc_report.png new file mode 100644 index 000000000..1ff2cf4f0 Binary files /dev/null and b/account_pdc/static/description/pdc_report.png differ diff --git a/account_pdc/views/account_payment_view.xml b/account_pdc/views/account_payment_view.xml new file mode 100644 index 000000000..0cd82fc50 --- /dev/null +++ b/account_pdc/views/account_payment_view.xml @@ -0,0 +1,77 @@ + + + + account.payment.form.inherited + account.payment + + + + + + + + + + Local Modules + ir.module.module + form + kanban,tree,form + {'search_default_app':1} + + + +

No module found!

+

You should try others search criteria.

+
+
+ + + +
diff --git a/developer_mode/views/ir_rule_view.xml b/developer_mode/views/ir_rule_view.xml new file mode 100644 index 000000000..3f74bb72c --- /dev/null +++ b/developer_mode/views/ir_rule_view.xml @@ -0,0 +1,14 @@ + + + + + ir.rule + + + + + + + + + diff --git a/developer_mode/views/web_view.xml b/developer_mode/views/web_view.xml new file mode 100644 index 000000000..fd34ee7a1 --- /dev/null +++ b/developer_mode/views/web_view.xml @@ -0,0 +1,13 @@ + + + + DeveloperMode + + + + '%s%sdebug=1' % (redirect or '/web', redirect and '?' in redirect and '&' or '?') + + + + + \ No newline at end of file diff --git a/export_stockinfo_xls/__init__.py b/export_stockinfo_xls/__init__.py new file mode 100644 index 000000000..5d1caed4a --- /dev/null +++ b/export_stockinfo_xls/__init__.py @@ -0,0 +1,2 @@ +import report +import models diff --git a/export_stockinfo_xls/__manifest__.py b/export_stockinfo_xls/__manifest__.py new file mode 100644 index 000000000..1fba75bc4 --- /dev/null +++ b/export_stockinfo_xls/__manifest__.py @@ -0,0 +1,22 @@ +{ + 'name': 'Export Product Stock in Excel', + 'version': '0.2', + 'category': 'Warehouse', + 'license': "AGPL-3", + 'summary': "Current Stock Report for all Products in each Warehouse", + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'website': 'http://www.cybrosys.com', + 'depends': [ + 'base', + 'stock', + 'sale', + 'purchase', + 'report_xlsx' + ], + 'data': [ + 'views/wizard_view.xml', + ], + 'installable': True, + 'auto_install': False, +} diff --git a/export_stockinfo_xls/__manifest__.py~ b/export_stockinfo_xls/__manifest__.py~ new file mode 100644 index 000000000..e8e80d3df --- /dev/null +++ b/export_stockinfo_xls/__manifest__.py~ @@ -0,0 +1,22 @@ +{ + 'name': 'Export Product Stock in Excel', + 'version': '0.2', + 'category': 'Inventory', + 'license': "AGPL-3", + 'summary': "Current Stock Report for all Products in each Warehouse", + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'website': 'http://www.cybrosys.com', + 'depends': [ + 'base', + 'stock', + 'sale', + 'purchase', + 'report_xlsx' + ], + 'data': [ + 'views/wizard_view.xml', + ], + 'installable': True, + 'auto_install': False, +} diff --git a/export_stockinfo_xls/models/__init__.py b/export_stockinfo_xls/models/__init__.py new file mode 100644 index 000000000..857a1d9b8 --- /dev/null +++ b/export_stockinfo_xls/models/__init__.py @@ -0,0 +1,2 @@ +import res_partner +import wizard diff --git a/export_stockinfo_xls/models/res_partner.py b/export_stockinfo_xls/models/res_partner.py new file mode 100644 index 000000000..139ed20b5 --- /dev/null +++ b/export_stockinfo_xls/models/res_partner.py @@ -0,0 +1,24 @@ +from openerp import models, fields + + +class Partner(models.Model): + _inherit = 'res.partner' + + supplier_id = fields.Many2many('wizard.stock.history', 'supp_wiz_rel', 'wiz', 'supp', invisible=True) + + +class Category(models.Model): + _inherit = 'product.category' + + obj = fields.Many2many('wizard.stock.history', 'categ_wiz_rel', 'wiz', 'categ', invisible=True) + + +class Warehouse(models.Model): + _inherit = 'stock.warehouse' + + obj = fields.Many2many('wizard.stock.history', 'wh_wiz_rel', 'wiz', 'wh', invisible=True) + + + + + diff --git a/export_stockinfo_xls/models/wizard.py b/export_stockinfo_xls/models/wizard.py new file mode 100644 index 000000000..a532994c6 --- /dev/null +++ b/export_stockinfo_xls/models/wizard.py @@ -0,0 +1,25 @@ +from openerp import models, fields, api + + +class StockReport(models.TransientModel): + _name = "wizard.stock.history" + _description = "Current Stock History" + + warehouse = fields.Many2many('stock.warehouse', 'wh_wiz_rel', 'wh', 'wiz', string='Warehouse', required=True) + category = fields.Many2many('product.category', 'categ_wiz_rel', 'categ', 'wiz', string='Warehouse') + + @api.multi + def export_xls(self): + context = self._context + datas = {'ids': context.get('active_ids', [])} + datas['model'] = 'product.product' + datas['form'] = self.read()[0] + for field in datas['form'].keys(): + if isinstance(datas['form'][field], tuple): + datas['form'][field] = datas['form'][field][0] + if context.get('xls_export'): + return {'type': 'ir.actions.report.xml', + 'report_name': 'export_stockinfo_xls.stock_report_xls.xlsx', + 'datas': datas, + 'name': 'Current Stock' + } diff --git a/export_stockinfo_xls/report/__init__.py b/export_stockinfo_xls/report/__init__.py new file mode 100644 index 000000000..a017abea4 --- /dev/null +++ b/export_stockinfo_xls/report/__init__.py @@ -0,0 +1,2 @@ +import current_stock_xls + diff --git a/export_stockinfo_xls/report/current_stock_xls.py b/export_stockinfo_xls/report/current_stock_xls.py new file mode 100644 index 000000000..39ea82b99 --- /dev/null +++ b/export_stockinfo_xls/report/current_stock_xls.py @@ -0,0 +1,161 @@ +from odoo.addons.report_xlsx.report.report_xlsx import ReportXlsx +import datetime + + +class StockReportXls(ReportXlsx): + + def get_warehouse(self, data): + if data.get('form', False) and data['form'].get('warehouse', False): + l1 = [] + l2 = [] + obj = self.env['stock.warehouse'].search([('id', 'in', data['form']['warehouse'])]) + for j in obj: + l1.append(j.name) + l2.append(j.id) + return l1, l2 + + def get_category(self, data): + if data.get('form', False) and data['form'].get('category', False): + l2 = [] + obj = self.env['product.category'].search([('id', 'in', data['form']['category'])]) + for j in obj: + l2.append(j.id) + return l2 + return '' + + def get_lines(self, data, warehouse): + lines = [] + categ = self.get_category(data) + if categ: + stock_history = self.env['product.product'].search([('categ_id', 'in', categ)]) + else: + stock_history = self.env['product.product'].search([]) + for obj in stock_history: + sale_value = 0 + purchase_value = 0 + product = self.env['product.product'].browse(obj.id) + sale_obj = self.env['sale.order.line'].search([('order_id.state', '=', 'done'), + ('product_id', '=', product.id), + ('order_id.warehouse_id', '=', warehouse)]) + for i in sale_obj: + sale_value = sale_value + i.product_uom_qty + purchase_obj = self.env['purchase.order.line'].search([('order_id.state', '=', 'done'), + ('product_id', '=', product.id), + ('order_id.picking_type_id', '=', warehouse)]) + for i in purchase_obj: + purchase_value = purchase_value + i.product_qty + available_qty = product.with_context({'warehouse': warehouse}).virtual_available + \ + product.with_context({'warehouse': warehouse}).outgoing_qty - \ + product.with_context({'warehouse': warehouse}).incoming_qty + value = available_qty * product.standard_price + vals = { + 'sku': product.default_code, + 'name': product.name, + 'category': product.categ_id.name, + 'cost_price': product.standard_price, + 'available': available_qty, + 'virtual': product.with_context({'warehouse': warehouse}).virtual_available, + 'incoming': product.with_context({'warehouse': warehouse}).incoming_qty, + 'outgoing': product.with_context({'warehouse': warehouse}).outgoing_qty, + 'net_on_hand': product.with_context({'warehouse': warehouse}).qty_available, + 'total_value': value, + 'sale_value': sale_value, + 'purchase_value': purchase_value, + } + lines.append(vals) + return lines + + def generate_xlsx_report(self, workbook, data, lines): + get_warehouse = self.get_warehouse(data) + count = len(get_warehouse[0]) * 11 + 6 + sheet = workbook.add_worksheet() + format1 = workbook.add_format({'font_size': 14, 'bottom': True, 'right': True, 'left': True, 'top': True, 'align': 'vcenter', 'bold': True}) + format11 = workbook.add_format({'font_size': 12, 'align': 'center', 'right': True, 'left': True, 'bottom': True, 'top': True, 'bold': True}) + format21 = workbook.add_format({'font_size': 10, 'align': 'center', 'right': True, 'left': True,'bottom': True, 'top': True, 'bold': True}) + format3 = workbook.add_format({'bottom': True, 'top': True, 'font_size': 12}) + font_size_8 = workbook.add_format({'bottom': True, 'top': True, 'right': True, 'left': True, 'font_size': 8}) + red_mark = workbook.add_format({'bottom': True, 'top': True, 'right': True, 'left': True, 'font_size': 8, + 'bg_color': 'red'}) + justify = workbook.add_format({'bottom': True, 'top': True, 'right': True, 'left': True, 'font_size': 12}) + format3.set_align('center') + font_size_8.set_align('center') + justify.set_align('justify') + format1.set_align('center') + red_mark.set_align('center') + sheet.merge_range('A3:G3', 'Report Date: ' + str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M %p")), format1) + sheet.merge_range(2, 7, 2, count, 'Warehouses', format1) + sheet.merge_range('A4:G4', 'Product Information', format11) + w_col_no = 6 + w_col_no1 = 7 + for i in get_warehouse[0]: + w_col_no = w_col_no + 11 + sheet.merge_range(3, w_col_no1, 3, w_col_no, i, format11) + w_col_no1 = w_col_no1 + 11 + sheet.write(4, 0, 'SKU', format21) + sheet.merge_range(4, 1, 4, 3, 'Name', format21) + sheet.merge_range(4, 4, 4, 5, 'Category', format21) + sheet.write(4, 6, 'Cost Price', format21) + p_col_no1 = 7 + for i in get_warehouse[0]: + sheet.write(4, p_col_no1, 'Available', format21) + sheet.write(4, p_col_no1 + 1, 'Virtual', format21) + sheet.write(4, p_col_no1 + 2, 'Incoming', format21) + sheet.write(4, p_col_no1 + 3, 'Outgoing', format21) + sheet.merge_range(4, p_col_no1 + 4, 4, p_col_no1 + 5, 'Net On Hand', format21) + sheet.merge_range(4, p_col_no1 + 6, 4, p_col_no1 + 7, 'Total Sold', format21) + sheet.merge_range(4, p_col_no1 + 8, 4, p_col_no1 + 9, 'Total Purchased', format21) + sheet.write(4, p_col_no1 + 10, 'Valuation', format21) + p_col_no1 = p_col_no1 + 11 + prod_row = 5 + prod_col = 0 + for i in get_warehouse[1]: + get_line = self.get_lines(data, i) + for each in get_line: + sheet.write(prod_row, prod_col, each['sku'], font_size_8) + sheet.merge_range(prod_row, prod_col + 1, prod_row, prod_col + 3, each['name'], font_size_8) + sheet.merge_range(prod_row, prod_col + 4, prod_row, prod_col + 5, each['category'], font_size_8) + sheet.write(prod_row, prod_col + 6, each['cost_price'], font_size_8) + prod_row = prod_row + 1 + break + prod_row = 5 + prod_col = 7 + for i in get_warehouse[1]: + get_line = self.get_lines(data, i) + for each in get_line: + if each['available'] < 0: + sheet.write(prod_row, prod_col, each['available'], red_mark) + else: + sheet.write(prod_row, prod_col, each['available'], font_size_8) + if each['virtual'] < 0: + sheet.write(prod_row, prod_col + 1, each['virtual'], red_mark) + else: + sheet.write(prod_row, prod_col + 1, each['virtual'], font_size_8) + if each['incoming'] < 0: + sheet.write(prod_row, prod_col + 2, each['incoming'], red_mark) + else: + sheet.write(prod_row, prod_col + 2, each['incoming'], font_size_8) + if each['outgoing'] < 0: + sheet.write(prod_row, prod_col + 3, each['outgoing'], red_mark) + else: + sheet.write(prod_row, prod_col + 3, each['outgoing'], font_size_8) + if each['net_on_hand'] < 0: + sheet.merge_range(prod_row, prod_col + 4, prod_row, prod_col + 5, each['net_on_hand'], red_mark) + else: + sheet.merge_range(prod_row, prod_col + 4, prod_row, prod_col + 5, each['net_on_hand'], font_size_8) + if each['sale_value'] < 0: + sheet.merge_range(prod_row, prod_col + 6, prod_row, prod_col + 7, each['sale_value'], red_mark) + else: + sheet.merge_range(prod_row, prod_col + 6, prod_row, prod_col + 7, each['sale_value'], font_size_8) + if each['purchase_value'] < 0: + sheet.merge_range(prod_row, prod_col + 8, prod_row, prod_col + 9, each['purchase_value'], red_mark) + else: + sheet.merge_range(prod_row, prod_col + 8, prod_row, prod_col + 9, each['purchase_value'], font_size_8) + if each['total_value'] < 0: + sheet.write(prod_row, prod_col + 10, each['total_value'], red_mark) + else: + sheet.write(prod_row, prod_col + 10, each['total_value'], font_size_8) + prod_row = prod_row + 1 + prod_row = 5 + prod_col = prod_col + 11 + +StockReportXls('report.export_stockinfo_xls.stock_report_xls.xlsx', 'product.product') diff --git a/export_stockinfo_xls/static/description/icon.png b/export_stockinfo_xls/static/description/icon.png new file mode 100644 index 000000000..a14eba82a Binary files /dev/null and b/export_stockinfo_xls/static/description/icon.png differ diff --git a/export_stockinfo_xls/static/description/image1.png b/export_stockinfo_xls/static/description/image1.png new file mode 100644 index 000000000..21561b631 Binary files /dev/null and b/export_stockinfo_xls/static/description/image1.png differ diff --git a/export_stockinfo_xls/static/description/image2.png b/export_stockinfo_xls/static/description/image2.png new file mode 100644 index 000000000..33ad12b3d Binary files /dev/null and b/export_stockinfo_xls/static/description/image2.png differ diff --git a/export_stockinfo_xls/static/description/image3.png b/export_stockinfo_xls/static/description/image3.png new file mode 100644 index 000000000..2e69296e0 Binary files /dev/null and b/export_stockinfo_xls/static/description/image3.png differ diff --git a/export_stockinfo_xls/static/description/index.html b/export_stockinfo_xls/static/description/index.html new file mode 100644 index 000000000..1b07f9d91 --- /dev/null +++ b/export_stockinfo_xls/static/description/index.html @@ -0,0 +1,77 @@ +
+
+

Current Stock XLS

+

Current Stock Report for all Products in each Warehouse

+

Author : Cybrosys Techno Solutions , www.cybrosys.com

+
+
+
+ This module helps to print Current Stock Report for all Products in each Warehouse with XLS. +
+
+
+
+ ☛ Installation : To install this module, you need also the report_xlsx module. +
+
+
+
+
+ +
+
+
+

+ Go to Inventory -> Reports -> Current stock in Excel. Now a wizard will appear on your screen. + Please enter the warehouses which you want to take the report. You can also select category for products(It is Optional). + Then Click "Export Product with Stock Info" button. Then You will get the corresponding report in XLS. +

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

+ Per warehouse you can get Available Qty, Virtual Qty, Incoming Qty, Outgoing Qty, Net On Hand Qty, + Total Sold & Total Purchased Qty. You can get your stock valuation details too. In below screen-shot you + can see stock details of 2 warehouse exported in single spreadsheet. Negative stock will be highlighted + in "red" cells. +

+
+
+
+ +
+
+
+
+ +
+

Need Any Help?

+ +
+ + + diff --git a/export_stockinfo_xls/views/wizard_view.xml b/export_stockinfo_xls/views/wizard_view.xml new file mode 100644 index 000000000..1f71bb463 --- /dev/null +++ b/export_stockinfo_xls/views/wizard_view.xml @@ -0,0 +1,50 @@ + + + + + wizard.stock.history.form + wizard.stock.history + +
+ + + + + + + + + + + + +
+
+
+
+
+ + Export product stock in Excel + wizard.stock.history + form + form + + new + + + +
+
\ No newline at end of file diff --git a/payment_receipt_invoice/README.rst b/payment_receipt_invoice/README.rst new file mode 100644 index 000000000..f85ab60e3 --- /dev/null +++ b/payment_receipt_invoice/README.rst @@ -0,0 +1,12 @@ +Account Payment Receipt v10 +=========================== + +This module will print payment receipts with paid details + + +Credits +======= +Cybrosys Techno Solutions +Author +------ +* Cybrosys Techno Solutions diff --git a/payment_receipt_invoice/__init__.py b/payment_receipt_invoice/__init__.py new file mode 100644 index 000000000..be6313a49 --- /dev/null +++ b/payment_receipt_invoice/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# Author: Niyas Raphy() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 models diff --git a/payment_receipt_invoice/__manifest__.py b/payment_receipt_invoice/__manifest__.py new file mode 100644 index 000000000..d949cdca6 --- /dev/null +++ b/payment_receipt_invoice/__manifest__.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# Author: Niyas Raphy() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 . +# +############################################################################## +{ + 'name': 'Account Payment Receipt', + 'summary': """Payment Receipt With Paid Details""", + 'version': '0.3', + 'description': """""", + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'website': 'http://www.cybrosys.com', + 'category': 'Accounting', + 'depends': ['base', 'account'], + 'license': 'AGPL-3', + 'data': [ + 'views/receipt_print_template.xml', + 'views/account_payment_print.xml', + ], + 'demo': [], + 'images': ['static/description/banner.jpg'], + 'installable': True, + 'auto_install': False, + +} diff --git a/payment_receipt_invoice/models/__init__.py b/payment_receipt_invoice/models/__init__.py new file mode 100644 index 000000000..33720fea2 --- /dev/null +++ b/payment_receipt_invoice/models/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# Author: Niyas Raphy() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 account_receipt_parser diff --git a/payment_receipt_invoice/models/account_receipt_parser.py b/payment_receipt_invoice/models/account_receipt_parser.py new file mode 100644 index 000000000..f5f17ea3a --- /dev/null +++ b/payment_receipt_invoice/models/account_receipt_parser.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# Author: Niyas Raphy() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 json +from odoo.report import report_sxw +from odoo.osv import osv +from odoo import api +from odoo.http import request + + +class AccountReceiptParser(report_sxw.rml_parse): + + def __init__(self, cr, uid, name, context=None): + super(AccountReceiptParser, self).__init__(cr, uid, name, context=context) + self.localcontext.update({ + 'get_details': self.get_details, + 'get_details_invoice': self.get_details_invoice, + }) + self.context = context + + @api.multi + def get_details_invoice(self, doc): + lines = [] + if doc.number: + acc_inv = request.env['account.invoice'] + acc_inv_rec = acc_inv.search([('number', '=', doc.number)]) + total_amount = acc_inv_rec.amount_total + if acc_inv_rec.state == 'draft': + balance_amount = total_amount + else: + balance_amount = acc_inv_rec.residual + paid = total_amount - balance_amount + vals = { + 'total_amount': total_amount, + 'balance_amount': balance_amount, + 'paid': paid, + } + lines.append(vals) + else: + vals = { + 'total_amount': doc.amount_total, + 'balance_amount': doc.amount_total, + 'paid': 0, + } + lines.append(vals) + return lines + + @api.multi + def get_details(self, doc): + lines = [] + if doc.number: + acc_inv = request.env['account.invoice'] + acc_inv_rec = acc_inv.search([('number', '=', doc.number)]) + d = json.loads(acc_inv_rec.payments_widget) + for payment in d['content']: + vals = { + 'memo': payment['name'], + 'amount': payment['amount'], + 'method': payment['journal_name'], + 'date': payment['date'], + } + lines.append(vals) + return lines + + +class PrintReport(osv.AbstractModel): + _name = 'report.payment_receipt_invoice.report_payment' + _inherit = 'report.abstract_report' + _template = 'payment_receipt_invoice.report_payment' + _wrapped_report_class = AccountReceiptParser + + diff --git a/payment_receipt_invoice/static/description/banner.jpg b/payment_receipt_invoice/static/description/banner.jpg new file mode 100644 index 000000000..7b577dc0a Binary files /dev/null and b/payment_receipt_invoice/static/description/banner.jpg differ diff --git a/payment_receipt_invoice/static/description/customer_invoice_form_view.png b/payment_receipt_invoice/static/description/customer_invoice_form_view.png new file mode 100644 index 000000000..0af91bed4 Binary files /dev/null and b/payment_receipt_invoice/static/description/customer_invoice_form_view.png differ diff --git a/payment_receipt_invoice/static/description/customer_receipt.png b/payment_receipt_invoice/static/description/customer_receipt.png new file mode 100644 index 000000000..7f0a34cb7 Binary files /dev/null and b/payment_receipt_invoice/static/description/customer_receipt.png differ diff --git a/payment_receipt_invoice/static/description/cybro_logo.png b/payment_receipt_invoice/static/description/cybro_logo.png new file mode 100644 index 000000000..bb309114c Binary files /dev/null and b/payment_receipt_invoice/static/description/cybro_logo.png differ diff --git a/payment_receipt_invoice/static/description/icon.png b/payment_receipt_invoice/static/description/icon.png new file mode 100644 index 000000000..b646dbde0 Binary files /dev/null and b/payment_receipt_invoice/static/description/icon.png differ diff --git a/payment_receipt_invoice/static/description/index.html b/payment_receipt_invoice/static/description/index.html new file mode 100644 index 000000000..a072a26d5 --- /dev/null +++ b/payment_receipt_invoice/static/description/index.html @@ -0,0 +1,103 @@ +
+
+

Payment Receipt Report

+

Customer Receipts & Vendor Payment Report

+

Cybrosys Techno Solutions, www.cybrosys.com

+
+
+
+
+
+ ☀ Generate Customer invoice receipt with payment details.
+ ☀ Generate Vendor receipt with payment details.
+
+
+
+

Customer Invoice

+

Customer Invoice Form View

+
+

+
+

+
+ +
+
+
+
+

Customer Receipt Print

+
+

+
+

+
+ +
+
+
+
+

Customer Receipt Report

+
+

+
+

+
+ +
+
+
+
+
+
+

Vendor Bill

+

Vendor Bill Form View

+
+

+
+

+
+ +
+
+
+
+

Vendor Receipt Print

+
+

+
+

+
+ +
+
+
+
+

Vendor Receipt Report

+
+

+
+

+
+ +
+
+
+
+ +
+

Need Any Help?

+ + +
+ + diff --git a/payment_receipt_invoice/static/description/receipt_print_customer.png b/payment_receipt_invoice/static/description/receipt_print_customer.png new file mode 100644 index 000000000..68ac64059 Binary files /dev/null and b/payment_receipt_invoice/static/description/receipt_print_customer.png differ diff --git a/payment_receipt_invoice/static/description/vendor_invoice_form.png b/payment_receipt_invoice/static/description/vendor_invoice_form.png new file mode 100644 index 000000000..b61e73b09 Binary files /dev/null and b/payment_receipt_invoice/static/description/vendor_invoice_form.png differ diff --git a/payment_receipt_invoice/static/description/vendor_print_button.png b/payment_receipt_invoice/static/description/vendor_print_button.png new file mode 100644 index 000000000..15e38d4e7 Binary files /dev/null and b/payment_receipt_invoice/static/description/vendor_print_button.png differ diff --git a/payment_receipt_invoice/static/description/vendor_receipt.png b/payment_receipt_invoice/static/description/vendor_receipt.png new file mode 100644 index 000000000..8d0603df2 Binary files /dev/null and b/payment_receipt_invoice/static/description/vendor_receipt.png differ diff --git a/payment_receipt_invoice/views/account_payment_print.xml b/payment_receipt_invoice/views/account_payment_print.xml new file mode 100644 index 000000000..4b719f9f8 --- /dev/null +++ b/payment_receipt_invoice/views/account_payment_print.xml @@ -0,0 +1,22 @@ + + + + + + + + + diff --git a/payment_receipt_invoice/views/receipt_print_template.xml b/payment_receipt_invoice/views/receipt_print_template.xml new file mode 100644 index 000000000..3be8f4271 --- /dev/null +++ b/payment_receipt_invoice/views/receipt_print_template.xml @@ -0,0 +1,82 @@ + + + + diff --git a/pos_chatter/README.rst b/pos_chatter/README.rst new file mode 100644 index 000000000..af5038581 --- /dev/null +++ b/pos_chatter/README.rst @@ -0,0 +1,29 @@ +=============== +POS Chatter v10 +=============== + +This module adds chat interface in Point of sale screen. + +Installation +============ + +Just select it from available modules to install it, there is no need to extra installations. + +Configuration +============= + +Nothing to configure. + +Usage +===== + +* Chat Button on POS screen. +* On clicking chat button,display chatlist on the screen. +* On clicking an item in chatlist, chat window open in pos screen. + +Credits +======= +Developer: Aswani pc @ cybrosys +Guidance: Nilmar Shereef @ cybrosys, shereef@cybrosys.in + + diff --git a/pos_chatter/__init__.py b/pos_chatter/__init__.py new file mode 100644 index 000000000..06839078f --- /dev/null +++ b/pos_chatter/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# Author: Nilmar Shereef() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 . +# +############################################################################## + diff --git a/pos_chatter/__manifest__.py b/pos_chatter/__manifest__.py new file mode 100644 index 000000000..c2f90861c --- /dev/null +++ b/pos_chatter/__manifest__.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# Author: Nilmar Shereef() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 . +# +############################################################################## +{ + 'name': "POS Chat Box", + 'summary': """Chat Box In POS Screen""", + 'description': "This module adds chat interface in Point of sale screen.", + 'author': "Cybrosys Techno Solutions", + 'company': "Cybrosys Techno Solutions", + 'website': "http://www.cybrosys.com", + 'category': 'Point Of Sale', + 'version': '0.4', + 'depends': ['base', 'point_of_sale'], + 'data': ['views/pos_chat.xml'], + 'qweb': ['static/src/xml/pos_msg.xml'], + 'images': ['static/description/banner.jpg'], + 'license': 'AGPL-3', + 'installable': True, + 'auto_install': False, +} diff --git a/pos_chatter/__manifest__.py~ b/pos_chatter/__manifest__.py~ new file mode 100644 index 000000000..fc0005426 --- /dev/null +++ b/pos_chatter/__manifest__.py~ @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# Author: Nilmar Shereef() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 . +# +############################################################################## +{ + 'name': "POS Chat Box", + 'summary': """Chat in POS""", + 'description': "This module adds chat interface in Point of sale screen.", + 'author': "Cybrosys Techno Solutions", + 'company': "Cybrosys Techno Solutions", + 'website': "http://www.cybrosys.com", + 'category': 'Point Of Sale', + 'version': '0.4', + 'depends': ['base', 'point_of_sale'], + 'data': ['views/pos_chat.xml'], + 'qweb': ['static/src/xml/pos_msg.xml'], + 'images': ['static/description/banner.jpg'], + 'license': 'AGPL-3', + 'installable': True, + 'auto_install': False, +} diff --git a/pos_chatter/static/description/banner.jpg b/pos_chatter/static/description/banner.jpg new file mode 100644 index 000000000..78370eb22 Binary files /dev/null and b/pos_chatter/static/description/banner.jpg differ diff --git a/pos_chatter/static/description/cybro_logo.png b/pos_chatter/static/description/cybro_logo.png new file mode 100644 index 000000000..bb309114c Binary files /dev/null and b/pos_chatter/static/description/cybro_logo.png differ diff --git a/pos_chatter/static/description/icon.png b/pos_chatter/static/description/icon.png new file mode 100644 index 000000000..070786c96 Binary files /dev/null and b/pos_chatter/static/description/icon.png differ diff --git a/pos_chatter/static/description/index.html b/pos_chatter/static/description/index.html new file mode 100644 index 000000000..4f6289fcf --- /dev/null +++ b/pos_chatter/static/description/index.html @@ -0,0 +1,48 @@ +
+
+

POS Chat

+

Easily communicate each other without going outside of POS Screen.

+

Cybrosys Technologies , www.cybrosys.com

+
+

Features:

+
    +
  • We can easily communicate each other in POS.
  • +
  • Nothing to configure.
  • +
+
+
+
+ +
+
+

Chat Button on POS screen

+
+ +
+
+
+ +
+
+

On clicking an item in chatlist, chat window open in pos screen

+
+ +
+
+
+ +
+

Need Any Help?

+ + +
\ No newline at end of file diff --git a/pos_chatter/static/description/pos_chat_001.png b/pos_chatter/static/description/pos_chat_001.png new file mode 100644 index 000000000..44ee6c864 Binary files /dev/null and b/pos_chatter/static/description/pos_chat_001.png differ diff --git a/pos_chatter/static/description/pos_chat_002.png b/pos_chatter/static/description/pos_chat_002.png new file mode 100644 index 000000000..bf43c9878 Binary files /dev/null and b/pos_chatter/static/description/pos_chat_002.png differ diff --git a/pos_chatter/static/src/css/message.css b/pos_chatter/static/src/css/message.css new file mode 100644 index 000000000..8867a61b2 --- /dev/null +++ b/pos_chatter/static/src/css/message.css @@ -0,0 +1,86 @@ +.pos .message-box{ + position: absolute; + right: -350px; + top: 50px; + width: 100%; + height:100%; + background-color: rgba(0,0,0,0); + z-index:1000; +} +.pos .message-box .message{ + position:relative; + top:0;left: 0; right: 0; bottom:0; + margin: auto; + width:350px; + font-size:22px; + background-color: #F0EEEE; + box-shadow: 0px 10px 20px rgba(0,0,0,0.4); + z-index:1200; + font-family: 'Lato'; + font-family: Lato; +} +.pos .message .title { + background: #FFFFFF; + margin: 0; + padding: 4px; + border-bottom: solid 1px rgba(60,60,60,0.1); +} +.pos .pos-new_message{ + margin-left :90px; + color: #7f82ac; + } + +.pos .message a { + text-decoration: none; + font-size: 11px; + cursor: pointer; + padding: 4px 10px; + +} +.pos .message a:hover { + color: #7f82ac; +} + +.pos .pos-selected { + font-weight: bold; + color : #7f82ac; + } + +.pos .fa-close { + margin-right: 10px; + cursor: pointer; + } + + +.ui-widget{ + font-family: "Lucida Grande", Helvetica, Verdana, Arial, sans-serif; + background:#FFFFFF; + font-size: 13px; + width:200px; + z-index: 10000; + +} +.ui-menu{ + padding: 2px 0; + margin-top: 4px; + } +.ui-menu-item{ + display: block; + background:#FFFFFF; + color: #000000; : +} + +.ui-menu-item:hover{ + display: block; + background:#7f82ac; + color:#FFFFFF; +} +.ui-menu .ui-menu-item a{ + height:10px; + padding: 1px 16px; +} + +.hide { + display: none !important; +} + diff --git a/pos_chatter/static/src/js/pos_chat.js b/pos_chatter/static/src/js/pos_chat.js new file mode 100644 index 000000000..b9daf7c68 --- /dev/null +++ b/pos_chatter/static/src/js/pos_chat.js @@ -0,0 +1,183 @@ +odoo.define('point_of_sale.pos_chatter', function (require) { +"use strict"; +var chrome = require('point_of_sale.chrome'); +var core = require('web.core'); +var chat_manager = require('mail.chat_manager'); +var window_manager = require('mail.window_manager'); +var ajax = require('web.ajax'); +var gui = require('point_of_sale.gui'); +var popup = require('point_of_sale.popups'); +var PosBaseWidget = require('point_of_sale.BaseWidget'); +var QWeb = core.qweb; +var _t = core._t; + +chrome.Chrome.include({ + events: { + "click .pos-message": "on_click_pos_message", + }, + renderElement: function(){ + var self = this; + this.filter = false; + chat_manager.bus.on("update_channel_unread_counter", this, this.update_counter); + chat_manager.is_ready.then(this.update_counter.bind(this)); + return this._super(); + }, + + is_open: function () { + return this.$el.hasClass('open'); + }, + + update_counter: function () { + var counter = chat_manager.get_unread_conversation_counter(); + this.$('.o_notification_counter').text(counter); + this.$el.toggleClass('o_no_notification', !counter); + this.$el.toggleClass('o_unread_chat', !!chat_manager.get_chat_unread_counter()); + if (this.is_open()) { + this.update_channels_preview(); + } + }, + + update_channels_preview: function () { + var self = this; + chat_manager.is_ready.then(function () { + var channels = _.filter(chat_manager.get_channels(), function (channel) { + if (self.filter === 'chat') { + return channel.is_chat; + } else if (self.filter === 'channels') { + return !channel.is_chat && channel.type !== 'static'; + } else { + return channel.type !== 'static'; + } + }); + chat_manager.get_channels_preview(channels).then(self._render_channels_preview.bind(self)); + }); + }, + + _render_channels_preview: function (channels_preview) { + channels_preview.sort(function (c1, c2) { + return Math.min(1, c2.unread_counter) - Math.min(1, c1.unread_counter) || + c2.is_chat - c1.is_chat || + c2.last_message.date.diff(c1.last_message.date); + }); + + _.each(channels_preview, function (channel) { + channel.last_message_preview = chat_manager.get_message_body_preview(channel.last_message.body); + if (channel.last_message.date.isSame(new Date(), 'd')) { // today + channel.last_message_date = channel.last_message.date.format('LT'); + } else { + channel.last_message_date = channel.last_message.date.format('lll'); + } + }); + this.gui.show_popup('message',{list:channels_preview}); + }, + + on_click_pos_message: function () { + var self = this; + if (this.gui.current_popup) { + this.gui.close_popup(); + } + else{ + this.update_channels_preview(); + } + }, + + on_click_new_message: function () { + chat_manager.bus.trigger('open_chat'); + }, + +}); + + +var MessageWidget = PosBaseWidget.extend({ + template:'MessageWidget', + events: { + "click .o_mail_channel_preview": "on_click_message_item", + "click .pos-new_message": "on_click_new_message", + "click .pos-filter": "on_click_filter", + }, + renderElement: function(){ + var self = this; + return this._super(); + }, + show: function(options){ + options = options || {}; + var self = this; + this._super(options); + this.list = options.list || []; + this.renderElement(); + + }, + on_click_new_message: function () { + this.gui.close_popup(); + chat_manager.bus.trigger('open_chat'); + }, + + on_click_filter: function (event) { + event.stopPropagation(); + this.$(".pos-filter").removeClass('pos-selected'); + var $target = $(event.currentTarget); + $target.addClass('pos-selected'); + this.filter = $target.data('filter'); + this.update_channels_preview(); + }, + + update_channels_preview: function () { + var self = this; + this.$('.o_mail_navbar_dropdown_channels').html(QWeb.render('Spinner')); + chat_manager.is_ready.then(function () { + var channels = _.filter(chat_manager.get_channels(), function (channel) { + if (self.filter === 'chat') { + return channel.is_chat; + } else if (self.filter === 'channels') { + return !channel.is_chat && channel.type !== 'static'; + } else { + return channel.type !== 'static'; + } + }); + chat_manager.get_channels_preview(channels).then(self._render_channels_preview.bind(self)); + }); + }, + + _render_channels_preview: function (channels_preview) { + + channels_preview.sort(function (c1, c2) { + return Math.min(1, c2.unread_counter) - Math.min(1, c1.unread_counter) || + c2.is_chat - c1.is_chat || + c2.last_message.date.diff(c1.last_message.date); + }); + + _.each(channels_preview, function (channel) { + channel.last_message_preview = chat_manager.get_message_body_preview(channel.last_message.body); + if (channel.last_message.date.isSame(new Date(), 'd')) { // today + channel.last_message_date = channel.last_message.date.format('LT'); + } else { + channel.last_message_date = channel.last_message.date.format('lll'); + } + }); + this.$('.o_mail_navbar_dropdown_channels').html(QWeb.render('mail.chat.ChannelsPreview', { + channels: channels_preview, + })); +}, + + close: function(){ + if (this.$el) { + this.$el.addClass('oe_hidden'); + } + }, + + on_click_message_item: function(event){ + event.stopPropagation(); + var $target = $(event.currentTarget); + var channel_id = $target.data('channel_id'); + var channel = chat_manager.get_channel(channel_id); + if (channel) { + this.gui.close_popup(); + chat_manager.open_channel(channel); + } + }, +}); + +gui.define_popup({name:'message', widget: MessageWidget}); + + +}); diff --git a/pos_chatter/static/src/less/message.less b/pos_chatter/static/src/less/message.less new file mode 100644 index 000000000..2a8b0a9b2 --- /dev/null +++ b/pos_chatter/static/src/less/message.less @@ -0,0 +1,120 @@ +@gray: #52575C; +@gray-light: lighten(#000, 46.7%); // #777 +@gray-lighter: lighten(#000, 93.5%); // #eee +@screen-xs-max: 767px; +@screen-sm: 768px; +@screen-sm-min: @screen-sm; +@text-color: #C8C8C8; + +@navbar-default-link-color: @text-color; +@navbar-default-link-hover-color: #fff; +@navbar-default-link-hover-bg: transparent; +@navbar-default-link-active-color: #fff; +@navbar-default-link-active-bg: transparent; +@navbar-default-link-disabled-color: @gray-light; +@navbar-default-link-disabled-bg: transparent; + +@navbar-height: 44px; +.text-muted { + color: @gray-light; +} +.box-sizing(@boxmodel) { + -webkit-box-sizing: @boxmodel; + -moz-box-sizing: @boxmodel; + box-sizing: @boxmodel; +} + +.o_chat_window { + &,* { + .box-sizing(border-box); + } + .o_chat_header { + height: 28px; + .fa-close { + text-decoration: none; + font-weight: bold; + + } + > span { + margin: auto 0; + } + } +} + +.btn-link { + color: @navbar-default-link-color; + &:hover, + &:focus { + color: @navbar-default-link-hover-color; + } + &[disabled], + fieldset[disabled] & { + &:hover, + &:focus { + color: @navbar-default-link-disabled-color; + } + } +} + + + +.o_mail_navbar_dropdown_channels { + .o-flex(0, 1, auto); + background: #FFFFFF; + max-height: 400px; + min-height: 50px; + overflow-y: auto; + + @media (max-width: @screen-xs-max) { + max-height: none; + } + + .o_mail_channel_preview { + .o-flex-display(); + height: 40px; + align-items: center; + padding: 5px; + cursor: pointer; + font-size: 12px; + overflow: hidden; + &~.o_mail_channel_preview { + border-top: 1px solid lightgray; + } + &.o_channel_unread { + background-color: lighten(lightgray, 10%); + } + &:hover { + background-color: lighten(lightgray, 5%); + } + + .o_channel_image { + .o-flex(0, 0, 36px); + max-height: 36px; + } + .o_channel_info { + .o-flex(1, 1, 100%); + margin-left: 5px; + overflow: hidden; + + .o_channel_title { + .o-flex-display(); + .o_channel_name { + .o-flex(1, 1, auto); + .o-text-overflow(); + } + .o_last_message_date { + .o-flex(0, 0, auto); + padding-top: 3px; + font-size: xx-small; + color: @odoo-main-color-muted; + } + } + .o_last_message_preview { + width: 100%; + color: @odoo-main-color-muted; + .o-text-overflow(); + } + } + } +} + diff --git a/pos_chatter/static/src/xml/pos_msg.xml b/pos_chatter/static/src/xml/pos_msg.xml new file mode 100644 index 000000000..a0cd0310b --- /dev/null +++ b/pos_chatter/static/src/xml/pos_msg.xml @@ -0,0 +1,58 @@ + + + + + + + diff --git a/pos_chatter/views/pos_chat.xml b/pos_chatter/views/pos_chat.xml new file mode 100644 index 000000000..96304387c --- /dev/null +++ b/pos_chatter/views/pos_chat.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/project_lifeline/README.rst b/project_lifeline/README.rst new file mode 100644 index 000000000..ee7b6c83a --- /dev/null +++ b/project_lifeline/README.rst @@ -0,0 +1,26 @@ +Lifeline for Task +================= + +This module aims to automatically update the color of the progressbar in task form. +LifeLine progressbar is calculated based on live time and given deadline time. + +Features +======== + +* User Defined Progress Bar Colour Configuration. +* Task Lifeline Bar based on Deadline. +* Automatic Colour Change of Lifeline Bar. +* Default Colour for Forbidden. + + + .. note:: + + A new menu is created under Project-configuration where + >set color for percentage range. + + It effects the task form view Life line progress bar + + +Credits +======= +Developer: Nilmar Shereef @ cybrosys, shereef@cybrosys.in diff --git a/project_lifeline/__init__.py b/project_lifeline/__init__.py new file mode 100644 index 000000000..b2462eb50 --- /dev/null +++ b/project_lifeline/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# Author: Nilmar Shereef() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 models diff --git a/project_lifeline/__manifest__.py b/project_lifeline/__manifest__.py new file mode 100644 index 000000000..703c1b753 --- /dev/null +++ b/project_lifeline/__manifest__.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# Author: Nilmar Shereef() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 . +# +############################################################################## +{ + 'name': "Lifeline for Task", + 'summary': """Lifeline Progressbar for Tasks (100% -> 0%)""", + 'description': """Calculates the time remaining based on live time & deadline.""", + 'author': 'Cybrosys Techno Solutions', + 'website': "http://www.cybrosys.com", + 'company': 'Cybrosys Techno Solutions', + 'category': 'Project', + 'version': '10.0.1.0.0', + 'depends': ['base', 'project'], + 'data': [ + 'views/task_lifeline_view.xml', + 'views/progress_bar_view.xml', + 'views/progress_bar_settings.xml', + ], + 'images': ['static/description/banner.jpg'], + 'installable': True, + 'auto_install': False, +} diff --git a/project_lifeline/__manifest__.py~ b/project_lifeline/__manifest__.py~ new file mode 100644 index 000000000..934d97a87 --- /dev/null +++ b/project_lifeline/__manifest__.py~ @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# Author: Nilmar Shereef() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 . +# +############################################################################## +{ + 'name': "Lifeline for Task", + 'summary': """Lifeline Progressbar for Tasks (100% -> 0%)""", + 'description': """Calculates the time remaining based on live time & deadline.""", + 'author': 'Cybrosys Techno Solutions', + 'website': "http://www.cybrosys.com", + 'company': 'Cybrosys Techno Solutions', + 'category': 'Project', + 'version': '0.2', + 'depends': ['base', 'project'], + 'data': [ + 'views/task_lifeline_view.xml', + 'views/progress_bar_view.xml', + 'views/progress_bar_settings.xml', + ], + 'images': ['static/description/banner.jpg'], + 'installable': True, + 'auto_install': False, +} diff --git a/project_lifeline/models/__init__.py b/project_lifeline/models/__init__.py new file mode 100644 index 000000000..c9c2a95fb --- /dev/null +++ b/project_lifeline/models/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# Author: Nilmar Shereef() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 task_lifeline +import progress_bar_color diff --git a/project_lifeline/models/progress_bar_color.py b/project_lifeline/models/progress_bar_color.py new file mode 100644 index 000000000..07491f6dc --- /dev/null +++ b/project_lifeline/models/progress_bar_color.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# Author: Nilmar Shereef() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 odoo import models, fields, api, exceptions, _ + + +class SelectColor(models.Model): + _name = "set.progressbar.color" + _rec_name = 'color' + + range_start = fields.Integer(string='Range From(%)', required=True, help="Starting range of Statusbar in Percentage") + range_stop = fields.Integer(string='Range To(%)', required=True, help="Stop range of Statusbar in Percentage") + color = fields.Selection([('red', 'Red'), ('green', 'Green'), ('yellow', 'Yellow'), + ('pink', 'Pink'), ('orange', 'Orange'), + ('light_green', 'Light Green'), ('grey', 'Grey'), + ('blue', 'Blue'), ('purple', 'Purple'), + ('black', 'Black'), ('brown', 'Brown')], + string='Color', required=True, default='red', + help="Choose a color for selected range") + + @api.multi + def assign_progress_bar_color(self): + values = self.env['set.progressbar.color'].search([]) + list_ret = [] + for value in values: + list_temp = [] + list_temp.append(value.range_start) + list_temp.append(value.range_stop) + list_temp.append(value.color) + list_ret.append(list_temp) + return list_ret + + @api.multi + @api.constrains('range_start', 'range_stop') + def check_range(self): + if self.range_start > self.range_stop: + raise exceptions.ValidationError("Start range should be less than stop range") diff --git a/project_lifeline/models/task_lifeline.py b/project_lifeline/models/task_lifeline.py new file mode 100644 index 000000000..6d1b57720 --- /dev/null +++ b/project_lifeline/models/task_lifeline.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# Author: Nilmar Shereef() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 odoo import fields, models +from dateutil.relativedelta import relativedelta + + +class TaskLifeline(models.Model): + _inherit = 'project.task' + + lifeline = fields.Float(string="Life line", default='100', copy=False, readonly=True) + date_deadline = fields.Datetime('Deadline', required=True) + + def process_lifeline_scheduler(self): + task_obj = self.env['project.task'] + task_ids = task_obj.search([]) + time_now = fields.Datetime.from_string(fields.Datetime.now()) + for task in task_ids: + start_date = fields.Datetime.from_string(task.date_assign) + end_date = fields.Datetime.from_string(task.date_deadline) + if task.stage_id and (task.stage_id.name == 'Done' or task.stage_id.name == 'Cancelled'): + task.lifeline = 0 + else: + if task.date_deadline and task.date_assign and end_date > start_date: + if time_now < end_date: + total_difference_days = relativedelta(end_date, start_date) + difference_minute = total_difference_days.hours * 60 + total_difference_days.minutes + date_difference = end_date - start_date + total_difference_minute = int(date_difference.days) * 24 * 60 + difference_minute + + remaining_days = relativedelta(time_now, start_date) + remaining_minute = remaining_days.hours * 60 + remaining_days.minutes + date_remaining = time_now - start_date + total_minute_remaining = int(date_remaining.days) * 24 * 60 + remaining_minute + if total_difference_minute != 0: + task.lifeline = (100 - ((total_minute_remaining * 100) / total_difference_minute)) + else: + task.lifeline = 0 + else: + task.lifeline = 0 diff --git a/project_lifeline/static/description/banner.jpg b/project_lifeline/static/description/banner.jpg new file mode 100644 index 000000000..ff24e05f6 Binary files /dev/null and b/project_lifeline/static/description/banner.jpg differ diff --git a/project_lifeline/static/description/cybro_logo.png b/project_lifeline/static/description/cybro_logo.png new file mode 100644 index 000000000..bb309114c Binary files /dev/null and b/project_lifeline/static/description/cybro_logo.png differ diff --git a/project_lifeline/static/description/disply.png b/project_lifeline/static/description/disply.png new file mode 100644 index 000000000..31bf85a73 Binary files /dev/null and b/project_lifeline/static/description/disply.png differ diff --git a/project_lifeline/static/description/form_view.png b/project_lifeline/static/description/form_view.png new file mode 100644 index 000000000..481d02865 Binary files /dev/null and b/project_lifeline/static/description/form_view.png differ diff --git a/project_lifeline/static/description/icon.png b/project_lifeline/static/description/icon.png new file mode 100644 index 000000000..31bf85a73 Binary files /dev/null and b/project_lifeline/static/description/icon.png differ diff --git a/project_lifeline/static/description/index.html b/project_lifeline/static/description/index.html new file mode 100644 index 000000000..3da16973a --- /dev/null +++ b/project_lifeline/static/description/index.html @@ -0,0 +1,131 @@ +
+
+

LifeLine ProgressBar for Task

+

LifeLine is calculated based on live time and deadline time.

+

Author : Cybrosys Techno Solutions , www.cybrosys.com

+
+
+
+ ☀ User Defined Progress Bar Colour Configuration.
+ ☀ Task Lifeline Bar based on Deadline.
+ ☀ Automatic Colour Change of Lifeline Bar.
+ ☀ Default Colour for Forbidden.
+
+
+
+ +
+
+
+ +
+ +
+
+

+ ☛ Default Form/Tree view of Task +

+
+
+

Form View

+ +
+
+
+
+

Tree View

+ +
+
+
+
+ +
+
+

+ ☛User Can Define the Color of Progressbar for Different Percentage Ranges. +

+
+
+

Form View

+ +
+
+
+
+

Tree View

+ +
+
+
+
+
+
+
+
+

+ ☛Color of progressbar based on different ranges +

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

+ ☛Color of progressbar based on different ranges +

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

+ ☛Color of progressbar based on different ranges +

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

Need Any Help?

+ + +
\ No newline at end of file diff --git a/project_lifeline/static/description/set_green.png b/project_lifeline/static/description/set_green.png new file mode 100644 index 000000000..73bf0b6b6 Binary files /dev/null and b/project_lifeline/static/description/set_green.png differ diff --git a/project_lifeline/static/description/set_range_form_view.png b/project_lifeline/static/description/set_range_form_view.png new file mode 100644 index 000000000..3d30e7d91 Binary files /dev/null and b/project_lifeline/static/description/set_range_form_view.png differ diff --git a/project_lifeline/static/description/set_range_green.png b/project_lifeline/static/description/set_range_green.png new file mode 100644 index 000000000..1e7276fda Binary files /dev/null and b/project_lifeline/static/description/set_range_green.png differ diff --git a/project_lifeline/static/description/set_range_red.png b/project_lifeline/static/description/set_range_red.png new file mode 100644 index 000000000..7bd43950c Binary files /dev/null and b/project_lifeline/static/description/set_range_red.png differ diff --git a/project_lifeline/static/description/set_range_tree_view.png b/project_lifeline/static/description/set_range_tree_view.png new file mode 100644 index 000000000..56584cdea Binary files /dev/null and b/project_lifeline/static/description/set_range_tree_view.png differ diff --git a/project_lifeline/static/description/set_range_yellow.png b/project_lifeline/static/description/set_range_yellow.png new file mode 100644 index 000000000..6eed37af2 Binary files /dev/null and b/project_lifeline/static/description/set_range_yellow.png differ diff --git a/project_lifeline/static/description/set_red.png b/project_lifeline/static/description/set_red.png new file mode 100644 index 000000000..44ec54333 Binary files /dev/null and b/project_lifeline/static/description/set_red.png differ diff --git a/project_lifeline/static/description/set_yellow.png b/project_lifeline/static/description/set_yellow.png new file mode 100644 index 000000000..a0c92b762 Binary files /dev/null and b/project_lifeline/static/description/set_yellow.png differ diff --git a/project_lifeline/static/description/tree_view.png b/project_lifeline/static/description/tree_view.png new file mode 100644 index 000000000..e129503eb Binary files /dev/null and b/project_lifeline/static/description/tree_view.png differ diff --git a/project_lifeline/static/src/css/progress_bar_color.css b/project_lifeline/static/src/css/progress_bar_color.css new file mode 100644 index 000000000..e84014fae --- /dev/null +++ b/project_lifeline/static/src/css/progress_bar_color.css @@ -0,0 +1,52 @@ +.o_progressbar .o_progress .o_progressbar_complete.o_progress_gt_fty { + background-color: #456325; + height: 100%; +} +.o_progressbar .o_progress .o_progressbar_complete.o_progress_lt_fty { + background-color: orange; + height: 100%; +} +.o_progressbar .o_progress .o_progressbar_complete.o_progress_red { + background-color: #FF0000; + height: 100%; +} +.o_progressbar .o_progress .o_progressbar_complete.o_progress_pink { + background-color: #FFC0CB; + height: 100%; +} +.o_progressbar .o_progress .o_progressbar_complete.o_progress_orange { + background-color: #FFA500; + height: 100%; +} +.o_progressbar .o_progress .o_progressbar_complete.o_progress_yellow { + background-color: #FFFF00; + height: 100%; +} +.o_progressbar .o_progress .o_progressbar_complete.o_progress_light_green { + background-color: #00FF00; + height: 100%; +} +.o_progressbar .o_progress .o_progressbar_complete.o_progress_green { + background-color: #008000; + height: 100%; +} +.o_progressbar .o_progress .o_progressbar_complete.o_progress_grey { + background-color:#A9A9A9; + height: 100%; +} +.o_progressbar .o_progress .o_progressbar_complete.o_progress_blue { + background-color:#0000FF; + height: 100%; +} +.o_progressbar .o_progress .o_progressbar_complete.o_progress_purple { + background-color:#800080; + height: 100%; +} +.o_progressbar .o_progress .o_progressbar_complete.o_progress_brown { + background-color:#835C3B; + height: 100%; +} +.o_progressbar .o_progress .o_progressbar_complete.o_progress_black { + background-color:#000000; + height: 100%; +} \ No newline at end of file diff --git a/project_lifeline/static/src/js/progress_bar_color.js b/project_lifeline/static/src/js/progress_bar_color.js new file mode 100644 index 000000000..155cad3c0 --- /dev/null +++ b/project_lifeline/static/src/js/progress_bar_color.js @@ -0,0 +1,83 @@ +odoo.define('progress_bar_color.ProgressBar', function (require) { +"use strict"; + +var core = require('web.core'); +var utils = require('web.utils'); +var Widget = require('web.Widget'); +var ProgressBar = require('web.ProgressBar') +var Model = require('web.DataModel'); + +var QWeb = core.qweb; +var _t = core._t; + + +ProgressBar.include({ + + _render_value: function(v) { + var self = this + var value = this.value; + var max_value = this.max_value; + if(!isNaN(v)) { + if(this.edit_max_value) { + max_value = v; + } else { + value = v; + } + } + value = value || 0; + max_value = max_value || 0; + + var widthComplete; + if(value <= max_value) { + widthComplete = value/max_value * 100; + } else { + widthComplete = max_value/value * 100; + } + var Users = new Model('set.progressbar.color'); + Users.call('assign_progress_bar_color', [[]]).then(function (result) { + if (result[0]){ + for (var ranges = 0; ranges < result.length; ranges++){ + self.$('.o_progress').toggleClass('o_progress_overflow', value > max_value); + if (widthComplete >= result[ranges][0] && widthComplete <= result[ranges][1]){ + console.log(widthComplete) + self.$('.o_progressbar_complete').toggleClass('o_progress_red', result[ranges][2] == 'red').css('width', widthComplete + '%'); + self.$('.o_progressbar_complete').toggleClass('o_progress_pink', result[ranges][2] == 'pink').css('width', widthComplete + '%'); + self.$('.o_progressbar_complete').toggleClass('o_progress_orange', result[ranges][2] == 'orange').css('width', widthComplete + '%'); + self.$('.o_progressbar_complete').toggleClass('o_progress_yellow', result[ranges][2] == 'yellow').css('width', widthComplete + '%'); + self.$('.o_progressbar_complete').toggleClass('o_progress_light_green', result[ranges][2] == 'light_green').css('width', widthComplete + '%'); + self.$('.o_progressbar_complete').toggleClass('o_progress_green', result[ranges][2] == 'green').css('width', widthComplete + '%'); + self.$('.o_progressbar_complete').toggleClass('o_progress_grey', result[ranges][2] == 'grey').css('width', widthComplete + '%'); + self.$('.o_progressbar_complete').toggleClass('o_progress_blue', result[ranges][2] == 'blue').css('width', widthComplete + '%'); + self.$('.o_progressbar_complete').toggleClass('o_progress_purple', result[ranges][2] == 'purple').css('width', widthComplete + '%'); + self.$('.o_progressbar_complete').toggleClass('o_progress_black', result[ranges][2] == 'black').css('width', widthComplete + '%'); + self.$('.o_progressbar_complete').toggleClass('o_progress_brown', result[ranges][2] == 'brown').css('width', widthComplete + '%'); + + break; + } + else if (ranges == (result.length - 1)){ + self.$('.o_progressbar_complete').toggleClass('o_progress_grey', widthComplete != 0).css('width', widthComplete + '%'); + } + + } + } + else{ + self.$('.o_progress').toggleClass('o_progress_overflow', value > max_value); + self.$('.o_progressbar_complete').toggleClass('o_progress_gt_fty', widthComplete > 50).css('width', widthComplete + '%'); + self.$('.o_progressbar_complete').toggleClass('o_progress_lt_fty', widthComplete <= 50).css('width', widthComplete + '%'); + } + }); + + if(this.readonly) { + if(max_value !== 100) { + this.$('.o_progressbar_value').html(utils.human_number(value) + " / " + utils.human_number(max_value)); + } else { + this.$('.o_progressbar_value').html(utils.human_number(value) + "%"); + } + } else if(isNaN(v)) { + this.$('.o_progressbar_value').val(this.edit_max_value ? max_value : value); + } + } +}); + + +}); diff --git a/project_lifeline/views/progress_bar_settings.xml b/project_lifeline/views/progress_bar_settings.xml new file mode 100644 index 000000000..d74702d31 --- /dev/null +++ b/project_lifeline/views/progress_bar_settings.xml @@ -0,0 +1,54 @@ + + + + + + set.progressbar.color.tree + set.progressbar.color + + + + + + + + + + + set.progressbar.color.form + set.progressbar.color + +
+ + + + + + + + + + + +
+
+
+ + + Set Range + set.progressbar.color + form + tree,form + +

+ Create a new range +

+ Create a new range and assign a color for progress bar +

+
+
+ + +
+
\ No newline at end of file diff --git a/project_lifeline/views/progress_bar_view.xml b/project_lifeline/views/progress_bar_view.xml new file mode 100644 index 000000000..3937901eb --- /dev/null +++ b/project_lifeline/views/progress_bar_view.xml @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/project_lifeline/views/task_lifeline_view.xml b/project_lifeline/views/task_lifeline_view.xml new file mode 100644 index 000000000..913ca995f --- /dev/null +++ b/project_lifeline/views/task_lifeline_view.xml @@ -0,0 +1,39 @@ + + + + Lifeline scheduler + + 1 + minutes + -1 + + + + + + + project.lifeline.tree + project.task + + + + + + + + + + project.lifeline.form + project.task + + + + + + + + + + + + \ No newline at end of file diff --git a/project_time_spend/__init__.py b/project_time_spend/__init__.py new file mode 100644 index 000000000..bff786c08 --- /dev/null +++ b/project_time_spend/__init__.py @@ -0,0 +1 @@ +import models diff --git a/project_time_spend/__manifest__.py b/project_time_spend/__manifest__.py new file mode 100644 index 000000000..65b03ea8e --- /dev/null +++ b/project_time_spend/__manifest__.py @@ -0,0 +1,17 @@ +{ + 'name': 'Task Statusbar', + 'author': 'Cybrosys Techno Solutions', + 'website': 'www.cybrosys.com', + 'category': 'Project', + 'version': '0.3', + 'summary': 'Calculates the time spend based on assigning date and deadline', + 'depends': [ + 'base', + 'project', + ], + 'data': [ + 'security/ir.model.access.csv', + 'views/project_statusbar_view.xml', + ], + 'installable': True, +} diff --git a/project_time_spend/__manifest__.py~ b/project_time_spend/__manifest__.py~ new file mode 100644 index 000000000..eeb91c878 --- /dev/null +++ b/project_time_spend/__manifest__.py~ @@ -0,0 +1,17 @@ +{ + 'name': 'Task Statusbar', + 'author': 'Nilmar Shereef PT', + 'website': 'www.cybrosys.com', + 'category': 'Project', + 'version': '10.0.0.3', + 'summary': 'Calculates the time spend based on assigning date and deadline', + 'depends': [ + 'base', + 'project', + ], + 'data': [ + 'security/ir.model.access.csv', + 'views/project_statusbar_view.xml', + ], + 'installable': True, +} \ No newline at end of file diff --git a/project_time_spend/models/__init__.py b/project_time_spend/models/__init__.py new file mode 100644 index 000000000..83fddeff1 --- /dev/null +++ b/project_time_spend/models/__init__.py @@ -0,0 +1 @@ +import project_statusbar diff --git a/project_time_spend/models/project_statusbar.py b/project_time_spend/models/project_statusbar.py new file mode 100644 index 000000000..1fa3f5e63 --- /dev/null +++ b/project_time_spend/models/project_statusbar.py @@ -0,0 +1,96 @@ +from odoo import models, fields, api +from dateutil.relativedelta import relativedelta + + +class ProjectCustom(models.Model): + _inherit = 'project.task' + + @api.model + def _check_ami_responsible(self): + """ Checks if user is responsible for this request + @return: Dictionary of values + """ + flag_poject_manager = self.env['res.users'].has_group('project.group_project_manager') + flag_project_user = self.env['res.users'].has_group('project.group_project_user') + for each in self: + + if flag_poject_manager: + each.get_user = True + elif flag_project_user: + each.get_user = False + else: + each.get_user = False + + get_user = fields.Boolean(string='Is Top User', compute=_check_ami_responsible) + done_time=fields.Datetime(compute='done_date',string="Color") + progress1 = fields.Integer(string="Working Time Progress(%)", copy=False, readonly=True) + + deadline_color = fields.Char(compute='compute_color',) + task_time = fields.Float(string="Time Range", copy=True) + date_deadline_ex = fields.Datetime('Deadline', select=True, copy=False, required=True) + kanban_state = fields.Selection( + [('normal', 'In Progress'), ('blocked', 'Blocked'), ('done', 'Ready for next stage')], 'Kanban State', + track_visibility='onchange', + help="A task's kanban state indicates special situations affecting it:\n" + " * Normal is the default situation\n" + " * Blocked indicates something is preventing the progress of this task\n" + " * Ready for next stage indicates the task is ready to be pulled to the next stage", + required=False, copy=False) + + _defaults = { + 'get_user': True, + } + + def compute_color(self): + + obj = self.env['project.task'] + obj1 = obj.search([]) + now = fields.Datetime.from_string(fields.Datetime.now()) + for obj2 in obj1: + + obj3 = obj2 + if obj3.stage_id.name != 'Done' and obj3.stage_id.name != 'Cancelled' and obj3.stage_id.name != 'Verified': + + end_date = fields.Datetime.from_string(obj3.date_deadline_ex) + + deadline_count = relativedelta(end_date, now) + if deadline_count.seconds < 0: + obj3.deadline_color = 'red' + else: + obj3.deadline_color = 'nothing' + + elif obj3.stage_id.name == 'Done' or obj3.stage_id.name == 'Verified': + + if obj3.progress1 < 100: + obj3.deadline_color = 'green' + else: + obj3.deadline_color = 'red' + + def process_demo_scheduler_queue(self): + + obj = self.env['project.task'] + obj1 = obj.search([]) + now = fields.Datetime.from_string(fields.Datetime.now()) + for obj2 in obj1: + obj3 = obj2 + if obj3.stage_id.name != 'Done' and obj3.stage_id.name != 'Cancelled' and obj3.stage_id.name != 'Verified': + start_date = fields.Datetime.from_string(obj3.date_assign) + end_date = fields.Datetime.from_string(obj3.date_deadline_ex) + if obj3.date_deadline_ex and obj3.date_assign and end_date > start_date: + if now < end_date: + dif_tot = relativedelta(end_date, start_date) + dif_minut = dif_tot.hours * 60 + dif_tot.minutes + diff1 = end_date - start_date + total_minut = int(diff1.days) * 24 * 60 + dif_minut + dif2_tot = relativedelta(now, start_date) + dif2_minut = dif2_tot.hours * 60 + dif2_tot.minutes + diff2 = now - start_date + used_minut = int(diff2.days) * 24 * 60 + dif2_minut + if total_minut != 0: + obj3.progress1 = ((used_minut * 100) / total_minut) + else: + obj3.progress1 = 100 + else: + obj3.progress1 = 100 + else: + obj3.progress1 = 0 diff --git a/project_time_spend/security/ir.model.access.csv b/project_time_spend/security/ir.model.access.csv new file mode 100644 index 000000000..0bb85e38c --- /dev/null +++ b/project_time_spend/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +project.access_project_task,project.task,project.model_project_task,project.group_project_user,1,1,0,0 diff --git a/project_time_spend/static/description/Screenshot from 2016-10-06 12:29:07.png b/project_time_spend/static/description/Screenshot from 2016-10-06 12:29:07.png new file mode 100644 index 000000000..37bd23986 Binary files /dev/null and b/project_time_spend/static/description/Screenshot from 2016-10-06 12:29:07.png differ diff --git a/project_time_spend/static/description/Screenshot from 2016-10-06 12:30:12.png b/project_time_spend/static/description/Screenshot from 2016-10-06 12:30:12.png new file mode 100644 index 000000000..86fac1971 Binary files /dev/null and b/project_time_spend/static/description/Screenshot from 2016-10-06 12:30:12.png differ diff --git a/project_time_spend/static/description/Screenshot from 2016-10-06 12:31:09.png b/project_time_spend/static/description/Screenshot from 2016-10-06 12:31:09.png new file mode 100644 index 000000000..ba41a7be5 Binary files /dev/null and b/project_time_spend/static/description/Screenshot from 2016-10-06 12:31:09.png differ diff --git a/project_time_spend/static/description/icon.png b/project_time_spend/static/description/icon.png new file mode 100644 index 000000000..a0fb5a2ee Binary files /dev/null and b/project_time_spend/static/description/icon.png differ diff --git a/project_time_spend/static/description/index.html b/project_time_spend/static/description/index.html new file mode 100644 index 000000000..1d9b26812 --- /dev/null +++ b/project_time_spend/static/description/index.html @@ -0,0 +1,51 @@ +
+
+

Task Time Spend

+

Calculates the time spend based on start date and deadline for every one hour

+

Author : NILMAR SHEREEF , www.cybrosys.com

+
+
+
+ This module helps to calculate the time spend for the specific task based on start date and deadline for every one hour until the stage becomes Done. And will shows + the progressbar in tree view and form view. +
+
+
+
+ ☛ Installation : To install this module, you need also the project module. +
+
+
+
+
+ +
+
+
+

+ Go to Project -> Task. And then create Task by specifying start date and deadline. +

+
+
+
+ +
+
+
+

+ Go to Project -> Task . Here you can see progress bar based on start date and dead line in both list and form view. +

+
+
+

Tree view

+
+ +
+
+
+

Form view

+ +
+
+
+ diff --git a/project_time_spend/views/project_statusbar_view.xml b/project_time_spend/views/project_statusbar_view.xml new file mode 100644 index 000000000..a1e269c46 --- /dev/null +++ b/project_time_spend/views/project_statusbar_view.xml @@ -0,0 +1,120 @@ + + + + Demo scheduler + + 1 + minutes + -1 + + + + + + + Project Inherit + project.task + + + + + + + + red:deadline_color=='red';green:deadline_color=='green' + + + + {'invisible': [('deadline_color', '!=', 'XYZ')]} + + + + + + Project Inherit1 + project.task + + + +
+
+ +
+ +
+ +
+ +
+

+ + +

+
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + Project Inherit2 + project.task + + + + {'invisible':[('kanban_state','=','blocked')]} + + + + + + \ No newline at end of file diff --git a/sale_discount_total/__init__.py b/sale_discount_total/__init__.py new file mode 100644 index 000000000..6446b4cc6 --- /dev/null +++ b/sale_discount_total/__init__.py @@ -0,0 +1,3 @@ +import models +import reports + diff --git a/sale_discount_total/__manifest__.py b/sale_discount_total/__manifest__.py new file mode 100644 index 000000000..53b2ce905 --- /dev/null +++ b/sale_discount_total/__manifest__.py @@ -0,0 +1,33 @@ +{ + 'name': 'Sale Discount on Total Amount', + 'version': '1.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' + ], + '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': [ + ], + 'application': True, + 'installable': True, + 'auto_install': False, +} diff --git a/sale_discount_total/__manifest__.py~ b/sale_discount_total/__manifest__.py~ new file mode 100644 index 000000000..56aa9bfcb --- /dev/null +++ b/sale_discount_total/__manifest__.py~ @@ -0,0 +1,33 @@ +{ + 'name': 'Sale Discount on Total Amount', + 'version': '1.0', + 'category': 'sale', + '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' + ], + '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': [ + ], + 'application': True, + 'installable': True, + 'auto_install': False, +} diff --git a/sale_discount_total/models/__init__.py b/sale_discount_total/models/__init__.py new file mode 100644 index 000000000..71b1402a2 --- /dev/null +++ b/sale_discount_total/models/__init__.py @@ -0,0 +1,4 @@ +import sale +import account_invoice +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..dffeefab4 --- /dev/null +++ b/sale_discount_total/models/account_invoice.py @@ -0,0 +1,80 @@ +from odoo import api, fields, models +import odoo.addons.decimal_precision as dp + + +class AccountInvoice(models.Model): + _inherit = "account.invoice" + + @api.one + @api.depends('invoice_line_ids.price_subtotal', 'tax_line_ids.amount', 'currency_id', 'company_id', 'date_invoice') + def _compute_amount(self): + self.amount_untaxed = sum(line.price_subtotal for line in self.invoice_line_ids) + self.amount_tax = sum(line.amount for line in self.tax_line_ids) + self.amount_total = self.amount_untaxed + self.amount_tax + self.amount_discount = sum((line.quantity * line.price_unit * line.discount)/100 for line in self.invoice_line_ids) + amount_total_company_signed = self.amount_total + amount_untaxed_signed = self.amount_untaxed + if self.currency_id and self.currency_id != self.company_id.currency_id: + currency_id = self.currency_id.with_context(date=self.date_invoice) + amount_total_company_signed = currency_id.compute(self.amount_total, self.company_id.currency_id) + amount_untaxed_signed = currency_id.compute(self.amount_untaxed, self.company_id.currency_id) + sign = self.type in ['in_refund', 'out_refund'] and -1 or 1 + self.amount_total_company_signed = amount_total_company_signed * sign + self.amount_total_signed = self.amount_total * sign + self.amount_untaxed_signed = amount_untaxed_signed * sign + + 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.invoice_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 + + @api.multi + def compute_invoice_totals(self, company_currency, invoice_move_lines): + total = 0 + total_currency = 0 + for line in invoice_move_lines: + if self.currency_id != company_currency: + currency = self.currency_id.with_context(date=self.date_invoice or fields.Date.context_today(self)) + line['currency_id'] = currency.id + line['amount_currency'] = currency.round(line['price']) + line['price'] = currency.compute(line['price'], company_currency) + else: + line['currency_id'] = False + line['amount_currency'] = False + line['price'] = line['price'] + if self.type in ('out_invoice', 'in_refund'): + total += line['price'] + total_currency += line['amount_currency'] or line['price'] + line['price'] = - line['price'] + else: + total -= line['price'] + total_currency -= line['amount_currency'] or line['price'] + return total, total_currency, invoice_move_lines + + @api.multi + def button_dummy(self): + self.supply_rate() + return True + +class AccountInvoiceLine(models.Model): + _inherit = "account.invoice.line" + + discount = fields.Float(string='Discount (%)', digits=(16, 20), default=0.0) \ No newline at end of file diff --git a/sale_discount_total/models/discount_approval.py b/sale_discount_total/models/discount_approval.py new file mode 100644 index 000000000..a60fd0d74 --- /dev/null +++ b/sale_discount_total/models/discount_approval.py @@ -0,0 +1,87 @@ +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') + + @api.multi + def action_confirm(self): + discnt = 0.0 + no_line = 0.0 + for order in self: + if order.company_id.discount_approval: + print order.company_id.discount_approval + for line in order.order_line: + no_line += 1 + discnt += line.discount + discnt = (discnt / no_line) + if order.company_id.limit_discount and discnt > order.company_id.limit_discount: + order.state = 'waiting' + return True + order.state = 'sale' + order.confirmation_date = fields.Datetime.now() + if self.env.context.get('send_email'): + self.force_quotation_send() + order.order_line._action_procurement_create() + if self.env['ir.values'].get_default('sale.config.settings', 'auto_done_setting'): + self.action_done() + return True + + @api.multi + def action_approve(self): + for order in self: + order.state = 'sale' + order.confirmation_date = fields.Datetime.now() + if self.env.context.get('send_email'): + self.force_quotation_send() + order.order_line._action_procurement_create() + if self.env['ir.values'].get_default('sale.config.settings', 'auto_done_setting'): + self.action_done() + return True + + + + +class Company(models.Model): + _inherit = 'res.company' + + limit_discount = fields.Float(string="Discount limit requires approval %", + help="Discount after which approval of sale is required.") + discount_approval = fields.Boolean("Force two levels of approvals", + help='Provide a double validation mechanism for sale exceeding minimum discount.') + + @api.multi + def set_default_discount(self): + if self.discount_approval and self.discount_approval != self.company_id.discount_approval: + self.company_id.write({'discount_approval': self.discount_approval}) + if self.limit_discount and self.limit_discount != self.company_id.limit_discount: + self.company_id.write({'limit_discount': self.limit_discount}) + + +class AccountDiscountSettings(models.TransientModel): + _inherit = 'account.config.settings' + + limit_discount = fields.Float(string="Discount limit requires approval in %", + related='company_id.limit_discount', + help="Discount after which approval of sale is required.") + discount_approval = fields.Boolean("Force two levels of approval on discount", + related='company_id.discount_approval', + help='Provide a double validation mechanism for sale exceeding maximum discount limit.') + + @api.onchange('company_id') + def onchange_company_id(self): + if self.company_id: + company = self.company_id + self.discount_approval = company.discount_approval + self.limit_discount = company.limit_discount + res = super(AccountDiscountSettings, self).onchange_company_id() + return res \ No newline at end of file diff --git a/sale_discount_total/models/sale.py b/sale_discount_total/models/sale.py new file mode 100644 index 000000000..8cc568547 --- /dev/null +++ b/sale_discount_total/models/sale.py @@ -0,0 +1,148 @@ +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': order.pricelist_id.currency_id.round(amount_untaxed), + 'amount_tax': order.pricelist_id.currency_id.round(amount_tax), + 'amount_discount': order.pricelist_id.currency_id.round(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_compute=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_compute=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 + + @api.multi + 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 + + @api.multi + def button_dummy(self): + self.supply_rate() + return True + +class AccountTax(models.Model): + _inherit = 'account.tax' + + @api.multi + def compute_all(self, price_unit, currency=None, quantity=1.0, product=None, partner=None): + print "hello" + if len(self) == 0: + company_id = self.env.user.company_id + else: + company_id = self[0].company_id + if not currency: + currency = company_id.currency_id + taxes = [] + prec = currency.decimal_places + round_tax = False if company_id.tax_calculation_rounding_method == 'round_globally' else True + round_total = True + if 'round' in self.env.context: + round_tax = bool(self.env.context['round']) + round_total = bool(self.env.context['round']) + + if not round_tax: + prec += 5 + # total_excluded = total_included = base = round(price_unit * quantity, prec) + total_excluded = total_included = base = (price_unit * quantity) + + for tax in self.sorted(key=lambda r: r.sequence): + if tax.amount_type == 'group': + ret = tax.children_tax_ids.compute_all(price_unit, currency, quantity, product, partner) + total_excluded = ret['total_excluded'] + base = ret['base'] + total_included = ret['total_included'] + tax_amount = total_included - total_excluded + taxes += ret['taxes'] + continue + + tax_amount = tax._compute_amount(base, price_unit, quantity, product, partner) + if not round_tax: + tax_amount = round(tax_amount, prec) + else: + tax_amount = currency.round(tax_amount) + + if tax.price_include: + total_excluded -= tax_amount + base -= tax_amount + else: + total_included += tax_amount + + tax_base = base + + if tax.include_base_amount: + base += tax_amount + + taxes.append({ + 'id': tax.id, + 'name': tax.with_context(**{'lang': partner.lang} if partner else {}).name, + 'amount': tax_amount, + 'sequence': tax.sequence, + 'account_id': tax.account_id.id, + 'refund_account_id': tax.refund_account_id.id, + 'analytic': tax.analytic, + 'base': tax_base, + }) + print "total_excluded:",total_excluded + print "total_included:",total_included + return { + 'taxes': sorted(taxes, key=lambda k: k['sequence']), + 'total_excluded': total_excluded, + 'total_included': total_included, + 'base': base, + } + + + +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..edd49ab05 --- /dev/null +++ b/sale_discount_total/reports/__init__.py @@ -0,0 +1,2 @@ +import invoice_report +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..59a19ccf7 --- /dev/null +++ b/sale_discount_total/reports/invoice_report.py @@ -0,0 +1,18 @@ +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 + """, sub.discount AS discount """ + return select_str + + def _sub_select(self): + res = super(AccountInvoiceReport,self)._sub_select() + select_str = res + """,SUM ((invoice_type.sign * ail.quantity) / (u.factor * u2.factor) * ail.price_unit * + ail.discount / 100) AS discount""" + return select_str \ No newline at end of file diff --git a/sale_discount_total/reports/sale_report.py b/sale_discount_total/reports/sale_report.py new file mode 100644 index 000000000..11fce8d58 --- /dev/null +++ b/sale_discount_total/reports/sale_report.py @@ -0,0 +1,13 @@ +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/Disc_appr_conf.png b/sale_discount_total/static/description/Disc_appr_conf.png new file mode 100644 index 000000000..7282092a0 Binary files /dev/null and b/sale_discount_total/static/description/Disc_appr_conf.png differ diff --git a/sale_discount_total/static/description/Disc_appr_wrkfl.png b/sale_discount_total/static/description/Disc_appr_wrkfl.png new file mode 100644 index 000000000..9ca5f0e7d Binary files /dev/null and b/sale_discount_total/static/description/Disc_appr_wrkfl.png differ diff --git a/sale_discount_total/static/description/Discount_inv_amnt.png b/sale_discount_total/static/description/Discount_inv_amnt.png new file mode 100644 index 000000000..01ba9e952 Binary files /dev/null and b/sale_discount_total/static/description/Discount_inv_amnt.png differ diff --git a/sale_discount_total/static/description/Discount_so_perc.png b/sale_discount_total/static/description/Discount_so_perc.png new file mode 100644 index 000000000..5eb1e6bf5 Binary files /dev/null and b/sale_discount_total/static/description/Discount_so_perc.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 100755 index 000000000..708815aeb --- /dev/null +++ b/sale_discount_total/static/description/index.html @@ -0,0 +1,39 @@ +
+
+

Discount On Sale

+ +
+

+ This module allows you to mention discount on Total of sale order and Total of Customer Invoice in two ways +

+
+

+ 1. As percentage
+ Select 'Percentage' from Discount type and give discount percentage as Discount rate. + System will update the value of Discount and Total +

+
+ +
+
+

+ 2. As amount
+ Select 'Amount' from Discount type and give discount amount as Discount rate. + System will update the value of Discount and Total +

+
+ +
+
+

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

+
+
+ +
+
+ +
+
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..61456b7ae --- /dev/null +++ b/sale_discount_total/views/account_invoice_view.xml @@ -0,0 +1,41 @@ + + + + + + discount.account.invoice + account.invoice + + + + (16, 2) + + + + + +
+
+
+
+
+
+
+ + + discount.account.invoice.line.tree + account.invoice.line + + + + (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..ef8802233 --- /dev/null +++ b/sale_discount_total/views/invoice_report.xml @@ -0,0 +1,18 @@ + + + + + + + + \ No newline at end of file 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..afa6839fc --- /dev/null +++ b/sale_discount_total/views/res_config_view.xml @@ -0,0 +1,28 @@ + + + + + discount.config + account.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..e3e92342a --- /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..249a1a928 --- /dev/null +++ b/sale_discount_total/views/sale_view.xml @@ -0,0 +1,43 @@ + + + + + + discount.sale.order.form + sale.order + + + +
+ + + +
+
+
+ +
+
diff --git a/sale_invoice_tag_pass/__init__.py b/sale_invoice_tag_pass/__init__.py new file mode 100644 index 000000000..b2462eb50 --- /dev/null +++ b/sale_invoice_tag_pass/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# Author: Nilmar Shereef() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 models diff --git a/sale_invoice_tag_pass/__manifest__.py b/sale_invoice_tag_pass/__manifest__.py new file mode 100644 index 000000000..6b60efd06 --- /dev/null +++ b/sale_invoice_tag_pass/__manifest__.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# Author: Nilmar Shereef() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 . +# +############################################################################## +{ + 'name': 'Sales Tags To Invoice Tags', + 'version': '0.1', + 'description': """Pass the sales tags to its invoice""", + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'website': 'http://www.cybrosys.com', + 'category': 'Sales Management', + 'depends': ['account', 'base', 'sale'], + 'license': 'AGPL-3', + 'data': [ + 'views/sale_invoice_tag_pass_view.xml' + ], + 'demo': [], + 'images': ['static/description/banner.jpg'], + 'installable': True, + 'auto_install': False, + +} diff --git a/sale_invoice_tag_pass/__manifest__.py~ b/sale_invoice_tag_pass/__manifest__.py~ new file mode 100644 index 000000000..96d050854 --- /dev/null +++ b/sale_invoice_tag_pass/__manifest__.py~ @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# Author: Nilmar Shereef() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 . +# +############################################################################## +{ + 'name': 'Sales Tags To Invoice Tags', + 'version': '0.1', + 'description': """Pass the sales tags to its invoice""", + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'website': 'http://www.cybrosys.com', + 'category': 'sale', + 'depends': ['account', 'base', 'sale'], + 'license': 'AGPL-3', + 'data': [ + 'views/sale_invoice_tag_pass_view.xml' + ], + 'demo': [], + 'images': ['static/description/banner.jpg'], + 'installable': True, + 'auto_install': False, + +} \ No newline at end of file diff --git a/sale_invoice_tag_pass/models/__init__.py b/sale_invoice_tag_pass/models/__init__.py new file mode 100644 index 000000000..251b8ed90 --- /dev/null +++ b/sale_invoice_tag_pass/models/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# Author: Nilmar Shereef() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 sale_invoice_tag_pass diff --git a/sale_invoice_tag_pass/models/sale_invoice_tag_pass.py b/sale_invoice_tag_pass/models/sale_invoice_tag_pass.py new file mode 100644 index 000000000..0ec1a532a --- /dev/null +++ b/sale_invoice_tag_pass/models/sale_invoice_tag_pass.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# Author: Nilmar Shereef() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 odoo import models, api, fields + + +class SaleTag(models.Model): + _inherit = 'sale.order' + + def _default_category(self): + return self.env['res.partner.category'].browse(self._context.get('category_id')) + + sale_tag = fields.Many2many('res.partner.category', column1='partner_id', + column2='category_id', string='Sales Tag', default=_default_category) + + +class AccountInvoice(models.Model): + _inherit = 'account.invoice' + + check_sale_tag = fields.Boolean() + sale_tag = fields.Many2many('res.partner.category', column1='partner_id', + column2='category_id', string='Sales Tag', compute='get_sales_tag') + + @api.one + @api.depends('user_id') + def get_sales_tag(self): + if self.name: + sale_order = self.env['sale.order'] + sale_tags = sale_order.search([('name', '=', self.name)]) + for tag in sale_tags: + self.sale_tag = tag.sale_tag + + + + + diff --git a/sale_invoice_tag_pass/static/description/banner.jpg b/sale_invoice_tag_pass/static/description/banner.jpg new file mode 100644 index 000000000..cef2552ca Binary files /dev/null and b/sale_invoice_tag_pass/static/description/banner.jpg differ diff --git a/sale_invoice_tag_pass/static/description/icon.png b/sale_invoice_tag_pass/static/description/icon.png new file mode 100644 index 000000000..ce95223da Binary files /dev/null and b/sale_invoice_tag_pass/static/description/icon.png differ diff --git a/sale_invoice_tag_pass/static/description/index.html b/sale_invoice_tag_pass/static/description/index.html new file mode 100644 index 000000000..8ec027b0a --- /dev/null +++ b/sale_invoice_tag_pass/static/description/index.html @@ -0,0 +1,69 @@ +
+
+

Sales Tags To Invoice Tags

+

It Gives Sales Tags To Invoice Tags

+

Author : Cybrosys Techno Solutions , www.cybrosys.com

+
+ +
+

Add Sale Invoice Tags

+
+

+ ☛This module enables the feature to add tags on invoice form and allow user to pass tags from sales order to customer invoice form. + Supporting for
* Invoice from Sales order
* Advance Invoice
* Percentage bases invoice from Sales Order. +

+
+
+
+
+
+ +
+
+

Sale Order Tags - Odoo Default

+
+

+ ☛Tags display on Quotation/Sale Order form will be pass to respective customer invoices of that sales order.
+ +

+
+ +
+
+
+
+ +
+
+

Tax Tags on Customer Invoice Form

+
+

+ ☛Tags from sale order will be shown here.
+ +

+
+ +
+
+
+
+ +
+

Need Any Help?

+ +
+ + + + + diff --git a/sale_invoice_tag_pass/static/description/invoice_tag.png b/sale_invoice_tag_pass/static/description/invoice_tag.png new file mode 100644 index 000000000..c7fc6e95a Binary files /dev/null and b/sale_invoice_tag_pass/static/description/invoice_tag.png differ diff --git a/sale_invoice_tag_pass/static/description/sale_order_tag.png b/sale_invoice_tag_pass/static/description/sale_order_tag.png new file mode 100644 index 000000000..4893d3a83 Binary files /dev/null and b/sale_invoice_tag_pass/static/description/sale_order_tag.png differ diff --git a/sale_invoice_tag_pass/views/sale_invoice_tag_pass_view.xml b/sale_invoice_tag_pass/views/sale_invoice_tag_pass_view.xml new file mode 100644 index 000000000..4e7e2223d --- /dev/null +++ b/sale_invoice_tag_pass/views/sale_invoice_tag_pass_view.xml @@ -0,0 +1,27 @@ + + + + + + sale.order + sale.order + + + + + + + + + account.invoice + account.invoice + + + + + + + + + + \ No newline at end of file diff --git a/timesheets_by_employee/__init__.py b/timesheets_by_employee/__init__.py new file mode 100644 index 000000000..4b748e404 --- /dev/null +++ b/timesheets_by_employee/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 report +import wizard diff --git a/timesheets_by_employee/__manifest__.py b/timesheets_by_employee/__manifest__.py new file mode 100644 index 000000000..67864ff77 --- /dev/null +++ b/timesheets_by_employee/__manifest__.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 . +# +############################################################################## +{ + 'name': 'Timesheet PDF Report', + 'version': '10.0.1.0.0', + "category": "Generic Modules/Human Resources", + 'sequence': 25, + 'summary': 'Timesheet PDF Report of Employees', + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'website': 'www.cybrosys.com', + 'depends': ['hr_timesheet'], + 'data': [ + 'report/report_timesheets.xml', + 'wizard/timesheet_wizard.xml', + ], + 'images': ['static/description/banner.jpg'], + 'license': 'AGPL-3', + 'installable': True, + 'auto_install': False, + 'application': False, +} diff --git a/timesheets_by_employee/__manifest__.py~ b/timesheets_by_employee/__manifest__.py~ new file mode 100644 index 000000000..5e7a4c17a --- /dev/null +++ b/timesheets_by_employee/__manifest__.py~ @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 . +# +############################################################################## +{ + 'name': 'Timesheet PDF Report', + 'version': '10.0.1.0.0', + "category": "Generic Modules/Human Resources", + 'sequence': 25, + 'summary': 'Timesheet PDF Report of Employee', + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'website': 'www.cybrosys.com', + 'depends': ['hr_timesheet'], + 'data': [ + 'report/report_timesheets.xml', + 'wizard/timesheet_wizard.xml', + ], + 'images': ['static/description/banner.jpg'], + 'license': 'AGPL-3', + 'installable': True, + 'auto_install': False, + 'application': False, +} diff --git a/timesheets_by_employee/report/__init__.py b/timesheets_by_employee/report/__init__.py new file mode 100644 index 000000000..3360d21fb --- /dev/null +++ b/timesheets_by_employee/report/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 report_timesheets diff --git a/timesheets_by_employee/report/report_timesheets.py b/timesheets_by_employee/report/report_timesheets.py new file mode 100644 index 000000000..7b7454ecd --- /dev/null +++ b/timesheets_by_employee/report/report_timesheets.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 odoo import models, fields, api + + +class ReportTimesheet(models.AbstractModel): + _name = 'report.timesheets_by_employee.report_timesheets' + + def get_timesheets(self, docs): + """input : name of employee and the starting date and ending date + output: timesheets by that particular employee within that period and the total duration""" + + if docs.from_date and docs.to_date: + rec = self.env['account.analytic.line'].search([('user_id', '=', docs.employee[0].id), + ('date', '>=', docs.from_date),('date', '<=', docs.to_date)]) + elif docs.from_date: + rec = self.env['account.analytic.line'].search([('user_id', '=', docs.employee[0].id), + ('date', '>=', docs.from_date)]) + elif docs.to_date: + rec = self.env['account.analytic.line'].search([('user_id', '=', docs.employee[0].id), + ('date', '<=', docs.to_date)]) + else: + rec = self.env['account.analytic.line'].search([('user_id', '=', docs.employee[0].id)]) + records = [] + total = 0 + for r in rec: + vals = {'project': r.project_id.name, + 'user': r.user_id.partner_id.name, + 'duration': r.unit_amount, + 'date': r.date, + } + total += r.unit_amount + records.append(vals) + return [records, total] + + @api.model + def render_html(self, docids, data=None): + """we are overwriting this function because we need to show values from other models in the report + we pass the objects in the docargs dictionary""" + + self.model = self.env.context.get('active_model') + docs = self.env[self.model].browse(self.env.context.get('active_id')) + identification = [] + for i in self.env['hr.employee'].search([('user_id', '=', docs.employee[0].id)]): + if i: + identification.append({'id': i.identification_id, 'name': i.name_related}) + + timesheets = self.get_timesheets(docs) + period = None + if docs.from_date and docs.to_date: + period = "From " + str(docs.from_date) + " To " + str(docs.to_date) + elif docs.from_date: + period = "From " + str(docs.from_date) + elif docs.from_date: + period = " To " + str(docs.to_date) + docargs = { + 'doc_ids': self.ids, + 'doc_model': self.model, + 'docs': docs, + 'timesheets': timesheets[0], + 'total': timesheets[1], + 'company': docs.employee[0].company_id.name, + 'identification': identification, + 'period': period, + } + return self.env['report'].render('timesheets_by_employee.report_timesheets', docargs) diff --git a/timesheets_by_employee/report/report_timesheets.xml b/timesheets_by_employee/report/report_timesheets.xml new file mode 100644 index 000000000..0d527eac4 --- /dev/null +++ b/timesheets_by_employee/report/report_timesheets.xml @@ -0,0 +1,72 @@ + + + + \ No newline at end of file diff --git a/timesheets_by_employee/static/description/banner.jpg b/timesheets_by_employee/static/description/banner.jpg new file mode 100644 index 000000000..61a8c596b Binary files /dev/null and b/timesheets_by_employee/static/description/banner.jpg differ diff --git a/timesheets_by_employee/static/description/cybro_logo.png b/timesheets_by_employee/static/description/cybro_logo.png new file mode 100644 index 000000000..bb309114c Binary files /dev/null and b/timesheets_by_employee/static/description/cybro_logo.png differ diff --git a/timesheets_by_employee/static/description/icon.png b/timesheets_by_employee/static/description/icon.png new file mode 100644 index 000000000..ee52f55b3 Binary files /dev/null and b/timesheets_by_employee/static/description/icon.png differ diff --git a/timesheets_by_employee/static/description/image1.png b/timesheets_by_employee/static/description/image1.png new file mode 100644 index 000000000..2ee674479 Binary files /dev/null and b/timesheets_by_employee/static/description/image1.png differ diff --git a/timesheets_by_employee/static/description/image2.png b/timesheets_by_employee/static/description/image2.png new file mode 100644 index 000000000..fec41bed0 Binary files /dev/null and b/timesheets_by_employee/static/description/image2.png differ diff --git a/timesheets_by_employee/static/description/index.html b/timesheets_by_employee/static/description/index.html new file mode 100644 index 000000000..8d395de26 --- /dev/null +++ b/timesheets_by_employee/static/description/index.html @@ -0,0 +1,50 @@ +
+
+

Timesheet PDF Report of Employee

+

..Print timesheets of selected employees..

+

Cybrosys Technologies , www.cybrosys.com

+
+

+ This module by Cybrosys Technologies allows to print the timesheets of selected employee. It will group all timesheet lines + of selected employee in wizard by period. +

+
+
+ +
+
+
+

Generate Timesheet Report Wizard With Dates:

+
+ +
+
+
+
+ +
+
+
+

PDF Report Of Employee Timesheet:

+
+ +
+
+
+
+ +
+

Need Any Help?

+ + +
diff --git a/timesheets_by_employee/static/description/index.html~ b/timesheets_by_employee/static/description/index.html~ new file mode 100644 index 000000000..406f404b0 --- /dev/null +++ b/timesheets_by_employee/static/description/index.html~ @@ -0,0 +1,50 @@ +
+
+

Timesheet PDF Report of Employee

+

..Print timesheets of selected employees..

+

Cybrosys Technologies , www.cybrosys.com

+
+

+ This module by Cybrosys Technologies allows to print the timesheets of selected employee. It will group all timesheet lines + of selected employee in wizard by period. +

+
+
+ +
+
+
+

Generate Timesheet Report Wizard With Dates:

+
+ +
+
+
+
+ +
+
+
+

PDF Report Of Employee Timesheet:

+
+ +
+
+
+
+ +
+

Need Any Help?

+ + +
diff --git a/timesheets_by_employee/wizard/__init__.py b/timesheets_by_employee/wizard/__init__.py new file mode 100644 index 000000000..e2d78765f --- /dev/null +++ b/timesheets_by_employee/wizard/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 timesheet_employee diff --git a/timesheets_by_employee/wizard/timesheet_employee.py b/timesheets_by_employee/wizard/timesheet_employee.py new file mode 100644 index 000000000..20f63fd16 --- /dev/null +++ b/timesheets_by_employee/wizard/timesheet_employee.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2009-TODAY Cybrosys Technologies(). +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 odoo import models, fields + + +class EmployeeTimesheet(models.TransientModel): + _name = 'timesheet.wizard' + + employee = fields.Many2one('res.users', string="Employee", required=True) + from_date = fields.Date(string="Starting Date") + to_date = fields.Date(string="Ending Date") + + def print_timesheet(self, data): + """Redirects to the report with the values obtained from the wizard + 'data['form']': name of employee and the date duration""" + data = {} + data['form'] = self.read(['employee', 'from_date', 'to_date'])[0] + return self.env['report'].get_action(self, 'timesheets_by_employee.report_timesheets', data=data) + diff --git a/timesheets_by_employee/wizard/timesheet_wizard.xml b/timesheets_by_employee/wizard/timesheet_wizard.xml new file mode 100644 index 000000000..404f31e0a --- /dev/null +++ b/timesheets_by_employee/wizard/timesheet_wizard.xml @@ -0,0 +1,51 @@ + + + + + Timesheets Wizard + timesheet.wizard + +
+ + + + + + + + +
+
+
+
+
+
+ + + Generate Timesheet Report + timesheet.wizard + ir.actions.act_window + form + form + + new + + + + + +
+
+ + +