اذهب إلى المحتوى

السؤال

نشر

السلام عليكم جميعا ...

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

علما أن قاعدة البيانات اوراكل .

Recommended Posts

  • 0
نشر (معدل)

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

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

انظر الرابط التالي للفائدة
http://www.araboug.org/ib/index.php?showtopic=22&hl=ê‎‏يّ

 

تحياتي

تم التعديل في بواسطة مختار سيد صالح
  • 0
نشر

لا يهم ما نوع قاعدة البيانات التي تسخدمها المهم لغة البرمجة المستخدم 

ما هي لغة البرمجة المستخدمة لديك؟ 

  • 0
نشر

لا توجد في Oracle دالة جاهزة لكتابة المبالغ بالعربية. الحيلة المشهورة:

SELECT TO_CHAR(TO_DATE(28230, 'J'), 'JSP') FROM dual;

تعطي الرقم بالإنجليزية فقط (TWENTY-EIGHT THOUSAND TWO HUNDRED THIRTY)، ولا تصلح للعربية ولا للكسور.

وانتبه أولاً إلى أن الصيغة المطلوبة في السؤال نفسها تحتاج تصحيحاً: الصحيح «ثمانية وعشرون ألفاً ومئتان وثلاثون ديناراً»، لأن العدد من ١١ إلى ٩٩ يأتي بعده المعدود مفرداً منصوباً («ألفاً»، «ديناراً»). لذلك لا يكفي استبدال كل رقم بكلمة؛ الدالة تحتاج هذه القواعد:

  • واو العطف بين أجزاء العدد: «مئتان وثلاثون».
  • صيغة المعدود تتغير مع العدد: «دينار واحد»، «ديناران»، «ثلاثة دنانير»، «أحد عشر ديناراً»، «ألف وخمسة عشر ديناراً»، «مئة دينار»، «ثلاثة آلاف دينار».
  • الإضافة: إذا جاء اسم العملة بعد «ألف» أو «ألفان» مباشرة حُذف التنوين أو النون: «أحد عشر ألف دينار»، «ألفا دينار».
  • الفلوس: يتكوّن الدينار الكويتي والبحريني والأردني من ألف فلس، فالكسر بثلاث خانات: 1.250 دينار = «دينار واحد ومئتان وخمسون فلساً»، لا «خمسة وعشرون».
  • عدم الالتباس: 101,000 تُكتب «مئة ألف وألف» لا «مئة وألف» التي قد تُقرأ 1,100.

أفضل مكان للتحويل عادةً هو طبقة التطبيق أو التقرير لا قاعدة البيانات: اجلب المجموع رقماً كما هو، وحوّله إلى نص عند العرض. إن كان تطبيقك بلغة Python فهذه دالة كاملة. وهي نسخة من الدالة في إجابتي على سؤال التفقيط بالريال، معدّلة للدينار والفلس:

from decimal import Decimal, ROUND_HALF_UP

UNITS_M = ["", "", "", "ثلاثة", "أربعة", "خمسة", "ستة", "سبعة", "ثمانية", "تسعة", "عشرة"]
UNITS_F = ["", "", "", "ثلاث", "أربع", "خمس", "ست", "سبع", "ثماني", "تسع", "عشر"]
HUNDREDS_PREFIX = ["", "", "", "ثلاث", "أربع", "خمس", "ست", "سبع", "ثمان", "تسع"]
TENS = ["", "", "عشرون", "ثلاثون", "أربعون", "خمسون", "ستون", "سبعون", "ثمانون", "تسعون"]

# صيغ المعدود: (مذكر؟, صيغة الواحد, مفرد, مفرد منصوب, مثنى, مثنى مضاف, جمع, هل هو ألف/مليون/مليار؟)
ALF = (True, "ألف", "ألف", "ألفاً", "ألفان", "ألفا", "آلاف", True)
MILYON = (True, "مليون", "مليون", "مليوناً", "مليونان", "مليونا", "ملايين", True)
MILYAR = (True, "مليار", "مليار", "ملياراً", "ملياران", "مليارا", "مليارات", True)
SCALES = [MILYAR, MILYON, ALF]
DINAR = (True, "دينار واحد", "دينار", "ديناراً", "ديناران", None, "دنانير", False)
FILS = (True, "فلس واحد", "فلس", "فلساً", "فلسان", None, "فلوس", False)

def below_hundred(n, masc):
    if n == 0:
        return ""
    if n == 1:
        return "واحد" if masc else "واحدة"
    if n == 2:
        return "اثنان" if masc else "اثنتان"
    if n <= 10:
        return (UNITS_M if masc else UNITS_F)[n]  # ٣–١٠ تخالف المعدود
    if n == 11:
        return "أحد عشر" if masc else "إحدى عشرة"
    if n == 12:
        return "اثنا عشر" if masc else "اثنتا عشرة"
    if n < 20:
        return f"{UNITS_M[n - 10]} عشر" if masc else f"{UNITS_F[n - 10]} عشرة"
    t, u = divmod(n, 10)
    if u == 0:
        return TENS[t]
    unit = ("واحد" if masc else "إحدى") if u == 1 else below_hundred(u, masc)
    return f"{unit} و{TENS[t]}"


def below_thousand(n, masc, construct=False):
    h, r = divmod(n, 100)
    hw = ""
    if h == 1:
        hw = "مئة"
    elif h == 2:
        hw = "مئتا" if construct and r == 0 else "مئتان"
    elif h > 2:
        hw = HUNDREDS_PREFIX[h] + "مئة"
    return " و".join(p for p in (hw, below_hundred(r, masc)) if p)


def integer_words(n, masc, construct=False):
    groups = [n // 10**9 % 1000, n // 10**6 % 1000, n // 1000 % 1000, n % 1000]
    last = max(i for i, v in enumerate(groups) if v) if n else 3
    parts = []
    for i, v in enumerate(groups):
        if v:
            cons = construct and i == last
            parts.append(below_thousand(v, masc, cons) if i == 3 else count_noun(v, SCALES[i], cons))
    return " و".join(parts)


def count_noun(n, noun, construct=False):
    # construct=True: يلي العددَ معدودٌ آخر مباشرة (مثل «ريال» بعد «ألف»)، فيصير مضافاً بلا تنوين.
    masc, one, sing, sing_acc, dual, dual_cons, plural, is_scale = noun
    if n <= 0:
        return ""
    r = n % 100
    rest = n - r
    if r == 0:  # مئة/ألف/مليون… والمعدود مفرد مجرور: مئة ريال، ثلاثة آلاف ريال
        return f"{integer_words(rest, masc, True)} {sing}"
    if r == 1:
        tail = one
    elif r == 2:
        tail = dual_cons if construct and dual_cons else dual  # ألفا ريال
    elif r <= 10:
        tail = f"{below_hundred(r, masc)} {plural}"  # ثلاثة آلاف، خمسة ريالات
    else:  # ١١–٩٩: مفرد منصوب، إلا إذا تلاه معدود: أحد عشر ألف ريال
        tail = f"{below_hundred(r, masc)} {sing if construct else sing_acc}"
    if rest == 0:
        return tail
    if r <= 2 and is_scale:  # 101,000 → مئة ألف وألف (وليس مئة وألف التي تُقرأ 1,100)
        return f"{integer_words(rest, masc, True)} {sing} و{tail}"
    return f"{integer_words(rest, masc)} و{tail}"


def tafqit_dinar(amount, cheque=True, unit=DINAR, sub=FILS):
    raw = Decimal(str(amount))
    value = raw.quantize(Decimal("0.001"), rounding=ROUND_HALF_UP)  # الدينار ألف فلس: ثلاث خانات عشرية
    if raw < 0 or value >= 10**12:
        raise ValueError("المبلغ يجب أن يكون من 0 إلى 999,999,999,999.999")
    dinars = int(value)
    fils = int((value - dinars) * 1000)
    parts = [p for p in (count_noun(dinars, unit), count_noun(fils, sub)) if p]
    words = " و".join(parts) if parts else "صفر " + unit[2]
    return f"فقط {words} لا غير" if cheque else words

مثال:

tafqit_dinar(28230)     # فقط ثمانية وعشرون ألفاً ومئتان وثلاثون ديناراً لا غير
tafqit_dinar("1.250")   # فقط دينار واحد ومئتان وخمسون فلساً لا غير

ملاحظات:

  • إن أردت اسم الدولة («دينار كويتي»، «دينار أردني»...) فعدّل صيغ DINAR، مثلاً للكويتي: (True, "دينار كويتي واحد", "دينار كويتي", "ديناراً كويتياً", "ديناران كويتيان", None, "دنانير كويتية", False).
  • تقرّب الدالة المبلغ إلى ثلاث خانات بالتقريب المعتاد (ROUND_HALF_UP)، فإن كانت سياسة التقريب في جهتك مختلفة فغيّرها، أو مرّر المبلغ مقرّباً جاهزاً.
  • للإفصاح: قارنت نتائج هذه الدالة بنتائج مكتبة تفقيط مفتوحة المصدر أعمل عليها، على أكثر من 8000 مبلغ، فتطابقت كلها.
  • إن كان لا بد من التحويل داخل Oracle نفسه، فالقواعد أعلاه هي ما تحتاج كتابته في دالة PL/SQL، واختبرها على مبالغ مثل 11000 و2000 و101000 و1.250 قبل اعتمادها.

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...