Exemple #1
0
class PartnerTitle(models.Model):
    _name = 'res.partner.title'
    _order = 'name'
    _description = 'Partner Title'

    name = fields.Char(string='Title', required=True, translate=True)
    shortcut = fields.Char(string='Abbreviation', translate=True)
class Company(models.Model):
    _inherit = 'res.company'

    street_name = fields.Char('Street Name',
                              compute='_compute_address',
                              inverse='_inverse_street')
    street_number = fields.Char('House Number',
                                compute='_compute_address',
                                inverse='_inverse_street')
    street_number2 = fields.Char('Door Number',
                                 compute='_compute_address',
                                 inverse='_inverse_street')

    def _get_company_address_fields(self, partner):
        address_fields = super(Company,
                               self)._get_company_address_fields(partner)
        address_fields.update({
            'street_name': partner.street_name,
            'street_number': partner.street_number,
            'street_number2': partner.street_number2,
        })
        return address_fields

    def _inverse_street(self):
        for company in self:
            company.partner_id.write({
                'street_name': company.street_name,
                'street_number': company.street_number,
                'street_number2': company.street_number2
            })
class ResConfigSettings(models.TransientModel):
    _inherit = 'res.config.settings'

    @api.model
    def get_uri(self):
        return "%s/auth_oauth/signin" % (
            self.env['ir.config_parameter'].get_param('web.base.url'))

    auth_oauth_google_enabled = fields.Boolean(
        string='Allow users to sign in with Google')
    auth_oauth_google_client_id = fields.Char(string='Client ID')
    server_uri_google = fields.Char(string='Server uri')

    @api.model
    def get_values(self):
        res = super(ResConfigSettings, self).get_values()
        google_provider = self.env.ref('auth_oauth.provider_google', False)
        res.update(
            auth_oauth_google_enabled=google_provider.enabled,
            auth_oauth_google_client_id=google_provider.client_id,
            server_uri_google=self.get_uri(),
        )
        return res

    def set_values(self):
        super(ResConfigSettings, self).set_values()
        google_provider = self.env.ref('auth_oauth.provider_google', False)
        google_provider.write({
            'enabled': self.auth_oauth_google_enabled,
            'client_id': self.auth_oauth_google_client_id,
        })
class MailResendCancel(models.TransientModel):
    _name = 'mail.resend.cancel'
    _description = 'Dismiss notification for resend by model'

    model = fields.Char(string='Model')
    help_message = fields.Char(string='Help message', compute='_compute_help_message')

    @api.depends('model')
    def _compute_help_message(self):
        for wizard in self:
            wizard.help_message = _("Are you sure you want to discard %s mail delivery failures. You won't be able to re-send these mails later!") % (wizard._context.get('unread_counter'))

    def cancel_resend_action(self):
        author_id = self.env.user.partner_id.id
        for wizard in self:
            self._cr.execute("""
                                SELECT notif.id, mes.id
                                FROM mail_message_res_partner_needaction_rel notif
                                JOIN mail_message mes
                                    ON notif.mail_message_id = mes.id
                                WHERE notif.notification_status IN ('bounce', 'exception')
                                    AND mes.model = %s
                                    AND mes.author_id = %s
                            """, (wizard.model, author_id))
            res = self._cr.fetchall()
            notif_ids = [row[0] for row in res]
            messages_ids = list(set([row[1] for row in res]))
            if notif_ids:
                self.env["mail.notification"].browse(notif_ids).sudo().write({'notification_status': 'canceled'})
                self.env["mail.message"].browse(messages_ids)._notify_mail_failure_update()
        return {'type': 'ir.actions.act_window_close'}
Exemple #5
0
class MrpRouting(models.Model):
    """ Specifies routings of work centers """
    _name = 'mrp.routing'
    _description = 'Routings'

    name = fields.Char('Routing', required=True)
    active = fields.Boolean(
        'Active',
        default=True,
        help=
        "If the active field is set to False, it will allow you to hide the routing without removing it."
    )
    code = fields.Char('Reference',
                       copy=False,
                       default=lambda self: _('New'),
                       readonly=True)
    note = fields.Text('Description')
    operation_ids = fields.One2many('mrp.routing.workcenter',
                                    'routing_id',
                                    'Operations',
                                    copy=True)
    company_id = fields.Many2one('res.company',
                                 'Company',
                                 default=lambda self: self.env.company)

    @api.model
    def create(self, vals):
        if 'code' not in vals or vals['code'] == _('New'):
            vals['code'] = self.env['ir.sequence'].next_by_code(
                'mrp.routing') or _('New')
        return super(MrpRouting, self).create(vals)
class RegistrationEditorLine(models.TransientModel):
    """Event Registration"""
    _name = "registration.editor.line"
    _description = 'Edit Attendee Line on Sales Confirmation'

    editor_id = fields.Many2one('registration.editor')
    sale_order_line_id = fields.Many2one('sale.order.line', string='Sales Order Line')
    event_id = fields.Many2one('event.event', string='Event', required=True)
    registration_id = fields.Many2one('event.registration', 'Original Registration')
    event_ticket_id = fields.Many2one('event.event.ticket', string='Event Ticket')
    email = fields.Char(string='Email')
    phone = fields.Char(string='Phone')
    mobile = fields.Char(string='Mobile')
    name = fields.Char(string='Name', index=True)

    def get_registration_data(self):
        self.ensure_one()
        return {
            'event_id': self.event_id.id,
            'event_ticket_id': self.event_ticket_id.id,
            'partner_id': self.editor_id.sale_order_id.partner_id.id,
            'name': self.name or self.editor_id.sale_order_id.partner_id.name,
            'phone': self.phone or self.editor_id.sale_order_id.partner_id.phone,
            'mobile': self.mobile or self.editor_id.sale_order_id.partner_id.mobile,
            'email': self.email or self.editor_id.sale_order_id.partner_id.email,
            'origin': self.editor_id.sale_order_id.name,
            'sale_order_id': self.editor_id.sale_order_id.id,
            'sale_order_line_id': self.sale_order_line_id.id,
        }
Exemple #7
0
class ResCompany(models.Model):
    _inherit = 'res.company'

    pad_server = fields.Char(
        help="Etherpad lite server. Example: beta.primarypad.com")
    pad_key = fields.Char('Pad Api Key',
                          help="Etherpad lite api key.",
                          groups="base.group_system")
Exemple #8
0
class ResPartnerIndustry(models.Model):
    _description = 'Industry'
    _name = "res.partner.industry"
    _order = "name"

    name = fields.Char('Name', translate=True)
    full_name = fields.Char('Full Name', translate=True)
    active = fields.Boolean('Active', default=True)
Exemple #9
0
class User(models.Model):
    _inherit = "res.users"

    leave_manager_id = fields.Many2one(related='employee_id.leave_manager_id')
    show_leaves = fields.Boolean(related='employee_id.show_leaves')
    allocation_used_count = fields.Float(
        related='employee_id.allocation_used_count')
    allocation_count = fields.Float(related='employee_id.allocation_count')
    leave_date_to = fields.Date(related='employee_id.leave_date_to')
    is_absent = fields.Boolean(related='employee_id.is_absent')
    allocation_used_display = fields.Char(
        related='employee_id.allocation_used_display')
    allocation_display = fields.Char(related='employee_id.allocation_display')

    def __init__(self, pool, cr):
        """ Override of __init__ to add access rights.
            Access rights are disabled by default, but allowed
            on some specific fields defined in self.SELF_{READ/WRITE}ABLE_FIELDS.
        """

        readable_fields = [
            'leave_manager_id',
            'show_leaves',
            'allocation_used_count',
            'allocation_count',
            'leave_date_to',
            'is_absent',
            'allocation_used_display',
            'allocation_display',
        ]
        init_res = super(User, self).__init__(pool, cr)
        # duplicate list to avoid modifying the original reference
        type(self).SELF_READABLE_FIELDS = type(
            self).SELF_READABLE_FIELDS + readable_fields
        return init_res

    def _compute_im_status(self):
        super(User, self)._compute_im_status()
        on_leave_user_ids = self._get_on_leave_ids()
        for user in self:
            if user.id in on_leave_user_ids:
                if user.im_status == 'online':
                    user.im_status = 'leave_online'
                else:
                    user.im_status = 'leave_offline'

    @api.model
    def _get_on_leave_ids(self, partner=False):
        now = fields.Datetime.now()
        field = 'partner_id' if partner else 'id'
        self.env.cr.execute(
            '''SELECT res_users.%s FROM res_users
                            JOIN hr_leave ON hr_leave.user_id = res_users.id
                            AND state not in ('cancel', 'refuse')
                            AND res_users.active = 't'
                            AND date_from <= %%s AND date_to >= %%s''' % field,
            (now, now))
        return [r[0] for r in self.env.cr.fetchall()]
Exemple #10
0
class ReportLayout(models.Model):
    _name = "report.layout"
    _description = 'Report Layout'

    view_id = fields.Many2one('ir.ui.view', 'Document Template', required=True)
    image = fields.Char(string="Preview image src")
    pdf = fields.Char(string="Preview pdf src")

    name = fields.Char()
class ResConfigSettings(models.TransientModel):
    _inherit = 'res.config.settings'

    pad_server = fields.Char(related='company_id.pad_server',
                             string="Pad Server *",
                             readonly=False)
    pad_key = fields.Char(related='company_id.pad_key',
                          string="Pad Api Key *",
                          readonly=False)
Exemple #12
0
class MailTestSimple(models.Model):
    """ A very simple model only inheriting from mail.thread when only
    communication history is necessary. """
    _description = 'Simple Chatter Model'
    _name = 'mail.test.simple'
    _inherit = ['mail.thread']

    name = fields.Char()
    email_from = fields.Char()
Exemple #13
0
class ProductCategory(models.Model):
    _name = "product.category"
    _description = "Product Category"
    _parent_name = "parent_id"
    _parent_store = True
    _rec_name = 'complete_name'
    _order = 'complete_name'

    name = fields.Char('Name', index=True, required=True)
    complete_name = fields.Char('Complete Name',
                                compute='_compute_complete_name',
                                store=True)
    parent_id = fields.Many2one('product.category',
                                'Parent Category',
                                index=True,
                                ondelete='cascade')
    parent_path = fields.Char(index=True)
    child_id = fields.One2many('product.category', 'parent_id',
                               'Child Categories')
    product_count = fields.Integer(
        '# Products',
        compute='_compute_product_count',
        help=
        "The number of products under this category (Does not consider the children categories)"
    )

    @api.depends('name', 'parent_id.complete_name')
    def _compute_complete_name(self):
        for category in self:
            if category.parent_id:
                category.complete_name = '%s / %s' % (
                    category.parent_id.complete_name, category.name)
            else:
                category.complete_name = category.name

    def _compute_product_count(self):
        read_group_res = self.env['product.template'].read_group(
            [('categ_id', 'child_of', self.ids)], ['categ_id'], ['categ_id'])
        group_data = dict((data['categ_id'][0], data['categ_id_count'])
                          for data in read_group_res)
        for categ in self:
            product_count = 0
            for sub_categ_id in categ.search([('id', 'child_of', categ.ids)
                                              ]).ids:
                product_count += group_data.get(sub_categ_id, 0)
            categ.product_count = product_count

    @api.constrains('parent_id')
    def _check_category_recursion(self):
        if not self._check_recursion():
            raise ValidationError(_('You cannot create recursive categories.'))
        return True

    @api.model
    def name_create(self, name):
        return self.create({'name': name}).name_get()[0]
class AccountAnalyticLine(models.Model):
    _inherit = 'account.analytic.line'
    _description = 'Analytic Line'
    _order = 'date desc'

    product_id = fields.Many2one(
        'product.product',
        string='Product',
        domain=
        "['|', ('company_id', '=', False), ('company_id', '=', company_id)]")
    general_account_id = fields.Many2one('account.account',
                                         string='Financial Account',
                                         ondelete='restrict',
                                         readonly=True,
                                         related='move_id.account_id',
                                         store=True,
                                         domain=[('deprecated', '=', False)],
                                         compute_sudo=True)
    move_id = fields.Many2one('account.move.line',
                              string='Journal Item',
                              ondelete='cascade',
                              index=True)
    code = fields.Char(size=8)
    ref = fields.Char(string='Ref.')

    @api.onchange('product_id', 'product_uom_id', 'unit_amount', 'currency_id')
    def on_change_unit_amount(self):
        if not self.product_id:
            return {}

        result = 0.0
        prod_accounts = self.product_id.product_tmpl_id._get_product_accounts()
        unit = self.product_uom_id
        account = prod_accounts['expense']
        if not unit or self.product_id.uom_po_id.category_id.id != unit.category_id.id:
            unit = self.product_id.uom_po_id

        # Compute based on pricetype
        amount_unit = self.product_id.price_compute(
            'standard_price', uom=unit)[self.product_id.id]
        amount = amount_unit * self.unit_amount or 0.0
        result = (self.currency_id.round(amount)
                  if self.currency_id else round(amount, 2)) * -1
        self.amount = result
        self.general_account_id = account
        self.product_uom_id = unit

    @api.model
    def view_header_get(self, view_id, view_type):
        context = (self._context or {})
        header = False
        if context.get('account_id', False):
            analytic_account = self.env['account.analytic.account'].search(
                [('id', '=', context['account_id'])], limit=1)
            header = _('Entries: ') + (analytic_account.name or '')
        return header
Exemple #15
0
class BaseLanguageImport(models.TransientModel):
    _name = "base.language.import"
    _description = "Language Import"

    name = fields.Char('Language Name', required=True)
    code = fields.Char('ISO Code',
                       size=6,
                       required=True,
                       help="ISO Language and Country code, e.g. en_US")
    data = fields.Binary('File', required=True, attachment=False)
    filename = fields.Char('File Name', required=True)
    overwrite = fields.Boolean(
        'Overwrite Existing Terms',
        default=True,
        help=
        "If you enable this option, existing translations (including custom ones) "
        "will be overwritten and replaced by those in this file")

    def import_lang(self):
        this = self[0]
        this = this.with_context(overwrite=this.overwrite)
        with TemporaryFile('wb+') as buf:
            try:
                buf.write(base64.decodestring(this.data))

                # now we determine the file format
                buf.seek(0)
                fileformat = os.path.splitext(this.filename)[-1][1:].lower()

                tools.trans_load_data(this._cr,
                                      buf,
                                      fileformat,
                                      this.code,
                                      lang_name=this.name,
                                      context=this._context)
            except ProgrammingError as e:
                _logger.exception(
                    'File unsuccessfully imported, due to a malformed file.')

                with closing(sql_db.db_connect(
                        self._cr.dbname).cursor()) as cr:
                    raise UserError(
                        _('File %r not imported due to a malformed file.\n\n' +
                          'This issue can be caused by duplicates entries who are referring to the same field. '
                          +
                          'Please check the content of the file you are trying to import.\n\n'
                          + 'Technical Details:\n%s') % tools.ustr(e))
            except Exception as e:
                _logger.exception(
                    'File unsuccessfully imported, due to format mismatch.')
                raise UserError(
                    _('File %r not imported due to format mismatch or a malformed file.'
                      ' (Valid formats are .csv, .po, .pot)\n\nTechnical Details:\n%s') % \
                    (this.filename, tools.ustr(e))
                )
        return True
Exemple #16
0
class L10nPeResCityDistrict(models.Model):
    _name = 'l10n_pe.res.city.district'
    _description = 'District'
    _order = 'name'

    name = fields.Char(translate=True)
    city_id = fields.Many2one('res.city', 'City')
    code = fields.Char(
        help='This code will help with the identification of each district '
        'in Peru.')
Exemple #17
0
class AccountChartTemplate(models.Model):
    _inherit = 'account.chart.template'
    _order = 'name'

    name = fields.Char(translate=True)
    spoken_languages = fields.Char(
        string='Spoken Languages',
        help=
        "State here the languages for which the translations of templates could be loaded at the time of installation of this localization module and copied in the final object when generating them from templates. You must provide the language codes separated by ';'"
    )
Exemple #18
0
class Edition(models.Model):
    _name = 'test_new_api.creativework.edition'
    _description = 'Test New API Creative Work Edition'

    name = fields.Char()
    res_id = fields.Integer(required=True)
    res_model_id = fields.Many2one('ir.model', required=True)
    res_model = fields.Char(related='res_model_id.model',
                            store=True,
                            readonly=False)
Exemple #19
0
class MassMailTest(models.Model):
    """ A very simple model only inheriting from mail.thread to test pure mass
    mailing features and base performances. """
    _description = 'Simple Mass Mailing Model'
    _name = 'mass.mail.test'
    _inherit = ['mail.thread', 'mail.address.mixin']
    _primary_email = 'email_from'

    name = fields.Char()
    email_from = fields.Char()
Exemple #20
0
class MailTestGateway(models.Model):
    """ A very simple model only inheriting from mail.thread to test pure mass
    mailing features and base performances. """
    _description = 'Simple Chatter Model for Mail Gateway'
    _name = 'mail.test.gateway'
    _inherit = ['mail.thread.blacklist']
    _primary_email = 'email_from'

    name = fields.Char()
    email_from = fields.Char()
    custom_field = fields.Char()
Exemple #21
0
class ComputeProtected(models.Model):
    _name = 'test_new_api.compute.protected'
    _description = 'Test New API Compute Protected'

    foo = fields.Char(default='')
    bar = fields.Char(compute='_compute_bar', store=True)

    @api.depends('foo')
    def _compute_bar(self):
        for record in self:
            record.bar = record.foo
Exemple #22
0
class MailingTraceReport(models.Model):
    _name = 'mailing.trace.report'
    _auto = False
    _description = 'Mass Mailing Statistics'

    # mailing
    name = fields.Char(string='Mass Mail', readonly=True)
    mailing_type = fields.Selection([('mail', 'Mail')],
                                    string='Type',
                                    default='mail',
                                    required=True)
    campaign = fields.Char(string='Mass Mail Campaign', readonly=True)
    scheduled_date = fields.Datetime(string='Scheduled Date', readonly=True)
    state = fields.Selection([('draft', 'Draft'), ('test', 'Tested'),
                              ('done', 'Sent')],
                             string='Status',
                             readonly=True)
    email_from = fields.Char('From', readonly=True)
    # traces
    sent = fields.Integer(readonly=True)
    delivered = fields.Integer(readonly=True)
    opened = fields.Integer(readonly=True)
    replied = fields.Integer(readonly=True)
    clicked = fields.Integer(readonly=True)
    bounced = fields.Integer(readonly=True)

    def init(self):
        """Mass Mail Statistical Report: based on mailing.trace that models the various
        statistics collected for each mailing, and mailing.mailing model that models the
        various mailing performed. """
        tools.drop_view_if_exists(self.env.cr, 'mailing_trace_report')
        self.env.cr.execute("""
            CREATE OR REPLACE VIEW mailing_trace_report AS (
                SELECT
                    min(trace.id) as id,
                    utm_source.name as name,
                    mailing.mailing_type,
                    utm_campaign.name as campaign,
                    trace.scheduled as scheduled_date,
                    mailing.state,
                    mailing.email_from,
                    count(trace.sent) as sent,
                    (count(trace.sent) - count(trace.bounced)) as delivered,
                    count(trace.opened) as opened,
                    count(trace.replied) as replied,
                    count(trace.clicked) as clicked,
                    count(trace.bounced) as bounced
                FROM
                    mailing_trace as trace
                    left join mailing_mailing as mailing ON (trace.mass_mailing_id=mailing.id)
                    left join utm_campaign as utm_campaign ON (mailing.campaign_id = utm_campaign.id)
                    left join utm_source as utm_source ON (mailing.source_id = utm_source.id)
                GROUP BY trace.scheduled, utm_source.name, utm_campaign.name, mailing.mailing_type, mailing.state, mailing.email_from
            )""")
Exemple #23
0
class IrExports(models.Model):
    _name = "ir.exports"
    _description = 'Exports'
    _order = 'name'

    name = fields.Char(string='Export Name')
    resource = fields.Char(index=True)
    export_fields = fields.One2many('ir.exports.line',
                                    'export_id',
                                    string='Export ID',
                                    copy=True)
Exemple #24
0
class MailTestStandard(models.Model):
    """ This model can be used in tests when automatic subscription and simple
    tracking is necessary. Most features are present in a simple way. """
    _description = 'Standard Chatter Model'
    _name = 'mail.test.track'
    _inherit = ['mail.thread']

    name = fields.Char()
    email_from = fields.Char()
    user_id = fields.Many2one('res.users', 'Responsible', tracking=True)
    umbrella_id = fields.Many2one('mail.test', tracking=True)
    company_id = fields.Many2one('res.company')
Exemple #25
0
class ModuleCategory(models.Model):
    _name = "ir.module.category"
    _description = "Application"
    _order = 'name'

    @api.depends('module_ids')
    def _compute_module_nr(self):
        cr = self._cr
        cr.execute(
            'SELECT category_id, COUNT(*) \
                      FROM ir_module_module \
                     WHERE category_id IN %(ids)s \
                        OR category_id IN (SELECT id \
                                             FROM ir_module_category \
                                            WHERE parent_id IN %(ids)s) \
                     GROUP BY category_id', {'ids': tuple(self.ids)})
        result = dict(cr.fetchall())
        for cat in self.filtered('id'):
            cr.execute('SELECT id FROM ir_module_category WHERE parent_id=%s',
                       (cat.id, ))
            cat.module_nr = sum([result.get(c, 0) for (c, ) in cr.fetchall()],
                                result.get(cat.id, 0))

    name = fields.Char(string='Name',
                       required=True,
                       translate=True,
                       index=True)
    parent_id = fields.Many2one('ir.module.category',
                                string='Parent Application',
                                index=True)
    child_ids = fields.One2many('ir.module.category',
                                'parent_id',
                                string='Child Applications')
    module_nr = fields.Integer(string='Number of Apps',
                               compute='_compute_module_nr')
    module_ids = fields.One2many('ir.module.module',
                                 'category_id',
                                 string='Modules')
    description = fields.Text(string='Description', translate=True)
    sequence = fields.Integer(string='Sequence')
    visible = fields.Boolean(string='Visible', default=True)
    exclusive = fields.Boolean(string='Exclusive')
    xml_id = fields.Char(string='External ID', compute='_compute_xml_id')

    def _compute_xml_id(self):
        xml_ids = defaultdict(list)
        domain = [('model', '=', self._name), ('res_id', 'in', self.ids)]
        for data in self.env['ir.model.data'].sudo().search_read(
                domain, ['module', 'name', 'res_id']):
            xml_ids[data['res_id']].append("%s.%s" %
                                           (data['module'], data['name']))
        for cat in self:
            cat.xml_id = xml_ids.get(cat.id, [''])[0]
Exemple #26
0
class IndustryTag(models.Model):
    """ Industry Tags of Acquisition Rules """
    _name = 'crm.iap.lead.industry'
    _description = 'Industry Tag'

    name = fields.Char(string='Tag Name', required=True, translate=True)
    reveal_id = fields.Char(required=True)
    color = fields.Integer(string='Color Index')

    _sql_constraints = [
        ('name_uniq', 'unique (name)', 'Tag name already exists!'),
    ]
Exemple #27
0
class mother(models.Model):
    _name = 'test.inherit.mother'
    _description = 'Test Inherit Mother'

    name = fields.Char(default='Foo')
    state = fields.Selection([('a', 'A'), ('b', 'B')], default='a')
    surname = fields.Char(compute='_compute_surname')

    @api.depends('name')
    def _compute_surname(self):
        for rec in self:
            rec.surname = rec.name or ''
Exemple #28
0
class L10nInPortCode(models.Model):
    """Port code must be mentioned in export and import of goods under GST."""
    _name = 'l10n_in.port.code'
    _description = "Indian port code"
    _rec_name = 'code'

    code = fields.Char(string="Port Code", required=True)
    name = fields.Char(string="Port", required=True)
    state_id = fields.Many2one('res.country.state', string="State")

    _sql_constraints = [
        ('code_uniq', 'unique (code)', 'The Port Code must be unique!')
    ]
Exemple #29
0
class City(models.Model):
    _name = 'res.city'
    _description = 'City'
    _order = 'name'

    name = fields.Char("Name", required=True, translate=True)
    zipcode = fields.Char("Zip")
    country_id = fields.Many2one('res.country',
                                 string='Country',
                                 required=True)
    state_id = fields.Many2one('res.country.state',
                               'State',
                               domain="[('country_id', '=', country_id)]")
class SnailmailLetterMissingRequiredFields(models.TransientModel):
    _name = 'snailmail.letter.missing.required.fields'
    _description = 'Update address of partner'

    partner_id = fields.Many2one('res.partner')
    letter_id = fields.Many2one('snailmail.letter')

    street = fields.Char('Street')
    street2 = fields.Char('Street2')
    zip = fields.Char('Zip')
    city = fields.Char('City')
    state_id = fields.Many2one("res.country.state", string='State')
    country_id = fields.Many2one('res.country', string='Country')

    @api.model
    def default_get(self, fields):
        rec = super(SnailmailLetterMissingRequiredFields,
                    self).default_get(fields)
        letter_id = self.env['snailmail.letter'].browse(
            self.env.context.get('letter_id'))
        rec.update({
            'partner_id': letter_id.partner_id.id,
            'letter_id': letter_id.id,
            'street': letter_id.street,
            'street2': letter_id.street2,
            'zip': letter_id.zip,
            'city': letter_id.city,
            'state_id': letter_id.state_id.id,
            'country_id': letter_id.country_id.id,
        })
        return rec

    def update_address_cancel(self):
        self.letter_id.cancel()

    def update_address_save(self):
        address_data = {
            'street': self.street,
            'street2': self.street2,
            'zip': self.zip,
            'city': self.city,
            'state_id': self.state_id.id,
            'country_id': self.country_id.id,
        }
        self.partner_id.write(address_data)
        letters_to_resend = self.env['snailmail.letter'].search([
            ('partner_id', '=', self.partner_id.id),
            ('error_code', '=', 'MISSING_REQUIRED_FIELDS'),
        ])
        letters_to_resend.write(address_data)
        letters_to_resend.snailmail_print()