Skip to content
Mozn Jamousمزن جاموسEnd-to-End Product Builderصناعة منتجات من الفكرة إلى الإطلاق
Back to workعودة إلى الأعمال

UX-led design · Odoo 19 · Open sourceتصميمٌ بقيادة التجربة · Odoo 19 · مفتوح المصدرLive · LGPL-3.0حيّ · LGPL-3.0

Smart Expense Manager — approvals at the speed of one click.Smart Expense Manager — موافقاتٌ بسرعة نقرةٍ واحدة.

An Odoo 19 custom module that replaces paper-based expense flows. Token-secured email approvals route via the hr.employee hierarchy — no login required. Auto-generated journal entries on finance sign-off; monthly PDF reports emailed by cron.وحدة Odoo 19 مخصّصة تحلّ محلّ تدفّقات النفقات الورقية. موافقاتٌ بريديّة مؤمّنة برمز تُوجَّه عبر تسلسل hr.employee — دون الحاجة لتسجيل الدخول. قيودٌ محاسبية مُولّدة تلقائياً عند اعتماد المالية؛ وتقارير PDF شهرية تُرسَل بالبريد عبر cron.

Yearالسنة
2026 — Present2026 — حتى الآن
Roleالدور
UX-led design + Sole developerتصميمٌ بقيادة التجربة + مطوّرة وحيدة
Stackالتقنيات
PythonOdoo 19 ORMPostgreSQLQWebOWLXMLBootstrap
Days → Secsأيام ← ثوانٍ
Approval time — one-click flow, no login requiredزمن الموافقة — تدفّق بنقرةٍ واحدة، دون تسجيل دخول
No loginبلا تسجيل دخول
Managers act from email; the system gets usedالمديرون يتصرّفون من البريد؛ فيُستخدَم النظام
Audit-gradeبمستوى التدقيق
Access enforced in record rules, not hidden menusالوصول مفروضٌ في قواعد السجلات، لا في قوائم مخفية
Open sourceمفتوح المصدر
Live on GitHub under LGPL-3.0حيّ على GitHub تحت LGPL-3.0

§ Overviewنظرة عامة

What it does, and what I owned.ما الذي يفعله، وما الذي تولّيته.

Employee submits a receipt from mobile. Manager approves with one click from email. Finance posts with one click from email. The journal entry is generated automatically and a monthly department digest is mailed by cron — no logins along the way.الموظّف يقدّم إيصالاً من الجوال. المدير يوافق بنقرةٍ واحدة من البريد. المالية تُرحّل بنقرةٍ واحدة من البريد. يُولَّد القيد المحاسبي تلقائياً ويُرسَل ملخّصٌ شهري للقسم عبر cron — دون أي تسجيل دخولٍ في الطريق.

Roleالدور
UX + sole developerتجربة المستخدم + مطوّرة وحيدة
Timelineالإطار الزمني
2026 — present2026 — حتى الآن
Module typeنوع الوحدة
Odoo 19 customOdoo 19 مخصّصة
Usersالمستخدمون
Employees · managers · financeموظفون · مديرون · مالية
Auth patternنمط المصادقة
Token-secured URLرابطٌ مؤمّن برمز
Licenseالترخيص
LGPL-3.0 · open sourceLGPL-3.0 · مفتوح المصدر

§ Problemالمشكلة

Paper-based expense workflows in small businesses are quietly broken.تدفّقات النفقات الورقية في الشركات الصغيرة معطّلةٌ بصمت.

In a typical small business in Damascus, an employee buys something for work, keeps the receipt in a desk drawer for two weeks, hands it to a manager who signs a paper form, walks it to finance who types it into a ledger — and at every stage someone is the bottleneck. Receipts get lost. Numbers get re-typed. The whole loop is invisible to the company until month-end.في شركةٍ صغيرة نموذجية بدمشق، يشتري موظّفٌ شيئاً للعمل، ويحتفظ بالإيصال في درج مكتبٍ أسبوعين، ثم يسلّمه لمديرٍ يوقّع نموذجاً ورقياً، ويمشي به إلى المالية التي تكتبه في دفترٍ — وفي كل مرحلةٍ يكون أحدٌ هو عنق الزجاجة. تضيع الإيصالات. تُعاد كتابة الأرقام. وتبقى الحلقة كلّها غير مرئيةٍ للشركة حتى نهاية الشهر.

Existing Odoo expense modules require everyone in the chain to log into the system. In practice, managers don't log in. Approvals stall. The system goes unused. I needed a flow that works for people who never open Odoo.تتطلّب وحدات نفقات Odoo الموجودة أن يسجّل كلّ من في السلسلة دخوله إلى النظام. وعملياً، المديرون لا يسجّلون الدخول. تتعثّر الموافقات. ولا يُستخدَم النظام. احتجتُ تدفّقاً يعمل لأناسٍ لا يفتحون Odoo أبداً.

§ Users & personasالمستخدمون والـ Personas

Who has to actually use it.من عليه أن يستخدمه فعلاً.

The flow crosses three roles, and the one who decides whether the system lives or dies is the manager who never logs in. Each role became a persona with a one-line story and the friction that kept the old paper loop alive.يعبر التدفّق ثلاثة أدوار، ومن يقرّر حياة النظام أو موته هو المدير الذي لا يسجّل الدخول أبداً. صار كلّ دورٍ persona بقصةٍ من سطرٍ والاحتكاك الذي أبقى الحلقة الورقية القديمة حيّة.

Omar — employeeعمر — موظّف

Submits the expenseيقدّم النفقة

I just want to snap the receipt and get reimbursed — not babysit a paper form through the building.أريد فقط أن ألتقط صورة الإيصال وأُعوَّض — لا أن أرافق نموذجاً ورقياً عبر المبنى.

Goalsالأهداف

Submit from his phone in seconds; know where the request stands.التقديم من جوّاله في ثوانٍ؛ ومعرفة أين وصل الطلب.

Frustrationsالإحباطات

Lost receipts; reimbursements that take weeks because a form sat in a drawer.إيصالاتٌ ضائعة؛ وتعويضاتٌ تستغرق أسابيع لأن نموذجاً بقي في درج.

Nour — line managerنور — مديرة مباشِرة

Approves · the make-or-break userتوافق · المستخدمة الحاسمة

I want to approve in one tap from my inbox — I'm not going to log into yet another system to click yes.أريد أن أوافق بنقرةٍ واحدة من بريدي — لن أسجّل الدخول إلى نظامٍ آخر فقط لأنقر «نعم».

Goalsالأهداف

Clear the approval the moment she sees it, wherever she is.إنهاء الموافقة لحظة رؤيتها، أينما كانت.

Frustrationsالإحباطات

Being asked to log into Odoo for a 5-second decision — so approvals stall for days.أن يُطلب منها تسجيل الدخول إلى Odoo لقرارٍ من 5 ثوانٍ — فتتعثّر الموافقات أياماً.

Farah — financeفرح — المالية

Posts to the ledgerتُرحّل إلى دفتر الأستاذ

I want a clean ledger — only real, approved liabilities, never entries I have to reverse.أريد دفتر أستاذٍ نظيفاً — التزاماتٌ حقيقية معتمدة فقط، لا قيوداً أُضطرّ لعكسها.

Goalsالأهداف

Post with one click; trust that every entry is already approved.الترحيل بنقرةٍ واحدة؛ والثقة بأن كلّ قيدٍ معتمدٌ أصلاً.

Frustrationsالإحباطات

A ledger filling with unapproved or duplicate entries she has to clean up.دفتر أستاذٍ يمتلئ بقيودٍ غير معتمدة أو مكرّرة عليها تنظيفها.

§ Design strategyاستراتيجية التصميم

Optimize for the approval that actually happens.حسّن من أجل الموافقة التي تحدث فعلاً.

A module that's technically complete but never used is a failure. The whole strategy was to remove every reason a manager might not approve — starting with the login.وحدةٌ مكتملة تقنياً لكن لا تُستخدَم أبداً هي فشل. كانت الاستراتيجية كلّها إزالة كل سببٍ قد يجعل المدير لا يوافق — بدءاً من تسجيل الدخول.

Goalالهدف
Approvals that actually get done, fastموافقاتٌ تُنجَز فعلاً، وبسرعة
Hypothesisالفرضية
Email-as-UI removes the stall that kills adoption«البريد كواجهة» يزيل التعثّر الذي يقتل التبنّي
Priorityالأولوية
Friction reduction over feature surfaceتقليل الاحتكاك قبل اتّساع الميزات
Tradeoffالمفاضلة
Token-security burden for a zero-login flowعبء تأمين الرمز مقابل تدفّقٍ بلا تسجيل دخول

§ Approachالمقاربة

Email is the UI.البريد هو الواجهة.

The module attaches a unique token to each expense request when it's sent to a manager. The approval email contains two links: Approve and Reject. Each link is a one-time URL bound to the token, the request ID, and the manager's hr.employee record. Clicking it triggers a state transition — no Odoo login required.تُرفق الوحدة رمزاً فريداً بكل طلب نفقةٍ عند إرساله إلى المدير. ويحوي بريد الموافقة رابطين: موافقة ورفض. كلّ رابطٍ عنوانٌ يُستخدَم مرّةً واحدة مرتبطٌ بالرمز، ومعرّف الطلب، وسجلّ hr.employee للمدير. والنقر عليه يُطلق انتقال حالة — دون الحاجة لتسجيل الدخول إلى Odoo.

Architectureالبنية · Smart Expense Manager — approval flowSmart Expense Manager — مسار الموافقة

SVG

EMPLOYEESubmitmobile receipthr.employeeMANAGERApprove1-click · emailtoken-securedFINANCEPost1-click · emailpostJOURNALaccount.moveauto-generated⏱ cron job · QWeb PDF monthly digest emailed to managers
Token-secured email approvals · auto-journal on finance sign-off.موافقات عبر البريد محميّة برمز · قيد محاسبي تلقائي عند اعتماد المالية.

Approval email

Visual placeholder · add exportصورة مؤقتة · أضف التصدير

One-click Approve / Reject email — add screenshotبريد موافقة / رفض بنقرةٍ واحدة — تُضاف اللقطة

§ Technical architectureالبنية التقنية

Three trade-offs that shaped the build.ثلاث مفاضلاتٍ شكّلت البناء.

ADR-001

Token-secured URLs over OAuth approval flows.روابط مؤمّنة برمز بدل تدفّقات موافقة OAuth.

Contextالسياق

The standard Odoo pattern sends a notification email with a link into the Odoo UI. Manager logs in, finds the record, clicks approve. Real-world result: approvals stall for days.النمط القياسي في Odoo يرسل بريد إشعارٍ برابطٍ إلى واجهة Odoo. المدير يسجّل الدخول، ويجد السجلّ، وينقر موافقة. النتيجة في الواقع: تتعثّر الموافقات أياماً.

Decisionالقرار

I embed a cryptographically random token in the email URL itself. The token is single-use, bound to the request and the manager's employee record, and expires once acted on.أُضمّن رمزاً عشوائياً تشفيرياً في رابط البريد نفسه. الرمز يُستخدَم مرّةً واحدة، ومرتبطٌ بالطلب وبسجلّ موظّف المدير، وينتهي بمجرّد التصرّف به.

Consequencesالنتائج

Approvals collapse from days to seconds, and every state transition logs the token used. Trade-off: emails must be sent over TLS-encrypted SMTP, since the token grants action rights.تنهار الموافقات من أيامٍ إلى ثوانٍ، وكلّ انتقال حالةٍ يُسجّل الرمز المُستخدَم. المفاضلة: يجب إرسال الرسائل عبر SMTP مشفّر بـTLS، لأن الرمز يمنح حقوق التصرّف.
ADR-002

Journal entries on finance approval, not on submission.القيود المحاسبية عند موافقة المالية، لا عند التقديم.

Contextالسياق

An eager design auto-creates the journal entry the moment an employee submits. Simpler state machine, but the ledger fills with unapproved entries that have to be reversed.تصميمٌ متعجّل يُنشئ القيد المحاسبي تلقائياً لحظة تقديم الموظّف. آلة حالاتٍ أبسط، لكن دفتر الأستاذ يمتلئ بقيودٍ غير معتمدة يلزم عكسها.

Decisionالقرار

The account.move is only generated on the finance-approval transition. Until then, the request is just an HR record.لا يُولَّد account.move إلا عند انتقال موافقة المالية. حتى ذلك الحين، يبقى الطلب مجرّد سجلّ موارد بشرية.

Consequencesالنتائج

The ledger stays clean — accountants only see entries that are real liabilities. Trade-off: an extra state, and the cron digest must know to skip pending requests.يبقى دفتر الأستاذ نظيفاً — لا يرى المحاسبون إلا قيوداً تمثّل التزاماتٍ حقيقية. المفاضلة: حالةٌ إضافية، وعلى ملخّص cron أن يعرف تخطّي الطلبات المعلّقة.
ADR-003

RBAC at the record-rule layer, not the menu layer.تحكّمٌ بالوصول في طبقة قواعد السجلات، لا طبقة القوائم.

Contextالسياق

The easiest Odoo RBAC hides menus per group. But users can still construct URLs and reach records they shouldn't see.أسهل تحكّمٍ بالوصول في Odoo يُخفي القوائم حسب المجموعة. لكن يظلّ بإمكان المستخدمين تركيب الروابط والوصول إلى سجلاتٍ لا ينبغي أن يروها.

Decisionالقرار

Permissions live in record rules at the ORM layer. An employee sees only their own requests; a manager only requests routed to them; finance the approved queue. Menu hiding is cosmetic — the rules are the contract.تعيش الصلاحيات في قواعد السجلات في طبقة ORM. الموظّف يرى طلباته فقط؛ والمدير الطلبات المُوجَّهة إليه فقط؛ والمالية الطابور المعتمد. إخفاء القوائم تجميلي — القواعد هي العقد.

Consequencesالنتائج

Audit-grade access enforcement. A URL-poking employee hits an ORM exception, not a leak. Trade-off: a small testing matrix for cross-role visibility.فرضُ وصولٍ بمستوى التدقيق. موظّفٌ يعبث بالروابط يصطدم باستثناء ORM، لا بتسريب. المفاضلة: مصفوفة اختبارٍ صغيرة للرؤية عبر الأدوار.

§ Bilingual by defaultثنائي اللغة افتراضياً

Full EN/AR translations — not an afterthought.ترجمةٌ كاملة بالإنجليزية والعربية — لا فكرةً لاحقة.

Every field, label, status, email template, and PDF report ships with full Arabic and English translations. The approval emails detect the recipient's preferred language from their res.users.lang setting, and QWeb-generated PDF reports pick up the same locale automatically.كلّ حقلٍ وتسمية وحالة وقالب بريدٍ وتقرير PDF يُطلق بترجمةٍ كاملة بالعربية والإنجليزية. وتكتشف رسائل الموافقة لغة المستلِم المفضّلة من إعداد res.users.lang الخاص به، وتلتقط تقارير PDF المُولّدة بـQWeb المنطقة نفسها تلقائياً.

In a Damascus-based SME, this is what makes the difference between a module that gets installed and one that gets used.في شركةٍ صغيرة بدمشق، هذا ما يصنع الفرق بين وحدةٍ تُثبَّت وأخرى تُستخدَم.

§ Outcomesالنتائج

A pattern worth open-sourcing.نمطٌ يستحقّ أن يُفتَح مصدره.

Smart Expense is live and open source under LGPL-3.0 — the token-secured approval flow turns a multi-day paper loop into a one-click action that managers complete from their inbox, with access enforced at the ORM layer and a clean ledger downstream.Smart Expense حيّ ومفتوح المصدر تحت LGPL-3.0 — يحوّل تدفّق الموافقة المؤمّن بالرمز حلقةً ورقية تستغرق أياماً إلى إجراءٍ بنقرةٍ واحدة يُنجزه المديرون من بريدهم، بوصولٍ مفروضٍ في طبقة ORM ودفتر أستاذٍ نظيف تالياً.

  1. Reusable. The token-secured approval pattern generalizes far beyond expense reports.قابل لإعادة الاستخدام. نمط الموافقة المؤمّن بالرمز يتعمّم إلى ما هو أبعد بكثير من تقارير النفقات.
  2. Auditable. An Odoo 19 module signed with my name lives longer than a CV bullet.قابل للتدقيق. وحدة Odoo 19 موقّعةٌ باسمي تعيش أطول من سطرٍ في سيرةٍ ذاتية.
  3. Low IP risk. The module is mechanical, not strategic — sharing it costs nothing and helps the Odoo community.مخاطر ملكيةٍ فكرية منخفضة. الوحدة آليّة، لا استراتيجية — مشاركتها لا تكلّف شيئاً وتُفيد مجتمع Odoo.

§ Validationالتحقّق

The real test is adoption.الاختبار الحقيقي هو التبنّي.

For an internal tool, the success metric isn't a satisfaction score — it's whether managers actually approve. I'd validate with a short usability study on the one-click email path, then watch the token logs (which already record every transition) as the affinity-style signal for where the flow stalls, and prioritize from there.بالنسبة لأداةٍ داخلية، مقياس النجاح ليس درجة رضا — بل ما إذا كان المديرون يوافقون فعلاً. سأتحقّق بدراسة قابلية استخدامٍ قصيرة على مسار البريد بنقرةٍ واحدة، ثم أراقب سجلّات الرمز (التي تُسجّل كل انتقالٍ أصلاً) كإشارةٍ — على غرار التقارب — لأين يتعثّر التدفّق، وأرتّب الأولويات من هناك.

  • P0The one-click Approve / Reject must work reliably across the email clients managers actually use — if it breaks once, trust in the link is gone.«موافقة / رفض» بنقرةٍ واحدة يجب أن يعمل بثباتٍ عبر عملاء البريد التي يستخدمها المديرون فعلاً — إن تعطّل مرّةً، ذهبت الثقة بالرابط.
  • P1The Arabic and English approval emails must render identically well, since recipients act straight from the inbox.بريدا الموافقة بالعربية والإنجليزية يجب أن يُعرَضا بجودةٍ متطابقة، لأن المستلِمين يتصرّفون مباشرةً من البريد.
  • P2A lightweight audit dashboard surfacing the token logs — proving adoption from data that already exists.لوحة تدقيقٍ خفيفة تُظهر سجلّات الرمز — لإثبات التبنّي من بياناتٍ موجودةٍ أصلاً.

§ Reflectionتأمّل

What I'd carry forward.ما سأحمله معي.

The win here was a product insight, not a technical one: meeting people where they already are (their inbox) beats any amount of in-app polish they'll never see. I'll keep reaching for the lowest-friction surface before building a new screen.كان الفوز هنا استنتاجاً عن المنتج، لا تقنياً: لقاء الناس حيث هم أصلاً (بريدهم) يتفوّق على أي قدرٍ من الصقل داخل التطبيق لن يروه أبداً. وسأظلّ أمدّ يدي إلى أقلّ السطوح احتكاكاً قبل بناء شاشةٍ جديدة.

Next, I'd add usage analytics and a lightweight audit dashboard — the token model already logs every transition, so the data to prove adoption is there to surface.تالياً، سأضيف تحليلات استخدامٍ ولوحة تدقيقٍ خفيفة — نموذج الرمز يُسجّل كلّ انتقالٍ أصلاً، فالبيانات اللازمة لإثبات التبنّي موجودةٌ وجاهزة للعرض.