docx_report_generation/wizard/res_partner_contract_wizard.py

247 lines
8.2 KiB
Python
Raw Normal View History

2019-12-04 16:48:47 +05:00
import base64
import logging
2018-11-08 17:16:01 +05:00
2020-01-17 18:01:53 +05:00
from odoo import api, fields, models
2020-01-15 18:34:01 +05:00
from odoo.exceptions import ValidationError
2018-11-08 17:16:01 +05:00
2019-12-28 15:09:32 +05:00
from ..utils import MODULE_NAME
2019-12-04 16:48:47 +05:00
from ..utils.docxtpl import get_document_from_values_stream
2020-01-29 13:57:03 +05:00
from ..utils.misc import Extension
2018-11-08 17:16:01 +05:00
_logger = logging.getLogger(__name__)
2019-12-12 17:23:54 +05:00
2020-01-29 13:57:03 +05:00
class ContractWizard(models.TransientModel, Extension):
2019-12-17 09:53:47 +05:00
_name = "res.partner.contract.wizard"
2018-11-08 17:16:01 +05:00
def _default_target(self):
return "{model},{target_id}".format(
model=self.active_model, target_id=int(self.env.context.get("self_id"))
)
2020-01-27 15:12:59 +05:00
def _default_document_template(self):
return self.env["res.partner.document.template"].search(self._get_template_domain(), limit=1)
def _get_template_domain(self):
template_type = {
"res.partner.contract": "contract",
"res.partner.contract.annex": "annex",
}.get(self.active_model, False)
company_type = (
self.partner_id.company_form if self.partner_id.is_company else "person"
)
document_template_domain = [
("template_type", "=", template_type),
("company_type", "=", company_type),
]
return document_template_domain
target = fields.Reference(
selection=[
("res.partner.contract", "Contract"),
("res.partner.contract.annex", "Contract Annex"),
],
string="Target",
default=_default_target,
2019-11-12 16:16:14 +05:00
)
2020-01-20 19:34:25 +05:00
company_id = fields.Many2one(
"res.partner", string="Company", compute="_compute_company_id",
)
partner_id = fields.Many2one(
"res.partner", string="Partner", compute="_compute_partner_id",
)
2020-01-21 16:07:57 +05:00
document_name = fields.Char(
string="Document Name", compute="_compute_document_name"
)
document_template = fields.Many2one(
2020-01-20 18:48:12 +05:00
"res.partner.document.template",
string="Document Template",
2020-01-27 15:12:59 +05:00
default=_default_document_template,
readonly=False,
2020-01-20 18:48:12 +05:00
)
transient_field_ids = fields.One2many(
2019-12-17 09:53:47 +05:00
"res.partner.contract.field.transient",
"_contract_wizard_id",
string="Contract Fields",
)
transient_field_ids_hidden = fields.One2many(
"res.partner.contract.field.transient", "_contract_wizard_id",
)
@api.depends("company_id", "target")
def _compute_company_id(self):
if self.target:
self.company_id = self.target.company_id
@api.depends("partner_id", "target")
def _compute_partner_id(self):
if self.target:
self.partner_id = self.target.partner_id
2020-01-20 18:48:12 +05:00
@api.depends("document_name", "document_template", "target")
def _compute_document_name(self):
2020-01-20 18:48:12 +05:00
self.document_name = self.target.get_name_by_document_template(
self.document_template
)
2020-01-21 16:07:57 +05:00
@api.constrains("document_template")
def _check_document_template(self):
if not self.document_template:
raise ValidationError("You did not set up the template...")
@api.onchange('document_template')
def _domain_document_template(self):
return {
"domain": {
"document_template": self._get_template_domain(),
}
}
@api.onchange("document_template")
2020-01-13 18:02:42 +05:00
def _onchange_document_template(self):
"""Creates transient fields for generate contract template
Looks as a tree view of *_contract_field_transient model in xml
"""
2019-12-17 09:53:47 +05:00
def get_contract_field(technical_name):
2019-12-17 09:53:47 +05:00
return self.env["res.partner.contract.field"].search(
[("technical_name", "=", technical_name),]
)
model_to_action = {
2020-01-17 17:58:20 +05:00
"res.partner.contract": "action_get_contract_context",
"res.partner.contract.annex": "action_get_annex_context",
}
2020-01-17 17:58:20 +05:00
action = "{}.{}".format(MODULE_NAME, model_to_action[self.active_model])
# Get dictionary for `transient_fields_ids` with editable fields
# With data from Odoo database
2019-12-17 09:53:47 +05:00
contract_context_values = (
self.env.ref(action).with_context({"onchange_self": self.target}).run()
2019-12-17 09:53:47 +05:00
)
self.transient_field_ids = [ # one2many
(
4,
2019-12-17 09:53:47 +05:00
self.env["res.partner.contract.field.transient"]
.create(
{"contract_field_id": get_contract_field(field).id, "value": value,}
)
.id,
0,
2019-12-17 09:53:47 +05:00
)
2019-12-30 16:02:07 +05:00
for field, value in sorted(
contract_context_values.items(),
key=lambda tpl: self.env.ref(
"{}.contract_field_{}".format(MODULE_NAME, tpl[0])
).sequence,
)
]
self.transient_field_ids_hidden = (
self.transient_field_ids - self.transient_field_ids.filtered("visible")
)
self.transient_field_ids = (
self.transient_field_ids - self.transient_field_ids_hidden
)
2020-01-21 16:07:57 +05:00
# Other
@api.multi
2018-11-08 17:16:01 +05:00
def get_docx_contract(self):
2020-01-13 17:37:35 +05:00
template = self.document_template.attachment_id
2020-01-27 13:56:09 +05:00
template_path = template._full_path(template.store_fname)
2020-01-27 13:56:09 +05:00
payload = self.payload()
binary_data = get_document_from_values_stream(template_path, payload).read()
encoded_data = base64.b64encode(binary_data)
get_fn = self.target.get_filename_by_document_template
attachment_name = "{}.docx".format(get_fn(self.document_template or "Unknown"))
2020-01-27 13:56:09 +05:00
document_as_attachment = self.env["ir.attachment"].create(
{
"name": attachment_name,
"datas_fname": attachment_name,
"type": "binary",
"datas": encoded_data,
}
)
return self.afterload(document_as_attachment)
def payload(self):
# Collect fields into a key-value structure
fields = {
transient_field.technical_name: transient_field.value
for transient_field in (
self.transient_field_ids + self.transient_field_ids_hidden
)
}
# Extend with special case
if self.target._name == "res.partner.contract.annex":
2020-01-20 18:48:12 +05:00
fields.update(
{
"annex_name": self.document_name,
"specification_name": self.target.specification_name,
}
)
# Extend with order product lines
if hasattr(self.target, "order_id") and self.target.order_id.order_line:
def number_generator(n=1):
while (True):
yield n
n += 1
counter = number_generator()
fields.update(
{
"products": [
{
"number": next(counter),
"label": item.product_id.name,
"description": item.product_id.description_sale,
"count": item.product_uom_qty,
"unit": item.product_uom.name,
2020-01-29 15:28:54 +05:00
"cost": self.to_fixed(item.price_unit),
"subtotal": self.to_fixed(item.price_subtotal),
} for item in self.target.order_id.order_line or []
],
"total_amount": self.to_fixed(sum(self.target.order_id.order_line.mapped("price_subtotal")))
}
)
return self.middleware_fields(fields)
2019-12-04 16:54:42 +05:00
2020-01-27 13:56:09 +05:00
def afterload(self, result):
res_id = self.target.id
if hasattr(self.target, "contract_id"):
res_id = self.target.contract_id.id
self.env["mail.message"].create(
2019-12-17 09:53:47 +05:00
{
"model": "res.partner.contract",
"res_id": res_id,
2019-12-17 09:53:47 +05:00
"message_type": "comment",
2020-01-27 13:56:09 +05:00
"attachment_ids": [(4, result.id, False)],
2019-12-17 09:53:47 +05:00
}
)
return result
2020-01-21 16:07:57 +05:00
def middleware_fields(self, kv):
# Debug False values
empty = []
for k,v in list(kv.items()):
if not v:
empty.append(k)
kv.pop(k)
_logger.debug("Empty fields: {}".format(empty))
return kv
@property
def active_model(self):
return self.env.context.get("active_model")