Get a quote

كيف تبني نظام إدارة الموردين وأوامر الشراء للمطاعم والمتاجر في لبنان والمنطقة

تعمل غالبية المطاعم والمتاجر في لبنان دون نظام منظم لإدارة الموردين. الطلبات عبر واتساب والفواتير الورقية تكفي للبداية، لكنها تتحول إلى عبء حقيقي عند التوسع. كيف تبني نظاماً يحل هذه المشكلة.

تعمل غالبية المطاعم والمتاجر في لبنان دون نظام منظم لإدارة الموردين. تُسجَّل الطلبات عبر واتساب، وتُحفظ الفواتير في ملفات ورقية، وتُعتمد الأسعار من الذاكرة لا من سجل موثق. هذا النهج كافٍ للبدء، لكنه يتحول إلى عبء حقيقي عند التوسع. نظام إدارة الموردين ليس رفاهية للمطاعم التي تعمل بشكل احترافي، بل هو أداة تشغيلية أساسية.

لماذا تحتاج المطاعم والمتاجر إلى نظام موردين منفصل؟

الإشكالية الأساسية في غياب نظام الموردين هي عدم وجود مرجعية واحدة موثوقة. يحدث دائماً أن يتفاوض المدير مع مورد على سعر، ثم يستلم المسؤول عن المشتريات الفاتورة بسعر مختلف، ولا توجد وثيقة تحسم الخلاف. أو يُطلب صنف من مورد غير مسجل فيصل دون فاتورة رسمية.

هذه ليست إخفاقات كارثية. إنها تسربات صغيرة تتراكم. على مدار عام من تشغيل مطعم متوسط الحجم في لبنان، النواقص غير المتتبعة وتغيرات الأسعار والتباينات غير الموثقة تتجمع لتشكل خسارة هامش ملموسة.

ما الذي يجب أن يفعله نظام إدارة الموردين؟

نظام إدارة موردين مناسب للمطعم أو المتجر اللبناني يحتاج أن يتعامل مع:

بيانات الموردين الرئيسية: الاسم، جهة الاتصال، جدول التسليم، شروط الدفع، فئات المنتجات. هذا وحده يُلغي مشكلة تقديم طلبات لموردين غير موثقين.

سجلات الأسعار المتعاقد عليها: السعر المتفق عليه لكل وحدة لكل منتج مع كل مورد، مع تواريخ السريان. عندما تصل فاتورة بسعر يختلف عن السعر المتعاقد عليه، يُعلم النظام للمراجعة قبل الموافقة على الدفع.

دورة حياة أمر الشراء: مسودة، مُرسَل، مُستلَم جزئياً، مُستلَم بالكامل، مُفوتَر، مدفوع. كل مرحلة تُنشئ سجلاً.

استلام البضاعة: الكميات الفعلية المستلمة مقابل المطلوبة على مستوى الصنف. تُوثَّق النواقص تلقائياً. يتحدث نظام المخزون من سجلات الاستلام لا من كميات أوامر الشراء.

نموذج بيانات إدارة أوامر الشراء

CREATE TABLE suppliers (
    id            bigserial PRIMARY KEY,
    tenant_id     bigint NOT NULL,
    name          text NOT NULL,
    contact_name  text,
    phone         text,
    payment_terms text,   -- 'cod', 'net_30', 'net_15'
    delivery_days text[], -- ['monday', 'thursday']
    active        boolean NOT NULL DEFAULT true
);

CREATE TABLE supplier_price_list (
    id             bigserial PRIMARY KEY,
    supplier_id    bigint NOT NULL REFERENCES suppliers(id),
    tenant_id      bigint NOT NULL,
    product_id     bigint NOT NULL,
    unit_price     decimal(12, 4) NOT NULL,
    unit           text NOT NULL,
    effective_from date NOT NULL,
    effective_to   date
);

CREATE TABLE purchase_orders (
    id              bigserial PRIMARY KEY,
    tenant_id       bigint NOT NULL,
    supplier_id     bigint NOT NULL REFERENCES suppliers(id),
    status          text NOT NULL DEFAULT 'draft',
    ordered_at      timestamptz,
    expected_at     date,
    received_at     timestamptz,
    total_ordered   decimal(12, 2),
    total_received  decimal(12, 2),
    notes           text
);

CREATE TABLE purchase_order_items (
    id                bigserial PRIMARY KEY,
    purchase_order_id bigint NOT NULL REFERENCES purchase_orders(id),
    product_id        bigint NOT NULL,
    ordered_qty       decimal(10, 3) NOT NULL,
    received_qty      decimal(10, 3),
    unit              text NOT NULL,
    unit_price        decimal(12, 4) NOT NULL
);

الربط مع نظام المخزون

عند تسجيل استلام بضاعة، يجب أن يُحدَّث المخزون تلقائياً:

func (s *PurchaseService) RecordReceipt(ctx context.Context, req ReceiptRequest) error {
    tx, err := s.db.BeginTx(ctx, nil)
    if err != nil {
        return err
    }
    defer tx.Rollback()

    for _, item := range req.Items {
        // تحديث كمية الاستلام الفعلية في أمر الشراء
        _, err = tx.ExecContext(ctx, `
            UPDATE purchase_order_items
            SET received_qty = $1
            WHERE id = $2 AND purchase_order_id = $3
        `, item.ReceivedQty, item.ItemID, req.PurchaseOrderID)
        if err != nil {
            return err
        }

        // إضافة للمخزون بالكمية الفعلية المستلمة
        _, err = tx.ExecContext(ctx, `
            INSERT INTO inventory_movements
              (tenant_id, product_id, location_id, type, quantity,
               reference_type, reference_id, unit_cost)
            VALUES ($1, $2, $3, 'receipt', $4, 'purchase_order', $5, $6)
        `, req.TenantID, item.ProductID, req.LocationID,
            item.ReceivedQty, req.PurchaseOrderID, item.UnitCost)
        if err != nil {
            return err
        }
    }

    _, err = tx.ExecContext(ctx, `
        UPDATE purchase_orders SET status = 'received', received_at = now()
        WHERE id = $1
    `, req.PurchaseOrderID)
    if err != nil {
        return err
    }

    return tx.Commit()
}

تقارير الموردين التي تحتاجها فعلاً

تقرير المشتريات حسب المورد: ماذا اشترينا من كل مورد هذا الشهر، وكم أنفقنا؟ هل هناك موردون يزيد اعتمادنا عليهم بشكل مفرط؟

تقرير مقارنة الأسعار: كيف تغيرت أسعار المواد الخام خلال الأشهر الستة الماضية؟ أي الموردين يقدمون أفضل سعر لكل صنف؟

تقرير المدفوعات المستحقة: ما الفواتير التي تستحق الدفع هذا الأسبوع؟ هل هناك مبالغ متأخرة تؤثر على العلاقة مع المورد؟

تقرير الفروقات: كم مرة وصلت بضاعة أقل مما طُلب من كل مورد؟ أي الموردين يحقق مستوى خدمة أعلى؟

دروس من أنظمة تشغيلية في لبنان

اجعل واجهة الاستلام بسيطة. الموظف الذي يُسجل الاستلام في المستودع ليس مبرمجاً. إذا تطلب النظام خطوات كثيرة لتسجيل استلام بضاعة، سيتجاوز الموظف النظام.

دعم اللغة العربية ضرورة لا خيار. أسماء الموردين والأصناف في لبنان غالباً ما تكون بالعربية. نظام يدعم الإدخال والعرض باللغة العربية يُعتمد أسرع ويُستخدم أكثر.

lا تبنِ النظام معقداً منذ البداية. ابدأ بالميزات الأساسية: قاعدة بيانات الموردين، أوامر الشراء، وتسجيل الاستلام. أضف التقارير المتقدمة لاحقاً بعد أن يتعود الفريق على استخدام النظام.

الخلاصة

أعلى قيمة مضافة تأتي من سجلات أسعار الموردين وتوثيق استلام البضاعة. سجلات الأسعار تمنحك مرجعاً لنزاعات الفواتير. سجلات الاستلام تُحدث المخزون من الكميات الفعلية لا الكميات النظرية لأوامر الشراء. كل شيء آخر يُبنى فوق هاتين القدرتين.

العودة إلى المدونة
Chat on WhatsApp