@@ -1,3 +1,4 @@
|
||||
* Add promotion coupon as action
|
||||
* Use actual quantity of sale line
|
||||
|
||||
Version 7.4.0 - 2024-11-04
|
||||
|
||||
@@ -18,3 +18,8 @@ def register():
|
||||
sale.Sale,
|
||||
account.InvoiceLine,
|
||||
module='sale_complaint', type_='model')
|
||||
Pool.register(
|
||||
complaint.Complaint_PromotionCoupon,
|
||||
complaint.Action_PromotionCoupon,
|
||||
module='sale_complaint', type_='model',
|
||||
depends=['sale_promotion_coupon'])
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
import datetime as dt
|
||||
from collections import defaultdict
|
||||
from decimal import Decimal
|
||||
|
||||
@@ -15,7 +16,7 @@ from trytond.modules.company.model import (
|
||||
employee_field, reset_employee, set_employee)
|
||||
from trytond.modules.currency.fields import Monetary
|
||||
from trytond.modules.product import price_digits
|
||||
from trytond.pool import Pool
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
from trytond.pyson import Bool, Eval, If
|
||||
from trytond.tools import grouped_slice
|
||||
from trytond.transaction import Transaction
|
||||
@@ -497,6 +498,9 @@ class Action(ModelSQL, ModelView):
|
||||
complaint_state = fields.Function(
|
||||
fields.Selection('get_complaint_states', "Complaint State"),
|
||||
'on_change_with_complaint_state')
|
||||
company = fields.Function(
|
||||
fields.Many2One('company.company', "Company"),
|
||||
'on_change_with_company')
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
@@ -583,6 +587,11 @@ class Action(ModelSQL, ModelView):
|
||||
if self.complaint:
|
||||
return self.complaint.state
|
||||
|
||||
@fields.depends('complaint', '_parent_complaint.company')
|
||||
def on_change_with_company(self, name=None):
|
||||
if self.complaint:
|
||||
return self.complaint.company
|
||||
|
||||
@classmethod
|
||||
def _get_result(cls):
|
||||
'Return list of Model names for result Reference'
|
||||
@@ -861,3 +870,67 @@ class Action_InvoiceLine(_Action_Line, ModelView, ModelSQL):
|
||||
return self.unit_price
|
||||
elif self.line:
|
||||
return self.line.unit_price
|
||||
|
||||
|
||||
class Complaint_PromotionCoupon(metaclass=PoolMeta):
|
||||
__name__ = 'sale.complaint'
|
||||
|
||||
@classmethod
|
||||
def _actions_domains(cls):
|
||||
domains = super()._actions_domains()
|
||||
for name, domain in domains.items():
|
||||
domain.append('promotion_coupon')
|
||||
return domains
|
||||
|
||||
|
||||
class Action_PromotionCoupon(metaclass=PoolMeta):
|
||||
__name__ = 'sale.complaint.action'
|
||||
|
||||
_promtion_coupon_states = {
|
||||
'invisible': Eval('action') != 'promotion_coupon',
|
||||
'required': Eval('action') == 'promotion_coupon',
|
||||
}
|
||||
|
||||
promotion_coupon = fields.Many2One(
|
||||
'sale.promotion.coupon', "Promotion Coupon",
|
||||
domain=[
|
||||
('company', '=', Eval('company', -1)),
|
||||
('number_of_use', '=', 1),
|
||||
('per_party', '=', False),
|
||||
],
|
||||
states=_promtion_coupon_states)
|
||||
promotion_coupon_number = fields.Char(
|
||||
"Number", states=_promtion_coupon_states)
|
||||
promotion_coupon_duration = fields.TimeDelta(
|
||||
"Duration", states=_promtion_coupon_states)
|
||||
|
||||
del _promtion_coupon_states
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
cls.action.selection.append(('promotion_coupon', "Promotion Coupon"))
|
||||
|
||||
@classmethod
|
||||
def default_promotion_coupon_duration(cls):
|
||||
return dt.timedelta(days=90)
|
||||
|
||||
@classmethod
|
||||
def _get_result(cls):
|
||||
return super()._get_result() + ['sale.promotion.coupon.number']
|
||||
|
||||
def do_promotion_coupon(self):
|
||||
pool = Pool()
|
||||
PromotionCouponNumber = pool.get('sale.promotion.coupon.number')
|
||||
Date = pool.get('ir.date')
|
||||
|
||||
with Transaction().set_context(company=self.company.id):
|
||||
today = Date.today()
|
||||
|
||||
return PromotionCouponNumber(
|
||||
number=self.promotion_coupon_number,
|
||||
coupon=self.promotion_coupon,
|
||||
company=self.company,
|
||||
start_date=today,
|
||||
end_date=today + self.promotion_coupon_duration,
|
||||
)
|
||||
|
||||
@@ -288,4 +288,11 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="name">action_line_list</field>
|
||||
</record>
|
||||
</data>
|
||||
<data depends="sale_promotion_coupon">
|
||||
<record model="ir.ui.view" id="action_view_form_promotion_coupon">
|
||||
<field name="model">sale.complaint.action</field>
|
||||
<field name="inherit" ref="action_view_form"/>
|
||||
<field name="name">action_form_promotion_coupon</field>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
|
||||
@@ -47,7 +47,10 @@ for dep in info.get('depends', []):
|
||||
requires.append(get_require_version('trytond_%s' % dep))
|
||||
requires.append(get_require_version('trytond'))
|
||||
|
||||
tests_require = [get_require_version('proteus')]
|
||||
tests_require = [
|
||||
get_require_version('proteus'),
|
||||
get_require_version('trytond_sale_promotion_coupon'),
|
||||
]
|
||||
|
||||
setup(name=name,
|
||||
version=version,
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
=============================================
|
||||
Sale Complaint with Promotion Coupon Scenario
|
||||
=============================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.account.tests.tools import (
|
||||
... create_chart, create_fiscalyear, get_accounts)
|
||||
>>> from trytond.modules.account_invoice.tests.tools import (
|
||||
... set_fiscalyear_invoice_sequences)
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules(
|
||||
... ['sale_complaint', 'sale_promotion_coupon'],
|
||||
... create_company, create_chart)
|
||||
|
||||
>>> Complaint = Model.get('sale.complaint')
|
||||
>>> IrModel = Model.get('ir.model')
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> ProductCategory = Model.get('product.category')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> Promotion = Model.get('sale.promotion')
|
||||
>>> Sale = Model.get('sale.sale')
|
||||
>>> Type = Model.get('sale.complaint.type')
|
||||
|
||||
Create fiscal year::
|
||||
|
||||
>>> fiscalyear = set_fiscalyear_invoice_sequences(create_fiscalyear())
|
||||
>>> fiscalyear.click('create_period')
|
||||
|
||||
Get accounts::
|
||||
|
||||
>>> accounts = get_accounts()
|
||||
|
||||
Create parties::
|
||||
|
||||
>>> customer = Party(name='Customer')
|
||||
>>> customer.save()
|
||||
|
||||
Create complaint type::
|
||||
|
||||
>>> sale_type = Type(name='Sale')
|
||||
>>> sale_type.origin, = IrModel.find([('name', '=', 'sale.sale')])
|
||||
>>> sale_type.save()
|
||||
|
||||
Create account category::
|
||||
|
||||
>>> account_category = ProductCategory(name="Account Category")
|
||||
>>> account_category.accounting = True
|
||||
>>> account_category.account_revenue = accounts['revenue']
|
||||
>>> account_category.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> unit, = ProductUom.find([('name', '=', "Unit")])
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = "Product"
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.salable = True
|
||||
>>> template.list_price = Decimal('10')
|
||||
>>> template.account_category = account_category
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
Create Promotion with coupon::
|
||||
|
||||
>>> promotion = Promotion(name="50%")
|
||||
>>> promotion.formula = '0.5 * unit_price'
|
||||
>>> coupon = promotion.coupons.new()
|
||||
>>> coupon.number_of_use = 1
|
||||
>>> coupon.per_party = False
|
||||
>>> promotion.save()
|
||||
>>> coupon, = promotion.coupons
|
||||
|
||||
Sale 1 product::
|
||||
|
||||
>>> sale = Sale()
|
||||
>>> sale.party = customer
|
||||
>>> sale_line = sale.lines.new()
|
||||
>>> sale_line.product = product
|
||||
>>> sale_line.quantity = 1
|
||||
>>> sale.click('quote')
|
||||
>>> sale.click('confirm')
|
||||
>>> sale.state
|
||||
'processing'
|
||||
|
||||
Fill a complaint for the sale::
|
||||
|
||||
>>> complaint = Complaint()
|
||||
>>> complaint.customer = customer
|
||||
>>> complaint.type = sale_type
|
||||
>>> complaint.origin = sale
|
||||
>>> complaint.save()
|
||||
|
||||
Resolve complaint with a coupon::
|
||||
|
||||
>>> action = complaint.actions.new(action='promotion_coupon')
|
||||
>>> action.promotion_coupon = coupon
|
||||
>>> action.promotion_coupon_number = "DISC50"
|
||||
>>> action.promotion_coupon_duration = dt.timedelta(days=30)
|
||||
>>> complaint.click('wait')
|
||||
>>> complaint.click('approve')
|
||||
>>> complaint.state
|
||||
'done'
|
||||
|
||||
>>> action, = complaint.actions
|
||||
>>> coupon_number = action.result
|
||||
>>> coupon_number.number
|
||||
'DISC50'
|
||||
>>> assertEqual(coupon_number.coupon, coupon)
|
||||
>>> assertEqual(
|
||||
... coupon_number.end_date - coupon_number.start_date, dt.timedelta(days=30))
|
||||
@@ -8,6 +8,7 @@ from trytond.tests.test_tryton import ModuleTestCase
|
||||
class SaleComplaintTestCase(CompanyTestMixin, ModuleTestCase):
|
||||
'Test Sale Complaint module'
|
||||
module = 'sale_complaint'
|
||||
extras = ['sale_promotion_coupon']
|
||||
|
||||
|
||||
del ModuleTestCase
|
||||
|
||||
@@ -6,6 +6,8 @@ depends:
|
||||
ir
|
||||
party
|
||||
sale
|
||||
extras_depend:
|
||||
sale_promotion_coupon
|
||||
xml:
|
||||
complaint.xml
|
||||
sale.xml
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<data>
|
||||
<xpath expr="//field[@name='invoice_lines']" position="after">
|
||||
<label name="promotion_coupon"/>
|
||||
<field name="promotion_coupon"/>
|
||||
<label name="promotion_coupon_number"/>
|
||||
<field name="promotion_coupon_number"/>
|
||||
|
||||
<label name="promotion_coupon_duration"/>
|
||||
<field name="promotion_coupon_duration"/>
|
||||
<newline/>
|
||||
</xpath>
|
||||
</data>
|
||||
Reference in New Issue
Block a user