مقارنة برامج الفوترة المستضافة ذاتيًا على VPS واحد
قارن Invoice Ninja وInvoiceShelf وInvoicePlane وKimai وERPNext على VPS واحد: الفوترة المتكررة والضرائب وبوابة العميل والدفع وشروط التراخيص.
ما برنامج الفوترة الذي تستضيفه بنفسك ينبغي أن تختار؟
تنحصر خيارات برامج الفوترة المستضافة ذاتياً والواقعية على VPS واحد في خمسة خيارات، وهي ليست بدائل متقاربة. يُعد Invoice Ninja المنتج الأكثر اكتمالاً: تعمل الفواتير المتكررة، وبوابة العميل، وبوابات الدفع، وتنسيقات الفواتير الإلكترونية منذ يوم تثبيته. أما InvoiceShelf فهو الخيار الأخف والمفتوح المصدر بالكامل. وInvoicePlane تطبيق PHP بسيط لا يحتاج إلى تنسيق مكونات متعددة. ويحسب Kimai الساعات المتعقبة بدلاً من بنود الفاتورة. أما ERPNext فهو نظام محاسبة كامل يطبع الفواتير أيضاً.
هناك مشكلتان تتسببان في فشل إعداد الفوترة المستضافة ذاتياً أكثر بكثير من فقدان ميزة ما. الأولى هي البريد الإلكتروني. الفاتورة الموجودة في مجلد البريد العشوائي هي فاتورة غير مدفوعة، ولا توجد طريقة تخبرك بأن ذلك حدث. والثانية هي النسخ الاحتياطية. هذه هي قاعدة البيانات المستضافة ذاتياً التي يؤدي فقدانها إلى مشكلة ضريبية، لا مجرد إزعاج.
اقرأ الترخيص قبل أن تقرأ قائمة الميزات. ثلاثة من هذه الخيارات الخمسة تستخدم تراخيص copyleft، وواحد يستخدم ترخيصاً متساهلاً، وواحد يتيح الشيفرة المصدرية مع قيود فعلية على ما يمكنك فعله بها.
الخيارات الخمسة، ولمن يناسب كل خيار
Invoice Ninja
تطبيق Laravel، وهو حالياً ضمن سلسلة v5. الاستضافة الذاتية مجانية ومفتوحة بالكامل: الفواتير المتكررة، وعروض الأسعار، والمشاريع، وتتبع الوقت، والمصروفات، وبوابة العملاء، وبوابات الدفع، بما فيها Stripe وPayPal. يصف المشروع نفسه بأنه «تطبيق للفواتير وعروض الأسعار والمشاريع وتتبع الوقت، ومتاح المصدر، ومبني باستخدام Laravel». الجزء المدفوع الوحيد هو إزالة العلامة التجارية. ووفقاً لكلمات المشروع نفسه: «نقدم ترخيص white-label بسعر $40 سنوياً لإزالة العلامة التجارية لـ Invoice Ninja من الأجزاء التي يراها العملاء في التطبيق». هذا السعر ساري حتى August 2026.
اختره إذا كنت تريد المنتج الأكثر تكاملاً، وتقبل بتشغيل أكبر حزمة من المكونات.
InvoiceShelf
نسخة fork من Crater، ومرخّصة بموجب GNU Affero General Public License version 3 (AGPL-3.0). تشمل الفواتير، والتقديرات، والفوترة المتكررة، والمصروفات، والضرائب، وتعدد العملات، وبوابة العملاء، ودعم عدة شركات. توجد المدفوعات وإزالة العلامة التجارية في مستودعين رسميين منفصلين للوحدات، وكلاهما مرخّص بموجب AGPL-3.0 ومتاح مجاناً. تتم مدفوعات البطاقات عبر Stripe checkout.
اختره إذا كنت تريد تطبيقاً صغيراً ومفتوح المصدر بالكامل، ولا تحتاج إلى ثلاثين بوابة دفع.
InvoicePlane
تطبيق PHP مبني على CodeIgniter، ومرخّص بموجب MIT licence. وهو الخيار الوحيد هنا الذي يثبَّت بفك ضغط الملفات داخل web root. لا يستخدم Docker ولا يتطلب خطوة بناء لـ Node. تُنشأ ملفات PDF باستخدام mPDF، لذلك تكون القوالب عبارة عن HTML وCSS. يحصل العملاء على guest link لعرض الفاتورة ودفعها.
المشكلة هي المدفوعات. توضح الوثائق صراحةً أن InvoicePlane 1.6 يدعم Stripe فقط افتراضياً، وأن مزوّدي الدفع الآخرين أُزيلوا في ذلك الإصدار. المتطلبات المنشورة لسلسلة 1.6 هي PHP 8.0 إلى 8.1 مع MySQL 5.5 أو إصدار MariaDB المطابق. اقرأ ملاحظات الإصدار الذي ستنزّله، لأن سلسلة 1.7 ما زالت قيد التطوير.
اختره إذا كنت تستخدم shared hosting أو VPS بسعة 512 MB.
Kimai
أداة لتتبع الوقت، ومرخّصة بموجب AGPL-3.0، وتُنشئ الفواتير من جداول الساعات. وهي الخيار المناسب لمن يحاسب العملاء على أساس الساعات. تُرفع قوالب الفواتير كملفات DOCX أو ODS أو XLSX، وتؤكد الوثائق أن هذه هي الصيغ المقبولة الوحيدة، ثم تُحوَّل إلى PDF أو HTML. تنسّق فاتورتك في معالج نصوص بدلاً من كتابة CSS، وهذا أسهل لمعظم المستخدمين.
لا يوفّر Kimai بوابة عملاء ولا بوابة دفع، لذلك ترسل ملف PDF عبر البريد الإلكتروني. الفوترة الإلكترونية المنظمة متاحة كإضافة مدفوعة من المتجر باسم E-Invoice Plus، بسعر مدرج قدره 99 EUR سنوياً، دون VAT، للتثبيت الذاتي، وذلك حتى August 2026. وتشمل الإضافة ملفات EN16931 وXRechnung وZUGFeRD وFactur-X وPeppol.
اختره إذا كانت الفاتورة ناتجة عن الوقت الذي تتبعه.
ERPNext
مرخّص بموجب GPL-3.0، وينتمي إلى فئة مختلفة من البرمجيات. فاتورة المبيعات هي نوع مستند واحد داخل نظام محاسبة متكامل يضم شجرة حسابات، وقيوداً يومية، ومخزوناً، ورواتب. وهو الخيار المناسب عندما تتوقف الفوترة عن كونها المهمة الأساسية الوحيدة. أما لمستقل واحد لديه ثمانية عملاء، فهو برنامج أكبر بكثير من الحاجة. إعداد النظام مشروع مستقل بحد ذاته، وقد غُطي في تشغيل ERPNext على VPS.
تعتمد الفواتير الدورية على مجدول لا يمكنك رؤيته
ينشئ Invoice Ninja وInvoiceShelf وInvoicePlane وERPNext فواتير دورية. لا تتضمن Kimai ميزة الفواتير الدورية في النواة، لأن الفاتورة فيها تُنشأ من قيود سجل الساعات لفترة محددة.
نمط الفشل واحد في جميع التطبيقات المبنية على Laravel، ويحدث بصمت. تُنشأ الفواتير الدورية بواسطة مهمة مجدولة، php artisan schedule:run، ويجب أن يستدعيها مكوّن خارج التطبيق كل دقيقة. إذا لم يستدعها أي مكوّن، فستظل قائمة الفواتير الدورية تعرض تاريخ الإرسال التالي، ويمر ذلك التاريخ ببساطة. لن تظهر أي فاتورة. ولن يُسجَّل أي خطأ، لأن الشيفرة لم تُنفَّذ.
لذلك، بعد إنشاء أول فاتورة دورية، اضبط تاريخ الإرسال التالي ليكون بعد بضع دقائق وانتظر. إذا لم تصل أي فاتورة، فالمجدول لا يعمل. في تثبيت Docker، يعني ذلك عادةً أن خدمة cron أو scheduler في ملف compose لم تبدأ، أو أنها توقفت.
docker compose ps
docker compose logs --tail 50يجب أن تعرض كل خدمة في الملف الحالة running. أما الخدمة التي تكون في الحالة exited فهي الخدمة التي تحتاج إلى قراءة سجلاتها.
العملات المتعددة والضرائب: ما يجب التحقق منه قبل الالتزام
تذكر قوائم الميزات عبارة «العملات المتعددة»، لكنها قد تعني أشياء مختلفة جداً. نفّذ هذه الاختبارات الأربعة على نسخة تجريبية، مستخدماً أرقاماً حقيقية من نشاطك التجاري، لأن محاسبك هو من سيكتشف الخطأ هنا، لا أنت.
- هل تحفظ الفاتورة سعر الصرف المطبّق في تاريخ إصدارها؟ يجب أن تفعل ذلك. إذا كان التطبيق يعيد حساب الإجماليات باستخدام سعر صرف مباشر، فستتغير تقارير الربع السابق في كل مرة تفتحها فيها، ولن تعود دفاترك مطابقة لما سبق أن أودعته.
- هل تُطبَّق الضريبة على كل بند، أم على الفاتورة، أم على كليهما؟ يكون استخدام معدل واحد على مستوى الفاتورة مناسباً إلى أن يتضمن أحد البنود ضريبة بنسبة صفر.
- هل يمكنك إدخال الأسعار شاملة الضريبة وكذلك غير شاملة لها؟ يؤدي التحويل بعد ذلك إلى فروق تقريب مقدارها سنت واحد لكل بند، وتتراكم هذه الفروقات خلال السنة.
- ماذا يعرض المستند لعميل في دولة أخرى لا يدين بضريبة VAT؟ تحتاج إلى طباعة ملاحظة الإعفاء على الفاتورة، وليس مجرد عرض صفر في عمود الضريبة.
يتعامل Invoice Ninja وERPNext مع الحالات الأربع كلها. ويذكر InvoiceShelf الضرائب والعملات المتعددة ضمن ميزاته. أما InvoicePlane وKimai فهما أبسط، لذلك اختبرهما باستخدام أكثر فواتيرك تعقيداً، لا أسهلها.
بوابة العميل وبوابات الدفع
بوابة العميل هي صفحة يعرض فيها العميل فواتيره، وينزّل ملفات PDF، ويدفع مستحقاته. وتكمن أهميتها في أنها أكبر مما قد يبدو، لأن متابعة الدفع عبر البريد الإلكتروني تستهلك من وقتك أكثر مما استغرقه إصدار الفاتورة.
يتفوق Invoice Ninja في هذا الجانب، إذ يوفّر بوابة متكاملة، والعديد من بوابات الدفع، ووسائل دفع محفوظة، والفوترة التلقائية للفواتير المتكررة. يوفّر InvoiceShelf بوابة للعملاء، ويضيف صفحة دفع Stripe من خلال وحدة payments الخاصة به. ويمنح InvoicePlane كل فاتورة رابط ضيف، ويدعم Stripe. أما Kimai فلا يوفّر أياً من ذلك، لذلك يُرسل ملف PDF كمرفق.
هناك نقطة يكثر الخلط بشأنها. لا يعني الاستضافة الذاتية لتطبيق الفوترة أنك تحتفظ بأرقام البطاقات. عند استخدام صفحة دفع Stripe، يُعاد توجيه العميل إلى Stripe، ويدخل بيانات البطاقة هناك، ولا يرى VPS الخاص بك الرقم مطلقاً. ويظل نطاق التزاماتك المتعلقة بمعيار PCI (صناعة بطاقات الدفع) محدوداً، تحديداً لأنك لم تبنِ نموذج الدفع بنفسك. إذا احتجت لاحقاً إلى أكثر من معالج دفع واحد، أو أردت توجيه المدفوعات حسب البلد، فينبغي وضع ذلك في طبقة منفصلة مثل تنسيق المدفوعات المستضاف ذاتياً باستخدام Hyperswitch.
جودة PDF، والقالب الذي ستنتهي إلى تحريره
ستحرّر القالب. كل قيمة افتراضية هنا تضع عنوانك في الموضع الخاطئ لبلدك.
يعرض Invoice Ninja قوالب HTML وCSS بصيغة PDF باستخدام Chromium يعمل دون واجهة رسومية ومضمّن في image، ولذلك تكون الحاوية كبيرة. خصّص له قدراً كافياً من الذاكرة: فالمتصفح الذي يعمل دون واجهة رسومية هو أثقل عملية في المكدس، ولذلك تكون VPS بسعة 1 GB محدودة. يستخدم InvoicePlane مكتبة mPDF، وهي مكتبة PHP خالصة وخفيفة، لكن ذلك يأتي على حساب تجاهل بعض ميزات CSS الحديثة. أما Kimai فيتبع نهجاً معاكساً، إذ يطلب منك تحميل ملف DOCX أو ODS، بحيث ينفّذ شخص لم يكتب stylesheet من قبل تنسيق المستند في LibreOffice أو Word.
إذا كان تصميم الفاتورة مهماً لك ولا تحتاج إلى CSS، فإن نهج Kimai هو الأفضل. وإذا أردت حفظ القالب في version control وإجراء diff عليه، فإن HTML هو الخيار الأفضل.
هل يتيح لك الترخيص استخدامه تجارياً؟
تتيح لك المنتجات الخمسة إصدار فواتير لعملائك مباشرةً. تظهر الفروق عندما تفعل أي شيء يتجاوز ذلك.
يخضع Invoice Ninja لـElastic License 2.0. هناك بندان مهمان.
لا يجوز لك توفير البرنامج إلى أطراف ثالثة كخدمة مستضافة أو مُدارة، إذا كانت الخدمة تتيح للمستخدمين الوصول إلى مجموعة كبيرة من ميزات البرنامج أو وظائفه.
لا يجوز لك نقل وظيفة مفتاح الترخيص في البرنامج أو تغييرها أو تعطيلها أو التحايل عليها.
لذلك، لا مشكلة في تشغيله لنشاطك التجاري، لكن لا يجوز تشغيل مثيلات للعملاء باعتباره منتجاً. والبند الثاني هو سبب كون إزالة العلامة التجارية ترخيصاً بقيمة $40، وليست تعديلاً على source.
يخضع InvoiceShelf وKimai وCrater لـAGPL-3.0. الاستخدام التجاري مجاني، ولا توجد طبقة أعلى منك. يرد الالتزام في القسم 13: إذا عدّلت code وأتحت لأشخاص آخرين استخدام نسختك المعدّلة عبر network، فيجب أن تتيح لهم source الخاص بتغييراتك. أما instance غير المعدّلة، فهي مشمولة أصلاً بـsource العام للمشروع الأصلي، ولذلك لا يضطر معظم مشغّلي الاستضافة الذاتية إلى التعامل مع هذا الالتزام.
يخضع InvoicePlane لـMIT، وهو أخف التزامات المجموعة، مع أن README يوضح أن الاسم والشعار يظلان ملكاً للمشروع.
يخضع ERPNext لـGPL-3.0. يجب مشاركة التعديلات التي توزّعها، ولا ينشأ أي التزام من تشغيله بشكل خاص.
هذا وصف لنص الترخيص، وليس استشارة قانونية.
هل ما زال المشروع قيد الصيانة؟ تحقّق من سجل الالتزامات
كان Crater تطبيق الفوترة مفتوح المصدر الشائع لعدة سنوات، ولا تزال أدلة كثيرة توصي به. لم يتضمن الفرع الافتراضي أي التزام منذ 741 يوماً.
The data behind this chart
[
{
"label": "ERPNext",
"commit_gap": 0
},
{
"label": "Invoice Ninja",
"commit_gap": 1
},
{
"label": "Kimai",
"commit_gap": 1
},
{
"label": "InvoicePlane",
"commit_gap": 3
},
{
"label": "InvoiceShelf",
"commit_gap": 4
},
{
"label": "Crater",
"commit_gap": 741
}
]من بين المشاريع البالغ عددها 6 في تلك الكتلة، تضمّن خمسة منها التزاماً خلال الأسبوع الماضي. يُعد InvoiceShelf النسخة المتفرعة التي واصلت العمل على Crater، بموجب ترخيص AGPL-3.0 نفسه وبنموذج البيانات نفسه، ولذلك فإن الانتقال إليه هو ترحيل للبيانات وليس إعادة كتابة. ثبّت InvoiceShelf، وليس Crater.
تثبيت كل تطبيق على VPS
تعمل جميع التطبيقات، باستثناء InvoicePlane، بسهولة أكبر باستخدام Docker Compose. إذا كان ذلك جديداً عليك، فابدأ بـ أول حزمة Docker Compose على VPS ثم عُد إلى هنا.
يصدر Invoice Ninja مستودع compose خاصاً به.
git clone https://github.com/invoiceninja/dockerfiles.git
cd dockerfiles
docker run --rm -it invoiceninja/invoiceninja php artisan key:generate --showانسخ ذلك المفتاح إلى الملف env في المستودع، مع إضافة APP_URL الفعلي الخاص بك. ثم اضبط الملكية التي تتوقعها image وشغّلها.
chmod 755 docker/app/public
sudo chown -R 1500:1500 docker/app
docker compose up -dتطابق ملكية 1500:1500 المستخدمَ داخل image. إذا تخطيت هذه الخطوة، فلن يتمكن التطبيق من الكتابة إلى ذاكرة التخزين المؤقت أو ملفات PDF التي ينشئها. في معالج الإعداد، أدخل db باعتباره مضيف قاعدة البيانات، لأنه اسم الخدمة على شبكة compose. يشير localhost هناك إلى حاوية التطبيق نفسها.
ينشر InvoiceShelf ملفات compose جاهزة، ملفاً واحداً لكل محرك قاعدة بيانات.
curl -fLO https://raw.githubusercontent.com/InvoiceShelf/docker/master/docker-compose.mysql.yml
mv docker-compose.mysql.yml docker-compose.ymlافتح ذلك الملف قبل تشغيله. كل كلمة مرور فيه هي قيمة نائبة، ويوضح الملف ذلك في تعليقاته. تكون APP_URL وSESSION_DOMAIN وSANCTUM_STATEFUL_DOMAINS مضبوطة افتراضياً على localhost، ويجب ضبط الثلاثة على اسم المضيف الفعلي قبل تسجيل الدخول للمرة الأولى. ثم شغّلها.
docker compose up -dينشر المنفذ 8090 على المضيف، ويخدم على المنفذ 8080 داخل الحاوية. ضع reverse proxy مع TLS (أمان طبقة النقل) أمامه قبل توجيه أي عميل إليه.
ملف compose للإنتاج في Kimai، من وثائق المشروع
services:
sqldb:
image: mysql:8.3
volumes:
- mysql:/var/lib/mysql
environment:
- MYSQL_DATABASE=kimai
- MYSQL_USER=kimaiuser
- MYSQL_PASSWORD=kimaipassword
- MYSQL_ROOT_PASSWORD=changemeplease
command: --default-storage-engine innodb
restart: unless-stopped
healthcheck:
test: mysqladmin -uroot -p$$MYSQL_ROOT_PASSWORD ping -h 127.0.0.1 --silent
interval: 10s
timeout: 5s
retries: 12
start_period: 30s
kimai:
image: kimai/kimai2:stable
depends_on:
sqldb:
condition: service_healthy
restart: true
volumes:
- data:/opt/kimai/var/data
- plugins:/opt/kimai/var/plugins
ports:
- 8001:8001
environment:
- APP_SECRET=your-fantastic-long-random-and-ultra-secure-secret
- TRUSTED_HOSTS=kimai.example.com
- ADMINMAIL=admin@example.com
- ADMINPASS=changemeplease
- DATABASE_URL=mysql://kimaiuser:kimaipassword@sqldb/kimai?charset=utf8mb4&serverVersion=8.3.0
restart: unless-stopped
volumes:
data:
mysql:
plugins:اضبط APP_SECRET على سلسلة عشوائية طويلة من اختيارك، واضبط TRUSTED_HOSTS على النطاق الذي ستستخدمه فعلياً. ينشئ ADMINMAIL وADMINPASS أول مدير عند الإقلاع الأول، لذلك غيّر كلمة المرور هذه في الواجهة بعد ذلك وأزلها من الملف.
لا يحتوي InvoicePlane على حاوية. أنشئ قاعدة بيانات فارغة أولاً.
sudo mysql -e "CREATE DATABASE invoiceplane CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"نزّل الأرشيف من صفحة إصدارات المشروع، واستخرجه إلى جذر الويب، وانسخ ipconfig.php.example إلى ipconfig.php، واضبط عنوان URL الخاص بك داخله باتباع التعليقات الموجودة في الملف. ثم افتح https://your-domain.example/index.php/setup واتبع خطوات برنامج التثبيت.
لماذا تصل فاتورتك إلى مجلد البريد العشوائي
هذا هو العطل الذي يكلّفك المال، وسيعرض التطبيق الفاتورة على أنّها أُرسلت دون مشكلة.
لا ترسل البريد الخاص بالفواتير من عنوان IP الخاص بـVPS نفسه. لا يملك عنوان IP جديد لـVPS سجل إرسال سابقاً، وتتعامل الجهات المستقبِلة الكبيرة افتراضياً مع أول رسالة من عنوان غير معروف ضمن نطاق استضافة على أنّها رسالة مشبوهة. أرسل الرسائل عبر SMTP (بروتوكول نقل البريد البسيط) relay على نطاق صادقت عليه. يتطلب تنفيذ ذلك من البداية إلى النهاية دليلاً مستقلاً، ويشرح إرسال البريد بشكل موثوق من تطبيق مستضاف ذاتياً إعداد relay، وسجلات DNS، والاختبار.
يحدث معظم الخطأ في إعدادات الفوترة في عنوان From. يجب أن يكون العنوان على نطاق تتحكم فيه، وأن يوقّعه relay باستخدام DKIM (بريد النطاقات المحددة بالمفاتيح). قد يبدو وضع عنوان العميل في From تصرفاً مهذباً، لكنه يعطّل التسليم، لأن الخادم المستقبِل يتحقق من تطابق نطاق From مع النطاق الذي صادق على الرسالة. يرفض Gmail عدم التطابق مباشرة:
550 5.7.1 Unauthenticated email from example.com is not accepted due to domain's DMARC policyاحتفظ بعنوانك في From، وضع عنوان العميل في Reply-To. افحص السجلات المنشورة قبل إرسال أي رسالة فعلية.
dig +short TXT example.com
dig +short TXT _dmarc.example.com
dig +short TXT selector1._domainkey.example.comيجب أن يعيد الاستعلام الأول سجل SPF (إطار سياسة المرسل) الذي يذكر relay الخاص بك. ويجب أن يعيد الثاني سياسة DMARC (مصادقة الرسائل المستندة إلى النطاق وإعداد التقارير والامتثال). يعتمد الثالث على selector الذي منحه لك relay، وتعني الإجابة الفارغة أنّ سجل DKIM مفقود أو منشور باسم غير صحيح؛ لذلك سيفشل فحص التوقيع لكل رسالة ترسلها.
أرسل بعد ذلك فاتورة فعلية إلى حساب تملكه لدى مزوّد كبير، واقرأ الرؤوس الخام. يُعد ظهور dkim=pass وspf=pass في رأس Authentication-Results الدليل الوحيد الموثوق. وتعني علامة "sent" في التطبيق فقط أنّه سلّم الرسالة إلى relay.
النسخ الاحتياطية: قاعدة البيانات الوحيدة التي لا يمكنك فقدانها
يعني فقدان خادم الوسائط تنزيل الملفات مرة أخرى. وحتى خادم صور مستضاف ذاتياً مثل PhotoPrism أو Immich يحتفظ عادةً بنسخة ثانية من الملفات الأصلية التي ما تزال موجودة على الهاتف الذي التقطها. أما فقدان قاعدة بيانات الفوترة فيعني أنك لا تستطيع إثبات ما فوّترته، وما دُفع لك، وما يزال مستحقاً عليك. تعامل معها وفقاً لذلك.
انسخ أربعة أشياء احتياطياً. قاعدة البيانات. وحدة التخزين التي تحتوي على الشعارات وملفات PDF المُنشأة وإيصالات المصروفات. ملف بيئة التطبيق. وملفات PDF المُصدَّرة المحفوظة كملفات عادية، لأن ملف PDF يفتح بعد عشر سنوات حتى من دون التطبيق الذي أنشأه.
ملف البيئة أهم مما يتوقع كثيرون. يشفّر Laravel القيم الحساسة المخزنة، بما في ذلك بيانات اعتماد بوابة الدفع، باستخدام APP_KEY الموجود في ذلك الملف. إذا استعدت قاعدة البيانات إلى جانب مفتاح مُنشأ حديثاً، فلن تُفكّ شفرة تلك القيم. ستكون فواتيرك موجودة كلها، لكن إعدادات بوابة الدفع لن تكون قابلة للقراءة.
يبدو التفريغ من مكدس InvoiceShelf كما يلي. تعمل خدمة قاعدة البيانات لديه على mariadb:10، ولذلك تكون الأداة الموجودة داخل الحاوية هي mariadb-dump.
docker compose exec -T database mariadb-dump \
--user=root --password=YOUR_ROOT_PASSWORD \
--single-transaction --databases invoiceshelf > invoiceshelf.sqlيأخذ --single-transaction لقطة متسقة لجداول InnoDB من دون قفلها، لذلك يواصل التطبيق تقديم الخدمة أثناء تشغيل التفريغ. ويمنع -T Docker من تخصيص طرفية، لأن ذلك قد يفسد المخرجات المُعاد توجيهها وينتج ملف تفريغ لا يمكن استيراده.
أرسل النسخة الاحتياطية خارج الخادم وفق جدول زمني باستخدام نسخ restic الاحتياطية المشفّرة إلى تخزين خارج الموقع، واضبط مدة الاحتفاظ بما يكفي لتغطية الفترة التي يحددها محاسبك.
ثم استعدها. شغّل التفريغ في حاوية مؤقتة، وسجّل الدخول، وافتح فاتورة الشهر الماضي. ما لم تفعل ذلك مرة واحدة، فلن تعرف ما إذا كانت النسخة الاحتياطية تعمل.
ما سيطلبه منك المحاسب
لا تعتمد على هذا الدليل للحصول على مشورة ضريبية. يوضح ما يلي ما يستطيع هذا البرنامج إنتاجه، حتى تتمكن من أخذ القائمة إلى الشخص الذي يقدم لك المشورة.
البيانات القابلة للتصدير. ينبغي أن تتمكن من تصدير فواتيرك ومدفوعاتك إلى CSV من الواجهة، من دون استخدام عميل قاعدة بيانات ومن دون فتح تذكرة دعم. تفريغ SQL نسخة احتياطية، وليس تصديراً، لأن المحاسب لا يستطيع فتحه.
الترقيم غير القابل للتغيير. ينبغي أن تسير أرقام الفواتير بالتسلسل وألا يعاد استخدامها مطلقاً، من دون فجوات. يؤدي حذف فاتورة إلى ترك فجوة يجب تفسيرها لاحقاً. ألغِ الفاتورة أو أصدر إشعاراً دائناً بدلاً من ذلك، فهذا ما تدعمه كل التطبيقات هنا. يعتمد إلزامك بالترقيم المتصل من دون فجوات على مكان تسجيلك، ومن المفيد أن تسأل عن ذلك مبكراً.
الاحتفاظ. احتفظ بتفريغات قاعدة البيانات وملفات PDF المعروضة طوال المدة التي تفرضها القواعد المعمول بها. ملف PDF هو المستند الذي أُرسل فعلياً، وهو السجل المهم إذا اعترض أحد على فاتورة.
سجل التغييرات. من المفيد أن تتمكن من إظهار من عدّل فاتورة ومتى عدّلها، ويختلف هذا الجانب بدرجة أكبر بين هذه التطبيقات. يحتفظ Invoice Ninja بسجل نشاط لكل سجل.
أصبح إصدار الفواتير الإلكترونية المنظمة متطلباً فعلياً، وليس ميزة إضافية محبذة، في أجزاء من الاتحاد الأوروبي. ينشئ Invoice Ninja التنسيقات الشائعة، بما في ذلك ZUGFeRD وXRechnung وFacturae وFatturaPA والتنسيق العام EN16931. يمر التسليم عبر شبكة Peppol من نسخة مستضافة ذاتياً عبر نقطة الوصول الخاصة بـInvoice Ninja: تسجّل كيانك لديهم وتشتري أرصدة لكل عملية إرسال، ولذلك فهي خدمة مدفوعة اعتباراً من August 2026. يصل Kimai إلى التنسيقات نفسها عبر إضافته المدفوعة. لا ينتج أي من التطبيقات الثلاثة الأخرى فواتير إلكترونية منظمة حتى اليوم، وهذا هو السبب الأقوى لاختيار Invoice Ninja إذا كنت تصدر الفواتير داخل الاتحاد الأوروبي.
FAQ
هل أُثبّت Crater أم InvoiceShelf؟
InvoiceShelf. لم يتضمن الفرع الافتراضي لـCrater أي commit منذ 741 يوماً حتى 21 August 2026، كما يشير متتبّع المشكلات الخاص به إلى النسخة المتفرعة. يستخدم InvoiceShelf ترخيص AGPL-3.0 نفسه ونموذج البيانات نفسه، لذلك يكون الانتقال بينهما عملية ترحيل لقاعدة البيانات، وليس إعادة كتابة. أي دليل لا يزال يوصي بـCrater كُتب قبل أن يتوقف المشروع عن النشاط.
هل يمكنني استخدام Invoice Ninja لأعمالي الخاصة من دون دفع؟
نعم. يعمل Invoice Ninja المستضاف ذاتياً بكامل وظائفه مجاناً من خلال ترخيص Elastic License 2.0، بما في ذلك الفواتير المتكررة، وبوابة العميل، وبوابات الدفع. هناك أمران يتطلبان الدفع. إزالة العلامة التجارية لـInvoice Ninja من الصفحات الموجهة إلى العملاء تتطلب ترخيص white-label، وتبلغ تكلفته "$40 per year" وفقاً لعبارات المشروع نفسه حتى August 2026. ويُحتسب إرسال الفواتير الإلكترونية عبر شبكة Peppol بشكل منفصل. ما يمنعه الترخيص هو تشغيل البرنامج كخدمة مستضافة لأشخاص آخرين.
لماذا تصل رسائل الفواتير الإلكترونية إلى مجلد البريد العشوائي؟
يحدث ذلك في الغالب لأن الرسالة غير موثّقة للنطاق الموجود في عنوان From الخاص بها. أرسل الرسالة عبر SMTP relay بدلاً من إرسالها من VPS نفسه، ثم انشر سجلات SPF وDMARC لنطاقك، وأضف سجل DKIM ضمن selector الذي يزوّدك به relay. أبقِ عنوانك في From وضع عنوان العميل في Reply-To. يؤدي ضبط عنوان العميل باعتباره المرسل إلى رفض Gmail للرسالة مع 550 5.7.1 Unauthenticated email from example.com is not accepted due to domain's DMARC policy. أكّد إصلاح المشكلة بالعثور على dkim=pass وspf=pass في ترويسة Authentication-Results لرسالة اختبار.
أي خيار أختار إذا كنت أحاسب بالساعة؟
Kimai. فهو أداة لتتبّع الوقت أولاً، ولذلك تُنشأ الفاتورة من إدخالات timesheet المعتمدة، وتكون بنود الفاتورة هي الأعمال التي سجّلتها. القوالب عبارة عن ملفات DOCX أو ODS أو XLSX تصممها في معالج نصوص، وهذا أسهل من تعديل CSS. المقابل هو أن Kimai لا يتضمن بوابة عميل أو بوابة دفع، لذلك ترسل ملف PDF بالبريد الإلكتروني وتتلقى الدفع عبر تحويل. يتتبّع Invoice Ninja الوقت أيضاً، ويتضمن بوابة، لذا اختره بدلاً من ذلك إذا كان الدفع بالبطاقة عبر الإنترنت أهم بالنسبة إليك من تفاصيل timesheet.
ما الذي أحتاج إلى نسخه احتياطياً تحديداً؟
قاعدة البيانات، ووحدة التخزين التي تحتوي على الشعارات وملفات PDF المُنشأة، وملف البيئة، وملفات PDF المُصيّرة المحفوظة كملفات عادية. ملف البيئة هو العنصر الذي يغفل عنه الناس: تشفّر تطبيقات Laravel مثل Invoice Ninja وInvoiceShelf بيانات الاعتماد المحفوظة باستخدام APP_KEY، لذلك يؤدي استعادة قاعدة البيانات بجوار مفتاح مُنشأ حديثاً إلى جعل إعدادات بوابة الدفع غير قابلة للقراءة. استعد كل شيء في instance مؤقتة مرة واحدة، ثم افتح فاتورة قديمة، فهذه هي الطريقة الوحيدة لمعرفة أن النسخة الاحتياطية تعمل.