From d8ccc0e9b0b254ec27d3f1ac7316e4e6cf7516ee Mon Sep 17 00:00:00 2001 From: ps-tubtim Date: Wed, 11 Mar 2020 10:24:44 +0700 Subject: [PATCH 01/41] [12.0][ADD]hr_expense_petty_cash --- hr_expense_petty_cash/README.rst | 123 +++++ hr_expense_petty_cash/__init__.py | 4 + hr_expense_petty_cash/__manifest__.py | 22 + hr_expense_petty_cash/models/__init__.py | 7 + .../models/account_invoice.py | 76 +++ hr_expense_petty_cash/models/hr_expense.py | 47 ++ .../models/hr_expense_sheet.py | 55 ++ hr_expense_petty_cash/models/petty_cash.py | 43 ++ hr_expense_petty_cash/readme/CONFIGURE.rst | 9 + hr_expense_petty_cash/readme/CONTRIBUTORS.rst | 3 + hr_expense_petty_cash/readme/DESCRIPTION.rst | 8 + hr_expense_petty_cash/readme/USAGE.rst | 24 + .../security/ir.model.access.csv | 2 + .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 472 ++++++++++++++++++ hr_expense_petty_cash/tests/__init__.py | 4 + .../tests/test_hr_expense_petty_cash.py | 257 ++++++++++ .../views/account_invoice_views.xml | 15 + .../views/hr_expense_sheet_views.xml | 30 ++ .../views/hr_expense_views.xml | 32 ++ .../views/petty_cash_views.xml | 92 ++++ 21 files changed, 1325 insertions(+) create mode 100644 hr_expense_petty_cash/README.rst create mode 100644 hr_expense_petty_cash/__init__.py create mode 100644 hr_expense_petty_cash/__manifest__.py create mode 100644 hr_expense_petty_cash/models/__init__.py create mode 100644 hr_expense_petty_cash/models/account_invoice.py create mode 100644 hr_expense_petty_cash/models/hr_expense.py create mode 100644 hr_expense_petty_cash/models/hr_expense_sheet.py create mode 100644 hr_expense_petty_cash/models/petty_cash.py create mode 100644 hr_expense_petty_cash/readme/CONFIGURE.rst create mode 100644 hr_expense_petty_cash/readme/CONTRIBUTORS.rst create mode 100644 hr_expense_petty_cash/readme/DESCRIPTION.rst create mode 100644 hr_expense_petty_cash/readme/USAGE.rst create mode 100644 hr_expense_petty_cash/security/ir.model.access.csv create mode 100644 hr_expense_petty_cash/static/description/icon.png create mode 100644 hr_expense_petty_cash/static/description/index.html create mode 100644 hr_expense_petty_cash/tests/__init__.py create mode 100644 hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py create mode 100644 hr_expense_petty_cash/views/account_invoice_views.xml create mode 100644 hr_expense_petty_cash/views/hr_expense_sheet_views.xml create mode 100644 hr_expense_petty_cash/views/hr_expense_views.xml create mode 100644 hr_expense_petty_cash/views/petty_cash_views.xml diff --git a/hr_expense_petty_cash/README.rst b/hr_expense_petty_cash/README.rst new file mode 100644 index 000000000..86a3160a5 --- /dev/null +++ b/hr_expense_petty_cash/README.rst @@ -0,0 +1,123 @@ +========== +Petty Cash +========== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fhr-lightgray.png?logo=github + :target: https://github.com/OCA/hr/tree/12.0/hr_expense_petty_cash + :alt: OCA/hr +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/hr-12-0/hr-12-0-hr_expense_petty_cash + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/116/12.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module work about expense that paid by petty cash. + +General Process: + +#. Create Petty Cash Holder +#. Transfer cash to Petty Cash Holder By Vendor bill +#. You can create expense paid by petty cash and select petty cash holder. +#. Then balance of petty cash holder less than amount of expense, you must transfer cash to petty cash holder before Submit Report to Manager. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +**Create a Petty Cash Account** + +#. Go to Invoicing > Configuration > Chart of accounts +#. Create a new petty cash account +#. Type = Bank and Cash or Account type that is asset + +Note: + +* You will need the "Show Full Accounting Features" to see accounting data + +Usage +===== + +**Create a Petty Cash Holder** + +#. Go to Invoicing > Configuration > Petty Cash +#. Create a new petty cash holder +#. Select Petty Cash Account + +**Add Balance for Petty Cash Holder** + +#. Go to Invoicing > Vendor > Bill +#. Create a new vendor bill +#. Select Vendor (Petty Cash Holder) +#. Check Petty Cash will auto line with Unit Price = Max Limit - Balance + +**Create an Expense paid by Petty Cash** + +#. Go to Expenses > My Expenses +#. Create a new expense +#. Select Paid by = Petty Cash and Select Petty Cash Holder + +**Create an Expense Report paid by Petty Cash** + +#. Go to Expenses > My Expense Reports +#. Create a new expense report +#. Select or Create expenses Paid by Petty Cash and same Petty Cash Holder + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Ecosoft + +Contributors +~~~~~~~~~~~~ + +* `Ecosoft `__: + + * Pimolnat Suntian + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/hr `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/hr_expense_petty_cash/__init__.py b/hr_expense_petty_cash/__init__.py new file mode 100644 index 000000000..4fb530fd1 --- /dev/null +++ b/hr_expense_petty_cash/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import models diff --git a/hr_expense_petty_cash/__manifest__.py b/hr_expense_petty_cash/__manifest__.py new file mode 100644 index 000000000..558ee7107 --- /dev/null +++ b/hr_expense_petty_cash/__manifest__.py @@ -0,0 +1,22 @@ +# Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + 'name': 'Petty Cash', + 'version': '12.0.1.0.0', + 'category': 'Human Resources', + 'author': 'Ecosoft, Odoo Community Association (OCA)', + 'license': 'AGPL-3', + 'website': 'https://github.com/OCA/hr', + 'depends': [ + 'hr_expense', + ], + 'data': [ + 'security/ir.model.access.csv', + 'views/account_invoice_views.xml', + 'views/hr_expense_sheet_views.xml', + 'views/hr_expense_views.xml', + 'views/petty_cash_views.xml', + ], + 'installable': True, +} diff --git a/hr_expense_petty_cash/models/__init__.py b/hr_expense_petty_cash/models/__init__.py new file mode 100644 index 000000000..260bacdf9 --- /dev/null +++ b/hr_expense_petty_cash/models/__init__.py @@ -0,0 +1,7 @@ +# Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import account_invoice +from . import hr_expense +from . import hr_expense_sheet +from . import petty_cash diff --git a/hr_expense_petty_cash/models/account_invoice.py b/hr_expense_petty_cash/models/account_invoice.py new file mode 100644 index 000000000..809f1d240 --- /dev/null +++ b/hr_expense_petty_cash/models/account_invoice.py @@ -0,0 +1,76 @@ +# Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models, _ +from odoo.exceptions import ValidationError + + +class AccountInvoice(models.Model): + _inherit = 'account.invoice' + + is_petty_cash = fields.Boolean( + string='Petty Cash', + readonly=True, + states={'draft': [('readonly', False)]}, + ) + + @api.multi + @api.constrains('invoice_line_ids') + def _check_petty_cash_amount(self): + petty_cash_env = self.env['petty.cash'] + for rec in self.filtered('is_petty_cash'): + petty_cash = petty_cash_env.search( + [('partner_id', '=', rec.partner_id.id)], limit=1) + if not petty_cash: + raise ValidationError(_('%s is not a petty cash holder') % + rec.partner_id.name) + balance = petty_cash.petty_cash_balance + limit = petty_cash.petty_cash_limit + max_amount = limit - balance + account = petty_cash.account_id + amount = sum(rec.invoice_line_ids.filtered( + lambda l: l.account_id == account).mapped('price_subtotal')) + company_currency = rec.company_id.currency_id + amount_company = rec.currency_id._convert( + amount, company_currency, rec.company_id, + rec.date_invoice or fields.Date.today()) + if amount_company > max_amount: + raise ValidationError( + _('Petty Cash balance is %s %s.\n' + 'Max amount to add is %s %s.') % + ('{:,.2f}'.format(balance), company_currency.symbol, + '{:,.2f}'.format(max_amount), company_currency.symbol)) + + @api.multi + def _add_petty_cash_invoice_line(self, petty_cash): + self.ensure_one() + # Get suggested currency amount + amount = petty_cash.petty_cash_limit - petty_cash.petty_cash_balance + company_currency = self.env.user.company_id.currency_id + amount_doc_currency = company_currency._convert( + amount, self.currency_id, self.company_id, + self.date_invoice or fields.Date.today()) + + inv_line = self.env['account.invoice.line'].new({ + 'name': petty_cash.account_id.name, + 'invoice_id': self.id, + 'account_id': petty_cash.account_id.id, + 'price_unit': amount_doc_currency, + 'quantity': 1, + }) + return inv_line + + @api.multi + @api.onchange('is_petty_cash', 'partner_id') + def _onchange_is_petty_cash(self): + self.invoice_line_ids = False + if self.is_petty_cash: + if not self.partner_id: + raise ValidationError(_('Please select petty cash holder')) + # Selected parenter must be petty cash holder + petty_cash = self.env['petty.cash'].search( + [('partner_id', '=', self.partner_id.id)], limit=1) + if not petty_cash: + raise ValidationError(_('%s is not a petty cash holder') % + self.partner_id.name) + self._add_petty_cash_invoice_line(petty_cash) diff --git a/hr_expense_petty_cash/models/hr_expense.py b/hr_expense_petty_cash/models/hr_expense.py new file mode 100644 index 000000000..3ab894818 --- /dev/null +++ b/hr_expense_petty_cash/models/hr_expense.py @@ -0,0 +1,47 @@ +# Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models, _ +from odoo.exceptions import ValidationError + + +class HrExpense(models.Model): + _inherit = 'hr.expense' + + payment_mode = fields.Selection( + selection_add=[('petty_cash', 'Petty Cash')], + ) + petty_cash_id = fields.Many2one( + string='Petty cash holder', + comodel_name='petty.cash', + ondelete='restrict', + readonly=True, + states={'draft': [('readonly', False)]}, + ) + + @api.multi + def action_submit_expenses(self): + res = super().action_submit_expenses() + context = res['context'] + context['default_expense_line_ids'] = self.ids + context['default_name'] = self[0].name if len(self) == 1 else '' + set_petty_cash_ids = set() + for rec in self: + set_petty_cash_ids.add(rec.petty_cash_id.id) + if set_petty_cash_ids: + if len(set_petty_cash_ids) == 1: + context['default_petty_cash_id'] = set_petty_cash_ids.pop() + return res + raise ValidationError(_('You cannot create report from ' + 'many petty cash holders.')) + + @api.multi + def _get_account_move_line_values(self): + res = super()._get_account_move_line_values() + for expense in self.filtered( + lambda p: p.payment_mode == 'petty_cash'): + line = res[expense.id][1] + line['account_id'] = expense.petty_cash_id.account_id.id + line['partner_id'] = expense.petty_cash_id.partner_id.id + res[expense.id][1] = line + return res diff --git a/hr_expense_petty_cash/models/hr_expense_sheet.py b/hr_expense_petty_cash/models/hr_expense_sheet.py new file mode 100644 index 000000000..84f862a01 --- /dev/null +++ b/hr_expense_petty_cash/models/hr_expense_sheet.py @@ -0,0 +1,55 @@ +# Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models, _ +from odoo.exceptions import ValidationError + + +class HrExpenseSheet(models.Model): + _inherit = 'hr.expense.sheet' + + payment_mode = fields.Selection( + selection_add=[('petty_cash', 'Petty Cash')], + ) + petty_cash_id = fields.Many2one( + string='Petty cash holder', + comodel_name='petty.cash', + ondelete='restrict', + readonly=True, + compute='_compute_petty_cash', + ) + + @api.depends('expense_line_ids', 'payment_mode') + def _compute_petty_cash(self): + for rec in self: + if rec.payment_mode == 'petty_cash': + set_petty_cash_ids = set() + for line in rec.expense_line_ids: + set_petty_cash_ids.add(line.petty_cash_id.id) + if len(set_petty_cash_ids) == 1: + rec.petty_cash_id = rec.env['petty.cash'].browse( + set_petty_cash_ids.pop()) + else: + raise ValidationError(_('You cannot create report from ' + 'many petty cash holders.')) + + @api.multi + @api.constrains('expense_line_ids', 'total_amount') + def _check_petty_cash_amount(self): + for rec in self: + if rec.payment_mode == 'petty_cash': + petty_cash = rec.petty_cash_id + balance = petty_cash.petty_cash_balance + amount = rec.total_amount + company_currency = rec.company_id.currency_id + amount_company = rec.currency_id._convert( + amount, company_currency, rec.company_id, + rec.accounting_date or fields.Date.today()) + if amount_company > balance: + raise ValidationError( + _('Not enough money in petty cash holder.\n' + 'You are requesting %s%s, ' + 'but the balance is %s%s.') % + ('{:,.2f}'.format(amount_company), + company_currency.symbol, '{:,.2f}'.format(balance), + company_currency.symbol)) diff --git a/hr_expense_petty_cash/models/petty_cash.py b/hr_expense_petty_cash/models/petty_cash.py new file mode 100644 index 000000000..e160d2e5a --- /dev/null +++ b/hr_expense_petty_cash/models/petty_cash.py @@ -0,0 +1,43 @@ +# Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class PettyCash(models.Model): + _name = 'petty.cash' + _description = 'Petty Cash' + _rec_name = 'partner_id' + + partner_id = fields.Many2one( + comodel_name='res.partner', + string='Petty Cash Holder', + domain=[('supplier', '=', True)], + required=True, + ) + account_id = fields.Many2one( + comodel_name='account.account', + string='Petty Cash Account', + required=True, + ) + petty_cash_limit = fields.Float( + string='Max Limit', + required=True, + ) + petty_cash_balance = fields.Float( + string='Balance', + compute='_compute_petty_cash_balance', + ) + _sql_constraints = [ + ('partner_uniq', 'unique(partner_id)', + 'Petty Cash Holder must be unique!'), + ] + + @api.depends('partner_id', 'account_id') + def _compute_petty_cash_balance(self): + aml_env = self.env['account.move.line'] + for rec in self: + aml = aml_env.search([('partner_id', '=', rec.partner_id.id), + ('account_id', '=', rec.account_id.id)]) + balance = sum([line.debit - line.credit for line in aml]) + rec.petty_cash_balance = balance diff --git a/hr_expense_petty_cash/readme/CONFIGURE.rst b/hr_expense_petty_cash/readme/CONFIGURE.rst new file mode 100644 index 000000000..ea01a77ff --- /dev/null +++ b/hr_expense_petty_cash/readme/CONFIGURE.rst @@ -0,0 +1,9 @@ +**Create a Petty Cash Account** + +#. Go to Invoicing > Configuration > Chart of accounts +#. Create a new petty cash account +#. Type = Bank and Cash or Account type that is asset + +Note: + +* You will need the "Show Full Accounting Features" to see accounting data diff --git a/hr_expense_petty_cash/readme/CONTRIBUTORS.rst b/hr_expense_petty_cash/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..ea63aa7bc --- /dev/null +++ b/hr_expense_petty_cash/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* `Ecosoft `__: + + * Pimolnat Suntian diff --git a/hr_expense_petty_cash/readme/DESCRIPTION.rst b/hr_expense_petty_cash/readme/DESCRIPTION.rst new file mode 100644 index 000000000..c3429b393 --- /dev/null +++ b/hr_expense_petty_cash/readme/DESCRIPTION.rst @@ -0,0 +1,8 @@ +This module work about expense that paid by petty cash. + +General Process: + +#. Create Petty Cash Holder +#. Transfer cash to Petty Cash Holder By Vendor bill +#. You can create expense paid by petty cash and select petty cash holder. +#. Then balance of petty cash holder less than amount of expense, you must transfer cash to petty cash holder before Submit Report to Manager. diff --git a/hr_expense_petty_cash/readme/USAGE.rst b/hr_expense_petty_cash/readme/USAGE.rst new file mode 100644 index 000000000..c7afde627 --- /dev/null +++ b/hr_expense_petty_cash/readme/USAGE.rst @@ -0,0 +1,24 @@ +**Create a Petty Cash Holder** + +#. Go to Invoicing > Configuration > Petty Cash +#. Create a new petty cash holder +#. Select Petty Cash Account + +**Add Balance for Petty Cash Holder** + +#. Go to Invoicing > Vendor > Bill +#. Create a new vendor bill +#. Select Vendor (Petty Cash Holder) +#. Check Petty Cash will auto line with Unit Price = Max Limit - Balance + +**Create an Expense paid by Petty Cash** + +#. Go to Expenses > My Expenses +#. Create a new expense +#. Select Paid by = Petty Cash and Select Petty Cash Holder + +**Create an Expense Report paid by Petty Cash** + +#. Go to Expenses > My Expense Reports +#. Create a new expense report +#. Select or Create expenses Paid by Petty Cash and same Petty Cash Holder diff --git a/hr_expense_petty_cash/security/ir.model.access.csv b/hr_expense_petty_cash/security/ir.model.access.csv new file mode 100644 index 000000000..de6f0bca0 --- /dev/null +++ b/hr_expense_petty_cash/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 +access_hr_expense_petty_cash,access_hr_expense_petty_cash,model_petty_cash,account.group_account_manager,1,1,1,1 diff --git a/hr_expense_petty_cash/static/description/icon.png b/hr_expense_petty_cash/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/hr_expense_petty_cash/static/description/index.html b/hr_expense_petty_cash/static/description/index.html new file mode 100644 index 000000000..85e04f445 --- /dev/null +++ b/hr_expense_petty_cash/static/description/index.html @@ -0,0 +1,472 @@ + + + + + + +Petty Cash + + + +
+

Petty Cash

+ + +

Beta License: AGPL-3 OCA/hr Translate me on Weblate Try me on Runbot

+

This module work about expense that paid by petty cash.

+

General Process:

+
    +
  1. Create Petty Cash Holder
  2. +
  3. Transfer cash to Petty Cash Holder By Vendor bill
  4. +
  5. You can create expense paid by petty cash and select petty cash holder.
  6. +
  7. Then balance of petty cash holder less than amount of expense, you must transfer cash to petty cash holder before Submit Report to Manager.
  8. +
+

Table of contents

+ +
+

Configuration

+

Create a Petty Cash Account

+
    +
  1. Go to Invoicing > Configuration > Chart of accounts
  2. +
  3. Create a new petty cash account
  4. +
  5. Type = Bank and Cash or Account type that is asset
  6. +
+

Note:

+
    +
  • You will need the “Show Full Accounting Features” to see accounting data
  • +
+
+
+

Usage

+

Create a Petty Cash Holder

+
    +
  1. Go to Invoicing > Configuration > Petty Cash
  2. +
  3. Create a new petty cash holder
  4. +
  5. Select Petty Cash Account
  6. +
+

Add Balance for Petty Cash Holder

+
    +
  1. Go to Invoicing > Vendor > Bill
  2. +
  3. Create a new vendor bill
  4. +
  5. Select Vendor (Petty Cash Holder)
  6. +
  7. Check Petty Cash will auto line with Unit Price = Max Limit - Balance
  8. +
+

Create an Expense paid by Petty Cash

+
    +
  1. Go to Expenses > My Expenses
  2. +
  3. Create a new expense
  4. +
  5. Select Paid by = Petty Cash and Select Petty Cash Holder
  6. +
+

Create an Expense Report paid by Petty Cash

+
    +
  1. Go to Expenses > My Expense Reports
  2. +
  3. Create a new expense report
  4. +
  5. Select or Create expenses Paid by Petty Cash and same Petty Cash Holder
  6. +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Ecosoft
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/hr project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/hr_expense_petty_cash/tests/__init__.py b/hr_expense_petty_cash/tests/__init__.py new file mode 100644 index 000000000..9187e19b9 --- /dev/null +++ b/hr_expense_petty_cash/tests/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import test_hr_expense_petty_cash diff --git a/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py b/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py new file mode 100644 index 000000000..97c2be8bd --- /dev/null +++ b/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py @@ -0,0 +1,257 @@ +# Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.exceptions import ValidationError +from odoo.tests import common + + +class TestHrExpensePettyCash(common.TransactionCase): + def setUp(self): + super(TestHrExpensePettyCash, self).setUp() + + # Create an employee + self.employee_id = self.env.ref('hr.employee_admin') + + # Create a product + self.product_id = self.env.ref('hr_expense.air_ticket') + + # Create an account payable + payable_type = self.env.ref('account.data_account_type_payable') + self.account_id = self.env['account.account'].create({ + 'code': '111111', + 'name': 'Payable - Test', + 'user_type_id': payable_type.id, + 'reconcile': True, + }) + + # Create a Petty Cash Account + liquidity_type = self.env.ref('account.data_account_type_liquidity') + self.petty_cash_account_id = self.env['account.account'].create({ + 'code': '000000', + 'name': 'Petty Cash - Test', + 'user_type_id': liquidity_type.id, + }) + + # Create Partner + self.partner_1 = self.env['res.partner'].create({ + 'name': 'Partner 1 - Test', + }) + self.partner_2 = self.env['res.partner'].create({ + 'name': 'Partner 2 - Test', + }) + + def create_petty_cash_holder(self, partner, petty_cash_balance=False): + petty_cash_holder = self.env['petty.cash'].create({ + 'partner_id': partner.id, + 'account_id': self.petty_cash_account_id.id, + 'petty_cash_limit': 1000.00, + 'petty_cash_balance': petty_cash_balance or 0.0, + }) + return petty_cash_holder + + def test_petty_cash(self): + petty_cash_holder = self.create_petty_cash_holder(self.partner_1) + self.assertEqual(petty_cash_holder.petty_cash_balance, 0.00) + invoice = self.env['account.invoice'].create({ + 'partner_id': self.partner_1.id, + 'account_id': self.account_id.id, + 'type': 'in_invoice', + 'is_petty_cash': True, + }) + self.env['account.invoice.line'].create({ + 'name': 'Petty Cash', + 'account_id': self.petty_cash_account_id.id, + 'invoice_id': invoice.id, + 'quantity': 1.000, + 'price_unit': 1000.00, + }) + invoice.action_invoice_open() + petty_cash_holder._compute_petty_cash_balance() + self.assertEqual(petty_cash_holder.petty_cash_balance, 1000.00) + + def test_account_invoice_1(self): + # Check Petty Cash without partner + with self.assertRaises(ValidationError): + invoice = self.env['account.invoice'].create({ + 'account_id': self.account_id.id, + 'type': 'in_invoice', + 'is_petty_cash': True, + }) + invoice._check_petty_cash_amount() + invoice._onchange_is_petty_cash() + + def test_account_invoice_2(self): + # Select partner not petty cash holder > check Petty Cash + with self.assertRaises(ValidationError): + invoice = self.env['account.invoice'].create({ + 'partner_id': self.partner_1.id, + 'account_id': self.account_id.id, + 'type': 'in_invoice', + 'is_petty_cash': True, + }) + invoice._check_petty_cash_amount() + invoice._onchange_is_petty_cash() + + def test_account_invoice_3(self): + petty_cash_holder = self.create_petty_cash_holder(self.partner_1) + self.assertEqual(petty_cash_holder.petty_cash_balance, 0.00) + product = self.env.ref('product.product_product_4') + + # Select petty cash holder > check Petty Cash + invoice = self.env['account.invoice'].create({ + 'partner_id': self.partner_1.id, + 'account_id': self.account_id.id, + 'type': 'in_invoice', + 'is_petty_cash': True, + }) + self.env['account.invoice.line'].create({ + 'product_id': product.id, + 'quantity': 1.000, + 'price_unit': 300.00, + 'invoice_id': invoice.id, + 'name': 'something', + 'account_id': self.account_id.id, + }) + invoice._check_petty_cash_amount() + invoice._onchange_is_petty_cash() + + def test_account_invoice_4(self): + petty_cash_holder = self.create_petty_cash_holder(self.partner_1) + self.assertEqual(petty_cash_holder.petty_cash_balance, 0.00) + + # Test Amount > Max Limit - Balance + invoice = self.env['account.invoice'].create({ + 'partner_id': self.partner_1.id, + 'account_id': self.account_id.id, + 'type': 'in_invoice', + 'is_petty_cash': True, + }) + self.env['account.invoice.line'].create({ + 'name': 'Petty Cash', + 'account_id': self.petty_cash_account_id.id, + 'invoice_id': invoice.id, + 'quantity': 1.000, + 'price_unit': 2000.00, + }) + self.assertEqual(len(invoice.invoice_line_ids), 1) + with self.assertRaises(ValidationError): + invoice._check_petty_cash_amount() + invoice._onchange_is_petty_cash() + + def test_expense_sheet(self): + petty_cash_holder = self.create_petty_cash_holder(self.partner_1) + self.assertEqual(petty_cash_holder.petty_cash_balance, 0.00) + + with self.assertRaises(ValidationError): + expense_report = self.env['hr.expense.sheet'].create({ + 'name': 'Expense Report - Test', + 'employee_id': self.employee_id.id, + }) + expense = self.env['hr.expense'].create({ + 'name': 'Expense - Test', + 'employee_id': self.employee_id.id, + 'product_id': self.product_id.id, + 'unit_amount': 500.00, + 'sheet_id': expense_report.id, + 'payment_mode': 'petty_cash', + 'petty_cash_id': petty_cash_holder.id, + }) + expense._onchange_product_id() + + # Submitted to Manager + expense_report.action_submit_sheet() + self.assertEquals(expense_report.state, 'submit') + + # Approve + expense_report.approve_expense_sheets() + self.assertEquals(expense_report.state, 'approve') + + # Create Expense Entries + expense_report.action_sheet_move_create() + self.assertEquals(expense_report.state, 'done') + self.assertTrue( + expense_report.account_move_id.id, 'Expense Entry is not created') + + def test_a_expense(self): + petty_cash_holder = self.create_petty_cash_holder(self.partner_1) + + with self.assertRaises(ValidationError): + expense_report = self.env['hr.expense.sheet'].create({ + 'name': 'Expense Report - Test', + 'employee_id': self.employee_id.id, + }) + expense = self.env['hr.expense'].create({ + 'name': 'Expense - Test', + 'employee_id': self.employee_id.id, + 'product_id': self.product_id.id, + 'unit_amount': 500.00, + 'sheet_id': expense_report.id, + 'payment_mode': 'petty_cash', + 'petty_cash_id': petty_cash_holder.id, + }) + expense._onchange_product_id() + + # Submitted to Manager + expense_report.action_submit_sheet() + self.assertEquals(expense_report.state, 'submit') + + # Approve + expense_report.approve_expense_sheets() + self.assertEquals(expense_report.state, 'approve') + + # Create Expense Entries + expense_report.action_sheet_move_create() + self.assertEquals(expense_report.state, 'done') + self.assertTrue( + expense_report.account_move_id.id, 'Expense Entry is not created') + + def test_multiexpense(self): + petty_cash_holder = self.create_petty_cash_holder(self.partner_1, 1000) + + expense_1 = self.env['hr.expense'].create({ + 'name': 'Expense 1 - Test', + 'employee_id': self.employee_id.id, + 'product_id': self.product_id.id, + 'unit_amount': 500.00, + 'payment_mode': 'petty_cash', + 'petty_cash_id': petty_cash_holder.id, + }) + expense_1._onchange_product_id() + expense_2 = self.env['hr.expense'].create({ + 'name': 'Expense 2 - Test', + 'employee_id': self.employee_id.id, + 'product_id': self.product_id.id, + 'unit_amount': 500.00, + 'payment_mode': 'petty_cash', + 'petty_cash_id': petty_cash_holder.id, + }) + expense_2._onchange_product_id() + expense = self.env['hr.expense'].search([('id', 'in', ( + expense_1.id, expense_2.id))]) + expense.action_submit_expenses() + + def test_multiexpense_multipettycashholder(self): + pc_holder_1 = self.create_petty_cash_holder(self.partner_1, 1000) + pc_holder_2 = self.create_petty_cash_holder(self.partner_2, 1000) + expense_1 = self.env['hr.expense'].create({ + 'name': 'Expense 1 - Test', + 'employee_id': self.employee_id.id, + 'product_id': self.product_id.id, + 'unit_amount': 700.00, + 'payment_mode': 'petty_cash', + 'petty_cash_id': pc_holder_1.id, + }) + expense_1._onchange_product_id() + expense_2 = self.env['hr.expense'].create({ + 'name': 'Expense 2 - Test', + 'employee_id': self.employee_id.id, + 'product_id': self.product_id.id, + 'unit_amount': 700.00, + 'payment_mode': 'petty_cash', + 'petty_cash_id': pc_holder_2.id, + }) + expense_2._onchange_product_id() + expenses = self.env['hr.expense'].search([( + 'id', 'in', (expense_1.id, expense_2.id))]) + with self.assertRaises(ValidationError): + expenses.action_submit_expenses() diff --git a/hr_expense_petty_cash/views/account_invoice_views.xml b/hr_expense_petty_cash/views/account_invoice_views.xml new file mode 100644 index 000000000..58a0098cc --- /dev/null +++ b/hr_expense_petty_cash/views/account_invoice_views.xml @@ -0,0 +1,15 @@ + + + + + account.invoice.supplier.form + account.invoice + + + + + + + + + diff --git a/hr_expense_petty_cash/views/hr_expense_sheet_views.xml b/hr_expense_petty_cash/views/hr_expense_sheet_views.xml new file mode 100644 index 000000000..d7db42cd9 --- /dev/null +++ b/hr_expense_petty_cash/views/hr_expense_sheet_views.xml @@ -0,0 +1,30 @@ + + + + + view.hr.expense.sheet.form.inherit + hr.expense.sheet + + + + + + + + + + + hr.expense.sheet.filter.inherit + hr.expense.sheet + + + + + + + + + + + + diff --git a/hr_expense_petty_cash/views/hr_expense_views.xml b/hr_expense_petty_cash/views/hr_expense_views.xml new file mode 100644 index 000000000..06ad59b73 --- /dev/null +++ b/hr_expense_petty_cash/views/hr_expense_views.xml @@ -0,0 +1,32 @@ + + + + + hr.expense.view.form.inherit + hr.expense + + + +
+ +
+
+
+
+ + + + hr.expense.filter.inherit + hr.expense + + + + + + + + + + + +
diff --git a/hr_expense_petty_cash/views/petty_cash_views.xml b/hr_expense_petty_cash/views/petty_cash_views.xml new file mode 100644 index 000000000..c9cdc2d74 --- /dev/null +++ b/hr_expense_petty_cash/views/petty_cash_views.xml @@ -0,0 +1,92 @@ + + + + + petty.cash.form + petty.cash + +
+ + + + + + + + + + + + +
+
+
+ + + petty.cash.list + petty.cash + + + + + + + + + + + + petty.cash.kanban + petty.cash + + + + + + +
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+ + + petty.cash.search + petty.cash + + + + + + + + + Petty Cash + petty.cash + form + tree,kanban,form + + + +

+ Create a new petty cash holder +

+
+
+ + + +
From 34d9df479bddba089f73c98b194d1004e5e17964 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Tue, 17 Mar 2020 08:13:04 +0000 Subject: [PATCH 02/41] [UPD] Update hr_expense_petty_cash.pot --- .../i18n/hr_expense_petty_cash.pot | 178 ++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot diff --git a/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot b/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot new file mode 100644 index 000000000..911db0247 --- /dev/null +++ b/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot @@ -0,0 +1,178 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * hr_expense_petty_cash +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: hr_expense_petty_cash +#: code:addons/hr_expense_petty_cash/models/account_invoice.py:25 +#: code:addons/hr_expense_petty_cash/models/account_invoice.py:74 +#, python-format +msgid "%s is not a petty cash holder" +msgstr "" + +#. module: hr_expense_petty_cash +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash__petty_cash_balance +#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_petty_cash_list +msgid "Balance" +msgstr "" + +#. module: hr_expense_petty_cash +#: selection:hr.expense,payment_mode:0 +msgid "Company" +msgstr "" + +#. module: hr_expense_petty_cash +#: model_terms:ir.actions.act_window,help:hr_expense_petty_cash.action_petty_cash +msgid "Create a new petty cash holder" +msgstr "" + +#. module: hr_expense_petty_cash +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash__create_uid +msgid "Created by" +msgstr "" + +#. module: hr_expense_petty_cash +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash__create_date +msgid "Created on" +msgstr "" + +#. module: hr_expense_petty_cash +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash__display_name +msgid "Display Name" +msgstr "" + +#. module: hr_expense_petty_cash +#: selection:hr.expense,payment_mode:0 +msgid "Employee (to reimburse)" +msgstr "" + +#. module: hr_expense_petty_cash +#: model:ir.model,name:hr_expense_petty_cash.model_hr_expense +msgid "Expense" +msgstr "" + +#. module: hr_expense_petty_cash +#: model:ir.model,name:hr_expense_petty_cash.model_hr_expense_sheet +msgid "Expense Report" +msgstr "" + +#. module: hr_expense_petty_cash +#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_petty_cash_search +msgid "Group By" +msgstr "" + +#. module: hr_expense_petty_cash +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash__id +msgid "ID" +msgstr "" + +#. module: hr_expense_petty_cash +#: model:ir.model,name:hr_expense_petty_cash.model_account_invoice +msgid "Invoice" +msgstr "" + +#. module: hr_expense_petty_cash +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash____last_update +msgid "Last Modified on" +msgstr "" + +#. module: hr_expense_petty_cash +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: hr_expense_petty_cash +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash__write_date +msgid "Last Updated on" +msgstr "" + +#. module: hr_expense_petty_cash +#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_petty_cash_list +msgid "Limit" +msgstr "" + +#. module: hr_expense_petty_cash +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash__petty_cash_limit +msgid "Max Limit" +msgstr "" + +#. module: hr_expense_petty_cash +#: code:addons/hr_expense_petty_cash/models/hr_expense_sheet.py:50 +#, python-format +msgid "Not enough money in petty cash holder.\n" +"You are requesting %s%s, but the balance is %s%s." +msgstr "" + +#. module: hr_expense_petty_cash +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_hr_expense__payment_mode +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_hr_expense_sheet__payment_mode +msgid "Paid By" +msgstr "" + +#. module: hr_expense_petty_cash +#: selection:hr.expense,payment_mode:0 +#: model:ir.actions.act_window,name:hr_expense_petty_cash.action_petty_cash +#: model:ir.model,name:hr_expense_petty_cash.model_petty_cash +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_account_invoice__is_petty_cash +#: model:ir.ui.menu,name:hr_expense_petty_cash.menu_petty_cash +#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_hr_expense_filter_inherit +#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_hr_expense_sheet_filter_inherit +#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_petty_cash_form +#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_petty_cash_list +#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_petty_cash_search +msgid "Petty Cash" +msgstr "" + +#. module: hr_expense_petty_cash +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash__account_id +msgid "Petty Cash Account" +msgstr "" + +#. module: hr_expense_petty_cash +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash__partner_id +#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_hr_expense_filter_inherit +#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_hr_expense_sheet_filter_inherit +msgid "Petty Cash Holder" +msgstr "" + +#. module: hr_expense_petty_cash +#: sql_constraint:petty.cash:0 +msgid "Petty Cash Holder must be unique!" +msgstr "" + +#. module: hr_expense_petty_cash +#: code:addons/hr_expense_petty_cash/models/account_invoice.py:39 +#, python-format +msgid "Petty Cash balance is %s %s.\n" +"Max amount to add is %s %s." +msgstr "" + +#. module: hr_expense_petty_cash +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_hr_expense__petty_cash_id +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_hr_expense_sheet__petty_cash_id +msgid "Petty cash holder" +msgstr "" + +#. module: hr_expense_petty_cash +#: code:addons/hr_expense_petty_cash/models/account_invoice.py:69 +#, python-format +msgid "Please select petty cash holder" +msgstr "" + +#. module: hr_expense_petty_cash +#: code:addons/hr_expense_petty_cash/models/hr_expense.py:35 +#: code:addons/hr_expense_petty_cash/models/hr_expense_sheet.py:33 +#, python-format +msgid "You cannot create report from many petty cash holders." +msgstr "" + From f6bb3c038e3bc1410b0ddc5595b1d5f0b83fd4a3 Mon Sep 17 00:00:00 2001 From: Saran440 Date: Fri, 28 Aug 2020 16:26:10 +0700 Subject: [PATCH 03/41] [ENH] add journal in petty cash --- hr_expense_petty_cash/README.rst | 8 +- .../models/account_invoice.py | 4 + .../models/hr_expense_sheet.py | 14 + hr_expense_petty_cash/models/petty_cash.py | 3 + hr_expense_petty_cash/readme/CONTRIBUTORS.rst | 1 + hr_expense_petty_cash/readme/DESCRIPTION.rst | 2 +- hr_expense_petty_cash/readme/USAGE.rst | 5 +- .../static/description/index.html | 7 +- .../tests/test_hr_expense_petty_cash.py | 314 ++++++------------ .../views/hr_expense_sheet_views.xml | 3 + .../views/petty_cash_views.xml | 2 + 11 files changed, 146 insertions(+), 217 deletions(-) diff --git a/hr_expense_petty_cash/README.rst b/hr_expense_petty_cash/README.rst index 86a3160a5..d55347de9 100644 --- a/hr_expense_petty_cash/README.rst +++ b/hr_expense_petty_cash/README.rst @@ -30,7 +30,7 @@ This module work about expense that paid by petty cash. General Process: #. Create Petty Cash Holder -#. Transfer cash to Petty Cash Holder By Vendor bill +#. Transfer cash to Petty Cash Holder #. You can create expense paid by petty cash and select petty cash holder. #. Then balance of petty cash holder less than amount of expense, you must transfer cash to petty cash holder before Submit Report to Manager. @@ -59,7 +59,7 @@ Usage #. Go to Invoicing > Configuration > Petty Cash #. Create a new petty cash holder -#. Select Petty Cash Account +#. Select Petty Cash Account and Journal (optional) **Add Balance for Petty Cash Holder** @@ -80,6 +80,9 @@ Usage #. Create a new expense report #. Select or Create expenses Paid by Petty Cash and same Petty Cash Holder +Note : Bill and Expense will default journal from petty cash holder, +if you configure journal in petty cash holder. + Bug Tracker =========== @@ -104,6 +107,7 @@ Contributors * `Ecosoft `__: * Pimolnat Suntian + * Saran Lim. Maintainers ~~~~~~~~~~~ diff --git a/hr_expense_petty_cash/models/account_invoice.py b/hr_expense_petty_cash/models/account_invoice.py index 809f1d240..96d88f119 100644 --- a/hr_expense_petty_cash/models/account_invoice.py +++ b/hr_expense_petty_cash/models/account_invoice.py @@ -64,6 +64,7 @@ def _add_petty_cash_invoice_line(self, petty_cash): @api.onchange('is_petty_cash', 'partner_id') def _onchange_is_petty_cash(self): self.invoice_line_ids = False + ctx = self._context.copy() if self.is_petty_cash: if not self.partner_id: raise ValidationError(_('Please select petty cash holder')) @@ -74,3 +75,6 @@ def _onchange_is_petty_cash(self): raise ValidationError(_('%s is not a petty cash holder') % self.partner_id.name) self._add_petty_cash_invoice_line(petty_cash) + if petty_cash.journal_id: + ctx.update({'default_journal_id': petty_cash.journal_id.id}) + self.journal_id = self.with_context(ctx)._default_journal() diff --git a/hr_expense_petty_cash/models/hr_expense_sheet.py b/hr_expense_petty_cash/models/hr_expense_sheet.py index 84f862a01..6ea8a1367 100644 --- a/hr_expense_petty_cash/models/hr_expense_sheet.py +++ b/hr_expense_petty_cash/models/hr_expense_sheet.py @@ -8,6 +8,17 @@ class HrExpenseSheet(models.Model): _inherit = 'hr.expense.sheet' + @api.model + def _default_journal_id(self): + """ Update expense journal from petty cash """ + journal = super()._default_journal_id() + petty_cash_obj = self.env['petty.cash'] + petty_cash = self._context.get('default_petty_cash_id', False) + if petty_cash: + petty_cash_id = petty_cash_obj.browse(petty_cash) + journal = petty_cash_id.journal_id.id or journal + return journal + payment_mode = fields.Selection( selection_add=[('petty_cash', 'Petty Cash')], ) @@ -18,6 +29,9 @@ class HrExpenseSheet(models.Model): readonly=True, compute='_compute_petty_cash', ) + journal_id = fields.Many2one( + default=_default_journal_id + ) @api.depends('expense_line_ids', 'payment_mode') def _compute_petty_cash(self): diff --git a/hr_expense_petty_cash/models/petty_cash.py b/hr_expense_petty_cash/models/petty_cash.py index e160d2e5a..6cec5a7e4 100644 --- a/hr_expense_petty_cash/models/petty_cash.py +++ b/hr_expense_petty_cash/models/petty_cash.py @@ -28,6 +28,9 @@ class PettyCash(models.Model): string='Balance', compute='_compute_petty_cash_balance', ) + journal_id = fields.Many2one( + comodel_name='account.journal', + ) _sql_constraints = [ ('partner_uniq', 'unique(partner_id)', 'Petty Cash Holder must be unique!'), diff --git a/hr_expense_petty_cash/readme/CONTRIBUTORS.rst b/hr_expense_petty_cash/readme/CONTRIBUTORS.rst index ea63aa7bc..8b17ebf09 100644 --- a/hr_expense_petty_cash/readme/CONTRIBUTORS.rst +++ b/hr_expense_petty_cash/readme/CONTRIBUTORS.rst @@ -1,3 +1,4 @@ * `Ecosoft `__: * Pimolnat Suntian + * Saran Lim. diff --git a/hr_expense_petty_cash/readme/DESCRIPTION.rst b/hr_expense_petty_cash/readme/DESCRIPTION.rst index c3429b393..9aad21d9a 100644 --- a/hr_expense_petty_cash/readme/DESCRIPTION.rst +++ b/hr_expense_petty_cash/readme/DESCRIPTION.rst @@ -3,6 +3,6 @@ This module work about expense that paid by petty cash. General Process: #. Create Petty Cash Holder -#. Transfer cash to Petty Cash Holder By Vendor bill +#. Transfer cash to Petty Cash Holder (by using Vendor Bill) #. You can create expense paid by petty cash and select petty cash holder. #. Then balance of petty cash holder less than amount of expense, you must transfer cash to petty cash holder before Submit Report to Manager. diff --git a/hr_expense_petty_cash/readme/USAGE.rst b/hr_expense_petty_cash/readme/USAGE.rst index c7afde627..ad13cb768 100644 --- a/hr_expense_petty_cash/readme/USAGE.rst +++ b/hr_expense_petty_cash/readme/USAGE.rst @@ -2,7 +2,7 @@ #. Go to Invoicing > Configuration > Petty Cash #. Create a new petty cash holder -#. Select Petty Cash Account +#. Select Petty Cash Account and Journal (optional) **Add Balance for Petty Cash Holder** @@ -22,3 +22,6 @@ #. Go to Expenses > My Expense Reports #. Create a new expense report #. Select or Create expenses Paid by Petty Cash and same Petty Cash Holder + +Note : Bill and Expense will default journal from petty cash holder, +if you configure journal in petty cash holder. diff --git a/hr_expense_petty_cash/static/description/index.html b/hr_expense_petty_cash/static/description/index.html index 85e04f445..b15a391f3 100644 --- a/hr_expense_petty_cash/static/description/index.html +++ b/hr_expense_petty_cash/static/description/index.html @@ -372,7 +372,7 @@

Petty Cash

General Process:

  1. Create Petty Cash Holder
  2. -
  3. Transfer cash to Petty Cash Holder By Vendor bill
  4. +
  5. Transfer cash to Petty Cash Holder
  6. You can create expense paid by petty cash and select petty cash holder.
  7. Then balance of petty cash holder less than amount of expense, you must transfer cash to petty cash holder before Submit Report to Manager.
@@ -409,7 +409,7 @@

Usage

  1. Go to Invoicing > Configuration > Petty Cash
  2. Create a new petty cash holder
  3. -
  4. Select Petty Cash Account
  5. +
  6. Select Petty Cash Account and Journal (optional)

Add Balance for Petty Cash Holder

    @@ -430,6 +430,8 @@

    Usage

  1. Create a new expense report
  2. Select or Create expenses Paid by Petty Cash and same Petty Cash Holder
+

Note : Bill and Expense will default journal from petty cash holder, +if you configure journal in petty cash holder.

Bug Tracker

@@ -452,6 +454,7 @@

Contributors

diff --git a/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py b/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py index 97c2be8bd..d3d13ba2e 100644 --- a/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py +++ b/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py @@ -2,256 +2,148 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo.exceptions import ValidationError -from odoo.tests import common +from odoo.tests.common import TransactionCase, Form -class TestHrExpensePettyCash(common.TransactionCase): +class TestHrExpensePettyCash(TransactionCase): def setUp(self): super(TestHrExpensePettyCash, self).setUp() - # Create an employee self.employee_id = self.env.ref('hr.employee_admin') - - # Create a product self.product_id = self.env.ref('hr_expense.air_ticket') - - # Create an account payable - payable_type = self.env.ref('account.data_account_type_payable') + self.partner_1 = self.env.ref('base.res_partner_1') + self.partner_2 = self.env.ref('base.res_partner_2') + self.payable_type = self.env.ref('account.data_account_type_payable') + self.liquidity_type = \ + self.env.ref('account.data_account_type_liquidity') self.account_id = self.env['account.account'].create({ 'code': '111111', 'name': 'Payable - Test', - 'user_type_id': payable_type.id, + 'user_type_id': self.payable_type.id, 'reconcile': True, }) + self.petty_cash_journal_id = self.env['account.journal'].create({ + 'code': 'PC', + 'name': 'Petty Cash', + 'type': 'general' + }) # Create a Petty Cash Account - liquidity_type = self.env.ref('account.data_account_type_liquidity') self.petty_cash_account_id = self.env['account.account'].create({ 'code': '000000', 'name': 'Petty Cash - Test', - 'user_type_id': liquidity_type.id, + 'user_type_id': self.liquidity_type.id, }) + self.petty_cash_holder = self._create_petty_cash_holder(self.partner_1) - # Create Partner - self.partner_1 = self.env['res.partner'].create({ - 'name': 'Partner 1 - Test', - }) - self.partner_2 = self.env['res.partner'].create({ - 'name': 'Partner 2 - Test', - }) - - def create_petty_cash_holder(self, partner, petty_cash_balance=False): + def _create_petty_cash_holder(self, partner, petty_cash_balance=False): petty_cash_holder = self.env['petty.cash'].create({ 'partner_id': partner.id, 'account_id': self.petty_cash_account_id.id, - 'petty_cash_limit': 1000.00, + 'petty_cash_limit': 1000.0, 'petty_cash_balance': petty_cash_balance or 0.0, }) return petty_cash_holder - def test_petty_cash(self): - petty_cash_holder = self.create_petty_cash_holder(self.partner_1) - self.assertEqual(petty_cash_holder.petty_cash_balance, 0.00) + def _create_invoice(self, partner=False): invoice = self.env['account.invoice'].create({ - 'partner_id': self.partner_1.id, + 'partner_id': partner, 'account_id': self.account_id.id, 'type': 'in_invoice', - 'is_petty_cash': True, - }) - self.env['account.invoice.line'].create({ - 'name': 'Petty Cash', - 'account_id': self.petty_cash_account_id.id, - 'invoice_id': invoice.id, - 'quantity': 1.000, - 'price_unit': 1000.00, }) - invoice.action_invoice_open() - petty_cash_holder._compute_petty_cash_balance() - self.assertEqual(petty_cash_holder.petty_cash_balance, 1000.00) - - def test_account_invoice_1(self): - # Check Petty Cash without partner - with self.assertRaises(ValidationError): - invoice = self.env['account.invoice'].create({ - 'account_id': self.account_id.id, - 'type': 'in_invoice', - 'is_petty_cash': True, - }) - invoice._check_petty_cash_amount() - invoice._onchange_is_petty_cash() - - def test_account_invoice_2(self): - # Select partner not petty cash holder > check Petty Cash - with self.assertRaises(ValidationError): - invoice = self.env['account.invoice'].create({ - 'partner_id': self.partner_1.id, - 'account_id': self.account_id.id, - 'type': 'in_invoice', - 'is_petty_cash': True, - }) - invoice._check_petty_cash_amount() - invoice._onchange_is_petty_cash() - - def test_account_invoice_3(self): - petty_cash_holder = self.create_petty_cash_holder(self.partner_1) - self.assertEqual(petty_cash_holder.petty_cash_balance, 0.00) - product = self.env.ref('product.product_product_4') + return invoice - # Select petty cash holder > check Petty Cash - invoice = self.env['account.invoice'].create({ - 'partner_id': self.partner_1.id, - 'account_id': self.account_id.id, - 'type': 'in_invoice', - 'is_petty_cash': True, + def _create_expense(self, amount, mode, petty_cash_holder=False): + expense = self.env['hr.expense'].create({ + 'name': 'Expense - Test', + 'employee_id': self.employee_id.id, + 'product_id': self.product_id.id, + 'unit_amount': amount, + 'payment_mode': mode, + 'petty_cash_id': petty_cash_holder, }) - self.env['account.invoice.line'].create({ - 'product_id': product.id, - 'quantity': 1.000, - 'price_unit': 300.00, - 'invoice_id': invoice.id, - 'name': 'something', - 'account_id': self.account_id.id, + return expense + + def _create_expense_sheet(self, expense): + expense_sheet = self.env['hr.expense.sheet'].with_context( + {'default_petty_cash_id': self.petty_cash_holder.id} + ).create({ + 'name': expense.name, + 'employee_id': expense.employee_id.id, + 'expense_line_ids': [(6, 0, [expense.id])], }) - invoice._check_petty_cash_amount() - invoice._onchange_is_petty_cash() + return expense_sheet - def test_account_invoice_4(self): - petty_cash_holder = self.create_petty_cash_holder(self.partner_1) - self.assertEqual(petty_cash_holder.petty_cash_balance, 0.00) - - # Test Amount > Max Limit - Balance - invoice = self.env['account.invoice'].create({ - 'partner_id': self.partner_1.id, - 'account_id': self.account_id.id, - 'type': 'in_invoice', - 'is_petty_cash': True, - }) - self.env['account.invoice.line'].create({ - 'name': 'Petty Cash', - 'account_id': self.petty_cash_account_id.id, - 'invoice_id': invoice.id, - 'quantity': 1.000, - 'price_unit': 2000.00, - }) + def test_01_create_petty_cash_holder(self): + self.assertEqual(self.petty_cash_holder.petty_cash_balance, 0.00) + # no partner and check petty cash + invoice = self._create_invoice() + with self.assertRaises(ValidationError): + with Form(invoice) as inv: + inv.is_petty_cash = True + # partner is not holder. + invoice = self._create_invoice(self.partner_2.id) + with self.assertRaises(ValidationError): + with Form(invoice) as inv: + inv.is_petty_cash = True + invoice = self._create_invoice(self.partner_1.id) + with Form(invoice) as inv: + inv.is_petty_cash = True self.assertEqual(len(invoice.invoice_line_ids), 1) + self.assertEqual(invoice.invoice_line_ids.price_unit, 1000.0) + + invoice.invoice_line_ids.price_unit = 1500.0 with self.assertRaises(ValidationError): invoice._check_petty_cash_amount() - invoice._onchange_is_petty_cash() - def test_expense_sheet(self): - petty_cash_holder = self.create_petty_cash_holder(self.partner_1) - self.assertEqual(petty_cash_holder.petty_cash_balance, 0.00) + invoice.invoice_line_ids.price_unit = 1000.0 + invoice.action_invoice_open() + self.assertEqual(self.petty_cash_holder.petty_cash_balance, 1000.0) + def test_02_create_expense_petty_cash(self): + invoice = self._create_invoice(self.partner_1.id) + with Form(invoice) as inv: + inv.is_petty_cash = True + inv.invoice_line_ids.price_unit = 1000.0 + invoice.action_invoice_open() + self.assertEqual(self.petty_cash_holder.petty_cash_balance, 1000.0) + # Create expense + expense_own = self._create_expense(400.0, 'own_account') + expense_petty_cash = self._create_expense( + 400.0, 'petty_cash', self.petty_cash_holder.id) + expense_report = expense_own + expense_petty_cash with self.assertRaises(ValidationError): - expense_report = self.env['hr.expense.sheet'].create({ - 'name': 'Expense Report - Test', - 'employee_id': self.employee_id.id, - }) - expense = self.env['hr.expense'].create({ - 'name': 'Expense - Test', - 'employee_id': self.employee_id.id, - 'product_id': self.product_id.id, - 'unit_amount': 500.00, - 'sheet_id': expense_report.id, - 'payment_mode': 'petty_cash', - 'petty_cash_id': petty_cash_holder.id, - }) - expense._onchange_product_id() - - # Submitted to Manager - expense_report.action_submit_sheet() - self.assertEquals(expense_report.state, 'submit') - - # Approve - expense_report.approve_expense_sheets() - self.assertEquals(expense_report.state, 'approve') - - # Create Expense Entries - expense_report.action_sheet_move_create() - self.assertEquals(expense_report.state, 'done') - self.assertTrue( - expense_report.account_move_id.id, 'Expense Entry is not created') - - def test_a_expense(self): - petty_cash_holder = self.create_petty_cash_holder(self.partner_1) - + expense_report.action_submit_expenses() + result = expense_petty_cash.action_submit_expenses() + default_expense_line_ids = \ + result.get('context').get('default_expense_line_ids') + sheet = self._create_expense_sheet(expense_petty_cash) + self.assertEqual(sheet.expense_line_ids.ids, default_expense_line_ids) + self.assertEqual(sheet.state, 'draft') with self.assertRaises(ValidationError): - expense_report = self.env['hr.expense.sheet'].create({ - 'name': 'Expense Report - Test', - 'employee_id': self.employee_id.id, - }) - expense = self.env['hr.expense'].create({ - 'name': 'Expense - Test', - 'employee_id': self.employee_id.id, - 'product_id': self.product_id.id, - 'unit_amount': 500.00, - 'sheet_id': expense_report.id, - 'payment_mode': 'petty_cash', - 'petty_cash_id': petty_cash_holder.id, - }) - expense._onchange_product_id() - - # Submitted to Manager - expense_report.action_submit_sheet() - self.assertEquals(expense_report.state, 'submit') - - # Approve - expense_report.approve_expense_sheets() - self.assertEquals(expense_report.state, 'approve') - + sheet.expense_line_ids.unit_amount = 1600.0 + sheet.expense_line_ids.unit_amount = 400.0 + # Submitted to Manager and Approve + sheet.action_submit_sheet() + self.assertEquals(sheet.state, 'submit') + sheet.approve_expense_sheets() + self.assertEquals(sheet.state, 'approve') # Create Expense Entries - expense_report.action_sheet_move_create() - self.assertEquals(expense_report.state, 'done') - self.assertTrue( - expense_report.account_move_id.id, 'Expense Entry is not created') - - def test_multiexpense(self): - petty_cash_holder = self.create_petty_cash_holder(self.partner_1, 1000) - - expense_1 = self.env['hr.expense'].create({ - 'name': 'Expense 1 - Test', - 'employee_id': self.employee_id.id, - 'product_id': self.product_id.id, - 'unit_amount': 500.00, - 'payment_mode': 'petty_cash', - 'petty_cash_id': petty_cash_holder.id, - }) - expense_1._onchange_product_id() - expense_2 = self.env['hr.expense'].create({ - 'name': 'Expense 2 - Test', - 'employee_id': self.employee_id.id, - 'product_id': self.product_id.id, - 'unit_amount': 500.00, - 'payment_mode': 'petty_cash', - 'petty_cash_id': petty_cash_holder.id, - }) - expense_2._onchange_product_id() - expense = self.env['hr.expense'].search([('id', 'in', ( - expense_1.id, expense_2.id))]) - expense.action_submit_expenses() - - def test_multiexpense_multipettycashholder(self): - pc_holder_1 = self.create_petty_cash_holder(self.partner_1, 1000) - pc_holder_2 = self.create_petty_cash_holder(self.partner_2, 1000) - expense_1 = self.env['hr.expense'].create({ - 'name': 'Expense 1 - Test', - 'employee_id': self.employee_id.id, - 'product_id': self.product_id.id, - 'unit_amount': 700.00, - 'payment_mode': 'petty_cash', - 'petty_cash_id': pc_holder_1.id, - }) - expense_1._onchange_product_id() - expense_2 = self.env['hr.expense'].create({ - 'name': 'Expense 2 - Test', - 'employee_id': self.employee_id.id, - 'product_id': self.product_id.id, - 'unit_amount': 700.00, - 'payment_mode': 'petty_cash', - 'petty_cash_id': pc_holder_2.id, - }) - expense_2._onchange_product_id() - expenses = self.env['hr.expense'].search([( - 'id', 'in', (expense_1.id, expense_2.id))]) - with self.assertRaises(ValidationError): - expenses.action_submit_expenses() + sheet.action_sheet_move_create() + self.assertEquals(sheet.state, 'done') + self.assertTrue(sheet.account_move_id.id) + self.assertEquals(self.petty_cash_holder.petty_cash_balance, 600.0) + + def test_03_create_expense_petty_cash_with_journal(self): + self.petty_cash_holder.journal_id = self.petty_cash_journal_id + invoice = self._create_invoice(self.partner_1.id) + with Form(invoice) as inv: + inv.is_petty_cash = True + inv.invoice_line_ids.price_unit = 1000.0 + self.assertEqual(invoice.journal_id, self.petty_cash_holder.journal_id) + invoice.action_invoice_open() + self.assertEqual(self.petty_cash_holder.petty_cash_balance, 1000.0) + expense_petty_cash = self._create_expense( + 400.0, 'petty_cash', self.petty_cash_holder.id) + sheet = self._create_expense_sheet(expense_petty_cash) + self.assertEqual(sheet.journal_id, self.petty_cash_holder.journal_id) diff --git a/hr_expense_petty_cash/views/hr_expense_sheet_views.xml b/hr_expense_petty_cash/views/hr_expense_sheet_views.xml index d7db42cd9..98edf298f 100644 --- a/hr_expense_petty_cash/views/hr_expense_sheet_views.xml +++ b/hr_expense_petty_cash/views/hr_expense_sheet_views.xml @@ -9,6 +9,9 @@ + + {'invisible': [('payment_mode', 'not in', ['own_account', 'petty_cash'])]} + diff --git a/hr_expense_petty_cash/views/petty_cash_views.xml b/hr_expense_petty_cash/views/petty_cash_views.xml index c9cdc2d74..14b91cc3a 100644 --- a/hr_expense_petty_cash/views/petty_cash_views.xml +++ b/hr_expense_petty_cash/views/petty_cash_views.xml @@ -11,6 +11,7 @@ + @@ -29,6 +30,7 @@ + From 6b38864fdddd103fa553b175d2c5a2dcccc01228 Mon Sep 17 00:00:00 2001 From: Saran440 Date: Wed, 9 Sep 2020 15:41:49 +0700 Subject: [PATCH 04/41] [FIX] compare amount with float_compare --- hr_expense_petty_cash/models/account_invoice.py | 5 ++++- hr_expense_petty_cash/models/hr_expense_sheet.py | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/hr_expense_petty_cash/models/account_invoice.py b/hr_expense_petty_cash/models/account_invoice.py index 96d88f119..18dad9d07 100644 --- a/hr_expense_petty_cash/models/account_invoice.py +++ b/hr_expense_petty_cash/models/account_invoice.py @@ -3,6 +3,7 @@ from odoo import api, fields, models, _ from odoo.exceptions import ValidationError +from odoo.tools import float_compare class AccountInvoice(models.Model): @@ -34,7 +35,9 @@ def _check_petty_cash_amount(self): amount_company = rec.currency_id._convert( amount, company_currency, rec.company_id, rec.date_invoice or fields.Date.today()) - if amount_company > max_amount: + prec = rec.currency_id.rounding + if float_compare( + amount_company, max_amount, precision_rounding=prec) == 1: raise ValidationError( _('Petty Cash balance is %s %s.\n' 'Max amount to add is %s %s.') % diff --git a/hr_expense_petty_cash/models/hr_expense_sheet.py b/hr_expense_petty_cash/models/hr_expense_sheet.py index 6ea8a1367..61d6dbec2 100644 --- a/hr_expense_petty_cash/models/hr_expense_sheet.py +++ b/hr_expense_petty_cash/models/hr_expense_sheet.py @@ -3,6 +3,7 @@ from odoo import api, fields, models, _ from odoo.exceptions import ValidationError +from odoo.tools import float_compare class HrExpenseSheet(models.Model): @@ -59,7 +60,9 @@ def _check_petty_cash_amount(self): amount_company = rec.currency_id._convert( amount, company_currency, rec.company_id, rec.accounting_date or fields.Date.today()) - if amount_company > balance: + prec = rec.currency_id.rounding + if float_compare( + amount_company, balance, precision_rounding=prec) == 1: raise ValidationError( _('Not enough money in petty cash holder.\n' 'You are requesting %s%s, ' From ea82cef005c31ddca88995f13efd1551e74d66a9 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Tue, 15 Sep 2020 14:14:12 +0000 Subject: [PATCH 05/41] [UPD] Update hr_expense_petty_cash.pot --- .../i18n/hr_expense_petty_cash.pot | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot b/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot index 911db0247..1f91e0bf5 100644 --- a/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot +++ b/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot @@ -15,7 +15,9 @@ msgstr "" #. module: hr_expense_petty_cash #: code:addons/hr_expense_petty_cash/models/account_invoice.py:25 +#: code:addons/hr_expense_petty_cash/models/account_invoice.py:26 #: code:addons/hr_expense_petty_cash/models/account_invoice.py:74 +#: code:addons/hr_expense_petty_cash/models/account_invoice.py:78 #, python-format msgid "%s is not a petty cash holder" msgstr "" @@ -61,6 +63,11 @@ msgstr "" msgid "Expense" msgstr "" +#. module: hr_expense_petty_cash +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_hr_expense_sheet__journal_id +msgid "Expense Journal" +msgstr "" + #. module: hr_expense_petty_cash #: model:ir.model,name:hr_expense_petty_cash.model_hr_expense_sheet msgid "Expense Report" @@ -81,6 +88,11 @@ msgstr "" msgid "Invoice" msgstr "" +#. module: hr_expense_petty_cash +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash__journal_id +msgid "Journal" +msgstr "" + #. module: hr_expense_petty_cash #: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash____last_update msgid "Last Modified on" @@ -108,6 +120,7 @@ msgstr "" #. module: hr_expense_petty_cash #: code:addons/hr_expense_petty_cash/models/hr_expense_sheet.py:50 +#: code:addons/hr_expense_petty_cash/models/hr_expense_sheet.py:67 #, python-format msgid "Not enough money in petty cash holder.\n" "You are requesting %s%s, but the balance is %s%s." @@ -152,6 +165,7 @@ msgstr "" #. module: hr_expense_petty_cash #: code:addons/hr_expense_petty_cash/models/account_invoice.py:39 +#: code:addons/hr_expense_petty_cash/models/account_invoice.py:42 #, python-format msgid "Petty Cash balance is %s %s.\n" "Max amount to add is %s %s." @@ -165,13 +179,20 @@ msgstr "" #. module: hr_expense_petty_cash #: code:addons/hr_expense_petty_cash/models/account_invoice.py:69 +#: code:addons/hr_expense_petty_cash/models/account_invoice.py:73 #, python-format msgid "Please select petty cash holder" msgstr "" +#. module: hr_expense_petty_cash +#: model:ir.model.fields,help:hr_expense_petty_cash.field_hr_expense_sheet__journal_id +msgid "The journal used when the expense is done." +msgstr "" + #. module: hr_expense_petty_cash #: code:addons/hr_expense_petty_cash/models/hr_expense.py:35 #: code:addons/hr_expense_petty_cash/models/hr_expense_sheet.py:33 +#: code:addons/hr_expense_petty_cash/models/hr_expense_sheet.py:48 #, python-format msgid "You cannot create report from many petty cash holders." msgstr "" From 736ad6085ef520fa3c8179adec0a32933195bcab Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Tue, 15 Sep 2020 14:46:15 +0000 Subject: [PATCH 06/41] [UPD] README.rst --- hr_expense_petty_cash/README.rst | 2 +- hr_expense_petty_cash/static/description/index.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hr_expense_petty_cash/README.rst b/hr_expense_petty_cash/README.rst index d55347de9..75f2a0f08 100644 --- a/hr_expense_petty_cash/README.rst +++ b/hr_expense_petty_cash/README.rst @@ -30,7 +30,7 @@ This module work about expense that paid by petty cash. General Process: #. Create Petty Cash Holder -#. Transfer cash to Petty Cash Holder +#. Transfer cash to Petty Cash Holder (by using Vendor Bill) #. You can create expense paid by petty cash and select petty cash holder. #. Then balance of petty cash holder less than amount of expense, you must transfer cash to petty cash holder before Submit Report to Manager. diff --git a/hr_expense_petty_cash/static/description/index.html b/hr_expense_petty_cash/static/description/index.html index b15a391f3..679103e39 100644 --- a/hr_expense_petty_cash/static/description/index.html +++ b/hr_expense_petty_cash/static/description/index.html @@ -372,7 +372,7 @@

Petty Cash

General Process:

  1. Create Petty Cash Holder
  2. -
  3. Transfer cash to Petty Cash Holder
  4. +
  5. Transfer cash to Petty Cash Holder (by using Vendor Bill)
  6. You can create expense paid by petty cash and select petty cash holder.
  7. Then balance of petty cash holder less than amount of expense, you must transfer cash to petty cash holder before Submit Report to Manager.
From 3e39291f50565a5fcd87f421c0a01bee5a44f8fc Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Tue, 15 Sep 2020 14:46:16 +0000 Subject: [PATCH 07/41] hr_expense_petty_cash 12.0.1.1.0 --- hr_expense_petty_cash/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hr_expense_petty_cash/__manifest__.py b/hr_expense_petty_cash/__manifest__.py index 558ee7107..774137235 100644 --- a/hr_expense_petty_cash/__manifest__.py +++ b/hr_expense_petty_cash/__manifest__.py @@ -3,7 +3,7 @@ { 'name': 'Petty Cash', - 'version': '12.0.1.0.0', + 'version': '12.0.1.1.0', 'category': 'Human Resources', 'author': 'Ecosoft, Odoo Community Association (OCA)', 'license': 'AGPL-3', From 5e670978f04ba41ed6529cb039c57a2767f9ee47 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Tue, 15 Sep 2020 15:28:03 +0000 Subject: [PATCH 08/41] [UPD] Update hr_expense_petty_cash.pot --- hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot | 6 ------ 1 file changed, 6 deletions(-) diff --git a/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot b/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot index 1f91e0bf5..de43925df 100644 --- a/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot +++ b/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot @@ -14,9 +14,7 @@ msgstr "" "Plural-Forms: \n" #. module: hr_expense_petty_cash -#: code:addons/hr_expense_petty_cash/models/account_invoice.py:25 #: code:addons/hr_expense_petty_cash/models/account_invoice.py:26 -#: code:addons/hr_expense_petty_cash/models/account_invoice.py:74 #: code:addons/hr_expense_petty_cash/models/account_invoice.py:78 #, python-format msgid "%s is not a petty cash holder" @@ -119,7 +117,6 @@ msgid "Max Limit" msgstr "" #. module: hr_expense_petty_cash -#: code:addons/hr_expense_petty_cash/models/hr_expense_sheet.py:50 #: code:addons/hr_expense_petty_cash/models/hr_expense_sheet.py:67 #, python-format msgid "Not enough money in petty cash holder.\n" @@ -164,7 +161,6 @@ msgid "Petty Cash Holder must be unique!" msgstr "" #. module: hr_expense_petty_cash -#: code:addons/hr_expense_petty_cash/models/account_invoice.py:39 #: code:addons/hr_expense_petty_cash/models/account_invoice.py:42 #, python-format msgid "Petty Cash balance is %s %s.\n" @@ -178,7 +174,6 @@ msgid "Petty cash holder" msgstr "" #. module: hr_expense_petty_cash -#: code:addons/hr_expense_petty_cash/models/account_invoice.py:69 #: code:addons/hr_expense_petty_cash/models/account_invoice.py:73 #, python-format msgid "Please select petty cash holder" @@ -191,7 +186,6 @@ msgstr "" #. module: hr_expense_petty_cash #: code:addons/hr_expense_petty_cash/models/hr_expense.py:35 -#: code:addons/hr_expense_petty_cash/models/hr_expense_sheet.py:33 #: code:addons/hr_expense_petty_cash/models/hr_expense_sheet.py:48 #, python-format msgid "You cannot create report from many petty cash holders." From 9470e56b849066b62efd530ac627b1401b0d5895 Mon Sep 17 00:00:00 2001 From: ps-tubtim Date: Thu, 1 Oct 2020 11:54:26 +0700 Subject: [PATCH 09/41] [IMP] hr_expense_petty_cash: black, isort, prettier --- hr_expense_petty_cash/__manifest__.py | 30 ++-- .../models/account_invoice.py | 90 +++++++----- hr_expense_petty_cash/models/hr_expense.py | 36 +++-- .../models/hr_expense_sheet.py | 70 +++++----- hr_expense_petty_cash/models/petty_cash.py | 43 +++--- .../tests/test_hr_expense_petty_cash.py | 130 ++++++++++-------- .../views/account_invoice_views.xml | 8 +- .../views/hr_expense_sheet_views.xml | 31 +++-- .../views/hr_expense_views.xml | 28 ++-- .../views/petty_cash_views.xml | 74 +++++----- 10 files changed, 292 insertions(+), 248 deletions(-) diff --git a/hr_expense_petty_cash/__manifest__.py b/hr_expense_petty_cash/__manifest__.py index 774137235..05d3a3081 100644 --- a/hr_expense_petty_cash/__manifest__.py +++ b/hr_expense_petty_cash/__manifest__.py @@ -2,21 +2,19 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { - 'name': 'Petty Cash', - 'version': '12.0.1.1.0', - 'category': 'Human Resources', - 'author': 'Ecosoft, Odoo Community Association (OCA)', - 'license': 'AGPL-3', - 'website': 'https://github.com/OCA/hr', - 'depends': [ - 'hr_expense', + "name": "Petty Cash", + "version": "13.0.1.0.0", + "category": "Human Resources", + "author": "Ecosoft, Odoo Community Association (OCA)", + "license": "AGPL-3", + "website": "https://github.com/OCA/hr", + "depends": ["hr_expense"], + "data": [ + "security/ir.model.access.csv", + "views/account_invoice_views.xml", + "views/hr_expense_sheet_views.xml", + "views/hr_expense_views.xml", + "views/petty_cash_views.xml", ], - 'data': [ - 'security/ir.model.access.csv', - 'views/account_invoice_views.xml', - 'views/hr_expense_sheet_views.xml', - 'views/hr_expense_views.xml', - 'views/petty_cash_views.xml', - ], - 'installable': True, + "installable": True, } diff --git a/hr_expense_petty_cash/models/account_invoice.py b/hr_expense_petty_cash/models/account_invoice.py index 18dad9d07..1ba689861 100644 --- a/hr_expense_petty_cash/models/account_invoice.py +++ b/hr_expense_petty_cash/models/account_invoice.py @@ -1,48 +1,57 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import api, fields, models, _ +from odoo import _, api, fields, models from odoo.exceptions import ValidationError from odoo.tools import float_compare class AccountInvoice(models.Model): - _inherit = 'account.invoice' + _inherit = "account.invoice" is_petty_cash = fields.Boolean( - string='Petty Cash', - readonly=True, - states={'draft': [('readonly', False)]}, + string="Petty Cash", readonly=True, states={"draft": [("readonly", False)]}, ) @api.multi - @api.constrains('invoice_line_ids') + @api.constrains("invoice_line_ids") def _check_petty_cash_amount(self): - petty_cash_env = self.env['petty.cash'] - for rec in self.filtered('is_petty_cash'): + petty_cash_env = self.env["petty.cash"] + for rec in self.filtered("is_petty_cash"): petty_cash = petty_cash_env.search( - [('partner_id', '=', rec.partner_id.id)], limit=1) + [("partner_id", "=", rec.partner_id.id)], limit=1 + ) if not petty_cash: - raise ValidationError(_('%s is not a petty cash holder') % - rec.partner_id.name) + raise ValidationError( + _("%s is not a petty cash holder") % rec.partner_id.name + ) balance = petty_cash.petty_cash_balance limit = petty_cash.petty_cash_limit max_amount = limit - balance account = petty_cash.account_id - amount = sum(rec.invoice_line_ids.filtered( - lambda l: l.account_id == account).mapped('price_subtotal')) + amount = sum( + rec.invoice_line_ids.filtered(lambda l: l.account_id == account).mapped( + "price_subtotal" + ) + ) company_currency = rec.company_id.currency_id amount_company = rec.currency_id._convert( - amount, company_currency, rec.company_id, - rec.date_invoice or fields.Date.today()) + amount, + company_currency, + rec.company_id, + rec.date_invoice or fields.Date.today(), + ) prec = rec.currency_id.rounding - if float_compare( - amount_company, max_amount, precision_rounding=prec) == 1: + if float_compare(amount_company, max_amount, precision_rounding=prec) == 1: raise ValidationError( - _('Petty Cash balance is %s %s.\n' - 'Max amount to add is %s %s.') % - ('{:,.2f}'.format(balance), company_currency.symbol, - '{:,.2f}'.format(max_amount), company_currency.symbol)) + _("Petty Cash balance is %s %s.\n" "Max amount to add is %s %s.") + % ( + "{:,.2f}".format(balance), + company_currency.symbol, + "{:,.2f}".format(max_amount), + company_currency.symbol, + ) + ) @api.multi def _add_petty_cash_invoice_line(self, petty_cash): @@ -51,33 +60,40 @@ def _add_petty_cash_invoice_line(self, petty_cash): amount = petty_cash.petty_cash_limit - petty_cash.petty_cash_balance company_currency = self.env.user.company_id.currency_id amount_doc_currency = company_currency._convert( - amount, self.currency_id, self.company_id, - self.date_invoice or fields.Date.today()) + amount, + self.currency_id, + self.company_id, + self.date_invoice or fields.Date.today(), + ) - inv_line = self.env['account.invoice.line'].new({ - 'name': petty_cash.account_id.name, - 'invoice_id': self.id, - 'account_id': petty_cash.account_id.id, - 'price_unit': amount_doc_currency, - 'quantity': 1, - }) + inv_line = self.env["account.invoice.line"].new( + { + "name": petty_cash.account_id.name, + "invoice_id": self.id, + "account_id": petty_cash.account_id.id, + "price_unit": amount_doc_currency, + "quantity": 1, + } + ) return inv_line @api.multi - @api.onchange('is_petty_cash', 'partner_id') + @api.onchange("is_petty_cash", "partner_id") def _onchange_is_petty_cash(self): self.invoice_line_ids = False ctx = self._context.copy() if self.is_petty_cash: if not self.partner_id: - raise ValidationError(_('Please select petty cash holder')) + raise ValidationError(_("Please select petty cash holder")) # Selected parenter must be petty cash holder - petty_cash = self.env['petty.cash'].search( - [('partner_id', '=', self.partner_id.id)], limit=1) + petty_cash = self.env["petty.cash"].search( + [("partner_id", "=", self.partner_id.id)], limit=1 + ) if not petty_cash: - raise ValidationError(_('%s is not a petty cash holder') % - self.partner_id.name) + raise ValidationError( + _("%s is not a petty cash holder") % self.partner_id.name + ) self._add_petty_cash_invoice_line(petty_cash) if petty_cash.journal_id: - ctx.update({'default_journal_id': petty_cash.journal_id.id}) + ctx.update({"default_journal_id": petty_cash.journal_id.id}) self.journal_id = self.with_context(ctx)._default_journal() diff --git a/hr_expense_petty_cash/models/hr_expense.py b/hr_expense_petty_cash/models/hr_expense.py index 3ab894818..8ff024b00 100644 --- a/hr_expense_petty_cash/models/hr_expense.py +++ b/hr_expense_petty_cash/models/hr_expense.py @@ -1,47 +1,45 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import api, fields, models, _ +from odoo import _, api, fields, models from odoo.exceptions import ValidationError class HrExpense(models.Model): - _inherit = 'hr.expense' + _inherit = "hr.expense" - payment_mode = fields.Selection( - selection_add=[('petty_cash', 'Petty Cash')], - ) + payment_mode = fields.Selection(selection_add=[("petty_cash", "Petty Cash")],) petty_cash_id = fields.Many2one( - string='Petty cash holder', - comodel_name='petty.cash', - ondelete='restrict', + string="Petty cash holder", + comodel_name="petty.cash", + ondelete="restrict", readonly=True, - states={'draft': [('readonly', False)]}, + states={"draft": [("readonly", False)]}, ) @api.multi def action_submit_expenses(self): res = super().action_submit_expenses() - context = res['context'] - context['default_expense_line_ids'] = self.ids - context['default_name'] = self[0].name if len(self) == 1 else '' + context = res["context"] + context["default_expense_line_ids"] = self.ids + context["default_name"] = self[0].name if len(self) == 1 else "" set_petty_cash_ids = set() for rec in self: set_petty_cash_ids.add(rec.petty_cash_id.id) if set_petty_cash_ids: if len(set_petty_cash_ids) == 1: - context['default_petty_cash_id'] = set_petty_cash_ids.pop() + context["default_petty_cash_id"] = set_petty_cash_ids.pop() return res - raise ValidationError(_('You cannot create report from ' - 'many petty cash holders.')) + raise ValidationError( + _("You cannot create report from " "many petty cash holders.") + ) @api.multi def _get_account_move_line_values(self): res = super()._get_account_move_line_values() - for expense in self.filtered( - lambda p: p.payment_mode == 'petty_cash'): + for expense in self.filtered(lambda p: p.payment_mode == "petty_cash"): line = res[expense.id][1] - line['account_id'] = expense.petty_cash_id.account_id.id - line['partner_id'] = expense.petty_cash_id.partner_id.id + line["account_id"] = expense.petty_cash_id.account_id.id + line["partner_id"] = expense.petty_cash_id.partner_id.id res[expense.id][1] = line return res diff --git a/hr_expense_petty_cash/models/hr_expense_sheet.py b/hr_expense_petty_cash/models/hr_expense_sheet.py index 61d6dbec2..478b71f23 100644 --- a/hr_expense_petty_cash/models/hr_expense_sheet.py +++ b/hr_expense_petty_cash/models/hr_expense_sheet.py @@ -1,72 +1,78 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import api, fields, models, _ +from odoo import _, api, fields, models from odoo.exceptions import ValidationError from odoo.tools import float_compare class HrExpenseSheet(models.Model): - _inherit = 'hr.expense.sheet' + _inherit = "hr.expense.sheet" @api.model def _default_journal_id(self): """ Update expense journal from petty cash """ journal = super()._default_journal_id() - petty_cash_obj = self.env['petty.cash'] - petty_cash = self._context.get('default_petty_cash_id', False) + petty_cash_obj = self.env["petty.cash"] + petty_cash = self._context.get("default_petty_cash_id", False) if petty_cash: petty_cash_id = petty_cash_obj.browse(petty_cash) journal = petty_cash_id.journal_id.id or journal return journal - payment_mode = fields.Selection( - selection_add=[('petty_cash', 'Petty Cash')], - ) + payment_mode = fields.Selection(selection_add=[("petty_cash", "Petty Cash")],) petty_cash_id = fields.Many2one( - string='Petty cash holder', - comodel_name='petty.cash', - ondelete='restrict', + string="Petty cash holder", + comodel_name="petty.cash", + ondelete="restrict", readonly=True, - compute='_compute_petty_cash', - ) - journal_id = fields.Many2one( - default=_default_journal_id + compute="_compute_petty_cash", ) + journal_id = fields.Many2one(default=_default_journal_id) - @api.depends('expense_line_ids', 'payment_mode') + @api.depends("expense_line_ids", "payment_mode") def _compute_petty_cash(self): for rec in self: - if rec.payment_mode == 'petty_cash': + if rec.payment_mode == "petty_cash": set_petty_cash_ids = set() for line in rec.expense_line_ids: set_petty_cash_ids.add(line.petty_cash_id.id) if len(set_petty_cash_ids) == 1: - rec.petty_cash_id = rec.env['petty.cash'].browse( - set_petty_cash_ids.pop()) + rec.petty_cash_id = rec.env["petty.cash"].browse( + set_petty_cash_ids.pop() + ) else: - raise ValidationError(_('You cannot create report from ' - 'many petty cash holders.')) + raise ValidationError( + _("You cannot create report from " "many petty cash holders.") + ) @api.multi - @api.constrains('expense_line_ids', 'total_amount') + @api.constrains("expense_line_ids", "total_amount") def _check_petty_cash_amount(self): for rec in self: - if rec.payment_mode == 'petty_cash': + if rec.payment_mode == "petty_cash": petty_cash = rec.petty_cash_id balance = petty_cash.petty_cash_balance amount = rec.total_amount company_currency = rec.company_id.currency_id amount_company = rec.currency_id._convert( - amount, company_currency, rec.company_id, - rec.accounting_date or fields.Date.today()) + amount, + company_currency, + rec.company_id, + rec.accounting_date or fields.Date.today(), + ) prec = rec.currency_id.rounding - if float_compare( - amount_company, balance, precision_rounding=prec) == 1: + if float_compare(amount_company, balance, precision_rounding=prec) == 1: raise ValidationError( - _('Not enough money in petty cash holder.\n' - 'You are requesting %s%s, ' - 'but the balance is %s%s.') % - ('{:,.2f}'.format(amount_company), - company_currency.symbol, '{:,.2f}'.format(balance), - company_currency.symbol)) + _( + "Not enough money in petty cash holder.\n" + "You are requesting %s%s, " + "but the balance is %s%s." + ) + % ( + "{:,.2f}".format(amount_company), + company_currency.symbol, + "{:,.2f}".format(balance), + company_currency.symbol, + ) + ) diff --git a/hr_expense_petty_cash/models/petty_cash.py b/hr_expense_petty_cash/models/petty_cash.py index 6cec5a7e4..c289f54ff 100644 --- a/hr_expense_petty_cash/models/petty_cash.py +++ b/hr_expense_petty_cash/models/petty_cash.py @@ -5,42 +5,37 @@ class PettyCash(models.Model): - _name = 'petty.cash' - _description = 'Petty Cash' - _rec_name = 'partner_id' + _name = "petty.cash" + _description = "Petty Cash" + _rec_name = "partner_id" partner_id = fields.Many2one( - comodel_name='res.partner', - string='Petty Cash Holder', - domain=[('supplier', '=', True)], + comodel_name="res.partner", + string="Petty Cash Holder", + domain=[("supplier", "=", True)], required=True, ) account_id = fields.Many2one( - comodel_name='account.account', - string='Petty Cash Account', - required=True, - ) - petty_cash_limit = fields.Float( - string='Max Limit', - required=True, + comodel_name="account.account", string="Petty Cash Account", required=True, ) + petty_cash_limit = fields.Float(string="Max Limit", required=True,) petty_cash_balance = fields.Float( - string='Balance', - compute='_compute_petty_cash_balance', - ) - journal_id = fields.Many2one( - comodel_name='account.journal', + string="Balance", compute="_compute_petty_cash_balance", ) + journal_id = fields.Many2one(comodel_name="account.journal",) _sql_constraints = [ - ('partner_uniq', 'unique(partner_id)', - 'Petty Cash Holder must be unique!'), + ("partner_uniq", "unique(partner_id)", "Petty Cash Holder must be unique!"), ] - @api.depends('partner_id', 'account_id') + @api.depends("partner_id", "account_id") def _compute_petty_cash_balance(self): - aml_env = self.env['account.move.line'] + aml_env = self.env["account.move.line"] for rec in self: - aml = aml_env.search([('partner_id', '=', rec.partner_id.id), - ('account_id', '=', rec.account_id.id)]) + aml = aml_env.search( + [ + ("partner_id", "=", rec.partner_id.id), + ("account_id", "=", rec.account_id.id), + ] + ) balance = sum([line.debit - line.credit for line in aml]) rec.petty_cash_balance = balance diff --git a/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py b/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py index d3d13ba2e..fe25fb07e 100644 --- a/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py +++ b/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py @@ -2,76 +2,87 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo.exceptions import ValidationError -from odoo.tests.common import TransactionCase, Form +from odoo.tests.common import Form, TransactionCase class TestHrExpensePettyCash(TransactionCase): def setUp(self): super(TestHrExpensePettyCash, self).setUp() - self.employee_id = self.env.ref('hr.employee_admin') - self.product_id = self.env.ref('hr_expense.air_ticket') - self.partner_1 = self.env.ref('base.res_partner_1') - self.partner_2 = self.env.ref('base.res_partner_2') - self.payable_type = self.env.ref('account.data_account_type_payable') - self.liquidity_type = \ - self.env.ref('account.data_account_type_liquidity') - self.account_id = self.env['account.account'].create({ - 'code': '111111', - 'name': 'Payable - Test', - 'user_type_id': self.payable_type.id, - 'reconcile': True, - }) - self.petty_cash_journal_id = self.env['account.journal'].create({ - 'code': 'PC', - 'name': 'Petty Cash', - 'type': 'general' - }) + self.employee_id = self.env.ref("hr.employee_admin") + self.product_id = self.env.ref("hr_expense.air_ticket") + self.partner_1 = self.env.ref("base.res_partner_1") + self.partner_2 = self.env.ref("base.res_partner_2") + self.payable_type = self.env.ref("account.data_account_type_payable") + self.liquidity_type = self.env.ref("account.data_account_type_liquidity") + self.account_id = self.env["account.account"].create( + { + "code": "111111", + "name": "Payable - Test", + "user_type_id": self.payable_type.id, + "reconcile": True, + } + ) + self.petty_cash_journal_id = self.env["account.journal"].create( + {"code": "PC", "name": "Petty Cash", "type": "general"} + ) # Create a Petty Cash Account - self.petty_cash_account_id = self.env['account.account'].create({ - 'code': '000000', - 'name': 'Petty Cash - Test', - 'user_type_id': self.liquidity_type.id, - }) + self.petty_cash_account_id = self.env["account.account"].create( + { + "code": "000000", + "name": "Petty Cash - Test", + "user_type_id": self.liquidity_type.id, + } + ) self.petty_cash_holder = self._create_petty_cash_holder(self.partner_1) def _create_petty_cash_holder(self, partner, petty_cash_balance=False): - petty_cash_holder = self.env['petty.cash'].create({ - 'partner_id': partner.id, - 'account_id': self.petty_cash_account_id.id, - 'petty_cash_limit': 1000.0, - 'petty_cash_balance': petty_cash_balance or 0.0, - }) + petty_cash_holder = self.env["petty.cash"].create( + { + "partner_id": partner.id, + "account_id": self.petty_cash_account_id.id, + "petty_cash_limit": 1000.0, + "petty_cash_balance": petty_cash_balance or 0.0, + } + ) return petty_cash_holder def _create_invoice(self, partner=False): - invoice = self.env['account.invoice'].create({ - 'partner_id': partner, - 'account_id': self.account_id.id, - 'type': 'in_invoice', - }) + invoice = self.env["account.invoice"].create( + { + "partner_id": partner, + "account_id": self.account_id.id, + "type": "in_invoice", + } + ) return invoice def _create_expense(self, amount, mode, petty_cash_holder=False): - expense = self.env['hr.expense'].create({ - 'name': 'Expense - Test', - 'employee_id': self.employee_id.id, - 'product_id': self.product_id.id, - 'unit_amount': amount, - 'payment_mode': mode, - 'petty_cash_id': petty_cash_holder, - }) + expense = self.env["hr.expense"].create( + { + "name": "Expense - Test", + "employee_id": self.employee_id.id, + "product_id": self.product_id.id, + "unit_amount": amount, + "payment_mode": mode, + "petty_cash_id": petty_cash_holder, + } + ) return expense def _create_expense_sheet(self, expense): - expense_sheet = self.env['hr.expense.sheet'].with_context( - {'default_petty_cash_id': self.petty_cash_holder.id} - ).create({ - 'name': expense.name, - 'employee_id': expense.employee_id.id, - 'expense_line_ids': [(6, 0, [expense.id])], - }) + expense_sheet = ( + self.env["hr.expense.sheet"] + .with_context({"default_petty_cash_id": self.petty_cash_holder.id}) + .create( + { + "name": expense.name, + "employee_id": expense.employee_id.id, + "expense_line_ids": [(6, 0, [expense.id])], + } + ) + ) return expense_sheet def test_01_create_petty_cash_holder(self): @@ -108,29 +119,29 @@ def test_02_create_expense_petty_cash(self): invoice.action_invoice_open() self.assertEqual(self.petty_cash_holder.petty_cash_balance, 1000.0) # Create expense - expense_own = self._create_expense(400.0, 'own_account') + expense_own = self._create_expense(400.0, "own_account") expense_petty_cash = self._create_expense( - 400.0, 'petty_cash', self.petty_cash_holder.id) + 400.0, "petty_cash", self.petty_cash_holder.id + ) expense_report = expense_own + expense_petty_cash with self.assertRaises(ValidationError): expense_report.action_submit_expenses() result = expense_petty_cash.action_submit_expenses() - default_expense_line_ids = \ - result.get('context').get('default_expense_line_ids') + default_expense_line_ids = result.get("context").get("default_expense_line_ids") sheet = self._create_expense_sheet(expense_petty_cash) self.assertEqual(sheet.expense_line_ids.ids, default_expense_line_ids) - self.assertEqual(sheet.state, 'draft') + self.assertEqual(sheet.state, "draft") with self.assertRaises(ValidationError): sheet.expense_line_ids.unit_amount = 1600.0 sheet.expense_line_ids.unit_amount = 400.0 # Submitted to Manager and Approve sheet.action_submit_sheet() - self.assertEquals(sheet.state, 'submit') + self.assertEquals(sheet.state, "submit") sheet.approve_expense_sheets() - self.assertEquals(sheet.state, 'approve') + self.assertEquals(sheet.state, "approve") # Create Expense Entries sheet.action_sheet_move_create() - self.assertEquals(sheet.state, 'done') + self.assertEquals(sheet.state, "done") self.assertTrue(sheet.account_move_id.id) self.assertEquals(self.petty_cash_holder.petty_cash_balance, 600.0) @@ -144,6 +155,7 @@ def test_03_create_expense_petty_cash_with_journal(self): invoice.action_invoice_open() self.assertEqual(self.petty_cash_holder.petty_cash_balance, 1000.0) expense_petty_cash = self._create_expense( - 400.0, 'petty_cash', self.petty_cash_holder.id) + 400.0, "petty_cash", self.petty_cash_holder.id + ) sheet = self._create_expense_sheet(expense_petty_cash) self.assertEqual(sheet.journal_id, self.petty_cash_holder.journal_id) diff --git a/hr_expense_petty_cash/views/account_invoice_views.xml b/hr_expense_petty_cash/views/account_invoice_views.xml index 58a0098cc..a4bc35a5b 100644 --- a/hr_expense_petty_cash/views/account_invoice_views.xml +++ b/hr_expense_petty_cash/views/account_invoice_views.xml @@ -1,15 +1,13 @@ - + - account.invoice.supplier.form account.invoice - + - + - diff --git a/hr_expense_petty_cash/views/hr_expense_sheet_views.xml b/hr_expense_petty_cash/views/hr_expense_sheet_views.xml index 98edf298f..aaeae4620 100644 --- a/hr_expense_petty_cash/views/hr_expense_sheet_views.xml +++ b/hr_expense_petty_cash/views/hr_expense_sheet_views.xml @@ -1,33 +1,44 @@ - + - view.hr.expense.sheet.form.inherit hr.expense.sheet - + - + - {'invisible': [('payment_mode', 'not in', ['own_account', 'petty_cash'])]} + {'invisible': [('payment_mode', 'not in', ['own_account', 'petty_cash'])]} - hr.expense.sheet.filter.inherit hr.expense.sheet - + - + - + - diff --git a/hr_expense_petty_cash/views/hr_expense_views.xml b/hr_expense_petty_cash/views/hr_expense_views.xml index 06ad59b73..f4981fa63 100644 --- a/hr_expense_petty_cash/views/hr_expense_views.xml +++ b/hr_expense_petty_cash/views/hr_expense_views.xml @@ -1,32 +1,42 @@ - + - hr.expense.view.form.inherit hr.expense - +
- +
- hr.expense.filter.inherit hr.expense - + - + - + -
diff --git a/hr_expense_petty_cash/views/petty_cash_views.xml b/hr_expense_petty_cash/views/petty_cash_views.xml index 14b91cc3a..f847e6fb6 100644 --- a/hr_expense_petty_cash/views/petty_cash_views.xml +++ b/hr_expense_petty_cash/views/petty_cash_views.xml @@ -1,58 +1,60 @@ - + - petty.cash.form petty.cash
- - - - - - - - - - - - + + + + + + + + + + + +
- petty.cash.list petty.cash - - - - - - + + + + + + - petty.cash.kanban petty.cash - - + +
- + + +
- +
@@ -61,34 +63,32 @@
- petty.cash.search petty.cash - + - Petty Cash petty.cash form tree,kanban,form - - + +

Create a new petty cash holder

- - - +
From 2997e4eac058a5bb52e1e09d372599d52eefc2a1 Mon Sep 17 00:00:00 2001 From: ps-tubtim Date: Wed, 21 Oct 2020 16:18:53 +0700 Subject: [PATCH 10/41] [MIG] hr_expense_petty_cash: Migration to 13.0 --- hr_expense_petty_cash/__manifest__.py | 4 +- hr_expense_petty_cash/models/__init__.py | 2 +- .../models/account_invoice.py | 99 ---------- hr_expense_petty_cash/models/account_move.py | 132 ++++++++++++++ hr_expense_petty_cash/models/hr_expense.py | 62 +++++-- .../models/hr_expense_sheet.py | 6 +- hr_expense_petty_cash/models/petty_cash.py | 6 +- .../tests/test_hr_expense_petty_cash.py | 170 ++++++++++++++---- .../views/account_invoice_views.xml | 13 -- .../views/account_move_views.xml | 16 ++ .../views/hr_expense_sheet_views.xml | 8 +- .../views/hr_expense_views.xml | 6 +- .../views/petty_cash_views.xml | 8 +- 13 files changed, 344 insertions(+), 188 deletions(-) delete mode 100644 hr_expense_petty_cash/models/account_invoice.py create mode 100644 hr_expense_petty_cash/models/account_move.py delete mode 100644 hr_expense_petty_cash/views/account_invoice_views.xml create mode 100644 hr_expense_petty_cash/views/account_move_views.xml diff --git a/hr_expense_petty_cash/__manifest__.py b/hr_expense_petty_cash/__manifest__.py index 05d3a3081..13f972731 100644 --- a/hr_expense_petty_cash/__manifest__.py +++ b/hr_expense_petty_cash/__manifest__.py @@ -7,11 +7,11 @@ "category": "Human Resources", "author": "Ecosoft, Odoo Community Association (OCA)", "license": "AGPL-3", - "website": "https://github.com/OCA/hr", + "website": "https://github.com/OCA/hr-expense", "depends": ["hr_expense"], "data": [ "security/ir.model.access.csv", - "views/account_invoice_views.xml", + "views/account_move_views.xml", "views/hr_expense_sheet_views.xml", "views/hr_expense_views.xml", "views/petty_cash_views.xml", diff --git a/hr_expense_petty_cash/models/__init__.py b/hr_expense_petty_cash/models/__init__.py index 260bacdf9..e60741242 100644 --- a/hr_expense_petty_cash/models/__init__.py +++ b/hr_expense_petty_cash/models/__init__.py @@ -1,7 +1,7 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from . import account_invoice +from . import account_move from . import hr_expense from . import hr_expense_sheet from . import petty_cash diff --git a/hr_expense_petty_cash/models/account_invoice.py b/hr_expense_petty_cash/models/account_invoice.py deleted file mode 100644 index 1ba689861..000000000 --- a/hr_expense_petty_cash/models/account_invoice.py +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from odoo import _, api, fields, models -from odoo.exceptions import ValidationError -from odoo.tools import float_compare - - -class AccountInvoice(models.Model): - _inherit = "account.invoice" - - is_petty_cash = fields.Boolean( - string="Petty Cash", readonly=True, states={"draft": [("readonly", False)]}, - ) - - @api.multi - @api.constrains("invoice_line_ids") - def _check_petty_cash_amount(self): - petty_cash_env = self.env["petty.cash"] - for rec in self.filtered("is_petty_cash"): - petty_cash = petty_cash_env.search( - [("partner_id", "=", rec.partner_id.id)], limit=1 - ) - if not petty_cash: - raise ValidationError( - _("%s is not a petty cash holder") % rec.partner_id.name - ) - balance = petty_cash.petty_cash_balance - limit = petty_cash.petty_cash_limit - max_amount = limit - balance - account = petty_cash.account_id - amount = sum( - rec.invoice_line_ids.filtered(lambda l: l.account_id == account).mapped( - "price_subtotal" - ) - ) - company_currency = rec.company_id.currency_id - amount_company = rec.currency_id._convert( - amount, - company_currency, - rec.company_id, - rec.date_invoice or fields.Date.today(), - ) - prec = rec.currency_id.rounding - if float_compare(amount_company, max_amount, precision_rounding=prec) == 1: - raise ValidationError( - _("Petty Cash balance is %s %s.\n" "Max amount to add is %s %s.") - % ( - "{:,.2f}".format(balance), - company_currency.symbol, - "{:,.2f}".format(max_amount), - company_currency.symbol, - ) - ) - - @api.multi - def _add_petty_cash_invoice_line(self, petty_cash): - self.ensure_one() - # Get suggested currency amount - amount = petty_cash.petty_cash_limit - petty_cash.petty_cash_balance - company_currency = self.env.user.company_id.currency_id - amount_doc_currency = company_currency._convert( - amount, - self.currency_id, - self.company_id, - self.date_invoice or fields.Date.today(), - ) - - inv_line = self.env["account.invoice.line"].new( - { - "name": petty_cash.account_id.name, - "invoice_id": self.id, - "account_id": petty_cash.account_id.id, - "price_unit": amount_doc_currency, - "quantity": 1, - } - ) - return inv_line - - @api.multi - @api.onchange("is_petty_cash", "partner_id") - def _onchange_is_petty_cash(self): - self.invoice_line_ids = False - ctx = self._context.copy() - if self.is_petty_cash: - if not self.partner_id: - raise ValidationError(_("Please select petty cash holder")) - # Selected parenter must be petty cash holder - petty_cash = self.env["petty.cash"].search( - [("partner_id", "=", self.partner_id.id)], limit=1 - ) - if not petty_cash: - raise ValidationError( - _("%s is not a petty cash holder") % self.partner_id.name - ) - self._add_petty_cash_invoice_line(petty_cash) - if petty_cash.journal_id: - ctx.update({"default_journal_id": petty_cash.journal_id.id}) - self.journal_id = self.with_context(ctx)._default_journal() diff --git a/hr_expense_petty_cash/models/account_move.py b/hr_expense_petty_cash/models/account_move.py new file mode 100644 index 000000000..3aefb4558 --- /dev/null +++ b/hr_expense_petty_cash/models/account_move.py @@ -0,0 +1,132 @@ +# Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import _, api, fields, models +from odoo.exceptions import UserError, ValidationError +from odoo.tools import float_compare + + +class AccountMove(models.Model): + _inherit = "account.move" + + is_petty_cash = fields.Boolean( + string="Petty Cash", readonly=True, states={"draft": [("readonly", False)]}, + ) + + def action_post(self): + self._check_petty_cash_amount() + return super().action_post() + + @api.constrains("invoice_line_ids", "line_ids") + def _check_petty_cash_amount(self): + petty_cash_env = self.env["petty.cash"] + for rec in self: + petty_cash = petty_cash_env.search( + [("partner_id", "=", rec.partner_id.id)], limit=1 + ) + if petty_cash and rec.invoice_line_ids: + account = petty_cash.account_id + # Must check Petty Cash on vender bills + if ( + not rec.is_petty_cash + and account.id in rec.invoice_line_ids.mapped("account_id").ids + ): + raise UserError( + _("Please check Petty Cash on {}.".format(rec.display_name)) + ) + if rec.is_petty_cash: + if len(rec.invoice_line_ids) > 1: + raise UserError( + _( + "{} with petty cash checked must contain " + "only 1 line.".format(rec.display_name) + ) + ) + if rec.invoice_line_ids.account_id.id != account.id: + raise UserError( + _( + "Account on invoice line should be {}.".format( + account.display_name + ) + ) + ) + balance = petty_cash.petty_cash_balance + limit = petty_cash.petty_cash_limit + max_amount = limit - balance + amount = sum( + rec.invoice_line_ids.filtered( + lambda l: l.account_id == account + ).mapped("price_subtotal") + ) + company_currency = rec.company_id.currency_id + amount_company = rec.currency_id._convert( + amount, + company_currency, + rec.company_id, + rec.date or fields.Date.today(), + ) + prec = rec.currency_id.rounding + if ( + float_compare( + amount_company, max_amount, precision_rounding=prec + ) + == 1 + ): + raise ValidationError( + _( + "Petty Cash balance is %s %s.\n" + "Max amount to add is %s %s." + ) + % ( + "{:,.2f}".format(balance), + company_currency.symbol, + "{:,.2f}".format(max_amount), + company_currency.symbol, + ) + ) + + def _add_petty_cash_invoice_line(self, petty_cash): + self.ensure_one() + # Get suggested currency amount + amount = petty_cash.petty_cash_limit - petty_cash.petty_cash_balance + company_currency = self.env.user.company_id.currency_id + amount_doc_currency = company_currency._convert( + amount, self.currency_id, self.company_id, self.date or fields.Date.today(), + ) + + inv_line = self.env["account.move.line"].new( + { + "name": petty_cash.account_id.name, + "account_id": petty_cash.account_id.id, + "partner_id": petty_cash.partner_id.id, + "price_unit": amount_doc_currency, + "quantity": 1, + } + ) + return inv_line + + @api.onchange("is_petty_cash", "partner_id") + def _onchange_is_petty_cash(self): + self.line_ids = False + self.invoice_line_ids = False + ctx = self._context.copy() + if self.is_petty_cash: + if not self.partner_id: + raise ValidationError(_("Please select petty cash holder")) + # Selected parenter must be petty cash holder + petty_cash = self.env["petty.cash"].search( + [("partner_id", "=", self.partner_id.id)], limit=1 + ) + if not petty_cash: + raise ValidationError( + _("%s is not a petty cash holder") % self.partner_id.name + ) + self.invoice_line_ids = self._add_petty_cash_invoice_line(petty_cash) + if petty_cash.journal_id: + ctx.update( + { + "default_journal_id": petty_cash.journal_id.id, + "default_type": "general", + } + ) + self.journal_id = self.with_context(ctx)._get_default_journal() diff --git a/hr_expense_petty_cash/models/hr_expense.py b/hr_expense_petty_cash/models/hr_expense.py index 8ff024b00..132e19909 100644 --- a/hr_expense_petty_cash/models/hr_expense.py +++ b/hr_expense_petty_cash/models/hr_expense.py @@ -1,14 +1,14 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import _, api, fields, models -from odoo.exceptions import ValidationError +from odoo import _, fields, models +from odoo.exceptions import UserError class HrExpense(models.Model): _inherit = "hr.expense" - payment_mode = fields.Selection(selection_add=[("petty_cash", "Petty Cash")],) + payment_mode = fields.Selection(selection_add=[("petty_cash", "Petty Cash")]) petty_cash_id = fields.Many2one( string="Petty cash holder", comodel_name="petty.cash", @@ -17,24 +17,48 @@ class HrExpense(models.Model): states={"draft": [("readonly", False)]}, ) - @api.multi - def action_submit_expenses(self): - res = super().action_submit_expenses() - context = res["context"] - context["default_expense_line_ids"] = self.ids - context["default_name"] = self[0].name if len(self) == 1 else "" - set_petty_cash_ids = set() - for rec in self: - set_petty_cash_ids.add(rec.petty_cash_id.id) - if set_petty_cash_ids: - if len(set_petty_cash_ids) == 1: - context["default_petty_cash_id"] = set_petty_cash_ids.pop() - return res - raise ValidationError( - _("You cannot create report from " "many petty cash holders.") + def _prepare_expense_vals(self): + vals = { + "company_id": self.company_id.id, + "employee_id": self[0].employee_id.id, + "name": self[0].name if len(self) == 1 else "", + "expense_line_ids": [(6, 0, self.ids)], + } + return vals + + def _create_sheet_from_expense_petty_cash(self): + """ Overwrite function _create_sheet_from_expenses(), if petty cash mode. """ + if any(expense.state != "draft" or expense.sheet_id for expense in self): + raise UserError(_("You cannot report twice the same line!")) + if len(self.mapped("employee_id")) != 1: + raise UserError( + _( + "You cannot report expenses for different " + "employees in the same report." + ) + ) + if any(not expense.product_id for expense in self): + raise UserError(_("You can not create report without product.")) + ctx = self._context.copy() + ctx.update({"default_petty_cash_id": self[0].petty_cash_id.id}) + sheet = ( + self.env["hr.expense.sheet"] + .with_context(ctx) + .create(self._prepare_expense_vals()) + ) + sheet._onchange_employee_id() + return sheet + + def _create_sheet_from_expenses(self): + payment_mode = set(self.mapped("payment_mode")) + if len(payment_mode) > 1 and "petty_cash" in payment_mode: + raise UserError( + _("You cannot create report from many petty cash mode and other.") ) + if all(expense.payment_mode == "petty_cash" for expense in self): + return self._create_sheet_from_expense_petty_cash() + return super()._create_sheet_from_expenses() - @api.multi def _get_account_move_line_values(self): res = super()._get_account_move_line_values() for expense in self.filtered(lambda p: p.payment_mode == "petty_cash"): diff --git a/hr_expense_petty_cash/models/hr_expense_sheet.py b/hr_expense_petty_cash/models/hr_expense_sheet.py index 478b71f23..240e6f9bf 100644 --- a/hr_expense_petty_cash/models/hr_expense_sheet.py +++ b/hr_expense_petty_cash/models/hr_expense_sheet.py @@ -20,12 +20,10 @@ def _default_journal_id(self): journal = petty_cash_id.journal_id.id or journal return journal - payment_mode = fields.Selection(selection_add=[("petty_cash", "Petty Cash")],) petty_cash_id = fields.Many2one( string="Petty cash holder", comodel_name="petty.cash", ondelete="restrict", - readonly=True, compute="_compute_petty_cash", ) journal_id = fields.Many2one(default=_default_journal_id) @@ -33,6 +31,7 @@ def _default_journal_id(self): @api.depends("expense_line_ids", "payment_mode") def _compute_petty_cash(self): for rec in self: + rec.petty_cash_id = False if rec.payment_mode == "petty_cash": set_petty_cash_ids = set() for line in rec.expense_line_ids: @@ -43,10 +42,9 @@ def _compute_petty_cash(self): ) else: raise ValidationError( - _("You cannot create report from " "many petty cash holders.") + _("You cannot create report from many petty cash holders.") ) - @api.multi @api.constrains("expense_line_ids", "total_amount") def _check_petty_cash_amount(self): for rec in self: diff --git a/hr_expense_petty_cash/models/petty_cash.py b/hr_expense_petty_cash/models/petty_cash.py index c289f54ff..89134b0af 100644 --- a/hr_expense_petty_cash/models/petty_cash.py +++ b/hr_expense_petty_cash/models/petty_cash.py @@ -10,10 +10,7 @@ class PettyCash(models.Model): _rec_name = "partner_id" partner_id = fields.Many2one( - comodel_name="res.partner", - string="Petty Cash Holder", - domain=[("supplier", "=", True)], - required=True, + comodel_name="res.partner", string="Petty Cash Holder", required=True, ) account_id = fields.Many2one( comodel_name="account.account", string="Petty Cash Account", required=True, @@ -35,6 +32,7 @@ def _compute_petty_cash_balance(self): [ ("partner_id", "=", rec.partner_id.id), ("account_id", "=", rec.account_id.id), + ("parent_state", "=", "posted"), ] ) balance = sum([line.debit - line.credit for line in aml]) diff --git a/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py b/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py index fe25fb07e..bf088a6af 100644 --- a/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py +++ b/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py @@ -1,7 +1,7 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo.exceptions import ValidationError +from odoo.exceptions import UserError, ValidationError from odoo.tests.common import Form, TransactionCase @@ -9,12 +9,15 @@ class TestHrExpensePettyCash(TransactionCase): def setUp(self): super(TestHrExpensePettyCash, self).setUp() - self.employee_id = self.env.ref("hr.employee_admin") + self.employee_1 = self.env.ref("hr.employee_admin") + self.employee_2 = self.env.ref("hr.employee_al") self.product_id = self.env.ref("hr_expense.air_ticket") self.partner_1 = self.env.ref("base.res_partner_1") self.partner_2 = self.env.ref("base.res_partner_2") + self.partner_3 = self.env.ref("base.res_partner_3") self.payable_type = self.env.ref("account.data_account_type_payable") self.liquidity_type = self.env.ref("account.data_account_type_liquidity") + self.cost_type = self.env.ref("account.data_account_type_direct_costs") self.account_id = self.env["account.account"].create( { "code": "111111", @@ -23,6 +26,13 @@ def setUp(self): "reconcile": True, } ) + self.account_revenue_id = self.env["account.account"].create( + { + "code": "111112", + "name": "Cost Of Revenue - Test", + "user_type_id": self.cost_type.id, + } + ) self.petty_cash_journal_id = self.env["account.journal"].create( {"code": "PC", "name": "Petty Cash", "type": "general"} ) @@ -36,33 +46,29 @@ def setUp(self): } ) self.petty_cash_holder = self._create_petty_cash_holder(self.partner_1) + self.petty_cash_holder_2 = self._create_petty_cash_holder(self.partner_3) - def _create_petty_cash_holder(self, partner, petty_cash_balance=False): + def _create_petty_cash_holder(self, partner): petty_cash_holder = self.env["petty.cash"].create( { "partner_id": partner.id, "account_id": self.petty_cash_account_id.id, "petty_cash_limit": 1000.0, - "petty_cash_balance": petty_cash_balance or 0.0, } ) return petty_cash_holder def _create_invoice(self, partner=False): - invoice = self.env["account.invoice"].create( - { - "partner_id": partner, - "account_id": self.account_id.id, - "type": "in_invoice", - } + invoice = self.env["account.move"].create( + {"partner_id": partner, "type": "in_invoice"} ) return invoice - def _create_expense(self, amount, mode, petty_cash_holder=False): + def _create_expense(self, amount, employee_id, mode, petty_cash_holder=False): expense = self.env["hr.expense"].create( { "name": "Expense - Test", - "employee_id": self.employee_id.id, + "employee_id": employee_id, "product_id": self.product_id.id, "unit_amount": amount, "payment_mode": mode, @@ -71,22 +77,53 @@ def _create_expense(self, amount, mode, petty_cash_holder=False): ) return expense - def _create_expense_sheet(self, expense): + def _create_expense_sheet(self, expenses): expense_sheet = ( self.env["hr.expense.sheet"] .with_context({"default_petty_cash_id": self.petty_cash_holder.id}) .create( { - "name": expense.name, - "employee_id": expense.employee_id.id, - "expense_line_ids": [(6, 0, [expense.id])], + "name": expenses[0].name, + "employee_id": expenses[0].employee_id.id, + "expense_line_ids": [(6, 0, expenses.ids)], } ) ) return expense_sheet - def test_01_create_petty_cash_holder(self): - self.assertEqual(self.petty_cash_holder.petty_cash_balance, 0.00) + def _create_multi_invoice_line(self, petty_cash=False): + invoice = self.env["account.move"].create( + { + "partner_id": self.partner_1.id, + "type": "in_invoice", + "is_petty_cash": petty_cash, + "invoice_line_ids": [ + ( + 0, + 0, + { + "name": "Test line 1", + "quantity": 1, + "price_unit": 100, + "account_id": self.account_revenue_id.id, + }, + ), + ( + 0, + 0, + { + "name": "Test line 2", + "quantity": 1, + "price_unit": 100, + "account_id": self.account_revenue_id.id, + }, + ), + ], + } + ) + return invoice + + def _check_warning(self): # no partner and check petty cash invoice = self._create_invoice() with self.assertRaises(ValidationError): @@ -102,13 +139,56 @@ def test_01_create_petty_cash_holder(self): inv.is_petty_cash = True self.assertEqual(len(invoice.invoice_line_ids), 1) self.assertEqual(invoice.invoice_line_ids.price_unit, 1000.0) - - invoice.invoice_line_ids.price_unit = 1500.0 + # over limit with self.assertRaises(ValidationError): - invoice._check_petty_cash_amount() + invoice.invoice_line_ids.with_context({"check_move_validity": False}).write( + {"price_unit": 1500.0} + ) + invoice.action_post() + # change account to not petty cash + invoice.invoice_line_ids.account_id = self.account_revenue_id.id + with self.assertRaises(UserError): + invoice.action_post() + # no partner + invoice.invoice_line_ids.account_id = self.petty_cash_account_id.id + with self.assertRaises(UserError): + invoice.write({"partner_id": False}) + invoice.action_post() + # Create line manual and not check petty cash + invoice = self.env["account.move"].create( + { + "partner_id": self.partner_1.id, + "type": "in_invoice", + "invoice_line_ids": [ + ( + 0, + 0, + { + "name": "Test line", + "quantity": 1, + "price_unit": 100, + "account_id": self.account_revenue_id.id, + }, + ) + ], + } + ) + invoice.invoice_line_ids.account_id = self.petty_cash_account_id.id + with self.assertRaises(UserError): + invoice.action_post() + + # Create multi line and check petty cash + with self.assertRaises(UserError): + self._create_multi_invoice_line(petty_cash=True) - invoice.invoice_line_ids.price_unit = 1000.0 - invoice.action_invoice_open() + def test_01_create_petty_cash_holder(self): + self.assertEqual(self.petty_cash_holder.petty_cash_balance, 0.00) + self._check_warning() + invoice = self._create_invoice(self.partner_1.id) + with Form(invoice) as inv: + inv.is_petty_cash = True + invoice.action_post() + self.petty_cash_holder._compute_petty_cash_balance() self.assertEqual(self.petty_cash_holder.petty_cash_balance, 1000.0) def test_02_create_expense_petty_cash(self): @@ -116,29 +196,51 @@ def test_02_create_expense_petty_cash(self): with Form(invoice) as inv: inv.is_petty_cash = True inv.invoice_line_ids.price_unit = 1000.0 - invoice.action_invoice_open() + invoice.action_post() + self.petty_cash_holder._compute_petty_cash_balance() self.assertEqual(self.petty_cash_holder.petty_cash_balance, 1000.0) # Create expense - expense_own = self._create_expense(400.0, "own_account") + expense_own = self._create_expense(400.0, self.employee_1.id, "own_account") expense_petty_cash = self._create_expense( - 400.0, "petty_cash", self.petty_cash_holder.id + 400.0, self.employee_1.id, "petty_cash", self.petty_cash_holder.id ) - expense_report = expense_own + expense_petty_cash - with self.assertRaises(ValidationError): + expense_petty_cash_2 = self._create_expense( + 200.0, self.employee_1.id, "petty_cash", self.petty_cash_holder_2.id + ) + expense_petty_cash_3 = self._create_expense( + 100.0, self.employee_2.id, "petty_cash", self.petty_cash_holder_2.id + ) + expense_report = expense_own + expense_petty_cash + expense_petty_cash_2 + with self.assertRaises(UserError): expense_report.action_submit_expenses() - result = expense_petty_cash.action_submit_expenses() - default_expense_line_ids = result.get("context").get("default_expense_line_ids") + # check create direct expense sheet and many diff petty cash + expense_diff_holder = expense_petty_cash + expense_petty_cash_2 + with self.assertRaises(ValidationError): + self._create_expense_sheet(expense_diff_holder) + # create expense normal not petty cash + expense_own.sheet_id = False + action = expense_own.action_submit_expenses() + self.assertEqual(action["res_model"], "hr.expense.sheet") sheet = self._create_expense_sheet(expense_petty_cash) - self.assertEqual(sheet.expense_line_ids.ids, default_expense_line_ids) self.assertEqual(sheet.state, "draft") with self.assertRaises(ValidationError): sheet.expense_line_ids.unit_amount = 1600.0 + sheet._check_petty_cash_amount() sheet.expense_line_ids.unit_amount = 400.0 # Submitted to Manager and Approve sheet.action_submit_sheet() self.assertEquals(sheet.state, "submit") sheet.approve_expense_sheets() self.assertEquals(sheet.state, "approve") + # Check state != draft, many employee and don't have product + with self.assertRaises(UserError): + expense_petty_cash.action_submit_expenses() + expense_test = expense_petty_cash_2 + expense_petty_cash_3 + with self.assertRaises(UserError): + expense_test.action_submit_expenses() + expense_petty_cash_3.product_id = False + with self.assertRaises(UserError): + expense_petty_cash_3.action_submit_expenses() # Create Expense Entries sheet.action_sheet_move_create() self.assertEquals(sheet.state, "done") @@ -152,10 +254,12 @@ def test_03_create_expense_petty_cash_with_journal(self): inv.is_petty_cash = True inv.invoice_line_ids.price_unit = 1000.0 self.assertEqual(invoice.journal_id, self.petty_cash_holder.journal_id) - invoice.action_invoice_open() + invoice.action_post() + self.petty_cash_holder._compute_petty_cash_balance() self.assertEqual(self.petty_cash_holder.petty_cash_balance, 1000.0) expense_petty_cash = self._create_expense( - 400.0, "petty_cash", self.petty_cash_holder.id + 400.0, self.employee_1.id, "petty_cash", self.petty_cash_holder.id ) + expense_petty_cash.action_submit_expenses() sheet = self._create_expense_sheet(expense_petty_cash) self.assertEqual(sheet.journal_id, self.petty_cash_holder.journal_id) diff --git a/hr_expense_petty_cash/views/account_invoice_views.xml b/hr_expense_petty_cash/views/account_invoice_views.xml deleted file mode 100644 index a4bc35a5b..000000000 --- a/hr_expense_petty_cash/views/account_invoice_views.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - account.invoice.supplier.form - account.invoice - - - - - - - - diff --git a/hr_expense_petty_cash/views/account_move_views.xml b/hr_expense_petty_cash/views/account_move_views.xml new file mode 100644 index 000000000..af67a0940 --- /dev/null +++ b/hr_expense_petty_cash/views/account_move_views.xml @@ -0,0 +1,16 @@ + + + + account.move.form.inherit + account.move + + + + + + + + diff --git a/hr_expense_petty_cash/views/hr_expense_sheet_views.xml b/hr_expense_petty_cash/views/hr_expense_sheet_views.xml index aaeae4620..6f1ad2c29 100644 --- a/hr_expense_petty_cash/views/hr_expense_sheet_views.xml +++ b/hr_expense_petty_cash/views/hr_expense_sheet_views.xml @@ -19,12 +19,12 @@
- - hr.expense.sheet.filter.inherit + + hr.expense.sheet.search.inherit hr.expense.sheet - + - + - - hr.expense.filter.inherit + + hr.expense.search.inherit hr.expense - + - + @@ -28,7 +25,7 @@ petty.cash.list petty.cash - + @@ -75,7 +72,6 @@ Petty Cash petty.cash - form tree,kanban,form From ab16d9d16c8abd5de86c456548034b5c86f264e4 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Mon, 2 Nov 2020 07:10:29 +0000 Subject: [PATCH 11/41] [UPD] Update hr_expense_petty_cash.pot --- .../i18n/hr_expense_petty_cash.pot | 98 ++++++++++++------- 1 file changed, 64 insertions(+), 34 deletions(-) diff --git a/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot b/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot index de43925df..c69d71151 100644 --- a/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot +++ b/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot @@ -1,12 +1,12 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * hr_expense_petty_cash +# * hr_expense_petty_cash # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 12.0\n" +"Project-Id-Version: Odoo Server 13.0\n" "Report-Msgid-Bugs-To: \n" -"Last-Translator: <>\n" +"Last-Translator: \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -14,21 +14,21 @@ msgstr "" "Plural-Forms: \n" #. module: hr_expense_petty_cash -#: code:addons/hr_expense_petty_cash/models/account_invoice.py:26 -#: code:addons/hr_expense_petty_cash/models/account_invoice.py:78 +#: code:addons/hr_expense_petty_cash/models/account_move.py:0 #, python-format msgid "%s is not a petty cash holder" msgstr "" #. module: hr_expense_petty_cash -#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash__petty_cash_balance -#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_petty_cash_list -msgid "Balance" +#: code:addons/hr_expense_petty_cash/models/account_move.py:0 +#, python-format +msgid "Account on invoice line should be {}." msgstr "" #. module: hr_expense_petty_cash -#: selection:hr.expense,payment_mode:0 -msgid "Company" +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash__petty_cash_balance +#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_petty_cash_list +msgid "Balance" msgstr "" #. module: hr_expense_petty_cash @@ -51,11 +51,6 @@ msgstr "" msgid "Display Name" msgstr "" -#. module: hr_expense_petty_cash -#: selection:hr.expense,payment_mode:0 -msgid "Employee (to reimburse)" -msgstr "" - #. module: hr_expense_petty_cash #: model:ir.model,name:hr_expense_petty_cash.model_hr_expense msgid "Expense" @@ -82,13 +77,13 @@ msgid "ID" msgstr "" #. module: hr_expense_petty_cash -#: model:ir.model,name:hr_expense_petty_cash.model_account_invoice -msgid "Invoice" +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash__journal_id +msgid "Journal" msgstr "" #. module: hr_expense_petty_cash -#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash__journal_id -msgid "Journal" +#: model:ir.model,name:hr_expense_petty_cash.model_account_move +msgid "Journal Entries" msgstr "" #. module: hr_expense_petty_cash @@ -117,26 +112,26 @@ msgid "Max Limit" msgstr "" #. module: hr_expense_petty_cash -#: code:addons/hr_expense_petty_cash/models/hr_expense_sheet.py:67 +#: code:addons/hr_expense_petty_cash/models/hr_expense_sheet.py:0 #, python-format -msgid "Not enough money in petty cash holder.\n" +msgid "" +"Not enough money in petty cash holder.\n" "You are requesting %s%s, but the balance is %s%s." msgstr "" #. module: hr_expense_petty_cash #: model:ir.model.fields,field_description:hr_expense_petty_cash.field_hr_expense__payment_mode -#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_hr_expense_sheet__payment_mode msgid "Paid By" msgstr "" #. module: hr_expense_petty_cash -#: selection:hr.expense,payment_mode:0 #: model:ir.actions.act_window,name:hr_expense_petty_cash.action_petty_cash #: model:ir.model,name:hr_expense_petty_cash.model_petty_cash -#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_account_invoice__is_petty_cash +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_account_move__is_petty_cash +#: model:ir.model.fields.selection,name:hr_expense_petty_cash.selection__hr_expense__payment_mode__petty_cash #: model:ir.ui.menu,name:hr_expense_petty_cash.menu_petty_cash -#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_hr_expense_filter_inherit -#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_hr_expense_sheet_filter_inherit +#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.hr_expense_sheet_view_search_inherit +#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.hr_expense_view_search_inherit #: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_petty_cash_form #: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_petty_cash_list #: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_petty_cash_search @@ -150,20 +145,21 @@ msgstr "" #. module: hr_expense_petty_cash #: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash__partner_id -#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_hr_expense_filter_inherit -#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_hr_expense_sheet_filter_inherit +#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.hr_expense_sheet_view_search_inherit +#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.hr_expense_view_search_inherit msgid "Petty Cash Holder" msgstr "" #. module: hr_expense_petty_cash -#: sql_constraint:petty.cash:0 +#: model:ir.model.constraint,message:hr_expense_petty_cash.constraint_petty_cash_partner_uniq msgid "Petty Cash Holder must be unique!" msgstr "" #. module: hr_expense_petty_cash -#: code:addons/hr_expense_petty_cash/models/account_invoice.py:42 +#: code:addons/hr_expense_petty_cash/models/account_move.py:0 #, python-format -msgid "Petty Cash balance is %s %s.\n" +msgid "" +"Petty Cash balance is %s %s.\n" "Max amount to add is %s %s." msgstr "" @@ -174,7 +170,13 @@ msgid "Petty cash holder" msgstr "" #. module: hr_expense_petty_cash -#: code:addons/hr_expense_petty_cash/models/account_invoice.py:73 +#: code:addons/hr_expense_petty_cash/models/account_move.py:0 +#, python-format +msgid "Please check Petty Cash on {}." +msgstr "" + +#. module: hr_expense_petty_cash +#: code:addons/hr_expense_petty_cash/models/account_move.py:0 #, python-format msgid "Please select petty cash holder" msgstr "" @@ -185,9 +187,37 @@ msgid "The journal used when the expense is done." msgstr "" #. module: hr_expense_petty_cash -#: code:addons/hr_expense_petty_cash/models/hr_expense.py:35 -#: code:addons/hr_expense_petty_cash/models/hr_expense_sheet.py:48 +#: code:addons/hr_expense_petty_cash/models/hr_expense.py:0 +#, python-format +msgid "You can not create report without product." +msgstr "" + +#. module: hr_expense_petty_cash +#: code:addons/hr_expense_petty_cash/models/hr_expense_sheet.py:0 #, python-format msgid "You cannot create report from many petty cash holders." msgstr "" +#. module: hr_expense_petty_cash +#: code:addons/hr_expense_petty_cash/models/hr_expense.py:0 +#, python-format +msgid "You cannot create report from many petty cash mode and other." +msgstr "" + +#. module: hr_expense_petty_cash +#: code:addons/hr_expense_petty_cash/models/hr_expense.py:0 +#, python-format +msgid "You cannot report expenses for different employees in the same report." +msgstr "" + +#. module: hr_expense_petty_cash +#: code:addons/hr_expense_petty_cash/models/hr_expense.py:0 +#, python-format +msgid "You cannot report twice the same line!" +msgstr "" + +#. module: hr_expense_petty_cash +#: code:addons/hr_expense_petty_cash/models/account_move.py:0 +#, python-format +msgid "{} with petty cash checked must contain only 1 line." +msgstr "" From 077df650afc13067639b0d0223c972884195d9d7 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Mon, 2 Nov 2020 07:16:40 +0000 Subject: [PATCH 12/41] [UPD] README.rst --- hr_expense_petty_cash/README.rst | 16 ++++++++-------- .../static/description/index.html | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/hr_expense_petty_cash/README.rst b/hr_expense_petty_cash/README.rst index 75f2a0f08..75074fb38 100644 --- a/hr_expense_petty_cash/README.rst +++ b/hr_expense_petty_cash/README.rst @@ -13,14 +13,14 @@ Petty Cash .. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 -.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fhr-lightgray.png?logo=github - :target: https://github.com/OCA/hr/tree/12.0/hr_expense_petty_cash - :alt: OCA/hr +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fhr--expense-lightgray.png?logo=github + :target: https://github.com/OCA/hr-expense/tree/13.0/hr_expense_petty_cash + :alt: OCA/hr-expense .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/hr-12-0/hr-12-0-hr_expense_petty_cash + :target: https://translation.odoo-community.org/projects/hr-expense-13-0/hr-expense-13-0-hr_expense_petty_cash :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/116/12.0 + :target: https://runbot.odoo-community.org/runbot/289/13.0 :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| @@ -86,10 +86,10 @@ if you configure journal in petty cash holder. Bug Tracker =========== -Bugs are tracked on `GitHub Issues `_. +Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -122,6 +122,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -This module is part of the `OCA/hr `_ project on GitHub. +This module is part of the `OCA/hr-expense `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/hr_expense_petty_cash/static/description/index.html b/hr_expense_petty_cash/static/description/index.html index 679103e39..087d35183 100644 --- a/hr_expense_petty_cash/static/description/index.html +++ b/hr_expense_petty_cash/static/description/index.html @@ -367,7 +367,7 @@

Petty Cash

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: AGPL-3 OCA/hr Translate me on Weblate Try me on Runbot

+

Beta License: AGPL-3 OCA/hr-expense Translate me on Weblate Try me on Runbot

This module work about expense that paid by petty cash.

General Process:

    @@ -435,10 +435,10 @@

    Usage

Bug Tracker

-

Bugs are tracked on GitHub Issues. +

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed -feedback.

+feedback.

Do not contact contributors directly about support or help with technical issues.

@@ -466,7 +466,7 @@

Maintainers

OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.

-

This module is part of the OCA/hr project on GitHub.

+

This module is part of the OCA/hr-expense project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

From 2c8dc58757cac166f92e8447ebab8f3186a6a894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?= Date: Tue, 23 Mar 2021 10:24:43 +0100 Subject: [PATCH 13/41] [FIX] hr_expense_petty_cash: Fix tests according to journal_id is correct --- hr_expense_petty_cash/models/account_move.py | 23 ++++++++++++------- .../tests/test_hr_expense_petty_cash.py | 2 +- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/hr_expense_petty_cash/models/account_move.py b/hr_expense_petty_cash/models/account_move.py index 3aefb4558..ae74dfa87 100644 --- a/hr_expense_petty_cash/models/account_move.py +++ b/hr_expense_petty_cash/models/account_move.py @@ -109,7 +109,6 @@ def _add_petty_cash_invoice_line(self, petty_cash): def _onchange_is_petty_cash(self): self.line_ids = False self.invoice_line_ids = False - ctx = self._context.copy() if self.is_petty_cash: if not self.partner_id: raise ValidationError(_("Please select petty cash holder")) @@ -123,10 +122,18 @@ def _onchange_is_petty_cash(self): ) self.invoice_line_ids = self._add_petty_cash_invoice_line(petty_cash) if petty_cash.journal_id: - ctx.update( - { - "default_journal_id": petty_cash.journal_id.id, - "default_type": "general", - } - ) - self.journal_id = self.with_context(ctx)._get_default_journal() + # Prevent inconsistent journal_id + if ( + ( + self.type in self.get_sale_types(include_receipts=True) + and petty_cash.journal_id.type == "sale" + ) + or ( + self.type in self.get_purchase_types(include_receipts=True) + and petty_cash.journal_id.type == "purchase" + ) + or ( + self.type == "entry" and petty_cash.journal_id.type == "general" + ) + ): + self.journal_id = petty_cash.journal_id.id diff --git a/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py b/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py index bf088a6af..eb2d363bf 100644 --- a/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py +++ b/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py @@ -34,7 +34,7 @@ def setUp(self): } ) self.petty_cash_journal_id = self.env["account.journal"].create( - {"code": "PC", "name": "Petty Cash", "type": "general"} + {"code": "PC", "name": "Petty Cash", "type": "purchase"} ) # Create a Petty Cash Account From 4114b51f2818ab10bcddcd00d5348ac629934452 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Fri, 26 Mar 2021 08:26:34 +0000 Subject: [PATCH 14/41] hr_expense_petty_cash 13.0.1.0.1 --- hr_expense_petty_cash/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hr_expense_petty_cash/__manifest__.py b/hr_expense_petty_cash/__manifest__.py index 13f972731..d46b10df7 100644 --- a/hr_expense_petty_cash/__manifest__.py +++ b/hr_expense_petty_cash/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Petty Cash", - "version": "13.0.1.0.0", + "version": "13.0.1.0.1", "category": "Human Resources", "author": "Ecosoft, Odoo Community Association (OCA)", "license": "AGPL-3", From 51b3ab07e3f9776d978595c1501818d083573ccc Mon Sep 17 00:00:00 2001 From: Saran440 Date: Fri, 6 Nov 2020 12:12:07 +0700 Subject: [PATCH 15/41] [IMP] add active/inactive petty_cash view --- hr_expense_petty_cash/models/petty_cash.py | 1 + .../views/petty_cash_views.xml | 41 ++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/hr_expense_petty_cash/models/petty_cash.py b/hr_expense_petty_cash/models/petty_cash.py index 89134b0af..ff49584be 100644 --- a/hr_expense_petty_cash/models/petty_cash.py +++ b/hr_expense_petty_cash/models/petty_cash.py @@ -9,6 +9,7 @@ class PettyCash(models.Model): _description = "Petty Cash" _rec_name = "partner_id" + active = fields.Boolean(default=True) partner_id = fields.Many2one( comodel_name="res.partner", string="Petty Cash Holder", required=True, ) diff --git a/hr_expense_petty_cash/views/petty_cash_views.xml b/hr_expense_petty_cash/views/petty_cash_views.xml index 0b008f681..29d58b170 100644 --- a/hr_expense_petty_cash/views/petty_cash_views.xml +++ b/hr_expense_petty_cash/views/petty_cash_views.xml @@ -6,9 +6,19 @@
+ + - + @@ -65,7 +75,34 @@ petty.cash - + + + + + + + + From 4a82ef93f4d12f180d0afcdfa9bdb29cb96c16c5 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Sat, 15 May 2021 17:33:19 +0000 Subject: [PATCH 16/41] [UPD] Update hr_expense_petty_cash.pot --- .../i18n/hr_expense_petty_cash.pot | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot b/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot index c69d71151..501b07900 100644 --- a/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot +++ b/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot @@ -25,6 +25,17 @@ msgstr "" msgid "Account on invoice line should be {}." msgstr "" +#. module: hr_expense_petty_cash +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash__active +msgid "Active" +msgstr "" + +#. module: hr_expense_petty_cash +#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_petty_cash_form +#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_petty_cash_search +msgid "Archived" +msgstr "" + #. module: hr_expense_petty_cash #: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash__petty_cash_balance #: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_petty_cash_list @@ -78,6 +89,7 @@ msgstr "" #. module: hr_expense_petty_cash #: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash__journal_id +#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_petty_cash_search msgid "Journal" msgstr "" @@ -140,6 +152,7 @@ msgstr "" #. module: hr_expense_petty_cash #: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash__account_id +#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_petty_cash_search msgid "Petty Cash Account" msgstr "" @@ -147,6 +160,7 @@ msgstr "" #: model:ir.model.fields,field_description:hr_expense_petty_cash.field_petty_cash__partner_id #: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.hr_expense_sheet_view_search_inherit #: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.hr_expense_view_search_inherit +#: model_terms:ir.ui.view,arch_db:hr_expense_petty_cash.view_petty_cash_search msgid "Petty Cash Holder" msgstr "" From e1cf739a11934313533589560f0eef968a050195 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Sat, 15 May 2021 17:41:41 +0000 Subject: [PATCH 17/41] hr_expense_petty_cash 13.0.1.1.0 --- hr_expense_petty_cash/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hr_expense_petty_cash/__manifest__.py b/hr_expense_petty_cash/__manifest__.py index d46b10df7..29632c0d1 100644 --- a/hr_expense_petty_cash/__manifest__.py +++ b/hr_expense_petty_cash/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Petty Cash", - "version": "13.0.1.0.1", + "version": "13.0.1.1.0", "category": "Human Resources", "author": "Ecosoft, Odoo Community Association (OCA)", "license": "AGPL-3", From 5708689fb629a997224c27968e8227f5f29b301a Mon Sep 17 00:00:00 2001 From: modnoting Date: Mon, 16 Nov 2020 11:59:38 +0700 Subject: [PATCH 18/41] [IMP] hr_expense_petty_cash: black, isort, prettier --- hr_expense_petty_cash/README.rst | 19 ++++++++++------- hr_expense_petty_cash/__init__.py | 1 + hr_expense_petty_cash/__manifest__.py | 3 ++- .../i18n/hr_expense_petty_cash.pot | 10 +++++++-- hr_expense_petty_cash/models/__init__.py | 1 + hr_expense_petty_cash/models/account_move.py | 10 +++++++-- hr_expense_petty_cash/models/hr_expense.py | 2 +- .../models/hr_expense_sheet.py | 5 ++++- hr_expense_petty_cash/models/petty_cash.py | 21 ++++++++++++++----- hr_expense_petty_cash/readme/CONTRIBUTORS.rst | 4 ++++ .../static/description/index.html | 4 ++++ hr_expense_petty_cash/tests/__init__.py | 1 + .../tests/test_hr_expense_petty_cash.py | 13 +++++++++--- .../views/account_move_views.xml | 2 +- 14 files changed, 72 insertions(+), 24 deletions(-) diff --git a/hr_expense_petty_cash/README.rst b/hr_expense_petty_cash/README.rst index 75074fb38..e5040b383 100644 --- a/hr_expense_petty_cash/README.rst +++ b/hr_expense_petty_cash/README.rst @@ -14,16 +14,16 @@ Petty Cash :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fhr--expense-lightgray.png?logo=github - :target: https://github.com/OCA/hr-expense/tree/13.0/hr_expense_petty_cash + :target: https://github.com/OCA/hr-expense/tree/14.0/hr_expense_petty_cash :alt: OCA/hr-expense .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/hr-expense-13-0/hr-expense-13-0-hr_expense_petty_cash + :target: https://translation.odoo-community.org/projects/hr-expense-14-0/hr-expense-13-0-hr_expense_petty_cash :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/289/13.0 + :target: https://runbot.odoo-community.org/runbot/289/14.0 :alt: Try me on Runbot -|badge1| |badge2| |badge3| |badge4| |badge5| +|badge1| |badge2| |badge3| |badge4| |badge5| This module work about expense that paid by petty cash. @@ -89,7 +89,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -98,17 +98,20 @@ Credits Authors ~~~~~~~ - * Ecosoft +* Trinityroots Contributors ~~~~~~~~~~~~ - * `Ecosoft `__: * Pimolnat Suntian * Saran Lim. +* `Trinityroots `__: + + * Santi Techatoo + Maintainers ~~~~~~~~~~~ @@ -122,6 +125,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -This module is part of the `OCA/hr-expense `_ project on GitHub. +This module is part of the `OCA/hr-expense `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/hr_expense_petty_cash/__init__.py b/hr_expense_petty_cash/__init__.py index 4fb530fd1..005fdc68a 100644 --- a/hr_expense_petty_cash/__init__.py +++ b/hr_expense_petty_cash/__init__.py @@ -1,4 +1,5 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# Copyright 2020 Trinityroots Co., Ltd. (http://trinityroots.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from . import models diff --git a/hr_expense_petty_cash/__manifest__.py b/hr_expense_petty_cash/__manifest__.py index 29632c0d1..df286f06e 100644 --- a/hr_expense_petty_cash/__manifest__.py +++ b/hr_expense_petty_cash/__manifest__.py @@ -1,9 +1,10 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# Copyright 2020 Trinityroots Co., Ltd. (http://trinityroots.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { "name": "Petty Cash", - "version": "13.0.1.1.0", + "version": "14.0.1.0.0", "category": "Human Resources", "author": "Ecosoft, Odoo Community Association (OCA)", "license": "AGPL-3", diff --git a/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot b/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot index 501b07900..d77c4f339 100644 --- a/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot +++ b/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot @@ -1,10 +1,10 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * hr_expense_petty_cash +# * hr_expense_petty_cash # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 13.0\n" +"Project-Id-Version: Odoo Server 14.0\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: \n" "Language-Team: \n" @@ -62,6 +62,11 @@ msgstr "" msgid "Display Name" msgstr "" +#. module: hr_expense_petty_cash +#: selection:hr.expense,payment_mode:0 +msgid "Employee (to reimburse)" +msgstr "" + #. module: hr_expense_petty_cash #: model:ir.model,name:hr_expense_petty_cash.model_hr_expense msgid "Expense" @@ -133,6 +138,7 @@ msgstr "" #. module: hr_expense_petty_cash #: model:ir.model.fields,field_description:hr_expense_petty_cash.field_hr_expense__payment_mode +#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_hr_expense_sheet__payment_mode msgid "Paid By" msgstr "" diff --git a/hr_expense_petty_cash/models/__init__.py b/hr_expense_petty_cash/models/__init__.py index e60741242..2d5315221 100644 --- a/hr_expense_petty_cash/models/__init__.py +++ b/hr_expense_petty_cash/models/__init__.py @@ -1,4 +1,5 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# Copyright 2020 Trinityroots Co., Ltd. (http://trinityroots.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from . import account_move diff --git a/hr_expense_petty_cash/models/account_move.py b/hr_expense_petty_cash/models/account_move.py index ae74dfa87..a97baf4eb 100644 --- a/hr_expense_petty_cash/models/account_move.py +++ b/hr_expense_petty_cash/models/account_move.py @@ -1,4 +1,5 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# Copyright 2020 Trinityroots Co., Ltd. (http://trinityroots.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import _, api, fields, models @@ -10,7 +11,9 @@ class AccountMove(models.Model): _inherit = "account.move" is_petty_cash = fields.Boolean( - string="Petty Cash", readonly=True, states={"draft": [("readonly", False)]}, + string="Petty Cash", + readonly=True, + states={"draft": [("readonly", False)]}, ) def action_post(self): @@ -91,7 +94,10 @@ def _add_petty_cash_invoice_line(self, petty_cash): amount = petty_cash.petty_cash_limit - petty_cash.petty_cash_balance company_currency = self.env.user.company_id.currency_id amount_doc_currency = company_currency._convert( - amount, self.currency_id, self.company_id, self.date or fields.Date.today(), + amount, + self.currency_id, + self.company_id, + self.date or fields.Date.today(), ) inv_line = self.env["account.move.line"].new( diff --git a/hr_expense_petty_cash/models/hr_expense.py b/hr_expense_petty_cash/models/hr_expense.py index 132e19909..206caf26f 100644 --- a/hr_expense_petty_cash/models/hr_expense.py +++ b/hr_expense_petty_cash/models/hr_expense.py @@ -1,4 +1,5 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# Copyright 2020 Trinityroots Co., Ltd. (http://trinityroots.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import _, fields, models @@ -46,7 +47,6 @@ def _create_sheet_from_expense_petty_cash(self): .with_context(ctx) .create(self._prepare_expense_vals()) ) - sheet._onchange_employee_id() return sheet def _create_sheet_from_expenses(self): diff --git a/hr_expense_petty_cash/models/hr_expense_sheet.py b/hr_expense_petty_cash/models/hr_expense_sheet.py index 240e6f9bf..a303504f1 100644 --- a/hr_expense_petty_cash/models/hr_expense_sheet.py +++ b/hr_expense_petty_cash/models/hr_expense_sheet.py @@ -1,4 +1,5 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# Copyright 2020 Trinityroots Co., Ltd. (http://trinityroots.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import _, api, fields, models @@ -26,7 +27,9 @@ def _default_journal_id(self): ondelete="restrict", compute="_compute_petty_cash", ) - journal_id = fields.Many2one(default=_default_journal_id) + journal_id = fields.Many2one( + comodel_name="account.journal", default=_default_journal_id + ) @api.depends("expense_line_ids", "payment_mode") def _compute_petty_cash(self): diff --git a/hr_expense_petty_cash/models/petty_cash.py b/hr_expense_petty_cash/models/petty_cash.py index ff49584be..ea9ee6e12 100644 --- a/hr_expense_petty_cash/models/petty_cash.py +++ b/hr_expense_petty_cash/models/petty_cash.py @@ -1,4 +1,5 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# Copyright 2020 Trinityroots Co., Ltd. (http://trinityroots.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import api, fields, models @@ -11,16 +12,26 @@ class PettyCash(models.Model): active = fields.Boolean(default=True) partner_id = fields.Many2one( - comodel_name="res.partner", string="Petty Cash Holder", required=True, + comodel_name="res.partner", + string="Petty Cash Holder", + required=True, ) account_id = fields.Many2one( - comodel_name="account.account", string="Petty Cash Account", required=True, + comodel_name="account.account", + string="Petty Cash Account", + required=True, + ) + petty_cash_limit = fields.Float( + string="Max Limit", + required=True, ) - petty_cash_limit = fields.Float(string="Max Limit", required=True,) petty_cash_balance = fields.Float( - string="Balance", compute="_compute_petty_cash_balance", + string="Balance", + compute="_compute_petty_cash_balance", + ) + journal_id = fields.Many2one( + comodel_name="account.journal", ) - journal_id = fields.Many2one(comodel_name="account.journal",) _sql_constraints = [ ("partner_uniq", "unique(partner_id)", "Petty Cash Holder must be unique!"), ] diff --git a/hr_expense_petty_cash/readme/CONTRIBUTORS.rst b/hr_expense_petty_cash/readme/CONTRIBUTORS.rst index 8b17ebf09..7ad5c5105 100644 --- a/hr_expense_petty_cash/readme/CONTRIBUTORS.rst +++ b/hr_expense_petty_cash/readme/CONTRIBUTORS.rst @@ -2,3 +2,7 @@ * Pimolnat Suntian * Saran Lim. + +* `Trinityroots `__: + + * Santi Techatoo diff --git a/hr_expense_petty_cash/static/description/index.html b/hr_expense_petty_cash/static/description/index.html index 087d35183..60d293c79 100644 --- a/hr_expense_petty_cash/static/description/index.html +++ b/hr_expense_petty_cash/static/description/index.html @@ -456,6 +456,10 @@

Contributors

  • Pimolnat Suntian <pimolnats@ecosoft.co.th>
  • Saran Lim. <saranl@ecosoft.co.th>
  • + diff --git a/hr_expense_petty_cash/tests/__init__.py b/hr_expense_petty_cash/tests/__init__.py index 9187e19b9..62ead3b38 100644 --- a/hr_expense_petty_cash/tests/__init__.py +++ b/hr_expense_petty_cash/tests/__init__.py @@ -1,4 +1,5 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# Copyright 2020 Trinityroots Co., Ltd. (http://trinityroots.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from . import test_hr_expense_petty_cash diff --git a/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py b/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py index eb2d363bf..dbfb6846c 100644 --- a/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py +++ b/hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py @@ -1,4 +1,5 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# Copyright 2020 Trinityroots Co., Ltd. (http://trinityroots.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo.exceptions import UserError, ValidationError @@ -53,6 +54,7 @@ def _create_petty_cash_holder(self, partner): { "partner_id": partner.id, "account_id": self.petty_cash_account_id.id, + "journal_id": self.petty_cash_journal_id.id, "petty_cash_limit": 1000.0, } ) @@ -60,7 +62,11 @@ def _create_petty_cash_holder(self, partner): def _create_invoice(self, partner=False): invoice = self.env["account.move"].create( - {"partner_id": partner, "type": "in_invoice"} + { + "partner_id": partner, + "move_type": "in_invoice", + "journal_id": self.petty_cash_holder.journal_id.id, + } ) return invoice @@ -95,7 +101,7 @@ def _create_multi_invoice_line(self, petty_cash=False): invoice = self.env["account.move"].create( { "partner_id": self.partner_1.id, - "type": "in_invoice", + "move_type": "in_invoice", "is_petty_cash": petty_cash, "invoice_line_ids": [ ( @@ -158,7 +164,7 @@ def _check_warning(self): invoice = self.env["account.move"].create( { "partner_id": self.partner_1.id, - "type": "in_invoice", + "move_type": "in_invoice", "invoice_line_ids": [ ( 0, @@ -196,6 +202,7 @@ def test_02_create_expense_petty_cash(self): with Form(invoice) as inv: inv.is_petty_cash = True inv.invoice_line_ids.price_unit = 1000.0 + invoice.action_post() self.petty_cash_holder._compute_petty_cash_balance() self.assertEqual(self.petty_cash_holder.petty_cash_balance, 1000.0) diff --git a/hr_expense_petty_cash/views/account_move_views.xml b/hr_expense_petty_cash/views/account_move_views.xml index af67a0940..d85154a47 100644 --- a/hr_expense_petty_cash/views/account_move_views.xml +++ b/hr_expense_petty_cash/views/account_move_views.xml @@ -8,7 +8,7 @@
    From 79ce0e3b17b13b8b0b27f166dd09bd17c980af3d Mon Sep 17 00:00:00 2001 From: modnoting Date: Mon, 16 Nov 2020 11:59:38 +0700 Subject: [PATCH 19/41] [MIG] hr_expense_petty_cash: Migration to 14.0 --- hr_expense_petty_cash/README.rst | 7 ++++--- hr_expense_petty_cash/__init__.py | 1 - hr_expense_petty_cash/__manifest__.py | 1 - .../i18n/hr_expense_petty_cash.pot | 10 ++-------- hr_expense_petty_cash/models/__init__.py | 1 - hr_expense_petty_cash/models/account_move.py | 8 ++++---- hr_expense_petty_cash/models/hr_expense.py | 1 - hr_expense_petty_cash/models/hr_expense_sheet.py | 4 ++-- hr_expense_petty_cash/models/petty_cash.py | 1 - .../static/description/index.html | 14 +++++++------- hr_expense_petty_cash/tests/__init__.py | 1 - .../tests/test_hr_expense_petty_cash.py | 8 ++++---- 12 files changed, 23 insertions(+), 34 deletions(-) diff --git a/hr_expense_petty_cash/README.rst b/hr_expense_petty_cash/README.rst index e5040b383..cb20830e4 100644 --- a/hr_expense_petty_cash/README.rst +++ b/hr_expense_petty_cash/README.rst @@ -17,13 +17,13 @@ Petty Cash :target: https://github.com/OCA/hr-expense/tree/14.0/hr_expense_petty_cash :alt: OCA/hr-expense .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/hr-expense-14-0/hr-expense-13-0-hr_expense_petty_cash + :target: https://translation.odoo-community.org/projects/hr-expense-14-0/hr-expense-14-0-hr_expense_petty_cash :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png :target: https://runbot.odoo-community.org/runbot/289/14.0 :alt: Try me on Runbot -|badge1| |badge2| |badge3| |badge4| |badge5| +|badge1| |badge2| |badge3| |badge4| |badge5| This module work about expense that paid by petty cash. @@ -98,11 +98,12 @@ Credits Authors ~~~~~~~ + * Ecosoft -* Trinityroots Contributors ~~~~~~~~~~~~ + * `Ecosoft `__: * Pimolnat Suntian diff --git a/hr_expense_petty_cash/__init__.py b/hr_expense_petty_cash/__init__.py index 005fdc68a..4fb530fd1 100644 --- a/hr_expense_petty_cash/__init__.py +++ b/hr_expense_petty_cash/__init__.py @@ -1,5 +1,4 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) -# Copyright 2020 Trinityroots Co., Ltd. (http://trinityroots.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from . import models diff --git a/hr_expense_petty_cash/__manifest__.py b/hr_expense_petty_cash/__manifest__.py index df286f06e..34e3410db 100644 --- a/hr_expense_petty_cash/__manifest__.py +++ b/hr_expense_petty_cash/__manifest__.py @@ -1,5 +1,4 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) -# Copyright 2020 Trinityroots Co., Ltd. (http://trinityroots.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { diff --git a/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot b/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot index d77c4f339..501b07900 100644 --- a/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot +++ b/hr_expense_petty_cash/i18n/hr_expense_petty_cash.pot @@ -1,10 +1,10 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * hr_expense_petty_cash +# * hr_expense_petty_cash # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 14.0\n" +"Project-Id-Version: Odoo Server 13.0\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: \n" "Language-Team: \n" @@ -62,11 +62,6 @@ msgstr "" msgid "Display Name" msgstr "" -#. module: hr_expense_petty_cash -#: selection:hr.expense,payment_mode:0 -msgid "Employee (to reimburse)" -msgstr "" - #. module: hr_expense_petty_cash #: model:ir.model,name:hr_expense_petty_cash.model_hr_expense msgid "Expense" @@ -138,7 +133,6 @@ msgstr "" #. module: hr_expense_petty_cash #: model:ir.model.fields,field_description:hr_expense_petty_cash.field_hr_expense__payment_mode -#: model:ir.model.fields,field_description:hr_expense_petty_cash.field_hr_expense_sheet__payment_mode msgid "Paid By" msgstr "" diff --git a/hr_expense_petty_cash/models/__init__.py b/hr_expense_petty_cash/models/__init__.py index 2d5315221..e60741242 100644 --- a/hr_expense_petty_cash/models/__init__.py +++ b/hr_expense_petty_cash/models/__init__.py @@ -1,5 +1,4 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) -# Copyright 2020 Trinityroots Co., Ltd. (http://trinityroots.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from . import account_move diff --git a/hr_expense_petty_cash/models/account_move.py b/hr_expense_petty_cash/models/account_move.py index a97baf4eb..1e41c470b 100644 --- a/hr_expense_petty_cash/models/account_move.py +++ b/hr_expense_petty_cash/models/account_move.py @@ -1,5 +1,4 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) -# Copyright 2020 Trinityroots Co., Ltd. (http://trinityroots.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import _, api, fields, models @@ -131,15 +130,16 @@ def _onchange_is_petty_cash(self): # Prevent inconsistent journal_id if ( ( - self.type in self.get_sale_types(include_receipts=True) + self.move_type in self.get_sale_types(include_receipts=True) and petty_cash.journal_id.type == "sale" ) or ( - self.type in self.get_purchase_types(include_receipts=True) + self.move_type in self.get_purchase_types(include_receipts=True) and petty_cash.journal_id.type == "purchase" ) or ( - self.type == "entry" and petty_cash.journal_id.type == "general" + self.move_type == "entry" + and petty_cash.journal_id.type == "general" ) ): self.journal_id = petty_cash.journal_id.id diff --git a/hr_expense_petty_cash/models/hr_expense.py b/hr_expense_petty_cash/models/hr_expense.py index 206caf26f..8db9379ae 100644 --- a/hr_expense_petty_cash/models/hr_expense.py +++ b/hr_expense_petty_cash/models/hr_expense.py @@ -1,5 +1,4 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) -# Copyright 2020 Trinityroots Co., Ltd. (http://trinityroots.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import _, fields, models diff --git a/hr_expense_petty_cash/models/hr_expense_sheet.py b/hr_expense_petty_cash/models/hr_expense_sheet.py index a303504f1..bdb9319d5 100644 --- a/hr_expense_petty_cash/models/hr_expense_sheet.py +++ b/hr_expense_petty_cash/models/hr_expense_sheet.py @@ -1,5 +1,4 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) -# Copyright 2020 Trinityroots Co., Ltd. (http://trinityroots.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import _, api, fields, models @@ -28,7 +27,8 @@ def _default_journal_id(self): compute="_compute_petty_cash", ) journal_id = fields.Many2one( - comodel_name="account.journal", default=_default_journal_id + comodel_name="account.journal", + default=_default_journal_id, ) @api.depends("expense_line_ids", "payment_mode") diff --git a/hr_expense_petty_cash/models/petty_cash.py b/hr_expense_petty_cash/models/petty_cash.py index ea9ee6e12..3a353511f 100644 --- a/hr_expense_petty_cash/models/petty_cash.py +++ b/hr_expense_petty_cash/models/petty_cash.py @@ -1,5 +1,4 @@ # Copyright 2019 Ecosoft Co., Ltd. (http://ecosoft.co.th) -# Copyright 2020 Trinityroots Co., Ltd. (http://trinityroots.co.th) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import api, fields, models diff --git a/hr_expense_petty_cash/static/description/index.html b/hr_expense_petty_cash/static/description/index.html index 60d293c79..121cd5ed2 100644 --- a/hr_expense_petty_cash/static/description/index.html +++ b/hr_expense_petty_cash/static/description/index.html @@ -3,7 +3,7 @@ - + Petty Cash