From 8879b1c391af115e6025c9bd04bfb1403feacc0a Mon Sep 17 00:00:00 2001
From: EstherWee <89062424+EstherWee@users.noreply.github.com>
Date: Tue, 19 Dec 2023 15:58:01 +0700
Subject: [PATCH 01/14] changed inherited model name
---
local-addons/morons/security/security.xml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/local-addons/morons/security/security.xml b/local-addons/morons/security/security.xml
index 5ac49d6..7e95750 100644
--- a/local-addons/morons/security/security.xml
+++ b/local-addons/morons/security/security.xml
@@ -20,7 +20,7 @@
Contributor access
-
+
@@ -30,7 +30,7 @@
PM access
-
+
@@ -48,7 +48,7 @@
PO Contributor Access
-
+
[('user_id','=',user.id)]
@@ -56,7 +56,7 @@
PO PM Access
-
+
[('user_id','=',user.id)]
From 751f32156228a746bdffb9ff78f53ae662320cfb Mon Sep 17 00:00:00 2001
From: Toh Zhengfeng
Date: Wed, 20 Dec 2023 22:01:51 +0700
Subject: [PATCH 02/14] Added internal user form for admin accounts
---
local-addons/morons/models/contributor.py | 96 +++++++++++------------
local-addons/morons/views/project.xml | 44 +++++++++++
local-addons/morons/views/user.xml | 24 ++++++
3 files changed, 116 insertions(+), 48 deletions(-)
diff --git a/local-addons/morons/models/contributor.py b/local-addons/morons/models/contributor.py
index cbe99c9..2418e03 100644
--- a/local-addons/morons/models/contributor.py
+++ b/local-addons/morons/models/contributor.py
@@ -12,51 +12,51 @@ class InternalUser(models.Model):
contributor = fields.Boolean(string='Contributor', default=False)
active = fields.Boolean(string='Active', default=True)
currency = fields.Many2one('res.currency', string='Currency')
- # skype = fields.Char(string='Skype')
- # nationality = fields.Many2many('res.lang', required=True)
- # country_of_residence = fields.Many2one('res.country', required=True)
- # timezone = fields.Selection('_tz_get',
- # string='Timezone',
- # required=True,
- # default=lambda self: self.env.user.tz or 'UTC')
- #
- # @api.model
- # def _tz_get(self):
- # return [(x, x) for x in pytz.all_timezones]
- #
- # # Payment Methods
- # paypal = fields.Char('PayPal ID')
- # transferwise_id = fields.Char('Wise ID')
- # bank_account_number = fields.Char('Bank Account Number')
- # bank_name = fields.Char('Bank Name')
- # iban = fields.Char('IBAN')
- # swift = fields.Char('SWIFT')
- # bank_address = fields.Char('Bank Address')
- # preferred_payment_method = fields.Selection(selection=[('paypal', 'Paypal'),
- # ('transferwise', 'Wise'),
- # ('bank', 'Bank Transfer')])
- #
- # @api.constrains('paypal')
- # def validate_email(self):
- # if self.paypal:
- # match = re.match(
- # '^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$',
- # self.paypal)
- # if match is None:
- # raise ValidationError('Not a valid email')
- #
- # # Education and Experience
- # dates_attended = fields.Date('Date Attended')
- # school = fields.Char('School')
- # field_of_study = fields.Char('Field of Study')
- # year_obtained = fields.Selection([(num, str(num)) for num in range(1900, datetime.datetime.now().year + 1)], 'Year')
- # certificate = fields.Char('Certificate')
- #
- # @api.constrains('login')
- # def validate_email(self):
- # if self.login:
- # match = re.match(
- # '^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$',
- # self.login)
- # if match is None:
- # raise ValidationError('Not a valid email')
+ skype = fields.Char(string='Skype')
+ nationality = fields.Many2many('res.lang', required=True)
+ country_of_residence = fields.Many2one('res.country', required=True)
+ timezone = fields.Selection('_tz_get',
+ string='Timezone',
+ required=True,
+ default=lambda self: self.env.user.tz or 'UTC')
+
+ @api.model
+ def _tz_get(self):
+ return [(x, x) for x in pytz.all_timezones]
+
+ # Payment Methods
+ paypal = fields.Char('PayPal ID')
+ transferwise_id = fields.Char('Wise ID')
+ bank_account_number = fields.Char('Bank Account Number')
+ bank_name = fields.Char('Bank Name')
+ iban = fields.Char('IBAN')
+ swift = fields.Char('SWIFT')
+ bank_address = fields.Char('Bank Address')
+ preferred_payment_method = fields.Selection(selection=[('paypal', 'Paypal'),
+ ('transferwise', 'Wise'),
+ ('bank', 'Bank Transfer')])
+
+ @api.constrains('paypal')
+ def validate_paypal(self):
+ if self.paypal:
+ match = re.match(
+ '^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$',
+ self.paypal)
+ if match is None:
+ raise ValidationError('Not a valid email')
+
+ # Education and Experience
+ dates_attended = fields.Date('Date Attended')
+ school = fields.Char('School')
+ field_of_study = fields.Char('Field of Study')
+ year_obtained = fields.Selection([(str(num), str(num)) for num in range(1900, datetime.datetime.now().year + 1)], 'Year')
+ certificate = fields.Char('Certificate')
+
+ @api.constrains('login')
+ def validate_login(self):
+ if self.login:
+ match = re.match(
+ '^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$',
+ self.login)
+ if match is None:
+ raise ValidationError('Not a valid email')
diff --git a/local-addons/morons/views/project.xml b/local-addons/morons/views/project.xml
index b0462a8..2a77c3c 100644
--- a/local-addons/morons/views/project.xml
+++ b/local-addons/morons/views/project.xml
@@ -123,11 +123,55 @@
+
+
+ res.users.form.custom
+ res.users
+
+
+
+
+ Contributor
+ Currency
+ Active
+ Skype
+ Nationality
+ Country of Residence
+ Timezone
+
+
+
+
+ Preferred Payment Method
+ PayPal ID
+ Wise ID
+ Bank Account Number
+ Bank Name
+ IBAN
+ SWIFT
+ Bank Address
+
+
+
+
+ Dates Attended
+ School
+ Field of Study
+ Year Obtained
+ Certificate
+
+
+
+
+
+
+
Internal Users
res.users
tree,form
+
[('share', '=', False)]
diff --git a/local-addons/morons/views/user.xml b/local-addons/morons/views/user.xml
index 170b35d..8f7c3fb 100644
--- a/local-addons/morons/views/user.xml
+++ b/local-addons/morons/views/user.xml
@@ -12,8 +12,32 @@
+
Contributor
Currency
+ Active
+ Skype
+ Nationality
+ Country of Residence
+ Timezone
+
+
+ Preferred Payment Method
+ PayPal ID
+ Wise ID
+ Bank Account Number
+ Bank Name
+ IBAN
+ SWIFT
+ Bank Address
+
+
+ Dates Attended
+ School
+ Field of Study
+ Year Obtained
+ Certificate
+
From 3ccaf1f2b1171eb4c2a6c8f5a4474d62ecd70c2f Mon Sep 17 00:00:00 2001
From: Toh Zhengfeng
Date: Thu, 21 Dec 2023 00:21:04 +0700
Subject: [PATCH 03/14] Added limitation for group_id
---
local-addons/morons/models/project.py | 2 +-
local-addons/morons/views/project.xml | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/local-addons/morons/models/project.py b/local-addons/morons/models/project.py
index 30a0a68..4659a79 100644
--- a/local-addons/morons/models/project.py
+++ b/local-addons/morons/models/project.py
@@ -12,7 +12,7 @@
class MercTransServices(models.Model):
_name = "merctrans.services"
- _rec_name = "name"
+ _rec_name = "name"
_description = "Services offered by MercTrans"
department_list = [
diff --git a/local-addons/morons/views/project.xml b/local-addons/morons/views/project.xml
index 2a77c3c..7406ad8 100644
--- a/local-addons/morons/views/project.xml
+++ b/local-addons/morons/views/project.xml
@@ -130,6 +130,10 @@
+ User Groups
Contributor
Currency
From d4c56778c50eab0ff3f6264b24d1949d52032580 Mon Sep 17 00:00:00 2001
From: EstherWee <89062424+EstherWee@users.noreply.github.com>
Date: Thu, 21 Dec 2023 04:28:54 +0700
Subject: [PATCH 04/14] access rights for Apps menu
---
local-addons/morons/views/project.xml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/local-addons/morons/views/project.xml b/local-addons/morons/views/project.xml
index b0462a8..16791b3 100644
--- a/local-addons/morons/views/project.xml
+++ b/local-addons/morons/views/project.xml
@@ -138,5 +138,7 @@
action="action_open_res_users"
groups="base.group_system"
sequence="5"/>
+
+
\ No newline at end of file
From 1667e033cb034af5027579807afe6f3df6c39782 Mon Sep 17 00:00:00 2001
From: EstherWee <89062424+EstherWee@users.noreply.github.com>
Date: Thu, 21 Dec 2023 05:06:58 +0700
Subject: [PATCH 05/14] access rights to see all projects
---
local-addons/morons/views/project.xml | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/local-addons/morons/views/project.xml b/local-addons/morons/views/project.xml
index 16791b3..d2afe2a 100644
--- a/local-addons/morons/views/project.xml
+++ b/local-addons/morons/views/project.xml
@@ -139,6 +139,13 @@
groups="base.group_system"
sequence="5"/>
-
+
+
+
\ No newline at end of file
From 7928b53c0dfd9e5e3c106fa5a9c787ae97578cfb Mon Sep 17 00:00:00 2001
From: Toh Zhengfeng
Date: Thu, 21 Dec 2023 12:51:00 +0700
Subject: [PATCH 06/14] Added invoice model
---
local-addons/morons/__manifest__.py | 4 ++--
local-addons/morons/models/__init__.py | 3 ++-
local-addons/morons/models/contributor.py | 1 +
local-addons/morons/views/project.xml | 4 ++--
4 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/local-addons/morons/__manifest__.py b/local-addons/morons/__manifest__.py
index 136904f..ee6a93a 100644
--- a/local-addons/morons/__manifest__.py
+++ b/local-addons/morons/__manifest__.py
@@ -26,14 +26,14 @@
# 'security/ir.model.access.csv',
'views/project.xml',
'views/user.xml',
- "security/ir.model.access.csv",
- "security/security.xml",
'data/languages.xml',
'data/currencies.xml',
'data/email_template.xml',
'data/company_data.xml',
'data/services.xml',
'data/tags.xml',
+ "security/ir.model.access.csv",
+ "security/security.xml",
],
# only loaded in demonstration mode
'demo': [
diff --git a/local-addons/morons/models/__init__.py b/local-addons/morons/models/__init__.py
index bba51e2..f953daa 100644
--- a/local-addons/morons/models/__init__.py
+++ b/local-addons/morons/models/__init__.py
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from . import project
-from . import contributor
\ No newline at end of file
+from . import contributor
+from . import invoice
\ No newline at end of file
diff --git a/local-addons/morons/models/contributor.py b/local-addons/morons/models/contributor.py
index cc90a68..f659a17 100644
--- a/local-addons/morons/models/contributor.py
+++ b/local-addons/morons/models/contributor.py
@@ -95,6 +95,7 @@ def validate_paypal(self):
year_obtained = fields.Selection([(str(num), str(num)) for num in range(1900, datetime.datetime.now().year + 1)], 'Year')
certificate = fields.Char('Certificate')
+
@api.constrains('login')
def validate_login(self):
if self.login:
diff --git a/local-addons/morons/views/project.xml b/local-addons/morons/views/project.xml
index 94058e9..3b9fd34 100644
--- a/local-addons/morons/views/project.xml
+++ b/local-addons/morons/views/project.xml
@@ -141,7 +141,7 @@
-
+
Contributor
Currency
Active
@@ -168,7 +168,7 @@
-
+
Dates Attended
School
Field of Study
From 4ae6a609e15d10c36bf7735208cab581f07f305c Mon Sep 17 00:00:00 2001
From: Toh Zhengfeng
Date: Fri, 22 Dec 2023 13:09:52 +0700
Subject: [PATCH 07/14] Added boilerplate invoice model
---
local-addons/morons/models/contributor.py | 7 +++
local-addons/morons/views/project.xml | 55 +++++++++++++++++++++--
2 files changed, 58 insertions(+), 4 deletions(-)
diff --git a/local-addons/morons/models/contributor.py b/local-addons/morons/models/contributor.py
index f659a17..032d2c4 100644
--- a/local-addons/morons/models/contributor.py
+++ b/local-addons/morons/models/contributor.py
@@ -95,6 +95,13 @@ def validate_paypal(self):
year_obtained = fields.Selection([(str(num), str(num)) for num in range(1900, datetime.datetime.now().year + 1)], 'Year')
certificate = fields.Char('Certificate')
+ assigned_records_count = fields.Integer(string='Assigned Records Count', compute='_compute_assigned_records_count')
+
+ def _compute_assigned_records_count(self):
+ for record in self:
+ # Count the number of project.task records where this user is in user_ids
+ count = self.env['project.task'].search_count([('user_ids', 'in', record.id)])
+ record.assigned_records_count = count
@api.constrains('login')
def validate_login(self):
diff --git a/local-addons/morons/views/project.xml b/local-addons/morons/views/project.xml
index 3b9fd34..27a6ab2 100644
--- a/local-addons/morons/views/project.xml
+++ b/local-addons/morons/views/project.xml
@@ -186,16 +186,63 @@
Internal Users
res.users
tree,form
-
- [('share', '=', False)]
+
+ [('share', '=', False)]
+
+ morons list
+ morons.invoice
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Invoices
+ morons.invoice
+ tree
+
+
+
+
+
+
+
+
+ groups="base.group_system"/>
+
+
+
+
+
+
+
\ No newline at end of file
From 95dba022ab5c66a5f3af2d4f626706756ad9efef Mon Sep 17 00:00:00 2001
From: EstherWee <89062424+EstherWee@users.noreply.github.com>
Date: Fri, 22 Dec 2023 13:10:16 +0700
Subject: [PATCH 08/14] created 2 new groups
---
local-addons/morons/__manifest__.py | 4 ++--
local-addons/morons/security/security.xml | 10 ++++++++++
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/local-addons/morons/__manifest__.py b/local-addons/morons/__manifest__.py
index 136904f..68b72b9 100644
--- a/local-addons/morons/__manifest__.py
+++ b/local-addons/morons/__manifest__.py
@@ -24,10 +24,10 @@
# always loaded
'data': [
# 'security/ir.model.access.csv',
- 'views/project.xml',
- 'views/user.xml',
"security/ir.model.access.csv",
"security/security.xml",
+ 'views/project.xml',
+ 'views/user.xml',
'data/languages.xml',
'data/currencies.xml',
'data/email_template.xml',
diff --git a/local-addons/morons/security/security.xml b/local-addons/morons/security/security.xml
index 7e95750..4648fb3 100644
--- a/local-addons/morons/security/security.xml
+++ b/local-addons/morons/security/security.xml
@@ -17,6 +17,16 @@
+
+ BOD
+
+
+
+
+ Accountants
+
+
+
Contributor access
From 8ce23a6d61c625d32844331f57adaecf0c52dbde Mon Sep 17 00:00:00 2001
From: Toh Zhengfeng
Date: Fri, 22 Dec 2023 13:21:04 +0700
Subject: [PATCH 09/14] Added boilerplate invoice model
---
local-addons/morons/models/invoice.py | 96 +++++++++++++++++++++++++++
local-addons/morons/views/invoice.xml | 0
local-addons/morons/views/project.xml | 6 +-
3 files changed, 99 insertions(+), 3 deletions(-)
create mode 100644 local-addons/morons/models/invoice.py
create mode 100644 local-addons/morons/views/invoice.xml
diff --git a/local-addons/morons/models/invoice.py b/local-addons/morons/models/invoice.py
new file mode 100644
index 0000000..c9b6219
--- /dev/null
+++ b/local-addons/morons/models/invoice.py
@@ -0,0 +1,96 @@
+# -*- coding: utf-8 -*-
+
+from odoo import models, fields, api
+
+class Invoice(models.Model):
+ """
+ A model representing invoices in the MercTrans system.
+
+ This class extends the basic functionality of Odoo's invoicing system
+ to meet the specific requirements of MercTrans. It includes features
+ like a variety of work units, different statuses for invoices and payments,
+ and the capability to handle different currencies with automatic conversion
+ to USD. It also manages the link with purchase orders from projects and
+ calculates payable amounts based on dynamic rates and units.
+
+ Attributes:
+ _name (str): Identifier for the Odoo model.
+ invoice_status_list (list of tuples): A predefined list of possible statuses for an invoice.
+ work_unit_list (list of tuples): A predefined list of work units applicable to an invoice.
+ payment_status_list (list of tuples): A predefined list of payment statuses for tracking invoice payments.
+ issue_date (fields.Date): Field for the date when the invoice is issued.
+ due_date (fields.Date): Field for the date when the invoice payment is due.
+ sender (fields.Char): Field for the name of the sender of the invoice.
+ purchase_order (fields.Many2one): Relationship to the 'project.project' model, representing the associated purchase order.
+ purchase_order_name (fields.Char): Field for displaying the name of the related purchase order, derived from 'purchase_order'.
+ note (fields.Text): Field for any additional notes or comments on the invoice.
+ currency (fields.Many2one): Field linking to the 'res.currency' model for specifying the currency used in the invoice.
+ work_unit (fields.Selection): Field for selecting a work unit from the work_unit_list.
+ rate (fields.Float): Field for the rate applied in the invoice, dependent on the chosen work unit.
+ sale_unit (fields.Integer): Field for the number of work units being billed in the invoice.
+ payable (fields.Monetary): Computed field for the total payable amount in the invoice's currency.
+ payable_usd (fields.Monetary): Computed field for the total payable amount converted to USD.
+ status (fields.Selection): Field for the current status of the invoice, selected from invoice_status_list.
+ payment_status (fields.Selection): Field for the current payment status of the invoice, selected from payment_status_list.
+
+ Methods:
+ _compute_payable_amount(self): Computes the total payable amount based on the rate and sale unit.
+ _compute_amount_usd(self): Converts the payable amount into USD based on the current exchange rate and invoice date.
+ """
+
+ _name = 'morons.invoice'
+
+ invoice_status_list = [
+ ("in progress", "In Progress"),
+ ("completed", "Completed"),
+ ("canceled", "Canceled"),
+ ("draft", "Draft"),
+ ]
+
+ work_unit_list = [
+ ("word", "Word"),
+ ("hour", "Hour"),
+ ("page", "Page"),
+ ("job", "Job"),
+ ]
+
+ payment_status_list = [
+ ("unpaid", "Unpaid"),
+ ("invoiced", "Invoiced"),
+ ("paid", "Paid"),
+ ]
+
+ issue_date = fields.Date(string='Issue Date')
+ due_date = fields.Date(string='Due Date')
+ sender = fields.Char(string='Issued By')
+
+ purchase_order = fields.Many2one('project.project', string='Purchase Order')
+ purchase_order_name = fields.Char(string="Purchase Order Name", related='purchase_order.name', readonly=True)
+
+ note = fields.Text(string='Note')
+
+ currency = fields.Many2one('res.currency', string='Currency')
+ work_unit = fields.Selection(string='Work Unit', selection=work_unit_list, default='word')
+ rate = fields.Float(string="Rate", digits=(16, 2))
+ sale_unit = fields.Integer(string='Sale Unit')
+ payable = fields.Monetary(string='Payable', currency_field='currency', compute='_compute_payable_amount', store=True)
+ payable_usd = fields.Monetary(string='Payable(USD)', currency_field='currency', compute='_compute_amount_usd')
+
+ @api.depends('rate', 'sale_unit')
+ def _compute_payable_amount(self):
+ for record in self:
+ record.payable = record.rate * record.sale_unit
+
+ @api.depends('payable', 'currency')
+ def _compute_amount_usd(self):
+ usd_currency_id = self.env.ref('base.USD').id
+ for record in self:
+ if record.currency and record.currency.id != usd_currency_id:
+ conversion_rate = record.currency.with_context(date=record.issue_date).rate
+ record.payable_usd = record.payable * conversion_rate
+ else:
+ record.payable_usd = record.payable
+
+ status = fields.Selection(string='Status', selection=invoice_status_list, default='draft')
+ payment_status = fields.Selection(string='Payment Status', selection=payment_status_list, default='unpaid')
+
diff --git a/local-addons/morons/views/invoice.xml b/local-addons/morons/views/invoice.xml
new file mode 100644
index 0000000..e69de29
diff --git a/local-addons/morons/views/project.xml b/local-addons/morons/views/project.xml
index 27a6ab2..904eb2e 100644
--- a/local-addons/morons/views/project.xml
+++ b/local-addons/morons/views/project.xml
@@ -205,8 +205,8 @@
-
+
+
@@ -215,7 +215,7 @@
Invoices
morons.invoice
tree
-
+
From 5fd9a433d85276def1791ad30761e5046eef29ce Mon Sep 17 00:00:00 2001
From: EstherWee <89062424+EstherWee@users.noreply.github.com>
Date: Fri, 22 Dec 2023 14:43:06 +0700
Subject: [PATCH 10/14] access rights for invoice status
---
local-addons/morons/models/invoice.py | 4 +-
local-addons/morons/security/security.xml | 49 ++++++++++++++++++++
local-addons/morons/views/project.xml | 55 ++++++++++++++++-------
3 files changed, 91 insertions(+), 17 deletions(-)
diff --git a/local-addons/morons/models/invoice.py b/local-addons/morons/models/invoice.py
index c9b6219..6e6a4d3 100644
--- a/local-addons/morons/models/invoice.py
+++ b/local-addons/morons/models/invoice.py
@@ -64,8 +64,8 @@ class Invoice(models.Model):
due_date = fields.Date(string='Due Date')
sender = fields.Char(string='Issued By')
- purchase_order = fields.Many2one('project.project', string='Purchase Order')
- purchase_order_name = fields.Char(string="Purchase Order Name", related='purchase_order.name', readonly=True)
+ # purchase_order = fields.Many2one('project.project', string='Purchase Order')
+ # purchase_order_name = fields.Char(string="Purchase Order Name", related='purchase_order.name', readonly=True)
note = fields.Text(string='Note')
diff --git a/local-addons/morons/security/security.xml b/local-addons/morons/security/security.xml
index 7e95750..337402a 100644
--- a/local-addons/morons/security/security.xml
+++ b/local-addons/morons/security/security.xml
@@ -17,6 +17,15 @@
+
+ BOD
+
+
+
+ Accountants
+
+
+
Contributor access
@@ -38,6 +47,46 @@
+
+ Contributor access to invoice
+
+
+
+
+
+
+
+
+
+ PM access to invoice
+
+
+
+
+
+
+
+
+
+ BOD access to invoice
+
+
+
+
+
+
+
+
+
+ Accountant access to invoice
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
morons list
morons.invoice
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
Invoices
morons.invoice
- tree
-
+ tree,form
+
From 7991358817a3358825ff3f3de7361aec077c069b Mon Sep 17 00:00:00 2001
From: Toh Zhengfeng
Date: Fri, 22 Dec 2023 16:57:15 +0700
Subject: [PATCH 11/14] Revised invoice model
---
local-addons/morons/views/project.xml | 33 +++++++++++++++------------
1 file changed, 18 insertions(+), 15 deletions(-)
diff --git a/local-addons/morons/views/project.xml b/local-addons/morons/views/project.xml
index 27a6ab2..c57156b 100644
--- a/local-addons/morons/views/project.xml
+++ b/local-addons/morons/views/project.xml
@@ -195,27 +195,30 @@
morons list
morons.invoice
-
-
-
-
-
-
-
-
-
-
-
-
+
Invoices
morons.invoice
- tree
-
+ tree,form
+
From 7cb73b19d6c1ec74810c0980c53b977c5415d0c7 Mon Sep 17 00:00:00 2001
From: Toh Zhengfeng
Date: Mon, 25 Dec 2023 14:51:11 +0700
Subject: [PATCH 12/14] Completed payable_usd computation and total contributor
records
---
local-addons/morons/models/contributor.py | 2 +-
local-addons/morons/views/project.xml | 5 +++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/local-addons/morons/models/contributor.py b/local-addons/morons/models/contributor.py
index 032d2c4..68e30a0 100644
--- a/local-addons/morons/models/contributor.py
+++ b/local-addons/morons/models/contributor.py
@@ -95,7 +95,7 @@ def validate_paypal(self):
year_obtained = fields.Selection([(str(num), str(num)) for num in range(1900, datetime.datetime.now().year + 1)], 'Year')
certificate = fields.Char('Certificate')
- assigned_records_count = fields.Integer(string='Assigned Records Count', compute='_compute_assigned_records_count')
+ assigned_records_count = fields.Integer(string=' Assigned Tasks', compute='_compute_assigned_records_count')
def _compute_assigned_records_count(self):
for record in self:
diff --git a/local-addons/morons/views/project.xml b/local-addons/morons/views/project.xml
index c57156b..595a587 100644
--- a/local-addons/morons/views/project.xml
+++ b/local-addons/morons/views/project.xml
@@ -174,6 +174,7 @@
Field of Study
Year Obtained
Certificate
+
@@ -191,7 +192,7 @@
[('share', '=', False)]
-
+
morons list
morons.invoice
@@ -218,7 +219,7 @@
Invoices
morons.invoice
tree,form
-
+
From 245e0de937e2eaef685f9882485d594abad90408 Mon Sep 17 00:00:00 2001
From: Toh Zhengfeng
Date: Mon, 25 Dec 2023 14:52:15 +0700
Subject: [PATCH 13/14] Fix: Added invoice model
---
local-addons/morons/models/invoice.py | 107 ++++++++++++++++++++++++++
1 file changed, 107 insertions(+)
create mode 100644 local-addons/morons/models/invoice.py
diff --git a/local-addons/morons/models/invoice.py b/local-addons/morons/models/invoice.py
new file mode 100644
index 0000000..0de8988
--- /dev/null
+++ b/local-addons/morons/models/invoice.py
@@ -0,0 +1,107 @@
+# -*- coding: utf-8 -*-
+
+from odoo import models, fields, api
+
+class Invoice(models.Model):
+ """
+ A model representing invoices in the MercTrans system.
+
+ This class extends the basic functionality of Odoo's invoicing system
+ to meet the specific requirements of MercTrans. It includes features
+ like a variety of work units, different statuses for invoices and payments,
+ and the capability to handle different currencies with automatic conversion
+ to USD. It also manages the link with purchase orders from projects and
+ calculates payable amounts based on dynamic rates and units.
+
+ Attributes:
+ _name (str): Identifier for the Odoo model.
+ invoice_status_list (list of tuples): A predefined list of possible statuses for an invoice.
+ work_unit_list (list of tuples): A predefined list of work units applicable to an invoice.
+ payment_status_list (list of tuples): A predefined list of payment statuses for tracking invoice payments.
+ issue_date (fields.Date): Field for the date when the invoice is issued.
+ due_date (fields.Date): Field for the date when the invoice payment is due.
+ sender (fields.Char): Field for the name of the sender of the invoice.
+ purchase_order (fields.Many2one): Relationship to the 'project.project' model, representing the associated purchase order.
+ purchase_order_name (fields.Char): Field for displaying the name of the related purchase order, derived from 'purchase_order'.
+ note (fields.Text): Field for any additional notes or comments on the invoice.
+ currency (fields.Many2one): Field linking to the 'res.currency' model for specifying the currency used in the invoice.
+ work_unit (fields.Selection): Field for selecting a work unit from the work_unit_list.
+ rate (fields.Float): Field for the rate applied in the invoice, dependent on the chosen work unit.
+ sale_unit (fields.Integer): Field for the number of work units being billed in the invoice.
+ payable (fields.Monetary): Computed field for the total payable amount in the invoice's currency.
+ payable_usd (fields.Monetary): Computed field for the total payable amount converted to USD.
+ status (fields.Selection): Field for the current status of the invoice, selected from invoice_status_list.
+ payment_status (fields.Selection): Field for the current payment status of the invoice, selected from payment_status_list.
+
+ Methods:
+ _compute_payable_amount(self): Computes the total payable amount based on the rate and sale unit.
+ _compute_amount_usd(self): Converts the payable amount into USD based on the current exchange rate and invoice date.
+ """
+
+ _name = 'morons.invoice'
+
+ invoice_status_list = [
+ ("in progress", "In Progress"),
+ ("completed", "Completed"),
+ ("canceled", "Canceled"),
+ ("draft", "Draft"),
+ ]
+
+ work_unit_list = [
+ ("word", "Word"),
+ ("hour", "Hour"),
+ ("page", "Page"),
+ ("job", "Job"),
+ ]
+
+ payment_status_list = [
+ ("unpaid", "Unpaid"),
+ ("invoiced", "Invoiced"),
+ ("paid", "Paid"),
+ ]
+
+ issue_date = fields.Date(string='Issue Date')
+ due_date = fields.Date(string='Due Date')
+ sender = fields.Char(string='Issued By')
+
+ purchase_order = fields.Many2one('project.task', string='Purchase Order')
+
+ note = fields.Text(string='Note')
+
+ currency = fields.Many2one('res.currency', string='Currency')
+ work_unit = fields.Selection(string='Work Unit', selection=work_unit_list, default='word')
+ rate = fields.Float(string="Rate", digits=(16, 2))
+ sale_unit = fields.Integer(string='Sale Unit')
+ payable = fields.Monetary(string='Payable', currency_field='currency', compute='_compute_payable_amount', store=True, readonly=True)
+ usd_currency_id = fields.Many2one('res.currency', string='USD Currency', default=lambda self: self.env.ref('base.USD'))
+ payable_usd = fields.Monetary(string='Payable(USD)', currency_field='usd_currency_id', compute='_compute_amount_usd')
+
+ @api.depends('rate', 'sale_unit')
+ def _compute_payable_amount(self):
+ for record in self:
+ record.payable = record.rate * record.sale_unit
+
+ @api.depends('payable')
+ def _compute_amount_usd(self):
+ """
+ For now, it is hardcoded to convert from VND to USD and EUR to USD.
+ (TODO) Auto compute regardless of currency.
+ """
+ for record in self:
+ if record.currency.name == 'VND':
+ record.payable_usd = record.payable * 0.000041
+ elif record.currency.name == 'EUR':
+ record.payable_usd = record.payable * 1.10
+ else:
+ record.payable_usd = record.payable
+
+ # @api.depends('payable', 'currency')
+ # def _compute_payable_usd(self):
+ # for record in self:
+ # USD = self.env['res.currency'].search([('name', '=', 'USD')])
+ # curr = self.env['res.currency'].search([('name', '=', 'VND')])
+ # record.payable_usd = USD.compute(record.payable, curr)
+
+ status = fields.Selection(string='Status', selection=invoice_status_list, default='draft')
+ payment_status = fields.Selection(string='Payment Status', selection=payment_status_list, default='unpaid')
+
From 688c6f8dc38f5f05bf0b419243e6b1b4790a6c78 Mon Sep 17 00:00:00 2001
From: Toh Zhengfeng
Date: Mon, 25 Dec 2023 16:19:37 +0700
Subject: [PATCH 14/14] Added increments for invoice
---
local-addons/morons/models/invoice.py | 11 +++-
local-addons/morons/views/project.xml | 91 ++++++++++++++-------------
2 files changed, 59 insertions(+), 43 deletions(-)
diff --git a/local-addons/morons/models/invoice.py b/local-addons/morons/models/invoice.py
index 0de8988..6111098 100644
--- a/local-addons/morons/models/invoice.py
+++ b/local-addons/morons/models/invoice.py
@@ -59,10 +59,19 @@ class Invoice(models.Model):
("invoiced", "Invoiced"),
("paid", "Paid"),
]
+
+ invoice_id = fields.Char(string='Invoice ID', required=True, copy=False, readonly=True, index=True, default=lambda self: 'New')
+
+ @api.model
+ def create(self, vals):
+ if vals.get('invoice_id', 'New') == 'New':
+ vals['invoice_id'] = self.env['ir.sequence'].next_by_code('morons.invoice') or 'New'
+ result = super(Invoice, self).create(vals)
+ return result
issue_date = fields.Date(string='Issue Date')
due_date = fields.Date(string='Due Date')
- sender = fields.Char(string='Issued By')
+ sender = fields.Many2one('res.user',string='Issued By')
purchase_order = fields.Many2one('project.task', string='Purchase Order')
diff --git a/local-addons/morons/views/project.xml b/local-addons/morons/views/project.xml
index b95b754..47e2873 100644
--- a/local-addons/morons/views/project.xml
+++ b/local-addons/morons/views/project.xml
@@ -192,49 +192,69 @@
[('share', '=', False)]
+
+
+ Morons Invoice
+ morons.invoice
+ INV-
+ 5
+ 1
+
+
+
morons list
morons.invoice
-
+
+
+
+
morons list
morons.invoice
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Invoices
morons.invoice
@@ -248,9 +268,7 @@
-
+ action="action_open_invoice"/>
-
-
-
-
-
-
-