Add compute unit cost for BOM
This commit is contained in:
parent
81c84a8683
commit
bfcee95d57
|
@ -1,4 +1,4 @@
|
|||
Copyright (C) 2019 Oscar Alvarez
|
||||
Copyright (C) 2019-2023 Oscar Alvarez
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
2
INSTALL
2
INSTALL
|
@ -4,7 +4,7 @@ Installing trytond_production_accounting
|
|||
Prerequisites
|
||||
-------------
|
||||
|
||||
* Python 3.6 or later (http://www.python.org/)
|
||||
* Python 3.7 or later (http://www.python.org/)
|
||||
* trytond (http://www.tryton.org/)
|
||||
* trytond_company (http://www.tryton.org/)
|
||||
* trytond_party (http://www.tryton.org/)
|
||||
|
|
2
PKG-INFO
2
PKG-INFO
|
@ -1,6 +1,6 @@
|
|||
Metadata-Version: 1.0
|
||||
Name: trytond_production_accounting
|
||||
Version: 5.0.0
|
||||
Version: 6.0.0
|
||||
Summary: Tryton module creates account moves for production stock moves.
|
||||
Home-page: http://www.tryton.org/
|
||||
Author: Oscar Alvarez
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from decimal import Decimal
|
||||
|
||||
from trytond.pool import PoolMeta, Pool
|
||||
from trytond.pyson import Eval
|
||||
from trytond.model import fields
|
||||
from trytond.wizard import Wizard, StateTransition
|
||||
from trytond.pool import PoolMeta
|
||||
|
||||
|
||||
class Move(metaclass=PoolMeta):
|
||||
|
|
33
bom.py
33
bom.py
|
@ -1,4 +1,4 @@
|
|||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from decimal import Decimal
|
||||
from datetime import datetime, date
|
||||
|
@ -15,13 +15,15 @@ class BOM(metaclass=PoolMeta):
|
|||
|
||||
@classmethod
|
||||
def calc_cost_ldm(cls):
|
||||
# This method is temporal for CRON sync for a specific customer
|
||||
ProductLdm = Pool().get('production.bom')
|
||||
ProductLdmOut = Pool().get('production.bom.output')
|
||||
Product = Pool().get('product.product')
|
||||
Uom = Pool().get('product.uom')
|
||||
|
||||
current_date = datetime.combine(date.today(), datetime.min.time())
|
||||
products_ldm = [p['product'] for p in ProductLdmOut.search_read([], fields_names=['id', 'product'])]
|
||||
ldm_outs = ProductLdmOut.search_read([], fields_names=['id', 'product'])
|
||||
products_ldm = [p['product'] for p in ldm_outs]
|
||||
products = Product.search([
|
||||
('active', '=', True),
|
||||
('template.producible', '=', True),
|
||||
|
@ -38,22 +40,31 @@ class BOM(metaclass=PoolMeta):
|
|||
output = ldm.outputs[0]
|
||||
if not ldm.outputs or not ldm.inputs:
|
||||
continue
|
||||
cost = cls.get_cost_ldm(ldm, uom_compute_qty)
|
||||
cost = ldm.get_cost_ldm(uom_compute_qty)
|
||||
if cost > 0:
|
||||
cost = round(cost / Decimal(output.quantity), 4)
|
||||
Product.write([output.product], {'cost_price': cost})
|
||||
|
||||
@classmethod
|
||||
def get_cost_ldm(cls, ldm, uom_compute_qty):
|
||||
def compute_unit_cost(self):
|
||||
Product = Pool().get('product.product')
|
||||
total_cost = self.get_cost_ldm()
|
||||
for output in self.outputs:
|
||||
if output.quantity > 0:
|
||||
cost = round(total_cost / Decimal(output.quantity), 4)
|
||||
Product.write([output.product], {'cost_price': cost})
|
||||
|
||||
cost = Decimal(0)
|
||||
for input_ in ldm.inputs:
|
||||
quantity = uom_compute_qty(input_.uom, input_.quantity,
|
||||
input_.product.default_uom)
|
||||
def get_cost_ldm(self):
|
||||
Uom = Pool().get('product.uom')
|
||||
compute_qty = Uom.compute_qty
|
||||
res = []
|
||||
for input_ in self.inputs:
|
||||
quantity = compute_qty(
|
||||
input_.uom, input_.quantity,
|
||||
input_.product.default_uom)
|
||||
cost_price = input_.product.cost_price
|
||||
cost += (Decimal(str(quantity)) * cost_price)
|
||||
res.append(Decimal(str(quantity)) * cost_price)
|
||||
|
||||
return round_price(cost)
|
||||
return round_price(sum(res))
|
||||
|
||||
|
||||
class BOMDirectCost(ModelSQL, ModelView):
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from trytond.pool import PoolMeta
|
||||
from trytond.model import fields
|
||||
|
|
3
ir.py
3
ir.py
|
@ -1,3 +1,6 @@
|
|||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
from trytond.pool import PoolMeta
|
||||
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ class Production(metaclass=PoolMeta):
|
|||
if not total_cost and self.cost:
|
||||
total_cost = self.cost
|
||||
|
||||
ouput = self.outputs[0]
|
||||
# ouput = self.outputs[0]
|
||||
new_cost_price = round_dec(total_cost / Decimal(self.quantity))
|
||||
return new_cost_price
|
||||
|
||||
|
@ -152,15 +152,15 @@ class Production(metaclass=PoolMeta):
|
|||
for input in rec.inputs:
|
||||
account_id = input.product.account_expense_used.id
|
||||
amount = input.product.cost_price * Decimal(input.quantity)
|
||||
_line = {
|
||||
line = {
|
||||
'description': input.product.rec_name,
|
||||
'account': account_id,
|
||||
'debit': 0,
|
||||
'credit': amount,
|
||||
}
|
||||
cost_production.append(amount)
|
||||
cls.set_analytic_lines(_line, date_, rec.analytic_account_materials)
|
||||
lines.append(_line)
|
||||
cls.set_analytic_lines(line, date_, rec.analytic_account_materials)
|
||||
lines.append(line)
|
||||
|
||||
account_id = None
|
||||
for cost in rec.costs:
|
||||
|
@ -188,7 +188,6 @@ class Production(metaclass=PoolMeta):
|
|||
def get_consumption_lines(cls, inputs, factor, date_, args=None):
|
||||
""" Get Consumption Account Move Lines """
|
||||
lines = []
|
||||
# balance = []
|
||||
costs_lines = {}
|
||||
for _in in inputs:
|
||||
product = _in.product
|
||||
|
@ -210,7 +209,6 @@ class Production(metaclass=PoolMeta):
|
|||
'credit': credit
|
||||
}
|
||||
lines.append(_line)
|
||||
# balance.append(credit)
|
||||
account_expense_id = category.account_expense.id
|
||||
try:
|
||||
costs_lines[account_expense_id].append(credit)
|
||||
|
@ -340,7 +338,8 @@ class Production(metaclass=PoolMeta):
|
|||
res.append(Decimal(quantity) * cost_price)
|
||||
self.material_costs = sum(res)
|
||||
|
||||
@fields.depends('costs', 'indirect_costs', 'services_costs', 'labour_costs')
|
||||
@fields.depends(
|
||||
'costs', 'indirect_costs', 'services_costs', 'labour_costs')
|
||||
def on_change_costs(self, name=None):
|
||||
indirect_costs = []
|
||||
services_costs = []
|
||||
|
@ -440,7 +439,8 @@ class ProcessProductionAsyncStart(ModelView):
|
|||
class ProcessProductionAsync(Wizard):
|
||||
'Process Production Async'
|
||||
__name__ = 'production.process_production_async'
|
||||
start = StateView('production.process_production_async.start',
|
||||
start = StateView(
|
||||
'production.process_production_async.start',
|
||||
'production_accounting.process_production_async_start_view_form', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Ok', 'accept', 'tryton-ok', default=True),
|
||||
|
@ -456,11 +456,17 @@ class ProcessProductionAsync(Wizard):
|
|||
'state': 'draft',
|
||||
'lines': [('create', lines)],
|
||||
'description': '',
|
||||
# 'origin': ,
|
||||
}])
|
||||
Move.post([move])
|
||||
print('Asiento creado No ', move.number)
|
||||
|
||||
def update_product_cost(self, producibles):
|
||||
print('Actualizando update product cost')
|
||||
for product, value in producibles.items():
|
||||
cost = value['bom'].compute_unit_cost(value['quantity'])
|
||||
product.average_cost = cost
|
||||
product.save()
|
||||
|
||||
def create_stock_moves(self, producibles):
|
||||
Move = Pool().get('stock.move')
|
||||
date_ = self.start.date
|
||||
|
@ -589,7 +595,6 @@ class ProcessProductionAsync(Wizard):
|
|||
def transition_accept(self):
|
||||
pool = Pool()
|
||||
SaleLine = pool.get('sale.line')
|
||||
# Shop = pool.get('sale.shop')
|
||||
Period = pool.get('account.period')
|
||||
Journal = pool.get('account.journal')
|
||||
Configuration = pool.get('production.configuration')
|
||||
|
@ -617,7 +622,6 @@ class ProcessProductionAsync(Wizard):
|
|||
if not lines:
|
||||
return 'end'
|
||||
|
||||
# shop = Shop(self.start.shop.id)
|
||||
producibles = {}
|
||||
|
||||
for line in lines:
|
||||
|
@ -637,6 +641,8 @@ class ProcessProductionAsync(Wizard):
|
|||
}
|
||||
if configuration.production_accounting:
|
||||
self.create_production_moves(producibles, journal, period_id)
|
||||
|
||||
self.update_product_cost(producibles)
|
||||
self.create_stock_moves(producibles)
|
||||
SaleLine.write(lines, {'produced': True})
|
||||
return 'end'
|
||||
|
@ -668,7 +674,8 @@ class ProductionDetailedStart(ModelView):
|
|||
class ProductionDetailed(Wizard):
|
||||
'Production Detailed'
|
||||
__name__ = 'production.detailed'
|
||||
start = StateView('production.detailed.start',
|
||||
start = StateView(
|
||||
'production.detailed.start',
|
||||
'production_accounting.production_detailed_start_view_form', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Print', 'print_', 'tryton-ok', default=True),
|
||||
|
|
13
sale.py
13
sale.py
|
@ -1,17 +1,8 @@
|
|||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from datetime import timedelta, date
|
||||
from itertools import chain
|
||||
from sql import Table
|
||||
from decimal import Decimal
|
||||
|
||||
from trytond.model import fields, ModelSQL, ModelView
|
||||
from trytond.model import fields
|
||||
from trytond.pool import PoolMeta
|
||||
# from trytond.pyson import Eval
|
||||
# from trytond.transaction import Transaction
|
||||
# from trytond.exceptions import UserError
|
||||
# from trytond.report import Report
|
||||
# from trytond.wizard import Wizard, StateView, Button, StateTransition, StateReport
|
||||
|
||||
|
||||
class SaleLine(metaclass=PoolMeta):
|
||||
|
|
2
stock.py
2
stock.py
|
@ -1,4 +1,4 @@
|
|||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
from trytond.pool import PoolMeta
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[tryton]
|
||||
version=6.0.6
|
||||
version=6.0.7
|
||||
depends:
|
||||
party
|
||||
company
|
||||
|
|
Loading…
Reference in New Issue