[{"data":1,"prerenderedAt":270},["ShallowReactive",2],{"i-lucide:chevron-down":3,"i-lucide:arrow-up-right":8,"i-simple-icons:github":10,"i-simple-icons:x":12,"i-brand:linkedin":14,"i-simple-icons:medium":18,"i-lucide:mail":20,"i-lucide:sun":22,"project:\u002Fprojects\u002Fcrm-and-hr":24,"project-more:\u002Fprojects\u002Fcrm-and-hr":244,"i-lucide:briefcase-business":266,"i-lucide:calendar":268},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":7},0,24,false,"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m6 9l6 6l6-6\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":9},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M7 7h10v10M7 17L17 7\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":11},"\u003Cpath fill=\"currentColor\" d=\"M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":13},"\u003Cpath fill=\"currentColor\" d=\"M14.234 10.162L22.977 0h-2.072l-7.591 8.824L7.251 0H.258l9.168 13.343L.258 24H2.33l8.016-9.318L16.749 24h6.993zm-2.837 3.299l-.929-1.329L3.076 1.56h3.182l5.965 8.532l.929 1.329l7.754 11.09h-3.182z\"\u002F>",{"left":4,"top":15,"width":16,"height":16,"rotate":4,"vFlip":6,"hFlip":6,"body":17},32,448,"\u003Cpath fill=\"currentColor\" d=\"M416 32L31.9 32C14.3 32 0 46.5 0 64.3L0 447.7C0 465.5 14.3 480 31.9 480L416 480c17.6 0 32-14.5 32-32.3l0-383.4C448 46.5 433.6 32 416 32zM135.4 416l-66.4 0 0-213.8 66.5 0 0 213.8-.1 0zM102.2 96a38.5 38.5 0 1 1 0 77 38.5 38.5 0 1 1 0-77zM384.3 416l-66.4 0 0-104c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9l0 105.8-66.4 0 0-213.8 63.7 0 0 29.2 .9 0c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9l0 117.2z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":19},"\u003Cpath fill=\"currentColor\" d=\"M4.21 0A4.2 4.2 0 0 0 0 4.21v15.58A4.2 4.2 0 0 0 4.21 24h15.58A4.2 4.2 0 0 0 24 19.79v-1.093a5 5 0 0 1-.422.02c-2.577 0-4.027-2.146-4.09-4.832a8 8 0 0 1 .022-.708c.093-1.186.475-2.241 1.105-3.022a3.9 3.9 0 0 1 1.395-1.1c.468-.237 1.127-.367 1.664-.367h.023q.151 0 .303.01V4.211A4.2 4.2 0 0 0 19.79 0Zm.198 5.583h4.165l3.588 8.435l3.59-8.435h3.864v.146l-.019.004c-.705.16-1.063.397-1.063 1.254h-.003l.003 10.274c.06.676.424.885 1.063 1.03l.02.004v.145h-4.923v-.145l.019-.005c.639-.144.994-.353 1.054-1.03V7.267l-4.745 11.15h-.261L6.15 7.569v9.445c0 .857.358 1.094 1.063 1.253l.02.004v.147H4.405v-.147l.019-.004c.705-.16 1.065-.397 1.065-1.253V6.987c0-.857-.358-1.094-1.064-1.254l-.018-.004zm19.25 3.668c-1.086.023-1.733 1.323-1.813 3.124H24V9.298a1.4 1.4 0 0 0-.342-.047m-1.862 3.632c-.1 1.756.86 3.239 2.204 3.634v-3.634z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":21},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"m22 7l-8.991 5.727a2 2 0 0 1-2.009 0L2 7\"\u002F>\u003Crect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":23},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"4\"\u002F>\u003Cpath d=\"M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41\"\u002F>\u003C\u002Fg>",{"page":25,"project":230},{"id":26,"title":27,"body":28,"description":221,"extension":222,"meta":223,"navigation":224,"path":225,"seo":226,"sitemap":227,"stem":228,"__hash__":229},"projectPages\u002Fprojects\u002Fcrm-and-hr.md","Crm And Hr",{"type":29,"value":30,"toc":206},"minimark",[31,36,40,51,55,58,81,85,93,99,105,111,115,132,136,143,147,154,157,162,169,172,176,183,186,190,198],[32,33,35],"h2",{"id":34},"overview","Overview",[37,38,39],"p",{},"Faris Petrol issues Faris electronic cards and runs Clever, a loyalty app with partner stores. I joined in 2019 as a full-stack developer, and from September 2020 I built, with one other developer, the system its customer service, field and HR teams work in. One side is a CRM linked to the phone system and Clever; the other is HR, with attendance read from the company’s access-control devices.",[41,42,48],"project-shot",{":single":43,"alt":44,"height":45,"src":46,"width":47,":bare":43},"true","Three screens of the Arabic interface. In front, the monthly calendar of store visits, with planned visits in yellow and completed ones in green. Tilted behind it, the weekly attendance sheet on the left and the employees list on the right.",660,"\u002Fprojects\u002Fcrm-and-hr\u002Fscreens.webp",1760,[37,49,50],{},"The month's store visits in front, with the attendance sheet and the employees beside it.",[32,52,54],{"id":53},"the-problem","The problem",[37,56,57],{},"The teams needed one place for their daily work, and HR needed attendance it could rely on.",[59,60,61,69,75],"ul",{},[62,63,64,68],"li",{},[65,66,67],"strong",{},"Calls without context."," A call reached an agent as a bare phone number.",[62,70,71,74],{},[65,72,73],{},"Work spread across systems."," Requests had no owner, store visits had no plan, and partner stores lived in Clever.",[62,76,77,80],{},[65,78,79],{},"Punches, not shifts."," The devices recorded punches, but HR needed shifts, including 24-hour shifts across midnight.",[32,82,84],{"id":83},"the-solution","The solution",[86,87,90],"sketch-figure",{"alt":88,"name":89},"Before: a person switches between the phone system, which shows only a number, an old CRM with contacts, Clever with stores and balances, and devices with raw punches. Now: one system with a CRM side and an HR side, linked both ways to the phone system, Clever, SMS and messaging apps, and the access-control devices.","crm-and-hr\u002Fbefore-after",[37,91,92],{},"One record per customer and per employee, fed by the systems around it.",[37,94,95,98],{},[65,96,97],{},"The caller on screen."," The phone system asks the CRM who is calling, and every call is logged on the caller’s record.",[37,100,101,104],{},[65,102,103],{},"One place for the daily work."," Tickets have an owner, partner stores sync from Clever, and every store gets a monthly visit.",[37,106,107,110],{},[65,108,109],{},"Shifts from punches."," One rule pairs punches into shifts, and HR can fix a missed punch or re-run a day.",[32,112,114],{"id":113},"what-i-did","What I did",[59,116,117,120,123,126,129],{},[62,118,119],{},"Set up the project and built it with one other developer, releasing it a module at a time.",[62,121,122],{},"Built the HR side: employees, contracts, shifts, leave and attendance from the access-control devices.",[62,124,125],{},"Built the phone-system integration that shows the caller and logs every call.",[62,127,128],{},"Built SMS templates, the monthly visit plans, and the scheduled Clever sync with low-balance alerts.",[62,130,131],{},"Built contacts, tickets, visits and messaging with the other developer, and set up roles and permissions.",[32,133,135],{"id":134},"what-it-offers","What it offers",[86,137,140],{"alt":138,"name":139},"Everything in the system. CRM, for customer service and the field team: contacts, calls, tickets, partner stores synced from Clever, monthly visit plans and messages. HR, for HR and managers: employees, contracts, shifts, leave and holidays, attendance from the access-control devices, and reports. Both sides share notifications and roles.","crm-and-hr\u002Ffeature-map",[37,141,142],{},"The CRM and HR sides, and what they share.",[32,144,146],{"id":145},"system-design","System design",[86,148,151],{"alt":149,"name":150},"Agents, the field team, HR and managers use one web system, where roles decide who sees what, with a CRM side, an HR side and notifications. It talks both ways to the phone system, Clever, messaging apps and the access-control devices. Behind it sit the database, and queues and schedules for the slow work.","crm-and-hr\u002Farchitecture",[37,152,153],{},"One system for every team, with the outside systems feeding it.",[37,155,156],{},"Roles decide what each person sees, from station supervisors to the field team and HR. Queues and schedules do the slow work, so nobody waits on screen for a sync or a message to send.",[158,159,161],"h3",{"id":160},"calls-and-contacts","Calls and contacts",[86,163,166],{"alt":164,"name":165},"When a call comes in, the phone system asks the CRM who is calling: a known caller’s record opens for the agent, and an unknown number is kept for later. When the call ends, it is logged on the contact as in, out or missed, with the agent and times.","crm-and-hr\u002Fincoming-call",[37,167,168],{},"The agent knows who is calling before answering.",[37,170,171],{},"An unknown number is kept, so an agent can link it to a contact later.",[158,173,175],{"id":174},"from-punches-to-shifts","From punches to shifts",[86,177,180],{"alt":178,"name":179},"Punches from the access-control devices are imported and kept raw, paired into shifts by one rule, corrected by HR and summed up in reports. Two timelines show a day shift and a 24-hour shift across midnight, each made one shift by the same rule.","crm-and-hr\u002Fattendance",[37,181,182],{},"A day shift and a 24-hour shift go through the same rule.",[37,184,185],{},"Each employee’s shift tells the rule when it starts and on which day it ends. After a power or network outage, HR re-runs the period.",[32,187,189],{"id":188},"in-the-product","In the product",[41,191,195],{":single":43,"alt":192,"height":193,"src":194,"width":47},"The visit calendar for a month: planned visits in yellow and completed ones in green on each day, next to the month’s totals and today’s visits.",852,"\u002Fprojects\u002Fcrm-and-hr\u002Fvisit-plan.webp",[37,196,197],{},"The monthly visit plan, with completed visits in green.",[41,199,203],{":single":43,"alt":200,"height":201,"src":202,"width":47},"A week of attendance: one row per employee, with check-in and check-out times for each day and missing punches in red.",799,"\u002Fprojects\u002Fcrm-and-hr\u002Fattendance-sheet.webp",[37,204,205],{},"A week of attendance, with missing punches in red for HR to fix.",{"title":207,"searchDepth":208,"depth":208,"links":209},"",2,[210,211,212,213,214,215,220],{"id":34,"depth":208,"text":35},{"id":53,"depth":208,"text":54},{"id":83,"depth":208,"text":84},{"id":113,"depth":208,"text":114},{"id":134,"depth":208,"text":135},{"id":145,"depth":208,"text":146,"children":216},[217,219],{"id":160,"depth":218,"text":161},3,{"id":174,"depth":218,"text":175},{"id":188,"depth":208,"text":189},"The CRM I built with one other developer for Faris Petrol’s customer service and field teams, linked to the phone system and Clever, and the HR system that turns access-control punches into shifts.","md",{},true,"\u002Fprojects\u002Fcrm-and-hr",{"description":221},{"loc":225},"projects\u002Fcrm-and-hr","G-i97SKPAfH509DRiUVG382OCnuX8eo0Z3CWhgeK0qM",{"id":231,"title":232,"context":233,"description":234,"extension":235,"highlight":236,"links":237,"mark":238,"meta":240,"order":241,"stem":228,"year":242,"__hash__":243},"projects\u002Fprojects\u002Fcrm-and-hr.yml","CRM & HR system","Faris Petrol · Sep 2020 – Sep 2021","One system for Faris Petrol’s customer service and field teams (calls, tickets, visits and messages) and for HR, where punches become shifts. Built with one other developer.","yml",null,[],{"logo":239},"faris",{},1,2020,"QT-PyWJLO1R4kMBOF_xSotPjMjzg4-NSkXJm00cWwhY",[245,252,259],{"path":246,"title":247,"description":248,"mark":249,"year":251},"\u002Fprojects\u002Frunarks","Runarks · Governed access to production databases","My own product: every query against a production database is reviewed, approved, run once and logged, and nobody sees a password.",{"logo":250},"runarks",2026,{"path":253,"title":254,"description":255,"mark":256,"year":258},"\u002Fprojects\u002Fsanad","Sanad · Real-estate investment platform","The API and admin dashboard I built for a Saudi real-estate investment platform: verified investors, a wallet, investments and returns paid on a schedule.",{"logo":257},"sanad",2024,{"path":260,"title":261,"description":262,"mark":263,"year":265},"\u002Fprojects\u002Fwinch","WINCH · Saudi logistics platform","The back end of a Saudi logistics platform for businesses and carriers: more than 50 domains, and the integration engine I built for government services, payments and AI.",{"logo":264},"winch",2023,{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":267},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M12 12h.01M16 6V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v2m14 7a18.15 18.15 0 0 1-20 0\"\u002F>\u003Crect width=\"20\" height=\"14\" x=\"2\" y=\"6\" rx=\"2\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":269},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M8 2v3m8-3v3\"\u002F>\u003Crect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"\u002F>\u003Cpath d=\"M3 9h18\"\u002F>\u003C\u002Fg>",1791781461217]