210 lines
6.5 KiB
Python
210 lines
6.5 KiB
Python
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
|
# this repository contains the full copyright notices and license terms.
|
|
from trytond.model import ModelView, ModelSQL, fields, Workflow
|
|
from trytond.pool import Pool
|
|
from trytond.transaction import Transaction
|
|
from trytond.modules.currency.fields import Monetary
|
|
from trytond.modules.product import price_digits
|
|
from trytond.pyson import Eval, Bool
|
|
from decimal import Decimal
|
|
from datetime import date
|
|
|
|
|
|
class SaleOrder (Workflow, ModelView, ModelSQL):
|
|
"Sale Order"
|
|
__name__ = 'sale.order'
|
|
|
|
_states = {
|
|
'readonly': Eval('state').in_(['confirmed', 'done'])
|
|
}
|
|
|
|
company = fields.Many2One(
|
|
'company.company', "Company", states={
|
|
'readonly': True,
|
|
'required': True
|
|
})
|
|
currency = fields.Many2One(
|
|
'currency.currency', 'Currency', states={
|
|
'readonly': True,
|
|
'required': True
|
|
})
|
|
number = fields.Char(
|
|
"Number", readonly=True)
|
|
party = fields.Many2One(
|
|
'party.party', "Party", required=True, states=_states)
|
|
order_address = fields.Many2One(
|
|
'party.address', 'Address', required=True, states=_states)
|
|
pickup_location = fields.Selection([
|
|
("on_site", "On Site"),
|
|
("at_home", "At Home")], 'Pickup Location', states=_states)
|
|
order_mobile = fields.Char('Mobile', states=_states)
|
|
date = fields.Date("Date", required=True, states=_states)
|
|
lines = fields.One2Many(
|
|
'order.line', 'order', 'Lines', states=_states)
|
|
total_order = fields.Function(
|
|
Monetary("Total", currency='currency', digits='currency'),
|
|
'on_change_with_total_order')
|
|
state = fields.Selection([
|
|
('draft', 'Draft'),
|
|
('confirmed', 'Confirmed'),
|
|
('done', "Done")
|
|
], "State", readonly=True)
|
|
|
|
@classmethod
|
|
def __setup__(cls):
|
|
super(SaleOrder, cls).__setup__()
|
|
cls._buttons.update({
|
|
'confirm': {
|
|
'readonly': Eval('state').in_(['confirmed']),
|
|
'invisible': Eval('state').in_(['confirmed']) | ~Bool(
|
|
Eval('lines', [0]))
|
|
}
|
|
})
|
|
cls._transitions |= set((
|
|
('draft', 'confirmed'),
|
|
))
|
|
|
|
@classmethod
|
|
def set_code(cls, orders):
|
|
for order in orders:
|
|
order.number = cls.get_number()[0].get()
|
|
order.save()
|
|
|
|
@classmethod
|
|
def get_number(cls):
|
|
pool = Pool()
|
|
Sequence = pool.get('ir.sequence')
|
|
order_sequence = Sequence.search([(
|
|
'sequence_type.name', '=', "Order")])
|
|
return order_sequence
|
|
|
|
@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
|
|
|
|
@staticmethod
|
|
def default_date():
|
|
return date.today()
|
|
|
|
@staticmethod
|
|
def default_state():
|
|
return 'draft'
|
|
|
|
@fields.depends('party')
|
|
def on_change_party(self):
|
|
if self.party:
|
|
self.order_address =\
|
|
self.party.addresses[0].id if self.party.addresses else None
|
|
|
|
@fields.depends('lines')
|
|
def on_change_with_total_order(self, name=None):
|
|
total = Decimal('0.0')
|
|
if self.lines:
|
|
for line in self.lines:
|
|
if line.total_amount:
|
|
total += Decimal(line.total_amount)
|
|
return total
|
|
|
|
@fields.depends('party')
|
|
def on_change_with_order_mobile(self, name=None):
|
|
if self.party:
|
|
pool = Pool()
|
|
ContactMechanism = pool.get('party.contact_mechanism')
|
|
mechanisms = ContactMechanism.search([
|
|
('party', '=', self.party.id),
|
|
('type', '=', 'mobile')
|
|
])
|
|
if mechanisms:
|
|
return mechanisms[0].value
|
|
return
|
|
|
|
@classmethod
|
|
@ModelView.button
|
|
@Workflow.transition('confirmed')
|
|
def confirm(cls, orders):
|
|
for order in orders:
|
|
if order.number:
|
|
continue
|
|
else:
|
|
cls.set_code([order])
|
|
|
|
|
|
class OrderLine(ModelView, ModelSQL):
|
|
"Order Line"
|
|
__name__ = 'order.line'
|
|
|
|
_states = {
|
|
'readonly': Eval('_parent_order.state').in_(['confirmed'])
|
|
}
|
|
order = fields.Many2One(
|
|
'sale.order', "Order")
|
|
company = fields.Many2One(
|
|
'company.company', "Company", states={
|
|
'readonly': True,
|
|
'required': True
|
|
})
|
|
currency = fields.Many2One(
|
|
'currency.currency', 'Currency', states={
|
|
'readonly': True,
|
|
'required': True
|
|
})
|
|
product = fields.Many2One(
|
|
'product.product', 'Product', required=True, states=_states)
|
|
unit = fields.Many2One(
|
|
'product.uom', 'Unit', required=True, states=_states
|
|
)
|
|
product_uom_category = fields.Function(
|
|
fields.Many2One('product.uom.category', 'Product UOM Category'),
|
|
'on_change_with_product_uom_category')
|
|
quantity = fields.Float(
|
|
"Quantity", digits=('unit'), required=True, states=_states)
|
|
unitprice = Monetary(
|
|
"Unit Price",
|
|
digits=price_digits,
|
|
currency='currency', required=True, states=_states)
|
|
total_amount = fields.Function(
|
|
Monetary("Total Amount", currency='currency', digits='currency'),
|
|
'on_change_with_total_amount')
|
|
|
|
@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
|
|
|
|
@fields.depends('product')
|
|
def on_change_product(self):
|
|
if self.product:
|
|
self.unit = self.product.default_uom.id
|
|
|
|
@fields.depends('product')
|
|
def on_change_with_product_uom_category(self, name=None):
|
|
if self.product:
|
|
return self.product.default_uom.category.id
|
|
return None
|
|
|
|
@fields.depends('quantity', 'unitprice')
|
|
def on_change_with_total_amount(self, name=None):
|
|
if self.unitprice and self.quantity:
|
|
total_amount = self.unitprice * Decimal(self.quantity)
|
|
|
|
return total_amount
|