diff --git a/base_accounting_kit/__manifest__.py b/base_accounting_kit/__manifest__.py
index 9e8aa5780..565817502 100644
--- a/base_accounting_kit/__manifest__.py
+++ b/base_accounting_kit/__manifest__.py
@@ -21,7 +21,7 @@
#############################################################################
{
'name': 'Odoo 18 Full Accounting Kit for Community',
- 'version': '18.0.1.0.0',
+ 'version': '18.0.1.0.1',
'category': 'Accounting',
'summary': """Odoo 18 Accounting, Odoo 18 Accounting Reports, Odoo18 Accounting, Odoo Accounting, Odoo18 Financial Reports, Odoo18 Asset, Odoo18 Profit and Loss, PDC, Followups, Odoo18, Accounting, Odoo Apps, Reports""",
'description': """ Odoo 18 Accounting, The module used to manage the Full
@@ -92,15 +92,22 @@
'views/account_bank_statement_views.xml',
'views/account_bank_statement_line_views.xml',
'views/account_payment_view.xml',
+ 'wizard/account_lock_date_views.xml',
],
'assets': {
'web.assets_backend': [
'base_accounting_kit/static/src/scss/style.scss',
'base_accounting_kit/static/src/scss/bank_rec_widget.css',
+ 'base_accounting_kit/static/src/js/bank_reconcile_form_list_widget.js',
+ 'base_accounting_kit/static/src/js/KanbanController.js',
+ 'base_accounting_kit/static/src/js/ListController.js',
+ 'base_accounting_kit/static/src/js/bank_reconcile_form_lines_widget.js',
+ 'base_accounting_kit/static/src/xml/bank_rec_widget.xml',
+ 'base_accounting_kit/static/src/xml/bank_reconcile_widget.xml',
]
},
'license': 'LGPL-3',
- 'images': ['static/description/banner.jpg'],
+ 'images': ['static/description/banner.png'],
'installable': True,
'auto_install': False,
'application': True,
diff --git a/base_accounting_kit/doc/RELEASE_NOTES.md b/base_accounting_kit/doc/RELEASE_NOTES.md
index 41a16b19a..10ddd5fa8 100644
--- a/base_accounting_kit/doc/RELEASE_NOTES.md
+++ b/base_accounting_kit/doc/RELEASE_NOTES.md
@@ -4,3 +4,9 @@
#### Version 18.0.1.0.0
#### ADD
- Initial commit for Odoo 18 Full Accounting Kit for Community
+
+#### 22.10.2024
+#### Version 18.0.1.0.1
+#### UPDT
+- Added the reconciliation widget and lock dates.
+
diff --git a/base_accounting_kit/models/account_bank_statement_line.py b/base_accounting_kit/models/account_bank_statement_line.py
index 3442b6756..c4af11558 100755
--- a/base_accounting_kit/models/account_bank_statement_line.py
+++ b/base_accounting_kit/models/account_bank_statement_line.py
@@ -79,12 +79,20 @@ class AccountBankStatementLine(models.Model):
"""Ensure the current recordset holds a single record and mark it as reconciled."""
self.ensure_one()
self.is_reconciled = True
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'reload',
+ }
def button_reset(self):
"""Reset the current bank statement line if it is in a 'reconciled' state."""
self.ensure_one()
if self.bank_state == 'reconciled':
self.action_undo_reconciliation()
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'reload',
+ }
def button_to_check(self, async_action=True):
"""Ensure the current recordset holds a single record, validate the bank
@@ -93,11 +101,19 @@ class AccountBankStatementLine(models.Model):
if self.bank_state == 'valid':
self.button_validation(async_action=async_action)
self.move_id.to_check = True
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'reload',
+ }
def button_set_as_checked(self):
"""Mark the associated move as 'not to check' by setting 'to_check' to False."""
self.ensure_one()
self.move_id.to_check = False
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'reload',
+ }
@api.model
def get_statement_line(self, record_id):
diff --git a/base_accounting_kit/models/account_journal.py b/base_accounting_kit/models/account_journal.py
index 3f8a05266..1376f84c1 100644
--- a/base_accounting_kit/models/account_journal.py
+++ b/base_accounting_kit/models/account_journal.py
@@ -55,7 +55,56 @@ class AccountJournal(models.Model):
def action_open_reconcile(self):
"""Open the reconciliation view based on the type of the account journal."""
self.ensure_one()
-
+ if self.type in ('bank', 'cash'):
+ views = [
+ (self.env.ref(
+ 'base_accounting_kit.account_bank_statement_line_view_kanban').id,
+ 'kanban'),
+ (self.env.ref(
+ 'base_accounting_kit.account_bank_statement_line_view_tree').id,
+ 'list'), # Include tree view
+ ]
+ context = {
+ 'default_journal_id': self.id,
+ 'search_default_journal_id': self.id,
+ }
+ kanban_first = True
+ name = None
+ extra_domain = None
+ return {
+ 'name': name or _("Bank Reconciliation"),
+ 'type': 'ir.actions.act_window',
+ 'res_model': 'account.bank.statement.line',
+ 'context': context,
+ 'search_view_id': [
+ self.env.ref(
+ 'base_accounting_kit.account_bank_statement_line_view_search').id,
+ 'search'],
+ 'view_mode': 'kanban,list' if kanban_first else 'list,kanban',
+ 'views': views if kanban_first else views[::-1],
+ 'domain': [('state', '!=', 'cancel')] + (extra_domain or []),
+ 'help': _("""
+
+ Nothing to do here!
+
+
+ No transactions matching your filters were found.
+
+ """),
+ }
+ else:
+ # Open reconciliation view for customers/suppliers
+ action_context = {'show_mode_selector': False,
+ 'company_ids': self.mapped('company_id').ids}
+ if self.type == 'sale':
+ action_context.update({'mode': 'customers'})
+ elif self.type == 'purchase':
+ action_context.update({'mode': 'suppliers'})
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'manual_reconciliation_view',
+ 'context': action_context,
+ }
def create_cash_statement(self):
"""for redirecting in to bank statement lines"""
diff --git a/base_accounting_kit/models/res_company.py b/base_accounting_kit/models/res_company.py
index 7e5e94d5a..07cf3fc2d 100644
--- a/base_accounting_kit/models/res_company.py
+++ b/base_accounting_kit/models/res_company.py
@@ -27,14 +27,13 @@ class ResCompany(models.Model):
"""Model for inheriting res_company."""
_inherit = "res.company"
- def _validate_fiscalyear_lock(self, values):
- """Validate the fiscal year lock date by checking for unposted entries and unreconciled bank statement lines."""
- if values.get('fiscalyear_lock_date'):
-
+ def _validate_locks(self, values):
+ """Validate the hard lock date by checking for unposted entries and unreconciled bank statement lines."""
+ if values.get('hard_lock_date'):
draft_entries = self.env['account.move'].search([
('company_id', 'in', self.ids),
('state', '=', 'draft'),
- ('date', '<=', values['fiscalyear_lock_date'])])
+ ('date', '<=', values['hard_lock_date'])])
if draft_entries:
error_msg = _('There are still unposted entries in the '
'period you want to lock. You should either post '
@@ -53,21 +52,20 @@ class ResCompany(models.Model):
unreconciled_statement_lines = self.env['account.bank.statement.line'].search([
('company_id', 'in', self.ids),
('is_reconciled', '=', False),
- ('date', '<=', values['fiscalyear_lock_date']),
+ ('date', '<=', values['hard_lock_date']),
('move_id.state', 'in', ('draft', 'posted')),
])
if unreconciled_statement_lines:
error_msg = _("There are still unreconciled bank statement lines in the period you want to lock."
"You should either reconcile or delete them.")
action_error = {
- 'view_mode': 'list',
+ 'view_mode': 'kanban',
'name': 'Unreconciled Transactions',
'res_model': 'account.bank.statement.line',
'type': 'ir.actions.act_window',
'domain': [('id', 'in', unreconciled_statement_lines.ids)],
'views': [[self.env.ref(
- 'base_accounting_kit.view_bank_statement_line_tree').id,
- 'list']]
+ 'base_accounting_kit.account_bank_statement_line_view_kanban').id,
+ 'kanban']]
}
- raise RedirectWarning(error_msg, action_error,
- _('Show Unreconciled Bank Statement Line'))
+ raise RedirectWarning(error_msg, action_error, _('Show Unreconciled Bank Statement Lines'))
diff --git a/base_accounting_kit/security/ir.model.access.csv b/base_accounting_kit/security/ir.model.access.csv
index 5d32e5cdf..b89efcea1 100644
--- a/base_accounting_kit/security/ir.model.access.csv
+++ b/base_accounting_kit/security/ir.model.access.csv
@@ -42,9 +42,6 @@ access_account_common_journal_report,account.common.journal.report,model_account
access_account_account_type,account.account.type,model_account_account_type,account.group_account_user,1,1,1,1
+access_account_lock_date,access.account.lock.date,model_account_lock_date,account.group_account_user,1,1,1,1
access_account_recurring_entries_line,access.account.recurring.entries.line,model_account_recurring_entries_line,account.group_account_user,1,1,1,1
access_generate_recurring_entries,generate.recurring.entries.user,model_account_recurring_payments,account.group_account_user,1,1,1,1
-
-
-
-
diff --git a/base_accounting_kit/static/description/assets/screenshots/loc3.png b/base_accounting_kit/static/description/assets/screenshots/loc3.png
new file mode 100644
index 000000000..819a348b9
Binary files /dev/null and b/base_accounting_kit/static/description/assets/screenshots/loc3.png differ
diff --git a/base_accounting_kit/static/description/assets/screenshots/loc_1.png b/base_accounting_kit/static/description/assets/screenshots/loc_1.png
new file mode 100644
index 000000000..eb3f26ee4
Binary files /dev/null and b/base_accounting_kit/static/description/assets/screenshots/loc_1.png differ
diff --git a/base_accounting_kit/static/description/assets/screenshots/loc_2.png b/base_accounting_kit/static/description/assets/screenshots/loc_2.png
new file mode 100644
index 000000000..632937a85
Binary files /dev/null and b/base_accounting_kit/static/description/assets/screenshots/loc_2.png differ
diff --git a/base_accounting_kit/static/description/assets/screenshots/rec_1.png b/base_accounting_kit/static/description/assets/screenshots/rec_1.png
new file mode 100644
index 000000000..bd2d203a3
Binary files /dev/null and b/base_accounting_kit/static/description/assets/screenshots/rec_1.png differ
diff --git a/base_accounting_kit/static/description/assets/screenshots/rec_2.png b/base_accounting_kit/static/description/assets/screenshots/rec_2.png
new file mode 100644
index 000000000..ed66aeed9
Binary files /dev/null and b/base_accounting_kit/static/description/assets/screenshots/rec_2.png differ
diff --git a/base_accounting_kit/static/description/assets/screenshots/rec_3.png b/base_accounting_kit/static/description/assets/screenshots/rec_3.png
new file mode 100644
index 000000000..a95d7bedd
Binary files /dev/null and b/base_accounting_kit/static/description/assets/screenshots/rec_3.png differ
diff --git a/base_accounting_kit/static/description/banner.jpg b/base_accounting_kit/static/description/banner.jpg
deleted file mode 100644
index 3cb15fe01..000000000
Binary files a/base_accounting_kit/static/description/banner.jpg and /dev/null differ
diff --git a/base_accounting_kit/static/description/banner.png b/base_accounting_kit/static/description/banner.png
new file mode 100644
index 000000000..738d65baf
Binary files /dev/null and b/base_accounting_kit/static/description/banner.png differ
diff --git a/base_accounting_kit/static/description/index.html b/base_accounting_kit/static/description/index.html
index cc79a478b..c4bc1caab 100644
--- a/base_accounting_kit/static/description/index.html
+++ b/base_accounting_kit/static/description/index.html
@@ -126,7 +126,7 @@
font-size: 46px;
font-weight: 700;
line-height: normal;
- ">Odoo 18 Full Accounting Kit for Community
+ ">Odoo 18 Full Accounting Kit
-
+
+
+
+
+
+
+ Reconciliation Widget.
+
+
+ In the Account Dashboard we can reconcile by clicking the button Reconcile.
+
+
+
+
+
+
+
+
+
+ Lock Dates.
+
+
+ In the Lock Dates wizard we can set the different Lock Dates.
+
+
+
@@ -366,7 +407,7 @@
Odoo 18 Full Accounting Kit for Community
+ style="font-size: 40px; font-weight: 700; color: #fff;line-height: 60px; text-transform: capitalize; width: 450px;">Odoo 18 Full Accounting Kit
Are you ready to make your business more
@@ -605,9 +646,7 @@
- Manage
-
-
+ Manage
Post dated checks.
@@ -629,6 +668,86 @@
+
+
+
+
+
+ Reconciliation
+ Widget.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Lock
+ Dates.
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+ Reconciliation Widget.
+
+
+
+
@@ -1244,6 +1378,35 @@
class="tab-pane fade show" id="releases"
role="tabpanel">
+
+
+
+ Latest Release 18.0.1.0.1
+
+
+ 22nd October, 2024
+
+
+
+
+
+
+
+
+ Added reconciliation widget and lock date
+
+
+
+
+
+
+
+
diff --git a/base_accounting_kit/static/src/js/KanbanController.js b/base_accounting_kit/static/src/js/KanbanController.js
new file mode 100755
index 000000000..37acd5c3f
--- /dev/null
+++ b/base_accounting_kit/static/src/js/KanbanController.js
@@ -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);
diff --git a/base_accounting_kit/static/src/js/ListController.js b/base_accounting_kit/static/src/js/ListController.js
new file mode 100755
index 000000000..da17c06f3
--- /dev/null
+++ b/base_accounting_kit/static/src/js/ListController.js
@@ -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 = `${record.data.move_id[1]} `;
+ }
+
+
+ if (amount < 0) {
+ debitColumn = `${currencySymbol[0].symbol} ${-amount} `;
+ } else {
+ creditColumn = `${currencySymbol[0].symbol} ${amount} `;
+ }
+
+ const newRow = document.createElement('tr');
+ newRow.setAttribute('data-resId', record.resId); // Set a unique identifier for the row
+ if (debitColumn !== '') {
+ newRow.innerHTML = `${record.data.account_id[1]}
+ ${moveId} : ${record.data.name}
+ ${partnerName}
+ ${formattedDate}
+ ${debitColumn}
+
+
+
+ `;
+
+ } else if (creditColumn !== '') {
+ newRow.innerHTML = `${record.data.account_id[1]}
+ ${moveId} : ${record.data.name}
+ ${partnerName}
+ ${formattedDate}
+
+ ${creditColumn}
+
+
+ `;
+ }
+ 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);
\ No newline at end of file
diff --git a/base_accounting_kit/static/src/js/bank_reconcile_form_lines_widget.js b/base_accounting_kit/static/src/js/bank_reconcile_form_lines_widget.js
new file mode 100755
index 000000000..48054237e
--- /dev/null
+++ b/base_accounting_kit/static/src/js/bank_reconcile_form_lines_widget.js
@@ -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)
diff --git a/base_accounting_kit/static/src/js/bank_reconcile_form_list_widget.js b/base_accounting_kit/static/src/js/bank_reconcile_form_list_widget.js
new file mode 100755
index 000000000..63d527ae6
--- /dev/null
+++ b/base_accounting_kit/static/src/js/bank_reconcile_form_list_widget.js
@@ -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: `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `,
+ 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);
diff --git a/base_accounting_kit/static/src/scss/style.scss b/base_accounting_kit/static/src/scss/style.scss
index a9bc9f556..66d797bc2 100755
--- a/base_accounting_kit/static/src/scss/style.scss
+++ b/base_accounting_kit/static/src/scss/style.scss
@@ -214,7 +214,6 @@
}
.accounts-dashboard-wrap .info-box .info-box-icon {
-
border-radius: .25rem;
-ms-flex-align: center;
align-items: center;
diff --git a/base_accounting_kit/static/src/xml/bank_rec_widget.xml b/base_accounting_kit/static/src/xml/bank_rec_widget.xml
new file mode 100755
index 000000000..fa9caebda
--- /dev/null
+++ b/base_accounting_kit/static/src/xml/bank_rec_widget.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ o_kanban_renderer o_custom_class
+
+
+ width:30%;
+
+
+
+
+
+
+
diff --git a/base_accounting_kit/static/src/xml/bank_reconcile_widget.xml b/base_accounting_kit/static/src/xml/bank_reconcile_widget.xml
new file mode 100755
index 000000000..682e2813a
--- /dev/null
+++ b/base_accounting_kit/static/src/xml/bank_reconcile_widget.xml
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/base_accounting_kit/wizard/__init__.py b/base_accounting_kit/wizard/__init__.py
index 6ade6f277..be8068123 100644
--- a/base_accounting_kit/wizard/__init__.py
+++ b/base_accounting_kit/wizard/__init__.py
@@ -25,6 +25,7 @@ from . import account_balance_report
from . import account_bank_book_report
from . import account_cash_book_report
from . import account_day_book_report
+from . import account_lock_date
from . import account_print_journal
from . import account_report_general_ledger
from . import account_report_partner_ledger
diff --git a/base_accounting_kit/wizard/account_lock_date.py b/base_accounting_kit/wizard/account_lock_date.py
new file mode 100644
index 000000000..18546336b
--- /dev/null
+++ b/base_accounting_kit/wizard/account_lock_date.py
@@ -0,0 +1,64 @@
+# -*- coding: utf-8 -*-
+#############################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+#
+# Copyright (C) 2024-TODAY Cybrosys Technologies()
+# Author: Cybrosys Techno Solutions()
+#
+# 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 .
+#
+#############################################################################
+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,
+ })
diff --git a/base_accounting_kit/wizard/account_lock_date_views.xml b/base_accounting_kit/wizard/account_lock_date_views.xml
new file mode 100644
index 000000000..33c6efa14
--- /dev/null
+++ b/base_accounting_kit/wizard/account_lock_date_views.xml
@@ -0,0 +1,46 @@
+
+
+
+
+ account.lock.date.view.form
+ account.lock.date
+
+
+
+
+
+
+ Lock your Fiscal Period
+ account.lock.date
+ form
+ new
+
+
+
+
+