changes
This commit is contained in:
@@ -30,4 +30,5 @@ from . import odsp_discretionary_wizard
|
||||
from . import odsp_pre_approved_wizard
|
||||
from . import odsp_ready_delivery_wizard
|
||||
from . import odsp_submit_to_odsp_wizard
|
||||
from . import ltc_repair_create_so_wizard
|
||||
from . import ltc_repair_create_so_wizard
|
||||
from . import send_page11_wizard
|
||||
BIN
fusion_claims/wizard/__pycache__/__init__.cpython-312.pyc
Normal file
BIN
fusion_claims/wizard/__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -34,18 +34,42 @@ class ApplicationReceivedWizard(models.TransientModel):
|
||||
|
||||
signed_pages_11_12 = fields.Binary(
|
||||
string='Signed Pages 11 & 12',
|
||||
required=True,
|
||||
help='Upload the signed pages 11 and 12 from the application',
|
||||
help='Upload the signed pages 11 and 12 from the application. '
|
||||
'Not required if a remote signing request has been sent.',
|
||||
)
|
||||
signed_pages_filename = fields.Char(
|
||||
string='Pages Filename',
|
||||
)
|
||||
|
||||
has_pending_page11_request = fields.Boolean(
|
||||
compute='_compute_has_pending_page11_request',
|
||||
)
|
||||
has_signed_page11 = fields.Boolean(
|
||||
compute='_compute_has_pending_page11_request',
|
||||
)
|
||||
|
||||
notes = fields.Text(
|
||||
string='Notes',
|
||||
help='Any notes about the received application',
|
||||
)
|
||||
|
||||
@api.depends('sale_order_id')
|
||||
def _compute_has_pending_page11_request(self):
|
||||
for wiz in self:
|
||||
order = wiz.sale_order_id
|
||||
if order:
|
||||
requests = order.page11_sign_request_ids
|
||||
wiz.has_pending_page11_request = bool(
|
||||
requests.filtered(lambda r: r.state in ('draft', 'sent'))
|
||||
)
|
||||
wiz.has_signed_page11 = bool(
|
||||
order.x_fc_signed_pages_11_12
|
||||
or requests.filtered(lambda r: r.state == 'signed')
|
||||
)
|
||||
else:
|
||||
wiz.has_pending_page11_request = False
|
||||
wiz.has_signed_page11 = False
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields_list):
|
||||
res = super().default_get(fields_list)
|
||||
@@ -53,7 +77,6 @@ class ApplicationReceivedWizard(models.TransientModel):
|
||||
if active_id:
|
||||
order = self.env['sale.order'].browse(active_id)
|
||||
res['sale_order_id'] = order.id
|
||||
# Pre-fill if documents already exist
|
||||
if order.x_fc_original_application:
|
||||
res['original_application'] = order.x_fc_original_application
|
||||
res['original_application_filename'] = order.x_fc_original_application_filename
|
||||
@@ -91,20 +114,33 @@ class ApplicationReceivedWizard(models.TransientModel):
|
||||
if order.x_fc_adp_application_status not in ('assessment_completed', 'waiting_for_application'):
|
||||
raise UserError("Can only receive application from 'Waiting for Application' status.")
|
||||
|
||||
# Validate files are uploaded
|
||||
if not self.original_application:
|
||||
raise UserError("Please upload the Original ADP Application.")
|
||||
if not self.signed_pages_11_12:
|
||||
raise UserError("Please upload the Signed Pages 11 & 12.")
|
||||
|
||||
# Update sale order with documents
|
||||
order.with_context(skip_status_validation=True).write({
|
||||
|
||||
page11_covered = bool(
|
||||
self.signed_pages_11_12
|
||||
or order.x_fc_signed_pages_11_12
|
||||
or order.page11_sign_request_ids.filtered(
|
||||
lambda r: r.state in ('sent', 'signed')
|
||||
)
|
||||
)
|
||||
if not page11_covered:
|
||||
raise UserError(
|
||||
"Signed Pages 11 & 12 are required.\n\n"
|
||||
"You can either upload the file here, or use the "
|
||||
"'Request Page 11 Signature' button on the sale order "
|
||||
"to send it for remote signing before confirming."
|
||||
)
|
||||
|
||||
vals = {
|
||||
'x_fc_adp_application_status': 'application_received',
|
||||
'x_fc_original_application': self.original_application,
|
||||
'x_fc_original_application_filename': self.original_application_filename,
|
||||
'x_fc_signed_pages_11_12': self.signed_pages_11_12,
|
||||
'x_fc_signed_pages_filename': self.signed_pages_filename,
|
||||
})
|
||||
}
|
||||
if self.signed_pages_11_12:
|
||||
vals['x_fc_signed_pages_11_12'] = self.signed_pages_11_12
|
||||
vals['x_fc_signed_pages_filename'] = self.signed_pages_filename
|
||||
order.with_context(skip_status_validation=True).write(vals)
|
||||
|
||||
# Post to chatter
|
||||
from datetime import date
|
||||
@@ -128,3 +164,15 @@ class ApplicationReceivedWizard(models.TransientModel):
|
||||
)
|
||||
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
def action_request_page11_signature(self):
|
||||
"""Open the Page 11 remote signing wizard from within the Application Received wizard."""
|
||||
self.ensure_one()
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': 'Request Page 11 Signature',
|
||||
'res_model': 'fusion_claims.send.page11.wizard',
|
||||
'view_mode': 'form',
|
||||
'target': 'new',
|
||||
'context': {'default_sale_order_id': self.sale_order_id.id},
|
||||
}
|
||||
|
||||
@@ -10,10 +10,12 @@
|
||||
<strong><i class="fa fa-info-circle"/> Upload Required Documents</strong>
|
||||
<p class="mb-0">Please upload the ADP application documents received from the client.</p>
|
||||
</div>
|
||||
|
||||
|
||||
<field name="sale_order_id" invisible="1"/>
|
||||
<field name="has_pending_page11_request" invisible="1"/>
|
||||
<field name="has_signed_page11" invisible="1"/>
|
||||
|
||||
<group>
|
||||
<field name="sale_order_id" invisible="1"/>
|
||||
|
||||
<group string="Original ADP Application">
|
||||
<field name="original_application" filename="original_application_filename"
|
||||
widget="binary" class="oe_inline"/>
|
||||
@@ -24,6 +26,28 @@
|
||||
<field name="signed_pages_11_12" filename="signed_pages_filename"
|
||||
widget="binary" class="oe_inline"/>
|
||||
<field name="signed_pages_filename" invisible="1"/>
|
||||
|
||||
<div invisible="has_signed_page11" class="mt-2">
|
||||
<span class="text-muted small">Don't have signed pages? </span>
|
||||
<button name="action_request_page11_signature" type="object"
|
||||
string="Request Remote Signature"
|
||||
class="btn btn-sm btn-outline-warning"
|
||||
icon="fa-pencil-square-o"
|
||||
help="Send Page 11 to a family member or agent for digital signing"/>
|
||||
</div>
|
||||
|
||||
<div invisible="not has_pending_page11_request" class="mt-2">
|
||||
<div class="alert alert-warning mb-0 py-2 px-3">
|
||||
<i class="fa fa-clock-o"/> A remote signing request has been sent.
|
||||
You can proceed without uploading signed pages -- they will be auto-filled when signed.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div invisible="not has_signed_page11 or signed_pages_11_12" class="mt-2">
|
||||
<div class="alert alert-success mb-0 py-2 px-3">
|
||||
<i class="fa fa-check-circle"/> Page 11 has been signed remotely.
|
||||
</div>
|
||||
</div>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
|
||||
92
fusion_claims/wizard/send_page11_wizard.py
Normal file
92
fusion_claims/wizard/send_page11_wizard.py
Normal file
@@ -0,0 +1,92 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2024-2026 Nexa Systems Inc.
|
||||
# License OPL-1 (Odoo Proprietary License v1.0)
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class SendPage11Wizard(models.TransientModel):
|
||||
_name = 'fusion_claims.send.page11.wizard'
|
||||
_description = 'Send Page 11 for Remote Signing'
|
||||
|
||||
sale_order_id = fields.Many2one(
|
||||
'sale.order', string='Sale Order',
|
||||
required=True, readonly=True,
|
||||
)
|
||||
signer_email = fields.Char(string='Recipient Email', required=True)
|
||||
signer_type = fields.Selection([
|
||||
('client', 'Client (Self)'),
|
||||
('spouse', 'Spouse'),
|
||||
('parent', 'Parent'),
|
||||
('legal_guardian', 'Legal Guardian'),
|
||||
('poa', 'Power of Attorney'),
|
||||
('public_trustee', 'Public Trustee'),
|
||||
], string='Signer Type', default='client', required=True)
|
||||
signer_name = fields.Char(string='Signer Name', required=True)
|
||||
custom_message = fields.Text(
|
||||
string='Personal Message',
|
||||
help='Optional message to include in the signing request email.',
|
||||
)
|
||||
expiry_days = fields.Integer(
|
||||
string='Link Valid For (days)', default=7, required=True,
|
||||
)
|
||||
|
||||
client_name = fields.Char(string='Client', readonly=True)
|
||||
case_ref = fields.Char(string='Case Reference', readonly=True)
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields_list):
|
||||
res = super().default_get(fields_list)
|
||||
active_id = self.env.context.get('active_id')
|
||||
if not active_id:
|
||||
return res
|
||||
|
||||
order = self.env['sale.order'].browse(active_id)
|
||||
res['sale_order_id'] = order.id
|
||||
res['client_name'] = order.partner_id.name or ''
|
||||
res['case_ref'] = order.name or ''
|
||||
res['signer_name'] = order.partner_id.name or ''
|
||||
res['signer_email'] = order.partner_id.email or ''
|
||||
return res
|
||||
|
||||
def action_send(self):
|
||||
"""Create a signing request and send the email."""
|
||||
self.ensure_one()
|
||||
|
||||
if not self.signer_email:
|
||||
raise UserError(_("Please enter the recipient's email address."))
|
||||
if self.expiry_days < 1:
|
||||
raise UserError(_("Expiry must be at least 1 day."))
|
||||
|
||||
request = self.env['fusion.page11.sign.request'].create({
|
||||
'sale_order_id': self.sale_order_id.id,
|
||||
'signer_email': self.signer_email,
|
||||
'signer_type': self.signer_type,
|
||||
'signer_name': self.signer_name,
|
||||
'custom_message': self.custom_message,
|
||||
'expiry_date': fields.Datetime.now() + timedelta(days=self.expiry_days),
|
||||
'consent_signed_by': 'applicant' if self.signer_type == 'client' else 'agent',
|
||||
'signer_relationship': dict(self._fields['signer_type'].selection).get(
|
||||
self.signer_type, ''
|
||||
) if self.signer_type != 'client' else '',
|
||||
})
|
||||
|
||||
request._send_signing_email()
|
||||
|
||||
return {
|
||||
'type': 'ir.actions.client',
|
||||
'tag': 'display_notification',
|
||||
'params': {
|
||||
'title': _('Page 11 Signing Request Sent'),
|
||||
'message': _(
|
||||
'Signing request has been sent to %s.',
|
||||
self.signer_email,
|
||||
),
|
||||
'type': 'success',
|
||||
'sticky': False,
|
||||
'next': {'type': 'ir.actions.act_window_close'},
|
||||
},
|
||||
}
|
||||
39
fusion_claims/wizard/send_page11_wizard_views.xml
Normal file
39
fusion_claims/wizard/send_page11_wizard_views.xml
Normal file
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<record id="view_send_page11_wizard_form" model="ir.ui.view">
|
||||
<field name="name">fusion_claims.send.page11.wizard.form</field>
|
||||
<field name="model">fusion_claims.send.page11.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Send Page 11 for Signing">
|
||||
<group>
|
||||
<group string="Case Information">
|
||||
<field name="sale_order_id" invisible="1"/>
|
||||
<field name="client_name"/>
|
||||
<field name="case_ref"/>
|
||||
</group>
|
||||
<group string="Recipient">
|
||||
<field name="signer_name"/>
|
||||
<field name="signer_email" widget="email"/>
|
||||
<field name="signer_type"/>
|
||||
<field name="expiry_days"/>
|
||||
</group>
|
||||
</group>
|
||||
<group string="Personal Message (Optional)">
|
||||
<field name="custom_message" nolabel="1" placeholder="Add a personal note to include in the email..."/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="action_send" type="object" string="Send Signing Request" class="btn-primary"/>
|
||||
<button string="Cancel" class="btn-secondary" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_send_page11_wizard" model="ir.actions.act_window">
|
||||
<field name="name">Request Page 11 Signature</field>
|
||||
<field name="res_model">fusion_claims.send.page11.wizard</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
<field name="context">{'default_sale_order_id': active_id}</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -61,6 +61,18 @@ class StatusChangeReasonWizard(models.TransientModel):
|
||||
help='Select the reason ADP denied the funding',
|
||||
)
|
||||
|
||||
# ==========================================================================
|
||||
# WITHDRAWAL INTENT (for 'withdrawn' status)
|
||||
# ==========================================================================
|
||||
withdrawal_intent = fields.Selection(
|
||||
selection=[
|
||||
('cancel', 'Cancel Application'),
|
||||
('resubmit', 'Withdraw for Correction & Resubmission'),
|
||||
],
|
||||
string='What would you like to do after withdrawal?',
|
||||
default='resubmit',
|
||||
)
|
||||
|
||||
reason = fields.Text(
|
||||
string='Reason / Additional Details',
|
||||
help='Please provide additional details for this status change.',
|
||||
@@ -181,8 +193,10 @@ class StatusChangeReasonWizard(models.TransientModel):
|
||||
}
|
||||
header_color, bg_color, border_color = status_colors.get(new_status, ('#17a2b8', '#f0f9ff', '#bee5eb'))
|
||||
|
||||
# For on_hold, also store the previous status and hold date
|
||||
# Build initial update vals
|
||||
update_vals = {'x_fc_adp_application_status': new_status}
|
||||
if new_status == 'withdrawn':
|
||||
update_vals['x_fc_previous_status_before_withdrawal'] = self.previous_status
|
||||
|
||||
# =================================================================
|
||||
# REJECTED: ADP rejected submission (within 24 hours)
|
||||
@@ -261,7 +275,7 @@ class StatusChangeReasonWizard(models.TransientModel):
|
||||
# Don't post message here - _send_on_hold_email() will post the message
|
||||
message_body = None
|
||||
elif new_status == 'withdrawn':
|
||||
# Don't post message here - _send_withdrawal_email() will post the message
|
||||
# Handled entirely below based on withdrawal_intent
|
||||
message_body = None
|
||||
elif new_status == 'cancelled':
|
||||
# Cancelled has its own detailed message posted later
|
||||
@@ -302,10 +316,129 @@ class StatusChangeReasonWizard(models.TransientModel):
|
||||
order._send_correction_needed_email(reason=reason)
|
||||
|
||||
# =================================================================
|
||||
# WITHDRAWN: Send email notification to all parties
|
||||
# WITHDRAWN: Branch based on withdrawal intent
|
||||
# =================================================================
|
||||
if new_status == 'withdrawn':
|
||||
order._send_withdrawal_email(reason=reason)
|
||||
intent = self.withdrawal_intent
|
||||
|
||||
if intent == 'cancel':
|
||||
# ---------------------------------------------------------
|
||||
# WITHDRAW & CANCEL: Cancel invoices + SO
|
||||
# ---------------------------------------------------------
|
||||
cancelled_invoices = []
|
||||
cancelled_so = False
|
||||
|
||||
# Cancel related invoices first
|
||||
invoices = order.invoice_ids.filtered(lambda inv: inv.state != 'cancel')
|
||||
for invoice in invoices:
|
||||
try:
|
||||
inv_msg = Markup(f'''
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<h5 class="alert-heading"><i class="fa fa-ban"></i> Invoice Cancelled (Withdrawal)</h5>
|
||||
<ul>
|
||||
<li><strong>Related Order:</strong> {order.name}</li>
|
||||
<li><strong>Cancelled By:</strong> {user_name}</li>
|
||||
<li><strong>Date:</strong> {change_date}</li>
|
||||
</ul>
|
||||
<hr>
|
||||
<p class="mb-0"><strong>Reason:</strong> {reason}</p>
|
||||
</div>
|
||||
''')
|
||||
invoice.message_post(
|
||||
body=inv_msg,
|
||||
message_type='notification',
|
||||
subtype_xmlid='mail.mt_note',
|
||||
)
|
||||
if invoice.state == 'posted':
|
||||
invoice.button_draft()
|
||||
invoice.button_cancel()
|
||||
cancelled_invoices.append(invoice.name)
|
||||
except Exception as e:
|
||||
warn_msg = Markup(f'''
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<p class="mb-0"><i class="fa fa-exclamation-triangle"></i> <strong>Warning:</strong> Could not cancel invoice {invoice.name}</p>
|
||||
<p class="mb-0 small">{str(e)}</p>
|
||||
</div>
|
||||
''')
|
||||
order.message_post(
|
||||
body=warn_msg,
|
||||
message_type='notification',
|
||||
subtype_xmlid='mail.mt_note',
|
||||
)
|
||||
|
||||
# Cancel the sale order itself
|
||||
if order.state not in ('cancel', 'done'):
|
||||
try:
|
||||
order._action_cancel()
|
||||
cancelled_so = True
|
||||
except Exception as e:
|
||||
warn_msg = Markup(f'''
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<p class="mb-0"><i class="fa fa-exclamation-triangle"></i> <strong>Warning:</strong> Could not cancel sale order</p>
|
||||
<p class="mb-0 small">{str(e)}</p>
|
||||
</div>
|
||||
''')
|
||||
order.message_post(
|
||||
body=warn_msg,
|
||||
message_type='notification',
|
||||
subtype_xmlid='mail.mt_note',
|
||||
)
|
||||
|
||||
# Build cancellation summary
|
||||
invoice_list_html = ''
|
||||
if cancelled_invoices:
|
||||
invoice_items = ''.join([f'<li>{inv}</li>' for inv in cancelled_invoices])
|
||||
invoice_list_html = f'<li><strong>Invoices Cancelled:</strong><ul>{invoice_items}</ul></li>'
|
||||
|
||||
so_status = 'Cancelled' if cancelled_so else 'Not applicable'
|
||||
summary_msg = Markup(f'''
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<h5 class="alert-heading"><i class="fa fa-ban"></i> Application Withdrawn & Cancelled</h5>
|
||||
<ul>
|
||||
<li><strong>Withdrawn By:</strong> {user_name}</li>
|
||||
<li><strong>Date:</strong> {change_date}</li>
|
||||
<li><strong>Sale Order:</strong> {so_status}</li>
|
||||
{invoice_list_html}
|
||||
</ul>
|
||||
<hr>
|
||||
<p class="mb-0"><strong>Reason:</strong> {reason}</p>
|
||||
</div>
|
||||
''')
|
||||
order.message_post(
|
||||
body=summary_msg,
|
||||
message_type='notification',
|
||||
subtype_xmlid='mail.mt_note',
|
||||
)
|
||||
order._send_withdrawal_email(reason=reason, intent='cancel')
|
||||
|
||||
else:
|
||||
# ---------------------------------------------------------
|
||||
# WITHDRAW & RESUBMIT: Return to ready_submission
|
||||
# ---------------------------------------------------------
|
||||
order.with_context(skip_status_validation=True).write({
|
||||
'x_fc_adp_application_status': 'ready_submission',
|
||||
'x_fc_previous_status_before_withdrawal': self.previous_status,
|
||||
})
|
||||
|
||||
resubmit_msg = Markup(f'''
|
||||
<div class="alert alert-info" role="alert">
|
||||
<h5 class="alert-heading"><i class="fa fa-undo"></i> Application Withdrawn for Correction</h5>
|
||||
<ul>
|
||||
<li><strong>Withdrawn By:</strong> {user_name}</li>
|
||||
<li><strong>Date:</strong> {change_date}</li>
|
||||
<li><strong>Status Returned To:</strong> Ready for Submission</li>
|
||||
</ul>
|
||||
<hr>
|
||||
<p class="mb-0"><strong>Reason:</strong> {reason}</p>
|
||||
<p class="mb-0 mt-2"><i class="fa fa-info-circle"></i> Make corrections and click <strong>Submit Application</strong> to resubmit.</p>
|
||||
</div>
|
||||
''')
|
||||
order.message_post(
|
||||
body=resubmit_msg,
|
||||
message_type='notification',
|
||||
subtype_xmlid='mail.mt_note',
|
||||
)
|
||||
order._send_withdrawal_email(reason=reason, intent='resubmit')
|
||||
|
||||
# =================================================================
|
||||
# ON HOLD: Send email notification to all parties
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
<div class="alert alert-info mb-3 rounded-0" role="alert" invisible="new_status != 'withdrawn'"
|
||||
style="margin: -16px -16px 16px -16px; padding: 12px 16px;">
|
||||
<i class="fa fa-undo me-2"/> You are about to <strong>Withdraw</strong> this application. Please provide the reason for withdrawal.
|
||||
<i class="fa fa-undo me-2"/> You are about to <strong>Withdraw</strong> this application. Please select what you would like to do after withdrawal.
|
||||
</div>
|
||||
|
||||
<div class="alert alert-secondary mb-3 rounded-0" role="alert" invisible="new_status != 'on_hold'"
|
||||
@@ -45,6 +45,26 @@
|
||||
</div>
|
||||
|
||||
<div class="px-3 pb-3">
|
||||
<!-- WITHDRAWAL INTENT (for 'withdrawn' status) -->
|
||||
<group invisible="new_status != 'withdrawn'">
|
||||
<group>
|
||||
<field name="withdrawal_intent"
|
||||
required="new_status == 'withdrawn'"
|
||||
widget="radio"
|
||||
options="{'horizontal': false}"/>
|
||||
</group>
|
||||
</group>
|
||||
<div class="alert alert-danger mt-2 mb-3" role="alert"
|
||||
invisible="new_status != 'withdrawn' or withdrawal_intent != 'cancel'">
|
||||
<i class="fa fa-exclamation-triangle me-2"/>
|
||||
This will <strong>permanently cancel</strong> the sale order and all related invoices. This action cannot be undone.
|
||||
</div>
|
||||
<div class="alert alert-info mt-2 mb-3" role="alert"
|
||||
invisible="new_status != 'withdrawn' or withdrawal_intent != 'resubmit'">
|
||||
<i class="fa fa-info-circle me-2"/>
|
||||
The application will return to <strong>Ready for Submission</strong> status. You can make corrections and resubmit.
|
||||
</div>
|
||||
|
||||
<!-- REJECTION REASON (for 'rejected' status) -->
|
||||
<group invisible="new_status != 'rejected'">
|
||||
<group>
|
||||
|
||||
Reference in New Issue
Block a user