odoo 实现单据金额大写

odoo原生是没有金额大写功能的,但实际业务有时又需要,现将 实现的方法整理如下(以“开票”中的账单为例):
注:开票对应的模型account.invoice
在这里插入图片描述
要求:在“总计”下面加上金额大写。
第一步,小写转换成大写的python代码:

# -*- coding: utf-8 -*-


from decimal import Decimal
class cnumber:
    cdict = {}
    gdict = {}
    xdict = {}

    def __init__(self):
        self.cdict = {1: u'', 2: u'拾', 3: u'佰', 4: u'仟'}
        self.xdict = {1: u'元', 2: u'万', 3: u'亿', 4: u'兆'}  # 数字标识符
        self.gdict = {0: u'零', 1: u'壹', 2: u'贰', 3: u'叁', 4: u'肆', 5: u'伍', 6: u'陆', 7: u'柒', 8: u'捌', 9: u'玖'}

    def csplit(self, cdata):  # 拆分函数,将整数字符串拆分成[亿,万,仟]的list
        g = len(cdata) % 4
        csdata = []
        lx = len(cdata) - 1
        if g > 0:
            csdata.append(cdata[0:g])
        k = g
        while k <= lx:
            csdata.append(cdata[k:k + 4])
            k += 4
        return csdata

    def cschange(self, cki):  # 对[亿,万,仟]的list中每个字符串分组进行大写化再合并
        lenki = len(cki)
        i = 0
        lk = lenki
        chk = u''
        for i in range(lenki):
            if int(cki[i]) == 0:
                if i < lenki - 1:
                    if int(cki[i + 1]) != 0:
                        chk = chk + self.gdict[int(cki[i])]
            else:
                chk = chk + self.gdict[int(cki[i])] + self.cdict[lk]
            lk -= 1
        return chk

    def cwchange(self, data):
        cdata = str(data).split('.')

        cki = cdata[0]
        ckj = cdata[1]
        i = 0
        chk = u''
        cski = self.csplit(cki)  # 分解字符数组[亿,万,仟]三组List:['0000','0000','0000']
        ikl = len(cski)  # 获取拆分后的List长度
        # 大写合并
        for i in range(ikl):
            if self.cschange(cski[i]) == '':  # 有可能一个字符串全是0的情况
                chk = chk + self.cschange(cski[i])  # 此时不需要将数字标识符引入
            else:
                chk = chk + self.cschange(cski[i]) + self.xdict[ikl - i]  # 合并:前字符串大写+当前字符串大写+标识符
        # 处理小数部分
        lenkj = len(ckj)
        if lenkj == 1:  # 若小数只有1位
            if int(ckj[0]) == 0:
                chk = chk + u''
            else:
                chk = chk + self.gdict[int(ckj[0])] + u'角'
        else:  # 若小数有两位的四种情况
            if int(ckj[0]) == 0 and int(ckj[1]) != 0:
                chk = chk + u'零' + self.gdict[int(ckj[1])] + u'分'
            elif int(ckj[0]) == 0 and int(ckj[1]) == 0:
                chk = chk + u''
            elif int(ckj[0]) != 0 and int(ckj[1]) != 0:
                chk = chk + self.gdict[int(ckj[0])] + u'角' + self.gdict[int(ckj[1])] + u'分'
            else:
                chk = chk + self.gdict[int(ckj[0])] + u'角'
        return chk

if __name__ == '__main__':
    pt = cnumber()
    print(pt.cwchange(float(input('请输入金额:'))))

经过测试(右键-run),代码无问题。
在这里插入图片描述

第二步:account.invoice模型增加一个字段:
amount_in_words = fields.Char(string=‘大写金额’, compute=‘_cwchange’, readonly=True)
增加如下代码:

def csplit(self, cdata):  # 拆分函数,将整数字符串拆分成[亿,万,仟]的list
    g = len(cdata) % 4
    csdata = []
    lx = len(cdata) - 1
    if g > 0:
        csdata.append(cdata[0:g])
    k = g
    while k <= lx:
        csdata.append(cdata[k:k + 4])
        k += 4
    return csdata

def cschange(self, cki):  # 对[亿,万,仟]的list中每个字符串分组进行大写化再合并
    lenki = len(cki)
    i = 0
    lk = lenki
    chk = u''
    for i in range(lenki):
        if int(cki[i]) == 0:
            if i < lenki - 1:
                if int(cki[i + 1]) != 0:
                    chk = chk + self.gdict[int(cki[i])]
        else:
            chk = chk + self.gdict[int(cki[i])] + self.cdict[lk]
        lk -= 1
    return chk

@api.depends('amount_total')
def _cwchange(self):
    cdict = {}
    gdict = {}
    xdict = {}
    self.cdict = {1: u'', 2: u'拾', 3: u'佰', 4: u'仟'}
    self.xdict = {1: u'元', 2: u'万', 3: u'亿', 4: u'兆'}  # 数字标识符
    self.gdict = {0: u'零', 1: u'壹', 2: u'贰', 3: u'叁', 4: u'肆', 5: u'伍', 6: u'陆', 7: u'柒', 8: u'捌', 9: u'玖'}
    cdata = str(self.amount_total).split('.')

    cki = cdata[0]
    ckj = cdata[1]
    i = 0
    chk = u''
    cski = self.csplit(cki)  # 分解字符数组[亿,万,仟]三组List:['0000','0000','0000']
    ikl = len(cski)  # 获取拆分后的List长度
    # 大写合并
    for i in range(ikl):
        if self.cschange(cski[i]) == '':  # 有可能一个字符串全是0的情况
            chk = chk + self.cschange(cski[i])  # 此时不需要将数字标识符引入
        else:
            chk = chk + self.cschange(cski[i]) + self.xdict[ikl - i]  # 合并:前字符串大写+当前字符串大写+标识符
    # 处理小数部分
    lenkj = len(ckj)
    if lenkj == 1:  # 若小数只有1位
        if int(ckj[0]) == 0:
            chk = chk + u''
        else:
            chk = chk + self.gdict[int(ckj[0])] + u'角'
    else:  # 若小数有两位的四种情况
        if int(ckj[0]) == 0 and int(ckj[1]) != 0:
            chk = chk + u'零' + self.gdict[int(ckj[1])] + u'分'
        elif int(ckj[0]) == 0 and int(ckj[1]) == 0:
            chk = chk + u''
        elif int(ckj[0]) != 0 and int(ckj[1]) != 0:
            chk = chk + self.gdict[int(ckj[0])] + u'角' + self.gdict[int(ckj[1])] + u'分'
        else:
            chk = chk + self.gdict[int(ckj[0])] + u'角'
    self.amount_in_words = chk

xml文件增加代码:

<record id="invoice_supplier_form_inherit1" model="ir.ui.view">
    <field name="name">account.invoice.supplier.form.inherit1</field>
    <field name="model">account.invoice</field>
    <field name="inherit_id" ref="account.invoice_supplier_form"/>
    <field name="arch" type="xml">
        <field name="outstanding_credits_debits_widget" position="after">
            <field name="amount_in_words" style="width:250px" readonly="1"></field>
       </field>
    </field>
</record>

最终实现效果:
在这里插入图片描述
打印单上增加大写金额:

   <template id="report_invoice_document_with_payments1" inherit_id="account.report_invoice_document" >
       <xpath expr="//div[@id='total']/div/table" position="after">
                     <div class="col-auto mw-100 mb-2" t-if="o.amount_in_words" name="人民币大写">
                        <strong>人民币大写:</strong>
                        <p class="m-0" t-field="o.amount_in_words"/>
                    </div>
       </xpath>
    </template>

效果:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值