近日接到財務(wù)需求秉氧,要從銷售訂單增加部門眷昆,并將部門與原始的合約帶入到會計憑證以便進行財務(wù)分析。
首先厘清需求:
- SO新增部門欄位
- 會計憑證增加部門及合約欄位
- 出貨單驗證后會產(chǎn)生憑證
- 開立發(fā)票后產(chǎn)生憑證
開發(fā)步驟:
- 在sale_order先增加department_id(Odoo本身就已經(jīng)在SO上面存在project_id了)
- 在stock.picking增加department_id和project_id汁咏,以便于產(chǎn)生會計憑證時可以取得欄位
- 在account_move增加department_id和project_id
代碼追蹤及功能實現(xiàn):
- Odoo在確認訂單的時候會產(chǎn)生Picking亚斋,所以追蹤到此按鈕的對應(yīng)method: action_button_confirm
- 此方法啟動了order_confirm的workflow signal
self.signal_workflow(cr, uid, ids, 'order_confirm')
- 進入workflow的編輯頁面,沿著流程找下去攘滩,下一步到了route伞访,此階段執(zhí)行了action_wait(),但此方法中沒有產(chǎn)生picking相關(guān)的部分
- 此時流程尚未結(jié)束轰驳,繼續(xù)沿著流程找到了wait_ship節(jié)點厚掷,此節(jié)點未執(zhí)行動作
- 繼續(xù)沿著節(jié)點找下去,到了ship節(jié)點级解,此節(jié)點執(zhí)行了action_ship_create()冒黑,但此方法僅產(chǎn)生了procurement,然后執(zhí)行了procurement中run的動作勤哗,追蹤的動作到這里卡住了抡爹,因為沒有任何關(guān)于產(chǎn)生picking的代碼判斷,雖然憑經(jīng)驗知道picking應(yīng)該是在run procurement的時候產(chǎn)生芒划。不過我們不需要繼續(xù)看下去就可以切入了冬竟,我們知道SO和Picking是通過procurement_group_id來關(guān)聯(lián)欧穴,因此可以繼承此方法,用procurement來找到SO對應(yīng)的picking泵殴,并更新我們剛剛新增的department_id及project_id兩個欄位
def action_ship_create(self):
res = super(BelstarSaleOrderExtend, self).action_ship_create()
picking = self.env['stock.picking'].search([('group_id', '=', self.procurement_group_id.id)])
picking.write({'department_id': self.department_id.id, 'project_id': self.project_id.id})
return res
- 在驗證出貨單的時候又遇到了問題涮帘,追蹤頁面驗收功能,從do_detailed_transfer到do_transfer的執(zhí)行流程中都沒有找到產(chǎn)生會計憑證的相關(guān)代碼笑诅,于是調(diào)整追蹤代碼的方向调缨,我們知道warehouse的模塊名稱是stock,那么就去stock模塊里面查找會計憑證相關(guān)的模塊account.move吆你,但查詢結(jié)果顯示stock模塊里面沒有出現(xiàn)account.move的任何內(nèi)容弦叶。但跟stock相關(guān)的模塊還有stock_account,根據(jù)模塊名可判斷出此模塊為warehouse中對account的擴展妇多,在此模塊中繼續(xù)搜尋account.move伤哺,bingo! 找到目標出現(xiàn)在_create_account_move_line方法中,原來是在stock.quants的model下面者祖,通過查看此段代碼知道最終寫入的資料來自于另一個輔助方法_prepare_account_move_line
move_lines = self._prepare_account_move_line(cr, uid, move, qty, cost, credit_account_id, debit_account_id, context=context)
- 至此終于找到了最關(guān)鍵的代碼片段
debit_line_vals = {
'name': move.name,
'product_id': move.product_id.id,
'quantity': qty,
'product_uom_id': move.product_id.uom_id.id,
'ref': move.picking_id and move.picking_id.name or False,
'date': fields.date.context_today(self, cr, uid, context=context),
'partner_id': partner_id,
'debit': valuation_amount > 0 and valuation_amount or 0,
'credit': valuation_amount < 0 and -valuation_amount or 0,
'account_id': debit_account_id,
}
credit_line_vals = {
'name': move.name,
'product_id': move.product_id.id,
'quantity': qty,
'product_uom_id': move.product_id.uom_id.id,
'ref': move.picking_id and move.picking_id.name or False,
'date': fields.date.context_today(self, cr, uid, context=context),
'partner_id': partner_id,
'credit': valuation_amount > 0 and valuation_amount or 0,
'debit': valuation_amount < 0 and -valuation_amount or 0,
'account_id': credit_account_id,
}
- 找到了需要修改的代碼片段立莉,就可以著手修改了,這邊還有2個小問題咸包,stock_account里面stock.quants是繼承stock模塊的桃序,我們也要繼承相同的代碼并覆蓋掉stock_account里面的代碼,因此需要確認odoo載入順序烂瘫,另一個問題是官方模塊是old api的代碼格式需要用old api的方式來繼承媒熊,比較不會有new api轉(zhuǎn)換上的問題。繼承順序的部分經(jīng)過google查詢之后坟比,只要在模塊聲明文件中depends stock_account就可以確保當前模塊在stock_account加載之后才加載芦鳍,以確保加載的順序。
- 資訊從SO帶到出貨單再帶到會計憑證的部分沒有問題之后葛账,要開始看如何在發(fā)票驗證的時候把project_id和department_id帶入會計憑證的部分
- 通過Odoo銷售訂單產(chǎn)生發(fā)票柠衅,當點了創(chuàng)建發(fā)票按鈕后我們會看到有幾種開票方式:整單建立發(fā)票,百分比建立發(fā)票籍琳,固定金額建立發(fā)票以及訂單行建立發(fā)票菲宴,通過開立發(fā)票按鈕的方法create_invoices我們追蹤到代碼,可以看到如果為整單建立發(fā)票趋急,Odoo會調(diào)用sale.order下面的方法manual_invoice喝峦,此發(fā)票又去觸發(fā)了workflow中的manual_invoice,此時節(jié)點會跑到invoice節(jié)點并觸發(fā)方法action_invoice_create()呜达,回過頭檢查sale_order里面的此方法找到發(fā)票建立是在其中調(diào)用_make_invoice方法谣蠢,而此方法中的發(fā)票數(shù)據(jù)處理是調(diào)用了_prepare_invoice,至此找到了整單建立發(fā)票的關(guān)鍵代碼片段
- 如果是固定金額或百分比方式,回頭看create_invoices方法中眉踱,如果為固定金額或百分比挤忙,可以看到方法中會調(diào)用_prepare_advance_invoice_vals來準備發(fā)票的數(shù)據(jù),所以我們也找到了固定金額或百分比中建立發(fā)票的關(guān)鍵代碼片段
- 如果是以發(fā)票明細行的方式開發(fā)票谈喳,系統(tǒng)會先導入到選擇發(fā)票明細行的頁面册烈,選擇之后按下開立發(fā)票按鈕,會觸發(fā)方法make_invoices叁执,實際追蹤發(fā)現(xiàn)此方法生效為sale_line_invoice.py中的同方法名茄厘,此方法中有一個子方法make_invoice矮冬,會調(diào)用_prepare_invoice準備數(shù)據(jù)谈宛,至此全部發(fā)票開立方式的關(guān)鍵代碼片段都已經(jīng)找到
- 在開發(fā)發(fā)票的數(shù)據(jù)中寫入project_id及department_id之后,就可以從驗證發(fā)票并產(chǎn)生會計憑證這邊下手了胎署,先去跟蹤驗證發(fā)票按鈕吆录,進入Edit Form可以查看到驗證按鈕為workflow中invoice_open的觸發(fā)點,再進入發(fā)票的workflow查看節(jié)點會進入到open中琼牧,此節(jié)點共計執(zhí)行了4個方法action_date_assign() action_move_create() action_number() invoice_validate()恢筝,直接透過字面含義可知我們要修改的代碼存在于action_move_create中
- 進入action_move_create中,分析了一下代碼發(fā)現(xiàn)我們修改的最終代碼片段就是在這個方法中巨坊,我們需要在account_move及account.move.line中增加project_id及department_id撬槽,于是我們繼承這個方法并進行修改
line = inv.finalize_invoice_move_lines(line)
for el in line:
el[2].update({'analytic_account_3': inv.department_id and inv.department_id.id or False,
'analytic_account': inv.project_id and inv.project_id.id or False
})
move_vals = {
'ref': inv.reference or inv.name,
'line_id': line,
'journal_id': journal.id,
'date': inv.date_invoice,
'narration': inv.comment,
'company_id': inv.company_id.id,
'analytic_account': inv.project_id and inv.project_id.id or False,
'analytic_account_3': inv.department_id and inv.department_id.id or False,
}
總結(jié):
- Odoo8同時存在的old api及new api對開發(fā)造成相當?shù)睦_,一個Model有時要開兩個文件來繼承修改以區(qū)分api/old api
- workflow在后續(xù)版本拿掉真的是必然趾撵,在debug的時候要從程式代碼和workflow切來切去很不方便侄柔,并且對版本管控來說workflow也不是良好的實現(xiàn)方式
- 當原生模塊就已經(jīng)繼承的時候,要找到關(guān)鍵的代碼片段也不是一件容易的事情