trytond-sale_cost_apply_pur.../sale_cost.py

156 lines
5.4 KiB
Python

# The COPYRIGHT file at the top level of this repository contains the full
# copyright notices and license terms.
from decimal import Decimal
from trytond.pool import PoolMeta, Pool
from trytond.model import fields
from trytond.pyson import Eval, Not, Bool, Or
from trytond.transaction import Transaction
from trytond.exceptions import UserError
from trytond.i18n import gettext
from sql.operators import Concat
from functools import partial
from itertools import groupby
class SaleCost(metaclass=PoolMeta):
__name__ = 'sale.cost'
purchase = fields.Function(
fields.Many2One('purchase.purchase', 'Purchase', readonly=True,
states={
'invisible': Eval('apply_method', '') != 'purchase'
}, depends=['apply_method']), 'get_purchase')
purchase_lines = fields.One2Many('purchase.line', 'origin',
'Purchase lines',
states={
'invisible': Eval('apply_method', '') != 'purchase'
}, depends=['apply_method'])
@classmethod
def __setup__(cls):
super().__setup__()
invisible_condition = cls._buttons['apply']['invisible']
cls._buttons['apply']['invisible'] = Or(
invisible_condition,
Bool(Eval('purchase')))
cls._buttons['apply']['depends'].append('purchase')
invisible_condition = cls._buttons['unapply']['invisible']
cls._buttons['unapply']['invisible'] = Or(
invisible_condition,
Not(Bool(Eval('purchase'))))
cls._buttons['unapply']['depends'].append('purchase')
cls.apply_method.selection.append(('purchase', 'Purchase'))
cls.invoice_party.states['invisible'] &= (
Eval('apply_method') != 'purchase')
@classmethod
def __register__(cls, module_name):
table = cls.__table_handler__(module_name)
Purchase_lines = Pool().get('purchase.line')
cursor = Transaction().connection.cursor()
sql_table = cls.__table__()
purchase_line = Purchase_lines.__table__()
purchase_exists = table.column_exist('purchase')
super(SaleCost, cls).__register__(module_name)
if purchase_exists:
cursor.execute(*purchase_line.join(sql_table,
condition=purchase_line.purchase == sql_table.purchase
).select(
purchase_line.id,
sql_table.id,
where=(purchase_line.type == 'line'))
)
for pline_id, cost_id in cursor.fetchall():
cursor.execute(*purchase_line.update(
columns=[purchase_line.origin],
values=[Concat(cls.__name__ + ',', cost_id)],
where=purchase_line.id == pline_id
))
table.drop_column('purchase')
def get_purchase(self, name=None):
if self.purchase_lines:
return self.purchase_lines[0].purchase.id
@classmethod
def _apply_method(cls, apply_method, costs):
Purchase = Pool().get('purchase.purchase')
if apply_method != 'purchase':
return super()._apply_method(apply_method, costs)
cost_keyfunc = partial(cls._get_purchase_keygroup)
sorted_cost_lines = sorted(costs, key=cost_keyfunc)
purchases = []
for key, grouped_lines in groupby(sorted_cost_lines, key=cost_keyfunc):
purchase = Purchase(**dict(key))
purchase.on_change_party()
lines = []
group_lines = list(grouped_lines)
for cost in group_lines:
lines.append(cost._get_purchase_line(purchase))
purchase.lines = lines
purchases.append(purchase)
Purchase.save(purchases)
Purchase.quote(purchases)
return []
def _get_purchase_line(self, purchase):
pool = Pool()
PurchaseLine = pool.get('purchase.line')
line = PurchaseLine()
line.purchase = purchase
line.type = 'line'
line.product = self.type_.product
line.on_change_product()
line.quantity = self.quantity
line.on_change_quantity()
digits = PurchaseLine.unit_price.digits[1]
line.unit_price = (self.amount / Decimal(str(self.quantity))
).quantize(Decimal(10) ** -Decimal(digits))
line.amount = line.on_change_with_amount()
line.origin = self
return line
@classmethod
def _get_purchase_keygroup(cls, cost):
if not cost.invoice_party:
raise UserError(gettext('document_cost_apply_invoice.'
'msg_document_cost_apply_invoice_invoice_no_party',
type_=cost.type_.rec_name,
cost=cost.document.rec_name))
return [
('company', cost.document.company),
('party', cost.invoice_party),
('purchase_date', cost.sale.sale_date)]
@classmethod
def _unapply_method(cls, apply_method, costs):
pool = Pool()
Purchase = pool.get('purchase.purchase')
if apply_method != 'purchase':
super(SaleCost, cls)._unapply_method(apply_method, costs)
purchases = Purchase.search([
('id', 'in', [c.purchase.id for c in costs if c.purchase])])
if purchases:
Purchase.delete(purchases)
class CostType(metaclass=PoolMeta):
__name__ = 'sale.cost.type'
@classmethod
def __setup__(cls):
super(CostType, cls).__setup__()
cls.apply_method.selection.append(('purchase', 'Purchase'))