Compare commits

...

2 Commits

Author SHA1 Message Date
Raimon Esteve 5f3ae819ce Add allow to pay sale and control not pay the sale twice times
#162876
2023-10-23 12:32:19 +02:00
Raimon Esteve 286896268e Allow pay and workflow_to_end when sale is in draft, quote or confirmed
#162967
2023-10-23 11:23:47 +02:00
1 changed files with 35 additions and 14 deletions

49
sale.py
View File

@ -2,12 +2,13 @@
# The COPYRIGHT file at the top level of this repository contains the full # The COPYRIGHT file at the top level of this repository contains the full
# copyright notices and license terms. # copyright notices and license terms.
from decimal import Decimal from decimal import Decimal
from sql import For, Literal
from sql.aggregate import Sum from sql.aggregate import Sum
from sql.conditionals import Coalesce from sql.conditionals import Coalesce
from trytond.model import ModelView, fields from trytond.model import ModelView, fields
from trytond.pool import PoolMeta, Pool from trytond.pool import PoolMeta, Pool
from trytond.pyson import Bool, Eval, Not, Or, Equal from trytond.pyson import Eval
from trytond.transaction import Transaction from trytond.transaction import Transaction
from trytond.wizard import Wizard, StateView, StateTransition, Button from trytond.wizard import Wizard, StateView, StateTransition, Button
from trytond.i18n import gettext from trytond.i18n import gettext
@ -15,10 +16,6 @@ from trytond.exceptions import UserError
from trytond.modules.currency.fields import Monetary from trytond.modules.currency.fields import Monetary
__all__ = ['Sale', 'SalePaymentForm', 'WizardSalePayment',
'WizardSaleReconcile']
class Sale(metaclass=PoolMeta): class Sale(metaclass=PoolMeta):
__name__ = 'sale.sale' __name__ = 'sale.sale'
payments = fields.One2Many('account.statement.line', 'sale', 'Payments') payments = fields.One2Many('account.statement.line', 'sale', 'Payments')
@ -32,6 +29,8 @@ class Sale(metaclass=PoolMeta):
'readonly': Eval('state') != 'draft', 'readonly': Eval('state') != 'draft',
} }
) )
allow_to_pay = fields.Function(fields.Boolean('Allow To Pay'),
'get_allow_to_pay')
@classmethod @classmethod
def __setup__(cls): def __setup__(cls):
@ -39,10 +38,8 @@ class Sale(metaclass=PoolMeta):
cls._buttons.update({ cls._buttons.update({
'wizard_sale_payment': { 'wizard_sale_payment': {
'invisible': Eval('state') == 'done', 'invisible': Eval('state') == 'done',
'readonly': Or( 'readonly': ~Eval('allow_to_pay', False),
Not(Bool(Eval('lines'))), 'depends': ['state', 'allow_to_pay'],
Equal(Eval('residual_amount', 0), 0)
),
}, },
}) })
@ -177,6 +174,13 @@ class Sale(metaclass=PoolMeta):
)) ))
return [('id', 'in', query)] return [('id', 'in', query)]
def get_allow_to_pay(self, name):
if ((self.state in ('cancelled', 'done'))
or (self.invoice_state == 'paid')
or (self.total_amount <= self.paid_amount)):
return False
return True
@classmethod @classmethod
@ModelView.button_action('sale_payment.wizard_sale_payment') @ModelView.button_action('sale_payment.wizard_sale_payment')
def wizard_sale_payment(cls, sales): def wizard_sale_payment(cls, sales):
@ -218,10 +222,11 @@ class WizardSalePayment(Wizard):
def default_start(self, fields): def default_start(self, fields):
pool = Pool() pool = Pool()
Sale = pool.get('sale.sale')
User = pool.get('res.user') User = pool.get('res.user')
sale = Sale(Transaction().context['active_id'])
user = User(Transaction().user) user = User(Transaction().user)
sale = self.record
sale_device = sale.sale_device or user.sale_device or False sale_device = sale.sale_device or user.sale_device or False
if user.id != 0 and not sale_device: if user.id != 0 and not sale_device:
raise UserError(gettext('sale_payment.not_sale_device')) raise UserError(gettext('sale_payment.not_sale_device'))
@ -276,8 +281,24 @@ class WizardSalePayment(Wizard):
def transition_pay_(self): def transition_pay_(self):
Sale = Pool().get('sale.sale') Sale = Pool().get('sale.sale')
active_id = Transaction().context.get('active_id', False) sale = self.record
sale = Sale(active_id) if not sale.allow_to_pay:
return 'end'
transaction = Transaction()
database = transaction.database
connection = transaction.connection
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) line = self.get_statement_line(sale)
if line: if line:
@ -285,7 +306,7 @@ class WizardSalePayment(Wizard):
if sale.total_amount != sale.paid_amount: if sale.total_amount != sale.paid_amount:
return 'start' return 'start'
if sale.state != 'draft': if sale.state not in ('draft', 'quotation', 'confirmed'):
return 'end' return 'end'
sale.description = sale.reference sale.description = sale.reference