diff --git a/custom_addons/costing_mrp_bom/__manifest__.py b/custom_addons/costing_mrp_bom/__manifest__.py
index d2ffd54db..8dc7641dc 100644
--- a/custom_addons/costing_mrp_bom/__manifest__.py
+++ b/custom_addons/costing_mrp_bom/__manifest__.py
@@ -6,7 +6,7 @@
'description': """ BOM Cost """,
'author': 'Raman Marikanti',
'category': 'Manufacturing',
- 'depends': ['sale_management', 'mrp','stock'],
+ 'depends': ['sale_management', 'mrp','stock',],
'data': [
"views/bom_view.xml",
"report/mrp_costing_report.xml",
diff --git a/custom_addons/costing_mrp_bom/models/sale_order_line.py b/custom_addons/costing_mrp_bom/models/sale_order_line.py
index 0a5356ea1..3c3e498f8 100644
--- a/custom_addons/costing_mrp_bom/models/sale_order_line.py
+++ b/custom_addons/costing_mrp_bom/models/sale_order_line.py
@@ -4,13 +4,98 @@ from odoo.tools import float_round
from odoo.exceptions import ValidationError
+
+class SaleOrderInherit(models.Model):
+ _inherit = 'sale.order'
+
+ freight_charges = fields.Monetary(string='Freight', readonly=False)
+ total_production_cost = fields.Monetary(string="Total Production Cost", readonly=True, compute="_compute_purchase_price", precompute=True)
+
+ @api.depends('freight_charges', 'order_line')
+ def _compute_purchase_price(self):
+ for order in self:
+ production_cost = 0
+ for line in order.order_line:
+ production_cost += line.purchase_price * line.product_uom_qty
+ order.total_production_cost = production_cost + order.freight_charges
+
+
+
+#
+# class AccountMoveInherit(models.Model):
+# _inherit = 'account.move'
+#
+# freight_charges = fields.Monetary(string='Freight Charges', readonly=False, store=True,
+# compute='_compute_freight_charges_amount')
+#
+# @api.onchange('freight_charges')
+# @api.depends(
+# 'invoice_line_ids.currency_rate',
+# 'invoice_line_ids.tax_base_amount',
+# 'invoice_line_ids.tax_line_id',
+# 'invoice_line_ids.price_total',
+# 'invoice_line_ids.price_subtotal',
+# 'invoice_payment_term_id',
+# 'partner_id',
+# 'currency_id',
+# )
+# def _compute_tax_totals(self):
+# """ Computed field used for custom widget's rendering.
+# Only set on invoices.
+# """
+# res = super()._compute_tax_totals()
+# for order in self:
+# order.tax_totals['subtotals'][0]['base_amount'] += order.freight_charges
+# order.tax_totals['subtotals'][0]['base_amount_currency'] += order.freight_charges
+# order.tax_totals['base_amount'] += order.freight_charges
+# order.tax_totals['base_amount_currency'] += order.freight_charges
+# order.tax_totals['total_amount'] += order.freight_charges
+# order.tax_totals['total_amount_currency'] += order.freight_charges
+# return res
+
+
class SaleOrderLine(models.Model):
_inherit = 'sale.order.line'
- unit_prod_cost = fields.Float('Unit Prodcut Cost',digits="Product Unit of Measure")
- @api.depends('product_id')
- def _compute_unit_prod_cost(self):
+ purchase_price = fields.Float(
+ string="Cost", compute="_compute_purchase_price",
+ digits='Product Price', store=True, readonly=False, copy=False, precompute=True,
+ groups="base.group_user")
+
+ bag_weight = fields.Float(
+ string="Weight", compute="_compute_bag_weight",
+ digits='Product Price', store=True, readonly=False, precompute=True,
+ groups="base.group_user")
+
+ @api.depends('product_id', 'company_id', 'product_uom')
+ def _compute_bag_weight(self):
for line in self:
- line.unit_prod_cost = line.product_id.standard_price
+ line.bag_weight = line.product_id.weight * line.product_uom_qty
+
+ @api.depends('product_id', 'company_id', 'currency_id', 'product_uom')
+ def _compute_purchase_price(self):
+ for line in self:
+ if not line.product_id:
+ line.purchase_price = 0.0
+ continue
+ line = line.with_company(line.company_id)
+
+ # Convert the cost to the line UoM
+ product_cost = line.product_id.uom_id._compute_price(
+ line.product_id.standard_price,
+ line.product_uom,
+ )
+
+ line.purchase_price = line._convert_to_sol_currency(
+ product_cost,
+ line.product_id.cost_currency_id)
+
+
+
+ @api.depends('product_id', 'product_uom', 'product_uom_qty')
+ def _compute_price_unit(self):
+ for line in self:
+ line.price_unit = 0.0
+
diff --git a/custom_addons/costing_mrp_bom/views/bom_view.xml b/custom_addons/costing_mrp_bom/views/bom_view.xml
index b5d0996a5..bc465b96f 100644
--- a/custom_addons/costing_mrp_bom/views/bom_view.xml
+++ b/custom_addons/costing_mrp_bom/views/bom_view.xml
@@ -14,6 +14,47 @@
+
+
+
+ sale.order.form.inherit
+ sale.order
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
mrp.production.inherited.form.decoration
mrp.production
diff --git a/custom_addons/dashboard/__manifest__.py b/custom_addons/dashboard/__manifest__.py
index 27e1d6985..f7141f8d8 100644
--- a/custom_addons/dashboard/__manifest__.py
+++ b/custom_addons/dashboard/__manifest__.py
@@ -2,6 +2,7 @@
'name': 'Samashti Dashboard (OWL)',
'version': '1.0',
'category': 'View',
+ 'license': 'LGPL-3',
'summary': 'Samashti Dashboard (OWL + pqGrid)',
'author': 'Raman Marikanti',
'depends': ['stock', 'web_grid','costing_mrp_bom'],
diff --git a/custom_addons/dashboard/models/stock_dashboard.py b/custom_addons/dashboard/models/stock_dashboard.py
index fc9313746..bdced02e0 100644
--- a/custom_addons/dashboard/models/stock_dashboard.py
+++ b/custom_addons/dashboard/models/stock_dashboard.py
@@ -112,6 +112,39 @@ class SamashtiDashboard(models.AbstractModel):
def get_sale_margin_data(self,from_date,to_date):
fromDate = "'"+str(from_date)+" 00:00:00'"
toDate = "'"+str(to_date)+" 23:59:59'"
+ datas = []
+
+ sale_orders = self.env['sale.order'].search_read(
+ [
+ ('state', '=', 'sale'),
+ ('date_order', '>=', fromDate),
+ ('date_order', '<=', toDate)
+ ],
+ ['id', 'name', 'amount_total', 'partner_id', 'total_production_cost','date_order']
+ )
+
+ for r in sale_orders:
+ cost = r['total_production_cost']
+ sale_price = r['amount_total']
+ margin = sale_price - cost
+ margin_percent = (margin / sale_price * 100) if sale_price else 0.0
+ customer = r['partner_id'][-1]
+ quantity = sum(self.env['sale.order'].browse(r['id']).order_line.mapped('product_uom_qty'))
+ weight = str(sum(self.env['sale.order'].browse(r['id']).order_line.mapped('bag_weight')))+" kg"
+
+ datas.append({
+ 'sale_order': r['name'],
+ 'weight':weight,
+ 'customer':customer,
+ 'quantity':quantity,
+ 'cost': cost,
+ 'date':r['date_order'],
+ 'sale_price': sale_price,
+ 'margin': margin,
+ 'margin_percent':margin_percent
+ })
+ return datas
+
where_caluse = f" AND so.date_order BETWEEN {fromDate} AND {toDate}"
sql = """
SELECT
@@ -152,3 +185,17 @@ class SamashtiDashboard(models.AbstractModel):
else:
return []
+ def _get_production_cost(self, sale_order_id):
+ sale_order = self.env['sale.order'].browse(sale_order_id)
+ cost = 0.0
+ for line in sale_order.order_line.filtered(lambda l: l.product_id.type == 'consu'):
+ line_cost = line.purchase_price or 0
+ cost += line_cost * line.product_uom_qty
+
+ for line in sale_order.order_line.filtered(lambda l: l.product_id.type == 'service' and l.price_total > 0):
+ cost += line.price_total
+
+ return cost
+
+
+
diff --git a/custom_addons/dashboard/static/src/components/pqgrid_dashboard/pqgrid_stock_dashboard.js b/custom_addons/dashboard/static/src/components/pqgrid_dashboard/pqgrid_stock_dashboard.js
index d7227e9d0..ace0d611b 100644
--- a/custom_addons/dashboard/static/src/components/pqgrid_dashboard/pqgrid_stock_dashboard.js
+++ b/custom_addons/dashboard/static/src/components/pqgrid_dashboard/pqgrid_stock_dashboard.js
@@ -172,16 +172,14 @@ export class SamashtiDashboard extends Component {
async getSaleColumns(){
return[
{ title: "Sale Order", dataIndx: "sale_order", width: 100,filter: { type: 'textbox', condition: 'contain', listeners: ['keyup'] } },
- { title: "Product Code", dataIndx: "product_code", width: 100,filter: { type: 'textbox', condition: 'contain', listeners: ['keyup'] } },
- { title: "Product Name", dataIndx: "product_name", width: 280,filter: { type: 'textbox', condition: 'contain', listeners: ['keyup'] } },
- { title: "Category", dataIndx: "category", width: 150 },
+ { title: "Customer", dataIndx: "customer", width: 280,filter: { type: 'textbox', condition: 'contain', listeners: ['keyup'] } },
+ { title: "Date", dataIndx: "date", width: 150 },
{ title: "Quantity", dataIndx: "quantity", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
- { title: "Unit Cost", dataIndx: "unit_cost", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
- { title: "Unit Sale Price", dataIndx: "unit_sale_price", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
- { title: "Unit Margin", dataIndx: "margin", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
- { title: "Total Cost", dataIndx: "total_cost", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
- { title: "Total Sale Price", dataIndx: "total_sale_price", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
- { title: "Total Margin", dataIndx: "total_margin", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
+ { title: "Weight", dataIndx: "weight", width: 150 },
+ { title: "Production Cost", dataIndx: "cost", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
+ { title: "Sale Price", dataIndx: "sale_price", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
+ { title: "Margin", dataIndx: "margin", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
+ { title: "Margin %", dataIndx: "margin_percent", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
]
}
diff --git a/custom_addons/fixed_asset_management/__init__.py b/custom_addons/fixed_asset_management/__init__.py
new file mode 100644
index 000000000..9a7e03ede
--- /dev/null
+++ b/custom_addons/fixed_asset_management/__init__.py
@@ -0,0 +1 @@
+from . import models
\ No newline at end of file
diff --git a/custom_addons/fixed_asset_management/__manifest__.py b/custom_addons/fixed_asset_management/__manifest__.py
new file mode 100644
index 000000000..102f9e41f
--- /dev/null
+++ b/custom_addons/fixed_asset_management/__manifest__.py
@@ -0,0 +1,22 @@
+{
+ 'name': 'Asset Management',
+ 'version': '18.0',
+ 'category': 'Documents',
+ 'summary': 'Fixed Asset Management',
+ 'author': 'Raman Marikanti',
+ 'depends': ['mail', 'base'],
+
+ 'data': [
+ 'data/ir_sequence.xml',
+ 'views/asset_category_view.xml',
+ 'views/asset_detail_view.xml',
+ 'views/asset_location_view.xml',
+ 'views/asset_move_view.xml',
+ 'security/ir.model.access.csv',
+ ],
+
+ 'license': 'LGPL-3',
+ 'installable': True,
+ 'application': True,
+ 'auto_install': False,
+}
diff --git a/custom_addons/fixed_asset_management/data/ir_sequence.xml b/custom_addons/fixed_asset_management/data/ir_sequence.xml
new file mode 100644
index 000000000..ba83a09ed
--- /dev/null
+++ b/custom_addons/fixed_asset_management/data/ir_sequence.xml
@@ -0,0 +1,18 @@
+
+
+
+ Asset Move
+ asset.move
+ MOV/%(range_year)s/
+ 5
+
+
+
+ Asset Detail
+ asset.detail
+ AST/%(range_year)s/
+ 5
+
+
+
+
\ No newline at end of file
diff --git a/custom_addons/fixed_asset_management/models/__init__.py b/custom_addons/fixed_asset_management/models/__init__.py
new file mode 100644
index 000000000..4159d86ed
--- /dev/null
+++ b/custom_addons/fixed_asset_management/models/__init__.py
@@ -0,0 +1,4 @@
+from . import asset_detail
+from . import asset_move
+from . import asset_location
+from . import asset_category
\ No newline at end of file
diff --git a/custom_addons/fixed_asset_management/models/asset_category.py b/custom_addons/fixed_asset_management/models/asset_category.py
new file mode 100644
index 000000000..cf467e580
--- /dev/null
+++ b/custom_addons/fixed_asset_management/models/asset_category.py
@@ -0,0 +1,8 @@
+from odoo import fields, models, api
+
+
+class AssetCategory(models.Model):
+ _name = "asset.category"
+ _description = "Asset Category"
+
+ name = fields.Char(string="Name")
\ No newline at end of file
diff --git a/custom_addons/fixed_asset_management/models/asset_detail.py b/custom_addons/fixed_asset_management/models/asset_detail.py
new file mode 100644
index 000000000..397211c93
--- /dev/null
+++ b/custom_addons/fixed_asset_management/models/asset_detail.py
@@ -0,0 +1,40 @@
+from odoo import fields, models, api
+from datetime import datetime
+
+
+class AssetDetail(models.Model):
+ _name = "asset.detail"
+ _description = "Asset Detail"
+
+ name = fields.Char(string="Name")
+ asset_image = fields.Binary(string="Image")
+ category_id = fields.Many2one(comodel_name="asset.category", string="Category")
+ asset_code = fields.Char(string="Asset Code")
+ asset_model = fields.Char(string="Asset Model")
+ serial_no = fields.Char(string="Serial No.")
+ purchase_date = fields.Date(string="Purchase Date")
+ purchase_value = fields.Float(string="Purchase Value")
+ location_id = fields.Many2one(comodel_name="asset.location", string="Current Location")
+ # employee_id = fields.Many2one(comodel_name="hr.employee", string="Employee")
+ vendor_id = fields.Many2one(comodel_name="res.partner", string="Vendor")
+ warranty_start = fields.Date(string="Warranty Start")
+ warranty_end = fields.Date(string="Warranty End")
+ note = fields.Html(string="Note")
+ state = fields.Selection([('draft', 'New'), ('active', 'Active'), ('scrap', 'Scrap')], string='State', default="draft")
+
+ @api.model
+ def create(self, vals):
+ location_id = self.env["asset.location"].search([("is_default", "=", True)], limit=1)
+ vals["asset_code"] = self.env["ir.sequence"].next_by_code("asset.detail", sequence_date=datetime.now().year) or "New"
+ vals["location_id"] = location_id.id if location_id else None
+ return super(AssetDetail, self).create(vals)
+
+ def scrap_asset(self):
+ for asset_id in self:
+ location_id = self.env["asset.location"].search([("is_scrap", "=", True)], limit=1)
+ if location_id:
+ asset_id.state = "scrap"
+
+ def confirm_asset(self):
+ for asset_id in self:
+ asset_id.state = "active"
\ No newline at end of file
diff --git a/custom_addons/fixed_asset_management/models/asset_location.py b/custom_addons/fixed_asset_management/models/asset_location.py
new file mode 100644
index 000000000..bab62a4cd
--- /dev/null
+++ b/custom_addons/fixed_asset_management/models/asset_location.py
@@ -0,0 +1,12 @@
+from odoo import fields, models, api
+
+
+class AssetLocation(models.Model):
+ _name = "asset.location"
+ _description = "Asset Location"
+
+ name = fields.Char(string="Name")
+ is_default = fields.Boolean(string="Default")
+ is_scrap = fields.Boolean(string="Scrap")
+ asset_line = fields.One2many(comodel_name="asset.detail", inverse_name="location_id")
+
diff --git a/custom_addons/fixed_asset_management/models/asset_move.py b/custom_addons/fixed_asset_management/models/asset_move.py
new file mode 100644
index 000000000..8c274ad08
--- /dev/null
+++ b/custom_addons/fixed_asset_management/models/asset_move.py
@@ -0,0 +1,31 @@
+from odoo import fields, models, api
+from datetime import datetime
+
+
+class AssetMove(models.Model):
+ _name = "asset.move"
+ _description = "Asset Move"
+
+ name = fields.Char(string="Name")
+ location_id = fields.Many2one(comodel_name="asset.location", string="Source Location")
+ location_dest_id = fields.Many2one(comodel_name="asset.location", string="Destination Location")
+ asset_id = fields.Many2one(comodel_name="asset.detail", string="Asset")
+ state = fields.Selection([('draft', 'Draft'),('done', 'Done'),('cancel', 'Cancel')], string='State', default="draft")
+
+ @api.model
+ def create(self, vals):
+ vals["name"] = self.env["ir.sequence"].next_by_code("asset.move", sequence_date=datetime.now().year) or "New"
+ return super(AssetMove, self).create(vals)
+
+ @api.onchange("asset_id")
+ def onchange_asset(self):
+ self.location_id = self.asset_id.location_id.id
+
+ def move_asset(self):
+ for asset_id in self:
+ asset_id.asset_id.location_id = asset_id.location_dest_id.id
+ asset_id.state = "done"
+
+ def cancel_move(self):
+ for asset_id in self:
+ asset_id.state = "cancel"
\ No newline at end of file
diff --git a/custom_addons/fixed_asset_management/security/ir.model.access.csv b/custom_addons/fixed_asset_management/security/ir.model.access.csv
new file mode 100644
index 000000000..ea487de68
--- /dev/null
+++ b/custom_addons/fixed_asset_management/security/ir.model.access.csv
@@ -0,0 +1,5 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+asset_category,asset.category,model_asset_category,,1,1,1,1
+asset_detail,asset.detail,model_asset_detail,,1,1,1,1
+asset_location,asset.location,model_asset_location,,1,1,1,1
+asset_move,asset.move,model_asset_move,,1,1,1,1
\ No newline at end of file
diff --git a/custom_addons/fixed_asset_management/static/description/icon.png b/custom_addons/fixed_asset_management/static/description/icon.png
new file mode 100644
index 000000000..231a4fbd0
--- /dev/null
+++ b/custom_addons/fixed_asset_management/static/description/icon.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:31255c2b3d454708d62a118e2a9b9e7526670ad0f5774acec8fb83db71d6b8fc
+size 43161
diff --git a/custom_addons/fixed_asset_management/views/asset_category_view.xml b/custom_addons/fixed_asset_management/views/asset_category_view.xml
new file mode 100644
index 000000000..5ed29ed97
--- /dev/null
+++ b/custom_addons/fixed_asset_management/views/asset_category_view.xml
@@ -0,0 +1,19 @@
+
+
+ Asset Category
+ asset.category
+
+
+
+
+
+
+
+ Asset Category
+ asset.category
+ list
+
+
+
+
+
\ No newline at end of file
diff --git a/custom_addons/fixed_asset_management/views/asset_detail_view.xml b/custom_addons/fixed_asset_management/views/asset_detail_view.xml
new file mode 100644
index 000000000..4e755786b
--- /dev/null
+++ b/custom_addons/fixed_asset_management/views/asset_detail_view.xml
@@ -0,0 +1,68 @@
+
+
+ asset.detail.list.view
+ asset.detail
+
+
+
+
+
+
+
+
+
+
+
+ asset.detail.form.view
+ asset.detail
+
+
+
+
+
+ Assets
+ asset.detail
+ list,form
+
+
+
+
diff --git a/custom_addons/fixed_asset_management/views/asset_location_view.xml b/custom_addons/fixed_asset_management/views/asset_location_view.xml
new file mode 100644
index 000000000..a6946099f
--- /dev/null
+++ b/custom_addons/fixed_asset_management/views/asset_location_view.xml
@@ -0,0 +1,53 @@
+
+
+ Asset Location
+ asset.location
+
+
+
+
+
+
+
+
+
+ asset.location.form.view
+ asset.location
+
+
+
+
+
+ Asset Location
+ asset.location
+ list,form
+
+
+
diff --git a/custom_addons/fixed_asset_management/views/asset_move_view.xml b/custom_addons/fixed_asset_management/views/asset_move_view.xml
new file mode 100644
index 000000000..70eab5ad2
--- /dev/null
+++ b/custom_addons/fixed_asset_management/views/asset_move_view.xml
@@ -0,0 +1,45 @@
+
+
+ asset.move.list.view
+ asset.move
+
+
+
+
+
+
+
+
+
+
+
+ asset.move.form.view
+ asset.move
+
+
+
+
+
+ Asset Move
+ asset.move
+ list,form
+
+
+
diff --git a/custom_addons/grn/models/grn.py b/custom_addons/grn/models/grn.py
index e4cf4b886..6a315c7e0 100644
--- a/custom_addons/grn/models/grn.py
+++ b/custom_addons/grn/models/grn.py
@@ -4,6 +4,7 @@ from email.policy import default
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError, UserError
+
class Grn(models.Model):
_name = 'grn'
_description = 'Goods Receipt Note'
@@ -44,8 +45,36 @@ class Grn(models.Model):
def _get_product_catalog_order_data(self, products, **kwargs):
res = super()._get_product_catalog_order_data(products, **kwargs)
+ for product in products:
+ res[product.id] |= {
+ 'price': product.standard_price,
+ }
return res
+ def _get_product_catalog_domain(self):
+ """Get the domain to search for products in the catalog.
+ """
+ domain = [('company_id', 'in', [self.company_id.id, False]), ('type', '=', 'consu'), ('purchase_ok', '=', True)]
+ return domain
+
+ def _update_order_line_info(self, product_id, quantity, **kwargs):
+ self.ensure_one()
+ pol = self.grn_line_ids.filtered(lambda line: line.product_id.id == product_id)
+ if pol:
+ if quantity != 0:
+ pol.quantity = quantity
+ else:
+ pol.unlink()
+ elif quantity > 0:
+ pol = self.env['grn.lines'].create({
+ 'grn_id': self.id,
+ 'product_id': product_id,
+ 'quantity': quantity,
+ })
+ else:
+ pass
+ return 0
+
@api.depends('grn_line_ids')
def _compute_total_amount(self):
"""Compute the value of the field computed_field."""
@@ -55,8 +84,12 @@ class Grn(models.Model):
amount += (line.quantity * line.price)
record.total_amount = amount
-
-
+ def _get_product_catalog_lines_data(self):
+ catalog_info = {
+ 'quantity': self.quantity,
+ 'price': self.product_id.standard_price,
+ }
+ return catalog_info
def button_action_confirm(self):
"""Confirm the GRN and assign sequence and received user"""
@@ -122,7 +155,7 @@ class Grn(models.Model):
'location_dest_id': self.location_id.id,
'location_id': picking_type.default_location_src_id.id,
'picking_type_id': picking_type.id,
- 'partner_id':self.vendor_id.id
+ 'partner_id': self.vendor_id.id
})
moves = []
@@ -140,7 +173,7 @@ class Grn(models.Model):
picking.action_confirm()
for move in picking:
move.location_dest_id = self.location_id
- picking.location_dest_id = self.location_id
+ picking.location_dest_id = self.location_id
self.picking_id = picking
def action_view_transfer(self):
@@ -155,7 +188,6 @@ class Grn(models.Model):
'res_id': self.picking_id.id,
}
-
@api.model_create_multi
def create(self, vals_list):
return super().create(vals_list)
@@ -170,10 +202,6 @@ class Grn(models.Model):
) % self.name)
return super().unlink()
- def action_add_from_catalog(self):
- res = super().action_add_from_catalog()
- return res
-
class GrnLines(models.Model):
_name = 'grn.lines'
@@ -184,7 +212,7 @@ class GrnLines(models.Model):
'product.product',
string='Product',
ondelete="cascade",
- domain=[('type', '!=', 'service'),('purchase_ok','=',True)],
+ domain=[('type', '!=', 'service'), ('purchase_ok', '=', True)],
index=True
)
product_uom_id = fields.Many2one(related='product_id.uom_id', string='Unit of Measure')
@@ -204,13 +232,10 @@ class GrnLines(models.Model):
if len(duplicate_lines) > 1:
raise UserError(_('The product %s already exists in the GRN.') % rec.product_id.display_name)
-
def action_add_from_catalog(self):
order = self.env['grn'].browse(self.env.context.get('order_id'))
return order.with_context(child_field='grn_line_ids').action_add_from_catalog()
-
-
def unlink(self):
if any(rec.grn_id.state not in ['cancel', 'draft'] for rec in self):
raise UserError(_(
diff --git a/custom_addons/grn/views/grn_views.xml b/custom_addons/grn/views/grn_views.xml
index 82f8e74ce..04a36c261 100644
--- a/custom_addons/grn/views/grn_views.xml
+++ b/custom_addons/grn/views/grn_views.xml
@@ -33,9 +33,11 @@
+
+
+
-
diff --git a/custom_addons/grn_purchase/__init__.py b/custom_addons/grn_purchase/__init__.py
new file mode 100644
index 000000000..5305644df
--- /dev/null
+++ b/custom_addons/grn_purchase/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+from . import models
\ No newline at end of file
diff --git a/custom_addons/grn_purchase/__manifest__.py b/custom_addons/grn_purchase/__manifest__.py
new file mode 100644
index 000000000..e0dd50da1
--- /dev/null
+++ b/custom_addons/grn_purchase/__manifest__.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+{
+ 'name': 'Grn Purchase',
+ 'version': '1.0',
+ 'summary': 'GRN LINK WITH Purchase',
+ 'description': '''
+ Detailed description of the module
+ ''',
+ 'category': 'Purchase',
+ 'author': 'Raman Marikanti',
+ 'depends': ['base', 'mail', 'grn','purchase'],
+ 'data': [
+ # 'security/ir.model.access.csv',
+ 'views/grn_purchase_views.xml',
+ ],
+ 'license': 'LGPL-3',
+ 'installable': True,
+ 'application': False,
+ 'auto_install': False,
+}
\ No newline at end of file
diff --git a/custom_addons/grn_purchase/models/__init__.py b/custom_addons/grn_purchase/models/__init__.py
new file mode 100644
index 000000000..22b643d49
--- /dev/null
+++ b/custom_addons/grn_purchase/models/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+from . import grn_purchase
\ No newline at end of file
diff --git a/custom_addons/grn_purchase/models/grn_purchase.py b/custom_addons/grn_purchase/models/grn_purchase.py
new file mode 100644
index 000000000..8130fdf8a
--- /dev/null
+++ b/custom_addons/grn_purchase/models/grn_purchase.py
@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*-
+
+from odoo import _,api, fields, models
+
+
+class StockPicking(models.Model):
+ _inherit = 'stock.picking'
+
+
+ def _action_done(self):
+ res = super(StockPicking, self)._action_done()
+ for rec in self:
+ if rec.purchase_id and rec.picking_type_id.code == 'incoming':
+ grn = self.env['grn'].search([('picking_id','=', rec.id)])
+ if not grn:
+ grn_data = {
+ 'vendor_id':rec.partner_id.id,
+ 'date':fields.Datetime.now(),
+ 'location_id':rec.location_dest_id.id,
+ 'note':rec.purchase_id.name,
+ 'grn_line_ids':[]
+ }
+ for line in rec.move_ids.filtered(lambda x:x.product_id.type == 'consu'):
+ grn_data['grn_line_ids'].append((0,0,{
+ 'product_id':line.product_id.id,
+ 'quantity':line.quantity,
+ 'product_uom_id':line.product_id.uom_id.id,
+ 'price':line.price_unit,
+ }))
+ new_grn = self.env['grn'].create(grn_data)
+ new_grn.name = self.env['ir.sequence'].next_by_code('grn') or _('New')
+ new_grn.picking_id = rec
+ new_grn.state = 'done'
+ rec.purchase_id.grn_ids |= new_grn
+ elif grn and grn.state != 'done':
+ grn.state = 'done'
+ return res
+
+
+
+class PurchaseOrder(models.Model):
+ _inherit = "purchase.order"
+
+ grn_ids = fields.Many2many('grn', string="GRN")
+ grn_count = fields.Integer('GRN Count', compute='_compute_grn_count')
+
+ @api.depends('grn_ids')
+ def _compute_grn_count(self):
+ self.grn_count = len(self.grn_ids)
+
+ def action_show_grn_ids(self):
+ action = self.env['ir.actions.actions']._for_xml_id('grn.grn_action')
+ action['domain'] = [('id', 'in', self.grn_ids.ids)]
+ action['context'] = {}
+ return action
\ No newline at end of file
diff --git a/custom_addons/grn_purchase/security/ir.model.access.csv b/custom_addons/grn_purchase/security/ir.model.access.csv
new file mode 100644
index 000000000..97dd8b917
--- /dev/null
+++ b/custom_addons/grn_purchase/security/ir.model.access.csv
@@ -0,0 +1 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
diff --git a/custom_addons/grn_purchase/views/grn_purchase_views.xml b/custom_addons/grn_purchase/views/grn_purchase_views.xml
new file mode 100644
index 000000000..55efa1c5a
--- /dev/null
+++ b/custom_addons/grn_purchase/views/grn_purchase_views.xml
@@ -0,0 +1,20 @@
+
+
+
+
+ purchase.order.inherited.form.grn
+ purchase.order
+
+
+
+
+
+
+
+
+
\ No newline at end of file