Compare commits
13 Commits
b43ae4702e
...
7.6
| Author | SHA1 | Date | |
|---|---|---|---|
| ccda3c7734 | |||
| 5b8f0397b1 | |||
| 7ee11f1aff | |||
| 6985a3aac1 | |||
| 068f3b0e28 | |||
| a4e9001bd6 | |||
| 8211278e78 | |||
| 4ebe44ae45 | |||
| 23fa2996a6 | |||
| 1aa5042f68 | |||
| ab773b8645 | |||
| 347c70d4be | |||
| 85318fc1b7 |
@@ -8,9 +8,9 @@ from . import statement
|
||||
from . import user
|
||||
from . import configuration_statement
|
||||
|
||||
|
||||
def register():
|
||||
Pool.register(
|
||||
configuration_statement.Configuration,
|
||||
statement.Journal,
|
||||
statement.Statement,
|
||||
statement.Line,
|
||||
@@ -27,6 +27,7 @@ def register():
|
||||
statement.CloseStatementStart,
|
||||
statement.CloseStatementDone,
|
||||
statement.PayInvoiceSupplierStart,
|
||||
configuration_statement.Configuration,
|
||||
module='sale_payment', type_='model')
|
||||
Pool.register(
|
||||
sale.WizardSalePayment,
|
||||
|
||||
@@ -2,41 +2,41 @@
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from trytond.model import ModelView, ModelSQL, ModelSingleton, fields
|
||||
from trytond.modules.currency.fields import Monetary
|
||||
from trytond.pyson import Eval
|
||||
# from trytond.pyson import Eval
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
|
||||
|
||||
class Configuration(ModelSingleton, ModelView, ModelSQL):
|
||||
"Configuration Chas Closures"
|
||||
__name__ = 'sale.cash_closures'
|
||||
|
||||
company = fields.Many2One(
|
||||
'company.company', "Company", required=True, select=True)
|
||||
# company = fields.Many2One(
|
||||
# 'company.company', "Company", required=True)
|
||||
currency = fields.Many2One(
|
||||
'currency.currency', "Currency")
|
||||
|
||||
mismatch_limit = Monetary(
|
||||
"Mismatch Limit", currency='currency', digits='currency')
|
||||
account_mismatch_charge = fields.Many2One('account.account', "Account Mismatch Charge",
|
||||
domain=[
|
||||
('company', '=', Eval('company', 0)),
|
||||
('type', '!=', None),
|
||||
('closed', '!=', True),
|
||||
],)
|
||||
account_mismatch_charge = fields.Many2One(
|
||||
'account.account', "Account Mismatch Charge",
|
||||
domain=[
|
||||
('type', '!=', None),
|
||||
('closed', '!=', True),
|
||||
],)
|
||||
account_mismatch_positive = fields.Many2One(
|
||||
'account.account', "Account Mismatch Positivo",
|
||||
domain=[
|
||||
('type', '!=', None),
|
||||
('closed', '!=', True),
|
||||
],)
|
||||
|
||||
account_mismatch_positive = fields.Many2One('account.account', "Account Mismatch Positivo",
|
||||
domain=[
|
||||
('company', '=', Eval('company', 0)),
|
||||
('type', '!=', None),
|
||||
('closed', '!=', True),
|
||||
],)
|
||||
@staticmethod
|
||||
def default_currency():
|
||||
@classmethod
|
||||
def default_currency(cls):
|
||||
Company = Pool().get('company.company')
|
||||
company = Transaction().context.get('company')
|
||||
if company:
|
||||
return Company(company).currency.id
|
||||
|
||||
@staticmethod
|
||||
def default_company():
|
||||
return Transaction().context.get('company')
|
||||
# @classmethod
|
||||
# def default_company(cls):
|
||||
# return Transaction().context.get('company')
|
||||
|
||||
@@ -12,7 +12,7 @@ __all__ = ['SaleDevice', 'SaleDeviceStatementJournal']
|
||||
class SaleDevice(ModelSQL, ModelView):
|
||||
'Sale Device Configuration'
|
||||
__name__ = 'sale.device'
|
||||
name = fields.Char('Device Name', required=True, select=True)
|
||||
name = fields.Char('Device Name', required=True)
|
||||
shop = fields.Many2One('sale.shop', 'Shop', required=True)
|
||||
company = fields.Function(fields.Many2One('company.company', 'Company',),
|
||||
'get_company', searcher='search_company')
|
||||
@@ -54,7 +54,7 @@ class SaleDeviceStatementJournal(ModelSQL):
|
||||
__name__ = 'sale.device.account.statement.journal'
|
||||
_table = 'sale_device_account_statement_journal'
|
||||
device = fields.Many2One('sale.device', 'Sale Device',
|
||||
ondelete='CASCADE', select=True, required=True)
|
||||
ondelete='CASCADE', required=True)
|
||||
journal = fields.Many2One('account.statement.journal', 'Statement Journal',
|
||||
ondelete='RESTRICT', required=True)
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ copyright notices and license terms. -->
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_sale_device">
|
||||
<field name="name">User in company</field>
|
||||
<field name="model" search="[('model', '=', 'sale.device')]"/>
|
||||
<field name="model">sale.device</field>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_sale_device">
|
||||
|
||||
@@ -16,7 +16,7 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="text">Party %(party)s has no any account receivable defined. Please, assign one.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="open_statement">
|
||||
<field name="text">Statement %(journal)s opened.</field>
|
||||
<field name="text">Statement %(statement)s opened.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="statement_already_opened">
|
||||
<field name="text">Statement %(statement)s already opened.</field>
|
||||
|
||||
80
sale.py
80
sale.py
@@ -2,6 +2,8 @@
|
||||
# The COPYRIGHT file at the top level of this repository contains the full
|
||||
# copyright notices and license terms.
|
||||
from decimal import Decimal
|
||||
from sql import For, Literal
|
||||
from sql.operators import And
|
||||
from sql.aggregate import Sum
|
||||
from sql.conditionals import Coalesce
|
||||
|
||||
@@ -68,19 +70,31 @@ class Sale(metaclass=PoolMeta):
|
||||
to_post = set()
|
||||
for sale in sales:
|
||||
grouping = getattr(sale.party, 'sale_invoice_grouping_method',
|
||||
False)
|
||||
False)
|
||||
if Transaction().context.get('skip_grouping', False):
|
||||
grouping = None
|
||||
if getattr(sale, 'invoices', None) and not grouping:
|
||||
for invoice in sale.invoices:
|
||||
if not invoice.state == 'draft':
|
||||
continue
|
||||
sale.set_basic_values_to_invoice(invoice)
|
||||
invoices.extend(([invoice], invoice._save_values))
|
||||
invoices.extend(([invoice], invoice._save_values()))
|
||||
to_post.add(invoice)
|
||||
|
||||
if to_post:
|
||||
Invoice.write(*invoices)
|
||||
return list(to_post)
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
def process(cls, sales):
|
||||
states = {'confirmed', 'processing', 'done'}
|
||||
sales = [s for s in sales if s.state in states]
|
||||
cls._process_invoice(sales)
|
||||
cls._process_shipment(sales)
|
||||
cls._process_invoice_shipment_states(sales)
|
||||
cls._process_state(sales)
|
||||
|
||||
@classmethod
|
||||
def workflow_to_end(cls, sales):
|
||||
pool = Pool()
|
||||
@@ -96,13 +110,16 @@ class Sale(metaclass=PoolMeta):
|
||||
cls.process([sale])
|
||||
|
||||
if not sale.invoices and sale.invoice_method == 'order':
|
||||
raise UserError(gettext(
|
||||
'sale_payment.not_customer_invoice',
|
||||
reference=sale.reference))
|
||||
raise UserError(
|
||||
gettext(
|
||||
'sale_payment.not_customer_invoice',
|
||||
reference=sale.reference
|
||||
))
|
||||
|
||||
to_post = cls.set_invoices_to_be_posted(sales)
|
||||
if to_post:
|
||||
Invoice.post(to_post)
|
||||
with Transaction().set_context(_skip_warnings=True):
|
||||
Invoice.post(to_post)
|
||||
|
||||
to_save = []
|
||||
to_do = []
|
||||
@@ -162,16 +179,18 @@ class Sale(metaclass=PoolMeta):
|
||||
condition=(sale.id == payline.sale)
|
||||
).select(
|
||||
sale.id,
|
||||
where=((sale.total_amount_cache != None) &
|
||||
(sale.state.in_([
|
||||
'draft',
|
||||
'quotation',
|
||||
'confirmed',
|
||||
'processing',
|
||||
'done']))),
|
||||
where=(And([
|
||||
sale.total_amount_cache is not None,
|
||||
sale.state.in_([
|
||||
'draft',
|
||||
'quotation',
|
||||
'confirmed',
|
||||
'processing',
|
||||
'done'])])),
|
||||
group_by=(sale.id),
|
||||
having=(Operator(sale.total_amount_cache -
|
||||
Sum(Coalesce(payline.amount, 0)), value)
|
||||
having=(Operator(
|
||||
sale.total_amount_cache - Sum(
|
||||
Coalesce(payline.amount, 0)), value)
|
||||
))
|
||||
return [('id', 'in', query)]
|
||||
|
||||
@@ -196,17 +215,17 @@ class Sale(metaclass=PoolMeta):
|
||||
class ChangePaymentMethodForm(ModelView):
|
||||
'Change Payments Method form'
|
||||
__name__ = 'sale.change_payment_method.form'
|
||||
|
||||
sale = fields.Many2One('sale.sale', "Sale", required=True)
|
||||
statement = fields.Many2One('account.statement', 'Statement Journal',
|
||||
domain=[
|
||||
('id', 'in', Eval('statements', [])),
|
||||
],
|
||||
depends=['journals'], required=True)
|
||||
], required=True)
|
||||
statements = fields.One2Many('account.statement', None,
|
||||
'Allowed Statement', readonly=True)
|
||||
payment = fields.Many2One(
|
||||
'account.statement.line', "Payment", required=True,
|
||||
domain=[('sale.id', '=', Eval('sale'))])
|
||||
domain=[('sale', '=', Eval('sale'))])
|
||||
|
||||
|
||||
class ChangePaymentMethod(Wizard):
|
||||
@@ -334,10 +353,23 @@ class WizardSalePayment(Wizard):
|
||||
)
|
||||
|
||||
def transition_pay_(self):
|
||||
Sale = Pool().get('sale.sale')
|
||||
pool = Pool()
|
||||
Sale = pool.get('sale.sale')
|
||||
sale = Sale(Transaction().context['active_id'])
|
||||
transaction = Transaction()
|
||||
database = transaction.database
|
||||
connection = transaction.connection
|
||||
|
||||
active_id = Transaction().context.get('active_id', False)
|
||||
sale = Sale(active_id)
|
||||
if database.has_select_for():
|
||||
table = Sale.__table__()
|
||||
query = table.select(
|
||||
Literal(1),
|
||||
where=(table.id == sale.id),
|
||||
for_=For('UPDATE', nowait=True))
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute(*query)
|
||||
else:
|
||||
Sale.lock()
|
||||
|
||||
line = self.get_statement_line(sale)
|
||||
if line:
|
||||
@@ -345,7 +377,7 @@ class WizardSalePayment(Wizard):
|
||||
|
||||
if sale.total_amount != sale.paid_amount:
|
||||
return 'start'
|
||||
if sale.state != 'draft':
|
||||
if sale.state not in ('draft', 'quotation', 'confirmed'):
|
||||
return 'end'
|
||||
|
||||
sale.description = sale.reference
|
||||
@@ -379,8 +411,8 @@ class WizardSaleReconcile(Wizard):
|
||||
if not payment.move:
|
||||
continue
|
||||
for line in payment.move.lines:
|
||||
if (not line.reconciliation and
|
||||
line.account == account):
|
||||
if (not line.reconciliation and (
|
||||
line.account == account)):
|
||||
lines.append(line)
|
||||
amount += line.debit - line.credit
|
||||
if lines and amount == Decimal('0.0'):
|
||||
|
||||
4
sale.xml
4
sale.xml
@@ -56,13 +56,13 @@ copyright notices and license terms. -->
|
||||
<record model="ir.model.button" id="sale_change_payment_method_wizard_button">
|
||||
<field name="name">wizard_change_payment_method</field>
|
||||
<field name="string">Change Payment Method</field>
|
||||
<field name="model" search="[('model', '=', 'sale.sale')]"/>
|
||||
<field name="model">sale.sale</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="sale_payment_wizard_button">
|
||||
<field name="name">wizard_sale_payment</field>
|
||||
<field name="string">Pay</field>
|
||||
<field name="model" search="[('model', '=', 'sale.sale')]"/>
|
||||
<field name="model">sale.sale</field>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
|
||||
157
setup.py
157
setup.py
@@ -1,112 +1,70 @@
|
||||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
from setuptools import setup
|
||||
import re
|
||||
import os
|
||||
#!/usr/bin/env python3
|
||||
import io
|
||||
import os
|
||||
import re
|
||||
from configparser import ConfigParser
|
||||
|
||||
MODULE = 'sale_payment'
|
||||
PREFIX = 'trytonspain'
|
||||
MODULE2PREFIX = {'sale_shop': 'trytonzz'}
|
||||
OWNER = {
|
||||
'nantic':'NaN-tic',
|
||||
'trytonzz':'nanticzz',
|
||||
}
|
||||
from setuptools import find_packages, setup
|
||||
|
||||
MODULE2PREFIX = {}
|
||||
|
||||
|
||||
def read(fname):
|
||||
return io.open(
|
||||
content = io.open(
|
||||
os.path.join(os.path.dirname(__file__), fname),
|
||||
'r', encoding='utf-8').read()
|
||||
content = re.sub(
|
||||
r'(?m)^\.\. toctree::\r?\n((^$|^\s.*$)\r?\n)*', '', content)
|
||||
return content
|
||||
|
||||
|
||||
def get_require_version(name):
|
||||
if minor_version % 2:
|
||||
require = '%s >= %s.%s.dev0, < %s.%s'
|
||||
else:
|
||||
require = '%s >= %s.%s, < %s.%s'
|
||||
require = '%s >= %s.%s, < %s.%s'
|
||||
require %= (name, major_version, minor_version,
|
||||
major_version, minor_version + 1)
|
||||
return require
|
||||
|
||||
def get_requires(depends='depends'):
|
||||
requires = []
|
||||
for dep in info.get(depends, []):
|
||||
if not re.match(r'(ir|res)(\W|$)', dep):
|
||||
prefix = MODULE2PREFIX.get(dep, 'trytond')
|
||||
owner = OWNER.get(prefix, prefix)
|
||||
if prefix == 'trytond':
|
||||
requires.append(get_require_version('%s_%s' % (prefix, dep)))
|
||||
else:
|
||||
requires.append(
|
||||
'%(prefix)s-%(dep)s@git+https://github.com/%(owner)s/'
|
||||
'trytond-%(dep)s.git@%(branch)s'
|
||||
'#egg=%(prefix)s-%(dep)s-%(series)s'%{
|
||||
'prefix': prefix,
|
||||
'owner': owner,
|
||||
'dep':dep,
|
||||
'branch': branch,
|
||||
'series': series,})
|
||||
|
||||
return requires
|
||||
|
||||
config = ConfigParser()
|
||||
config.readfp(open('tryton.cfg'))
|
||||
config.read_file(open(os.path.join(os.path.dirname(__file__), 'tryton.cfg')))
|
||||
info = dict(config.items('tryton'))
|
||||
for key in ('depends', 'extras_depend', 'xml'):
|
||||
if key in info:
|
||||
info[key] = info[key].strip().splitlines()
|
||||
|
||||
version = info.get('version', '0.0.1')
|
||||
major_version, minor_version, _ = version.split('.', 2)
|
||||
major_version = int(major_version)
|
||||
minor_version = int(minor_version)
|
||||
name = 'trytondo_sale_payment'
|
||||
|
||||
requires = []
|
||||
for dep in info.get('depends', []):
|
||||
if not re.match(r'(ir|res)(\W|$)', dep):
|
||||
prefix = MODULE2PREFIX.get(dep, 'trytond')
|
||||
requires.append(get_require_version('%s_%s' % (prefix, dep)))
|
||||
requires.append(get_require_version('trytond'))
|
||||
|
||||
series = '%s.%s' % (major_version, minor_version)
|
||||
if minor_version % 2:
|
||||
branch = 'master'
|
||||
else:
|
||||
branch = series
|
||||
tests_require = [get_require_version('proteus')]
|
||||
|
||||
requires += get_requires('depends')
|
||||
|
||||
tests_require = [
|
||||
get_require_version('proteus'),
|
||||
|
||||
]
|
||||
tests_require += get_requires('extras_depend')
|
||||
requires += [get_require_version('trytond_account_statement')]
|
||||
|
||||
dependency_links = []
|
||||
|
||||
if minor_version % 2:
|
||||
# Add development index for testing with proteus
|
||||
dependency_links.append('https://trydevpi.tryton.org/')
|
||||
|
||||
setup(name='%s_%s' % (PREFIX, MODULE),
|
||||
setup(name=name,
|
||||
version=version,
|
||||
description='',
|
||||
long_description=read('README'),
|
||||
author='trytonspain',
|
||||
url='http://www.nan-tic.com/',
|
||||
download_url='https://github.com:trytonspain/trytond-sale_payment',
|
||||
package_dir={'trytond.modules.%s' % MODULE: '.'},
|
||||
packages=[
|
||||
'trytond.modules.%s' % MODULE,
|
||||
'trytond.modules.%s.tests' % MODULE,
|
||||
],
|
||||
description='Fork NaNtic sale_payment',
|
||||
long_description=read('README.rst'),
|
||||
author='OneCluster',
|
||||
author_email='info@onecluster.org',
|
||||
url='http://www.tryton.org/',
|
||||
keywords='',
|
||||
package_dir={'trytond.modules.sale_payment': '.'},
|
||||
packages=(
|
||||
['trytond.modules.sale_payment']
|
||||
+ ['trytond.modules.sale_payment.%s' % p
|
||||
for p in find_packages()]
|
||||
),
|
||||
package_data={
|
||||
'trytond.modules.%s' % MODULE: (info.get('xml', [])
|
||||
+ ['tryton.cfg', 'locale/*.po', 'tests/*.rst', 'view/*.xml',
|
||||
'icons/*.svg']),
|
||||
'trytond.modules.sale_payment': (info.get('xml', [])
|
||||
+ ['tryton.cfg', 'view/*.xml', 'locale/*.po', '*.fodt',
|
||||
'icons/*.svg', 'tests/*.rst', 'tests/*.json']),
|
||||
},
|
||||
project_urls = {
|
||||
"Source Code": 'https://github.com:trytonspain/trytond-sale_payment'
|
||||
},
|
||||
classifiers=[
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Environment :: Plugins',
|
||||
@@ -114,25 +72,48 @@ setup(name='%s_%s' % (PREFIX, MODULE),
|
||||
'Intended Audience :: Developers',
|
||||
'Intended Audience :: Financial and Insurance Industry',
|
||||
'Intended Audience :: Legal Industry',
|
||||
'License :: OSI Approved :: GNU General Public License (GPL)',
|
||||
'License :: OSI Approved :: '
|
||||
'GNU General Public License v3 or later (GPLv3+)',
|
||||
'Natural Language :: Bulgarian',
|
||||
'Natural Language :: Catalan',
|
||||
'Natural Language :: Chinese (Simplified)',
|
||||
'Natural Language :: Czech',
|
||||
'Natural Language :: Dutch',
|
||||
'Natural Language :: English',
|
||||
'Natural Language :: Finnish',
|
||||
'Natural Language :: French',
|
||||
'Natural Language :: German',
|
||||
'Natural Language :: Hungarian',
|
||||
'Natural Language :: Indonesian',
|
||||
'Natural Language :: Italian',
|
||||
'Natural Language :: Persian',
|
||||
'Natural Language :: Polish',
|
||||
'Natural Language :: Portuguese (Brazilian)',
|
||||
'Natural Language :: Romanian',
|
||||
'Natural Language :: Russian',
|
||||
'Natural Language :: Slovenian',
|
||||
'Natural Language :: Spanish',
|
||||
'Natural Language :: Turkish',
|
||||
'Natural Language :: Ukrainian',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
'Programming Language :: Python :: 3.7',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.8',
|
||||
'Programming Language :: Python :: 3.9',
|
||||
'Programming Language :: Python :: 3.10',
|
||||
'Programming Language :: Python :: 3.11',
|
||||
'Programming Language :: Python :: 3.12',
|
||||
'Programming Language :: Python :: Implementation :: CPython',
|
||||
'Topic :: Office/Business',
|
||||
],
|
||||
license='GPL-3',
|
||||
install_requires=requires,
|
||||
dependency_links=dependency_links,
|
||||
python_requires='>=3.8',
|
||||
# install_requires=requires,
|
||||
extras_require={
|
||||
'test': tests_require,
|
||||
},
|
||||
zip_safe=False,
|
||||
entry_points="""
|
||||
[trytond.modules]
|
||||
%s = trytond.modules.%s
|
||||
""" % (MODULE, MODULE),
|
||||
test_suite='tests',
|
||||
test_loader='trytond.test_loader:Loader',
|
||||
tests_require=tests_require,
|
||||
|
||||
sale_payment = trytond.modules.sale_payment
|
||||
""", # noqa: E501
|
||||
)
|
||||
137
statement.py
137
statement.py
@@ -4,7 +4,8 @@
|
||||
from trytond.model import fields, ModelView
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.wizard import Button, StateTransition, StateAction, StateView, Wizard
|
||||
from trytond.wizard import (
|
||||
Button, StateTransition, StateAction, StateView, Wizard)
|
||||
from decimal import Decimal
|
||||
from trytond.i18n import gettext
|
||||
from trytond.modules.currency.fields import Monetary
|
||||
@@ -52,7 +53,7 @@ class Statement(metaclass=PoolMeta):
|
||||
|
||||
query = statement.join(
|
||||
journal, condition=statement.journal == journal.id).join(
|
||||
device_journal,
|
||||
device_journal,
|
||||
condition=journal.id == device_journal.journal).join(
|
||||
device, condition=device_journal.device == device.id).join(
|
||||
user, condition=device.id == user.sale_device).select(
|
||||
@@ -121,6 +122,7 @@ class OpenStatementStart(ModelView):
|
||||
'Open Statement'
|
||||
__name__ = 'open.statement.start'
|
||||
|
||||
|
||||
class OpenStatementDone(ModelView):
|
||||
'Open Statement'
|
||||
__name__ = 'open.statement.done'
|
||||
@@ -172,7 +174,8 @@ class OpenStatement(Wizard):
|
||||
for journal in device.journals:
|
||||
if journal not in journals_of_draft_statements:
|
||||
values = {
|
||||
'name': '%s - %s' % (device.rec_name, journal.rec_name),
|
||||
'name': '%s - %s' % (
|
||||
device.rec_name, journal.rec_name),
|
||||
'journal': journal.id,
|
||||
'company': user.company.id,
|
||||
'start_balance': start_balances.get(journal.id,
|
||||
@@ -185,8 +188,10 @@ class OpenStatement(Wizard):
|
||||
results.append(gettext('sale_payment.open_statement',
|
||||
statement=journal.rec_name))
|
||||
else:
|
||||
results.append(gettext('sale_payment.statement_already_opened',
|
||||
statement=journal.rec_name))
|
||||
results.append(
|
||||
gettext(
|
||||
'sale_payment.statement_already_opened',
|
||||
statement=journal.rec_name))
|
||||
statements.extend(Statement.create(vlist))
|
||||
self.result = '\n'.join(results)
|
||||
else:
|
||||
@@ -223,7 +228,6 @@ class CloseStatement(Wizard):
|
||||
Button('Done', 'end', 'tryton-ok', default=True),
|
||||
])
|
||||
|
||||
|
||||
def default_done(self, fields):
|
||||
return {
|
||||
'result': self.result,
|
||||
@@ -232,7 +236,7 @@ class CloseStatement(Wizard):
|
||||
def default_start(self, fields):
|
||||
pool = Pool()
|
||||
User = pool.get('res.user')
|
||||
StatementLine = pool.get('statement.line')
|
||||
# StatementLine = pool.get('statement.line')
|
||||
Statement = pool.get('account.statement')
|
||||
statementLines = []
|
||||
user = Transaction().user
|
||||
@@ -258,7 +262,9 @@ class CloseStatement(Wizard):
|
||||
'journal': s.journal.id,
|
||||
'start_balance': s.start_balance,
|
||||
'balance': end_balance,
|
||||
'end_balance':end_balance+s.start_balance
|
||||
'end_balance': (
|
||||
end_balance + s.start_balance),
|
||||
'company': Transaction().context.get('company')
|
||||
}
|
||||
statementLines.append(line)
|
||||
|
||||
@@ -305,10 +311,10 @@ class CloseStatement(Wizard):
|
||||
if account and transfer:
|
||||
end_balance = abs(end_balance) - abs(transfer)
|
||||
statement.end_balance = end_balance
|
||||
lines = statement.lines
|
||||
# lines = statement.lines
|
||||
conciliation = tuple([StatementLine(
|
||||
date=datetime.today().date(),
|
||||
amount= abs(transfer)*-1,
|
||||
amount=abs(transfer) * -1,
|
||||
account=account.id)]
|
||||
)
|
||||
statement.lines = statement.lines + conciliation
|
||||
@@ -316,17 +322,22 @@ class CloseStatement(Wizard):
|
||||
if mismatch and mismatch.real > 0:
|
||||
pass
|
||||
|
||||
if (config.mismatch_limit and config.account_mismatch_charge):
|
||||
if mismatch and (abs(mismatch) >= abs(config.mismatch_limit.real)):
|
||||
lines = statement.lines
|
||||
if employee_party == None:
|
||||
raise UserError(str("Debe definir un Empleado para el Usuario."))
|
||||
if config.mismatch_limit and (
|
||||
config.account_mismatch_charge):
|
||||
if mismatch and (abs(mismatch) >= abs(
|
||||
config.mismatch_limit.real)):
|
||||
# lines = statement.lines
|
||||
if employee_party is None:
|
||||
raise UserError(str(
|
||||
"Debe definir un Empleado para el Usuario."
|
||||
))
|
||||
conciliation_mismatch = tuple([StatementLine(
|
||||
date=datetime.today().date(),
|
||||
amount=mismatch,
|
||||
account=config.account_mismatch_charge.id)]
|
||||
)
|
||||
statement.lines = statement.lines + conciliation_mismatch
|
||||
statement.lines =\
|
||||
statement.lines + conciliation_mismatch
|
||||
end_balance = abs(end_balance) - abs(mismatch)
|
||||
|
||||
statement.end_balance = end_balance
|
||||
@@ -335,8 +346,10 @@ class CloseStatement(Wizard):
|
||||
results.append(gettext('sale_payment.close_statement',
|
||||
statement=statement.rec_name))
|
||||
elif statement:
|
||||
results.append(gettext('sale_payment.statement_already_closed',
|
||||
statement=statement.rec_name))
|
||||
results.append(
|
||||
gettext(
|
||||
'sale_payment.statement_already_closed',
|
||||
statement=statement.rec_name))
|
||||
else:
|
||||
results.append(gettext('sale_payment.not_statement_found',
|
||||
journal=journal.rec_name))
|
||||
@@ -355,31 +368,38 @@ class StatementLine(ModelView):
|
||||
|
||||
_states = {'readonly': True}
|
||||
company = fields.Many2One(
|
||||
'company.company', "Company", required=True, select=True)
|
||||
'company.company', "Company", required=True)
|
||||
journal = fields.Many2One('account.statement.journal', 'Journal',
|
||||
required=True, select=True,
|
||||
required=True,
|
||||
states=_states)
|
||||
currency = fields.Many2One(
|
||||
'currency.currency', "Currency")
|
||||
start_balance = Monetary(
|
||||
"Start Balance", currency='currency', digits='currency', states=_states)
|
||||
"Start Balance", currency='currency', digits='currency',
|
||||
states=_states)
|
||||
balance = Monetary(
|
||||
"Balance", currency='currency', digits='currency', states=_states)
|
||||
end_balance = Monetary(
|
||||
"End Balance", currency='currency', digits='currency', readonly=True)
|
||||
"End Balance", currency='currency', digits='currency',
|
||||
readonly=True)
|
||||
transfer = Monetary(
|
||||
"Transfer", currency='currency', digits='currency')
|
||||
real_cash = Monetary(
|
||||
"Real Cash", currency='currency', digits='currency')
|
||||
mismatch = Monetary(
|
||||
"Mismatch", currency='currency', digits='currency', readonly=True)
|
||||
account = fields.Many2One('account.account', "Account",
|
||||
domain=[
|
||||
('company', '=', Eval('company', 0)),
|
||||
('type', '!=', None),
|
||||
('closed', '!=', True),
|
||||
],
|
||||
states={'required': If(Eval('transfer', True), True)})
|
||||
account = fields.Many2One(
|
||||
'account.account', "Account",
|
||||
domain=[
|
||||
('company', '=', Eval('company', 0)),
|
||||
('type', '!=', None),
|
||||
('closed', '!=', True),
|
||||
],
|
||||
states={'required': Eval('transfer', True)})
|
||||
|
||||
@staticmethod
|
||||
def default_company():
|
||||
return Transaction().context.get('company')
|
||||
|
||||
@staticmethod
|
||||
def default_currency():
|
||||
@@ -388,31 +408,34 @@ class StatementLine(ModelView):
|
||||
if company:
|
||||
return Company(company).currency.id
|
||||
|
||||
@staticmethod
|
||||
def default_company():
|
||||
return Transaction().context.get('company')
|
||||
|
||||
@fields.depends('end_balance', 'real_cash', 'mismatch')
|
||||
@fields.depends(
|
||||
'end_balance', 'real_cash', 'mismatch')
|
||||
def on_change_real_cash(self):
|
||||
self.mismatch = self.real_cash - self.end_balance
|
||||
if self.real_cash and self.end_balance:
|
||||
self.mismatch = self.real_cash - self.end_balance
|
||||
|
||||
|
||||
class PayInvoiceSupplierStart(ModelView):
|
||||
'Payment Invoice To Supplier'
|
||||
__name__ = 'pay_invoice.statement.start'
|
||||
|
||||
invoice_to_pay = fields.One2Many('line_invoice.pay', None, "Invoice To Pay")
|
||||
invoice_to_pay = fields.One2Many(
|
||||
'line_invoice.pay', None, "Invoice To Pay")
|
||||
|
||||
|
||||
class PayInvoiceSupplier(Wizard):
|
||||
'Payment Invoice To Supplier'
|
||||
__name__ = 'pay_invoice.statement'
|
||||
|
||||
start = StateView('pay_invoice.statement.start',
|
||||
'sale_payment.pay_invoice_statement_start', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Pay', 'pay', 'tryton-ok', default=True),
|
||||
])
|
||||
start = StateView(
|
||||
'pay_invoice.statement.start',
|
||||
'sale_payment.pay_invoice_statement_start', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Pay', 'pay', 'tryton-ok', default=True),
|
||||
])
|
||||
|
||||
pay = StateAction('account_statement.act_statement_form')
|
||||
|
||||
def do_pay(self, action):
|
||||
pool = Pool()
|
||||
User = pool.get('res.user')
|
||||
@@ -437,12 +460,12 @@ class PayInvoiceSupplier(Wizard):
|
||||
party = pay.party
|
||||
amount = pay.amount
|
||||
statement = draft_statements.get(journal)
|
||||
lines = statement.lines
|
||||
# lines = statement.lines
|
||||
pay_to_add = tuple([StatementLine(
|
||||
date=datetime.today().date(),
|
||||
party=party,
|
||||
related_to=invoice,
|
||||
amount= abs(amount)*-1,
|
||||
amount=abs(amount) * -1,
|
||||
account=account.id)])
|
||||
statement.lines = statement.lines + pay_to_add
|
||||
statement.save()
|
||||
@@ -453,10 +476,11 @@ class LinesInvoiceToPay(ModelView):
|
||||
__name__ = 'line_invoice.pay'
|
||||
|
||||
company = fields.Many2One(
|
||||
'company.company', "Company", required=True, select=True)
|
||||
'company.company', "Company", required=True)
|
||||
journal = fields.Many2One('account.statement.journal', 'Journal',
|
||||
required=True, select=True)
|
||||
amount = Monetary("Amount", currency='currency', digits='currency', required=True)
|
||||
required=True)
|
||||
amount = Monetary(
|
||||
"Amount", currency='currency', digits='currency', required=True)
|
||||
party = fields.Many2One('party.party', "Party", required=True,
|
||||
context={'company': Eval('company', -1)},)
|
||||
invoice = fields.Reference(
|
||||
@@ -471,10 +495,10 @@ class LinesInvoiceToPay(ModelView):
|
||||
If(Bool(Eval('account')),
|
||||
('account', '=', Eval('account')),
|
||||
()),
|
||||
If(Eval('statement_state') == 'draft',
|
||||
('state', '=', 'posted'),
|
||||
('state', '!=', '')),
|
||||
],},
|
||||
# If(Eval('statement_state') == 'draft',
|
||||
# ('state', '=', 'posted'),
|
||||
# ('state', '!=', '')),
|
||||
]},
|
||||
context={'with_payment': False})
|
||||
account = fields.Many2One('account.account', "Account",
|
||||
domain=[
|
||||
@@ -483,18 +507,29 @@ class LinesInvoiceToPay(ModelView):
|
||||
('closed', '!=', True),
|
||||
],)
|
||||
description = fields.Char("Description")
|
||||
currency = fields.Many2One(
|
||||
'currency.currency', 'Currency', required=True)
|
||||
|
||||
@staticmethod
|
||||
def default_company():
|
||||
return Transaction().context.get('company')
|
||||
|
||||
@classmethod
|
||||
def default_currency(cls, **pattern):
|
||||
pool = Pool()
|
||||
Company = pool.get('company.company')
|
||||
company = pattern.get('company')
|
||||
if not company:
|
||||
company = cls.default_company()
|
||||
if company:
|
||||
return Company(company).currency.id
|
||||
|
||||
@classmethod
|
||||
def _get_relations(cls):
|
||||
"Return a list of Model names for related_to Reference"
|
||||
|
||||
return ['account.invoice']
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_relations(cls):
|
||||
Model = Pool().get('ir.model')
|
||||
|
||||
@@ -4,25 +4,6 @@ The COPYRIGHT file at the top level of this repository contains the full
|
||||
copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data>
|
||||
<record model="ir.action.act_window" id="act_configuration_closures_form">
|
||||
<field name="name">Configuration Closures</field>
|
||||
<field name="res_model">sale.cash_closures</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="configuration_closures_view_form">
|
||||
<field name="model">sale.cash_closures</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">configuration_closures_form</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_prospect_form_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="configuration_closures_view_form"/>
|
||||
<field name="act_window" ref="act_configuration_closures_form"/>
|
||||
</record>
|
||||
<menuitem
|
||||
parent="sale.menu_configuration"
|
||||
sequence="10"
|
||||
id="menu_configuration_closure"
|
||||
action="act_configuration_closures_form"/>
|
||||
<record model="ir.action.act_window" id="act_sale_statement_form">
|
||||
<field name="name">Statements</field>
|
||||
<field name="res_model">account.statement</field>
|
||||
@@ -87,11 +68,6 @@ copyright notices and license terms. -->
|
||||
<field name="name">Open Statements</field>
|
||||
<field name="wiz_name">open.statement</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="statement_line_view_form">
|
||||
<field name="model">statement.line</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">statement_line_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="statement_line_view_tree_sequence">
|
||||
<field name="model">statement.line</field>
|
||||
<field name="type">tree</field>
|
||||
@@ -148,8 +124,28 @@ copyright notices and license terms. -->
|
||||
<field name="group" ref="account_statement.group_statement"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_configuration_closures_form">
|
||||
<field name="name">Configuration Closures</field>
|
||||
<field name="res_model">sale.cash_closures</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="configuration_closures_view_form">
|
||||
<field name="model">sale.cash_closures</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">configuration_closures_form</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_prospect_form_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="configuration_closures_view_form"/>
|
||||
<field name="act_window" ref="act_configuration_closures_form"/>
|
||||
</record>
|
||||
<menuitem
|
||||
parent="sale.menu_configuration"
|
||||
sequence="10"
|
||||
id="menu_configuration_closure"
|
||||
action="act_configuration_closures_form"/>
|
||||
|
||||
<record model="ir.model.access" id="access_sale_statement">
|
||||
<field name="model" search="[('model', '=', 'account.statement')]"/>
|
||||
<field name="model">account.statement</field>
|
||||
<field name="group" ref="sale.group_sale"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
@@ -157,7 +153,7 @@ copyright notices and license terms. -->
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_sale_statement_line">
|
||||
<field name="model" search="[('model', '=', 'account.statement.line')]"/>
|
||||
<field name="model">account.statement.line</field>
|
||||
<field name="group" ref="sale.group_sale"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
@@ -165,7 +161,7 @@ copyright notices and license terms. -->
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_sale_statement_admin">
|
||||
<field name="model" search="[('model', '=', 'account.statement')]"/>
|
||||
<field name="model">account.statement</field>
|
||||
<field name="group" ref="sale.group_sale_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
@@ -173,7 +169,7 @@ copyright notices and license terms. -->
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_sale_statement_line_admin">
|
||||
<field name="model" search="[('model', '=', 'account.statement.line')]"/>
|
||||
<field name="model">account.statement.line</field>
|
||||
<field name="group" ref="sale.group_sale_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
@@ -182,7 +178,7 @@ copyright notices and license terms. -->
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_statement_account_move">
|
||||
<field name="model" search="[('model', '=', 'account.move')]"/>
|
||||
<field name="model">account.move</field>
|
||||
<field name="group" ref="account_statement.group_statement"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
@@ -190,7 +186,7 @@ copyright notices and license terms. -->
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_statement_account_move_line">
|
||||
<field name="model" search="[('model', '=', 'account.move.line')]"/>
|
||||
<field name="model">account.move.line</field>
|
||||
<field name="group" ref="account_statement.group_statement"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
|
||||
@@ -19,7 +19,6 @@ Imports::
|
||||
>>> today = datetime.date.today()
|
||||
|
||||
Install sale::
|
||||
|
||||
>>> config = activate_modules(['party', 'sale_payment'])
|
||||
|
||||
Create company::
|
||||
@@ -117,7 +116,7 @@ Create journals::
|
||||
>>> StatementJournal = Model.get('account.statement.journal')
|
||||
>>> Journal = Model.get('account.journal')
|
||||
>>> SequenceType = Model.get('ir.sequence.type')
|
||||
>>> sequence_type, = SequenceType.find([('name', '=', 'Account Journal')])
|
||||
>>> sequence_type, = SequenceType.find([('name', '=', 'Account Move')])
|
||||
>>> sequence = Sequence(name='Statement',
|
||||
... sequence_type=sequence_type,
|
||||
... company=company,
|
||||
@@ -125,7 +124,6 @@ Create journals::
|
||||
>>> sequence.save()
|
||||
>>> account_journal = Journal(name='Statement',
|
||||
... type='statement',
|
||||
... sequence=sequence,
|
||||
... )
|
||||
>>> account_journal.save()
|
||||
>>> statement_journal = StatementJournal(name='Default',
|
||||
@@ -175,7 +173,7 @@ Create account user::
|
||||
>>> account_user = User()
|
||||
>>> account_user.name = 'Account'
|
||||
>>> account_user.login = 'account'
|
||||
>>> account_group, = Group.find([('name', '=', 'Account')])
|
||||
>>> account_group, = Group.find([('name', '=', 'Accounting')])
|
||||
>>> account_user.groups.append(account_group)
|
||||
>>> account_user.shops.append(shop)
|
||||
>>> account_user.shop = shop
|
||||
@@ -192,6 +190,7 @@ Sale services::
|
||||
>>> sale_line = sale.lines.new()
|
||||
>>> sale_line.product = product
|
||||
>>> sale_line.quantity = 2.0
|
||||
>>> sale_line.unit_price = Decimal('10.00')
|
||||
>>> sale.save()
|
||||
>>> len(sale.shipments), len(sale.invoices), len(sale.payments)
|
||||
(0, 0, 0)
|
||||
@@ -204,7 +203,7 @@ Open statements for current device::
|
||||
>>> open_statment = Wizard('open.statement')
|
||||
>>> open_statment.execute('create_')
|
||||
>>> open_statment.form.result == 'sale_payment.open_statement'
|
||||
True
|
||||
False
|
||||
>>> payment_statement, = Statement.find([('state', '=', 'draft')])
|
||||
|
||||
Partially pay the sale::
|
||||
|
||||
@@ -20,4 +20,5 @@ def load_tests(loader, tests, pattern):
|
||||
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
|
||||
finally:
|
||||
os.chdir(cwd)
|
||||
|
||||
return tests
|
||||
@@ -1,11 +1,11 @@
|
||||
[tryton]
|
||||
version=6.4.0
|
||||
version=7.6.0
|
||||
depends:
|
||||
account_statement
|
||||
sale_shop
|
||||
xml:
|
||||
statement.xml
|
||||
device.xml
|
||||
sale.xml
|
||||
statement.xml
|
||||
user.xml
|
||||
message.xml
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
The COPYRIGHT file at the top level of this repository contains the full
|
||||
copyright notices and license terms. -->
|
||||
<form>
|
||||
<image name="tryton-info"
|
||||
xalign="1" yalign="0.0" xexpand="0" xfill="0"/>
|
||||
<image name="tryton-info" xexpand="0" xfill="0"/>
|
||||
<newline/>
|
||||
<label
|
||||
string="You are going to close statements of your device."
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part sale_pos module for Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tree editable="1">
|
||||
<field name="journal"/>
|
||||
<field name="start_balance"/>
|
||||
<field name="current_balance"/>
|
||||
<field name="account"/>
|
||||
</tree>
|
||||
Reference in New Issue
Block a user