|
After Width: | Height: | Size: 140 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 69 KiB |
After Width: | Height: | Size: 88 KiB |
After Width: | Height: | Size: 222 KiB |
Before Width: | Height: | Size: 767 KiB |
After Width: | Height: | Size: 90 KiB |
@ -0,0 +1,129 @@ |
|||||
|
/** @odoo-module **/ |
||||
|
import { registry } from "@web/core/registry"; |
||||
|
import { useService } from "@web/core/utils/hooks"; |
||||
|
import { View } from "@web/views/view"; |
||||
|
import { kanbanView } from "@web/views/kanban/kanban_view"; |
||||
|
import { KanbanController } from "@web/views/kanban/kanban_controller"; |
||||
|
import { KanbanRenderer } from "@web/views/kanban/kanban_renderer"; |
||||
|
import { KanbanRecord } from "@web/views/kanban/kanban_record"; |
||||
|
const { useState } = owl; |
||||
|
|
||||
|
class CustomKanbanController extends KanbanController { |
||||
|
async setup(){ |
||||
|
super.setup() |
||||
|
this.state = useState({ |
||||
|
selectedStLineId: null, |
||||
|
linesWidgetData: null, |
||||
|
moveLineData: null, |
||||
|
}); |
||||
|
this.action = useService("action") |
||||
|
this.orm = useService("orm") |
||||
|
const o_bank_reconcile_status_buttons_aside_left = document.getElementsByClassName("o_bank_reconcile_status_buttons_aside_left") |
||||
|
} |
||||
|
|
||||
|
async openRecord(record, mode) { |
||||
|
this.state.moveLineData = null; |
||||
|
this.state.viewID = await this.orm.call('res.config.settings', 'get_view_id', []) |
||||
|
await this.mountStLine(record.resId); |
||||
|
|
||||
|
const statementRecord = document.querySelectorAll('.o_bank_reconcile_st_line_kanban_card'); |
||||
|
statementRecord.forEach(line => { |
||||
|
line.addEventListener('click', async (event) => { |
||||
|
// Remove 'div-added' class and its child divs from all elements
|
||||
|
statementRecord.forEach(item => { |
||||
|
item.classList.remove('div-added'); |
||||
|
const childDiv = item.querySelector('.new-div'); |
||||
|
if (childDiv) { |
||||
|
item.removeChild(childDiv); |
||||
|
} |
||||
|
}); |
||||
|
// Add 'div-added' class and new div to the clicked record
|
||||
|
if (!line.classList.contains('div-added')) { |
||||
|
const newDiv = document.createElement('div'); |
||||
|
newDiv.classList.add('new-div'); // Add a class to identify the new div
|
||||
|
line.classList.add('div-added'); |
||||
|
line.appendChild(newDiv); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
async mountStLine(stLineId){ |
||||
|
const currentStLineId = this.state.selectedStLineId; |
||||
|
if (currentStLineId !== stLineId) { |
||||
|
this.state.selectedStLineId = stLineId; // Update selected ST Line ID
|
||||
|
try { |
||||
|
const data = await this.orm.call("account.bank.statement.line", "get_statement_line", [stLineId]); |
||||
|
this.state.linesWidgetData = data; |
||||
|
} catch (error) { |
||||
|
console.error("Error fetching statement line data:", error); |
||||
|
} |
||||
|
try { |
||||
|
const data = await this.orm.call('account.bank.statement.line', 'read', [[stLineId]], { fields: ['lines_widget_json'] }); |
||||
|
if (data && data.length > 0 && data[0].lines_widget_json) { |
||||
|
const parsedData = JSON.parse(data[0].lines_widget_json); |
||||
|
const moveIdMatch = parsedData.move_id.match(/\((\d+),\)/); |
||||
|
parsedData.numeric_move_id = moveIdMatch ? parseInt(moveIdMatch[1]) : null; |
||||
|
this.state.moveLineData = parsedData; |
||||
|
} else { |
||||
|
console.warn("No lines_widget_json found for selected statement line."); |
||||
|
} |
||||
|
} catch (error) { |
||||
|
console.error("Error reading statement line:", error); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
get prepareFormPropsBankReconcile(){ |
||||
|
if (!this.state.selectedStLineId) { |
||||
|
return null; // or some default props
|
||||
|
} |
||||
|
return { |
||||
|
type: "form", |
||||
|
viewId: this.state.viewID, |
||||
|
context: { |
||||
|
default_st_line_id: this.state.selectedStLineId, |
||||
|
default_lines_widget: this.state.linesWidgetData || null, |
||||
|
default_move_line: this.state.moveLineData || null, |
||||
|
}, |
||||
|
display: { controlPanel: false, noBreadcrumbs: true}, |
||||
|
mode: "edit", |
||||
|
resModel: "account.bank.statement.line", |
||||
|
resId: this.state.selectedStLineId, |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
CustomKanbanController.components = { |
||||
|
...CustomKanbanController.components, View } |
||||
|
CustomKanbanController.template = "base_accounting_kit.CustomKanbanView"; |
||||
|
|
||||
|
export class BankCustomKanbanRenderer extends KanbanRenderer { |
||||
|
setup(){ |
||||
|
super.setup(); |
||||
|
} |
||||
|
} |
||||
|
export class BankReconcileKanbanRecord extends KanbanRecord { |
||||
|
setup(){ |
||||
|
super.setup(); |
||||
|
this.state=useState({ |
||||
|
Statement_record:{} |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
BankReconcileKanbanRecord.template = "base_accounting_kit.BankReconcileKanbanRecord"; |
||||
|
|
||||
|
BankCustomKanbanRenderer.components = { |
||||
|
...KanbanRenderer.components, |
||||
|
KanbanRecord: BankReconcileKanbanRecord, |
||||
|
} |
||||
|
BankCustomKanbanRenderer.template = "base_accounting_kit.BankRecKanbanRenderer"; |
||||
|
|
||||
|
export const customKanbanView = { |
||||
|
...kanbanView, |
||||
|
Controller: CustomKanbanController, |
||||
|
Renderer: BankCustomKanbanRenderer, |
||||
|
searchMenuTypes: ["filter"], |
||||
|
}; |
||||
|
|
||||
|
// Register it to the views registry
|
||||
|
registry.category("views").add("custom_kanban", customKanbanView); |
@ -0,0 +1,168 @@ |
|||||
|
/** @odoo-module **/ |
||||
|
import { registry } from '@web/core/registry'; |
||||
|
import { ListController } from "@web/views/list/list_controller"; |
||||
|
import { listView } from "@web/views/list/list_view"; |
||||
|
import { useState, useRef } from "@odoo/owl"; |
||||
|
import { useListener, useService} from "@web/core/utils/hooks"; |
||||
|
export class AccountMoveLineListController extends ListController { |
||||
|
constructor() { |
||||
|
super(...arguments); |
||||
|
this.resIdList = []; |
||||
|
} |
||||
|
setup(){ |
||||
|
super.setup(); |
||||
|
this.state = useState({ selectedRecordId: null , |
||||
|
selectedRecordIds: [],}); |
||||
|
this.action = useService("action") |
||||
|
this.orm = useService("orm") |
||||
|
} |
||||
|
async openRecord(record) { |
||||
|
const kanban_row = this.__owl__.bdom.parentEl.ownerDocument.querySelector(`tr[data-id]`); |
||||
|
const data_id = parseInt(kanban_row.getAttribute('data-id')) |
||||
|
var data = await this.orm.call('account.bank.statement.line', |
||||
|
'update_match_row_data', |
||||
|
[record.resId]) |
||||
|
await this.orm.call('account.bank.statement.line', 'write', [[data_id], { lines_widget_json: JSON.stringify(data) }]); |
||||
|
const rowSelector = this.__owl__.bdom.parentEl.querySelector(`tr[data-id='${record.id}']`) |
||||
|
if (!record.clickCount) { |
||||
|
record.clickCount = true |
||||
|
rowSelector.style.backgroundColor = "#d1ecf1"; |
||||
|
} else { |
||||
|
// Set the default background color here
|
||||
|
record.clickCount = false; |
||||
|
rowSelector.style.backgroundColor = "white"; |
||||
|
} |
||||
|
|
||||
|
const currencySymbol = await this.orm.call('res.currency', 'read',[record.data.currency_id[0]]) |
||||
|
const mainKanbanDiv = this.__owl__.bdom.parentEl.ownerDocument.querySelector('#base_accounting_reconcile') |
||||
|
const existingRow = this.__owl__.bdom.parentEl.ownerDocument.querySelector(`tr[data-resId="${record.resId}"]`) |
||||
|
const stateLineRow = this.__owl__.bdom.parentEl.ownerDocument.querySelector('.statement_row') |
||||
|
if (stateLineRow){ |
||||
|
const dataIdValue = stateLineRow.getAttribute('data-id'); |
||||
|
if(dataIdValue == record.resId){ |
||||
|
mainKanbanDiv.removeChild(stateLineRow); |
||||
|
} |
||||
|
} |
||||
|
if (existingRow) { |
||||
|
mainKanbanDiv.removeChild(existingRow); |
||||
|
} else { |
||||
|
// If the row doesn't exist, create and add it
|
||||
|
const dateObject = new Date(record.data.date); |
||||
|
const year = dateObject.getFullYear(); |
||||
|
const month = String(dateObject.getMonth() + 1).padStart(2, '0'); // Months are 0-indexed
|
||||
|
const day = String(dateObject.getDate()).padStart(2, '0'); |
||||
|
const formattedDate = `${year}-${month}-${day}`; |
||||
|
let amount = parseFloat(record.data.amount_residual); |
||||
|
let debitColumn = ''; |
||||
|
let creditColumn = ''; |
||||
|
let partnerName = ''; |
||||
|
let moveId = ''; |
||||
|
|
||||
|
// Check if partner_id exists and is not empty
|
||||
|
if (record.data.partner_id && record.data.partner_id[1]) { |
||||
|
partnerName = record.data.partner_id[1]; |
||||
|
} |
||||
|
if (record.data.move_id && record.data.move_id[1]) { |
||||
|
moveId = `<br/><span id="moveLine" style="font-size: 12px; font-style: italic;font-weight: normal;color: #01666b;cursor: pointer;" data-moveId="${record.data.move_id[0]}">${record.data.move_id[1]}</span>`; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
if (amount < 0) { |
||||
|
debitColumn = `<td style="font-weight: bold; display: table-cell; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: top;">${currencySymbol[0].symbol} ${-amount}</td>`; |
||||
|
} else { |
||||
|
creditColumn = `<td style="font-weight: bold; display: table-cell; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: top;">${currencySymbol[0].symbol} ${amount}</td>`; |
||||
|
} |
||||
|
|
||||
|
const newRow = document.createElement('tr'); |
||||
|
newRow.setAttribute('data-resId', record.resId); // Set a unique identifier for the row
|
||||
|
if (debitColumn !== '') { |
||||
|
newRow.innerHTML = `<td style="font-weight: bold; display: table-cell; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: top;">${record.data.account_id[1]} |
||||
|
${moveId}<span style="font-size: 12px;font-style: italic;font-weight: normal;"> : ${record.data.name}</span></td> |
||||
|
<td style="font-weight: bold; display: table-cell; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: top;">${partnerName}</td> |
||||
|
<td style="font-weight: bold; display: table-cell; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: top;">${formattedDate}</td> |
||||
|
${debitColumn} |
||||
|
<td style="font-weight: bold; display: table-cell; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: top;"> </td> |
||||
|
<td class="o_list_remove_record"> |
||||
|
<button class="btn fa fa-trash-o" data-resId="${record.resId}"/> |
||||
|
</td>`; |
||||
|
|
||||
|
} else if (creditColumn !== '') { |
||||
|
newRow.innerHTML = `<td style="font-weight: bold; display: table-cell; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: top;">${record.data.account_id[1]} |
||||
|
${moveId}<span style="font-size: 12px;font-style: italic;font-weight: normal;"> : ${record.data.name}</span></td> |
||||
|
<td style="font-weight: bold; display: table-cell; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: top;">${partnerName}</td> |
||||
|
<td style="font-weight: bold; display: table-cell; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: top;">${formattedDate}</td> |
||||
|
<td style="font-weight: bold; display: table-cell; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: top;"> </td> |
||||
|
${creditColumn} |
||||
|
<td class="o_list_remove_record"> |
||||
|
<button class="btn fa fa-trash-o" data-resId="${record.resId}"/> |
||||
|
</td>`; |
||||
|
} |
||||
|
newRow.addEventListener('click', async () => { |
||||
|
const allRows = this.__owl__.bdom.parentEl.ownerDocument.querySelectorAll('tr[data-resId]'); |
||||
|
allRows.forEach(row => { |
||||
|
row.classList.remove('selected-row'); |
||||
|
}); |
||||
|
newRow.classList.add('selected-row'); |
||||
|
if (record.resId){ |
||||
|
const manualOpsTab = this.__owl__.bdom.parentEl.ownerDocument.querySelector('[name="manual_operations_tab"]'); |
||||
|
if (manualOpsTab) { |
||||
|
manualOpsTab.click(); |
||||
|
const accountField = this.__owl__.bdom.parentEl.ownerDocument.querySelector('[name="account_id"]'); |
||||
|
accountField.value = record.data.account_id[1]; |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
// Append the new row to the mainKanbanDiv
|
||||
|
mainKanbanDiv.appendChild(newRow); |
||||
|
const deleteButtons = this.__owl__.bdom.parentEl.ownerDocument.querySelectorAll('.fa-trash-o'); |
||||
|
deleteButtons.forEach(button => { |
||||
|
button.addEventListener('click', async (event) => { |
||||
|
const resId = event.target.getAttribute('data-resId'); |
||||
|
await this.removeRecord(resId); |
||||
|
}); |
||||
|
}); |
||||
|
const moveLine = this.__owl__.bdom.parentEl.ownerDocument.querySelectorAll('#moveLine'); |
||||
|
moveLine.forEach(line => { |
||||
|
line.addEventListener('click',async (event) => { |
||||
|
const moveId = event.target.getAttribute('data-moveId'); |
||||
|
await this.ShowMoveForm(moveId); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
this.updateResIdList(); |
||||
|
} |
||||
|
async removeRecord(resId){ |
||||
|
const mainKanbanDiv = this.__owl__.bdom.parentEl.ownerDocument.querySelector('#base_accounting_reconcile'); |
||||
|
const rowToRemove = this.__owl__.bdom.parentEl.ownerDocument.querySelector(`tr[data-resId="${resId}"]`); |
||||
|
if (rowToRemove) { |
||||
|
mainKanbanDiv.removeChild(rowToRemove); |
||||
|
this.updateResIdList(); |
||||
|
} |
||||
|
} |
||||
|
async ShowMoveForm(moveId) { |
||||
|
// Convert moveId from string to integer
|
||||
|
const moveIdInt = parseInt(moveId, 10); |
||||
|
// Check if the conversion is successful
|
||||
|
if (!isNaN(moveIdInt)) { |
||||
|
this.action.doAction({ |
||||
|
type: 'ir.actions.act_window', |
||||
|
res_model: 'account.move', |
||||
|
res_id: moveIdInt, |
||||
|
views: [[false, "form"]], |
||||
|
target: 'current', |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
updateResIdList() { |
||||
|
// Get all resId values from the current rows and update the resIdList array
|
||||
|
const rows = this.__owl__.bdom.parentEl.ownerDocument.querySelectorAll('tr[data-resId]'); |
||||
|
this.resIdList = Array.from(rows).map(row => parseInt(row.getAttribute('data-resId'), 10)); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
AccountMoveLineListController.template = 'base_accounting_kit.AccountMoveLineListController'; |
||||
|
export const AccountMoveListView = { |
||||
|
...listView, |
||||
|
Controller: AccountMoveLineListController, |
||||
|
}; |
||||
|
registry.category('views').add('account_move_line_list_controller', AccountMoveListView); |
@ -0,0 +1,79 @@ |
|||||
|
/** @odoo-module **/ |
||||
|
import { registry } from '@web/core/registry'; |
||||
|
import { useService } from "@web/core/utils/hooks"; |
||||
|
import { _t } from "@web/core/l10n/translation"; |
||||
|
const { Component, useState, useExternalListener } = owl; |
||||
|
export class BankReconcileFormLinesWidget extends Component { |
||||
|
setup(){ |
||||
|
super.setup(); |
||||
|
this.state = useState({statementLineResult: null, |
||||
|
MoveLineResult:null}); |
||||
|
this.action = useService("action") |
||||
|
this.orm = useService("orm") |
||||
|
} |
||||
|
range(n){ |
||||
|
return[...Array(Math.max(n,0)).keys()]; |
||||
|
} |
||||
|
get record(){ |
||||
|
return this.props.record; |
||||
|
} |
||||
|
async mountStatementLine(ev){ |
||||
|
const manualOpsTab = document.querySelector('[name="manual_operations_tab"]'); |
||||
|
if (manualOpsTab) { |
||||
|
manualOpsTab.click(); |
||||
|
} |
||||
|
} |
||||
|
async onclickLink(ev){ |
||||
|
const id = ev.currentTarget.dataset.id; |
||||
|
if (id) { |
||||
|
this.action.doAction({ |
||||
|
type: 'ir.actions.act_window', |
||||
|
res_model: 'account.move', |
||||
|
res_id: parseInt(id), |
||||
|
views: [[false, "form"]], |
||||
|
target: 'current', |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
async removeRecord(ev){ |
||||
|
ev.preventDefault(); |
||||
|
var button = ev.currentTarget; |
||||
|
var row = button.closest('tr'); |
||||
|
var firstRow = document.querySelector('.o_data_row:first-child'); |
||||
|
var data_id = firstRow.dataset.id; |
||||
|
try { |
||||
|
await this.orm.call('account.bank.statement.line', 'write', [[parseInt(data_id)], {'lines_widget_json': null}]); |
||||
|
// Update the UI or perform any other actions as needed
|
||||
|
} catch (error) { |
||||
|
console.error('Error removing lines_widget_json:', error); |
||||
|
// Handle the error as needed
|
||||
|
} |
||||
|
row.remove(); |
||||
|
} |
||||
|
getRenderValues(){ |
||||
|
var self=this; |
||||
|
let data = this.props.record.context |
||||
|
this.orm.call('account.bank.statement.line', 'update_rowdata', [this.props.record.data.id]) |
||||
|
let columns=[ |
||||
|
["account",_t("Account")], |
||||
|
["partner",_t("Partner")], |
||||
|
["date",_t("Date")], |
||||
|
]; |
||||
|
if(data.display_analytic_account_column){ |
||||
|
columns.push(["analytic_account", _t("Analytic Account")]); |
||||
|
} |
||||
|
if(data.display_multi_currency_column){ |
||||
|
columns.push(["amount_currency", _t("Amount in Currency")], ["currency", _t("Currency")]); |
||||
|
} |
||||
|
if(data.display_taxes_column){ |
||||
|
columns.push(["taxes", _t("Taxes")]); |
||||
|
} |
||||
|
columns.push(["debit", _t("Debit")], ["credit", _t("Credit")], ["__trash", ""]); |
||||
|
return {...data,columns:columns} |
||||
|
} |
||||
|
} |
||||
|
BankReconcileFormLinesWidget.template = 'base_accounting_kit.bank_reconcile_widget_lines_widget'; |
||||
|
export const FormLines = { |
||||
|
component: BankReconcileFormLinesWidget |
||||
|
} |
||||
|
registry.category("fields").add('bank_reconcile_widget_lines_widget', FormLines) |
@ -0,0 +1,124 @@ |
|||||
|
/** @odoo-module **/ |
||||
|
import { registry } from '@web/core/registry'; |
||||
|
import { standardWidgetProps } from "@web/views/widgets/standard_widget_props"; |
||||
|
import { View } from "@web/views/view"; |
||||
|
const { Component, useSubEnv } = owl; |
||||
|
|
||||
|
class FormListView extends Component { |
||||
|
setup(){ |
||||
|
useSubEnv({ |
||||
|
config:{}, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
get bankReconcileListViewProps(){ |
||||
|
return{ |
||||
|
type:'list', |
||||
|
display:{ |
||||
|
controlPanel:{ |
||||
|
"top-left":false, |
||||
|
"bottom-left":false, |
||||
|
} |
||||
|
}, |
||||
|
resModel:this.props.resModel, |
||||
|
searchMenuTypes:["filter"], |
||||
|
allowSelectors:false, |
||||
|
searchViewId:false, |
||||
|
searchViewArch: ` |
||||
|
<search> |
||||
|
<field name="name" string="Journal Item"/> |
||||
|
<field name="journal_id"/> |
||||
|
<field name="account_id"/> |
||||
|
<field name="partner_id"/> |
||||
|
<field name="move_id"/> |
||||
|
<field name="currency_id" groups="base.group_multi_currency"/> |
||||
|
<field name="date" string="Date"/> |
||||
|
<separator/> |
||||
|
<filter name="amount_received" string="Incoming" domain="[('balance','>',0.0)]"/> |
||||
|
<filter name="amount_paid" string="Outgoing" domain="[('balance','<',0.0)]"/> |
||||
|
<separator name="inject_after"/> |
||||
|
<filter name="date" string="Date" date="date"/> |
||||
|
<filter string="Customer/Vendor" name="partner_id" domain="[]"/> |
||||
|
<filter string="Miscellaneous" domain="[('journal_id.type', '=', 'general')]" name="misc_filter"/> |
||||
|
</search> |
||||
|
`,
|
||||
|
searchViewFields: { |
||||
|
name: { |
||||
|
name:"name", |
||||
|
string:"Journal Item", |
||||
|
type:"char", |
||||
|
store: true, |
||||
|
sortable: true, |
||||
|
searchable: true, |
||||
|
}, |
||||
|
date: { |
||||
|
name: "date", |
||||
|
string: "Date", |
||||
|
type: "date", |
||||
|
store: true, |
||||
|
sortable: true, |
||||
|
searchable: true, |
||||
|
}, |
||||
|
journal_id: { |
||||
|
name: "journal_id", |
||||
|
string: "Journal", |
||||
|
type: "many2one", |
||||
|
store: true, |
||||
|
sortable: true, |
||||
|
searchable: true, |
||||
|
}, |
||||
|
account_id: { |
||||
|
name: "account_id", |
||||
|
string: "Account", |
||||
|
type: "many2one", |
||||
|
store: true, |
||||
|
sortable: true, |
||||
|
searchable: true, |
||||
|
}, |
||||
|
partner_id: { |
||||
|
name: "partner_id", |
||||
|
string: "Partner", |
||||
|
type: "many2one", |
||||
|
store: true, |
||||
|
sortable: true, |
||||
|
searchable: true, |
||||
|
group_by:"partner_id", |
||||
|
}, |
||||
|
currency_id: { |
||||
|
name: "currency_id", |
||||
|
string: "Currency", |
||||
|
type: "many2one", |
||||
|
store: true, |
||||
|
sortable: true, |
||||
|
searchable: true, |
||||
|
}, |
||||
|
move_id: { |
||||
|
name:"move_id", |
||||
|
string:"Journal Entry", |
||||
|
type:"many2one", |
||||
|
store:true, |
||||
|
sortable:true, |
||||
|
searchable:true, |
||||
|
filter_domain:"['|',('move_id.name','ilike',self),('move_id.ref','ilike',self)]", |
||||
|
}, |
||||
|
}, |
||||
|
context:{ |
||||
|
list_view_ref:"base_accounting_kit.account_move_line_view_tree", |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
FormListView.template = "base_accounting_kit.FormListView"; |
||||
|
FormListView.components = { View }; |
||||
|
FormListView.props = { |
||||
|
...standardWidgetProps, |
||||
|
resModel: { type: String }, |
||||
|
}; |
||||
|
export const formListView = { |
||||
|
component: FormListView, |
||||
|
extractProps: ({ attrs }) => ({ |
||||
|
resModel: attrs.resModel, |
||||
|
}), |
||||
|
}; |
||||
|
registry.category("view_widgets").add("form_list_view", formListView); |
@ -0,0 +1,33 @@ |
|||||
|
<templates> |
||||
|
<t t-name="base_accounting_kit.CustomKanbanView" t-inherit="web.KanbanView" |
||||
|
owl="1"> |
||||
|
<xpath expr="//Layout" position="inside"> |
||||
|
<div class="h-100 form_view_class"> |
||||
|
<View t-if="state.selectedStLineId" |
||||
|
t-props="prepareFormPropsBankReconcile" |
||||
|
t-key="state.selectedStLineId"/> |
||||
|
</div> |
||||
|
</xpath> |
||||
|
</t> |
||||
|
<t t-name="base_accounting_kit.BankRecKanbanRenderer" |
||||
|
t-inherit="web.KanbanRenderer" t-inherit-mode="primary" owl="1"> |
||||
|
<xpath expr="//div[hasclass('o_kanban_renderer')]" |
||||
|
position="before"> |
||||
|
</xpath> |
||||
|
<xpath expr="//div[hasclass('o_kanban_renderer')]" |
||||
|
position="attributes"> |
||||
|
<attribute name="class">o_kanban_renderer o_custom_class</attribute> |
||||
|
</xpath> |
||||
|
<xpath expr="//div[hasclass('o_custom_class')]" |
||||
|
position="attributes"> |
||||
|
<attribute name="style">width:30%;</attribute> |
||||
|
</xpath> |
||||
|
</t> |
||||
|
<t t-name="base_accounting_kit.BankReconcileKanbanRecord" |
||||
|
t-inherit="web.KanbanRecord" t-inherit-mode="primary" owl="1"> |
||||
|
</t> |
||||
|
<t t-name="base_accounting_kit.AccountMoveLineListController" |
||||
|
t-inherit="web.ListView" |
||||
|
t-inherit-mode="primary" owl="1"> |
||||
|
</t> |
||||
|
</templates> |
@ -0,0 +1,124 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<templates id="template" xml:space="preserve"> |
||||
|
<t t-name="base_accounting_kit.bank_reconcile_widget_lines_widget"> |
||||
|
<t t-set="data" t-value="getRenderValues()"/> |
||||
|
<div class="o_list_renderer table-responsive"> |
||||
|
<table class="table table-sm position-relative mb-0 o_list_table_ungrouped table-striped o_bank_reconcile_lines_widget_line"> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<t t-foreach="data.columns" t-as="column" |
||||
|
t-key="column[0]"> |
||||
|
<th t-esc="column[1]"/> |
||||
|
</t> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody id="base_accounting_reconcile"> |
||||
|
<t t-if="data.default_lines_widget"> |
||||
|
<t t-foreach="data.default_lines_widget" t-as="line" |
||||
|
t-key="line.id"> |
||||
|
<tr class="o_data_row" |
||||
|
t-on-click="mountStatementLine" |
||||
|
t-att-data-id="line.id"> |
||||
|
<t t-set="account" |
||||
|
t-value="line.account_code+' '+line.account_name"/> |
||||
|
<t t-set="amount" |
||||
|
t-value="line.currency_symbol+' '+line.amount"/> |
||||
|
<td class="o_data_cell o_field_cell" |
||||
|
style="font-weight: bolder;" |
||||
|
field="account_id"> |
||||
|
<t t-esc="account"/> |
||||
|
<br/> |
||||
|
<span class="text-muted" |
||||
|
style="font-style: italic;"> |
||||
|
<t t-esc="line.payment_ref"/> |
||||
|
</span> |
||||
|
</td> |
||||
|
<t t-if="line.partner_id"> |
||||
|
<td field="partner_id" |
||||
|
t-esc="line.partner_id[1]" |
||||
|
style="font-weight: bolder;"/> |
||||
|
</t> |
||||
|
<t t-else=""> |
||||
|
<td t-esc="line.partner_id[1]"/> |
||||
|
</t> |
||||
|
<td field="date" |
||||
|
t-esc="line.date" |
||||
|
style="font-weight: bolder;"/> |
||||
|
<t t-if="line.amount > 0"> |
||||
|
<td field="debit" |
||||
|
t-esc="amount" |
||||
|
style="font-weight: bolder;"/> |
||||
|
</t> |
||||
|
<t t-else=""> |
||||
|
<td t-esc="' '"/> |
||||
|
</t> |
||||
|
<t t-if="line.amount < 0"> |
||||
|
<td field="credit" |
||||
|
t-esc="amount" |
||||
|
style="font-weight: bolder;"/> |
||||
|
</t> |
||||
|
</tr> |
||||
|
</t> |
||||
|
</t> |
||||
|
<t t-if="data.default_move_line"> |
||||
|
<tr class="o_data_row statement_row" |
||||
|
t-on-click="mountStatementLine" |
||||
|
t-att-data-id="data.default_move_line.id"> |
||||
|
<t t-set="amount_residual" |
||||
|
t-value="data.default_move_line.currency_symbol+' '+data.default_move_line.amount_residual"/> |
||||
|
<t t-set="move_account" |
||||
|
t-value="data.default_move_line.account_code+' '+data.default_move_line.account_name"/> |
||||
|
<td class="o_data_cell o_field_cell" |
||||
|
style="font-weight: bolder;"> |
||||
|
<t t-esc="move_account"/> |
||||
|
<br/> |
||||
|
<span style="font-size: 12px; font-style: italic;font-weight: normal;color: #01666b;cursor: pointer;" |
||||
|
t-att-data-id="data.default_move_line.numeric_move_id" |
||||
|
t-on-click="onclickLink"> |
||||
|
<t t-esc="data.default_move_line.move_name"/> |
||||
|
</span> |
||||
|
: |
||||
|
<span class="text-muted" |
||||
|
style="font-style: italic;"> |
||||
|
<t t-esc="data.default_move_line.name"/> |
||||
|
</span> |
||||
|
</td> |
||||
|
<t t-if="data.default_move_line.partner_id"> |
||||
|
<td t-esc="data.default_move_line.partner_name" |
||||
|
style="font-weight: bolder;"/> |
||||
|
</t> |
||||
|
<t t-else=""> |
||||
|
<td t-esc="data.default_move_line.partner_name"/> |
||||
|
</t> |
||||
|
<td t-esc="data.default_move_line.date" |
||||
|
style="font-weight: bolder;"/> |
||||
|
<t t-if="data.default_move_line.amount_residual < 0"> |
||||
|
<td t-esc="amount_residual" |
||||
|
style="font-weight: bolder;"/> |
||||
|
</t> |
||||
|
<t t-else=""> |
||||
|
<td t-esc="' '"/> |
||||
|
</t> |
||||
|
<t t-if="data.default_move_line.amount_residual > 0"> |
||||
|
<td t-esc="amount_residual" |
||||
|
style="font-weight: bolder;"/> |
||||
|
</t> |
||||
|
<t t-if="this.props.record.data.bank_state!='reconciled'"> |
||||
|
<td class="o_list_remove_record"> |
||||
|
<button class="btn fa fa-trash-o" |
||||
|
style="margin-top: -4px;" |
||||
|
t-on-click="removeRecord"/> |
||||
|
</td> |
||||
|
</t> |
||||
|
</tr> |
||||
|
</t> |
||||
|
</tbody> |
||||
|
</table> |
||||
|
</div> |
||||
|
</t> |
||||
|
<t t-name="base_accounting_kit.FormListView" owl="1"> |
||||
|
<t t-if="props.record.id"> |
||||
|
<View t-props="bankReconcileListViewProps"/> |
||||
|
</t> |
||||
|
</t> |
||||
|
</templates> |
@ -0,0 +1,64 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
############################################################################# |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
||||
|
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU LESSER |
||||
|
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
||||
|
# |
||||
|
# This program is distributed in the hope that it will be useful, |
||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
||||
|
# (LGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
############################################################################# |
||||
|
from odoo import api, fields, models, SUPERUSER_ID, _ |
||||
|
from odoo.exceptions import UserError |
||||
|
|
||||
|
|
||||
|
class AccountUpdateLockDate(models.TransientModel): |
||||
|
_name = 'account.lock.date' |
||||
|
_description = 'Lock date for accounting' |
||||
|
|
||||
|
company_id = fields.Many2one(comodel_name='res.company', string="Company", |
||||
|
required=True) |
||||
|
sale_lock_date = fields.Date(string="Sales Lock Date", help='Prevents creating and modifying invoices up to the date.') |
||||
|
purchase_lock_date = fields.Date(string="Purchase Lock date", help='Prevents creating and modifying bills up to the date.') |
||||
|
hard_lock_date = fields.Date(string="Lock Everyone", |
||||
|
help="No users, including Advisers, can edit accounts prior to and " |
||||
|
"inclusive of this date. Use it for fiscal year locking for " |
||||
|
"example.") |
||||
|
@api.model |
||||
|
def default_get(self, field_list): |
||||
|
res = super(AccountUpdateLockDate, self).default_get(field_list) |
||||
|
company = self.env.company |
||||
|
res.update({ |
||||
|
'company_id': company.id, |
||||
|
'sale_lock_date': company.sale_lock_date, |
||||
|
'purchase_lock_date': company.purchase_lock_date, |
||||
|
'hard_lock_date': company.hard_lock_date, |
||||
|
}) |
||||
|
return res |
||||
|
|
||||
|
def _check_execute_allowed(self): |
||||
|
self.ensure_one() |
||||
|
has_adviser_group = self.env.user.has_group( |
||||
|
'account.group_account_manager') |
||||
|
if not (has_adviser_group or self.env.uid == SUPERUSER_ID): |
||||
|
raise UserError(_("You are not allowed to execute this action.")) |
||||
|
|
||||
|
def execute(self): |
||||
|
self.ensure_one() |
||||
|
self._check_execute_allowed() |
||||
|
self.company_id.sudo().write({ |
||||
|
'sale_lock_date': self.sale_lock_date, |
||||
|
'purchase_lock_date': self.purchase_lock_date, |
||||
|
'hard_lock_date': self.hard_lock_date, |
||||
|
}) |
@ -0,0 +1,46 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<odoo> |
||||
|
<!--Account Lock Date Form View--> |
||||
|
<record model="ir.ui.view" id="account_lock_date_view_form"> |
||||
|
<field name="name">account.lock.date.view.form</field> |
||||
|
<field name="model">account.lock.date</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form> |
||||
|
<group> |
||||
|
<field name="company_id" invisible="1"/> |
||||
|
<label for="sale_lock_date"/> |
||||
|
<div class="d-flex"> |
||||
|
<field name="sale_lock_date" class="oe_inline"/><span class="text-muted"><i>to lock invoices</i></span> |
||||
|
</div> |
||||
|
<label for="purchase_lock_date"/> |
||||
|
<div class="d-flex"> |
||||
|
<field name="purchase_lock_date" class="oe_inline"/><span class="text-muted"><i>to lock bills</i></span> |
||||
|
</div> |
||||
|
<field name="hard_lock_date" class="oe_inline"/> |
||||
|
</group> |
||||
|
<footer> |
||||
|
<button string="Update" name="execute" type="object" class="btn-primary"/> |
||||
|
<button string="Cancel" class="btn-default" special="cancel"/> |
||||
|
</footer> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
<!--Action Account Lock Date--> |
||||
|
<record model="ir.actions.act_window" id="account_update_lock_date_act_window"> |
||||
|
<field name="name">Lock your Fiscal Period</field> |
||||
|
<field name="res_model">account.lock.date</field> |
||||
|
<field name="view_mode">form</field> |
||||
|
<field name="target">new</field> |
||||
|
</record> |
||||
|
<!--Menu Lock Dates--> |
||||
|
<menuitem id="actions_menu" |
||||
|
name="Actions" |
||||
|
sequence="500" |
||||
|
parent="account.menu_finance_entries" |
||||
|
groups="account.group_account_manager"/> |
||||
|
<menuitem id="menu_lock_dates" |
||||
|
name="Lock Dates" |
||||
|
action="account_update_lock_date_act_window" |
||||
|
parent="base_accounting_kit.actions_menu" |
||||
|
groups="account.group_account_manager"/> |
||||
|
</odoo> |