Code:
from osv import osv, fields
import time, datetime
import datetime
import netsvc
import ir
from mx import DateTime
import pooler
from tools import config
from construction.construction import *
class construction_purchase(osv.osv):
_name = 'construction.purchase'
_description = 'Purchase Order'
def _total_amount(self, cr, uid, ids, field_name, arg, context):
#
#print "Domain:", self.pool.get('ir.rule').domain_get(cr, uid, 'Confirmed Purchase Orders')
res = {}
for f in self.browse(cr, uid, ids):
res[f.id] = 0.0
for line in f.purchase_line:
res[f.id] += line.amount
res[f.id] = round(res[f.id] / 0.01) * 0.01
return res
def _is_due(self, cr, uid, ids, field_name, arg, context):
now = DateTime.now()
res = {}
for f in self.browse(cr, uid, ids):
due = DateTime.strptime(f.due_date, '%Y-%m-%d')
#print now, due
if now > due:
res[f.id] = True
else:
res[f.id] = False
return res
def _balance(self, cr, uid, ids, field_name, arg, context):
res = {}
for f in self.browse(cr, uid, ids):
res[f.id] = f.amount - f.paid_amount
return res
_columns = {
'category': fields.selection(
(
('labor', 'Labor'),
('material', 'Material'),
),
'Category', required=True, change_default=True),
'name' : fields.char('Number / Reference',
size=100,
required=True,
readonly=True,
select=1,
states={
'draft':[('readonly',False)]
}),
'date_ordered':fields.date('Order Date',
required=True,
readonly=True,
states={
'draft':[('readonly',False)],
}),
'supplier_id':fields.many2one('construction.suppliers', 'Supplier',
required=True,
readonly=True,
select=1,
states={
'draft':[('readonly',False)],
}),
'project_id':fields.many2one('construction.projectro', 'Project',
required=True,
readonly=True,
select=1,
domain="[('state','=','confirmed')]",
states={
'draft':[('readonly',False)],
}),
'created_by':fields.many2one('res.users', 'Created by',
required=True,
readonly=True,
states={
'draft':[('readonly',False)],
}),
'date_created':fields.date('Date Created',
required=True,
readonly=True,
states={
'draft':[('readonly',False)],
}),
'purchase_line': fields.one2many('construction.purchase.line',
'purchase_id',
'Order Lines',
states={
'done':[('readonly',True)]
}),
'note': fields.text('Notes'),
'state': fields.selection(
[
('draft','Draft'),
('done','Released'),
],
'State'),
'total_amount': fields.function(_total_amount,
method=True, string='Total Amount',
digits=(16, int(config['price_accuracy'])),
),
'amount':fields.float('Amount', readonly=True, digits=(16, 2)),
'paid_amount':fields.float('Payment', readonly=True, digits=(16, 2)),
'is_paid':fields.boolean('Paid', readonly=True, ),
'due_date':fields.date('Due Date',
required=True,
readonly=True,
states={
'draft':[('readonly',False)],
}),
'release_date':fields.date('Date Released',
readonly=True,
states={
'draft':[('readonly',False)],
}),
'is_due': fields.function(_is_due, type='boolean',
method=True, string='Due',
),
'balance': fields.function(_balance, type='float', digits=(16, 2),
method=True, string='Balance',
),
'for_reimbursement':fields.boolean('For Reimbursement', readonly=True,
states={
'draft':[('readonly',False)],
}),
'quote_verify':fields.boolean('For Actual Verification', readonly=True,
states={
'draft':[('readonly',False)],
}),
'checked_by':fields.many2one('res.users', 'Checked / Verified by',
readonly=True,
states={
'draft':[('readonly',False)],
}),
'date_verified':fields.date('Date Verified',
readonly=True,
states={
'draft':[('readonly',False)],
}),
}
_defaults = {
'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'construction.purchase'),
'state': lambda *a: 'draft',
'paid_amount': lambda *a: 0,
'date_created': lambda *a: time.strftime('%Y-%m-%d'),
'date_ordered': lambda *a: time.strftime('%Y-%m-%d'),
'due_date': lambda *a: time.strftime('%Y-%m-%d'),
'created_by' : lambda obj, cr, uid, context: uid,
'category': lambda *a: 'material',
'is_paid': lambda *a: False,
'for_reimbursement': lambda *a: False,
'quote_verify': lambda *a: False,
}
_order = 'name desc'
def update_req_po_qty(self, cr, uid, ids):
req_line_ids = []
for f in self.browse(cr, uid, ids):
for line in f.purchase_line:
req_line_ids.append(line.read(cr, uid, line.id,['request_line_id'])['request_line_id'][0])
if req_line_ids:
sql = "select a.request_line_id, sum(case when b.state='done' then a.quantity else 0 end) as qty"
sql += " from construction_purchase_line as a inner join construction_purchase as b on a.purchase_id = b.id"
sql += " where a.request_line_id in (" + ",".join(map(str, req_line_ids)) + ")"
sql += " group by 1"
#print(sql)
cr.execute(sql)
for rec in cr.fetchall():
self.pool.get("construction.requests.line").write(cr, uid, rec[0], {'po_quantity' : rec[1]})
def bt_purchase_confirm(self,cr, uid, ids, *args):
self.write(cr, uid, ids, {'state': 'done'})
#compute po amount
self.update_req_po_qty(cr, uid, ids)
for f in self.browse(cr, uid, ids):
amt = 0
release_date = f.release_date
for line in f.purchase_line:
amt += line.amount
amt = round(amt / 0.01) * 0.01
self.write(cr, uid, ids, {'amount': amt})
if not release_date:
self.write(cr, uid, ids, {'release_date': time.strftime('%Y-%m-%d')})
return True
def bt_purchase_unconfirm(self,cr, uid, ids, *args):
if not user_with_rights(self, cr, uid, uid, 'Unconfirm Purchase Order Rights'):
return False
self.write(cr, uid, ids, {'state': 'draft'})
self.update_req_po_qty(cr, uid, ids)
return True
def compute_due_date(self, cr, uid, ids, supplier_id, date_ordered):
v={}
#print supplier_id, date_ordered
if not supplier_id:
return {}
if not date_ordered:
return {}
supplier=self.pool.get('construction.suppliers').browse(cr,uid,supplier_id)
due_date = DateTime.strptime(date_ordered, '%Y-%m-%d') + DateTime.RelativeDateTime(days=int(supplier.terms))
#print date_ordered, due_date, due_date.strftime('%Y-%m-%d')
v['due_date'] = due_date.strftime('%Y-%m-%d')
return {'value':v}
construction_purchase()
##
class construction_reqlookup(osv.osv):
_name = 'construction.reqlookup'
_inherit = 'construction.requests.line'
_table = 'construction_requests_line'
_description = 'Requisitions Lookup'
_order = 'seq, name'
construction_reqlookup()
class construction_purchase_line(osv.osv):
_name = 'construction.purchase.line'
_description = 'Purchase Order Details'
def onchange_request_line_id(self, cr, uid, ids, request_line_id):
v={}
if request_line_id :
req_line=self.pool.get('construction.requests.line').browse(cr,uid,request_line_id)
po_lines = self.browse(cr,uid,ids)
v['quantity'] = req_line.quantity - req_line.po_quantity
v['price'] = req_line.price
v['unit'] = req_line.unit
v['name'] = req_line.name
return {'value':v}
def _constraint_po_qty(self, cr, uid, ids):
for f in self.browse(cr, uid, ids):
if f.request_line_id:
cr.execute('select quantity from construction_requests_line where id=%d', (f.request_line_id,))
req_qty = cr.fetchone()[0]
cr.execute('select sum(quantity) from construction_purchase_line where request_line_id=%d', (f.request_line_id,))
po_qty = cr.fetchone()[0]
#raise osv.except_osv(
# 'Debug',
# 'PoQty = %d, ReqQty=%d' % (po_qty, req_qty))
return (req_qty - po_qty) > -0.001
else:
return True
def _amount(self, cr, uid, ids, field_name, arg, context):
res = {}
for f in self.browse(cr, uid, ids):
res[f.id] = round((f.price * f.quantity)/0.01) * 0.01
return res
def _show_item(self, cr, uid, ids, field_name, arg, context):
res = {}
for f in self.browse(cr, uid, ids):
res[f.id] = f.request_line_id.name
return res
def _show_unit(self, cr, uid, ids, field_name, arg, context):
res = {}
for f in self.browse(cr, uid, ids):
res[f.id] = f.request_line_id.unit
return res
_columns = {
'purchase_id': fields.many2one('construction.purchase', 'Requisition Ref',
required=True),
'name' : fields.char('Item', size=100),
'request_line_id' : fields.many2one('construction.reqlookup', 'Item',
domain="[('project_id', '= ', parent.project_id),('quantity','> po_quantity or 1=','0'),('category','=',parent.category)]",
required=True),
'seq': fields.integer('Sequence', select=False),
'item': fields.function(_show_item, size=30, type='char', method=True, string='Item'),
'quantity': fields.float('Quantity', required=True, digits=(16, 2)),
'unit': fields.function(_show_unit, size=10, type='char', method=True, string='Unit'),
#'unit': fields.char('Unit', size=10),
'price': fields.float('Price', required=True, digits=(16, int(config['price_accuracy']))),
'note': fields.text('Notes'),
'amount': fields.function(_amount, method=True, string='Amount', digits=(16, int(config['price_accuracy']))),
'received_qty': fields.float('Received Qty', readonly=True, digits=(16, 2)),
}
_defaults = {
'seq': lambda *a: 10,
'quantity': lambda *a: 0,
'price': lambda *a: 0,
'received_qty': lambda *a: 0,
}
_order = 'seq, id'
_constraints = [
(_constraint_po_qty,'Error! P.O. quantity is more than requisition quantity.',[])
]
construction_purchase_line()
##
class construction_jo_old(osv.osv):
_name = 'construction.jo'
_table = 'construction_purchase'
_description = 'Job Order'
_inherit = 'construction.purchase'
_defaults = {
'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'construction.jo'),
'category': lambda *a: 'labor',
}
class construction_jo(osv.osv):
_name = 'construction.jo'
_table = 'construction_purchase'
_description = 'Job Order'
def _total_amount(self, cr, uid, ids, field_name, arg, context):
res = {}
for f in self.browse(cr, uid, ids):
res[f.id] = 0.0
for line in f.purchase_line:
res[f.id] += line.amount
res[f.id] = round(res[f.id] / 0.01) * 0.01
return res
def _is_due(self, cr, uid, ids, field_name, arg, context):
now = DateTime.now()
res = {}
for f in self.browse(cr, uid, ids):
due = DateTime.strptime(f.due_date, '%Y-%m-%d')
#print now, due
if now > due:
res[f.id] = True
else:
res[f.id] = False
return res
def _balance(self, cr, uid, ids, field_name, arg, context):
res = {}
for f in self.browse(cr, uid, ids):
res[f.id] = f.amount - f.paid_amount
return res
_columns = {
'category': fields.selection(
(
('labor', 'Labor'),
('material', 'Material'),
),
'Category', required=True, change_default=True),
'name' : fields.char('Number / Reference',
size=100,
required=True,
readonly=True,
select=1,
states={
'draft':[('readonly',False)]
}),
'date_ordered':fields.date('Order Date',
required=True,
readonly=True,
states={
'draft':[('readonly',False)],
}),
'supplier_id':fields.many2one('construction.suppliers', 'Supplier',
required=True,
readonly=True,
select=1,
states={
'draft':[('readonly',False)],
}),
'project_id':fields.many2one('construction.projectro', 'Project',
required=True,
readonly=True,
select=1,
domain="[('state','=','confirmed')]",
states={
'draft':[('readonly',False)],
}),
'created_by':fields.many2one('res.users', 'Created by',
required=True,
readonly=True,
states={
'draft':[('readonly',False)],
}),
'date_created':fields.date('Date Created',
required=True,
readonly=True,
states={
'draft':[('readonly',False)],
}),
'purchase_line': fields.one2many('construction.jo.line',
'purchase_id',
'Order Lines',
states={
'done':[('readonly',True)]
}),
'note': fields.text('Notes'),
'state': fields.selection(
[
('draft','Draft'),
('done','Released'),
],
'State'),
'total_amount': fields.function(_total_amount,
method=True, string='Total Amount',
digits=(16, int(config['price_accuracy'])),
),
'amount':fields.float('Amount', readonly=True, digits=(16, 2)),
'paid_amount':fields.float('Payment', readonly=True, digits=(16, 2)),
'is_paid':fields.boolean('Paid', ),
'due_date':fields.date('Due Date',
required=True,
readonly=True,
states={
'draft':[('readonly',False)],
}),
'release_date':fields.date('Date Released',
readonly=True,
states={
'draft':[('readonly',False)],
}),
'is_due': fields.function(_is_due, type='boolean',
method=True, string='Due',
),
'balance': fields.function(_balance, type='float', digits=(16, 2),
method=True, string='Balance',
),
'for_reimbursement':fields.boolean('For Reimbursement', readonly=True,
states={
'draft':[('readonly',False)],
}),
'quote_verify':fields.boolean('For Actual Verification', readonly=True,
states={
'draft':[('readonly',False)],
}),
'checked_by':fields.many2one('res.users', 'Checked / Verified by',
readonly=True,
states={
'draft':[('readonly',False)],
}),
'date_verified':fields.date('Date Verified',
readonly=True,
states={
'draft':[('readonly',False)],
}),
}
_defaults = {
'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'construction.jo'),
'state': lambda *a: 'draft',
'paid_amount': lambda *a: 0,
'date_created': lambda *a: time.strftime('%Y-%m-%d'),
'date_ordered': lambda *a: time.strftime('%Y-%m-%d'),
'due_date': lambda *a: time.strftime('%Y-%m-%d'),
'created_by' : lambda obj, cr, uid, context: uid,
'category': lambda *a: 'labor',
'is_paid': lambda *a: False,
'for_reimbursement': lambda *a: False,
'quote_verify': lambda *a: False,
}
_order = 'name desc'
def bt_purchase_confirm(self,cr, uid, ids, *args):
self.write(cr, uid, ids, {'state': 'done'})
#compute po amount
#self.update_req_po_qty(cr, uid, ids)
for f in self.browse(cr, uid, ids):
amt = 0
release_date = f.release_date
for line in f.purchase_line:
amt += line.amount
amt = round(amt / 0.01) * 0.01
self.write(cr, uid, ids, {'amount': amt})
if not release_date:
self.write(cr, uid, ids, {'release_date': time.strftime('%Y-%m-%d')})
return True
def bt_purchase_unconfirm(self,cr, uid, ids, *args):
if not user_with_rights(self, cr, uid, uid, 'Unconfirm Purchase Order Rights'):
return False
self.write(cr, uid, ids, {'state': 'draft'})
#self.update_req_po_qty(cr, uid, ids)
return True
def compute_due_date(self, cr, uid, ids, supplier_id, date_ordered):
v={}
#print supplier_id, date_ordered
if not supplier_id:
return {}
if not date_ordered:
return {}
supplier=self.pool.get('construction.suppliers').browse(cr,uid,supplier_id)
due_date = DateTime.strptime(date_ordered, '%Y-%m-%d') + DateTime.RelativeDateTime(days=int(supplier.terms))
#print date_ordered, due_date, due_date.strftime('%Y-%m-%d')
v['due_date'] = due_date.strftime('%Y-%m-%d')
return {'value':v}
construction_jo()
class construction_jo_line(osv.osv):
_name = 'construction.jo.line'
_table = 'construction_purchase_line'
_description = 'Job Order Details'
def _amount(self, cr, uid, ids, field_name, arg, context):
res = {}
for f in self.browse(cr, uid, ids):
res[f.id] = round((f.price * f.quantity)/0.01) * 0.01
return res
def _show_item(self, cr, uid, ids, field_name, arg, context):
res = {}
for f in self.browse(cr, uid, ids):
res[f.id] = f.request_line_id.name
return res
def _show_unit(self, cr, uid, ids, field_name, arg, context):
res = {}
for f in self.browse(cr, uid, ids):
res[f.id] = f.request_line_id.unit
return res
_columns = {
'purchase_id': fields.many2one('construction.purchase', 'Requisition Ref',
required=True),
'name' : fields.char('Item', size=100),
'seq': fields.integer('Sequence', select=False),
#'item': fields.function(_show_item, size=30, type='char', method=True, string='Item'),
'quantity': fields.float('Quantity', required=True, digits=(16, 2)),
#'unit': fields.function(_show_unit, size=10, type='char', method=True, string='Unit'),
'unit2': fields.char('Unit', size=10),
'price': fields.float('Price', required=True, digits=(16, int(config['price_accuracy']))),
'note': fields.text('Notes'),
'amount': fields.function(_amount, method=True, string='Amount', digits=(16, int(config['price_accuracy']))),
'received_qty': fields.float('Received Qty', readonly=True, digits=(16, 2)),
}
_defaults = {
'seq': lambda *a: 10,
'quantity': lambda *a: 1,
'price': lambda *a: 0,
'received_qty': lambda *a: 0,
}
_order = 'seq, id'
construction_jo_line()