| 
 | 
| 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> | |||