yes i made it
class Client(Document):
def after_insert(self):
# After inserting a new client, create a user
user_doc = self.create_user()
if user_doc:
self.assign_user_roles(user_doc)
def create_user(self):
# Create a user based on client data
user_doc = frappe.new_doc("User")
# Set the user ID as the full name
full_name = " ".join(filter(None, [self.client_name, self.business_name]))
user_doc = frappe.new_doc("User")
user_doc.update({
"first_name": self.client_name,
"last_name": self.business_name,
"email": self.email,
"phone": self.telephone,
"mobile_no": self.contact_no,
"name": full_name, # Set user ID as the full name
# Add other relevant fields from the client DocType to the user
})
try:
user_doc.insert(ignore_permissions=True)
# Calculate expiry details and color indicator
self.calculate_expiry_details(client_doc)
return user_doc
except Exception as e:
frappe.log_error(f"Error creating user: {e}", _("Create User Error"))
return None
in work space i created custom html
Html Block
<table id="user_info_table">
<tr>
<th>Full Name</th>
<th>Email</th>
<th>Company Name</th>
<th>Client Code</th>
<th>Category</th>
<th>Scope</th>
<th>Status</th>
</tr>
<tr>
<td id="full_name"></td>
<td id="email"></td>
<td id="business_name"></td>
<td id="client_code"></td>
<td id="category"></td>
<td id="scope"></td>
<td id="status"></td>
</tr>
<tr>
<th>Standards</th>
<th>Certified Since</th>
<th>Certified Expiry</th>
<th>Remaining Days</th>
<th>Extension</th>
<th>Region</th>
<th>City</th>
</tr>
<tr>
<td id="standards"></td>
<td id="certified_since"></td>
<td id="certified_expiry"></td>
<td id="remaining_days"></td>
<td id="ext"></td>
<td id=region></td>
<td id="city"></td>
</tr>
</table>
JS Block
frappe.call({
method: "frappe.client.get",
args: {
doctype: "User",
name: frappe.session.user,
},
callback: async function(r_user) {
if (r_user.message) {
root_element.querySelector("#full_name").textContent = r_user.message.full_name;
root_element.querySelector("#email").textContent = r_user.message.email;
// Fetch client information and other related data based on email and user ID
await fetchClientInfo(r_user.message.email);
}
},
async: true
});
function hasClientRole(roles) {
// Check if the roles array contains the "Client" role
return roles.includes("Client");
}
function fetchClientInfo(user_email) {
frappe.call({
method: "frappe.client.get",
args: {
doctype: "Client",
filters: {
email: user_email,
},
fields: ["client_name", "standards", "client_code", "scope", "category", "status", "certified_since", "certified_expiry", "ext", "region", "city"]
},
callback: function(r_client) {
root_element.querySelector("#business_name").innerHTML = r_client.message.business_name;
root_element.querySelector("#client_code").innerHTML = r_client.message.client_code;
root_element.querySelector("#status").innerHTML = r_client.message.status;
root_element.querySelector("#category").innerHTML = r_client.message.category;
root_element.querySelector("#scope").innerHTML = r_client.message.scope;
root_element.querySelector("#standards").innerHTML = r_client.message.standards;
root_element.querySelector("#certified_since").innerHTML = r_client.message.certified_since;
root_element.querySelector("#certified_expiry").innerHTML = r_client.message.certified_expiry;
root_element.querySelector("#ext").innerHTML = r_client.message.ext;
root_element.querySelector("#region").innerHTML = r_client.message.region;
root_element.querySelector("#city").innerHTML = r_client.message.city;
// Calculate remaining days
var expiryDate = new Date(r_client.message.certified_expiry);
var currentDate = new Date();
var timeDifference = expiryDate.getTime() - currentDate.getTime();
var remainingDays = Math.ceil(timeDifference / (1000 * 3600 * 24)); // Convert milliseconds to days
var statusElement = root_element.querySelector("#status");
// Remove any existing status classes
statusElement.classList.remove('status-valid', 'status-expiring-soon', 'status-expiring', 'status-expired');
// Apply the correct status class and text content
if (remainingDays <= 0) {
statusElement.textContent = 'Expired';
statusElement.classList.add('status-expired');
} else if (remainingDays < 30) {
statusElement.textContent = 'Expiring';
statusElement.classList.add('status-expiring');
} else if (remainingDays < 60) {
statusElement.textContent = 'Expiring Soon';
statusElement.classList.add('status-expiring-soon');
} else {
statusElement.textContent = 'Valid';
statusElement.classList.add('status-valid');
}
root_element.querySelector("#remaining_days").innerHTML = remainingDays;
}
});
}
Css
type or paste code here
#user_info_table {
width: 100%;
border-collapse: collapse;
}
#user_info_table th,
#user_info_table td {
padding: 8px;
border-bottom: 1px solid #ddd;
text-align: left;
color: #555555;;
}
#user_info_table th {
background-color: #f2f2f2;
color: #555555;
font-weight: bold; /* Make headers bold */
}
.status-valid {
background-color: #dff0d8;
color: white;
}
.status-expiring-soon {
background-color: #f4e69c;
color: black;
}
.status-expiring {
background-color: #e8b29f;
color: white;
}
.status-expired {
background-color: #f2dede;
color: white;
}