Начальное наполнение
This commit is contained in:
parent
f31b6129a0
commit
c008ed1ab6
68
README.md
68
README.md
@ -1,2 +1,68 @@
|
||||
# account
|
||||
Odoo Accounting
|
||||
---------------
|
||||
|
||||
The Odoo <a href="https://www.odoo.com/app/accounting">Open Source Accounting</a> app allows a better way to
|
||||
collaborate with your accountants, your customers and control your suppliers.
|
||||
|
||||
Activate features on demand, from integrated analytic accounting to budget,
|
||||
assets and multiple companies consolidation.
|
||||
|
||||
A Smart User Interface
|
||||
----------------------
|
||||
|
||||
Record transactions in a few clicks and easily manage all financial activities
|
||||
in one place. Odoo's user interface is designed with productivity in mind.
|
||||
|
||||
A Better Way To Work – Together
|
||||
-------------------------------
|
||||
|
||||
Share access to your latest business numbers with your team and your accountant
|
||||
– so everyone is up to speed. From work, home or on the go.
|
||||
|
||||
Connect Your Bank Accounts
|
||||
--------------------------
|
||||
|
||||
Import your bank statements and reconcile them in just a few clicks. Prepare
|
||||
payment orders based on your supplier invoices and payment terms.
|
||||
|
||||
Electronic invoicing and automated follow-ups
|
||||
---------------------------------------------
|
||||
|
||||
Create and send professional invoices & get paid online. Get rid of the stress
|
||||
of having to constantly remind your debtors. Simply set-up and automate
|
||||
follow-ups to get paid quickly.
|
||||
|
||||
Sales Integration
|
||||
-----------------
|
||||
|
||||
Automatically create invoices from sales orders, delivery orders or base them
|
||||
on time and material. Re-invoice expenses on projects to your customer in just
|
||||
a few clicks.
|
||||
|
||||
|
||||
Purchase Integration
|
||||
--------------------
|
||||
|
||||
Control supplier invocies based on purchase orders. Get real-time inventory
|
||||
valuation reports automatically posted in your accounts.
|
||||
|
||||
Multi-Level Analytic Accounting
|
||||
-------------------------------
|
||||
|
||||
Integrate your analytic accounting operations with timesheets, projects,
|
||||
invoices, expenses, etc. No need to record transactions, all analytic entries
|
||||
are posted automatically following your business rules.
|
||||
|
||||
Everything you need to grow
|
||||
---------------------------
|
||||
|
||||
Manage your assets, track expenses, control budgets, multi-level analytic
|
||||
accounting; Odoo has all the features you need to sustain all your business
|
||||
activities.
|
||||
|
||||
Scale With Your Organization
|
||||
----------------------------
|
||||
|
||||
Odoo supports multiple currencies, multiple users with different access rights,
|
||||
multiple companies with real time consolidation and unlimited analytic plans.
|
||||
|
||||
|
63
__init__.py
Normal file
63
__init__.py
Normal file
@ -0,0 +1,63 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
SYSCOHADA_LIST = ['BJ', 'BF', 'CM', 'CF', 'KM', 'CG', 'CI', 'GA', 'GN', 'GW', 'GQ', 'ML', 'NE',
|
||||
'CD', 'SN', 'TD', 'TG']
|
||||
VAT_LIST = ['AT', 'BE', 'CA', 'CO', 'DE', 'EC', 'ES', 'ET', 'FR', 'GR', 'IT', 'LU', 'MX', 'NL',
|
||||
'NO', 'PL', 'PT', 'RO', 'SI', 'TR', 'GB', 'VE', 'VN']
|
||||
|
||||
def _set_fiscal_country(env):
|
||||
""" Sets the fiscal country on existing companies when installing the module.
|
||||
That field is an editable computed field. It doesn't automatically get computed
|
||||
on existing records by the ORM when installing the module, so doing that by hand
|
||||
ensures existing records will get a value for it if needed.
|
||||
"""
|
||||
env['res.company'].search([]).compute_account_tax_fiscal_country()
|
||||
|
||||
|
||||
def _auto_install_l10n(env):
|
||||
# Check the country of the main company (only) and eventually load some module needed in that country
|
||||
country = env.company.country_id
|
||||
country_code = country.code
|
||||
if country_code:
|
||||
module_list = []
|
||||
if not env.company.chart_template:
|
||||
template_code = env['account.chart.template']._guess_chart_template(country)
|
||||
module_list.append(env['account.chart.template']._get_chart_template_mapping()[template_code]['module'])
|
||||
if country_code in ['US', 'CA']:
|
||||
module_list.append('account_check_printing')
|
||||
if country_code in SYSCOHADA_LIST + VAT_LIST:
|
||||
module_list.append('base_vat')
|
||||
if country_code == 'uk':
|
||||
module_list.append('account_bacs')
|
||||
|
||||
module_ids = env['ir.module.module'].search([('name', 'in', module_list), ('state', '=', 'uninstalled')])
|
||||
if module_ids:
|
||||
module_ids.sudo().button_install()
|
||||
|
||||
def _auto_install_avatax(env):
|
||||
""" Install the avatax module automatically if the company is in a country that uses avatax """
|
||||
avatax_country_codes = ['US', 'CA']
|
||||
|
||||
country = env.company.country_id
|
||||
country_code = country.code
|
||||
|
||||
if country_code in avatax_country_codes:
|
||||
module = env['ir.module.module'].search([('name', '=', 'account_avatax')])
|
||||
if module.state == 'uninstalled':
|
||||
module.sudo().button_install()
|
||||
|
||||
def _account_post_init(env):
|
||||
_auto_install_l10n(env)
|
||||
_set_fiscal_country(env)
|
||||
_auto_install_avatax(env)
|
||||
|
||||
# imported here to avoid dependency cycle issues
|
||||
# pylint: disable=wrong-import-position
|
||||
from . import controllers
|
||||
from . import models
|
||||
from . import demo
|
||||
from . import wizard
|
||||
from . import report
|
||||
from . import populate
|
||||
from . import tools
|
117
__manifest__.py
Normal file
117
__manifest__.py
Normal file
@ -0,0 +1,117 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
{
|
||||
'name' : 'Invoicing',
|
||||
'version' : '1.2',
|
||||
'summary': 'Invoices & Payments',
|
||||
'sequence': 10,
|
||||
'description': """
|
||||
Invoicing & Payments
|
||||
====================
|
||||
The specific and easy-to-use Invoicing system in Odoo allows you to keep track of your accounting, even when you are not an accountant. It provides an easy way to follow up on your vendors and customers.
|
||||
|
||||
You could use this simplified accounting in case you work with an (external) account to keep your books, and you still want to keep track of payments. This module also offers you an easy method of registering payments, without having to encode complete abstracts of account.
|
||||
""",
|
||||
'category': 'Accounting/Accounting',
|
||||
'website': 'https://www.odoo.com/app/invoicing',
|
||||
'depends': ['base_setup', 'onboarding', 'product', 'analytic', 'portal', 'digest'],
|
||||
'data': [
|
||||
'security/account_security.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'data/account_data.xml',
|
||||
'data/digest_data.xml',
|
||||
'views/account_report.xml',
|
||||
'data/mail_template_data.xml',
|
||||
'data/onboarding_data.xml',
|
||||
'views/account_payment_view.xml',
|
||||
'wizard/account_automatic_entry_wizard_views.xml',
|
||||
'wizard/account_unreconcile_view.xml',
|
||||
'wizard/account_move_reversal_view.xml',
|
||||
'wizard/account_resequence_views.xml',
|
||||
'wizard/account_payment_register_views.xml',
|
||||
'views/account_move_views.xml',
|
||||
'wizard/setup_wizards_view.xml',
|
||||
'views/account_account_views.xml',
|
||||
'views/account_group_views.xml',
|
||||
'views/account_journal_views.xml',
|
||||
'views/account_account_tag_views.xml',
|
||||
'views/account_bank_statement_views.xml',
|
||||
'views/account_reconcile_model_views.xml',
|
||||
'views/account_tax_views.xml',
|
||||
'views/account_full_reconcile_views.xml',
|
||||
'views/account_payment_term_views.xml',
|
||||
'views/account_payment_method.xml',
|
||||
'views/res_partner_bank_views.xml',
|
||||
'views/report_statement.xml',
|
||||
'views/terms_template.xml',
|
||||
'wizard/account_validate_move_view.xml',
|
||||
'views/res_company_views.xml',
|
||||
'views/product_view.xml',
|
||||
'views/account_analytic_plan_views.xml',
|
||||
'views/account_analytic_account_views.xml',
|
||||
'views/account_analytic_distribution_model_views.xml',
|
||||
'views/account_analytic_line_views.xml',
|
||||
'views/report_invoice.xml',
|
||||
'report/account_invoice_report_view.xml',
|
||||
'views/account_cash_rounding_view.xml',
|
||||
'views/ir_module_views.xml',
|
||||
'views/res_config_settings_views.xml',
|
||||
'views/partner_view.xml',
|
||||
'views/account_journal_dashboard_view.xml',
|
||||
'views/account_portal_templates.xml',
|
||||
'views/report_payment_receipt_templates.xml',
|
||||
'data/service_cron.xml',
|
||||
'views/account_incoterms_view.xml',
|
||||
'data/account_incoterms_data.xml',
|
||||
'views/digest_views.xml',
|
||||
'wizard/account_move_send_views.xml',
|
||||
'report/account_hash_integrity_templates.xml',
|
||||
'views/res_currency.xml',
|
||||
'views/account_menuitem.xml',
|
||||
'wizard/account_tour_upload_bill.xml',
|
||||
'wizard/accrued_orders.xml',
|
||||
'views/bill_preview_template.xml',
|
||||
'data/account_reports_data.xml',
|
||||
'views/uom_uom_views.xml',
|
||||
],
|
||||
'demo': [
|
||||
'demo/account_demo.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'application': True,
|
||||
'post_init_hook': '_account_post_init',
|
||||
'assets': {
|
||||
'web._assets_primary_variables': [
|
||||
'account/static/src/scss/variables.scss',
|
||||
],
|
||||
'web.assets_backend': [
|
||||
'account/static/src/css/account_bank_and_cash.css',
|
||||
'account/static/src/css/account.css',
|
||||
'account/static/src/scss/account_journal_dashboard.scss',
|
||||
'account/static/src/scss/account_searchpanel.scss',
|
||||
'account/static/src/components/**/*',
|
||||
'account/static/src/services/*.js',
|
||||
'account/static/src/js/tours/account.js',
|
||||
'account/static/src/views/**/*.js',
|
||||
'account/static/src/js/search/search_bar/search_bar.js',
|
||||
],
|
||||
'web.assets_frontend': [
|
||||
'account/static/src/js/account_portal_sidebar.js',
|
||||
'account/static/src/js/account_portal.js',
|
||||
],
|
||||
'web.assets_tests': [
|
||||
'account/static/tests/tours/**/*',
|
||||
],
|
||||
'web.qunit_suite_tests': [
|
||||
'account/static/tests/helpers/*.js',
|
||||
'account/static/tests/*.js',
|
||||
],
|
||||
'web.report_assets_common': [
|
||||
'account/static/src/css/report_invoice.css',
|
||||
],
|
||||
'web.report_assets_pdf': [
|
||||
'account/static/src/css/report_invoice.css',
|
||||
],
|
||||
},
|
||||
'license': 'LGPL-3',
|
||||
}
|
6
controllers/__init__.py
Normal file
6
controllers/__init__.py
Normal file
@ -0,0 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import portal
|
||||
from . import terms
|
||||
from . import download_docs
|
28
controllers/download_docs.py
Normal file
28
controllers/download_docs.py
Normal file
@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import http, _
|
||||
from odoo.http import request, content_disposition
|
||||
|
||||
|
||||
def _get_zip_headers(content, filename):
|
||||
return [
|
||||
('Content-Type', 'zip'),
|
||||
('X-Content-Type-Options', 'nosniff'),
|
||||
('Content-Length', len(content)),
|
||||
('Content-Disposition', content_disposition(filename)),
|
||||
]
|
||||
|
||||
|
||||
class AccountDocumentDownloadController(http.Controller):
|
||||
@http.route('/account/export_zip_documents', type='http', auth='user')
|
||||
def export_zip_documents(self, **args):
|
||||
""" Download zipped attachments. """
|
||||
ids = list(map(int, request.httprequest.args.getlist('ids')))
|
||||
filename = request.httprequest.args.get('filename')
|
||||
attachments = request.env['ir.attachment'].browse(ids)
|
||||
attachments.check_access_rights('read')
|
||||
attachments.check_access_rule('read')
|
||||
content = attachments._build_zip_from_attachments()
|
||||
headers = _get_zip_headers(content, filename)
|
||||
return request.make_response(content, headers)
|
180
controllers/portal.py
Normal file
180
controllers/portal.py
Normal file
@ -0,0 +1,180 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from odoo import http, _
|
||||
from odoo.osv import expression
|
||||
from odoo.addons.portal.controllers.portal import CustomerPortal, pager as portal_pager
|
||||
from odoo.addons.account.controllers.download_docs import _get_zip_headers
|
||||
from odoo.exceptions import AccessError, MissingError
|
||||
from odoo.http import request
|
||||
|
||||
|
||||
class PortalAccount(CustomerPortal):
|
||||
|
||||
def _prepare_home_portal_values(self, counters):
|
||||
values = super()._prepare_home_portal_values(counters)
|
||||
if 'invoice_count' in counters:
|
||||
invoice_count = request.env['account.move'].search_count(self._get_invoices_domain('out'), limit=1) \
|
||||
if request.env['account.move'].check_access_rights('read', raise_exception=False) else 0
|
||||
values['invoice_count'] = invoice_count
|
||||
if 'bill_count' in counters:
|
||||
bill_count = request.env['account.move'].search_count(self._get_invoices_domain('in'), limit=1) \
|
||||
if request.env['account.move'].check_access_rights('read', raise_exception=False) else 0
|
||||
values['bill_count'] = bill_count
|
||||
return values
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# My Invoices
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def _invoice_get_page_view_values(self, invoice, access_token, **kwargs):
|
||||
values = {
|
||||
'page_name': 'invoice',
|
||||
'invoice': invoice,
|
||||
}
|
||||
return self._get_page_view_values(invoice, access_token, values, 'my_invoices_history', False, **kwargs)
|
||||
|
||||
def _get_invoices_domain(self, m_type=None):
|
||||
if m_type in ['in', 'out']:
|
||||
move_type = [m_type+move for move in ('_invoice', '_refund', '_receipt')]
|
||||
else:
|
||||
move_type = ('out_invoice', 'out_refund', 'in_invoice', 'in_refund', 'out_receipt', 'in_receipt')
|
||||
return [('state', 'not in', ('cancel', 'draft')), ('move_type', 'in', move_type)]
|
||||
|
||||
def _get_account_searchbar_sortings(self):
|
||||
return {
|
||||
'date': {'label': _('Date'), 'order': 'invoice_date desc'},
|
||||
'duedate': {'label': _('Due Date'), 'order': 'invoice_date_due desc'},
|
||||
'name': {'label': _('Reference'), 'order': 'name desc'},
|
||||
'state': {'label': _('Status'), 'order': 'state'},
|
||||
}
|
||||
|
||||
def _get_account_searchbar_filters(self):
|
||||
return {
|
||||
'all': {'label': _('All'), 'domain': []},
|
||||
'invoices': {'label': _('Invoices'), 'domain': [('move_type', 'in', ('out_invoice', 'out_refund', 'out_receipt'))]},
|
||||
'bills': {'label': _('Bills'), 'domain': [('move_type', 'in', ('in_invoice', 'in_refund', 'in_receipt'))]},
|
||||
}
|
||||
|
||||
@http.route(['/my/invoices', '/my/invoices/page/<int:page>'], type='http', auth="user", website=True)
|
||||
def portal_my_invoices(self, page=1, date_begin=None, date_end=None, sortby=None, filterby=None, **kw):
|
||||
values = self._prepare_my_invoices_values(page, date_begin, date_end, sortby, filterby)
|
||||
|
||||
# pager
|
||||
pager = portal_pager(**values['pager'])
|
||||
|
||||
# content according to pager and archive selected
|
||||
invoices = values['invoices'](pager['offset'])
|
||||
request.session['my_invoices_history'] = invoices.ids[:100]
|
||||
|
||||
values.update({
|
||||
'invoices': invoices,
|
||||
'pager': pager,
|
||||
})
|
||||
return request.render("account.portal_my_invoices", values)
|
||||
|
||||
def _prepare_my_invoices_values(self, page, date_begin, date_end, sortby, filterby, domain=None, url="/my/invoices"):
|
||||
values = self._prepare_portal_layout_values()
|
||||
AccountInvoice = request.env['account.move']
|
||||
|
||||
domain = expression.AND([
|
||||
domain or [],
|
||||
self._get_invoices_domain(),
|
||||
])
|
||||
|
||||
searchbar_sortings = self._get_account_searchbar_sortings()
|
||||
# default sort by order
|
||||
if not sortby:
|
||||
sortby = 'date'
|
||||
order = searchbar_sortings[sortby]['order']
|
||||
|
||||
searchbar_filters = self._get_account_searchbar_filters()
|
||||
# default filter by value
|
||||
if not filterby:
|
||||
filterby = 'all'
|
||||
domain += searchbar_filters[filterby]['domain']
|
||||
|
||||
if date_begin and date_end:
|
||||
domain += [('create_date', '>', date_begin), ('create_date', '<=', date_end)]
|
||||
|
||||
values.update({
|
||||
'date': date_begin,
|
||||
# content according to pager and archive selected
|
||||
# lambda function to get the invoices recordset when the pager will be defined in the main method of a route
|
||||
'invoices': lambda pager_offset: (
|
||||
AccountInvoice.search(domain, order=order, limit=self._items_per_page, offset=pager_offset)
|
||||
if AccountInvoice.check_access_rights('read', raise_exception=False) else
|
||||
AccountInvoice
|
||||
),
|
||||
'page_name': 'invoice',
|
||||
'pager': { # vals to define the pager.
|
||||
"url": url,
|
||||
"url_args": {'date_begin': date_begin, 'date_end': date_end, 'sortby': sortby},
|
||||
"total": AccountInvoice.search_count(domain) if AccountInvoice.check_access_rights('read', raise_exception=False) else 0,
|
||||
"page": page,
|
||||
"step": self._items_per_page,
|
||||
},
|
||||
'default_url': url,
|
||||
'searchbar_sortings': searchbar_sortings,
|
||||
'sortby': sortby,
|
||||
'searchbar_filters': OrderedDict(sorted(searchbar_filters.items())),
|
||||
'filterby': filterby,
|
||||
})
|
||||
return values
|
||||
|
||||
@http.route(['/my/invoices/<int:invoice_id>'], type='http', auth="public", website=True)
|
||||
def portal_my_invoice_detail(self, invoice_id, access_token=None, report_type=None, download=False, **kw):
|
||||
try:
|
||||
invoice_sudo = self._document_check_access('account.move', invoice_id, access_token)
|
||||
except (AccessError, MissingError):
|
||||
return request.redirect('/my')
|
||||
|
||||
if report_type == 'pdf' and download and invoice_sudo.state == 'posted':
|
||||
# Send & Print wizard with only the 'download' checkbox to get the official attachment(s)
|
||||
template = request.env.ref(invoice_sudo._get_mail_template())
|
||||
attachment_ids = invoice_sudo._generate_pdf_and_send_invoice(template, bypass_download=True, checkbox_send_mail=False, checkbox_download=True)
|
||||
attachments = request.env['ir.attachment'].browse(attachment_ids)
|
||||
if len(attachments) > 1:
|
||||
filename = invoice_sudo._get_invoice_report_filename(extension='zip')
|
||||
zip_content = attachments.sudo()._build_zip_from_attachments()
|
||||
headers = _get_zip_headers(zip_content, filename)
|
||||
return request.make_response(zip_content, headers)
|
||||
headers = self._get_http_headers(invoice_sudo, report_type, attachments.raw, download)
|
||||
return request.make_response(attachments.raw, list(headers.items()))
|
||||
|
||||
elif report_type in ('html', 'pdf', 'text'):
|
||||
return self._show_report(model=invoice_sudo, report_type=report_type, report_ref='account.account_invoices', download=download)
|
||||
|
||||
values = self._invoice_get_page_view_values(invoice_sudo, access_token, **kw)
|
||||
return request.render("account.portal_invoice_page", values)
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# My Home
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def details_form_validate(self, data, partner_creation=False):
|
||||
error, error_message = super(PortalAccount, self).details_form_validate(data)
|
||||
# prevent VAT/name change if invoices exist
|
||||
partner = request.env['res.users'].browse(request.uid).partner_id
|
||||
# Skip this test if we're creating a new partner as we won't ever block him from filling values.
|
||||
if not partner_creation and not partner.can_edit_vat():
|
||||
if 'vat' in data and (data['vat'] or False) != (partner.vat or False):
|
||||
error['vat'] = 'error'
|
||||
error_message.append(_('Changing VAT number is not allowed once invoices have been issued for your account. Please contact us directly for this operation.'))
|
||||
if 'name' in data and (data['name'] or False) != (partner.name or False):
|
||||
error['name'] = 'error'
|
||||
error_message.append(_('Changing your name is not allowed once invoices have been issued for your account. Please contact us directly for this operation.'))
|
||||
if 'company_name' in data and (data['company_name'] or False) != (partner.company_name or False):
|
||||
error['company_name'] = 'error'
|
||||
error_message.append(_('Changing your company name is not allowed once invoices have been issued for your account. Please contact us directly for this operation.'))
|
||||
return error, error_message
|
||||
|
||||
def extra_details_form_validate(self, data, additional_required_fields, error, error_message):
|
||||
""" Ensure that all additional required fields have a value in the data """
|
||||
for field in additional_required_fields:
|
||||
if field.name not in data or not data[field.name]:
|
||||
error[field.name] = 'error'
|
||||
error_message.append(_('The field %s must be filled.', field.field_description.lower()))
|
||||
return error, error_message
|
29
controllers/terms.py
Normal file
29
controllers/terms.py
Normal file
@ -0,0 +1,29 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import http, _
|
||||
from odoo.http import request
|
||||
|
||||
|
||||
def sitemap_terms(env, rule, qs):
|
||||
if qs and qs.lower() not in '/terms':
|
||||
return
|
||||
use_invoice_terms = env['ir.config_parameter'].sudo().get_param('account.use_invoice_terms')
|
||||
if use_invoice_terms and env.company.terms_type == 'html':
|
||||
yield {'loc': '/terms'}
|
||||
|
||||
|
||||
class TermsController(http.Controller):
|
||||
|
||||
@http.route('/terms', type='http', auth='public', website=True, sitemap=sitemap_terms)
|
||||
def terms_conditions(self, **kwargs):
|
||||
use_invoice_terms = request.env['ir.config_parameter'].sudo().get_param('account.use_invoice_terms')
|
||||
if not (use_invoice_terms and request.env.company.terms_type == 'html'):
|
||||
return request.render('http_routing.http_error', {
|
||||
'status_code': _('Oops'),
|
||||
'status_message': _("""The requested page is invalid, or doesn't exist anymore.""")})
|
||||
values = {
|
||||
'use_invoice_terms': use_invoice_terms,
|
||||
'company': request.env.company
|
||||
}
|
||||
return request.render("account.account_terms_conditions_page", values)
|
152
data/account_data.xml
Normal file
152
data/account_data.xml
Normal file
@ -0,0 +1,152 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
|
||||
<record forcecreate="True" id="decimal_payment" model="decimal.precision">
|
||||
<field name="name">Payment Terms</field>
|
||||
<field name="digits">6</field>
|
||||
</record>
|
||||
|
||||
<!-- Open Settings from Purchase Journal to configure mail servers -->
|
||||
<record id="action_open_settings" model="ir.actions.act_window">
|
||||
<field name="name">Settings</field>
|
||||
<field name="res_model">res.config.settings</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">inline</field>
|
||||
<field name="context" eval="{'module': 'general_settings', 'bin_size': False}"/>
|
||||
</record>
|
||||
|
||||
<!-- TAGS FOR CASH FLOW STATEMENT DIRECT METHOD -->
|
||||
|
||||
<record id="account_tag_operating" model="account.account.tag">
|
||||
<field name="name">Operating Activities</field>
|
||||
<field name="applicability">accounts</field>
|
||||
</record>
|
||||
<record id="account_tag_financing" model="account.account.tag">
|
||||
<field name="name">Financing Activities</field>
|
||||
<field name="applicability">accounts</field>
|
||||
</record>
|
||||
<record id="account_tag_investing" model="account.account.tag">
|
||||
<field name="name">Investing & Extraordinary Activities</field>
|
||||
<field name="applicability">accounts</field>
|
||||
</record>
|
||||
|
||||
<!--
|
||||
Payment terms
|
||||
-->
|
||||
<record id="account_payment_term_immediate" model="account.payment.term">
|
||||
<field name="name">Immediate Payment</field>
|
||||
<field name="note">Payment terms: Immediate Payment</field>
|
||||
<field name="line_ids" eval="[Command.clear(), Command.create({'value': 'percent', 'value_amount': 100.0, 'nb_days': 0})]"/>
|
||||
</record>
|
||||
|
||||
<record id="account_payment_term_15days" model="account.payment.term">
|
||||
<field name="name">15 Days</field>
|
||||
<field name="note">Payment terms: 15 Days</field>
|
||||
<field name="line_ids" eval="[Command.clear(), Command.create({'value': 'percent', 'value_amount': 100.0, 'nb_days': 15})]"/>
|
||||
</record>
|
||||
|
||||
<record id="account_payment_term_21days" model="account.payment.term">
|
||||
<field name="name">21 Days</field>
|
||||
<field name="note">Payment terms: 21 Days</field>
|
||||
<field name="line_ids" eval="[Command.clear(), Command.create({'value': 'percent', 'value_amount': 100.0, 'nb_days': 21})]"/>
|
||||
</record>
|
||||
|
||||
<record id="account_payment_term_30days" model="account.payment.term">
|
||||
<field name="name">30 Days</field>
|
||||
<field name="note">Payment terms: 30 Days</field>
|
||||
<field name="line_ids" eval="[Command.clear(), Command.create({'value': 'percent', 'value_amount': 100.0, 'nb_days': 30})]"/>
|
||||
</record>
|
||||
|
||||
<record id="account_payment_term_45days" model="account.payment.term">
|
||||
<field name="name">45 Days</field>
|
||||
<field name="note">Payment terms: 45 Days</field>
|
||||
<field name="line_ids" eval="[Command.clear(), Command.create({'value': 'percent', 'value_amount': 100.0, 'nb_days': 45})]"/>
|
||||
</record>
|
||||
|
||||
<record id="account_payment_term_end_following_month" model="account.payment.term">
|
||||
<field name="name">End of Following Month</field>
|
||||
<field name="note">Payment terms: End of Following Month</field>
|
||||
<field name="line_ids" eval="[Command.clear(), Command.create({'value': 'percent', 'value_amount': 100.0, 'delay_type':'days_after_end_of_next_month', 'nb_days': 0})]"/>
|
||||
</record>
|
||||
|
||||
<record id="account_payment_term_30_days_end_month_the_10" model="account.payment.term">
|
||||
<field name="name">10 Days after End of Next Month</field>
|
||||
<field name="note">Payment terms: 10 Days after End of Next Month</field>
|
||||
<field name="line_ids" eval="[Command.clear(), Command.create({'value': 'percent', 'value_amount': 100.0, 'delay_type':'days_after_end_of_next_month', 'nb_days': 10})]"/>
|
||||
</record>
|
||||
|
||||
<record id="account_payment_term_advance_60days" model="account.payment.term">
|
||||
<field name="name">30% Now, Balance 60 Days</field>
|
||||
<field name="note">Payment terms: 30% Now, Balance 60 Days</field>
|
||||
<field name="line_ids" eval="[
|
||||
Command.clear(),
|
||||
Command.create({'value': 'percent', 'value_amount': 30.0, 'nb_days': 0}),
|
||||
Command.create({'value': 'percent', 'value_amount': 70.0, 'nb_days': 60})]"/>
|
||||
</record>
|
||||
|
||||
<record id="account_payment_term_30days_early_discount" model="account.payment.term">
|
||||
<field name="name">2/7 Net 30</field>
|
||||
<field name="note">Payment terms: 30 Days, 2% Early Payment Discount under 7 days</field>
|
||||
<field name="display_on_invoice">True</field>
|
||||
<field name="early_discount">True</field>
|
||||
<field name="discount_percentage">2</field>
|
||||
<field name="discount_days">7</field>
|
||||
<field name="line_ids" eval="[
|
||||
Command.clear(),
|
||||
Command.create({'value': 'percent', 'value_amount': 100.0, 'nb_days': 30})]"/>
|
||||
</record>
|
||||
|
||||
<!-- Account-related subtypes for messaging / Chatter -->
|
||||
<record id="mt_invoice_validated" model="mail.message.subtype">
|
||||
<field name="name">Validated</field>
|
||||
<field name="res_model">account.move</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Invoice validated</field>
|
||||
</record>
|
||||
<record id="mt_invoice_paid" model="mail.message.subtype">
|
||||
<field name="name">Paid</field>
|
||||
<field name="res_model">account.move</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Invoice paid</field>
|
||||
</record>
|
||||
<record id="mt_invoice_created" model="mail.message.subtype">
|
||||
<field name="name">Invoice Created</field>
|
||||
<field name="res_model">account.move</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="hidden" eval="True"/>
|
||||
<field name="description">Invoice Created</field>
|
||||
</record>
|
||||
|
||||
<!-- Payment methods -->
|
||||
<record id="account_payment_method_manual_in" model="account.payment.method">
|
||||
<field name="name">Manual</field>
|
||||
<field name="code">manual</field>
|
||||
<field name="payment_type">inbound</field>
|
||||
</record>
|
||||
<record id="account_payment_method_manual_out" model="account.payment.method">
|
||||
<field name="name">Manual</field>
|
||||
<field name="code">manual</field>
|
||||
<field name="payment_type">outbound</field>
|
||||
</record>
|
||||
|
||||
<!-- Partner Trust Property -->
|
||||
<record forcecreate="True" id="default_followup_trust" model="ir.property">
|
||||
<field name="name">Followup Trust Property</field>
|
||||
<field name="fields_id" search="[('model', '=', 'res.partner'), ('name', '=', 'trust')]"/>
|
||||
<field name="value">normal</field>
|
||||
<field name="type">selection</field>
|
||||
</record>
|
||||
|
||||
<!-- Share Button in action menu -->
|
||||
<record id="model_account_move_action_share" model="ir.actions.server">
|
||||
<field name="name">Share</field>
|
||||
<field name="model_id" ref="account.model_account_move"/>
|
||||
<field name="binding_model_id" ref="account.model_account_move"/>
|
||||
<field name="binding_view_types">form</field>
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = records.action_share()</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
50
data/account_incoterms_data.xml
Normal file
50
data/account_incoterms_data.xml
Normal file
@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="incoterm_EXW" model="account.incoterms">
|
||||
<field name="code">EXW</field>
|
||||
<field name="name">EX WORKS</field>
|
||||
</record>
|
||||
<record id="incoterm_FCA" model="account.incoterms">
|
||||
<field name="code">FCA</field>
|
||||
<field name="name">FREE CARRIER</field>
|
||||
</record>
|
||||
<record id="incoterm_FAS" model="account.incoterms">
|
||||
<field name="code">FAS</field>
|
||||
<field name="name">FREE ALONGSIDE SHIP</field>
|
||||
</record>
|
||||
<record id="incoterm_FOB" model="account.incoterms">
|
||||
<field name="code">FOB</field>
|
||||
<field name="name">FREE ON BOARD</field>
|
||||
</record>
|
||||
<record id="incoterm_CFR" model="account.incoterms">
|
||||
<field name="code">CFR</field>
|
||||
<field name="name">COST AND FREIGHT</field>
|
||||
</record>
|
||||
<record id="incoterm_CIF" model="account.incoterms">
|
||||
<field name="code">CIF</field>
|
||||
<field name="name">COST, INSURANCE AND FREIGHT</field>
|
||||
</record>
|
||||
<record id="incoterm_CPT" model="account.incoterms">
|
||||
<field name="code">CPT</field>
|
||||
<field name="name">CARRIAGE PAID TO</field>
|
||||
</record>
|
||||
<record id="incoterm_CIP" model="account.incoterms">
|
||||
<field name="code">CIP</field>
|
||||
<field name="name">CARRIAGE AND INSURANCE PAID TO</field>
|
||||
</record>
|
||||
<record id="incoterm_DPU" model="account.incoterms">
|
||||
<field name="code">DPU</field>
|
||||
<field name="name">DELIVERED AT PLACE UNLOADED</field>
|
||||
</record>
|
||||
<record id="incoterm_DAP" model="account.incoterms">
|
||||
<field name="code">DAP</field>
|
||||
<field name="name">DELIVERED AT PLACE</field>
|
||||
</record>
|
||||
<record id="incoterm_DDP" model="account.incoterms">
|
||||
<field name="code">DDP</field>
|
||||
<field name="name">DELIVERED DUTY PAID</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
61
data/account_reports_data.xml
Normal file
61
data/account_reports_data.xml
Normal file
@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
|
||||
<!-- GENERIC TAX REPORT -->
|
||||
<record id="generic_tax_report" model="account.report">
|
||||
<field name="name">Generic Tax report</field>
|
||||
<field name="filter_multi_company">tax_units</field>
|
||||
<field name="filter_fiscal_position" eval="1"/>
|
||||
<field name="default_opening_date_filter">last_tax_period</field>
|
||||
<field name="only_tax_exigible" eval="True"/>
|
||||
<field name="column_ids">
|
||||
<record id="generic_tax_report_column_net" model="account.report.column">
|
||||
<field name="name">Net</field>
|
||||
<field name="expression_label">net</field>
|
||||
<field name="figure_type">monetary</field>
|
||||
</record>
|
||||
<record id="generic_tax_report_column_tax" model="account.report.column">
|
||||
<field name="name">Tax</field>
|
||||
<field name="expression_label">tax</field>
|
||||
<field name="figure_type">monetary</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="generic_tax_report_account_tax" model="account.report">
|
||||
<field name="name">Group by: Account > Tax </field>
|
||||
<field name="root_report_id" ref="generic_tax_report"/>
|
||||
<field name="column_ids">
|
||||
<record id="generic_tax_report_account_tax_column_net" model="account.report.column">
|
||||
<field name="name">Net</field>
|
||||
<field name="expression_label">net</field>
|
||||
<field name="figure_type">monetary</field>
|
||||
</record>
|
||||
<record id="generic_tax_report_account_tax_column_tax" model="account.report.column">
|
||||
<field name="name">Tax</field>
|
||||
<field name="expression_label">tax</field>
|
||||
<field name="figure_type">monetary</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="generic_tax_report_tax_account" model="account.report">
|
||||
<field name="name">Group by: Tax > Account </field>
|
||||
<field name="root_report_id" ref="generic_tax_report"/>
|
||||
<field name="column_ids">
|
||||
<record id="generic_tax_report_tax_account_column_net" model="account.report.column">
|
||||
<field name="name">Net</field>
|
||||
<field name="expression_label">net</field>
|
||||
<field name="figure_type">monetary</field>
|
||||
</record>
|
||||
<record id="generic_tax_report_tax_account_column_tax" model="account.report.column">
|
||||
<field name="name">Tax</field>
|
||||
<field name="expression_label">tax</field>
|
||||
<field name="figure_type">monetary</field>
|
||||
</record>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
23
data/digest_data.xml
Normal file
23
data/digest_data.xml
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record id="digest.digest_digest_default" model="digest.digest">
|
||||
<field name="kpi_account_total_revenue">True</field>
|
||||
</record>
|
||||
</data>
|
||||
|
||||
<data>
|
||||
<record id="digest_tip_account_0" model="digest.tip">
|
||||
<field name="name">Tip: No need to print, put in an envelop and post your invoices</field>
|
||||
<field name="sequence">700</field>
|
||||
<field name="group_id" ref="account.group_account_invoice" />
|
||||
<field name="tip_description" type="html">
|
||||
<div>
|
||||
<p class="tip_title">Tip: No need to print, put in an envelop and post your invoices</p>
|
||||
<p class="tip_content">Use the “<i>Send by Post</i>” option to post invoices automatically. For the cost of a local stamp, we do all the manual work: your invoice will be printed in the right country, put in an envelop and sent by snail mail. Use this feature from the list view to post hundreds of invoices in bulk.</p>
|
||||
<img src="https://download.odoocdn.com/digests/account/static/src/img/invoice-stamps.png" width="540" class="illustration_border" />
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
139
data/mail_template_data.xml
Normal file
139
data/mail_template_data.xml
Normal file
@ -0,0 +1,139 @@
|
||||
<?xml version="1.0" ?>
|
||||
<odoo>
|
||||
|
||||
<!-- Mail template are declared in a NOUPDATE block
|
||||
so users can freely customize/delete them -->
|
||||
<data noupdate="1">
|
||||
<!--Email template -->
|
||||
<record id="email_template_edi_invoice" model="mail.template">
|
||||
<field name="name">Invoice: Sending</field>
|
||||
<field name="model_id" ref="account.model_account_move"/>
|
||||
<field name="email_from">{{ (object.invoice_user_id.email_formatted or object.company_id.email_formatted or user.email_formatted) }}</field>
|
||||
<field name="partner_to">{{ object.partner_id.id }}</field>
|
||||
<field name="subject">{{ object.company_id.name }} Invoice (Ref {{ object.name or 'n/a' }})</field>
|
||||
<field name="description">Sent to customers with their invoices in attachment</field>
|
||||
<field name="body_html" type="html">
|
||||
<div style="margin: 0px; padding: 0px;">
|
||||
<p style="margin: 0px; padding: 0px; font-size: 13px;">
|
||||
Dear
|
||||
<t t-if="object.partner_id.parent_id">
|
||||
<t t-out="object.partner_id.name or ''">Brandon Freeman</t> (<t t-out="object.partner_id.parent_id.name or ''">Azure Interior</t>),
|
||||
</t>
|
||||
<t t-else="">
|
||||
<t t-out="object.partner_id.name or ''">Brandon Freeman</t>,
|
||||
</t>
|
||||
<br /><br />
|
||||
Here is your
|
||||
<t t-if="object.name">
|
||||
invoice <span style="font-weight:bold;" t-out="object.name or ''">INV/2021/05/0005</span>
|
||||
</t>
|
||||
<t t-else="">
|
||||
invoice
|
||||
</t>
|
||||
<t t-if="object.invoice_origin">
|
||||
(with reference: <t t-out="object.invoice_origin or ''">SUB003</t>)
|
||||
</t>
|
||||
amounting in <span style="font-weight:bold;" t-out="format_amount(object.amount_total, object.currency_id) or ''">$ 143,750.00</span>
|
||||
from <t t-out="object.company_id.name or ''">YourCompany</t>.
|
||||
<t t-if="object.payment_state in ('paid', 'in_payment')">
|
||||
This invoice is already paid.
|
||||
</t>
|
||||
<t t-else="">
|
||||
Please remit payment at your earliest convenience.
|
||||
<t t-if="object.payment_reference">
|
||||
<br /><br />
|
||||
Please use the following communication for your payment: <span style="font-weight:bold;" t-out="object.payment_reference or ''">INV/2021/05/0005</span>.
|
||||
</t>
|
||||
</t>
|
||||
<t t-if="hasattr(object, 'timesheet_count') and object.timesheet_count">
|
||||
<br /><br />
|
||||
PS: you can review your timesheets <a t-att-href="'my/timesheets?search_in=invoice&search=%s' % object.name">from the portal.</a>
|
||||
</t>
|
||||
<br /><br />
|
||||
Do not hesitate to contact us if you have any questions.
|
||||
<t t-if="not is_html_empty(object.invoice_user_id.signature)">
|
||||
<br /><br />
|
||||
<t t-out="object.invoice_user_id.signature or ''">--<br/>Mitchell Admin</t>
|
||||
</t>
|
||||
</p>
|
||||
</div>
|
||||
</field>
|
||||
<field name="report_template_ids" eval="[(4, ref('account.account_invoices'))]"/>
|
||||
<field name="lang">{{ object.partner_id.lang }}</field>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="mail_template_data_payment_receipt" model="mail.template">
|
||||
<field name="name">Payment: Payment Receipt</field>
|
||||
<field name="model_id" ref="account.model_account_payment"/>
|
||||
<field name="subject">{{ object.company_id.name }} Payment Receipt (Ref {{ object.name or 'n/a' }})</field>
|
||||
<field name="partner_to">{{ object.partner_id.id }}</field>
|
||||
<field name="description">Sent manually to customer when clicking on 'Send receipt by email' in payment action</field>
|
||||
<field name="body_html" type="html">
|
||||
<div style="margin: 0px; padding: 0px;">
|
||||
<p style="margin: 0px; padding: 0px; font-size: 13px;">
|
||||
Dear <t t-out="object.partner_id.name or ''">Azure Interior</t><br/><br/>
|
||||
Thank you for your payment.
|
||||
Here is your payment receipt <span style="font-weight:bold;" t-out="(object.name or '').replace('/','-') or ''">BNK1-2021-05-0002</span> amounting
|
||||
to <span style="font-weight:bold;" t-out="format_amount(object.amount, object.currency_id) or ''">$ 10.00</span> from <t t-out="object.company_id.name or ''">YourCompany</t>.
|
||||
<br/><br/>
|
||||
Do not hesitate to contact us if you have any questions.
|
||||
<br/><br/>
|
||||
Best regards,
|
||||
<t t-if="not is_html_empty(user.signature)">
|
||||
<br/><br/>
|
||||
<t t-out="user.signature or ''">--<br/>Mitchell Admin</t>
|
||||
</t>
|
||||
</p>
|
||||
</div>
|
||||
</field>
|
||||
<field name="report_template_ids" eval="[(4, ref('account.action_report_payment_receipt'))]"/>
|
||||
<field name="lang">{{ object.partner_id.lang }}</field>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
</record>
|
||||
<!-- Credit note template -->
|
||||
<record id="email_template_edi_credit_note" model="mail.template">
|
||||
<field name="name">Credit Note: Sending</field>
|
||||
<field name="model_id" ref="account.model_account_move"/>
|
||||
<field name="email_from">{{ (object.invoice_user_id.email_formatted or object.company_id.email_formatted or user.email_formatted) }}</field>
|
||||
<field name="partner_to">{{ object.partner_id.id }}</field>
|
||||
<field name="subject">{{ object.company_id.name }} Credit Note (Ref {{ object.name or 'n/a' }})</field>
|
||||
<field name="description">Sent to customers with the credit note in attachment</field>
|
||||
<field name="body_html" type="html">
|
||||
<div style="margin: 0px; padding: 0px;">
|
||||
<p style="margin: 0px; padding: 0px; font-size: 13px;">
|
||||
Dear
|
||||
<t t-if="object.partner_id.parent_id">
|
||||
<t t-out="object.partner_id.name or ''">Brandon Freeman</t> (<t t-out="object.partner_id.parent_id.name or ''">Azure Interior</t>),
|
||||
</t>
|
||||
<t t-else="">
|
||||
<t t-out="object.partner_id.name or ''">Brandon Freeman</t>,
|
||||
</t>
|
||||
<br /><br />
|
||||
Here is your
|
||||
<t t-if="object.name">
|
||||
credit note <span style="font-weight:bold;" t-out="object.name or ''">RINV/2021/05/0001</span>
|
||||
</t>
|
||||
<t t-else="">
|
||||
credit note
|
||||
</t>
|
||||
<t t-if="object.invoice_origin">
|
||||
(with reference: <t t-out="object.invoice_origin or ''">SUB003</t>)
|
||||
</t>
|
||||
amounting in <span style="font-weight:bold;" t-out="format_amount(object.amount_total, object.currency_id) or ''">$ 143,750.00</span>
|
||||
from <t t-out="object.company_id.name or ''">YourCompany</t>.
|
||||
<br /><br />
|
||||
Do not hesitate to contact us if you have any questions.
|
||||
<t t-if="not is_html_empty(object.invoice_user_id.signature)">
|
||||
<br /><br />
|
||||
<t t-out="object.invoice_user_id.signature or ''">--<br/>Mitchell Admin</t>
|
||||
</t>
|
||||
</p>
|
||||
</div>
|
||||
</field>
|
||||
<field name="report_template_ids" eval="[(4, ref('account.account_invoices'))]"/>
|
||||
<field name="lang">{{ object.partner_id.lang }}</field>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
134
data/onboarding_data.xml
Normal file
134
data/onboarding_data.xml
Normal file
@ -0,0 +1,134 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<!-- ONBOARDING STEPS -->
|
||||
<!-- INVOICING -->
|
||||
<record id="onboarding_onboarding_step_company_data" model="onboarding.onboarding.step">
|
||||
<field name="title">Company Data</field>
|
||||
<field name="description">Set your company's data for documents header/footer.</field>
|
||||
<field name="button_text">Let's start!</field>
|
||||
<field name="done_text">Looks great!</field>
|
||||
<field name="panel_step_open_action_name">action_open_step_company_data</field>
|
||||
<field name="step_image" type="base64" file="base/static/img/onboarding_company-data.png"></field>
|
||||
<field name="step_image_filename">onboarding_company-data.png</field>
|
||||
<field name="step_image_alt">Onboarding Company Data</field>
|
||||
<field name="sequence">1</field>
|
||||
</record>
|
||||
|
||||
<record id="onboarding_onboarding_step_base_document_layout" model="onboarding.onboarding.step">
|
||||
<field name="title">Documents Layout</field>
|
||||
<field name="description">Customize the look of your documents.</field>
|
||||
<field name="button_text">Customize</field>
|
||||
<field name="done_text">Looks great!</field>
|
||||
<field name="panel_step_open_action_name">action_open_step_base_document_layout</field>
|
||||
<field name="step_image" type="base64" file="base/static/img/onboarding_quotation-layout.png"></field>
|
||||
<field name="step_image_filename">onboarding_quotation-layout.png</field>
|
||||
<field name="step_image_alt">Onboarding Documents Layout</field>
|
||||
<field name="sequence">3</field>
|
||||
</record>
|
||||
|
||||
<record id="onboarding_onboarding_step_create_invoice" model="onboarding.onboarding.step">
|
||||
<field name="title">Create Invoice</field>
|
||||
<field name="description">Create your first invoice.</field>
|
||||
<field name="button_text">Create</field>
|
||||
<field name="done_text">First invoice sent!</field>
|
||||
<field name="panel_step_open_action_name">action_open_step_create_invoice</field>
|
||||
<field name="step_image" type="base64" file="base/static/img/onboarding_default.png"></field>
|
||||
<field name="step_image_filename">onboarding_default.png</field>
|
||||
<field name="step_image_alt">Onboarding Create Invoice</field>
|
||||
<field name="sequence">4</field>
|
||||
</record>
|
||||
|
||||
<!-- DASHBOARD -->
|
||||
<record id="onboarding_onboarding_step_fiscal_year" model="onboarding.onboarding.step">
|
||||
<field name="title">Accounting Periods</field>
|
||||
<field name="description">Define your fiscal years & tax returns periodicity.</field>
|
||||
<field name="button_text">Configure</field>
|
||||
<field name="done_text">Step completed!</field>
|
||||
<field name="panel_step_open_action_name">action_open_step_fiscal_year</field>
|
||||
<field name="step_image" type="base64" file="base/static/img/onboarding_accounting-periods.png"></field>
|
||||
<field name="step_image_filename">onboarding_accounting-periods.png</field>
|
||||
<field name="step_image_alt">Onboarding Accounting Periods</field>
|
||||
<field name="sequence">1</field>
|
||||
</record>
|
||||
|
||||
<record id="onboarding_onboarding_step_bank_account" model="onboarding.onboarding.step">
|
||||
<field name="title">Bank Account</field>
|
||||
<field name="description">Connect your financial accounts in seconds.</field>
|
||||
<field name="button_text">Add a bank account</field>
|
||||
<field name="done_text">Step Completed!</field>
|
||||
<field name="panel_step_open_action_name">action_open_step_bank_account</field>
|
||||
<field name="step_image" type="base64" file="base/static/img/onboarding_puzzle.png"></field>
|
||||
<field name="step_image_filename">onboarding_puzzle.png</field>
|
||||
<field name="step_image_alt">Onboarding Bank Account</field>
|
||||
<field name="sequence">2</field>
|
||||
</record>
|
||||
|
||||
<record id="onboarding_onboarding_step_default_taxes" model="onboarding.onboarding.step">
|
||||
<field name="title">Taxes</field>
|
||||
<field name="description">Set default Taxes for sales and purchase transactions.</field>
|
||||
<field name="button_text">Review</field>
|
||||
<field name="done_text">Taxes set!</field>
|
||||
<field name="panel_step_open_action_name">action_open_step_default_taxes</field>
|
||||
<field name="step_image" type="base64" file="base/static/img/onboarding_taxes.png"></field>
|
||||
<field name="step_image_filename">onboarding_taxes.png</field>
|
||||
<field name="step_image_alt">Onboarding Taxes</field>
|
||||
<field name="sequence">3</field>
|
||||
</record>
|
||||
|
||||
<record id="onboarding_onboarding_step_chart_of_accounts" model="onboarding.onboarding.step">
|
||||
<field name="title">Chart of Accounts</field>
|
||||
<field name="description">Set up your chart of accounts and record initial balances.</field>
|
||||
<field name="button_text">Review</field>
|
||||
<field name="done_text">Chart of accounts set!</field>
|
||||
<field name="panel_step_open_action_name">action_open_step_chart_of_accounts</field>
|
||||
<field name="step_image" type="base64" file="base/static/img/onboarding_chart-of-accounts.png"></field>
|
||||
<field name="step_image_filename">onboarding_chart-of-accounts.png</field>
|
||||
<field name="step_image_alt">Onboarding Bank Account</field>
|
||||
<field name="sequence">4</field>
|
||||
</record>
|
||||
|
||||
<!-- WITHOUT PANEL -->
|
||||
<record id="onboarding_onboarding_step_setup_bill" model="onboarding.onboarding.step">
|
||||
<field name="title">Import Vendor Bills</field>
|
||||
<field name="sequence">1000</field>
|
||||
</record>
|
||||
|
||||
<record id="onboarding_onboarding_step_sales_tax" model="onboarding.onboarding.step">
|
||||
<field name="title">Taxes</field>
|
||||
<!-- Fields values used if/when added in a panel within other modules -->
|
||||
<field name="description">Choose a default sales tax for your products.</field>
|
||||
<field name="button_text">Set taxes</field>
|
||||
<field name="done_text">Step Completed!</field>
|
||||
<field name="panel_step_open_action_name">action_open_step_sales_tax</field>
|
||||
<field name="step_image" type="base64" file="base/static/img/onboarding_puzzle.png"></field>
|
||||
<field name="step_image_filename">onboarding_puzzle.png</field>
|
||||
<field name="step_image_alt">Onboarding Bank Account</field>
|
||||
<field name="sequence">100</field> <!-- after "Online Payment" -->
|
||||
</record>
|
||||
|
||||
<!-- ONBOARDING PANELS -->
|
||||
<record id="onboarding_onboarding_account_invoice" model="onboarding.onboarding">
|
||||
<field name="name">Invoicing Onboarding</field>
|
||||
<field name="step_ids" eval="[
|
||||
Command.link(ref('account.onboarding_onboarding_step_company_data')),
|
||||
Command.link(ref('account.onboarding_onboarding_step_base_document_layout')),
|
||||
Command.link(ref('account.onboarding_onboarding_step_create_invoice'))
|
||||
]"/>
|
||||
<field name="route_name">account_invoice</field>
|
||||
<field name="panel_close_action_name">action_close_panel_account_invoice</field>
|
||||
</record>
|
||||
|
||||
<record id="onboarding_onboarding_account_dashboard" model="onboarding.onboarding">
|
||||
<field name="name">Account Dashboard Onboarding</field>
|
||||
<field name="step_ids" eval="[
|
||||
Command.link(ref('account.onboarding_onboarding_step_fiscal_year')),
|
||||
Command.link(ref('account.onboarding_onboarding_step_bank_account')),
|
||||
Command.link(ref('account.onboarding_onboarding_step_default_taxes')),
|
||||
Command.link(ref('account.onboarding_onboarding_step_chart_of_accounts'))
|
||||
]"/>
|
||||
<field name="route_name">account_dashboard</field>
|
||||
<field name="panel_close_action_name">action_close_panel_account_dashboard</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
25
data/service_cron.xml
Normal file
25
data/service_cron.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="ir_cron_auto_post_draft_entry" model="ir.cron">
|
||||
<field name="name">Account: Post draft entries with auto_post enabled and accounting date up to today</field>
|
||||
<field name="interval_number">1</field>
|
||||
<field name="interval_type">days</field>
|
||||
<field name="numbercall">-1</field>
|
||||
<field name="nextcall" eval="(DateTime.now().replace(hour=2, minute=0) + timedelta(days=1)).strftime('%Y-%m-%d %H:%M:%S')" />
|
||||
<field name="doall" eval="False"/>
|
||||
<field name="model_id" ref="model_account_move"/>
|
||||
<field name="code">model._autopost_draft_entries()</field>
|
||||
<field name="state">code</field>
|
||||
</record>
|
||||
|
||||
<record id="ir_cron_account_move_send" model="ir.cron">
|
||||
<field name="name">Send invoices automatically</field>
|
||||
<field name="model_id" ref="model_account_move"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">model._cron_account_move_send(job_count=20)</field>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="interval_number">1</field>
|
||||
<field name="interval_type">days</field>
|
||||
<field name="numbercall">-1</field>
|
||||
</record>
|
||||
</odoo>
|
41
data/template/account.account-generic_coa.csv
Normal file
41
data/template/account.account-generic_coa.csv
Normal file
@ -0,0 +1,41 @@
|
||||
"id","name","code","account_type","tag_ids","reconcile"
|
||||
"current_assets","Current Assets","1010","asset_current","","False"
|
||||
"stock_valuation","Stock Valuation","1101","asset_current","","False"
|
||||
"stock_in","Stock Interim (Received)","1102","asset_current","","True"
|
||||
"stock_out","Stock Interim (Delivered)","1103","asset_current","","True"
|
||||
"cost_of_production","Cost of Production","1104","asset_current","","True"
|
||||
"receivable","Account Receivable","1210","asset_receivable","","True"
|
||||
"to_receive_rec","Products to receive","1211","asset_current","","True"
|
||||
"tax_paid","Tax Paid","1310","asset_current","","False"
|
||||
"tax_receivable","Tax Receivable","1320","asset_current","","False"
|
||||
"prepayments","Prepayments","1410","asset_prepayments","","False"
|
||||
"fixed_assets","Fixed Asset","1510","asset_fixed","","False"
|
||||
"non_current_assets","Non-current assets","1910","asset_non_current","","False"
|
||||
"current_liabilities","Current Liabilities","2010","liability_current","","False"
|
||||
"payable","Account Payable","2110","liability_payable","","True"
|
||||
"to_receive_pay","Bills to receive","2111","liability_current","","True"
|
||||
"salary_payable","Salary Payable","2300","liability_current","","True"
|
||||
"employee_payroll_taxes","Employee Payroll Taxes","2301","liability_current","","True"
|
||||
"employer_payroll_taxes","Employer Payroll Taxes","2302","liability_current","","True"
|
||||
"tax_received","Tax Received","2510","liability_current","","False"
|
||||
"tax_payable","Tax Payable","2520","liability_current","","False"
|
||||
"non_current_liabilities","Non-current Liabilities","2910","liability_non_current","","False"
|
||||
"capital","Capital","3010","equity","","False"
|
||||
"dividends","Dividends","3020","equity","","False"
|
||||
"income","Product Sales","4000","income","account.account_tag_operating","False"
|
||||
"income_currency_exchange","Foreign Exchange Gain","4410","income","account.account_tag_financing","False"
|
||||
"cash_diff_income","Cash Difference Gain","4420","income","account.account_tag_investing","False"
|
||||
"cash_discount_loss","Cash Discount Loss","4430","expense","","False"
|
||||
"other_income","Other Income","4500","income_other","","False"
|
||||
"cost_of_goods_sold","Cost of Goods Sold","5000","expense_direct_cost","account.account_tag_operating","False"
|
||||
"expense","Expenses","6000","expense","account.account_tag_operating","False"
|
||||
"expense_invest","Purchase of Equipments","6110","expense","account.account_tag_investing","False"
|
||||
"expense_rent","Rent","6120","expense","account.account_tag_investing","False"
|
||||
"expense_finance","Bank Fees","6200","expense","account.account_tag_financing","False"
|
||||
"expense_salary","Salary Expenses","6300","expense","account.account_tag_operating","False"
|
||||
"expense_currency_exchange","Foreign Exchange Loss","6410","expense","account.account_tag_financing","False"
|
||||
"cash_diff_expense","Cash Difference Loss","6420","expense","account.account_tag_investing","False"
|
||||
"cash_discount_gain","Cash Discount Gain","6430","income","","False"
|
||||
"expense_rd","RD Expenses","9610","expense","account.account_tag_investing","False"
|
||||
"expense_sales","Sales Expenses","9620","expense","account.account_tag_investing","False"
|
||||
"pos_receivable","Account Receivable (PoS)","1013","asset_receivable","","True"
|
|
9
data/template/account.tax-generic_coa.csv
Normal file
9
data/template/account.tax-generic_coa.csv
Normal file
@ -0,0 +1,9 @@
|
||||
"id","name","description","invoice_label","amount","type_tax_use","tax_group_id","repartition_line_ids/document_type","repartition_line_ids/factor_percent","repartition_line_ids/repartition_type","repartition_line_ids/account_id"
|
||||
"sale_tax_template","15%","","","15","sale","tax_group_15","invoice","100","base",""
|
||||
"","","","","","","","invoice","100","tax","tax_received"
|
||||
"","","","","","","","refund","100","base",""
|
||||
"","","","","","","","refund","100","tax","tax_received"
|
||||
"purchase_tax_template","15%","","","15","purchase","tax_group_15","invoice","100","base",""
|
||||
"","","","","","","","invoice","100","tax","tax_paid"
|
||||
"","","","","","","","refund","100","base",""
|
||||
"","","","","","","","refund","100","tax","tax_paid"
|
|
2
data/template/account.tax.group-generic_coa.csv
Normal file
2
data/template/account.tax.group-generic_coa.csv
Normal file
@ -0,0 +1,2 @@
|
||||
id,name,country_id,tax_payable_account_id,tax_receivable_account_id
|
||||
tax_group_15,Tax 15%,base.us,tax_payable,tax_receivable
|
|
3
demo/__init__.py
Normal file
3
demo/__init__.py
Normal file
@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import account_demo
|
491
demo/account_demo.py
Normal file
491
demo/account_demo.py
Normal file
@ -0,0 +1,491 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
import time
|
||||
from datetime import timedelta
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from odoo import api, fields, models, Command
|
||||
from odoo.tools.misc import file_open, formatLang
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AccountChartTemplate(models.AbstractModel):
|
||||
_inherit = "account.chart.template"
|
||||
|
||||
@api.model
|
||||
def _get_demo_data(self, company=False):
|
||||
"""Generate the demo data related to accounting."""
|
||||
# This is a generator because data created here might be referenced by xml_id to data
|
||||
# created later but defined in this same function.
|
||||
self._get_demo_data_products(company)
|
||||
return {
|
||||
'account.move': self._get_demo_data_move(company),
|
||||
'account.bank.statement': self._get_demo_data_statement(company),
|
||||
'account.bank.statement.line': self._get_demo_data_transactions(company),
|
||||
'account.reconcile.model': self._get_demo_data_reconcile_model(company),
|
||||
'ir.attachment': self._get_demo_data_attachment(company),
|
||||
'mail.message': self._get_demo_data_mail_message(company),
|
||||
'mail.activity': self._get_demo_data_mail_activity(company),
|
||||
}
|
||||
|
||||
def _post_load_demo_data(self, company=False):
|
||||
invoices = (
|
||||
self.ref('demo_invoice_1')
|
||||
+ self.ref('demo_invoice_2')
|
||||
+ self.ref('demo_invoice_3')
|
||||
+ self.ref('demo_invoice_followup')
|
||||
+ self.ref('demo_invoice_5')
|
||||
+ self.ref('demo_invoice_equipment_purchase')
|
||||
+ self.ref('demo_move_auto_reconcile_1')
|
||||
+ self.ref('demo_move_auto_reconcile_2')
|
||||
+ self.ref('demo_move_auto_reconcile_3')
|
||||
+ self.ref('demo_move_auto_reconcile_4')
|
||||
+ self.ref('demo_move_auto_reconcile_5')
|
||||
+ self.ref('demo_move_auto_reconcile_6')
|
||||
+ self.ref('demo_move_auto_reconcile_7')
|
||||
+ self.ref('demo_move_auto_reconcile_8')
|
||||
+ self.ref('demo_move_auto_reconcile_9')
|
||||
)
|
||||
|
||||
# the invoice_extract acts like a placeholder for the OCR to be ran and doesn't contain
|
||||
# any lines yet
|
||||
for move in invoices:
|
||||
try:
|
||||
move.action_post()
|
||||
except (UserError, ValidationError):
|
||||
_logger.exception('Error while posting demo data')
|
||||
|
||||
@api.model
|
||||
def _get_demo_data_products(self, company=False):
|
||||
prod_templates = self.env['product.product'].search(self.env['product.product']._check_company_domain(company))
|
||||
if self.env.company.account_sale_tax_id:
|
||||
prod_templates_sale = prod_templates.filtered(
|
||||
lambda p: not p.taxes_id.filtered_domain(p.taxes_id._check_company_domain(company)))
|
||||
prod_templates_sale.write({'taxes_id': [Command.link(self.env.company.account_sale_tax_id.id)]})
|
||||
if self.env.company.account_purchase_tax_id:
|
||||
prod_templates_purchase = prod_templates.filtered(
|
||||
lambda p: not p.supplier_taxes_id.filtered_domain(p.taxes_id._check_company_domain(company)))
|
||||
prod_templates_purchase.write({'supplier_taxes_id': [Command.link(self.env.company.account_purchase_tax_id.id)]})
|
||||
|
||||
@api.model
|
||||
def _get_demo_data_move(self, company=False):
|
||||
one_month_ago = fields.Date.today() + relativedelta(months=-1)
|
||||
fifteen_months_ago = fields.Date.today() + relativedelta(months=-15)
|
||||
cid = company.id or self.env.company.id
|
||||
misc_journal = self.env['account.journal'].search(
|
||||
domain=[
|
||||
*self.env['account.journal']._check_company_domain(cid),
|
||||
('type', '=', 'general'),
|
||||
],
|
||||
limit=1,
|
||||
)
|
||||
bank_journal = self.env['account.journal'].search(
|
||||
domain=[
|
||||
*self.env['account.journal']._check_company_domain(cid),
|
||||
('type', '=', 'bank'),
|
||||
],
|
||||
limit=1,
|
||||
)
|
||||
default_receivable = self.env.ref('base.res_partner_3').with_company(company).property_account_receivable_id
|
||||
income_account = self.env['account.account'].search([
|
||||
('company_id', '=', cid),
|
||||
('account_type', '=', 'income'),
|
||||
('id', '!=', (company or self.env.company).account_journal_early_pay_discount_gain_account_id.id)
|
||||
], limit=1)
|
||||
return {
|
||||
'demo_invoice_1': {
|
||||
'move_type': 'out_invoice',
|
||||
'partner_id': 'base.res_partner_12',
|
||||
'invoice_user_id': 'base.user_demo',
|
||||
'invoice_payment_term_id': 'account.account_payment_term_end_following_month',
|
||||
'invoice_date': time.strftime('%Y-%m-01'),
|
||||
'delivery_date': time.strftime('%Y-%m-01'),
|
||||
'invoice_line_ids': [
|
||||
Command.create({'product_id': 'product.consu_delivery_02', 'quantity': 5}),
|
||||
Command.create({'product_id': 'product.consu_delivery_03', 'quantity': 5}),
|
||||
],
|
||||
},
|
||||
'demo_invoice_2': {
|
||||
'move_type': 'out_invoice',
|
||||
'partner_id': 'base.res_partner_2',
|
||||
'invoice_user_id': False,
|
||||
'invoice_date': (fields.Date.today() + timedelta(days=-2)).strftime('%Y-%m-%d'),
|
||||
'delivery_date': (fields.Date.today() + timedelta(days=-2)).strftime('%Y-%m-%d'),
|
||||
'invoice_line_ids': [
|
||||
Command.create({'product_id': 'product.consu_delivery_03', 'quantity': 5}),
|
||||
Command.create({'product_id': 'product.consu_delivery_01', 'quantity': 20}),
|
||||
],
|
||||
},
|
||||
'demo_invoice_3': {
|
||||
'move_type': 'out_invoice',
|
||||
'partner_id': 'base.res_partner_2',
|
||||
'invoice_user_id': False,
|
||||
'invoice_date': (fields.Date.today() + timedelta(days=-3)).strftime('%Y-%m-%d'),
|
||||
'delivery_date': (fields.Date.today() + timedelta(days=-3)).strftime('%Y-%m-%d'),
|
||||
'invoice_line_ids': [
|
||||
Command.create({'product_id': 'product.consu_delivery_01', 'quantity': 5}),
|
||||
Command.create({'product_id': 'product.consu_delivery_03', 'quantity': 5}),
|
||||
],
|
||||
},
|
||||
'demo_invoice_followup': {
|
||||
'move_type': 'out_invoice',
|
||||
'partner_id': 'base.res_partner_2',
|
||||
'invoice_user_id': 'base.user_demo',
|
||||
'invoice_payment_term_id': 'account.account_payment_term_immediate',
|
||||
'invoice_date': (fields.Date.today() + timedelta(days=-15)).strftime('%Y-%m-%d'),
|
||||
'delivery_date': (fields.Date.today() + timedelta(days=-15)).strftime('%Y-%m-%d'),
|
||||
'invoice_line_ids': [
|
||||
Command.create({'product_id': 'product.consu_delivery_02', 'quantity': 5}),
|
||||
Command.create({'product_id': 'product.consu_delivery_03', 'quantity': 5}),
|
||||
],
|
||||
},
|
||||
'demo_invoice_5': {
|
||||
'move_type': 'in_invoice',
|
||||
'partner_id': 'base.res_partner_12',
|
||||
'invoice_payment_term_id': 'account.account_payment_term_end_following_month',
|
||||
'invoice_date': time.strftime('%Y-%m-01'),
|
||||
'delivery_date': time.strftime('%Y-%m-01'),
|
||||
'invoice_line_ids': [
|
||||
Command.create({'product_id': 'product.product_delivery_01', 'price_unit': 10.0, 'quantity': 1}),
|
||||
Command.create({'product_id': 'product.product_order_01', 'price_unit': 4.0, 'quantity': 5}),
|
||||
],
|
||||
},
|
||||
'demo_invoice_extract': {
|
||||
'move_type': 'in_invoice',
|
||||
'message_main_attachment_id': 'ir_attachment_in_invoice_1',
|
||||
},
|
||||
'demo_invoice_equipment_purchase': {
|
||||
'move_type': 'in_invoice',
|
||||
'ref': f'INV/{fifteen_months_ago.year}/0057',
|
||||
'partner_id': 'base.res_partner_12',
|
||||
'invoice_user_id': False,
|
||||
'invoice_date': fifteen_months_ago.strftime("%Y-%m-17"),
|
||||
'delivery_date': fifteen_months_ago.strftime("%Y-%m-17"),
|
||||
'invoice_line_ids': [
|
||||
Command.create({'name': 'Redeem Reference Number: PO02529', 'quantity': 1, 'price_unit': 541.10,
|
||||
'tax_ids': self.env.company.account_purchase_tax_id.ids}),
|
||||
],
|
||||
'message_main_attachment_id': 'ir_attachment_in_invoice_2',
|
||||
},
|
||||
'demo_move_auto_reconcile_1': {
|
||||
'move_type': 'out_refund',
|
||||
'partner_id': 'base.res_partner_12',
|
||||
'invoice_date': one_month_ago.strftime("%Y-%m-02"),
|
||||
'delivery_date': one_month_ago.strftime("%Y-%m-02"),
|
||||
'invoice_line_ids': [
|
||||
Command.create({'product_id': 'product.consu_delivery_03', 'quantity': 5}),
|
||||
],
|
||||
},
|
||||
'demo_move_auto_reconcile_2': {
|
||||
'move_type': 'out_refund',
|
||||
'partner_id': 'base.res_partner_12',
|
||||
'invoice_date': one_month_ago.strftime("%Y-%m-03"),
|
||||
'delivery_date': one_month_ago.strftime("%Y-%m-03"),
|
||||
'invoice_line_ids': [
|
||||
Command.create({'product_id': 'product.consu_delivery_02', 'quantity': 5}),
|
||||
],
|
||||
},
|
||||
'demo_move_auto_reconcile_3': {
|
||||
'move_type': 'in_refund',
|
||||
'partner_id': 'base.res_partner_12',
|
||||
'invoice_date': time.strftime('%Y-%m-01'),
|
||||
'delivery_date': time.strftime('%Y-%m-01'),
|
||||
'invoice_line_ids': [
|
||||
Command.create({'product_id': 'product.product_delivery_01', 'price_unit': 10.0, 'quantity': 1}),
|
||||
Command.create({'product_id': 'product.product_order_01', 'price_unit': 4.0, 'quantity': 5}),
|
||||
],
|
||||
},
|
||||
'demo_move_auto_reconcile_4': {
|
||||
'move_type': 'in_refund',
|
||||
'partner_id': 'base.res_partner_12',
|
||||
'invoice_date': fifteen_months_ago.strftime("%Y-%m-19"),
|
||||
'delivery_date': fifteen_months_ago.strftime("%Y-%m-19"),
|
||||
'invoice_line_ids': [
|
||||
Command.create({'name': 'Redeem Reference Number: PO02529', 'quantity': 1, 'price_unit': 541.10,
|
||||
'tax_ids': self.env.company.account_purchase_tax_id.ids}),
|
||||
],
|
||||
},
|
||||
'demo_move_auto_reconcile_5': {
|
||||
'move_type': 'out_refund',
|
||||
'partner_id': 'base.res_partner_2',
|
||||
'invoice_date': (fields.Date.today() + timedelta(days=-10)).strftime('%Y-%m-%d'),
|
||||
'delivery_date': (fields.Date.today() + timedelta(days=-10)).strftime('%Y-%m-%d'),
|
||||
'invoice_line_ids': [
|
||||
Command.create({'product_id': 'product.consu_delivery_02', 'quantity': 5}),
|
||||
Command.create({'product_id': 'product.consu_delivery_03', 'quantity': 5}),
|
||||
],
|
||||
},
|
||||
'demo_move_auto_reconcile_6': {
|
||||
'move_type': 'out_refund',
|
||||
'partner_id': 'base.res_partner_2',
|
||||
'invoice_user_id': False,
|
||||
'invoice_date': (fields.Date.today() + timedelta(days=-1)).strftime('%Y-%m-%d'),
|
||||
'delivery_date': (fields.Date.today() + timedelta(days=-1)).strftime('%Y-%m-%d'),
|
||||
'invoice_line_ids': [
|
||||
Command.create({'product_id': 'product.consu_delivery_03', 'quantity': 5}),
|
||||
Command.create({'product_id': 'product.consu_delivery_01', 'quantity': 20}),
|
||||
],
|
||||
},
|
||||
'demo_move_auto_reconcile_7': {
|
||||
'move_type': 'out_refund',
|
||||
'partner_id': 'base.res_partner_2',
|
||||
'invoice_date': (fields.Date.today() + timedelta(days=-2)).strftime('%Y-%m-%d'),
|
||||
'delivery_date': (fields.Date.today() + timedelta(days=-2)).strftime('%Y-%m-%d'),
|
||||
'invoice_line_ids': [
|
||||
Command.create({'product_id': 'product.consu_delivery_01', 'quantity': 5}),
|
||||
Command.create({'product_id': 'product.consu_delivery_03', 'quantity': 5}),
|
||||
],
|
||||
},
|
||||
'demo_move_auto_reconcile_8': {
|
||||
'move_type': 'entry',
|
||||
'partner_id': 'base.res_partner_2',
|
||||
'date': (fields.Date.today() + timedelta(days=-20)).strftime('%Y-%m-%d'),
|
||||
'journal_id': misc_journal.id,
|
||||
'line_ids': [
|
||||
Command.create({'debit': 0.0, 'credit': 2500.0, 'account_id': default_receivable.id}),
|
||||
Command.create({'debit': 2500.0, 'credit': 0.0, 'account_id': bank_journal.default_account_id.id}),
|
||||
],
|
||||
},
|
||||
'demo_move_auto_reconcile_9': {
|
||||
'move_type': 'entry',
|
||||
'partner_id': 'base.res_partner_2',
|
||||
'date': (fields.Date.today() + timedelta(days=-20)).strftime('%Y-%m-%d'),
|
||||
'journal_id': misc_journal.id,
|
||||
'line_ids': [
|
||||
Command.create({'debit': 2500.0, 'credit': 0.0, 'account_id': default_receivable.id}),
|
||||
Command.create({'debit': 0.0, 'credit': 2500.0, 'account_id': income_account.id}),
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
@api.model
|
||||
def _get_demo_data_statement(self, company=False):
|
||||
cid = company.id or self.env.company.id
|
||||
bnk_journal = self.env['account.journal'].search(
|
||||
domain=[
|
||||
*self.env['account.journal']._check_company_domain(cid),
|
||||
('type', '=', 'bank'),
|
||||
],
|
||||
limit=1,
|
||||
)
|
||||
return {
|
||||
'demo_bank_statement_1': {
|
||||
'name': f'{bnk_journal.name} - {time.strftime("%Y")}-01-01/1',
|
||||
'balance_end_real': 6378.0,
|
||||
'balance_start': 0.0,
|
||||
'line_ids': [
|
||||
Command.create({
|
||||
'journal_id': bnk_journal.id,
|
||||
'payment_ref': 'Initial balance',
|
||||
'amount': 5103.0,
|
||||
'date': time.strftime('%Y-01-01'),
|
||||
}),
|
||||
Command.create({
|
||||
'journal_id': bnk_journal.id,
|
||||
'payment_ref': time.strftime('INV/%Y/00002 and INV/%Y/00003'),
|
||||
'amount': 1275.0,
|
||||
'date': time.strftime('%Y-01-01'),
|
||||
'partner_id': 'base.res_partner_12',
|
||||
}),
|
||||
]
|
||||
},
|
||||
}
|
||||
|
||||
@api.model
|
||||
def _get_demo_data_transactions(self, company=False):
|
||||
cid = company.id or self.env.company.id
|
||||
bnk_journal = self.env['account.journal'].search(
|
||||
domain=[
|
||||
*self.env['account.journal']._check_company_domain(cid),
|
||||
('type', '=', 'bank'),
|
||||
],
|
||||
limit=1,
|
||||
)
|
||||
return {
|
||||
'demo_bank_statement_line_0': {
|
||||
'journal_id': bnk_journal.id,
|
||||
'payment_ref': 'Bank Fees',
|
||||
'amount': -32.58,
|
||||
'date': time.strftime('%Y-01-01'),
|
||||
},
|
||||
'demo_bank_statement_line_1': {
|
||||
'journal_id': bnk_journal.id,
|
||||
'payment_ref': 'Prepayment',
|
||||
'amount': 650,
|
||||
'date': time.strftime('%Y-01-01'),
|
||||
'partner_id': 'base.res_partner_12',
|
||||
},
|
||||
'demo_bank_statement_line_2': {
|
||||
'journal_id': bnk_journal.id,
|
||||
'payment_ref': time.strftime(f'First {formatLang(self.env, 2000, currency_obj=self.env.company.currency_id)} of invoice %Y/00001'),
|
||||
'amount': 2000,
|
||||
'date': time.strftime('%Y-01-01'),
|
||||
'partner_id': 'base.res_partner_12',
|
||||
},
|
||||
'demo_bank_statement_line_3': {
|
||||
'journal_id': bnk_journal.id,
|
||||
'payment_ref': 'Last Year Interests',
|
||||
'amount': 102.78,
|
||||
'date': time.strftime('%Y-01-01'),
|
||||
},
|
||||
'demo_bank_statement_line_4': {
|
||||
'journal_id': bnk_journal.id,
|
||||
'payment_ref': time.strftime('INV/%Y/00002'),
|
||||
'amount': 750,
|
||||
'date': time.strftime('%Y-01-01'),
|
||||
'partner_id': 'base.res_partner_2',
|
||||
},
|
||||
'demo_bank_statement_line_5': {
|
||||
'journal_id': bnk_journal.id,
|
||||
'payment_ref': f'R:9772938 10/07 AX 9415116318 T:5 BRT: {formatLang(self.env, 100.0, digits=2)} C/ croip',
|
||||
'amount': 96.67,
|
||||
'date': time.strftime('%Y-01-01'),
|
||||
},
|
||||
}
|
||||
|
||||
@api.model
|
||||
def _get_demo_data_reconcile_model(self, company=False):
|
||||
return {
|
||||
'reconcile_from_label': {
|
||||
'name': 'Line with Bank Fees',
|
||||
'rule_type': 'writeoff_suggestion',
|
||||
'match_label': 'contains',
|
||||
'match_label_param': 'BRT',
|
||||
'line_ids': [
|
||||
Command.create({
|
||||
'label': 'Due amount',
|
||||
'account_id': self._get_demo_account(
|
||||
'income',
|
||||
'income',
|
||||
self.env.company,
|
||||
).id,
|
||||
'amount_type': 'regex',
|
||||
'amount_string': r'BRT: ([\d,.]+)',
|
||||
}),
|
||||
Command.create({
|
||||
'label': 'Bank Fees',
|
||||
'account_id': self._get_demo_account(
|
||||
'cost_of_goods_sold',
|
||||
'expense_direct_cost',
|
||||
self.env.company,
|
||||
).id,
|
||||
'amount_type': 'percentage',
|
||||
'amount_string': '100',
|
||||
}),
|
||||
]
|
||||
},
|
||||
}
|
||||
|
||||
@api.model
|
||||
def _get_demo_data_attachment(self, company=False):
|
||||
return {
|
||||
'ir_attachment_in_invoice_1': {
|
||||
'type': 'binary',
|
||||
'name': 'in_invoice_yourcompany_demo.pdf',
|
||||
'res_model': 'account.move',
|
||||
'res_id': 'demo_invoice_extract',
|
||||
'raw': file_open(
|
||||
'account/static/demo/in_invoice_yourcompany_demo_1.pdf', 'rb'
|
||||
).read()
|
||||
},
|
||||
'ir_attachment_in_invoice_2': {
|
||||
'type': 'binary',
|
||||
'name': 'in_invoice_yourcompany_demo.pdf',
|
||||
'res_model': 'account.move',
|
||||
'res_id': 'demo_invoice_equipment_purchase',
|
||||
'raw': file_open(
|
||||
'account/static/demo/in_invoice_yourcompany_demo_2.pdf', 'rb'
|
||||
).read()
|
||||
},
|
||||
}
|
||||
|
||||
@api.model
|
||||
def _get_demo_data_mail_message(self, company=False):
|
||||
return {
|
||||
'mail_message_in_invoice_1': {
|
||||
'model': 'account.move',
|
||||
'res_id': 'demo_invoice_extract',
|
||||
'body': 'Vendor Bill attachment',
|
||||
'message_type': 'comment',
|
||||
'author_id': 'base.partner_demo',
|
||||
'attachment_ids': [Command.set([
|
||||
'ir_attachment_in_invoice_1',
|
||||
])]
|
||||
},
|
||||
'mail_message_in_invoice_2': {
|
||||
'model': 'account.move',
|
||||
'res_id': 'demo_invoice_equipment_purchase',
|
||||
'body': 'Vendor Bill attachment',
|
||||
'message_type': 'comment',
|
||||
'author_id': 'base.partner_demo',
|
||||
'attachment_ids': [Command.set([
|
||||
'ir_attachment_in_invoice_2',
|
||||
])]
|
||||
},
|
||||
}
|
||||
|
||||
@api.model
|
||||
def _get_demo_data_mail_activity(self, company=False):
|
||||
return {
|
||||
'invoice_activity_1': {
|
||||
'res_id': 'demo_invoice_3',
|
||||
'res_model_id': 'account.model_account_move',
|
||||
'activity_type_id': 'mail.mail_activity_data_todo',
|
||||
'date_deadline': (fields.Datetime.today() + relativedelta(days=5)).strftime('%Y-%m-%d %H:%M'),
|
||||
'summary': 'Follow-up on payment',
|
||||
'create_uid': 'base.user_admin',
|
||||
'user_id': 'base.user_admin',
|
||||
},
|
||||
'invoice_activity_2': {
|
||||
'res_id': 'demo_invoice_2',
|
||||
'res_model_id': 'account.model_account_move',
|
||||
'activity_type_id': 'mail.mail_activity_data_call',
|
||||
'date_deadline': fields.Datetime.today().strftime('%Y-%m-%d %H:%M'),
|
||||
'create_uid': 'base.user_admin',
|
||||
'user_id': 'base.user_admin',
|
||||
},
|
||||
'invoice_activity_3': {
|
||||
'res_id': 'demo_invoice_1',
|
||||
'res_model_id': 'account.model_account_move',
|
||||
'activity_type_id': 'mail.mail_activity_data_todo',
|
||||
'date_deadline': (fields.Datetime.today() + relativedelta(days=5)).strftime('%Y-%m-%d %H:%M'),
|
||||
'summary': 'Include upsell',
|
||||
'create_uid': 'base.user_admin',
|
||||
'user_id': 'base.user_admin',
|
||||
},
|
||||
'invoice_activity_4': {
|
||||
'res_id': 'demo_invoice_extract',
|
||||
'res_model_id': 'account.model_account_move',
|
||||
'activity_type_id': 'mail.mail_activity_data_todo',
|
||||
'date_deadline': (fields.Datetime.today() + relativedelta(days=5)).strftime('%Y-%m-%d %H:%M'),
|
||||
'summary': 'Update address',
|
||||
'create_uid': 'base.user_admin',
|
||||
'user_id': 'base.user_admin',
|
||||
},
|
||||
}
|
||||
|
||||
@api.model
|
||||
def _get_demo_account(self, xml_id, account_type, company):
|
||||
"""Find the most appropriate account possible for demo data creation.
|
||||
|
||||
:param xml_id (str): the xml_id of the account template in the generic coa
|
||||
:param account_type (str): the full xml_id of the account type wanted
|
||||
:param company (Model<res.company>): the company for which we search the account
|
||||
:return (Model<account.account>): the most appropriate record found
|
||||
"""
|
||||
return (
|
||||
self.env['account.account'].browse(self.env['ir.model.data'].sudo().search([
|
||||
('name', '=', '%d_%s' % (company.id, xml_id)),
|
||||
('model', '=', 'account.account'),
|
||||
('module', '=like', 'l10n%')
|
||||
], limit=1).res_id)
|
||||
or self.env['account.account'].search([
|
||||
*self.env['account.account']._check_company_domain(company),
|
||||
('account_type', '=', account_type),
|
||||
], limit=1)
|
||||
or self.env['account.account'].search([
|
||||
*self.env['account.account']._check_company_domain(company),
|
||||
], limit=1)
|
||||
)
|
66
demo/account_demo.xml
Normal file
66
demo/account_demo.xml
Normal file
@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record id="base.user_demo" model="res.users">
|
||||
<field name="groups_id" eval="[(3, ref('account.group_account_manager'))]"/>
|
||||
</record>
|
||||
</data>
|
||||
<data>
|
||||
<function model="account.chart.template" name="try_loading">
|
||||
<value eval="[]"/>
|
||||
<value>generic_coa</value>
|
||||
<value model="res.company" search="[('partner_id.country_id.code', 'in', ['US', False])]"/>
|
||||
</function>
|
||||
|
||||
<!-- TAGS FOR RETRIEVING THE DEMO ACCOUNTS -->
|
||||
<record id="demo_capital_account" model="account.account.tag">
|
||||
<field name="name">Demo Capital Account</field>
|
||||
</record>
|
||||
<record id="demo_stock_account" model="account.account.tag">
|
||||
<field name="name">Demo Stock Account</field>
|
||||
</record>
|
||||
<record id="demo_sale_of_land_account" model="account.account.tag">
|
||||
<field name="name">Demo Sale of Land Account</field>
|
||||
</record>
|
||||
<record id="demo_ceo_wages_account" model="account.account.tag">
|
||||
<field name="name">Demo CEO Wages Account</field>
|
||||
</record>
|
||||
<record id="demo_office_furniture_account" model="account.account.tag">
|
||||
<field name="name">Office Furniture</field>
|
||||
</record>
|
||||
<!-- Payment Terms -->
|
||||
|
||||
<record id="account_payment_term_advance" model="account.payment.term">
|
||||
<field name="name">30% Advance End of Following Month</field>
|
||||
<field name="note">Payment terms: 30% Advance End of Following Month</field>
|
||||
<field name="line_ids" eval="[
|
||||
Command.clear(),
|
||||
Command.create({'value': 'percent', 'value_amount': 30.0, 'nb_days': 0}),
|
||||
Command.create({'value': 'percent', 'value_amount': 70.0, 'delay_type': 'days_after_end_of_next_month','nb_days': 0})]"/>
|
||||
</record>
|
||||
|
||||
<!-- Add Payment terms on some demo partners -->
|
||||
<record id="base.res_partner_2" model="res.partner">
|
||||
<field name="property_payment_term_id" ref="account.account_payment_term_30days"/>
|
||||
</record>
|
||||
<record id="base.res_partner_12" model="res.partner">
|
||||
<field name="property_payment_term_id" ref="account.account_payment_term_end_following_month"/>
|
||||
<field name="property_supplier_payment_term_id" ref="account.account_payment_term_end_following_month"/>
|
||||
</record>
|
||||
<record id="base.res_partner_4" model="res.partner">
|
||||
<field name="property_supplier_payment_term_id" ref="account.account_payment_term_30days"/>
|
||||
</record>
|
||||
<record id="base.res_partner_1" model="res.partner">
|
||||
<field name="property_supplier_payment_term_id" ref="account.account_payment_term_end_following_month"/>
|
||||
</record>
|
||||
|
||||
<!-- Analytic -->
|
||||
<record id="analytic.analytic_plan_internal" model="account.analytic.plan">
|
||||
<field name="applicability_ids" eval="[
|
||||
Command.create({
|
||||
'business_domain': 'invoice',
|
||||
'account_prefix': '450000',
|
||||
'applicability': 'mandatory'})]"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
BIN
doc/account_anglo_saxon.ods
Normal file
BIN
doc/account_anglo_saxon.ods
Normal file
Binary file not shown.
BIN
doc/account_anglo_saxon.pdf
Normal file
BIN
doc/account_anglo_saxon.pdf
Normal file
Binary file not shown.
16786
i18n/account.pot
Normal file
16786
i18n/account.pot
Normal file
File diff suppressed because it is too large
Load Diff
15039
i18n/af.po
Normal file
15039
i18n/af.po
Normal file
File diff suppressed because it is too large
Load Diff
15035
i18n/am.po
Normal file
15035
i18n/am.po
Normal file
File diff suppressed because it is too large
Load Diff
17606
i18n/ar.po
Normal file
17606
i18n/ar.po
Normal file
File diff suppressed because it is too large
Load Diff
15106
i18n/az.po
Normal file
15106
i18n/az.po
Normal file
File diff suppressed because it is too large
Load Diff
17058
i18n/bg.po
Normal file
17058
i18n/bg.po
Normal file
File diff suppressed because it is too large
Load Diff
15043
i18n/bs.po
Normal file
15043
i18n/bs.po
Normal file
File diff suppressed because it is too large
Load Diff
17887
i18n/ca.po
Normal file
17887
i18n/ca.po
Normal file
File diff suppressed because it is too large
Load Diff
17791
i18n/cs.po
Normal file
17791
i18n/cs.po
Normal file
File diff suppressed because it is too large
Load Diff
17500
i18n/da.po
Normal file
17500
i18n/da.po
Normal file
File diff suppressed because it is too large
Load Diff
18014
i18n/de.po
Normal file
18014
i18n/de.po
Normal file
File diff suppressed because it is too large
Load Diff
15073
i18n/el.po
Normal file
15073
i18n/el.po
Normal file
File diff suppressed because it is too large
Load Diff
16077
i18n/en_AU.po
Normal file
16077
i18n/en_AU.po
Normal file
File diff suppressed because it is too large
Load Diff
15038
i18n/en_GB.po
Normal file
15038
i18n/en_GB.po
Normal file
File diff suppressed because it is too large
Load Diff
17958
i18n/es.po
Normal file
17958
i18n/es.po
Normal file
File diff suppressed because it is too large
Load Diff
17955
i18n/es_419.po
Normal file
17955
i18n/es_419.po
Normal file
File diff suppressed because it is too large
Load Diff
15038
i18n/es_BO.po
Normal file
15038
i18n/es_BO.po
Normal file
File diff suppressed because it is too large
Load Diff
15039
i18n/es_CL.po
Normal file
15039
i18n/es_CL.po
Normal file
File diff suppressed because it is too large
Load Diff
15038
i18n/es_CO.po
Normal file
15038
i18n/es_CO.po
Normal file
File diff suppressed because it is too large
Load Diff
15038
i18n/es_CR.po
Normal file
15038
i18n/es_CR.po
Normal file
File diff suppressed because it is too large
Load Diff
15038
i18n/es_DO.po
Normal file
15038
i18n/es_DO.po
Normal file
File diff suppressed because it is too large
Load Diff
15038
i18n/es_EC.po
Normal file
15038
i18n/es_EC.po
Normal file
File diff suppressed because it is too large
Load Diff
15217
i18n/es_MX.po
Normal file
15217
i18n/es_MX.po
Normal file
File diff suppressed because it is too large
Load Diff
15038
i18n/es_PE.po
Normal file
15038
i18n/es_PE.po
Normal file
File diff suppressed because it is too large
Load Diff
15038
i18n/es_PY.po
Normal file
15038
i18n/es_PY.po
Normal file
File diff suppressed because it is too large
Load Diff
15038
i18n/es_VE.po
Normal file
15038
i18n/es_VE.po
Normal file
File diff suppressed because it is too large
Load Diff
17294
i18n/et.po
Normal file
17294
i18n/et.po
Normal file
File diff suppressed because it is too large
Load Diff
15038
i18n/eu.po
Normal file
15038
i18n/eu.po
Normal file
File diff suppressed because it is too large
Load Diff
17378
i18n/fa.po
Normal file
17378
i18n/fa.po
Normal file
File diff suppressed because it is too large
Load Diff
17827
i18n/fi.po
Normal file
17827
i18n/fi.po
Normal file
File diff suppressed because it is too large
Load Diff
15038
i18n/fo.po
Normal file
15038
i18n/fo.po
Normal file
File diff suppressed because it is too large
Load Diff
17996
i18n/fr.po
Normal file
17996
i18n/fr.po
Normal file
File diff suppressed because it is too large
Load Diff
15040
i18n/fr_BE.po
Normal file
15040
i18n/fr_BE.po
Normal file
File diff suppressed because it is too large
Load Diff
15038
i18n/fr_CA.po
Normal file
15038
i18n/fr_CA.po
Normal file
File diff suppressed because it is too large
Load Diff
15038
i18n/gl.po
Normal file
15038
i18n/gl.po
Normal file
File diff suppressed because it is too large
Load Diff
15211
i18n/gu.po
Normal file
15211
i18n/gu.po
Normal file
File diff suppressed because it is too large
Load Diff
17142
i18n/he.po
Normal file
17142
i18n/he.po
Normal file
File diff suppressed because it is too large
Load Diff
15098
i18n/hr.po
Normal file
15098
i18n/hr.po
Normal file
File diff suppressed because it is too large
Load Diff
16981
i18n/hu.po
Normal file
16981
i18n/hu.po
Normal file
File diff suppressed because it is too large
Load Diff
17861
i18n/id.po
Normal file
17861
i18n/id.po
Normal file
File diff suppressed because it is too large
Load Diff
15059
i18n/is.po
Normal file
15059
i18n/is.po
Normal file
File diff suppressed because it is too large
Load Diff
17960
i18n/it.po
Normal file
17960
i18n/it.po
Normal file
File diff suppressed because it is too large
Load Diff
17145
i18n/ja.po
Normal file
17145
i18n/ja.po
Normal file
File diff suppressed because it is too large
Load Diff
15038
i18n/ka.po
Normal file
15038
i18n/ka.po
Normal file
File diff suppressed because it is too large
Load Diff
15038
i18n/kab.po
Normal file
15038
i18n/kab.po
Normal file
File diff suppressed because it is too large
Load Diff
15764
i18n/km.po
Normal file
15764
i18n/km.po
Normal file
File diff suppressed because it is too large
Load Diff
17236
i18n/ko.po
Normal file
17236
i18n/ko.po
Normal file
File diff suppressed because it is too large
Load Diff
15039
i18n/lb.po
Normal file
15039
i18n/lb.po
Normal file
File diff suppressed because it is too large
Load Diff
15038
i18n/lo.po
Normal file
15038
i18n/lo.po
Normal file
File diff suppressed because it is too large
Load Diff
17084
i18n/lt.po
Normal file
17084
i18n/lt.po
Normal file
File diff suppressed because it is too large
Load Diff
17814
i18n/lv.po
Normal file
17814
i18n/lv.po
Normal file
File diff suppressed because it is too large
Load Diff
15038
i18n/mk.po
Normal file
15038
i18n/mk.po
Normal file
File diff suppressed because it is too large
Load Diff
15127
i18n/mn.po
Normal file
15127
i18n/mn.po
Normal file
File diff suppressed because it is too large
Load Diff
15074
i18n/nb.po
Normal file
15074
i18n/nb.po
Normal file
File diff suppressed because it is too large
Load Diff
15035
i18n/ne.po
Normal file
15035
i18n/ne.po
Normal file
File diff suppressed because it is too large
Load Diff
17926
i18n/nl.po
Normal file
17926
i18n/nl.po
Normal file
File diff suppressed because it is too large
Load Diff
17716
i18n/pl.po
Normal file
17716
i18n/pl.po
Normal file
File diff suppressed because it is too large
Load Diff
17190
i18n/pt.po
Normal file
17190
i18n/pt.po
Normal file
File diff suppressed because it is too large
Load Diff
17926
i18n/pt_BR.po
Normal file
17926
i18n/pt_BR.po
Normal file
File diff suppressed because it is too large
Load Diff
15184
i18n/ro.po
Normal file
15184
i18n/ro.po
Normal file
File diff suppressed because it is too large
Load Diff
17935
i18n/ru.po
Normal file
17935
i18n/ru.po
Normal file
File diff suppressed because it is too large
Load Diff
17264
i18n/sk.po
Normal file
17264
i18n/sk.po
Normal file
File diff suppressed because it is too large
Load Diff
16889
i18n/sl.po
Normal file
16889
i18n/sl.po
Normal file
File diff suppressed because it is too large
Load Diff
15039
i18n/sq.po
Normal file
15039
i18n/sq.po
Normal file
File diff suppressed because it is too large
Load Diff
17801
i18n/sr.po
Normal file
17801
i18n/sr.po
Normal file
File diff suppressed because it is too large
Load Diff
15048
i18n/sr@latin.po
Normal file
15048
i18n/sr@latin.po
Normal file
File diff suppressed because it is too large
Load Diff
17741
i18n/sv.po
Normal file
17741
i18n/sv.po
Normal file
File diff suppressed because it is too large
Load Diff
17644
i18n/th.po
Normal file
17644
i18n/th.po
Normal file
File diff suppressed because it is too large
Load Diff
17725
i18n/tr.po
Normal file
17725
i18n/tr.po
Normal file
File diff suppressed because it is too large
Load Diff
17862
i18n/uk.po
Normal file
17862
i18n/uk.po
Normal file
File diff suppressed because it is too large
Load Diff
17827
i18n/vi.po
Normal file
17827
i18n/vi.po
Normal file
File diff suppressed because it is too large
Load Diff
17127
i18n/zh_CN.po
Normal file
17127
i18n/zh_CN.po
Normal file
File diff suppressed because it is too large
Load Diff
17107
i18n/zh_TW.po
Normal file
17107
i18n/zh_TW.po
Normal file
File diff suppressed because it is too large
Load Diff
44
models/__init__.py
Normal file
44
models/__init__.py
Normal file
@ -0,0 +1,44 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import sequence_mixin
|
||||
from . import partner
|
||||
from . import ir_http
|
||||
from . import res_partner_bank
|
||||
from . import account_account_tag
|
||||
from . import account_account
|
||||
from . import account_journal
|
||||
from . import account_tax
|
||||
from . import account_reconcile_model
|
||||
from . import account_payment_term
|
||||
from . import account_move
|
||||
from . import account_move_line
|
||||
from . import account_move_line_tax_details
|
||||
from . import account_partial_reconcile
|
||||
from . import account_full_reconcile
|
||||
from . import account_payment
|
||||
from . import account_payment_method
|
||||
from . import account_bank_statement
|
||||
from . import account_bank_statement_line
|
||||
from . import chart_template
|
||||
from . import account_analytic_account
|
||||
from . import account_analytic_distribution_model
|
||||
from . import account_analytic_plan
|
||||
from . import account_analytic_line
|
||||
from . import account_journal_dashboard
|
||||
from . import product
|
||||
from . import company
|
||||
from . import res_config_settings
|
||||
from . import account_cash_rounding
|
||||
from . import account_incoterms
|
||||
from . import decimal_precision
|
||||
from . import digest
|
||||
from . import res_users
|
||||
from . import ir_attachment
|
||||
from . import ir_actions_report
|
||||
from . import ir_module
|
||||
from . import res_currency
|
||||
from . import account_report
|
||||
from . import onboarding_onboarding
|
||||
from . import onboarding_onboarding_step
|
||||
from . import template_generic_coa
|
||||
from . import uom_uom
|
1036
models/account_account.py
Normal file
1036
models/account_account.py
Normal file
File diff suppressed because it is too large
Load Diff
65
models/account_account_tag.py
Normal file
65
models/account_account_tag.py
Normal file
@ -0,0 +1,65 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from odoo import api, fields, models, _
|
||||
from odoo import osv
|
||||
|
||||
|
||||
class AccountAccountTag(models.Model):
|
||||
_name = 'account.account.tag'
|
||||
_description = 'Account Tag'
|
||||
|
||||
name = fields.Char('Tag Name', required=True, translate=True)
|
||||
applicability = fields.Selection([('accounts', 'Accounts'), ('taxes', 'Taxes'), ('products', 'Products')], required=True, default='accounts')
|
||||
color = fields.Integer('Color Index')
|
||||
active = fields.Boolean(default=True, help="Set active to false to hide the Account Tag without removing it.")
|
||||
tax_negate = fields.Boolean(string="Negate Tax Balance", help="Check this box to negate the absolute value of the balance of the lines associated with this tag in tax report computation.")
|
||||
country_id = fields.Many2one(string="Country", comodel_name='res.country', help="Country for which this tag is available, when applied on taxes.")
|
||||
|
||||
_sql_constraints = [('name_uniq', "unique(name, applicability, country_id)", "A tag with the same name and applicability already exists in this country.")]
|
||||
|
||||
@api.depends('applicability', 'country_id')
|
||||
@api.depends_context('company')
|
||||
def _compute_display_name(self):
|
||||
if not self.env.company.multi_vat_foreign_country_ids:
|
||||
return super()._compute_display_name()
|
||||
|
||||
for tag in self:
|
||||
name = tag.name
|
||||
if tag.applicability == "taxes" and tag.country_id and tag.country_id != self.env.company.account_fiscal_country_id:
|
||||
name = _("%s (%s)", tag.name, tag.country_id.code)
|
||||
tag.display_name = name
|
||||
|
||||
@api.model
|
||||
def _get_tax_tags(self, tag_name, country_id):
|
||||
""" Returns all the tax tags corresponding to the tag name given in parameter
|
||||
in the specified country.
|
||||
"""
|
||||
domain = self._get_tax_tags_domain(tag_name, country_id)
|
||||
return self.env['account.account.tag'].with_context(active_test=False).search(domain)
|
||||
|
||||
@api.model
|
||||
def _get_tax_tags_domain(self, tag_name, country_id, sign=None):
|
||||
""" Returns a domain to search for all the tax tags corresponding to the tag name given in parameter
|
||||
in the specified country.
|
||||
"""
|
||||
escaped_tag_name = tag_name.replace('\\', '\\\\').replace('%', '\%').replace('_', '\_')
|
||||
return [
|
||||
('name', '=like', (sign or '_') + escaped_tag_name),
|
||||
('country_id', '=', country_id),
|
||||
('applicability', '=', 'taxes')
|
||||
]
|
||||
|
||||
def _get_related_tax_report_expressions(self):
|
||||
if not self:
|
||||
return self.env['account.report.expression']
|
||||
|
||||
or_domains = []
|
||||
for record in self:
|
||||
expr_domain = [
|
||||
'&',
|
||||
('report_line_id.report_id.country_id', '=', record.country_id.id),
|
||||
('formula', '=', record.name[1:]),
|
||||
]
|
||||
or_domains.append(expr_domain)
|
||||
|
||||
domain = osv.expression.AND([[('engine', '=', 'tax_tags')], osv.expression.OR(or_domains)])
|
||||
return self.env['account.report.expression'].search(domain)
|
98
models/account_analytic_account.py
Normal file
98
models/account_analytic_account.py
Normal file
@ -0,0 +1,98 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
|
||||
|
||||
class AccountAnalyticAccount(models.Model):
|
||||
_inherit = 'account.analytic.account'
|
||||
|
||||
invoice_count = fields.Integer(
|
||||
"Invoice Count",
|
||||
compute='_compute_invoice_count',
|
||||
)
|
||||
vendor_bill_count = fields.Integer(
|
||||
"Vendor Bill Count",
|
||||
compute='_compute_vendor_bill_count',
|
||||
)
|
||||
|
||||
@api.depends('line_ids')
|
||||
def _compute_invoice_count(self):
|
||||
sale_types = self.env['account.move'].get_sale_types(include_receipts=True)
|
||||
|
||||
query = self.env['account.move.line']._search([
|
||||
('parent_state', '=', 'posted'),
|
||||
('move_id.move_type', 'in', sale_types),
|
||||
])
|
||||
query.add_where(
|
||||
'account_move_line.analytic_distribution ?| %s',
|
||||
[[str(account_id) for account_id in self.ids]],
|
||||
)
|
||||
|
||||
query_string, query_param = query.select(
|
||||
'jsonb_object_keys(account_move_line.analytic_distribution) as account_id',
|
||||
'COUNT(DISTINCT(account_move_line.move_id)) as move_count',
|
||||
)
|
||||
query_string = f"{query_string} GROUP BY jsonb_object_keys(account_move_line.analytic_distribution)"
|
||||
|
||||
self._cr.execute(query_string, query_param)
|
||||
data = {int(record.get('account_id')): record.get('move_count') for record in self._cr.dictfetchall()}
|
||||
for account in self:
|
||||
account.invoice_count = data.get(account.id, 0)
|
||||
|
||||
@api.depends('line_ids')
|
||||
def _compute_vendor_bill_count(self):
|
||||
purchase_types = self.env['account.move'].get_purchase_types(include_receipts=True)
|
||||
|
||||
query = self.env['account.move.line']._search([
|
||||
('parent_state', '=', 'posted'),
|
||||
('move_id.move_type', 'in', purchase_types),
|
||||
])
|
||||
query.add_where(
|
||||
'account_move_line.analytic_distribution ?| %s',
|
||||
[[str(account_id) for account_id in self.ids]],
|
||||
)
|
||||
|
||||
query_string, query_param = query.select(
|
||||
'jsonb_object_keys(account_move_line.analytic_distribution) as account_id',
|
||||
'COUNT(DISTINCT(account_move_line.move_id)) as move_count',
|
||||
)
|
||||
query_string = f"{query_string} GROUP BY jsonb_object_keys(account_move_line.analytic_distribution)"
|
||||
|
||||
self._cr.execute(query_string, query_param)
|
||||
data = {int(record.get('account_id')): record.get('move_count') for record in self._cr.dictfetchall()}
|
||||
for account in self:
|
||||
account.vendor_bill_count = data.get(account.id, 0)
|
||||
|
||||
def action_view_invoice(self):
|
||||
self.ensure_one()
|
||||
query = self.env['account.move.line']._search([('move_id.move_type', 'in', self.env['account.move'].get_sale_types())])
|
||||
query.add_where('analytic_distribution ? %s', [str(self.id)])
|
||||
query_string, query_param = query.select('DISTINCT account_move_line.move_id')
|
||||
self._cr.execute(query_string, query_param)
|
||||
move_ids = [line.get('move_id') for line in self._cr.dictfetchall()]
|
||||
result = {
|
||||
"type": "ir.actions.act_window",
|
||||
"res_model": "account.move",
|
||||
"domain": [('id', 'in', move_ids)],
|
||||
"context": {"create": False, 'default_move_type': 'out_invoice'},
|
||||
"name": _("Customer Invoices"),
|
||||
'view_mode': 'tree,form',
|
||||
}
|
||||
return result
|
||||
|
||||
def action_view_vendor_bill(self):
|
||||
self.ensure_one()
|
||||
query = self.env['account.move.line']._search([('move_id.move_type', 'in', self.env['account.move'].get_purchase_types())])
|
||||
query.add_where('analytic_distribution ? %s', [str(self.id)])
|
||||
query_string, query_param = query.select('DISTINCT account_move_line.move_id')
|
||||
self._cr.execute(query_string, query_param)
|
||||
move_ids = [line.get('move_id') for line in self._cr.dictfetchall()]
|
||||
result = {
|
||||
"type": "ir.actions.act_window",
|
||||
"res_model": "account.move",
|
||||
"domain": [('id', 'in', move_ids)],
|
||||
"context": {"create": False, 'default_move_type': 'in_invoice'},
|
||||
"name": _("Vendor Bills"),
|
||||
'view_mode': 'tree,form',
|
||||
}
|
||||
return result
|
29
models/account_analytic_distribution_model.py
Normal file
29
models/account_analytic_distribution_model.py
Normal file
@ -0,0 +1,29 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class AccountAnalyticDistributionModel(models.Model):
|
||||
_inherit = 'account.analytic.distribution.model'
|
||||
|
||||
account_prefix = fields.Char(
|
||||
string='Accounts Prefix',
|
||||
help="This analytic distribution will apply to all financial accounts sharing the prefix specified.",
|
||||
)
|
||||
product_id = fields.Many2one(
|
||||
'product.product',
|
||||
string='Product',
|
||||
ondelete='cascade',
|
||||
check_company=True,
|
||||
help="Select a product for which the analytic distribution will be used (e.g. create new customer invoice or Sales order if we select this product, it will automatically take this as an analytic account)",
|
||||
)
|
||||
product_categ_id = fields.Many2one(
|
||||
'product.category',
|
||||
string='Product Category',
|
||||
ondelete='cascade',
|
||||
help="Select a product category which will use analytic account specified in analytic default (e.g. create new customer invoice or Sales order if we select this product, it will automatically take this as an analytic account)",
|
||||
)
|
||||
|
||||
def _create_domain(self, fname, value):
|
||||
if not fname == 'account_prefix':
|
||||
return super()._create_domain(fname, value)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user