diff --git a/act_revise/README.md b/act_revise/README.md deleted file mode 100644 index 5384752..0000000 --- a/act_revise/README.md +++ /dev/null @@ -1,93 +0,0 @@ -# act_revise - - - -## Getting started - -To make it easy for you to get started with GitLab, here's a list of recommended next steps. - -Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! - -## Add your files - -- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files -- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command: - -``` -cd existing_repo -git remote add origin https://gitlab.inf-centre.ru/mklab-base/l10n-russia/act_revise.git -git branch -M v17-dev -git push -uf origin v17-dev -``` - -## Integrate with your tools - -- [ ] [Set up project integrations](https://gitlab.inf-centre.ru/mklab-base/l10n-russia/act_revise/-/settings/integrations) - -## Collaborate with your team - -- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) -- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) -- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) -- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) -- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html) - -## Test and Deploy - -Use the built-in continuous integration in GitLab. - -- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html) -- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) -- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) -- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/) -- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) - -*** - -# Editing this README - -When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template. - -## Suggestions for a good README - -Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information. - -## Name -Choose a self-explaining name for your project. - -## Description -Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors. - -## Badges -On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. - -## Visuals -Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method. - -## Installation -Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection. - -## Usage -Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. - -## Support -Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. - -## Roadmap -If you have ideas for releases in the future, it is a good idea to list them in the README. - -## Contributing -State if you are open to contributions and what your requirements are for accepting them. - -For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. - -You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. - -## Authors and acknowledgment -Show your appreciation to those who have contributed to the project. - -## License -For open source projects, say how it is licensed. - -## Project status -If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. diff --git a/act_revise/__init__.py b/act_revise/__init__.py deleted file mode 100644 index 778f647..0000000 --- a/act_revise/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from . import models -from . import report -from . import wizard -from . import controllers diff --git a/act_revise/__manifest__.py b/act_revise/__manifest__.py deleted file mode 100644 index 830ebc7..0000000 --- a/act_revise/__manifest__.py +++ /dev/null @@ -1,45 +0,0 @@ -# -*- coding: utf-8 -*- -{ - 'name': "act_revise", - - 'summary': """ - Добавление отчета акт сверки""", - - 'description': """ - Добавление формы акт сверки, находящегося в контактах, с помощью которого можно легко отслеживать дебеторские и кредиторские проводки с клиентами. - - Для печати: - 1. Выбираем меню Контакты - конкретного партнера - Действия - "Печать акт сверки"; - 2. В визарде выбираем: - 2.1. Компанию (для которой нужна сверка с выбранным контактом); - 2.2. Период сверки; - 2.3. Цель (один из режимом: все проведенные проводки или все проводки, включая черновики); - 3. Кнопка "Печать" - - """, - - 'author': "Odoo Community Association (OCA), MK Lab", - 'website': "https://www.inf-centre.ru/", - - 'category': 'Uncategorized', - 'version': '0.1', - - # any module necessary for this one to work correctly - "depends": ["account", "portal", "website", "l10n_ru_doc", 'contract'], - "data": [ - "security/ir.model.access.csv", - "wizard/general_ledger_wizard_view.xml", - "report/layouts.xml", - "report/general_ledger.xml", - "views/account_account_views.xml", - "views/report_general_ledger.xml", - "views/portal_templates.xml", - ], - "installable": True, - "application": True, - "auto_install": False, - # only loaded in demonstration mode - 'demo': [ - 'demo/demo.xml', - ], -} diff --git a/act_revise/controllers/__init__.py b/act_revise/controllers/__init__.py deleted file mode 100644 index 457bae2..0000000 --- a/act_revise/controllers/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -*- coding: utf-8 -*- - -from . import controllers \ No newline at end of file diff --git a/act_revise/controllers/controllers.py b/act_revise/controllers/controllers.py deleted file mode 100644 index 55c7062..0000000 --- a/act_revise/controllers/controllers.py +++ /dev/null @@ -1,89 +0,0 @@ -from odoo import http -from odoo.http import request -from datetime import datetime, date - - -class ActRevise(http.Controller): - - @http.route(['/my/act_revise/'], type='http', auth="public", website=True) - def print_report(self): - partner = request.env.user.partner_id.parent_id.id - partner_name = request.env.user.partner_id.parent_id.name - if not partner: - partner = request.env.user.partner_id.id - partner_name = request.env.user.partner_id.name - company = request.env.user.company_id.id - company_name = request.env.user.company_id.name - today = date.today() - d1 = today.strftime("%d.%m.%y") - - wizard_data = { - "target_move": "posted", - "hide_account_at_0": True, - "foreign_currency": True, - "company_id": company, - "partner_ids": [partner], - "show_cost_center": True, - "centralize": True - } - wizard_record = request.env['general.ledger.act_revise.wizard'].sudo().create(wizard_data) - - action = request.env.ref('act_revise.action_general_ledger_wizard').read()[0] - action['res_id'] = wizard_record.id - action['context'] = dict(request.env.context) - return request.redirect('/web#action=' + str(action['id']) + '&id=' + str(wizard_record.id) + '&view_type=form') - - # @http.route(['/my/act_revise/'], type='http', auth="public", website=True) - # def print_report(self): - # partner = request.env.user.partner_id.parent_id.id - # partner_name = request.env.user.partner_id.parent_id.name - # if not partner: - # partner = request.env.user.partner_id.id - # partner_name = request.env.user.partner_id.name - # company = request.env.user.company_id.id - # company_name = request.env.user.company_id.name - # today = date.today() - # d1 = today.strftime("%d.%m.%y") - # # new_url = str('Акт Сверки ' + d1 + ' ' + company_name + '_' + partner_name) - # # new_url=str('AC ' + company +' - ' + partner + ' ' + d1) - # # if request.httprequest.full_path == '/my/act_revise/a?': - # # return werkzeug.utils.redirect('/my/act_revise/%s' % new_url) - # wizard_data = {"target_move": "posted", - # "hide_account_at_0": True, - # "foreign_currency": True, - # #"show_analytic_tags": True, - # "company_id": company, - # "partner_ids": [partner], - # #"show_partner_details": True, - # "show_cost_center": True, - # "centralize": True} - # t = request.env['general.ledger.act_revise.wizard'].sudo().create(wizard_data) - # data = t._prepare_report_general_ledger() - # name = t.get_report_filename() - # report_name = name.encode('cp1251') - # pdf, _ = request.env['ir.actions.report']._render_qweb_pdf( - # 'act_revise.action_print_report_general_ledger_qweb', res_ids=t.id, data=data) - # pdfhttpheaders = [('Content-Type', 'application/pdf'), ('Content-Length', len(pdf)), ] - # return request.make_response(pdf, headers=pdfhttpheaders) - - @http.route(['/my/act_revise_contact/'], type='http', auth="public", website=True) - def print_report_contact(self, date_to, date_from, target_move, company, partner): - partner_id = int(partner) or 'default_partner_value' - company_id = int(company) - wizard_data = {"date_to": date_to, - "date_from": date_from, - "target_move": target_move, - "hide_account_at_0": True, - "foreign_currency": True, - #"show_analytic_tags": True, - "company_id": company_id, - "partner_ids": [partner_id], - #"show_partner_details": True, - "show_cost_center": True, - "centralize": True} - t = request.env['general.ledger.act_revise.wizard'].sudo().create(wizard_data) - data = t._prepare_report_general_ledger() - pdf, _ = request.env['ir.actions.report']._render_qweb_pdf( - 'act_revise.action_print_report_general_ledger_qweb', res_ids=t.id, data=data) - pdfhttpheaders = [('Content-Type', 'application/pdf'), ('Content-Length', len(pdf)), ] - return request.make_response(pdf, headers=pdfhttpheaders) \ No newline at end of file diff --git a/act_revise/demo/demo.xml b/act_revise/demo/demo.xml deleted file mode 100644 index 340fdd0..0000000 --- a/act_revise/demo/demo.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - \ No newline at end of file diff --git a/act_revise/models/__init__.py b/act_revise/models/__init__.py deleted file mode 100644 index f75a803..0000000 --- a/act_revise/models/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from . import account_account -from . import ir_actions_report \ No newline at end of file diff --git a/act_revise/models/account_account.py b/act_revise/models/account_account.py deleted file mode 100644 index 3e251fe..0000000 --- a/act_revise/models/account_account.py +++ /dev/null @@ -1,7 +0,0 @@ -from odoo import fields, models, _ - - -class AccountAccount(models.Model): - _inherit = "account.account" - - centralized = fields.Boolean(_("Централизованно")) diff --git a/act_revise/models/ir_actions_report.py b/act_revise/models/ir_actions_report.py deleted file mode 100644 index b0f8377..0000000 --- a/act_revise/models/ir_actions_report.py +++ /dev/null @@ -1,10 +0,0 @@ -from odoo import api, models - - -class IrActionsReport(models.Model): - _inherit = "ir.actions.report" - - @api.model - def _prepare_account_financial_report_context(self, data): - lang = data and data.get("account_financial_report_lang") or "" - return dict(self.env.context or {}, lang=lang) if lang else False diff --git a/act_revise/report/__init__.py b/act_revise/report/__init__.py deleted file mode 100644 index f7ccab0..0000000 --- a/act_revise/report/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from . import general_ledger - diff --git a/act_revise/report/general_ledger.py b/act_revise/report/general_ledger.py deleted file mode 100644 index d2c99d8..0000000 --- a/act_revise/report/general_ledger.py +++ /dev/null @@ -1,1045 +0,0 @@ -import calendar -import datetime -import operator - -from odoo.exceptions import UserError -from odoo import _, api, models -from odoo.tools import float_is_zero - -class GeneralLedgerReport(models.AbstractModel): - _name = "report.act_revise.general_ledger" - _description = "General Ledger Report" - - COMMON_ML_FIELDS = [ - "account_id", - "partner_id", - "journal_id", - "move_type", - "date", - "ref", - "id", - "move_id", - "name", - ] - - @api.model - def _get_move_lines_domain_not_reconciled( - self, company_id, account_ids, partner_ids, only_posted_moves, date_from - ): - domain = [ - ("account_id", "in", account_ids), - ("company_id", "=", company_id), - ("reconciled", "=", False), - ] - if partner_ids: - domain += [("partner_id", "in", partner_ids)] - if only_posted_moves: - domain += [("move_id.state", "=", "posted")] - else: - domain += [("move_id.state", "in", ["posted", "draft"])] - if date_from: - domain += [("date", ">", date_from)] - return domain - - @api.model - def _get_new_move_lines_domain( - self, new_ml_ids, account_ids, company_id, partner_ids, only_posted_moves - ): - domain = [ - ("account_id", "in", account_ids), - ("company_id", "=", company_id), - ("id", "in", new_ml_ids), - ] - if partner_ids: - domain += [("partner_id", "in", partner_ids)] - if only_posted_moves: - domain += [("move_id.state", "=", "posted")] - else: - domain += [("move_id.state", "in", ["posted", "draft"])] - return domain - - def _recalculate_move_lines( - self, - move_lines, - move_type, - debit_ids, - credit_ids, - debit_amount, - credit_amount, - ml_ids, - account_ids, - company_id, - partner_ids, - only_posted_moves, - debit_amount_currency, - credit_amount_currency, - ): - debit_ids = set(debit_ids) - credit_ids = set(credit_ids) - in_credit_but_not_in_debit = credit_ids - debit_ids - reconciled_ids = list(debit_ids) + list(in_credit_but_not_in_debit) - reconciled_ids = set(reconciled_ids) - ml_ids = set(ml_ids) - new_ml_ids = reconciled_ids - ml_ids - new_ml_ids = list(new_ml_ids) - new_domain = self._get_new_move_lines_domain( - new_ml_ids, account_ids, company_id, partner_ids, only_posted_moves - ) - company_currency = self.env["res.company"].browse(company_id).currency_id - ml_fields = self._get_ml_fields() - new_move_lines = self.env["account.move.line"].search_read( - domain=new_domain, fields=ml_fields - ) - move_lines = move_lines + new_move_lines - for move_line in move_lines: - ml_id = move_line["id"] - if ml_id in debit_ids: - if move_line.get("amount_residual", False): - move_line["amount_residual"] += debit_amount[ml_id] - else: - move_line["amount_residual"] = debit_amount[ml_id] - if move_line.get("amount_residual_currency", False): - move_line["amount_residual_currency"] += debit_amount_currency[ - ml_id - ] - else: - move_line["amount_residual_currency"] = debit_amount_currency[ml_id] - if ml_id in credit_ids: - if move_line.get("amount_residual", False): - move_line["amount_residual"] -= credit_amount[ml_id] - else: - move_line["amount_residual"] = -credit_amount[ml_id] - if move_line.get("amount_residual_currency", False): - move_line["amount_residual_currency"] -= credit_amount_currency[ - ml_id - ] - else: - move_line["amount_residual_currency"] = -credit_amount_currency[ - ml_id - ] - # Set amount_currency=0 to keep the same behaviour as in v13 - # Conditions: if there is no curency_id defined or it is equal - # to the company's curency_id - if "amount_currency" in move_line and ( - "currency_id" not in move_line - or move_line["currency_id"] == company_currency.id - ): - move_line["amount_currency"] = 0 - return move_lines - - def _get_accounts_data(self, accounts_ids): - accounts = self.env["account.account"].browse(accounts_ids) - accounts_data = {} - for account in accounts: - accounts_data.update( - { - account.id: { - "id": account.id, - "code": account.code, - "name": account.name, - "hide_account": False, - "group_id": account.group_id.id, - "currency_id": account.currency_id.id, - "currency_name": account.currency_id.name, - "centralized": account.centralized, - } - } - ) - return accounts_data - - def _get_journals_data(self, journals_ids): - journals = self.env["account.journal"].browse(journals_ids) - journals_data = {} - for journal in journals: - journals_data.update({journal.id: {"id": journal.id, "code": journal.code}}) - return journals_data - - def _get_analytic_data(self, account_ids): - analytic_accounts = self.env["account.analytic.account"].browse(account_ids) - analytic_data = {} - for account in analytic_accounts: - analytic_data.update({account.id: {"name": account.name}}) - return analytic_data - - def _get_taxes_data(self, taxes_ids): - taxes = self.env["account.tax"].browse(taxes_ids) - taxes_data = {} - for tax in taxes: - taxes_data.update( - { - tax.id: { - "id": tax.id, - "amount": tax.amount, - "amount_type": tax.amount_type, - "display_name": tax.display_name, - } - } - ) - if tax.amount_type == "percent" or tax.amount_type == "division": - taxes_data[tax.id]["string"] = "%" - else: - taxes_data[tax.id]["string"] = "" - taxes_data[tax.id]["tax_name"] = ( - tax.display_name - + " (" - + str(tax.amount) - + taxes_data[tax.id]["string"] - + ")" - ) - return taxes_data - - def _get_account_type_domain(self, grouped_by): - """To avoid set all possible types, set in or not in as operator of the types - we are interested in. In v15 we used the internal_type field (type of - account.account.type).""" - at_op = "in" if grouped_by != "taxes" else "not in" - return [ - ("account_type", at_op, ["asset_receivable", "liability_payable"]), - ] - - def _get_acc_prt_accounts_ids(self, company_id, grouped_by): - accounts_domain = [ - ("company_id", "=", company_id), - ] + self._get_account_type_domain(grouped_by) - acc_prt_accounts = self.env["account.account"].search(accounts_domain) - return acc_prt_accounts.ids - - def _get_initial_balances_bs_ml_domain( - self, account_ids, company_id, date_from, base_domain, grouped_by, acc_prt=False - ): - accounts_domain = [ - ("company_id", "=", company_id), - ("include_initial_balance", "=", True), - ] - if account_ids: - accounts_domain += [("id", "in", account_ids)] - domain = [] - domain += base_domain - domain += [("date", "<", date_from)] - accounts = self.env["account.account"].search(accounts_domain) - domain += [("account_id", "in", accounts.ids)] - if acc_prt: - domain += self._get_account_type_domain(grouped_by) - return domain - - def _get_initial_balances_pl_ml_domain( - self, account_ids, company_id, date_from, fy_start_date, base_domain - ): - accounts_domain = [ - ("company_id", "=", company_id), - ("include_initial_balance", "=", False), - ] - if account_ids: - accounts_domain += [("id", "in", account_ids)] - domain = [] - domain += base_domain - domain += [("date", "<", date_from), ("date", ">=", fy_start_date)] - accounts = self.env["account.account"].search(accounts_domain) - domain += [("account_id", "in", accounts.ids)] - return domain - - def _get_accounts_initial_balance(self, initial_domain_bs, initial_domain_pl): - gl_initial_acc_bs = self.env["account.move.line"].read_group( - domain=initial_domain_bs, - fields=["account_id", "debit", "credit", "balance", "amount_currency:sum"], - groupby=["account_id"], - ) - gl_initial_acc_pl = self.env["account.move.line"].read_group( - domain=initial_domain_pl, - fields=["account_id", "debit", "credit", "balance", "amount_currency:sum"], - groupby=["account_id"], - ) - gl_initial_acc = gl_initial_acc_bs + gl_initial_acc_pl - return gl_initial_acc - - def _get_initial_balance_fy_pl_ml_domain( - self, account_ids, company_id, fy_start_date, base_domain - ): - accounts_domain = [ - ("company_id", "=", company_id), - ("include_initial_balance", "=", False), - ] - if account_ids: - accounts_domain += [("id", "in", account_ids)] - domain = [] - domain += base_domain - domain += [("date", "<", fy_start_date)] - accounts = self.env["account.account"].search(accounts_domain) - domain += [("account_id", "in", accounts.ids)] - return domain - - def _get_pl_initial_balance( - self, account_ids, company_id, fy_start_date, foreign_currency, base_domain - ): - domain = self._get_initial_balance_fy_pl_ml_domain( - account_ids, company_id, fy_start_date, base_domain - ) - initial_balances = self.env["account.move.line"].read_group( - domain=domain, - fields=["account_id", "debit", "credit", "balance", "amount_currency:sum"], - groupby=["account_id"], - ) - pl_initial_balance = { - "debit": 0.0, - "credit": 0.0, - "balance": 0.0, - "bal_curr": 0.0, - } - for initial_balance in initial_balances: - pl_initial_balance["debit"] += initial_balance["debit"] - pl_initial_balance["credit"] += initial_balance["credit"] - pl_initial_balance["balance"] += initial_balance["balance"] - pl_initial_balance["bal_curr"] += initial_balance["amount_currency"] - return pl_initial_balance - - def _get_gl_initial_acc( - self, account_ids, company_id, date_from, fy_start_date, base_domain, grouped_by - ): - initial_domain_bs = self._get_initial_balances_bs_ml_domain( - account_ids, company_id, date_from, base_domain, grouped_by - ) - initial_domain_pl = self._get_initial_balances_pl_ml_domain( - account_ids, company_id, date_from, fy_start_date, base_domain - ) - return self._get_accounts_initial_balance(initial_domain_bs, initial_domain_pl) - - def _prepare_gen_ld_data_item(self, gl): - res = {} - for key_bal in ["init_bal", "fin_bal"]: - res[key_bal] = {} - for key_field in ["credit", "debit", "balance", "bal_curr"]: - field_name = key_field if key_field != "bal_curr" else "amount_currency" - res[key_bal][key_field] = gl[field_name] - return res - - def _prepare_gen_ld_data(self, gl_initial_acc, domain, grouped_by): - data = {} - for gl in gl_initial_acc: - acc_id = gl["account_id"][0] - data[acc_id] = self._prepare_gen_ld_data_item(gl) - data[acc_id]["id"] = acc_id - if grouped_by: - data[acc_id][grouped_by] = False - method = "_prepare_gen_ld_data_group_%s" % grouped_by - if not hasattr(self, method): - return data - return getattr(self, method)(data, domain, grouped_by) - - def _prepare_gen_ld_data_group_partners(self, data, domain, grouped_by): - gl_initial_acc_prt = self.env["account.move.line"].read_group( - domain=domain, - fields=[ - "account_id", - "partner_id", - "debit", - "credit", - "balance", - "amount_currency:sum", - ], - groupby=["account_id", "partner_id"], - lazy=False, - ) - if gl_initial_acc_prt: - for gl in gl_initial_acc_prt: - if not gl["partner_id"]: - prt_id = 0 - prt_name = _("Missing Partner") - else: - prt_id = gl["partner_id"][0] - prt_name = gl["partner_id"][1] - prt_name = prt_name._value - acc_id = gl["account_id"][0] - data[acc_id][prt_id] = self._prepare_gen_ld_data_item(gl) - data[acc_id][prt_id]["id"] = prt_id - data[acc_id][prt_id]["name"] = prt_name - data[acc_id][grouped_by] = True - return data - - def _prepare_gen_ld_data_group_taxes(self, data, domain, grouped_by): - gl_initial_acc_prt = self.env["account.move.line"].read_group( - domain=domain, - fields=[ - "account_id", - "debit", - "credit", - "balance", - "amount_currency:sum", - "tax_line_id", - ], - groupby=["account_id"], - lazy=False, - ) - if gl_initial_acc_prt: - for gl in gl_initial_acc_prt: - if "tax_line_id" in gl and gl["tax_line_id"]: - tax_id = gl["tax_line_id"][0] - tax_name = gl["tax_line_id"][1] - tax_name = tax_name._value - else: - tax_id = 0 - tax_name = "Missing Tax" - acc_id = gl["account_id"][0] - data[acc_id][tax_id] = self._prepare_gen_ld_data_item(gl) - data[acc_id][tax_id]["id"] = tax_id - data[acc_id][tax_id]["name"] = tax_name - data[acc_id][grouped_by] = True - return data - - def _get_initial_balance_data( - self, - account_ids, - partner_ids, - company_id, - date_from, - foreign_currency, - only_posted_moves, - unaffected_earnings_account, - fy_start_date, - cost_center_ids, - extra_domain, - grouped_by, - ): - # If explicit list of accounts is provided, - # don't include unaffected earnings account - if account_ids: - unaffected_earnings_account = False - base_domain = [] - if company_id: - base_domain += [("company_id", "=", company_id)] - if partner_ids: - base_domain += [("partner_id", "in", partner_ids)] - if only_posted_moves: - base_domain += [("move_id.state", "=", "posted")] - else: - base_domain += [("move_id.state", "in", ["posted", "draft"])] - if cost_center_ids: - base_domain += [("analytic_account_ids", "in", cost_center_ids)] - if extra_domain: - base_domain += extra_domain - gl_initial_acc = self._get_gl_initial_acc( - account_ids, company_id, date_from, fy_start_date, base_domain, grouped_by - ) - domain = self._get_initial_balances_bs_ml_domain( - account_ids, company_id, date_from, base_domain, grouped_by, acc_prt=True - ) - data = self._prepare_gen_ld_data(gl_initial_acc, domain, grouped_by) - accounts_ids = list(data.keys()) - unaffected_id = unaffected_earnings_account - if unaffected_id: - if unaffected_id not in accounts_ids: - accounts_ids.append(unaffected_id) - data[unaffected_id] = self._initialize_data(foreign_currency) - data[unaffected_id]["id"] = unaffected_id - data[unaffected_id]["mame"] = "" - data[unaffected_id][grouped_by] = False - pl_initial_balance = self._get_pl_initial_balance( - account_ids, company_id, fy_start_date, foreign_currency, base_domain - ) - for key_bal in ["init_bal", "fin_bal"]: - fields_balance = ["credit", "debit", "balance"] - if foreign_currency: - fields_balance.append("bal_curr") - for field_name in fields_balance: - data[unaffected_id][key_bal][field_name] += pl_initial_balance[ - field_name - ] - return data - - @api.model - def _get_move_line_data(self, move_line): - move_type = move_line.get("move_type", "") - inscription = "" - account = self.env['account.account'].browse(move_line['account_id'][0]) - accounttype = account.account_type - if move_type == "entry": - if accounttype == "liability_payable": - inscription = "Платеж поставщику" - elif accounttype == "asset_receivable": - inscription = "Оплата покупателя" - # elif accounttype == "asset_current": - # inscription = "Оплата покупателя" - # else: - # inscription = "" - elif move_type == "out_invoice": - inscription = "Продажа товаров и услуг" - # elif move_type == "out_refund": - # inscription = "Сторно клиента " - elif move_type == "in_invoice": - inscription = "Покупка товаров и услуг " - # elif move_type == "in_refund": - # inscription = "Кредитное обязательство поставщика " - # elif move_type == "out_receipt": - # inscription = "Квитанция продаж" - # elif move_type == "in_receipt": - # inscription = "Квитанция покупки" - - transformed_move_name = f"{inscription} No. {move_line['move_name']}" - move_line_data = { - "id": move_line["id"], - "date": move_line["date"], - "entry": transformed_move_name, - # "entry": move_line["move_name"], - "entry_id": move_line["move_id"][0], - "journal_id": move_line["journal_id"][0], - "account_id": move_line["account_id"][0], - "partner_id": move_line["partner_id"][0] - if move_line["partner_id"] - else False, - "partner_name": move_line["partner_id"][1] - if move_line["partner_id"] - else "", - "ref": "" if not move_line["ref"] else move_line["ref"], - "name": "" if not move_line["name"] else move_line["name"], - "tax_ids": move_line["tax_ids"], - "tax_line_id": move_line["tax_line_id"], - "debit": move_line["debit"], - "credit": move_line["credit"], - "balance": move_line["balance"], - "bal_curr": move_line["amount_currency"], - "rec_id": move_line["full_reconcile_id"][0] - if move_line["full_reconcile_id"] - else False, - "rec_name": move_line["full_reconcile_id"][1] - if move_line["full_reconcile_id"] - else "", - "currency_id": move_line["currency_id"], - "analytic_distribution": move_line["analytic_distribution"] or {}, - } - if ( - move_line_data["ref"] == move_line_data["name"] - or move_line_data["ref"] == "" - ): - ref_label = move_line_data["name"] - elif move_line_data["name"] == "": - ref_label = move_line_data["ref"] - else: - ref_label = move_line_data["ref"] + str(" - ") + move_line_data["name"] - move_line_data.update({"ref_label": ref_label}) - return move_line_data - - @api.model - def _get_period_domain( - self, - account_ids, - partner_ids, - company_id, - only_posted_moves, - date_to, - date_from, - cost_center_ids, - ): - domain = [ - ("display_type", "not in", ["line_note", "line_section"]), - ("date", ">=", date_from), - ("date", "<=", date_to), - ] - if account_ids: - domain += [("account_id", "in", account_ids)] - if company_id: - domain += [("company_id", "=", company_id)] - if partner_ids: - domain += [("partner_id", "in", partner_ids)] - if only_posted_moves: - domain += [("move_id.state", "=", "posted")] - else: - domain += [("move_id.state", "in", ["posted", "draft"])] - - if cost_center_ids: - domain += [("analytic_account_ids", "in", cost_center_ids)] - return domain - - def _initialize_data(self, foreign_currency): - res = {} - for key_bal in ["init_bal", "fin_bal"]: - res[key_bal] = {} - for key_field in ["balance", "credit", "debit"]: - res[key_bal][key_field] = 0.0 - if foreign_currency: - res[key_bal]["bal_curr"] = 0.0 - return res - - def _get_reconciled_after_date_to_ids(self, full_reconcile_ids, date_to): - full_reconcile_ids = list(full_reconcile_ids) - domain = [ - ("max_date", ">", date_to), - ("full_reconcile_id", "in", full_reconcile_ids), - ] - fields = ["full_reconcile_id"] - reconciled_after_date_to = self.env["account.partial.reconcile"].search_read( - domain=domain, fields=fields - ) - rec_after_date_to_ids = list( - map(operator.itemgetter("full_reconcile_id"), reconciled_after_date_to) - ) - rec_after_date_to_ids = [i[0] for i in rec_after_date_to_ids] - return rec_after_date_to_ids - - def _prepare_ml_items(self, move_line, grouped_by): - res = [] - if grouped_by == "partners": - item_id = move_line["partner_id"][0] if move_line["partner_id"] else 0 - item_name = ( - move_line["partner_id"][1] - if move_line["partner_id"] - else _("Missing Partner") - ) - res.append({"id": item_id, "name": item_name}) - elif grouped_by == "taxes": - if move_line["tax_line_id"]: - item_id = move_line["tax_line_id"][0] - item_name = move_line["tax_line_id"][1] - res.append({"id": item_id, "name": item_name}) - elif move_line["tax_ids"]: - for tax_id in move_line["tax_ids"]: - tax_item = self.env["account.tax"].browse(tax_id) - res.append({"id": tax_item.id, "name": tax_item.name}) - else: - res.append({"id": 0, "name": "Missing Tax"}) - else: - res.append({"id": 0, "name": ""}) - return res - - def _get_period_ml_data( - self, - account_ids, - partner_ids, - company_id, - foreign_currency, - only_posted_moves, - date_from, - date_to, - gen_ld_data, - cost_center_ids, - extra_domain, - grouped_by, - ): - domain = self._get_period_domain( - account_ids, - partner_ids, - company_id, - only_posted_moves, - date_to, - date_from, - cost_center_ids, - ) - if extra_domain: - domain += extra_domain - ml_fields = self._get_ml_fields() - move_lines = self.env["account.move.line"].search_read( - domain=domain, fields=ml_fields, order="date,move_name" - ) - journal_ids = set() - full_reconcile_ids = set() - taxes_ids = set() - analytic_ids = set() - full_reconcile_data = {} - acc_prt_account_ids = self._get_acc_prt_accounts_ids(company_id, grouped_by) - for move_line in move_lines: - journal_ids.add(move_line["journal_id"][0]) - for tax_id in move_line["tax_ids"]: - taxes_ids.add(tax_id) - for analytic_account in move_line["analytic_distribution"] or {}: - analytic_ids.add(int(analytic_account)) - if move_line["full_reconcile_id"]: - rec_id = move_line["full_reconcile_id"][0] - if rec_id not in full_reconcile_ids: - full_reconcile_data.update( - { - rec_id: { - "id": rec_id, - "name": move_line["full_reconcile_id"][1], - } - } - ) - full_reconcile_ids.add(rec_id) - acc_id = move_line["account_id"][0] - ml_id = move_line["id"] - if acc_id not in gen_ld_data.keys(): - gen_ld_data[acc_id] = self._initialize_data(foreign_currency) - gen_ld_data[acc_id]["id"] = acc_id - gen_ld_data[acc_id]["mame"] = move_line["account_id"][1] - if grouped_by: - gen_ld_data[acc_id][grouped_by] = False - if acc_id in acc_prt_account_ids: - item_ids = self._prepare_ml_items(move_line, grouped_by) - for item in item_ids: - item_id = item["id"] - if item_id not in gen_ld_data[acc_id]: - if grouped_by: - gen_ld_data[acc_id][grouped_by] = True - gen_ld_data[acc_id][item_id] = self._initialize_data( - foreign_currency - ) - gen_ld_data[acc_id][item_id]["id"] = item_id - gen_ld_data[acc_id][item_id]["name"] = item["name"] - gen_ld_data[acc_id][item_id][ml_id] = self._get_move_line_data( - move_line - ) - gen_ld_data[acc_id][item_id]["fin_bal"]["credit"] += move_line[ - "credit" - ] - gen_ld_data[acc_id][item_id]["fin_bal"]["debit"] += move_line[ - "debit" - ] - gen_ld_data[acc_id][item_id]["fin_bal"]["balance"] += move_line[ - "balance" - ] - if foreign_currency: - gen_ld_data[acc_id][item_id]["fin_bal"][ - "bal_curr" - ] += move_line["amount_currency"] - else: - gen_ld_data[acc_id][ml_id] = self._get_move_line_data(move_line) - gen_ld_data[acc_id]["fin_bal"]["credit"] += move_line["credit"] - gen_ld_data[acc_id]["fin_bal"]["debit"] += move_line["debit"] - gen_ld_data[acc_id]["fin_bal"]["balance"] += move_line["balance"] - if foreign_currency: - gen_ld_data[acc_id]["fin_bal"]["bal_curr"] += move_line[ - "amount_currency" - ] - journals_data = self._get_journals_data(list(journal_ids)) - accounts_data = self._get_accounts_data(gen_ld_data.keys()) - taxes_data = self._get_taxes_data(list(taxes_ids)) - analytic_data = self._get_analytic_data(list(analytic_ids)) - rec_after_date_to_ids = self._get_reconciled_after_date_to_ids( - full_reconcile_data.keys(), date_to - ) - return ( - gen_ld_data, - accounts_data, - journals_data, - full_reconcile_data, - taxes_data, - analytic_data, - rec_after_date_to_ids, - ) - - @api.model - def _recalculate_cumul_balance( - self, move_lines, last_cumul_balance, rec_after_date_to_ids - ): - for move_line in move_lines: - move_line["balance"] += last_cumul_balance - last_cumul_balance = move_line["balance"] - if move_line["rec_id"] in rec_after_date_to_ids: - move_line["rec_name"] = "(" + _("future") + ") " + move_line["rec_name"] - return move_lines - - def _create_account(self, account, acc_id, gen_led_data, rec_after_date_to_ids): - move_lines = [] - for ml_id in gen_led_data[acc_id].keys(): - if not isinstance(ml_id, int): - account.update({ml_id: gen_led_data[acc_id][ml_id]}) - else: - move_lines += [gen_led_data[acc_id][ml_id]] - move_lines = sorted(move_lines, key=lambda k: (k["date"])) - move_lines = self._recalculate_cumul_balance( - move_lines, - gen_led_data[acc_id]["init_bal"]["balance"], - rec_after_date_to_ids, - ) - account.update({"move_lines": move_lines}) - return account - - def _create_account_not_show_item( - self, account, acc_id, gen_led_data, rec_after_date_to_ids, grouped_by - ): - move_lines = [] - for prt_id in gen_led_data[acc_id].keys(): - if not isinstance(prt_id, int): - account.update({prt_id: gen_led_data[acc_id][prt_id]}) - elif isinstance(gen_led_data[acc_id][prt_id], dict): - for ml_id in gen_led_data[acc_id][prt_id].keys(): - if isinstance(ml_id, int): - move_lines += [gen_led_data[acc_id][prt_id][ml_id]] - move_lines = sorted(move_lines, key=lambda k: (k["date"])) - move_lines = self._recalculate_cumul_balance( - move_lines, - gen_led_data[acc_id]["init_bal"]["balance"], - rec_after_date_to_ids, - ) - account.update({"move_lines": move_lines, grouped_by: False}) - return account - - def _get_list_grouped_item( - self, data, account, rec_after_date_to_ids, hide_account_at_0, rounding - ): - list_grouped = [] - for data_id in data.keys(): - group_item = {} - move_lines = [] - if not isinstance(data_id, int): - account.update({data_id: data[data_id]}) - else: - for ml_id in data[data_id].keys(): - if not isinstance(ml_id, int): - group_item.update({ml_id: data[data_id][ml_id]}) - else: - move_lines += [data[data_id][ml_id]] - move_lines = sorted(move_lines, key=lambda k: (k["date"])) - move_lines = self._recalculate_cumul_balance( - move_lines, - data[data_id]["init_bal"]["balance"], - rec_after_date_to_ids, - ) - group_item.update({"move_lines": move_lines}) - if ( - hide_account_at_0 - and float_is_zero( - data[data_id]["init_bal"]["balance"], - precision_rounding=rounding, - ) - and group_item["move_lines"] == [] - ): - continue - list_grouped += [group_item] - return account, list_grouped - - def _create_general_ledger( - self, - gen_led_data, - accounts_data, - grouped_by, - rec_after_date_to_ids, - hide_account_at_0, - ): - general_ledger = [] - rounding = self.env.company.currency_id.rounding - for acc_id in gen_led_data.keys(): - account = {} - account.update( - { - "code": accounts_data[acc_id]["code"], - "name": accounts_data[acc_id]["name"], - "type": "account", - "currency_id": accounts_data[acc_id]["currency_id"], - "centralized": accounts_data[acc_id]["centralized"], - "grouped_by": grouped_by, - } - ) - if grouped_by and not gen_led_data[acc_id][grouped_by]: - account = self._create_account( - account, acc_id, gen_led_data, rec_after_date_to_ids - ) - if ( - hide_account_at_0 - and float_is_zero( - gen_led_data[acc_id]["init_bal"]["balance"], - precision_rounding=rounding, - ) - and account["move_lines"] == [] - ): - continue - else: - if grouped_by: - account, list_grouped = self._get_list_grouped_item( - gen_led_data[acc_id], - account, - rec_after_date_to_ids, - hide_account_at_0, - rounding, - ) - account.update({"list_grouped": list_grouped}) - if ( - hide_account_at_0 - and float_is_zero( - gen_led_data[acc_id]["init_bal"]["balance"], - precision_rounding=rounding, - ) - and account["list_grouped"] == [] - ): - continue - else: - account = self._create_account_not_show_item( - account, acc_id, gen_led_data, rec_after_date_to_ids, grouped_by - ) - if ( - hide_account_at_0 - and float_is_zero( - gen_led_data[acc_id]["init_bal"]["balance"], - precision_rounding=rounding, - ) - and account["move_lines"] == [] - ): - continue - general_ledger += [account] - return general_ledger - - @api.model - def _calculate_centralization(self, centralized_ml, move_line, date_to): - jnl_id = move_line["journal_id"] - month = move_line["date"].month - if jnl_id not in centralized_ml.keys(): - centralized_ml[jnl_id] = {} - if month not in centralized_ml[jnl_id].keys(): - centralized_ml[jnl_id][month] = {} - last_day_month = calendar.monthrange(move_line["date"].year, month) - date = datetime.date(move_line["date"].year, month, last_day_month[1]) - if date > date_to: - date = date_to - centralized_ml[jnl_id][month].update( - { - "journal_id": jnl_id, - "ref_label": "Centralized entries", - "date": date, - "debit": 0.0, - "credit": 0.0, - "balance": 0.0, - "bal_curr": 0.0, - "partner_id": False, - "rec_id": 0, - "entry_id": False, - "tax_ids": [], - "tax_line_id": False, - "full_reconcile_id": False, - "id": False, - "currency_id": False, - "analytic_distribution": {}, - } - ) - centralized_ml[jnl_id][month]["debit"] += move_line["debit"] - centralized_ml[jnl_id][month]["credit"] += move_line["credit"] - centralized_ml[jnl_id][month]["balance"] += ( - move_line["debit"] - move_line["credit"] - ) - centralized_ml[jnl_id][month]["bal_curr"] += move_line["bal_curr"] - return centralized_ml - - @api.model - def _get_centralized_ml(self, account, date_to, grouped_by): - centralized_ml = {} - if isinstance(date_to, str): - date_to = datetime.datetime.strptime(date_to, "%Y-%m-%d").date() - if grouped_by and account[grouped_by]: - for item in account["list_grouped"]: - for move_line in item["move_lines"]: - centralized_ml = self._calculate_centralization( - centralized_ml, - move_line, - date_to, - ) - else: - for move_line in account["move_lines"]: - centralized_ml = self._calculate_centralization( - centralized_ml, - move_line, - date_to, - ) - list_centralized_ml = [] - for jnl_id in centralized_ml.keys(): - list_centralized_ml += list(centralized_ml[jnl_id].values()) - return list_centralized_ml - - def _get_report_values(self, docids, data): - wizard_id = data["wizard_id"] - company = self.env["res.company"].browse(data["company_id"]) - company_id = data["company_id"] - date_to = data["date_to"] - date_from = data["date_from"] - partner_ids = data["partner_ids"] - account_ids = data["account_ids"] - cost_center_ids = data["cost_center_ids"] - grouped_by = data["grouped_by"] - hide_account_at_0 = data["hide_account_at_0"] - foreign_currency = data["foreign_currency"] - only_posted_moves = data["only_posted_moves"] - unaffected_earnings_account = data["unaffected_earnings_account"] - fy_start_date = data["fy_start_date"] - extra_domain = data["domain"] - gen_ld_data = self._get_initial_balance_data( - account_ids, - partner_ids, - company_id, - date_from, - foreign_currency, - only_posted_moves, - unaffected_earnings_account, - fy_start_date, - cost_center_ids, - extra_domain, - grouped_by, - ) - centralize = data["centralize"] - ( - gen_ld_data, - accounts_data, - journals_data, - full_reconcile_data, - taxes_data, - analytic_data, - rec_after_date_to_ids, - ) = self._get_period_ml_data( - account_ids, - partner_ids, - company_id, - foreign_currency, - only_posted_moves, - date_from, - date_to, - gen_ld_data, - cost_center_ids, - extra_domain, - grouped_by, - ) - general_ledger = self._create_general_ledger( - gen_ld_data, - accounts_data, - grouped_by, - rec_after_date_to_ids, - hide_account_at_0, - ) - if centralize: - for account in general_ledger: - if account["centralized"]: - centralized_ml = self._get_centralized_ml( - account, date_to, grouped_by - ) - account["move_lines"] = centralized_ml - account["move_lines"] = self._recalculate_cumul_balance( - account["move_lines"], - gen_ld_data[account["id"]]["init_bal"]["balance"], - rec_after_date_to_ids, - ) - if grouped_by and account[grouped_by]: - account[grouped_by] = False - del account["list_grouped"] - general_ledger = sorted(general_ledger, key=lambda k: k["code"]) - if not general_ledger: - raise UserError(f'Проводок для формирования акта по введенным условиям не найдено.') - return { - "doc_ids": [wizard_id], - "doc_model": "general.ledger.act_revise.wizard", - "docs": self.env["general.ledger.act_revise.wizard"].browse(wizard_id), - "foreign_currency": data["foreign_currency"], - "company_name": company.display_name, - "company_currency": company.currency_id, - "currency_name": company.currency_id.name, - "date_from": data["date_from"], - "date_to": data["date_to"], - "only_posted_moves": data["only_posted_moves"], - "hide_account_at_0": data["hide_account_at_0"], - "show_cost_center": data["show_cost_center"], - "general_ledger": general_ledger, - "accounts_data": accounts_data, - "journals_data": journals_data, - "full_reconcile_data": full_reconcile_data, - "taxes_data": taxes_data, - "centralize": centralize, - "analytic_data": analytic_data, - "filter_partner_ids": True if partner_ids else False, - "currency_model": self.env["res.currency"], - } - - def _get_ml_fields(self): - return self.COMMON_ML_FIELDS + [ - "analytic_distribution", - "full_reconcile_id", - "tax_line_id", - "currency_id", - "credit", - "debit", - "amount_currency", - "balance", - "tax_ids", - "move_name", - ] diff --git a/act_revise/report/general_ledger.xml b/act_revise/report/general_ledger.xml deleted file mode 100644 index f6f565f..0000000 --- a/act_revise/report/general_ledger.xml +++ /dev/null @@ -1,286 +0,0 @@ - - - - - - - - - - - - - - - - - Акт сверки - general.ledger.act_revise.wizard - qweb-pdf - act_revise.general_ledger - act_revise.general_ledger - 'Акт сверки - %s' % (object.get_report_filename() or '') - - - - - Account financial report qweb paperformat - - custom - 297 - 210 - Landscape - 12 - 8 - 5 - 5 - - 10 - 110 - - - - - \ No newline at end of file diff --git a/act_revise/report/layouts.xml b/act_revise/report/layouts.xml deleted file mode 100644 index 3ea8b44..0000000 --- a/act_revise/report/layouts.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - diff --git a/act_revise/security/ir.model.access.csv b/act_revise/security/ir.model.access.csv deleted file mode 100644 index 96c0232..0000000 --- a/act_revise/security/ir.model.access.csv +++ /dev/null @@ -1,2 +0,0 @@ -id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_general_ledger_act_revise_wizard,general.ledger.act_revise.wizard,model_general_ledger_act_revise_wizard,base.group_user,1,1,1,1 diff --git a/act_revise/views/account_account_views.xml b/act_revise/views/account_account_views.xml deleted file mode 100644 index 38dce94..0000000 --- a/act_revise/views/account_account_views.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - account.account.form.inherit - - account.account - form - - - - - - - diff --git a/act_revise/views/portal_templates.xml b/act_revise/views/portal_templates.xml deleted file mode 100644 index b7a1ff2..0000000 --- a/act_revise/views/portal_templates.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - diff --git a/act_revise/views/report_general_ledger.xml b/act_revise/views/report_general_ledger.xml deleted file mode 100644 index cade50a..0000000 --- a/act_revise/views/report_general_ledger.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - diff --git a/act_revise/wizard/__init__.py b/act_revise/wizard/__init__.py deleted file mode 100644 index c0d813c..0000000 --- a/act_revise/wizard/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from . import abstract_wizard -from . import general_ledger_wizard diff --git a/act_revise/wizard/abstract_wizard.py b/act_revise/wizard/abstract_wizard.py deleted file mode 100644 index 216bae7..0000000 --- a/act_revise/wizard/abstract_wizard.py +++ /dev/null @@ -1,38 +0,0 @@ -from odoo import models, fields - - -class AbstractWizard(models.AbstractModel): - _name = "act_revise.abstract_wizard" - _description = "Abstract Wizard" - - def _get_partner_ids_domain(self): - return [ - "&", - "|", - ("company_id", "=", self.company_id.id), - ("company_id", "=", False), - "|", - ("parent_id", "=", False), - ("is_company", "=", True), - ] - - def _default_partners(self): - context = self.env.context - if context.get("active_ids") and context.get("active_model") == "res.partner": - partners = self.env["res.partner"].browse(context["active_ids"]) - corp_partners = partners.filtered("parent_id") - partners -= corp_partners - partners |= corp_partners.mapped("commercial_partner_id") - return partners.ids - - company_id = fields.Many2one( - comodel_name="res.company", - default=lambda self: self.env.company.id, - required=False, - string="Компания", - ) - - def button_export_pdf(self): - self.ensure_one() - report_type = "qweb-pdf" - return self._export(report_type) \ No newline at end of file diff --git a/act_revise/wizard/general_ledger_wizard.py b/act_revise/wizard/general_ledger_wizard.py deleted file mode 100644 index 569a53f..0000000 --- a/act_revise/wizard/general_ledger_wizard.py +++ /dev/null @@ -1,898 +0,0 @@ -import logging -import time -from ast import literal_eval -from odoo import _, api, fields, models -from odoo.tools import date_utils,pycompat -from pytils import dt,numeral -from datetime import datetime, date -import re -import urllib -from odoo.exceptions import UserError - -class GeneralLedgerReportWizard(models.TransientModel): - """General ledger report wizard.""" - - _name = "general.ledger.act_revise.wizard" - _description = "General Ledger Report Wizard" - _inherit = "act_revise.abstract_wizard" - - # date_range_id = fields.Many2one(comodel_name="date.range", string="Date range") - date_from = fields.Date(string="Начало даты", required=True, default=lambda self: self._init_date_from()) - date_to = fields.Date(string="Конец даты", required=True, default=fields.Date.context_today) - fy_start_date = fields.Date(compute="_compute_fy_start_date") - target_move = fields.Selection( - [("posted", "Все проведенные проводки"), ("all", "Все проводки")], - string="Цель операции", - required=True, - default="posted", - ) - account_ids = fields.Many2many( - comodel_name="account.account", string=_("Filter accounts") - ) - centralize = fields.Boolean(string=_("Activate centralization"), default=True) - hide_account_at_0 = fields.Boolean( - string=_("Hide account ending balance at 0"), - help=_("Use this filter to hide an account or a partner " - "with an ending balance at 0. " - "If partners are filtered, " - "debits and credits totals will not match the trial balance."), - ) - receivable_accounts_only = fields.Boolean() - payable_accounts_only = fields.Boolean() - partner_ids = fields.Many2many( - comodel_name="res.partner", - string=_("Filter partners"), - default=lambda self: self._default_partners(), - ) - account_journal_ids = fields.Many2many( - comodel_name="account.journal", string=_("Filter journals") - ) - cost_center_ids = fields.Many2many( - comodel_name="account.analytic.account", string=_("Filter cost centers") - ) - - not_only_one_unaffected_earnings_account = fields.Boolean(readonly=True) - foreign_currency = fields.Boolean( - string=_("Show foreign currency"), - help=_("Display foreign currency for move lines, unless " - "account currency is not setup through chart of accounts " - "will display initial and final balance in that currency."), - default=lambda self: self._default_foreign_currency(), - ) - account_code_from = fields.Many2one( - comodel_name="account.account", - help="Starting account in a range", - ) - account_code_to = fields.Many2one( - comodel_name="account.account", - help="Ending account in a range", - ) - grouped_by = fields.Selection( - selection=[("", "None"), ("partners", "Partners"), ("taxes", "Taxes")], - default="partners", - ) - show_cost_center = fields.Boolean( - string="Show Analytic Account", - default=True, - ) - domain = fields.Char( - string="Journal Items Domain", - default=[], - help="This domain will be used to select specific domain for Journal " "Items", - ) - - # def _print_report(self, report_type): - # self.ensure_one() - # data = self._prepare_report_general_ledger() - # report = self.env["ir.actions.report"].search( - # [("report_name", "=", "act_revise.general_ledger"), ("report_type", "=", report_type)], limit=1, ) - # if self.partner_ids[0].parent_id: - # partner = int(self.partner_ids[0].parent_id.id) - # else: - # partner = int(self.partner_ids[0].id) - # return { - # 'type': 'ir.actions.act_url', - # 'url': '/my/act_revise_contact/%s?date_to=%s&date_from=%s&target_move=%s&company=%s&partner=%s' % ( - # urllib.parse.quote(self.get_report_filename()), self.date_to, self.date_from, self.target_move, - # self.company_id.id, partner), - # 'target': 'new', - # } - - def _get_account_move_lines_domain(self): - domain = literal_eval(self.domain) if self.domain else [] - return domain - - @api.onchange("account_code_from", "account_code_to") - def on_change_account_range(self): - if ( - self.account_code_from - and self.account_code_from.code.isdigit() - and self.account_code_to - and self.account_code_to.code.isdigit() - ): - start_range = self.account_code_from.code - end_range = self.account_code_to.code - self.account_ids = self.env["account.account"].search( - [("code", ">=", start_range), ("code", "<=", end_range)] - ) - if self.company_id: - self.account_ids = self.account_ids.filtered( - lambda a: a.company_id == self.company_id - ) - - def _init_date_from(self): - """set start date to begin of current year if fiscal year running""" - today = fields.Date.context_today(self) - company = self.company_id or self.env.company - last_fsc_month = company.fiscalyear_last_month - last_fsc_day = company.fiscalyear_last_day - - if ( - today.month < int(last_fsc_month) - or today.month == int(last_fsc_month) - and today.day <= last_fsc_day - ): - return time.strftime("%Y-01-01") - else: - return False - - def _default_foreign_currency(self): - return self.env.user.has_group("base.group_multi_currency") - - @api.depends("date_from") - def _compute_fy_start_date(self): - for wiz in self: - if wiz.date_from: - date_from, date_to = date_utils.get_fiscal_year( - wiz.date_from, - day=self.company_id.fiscalyear_last_day, - month=int(self.company_id.fiscalyear_last_month), - ) - wiz.fy_start_date = date_from - else: - wiz.fy_start_date = False - - @api.onchange("company_id") - def onchange_company_id(self): - """Handle company change.""" - count = self.env["account.account"].search_count( - [ - ("account_type", "=", "equity_unaffected"), - ("company_id", "=", self.company_id.id), - ] - ) - self.not_only_one_unaffected_earnings_account = count != 1 - # if ( - # self.company_id - # and self.date_range_id.company_id - # and self.date_range_id.company_id != self.company_id - # ): - # self.date_range_id = False - if self.company_id and self.account_journal_ids: - self.account_journal_ids = self.account_journal_ids.filtered( - lambda p: p.company_id == self.company_id or not p.company_id - ) - if self.company_id and self.partner_ids: - self.partner_ids = self.partner_ids.filtered( - lambda p: p.company_id == self.company_id or not p.company_id - ) - if self.company_id and self.account_ids: - if self.receivable_accounts_only or self.payable_accounts_only: - self.onchange_type_accounts_only() - else: - self.account_ids = self.account_ids.filtered( - lambda a: a.company_id == self.company_id - ) - if self.company_id and self.cost_center_ids: - self.cost_center_ids = self.cost_center_ids.filtered( - lambda c: c.company_id == self.company_id - ) - res = { - "domain": { - "account_ids": [], - "partner_ids": [], - "account_journal_ids": [], - "cost_center_ids": [], - # "date_range_id": [], - } - } - if not self.company_id: - return res - else: - res["domain"]["account_ids"] += [("company_id", "=", self.company_id.id)] - res["domain"]["account_journal_ids"] += [ - ("company_id", "=", self.company_id.id) - ] - res["domain"]["partner_ids"] += self._get_partner_ids_domain() - res["domain"]["cost_center_ids"] += [ - ("company_id", "=", self.company_id.id) - ] - # res["domain"]["date_range_id"] += [ - # "|", - # ("company_id", "=", self.company_id.id), - # ("company_id", "=", False), - # ] - return res - - # @api.onchange("date_range_id") - # def onchange_date_range_id(self): - # """Handle date range change.""" - # if self.date_range_id: - # self.date_from = self.date_range_id.date_start - # self.date_to = self.date_range_id.date_end - - # @api.constrains("company_id", "date_range_id") - # def _check_company_id_date_range_id(self): - # for rec in self.sudo(): - # if ( - # rec.company_id - # and rec.date_range_id.company_id - # and rec.company_id != rec.date_range_id.company_id - # ): - # raise ValidationError( - # _( - # "The Company in the General Ledger Report Wizard and in " - # "Date Range must be the same." - # ) - # ) - - @api.onchange("receivable_accounts_only", "payable_accounts_only") - def onchange_type_accounts_only(self): - """Handle receivable/payable accounts only change.""" - if self.receivable_accounts_only or self.payable_accounts_only: - domain = [("company_id", "=", self.company_id.id)] - if self.receivable_accounts_only and self.payable_accounts_only: - domain += [ - ("account_type", "in", ("asset_receivable", "liability_payable")) - ] - elif self.receivable_accounts_only: - domain += [("account_type", "=", "asset_receivable")] - elif self.payable_accounts_only: - domain += [("account_type", "=", "liability_payable")] - self.account_ids = self.env["account.account"].search(domain) - else: - self.account_ids = None - - @api.onchange("partner_ids") - def onchange_partner_ids(self): - """Handle partners change.""" - if self.partner_ids: - self.receivable_accounts_only = self.payable_accounts_only = True - else: - self.receivable_accounts_only = self.payable_accounts_only = False - - @api.depends("company_id") - def _compute_unaffected_earnings_account(self): - for record in self: - record.unaffected_earnings_account = self.env["account.account"].search( - [ - ("account_type", "=", "equity_unaffected"), - ("company_id", "=", record.company_id.id), - ] - ) - - unaffected_earnings_account = fields.Many2one( - comodel_name="account.account", - compute="_compute_unaffected_earnings_account", - store=True, - ) - - # def _print_report(self, report_type): - # self.ensure_one() - # data = self._prepare_report_general_ledger() - # report_name = "act_revise.general_ledger" - # return ( - # self.env["ir.actions.report"] - # .search( - # [("report_name", "=", report_name), ("report_type", "=", report_type)], - # limit=1, - # ) - # .report_action(self, data=data) - # ) - def _print_report(self, report_type): - self.ensure_one() - data = self._prepare_report_general_ledger() - report = self.env["ir.actions.report"].search( - [("report_name", "=", "act_revise.general_ledger"), ("report_type", "=", report_type)], limit=1, ) - - if self.partner_ids[0].parent_id: - partner = int(self.partner_ids[0].parent_id.id) - else: - partner = int(self.partner_ids[0].id) - account_data = self.env['account.move.line'].sudo().search([ - ('partner_id', '=', partner), - ('account_id.account_type', 'in', ('liability_payable', 'asset_receivable')), - ('account_id.non_trade', '=', False), - ('date', '<=', self.date_to), - ('date', '>=', self.date_from) - ]) - logging.warning(f'account_data {account_data}') - if self.target_move == 'posted' and not account_data.filtered(lambda p: p.parent_state == 'posted') or not account_data: - raise UserError(f'Проводок для формирования акта по введенным условиям не найдено.') - return { - 'type': 'ir.actions.act_url', - 'url': '/my/act_revise_contact/%s?date_to=%s&date_from=%s&target_move=%s&company=%s&partner=%s' % ( - urllib.parse.quote(self.get_report_filename()), self.date_to, self.date_from, self.target_move, - self.company_id.id, partner), - 'target': 'new', - } - - def _prepare_report_general_ledger(self): - self.ensure_one() - return { - "wizard_id": self.id, - "date_from": self.date_from, - "date_to": self.date_to, - "only_posted_moves": self.target_move == "posted", - "hide_account_at_0": self.hide_account_at_0, - "foreign_currency": self.foreign_currency, - "company_id": self.company_id.id, - "account_ids": self.account_ids.ids, - "partner_ids": self.partner_ids.ids, - "grouped_by": self.grouped_by, - "cost_center_ids": self.cost_center_ids.ids, - "show_cost_center": self.show_cost_center, - "journal_ids": self.account_journal_ids.ids, - "centralize": self.centralize, - "fy_start_date": self.fy_start_date, - "unaffected_earnings_account": self.unaffected_earnings_account.id, - "account_financial_report_lang": self.env.lang, - "domain": self._get_account_move_lines_domain(), - } - - def _export(self, report_type): - """Default export is PDF.""" - return self._print_report(report_type) - - def _get_atr_from_dict(self, obj_id, data, key): - try: - return data[obj_id][key] - except KeyError: - return data[str(obj_id)][key] - - def numer(self, name): - if name: - numeration = re.findall('\d+$', name) - if numeration: return numeration[0] - return name - - def get_data_format(self, date): - if date and date != 'False': - return dt.ru_strftime(u'%d.%m.%Y г.', date=datetime.strptime(str(date), "%Y-%m-%d"), inflected=True) - return '' - - def initials(self, fio): - if fio: - return (fio.split()[0] + ' ' + ''.join([fio[0:1] + '.' for fio in fio.split()[1:]])).strip() - return '' - - def rubles(self, sum): - "Transform sum number in rubles to text" - text_rubles = numeral.rubles(int(sum)) - copeck = round((sum - int(sum)) * 100) - text_copeck = numeral.choose_plural(int(copeck), (u"копейка", u"копейки", u"копеек")) - return ("%s %02d %s") % (text_rubles, copeck, text_copeck) - - def img(self, img, type='png', width=0, height=0): - if width: - width = "width='%spx'" % (width) - else: - width = " " - if height: - height = "height='%spx'" % (height) - else: - height = " " - toreturn = "" % ( - width, - height, - type, - str(pycompat.to_text(img))) - return toreturn - - def get_contract(self): - partner = int(self.partner_ids[0].id) - contract = self.env['partner.contract.customer'].search( - [('partner_id', '=', partner), ('state', '=', 'signed')], limit=1) - if contract: - return contract - - def get_function_partner(self, partner): - director = self.env['res.partner'].search([('parent_id', '=', partner), ('type', '=', 'director')], limit=1) - if director: - if director.function: - return director.function or 'отсутствует' - - def get_name_partner(self, partner): - director = self.env['res.partner'].search([('parent_id', '=', partner), ('type', '=', 'director')], limit=1) - if director: - return director.name or 'отсутствует' - - def get_report_filename(self): - today = date.today() - d1 = today.strftime("%d-%m-%Y") - if self.partner_ids[0].parent_id: - p = ''.join(self.partner_ids[0].parent_id.name) - else: - p = ''.join(self.partner_ids[0].name) - # return 'Акт Сверки '+ d1 + ' ' + self.company_id.name+'_'+p - return str(self.company_id.id) + ' - ' + ' ' + d1 - - def sorted_lines(self, list): - list = sorted(list, key=lambda k: k.get('date'), reverse=False) - return list - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -# import time -# from ast import literal_eval -# from odoo import _, api, fields, models -# from odoo.tools import date_utils,pycompat -# from pytils import dt,numeral -# from datetime import datetime, date -# import re -# import urllib -# -# class GeneralLedgerReportWizard(models.TransientModel): -# """General ledger report wizard.""" -# -# _name = "general.ledger.act_revise.wizard" -# _description = "General Ledger Report Wizard" -# _inherit = "act_revise.abstract_wizard" -# -# # date_range_id = fields.Many2one(comodel_name="date.range", string="Date range") -# date_from = fields.Date(string="Начало даты", required=True, default=lambda self: self._init_date_from()) -# date_to = fields.Date(string="Конец даты", required=True, default=fields.Date.context_today) -# fy_start_date = fields.Date(compute="_compute_fy_start_date") -# target_move = fields.Selection( -# [("posted", "Р’СЃРµ проведенные РїСЂРѕРІРѕРґРєРё"), ("all", "Р’СЃРµ РїСЂРѕРІРѕРґРєРё")], -# string="Цель операции", -# required=True, -# default="posted", -# ) -# account_ids = fields.Many2many( -# comodel_name="account.account", string=_("Filter accounts") -# ) -# centralize = fields.Boolean(string=_("Activate centralization"), default=True) -# hide_account_at_0 = fields.Boolean( -# string=_("Hide account ending balance at 0"), -# help=_("Use this filter to hide an account or a partner " -# "with an ending balance at 0. " -# "If partners are filtered, " -# "debits and credits totals will not match the trial balance."), -# ) -# receivable_accounts_only = fields.Boolean() -# payable_accounts_only = fields.Boolean() -# partner_ids = fields.Many2many( -# comodel_name="res.partner", -# string=_("Filter partners"), -# default=lambda self: self._default_partners(), -# ) -# account_journal_ids = fields.Many2many( -# comodel_name="account.journal", string=_("Filter journals") -# ) -# cost_center_ids = fields.Many2many( -# comodel_name="account.analytic.account", string=_("Filter cost centers") -# ) -# -# not_only_one_unaffected_earnings_account = fields.Boolean(readonly=True) -# foreign_currency = fields.Boolean( -# string=_("Show foreign currency"), -# help=_("Display foreign currency for move lines, unless " -# "account currency is not setup through chart of accounts " -# "will display initial and final balance in that currency."), -# default=lambda self: self._default_foreign_currency(), -# ) -# account_code_from = fields.Many2one( -# comodel_name="account.account", -# help="Starting account in a range", -# ) -# account_code_to = fields.Many2one( -# comodel_name="account.account", -# help="Ending account in a range", -# ) -# grouped_by = fields.Selection( -# selection=[("", "None"), ("partners", "Partners"), ("taxes", "Taxes")], -# default="partners", -# ) -# show_cost_center = fields.Boolean( -# string="Show Analytic Account", -# default=True, -# ) -# domain = fields.Char( -# string="Journal Items Domain", -# default=[], -# help="This domain will be used to select specific domain for Journal " "Items", -# ) -# -# # def _print_report(self, report_type): -# # self.ensure_one() -# # data = self._prepare_report_general_ledger() -# # report = self.env["ir.actions.report"].search( -# # [("report_name", "=", "act_revise.general_ledger"), ("report_type", "=", report_type)], limit=1, ) -# # if self.partner_ids[0].parent_id: -# # partner = int(self.partner_ids[0].parent_id.id) -# # else: -# # partner = int(self.partner_ids[0].id) -# # return { -# # 'type': 'ir.actions.act_url', -# # 'url': '/my/act_revise_contact/%s?date_to=%s&date_from=%s&target_move=%s&company=%s&partner=%s' % ( -# # urllib.parse.quote(self.get_report_filename()), self.date_to, self.date_from, self.target_move, -# # self.company_id.id, partner), -# # 'target': 'new', -# # } -# -# def _get_account_move_lines_domain(self): -# domain = literal_eval(self.domain) if self.domain else [] -# return domain -# -# @api.onchange("account_code_from", "account_code_to") -# def on_change_account_range(self): -# if ( -# self.account_code_from -# and self.account_code_from.code.isdigit() -# and self.account_code_to -# and self.account_code_to.code.isdigit() -# ): -# start_range = self.account_code_from.code -# end_range = self.account_code_to.code -# self.account_ids = self.env["account.account"].search( -# [("code", ">=", start_range), ("code", "<=", end_range)] -# ) -# if self.company_id: -# self.account_ids = self.account_ids.filtered( -# lambda a: a.company_id == self.company_id -# ) -# -# def _init_date_from(self): -# """set start date to begin of current year if fiscal year running""" -# today = fields.Date.context_today(self) -# company = self.company_id or self.env.company -# last_fsc_month = company.fiscalyear_last_month -# last_fsc_day = company.fiscalyear_last_day -# -# if ( -# today.month < int(last_fsc_month) -# or today.month == int(last_fsc_month) -# and today.day <= last_fsc_day -# ): -# return time.strftime("%Y-01-01") -# else: -# return False -# -# def _default_foreign_currency(self): -# return self.env.user.has_group("base.group_multi_currency") -# -# @api.depends("date_from") -# def _compute_fy_start_date(self): -# for wiz in self: -# if wiz.date_from: -# date_from, date_to = date_utils.get_fiscal_year( -# wiz.date_from, -# day=self.company_id.fiscalyear_last_day, -# month=int(self.company_id.fiscalyear_last_month), -# ) -# wiz.fy_start_date = date_from -# else: -# wiz.fy_start_date = False -# -# @api.onchange("company_id") -# def onchange_company_id(self): -# """Handle company change.""" -# count = self.env["account.account"].search_count( -# [ -# ("account_type", "=", "equity_unaffected"), -# ("company_id", "=", self.company_id.id), -# ] -# ) -# self.not_only_one_unaffected_earnings_account = count != 1 -# # if ( -# # self.company_id -# # and self.date_range_id.company_id -# # and self.date_range_id.company_id != self.company_id -# # ): -# # self.date_range_id = False -# if self.company_id and self.account_journal_ids: -# self.account_journal_ids = self.account_journal_ids.filtered( -# lambda p: p.company_id == self.company_id or not p.company_id -# ) -# if self.company_id and self.partner_ids: -# self.partner_ids = self.partner_ids.filtered( -# lambda p: p.company_id == self.company_id or not p.company_id -# ) -# if self.company_id and self.account_ids: -# if self.receivable_accounts_only or self.payable_accounts_only: -# self.onchange_type_accounts_only() -# else: -# self.account_ids = self.account_ids.filtered( -# lambda a: a.company_id == self.company_id -# ) -# if self.company_id and self.cost_center_ids: -# self.cost_center_ids = self.cost_center_ids.filtered( -# lambda c: c.company_id == self.company_id -# ) -# res = { -# "domain": { -# "account_ids": [], -# "partner_ids": [], -# "account_journal_ids": [], -# "cost_center_ids": [], -# # "date_range_id": [], -# } -# } -# if not self.company_id: -# return res -# else: -# res["domain"]["account_ids"] += [("company_id", "=", self.company_id.id)] -# res["domain"]["account_journal_ids"] += [ -# ("company_id", "=", self.company_id.id) -# ] -# res["domain"]["partner_ids"] += self._get_partner_ids_domain() -# res["domain"]["cost_center_ids"] += [ -# ("company_id", "=", self.company_id.id) -# ] -# # res["domain"]["date_range_id"] += [ -# # "|", -# # ("company_id", "=", self.company_id.id), -# # ("company_id", "=", False), -# # ] -# return res -# -# # @api.onchange("date_range_id") -# # def onchange_date_range_id(self): -# # """Handle date range change.""" -# # if self.date_range_id: -# # self.date_from = self.date_range_id.date_start -# # self.date_to = self.date_range_id.date_end -# -# # @api.constrains("company_id", "date_range_id") -# # def _check_company_id_date_range_id(self): -# # for rec in self.sudo(): -# # if ( -# # rec.company_id -# # and rec.date_range_id.company_id -# # and rec.company_id != rec.date_range_id.company_id -# # ): -# # raise ValidationError( -# # _( -# # "The Company in the General Ledger Report Wizard and in " -# # "Date Range must be the same." -# # ) -# # ) -# -# @api.onchange("receivable_accounts_only", "payable_accounts_only") -# def onchange_type_accounts_only(self): -# """Handle receivable/payable accounts only change.""" -# if self.receivable_accounts_only or self.payable_accounts_only: -# domain = [("company_id", "=", self.company_id.id)] -# if self.receivable_accounts_only and self.payable_accounts_only: -# domain += [ -# ("account_type", "in", ("asset_receivable", "liability_payable")) -# ] -# elif self.receivable_accounts_only: -# domain += [("account_type", "=", "asset_receivable")] -# elif self.payable_accounts_only: -# domain += [("account_type", "=", "liability_payable")] -# self.account_ids = self.env["account.account"].search(domain) -# else: -# self.account_ids = None -# -# @api.onchange("partner_ids") -# def onchange_partner_ids(self): -# """Handle partners change.""" -# if self.partner_ids: -# self.receivable_accounts_only = self.payable_accounts_only = True -# else: -# self.receivable_accounts_only = self.payable_accounts_only = False -# -# @api.depends("company_id") -# def _compute_unaffected_earnings_account(self): -# for record in self: -# record.unaffected_earnings_account = self.env["account.account"].search( -# [ -# ("account_type", "=", "equity_unaffected"), -# ("company_id", "=", record.company_id.id), -# ] -# ) -# -# unaffected_earnings_account = fields.Many2one( -# comodel_name="account.account", -# compute="_compute_unaffected_earnings_account", -# store=True, -# ) -# -# # def _print_report(self, report_type): -# # self.ensure_one() -# # data = self._prepare_report_general_ledger() -# # report_name = "act_revise.general_ledger" -# # return ( -# # self.env["ir.actions.report"] -# # .search( -# # [("report_name", "=", report_name), ("report_type", "=", report_type)], -# # limit=1, -# # ) -# # .report_action(self, data=data) -# # ) -# def _print_report(self, report_type): -# self.ensure_one() -# data = self._prepare_report_general_ledger() -# report = self.env["ir.actions.report"].search( -# [("report_name", "=", "act_revise.general_ledger"), ("report_type", "=", report_type)], limit=1, ) -# # report.report_name='Test' -# # report.headers.add('Content-Disposition', 'attachment; filename="Test.pdf";') -# # pdf, _ = request.env.ref('act_revise.action_print_report_general_ledger_qweb').sudo().render_qweb_pdf(self,data=data) -# # pdfhttpheaders = [('Content-Type', 'application/pdf'), ('Content-Length', len(pdf)),('Content-Disposition', 'attachment; filename="%s";' % report_name),] -# # return request.make_response(pdf, headers=pdfhttpheaders) -# # return ( -# # self.env["ir.actions.report"] -# # .search( -# # [("report_name", "=", "act_revise.general_ledger"), ("report_type", "=", report_type)], -# # limit=1, -# # ) -# # report.report_action(self, data=data) -# # ) -# # name='Test' -# if self.partner_ids[0].parent_id: -# partner = int(self.partner_ids[0].parent_id.id) -# else: -# partner = int(self.partner_ids[0].id) -# account_data = self.env['account.move.line'].sudo().search([ -# ('partner_id', '=', partner.id), -# ('account_id.account_type', 'in', ('liability_payable', 'asset_receivable')), -# ('account_id.non_trade', '=', False), -# ('date', '<=', self.date_to), -# ('date', '>=', self.date_from) -# ]) -# if not account_data: -# raise UserError(f'Проводок для формирования акта по введенным условиям не найдено.') -# return { -# 'type': 'ir.actions.act_url', -# 'url': '/my/act_revise_contact/%s?date_to=%s&date_from=%s&target_move=%s&company=%s&partner=%s' % ( -# urllib.parse.quote(self.get_report_filename()), self.date_to, self.date_from, self.target_move, -# self.company_id.id, partner), -# 'target': 'new', -# } -# -# def _prepare_report_general_ledger(self): -# self.ensure_one() -# return { -# "wizard_id": self.id, -# "date_from": self.date_from, -# "date_to": self.date_to, -# "only_posted_moves": self.target_move == "posted", -# "hide_account_at_0": self.hide_account_at_0, -# "foreign_currency": self.foreign_currency, -# "company_id": self.company_id.id, -# "account_ids": self.account_ids.ids, -# "partner_ids": self.partner_ids.ids, -# "grouped_by": self.grouped_by, -# "cost_center_ids": self.cost_center_ids.ids, -# "show_cost_center": self.show_cost_center, -# "journal_ids": self.account_journal_ids.ids, -# "centralize": self.centralize, -# "fy_start_date": self.fy_start_date, -# "unaffected_earnings_account": self.unaffected_earnings_account.id, -# "account_financial_report_lang": self.env.lang, -# "domain": self._get_account_move_lines_domain(), -# } -# -# def _export(self, report_type): -# """Default export is PDF.""" -# return self._print_report(report_type) -# -# def _get_atr_from_dict(self, obj_id, data, key): -# try: -# return data[obj_id][key] -# except KeyError: -# return data[str(obj_id)][key] -# -# def numer(self, name): -# if name: -# numeration = re.findall('\d+$', name) -# if numeration: return numeration[0] -# return name -# -# def get_data_format(self, date): -# if date and date != 'False': -# return dt.ru_strftime(u'%d.%m.%Y Рі.', date=datetime.strptime(str(date), "%Y-%m-%d"), inflected=True) -# return '' -# -# def initials(self, fio): -# if fio: -# return (fio.split()[0] + ' ' + ''.join([fio[0:1] + '.' for fio in fio.split()[1:]])).strip() -# return '' -# -# def rubles(self, sum): -# "Transform sum number in rubles to text" -# text_rubles = numeral.rubles(int(sum)) -# copeck = round((sum - int(sum)) * 100) -# text_copeck = numeral.choose_plural(int(copeck), (u"копейка", u"копейки", u"копеек")) -# return ("%s %02d %s") % (text_rubles, copeck, text_copeck) -# -# def img(self, img, type='png', width=0, height=0): -# if width: -# width = "width='%spx'" % (width) -# else: -# width = " " -# if height: -# height = "height='%spx'" % (height) -# else: -# height = " " -# toreturn = "" % ( -# width, -# height, -# type, -# str(pycompat.to_text(img))) -# return toreturn -# -# def get_contract(self): -# partner = int(self.partner_ids[0].id) -# contract = self.env['partner.contract.customer'].search( -# [('partner_id', '=', partner), ('state', '=', 'signed')], limit=1) -# if contract: -# return contract -# -# def get_function_partner(self, partner): -# director = self.env['res.partner'].search([('parent_id', '=', partner), ('type', '=', 'director')], limit=1) -# if director: -# if director.function: -# return director.function or 'отсутствует' -# -# def get_name_partner(self, partner): -# director = self.env['res.partner'].search([('parent_id', '=', partner), ('type', '=', 'director')], limit=1) -# if director: -# return director.name or 'отсутствует' -# -# def get_report_filename(self): -# today = date.today() -# d1 = today.strftime("%d-%m-%Y") -# if self.partner_ids[0].parent_id: -# p = ''.join(self.partner_ids[0].parent_id.name) -# else: -# p = ''.join(self.partner_ids[0].name) -# # return 'РђРєС‚ Сверки '+ d1 + ' ' + self.company_id.name+'_'+p -# return str(self.company_id.id) + ' - ' + ' ' + d1 -# -# def sorted_lines(self, list): -# list = sorted(list, key=lambda k: k.get('date'), reverse=False) -# return list diff --git a/act_revise/wizard/general_ledger_wizard_view.xml b/act_revise/wizard/general_ledger_wizard_view.xml deleted file mode 100644 index 7ea248f..0000000 --- a/act_revise/wizard/general_ledger_wizard_view.xml +++ /dev/null @@ -1,167 +0,0 @@ - - - - - Акт сверки - general.ledger.act_revise.wizard - -
- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -

- General Ledger can be computed only if selected company have - only one unaffected earnings account. -

- -
-
-
-
-
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - Акт сверки - general.ledger.act_revise.wizard - form - - new - - - - Печатать акт сверки - general.ledger.act_revise.wizard - - form - {'default_receivable_accounts_only': 1, 'default_payable_accounts_only': 1} - - new - - - - -
diff --git a/base_russian_localization/README.md b/base_russian_localization/README.md deleted file mode 100644 index 7346be9..0000000 --- a/base_russian_localization/README.md +++ /dev/null @@ -1,93 +0,0 @@ -# Base Russian Localization - - - -## Getting started - -To make it easy for you to get started with GitLab, here's a list of recommended next steps. - -Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! - -## Add your files - -- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files -- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command: - -``` -cd existing_repo -git remote add origin https://gitlab.inf-centre.ru/mklab-base/l10n-russia/base_russian_localization.git -git branch -M v17-dev -git push -uf origin v17-dev -``` - -## Integrate with your tools - -- [ ] [Set up project integrations](https://gitlab.inf-centre.ru/mklab-base/l10n-russia/base_russian_localization/-/settings/integrations) - -## Collaborate with your team - -- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) -- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) -- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) -- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) -- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html) - -## Test and Deploy - -Use the built-in continuous integration in GitLab. - -- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html) -- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) -- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) -- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/) -- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) - -*** - -# Editing this README - -When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template. - -## Suggestions for a good README - -Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information. - -## Name -Choose a self-explaining name for your project. - -## Description -Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors. - -## Badges -On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. - -## Visuals -Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method. - -## Installation -Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection. - -## Usage -Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. - -## Support -Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. - -## Roadmap -If you have ideas for releases in the future, it is a good idea to list them in the README. - -## Contributing -State if you are open to contributions and what your requirements are for accepting them. - -For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. - -You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. - -## Authors and acknowledgment -Show your appreciation to those who have contributed to the project. - -## License -For open source projects, say how it is licensed. - -## Project status -If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. diff --git a/base_russian_localization/__init__.py b/base_russian_localization/__init__.py deleted file mode 100644 index 899bcc9..0000000 --- a/base_russian_localization/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from . import models - diff --git a/base_russian_localization/__manifest__.py b/base_russian_localization/__manifest__.py deleted file mode 100644 index 62dd9ba..0000000 --- a/base_russian_localization/__manifest__.py +++ /dev/null @@ -1,28 +0,0 @@ -# -*- coding: utf-8 -*- -{ - 'name': "base_russian_localization", - 'summary': """ - Российская локализация: основные отчеты и печатные формы. - """, - - 'description': """ - Российская локализация: основные отчеты и печатные формы. - - Для включения модулей: - 1. Меню Настройки - в боковом меню "Российская локализация" - 2. Выбирается нужный блок. - """, - - 'author': "Odoo Community Association (OCA), MK Lab", - 'website': "https://www.inf-centre.ru/", - - 'version': '17.0.1.0.0', - 'license': 'LGPL-3', - 'category': 'Uncategorized', - - 'depends': [], - - 'data': [ - 'views/res_config_settings_views.xml', - ], -} diff --git a/base_russian_localization/i18n/ru_RU.po b/base_russian_localization/i18n/ru_RU.po deleted file mode 100644 index 4e0f84e..0000000 --- a/base_russian_localization/i18n/ru_RU.po +++ /dev/null @@ -1,109 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * base_russian_localization -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 17.0+e-20240904\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-29 07:45+0000\n" -"PO-Revision-Date: 2024-10-29 07:45+0000\n" -"Last-Translator: \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: base_russian_localization -#. odoo-python -#: code:addons/base_russian_localization/models/res_config_settings.py:0 -#: model:ir.model.fields,field_description:base_russian_localization.field_res_config_settings__module_act_revise -#: model_terms:ir.ui.view,arch_db:base_russian_localization.res_config_settings_view_form -#, python-format -msgid "Act revise" -msgstr "Акт сверки" - -#. module: base_russian_localization -#: model:ir.model.fields,field_description:base_russian_localization.field_res_config_settings__company_status_rf -msgid "Company Status Rf" -msgstr "Статус компании" - -#. module: base_russian_localization -#: model:ir.model,name:base_russian_localization.model_res_config_settings -msgid "Config Settings" -msgstr "Параметры конфигурации" - -#. module: base_russian_localization -#. odoo-python -#: code:addons/base_russian_localization/models/res_config_settings.py:0 -#: model:ir.model.fields,field_description:base_russian_localization.field_res_config_settings__module_fehu_base_consent -#: model_terms:ir.ui.view,arch_db:base_russian_localization.res_config_settings_view_form -#, python-format -msgid "Consent" -msgstr "Доверенность" - -#. module: base_russian_localization -#. odoo-python -#: code:addons/base_russian_localization/models/res_config_settings.py:0 -#: model:ir.model.fields,field_description:base_russian_localization.field_res_config_settings__module_contract -#, python-format -msgid "Contract" -msgstr "Договор" - -#. module: base_russian_localization -#: model_terms:ir.ui.view,arch_db:base_russian_localization.res_config_settings_view_form -msgid "Contracts" -msgstr "Договоры" - -#. module: base_russian_localization -#: model_terms:ir.ui.view,arch_db:base_russian_localization.res_config_settings_view_form -msgid "Powers of attorney" -msgstr "Доверенность на получение ТМЦ" - -#. module: base_russian_localization -#. odoo-python -#: code:addons/base_russian_localization/models/res_config_settings.py:0 -#: model:ir.model.fields,field_description:base_russian_localization.field_res_config_settings__module_l10n_ru_doc -#: model_terms:ir.ui.view,arch_db:base_russian_localization.res_config_settings_view_form -#, python-format -msgid "Print forms" -msgstr "Печатные формы" - -#. module: base_russian_localization -#: model_terms:ir.ui.view,arch_db:base_russian_localization.res_config_settings_view_form -msgid "Report act revise" -msgstr "Отчет Акт сверки" - -#. module: base_russian_localization -#: model_terms:ir.ui.view,arch_db:base_russian_localization.res_config_settings_view_form -msgid "Report contract" -msgstr "Договоры" - -#. module: base_russian_localization -#: model_terms:ir.ui.view,arch_db:base_russian_localization.res_config_settings_view_form -msgid "Report report_xml" -msgstr "УПД в формате xml для ЭДО" - -#. module: base_russian_localization -#. odoo-python -#: code:addons/base_russian_localization/models/res_config_settings.py:0 -#: model:ir.model.fields,field_description:base_russian_localization.field_res_config_settings__module_report_xml -#, python-format -msgid "Report_xml" -msgstr "Универсальный передаточный документ (УПД) в формате xml для ЭДО" - -#. module: base_russian_localization -#: model_terms:ir.ui.view,arch_db:base_russian_localization.res_config_settings_view_form -msgid "Russian Localization" -msgstr "Российская локализация" - -#. module: base_russian_localization -#: model_terms:ir.ui.view,arch_db:base_russian_localization.res_config_settings_view_form -msgid "UPD xml" -msgstr "УПД в формате xml для ЭДО" - -#. module: base_russian_localization -#: model_terms:ir.ui.view,arch_db:base_russian_localization.res_config_settings_view_form -msgid "print_forms" -msgstr "Печатные формы документов" diff --git a/base_russian_localization/models/__init__.py b/base_russian_localization/models/__init__.py deleted file mode 100644 index 4a30401..0000000 --- a/base_russian_localization/models/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from . import res_config_settings - - - diff --git a/base_russian_localization/models/res_config_settings.py b/base_russian_localization/models/res_config_settings.py deleted file mode 100644 index e37a1bf..0000000 --- a/base_russian_localization/models/res_config_settings.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from odoo import _, api, fields, models - -class ResConfigSettings(models.TransientModel): - _inherit = 'res.config.settings' - - module_act_revise = fields.Boolean(_("Act revise")) - module_contract = fields.Boolean(_("Contract")) - module_report_xml = fields.Boolean(_("Report_xml")) - module_l10n_ru_doc = fields.Boolean(_("Print forms")) - module_fehu_base_consent = fields.Boolean(_("Consent")) - company_status_rf = fields.Boolean('', compute='_compute_company_status') - - def _compute_company_status(self): - company_state = False - if self.env.company: - company_state = self.env.company.state_id.code == 'RU' - self.company_status_rf = company_state - - @api.onchange('company_status_rf') - def _onchange_company_status_rf(self): - if self.company_status_rf: - self.module_act_revise = False - self.module_contract = False - self.module_report_xml = False - self.module_l10n_ru_doc = False - self.module_fehu_base_consent = False - diff --git a/base_russian_localization/static/description/icon.png b/base_russian_localization/static/description/icon.png deleted file mode 100644 index 5ea24f8..0000000 Binary files a/base_russian_localization/static/description/icon.png and /dev/null differ diff --git a/base_russian_localization/views/res_config_settings_views.xml b/base_russian_localization/views/res_config_settings_views.xml deleted file mode 100644 index 1c08ed0..0000000 --- a/base_russian_localization/views/res_config_settings_views.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - res.config.settings.view.form.inherit.russian.localization - res.config.settings - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/contract/__init__.py b/contract/__init__.py deleted file mode 100644 index 7db6694..0000000 --- a/contract/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -*- coding: utf-8 -*- -from . import models -from . import report diff --git a/contract/__manifest__.py b/contract/__manifest__.py deleted file mode 100644 index c1ad9b9..0000000 --- a/contract/__manifest__.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -{ - 'name': 'Контракты клиентов', - 'version': '17.0.2024.02.02', - 'sequence': 0, - 'author': 'StarlingSoft', - 'website': 'https://inf-centre.ru', - 'depends': [ - 'base', - 'mail', - 'account', 'sale', 'sale_management', 'purchase' - ], - 'data': [ - 'data/data.xml', - 'views/contract_customer_view.xml', - 'security/ir.model.access.csv', - 'report/report_contract.xml', - 'report/report_contract_order.xml', - 'report/report_contract_order1.xml', - 'report/report_contract_invoce.xml', - - ], - 'installable': True, - 'auto_install': False, -} diff --git a/contract/data/data.xml b/contract/data/data.xml deleted file mode 100644 index 3b1bf11..0000000 --- a/contract/data/data.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - Договор последовательность клиент - partner.contract.customer.sequence - - - - 5 - - - Договор последовательность поставщик - partner.contract.supplier.sequence - - - - 5 - - - diff --git a/contract/models/__init__.py b/contract/models/__init__.py deleted file mode 100644 index 837d2e2..0000000 --- a/contract/models/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# -*- coding: utf-8 -*- -from . import contract_customer, invoice_saleorder, dop_field, crutch_fields_header diff --git a/contract/models/contract_customer.py b/contract/models/contract_customer.py deleted file mode 100644 index a9464d0..0000000 --- a/contract/models/contract_customer.py +++ /dev/null @@ -1,334 +0,0 @@ -# -*- coding: utf-8 -*- -from odoo import api, fields, models, exceptions, tools -import pymorphy2 -from datetime import datetime, timedelta -from dateutil.relativedelta import relativedelta -from .crutch_fields_header import IP_CONTACT_HEADER, ENTITY_CONTRACT_HEADER, INDIVIDUAL_CONTRACT_HEADER - - -class PartnerContractCustomer(models.Model): - _name = 'partner.contract.customer' - _inherit = ['mail.thread', 'mail.activity.mixin', 'mail.render.mixin'] - - def get_dateend(self): - if self.date_start: - six_months = fields.Datetime.from_string(self.date_start) + relativedelta(months=+11) - else: - six_months = datetime.today() + relativedelta(months=+11) - return fields.Datetime.to_string(six_months) - - name = fields.Char(string='Номер') - date_start = fields.Date(string='Дата договора', required=True, default=fields.Datetime.now()) - partner_id = fields.Many2one('res.partner', string='Контрагент', required=True) - sec_partner_id = fields.Many2one('res.partner', string='Контрагент как в заказе') - company_id = fields.Many2one('res.company', string='Компания', required=True) - name_print = fields.Char(string='Имя для печати', compute='_get_name_print') - name_print1 = fields.Char(string='Имя для печати, И.П.', compute='_get_name_printip') - date_end = fields.Date(string='Дата окончания', required=True, default=get_dateend) - name_dirprint = fields.Char(string='Имя нашего директора для печати') - name_dirprint1 = fields.Char(string='Имя нашего директора для печати И.П.') - lines = fields.One2many('contract.line', 'contract_id', string='Договорные цены') - type = fields.Selection( - [('customer', 'С покупателем'), - ('supplier', 'С поставщиком'), - ('other', 'Прочие расчеты'), - - ], - string='Тип договора', default='customer', required=True) - saleorder_id = fields.Many2one('sale.order', string='Заказ/Сделка') - stamp = fields.Boolean(string='Печать и подпись') - signed = fields.Boolean(string='Договор подписан') - state = fields.Selection( - [('draft', 'Черновик'), - ('progress', 'На согласовании'), - ('signed', 'Подписан, действует'), - ('closed', 'Истёк'), - ], - string='Статус', default='draft', group_expand='_expand_states', index=True - ) - is_template = fields.Boolean('Это шаблон') - copy_from = fields.Many2one('partner.contract.customer', string='Копировать из этого шаблона') - profile_id = fields.Many2one('contract.profile', string='Вид договора', required=True) - credit_limit = fields.Float(string='Лимит кредита') - guid_1s = fields.Char('Код договора из 1С') - buh_code = fields.Char('Код договора из бухгалтерии') - payment_term_id = fields.Many2one('account.payment.term', string='Условие оплаты') - manager_id = fields.Many2one('res.users', string='Менеджер по продажам') - accountant_id = fields.Many2one('res.users', string='Бухгалтер по взаиморасчетам') - time_to_delivery_from = fields.Datetime('Время доставки от') - time_to_delivery_to = fields.Datetime('Время доставки до') - day_of_delivery = fields.Float('Дни доставки') - day_of_otgruzki = fields.Float('Дни отгрузки') - - channel_id = fields.Many2one('saleorder.channel', string='Канал продаж') - team_id = fields.Many2one('crm.team', string='Команда продаж') - order_days_ids = fields.Many2many(comodel_name='contract.day', relation='orderdays', string='Дни доставки', - column1='contract_id', column2='day_id') - shipment_days_ids = fields.Many2many(comodel_name='contract.day', relation='shipmentdays', string='Дни отгрузки', - column1='contract_id', - column2='day_id') - # Доработка хедера договора - partner_type = fields.Selection(string='Тип контрагента', selection=[ - ('person', 'Физ. лицо'), - ('company_ip', 'ИП'), - ('company', 'Юр. лицо') - ], required=True) - contract_header = fields.Html('Шапка договора') - - @api.onchange('partner_type') - def generate_contract_header(self): - self.ensure_one() - self.render_model = 'partner.contract.customer' - if self.partner_type == 'company_ip': - self.contract_header = IP_CONTACT_HEADER - elif self.partner_type == 'person': - self.contract_header = INDIVIDUAL_CONTRACT_HEADER - else: - self.contract_header = ENTITY_CONTRACT_HEADER - # # Рендер Jinja выражение типа {{object.field}} - result = self._render_template(self.contract_header, self.render_model, res_ids=[self.id]) - result = tools.html_sanitize(result[self.id]) - self.contract_header = result - - @api.onchange('sec_partner_id') - def set_pid(self): - self.partner_id = self.sec_partner_id.parent_id if self.sec_partner_id.parent_id else self.sec_partner_id - - def _expand_states(self, states, domain, order): - return [key for key, val in type(self).state.selection] - - def copy_it(self): - if self.copy_from: - for line in self.copy_from.lines: - line.copy({'contract_id': self.id}) - - def _get_name_print(self): - morph = pymorphy2.MorphAnalyzer() - self.name_print = False - director = self.env['res.partner'].search([('parent_id', '=', self.partner_id.id), ('type', '=', 'director')], - limit=1) - if director: - if len(director.name.split(' ')) == 3: - lastname_old, firstname_old, middlename_old = director.name.split(' ') - - if lastname_old: - lastname_n = morph.parse(lastname_old)[0] - if lastname_n.inflect({'gent'}): - lastname_n = lastname_n.inflect({'gent'}).word - else: - lastname_n = lastname_old - else: - lastname_n = '' - - if firstname_old: - firstname_n = morph.parse(firstname_old)[0] - firstname_n = firstname_n.inflect({'gent'}).word - else: - firstname_n = '' - - if middlename_old: - middlename_n = morph.parse(middlename_old)[0] - middlename_n = middlename_n.inflect({'gent'}).word - else: - middlename_n = '' - - name_print = lastname_n + ' ' + firstname_n + ' ' + middlename_n - - self.name_print = name_print.title() - - def _get_name_print1(self): - # morph = pymorphy2.MorphAnalyzer() - director = self.company_id.chief_id.partner_id if self.company_id.chief_id else False - # raise exceptions.UserError(str(director)) - self.name_dirprint = False - if director: - if len(director.name.split(' ')) == 3: - lastname_old, firstname_old, middlename_old = director.name.split(' ') - - if lastname_old: - lastname_n = morph.parse(lastname_old)[0] - lastname_n = lastname_n.inflect({'gent'}).word - else: - lastname_n = '' - - if firstname_old: - firstname_n = morph.parse(firstname_old)[0] - firstname_n = firstname_n.inflect({'gent'}).word - else: - firstname_n = '' - - if middlename_old: - middlename_n = morph.parse(middlename_old)[0] - middlename_n = middlename_n.inflect({'gent'}).word - else: - middlename_n = '' - - name_print = lastname_n + ' ' + firstname_n + ' ' + middlename_n - - self.name_dirprint = name_print.title() - - @api.model - def create(self, values): - res = super(PartnerContractCustomer, self).create(values) - - if values.get('is_template'): - return res - - if values.get('type') == 'customer': - sequence_code = 'partner.contract.customer.sequence' - elif values.get('type') == 'supplier': - sequence_code = 'partner.contract.supplier.sequence' - else: - return res - - name = self.env['ir.sequence'].next_by_code(sequence_code) - - res.update({ - 'name': name, - }) - - return res - - # @api.model - def write(self, values): - - if 'state' in values: - if self.state != values['state']: - msg = 'Статус: ' + dict(self._fields['state'].selection).get(self.state) + ' -> ' + dict( - self._fields['state'].selection).get(values['state']) - self.message_post(body=msg) - res = super(PartnerContractCustomer, self).write(values) - return res - - def _get_name_print1ip(self): - self.name_dirprint1 = self.company_id.chief_id.partner_id.name if self.company_id.chief_id else False - - def _get_name_printip(self): - self.name_print1 = False - director = self.env['res.partner'].search([('parent_id', '=', self.partner_id.id), ('type', '=', 'director')], - limit=1) - if director: - self.name_print1 = director.name - - def print_supp(self): - # self.filtered(lambda s: s.state == 'draft').write({'state': 'sent'}) - return self.env['report'].get_action(self, 'mta_base.action_mtacontractsupp_report') - - def print_contract_cust(self): - if self.saleorder_id: - return self.saleorder_id.print_contract() - else: - raise exceptions.UserError( - 'Вы не можете напечатать договор с Клиентом, потому что нет связи с Заказом. Нужно зайти в Заказ и привязать этот договор.') - - def contract_action_confirm(self): - if self.state == 'draft': - self.state = 'progress' - elif self.state == 'progress': - self.state = 'signed' - - def contract_in_draft(self): - self.state = 'draft' - - @api.onchange('name') - def set_comp_and_partn(self): - context = self._context - order_id = context.get('sale_order_id') - if order_id: - sale_order = self.env['sale.order'].browse(order_id) - - self.company_id = sale_order.company_id - self.partner_id = sale_order.partner_id - - @api.onchange('profile_id') - def set_payment(self): - if self.profile_id.payment_term_id: - self.payment_term_id = self.profile_id.payment_term_id - - # @api.constrains('name') - def check_name(self): - obj = self.search([('name', '=', self.name), ('id', '!=', self.id), ('state', '!=', 'closed')]) - if obj: - raise exceptions.ValidationError('Договор с таким номером уже существует') - - """ - @api.constrains('profile_id') - def check_profile_id(self): - contracts = self.search([('partner_id', '=', self.partner_id.id), ('id', '!=', self.id)]) - if contracts: - profiles_in_contracts = contracts.profile_id - # raise exceptions.ValidationError(profiles_in_contracts.ids) - if profiles_in_contracts: - ads = self.env['contract.allowed.profiles'].search( - [('allowed_profiles', 'in', profiles_in_contracts.ids)]) - if ads: - raise exceptions.ValidationError((self.profile_id.name, ads.name)) - # raise exceptions.ValidationError(contracts) - """ - - -class Partner(models.Model): - _inherit = 'res.partner' - - contract_count = fields.Integer(string='Договоры', compute='get_count_contract') - pol = fields.Selection(string="Пол", selection=[('m', 'Муж.'), ('j', 'Жен'), ], required=False) - type = fields.Selection(selection_add=[('director', 'Директор')]) - - def get_count_contract(self): - contract = self.env['partner.contract.customer'] - self.contract_count = contract.search_count([('partner_id', '=', self.id)]) - - def action_view_contract(self): - action = self.env.ref('contract.contract_customer_action').read()[0] - - action['domain'] = [('partner_id', '=', self.id)] - - return action - - -class ContractLine(models.Model): - _name = 'contract.line' - contract_id = fields.Many2one('partner.contract.customer', string='Order Reference', required=True, - ondelete='cascade', index=True, copy=False) - _order = "sequence desc" - # name = fields.Text(string='Название для договора') - # price_unit = fields.Float('Цена', default=0.0) - # product_uom = fields.Many2one('uom.uom', string='Единица измерения') - # product_id = fields.Many2one('product.product', string='Услуга', domain=[('sale_ok', '=', True)], change_default=True, ondelete='restrict') - sequence = fields.Integer('Порядок') - name = fields.Char('Номер пункта') - punct = fields.Html('Текст пункта') - - @api.onchange('product_id') - def set_name(self): - self.name = self.product_id.name - - -class AllowedProfiles(models.Model): - _name = 'contract.allowed.profiles' - name = fields.Char(string='Одновременно включены следующие виды договоров:') - allowed_profiles = fields.Many2many('contract.profile', string='Виды договоров', required=True) - - @api.onchange('allowed_profiles') - def set_name(self): - self.name = '' - for profile in self.allowed_profiles: - self.name += profile.name + ' + ' - if self.name: - if self.name[-2] == '+': - self.name = self.name[:-2] - - -class ContractProfile(models.Model): - _name = 'contract.profile' - name = fields.Char(string='Вид договора', required=True) - payable_account_id = fields.Many2one('account.account', string='Счет кредиторской задолженности', required=True) - receivable_account_id = fields.Many2one('account.account', string='Счет дебиторской задолженности', required=True) - max_receivable_id = fields.Float(string='Максимальная деб. задолженность', required=True) - payment_term_id = fields.Many2one('account.payment.term', string='Условие оплаты', required=True) - journal_id = fields.Many2one('account.journal', string='Журнал', required=True) - - -class ContractDay(models.Model): - _name = 'contract.day' - name = fields.Char('День') diff --git a/contract/models/crutch_fields_header.py b/contract/models/crutch_fields_header.py deleted file mode 100644 index f290eff..0000000 --- a/contract/models/crutch_fields_header.py +++ /dev/null @@ -1,33 +0,0 @@ -ENTITY_CONTRACT_HEADER = """ -{{object.company_id.partner_id.name}}, -именуемое в дальнейшем «Поставщик», в лице -{{(object.company_id.chief_id.partner_id.function or '').lower()}} -{{(object.name_dirprint1 or '').title()}}, - действующего на основании ОГРНИП № {{object.company_id.company_registry or ''}}, с одной стороны, и {{object.partner_id.name or ''}}, -именуемое в дальнейшем «Покупатель», в лице -{{(object.get_function_partner1(object.partner_id.id) or '').lower()}} -{{(object.name_print1 or '').title()}}, действующего на основании устава общества, с другой стороны, вместе именуемые в дальнейшем «Стороны» заключили -настоящий Договор о нижеследующем: - """ -IP_CONTACT_HEADER = """ -{{object.company_id.partner_id.name}}, -именуемое в дальнейшем «Поставщик», в лице -{{(object.company_id.chief_id.partner_id.function or '').lower()}} -{{(object.name_dirprint1 or '').title()}}, - действующего на основании ОГРНИП № {{object.company_id.company_registry or ''}}, с одной стороны, и {{object.partner_id.name or ''}}, -именуемое в дальнейшем «Покупатель», в лице -{{(object.get_function_partner1(object.partner_id.id) or '').lower()}} -{{(object.name_print1 or '').title()}}, действующего на основании ОГРНИП №{{object.partner_id.ogrn or ''}}, - с другой стороны, вместе именуемые в дальнейшем «Стороны» заключили -настоящий Договор о нижеследующем: -""" - -INDIVIDUAL_CONTRACT_HEADER = """ -{{object.company_id.partner_id.name}}, -именуемое в дальнейшем «Поставщик», в лице -{{(object.company_id.chief_id.partner_id.function or '').lower()}} -{{(object.name_dirprint1 or '').title()}}, - действующего на основании ОГРНИП № {{object.company_id.company_registry or ''}}, с одной стороны, и {{object.partner_id.name or ''}}, -именуемое в дальнейшем «Покупатель», вместе именуемые в дальнейшем «Стороны» заключили -настоящий Договор о нижеследующем: - """ diff --git a/contract/models/dop_field.py b/contract/models/dop_field.py deleted file mode 100644 index 9c8626d..0000000 --- a/contract/models/dop_field.py +++ /dev/null @@ -1,353 +0,0 @@ -from odoo import api, fields, models, exceptions -from datetime import datetime -import re -import pymorphy2 -from odoo.tools import pycompat - -FRACTIONS = ( - (u"десятая", u"десятых", u"десятых"), - (u"сотая", u"сотых", u"сотых"), - (u"тысячная", u"тысячных", u"тысячных"), - (u"десятитысячная", u"десятитысячных", u"десятитысячных"), - (u"стотысячная", u"стотысячных", u"стотысячных"), - (u"миллионная", u"милллионных", u"милллионных"), - (u"десятимиллионная", u"десятимилллионных", u"десятимиллионных"), - (u"стомиллионная", u"стомилллионных", u"стомиллионных"), - (u"миллиардная", u"миллиардных", u"миллиардных"), -) - -ONES = { - 0: (u"", u"", u""), - 1: (u"один", u"одна", u"одно"), - 2: (u"два", u"две", u"два"), - 3: (u"три", u"три", u"три"), - 4: (u"четыре", u"четыре", u"четыре"), - 5: (u"пять", u"пять", u"пять"), - 6: (u"шесть", u"шесть", u"шесть"), - 7: (u"семь", u"семь", u"семь"), - 8: (u"восемь", u"восемь", u"восемь"), - 9: (u"девять", u"девять", u"девять"), -} - -TENS = { - 0: u"", - 10: u"десять", - 11: u"одиннадцать", - 12: u"двенадцать", - 13: u"тринадцать", - 14: u"четырнадцать", - 15: u"пятнадцать", - 16: u"шестнадцать", - 17: u"семнадцать", - 18: u"восемнадцать", - 19: u"девятнадцать", - 2: u"двадцать", - 3: u"тридцать", - 4: u"сорок", - 5: u"пятьдесят", - 6: u"шестьдесят", - 7: u"семьдесят", - 8: u"восемьдесят", - 9: u"девяносто", -} - -HUNDREDS = { - 0: u"", - 1: u"сто", - 2: u"двести", - 3: u"триста", - 4: u"четыреста", - 5: u"пятьсот", - 6: u"шестьсот", - 7: u"семьсот", - 8: u"восемьсот", - 9: u"девятьсот", -} - -MALE = 1 -FEMALE = 2 - -import operator -import sys -import types - -PY2 = sys.version_info[0] == 2 -PY3 = sys.version_info[0] == 3 - -if PY3: - string_types = str, - integer_types = int, - class_types = type, - text_type = str - binary_type = bytes - - MAXSIZE = sys.maxsize -else: - string_types = basestring, - integer_types = (int, long) - class_types = (type, types.ClassType) - text_type = unicode - binary_type = str - - -class Partner_Bank(models.Model): - _inherit = 'res.partner.bank' - bank_corr_acc = fields.Char('Кор.счет') - - -# class Bank(models.Model): -# _inherit = 'res.bank' - -# corr_acc = fields.Char('Corresponding account', size=64) - -# class Users(models.Model): -# _inherit = 'res.users' - -# facsimile = fields.Binary("Facsimile") - -class Company(models.Model): - _inherit = 'res.company' - - inn = fields.Char(related='partner_id.inn', readonly=False) - kpp = fields.Char(related='partner_id.kpp', readonly=False) - okpo = fields.Char(related='partner_id.okpo', readonly=False) - chief_id = fields.Many2one('res.users', 'Имя директора') - stamp = fields.Binary("Stamp") - - -class Partner(models.Model): - _inherit = 'res.partner' - ogrn = fields.Char('ОГРН') - okpo = fields.Char('ОКПО') - inn = fields.Char('ИНН') - kpp = fields.Char('KPP') - passport = fields.Char('Паспорт') - - -class Report_contract_customer(models.Model): - _inherit = 'partner.contract.customer' - - def img(self, img, type='png', width=0, height=0): - if width: - width = "width='%spx'" % (width) - else: - width = " " - if height: - height = "height='%spx'" % (height) - else: - height = " " - toreturn = "" % ( - width, - height, - type, - str(pycompat.to_text(img))) - return toreturn - - def numer(self, name): - if name: - numeration = re.findall('\d+$', name) - if numeration: return numeration[0] - return '' - - def ru_date(self, date): - if date and date != 'False': - return dt.ru_strftime(u'"%d" %B %Y года', date=datetime.strptime(str(date), "%Y-%m-%d"), inflected=True) - return '' - - def ru_date2(self, date): - if date and date != 'False': - return dt.ru_strftime(u'%d %B %Y г.', date=datetime.strptime(str(date), "%Y-%m-%d %H:%M:%S"), - inflected=True) - return '' - - def in_words(self, number): - return numeral.in_words(number) - - def rubles(self, sum): - "Transform sum number in rubles to text" - text_rubles = self.numeral_rubles(int(sum)) - copeck = round((sum - int(sum)) * 100) - text_copeck = self.numeral_choose_plural(int(copeck), (u"копейка", u"копейки", u"копеек")) - return ("%s %02d %s") % (text_rubles, copeck, text_copeck) - - def numeral_rubles(self, amount, zero_for_kopeck=False): - self.check_positive(amount) - pts = [] - amount = round(amount, 2) - pts.append(self.sum_string(int(amount), 1, (u"рубль", u"рубля", u"рублей"))) - remainder = self._get_float_remainder(amount, 2) - iremainder = int(remainder) - - if iremainder != 0 or zero_for_kopeck: - if iremainder < 10 and len(remainder) == 1: - iremainder *= 10 - pts.append(self.sum_string(iremainder, 2, - (u"копейка", u"копейки", u"копеек"))) - return u" ".join(pts) - - def _get_float_remainder(self, fvalue, signs=9): - self.check_positive(fvalue) - if isinstance(fvalue, integer_types): - return "0" - if isinstance(fvalue, Decimal) and fvalue.as_tuple()[2] == 0: - return "0" - - def sum_string(self, amount, gender, items=None): - if isinstance(items, text_type): - items = split_values(items) - if items is None: - items = (u"", u"", u"") - try: - one_item, two_items, five_items = items - except ValueError: - raise ValueError("Items must be 3-element sequence") - self.check_positive(amount) - if amount == 0: - return u"ноль %s" % five_items - into = u'' - tmp_val = amount - into, tmp_val = self._sum_string_fn(into, tmp_val, gender, items) - into, tmp_val = self._sum_string_fn(into, tmp_val, FEMALE, - (u"тысяча", u"тысячи", u"тысяч")) - into, tmp_val = self._sum_string_fn(into, tmp_val, MALE, - (u"миллион", u"миллиона", u"миллионов")) - into, tmp_val = self._sum_string_fn(into, tmp_val, MALE, - (u"миллиард", u"миллиарда", u"миллиардов")) - if tmp_val == 0: - return into - else: - raise ValueError("Cannot operand with numbers bigger than 10**11") - - def _sum_string_fn(self, into, tmp_val, gender, items=None): - if items is None: - items = (u"", u"", u"") - one_item, two_items, five_items = items - self.check_positive(tmp_val) - if tmp_val == 0: - return into, tmp_val - words = [] - rest = tmp_val % 1000 - tmp_val = tmp_val // 1000 - if rest == 0: - if into == u"": - into = u"%s " % five_items - return into, tmp_val - end_word = five_items - words.append(HUNDREDS[rest // 100]) - rest = rest % 100 - rest1 = rest // 10 - tens = rest1 == 1 and TENS[rest] or TENS[rest1] - words.append(tens) - if rest1 < 1 or rest1 > 1: - amount = rest % 10 - end_word = self.numeral_choose_plural(amount, items) - words.append(ONES[amount][gender - 1]) - words.append(end_word) - words.append(into) - words = filter(lambda x: len(x) > 0, words) - return u" ".join(words).strip(), tmp_val - - def check_positive(self, value, strict=False): - if not strict and value < 0: - raise ValueError("Value must be positive or zero, not %s" % str(value)) - if strict and value <= 0: - raise ValueError("Value must be positive, not %s" % str(value)) - - def numeral_choose_plural(self, amount, variants): - if isinstance(variants, text_type): - variants = split_values(variants) - self.check_length(variants, 3) - amount = abs(amount) - if amount % 10 == 1 and amount % 100 != 11: - variant = 0 - elif amount % 10 >= 2 and amount % 10 <= 4 and \ - (amount % 100 < 10 or amount % 100 >= 20): - variant = 1 - else: - variant = 2 - return variants[variant] - - def check_length(self, value, length): - _length = len(value) - if _length != length: - raise ValueError("length must be %d, not %d" % \ - (length, _length)) - - def initials(self, fio): - if fio: - return (fio.split()[0] + ' ' + ''.join([fio[0:1] + '.' for fio in fio.split()[1:]])).strip() - return '' - - def address(self, partner): - repr = [] - if partner.zip: repr.append(partner.zip) - if partner.city: repr.append(partner.city) - if partner.street: repr.append(partner.street) - if partner.street2: repr.append(partner.street2) - return ', '.join(repr) - - def address_delivery(self, partner): - if partner: - addr = self.env['res.partner'].search([('parent_id', '=', partner), ('type', '=', 'delivery')], limit=1) - repr = [] - if addr: - if addr.zip: repr.append(addr.zip) - if addr.city: repr.append(addr.city) - if addr.street: repr.append(addr.street) - if addr.street2: repr.append(addr.street2) - return ', '.join(repr) - - def get_function_print(self, function): - morph = pymorphy2.MorphAnalyzer() - if function: - f = morph.parse(function)[0] - f = f.inflect({'gent'}).word - return f.title() - - def get_function_partnerip(self, partner): - director = self.env['res.partner'].search([('parent_id', '=', partner), ('type', '=', 'director')], limit=1) - if director: - if director.function: - return director.function - - def get_function_partner(self, partner): - res = [] - morph = pymorphy2.MorphAnalyzer() - if partner: - director = self.env['res.partner'].search([('parent_id', '=', partner), ('type', '=', 'director')], limit=1) - if director: - if director.function: - list_f = str(director.function).split(' ') - for func in list_f: - f = morph.parse(func)[0] - f = f.inflect({'gent'}).word - res.append(f) - return ' '.join(res) - - def get_function_partner1(self, partner): - if partner: - director = self.env['res.partner'].search([('parent_id', '=', partner), ('type', '=', 'director')], limit=1) - if director: - if director.function: - return director.function - - def get_date_text(self, date): - month_list = ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', - 'ноября', 'декабря'] - if date: - date_list = str(date).split('-') - if date_list[0] and date_list[1] and date_list[2]: - return ('"' + date_list[2] + '" ' + month_list[int(date_list[1]) - 1] + ' ' + date_list[0] + ' г.') - - def get_bank(self, partner): - repr = [] - bank = None - if partner.bank_ids: - bank = partner.bank_ids[0] - elif partner.parent_id.bank_ids: - bank = partner.parent_id.bank_ids[0] - if bank and bank.bank_name: repr.append(bank.bank_name) - if bank and bank.acc_number: repr.append(u"Р/счет " + bank.acc_number) - if bank and bank.bank_bic: repr.append(u"БИК " + bank.bank_bic) - if bank and bank.bank_corr_acc: repr.append(u"к/с " + bank.bank_corr_acc) - return '
'.join(repr) diff --git a/contract/models/invoice_saleorder.py b/contract/models/invoice_saleorder.py deleted file mode 100644 index 3bfa5bd..0000000 --- a/contract/models/invoice_saleorder.py +++ /dev/null @@ -1,128 +0,0 @@ -from odoo import api, fields, models, exceptions -from datetime import datetime - - -class contract_sale_order(models.Model): - _inherit = 'sale.order' - mt_contractid = fields.Many2one('partner.contract.customer', string='Номер договора') - sec_partner_id = fields.Many2one('res.partner', string='Контрагент', store=True, compute='get_pid') - stamp = fields.Boolean(string='Печать и подпись', related='mt_contractid.stamp') - - @api.depends('partner_id') - def get_pid(self): - for s in self: - s.sec_partner_id = s.partner_id.parent_id if s.partner_id.parent_id else s.partner_id - - @api.onchange('mt_contractid') - def set_ons(self): - if self.mt_contractid: - self.payment_term_id = self.mt_contractid.payment_term_id - - @api.constrains('state') - def late_payment_check(self): - if self.mt_contractid: - if self.state == 'sale': - late_invoices_count = 0 - max_receivable = self.mt_contractid.profile_id.max_receivable_id # макс. деб. задолженность в договоре - # ищу просроченные инвойсы контрагента указанного в заказе со стейтом "Подтверждено" - invoices_obj = self.env['account.move'].search([('partner_id', '=', self.partner_id.id), - ('state', '=', 'posted'), - ('invoice_date_due', '<', datetime.now().date())]) - - for invoice in invoices_obj: - late_invoices_count += invoice.amount_residual # складываю деб. задолженность по просроченным инвойсам - - if late_invoices_count > max_receivable: - raise exceptions.ValidationError( - f'Нельзя подтвердить заказ, так как у контрагента {self.sec_partner_id.name} нарушено ' - f'условие по дебиторской задолженности.\n\n' - f'Контрагент {self.sec_partner_id.name} должен {late_invoices_count}руб.\n' - f'Максимальная дебиторская задолженность указанная в ' - f'договоре №{self.mt_contractid.name} - {max_receivable}руб.\n\n' - f'Проверьте следующие неоплаченные счета контрагента:\n' - f'{", ".join([invoice.name for invoice in invoices_obj])}') - - # при выбора счета "Обычный счет" - @api.model - def _create_invoices(self, grouped=False, final=False, date=None): - res = super(contract_sale_order, self)._create_invoices(grouped, final, date) - if self.mt_contractid: - res.write({'mt_contractid': self.mt_contractid, - 'journal_id': self.mt_contractid.profile_id.journal_id}) - # 'invoice_payment_term_id': self.mt_contractid.profile_id.payment_term_id - # 'line_ids': [(0, 0, { - # 'account_id': self.mt_contractid.profile_id.receivable_account_id.id})] - return res - - -class ContractCreateInvoice(models.TransientModel): - _inherit = 'sale.advance.payment.inv' - - # при выбора счета "Авансовый платеж" - @api.model - def _create_invoice(self, order, so_line, amount): - res = super(ContractCreateInvoice, self)._create_invoice(order, so_line, amount) - if order.mt_contractid: - res.write({'mt_contractid': order.mt_contractid, - 'journal_id': order.mt_contractid.profile_id.journal_id, }) - # 'invoice_payment_term_id': order.mt_contractid.profile_id.payment_term_id - return res - - -class contract_invoice(models.Model): - _inherit = 'account.move' - mt_contractid = fields.Many2one('partner.contract.customer', string='Номер договора') - sf_number = fields.Char(string='Номер с/ф') - osnovanie = fields.Char(string='Основание') - sec_partner_id = fields.Many2one('res.partner', string='Контрагент', store=True, compute='get_pid') - stamp = fields.Boolean(string='Печать и подпись', related='mt_contractid.stamp') - - @api.depends('partner_id') - def get_pid(self): - for s in self: - s.sec_partner_id = s.partner_id.parent_id if s.partner_id.parent_id else s.partner_id - - @api.onchange('mt_contractid') - def set_ons(self): - if self.mt_contractid: - self.osnovanie = 'Договор № ' + self.mt_contractid.name + ' от ' + fields.Datetime.from_string( - self.mt_contractid.date_start).strftime("%d.%m.%Y") - - @api.constrains('state') - def invoice_fields_check(self): - for s in self: - if s.state == 'posted': - if s.mt_contractid: - errors_list = [] - journal_in_contract = s.mt_contractid.profile_id.journal_id - payment_term_in_contract = s.mt_contractid.profile_id.payment_term_id - receivable_in_contract = s.mt_contractid.profile_id.receivable_account_id - - if journal_in_contract != s.journal_id: - errors_list.append(f'Отличается Журнал - [{s.journal_id.name}] ' - f'и указанный в договоре №{s.mt_contractid.name} ' - f'Журнал - [{journal_in_contract.name}]\n\n') - - if payment_term_in_contract != s.invoice_payment_term_id: - errors_list.append(f'Отличается поле "Условие оплаты" в инвойсе ' - f'[Условие оплаты - {s.invoice_payment_term_id.name}] ' - f'и указанный в договоре №{s.mt_contractid.name} ' - f'[Условие оплаты - {payment_term_in_contract.name}]\n\n') - - if receivable_in_contract not in s.line_ids.account_id: - errors_list.append(f'Отличается поле "Счет дебиторской задолженности" в инвойсе ' - f'и указанный в договоре №{s.mt_contractid.name}') - - if errors_list: - raise exceptions.ValidationError(''.join(errors_list)) - - -class contact_purchase_order(models.Model): - _inherit = 'purchase.order' - mt_contractid = fields.Many2one('partner.contract.customer', string='Номер договора') - sec_partner_id = fields.Many2one('res.partner', string='Контрагент', store=True, compute='get_pid') - - @api.depends('partner_id') - def get_pid(self): - for s in self: - s.sec_partner_id = s.partner_id.parent_id if s.partner_id.parent_id else s.partner_id diff --git a/contract/report/__init__.py b/contract/report/__init__.py deleted file mode 100644 index 6527450..0000000 --- a/contract/report/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# -*- coding: utf-8 -*- -from . import report_contract,report_contract_order,report_contract_invoce diff --git a/contract/report/report_contract.py b/contract/report/report_contract.py deleted file mode 100644 index 3baf414..0000000 --- a/contract/report/report_contract.py +++ /dev/null @@ -1,14 +0,0 @@ -# -*- coding: utf-8 -*- -from odoo import api, models - -class ContractCustomerReport(models.AbstractModel): - _name = 'contract.customer.report' - - - def get_report_values(self, docids, data=None): - docs = self.env['partner.contract.customer'].browse(docids) - return { - 'doc_ids': docs.ids, - 'doc_model': 'partner.contract.customer', - 'docs': docs, - } diff --git a/contract/report/report_contract.xml b/contract/report/report_contract.xml deleted file mode 100644 index 361871d..0000000 --- a/contract/report/report_contract.xml +++ /dev/null @@ -1,398 +0,0 @@ - - - - - - A4 - - A4 - 0 - 0 - Portrait - 15 - 30 - 7 - 7 - - 10 - 90 - - - - Договор - partner.contract.customer - qweb-pdf - contract.report_contract_customer - contract.report_contract_customer - 'Договор - %s' % (object.name) - - - report - - diff --git a/contract/report/report_contract_invoce.py b/contract/report/report_contract_invoce.py deleted file mode 100644 index f07f090..0000000 --- a/contract/report/report_contract_invoce.py +++ /dev/null @@ -1,15 +0,0 @@ -# -*- coding: utf-8 -*- -from odoo import api, models - - -class ContractCustomerReportOrder(models.AbstractModel): - _name = 'contract.customer.report_invoce' - - - def get_report_values(self, docids, data=None): - docs = self.env['account.move'].browse(docids) - return { - 'doc_ids': docs.ids, - 'doc_model': 'account.move', - 'docs': docs, - } diff --git a/contract/report/report_contract_invoce.xml b/contract/report/report_contract_invoce.xml deleted file mode 100644 index 634df7f..0000000 --- a/contract/report/report_contract_invoce.xml +++ /dev/null @@ -1,592 +0,0 @@ - - - - - - A4 - - A4 - 0 - 0 - Portrait - 15 - 30 - 7 - 7 - - 10 - 90 - - - - Договор со спецификацией - account.move - qweb-pdf - contract.report_contract_customer_invoce - contract.report_contract_customer_invoce - 'Договор со спецификацией - %s' % (object.name) - - - report - - diff --git a/contract/report/report_contract_order.py b/contract/report/report_contract_order.py deleted file mode 100644 index 42a679d..0000000 --- a/contract/report/report_contract_order.py +++ /dev/null @@ -1,18 +0,0 @@ -# -*- coding: utf-8 -*- -from odoo import api, models - - -class ContractCustomerReportOrder(models.AbstractModel): - _name = 'contract.customer.report_order' - - - def get_report_values(self, docids, data=None): - docs = self.env['sale.order'].browse(docids) - return { - 'doc_ids': docs.ids, - 'doc_model': 'sale.order', - 'docs': docs, - } - - - diff --git a/contract/report/report_contract_order.xml b/contract/report/report_contract_order.xml deleted file mode 100644 index 4e03297..0000000 --- a/contract/report/report_contract_order.xml +++ /dev/null @@ -1,594 +0,0 @@ - - - - - - A4 - - A4 - 0 - 0 - Portrait - 15 - 30 - 7 - 7 - - 10 - 90 - - - - Договор со спецификацией - sale.order - qweb-pdf - contract.report_contract_customer_order - contract.report_contract_customer_order - 'Договор со спецификацией - %s' % (object.name) - - - report - - diff --git a/contract/report/report_contract_order1.xml b/contract/report/report_contract_order1.xml deleted file mode 100644 index 2b8a887..0000000 --- a/contract/report/report_contract_order1.xml +++ /dev/null @@ -1,406 +0,0 @@ - - - - - - A4 - - A4 - 0 - 0 - Portrait - 15 - 30 - 7 - 7 - - 10 - 90 - - - - Спецификация - sale.order - qweb-pdf - contract.report_contract_customer_order1 - contract.report_contract_customer_order1 - 'Спецификация - %s' % (object.name) - - - report - - diff --git a/contract/security/ir.model.access.csv b/contract/security/ir.model.access.csv deleted file mode 100644 index 4f09569..0000000 --- a/contract/security/ir.model.access.csv +++ /dev/null @@ -1,6 +0,0 @@ -id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_partner_contract_customer,access_partner_contract_customer,model_partner_contract_customer,,1,1,1,1 -access_contract_profile,access_contract_profile,model_contract_profile,,1,1,1,1 -access_contract_day,access_contract_day,model_contract_day,,1,1,1,1 -access_contract_allowed_profiles,access_contract_allowed_profiles,model_contract_allowed_profiles,,1,1,1,1 -access_partner_contract_customerline,access_partner_contract_customerline,model_contract_line,,1,1,1,1 diff --git a/contract/views/contract_customer_view.xml b/contract/views/contract_customer_view.xml deleted file mode 100644 index ca1ecd9..0000000 --- a/contract/views/contract_customer_view.xml +++ /dev/null @@ -1,358 +0,0 @@ - - - - - - Договор - partner.contract.customer - -
-
- -
- -

-

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - view_saleorder_form - sale.order - - - - - - - - - - - - - view_purchaseorder_formcontr - purchase.order - - - - - - - - - - - - - - view_invoice_form - account.move - - - - - - - - - - - - - - - - Договор - partner.contract.customer - - - - - - - - - - -
-
-
- Номер: -
-
- Контрагент:
- Тип:
- Вид договора: -
-
- Наша компания: -
-
-
-
-
-
- - -
-
- - - - - - - - - - - - - - - - -
-
diff --git a/fehy_base_consent/README.md b/fehy_base_consent/README.md deleted file mode 100644 index d336cfb..0000000 --- a/fehy_base_consent/README.md +++ /dev/null @@ -1,93 +0,0 @@ -# fehy_base_consent - - - -## Getting started - -To make it easy for you to get started with GitLab, here's a list of recommended next steps. - -Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! - -## Add your files - -- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files -- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command: - -``` -cd existing_repo -git remote add origin https://gitlab.inf-centre.ru/mklab-base/l10n-russia/fehy_base_consent.git -git branch -M v17-dev -git push -uf origin v17-dev -``` - -## Integrate with your tools - -- [ ] [Set up project integrations](https://gitlab.inf-centre.ru/mklab-base/l10n-russia/fehy_base_consent/-/settings/integrations) - -## Collaborate with your team - -- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) -- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) -- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) -- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) -- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html) - -## Test and Deploy - -Use the built-in continuous integration in GitLab. - -- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html) -- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) -- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) -- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/) -- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) - -*** - -# Editing this README - -When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template. - -## Suggestions for a good README - -Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information. - -## Name -Choose a self-explaining name for your project. - -## Description -Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors. - -## Badges -On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. - -## Visuals -Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method. - -## Installation -Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection. - -## Usage -Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. - -## Support -Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. - -## Roadmap -If you have ideas for releases in the future, it is a good idea to list them in the README. - -## Contributing -State if you are open to contributions and what your requirements are for accepting them. - -For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. - -You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. - -## Authors and acknowledgment -Show your appreciation to those who have contributed to the project. - -## License -For open source projects, say how it is licensed. - -## Project status -If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. diff --git a/fehy_base_consent/__init__.py b/fehy_base_consent/__init__.py deleted file mode 100644 index 5305644..0000000 --- a/fehy_base_consent/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -*- coding: utf-8 -*- - -from . import models \ No newline at end of file diff --git a/fehy_base_consent/__manifest__.py b/fehy_base_consent/__manifest__.py deleted file mode 100644 index f89e240..0000000 --- a/fehy_base_consent/__manifest__.py +++ /dev/null @@ -1,42 +0,0 @@ -# -*- coding: utf-8 -*- -{ - 'name': "fehu_base_consent", - - 'summary': """ - Печать доверенности на получение ТМЦ - """, - - 'description': """ - Создание списка доверенностей на получение ТМЦ и их печать. - - Создание доверенности: - 1. Меню Покупки - Доверенности - кнопка "Создать"; - 2. На форме указываем: - 2.1. Контрагент - поставщик; - 2.2. Заказ на закупку; - 2.3. Даты действия доверенности ("дата выдачи" и "действительно по"). - - Для печати: - 1. Меню Настройки - Техническое - Отчеты; - 2. Находим в списке fehu_base_consent и добавляем в меню "Печать"; - 3. Открываем созданную запись доверенности - Действие - "Доверенность". - """, - - 'author': "Odoo Community Association (OCA), MK Lab", - 'website': "https://www.inf-centre.ru/", - - 'category': 'Uncategorized', - 'version': '0.1', - - # any module necessary for this one to work correctly - 'depends': ['base','account','sale', 'purchase','hr',], - - # always loaded - 'data': [ - 'security/ir.model.access.csv', - 'views/fehy_base_consent_views.xml', - 'views/hr_employee_views.xml', - 'views/purchase_order_views.xml', - 'report/consent_report.xml', - ], -} diff --git a/fehy_base_consent/models/__init__.py b/fehy_base_consent/models/__init__.py deleted file mode 100644 index 7d037e6..0000000 --- a/fehy_base_consent/models/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# -*- coding: utf-8 -*- - -from . import fehu_base_consent -from . import hr_employee -from . import purchase_order \ No newline at end of file diff --git a/fehy_base_consent/models/fehu_base_consent.py b/fehy_base_consent/models/fehu_base_consent.py deleted file mode 100644 index dec7642..0000000 --- a/fehy_base_consent/models/fehu_base_consent.py +++ /dev/null @@ -1,46 +0,0 @@ -# -*- coding: utf-8 -*- - -from odoo import api, fields, models, _ -from datetime import datetime, timedelta - - -class FehuBaseConsent(models.Model): - _name = 'fehu.base.consent' - _inherit = ['mail.thread', 'utm.mixin'] - _description = 'Consent' - _order = 'date_from desc' - - name = fields.Char(string=_('Номер')) - date_from = fields.Date(string=_('Дата выдачи'), default=lambda self: fields.Datetime.now()) - date_to = fields.Date(string=_('Действительна по'), default=lambda self: datetime.today() + timedelta(days=180)) - partner_id = fields.Many2one('res.partner', string=_('Контрагент'), required=1) - employee_id = fields.Many2one('hr.employee', string=_('Сотрудник'), required=1) - purchaseorder_id = fields.Many2one('purchase.order', _('Заказ на закупку'), domain="[('partner_id','=',partner_id)]", - required=1) - company_id = fields.Many2one('res.company', string=_('Компания'), - default=lambda self: self.env['res.company']._company_default_get('fehu.consent'), - required=1) - - @api.model - def create(self, val): - name = self.env['ir.sequence'].next_by_code('fehu.base.consent') - if name: - if 'name' in val: - if val['name'] == False: - val.update({ - 'name': name, - }) - - result = super(FehuBaseConsent, self).create(val) - return result - - @api.onchange('purchaseorder_id') - def set_partner(self): - if self.purchaseorder_id: - self.partner_id = self.purchaseorder_id.partner_id - - @api.constrains('purchaseorder_id') - def fill_order(self): - p_orders = self.env['purchase.order'].sudo().browse(self.purchaseorder_id.id) - for order in p_orders: - order.consent_id = self.id diff --git a/fehy_base_consent/models/hr_employee.py b/fehy_base_consent/models/hr_employee.py deleted file mode 100644 index 1e63258..0000000 --- a/fehy_base_consent/models/hr_employee.py +++ /dev/null @@ -1,11 +0,0 @@ -# -*- coding: utf-8 -*- - -from odoo import fields, models, _ - - -class HrEmployee(models.Model): - _inherit = 'hr.employee' - - inn = fields.Char(string=_("ИНН")) - pass_kem = fields.Char(string=_("Кем выдан паспорт")) - pass_date = fields.Date(string=_('Дата выдачи паспорта')) diff --git a/fehy_base_consent/models/purchase_order.py b/fehy_base_consent/models/purchase_order.py deleted file mode 100644 index 916aee9..0000000 --- a/fehy_base_consent/models/purchase_order.py +++ /dev/null @@ -1,9 +0,0 @@ -# -*- coding: utf-8 -*- - -from odoo import fields, models, _ - - -class PurchaseOrder(models.Model): - _inherit = 'purchase.order' - - consent_id = fields.Many2one('fehu.base.consent', string=_('Доверенность')) diff --git a/fehy_base_consent/report/consent_report.xml b/fehy_base_consent/report/consent_report.xml deleted file mode 100644 index 45eeb35..0000000 --- a/fehy_base_consent/report/consent_report.xml +++ /dev/null @@ -1,560 +0,0 @@ - - - - - - - Доверенность - fehu.base.consent - (u'Доверенность - %s.pdf' % (object.name)) - qweb-pdf - fehu_base_consent.report_consent - - - - A4 - - A4 - 0 - 0 - Portrait - 15 - 15 - 7 - 7 - - 10 - 90 - - - - - diff --git a/fehy_base_consent/security/ir.model.access.csv b/fehy_base_consent/security/ir.model.access.csv deleted file mode 100644 index d3caa71..0000000 --- a/fehy_base_consent/security/ir.model.access.csv +++ /dev/null @@ -1,2 +0,0 @@ -id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_fehu_base_consent,fehu.base.consent,model_fehu_base_consent,base.group_user,1,1,1,1 diff --git a/fehy_base_consent/views/fehu_base_consent_views.xml b/fehy_base_consent/views/fehu_base_consent_views.xml deleted file mode 100644 index 7fde850..0000000 --- a/fehy_base_consent/views/fehu_base_consent_views.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - Consents - fehu_base_consent - - - - - - - - - - - - - consent.form - fehu.base.consent - -
-
- - - - - - - - - - - - - - - -
- - -
-
-
-
- - - Доверенности - fehu.base.consent - tree,form - - - - - - Consents - fehu.consent - CON - 5 - - - -
-
diff --git a/fehy_base_consent/views/hr_employe_eviews.xml b/fehy_base_consent/views/hr_employe_eviews.xml deleted file mode 100644 index 440c5d4..0000000 --- a/fehy_base_consent/views/hr_employe_eviews.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - view_employee_form.inherit - hr.employee - - - - - - - - - - - - - diff --git a/fehy_base_consent/views/purchase_order_views.xml b/fehy_base_consent/views/purchase_order_views.xml deleted file mode 100644 index 4003990..0000000 --- a/fehy_base_consent/views/purchase_order_views.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - purchase.order.form.inherit - purchase.order - - - - - - - - - diff --git a/l10n_ru_doc/__init__.py b/l10n_ru_doc/__init__.py deleted file mode 100644 index 10a94a5..0000000 --- a/l10n_ru_doc/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# -*- coding: utf-8 -*- - -from . import models -from . import report_helper -from . import report diff --git a/l10n_ru_doc/__manifest__.py b/l10n_ru_doc/__manifest__.py deleted file mode 100644 index 49537f1..0000000 --- a/l10n_ru_doc/__manifest__.py +++ /dev/null @@ -1,51 +0,0 @@ -# -*- coding: utf-8 -*- -{ - 'name': "Russia - Documents", - - 'summary': "Первичные документы", - - 'description': """ -The module for print documents in accordance laws of Russia. -============================================================ -Возможности: - * Товарная накладная (ТОРГ-12) - * Счет на оплату - * Счет-фактура - * Акт выполненных работ - * Вывод подписей и печати - """, - - 'author': "CodUP and MKLab", - 'website': "https://inf-centre.ru", - - 'license': 'AGPL-3', - 'category': 'Localization', - 'version': '17.0.2024.06.28', - - 'depends': ['base','sale','account','sale_stock','uom'], - - 'external_dependencies': {'python' : ['pytils']}, - - 'data': [ - 'views/account_invoice_view.xml', - 'views/res_partner_view.xml', - 'views/res_company_view.xml', - 'views/res_users_view.xml', - 'views/res_bank_view.xml', - 'views/uom.xml', - 'views/tax.xml', - 'views/product.xml', - 'views/l10n_ru_doc_data.xml', - 'report/l10n_ru_doc_report.xml', - 'report/report_order.xml', - 'report/report_invoice.xml', - 'report/report_bill.xml', - 'report/report_act.xml', - 'report/report_upd.xml', - 'report/report_updn.xml', - ], - - 'demo': [ - 'demo/l10n_ru_doc_demo.xml', - ], -} diff --git a/l10n_ru_doc/__pycache__/__init__.cpython-310.pyc b/l10n_ru_doc/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 59706c9..0000000 Binary files a/l10n_ru_doc/__pycache__/__init__.cpython-310.pyc and /dev/null differ diff --git a/l10n_ru_doc/__pycache__/report_helper.cpython-310.pyc b/l10n_ru_doc/__pycache__/report_helper.cpython-310.pyc deleted file mode 100644 index 371ad1e..0000000 Binary files a/l10n_ru_doc/__pycache__/report_helper.cpython-310.pyc and /dev/null differ diff --git a/l10n_ru_doc/demo/l10n_ru_doc_demo.xml b/l10n_ru_doc/demo/l10n_ru_doc_demo.xml deleted file mode 100644 index 16d7d63..0000000 --- a/l10n_ru_doc/demo/l10n_ru_doc_demo.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - ОАО "СБЕРБАНК РОССИИ" - г.Москва - 044525225 - 30101810400000000225 - - - - 40707810600025341231 - - - - - - - iVBORw0KGgoAAAANSUhEUgAAALQAAABACAYAAACzzl09AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2lpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDoxMGE3N2JhNy01MThlLTMwNGEtODcxOC0wMmQ5MWYzYTdiNTUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MjQ2QTI3QjdCQ0JCMTFFMzgwRTQ4NjcwRjlEM0QyMTAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MjQ2QTI3QjZCQ0JCMTFFMzgwRTQ4NjcwRjlEM0QyMTAiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkYzOTcwMjU2QkNCOTExRTM5OEZFRDU5OUQxQUU3MUUzIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkYzOTcwMjU3QkNCOTExRTM5OEZFRDU5OUQxQUU3MUUzIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+LLXcsQAAAjFJREFUeNrs3TFKM0EUB3BXv+QAgqViYWflBQLbWNhZKwE7QQSPkCMIItgJQW+gtjmCBxLZr34zsMPDiCK/X6c7swPxz/B4zJhuGIYN+Cs2fQQINAg0fL9/5S+6o6NUUT28v3dh/s1NnP/5OT7/7i7Ov7qK83d24vjFoht7X/f4GOfv78f5fd/5s9uhQaBBoGGdNXSzRs7W2GWNfH09On+4v4/jF4vcehcXcf5qpdFuhwaBBoEGgQaBRqBBoOHnNPvQ2b7zxtZWnF+e7SieV+uVZzkOD0efV33r8ixH38f5RV/a2Q47NAg0CDQkde4UYocGgQaBhpT6TuF8Hovq7e3w43B7O36nr+9z55dXq9hHXi7j/N3dOL7RN+6Oj8fXn07j+15e9KHt0CDQINDwpRp6WC5TdwDTNXKjxh7m8zB+mr0TOJnE972+xvVPTzXe7dAg0CDQsNYa+rf58DfCDo1Ag0DDL6+hu7Oz2Kc9OIjPi7MeZd+6/H/Q3WyW6vtWZzlms/j86Smuf34e1/+IVXd1tqM4y4EdGgQaBBqS3CnEDg0CDQINOXUf+u0tdyfw5CSeN354iPP39kbHV+snz19X3+FS9tHLO5HFeOzQINAg0PDVGrpZIzdq7OHyMjU+XSO3vufw+XmtdyKxQ4NAg0BDq4aeNCZMfGbYoUGgQaBRQ4+aJvvI1VmO8k5g8bzsW1fvS/aRm3cii/c522GHBoEGgYYkdwqxQ4NAg0BDzn8BBgBlrqW6k1gn5wAAAABJRU5ErkJggg== - codup-test@mail.ru - www.codup.com - 0000000000 - 000000000 - 00000000 - - - - ООО "CodUP" - ул.Земляничная - дом № 13 - 123456 - г.Москва - CodUP - - - 1 - 1 - iVBORw0KGgoAAAANSUhEUgAAAOYAAADmCAMAAAD2tAmJAAAC2VBMVEUWAGH///8WAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGEWAGF7Mdv3AAAA83RSTlMAAAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0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 - - - - Иванов Иван Петрович - codup-test@mail.ru - - - - Иванов Иван Петрович - iVBORw0KGgoAAAANSUhEUgAAAZQAAAETCAMAAAAmrgDyAAAC61BMVEUOF9r///8OF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9oOF9r/ATCgAAAA+HRSTlMAAAECAwQFBgcICQoLDA0ODxAREhQVFhcYGRobHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2Nzg5Ojs8PT4/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaW1xdXl9gYWJj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 - - - - Сидоров Семен Иванович - codup-test@mail.ru - - - - Сидоров Семен Иванович - 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 - - - - diff --git a/l10n_ru_doc/i18n/ru.po b/l10n_ru_doc/i18n/ru.po deleted file mode 100644 index 59d03de..0000000 --- a/l10n_ru_doc/i18n/ru.po +++ /dev/null @@ -1,116 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * l10n_ru_doc -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 13.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-08-19 09:27+0000\n" -"PO-Revision-Date: 2020-08-19 09:27+0000\n" -"Last-Translator: \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: l10n_ru_doc -#: model:ir.actions.report,name:l10n_ru_doc.report_account_invoice_act -msgid "Act" -msgstr "Акт об оказании услуг" - -#. module: l10n_ru_doc -#: model:ir.actions.report,name:l10n_ru_doc.report_account_invoice_bill -msgid "Bill" -msgstr "Товарная накладная (ТОРГ-12)" - -#. module: l10n_ru_doc -#: model:ir.model.fields,help:l10n_ru_doc.field_res_company__print_facsimile -#: model:ir.model.fields,help:l10n_ru_doc.field_res_users__print_facsimile -msgid "Check this for adding Facsimiles of responsible persons to documents." -msgstr "Отметьте, для вставки подписей ответственных лиц в документы." - -#. module: l10n_ru_doc -#: model:ir.model.fields,help:l10n_ru_doc.field_res_company__print_stamp -msgid "Check this for adding Stamp of company to documents." -msgstr "Отметьте, для вставки печати организации в документы." - -#. module: l10n_ru_doc -#: model:ir.model.fields,field_description:l10n_ru_doc.field_res_company__chief_id -msgid "Chief" -msgstr "Руководитель организации" - -#. module: l10n_ru_doc -#: model:ir.model.fields,field_description:l10n_ru_doc.field_account_setup_bank_manual_config__bank_corr_acc -#: model:ir.model.fields,field_description:l10n_ru_doc.field_res_bank__corr_acc -#: model:ir.model.fields,field_description:l10n_ru_doc.field_res_partner_bank__bank_corr_acc -msgid "Corresponding account" -msgstr "Корр. счет" - -#. module: l10n_ru_doc -#: model_terms:ir.ui.view,arch_db:l10n_ru_doc.view_company_ru_form -msgid "Documents" -msgstr "Документы" - -#. module: l10n_ru_doc -#: model:ir.model.fields,field_description:l10n_ru_doc.field_res_users__facsimile -msgid "Facsimile" -msgstr "Подпись" - -#. module: l10n_ru_doc -#: model:ir.model.fields,field_description:l10n_ru_doc.field_res_company__inn -#: model:ir.model.fields,field_description:l10n_ru_doc.field_res_partner__inn -#: model:ir.model.fields,field_description:l10n_ru_doc.field_res_users__inn -msgid "INN" -msgstr "ИНН" - -#. module: l10n_ru_doc -#: model:ir.model.fields,field_description:l10n_ru_doc.field_res_company__kpp -#: model:ir.model.fields,field_description:l10n_ru_doc.field_res_partner__kpp -#: model:ir.model.fields,field_description:l10n_ru_doc.field_res_users__kpp -msgid "KPP" -msgstr "КПП" - -#. module: l10n_ru_doc -#: model:ir.model.fields,field_description:l10n_ru_doc.field_res_company__okpo -#: model:ir.model.fields,field_description:l10n_ru_doc.field_res_partner__okpo -#: model:ir.model.fields,field_description:l10n_ru_doc.field_res_users__okpo -msgid "OKPO" -msgstr "ОКПО" - -#. module: l10n_ru_doc -#: model:ir.model.fields,field_description:l10n_ru_doc.field_res_company__print_anywhere -msgid "Print Anywhere" -msgstr "Документы" - -#. module: l10n_ru_doc -#: model:ir.model.fields,field_description:l10n_ru_doc.field_res_company__print_facsimile -#: model:ir.model.fields,field_description:l10n_ru_doc.field_res_users__print_facsimile -msgid "Print Facsimile" -msgstr "Выводить подписи" - -#. module: l10n_ru_doc -#: model:ir.model.fields,field_description:l10n_ru_doc.field_res_company__print_stamp -msgid "Print Stamp" -msgstr "Выводить печать" - -#. module: l10n_ru_doc -#: model_terms:ir.ui.view,arch_db:l10n_ru_doc.view_company_ru_form -msgid "Responsible Persons" -msgstr "Ответственные лица" - -#. module: l10n_ru_doc -#: model:ir.model.fields,field_description:l10n_ru_doc.field_res_company__stamp -msgid "Stamp" -msgstr "Печать" - -#. module: l10n_ru_doc -#: model:ir.model.fields,help:l10n_ru_doc.field_res_company__print_anywhere -msgid "Uncheck this, if you want add Facsimile and Stamp only in email." -msgstr "Снимите отметку, если хотите добавлять подписи и печать только в email." - -#. module: l10n_ru_doc -#: model:ir.actions.report,name:l10n_ru_doc.report_account_invoice_upd -msgid "Upd" -msgstr "Универсальный платежный документ (УПД)" diff --git a/l10n_ru_doc/models/__init__.py b/l10n_ru_doc/models/__init__.py deleted file mode 100644 index d378530..0000000 --- a/l10n_ru_doc/models/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -# -*- coding: utf-8 -*- - -from . import res_partner -from . import res_company -from . import res_users -from . import res_bank -from . import account_invoice -from . import account_move_line -from . import sale -from . import uom -from . import tax -from . import product diff --git a/l10n_ru_doc/models/__pycache__/__init__.cpython-310.pyc b/l10n_ru_doc/models/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 3d51288..0000000 Binary files a/l10n_ru_doc/models/__pycache__/__init__.cpython-310.pyc and /dev/null differ diff --git a/l10n_ru_doc/models/__pycache__/account_invoice.cpython-310.pyc b/l10n_ru_doc/models/__pycache__/account_invoice.cpython-310.pyc deleted file mode 100644 index 9900076..0000000 Binary files a/l10n_ru_doc/models/__pycache__/account_invoice.cpython-310.pyc and /dev/null differ diff --git a/l10n_ru_doc/models/__pycache__/account_move_line.cpython-310.pyc b/l10n_ru_doc/models/__pycache__/account_move_line.cpython-310.pyc deleted file mode 100644 index 2bdf1b4..0000000 Binary files a/l10n_ru_doc/models/__pycache__/account_move_line.cpython-310.pyc and /dev/null differ diff --git a/l10n_ru_doc/models/__pycache__/product.cpython-310.pyc b/l10n_ru_doc/models/__pycache__/product.cpython-310.pyc deleted file mode 100644 index 2e4d98f..0000000 Binary files a/l10n_ru_doc/models/__pycache__/product.cpython-310.pyc and /dev/null differ diff --git a/l10n_ru_doc/models/__pycache__/res_bank.cpython-310.pyc b/l10n_ru_doc/models/__pycache__/res_bank.cpython-310.pyc deleted file mode 100644 index d73d6d5..0000000 Binary files a/l10n_ru_doc/models/__pycache__/res_bank.cpython-310.pyc and /dev/null differ diff --git a/l10n_ru_doc/models/__pycache__/res_company.cpython-310.pyc b/l10n_ru_doc/models/__pycache__/res_company.cpython-310.pyc deleted file mode 100644 index aaaff18..0000000 Binary files a/l10n_ru_doc/models/__pycache__/res_company.cpython-310.pyc and /dev/null differ diff --git a/l10n_ru_doc/models/__pycache__/res_partner.cpython-310.pyc b/l10n_ru_doc/models/__pycache__/res_partner.cpython-310.pyc deleted file mode 100644 index ed7504e..0000000 Binary files a/l10n_ru_doc/models/__pycache__/res_partner.cpython-310.pyc and /dev/null differ diff --git a/l10n_ru_doc/models/__pycache__/res_users.cpython-310.pyc b/l10n_ru_doc/models/__pycache__/res_users.cpython-310.pyc deleted file mode 100644 index b0c10a5..0000000 Binary files a/l10n_ru_doc/models/__pycache__/res_users.cpython-310.pyc and /dev/null differ diff --git a/l10n_ru_doc/models/__pycache__/sale.cpython-310.pyc b/l10n_ru_doc/models/__pycache__/sale.cpython-310.pyc deleted file mode 100644 index 94725f8..0000000 Binary files a/l10n_ru_doc/models/__pycache__/sale.cpython-310.pyc and /dev/null differ diff --git a/l10n_ru_doc/models/__pycache__/tax.cpython-310.pyc b/l10n_ru_doc/models/__pycache__/tax.cpython-310.pyc deleted file mode 100644 index c251382..0000000 Binary files a/l10n_ru_doc/models/__pycache__/tax.cpython-310.pyc and /dev/null differ diff --git a/l10n_ru_doc/models/__pycache__/uom.cpython-310.pyc b/l10n_ru_doc/models/__pycache__/uom.cpython-310.pyc deleted file mode 100644 index 3399650..0000000 Binary files a/l10n_ru_doc/models/__pycache__/uom.cpython-310.pyc and /dev/null differ diff --git a/l10n_ru_doc/models/account_invoice.py b/l10n_ru_doc/models/account_invoice.py deleted file mode 100644 index bf5c88a..0000000 --- a/l10n_ru_doc/models/account_invoice.py +++ /dev/null @@ -1,144 +0,0 @@ -from datetime import datetime -from odoo import api, fields, models - -class AccountInvoice(models.Model): - _inherit = 'account.move' - kladov=fields.Many2one('res.users', string='Ответственный за передачу товаров/услуг') - gruzopol=fields.Many2one('res.partner', string='Грузополучатель') - gruzootpr=fields.Many2one('res.partner', string='Грузоотправитель') - transport=fields.Char('Данные о транспортировке и грузе') - osnovanie=fields.Char('Основание') - payment_text=fields.Char('Текст для платежек в УПД', compute='_compute_get_txtpayment') - payment_num=fields.Char('Номер платежки в УПД', compute='_compute_get_txtpayment') - payment_date = fields.Char('Дата платежки в УПД', compute='_compute_get_txtpayment') - only_service = fields.Boolean('Только услуги', compute='_compute_get_check_service') - - @api.depends('invoice_line_ids') - def _compute_get_check_service(self): - for s in self: - s.only_service = all((line.product_id.type=='service') for line in s.invoice_line_ids) - - def _compute_get_txtpayment(self): - for s in self: - payments = s._get_reconciled_payments() - payment_text = '' - - for payment in payments: - if payment.date: - payment_text += payment.name + ' от ' + \ - fields.Datetime.from_string(payment.date).strftime("%d.%m.%Y") - if payments[-1]!=payment: - payment_text += ', ' - if payments: - s.payment_num = payments[0].name - s.payment_date = fields.Datetime.from_string(payments[0].date).strftime("%d.%m.%Y") - else: - s.payment_num = '' - s.payment_text = '' - s.payment_date = '' - - s.payment_text = payment_text - - def action_bill_sent(self): - assert len(self) == 1, 'This option should only be used for a single id at a time.' - template = self.env.ref('account.email_template_edi_invoice', False) - compose_form = self.env.ref('mail.email_compose_message_wizard_form', False) - ctx = { - 'default_model': 'account.move', - 'default_res_id': self.id, - 'default_use_template': bool(template), - 'default_template_id': template.id, - 'default_composition_mode': 'comment', - 'mark_invoice_as_sent': True, - } - return { - 'name': 'Compose Email', - 'type': 'ir.actions.act_window', - 'view_type': 'form', - 'view_mode': 'form', - 'res_model': 'mail.compose.message', - 'views': [(compose_form.id, 'form')], - 'view_id': compose_form.id, - 'target': 'new', - 'context': ctx, - } - - def bill_print(self): - assert len(self) == 1, 'This option should only be used for a single id at a time.' - return self.env['report'].get_action(self, 'l10n_ru_doc.report_upd') - - def get_delivery_doc_name(self): - for s in self: - pickings = [] - pickings_list = '0' - orders = self.env['sale.order'].sudo().search([('name','=',s.invoice_origin)]) - for o in orders: - if o.picking_ids: - for p in o.picking_ids: - pickings.append(p.name) - if len(pickings)>0: - pickings_list = ';'.join(pickings) - if pickings_list != '0': - return pickings_list - if s.name.find('/') > -1: - return 'УПД № ' + s.name[len(s.name) - 4:] - return 'УПД № ' + s.name - - def get_delivery_doc_date(self): - for s in self: - pickings = [] - pickings_list = '0' - orders = self.env['sale.order'].sudo().search([('name','=',s.invoice_origin)]) - for o in orders: - if o.picking_ids: - for p in o.picking_ids: - pickings.append(datetime.strftime(p.date, '%d.%m.%Y')) - if len(pickings)>0: - pickings_list = ';'.join(pickings) - if pickings_list != '0': - return pickings_list - return datetime.strftime(s.date, '%d.%m.%Y') - - def get_function_partner(self, partner=False, type='director'): - if partner: - if partner.parent_id: - partner = partner.parent_id - director = self.env['res.partner'].search([('parent_id', '=', partner.id), - ('type', '=', type)], limit=1) - if director: - if director.function: - return director.function - return '' - - def get_name_partner(self, partner=False, type='director'): - if partner: - if partner.parent_id: - partner = partner.parent_id - director = self.env['res.partner'].search([('parent_id', '=', partner.id), - ('type', '=', type)], limit=1) - if director: - if director.name: - return director.name - return '' - - def get_facsimile_partner(self, partner=False, type='director'): - if partner: - if partner.parent_id: - partner = partner.parent_id - director = self.env['res.partner'].search([('parent_id', '=', partner.id), - ('type', '=', type)], - limit=1) - if director: - if director.facsimile: - return director.facsimile - return '' - - def get_stamp_partner(self, partner=False): - if partner: - if partner.parent_id: - partner = partner.parent_id - if partner.stamp: - return partner.stamp - return False - - diff --git a/l10n_ru_doc/models/account_move_line.py b/l10n_ru_doc/models/account_move_line.py deleted file mode 100644 index 06e0f5e..0000000 --- a/l10n_ru_doc/models/account_move_line.py +++ /dev/null @@ -1,29 +0,0 @@ -from datetime import datetime -from odoo import api, fields, models - -class AccountMoveLine(models.Model): - _inherit = 'account.move.line' - - price_total_pf = fields.Monetary( - string='TotalPF', - compute='_compute_totals', - currency_field='currency_id', - ) - - @api.depends('quantity', 'discount', 'price_unit', 'tax_ids', 'currency_id') - def _compute_totals(self): - super(AccountMoveLine,self)._compute_totals() - for line in self: - line_discount_price_unit = line.price_unit * (1 - (line.discount / 100.0)) - if line.tax_ids.filtered(lambda tax: tax.invisiblePF == False): - taxes_res = line.tax_ids.filtered(lambda tax: tax.invisiblePF == False).compute_all( - line_discount_price_unit, - quantity=line.quantity, - currency=line.currency_id, - product=line.product_id, - partner=line.partner_id, - is_refund=line.is_refund, - ) - line.price_total_pf = taxes_res['total_included'] - else: - line.price_total_pf = line.price_total \ No newline at end of file diff --git a/l10n_ru_doc/models/product.py b/l10n_ru_doc/models/product.py deleted file mode 100644 index c230841..0000000 --- a/l10n_ru_doc/models/product.py +++ /dev/null @@ -1,5 +0,0 @@ -from odoo import fields, models - -class ProductTnved(models.Model): - _inherit = 'product.product' - kod_tnved = fields.Char('Код ТНВЭД') diff --git a/l10n_ru_doc/models/res_bank.py b/l10n_ru_doc/models/res_bank.py deleted file mode 100644 index f22d430..0000000 --- a/l10n_ru_doc/models/res_bank.py +++ /dev/null @@ -1,19 +0,0 @@ -from odoo import api, fields, models - -class Bank(models.Model): - _inherit = 'res.bank' - - corr_acc = fields.Char('Corresponding account', size=64) - - -class ResPartnerBank(models.Model): - _inherit = 'res.partner.bank' - - bank_corr_acc = fields.Char('Corresponding account', size=64) - - @api.onchange('bank_id') - def onchange_bank_id(self): - for s in self: - s.bank_name = s.bank_id.name - s.bank_bic = s.bank_id.bic - s.bank_corr_acc = s.bank_id.corr_acc diff --git a/l10n_ru_doc/models/res_company.py b/l10n_ru_doc/models/res_company.py deleted file mode 100644 index 9ca4ae7..0000000 --- a/l10n_ru_doc/models/res_company.py +++ /dev/null @@ -1,18 +0,0 @@ -from odoo import fields, models - -class Company(models.Model): - _inherit = 'res.company' - - inn = fields.Char(related='partner_id.inn', readonly=False) - kpp = fields.Char(related='partner_id.kpp', readonly=False) - okpo = fields.Char(related='partner_id.okpo', readonly=False) - chief_id = fields.Many2one('res.users', 'Chief') - accountant_id = fields.Many2one('res.users', 'General Accountant') - print_facsimile = fields.Boolean(string='Print Facsimile', - help="Check this for adding Facsimiles of responsible persons to documents.") - print_stamp = fields.Boolean(string='Print Stamp', - help="Check this for adding Stamp of company to documents.") - stamp = fields.Binary("Stamp") - print_anywhere = fields.Boolean(string='Print Anywhere', - help="Uncheck this, if you want add Facsimile and Stamp only in email.", - default=True) diff --git a/l10n_ru_doc/models/res_partner.py b/l10n_ru_doc/models/res_partner.py deleted file mode 100644 index e918a39..0000000 --- a/l10n_ru_doc/models/res_partner.py +++ /dev/null @@ -1,11 +0,0 @@ -from odoo import fields, models -class ResPartner(models.Model): - _inherit = 'res.partner' - - inn = fields.Char('INN', related='vat') - kpp = fields.Char('KPP', size=9) - okpo = fields.Char('OKPO', size=14) - ogrn = fields.Char('ОГРН') - type = fields.Selection(selection_add=[('director', 'Директор'), ('accountant', 'Бухгалтер')]) - facsimile = fields.Binary("Подпись") - stamp = fields.Binary("Печать") diff --git a/l10n_ru_doc/models/res_users.py b/l10n_ru_doc/models/res_users.py deleted file mode 100644 index aaf70cb..0000000 --- a/l10n_ru_doc/models/res_users.py +++ /dev/null @@ -1,7 +0,0 @@ -from odoo import fields, models - -class Users(models.Model): - _inherit = 'res.users' - - print_facsimile = fields.Boolean(related='company_id.print_facsimile') - facsimile = fields.Binary() diff --git a/l10n_ru_doc/models/sale.py b/l10n_ru_doc/models/sale.py deleted file mode 100644 index 54707e2..0000000 --- a/l10n_ru_doc/models/sale.py +++ /dev/null @@ -1,8 +0,0 @@ -from odoo import models - -class SaleOrder(models.Model): - _inherit = 'sale.order' - def print_quotation(self): - self.filtered(lambda s: s.state == 'draft').write({'state': 'sent'}) - return self.env['report'].get_action(self, 'l10n_ru_doc.report_order') - diff --git a/l10n_ru_doc/models/tax.py b/l10n_ru_doc/models/tax.py deleted file mode 100644 index 081adb1..0000000 --- a/l10n_ru_doc/models/tax.py +++ /dev/null @@ -1,6 +0,0 @@ -from odoo import fields, models - -class TaxInherit(models.Model): - _inherit = 'account.tax' - - invisiblePF = fields.Boolean('Не видно в ПФ') diff --git a/l10n_ru_doc/models/uom.py b/l10n_ru_doc/models/uom.py deleted file mode 100644 index 1de1e3b..0000000 --- a/l10n_ru_doc/models/uom.py +++ /dev/null @@ -1,4 +0,0 @@ -from odoo import fields, models -class UomInherit(models.Model): - _inherit = 'uom.uom' - kod = fields.Char('Код единицы измерения') diff --git a/l10n_ru_doc/report/__init__.py b/l10n_ru_doc/report/__init__.py deleted file mode 100644 index b058f02..0000000 --- a/l10n_ru_doc/report/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from . import report_order -from . import report_invoice -from . import report_bill -from . import report_act -from . import report_upd diff --git a/l10n_ru_doc/report/__pycache__/__init__.cpython-310.pyc b/l10n_ru_doc/report/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index af59652..0000000 Binary files a/l10n_ru_doc/report/__pycache__/__init__.cpython-310.pyc and /dev/null differ diff --git a/l10n_ru_doc/report/__pycache__/report_act.cpython-310.pyc b/l10n_ru_doc/report/__pycache__/report_act.cpython-310.pyc deleted file mode 100644 index e8bc325..0000000 Binary files a/l10n_ru_doc/report/__pycache__/report_act.cpython-310.pyc and /dev/null differ diff --git a/l10n_ru_doc/report/__pycache__/report_bill.cpython-310.pyc b/l10n_ru_doc/report/__pycache__/report_bill.cpython-310.pyc deleted file mode 100644 index dd10562..0000000 Binary files a/l10n_ru_doc/report/__pycache__/report_bill.cpython-310.pyc and /dev/null differ diff --git a/l10n_ru_doc/report/__pycache__/report_invoice.cpython-310.pyc b/l10n_ru_doc/report/__pycache__/report_invoice.cpython-310.pyc deleted file mode 100644 index 7818d1a..0000000 Binary files a/l10n_ru_doc/report/__pycache__/report_invoice.cpython-310.pyc and /dev/null differ diff --git a/l10n_ru_doc/report/__pycache__/report_order.cpython-310.pyc b/l10n_ru_doc/report/__pycache__/report_order.cpython-310.pyc deleted file mode 100644 index ab3e710..0000000 Binary files a/l10n_ru_doc/report/__pycache__/report_order.cpython-310.pyc and /dev/null differ diff --git a/l10n_ru_doc/report/__pycache__/report_upd.cpython-310.pyc b/l10n_ru_doc/report/__pycache__/report_upd.cpython-310.pyc deleted file mode 100644 index 619c778..0000000 Binary files a/l10n_ru_doc/report/__pycache__/report_upd.cpython-310.pyc and /dev/null differ diff --git a/l10n_ru_doc/report/l10n_ru_doc_report.xml b/l10n_ru_doc/report/l10n_ru_doc_report.xml deleted file mode 100644 index 328441b..0000000 --- a/l10n_ru_doc/report/l10n_ru_doc_report.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - - A4 - - A4 - 0 - 0 - Portrait - 7 - 7 - 7 - 7 - - 35 - 75 - - - A4 Landscape - - A4 - 0 - 0 - Landscape - 7 - 7 - 7 - 7 - - 75 - 60 - - - - Счет по форме 1С - sale.order - qweb-pdf - l10n_ru_doc.report_order - l10n_ru_doc.report_order - 'Счет - %s ' % (object.name+' '+(object.partner_id.parent_id.name if object.partner_id.parent_id else object.partner_id.name)) - - - report - - - - Счет-фактура - account.move - qweb-pdf - l10n_ru_doc.report_invoice - l10n_ru_doc.report_invoice - 'Счет-фактура - %s ' % (object.name+' '+(object.partner_id.parent_id.name if object.partner_id.parent_id else object.partner_id.name)) - - - report - - - - Товарная накладная (ТОРГ-12) - account.move - qweb-pdf - l10n_ru_doc.report_bill - l10n_ru_doc.report_bill - 'Товарная накладная - %s ' % (object.name+' '+(object.partner_id.parent_id.name if object.partner_id.parent_id else object.partner_id.name)) - - - report - - - - Акт выполненных работ - account.move - qweb-pdf - l10n_ru_doc.report_act - l10n_ru_doc.report_act - 'Акт - %s ' % (object.name+' '+(object.partner_id.parent_id.name if object.partner_id.parent_id else object.partner_id.name)) - - - report - - - - Универсальный передаточный документ(УПД) - account.move - qweb-pdf - l10n_ru_doc.report_upd - l10n_ru_doc.report_upd - 'УПД' - - - report - - - - УПД без печатей - account.move - qweb-pdf - l10n_ru_doc.report_updn - l10n_ru_doc.report_updn - 'УПД без печатей' - - - report - - - diff --git a/l10n_ru_doc/report/report_act.py b/l10n_ru_doc/report/report_act.py deleted file mode 100644 index 133336e..0000000 --- a/l10n_ru_doc/report/report_act.py +++ /dev/null @@ -1,16 +0,0 @@ -# -*- coding: utf-8 -*- - -from odoo import models -from odoo.addons.l10n_ru_doc.report_helper import QWebHelper - -class RuActReport(models.AbstractModel): - _name = 'report.l10n_ru_doc.report_act' - - def _get_report_values(self, docids, data=None): - docs = self.env['account.move'].browse(docids) - return { - 'helper': QWebHelper(), - 'doc_ids': docs.ids, - 'doc_model': 'account.move', - 'docs': docs - } diff --git a/l10n_ru_doc/report/report_act.xml b/l10n_ru_doc/report/report_act.xml deleted file mode 100644 index 4af4ce3..0000000 --- a/l10n_ru_doc/report/report_act.xml +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - diff --git a/l10n_ru_doc/report/report_bill.py b/l10n_ru_doc/report/report_bill.py deleted file mode 100644 index 400d3ad..0000000 --- a/l10n_ru_doc/report/report_bill.py +++ /dev/null @@ -1,14 +0,0 @@ -from odoo import models -from odoo.addons.l10n_ru_doc.report_helper import QWebHelper - -class RuBillReport(models.AbstractModel): - _name = 'report.l10n_ru_doc.report_bill' - - def _get_report_values(self, docids, data=None): - docs = self.env['account.move'].browse(docids) - return { - 'helper': QWebHelper(), - 'doc_ids': docs.ids, - 'doc_model': 'account.move', - 'docs': docs - } diff --git a/l10n_ru_doc/report/report_bill.xml b/l10n_ru_doc/report/report_bill.xml deleted file mode 100644 index c7f5568..0000000 --- a/l10n_ru_doc/report/report_bill.xml +++ /dev/null @@ -1,758 +0,0 @@ - - - - - - diff --git a/l10n_ru_doc/report/report_invoice.py b/l10n_ru_doc/report/report_invoice.py deleted file mode 100644 index a71c09a..0000000 --- a/l10n_ru_doc/report/report_invoice.py +++ /dev/null @@ -1,13 +0,0 @@ -# -*- coding: utf-8 -*- -from odoo import models -from odoo.addons.l10n_ru_doc.report_helper import QWebHelper -class RuInvoiceReport(models.AbstractModel): - _name = 'report.l10n_ru_doc.report_invoice' - def _get_report_values(self, docids, data=None): - docs = self.env['account.move'].browse(docids) - return { - 'helper': QWebHelper(), - 'doc_ids': docs.ids, - 'doc_model': 'account.move', - 'docs': docs - } diff --git a/l10n_ru_doc/report/report_invoice.xml b/l10n_ru_doc/report/report_invoice.xml deleted file mode 100644 index 78b8b21..0000000 --- a/l10n_ru_doc/report/report_invoice.xml +++ /dev/null @@ -1,329 +0,0 @@ - - - - - - diff --git a/l10n_ru_doc/report/report_order.py b/l10n_ru_doc/report/report_order.py deleted file mode 100644 index eb94aca..0000000 --- a/l10n_ru_doc/report/report_order.py +++ /dev/null @@ -1,13 +0,0 @@ -# -*- coding: utf-8 -*- -from odoo import models -from odoo.addons.l10n_ru_doc.report_helper import QWebHelper -class RuSaleOrderReport(models.AbstractModel): - _name = 'report.l10n_ru_doc.report_order' - def _get_report_values(self, docids, data=None): - docs = self.env['sale.order'].browse(docids) - return { - 'helper': QWebHelper(), - 'doc_ids': docs.ids, - 'doc_model': 'sale.order', - 'docs': docs - } diff --git a/l10n_ru_doc/report/report_order.xml b/l10n_ru_doc/report/report_order.xml deleted file mode 100644 index f9d2127..0000000 --- a/l10n_ru_doc/report/report_order.xml +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - diff --git a/l10n_ru_doc/report/report_upd.py b/l10n_ru_doc/report/report_upd.py deleted file mode 100644 index 1537ba8..0000000 --- a/l10n_ru_doc/report/report_upd.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -from odoo import models -from odoo.addons.l10n_ru_doc.report_helper import QWebHelper - -class RuUpdReport(models.AbstractModel): - _name = 'report.l10n_ru_doc.report_upd' - def _get_report_values(self, docids, data=None): - docs = self.env['account.move'].browse(docids) - return { - 'helper': QWebHelper(), - 'doc_ids': docs.ids, - 'doc_model': 'account.move', - 'docs': docs - } -class RuUpdReportn(models.AbstractModel): - _name = 'report.l10n_ru_doc.report_updn' - def _get_report_values(self, docids, data=None): - docs = self.env['account.move'].browse(docids) - return { - 'helper': QWebHelper(), - 'doc_ids': docs.ids, - 'doc_model': 'account.move', - 'docs': docs - } diff --git a/l10n_ru_doc/report/report_upd.xml b/l10n_ru_doc/report/report_upd.xml deleted file mode 100644 index 1825c87..0000000 --- a/l10n_ru_doc/report/report_upd.xml +++ /dev/null @@ -1,1108 +0,0 @@ - - - - - - diff --git a/l10n_ru_doc/report/report_updn.xml b/l10n_ru_doc/report/report_updn.xml deleted file mode 100644 index b3013c4..0000000 --- a/l10n_ru_doc/report/report_updn.xml +++ /dev/null @@ -1,1177 +0,0 @@ - - - - - - diff --git a/l10n_ru_doc/report_helper.py b/l10n_ru_doc/report_helper.py deleted file mode 100644 index 4ae4803..0000000 --- a/l10n_ru_doc/report_helper.py +++ /dev/null @@ -1,112 +0,0 @@ -from datetime import datetime -import re -from pytils import numeral, dt -from odoo.tools import pycompat - - -class QWebHelper(object): - - def img(self, img, type='png', width=0, height=0) : - if width : - width = "width='%spx'"%(width) - else : - width = " " - if height : - height = "height='%spx'"%(height) - else : - height = " " - toreturn = ""%( - width, - height, - type, - str(pycompat.to_text(img))) - return toreturn - - def numer(self, name): - if name: - numeration = re.findall(r'\d+$', name) - if numeration: - return numeration[0] - return '' - - def ru_date(self, date): - if date and date != 'False': - return dt.ru_strftime('"%d" %B %Y года', date=datetime.strptime(str(date), - "%Y-%m-%d"), inflected=True) - return '' - - def ru_date2(self, date): - if date and date != 'False': - return dt.ru_strftime('%d %B %Y г.', date=datetime.strptime(str(date), - "%Y-%m-%d %H:%M:%S"), inflected=True) - return '' - - def in_words(self, number): - return numeral.in_words(number) - - def rubles(self, sum): - text_rubles = numeral.rubles(int(sum)) - copeck = round((sum - int(sum))*100) - text_copeck = numeral.choose_plural(int(copeck), ("копейка", "копейки", "копеек")) - return ("%s %02d %s")%(text_rubles, copeck, text_copeck) - - def initials(self, fio): - if fio: - return (fio.split()[0]+' '+''.join([fio[0:1]+'.' for fio in fio.split()[1:]])).strip() - return '' - - def address(self, partner): - repr = [] - if partner.zip: - repr.append(partner.zip) - if partner.country_id: - repr.append(partner.country_id.name) - if partner.state_id: - repr.append(partner.state_id.name) - if partner.city: - repr.append(partner.city) - if partner.street: - repr.append(partner.street) - if partner.street2: - repr.append(partner.street2) - return ', '.join(repr) - - def representation(self, partner): - repr = [] - if partner.name: - repr.append(partner.name) - if partner.inn: - repr.append("ИНН " + partner.inn) - if partner.kpp: - repr.append("КПП " + partner.kpp) - repr.append(self.address(partner)) - return ', '.join(repr) - - def full_representation(self, partner): - repr = [self.representation(partner)] - if partner.phone: - repr.append("тел.: " + partner.phone) - elif partner.parent_id.phone: - repr.append("тел.: " + partner.parent_id.phone) - bank = None - if partner.bank_ids: - bank = partner.bank_ids[0] - elif partner.parent_id.bank_ids: - bank = partner.parent_id.bank_ids[0] - if bank and bank.acc_number: - repr.append("р/сч " + bank.acc_number) - if bank and bank.bank_name: - repr.append("в банке " + bank.bank_name) - if bank and bank.banvk_bic: - repr.append("БИК " + bank.bank_bic) - if bank and bank.bank_corr_acc: - repr.append("к/с " + bank.bank_corr_acc) - return ', '.join(repr) - - def representation_small(self, partner): - repr = [] - if partner.name: - repr.append(partner.name) - - repr.append(self.address(partner)) - return ', '.join(repr) diff --git a/l10n_ru_doc/static/description/docs.png b/l10n_ru_doc/static/description/docs.png deleted file mode 100644 index 7cc91a8..0000000 Binary files a/l10n_ru_doc/static/description/docs.png and /dev/null differ diff --git a/l10n_ru_doc/static/description/icon.png b/l10n_ru_doc/static/description/icon.png deleted file mode 100644 index 5b3a94e..0000000 Binary files a/l10n_ru_doc/static/description/icon.png and /dev/null differ diff --git a/l10n_ru_doc/static/description/index.html b/l10n_ru_doc/static/description/index.html deleted file mode 100644 index d4c9e96..0000000 --- a/l10n_ru_doc/static/description/index.html +++ /dev/null @@ -1,45 +0,0 @@ -
-
-

Первичные документы РФ

-
-

-Модуль для печати первичных документов в соответствии с законами РФ. -

-

-Возможности: -

    -
  • Товарная накладная (ТОРГ-12)
  • -
  • Счет на оплату
  • -
  • Счет-фактура
  • -
  • Акт выполненных работ
  • -
  • Вывод подписей и печати
  • -
-

-
-
-
- -
-
-
-
- -
-
-

Помощь и поддержка

-
-
- -
-
- -
-
\ No newline at end of file diff --git a/l10n_ru_doc/static/description/support.png b/l10n_ru_doc/static/description/support.png deleted file mode 100644 index 2805ec7..0000000 Binary files a/l10n_ru_doc/static/description/support.png and /dev/null differ diff --git a/l10n_ru_doc/static/description/waybill.png b/l10n_ru_doc/static/description/waybill.png deleted file mode 100644 index 8bab618..0000000 Binary files a/l10n_ru_doc/static/description/waybill.png and /dev/null differ diff --git a/l10n_ru_doc/static/src/css/l10n_ru_doc.css b/l10n_ru_doc/static/src/css/l10n_ru_doc.css deleted file mode 100644 index d77b69a..0000000 --- a/l10n_ru_doc/static/src/css/l10n_ru_doc.css +++ /dev/null @@ -1,7 +0,0 @@ -@charset "utf-8"; -.openerp .codup_sign > img { - width: 235px; - height: 65px; - max-width: 235px; - max-height: 65px; -} \ No newline at end of file diff --git a/l10n_ru_doc/views/account_invoice_view.xml b/l10n_ru_doc/views/account_invoice_view.xml deleted file mode 100644 index 1d701fa..0000000 --- a/l10n_ru_doc/views/account_invoice_view.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - account.invoice.ru.form - account.move - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/l10n_ru_doc/views/l10n_ru_doc_data.xml b/l10n_ru_doc/views/l10n_ru_doc_data.xml deleted file mode 100644 index 169bcd7..0000000 --- a/l10n_ru_doc/views/l10n_ru_doc_data.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - 1 - - - - - - - diff --git a/l10n_ru_doc/views/product.xml b/l10n_ru_doc/views/product.xml deleted file mode 100644 index 7fea41d..0000000 --- a/l10n_ru_doc/views/product.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - tnved_product - product.product - - - - - - - - - - diff --git a/l10n_ru_doc/views/res_bank_view.xml b/l10n_ru_doc/views/res_bank_view.xml deleted file mode 100644 index 7468aac..0000000 --- a/l10n_ru_doc/views/res_bank_view.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - res.bank.ru.form - res.bank - form - - - - - - - - - - diff --git a/l10n_ru_doc/views/res_company_view.xml b/l10n_ru_doc/views/res_company_view.xml deleted file mode 100644 index 6342ad2..0000000 --- a/l10n_ru_doc/views/res_company_view.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - res.companyruform - res.company - - - - - - - - - - ИНН - - - ОГРН - - - - - - - - - - - - - - - - - - - - - - diff --git a/l10n_ru_doc/views/res_partner_view.xml b/l10n_ru_doc/views/res_partner_view.xml deleted file mode 100644 index 016701b..0000000 --- a/l10n_ru_doc/views/res_partner_view.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - res.partner.ru.form - res.partner - - - - - - - - - - ИНН - - - - - - - - - - - - - - - - - - - diff --git a/l10n_ru_doc/views/res_users_view.xml b/l10n_ru_doc/views/res_users_view.xml deleted file mode 100644 index e7ae0cf..0000000 --- a/l10n_ru_doc/views/res_users_view.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - res.users.signature.form - res.users - - - - - - - - - - - - res.users.simple.form - res.users - - - - - - - - - - - - - diff --git a/l10n_ru_doc/views/tax.xml b/l10n_ru_doc/views/tax.xml deleted file mode 100644 index 3cefac6..0000000 --- a/l10n_ru_doc/views/tax.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - view_taxiher_form - account.tax - - - - - - - - - - - diff --git a/l10n_ru_doc/views/uom.xml b/l10n_ru_doc/views/uom.xml deleted file mode 100644 index 08e8b0c..0000000 --- a/l10n_ru_doc/views/uom.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - view_uomiher_form - uom.uom - - - - - - - - - - view_uomiher_tree - uom.category - - - - - - - - - - - diff --git a/upd_xml/__init__.py b/upd_xml/__init__.py deleted file mode 100644 index 5a79dbb..0000000 --- a/upd_xml/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# -*- coding: utf-8 -*- - -from . import controllers -from . import models -from . import reports diff --git a/upd_xml/__manifest__.py b/upd_xml/__manifest__.py deleted file mode 100644 index 4cb612d..0000000 --- a/upd_xml/__manifest__.py +++ /dev/null @@ -1,51 +0,0 @@ -# -*- coding: utf-8 -*- -{ - 'name': "Печать УПД в xml формате", - - 'summary': "Формирует УПД в формате XML, формат 5.01", - - 'description': """ -Формирует УПД в формате XML, формат 5.01 - """, - - 'author': "MKLab", - 'website': "https://inf-centre.ru", - - # Categories can be used to filter modules in modules listing - # Check https://github.com/odoo/odoo/blob/15.0/odoo/addons/base/data/ir_module_category_data.xml - # for the full list - 'category': 'Localization', - 'version': '17.0.1.230710', - - # any module necessary for this one to work correctly - 'depends': ['web','base','account','l10n_ru_doc','contract'], - - # always loaded - 'data': [ - 'views/ir_actions_report_view.xml', - 'views/res_partner_view.xml', - 'views/res_company_view.xml', - 'views/res_users_view.xml', - 'views/views_uom_okei.xml', - 'views/view_move.xml', - 'reports/report.xml', - 'reports/upd_report.xml', - ], - - 'assets': { - 'web.assets_backend': [ - 'upd_xml/static/src/js/report/action_manager_report.js', - ], - }, - # only loaded in demonstration mode - 'demo': [ - 'demo/demo.xml', - ], - - 'external_dependencies': { - 'python': [ - 'lxml' - ] - }, -} - diff --git a/upd_xml/__pycache__/__init__.cpython-310.pyc b/upd_xml/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index f00f6c6..0000000 Binary files a/upd_xml/__pycache__/__init__.cpython-310.pyc and /dev/null differ diff --git a/upd_xml/controllers/__init__.py b/upd_xml/controllers/__init__.py deleted file mode 100644 index b0f26a9..0000000 --- a/upd_xml/controllers/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -*- coding: utf-8 -*- - -from . import controllers diff --git a/upd_xml/controllers/__pycache__/__init__.cpython-310.pyc b/upd_xml/controllers/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index d0fb94f..0000000 Binary files a/upd_xml/controllers/__pycache__/__init__.cpython-310.pyc and /dev/null differ diff --git a/upd_xml/controllers/__pycache__/controllers.cpython-310.pyc b/upd_xml/controllers/__pycache__/controllers.cpython-310.pyc deleted file mode 100644 index fbaedf3..0000000 Binary files a/upd_xml/controllers/__pycache__/controllers.cpython-310.pyc and /dev/null differ diff --git a/upd_xml/controllers/controllers.py b/upd_xml/controllers/controllers.py deleted file mode 100644 index 537e3a8..0000000 --- a/upd_xml/controllers/controllers.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright (C) 2014-2015 Grupo ESOC -# License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html). - -import json -import logging - -from werkzeug.urls import url_parse - -from odoo.http import content_disposition, request, route, serialize_exception -from odoo.tools import html_escape -from odoo.tools.safe_eval import safe_eval, time - -from odoo.addons.web.controllers import report - -_logger = logging.getLogger(__name__) - - -class ReportController(report.ReportController): - @route() - def report_routes( - self, reportname, docids=None, converter=None, options=None, **kwargs - ): - if converter != "xml": - return super().report_routes( - reportname, - docids=docids, - converter=converter, - options=options, - **kwargs, - ) - if docids: - docids = [int(_id) for _id in docids.split(",")] - data = {**json.loads(options or "{}"), **kwargs} - context = dict(request.env.context) - if "context" in data: - data["context"] = json.loads(data["context"] or "{}") - # Ignore 'lang' here, because the context in data is the one from the - # webclient *but* if the user explicitely wants to change the lang, this - # mechanism overwrites it. - if "lang" in data["context"]: - del data["context"]["lang"] - context.update(data["context"]) - report_Obj = request.env["ir.actions.report"] - xml = report_Obj.with_context(**context)._render_qweb_xml( - reportname, docids, data=data - )[0] - xmlhttpheaders = [("Content-Type", "text/xml"), ("Content-Length", len(xml))] - return request.make_response(xml, headers=xmlhttpheaders) - - @route() - def report_download(self, data, context=None, token=None): - requestcontent = json.loads(data) - url, report_type = requestcontent[0], requestcontent[1] - reportname = "???" - if report_type != "qweb-xml": - return super().report_download(data, context=context, token=token) - try: - reportname = url.split("/report/xml/")[1].split("?")[0] - docids = None - if "/" in reportname: - reportname, docids = reportname.split("/") - report = request.env["ir.actions.report"]._get_report_from_name(reportname) - filename = None - if docids: - response = self.report_routes( - reportname, docids=docids, converter="xml", context=context - ) - ids = [int(x) for x in docids.split(",")] - obj = request.env[report.model].browse(ids) - if report.print_report_name and not len(obj) > 1: - report_name = safe_eval( - report.print_report_name, {"object": obj, "time": time} - ) - filename = f"{report_name}.{report.xml_extension}" - else: - data = url_parse(url).decode_query(cls=dict) - if "context" in data: - context = json.loads(context or "{}") - data_context = json.loads(data.pop("context")) - context = json.dumps({**context, **data_context}) - response = self.report_routes( - reportname, converter="xml", context=context, **data - ) - filename = filename or f"{report.name}.{report.xml_extension}" - response.headers.add("Content-Disposition", content_disposition(filename)) - return response - except Exception as e: - _logger.exception(f"Error while generating report {reportname}") - se = serialize_exception(e) - error = {"code": 200, "message": "Odoo Server Error", "data": se} - return request.make_response(html_escape(json.dumps(error))) \ No newline at end of file diff --git a/upd_xml/demo/demo.xml b/upd_xml/demo/demo.xml deleted file mode 100644 index b5678e1..0000000 --- a/upd_xml/demo/demo.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - diff --git a/upd_xml/models/__init__.py b/upd_xml/models/__init__.py deleted file mode 100644 index 6c43466..0000000 --- a/upd_xml/models/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -# -*- coding: utf-8 -*- - -from . import ir_actions_report -from . import res_company -from . import res_partner -from . import res_users -from . import uom_okei -from . import move diff --git a/upd_xml/models/__pycache__/__init__.cpython-310.pyc b/upd_xml/models/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 069b0db..0000000 Binary files a/upd_xml/models/__pycache__/__init__.cpython-310.pyc and /dev/null differ diff --git a/upd_xml/models/__pycache__/ir_actions_report.cpython-310.pyc b/upd_xml/models/__pycache__/ir_actions_report.cpython-310.pyc deleted file mode 100644 index bd05cb0..0000000 Binary files a/upd_xml/models/__pycache__/ir_actions_report.cpython-310.pyc and /dev/null differ diff --git a/upd_xml/models/__pycache__/move.cpython-310.pyc b/upd_xml/models/__pycache__/move.cpython-310.pyc deleted file mode 100644 index 485d4bb..0000000 Binary files a/upd_xml/models/__pycache__/move.cpython-310.pyc and /dev/null differ diff --git a/upd_xml/models/__pycache__/res_company.cpython-310.pyc b/upd_xml/models/__pycache__/res_company.cpython-310.pyc deleted file mode 100644 index 384dab7..0000000 Binary files a/upd_xml/models/__pycache__/res_company.cpython-310.pyc and /dev/null differ diff --git a/upd_xml/models/__pycache__/res_partner.cpython-310.pyc b/upd_xml/models/__pycache__/res_partner.cpython-310.pyc deleted file mode 100644 index de5e486..0000000 Binary files a/upd_xml/models/__pycache__/res_partner.cpython-310.pyc and /dev/null differ diff --git a/upd_xml/models/__pycache__/res_users.cpython-310.pyc b/upd_xml/models/__pycache__/res_users.cpython-310.pyc deleted file mode 100644 index 7a5e740..0000000 Binary files a/upd_xml/models/__pycache__/res_users.cpython-310.pyc and /dev/null differ diff --git a/upd_xml/models/__pycache__/uom_okei.cpython-310.pyc b/upd_xml/models/__pycache__/uom_okei.cpython-310.pyc deleted file mode 100644 index c2caf92..0000000 Binary files a/upd_xml/models/__pycache__/uom_okei.cpython-310.pyc and /dev/null differ diff --git a/upd_xml/models/ir_actions_report.py b/upd_xml/models/ir_actions_report.py deleted file mode 100755 index db8e07e..0000000 --- a/upd_xml/models/ir_actions_report.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright (C) 2014-2015 Grupo ESOC -# License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html). - -from odoo import fields, models, api - - -class IrActionsReport(models.Model): - _inherit = "ir.actions.report" - - report_type = fields.Selection( - selection_add=[("qweb-xml", "XML")], ondelete={"qweb-xml": "set default"} - ) - xsd_schema = fields.Binary( - string="XSD Validation Schema", - attachment=True, - help="File with XSD Schema for checking content of result report. Can be empty " - "if validation is not required.", - ) - xml_encoding = fields.Selection( - selection=[ - ("WINDOWS-1251", "WINDOWS-1251") # will be used as default even if nothing is selected - ], - string="XML Encoding", - help=( - "Encoding for XML reports. If nothing is selected, " - "then UTF-8 will be applied." - ), - ) - xml_declaration = fields.Boolean( - string="XML Declaration", - help=( - """Add `` at the start """ - """of final report file.""" - ), - default=True, - ) - xml_extension = fields.Char( - default="xml", - help="Extension for XML Reports, by default is `xml`", - ) - - @api.model - def _render_qweb_xml(self, report_ref, res_ids, data=None): - """ - Call `generate_report` method of report abstract class - `report.` or of standard class for XML report - rendering - `report.upd_xml.abstract` - - Args: - * docids(list) - IDs of instances for those report will be generated - * data(dict, None) - variables for report rendering - - Returns: - * str - result content of report - * str - type of result content - """ - report = self._get_report(report_ref) - report_model = self.env.get( - f"report.{report.report_name}", self.env["report.upd_xml.abstract"] - ) - return report_model.generate_report( - ir_report=report, # will be used to get settings of report - docids=res_ids, - data=data or {}, - ) diff --git a/upd_xml/models/move.py b/upd_xml/models/move.py deleted file mode 100755 index 208e7b9..0000000 --- a/upd_xml/models/move.py +++ /dev/null @@ -1,209 +0,0 @@ -from odoo import api, fields, models -import hashlib -from odoo.exceptions import UserError -from odoo.http import request - -class Users(models.Model): - _inherit = 'account.move' - - edi = fields.Char(string='ID EDI', compute='sh1_edi') - kpp = fields.Char(string='КПП', compute='get_kpp') - def get_kpp(self): - for s in self: - pid=self.partner_id.parent_id or self.partner_id - - s.kpp=pid.kpp if (s.partner_id==s.partner_shipping_id or not s.partner_shipping_id) else s.partner_shipping_id.kpp - - @api.depends('name') - def sh1_edi(self): - hash_object = hashlib.sha1((self.name).encode('utf-8')) - pid=self.partner_id.parent_id or self.partner_id - self.edi='ON_NSCHFDOPPR_2BM-'+str(pid.edi)+'_'+str(self.company_id.edi)+'_'+hash_object.hexdigest() - - def print_upd(self): - for s in self: - mes = str(s.check_correct_upd()).strip() - if mes != "": - raise UserError(u"Не удалось сформировать УПД. Выявлены следующие ошибки:\n{}".format(mes)) - else: - # pdf = \ - return self.env.ref('upd_xml.upd_xml_report').sudo().report_action(s.id) # render_qweb_xml(s.id) - # pdfhttpheaders = [('Content-Type', 'application/pdf'), ('Content-Length', len(pdf)), ] - # return request.make_response(pdf, headers=pdfhttpheaders) - - def check_correct_upd(self, manually=True): - for s in self: - mes = "" - company = s.company_id - if s.name == '/': - mes += u"Отсутствует наименование документа. Проверидите документ, чтобы назваие сформировалось автоматически.\n" - if not s.only_service and s.get_delivery_doc_name()=='0': - mes += u"Отсутствуют связанные отгрузки.\n" - if not company: - company = self.env.company - if not company: - mes += u"Не указана компания.\n" - else: - if not company.edi: - mes += u"Не указан идентификатор компании для Diadoc.\n" - if not company.name: - mes += u"Не указано наименование компании.\n" - if not company.okpo: - mes += u"Не указано ОКПО компании.\n" - if not company.inn: - mes += u"Не указан ИНН компании.\n" - else: - if len(company.inn) == 12: - if not company.partner_id.last_name_IP: - mes += u"Не указана фамилия ИП для вашей компании.\n" - if not company.partner_id.first_name_IP: - mes += u"Не указано имя ИП для вашей компании.\n" - if not company.partner_id.middle_name_IP: - mes += u"Не указано отчество ИП для вашей компании.\n" - elif len(company.inn) == 10: - if not company.kpp: - mes += u"Не указан КПП компании.\n" - else: - mes += u"Некорректный ИНН компании.\n" - if not company.city: - mes += u"Не указан город компании.\n" - if not company.street: - mes += u"Не указан адрес компании.\n" - if not company.chief_id: - mes += u"Не указан руководитель компании.\n" - else: - if not company.chief_id.function: - mes += u"Не указана должность руководителя компании.\n" - if not company.chief_id.last_name: - mes += u"Не указана фамилия руководителя компании.\n" - if not company.chief_id.first_name: - mes += u"Не указано имя руководителя компании.\n" - if not company.chief_id.second_name: - mes += u"Не указано отчество руководителя компании.\n" - pid = s.partner_id.parent_id - if not pid: - pid = s.partner_id - if not pid: - mes += u"Не указан контрагент.\n" - else: - if not pid.edi: - mes += u"Не указан идентификатор контрагента для Diadoc.\n" - if not pid.name: - mes += u"Не указано наименование контрагента.\n" - if not pid.okpo: - mes += u"Не указано ОКПО контрагента.\n" - if not pid.inn: - mes += u"Не указан ИНН контрагента.\n" - else: - if len(pid.inn) == 12: - if not pid.last_name_IP: - mes += u"Не указана фамилия ИП для контрагента.\n" - if not pid.first_name_IP: - mes += u"Не указано имя ИП для контрагента.\n" - if not pid.middle_name_IP: - mes += u"Не указано отчество ИП для контрагента.\n" - elif len(pid.inn) == 10: - if not pid.kpp: - mes += u"Не указан КПП контрагента.\n" - else: - mes += u"Некорректный ИНН контрагента.\n" - if not pid.city: - mes += u"Не указан город контрагента.\n" - if not pid.street: - mes += u"Не указан адрес контрагента.\n" - if manually: - if not s.edi: - mes += u"Не указан идентификатор документа для Diadoc.\n" - if not s.name: - mes += u"Не указано наименование документа\n" - if not s.invoice_date: - mes += u"Не указана дата документа\n" - if not s.only_service: - gruzootpr = s.gruzootpr - if not gruzootpr: - gruzootpr = pid - if gruzootpr.parent_id: - gruzootpr = gruzootpr.parent_id - if not gruzootpr: - mes += u"Не указан грузоотправитель.\n" - else: - if not gruzootpr.name: - mes += u"Не указано наименование грузоотправителя.\n" - if not gruzootpr.okpo: - mes += u"Не указано ОКПО грузоотправителя.\n" - if not gruzootpr.inn: - mes += u"Не указан ИНН грузоотправителя.\n" - else: - if len(gruzootpr.inn) == 12: - if not gruzootpr.last_name_IP: - mes += u"Не указана фамилия ИП для грузоотправителя.\n" - if not gruzootpr.first_name_IP: - mes += u"Не указано имя ИП для грузоотправителя.\n" - if not gruzootpr.middle_name_IP: - mes += u"Не указано отчество ИП для грузоотправителя.\n" - elif len(gruzootpr.inn) == 10: - if not gruzootpr.kpp: - mes += u"Не указан КПП грузоотправителя.\n" - else: - mes += u"Некорректный ИНН грузоотправителя.\n" - if not gruzootpr.city: - mes += u"Не указан город грузоотправителя.\n" - if not gruzootpr.street: - mes += u"Не указан адрес грузоотправителя.\n" - gruzopol = s.gruzopol - if not gruzopol: - gruzopol = pid - if gruzopol.parent_id: - gruzopol = gruzopol.parent_id - if not gruzopol: - mes += u"Не указан грузополучатель.\n" - else: - if not gruzopol.name: - mes += u"Не указано наименование грузополучателя.\n" - if not gruzopol.okpo: - mes += u"Не указано ОКПО грузополучателя.\n" - if not gruzopol.inn: - mes += u"Не указан ИНН грузополучателя.\n" - else: - if len(gruzopol.inn) == 12: - if not gruzopol.last_name_IP: - mes += u"Не указана фамилия ИП для грузополучателя.\n" - if not gruzopol.first_name_IP: - mes += u"Не указано имя ИП для грузополучателя.\n" - if not gruzopol.middle_name_IP: - mes += u"Не указано отчество ИП для грузополучателя.\n" - elif len(gruzopol.inn) == 10: - if not gruzopol.kpp: - mes += u"Не указан КПП грузополучателя.\n" - else: - mes += u"Некорректный ИНН грузополучателя.\n" - if not gruzopol.city: - mes += u"Не указан город грузополучателя.\n" - if not gruzopol.street: - mes += u"Не указан адрес грузополучателя.\n" - if s.payment_num: - if not s.payment_date: - mes += u"Не указана дата платежки в УПД.\n" - if not s.invoice_line_ids: - mes += u"Отсутствуют строки заказа.\n" - else: - for line in s.invoice_line_ids: - if not line.price_unit: - mes += u"Не указана цена за единицу для товара {}.\n".format(line.name) - if not line.quantity: - mes += u"Не указано количество для товара {}.\n".format(line.name) - if not line.product_uom_id.okei: - mes += u"Не указан код ОКЕИ для единицы измерения {}.\n".format(line.product_uom_id.name) - if not s.mt_contractid: - mes += u"Не указан договор.\n" - else: - if not s.mt_contractid.name: - mes += u"Не указано наименование договора.\n" - if not s.mt_contractid.date_start: - mes += u"Не указана дата договора.\n" - if not s.kladov: - mes += u"Не указано лицо, ответственное за передачу товаров/услуг.\n" - else: - if not s.kladov.partner_id.function: - mes += u"Не указана должность лица, ответственного за передачу товаров/услуг.\n" - return str(mes) \ No newline at end of file diff --git a/upd_xml/models/res_company.py b/upd_xml/models/res_company.py deleted file mode 100755 index 945d134..0000000 --- a/upd_xml/models/res_company.py +++ /dev/null @@ -1,6 +0,0 @@ -from odoo import api, fields, models - -class Company(models.Model): - _inherit = 'res.company' - - edi = fields.Char(string='ID EDI', readonly=False) \ No newline at end of file diff --git a/upd_xml/models/res_partner.py b/upd_xml/models/res_partner.py deleted file mode 100755 index ddf1f85..0000000 --- a/upd_xml/models/res_partner.py +++ /dev/null @@ -1,33 +0,0 @@ -from odoo import api, fields, models - -class ResPartner(models.Model): - _inherit = 'res.partner' - - edi = fields.Char('ID EDI') - house = fields.Char('Дом') - office = fields.Char('Квартира, офис') - fias_id = fields.Char('Код ФИАС') - last_name_IP = fields.Char('Фамилия ИП', compute='get_fio', readonly=False) - first_name_IP = fields.Char('Имя ИП', compute='get_fio',readonly=False) - middle_name_IP = fields.Char('Отчество ИП', compute='get_fio',readonly=False) - - @api.depends('name') - def get_fio(self): - for s in self: - if s.name: - name = s.name - if name.find('ИП ')!=-1: - name = name[name.find(' ')+1:] - s.last_name_IP = name[:name.find(' ')] - name = name[name.find(' ') + 1:] - s.first_name_IP = name[:name.find(' ')] - name = name[name.find(' ') + 1:] - s.middle_name_IP = name - else: - s.last_name_IP = "" - s.first_name_IP = "" - s.middle_name_IP = "" - else: - s.last_name_IP = "" - s.first_name_IP = "" - s.middle_name_IP = "" \ No newline at end of file diff --git a/upd_xml/models/res_users.py b/upd_xml/models/res_users.py deleted file mode 100755 index 30a844d..0000000 --- a/upd_xml/models/res_users.py +++ /dev/null @@ -1,25 +0,0 @@ -from odoo import api, fields, models - -class Users(models.Model): - _inherit = 'res.users' - - last_name = fields.Char(string='Фамилия', compute='update_name') - first_name = fields.Char(string='Имя', compute='update_name') - second_name = fields.Char(string='Отчество', compute='update_name') - - @api.depends('name') - def update_name(self): - for s in self: - s.last_name = '' - s.first_name = '' - s.second_name = '' - if s.name: - s.last_name = s.name - s.first_name = '' - s.second_name = '' - if len(s.name.split(' ')) == 3: - s.last_name, s.first_name, s.second_name = s.name.split(' ') - if len(s.name.split(' ')) == 4: - s.last_name, s.first_name, second_name1, second_name2 = s.name.split(' ') - s.second_name = second_name1 + ' ' + second_name2 - diff --git a/upd_xml/models/uom_okei.py b/upd_xml/models/uom_okei.py deleted file mode 100755 index b40925b..0000000 --- a/upd_xml/models/uom_okei.py +++ /dev/null @@ -1,12 +0,0 @@ -from odoo import models, fields, api - - -class uom(models.Model): - _inherit="uom.uom" - - okei = fields.Char(string="Код ОКЕИ") - -class uom_move(models.Model): - _inherit="account.move.line" - - uom_okei = fields.Char(string='Код ОКЕИ',related='product_uom_id.okei') diff --git a/upd_xml/reports/__init__.py b/upd_xml/reports/__init__.py deleted file mode 100755 index fff0f44..0000000 --- a/upd_xml/reports/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html). - -from . import report_report_xml_abstract diff --git a/upd_xml/reports/__pycache__/__init__.cpython-310.pyc b/upd_xml/reports/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index a0e94a4..0000000 Binary files a/upd_xml/reports/__pycache__/__init__.cpython-310.pyc and /dev/null differ diff --git a/upd_xml/reports/__pycache__/__init__.cpython-36.pyc b/upd_xml/reports/__pycache__/__init__.cpython-36.pyc deleted file mode 100755 index 2055cb9..0000000 Binary files a/upd_xml/reports/__pycache__/__init__.cpython-36.pyc and /dev/null differ diff --git a/upd_xml/reports/__pycache__/__init__.cpython-37.pyc b/upd_xml/reports/__pycache__/__init__.cpython-37.pyc deleted file mode 100755 index 9a27f91..0000000 Binary files a/upd_xml/reports/__pycache__/__init__.cpython-37.pyc and /dev/null differ diff --git a/upd_xml/reports/__pycache__/report_report_xml_abstract.cpython-310.pyc b/upd_xml/reports/__pycache__/report_report_xml_abstract.cpython-310.pyc deleted file mode 100644 index baed717..0000000 Binary files a/upd_xml/reports/__pycache__/report_report_xml_abstract.cpython-310.pyc and /dev/null differ diff --git a/upd_xml/reports/__pycache__/report_report_xml_abstract.cpython-36.pyc b/upd_xml/reports/__pycache__/report_report_xml_abstract.cpython-36.pyc deleted file mode 100755 index 36474ce..0000000 Binary files a/upd_xml/reports/__pycache__/report_report_xml_abstract.cpython-36.pyc and /dev/null differ diff --git a/upd_xml/reports/__pycache__/report_report_xml_abstract.cpython-37.pyc b/upd_xml/reports/__pycache__/report_report_xml_abstract.cpython-37.pyc deleted file mode 100755 index 52ea2da..0000000 Binary files a/upd_xml/reports/__pycache__/report_report_xml_abstract.cpython-37.pyc and /dev/null differ diff --git a/upd_xml/reports/report.xml b/upd_xml/reports/report.xml deleted file mode 100755 index bed15ef..0000000 --- a/upd_xml/reports/report.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - УПД xml - account.move - qweb-xml - upd_xml.demo_report_xml_view - upd_xml.demo_report_xml_view - '%s' % (object.edi) - - report - - diff --git a/upd_xml/reports/report_report_xml_abstract.py b/upd_xml/reports/report_report_xml_abstract.py deleted file mode 100755 index e4fd6a5..0000000 --- a/upd_xml/reports/report_report_xml_abstract.py +++ /dev/null @@ -1,48 +0,0 @@ -# License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html). - -from base64 import b64decode -from xml.dom import minidom - -from lxml import etree - -from odoo import api, models,SUPERUSER_ID -from odoo.exceptions import ValidationError - - -class ReportXmlAbstract(models.AbstractModel): - _name = "report.upd_xml.abstract" - _description = "Abstract XML Report" - - @api.model - def generate_report(self, ir_report, docids, data=None): - data = data or {} - data.setdefault("report_type", "text") - data = ir_report._get_rendering_context(ir_report, docids, data) - - result_bin = ir_report._render_template(ir_report.report_name, data) - - parsed_result_bin = minidom.parseString(result_bin) - result = parsed_result_bin.toprettyxml(indent=" ") - - # remove empty lines - utf8 = "UTF-8" - cp1251="WINDOWS-1251" - result = "\n".join( - line for line in result.splitlines() if line and not line.isspace() - ).encode('utf8') - - content = etree.tostring( - etree.fromstring(result), - encoding=ir_report.xml_encoding or cp1251, - xml_declaration=True, - pretty_print=True, - ) - return content, "xml" - - @api.model - def _get_report_values(self, docids, data=None): - return data or {} - - # if not data: - # data = {} - # return data.decode('cp1251') diff --git a/upd_xml/reports/upd_report.xml b/upd_xml/reports/upd_report.xml deleted file mode 100755 index 50d47b5..0000000 --- a/upd_xml/reports/upd_report.xml +++ /dev/null @@ -1,186 +0,0 @@ - - - - diff --git a/upd_xml/security/ir.model.access.csv b/upd_xml/security/ir.model.access.csv deleted file mode 100644 index 7a89480..0000000 --- a/upd_xml/security/ir.model.access.csv +++ /dev/null @@ -1,2 +0,0 @@ -id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_upd_xml_upd_xml,upd_xml.upd_xml,model_upd_xml_upd_xml,base.group_user,1,1,1,1 diff --git a/upd_xml/static/src/js/report/action_manager_report.js b/upd_xml/static/src/js/report/action_manager_report.js deleted file mode 100755 index e83200e..0000000 --- a/upd_xml/static/src/js/report/action_manager_report.js +++ /dev/null @@ -1,49 +0,0 @@ -/** @odoo-module **/ - -import {download} from "@web/core/network/download"; -import {registry} from "@web/core/registry"; - -function getReportUrl({report_name, context, data}, env) { - // Rough copy of action_service.js _getReportUrl method. - let url = `/report/xml/${report_name}`; - const actionContext = context || {}; - if (data && JSON.stringify(data) !== "{}") { - const encodedOptions = encodeURIComponent(JSON.stringify(data)); - const encodedContext = encodeURIComponent(JSON.stringify(actionContext)); - return `${url}?options=${encodedOptions}&context=${encodedContext}`; - } - if (actionContext.active_ids) { - url += `/${actionContext.active_ids.join(",")}`; - } - const userContext = encodeURIComponent(JSON.stringify(env.services.user.context)); - return `${url}?context=${userContext}`; -} -async function triggerDownload(action, {onClose}, env) { - // Rough copy of action_service.js _triggerDownload method. - env.services.ui.block(); - const data = JSON.stringify([getReportUrl(action, env), action.report_type]); - const context = JSON.stringify(env.services.user.context); - try { - await download({url: "/report/download", data: {data, context}}); - } finally { - env.services.ui.unblock(); - } - if (action.close_on_report_download) { - return env.services.action.doAction( - {type: "ir.actions.act_window_close"}, - {onClose} - ); - } - if (onClose) { - onClose(); - } -} -registry - .category("ir.actions.report handlers") - .add("xml_handler", async function (action, options, env) { - if (action.report_type === "qweb-xml") { - await triggerDownload(action, options, env); - return true; - } - return false; - }); diff --git a/upd_xml/views/ir_actions_report_view.xml b/upd_xml/views/ir_actions_report_view.xml deleted file mode 100755 index d5cd94f..0000000 --- a/upd_xml/views/ir_actions_report_view.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - ir.actions.report.view.form.report.xml - ir.actions.report - - - - - - - - - - - - - diff --git a/upd_xml/views/res_company_view.xml b/upd_xml/views/res_company_view.xml deleted file mode 100755 index 2d43a2c..0000000 --- a/upd_xml/views/res_company_view.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - res.company.ru.form - res.company - - - - - - - - - - - - diff --git a/upd_xml/views/res_partner_view.xml b/upd_xml/views/res_partner_view.xml deleted file mode 100755 index c716587..0000000 --- a/upd_xml/views/res_partner_view.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - res.partner.ru.form - res.partner - - - - - - - - - - - - - - - - - - - diff --git a/upd_xml/views/res_users_view.xml b/upd_xml/views/res_users_view.xml deleted file mode 100755 index 8dc9487..0000000 --- a/upd_xml/views/res_users_view.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - res.users.signature.form - res.users - - - - - - - - - - - - - - diff --git a/upd_xml/views/view_move.xml b/upd_xml/views/view_move.xml deleted file mode 100755 index 21a699b..0000000 --- a/upd_xml/views/view_move.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - edi account move - account.move - - - - -